/* 智造ERP 自定义样式 */

/* ============================================================
   主题变量体系
   - 所有颜色通过 CSS 变量控制，由 <html data-theme="..."> 切换
   - data-bs-theme="dark" 由 Bootstrap 5.3 处理组件深色化
   - 各主题见下方 [data-theme="..."] 规则
   ============================================================ */
/* ★★ 2026-10-04 深色主题统一覆盖：表格分组色 / 行悬停 / 选中行 / 边框。
   为什么要统一规则而不是逐个主题块：深色主题有 8 个（dark-blue/green/purple、
   tech-neon/carbon、3d-aurora/titanium/crystal…），逐块写必漏、且以后新增主题又漏。
   ★ base.html 已用 `data-bs-theme="{{ current_theme.mode }}"` 统一标记明暗
     （见 base.html:2），故一条 [data-bs-theme="dark"] 即可覆盖全部深色主题。
   ★ 为什么深色要单独提高不透明度：同样的 rgba(...,0.10) 叠在浅底上是淡彩、
     叠在深底上几乎等于没涂（alpha 太低被深底吃掉）⇒ 深底统一提到 0.16~0.20。 */
[data-bs-theme="dark"] {
    --erp-grp-0: rgba(148, 163, 184, 0.10);
    --erp-grp-1: rgba(56, 189, 248, 0.16);
    --erp-grp-2: rgba(52, 211, 153, 0.16);
    --erp-grp-3: rgba(251, 191, 36, 0.18);
    --erp-grp-4: rgba(192, 132, 252, 0.16);
    --erp-grp-5: rgba(251, 113, 133, 0.16);
    --erp-row-hover: rgba(148, 163, 184, 0.20);
    --erp-preselect: rgba(52, 211, 153, 0.26);

    /* 「表格纸」变量（2026-10-04）：工资表 / 员工档案这类**密集数字表**原先把
       纸色写死白底（注释称"浅色表格纸"），深色主题下一整块白纸刺眼。
       深色下把纸压暗、字提亮 ⇒ 仍是"一张纸"的视觉，但与主题协调。 */
    --erp-paper-bg: #16233a;
    --erp-paper-fg: #e2e8f0;
    /* 工资表四段分区（考勤/应发/扣款/结算）：色相是**业务语义**、不随主题变，
       只提高不透明度让深底上清晰可辨。 */
    --erp-zone-person: rgba(148, 163, 184, 0.18);
    --erp-zone-person-fg: #e2e8f0;
    --erp-zone-att: rgba(56, 189, 248, 0.20);
    --erp-zone-att-fg: #bae6fd;
    --erp-zone-gross: rgba(52, 211, 153, 0.20);
    --erp-zone-gross-fg: #bbf7d0;
    --erp-zone-ded: rgba(251, 113, 133, 0.20);
    --erp-zone-ded-fg: #fecdd3;
    --erp-zone-settle: rgba(192, 132, 252, 0.20);
    --erp-zone-settle-fg: #e9d5ff;
    --erp-zone-total: rgba(251, 191, 36, 0.18);
    --erp-zone-total-fg: #fde68a;
}

:root {
    --erp-primary: #1a3a5c;
    --erp-accent: #2563eb;
    --erp-navbar-from: #1a3a5c;
    --erp-navbar-to: #2563eb;
    --erp-bg: #f5f7fa;
    --erp-sidebar-bg: #f8fafc;
    --erp-sidebar-border: #e2e8f0;
    --erp-sidebar-color: #334155;
    --erp-sidebar-hover-bg: #e2e8f0;
    --erp-sidebar-hover-color: #2563eb;
    --erp-sidebar-active-bg: #dbeafe;
    --erp-sidebar-active-color: #2563eb;
    --erp-card-bg: #ffffff;
    --erp-card-shadow: 0 1px 3px rgba(0,0,0,0.08);
    --erp-card-glow: 0 0 0 rgba(0,0,0,0); /* 3D/科技主题彩色光晕 */
    --erp-text: #1e293b;
    --erp-text-muted: #5a6b82; /* 次要文字，兼顾浅色底对比度 */
    --erp-table-head-bg: #f1f5f9;
    --erp-table-head-color: #475569;
    --erp-table-border: #e2e8f0;
    /* ★ 2026-10-04 新增：表格分组色 / 行悬停 / 选中行（供模板私有 CSS 引用）。
       此前 settlement_batches 与 outbounds 把这些写成硬编码浅色，深色主题下失配。
       用**半透明叠色**：同一份声明在浅色底上是淡彩、在深色底上自动变暗，
       不必为每个主题各写一套。深色主题块里另有加强版（见下）。 */
    --erp-grp-0: rgba(120, 120, 128, 0.06);
    --erp-grp-1: rgba(14, 165, 233, 0.10);
    --erp-grp-2: rgba(16, 185, 129, 0.10);
    --erp-grp-3: rgba(245, 158, 11, 0.12);
    --erp-grp-4: rgba(168, 85, 247, 0.10);
    --erp-grp-5: rgba(244, 63, 94, 0.10);
    --erp-row-hover: rgba(120, 120, 128, 0.14);
    --erp-preselect: rgba(16, 185, 129, 0.22);
    --erp-border: #e2e8f0;
    /* 「表格纸」与工资表四段分区（浅色主题：与历史表现完全一致） */
    --erp-paper-bg: #ffffff;
    --erp-paper-fg: #212529;
    --erp-zone-person: #eef1f4;
    --erp-zone-person-fg: #212529;
    --erp-zone-att: rgba(14, 165, 233, 0.16);
    --erp-zone-att-fg: #0b4a7d;
    --erp-zone-gross: rgba(16, 185, 129, 0.16);
    --erp-zone-gross-fg: #136b3c;
    --erp-zone-ded: rgba(244, 63, 94, 0.16);
    --erp-zone-ded-fg: #a4232f;
    --erp-zone-settle: rgba(168, 85, 247, 0.16);
    --erp-zone-settle-fg: #4a3aa8;
    --erp-zone-total: #fff8e1;
    --erp-zone-total-fg: #8a6d00;
    /* ★ 2026-09-28：170px → 190px。折叠项里最长的菜单名「跨仓盘点调整」(
       6 个汉字 ≈ 82px) + 图标 + 间距 + 红色角标(≈20px) 共需 ≈131px 内容宽，
       而 170px 侧栏在 3D 主题下（item 左外距 18px + 内距 0.75rem×2）只剩 ≈120px
       ⇒ 角标被排到菜单项盒子之外，被 `.erp-sidebar{overflow-x:hidden}` 裁成一条竖线
       （浏览器实测：角标 right=181.55 > 侧栏右边界 170，19.55px 宽只剩 8px 可见）。 */
    --erp-sidebar-width: 190px;
    --erp-navbar-height: 44px;
    /* Bootstrap muted 文字（text-muted/placeholder 等）统一对比度，加载晚于 bootstrap.min.css 故可覆盖 */
    --bs-secondary-color: #5a6b82;
    /* ★ 2026-09-29 图表色（利润中心利润表 · 柱状图）。默认按「浅色」，深色由下面的
       [data-bs-theme="dark"] 一次性派生 —— 14 个主题里 8 个是深色，逐个主题块写会漏；
       将来某主题想单独定制，只需在它自己的块里覆盖这 6 个变量即可（同权重、后写者胜）。 */
    --erp-chart-pos: #2563eb;      /* 盈利柱（柱 vs 白底非文本对比 ≈5.4:1） */
    --erp-chart-neg: #b02a37;      /* 亏损柱 */
    --erp-chart-zero: #64748b;     /* 零轴线（#94a3b8 压白底只有 2.56:1，图形需 3:1） */
    --erp-chart-none: #cbd5e1;     /* 无数据标记 */
    --erp-chart-trend: #0f766e;    /* 趋势折线 */
    /* ★ 亏损金额文字色必须**单列**：柱色 #b02a37 压深底色只有 2.55:1，不能直接当文字色 */
    --erp-neg-text: #c02a35;
    /* ★ 2026-09-29 多系列图表色（采购统计 12 月多折线，最多 8 个采购部并行）。
       浅色底一律选深一档（每个都对 #ffffff ≥ 3:1 的非文本阈值），深色底由下面的
       [data-bs-theme="dark"] 一次派生成亮一档（每个都对 #171f2a ≥ 3:1）。
       实测手段见 erp-browser-layout-probe（对比度只能量，不能估）。 */
    --erp-chart-s1: #1d4ed8;
    --erp-chart-s2: #b45309;
    --erp-chart-s3: #0f766e;
    --erp-chart-s4: #be185d;
    --erp-chart-s5: #15803d;
    --erp-chart-s6: #c2410c;
    --erp-chart-s7: #6d28d9;
    --erp-chart-s8: #0e7490;
}

/* ---------- 图表色（深色主题派生）----------
   ★ 2026-09-29 浏览器实测修正：深色下亏损柱**不能**沿用浅色的 #b02a37 ——
     它压深色卡片底(#171f2a)只有 **2.55:1**，低于「非文本/图形 3:1」的做法线（实测见
     _pm_bar_shots_20260929/report_sim.png）。改成 #e5484d 后 = **4.25:1**。
   ★ 亏损金额**文字**色另行单列 --erp-neg-text：柱色系都不能直接当文字色
     （#ff8b93 压 #171f2a = 7.40:1 才够；#b02a37 只有 2.55）。
   ★ 盈利柱 #3b82f6 压 #171f2a = 4.51:1 ✅ */
[data-bs-theme="dark"] {
    --erp-chart-pos: #3b82f6;
    --erp-chart-neg: #e5484d;
    --erp-chart-zero: #64748b;    /* #475569 压 #171f2a 只有 2.19:1 < 3 */
    --erp-chart-none: #475569;
    --erp-chart-trend: #5eead4;
    --erp-neg-text: #ff8b93;
    --erp-chart-s1: #60a5fa;
    --erp-chart-s2: #fbbf24;
    --erp-chart-s3: #2dd4bf;
    --erp-chart-s4: #f472b6;
    --erp-chart-s5: #4ade80;
    --erp-chart-s6: #fb923c;
    --erp-chart-s7: #a78bfa;
    --erp-chart-s8: #22d3ee;
}

/* ---------- 浅色主题：清新绿 ---------- */
[data-theme="light-green"] {
    --erp-primary: #065f46;
    --erp-accent: #059669;
    --erp-navbar-from: #065f46;
    --erp-navbar-to: #10b981;
    --erp-bg: #f2faf5;
    --erp-sidebar-bg: #f7fbf8;
    --erp-sidebar-border: #d6e9e0;
    --erp-sidebar-color: #34524a;
    --erp-sidebar-hover-bg: #d6e9e0;
    --erp-sidebar-hover-color: #059669;
    --erp-sidebar-active-bg: #cdeee0;
    --erp-sidebar-active-color: #047857;
    --erp-card-shadow: 0 1px 3px rgba(4,120,87,0.08);
    --erp-table-head-bg: #e8f5ef;
    --erp-table-head-color: #3f6257;
    --erp-table-border: #d6e9e0;
}

/* ---------- 浅色主题：暖阳橙 ---------- */
[data-theme="light-warm"] {
    --erp-primary: #9a3412;
    --erp-accent: #ea580c;
    --erp-navbar-from: #9a3412;
    --erp-navbar-to: #f97316;
    --erp-bg: #fdf6f0;
    --erp-sidebar-bg: #fdf9f5;
    --erp-sidebar-border: #f0ddd0;
    --erp-sidebar-color: #5c4333;
    --erp-sidebar-hover-bg: #f0ddd0;
    --erp-sidebar-hover-color: #ea580c;
    --erp-sidebar-active-bg: #fde3d0;
    --erp-sidebar-active-color: #c2410c;
    --erp-card-shadow: 0 1px 3px rgba(234,88,12,0.08);
    --erp-table-head-bg: #fceee4;
    --erp-table-head-color: #6b4a36;
    --erp-table-border: #f0ddd0;
}

/* ---------- 深色主题：深夜蓝 ---------- */
[data-theme="dark-blue"] {
    --erp-primary: #0b1220;
    --erp-accent: #3b82f6;
    --erp-navbar-from: #0b1220;
    --erp-navbar-to: #1e3a5f;
    --erp-bg: #0f172a;
    --erp-sidebar-bg: #111c33;
    --erp-sidebar-border: #1e293b;
    --erp-sidebar-color: #b6c2d6;
    --erp-sidebar-hover-bg: #1c2a47;
    --erp-sidebar-hover-color: #93c5fd;
    --erp-sidebar-active-bg: #1e3a5f;
    --erp-sidebar-active-color: #93c5fd;
    --erp-card-bg: #17213a;
    --erp-card-shadow: 0 1px 3px rgba(0,0,0,0.35);
    --erp-text: #e2e8f0;
    --erp-text-muted: #aab8cc; /* 提高次要文字亮度 */
    --erp-table-head-bg: #1e293b;
    --erp-table-head-color: #cbd5e1;
    --erp-table-border: #334155;
    --erp-border: #334155;
    --bs-secondary-color: #aab8cc;
    --bs-tertiary-color: #8fa1b8;
}

/* ---------- 深色主题：墨玉绿 ---------- */
[data-theme="dark-green"] {
    --erp-primary: #022c22;
    --erp-accent: #34d399;
    --erp-navbar-from: #022c22;
    --erp-navbar-to: #065f46;
    --erp-bg: #0c1a15;
    --erp-sidebar-bg: #0f231c;
    --erp-sidebar-border: #173a2e;
    --erp-sidebar-color: #a8c5ba;
    --erp-sidebar-hover-bg: #153629;
    --erp-sidebar-hover-color: #6ee7b7;
    --erp-sidebar-active-bg: #14532d;
    --erp-sidebar-active-color: #6ee7b7;
    --erp-card-bg: #12251e;
    --erp-card-shadow: 0 1px 3px rgba(0,0,0,0.35);
    --erp-text: #d7e5df;
    --erp-text-muted: #9db8ad; /* 提高次要文字亮度 */
    --erp-table-head-bg: #173a2e;
    --erp-table-head-color: #bcd5cc;
    --erp-table-border: #21523f;
    --bs-secondary-color: #9db8ad;
    --bs-tertiary-color: #86a79a;
}

/* ---------- 深色主题：夜魅紫 ---------- */
[data-theme="dark-purple"] {
    --erp-primary: #1e1b4b;
    --erp-accent: #a78bfa;
    --erp-navbar-from: #1e1b4b;
    --erp-navbar-to: #4c1d95;
    --erp-bg: #16131f;
    --erp-sidebar-bg: #1b1730;
    --erp-sidebar-border: #2b2444;
    --erp-sidebar-color: #bfb3d8;
    --erp-sidebar-hover-bg: #2a2350;
    --erp-sidebar-hover-color: #c4b5fd;
    --erp-sidebar-active-bg: #3b1f7a;
    --erp-sidebar-active-color: #c4b5fd;
    --erp-card-bg: #211c3a;
    --erp-card-shadow: 0 1px 3px rgba(0,0,0,0.35);
    --erp-text: #e6dff4;
    --erp-text-muted: #b6a9d9; /* 提高次要文字亮度 */
    --erp-table-head-bg: #2b2444;
    --erp-table-head-color: #d2c7e8;
    --erp-table-border: #3a2f5c;
    --bs-secondary-color: #b6a9d9;
    --bs-tertiary-color: #a899c9;
}

/* ---------- 3D/科技感主题：冰蓝科技（浅色） ---------- */
[data-theme="tech-blue"] {
    --erp-primary: #0369a1;
    --erp-accent: #0ea5e9;
    --erp-navbar-from: #0369a1;
    --erp-navbar-to: #38bdf8;
    --erp-bg: #eef6fc;
    --erp-sidebar-bg: #f6fafd;
    --erp-sidebar-border: #d9e9f5;
    --erp-sidebar-color: #334e63;
    --erp-sidebar-hover-bg: #dcecf7;
    --erp-sidebar-hover-color: #0284c7;
    --erp-sidebar-active-bg: #d1e8f7;
    --erp-sidebar-active-color: #0369a1;
    --erp-card-bg: #ffffff;
    --erp-card-shadow: 0 1px 2px rgba(2,132,199,0.10), inset 0 1px 0 rgba(255,255,255,0.9), 0 10px 30px -12px rgba(2,132,199,0.25);
    --erp-card-glow: 0 0 0 1px rgba(14,165,233,0.06);
    --erp-text: #16303f;
    --erp-text-muted: #52728c;
    --erp-table-head-bg: #e3f0f8;
    --erp-table-head-color: #3f5f7a;
    --erp-table-border: #cfdfeb;
    --bs-secondary-color: #52728c;
    --bs-tertiary-color: #6f8ea8;
}

/* ---------- 3D/科技感主题：晶透玻璃（浅色） ---------- */
[data-theme="tech-glass"] {
    --erp-primary: #4c1d95;
    --erp-accent: #8b5cf6;
    --erp-navbar-from: #4c1d95;
    --erp-navbar-to: #a78bfa;
    --erp-bg: #f5f3ff;
    --erp-sidebar-bg: #faf9ff;
    --erp-sidebar-border: #e5dcf5;
    --erp-sidebar-color: #4b3a63;
    --erp-sidebar-hover-bg: #ece5fb;
    --erp-sidebar-hover-color: #7c3aed;
    --erp-sidebar-active-bg: #e2d9f8;
    --erp-sidebar-active-color: #6d28d9;
    --erp-card-bg: rgba(255, 255, 255, 0.85);
    --erp-card-shadow: 0 2px 6px rgba(124,58,237,0.10), inset 0 1px 0 rgba(255,255,255,0.95), 0 12px 32px -12px rgba(124,58,237,0.22);
    --erp-card-glow: 0 0 0 1px rgba(139,92,246,0.08);
    --erp-text: #251c3a;
    --erp-text-muted: #65508f;
    --erp-table-head-bg: #efeafb;
    --erp-table-head-color: #4f3c78;
    --erp-table-border: #e2d8f2;
    --bs-secondary-color: #65508f;
    --bs-tertiary-color: #7f6aa8;
}

/* ---------- 3D/科技感主题：赛博霓虹（深色） ---------- */
[data-theme="tech-neon"] {
    --erp-primary: #0e7490;
    --erp-accent: #22d3ee;
    --erp-navbar-from: #020617;
    --erp-navbar-to: #0e7490;
    --erp-bg: #070d1a;
    --erp-sidebar-bg: #0a1322;
    --erp-sidebar-border: #1e293b;
    --erp-sidebar-color: #b8cddd;
    --erp-sidebar-hover-bg: #14263a;
    --erp-sidebar-hover-color: #67e8f9;
    --erp-sidebar-active-bg: #164e63;
    --erp-sidebar-active-color: #a5f3fc;
    --erp-card-bg: #0f1c2e;
    --erp-card-shadow: 0 2px 6px rgba(0,0,0,0.45), inset 0 1px 0 rgba(255,255,255,0.06), 0 14px 34px -14px rgba(34,211,238,0.22);
    --erp-card-glow: 0 0 24px rgba(34,211,238,0.10);
    --erp-text: #e6f2f7;
    --erp-text-muted: #a3c4d6;
    --erp-table-head-bg: #16283c;
    --erp-table-head-color: #a8c9dd;
    --erp-table-border: #1f3a4f;
    --bs-secondary-color: #a3c4d6;
    --bs-tertiary-color: #7fa3b8;
}

/* ---------- 3D/科技感主题：曜石黑（深色） ---------- */
[data-theme="tech-carbon"] {
    --erp-primary: #1f2937;
    --erp-accent: #60a5fa;
    --erp-navbar-from: #0a0a0a;
    --erp-navbar-to: #1f2937;
    --erp-bg: #0d0d0f;
    --erp-sidebar-bg: #131316;
    --erp-sidebar-border: #232329;
    --erp-sidebar-color: #c2c2cc;
    --erp-sidebar-hover-bg: #1d1d24;
    --erp-sidebar-hover-color: #93c5fd;
    --erp-sidebar-active-bg: #1e2937;
    --erp-sidebar-active-color: #93c5fd;
    --erp-card-bg: #18181b;
    --erp-card-shadow: 0 3px 8px rgba(0,0,0,0.5), inset 0 1px 0 rgba(255,255,255,0.07), 0 16px 40px -16px rgba(96,165,250,0.18);
    --erp-card-glow: 0 0 26px rgba(96,165,250,0.08);
    --erp-text: #ececf1;
    --erp-text-muted: #a5a5b0;
    --erp-table-head-bg: #202026;
    --erp-table-head-color: #c3c3ce;
    --erp-table-border: #2a2a31;
    --bs-secondary-color: #a5a5b0;
    --bs-tertiary-color: #83838e;
}

/* ---------- 3D 立体感主题：鎏金璀璨（浅色） ---------- */
[data-theme="3d-gold"] {
    --erp-primary: #92400e;
    --erp-accent: #f59e0b;
    /* 立体渐变对（背景用，需足够深保证白字可读） */
    --erp-grad-from: #92400e;
    --erp-grad-to: #d97706;
    --erp-navbar-from: #7c2d12;
    --erp-navbar-to: #d97706;
    --erp-bg: #fdfaf3;
    --erp-sidebar-bg: #fffaf0;
    --erp-sidebar-border: #ecd9b4;
    --erp-sidebar-color: #5c4520;
    --erp-sidebar-hover-bg: #f9e8c8;
    --erp-sidebar-hover-color: #b45309;
    --erp-sidebar-active-bg: #f3d9a4;
    --erp-sidebar-active-color: #92400e;
    --erp-card-bg: #ffffff;
    --erp-card-shadow: 0 2px 6px rgba(146,64,14,0.10), inset 0 1px 0 rgba(255,255,255,0.9), 0 12px 30px -12px rgba(217,119,6,0.28);
    --erp-card-glow: 0 0 0 1px rgba(245,158,11,0.08);
    --erp-text: #3d2c14;
    --erp-text-muted: #8a6d3b;
    --erp-table-head-bg: #f9e8c8;
    --erp-table-head-color: #7c5a24;
    --erp-table-border: #ecd9b4;
    --bs-secondary-color: #8a6d3b;
    --bs-tertiary-color: #a58a56;
}

/* ---------- 3D 立体感主题：极光幻彩（深色） ---------- */
[data-theme="3d-aurora"] {
    --erp-primary: #0e7490;
    --erp-accent: #22d3ee;
    --erp-grad-from: #0e7490;
    --erp-grad-to: #7c3aed;
    --erp-navbar-from: #020617;
    --erp-navbar-to: #0e7490;
    --erp-bg: #050a16;
    --erp-sidebar-bg: #0a1424;
    --erp-sidebar-border: #1c3a52;
    --erp-sidebar-color: #b4ccdd;
    --erp-sidebar-hover-bg: #12283c;
    --erp-sidebar-hover-color: #67e8f9;
    --erp-sidebar-active-bg: #164e63;
    --erp-sidebar-active-color: #a5f3fc;
    --erp-card-bg: #0d1b2e;
    --erp-card-shadow: 0 2px 6px rgba(0,0,0,0.45), inset 0 1px 0 rgba(255,255,255,0.06), 0 14px 34px -14px rgba(34,211,238,0.25);
    --erp-card-glow: 0 0 24px rgba(124,58,237,0.12);
    --erp-text: #e8f4f8;
    --erp-text-muted: #9fc4d6;
    --erp-table-head-bg: #12283c;
    --erp-table-head-color: #a8d1e4;
    --erp-table-border: #1c3a52;
    --bs-secondary-color: #9fc4d6;
    --bs-tertiary-color: #7fa3b8;
}

/* ---------- 3D 立体感主题：钛银机甲（深色） ---------- */
[data-theme="3d-titanium"] {
    --erp-primary: #1e293b;
    --erp-accent: #60a5fa;
    --erp-grad-from: #334155;
    --erp-grad-to: #3b82f6;
    --erp-navbar-from: #0b1220;
    --erp-navbar-to: #1e3a5f;
    --erp-bg: #0e1116;
    --erp-sidebar-bg: #131a23;
    --erp-sidebar-border: #2a3642;
    --erp-sidebar-color: #b6c3d1;
    --erp-sidebar-hover-bg: #1e2933;
    --erp-sidebar-hover-color: #93c5fd;
    --erp-sidebar-active-bg: #1e3a5f;
    --erp-sidebar-active-color: #93c5fd;
    --erp-card-bg: #171f2a;
    --erp-card-shadow: 0 3px 8px rgba(0,0,0,0.5), inset 0 1px 0 rgba(255,255,255,0.07), 0 16px 40px -16px rgba(96,165,250,0.20);
    --erp-card-glow: 0 0 26px rgba(96,165,250,0.08);
    --erp-text: #eef2f6;
    --erp-text-muted: #a9b6c4;
    --erp-table-head-bg: #1e2933;
    --erp-table-head-color: #c4d0db;
    --erp-table-border: #2a3642;
    --bs-secondary-color: #a9b6c4;
    --bs-tertiary-color: #8797a8;
}

/* ---------- 3D 立体感主题：琉璃蓝（暗色玻璃态 + 亮蓝渐变表头） ---------- */
[data-theme="3d-crystal"] {
    --erp-primary: #0b1220;
    --erp-accent: #60a5fa;
    --erp-grad-from: #2563eb;
    --erp-grad-to: #3b82f6;
    --erp-navbar-from: #050914;
    --erp-navbar-to: #1e3a5f;
    --erp-bg: #070b14;
    --erp-sidebar-bg: rgba(11, 18, 32, 0.92);
    --erp-sidebar-border: rgba(59, 130, 246, 0.22);
    --erp-sidebar-color: #a8c6e8;
    --erp-sidebar-hover-bg: rgba(37, 99, 235, 0.22);
    --erp-sidebar-hover-color: #93c5fd;
    --erp-sidebar-active-bg: rgba(37, 99, 235, 0.32);
    --erp-sidebar-active-color: #bfdbfe;
    --erp-card-bg: rgba(15, 23, 42, 0.78);
    --erp-card-shadow: 0 8px 32px rgba(0, 0, 0, 0.45), inset 0 1px 0 rgba(255, 255, 255, 0.08);
    --erp-card-glow: 0 0 30px rgba(59, 130, 246, 0.18);
    --erp-text: #e2e8f0;
    --erp-text-muted: #94a3b8;
    --erp-table-head-bg: rgba(30, 58, 95, 0.85);
    --erp-table-head-color: #dbeafe;
    --erp-table-border: rgba(59, 130, 246, 0.22);
    --bs-secondary-color: #94a3b8;
    --bs-tertiary-color: #64748b;
}

/* ============================================================
   Bootstrap 组件主题适配
   让 .bg-light / .table-light / code 等跟随 ERP 主题变量，
   避免深色主题下出现浅灰底浅字或默认粉色 code 看不清
   ============================================================ */

/* 卡片头部 bg-light 跟随主题表头背景，文字使用主题主色 */
.card-header.bg-light,
.card-header.bg-light h5,
.card-header.bg-light h6,
.card-header.bg-light strong,
.bg-light {
    background-color: var(--erp-table-head-bg) !important;
    color: var(--erp-text) !important;
}

/* 表格 light 头部跟随主题 */
.table-light {
    --bs-table-bg: var(--erp-table-head-bg) !important;
    --bs-table-color: var(--erp-table-head-color) !important;
    --bs-table-border-color: var(--erp-table-border) !important;
}

/* 表格 secondary（合计行/小计行等）跟随主题：
   浅色主题 → 浅底深字；深色主题 → 深底浅字（Bootstrap 默认硬编码黑字，深色下不可见） */
.table-secondary {
    --bs-table-bg: var(--erp-table-head-bg) !important;
    --bs-table-color: var(--erp-table-head-color) !important;
    --bs-table-border-color: var(--erp-table-border) !important;
}

/* 深色主题兜底：所有合计行（tfoot/summary）文字强制使用主题表头文字色，
   防止任何未带主题类的合计行残留黑色字（text-success/danger 等语义色优先级更高，不受影响） */
[data-bs-theme="dark"] .table tfoot > tr > th,
[data-bs-theme="dark"] .table tfoot > tr > td {
    color: var(--erp-table-head-color, var(--erp-text, #e2e8f0));
}
[data-bs-theme="light"] .table tfoot > tr > th,
[data-bs-theme="light"] .table tfoot > tr > td {
    color: var(--erp-table-head-color, var(--erp-text, #1e293b));
}

/* code 标签使用主题强调色，避免 Bootstrap 默认粉色在浅色底对比度不足 */
code {
    color: var(--erp-accent);
    background-color: rgba(0,0,0,0.04);
    padding: 0.1em 0.35em;
    border-radius: 4px;
}

[data-bs-theme="dark"] code {
    background-color: rgba(255,255,255,0.08);
}

/* 深色主题下强制 text-muted 等次要文字使用更亮的主题变量 */
[data-bs-theme="dark"] .text-muted,
[data-bs-theme="dark"] .form-text,
[data-bs-theme="dark"] .text-secondary {
    color: var(--erp-text-muted) !important;
}

* { box-sizing: border-box; }

html, body {
    min-height: 100%;
}

body {
    font-family: -apple-system, "Microsoft YaHei", "Segoe UI", sans-serif;
    background-color: var(--erp-bg);
    margin: 0;
    padding: 0;
    overflow-y: auto; /* 确保内容超出页面时可上下滚动 */
}

/* ========== 导航栏 ========== */
.erp-navbar {
    background: linear-gradient(135deg, var(--erp-navbar-from) 0%, var(--erp-navbar-to) 100%);
    height: var(--erp-navbar-height);
    box-shadow: 0 2px 8px rgba(0,0,0,0.15);
}

/* 导航栏底部霓虹高光线条（3D 立体感） */
.erp-navbar::after {
    content: "";
    position: absolute;
    left: 0;
    right: 0;
    bottom: 0;
    height: 2px;
    background: linear-gradient(90deg, transparent, var(--erp-accent), transparent);
    opacity: 0.55;
    pointer-events: none;
}

.erp-navbar .navbar-brand {
    font-weight: 700;
    font-size: 1.0rem;
    letter-spacing: 1px;
    padding-top: 0.25rem;
    padding-bottom: 0.25rem;
    display: inline-flex;
    align-items: center;
}

/* ⚠️ 2026-10-08 弃用：顶栏 LOGO 已按用户要求删除（base.html 的 .navbar-brand 里
   不再有 <img>）。规则暂留，便于一行回退。 */
.erp-navbar .navbar-brand .navbar-logo {
    height: 52px;
    width: auto;
    max-width: 200px;
    object-fit: contain;
}

.erp-navbar .navbar-brand .navbar-brand-text {
    color: #fff;
    font-weight: 700;
    font-size: 1.1rem;
    letter-spacing: 1px;
    /* ★ 2026-10-08：原为 10px ——「品牌文字与左侧 LOGO 的间距」。
       LOGO 删除后它成了孤儿属性，会让文字凭空左缩 10px（.navbar-brand 本身
       padding-left 为 0，文字应贴住 .container-fluid 的左内边距）。
       故归零，使文字左边缘落在原来 LOGO 的位置。 */
    margin-left: 0;
}

.erp-navbar .nav-link {
    font-size: 0.85rem;
    /* ★ 2026-10-07：由 0.35rem 0.7rem / margin 0 2px 收紧（用户要求「菜单之间的距离
       还可以紧凑一点」）—— 顶栏要平铺 9~10 个分组，每项省下的这几像素是决定性的。
       顶栏还另有更紧的一档（见 2026-10-07 节的 .erp-topnav > .nav-item > .nav-link）。 */
    padding: 0.3rem 0.55rem !important;
    border-radius: 6px;
    margin: 0 1px;
    transition: background 0.2s;
}

.erp-navbar .nav-link:hover {
    background: rgba(255,255,255,0.15);
}

.erp-navbar .nav-link.disabled {
    opacity: 0.55;
}

/* ========== 侧边栏 ========== */
.erp-sidebar {
    position: fixed;
    left: 0;
    top: var(--erp-navbar-height);
    bottom: 0;
    width: var(--erp-sidebar-width);
    background: var(--erp-sidebar-bg);
    border-right: 1px solid var(--erp-sidebar-border);
    padding-top: 1rem;
    overflow-y: auto;
    overflow-x: hidden;
    z-index: 100;
}

.sidebar-header {
    padding: 0.5rem 1rem 0.5rem;
    text-transform: uppercase;
    font-size: 0.8rem;
    letter-spacing: 1px;
}

/* 侧边栏分组折叠触发器 */
.sidebar-group-toggle {
    display: flex;
    align-items: center;
    width: 100%;
    background: none;
    border: none;
    text-align: left;
    padding: 0.75rem 1rem;
    color: var(--erp-sidebar-color);
    font-size: 1.0rem;
    font-weight: 700;
    letter-spacing: 0.5px;
    text-transform: uppercase;
    cursor: pointer;
    border-left: 3px solid transparent;
    transition: color 0.15s, background 0.15s;
}

.sidebar-group-toggle:hover {
    color: var(--erp-sidebar-hover-color);
    background: var(--erp-sidebar-hover-bg);
}

.sidebar-group-toggle i.bi-chevron-right {
    font-size: 0.85rem;
    margin-right: 8px;
    transition: transform 0.2s ease;
}

/* 展开时箭头向下（Bootstrap 会切换 aria-expanded 属性） */
.sidebar-group-toggle[aria-expanded="true"] i.bi-chevron-right,
.sidebar-group-toggle.open i.bi-chevron-right {
    transform: rotate(90deg);
}

/* 折叠分组内的菜单项缩进，体现层级。
   ★ 2026-10-07：作用域从 `.erp-sidebar` 改为 `.erp-navtree` —— 窄屏抽屉（offcanvas）
   不是 `.erp-sidebar`，但装的是**同一份**菜单树；用容器类而非具体某个容器，
   两处缩进/行高才会永远一致（否则抽屉里的子项会顶格显示，与侧栏两副样子）。 */
.erp-navtree .collapse .erp-sidebar-item {
    padding-left: 2.1rem;
}

.erp-sidebar-item {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 0.75rem 1rem;
    color: var(--erp-sidebar-color);
    text-decoration: none;
    font-size: 0.85rem;
    border-left: 3px solid transparent;
    transition: all 0.15s;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.erp-sidebar-item:hover {
    background: var(--erp-sidebar-hover-bg);
    color: var(--erp-sidebar-hover-color);
    text-decoration: none;
}

.erp-sidebar-item.active {
    background: var(--erp-sidebar-active-bg);
    color: var(--erp-sidebar-active-color);
    border-left-color: var(--erp-accent);
    font-weight: 600;
}

.erp-sidebar-item i {
    font-size: 1.1rem;
}

/* ---------- 侧栏待办角标（★ 2026-09-28 修复） ----------
   症状：菜单项右侧的红色角标「显示不全」，只剩一条红色竖线（用户截图）。
   真根因（浏览器实测数据）：`.erp-sidebar` 是 `overflow-x:hidden`。
   `跨仓盘点调整`(6 汉字 ≈82px) + 图标 + 间距 + 角标(≈20px) 共需 ≈131px，
   而 170px 侧栏在 3D 主题下只剩 ≈120px ⇒ 角标被排到菜单项盒子右边界之外
   （实测 `right=181.55` > 侧栏右边界 `170`），**被 overflow-x:hidden 裁掉 11.55px，
   19.55px 宽的角标只剩 8.00px 可见** —— 这就是那条「红竖线」。
   修法三件：
   ① `flex:0 0 auto` —— 角标不参与收缩，保证它自身宽度完整；
   ② `margin-left:auto` —— 推到内容区最右（与其他角标对齐），并把「文字 vs 角标」的
      空间分配交给 flex；用 `!important` 压掉 Bootstrap `.ms-1`
      （`margin-left:.25rem !important`）——两者同为 important 时靠后者胜，
      本文件在 bootstrap.min.css 之后加载，故稳定生效；
   ③ `white-space:nowrap` —— 防两位数（如 10）竖排换行。
   ⚠ ①② 只保证角标不被压扁，**容器宽度不够时被裁的会换成菜单文字** ⇒
      必须配合 `--erp-sidebar-width` 加宽（见该变量处的注释）。
   A/B 实测（headless Edge + 真 style.css，1600×1500）：可见宽 **8.00px → 19.55px**。 */
.erp-sidebar-item .badge,
.sidebar-group-toggle .badge {
    flex: 0 0 auto;
    margin-left: auto !important;
    white-space: nowrap;
}

/* 顶级直达菜单项（无子菜单，如「修改审批」「工资表」）：
   与分组触发器同高、同字号，视觉上仍是一级卡片，但点击即跳转，不再展开子菜单。
   ★ 2026-10-07：作用域用 .erp-navtree（侧栏与窄屏抽屉共用），不是 .erp-sidebar */
.erp-navtree .erp-sidebar-toplink {
    padding-left: 1rem;
    font-size: 1.0rem;
    font-weight: 700;
    letter-spacing: 0.5px;
}

/* ==========================================================================
   ★ 2026-10-07 导航改造：顶栏下拉镜像左栏 / 侧栏收起箭头 / 窄屏抽屉
   背景：菜单真源已收敛到 nav.py（顶栏与左栏不再各写一套）。本节只管外观。
   ========================================================================== */

/* ---------- 0.5 顶栏文字：**全站统一一种字色** + 浅色渐变上的可读性 ----------
   用户 2026-10-07 实测反馈：「顶部栏折叠成更多后，主菜单字体看不清了；各菜单字体颜色
   不统一，财务管理和修改审批明显要白一点」。根因是两段样式打架：
     · `.erp-navbar .nav-link` **从来没有设过 color** ⇒ 顶栏文字吃的是 Bootstrap 的
       `.navbar-dark .navbar-nav .nav-link{color:rgba(255,255,255,.55)}` —— 55% 白
       压在深色渐变上就是「看不清」；
     · 而 `.nav-link.active`（当前所在菜单）被 Bootstrap 加成 `#fff` ⇒ 同一条顶栏里
       并存 55% 白与 100% 白两种字色，就是用户说的「颜色不统一、要白一点」。
   修法：**所有**顶栏链接统一到同一个颜色，高亮只加背景药丸、**不改字色**；再补一层
   深色 text-shadow —— tech-blue(#38bdf8)/light-warm(#f97316)/tech-glass(#a78bfa)/
   3d-gold(#d97706) 这几个主题的渐变右端偏亮，白字必须靠阴影才立得住。
   ⚠️ 选择器必须写成 `.erp-navbar .navbar-nav .nav-link`（(0,3,0)）：写成
      `.erp-navbar .nav-link`（(0,2,0)）会被 Bootstrap 那条 (0,3,0) **反超**，
      症状是「改了没反应」——本项目已在同类问题上踩过一次。 */
.erp-navbar {
    --erp-navbar-fg: rgba(255, 255, 255, .93);
    /* 当前所在菜单：只靠背景药丸区分，字色与其它项完全一致 */
    --erp-navbar-pill: rgba(255, 255, 255, .20);
    /* 下拉展开中的父项：比药丸淡一档，避免与「当前所在菜单」混淆 */
    --erp-navbar-pill-open: rgba(255, 255, 255, .12);
}

.erp-navbar .navbar-nav .nav-link {
    color: var(--erp-navbar-fg);
    text-shadow: 0 1px 2px rgba(0, 0, 0, .45);
}

.erp-navbar .navbar-nav .nav-link:hover,
.erp-navbar .navbar-nav .nav-link:focus {
    color: #fff;
}

/* 当前所在菜单 / 下拉展开中的父项：**只加背景药丸，绝不改字色**。
   ★ 探针实测踩过：这里原先写了 `color:#fff`，于是「仪表盘」（当前页）是纯白、
     其余项是 93% 白 —— 正好复现用户说的「颜色不统一、有的要白一点」。
     用户要的是**全站一种字色**，所以区分只能靠背景。 */
.erp-navbar .navbar-nav .nav-link.active {
    background: var(--erp-navbar-pill);
}

.erp-navbar .navbar-nav .nav-link.dropdown-toggle.show {
    background: var(--erp-navbar-pill-open);
}

/* ---------- 0.6 顶栏菜单项的紧凑档 ----------
   顶栏要平铺所有分组（不再把长尾塞进「更多」），所以每项再省一档：
   padding .7rem→.5rem、外边距归零、图标与文字改用 gap（模板里的空格会被 flex 吞掉）。 */
.erp-topnav > .nav-item > .nav-link {
    white-space: nowrap;
    display: flex;
    align-items: center;
    gap: .3rem;
    padding: .3rem .5rem !important;
    margin: 0 !important;
}

.erp-topnav .dropdown-toggle::after {
    margin-left: .18rem;
}

/* ---------- 0. 顶栏横向菜单的显示阈值 ----------
   真浏览器实测（headless Edge + 同源 iframe 矩阵，运行器见
   scripts/verify/_probe_nav_layout_20261007.py）：
     · 顶栏平铺**全部分组**（管理员 9 个）需要 **1697px** —— 这是「一个固定阈值
       分层/不分层」都会失败的根本原因：任何阈值以下都会浪费空间，用户看到的就是
       「明明还有地方，菜单却折叠了」（2026-10-07 第二轮反馈）。
     · ⇒ 阈值只负责「横排 / 汉堡」这一件事，**不再负责分层**：
         ≥1200 横排（放不下的长尾由 base.html 里的 erpFitTopbar 按真实剩余宽度
         自动搬进「更多 ▾」，1700px 以上一个都不折叠）；
         <1200 退化为「汉堡 + 抽屉」。
     · 为什么下沿取 1200 而不是 992：侧栏在 <992 才消失，992~1199 时顶栏横排虽然
       放得下，但「更多」里会装掉大半、还不如整块换抽屉。1200 是「还能平铺 4~5 个」
       的下沿（实测：1366 时 6 个、1200 时 4 个）。
     抽屉里是**同一份**菜单树（templates/_nav_tree.html）⇒ <1200 菜单一条都没少。
   ⚠️ 为什么不用 `d-lg-*` / `navbar-expand-lg`（lg=992）或 `xxl`（1400）：
     那两个断点是「内容宽度」而非「本页真实剩余宽度」，实测在 992~1439 会溢出
     （见上：全平铺要 1697px）。故阈值只能用自定义媒体查询。
   ⚠️ 权重必须压过 Bootstrap 的 `.navbar-expand-lg .navbar-collapse{display:flex!important}`
     （那是 (0,2,0) 且带 !important）⇒ 这里写成 (0,3,0)，并靠 style.css 在 Bootstrap
     之后加载取胜。别图省事改成 `.erp-nav-topwrap` 单类（会被 Bootstrap 反超）。 */
.erp-navbar .navbar-toggler.erp-nav-burger { display: inline-block !important; }
.erp-navbar .navbar-collapse.erp-nav-topwrap { display: none !important; }

@media (min-width: 1200px) {
    .erp-navbar .navbar-toggler.erp-nav-burger { display: none !important; }
    .erp-navbar .navbar-collapse.erp-nav-topwrap { display: flex !important; }
}

/* ★「更多」的隐藏**必须显式写**：`hidden` 属性只保证 UA 样式表里的 display:none，
   本项目已有一次被作者样式反超的实际教训（见下方仪表盘「经典/图表模式」的注释）。
   这里用 !important 钉死，免得某个主题给 `.nav-item` 写了 display。 */
.erp-navbar .erp-nav-more[hidden] { display: none !important; }

/* ★ 右侧「打印/关于/用户」组在**任何宽度**都必须横排：
   它被刻意放在 collapse 之外（窄屏也要能退出登录 / 切部门 / 切主题），
   而 <992 时 Bootstrap 的 `.navbar-expand-lg .navbar-nav{flex-direction:row}` 不生效，
   默认 `.navbar-nav{flex-direction:column}` 会把它**竖着堆**（实测 768 下三项竖排；
   旧探针只查了 display 没查方向，所以漏掉了）。
   选择器 (0,2,1) 压过 (0,2,0)。 */
.erp-navbar ul.navbar-nav { flex-direction: row; }

/* ---------- 1. 侧栏收起（190px ↔ 56px 图标条）----------
   机制：切 <html> 上的 .erp-sidebar-collapsed ⇒ **只改 --erp-sidebar-width 一个变量**。
   `.erp-sidebar{width}` 与 `.erp-main{margin-left}` 都吃这个变量，故内容区自动跟随，
   零 JS 挪布局（实测：收起后侧栏 190→56、内容区左边界精确跟随、内容区 +134px）。
   ⚠️ 别在这里写 `.erp-main{margin-left:56px}` 之类的第二处几何 —— 那必然会漏掉
      响应式断点或某个主题，两处一漂移就会出现侧栏与内容区错位。 */
html.erp-sidebar-collapsed {
    --erp-sidebar-width: 56px;
}

/* 收起 / 展开箭头 —— **全站唯一的收起入口**（用户 2026-10-07 明确：顶栏不放这个按钮）。
   ① 必须挂在 .erp-sidebar **外面**：侧栏是 overflow-x:hidden，按钮若用 right:-13px
      会被整体裁掉（该 overflow 是 2026-09-28 为裁角标而加的，不能动）；
   ② left 用 calc(变量 - 13px)：位置跟着同一个变量走 ⇒ 收起时自动贴住图标条右缘；
   ③ 位于 fixed-top 导航栏之下，故 z-index 取 102（>侧栏 100，<Bootstrap navbar 1030）。 */
.erp-sidebar-toggle {
    position: fixed;
    left: calc(var(--erp-sidebar-width) - 13px);
    top: calc(var(--erp-navbar-height) + 12px);
    z-index: 102;
    width: 26px;
    height: 26px;
    align-items: center;
    justify-content: center;
    padding: 0;
    border: 1px solid var(--erp-sidebar-border);
    border-radius: 50%;
    background: var(--erp-sidebar-bg);
    color: var(--erp-sidebar-color);
    box-shadow: 0 1px 3px rgba(15, 23, 42, .18);
    transition: left .18s ease, color .15s, background .15s;
}

.erp-sidebar-toggle:hover {
    color: var(--erp-sidebar-hover-color);
    background: var(--erp-sidebar-hover-bg);
}

.erp-sidebar-toggle i { font-size: .8rem; line-height: 1; }
html.erp-sidebar-collapsed .erp-sidebar-toggle i { transform: rotate(180deg); }

/* ---------- 2. 收起态内部：只留图标 ----------
   56px 里放不下「跨仓盘点调整」6 个字（≈82px）+ 数字角标，故：
     文字隐藏、分组箭头换成**分组图标**（只留箭头会变成一个看不见的按钮）、
     数字药丸退化为角上的小圆点（见 .erp-nav-dot）—— 这是刻意的取舍：
     宁可少显示数字，也不能让「有待办」这件事在收起后彻底消失。 */
.erp-nav-grpicon { display: none; }

html.erp-sidebar-collapsed .erp-navtree .erp-nav-label,
html.erp-sidebar-collapsed .erp-sidebar .sidebar-group-toggle > i.bi-chevron-right,
html.erp-sidebar-collapsed .erp-sidebar .erp-nav-badge {
    display: none;
}

html.erp-sidebar-collapsed .erp-sidebar .erp-nav-grpicon { display: inline-block; }

html.erp-sidebar-collapsed .erp-sidebar .erp-sidebar-item,
html.erp-sidebar-collapsed .erp-sidebar .sidebar-group-toggle {
    justify-content: center;
    gap: 0;
    padding-left: 0;
    padding-right: 0;
}

/* 压掉「折叠分组内缩进 2.1rem」（选择器更高权重） */
html.erp-sidebar-collapsed .erp-navtree .collapse .erp-sidebar-item {
    padding-left: 0;
}

/* 收起态的小圆点（数字药丸的退化形态）；只作用于侧栏 —— 顶栏与抽屉不参与收起，
   永久使用数字药丸（`.erp-nav-dot{display:none}` 是它的默认态）。 */
.erp-nav-dot { display: none; }

.erp-sidebar .erp-sidebar-item,
.erp-sidebar .sidebar-group-toggle {
    position: relative;
}

html.erp-sidebar-collapsed .erp-sidebar .erp-nav-dot {
    display: block;
    position: absolute;
    top: 7px;
    right: 13px;
    width: 8px;
    height: 8px;
    border-radius: 50%;
    box-shadow: 0 0 0 2px var(--erp-sidebar-bg);
}

.erp-nav-dot-red { background: var(--bs-danger, #dc3545); }
.erp-nav-dot-blue { background: var(--bs-info, #0dcaf0); }
/* ★ 2026-10-09 第三轮：黄色 = 「本部门单据的申请正在等别人批」（销售方提示视角）。
   圆点用 --bs-warning 的**深一档**色（#ffc107 在白底/浅底上对比太弱，
   8px 的小圆点会糊掉），与红/蓝同为一处定义，勿在别处再写颜色。 */
.erp-nav-dot-amber { background: #e0a800; }

/* ---------- 3. 顶栏下拉（镜像左边栏）---------- */
/* 顶栏项本身的几何（white-space/display/gap/padding）已在 §0.6 定义，此处不重复，
   否则两处一漂移就会出现「改了上面那句没反应」。 */

/* 子菜单面板：窄屏不放，桌面给足宽度；组多时（「更多」）内部滚动而不是撑破视口 */
.erp-topnav .erp-topnav-menu {
    min-width: 15rem;
    max-height: min(70vh, 30rem);
    overflow-y: auto;
}

.erp-topnav-menu .dropdown-item {
    gap: .3rem;
    white-space: nowrap;
}

.erp-topnav-menu .dropdown-header {
    font-weight: 700;
    color: var(--erp-navbar-from);
}

/* 菜单角标（顶栏/侧栏/抽屉共用）：比正文小一档，两位数不竖排 */
.erp-nav-badge {
    font-size: .68rem;
    font-weight: 600;
    line-height: 1.2;
}

/* ---------- 4. 窄屏抽屉（<lg：汉堡 → offcanvas）----------
   与左边栏共用同一份菜单树（templates/_nav_tree.html），故这里只补容器外观：
   抽屉不在 .erp-sidebar 里，拿不到它的背景/文字色变量，需显式对齐。 */
.erp-navdrawer {
    width: min(280px, 85vw);
    background: var(--erp-sidebar-bg);
    color: var(--erp-sidebar-color);
}

.erp-navdrawer .offcanvas-header {
    border-bottom: 1px solid var(--erp-sidebar-border);
}

.erp-navdrawer .offcanvas-body {
    padding: .5rem 0 1rem;
    overflow-y: auto;
}

/* ========== 主内容区 ========== */
.erp-main {
    margin-left: var(--erp-sidebar-width);
    margin-top: var(--erp-navbar-height);
    padding: 1rem 1.5rem 1.5rem 1.5rem; /* 顶部少留一点空间 */
    min-height: calc(100vh - var(--erp-navbar-height));
}

@media (max-width: 991px) {
    .erp-main {
        margin-left: 0;
    }
}

/* ========== 卡片 ========== */
.stat-card {
    background: var(--erp-card-bg);
    border-radius: 12px;
    padding: 1.5rem;
    box-shadow: var(--erp-card-shadow), var(--erp-card-glow);
    border: 1px solid var(--erp-table-border);
    transition: transform 0.15s, box-shadow 0.15s;
    height: 100%;
}

.stat-card:hover {
    transform: translateY(-3px);
    box-shadow: var(--erp-card-shadow), var(--erp-card-glow), 0 14px 34px -14px rgba(0,0,0,0.25);
}

a.stat-card {
    display: block;
    text-decoration: none;
    color: inherit;
}

.stat-card .stat-icon {
    width: 48px;
    height: 48px;
    border-radius: 10px;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 1.5rem;
    flex-shrink: 0;
    /* ★ 2026-10-05：统一走主题色。
       原先仪表盘模板把 15 个图标写成内联 `style="background:#dbeafe;color:#2563eb"`
       （共 10 套互不相同的浅色对），与当前主题完全无关 —— 换成深色/3D 主题后
       仍是浅蓝/浅绿/浅黄小方块，正是「同一主题下不同颜色渲染」的典型。
       现由这里统一提供主题渐变底 + 白图标；模板内联样式已同步删除。
       变量兜底链：3D 主题无 `--erp-grad-*` 之外的 9 个主题走 navbar 主色，
       保证 14 套主题下都有底色，不会退化成透明。 */
    background: linear-gradient(135deg,
        var(--erp-grad-from, var(--erp-navbar-from)) 0%,
        var(--erp-grad-to, var(--erp-accent)) 100%);
    color: #fff;
    box-shadow: 0 2px 10px -3px var(--erp-accent);
}

.stat-card .stat-value {
    font-size: 1.8rem;
    font-weight: 700;
    color: var(--erp-text);
    line-height: 1.2;
}

.stat-card .stat-label {
    color: var(--erp-text-muted);
    font-size: 0.85rem;
    margin-top: 2px;
}

/* 普通卡片（系统设置/详情页等）跟随主题 */
.card.erp-card {
    background: var(--erp-card-bg);
    box-shadow: var(--erp-card-shadow), var(--erp-card-glow);
    border-color: var(--erp-table-border);
}

/* ========== 登录页面 ========== */
.erp-login-bg {
    min-height: 100vh;
    background: var(--erp-bg);
}

.login-wrapper {
    display: flex;
    min-height: 100vh;
}

.login-brand {
    flex: 1 1 55%;
    position: relative;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 3rem;
    background: linear-gradient(135deg, var(--erp-primary) 0%, var(--erp-navbar-from) 55%, var(--erp-accent) 100%);
    color: #fff;
    overflow: hidden;
}

.login-brand-inner {
    position: relative;
    z-index: 2;
    max-width: 520px;
}

/* 品牌区深色遮罩：保证白色文字在亮色 accent 渐变上仍清晰 */
.login-brand::before {
    content: "";
    position: absolute;
    inset: 0;
    background: linear-gradient(135deg, rgba(0,0,0,0.10) 0%, rgba(0,0,0,0.30) 100%);
    z-index: 1;
}

/* ⚠️ 2026-10-08 弃用：登录页 LOGO 已按用户要求整块删除（login.html 的
   .login-brand-inner 里不再有 .brand-logo）。规则暂留，便于一行回退。
   ★ 它本来是 168×168 的 flex 容器、只负责居中里面那张 img，整块删除是安全的
     （父级 .login-brand 是 align-items:center 的 flex，内容会自动重新垂直居中，
      不需要补任何 margin 占位）。 */
.brand-logo {
    width: 168px;
    height: 168px;
    display: flex;
    align-items: center;
    justify-content: center;
    margin-bottom: 1.75rem;
    background: transparent;
    border: 0;
    backdrop-filter: none;
}
.brand-logo img {
    width: 100%;
    height: 100%;
    object-fit: contain;
    display: block;
    filter: drop-shadow(0 2px 8px rgba(0, 0, 0, 0.35));
}

.login-brand h1 {
    /* 2026-10-10 第六版：**纯白**。
       用户原话「把"智造ERP"还是改为纯白色」，即第五版的「白字 + 绿描边 +
       绿外发光」在深色底上仍被看成一层绿雾、不是纯白，故本次把描边与发光
       **整个删掉**，只留 color:#ffffff 的字面本身。
       ★ 教训：`-webkit-text-stroke` + `text-shadow` 的绿即使透明度压到 .16~.30，
         在大字号（3.05rem）下仍会明显染绿字缘 —— 要"纯"就别留任何描边/发光。 */
    font-size: 3.05rem;
    font-weight: 800;
    margin-bottom: 0.5rem;
    letter-spacing: 1px;
    color: #ffffff;
    padding: 0.08em 0.1em 0.12em 0;
}






.brand-subtitle {
    font-size: 1.15rem;
    color: rgba(255, 255, 255, 0.78);
    margin-bottom: 2.5rem;
}

/* ★★ 水印大字「大处着眼 · 小处着手」（2026-10-04）
   透明度刻意压得很低（.08~.13），只在余光里浮现，不抢标题与特性列表的注意力。
   用 transform 轻微旋转，让它像"印在背景上"而非正文的一部分。 */
.brand-watermark {
    position: absolute;
    /* 放在品牌区右下方，避开 logo / 标题 / 特性列表（那些是 z-index:2 的内容层） */
    /* ★ 2026-10-04 截图实证：右/下两截被容器裁掉 ⇒ 往左上收。
       负值是"出血"，会往外溢出；这里要的是整体移进可视区，故用较小的负偏移，
       靠 max-width + 字号缩小确保两行都完整可见。 */
    right: 1.4rem;
    bottom: 0.9rem;
    z-index: 1;                 /* 与 ::before 同层 ⇒ 位于渐变遮罩之下、看起来更"沉" */
    display: flex;
    flex-direction: column;
    align-items: flex-end;
    line-height: 1.02;
    pointer-events: none;       /* 纯装饰，不吃点击、不影响表单交互 */
    user-select: none;          /* 别让用户误选中复制 */
    transform: rotate(-7deg);
}

.brand-watermark .wm-line {
    display: block;
    /* ★ 两行统一 3.9rem（原 4.1 / 3.35 不一致，第二行明显小一号）。
       line-height 交给 .brand-watermark 的 1.02 + .wm-line-2 的 margin-top。 */
    font-size: 3.9rem;
    font-weight: 900;
    letter-spacing: 4px;
    white-space: nowrap;
    /* ★ 极低透明度 = 水印感。实测 0.085 在深蓝底上仍偏亮（截图实证）⇒ 压到 0.05，
       真正「只在余光里浮现」。两行再各自微调，第二行更淡制造层次。 */
    color: rgba(255, 255, 255, 0.05);
    text-shadow: 0 2px 22px rgba(0, 0, 0, 0.30);
}

.brand-watermark .wm-line-2 {
    color: rgba(255, 255, 255, 0.075);
    /* 与第一行等宽后错位改用 margin：向左偏一点点，两行仍成组、不散架 */
    /* ★ 原来 margin-top:-0.25rem 让两行贴太紧、糊成一块 ⇒ 改为 +0.45rem 拉开。
       同字号下 0.45rem 约等于行高的 11%，看着舒展又不散。 */
    margin-top: 0.45rem;
    /* ★ 不要 padding-right 把它往右顶 —— 那会让「手」字被容器裁掉（截图实证） */
    padding-right: 0;
    font-size: 3.9rem;
}

.brand-divider {
    /* ★ 2026-10-04 用户要求：在原 210px 基础上再加长 50% ⇒ 315px。
       （最初 64px 远短于标题 → 210px 与标题齐 → 本次再放大 1.5 倍做强调线） */
    width: 315px;
    max-width: 100%;
    height: 4px;
    border-radius: 2px;
    background: rgba(255, 255, 255, 0.4);
    margin-bottom: 2rem;
}

.brand-features {
    list-style: none;
    padding: 0;
    margin: 0;
    font-size: 1rem;
    color: rgba(255, 255, 255, 0.85);
}

.brand-features li {
    margin-bottom: 0.9rem;
    display: flex;
    align-items: center;
    gap: 0.75rem;
}

.brand-features li i {
    color: #60a5fa;
    font-size: 1.1rem;
}

.brand-shape {
    position: absolute;
    border-radius: 50%;
    background: rgba(255, 255, 255, 0.04);
    z-index: 1;
}

.brand-shape.shape-1 {
    width: 420px;
    height: 420px;
    top: -120px;
    right: -80px;
}

.brand-shape.shape-2 {
    width: 300px;
    height: 300px;
    bottom: -60px;
    left: -60px;
}

.brand-shape.shape-3 {
    width: 160px;
    height: 160px;
    top: 40%;
    right: 12%;
    background: color-mix(in srgb, var(--erp-accent) 22%, transparent);
}

.login-form-panel {
    flex: 1 1 45%;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    padding: 2rem;
    background: var(--erp-card-bg);
    position: relative;
}

.login-form-card {
    width: 100%;
    max-width: 420px;
    padding: 2.5rem 0.5rem;
}

.form-header {
    margin-bottom: 1.75rem;
}

.form-header h2 {
    font-size: 1.75rem;
    font-weight: 700;
    color: var(--erp-text);
    margin-bottom: 0.35rem;
}

.form-header p {
    color: var(--erp-text-muted);
    font-size: 0.95rem;
    margin-bottom: 0;
}

.login-form-card .form-label {
    font-size: 0.85rem;
    font-weight: 500;
    color: var(--erp-table-head-color);
    margin-bottom: 0.4rem;
}

.login-form-card .form-control {
    padding: 0.75rem 0.9rem;
    font-size: 0.95rem;
    border-color: var(--erp-table-border);
}

.login-form-card .form-control:focus {
    border-color: var(--erp-accent);
    box-shadow: 0 0 0 0.2rem color-mix(in srgb, var(--erp-accent) 12%, transparent);
}

.login-form-card .input-group-text {
    background: var(--erp-sidebar-bg);
    border-color: var(--erp-table-border);
    color: var(--erp-text-muted);
}

.login-form-card .btn-primary {
    background: linear-gradient(135deg, var(--erp-accent), var(--erp-primary));
    border: none;
    padding: 0.8rem;
    font-size: 1rem;
    font-weight: 600;
    border-radius: 0.5rem;
    transition: transform 0.15s ease, box-shadow 0.15s ease;
}

.login-form-card .btn-primary:hover {
    transform: translateY(-1px);
    box-shadow: 0 8px 20px color-mix(in srgb, var(--erp-accent) 30%, transparent);
}

.login-hint {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    background: var(--erp-sidebar-active-bg);
    border: 1px solid color-mix(in srgb, var(--erp-accent) 25%, transparent);
    border-radius: 8px;
    padding: 0.75rem 1rem;
    font-size: 0.8rem;
    color: var(--erp-sidebar-active-color);
}

.login-hint i {
    font-size: 1rem;
}

.login-hint code {
    color: var(--erp-accent);
    font-weight: 600;
    background: color-mix(in srgb, var(--erp-card-bg) 70%, transparent);
    padding: 0.1rem 0.35rem;
    border-radius: 4px;
}

.login-footer {
    position: absolute;
    bottom: 1.25rem;
    color: var(--erp-text-muted);
    font-size: 0.8rem;
    text-align: center;
}

@media (max-width: 991.98px) {
    .login-wrapper {
        flex-direction: column;
    }
    .login-brand {
        flex: 0 0 auto;
        min-height: 240px;
        padding: 2rem;
        text-align: center;
    }
    .login-brand-inner {
        max-width: 100%;
    }
    /* ⚠️ 2026-10-08 随 .brand-logo 一并弃用（登录页已无 LOGO） */
    .brand-logo {
        width: 128px;
        height: 128px;
        margin: 0 auto 1.25rem;
    }
    .brand-divider {
        margin-left: auto;
        margin-right: auto;
    }
    .brand-features {
        display: inline-block;
        text-align: left;
    }
    .brand-features li {
        justify-content: flex-start;
    }
    .login-form-panel {
        flex: 1 1 auto;
        padding: 1.5rem;
    }
    .login-form-card {
        padding: 1.5rem 0;
    }
    .login-footer {
        position: static;
        margin-top: 1.5rem;
    }
}

@media (max-width: 575.98px) {
    .login-brand h1 {
        font-size: 2rem;
    }
    .brand-subtitle {
        font-size: 1rem;
    }
    .brand-features {
        font-size: 0.9rem;
    }
}

/* ========== 筛选栏（自动生效 + 强制单行） ==========
   ★★★ 用户要求（2026-10-04）：「筛选排版都只在一行，跨行的调整宽度」。

   ★★★★ 本段踩了 4 个坑（只有浏览器实测才发现，务必记住）：
   ① **属性选择器大小写敏感**：模板写 `method="GET"`（大写），而
      `form[method="get"]` 大小写敏感 ⇒ 规则一次都没命中。
      连 CSS4 的 `[method="GET" i]` 也不行 —— headless Edge 实测
      `matches('...[i]')` 返回 **false**。⇒ **大小写两种都要写**。
   ② ★★ **逗号是「选择器列表」的分隔符，不是「并且」**：
      `form[method="GET"], form[method="get"].row` 解析成
      「所有 GET form」 **OR** 「method=get 且有 .row」—— 语义完全错。
      正确：每个完整选择器各自重复前缀 `form[method="GET"].row, form[method="get"].row { }`。
   ③ **flex 等分治不了多列**：试过 `flex:1 1 0` / `flex:1 1 auto` / `:has()` /
      `box-sizing` 四种办法，仍因差 1~3px 换行（6×182 + 82 = 1174 > 1173）。
   ④ ★★ **决定性方案：清除按钮用绝对定位**，不占栅格位。
      `.row` 是 `position:relative`（Bootstrap 5 默认），把清除列
      `position:absolute; right:0; top:0` ⇒ **完全不参与 flex 布局**，
      既不会挤掉其它列、也不会自己换行。筛选控件则留出右侧余量
      （`padding-right` 给按钮腾位）。

   ★ 窄屏（<768px）恢复普通流（position:static）—— 手机上横排 7 个框没法用。 */
@media (min-width: 768px) {
    /* 筛选栏定位上下文：清除按钮要绝对定位到右上角 */
    form[method="GET"].row,
    form[method="get"].row {
        flex-wrap: nowrap;
        position: relative;
        /* ★★ 2026-10-05：删掉 `padding-right: 100px`。
           那是"清除按钮绝对定位到右上角"时代的留白（绝对定位 = 不参与 flex
           布局，必须在容器右侧留出按钮位置）。而清除按钮早已改成**流内元素**
           （报表页在「核算部门」列内、其它页独占一个 `col-auto` 列），
           这段 padding 只白白吃掉筛选栏右侧 100px 可用宽度，
           逼着固定百分比宽度的筛选列把内容挤出容器 ⇒ 换行/悬空。
           同时更正注释：这里不再需要"定位上下文"，保留 `position: relative`
           仅为兼容可能存在的其它绝对定位子元素。 */
    }
    /* 清除按钮本身：贴底对齐（与筛选框同一水平线） */
    form[method="GET"].row [class*="erp-clear-filter"],
    form[method="get"].row [class*="erp-clear-filter"],
    form[method="GET"].row .btn-outline-secondary,
    form[method="get"].row .btn-outline-secondary {
        display: inline-block;
        width: auto;
        margin: 0;
        white-space: nowrap;
    }
}
/* 筛选控件撑满所在列；长 placeholder 靠省略号而不是撑破容器 */
form[method="GET"].row .form-control,
form[method="get"].row .form-control,
form[method="GET"].row .form-select,
form[method="get"].row .form-select {
    width: 100%;
    min-width: 0;
}
form[method="GET"].row .form-label,
form[method="get"].row .form-label {
    /* ★ 2026-10-05 顶端对齐根因：label 默认 inline，行盒高度被父级 strut 撑高
       （14px 文本占 ~27px 行盒），而 .erp-has-clear 列是 flex 容器、label 变
       flex item 无 strut ⇒ 标签行差 6px、输入框不在一条线上。
       display:block 后所有列统一为「行高 21px + margin-bottom 8px」。 */
    display: block;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* ========== 锁定部门框（报表页「核算部门」） ==========
   ★★ 2026-10-04：用户要「锁定图标放到核算部门框边上」。
   根因：原来用 Bootstrap `.input-group` + `max-width:14rem`，而 `.input-group`
   是 `display:flex; flex-wrap:wrap` ⇒ 限宽后图标与输入框**上下换行**
   （浏览器实测 group 高 62px、图标 top=142 / 输入框 top=173），
   看起来就像"图标飘在框外面"。
   ✅ 改法：图标**绝对定位**贴在输入框左内侧，不占布局宽度；
   输入框用 `padding-left` 给图标让位。这样图标真正"在框边上"，
   无论列宽怎么变都不会换行。 */
.erp-locked-dept {
    position: relative;
    min-width: 10rem;
}
.erp-locked-dept .erp-locked-dept-icon {
    position: absolute;
    left: 0;
    top: 0;
    bottom: 0;
    /* 宽度与 .form-control-sm 的左内边距对齐 ⇒ 图标正好落在"框内左侧" */
    display: flex;
    align-items: center;
    padding: 0 0 0 0.5rem;
    color: var(--erp-text-muted, #6c757d);
    pointer-events: none;   /* 不吃点击，悬停 title 仍由父级 .erp-locked-dept 承担 */
}
/* ★ 输入框左侧留出图标空间（form-control-sm 默认 padding-left 约 0.5rem，不够） */
.erp-locked-dept .form-control {
    padding-left: 1.6rem;
}

/* ========== 报表页筛选栏（核算部门 + 清除筛选） ==========
    /* ★★ 2026-10-05 用户要求：「核算部门框和清除筛选按钮要放到月份边上」。

       ★★★ **本段连续返工 3 次才收口，根因链如下（务必记住）**：
       ① 报表页末尾有个说明文字列 `class="col-auto ms-auto"`，
          `ms-auto` = `margin-left:auto` ⇒ 吃掉筛选栏全部剩余空间。
       ② 隐藏「查询」按钮后，它的**宿主列仍占位 8px**（空列），
          而 `.row` 是 flex ⇒ 空列把**核算部门列顶到最右**。
       ③ 给部门列加 `padding-right:96px` 给清除按钮留位 ⇒ 列被撑到 **291px**，
          反而让它在 flex 里占更宽、位置更靠右。
       ✅ 最终解法（三处同时做，缺一不可）：
          a. 模板去掉那 4 页说明文字列的 `ms-auto`；
          b. `base.html` 脚本：按钮隐藏时**连带隐藏它的宿主列**（不留空列）；
          c. ★ 清除按钮**不再绝对定位**，改为**流内**排在该列下方一行
             （`d-flex justify-content-end`），列宽回到内容宽、不再被撑开。

       ★ 教训：flex 布局里"给某个元素留白"的正确姿势是
       **让容器跟着内容走**（流内换行），而不是给容器加 padding /
       用绝对定位 —— 后两者都会改变该元素在 flex 里的宽度分配。
       ★ 采购/销售/生产等页面的 `ms-auto` **保持原样**（正常设计）。

       ★★ 2026-10-05：本段（`.erp-has-clear`）现在**只作用于报表页的「核算部门」列**
       （base.html 里只有"找到 .erp-locked-dept / select[name=dept_id] 列"这一支
       才会加这个 class）。其它页的清除按钮改为**独占一个 `col-auto` 列**、不再塞进
       已有筛选列 —— 因为那些列的宽度是内联百分比/`col-md-2`，装不下第二个控件。
       ⇒ 维护时注意：改这里的 flex 规则只影响报表页，不会波及普通列表页。 */
    form[method="GET"].row > .erp-has-clear {
        position: static;      /* 不再作为绝对定位的参照系 */
        /* ★★★ 2026-10-05 v4：从 `display:flex; flex-wrap:wrap` 换成 **grid 两列**。
           为什么 flex 方案一定失败（这正是"还是有问题"连返工两轮的根因）：
             该列是 `col-auto`（shrink-to-fit），而 flex 的**换行判定用的是
             flex base size 之和**：输入框 `width:100%` ⇒ base = 整列宽 270px，
             再加按钮 74px = 350 > 270 ⇒ **必然换行**（浏览器实测：
             输入框 top=136 / 清除按钮 top=167，两行）。
             而把输入框改成 `flex:1 1 0` 也不行：整列 max-content 会缩到
             0+6+74=80px，再被 `min-width:8rem` 夹回 128px ⇒ 依然装不下，
             反而把核算部门框压得更窄。
             （本质：容器宽度由内容决定、内容又依赖容器宽度 ⇒ 循环，
             浏览器只能给出自相矛盾的答案。）
           ✅ grid 不做换行判定：列宽 = 各列 max-content 之和
             （270 + 6 + 74 = 350），第一列拿 `1fr`、第二列拿 `auto`
             ⇒ [🔒核算部门输入框][清除筛选] 一行放定，永不换行。
           子元素：label 跨两列（`grid-column:1/-1`）独占第一行。 */
        display: grid;
        grid-template-columns: minmax(8rem, 1fr) auto;
        align-items: end;
        column-gap: 6px;
    }
    /* 标签独占第一行（跨两列） */
    form[method="GET"].row > .erp-has-clear > .form-label {
        grid-column: 1 / -1;
    }
    /* 输入框 / 下拉占第一列（1fr，最小 8rem，实际宽度由 grid 分配） */
    form[method="GET"].row > .erp-has-clear > .erp-locked-dept,
    form[method="GET"].row > .erp-has-clear > select {
        min-width: 8rem;
    }
    /* 清除按钮：占第二列、贴输入框右侧、底边对齐 */
    form[method="GET"].row > .erp-has-clear > .erp-clear-filter {
        margin: 0;
        width: auto;
        white-space: nowrap;
    }


/* ========== 表格 ========== */
.table thead th {
    background: var(--erp-table-head-bg);
    color: var(--erp-table-head-color);
    font-weight: 600;
    font-size: 0.8rem;
    text-transform: uppercase;
    letter-spacing: 0.5px;
    border-bottom: 2px solid var(--erp-table-border);
    white-space: nowrap;
    text-align: center;
}

.table td {
    vertical-align: middle;
    font-size: 0.875rem;
    text-align: center;
}

/* ERP 统一列表表格：固定列宽，防止内容挤在一起 */
.table.erp-table {
    table-layout: fixed;
    width: 100%;
    min-width: 960px;
}

.table.erp-table thead th,
.table.erp-table tbody td {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* 常用列宽（可按页面组合使用） */
.col-select { width: 40px; text-align: center; }
.col-no { width: 130px; }
.col-code { width: 110px; }
.col-date { width: 95px; }
.col-status { width: 80px; text-align: center; }
.col-creator { width: 80px; }
.col-amount { width: 110px; text-align: center; }
.col-weight { width: 100px; text-align: center; }
.col-qty { width: 90px; text-align: center; }
.col-price { width: 100px; text-align: center; }
.col-actions {
    width: 120px !important;
    text-align: center !important;
    white-space: nowrap;
}

/* 仅明细行的单号/编码左对齐，表头保持居中 */
.table tbody td.col-no,
.table tbody td.col-code {
    text-align: left !important;
}

/* 操作列按钮统一不换行、居中、等间距 */
.col-actions .btn,
td.col-actions .btn,
th.col-actions .btn {
    margin: 0 2px;
    padding: 0.25rem 0.45rem;
}

/* 操作列容器：让按钮始终在一行，无按钮时也占住高度 */
.actions-cell {
    display: flex;
    justify-content: center;
    align-items: center;
    gap: 4px;
    min-height: 31px;
}

/* 长文本单元格截断 */
.cell-truncate {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    max-width: 100%;
    display: inline-block;
    vertical-align: middle;
}

/* 数字/金额统一居中对齐（与表头/明细行保持一致） */
.table.erp-table .text-end,
.table.erp-table th.text-end {
    text-align: center !important;
}

/* 分页与表格间距 */
.table-responsive + nav,
.table-responsive + .pagination {
    margin-top: 1rem;
}

/* ========== 按钮 ========== */
.btn-sm {
    font-size: 0.8rem;
    padding: 0.25rem 0.6rem;
}

/* ========== 页面标题 ========== */
.page-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin-bottom: 1.5rem;
    flex-wrap: wrap;
    gap: 0.5rem;
}

.page-header h4 {
    margin: 0;
    font-weight: 700;
    color: var(--erp-text);
}

.page-header .breadcrumb {
    margin: 0;
    font-size: 0.85rem;
}

/* ========== 状态标签 ========== */
.status-badge {
    font-size: 0.75rem;
    padding: 0.2em 0.6em;
    border-radius: 4px;
    font-weight: 600;
}

/* ========== 采购订单明细表 ========== */
.po-item-row {
    background: var(--erp-sidebar-bg);
}

.po-item-row td {
    background: transparent;
}

/* ========== 金额显示 ========== */
.amount {
    font-family: "Courier New", monospace;
    font-weight: 600;
}

.amount-total {
    font-size: 1.2rem;
    color: #dc2626;
}

/* ========== 空状态 ========== */
.empty-state {
    text-align: center;
    padding: 3rem 1rem;
    color: var(--erp-text-muted);
}

.empty-state i {
    font-size: 3rem;
    margin-bottom: 1rem;
}

/* ========== 库存状态 ========== */
.stock-danger { color: #dc2626; font-weight: 600; }
.stock-warning { color: #d97706; font-weight: 600; }
.stock-success { color: #059669; font-weight: 600; }

/* ========== 可折叠说明框 ========== */
.alert-details {
  border: 1px solid transparent;
  border-radius: 0.375rem;
  padding: 0.5rem 0.75rem;
}
.alert-details summary {
  cursor: pointer;
  list-style: none;
  user-select: none;
  font-weight: 500;
}
.alert-details summary::-webkit-details-marker {
  display: none;
}
.alert-details summary::before {
  content: "\f282";
  font-family: "bootstrap-icons";
  display: inline-block;
  margin-right: 0.35rem;
  font-size: 0.8em;
  transition: transform 0.2s;
  vertical-align: middle;
}
.alert-details[open] summary::before {
  transform: rotate(180deg);
}
.alert-details > div {
  margin-top: 0.75rem;
}
.alert-details.alert-info { background-color: #cff4fc; border-color: #b6effb; color: #055160; }
.alert-details.alert-warning { background-color: #fff3cd; border-color: #ffecb5; color: #664d03; }
.alert-details.alert-success { background-color: #d1e7dd; border-color: #badbcc; color: #0f5132; }

/* ========== 统一日期输入框 placeholder 为 yyyy-mm-dd ========== */
.date-input-wrap {
    position: relative;
    display: block;
    width: 100%;
}
.date-input-wrap > input[type="date"] {
    width: 100%;
}
.date-input-wrap .date-placeholder-text {
    position: absolute;
    left: 0.75rem;
    top: 50%;
    transform: translateY(-50%);
    color: var(--erp-text-muted);
    pointer-events: none;
    background: var(--erp-card-bg);
    padding-right: 0.5rem;
    white-space: nowrap;
    font-size: 1rem;
    line-height: 1.5;
    display: none;
}
.date-input-wrap.show-placeholder .date-placeholder-text {
    display: block;
}
.date-input-wrap.show-placeholder > input[type="date"]::-webkit-datetime-edit {
    color: transparent;
}
.date-input-wrap.show-placeholder > input[type="date"]:focus::-webkit-datetime-edit {
    color: inherit;
}
.alert-details.alert-light { background-color: #f8f9fa; border-color: #e9ecef; color: var(--erp-text-muted); }

/* ========== 深色主题适配 ========== */
/* 折叠说明框：深色主题下用半透明语义色，避免刺眼的浅色底 */
[data-bs-theme="dark"] .alert-details.alert-info {
    background-color: rgba(13, 202, 240, 0.12);
    border-color: rgba(13, 202, 240, 0.28);
    color: #9ee7f5;
}
[data-bs-theme="dark"] .alert-details.alert-warning {
    background-color: rgba(255, 193, 7, 0.12);
    border-color: rgba(255, 193, 7, 0.28);
    color: #f5d78e;
}
[data-bs-theme="dark"] .alert-details.alert-success {
    background-color: rgba(25, 135, 84, 0.15);
    border-color: rgba(25, 135, 84, 0.30);
    color: #9fe0c2;
}
[data-bs-theme="dark"] .alert-details.alert-light {
    background-color: rgba(248, 249, 250, 0.08);
    border-color: rgba(248, 249, 250, 0.15);
    color: #b6bfc8;
}
/* 深色下 date 输入框占位文本背景对齐卡片底色（form-control 由 Bootstrap 深色化） */
[data-bs-theme="dark"] .date-input-wrap .date-placeholder-text {
    background: var(--erp-card-bg);
}
/* 深色下状态标签色微调保证可读 */
[data-bs-theme="dark"] .text-muted-50 { color: var(--erp-text-muted); }
/* 深色下统一提升 Bootstrap muted 文字亮度（text-muted/form-text/placeholder 等） */
[data-bs-theme="dark"] .text-muted,
[data-bs-theme="dark"] .text-secondary,
[data-bs-theme="dark"] .form-text {
    color: var(--erp-text-muted) !important;
}

/* ========== 主题选择器（系统设置页） ========== */
.theme-card {
    display: flex;
    flex-direction: column;
    cursor: pointer;
    border: 2px solid var(--erp-table-border);
    border-radius: 10px;
    padding: 0.75rem;
    background: var(--erp-card-bg);
    transition: border-color 0.15s, box-shadow 0.15s;
    margin-bottom: 0;
    position: relative;
}
.theme-card:hover { border-color: var(--erp-accent); }
.theme-card.active {
    border-color: var(--erp-accent);
    box-shadow: 0 0 0 3px color-mix(in srgb, var(--erp-accent) 15%, transparent);
}
.theme-card input[type="radio"] {
    position: absolute;
    opacity: 0;
    pointer-events: none;
}
.theme-preview {
    height: 48px;
    border-radius: 6px;
    display: flex;
    align-items: flex-end;
    padding: 6px;
    margin-bottom: 8px;
    box-shadow: inset 0 1px 0 rgba(255,255,255,0.35), inset 0 -2px 6px rgba(0,0,0,0.12);
}
.theme-preview .theme-dot {
    width: 20px;
    height: 20px;
    border-radius: 50%;
    border: 1px solid rgba(255, 255, 255, 0.55);
}
.theme-preview .theme-accent {
    width: 20px;
    height: 20px;
    border-radius: 50%;
    margin-left: 6px;
    border: 1px solid rgba(255, 255, 255, 0.55);
}
.theme-name { font-weight: 600; font-size: 0.9rem; color: var(--erp-text); }
.theme-desc { font-size: 0.75rem; color: var(--erp-text-muted); }

/* ============================================================
   3D 立体增强（仅 3D 主题生效，id 以 "3d-" 开头）
   - 侧边栏导航：立体渐变背景框（hover/active）
   - 卡片头部 / 表格头部 / 主按钮 / 徽标：渐变 + 高光
   - 导航栏：顶部高光线条 + 更深投影
   ============================================================ */

/* ---------- 侧边栏：渐变背景框 ---------- */

/* 主菜单分组触发器：保持与侧边栏同宽，视觉上是“一级卡片” */
[data-theme^="3d-"] .sidebar-group-toggle {
    border-left: none;
    border-radius: 10px;
    width: calc(100% - 12px);
    margin: 2px 6px;
    padding: 0.5rem 0.55rem;
    transition: all 0.18s ease;
    font-weight: 700;
    font-size: 0.9rem;
    letter-spacing: 0;
    white-space: nowrap;
    overflow: visible;
}

[data-theme^="3d-"] .sidebar-group-toggle:hover {
    background: linear-gradient(135deg, var(--erp-grad-from) 0%, var(--erp-grad-to) 100%);
    color: #fff;
    text-shadow: 0 1px 2px rgba(0,0,0,0.35);
    box-shadow: 0 4px 12px -4px var(--erp-accent), inset 0 1px 0 rgba(255,255,255,0.25);
}
[data-theme^="3d-"] .sidebar-group-toggle[aria-expanded="true"],
[data-theme^="3d-"] .sidebar-group-toggle.open {
    background: linear-gradient(135deg, var(--erp-grad-from) 0%, var(--erp-grad-to) 100%);
    color: #fff;
    text-shadow: 0 1px 2px rgba(0,0,0,0.35);
    box-shadow: 0 4px 12px -4px var(--erp-accent), inset 0 1px 0 rgba(255,255,255,0.25);
}

/* 子菜单项：比主菜单窄，体现层级从属关系 */
[data-theme^="3d-"] .erp-sidebar-item {
    border-left: none;
    border-radius: 8px;
    margin: 2px 8px 2px 14px;
    padding: 0.55rem 0.75rem;
    transition: all 0.18s ease;
    font-weight: 600;
    font-size: 0.85rem;
}

/* 覆盖默认的折叠内缩进，改用整体 box 缩进 */
[data-theme^="3d-"] .erp-sidebar .collapse .erp-sidebar-item {
    padding-left: 0.75rem;
}

/* 顶级直达项（如「工资表」）：沿用分组触发器的一级卡片尺寸，但可直接点击 */
[data-theme^="3d-"] .erp-sidebar .erp-sidebar-toplink {
    margin: 2px 6px;
    padding: 0.5rem 0.55rem;
    border-radius: 10px;
    font-size: 0.9rem;
    letter-spacing: 0;
}

[data-theme^="3d-"] .erp-sidebar-item i {
    font-size: 1rem;
}

/* 菜单项：hover 渐变背景框 + 上浮 */
[data-theme^="3d-"] .erp-sidebar-item:hover {
    background: linear-gradient(135deg, var(--erp-grad-from) 0%, var(--erp-grad-to) 100%);
    color: #fff;
    text-shadow: 0 1px 2px rgba(0,0,0,0.35);
    box-shadow: 0 4px 14px -4px var(--erp-accent), inset 0 1px 0 rgba(255,255,255,0.28);
    transform: translateX(3px);
}
/* 菜单项：active 渐变背景框 + 立体按压感 */
[data-theme^="3d-"] .erp-sidebar-item.active {
    background: linear-gradient(135deg, var(--erp-grad-from) 0%, var(--erp-grad-to) 100%);
    color: #fff;
    font-weight: 700;
    text-shadow: 0 1px 2px rgba(0,0,0,0.35);
    box-shadow: 0 5px 16px -4px var(--erp-accent),
                inset 0 1px 0 rgba(255,255,255,0.32),
                inset 0 -3px 6px rgba(0,0,0,0.18);
    transform: translateX(3px);
}

/* ---------- 卡片头部：高级立体渐变框 ---------- */
[data-theme^="3d-"] .card-header.bg-light {
    position: relative;
    background:
        linear-gradient(180deg, rgba(255,255,255,0.06) 0%, rgba(255,255,255,0) 100%),
        rgba(15, 23, 42, 0.72) !important;
    color: #fff !important;
    border-bottom: 1px solid transparent;
    border-radius: 12px 12px 0 0;
    padding: 0.9rem 1.1rem;
    text-shadow: 0 1px 3px rgba(0,0,0,0.45);
    box-shadow:
        inset 0 1px 0 rgba(255,255,255,0.12),
        inset 0 -1px 0 rgba(0,0,0,0.18),
        0 4px 14px -6px rgba(0,0,0,0.35);
    overflow: hidden;
}

/* 左侧高光条 */
[data-theme^="3d-"] .card-header.bg-light::before {
    content: "";
    position: absolute;
    left: 0;
    top: 12%;
    bottom: 12%;
    width: 4px;
    border-radius: 0 4px 4px 0;
    background: linear-gradient(180deg, var(--erp-grad-from) 0%, var(--erp-accent) 50%, var(--erp-grad-to) 100%);
    box-shadow: 0 0 10px var(--erp-accent);
}

/* 底部渐变光带 */
[data-theme^="3d-"] .card-header.bg-light::after {
    content: "";
    position: absolute;
    left: 0;
    right: 0;
    bottom: 0;
    height: 2px;
    background: linear-gradient(90deg,
        transparent 0%,
        var(--erp-grad-from) 15%,
        var(--erp-accent) 50%,
        var(--erp-grad-to) 85%,
        transparent 100%);
    opacity: 0.85;
}

[data-theme^="3d-"] .card-header.bg-light h5,
[data-theme^="3d-"] .card-header.bg-light h6,
[data-theme^="3d-"] .card-header.bg-light strong {
    color: #fff !important;
    font-weight: 600;
    letter-spacing: 0.3px;
    position: relative;
    z-index: 1;
}

[data-theme^="3d-"] .card-header.bg-light .bi,
[data-theme^="3d-"] .card-header.bg-light i {
    color: var(--erp-accent);
    margin-right: 0.45rem;
    filter: drop-shadow(0 0 4px var(--erp-accent));
}

/* ============================================================
   库存总览仓库分组表头：沉浸式 3D 主题卡片头部
   与右侧汇总徽章形成统一的“高级舱室”视觉层级
   ============================================================ */
/* ============================================================
   3D 主题分组卡片头部（库存总览仓库 / 仓库管理部门 / 其他分组卡片）
   ============================================================ */
[data-theme^="3d-"] .card-header.inventory-wh-header,
[data-theme^="3d-"] .card-header.warehouse-dept-header,
[data-theme^="3d-"] .card-header.group-card-header {
    position: relative;
    background:
        /* 顶部高光层 */
        linear-gradient(180deg, rgba(255,255,255,0.28) 0%, rgba(255,255,255,0) 40%),
        /* 斜向光泽 */
        linear-gradient(135deg, rgba(255,255,255,0.14) 0%, rgba(255,255,255,0) 45%),
        /* 主题主渐变 */
        linear-gradient(90deg, var(--erp-grad-from) 0%, var(--erp-grad-to) 100%) !important;
    color: #fff !important;
    border-bottom: 1px solid rgba(255,255,255,0.22);
    border-radius: 14px 14px 0 0;
    padding: 0.85rem 1.15rem;
    box-shadow:
        /* 内嵌顶部高光 */
        inset 0 1px 0 rgba(255,255,255,0.35),
        inset 0 -1px 0 rgba(0,0,0,0.22),
        /* 外悬浮投影 */
        0 10px 28px -8px rgba(0,0,0,0.45),
        /* 主题辉光 */
        0 0 28px -6px var(--erp-accent);
    overflow: hidden;
    transform: translateZ(0);
}

/* 动态光泽扫过效果 */
[data-theme^="3d-"] .card-header.inventory-wh-header::before,
[data-theme^="3d-"] .card-header.warehouse-dept-header::before,
[data-theme^="3d-"] .card-header.group-card-header::before {
    content: "";
    position: absolute;
    left: -100%;
    top: 0;
    bottom: 0;
    width: 60%;
    background: linear-gradient(90deg,
        transparent 0%,
        rgba(255,255,255,0.18) 50%,
        transparent 100%);
    transform: skewX(-20deg);
    animation: group-card-shine 5s ease-in-out infinite;
    pointer-events: none;
    z-index: 0;
}

@keyframes group-card-shine {
    0%, 100% { left: -100%; }
    50% { left: 140%; }
    75% { left: 140%; }
}

/* 左侧立体渐变竖条 */
[data-theme^="3d-"] .card-header.inventory-wh-header::after,
[data-theme^="3d-"] .card-header.warehouse-dept-header::after,
[data-theme^="3d-"] .card-header.group-card-header::after {
    content: "";
    position: absolute;
    left: 0;
    top: 10%;
    bottom: 10%;
    width: 5px;
    border-radius: 0 6px 6px 0;
    background: linear-gradient(180deg,
        rgba(255,255,255,0.85) 0%,
        var(--erp-accent) 45%,
        rgba(255,255,255,0.55) 100%);
    box-shadow:
        0 0 14px var(--erp-accent),
        inset 0 1px 0 rgba(255,255,255,0.6);
    z-index: 1;
}

/* 标题：大号加粗 + 立体阴影 + 微渐变文字 */
[data-theme^="3d-"] .card-header.inventory-wh-header :is(h1, h2, h3, h4, h5, h6),
[data-theme^="3d-"] .card-header.warehouse-dept-header :is(h1, h2, h3, h4, h5, h6),
[data-theme^="3d-"] .card-header.group-card-header :is(h1, h2, h3, h4, h5, h6) {
    color: #fff !important;
    font-size: 1.15rem;
    font-weight: 800;
    letter-spacing: 0.02em;
    text-shadow:
        0 1px 2px rgba(0,0,0,0.35),
        0 2px 4px rgba(0,0,0,0.25);
    position: relative;
    z-index: 2;
    margin-left: 0.6rem;
}

/* 图标：带发光 */
[data-theme^="3d-"] .card-header.inventory-wh-header h5 i,
[data-theme^="3d-"] .card-header.warehouse-dept-header h5 i,
[data-theme^="3d-"] .card-header.group-card-header h5 i {
    color: rgba(255,255,255,0.95) !important;
    filter: drop-shadow(0 0 5px rgba(255,255,255,0.55));
    margin-right: 0.45rem;
}

/* 右侧汇总徽章：3D 玻璃胶囊。
   ★ 2026-10-05 修正「同元素异色」：本条原先用 `background: rgba(15,23,42,.72) !important`
     把表头内**所有**徽章一律压成深灰玻璃，于是同一个 `badge bg-primary` /
     `badge bg-success` 在表格里是主题渐变/绿色、在分组卡片表头里变成深灰 —— 观感上
     像是两套渲染规则（实测：bg-secondary 28 处正常 vs 15 处深灰；bg-success 113 vs 3；
     bg-primary 54 vs 5）。
   现在改为：本条只负责**胶囊外形 + 3D 质感**，底色交回各自的 `bg-*` 变体规则。
   实现要点：整套选择器用 `:where()` 包裹，把本条优先级降到 0 ——
     ① 只写 `class="badge"` 的徽章仍命中本条的兜底底色（主题渐变），不会变透明；
     ② `[data-theme^="3d-"] .badge.bg-success` 等既有变体规则（权重 0,3,0）正常胜出，
        语义色相（绿/青/黄/红/灰）在表头内也得以保留。
   注：`:where()` 支持 Chrome/Edge 88+，与文件内既有的 `:has()` / `color-mix()` 同级。 */
:where([data-theme^="3d-"]) :where(.card-header.inventory-wh-header,
                                   .card-header.warehouse-dept-header,
                                   .card-header.group-card-header) :where(.badge) {
    position: relative;
    z-index: 2;
    color: #fff !important;
    font-weight: 700;
    font-size: 0.85rem;
    padding: 0.55em 0.95em;
    background:
        linear-gradient(135deg, var(--erp-grad-from) 0%, var(--erp-grad-to) 100%) !important;
    /* ★ 2026-10-05：底色与表头同为一条主题渐变后，原 1px/28% 的白边在表头右半侧
       （表头本身就是紫端）几乎看不出边界，胶囊会「融」进表头。
       这里只加强**容器质感**（描边环 + 外投影），不改徽章颜色 ——
       既保持「同一个 bg-* 徽章在表头与表格里同色」，又恢复轮廓辨识度。
       实测：边界由 rgba(255,255,255,0.28) 提升到 0.55，外投影 0.35→0.45。
       对比度只能量不能估，改动后已重新截图核对。 */
    border: 1px solid rgba(255,255,255,0.55);
    border-radius: 999px;
    box-shadow:
        0 4px 14px rgba(0,0,0,0.45),
        inset 0 1px 0 rgba(255,255,255,0.30),
        inset 0 -1px 0 rgba(0,0,0,0.22),
        0 0 16px -4px var(--erp-accent);
    text-shadow: 0 1px 2px rgba(0,0,0,0.45);
    backdrop-filter: blur(6px);
    -webkit-backdrop-filter: blur(6px);
}

/* 分组卡片整体：外发光 + 圆角 */
[data-theme^="3d-"] .card:has(.card-header.inventory-wh-header),
[data-theme^="3d-"] .card:has(.card-header.warehouse-dept-header),
[data-theme^="3d-"] .card:has(.card-header.group-card-header) {
    border-radius: 14px;
    border: 1px solid rgba(255,255,255,0.08);
    box-shadow:
        0 14px 38px -14px rgba(0,0,0,0.45),
        0 0 0 1px rgba(255,255,255,0.05),
        0 0 30px -10px var(--erp-accent);
    overflow: hidden;
}

/* 分组卡片内部表格表头：与仓库头部同色系，增强一体感 */
[data-theme^="3d-"] .card-header.inventory-wh-header + .card-body .table thead th,
[data-theme^="3d-"] .card-header.inventory-wh-header + .card-body .table-light > :not(caption) > * > *,
[data-theme^="3d-"] .card-header.warehouse-dept-header + .card-body .table thead th,
[data-theme^="3d-"] .card-header.warehouse-dept-header + .card-body .table-light > :not(caption) > * > *,
[data-theme^="3d-"] .card-header.group-card-header + .card-body .table thead th,
[data-theme^="3d-"] .card-header.group-card-header + .card-body .table-light > :not(caption) > * > * {
    background: linear-gradient(180deg, var(--erp-grad-from) 0%, var(--erp-grad-to) 100%) !important;
    color: #fff !important;
    text-shadow: 0 1px 2px rgba(0,0,0,0.30);
    border-bottom: 2px solid rgba(255,255,255,0.25);
}

/* 浅色 3D 主题下分组表头微调：保持标题可读 */
[data-theme="3d-gold"] .card-header.inventory-wh-header,
[data-theme="3d-gold"] .card-header.warehouse-dept-header,
[data-theme="3d-gold"] .card-header.group-card-header,
[data-theme="3d-gold"] .card-header.inventory-wh-header h5,
[data-theme="3d-gold"] .card-header.warehouse-dept-header h5,
[data-theme="3d-gold"] .card-header.group-card-header h5,
[data-theme="3d-gold"] .card-header.inventory-wh-header .badge,
[data-theme="3d-gold"] .card-header.warehouse-dept-header .badge,
[data-theme="3d-gold"] .card-header.group-card-header .badge {
    color: #fff !important;
}


/* ---------- 表格头部：渐变立体 ---------- */
[data-theme^="3d-"] .table thead th,
[data-theme^="3d-"] .table-light > :not(caption) > * > * {
    background: linear-gradient(180deg, var(--erp-grad-from) 0%, var(--erp-grad-to) 100%) !important;
    color: #fff !important;
    text-shadow: 0 1px 2px rgba(0,0,0,0.30);
    border-bottom: 2px solid rgba(255,255,255,0.25);
}

/* 操作列表头强制跟随主题渐变，避免个别页面因优先级/缓存导致渲染缺失 */
[data-theme^="3d-"] .table thead th.col-actions {
    background: linear-gradient(180deg, var(--erp-grad-from) 0%, var(--erp-grad-to) 100%) !important;
    color: #fff !important;
    text-shadow: 0 1px 2px rgba(0,0,0,0.30);
}

/* ---------- 主按钮：渐变立体 ---------- */
[data-theme^="3d-"] .btn-primary {
    background: linear-gradient(135deg, var(--erp-grad-from) 0%, var(--erp-grad-to) 100%);
    border: none;
    color: #fff;
    text-shadow: 0 1px 2px rgba(0,0,0,0.25);
    box-shadow: 0 3px 10px -2px var(--erp-accent), inset 0 1px 0 rgba(255,255,255,0.28);
}
[data-theme^="3d-"] .btn-primary:hover,
[data-theme^="3d-"] .btn-primary:focus {
    background: linear-gradient(135deg, var(--erp-grad-from) 0%, var(--erp-grad-to) 100%);
    filter: brightness(1.10);
    color: #fff;
    box-shadow: 0 5px 16px -2px var(--erp-accent), inset 0 1px 0 rgba(255,255,255,0.28);
}
[data-theme^="3d-"] .btn-primary:active {
    filter: brightness(0.94);
    box-shadow: inset 0 3px 8px rgba(0,0,0,0.25);
}
[data-theme^="3d-"] .btn-primary:disabled {
    background: linear-gradient(135deg, var(--erp-grad-from) 0%, var(--erp-grad-to) 100%);
    opacity: 0.6;
}

/* ---------- 徽标：渐变立体 ---------- */
[data-theme^="3d-"] .badge.bg-primary {
    background: linear-gradient(135deg, var(--erp-grad-from) 0%, var(--erp-grad-to) 100%) !important;
    box-shadow: 0 2px 8px -2px var(--erp-accent);
}
[data-theme^="3d-"] .badge.bg-success { background: linear-gradient(135deg, #34d399, #059669) !important; }
[data-theme^="3d-"] .badge.bg-info { background: linear-gradient(135deg, #38bdf8, #0284c7) !important; }
[data-theme^="3d-"] .badge.bg-warning { background: linear-gradient(135deg, #fbbf24, #d97706) !important; color: #1f2937 !important; }
[data-theme^="3d-"] .badge.bg-danger { background: linear-gradient(135deg, #f87171, #dc2626) !important; }
[data-theme^="3d-"] .badge.bg-secondary { background: linear-gradient(135deg, #9ca3af, #4b5563) !important; }

/* ---------- 导航栏：顶部高光 + 立体投影 ---------- */
[data-theme^="3d-"] .erp-navbar {
    box-shadow: 0 4px 18px -6px rgba(0,0,0,0.35), inset 0 1px 0 rgba(255,255,255,0.12);
}
[data-theme^="3d-"] .erp-navbar::before {
    content: "";
    position: absolute;
    left: 0;
    right: 0;
    top: 0;
    height: 3px;
    background: linear-gradient(90deg, transparent, var(--erp-accent), transparent);
    opacity: 0.80;
    pointer-events: none;
}

/* ---------- 页面标题：渐变竖条 ---------- */
[data-theme^="3d-"] h4 {
    padding-left: 10px;
    border-left: 4px solid transparent;
    border-image: linear-gradient(180deg, var(--erp-grad-from), var(--erp-grad-to)) 1;
}

/* ---------- 卡片/窗体：统一 3D 玻璃态 ----------
   主内容区 .erp-main 内的所有 .card 自动获得 3D 卡片效果，
   无需逐个模板加 .erp-card；登录页等独立区域不受影响。
   ---------- */
[data-theme^="3d-"] .erp-main .card,
[data-theme^="3d-"] .card.erp-card,
[data-theme^="3d-"] .stat-card {
    position: relative;
    background: var(--erp-card-bg);
    border: 1px solid var(--erp-table-border);
    border-radius: 12px;
    box-shadow:
        var(--erp-card-shadow),
        var(--erp-card-glow),
        0 14px 36px -14px rgba(0,0,0,0.55);
    overflow: hidden;
}

/* 顶部渐变高光线条（用伪元素实现，兼容圆角） */
[data-theme^="3d-"] .erp-main .card::before,
[data-theme^="3d-"] .card.erp-card::before,
[data-theme^="3d-"] .stat-card::before {
    content: "";
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    height: 3px;
    background: linear-gradient(90deg, var(--erp-grad-from), var(--erp-accent), var(--erp-grad-to));
    opacity: 0.85;
    z-index: 2;
    pointer-events: none;
}

/* 卡片 hover 轻微上浮 + 辉光增强 */
[data-theme^="3d-"] .erp-main .card:hover,
[data-theme^="3d-"] .card.erp-card:hover,
[data-theme^="3d-"] .stat-card:hover {
    box-shadow:
        var(--erp-card-shadow),
        var(--erp-card-glow),
        0 20px 44px -16px var(--erp-accent);
    transform: translateY(-1px);
}

/* 带语义边框的卡片：保留原色边框 + 玻璃背景 */
[data-theme^="3d-"] .erp-main .card.border-primary,
[data-theme^="3d-"] .erp-main .card.border-success,
[data-theme^="3d-"] .erp-main .card.border-warning,
[data-theme^="3d-"] .erp-main .card.border-danger,
[data-theme^="3d-"] .erp-main .card.border-info,
[data-theme^="3d-"] .card.erp-card.border-primary,
[data-theme^="3d-"] .card.erp-card.border-success,
[data-theme^="3d-"] .card.erp-card.border-warning,
[data-theme^="3d-"] .card.erp-card.border-danger,
[data-theme^="3d-"] .card.erp-card.border-info {
    background: var(--erp-card-bg);
    border-width: 1px;
    box-shadow:
        var(--erp-card-shadow),
        var(--erp-card-glow),
        0 14px 36px -14px rgba(0,0,0,0.55);
}

/* ★ 2026-10-05：`.border-primary` 卡片的顶部装饰条原先写死蓝色 (#2563eb → #3b82f6)，
   与主题无关 —— 同一页里普通卡片走主题渐变、primary 卡片却是固定蓝，属「同元素异色」。
   改为与默认装饰条（见上 `.card::before`）同一条主题渐变，仅保留 primary 的强调含义。
   success/info/warning/danger 保持各自语义色相，不动。 */
[data-theme^="3d-"] .erp-main .card.border-primary::before,
[data-theme^="3d-"] .card.erp-card.border-primary::before { background: linear-gradient(90deg, var(--erp-grad-from), var(--erp-accent), var(--erp-grad-to)); }
[data-theme^="3d-"] .erp-main .card.border-success::before,
[data-theme^="3d-"] .card.erp-card.border-success::before { background: linear-gradient(90deg, #059669, #34d399); }
[data-theme^="3d-"] .erp-main .card.border-warning::before,
[data-theme^="3d-"] .card.erp-card.border-warning::before { background: linear-gradient(90deg, #d97706, #fbbf24); }
[data-theme^="3d-"] .erp-main .card.border-danger::before,
[data-theme^="3d-"] .card.erp-card.border-danger::before { background: linear-gradient(90deg, #dc2626, #f87171); }
[data-theme^="3d-"] .erp-main .card.border-info::before,
[data-theme^="3d-"] .card.erp-card.border-info::before { background: linear-gradient(90deg, #0891b2, #22d3ee); }

/* ---------- 仪表盘统计卡片图标：3D 立体增强（底色统一由 .stat-card .stat-icon 提供） ---------- */
[data-theme^="3d-"] .stat-card .stat-icon {
    border-radius: 12px;
    box-shadow:
        0 5px 16px -5px var(--erp-accent),
        inset 0 1px 0 rgba(255,255,255,0.32),
        inset 0 -2px 5px rgba(0,0,0,0.20);
    text-shadow: 0 1px 2px rgba(0,0,0,0.28);
}

/* ============================================================
   3D 细节组件增强（仅 3D 主题生效：按钮/表单/模态框/下拉/分页/统计/提示/表格）
   ============================================================ */

/* ---------- 按钮：实色变体（secondary/success/info/warning/danger） ---------- */
[data-theme^="3d-"] .btn-secondary {
    background: linear-gradient(135deg, #94a3b8, #475569);
    border: none; color: #fff;
    text-shadow: 0 1px 2px rgba(0,0,0,0.25);
    box-shadow: 0 3px 10px -2px rgba(71,85,105,0.5), inset 0 1px 0 rgba(255,255,255,0.25);
}
[data-theme^="3d-"] .btn-success {
    background: linear-gradient(135deg, #34d399, #059669);
    border: none; color: #fff;
    text-shadow: 0 1px 2px rgba(0,0,0,0.25);
    box-shadow: 0 3px 10px -2px rgba(5,150,105,0.5), inset 0 1px 0 rgba(255,255,255,0.25);
}
[data-theme^="3d-"] .btn-info {
    background: linear-gradient(135deg, #38bdf8, #0284c7);
    border: none; color: #fff;
    text-shadow: 0 1px 2px rgba(0,0,0,0.25);
    box-shadow: 0 3px 10px -2px rgba(2,132,199,0.5), inset 0 1px 0 rgba(255,255,255,0.25);
}
[data-theme^="3d-"] .btn-warning {
    background: linear-gradient(135deg, #fbbf24, #d97706);
    border: none; color: #1f2937;
    text-shadow: 0 1px 2px rgba(255,255,255,0.25);
    box-shadow: 0 3px 10px -2px rgba(217,119,6,0.5), inset 0 1px 0 rgba(255,255,255,0.35);
}
[data-theme^="3d-"] .btn-danger {
    background: linear-gradient(135deg, #f87171, #dc2626);
    border: none; color: #fff;
    text-shadow: 0 1px 2px rgba(0,0,0,0.25);
    box-shadow: 0 3px 10px -2px rgba(220,38,38,0.5), inset 0 1px 0 rgba(255,255,255,0.25);
}
[data-theme^="3d-"] .btn-secondary:hover,
[data-theme^="3d-"] .btn-success:hover,
[data-theme^="3d-"] .btn-info:hover,
[data-theme^="3d-"] .btn-warning:hover,
[data-theme^="3d-"] .btn-danger:hover,
[data-theme^="3d-"] .btn-secondary:focus,
[data-theme^="3d-"] .btn-success:focus,
[data-theme^="3d-"] .btn-info:focus,
[data-theme^="3d-"] .btn-warning:focus,
[data-theme^="3d-"] .btn-danger:focus {
    filter: brightness(1.08);
    color: #fff;
}
[data-theme^="3d-"] .btn-warning:hover,
[data-theme^="3d-"] .btn-warning:focus { color: #1f2937; }
[data-theme^="3d-"] .btn-secondary:active,
[data-theme^="3d-"] .btn-success:active,
[data-theme^="3d-"] .btn-info:active,
[data-theme^="3d-"] .btn-warning:active,
[data-theme^="3d-"] .btn-danger:active {
    filter: brightness(0.93);
    box-shadow: inset 0 3px 8px rgba(0,0,0,0.25);
}

/* ---------- 按钮：描边变体（outline-*）渐变边框 + hover 实心渐变 ---------- */
[data-theme^="3d-"] .btn-outline-primary,
[data-theme^="3d-"] .btn-outline-secondary,
[data-theme^="3d-"] .btn-outline-success,
[data-theme^="3d-"] .btn-outline-info,
[data-theme^="3d-"] .btn-outline-warning,
[data-theme^="3d-"] .btn-outline-danger {
    border: 2px solid transparent;
    color: var(--erp-grad-to);
    background:
        linear-gradient(var(--erp-card-bg), var(--erp-card-bg)) padding-box,
        linear-gradient(135deg, var(--erp-grad-from), var(--erp-grad-to)) border-box;
    box-shadow: 0 2px 8px -3px var(--erp-accent), inset 0 1px 0 rgba(255,255,255,0.15);
    transition: all 0.15s ease;
}
[data-theme^="3d-"] .btn-outline-primary:hover,
[data-theme^="3d-"] .btn-outline-secondary:hover,
[data-theme^="3d-"] .btn-outline-success:hover,
[data-theme^="3d-"] .btn-outline-info:hover,
[data-theme^="3d-"] .btn-outline-warning:hover,
[data-theme^="3d-"] .btn-outline-danger:hover,
[data-theme^="3d-"] .btn-outline-primary:focus,
[data-theme^="3d-"] .btn-outline-secondary:focus,
[data-theme^="3d-"] .btn-outline-success:focus,
[data-theme^="3d-"] .btn-outline-info:focus,
[data-theme^="3d-"] .btn-outline-warning:focus,
[data-theme^="3d-"] .btn-outline-danger:focus {
    color: #fff;
    border-color: transparent;
    text-shadow: 0 1px 2px rgba(0,0,0,0.25);
    background:
        linear-gradient(135deg, var(--erp-grad-from), var(--erp-grad-to)) padding-box,
        linear-gradient(135deg, var(--erp-grad-from), var(--erp-grad-to)) border-box;
    box-shadow: 0 4px 14px -3px var(--erp-accent), inset 0 1px 0 rgba(255,255,255,0.25);
}
[data-theme^="3d-"] .btn-outline-primary:active,
[data-theme^="3d-"] .btn-outline-secondary:active,
[data-theme^="3d-"] .btn-outline-success:active,
[data-theme^="3d-"] .btn-outline-info:active,
[data-theme^="3d-"] .btn-outline-warning:active,
[data-theme^="3d-"] .btn-outline-danger:active {
    filter: brightness(0.95);
    box-shadow: inset 0 3px 8px rgba(0,0,0,0.25);
}

/* ---------- 表单控件：内嵌立体阴影 + 聚焦渐变光环 ---------- */
[data-theme^="3d-"] .form-control,
[data-theme^="3d-"] .form-select {
    border-color: var(--erp-table-border);
    box-shadow: inset 0 1px 3px rgba(0,0,0,0.10);
}
[data-theme^="3d-"] .form-control:focus,
[data-theme^="3d-"] .form-select:focus {
    border-color: var(--erp-grad-to);
    outline: none;
    box-shadow:
        0 0 0 0.2rem color-mix(in srgb, var(--erp-grad-to) 22%, transparent),
        inset 0 1px 3px rgba(0,0,0,0.08);
}

/* ---------- 模态框：渐变头部 + 顶部高光 + 立体投影 ---------- */
[data-theme^="3d-"] .modal-content {
    border: none;
    background: var(--erp-card-bg);
    box-shadow: 0 24px 64px -20px rgba(0,0,0,0.5), var(--erp-card-glow);
}
[data-theme^="3d-"] .modal-header {
    background: linear-gradient(135deg, var(--erp-grad-from), var(--erp-grad-to));
    color: #fff;
    border-bottom: 1px solid rgba(255,255,255,0.20);
    text-shadow: 0 1px 2px rgba(0,0,0,0.30);
}
[data-theme^="3d-"] .modal-header .modal-title { color: #fff; }
[data-theme^="3d-"] .modal-header .btn-close { filter: invert(1); opacity: 0.9; }

/* ---------- 下拉菜单：悬浮渐变项 + 立体投影 ---------- */
[data-theme^="3d-"] .dropdown-menu {
    background: var(--erp-card-bg);
    border: 1px solid var(--erp-table-border);
    box-shadow: 0 14px 34px -12px rgba(0,0,0,0.45), var(--erp-card-glow);
}
[data-theme^="3d-"] .dropdown-item:hover,
[data-theme^="3d-"] .dropdown-item:focus {
    background: linear-gradient(135deg, var(--erp-grad-from), var(--erp-grad-to));
    color: #fff;
}

/* ---------- 右上角用户菜单：主题切换色块 ---------- */
.theme-swatch {
    display: inline-block;
    width: 16px;
    height: 16px;
    border-radius: 4px;
    flex: 0 0 auto;
    box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.35), 0 1px 2px rgba(0, 0, 0, 0.25);
}

/* 部门列表里的「该部门界面主题」色条（2026-10-05 主题按部门记忆）
   一条竖色带，宽度固定 5px、高度跟随行高：兼任多部门的账号扫一眼就知道
   每个部门切过去是什么颜色，与切换后整页实际变色的结果一一对应。
   ★ 用 flex:0 0 auto 防止被 text-truncate 的部门名挤压。 */
.dept-theme-bar {
    display: inline-block;
    width: 5px;
    height: 1.15em;
    border-radius: 2px;
    flex: 0 0 auto;
    box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.35);
}

/* ★ 2026-10-06 「部门已切换」弹窗正文前的主题色条：比下拉里那条更醒目一点，
   让用户点确定之前先看清自己现在是什么颜色（＝哪个部门）。 */
.erp-flash-theme-bar {
    display: inline-block;
    width: 7px;
    height: 1.25em;
    border-radius: 3px;
    vertical-align: -0.22em;
    margin-right: 8px;
    box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.35);
}

/* 主题切换网格：两列紧凑布局，避免菜单过长把退出登录挤出可视区 */
.theme-grid {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 4px;
    padding: 4px 0;
}
.theme-grid-item {
    padding: 0.35rem 0.5rem;
    border-radius: 0.375rem;
    color: var(--erp-text);
    text-decoration: none;
    font-size: 0.875rem;
    transition: background-color 0.15s ease-in-out;
}
.theme-grid-item:hover,
.theme-grid-item:focus {
    background-color: var(--erp-table-head-bg);
    color: var(--erp-text);
}
.theme-grid-item.active {
    background: linear-gradient(135deg, var(--erp-grad-from), var(--erp-grad-to));
    color: #fff;
}
.theme-grid-item .theme-name {
    max-width: 70px;
}
html[data-theme^="3d-"] .theme-grid-item:hover,
html[data-theme^="3d-"] .theme-grid-item:focus {
    background: rgba(255, 255, 255, 0.12);
}
html[data-theme^="3d-"] .theme-grid-item.active {
    background: linear-gradient(135deg, var(--erp-grad-from), var(--erp-grad-to));
    color: #fff;
}

/* ★ 2026-10-05 主题按部门记忆后，菜单里又多了「当前部门 + 切换部门列表 + 来源说明」，
   整条菜单实测可到 860px 高 ⇒ 矮窗口下末尾几项（恢复按部门自动区分 / 退出登录）够不到。
   这里给菜单本身加滚动上限，保证任何窗口高度下都能滚到最后一项。 */
.dropdown-menu.erp-theme-menu {
    /* ★ 2026-10-06 主题名被挤断：菜单默认宽实测 240px，两列主题格每格只有 109px，
       选中项还多一个 ✓（1em + ms-1 = 18px）⇒ 4 字名「冰蓝科技」可用宽仅 51px < 需要的 58px，
       被 text-truncate 截成「冰蓝科…」（headless Edge 实测 scrollW 58 > clientW 52）。
       268px 时可用宽 65px，留 7px 余量；右锚定下拉向左展开，不会顶出视口。 */
    min-width: 268px;
    max-height: calc(100vh - 64px);
    overflow-y: auto;
    overscroll-behavior: contain;
}

/* ---------- 分页：激活项渐变立体 ---------- */
[data-theme^="3d-"] .pagination .page-link {
    color: var(--erp-grad-to);
    background: var(--erp-card-bg);
    border-color: var(--erp-table-border);
}
[data-theme^="3d-"] .pagination .page-link:hover {
    color: #fff;
    border-color: transparent;
    background: linear-gradient(135deg, var(--erp-grad-from), var(--erp-grad-to));
}
[data-theme^="3d-"] .pagination .page-item.active .page-link {
    color: #fff;
    border-color: transparent;
    background: linear-gradient(135deg, var(--erp-grad-from), var(--erp-grad-to));
    box-shadow: 0 3px 10px -2px var(--erp-accent), inset 0 1px 0 rgba(255,255,255,0.25);
}

/* ---------- 统计数字：渐变文字（高级感） ---------- */
[data-theme^="3d-"] .stat-card .stat-value {
    background: linear-gradient(135deg, var(--erp-grad-from), var(--erp-grad-to));
    -webkit-background-clip: text;
    background-clip: text;
    color: transparent;
    -webkit-text-fill-color: transparent;
}

/* ---------- 提示框：左侧渐变光条 ---------- */
[data-theme^="3d-"] .alert { position: relative; overflow: hidden; }
[data-theme^="3d-"] .alert::before {
    content: "";
    position: absolute;
    left: 0; top: 0; bottom: 0;
    width: 4px;
    background: linear-gradient(180deg, var(--erp-grad-from), var(--erp-grad-to));
}

/* ---------- 表格行：悬浮渐变高亮 ---------- */
[data-theme^="3d-"] .table tbody tr:hover {
    background: color-mix(in srgb, var(--erp-grad-to) 12%, var(--erp-card-bg));
}

/* ---------- 导航栏链接：悬浮微光 ---------- */
[data-theme^="3d-"] .erp-navbar .nav-link:hover {
    color: #fff;
    text-shadow: 0 0 10px var(--erp-accent);
}

/* ============================================================
   琉璃蓝（3d-crystal）专属玻璃态增强
   ============================================================ */

/* 页面背景：顶部微光 radial，衬托玻璃态卡片 */
[data-theme="3d-crystal"] body {
    background:
        radial-gradient(ellipse 80% 50% at 50% -10%, rgba(30, 58, 95, 0.35) 0%, transparent 70%),
        var(--erp-bg);
}

/* 卡片/面板：毛玻璃模糊 + 发光边框 */
[data-theme="3d-crystal"] .erp-main .card,
[data-theme="3d-crystal"] .card.erp-card,
[data-theme="3d-crystal"] .stat-card,
[data-theme="3d-crystal"] .modal-content,
[data-theme="3d-crystal"] .dropdown-menu {
    -webkit-backdrop-filter: blur(12px);
    backdrop-filter: blur(12px);
    border: 1px solid rgba(96, 165, 250, 0.18);
}

/* 侧边栏：毛玻璃 */
[data-theme="3d-crystal"] .erp-sidebar {
    -webkit-backdrop-filter: blur(14px);
    backdrop-filter: blur(14px);
}

/* 表头：更亮的蓝色高光底边 */
[data-theme="3d-crystal"] .table thead th,
[data-theme="3d-crystal"] .table-light > :not(caption) > * > * {
    border-bottom: 2px solid rgba(96, 165, 250, 0.45);
    box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.12);
}

/* 空状态：带一点蓝色微光 */
[data-theme="3d-crystal"] .empty-state,
[data-theme="3d-crystal"] .table tbody tr td.text-center.text-muted i {
    color: #60a5fa;
    text-shadow: 0 0 16px rgba(96, 165, 250, 0.35);
}

/* 主按钮：更强的蓝色辉光 */
[data-theme="3d-crystal"] .btn-primary,
[data-theme="3d-crystal"] .pagination .page-item.active .page-link {
    box-shadow: 0 4px 16px -4px rgba(37, 99, 235, 0.65), inset 0 1px 0 rgba(255,255,255,0.28);
}

/* 表单控件：暗底 + 蓝色聚焦光环 */
[data-theme="3d-crystal"] .form-control,
[data-theme="3d-crystal"] .form-select {
    /* ★ 2026-10-08：这里原是 background **简写**，会把 Bootstrap 的
       `background-image: var(--bs-form-select-bg-img), …` 重置为 none ⇒
       3d-crystal 主题下**全站下拉框都没有箭头**。改用 background-color
       只覆盖底色，箭头（含 repeat/position/size）交回 Bootstrap。 */
    background-color: rgba(11, 18, 32, 0.65);
    border-color: rgba(96, 165, 250, 0.25);
    color: var(--erp-text);
}
[data-theme="3d-crystal"] .form-control:focus,
[data-theme="3d-crystal"] .form-select:focus {
    border-color: #60a5fa;
    /* ★ 2026-10-08：同上面一条 —— 简写会连箭头一起抹掉，改 background-color。 */
    background-color: rgba(11, 18, 32, 0.85);
    box-shadow: 0 0 0 0.2rem rgba(96, 165, 250, 0.25), inset 0 1px 3px rgba(0,0,0,0.15);
}

/* 折叠详情内卡片：适配玻璃态 */
[data-theme="3d-crystal"] .bg-light.border-start {
    background: rgba(30, 58, 95, 0.35) !important;
    border-color: rgba(96, 165, 250, 0.35) !important;
}

/* 销售出库展开详情面板：与合计行统一背景，避免 3D 主题下 bg-light 渐变不统一 */
.so-detail-panel {
    background-color: var(--erp-table-head-bg) !important;
    color: var(--erp-text) !important;
}

html[data-theme^="3d-"] body .erp-main .so-detail-panel {
    background: rgba(255, 255, 255, 0.08) !important;
    background-color: rgba(255, 255, 255, 0.08) !important;
    background-image: none !important;
    color: var(--erp-text) !important;
    text-shadow: none !important;
    box-shadow: none !important;
}

/* 强制面板内表格/网格背景透明，避免子元素自带背景导致色块不均匀 */
.so-detail-panel [class*="col-"],
.so-detail-panel .table,
.so-detail-panel .table > :not(caption) > * > * {
    background-color: transparent !important;
    background-image: none !important;
    --bs-table-bg: transparent !important;
}

/* ============================================================
   操作列表头：最高优先级兜底
   部分页面（客户管理、销售出库等）的操作列表头在 3D 主题下
   会被 Bootstrap 的 .table-light 变量覆盖，导致渐变缺失。
   这里用 html > body > .erp-main 的完整层级选择器 + !important
   强制操作头始终跟随主题渐变。
   ============================================================ */
html[data-theme^="3d-"] body .erp-main .table.erp-table > thead.table-light > tr > th.col-actions,
html[data-theme^="3d-"] body .erp-main .table.erp-table > thead > tr > th.col-actions,
html[data-theme^="3d-"] body .erp-main .table > thead.table-light > tr > th.col-actions,
html[data-theme^="3d-"] body .erp-main .table > thead > tr > th.col-actions,
html[data-theme^="3d-"] body .erp-main .table.erp-table thead th.col-actions,
html[data-theme^="3d-"] body .erp-main .table thead th.col-actions {
    background: linear-gradient(180deg, var(--erp-grad-from) 0%, var(--erp-grad-to) 100%) !important;
    background-color: transparent !important;
    background-image: linear-gradient(180deg, var(--erp-grad-from) 0%, var(--erp-grad-to) 100%) !important;
    color: #fff !important;
    text-shadow: 0 1px 2px rgba(0,0,0,0.30) !important;
    box-shadow: none !important;
}

/* 兼容无 erp-table 类或未加 col-actions 的表格 */
html[data-theme^="3d-"] body .erp-main .table > thead > tr > th:last-child,
html[data-theme^="3d-"] body .erp-main .table.erp-table > thead > tr > th:last-child {
    background: linear-gradient(180deg, var(--erp-grad-from) 0%, var(--erp-grad-to) 100%) !important;
    background-color: transparent !important;
    background-image: linear-gradient(180deg, var(--erp-grad-from) 0%, var(--erp-grad-to) 100%) !important;
    color: #fff !important;
    text-shadow: 0 1px 2px rgba(0,0,0,0.30) !important;
    box-shadow: none !important;
}

/* 最强兜底：所有位于 thead 最后一个位置且带 col-actions 的 th，避免 Bootstrap .table-light 变量残留 */
html[data-theme^="3d-"] body .erp-main .table thead tr > th.col-actions:last-child,
html[data-theme^="3d-"] body .erp-main .table.erp-table thead tr > th.col-actions:last-child {
    background: linear-gradient(180deg, var(--erp-grad-from) 0%, var(--erp-grad-to) 100%) !important;
    background-color: transparent !important;
    background-image: linear-gradient(180deg, var(--erp-grad-from) 0%, var(--erp-grad-to) 100%) !important;
    color: #fff !important;
    text-shadow: 0 1px 2px rgba(0,0,0,0.30) !important;
    box-shadow: none !important;
}

/* ============================================================
   表格底部合计行（tfoot .table-light）
   避免 3D 主题下 .table-light 的渐变背景作用到合计行，
   导致部分浏览器（Edge）中跨列的操作列位置颜色不一致。
   统一使用实色深色背景，与数据行区分但不含渐变。

   ★★ 2026-09-27 修（用户反馈「合计行会跟着滚动」的第三层成因）：
     此处原先是 rgba(255, 255, 255, 0.08) —— **半透明**底。
     当合计行被 .erp-sticky-table 吸底（position: sticky; bottom: 0）固定住之后，
     半透明底会把下方正在滚动的数据行「透」出来，与合计文字重叠
     （实测 1336 宽视口下可同时看到「MAT0025」与「合计」两行文字叠在一起），
     视觉上完全等价于「合计行自己在跟着滚」。
     表头之所以没有这个问题，是因为上面 :1602 的
       [data-theme^="3d-"] .table thead th { background: linear-gradient(...) } 是不透明的。
     ⇒ 合计行底色必须**不透明**；各 3D 主题的 --erp-table-head-bg 均为深色实色，
       直接取用即可（浅色 3D 主题同样是实色），再补一条顶部细分隔线把
       「合计」与最后一行数据明确切开。
     ★ 改这里时请同步看下面 .erp-sticky-table tfoot 的通用实色兜底，两处口径必须一致。
   ============================================================ */
html[data-theme^="3d-"] body .erp-main .table tfoot.table-light > tr > td,
html[data-theme^="3d-"] body .erp-main .table tfoot > tr.table-light > td,
html[data-theme^="3d-"] body .erp-main .table tfoot.table-light > tr > th,
html[data-theme^="3d-"] body .erp-main .table tfoot > tr.table-light > th,
html[data-theme^="3d-"] body .erp-main .table tfoot > tr.total-summary-row > td,
html[data-theme^="3d-"] body .erp-main .table tfoot > tr.total-summary-row > th {
    background: var(--erp-table-head-bg, #12283c) !important;
    background-color: var(--erp-table-head-bg, #12283c) !important;
    background-image: none !important;
    color: var(--erp-text) !important;
    text-shadow: none !important;
    box-shadow: none !important;
    border-top: 1px solid rgba(255, 255, 255, 0.18) !important;
}

/* ========== 打印模式（全局）
   打印/导出 PDF 时去掉顶部导航栏、左侧菜单、flash 提示、模态框，
   取消主内容区的 left/top 偏移与 padding，让单据/报表/档案铺满 A4 纸。
   任何页面（默认）触发打印都生效。
   ========== */
@media print {
    /* 顶部导航 / 左侧菜单 / 工具按钮 / 弹窗 / 提示条：统统不打印。
       ★ 2026-10-10：清单按「视口断点显形的 fixed 浮层」补三类漏网元素 ——
         判据不是"它在不在侧栏里"，而是"它会不会在出纸时落在版心内"。
         · .erp-sidebar-toggle：**body 直属**（故意放在 .erp-sidebar 外面，
           因为侧栏 overflow-x:hidden 会裁掉它右移的半个圆）。
           ⇒ `.erp-sidebar{display:none}` 管不到它，屏宽 ≥992px（d-lg-flex 生效）
             时打印，这个圆形箭头会印在纸张左侧、压在卡片左缘 —— 用户报的
             「每个打印页面出现红框里的箭头图标」就是它。
         · .counterparty-ac-menu / #material-ac-menu：两个 autocomplete 下拉浮层，
           同为 position:fixed，若出纸瞬间恰好展开（或残留 .show）会印到纸上。
         ★ 以后新增任何 position:fixed 的浮层/角标/抽屉，都要回来登记到这里。 */
    .erp-navbar,
    .erp-sidebar,
    .erp-sidebar-toggle,
    .counterparty-ac-menu,
    #material-ac-menu,
    .navbar,
    .modal,
    .modal-backdrop,
    .toast-container,
    .no-print,
    .alert {
        display: none !important;
    }

    /* 主内容区：清掉偏移和留白，恢复到 0/0 */
    .erp-main {
        margin: 0 !important;
        padding: 0 !important;
        min-height: 0 !important;
        background: #fff !important;
    }
    .container-fluid { padding: 0 !important; margin: 0 !important; }

    /* 页面背景去掉，避免彩色背景被打印 */
    html, body {
        background: #fff !important;
        color: #000;
    }

    /* 链接 URL 强制隐藏（PDF 里出现一长串 URL 很丑） */
    a[href]:after { content: "" !important; }

    /* 输入框/下拉/textarea 在打印时去掉浏览器默认外观，按真实内容渲染 */
    input, select, textarea {
        background: transparent !important;
        border: none !important;
        box-shadow: none !important;
        -webkit-appearance: none;
        appearance: none;
    }
}

/* ============================================================
   往来单位 autocomplete（客户 / 供应商）
   ============================================================ */
.counterparty-ac-menu {
    position: fixed;
    max-height: 220px;
    overflow-y: auto;
    background-color: var(--bs-body-bg, #fff);
    border: 1px solid var(--bs-border-color, rgba(0,0,0,0.175));
    border-radius: 0.375rem;
    box-shadow: 0 0.5rem 1rem rgba(0,0,0,0.15);
    z-index: 9999;
}

.counterparty-ac-item {
    padding: 0.5rem 0.75rem;
    cursor: pointer;
    color: var(--bs-body-color, #212529);
    border-bottom: 1px solid var(--bs-border-color-translucent, rgba(0,0,0,0.05));
}

.counterparty-ac-item:last-child {
    border-bottom: none;
}

.counterparty-ac-item:hover,
.counterparty-ac-item.active {
    background-color: var(--bs-primary, #0d6efd);
    color: #fff;
}

.counterparty-ac-empty {
    padding: 0.75rem;
    color: var(--bs-secondary, #6c757d);
    text-align: center;
}

/* ========== 可滚动表格容器 ========== */
.table-container {
    max-height: 60vh;
    overflow-y: auto;
    overflow-x: auto;
}
.table-container .sticky-top {
    position: sticky;
    top: 0;
    z-index: 3;
}

/* ============================================================
   固定表头 + 明细滚动（列表页通用工具类 .erp-sticky-table）
   用法：在主表格外层容器上加此类（可叠加在 .table-responsive / .table-container 上）：
     <div class="table-responsive erp-sticky-table">
   容器由 base.html 的脚本按视口位置动态设置 max-height，
   表头(thead)与合计行(tfoot) position: sticky 固定，仅明细滚动。
   导航栏本身已是 Bootstrap fixed-top，本类负责让表格表头在明细滚动时保持固定。
   ============================================================ */
.erp-sticky-table {
    max-height: 60vh;            /* JS 加载后用精确值覆盖 */
    overflow: auto;
    border-radius: 0 0 var(--bs-card-border-radius, 0.375rem) var(--bs-card-border-radius, 0.375rem);
}
.erp-sticky-table > table {
    margin-bottom: 0;            /* 去除默认底边距，避免滚动条额外占高 */
}
/* 表头固定 */
.erp-sticky-table thead th {
    position: sticky;
    top: 0;
    z-index: 3;
}
/* 未使用 Bootstrap 主题表头色（table-light/table-dark）时给兜底背景，
   避免明细滚动时从表头缝隙透出下方内容 */
.erp-sticky-table thead:not(.table-light):not(.table-dark) th {
    background-color: var(--erp-table-head-bg, #f1f5f9);
    color: var(--erp-table-head-color, #475569);
}
/* 合计行固定（底部） */
.erp-sticky-table tfoot th,
.erp-sticky-table tfoot td {
    position: sticky;
    bottom: 0;
    z-index: 3;
}
.erp-sticky-table tfoot:not(.table-light):not(.table-dark) th,
.erp-sticky-table tfoot:not(.table-light):not(.table-dark) td {
    background-color: var(--erp-table-head-bg, #f1f5f9);
}
/* ★★ 吸底合计行必须**不透明**（2026-09-27 用户反馈「合计行会跟着滚动」）
   合计行一旦 position: sticky; bottom: 0 固定，半透明底就会把下方滚动中的
   数据行透出来、文字重叠 —— 用户看到的就是「合计行自己在滚」。
   这里对容器内所有合计行细胞统一兜一层实色底（各主题 --erp-table-head-bg 均为实色：
   浅色主题浅底 / 3D 主题深底），并加顶部内阴影做一条分隔线。
   注：3D 主题的 tfoot.table-light 另有一条更高优先级(!important)的实色规则，
       两处口径必须保持一致，改一处务必检查另一处。 */
.erp-sticky-table tfoot > tr > td,
.erp-sticky-table tfoot > tr > th {
    background-color: var(--erp-table-head-bg, #f1f5f9);
    border-top: 1px solid var(--erp-table-border, rgba(148, 163, 184, 0.45));
}

/* ============================================================
   表格整表展开（.erp-fit-table）
   与 .erp-sticky-table 相反：**不做容器内滚动**，表格按内容全高铺开，
   表头也不吸顶，滚动交给页面本身。
   用途：报表类页面（资产负债表等）行数固定且需要「一眼看全/整页打印」，
   容器内滚动会让用户看不到完整表体。
   仅保留卡片底部的圆角收口，视觉与 .erp-sticky-table 一致。
   ============================================================ */
.erp-fit-table {
    max-height: none;            /* 不设高度上限 → 容器随内容增高，无纵向滚动 */
    border-radius: 0 0 var(--bs-card-border-radius, 0.375rem) var(--bs-card-border-radius, 0.375rem);
}
.erp-fit-table > table {
    margin-bottom: 0;
}
/* ============================================================
   报表页打印优化（资产负债表 / 利润表 / 现金流量表）
   —— 目标：1 张 A4 完整显示 + 白底黑字清晰可读

   仅作用于 .erp-fit-table（报表页专用）与 .erp-report-card，
   列表页 / 单据页的 sticky 表格不受影响。

   选择器刻意写成 `html[data-theme] body .x.x`：
   类名重复一次 + 前缀属性选择器，用于压过
   `[data-theme^="3d-"] .card-header.inventory-wh-header { background: ... !important }`
   这类同样带 !important 的主题规则（同权重时靠文档顺序，我这块在文件末尾）。
   ============================================================ */
@media print {
    /* ① 裁切问题：.table-responsive 的 overflow:auto 打印时会裁掉超出内容，
       这正是「资产负债表右侧金额被切掉」的原因。 */
    html[data-theme] body .erp-fit-table.erp-fit-table {
        overflow: visible !important;
        max-height: none !important;
        border-radius: 0 !important;
        border: 0 !important;
    }

    /* ② 白底黑字：深色/3d 主题在纸上既费墨又看不清，表格相关元素一律拍平 */
    html[data-theme] body .erp-fit-table.erp-fit-table,
    html[data-theme] body .erp-fit-table.erp-fit-table > table,
    html[data-theme] body .erp-fit-table.erp-fit-table > table > thead,
    html[data-theme] body .erp-fit-table.erp-fit-table > table > thead > tr,
    html[data-theme] body .erp-fit-table.erp-fit-table > table > thead > tr > th,
    html[data-theme] body .erp-fit-table.erp-fit-table > table > tbody,
    html[data-theme] body .erp-fit-table.erp-fit-table > table > tbody > tr,
    html[data-theme] body .erp-fit-table.erp-fit-table > table > tbody > tr > th,
    html[data-theme] body .erp-fit-table.erp-fit-table > table > tbody > tr > td {
        background: transparent !important;
        background-image: none !important;
        background-color: transparent !important;
        color: #000 !important;
        box-shadow: none !important;
        text-shadow: none !important;
    }

    /* ③ 行高决定页数：Bootstrap .table 默认 padding 0.5rem（≈16px/行），
       报表 16~27 行就能多出 200px 以上，压掉它才收得进 1 页。 */
    html[data-theme] body .erp-fit-table.erp-fit-table > table {
        width: 100% !important;
        margin: 0 !important;
        font-size: var(--pr-font, 13px) !important;
        line-height: 1.3 !important;
        border-color: #adb5bd !important;
    }
    html[data-theme] body .erp-fit-table.erp-fit-table > table > thead > tr > th,
    html[data-theme] body .erp-fit-table.erp-fit-table > table > tbody > tr > td {
        padding: var(--pr-pad-y, 1px) var(--pr-pad-x, 5px) !important;
        border-color: #adb5bd !important;
    }

    /* ④ 只保留两处极浅灰底做层次（表头 / 合计与分组行），并显式允许其打印；
       其余背景一律不打印，省墨且对比度最高。 */
    html[data-theme] body .erp-fit-table.erp-fit-table > table > thead > tr > th {
        background-color: #e9ecef !important;
        -webkit-print-color-adjust: exact;
        print-color-adjust: exact;
    }
    html[data-theme] body .erp-fit-table.erp-fit-table > table > tbody > tr.table-light > td,
    html[data-theme] body .erp-fit-table.erp-fit-table > table > tbody > tr.table-secondary > td,
    html[data-theme] body .erp-fit-table.erp-fit-table > table > tbody > tr.table-primary > td,
    html[data-theme] body .erp-fit-table.erp-fit-table > table > tbody > tr.table-info > td,
    html[data-theme] body .erp-fit-table.erp-fit-table > table > tbody > tr.table-warning > td {
        background-color: #f1f3f5 !important;
        -webkit-print-color-adjust: exact;
        print-color-adjust: exact;
    }

    html[data-theme] body .erp-fit-table.erp-fit-table > table > thead {
        display: table-header-group;
    }
    html[data-theme] body .erp-fit-table.erp-fit-table > table > tbody > tr {
        break-inside: avoid;
        page-break-inside: avoid;
    }

    /* ⑤ 报表卡片：主题渐变 / 光泽伪元素 / 阴影全部去掉，且避免被拆到两页 */
    html[data-theme] body .erp-report-card.erp-report-card {
        background: #fff !important;
        border: 0 !important;
        box-shadow: none !important;
        margin-bottom: 3px !important;
        break-inside: avoid;
        page-break-inside: avoid;
    }
    html[data-theme] body .erp-report-card.erp-report-card > .card-header,
    html[data-theme] body .erp-report-card.erp-report-card > .card-header.inventory-wh-header,
    html[data-theme] body .erp-report-card.erp-report-card > .card-header.warehouse-dept-header,
    html[data-theme] body .erp-report-card.erp-report-card > .card-header.group-card-header {
        background: #fff !important;
        background-image: none !important;
        color: #000 !important;
        padding: 1px 5px !important;
        border-bottom: 1px solid #adb5bd !important;
        box-shadow: none !important;
        text-shadow: none !important;
    }
    html[data-theme] body .erp-report-card.erp-report-card > .card-header::before,
    html[data-theme] body .erp-report-card.erp-report-card > .card-header::after {
        display: none !important;
        content: none !important;
    }
    html[data-theme] body .erp-report-card.erp-report-card > .card-header :is(h1, h2, h3, h4, h5, h6) {
        color: #000 !important;
        text-shadow: none !important;
        font-size: 13px !important;
        font-weight: 700 !important;
        margin: 0 !important;
    }

    /* ⑥ 报表页标题与栅格：收紧，省纸 */
    html[data-theme] body h4 {
        font-size: 15px !important;
        margin: 0 0 4px 0 !important;
        color: #000 !important;
    }
    html[data-theme] body .row {
        --bs-gutter-x: 0.4rem !important;
        --bs-gutter-y: 0 !important;
    }
    html[data-theme] body .col-md-6 {
        padding-left: 4px !important;
        padding-right: 4px !important;
    }

    /* ⑦ 打印时 .text-muted 在纸面上太浅，加深 */
    html[data-theme] body .text-muted { color: #333 !important; }

    /* ⑧ 末列兜底：主题里 ".table > thead > tr > th:last-child" 会给「最后一列」
       铺主题渐变（本是为操作列设计），报表的末列（如「期末余额」）也会中招。
       这里用同样的 :last-child 伪类把权重顶到 (0,4,6) 才能压过它 (0,4,5)。 */
    html[data-theme] body .erp-fit-table.erp-fit-table > table > thead > tr > th:last-child,
    html[data-theme] body .erp-fit-table.erp-fit-table > table > tfoot > tr > th:last-child {
        background: #e9ecef !important;
        background-image: none !important;
        background-color: #e9ecef !important;
        color: #000 !important;
        text-shadow: none !important;
        box-shadow: none !important;
    }
    html[data-theme] body .erp-fit-table.erp-fit-table > table > tbody > tr > td:last-child {
        background: transparent !important;
        background-image: none !important;
        background-color: transparent !important;
        color: #000 !important;
        text-shadow: none !important;
    }

    /* ⑨ 卡片头残留装饰兜底：主题可能用伪元素或 border-image 画渐变装饰线，
       打印时一律清掉（只留一条灰底线分隔标题与表体）。 */
    html[data-theme] body .erp-report-card.erp-report-card > .card-header,
    html[data-theme] body .erp-report-card.erp-report-card > .card-header * {
        background-image: none !important;
        border-image: none !important;
        box-shadow: none !important;
        text-shadow: none !important;
    }
    html[data-theme] body .erp-report-card.erp-report-card > .card-header::before,
    html[data-theme] body .erp-report-card.erp-report-card > .card-header::after,
    html[data-theme] body .erp-report-card.erp-report-card > .card-header *::before,
    html[data-theme] body .erp-report-card.erp-report-card > .card-header *::after {
        display: none !important;
        content: none !important;
        border: 0 !important;
        background: none !important;
    }

    /* ⑩ 卡片头内部元素（h5 / 图标 / 徽章等）一律去底色与彩边，
       主题给标题加的下划线或光泽底衬在纸面上没有意义。 */
    html[data-theme] body .erp-report-card.erp-report-card > .card-header > *,
    html[data-theme] body .erp-report-card.erp-report-card > .card-header > * > * {
        background: none !important;
        background-image: none !important;
        border-color: transparent !important;
        filter: none !important;
        box-shadow: none !important;
    }

    /* ⑪ tfoot（如现金流量表的「期初/期末现金余额」）也要白底黑字。
       之前只覆盖了 thead/tbody，而 Bootstrap 的 `.table-light` 等类在暗色主题下
       会把该行的文字变量改成浅色 —— 白纸上就是「看不清」。 */
    html[data-theme] body .erp-fit-table.erp-fit-table.erp-fit-table > table > tfoot,
    html[data-theme] body .erp-fit-table.erp-fit-table.erp-fit-table > table > tfoot > tr,
    html[data-theme] body .erp-fit-table.erp-fit-table.erp-fit-table > table > tfoot > tr > th,
    html[data-theme] body .erp-fit-table.erp-fit-table.erp-fit-table > table > tfoot > tr > td {
        background-color: #e9ecef !important;
        background-image: none !important;
        color: #000 !important;
        border-color: #adb5bd !important;
        text-shadow: none !important;
        box-shadow: none !important;
        padding: var(--pr-pad-y, 1px) var(--pr-pad-x, 5px) !important;
        -webkit-print-color-adjust: exact;
        print-color-adjust: exact;
    }

    /* ⑫ 卡片头装饰动画（主题扫光 ::before）在打印件上只会留下一条残影，禁掉 */
    html[data-theme] body .erp-report-card.erp-report-card > .card-header,
    html[data-theme] body .erp-report-card.erp-report-card > .card-header::before,
    html[data-theme] body .erp-report-card.erp-report-card > .card-header::after {
        animation: none !important;
        transition: none !important;
    }

    /* ⑬ 表格顶部装饰线：主题会给 table / thead / th 铺极细的主题渐变描边，
       纸面上就是一条彩色细线，清掉（表头本身有浅灰底做分隔，不影响辨识）。 */
    html[data-theme] body .erp-fit-table.erp-fit-table.erp-fit-table > table,
    html[data-theme] body .erp-fit-table.erp-fit-table.erp-fit-table > table > thead,
    html[data-theme] body .erp-fit-table.erp-fit-table.erp-fit-table > table > thead > tr > th {
        border-top: 0 !important;
        border-image: none !important;
        background-image: none !important;
        box-shadow: none !important;
        outline: 0 !important;
    }
    html[data-theme] body .erp-fit-table.erp-fit-table.erp-fit-table > table > thead > tr > th::before,
    html[data-theme] body .erp-fit-table.erp-fit-table.erp-fit-table > table > thead > tr > th::after,
    html[data-theme] body .erp-fit-table.erp-fit-table.erp-fit-table > table::before,
    html[data-theme] body .erp-fit-table.erp-fit-table.erp-fit-table > table::after {
        display: none !important;
        content: none !important;
        border: 0 !important;
        background: none !important;
    }

    /* ⑭ 卡片自身的顶部装饰条（屏幕上是 3px 主题渐变，纸上就是一条彩色横线） */
    html[data-theme] body .erp-report-card.erp-report-card::before,
    html[data-theme] body .erp-report-card.erp-report-card::after {
        display: none !important;
        content: none !important;
        background: none !important;
        border: 0 !important;
    }

    /* ⑮ 终局兜底：报表卡片内「所有元素 + 所有伪元素」都不再绘制渐变背景图 /
       边框图 / 阴影 / 动画。主题装饰五花八门（卡片彩条、标题下划线、扫光、
       玻璃态内阴影…），逐个定位太脆，这里一次性拍平。
       只清 background-image / border-image / box-shadow / text-shadow / filter /
       animation，**不动 background-color** —— 表头与合计行的浅灰底仍保留。 */
    html[data-theme] body .erp-report-card.erp-report-card,
    html[data-theme] body .erp-report-card.erp-report-card * {
        background-image: none !important;
        border-image: none !important;
        box-shadow: none !important;
        text-shadow: none !important;
        filter: none !important;
        animation: none !important;
        transition: none !important;
    }
    html[data-theme] body .erp-report-card.erp-report-card::before,
    html[data-theme] body .erp-report-card.erp-report-card::after,
    html[data-theme] body .erp-report-card.erp-report-card *::before,
    html[data-theme] body .erp-report-card.erp-report-card *::after {
        display: none !important;
        content: none !important;
        background: none !important;
        border: 0 !important;
    }
}


/* ============================================================
   自适应 A4 打印模板（全站通用）
   ------------------------------------------------------------
   目标：任何页面（报表 / 列表 / 单据 / 档案）打印时都
         「铺满 A4、不裁切、字看得清、每页行数有上限」。

   ① 「只打印屏幕上看得见的那几行」——
      列表页表格装在 .erp-sticky-table 里：容器有 max-height + overflow:auto，
      且 base.html 的 erpInitStickyTables() 还会把 max-height 写进内联样式。
      打印时超出容器的行被裁掉，于是只出现可见的几行。
      这里在打印媒体强制 overflow:visible / max-height:none
      （!important 的样式表声明压得住内联样式），滚动区里的数据全部打印。

   ② 字号与行高不再硬编码，由 CSS 变量驱动，变量值由 base.html 的
      erpPrintFit() 在页面加载后 / 打印前按纸面算出来：
        · 内容少 → 字号放大（≤15px）、行高放大（≤34px），把纸面铺满；
        · 内容多 → 缩到一页放不下的可读下限后**不再缩**，改用固定行高
          自然分页（表头每页重复），保证每页行数固定、字始终看得清；
        · 纵向放不下（宽表格）→ 自动改 A4 横向。
      可用区：A4 纵向 190×277mm ≈ 718×1047px（边距 10mm）。

   ③ 「字看不清」——深色/3d 主题在屏幕上把文字设成浅色、给表头铺渐变，
      纸上就是浅字/彩条，且费墨。这里统一拍平成白底黑字，
      只保留表头（#e9ecef）与合计行（#f1f3f5）两层极浅灰，
      并用 print-color-adjust: exact 让底色真的打印出来。

   选择器写成 `html[data-theme] body .erp-main ...`：
   属性选择器 + 类名提高权重，用来压过主题里同样带 !important 的
   `[data-theme^="3d-"] .card-header.inventory-wh-header { ... !important }` 之类规则。
   ============================================================ */

@page {
    /* 只给页边距，**不写 size**（2026-09-20 修）：
       写了 size 就等于把纸张尺寸和方向钉死 —— Chromium 里 @page 的 size
       优先于打印对话框里的「布局：纵向/横向」，用户点横向也没用，
       于是全站变成「只能纵向、改不成横向」。
       方向与尺寸由引擎按需动态决定（base.html 的 erpPrintFit / writeVars）：
         · 自动 + 纵向 → 同样不写 size，纸张方向交还给打印对话框；
         · 自动判成横向（宽表格）或用户点了「强制横向/纵向」→ 才写 size。 */
    margin: 10mm;
}

:root {
    --pr-font: 11px;            /* 表格正文字号（erpPrintFit 会覆盖） */
    --pr-pad-y: 1.5px;          /* 单元格上下内边距（随字号缩放） */
    --pr-pad-x: 5px;            /* 单元格左右内边距 */
    --pr-row-h: 15px;           /* 行高下限：行不得低于此值，内容多则更高 */
}

@media print {
    /* ---------- ① 滚动容器全部展开：打印全部数据，而非屏幕上可见的部分 ----------
       2026-09-20 补：**各页面自造的内滚容器也要展开**。之前只认
       .erp-sticky-table / .table-responsive / .table-container，于是
       hr/employee_list.html 的 .emp-table-wrapper{max-height:calc(100vh - 440px);
       overflow-y:auto} 漏网 —— 员工档案打印只出前 12 行，E013~E020 整整 7 行
       被容器裁掉，而且因为裁切后总高「刚好」不超版心，引擎并不报分页、
       看着像正常 1 页（实测 PDF 末行停在 E012，两种纸都一样）。
       除显式列名外，再用 class 名通配兜底（table-wrapper / table-scroll /
       -scroll-box），以后新页面自造容器不必再回来改这里。 */
    html[data-theme] body .erp-main .erp-sticky-table,
    html[data-theme] body .erp-main .erp-sticky-table.erp-sticky-table,
    html[data-theme] body .erp-main .table-responsive,
    html[data-theme] body .erp-main .table-responsive.table-responsive,
    html[data-theme] body .erp-main .table-container,
    html[data-theme] body .erp-main .emp-table-wrapper,
    html[data-theme] body .erp-main [class*="table-wrapper"],
    html[data-theme] body .erp-main [class*="table-scroll"],
    html[data-theme] body .erp-main [class*="-scroll-box"] {
        overflow: visible !important;
        max-height: none !important;
        height: auto !important;
        border: 0 !important;
        border-radius: 0 !important;
    }

    /* ---------- ② 与纸面无关的元素不打印 ---------- */
    html[data-theme] body .erp-main .btn,
    html[data-theme] body .erp-main .pagination,
    html[data-theme] body .erp-main .page-link,
    html[data-theme] body .erp-main .page-item,
    html[data-theme] body .erp-main .breadcrumb,
    html[data-theme] body .erp-main .erp-print-skip,
    html[data-theme] body .erp-main form:has([type="submit"]),
    html[data-theme] body .erp-main input[type="checkbox"],
    html[data-theme] body .erp-main input[type="radio"] {
        display: none !important;
    }

    /* ---------- ③ 主内容区：白底黑字，去掉屏幕式的偏移与留白 ---------- */
    html[data-theme] body .erp-main {
        margin: 0 !important;
        padding: 0 !important;
        min-height: 0 !important;
        background: #fff !important;
        color: #000 !important;
    }
    html[data-theme] body .erp-main > .container-fluid,
    html[data-theme] body .erp-main .container-fluid {
        margin: 0 !important;
        padding: 0 !important;
    }

    /* ---------- ④ 主题装饰全面拍平（只清背景图/边框图/阴影/动画，保留底色） ---------- */
    html[data-theme] body .erp-main .card,
    html[data-theme] body .erp-main .card * {
        background-image: none !important;
        border-image: none !important;
        box-shadow: none !important;
        text-shadow: none !important;
        filter: none !important;
        animation: none !important;
        transition: none !important;
    }
    html[data-theme] body .erp-main .card::before,
    html[data-theme] body .erp-main .card::after,
    html[data-theme] body .erp-main .card *::before,
    html[data-theme] body .erp-main .card *::after {
        display: none !important;
        content: none !important;
        background: none !important;
        border: 0 !important;
    }
    html[data-theme] body .erp-main .card {
        background: #fff !important;
        border: 1px solid #dee2e6 !important;
        border-radius: 0 !important;
        margin-bottom: 3px !important;
    }
    /* 只有报表卡（内容固定、本来就 1 页）禁止内部断页。
       列表卡若也 avoid，整张长表会被当成一个不可分割块，
       浏览器只好把它推到下一页再硬裁，表现就是「数据显示不全」。 */
    html[data-theme] body .erp-main .erp-report-card {
        break-inside: avoid;
        page-break-inside: avoid;
    }
    html[data-theme] body .erp-main .card-body { padding: 2px 4px !important; }
    html[data-theme] body .erp-main .card-header,
    html[data-theme] body .erp-main .card-header.inventory-wh-header,
    html[data-theme] body .erp-main .card-header.warehouse-dept-header,
    html[data-theme] body .erp-main .card-header.group-card-header {
        background: #fff !important;
        background-image: none !important;
        color: #000 !important;
        border-bottom: 1px solid #adb5bd !important;
        box-shadow: none !important;
        text-shadow: none !important;
        padding: 1px 4px !important;
    }
    html[data-theme] body .erp-main h1,
    html[data-theme] body .erp-main h2,
    html[data-theme] body .erp-main h3,
    html[data-theme] body .erp-main h4,
    html[data-theme] body .erp-main h5,
    html[data-theme] body .erp-main h6,
    html[data-theme] body .erp-main .card,
    html[data-theme] body .erp-main .card-body,
    html[data-theme] body .erp-main p,
    html[data-theme] body .erp-main li,
    html[data-theme] body .erp-main label,
    html[data-theme] body .erp-main td,
    html[data-theme] body .erp-main th {
        color: #000 !important;
    }

    /* ---------- ⑤ 表格：铺满纸宽 + 变量驱动的字号/行高 + 分页规则 ---------- */
    html[data-theme] body .erp-main table {
        width: 100% !important;
        max-width: 100% !important;
        margin: 0 !important;
        font-size: var(--pr-font, 11px) !important;
        line-height: 1.3 !important;
        border-collapse: collapse !important;
        color: #000 !important;
    }
    html[data-theme] body .erp-main table > thead > tr > th,
    html[data-theme] body .erp-main table > tbody > tr > th,
    html[data-theme] body .erp-main table > tbody > tr > td,
    html[data-theme] body .erp-main table > tfoot > tr > th,
    html[data-theme] body .erp-main table > tfoot > tr > td {
        padding: var(--pr-pad-y, 1.5px) var(--pr-pad-x, 5px) !important;
        border-color: #adb5bd !important;
        background-image: none !important;
        color: #000 !important;
        text-shadow: none !important;
        box-shadow: none !important;
    }
    html[data-theme] body .erp-main table > thead > tr > th {
        background-color: #e9ecef !important;
        border-bottom: 1px solid #6c757d !important;
        font-weight: 700 !important;
        -webkit-print-color-adjust: exact;
        print-color-adjust: exact;
    }
    html[data-theme] body .erp-main table > tfoot > tr > th,
    html[data-theme] body .erp-main table > tfoot > tr > td,
    html[data-theme] body .erp-main table > tbody > tr.table-light > td,
    html[data-theme] body .erp-main table > tbody > tr.table-light > th,
    html[data-theme] body .erp-main table > tbody > tr.table-secondary > td,
    html[data-theme] body .erp-main table > tbody > tr.table-primary > td,
    html[data-theme] body .erp-main table > tbody > tr.table-info > td,
    html[data-theme] body .erp-main table > tbody > tr.table-warning > td,
    html[data-theme] body .erp-main table > tbody > tr.table-success > td,
    html[data-theme] body .erp-main table > tbody > tr.table-danger > td {
        background-color: #f1f3f5 !important;
        font-weight: 600 !important;
        -webkit-print-color-adjust: exact;
        print-color-adjust: exact;
    }
    /* 行高：CSS 里表格行的 height 是「下限」。
       于是 —— 内容少时由 --pr-row-h 把行撑开铺满纸面（有上限，
       1 行数据也不会占满整页）；内容多时行按内容自然变高，
       不会被压缩到看不清。 */
    html[data-theme] body .erp-main table > thead > tr,
    html[data-theme] body .erp-main table > tbody > tr,
    html[data-theme] body .erp-main table > tfoot > tr {
        height: var(--pr-row-h, 15px) !important;
        break-inside: avoid;
        page-break-inside: avoid;
    }
    /* 跨页时每页重复表头，合计行跟到最后一页 */
    html[data-theme] body .erp-main table > thead { display: table-header-group; }
    html[data-theme] body .erp-main table > tfoot { display: table-footer-group; }

    /* ---------- ⑬ 单元格「不截断」：列表表格用了
       `white-space:nowrap + text-overflow:ellipsis + overflow:hidden`
       把长内容截成「…」（金额被切成 ¥-218565.0… 就是这么来的），
       且 `min-width:960px` 比 A4 内容区(718px)还宽 —— 右侧整列出界被裁。
       打印时改成按内容自适应 + 允许换行，纸面上是完整数据。 */
    html[data-theme] body .erp-main table,
    html[data-theme] body .erp-main table.erp-table,
    html[data-theme] body .erp-main .table {
        min-width: 0 !important;
        table-layout: auto !important;
    }
    html[data-theme] body .erp-main table th,
    html[data-theme] body .erp-main table td {
        overflow: visible !important;
        text-overflow: clip !important;
        white-space: normal !important;
        word-break: break-word;
        overflow-wrap: anywhere;
    }

    /* ---------- ⑭ 解除吸顶/吸底：屏幕上的 .erp-sticky-table 表头是
       position:sticky(top:0)、合计行是 sticky(bottom:0)。分页打印时
       sticky 会贴到**每一页**的上下边缘并与正文重叠，表现就是
       「有些行被压住、显示不全」。纸上不需要吸附，改回静态定位；
       表头跨页重复由上方的 table-header-group 负责。 */
    html[data-theme] body .erp-main .erp-sticky-table > table > thead > tr > th,
    html[data-theme] body .erp-main .erp-sticky-table > table > tfoot > tr > th,
    html[data-theme] body .erp-main .erp-sticky-table > table > tfoot > tr > td,
    html[data-theme] body .erp-main thead th,
    html[data-theme] body .erp-main tfoot th,
    html[data-theme] body .erp-main tfoot td {
        position: static !important;
        top: auto !important;
        bottom: auto !important;
        z-index: auto !important;
    }

    /* ---------- ⑮ 版心归零：Bootstrap 的 .row 负外边距 + 列内边距
       会让内容比纸面宽出若干像素（实测 726px vs 可用 718px），
       右侧被裁，而且 JS 的「一页放得下」判定会永远失败 ——
       那就永远进不了「铺满 A4」模式。 */
    html[data-theme] body .erp-main .row {
        margin-left: 0 !important;
        margin-right: 0 !important;
    }
    html[data-theme] body .erp-main [class*="col-"] {
        padding-left: 0 !important;
        padding-right: 0 !important;
    }

    /* ---------- ⑯ 数据行不带底色：主题会给单元格铺浅灰底，屏幕上没问题，
       一上纸整张表就发灰、字也跟着显得浅。层次只留给表头与合计行
       （⑤ 里那两条选择器权重更高，语义行/合计行的浅灰底不受影响）。 */
    html[data-theme] body .erp-main table > tbody > tr > td,
    html[data-theme] body .erp-main table > tbody > tr > th {
        background-color: transparent !important;
        background-image: none !important;
    }

    /* ---------- ⑰ 语义弱化文字在纸上加深：.text-muted 等取的是
       var(--erp-text-muted) —— 为深色屏幕挑的浅色，打印出来几乎看不见
       （应付款里「其中期初预付 ¥…」就是这么丢的）。
       主题那条 [data-bs-theme="dark"] .text-muted 权重只有 (0,2,0)，
       这里 (0,4,3) 且同为 !important，压得住。 */
    html[data-theme] body .erp-main .text-muted,
    html[data-theme] body .erp-main .text-body-secondary,
    html[data-theme] body .erp-main .text-secondary,
    html[data-theme] body .erp-main .form-text,
    html[data-theme] body .erp-main small {
        color: #444 !important;
    }
    html[data-theme] body .erp-main table > tbody > tr > td .small,
    html[data-theme] body .erp-main table > tbody > tr > td small {
        color: #4a4a4a !important;
    }

    /* ---------- ⑥ 语义色在纸上加深（深色主题的浅色文字会被这里纠正） ---------- */
    html[data-theme] body .erp-main .text-muted,
    html[data-theme] body .erp-main .text-secondary,
    html[data-theme] body .erp-main .text-body-secondary,
    html[data-theme] body .erp-main small,
    html[data-theme] body .erp-main .small { color: #333 !important; }
    html[data-theme] body .erp-main .text-primary { color: #0a4a9e !important; }
    html[data-theme] body .erp-main .text-success { color: #14652c !important; }
    html[data-theme] body .erp-main .text-danger { color: #a1121b !important; }
    html[data-theme] body .erp-main .text-info { color: #0b5c6b !important; }
    html[data-theme] body .erp-main .text-warning { color: #7a4a00 !important; }
    html[data-theme] body .erp-main .fw-bold,
    html[data-theme] body .erp-main strong,
    html[data-theme] body .erp-main b { color: #000 !important; }
    html[data-theme] body .erp-main .badge {
        background: #f1f3f5 !important;
        border: 1px solid #adb5bd !important;
        color: #000 !important;
    }

    /* ---------- ⑱ 资产负债表：纸面把左右两栏钉死成 50%/50% ----------
       Bootstrap 的 .col-md-6 落在 @media (min-width:768px) 里，而打印时这个断点
       按「纸张盒」算：A4 纵向可打印区只有 190mm = 718px < 768px，于是两栏会退化成
       上下堆叠 —— 同一个浏览器在不同打印入口（对话框预览 / headless --print-to-pdf）
       下取值还可能不一样，屏幕上并排、纸上却堆叠，左边右边根本没法对着看。
       这里不依赖任何断点，直接把两栏钉死：纸面永远是并排的。
       内边距与「测量环境」严格对齐（见 balance_sheet.html 里 html.erp-measuring
       的同名规则），否则在测量里算出的补行数与纸面不符。 */
    html[data-theme] body .erp-main .bs-row {
        display: flex !important;
        flex-wrap: nowrap !important;
        margin-left: 0 !important;
        margin-right: 0 !important;
    }
    html[data-theme] body .erp-main .bs-row > .bs-left,
    html[data-theme] body .erp-main .bs-row > .bs-right {
        flex: 0 0 50% !important;
        width: 50% !important;
        max-width: 50% !important;
    }
    html[data-theme] body .erp-main .bs-row > .bs-left {
        padding-left: 0 !important;
        padding-right: 4px !important;
    }
    html[data-theme] body .erp-main .bs-row > .bs-right {
        padding-left: 8px !important;
        padding-right: 0 !important;
    }
    /* ⑲ 金额列不许折行（2026-09-20）：⑬ 给所有单元格开了 word-break:break-word，
       列一窄就会把「¥2125736.95」硬拆成「¥2125736.9 / 5」两行 ——
       A4 纵向 + 左右两栏（各 355px）+ 14px 字号下必现（实测打印截图）。
       右对齐的数字列本来就该整串显示：改成 nowrap，宽度交给 table-layout:auto
       分配，装不下时优先挤「项目」列的中文（中文换行是正常的）。 */
    html[data-theme] body .erp-main table td.text-end,
    html[data-theme] body .erp-main table th.text-end {
        white-space: nowrap !important;
        overflow-wrap: normal !important;
        word-break: keep-all !important;
    }

    /* ⑲b 单号 / 日期列不许折行（2026-09-23）：加工费报表页的「结算日期」
       「合并结算单号」「单据号」在 A4 纵向窄列下被 ⑬ 的 break-word 硬拆成
       「2026-06-」/「05」、「SSET-20260826-」/「002」两行，行高翻倍。
       模板上已写 Bootstrap `.text-nowrap`，但它权重 (0,1,0) 低于 ⑬ 的
       `html[data-theme] body .erp-main table td` (0,2,3)，同为 !important 时被压掉，
       所以这里按类名显式豁免。 */
    html[data-theme] body .erp-main table td.text-nowrap,
    html[data-theme] body .erp-main table th.text-nowrap {
        white-space: nowrap !important;
        overflow-wrap: normal !important;
        word-break: keep-all !important;
    }

    /* ⑲c 单号 / 日期列不许折行（2026-10-10）：销售出库、采购入库等列表页把
       「出库单号 / 入库单号」写成 `<th class="col-no" style="width:170px;
       white-space:nowrap">` —— **内联样式**不是 Bootstrap `.text-nowrap` 类，
       ⑲b 的豁免覆盖不到它，⑬ 的 `white-space:normal !important` 照样把内联
       nowrap 压掉。真实出纸实测症状：A4 纵向下该列被压到**一个字符宽**，
       `SO-20260827-001` 逐字竖排、行高被撑到 ~300px，
       **10 行数据印成 4 页**（采购入库 58 行印 7 页、每页只有 8 行）。
       按列类名显式豁免，与 ⑲/⑲b 同源。 */
    html[data-theme] body .erp-main table td.col-no,
    html[data-theme] body .erp-main table th.col-no,
    html[data-theme] body .erp-main table td.col-date,
    html[data-theme] body .erp-main table th.col-date {
        white-space: nowrap !important;
        overflow-wrap: normal !important;
        word-break: keep-all !important;
    }

    /* ⑳ 打印态列宽交回内容（2026-10-10）：列表页模板为了屏幕上的横向滚动，
       给若干列写了**内联** `style="width:170px"`（出库单号）、`width:140px`（客户）、
       `width:85px`（物料种类）…… 纸上没有横向滚动，这些「奢侈宽度」会挤掉末尾列：
       实测销售出库打印视图（A4 横向 1047px、12 列）里，「部门/状态/创建人」只剩
       ~35px/列，「系统管理员」被竖排成 3 行 ⇒ 行高翻倍 ⇒ 10 行数据溢出到第 2 页。
       `table-layout` 已由 ⑬ 设为 auto ⇒ 解除内联宽度后由内容分配即可。
       ★ 内联样式的特异性最高，必须用 !important 才压得住（⑬/⑲b 同理）。 */
    html[data-theme] body .erp-main table th[style*="width"],
    html[data-theme] body .erp-main table td[style*="width"] {
        width: auto !important;
        min-width: 0 !important;
        max-width: none !important;
    }

    /* 补行不得参与分页控制：它是空白行，不许把「资产总计」顶到下一页 */
    html[data-theme] body .erp-main .bs-left tr.bs-filler,
    html[data-theme] body .erp-main .bs-left tr.bs-filler > td {
        break-inside: auto !important;
        page-break-inside: auto !important;
        border-color: transparent !important;
    }
    /* ⑱b 纸面高度兜底（2026-09-20）：补行只能整行补，最后必剩不足一行的余量
       （纸面行距 21.5px，半行就是 10px）。这里让左栏表格撑满卡片正文高度 ——
       表格的 height 是「下限」，多出来的高度会被浏览器平摊到各行，
       于是「资产总计」正好落在卡片底部，与右栏最后一行像素级齐平，
       而每行只多零点几像素，肉眼看不出来。
       注意：只有左栏这么做。右栏是两张卡片、由内容撑高，是基准。
       纸面若退化成上下堆叠（极窄场景），card-body 高度为 auto，
       height:100% 解析成 auto → 自动失效，不会误伤。 */
    html[data-theme] body .erp-main .bs-left > .card > .table-responsive,
    html[data-theme] body .erp-main .bs-left > .card > .erp-fit-table {
        flex: 1 1 auto !important;
        overflow: visible !important;
        max-height: none !important;
    }
    html[data-theme] body .erp-main .bs-left > .card > .table-responsive > table,
    html[data-theme] body .erp-main .bs-left > .card > .erp-fit-table > table {
        height: 100% !important;
    }
}

/* ============================================================
   ⑳ 仪表盘顶部「利润中心利润表」（2026-09-24）
   —— 全部使用主题变量 var(--erp-*)，14 个主题自动匹配，**不硬编码任何颜色**。
   ============================================================ */
.erp-pm-year { width: auto; }

.erp-pm-table thead.erp-pm-head th {
    background: var(--erp-table-head-bg);
    color: var(--erp-table-head-color);
    border-color: var(--erp-table-border);
    font-weight: 600;
}
.erp-pm-table tfoot.erp-pm-foot td {
    background: var(--erp-table-head-bg);
    color: var(--erp-text);
    border-color: var(--erp-table-border);
}
.erp-pm-table td, .erp-pm-table th { border-color: var(--erp-table-border); }

/* 利润中心列吸附左侧：横向滚动（窄屏）时始终可见（内容居中） */
.erp-pm-table .erp-pm-dept {
    position: sticky;
    left: 0;
    z-index: 2;
    background: var(--erp-card-bg);
    color: var(--erp-text);
    text-align: center;   /* 2026-09-24 用户要求：红框内全部居中，首列不再左对齐 */
}
.erp-pm-table thead .erp-pm-dept {
    background: var(--erp-table-head-bg);
    color: var(--erp-table-head-color);
    z-index: 3;
}
.erp-pm-table tfoot .erp-pm-dept { background: var(--erp-table-head-bg); }

/* 年合计列加一道分隔线，与 12 个月列区分开 */
.erp-pm-table .erp-pm-sum { border-left: 2px solid var(--erp-table-border); }

/* 全表内容居中（表头 / 数据行 / 合计行一律居中），2026-09-24 用户要求。
   注意：Bootstrap 的 .text-end 带 !important，非 !important 规则压不住它，
   所以模板里表头的对齐类必须写 text-center（已在 dashboard/index.html 落地），
   本规则负责把「无对齐类的数据格」也一并居中对齐。 */
.erp-pm-table th,
.erp-pm-table td { text-align: center; }
/* 列宽固定：**不随数据变化**。
   2026-09-24 用户反馈「有数据的月份列宽变宽了，如果全部有数据，那都会变宽，页面就无法显示完整」——
   根因是默认 table-layout:auto 由内容撑开列宽：含金额的列必然比只含「—」的列宽一倍多。
   fixed 布局下列宽只由下面几条决定，与单元格内容无关；12 个月列不写宽度 → 自动等分剩余空间，永远等宽。
   ★ 宽度预算一律取**浏览器实测值**（headless Edge + canvas measureText，不靠「每字符 0.6em」的估算）：
     字号 .7rem = 11.2px「Courier New」→ 实测每字符 6.721px（12 字符 = 80.65px）
   2026-09-24 用户追问「年合计列按「-」+千万+小数 2 位，列宽够不够？」→ 实测原 4.9rem(78.4px)
   装不下：12 字符需 80.65px，而该列内容可用宽只有 77.0px（判溢出）。故调整如下：
     · padding 收到 .2rem(3.2px/边)：13 个金额列各腾出 3.2px
     · 年合计列 5.7rem(91.2px) → 内容可用 84.8px ≥ 80.65px（装得下 12 字符，余量 4.15px）
     · 单个月列保底装 10 字符（-123456.78）：需 67.21 + 6.4 = 73.6px
     整表 = 首列 4.3rem(68.8) + 年合计 5.7rem(91.2) + 12 × 77.33 = 1088px = 68rem
        （月列 = (1088 − 68.8 − 91.2) / 12 = 77.33px，可用 70.93px ≥ 73.6 的文本部分 67.21px）
   → 内容区 ≥1088px **完全不需要横向滚动**；容器更宽时月列自动变宽（1280 容器下同样装得下 12 字符）。
   更窄时才由 .table-responsive 滚动 —— 宁可滚动，也不让列被数据撑变形。 */
.erp-pm-table { table-layout: fixed; width: 100%; min-width: 68rem; }
/* ⚠ 字号**必须写在这一层**：全站有 `.table td { font-size: .875rem }`(=14px，特异性 0,1,1)，
   只写在 `.erp-pm-table`(0,1,0) 上会被它压掉 —— 浏览器实测过：14px 下 9 字符金额要 86.8px，
   直接顶出列宽（连 123647.00 都溢出）。td 层选择器是 (0,1,4)，才能压住。 */
table.erp-pm-table > thead > tr > th,
table.erp-pm-table > tbody > tr > td,
table.erp-pm-table > tfoot > tr > td { padding: .2rem; font-size: .7rem; }
.erp-pm-table .erp-pm-dept { width: 4.3rem; }
.erp-pm-table .erp-pm-sum { width: 5.7rem; }
/* 超出上述预算的金额（单月 >10 字符 / 年合计 >12 字符，如亿级）fixed 布局下会压到相邻单元格
   —— 用省略号兜底，模板已把金额写进 title，悬停仍可看到完整数字。 */
table.erp-pm-table td.amount { overflow: hidden; text-overflow: ellipsis; }


/* 当前月高亮：**淡底纹 + 加粗**。
   2026-09-24 用户反馈「太亮，耀眼」：原为 `box-shadow: inset 0 0 0 2px var(--erp-accent)`，
   而 --erp-accent 是高饱和主色（tech-neon #22d3ee / 3d-gold #f59e0b / dark-green #34d399），
   2px 整圈内描边落在暗色单元格上过于刺眼。
   现改用主题「选中态」变量 --erp-sidebar-active-bg 做淡底纹 ——
   14 个主题里它一律是低对比度底色（浅主题 #dbeafe、暗主题 #1e3a5f），
   在单元格底色上只「比周围略深一点」，看得清但不抢眼。
   仍然零硬编码颜色、不依赖 color-mix()、不使用主色描边。 */
.erp-pm-table .erp-pm-cur {
    background: var(--erp-sidebar-active-bg);
    font-weight: 600;
}
/* 表头行与合计行自身已带 --erp-table-head-bg 底色，浅色主题下与选中态底色色差偏小，
   故表头再叠一层文字配色（--erp-sidebar-active-color 与底色是主题里成对的组合）。 */
.erp-pm-table thead.erp-pm-head th.erp-pm-cur {
    background: var(--erp-sidebar-active-bg);
    color: var(--erp-sidebar-active-color);
}
.erp-pm-table tfoot.erp-pm-foot td.erp-pm-cur {
    background: var(--erp-sidebar-active-bg);
}

/* 可下钻单元格 */
.erp-pm-cell[data-drill-url] { cursor: pointer; }
.erp-pm-cell[data-drill-url]:hover {
    background: var(--erp-sidebar-hover-bg);
    color: var(--erp-sidebar-hover-color);
}

/* 空值「—」与锁标识 */
.erp-pm-empty { color: var(--erp-text-muted); }
.erp-pm-lock {
    background: var(--erp-sidebar-active-bg);
    color: var(--erp-sidebar-active-color);
}
.erp-pm-note { background: var(--erp-card-bg); color: var(--erp-text-muted); }
/* ============================================================
   ㉑ 仪表盘「各利润中心本期利润预估」卡片（2026-09-28）
   —— 只用主题变量 var(--erp-*)，14 个主题自动匹配，**不硬编码任何颜色**。
   —— 版式：上半 5 个指标 2 列网格（上月库存/本月库存 · 本月采购/本月销售 · 本月费用），
      下半一条「本期利润预估」高亮条。
   ============================================================ */
.erp-pe-sel { width: auto; min-width: 5.4rem; }
#profit-estimate-card .card-body { padding: .85rem 1rem; }
.erp-pe-card {
    border: 1px solid var(--erp-table-border);
    border-radius: .5rem;
    background: var(--erp-card-bg);
    overflow: hidden;
}
.erp-pe-head {
    display: flex; justify-content: space-between; align-items: center; gap: .5rem;
    padding: .4rem .7rem;
    background: var(--erp-table-head-bg);
    color: var(--erp-table-head-color);
    font-weight: 600;
}
.erp-pe-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.erp-pe-period { flex: 0 0 auto; font-size: .78rem; font-weight: 400; opacity: .85; }
.erp-pe-grid {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: .3rem .8rem;
    padding: .55rem .7rem;
}
.erp-pe-cell {
    display: flex; justify-content: space-between; align-items: baseline; gap: .5rem;
    font-size: .8rem; min-width: 0;
}
.erp-pe-label { color: var(--erp-text-muted); flex: 0 0 auto; }
/* 金额右对齐 + 等宽数字；nowrap + 省略号防止窄屏把布局顶破（悬停 title 看全值）。
   ★ 角标/金额一律 flex:0 0 auto 且 nowrap —— 被 flex 压缩或被 overflow 裁掉都会「显示不全」。 */
.erp-pe-val {
    flex: 0 1 auto;
    font-variant-numeric: tabular-nums;
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
    color: var(--erp-text);
}
.erp-pe-foot {
    display: flex; justify-content: space-between; align-items: baseline; gap: .5rem;
    padding: .45rem .7rem;
    border-top: 1px solid var(--erp-table-border);
    background: var(--erp-sidebar-active-bg);
    color: var(--erp-sidebar-active-color);
}
.erp-pe-foot strong { font-variant-numeric: tabular-nums; }
.erp-pe-total {
    display: flex; justify-content: space-between; align-items: baseline; gap: .5rem;
    margin-top: .7rem; padding: .5rem .7rem;
    border: 1px dashed var(--erp-table-border);
    border-radius: .5rem;
    background: var(--erp-card-bg);
    color: var(--erp-text);
}
.erp-pe-note { background: var(--erp-card-bg); color: var(--erp-text-muted); }

/* ============================================================
   ㉒ 仪表盘「各采购部采购数量统计」（2026-09-28）
   —— 本表**刻意复用 .erp-pm-table 全套版式**：列宽预算（5.7rem 合计列 / 4.3rem 首列）、
      table-layout:fixed、首列 sticky、当前月高亮、.erp-pm-empty「—」、.erp-pm-foot 合计行，
      故这里**只补一个本表独有的元素** —— 「全部采购部」徽标（语义与 erp-pm-lock 相反：
      那个是「被锁到本部门」，这个是「不做部门隔离」，绝不能复用同一个类名）。
      仍只用 var(--erp-*)，主题自动匹配。
   ============================================================ */
#purchase-qty-card .erp-pq-all {
    background: var(--erp-sidebar-active-bg);
    color: var(--erp-sidebar-active-color);
    font-weight: 500;
}
/* 数量列比金额列短（吨最多 8 字符），但**刻意沿用与利润矩阵相同的列宽预算**，
   让上下两张表的「合计」列在视觉上对齐；窄屏统一由 .table-responsive 滚动。 */

/* ============================================================
   利润中心利润表 · 柱状图（2026-09-29）
   —— 版式 = 用户选定的设计预览「A 方案」+ 用户三项调整：
       ① 部门名称放**柱子下面**（不进柱体）⇒ 不再受「柱太矮放不下名字」限制
          （本月最高/最矮有值柱差 31 倍，柱内竖排名只有 5/15 放得下，故移到柱下）
       ② 期间可筛「全年 / 1~12 月」
       ③ 「显示」可单独选一个部门 ⇒ 1~12 月柱 + 趋势折线
   —— 零轴几何（★ 关键）：
        每列自上而下 = [盈利区 --pbc-pos][亏损区 --pbc-neg][名称带]
        盈利柱在 pos 区 `justify-content:flex-end` ⇒ 贴零轴**向上**长
        亏损柱在 neg 区 `justify-content:flex-start` ⇒ 贴零轴**向下**长
        零轴 = .erp-pbc-zero 绝对定位 top:var(--pbc-pos) 的 1px 线
        - 亏损柱在 neg 内是 [bar][amt] 顺序：bar 贴零轴、金额在柱底下侧
        - 盈利柱在 pos 内是 [amt][bar] 顺序：bar 贴零轴、金额在柱顶上侧
      两侧柱都从同一条零轴长出 ⇒ 实测偏差 ≤1px
   —— 颜色全走 var(--erp-chart-*)，主题自动匹配（深色由 [data-bs-theme=dark] 派生）
   ============================================================ */
.erp-pbc-sel { width: auto; min-width: 6.4rem; }
.erp-pbc-legend {
    display: flex; align-items: center; gap: .9rem; flex-wrap: wrap;
    font-size: .75rem; color: var(--erp-text-muted); margin-bottom: .45rem;
}
.erp-pbc-dot {
    display: inline-block; width: .62rem; height: .62rem; border-radius: 2px;
    margin-right: .3rem; vertical-align: -1px;
}
.erp-pbc-dot.is-pos { background: var(--erp-chart-pos); }
.erp-pbc-dot.is-neg { background: var(--erp-chart-neg); }
.erp-pbc-line-lg {
    display: inline-block; width: 1rem; border-top: 2px solid var(--erp-chart-trend);
    margin-right: .3rem; vertical-align: .18rem;
}
.erp-pbc-sum { margin-left: auto; font-variant-numeric: tabular-nums; }
.erp-pbc-plot {
    position: relative; display: flex; align-items: flex-start; gap: 2px;
    padding: 0 .35rem;
}
.erp-pbc-zero {
    position: absolute; left: .35rem; right: .35rem; top: var(--pbc-pos, 0px);
    height: 1px; background: var(--erp-chart-zero);
}
/* 趋势折线覆盖层
   ★ 2026-09-29 实测教训：**不要用 viewBox 缩放 + preserveAspectRatio=none + vector-effect
     的组合** —— 那样算出来的坐标空间不可靠（实测 path 的 getBBox 只有 27.6/100 宽，
     折线只在个别柱缝里露出一点点）。改成**纯像素坐标**：不用 viewBox、不用 vector-effect，
     宽高由 JS 按绘图区实测尺寸写死，path 的坐标就是相对绘图区的 px。
   z-index:2 ⇒ 折线画在柱子**之上**（柱顶连线的部位本该盖住柱顶，才看得见趋势）。 */
.erp-pbc-trend { position: absolute; left: 0; top: 0; z-index: 2; pointer-events: none; }
.erp-pbc-trend path {
    fill: none; stroke: var(--erp-chart-trend); stroke-width: 2;
    stroke-linejoin: round; stroke-linecap: round;
}
.erp-pbc-col { flex: 1 1 0; min-width: 0; display: flex; flex-direction: column; }
/* overflow:visible —— 金额文字窄列时可以探出一点点，宁可轻微出格也不截断数字 */
.erp-pbc-pos, .erp-pbc-neg {
    display: flex; flex-direction: column; align-items: center; overflow: visible;
}
.erp-pbc-pos { height: var(--pbc-pos, 0px); justify-content: flex-end; }
.erp-pbc-neg { height: var(--pbc-neg, 0px); justify-content: flex-start; }
.erp-pbc-bar { width: min(56px, 74%); }
.erp-pbc-bar.is-pos { background: var(--erp-chart-pos); border-radius: 2px 2px 0 0; }
.erp-pbc-bar.is-neg { background: var(--erp-chart-neg); border-radius: 0 0 2px 2px; }
.erp-pbc-amt {
    font-size: .68rem; line-height: 1.1; white-space: nowrap; letter-spacing: -.01em;
    color: var(--erp-text); font-variant-numeric: tabular-nums;
}
.erp-pbc-amt.is-neg { color: var(--erp-neg-text); }
.erp-pbc-amt.is-zero { color: var(--erp-text-muted); }
.erp-pbc-none { font-size: .7rem; line-height: 1.1; color: var(--erp-text-muted); }
.erp-pbc-name {
    height: 2.4rem; font-size: .72rem; line-height: 1.2; text-align: center;
    color: var(--erp-text); overflow: hidden; padding: 0 1px;
}
.erp-pbc-col.is-drillable { cursor: pointer; }
.erp-pbc-col.is-drillable:hover .erp-pbc-name { color: var(--erp-accent); }
.erp-pbc-col.is-drillable:hover .erp-pbc-bar { filter: brightness(1.12); }
.erp-pbc-empty {
    text-align: center; padding: 1.4rem .5rem; color: var(--erp-text-muted); font-size: .82rem;
}
.erp-pbc-empty i { font-size: 1.3rem; display: block; margin-bottom: .35rem; }
.erp-pbc-empty .btn { margin-left: .5rem; }
.erp-pbc-hint {
    margin-top: .5rem; padding: .3rem .5rem; border-radius: .25rem;
    background: var(--erp-table-head-bg); color: var(--erp-text-muted);
}

/* ============================================================
   仪表盘「经典模式 / 图表模式」（2026-09-29 用户需求）
   —— 用户口径：页头右侧两枚按钮切换显示模式；
        经典模式 = 现有 3 张表卡（矩阵表 / 利润预估卡 / 采购统计表）；
        图表模式 = 柱状图利润表 + 利润预估图 + 采购统计图。
   —— ★ 切换**只改可见性、不重发请求**（模式记在浏览器 localStorage，
        刷新后保持；不写 session / 数据库，无服务端状态）。
   —— ★ 用 class 控制显示，**不用 `hidden` 属性**：
        本项目已踩过「`[hidden]` 只来自 UA 样式表，遇到任何 CSS 里写了 display
        的规则就失效」的坑（`.miniwrap{display:flex}` 让 hidden 形同虚设）。
        这里直接 `.erp-mode-pane{display:none}` + 显式 display，无优先级博弈。
   —— 默认「经典」由 CSS 兜底（不依赖 JS），`<html>.erp-dash-chart` 由页头里
        一小段内联脚本在**解析到卡片之前**加上 ⇒ 选图表模式刷新时不会先闪一下经典模式。
   ============================================================ */
.erp-mode-pane { display: none; }
.erp-mode-pane[data-pane="classic"] { display: block; }
html.erp-dash-chart .erp-mode-pane[data-pane="classic"] { display: none; }
html.erp-dash-chart .erp-mode-pane[data-pane="chart"] { display: block; }

.erp-mode-switch {
    margin-left: auto; display: inline-flex; align-items: center; gap: 2px;
    padding: 2px; border: 1px solid var(--erp-table-border); border-radius: 1.4rem;
    background: var(--erp-card-bg);
}
.erp-mode-btn {
    display: inline-flex; align-items: center; gap: .35rem;
    border: 0; background: transparent; color: var(--erp-text-muted);
    border-radius: 1.25rem; padding: .28rem .8rem; font-size: .8rem;
    line-height: 1.35; cursor: pointer; white-space: nowrap;
}
.erp-mode-btn:hover { color: var(--erp-text); }
/* ★ 选中态底色：**不能**直接拿 --erp-accent 当底再配白字 —— 实测 14 个主题的
   accent 亮度横跨太广：3d-titanium 亮蓝 #60a5fa 配白字只有 2.54:1；
   而 light-green #059669 / light-warm #ea580c 这类中间亮度配白字 3.5~3.8、
   配黑字也只有 5.9，两头都踩不到 4.5 的做法线。「白字 or 黑字」的任何二分都不成立。
   做法：把 accent 压暗 45% 再配白字 —— 与 accent 原本的明暗无关，实测一律 ≥7:1。
   @supports 兜底：不支持 color-mix 的老内核退回 accent 原色 + 白字（即改动前行为）。 */
.erp-mode-btn.is-on {
    background: var(--erp-accent); color: #fff; font-weight: 600;
}
@supports (background: color-mix(in srgb, red 50%, black)) {
    .erp-mode-btn.is-on {
        background: color-mix(in srgb, var(--erp-accent) 55%, #000);
    }
}
.erp-mode-btn.is-on:hover { color: #fff; }
.erp-mode-btn:focus-visible { outline: 2px solid var(--erp-accent); outline-offset: 1px; }

/* ---------- 图表模式 · 利润预估「蝴蝶条 + 五要素」（E2）----------
   一行 = [部门名 9rem][蝴蝶轨 flex][4 个要素 25rem][本期利润 7.6rem]
   ★ 零轴**不写死像素**：轨道是 flex:1，实际中点随容器宽度变化，
     零轴线位置与条长比例都由 JS 在**显示之后**用 getBoundingClientRect() 实测。
     （预览版曾把零轴写死 290px，换宽度就错位；`display:none` 下量到的是 0。）
   ★ 条长按**全表最大值归一**（不是盈亏平衡比例）—— 与预览页口径一致。 */
.erp-e2-scroll { overflow-x: auto; }
.erp-e2-inner { min-width: 60rem; }
.erp-e2-head, .erp-e2-row {
    display: flex; align-items: center; gap: .5rem;
}
.erp-e2-head {
    font-size: .68rem; color: var(--erp-text-muted);
    padding-bottom: .35rem; border-bottom: 1px solid var(--erp-table-border);
    margin-bottom: .25rem;
}
.erp-e2-hd-tr { flex: 1 1 auto; min-width: 6rem; display: flex; }
.erp-e2-hd-tr span:first-child { flex: 1; text-align: right; padding-right: .5rem; }
.erp-e2-hd-tr span:last-child { flex: 1; padding-left: .5rem; }
.erp-e2-nm {
    width: 9rem; flex: 0 0 9rem; font-size: .75rem;
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.erp-e2-tr {
    flex: 1 1 auto; min-width: 6rem; position: relative; height: 1.6rem;
}
.erp-e2-nums { width: 25rem; flex: 0 0 25rem; display: flex; }
.erp-e2-nc {
    flex: 1 1 0; min-width: 0; font-size: .66rem; text-align: right;
    padding-right: .4rem; font-variant-numeric: tabular-nums; overflow: hidden;
}
.erp-e2-nc i {
    font-style: normal; display: block; color: var(--erp-text-muted); font-size: .6rem;
}
.erp-e2-pl {
    width: 7.6rem; flex: 0 0 7.6rem; text-align: right; font-size: .72rem;
    font-weight: 700; font-variant-numeric: tabular-nums;
}
.erp-e2-bar { position: absolute; top: .33rem; height: .95rem; border-radius: 2px; }
.erp-e2-bar.is-pos { background: var(--erp-chart-pos); }
.erp-e2-bar.is-neg { background: var(--erp-chart-neg); }
.erp-e2-lab {
    position: absolute; top: .38rem; font-size: .66rem; color: var(--erp-text-muted);
    white-space: nowrap; font-variant-numeric: tabular-nums;
}
.erp-e2-body { position: relative; }
.erp-e2-zero {
    position: absolute; top: 0; bottom: 0; width: 1px;
    background: var(--erp-chart-zero);
}
.erp-e2-row { padding: .12rem 0; }
.erp-e2-row:hover { background: var(--erp-table-head-bg); }
/* 亏损数字用单列的 --erp-neg-text（柱色不能当文字色，见文件头注释）
   ★ 选择器必须与模板**实际生成的 class** 对齐：模板给「库存净变动为负」的
     `.erp-e2-nc` 和「利润为负」的 `.erp-e2-pl` 加 `is-neg`（不是另起一个
     `.erp-e2-txt` 包一层）—— 第一版只写了 `.erp-e2-txt.is-neg`，
     结果负值一个都不变红（静默失效，DOM 上完全看不出来）。 */
.erp-e2-nc.is-neg,
.erp-e2-pl.is-neg,
.erp-e2-txt.is-neg { color: var(--erp-neg-text); }

/* ---------- 图表模式 · 采购统计「12 月多折线」（P3）----------
   8 条部门线同轴；★ 比例尺**只按部门峰值**，不把「Σ 采购部」合计算进来 ——
   实测部门峰值与合计峰值差约 5 倍，同轴会把 8 条部门线全压到最底下两成
   （预览阶段量出来才发现）；总量趋势由 P1 堆叠柱承担，所以这里不画合计线。
   缺月断开不连线（避免连出假趋势）。SVG 宽度由 JS 按容器实测宽度写，随窗口重算。 */
.erp-p3-wrap { position: relative; overflow-x: auto; }
.erp-p3-wrap svg { display: block; }

/* ---------- 图表模式共用 · 图例 ---------- */
.erp-lg {
    display: flex; align-items: center; gap: .7rem; flex-wrap: wrap;
    font-size: .72rem; color: var(--erp-text-muted); margin-bottom: .55rem;
}
.erp-lg .it { display: inline-flex; align-items: center; gap: .25rem; white-space: nowrap; }
.erp-lg .sw {
    width: .62rem; height: .62rem; border-radius: 2px; display: inline-block;
}
.erp-lg .sumb {
    margin-left: auto; color: var(--erp-text); font-variant-numeric: tabular-nums;
}
.erp-p3-note, .erp-e2-note {
    font-size: .72rem; color: var(--erp-text-muted); padding: .35rem .5rem;
    border-radius: .25rem; background: var(--erp-table-head-bg); margin-top: .5rem;
}
.erp-p3-note b, .erp-e2-note b { color: var(--erp-text); }
.erp-p3-empty, .erp-e2-empty {
    padding: 1.4rem .5rem; text-align: center;
    color: var(--erp-text-muted); font-size: .82rem;
}

/* ---------- 额外关联部门 · 勾选组（2026-09-29 改造）----------
   背景：原为 <select multiple size="3"> —— 本库 19 个部门，一屏只看得见 3 行，
   必须按住 Ctrl 才能多选，选错一个就得整个重来。用户要求「像勾选权限一样」。
   现为多列勾选网格 + 已选计数 + 全选/清空。
   ★ 勾选框仍叫 name="extra_department_ids" ⇒ 后端 getlist 零改动。
   ★★★ 配色只走「主题已保证可读的那几对变量」：
     · 文字一律 var(--erp-text) / var(--erp-text-muted)；
     · **--erp-accent 只做淡底色，绝不当文字色** —— 实测 3d-gold 的 accent
       #f59e0b 压在 --erp-table-head-bg #f9e8c8 上只有 1.78:1、light-green
       #059669 压在 #e8f5ef 上只有 3.36:1，与上一轮仪表盘选中按钮同类的坑。
     · 兜底声明写在 @supports 之前，老引擎退化成 head-bg + text 仍是 10:1 以上。
   ★ max-height 只是兜底：19 个部门在 4 列下约 5 行，正常不触发滚动；
     部门数变多时面板内滚动而不是把整页撑长。 */
.erp-xdept {
    border: 1px solid var(--erp-table-border);
    border-radius: .5rem;
    overflow: hidden;
    background: var(--erp-card-bg);
}
.erp-xdept-hd {
    display: flex; align-items: center; gap: .5rem; flex-wrap: wrap;
    padding: .4rem .7rem;
    background: var(--erp-table-head-bg);
    border-bottom: 1px solid var(--erp-table-border);
    font-size: .74rem;
}
.erp-xdept-hd > i { color: var(--erp-text-muted); }
.erp-xdept-hd .ttl { color: var(--erp-text); }
.erp-xdept-hd .cnt {
    margin-left: auto; white-space: nowrap;
    font-weight: 600; font-variant-numeric: tabular-nums;
    color: var(--erp-text);
    background: var(--erp-table-head-bg);
    border: 1px solid var(--erp-table-border);
    border-radius: .7rem; padding: .02rem .5rem;
}
@supports (background: color-mix(in srgb, red 50%, transparent)) {
    .erp-xdept-hd .cnt { background: color-mix(in srgb, var(--erp-accent) 20%, transparent); border-color: transparent; }
}
.erp-xdept-hd .act { display: inline-flex; align-items: center; gap: .35rem; white-space: nowrap; }
.erp-xdept-hd .act button {
    border: 1px solid var(--erp-table-border);
    background: var(--erp-card-bg);
    color: var(--erp-text);
    border-radius: .25rem; padding: 0 .45rem;
    font-size: .7rem; line-height: 1.5; cursor: pointer;
}
.erp-xdept-hd .act button:hover { background: var(--erp-table-head-bg); }
.erp-xdept-bd {
    padding: .45rem .5rem .25rem;
    max-height: 11rem; overflow-y: auto;
}
.erp-xdept-it { margin: 0 0 .22rem; padding-left: 1.55rem; min-height: 1.2rem; }
.erp-xdept-it .form-check-input { cursor: pointer; margin-top: .18rem; }
.erp-xdept-it .form-check-label {
    font-size: .8rem; line-height: 1.25; cursor: pointer; color: var(--erp-text);
}
.erp-xdept-it .form-check-input:checked ~ .form-check-label { font-weight: 600; }
.erp-xdept-it.is-primary .form-check-input,
.erp-xdept-it.is-primary .form-check-label { cursor: not-allowed; }
.erp-xdept-it.is-primary .form-check-label { color: var(--erp-text-muted); font-weight: 400; }
.erp-xdept-tag, .erp-xdept-sub {
    display: inline-block; margin-left: .28rem; padding: 0 .28rem;
    border-radius: .2rem; font-size: .62rem; font-weight: 400;
    line-height: 1.5; vertical-align: 1px; white-space: nowrap;
}
.erp-xdept-tag { background: var(--erp-table-head-bg); color: var(--erp-text); }
@supports (background: color-mix(in srgb, red 50%, transparent)) {
    .erp-xdept-tag { background: color-mix(in srgb, var(--erp-accent) 20%, transparent); }
}
.erp-xdept-sub {
    background: transparent;
    color: var(--erp-text-muted);
}
/* ★ 「含下属」标记**不给底色**：实测两种底色都踩线 ——
   直接压 --erp-table-head-bg 时 3d-gold 只有 3.98:1（浅色主题的 head-bg 是淡彩），
   改成 text 的 8% 淡底又压到 4.18:1（3d-gold）/ 4.36:1（tech-blue）。
   退回「muted 压卡片底」这一对主题自己保证过的组合：14 主题实测最差 4.80:1。
   视觉上靠字号（.62rem）与字重（400）降级，不靠颜色。 */

/* ★ 2026-10-13：隐藏 Edge/Chrome 自带的「显示密码」小眼睛（::-ms-reveal）
   与「清除」小叉（::-ms-clear）。登录/改密/用户表单三页都有自定义眼睛按钮，
   浏览器原生控件叠在旁边会出现「两个眼睛」；隐藏原生、只留我们带 aria-label
   的那个（键盘可达、样式与主题一致）。该伪元素仅 Chromium 系识别，其余浏览器忽略。 */
input[type="password"]::-ms-reveal,
input[type="password"]::-ms-clear {
    display: none;
}
