/* v1.6.7 · 自有 @media 与 Tailwind 断点同一判据:同时看短边。
   手机横屏 844×390 → 移动规则若只按 max-width 判定会全部失效(用户看到的「转手机就变样」)。
   横屏 iframe 也是 844×390,但那是主动要的宽屏视图 → 会真正改变观感的规则用
   html:not(.ls-wide) 排除掉它(纯字号/内距一类无害的不排除,少改一点)。 */
/* ============================================================
   家庭账房 · Private Counting House
   一份起居室里的银行家账册
   ============================================================ */

:root {
  /* — Paper & Ink — */
  --paper:        #F4EFE6;
  --paper-soft:   #EDE6D7;
  --paper-deep:   #E5DCC8;
  --card:         #FFFCF5;
  --card-soft:    #FAF4E6;
  --ink:          #1A1714;   /* on card 17.4:1 */
  --ink-soft:     #5C5147;   /* on card  7.5:1 · AAA */
  /* v1.6 · 对比度修正(visual-spec §1.2 实测):原 #A09486 在 card 上仅 2.90:1 / 在 paper 上 2.59:1,
     连大字号 3:1 都不到,而它承载的恰恰是字号最小的一层(时间/序号/口径/计数/eyebrow)——
     小字 + 低对比 = 双重不可读。改 #706657(card 5.5:1 / paper 4.9:1,双底过 AA)。
     原浅值降级为 --ink-faint,只许画装饰(水印/禁用/占位图形),不许承载信息。 */
  --ink-subtle:   #706657;
  --ink-faint:    #A09486;
  --rule:         #BCAE96;   /* 非文字,but 原 #C9BDA8 仅 1.8:1 偏弱 → 略加深 */
  --rule-soft:    #DBD0BC;

  /* — Accents (used sparingly) — */
  --brass:        #B08642;   /* 仅作底/边/装饰:on card 3.2:1,不可作小字文字 */
  --brass-deep:   #8C6A33;
  /* v1.6 · 铜金作文字专用档(visual-spec §1.3):brass 3.2:1 / brass-deep 在 paper 上 4.34:1 都不过 AA,
     brass-text 5.3:1 / 4.8:1 双底过 AA —— 链接、eyebrow、可点强调文字用它 */
  --brass-text:   #85642F;
  --brass-soft:   #E8D9B6;
  --forest:       #4F6B47;
  --forest-soft:  #C8D5BD;
  --rust:         #9C4A2A;
  --rust-soft:    #E8C8B8;
  --plum:         #5C3A4B;
  --slate:        #3C4A5A;
  --slate-soft:   #C5CDD8;  /* v0.17 · 保险 pill 底色 */

  /* — Sizing — */
  --rule-thin:    0.5px;
  --rule-thick:   1px;

  /* — v1.2.2 · 全局字号档位(issue #7)· 一个变量驱动全站缩放;标准=1 时逐像素等价现状 — */
  --fs-scale:     1;

  /* — Effects — */
  --shadow-paper: 0 1px 0 rgba(26, 23, 20, 0.04), 0 8px 24px -12px rgba(26, 23, 20, 0.08);
  --shadow-deep:  0 2px 0 rgba(26, 23, 20, 0.04), 0 24px 60px -32px rgba(26, 23, 20, 0.18);
}

/* v1.2.2 · 字号档位:大 +15% / 特大 +30%(标准不设 = 用 :root 的 1) */
html[data-fs="lg"] { --fs-scale: 1.15; }
html[data-fs="xl"] { --fs-scale: 1.30; }

* { box-sizing: border-box; }

html, body {
  background: var(--paper);
  color: var(--ink);
  font-family: "Source Serif 4", "Noto Serif SC", Georgia, serif;
  font-feature-settings: "kern" 1, "liga" 1, "calt" 1;
  font-size: calc(15px * var(--fs-scale,1));
  line-height: 1.55;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

/* ——— 纸张纹理 ——— */
body::before {
  content: "";
  position: fixed;
  inset: 0;
  pointer-events: none;
  z-index: 1;
  background-image:
    radial-gradient(1px 1px at 10% 20%, rgba(176,134,66,0.05) 50%, transparent 50%),
    radial-gradient(1px 1px at 80% 60%, rgba(26,23,20,0.04) 50%, transparent 50%),
    radial-gradient(1px 1px at 30% 80%, rgba(176,134,66,0.04) 50%, transparent 50%),
    radial-gradient(1px 1px at 70% 30%, rgba(26,23,20,0.03) 50%, transparent 50%);
  background-size: 80px 80px, 120px 120px, 100px 100px, 90px 90px;
  background-position: 0 0, 40px 40px, 20px 60px, 60px 20px;
  opacity: 0.6;
  mix-blend-mode: multiply;
}

/* ——— Typography ——— */

.font-display { font-family: "Fraunces", "Noto Serif SC", Georgia, serif; }
.font-serif   { font-family: "Source Serif 4", "Noto Serif SC", Georgia, serif; }
.font-mono    { font-family: "JetBrains Mono", ui-monospace, "SF Mono", Menlo, monospace; font-feature-settings: "tnum" 1, "calt" 1; }

.tnum         { font-variant-numeric: tabular-nums; font-feature-settings: "tnum" 1; }
.swsh         { font-feature-settings: "swsh" 1, "ss01" 1; }   /* Fraunces swash + stylistic */

h1, h2, h3, h4 {
  font-family: "Fraunces", "Noto Serif SC", Georgia, serif;
  font-weight: 500;
  letter-spacing: -0.01em;
  color: var(--ink);
}

.eyebrow {
  font-family: "JetBrains Mono", ui-monospace, monospace;
  font-size: calc(10.5px * var(--fs-scale,1));
  font-weight: 400;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--brass-deep);
}

.eyebrow-ink {
  font-family: "JetBrains Mono", ui-monospace, monospace;
  font-size: calc(10.5px * var(--fs-scale,1));
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--ink-soft);
}

.dropcap::first-letter {
  font-family: "Fraunces", "Noto Serif SC", Georgia, serif;
  font-weight: 600;
  font-size: 3em;
  line-height: 1;
  float: left;
  padding: 4px 8px 0 0;
  color: var(--brass);
}

/* ——— Components ——— */

.paper-card {
  background: var(--card);
  border: var(--rule-thick) solid var(--rule);
  border-radius: 2px;
  box-shadow: var(--shadow-paper);
  position: relative;
}

.paper-card-soft {
  background: var(--card-soft);
  border: var(--rule-thin) solid var(--rule);
  border-radius: 2px;
}

.envelope {
  background: var(--card);
  border: var(--rule-thick) solid var(--ink);
  border-radius: 0;
  box-shadow:
    4px 4px 0 var(--paper-deep),
    var(--shadow-deep);
}

/* Bracket-cornered cards (账册装饰角) */
.bracket-card {
  position: relative;
  background: var(--card);
  border: 1px solid var(--rule);
  padding: 28px;
}
.bracket-card::before, .bracket-card::after {
  content: "";
  position: absolute;
  width: 14px;
  height: 14px;
  border: 1.5px solid var(--brass);
}
.bracket-card::before { top: -5px; left: -5px; border-right: none; border-bottom: none; }
.bracket-card::after  { bottom: -5px; right: -5px; border-left: none; border-top: none; }

/* Hairline rules (账册中的细线) */
.rule         { border-color: var(--rule); }
.rule-thick   { border-color: var(--ink); }
.rule-x       { border-top: 1px solid var(--rule); }
.rule-y       { border-left: 1px solid var(--rule); }
.rule-double  { border-top: 1px solid var(--rule); border-bottom: 1px solid var(--rule); padding: 1px 0; }
.rule-triple-bottom { border-bottom: 3px double var(--rule); padding-bottom: 4px; }

/* Buttons */
.btn-ink {
  background: var(--ink);
  color: var(--paper);
  font-family: "JetBrains Mono", ui-monospace, monospace;
  font-size: calc(12px * var(--fs-scale,1));
  letter-spacing: 0.12em;
  text-transform: uppercase;
  padding: 12px 20px;
  border: none;
  cursor: pointer;
  transition: all 180ms ease;
  display: inline-flex;
  align-items: center;
  gap: 10px;
}
.btn-ink:hover { background: var(--brass-deep); }

.btn-paper {
  background: transparent;
  color: var(--ink);
  font-family: "JetBrains Mono", ui-monospace, monospace;
  font-size: calc(12px * var(--fs-scale,1));
  letter-spacing: 0.12em;
  text-transform: uppercase;
  padding: 11px 19px;
  border: 1px solid var(--ink);
  cursor: pointer;
  transition: all 180ms ease;
  display: inline-flex;
  align-items: center;
  gap: 10px;
}
.btn-paper:hover { background: var(--ink); color: var(--paper); }

.btn-brass {
  background: var(--brass);
  color: var(--paper);
  font-family: "JetBrains Mono", ui-monospace, monospace;
  font-size: calc(12px * var(--fs-scale,1));
  letter-spacing: 0.12em;
  text-transform: uppercase;
  padding: 12px 20px;
  border: none;
  cursor: pointer;
  transition: background 180ms ease;
  display: inline-flex;
  align-items: center;
  gap: 10px;
}
.btn-brass:hover { background: var(--brass-deep); }

.btn-ghost {
  background: transparent;
  color: var(--ink-soft);
  font-family: "JetBrains Mono", ui-monospace, monospace;
  font-size: calc(11.5px * var(--fs-scale,1));
  letter-spacing: 0.12em;
  text-transform: uppercase;
  padding: 8px 14px;
  border: 1px solid transparent;
  cursor: pointer;
  transition: all 150ms ease;
}
.btn-ghost:hover { color: var(--ink); border-color: var(--rule); }

/* Form */
.field-input {
  background: transparent;
  border: none;
  border-bottom: 1px solid var(--rule);
  padding: 10px 2px;
  font-family: "Source Serif 4", "Noto Serif SC", serif;
  font-size: calc(16px * var(--fs-scale,1));
  color: var(--ink);
  width: 100%;
  outline: none;
  transition: border-color 180ms ease;
}
.field-input:focus { border-bottom: 2px solid var(--brass); padding-bottom: 9px; }

.field-input-num {
  font-family: "JetBrains Mono", monospace;
  font-variant-numeric: tabular-nums;
  font-size: calc(18px * var(--fs-scale,1));
  text-align: right;
  letter-spacing: 0.02em;
}

.field-label {
  font-family: "JetBrains Mono", monospace;
  font-size: calc(10.5px * var(--fs-scale,1));
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-soft);
  display: block;
  margin-bottom: 6px;
}

/* Pills / Chips / Tags */
.pill {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 4px 10px;
  border: 1px solid var(--rule);
  background: var(--paper-soft);
  font-family: "JetBrains Mono", monospace;
  font-size: calc(10.5px * var(--fs-scale,1));
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink-soft);
  border-radius: 1px;
}
.pill-brass { background: var(--brass-soft); border-color: var(--brass); color: var(--brass-deep); }
.pill-forest { background: var(--forest-soft); border-color: var(--forest); color: var(--forest); }
.pill-rust { background: var(--rust-soft); border-color: var(--rust); color: var(--rust); }
.pill-slate { background: var(--slate-soft); border-color: var(--slate); color: var(--slate); } /* v0.17 保险 */
.pill-ink { background: var(--ink); border-color: var(--ink); color: var(--paper); }

/* Number coloring */
.num-pos { color: var(--forest); }
.num-neg { color: var(--rust); }

/* KPI 卡片 */
.kpi-card {
  background: var(--card);
  border: 1px solid var(--rule);
  padding: 24px;
  position: relative;
  transition: border-color 180ms ease;
}
.kpi-card:hover { border-color: var(--ink-soft); }
.kpi-eyebrow {
  font-family: "JetBrains Mono", monospace;
  font-size: calc(10px * var(--fs-scale,1));
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--ink-soft);
  display: block;
  margin-bottom: 14px;
}
.kpi-value {
  font-family: "Fraunces", "Noto Serif SC", serif;
  font-feature-settings: "tnum" 1;
  font-size: calc(30px * var(--fs-scale,1));
  font-weight: 500;
  line-height: 1.1;
  color: var(--ink);
  letter-spacing: -0.015em;
}
.kpi-currency { font-size: 0.55em; vertical-align: 0.65em; color: var(--ink-soft); margin-right: 4px; }
.kpi-delta {
  font-family: "JetBrains Mono", monospace;
  font-feature-settings: "tnum" 1;
  font-size: calc(12px * var(--fs-scale,1));
  margin-top: 10px;
}

/* 成员 avatar 颜色(填报页分组 · 按 ownerColorMap index % 5 分配) */
.avatar-0 { background: #2f5d50 !important; } /* forest 深绿 */
.avatar-1 { background: #6b5b8a !important; } /* 紫灰 */
.avatar-2 { background: #3b6998 !important; } /* 蓝灰 */
.avatar-3 { background: #a77b35 !important; } /* 铜金 */
.avatar-4 { background: #4a5568 !important; } /* slate 灰(fallback / 共同) */

/* KPI 口径说明 tooltip · v0.4.13 */
.kpi-info-wrap {
  position: relative;
  display: inline-flex;
  align-items: center;
  vertical-align: middle;
}
.kpi-info-btn {
  display: inline-flex; align-items: center; justify-content: center;
  width: 14px; height: 14px;
  border: none; color: var(--ink-subtle);
  cursor: pointer; margin-left: 3px; vertical-align: middle;
  transition: color .2s;
  flex-shrink: 0; padding: 0; background: none;
}
.kpi-info-btn:hover { color: var(--brass-deep); }
/* 2026-07-19 · 移动可点性:视觉 14px 的小图标,触摸热区扩到 ~38px(::after 不占布局,只吃点击) */
.kpi-info-btn { position: relative; }
.kpi-info-btn::after, .tap::after {
  content: ''; position: absolute; inset: -12px;
}
.tap { position: relative; }
.kpi-info-panel {
  /* absolute 浮层 · 不撑开 parent card 布局 */
  position: absolute;
  top: calc(100% + 4px);
  left: 50%;
  transform: translateX(-50%);
  z-index: 50;
  padding: 8px 10px;
  background: var(--card); border: 1px solid var(--rule-soft);
  border-left: 3px solid var(--brass); border-radius: 4px;
  font-size: calc(11px * var(--fs-scale,1)); line-height: 1.6; color: var(--ink-soft);
  min-width: 220px; max-width: 320px; width: max-content;
  font-family: "Source Serif 4", "Noto Serif SC", serif;
  box-shadow: 0 4px 12px rgba(26,23,20,.12);
  /* 防 panel 把文字从 uppercase 继承过来 */
  text-transform: none; letter-spacing: normal;
}
/* v0.5.3 · 口径(formula)+ 真实计算数值(calc)双层 */
.kpi-info-formula { display: block; }
.kpi-info-calc {
  display: block;
  margin-top: 7px; padding-top: 7px;
  border-top: 1px dashed var(--rule-soft);
  font-family: "JetBrains Mono", ui-monospace, monospace;
  font-size: calc(10.5px * var(--fs-scale,1)); line-height: 1.7;
  color: var(--ink);
  /* 多行分项用 \n 软换行 · 不折叠空白 */
  white-space: pre-line;
  text-transform: none; letter-spacing: normal;
}
/* v0.5.5 · 报表「已关账」朱印章(横排小印 · 单行不换行 · 仅快照态显)*/
.report-seal {
  display: inline-flex; align-items: center; justify-content: center;
  flex-shrink: 0; white-space: nowrap;
  color: var(--rust);
  border: 2px solid var(--rust);
  border-radius: 5px;
  background: rgba(156, 74, 42, .05);
  box-shadow: inset 0 0 0 2px rgba(156, 74, 42, .14);
  transform: rotate(-4deg);
  padding: 3px 6px 3px 9px;   /* 右侧略收:letter-spacing 末位补偿 */
  font-family: "Noto Serif SC", serif; font-weight: 700;
  font-size: calc(13px * var(--fs-scale,1)); letter-spacing: 3px; line-height: 1;
  opacity: .92;
}
@media (max-width: 640px), (max-height: 479px) {
  .report-seal { font-size: calc(12px * var(--fs-scale,1)); letter-spacing: 2px; padding: 2px 5px 2px 7px; }
}

/* v0.5.6 · 报表长文目录 · PC 右侧常驻树状大纲 + 手机左上唤醒钮 + 底部 sheet */
/* 布局自管(不依赖 Tailwind lg: · 重页 JIT 不稳)· 窄屏单列+FAB · ≥1024px 双列 */
.toc-cols-main { min-width: 0; }
.toc-rail { display: none; }
@media (min-width: 1024px) and (min-height: 480px) {
  .toc-cols { display: flex; gap: 2rem; align-items: flex-start; }
  .toc-cols-main { flex: 1 1 0%; min-width: 0; }
  /* order:-1 把目录栏放到左列(内容在右)· DOM 仍内容优先(阅读/可访问顺序不变)*/
  .toc-rail { display: block; order: -1; position: sticky; top: 88px; align-self: flex-start; width: 224px; flex-shrink: 0; }
}
.toc-head { font-family:"JetBrains Mono",monospace; font-size: calc(10px * var(--fs-scale,1)); letter-spacing:.18em; text-transform:uppercase; color:var(--ink-subtle); padding:0 0 8px 14px; }
.toc-tree { position: relative; }
.toc-node { display:block; position:relative; text-decoration:none; line-height:1.35;
  font-family:"Source Serif 4","Noto Serif SC",serif; color:var(--ink-soft);
  padding:6px 8px 6px 14px; border-left:2px solid transparent;
  transition:color .15s, border-color .15s, background .15s; }
.toc-node .lbl { font-size: calc(13px * var(--fs-scale,1)); }
.toc-node:hover { color:var(--brass-deep); background:var(--card-soft); }
/* active:aria-current 作样式钩子(a11y)· 朱铜 + 左脊 + 底色 */
.toc-node[aria-current="true"] { color:var(--brass-deep); font-weight:600; border-left-color:var(--brass-deep); background:var(--card-soft); }
.toc-node.ancestor { color:var(--ink); }
/* 子层:缩进 + 竖向引导线 + 横向树枝(支持未来多层嵌套)*/
.toc-children { margin-left:13px; border-left:1.5px solid var(--rule-soft); }
.toc-children > .toc-node { padding-left:16px; }
.toc-children > .toc-node .lbl { font-size: calc(12px * var(--fs-scale,1)); }
.toc-children > .toc-node::before { content:''; position:absolute; left:-1px; top:15px; width:10px; height:1.5px; background:var(--rule-soft); }
.toc-children > .toc-node[aria-current="true"]::before { background:var(--brass-deep); }
/* 手机:左上角唤醒钮(icon-only 小圆钮)+ 底部 sheet · ≥1024px 隐藏(用右栏) */
/* v0.11 · 移动端目录浮钮挪到左下,与隐私浮控(#priv-float, bottom:18px)叠成同一操作区 */
/* v1.6 UED(review A1)· 浮钮从左下改右下 + iOS 安全区:左下是内容起始边,曾压住金额/图例/筛选行 */
.toc-fab { position:fixed; right:14px; bottom:calc(max(18px, env(safe-area-inset-bottom)) + 48px); z-index:60;
  width:38px; height:38px; border-radius:50%;
  background:var(--ink); color:var(--paper); border:none; box-shadow:0 3px 12px rgba(0,0,0,.22);
  display:inline-flex; align-items:center; justify-content:center; cursor:pointer;
  transition:opacity .25s ease; }
@media (min-width: 1024px) and (min-height: 480px) { .toc-fab { display: none !important; } }
.toc-sheet-mask { position:fixed; inset:0; background:rgba(26,23,20,.4); z-index:70; opacity:0; pointer-events:none; transition:opacity .2s; }
.toc-sheet-mask.open { opacity:1; pointer-events:auto; }
.toc-sheet { position:fixed; left:0; right:0; bottom:0; z-index:80; background:var(--card);
  border-top-left-radius:16px; border-top-right-radius:16px; box-shadow:0 -8px 32px rgba(0,0,0,.22);
  transform:translateY(110%); transition:transform .26s cubic-bezier(.22,1,.36,1);
  padding:8px 6px max(16px, env(safe-area-inset-bottom)); max-height:72vh; overflow:auto; }
.toc-sheet.open { transform:translateY(0); }
.toc-sheet-handle { width:40px; height:4px; border-radius:2px; background:var(--rule); margin:8px auto 4px; }
.toc-sheet-row { display:flex; align-items:center; justify-content:space-between; padding:2px 12px 6px; }
.toc-sheet-row .toc-head { padding:0; }
.toc-sheet-x { width:32px; height:32px; border:none; background:none; color:var(--ink-soft); cursor:pointer; font-size: calc(20px * var(--fs-scale,1)); line-height:1; }
.toc-sheet .toc-node { padding-top:11px; padding-bottom:11px; min-height:44px; box-sizing:border-box; }
.toc-sheet .toc-node .lbl { font-size: calc(15px * var(--fs-scale,1)); }
/* v1.4.x · 目录 sheet 打开时,收起左下角浮钮(隐私眼睛 + 目录浮钮),避免压住 sheet 底部条目 */
body.toc-open #priv-float, body.toc-open .toc-fab { display: none !important; }
/* v1.4.x · 旭日「分析指标 / 看板」横滑行的"还有更多"提示:右缘渐隐 + › 箭头,溢出且未滑到底时出现 */
.lens-hscroll { position: relative; }
.lens-hscroll > .overflow-x-auto { scrollbar-width: none; }
.lens-hscroll > .overflow-x-auto::-webkit-scrollbar { display: none; }
/* v1.6 UED(review A9)· iOS 硬约束:
   ① overscroll-behavior-x:contain —— 横滑到尽头继续拖不再触发 Safari 返回/前进手势(此前会莫名离开页面)
   ② scroll-snap —— 横滑停在完整 pill/卡片边界,不再半个被截断 */
.lens-hscroll > .overflow-x-auto,
.hscroll-x {
  overscroll-behavior-x: contain;
  -webkit-overflow-scrolling: touch;
  scroll-snap-type: x proximity;
}
.hscroll-x { overflow-x: auto; scrollbar-width: none; }
.hscroll-x::-webkit-scrollbar { display: none; }
.lens-hscroll > .overflow-x-auto > * > *,
.hscroll-x > * { scroll-snap-align: start; }
/* 内部纵向滚动容器不带动整页(iOS momentum 串联) */
.toc-sheet, .scroll-contain { overscroll-behavior: contain; }
/* 图表容器:长按不弹系统「拷贝图片」菜单(review A9 ⑦) */
.chart-card canvas, canvas[id], .echart-box { -webkit-touch-callout: none; }
.lens-hscroll::after {
  content: '\203A'; position: absolute; top: 0; right: 0; bottom: 5px; width: 34px;
  display: flex; align-items: center; justify-content: flex-end; padding-right: 5px;
  color: var(--brass-deep); font-family: 'JetBrains Mono', monospace; font-size: 18px; font-weight: 700;
  background: linear-gradient(to left, var(--card) 38%, transparent);
  pointer-events: none; opacity: 0; transition: opacity .2s; border-radius: 0 8px 8px 0;
}
.lens-hscroll.more::after { opacity: 1; }
@media (max-width: 640px), (max-height: 479px) {
  .kpi-info-panel {
    /* 手机端:固定到屏幕顶部 · 不跟 button 位置 */
    position: fixed;
    left: 1rem; right: 1rem;
    top: 5rem; bottom: auto; /* nav h-16 + sticky top-1 ≈ 68px · 5rem=80px 避开导航 */
    transform: none;
    min-width: unset; max-width: unset; width: auto;
    font-size: calc(12px * var(--fs-scale,1));
    box-shadow: 0 4px 20px rgba(26,23,20,.18);
    animation: kpi-slide-in .3s ease-out;
  }
}
@keyframes kpi-slide-in {
  from { opacity: 0; transform: translateY(-8px); }
  to   { opacity: 1; transform: translateY(0); }
}

/* 表格 — 账册风 */
.ledger-table {
  width: 100%;
  border-collapse: collapse;
  font-feature-settings: "tnum" 1;
}
.ledger-table thead th {
  font-family: "JetBrains Mono", monospace;
  font-size: calc(10px * var(--fs-scale,1));
  font-weight: 400;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--ink-soft);
  padding: 10px 14px;
  text-align: left;
  border-bottom: 1px solid var(--ink);
}
.ledger-table thead th.num { text-align: right; }
/* v0.8 列表排序:可排序列头 + 三态三角指示(CSS 绘制,不用字形/emoji) */
.ledger-table thead th.sortable-th { cursor: pointer; user-select: none; }
.ledger-table thead th.sortable-th:hover { color: var(--ink); }
.ledger-table thead th.sortable-th::after {
  content: ""; display: inline-block; width: 0; height: 0; margin-left: 5px;
  vertical-align: middle; opacity: .28;
  border-left: 3px solid transparent; border-right: 3px solid transparent;
  border-top: 4px solid currentColor;
}
.ledger-table thead th.sortable-th[aria-sort="ascending"]::after {
  border-top: 0; border-bottom: 4px solid var(--brass-deep); opacity: 1;
}
.ledger-table thead th.sortable-th[aria-sort="descending"]::after {
  border-bottom: 0; border-top: 4px solid var(--brass-deep); opacity: 1;
}
.ledger-table tbody td {
  padding: 14px;
  border-bottom: 1px solid var(--rule-soft);
  vertical-align: middle;
  font-size: calc(14.5px * var(--fs-scale,1));
}
.ledger-table tbody td.num {
  font-family: "JetBrains Mono", monospace;
  font-variant-numeric: tabular-nums;
  text-align: right;
  letter-spacing: 0.01em;
}
.ledger-table tbody tr:hover td { background: var(--card-soft); }

/* 边栏 */
.side-rule {
  border-left: 1px solid var(--rule);
  padding-left: 24px;
}

/* 序号水印 */
.folio {
  font-family: "Fraunces", serif;
  font-feature-settings: "ss01" 1, "swsh" 1;
  font-style: italic;
  font-size: calc(76px * var(--fs-scale,1));
  line-height: 1;
  color: var(--paper-deep);
  user-select: none;
}

/* 对勾 / 状态符号 */
.tick-done {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 18px; height: 18px;
  border: 1.5px solid var(--forest);
  background: var(--forest);
  color: var(--paper);
  font-size: calc(11px * var(--fs-scale,1));
  font-weight: 700;
}
.tick-pending {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 18px; height: 18px;
  border: 1.5px dashed var(--ink-subtle);
  color: var(--ink-subtle);
}

/* 响应处理 */
@media (max-width: 720px), (max-height: 479px) {
  body { font-size: calc(14.5px * var(--fs-scale,1)); }
  /* v0.14.1 UED · 手机 2 列 KPI 卡:24px padding 偏重、挤内容 → 收紧留白节奏,值略降一档更贴合窄卡 */
  .kpi-card { padding: 16px 15px; }
  .kpi-eyebrow { margin-bottom: 10px; }
  .kpi-value { font-size: calc(24px * var(--fs-scale,1)); }
  .kpi-delta { margin-top: 8px; }
}

/* Print-像-账册的微动效 */
@keyframes fade-up {
  from { opacity: 0; transform: translateY(6px); }
  to   { opacity: 1; transform: translateY(0); }
}
.fade-in        { animation: fade-up 600ms cubic-bezier(0.2, 0.8, 0.2, 1) both; }
.fade-in-delay-1 { animation: fade-up 600ms cubic-bezier(0.2, 0.8, 0.2, 1) both; animation-delay: 100ms; }
.fade-in-delay-2 { animation: fade-up 600ms cubic-bezier(0.2, 0.8, 0.2, 1) both; animation-delay: 200ms; }
.fade-in-delay-3 { animation: fade-up 600ms cubic-bezier(0.2, 0.8, 0.2, 1) both; animation-delay: 300ms; }
.fade-in-delay-4 { animation: fade-up 600ms cubic-bezier(0.2, 0.8, 0.2, 1) both; animation-delay: 400ms; }

/* 账册装饰 — 翻页角 */
.dog-ear {
  position: relative;
}
.dog-ear::after {
  content: "";
  position: absolute;
  top: 0; right: 0;
  width: 24px; height: 24px;
  background: linear-gradient(225deg, var(--paper-deep) 50%, var(--rule-soft) 50%);
  border-left: 1px solid var(--rule);
  border-bottom: 1px solid var(--rule);
}

/* 1px 内边线(账册分栏) */
.col-rule > * + * { border-left: 1px solid var(--rule); padding-left: 24px; }

/* 移动端遮罩(envelope 风格) */
.scrim {
  position: fixed;
  inset: 0;
  background: rgba(26, 23, 20, 0.4);
  backdrop-filter: blur(2px);
  z-index: 50;
}

/* 模态弹层(信函式) */
.envelope-modal {
  background: var(--card);
  border: 1px solid var(--ink);
  box-shadow: 8px 8px 0 var(--paper-deep), var(--shadow-deep);
  position: relative;
}
.envelope-modal::before {
  content: "";
  position: absolute;
  top: -1px; left: 24px; right: 24px;
  height: 4px;
  background: var(--brass);
}

/* 选择 */
::selection {
  background: var(--brass);
  color: var(--paper);
}

/* 链接 */
a {
  color: var(--ink);
  text-decoration-color: var(--rule);
  text-underline-offset: 4px;
  transition: text-decoration-color 200ms ease;
}
a:hover { text-decoration-color: var(--brass); }

a.brass-link {
  color: var(--brass-deep);
  text-decoration-color: var(--brass-soft);
}
a.brass-link:hover { text-decoration-color: var(--brass); }

/* —— Chart palette via CSS vars —— */
.chart-card {
  background: var(--card);
  border: 1px solid var(--rule);
  padding: 24px;
}

/* Sparkline 用 */
.sparkline-pos { color: var(--forest); }
.sparkline-neg { color: var(--rust); }

/* 滚动条 */
::-webkit-scrollbar { width: 12px; height: 12px; }
::-webkit-scrollbar-track { background: var(--paper); }
::-webkit-scrollbar-thumb { background: var(--rule); border: 3px solid var(--paper); }
::-webkit-scrollbar-thumb:hover { background: var(--ink-subtle); }

/* — Hamburger summary — 隐藏默认箭头 */
summary { list-style: none; }
summary::-webkit-details-marker { display: none; }
summary::marker { content: ''; }

/* — 填报页 ledger 展开/折叠 文案随状态切换(纯 CSS · 无 JS) — */
details[open]      > summary .lg-when-closed { display: none; }
details:not([open]) > summary .lg-when-open  { display: none; }

/* — v0.7 配置引导 · 折叠式「如何获取」帮助(纯 CSS · 无 JS) — */
.help-fold > summary {
  font-family: "JetBrains Mono", monospace; font-size: calc(11px * var(--fs-scale,1));
  color: var(--brass-deep); cursor: pointer; list-style: none;
  display: inline-flex; align-items: center; gap: 5px; margin-top: 6px;
}
.help-fold > summary::-webkit-details-marker { display: none; }
.help-fold > summary::marker { content: ''; }
.help-fold > summary::before { content: '+'; font-weight: 600; }
.help-fold[open] > summary::before { content: '\2013'; } /* en-dash */
.help-fold .help-body {
  font-size: calc(13px * var(--fs-scale,1)); color: var(--ink-soft); line-height: 1.85;
  margin-top: 8px; padding: 12px 14px;
  background: var(--card-soft); border: 1px solid var(--rule-soft);
}
.help-fold .help-body ol { margin: 0; padding-left: 18px; }
.help-fold .help-body a { color: var(--brass-deep); text-decoration: underline; }

/* ============================================================
   v1.2.2 · 字号档位 · 层2/层5(issue #7)
   层2:6 个写死的 Tailwind arbitrary 字号类(全站 820 处,仅 6 个离散尺寸)
        用 calc×scale 重定义;!important 压 Play CDN 生成的绝对 px
        (仓库既有手法:lens-select .lsel-q 16px !important)。
        标准档 scale=1 → calc(Npx*1)=Npx,与现状逐像素等价。
   ============================================================ */
.text-\[8px\]  { font-size: calc(8px  * var(--fs-scale,1)) !important; }
.text-\[9px\]  { font-size: calc(9px  * var(--fs-scale,1)) !important; }
.text-\[10px\] { font-size: calc(10px * var(--fs-scale,1)) !important; }
.text-\[11px\] { font-size: calc(11px * var(--fs-scale,1)) !important; }
.text-\[12px\] { font-size: calc(12px * var(--fs-scale,1)) !important; }
.text-\[13px\] { font-size: calc(13px * var(--fs-scale,1)) !important; }

/* 层5:移动端输入框 16px 地板(<16px 聚焦触发 iOS 整页放大)。
   只在 大/特大 档生效 → 标准档输入框完全不动,零回归;
   放大档取 max(16px, 14px×scale) 保证既变大又不触发 zoom。 */
@media (max-width: 640px), (max-height: 479px) {
  html[data-fs="lg"] input,  html[data-fs="lg"] select,  html[data-fs="lg"] textarea,
  html[data-fs="xl"] input,  html[data-fs="xl"] select,  html[data-fs="xl"] textarea {
    font-size: max(16px, calc(14px * var(--fs-scale,1))) !important;
  }
}

/* v1.2.2 · 字号控件(nav 下拉 + 移动菜单行)· 高亮 = aria-pressed */
.fs-opt { display:block; width:100%; text-align:left; background:transparent; border:0; cursor:pointer;
  font-family:"JetBrains Mono",monospace; font-size: calc(12px * var(--fs-scale,1)); color:var(--ink-soft);
  padding:7px 14px; white-space:nowrap; letter-spacing:.06em; }
.fs-opt:hover { background:var(--card-soft); color:var(--ink); }
.fs-opt[aria-pressed="true"] { background:var(--ink); color:var(--paper); }
.fs-opt-m { font-family:"JetBrains Mono",monospace; font-size: calc(12px * var(--fs-scale,1)); color:var(--ink-soft);
  border:1px solid var(--rule); background:var(--card); padding:5px 11px; cursor:pointer; letter-spacing:.04em; }
.fs-opt-m[aria-pressed="true"] { background:var(--ink); color:var(--paper); border-color:var(--ink); }
#fs-menu > summary::-webkit-details-marker { display:none; }
#fs-menu > summary::marker { content:''; }

/* v1.3 · 旭日分析指标选择器 */
.sun-m-off { opacity:.42; text-decoration:line-through; cursor:not-allowed; }
#sunMetricPop button { display:block; width:100%; text-align:left; background:none; border:0; cursor:pointer;
  font-family:"JetBrains Mono",monospace; font-size: calc(12px * var(--fs-scale,1)); color:var(--ink-soft);
  padding:6px 14px; white-space:nowrap; }
#sunMetricPop button:hover { background:var(--card-soft); color:var(--ink); }
#sunMetricPop button.on { background:var(--ink); color:var(--paper); }
#sunMetricPop button.off { opacity:.42; text-decoration:line-through; cursor:not-allowed; }

/* ============================================================
   v1.6 · UED review 修复(docs/ued-review-2026-07.md)
   ============================================================ */

/* 补 .pill-mute —— 3 处模板在用(nav 字号钮/隐私钮 · dashboard「本期未填收支」)但此前无定义,
   语义 = 中性/未启用/无数据(spec §6.2 状态标签第 4 档) */
.pill-mute { background: transparent; border-color: var(--rule-soft); color: var(--ink-subtle); }
button.pill-mute:hover, summary.pill-mute:hover { border-color: var(--rule); color: var(--ink-soft); }

/* PC 上目录 sheet 与遮罩彻底不参与渲染(此前仅靠 transform 移出视口,仍在合成层里) */
@media (min-width: 1024px) and (min-height: 480px) {
  .toc-sheet, .toc-sheet-mask { display: none !important; }
}

/* review A5 · 1px 发丝网格。
   旧写法 `gap-px bg-rule` 靠容器底色从缝隙透出来画线 —— 格子数不满一行时,空位也透出米灰色,
   形成突兀色块(accounts 9 类型 ÷ 6 列空 3 格 / checkup 5 KPI ÷ 2 列空 1 格)。
   改为:容器白底 + 上左外边线,子项各自画右下线 → 线条一致,空位自然是白底。 */
.grid-hairline { background: var(--card); border-top: 1px solid var(--rule); border-left: 1px solid var(--rule); }
.grid-hairline > * { border-right: 1px solid var(--rule); border-bottom: 1px solid var(--rule); }

/* review B3-4 · 表格窄列里的中文被挤成竖排 → 关键列不换行 */
.ledger-table td.nowrap, .ledger-table th.nowrap { white-space: nowrap; }

/* review B3-3 · 列表行「更多操作」下拉:高频操作留行内,低频收进 ⋯(spec §6.1 行内 ≤3) */
.row-more { position: relative; display: inline-block; vertical-align: middle; }
.row-more > summary {
  list-style: none; cursor: pointer;
  display: inline-flex; align-items: center; justify-content: center;
  width: 32px; height: 30px; color: var(--ink-subtle);
  border: 1px solid transparent; transition: color .15s, border-color .15s;
}
.row-more > summary::-webkit-details-marker { display: none; }
.row-more > summary::marker { content: ''; }
.row-more > summary:hover { color: var(--ink); border-color: var(--rule); }
.row-more[open] > summary { color: var(--ink); border-color: var(--rule); }
.row-more-pop {
  position: absolute; right: 0; top: 100%; z-index: 45; min-width: 156px;
  background: var(--card); border: 1px solid var(--ink);
  box-shadow: 4px 4px 0 var(--paper-deep), var(--shadow-deep);
  padding: 4px 0; text-align: left;
}
.row-more-pop > a, .row-more-pop button {
  display: block; width: 100%; text-align: left; background: none; border: 0; cursor: pointer;
  padding: 8px 14px; font-family: "JetBrains Mono", ui-monospace, monospace;
  font-size: calc(11px * var(--fs-scale,1)); color: var(--ink-soft); white-space: nowrap;
}
.row-more-pop > a:hover, .row-more-pop button:hover { background: var(--card-soft); color: var(--ink); }
/* 不可逆操作用 rust 描边语义(spec §6.1 danger:有色=要你做决定) */
.row-more-pop .row-more-danger { color: var(--rust); }
.row-more-pop .row-more-danger:hover { background: rgba(156,74,42,.07); color: var(--rust); }

/* review B2-2 · 填报行折叠(移动端 13.9 屏 → 约 3 屏)· summary 满足 40px 触摸高度 */
.entry-fold > summary {
  list-style: none; cursor: pointer;
  display: flex; align-items: center; gap: 6px;
  min-height: 40px; margin-top: 6px; padding-top: 8px;
  border-top: 1px solid var(--rule-soft);
  font-family: "JetBrains Mono", ui-monospace, monospace;
  font-size: calc(11px * var(--fs-scale,1)); letter-spacing: .08em;
  color: var(--brass-text, #85642F);
}
.entry-fold > summary::-webkit-details-marker { display: none; }
.entry-fold > summary::marker { content: ''; }
.entry-fold > summary:hover { color: var(--ink); }
.entry-fold > summary .fold-chev { transition: transform .18s ease; flex-shrink: 0; }
.entry-fold[open] > summary .fold-chev { transform: rotate(180deg); }
.entry-fold[open] > summary .fold-when-closed { display: none; }
.entry-fold:not([open]) > summary .fold-when-open { display: none; }

/* review A4 · 分析页顶部口径控件折叠条(窄屏收起 / PC 恒展开且不显示 summary → 零回归) */
.filter-fold > summary {
  list-style: none; cursor: pointer;
  display: flex; align-items: center; gap: 7px;
  min-height: 44px; padding: 0 14px; margin-bottom: 4px;
  background: var(--card); border: 1px solid var(--rule);
  font-family: "JetBrains Mono", ui-monospace, monospace;
  font-size: calc(11px * var(--fs-scale,1)); letter-spacing: .06em; color: var(--ink-soft);
}
.filter-fold > summary::-webkit-details-marker { display: none; }
.filter-fold > summary::marker { content: ''; }
/* v1.6.1 用户反馈②·箭头方向要符合直觉:收起 = ›(向右,「点开」)· 展开 = ⌄(向下)。
   此前是 ⌄ / ⌃,收起态看不出「这里能点开」。 */
.filter-fold > summary .fold-chev { transition: transform .18s ease; flex-shrink: 0; transform: rotate(-90deg); }
.filter-fold[open] > summary .fold-chev { transform: rotate(0deg); }
.filter-fold[open] > summary .fold-when-closed { display: none; }
.filter-fold:not([open]) > summary .fold-when-open { display: none; }
/* 收起态的行动号召:明确写出点开能干什么,而不是一个「改」字 */
.filter-fold > summary .fold-cta { color: var(--brass-text, #85642F); white-space: nowrap; }
.filter-fold:not([open]) > summary { border-color: var(--brass); background: var(--card-soft); }
@media (min-width: 768px) and (min-height: 480px) { .filter-fold > summary { display: none; } }
/* 横屏 iframe 短边只有 390 但确是宽屏视图 → 把手照旧隐藏 */
@media (min-width: 768px) { html.ls-wide .filter-fold > summary { display: none; } }

/* review B1-6 · KPI 带:窄屏「英雄数字 + 横滑 chip」。
   主 KPI(第一个)近满宽 + 字号升档,其余横滑 —— 五个同等大小的数字等于没有重点。 */
/* v1.6.1 用户反馈③ · 横滑方案退回网格。
   核心指标的要求是「一目了然」—— 横滑意味着有指标藏在屏幕外,得划一下才知道,这与目的相悖。
   改法:保留主次(净资产跨两列 + 大字),但把格子做紧凑(padding / eyebrow / value 全部收一档),
   让 5 个指标在一屏内同时可见。
   !important 必要:Tailwind Play CDN 在 style.css 之后注入,其 .grid-cols-2 同为单类选择器。 */
@media (max-width: 767px), (max-height: 479px) {
  html:not(.ls-wide) .kpi-band { display: grid !important; grid-template-columns: 1fr 1fr !important; }
  html:not(.ls-wide) .kpi-band > * { padding: 11px 12px !important; }
  html:not(.ls-wide) .kpi-band > * .kpi-eyebrow { margin-bottom: 5px; font-size: calc(9.5px * var(--fs-scale,1)); letter-spacing: .12em; }
  html:not(.ls-wide) .kpi-band > * .kpi-value { font-size: calc(19px * var(--fs-scale,1)); line-height: 1.15; }
  html:not(.ls-wide) .kpi-band > * .kpi-delta { margin-top: 4px; font-size: calc(10px * var(--fs-scale,1)); }
  /* 主指标:跨两列 + 字号升档,仍是视觉锚点 */
  html:not(.ls-wide) .kpi-band > *:first-child { grid-column: 1 / -1 !important; padding: 13px 14px !important; }
  /* 其余一律单列 —— 模板里第 5 个 KPI 原本带 col-span-2(那是「5 个平铺、最后一个居中」的老布局),
     现在主指标已占满第一行,第 5 个若还跨列就会让第 4 个旁边空一格。 */
  html:not(.ls-wide) .kpi-band > *:not(:first-child) { grid-column: auto !important; }
  html:not(.ls-wide) .kpi-band > *:first-child .kpi-value { font-size: calc(30px * var(--fs-scale,1)); }
  html:not(.ls-wide) .kpi-band > *:first-child .kpi-delta { font-size: calc(11px * var(--fs-scale,1)); }
}

/* review B3-2 · 类型汇总带:窄屏由多行网格改横滑单行(9 个类型曾占满整个首屏 ~950px) */
@media (max-width: 767px), (max-height: 479px) {
  html:not(.ls-wide) .summary-band {
    display: flex !important; overflow-x: auto;
    overscroll-behavior-x: contain; -webkit-overflow-scrolling: touch;
    scroll-snap-type: x proximity; scrollbar-width: none;
  }
  html:not(.ls-wide) .summary-band::-webkit-scrollbar { display: none; }
  html:not(.ls-wide) .summary-band > * { flex: 0 0 44% !important; scroll-snap-align: start; }
}

/* spec §5 · 尊重系统「减少动态效果」偏好 —— 前庭障碍用户会因动画产生生理不适。
   功能性 loader(htmx-indicator / animate-spin)保留,装饰性动画一律停。 */
@media (prefers-reduced-motion: reduce) {
  .fade-in, .fade-in-delay-1, .fade-in-delay-2, .fade-in-delay-3, .fade-in-delay-4 {
    animation: none !important; opacity: 1 !important; transform: none !important;
  }
  #page-overlay, #page-overlay * { animation: none !important; }
  #page-progress::before { animation: none !important; }
  .kpi-info-panel { animation: none !important; }
  .toc-sheet { transition-duration: .01ms !important; }
}

/* review B1-7 · 资产透视三个区块(旭日/排行/交叉表)靠 JS 异步填充,填充前是三个大空白框,
   用户不知道是坏了还是在算 → 给统一的计算中占位。JS 渲染时会覆盖。 */
.lens-skeleton {
  display: flex; align-items: center; justify-content: center; gap: 9px;
  min-height: 120px; height: 100%;
  font-family: "JetBrains Mono", ui-monospace, monospace;
  font-size: calc(11px * var(--fs-scale,1)); letter-spacing: .08em; color: var(--ink-subtle);
}

/* review B3-7 · ★ 在 JetBrains Mono 里没有字形,回落后被渲染成点/方块(实测「风险 ······」)。
   星级单独指定有该字形的字体族。 */
.stars {
  font-family: "Noto Serif SC", "Segoe UI Symbol", "Apple Symbols", sans-serif;
  letter-spacing: .04em;
}

/* v1.6.1 的 .rot-* 局部旋转层已删(JS 已无引用)。
   它当年就用对了典范写法 `width:100dvh; height:100vw; transform:translate(100vw,0) rotate(90deg)`,
   只错了一个单位:注释里写「用 dvh 而非 vh,因为 iOS 地址栏收放会改变 vh」—— **正好说反了**。
   vh 是 large viewport(工具栏收起时的高度,恒定),dvh 才是会随工具栏变化的那个。
   用 dvh 当固定尺寸 → 工具栏一收放盒子就变 → 重排。这个误解一路带到 v1.6.6 改成 JS 量 px。 */

/* 触发按钮(仅窄屏出现:桌面本来就宽) */
.landscape-btn { display: none; }
@media (pointer: coarse) { .landscape-btn { display: inline-flex; } }

/* ── v1.6.15 · 整页横屏 · **原地**改断点(不再用 iframe 重载页面)────────────
   历史:v1.6.6–v1.6.14 用同源 iframe 拿"独立 viewport"。有效,但点一下 = 一次完整
   后端渲染 + 12 个脚本重跑(实测 1362ms),而且新文档必然丢滚动位置。
   现在断点由 landscape.js 原地重编译(Play CDN 运行时编译器 · 实测 114ms),
   这里只负责把布局宽度锁成屏幕**长边**,并在设备竖屏时转 90°。

   尺寸用交换后的视口单位(与 v1.6.8 调研的通行写法同一套):
     设备竖屏:width=100vh(长边)· height=100vw(短边)· 转 90°
     设备横屏:width=100vw(长边)· height=100vh(短边)· 不转
   两种情况都是「长边 × 短边」= 同一个物理矩形 → 转手机零重排,且切换由媒体查询完成。
   `max-width: 479px` 是软键盘护栏(竖屏弹键盘会让 orientation 翻成 landscape · SO 8883163)。 */
html.ls-wide { overflow: hidden; }
html.ls-wide > body {
  position: fixed; top: 0; left: 0; margin: 0;
  width: 100vw; height: 100vh;
  /* body 自带 Tailwind `min-h-screen`(min-height:100vh)。不清掉它,height 就被压过去 ——
     实测 body 变成 844×844(应为 844×390),旋转后底部整段跑到屏外,
     连 position:fixed 的退出钮都被算到屏外(rect 3964,730)。 */
  min-height: 0 !important;
  overflow-y: auto; overflow-x: hidden;
  overscroll-behavior: contain; -webkit-overflow-scrolling: touch;
  transform-origin: 0 0; transform: none;
}
@media (orientation: portrait) and (max-width: 479px) {
  html.ls-wide > body {
    width: 100vh; height: 100vw;
    transform: translate(100vw, 0) rotate(90deg);
  }
}

/* 退出钮:跟着 body 一起转,位置天然正确。
   内缩量按 iPhone 圆角给足 —— 用户反馈「会被 iPhone 的圆角遮挡导致按不稳」:
   iPhone 的屏幕圆角半径约 44–55pt,贴边 8px 的按钮有一角落在圆角外侧。
   右/上各留 26px,并把 nav 的右侧预留同步加大(见 .nav-inner padding-right)。 */
/* 退出钮由 landscape.js 放进 .nav-actions(随 sticky 导航常驻)。
   不用 position:fixed —— body 被 transform 后 fixed 的包含块变成 body,会跟着内容滚走;
   放进导航行同时解决「被 iPhone 屏幕圆角切到、按不稳」(nav-inner 自带内距)。 */
.ls-exit {
  display: inline-flex; align-items: center; gap: 5px;
  /* v1.6.16 · 用户反馈「经常点击没反应,要点很多次」。
     旧值 min-height:26px —— 旋转后它在屏幕上只有 26px 宽的一条,远低于 iOS HIG 的 44pt
     最小触摸目标,拇指很容易点在边上。加高到 34px,并把整行抬到 44px(见 .nav-inner)。
     touch-action:manipulation 去掉双击缩放的 300ms 等待(等待期内的点击会被吞)。 */
  min-height: 34px; padding: 0 12px; margin-left: 8px; cursor: pointer;
  touch-action: manipulation; -webkit-tap-highlight-color: rgba(26,23,20,.18);
  background: rgba(26,23,20,.88); color: var(--paper); border: none; border-radius: 3px;
  font-family: "JetBrains Mono", ui-monospace, monospace;
  font-size: calc(11px * var(--fs-scale,1)); letter-spacing: .1em;
  backdrop-filter: blur(4px);
}
.ls-exit:active { transform: translateY(1px); }

/* ── v1.6.9 · 普通模式:手机横屏时把内容钉在设备坐标系(方案 B,用户选定)──────
   效果 = 就像开了系统的「竖屏方向锁定」,只对本 app 生效:
   转手机时页面在屏幕上**一动不动**,要读还得把手机转回来。

   为什么能做到零重排:
     · body 盒子 = 100vh × 100vw = 短边 × 长边 = **竖屏那个形状**(视口单位在横屏下自动交换)
     · 排版宽度仍是短边 → 与竖屏逐像素相同(断点也已在 v1.6.7 改成看短边)
     · 反向旋转把 OS 的旋转抵消掉 → 内容在设备上的位置不变

   旋转符号必须跟着设备转向走(v1.6.8 记录的正是这个风险):
     screen.orientation.angle 的定义 = viewport 相对自然方向**顺时针**转过的角度,
     要抵消就得转 -angle。angle 90(设备逆时针转)→ -90°;angle 270(设备顺时针转)→ +90°。
     angle 由 landscape.js 读出并挂 html.ori-cw(iOS 16.4+ 有 screen.orientation,
     更老的回落 window.orientation)。判错的表现是内容上下颠倒 —— 一个 class 之差。

   旋转量:绕左上角转 -90° 后盒子落到 y 轴负侧 → 下移一个盒子宽度(100vh);
   转 +90° 后落到 x 轴负侧 → 右移一个盒子高度(100vw)。

   护栏:pointer:coarse 挡 PC 矮窗 · min-width:480 挡竖屏软键盘假横屏(SO 8883163 · 112★)
   · :not(.ls-on) 让主动横屏模式不受影响 · :not(.ls-wide) 让 iframe 内不受影响。

   fixed 浮层(浮钮 / toast)会以被 transform 的 body 为包含块 → 自动跟着一起转,
   位置天然正确,不需要单独校正。 */
@media (pointer: coarse) and (orientation: landscape) and (max-height: 479px) and (min-width: 480px) {
  html:not(.ls-wide) { overflow: hidden; }
  html:not(.ls-wide) > body {
    position: fixed; top: 0; left: 0; margin: 0;
    width: 100vh; height: 100vw;
    overflow-y: auto; overflow-x: hidden;
    overscroll-behavior: contain; -webkit-overflow-scrolling: touch;
    transform-origin: 0 0;
    transform: translate(0, 100vh) rotate(-90deg);
  }
  html.ori-cw:not(.ls-wide) > body {
    transform: translate(100vw, 0) rotate(90deg);
  }
  /* 方案 B 固有代价:body 被 transform 之后,它内部所有 position:fixed 浮层的包含块
     从视口变成了 body 盒子。这些浮层的几何(inset-x-0 / bottom:0 / translateY(110%) 收起态)
     都是按「未旋转的视口」写的,放进旋转容器就会错位 —— 实测目录抽屉会漏进屏内、
     顶部进度条会横向溢出 988px。
     冻结态的语义是「用户误转了手机、马上会转回来」的过渡态,不需要这些浮层 →
     几何脆弱的一律藏掉,只留内容本身 + 两个小圆浮钮(它们随 body 一起转,位置自洽,
     而且方向钮必须留着:用户可能就是想横着拿再点开横屏视图)。 */
  html:not(.ls-wide) #toc-sheet,
  html:not(.ls-wide) .toc-sheet,
  html:not(.ls-wide) .toc-sheet-mask,
  html:not(.ls-wide) .toc-fab,
  html:not(.ls-wide) #page-progress,
  html:not(.ls-wide) #toast-stack { display: none !important; }
}

/* 旋转遮帘(普通模式):iOS 自己的旋转动画抹不掉,盖成纯纸面就看不出在转 */
html.ori-turning > body { background: var(--paper); }
html.ori-turning > body > * { opacity: 0 !important; }

/* 嵌套态(iframe 内)· 不再出现横屏入口,避免套娃 */
html.ls-wide #ori-float, html.ls-wide .landscape-btn { display: none !important; }

/* v1.6.10 · 横屏模式的导航条:加回来,但按 844×390 重排 ——————————————
   v1.6.8 我把它整个藏了,理由是「844 宽放不下、390 高太贵」。用户要求加回来 ——
   这是对的:藏掉能力不是解决排版问题的办法。真正要做的是给横屏一套自己的尺度。

   844 宽的账本(实测):退出钮占 ~112px 必须留出 → 可用 ~700px;
   7 个 tab 压到 10px + 13px 间距 ≈ 268px,加印章 20px ≈ 310px —— 宽度其实很宽裕。
   v1.6.8 之所以折行,不是 tab 太多,是 gap-12(48px)+ gap-7(28px)+ 完整品牌文字
   + 版本徽记 + 字号钮 + 隐私钮 + 账期 pill + 用户名 一起挤的结果。

   390 高才是真正稀缺的:导航从 64px 压到 38px,省下的 26px 直接给内容。
   取舍:品牌只留印章(文字/版本在这个高度里是纯消耗)· 右侧那组整组收起
   (隐私有右下浮钮、字号退出再调),换来 7 个 tab 全部一行放下。 */
html.ls-wide > body > header {
  position: sticky; top: 0;
  /* 横屏态去掉毛玻璃:backdrop-filter 在被 transform 的容器里是 iOS 已知的
     命中测试/合成干扰源,而这里它只是装饰(纸面本来就不透明感强)。 */
  backdrop-filter: none !important; -webkit-backdrop-filter: none !important;
  background: var(--paper) !important;
}
html.ls-wide .nav-inner {
  height: 44px !important;   /* 44 = iOS 最小触摸目标;内含 34px 高的钮 */
  padding-left: 12px !important;
  /* 退出钮已放进 .nav-actions 参与 flex 排,不再需要为它预留右侧空白;
     只留一点内缩避开 iPhone 屏幕圆角(圆角半径约 44–55pt,贴边元素会被切)。 */
  padding-right: 26px !important;
}
html.ls-wide .nav-lead { gap: 18px !important; }
html.ls-wide .nav-brandtext { display: none !important; }
html.ls-wide .nav-inner img { width: 21px !important; height: 21px !important; }
html.ls-wide .nav-tabs {
  gap: 13px !important;
  font-size: calc(10px * var(--fs-scale, 1)) !important;
  letter-spacing: .1em !important;
}
/* 选中态下划线原本用 pb-[18px] 撑到 h-16 的底,压扁后必须重算,否则下划线跑到栏外 */
html.ls-wide .nav-tabs > a { white-space: nowrap !important; padding-bottom: 0 !important; }
html.ls-wide .nav-tabs > a[class*="border-b-2"] { padding-bottom: 4px !important; }
/* 右侧那组默认收起,但**保留隐私钮**并放进导航条 —— 原因见下面的浮钮取舍。 */
html.ls-wide .nav-actions { display: flex !important; gap: 0 !important; }
html.ls-wide .nav-actions > * { display: none !important; }
html.ls-wide .nav-actions > .nav-priv { display: inline-flex !important; min-height: 34px; touch-action: manipulation; }
html.ls-wide .nav-actions > .ls-exit { display: inline-flex !important; }

/* 浮钮取舍:隐私浮钮在 390 高的横屏里会压住内容(实测压住交叉表的「AI 解读当前视图」按钮)。
   横屏导航条里 tab 结束在 335px、退出钮从 726px 开始 —— 中间 390px 全是空的,
   把隐私钮放回导航条既不压内容又更好找。目录钮在横屏无意义(整页就一屏多点)一并收起。 */
html.ls-wide #priv-float { display: none !important; }

/* ── v1.6.13 · 横屏模式下的「本页目录」──────────────────────────────
   v1.6.10 我把目录钮一起藏了,理由是「横屏整页就一屏多点,目录无意义」。
   这个判断错了:横屏高度只有 390,一屏能看的内容反而**更少**,跨节跳转比竖屏更需要。
   交互按横屏的空间特性重排:
     · 入口:不用右下浮钮(390 高里浮钮必压内容)→ 放进导航行,与隐私钮同列
     · 面板:不用底部 sheet(竖屏的做法 —— 横屏里它会盖掉大半屏)
              → 改**右侧侧栏**:横屏宽度富余、高度稀缺,侧栏正好反过来用
     · 点条目跳转后 toc.js 原逻辑自动关闭,无需额外处理 */
/* 目录钮参与导航行的 flex 排列(由 landscape.js 搬进 .nav-actions)——
   不用 position:fixed 摆坐标:那样必须和隐私钮的宽度"保持相等",一变就撞。 */
html.ls-wide .nav-actions > .toc-fab {
  display: inline-flex !important;
  position: static !important;
  min-height: 34px; touch-action: manipulation;
  top: auto; right: auto; bottom: auto; left: auto;
  margin-right: 8px;
  /* 与隔壁隐私钮**同款**:.pill + .pill-mute 的描边样式 ——
     并列同级控件必须同尺度同样式(AGENTS.md 护栏 / visual-spec「并列同类元素」)。
     原来它是 38px 深色实心圆(为右下浮钮设计的),搁在描边 pill 旁边像两个系统的东西。 */
  width: auto; height: auto; border-radius: 0;
  padding: 4px 9px;
  background: transparent;
  border: 1px solid var(--rule-soft);
  color: var(--ink-subtle);
  box-shadow: none;
  opacity: 1;
}
html.ls-wide .nav-actions > .toc-fab svg { width: 14px; height: 14px; }
html.ls-wide .nav-actions > .toc-fab:hover,
html.ls-wide .nav-actions > .toc-fab:active { color: var(--ink-soft); border-color: var(--rule); }
/* top 从 38px(横屏导航栏高)起,不是 0 ——————————————————————————
   `<main>` 带 `relative z-10`,它本身就是一个**层叠上下文**;抽屉在 main 里面,
   所以 `.toc-sheet` 的 z-index:80 永远升不到 z-30 的导航之上(实测抽屉的关闭 ×
   被 nav-inner 压住)。同一个原因也让 v1.6.13 的目录浮钮被隐私钮压住。
   与其去拆 main 的层叠上下文(牵连全站),不如让抽屉从导航条下方开始 ——
   顺带导航在抽屉打开时仍可点,体验反而更好。 */
html.ls-wide .toc-sheet {
  left: auto; right: 0; top: 44px; bottom: 0;
  width: min(320px, 42vw); max-height: none;
  border-radius: 14px 0 0 14px;
  box-shadow: -8px 0 32px rgba(0,0,0,.22);
  transform: translateX(110%);
  padding: 10px 8px 12px;
}
html.ls-wide .toc-sheet.open { transform: translateX(0); }
html.ls-wide .toc-sheet-mask { top: 44px; }   /* 遮罩同样不盖导航条 */
html.ls-wide .toc-sheet-handle { display: none; }
html.ls-wide .toc-sheet .toc-node { padding-top: 9px; padding-bottom: 9px; min-height: 38px; }

/* ── 横屏的垂直节奏:390 高是真正稀缺的资源 ────────────────────────
   实测(交叉表页):header 39 + main 上内边距 30 + 标题块 mt-10(37.5)+ 标题 51
   + 说明段 53 → 首张卡片被推到 **221px = 屏高的 57%**。横屏是为了看表格,
   不是为了看留白。压缩的是间距与标题字号,**不删任何内容**。 */
html.ls-wide main { padding-top: 8px !important; padding-bottom: 14px !important; }
html.ls-wide main .mt-8, html.ls-wide main .mt-10, html.ls-wide main .mt-12 { margin-top: 8px !important; }
html.ls-wide main .mb-8, html.ls-wide main .mb-10, html.ls-wide main .mb-12 { margin-bottom: 10px !important; }
/* 页面大标题降一档(text-2xl 不动:那一档大量用在金额上,压了会伤可读性) */
html.ls-wide main .text-4xl { font-size: calc(24px * var(--fs-scale, 1)) !important; line-height: 1.2 !important; }
html.ls-wide main .text-3xl { font-size: calc(22px * var(--fs-scale, 1)) !important; line-height: 1.2 !important; }
/* 首屏印章动画在嵌套态也跳过(landscape.js 已处理),这里兜底避免遮挡 */
html.ls-wide #page-overlay { display: none !important; }

/* 横屏浮钮:与隐私眼 / 目录钮同列。
   可见性只由「触屏」决定 —— **不能带 max-width**:设备横屏时 viewport 变宽会让按钮消失。 */
#ori-float {
  position: fixed; right: 14px;
  bottom: calc(max(18px, env(safe-area-inset-bottom)) + 96px);
  z-index: 56;
  display: none;
  align-items: center; justify-content: center;
  width: 38px; height: 38px; border-radius: 50%;
  background: var(--card); color: var(--ink-soft);
  border: 1px solid var(--rule); box-shadow: 0 3px 12px rgba(0,0,0,.16);
  cursor: pointer; opacity: .62;
  transition: opacity .25s ease, border-color .18s ease;
}
@media (pointer: coarse) { #ori-float { display: inline-flex; } }
#ori-float:hover, #ori-float:active, #ori-float:focus-visible { opacity: 1; border-color: var(--ink-soft); }
/* 方向图标双态(Tabler device-mobile / device-mobile-rotated · MIT · 同款描边):
   按钮显示**目标状态** —— 竖屏时显示"横屏手机"(点它去横屏),横屏时显示"竖屏手机"。 */
.ori-ico-port { display: none; }
[aria-pressed="true"] .ori-ico-land { display: none; }
[aria-pressed="true"] .ori-ico-port { display: inline; }
#ori-float[aria-pressed="true"] { background: var(--ink); color: var(--paper); border-color: var(--ink); opacity: 1; }
body.is-scrolling #ori-float { opacity: .22; }


/* ── 并列同类图表的公共容器(v1.6.12)────────────────────────────────
   「资产配置」与「按成员分布」是语义同级、并列展示的一对图。它们的容器高度
   原来各写各的 h-[348px]/h-[262px],于是两个环一大一小 —— 用户一眼就看出不对。
   规则(见 docs/visual-spec.md「并列同类图表」):**并列同类图表共用同一个容器 class**,
   任何一侧要改高度都会同时改到另一侧,不可能再单边漂移。 */
.chart-pair-box { height: 336px; }
@media (min-width: 640px) and (min-height: 480px) { .chart-pair-box { height: 380px; } }


/* ── v1.6.16 · 打标页手机端 ─────────────────────────────────────────
   实测 390 宽下:页头两段说明 + 穿透卡 + AI 卡共约 1200px,要滑一整屏才见到第一个
   可操作控件;整页 14054px 高(62 行卡片化),保存钮在最底部。
   做法:说明收成 <details>(PC 全文常显)+ 底部常驻保存条。不删任何信息。 */
.tags-intro > summary { list-style: none; cursor: pointer; }
.tags-intro > summary::-webkit-details-marker { display: none; }
.tags-savebar {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 55;
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  padding: 9px 14px calc(9px + env(safe-area-inset-bottom));
  background: var(--paper); border-top: 1px solid var(--rule);
  box-shadow: 0 -6px 20px rgba(26,23,20,.10);
}
/* 保存条会盖住最后一行 → 给页面补底部留白 */
body:has(.tags-savebar) main { padding-bottom: 76px; }

.tags-todo-toggle {
  display: inline-flex; align-items: center; gap: 7px; margin-bottom: 12px;
  font-size: calc(12px * var(--fs-scale,1)); color: var(--ink-soft); cursor: pointer;
  min-height: 34px; touch-action: manipulation;
}
.tags-todo-toggle input { width: 16px; height: 16px; accent-color: var(--brass-deep); }
