/* ==========================================================================
   微迹 Weetrack — 记账（订阅 / 固定资产）
   --------------------------------------------------------------------------
   两个部分共用一套框架：页头 → 标签页 → 汇总卡 → 工具条 → 列表。
   命名统一用 lg-（ledger）打头，两边各有的部分再用 sub- / as- 区分。
   ========================================================================== */

.lg-wrap {
  display: flex;
  flex-direction: column;
  gap: 16px;
  padding: 4px 0 32px;
  min-width: 0;
}

/* ------------------------------ 页头 ------------------------------ */

.lg-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  flex-wrap: wrap;
}
.lg-title {
  display: flex;
  align-items: baseline;
  gap: 10px;
  flex-wrap: wrap;
}
.lg-title h2 {
  margin: 0;
  font-size: 20px;
  font-weight: 600;
  letter-spacing: .3px;
}
.lg-sub { font-size: 12.5px; color: var(--text-3); }
.lg-head-acts { display: flex; gap: 8px; }

/* ------------------------------ 标签页 ------------------------------
 * 2026-09-26：这三个页签从"页头下面单独一行"挪进了**页头右上角**，
 * 并且改用待办/灵感同款的 `.segment` 控件（用户要求 UI 一致）。
 *
 * 所以这里**不要再给容器画背景和边框** —— 那两样 `.segment` 已经画了，
 * 再画一层就是"框里套框"。`.lg-tabs` 现在只负责"它是这组页签的容器"
 * 这个语义（也给拖动排序当挂载点），视觉全交给 `.segment`。
 */
.lg-tabs {
  /* 保留类名是因为：拖动排序要一个稳定的容器、检查脚本也在找 .lg-tab */
  display: inline-flex;
}
/* 【激活态要用 .on】
 * `.segment` 自己的激活类是 `.active`，而这三个页签用的是 `.on`
 * （ledger-ui-check 就是靠 `.lg-tab.on` 认"当前在哪一页"的）。
 * 与其改 JS 去迁就样式，不如让样式认这两个名字 ——
 * 一个类名换来的是"检查脚本不用动、也不会静默失效"。 */
.segment button.on {
  background: var(--surface);
  color: var(--text);
  box-shadow: var(--shadow-xs);
}
.lg-tab {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font: inherit;
  font-size: 12.5px;
  padding: 7px 14px;
  border: none;
  border-radius: 8px;
  background: transparent;
  color: var(--text-2);
  cursor: pointer;
  transition: background .15s var(--ease), color .15s var(--ease);
}
.lg-tab:hover { color: var(--text); }
.lg-tab.on {
  background: var(--surface);
  color: var(--text);
  font-weight: 600;
  box-shadow: 0 1px 2px rgba(0, 0, 0, .07);
}
.lg-tab .ic { font-size: 13px; opacity: .8; }
.lg-soon {
  font-size: 10px;
  padding: 1px 6px;
  border-radius: 20px;
  background: var(--surface-3);
  color: var(--text-3);
  font-weight: 400;
}

.lg-body { min-width: 0; }
.lg-sec { display: flex; flex-direction: column; gap: 14px; }
.lg-loading,
.lg-error {
  padding: 26px;
  text-align: center;
  font-size: 13px;
  color: var(--text-3);
}
.lg-error { color: #b8453d; }

/* ------------------------------ 提醒条 ------------------------------ */

.lg-alerts { display: flex; flex-direction: column; gap: 8px; }

.lg-alert {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 14px;
  border-radius: var(--r-md, 12px);
  border: 1px solid #e8d9a8;
  background: #fdf8ea;
  font-size: 12.5px;
  color: #7a6420;
}
/* 试用到期比"该续费了"更紧急：前者是"马上要开始扣钱了" */
.lg-alert.trial {
  border-color: #eccfc9;
  background: #fdf1ef;
  color: #8d4a3f;
}
.lg-alert .ic { font-size: 15px; flex: none; }
.lg-alert .tx { flex: 1 1 auto; min-width: 0; }
.lg-alert b { font-weight: 600; }

/* ------------------------------ 汇总卡 ------------------------------ */

.lg-stats {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(170px, 1fr));
  gap: 10px;
}

.lg-stat {
  position: relative;
  padding: 12px 14px;
  border-radius: var(--r-md, 12px);
  border: 1px solid var(--line);
  background: var(--surface);
  overflow: hidden;
  /* 【必须显式写 display:block —— 这是一处踩了很久的坑】
     下面第一张卡用的 tone 类原本叫 `brand`，而 layout.css 里有个**全局**的
     `.brand`（侧边栏那个"微迹"标志），它是 `display:flex; align-items:center`
     还带 `padding: 4px 6px 14px; margin-bottom: 10px; border-bottom`。
     类名撞上之后，这一张卡的布局被"标志"那套抢走：
       · 三个子元素被 flex 竖向居中挤成一团（offsetTop 29/33/35，
         而正常的卡是 12/33/66）
       · padding 被覆盖、底下多出一条边线
     实测后果就是用户说的"顶部四个快捷信息高度不一致"：
     第一张 87.4px，其余三张 97.4px，差 10px。
     所以这里两件事一起做：
       1. .lg-stat 自己钉死 display:block（不管身上还挂了什么类）
       2. tone 类改名叫 .is-accent，彻底避开全局的 .brand */
  display: block;
  box-sizing: border-box;
}
/* 第一张卡（每月合计 / 资产总额）左边加一条品牌色带，一眼找到重点。
   【tone 类不能叫 brand】见上面那段：会和全局 .brand（侧栏标志）撞。 */
.lg-stat.is-accent::before {
  content: '';
  position: absolute;
  left: 0; top: 0; bottom: 0;
  width: 3px;
  background: var(--brand, #48ab93);
}
/* 【老名字也留着，但不带任何布局】
   万一还有别处/旧缓存渲染出 .brand 的组合，至少保证它长得和别的卡一样 ——
   宁可少一条色带，也不要一张卡莫名其妙变形。 */
.lg-stat.brand {
  display: block;
  padding: 12px 14px;
  margin-bottom: 0;
  border-bottom: 0;
}
.lg-stat.good .ls-value { color: #4a8f6a; }

.ls-label { font-size: 11.5px; color: var(--text-3); }
.ls-value {
  margin-top: 3px;
  font-size: 19px;
  font-weight: 600;
  letter-spacing: .2px;
  font-variant-numeric: tabular-nums;
}
.ls-hint { margin-top: 2px; font-size: 11px; color: var(--text-3); }

/* ------------------------------ 分类分布条 ------------------------------ */

.as-cat-box { display: flex; flex-direction: column; gap: 8px; }
.as-cat-bar {
  display: flex;
  height: 8px;
  border-radius: 4px;
  overflow: hidden;
  background: var(--surface-2);
}
.as-cat-bar i { display: block; height: 100%; }
.as-cat-legend {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  font-size: 11px;
  color: var(--text-3);
}
.as-cat-legend .lg { display: flex; align-items: center; gap: 4px; }
.as-cat-legend i.dot { width: 8px; height: 8px; border-radius: 50%; display: block; }

/* ==========================================================================
   分类名做成"能点的小按钮" + 换分类的小面板
   —— 用户 2026-10-03 提的：
   「分类只能在添加物品时才能调整分类，这不对，应该在外面也可以调整，
     添加一个按钮」
   ========================================================================== */
.as-cat-btn,
.ci-cat-btn {
  border: 0;
  background: transparent;
  font: inherit;
  cursor: pointer;
  border-radius: var(--r-xs);
  /* 【虚线下划线是"这里能点"的老约定】
     不做成实心按钮，是因为列表一行里已经有 4 个操作图标了，
     再加一个实心块会显得很吵。 */
  border-bottom: 1px dashed currentColor;
  transition: color var(--dur) var(--ease), background var(--dur) var(--ease);
}
.as-cat-btn:hover,
.ci-cat-btn:hover {
  color: var(--brand);
  background: var(--brand-soft);
  border-bottom-color: transparent;
}

.cat-pop-back { position: fixed; inset: 0; z-index: 60; }
.cat-pop {
  position: fixed;
  z-index: 61;
  width: 186px;
  max-height: 320px;
  overflow-y: auto;
  padding: 7px;
  border-radius: var(--r-md);
  background: var(--surface);
  border: 1px solid var(--line);
  box-shadow: var(--shadow-lg);
}
.cat-pop-head {
  padding: 3px 6px 7px;
  font-size: 11px;
  color: var(--text-3);
}
.cat-pop-list { display: flex; flex-direction: column; gap: 1px; }
.cat-pop-item {
  display: flex;
  align-items: center;
  gap: 8px;
  width: 100%;
  padding: 5px 6px;
  border: 0;
  border-radius: var(--r-xs);
  background: transparent;
  color: var(--text-2);
  font-size: 12px;
  text-align: left;
  cursor: pointer;
}
.cat-pop-item:hover { background: var(--surface-2); color: var(--text); }
.cat-pop-item.on { background: var(--brand-soft); color: var(--brand-deep); font-weight: 600; }
.cat-pop-ico {
  flex: none;
  width: 20px;
  height: 20px;
  border-radius: var(--r-xs);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: 12px;
}
.cat-pop-name { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cat-pop-cur { flex: none; font-size: 10px; opacity: .7; }

/* ------------------------------ 工具条 ------------------------------ */

.lg-toolbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  flex-wrap: wrap;
}
.lg-toolbar-right { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }

.lg-seg {
  display: inline-flex;
  padding: 2px;
  border-radius: 9px;
  background: var(--surface-2);
  border: 1px solid var(--line);
}
.lg-seg-btn {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  font: inherit;
  font-size: 12px;
  padding: 5px 11px;
  border: none;
  border-radius: 7px;
  background: transparent;
  color: var(--text-2);
  cursor: pointer;
  transition: background .15s var(--ease), color .15s var(--ease);
}
.lg-seg-btn:hover { color: var(--text); }
.lg-seg-btn.on {
  background: var(--surface);
  color: var(--text);
  font-weight: 600;
  box-shadow: 0 1px 2px rgba(0, 0, 0, .07);
}
.lg-seg-btn .n {
  font-size: 10.5px;
  color: var(--text-3);
  font-weight: 400;
}
.lg-seg-btn.on .n { color: var(--brand, #48ab93); }

.lg-inp {
  font: inherit;
  font-size: 12px;
  padding: 5px 9px;
  border-radius: 8px;
  border: 1px solid var(--line);
  background: var(--surface);
  color: var(--text);
}
.lg-inp:focus {
  outline: none;
  border-color: var(--brand, #48ab93);
}
.lg-search { min-width: 150px; }

.lg-sec-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  flex-wrap: wrap;
}
.lg-sec-head h3 {
  margin: 0;
  font-size: 14px;
  font-weight: 600;
}
.lg-sec-acts { display: flex; gap: 8px; }

.lg-group {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 12px;
  color: var(--text-3);
  margin-top: 4px;
}
.lg-group .dot { width: 7px; height: 7px; border-radius: 50%; display: block; }
.lg-group .dot-active { background: #4a8f6a; }
.lg-group .dot-paused { background: #d59a2e; }
.lg-group .dot-canceled { background: var(--text-3); }

.lg-empty {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 10px;
  padding: 40px 20px;
  border-radius: var(--r-md, 12px);
  border: 1px dashed var(--line);
  background: var(--surface-2);
  color: var(--text-3);
  font-size: 13px;
  text-align: center;
}
.lg-empty .ico { font-size: 26px; opacity: .6; }
.lg-empty .txt { max-width: 460px; line-height: 1.7; }

/* ------------------------------ 记账占位 ------------------------------ */

.lg-soon-box {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 12px;
  padding: 52px 24px;
  border-radius: var(--r-md, 14px);
  border: 1px dashed var(--line);
  background: var(--surface-2);
  text-align: center;
}
.lg-soon-ico { font-size: 34px; opacity: .35; }
.lg-soon-box h3 { margin: 0; font-size: 16px; font-weight: 600; }
.lg-soon-box p {
  margin: 0;
  max-width: 520px;
  font-size: 12.5px;
  line-height: 1.8;
  color: var(--text-3);
}
.lg-soon-list {
  display: flex;
  flex-direction: column;
  gap: 6px;
  margin-top: 6px;
  font-size: 12.5px;
  color: var(--text-2);
  text-align: left;
}
.lg-soon-list .ic { color: var(--text-3); margin-right: 6px; }

/* ==========================================================================
   订阅
   ==========================================================================
   【2026-10-02 大改：订阅也做成四条视图了】
   用户的要求：「把固定资产的大部分功能和逻辑，能够复刻到订阅里的
   都复制一份过去，保持功能上的统一，共性的尽可能共性」。

   所以这里**不再有自己的卡片样式** —— 四条视图（默认列表 / 续费日历 /
   卡片墙 / 紧凑网格）全部复用固定资产那套 `.as-*`：
     · 默认列表  → .as-table / .as-row（只是列不同）
     · 卡片墙    → .as-wall / .as-card
     · 紧凑网格  → .as-grid / .as-gi
   于是两边的"一行""一张卡"看起来是一回事，改一处两边一起变。

   下面只留订阅**特有**的几样：状态小标、续费日历那条时间列、工具栏。
   -------------------------------------------------------------------------- */

/* 订阅在资产那套栅格里的列宽。
   资产是 11 列（图片/名称/金额/日期/时长/天数/天均/地点/成色/状态/操作），
   订阅是 10 列、而且字段名不同（周期/下次续费/已扣期数/累计/月成本）。
   所以单独定义一套列宽 —— 但用的仍是同一套格语言。

   【列宽必须算上 gap，不然会顶破】
   这套栅格是 `gap: 8px`。10 列 = **9 个间隙 = 72px**，
   再加上行本身 padding 10px × 2 = 20px，一共 92px 是"非内容"开销。
   第一版我按"内容想多宽就写多宽"排（合计 868px），
   结果 868 + 72 + 20 = 960px > 可用宽度，**在 1100px 屏下顶出去 58px**
   （实测 row.scrollWidth 950 vs clientWidth 890）。
   所以这里把总和压到 **约 700px**，留足余量：
   窄到 900px 会切成卡片式（见下面 media query），
   900~1100 这一段则靠 minmax(...,1fr) 那几列自己伸缩。
   实测 1500/1280/1100/880/720 五种宽度都不溢出。 */
.sub-table .as-thead,
.sub-table .as-row {
  grid-template-columns:
    38px                  /* 图片 */
    minmax(96px, 1.7fr)   /* 名称 */
    minmax(66px, .85fr)   /* 每期金额 */
    56px                  /* 周期 */
    minmax(76px, .95fr)   /* 下次续费 */
    58px                  /* 已扣期数 */
    minmax(66px, .8fr)    /* 累计花费 */
    minmax(74px, .9fr)    /* 折算月成本 */
    64px                  /* 状态 */
    84px;                 /* 操作 */
  gap: 7px;
}
/* 「每期」那一格：金额 + 小字"每期/一次" 竖着排 */
.sub-table .c-amt { display: flex; flex-direction: column; align-items: flex-start; gap: 1px; }
.sub-table .c-amt b { font-variant-numeric: tabular-nums; }
.sub-table .c-amt .u { font-size: 10.5px; color: var(--text-3); }
/* 「下次续费」：日期 + 还有几天 */
.sub-table .c-date { display: flex; flex-direction: column; gap: 1px; }
.sub-due-sub { font-size: 10.5px; color: var(--text-3); }
.sub-table .c-daily { font-variant-numeric: tabular-nums; }

/* 状态小标：三个状态三个颜色，一眼分得清 */
.sub-st {
  font-size: 11px;
  padding: 2px 8px;
  border-radius: 20px;
  background: var(--surface-3);
  color: var(--text-2);
  white-space: nowrap;
}
.sub-st.active { background: #eef2e8; color: #5a7048; }
.sub-st.paused { background: #fbf3e2; color: #8a6a20; }
.sub-st.canceled { background: var(--surface-3); color: var(--text-3); }

/* ---------------------- 续费日历（视图 2） ---------------------- */

.sub-due-sum {
  font-size: 12px;
  color: var(--text-2);
  background: var(--surface-2);
  border: 1px solid var(--line);
  border-radius: 10px;
  padding: 8px 11px;
  margin-bottom: 4px;
}
.sub-due-list { display: flex; flex-direction: column; gap: 2px; }

/* 一行：左边"还有几天"那一列 + 图标 + 正文 + 操作。
   时间列固定宽度，所以竖着扫下来是齐的 —— 这是这条视图存在的意义。 */
.sub-due-row {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 9px 10px;
  border-radius: var(--r-sm, 10px);
  border: 1px solid transparent;
  position: relative;
}
.sub-due-row:hover { background: var(--surface-2); border-color: var(--line); }
.sub-due-row.off { opacity: .58; }
/* 行与行之间的虚线 —— 和资产默认列表那条同一个做法 */
.sub-due-row + .sub-due-row::before {
  content: '';
  position: absolute;
  left: 10px; right: 10px; top: -1px;
  border-top: 1px dashed var(--line);
  pointer-events: none;
}
.sub-due-row:hover::before,
.sub-due-row:hover + .sub-due-row::before { opacity: 0; }

.sub-due-when {
  flex: 0 0 auto;
  width: 74px;
  text-align: right;
  display: flex;
  flex-direction: column;
  gap: 1px;
}
.sub-due-when b { font-size: 13px; font-weight: 600; color: var(--text-2); font-variant-numeric: tabular-nums; }
.sub-due-when span { font-size: 10.5px; color: var(--text-3); font-variant-numeric: tabular-nums; }
/* 7 天内要扣的：黄色提醒；已经过期的：红色 */
.sub-due-row.soon .sub-due-when b { color: #a8801f; }
.sub-due-row.late .sub-due-when b { color: #b4483a; }

/* 卡片墙上的「待续费 / 试用」小标 */
.sub-badge.renew { background: #fbf3e2; color: #8a6a20; }

/* ---------------------- 工具栏 ---------------------- */

/* 视图切换控件和资产那边共用 .segment，只是容器 class 不同 */
.sub-views { flex: none; }
/* 排序控件：下拉 + 升降序按钮，两个挨着 */
/* 排序控件：下拉 + 升降序按钮。
   【这里**不放 gap**，让它们共用外层的 8px】
   实测这条工具栏会在 1280px 顶换行：
     1280px 下可用 1038px
       固定资产 = 左 235 + 右 789 + 组间 10 = 1034  → 刚好挤得下（余 4px）
       订阅     = 左 247 + 右 791 + 组间 10 = 1048  → **超 10px，掉到第二行**
   而右组里比资产多出来的那些，主要就是这个 .lg-sort：
   它把「下拉 + 按钮」包成一层**又多加了一道 gap**（6px），
   而资产那边这两个是**平铺**在 .lg-toolbar-right 里的（它们的间距本来就由 8px 提供）。
   所以这里 gap 设 0 —— 视觉上的间距和资产完全一样，
   但少了一层自己的间隙，总宽收窄 6px，不再顶换行。 */
.lg-sort { display: flex; align-items: center; gap: 0; }

/* 窄屏：订阅那套列也切成卡片式（跟着资产那条 media query 的节奏走） */
@media (max-width: 900px) {
  .sub-table .as-thead { display: none; }
  .sub-table .as-row {
    grid-template-columns: 38px minmax(0, 1fr) auto;
    grid-template-areas:
      'img name status'
      'img amt  daily'
      'img date acts';
    gap: 8px;
    row-gap: 6px;
    border-color: var(--line);
    background: var(--surface);
  }
  .sub-table .c-img { grid-area: img; align-self: start; }
  .sub-table .c-name { grid-area: name; }
  .sub-table .c-amt { grid-area: amt; }
  .sub-table .c-daily { grid-area: daily; align-items: flex-end; }
  .sub-table .c-status { grid-area: status; align-items: flex-end; }
  .sub-table .c-date { grid-area: date; }
  .sub-table .c-acts { grid-area: acts; }
  /* 窄屏放不下的先藏起来：周期/期数/累计在卡片模式下不显示
     （名字下面那行已经写了周期，累计要点进详情看） */
  .sub-table .c-cycle, .sub-table .c-span, .sub-table .c-days { display: none; }
}

@media (max-width: 620px) {
  .sub-due-when { width: 58px; }
}

/* ==========================================================================
   固定资产
   ========================================================================== */

.as-table { display: flex; flex-direction: column; gap: 2px; }

/* 【行与行之间的虚线】
   用户报的：「默认列表下没有虚线，显得很单调」。
   原因：行本身是 `border: 1px solid transparent` —— 只有鼠标经过才显出边框，
   静止时整片是平的，一行行读下来没有任何视觉分隔。
   这里用 `相邻兄弟选择器`（`.as-row + .as-row`）给**两行之间**补一条虚线：
   只有"前面还有一个 .as-row"的行才画，所以第一行上面不会有、
   最后一行下面也不会有 —— 正好是"分隔"的意思，不是"给每行描边"。
   为什么用虚线而不是实线：
     · 这一屏的信息本来就密（10 列），实线会把表格切得很硬、更"报表"
     · 和图标选择框、空状态那些已有的虚线是同一套语言，看起来是一家人
   为什么用低对比度的 --line 而不是更深的颜色：
     它是**分隔**不是**强调**，抢眼就本末倒置了。 */
.as-row { position: relative; }
.as-row + .as-row::before {
  content: '';
  position: absolute;
  left: 10px;
  right: 10px;
  top: -1px;
  border-top: 1px dashed var(--line);
  pointer-events: none;
}
/* 鼠标经过的那一行把虚线让开（那行自己有边框了，两条叠着显得脏）*/
.as-row:hover::before,
.as-row:hover + .as-row::before { opacity: 0; }

/* 列宽统一在这里定义，表头和数据行共用（grid-template-columns 一致） */
.as-thead,
.as-row {
  display: grid;
  grid-template-columns:
    46px                  /* 图片 */
    minmax(130px, 2fr)    /* 名称 */
    minmax(76px, 1fr)     /* 金额 */
    92px                  /* 购买日期 */
    minmax(88px, 1fr)     /* 已用时长 */
    68px                  /* 天数 */
    minmax(104px, 1.1fr)  /* 天均 */
    110px                 /* 存放地点 */
    96px                  /* 成色 */
    minmax(80px, .85fr)   /* 状态 */
    120px;                /* 操作 */
  gap: 8px;
  align-items: center;
}

.as-thead {
  padding: 0 10px 7px;
  font-size: 11px;
  color: var(--text-3);
  border-bottom: 1px solid var(--line);
}

.as-row {
  padding: 9px 10px;
  border-radius: var(--r-sm, 10px);
  border: 1px solid transparent;
  transition: background .14s var(--ease), border-color .14s var(--ease);
}
.as-row:hover { background: var(--surface-2); border-color: var(--line); }
.as-row.off { opacity: .58; }
.as-row.off:hover { opacity: .85; }

.as-img {
  width: 38px;
  height: 38px;
  border-radius: 9px;
  object-fit: cover;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 18px;
  background: var(--surface-2);
  overflow: hidden;
}
img.as-img { background: none; }

.c-name { min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.c-name .nm {
  font-size: 13px;
  font-weight: 500;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.as-cat {
  font-size: 10.5px;
  font-weight: 400;
  color: var(--text-3);
  margin-left: 6px;
}
.as-note {
  font-size: 11px;
  color: var(--text-3);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
/* 存放位置：名称下面那行小字。
   比备注更"实"一点（它是这行数据的一部分，不是补充说明），
   所以用 text-2 而不是 text-3，一眼能扫到又不抢名称。 */
.as-loc {
  font-size: 11px;
  color: var(--text-2);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.as-warns { display: flex; flex-wrap: wrap; gap: 5px; }
.as-warn { font-size: 10.5px; padding: 1px 6px; border-radius: 20px; }
.as-warn.soon { background: #fbf3e2; color: #8a6a20; }
.as-warn.expired { background: #fbeceb; color: #a8403a; }

.c-amt { display: flex; flex-direction: column; gap: 1px; }
.c-amt b { font-size: 13.5px; font-weight: 600; font-variant-numeric: tabular-nums; }
.as-net { font-size: 10.5px; color: var(--text-3); font-variant-numeric: tabular-nums; }

.c-date, .c-span, .c-days {
  font-size: 12px;
  color: var(--text-2);
  font-variant-numeric: tabular-nums;
}
.c-span { color: var(--text-3); }

.c-daily { display: flex; flex-direction: column; gap: 2px; }
.c-daily-val { font-variant-numeric: tabular-nums; }
.c-daily-val b { font-size: 13px; font-weight: 600; }
.c-daily-val .unit { font-size: 10.5px; color: var(--text-3); }
.as-target {
  font-size: 10px;
  padding: 1px 5px;
  border-radius: 20px;
  align-self: flex-start;
}
.as-target.ok { background: #e9f2ea; color: #4a7a55; }
.as-target.over { background: #fbeceb; color: #a8403a; }

.c-status { display: flex; flex-direction: column; gap: 2px; align-items: flex-start; }
.as-status {
  font-size: 11px;
  padding: 2px 8px;
  border-radius: 20px;
  background: var(--surface-3);
  color: var(--text-2);
}
.as-status.serving { background: #e9f2ea; color: #4a7a55; }
.as-status.retired { background: var(--surface-3); color: var(--text-3); }
.as-status.favorite { background: #f5eef7; color: #7a5a85; }
.as-uses { font-size: 10.5px; color: var(--text-3); }

/* 存放地点：独立一列。
   它是"家 / 办公室 / 仓库"这种几个字的短标签，一行放得下；
   放不下就省略号 —— 完整内容在 title 里，hover 能看。
   空值给一个「—」占位，让整列看起来是齐的。 */
.c-loc { min-width: 0; align-self: center; }
.c-loc .as-loc {
  display: block;
  font-size: 11.5px;
  color: var(--text-2);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  /* 【line-height 必须显式给】
     不给的话这一格会继承行高，而 .as-row 是 grid + align-items:center ——
     格子被拉伸时 block 子元素跟着长高，实测窄屏下这一格高 70px，
     把整张卡片顶到 178px 高、白白多出一大片空白。
     钉死一行的高度，卡片才会是紧凑的。 */
  line-height: 18px;
}
/* 【这里**不能**用 .empty 这个类名】
   base.css 里有一个全局的 `.empty`（空状态占位：flex 居中 + padding 26px 16px）。
   我第一版把占位写成 `.as-loc.empty`，两个类撞在一起 ——
   那个 span 被撑到 70px 高，把整张卡片顶成 178px、多出一大片空白，
   而 computedStyle 看上去"哪条规则都对"，非常难查。
   所以占位改成自己的名字 `.as-loc.blank`，和全局那个 .empty 彻底分开。 */
.c-loc .as-loc.blank { color: var(--text-3); }

/* 成色：徽章 + 一颗「＋」。
   徽章按档位分色：越新越绿、越旧越暖，这样一屏扫下来
   "哪几件已经旧了"不用逐个读字。
   色档由 JS 打在 .wg-off / .wg-fair 这类类名上（见 ledger-assets.js 的 wearTone）。 */
.c-wear { display: flex; align-items: center; gap: 4px; min-width: 0; }
.as-wear {
  font-size: 11px;
  padding: 2px 8px;
  border-radius: 20px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  cursor: pointer;
  background: #e9f2ea;
  color: #4a7a55;
  transition: filter .14s var(--ease);
}
.as-wear:hover { filter: brightness(.96); }
/* 【为什么按档位分色】
   8 档要是全一个颜色，一屏扫下来只能逐个读字才知道哪件旧了。
   四档色：很新（99/95）绿 · 还行（90/80）蓝 · 旧了（70/60）琥珀 · 很旧（50/40）暖红。
   这是"扫一眼"和"逐个读"的区别。 */
.as-wear.wg-new { background: #e7f2ea; color: #3f7a51; }
.as-wear.wg-ok { background: #e8eff6; color: #47688c; }
.as-wear.wg-old { background: #fbf3e2; color: #8a6a20; }
.as-wear.wg-worn { background: #fbeceb; color: #a8403a; }
/* 没记过：灰底虚线感，明确是"空缺"而不是"某一种成色" */
.as-wear.none {
  background: transparent;
  border: 1px dashed var(--line-strong, var(--line));
  color: var(--text-3);
  padding: 1px 7px;
}
.c-wear .icon-btn.wear-add {
  min-width: 22px;
  height: 22px;
  font-size: 12px;
  padding: 0 4px;
  opacity: .55;
}
.c-wear:hover .icon-btn.wear-add { opacity: 1; }

.c-acts { display: flex; gap: 3px; justify-content: flex-end; }
.icon-btn {
  font: inherit;
  font-size: 11.5px;
  min-width: 26px;
  height: 26px;
  padding: 0 7px;
  border-radius: 7px;
  border: 1px solid transparent;
  background: transparent;
  color: var(--text-3);
  cursor: pointer;
  /* 【文字不许折行】
     用户报的：「退役按钮 字体现在超出的范围」。
     原因：这个类是给**单字符**按钮设计的（＋ ✎ ✕），
     内容盒只有 26 − 14(padding) = 12px 宽（实测 clientWidth 31−14=17px），
     而「退役」两个字要 23px 才排得下 —— 于是浏览器在两个字**中间断开**，
     竖着码成两行（实测 Range 给出两个 rect，y 分别是 375.3 / 393.7），
     文字高 33.4px 撑进 26px 的盒子里，上下都冒出去。
     加 nowrap 之后按钮会**按内容长宽**（把 min-width 当"最小值"用，
     这正是它该有的行为），两个字并排、盒子跟着变宽到 33px。
     这样也不用给每种图标按钮单独写死宽度。 */
  white-space: nowrap;
  transition: background .14s var(--ease), color .14s var(--ease), border-color .14s var(--ease);
}
.icon-btn:hover {
  background: var(--surface);
  border-color: var(--line);
  color: var(--text);
}
.icon-btn.del:hover { border-color: #e2c4c0; color: #a8403a; }

/* 窄屏：表格切成卡片式，一列一列横排会挤成一团 */
@media (max-width: 900px) {
  .as-thead { display: none; }
  /* 【卡片最后一行要并排放「存放地点 + 成色」，所以再切一格出来】
     原来只有 img / name / status 三列、三行网格区。
     现在多切一列 `meta`（放地点）和 `mwear`（放成色）：
         img name  status
         img amt   daily
         img span  acts
         img meta  mwear
     【为什么让它们各占一格，而不是都塞进同一个 grid-area】
     两个元素写同一个 grid-area 会**叠在一起**而不是并排 ——
     它们各自按自己的尺寸定位到那一格的左上/右上，
     实测 780px 下地点那一格宽 662px、成色直接压在它上面。
     各占一格才是真正的"左地点右成色"，而且挤不下时
     地点（minmax(0,1fr)）先收缩省略号，成色（auto）保住。 */
  .as-row {
    grid-template-columns: 46px minmax(0, 1fr) auto;
    grid-template-areas:
      'img name status'
      'img amt  daily'
      'img span acts'
      'img meta mwear';
    row-gap: 6px;
    border-color: var(--line);
    background: var(--surface);
  }
  .as-row .c-img { grid-area: img; align-self: start; }
  .as-row .c-name { grid-area: name; }
  .as-row .c-amt { grid-area: amt; }
  .as-row .c-daily { grid-area: daily; align-items: flex-end; }
  .as-row .c-status { grid-area: status; align-items: flex-end; }
  .as-row .c-acts { grid-area: acts; }
  .as-row .c-date, .as-row .c-days { display: none; }
  .as-row .c-span { grid-area: span; color: var(--text-3); }
  /* 地点靠左、成色靠右，各占一格，谁也不压谁 */
  .as-row .c-loc { grid-area: meta; min-width: 0; align-self: center; }
  .as-row .c-wear { grid-area: mwear; justify-self: end; align-self: center; }
}

/* ==========================================================================
   固定资产 · 四条视图
   ==========================================================================
   四条视图共用同一份数据，只是"看法"不同。切换控件放在工具条上，
   排在「全部分类」左边 —— 它是**换整块内容**的开关，比筛选更"大"，
   所以放在筛选控件的前面（从左到右：状态 → 视图 → 分类 → 排序 → 搜索）。
   -------------------------------------------------------------------------- */

.as-view-list,
.as-view-gallery,
.as-view-company,
.as-view-grid { display: flex; flex-direction: column; gap: 14px; }

/* 视图切换控件：复用 .segment 的公共外观，这里只调间距 */
.as-views { flex: none; }
.as-views .as-view-btn { white-space: nowrap; }

/* ---------------------- 视图 2：灵感画廊 ---------------------- */
/* 【为什么用 columns 而不是 grid】
   和灵感页的 .idea-wall 同一个做法：卡片按内容高低自然错落，
   不会出现"某张卡特别高 → 整行被撑到一样高 → 底下一大片空白"。
   3 列 / 每列至少 260px，宽度不够时浏览器自动减列。 */
.as-wall {
  columns: 3 260px;
  column-gap: 14px;
}
.as-card {
  break-inside: avoid;
  margin: 0 0 14px;
  padding: 14px;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r-md, 12px);
  box-shadow: var(--shadow-xs, 0 1px 2px rgba(0,0,0,.04));
  transition: transform .16s var(--ease), box-shadow .16s var(--ease), border-color .16s var(--ease);
}
.as-card:hover {
  transform: translateY(-2px);
  box-shadow: var(--shadow-md, 0 6px 16px rgba(0,0,0,.08));
  border-color: var(--line-strong, var(--line));
}
.as-card.off { opacity: .6; }
.as-card.off:hover { opacity: .85; }

.as-card-top { display: flex; align-items: flex-start; gap: 10px; }
/* 画廊的图标比列表大（列表 38px，这里 46px）—— 用户要求"图标/名字大一点" */
.as-card-img {
  width: 46px;
  height: 46px;
  flex: none;
  border-radius: 11px;
  object-fit: cover;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 22px;
  background: var(--surface-2);
  overflow: hidden;
}
img.as-card-img { background: none; }
.as-card-title { flex: 1 1 auto; min-width: 0; }
.ac-name {
  font-size: 14px;
  font-weight: 600;
  /* 【给标题留死两行的高度，哪怕它只有一行】
     用户报的：「灵感画廊有写标题两行会导致不对齐」。
     原因：标题一行时 .as-card-top 是 46px，两行时变 59px ——
     下面「金额 / 日均」那一行跟着往下走 13px。多列并排时，
     同一行里两张卡的数字高度就对不上了（实测两行那张 numsY=413、
     旁边一行的 400）。
     这里把高度**按两行钉死**，于是不管标题一行还是两行，
     卡片头都是同一个高度、下面的数字自然对齐。

     【必须写死 px 的行高，不能用 1.4 这种倍数】
     踩过一次：原来写 `line-height:1.4` + `min-height:calc(2*1.4*14px)`
     （算出 39.2px）。但标题现在是个 <button>，而 .as-name-btn 用了
     `font: inherit` —— 那个简写把行高重置回**继承来的 1.6**（= 22.4px）。
     于是两行真实高度 44.8px，撑破了按 39.2px 钉死的框：
     实测卡片头一行 58.8px、两行 64.4px，又回到不对齐。
     所以行高直接写 px（22px）、min-height 按它算两行（44px），两边同源。

     【截断交给里面的按钮】
     这里要 flex（垂直居中），而 -webkit-line-clamp 只在 display:-webkit-box
     下生效，两者不能同元素 —— 所以 .ac-name 只管撑高度 + 居中，
     .ac-name > .as-name-btn 负责两行截断（见上面那段）。 */
  line-height: 22px;
  min-height: 44px;
  display: flex;
  align-items: center;
}
.ac-cat { font-size: 11px; color: var(--text-3); margin-top: 2px; }

/* ---------------------- 点名称看详情 ---------------------- */

/* 【外观上要像"一段标题文字"，不能像个按钮】
   它是 <button>（为了键盘可达 + 读屏能念出来），但视觉上必须清掉
   按钮的一切痕迹：背景、边框、内边距、字体都用继承的。
   只在鼠标经过时给一点提示（下划线 + 变色），让人知道"这个能点"。 */
.as-name-btn {
  appearance: none;
  background: none;
  border: 0;
  padding: 0;
  margin: 0;
  font: inherit;
  color: inherit;
  text-align: left;
  cursor: pointer;
  /* 长名字要能换行（画廊里最多两行） */
  min-width: 0;
  /* 【自己负责两行截断】
     以前名字外面还套了一层 <span> 专门做 line-clamp，那是为了配合
     "高度钉死两行"那套。现在按钮本身就是直接内容，所以把截断收回来 ——
     但 flex 和 -webkit-box 不能同元素（见 .ac-name 那段），
     所以画廊里那个限制靠 .ac-name > .as-name-btn 单独处理。 */
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
  word-break: break-word;
}
.as-name-btn:hover { color: var(--brand, #48ab93); text-decoration: underline; text-underline-offset: 3px; }
.as-name-btn:focus-visible {
  outline: 2px solid var(--brand, #48ab93);
  outline-offset: 2px;
  border-radius: 4px;
}

/* 画廊里 .ac-name 是 flex（为了垂直居中），而 -webkit-line-clamp
   只在 display:-webkit-box 下生效 —— 两者不能同元素。
   所以画廊这一处用 .ac-name > .as-name-btn 把它变回 box 来截断：
   外层的 .ac-name 仍然负责"钉死两行的高度"。 */
.ac-name > .as-name-btn {
  display: -webkit-box;
  width: 100%;
}

/* ---------------------- 资产详情卡 ---------------------- */

.asd-body { display: flex; flex-direction: column; gap: 14px; }

/* 头部：大图标 + 大名字 */
.asd-head { display: flex; align-items: center; gap: 14px; }
.asd-icon-img {
  width: 76px; height: 76px;
  flex: 0 0 auto;
  border-radius: 16px;
  object-fit: cover;
  border: 1px solid var(--line);
}
.asd-icon-emoji {
  width: 76px; height: 76px;
  flex: 0 0 auto;
  border-radius: 16px;
  display: flex; align-items: center; justify-content: center;
  font-size: 38px;
}
.asd-head-main { min-width: 0; }
.asd-name {
  margin: 0;
  /* 比列表里那一行明显大（列表 13px）—— 这就是用户说的"放大" */
  font-size: 20px;
  font-weight: 600;
  line-height: 1.3;
  word-break: break-word;
}
.asd-tags { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 7px; }
.asd-tag {
  font-size: 11.5px;
  color: var(--text-2);
  background: var(--surface-2);
  border: 1px solid var(--line);
  border-radius: 999px;
  padding: 2px 9px;
  white-space: nowrap;
}
/* 状态用颜色区分：服役中=品牌色、退役=灰、收藏=金 */
.asd-status.serving { color: var(--brand, #48ab93); border-color: var(--brand-soft, rgba(107,122,90,.3)); }
.asd-status.retired { color: var(--text-3); }
.asd-status.favorite { color: #b8894a; border-color: #e6d5bb; }

/* 三个大数字 */
.asd-facts { display: grid; grid-template-columns: repeat(3, 1fr); gap: 10px; }
.asd-fact {
  background: var(--surface-2);
  border: 1px solid var(--line);
  border-radius: 10px;
  padding: 9px 11px;
  min-width: 0;
}
.asd-fact-k { display: block; font-size: 11px; color: var(--text-3); }
.asd-fact-v {
  display: block;
  margin-top: 2px;
  font-size: 17px;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}
.asd-fact-sub {
  display: block;
  margin-top: 3px;
  font-size: 10.5px;
  color: var(--text-3);
  line-height: 1.45;
  word-break: break-word;
}

/* 目标达成那一块 */
.asd-target {
  display: flex; flex-direction: column; gap: 2px;
  padding: 9px 11px;
  border-radius: 10px;
  background: var(--surface-2);
  border: 1px solid var(--line);
}
.asd-target.done { background: rgba(74, 143, 106, .1); border-color: rgba(74, 143, 106, .3); }
.asd-target-t { font-size: 12.5px; font-weight: 600; }
.asd-target.done .asd-target-t { color: #4a8f6a; }
.asd-target-d { font-size: 11px; color: var(--text-3); font-variant-numeric: tabular-nums; }

/* 详细字段：两列，空的自动不画 */
.asd-rows {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 7px 16px;
}
.asd-row { display: flex; align-items: baseline; gap: 8px; min-width: 0; }
.asd-k { flex: 0 0 auto; font-size: 11.5px; color: var(--text-3); }
.asd-v { font-size: 12.5px; color: var(--text); word-break: break-word; }

.asd-note {
  display: flex; flex-direction: column; gap: 4px;
  padding: 9px 11px;
  border-radius: 10px;
  background: var(--surface-2);
  border: 1px solid var(--line);
}
.asd-note-t { font-size: 12.5px; line-height: 1.6; white-space: pre-wrap; word-break: break-word; }

/* 成色那一块 */
.asd-wear {
  display: flex; flex-direction: column; gap: 8px;
  padding: 10px 11px;
  border-radius: 10px;
  background: var(--surface-2);
  border: 1px solid var(--line);
}
.asd-wear-now { display: flex; align-items: center; gap: 8px; font-size: 12px; }
.asd-wear-list { display: flex; flex-direction: column; gap: 3px; }
.asd-wear-row {
  display: flex; align-items: baseline; gap: 8px;
  font-size: 11.5px;
  min-width: 0;
}
.asd-wear-date { flex: 0 0 auto; color: var(--text-3); font-variant-numeric: tabular-nums; }
.asd-wear-g { flex: 0 0 auto; font-weight: 600; }
.asd-wear-note { color: var(--text-3); min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.asd-wear-more, .asd-wear-empty { font-size: 11px; color: var(--text-3); }
.asd-wear-btn { align-self: flex-start; }

/* 窄屏：两列压成一列，三个大数字也压成一列 */
@media (max-width: 700px) {
  .asd-facts { grid-template-columns: 1fr; }
  .asd-rows { grid-template-columns: 1fr; }
}

.as-card-nums {
  display: flex;
  gap: 18px;
  margin-top: 11px;
  padding-top: 10px;
  border-top: 1px solid var(--line);
}
.ac-num { display: flex; flex-direction: column; gap: 1px; }
.ac-num .k { font-size: 10.5px; color: var(--text-3); }
.ac-num .v { font-size: 13.5px; font-weight: 600; font-variant-numeric: tabular-nums; }

.as-card-meta {
  display: flex;
  flex-wrap: wrap;
  gap: 4px 10px;
  margin-top: 9px;
  font-size: 11px;
  color: var(--text-3);
}
.as-card-acts {
  display: flex;
  gap: 8px;
  justify-content: flex-end;
  margin-top: 11px;
}

/* ---------------------- 视图 3：陪伴列表 ---------------------- */
.as-company-list { display: flex; flex-direction: column; gap: 2px; }
.as-company-sum { font-size: 11.5px; color: var(--text-3); }

.as-ci-row {
  display: flex;
  align-items: center;
  gap: 11px;
  padding: 10px 11px;
  border-radius: var(--r-sm, 10px);
  border: 1px solid transparent;
  transition: background .14s var(--ease), border-color .14s var(--ease);
}
.as-ci-row:hover { background: var(--surface-2); border-color: var(--line); }
.as-ci-row.off { opacity: .58; }
.as-ci-row.off:hover { opacity: .85; }

.as-ci-img {
  width: 42px;
  height: 42px;
  flex: none;
  border-radius: 10px;
  object-fit: cover;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 20px;
  background: var(--surface-2);
  overflow: hidden;
}
img.as-ci-img { background: none; }

.as-ci-main { flex: 1 1 auto; min-width: 0; }
.ci-name {
  font-size: 13.5px;
  font-weight: 500;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.ci-cat { font-size: 10.5px; font-weight: 400; color: var(--text-3); margin-left: 7px; }
/* 「陪伴 428 天 · 日均 3.2 元 · 8成新」这一行。
   三段的字号和颜色一致，只有数字加粗 —— 一眼扫过去先看到数。 */
.ci-line {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 4px;
  margin-top: 3px;
  font-size: 12px;
  color: var(--text-2);
}
.ci-line b { font-weight: 600; color: var(--text); font-variant-numeric: tabular-nums; }
.ci-dot { color: var(--text-3); }
.ci-none { color: var(--text-3); }
.as-ci-acts { display: flex; align-items: center; gap: 4px; flex: none; }

/* ---------------------- 视图 4：多列网格 ---------------------- */
/* 【为什么用 auto-fill + minmax 而不是写死列数】
   写死 4 列的话，宽屏每格空一大块、窄屏硬挤 4 列会挤成一条线。
   auto-fill 让浏览器按可用宽度自己决定每行几列 ——
   宽屏自然多列、窄屏自动落成 1~2 列，而且**永远不会超过容器宽度**
   （横向溢出那条体检就盯这个）。 */
.as-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(190px, 1fr));
  gap: 10px;
}
.as-gi {
  display: flex;
  flex-direction: column;
  gap: 9px;
  padding: 11px;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r-sm, 10px);
  min-width: 0;
  transition: transform .16s var(--ease), box-shadow .16s var(--ease), border-color .16s var(--ease);
}
.as-gi:hover {
  transform: translateY(-1px);
  box-shadow: var(--shadow-xs, 0 1px 2px rgba(0,0,0,.05));
  border-color: var(--line-strong, var(--line));
}
.as-gi.off { opacity: .6; }
.as-gi-top { display: flex; align-items: center; gap: 8px; min-width: 0; }
.as-gi-img {
  width: 32px;
  height: 32px;
  flex: none;
  border-radius: 8px;
  object-fit: cover;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 16px;
  background: var(--surface-2);
  overflow: hidden;
}
img.as-gi-img { background: none; }
.gi-name {
  font-size: 12.5px;
  font-weight: 500;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.as-gi-body {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 6px;
  min-width: 0;
}
.gi-daily {
  font-size: 11.5px;
  color: var(--text-2);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

/* ---------------------- 四条视图的窄屏 ---------------------- */
/* 【窄屏要求：画廊 / 网格要能落到单列或两列，不许横向溢出、不许挤成一条线】
   —— 用户点名的那一条。
   · 画廊：columns 从 3 列 → 1 列（和灵感页 860px 的断点同一个做法）
   · 网格：minmax 的下限降到 150px，让 780px 下自然排成 2 列；
     再窄（<=560px）就落到 1 列。auto-fill 本身不会溢出，
     这里的断点只是调"每格至少多宽"，让列数好看一点。 */
@media (max-width: 1100px) {
  .as-wall { columns: 2 240px; }
}
@media (max-width: 780px) {
  .as-wall { columns: 1; }
  /* 【780px 下网格要落到两列 —— 用户点名的那一条】
     试过两个下限，都不对：
       · minmax(150px, 1fr) → 排出 **4 列**（每格 177px），名称截成一两个字
       · minmax(210px, 1fr) → 排出 **3 列**（每格 243px），还是偏窄
     容器在 780px 视口下约 738px，要稳定落成 2 列，
     下限必须满足 `3×下限 + 2×gap > 738` → 下限 > 239px。
     取 250px：3 列需要 770px（放不下），2 列每格 364px —— 宽松好读。
     【为什么是"下限"而不是写死 `repeat(2, 1fr)`】
     写死 2 列在 400px 的窄手机上也还是 2 列，又会挤扁；
     用下限 + auto-fill，更窄的屏会自己继续降到 1 列（见下面 560px 那条）。 */
  .as-grid { grid-template-columns: repeat(auto-fill, minmax(250px, 1fr)); }
  /* 陪伴列表在窄屏把操作按钮那一列收窄，别把"陪伴 N 天"那行挤掉 */
  .as-ci-row { gap: 9px; padding: 9px; }
  .as-ci-acts .icon-btn { min-width: 24px; padding: 0 5px; }
}
@media (max-width: 560px) {
  .as-grid { grid-template-columns: 1fr; }
}

/* ==========================================================================
   成色（磨损）记录弹窗
   ========================================================================== */

.as-wear-body { display: flex; flex-direction: column; gap: 12px; }

.as-wear-status {
  display: flex;
  align-items: baseline;
  gap: 8px;
  padding: 10px 12px;
  border-radius: var(--r-sm, 10px);
  background: var(--surface-2);
  border: 1px solid var(--line);
}
.as-wear-status .k { font-size: 12px; color: var(--text-3); }
.as-wear-status .v {
  font-size: 15px;
  font-weight: 600;
  display: flex;
  align-items: baseline;
  gap: 8px;
}
.as-wear-status .v.none { color: var(--text-3); font-weight: 500; font-size: 13px; }
.as-wear-status .v .dt { font-size: 11px; font-weight: 400; color: var(--text-3); }

.as-wear-list { display: flex; flex-direction: column; gap: 2px; }
.as-wear-loading,
.as-wear-empty {
  font-size: 12.5px;
  color: var(--text-3);
  line-height: 1.7;
  padding: 12px 2px;
}
/* 【每一格都要显式指定列，不能让 grid 自动排】
   历史行里「当前」那个标只有最新那条才有 —— 如果靠自动排，
   少一个子元素会让后面所有格子整体左移一格：
   实测没有 w-now 的那几行，删除按钮从 x=663 跳到 x=325，
   几行的按钮完全对不齐。所以用 grid-column 把每格钉死：
   日期 / 成色 / 「当前」/ 备注 / 删除，缺的那个留空。 */
.as-wear-row {
  display: grid;
  grid-template-columns: 88px 84px 34px minmax(0, 1fr) 30px;
  gap: 8px;
  align-items: center;
  padding: 8px 10px;
  border-radius: var(--r-sm, 10px);
  border: 1px solid transparent;
  font-size: 12px;
  transition: background .14s var(--ease);
}
.as-wear-row:hover { background: var(--surface-2); }
/* 最新那条（= 列表里显示的"当前成色"）加一点底色，
   用户一眼就知道"哪个才算数" */
.as-wear-row.latest { background: var(--brand-soft, #eef2e8); border-color: var(--line); }
.as-wear-row .w-date { grid-column: 1; color: var(--text-2); font-variant-numeric: tabular-nums; white-space: nowrap; }
.as-wear-row .w-grade { grid-column: 2; font-weight: 600; color: var(--text); white-space: nowrap; }
.as-wear-row .w-now {
  grid-column: 3;
  font-size: 10px;
  padding: 1px 6px;
  border-radius: 20px;
  background: var(--brand, #48ab93);
  color: var(--on-brand);
  justify-self: start;
  white-space: nowrap;
}
.as-wear-row .w-note {
  grid-column: 4;
  color: var(--text-3);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.as-wear-row .icon-btn.del { grid-column: 5; justify-self: end; }

.as-wear-add-box { display: flex; flex-direction: column; gap: 10px; }
.as-wear-form {
  display: grid;
  grid-template-columns: 150px 150px minmax(0, 1fr);
  gap: 12px;
}
/* 备注那一格占掉剩下的宽度；窄屏时整个表单落到一列 */
.as-wear-form .wcfg-field.wide { min-width: 0; }
.as-wear-form-acts { display: flex; gap: 8px; justify-content: flex-end; }

/* ==========================================================================
   表单零件（和组件设置共用一套外观，这里是记账特有的部分）
   ========================================================================== */

.wcfg-row {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  gap: 12px;
}
.wcfg-checks { display: flex; flex-wrap: wrap; gap: 16px; }
.wcfg-check {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 12.5px;
  color: var(--text-2);
  cursor: pointer;
}
.wcfg-check input { cursor: pointer; }

.wcfg-live {
  padding: 9px 12px;
  border-radius: 8px;
  background: var(--surface-2);
  border: 1px solid var(--line);
  font-size: 11.5px;
  line-height: 1.6;
  color: var(--text-2);
  font-variant-numeric: tabular-nums;
}

/* ------------------------------ 编辑弹窗里的「成色」 ------------------------------ */

/* 【为什么这一行只放一格，还要显式钉成一列】
   .wcfg-row 是 `repeat(auto-fit, minmax(150px, 1fr))` —— 自适应列数，
   弹窗内部可用宽度约 616px（modal 660 − 两侧 22px 内边距）能排下 3 列，
   只放一个孩子的话它会**独占一整行、被拉到 616px 宽**，
   旁边老大一片空白，看着像"这一格没做完"。
   钉成 1fr = 和「物品名称」那一格同宽（都是整行），下拉不会长得离谱；
   同时它是 1fr 而不是写死 px —— 窄屏跟着容器缩，不会撑出横向滚动条。 */
.as-grade-row { grid-template-columns: minmax(0, 1fr); }

/* 语义说明那一行小字。
   【为什么单独给个类，而不是直接复用 .wcfg-hint】
     .wcfg-hint 是"某一格下面的注解"（挂在 .wcfg-field 里、左边对齐那一格）。
     这一行讲的是**整格的行为**（保存是追加不是覆盖），横跨整个表单宽度，
     视觉上要像是弹窗自己的注解。所以给它一点底色，和上面那些输入框区分开。
   类名固定成 .as-grade-hint：检查脚本按它取这句话的原文做断言。 */
.as-grade-hint {
  display: block;
  padding: 8px 10px;
  border-radius: 8px;
  background: var(--surface-2);
  border: 1px solid var(--line);
  font-size: 11.5px;
  line-height: 1.65;
  color: var(--text-3);
}
/* 提示里那句"新增一条记录、不是覆盖"要能一眼看到 ——
   整段都是灰的，关键字用主题色加粗，扫一眼就抓住重点。
   主题色从 tokens.css 的 --brand 来，不写死：它会跟着主题（含深色）变。 */
.as-grade-hint b { color: var(--brand, #48ab93); font-weight: 600; }

/* ------------------------------ 图标选择器 ------------------------------ */

.icon-pick {
  display: flex;
  flex-direction: column;
  gap: 7px;
  padding: 10px;
  border-radius: 10px;
  border: 1px dashed var(--line);
  background: var(--surface-2);
  transition: border-color .15s var(--ease), background .15s var(--ease);
}
.icon-pick.over {
  border-color: var(--brand, #48ab93);
  background: var(--brand-soft, rgba(107, 122, 90, .08));
}
.icon-pick-box {
  width: 54px;
  height: 54px;
  border-radius: 12px;
  background: var(--surface);
  border: 1px solid var(--line);
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
}
.icon-pick-img { width: 100%; height: 100%; object-fit: cover; }
.icon-pick-emoji { font-size: 26px; }
.icon-pick-acts { display: flex; gap: 6px; flex-wrap: wrap; }
.icon-pick-hint { font-size: 11px; color: var(--text-3); }
.icon-pick-err {
  font-size: 11.5px;
  color: #a8403a;
  background: #fbeceb;
  padding: 5px 9px;
  border-radius: 7px;
}

/* ------------------------------ 分类：下拉 + 管理 ------------------------------ */

/* 分类那一格 = 下拉（自己占满剩余宽度）+ 「⚙ 管理」按钮 */
.as-cat-field {
  display: flex;
  align-items: center;
  gap: 6px;
}
.as-cat-field > select { flex: 1 1 auto; min-width: 0; }
/* 按钮不跟着拉长、也不被压扁 */
.as-cat-field > .as-cat-manage { flex: 0 0 auto; white-space: nowrap; }

/* ------------------------------ 管理分类弹窗 ------------------------------ */

.cm-body { display: flex; flex-direction: column; gap: 8px; }
.cm-sec-title {
  font-size: 11.5px;
  font-weight: 600;
  color: var(--text-3);
  letter-spacing: .02em;
  margin-top: 4px;
}
.cm-rows {
  display: flex;
  flex-direction: column;
  gap: 6px;
  /* 分类多了也不把弹窗撑爆：内部滚动 */
  max-height: 320px;
  overflow-y: auto;
  padding-right: 2px;
}
.cm-row {
  display: flex;
  align-items: center;
  gap: 7px;
}
/* 【合并之后这里只剩两个控件：图标方块 + 名称】
   原来还有「彩色小方块（.cm-swatch）+ 图标输入框（.cm-icon-inp）」两个 ——
   它们说的是同一件事，已合并成 .cm-icon-box（见下面那段说明）。 */
.cm-row .cm-name { flex: 1 1 auto; min-width: 0; }
/* 内置分类：名称框置灰，并挂一个「内置」小标 */
.cm-row .cm-name:disabled {
  background: var(--surface-2);
  color: var(--text-3);
  cursor: not-allowed;
}
.cm-tag {
  flex: 0 0 auto;
  font-size: 11px;
  color: var(--text-3);
  border: 1px solid var(--line);
  border-radius: 6px;
  padding: 3px 7px;
  white-space: nowrap;
}
.cm-row .cm-del { flex: 0 0 auto; }

.cm-add {
  display: flex;
  align-items: center;
  gap: 7px;
}
/* 新增区：图标方块 + 名称输入框 + 「添加」 */
.cm-add .wcfg-input { flex: 1 1 auto; min-width: 0; }
.cm-add > button { flex: 0 0 auto; white-space: nowrap; }
.cm-hint { font-size: 11px; color: var(--text-3); }

/* ------------------------------ 图标选择面板 ------------------------------ */

/* 每个分类行 + 它下面的面板（面板展开时把后面的内容推下去，不是浮层） */
.cm-item { display: flex; flex-direction: column; gap: 6px; }
.cm-panel-host:empty { display: none; }

/* 【图标只有一个控件：一个可以直接打字的方块】
   用户问过：「分类 图标为什么会有两个输入框？一个是选预置，一个是自定义？
   是否可以合并为一个」—— 合并之后它同时是：
     · 显示当前图标的方块
     · 可以**直接敲**的输入框
     · 点/聚焦就展开预设面板的入口
   所以样式上要"像方块"，但保留输入框的行为（居中、能编辑）。
   宽度写死 40px：够放一个 emoji，也不会把这一行挤变形。 */
.cm-icon-box {
  flex: 0 0 auto;
  width: 40px;
  height: 34px;
  padding: 0;
  text-align: center;
  font-size: 16px;
  line-height: 1;
  color: var(--text);
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 8px;
  cursor: text;
  transition: border-color .14s var(--ease);
}
.cm-icon-box:hover:not(:disabled) { border-color: var(--brand, #48ab93); }
.cm-icon-box:focus {
  outline: none;
  border-color: var(--brand, #48ab93);
  box-shadow: 0 0 0 3px var(--brand-soft, rgba(107, 122, 90, .15));
}
/* 内置分类：灰掉、不可编辑（图标在代码里，改了下次启动会变回去） */
.cm-icon-box.locked,
.cm-icon-box:disabled {
  background: var(--surface-2);
  color: var(--text-3);
  cursor: not-allowed;
}

.cip-panel {
  border: 1px solid var(--line);
  border-radius: 10px;
  background: var(--surface-2);
  padding: 9px;
  display: flex;
  flex-direction: column;
  gap: 7px;
}
.cip-head { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
.cip-title { font-size: 11.5px; font-weight: 600; color: var(--text-2); }
.cip-close {
  border: 0;
  background: none;
  color: var(--text-3);
  cursor: pointer;
  font-size: 13px;
  line-height: 1;
  padding: 3px 5px;
  border-radius: 6px;
}
.cip-close:hover { background: var(--surface); color: var(--text); }

.cip-search {
  font: inherit;
  font-size: 12px;
  padding: 6px 9px;
  border-radius: 7px;
  border: 1px solid var(--line);
  background: var(--surface);
  color: var(--text);
  width: 100%;
  box-sizing: border-box;
}
.cip-search:focus { outline: none; border-color: var(--brand, #48ab93); }

/* 图标网格：内部滚动。417 个图标全铺开会很长，
   给一个上限、让它自己滚 —— 弹窗整体高度就不会失控。 */
.cip-grid {
  max-height: 208px;
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  gap: 3px;
  padding-right: 2px;
}
.cip-group {
  font-size: 10.5px;
  font-weight: 600;
  color: var(--text-3);
  margin-top: 4px;
  position: sticky;
  top: 0;
  background: var(--surface-2);
  padding: 2px 0;
  z-index: 1;
}
.cip-row {
  display: grid;
  /* 自适应列数：窄屏自己少几列，不会横向溢出 */
  grid-template-columns: repeat(auto-fill, minmax(30px, 1fr));
  gap: 3px;
}
.cip-cell {
  font-size: 17px;
  line-height: 1;
  height: 30px;
  padding: 0;
  border-radius: 7px;
  border: 1px solid transparent;
  background: transparent;
  cursor: pointer;
  transition: background .12s var(--ease), border-color .12s var(--ease);
}
.cip-cell:hover { background: var(--surface); border-color: var(--line); }
.cip-cell.on {
  border-color: var(--brand, #48ab93);
  background: var(--brand-soft, rgba(107, 122, 90, .12));
}
.cip-cell:focus-visible { outline: 2px solid var(--brand, #48ab93); outline-offset: 1px; }
.cip-empty { font-size: 11.5px; color: var(--text-3); padding: 6px 2px; }

/* 底部那句说明：想用面板里没有的图标就去左边方块里敲。
   它只是提示，不是输入框（那正是用户觉得冗余的地方）。 */
.cip-tip { font-size: 11px; color: var(--text-3); line-height: 1.5; }

/* ==========================================================================
   记账 · 流水（需求六，兼容一木记账）
   ==========================================================================
   复用资产那套 `.as-table / .as-row / .as-thead` 的格语言 ——
   三个页签（订阅 / 资产 / 流水）的"一行"看起来是一回事，
   改一处节奏两边一起变。这里只定义流水**特有**的列宽和几个小标。
   -------------------------------------------------------------------------- */

/* 列宽。和订阅那张表同一个算法：把总和压在 ~700px，
   留足 9 个 7px 间隙（10 列）和行内边距的余量，
   免得窄屏顶出去（订阅那边就是因为漏算间隙顶破过一次）。

   【2026-10-03 改成 7 列 —— 备注和标签拆开了】
   用户提的：「备注和标签应该分开 单独列；不要做到同一列」。
   原来备注和标签挤在一个 minmax(140px, 2fr) 里，
   长备注会把标签挤没、短备注又让标签位置飘。
   现在各给一列：备注宽一点（它可能很长），标签窄一点（几个短词）。 */
.rec-table .as-thead,
.rec-table .as-row {
  /* 【列宽由 JS 写 inline style 覆盖 —— 用户要"像 Excel 那样拖"】
     这里给的是**初始值**（JS 里 REC_COLS 那份才是权威）。
     列是 10 个：时间 / 分类 / 备注 / 标签 / 地址 / 账户
                / 报销 / 账本 / 金额 / 操作。

     ⚠️ 【加列时这里必须跟着改】
     用户 2026-10-08 要加「报销」「账本」两列时，我改了 JS 里的
     REC_COLS 和表头，**漏了这个 CSS** ——
     结果 grid 只有 8 个轨道、DOM 有 10 个格子，最后两列被挤到隐式行里：
       · 拖列宽时位移数组少两项（金额列的下标都错了）
       · 金额列右缘出现 90px 固定空白
     check:ledger-ui 当场抓到了（"表格总宽没被撑大"、
     "金额列右缘始终贴住表格右边"）。**两处要一起改。**

     【金额列是弹性的】—— 用户 2026-10-03 提的：
       「金额根据窗口大小固定到最右侧吧」
     所以是 `minmax(104px, 1fr)` 而不是固定的 104px：
     窗口变宽时它吃掉多出来的空间，右缘始终贴着操作列。
     前面那些列固定 + 金额弹性 + 操作列固定 = 金额钉在最右。 */
  grid-template-columns:
    minmax(40px, 54px)     /* 时间 */
    minmax(80px, 160px)    /* 分类（一级图标+名 · 二级图标+名） */
    minmax(70px, 160px)    /* 备注 */
    minmax(62px, 120px)    /* 标签 */
    minmax(60px, 100px)    /* 地址 */
    minmax(62px, 110px)    /* 账户 */
    minmax(60px, 84px)     /* 报销（待报 / 已报 / 多报少报） */
    minmax(64px, 90px)    /* 账本 */
    minmax(78px, 1fr)      /* 金额（弹性，钉在最右） */
    72px;                  /* 操作 */
  gap: 7px;
}

/* 【列宽拖拽把手】
   贴在每列表头的右边缘。默认完全透明（不干扰视觉），
   悬停时才显出一条细线 —— 让用户知道"这里能拖"，但平时不吵。 */
.rec-resize {
  position: absolute;
  top: 0;
  bottom: 0;
  right: -4px;
  width: 8px;
  cursor: col-resize;
  z-index: 3;
}
.rec-resize::after {
  content: '';
  position: absolute;
  top: 2px;
  bottom: 2px;
  left: 3px;
  width: 1px;
  background: transparent;
  transition: background .12s var(--ease);
}
.rec-resize:hover::after { background: var(--brand, #48ab93); }
/* 表头每一列都要 relative，把手才能定位 */
.rec-table .as-thead > span { position: relative; }

/* 一天一条小标题（日期 + 当天小计）。
   一木那种一天几十笔的记法，平铺成一长条根本看不出"今天花了多少"。 */
.rec-day {
  display: flex;
  align-items: baseline;
  /* 【日期和小计挨在一起放左边 —— 用户 2026-10-03 提的】
     原来是 space-between，小计被甩到屏幕最右边，
     而最右边正好是月份导航栏那一条 —— 两个不相干的东西挤在一起，
     用户说"有点乱"。现在都靠左，右边留白。 */
  justify-content: flex-start;
  gap: 12px;
  padding: 12px 10px 4px;
  /* 第一天上面不要多余的空 */
  margin-top: 2px;
}
/* 【日期用紫色 —— 参考站的特征色，用户 2026-10-03 要求照抄】
   实测参考站的"2024年10月11日"是 #8b5cf6（w700、17px）。
   在它那儿这是**一眼能认出来**的记号：扫列表时先看到紫色的日期行，
   再往下看具体流水。我原来是 --text-2 的灰，和其它小字混在一起。
   字号也从 12px 提到 13px —— 它 17px 在手机上是主视觉，
   桌面端按比例缩到 13px 比较合适（我们的行更密）。 */
.rec-day .rd-date { font-size: 13px; font-weight: 700; color: var(--date-color); }
.rec-day .rd-sum { display: flex; align-items: baseline; gap: 10px; font-size: 11.5px; }
/* 当天小计的收/支也换成令牌 —— 原来写死 #b4483a/#4a8f6a，
   那是旧基调的砖红和墨绿，夜间主题下会糊在深底上 */
.rec-day .rd-sum .out { color: var(--red); font-variant-numeric: tabular-nums; }
.rec-day .rd-sum .in { color: var(--green); font-variant-numeric: tabular-nums; }
.rec-day .rd-n { color: var(--text-3); }

/* ==========================================================================
   流水表格：让每一列分得开、每一行看得出边界
   --------------------------------------------------------------------------
   用户 2026-10-03 提的两条：
   「流水页 表格 太单调，不利于观看，比如表格没有虚线等等，
     每一行的颜色填充和背景色一致，只有字体颜色不一致，这样会显得很单调」
   「流水页的列，并没有明显的分开，比如 备注和标签串在了一起；
     金额标题位置和实际内容不在同一个列对齐」

   两个问题的根因不同：
     · "太单调" —— 行与行之间只有间距，没有**边界**（没有虚线、没有底色差）
     · "列分不开" —— 格子之间只有 7px 的空隙，没有**视觉分隔**
   ========================================================================== */

/* --- 1. 表头 ---
   【用户 2026-10-03 提的】「表头 颜色填充有问题，太锐」
   原来表头有一层实底色 + 一条实下边线，对比度偏硬。
   现在：底色去掉（和表格同一个面）、只留一条**淡**的虚线做分隔，
   文字的层次靠字重和颜色拉开。 */
.rec-table .as-thead {
  position: sticky;
  /* 【top 的取值】
     页头是固定的（约 56px），表头要贴在它下面。
     给 0 会被页头盖住，给太大会露出一条缝。 */
  top: 0;
  z-index: 2;
  /* 【表头配色 —— 用户 2026-10-03 说"颜色填充有问题 / 与周边格格不入"】
     这里改过四次，把每次的问题记下来，免得再来回改：

       v1 `--surface`（#ffffff）—— 纯白。表头和数据行同色，
          两者之间只剩一条线，滚动时看着像"一整块"，很锐。
       v2 `color-mix(--surface 92%, transparent)` + 毛玻璃 ——
          **半透明会把滚动经过的流水文字透上来**，表头字和流水字叠成重影。
          用户说的"诡异"就是这个。
       v3 `--surface-2`（#faf9f7）—— 不透明了，但它是**比页面底色更亮**的白。
          实测亮度：表头 249 / 页面 242 —— 表头像一条**浮在上面的白带子**，
          而它周围（页面、卡片）都是米灰调，所以"格格不入"。

       v4（现在）**比页面底色更暗一档**：用 `--surface-3`（#f3f1ed）。
         这才是表头该有的样子 —— 它是"表的一部分"，不是浮起来的卡片。
         往暗里走也天然不会透出内容（不透明），不用毛玻璃。
         在深色主题下这套 token 同样成立（它们的相对关系是一样的）。 */
  background: var(--surface-3);
  color: var(--text-2);
  font-weight: 500;
  letter-spacing: .02em;
  /* 一条淡虚线代替原来的实线 */
  border-bottom: 1px dashed var(--line);
  padding-bottom: 7px;
  margin-bottom: 3px;
}

/* --- 2. 行：用**框**，不用斑马纹 ---
   【用户 2026-10-03 提的】
   「流水的行 每一行的高度不一致，同时 现在颜色有问题，使用交替颜色，
     但是 深色部分，我鼠标移动到上面时，灰色部分无法高亮，
     能不能改用框的方式，而不是交替颜色」

   【为什么斑马纹会"移上去不亮"】
     斑马纹是给偶数行加了一层 `color-mix(..., 3%, transparent)` 的**浅灰**。
     悬停时我又设 `background: var(--surface-2)` ——
     两者都是"给 background 赋值"，而悬停那条写在前面的选择器优先级更低，
     于是奇数行（本来透明）能亮、**偶数行（有灰底）亮不起来**。
     用户观察到的"深色部分移上去不高亮"就是这个。

   【改成框的好处】
     · 每行一个**独立**的圆角框，边界清楚，不再依赖底色深浅
     · 悬停只管改边框和底色，不存在"覆盖不掉"的问题
     · 行高不一致也不明显了 —— 每行自带边界，参差反而像卡片
   所以这里彻底去掉斑马纹和行间虚线，改成：每行一个框。 */
.rec-table .rec-row {
  position: relative;
  background: transparent;
  /* 【每行一个框】—— 1px 淡边 + 圆角 */
  border: 1px solid var(--line);
  border-radius: 9px;
  /* 【行高统一】
     用户说"每一行的高度不一致"。原因是有的行备注很长会换行、
     有的行标签多会撑高。给一个**最小高度**，
     并且让内容不换行（超出省略号），行高就齐了。 */
  min-height: 40px;
  padding-top: 6px;
  padding-bottom: 6px;
  margin-bottom: 5px;
  transition: border-color .12s var(--ease), background .12s var(--ease);
  /* 【操作列里的两个按钮不许换行 —— 用户 2026-10-03 报的 bug】
     「编辑和删除被挤到下一行去了」

     根因：`.icon-btn` 是 `min-width:26px + padding:0 7px`，
     两个按钮加 3px 间距 = 26+26+3 = **55px**；
     而操作列只给了 64px，再算上格子的内边距和 gap，实际可用不到 55px
     —— 于是第二个按钮被挤到下一行，行高从 40px 涨到 69px。

     这里做两件事：
       1. 让 `.c-acts` 自己不换行（flex-wrap: nowrap），
          并且 `overflow: visible` —— 宁可稍微溢出也不折行；
       2. 把操作列宽从 64px 提到 72px（REC_COLS 里同步改）。
     用 nowrap 而不是"把列加宽"单靠一招：**用户可以把列拖窄**，
     拖窄之后还是得靠 nowrap 兜底。 */
  grid-auto-rows: min-content;
}
.rec-table .rec-row .c-acts { flex-wrap: nowrap; }
/* 最后一行不要多余的间距 */
.rec-table .rec-row:last-child { margin-bottom: 0; }

/* 【悬停：边框变深 + 淡底色】
   用 border-color 和 background 两个都改，而且选择器只有一层 ——
   这样奇数行偶数行表现完全一样（上一版斑马纹就是栽在这）。 */
.rec-table .rec-row:hover {
  border-color: var(--brand, #48ab93);
  background: var(--surface-2);
}

/* --- 3. 列之间立一道分隔 ---
   在**分类 / 备注 / 标签 / 账户**这四列左侧各拉一根淡竖线，
   扫的时候眼睛有落点。（备注和标签拆开后，标签列也要有线。） */
.rec-row .c-cat,
.rec-row .c-note,
.rec-row .c-tags,
.rec-row .c-acct {
  position: relative;
}
.rec-row .c-cat::before,
.rec-row .c-note::before,
.rec-row .c-tags::before,
.rec-row .c-acct::before {
  content: '';
  position: absolute;
  left: -8px; top: 50%;
  transform: translateY(-50%);
  height: 62%;
  border-left: 1px solid var(--line);
  opacity: .5;
  pointer-events: none;
}
/* 表头也立一样的线，上下对齐 */
.rec-table .as-thead .c-cat,
.rec-table .as-thead .c-note,
.rec-table .as-thead .c-tags,
.rec-table .as-thead .c-acct { position: relative; }
.rec-table .as-thead .c-cat::before,
.rec-table .as-thead .c-note::before,
.rec-table .as-thead .c-tags::before,
.rec-table .as-thead .c-acct::before {
  content: '';
  position: absolute;
  left: -8px; top: 50%;
  transform: translateY(-50%);
  height: 60%;
  border-left: 1px solid var(--line);
  pointer-events: none;
}

/* --- 4. 备注列和标签列各自独立 ---
   （拆成两列之后不再需要"备注占满、标签靠右"那套，
    各占自己的列即可；这里只保证单行不撑高。） */
.rec-row .c-note,
.rec-row .c-tags {
  display: flex;
  align-items: center;
  gap: 6px;
  /* 【不换行】—— 换行会让行高不一致（用户提的）
     超出走省略号，反正鼠标悬停有 title 看全文。 */
  flex-wrap: nowrap;
  overflow: hidden;
  min-width: 0;
}
.rec-row .c-tags .rec-tags { flex-wrap: nowrap; overflow: hidden; }
/* 标签之间也拉开一点，不然三四个挤成一坨 */
.rec-tags { gap: 5px; }

/* 行的三个专用格子 */
.rec-row .c-when { font-size: 11.5px; color: var(--text-3); font-variant-numeric: tabular-nums; }
.rec-row .c-cat { display: flex; align-items: center; gap: 6px; min-width: 0; }
.rec-cat { font-size: 12.5px; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* 【二级分类：自己的图标 + 更小的字 —— 用户 2026-10-03 提的】
   「账单类别 二级分类 也应该有图标」
   和一级拉开层次：一级 12.5px 正常色，二级 11px 淡一档。
   中间那种「·」分隔符不要了 —— 两级各自有图标，视觉上已经分得开。 */
.rec-cat2 {
  display: inline-flex;
  align-items: center;
  gap: 3px;
  flex: 0 1 auto;
  min-width: 0;
  font-size: 11px;
  color: var(--text-3);
  /* 前面留一点空隙，别和一级粘在一起 */
  margin-left: 5px;
  padding-left: 6px;
  border-left: 1px solid var(--line);
}
.rec-cat2-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.rec-row .c-cat { display: flex; align-items: center; gap: 3px; min-width: 0; }
/* 「导入」小标：让用户分得清哪些是搬进来的、哪些是自己记的 */
.rec-imp {
  flex: 0 0 auto;
  font-size: 9.5px;
  color: var(--text-3);
  border: 1px solid var(--line);
  border-radius: 20px;
  padding: 0 5px;
  line-height: 14px;
}

.rec-row .c-note { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; min-width: 0; }
.rec-note {
  font-size: 12px; color: var(--text-2);
  min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.rec-tags { display: flex; gap: 4px; flex-wrap: wrap; }
.rec-tag {
  font-size: 10px;
  /* 【药丸的颜色跟着标签自己的色走 —— 用户 2026-10-03
     「标签颜色 流水风格 字体颜色什么的，也都抄一下，总感觉它那个更好」】

     参考站的药丸是"**同色系的浅底 + 深字**"：
     比如绿标签是 字 #69ba6c、底 #f1f9f1（底只留约 3% 色度）。

     这里用一个 --tag 变量同时算两样：
       文字 = --tag（标签自己的颜色）
       底色 = --tag 兑 10% 再混 var(--surface)
     兑底色**不写死成某个浅色**，而是混 var(--surface) ——
     这样夜间主题下它自动变成"深底 + 亮字"，不用写第二套。
     没设过颜色的标签退回中性灰，和原来一样。 */
  color: var(--tag, var(--text-3));
  background: var(--surface-2);
  background: color-mix(in srgb, var(--tag, var(--surface-2)) 10%, var(--surface));
  border-radius: 20px;
  padding: 1px 6px;
  white-space: nowrap;
}
.rec-tag.more { color: var(--text-3); background: none; }
/* 【夜间：标签文字要往白里提】
   标签的颜色是**固定 hex**（用户在管理页设的、或按名字算出来的），
   按浅底设计的（比如蓝 #2d45be）。搬到夜间主题上，
   深蓝字压在深蓝底上几乎看不见 —— 实测对比度只有 1.5 上下。

   这里把标签色**和白色混到 55%**再当文字色：
   深蓝 → 浅蓝紫，压在深底上就清楚了。
   底色不用改，它本来就是"混 var(--surface)"算出来的，会自动变深。 */
[data-theme="night"] .rec-tag {
  color: color-mix(in srgb, var(--tag, var(--text-3)) 55%, #ffffff);
}
.rec-place {
  font-size: 10.5px; color: var(--text-3);
  min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.rec-none { font-size: 11.5px; color: var(--text-3); }

.rec-row .c-acct { font-size: 11.5px; color: var(--text-2); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.rec-row .c-amt { display: flex; flex-direction: column; align-items: flex-end; gap: 1px; }
/* 【表头"金额"也要右对齐】
   行里的金额是 flex-end 靠右的；表头如果是左对齐，
   标题和数据就分居两端、看着不是同一列（用户实测反馈过）。
   表头这一格用普通 span，所以直接 text-align。 */
.rec-table .as-thead .th-amt { text-align: right; display: block; }
.rec-row .c-amt b { font-size: 13px; font-variant-numeric: tabular-nums; }
/* 支出红、收入绿 —— 和统计模块同一套颜色口径 */
.rec-row.out .c-amt b { color: #b4483a; }
.rec-row.in .c-amt b { color: #4a8f6a; }
.rec-row .rec-sub { font-size: 10px; color: var(--text-3); }

/* 汇总卡：收入绿 / 支出红（和上面同一个口径） */
.lg-stat.rec-in .ls-value { color: #4a8f6a; }
.lg-stat.rec-out .ls-value { color: #b4483a; }

/* 列表被 LIMIT 截断时的提示 */
.rec-more { font-size: 11.5px; color: var(--text-3); }

/* ---------------------- 月份竖栏（右侧） ---------------------- */

/* 【为什么从"底部横条"改成"右侧竖栏"】
   用户 2026-10-03 提的：「月份选择在底部，当我一个月有几百条流水，
   我需要把纵向滑块条滑到很底部才能找到，是否可以参考 DeepSeek harness
   的右侧历史聊天记录快捷栏做修改」。

   原设计的问题很实在：横条挂在列表**下方**，列表一长就得先滚到底。
   改法就是 DeepSeek 那个思路 —— **导航和内容分开滚**：
     · .rec-body 是两栏 grid（内容 + 竖栏）
     · 竖栏 position: sticky，自己滚自己的，不跟着列表跑
     · 竖栏自己 overflow-y: auto（月份多了也不用整页滚） */
.rec-body {
  display: grid;
  /* 【月份栏宽度 86 → 104px】
     用户 2026-10-03 报：「右侧月份 时间轴的年份 数字超出范围」

     根因是**栏太窄**。用户的年份行要显示「▾ 2024 2391」
     （他真实的年份条数是 2126 / 2391 / 2286 / 1838，都是四位数），
     而 86px 装不下 —— 条数被顶出去，还出现了横向滚动
     （实测内容右缘 1461 > 栏内缘 1456、scrollW 83 > clientW 76）。

     宽度是**量出来的**，不是估的（用临时元素量三个部分的自然宽度）：
       箭头 7.7 + 间距 5 + 年份"2024" 30.8 + 间距 5 + 条数"2391" 22.3
       + 头部内边距 14 + 边框 2 = **86.8px**
     再加上月份栏自己的左右内边距（各 5px）= 96.8px。
     原先试 96px 时正好差 1px，仍旧截断（实测"有 2 行被截断"）。
     取 **104px**，给四位数条数留 7px 余量 —— 将来某年上万条
     （"12345"）也基本装得下。 */
  grid-template-columns: minmax(0, 1fr) 104px;
  gap: 16px;
  align-items: start;
}
.rec-content { min-width: 0; }

.rec-rail {
  position: sticky;
  /* 【top 的取值】
     页头是固定的，留 12px 的呼吸。取太大会让竖栏一开始就"飘"在中间。 */
  top: 12px;
  display: flex;
  flex-direction: column;
  gap: 6px;
  max-height: calc(100vh - 140px);
  overflow-y: auto;
  /* 自己滚的时候不要露出难看的滚动条 */
  scrollbar-width: thin;
  padding-right: 2px;
}
.rec-rail-title {
  font-size: 10.5px;
  color: var(--text-3);
  padding: 0 0 4px 2px;
  letter-spacing: .04em;
}
.rec-rail-list {
  display: flex;
  flex-direction: column;
  gap: 6px;
  /* 【光标要相对**这个容器**定位】
     光标是 railList 的绝对定位子元素，靠 offsetTop 对齐月份按钮 ——
     所以 railList 必须是定位祖先，否则光标会跑到 monthRail 外面去。 */
  position: relative;
}

/* ==========================================================================
   自定义日期范围（统计页）—— 用户 2026-10-03 提的
   「时间范围 增加 自定义日期范围等」
   ========================================================================== */
.range-row {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
}
.range-row .lg-inp {
  /* 两个日期框等宽，看着整齐 */
  flex: 1 1 150px;
  min-width: 0;
}
.range-lab {
  font-size: 12px;
  color: var(--text-2);
  flex: none;
}
.range-quick {
  display: flex;
  gap: 6px;
  margin-top: 10px;
  flex-wrap: wrap;
}
/* 「自定义」那个粒度和按钮和另外三个长得一样，只是多一个省略号 */
.stat-grain-custom { white-space: nowrap; }

/* ==========================================================================
   滚轮选月份时的「矩形框光标」—— 用户 2026-10-03 提的
   「增加一个日期选择的矩形框，当我滚轮时，先矩形框动，
     上下动态动画移动……有一个动态的动画效果，柔和一点」
   --------------------------------------------------------------------------
   它只负责"动"：滚轮时立刻跟着走（transform，走合成层不掉帧），
   真的换月要等停稳 380ms（见 JS 里的 debounce）。
   这样滚的过程是顺滑的，而网络请求只在停下来之后发一次。
   ========================================================================== */
.rec-rail-cursor {
  position: absolute;
  left: 0;
  right: 0;
  top: 0;
  border-radius: var(--r-sm);
  /* 只描边不填色 —— 填色会盖住月份文字；描边反而更像"选择框" */
  border: 2px solid var(--brand);
  background: color-mix(in srgb, var(--brand) 10%, transparent);
  /* 【柔和的来源】用 cubic-bezier 而不是 linear：
     linear 是匀速的，机械；这条曲线起步快、收尾慢，
     像是有惯性，滚动快的时候尤其明显。 */
  transition: transform .22s cubic-bezier(.22, .61, .36, 1), height .16s var(--ease),
    opacity .16s var(--ease);
  pointer-events: none;         /* 别挡住月份的点击 */
  z-index: 2;
  opacity: 0;
}
/* 滚动过程中让光标稍微"呼吸"一下，暗示数据还在等停稳 */
.rec-rail.picking .rec-rail-cursor {
  background: color-mix(in srgb, var(--brand) 18%, transparent);
}

/* 【换月之后数据淡入 + 轻微上浮】
   用户要的"等我确认停下来后，再显示数据出来"。
   直接硬切会显得突兀；淡入让"光标停 → 内容出现"连成一气。 */
@keyframes recEnter {
  from { opacity: 0; transform: translateY(4px); }
  to   { opacity: 1; transform: none; }
}
.rec-table.rec-enter {
  animation: recEnter .26s cubic-bezier(.22, .61, .36, 1);
}
@media (prefers-reduced-motion: reduce) {
  .rec-rail-cursor { transition: none; }
  .rec-table.rec-enter { animation: none; }
}

/* ==========================================================================
   月份导航树：年（大节点）→ 月（小节点）
   --------------------------------------------------------------------------
   用户 2026-10-03 提的：
     「右侧月份选择应该是 大小节点的方式，月份为大节点，日期为小节点，
       可滚轮滑动，应该存在N年的情况」

   所以层次靠三样拉开：
     · 年：字号大一点、有底色、可折叠
     · 月：字号小一点、缩进在年下面
     · 年份之间一条虚线
   ========================================================================== */

/* 一年一组 */
.rec-year { display: flex; flex-direction: column; gap: 2px; }

/* 年那一行（大节点）：箭头 + 年份 + 该年总条数 */
.rec-year-head {
  font: inherit;
  display: flex;
  align-items: center;
  gap: 5px;
  /* 【不能用 width:100% + padding —— 用户 2026-10-03 报的
     「右侧月份 时间轴的年份 数字超出范围」】

     原因是 box-sizing 加 padding：`width:100%` 指的是**内容盒**，
     再叠加左右各 7px 的内边距和 1px 边框，整个盒子就比容器宽 16px。
     条数少（"36"）的时候看不出来，一旦是四位数
     （用户真实的年份条数是 2126 / 2391 / 2286 / 1838）就顶出去了 ——
     实测内容右缘 1461 > 月份栏内缘 1456，而且 scrollW 83 > clientW 76
     出现了横向滚动。

     改成 `width:auto`（flex 子项默认就会占满可用宽度），
     再靠 min-width:0 让里面的文字能被压缩、加省略号兜底。 */
  width: auto;
  min-width: 0;
  font-size: 12.5px;
  font-weight: 600;
  padding: 5px 7px;
  border-radius: 8px;
  border: 1px solid transparent;
  background: var(--surface-2);
  color: var(--text);
  /* 【溢出兜底】万一以后年份条数更多（五位），
     也不要顶破月份栏 —— 直接裁掉，不要出现横向滚动条。 */
  overflow: hidden;
}
  cursor: pointer;
  text-align: left;
  transition: background .12s var(--ease), border-color .12s var(--ease);
}
.rec-year-head:hover { border-color: var(--line-strong, var(--line)); }
/* 当前所在的年：左边一道竖线（和月份那个同一套语言） */
.rec-year-head.on {
  background: var(--brand-soft, rgba(107, 122, 90, .14));
  border-color: var(--brand, #48ab93);
}
.rec-year-arrow {
  flex: 0 0 11px;
  font-size: 9px;
  color: var(--text-3);
  line-height: 1;
}
/* 【年份那一行的三个部分怎么分空间】
   弹性分配：箭头固定、年份可伸缩、条数优先保住。
   条数**不能被压缩**（`flex: 0 0 auto`）—— 它是数字，
   压扁了就成了"212…"看不出是多少；实在放不下时
   宁可让年份被省略号截断（年份是 4 位、用户心里有数）。 */
.rec-year-name {
  flex: 1 1 auto;
  /* 【必须给 min-width:0，否则 flex 子项不会收缩到内容宽度以下】
     不给的话，年份"2024"会撑着自己的最小内容宽，
     把右边的条数顶出容器 —— 这正是"数字超出范围"的另一半原因。 */
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
}
/* 年总条数（小、淡 —— 别抢年份本身的注意力） */
.rec-year-n {
  /* 【不能再 0 0 auto 了】
     原来是 flex:0 0 auto —— 完全不收缩。四位数条数
     （用户真实的年份是 2126 / 2391）加上年份和箭头就超宽了。
     改成允许收缩、并且用更小的字号：
     10px → 9.5px，四位数字省下约 2px，加上能收缩就装得下了。
     另外加 nowrap + 数字等宽，避免它自己换行。 */
  flex: 0 1 auto;
  min-width: 0;
  font-size: 9.5px;
  font-weight: 400;
  color: var(--text-3);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

/* 回到底部那颗（翻远了才出现） */
.rec-rail-today {
  font: inherit;
  font-size: 11px;
  margin-top: 4px;
  padding: 4px 0;
  border-radius: 8px;
  border: 1px dashed var(--line);
  background: transparent;
  color: var(--text-3);
  cursor: pointer;
}
.rec-rail-today:hover { color: var(--text-2); border-style: solid; }

/* 月份（小节点）：缩进在年下面，字号比年小 */
.rec-month {
  font: inherit;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 1px;
  font-size: 11px;
  padding: 4px 8px 4px 16px;   /* 左内边距留出缩进，视觉上"挂在年下面" */
  border-radius: 8px;
  border: 1px solid transparent;
  /* 【未选中的不做卡片】
     一排 12 个描边小方块会显得很吵。未选中就"平"着，
     选中的那个才浮出来 —— 一眼看得出现在在哪个月。 */
  background: transparent;
  color: var(--text-3);
  cursor: pointer;
  text-align: left;
  position: relative;
  transition: background .12s var(--ease), color .12s var(--ease);
}
.rec-month:hover { background: var(--surface-2); color: var(--text-2); }
.rec-month.on {
  background: var(--brand-soft, rgba(107, 122, 90, .14));
  border-color: var(--brand, #48ab93);
  color: var(--text);
  font-weight: 600;
}
/* 当前那个再补一根左侧竖线 —— 色弱也分得出来 */
.rec-month.on::before {
  content: '';
  position: absolute;
  left: -1px; top: 50%;
  transform: translateY(-50%);
  width: 3px; height: 16px;
  border-radius: 2px;
  background: var(--brand, #48ab93);
}
/* 没有流水的月份：压暗，但仍然可点（点了就是空列表，不算错） */
.rec-month.empty { opacity: .45; }
/* `.mk` 是"26/10"这种月份，`.mn` 是右边的条数。
   （`.mn` 本来就有样式；`.mk` 是后加标签时漏的 —— audit:styles 抓出来过。） */
.rec-month .mk { font-variant-numeric: tabular-nums; white-space: nowrap; }
.rec-month .mn { font-size: 10px; color: var(--text-3); font-variant-numeric: tabular-nums; }

/* 窄屏：竖栏放不下，退回顶部一条横向可滚的条 */
@media (max-width: 820px) {
  .rec-body { grid-template-columns: minmax(0, 1fr); gap: 10px; }
  .rec-rail {
    position: static;
    flex-direction: row;
    align-items: center;
    gap: 6px;
    max-height: none;
    overflow-x: auto;
    overflow-y: hidden;
    padding-bottom: 4px;
    /* 放**上面**：窄屏没有"右侧"可用，横着滚的条放顶部更容易够到 */
    order: -1;
    border-bottom: 1px dashed var(--line);
  }
  .rec-rail-title { padding: 0 6px 0 0; flex: 0 0 auto; }
  /* 【窄屏：年/月树塌成一排横向的】——
     没有"右侧"可用，横着滚的条放顶部更容易够到。
     年那层在窄屏不再折叠（横向排展开更好认）。 */
  .rec-rail-list { flex-direction: row; gap: 8px; align-items: flex-start; }
  .rec-year { flex: 0 0 auto; }
  .rec-year-head { flex: 0 0 auto; width: auto; }
  .rec-year-arrow { display: none; }
  .rec-month { flex: 0 0 auto; align-items: center; padding: 4px 9px; }
  .rec-month.on::before { display: none; }
  .rec-rail-today { flex: 0 0 auto; margin-top: 0; padding: 4px 8px; }
}

/* ---------------------- 记一笔的表单 ---------------------- */

.rec-form { display: flex; flex-direction: column; gap: 12px; }
.rec-form-row { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }
.rec-form .field { min-width: 0; }
.rec-amount { font-size: 20px; font-weight: 600; text-align: right; font-variant-numeric: tabular-nums; }

/* ==========================================================================
   标签选择（两级：一级可收起，二级小字）
   --------------------------------------------------------------------------
   用户 2026-10-03 给的结构：
     （下箭头，可收起，默认展开）一级
     二级、二级、二级
   「二级字体要小一些」。

   所以这里的层次靠**三样**拉开：
     1. 一级独占一行、字号 12.5、加粗；二级在下一行、字号 11、不加粗
     2. 一级左边有箭头、有底色块；二级缩进 + 浅色描边
     3. 组与组之间一道虚线
   只靠一样不够 —— 用户之前就说"分不清哪几个属于哪一组"。
   ========================================================================== */
.rec-tagpick { display: flex; flex-direction: column; gap: 10px; }

/* 一组 = 一级那一行 + 它下面的二级行 */
.rec-taggroup { display: flex; flex-direction: column; gap: 6px; }
.rec-taggroup + .rec-taggroup {
  padding-top: 9px;
  border-top: 1px dashed var(--line);
}

/* 一级那一行：箭头 + 一级标签 + （收起时的）数量提示 */
.rec-taghead { display: flex; align-items: center; gap: 6px; }

/* 折叠箭头 */
.rec-tagarrow {
  flex: 0 0 16px;
  width: 16px;
  text-align: center;
  font-size: 10px;
  line-height: 1;
  color: var(--text-3);
  cursor: pointer;
  user-select: none;
  transition: color .12s var(--ease);
}
.rec-tagarrow:hover { color: var(--text); }
/* 没有小类的组：箭头位置放个点，保持左边缘对齐 */
.rec-tagarrow.empty { cursor: default; opacity: .35; }
.rec-tagarrow.empty:hover { color: var(--text-3); }

/* 收起时提示"这里面有几个"，不然收起来完全看不出这组多大 */
.rec-tagcount { font-size: 10.5px; color: var(--text-3); }

/* 二级那一行：缩进到一级文字下面 */
.rec-tagsubs {
  display: flex;
  flex-wrap: wrap;
  gap: 5px;
  align-items: center;
  padding-left: 22px;   /* 和一级的名字左对齐（箭头 16 + 间隙 6） */
}

.rec-tagchip {
  font: inherit;
  padding: 3px 10px;
  border-radius: 20px;
  border: 1px solid var(--line);
  background: var(--surface);
  color: var(--text-2);
  cursor: pointer;
  transition: background .12s var(--ease), border-color .12s var(--ease), color .12s var(--ease);
}
.rec-tagchip:hover { border-color: var(--line-strong, var(--line)); }
.rec-tagchip.on {
  background: var(--brand, #48ab93);
  border-color: var(--brand, #48ab93);
  color: var(--on-brand);
}

/* 一级：大一点、粗一点、有底色 —— 一眼看出这是"组名" */
.rec-tagchip-top {
  font-size: 12.5px;
  font-weight: 600;
  border-color: transparent;
  color: var(--text);
  background: var(--surface-2);
}
.rec-tagchip-top.on { background: var(--brand, #48ab93); color: #fff; }

/* 二级：**小一些、淡一些**（用户明确要求"二级字体要小一些"） */
.rec-tagchip-sub {
  font-size: 11px;
  padding: 2px 9px;
  color: var(--text-2);
}
/* 已选中的二级也要够明显 —— 小字号下光靠颜色不够，再加粗一点 */
.rec-tagchip-sub.on { font-weight: 600; }
.rec-tagchip-sub.on { background: var(--brand, #48ab93); color: #fff; }

/* 一个组里没有二级时的提示 */
.rec-tagnone { font-size: 10.5px; }


/* ---------------------- 导入对话框 ---------------------- */

.imp-body { display: flex; flex-direction: column; gap: 12px; }
.imp-lead { font-size: 12.5px; color: var(--text-2); line-height: 1.6; }
.imp-pick { display: flex; align-items: center; gap: 10px; }
.imp-file {
  font-size: 12px; color: var(--text-3);
  min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.imp-result:empty { display: none; }
.imp-busy, .imp-err { font-size: 12.5px; color: var(--text-2); }
.imp-err { color: #b4483a; }

.imp-preview, .imp-done {
  display: flex; flex-direction: column; gap: 6px;
  padding: 10px 12px;
  border-radius: 10px;
  background: var(--surface-2);
  border: 1px solid var(--line);
}
.imp-row { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; font-size: 12.5px; }
.imp-row .k { color: var(--text-3); flex: 0 0 auto; }
.imp-row b { font-variant-numeric: tabular-nums; text-align: right; min-width: 0; }
.imp-hint { font-size: 11px; color: var(--text-3); line-height: 1.55; margin-top: 2px; }
.imp-note {
  font-size: 11.5px; color: var(--text-3); line-height: 1.6;
  padding-top: 4px; border-top: 1px dashed var(--line);
}
.imp-note b { color: var(--text-2); }

/* ==========================================================================
   记账 · 导入记录与撤回
   ========================================================================== */

.imp-hist { display: flex; flex-direction: column; gap: 10px; }

/* 记录列表那一块的小标题（合并成一个对话框之后加的）——
   上面是"导入"区、下面是"记录"区，得有个东西把两段分开。 */
.imp-hist-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 10px;
  /* 上面那条虚线把它和"导入说明"分开 */
  margin-top: 6px;
  padding-top: 10px;
  border-top: 1px solid var(--line);
  font-size: 12.5px;
  font-weight: 600;
  color: var(--text);
}
.imp-hist-hint { font-size: 10.5px; font-weight: 400; color: var(--text-3); }
/* ==========================================================================
   余额记录（用户 2026-10-03 提的）
   --------------------------------------------------------------------------
   用户原话：「记录我每次的修改记录，什么时间填写，填写了多少，
              就类似于 导入账单那样的UI，下面是清单」
   所以结构照搬账单导入：上面说明 + 各账户概览，下面逐条清单。
   ========================================================================== */
.bal-body { display: flex; flex-direction: column; gap: 10px; }
.bal-lead { font-size: 12.5px; color: var(--text-2); line-height: 1.6; }

/* 上半：各账户当前余额 + 最后一次手填 */
.bal-sum {
  display: flex;
  flex-direction: column;
  gap: 3px;
  padding: 9px 10px;
  border-radius: 9px;
  background: var(--surface-2);
  border: 1px solid var(--line);
}
.bal-sum:empty { display: none; }
.bal-sum-title { font-size: 10.5px; color: var(--text-3); margin-bottom: 3px; }
.bal-sum-row {
  display: flex;
  align-items: baseline;
  gap: 8px;
  font-size: 12px;
  line-height: 1.7;
}
.bal-sum-name { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.bal-sum-cur { flex: 0 0 auto; font-variant-numeric: tabular-nums; font-weight: 600; }
.bal-sum-note { flex: 0 0 auto; font-size: 10.5px; color: var(--text-3); }
/* 手填的和当前值不一样 —— 这正是用户要盯的 */
.bal-sum-note.warn { color: #c07a2a; }

/* 下半：清单 */
.bal-list-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 10px;
  margin-top: 4px;
  padding-top: 9px;
  border-top: 1px solid var(--line);
  font-size: 12.5px;
  font-weight: 600;
}
.bal-list-hint { font-size: 10.5px; font-weight: 400; color: var(--text-3); }
.bal-list { display: flex; flex-direction: column; gap: 7px; max-height: 300px; overflow-y: auto; }
.bal-empty { font-size: 11.5px; color: var(--text-3); line-height: 1.6; padding: 6px 0; }

.bal-row {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 10px;
  padding: 8px 10px;
  border-radius: 9px;
  border: 1px solid var(--line);
}
.bal-main { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: 3px; }
.bal-head { display: flex; align-items: baseline; gap: 7px; }
.bal-name { font-size: 12.5px; font-weight: 600; }
.bal-src {
  font-size: 10px;
  color: var(--text-3);
  border: 1px solid var(--line);
  border-radius: 5px;
  padding: 0 5px;
}
.bal-flow {
  display: flex;
  align-items: baseline;
  gap: 6px;
  font-size: 12px;
  font-variant-numeric: tabular-nums;
}
.bal-from { color: var(--text-3); }
.bal-arrow { color: var(--text-3); font-size: 10px; }
.bal-to { font-weight: 600; }
.bal-delta { font-size: 11px; }
.bal-delta.up { color: #4a8f6a; }
.bal-delta.down { color: #b4483a; }
.bal-note { font-size: 11px; color: var(--text-3); }
.bal-when { flex: 0 0 auto; font-size: 10.5px; color: var(--text-3); white-space: nowrap; }

/* 一条导入记录都没有时的提示 */
.imp-hist-empty {
  font-size: 11.5px;
  color: var(--text-3);
  line-height: 1.6;
  padding: 8px 0;
}

/* 一批一行：左边是信息，右边是撤回按钮 */
.imp-batch {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  padding: 10px 12px;
  border-radius: var(--r-sm, 10px);
  background: var(--surface-2);
  border: 1px solid var(--line);
}
/* 已撤回的压暗 —— 留着当记录，但不再吸引注意 */
.imp-batch.done { opacity: .62; }

.imp-batch-main { flex: 1 1 auto; min-width: 0; }
.imp-batch-name {
  font-size: 12.5px;
  font-weight: 600;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.imp-batch-meta {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  margin-top: 3px;
  font-size: 11px;
  color: var(--text-2);
  font-variant-numeric: tabular-nums;
}
.imp-batch-sub {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-top: 4px;
  font-size: 10.5px;
  color: var(--text-3);
}
.imp-n { font-weight: 600; color: var(--text-2); font-variant-numeric: tabular-nums; }
/* 导入时间 / 数据范围：时间稍重一点，范围稍轻 ——
   用户主要是靠"什么时候"来认哪一批 */
.imp-when { color: var(--text-2); }
.imp-range { color: var(--text-3); }
/* "现存 N 条"要和"导了 N 条"区分开（用户可能手删过一些） */
.imp-alive { color: #a9762a; font-variant-numeric: tabular-nums; }
.imp-books, .imp-accts { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 100%; }
.imp-batch-note {
  margin-top: 5px;
  font-size: 10.5px;
  color: var(--text-3);
  line-height: 1.5;
}

.imp-batch-acts { flex: 0 0 auto; display: flex; align-items: center; }
.imp-undone {
  font-size: 10.5px;
  color: var(--text-3);
  white-space: nowrap;
}

/* 撤回确认框里那个"连账户一起删"的勾选项 */
.imp-opt {
  display: flex;
  align-items: flex-start;
  gap: 7px;
  margin-top: 10px;
  font-size: 12px;
  color: var(--text-2);
  line-height: 1.6;
  cursor: pointer;
}
.imp-opt input { flex: 0 0 auto; margin-top: 2px; }

/* ==========================================================================
   中窄屏（901~1180px）：表格还留着，但已经挤了 —— 换成"两行 + 小字"
   --------------------------------------------------------------------------
   用户 2026-10-03 提的：
     「列宽在极窄的情况下，可以考虑增加行宽+行文字变成2行但字体缩小
       等等方式去做调整」

   这一段就是为它写的。窗口挤到这个区间时，各列都压到了自己的 min，
   备注和标签被切成"三个字加省略号"，根本读不出内容。
   光靠继续压列宽已经没意义了（再压就成竖条），所以换一个方向：
     · 字号整体降半档 → 同样宽度能多放几个字
     · 备注折成**两行**（原来强制 nowrap + 省略号）
     · 标签允许换行成两排
     · 行高跟着从 40px 放到 50px，两行文字才不挤
   900px 以下另有更彻底的"塌成一列卡片"布局（见下面那个断点）。
   ========================================================================== */
@media (max-width: 1180px) and (min-width: 901px) {
  /* 字号降半档 */
  .rec-table .as-thead { font-size: 10px; }
  .rec-row .c-when { font-size: 10.5px; }
  .rec-row .c-acct { font-size: 10.5px; }
  .rec-row .c-amt b { font-size: 12px; }
  .rec-row .rec-sub { font-size: 9.5px; }
  .rec-row .c-note { font-size: 11px; }

  /* 备注折两行：原来 nowrap + 省略号，窄屏下只剩"三个字…"。
     用 -webkit-line-clamp 限两行，超出的才省略 —— 至少能读全大半句。 */
  .rec-row .c-note { flex-wrap: nowrap; align-items: flex-start; }
  .rec-note {
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    white-space: normal;
    overflow: hidden;
    text-overflow: clip;
    line-height: 1.32;
  }
  /* 标签也允许折成两排 */
  .rec-row .c-tags .rec-tags { flex-wrap: wrap; row-gap: 2px; }
  /* 行高放宽 —— 两行文字配 40px 会贴在一起 */
  .rec-table .rec-row { min-height: 50px; align-items: center; }
}

/* 窄屏：两张表都塌成一列（和订阅/资产同一个断点） */
@media (max-width: 900px) {
  .rec-table .as-thead { display: none; }
  .rec-table .as-row {
    grid-template-columns: minmax(0, 1fr) auto;
    /* 【备注和标签拆成两列之后，窄屏的排布也要跟着改】
       原来只有 note 一个区；现在 tags 单独一行。
       放一行的话标签会被挤到看不见（用户提过"串在一起"）。

       【2026-10-08 加了「报销 / 账本」两个区】
       不写进 grid-template-areas 的话，它们会掉进**隐式行**
       （浏览器自动加一行），排布就乱了 —— 而且不会报错。
       这两样在窄屏并排放一行：都是短标签，一行放得下。 */
    grid-template-areas:
      'cat  amt'
      'note note'
      'tags tags'
      'reimb book'
      'when acct';
    gap: 6px;
    border-color: var(--line);
    background: var(--surface);
  }
  .rec-table .c-cat { grid-area: cat; }
  .rec-table .c-amt { grid-area: amt; }
  .rec-table .c-note { grid-area: note; }
  .rec-table .c-tags { grid-area: tags; }
  .rec-table .c-reimb { grid-area: reimb; }
  .rec-table .c-book { grid-area: book; }
  .rec-table .c-when { grid-area: when; }
  .rec-table .c-acct { grid-area: acct; text-align: right; }
  .rec-table .c-acts { display: none; }
  /* 窄屏每行内容变多了，最小高度得放宽，不然会挤 */
  .rec-table .rec-row { min-height: 0; }
  /* 窄屏不立竖分隔线（列都塌了，线只会更乱） */
  .rec-row .c-cat::before,
  .rec-row .c-note::before,
  .rec-row .c-tags::before,
  .rec-row .c-acct::before { content: none; }
  .rec-form-row { grid-template-columns: 1fr; }
}

/* ==========================================================================
   记账 · 账本 / 分类 / 标签 管理（需求一~三）
   ========================================================================== */

.mgr { display: flex; flex-direction: column; gap: 12px; }
/* 三个标签页下面的内容区。给个最小高度：切到"分类"和"标签"时
   内容高度差很多，不给的话弹窗会一跳一跳。 */
.mgr-body { min-height: 220px; }

/* 三个标签页（分类 / 标签 / 账本） */
.mgr-tabs { display: flex; gap: 6px; border-bottom: 1px solid var(--line); padding-bottom: 8px; }
.mgr-tab {
  font: inherit;
  font-size: 12.5px;
  padding: 4px 12px;
  border-radius: 8px;
  border: 1px solid transparent;
  background: transparent;
  color: var(--text-2);
  cursor: pointer;
  transition: background .12s var(--ease), color .12s var(--ease);
}
.mgr-tab:hover { background: var(--surface-2); }
.mgr-tab.on {
  background: var(--brand-soft, rgba(107, 122, 90, .12));
  border-color: var(--brand, #48ab93);
  color: var(--text);
  font-weight: 600;
}

.mgr-pane { display: flex; flex-direction: column; gap: 10px; }
.mgr-hint { font-size: 11.5px; color: var(--text-3); line-height: 1.6; }
.mgr-hint-inline { font-size: 11px; color: var(--text-3); flex: 1 1 auto; }

.mgr-list { display: flex; flex-direction: column; }

/* 一行：图标/颜色 + 名字输入 + 计数 + 操作 */
.mgr-row {
  display: flex;
  align-items: center;
  gap: 7px;
  padding: 5px 6px;
  border-radius: 8px;
  position: relative;
}
.mgr-row:hover { background: var(--surface-2); }
.mgr-row .wcfg-input { flex: 1 1 auto; min-width: 0; }
.mgr-row.is-default { background: var(--brand-soft, rgba(107, 122, 90, .08)); }

/* 一级分类那行：加粗一点，和二级区分开 */
.mgr-row.mgr-top { background: var(--surface-2); }
.mgr-row.mgr-top .wcfg-input { font-weight: 600; }

.mgr-count {
  flex: 0 0 auto;
  font-size: 10.5px;
  color: var(--text-3);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.mgr-tag {
  flex: 0 0 auto;
  font-size: 10px;
  color: var(--brand, #48ab93);
  border: 1px solid var(--brand-soft, rgba(107, 122, 90, .3));
  border-radius: 20px;
  padding: 0 6px;
  line-height: 15px;
  white-space: nowrap;
}
.mgr-acts { flex: 0 0 auto; display: flex; gap: 4px; }

/* 二级分类：左边缩进一根竖线，看着是"挂在上面那个下面" */
.mgr-subs {
  display: flex;
  flex-direction: column;
  margin: 0 0 6px 22px;
  padding-left: 10px;
  border-left: 2px solid var(--line);
}
.mgr-sub { display: flex; align-items: center; gap: 7px; padding: 2px 4px; border-radius: 6px; }
.mgr-sub:hover { background: var(--surface-2); }
.mgr-sub .wcfg-input { flex: 1 1 auto; min-width: 0; font-size: 12.5px; }
.mgr-subadd { opacity: .55; }
.mgr-subadd:hover, .mgr-subadd:focus-within { opacity: 1; }
.mgr-inline { font-size: 12px; padding: 4px 8px !important; }

/* 图标/颜色那种很窄的输入框 */
.bk-icon, .cat-icon {
  flex: 0 0 40px !important;
  min-width: 40px !important;
  text-align: center;
  padding: 5px 2px !important;
}

/* ==========================================================================
   记账 · 图标选择器（用户提的"要有预设图标"）
   --------------------------------------------------------------------------
   账本 / 分类 / 账户三处共用（见 app/scripts/views/ledger-icons.js）。
   原来都是一个纯文本框要用户敲 emoji —— 手机上根本敲不出 🅰 这种字。
   ========================================================================== */

/* 列表里那颗"当前图标"按钮（点开选择器） */
.bk-icon-btn, .cat-icon-btn, .acc-icon-btn {
  flex: 0 0 34px;
  width: 34px; height: 34px;
  display: flex; align-items: center; justify-content: center;
  font-size: 17px;
  line-height: 1;
  border-radius: 9px;
  border: 1px solid var(--line);
  background: var(--surface);
  cursor: pointer;
  transition: border-color .12s var(--ease), background .12s var(--ease);
  padding: 0;
}
.bk-icon-btn:hover, .cat-icon-btn:hover, .acc-icon-btn:hover {
  border-color: var(--brand, #48ab93);
  background: var(--surface-2);
}

/* 选择器本体 */
.icon-pick { display: flex; flex-direction: column; gap: 10px; }

/* 顶部：当前选中的大图 + 自定义输入 */
.icon-pick-cur {
  flex: 0 0 52px;
  width: 52px; height: 52px;
  display: flex; align-items: center; justify-content: center;
  font-size: 26px;
  line-height: 1;
  border-radius: 12px;
  border: 1px dashed var(--line);
  background: var(--surface-2);
  cursor: pointer;
  padding: 0;
  transition: border-color .12s var(--ease);
}
.icon-pick-cur:hover { border-color: var(--brand, #48ab93); border-style: solid; }
.icon-pick-inp { max-width: 140px; text-align: center; }

/* 一行图标格子 */
.icon-pick-row {
  display: flex;
  flex-wrap: wrap;
  gap: 3px;
}
.icon-pick-cell {
  width: 30px; height: 30px;
  display: flex; align-items: center; justify-content: center;
  font-size: 17px;
  line-height: 1;
  border-radius: 7px;
  border: 1px solid transparent;
  background: transparent;
  cursor: pointer;
  padding: 0;
  transition: background .1s var(--ease), border-color .1s var(--ease);
}
.icon-pick-cell:hover { background: var(--surface-2); }
/* 选中的那个要明显 —— 一圈实线 + 淡底 */
.icon-pick-cell.on {
  border-color: var(--brand, #48ab93);
  background: var(--brand-soft, rgba(107, 122, 90, .16));
}

/* 「更多图标」折叠区（默认收着，省地方） */
.icon-pick-more { margin-top: 2px; }
.icon-pick-more > summary {
  font-size: 11.5px;
  color: var(--text-3);
  cursor: pointer;
  padding: 4px 0;
  user-select: none;
}
.icon-pick-more > summary:hover { color: var(--text-2); }
.icon-pick-group { margin: 8px 0 4px; }
.icon-pick-gname {
  font-size: 10.5px;
  color: var(--text-3);
  margin-bottom: 4px;
}

/* ==========================================================================
   图标选择器 · 品牌分页（2026-10-03 加）
   --------------------------------------------------------------------------
   用户要"支付宝/微信/京东/拼多多/抖音/美团"这些真 logo，
   后来又加了银行。现在库里 91 个品牌图标（见 brand-icons.js）。
   ========================================================================== */

/* 两个分页：表情符号 / 品牌图标 */
.icon-pick-tabs {
  display: flex;
  gap: 4px;
  border-bottom: 1px solid var(--line);
  padding-bottom: 7px;
}
.icon-pick-tab {
  font: inherit;
  font-size: 12px;
  padding: 4px 12px;
  border-radius: 8px 8px 0 0;
  border: 1px solid transparent;
  border-bottom: none;
  background: transparent;
  color: var(--text-2);
  cursor: pointer;
  transition: background .12s var(--ease), color .12s var(--ease);
}
.icon-pick-tab:hover { background: var(--surface-2); }
.icon-pick-tab.on {
  background: var(--brand-soft, rgba(107, 122, 90, .12));
  border-color: var(--brand, #48ab93);
  color: var(--text);
  font-weight: 600;
}

.icon-pane { display: flex; flex-direction: column; gap: 8px; }

/* 品牌那一块 */
.icon-pick-brands { display: flex; flex-direction: column; gap: 6px; }
.icon-pick-bcell { display: flex; align-items: center; justify-content: center; }
.icon-pick-bcell svg { display: block; }
.icon-pick-brow {
  display: flex;
  flex-wrap: wrap;
  gap: 3px;
  /* 【91 个品牌要能滚】
     全铺开会把弹窗撑得很高。给一个最大高度自己滚，
     弹窗高度就稳定了（不然每次开位置都在跳）。 */
  max-height: 168px;
  overflow-y: auto;
  scrollbar-width: thin;
  align-content: flex-start;
}
.icon-pick-search { font-size: 12px; }

/* 显示在列表/流水行里的品牌图标：垂直居中对齐文字 */
.brand-ico {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  vertical-align: -2px;
}
/* 流水行的分类图标 */
.rec-cat-ico {
  display: inline-flex;
  align-items: center;
  flex: 0 0 auto;
}

/* ==========================================================================
   账户图标：加一个圆角矩形底
   --------------------------------------------------------------------------
   用户 2026-10-03 提的：
     「账户的图标 太单调了，能不能加个圆角矩形框一下，
       有些图标和背景融为一体了」

   【为什么真的会"融为一体"】
   品牌图标（SVG）是用 `currentColor` 画的、颜色取**品牌色**。
   品牌色里有一批是**深色**：工商银行 #C7000B 暗红、
   苹果/耐克/荣耀/Steam #000000、Xbox #107C10…
   深色画在浅底上还行，可一旦行本身有了底色
   （悬停、或者"不计入总资产"那种压暗的行），边界就糊掉了。
   emoji 反而没这个问题 —— 它自带颜色和描边。

   【为什么是"底 + 细边"而不是只加边框】
   只加边框的话，深色图标仍然直接坐在行底色上，只是多了一圈线；
   垫一层**浅底**之后，不管品牌色多深、行底色是什么，
   图标永远有自己的浅色画布 —— 这才叫真的不会糊。

   【尺寸】22×22 方框配 20px 图标（留 1px 呼吸），圆角 7px。
   和账户编辑弹窗里那个 34×34 的按钮同一套语言
   （那边 border-radius: 9px，按比例缩过来就是 7px）。 */
.acc-ico {
  flex: 0 0 auto;
  width: 22px;
  height: 22px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: 7px;
  /* 【底色用 --surface 而不是透明】
     行悬停时行底色变成 --surface-2，而 --surface 比它亮 ——
     图标块会"浮"一下，正好让人看清它是个独立的块。 */
  background: var(--surface);
  border: 1px solid var(--line);
  line-height: 1;
  overflow: hidden;
}
.acc-ico > *, .acc-ico svg { display: block; }
/* 【压暗的行里，图标块淡得比整行少】
   整行 opacity .62；这里给 .8 ——
   本来就看不清的深色图标，跟着压到 .62 就更看不见了。 */
.acc-row.off .acc-ico { opacity: .8; }

.tag-color {
  flex: 0 0 26px !important;
  min-width: 26px !important;
  height: 26px;
  padding: 0 !important;
  border-radius: 6px;
  cursor: pointer;
}

.mgr-add { display: flex; align-items: center; gap: 7px; padding-top: 4px; border-top: 1px dashed var(--line); }
.mgr-add .wcfg-input { flex: 1 1 auto; min-width: 0; }
.mgr-add > button { flex: 0 0 auto; white-space: nowrap; }

.mgr-group-title {
  font-size: 11.5px;
  font-weight: 600;
  color: var(--text-2);
  padding: 8px 6px 2px;
}

/* 「智能添加」那颗小按钮：有规则时点亮 */
.mgr-rule {
  flex: 0 0 auto;
  font: inherit;
  font-size: 10.5px;
  padding: 2px 7px;
  border-radius: 20px;
  border: 1px solid var(--line);
  background: var(--surface);
  color: var(--text-3);
  cursor: pointer;
  white-space: nowrap;
}
.mgr-rule:hover { border-color: var(--brand, #48ab93); color: var(--text-2); }
.mgr-rule.on {
  background: var(--brand-soft, rgba(107, 122, 90, .14));
  border-color: var(--brand, #48ab93);
  color: var(--brand, #48ab93);
  font-weight: 600;
}

/* 空状态 + 套用模板 */
.mgr-empty {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 8px;
  padding: 12px;
  border-radius: 10px;
  background: var(--surface-2);
  border: 1px dashed var(--line);
  font-size: 12px;
  color: var(--text-2);
}

/* 分类树的支出/收入切换 */
.mgr-kind { flex: 0 0 auto; }

/* 规则编辑器 */
.rule-list { display: flex; flex-direction: column; gap: 7px; }
.rule-row { display: flex; align-items: center; gap: 6px; }
.rule-row select { flex: 0 0 auto; max-width: 110px; }
.rule-row input.wcfg-input { flex: 1 1 auto; min-width: 0; }

/* ==========================================================================
   记账 · 账户 + 资产（需求四 / 八）
   ========================================================================== */

/* 负债那张卡用暖色 —— 「资产 / 负债 / 净值」三个数要一眼分得开，
   不然用户看不出净值是不是已经减过债 */
.lg-stat.acc-debt .ls-value { color: #b4483a; }

.acc-group { display: flex; flex-direction: column; gap: 4px; margin-top: 4px; }
.acc-group-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 10px;
  padding: 10px 8px 2px;
  font-size: 11.5px;
  color: var(--text-2);
}
.acc-group-name { font-weight: 600; }
/* 【子类名 —— 用户 2026-10-08「我看账户也没有报销账户分类？」】
   债务下面有三类（报销账户 / 应付款 / 应收款），
   一级标题只写"债务"的话用户找不到"报销账户"。
   所以后面跟一段小一号、浅一点的字：「债务 · 报销账户」。
   浅色是故意的：它是补充说明，不该和一级名抢注意力。 */
.acc-sub-name { font-weight: 400; color: var(--text-3); font-size: 11.5px; }
.acc-group-sum { color: var(--text-3); font-variant-numeric: tabular-nums; }

/* 一行账户：图标 + 名称/副信息 + 金额 + 操作 */
.acc-row {
  display: grid;
  grid-template-columns: 38px minmax(0, 1fr) auto 66px;
  align-items: center;
  gap: 10px;
  padding: 8px 10px;
  border-radius: var(--r-sm, 10px);
  border: 1px solid transparent;
  position: relative;
}
.acc-row:hover { background: var(--surface-2); border-color: var(--line); }
/* 不计入总资产的压暗 —— 但**不能太淡**，用户还得能看清它有多少钱 */
.acc-row.off { opacity: .62; }
.acc-row.off:hover { opacity: .85; }
/* 行间虚线（和流水/订阅那两张表同一个做法） */
.acc-row + .acc-row::before {
  content: '';
  position: absolute;
  left: 10px; right: 10px; top: -2px;
  border-top: 1px dashed var(--line);
  pointer-events: none;
}
.acc-row:hover::before, .acc-row:hover + .acc-row::before { opacity: 0; }

.acc-icon {
  width: 38px; height: 38px;
  display: flex; align-items: center; justify-content: center;
  font-size: 19px;
  border-radius: 10px;
  background: var(--surface-2);
}
.acc-main { min-width: 0; }
.acc-name {
  font-size: 13px;
  font-weight: 600;
  display: flex;
  align-items: baseline;
  gap: 6px;
  min-width: 0;
}
.acc-short { font-size: 10.5px; color: var(--text-3); font-weight: 400; }
.acc-tag {
  font-size: 9.5px;
  color: var(--text-3);
  border: 1px solid var(--line);
  border-radius: 20px;
  padding: 0 5px;
  font-weight: 400;
  white-space: nowrap;
}
.acc-sub {
  font-size: 10.5px;
  color: var(--text-3);
  margin-top: 2px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.acc-amt { text-align: right; white-space: nowrap; }
.acc-amt b { display: block; font-size: 14px; font-weight: 600; font-variant-numeric: tabular-nums; }
.acc-amt span { font-size: 10px; color: var(--text-3); }
/* 负债红一点，和资产区分开 */
.acc-amt.debt b { color: #b4483a; }

/* ---------- 报销账户（2026-10-08）----------
   用户说「报销账户 应该也属于"账户"的范畴」。
   它的余额是**从流水算出来的**（待报销之和），不是用户填的，
   所以视觉上要和别的账户区分开、并且说明来源。 */

/* "待报销"三个字用品牌色 —— 它既不是"余额"（那是你手里的钱），
   也不是"欠款"（那是你欠别人的）。它是**别人欠你的**，
   第三类，值得单独一个颜色。 */
.acc-amt .acc-computed { color: var(--brand-deep); }

/* 编辑表单里"不用填余额"的说明 */
.acc-reimb-note {
  margin: 2px 0 10px;
  padding: 9px 11px;
  border-radius: var(--r-sm, 8px);
  background: var(--brand-soft);
  color: var(--brand-deep);
  font-size: 11.5px;
  line-height: 1.75;
}

/* 记账页：报销账户还没登记时的提示 */
.rec-reimb-nownote {
  margin-top: 6px;
  padding: 7px 9px;
  border-radius: var(--r-xs, 6px);
  background: var(--amber-soft);
  color: var(--amber);
  font-size: 11px;
  line-height: 1.7;
}
.rec-reimb-nownote:empty { display: none; }
.acc-acts { display: flex; gap: 4px; justify-content: flex-end; }

/* 未登记的账户名 */
.acc-unreg {
  margin-top: 14px;
  padding-top: 10px;
  border-top: 1px dashed var(--line);
}
.acc-unreg-title { font-size: 11.5px; color: var(--text-2); margin-bottom: 6px; }
.acc-unreg-list { display: flex; flex-wrap: wrap; gap: 6px; }
.acc-unreg-chip {
  font: inherit;
  font-size: 11px;
  padding: 3px 9px;
  border-radius: 20px;
  border: 1px dashed var(--line);
  background: var(--surface);
  color: var(--text-2);
  cursor: pointer;
  transition: border-color .12s var(--ease), color .12s var(--ease);
}
.acc-unreg-chip:hover { border-color: var(--brand, #48ab93); color: var(--text); border-style: solid; }
.acc-unreg-hint { font-size: 10.5px; color: var(--text-3); margin-top: 6px; }

.acc-empty-acts { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 6px; }

/* ---------------------- 账户编辑器 ---------------------- */

.acc-form { display: flex; flex-direction: column; gap: 12px; }
.acc-form-row { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }
.acc-form .field { min-width: 0; }
.acc-icon-inp { text-align: center; }
.acc-extra { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }
.acc-check {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 12px;
  color: var(--text-2);
  cursor: pointer;
  padding-top: 2px;
}
.acc-check input { flex: 0 0 auto; }

/* 预设快捷名（需求四每类账户给的预设） */
.acc-presets { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; }
.acc-preset-label { font-size: 11px; color: var(--text-3); }
.acc-preset {
  font: inherit;
  font-size: 11px;
  padding: 2px 9px;
  border-radius: 20px;
  border: 1px solid var(--line);
  background: var(--surface);
  color: var(--text-2);
  cursor: pointer;
  transition: background .12s var(--ease), border-color .12s var(--ease);
}
.acc-preset:hover { background: var(--surface-2); border-color: var(--brand, #48ab93); color: var(--text); }

/* 窄屏：账户行和表单都塌成一列 */
@media (max-width: 700px) {
  .acc-row { grid-template-columns: 34px minmax(0, 1fr) auto; grid-template-areas: 'icon main amt' 'acts acts acts'; }
  .acc-icon { grid-area: icon; width: 34px; height: 34px; font-size: 17px; }
  .acc-main { grid-area: main; }
  .acc-amt { grid-area: amt; }
  .acc-acts { grid-area: acts; }
  .acc-form-row, .acc-extra { grid-template-columns: 1fr; }
}

/* ==========================================================================
   记账 · 理财（需求五）
   ========================================================================== */

/* 盈亏那两张卡：赚了绿、亏了红。
   理财页用户第一眼就是找"赚了没有"，所以它是整页最显眼的。 */
.lg-stat.fund-pl .ls-value { font-variant-numeric: tabular-nums; }
.lg-stat.fund-pl.up .ls-value { color: #2f7d4f; }
.lg-stat.fund-pl.down .ls-value { color: #b4483a; }
.lg-stat.fund-pl.up .ls-hint { color: #2f7d4f; }
.lg-stat.fund-pl.down .ls-hint { color: #b4483a; }

/* 表：名称 | 份额 | 净值 | 成本 | 市值 | 盈亏 | 操作 */
.fund-table { display: flex; flex-direction: column; }
.fund-thead, .fund-row {
  display: grid;
  grid-template-columns: minmax(150px, 1.6fr) 92px 96px 100px 106px 116px 152px;
  align-items: center;
  gap: 8px;
}
.fund-thead {
  padding: 8px 10px;
  font-size: 10.5px;
  color: var(--text-3);
  text-transform: none;
}
.fund-row {
  padding: 8px 10px;
  border-radius: var(--r-sm, 10px);
  position: relative;
}
.fund-row:hover { background: var(--surface-2); }
/* 行间虚线（和流水/账户同一做法） */
.fund-row + .fund-row::before {
  content: '';
  position: absolute;
  left: 10px; right: 10px; top: -2px;
  border-top: 1px dashed var(--line);
  pointer-events: none;
}
.fund-row:hover::before, .fund-row:hover + .fund-row::before { opacity: 0; }

.fund-row .c-name { display: flex; align-items: center; gap: 9px; min-width: 0; }
.fund-icon {
  width: 32px; height: 32px;
  flex: 0 0 32px;
  display: flex; align-items: center; justify-content: center;
  font-size: 16px;
  border-radius: 9px;
  background: var(--surface-2);
}
.fund-name-box { min-width: 0; }
.fund-name {
  font-size: 12.5px; font-weight: 600;
  display: flex; align-items: baseline; gap: 5px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.fund-code { font-size: 10px; color: var(--text-3); font-weight: 400; }
.fund-sub {
  font-size: 10px; color: var(--text-3); margin-top: 2px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
/* 数字列右对齐 + 等宽数字（不然各行小数点对不齐，扫起来很累） */
.fund-num { text-align: right; font-variant-numeric: tabular-nums; font-size: 12.5px; white-space: nowrap; }
.fund-row .c-pl { display: flex; flex-direction: column; align-items: flex-end; line-height: 1.25; }
.fund-row .c-pl b { font-size: 13px; font-weight: 600; }
.fund-row .c-pl i { font-size: 10px; font-style: normal; opacity: .85; }
.fund-row .c-pl.up { color: #2f7d4f; }
.fund-row .c-pl.down { color: #b4483a; }
.fund-row .c-acts { display: flex; gap: 4px; justify-content: flex-end; }

/* 持仓编辑器里的实时预览 —— 用户填完立刻知道市值/盈亏对不对 */
.fund-preview {
  font-size: 11.5px;
  color: var(--text-2);
  background: var(--surface-2);
  border: 1px dashed var(--line);
  border-radius: 9px;
  padding: 8px 10px;
  line-height: 1.6;
}

/* 买卖弹窗 */
.fund-actions { display: flex; gap: 6px; }
.fund-action {
  font: inherit;
  font-size: 12.5px;
  padding: 5px 16px;
  border-radius: 9px;
  border: 1px solid var(--line);
  background: var(--surface);
  color: var(--text-2);
  cursor: pointer;
  transition: background .12s var(--ease), border-color .12s var(--ease), color .12s var(--ease);
}
.fund-action:hover { background: var(--surface-2); }
.fund-action.on {
  background: var(--brand-soft, rgba(107, 122, 90, .14));
  border-color: var(--brand, #48ab93);
  color: var(--text);
  font-weight: 600;
}
/* 买卖实时算式：份额×净值、扣款/到账、持有变化 */
.fund-calc {
  font-size: 11.5px;
  color: var(--text-2);
  background: var(--surface-2);
  border-radius: 9px;
  padding: 8px 10px;
  line-height: 1.6;
  font-variant-numeric: tabular-nums;
}
/* 超过持有份额时变红 —— 提交时服务端也会拦，但先提示更友好 */
.fund-calc.bad { color: #b4483a; background: rgba(180, 72, 58, .08); }

/* 交易记录 */
.fund-history { display: flex; flex-direction: column; }
.fund-hrow {
  display: grid;
  grid-template-columns: 46px 84px minmax(0, 1fr) auto 30px;
  align-items: center;
  gap: 8px;
  padding: 6px 4px;
  font-size: 12px;
  border-radius: 8px;
}
.fund-hrow:hover { background: var(--surface-2); }
.fund-hact {
  font-size: 10.5px;
  text-align: center;
  border-radius: 20px;
  padding: 1px 0;
  background: var(--surface-2);
  color: var(--text-2);
}
.fund-hact.sell { color: #b4483a; }
.fund-hact.div { color: #2f7d4f; }
.fund-hdate { color: var(--text-3); font-size: 11px; font-variant-numeric: tabular-nums; }
.fund-hnum { color: var(--text-2); font-variant-numeric: tabular-nums; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.fund-hamt { font-variant-numeric: tabular-nums; white-space: nowrap; }

/* 窄屏：理财表塌成一列 */
@media (max-width: 900px) {
  .fund-thead { display: none; }
  .fund-row {
    grid-template-columns: minmax(0, 1fr) auto;
    grid-template-areas:
      'name market'
      'nums nums'
      'pl   acts';
    gap: 6px;
    border: 1px solid var(--line);
  }
  .fund-row .c-name { grid-area: name; }
  .fund-row .c-market { grid-area: market; }
  /* 【窄屏把份额/净值/成本藏起来，但信息不能丢】
     这三列在窄屏挤不下，可"多少份、净值多少"是理财的关键信息。
     所以不删 DOM、只用 CSS 藏起来，再在下面补一行小字汇总
     （内容由 JS 写进 data-nums，见 ledger-funds.js 的 fundRow 注释）。 */
  .fund-row .c-shares, .fund-row .c-nav, .fund-row .c-cost { display: none; }
  .fund-row .c-pl { grid-area: pl; align-items: flex-start; }
  .fund-row .c-acts { grid-area: acts; }
  .fund-row::after {
    content: attr(data-nums);
    grid-area: nums;
    font-size: 10.5px;
    color: var(--text-3);
    font-variant-numeric: tabular-nums;
  }
}

/* ==========================================================================
   记账 · 预算（需求七）
   ========================================================================== */

/* 超支用暖红。整页只有"超"的地方是红的，扫一眼就能找到问题分类。 */
.lg-stat.bud-over .ls-value { color: #b4483a; }

.bud-month { display: flex; align-items: center; gap: 6px; }
.bud-month-label {
  font-size: 13px;
  font-weight: 600;
  min-width: 92px;
  text-align: center;
  font-variant-numeric: tabular-nums;
}

.bud-list { display: flex; flex-direction: column; }

.bud-row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 104px 62px;
  align-items: center;
  gap: 12px;
  padding: 10px;
  border-radius: var(--r-sm, 10px);
  position: relative;
}
.bud-row:hover { background: var(--surface-2); }
.bud-row + .bud-row::before {
  content: '';
  position: absolute;
  left: 10px; right: 10px; top: -2px;
  border-top: 1px dashed var(--line);
  pointer-events: none;
}
.bud-row:hover::before, .bud-row:hover + .bud-row::before { opacity: 0; }

.bud-main { min-width: 0; }
.bud-head { display: flex; align-items: center; gap: 6px; min-width: 0; }
.bud-cat {
  font-size: 12.5px;
  font-weight: 600;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.bud-tag {
  flex: 0 0 auto;
  font-size: 9.5px;
  border-radius: 20px;
  padding: 0 6px;
  line-height: 15px;
  border: 1px solid var(--line);
  color: var(--text-3);
  white-space: nowrap;
}
/* "没设预算"和"超支"是两种要提醒的状态，颜色分开 */
.bud-tag.warn { color: #a9762a; border-color: rgba(169, 118, 42, .35); }
.bud-tag.over { color: #b4483a; border-color: rgba(180, 72, 58, .4); background: rgba(180, 72, 58, .07); }

/* 进度条：超了整根变红 */
.bud-bar {
  height: 5px;
  margin: 7px 0 5px;
  border-radius: 4px;
  background: var(--surface-2);
  overflow: hidden;
}
.bud-bar > i {
  display: block;
  height: 100%;
  border-radius: 4px;
  background: var(--brand, #48ab93);
  transition: width .18s var(--ease);
}
/* 【条形封顶，数字不封顶】
   超支时条铺满 100% 就够了（再宽的也看不出多超了多少），
   但右边那个"超 ¥500"和上面的"用了 150%"是照实显示的 ——
   封的只是视觉，不是事实。 */
.bud-row.over .bud-bar > i { background: #b4483a; }

.bud-nums {
  display: flex;
  gap: 8px;
  font-size: 10.5px;
  color: var(--text-3);
  font-variant-numeric: tabular-nums;
}

.bud-right { text-align: right; }
.bud-left {
  font-size: 12.5px;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.bud-left.over { color: #b4483a; }
.bud-left.muted { color: var(--text-3); font-weight: 400; }

.bud-acts { display: flex; gap: 4px; justify-content: flex-end; }

.bud-hint {
  margin-top: 12px;
  padding-top: 10px;
  border-top: 1px dashed var(--line);
  font-size: 11px;
  color: var(--text-2);
  line-height: 1.6;
}
.bud-hint.muted { border-top: none; margin-top: 4px; padding-top: 0; color: var(--text-3); }

/* 窄屏：预算行塌成一列 */
@media (max-width: 700px) {
  .bud-row {
    grid-template-columns: minmax(0, 1fr) auto;
    grid-template-areas: 'main right' 'acts acts';
    gap: 6px;
  }
  .bud-main { grid-area: main; }
  .bud-right { grid-area: right; }
  .bud-acts { grid-area: acts; }
  .bud-nums { flex-wrap: wrap; }
}

/* ==========================================================================
   记账 · 统计（需求九）
   ========================================================================== */

/* 日常 / 月 / 年 三个粒度 */
.stat-grains { display: flex; gap: 6px; }
.stat-grain {
  font: inherit;
  font-size: 12.5px;
  padding: 4px 14px;
  border-radius: 9px;
  border: 1px solid var(--line);
  background: var(--surface);
  color: var(--text-2);
  cursor: pointer;
  transition: background .12s var(--ease), border-color .12s var(--ease), color .12s var(--ease);
}
.stat-grain:hover { background: var(--surface-2); }
.stat-grain.on {
  background: var(--brand-soft, rgba(107, 122, 90, .14));
  border-color: var(--brand, #48ab93);
  color: var(--text);
  font-weight: 600;
}

.stat-nav { display: flex; align-items: center; gap: 6px; }
.stat-key {
  font-size: 12.5px;
  font-weight: 600;
  min-width: 108px;
  text-align: center;
  font-variant-numeric: tabular-nums;
}
/* 【点得开的那个日期 —— 用户 2026-10-03 提的】
   「日常 月 年 都只能左右变动日期，能不能点击日期后出现一个日历表」
   同一个 .stat-key 的尺寸，只是变成按钮、加个下拉小箭头。
   (用同一套字号和 min-width，所以从 <span> 换成 <button> 之后
    布局一点没动 —— 这点很重要，否则两边箭头的相对位置会跳。) */
.stat-key-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 4px;
  padding: 3px 8px;
  border: 1px solid transparent;
  border-radius: var(--r-sm);
  background: transparent;
  color: inherit;
  font: inherit;
  cursor: pointer;
  transition: background var(--dur) var(--ease), border-color var(--dur) var(--ease);
}
.stat-key-btn:hover { background: var(--surface-2); border-color: var(--line); }
.stat-key-caret { font-size: 9px; opacity: .55; }

/* ==========================================================================
   「直接跳」面板 —— 点日期弹出来的日历
   --------------------------------------------------------------------------
   挂 body 上、fixed 定位（不受父级 overflow 裁剪），
   和右键菜单一个套路。背板是透明的，点它关掉。
   ========================================================================== */
.period-pop-back {
  position: fixed;
  inset: 0;
  z-index: 60;
}
.period-pop {
  position: fixed;
  z-index: 61;
  width: 246px;
  padding: 10px;
  border-radius: var(--r-md);
  background: var(--surface);
  border: 1px solid var(--line);
  box-shadow: var(--shadow-lg);
}
.period-head {
  display: flex;
  align-items: center;
  gap: 4px;
  margin-bottom: 8px;
}
.period-title {
  flex: 1;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 5px;
  padding: 4px 6px;
  border: 0;
  border-radius: var(--r-xs);
  background: transparent;
  color: var(--text);
  font-size: 12.5px;
  font-weight: 600;
  cursor: pointer;
  font-variant-numeric: tabular-nums;
}
.period-title:hover { background: var(--surface-2); }
.period-up { font-size: 8px; opacity: .5; }
.period-arrow {
  flex: none;
  width: 24px;
  height: 24px;
  border: 1px solid var(--line);
  border-radius: var(--r-xs);
  background: var(--surface);
  color: var(--text-2);
  cursor: pointer;
  line-height: 1;
  font-size: 14px;
}
.period-arrow:hover { background: var(--surface-2); color: var(--text); }

.period-week,
.period-grid {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  gap: 2px;
}
.period-week {
  margin-bottom: 3px;
  font-size: 10px;
  color: var(--text-3);
  text-align: center;
}
.period-grid { row-gap: 2px; }
.period-pad { display: block; }
.period-day {
  height: 28px;
  border: 0;
  border-radius: var(--r-xs);
  background: transparent;
  color: var(--text-2);
  font-size: 11.5px;
  cursor: pointer;
  font-variant-numeric: tabular-nums;
}
.period-day:hover { background: var(--surface-2); color: var(--text); }
/* 有流水的日子加粗 —— 一眼看出哪几天有东西 */
.period-day.has { color: var(--text); font-weight: 600; }
/* 今天：底下一个点（不用描边，否则和"选中"分不清） */
.period-day.today { box-shadow: inset 0 -2px 0 var(--brand); }
.period-day.on {
  background: var(--brand);
  color: var(--on-brand);
  font-weight: 700;
}

.period-grid-months,
.period-grid-years {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 4px;
}
.period-month,
.period-year {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 1px;
  height: 40px;
  border: 1px solid transparent;
  border-radius: var(--r-sm);
  background: transparent;
  color: var(--text-2);
  font-size: 11.5px;
  cursor: pointer;
  font-variant-numeric: tabular-nums;
}
.period-month:hover,
.period-year:hover { background: var(--surface-2); color: var(--text); }
/* 没有流水的月份/年份压淡 —— 仍然可以点（也许正是想看"确实是 0"） */
.period-month.empty,
.period-year.empty { opacity: .45; }
.period-month.has,
.period-year.has { color: var(--text); font-weight: 600; }
.period-month.on,
.period-year.on {
  background: var(--brand);
  border-color: var(--brand);
  color: var(--on-brand);
  font-weight: 700;
  opacity: 1;
}
.period-mn { font-size: 9px; opacity: .7; font-weight: 400; }
.period-foot-tip {
  margin-top: 7px;
  font-size: 10px;
  color: var(--text-3);
  text-align: center;
}


/* ==========================================================================
   统计页：两栏网格（2026-10-06）
   --------------------------------------------------------------------------
   用户原话：
     「日报表 占了太多的空间，导致大规模空白，可以作为半页面，
       做成组件，标签占比、支出组成之类的也可以作为半页面」

   改之前量到的实情（1500px 视口）：
     收支热力图 477 · 走势 278 · **日报表 1024** · 分类构成 238 · 标签占比 286
     五张卡纵向摞起来 **2589px**，每张都满宽 1248px。
     短卡（238、286）右边空掉一大片 —— 就是"大规模空白"。

   改法两条：
     1. 容器改成两栏网格；分类构成 / 标签占比各占一栏，并排
     2. 日报表默认只列"有流水"的天（那才是 1024px 的主因），
        没流水的折叠起来、可展开

   【为什么用 minmax(0, 1fr) 而不是 1fr】
     网格项默认 min-width:auto，里面一句长文本就会把那一栏撑破、
     把另一栏挤扁。写 minmax(0,1fr) 才允许它收缩。
     这个坑在别处踩过（邮件列表那次），这里一开始就写对。
   ========================================================================== */
.stat-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 14px;
  align-items: start;   /* 让每张卡各自高，不被同行那张拉齐 */
}
/* 满宽 / 半宽 */
.stat-grid > .stat-span-all,
.stat-grid > .lg-toolbar,
.stat-grid > .lg-stats {
  grid-column: 1 / -1;
}
.stat-grid > .span-half { grid-column: span 1; }

/* 【网格里不要再留 margin-top】
   原来 .stat-card 有 margin-top:14px —— 那是给单列 flex 排版用的。
   放进网格之后，间距交给 gap，再加 margin 会变成"每张卡头上多 14px"，
   而且网格的 align-items:start 会让它显得更歪。 */
.stat-grid > .stat-card { margin-top: 0; }

/* 窄屏退回单栏 —— 两栏在手机上每栏只剩 160px，什么都看不清 */
@media (max-width: 860px) {
  .stat-grid { grid-template-columns: minmax(0, 1fr); }
  .stat-grid > .span-half { grid-column: 1 / -1; }
}

/* 「显示 N 天没有流水」那个小按钮（长在卡片标题右边） */
.stat-foot-btn {
  margin-left: auto;
  padding: 2px 9px;
  border: 1px solid var(--line);
  border-radius: var(--r-pill);
  background: transparent;
  color: var(--text-3);
  font-size: 11px;
  cursor: pointer;
  transition: all var(--dur) var(--ease);
}
.stat-foot-btn:hover { border-color: var(--brand); color: var(--brand); }
.stat-foot-btn.on { background: var(--brand-soft); border-color: var(--brand); color: var(--brand-deep); }

/* 日报表：折叠时只显示有流水的天 */
.day-table-body { display: block; }

/* ==========================================================================
   存量汇总：固定资产 / 订阅 / 账户（2026-10-06）
   --------------------------------------------------------------------------
   用户原话：「统计应增加上 固定资产、订阅、账户等等统计，作为一个汇总页面」

   这几块和上面那些卡片的区别：**不跟着期间变**。
   所以在它们上面挂一句说明（.stat-card-note），
   否则用户切到"今天"发现固定资产还是 2.7 万，会以为统计坏了。
   ========================================================================== */
.stat-stock-head {
  /* 它是"一段的开始"，只要一个小标题，不要卡片那种厚度 */
  padding: 10px 14px;
  background: var(--surface-2);
  border-style: dashed;
}
.stat-card-note {
  margin-left: auto;
  font-size: 11px;
  color: var(--text-3);
  font-weight: 400;
}

/* 三个大数字并排 */
.stock-nums {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 10px;
  margin: 10px 0 4px;
}
.stock-num {
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 0;
}
.stock-num .sn-label {
  font-size: 11px;
  color: var(--text-3);
}
.stock-num .sn-value {
  font-size: 16px;
  font-weight: 650;
  color: var(--text);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
/* 负债用红的 —— 和"支出"同一套色，一眼看出方向 */
.stock-num .sn-value.danger { color: #d9534f; }
.stock-num .sn-hint {
  font-size: 10.5px;
  color: var(--text-3);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* 分类占比条（比统计页主列表更紧凑：这里只是"看一眼构成"） */
.stock-bars {
  display: flex;
  flex-direction: column;
  gap: 5px;
  margin-top: 10px;
  padding-top: 10px;
  border-top: 1px solid var(--line-soft);
}
.stock-bar-row {
  display: grid;
  grid-template-columns: minmax(0, 92px) minmax(0, 1fr) auto auto;
  align-items: center;
  gap: 8px;
  font-size: 11.5px;
}
.stock-bar-row .sb-name {
  color: var(--text-2);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.stock-bar-row .sb-track {
  height: 6px;
  border-radius: 3px;
  background: var(--surface-3);
  overflow: hidden;
}
.stock-bar-row .sb-fill {
  display: block;
  height: 100%;
  border-radius: 3px;
  background: var(--brand);
  transition: width var(--dur) var(--ease);
}
/* 欠钱那条用红的 */
.stock-bar-row .sb-fill.debt { background: #d9534f; }
.stock-bar-row .sb-val {
  color: var(--text);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.stock-bar-row .sb-n {
  font-size: 10.5px;
  color: var(--text-3);
  background: var(--surface-3);
  border-radius: var(--r-pill);
  padding: 0 6px;
  font-variant-numeric: tabular-nums;
}

/* 订阅：接下来要扣的 */
.stock-upcoming {
  margin-top: 10px;
  padding-top: 10px;
  border-top: 1px solid var(--line-soft);
}
.stock-upcoming .su-title {
  font-size: 11px;
  color: var(--text-3);
  margin-bottom: 6px;
}
.stock-upcoming .su-row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto auto;
  gap: 10px;
  align-items: center;
  font-size: 12px;
  padding: 3px 0;
}
.stock-upcoming .su-name {
  color: var(--text-2);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.stock-upcoming .su-date {
  color: var(--text-3);
  font-size: 11px;
  font-variant-numeric: tabular-nums;
}
.stock-upcoming .su-amt {
  color: var(--text);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
/* 有该提醒的订阅 */
.stock-warn {
  margin-top: 10px;
  padding: 7px 10px;
  border-radius: var(--r-xs);
  background: var(--warn-bg, var(--amber-soft));
  border: 1px solid var(--warn-line, var(--tone-amber-bd));
  font-size: 11.5px;
  color: var(--text-2);
}

/* 窄屏：三个大数字挤成两行，占比条的名字列收窄 */
@media (max-width: 860px) {
  .stock-nums { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .stock-bar-row { grid-template-columns: minmax(0, 68px) minmax(0, 1fr) auto; }
  .stock-bar-row .sb-n { display: none; }
}

/* ==========================================================================
   统计页：调整卡片顺序（2026-10-06）
   --------------------------------------------------------------------------
   用户原话：「统计也做可调整组件顺序，类似于 组件活动」

   "组件活动"指的是看板编辑模式那种拖一下就换位置的手感。
   这里同理，但更轻量：点一下「调整顺序」才进入可拖状态。
   ========================================================================== */
.stat-sort-bar {
  display: flex;
  align-items: center;
  gap: 10px;
  /* 【它在网格里占满一整行】
     它就是一条工具栏，半宽的话右边会空一块。 */
  grid-column: 1 / -1;
  padding: 2px 0 4px;
}
.stat-sort-btn { flex: none; }
.stat-sort-btn.on {
  background: var(--brand-soft);
  border-color: var(--brand);
  color: var(--brand-deep);
}
.stat-sort-hint {
  font-size: 11px;
  color: var(--text-3);
}

/* 调整模式下：卡片可以拖 */
.stat-grid.stat-sorting-on > .stat-card {
  cursor: grab;
  /* 【只留一条提示线，不加花哨的边框】
     加粗边框会让卡片尺寸变一下（border-box 也还是会动内容），
     整页看起来在抖。用 outline 不占布局。 */
  outline: 1px dashed var(--line-strong);
  outline-offset: 2px;
  transition: outline-color var(--dur) var(--ease);
}
.stat-grid.stat-sorting-on > .stat-card:hover {
  outline-color: var(--brand);
}
/* 正在拖的那张 */
.stat-grid > .stat-card.stat-dragging {
  cursor: grabbing;
  outline: 2px solid var(--brand) !important;
  outline-offset: 2px;
  opacity: .92;
  /* 【拖动中的卡片要浮起来】
     它底下的卡片会跟着挪，给个阴影能看清"这张是我抓着的"。 */
  box-shadow: var(--shadow-md, 0 8px 24px rgba(0, 0, 0, .14));
  z-index: 2;
  position: relative;
}
/* 拖动中禁掉整页选中 —— 否则会把卡片里的文字刷成蓝色 */
body.stat-sorting {
  user-select: none;
  cursor: grabbing;
}
/* 拖动中卡片里的勾选框、链接不该能点 */
body.stat-sorting .stat-grid .stat-card a,
body.stat-sorting .stat-grid .stat-card input,
body.stat-sorting .stat-grid .stat-card button {
  pointer-events: none;
}

/* ==========================================================================
   一木官网同步弹窗（2026-10-06）
   --------------------------------------------------------------------------
   用户原话：「流水官方自动同步或者手动点击同步这个…也做一下看看」

   这个弹窗要讲清三步（去官网登录 → 复制代码 → 贴回结果），
   所以用编号步骤的排版，而不是一大段说明文字。
   ========================================================================== */
.yms-wrap { display: block; }

/* 一步 = 一个圆编号 + 右边的内容 */
.yms-step {
  display: flex;
  gap: 10px;
  margin-bottom: 16px;
}
.yms-num {
  flex: none;
  width: 20px;
  height: 20px;
  border-radius: 50%;
  background: var(--brand);
  color: var(--on-brand);
  font-size: 11px;
  line-height: 20px;
  text-align: center;
  margin-top: 1px;
}
.yms-step-body { flex: 1; min-width: 0; }
.yms-step-title {
  font-size: 13px;
  font-weight: 600;
  color: var(--text);
  margin-bottom: 3px;
}
.yms-step-note {
  font-size: 11.5px;
  color: var(--text-3);
  line-height: 1.75;
  margin-bottom: 7px;
}
.yms-step-note kbd {
  padding: 1px 5px;
  border: 1px solid var(--line-strong);
  border-bottom-width: 2px;
  border-radius: 4px;
  font-size: 10.5px;
  background: var(--surface-2);
  font-family: inherit;
}

/* 代码块 + 复制按钮 */
.yms-code-head {
  display: flex;
  justify-content: flex-end;
  margin-bottom: 5px;
}
.yms-code,
.yms-paste {
  width: 100%;
  box-sizing: border-box;
  padding: 9px 10px;
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
  background: var(--surface-2);
  color: var(--text-2);
  font-family: ui-monospace, Menlo, Consolas, monospace;
  font-size: 11px;
  line-height: 1.6;
  resize: vertical;
}
/* 只读的代码块：用等宽 + 稍暗，一眼看出"这是要复制走的东西" */
.yms-code {
  color: var(--text-3);
  cursor: text;
}
.yms-paste { color: var(--text); }
.yms-paste:focus {
  outline: none;
  border-color: var(--brand);
}

.yms-acts {
  display: flex;
  gap: 8px;
  margin-top: 9px;
}

/* 上次同步到哪儿 —— 用户想知道"这次会拉多少" */
.yms-state {
  padding: 7px 10px;
  border-radius: var(--r-sm);
  background: var(--brand-soft);
  color: var(--brand-deep);
  font-size: 11.5px;
  margin-bottom: 10px;
}

/* 结果区 */
.yms-out { display: block; }
.yms-msg {
  font-size: 12px;
  color: var(--text-2);
  padding: 5px 0;
  line-height: 1.7;
}
.yms-msg.good { color: var(--green); font-weight: 600; }
.yms-msg.bad { color: var(--red); }
.yms-msg.warn { color: var(--amber); }

/* 试算时列的样例行 */
.yms-row {
  display: flex;
  align-items: baseline;
  gap: 9px;
  padding: 5px 0;
  border-bottom: 1px solid var(--line);
  font-size: 11.5px;
}
.yms-row:last-child { border-bottom: 0; }
.yms-d { flex: none; color: var(--text-3); font-variant-numeric: tabular-nums; }
.yms-k {
  flex: none;
  padding: 1px 6px;
  border-radius: 999px;
  background: var(--red-soft);
  color: var(--red);
  font-size: 10.5px;
}
.yms-k.in { background: var(--green-soft, var(--brand-soft)); color: var(--green); }
.yms-a {
  flex: none;
  min-width: 74px;
  text-align: right;
  font-variant-numeric: tabular-nums;
  color: var(--text);
}
.yms-c {
  flex: 1;
  min-width: 0;
  color: var(--text-3);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* ==========================================================================
   记账页签的「默认页签」小标（2026-10-06）
   --------------------------------------------------------------------------
   用户：「进记账页，默认停在『流水』，并且可设置」
   设过之后那一页签上挂个小房子 —— 不然下次进来发现落在别处，
   会以为"设置没生效/坏了"。
   ========================================================================== */
.lg-tab-default {
  flex: none;
  margin-left: 4px;
  font-size: 10px;
  line-height: 1;
  color: var(--brand);
  opacity: .95;
}
/* 选中的那个页签底色是主色，小标要跟着换成"在深底上看得清"的颜色 */
.lg-tab.on .lg-tab-default { color: var(--on-brand); }

/* ==========================================================================
   报销 + 账本（2026-10-08）
   --------------------------------------------------------------------------
   用户原话：
     「在流水页面增加两列，一列是报销账户列，一列是账本列」
     「报销功能 是我在支出的时候，可选择是否为报销，如果是 则选择一个
       报销账户，记录进去，这笔金额不计入支出」
   ========================================================================== */

/* ---------- 编辑弹窗里的报销块 ---------- */
.rec-reimb {
  margin: 2px 0 12px;
  padding: 10px 12px;
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
  background: var(--surface-2);
}
/* 勾上之后底色换成品牌色系 —— "这一笔走报销"是个重要状态，
   值得和普通字段区分开 */
.rec-reimb.on {
  border-color: var(--brand);
  background: var(--brand-soft);
}
.rec-reimb-head {
  display: flex;
  align-items: center;
  gap: 7px;
  cursor: pointer;
  font-size: 12.5px;
  color: var(--text-2);
}
.rec-reimb-head input { flex: none; }
.rec-reimb-hint {
  font-size: 11px;
  color: var(--text-3);
  margin-left: auto;
}
.rec-reimb.on .rec-reimb-hint { color: var(--brand-deep); }
.rec-reimb-body { margin-top: 8px; }

.rec-reimb-state {
  margin-top: 7px;
  font-size: 11.5px;
  line-height: 1.7;
}
.rec-reimb-state.pending { color: var(--amber); }
.rec-reimb-state.settled { color: var(--green); }

/* ---------- 流水列表里的报销格 ---------- */
.rec-reimb-tag {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  max-width: 100%;
  padding: 1px 7px;
  border-radius: 999px;
  font-size: 10.5px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
/* 一个小圆点：两个字的标签太小，点能让它在扫视时更显眼 */
.rec-reimb-tag .rr-dot {
  flex: none;
  width: 5px;
  height: 5px;
  border-radius: 50%;
  background: currentColor;
}
.rec-reimb-tag.pending {
  background: var(--amber-soft);
  color: var(--amber);
}
.rec-reimb-tag.settled {
  background: var(--brand-soft);
  color: var(--brand-deep);
}
/* 多报（多下来的钱）/ 少报（自己亏的）—— 和金额列同一套颜色语义 */
.rec-reimb-tag.settled.more { background: var(--green-soft, var(--brand-soft)); color: var(--green); }
.rec-reimb-tag.settled.less { background: var(--red-soft); color: var(--red); }

/* ---------- 账本列 ---------- */
.rec-book {
  display: inline-block;
  max-width: 100%;
  padding: 1px 7px;
  border-radius: var(--r-xs, 4px);
  /* 【账本用中性底色，不上彩色】
     它是个"归属"标签，一类账共用同一个值 ——
     上色的话满屏都是色块，反而看不出哪笔特殊。
     颜色要留给报销那种"状态"。 */
  background: var(--surface-3);
  color: var(--text-2);
  font-size: 10.5px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* ---------- 报销结算弹窗 ---------- */
.rsk-wrap { display: block; }
.rsk-head {
  display: flex;
  align-items: baseline;
  gap: 10px;
  margin-bottom: 12px;
}
.rsk-account {
  font-size: 13px;
  font-weight: 600;
  color: var(--text);
}
.rsk-note-row {
  font-size: 11.5px;
  color: var(--text-3);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* 花了多少 / 报回多少 —— 两栏对着看 */
.rsk-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 10px;
  margin-bottom: 12px;
}
.rsk-item {
  display: flex;
  flex-direction: column;
  gap: 5px;
  padding: 10px;
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
  background: var(--surface-2);
}
.rsk-lb { font-size: 11px; color: var(--text-3); }
.rsk-item b { font-size: 15px; color: var(--text); }

/* 差额那一行 —— 多报绿、少报红，和流水列表同一个语义 */
.rsk-line {
  display: flex;
  align-items: baseline;
  gap: 9px;
  padding: 9px 11px;
  border-radius: var(--r-sm);
  font-size: 12px;
  margin-bottom: 9px;
}
.rsk-line b { font-size: 14px; }
.rsk-line.more { background: var(--green-soft, var(--brand-soft)); color: var(--green); }
.rsk-line.less { background: var(--red-soft); color: var(--red); }
.rsk-line.even {
  background: var(--surface-2);
  color: var(--text-3);
}
.rsk-k { flex: none; font-weight: 600; }
.rsk-d { color: inherit; opacity: .85; font-size: 11.5px; }

.rsk-choice { margin-top: 4px; }
.rsk-chk {
  display: flex;
  align-items: center;
  gap: 7px;
  padding: 9px 11px;
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
  font-size: 12.5px;
  color: var(--text-2);
  cursor: pointer;
}
.rsk-chk:hover { border-color: var(--brand); }
.rsk-chk input { flex: none; }
.rsk-note {
  font-size: 11px;
  color: var(--text-3);
  line-height: 1.7;
  margin-top: 6px;
  padding-left: 2px;
}

/* 待报销那格里的「已报」按钮 —— 很小，但要能点到 */
.rr-act {
  flex: none;
  margin-left: 5px;
  padding: 0 6px;
  border: 0;
  border-radius: 999px;
  background: currentColor;
  color: var(--surface);
  font-size: 10px;
  line-height: 15px;
  cursor: pointer;
}
.rr-act:hover { opacity: .85; }

/* ---------- 账单详情悬浮窗（2026-10-08） ---------- */
.rd-wrap { display: block; }

/* 头：分类 + 金额，一眼看清这笔是什么 */
.rd-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 0 0 12px;
  margin-bottom: 12px;
  border-bottom: 1px solid var(--line);
}
.rd-head-cat {
  display: flex;
  align-items: center;
  gap: 6px;
  min-width: 0;
  font-size: 13px;
  color: var(--text-2);
}
.rd-head-ico { flex: none; display: flex; }
.rd-imp {
  flex: none;
  padding: 1px 6px;
  border-radius: var(--r-xs, 4px);
  background: var(--surface-3);
  color: var(--text-3);
  font-size: 10px;
}
.rd-head-amt {
  flex: none;
  font-size: 19px;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
}
.rd-head-amt.in { color: var(--green); }
.rd-head-amt.out { color: var(--red); }

/* 字段列表：左标签右值 —— 和一木那边一样的排法 */
.rd-list { display: block; }
.rd-row {
  display: flex;
  align-items: flex-start;
  gap: 12px;
  padding: 7px 0;
  border-bottom: 1px solid var(--line);
  font-size: 12.5px;
}
.rd-row:last-child { border-bottom: 0; }
.rd-label {
  flex: none;
  width: 68px;
  color: var(--text-3);
}
.rd-value {
  flex: 1;
  min-width: 0;
  color: var(--text);
  word-break: break-all;
}
/* 空值用破折号 —— 让用户看得出"这项我没填"，而不是"这项不存在" */
.rd-none { color: var(--text-3); }

.rd-amt-inline { font-variant-numeric: tabular-nums; }

/* 状态小标签：待报 / 多报 / 少报 / 不计入 */
.rd-tag {
  display: inline-block;
  padding: 1px 8px;
  border-radius: 999px;
  font-size: 11px;
}
.rd-tag.pending { background: var(--amber-soft); color: var(--amber); }
.rd-tag.more { background: var(--green-soft, var(--brand-soft)); color: var(--green); }
.rd-tag.less { background: var(--red-soft); color: var(--red); }
.rd-tag.even { background: var(--surface-3); color: var(--text-2); }
.rd-tag.off { background: var(--surface-3); color: var(--text-3); }

.rd-tags { display: flex; flex-wrap: wrap; gap: 5px; }
.rd-tag-item {
  padding: 1px 7px;
  border-radius: 999px;
  background: var(--surface-2);
  color: var(--text-2);
  font-size: 11px;
}

/* ---------- 从账户页跳进来的筛选横幅（2026-10-08） ----------
   点报销账户 → 跳到流水并自动筛好。
   这条横幅负责说清"在看什么"并给一个退出筛选的出口 ——
   没有它的话用户会以为"我的流水怎么只剩这几条了"。 */
.rec-filterbar {
  display: flex;
  align-items: center;
  gap: 9px;
  margin: 0 0 10px;
  padding: 8px 12px;
  border-radius: var(--r-sm, 8px);
  background: var(--brand-soft);
  color: var(--brand-deep);
  font-size: 12.5px;
}
.rec-filterbar .rb-ico { flex: none; }
.rec-filterbar .rb-text { flex: 1; min-width: 0; }
.rec-filterbar .rb-count {
  flex: none;
  color: var(--text-3);
  font-variant-numeric: tabular-nums;
}

/* 每张统计卡 */
.stat-card {
  margin-top: 14px;
  padding: 12px 14px;
  border-radius: var(--r-sm, 12px);
  background: var(--surface);
  border: 1px solid var(--line);
}
.stat-card-head {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
  margin-bottom: 10px;
}
.stat-card-title { font-size: 12.5px; font-weight: 600; }

/* ==========================================================================
   日报表 —— 用户 2026-10-03 提的「增加日报表」
   （口径：一天一行，日期 + 收入 + 支出 + 结余 + 笔数）
   --------------------------------------------------------------------------
   用 grid 对齐而不是 <table>：行和表头共用同一套列模板，
   改列宽只改一处，不会出现"表头和数据错位"。
   ========================================================================== */
.day-table { display: flex; flex-direction: column; }
.day-head,
.day-row {
  display: grid;
  /* 日期宽一点（要放"10 月 05 日"），三个数字列等宽，笔数最窄 */
  grid-template-columns: 78px 1fr 1fr 1fr 46px;
  gap: 8px;
  align-items: center;
  padding: 5px 6px;
  border-radius: 6px;
}
.day-head {
  font-size: 10.5px;
  color: var(--text-3);
  border-bottom: 1px solid var(--line);
  padding-bottom: 6px;
  margin-bottom: 2px;
}
.day-row { border-bottom: 1px solid var(--line-soft); font-size: 12px; }
.day-row:last-child { border-bottom: 0; }
.day-row:hover { background: var(--surface-2); }
/* 当天没有流水：整行压淡 —— 但要留一行，
   "这天没花钱"本身就是有用的信息，跳过会让人以为数据缺了 */
.day-row.idle { opacity: .45; }
.dh-num, .dr-num { text-align: right; font-variant-numeric: tabular-nums; }
.dh-n { text-align: right; }
.dr-date { color: var(--text-2); }
.dr-num.in { color: var(--green); }
.dr-num.out { color: var(--red); }
.dr-num.bal { color: var(--text-2); }
.dr-n { text-align: right; color: var(--text-3); font-variant-numeric: tabular-nums; }
/* 窄屏：笔数列藏掉，三个数字列挤一挤也要留着（它们是这张表的意义） */
@media (max-width: 720px) {
  .day-head, .day-row { grid-template-columns: 62px 1fr 1fr 1fr; }
  .dh-n, .dr-n { display: none; }
}

.stat-foot-inline { margin-left: auto; font-size: 11px; color: var(--text-3); font-variant-numeric: tabular-nums; }
.stat-foot {
  margin-top: 10px;
  padding-top: 8px;
  border-top: 1px dashed var(--line);
  font-size: 11px;
  color: var(--text-3);
  line-height: 1.6;
}
.stat-rest {
  margin-top: 8px;
  font-size: 11px;
  color: var(--text-3);
  line-height: 1.6;
}

/* ---------------------- 热力图 ---------------------- */

.stat-year { display: flex; align-items: center; gap: 4px; }
.stat-year-label { font-size: 11.5px; color: var(--text-2); font-variant-numeric: tabular-nums; }

.stat-legend {
  display: flex;
  align-items: center;
  gap: 4px;
  font-size: 10.5px;
  color: var(--text-3);
}
.stat-legend i {
  /* 8 个色块（支出 4 + 收入 4）+ 2 个标签挤在一行，
     从 11px 收到 10px，免得把卡片头顶换行 */
  width: 10px; height: 10px;
  border-radius: 3px;
  display: inline-block;
}

/* ==========================================================================
   热力图色阶
   --------------------------------------------------------------------------
   【用户 2026-10-03 报的】「收支热力图 应该是 红色支出，绿色收入，
   现在全是绿色了」

   原来五档**全是同一个绿**（rgba(107,122,90,…)），而且只按**支出**分档 ——
   收入在格子上完全没有体现（只在悬停的 tooltip 里提了一句）。
   所以整张图看着一片绿。

   现在分成两族：
     · **支出 = 红**（ex-lv1..4）—— 花得越多越红，符合"支出=警示"的直觉
     · **收入 = 绿**（in-lv1..4）—— 进账越多越绿
     · 0 档 = 很淡的底（那天没记录）

   【同一天既有支出又有收入怎么办】
     这是设计上的取舍，说明一下：
     一个 9px 的方块只能上一个底色，做不到"一半红一半绿"。
     所以取**金额大的那一方**定色 —— 那天是"净花"还是"净赚"，
     颜色就跟着哪边。
     具体金额仍然悬停可见（tooltip 里支出和收入都会列出来），
     所以信息没丢，只是底色按主导方向走。

   【为什么用两族而不是同色系深浅】
     收支是**方向相反**的两件事，用同一个色相表达不出来。
     红/绿是记账类产品的通行约定（用户自己也是这么说的），
     这里就按约定来，不去标新立异。

   深浅一律用"当期最大值"分档（见 heatLevel 的注释），
   所以"深 = 相对那天花得多/赚得多"，人和人之间不可比 —— 个人账本不需要比。 */

/* ---- 支出：红 ---- */
.heat-lv0 { background: var(--surface-2); }
.heat-ex1 { background: rgba(251, 86, 85, .18); }
.heat-ex2 { background: rgba(251, 86, 85, .40); }
.heat-ex3 { background: rgba(251, 86, 85, .64); }
.heat-ex4 { background: rgba(230, 62, 61, .92); }
/* ---- 收入：绿（参考站主色） ---- */
.heat-in1 { background: rgba(72, 171, 147, .18); }
.heat-in2 { background: rgba(72, 171, 147, .40); }
.heat-in3 { background: rgba(72, 171, 147, .64); }
.heat-in4 { background: rgba(48, 145, 122, .92); }

/* 【旧的 class 名保留成别名】
   检查脚本和别处可能还引用着 heat-lv1..4。
   直接删掉会让那些地方静默失效（背景变透明、看着像"格子丢了"）。
   映射到**支出**（原来那套色阶表达的就是支出），行为不变。 */
.heat-lv1 { background: rgba(251, 86, 85, .18); }
.heat-lv2 { background: rgba(251, 86, 85, .40); }
.heat-lv3 { background: rgba(251, 86, 85, .64); }
.heat-lv4 { background: rgba(230, 62, 61, .92); }

/* 4 行 × 3 列 */
.heat-grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 10px;
}
/* 【每格定高】
   月份天数不一样（28~31），不定高的话 2 月那格矮一截，
   4×3 网格参差不齐。 */
.heat-month {
  display: flex;
  flex-direction: column;
  gap: 5px;
  padding: 8px 9px;
  border-radius: 9px;
  background: var(--surface-2);
  min-height: 86px;
}
.heat-month-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 6px;
}
.heat-month-name { font-size: 11px; font-weight: 600; color: var(--text-2); }
.heat-month-sum {
  font-size: 10px;
  color: var(--text-3);
  font-variant-numeric: tabular-nums;
  display: flex;
  align-items: baseline;
  gap: 5px;
}
/* 月份汇总：支出红、收入绿 —— 和格子用同一套语言。
   加了 + 号区分进账（收入本来就是"加"） */
.heat-sum-ex { color: var(--red); }
.heat-sum-in { color: var(--green); }

/* 图例：两组各一个标签 + 四档色块 */
.stat-legend-label { font-size: 10.5px; color: var(--text-3); }
.stat-legend-gap { width: 8px; display: inline-block; }

/* 每天的方块：自动换行铺满一格宽度 */
.heat-days {
  display: flex;
  flex-wrap: wrap;
  gap: 2px;
  align-content: flex-start;
  flex: 1 1 auto;
}
.heat-cell {
  width: 9px; height: 9px;
  border-radius: 2px;
  display: block;
  cursor: default;
  transition: transform .1s var(--ease);
}
.heat-cell:hover { transform: scale(1.45); }
.heat-month-foot { font-size: 9.5px; color: var(--text-3); font-variant-numeric: tabular-nums; }

/* ---------------------- 走势 ---------------------- */

/* 「期初 → 期末」那一行 —— 用户拿它去对账户页的数字 */
.trend-range {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
  margin-bottom: 10px;
  font-size: 11.5px;
  color: var(--text-2);
  font-variant-numeric: tabular-nums;
}
.trend-arrow { color: var(--text-3); }
.trend-end { font-weight: 600; }
.trend-ok { color: #35907a; font-size: 11px; }
/* 对不上时**不报红** —— 那可能只是"还没登记账户"，不是错误 */
.trend-warn { color: #d97a1f; font-size: 11px; }

/* 【零轴画在中间偏上，不再是"最底下那条线"】
   用户 2026-10-03 提的：「收支走势 加入 结余」

   结余**有正有负**（实测数据 -104 ~ +306），
   负的结余必须画在零轴**下面**。
   所以容器从"贴底"改成"上下都有空间"：
     上半区 62% 给正的结余，下半区 38% 给负的。
   支出/收入两根柱子仍然从零轴往上长，它们是非负的。 */
/* 【图例变成开关 —— 用户 2026-10-03 提的
   「收支走势的 支出、收入、结余应可选择，默认全选，可多选显示」】

   每个主题一条，点一下切换显示/隐藏。
   `.on` 是显示中（色块实心、文字正常），
   `.off` 是已隐藏（色块变空心描边、文字变淡）——
   不用"划线"是因为三条挤在一起时划线看着很乱。 */
.trend-toggle {
  font: inherit;
  font-size: 10.5px;
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 2px 6px;
  margin: 0 1px;
  border: 1px solid transparent;
  border-radius: 6px;
  background: transparent;
  color: var(--text-3);
  cursor: pointer;
  transition: background .12s var(--ease), border-color .12s var(--ease);
}
.trend-toggle:hover { background: var(--surface-3); border-color: var(--line); }
.trend-toggle.on { color: var(--text-2); }
/* 隐藏的那条：色块只剩描边、整体压淡 —— 一眼看出它没参与 */
.trend-toggle.off { opacity: .55; }
.trend-toggle.off i {
  background: transparent !important;
  box-shadow: inset 0 0 0 1.5px currentColor;
}
.trend-toggle.off:hover { opacity: .85; }
/* 那个色块沿用 bar-* 的底色（.bar-exp/.bar-inc/.bar-bal.up） */
.trend-toggle i {
  width: 10px;
  height: 10px;
  border-radius: 3px;
  display: inline-block;
  flex: 0 0 auto;
}
/* 图例里那个没加 .up 的结余色块 —— 补上颜色 */
.trend-toggle i.bar-bal { background: #0081ff; }

/* 【结余关掉时零轴挪到底、支出/收入占满整列】
   原来下面那 38% 是留给负结余的，不显示结余就是白空着。 */
.trend-chart.no-bal .trend-bars {
  height: 100%;
  flex: 0 1 100%;
  margin-bottom: 0;
}
.trend-chart.no-bal::after { bottom: 16px; }

.trend-chart {
  display: flex;
  align-items: flex-end;
  gap: 3px;
  height: 148px;
  /* 上面留 4% 呼吸，下面留出负结余的位置 + 16px 放月份标签 */
  padding-top: 6px;
  padding-bottom: 16px;
  position: relative;
}
/* 【零轴】
   原来它在最底下（bottom:16px，正是标签上面那条线）。
   现在结余要跨它，所以挪到 62% 高处 —— 用 ::after 画。 */
.trend-chart::after {
  content: '';
  position: absolute;
  left: 0; right: 0;
  /* 【零轴 = 内容的 62% 高处】
     和 .trend-bars 的 height:62% 是同一个数 ——
     这样线和柱子必然对齐（踩过两次"两个基准不一致"的坑，
     一次是 38% vs 50%，一次是百分比 vs padding，
     现在干脆只用这一个数字）。
     16px 是底部留给月份标签的高度。 */
  bottom: calc(16px + (100% - 16px) * 0.38);
  border-top: 1px solid var(--line);
}
.trend-col {
  flex: 1 1 0;
  min-width: 0;
  height: 100%;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  align-items: center;
  position: relative;
}
/* 【结余柱：绝对定位，位置由 JS 算成像素】
   为什么不让 CSS 用 50%：
   .trend-chart 有 padding-bottom:16px（放月份标签），
   而 .trend-col 是 height:100%、**包含**那 16px ——
   于是 top:50% 比真正的零轴低 8px，负结余柱会跑到轴上面去
   （实测 relToZero -9px / -8px）。
   现在零轴的位置由 JS 量出来、算成 px 写进 inline style，
   CSS 只管外观，两边不会再打架。 */
.trend-col > .bar-bal {
  position: absolute;
  /* 和 .trend-bars 里那两根错开，不然会重叠 */
  left: 50%;
  transform: translateX(-50%);
  width: 3px;
  min-width: 3px;
  border-radius: 2px;
}
.trend-col > .bar-bal.up { border-radius: 2px 2px 0 0; }
.trend-col > .bar-bal.down { border-radius: 0 0 2px 2px; }
.trend-bars {
  display: flex;
  align-items: flex-end;
  justify-content: center;
  gap: 2px;
  width: 100%;
  /* 【零轴以上占 62%，下面 38% 留给负结余】
     支出/收入从这条带子的**底边**往上长，那条底边就是零轴。
     注意光写 height 不够 —— .trend-col 是
     justify-content:flex-end 的 flex 列，写多矮都会被**推到底**，
     零轴照样贴着图的底边。必须再给一个 margin-bottom 把它整体抬起来，
     下面那 38% 才真的空出来。 */
  height: 62%;
  flex: 0 1 62%;
  margin-bottom: 38%;
}
.trend-bars > i {
  flex: 1 1 0;
  min-width: 3px;
  max-width: 14px;
  border-radius: 3px 3px 0 0;
  display: block;
  min-height: 1px;
}
/* 支出用暖色、收入用绿色 —— 和别处"赚绿花红"的习惯一致。
   （热力图那边也是这套：花红赚绿，见 .heat-ex/.heat-in） */
.trend-bars .bar-exp { background: #fb5655; }
.trend-bars .bar-inc { background: #48ab93; }
/* 【结余柱：蓝灰，和红/绿两族都拉开】
   结余是"收支相抵之后剩下多少"，既不是花钱也不是赚钱，
   所以用第三色 —— 蓝灰，一眼能和红绿区分开。
   正值加深一点（"还剩"），负值浅一点（"超了"），方向已由位置表达。 */
/* 结余用蓝 —— 参考站图表里的蓝 #0081ff。
   红/绿已经被支出和收入占了，结余要第三种颜色才分得开。 */
.bar-bal.up { background: #0081ff; }
.bar-bal.down { background: rgba(0, 129, 255, .45); }
/* 图例里那个结余色块（.stat-legend i 统一 10px 方） */
.stat-legend i.bar-bal.up { background: #0081ff; }
.trend-label {
  position: absolute;
  bottom: -15px;
  font-size: 9px;
  color: var(--text-3);
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
}

/* ---------------------- 占比横条 ---------------------- */

/* ==========================================================================
   饼图（分类构成 / 只在"占比之和 = 100%"时才画）
   --------------------------------------------------------------------------
   用 SVG 而不是 div + conic-gradient：扇形之间的**边界**要看得清
   （相邻两块颜色接近时 conic-gradient 会糊成一片），
   而且 SVG 的每个 <path> 能单独挂悬停、能加描边。
   ========================================================================== */
.pie-wrap {
  display: flex;
  align-items: center;
  gap: 14px;
  flex-wrap: wrap;
  margin-bottom: 12px;
  /* 【窄屏时饼图缩小、图例换行】
     卡片本身可能不宽（统计页是两列），饼图固定 168px 会挤掉图例。 */
}
.pie-box { flex: 0 0 auto; line-height: 0; }
.pie-svg { display: block; width: 148px; height: 148px; }
/* 每块之间留一道白缝 —— 相邻两块颜色接近时全靠它分开 */
.pie-slice {
  stroke: var(--surface);
  stroke-width: 1.5;
  transition: opacity .12s var(--ease);
}
/* 悬停时把别块压暗一点，突出当前这块（SVG 里做不了"只亮自己"，
   所以反过来压暗别人 —— 效果一样，而且不用 JS 记状态） */
.pie-svg:hover .pie-slice { opacity: .45; }
.pie-svg .pie-slice:hover { opacity: 1; }

.pie-legend {
  flex: 1 1 150px;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 5px;
}
.pie-legend-row {
  display: grid;
  grid-template-columns: 9px minmax(0, 1fr) auto;
  align-items: center;
  gap: 7px;
  font-size: 11.5px;
  color: var(--text-2);
}
.pie-legend-name {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.pie-legend-pct {
  color: var(--text-3);
  font-variant-numeric: tabular-nums;
}
/* 圆点：饼图和横条共用，让两处能对上号 */
.pie-dot {
  width: 9px;
  height: 9px;
  border-radius: 50%;
  display: inline-block;
  flex: 0 0 auto;
}
/* 【不画饼时的占位圆点 —— 用户 2026-10-03 报的
   「进度条类的统计，进度条的起点不一致」】
   实测那条不是"起点差一点"，而是**整行错列**：
   不能画饼的卡片（标签占比）里，名称被挤成 46px、
   进度条跑进"名称列"、金额和笔数各错一位。

   【真正的成因 —— 我第一次写错了，这里改正】
   我一开始以为"传 null 会 append 成一个空节点、占掉一列"。
   查 util.js 的 append() 才发现**不是**：
     `if (c == null || c === false || c === true) continue`
   —— null 是被**正确跳过**的。

   真正的问题是：跳过之后这个元素只剩 **5 个子元素**，
   而模板是 **6 列**。grid 是按顺序往下排的，
   子元素少一个，后面每一个就都**提前一列**：
     name→第1列(auto＝46px) track→第2列(108px)
     pct→第3列(1fr＝848px) amt→第4列(46px) cnt→第5列(88px)
   实测的宽度和这个推算**完全对上**。

   所以关键不是"null 会不会变节点"，而是
   **子元素个数必须和列数一致**。
   现在圆点永远渲染，不画饼时用 .off 把它变透明 ——
   两条路径的列数从结构上就不可能分叉。
   **必须用 visibility:hidden 而不是 display:none** ——
   后者会让它从 grid 布局里消失，又变成"少一个子元素"。 */
.pie-dot.off { visibility: hidden; }

.stat-bars { display: flex; flex-direction: column; gap: 6px; }
/* 【列数必须和子元素个数严格相等 —— 这里是有血泪教训的】
   用户 2026-10-03 报过「进度条的起点不一致」，实测是**整行错列**：
   grid 是顺序排布的，**少一个子元素，后面每一个都提前一列**。

   现在这一行有 7 个子元素：
     勾选框 · 颜色圆点 · 名称 · 轨道 · 百分比 · 金额 · 笔数
   所以这里必须是 7 列。加/减任何一个都要同步改这里
   （包括下面两个窄屏断点 —— 那边靠 display:none 藏掉"笔数"，
     所以是 6 列，不是 7 列）。

   最前面那列宽度写死 16px（不是 auto）：勾选框在不在都不影响列宽，
   两条路径不可能再错位。 */
.stat-bar-row {
  display: grid;
  grid-template-columns: 16px 9px 108px minmax(40px, 1fr) 46px 88px 42px;
  align-items: center;
  gap: 8px;
  font-size: 11.5px;
}
/* 【勾选框：只有分类那一张卡有，标签卡没有】
   "可勾选账单"的口径是"按分类筛选合计"，所以只有分类构成那张卡带勾选。
   标签卡仍然渲染这个占位元素（用 .off 藏起来）——
   不渲染的话列数就对不上了（见上面的说明）。 */
.stat-bar-pick {
  width: 14px;
  height: 14px;
  margin: 0;
  cursor: pointer;
  accent-color: var(--brand);
}
.stat-bar-pick.off { visibility: hidden; }
/* 被勾掉的分类：整行压淡，一眼看出"这行不算数了" */
.stat-bar-row.off .stat-bar-name,
.stat-bar-row.off .stat-bar-pct,
.stat-bar-row.off .stat-bar-amt,
.stat-bar-row.off .stat-bar-cnt { opacity: .42; }
.stat-bar-row.off .stat-bar-track > i { background: var(--text-3); opacity: .5; }
.stat-bar-name {
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  color: var(--text-2);
}
.stat-bar-track {
  height: 8px;
  border-radius: 4px;
  background: var(--surface-2);
  overflow: hidden;
}
.stat-bar-track > i {
  display: block;
  height: 100%;
  border-radius: 4px;
  /* 【条子的颜色由 JS 给的 --bar-c 决定 —— 用户 2026-10-03 提的】
     「标签占比、支出分类构成 的进度条颜色 过于单一，应该不同颜色」

     原来是写死 `var(--brand)`，一根绿到底；而同一行前面的圆点
     早就是彩色的了（取自 PIE_COLORS），饼图图例也是那套色 ——
     于是"圆点是黄的、它右边的条子却是绿的"，两个说的不是一件事。

     兜底给 --brand：万一没有数据颜色（以后别处复用这个类），
     仍然是主色，不会变成一根看不见的空条。 */
  background: var(--bar-c, var(--brand));
  transition: width .2s var(--ease);
}
.stat-bar-pct { text-align: right; font-variant-numeric: tabular-nums; color: var(--text-2); font-weight: 600; }
.stat-bar-amt { text-align: right; font-variant-numeric: tabular-nums; }
.stat-bar-cnt { text-align: right; font-size: 10.5px; color: var(--text-3); font-variant-numeric: tabular-nums; }

/* 窄屏：热力图从 3 列变 2 列，占比行压缩 */
@media (max-width: 900px) {
  .heat-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  /* 6 列：勾选框 + 圆点 + 名称 + 轨道 + 百分比 + 金额（笔数被上面那行 display:none 藏掉了） */
  .stat-bar-row { grid-template-columns: 16px 9px 90px minmax(30px, 1fr) 40px 76px; }
  .stat-bar-cnt { display: none; }
}
@media (max-width: 560px) {
  .heat-grid { grid-template-columns: 1fr; }
  /* 同样是 6 列（理由同上） */
  .stat-bar-row { grid-template-columns: 16px 9px 78px minmax(24px, 1fr) 38px 70px; }
}
