@charset "UTF-8";
/* 个人财务看板 — 全局样式
 * UI reset Phase 2 推倒重做（Step 0b 起）·按 mockup index_new_UI_mockup.html L14–L99
 * 1:1 对齐 + N1–N10 归一化决策（见 /Users/zirui/.claude/plans/1-mockup-playful-bunny.md）
 *
 * 当前文件 = 唯一 :root + 全局基础设施 + 通用组件类骨架。
 * Step 1+ 在文件末尾追加各 view section 的样式（不再分散到 frag 内 :root）。
 */

:root {
  /* ===== UI_SPEC.md Part 0 §0.1–§0.12 全量 token（N1：唯一 :root）===== */

  /* §0.1 表面色 / 背景 */
  --bg-warm: #f3f4f6;
  --surface: #ffffff;
  --surface-2: #f5f6f7;
  --surface-tint: #fafafb;

  /* §0.2 文本色（4 级） */
  --text-1: #111827;
  --text-2: #4b5563;
  --text-3: #6b7280;
  --text-mute: #9ca3af;

  /* §0.3 边框 / 分隔线 */
  --border-1: #e5e7eb;
  --border-2: #d1d5db;
  --divider: #eaebee;

  /* §0.4 语义色（涨 / 跌 / 警告）· N3.a / N3.b */
  --up: #3c8b5a;
  --up-bg: #eaf5ee;
  --dn: #d44156;
  --dn-bg: #faeaea;
  --warn: #c46a1f;
  --warn-deep: #8a4715;
  --warn-bg: #fef6e4;

  /* §0.5 钴蓝 accent（默认 view-home 主题色）· N1.b 由 body[data-view="market"] 覆盖 */
  --accent: #2b57d4;
  --accent-deep: #1e41a8;
  --accent-lt: #e9edf8;

  /* portfolio v5 — benchmark 线专用色（仅 sec-portfolio 主图 SP500 / 沪深300 用；
     --bench-hsi 暂仅供 holdings-table 香港国家色竖线复用，无对应主图 benchmark 线） */
  --bench-spy: #5479a3;
  --bench-csi: #c8744c;
  --bench-hsi: #4a7a3a;

  /* §0.6 图表分类色（7 类，按 CATEGORY_SORT_ORDER 1:1 映射）
     · 2026-04-28 落地 6 类（N3.c）；2026-05-10 加 --chart-slate 服务 multi_asset 第 7 类 */
  --chart-blue:    #2c5f9e;
  --chart-purple:  #7c4ab5;
  --chart-teal:    #1f7a7a;
  --chart-magenta: #9e3a6b;
  --chart-sage:    #4a7a3a;
  --chart-umber:   #6b3a2c;
  --chart-slate:   #5a6b7a;  /* 多资产组合 · 中性蓝灰，语义"混合 / 组合" */
  --chart-blue-bg:    #e8f0fa;
  --chart-purple-bg:  #f2eafa;
  --chart-teal-bg:    #e4f2f2;
  --chart-magenta-bg: #f8e7ee;
  --chart-sage-bg:    #eaf2e3;
  --chart-umber-bg:   #f0e1da;
  --chart-slate-bg:   #e6e9ec;
  /* 7 序列别名：保 categorySeriesColors() 通过 --chart-series-N 读取 */
  --chart-series-1: var(--chart-blue);
  --chart-series-2: var(--chart-purple);
  --chart-series-3: var(--chart-teal);
  --chart-series-4: var(--chart-magenta);
  --chart-series-5: var(--chart-sage);
  --chart-series-6: var(--chart-umber);
  --chart-series-7: var(--chart-slate);

  /* §0.7 圆角 · N4.b */
  --radius-xs: 2px;
  --radius-sm: 4px;
  --radius-md: 8px;
  --radius-lg: 10px;
  --radius-pill: 999px;

  /* §0.8 间距尺度（4px base）· N4.d */
  --space-1: 4px;
  --space-2: 8px;
  --space-3: 12px;
  --space-4: 16px;
  --space-5: 20px;
  --space-6: 24px;
  --space-7: 32px;
  --space-8: 48px;

  /* §0.9 字号尺度 · N2.a/b/c */
  --fs-2xs: 10px;
  --fs-xs: 11px;          /* N2.c 表头 thead */
  --fs-sm: 12px;          /* N2.b 卡片标题 / chip */
  --fs-base: 13px;
  --fs-md: 14px;
  --fs-lg: 18px;
  --fs-xl: 20px;
  --fs-2xl: 22px;
  --fs-3xl: 26px;         /* N2.a section 大标题 */
  --fs-display: 32px;
  --fs-display-lg: 40px;

  /* §0.10 数字 mono 显示档位 · N2.d */
  --num-sm: 13px;
  --num-md: 16px;
  --num-lg: 22px;
  --num-xl: 32px;

  /* §0.11 阴影（2 层制）· N4.c */
  --shadow-sm: 0 1px 3px rgba(0, 0, 0, 0.06), 0 1px 2px rgba(0, 0, 0, 0.04);
  --shadow-md: 0 4px 16px rgba(0, 0, 0, 0.07), 0 1px 4px rgba(0, 0, 0, 0.05);

  /* §0.12 字体栈 · N6 双字体架构 · 字体本地自托管（vendor/fonts/ + css/fonts.css，见 ADR 0126） */
  --font-body: 'Inter', 'Noto Sans SC', 'PingFang SC', 'Helvetica Neue', -apple-system, system-ui, sans-serif;
  --mono: 'IBM Plex Mono', 'JetBrains Mono', 'SF Mono', monospace;

  /* N4.a 卡片 padding 2 档（标准 / 大浮层） */
  --card-padding: 16px 18px;
  --card-padding-lg: 24px 26px;

  /* N7 动画时长 + 缓动 */
  --motion-fast: 150ms;
  --motion-base: 200ms;
  --motion-slow: 300ms;
  --ease-standard: cubic-bezier(0.2, 0, 0, 1);

  /* ── 应用层布局 token（非 design system 但 keep zone 引用） ── */
  --layout-max-width: 1400px;
  --layout-padding-x: 24px;
  --breakpoint-mobile: 768px;
  --nav-height: 56px;
  --table-row-height: 44px;
  --table-cell-padding: 10px 16px;
  --range-btn-height: 28px;

  /* ── Legacy 别名（既有 keep-zone 样式仍消费的旧名 → 指向新 token） ── */
  --font-sans: var(--font-body);
  --color-bg: var(--bg-warm);
  --color-card: var(--surface);
  --color-border: var(--border-1);
  --color-text: var(--text-1);
  --color-text-secondary: var(--text-2);
  --color-text-muted: var(--text-3);
  --color-primary: var(--accent);
  --color-primary-hover: var(--accent-deep);
  --color-primary-soft: var(--accent-lt);
  --color-up: var(--up);
  --color-down: var(--dn);
  --color-disabled: #9e9e9e;
  --color-dirty: var(--warn);
  --color-warn-bg: var(--warn-bg);
  --color-error-bg: var(--dn-bg);
  --color-info-bg: var(--accent-lt);
  --color-info-border: var(--border-1);
  --color-link: var(--accent);
  --shadow-card: var(--shadow-sm);
}

/* 涨跌色双态（ADR 0157 新手引导）：缺省 = 绿涨红跌（上面 §0.4 默认值，--up 绿 / --dn 红）。
 * 用户在引导里选「红涨绿跌」→ bundle.upDownColor="redUp" → app.js 运行时挂 <html data-updown="redUp">。
 * 只翻这 4 个语义源变量，全站 var(--up/--up-bg/--dn/--dn-bg) 与其上的 color-mix 派生色随之整组对调；
 * 文字色 + 浅底色必须成对一起翻（只翻文字会出现红字配浅绿底的违和组合）。
 * 净值线已被 ADR 0156 改读钴蓝 --accent、与涨跌解耦，不受本翻转影响。 */
:root[data-updown="redUp"] {
  --up: #d44156;
  --up-bg: #faeaea;
  --dn: #3c8b5a;
  --dn-bg: #eaf5ee;
}

@media (max-width: 768px) {
  :root {
    --layout-padding-x: 12px;
    --nav-height: 48px;
  }
}

/* N1.b · view-market scoped accent → 蓝色（mockup L2840） */
body[data-view="market"] {
  --accent: var(--chart-blue);
  --accent-deep: #234a7c;
  --accent-lt: var(--chart-blue-bg);
}

/* ─── 全局基础设施 ──────────────────────────────────────────────────────── */

*,
*::before,
*::after {
  box-sizing: border-box;
}

/* HTML5 `hidden` 属性兜底 —— 作者 CSS 中 `display: flex/grid/...` 与 UA `[hidden]
 * { display: none }` 选择器同优先级（均 0,1,0），后定义者赢 → 作者 CSS 永远覆盖
 * 掉 UA 的 hidden 行为，导致 `el.hidden = true` 视觉上完全失效（banner / loading /
 * view-market / app-error / dialog 等均依赖此语义）。统一加 !important 兜底，所有
 * 后续组件 CSS 不再需要单独写 `&[hidden] { display: none }`。 */
[hidden] {
  display: none !important;
}

body {
  margin: 0;
  background: var(--bg-warm);
  color: var(--text-1);
  font-family: var(--font-body);
  font-size: var(--fs-base);
  line-height: 1.5;
}

.tabular,
.num {
  font-variant-numeric: tabular-nums;
}

/* ─── 顶部导航（fixed 56px + nav-meta 右侧容器） ─────────────────────────── */

#app-header {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: 50;
  height: var(--nav-height);
  background: var(--surface);
  border-bottom: 1px solid var(--border-1);
}

#app-nav {
  max-width: var(--layout-max-width);
  margin: 0 auto;
  height: 100%;
  padding: 0 var(--layout-padding-x);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-4);
}

.tabs {
  display: flex;
  align-items: center;
  gap: var(--space-2);
}

.tab-btn {
  appearance: none;
  border: 0;
  background: transparent;
  cursor: pointer;
  height: var(--nav-height);
  padding: 0 var(--space-3);
  font-family: var(--font-body);
  font-size: var(--fs-md);
  line-height: 22px;
  font-weight: 400;
  color: var(--text-1);
}

.tab-btn.is-active {
  font-weight: 600;
  box-shadow: inset 0 -2px 0 0 var(--accent);
}

.tab-btn:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

/* nav-meta：右侧容器（Step 8 落地双灯泡 + 时间文字；本 step 仅占位 + 容纳 status-bar） */
.nav-meta {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  min-width: 0;
}

/* ─── Step 8 · 顶部 nav 双灯泡 + 时间文字（mockup L141–L171 形态） ──────── */

.freshness-pair-group {
  display: flex;
  align-items: center;
  gap: var(--space-4);
  font-family: var(--font-body);
  font-variant-numeric: tabular-nums;
  font-size: 11px;
  letter-spacing: 0.02em;
  color: var(--text-3);
  font-variant-numeric: tabular-nums;
  flex-shrink: 0;
  min-width: 0;
  white-space: nowrap;
}

.freshness-pair {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  position: relative; /* .freshness-tooltip absolute 定位 anchor */
}

/* 问号光标与 tooltip 同开关：仅异常态（有 tooltip 可弹）才提示 hover，
 * 避免 happy path 光标变问号却啥都不弹（光标承诺与实际脱节）*/
.freshness-pair[data-has-tooltip="1"] {
  cursor: help;
}

/* ─── 自定义 tooltip popover（替代 native title，~120ms 出现） ─────────
 * 设计：
 *   - 默认隐藏（opacity 0 + pointer-events none）；hover 父 .freshness-pair 触发
 *   - 从父元素下沿弹出，距 nav 6px 间距；最大宽度 320px 自动换行
 *   - 第一行 msg 用 --text-1 主色；第二行 error 用 --text-3 灰字 + 1px 小字
 *   - 双路异常多行时每个 .freshness-tooltip-line 独立块，gap 6px
 *   - 仅 [data-has-tooltip="1"] 才走 :hover 显示，避免 happy path 空 tooltip 闪烁
 */
.freshness-tooltip {
  position: absolute;
  top: calc(100% + 6px);
  left: 0;
  z-index: 100;
  display: flex;
  flex-direction: column;
  gap: 6px;
  min-width: 200px;
  max-width: 320px;
  padding: 10px 12px;
  background: var(--surface);
  border: 1px solid var(--border-1);
  border-radius: var(--radius-md, 6px);
  box-shadow: 0 4px 16px rgba(0, 0, 0, 0.18);
  font-size: 11px;
  line-height: 1.5;
  letter-spacing: 0.01em;
  white-space: normal;
  color: var(--text-1);
  opacity: 0;
  pointer-events: none;
  transform: translateY(-2px);
  transition:
    opacity 120ms var(--ease-standard),
    transform 120ms var(--ease-standard);
}

.freshness-pair[data-has-tooltip="1"]:hover .freshness-tooltip,
.freshness-pair[data-has-tooltip="1"]:focus-within .freshness-tooltip {
  opacity: 1;
  transform: translateY(0);
}

.freshness-tooltip-line {
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.freshness-tooltip-msg {
  color: var(--text-1);
  font-weight: 500;
}

.freshness-tooltip-error {
  color: var(--text-3);
  font-size: 10px;
  font-family: var(--font-mono, var(--font-body));
  word-break: break-all;
}

/* 窄屏：右对齐避免溢出 viewport */
@media (max-width: 768px) {
  .freshness-tooltip {
    left: auto;
    right: 0;
    max-width: min(320px, calc(100vw - 32px));
  }
}

.freshness-dot {
  width: 7px;
  height: 7px;
  border-radius: var(--radius-pill);
  background: var(--text-mute);
  position: relative;
  box-shadow: 0 0 0 0 transparent;
  flex-shrink: 0;
  transition: background var(--motion-fast) var(--ease-standard);
}

.freshness-dot[data-status="ok"] {
  background: var(--up);
  animation: freshness-pulse-ok 2.4s ease-out infinite;
}

.freshness-dot[data-status="loading"] {
  background: var(--warn);
  animation: freshness-pulse-warn 1.4s ease-out infinite;
}

.freshness-dot[data-status="failed"] {
  background: var(--dn);
}

.freshness-dot[data-status="partial"] {
  background: var(--warn);
}

.freshness-dot[data-status="never"] {
  background: var(--text-mute);
  opacity: 0.55;
}

@keyframes freshness-pulse-ok {
  0%   { box-shadow: 0 0 0 0    color-mix(in srgb, var(--up) 45%, transparent); }
  70%  { box-shadow: 0 0 0 6px  color-mix(in srgb, var(--up) 0%, transparent); }
  100% { box-shadow: 0 0 0 0    color-mix(in srgb, var(--up) 0%, transparent); }
}

@keyframes freshness-pulse-warn {
  0%   { box-shadow: 0 0 0 0    color-mix(in srgb, var(--warn) 45%, transparent); }
  70%  { box-shadow: 0 0 0 5px  color-mix(in srgb, var(--warn) 0%, transparent); }
  100% { box-shadow: 0 0 0 0    color-mix(in srgb, var(--warn) 0%, transparent); }
}

@media (max-width: 768px) {
  .freshness-pair-group {
    gap: var(--space-2);
    font-size: 10px;
  }
  .freshness-pair[data-role="quote"] .freshness-text {
    display: none; /* 窄屏隐藏行情文字，仅留灯泡，避免挤压 tab */
  }
}

/* 问题 8：手机上状态区贴到 nav 右内缘 → 末尾灯 + 脉动光环（box-shadow 6px）被裁。
   三管齐下：压缩文字（省掉「 HKT」）+ 收紧间距（灯组 gap 8→4、灯↔字 6→4）让灯组整体变窄；
   再给灯组一点右 margin —— 因灯组靠 space-between 右对齐，仅压窄不会把末尾灯推离右缘，
   必须显式留白才能让末尾灯及其脉动光环完整离开屏幕边。 */
@media (max-width: 600px) {
  .freshness-pair-group {
    gap: var(--space-1);
    margin-right: var(--space-1);
  }
  .freshness-pair {
    gap: 4px;
  }
  .fresh-tz {
    display: none;
  }
}

/* ─── 主区域 ─────────────────────────────────────────────────────────── */

.app-main {
  position: relative;
  max-width: var(--layout-max-width);
  margin: 0 auto;
  padding: var(--space-7) var(--layout-padding-x);
  padding-top: calc(var(--nav-height) + var(--space-7));
}

.view-placeholder {
  margin: 0;
  font-size: var(--fs-md);
  line-height: 22px;
  color: var(--text-3);
  text-align: center;
  padding: var(--space-8) var(--space-4);
}

/* ─── 通用文字层级 ───────────────────────────────────────────────────── */

.h1 {
  margin: 0;
  font-family: var(--font-body);
  font-size: var(--fs-lg);
  line-height: 1.3;
  font-weight: 600;
  color: var(--text-2);
  letter-spacing: 0.005em;
}

.h2 {
  margin: 0;
  font-size: var(--fs-lg);
  line-height: 26px;
  font-weight: 600;
  color: var(--text-1);
}

/* N5.b · 大 section 标题（Color B 落地 2026-05-02：18px Noto Sans / 600 / text-2） */
.section-title {
  margin: 0;
  font-family: var(--font-body);
  font-size: var(--fs-lg);
  line-height: 1.3;
  font-weight: 600;
  color: var(--text-2);
  letter-spacing: 0.005em;
}

.eyebrow {
  margin: 0;
  font-size: var(--fs-sm);
  line-height: 16px;
  font-weight: 500;
  color: var(--text-3);
  text-transform: uppercase;
  letter-spacing: 0.06em;
}

.card-title {
  margin: 0;
  font-size: var(--fs-sm);
  line-height: 18px;
  font-weight: 600;
  color: var(--text-2);
}

.hero-sub {
  margin: 0;
  font-size: var(--num-md);
  line-height: 24px;
  font-weight: 500;
}

/* ─── N5.a · 卡 card + 修饰符 ───────────────────────────────────────── */

.card {
  background: var(--surface);
  border: 1px solid var(--border-1);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-sm);
  padding: var(--card-padding);
}

/* 大浮层 / 大卡（Hero / 顶层容器）·N4.a 大档 padding */
.card--lg {
  border-radius: var(--radius-lg);
  padding: var(--card-padding-lg);
}

/* 嵌套卡（次级表面，无阴影） */
.card--inset {
  background: var(--surface-2);
  box-shadow: none;
  border-color: var(--divider);
}

/* ─── N5.c · 通用 dot + 修饰符（替代 mockup 6 套独立 dot 类） ─────────── */

.dot {
  display: inline-block;
  width: 8px;
  height: 8px;
  border-radius: var(--radius-pill);
  background: var(--text-mute);
  flex-shrink: 0;
}

.dot--up   { background: var(--up); }
.dot--dn   { background: var(--dn); }
.dot--warn { background: var(--warn); }
.dot--mute { background: var(--text-mute); }
.dot--accent { background: var(--accent); }

/* ─── N10 · 占位符（等待外部数据时的 skeleton；保字号字宽，响应式） ─────── */

.ph {
  display: inline-block;
  background: color-mix(in srgb, var(--text-mute) 22%, transparent);
  border-radius: var(--radius-xs);
  color: transparent;
  /* 字号通过外层 inherit；min-width 让空内容也撑出可见占位条 */
  min-width: 2.5em;
  vertical-align: baseline;
}

/* 用于图表容器整体占位（保 viewBox / canvas 尺寸）。
 * 默认 min-height 80px 是为大图（≥180px）准备；嵌入小副图（如 .chart-sub-wrap
 * 44px）时由父容器自身高度约束，加 .ph-chart--inset 允许收缩到父高。 */
.ph-chart {
  background: color-mix(in srgb, var(--text-mute) 12%, transparent);
  border-radius: var(--radius-md);
  width: 100%;
  height: 100%;
  min-height: 80px;
}

.ph-chart--inset {
  min-height: 0;
}

/* ─── N5.d · 合并自 mockup 3 处的 keyframes ─────────────────────────── */

@keyframes fadeUp {
  from { opacity: 0; transform: translateY(8px); }
  to   { opacity: 1; transform: translateY(0); }
}

@keyframes popIn {
  from { opacity: 0; transform: scale(0.96); }
  to   { opacity: 1; transform: scale(1); }
}

@keyframes growBar {
  from { transform: scaleX(0); }
  to   { transform: scaleX(1); }
}

/* ─── 全局横幅 ────────────────────────────────────────────────────────
 * 横幅参与正文文档流（非 fixed 悬浮）：出现时把下方内容往下推，不遮挡任何东西。
 * 多条同时可见时由文档流自动纵向排队 —— 故此处不存在（也不需要）任何手写 top 偏移。 */

/* 间距全部由 .conflict-banner 自己的 margin-bottom 提供；隐藏的横幅是 display:none，
   不产生外边距 → 包裹容器无需任何样式，只作 DOM 分组用。 */
.conflict-banner {
  background: var(--warn-bg);
  border: 1px solid color-mix(in srgb, var(--warn) 40%, transparent);
  border-radius: var(--radius-md);
  margin-bottom: var(--space-4);
  padding: var(--space-3) var(--space-4);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-4);
  font-size: var(--fs-md);
  color: var(--warn-deep);
}

.conflict-banner__text {
  flex: 1 1 auto;
  min-width: 0;
}

.conflict-banner__actions {
  display: flex;
  gap: var(--space-2);
  flex-shrink: 0;
}

.conflict-banner__btn {
  appearance: none;
  border: 1px solid var(--warn);
  background: var(--warn);
  color: var(--surface);
  cursor: pointer;
  height: 32px;
  padding: 0 var(--space-3);
  font-size: var(--fs-sm);
  font-weight: 500;
  border-radius: var(--radius-sm);
  transition: background var(--motion-fast) var(--ease-standard);
}

.conflict-banner__btn:hover {
  background: var(--warn-deep);
  border-color: var(--warn-deep);
}

.conflict-banner__btn--ghost {
  background: transparent;
  color: var(--warn-deep);
}

.conflict-banner__btn--ghost:hover {
  background: color-mix(in srgb, var(--warn) 18%, transparent);
}

.demo-chip {
  display: inline-flex;
  align-items: center;
  height: 28px;
  padding: 0 var(--space-3);
  border-radius: var(--radius-pill);
  border: 1px solid color-mix(in srgb, var(--accent) 42%, var(--border-1));
  background: var(--accent-lt);
  color: var(--accent-deep);
  font-size: var(--fs-sm);
  font-weight: 600;
  white-space: nowrap;
}

@media (max-width: 600px) {
  .demo-chip {
    max-width: 110px;
    overflow: hidden;
    text-overflow: ellipsis;
    padding: 0 var(--space-2);
  }
}

body[data-demo-readonly="true"] #app-undo-btn,
body[data-demo-readonly="true"] #holdings-tx-open,
body[data-demo-readonly="true"] .alloc-ed-trigger,
body[data-demo-readonly="true"] .bench-ed-trigger,
body[data-demo-readonly="true"] .expand-row .exp-btn[data-mode],
body[data-demo-readonly="true"] .tl-del-btn {
  display: none !important;
}

/* 提示类横幅（国金对账 / RSU 待确认 / Day0 占位）：与 conflict-banner 视觉一致但更低
 * 饱和 —— 信息提示，非紧急决策。排队顺序由 DOM 顺序 + 文档流决定，无需 z-index / top。 */
.conflict-banner--warn {
  background: color-mix(in srgb, var(--warn-bg) 70%, var(--surface) 30%);
}

/* dialog 内的对账警告（CONTRACT §13.5.4）—— 与主页 banner 同语义，但非 fixed，
 * 直接放在上传 panel 顶部，跟随 dialog top-layer 一起渲染。 */
.dialog-recon-banner {
  margin: 0 0 var(--space-3);
  padding: var(--space-3) var(--space-4);
  background: color-mix(in srgb, var(--warn-bg) 70%, var(--surface) 30%);
  border: 1px solid color-mix(in srgb, var(--warn) 40%, transparent);
  border-radius: var(--radius-md);
  color: var(--warn-deep);
  font-size: var(--fs-sm);
  line-height: 1.45;
}
.dialog-recon-banner__text { display: block; }

/* ─── 错误 / 加载页 ─────────────────────────────────────────────────── */

.error-page {
  padding: var(--space-7) 0;
}

.error-page__inner {
  max-width: 480px;
  margin: 0 auto;
  text-align: center;
  padding: var(--card-padding-lg);
}

.error-lead {
  margin: var(--space-3) 0 var(--space-4);
  color: var(--text-2);
}

.error-list {
  text-align: left;
  margin: 0 0 var(--space-4);
  padding: 0 0 0 var(--space-5);
  color: var(--dn);
  font-size: var(--fs-sm);
}

.loading-page {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--space-3);
  padding: var(--space-8) 0;
}

.loading-text {
  margin: 0;
  color: var(--text-3);
  font-size: var(--fs-sm);
}

.dots-loader {
  display: inline-flex;
  gap: 6px;
}

.dots-loader span {
  width: 8px;
  height: 8px;
  border-radius: var(--radius-pill);
  background: var(--text-mute);
  animation: popIn 0.8s var(--ease-standard) infinite alternate;
}

.dots-loader span:nth-child(2) { animation-delay: 0.15s; }
.dots-loader span:nth-child(3) { animation-delay: 0.3s; }

/* ─── 角落 toast 容器（Phase 1 落地，沿用） ─────────────────────────── */

#toast-root,
.tx-toast-root {
  position: fixed;
  bottom: var(--space-6);
  right: var(--space-6);
  z-index: 100;
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  pointer-events: none;
}

.toast {
  pointer-events: auto;
  cursor: pointer;
  background: var(--surface);
  border: 1px solid var(--border-1);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-md);
  padding: var(--space-3) var(--space-4);
  font-size: var(--fs-sm);
  color: var(--text-1);
  animation: fadeUp var(--motion-base) var(--ease-standard);
  max-width: 360px;
}

.toast--success {
  border-left: 3px solid var(--up);
}

.toast--error {
  border-left: 3px solid var(--dn);
  color: var(--dn);
}

.toast--hide {
  opacity: 0;
  transform: translateY(8px);
  transition: opacity var(--motion-base) var(--ease-standard),
              transform var(--motion-base) var(--ease-standard);
}

/* ─── tx-dialog / confirm-dialog 容器骨架（Step 7 落地详细样式） ─────── */

.tx-dialog,
.confirm-dialog,
.onboarding-wizard {
  border: 0;
  padding: 0;
  background: transparent;
  max-width: 90vw;
  max-height: 90vh;
}

.tx-dialog::backdrop,
.confirm-dialog::backdrop,
.onboarding-wizard::backdrop {
  background: rgba(0, 0, 0, 0.4);
  backdrop-filter: blur(2px);
}

/* confirm-dialog 内部 shell（js/confirm-dialog.js 注入；MANUAL valueSnapshots 写入 confirm /
   未来其他确认场景共用）。容器 backdrop/border:0 已在上面 §tx-dialog/confirm-dialog 容器骨架 */
.confirm-dialog-shell {
  background: var(--surface-card, #ffffff);
  border-radius: var(--radius-md, 8px);
  box-shadow: var(--shadow-2, 0 10px 30px rgba(0, 0, 0, 0.2));
  padding: 24px 28px;
  min-width: 420px;
  max-width: 560px;
  font-family: inherit;
}
.confirm-dialog-shell__title {
  font-size: var(--font-h3, 18px);
  font-weight: 600;
  margin: 0 0 12px 0;
  color: var(--text-primary, #1a1a1a);
}
.confirm-dialog-shell__body {
  font-size: var(--font-body, 14px);
  line-height: 1.6;
  color: var(--text-secondary, #4a4a4a);
  margin-bottom: 20px;
  font-variant-numeric: tabular-nums;
}
.confirm-dialog-shell__actions {
  display: flex;
  gap: 12px;
  justify-content: flex-end;
}

/* ADR 0050：MANUAL 持仓行清仓快捷开关整段下线 —— 清仓 = 卖出后估值 0 自然触发，
   原 inline-edit 内清仓行 + label 样式已无消费者。 */

/* ADR 0044：.snap-mgr-* / .snap-add-form 整段下线（snap-mgr 子面板删除）
   原 ADR 0036 §D3 + ADR 0038 §D4 + ADR 0039 引用的样式已无消费者；
   VALUE_SNAP 行走 timeline (.tl-*) + 持仓表 staleness 小字 (.holding-cv-staleness) */

/*
 * ════════════════════════════════════════════════════════════════════════
 *  Step 1+ 在此追加各 view section 样式
 *  · view-home: sec-ticker / sec-portfolio / sec-allocation-overview
 *               / sec-holdings / sec-risk
 *  · view-market: 7 section（按 mockup 行号扫读）
 *  · tx-dialog: panel-upload / panel-holdings / panel-balance
 * ════════════════════════════════════════════════════════════════════════
 */

/* ═══ view-home § 1 · sec-ticker（mockup L3704–L3716 / L310–L325） ═══════ */

#sec-ticker {
  /* 顶部 nav 已 fixed 56px + .app-main 已留 padding-top；
     ticker 自身用上下 1px border 形成横向带状结构（mockup L314–L315）。 */
}

.ticker {
  display: flex;
  gap: var(--space-6);              /* mockup 1.5rem ≈ 24px */
  overflow-x: auto;
  padding: var(--space-3) 0;        /* mockup 0.7rem ≈ 11px → 12px (4px 阶梯) */
  border-top: 1px solid var(--border-1);
  border-bottom: 1px solid var(--border-1);
  scrollbar-width: none;            /* Firefox */
}

.ticker::-webkit-scrollbar {
  display: none;                    /* Chromium / WebKit */
}

.t-item {
  display: flex;
  align-items: baseline;
  gap: var(--space-1);              /* mockup 5px → 4px 阶梯（N4.d） */
  flex-shrink: 0;
}

.t-name {
  font-size: var(--fs-xs);          /* 11px */
  color: var(--text-3);
  font-weight: 500;
}

.t-val {
  font-size: var(--num-sm);         /* 13px mono */
  font-family: var(--font-body);
  font-variant-numeric: tabular-nums;
  font-weight: 600;
  color: var(--text-1);
  font-variant-numeric: tabular-nums;
}

.t-chg {
  font-size: var(--fs-xs);          /* 11px */
  font-family: var(--font-body);
  font-variant-numeric: tabular-nums;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  color: var(--text-3);             /* flat 默认色 */
}

.t-chg.up   { color: var(--up); }   /* N3.a · 删硬编码 */
.t-chg.dn   { color: var(--dn); }
.t-chg.flat { color: var(--text-3); }

/* 手机端（≤600px）行情条横向滚动提示：9 项放不下 → 右缘淡出渐变，把"被切一半"读成
   "还能往右滑"而非显示 bug（滚动条本就隐藏，缺可视提示）。mask 钉在可视区右缘、不随内容滚，
   滚到底时末项一并淡出（标准滚动条带行为，可接受）。gap 24→16 与窄屏 16px 留白主题一致、
   一屏多露半项当滑动提示。仅窄屏生效 → 桌面（够宽不滚动 / 已冻结）零影响。 */
@media (max-width: 600px) {
  .ticker {
    gap: var(--space-4);
    -webkit-mask-image: linear-gradient(to right, #000 calc(100% - 24px), transparent);
            mask-image: linear-gradient(to right, #000 calc(100% - 24px), transparent);
  }
}

/* ═══ view-home § 2 · sec-portfolio（mockup L3717–L3776 / L328–L416） ════
 * 1:1 还原 mockup `frag-mod2` 容器结构（card-title / port-head / port-range /
 * port-big-num / port-sub / chart-main-wrap / chart-legend / chart-sub-sep /
 * chart-sub-wrap / stats-row / stat-box / stat-label / stat-val / stat-sub），
 * + 归一化 token：颜色/字号/圆角全部走 :root，删硬编码 #2a7a4a / #b53030 / #bbb。 */

/* view-home grid 布局（mockup L3218–L3268 1:1）：
 *   row 1 ─ sec-ticker            满宽
 *   row 2 ─ sec-portfolio (65%) + sec-allocation-overview (35%)
 *   row 3 ─ sec-holdings           满宽
 *   row 4 ─ sec-risk               满宽
 * 窄屏 ≤1024px 取消 grid 改为纵向堆叠（提前堆叠：右卡 35% 在 900–1024px 太窄、配不下有界滑杆）。 */
#view-home {
  display: grid;
  grid-template-columns: 65fr 35fr;
  grid-template-areas:
    "ticker ticker"
    "portfolio allocation"
    "holdings holdings"
    "income income"
    "risk risk";
  row-gap: var(--space-7);
  column-gap: var(--space-4);
}

#view-home:has(> #sec-onboarding-welcome) {
  grid-template-areas:
    "welcome welcome"
    "ticker ticker"
    "portfolio allocation"
    "holdings holdings"
    "income income"
    "risk risk";
}

#view-home #sec-onboarding-welcome { grid-area: welcome; }
#view-home #sec-ticker             { grid-area: ticker; }
#view-home #sec-portfolio          { grid-area: portfolio; }
#view-home #sec-allocation-overview { grid-area: allocation; }
#view-home #sec-holdings           { grid-area: holdings; }
#view-home #sec-income             { grid-area: income; }
#view-home #sec-risk               { grid-area: risk; }

/* grid 内每个 section 自身要 min-width:0，否则 ECharts canvas 撑爆列宽 */
#view-home > .view-section {
  width: 100%;
  min-width: 0;
}

@media (max-width: 1024px) {
  #view-home {
    grid-template-columns: 1fr;
    grid-template-areas: "ticker" "portfolio" "allocation" "holdings" "income" "risk";
  }
  #view-home:has(> #sec-onboarding-welcome) {
    grid-template-areas: "welcome" "ticker" "portfolio" "allocation" "holdings" "income" "risk";
  }
}

#sec-portfolio {
  /* margin-top 由 #view-home row-gap 接管，不再单独留 */
}

#sec-portfolio .card-title {
  /* mockup 12px, text-3, weight 500, margin-bottom 0.4rem ≈ 6px */
  font-weight: 500;
  color: var(--text-3);
}

.port-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--space-3);
  margin-bottom: var(--space-2);
}

/* time-scale pill 切换；.price-chart-range / .pcr-btn 共用同款样式，
   class 名分开仅为 JS 作用域隔离（持仓图按钮与总览图按钮点击逻辑互不干扰）*/
.port-range,
.price-chart-range,
.income-range {
  display: inline-flex;
  align-items: center;
  gap: 2px;
  padding: 2px;
  border: 1px solid var(--border-1);
  border-radius: var(--radius-pill);
  background: var(--bg-warm);
}

.port-range-btn,
.pcr-btn,
.income-range-btn,
.deposit-range-btn {
  appearance: none;
  border: 0;
  background: transparent;
  padding: 4px 10px;
  font-family: var(--font-body);
  font-variant-numeric: tabular-nums;
  font-size: var(--fs-2xs);                  /* mockup 10px */
  letter-spacing: 0.04em;
  color: var(--text-3);
  cursor: pointer;
  border-radius: var(--radius-pill);
  line-height: 1.3;
  transition: color var(--motion-fast) var(--ease-standard),
              background var(--motion-fast) var(--ease-standard);
}

.port-range-btn:hover,
.pcr-btn:hover,
.income-range-btn:hover,
.deposit-range-btn:hover {
  color: var(--text-1);
}

.port-range-btn.is-active,
.pcr-btn.is-active,
.income-range-btn.is-active,
.deposit-range-btn.is-active {
  color: var(--accent);
  background: var(--surface);
  box-shadow: 0 0 0 1px var(--accent) inset;
}

.port-range-btn:focus-visible,
.pcr-btn:focus-visible,
.income-range-btn:focus-visible,
.deposit-range-btn:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

/* ── F7 · 股息与现金流（sec-income）────────────────────────────────────────── */
.income-stats { margin-bottom: var(--space-3); }

.income-note {
  font-size: var(--fs-xs);
  color: var(--dn);
  background: var(--dn-bg);
  border-radius: var(--radius-sm);
  padding: 6px 10px;
  margin-bottom: var(--space-3);
}

.income-chart-head {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: var(--space-4);
  margin-bottom: var(--space-2);
}

.income-chart-cap {
  font-size: var(--fs-sm);
  color: var(--text-3);
}

.income-chart-wrap { width: 100%; height: 220px; }

/* ── F27 · 月度入金图（沿用分红图视觉，仅在头部加一条分隔与上方分红图分开）── */
.income-chart-head--deposit {
  margin-top: var(--space-5);
  padding-top: var(--space-4);
  border-top: 1px solid var(--border-1);
}

/* ── F9 · 盈亏排行榜（sec-holdings 顶部）──────────────────────────────────────── */
.pnl-leaderboard {
  background: var(--surface);
  border: 1px solid var(--border-1);
  border-radius: var(--radius-md);
  padding: var(--space-3) var(--space-4);
  margin-bottom: var(--space-4);
}
.pnl-lb-title {
  font-size: var(--fs-sm);
  font-weight: 600;
  color: var(--text-1);
  margin-bottom: var(--space-3);
}
.pnl-lb-cols {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--space-4) var(--space-5);
}
.pnl-lb-cols--single { grid-template-columns: 1fr; }
.pnl-lb-col { display: flex; flex-direction: column; gap: 4px; }
.pnl-lb-col-h {
  font-size: var(--fs-2xs);
  letter-spacing: 0.04em;
  color: var(--text-3);
  margin-bottom: 2px;
}
.pnl-lb-col-h--best { color: var(--up); }
.pnl-lb-col-h--worst { color: var(--dn); }
.pnl-lb-row {
  display: flex;
  align-items: baseline;
  gap: var(--space-3);
  font-size: var(--fs-sm);
  font-variant-numeric: tabular-nums;
}
.pnl-lb-name {
  flex: 1 1 auto;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  color: var(--text-2);
}
.pnl-lb-amt { flex: 0 0 auto; text-align: right; }
.pnl-lb-rr {
  flex: 0 0 auto;
  width: 4.5em;
  text-align: right;
  font-size: var(--fs-xs);
}
.pnl-lb-foot {
  font-size: var(--fs-xs);
  color: var(--text-3);
  margin-top: var(--space-3);
}
@media (max-width: 560px) {
  .pnl-lb-cols { grid-template-columns: 1fr; }
}

.income-chart-unavailable,
.income-empty {
  font-size: var(--fs-sm);
  color: var(--text-3);
  padding: var(--space-6) 0;
  text-align: center;
}

.income-explainer {
  appearance: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 14px;
  height: 14px;
  margin-left: 4px;
  padding: 0;
  border: 1px solid var(--border-1);
  border-radius: 50%;
  background: transparent;
  color: var(--text-3);
  font-size: 10px;
  line-height: 1;
  cursor: pointer;
  vertical-align: middle;
}

.income-explainer:hover {
  color: var(--accent);
  border-color: var(--accent);
}


.port-big-num {
  font-family: var(--font-body);                  /* mono 数字与 N2.d/IBM Plex 一致 */
  font-variant-numeric: tabular-nums;
  font-size: var(--fs-display);              /* 32px ≈ mockup 28px → 升档 */
  font-weight: 600;
  letter-spacing: -1px;
  color: var(--text-1);
  font-variant-numeric: tabular-nums;
  line-height: 1.05;
}

.port-sub {
  font-size: var(--fs-sm);
  color: var(--text-3);
  margin-top: var(--space-1);
}

.port-sub .up { color: var(--up); }          /* N3.a */
.port-sub .dn { color: var(--dn); }
.port-sub .sep {
  margin: 0 var(--space-2);
  color: var(--text-mute);
}
/* 标签↔数字间距（拆成 .pnl-lbl/.pnl-val 双 span 后，桌面横排靠它补回原来的一个空格）。
   窄屏会被 @600 覆写成等宽列。 */
.port-sub .pnl-lbl { margin-right: 0.4em; }

/* port-sub 文字 + scale tabs 共行（v5）：左 port-sub，右 range tabs；
 * padding-right 让 tabs 右沿对齐绘图区右沿 —— grid.right 已改 0（ADR 0109），故归 0：
 * tabs 右缘 = 绘图区右缘 = KPI 卡右缘 = 卡片内容右缘，整列右侧对齐。 */
.port-sub-line {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: var(--space-4);
  padding-right: 0;
  margin-top: var(--space-1);
}

/* 窄屏：P&L 文字行与时间段切换器上下堆叠（横排放不下会把数字挤碎）。
   问题 1：两段（上一交易日 / 全部期间）各占一行，左侧标签用等宽列 → 数字对齐成一竖列；
   去掉两段之间的「·」（堆叠后分隔点无意义）。标签宽度按最长「上一交易日」(5 字 ≈ 5em) 取整。 */
@media (max-width: 600px) {
  .port-sub-line {
    display: block;
    padding-right: 0;
  }
  .port-range-inline {
    margin-top: var(--space-2);
  }
  .port-sub {
    display: flex;
    flex-direction: column;
    gap: 2px;
  }
  .port-sub .pnl-seg {
    display: flex;
    white-space: nowrap;
  }
  .port-sub .pnl-lbl {
    width: 5.4em;          /* 等宽标签列：「上一交易日」/「全部期间」对齐，数字同一起点 */
    margin-right: 0;
    flex-shrink: 0;
  }
  .port-sub .sep {
    display: none;
  }
}

/* 主图 / 副图：左侧竖排 vlabel + chart 用 row wrapper（v5） */
.port-chart-row {
  display: flex;
  align-items: stretch;
}

/* CJK upright 不加 transform rotate；flex stretch + writing-mode 居中需 padding 补偿 */
.chart-vlabel {
  display: flex;
  align-items: center;
  justify-content: center;
  writing-mode: vertical-rl;
  font-size: var(--fs-sm);
  font-weight: 500;
  color: var(--text-2);
  letter-spacing: 0.06em;
  padding: 0 6px 0 0;
  flex-shrink: 0;
  white-space: nowrap;
}
.port-chart-row--main .chart-vlabel { padding-top: 20px; }       /* 主图居中补偿（grid.top=28 grid.bottom=24 不对称） */
.port-chart-row--sub  .chart-vlabel { padding-bottom: 14px; }    /* 副图居中补偿（grid.top=8 grid.bottom=22 不对称） */

.chart-main-wrap {
  position: relative;
  height: 272px;                             /* plot 区 (272-28-24)=220 / 4 段 = 每段 55px */
  margin-top: var(--space-4);
  overflow: visible;                         /* tooltip 可伸出右沿 */
  flex: 1 1 auto;
  min-width: 0;
}

/* 主副图分隔线（ADR 0024 起：¥A→¥B 文字行已删，起止 ¥ label 改嵌入副图曲线两端 markPoint） */
.chart-sub-sep {
  border-top: 1px solid var(--border-1);
  margin: 16px 0 8px;
}

.chart-sub-wrap {
  position: relative;
  height: 164px;                             /* plot 区 (164-32-22)=110 / 2 段 = 每段 55px（= 主图 (272-28-24)/4） */
  overflow: visible;                         /* tooltip 可伸出右沿 */
  flex: 1 1 auto;
  min-width: 0;
}

.stats-row {
  display: flex;
  gap: clamp(8px, 1.4%, 18px);
  margin-top: var(--space-5);
}

.stat-box {
  flex: 1;
  background: var(--bg-warm);
  border-radius: var(--radius-md);
  padding: 10px 12px;
  min-width: 0;
}

.stat-label {
  font-size: var(--fs-xs);
  color: var(--text-3);
  line-height: 1.3;
  display: flex;
  align-items: center;
  gap: var(--space-1);
}

.stat-val {
  font-family: var(--font-body);
  font-variant-numeric: tabular-nums;
  font-size: var(--fs-md);                   /* mockup 14px */
  font-weight: 600;
  margin-top: 3px;
  color: var(--text-1);
  font-variant-numeric: tabular-nums;
}

.stat-val.up { color: var(--up); }
.stat-val.dn { color: var(--dn); }
/* ADR 0111：历史降级时时间序列 KPI 值显 "—"，用 muted 色（区别于 .ph 加载占位 / 真实 up·dn 数值） */
.stat-val.na { color: var(--text-mute); }

.stat-sub {
  font-size: var(--fs-2xs);
  color: var(--text-3);
  margin-top: 2px;
}

/* KPI explainer "?" badge（mockup L194–L213 1:1 还原） */
.kpi-explainer {
  appearance: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 13px;
  height: 13px;
  margin-left: 4px;
  padding: 0;
  border-radius: 50%;
  background: var(--surface-2);
  color: var(--text-3);
  font-family: var(--font-body);
  font-variant-numeric: tabular-nums;
  font-size: 9px;
  font-weight: 600;
  cursor: help;
  vertical-align: 1px;
  border: 1px solid var(--border-1);
  transition: background var(--motion-fast) var(--ease-standard),
              color var(--motion-fast) var(--ease-standard),
              border-color var(--motion-fast) var(--ease-standard);
}

.kpi-explainer:hover,
.kpi-explainer:focus-visible {
  background: var(--accent-lt);
  color: var(--accent-deep);
  border-color: var(--accent);
}

/* KPI explainer popover · v5 改 position: fixed + flip-up（贴底翻向上）
 * （旧版 absolute + 无 flip 在卡底贴底时会戳到下方相邻卡上面） */
.kpi-popover {
  position: fixed;
  z-index: 200;
  max-width: 240px;
  padding: 10px 12px;
  background: var(--surface);
  color: var(--text-2);
  border: 1px solid var(--border-1);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-md);
  font-size: 12px;
  line-height: 1.55;
  pointer-events: none;
  opacity: 0;
  transform: translateY(4px);
  transition: opacity .15s ease, transform .15s ease;
}
.kpi-popover.is-visible {
  opacity: 1;
  transform: translateY(0);
}
.kpi-popover-title {
  font-weight: 600;
  color: var(--text-1);
  margin-bottom: 4px;
  font-size: 12px;
}

@media (max-width: 768px) {
  .stats-row {
    flex-wrap: wrap;
  }
  /* 5 个 KPI 框：窄屏排成 3+2（每行 3 个，最后一行 2 个），
     比 2+2+1 更紧凑、不落单。基准取 1/3 宽，最后一行 2 个自动撑满。 */
  .stat-box {
    flex: 1 1 calc((100% - 2 * var(--space-3)) / 3);
  }
  .port-big-num {
    font-size: var(--num-xl);
  }
}

/* 极窄屏（≤340px）：3 列每框太挤，退回 2 列（2+2+1）。 */
@media (max-width: 340px) {
  .stat-box {
    flex: 1 1 calc(50% - var(--space-3) / 2);
  }
}

/* ═══ view-home § 3 · sec-allocation-overview（mockup L3778–L3854 / L418–L626） ═══
 * N3.c · 保后端 6 类（不改 mockup 4 类）—— ASSET_CATEGORIES + CATEGORY_SORT_ORDER。
 * targetAllocation 字段不在 schema 里 → 目标值 / 安全区 / pill / over-under desc /
 * 再平衡 alert **整组** N10 占位（保 mockup 骨架不缺格）。 */

#sec-allocation-overview {
  /* margin-top 由 #view-home row-gap 接管，不再单独留 */
}

/* 四边等比留白（supersede ADR 0104 横向-only 模型，详见新 ADR）：一条 clamp 管四边、
   左=右=上=下（删原右多 6px 的不对称）；单栏随卡宽平滑缩放——手机(~378)落 16px、
   堆叠宽卡封顶 24px（克制，不无脑等比）。圆角同步调大到 14px。
   选择器在编辑态（.card.alloc-card--editing）仍命中、同样生效。 */
#sec-portfolio > .card,
#sec-allocation-overview > .card {
  padding: clamp(16px, 3%, 24px);
  border-radius: 14px;
}
/* 双栏（>1024）：组合总览(65%)/资产配置(35%) 宽度差大，按 % 会让宽卡留白远超窄卡（悬殊）。
   双栏档两卡都封顶 24px → 与堆叠档 24 平滑衔接、两卡留白一致（ADR 0104「双栏协调」不变式）。
   缩放发生在单栏档（16→24）；双栏属「宽态」，封顶 24 即最大呼吸。 */
@media (min-width: 1025px) {
  #sec-portfolio > .card,
  #sec-allocation-overview > .card {
    padding: 24px;
  }
}

#sec-allocation-overview .card-title {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  font-weight: 500;
  color: var(--text-3);
  margin-bottom: var(--space-3);
}

/* 标题文字 padding-left:18 与父项目名字（margin-left:18 让出的箭头列）左缘对齐；margin-right:auto 把 toggle + icon 推右上 */
#sec-allocation-overview .card-title > span:first-child {
  margin-right: auto;
  padding-left: 18px;
}

/* 显示方式 toggle —— 嵌入 card-title 右上角，紧凑模式 */
.toggle-bar {
  display: flex;
  align-items: center;
}

.toggle-group {
  display: flex;
  background: var(--bg-warm);
  border-radius: var(--radius-md);
  padding: 2px;
}

.toggle-btn {
  appearance: none;
  border: 0;
  background: transparent;
  cursor: pointer;
  font-family: inherit;
  font-size: var(--fs-xs);
  font-weight: 500;
  padding: 3px 8px;
  border-radius: var(--radius-sm);
  color: var(--text-2);
  transition: background var(--motion-fast) var(--ease-standard),
              color var(--motion-fast) var(--ease-standard);
}

.toggle-btn:hover {
  color: var(--text-1);
}

.toggle-btn.is-active {
  background: var(--surface);
  color: var(--text-1);
  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.06);
}

.toggle-btn:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

/* ─── alloc-row（父类一行）─── */

.alloc-row {
  display: flex;
  align-items: center;
  gap: clamp(12px, 2.2%, 20px);       /* 堆叠档：卡越宽缝越大（1024 ~20px）。双栏档更小，见底部 @media min-width:1025 */
  padding: 14px 0;
}

/* 分隔线归属"下一父行的顶部"语义 —— 用 border-top + 兄弟选择器，第一个父行不画。
   折叠态：父行间各一条；展开态：分隔线天然落在"最后子行 → 下一父行"之间且距下一父行 14px (= padding-top)、
   距上方子行内容 (sub padding-bottom 7 + children padding-bottom 7) ≈ 14px，两侧视觉均衡。 */
.alloc-row[data-alloc-class] ~ .alloc-row[data-alloc-class] {
  border-top: 1px solid var(--divider);
}

.alloc-name {
  position: relative;                              /* 锚定 .alloc-chev 绝对定位（chev 移出文档流落到左 padding 内，名字文字左缘对齐标题） */
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: var(--fs-sm);
  color: var(--text-2);
  width: calc(clamp(104px, 14%, 150px) + 12px);   /* 名字列随宽 clamp 缩放；+12 = 名字↔滑杆额外 1 字(12px)；左对齐不动 */
  flex-shrink: 0;
}

/* nowrap 只给「父类名」（6 个已知短名）；子行名是任意持仓名（可能很长）→ 保持默认可换行，
   否则 nowrap 会让长名溢出压到进度条上。
   margin-left 18px：给左侧让出一条「展开箭头列」——旋转后的 ⌄ 实测 bbox ~12px，贴边会顶名字显挤；
   标题同步 padding-left:18 保持「标题↔父项目」左对齐（见 card-title 规则）。 */
.alloc-row[data-alloc-class] > .alloc-name {
  white-space: nowrap;
  margin-left: 18px;
}

/* chev 绝对定位到名字左侧的「箭头列」内（不占文档流、不挤名字宽度）→ 名字文字左缘 = 标题左缘对齐（问题 5）。
   名字 margin-left:18 让出箭头列；chev margin-right:9 → 旋转后 ⌄ 距名字 ~5–6px 呼吸、整体落在列内不戳进度条。
   hover/展开淡入，展开旋转 90°（与 translateY 居中复合）。 */
.alloc-chev {
  position: absolute;
  right: 100%;
  top: 50%;
  margin-right: 9px;
  transform: translateY(-50%);
  font-weight: 700;
  color: var(--text-3);
  line-height: 1;
  opacity: 0;
  transition: transform var(--motion-base) var(--ease-standard),
              opacity var(--motion-fast) var(--ease-standard);
}

.alloc-row[data-alloc-class] {
  cursor: pointer;
}

.alloc-row[data-alloc-class]:hover > .alloc-name > .alloc-chev,
.alloc-row.is-expanded > .alloc-name > .alloc-chev {
  opacity: 1;
}

.alloc-row.is-expanded > .alloc-name > .alloc-chev {
  transform: translateY(-50%) rotate(90deg);
}

/* ─── 进度条 track（mockup pill / safe band / target label）—— 整组 N10 占位 ─── */

.alloc-track {
  flex: 1 1 auto;                      /* 等比间隙：滑杆吃掉主要增量、消灭死缝（无封顶） */
  position: relative;
  height: 42px;
}

.alloc-bg {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  height: 2px;
  width: 100%;
  background: var(--border-1);
}

/* safe band 视觉宽度由每行 .alloc-track 上的 --band-half CSS var 注入
   （view-home renderAllocRow 计算：band(pp) × 5% → 5pp=25% / 2.5pp=12.5%）；
   占位行无 var 时 fallback 到 25%（即旧 5pp 视觉宽度）。
   颜色 #d6e6f3 来自 mockup index_new_UI_mockup.html L496。 */
.alloc-safe {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  left: calc(50% - var(--band-half, 25%));
  width: calc(var(--band-half, 25%) * 2);
  height: 14px;
  background: #d6e6f3;
  border-radius: 8px;
}

.alloc-lbl {
  position: absolute;
  left: 50%;
  bottom: calc(50% + 14px);
  transform: translateX(-50%);
  font-size: var(--fs-2xs);
  font-weight: 500;
  color: #3a6fa0;                    /* mockup L505：目标蓝（替代 var(--accent-deep) 太深） */
  white-space: nowrap;
  line-height: 1;
  transition: bottom var(--motion-base) var(--ease-standard);
}

/* |delta|≤2pp 时 pill 与 label 都在中线 50% 附近，会撞 → label 抬升避让。
   mockup L509–L511 写的是 +22px，但实际算下来 +22 让 label 顶突出 track 上方 11px，
   距 alloc-row 上分隔线只剩 3px 视觉空气；+18 抬升 4px、距分隔线恢复 7px、
   三角尖到 pill 顶仍有 ~3px 缓冲（不撞）。row 总高度不变。 */
.alloc-row.conflict:not(.alloc-row--editing) .alloc-lbl {
  bottom: calc(50% + 18px);
}

.alloc-lbl::after {
  content: "";
  position: absolute;
  top: 100%;
  left: 50%;
  transform: translateX(-50%);
  margin-top: 2px;
  width: 0;
  height: 0;
  border-left: 3.5px solid transparent;
  border-right: 3.5px solid transparent;
  border-top: 4px solid #3a6fa0;     /* mockup L521：目标蓝三角 */
}

.alloc-pill {
  position: absolute;
  top: 50%;
  transform: translate(-50%, -50%);
  width: 5px;
  height: 18px;
  background: var(--text-1);          /* 真值黑；占位由 .is-placeholder 覆盖、越界由 .out 覆盖 */
  border-radius: var(--radius-xs);
  box-shadow: 0 0 0 2px var(--surface);
  transition: left var(--motion-base) var(--ease-standard);
}

/* |delta|>5pp（safe band 25–75 之外）→ 橙色 pill（mockup L532）。
   局部覆写 #d4871a（mockup 原值），不走全局 --warn-deep（#8a4715 偏深，2026-05-04 决策）。 */
.alloc-pill.out { background: #cb800f; }

/* 占位骨架：snapshot=null 时把 pill / label / 三角全部退化到灰，保 N10 一致语言 */
.alloc-row.is-placeholder .alloc-lbl { color: var(--text-mute); }
.alloc-row.is-placeholder .alloc-lbl::after { border-top-color: var(--text-mute); }
.alloc-row.is-placeholder .alloc-pill { background: var(--text-mute); }

/* ─── alloc-nums（右侧真实 % / 金额 + 占位 over/under desc）─── */

.alloc-nums {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  width: clamp(72px, 9%, 96px);       /* 随宽 clamp 缩放且所有行同宽（滑杆恒等长）；右对齐由 align-items:flex-end 维持。
                                         下限 72 容最宽「低配 −XX.X%」desc（已 nowrap）。 */
  margin-left: 0;                     /* 删 auto：剩余宽度交给 .alloc-track flex:1 吸收，消灭死缝 */
  flex-shrink: 0;
  gap: 2px;
}

.alloc-pct {
  font-family: var(--font-body);
  font-variant-numeric: tabular-nums;
  font-size: var(--fs-md);
  font-weight: 600;
  color: var(--text-1);
  font-variant-numeric: tabular-nums;
}

.alloc-desc {
  font-size: var(--fs-xs);
  font-weight: 500;
  color: var(--text-3);
  white-space: nowrap;
}

/* desc 三态颜色（mockup L545–L547）。阈值 ±0.3pp 由 calcRebalanceTargets.descKind 决定 */
.alloc-desc.desc-over  { color: #cb800f; }
.alloc-desc.desc-under { color: var(--up); }
.alloc-desc.desc-ok    { color: var(--text-3); }

/* ─── 再平衡 alert（整段 N10 占位 —— 没有 targetAllocation 算不出建议）─── */

.rebalance-alert {
  margin-top: var(--space-4);
  padding: 10px 12px;
  background: var(--warn-bg);
  border-radius: var(--radius-md);
  border-left: 3px solid var(--warn);
}

.alert-title {
  font-size: var(--fs-xs);
  font-weight: 600;
  color: var(--warn-deep);
}

.alert-body {
  font-size: var(--fs-xs);
  color: var(--warn);
  margin-top: 3px;
  line-height: 1.5;
}

/* ─── 再平衡 alert · 健康态变体（无超低配时显示）─── */

.rebalance-alert.is-ok {
  background: color-mix(in srgb, var(--up) 8%, var(--surface));
  border-left-color: var(--up);
}
.rebalance-alert.is-ok .alert-title { color: var(--up); }
.rebalance-alert.is-ok .alert-body  { color: color-mix(in srgb, var(--up) 80%, var(--text-2)); }

/* ─── 父类展开后的子项行（按 asset 聚合 · top 6 + "其他 N 项"）─── */

.alloc-row-children {
  max-height: 0;
  overflow: hidden;
  margin: 0;                                       /* 不缩进，让 dashed / 下一父行 border-top 贯通卡片宽度 */
  padding: 0;
  transition: max-height var(--motion-slow) var(--ease-standard),
              padding var(--motion-slow) var(--ease-standard);
}

.alloc-row-children.is-open {
  max-height: 600px;
  padding: 0 0 14px;                               /* "上紧下松"非对称：
                                                      首子项→自己父行 = 父行 pad-b 14 + children pad-t 0 + sub pad-t 4 = 18px
                                                      末子项→下一父行 = sub pad-b 7 + children pad-b 14 + border 1 + 父行 pad-t 14 = 36px
                                                      末子项→下一父行（≈2×首子项→自己父行）让分隔线视觉归属"下一父行的顶"，符合"父行+子项视觉成一组"语义。 */
}

.alloc-row-children__empty {
  font-size: var(--fs-xs);
  color: var(--text-mute);
  padding: 8px 0;
}

/* 7 类 sub-fill 颜色：按屏序对齐 mockup classic 色盘（mockup L587–L594）+
   §0.6 chart token 1:1 映射。屏序 N → 第 N 色（cash 起步深蓝），不按语义分配。
   2026-05-04 重映射决策：原 cash=灰 / equity_index_fund=蓝 改为按位映射，第一行 = 深蓝
   与 mockup 视觉一致。2026-05-10：multi_asset 第 7 色用蓝灰 slate（混合语义）。 */
.alloc-row-children[data-children-for="cash"]              { --p-current: var(--chart-blue); }     /* 1st 蓝 */
.alloc-row-children[data-children-for="fixed_income"]      { --p-current: var(--chart-purple); }   /* 2nd 紫 */
.alloc-row-children[data-children-for="equity_index_fund"] { --p-current: var(--chart-teal); }     /* 3rd 青 */
.alloc-row-children[data-children-for="equity_single"]     { --p-current: var(--chart-magenta); }  /* 4th 品红 */
.alloc-row-children[data-children-for="commodity"]         { --p-current: var(--chart-sage); }     /* 5th 鼠尾草绿 */
.alloc-row-children[data-children-for="alternative"]       { --p-current: var(--chart-umber); }    /* 6th 赭石棕 */
.alloc-row-children[data-children-for="multi_asset"]       { --p-current: var(--chart-slate); }    /* 7th 蓝灰 */

.alloc-row-children .alloc-row.is-sub {
  /* 缩进随卡宽缩放：宽（堆叠 1024）→ 40px 保层级感；窄（双栏临界 / 手机）→ 20px 把空间让给进度条。
     用 CSS var 让 padding-left 与下面 dashed ::after 的 left 同步。top 4：首子项贴父行；bottom 7：中间子项 dashed 间距。
     +18px：父名已 margin-left:18 让出箭头列（见 .alloc-chev），子树同步右移 18 → 维持原「子↔父」嵌套量
     与「子进度条↔父滑杆」相对位置（整棵 label 树一起平移，不改相对关系）。 */
  --sub-indent: calc(clamp(20px, 4.5%, 40px) + 18px);
  padding: 4px 0 7px var(--sub-indent);
  border-bottom: 0;                                /* 子行用 ::after 画 dashed，本身不画 own border，避免与父类 .alloc-row 的 border-top 冲突 */
  cursor: default;
  gap: clamp(12px, 2.2%, 20px);                   /* 同父行节奏（双栏档更小见 @media min-width:1025） */
  position: relative;                              /* ::after 定位锚点 */
}
/* 中间子行 dashed 虚线：用 ::after 从缩进处（var）起画到 right:0，跳过左侧缩进区
   （若用 border-bottom 会跨整宽含 padding-left，视觉"全长" 不符合内缩节奏） */
.alloc-row-children .alloc-row.is-sub:not(:last-child)::after {
  content: "";
  position: absolute;
  left: var(--sub-indent);
  right: 0;
  bottom: 0;
  border-bottom: 1px dashed var(--divider);
}
/* 最后一个子行不画 own border —— 整组底分隔线由下一父行 border-top 提供 */

.alloc-row.is-sub .alloc-name {
  font-size: var(--fs-xs);
  color: var(--text-3);
  width: clamp(96px, 19%, 160px);                 /* 随卡宽缩放：堆叠 1024 → 160px（长名 2 行而非 3）；窄 → 96px 下限。
                                                     下限 96 = 父名下限 116 − 缩进下限 20：保证窄屏「缩进 + 子名 ≥ 父名」，
                                                     子进度条左缘不戳出父滑杆左缘。上限 160 是「2 行折中」（再宽到 ~210 可一行，但进度条左缘右移过多）。 */
}

.alloc-row.is-sub .sub-bar {
  /* 等比间隙：sub-bar 吃掉主要增量（无封顶）。右缘对齐父滑杆右缘由 .sub-value 与父行 nums 同款宽 + 同款右侧 gap 保证
     （与左侧缩进 / 名字列宽无关）；缩进与名字列加宽只影响 sub-bar 左端起点，右缘不动。 */
  flex: 1 1 auto;
  height: 6px;
  background: var(--border-1);
  border-radius: 3px;
  overflow: hidden;
  min-width: 0;
}

.alloc-row.is-sub .sub-fill {
  height: 100%;
  background: var(--p-current, var(--text-mute));
  border-radius: 3px;
  transition: width var(--motion-base) var(--ease-standard);
}

.alloc-row.is-sub .sub-value {
  font-family: var(--font-body);
  font-variant-numeric: tabular-nums;
  font-size: var(--fs-sm);
  font-weight: 500;
  color: var(--text-1);
  font-variant-numeric: tabular-nums;
  width: clamp(72px, 9%, 96px);       /* 与父行数字同套 clamp（同宽 → sub-bar 恒等长） */
  flex-shrink: 0;
  margin-left: 0;                     /* 删 auto：剩余宽度交给 .sub-bar flex:1 吸收 */
  text-align: right;
}

/* 窄屏：子行名字/数值进一步收窄，把宽度让给子行进度条 sub-bar
   —— 否则 320–375px 下子行进度条会被压成一个点。
   （缩进不再在此覆写：已由 base 的 --sub-indent clamp 在窄屏自然收到 ~20px；
     原此处 padding-left:22px 因 base 选择器更具体一直是死规则，移除。）*/
@media (max-width: 600px) {
  /* 父名列窄屏收窄（问题 6）：base 公式 14% 在手机够不到 → 全程钉死 116px，而最长父名
     「股票 - 指数基金」实测仅 84.3px、富余 ~32px。手机压到 clamp(96px, 25%, 116px)
     （96 = 84.3 最长名 + ~12 呼吸，nowrap 不截字；402→96 滑杆 +20px、600→116 平滑接回堆叠档）。
     省出的宽度由 .alloc-track flex:1 自动吃进滑杆（不封顶）。 */
  .alloc-row[data-alloc-class] > .alloc-name {
    width: clamp(96px, 25%, 116px);
  }
  /* 子名维持 base clamp(96px,…) 不在此压到 72：现父名下限 96，约束「缩进20 + 子名 ≥ 父名」=
     20+96 ≥ 96 成立，子进度条左缘不戳出父滑杆。子数值收到 60 让宽给 sub-bar。 */
  .alloc-row.is-sub .sub-value {
    width: 60px;
  }
}

/* 双栏档（>1024）：资产配置是 35% 窄栏（卡 336–468px），间距按堆叠公式会显大。
   父行用「带负截距的线」calc(4.7% − 7.4px)：比纯 % 降得更狠，临界 1025 收到 ~6px、撑到头 1440+ 封顶 12px，
   且仍是连续直线（平滑）。纯 % 受「双栏卡宽只差 1.45×」限制最低只能 ~8.5px，故用负截距突破。
   子行沿用纯 clamp(8,3%,12)（子行宽度策略另见 §子行）。堆叠瞬间放大到 ~20px（断点跳变是有意的）。
   放在文件靠后 + 与 base 同特异度 → 源序在后压过 base 的堆叠档。与 @media max-width:600/768 互斥不冲突。 */
@media (min-width: 1025px) {
  .alloc-row {
    gap: clamp(6px, calc(4.7% - 7.4px), 12px);
  }
  .alloc-row-children .alloc-row.is-sub {
    gap: clamp(8px, 3%, 12px);
  }
  /* 父名列在双栏档随宽收缩：base 公式 clamp(104,14%,150)+12 的 14% 在双栏区间(286–414)永远够不到 104 下限，
     名字列被钉死 116px → 临界不压缩、富余(含只该给全宽的 +12)全程都在。改用更高 % + 收紧上下限让它真随宽变：
     临界 1025 → 100px（刚够最长名「股票-指数基金」~96px + ~4px 防贴边，breathing 挤掉）；全宽 1440+ → 116px（保留 +12 breathing）。
     右侧数字列不压：72px ≈ 最坏说明标签「超配 +123.4%」71.8px，压窄会截标签。 */
  .alloc-row[data-alloc-class] > .alloc-name {
    width: clamp(100px, 28%, 116px);
  }
}

/* ─── E16 残项 · alloc 编辑模式（v2 卡片内联）—— 抄自 mockup/alloc-target-editor/switcher.html ─── */

/* ✎ 设置目标 SVG icon button（card-title 行最右；与 toggle-bar 紧邻） */
.alloc-ed-trigger {
  appearance: none;
  border: 1px solid var(--border-2);
  background: var(--surface);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  color: var(--text-2);
  padding: 4px;
  width: 24px;
  height: 24px;
  border-radius: var(--radius-md);
  cursor: pointer;
  transition: background var(--motion-fast) var(--ease-standard),
              border-color var(--motion-fast) var(--ease-standard),
              color var(--motion-fast) var(--ease-standard);
}
.alloc-ed-trigger > svg {
  display: block;
}
.alloc-ed-trigger:hover:not(:disabled) {
  background: var(--bg-warm);
  border-color: var(--accent);
  color: var(--accent);
}
.alloc-ed-trigger:disabled {
  opacity: 0.45;
  cursor: not-allowed;
}

/* 行 / label 进入编辑态 */
.alloc-row.alloc-row--editing {
  cursor: default !important;
  /* input 22px 撑大 label box 至 ~22 高，需要更厚 row padding 让 label 不撞上分隔线、底端不贴 pill */
  padding: 20px 0;
}
.alloc-row--editing .alloc-chev {
  opacity: 0 !important;
}
.alloc-row--editing .alloc-lbl {
  font-size: var(--fs-xs);
  color: var(--accent-deep);
  line-height: 1;
  /* +14px：label 顶距 row 上分隔线 ~5px、底距 pill 顶 ~5px。conflict 抬升在编辑态被 :not 排除，所有 6 行同位置 */
  bottom: calc(50% + 14px);
}
.alloc-row--editing .alloc-lbl::after {
  display: none;
}

/* number input 几何（mockup 已调到的最终值） */
.alloc-ed-v2-input {
  font-family: var(--mono);
  font-variant-numeric: tabular-nums;
  font-weight: 600;
  font-size: var(--fs-sm);   /* 12px：spinner 箭头会跟着加大 */
  width: 42px;
  padding: 3px 2px 3px 4px;  /* 上下 3px → input 总高 ~22px，箭头有空间 */
  border: 1px solid var(--accent);
  background: var(--accent-lt);
  color: var(--accent-deep);
  border-radius: 4px;
  text-align: right;
  margin: 0 1px;
  vertical-align: middle;
  box-sizing: border-box;
}
/* 让 spinner 箭头始终可见（默认 hover 才显示） */
.alloc-ed-v2-input::-webkit-inner-spin-button,
.alloc-ed-v2-input::-webkit-outer-spin-button {
  opacity: 1;
  cursor: pointer;
}
.alloc-ed-v2-input:focus {
  outline: 2px solid var(--accent);
  outline-offset: 1px;
}

/* footer：sum chip + 重置 / 取消 / 保存 */
.alloc-ed-v2-foot {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  margin-top: var(--space-3);
  padding: 12px 14px;
  background: var(--surface-2);
  border: 1px solid var(--border-1);
  border-radius: var(--radius-md);
}

/* 编辑期：toggle-bar / rebalance-alert 灰显 + 屏蔽点击 */
.card.alloc-card--editing .toggle-bar,
.card.alloc-card--editing .rebalance-alert {
  opacity: 0.35;
  pointer-events: none;
}

/* sum chip（合计） */
.alloc-ed-sum-chip {
  font-family: var(--font-body);
  font-variant-numeric: tabular-nums;
  font-size: var(--fs-sm);
  font-weight: 500;
  padding: 5px 10px;
  border-radius: 999px;
  background: var(--up-bg);
  color: var(--up);
}
.alloc-ed-sum-chip.is-bad {
  background: var(--dn-bg);
  color: var(--dn);
}

/* 操作区 */
.alloc-ed-actions {
  display: flex;
  align-items: center;
  gap: 10px;
}
.alloc-ed-link {
  appearance: none;
  background: transparent;
  border: 0;
  cursor: pointer;
  font-family: inherit;
  font-size: var(--fs-sm);
  color: var(--text-3);
  text-decoration: underline;
  text-underline-offset: 3px;
  padding: 4px 2px;
}
.alloc-ed-link:hover {
  color: var(--text-1);
}

/* ═══ ADR 0146 · α 基准篮子 + 主图对照线 就地编辑器 ═══════════════════════════
 * 铅笔 trigger（α 卡 / 主图旁）点开 → 在固定挂载点展开编辑面板。视觉沿用 alloc-ed-* 语汇。 */

.bench-ed-trigger {
  appearance: none;
  border: 1px solid var(--border-2);
  background: var(--surface);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  color: var(--text-2);
  padding: 3px;
  width: 20px;
  height: 20px;
  margin-left: 6px;
  border-radius: var(--radius-sm, 5px);
  cursor: pointer;
  vertical-align: middle;
  transition: background var(--motion-fast) var(--ease-standard),
              border-color var(--motion-fast) var(--ease-standard),
              color var(--motion-fast) var(--ease-standard);
}
.bench-ed-trigger > svg { display: block; }
.bench-ed-trigger:hover {
  background: var(--bg-warm);
  border-color: var(--accent);
  color: var(--accent);
}

/* 主图下方「对照线」编辑条 */
.bench-lines-ed-bar {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: 8px;
  margin: 6px 0 0;
}
.bench-lines-ed-cap {
  font-size: var(--fs-xs);
  color: var(--text-3);
}

/* 编辑面板 */
.bench-ed-panel {
  margin-top: var(--space-3);
  padding: 14px;
  background: var(--surface-2);
  border: 1px solid var(--border-1);
  border-radius: var(--radius-md);
}
.bench-ed-hint {
  font-size: var(--fs-xs);
  color: var(--text-3);
  margin-bottom: 10px;
  line-height: 1.4;
}
/* 行情退化黄条（renderDegradeWarn）：面板顶提示「市场历史部分失败」。 */
.bench-ed-warn {
  font-size: var(--fs-xs);
  color: var(--warn-deep);
  background: var(--warn-bg);
  border: 1px solid color-mix(in srgb, var(--warn-deep) 22%, transparent);
  border-radius: var(--radius-md);
  padding: 7px 10px;
  margin-bottom: 10px;
  line-height: 1.4;
}
.bench-ed-rows {
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.bench-ed-row {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
}
.bench-ed-row.is-bad {
  outline: 1px solid var(--dn);
  outline-offset: 4px;
  border-radius: 4px;
}
.bench-ed-select {
  appearance: auto;
  font-family: inherit;
  font-size: var(--fs-sm);
  padding: 5px 8px;
  border: 1px solid var(--border-2);
  background: var(--surface);
  color: var(--text-1);
  border-radius: 5px;
  min-width: 130px;
  cursor: pointer;
}
.bench-ed-custom {
  font-family: var(--mono);
  font-size: var(--fs-sm);
  padding: 5px 8px;
  width: 120px;
  border: 1px solid var(--accent);
  background: var(--accent-lt);
  color: var(--accent-deep);
  border-radius: 5px;
  box-sizing: border-box;
}
.bench-ed-wwrap {
  display: inline-flex;
  align-items: center;
  gap: 2px;
}
.bench-ed-input {
  font-family: var(--mono);
  font-variant-numeric: tabular-nums;
  font-weight: 600;
  font-size: var(--fs-sm);
  width: 48px;
  padding: 4px 2px 4px 6px;
  border: 1px solid var(--accent);
  background: var(--accent-lt);
  color: var(--accent-deep);
  border-radius: 4px;
  text-align: right;
  box-sizing: border-box;
}
.bench-ed-input::-webkit-inner-spin-button,
.bench-ed-input::-webkit-outer-spin-button {
  opacity: 1;
  cursor: pointer;
}
.bench-ed-input:focus,
.bench-ed-custom:focus {
  outline: 2px solid var(--accent);
  outline-offset: 1px;
}
.bench-ed-pct {
  font-size: var(--fs-sm);
  color: var(--text-2);
}
.bench-ed-del {
  appearance: none;
  border: 1px solid var(--border-2);
  background: var(--surface);
  color: var(--text-3);
  width: 24px;
  height: 24px;
  border-radius: 5px;
  cursor: pointer;
  font-size: 16px;
  line-height: 1;
  margin-left: auto;
}
.bench-ed-del:hover:not(:disabled) {
  border-color: var(--dn);
  color: var(--dn);
}
.bench-ed-del:disabled {
  opacity: 0.4;
  cursor: not-allowed;
}
.bench-ed-rowerr {
  font-size: var(--fs-xs);
  color: var(--dn);
  flex-basis: 100%;
}
.bench-ed-add {
  appearance: none;
  background: transparent;
  border: 1px dashed var(--border-2);
  border-radius: 6px;
  cursor: pointer;
  font-family: inherit;
  font-size: var(--fs-sm);
  color: var(--text-2);
  padding: 6px 10px;
  margin-top: 10px;
}
.bench-ed-add:hover {
  border-color: var(--accent);
  color: var(--accent);
}
.bench-ed-foot {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  margin-top: var(--space-3);
  padding-top: 12px;
  border-top: 1px solid var(--border-1);
}
.bench-ed-sum-chip {
  font-family: var(--font-body);
  font-variant-numeric: tabular-nums;
  font-size: var(--fs-sm);
  font-weight: 500;
  padding: 5px 10px;
  border-radius: 999px;
  background: var(--up-bg);
  color: var(--up);
}
.bench-ed-sum-chip.is-bad {
  background: var(--dn-bg);
  color: var(--dn);
}
.bench-ed-actions {
  display: flex;
  align-items: center;
  gap: 10px;
}

/* ═══ view-home § 4 · sec-holdings（mockup L3856–L3888 / L771–L1045 / L5461–L6046） ═══
 * 1:1 还原 mockup `frag-table` 容器（table-section / table-header / col-toggle /
 * table-wrap / thead.sortable / main-row / chevron / expand-row / expand-grid /
 * timeline / fundamentals-grid / exp-actions），归一化到唯一 :root token + 通用类。
 *
 * N10 占位：spark / rating / peRange / annReturn 在无 schema 字段时统一 .ph 占位。 */

#sec-holdings .section-header {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--space-3);
  margin-bottom: var(--space-3);
}

#sec-holdings .section-header-right {
  display: flex;
  align-items: center;
  gap: var(--space-2);
}

/* 列显示按钮 + popover（mockup L775–L850 1:1） */
.col-toggle-wrap {
  position: relative;
}

.col-toggle-btn {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 7px 14px;
  border: 1px solid var(--border-2);
  background: var(--surface);
  color: var(--text-2);
  border-radius: var(--radius-md);
  font-size: var(--fs-sm);
  line-height: 1.2;
  cursor: pointer;
  font-family: var(--font-body);
  transition: border-color var(--motion-fast) var(--ease-standard),
              color var(--motion-fast) var(--ease-standard),
              background var(--motion-fast) var(--ease-standard);
  user-select: none;
}

.col-toggle-btn:hover {
  border-color: var(--accent);
  color: var(--accent);
}

.col-toggle-btn.is-open {
  background: var(--accent-lt);
  border-color: var(--accent);
  color: var(--accent);
}

.col-toggle-icon {
  font-size: var(--fs-2xs);
  opacity: 0.8;
}

/* Filter 族（UI_SPEC §C.4）：chip-group + count + label；与 toggle 视觉不可混（详 §C.4.4）。
   sec-holdings status filter 用之；未来 alloc / 其他区域 filter 复用同一套 class。 */
.filter-component {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
  flex-wrap: wrap;
}
.filter-component-label {
  font-size: var(--fs-xs);
  color: var(--text-3);
  font-weight: 500;
  letter-spacing: 0.02em;
  margin-right: 4px;
  display: inline-flex;
  align-items: center;
  gap: 5px;
  white-space: nowrap;
}
.filter-component-chips {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
  flex-wrap: wrap;
}
.filter-chip {
  appearance: none;
  display: inline-flex;
  align-items: baseline;
  gap: 5px;
  background: transparent;
  border: 1px solid var(--border-2);
  color: var(--text-2);
  padding: 3px 10px;
  font-family: var(--font-body);
  font-size: var(--fs-2xs);
  letter-spacing: 0.04em;
  line-height: 1.4;
  border-radius: var(--radius-sm);
  cursor: pointer;
  transition: all var(--motion-fast);
}
.filter-chip:hover {
  border-color: var(--text-3);
  color: var(--text-1);
}
.filter-chip.is-active {
  background: var(--accent-lt);
  border-color: var(--accent);
  color: var(--accent-deep);
}
.filter-chip-text { font-weight: 400; }
.filter-chip.is-active .filter-chip-text { font-weight: 500; }
.filter-chip-count {
  font-family: var(--mono);
  font-variant-numeric: tabular-nums;
  font-size: var(--fs-2xs);
  color: var(--text-mute);
  transition: color var(--motion-fast);
}
.filter-chip.is-active .filter-chip-count {
  color: var(--accent-deep);
  font-weight: 600;
}
.filter-sep {
  width: 1px;
  height: 14px;
  background: var(--border-1);
  margin: 0 var(--space-2);
}

/* sec-holdings filter strip（UI_SPEC §C.4.3 Layout B'）：filter 独占 section-header 下方一行 */
#sec-holdings .holdings-filter-strip {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  flex-wrap: wrap;
  margin-bottom: var(--space-3);
}

/* 窄屏（问题 7）：三组 filter 各占一行、左侧标签等宽列 → 视图 / 持仓 / 账户分类 后面的
   chips 对齐成一竖列；去掉竖线分隔符（堆叠后无意义）。标签宽度按最长「账户分类」(4 字 ≈ 4.6em @11px)。 */
@media (max-width: 600px) {
  #sec-holdings .holdings-filter-strip {
    flex-direction: column;
    align-items: stretch;
  }
  #sec-holdings .filter-component-label {
    width: 4.6em;
    flex-shrink: 0;
  }
  #sec-holdings .filter-sep {
    display: none;
  }
}

.col-popover {
  position: absolute;
  top: calc(100% + 6px);
  right: 0;
  background: var(--surface);
  border: 1px solid var(--border-1);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-md);
  padding: 10px 4px;
  width: 220px;
  max-height: 80vh;
  overflow-y: auto;
  overscroll-behavior: contain;
  z-index: 50;
  display: none;
  animation: popIn var(--motion-fast) var(--ease-standard);
}

.col-popover.is-open {
  display: block;
}

.col-popover__title {
  font-family: var(--font-body);
  font-variant-numeric: tabular-nums;
  font-size: var(--fs-2xs);
  letter-spacing: 1.3px;
  text-transform: uppercase;
  color: var(--text-3);
  padding: 4px 12px 8px;
  border-bottom: 1px dashed var(--border-1);
  margin-bottom: 4px;
}

.col-item {
  display: flex;
  align-items: center;
  gap: 9px;
  padding: 6px 12px;
  cursor: pointer;
  border-radius: var(--radius-sm);
  margin: 1px 4px;
  transition: background var(--motion-fast) var(--ease-standard);
}

.col-item:hover {
  background: var(--bg-warm);
}

.col-item.is-locked {
  opacity: 0.5;
  cursor: not-allowed;
}

.col-item.is-locked:hover {
  background: transparent;
}

.col-chk {
  width: 14px;
  height: 14px;
  flex-shrink: 0;
  border: 1.5px solid var(--border-2);
  border-radius: 3px;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: var(--fs-2xs);
  color: white;
  background: var(--surface);
  transition: background var(--motion-fast) var(--ease-standard),
              border-color var(--motion-fast) var(--ease-standard);
}

.col-item.is-on .col-chk {
  background: var(--accent);
  border-color: var(--accent);
}

.col-label {
  font-size: var(--fs-sm);
  color: var(--text-2);
}

.col-item.is-on .col-label {
  color: var(--text-1);
}

/* ─── 表格本体 ────────────────────────────────────────────────────── */

.holdings-table-wrap {
  background: var(--surface);
  border: 1px solid var(--border-1);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-sm);
  overflow-x: auto;
  overflow-y: hidden;
  -webkit-overflow-scrolling: touch;
}

.holdings-table {
  width: 100%;
  border-collapse: collapse;
  /* 列宽由 <colgroup> 像素值承载（applyHoldingColWidths，BACKLOG E55 方案 B）——
     fixed 让 <col> 宽强制生效、列宽不再随行内容 reflow。详见 ADR 0053。 */
  table-layout: fixed;
}

.holdings-table thead th {
  padding: 11px 8px;
  text-align: left;
  font-family: var(--font-body);
  font-variant-numeric: tabular-nums;
  font-size: var(--fs-2xs); /* 10px，2026-05-07 与 Fidelity 实测对照后保留 */
  letter-spacing: 0;        /* 2026-05-07：原 1.2px 装饰小标对中文反效，取消 */
  text-transform: none;     /* 2026-05-07：中文 uppercase 无意义，取消 */
  color: var(--text-3);
  background: var(--bg-warm);
  border-bottom: 1px solid var(--border-1);
  white-space: nowrap;
  font-weight: 400;
}

.holdings-table thead th.is-right {
  text-align: right;
}

.holdings-table thead th.is-sortable {
  cursor: pointer;
  user-select: none;
  transition: color var(--motion-fast) var(--ease-standard),
              background var(--motion-fast) var(--ease-standard);
}

.holdings-table thead th.is-sortable:hover {
  color: var(--text-1);
  background: color-mix(in srgb, var(--accent-lt) 70%, var(--bg-warm));
}

.holdings-table thead th.is-active {
  color: var(--accent);
  background: var(--accent-lt);
}

.sort-icon {
  display: inline-block;
  width: 9px;
  margin-left: 5px;
  position: relative;
  top: 1px; /* ↕ 字形墨迹在自身盒内偏上（实测高 ~0.65px）→ 下推 1px 做光学居中 */
  opacity: 0;
  transition: opacity var(--motion-fast) var(--ease-standard);
  font-family: var(--font-body);
  font-variant-numeric: tabular-nums;
  font-size: var(--fs-xs);
}

.holdings-table thead th.is-sortable:hover .sort-icon {
  opacity: 0.7;
}

.holdings-table thead th.is-active .sort-icon {
  opacity: 1;
  color: var(--accent);
}

/* 列拖拽视觉：grab cursor + 拖动中半透明 + drop 落点 inset 边（不影响列宽） */
.holdings-table thead th[draggable="true"] {
  cursor: grab;
}
.holdings-table thead th[draggable="true"]:active {
  cursor: grabbing;
}
.holdings-table thead th.is-dragging {
  opacity: 0.4;
}
.holdings-table thead th.drop-before {
  box-shadow: inset 2px 0 0 var(--accent);
}
.holdings-table thead th.drop-after {
  box-shadow: inset -2px 0 0 var(--accent);
}

.holdings-table .main-row {
  border-bottom: 1px solid var(--border-1);
  transition: background var(--motion-fast) var(--ease-standard);
  cursor: pointer;
}

.holdings-table .main-row:hover {
  background: var(--surface-2);
}

.holdings-table .main-row.is-expanded {
  background: var(--surface-tint);
}

.holdings-table td {
  padding: 13px 8px;
  vertical-align: middle;
}

.holdings-table td.is-right {
  text-align: right;
  white-space: nowrap; /* 防"−¥XXX,XXX.00"等大数字被窄列折成 2 行；溢出由 .holdings-table-wrap 横滚兜底 */
}

/* spark 列上下 padding 缩到 4px：给加高的 52W 走势线（svg 28 / 线 26，buildSparkCell）腾竖向空间，
   而 cell（svg28+gap3+脚注10 = 41px）仍 < 标的名两行（~34.5+padding）→ 名字仍钉住行高、行高不变
   （桌面 62 / 窄屏 54）。attribute 选择器特异性(0,0,2,1) > 基础 .holdings-table td 与 @media≤900px 的
   .holdings-table td (0,0,1,1)，故桌面 13→4、窄屏 9→4 两态都被它覆盖；横向 8px 不变。 */
.holdings-table td[data-col-id="spark"] {
  padding-top: 4px;
  padding-bottom: 4px;
}

/* sticky 锁定列：chev + name 两列在横滚时贴左缘（追赶式吸附 —— 横滚后 country 被遮在后面）
   chev 列在 HOLDING_COLUMNS 中 width=22px（view-home-holdings.js:125），name 紧贴其右
   （故下方 name 的 sticky left 必须 = chev 列宽，两者改动需同步）
   chev td padding-left=12px：保留 country 色块↔chevron 的左侧呼吸；列宽 22px = 12 左 + 6 字形
   + 余量，刚好容下展开态（旋转 90°）的 chevron 不被切
   sticky cell 背景使用 var(--surface)（白色）与 .holdings-table-wrap 同色，默认态视觉无突兀 */
.holdings-table td[data-col-id="chev"],
.holdings-table th[data-col-id="chev"] {
  position: sticky;
  left: 0;
  z-index: 1;
  background: var(--surface);
  padding-left: 12px; /* country 色块↔chevron 左侧呼吸（不随全局 td 横 padding 8px 收紧） */
}
.holdings-table td[data-col-id="name"],
.holdings-table th[data-col-id="name"] {
  position: sticky;
  left: 22px;
  z-index: 1;
  background: var(--surface);
}
/* sticky cell 自身背景（+z-index 抬层）会盖住写在 <tr> 上的 .main-row border-bottom，
   令 chev / name 两列看不到行分隔线 —— 让单元格自己画一条等宽同色的底边补回 */
.holdings-table td[data-col-id="chev"],
.holdings-table td[data-col-id="name"] {
  border-bottom: 1px solid var(--border-1);
}
.holdings-table thead th[data-col-id="chev"],
.holdings-table thead th[data-col-id="name"] {
  z-index: 2;
  background: var(--bg-warm);
}
/* hover / expanded：sticky cell 背景跟随主行高亮，避免横滚时露出"白色 sticky cell 叠灰色主行"反差 */
.holdings-table .main-row:hover td[data-col-id="chev"],
.holdings-table .main-row:hover td[data-col-id="name"] {
  background: var(--surface-2);
}
.holdings-table .main-row.is-expanded td[data-col-id="chev"],
.holdings-table .main-row.is-expanded td[data-col-id="name"] {
  background: var(--surface-tint);
}

.t-name-cell {
  font-size: var(--fs-base);
  font-weight: 500;
  color: var(--text-1);
  display: inline-flex;
  align-items: center;
  gap: 6px;
}

.t-meta {
  font-family: var(--font-body);
  font-variant-numeric: tabular-nums;
  font-size: var(--fs-2xs);
  color: var(--text-3);
  margin-top: 1px;
}

.type-tag {
  font-family: var(--mono);
  font-size: var(--fs-xs);
  padding: 1px 5px;
  border-radius: 3px;
  letter-spacing: 0.3px;
  font-weight: 500;
  white-space: nowrap; /* 防"手动"等 2 字 chip 在窄父列被折成 2 行 */
}

.type-tag--manual {
  background: var(--chart-purple-bg);
  color: var(--chart-purple);
}

.holdings-table .dim  { color: var(--text-3); }
.holdings-table .sm   { font-size: var(--fs-xs); white-space: nowrap; } /* nowrap 防"未满 1 年"等灰字配角被窄列折行 */
.holdings-table td    { font-variant-numeric: tabular-nums; } /* N6 · 双字体架构兜底数字对齐 */

.holdings-table .c-up { color: var(--up); }
.holdings-table .c-dn { color: var(--dn); }

/* 持仓表主数字：14 列共用（现价 / 市值 / 持股数 + 各类盈亏 + 自建仓/窗口年化）。
 * 字距 -0.04em em 单位按比例缩放，收紧程度与字号无关；保持 Inter 不违反 §0.12。 */
.holdings-table .holding-num {
  font-size: var(--fs-sm);
  letter-spacing: -0.04em;
}
/* 未染色主数字（现价 / 市值 / 持股数）降一档，与 flag-tag 同深，不再是全表最深。
 * 染色数字带 .c-up/.c-dn 自带颜色、不加本 modifier，互不影响。 */
.holdings-table .holding-num--flat {
  color: var(--text-2);
}

/* 仓位占比 bar */
.bar-wrap {
  display: flex;
  align-items: center;
  gap: 6px;
  justify-content: flex-end;
}

.bar-bg {
  width: 52px;
  height: 4px;
  background: var(--border-1);
  border-radius: 2px;
  overflow: hidden;
}

.bar-fill {
  height: 100%;
  border-radius: 2px;
}

/* 评级 / type 通用 badge */
.badge-pill {
  display: inline-block;
  padding: 3px 8px;
  border-radius: var(--radius-sm);
  font-size: var(--fs-2xs);
  font-family: var(--mono);
  white-space: nowrap;
  font-weight: 500;
}

/* chevron */
.chevron {
  color: var(--text-3);
  font-size: 14px;
  font-weight: 700;
  transition: transform var(--motion-base) var(--ease-standard),
              opacity var(--motion-fast) var(--ease-standard);
  display: inline-block;
  opacity: 0;
  line-height: 1;
}

.holdings-table .main-row:hover .chevron,
.holdings-table .main-row.is-expanded .chevron {
  opacity: 1;
}

/* 「资金属地 / 账户」两列合并格 hover 豁免：合并格（rowspan）在 DOM 上归属合并块段首行，
   鼠标悬于其上原会令段首行错位变灰 + 浮现箭头（鼠标停在格中下部、变灰的却是第一行）。
   用 :has 侦测"当前悬停目标是这两列的 cell"时，把该行背景与箭头压回默认态 → 这两列悬停时屏幕无反应。
   .is-expanded 是点击后的持久态（非 hover），用 :not 排除，展开行视觉不受影响。
   退化态（未合并）下两列 td 同样带 data-col-id，一并豁免，合并/退化口径一致。 */
.holdings-table .main-row:not(.is-expanded):has(> td[data-col-id="country"]:hover, > td[data-col-id="account"]:hover) {
  background: transparent;
}
.holdings-table .main-row:not(.is-expanded):has(> td[data-col-id="country"]:hover, > td[data-col-id="account"]:hover) td[data-col-id="chev"],
.holdings-table .main-row:not(.is-expanded):has(> td[data-col-id="country"]:hover, > td[data-col-id="account"]:hover) td[data-col-id="name"] {
  background: var(--surface);
}
.holdings-table .main-row:not(.is-expanded):has(> td[data-col-id="country"]:hover, > td[data-col-id="account"]:hover) .chevron {
  opacity: 0;
}

.chevron.is-open {
  transform: rotate(90deg);
  opacity: 1;
}

/* country 列分组合并（ADR 0019 + §实施修订）—— rowspan 在 expand-row 处显式切段：
   - 块内无展开 → 单段 rowspan = 全块行数，hgr-cell 写「中国」 vertical-align:middle 居中
   - 块内有展开 → 切两段：pre rowspan = 块首到展开行（写文字），post rowspan = 展开行后（仅延续色块）
   - expand-row colspan = N 全宽（不再写 .hgr-filler 让位）
   - box-shadow inset 替代 border-left（不挤压 content，cell content 中心与 thead 中心对齐） */
.holdings-table .hgr-cell {
  width: 80px;
  background: var(--bg-warm);
  box-shadow: inset 3px 0 0 var(--bench-csi);
  border-right: 1px solid var(--border-1);
  border-bottom: 1px solid var(--border-1);
  text-align: center;
  vertical-align: middle;
  font-size: var(--fs-xs);
  font-weight: 500;
  color: var(--text-1);
  padding: 8px;
  user-select: none;
  white-space: nowrap;
}
.holdings-table .hgr-cell[data-country="US"] {
  box-shadow: inset 3px 0 0 var(--bench-spy);
}
.holdings-table .hgr-cell[data-country="HK"] {
  box-shadow: inset 3px 0 0 var(--bench-hsi);
}

/* hgr-cell 内的 .hgr-label —— renderHoldingTbody 后 anchorCountryLabels() 会写
   inline transform: translateY 把文字推到原全块中心（rowspan 切段后修偏移）。
   inline-block 让 transform 生效；will-change 让 transform 走 compositor 不引发 reflow。 */
.holdings-table .hgr-cell .hgr-label {
  display: inline-block;
  will-change: transform;
}

/* account 列分组合并（ADR 0103，与 country 同类 rowspan 切段，无色块 spine）：
   - 同账户多行用真 rowspan 合并、账户名 vertical-align:middle 居中
   - 固定白底 var(--surface) → 任何行 hover 都不高亮账户合并格（同 hgr-cell bg-warm 稳定思路）
   - 边界用普通 1px 行线，不加粗（用户要求） */
.holdings-table .acct-merge-cell {
  background: var(--surface);
  border-bottom: 1px solid var(--border-1);
  text-align: center;
  vertical-align: middle;
  font-size: var(--fs-xs);
  color: var(--text-1);
  padding: 8px;
  white-space: nowrap;
}
/* .acct-label —— renderHoldingTbody 后 anchorLabels() 写 inline transform:translateY 推到
   anchor 主行中点（rowspan 切段后修偏移）。inline-block 让 transform 生效；will-change 走 compositor。 */
.holdings-table .acct-merge-cell .acct-label {
  display: inline-block;
  will-change: transform;
}

/* country / account 列表头居中（合并态视觉一致）；退化态 cell 仍走 td 默认左对齐。
   sort-icon 改绝对定位避免占 14px 行内空间把可见文字向左推（与合并格真居中对齐）。 */
.holdings-table th[data-col-id="country"] {
  width: 80px;
  text-align: center;
  position: relative;
}
.holdings-table th[data-col-id="account"] {
  text-align: center;
  position: relative;
}
.holdings-table th[data-col-id="country"] .sort-icon,
.holdings-table th[data-col-id="account"] .sort-icon {
  position: absolute;
  right: 1px;          /* gap 与其它列 inline 箭头对齐（5px，原 right:8 让文字与箭头互嵌 2px → 用户反馈"挤"） */
  top: calc(50% + 1px);/* 居中 + 下推 1px 做光学居中（与全局 .sort-icon { top: 1px } 同步，跨列箭头 Y 一致） */
  transform: translateY(-50%);
  margin-left: 0;
}

/* 分类 dim-badge 走基础灰底（2026-05-07 去彩色，原 6 类 .dim-badge--<key> override 已删） */
.dim-badge {
  display: inline-block;
  padding: 2px 7px;
  border-radius: var(--radius-sm);
  font-family: var(--mono);
  font-size: var(--fs-xs);
  letter-spacing: 0.2px;
  font-weight: 500;
  background: var(--bg-warm);
  color: var(--text-2);
  white-space: nowrap;
}

.flag-tag {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  font-family: var(--mono);
  font-size: var(--fs-xs);
  color: var(--text-2);
  font-weight: 500;
  white-space: nowrap; /* chip 内文字不被父级窄列折行 */
}

.account-cell {
  font-family: var(--font-body);
  font-size: var(--fs-xs);
  color: var(--text-2);
  white-space: nowrap;
}

/* ─── 行展开：手风琴模式 ───────────────────────────────────────────── */

.expand-row { display: none; }
.expand-row.is-show { display: table-row; }

.expand-cell {
  padding: 0 !important;
  border-bottom: 1px solid var(--border-1);
  background: var(--surface-tint);
}

.expand-inner {
  position: sticky;
  left: var(--layout-padding-x);
  /* 风格 B（左右各让 24）：panel 在 wrap 可视区内**对称**留出 layout-padding-x，
   * 视觉是悬浮卡片感、与 layout grid 不贴边。
   * 必须满足 panel.right ≤ wrap.clientWidth，否则末尾会被 wrap 横滚剪掉。
   *   wrap.clientWidth = min(viewport, --layout-max-width) - 2*pad - 2px(wrap border)
   *   panel.right (相对 wrap origin) = left + width = pad + width
   *   要 panel.right ≤ clientWidth 且左右对称留 pad
   *   → width = clientWidth - 2*pad = min(vp, max-w) - 4*pad - 2px
   * 之前两次错版：
   *   commit 6aea281: width = min(vp - 2*pad, max-w) —— viewport >1400 时算出 1400, 远超 clientW
   *   commit d383c1b: width = min(vp, max-w) - 2*pad - 2px —— 算出 = clientW, 但 left:pad 让右
   *     边超出 clientW 一个 pad 量（user 永远只能看到左 gap 或末段平移后的右 gap，看不到对称）。
   * 详见 ADR 0046 D4 errata 第 2 版。 */
  width: calc(min(100vw, var(--layout-max-width)) - var(--layout-padding-x) * 4 - 2px);
  box-sizing: border-box;
  padding: 24px 28px 26px;
}

.expand-grid {
  display: grid;
  /* 股价图:持仓 = 45:55 — chart 侧占 45%，持仓 lot/timeline 侧占 55%。
   * chart SVG 用 viewBox + width:100% + height:auto，栏变窄时高度按比例等比缩小（不只是缩窄）。
   * minmax(0, Nfr) 防超大子内容（如 lot 表 7 列）撑大 track、忽略比例。 */
  grid-template-columns: minmax(0, 45fr) minmax(0, 55fr);
  gap: 32px;
}

.exp-title {
  font-family: var(--font-body);
  font-variant-numeric: tabular-nums;
  font-size: var(--fs-2xs);
  letter-spacing: 1.5px;
  text-transform: uppercase;
  color: var(--accent);
  margin-bottom: 14px;
  padding-bottom: 7px;
  border-bottom: 1px solid var(--border-1);
}

.exp-empty {
  font-size: var(--fs-xs);
  color: var(--text-mute);
  padding: 8px 0;
}

/* timeline */
.tl {
  display: flex;
  flex-direction: column;
}

.tl-item {
  display: flex;
  gap: 12px;
  padding-bottom: 12px;
  position: relative;
}

.tl-item:not(:last-child)::before {
  content: "";
  position: absolute;
  left: 6px;
  top: 15px;
  width: 1px;
  bottom: 0;
  background: var(--border-1);
}

.tl-dot {
  width: 13px;
  height: 13px;
  border-radius: var(--radius-pill);
  border: 2px solid var(--border-2);
  background: var(--surface);
  flex-shrink: 0;
  margin-top: 1px;
  position: relative;
  z-index: 1;
}

.tl-dot--buy    { border-color: var(--up);             background: var(--up-bg); }
.tl-dot--sell   { border-color: var(--dn);             background: var(--dn-bg); }
.tl-dot--div    { border-color: var(--accent);         background: var(--accent-lt); }
.tl-dot--cash   { border-color: var(--chart-teal);     background: var(--chart-teal-bg); }
.tl-dot--adjust { border-color: var(--text-mute);      background: var(--bg-warm); }
.tl-dot--snap   { border-color: var(--text-mute);      background: var(--bg-warm); }

.tl-content {
  flex: 1;
  min-width: 0;
}

.tl-head {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
}

.tl-date {
  font-family: var(--font-body);
  font-variant-numeric: tabular-nums;
  font-size: var(--fs-xs);
  color: var(--text-3);
}

.tl-type {
  font-size: var(--fs-2xs);
  padding: 1px 7px;
  border-radius: 3px;
  font-family: var(--font-body);
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.3px;
  font-weight: 500;
}

.tl-type--buy    { background: var(--up-bg);            color: var(--up); }
.tl-type--sell   { background: var(--dn-bg);            color: var(--dn); }
.tl-type--div    { background: var(--accent-lt);        color: var(--accent); }
.tl-type--cash   { background: var(--chart-teal-bg);    color: var(--chart-teal); }
.tl-type--adjust { background: var(--bg-warm);          color: var(--text-2); }
.tl-type--snap   { background: var(--bg-warm);          color: var(--text-2); }

/* ADR 0044：timeline 行 × 删除按钮（含 VALUE_SNAP 误录可撤） */
.tl-del-btn {
  margin-left: 4px;
  width: 18px;
  height: 18px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: transparent;
  border: none;
  color: var(--text-3);
  cursor: pointer;
  border-radius: 3px;
  font-size: 14px;
  line-height: 1;
  padding: 0;
  opacity: 0.5;
  transition: opacity 0.15s, background 0.15s, color 0.15s;
}
.tl-item:hover .tl-del-btn { opacity: 1; }
.tl-del-btn:hover {
  background: var(--dn-bg);
  color: var(--dn);
}

/* ADR 0044：持仓表「当前估值」列 staleness 小字（VALUE_SNAP.date < today 时显示） */
.holding-cv-staleness {
  font-family: var(--font-body);
  font-variant-numeric: tabular-nums;
  font-size: var(--fs-2xs);
  color: var(--text-3);
  margin-top: 1px;
}

.tl-desc {
  margin-left: auto;
  font-size: var(--fs-sm);
  color: var(--text-2);
  font-variant-numeric: tabular-nums;
  text-align: right;
  white-space: nowrap;
}

.tl-desc strong {
  color: var(--text-1);
  font-family: var(--font-body);
  font-variant-numeric: tabular-nums;
  font-weight: 500;
}

.tl-note {
  font-size: var(--fs-xs);
  color: var(--text-3);
  margin-top: 2px;
  font-style: italic;
}

/* ─── Purchase history lots 表（API_AUTO 持仓详情右栏专用） ──────────
 * UI_SPEC §2.X — 7 列：日期 / 盈亏(¥) / 盈亏(%) / 当前市值 / 数量 / 单价 / 成本。
 * 数据源 deriveApiAutoLots（CONTRACT §6.4 lot 视图）。
 * CASH/MANUAL 持仓仍走 .tl-* timeline，不复用本组样式。
 */
.exp-lots-table {
  width: 100%;
  border-collapse: collapse;
  /* table-layout: fixed 让 7 列按 width 均匀分配栏宽（autosize 会根据内容把"成本"列拉得过宽）。
   * 配合下方 :nth-child 给百分比列稍窄一些（"+25.18%" 比 "$11,436.50" 短），其他列均分。 */
  table-layout: fixed;
  font-family: var(--font-body);
  font-variant-numeric: tabular-nums;
  font-size: var(--fs-sm);
}

.exp-lots-table thead th {
  /* font-size: var(--fs-2xs) (10px) 与主 .holdings-table thead 统一（"表头本就该比
   * body 小一档"惯例）；body 仍 --fs-sm (12px)。text-transform: none 显式挡掉
   * .holdings-table thead th 的 uppercase bleed（汉字 uppercase 无效但语义不对）。
   * background: var(--bg-warm) 是显式选择（非 bleed 兜底）—— 表头浅暖底块当作
   * 视觉分隔，因此 border-bottom: 0（不再叠分割线）。tbody td 仍保留 row 间分割线。 */
  padding: 5px 8px;
  text-align: left;
  font-size: var(--fs-2xs);
  letter-spacing: 0.4px;
  text-transform: none;
  background: var(--bg-warm);
  color: var(--text-3);
  font-weight: 400;
  border-bottom: 0;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.exp-lots-table thead th.is-right {
  text-align: right;
}

/* 列宽分布（table-layout: fixed 下 thead width 决定列宽）：
 *   1 买入日期 24% / 2 盈亏 18% / 3 盈亏 % 18% / 4 持仓市值/售出额 20% / 5 成本 20%
 * 总和 100%。列 1 加宽以容纳「2024-10-17 + 已卖出 pill」（cell 内容需 ~140px）：
 *   @ 1440 视口右栏 668px，24% = 160px，buffer 20px ✓
 *   @ 1280 视口右栏 602px，24% = 144px，buffer 4px ✓
 *   < 1280 视口 buffer 不足，按 UI_SPEC §2.9.4.1 设计目标 1280px 以上。金额列对称占右。 */
.exp-lots-table thead th:nth-child(1) { width: 24%; }
.exp-lots-table thead th:nth-child(2) { width: 18%; }
.exp-lots-table thead th:nth-child(3) { width: 18%; }
.exp-lots-table thead th:nth-child(4) { width: 20%; }
.exp-lots-table thead th:nth-child(5) { width: 20%; }

.exp-lots-table tbody td {
  padding: 10px 8px;
  border-bottom: 1px solid var(--border-1);
  color: var(--text-2);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.exp-lots-table tbody tr:last-child td {
  border-bottom: 0;
}

/* .exp-lots-date 类保留在 HTML（view-home.js renderLotsTable）作为未来定制
 * 钩子；当前无视觉规则，颜色 / 字号 / letter-spacing 全继承 tbody td。 */

.exp-lots-num {
  text-align: right;
}

/* 涨跌色：盈亏(¥) 和 盈亏(%) 列跟着行的方向 token；其它列不染色 */
.exp-lots-row.is-up    .exp-lots-num:nth-child(2),
.exp-lots-row.is-up    .exp-lots-num:nth-child(3) { color: var(--up); }
.exp-lots-row.is-down  .exp-lots-num:nth-child(2),
.exp-lots-row.is-down  .exp-lots-num:nth-child(3) { color: var(--dn); }

/* 截断模式：lots > 10 时，table 加 .is-collapsed，11+ 行加 .exp-lots-row--overflow，
 * 此规则隐藏溢出行；点「显示全部」由 JS 移除 .is-collapsed 类，全部还原。 */
.exp-lots-table.is-collapsed .exp-lots-row--overflow {
  display: none;
}

/* lot 状态 badge（ADR 0045）：仅已卖行渲染「已卖出」标签，inline 标在日期单元格内
 * 右侧。剩余行（未卖过 / 部分卖出 lot 的剩余部分）不渲染 badge — 行视觉上无标签
 * 即代表 "持仓中"，与 row 类型一一对应。形态对齐同模块先例 .tl-type（CASH/MANUAL
 * timeline 的事件类型标签）：3px 圆角矩形 + 1px 7px padding，不用 pill 椭圆
 * （已卖是事件类型标签，与 .tl-type 同类）。中性灰（--divider / --text-3）不复用
 * --dn 红色，因为它是状态标签、非 P&L 方向，避免与列 2/3 染色语义冲突。 */
.exp-lots-badge {
  display: inline-block;
  margin-left: 6px;
  padding: 1px 7px;
  border-radius: 3px;
  font-size: 9px;
  letter-spacing: 0.3px;
  vertical-align: middle;
  font-family: var(--mono);
}
.exp-lots-badge--sold { background: var(--divider); color: var(--text-3); }
/* RSU 角标（钴蓝调）：标记买卖记录里由 vest BUY 派生的 lot 行（E34 Block A） */
.exp-lots-badge--rsu { background: var(--accent-lt); color: var(--accent-deep); }

/* ── E34 RSU 解禁进度（持仓展开两栏下方全宽区 + 点阵 5 态；ADR 0030/0033/0105）── */
.rsu-section {
  margin-top: var(--space-5);
  padding-top: var(--space-4);
  border-top: 1px solid var(--divider);
}
.rsu-cards {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  margin-top: var(--space-3);
}
.rsu-card {
  background: var(--surface-2);
  border: 1px solid var(--border-1);
  border-radius: var(--radius-md);
  padding: var(--space-3) var(--space-4);
}
.rsu-card-head {
  display: flex;
  align-items: baseline;
  gap: var(--space-3);
  flex-wrap: wrap;
}
.rsu-card-sym {
  font-weight: 600;
  font-size: var(--fs-md);
  color: var(--text-1);
  letter-spacing: 0.01em;
}
.rsu-card-tpl { font-size: var(--fs-xs); color: var(--text-3); }
/* 派生显示名：卡片抬头里认「哪一笔」的主要依据 */
.rsu-card-label { font-size: var(--fs-xs); color: var(--text-2); }
/* 券商授予编号：对账锚点，日常不需要读 → 最弱一档 + 等宽便于跟券商后台逐位核对 */
.rsu-card-award {
  font-size: var(--fs-2xs);
  color: var(--text-3);
  font-family: var(--font-mono, ui-monospace, monospace);
}
/* 表单字段下的说明行（去哪找这个编号）*/
.rsu-field-hint {
  display: block;
  margin-top: 4px;
  font-size: var(--fs-2xs);
  color: var(--text-3);
  line-height: 1.5;
}
.rsu-field-hint code {
  font-family: var(--font-mono, ui-monospace, monospace);
  font-size: 0.95em;
}
.rsu-card-stats {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2) var(--space-5);
  margin-top: var(--space-2);
}
.rsu-stat { display: inline-flex; align-items: baseline; gap: 6px; }
.rsu-stat-label { font-size: var(--fs-xs); color: var(--text-3); }
.rsu-stat-val { font-size: var(--fs-base); color: var(--text-1); font-variant-numeric: tabular-nums; }

.rsu-dot-grid {
  display: flex;
  flex-wrap: wrap;
  gap: 7px;
  margin-top: var(--space-3);
}
.rsu-dot-cell { position: relative; display: inline-flex; }
.rsu-dot {
  width: 14px;
  height: 14px;
  border-radius: var(--radius-xs);   /* 方格（非圆点） */
  box-sizing: border-box;
  display: inline-block;
  /* 自身建立定位上下文：作废态 ::after 斜纹用 position:absolute; inset:0，
     必须钳在 14px(图例 11px) 点内。图例「作废」swatch 是裸 .rsu-dot（无
     .rsu-dot-cell 定位祖先），缺此则 ::after 逃逸到面板级容器画出巨型斜纹。 */
  position: relative;
}
.rsu-dot--vested  { background: var(--accent); }
.rsu-dot--zero    { background: var(--text-mute); }   /* 实心灰 = 发生过但到手 0，非空格 */
.rsu-dot--pending {
  background: var(--warn-bg);
  border: 1.5px solid var(--warn);
  animation: rsu-pulse 1.6s var(--ease-standard) infinite;
}
.rsu-dot--future  { background: transparent; border: 1.5px solid var(--border-2); }
.rsu-dot--void    { background: var(--divider); opacity: 0.5; }
.rsu-dot--void::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(to bottom right, transparent 44%, var(--text-3) 44%, var(--text-3) 56%, transparent 56%);
}
@keyframes rsu-pulse {
  0%, 100% { box-shadow: 0 0 0 0 rgba(196, 106, 31, 0); }
  50%      { box-shadow: 0 0 0 3px rgba(196, 106, 31, 0.18); }
}

/* 点阵格悬停气泡（借 .freshness-tooltip 视觉 + 自带触发选择器，ADR 0105 / P2a）*/
.rsu-dot-tooltip {
  position: absolute;
  bottom: calc(100% + 6px);
  left: 50%;
  transform: translateX(-50%) translateY(2px);
  z-index: 100;
  display: flex;
  flex-direction: column;
  gap: 3px;
  min-width: 120px;
  max-width: 240px;
  padding: 8px 10px;
  background: var(--surface);
  border: 1px solid var(--border-1);
  border-radius: var(--radius-md);
  box-shadow: 0 4px 16px rgba(0, 0, 0, 0.18);
  font-size: var(--fs-xs);
  line-height: 1.5;
  white-space: nowrap;
  color: var(--text-1);
  opacity: 0;
  pointer-events: none;
  transition: opacity 120ms var(--ease-standard), transform 120ms var(--ease-standard);
}
.rsu-dot-cell[data-has-tooltip="1"]:hover .rsu-dot-tooltip {
  opacity: 1;
  transform: translateX(-50%) translateY(0);
}
.rsu-tip-head { font-weight: 600; color: var(--text-2); }
.rsu-tip-row { color: var(--text-1); }
.rsu-tip-row.rsu-tip-warn { color: var(--warn-deep); font-weight: 600; }
.rsu-tip-sub { color: var(--text-3); font-size: var(--fs-2xs); }

.rsu-legend {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2) var(--space-4);
  margin-top: var(--space-3);
  font-size: var(--fs-2xs);
  color: var(--text-3);
}
.rsu-legend-item { display: inline-flex; align-items: center; gap: 5px; }
.rsu-legend-item .rsu-dot { width: 11px; height: 11px; }
.rsu-legend-item .rsu-dot--pending { animation: none; }   /* 图例不闪 */

/* ── RSU tab（数据管理浮层第 5 个 tab · 待办优先三段布局；E34 Block B1） ────
   ① 顶部待确认 vest 卡（无待办则整块不渲染）② 中段全部 grant 总览卡（复用 .rsu-card）
   ③ 角落两个工具入口按钮。B1 只读骨架；卡片复用 .card / 点阵复用 .rsu-* 视觉。 */
.rsu-panel { display: flex; flex-direction: column; gap: 20px; }

/* ③ 角落工具入口（右上） */
.rsu-toolbar { display: flex; justify-content: flex-end; gap: 8px; }
.rsu-toolbar .btn.is-active { border-color: var(--accent); color: var(--accent); }

/* ① 待确认 vest 卡（B3：行可展开确认表单） */
.rsu-pending-card { padding: var(--card-padding-lg); }
.rsu-pending-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; }
.rsu-pending-row {
  padding: var(--space-2) 0;
  border-bottom: 1px solid var(--divider);
}
.rsu-pending-row:last-child { border-bottom: 0; }
.rsu-pending-main {
  display: flex;
  align-items: baseline;
  gap: var(--space-3);
}
.rsu-pending-sym { font-weight: 600; color: var(--text-1); min-width: 64px; }
/* 派生显示名（授予年月 · 总股数）——同 symbol 多笔授予时靠它区分；弱于 symbol、强于日期 */
.rsu-pending-label { font-size: var(--fs-sm); color: var(--text-2); }
.rsu-pending-period { font-size: var(--fs-sm); color: var(--text-2); }
.rsu-pending-date { font-size: var(--fs-sm); color: var(--warn-deep); }
.rsu-pending-cta { margin-left: auto; }

/* 行内确认 vest 表单（四数：应发 / 代税 / FMV / 到手） */
.rsu-confirm-form {
  margin-top: var(--space-3);
  padding: var(--space-3);
  background: var(--surface-tint);
  border: 1px solid var(--divider);
  border-radius: var(--radius-md);
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}
.rsu-confirm-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: var(--space-3);
}
.rsu-confirm-field { display: flex; flex-direction: column; gap: var(--space-1); }
.rsu-confirm-field .form-input-sm { width: 100%; }
.rsu-confirm-note { font-size: var(--fs-2xs); color: var(--text-mute); }
.rsu-confirm-net { justify-content: flex-start; }
.rsu-confirm-netval {
  font-weight: 600;
  color: var(--text-1);
  font-variant-numeric: tabular-nums;
  padding-top: 2px;
}
.rsu-confirm-actions { display: flex; align-items: center; gap: var(--space-2); }
.rsu-confirm-actions__spacer { flex: 1; }

/* ③ 导入 RSU 追踪 JSON 区（B3；从「数据维护」tab 迁来） */
.rsu-import-card { padding: var(--card-padding-lg); display: flex; flex-direction: column; gap: var(--space-4); }
.rsu-drop {
  border: 2px dashed var(--border-2);
  border-radius: var(--radius-lg);
  padding: 28px 24px;
  text-align: center;
  background: var(--surface-tint);
  transition: border-color var(--motion-base) var(--ease-standard),
              background var(--motion-base) var(--ease-standard);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
}
.rsu-drop.is-dragover { border-color: var(--accent); background: var(--accent-lt); }
.rsu-drop__icon { display: block; width: 32px; height: 32px; margin: 0 auto 10px; color: var(--accent); }
.rsu-drop__title { font-size: var(--fs-md); font-weight: 500; color: var(--text-1); margin-bottom: 14px; }
.rsu-drop__actions { display: inline-flex; gap: 8px; justify-content: center; margin-bottom: 12px; }
.rsu-drop__hint { font-size: var(--fs-2xs); color: var(--text-mute); letter-spacing: 0.3px; }

.rsu-import-banner {
  border: 1px solid var(--border-1);
  border-radius: var(--radius-md);
  padding: var(--space-4) var(--space-5);
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}
.rsu-import-banner--info { background: var(--accent-lt); border-color: var(--border-2); }
.rsu-import-banner--ok { background: var(--up-bg); border-color: var(--up); color: var(--up); }
.rsu-import-banner--err { background: var(--dn-bg); border-color: var(--dn); }
.rsu-import-banner__title { font-weight: 600; font-size: var(--fs-md); }
.rsu-import-banner--err .rsu-import-banner__title { color: var(--dn); }
.rsu-import-banner__body { font-size: var(--fs-sm); color: var(--text-2); }

.rsu-import-loaded {
  border: 1px solid var(--border-2);
  border-radius: var(--radius-md);
  padding: var(--space-3) var(--space-4);
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}
.rsu-import-loaded__head { display: flex; align-items: center; gap: var(--space-2); flex-wrap: wrap; }
.rsu-import-loaded__icon { color: var(--up); font-weight: 700; }
.rsu-import-loaded__name { font-weight: 600; color: var(--text-1); }
.rsu-import-loaded__meta { font-size: var(--fs-xs); color: var(--text-3); }
.rsu-import-actions { display: flex; gap: var(--space-2); }
.rsu-import-newacc { font-size: var(--fs-xs); color: var(--text-3); }
.rsu-import-warns { font-size: var(--fs-xs); }
.rsu-import-warns__title { color: var(--warn-deep); font-weight: 600; margin-bottom: var(--space-1); }
.rsu-import-warns ul { margin: 0; padding-left: 1.2em; color: var(--text-3); }
/* 导入记录 / 撤销卡：从「导入 JSON」折叠区移出后，常驻 RSU tab 底部作独立卡（ADR 0115）。 */
.rsu-import-history { padding: var(--card-padding-lg); }

/* ② 全部 grant 总览卡 */
.rsu-overview-card { padding: var(--card-padding-lg); }
.rsu-overview-cards {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
  gap: var(--space-4);
  margin-top: var(--space-4);
}
.rsu-grant-block { display: flex; flex-direction: column; }
.rsu-grant-next {
  margin-top: var(--space-2);
  padding-left: var(--space-2);
  font-size: var(--fs-xs);
  color: var(--text-3);
}
.rsu-empty { margin: var(--space-3) 0 0; font-size: var(--fs-sm); color: var(--text-3); }

/* ③ 录新 grant 表单（B2；ADR 0107）—— 复用 .asset-form__grid / .form-input-sm */
.rsu-grant-form-card { padding: var(--card-padding-lg); }
.rsu-grant-form { display: flex; flex-direction: column; gap: var(--space-4); margin-top: var(--space-3); }
/* 桶下拉外层 wrap：内部即 .asset-form__field，display:contents 让它直接落进 grid 列 */
.rsu-bucket-wrap { display: contents; }

.rsu-vestplan { display: flex; flex-direction: column; gap: var(--space-2); }
.rsu-vestplan-hint { margin: 0; font-size: var(--fs-sm); color: var(--text-3); }
.rsu-vestplan-head { font-size: var(--fs-sm); font-weight: 600; color: var(--text-2); }
.rsu-vestplan-table { width: 100%; border-collapse: collapse; font-size: var(--fs-sm); }
.rsu-vestplan-table thead th {
  text-align: left;
  font-weight: 600;
  color: var(--text-3);
  padding: var(--space-1) var(--space-2);
  border-bottom: 1px solid var(--divider);
}
.rsu-vestplan-table td {
  padding: var(--space-1) var(--space-2);
  border-bottom: 1px solid var(--divider);
  vertical-align: middle;
}
.rsu-vestplan-table tr:last-child td { border-bottom: 0; }
.rsu-vp-period { color: var(--text-2); white-space: nowrap; }
.rsu-vp-date { color: var(--text-3); white-space: nowrap; font-variant-numeric: tabular-nums; }
.rsu-vp-input { width: 40%; }
.rsu-vp-input .form-input-sm { width: 100%; }

.rsu-vp-sum { margin-top: var(--space-1); }
.rsu-vp-sum-badge { font-size: var(--fs-sm); font-weight: 600; }
.rsu-vp-sum-badge.is-ok { color: var(--up); }
.rsu-vp-sum-badge.is-bad { color: var(--dn); }

.rsu-form-actions { display: flex; justify-content: flex-end; gap: var(--space-2); }

/* ②b 编辑 / 删除 grant（Part D）—— 整张卡片可点击展开编辑面板 */
.rsu-grant-clickable {
  position: relative;
  cursor: pointer;
  border-radius: var(--radius-md);
}
/* 折叠态外观不变（卡片自带 bg/border）；hover 时卡片描边转金 + 右下角浮现「编辑 ▾」提示 */
.rsu-grant-clickable:hover .rsu-card { border-color: var(--accent); }
.rsu-grant-edit-hint {
  position: absolute;
  bottom: 2px;
  right: var(--space-2);
  font-size: var(--fs-xs);
  color: var(--accent-deep);
  opacity: 0;
  transition: opacity var(--motion-fast) var(--ease-standard);
  pointer-events: none;
}
.rsu-grant-clickable:hover .rsu-grant-edit-hint,
.rsu-grant-block.is-editing .rsu-grant-edit-hint { opacity: 1; }

.rsu-grant-edit {
  margin-top: var(--space-3);
  padding: var(--space-3) var(--space-4);
  border: 1px solid var(--border-1);
  border-radius: var(--radius-md);
  background: var(--surface-tint);
}
.rsu-edit-form { display: flex; flex-direction: column; gap: var(--space-3); }
.rsu-edit-locked {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2) var(--space-3);
  font-size: var(--fs-sm);
  color: var(--text-2);
}
.rsu-edit-locked-item { font-weight: 600; }
.rsu-edit-locked-note { font-size: var(--fs-xs); color: var(--text-3); font-weight: 400; }

.rsu-edit-grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: var(--space-3); }

.rsu-edit-skipsec { display: flex; flex-direction: column; gap: var(--space-2); }
.rsu-edit-hint { margin: 0; font-size: var(--fs-sm); color: var(--text-3); }
.rsu-edit-skips { display: flex; flex-wrap: wrap; gap: var(--space-2); }
.rsu-edit-skip-chip {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  padding: 2px 2px 2px var(--space-2);
  border: 1px solid var(--border-1);
  border-radius: var(--radius-pill);
  font-size: var(--fs-sm);
  color: var(--text-2);
}
.rsu-edit-unskip { padding: 1px var(--space-2); font-size: var(--fs-xs); }

.rsu-edit-actions { display: flex; align-items: center; gap: var(--space-2); }
.rsu-edit-actions__spacer { flex: 1; }
.rsu-edit-del { color: var(--dn); }
.rsu-edit-del:hover { border-color: var(--dn); }

.rsu-edit-delconfirm {
  margin-top: var(--space-3);
  padding: var(--space-3);
  border: 1px solid var(--warn);
  border-radius: var(--radius-md);
  background: var(--warn-bg);
}
.rsu-edit-delconfirm__msg { font-size: var(--fs-sm); color: var(--warn-deep); }
.rsu-edit-delconfirm__actions { display: flex; justify-content: flex-end; gap: var(--space-2); margin-top: var(--space-2); }

/* 窄屏：grant 卡单列 + 确认四数两列 + 编辑两栏转单列（桌面端不受影响——仅 max-width:600px 生效） */
@media (max-width: 600px) {
  .rsu-overview-cards { grid-template-columns: 1fr; }
  .rsu-confirm-grid { grid-template-columns: repeat(2, 1fr); }
  .rsu-edit-grid { grid-template-columns: 1fr; }
}

/* 「显示全部 N 条 ▾ / 收起 ▴」按钮 —— 紧贴 lot 表底部，全宽，文字居中。
 * 入快出慢（150ms in / 500ms out）：点击展开后行数撑开、按钮位移，鼠标短暂
 * 离开 hover 区导致 :hover 中断；快速 fade-out 会感知为"闪一下"。出场拉到 500ms
 * 让消退极柔和（鼠标追上时 bg 几乎没褪色），追上后 hover-in 仍 150ms 灵敏响应。
 * :active 显式锁成 hover 同色，挡掉浏览器默认按下瞬间的 bg 变暗 → 弹回的"咔哒"。
 * :focus-visible 只对键盘 tab 显示焦点环（鼠标点击不挂残留焦点环）。 */
.exp-lots-show-more {
  display: block;
  width: 100%;
  margin-top: 0;
  padding: 8px;
  background: transparent;
  border: 0;
  border-top: 1px solid var(--border-1);
  color: var(--accent);
  font-family: var(--font-body);
  font-size: var(--fs-sm);
  text-align: center;
  cursor: pointer;
  outline: none;
  transition: background 500ms var(--ease-standard);
}

.exp-lots-show-more:hover,
.exp-lots-show-more:active {
  background: var(--accent-lt);
  transition: background var(--motion-fast) var(--ease-standard);
}

.exp-lots-show-more:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: -2px;
}

/* fundamentals 右栏 */
.fundamentals-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 10px 28px;
}

.kv {
  display: flex;
  justify-content: space-between;
  align-items: center;
}

.kv-k {
  font-size: var(--fs-sm);
  color: var(--text-3);
}

.kv-v {
  font-family: var(--font-body);
  font-variant-numeric: tabular-nums;
  font-size: var(--fs-sm);
  color: var(--text-1);
  font-weight: 500;
}

/* 内联操作 */
.exp-actions {
  margin-top: 18px;
  padding-top: 14px;
  border-top: 1px dashed var(--border-1);
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}

.exp-btn {
  padding: 6px 12px;
  font-size: var(--fs-sm);
  border: 1px solid var(--border-2);
  background: var(--surface);
  border-radius: var(--radius-sm);
  cursor: pointer;
  color: var(--text-2);
  font-family: var(--font-body);
  text-decoration: none;
  display: inline-flex;
  align-items: center;
  gap: 4px;
  transition: border-color var(--motion-fast) var(--ease-standard),
              color var(--motion-fast) var(--ease-standard),
              background var(--motion-fast) var(--ease-standard);
}

.exp-btn:hover {
  border-color: var(--accent);
  color: var(--accent);
  background: var(--accent-lt);
}

.exp-btn--primary {
  background: var(--accent);
  color: #fff;
  border-color: var(--accent);
}

.exp-btn--primary:hover {
  background: var(--accent-deep);
  border-color: var(--accent-deep);
  color: #fff;
}

/* ═══════════════════════════════════════════════════════════════════
 * D4 · 持仓行展开面板（mockup index_new_UI_mockup.html L962-L1059 / L6281-L6328 1:1）
 * left: chart-header + price-chart-wrap | manual-no-chart + fundamentals
 * right: timeline + exp-actions + holding-inline-edit panels
 * ═══════════════════════════════════════════════════════════════════ */

.expand-left  { display: flex; flex-direction: column; gap: 24px; min-width: 0; }
.expand-right { display: flex; flex-direction: column; min-width: 0; }

.exp-chart-header {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 8px;
  padding-bottom: 7px;
  border-bottom: 1px solid var(--border-1);
}

.exp-chart-title {
  font-family: var(--font-body);
  font-variant-numeric: tabular-nums;
  font-size: var(--fs-2xs);
  letter-spacing: 1.5px;
  text-transform: uppercase;
  color: var(--accent);
}

/* Legend 占据 toolbar 行左侧（替代原副标题"建仓以来"位置；分红 item 已删除） */
.exp-chart-legend {
  display: flex;
  gap: 14px;
  font-size: var(--fs-2xs);
  color: var(--text-3);
  align-items: center;
  flex-wrap: wrap;
}

.ecl-item { display: flex; align-items: center; gap: 4px; }
.ecl-dot  { width: 8px; height: 8px; border-radius: var(--radius-pill); border: 1.5px solid; }
.ecl-dot.buy  { border-color: var(--up); background: var(--up-bg); }
.ecl-dot.sell { border-color: var(--dn); background: var(--dn-bg); }
.ecl-line     { width: 16px; height: 0; border-top: 1.5px dashed var(--accent); }
/* 清仓资产 legend：买入均价线（绿）/ 卖出均价线（红）— ADR 0045 */
.ecl-line--buy  { border-top-color: var(--up); }
.ecl-line--sell { border-top-color: var(--dn); }

/* 价格图工具栏：legend（左）+ range tab pill 组（右）；现在嵌于 .price-chart-wrap 白框内 */
.price-chart-toolbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  margin: 0 0 6px 0;
}

/* .price-chart-range / .pcr-btn 样式见 .port-range / .port-range-btn 合并选择器 */

.price-chart-wrap {
  background: var(--surface);
  border: 1px solid var(--border-1);
  border-radius: var(--radius-md);
  /* 上下左右对称内边距；ECharts grid 内部再加各方向 padding（左 50 容纳 Y label + cost 标签） */
  padding: 8px;
  /* toolbar(~28px) + 8 margin + chart(240) + padding(16) ≈ 292，留 4px 余量 */
  min-height: 296px;
  display: flex;
  flex-direction: column;
}

/* fallback 占位（manual-no-chart）嵌在 wrap 内时去 surface 双层边框，让 manual-no-chart 自身的 dashed border 单独成立 */
.price-chart-wrap.is-empty {
  background: transparent;
  border: 0;
  padding: 0;
}

/* ECharts 容器：固定 240px 高度，宽度填满 wrap；wrap.price-chart-loading 居中靠 wrap 内的 .price-chart-loading 自身 padding 控制 */
.price-chart {
  width: 100%;
  height: 240px;
  display: block;
}

.price-chart-loading {
  font-family: var(--font-body);
  font-variant-numeric: tabular-nums;
  font-size: var(--fs-xs);
  color: var(--text-3);
  padding: 80px 0;
  text-align: center;
}

.manual-no-chart {
  background: var(--surface);
  border: 1px dashed var(--border-2);
  border-radius: var(--radius-md);
  padding: 36px 20px;
  text-align: center;
}
.mnc-icon  { font-size: 32px; opacity: 0.35; margin-bottom: 10px; }
.mnc-title { font-size: var(--fs-sm); color: var(--text-2); font-weight: 500; margin-bottom: 4px; }
.mnc-sub   { font-size: var(--fs-xs); color: var(--text-3); line-height: 1.55; }

/* ── inline edit 4 面板（mockup L6119-L6235 / L2761-L2774 1:1） ── */

.holding-inline-edit {
  display: none;
  margin-top: 14px;
  padding-top: 14px;
  border-top: 1px dashed var(--border-1);
}
.holding-inline-edit.is-open { display: block; }

.expand-form-balance,
.expand-form-tx {
  display: flex;
  align-items: end;
  gap: 10px;
  flex-wrap: wrap;
  justify-content: flex-end;
}
/* attr 面板：12 列 grid（row1: 3 字段 × span 4 / row2: 4 字段 × span 3） */
.expand-form-attr {
  display: grid;
  grid-template-columns: repeat(12, minmax(0, 1fr));
  column-gap: 12px;
  row-gap: 10px;
  align-items: end;
}
.expand-field--row1 { grid-column: span 4; }
.expand-field--row2 { grid-column: span 3; }
/* 双类选择器提优先级——单类 `.expand-field--hidden` 会被后定义、同优先级的
   `.expand-field { display:flex }` 覆盖，导致隐藏失效（投资地域字段该藏没藏）。 */
.expand-field.expand-field--hidden { display: none; }
/* CASH 资产无「分类」字段（category 恒为 cash）→ row1 两字段 / row2 三字段重新均分填满 */
.expand-form-attr--cash .expand-field--row1 { grid-column: span 6; }
.expand-form-attr--cash .expand-field--row2 { grid-column: span 4; }
.expand-form-attr .expand-actions { grid-column: 1 / -1; justify-content: flex-end; }

.expand-field {
  display: flex;
  flex-direction: column;
  gap: 4px;
  min-width: 100px;
  flex: 1 1 120px;
}

.expand-actions {
  display: flex;
  gap: 6px;
  align-items: center;
  height: 32px;
}

/* D4 inline edit 元素统一高度 — 修截图里 select(40) vs button(30) 高度不齐
   涉及面板内所有交互元素：input / select / .dropdown-trigger / .btn / .tx-type-btn */
.holding-inline-edit .form-input-sm,
.holding-inline-edit select.form-input-sm,
.holding-inline-edit .dropdown-trigger,
.holding-inline-edit .tx-type-btn,
.holding-inline-edit .btn {
  height: 32px;
  box-sizing: border-box;
  line-height: 1.2;
}
.holding-inline-edit .form-input-sm,
.holding-inline-edit .dropdown-trigger {
  padding: 0 10px;
}
.holding-inline-edit .btn {
  padding: 0 var(--space-3);
}
.holding-inline-edit .tx-type-btn {
  padding: 0 10px;
}

.tx-type-group { display: flex; gap: 4px; }
.tx-type-btn {
  border: 1px solid var(--border-2);
  border-radius: var(--radius-sm);
  font-size: var(--fs-2xs);
  background: var(--surface);
  cursor: pointer;
  color: var(--text-3);
  transition: all var(--motion-fast) var(--ease-standard);
  font-family: var(--font-body);
}
.tx-type-btn.on.buy  { background: var(--up-bg); color: var(--up); border-color: var(--up); }
.tx-type-btn.on.sell { background: var(--dn-bg); color: var(--dn); border-color: var(--dn); }

/* exp-btn editing 态（被点击的按钮高亮、兄弟灰化） */
.exp-btn.is-editing {
  background: var(--accent-lt);
  color: var(--accent);
  border-color: var(--accent);
}
.exp-btn[disabled] {
  opacity: 0.45;
  cursor: not-allowed;
  pointer-events: none;
}

/* ─── 空持仓骨架 ─── */
.onboarding-welcome-card {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-6);
  padding: var(--card-padding-lg);
  border: 1px solid var(--border-1);
}

.onboarding-welcome-copy {
  min-width: 0;
}

.onboarding-welcome-kicker {
  margin: 0 0 var(--space-2);
  color: var(--accent-deep);
  font-size: var(--fs-xs);
  font-weight: 700;
}

.onboarding-welcome-title {
  margin: 0;
  color: var(--text-1);
  font-size: var(--fs-2xl);
  font-weight: 700;
  line-height: 1.28;
  letter-spacing: 0;
}

.onboarding-welcome-text {
  max-width: 620px;
  margin: var(--space-3) 0 0;
  color: var(--text-3);
  font-size: var(--fs-md);
  line-height: 1.7;
}

.onboarding-welcome-actions {
  display: flex;
  flex-wrap: wrap;
  justify-content: flex-end;
  gap: var(--space-3);
  flex-shrink: 0;
}

.onboarding-welcome-actions .btn {
  min-width: 128px;
  height: 36px;
  justify-content: center;
}

.holdings-empty {
  padding: 48px 24px;
  text-align: center;
  color: var(--text-3);
  font-size: var(--fs-sm);
}

/* T4：空库诚实空状态文案（总览 / 资产配置 / 风险敞口）——与 .holdings-empty 同款语言，
   把"无数据"显式区分于"加载中"骨架。 */
.port-empty-hint,
.alloc-empty-hint,
.risk-empty-hint {
  padding: 24px 8px;
  text-align: center;
  color: var(--text-3);
  font-size: var(--fs-sm);
}
.port-empty-hint { padding: 12px 0 8px; text-align: left; }

/* 持仓表「52W 走势」列（spark）—— 迷你折线：折线 + 起点价虚线 + 末端点 + 起点/现价脚注；align: r */
.spark-cell {
  display: inline-flex;
  flex-direction: column;
  gap: 3px;
  width: 100px;
  font-variant-numeric: tabular-nums;
  vertical-align: middle;
}
/* height 28 + overflow:visible：折线 padY=1 撑到接近上下沿、末端圆点溢出到留白不被裁（buildSparkCell）。
   行高靠 spark 列 padding 缩到 4px 兜住（见 .holdings-table td[data-col-id="spark"]）—— cell 41px 仍 < 标的名，行高不变。 */
.spark-cell .spark-svg { display: block; width: 100px; height: 28px; overflow: visible; }
.spark-foot {
  display: flex;
  justify-content: space-between;
  font-size: var(--fs-2xs);
  color: var(--text-3);
  line-height: 1;
}
/* 折线 / 末端点：整条单色，按「末端 vs 起点价」红绿；起点价虚线中性灰 */
.spark-base    { stroke: var(--text-3); opacity: .55; }
.spark-line-up { stroke: var(--up); }
.spark-dot-up  { fill: var(--up); }
.spark-line-dn { stroke: var(--dn); }
.spark-dot-dn  { fill: var(--dn); }

/* 持仓表「P/E 区间」列：仿 52W 区间条，多一条均值刻度（居中）。dot = 当前 P/E 位置。 */
.peband-cell {
  display: inline-flex;
  flex-direction: column;
  gap: 4px;
  width: 100px;
  font-variant-numeric: tabular-nums;
  vertical-align: middle;
}
.peband-bar {
  position: relative;
  width: 100%;
  height: 1px;
  background: var(--border-2);
  border-radius: 1px;
}
.peband-mean {
  position: absolute;
  left: 50%;
  top: 50%;
  width: 1px;
  height: 7px;
  background: var(--text-3);
  transform: translate(-50%, -50%);
}
.peband-dot {
  position: absolute;
  top: 50%;
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--text-2);
  transform: translate(-50%, -50%);
}
.peband-foot {
  display: flex;
  justify-content: space-between;
  font-size: var(--fs-2xs);
  color: var(--text-3);
  line-height: 1;
}

@media (max-width: 900px) {
  .holdings-table thead th,
  .holdings-table td {
    padding: 9px 8px;
  }
  .expand-grid {
    grid-template-columns: 1fr;
    gap: 20px;
  }
}

/* ═══ view-home § 5 · sec-risk（mockup L3890–L3968 / L697–L770） ═══
 * 1:1 还原 mockup `frag-risk` 容器（risk-grid / risk-card / rc-title-text /
 * rc-count / risk-bars / rb-head / rb-name / rb-dot / rb-label / rb-pct /
 * rb-bar / rb-fill / rb-val / rb-group-* 折叠）。
 *
 * 颜色：N1.c · 全部走 :root --chart-* token；分类大类用 §0.6 6 色。
 * 占位（N10）：snapshot=null（fxRate 缺失）→ 4 卡每张 3 占位条，保骨架不缺格。
 * 数据源：CONTRACT §10.4 aggregateByDimension 4 dim（accountCountry / account /
 * exposureRegion / category）。 */

#sec-risk .section-header {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--space-3);
  margin-bottom: var(--space-3);
}

.risk-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: var(--space-4);
}

.risk-card {
  background: var(--surface);
  border: 1px solid var(--border-1);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-sm);
  padding: var(--card-padding);
  display: flex;
  flex-direction: column;
  animation: fadeUp var(--motion-base) var(--ease-standard) both;
}

.risk-card:nth-child(1) { animation-delay: 0.05s; }
.risk-card:nth-child(2) { animation-delay: 0.10s; }
.risk-card:nth-child(3) { animation-delay: 0.15s; }
.risk-card:nth-child(4) { animation-delay: 0.20s; }

.risk-card-title {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: var(--space-3);
}

.rc-title-text {
  font-size: var(--fs-base);          /* 13px */
  font-weight: 500;
  color: var(--text-1);
  display: flex;
  align-items: center;
  gap: 7px;
}

.rc-count {
  font-family: var(--font-body);
  font-variant-numeric: tabular-nums;
  font-size: var(--fs-2xs);            /* 10px */
  color: var(--text-3);
  padding: 2px 7px;
  background: var(--bg-warm);
  border-radius: var(--radius-pill);
  letter-spacing: 0.04em;
  flex-shrink: 0;
}

.risk-bars {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);                /* 8-10 */
  flex: 1;
}

.risk-bars > div {
  /* 每条 bar 块占据自身高度，子元素由内部 layout 决定 */
}

.rb-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: var(--space-1);
  gap: var(--space-2);
}

.rb-name {
  display: flex;
  align-items: center;
  gap: 7px;
  font-size: var(--fs-sm);            /* 12px */
  color: var(--text-2);
  flex: 1;
  min-width: 0;
}

.rb-dot {
  width: 7px;
  height: 7px;
  border-radius: var(--radius-xs);    /* 2px */
  flex-shrink: 0;
  display: inline-block;
}

.rb-label {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.rb-pct {
  font-family: var(--font-body);
  font-variant-numeric: tabular-nums;
  font-size: var(--fs-sm);            /* 12px */
  color: var(--text-1);
  font-weight: 500;
  flex-shrink: 0;
  letter-spacing: 0.02em;
}

.rb-bar {
  height: 5px;
  background: var(--bg-warm);
  border-radius: 3px;
  overflow: hidden;
}

.rb-fill {
  height: 100%;
  border-radius: 3px;
  transform-origin: left;
  animation: growBar 0.7s var(--ease-standard) both;
}

.rb-val {
  font-family: var(--font-body);
  font-variant-numeric: tabular-nums;
  font-size: var(--fs-2xs);            /* 10px */
  color: var(--text-3);
  margin-top: 2px;
}

/* ── 折叠组：rb-group-header 点击切换 children open ── */
.rb-group-header {
  cursor: pointer;
  padding-top: var(--space-2);
  margin-top: 2px;
  border-top: 1px dashed var(--border-1);
  transition: opacity var(--motion-fast) var(--ease-standard);
  user-select: none;
}

.rb-group-header:hover { opacity: 0.75; }

.rb-group-header .rb-label {
  color: var(--text-3);
  display: inline-flex;
  align-items: center;
  gap: 4px;
}

.rb-group-caret {
  display: inline-block;
  font-family: var(--font-body);
  font-variant-numeric: tabular-nums;
  font-size: var(--fs-2xs);
  color: var(--text-3);
  transition: transform var(--motion-base) var(--ease-standard);
  width: 8px;
}

.rb-group-header.open .rb-group-caret {
  transform: rotate(90deg);
}

.rb-group-tiny-count {
  font-size: var(--fs-xs);             /* 11px */
  padding: 1px 5px;
  background: var(--bg-warm);
  border-radius: var(--radius-md);
  color: var(--text-3);
  font-family: var(--font-body);
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.02em;
  border: 1px solid var(--border-1);
}

.rb-group-children {
  overflow: hidden;
  max-height: 0;
  transition: max-height var(--motion-slow) var(--ease-standard),
              padding var(--motion-base) var(--ease-standard);
  padding-top: 0;
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}

.rb-group-children.open {
  max-height: 320px;
  padding-top: var(--space-2);
}

.rb-group-children .rb-name {
  font-size: var(--fs-xs);             /* 11px */
  color: var(--text-3);
  padding-left: 10px;
}

.rb-group-children .rb-pct {
  font-size: var(--fs-xs);
  color: var(--text-2);
  font-weight: 400;
}

.rb-group-children .rb-bar {
  height: 3px;
  margin-left: 10px;
  width: calc(100% - 10px);
}

.rb-group-children .rb-val {
  font-size: var(--fs-xs);
  padding-left: 10px;
}

/* 窄屏：4 列 → 2 列 → 1 列 */
@media (max-width: 1100px) {
  .risk-grid { grid-template-columns: repeat(2, 1fr); }
}

@media (max-width: 600px) {
  .risk-grid { grid-template-columns: 1fr; }
  .port-range-btn { white-space: nowrap; }  /* 窄屏防「全部」2 字折行撑高按钮 */
}

/* ─────────────────────────────────────────────────────────────────────────
   Step 6 · view-market（mockup L3971–L4400 · 7 SECTION）
   1:1 还原 mockup .frag-market 内部 + N1–N10 归一化（颜色 / 字号 / 圆角 / 阴影
   全部通过 :root token 接管；mockup 内部 frag :root 全删）。
   蓝色 accent 由 body[data-view="market"] 已 scoped 到 var(--accent)（N1.b）。
   ───────────────────────────────────────────────────────────────────────── */

#view-market {
  padding-bottom: 24px;
}

.market-page {
  display: flex;
  flex-direction: column;
  gap: var(--space-7);  /* 32px section 间距 */
}

.market-section {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);  /* header 与 grid 之间 12px */
}

/* section header（mockup .section-header / .section-title / .section-sub） */
.market-section-header {
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
}

.market-section-sub {
  font-size: var(--fs-sm);
  color: var(--text-3);
  line-height: 1.5;
  max-width: 720px;
}

/* grid 系统（mockup .grid / .g3 / 自定义 1fr 2fr） */
.market-grid {
  display: grid;
  gap: var(--space-4);  /* 16px */
}

.market-grid--3 { grid-template-columns: repeat(3, 1fr); }
.market-grid--vix-curve { grid-template-columns: 280px 1fr; }
.market-grid--fx { grid-template-columns: 1fr 2fr; }

.market-grid-spacer {
  visibility: hidden;
  pointer-events: none;
}

/* card / card-label（mockup .card / .card-label） —— 直接复用全局 .card */
.market-card-label {
  font-size: var(--fs-2xs);
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--text-3);
  display: flex;
  align-items: center;
  gap: var(--space-2);
}

/* mockup .pill-ink ticker pill */
.market-pill-ink {
  display: inline-flex;
  align-items: center;
  padding: 2px 7px;
  border-radius: var(--radius-pill);
  font-size: var(--fs-2xs);
  font-weight: 600;
  font-family: var(--mono);
  background: var(--surface-2);
  color: var(--text-3);
}

.market-card-head-row {
  display: flex;
  justify-content: space-between;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--space-3);
  margin-bottom: var(--space-3);
}

.market-card-note {
  font-size: var(--fs-xs);
  color: var(--text-3);
  margin-top: 10px;
  padding-top: 10px;
  border-top: 1px dashed var(--border-1);
  line-height: 1.55;
}
.market-card-note strong { color: var(--text-2); }

/* card 底部 group flag chip 区（与 card-note 并列；类似 mockup L4043 padding-top） */
.market-card-flags {
  margin-top: 14px;
  padding-top: 12px;
  border-top: 1px solid var(--border-1);
  display: flex;
  gap: var(--space-2);
  flex-wrap: wrap;
}

/* group-flags 容器（金银比 / ETH-BTC ratio） */
.market-group-flags {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
  padding: var(--space-3) 14px;
  background: var(--surface);
  border: 1px solid var(--border-1);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-sm);
  align-items: center;
}

.market-group-flag-label {
  font-size: var(--fs-2xs);
  color: var(--text-3);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  font-weight: 600;
  margin-right: var(--space-1);
}

/* gflag chip（mockup .gflag） */
.market-gflag {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  padding: 6px 10px;
  background: var(--bg-warm);
  border: 1px solid var(--border-1);
  border-radius: var(--radius-pill);
  font-size: var(--fs-sm);
  color: var(--text-2);
  line-height: 1;
  cursor: help;
}

.market-gflag-name { font-weight: 500; }
.market-gflag-val {
  font-family: var(--font-body);
  font-variant-numeric: tabular-nums;
  font-weight: 600;
  color: var(--text-1);
}

.market-gflag-tag {
  font-family: var(--mono); /* N6 · 国家代号 mono 字体（与 ticker / 货币代号统一）· 2026-05-05 */
  font-size: var(--fs-2xs);
  padding: 2px 7px;
  border-radius: var(--radius-pill);
  font-weight: 600;
  letter-spacing: 0.02em;
}
.market-gflag-tag.up    { background: var(--up-bg);          color: var(--up); }
.market-gflag-tag.dn    { background: var(--dn-bg);          color: var(--dn); }
.market-gflag-tag.neu   { background: var(--warn-bg);        color: var(--warn); }
.market-gflag-tag.gray  { background: var(--surface-2);      color: var(--text-3); }
.market-gflag-tag.blue  { background: var(--chart-blue-bg);  color: var(--chart-blue); }
.market-gflag-tag.purple{ background: var(--chart-purple-bg);color: var(--chart-purple); }

/* ── S1 · VIX 卡 ─────────────────────────────────────────────────────── */
.market-vix-card {
  display: flex;
  flex-direction: column;
  animation: fadeUp var(--motion-base) var(--ease-standard) both;
}

.market-vix-big {
  font-family: var(--font-body);
  font-variant-numeric: tabular-nums;
  font-size: var(--fs-display-lg);
  line-height: 1;
  color: var(--warn);
  margin: var(--space-2) 0 var(--space-1);
  letter-spacing: -0.02em;
}

.market-vix-label {
  font-size: var(--fs-sm);
  font-weight: 600;
}

.market-vix-pct-wrap {
  margin-top: 14px;
  padding-top: var(--space-3);
  border-top: 1px solid var(--border-1);
}

.market-vix-pct-cap {
  font-size: var(--fs-2xs);
  color: var(--text-3);
  margin-bottom: var(--space-1);
}

.market-vix-pct-bar {
  height: 6px;
  background: linear-gradient(to right, var(--up) 0%, var(--warn) 50%, var(--dn) 100%);
  border-radius: 3px;
  position: relative;
  margin: 6px 0 var(--space-1);
}

.market-vix-needle {
  position: absolute;
  top: 50%;
  left: 28%;
  transform: translate(-50%, -50%);
  width: 12px;
  height: 12px;
  background: var(--surface);
  border: 2.5px solid var(--warn);
  border-radius: 50%;
}

.market-vix-needle--ph {
  /* N10：分位 needle 依赖 5 年历史 → 占位灰边、固定 28% 位置 */
  border-color: var(--text-mute);
  opacity: 0.7;
}

.market-vix-axis {
  display: flex;
  justify-content: space-between;
  font-size: var(--fs-2xs);
  color: var(--text-3);
}

.market-vix-foot {
  font-size: var(--fs-2xs);
  color: var(--text-3);
  margin-top: 6px;
  text-align: center;
}
.market-vix-foot strong { font-weight: 600; }

/* ── S1 · 美债收益率曲线 SVG / curve-stats ────────────────────────────── */
.market-curve-svg {
  width: 100%;
  height: 160px;
  display: block;
  margin-top: var(--space-2);
}

.market-curve-stats {
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  gap: var(--space-2);
  margin-top: 14px;
  padding-top: 14px;
  border-top: 1px solid var(--border-1);
}

.market-curve-pt {
  text-align: center;
}

.market-curve-pt-name {
  font-size: var(--fs-2xs);
  color: var(--text-3);
  font-family: var(--font-body);
  font-variant-numeric: tabular-nums;
}

.market-curve-pt-val {
  font-family: var(--font-body);
  font-variant-numeric: tabular-nums;
  font-size: var(--fs-md);
  font-weight: 600;
  margin-top: 2px;
  color: var(--text-1);
}

.market-curve-pt-chg {
  font-size: var(--fs-2xs);
  margin-top: 1px;
  color: var(--text-3);
}

/* ── tile（S2/S3/S4/S6/S7 共用）─────────────────────────────────────── */
.tile {
  background: var(--surface);
  border: 1px solid var(--border-1);
  border-radius: var(--radius-md);
  padding: 14px;
  box-shadow: var(--shadow-sm);
  animation: fadeUp var(--motion-base) var(--ease-standard) both;
  display: flex;
  flex-direction: column;
}

.tile-head {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  margin-bottom: 6px;
  gap: var(--space-2);
}

.tile-name {
  font-size: var(--fs-sm);
  color: var(--text-2);
  font-weight: 500;
}

.tile-ticker {
  font-family: var(--mono);
  font-size: var(--fs-xs);
  color: var(--text-3);
  background: var(--surface-2);
  padding: 1px 6px;
  border-radius: var(--radius-sm);
  flex-shrink: 0;
}

.tile-val {
  font-family: var(--font-body);
  font-variant-numeric: tabular-nums;
  font-size: var(--fs-lg);
  font-weight: 500;
  color: var(--text-1);
  line-height: 1.1;
}

.tile-changes {
  display: flex;
  align-items: baseline;
  gap: var(--space-2);
  margin-top: var(--space-1);
}

.tile-chg-period {
  font-size: var(--fs-base);
  font-weight: 600;
  color: var(--text-2);
}

.tile-chg-today {
  font-size: var(--fs-2xs);
  color: var(--text-3);
}

.spark-wrap {
  height: 40px;
  margin-top: 10px;
  position: relative;
}

.spark-wrap .spark-svg {
  width: 100%;
  height: 100%;
  display: block;
}

.tile-flags {
  margin-top: 10px;
  padding-top: 10px;
  border-top: 1px dashed var(--border-1);
  display: flex;
  flex-wrap: wrap;
  gap: 5px;
  justify-content: space-between;
}
.tile-flags:has(> .tflag:only-child) { justify-content: flex-start; }

.tflag {
  font-size: var(--fs-xs);
  padding: 3px 8px;
  border-radius: var(--radius-pill);
  font-weight: 500;
  display: inline-flex;
  align-items: center;
  gap: 5px;
  cursor: help;
  white-space: nowrap;
}

.tflag-val {
  font-family: var(--font-body);
  font-variant-numeric: tabular-nums;
  font-weight: 600;
}

.tflag.up    { background: var(--up-bg);          color: var(--up); }
.tflag.dn    { background: var(--dn-bg);          color: var(--dn); }
.tflag.neu   { background: var(--warn-bg);        color: var(--warn); }
.tflag.gray  { background: var(--surface-2);      color: var(--text-3); }
.tflag.blue  { background: var(--chart-blue-bg);  color: var(--chart-blue); }

.c-up { color: var(--up); }
.c-dn { color: var(--dn); }
.c-neu { color: var(--warn); }

/* E53（2026-05-12）：脏数据 ERR 单元格——区别于 "—"（不适用 / 无数据），
   红字加粗 + cursor:help 暗示 hover 看 tooltip；占位与普通数字单元格一致 */
.err-cell {
  color: var(--dn);
  font-weight: 600;
  font-size: var(--fs-sm);   /* 12px，与持仓表主数字 .holding-num 同字号 */
  cursor: help;
  letter-spacing: 0.02em;
}

/* ── S5 · 汇率（DXY 卡 / CNY-CNH 卡）───────────────────────────────── */
.market-cny-legend {
  display: flex;
  gap: 16px;
  font-size: var(--fs-xs);
  color: var(--text-2);
  flex-wrap: wrap;
}

.market-cny-legend__item {
  display: inline-flex;
  align-items: center;
  gap: 6px;
}

.market-cny-legend__dot {
  width: 10px;
  height: 2px;
  border-radius: 1px;
}

.market-cny-legend .num {
  font-family: var(--font-body);
  font-variant-numeric: tabular-nums;
  font-weight: 600;
  color: var(--text-1);
  margin-left: var(--space-1);
}

.market-fx-chart-wrap {
  position: relative;
}

.market-fx-chart {
  width: 100%;
  height: 140px;
  display: block;
}

.market-fx-axis {
  display: flex;
  justify-content: space-between;
  font-size: var(--fs-2xs);
  color: var(--text-3);
  font-family: var(--font-body);
  font-variant-numeric: tabular-nums;
  margin-top: 2px;
}

/* ── 窄屏断点 ────────────────────────────────────────────────────────── */
@media (max-width: 1100px) {
  .market-grid--3 { grid-template-columns: repeat(2, 1fr); }
  .market-grid--vix-curve { grid-template-columns: 1fr; }
  .market-grid--fx { grid-template-columns: 1fr; }
}

@media (max-width: 700px) {
  .market-grid--3 { grid-template-columns: 1fr; }
  .market-curve-stats { grid-template-columns: repeat(3, 1fr); row-gap: var(--space-3); }
}


/* ════════════════════════════════════════════════════════════════════════
 * tx-dialog · UI reset Step 7（mockup L4405–L4910）
 *
 * 浮层根容器 .tx-dialog 已在文件顶部 §"tx-dialog 容器骨架" 定义（border:0 + ::backdrop）。
 * 本段落实 shell（顶 bar + body）/ mode-tabs / 三 panel（upload + holdings + balance）/
 * db-menu / review-section / clearDialog overlay。颜色 / 字体 / 圆角 / 阴影全部走 §0 token，
 * mockup `--pos`/`--neg`/`--accent-lt` 等 alias 映射到 `var(--up)`/`var(--dn)`/`var(--accent-lt)`。
 * ════════════════════════════════════════════════════════════════════════ */

.tx-dialog {
  width: 1280px;
  width: min(1280px, 92vw);
  height: 92vh;
  border-radius: var(--radius-lg);
  background: var(--surface);
  overflow: hidden;
  box-shadow: 0 20px 60px rgba(0, 0, 0, 0.2);
}

.tx-dialog-shell {
  display: flex;
  flex-direction: column;
  height: 92vh;
  outline: none;
}

.tx-dialog-bar {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  padding: 18px 24px 14px;
  border-bottom: 1px solid var(--border-1);
  flex-shrink: 0;
}

.tx-dialog-title-block {
  display: flex;
  flex-direction: column;
  gap: 2px;
}

#tx-dialog-title {
  font-family: var(--font-body);
  font-size: var(--fs-lg);
  line-height: 1.3;
  font-weight: 600;
  color: var(--text-2);
  letter-spacing: 0.005em;
}

.tx-dialog-bar-actions {
  display: flex;
  align-items: center;
  gap: 8px;
}

.tx-dialog-close {
  width: 32px;
  height: 32px;
  border: 1px solid var(--border-2);
  border-radius: var(--radius-md);
  background: var(--surface);
  color: var(--text-2);
  font-size: 18px;
  line-height: 1;
  cursor: pointer;
  transition: background var(--motion-fast) var(--ease-standard);
}
.tx-dialog-close:hover { background: var(--bg-warm); color: var(--text-1); }

.tx-dialog-body {
  padding: 18px 24px 24px;
  overflow-y: auto;
  overscroll-behavior: contain;
  flex: 1 1 auto;
}

/* ── 通用 .btn 体系（base + variants） ───────── */
/* 顺序：.btn (base) → .btn-sm / .btn-icon-only (size variants) → .btn-danger / .btn-primary (color variants)
   modifier 必须在 base 之后，否则同特异性下 base 会反向覆盖 modifier 的 bg/color。 */

.btn {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: var(--space-2) var(--space-3);
  border: 1px solid var(--border-2);
  border-radius: var(--radius-md);
  background: var(--surface);
  color: var(--text-2);
  font-family: var(--font-body);
  font-size: var(--fs-sm);
  line-height: 1.2;
  cursor: pointer;
  text-decoration: none;
  transition: background var(--motion-fast) var(--ease-standard),
              border-color var(--motion-fast) var(--ease-standard),
              color var(--motion-fast) var(--ease-standard);
}
.btn:hover { background: var(--bg-warm); border-color: var(--text-3); }
/* [hidden] 兜底：.btn 的 display:flex 会盖过 [hidden] 默认 display:none，这里补回（撤销按钮无可撤时整颗隐藏）。 */
.btn[hidden] { display: none; }
/* 通用 disabled 灰显：覆盖基础 .btn 与 .btn-primary（.btn-danger:disabled 同等特异性、靠后定义自留）。
   修复"禁用按钮看着仍像可点"（导入复核未选分类时「确认导入」）。 */
.btn:disabled,
.btn:disabled:hover {
  background: var(--border-2);
  border-color: var(--border-2);
  color: var(--surface);
  cursor: not-allowed;
}

.btn-sm { padding: var(--space-1) var(--space-3); font-size: var(--fs-xs); border-radius: var(--radius-sm); }

.btn-icon-only { padding: var(--space-2); }

.btn-danger {
  background: var(--dn);
  border-color: var(--dn);
  color: #fff;
}
.btn-danger:hover { background: #962525; border-color: #962525; }
.btn-danger:disabled { background: var(--border-2); border-color: var(--border-2); color: var(--surface); cursor: not-allowed; }

/* .btn-primary 主按钮变体 — 必须在 .btn 之后，否则 base 的 surface 底会覆盖 accent */
.btn-primary {
  background: var(--accent);
  border-color: var(--accent);
  color: #fff;
}
.btn-primary:hover { background: var(--accent-deep); border-color: var(--accent-deep); }

/* ── db-menu 数据备份/危险操作 dropdown（mockup L4430–L4450） ────────── */

.db-menu-wrap { position: relative; }

.db-menu {
  position: absolute;
  top: calc(100% + 6px);
  right: 0;
  background: var(--surface);
  border: 1px solid var(--border-1);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-md);
  padding: 5px;
  min-width: 220px;
  display: none;
  z-index: 30;
  animation: fadeIn var(--motion-fast) ease both;
}
.db-menu.show { display: block; }

@keyframes fadeIn { from { opacity: 0; transform: translateY(-4px); } to { opacity: 1; transform: translateY(0); } }

.db-menu-section { padding: 4px 0; }
.db-menu-section + .db-menu-section { border-top: 1px solid var(--border-1); }

.db-menu-label {
  font-size: var(--fs-xs);
  font-family: var(--font-body);
  font-variant-numeric: tabular-nums;
  letter-spacing: 1px;
  text-transform: uppercase;
  color: var(--text-3);
  padding: 4px 14px;
  margin-bottom: 2px;
}

.db-menu-item {
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  padding: 8px 12px;
  cursor: pointer;
  border: 0;
  border-radius: var(--radius-sm);
  font-size: var(--fs-base);
  color: var(--text-1);
  background: transparent;
  text-align: left;
  font-family: var(--font-body);
  transition: background var(--motion-fast) var(--ease-standard);
}
.db-menu-item:hover { background: var(--bg-warm); }
.db-menu-item.danger { color: var(--dn); }
.db-menu-item.danger:hover { background: var(--dn-bg); }

.db-menu-meta {
  font-family: var(--font-body);
  font-variant-numeric: tabular-nums;
  font-size: var(--fs-2xs);
  color: var(--text-3);
  padding: 6px 14px 4px;
  line-height: 1.5;
}

/* ── mode-tabs（mockup L4454–L4458 / L2417–L2437） ─────────────────────── */

.mode-tabs {
  display: inline-flex;
  background: var(--bg-warm);
  border: 1px solid var(--border-1);
  border-radius: var(--radius-lg);
  padding: 4px;
  margin-bottom: 20px;
  box-shadow: var(--shadow-sm);
}

.mode-tab {
  padding: 8px 20px;
  border: 0;
  border-radius: var(--radius-md);
  font-size: var(--fs-base);
  color: var(--text-3);
  cursor: pointer;
  user-select: none;
  display: flex;
  align-items: center;
  gap: 7px;
  background: transparent;
  font-family: var(--font-body);
  transition: background var(--motion-base) var(--ease-standard),
              color var(--motion-base) var(--ease-standard);
}
.mode-tab:hover { color: var(--text-1); }
.mode-tab.active { background: var(--text-1); color: var(--surface); font-weight: 500; }

/* 窄屏：4 个 tab 桌面用固定 padding:8px 20px，320–375px 下塞不下 →
   每个 tab 被压窄、标签「导入流水」逐字竖排。改为整条 flex 平分 +
   收窄左右内边距 + nowrap，标签恒定一行。 */
@media (max-width: 600px) {
  .mode-tabs {
    display: flex;
    width: 100%;
  }
  .mode-tab {
    flex: 1;
    justify-content: center;
    padding: 8px 4px;
    white-space: nowrap;
  }
}

.tx-panels { animation: fadeIn var(--motion-slow) ease both; }
.panel { display: none; }
.panel.active { display: block; }

/* ── 数据维护 panel（patch tab · drop-zone 重设计） ─────────────────────
   导入补丁卡（idle drop-zone / loaded / preview 三态）+ 最近应用右侧栏 +
   底部紧凑工具区。详见 ADR 0037 + 后续 ADR。 */

.patch-pane-2 { position: relative; }

/* 「这是做什么的?」帮助入口：绝对定位上移到 mode-tabs 那一行的右侧空白处
   （tab 行右半截本就空着），不占 patch panel 行流，让下方 patch-grid 两卡
   顶到顶部、与其他 tab 同高。-55px ≈ 越过 tab 行高 46 + gap 20，落在 tab 行内。 */
.patch-topbar {
  position: absolute;
  top: -55px;
  right: 0;
  z-index: 2;
}
.patch-help-wrap { position: relative; display: inline-flex; }
.patch-help-question {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  background: transparent;
  border: 0;
  color: var(--text-3);
  font-size: var(--fs-xs);
  font-family: var(--font-body);
  cursor: pointer;
  padding: 4px 6px;
  border-radius: var(--radius-sm);
}
.patch-help-question:hover,
.patch-help-question[aria-expanded="true"] { color: var(--text-1); }

/* patch-grid：左右 45:55 等高 */
.patch-grid {
  display: grid;
  grid-template-columns: minmax(0, 45fr) minmax(0, 55fr);
  gap: 20px;
  align-items: stretch;
}
.patch-main-col,
.patch-side-col { min-width: 0; display: flex; }
/* side-col 现有两张卡（最近应用 + RSU 导入记录），纵向堆叠 */
.patch-side-col { flex-direction: column; gap: 20px; }
.patch-main-card,
.recent-patch-card {
  flex: 1;
  display: flex;
  flex-direction: column;
  min-width: 0;
  padding: var(--card-padding-lg);
}
/* 主卡定 460px 高度基线（drop-zone 主导）；patch-grid align-items:stretch 让
   side-col 拉到等高，recent-patch-card 的 flex:1 吃掉 RSU 卡之外的剩余高度。 */
.patch-main-card { min-height: 460px; }

/* idle 态 drop-zone */
.patch-drop {
  border: 2px dashed var(--border-2);
  border-radius: var(--radius-lg);
  padding: 40px 28px;
  text-align: center;
  background: var(--surface-tint);
  transition: border-color var(--motion-base) var(--ease-standard),
              background var(--motion-base) var(--ease-standard);
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
}
.patch-drop.is-dragover { border-color: var(--accent); background: var(--accent-lt); }
.patch-drop__icon { display: block; width: 36px; height: 36px; margin: 0 auto 12px; color: var(--accent); }
.patch-drop__title { font-size: var(--fs-md); font-weight: 500; color: var(--text-1); margin-bottom: 16px; }
.patch-drop__actions { display: inline-flex; gap: 8px; justify-content: center; margin-bottom: 14px; }
.patch-drop__primary {
  padding: 7px 16px; border: 0; border-radius: var(--radius-md);
  background: var(--text-1); color: var(--surface); font-size: var(--fs-sm); cursor: pointer;
}
.patch-drop__primary:hover { background: #000; }
.patch-drop__secondary {
  padding: 7px 14px; border: 1px solid var(--border-2); border-radius: var(--radius-md);
  background: var(--surface); color: var(--text-2); font-size: var(--fs-sm); cursor: pointer;
}
.patch-drop__secondary:hover { background: var(--bg-warm); border-color: var(--text-3); }
.patch-drop__hint { font-size: var(--fs-2xs); color: var(--text-mute); letter-spacing: 0.3px; }

/* 窄屏：补丁拖放区左右内边距 40/28 太宽，挤得「浏览文件」「粘贴 JSON」
   两个按钮逐字折行。收窄内边距 + 按钮 nowrap，按钮文字恒定一行。 */
@media (max-width: 600px) {
  .patch-drop {
    padding: 28px 14px;
  }
  .patch-drop__primary,
  .patch-drop__secondary {
    white-space: nowrap;
  }
}

/* loaded / preview 态 */
.patch-loaded { display: flex; flex-direction: column; }
.patch-loaded__head {
  display: flex; justify-content: space-between; align-items: flex-start;
  gap: 12px; padding-bottom: 14px; border-bottom: 1px solid var(--divider); margin-bottom: 14px;
}
.patch-loaded__head--bare { border-bottom: 0; padding-bottom: 0; margin-bottom: 0; }
.patch-loaded__src { display: flex; align-items: center; gap: 8px; min-width: 0; }
.patch-loaded__src-icon {
  width: 28px; height: 28px; border-radius: var(--radius-sm); flex-shrink: 0;
  background: var(--up-bg); color: var(--up);
  display: flex; align-items: center; justify-content: center;
  font-size: var(--fs-md); font-weight: 600;
}
.patch-loaded__src-icon--err { background: var(--dn-bg); color: var(--dn); }
.patch-loaded__src-text { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.patch-loaded__src-name { font-size: var(--fs-sm); color: var(--text-1); font-weight: 500; word-break: break-all; }
.patch-loaded__src-meta { font-size: var(--fs-2xs); color: var(--text-3); }
.patch-loaded__summary-title {
  font-size: var(--fs-2xs); color: var(--text-3);
  letter-spacing: 1px; text-transform: uppercase; margin-bottom: 10px;
}
.patch-loaded__error {
  font-size: var(--fs-sm); color: var(--dn); line-height: 1.6;
  background: var(--dn-bg); border-radius: var(--radius-md);
  padding: 10px 12px; margin-bottom: 14px; word-break: break-word;
}
.patch-loaded__actions { display: flex; gap: 8px; align-items: center; }
.patch-loaded--compact { margin-bottom: 14px; }

.patch-op-list { list-style: none; padding: 0; margin: 0 0 16px; display: flex; flex-direction: column; gap: 8px; }
.patch-op-item {
  display: flex; align-items: center; gap: 10px;
  padding: 8px 12px;
  background: var(--surface-tint); border: 1px solid var(--divider);
  border-radius: var(--radius-md); font-size: var(--fs-sm);
}
.patch-op-item__chip {
  display: inline-block; padding: 2px 7px; border-radius: var(--radius-sm);
  font-size: var(--fs-2xs); font-weight: 500; letter-spacing: 0.3px;
  white-space: nowrap; font-family: var(--mono); flex-shrink: 0;
}
.patch-op-item__chip--add { background: var(--up-bg); color: var(--up); }
.patch-op-item__chip--del { background: var(--dn-bg); color: var(--dn); }
.patch-op-item__chip--mod { background: var(--chart-blue-bg); color: var(--chart-blue); }
.patch-op-item__count {
  font-variant-numeric: tabular-nums; font-size: var(--fs-base);
  color: var(--text-1); font-weight: 500; min-width: 28px; text-align: right;
}
.patch-op-item__label { color: var(--text-2); flex-shrink: 0; }
.patch-op-item__detail {
  font-size: var(--fs-xs); color: var(--text-3); flex: 1; min-width: 0;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; text-align: right;
}

.patch-raw-details { margin-top: 12px; }
.patch-raw-details summary {
  font-size: var(--fs-xs); color: var(--text-mute); cursor: pointer;
  padding: 4px 0; list-style: none;
}
.patch-raw-details summary::-webkit-details-marker { display: none; }
.patch-raw-details summary::before { content: "▸ "; font-size: 9px; }
.patch-raw-details[open] summary::before { content: "▾ "; }
.patch-raw-details pre {
  background: var(--surface-tint); border: 1px solid var(--divider);
  border-radius: var(--radius-md); padding: 12px 14px;
  font-family: var(--mono); font-size: var(--fs-xs); color: var(--text-2);
  overflow-x: auto; margin: 6px 0 0; max-height: 240px; overflow-y: auto;
  white-space: pre-wrap; word-break: break-all;
}

.patch-banner {
  border: 1px solid var(--border-1);
  border-radius: var(--radius-md);
  padding: var(--space-4) var(--space-5);
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}

.patch-banner--info {
  background: var(--accent-lt);
  border-color: var(--border-2);
}

.patch-banner--ok {
  background: var(--up-bg);
  border-color: var(--up);
  color: var(--up);
}

.patch-banner--err {
  background: var(--dn-bg);
  border-color: var(--dn);
}

.patch-banner__title {
  font-weight: 600;
  font-size: var(--fs-md);
}

.patch-banner--err .patch-banner__title {
  color: var(--dn);
}

.patch-banner__body {
  color: var(--text-1);
  font-size: var(--fs-base);
  line-height: 1.6;
}

.patch-banner__errors {
  margin: 0;
  padding-left: var(--space-5);
  color: var(--text-1);
  font-size: var(--fs-base);
  line-height: 1.6;
}

.patch-banner__errors li + li {
  margin-top: var(--space-1);
}

.patch-banner__actions {
  display: flex;
  gap: var(--space-2);
  align-items: center;
  margin-top: var(--space-1);
}

/* ── 底部紧凑工具区（数据备份 / 重置凭据 / 清空数据） ───────────────── */

.patch-utils {
  display: flex;
  align-items: center;
  gap: 0;
  padding-top: 14px;
  margin-top: 18px;
  border-top: 1px solid var(--divider);
  font-size: var(--fs-xs);
  color: var(--text-3);
  flex-wrap: wrap;
}
.patch-utils__label { color: var(--text-mute); margin-right: 8px; letter-spacing: 0.3px; }
.patch-utils__link {
  background: transparent;
  border: 0;
  padding: 3px 8px;
  font-size: var(--fs-xs);
  color: var(--text-2);
  font-family: var(--font-body);
  cursor: pointer;
  border-radius: var(--radius-sm);
}
.patch-utils__link:hover { background: var(--bg-warm); color: var(--text-1); }
.patch-utils__sep { color: var(--text-mute); margin: 0 2px; user-select: none; }
.patch-utils__group { display: inline-flex; align-items: center; gap: 2px; }
.patch-utils__group + .patch-utils__group {
  margin-left: 14px;
  padding-left: 14px;
  border-left: 1px solid var(--divider);
}
.patch-utils__group--end { margin-left: auto; border-left: 0; padding-left: 0; }
.patch-utils__danger { color: var(--text-3); }
.patch-utils__danger:hover { color: var(--dn); background: var(--dn-bg); }

.patch-popover {
  position: absolute;
  right: 0;
  top: calc(100% + 6px);
  z-index: 20;
  width: 340px;
  border: 1px solid var(--border-1);
  border-radius: var(--radius-md);
  background: var(--surface);
  box-shadow: var(--shadow-md);
  overflow: hidden;
}

.patch-popover__header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: var(--space-2) var(--space-4);
  background: var(--surface-2);
  border-bottom: 1px solid var(--border-1);
}

.patch-popover__title {
  font-size: var(--fs-sm);
  font-weight: 600;
  color: var(--text-1);
}

.patch-popover__close {
  background: transparent;
  border: 0;
  cursor: pointer;
  color: var(--text-3);
  font-size: 16px;
  padding: 0 4px;
  line-height: 1;
}

.patch-popover__close:hover {
  color: var(--text-1);
}

.patch-popover__intro {
  margin: 0;
  padding: var(--space-3) var(--space-4) 0;
  font-size: var(--fs-sm);
  color: var(--text-2);
  line-height: 1.6;
}

.patch-popover__body {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  padding: var(--space-3) var(--space-4);
}

.patch-popover__item {
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
}

.patch-popover__op {
  font-size: var(--fs-sm);
  font-weight: 500;
  color: var(--text-1);
}

.patch-popover__desc {
  font-size: var(--fs-sm);
  color: var(--text-2);
  line-height: 1.6;
}

/* ── Phase 2.2 conflict banner / hint / danger 副标题 ────────────── */

.patch-banner--warn {
  background: var(--warn-bg);
  border-color: var(--warn);
}

.patch-banner--warn .patch-banner__title {
  color: var(--warn-deep);
}

.patch-banner__danger {
  color: var(--warn-deep);
  font-size: var(--fs-sm);
  margin-top: var(--space-1);
  padding: var(--space-1) var(--space-2);
  background: var(--warn-bg);
  border-radius: var(--radius-sm);
}

.patch-banner__hint {
  color: var(--text-2);
  font-size: var(--fs-sm);
  margin-top: var(--space-1);
  font-style: italic;
}

.patch-err-locator {
  font-family: var(--mono);
  font-size: 11.5px;
  color: var(--dn);
  background: var(--dn-bg);
  border-radius: var(--radius-sm);
  padding: 1px 5px;
  margin-right: 4px;
}

/* ── Phase 2.1 diff 视觉化 ────────────────────────────────────────── */

.patch-diff {
  border: 1px solid var(--border-1);
  border-radius: var(--radius-md);
  background: var(--surface);
  padding: var(--space-3) var(--space-4);
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}

.patch-diff__header {
  display: flex;
  align-items: center;
  justify-content: space-between;
}

.patch-diff__title {
  font-size: var(--fs-md);
  font-weight: 600;
  color: var(--text-1);
}

.patch-diff__toggle-all {
  background: transparent;
  border: 1px solid var(--border-2);
  border-radius: var(--radius-sm);
  padding: 3px 10px;
  font-size: var(--fs-xs);
  color: var(--text-2);
  cursor: pointer;
}

.patch-diff__toggle-all:hover {
  background: var(--surface-2);
}

.patch-diff__op {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}

.patch-diff__op-title {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  font-size: var(--fs-sm);
  color: var(--text-2);
  border-bottom: 1px dashed var(--border-1);
  padding-bottom: 4px;
}

.patch-diff__op-title code {
  font-family: var(--mono);
  background: var(--surface-2);
  border: 1px solid var(--border-1);
  border-radius: var(--radius-sm);
  padding: 1px 6px;
  font-size: 12px;
  color: var(--text-1);
}

.patch-diff__op-counts {
  color: var(--text-3);
  font-size: var(--fs-xs);
  margin-left: auto;
}

.patch-diff__cards {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}

.patch-diff__card {
  border: 1px solid var(--border-1);
  border-radius: var(--radius-sm);
  background: var(--surface);
  overflow: hidden;
}

.patch-diff__card--added {
  border-color: var(--up);
  background: var(--up-bg);
}

.patch-diff__card--deleted {
  border-color: var(--dn);
  background: var(--dn-bg);
}

.patch-diff__card--modified {
  border-color: var(--accent);
  background: var(--accent-lt);
}

.patch-diff__card--info {
  border-color: var(--border-2);
  background: var(--surface-2);
}

.patch-diff__card-summary {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-2) var(--space-3);
  cursor: pointer;
  list-style: none;
  font-size: var(--fs-sm);
}

.patch-diff__card-summary::-webkit-details-marker {
  display: none;
}

.patch-diff__card-summary::before {
  content: "▸";
  color: var(--text-3);
  font-size: 10px;
}

.patch-diff__card[open] .patch-diff__card-summary::before {
  content: "▾";
}

.patch-diff__chip {
  font-size: var(--fs-xs);
  font-weight: 600;
  padding: 1px 6px;
  border-radius: var(--radius-sm);
  flex: 0 0 auto;
}

.patch-diff__chip--added {
  background: var(--up);
  color: #fff;
}

.patch-diff__chip--deleted {
  background: var(--dn);
  color: #fff;
}

.patch-diff__chip--modified {
  background: var(--accent);
  color: #fff;
}

.patch-diff__id {
  font-family: var(--mono);
  font-size: 11.5px;
  color: var(--text-1);
  flex: 0 0 auto;
}

.patch-diff__id--strike {
  text-decoration: line-through;
  color: var(--text-3);
}

.patch-diff__brief {
  color: var(--text-2);
  font-size: var(--fs-xs);
  flex: 1 1 auto;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.patch-diff__brief--strike {
  text-decoration: line-through;
  color: var(--text-3);
}

.patch-diff__changed-count {
  font-size: var(--fs-xs);
  color: var(--text-3);
  flex: 0 0 auto;
}

.patch-diff__card-body {
  padding: var(--space-2) var(--space-3) var(--space-3);
  border-top: 1px dashed var(--border-1);
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
  background: var(--surface);
}

.patch-diff__card--added .patch-diff__card-body,
.patch-diff__card--deleted .patch-diff__card-body,
.patch-diff__card--modified .patch-diff__card-body,
.patch-diff__card--info .patch-diff__card-body {
  background: rgba(255, 255, 255, 0.6);
}

.patch-diff__field {
  display: flex;
  align-items: baseline;
  gap: var(--space-2);
  font-size: var(--fs-sm);
}

.patch-diff__field-name {
  flex: 0 0 84px;
  color: var(--text-3);
  font-family: var(--mono);
  font-size: 11.5px;
  text-transform: uppercase;
  letter-spacing: 0.5px;
}

.patch-diff__field-val {
  font-family: var(--mono);
  font-size: 12.5px;
  color: var(--text-1);
}

.patch-diff__field--unchanged .patch-diff__field-val {
  color: var(--text-3);
}

.patch-diff__field--changed {
  align-items: center;
}

.patch-diff__field-val--old {
  background: var(--dn-bg);
  color: var(--dn);
  text-decoration: line-through;
  padding: 1px 5px;
  border-radius: var(--radius-sm);
}

.patch-diff__field-val--new {
  background: var(--up-bg);
  color: var(--up);
  padding: 1px 5px;
  border-radius: var(--radius-sm);
}

.patch-diff__field-val--strike {
  text-decoration: line-through;
  color: var(--text-3);
}

.patch-diff__field-arrow {
  color: var(--text-3);
  font-size: 11px;
}

.patch-diff__warn {
  color: var(--warn-deep);
  font-size: var(--fs-xs);
}

/* ── 最近应用右侧栏（op 摘要 chip + 文件名 + 时间 + 撤销） ──────────── */

.recent-patch__empty { font-size: var(--fs-sm); color: var(--text-3); padding: 10px 0 0; }

.recent-patch__list { list-style: none; padding: 0; margin: 0; }
.recent-patch__item {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 10px;
  padding: 11px 0;
  border-bottom: 1px solid var(--divider);
}
.recent-patch__item:first-child { padding-top: 0; }
.recent-patch__item:last-child { border-bottom: 0; padding-bottom: 0; }
.recent-patch__main { min-width: 0; flex: 1; }
.recent-patch__chips { display: flex; gap: 5px; margin-bottom: 5px; flex-wrap: wrap; }
.rp-chip {
  font-size: var(--fs-2xs);
  font-family: var(--mono);
  padding: 1px 6px;
  border-radius: var(--radius-sm);
  font-weight: 500;
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
}
.rp-chip--add { background: var(--up-bg); color: var(--up); }
.rp-chip--mod { background: var(--chart-blue-bg); color: var(--chart-blue); }
.rp-chip--del { background: var(--dn-bg); color: var(--dn); }
.recent-patch__file {
  font-size: var(--fs-xs);
  color: var(--text-3);
  font-family: var(--mono);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.recent-patch__meta { display: flex; flex-direction: column; align-items: flex-end; gap: 6px; flex-shrink: 0; }
.recent-patch__time { font-size: var(--fs-2xs); color: var(--text-mute); white-space: nowrap; }
.recent-patch__undo {
  font-size: var(--fs-xs);
  padding: 3px 9px;
  border: 1px solid var(--border-2);
  border-radius: var(--radius-sm);
  background: var(--surface);
  color: var(--text-2);
  cursor: pointer;
  white-space: nowrap;
}
.recent-patch__undo:hover { border-color: var(--dn); color: var(--dn); background: var(--dn-bg); }
/* 非最近一次的历史条目：撤销按钮灰禁用（只能撤销最近一次） */
.recent-patch__undo:disabled {
  opacity: 0.38;
  cursor: not-allowed;
}
.recent-patch__undo:disabled:hover {
  border-color: var(--border-2);
  color: var(--text-2);
  background: var(--surface);
}
/* armed 二次确认态：红底白字，5s 内再点才执行 */
.recent-patch__undo.is-armed,
.recent-patch__undo.is-armed:hover {
  background: var(--dn);
  border-color: var(--dn);
  color: #fff;
}
.recent-patch__undo.is-armed:hover {
  background: #8a2424;
  border-color: #8a2424;
}
/* 陈旧警告：应用补丁后数据又变过，撤销会一并丢失那些改动 */
.recent-patch__stale-warn {
  display: block;
  margin-top: 5px;
  font-size: var(--fs-2xs);
  color: var(--warn);
  line-height: 1.4;
}

/* ── 上传 panel: dropzone + 复核 + 最近上传（mockup L4461–L4670） ────── */

.upload-grid {
  display: grid;
  /* minmax(0, *fr) 让 grid 列可在内容超长时正确收缩到 fr 比例
   * （默认 fr 隐含 min-content，长 token 如多文件合并 filename 会撑爆右栏挤死左栏）。
   * 2026-05-02 多文件上传修订。 */
  grid-template-columns: minmax(0, 45fr) minmax(0, 55fr);
  gap: 16px;
  align-items: stretch;
}
.upload-grid > div { display: flex; min-width: 0; }
.upload-grid > div > .card { flex: 1; display: flex; flex-direction: column; min-width: 0; }

.upload-left-card { padding: var(--card-padding-lg); }
.upload-recent-card { padding: var(--card-padding-lg); }

.drop-zone {
  border: 2px dashed var(--border-2);
  border-radius: var(--radius-lg);
  padding: 28px 24px;
  text-align: center;
  background: var(--surface-tint);
  cursor: pointer;
  transition: border-color var(--motion-base) var(--ease-standard),
              background var(--motion-base) var(--ease-standard);
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
}
.drop-zone:hover,
.drop-zone:focus-visible,
.drop-zone.is-dragover { border-color: var(--accent); background: var(--accent-lt); }
.drop-zone:focus-visible { outline: none; }

.dz-icon { display: block; width: 32px; height: 32px; margin: 0 auto 10px; color: var(--accent); }
.dz-title { font-size: var(--fs-md); font-weight: 500; margin-bottom: 6px; color: var(--text-1); }
.dz-hint { font-size: var(--fs-sm); color: var(--text-3); margin-bottom: 18px; line-height: 1.55; }
.dz-actions { display: inline-flex; gap: 8px; justify-content: center; }
.dz-browse {
  display: inline-flex;
  padding: 7px 18px;
  border: 0;
  border-radius: var(--radius-md);
  background: var(--text-1);
  color: var(--surface);
  font-size: var(--fs-sm);
  font-family: var(--font-body);
  cursor: pointer;
}
.dz-browse:hover { background: #000; }
.dz-formats {
  margin-top: 18px;
  font-family: var(--font-body);
  font-variant-numeric: tabular-nums;
  font-size: var(--fs-2xs);
  color: var(--text-3);
  letter-spacing: 0.5px;
}

.upload-progress { height: 3px; background: var(--bg-warm); border-radius: var(--radius-xs); margin-top: 12px; overflow: hidden; }
.upload-progress > span { display: block; height: 100%; width: 30%; background: var(--accent); animation: progressPulse 1.2s linear infinite; }
@keyframes progressPulse { 0% { transform: translateX(-100%); } 100% { transform: translateX(400%); } }
.upload-progress[hidden] { display: none; }

.ocr-progress {
  margin: 10px 0 8px;
}
.ocr-progress__label {
  margin-bottom: 6px;
  font-size: var(--fs-xs);
  color: var(--text-3);
  font-variant-numeric: tabular-nums;
}
.ocr-progress__bar {
  height: 3px;
  background: var(--bg-warm);
  border-radius: var(--radius-xs);
  overflow: hidden;
}
.ocr-progress__bar > span {
  display: block;
  height: 100%;
  width: 0;
  min-width: 8px;
  background: var(--accent);
  transition: width var(--motion-fast) var(--ease-standard);
}
.ocr-progress__bar--indeterminate > span {
  width: 30%;
  min-width: 0;
  animation: progressPulse 1.2s linear infinite;
}

.ocr-card {
  margin-top: 16px;
  padding-top: 14px;
  border-top: 1px solid var(--divider);
}
.ocr-card__head {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  gap: 12px;
  margin-bottom: 10px;
}
.ocr-card__title { font-size: var(--fs-md); font-weight: 650; color: var(--text-1); }
.ocr-card__sub { margin-top: 2px; font-size: var(--fs-xs); color: var(--text-3); }
.ocr-card__privacy {
  padding: 9px 10px;
  border-radius: var(--radius-sm);
  background: var(--warn-bg);
  color: var(--warn);
  font-size: var(--fs-xs);
  line-height: 1.45;
  margin-bottom: 10px;
}
.ocr-card__quota {
  margin-bottom: 10px;
  font-size: var(--fs-xs);
  line-height: 1.45;
  color: var(--text-2);
}
.ocr-card__quota--muted { color: var(--text-3); }
.ocr-card__fields {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(140px, 0.8fr);
  gap: 10px;
}
.ocr-card__check {
  display: flex;
  align-items: flex-start;
  gap: 8px;
  margin: 10px 0;
  font-size: var(--fs-xs);
  line-height: 1.45;
  color: var(--text-2);
}
.ocr-card__check input { margin-top: 2px; }
.ocr-card__file {
  min-height: 18px;
  margin-bottom: 10px;
  color: var(--text-3);
  font-size: var(--fs-xs);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.ocr-card__notice {
  margin: 8px 0;
  color: var(--warn);
  font-size: var(--fs-xs);
  line-height: 1.45;
}
.ocr-card__batch-meter {
  margin: 8px 0 10px;
  color: var(--text-3);
  font-size: var(--fs-xs);
  line-height: 1.45;
}
.ocr-card__batch-meter--over { color: var(--dn); font-weight: 600; }
.ocr-card__actions { display: flex; flex-wrap: wrap; gap: 8px; }
.ocr-card__status {
  margin-top: 10px;
  font-size: var(--fs-xs);
  color: var(--text-3);
}
.ocr-card__error { margin-top: 10px; margin-bottom: 0; }
.ocr-card__result {
  margin-top: 10px;
  padding: 10px;
  border: 1px solid var(--up);
  border-radius: var(--radius-sm);
  background: var(--up-bg);
  color: var(--text-2);
  font-size: var(--fs-xs);
  line-height: 1.5;
}
.ocr-card__meta { color: var(--text-3); }

.ocr-thumb-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(132px, 1fr));
  gap: 10px;
  margin: 10px 0 8px;
}
.ocr-thumb {
  position: relative;
  min-width: 0;
  border: 1px solid var(--border-1);
  border-radius: var(--radius-md);
  background: var(--surface);
  overflow: hidden;
}
.ocr-thumb--ok { border-color: color-mix(in srgb, var(--up) 48%, var(--border-1)); background: var(--up-bg); }
.ocr-thumb--failed { border-color: color-mix(in srgb, var(--dn) 48%, var(--border-1)); background: var(--dn-bg); }
.ocr-thumb--running { border-color: color-mix(in srgb, var(--accent) 48%, var(--border-1)); background: var(--accent-lt); }
.ocr-thumb--given_up { background: var(--surface-2); opacity: 0.86; }
.ocr-thumb__preview {
  display: block;
  width: 100%;
  aspect-ratio: 4 / 3;
  padding: 0;
  border: 0;
  background: var(--surface-2);
  cursor: zoom-in;
}
.ocr-thumb__preview img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}
.ocr-thumb__delete {
  position: absolute;
  top: 5px;
  right: 5px;
  width: 22px;
  height: 22px;
  border: 1px solid color-mix(in srgb, var(--text-1) 14%, transparent);
  border-radius: var(--radius-pill);
  background: color-mix(in srgb, var(--surface) 92%, transparent);
  color: var(--text-2);
  font-size: var(--fs-sm);
  line-height: 1;
  z-index: 1;
}
.ocr-thumb__status {
  padding: 6px 8px 0;
  color: var(--text-2);
  font-size: var(--fs-xs);
  font-weight: 600;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.ocr-thumb__name {
  padding: 3px 8px 0;
  color: var(--text-3);
  font-size: var(--fs-2xs);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.ocr-thumb__actions {
  display: flex;
  flex-wrap: wrap;
  gap: 2px 6px;
  padding: 4px 8px 8px;
}
.ocr-thumb__actions .btn-link {
  height: auto;
  min-height: 20px;
  padding: 0;
  font-size: var(--fs-2xs);
}

.ocr-preview-overlay {
  z-index: 120;
}
.ocr-preview-card {
  width: min(920px, calc(100vw - 48px));
  height: min(760px, calc(100vh - 64px));
  display: flex;
  flex-direction: column;
  border-radius: var(--radius-lg);
  background: var(--surface);
  box-shadow: var(--shadow-md);
  overflow: hidden;
}
.ocr-preview-card__head {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 12px;
  padding: 12px 16px;
  border-bottom: 1px solid var(--border-1);
  color: var(--text-2);
  font-size: var(--fs-sm);
}
.ocr-preview-card__head span {
  min-width: 0;
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
}
.ocr-preview-card__body {
  flex: 1;
  min-height: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--surface-2);
  padding: 12px;
}
.ocr-preview-card__body img {
  max-width: 100%;
  max-height: 100%;
  object-fit: contain;
  border-radius: var(--radius-sm);
  background: var(--surface);
}

.ocr-phrase-admin {
  margin-top: 12px;
  padding-top: 12px;
  border-top: 1px dashed var(--divider);
}
.ocr-phrase-admin__head {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 10px;
  margin-bottom: 8px;
  font-size: var(--fs-xs);
  color: var(--text-3);
}
.ocr-phrase-admin__head strong { color: var(--text-1); }
.ocr-phrase-admin__empty {
  font-size: var(--fs-xs);
  color: var(--text-3);
}
.ocr-phrase-admin__list {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin: 0;
  padding: 0;
  list-style: none;
}
.ocr-phrase-admin__item {
  display: flex;
  justify-content: space-between;
  gap: 10px;
  align-items: center;
  padding: 8px 10px;
  border: 1px solid var(--border-1);
  border-radius: var(--radius-sm);
  background: var(--surface-tint);
}
.ocr-phrase-admin__main { min-width: 0; }
.ocr-phrase-admin__phrase {
  color: var(--text-1);
  font-size: var(--fs-xs);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.ocr-phrase-admin__meta {
  margin-top: 2px;
  color: var(--text-3);
  font-size: var(--fs-2xs);
}
.ocr-phrase-admin__actions {
  display: flex;
  flex: 0 0 auto;
  gap: 6px;
}

/* 聚合审核：一组一卡（比例条 + 多个判定按钮）。main 占满、actions 竖排换行。 */
.ocr-phrase-admin__item--group {
  align-items: flex-start;
  flex-wrap: wrap;
}
.ocr-phrase-admin__item--group .ocr-phrase-admin__main { flex: 1 1 60%; }
.ocr-phrase-admin__item--group .ocr-phrase-admin__actions {
  flex-direction: column;
  align-items: stretch;
}
.ocr-phrase-admin__item--group .ocr-phrase-admin__bars,
.ocr-phrase-admin__item--group .admin-dash__bars { margin-top: 6px; }
/* 格式池：组内每个结构变体一块 */
.ocr-phrase-admin__variant {
  margin-top: 8px;
  padding-top: 8px;
  border-top: 1px dashed var(--divider);
  display: flex;
  flex-direction: column;
  gap: 4px;
  align-items: flex-start;
}
/* 已下架条目：灰显 */
.ocr-phrase-admin__item--inactive { opacity: 0.55; }
/* 异见计数：醒目暖色 */
.ocr-phrase-admin__dissent { color: var(--warn, #b45309); font-weight: 600; }

/* Day 0 候选复核区（ADR 0118 落地实现） — OCR 卡下方延伸出来的列表 */
.day0-cands-empty {
  margin-top: 12px;
  padding: 10px 12px;
  border-top: 1px dashed var(--divider);
  font-size: var(--fs-xs);
  color: var(--text-3);
  line-height: 1.5;
}
.day0-cands {
  margin-top: 16px;
  padding-top: 14px;
  border-top: 1px solid var(--divider);
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.day0-cands__head {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 12px;
  flex-wrap: wrap;
}
.day0-cands__title {
  font-size: var(--fs-md);
  font-weight: 650;
  color: var(--text-1);
}
.day0-cands__meta { display: flex; gap: 6px; flex-wrap: wrap; }
.day0-cands__chip {
  font-size: var(--fs-2xs);
  padding: 2px 8px;
  border-radius: 999px;
  border: 1px solid var(--border-1);
  background: var(--bg-2);
  color: var(--text-2);
  font-variant-numeric: tabular-nums;
}
.day0-cands__chip--pending { border-color: rgba(217, 119, 6, 0.4); background: var(--warn-bg); color: var(--warn-deep, #92400e); }
.day0-cands__chip--saved { border-color: rgba(34, 139, 34, 0.4); background: var(--up-bg); color: var(--up); }
.day0-cands__chip--skipped { color: var(--text-3); }
.day0-cands__hint {
  font-size: var(--fs-xs);
  color: var(--text-3);
  line-height: 1.5;
  margin-bottom: 2px;
}
.day0-cand {
  border: 1px solid var(--border-1);
  border-radius: var(--radius-md);
  padding: 12px 14px;
  background: var(--surface);
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.day0-cand--saved {
  flex-direction: row;
  align-items: center;
  justify-content: space-between;
  background: var(--up-bg);
  border-color: rgba(34, 139, 34, 0.35);
  padding: 10px 14px;
}
.day0-cand--skipped {
  flex-direction: row;
  align-items: center;
  justify-content: space-between;
  background: var(--bg-2);
  color: var(--text-3);
  padding: 10px 14px;
}
.day0-cand--error { border-color: var(--dn); background: var(--dn-bg); }
.day0-cand--blocked { border-color: var(--dn); background: var(--dn-bg); }
.day0-cand__blocked {
  display: flex;
  gap: 8px;
  align-items: flex-start;
  padding: 8px 10px;
  border: 1px solid var(--dn);
  background: var(--dn-bg);
  border-radius: var(--radius-sm);
  color: var(--dn);
  font-size: var(--fs-xs);
  line-height: 1.5;
}
.day0-cand__blocked-icon { flex-shrink: 0; font-size: var(--fs-sm); line-height: 1.4; }
.day0-cand__head {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
}
.day0-cand__rank {
  font-size: var(--fs-xs);
  font-weight: 600;
  color: var(--text-2);
}
.day0-cand__source {
  font-size: var(--fs-xs);
  color: var(--text-3);
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.day0-cand__saved-mark { font-size: var(--fs-sm); color: var(--up); font-weight: 600; }
.day0-cand__skipped-mark { font-size: var(--fs-sm); color: var(--text-3); }
.day0-cand__rowtext {
  font-size: var(--fs-2xs);
  color: var(--text-3);
  padding: 6px 10px;
  background: var(--bg-warm);
  border-radius: var(--radius-sm);
  line-height: 1.5;
  overflow: hidden;
  text-overflow: ellipsis;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
}
/* 自动补的现金候选：原行文字位置改放灰色说明（无原始 rowText 可回显），不裁剪行数 */
.day0-cand__rowtext--synth {
  font-style: italic;
  -webkit-line-clamp: initial;
  display: block;
}
.day0-cand__kind {
  display: flex;
  align-items: center;
  gap: 12px;
  flex-wrap: wrap;
  padding: 6px 0;
  border-bottom: 1px dashed var(--divider);
}
.day0-cand__kind-label { font-size: var(--fs-xs); color: var(--text-2); }
.day0-cand__kind-opt {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  font-size: var(--fs-xs);
  color: var(--text-2);
  cursor: pointer;
}
.day0-cand__grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 10px 14px;
}
@media (max-width: 900px) {
  .day0-cand__grid { grid-template-columns: 1fr; }
}
.day0-cand__field--uncertain {
  background: var(--warn-bg);
  padding: 4px 6px;
  margin: -4px -6px;
  border-radius: var(--radius-sm);
}
.day0-cand__errors {
  display: flex;
  gap: 8px;
  align-items: flex-start;
  padding: 8px 10px;
  border: 1px solid var(--dn);
  background: var(--dn-bg);
  border-radius: var(--radius-sm);
  color: var(--dn);
  font-size: var(--fs-xs);
  line-height: 1.5;
}
.day0-cand__errors-icon {
  width: 18px;
  height: 18px;
  flex-shrink: 0;
  border-radius: 50%;
  background: var(--dn);
  color: #fff;
  display: flex;
  align-items: center;
  justify-content: center;
  font-weight: 700;
  font-size: var(--fs-2xs);
}
.day0-cand__actions {
  display: flex;
  justify-content: flex-end;
  gap: 8px;
  margin-top: 4px;
}

/* 字段来源 chip — evidence/inferred/missing/touched */
.day0-chip {
  display: inline-block;
  font-size: var(--fs-2xs);
  padding: 1px 6px;
  border-radius: 999px;
  margin-left: 4px;
  font-weight: 500;
  vertical-align: middle;
  letter-spacing: 0.2px;
}
.day0-chip--evidence { background: var(--up-bg); color: var(--up); }
.day0-chip--inferred { background: var(--accent-lt, #e0e7ff); color: var(--accent, #4338ca); }
.day0-chip--missing { background: var(--dn-bg); color: var(--dn); }
.day0-chip--touched { background: var(--bg-2); color: var(--text-3); border: 1px solid var(--border-1); }
.day0-cand__estimate {
  grid-column: 1 / -1;
}
.day0-cand__estimate--ok {
  border-color: rgba(196, 106, 31, 0.45);
  background: var(--warn-bg);
}
.day0-cand__estimate--idle {
  border-color: rgba(196, 106, 31, 0.3);
}

/* ── 截图历史导入复核（ADR 0119） ───────────────────────────────────── */
.history-review {
  margin-top: 16px;
  padding-top: 14px;
  border-top: 1px solid var(--divider);
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.history-review__head {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 12px;
  flex-wrap: wrap;
}
.history-review__title { font-size: var(--fs-md); font-weight: 650; color: var(--text-1); }
.history-review__meta { font-size: var(--fs-xs); color: var(--text-3); }
.history-review__hint { font-size: var(--fs-xs); color: var(--text-3); line-height: 1.5; }
.history-review__banners { display: flex; flex-direction: column; gap: 6px; }
.history-banner {
  font-size: var(--fs-sm);
  padding: 8px 10px;
  border-radius: var(--radius-md);
  border: 1px solid var(--border-1);
}
.history-banner--warn { background: var(--warn-bg); border-color: rgba(217, 119, 6, 0.4); color: var(--warn-deep, #92400e); }
.history-banner--block { background: var(--dn-bg); border-color: rgba(220, 38, 38, 0.4); color: var(--dn); }

/* 持仓页对账锚点（C 方案，Phase 5）：黄条/已记录未入账清单 + 知道了 */
.history-snapshot-recon { display: flex; flex-direction: column; gap: 6px; margin: 6px 0; }
.history-snapshot-recon__list { margin: 6px 0 0; padding-left: 18px; }
.history-snapshot-recon__list li { margin: 2px 0; }
.history-snapshot-recon__dismiss { display: flex; justify-content: flex-end; }

.history-day0-seed {
  background: var(--surface);
  border: 1px solid var(--border-1);
  border-radius: var(--radius-md);
  padding: 10px 12px;
}
.history-day0-seed__head { font-size: var(--fs-sm); margin-bottom: 8px; }
.history-day0-seed__hint { font-size: var(--fs-xs); color: var(--text-3); margin-left: 8px; }
.history-day0-seed__list { list-style: none; padding: 0; margin: 0; display: flex; flex-direction: column; gap: 6px; }
.history-day0-seed__list code { font-family: inherit; font-size: var(--fs-2xs); color: var(--text-3); }

.history-review__rows { display: flex; flex-direction: column; gap: 8px; }
.history-row {
  border: 1px solid var(--border-1);
  border-radius: var(--radius-md);
  padding: 10px 12px;
  background: var(--surface);
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.history-row--green { border-left: 3px solid var(--up); }
.history-row--yellow { border-left: 3px solid var(--warn); background: var(--warn-bg); }
.history-row--red { border-left: 3px solid var(--dn); background: var(--dn-bg); }
.history-row--skip { border-left: 3px solid var(--text-3); opacity: 0.7; }
.history-row--skipped {
  background: var(--bg-2);
  color: var(--text-3);
  display: flex;
  flex-direction: row;
  align-items: center;
  gap: 12px;
  border-left: 3px solid var(--text-3);
}
.history-row__head { display: flex; gap: 12px; align-items: center; flex-wrap: wrap; }
.history-row__rank { font-size: var(--fs-xs); color: var(--text-3); }
.history-row__verdict { font-size: var(--fs-xs); padding: 2px 6px; border-radius: 999px; background: var(--bg-2); color: var(--text-2); }
.history-row__parsed { font-size: var(--fs-sm); color: var(--text-2); margin-left: auto; }
.history-row__rowtext {
  font-size: var(--fs-xs);
  color: var(--text-3);
  background: var(--bg-2);
  padding: 6px 8px;
  border-radius: var(--radius-sm);
  overflow: hidden;
  text-overflow: ellipsis;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
}
.history-row__reasons { font-size: var(--fs-xs); color: var(--text-3); display: flex; flex-wrap: wrap; gap: 4px; }
.history-row__estimate {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
  padding: 7px 8px;
  border-radius: var(--radius-sm);
  border: 1px solid rgba(196, 106, 31, 0.3);
  background: rgba(255, 255, 255, 0.55);
  font-size: var(--fs-xs);
}
.history-row__estimate--ok { border-color: rgba(60, 139, 90, 0.35); background: var(--up-bg); }
.history-row__estimate--error { border-color: rgba(212, 65, 86, 0.35); background: rgba(255, 255, 255, 0.6); }
.history-row__estimate-note { color: var(--text-2); line-height: 1.45; }
.history-row__estimate--error .history-row__estimate-note { color: var(--dn); }
.history-row__pickers { display: flex; gap: 12px; flex-wrap: wrap; }
.history-row__field { display: flex; flex-direction: column; gap: 4px; min-width: 180px; flex: 1; }

/* 逐行手填日期 / 金额（救 OCR 读错 / 读空）：折叠展开的两字段区 + ✎ 已手填标记 + 无效输入红框 */
.history-row__parsed-edited { color: var(--dn); font-size: var(--fs-xs); }
.history-row__edit {
  display: flex;
  gap: 12px;
  flex-wrap: wrap;
  padding: 7px 8px;
  border-radius: var(--radius-sm);
  border: 1px dashed var(--border-1);
  background: rgba(255, 255, 255, 0.55);
}
.history-row__edit-field { display: flex; flex-direction: column; gap: 4px; min-width: 160px; flex: 1; }
.history-row__edit-input--err { border-color: var(--dn); }
.history-row__edit-err { font-size: var(--fs-xs); color: var(--dn); line-height: 1.4; }
.history-row__edit-hint { font-size: var(--fs-xs); color: var(--text-3); line-height: 1.4; }

/* ADR 0148：手动拆/合产品组 — 行级 grip + 「移到…」菜单 + 已移动标记 + 拖拽放置高亮 */
.history-row__regroup { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin-top: 4px; }
.history-row__grip {
  cursor: grab; user-select: none; font-size: var(--fs-xs); color: var(--text-3);
  padding: 2px 8px; border: 1px dashed var(--border-1); border-radius: 999px; background: var(--bg-2);
}
.history-row__grip:active { cursor: grabbing; }
.history-row__regroup-menu { max-width: 240px; }
.history-row--moved { border-left-color: var(--accent); }
.history-row__moved-mark { font-size: var(--fs-xs); color: var(--accent); font-weight: 650; }
.history-row.is-regroup-over { outline: 2px dashed var(--accent); outline-offset: 1px; }
.history-new-asset__warn {
  font-size: var(--fs-xs); line-height: 1.45; color: var(--text-2);
  border: 1px solid var(--warn); background: var(--warn-bg); border-radius: var(--radius-sm);
  padding: 6px 8px;
}
.history-review__stale {
  font-size: var(--fs-xs); line-height: 1.45; color: var(--text-2);
  border: 1px solid var(--warn); background: var(--warn-bg); border-radius: var(--radius-sm);
  padding: 6px 8px; display: flex; align-items: center; gap: 6px; flex-wrap: wrap;
}
.history-draft-chip__warn { color: var(--warn); font-weight: 700; }
.history-draft-chip.has-acct-conflict { border-color: var(--warn); }

.history-new-asset {
  background: var(--bg-2);
  border: 1px dashed var(--border-1);
  border-radius: var(--radius-md);
  padding: 10px 12px;
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.history-new-asset__head { display: flex; gap: 12px; align-items: center; flex-wrap: wrap; font-size: var(--fs-sm); }
.history-new-asset__head label { display: flex; gap: 4px; align-items: center; font-size: var(--fs-xs); }
.history-new-asset__grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(180px, 1fr));
  gap: 8px;
}
@media (max-width: 900px) { .history-new-asset__grid { grid-template-columns: 1fr; } }
.history-new-asset__grid label { display: flex; flex-direction: column; gap: 4px; }
.history-new-asset__actions { display: flex; gap: 8px; justify-content: flex-end; }

/* 方案 A：按产品草稿的清仓/持有线索 + 探活状态 + 两 section 概览 */
.history-draft__probe { font-size: var(--fs-xs); margin-left: 6px; }
.history-draft__probe--hit { color: var(--up); }
.history-draft__probe--miss, .history-draft__probe--fail { color: var(--dn); }
.history-draft__probe--probing { color: var(--text-3); }
.history-draft__cleared { flex-direction: row !important; align-items: center; gap: 6px; font-size: var(--fs-xs); grid-column: 1 / -1; }
.history-draft__hint { color: var(--accent); }
.history-draft__note { grid-column: 1 / -1; font-size: var(--fs-xs); color: var(--text-3); }

.history-draft-sections { display: flex; gap: 12px; flex-wrap: wrap; }
@media (max-width: 900px) { .history-draft-sections { flex-direction: column; } }
.history-draft-section {
  flex: 1; min-width: 200px;
  border: 1px solid var(--border-1);
  border-radius: var(--radius-md);
  padding: 8px 10px;
  background: var(--bg-2);
}
.history-draft-section__head { font-size: var(--fs-xs); font-weight: 650; color: var(--text-2); margin-bottom: 6px; }
.history-draft-section__list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 4px; }
.history-draft-chip {
  display: flex; align-items: center; gap: 6px;
  font-size: var(--fs-xs); color: var(--text-1);
  padding: 4px 6px; border-radius: var(--radius-sm); background: var(--surface);
}
.history-draft-chip.is-empty { color: var(--text-3); background: transparent; }
.history-draft-chip.is-saved { border-left: 2px solid var(--up); }
.history-draft-chip__kind { color: var(--text-3); }
.history-draft-chip__pending { color: var(--accent); margin-left: auto; }

.history-review__commit { display: flex; gap: 8px; justify-content: flex-end; margin-top: 6px; }

/* recent-list（mockup L4619–L4665）—— 容器头部统一走 .tx-section-head */
.recent-empty { font-size: var(--fs-sm); color: var(--text-3); padding: 10px 0; }
.recent-list { display: flex; flex-direction: column; gap: 6px; }
.recent-item {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 12px;
  border: 1px solid var(--border-1);
  border-radius: var(--radius-md);
  background: var(--surface);
  font-size: var(--fs-sm);
}
.recent-icon {
  width: 28px; height: 28px;
  border-radius: var(--radius-sm);
  background: var(--up-bg);
  color: var(--up);
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  font-size: var(--fs-base);
}
.recent-info { flex: 1; min-width: 0; }
.recent-file {
  font-family: var(--font-body);
  font-size: var(--fs-sm);
  color: var(--text-1);
  font-weight: 500;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.recent-stats {
  font-family: var(--font-body);
  font-variant-numeric: tabular-nums;
  font-size: var(--fs-2xs);
  color: var(--text-3);
  margin-top: 2px;
  display: flex;
  gap: 8px;
}
.recent-stats .pos { color: var(--up); font-weight: 500; }
.recent-stats .dim { color: var(--text-3); }
.recent-actions { display: flex; gap: 4px; }

/* 窄屏：「最近导入」条目的统计行（写入/跳过 + 日期）整体宽度不够时，
   两段（统计 / 日期）会各自在空格处乱断行。改为整段不可拆、段间换行。 */
@media (max-width: 600px) {
  .recent-stats {
    flex-wrap: wrap;
  }
  .recent-stats .pos,
  .recent-stats .dim {
    white-space: nowrap;
  }
}

.recent-undo {
  font-size: var(--fs-xs);
  padding: 4px 9px;
  border-radius: var(--radius-sm);
  border: 1px solid var(--border-2);
  background: var(--surface);
  color: var(--text-2);
  cursor: pointer;
  font-family: var(--font-body);
  transition: background var(--motion-base) var(--ease-standard),
              border-color var(--motion-base) var(--ease-standard),
              color var(--motion-base) var(--ease-standard);
}
.recent-undo:hover { color: var(--dn); border-color: var(--dn); }

/* ── armed 二次确认（mockup L2511–L2548） ──────────────────────────── */

.recent-undo.is-armed,
.btn[data-confirm-delete].is-armed {
  background: var(--dn);
  border-color: var(--dn);
  color: #fff;
  position: relative;
  overflow: hidden;
}
.recent-undo.is-armed > .label,
.btn[data-confirm-delete].is-armed > .label { font-size: 0; color: #fff; }
.btn[data-confirm-delete].is-armed > .label::before {
  content: '确认删除';
  font-size: var(--fs-sm);
  color: #fff;
}
.recent-undo.is-armed > .label::before {
  content: '确认撤销';
  font-size: var(--fs-xs);
  color: #fff;
}
.recent-undo.is-armed::after,
.btn[data-confirm-delete].is-armed::after {
  content: '';
  position: absolute;
  left: 0; bottom: 0;
  height: 2px;
  background: rgba(255, 255, 255, 0.7);
  animation: armed-countdown 5s linear forwards;
}
@keyframes armed-countdown { from { width: 100%; } to { width: 0; } }

.btn[data-confirm-delete].is-armed:hover,
.recent-undo.is-armed:hover {
  background: #8a2424;
  border-color: #8a2424;
  color: #fff;
}

/* ── 复核清单（v8 终稿，2026-05-03 mockup/review-list-v8.html merge） ──── */

.review-section { display: block; }

/* dry-run commitImport 校验失败时的红色横幅（onReviewConfirm fail 场景） */
.review-error-banner {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  padding: 10px 12px;
  margin-bottom: 12px;
  background: var(--dn-bg, #fef0f0);
  color: var(--dn, #b42318);
  border: 1px solid var(--dn, #b42318);
  border-radius: var(--radius-sm);
  font-size: var(--fs-xs);
  line-height: 1.45;
}
.review-error-banner__icon { flex-shrink: 0; font-size: 14px; }
.review-error-banner__text { flex: 1; word-break: break-word; }
.review-error-banner__close {
  flex-shrink: 0;
  background: transparent;
  border: none;
  color: inherit;
  font-size: 16px;
  line-height: 1;
  padding: 2px 6px;
  cursor: pointer;
  border-radius: var(--radius-xs, 4px);
}
.review-error-banner__close:hover { background: rgba(180, 35, 24, 0.08); }

.review-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  margin-bottom: 6px;
  flex-wrap: wrap;
}
.review-title { font-size: var(--fs-md); font-weight: 500; color: var(--text-1); }
.review-actions { display: flex; gap: 8px; flex-shrink: 0; flex-wrap: wrap; }

/* 顶部 overview（替代旧 .summary-strip） */
.review-overview {
  display: flex;
  gap: 32px;
  padding: 18px 22px;
  background: var(--surface-tint);
  border: 1px solid var(--border-1);
  border-radius: var(--radius-md);
  margin-bottom: 16px;
  align-items: center;
}
.ov-item { display: flex; flex-direction: column; gap: 3px; }
.ov-k {
  font-size: var(--fs-2xs);
  color: var(--text-3);
  letter-spacing: 0.4px;
  text-transform: uppercase;
}
.ov-v {
  font-family: var(--font-body);
  font-variant-numeric: tabular-nums;
  font-size: 20px;
  color: var(--text-1);
  font-weight: 500;
  line-height: 1.1;
}
.ov-v.warning { color: var(--warn); }
.ov-v.success { color: var(--up); }
.ov-divider { width: 1px; align-self: stretch; background: var(--border-1); }

/* 分组 section 标题（"待你确认 N" / "已自动识别 Z"） */
.rgroup-title {
  display: flex;
  align-items: center;
  gap: 8px;
  font-family: var(--font-body);
  font-variant-numeric: tabular-nums;
  font-size: var(--fs-xs);
  letter-spacing: 0.5px;
  text-transform: uppercase;
  color: var(--text-3);
  margin: 14px 0 8px;
  padding-top: 4px;
}
.rgroup-title:first-of-type { margin-top: 0; }
.rgroup-title.pending { color: var(--warn); }
.rgroup-count {
  font-family: var(--font-body);
  font-variant-numeric: tabular-nums;
  font-size: var(--fs-2xs);
  padding: 1px 7px;
  border-radius: 9px;
  background: var(--bg-warm);
  color: var(--text-3);
}
.rgroup-title.pending .rgroup-count { background: var(--warn-bg); color: var(--warn-deep); }

.review-list { display: flex; flex-direction: column; gap: 8px; }

/* ── 行卡片 ── */
.rrow {
  background: var(--surface);
  border: 1px solid var(--border-1);
  border-radius: var(--radius-md);
  padding: 14px 16px;
}
.rrow-probe {
  border-color: #f2dfb3;
  background: #fffaef;
}

.rrow-head {
  display: flex;
  align-items: center;
  gap: 12px;
  flex-wrap: wrap;
}
.rrow-badge {
  font-size: var(--fs-2xs);
  padding: 3px 9px;
  border-radius: 999px;
  font-family: var(--font-body);
  font-weight: 500;
  letter-spacing: 0.2px;
  white-space: nowrap;
}
.rrow-badge.pending   { background: var(--warn-bg); color: var(--warn-deep); }
.rrow-badge.warning   { background: var(--warn-bg); color: var(--warn-deep); }
.rrow-badge.confirmed { background: var(--up-bg); color: var(--up); }

/* 入账前校验黄灯行（A1 单价×股数对不上 / A2 疑似重复）—— 提升到可见、逐笔可跳过 */
.rrow-warn { border-left: 3px solid var(--warn); background: var(--warn-bg); }
.rrow-warn--skipped { opacity: 0.55; }
.rrow-warn-amt {
  font-variant-numeric: tabular-nums;
  font-size: var(--fs-base);
  color: var(--text-2);
  margin-left: auto;
  white-space: nowrap;
}
.rwarn-reason {
  font-size: 13px;
  color: var(--warn-deep);
  padding: 4px 12px 8px;
  line-height: 1.4;
}

.rrow-symbol {
  font-family: var(--mono);
  font-size: 16px;
  font-weight: 500;
  color: var(--text-1);
}
.rrow-arrow {
  color: var(--text-mute);
  font-family: var(--font-body);
  font-variant-numeric: tabular-nums;
  font-size: 14px;
}
.rrow-resolved {
  font-size: var(--fs-base);
  color: var(--text-1);
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.rrow-resolved .ccy {
  font-family: var(--mono);
  font-size: var(--fs-xs);
  color: var(--text-3);
  margin-left: 6px;
}
.rrow-count-chip {
  font-family: var(--font-body);
  font-variant-numeric: tabular-nums;
  font-size: var(--fs-2xs);
  padding: 2px 7px;
  border-radius: 9px;
  background: var(--bg-warm);
  color: var(--text-3);
  flex-shrink: 0;
}
.rrow-head-actions {
  display: flex;
  gap: 4px;
  align-items: center;
  margin-left: auto;
}

.btn-link {
  background: transparent;
  border: 0;
  color: var(--text-3);
  font-size: var(--fs-xs);
  cursor: pointer;
  padding: var(--space-1) var(--space-2);
  border-radius: var(--radius-sm);
  font-family: var(--font-body);
}
.btn-link:hover { background: var(--bg-warm); color: var(--text-1); }
.btn-link.danger:hover { background: var(--dn-bg); color: var(--dn); }

/* ── probe 行：问句 + 3 选项卡 ── */
.rrow-question {
  margin-top: 10px;
  padding-top: 10px;
  border-top: 1px dashed #e8d9b8;
  font-size: var(--fs-sm);
  color: var(--text-1);
  line-height: 1.55;
}
.rrow-question b { font-weight: 500; }
.rrow-question code {
  font-family: var(--mono);
  font-size: var(--fs-xs);
  padding: 1px 5px;
  background: rgba(255, 255, 255, 0.7);
  border: 1px solid #e8d9b8;
  border-radius: 3px;
  color: var(--text-1);
  font-weight: 500;
}

.rrow-options {
  display: flex;
  flex-direction: column;
  gap: 6px;
  margin-top: 10px;
}
.ropt {
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 10px 14px;
  background: var(--surface);
  border: 1px solid #e8d9b8;
  border-radius: var(--radius-sm);
  transition: background var(--motion-fast), border-color var(--motion-fast);
}
.ropt:hover { border-color: var(--accent); background: #fffefa; }
.ropt-hint { flex: 1; min-width: 0; }
.ropt-hint-title {
  font-size: var(--fs-sm);
  font-weight: 500;
  color: var(--text-1);
  line-height: 1.4;
}
.ropt-hint-sub {
  font-size: var(--fs-xs);
  color: var(--text-3);
  line-height: 1.45;
  margin-top: 2px;
}
.ropt-action {
  display: flex;
  align-items: center;
  gap: 6px;
  flex-shrink: 0;
}

/* ── confirmed 行：始终显示 name + category 编辑 ── */
.rrow-edit {
  display: flex;
  align-items: end;
  gap: 24px;
  margin-top: 12px;
  padding-top: 12px;
  border-top: 1px dashed var(--border-1);
  justify-content: flex-start;
}
.rrow-edit-field {
  display: flex;
  flex-direction: column;
  gap: 4px;
}
.rrow-edit-field-label {
  font-family: var(--font-body);
  font-variant-numeric: tabular-nums;
  font-size: var(--fs-2xs);
  color: var(--text-3);
  letter-spacing: 0.3px;
  text-transform: uppercase;
}
.rrow-edit-field--name { flex: 0 0 320px; }
.rrow-edit-field--name input { width: 100%; }
.rrow-edit-field--category { flex: 0 0 150px; position: relative; }

/* T2：已匹配但未选分类 → 阻塞「确认导入」。整行 + 分类框暖色高亮（与 probe 行「待处理」同款语言），
   标签挂「请选择」小标 + 「已自动识别」组标题挂「⚠ N 项待选分类」提示。选完分类后重渲自动消失。 */
.rrow--needs-category {
  border-color: #f2dfb3;
  background: #fffaef;
}
.rrow-edit-field--category.is-blocking .dropdown-trigger {
  border-color: var(--warn);
  box-shadow: 0 0 0 1px var(--warn) inset;
}
.rrow-cat-flag {
  margin-left: 4px;
  padding: 0 6px;
  border-radius: 8px;
  background: var(--warn-bg);
  color: var(--warn-deep);
  text-transform: none;
  letter-spacing: 0;
}
.rgroup-blocking-hint {
  color: var(--warn-deep);
  text-transform: none;
  letter-spacing: 0;
}

/* ── review 行内文本输入（probe 行 symbol 输入 + confirmed 行 name 输入） ── */
.review-input {
  height: 30px;
  padding: 0 10px;
  border: 1px solid var(--border-2);
  border-radius: var(--radius-sm);
  background: var(--surface);
  font-family: var(--font-body);
  font-size: var(--fs-sm);
  color: var(--text-1);
  line-height: 28px;
}
.review-input:focus { outline: none; border-color: var(--accent); }
.review-input.mono { font-family: var(--mono); }

/* ── 通用 dropdown 模块（共用：tx-dialog 复核清单 category picker + view-home 持仓详情属性 4 字段） ──
 * 配 js/dropdown.js 的 wireDropdowns / dropdownTemplate 使用。
 * 容器 [data-dropdown] 提供定位上下文（position:relative）；菜单是 trigger 的兄弟节点，
 * 通过 .is-open 显示，通过 .is-flipped 在下方空间不足时翻向上展开（auto-flip up，修 bug1
 * 持仓表最底行 popover 被 .holdings-table-wrap overflow:hidden 切的问题）。
 *
 * Chromium quirk 必须保留（误删会破坏 .is-open 状态）：
 * 1) appearance:none — 否则 <button> UA 默认锁背景色
 * 2) base 必须用 longhand border-* / background-color — 否则 .is-open 跨选择器 longhand override 失效
 * 3) 不加 transition — 多 longhand color + var() 在 transition 下 Chromium 卡死颜色切换 */
[data-dropdown] { position: relative; }

.dropdown-trigger {
  appearance: none;
  -webkit-appearance: none;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  width: 100%;
  height: 30px;
  padding: 0 10px;
  border-style: solid;
  border-width: 1px;
  border-top-color: var(--border-2);
  border-right-color: var(--border-2);
  border-bottom-color: var(--border-2);
  border-left-color: var(--border-2);
  border-radius: var(--radius-sm);
  background-color: var(--surface);
  color: var(--text-1);
  font-family: var(--font-body);
  font-size: var(--fs-sm);
  line-height: 1;
  cursor: pointer;
  user-select: none;
}
.dropdown-trigger:hover {
  border-top-color: var(--text-3);
  border-right-color: var(--text-3);
  border-bottom-color: var(--text-3);
  border-left-color: var(--text-3);
}
.dropdown-trigger.is-open {
  border-top-color: var(--accent);
  border-right-color: var(--accent);
  border-left-color: var(--accent);
  background-color: var(--accent-lt);
  color: var(--accent);
  border-bottom-color: transparent;
  border-bottom-left-radius: 0;
  border-bottom-right-radius: 0;
}
/* is-flipped：菜单贴上方时，trigger 与菜单的连边在顶部 */
.dropdown-trigger.is-open.is-flipped {
  border-top-color: transparent;
  border-bottom-color: var(--accent);
  border-top-left-radius: 0;
  border-top-right-radius: 0;
  border-bottom-left-radius: var(--radius-sm);
  border-bottom-right-radius: var(--radius-sm);
}
.dropdown-trigger-label { flex: 1; text-align: left; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.dropdown-trigger-icon { font-size: var(--fs-2xs); opacity: 0.7; flex-shrink: 0; }

.dropdown-menu {
  position: absolute;
  /* -1px：覆盖 .dropdown-trigger.is-open 的 transparent 底 border，使左右金边视觉连续 */
  top: calc(100% - 1px);
  left: 0;
  right: 0;
  background: var(--surface);
  border: 1px solid var(--accent);
  border-top: 0;
  border-radius: 0 0 var(--radius-sm) var(--radius-sm);
  box-shadow: var(--shadow-md);
  padding: 4px 4px 6px;
  z-index: 50;
  display: none;
  animation: dropdownPopIn 90ms cubic-bezier(0.2, 0.9, 0.3, 1);
  transform-origin: top center;
}
.dropdown-menu.is-open { display: block; }
/* is-flipped：菜单贴在 trigger 上方，圆角/边框/动画方向都翻转 */
.dropdown-menu.is-flipped {
  top: auto;
  bottom: calc(100% - 1px);
  border-top: 1px solid var(--accent);
  border-bottom: 0;
  border-radius: var(--radius-sm) var(--radius-sm) 0 0;
  transform-origin: bottom center;
  animation: dropdownPopInFlipped 90ms cubic-bezier(0.2, 0.9, 0.3, 1);
}
@keyframes dropdownPopIn {
  from { opacity: 0; transform: translateY(-6px); }
  to   { opacity: 1; transform: translateY(0); }
}
@keyframes dropdownPopInFlipped {
  from { opacity: 0; transform: translateY(6px); }
  to   { opacity: 1; transform: translateY(0); }
}

.dropdown-item {
  appearance: none;
  -webkit-appearance: none;
  display: flex;
  align-items: center;
  padding: 6px 10px;
  cursor: pointer;
  border-radius: var(--radius-sm);
  margin: 1px 4px;
  width: calc(100% - 8px);
  border: 0;
  background-color: transparent;
  font-family: var(--font-body);
  text-align: left;
  transition: background-color 80ms var(--ease-standard);
}
.dropdown-item:hover { background-color: var(--bg-warm); }
.dropdown-label { font-size: var(--fs-sm); color: var(--text-2); }

/* manual-cash 行的提示（分类自动写为 cash） */
.rrow-cash-hint {
  font-size: var(--fs-xs);
  color: var(--text-3);
  font-family: var(--font-body);
  font-variant-numeric: tabular-nums;
  margin-top: 8px;
}

/* "已绑定到现有账户/持仓"折叠 row（hiddenCount > 0 时在已自动识别分组底部显示） */
.rrow-hidden { background: var(--surface-tint); }
.rrow-hidden .rrow-symbol {
  font-family: var(--font-body);
  font-size: var(--fs-base);
  color: var(--text-2);
  font-weight: 500;
}
.rrow-hidden .rrow-resolved {
  font-size: var(--fs-xs);
  color: var(--text-3);
  white-space: normal;
}
.rrow-hidden-list {
  display: flex;
  flex-direction: column;
  gap: 4px;
  margin-top: 10px;
  padding-top: 10px;
  border-top: 1px dashed var(--border-1);
}
.rrow-hidden-item {
  display: grid;
  grid-template-columns: 90px 1fr auto;
  gap: 12px;
  align-items: center;
  font-size: var(--fs-xs);
  padding: 4px 4px;
}
.rrow-hidden-date { font-family: var(--font-body); font-variant-numeric: tabular-nums; color: var(--text-3); }
.rrow-hidden-desc {
  color: var(--text-2);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  min-width: 0;
}
.rrow-hidden-amt {
  font-family: var(--font-body);
  font-variant-numeric: tabular-nums;
  color: var(--text-1);
  text-align: right;
  white-space: nowrap;
}

/* ── 持仓 / 余额 panel —— centered 单卡 + assets-table ─────────────── */

/* 持仓 / 余额 panel 满 body 宽 —— 与导入流水 / 数据维护 tab 同宽 */
.centered-pane { width: 100%; }
.list-card { padding: 0; }

/* ── 数据管理弹窗 section / 「最近」卡统一头部：金色小标题 + 下横线 ────── */
.tx-section-head {
  font-family: var(--font-body);
  font-variant-numeric: tabular-nums;
  font-size: var(--fs-2xs);
  letter-spacing: 1.5px;
  text-transform: uppercase;
  color: var(--accent);
  padding-bottom: 8px;
  margin-bottom: 14px;
  border-bottom: 1px solid var(--border-1);
  display: flex;
  justify-content: space-between;
  align-items: center;
}
/* 持仓/余额：list-card 自身 padding:0，头部用 margin 补卡片内边距 —— 横线宽度与上传/补丁卡一致 */
.list-card .tx-section-head { margin: 24px 26px 14px; }
.tx-section-head__count { font-size: var(--fs-2xs); color: var(--text-3); }
.tx-section-actions {
  display: flex;
  justify-content: flex-end;
  gap: var(--space-2);
  flex-wrap: wrap;
  padding: 0 26px 14px;
}

/* API_AUTO 表单 symbol 探活状态 */
.api-auto-symbol-status {
  display: block;
  margin-top: 4px;
  font-size: var(--fs-xs);
  line-height: 1.4;
  min-height: 1em;
  font-family: var(--mono);
}
.api-auto-symbol-status[data-status="probing"] { color: var(--text-3); }
.api-auto-symbol-status[data-status="hit"]     { color: var(--up, #16a34a); }
.api-auto-symbol-status[data-status="miss"]    { color: var(--dn, #b42318); }
.api-auto-symbol-status[data-status="fail"]    { color: var(--warn, #b45309); }
.api-auto-symbol-status[data-status="disambig"]{ color: var(--warn, #b45309); }

.input-error { border-color: var(--dn, #b42318) !important; }
.input-warn  { border-color: var(--warn, #b45309) !important; }

/* API_AUTO 表单 — 探活两路并查后的歧义单选块（≥ 2 命中时显示） */
.api-auto-symbol-disambig {
  display: flex;
  flex-direction: column;
  gap: 6px;
  margin-top: 6px;
}
.api-auto-symbol-disambig[hidden] { display: none; }
.api-auto-disambig-option {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 6px 10px;
  border: 1px solid var(--border, #e5e7eb);
  border-left: 3px solid var(--text-3, #9ca3af);
  border-radius: 4px;
  background: var(--bg-2, #f9fafb);
  cursor: pointer;
  font-size: var(--fs-xs);
  line-height: 1.4;
}
.api-auto-disambig-option:hover { background: var(--bg-3, #f3f4f6); }
.api-auto-disambig-option[data-source="yahoo"] { border-left-color: #2563eb; }
.api-auto-disambig-option[data-source="fund"]  { border-left-color: #d97706; }
.api-auto-disambig-option input[type="radio"] { margin: 0; }
.api-auto-disambig-src {
  font-weight: 600;
  color: var(--text-2, #4b5563);
  min-width: 52px;
}
.api-auto-disambig-name { flex: 1; color: var(--text-1, #111827); }
.api-auto-disambig-price { font-family: var(--mono); color: var(--text-2, #4b5563); }

.note-banner {
  display: flex;
  gap: 10px;
  padding: 10px 14px;
  background: #fef6e4;
  border: 1px solid #f2dfb3;
  border-radius: var(--radius-md);
  font-size: var(--fs-sm);
  color: var(--text-2);
  line-height: 1.55;
  margin-bottom: 18px;
}

/* assets-table —— 持仓 / 余额账户 单层 row 表格 */
/* table-layout:fixed + colgroup：持仓 / 余额两表逐列列宽严格一致（结构已统一为 6 列）。 */
.assets-table { width: 100%; border-collapse: collapse; font-size: var(--fs-base); margin-top: 0; table-layout: fixed; }
/* 列宽按实测内容占比分配：操作列容 4 按钮（更新估值/记录交易/编辑属性/删除）需 ~30%，
   资金属地只显 2 字母国家码 + 表头「资金属地」2 行折行，7% 足够，富余匀给操作列——
   使 >1024px 桌面不再挤重叠。≤1024px 走横滑兜底（见底部 @media），内容总量装不下时
   整表横滑而非压垮列宽。 */
.assets-col--country { width: 7%; }
.assets-col--account { width: 15%; }
.assets-col--name    { width: 20%; }
.assets-col--cat     { width: 14%; }
.assets-col--num     { width: 14%; }
.assets-col--actions { width: 30%; }
.assets-table thead th {
  padding: 10px 14px 8px;
  font-size: var(--fs-2xs);
  letter-spacing: 0.8px;
  text-transform: uppercase;
  color: var(--text-3);
  font-weight: 500;
  text-align: left;
  background: var(--surface-tint);
  border-bottom: 1px solid var(--border-1);
}
.assets-table thead th.num { text-align: right; }
.assets-table thead th.actions-col { text-align: right; padding-right: 26px; }
.assets-table thead th:first-child { padding-left: 26px; }
.assets-table tbody tr.assets-row {
  border-bottom: 1px solid var(--divider);
  transition: background var(--motion-base) var(--ease-standard);
}
.assets-table tbody tr.assets-row:hover { background: var(--surface-tint); }
.assets-table tbody td { padding: 12px 14px; vertical-align: middle; }
.assets-table tbody td:first-child { padding-left: 26px; }
.assets-table tbody td:last-child { padding-right: 26px; }
.assets-row.is-expanded { border-bottom: none; }
.assets-row.is-expanded > td { background: var(--surface-tint); }

.t-name-cell {
  font-size: var(--fs-base);
  font-weight: 500;
  color: var(--text-1);
  display: inline-flex;
  align-items: center;
  gap: 6px;
}
.account-cell { font-size: var(--fs-xs); color: var(--text-2); white-space: nowrap; }
.flag-tag { font-family: var(--mono); font-size: var(--fs-xs); color: var(--text-2); font-weight: 500; white-space: nowrap; }
.num-cell {
  font-family: var(--font-body);
  font-variant-numeric: tabular-nums;
  font-size: var(--fs-base);
  color: var(--text-1);
  text-align: right;
}
.num-cell-ccy { font-size: var(--fs-2xs); color: var(--text-3); margin-left: 4px; }
.type-tag--api { background: var(--chart-blue-bg); color: var(--chart-blue); }

.row-actions { display: flex; gap: 4px; justify-content: flex-end; }
.row-actions .btn-link { font-size: var(--fs-xs); padding: var(--space-1) var(--space-2); white-space: nowrap; }
.btn-link.danger.is-armed,
.btn-link.danger.is-armed:hover { background: var(--dn); color: #fff; }

/* expand-row —— 行内展开编辑 / 新增表单（复用 view-home colspan 模式） */
.assets-table .expand-row { display: none; }
.assets-table .expand-row.is-show { display: table-row; }
.assets-table .expand-row > td {
  padding: 0;
  background: var(--surface-tint);
  border-bottom: 1px solid var(--divider);
}
.assets-row__expand {
  padding: 16px 26px 18px;
  animation: fadeIn var(--motion-base) ease both;
}

.assets-table__empty-row > td {
  padding: 28px 26px;
  text-align: center;
  color: var(--text-3);
  font-size: var(--fs-sm);
}

.asset-form { display: flex; flex-direction: column; gap: 12px; }
.asset-form__title {
  font-size: var(--fs-sm);
  font-weight: 500;
  color: var(--text-2);
  font-family: var(--font-body);
  font-variant-numeric: tabular-nums;
  text-transform: uppercase;
  letter-spacing: 0.3px;
}
.asset-form__grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 10px 14px;
}
.asset-form__field { display: flex; flex-direction: column; gap: 4px; min-width: 0; }
.asset-form__field--full { grid-column: 1 / -1; }
.asset-form__field--hidden { display: none; }
.asset-form-error-banner {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  padding: 10px 12px;
  background: var(--dn-bg);
  color: var(--dn);
  border: 1px solid var(--dn);
  border-radius: var(--radius-sm);
  font-size: var(--fs-xs);
  line-height: 1.45;
}
.asset-form-error-banner__icon {
  display: inline-grid;
  place-items: center;
  width: 18px;
  height: 18px;
  border-radius: 50%;
  border: 1px solid currentColor;
  font-family: var(--mono);
  font-size: 12px;
  line-height: 1;
  flex: 0 0 auto;
}
.asset-form-error-banner__text { flex: 1; word-break: break-word; }

.form-label-sm {
  display: block;
  font-size: var(--fs-2xs);
  color: var(--text-3);
  letter-spacing: 0.3px;
  text-transform: uppercase;
  font-family: var(--mono);
}
.form-input-sm {
  padding: 7px 10px;
  border: 1px solid var(--border-2);
  border-radius: var(--radius-sm);
  background: var(--surface);
  font-family: var(--mono);
  font-size: var(--fs-sm);
  color: var(--text-1);
  width: 100%;
}
textarea.form-input-sm {
  font-family: var(--font-body);
  resize: vertical;
  min-height: 56px;
}
.form-input-sm:focus { outline: none; border-color: var(--accent); }

/* 2026-05-04 API_AUTO edit form「持仓量/成本由流水反算」hint 文案样式。
   语义灰色提示文字，与 .form-input-sm 同 padding 但无边框。 */
.form-hint-text {
  padding: 7px 10px;
  font-size: var(--fs-sm);
  color: var(--text-3);
  font-style: italic;
}

/* D4 smart-date input 状态（mockup L2758-L2759；Variant B 红框 + 红字 / 绿框 + 绿字）。
   位置在 .form-input-sm 之后以胜出 selector specificity tie-break。 */
.smart-date-input.parsed  { color: var(--up); border-color: var(--up); }
.smart-date-input.invalid { color: var(--dn); border-color: var(--dn); }

.asset-form__actions { display: flex; gap: 8px; justify-content: flex-end; }

/* ── clearDialog overlay（mockup L4894–L4910） ─────────────────────── */

.dialog-overlay {
  position: fixed;
  top: 0; left: 0; right: 0; bottom: 0;
  background: rgba(26, 26, 24, 0.4);
  backdrop-filter: blur(2px);
  display: none;
  align-items: center;
  justify-content: center;
  z-index: 100;
  animation: fadeIn var(--motion-fast) ease both;
}
.dialog-overlay.show { display: flex; }

.dialog-card {
  background: var(--surface);
  border-radius: var(--radius-lg);
  box-shadow: 0 20px 60px rgba(0, 0, 0, 0.2);
  padding: 26px 28px;
  width: 460px;
  max-width: calc(100vw - 40px);
  animation: dialogIn var(--motion-base) ease both;
}
@keyframes dialogIn {
  from { transform: translateY(8px) scale(0.98); opacity: 0; }
  to { transform: translateY(0) scale(1); opacity: 1; }
}

.dialog-icon-wrap {
  width: 44px; height: 44px;
  border-radius: var(--radius-lg);
  background: var(--dn-bg);
  color: var(--dn);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 20px;
  font-weight: 700;
  margin-bottom: 14px;
}
.dialog-title {
  font-family: var(--font-body);
  font-size: var(--fs-lg);
  font-weight: 600;
  line-height: 1.3;
  letter-spacing: 0.005em;
  margin-bottom: 8px;
  color: var(--text-2);
}
.dialog-body {
  font-size: var(--fs-base);
  color: var(--text-2);
  line-height: 1.6;
  margin-bottom: 18px;
}
.dialog-body strong { color: var(--text-1); font-weight: 500; }
.dialog-confirm-input {
  width: 100%;
  padding: 9px 12px;
  border: 1px solid var(--border-2);
  border-radius: var(--radius-md);
  font-family: var(--mono);
  font-size: var(--fs-base);
  margin-top: 8px;
}
.dialog-confirm-input:focus { outline: none; border-color: var(--dn); }
.dialog-actions {
  display: flex;
  gap: 8px;
  justify-content: flex-end;
  margin-top: 18px;
}

/* ── 窄屏 ───────────────────────────────────────────────────────────── */

@media (max-width: 900px) {
  .upload-grid { grid-template-columns: 1fr; }
  .ocr-card__fields { grid-template-columns: 1fr; }
  .asset-form__grid { grid-template-columns: repeat(2, 1fr); }
}

/* 浮层内 6 列表格横滑兜底（持仓资产 / 余额账户 tab）。
 * 桌面 >1024px：table-layout:fixed 按列宽比例铺满（见 .assets-col--*），实测内容装得下不挤。
 * ≤1024px：6 列内容总量 > 可用表宽，固定比例会把列压到文字重叠 → 改 table-layout:auto
 * 按内容定宽 + .list-card 横滑兜底（与首页持仓表 .holdings-table-wrap 同款手感）。
 * 断点取 1024px：实测重排列宽后正好在此宽度临界清零，再窄即重叠。*/
@media (max-width: 1024px) {
  .list-card { overflow-x: auto; }
  .assets-table { table-layout: auto; width: auto; min-width: 100%; }
  .assets-table thead th,
  .assets-table tr.assets-row td { white-space: nowrap; }
}

@media (max-width: 600px) {
  .onboarding-welcome-card {
    align-items: stretch;
    flex-direction: column;
    gap: var(--space-4);
    padding: 20px;
  }
  .onboarding-welcome-title {
    font-size: var(--fs-xl);
  }
  .onboarding-welcome-text {
    font-size: var(--fs-base);
  }
  .onboarding-welcome-actions {
    flex-direction: column;
  }
  .onboarding-welcome-actions .btn {
    width: 100%;
  }

  .tx-dialog-bar { padding: 14px 16px 12px; }
  .tx-dialog-body { padding: 14px 16px 18px; }
  .asset-form__grid { grid-template-columns: 1fr; }
  /* 窄屏：数据维护 tab 双栏塌缩单栏，拖拽区恢复正常宽度 */
  .patch-grid { grid-template-columns: 1fr; }
  /* 窄屏：tab 行折行后右侧不再有空白，「这是做什么的?」帮助入口从绝对定位
     改回正常流，落到 tab 行下方、patch-grid 上方，避免压在最右 tab 上 */
  .patch-topbar { position: static; text-align: right; margin-bottom: 6px; }
}

/* ── 触屏设备 input 16px 兜底 ───────────────────────────────────────────
 * iOS Safari 在 input/textarea/select 字号 < 16px 时聚焦会自动放大整页，
 * 体验破坏性。pointer: coarse 精确命中触屏（iPhone/iPad），不波及鼠标桌面。
 * 视觉零变化：桌面 input 仍是 13px（.form-input-sm 等），仅手机触屏放大到 16px。
 */
@media (pointer: coarse) {
  input:not([type="checkbox"]):not([type="radio"]):not([type="range"]):not([type="color"]),
  select,
  textarea {
    font-size: 16px;
  }
}

/* ─── §产品化 P1 D-ε · 顶部 user chip + 改密码 dialog ─────────────────────
 * chip 形态：状态栏（双灯泡）右侧；视觉与 .db-menu 同源（白底 dropdown）。
 * 仅登录态显示（mountUserMenu 在 bootstrap 成功后才挂；未登录跳 login.html）。
 */
.user-chip-host {
  position: relative;
  display: inline-flex;
  align-items: center;
  flex-shrink: 0;
}

.user-chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 4px 8px;
  border: 1px solid transparent;
  border-radius: var(--radius-sm);
  background: transparent;
  cursor: pointer;
  font-family: var(--font-body);
  font-size: var(--fs-xs);
  color: var(--text-2);
  max-width: 220px;
  transition: background var(--motion-fast) var(--ease-standard),
              border-color var(--motion-fast) var(--ease-standard);
}
.user-chip:hover,
.user-chip[aria-expanded="true"] { background: var(--bg-warm); border-color: var(--border-1); }

.user-chip__email {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  max-width: 180px;
}
.user-chip__caret {
  font-size: 10px;
  color: var(--text-3);
  flex-shrink: 0;
}

.user-menu-popover {
  position: absolute;
  top: calc(100% + 6px);
  right: 0;
  z-index: 60;
  background: var(--surface);
  border: 1px solid var(--border-1);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-md);
  padding: 5px;
  min-width: 160px;
  display: flex;
  flex-direction: column;
  animation: fadeIn var(--motion-fast) ease both;
}
.user-menu-popover[hidden] { display: none; }

.user-menu-item {
  display: block;
  width: 100%;
  padding: 8px 12px;
  border: 0;
  border-radius: var(--radius-sm);
  background: transparent;
  text-align: left;
  font-family: var(--font-body);
  font-size: var(--fs-base);
  color: var(--text-1);
  cursor: pointer;
  transition: background var(--motion-fast) var(--ease-standard);
  text-decoration: none;
  box-sizing: border-box;
}
.user-menu-item:hover { background: var(--bg-warm); }
.user-menu-item--danger { color: var(--dn); }
.user-menu-item--danger:hover { background: var(--dn-bg); }

/* 窄屏：chip 邮箱长度压缩避免挤压 tab */
@media (max-width: 600px) {
  .user-chip__email { max-width: 96px; }
}

/* ── 改密码 dialog（与 .confirm-dialog 容器骨架共用）─────────────────── */
.cp-dialog-shell { min-width: 380px; max-width: 460px; }

.cp-row { display: flex; flex-direction: column; gap: 4px; margin-bottom: 12px; }
.cp-row:last-of-type { margin-bottom: 4px; }

.cp-label {
  font-size: var(--fs-xs);
  color: var(--text-2);
  font-weight: 500;
}

.cp-input {
  width: 100%;
  padding: 8px 10px;
  border: 1px solid var(--border-1);
  border-radius: var(--radius-sm);
  font-size: var(--fs-base);
  font-family: var(--font-body);
  color: var(--text-1);
  background: var(--surface);
  box-sizing: border-box;
  outline: none;
  transition: border-color var(--motion-fast) var(--ease-standard);
}
.cp-input:focus { border-color: #1f6feb; }
.cp-input:disabled { background: var(--surface-2); color: var(--text-3); }

.cp-error,
.cp-halfwrite {
  margin-top: 8px;
  padding: 8px 10px;
  border-radius: var(--radius-sm);
  font-size: var(--fs-xs);
  line-height: 1.5;
  white-space: pre-line;
}
.cp-error {
  background: #fef2f2;
  border: 1px solid #fecaca;
  color: #b91c1c;
}
.cp-halfwrite {
  background: #fef9c3;
  border: 1px solid #fde68a;
  color: #92400e;
}
.cp-error[hidden],
.cp-halfwrite[hidden] { display: none; }

/* ── 改邮箱 dialog（P1.5；与 .confirm-dialog 容器骨架共用，沿用 .cp-* 视觉）──── */
.ce-dialog-shell { min-width: 380px; max-width: 480px; }

.ce-row { display: flex; flex-direction: column; gap: 4px; margin-bottom: 12px; }
.ce-row:last-of-type { margin-bottom: 4px; }

.ce-label { font-size: var(--fs-xs); color: var(--text-2); font-weight: 500; }

.ce-input {
  width: 100%;
  padding: 8px 10px;
  border: 1px solid var(--border-1);
  border-radius: var(--radius-sm);
  font-size: var(--fs-base);
  font-family: var(--font-body);
  color: var(--text-1);
  background: var(--surface);
  box-sizing: border-box;
  outline: none;
  transition: border-color var(--motion-fast) var(--ease-standard);
}
.ce-input:focus { border-color: #1f6feb; }
.ce-input:disabled { background: var(--surface-2); color: var(--text-3); }

.ce-hint {
  font-size: var(--fs-xs);
  color: var(--text-2);
  line-height: 1.6;
  margin: 0 0 14px;
}

.ce-error, .ce-status {
  margin-top: 8px;
  padding: 8px 10px;
  border-radius: var(--radius-sm);
  font-size: var(--fs-xs);
  line-height: 1.5;
  white-space: pre-line;
}
.ce-error { background: #fef2f2; border: 1px solid #fecaca; color: #b91c1c; }
.ce-status { background: #ddf4ff; border: 1px solid #b6e3ff; color: #0a3069; }
.ce-error[hidden], .ce-status[hidden] { display: none; }

.ce-resend {
  margin-top: 4px;
  align-self: flex-start;
  font-size: var(--fs-xs);
}
.ce-resend:disabled { opacity: 0.55; cursor: default; }

/* 恢复码展示（dialog 内，作用域 .ce-dialog，不影响 login.html 内联同名类）*/
.ce-dialog .auth-recovery {
  display: flex; align-items: center; gap: 8px;
  background: var(--surface-2); border: 1px solid var(--border-1); border-radius: var(--radius-sm);
  padding: 12px; margin: 12px 0;
}
.ce-dialog .auth-recovery__code {
  flex: 1; font-family: var(--font-mono, "SF Mono", "Menlo", "Consolas", monospace);
  font-size: 15px; letter-spacing: 0.04em; color: var(--text-1); word-break: break-all;
}
.ce-check {
  display: flex; align-items: center; gap: 8px;
  font-size: var(--fs-xs); color: var(--text-1);
  margin: 14px 0 4px;
}
.ce-check input[type="checkbox"] { width: 16px; height: 16px; }

/* ── 拆股确认浮层（ADR 0140 / phase 5；与 .confirm-dialog 容器骨架共用）──────
   js/pending-splits-dialog.js 注入；「拿不准」拆股一个滚动列表逐条确认补前/补后。 */
.ps-dialog-shell { min-width: 480px; max-width: 620px; padding: 22px 24px; }
.ps-intro {
  font-size: var(--fs-xs); line-height: 1.6; color: var(--text-2);
  margin: 0 0 14px;
}
.ps-list {
  list-style: none; margin: 0 0 4px; padding: 0;
  display: flex; flex-direction: column; gap: 12px;
  max-height: 56vh; overflow-y: auto;
}
.ps-item {
  border: 1px solid var(--border-1); border-radius: var(--radius-md);
  padding: 12px 14px; background: var(--surface-2);
}
.ps-item__head {
  display: flex; align-items: baseline; gap: 8px; margin-bottom: 4px;
}
.ps-item__name { font-weight: 650; font-size: 14px; color: var(--text-1); }
.ps-item__sym {
  font-family: var(--font-mono, "SF Mono", "Menlo", "Consolas", monospace);
  font-size: 12px; color: var(--text-3);
}
.ps-item__ratio {
  margin-left: auto; font-size: 12px; font-weight: 600; color: var(--text-2);
  background: var(--surface); border: 1px solid var(--border-1);
  border-radius: var(--radius-sm); padding: 1px 8px;
}
.ps-item__reason { font-size: var(--fs-xs); color: var(--text-3); margin: 0 0 10px; }
.ps-compare {
  width: 100%; border-collapse: collapse; font-size: 13px;
  font-variant-numeric: tabular-nums; margin-bottom: 4px;
}
.ps-compare th, .ps-compare td {
  text-align: right; padding: 3px 6px; border-bottom: 1px solid var(--border-1);
}
.ps-compare thead th { color: var(--text-3); font-weight: 500; font-size: 12px; }
.ps-compare tbody th[scope="row"] { text-align: left; color: var(--text-2); font-weight: 500; }
.ps-compare tbody td:last-child { color: var(--text-1); font-weight: 600; } /* 补后列加重 */
.ps-reverse-hint {
  font-size: var(--fs-xs); color: var(--text-2);
  background: var(--surface); border-left: 2px solid var(--border-2, var(--border-1));
  padding: 6px 10px; margin: 8px 0 0; border-radius: var(--radius-sm);
}
.ps-item__err {
  font-size: var(--fs-xs); color: var(--dn); margin-top: 8px;
}
.ps-item__actions {
  display: flex; gap: 8px; justify-content: flex-end; margin-top: 10px;
}

/* ============================================================================
 * 管理员遥测后台（view-admin · Phase 2 / ADR 0130）
 * 复用现有 design token；仅管理员账号动态挂载，普通账号无此视图。详见 UI_SPEC §2.13。
 * ========================================================================== */
.admin-dash { display: flex; flex-direction: column; gap: 16px; }
.admin-dash__head {
  display: flex; align-items: baseline; justify-content: space-between; gap: 12px;
}
.admin-dash__title { font-size: 18px; font-weight: 650; color: var(--text-1); margin: 0; }
.admin-dash__head-actions { display: flex; align-items: center; gap: 10px; }
.admin-dash__range { font-size: 12px; color: var(--text-3); }

.admin-dash__card {
  background: var(--surface);
  border: 1px solid var(--border-1);
  border-radius: var(--radius-md);
  padding: 14px 16px;
}
.admin-dash__h2 {
  font-size: 13px; font-weight: 650; color: var(--text-2); margin: 0 0 10px;
  display: flex; align-items: baseline; gap: 8px;
}
.admin-dash__count { font-size: 12px; font-weight: 400; color: var(--text-3); }
/* 卡内子块标题（导入纠错诊断 ①②③ 三块 / ADR 0152）：比卡标题 h2 略轻、上方留间隔分隔块。 */
.admin-dash__h3 {
  font-size: 12px; font-weight: 600; color: var(--text-2); margin: 14px 0 6px;
  display: flex; align-items: baseline; gap: 8px;
}
.admin-dash__h3:first-of-type { margin-top: 6px; }
.admin-dash__empty, .admin-dash__loading, .admin-dash__note {
  font-size: 13px; color: var(--text-3); padding: 6px 0;
}

/* 业务粗粒度档：日/周/月 周期切换 + 假名化提示（Phase 4） */
.admin-dash__seg-group { display: inline-flex; gap: 2px; margin-bottom: 8px; }
.admin-dash__seg {
  font-size: 12px; padding: 3px 12px; cursor: pointer;
  color: var(--text-2); background: var(--surface-2);
  border: 1px solid var(--border-1); border-left-width: 0;
}
.admin-dash__seg:first-child { border-left-width: 1px; border-radius: var(--radius-sm) 0 0 var(--radius-sm); }
.admin-dash__seg:last-child { border-radius: 0 var(--radius-sm) var(--radius-sm) 0; }
.admin-dash__seg.is-active { color: #fff; background: var(--accent); border-color: var(--accent); }
.admin-dash__hint { font-size: 11px; color: var(--text-3); line-height: 1.5; margin-bottom: 8px; }
.admin-dash__error {
  font-size: 13px; color: var(--warn-deep);
  background: var(--warn-bg);
  border: 1px solid color-mix(in srgb, var(--warn) 40%, transparent);
  border-radius: var(--radius-md); padding: 8px 12px;
}

/* 数据完整性 banner */
.admin-dash__health {
  border-radius: var(--radius-md); padding: 10px 14px; font-size: 13px;
}
.admin-dash__health--ok {
  background: var(--surface-2); border: 1px solid var(--border-1); color: var(--text-3);
}
.admin-dash__health--warn {
  background: var(--warn-bg);
  border: 1px solid color-mix(in srgb, var(--warn) 45%, transparent);
  color: var(--warn-deep);
}
.admin-dash__health-list { margin: 6px 0 4px; padding-left: 18px; }
.admin-dash__health-list li { margin: 2px 0; }
.admin-dash__health-meta { font-size: 11px; color: var(--text-3); margin-top: 4px; }

/* 表格 */
.admin-dash__table { width: 100%; border-collapse: collapse; font-size: 13px; }
.admin-dash__table th {
  text-align: left; font-weight: 600; color: var(--text-3); font-size: 11px;
  text-transform: uppercase; letter-spacing: 0.03em;
  padding: 6px 8px; border-bottom: 1px solid var(--border-1);
}
.admin-dash__table td {
  padding: 6px 8px; border-bottom: 1px solid var(--border-1);
  color: var(--text-2); font-variant-numeric: tabular-nums; vertical-align: top;
}
.admin-dash__table tr:last-child td { border-bottom: none; }
.admin-dash__num { text-align: right; font-variant-numeric: tabular-nums; }
.admin-dash__mono { font-family: var(--mono); font-size: 12px; }
.admin-dash__props { color: var(--text-3); word-break: break-all; max-width: 360px; }

/* 按天分布条 */
.admin-dash__bars { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 4px; }
.admin-dash__bar-row { display: grid; grid-template-columns: 96px 1fr 56px; align-items: center; gap: 10px; font-size: 12px; }
.admin-dash__bar-day { color: var(--text-3); font-variant-numeric: tabular-nums; }
.admin-dash__bar-track { background: var(--surface-2); border-radius: 4px; height: 10px; overflow: hidden; }
.admin-dash__bar-fill { display: block; height: 100%; background: var(--accent); border-radius: 4px; }
.admin-dash__bar-n { text-align: right; color: var(--text-2); font-variant-numeric: tabular-nums; }
/* 截图导入漏斗（ADR 0132）：右列要显「计数 · 留存%」两段，比按天分布的单数字宽，故加宽数字列防 3 位数折行。 */
.admin-dash__bars--funnel .admin-dash__bar-row { grid-template-columns: 96px 1fr 88px; }

/* 下钻输入 */
.admin-dash__drill-form { display: flex; gap: 8px; margin-bottom: 10px; }
.admin-dash__input {
  flex: 1; min-width: 0; padding: 6px 10px; font-size: 13px;
  font-family: var(--mono);
  border: 1px solid var(--border-1); border-radius: var(--radius-md);
  background: var(--surface); color: var(--text-1);
}
.admin-dash__input:focus { outline: none; border-color: var(--accent); }

@media (max-width: 600px) {
  .admin-dash__bar-row { grid-template-columns: 76px 1fr 44px; }
  .admin-dash__bars--funnel .admin-dash__bar-row { grid-template-columns: 76px 1fr 76px; }
  .admin-dash__props { max-width: 160px; }
}

/* ═══ Phase 2C：通用导入「确认映射」统一确认界面（.cm-*） ═══ */
.cm-panel { padding: var(--card-padding-lg); }
.cm-loaded {
  display: flex; align-items: center; gap: 12px;
  padding: 12px 16px; margin: 4px 0 14px;
  border: 1px solid var(--border-1); border-radius: var(--radius-md); background: var(--surface-2);
}
.cm-loaded-icon {
  width: 30px; height: 30px; flex-shrink: 0; border-radius: var(--radius-sm);
  background: var(--accent-lt); color: var(--accent-deep);
  display: flex; align-items: center; justify-content: center;
}
.cm-loaded-info { flex: 1; min-width: 0; }
.cm-loaded-name {
  font-family: var(--mono); font-size: var(--fs-sm); font-weight: 500; color: var(--text-1);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.cm-loaded-meta { font-family: var(--mono); font-size: var(--fs-2xs); color: var(--text-3); margin-top: 2px; }
.cm-intro { font-size: var(--fs-xs); color: var(--text-3); margin: 0 0 12px; }
.cm-intro b { color: var(--text-2); font-weight: 500; }

.cm-sec {
  border: 1px solid var(--border-1); border-radius: var(--radius-md);
  background: var(--surface); margin-top: 12px; overflow: hidden;
}
.cm-sec.cm-flag-warn { border-color: #eccd92; }
.cm-sec.cm-flag-bad { border-color: #e6a8b1; }
.cm-sec-head {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  padding: 10px 14px; background: var(--surface-2); border-bottom: 1px solid var(--border-1);
}
.cm-num {
  width: 20px; height: 20px; flex-shrink: 0; border-radius: 50%;
  background: var(--text-1); color: var(--surface);
  font-family: var(--mono); font-size: var(--fs-2xs); font-weight: 500;
  display: flex; align-items: center; justify-content: center;
}
.cm-sec-title { font-size: var(--fs-sm); font-weight: 500; color: var(--text-1); }
.cm-spacer { flex: 1; }
.cm-sec-body { padding: 12px 14px; }
.cm-note { font-size: var(--fs-xs); color: var(--text-3); margin: 8px 0 0; }
.cm-hint { font-size: var(--fs-xs); color: var(--text-3); }
.cm-mono { font-family: var(--mono); font-size: var(--fs-xs); color: var(--text-3); }

.cm-lamp {
  display: inline-flex; align-items: center; gap: 5px;
  font-size: var(--fs-xs); padding: 2px 8px 2px 7px; border-radius: var(--radius-pill);
  white-space: nowrap; border: 1px solid transparent;
}
.cm-lamp::before { content: ''; width: 7px; height: 7px; border-radius: 50%; flex-shrink: 0; }
.cm-lamp--ok { background: var(--up-bg); color: var(--up); border-color: #cfe7d8; }
.cm-lamp--ok::before { background: var(--up); }
.cm-lamp--warn { background: var(--warn-bg); color: var(--warn-deep); border-color: #f0dcb0; }
.cm-lamp--warn::before { background: var(--warn); }
.cm-lamp--bad { background: var(--dn-bg); color: var(--dn); border-color: #efc9cf; }
.cm-lamp--bad::before { background: var(--dn); }
.cm-lamp--mute { background: var(--bg-warm); color: var(--text-mute); border-color: var(--border-1); }
.cm-lamp--mute::before { background: var(--text-mute); }

.cm-field-row { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.cm-field-row + .cm-field-row { margin-top: 9px; }
.cm-k {
  font-family: var(--mono); font-size: var(--fs-2xs); color: var(--text-3);
  text-transform: uppercase; letter-spacing: 0.3px; min-width: 56px;
}
.cm-k--inline { min-width: auto; }
.cm-ctl {
  padding: 5px 8px; border: 1px solid var(--border-2); border-radius: var(--radius-sm);
  background: var(--surface); font-family: var(--font-body); font-size: var(--fs-sm); color: var(--text-1);
  max-width: 100%;
}
.cm-ctl--wide { min-width: 240px; flex: 1; }
.cm-ctl:focus { outline: 2px solid var(--accent-lt); border-color: var(--accent); }

.cm-map { width: 100%; border-collapse: collapse; font-size: var(--fs-sm); }
.cm-map th {
  text-align: left; font-size: var(--fs-2xs); color: var(--text-3);
  text-transform: uppercase; letter-spacing: 0.3px; font-weight: 500;
  padding: 4px 8px; border-bottom: 1px solid var(--border-1);
}
.cm-map td { padding: 7px 8px; border-bottom: 1px solid var(--divider); vertical-align: middle; }
.cm-map tr:last-child td { border-bottom: 0; }
.cm-col-src { font-family: var(--mono); color: var(--text-1); }
.cm-col-sample { font-family: var(--mono); font-size: var(--fs-xs); color: var(--text-3); word-break: break-all; }
.cm-lock {
  font-size: var(--fs-2xs); color: var(--accent-deep); background: var(--accent-lt);
  border-radius: var(--radius-xs); padding: 1px 5px; margin-left: 6px;
}

.cm-callout {
  background: var(--warn-bg); border: 1px solid #f0dcb0; border-radius: var(--radius-sm);
  padding: 8px 11px; color: var(--warn-deep); font-size: var(--fs-xs); margin: 0 0 9px;
}
.cm-meaning { display: flex; gap: 10px; flex-wrap: wrap; }
.cm-radio {
  flex: 1; min-width: 220px; display: flex; gap: 9px; align-items: flex-start;
  padding: 10px 12px; border: 1px solid var(--border-2); border-radius: var(--radius-md);
  cursor: pointer; background: var(--surface);
}
.cm-radio:hover { border-color: var(--text-3); }
.cm-radio:has(input:checked) { border-color: var(--accent); background: var(--surface-tint); box-shadow: 0 0 0 1px var(--accent-lt); }
.cm-radio span { font-size: var(--fs-sm); color: var(--text-2); }
.cm-radio b { display: block; color: var(--text-1); font-weight: 500; margin-bottom: 2px; }
.cm-radio small { color: var(--text-3); font-size: var(--fs-xs); }
/* 对账控件「写入余额校正」开关（Phase 4E [D4]）：复用 cm-radio 形态，整行铺满 + 与上方下拉留距 */
.cm-recon-adjust { margin-top: 9px; flex: 1 1 100%; }

.cm-unclassified {
  margin-top: 9px; padding: 10px 12px; border: 1px solid #f0dcb0;
  background: var(--warn-bg); border-radius: var(--radius-sm); font-size: var(--fs-xs); color: var(--warn-deep);
}
.cm-unclassified.cm-resolved { border-color: #cfe7d8; background: var(--up-bg); }
/* 行级 AI 重做：本地已确定的行模式折叠成一行汇总 */
.cm-uc-determined { margin-bottom: 8px; color: var(--up); font-size: var(--fs-xs); }
/* 行级 AI 重做：未确定「行模式」逐组选类型（每组一行：样本 + 命中行数 + 下拉 + AI 建议） */
.cm-uc-rows { margin: 6px 0 4px; display: flex; flex-direction: column; gap: 8px; }
.cm-uc-row {
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
  padding: 7px 9px; background: var(--surface); border: 1px solid var(--border-1); border-radius: var(--radius-sm);
}
.cm-uc-pat { flex: 1 1 240px; min-width: 0; color: var(--text-2); font-size: var(--fs-xs); line-height: 1.55; }
.cm-uc-pat code {
  font-family: var(--mono); font-size: var(--fs-xs); padding: 1px 6px;
  background: var(--bg-warm); border: 1px solid var(--border-1); border-radius: 3px; color: var(--text-2);
}
.cm-uc-count { color: var(--text-3); font-size: var(--fs-2xs); white-space: nowrap; }
.cm-uc-sym {
  font-size: var(--fs-2xs); padding: 0 5px; border-radius: var(--radius-xs);
  border: 1px solid var(--border-1); color: var(--text-3);
}
.cm-uc-row .cm-ctl { flex: 0 1 200px; min-width: 140px; }
.cm-ok-note { color: var(--up); }
.cm-ai-slot {
  margin-top: 10px; padding: 8px 12px; border: 1px dashed var(--border-2); border-radius: var(--radius-md);
  background: var(--surface-tint); font-size: var(--fs-xs); color: var(--text-3);
  display: flex; align-items: center; gap: 8px;
}
.cm-ai-tag {
  font-family: var(--mono); font-size: var(--fs-2xs); text-transform: uppercase; letter-spacing: 0.3px;
  color: var(--text-mute); border: 1px solid var(--border-1); border-radius: var(--radius-xs); padding: 1px 5px; flex-shrink: 0;
}
.cm-btn-ack {
  font-size: var(--fs-xs); padding: 4px 10px; border-radius: var(--radius-sm);
  border: 1px solid var(--border-2); background: var(--surface); color: var(--text-2);
  cursor: pointer; font-family: var(--font-body);
}
.cm-btn-ack:hover { border-color: var(--text-3); background: var(--bg-warm); }
/* Phase 3D：AI 建议小提示（列角色下方 / 动作词行内）。恒黄、仅提示 + 一键采用。 */
.cm-ai-hint {
  display: inline-flex; align-items: center; gap: 6px; flex-wrap: wrap;
  margin-top: 4px; font-size: var(--fs-2xs); color: var(--text-3);
}
.cm-ai-hint .cm-btn-ack { padding: 2px 8px; font-size: var(--fs-2xs); }

.cm-summary {
  display: flex; gap: 22px; padding: 12px 16px; margin-top: 14px;
  background: var(--bg-warm); border: 1px solid var(--border-1); border-radius: var(--radius-md);
}
.cm-ss { display: flex; flex-direction: column; gap: 2px; }
.cm-ss-k { font-size: var(--fs-2xs); color: var(--text-3); letter-spacing: 0.3px; }
.cm-ss-v { font-family: var(--mono); font-size: var(--fs-md); color: var(--text-1); font-weight: 500; }
.cm-ss-v.cm-ok { color: var(--up); }
.cm-ss-v.cm-warn { color: var(--warn-deep); }

.cm-blocker {
  margin-top: 12px; padding: 11px 15px; border-radius: var(--radius-md);
  display: flex; align-items: flex-start; gap: 9px; font-size: var(--fs-sm);
}
.cm-blocker--bad { background: var(--dn-bg); border: 1px solid #efc9cf; color: var(--dn); }
.cm-blocker--ok { background: var(--up-bg); border: 1px solid #cfe7d8; color: var(--up); }
.cm-blocker ul { margin: 4px 0 0; padding-left: 4px; list-style: none; }
.cm-blocker li { margin-top: 2px; }
.cm-blocker li::before { content: '· '; opacity: 0.7; }

.cm-actions {
  display: flex; justify-content: flex-end; align-items: center; gap: 10px;
  margin-top: 16px; padding-top: 14px; border-top: 1px solid var(--border-1);
}
.cm-actions-hint { margin-right: auto; font-size: var(--fs-xs); color: var(--text-3); }

/* ───────────────────────────────────────────────────────────────────────────
 * onboarding-wizard 向导骨架（ADR 0157 · js/onboarding-wizard.js 注入）
 * 强制配置向导：三步、无关闭按钮。容器 border:0 / ::backdrop 见上面 §dialog 骨架。
 * ─────────────────────────────────────────────────────────────────────────── */
.ow-shell {
  width: min(560px, 90vw);
  box-sizing: border-box;
  background: var(--surface);
  border-radius: var(--radius-lg);
  padding: 28px 28px 22px;
  box-shadow: var(--shadow-lg, 0 12px 40px rgba(0, 0, 0, 0.18));
  display: flex;
  flex-direction: column;
  gap: 18px;
}
.ow-progress {
  display: flex; align-items: center; justify-content: space-between;
}
.ow-step-count { font-size: var(--fs-xs); color: var(--text-3); letter-spacing: 0.02em; }
.ow-dots { display: inline-flex; gap: 6px; }
.ow-dot {
  width: 8px; height: 8px; border-radius: var(--radius-pill);
  background: var(--border-2); transition: background var(--motion-fast) var(--ease-standard);
}
.ow-dot.is-done { background: var(--accent-lt); }
.ow-dot.is-active { background: var(--accent); }

.ow-title { font-size: var(--fs-xl, 20px); font-weight: 650; color: var(--text-1); margin: 0; }
.ow-lead { font-size: var(--fs-sm); color: var(--text-2); line-height: 1.5; margin: 6px 0 0; }
.ow-content { display: flex; flex-direction: column; gap: 16px; }

.ow-group { display: flex; flex-direction: column; gap: 8px; }
.ow-group__label { font-size: var(--fs-xs); font-weight: 600; color: var(--text-3); }

.ow-choices { display: grid; gap: 10px; }
.ow-choices--2 { grid-template-columns: 1fr 1fr; }
.ow-choices--3 { grid-template-columns: 1fr 1fr 1fr; }

.ow-choice {
  display: flex; flex-direction: column; gap: 4px; text-align: left;
  padding: 12px 14px; border: 1.5px solid var(--border-2); border-radius: var(--radius-md);
  background: var(--surface); color: var(--text-1); cursor: pointer;
  font-family: var(--font-body);
  transition: border-color var(--motion-fast) var(--ease-standard),
              background var(--motion-fast) var(--ease-standard);
}
.ow-choice:hover { border-color: var(--text-3); background: var(--surface-2); }
.ow-choice.is-selected { border-color: var(--accent); background: var(--accent-lt); }
.ow-choice__title { font-size: var(--fs-sm); font-weight: 600; }
.ow-choice__sub { font-size: var(--fs-xs); color: var(--text-3); line-height: 1.4; }
.ow-choice__detail { font-size: var(--fs-xs); color: var(--text-2); font-variant-numeric: tabular-nums; }

.ow-error {
  font-size: var(--fs-xs); color: var(--dn); background: var(--dn-bg);
  border: 1px solid var(--dn); border-radius: var(--radius-sm); padding: 8px 12px; line-height: 1.45;
}
.ow-actions { display: flex; align-items: center; justify-content: space-between; gap: 12px; }

@media (max-width: 560px) {
  .ow-choices--2, .ow-choices--3 { grid-template-columns: 1fr; }
}
