/* ============================================================
   Apple 风格设计系统
   - 实色表面 + 发丝线分层（HIG：工具界面不靠毛玻璃/投影堆质感）
   - 大圆角 / 大留白
   - 弹簧动画 (cubic-bezier(.34,1.56,.64,1))
   - SF Pro 字体栈
   ============================================================ */

:root {
  --bg: #F4F4F7;
  --card: #FFFFFF;
  --card-solid: #FFFFFF;
  /* 补齐历史上只靠 fallback 的变量（--text-1 连 fallback 都没有 → 声明静默失效） */
  --text-1: #1d1d1f;
  --line-soft: rgba(17, 24, 39, .06);
  /* 全站只留一个"可读的链接蓝"（白底 5.6:1），不再与 --accent 争主色 */
  --blue-deep: #0A63CC;
  --accent-ink: #0A63CC;
  --primary-soft: rgba(0, 122, 255, .08);
  --line: rgba(17, 24, 39, .075);
  --line-strong: rgba(17, 24, 39, .11);
  --text: #1d1d1f;
  --text-2: #3a3a3c;
  --muted: #6e6e73; /* 2026-10-19 无障碍：原 #86868b 在白底仅 3.6:1（12px 正文要求 ≥4.5），提深到约 5:1 */
  --muted-2: #9B9BA3;
  /* 系统蓝：提到 Apple 标准 #007AFF（浅）/ 已由 --accent 在深色下用 #0A84FF */
  --accent: #007AFF;
  /* 按下时"变深"而不是变亮（原来 #0a84ff 会让按压看起来像被点亮） */
  --accent-press: #0062CC;
  --accent-soft: rgba(0, 122, 255, .09);
  /* 语义色整体降饱和：一排徽章不该像仪表盘警示灯 */
  --green: #2E9E57;
  --green-deep: #1B6B3A;
  --green-soft: rgba(46, 158, 87, .12);
  --orange: #C97C00;
  --orange-deep: #8A4B00;
  --orange-soft: rgba(201, 124, 0, .11);
  --red: #E04A3F;
  --red-deep: #A81E16;
  --red-soft: rgba(224, 74, 63, .12);
  --amber: #C08A00;
  --amber-deep: #7A5A00;
  --amber-soft: rgba(192, 138, 0, .12);
  --purple: #6E5BD6;
  --purple-soft: rgba(110, 91, 214, .12);
  --teal: #2A94A8;
  --gray-soft: rgba(17, 24, 39, .05);
  --radius-lg: 20px;
  --radius-md: 16px;
  --radius-sm: 10px;
  /* 双层柔和投影：一层贴地、一层环境，总不透明度 ≤ 12%（纯黑大模糊会发灰发脏） */
  --shadow-sm: 0 1px 1px rgba(17, 24, 39, .04), 0 2px 6px -1px rgba(17, 24, 39, .05);
  --shadow-md: 0 1px 2px rgba(17, 24, 39, .05), 0 8px 24px -6px rgba(17, 24, 39, .10);
  --shadow-lg: 0 2px 4px rgba(17, 24, 39, .04), 0 16px 40px -12px rgba(17, 24, 39, .16);
  /* 统一三条曲线：入场(出慢)、退场(加速)、弹性(只用于"出现"，不用于位移) */
  --spring: cubic-bezier(.34, 1.28, .64, 1);
  --spring-soft: cubic-bezier(.25, 1.12, .4, 1);
  --ease: cubic-bezier(.22, 1, .36, 1);
  --e-out: cubic-bezier(.22, 1, .36, 1);
  --e-in: cubic-bezier(.4, 0, 1, 1);
  --e-spring: cubic-bezier(.34, 1.28, .64, 1);

  /* ---------- Apple HIG 类型阶（2026-09-22 精修）----------
     HIG 原始值：large-title 34/41 · title-1 28/34 · title-2 22/28 · headline 17/22 · body 17/22 · footnote 13/18。
     本项目是**中文密集数据工具**：正文用 13.5 而不是 17（17 会把表格行高撑到 60px+，一屏看不了几行），
     页面大标题用 28（HIG title-1 / macOS 窗口标题的观感），保留 Large Title 的气派又不用占两行。 */
  --fs-large-title: 28px;
  --fs-title-1: 22px;
  --fs-title-2: 17px;
  --fs-headline: 15px;
  --fs-body: 13.5px;
  --fs-footnote: 12px;
  /* HIG 的负字距是为**拉丁**大字设计的；中文压得太紧会粘连，所以只收到 -.01em */
  --tracking-display: -.01em;
  --tracking-body: 0;
  /* HIG：分隔线/描边用固定的灰（#D2D2D7），而不是"黑色 8% 透明"——
     后者在灰底上会发脏，前者是 Apple 那条干净的发丝线 */
  --hairline: rgba(17, 24, 39, .075);
  --fill-secondary: #EDEDF2;          /* 次级按钮/胶囊填充 */
  --fill-tertiary: rgba(120, 120, 128, .10); /* 分段控件容器 / 进度条轨道 */
  --surface-2: #FBFBFD;               /* 二级表面（表格容器等）：去掉 alpha，避免"叠了等于没有" */
  /* ---------- 交互表面令牌 ----------
     为什么单独抽出来：这些位置原来直接写 rgba(255,255,255,.x)（输入框、下拉、用户徽章、
     侧栏选中项、弹窗面板、合并子行）。浅色下没毛病，但**深色下写死的白底会变成刺眼的亮块**
     （实测扫出输入框 30k px²、侧栏选中项 9k px² 的白底），而上一轮的检查只查 `background: #fff`
     这种精确写法，rgba 写法全漏了。抽成令牌后浅/深各一套，不存在"漏改一处"的可能。 */
  --surface-input: rgba(255, 255, 255, .8);  /* 输入框 / 下拉 / 搜索框 */
  --surface-chip: rgba(255, 255, 255, .75);  /* 顶栏用户徽章 */
  --surface-nav-active: rgba(255, 255, 255, .85); /* 侧栏选中项（浅色=白色胶囊） */
  --surface-sheet: #FFFFFF; /* 弹窗面板：实色，避免双层毛玻璃变"磨砂塑料" */
  --surface-topbar-solid: rgba(250, 250, 252, .96); /* 滚动后的顶栏实色（原来只被 var(--x, fallback) 引用，从未定义） */
  --surface-nested: rgba(255, 255, 255, .6); /* 合并后的子行（比父行略亮，表示从属） */
  --font: -apple-system, BlinkMacSystemFont, "SF Pro Text", "SF Pro Display",
    "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "Noto Sans SC", sans-serif;

  /* ---------- 动效令牌（2026-09-24 苹果风精修）---------- */
  --t-fast: 120ms;
  --t-mid: 180ms;
  --t-slow: 260ms;
  --t-1: 120ms;
  --t-2: 180ms;
  --t-3: 260ms;
  --t-4: 420ms;
  --ease-std: cubic-bezier(.22, 1, .36, 1);         /* 兼容旧引用，等同 --e-out */
  --ease-spring: cubic-bezier(.34, 1.28, .64, 1);
  /* 圆角只留 4 档：表面 16 / 控件 10 / 微件 6 / 胶囊 999 */
  --radius-card: 16px;
  --radius-btn: 10px;
  --radius-input: 10px;
  --radius-xs: 6px;
  --radius-pill: 999px;
  /* 4/8 间距令牌（新代码一律用它们，避免再出现 7/9/11/14 这种孤值） */
  --sp-1: 4px;
  --sp-2: 8px;
  --sp-3: 12px;
  --sp-4: 16px;
  --sp-5: 24px;
  /* 系统蓝（与 --accent 浅深一致） */
  --system-blue: #007AFF;
  --system-blue-dark: #0A84FF;
  /* 焦点/光晕：浅色 30% 蓝、深色 42% 蓝（深色底色深，需更浓才看得见） */
  --accent-glow: rgba(0, 122, 255, .30);
  --accent-glow-strong: rgba(0, 122, 255, .42);
  --focus-ring: rgba(0, 122, 255, .42);
  /* hover 叠层 / 表格行 hover */
  --hover-overlay: rgba(0, 0, 0, .04);
  --row-hover: rgba(0, 122, 255, .05);
  /* 毛玻璃表面（侧栏 / 顶栏）：半透明 + 发丝线 */
  --glass-sidebar: rgba(245, 245, 247, .72);
  --glass-topbar: rgba(245, 245, 247, .72);
  --glass-border: rgba(0, 0, 0, .08);
  --glass-border-strong: rgba(0, 0, 0, .14);
  /* 柔和多层阴影（HIG：毛玻璃上的轻投影，不靠重影堆质感） */
  --shadow-soft: 0 1px 1px rgba(17, 24, 39, .03), 0 2px 8px -2px rgba(17, 24, 39, .05);
  /* 细滚动条 */
  --scrollbar-thumb: rgba(0, 0, 0, .18);
  --scrollbar-thumb-hover: rgba(0, 0, 0, .32);
  --scrollbar-track: transparent;
}

* { box-sizing: border-box; margin: 0; padding: 0; }

/* ---------- 暗色模式 ---------- */
[data-theme="dark"] {
  --bg: #141418;
  /* 卡片只比底色提亮 1.12（原来 #2c2c2e vs #161618 是 1.30，像黑纸贴灰板） */
  --card: #1E1E24;
  --card-solid: #1E1E24;
  --line: rgba(255, 255, 255, .07);
  --line-strong: rgba(255, 255, 255, .12);
  --line-soft: rgba(255, 255, 255, .07);
  --text: #f5f5f7;
  --text-2: #d1d1d6;
  --muted: #9A9AA1;
  --muted-2: #6E6E76;
  --accent: #0A84FF;
  --accent-press: #0062CC;
  --accent-ink: #6FB4FF;
  --accent-soft: rgba(10, 132, 255, .14);
  /* --blue-deep 全站有 12 处当"链接色/强调色"用（link-cell/tag-chip/补货数字…），
     深色下必须提亮，否则 #185fa5 在深底上对比度严重不足（实测表格里"日均"链接几乎看不见） */
  --blue-deep: #6FB4FF;
  --green: #4CC46A;
  --green-deep: #7FE39A;
  --green-soft: rgba(76, 196, 106, .16);
  --orange: #E9A23B;
  --orange-deep: #FFC078;
  --orange-soft: rgba(233, 162, 59, .16);
  --red: #FF6B5E;
  --red-deep: #FF9C92;
  --red-soft: rgba(255, 107, 94, .16);
  --amber: #E5C34A;
  --amber-deep: #F2D97A;
  --amber-soft: rgba(229, 195, 74, .16);
  --purple: #bf5af2;
  --purple-soft: rgba(191, 90, 242, .16);
  --teal: #64d2ff;
  --gray-soft: rgba(255, 255, 255, .05);
  /* HIG 深色：分隔线用白色 14%（不再靠阴影分层——深色下 Apple 用"色调 + 描边"而不是投影） */
  --hairline: rgba(255, 255, 255, .08);
  --fill-secondary: rgba(255, 255, 255, .08);
  --fill-tertiary: rgba(120, 120, 128, .22);
  --surface-2: #1A1A1F;
  --surface-input: #1f1f21;
  --surface-chip: rgba(255, 255, 255, .08);
  /* HIG 深色侧栏选中项：不用白色（会变成刺眼亮块），用低饱和的蓝色调 */
  --surface-nav-active: rgba(10, 132, 255, .22);
  --surface-sheet: #1E1E24;
  --surface-nested: rgba(255, 255, 255, .04);
  --surface-topbar-solid: rgba(20, 20, 24, .96);
  --shadow-sm: 0 1px 1px rgba(0, 0, 0, .3), 0 2px 6px -1px rgba(0, 0, 0, .32);
  --shadow-md: 0 1px 2px rgba(0, 0, 0, .35), 0 8px 24px -6px rgba(0, 0, 0, .45);
  --shadow-lg: 0 2px 4px rgba(0, 0, 0, .3), 0 16px 40px -12px rgba(0, 0, 0, .5);

  /* ---------- 动效令牌 · 深色 ---------- */
  --t-fast: 120ms;
  --t-mid: 180ms;
  --t-slow: 260ms;
  --t-1: 120ms;
  --t-2: 180ms;
  --t-3: 260ms;
  --t-4: 420ms;
  --ease-std: cubic-bezier(.22, 1, .36, 1);
  --ease-spring: cubic-bezier(.34, 1.28, .64, 1);
  --e-out: cubic-bezier(.22, 1, .36, 1);
  --e-in: cubic-bezier(.4, 0, 1, 1);
  --e-spring: cubic-bezier(.34, 1.28, .64, 1);
  --radius-card: 16px;
  --radius-btn: 10px;
  --radius-input: 10px;
  --radius-xs: 6px;
  --radius-pill: 999px;
  --sp-1: 4px;
  --sp-2: 8px;
  --sp-3: 12px;
  --sp-4: 16px;
  --sp-5: 24px;
  --system-blue: #0A84FF;
  --system-blue-dark: #0A84FF;
  /* 深色底色深 → 光晕/光圈要更浓才显形 */
  --accent-glow: rgba(10, 132, 255, .42);
  --accent-glow-strong: rgba(10, 132, 255, .55);
  --focus-ring: rgba(10, 132, 255, .55);
  --hover-overlay: rgba(255, 255, 255, .06);
  --row-hover: rgba(10, 132, 255, .10);
  --glass-sidebar: rgba(28, 28, 30, .72);
  --glass-topbar: rgba(28, 28, 30, .72);
  --glass-border: rgba(255, 255, 255, .10);
  --glass-border-strong: rgba(255, 255, 255, .16);
  --shadow-soft: 0 1px 1px rgba(0, 0, 0, .28), 0 2px 8px -2px rgba(0, 0, 0, .32);
  --scrollbar-thumb: rgba(255, 255, 255, .20);
  --scrollbar-thumb-hover: rgba(255, 255, 255, .34);
  --scrollbar-track: transparent;
}
/* 高频浅色硬编码规则在暗色下的覆盖 */
/* btn-ghost 已改用语义变量 --fill-secondary（浅/深各自一套），不需要单独覆盖 */
/* 表格容器底色已改用语义变量 --surface-2（浅/深各自一套），不再需要单独的深色覆盖 */
[data-theme="dark"] .field input, [data-theme="dark"] .field select, [data-theme="dark"] .field textarea,
[data-theme="dark"] input, [data-theme="dark"] select, [data-theme="dark"] textarea { background: #1f1f21; color: var(--text); }
[data-theme="dark"] .sidebar { background: var(--glass-sidebar); }
[data-theme="dark"] .auth-card { background: var(--card); }
[data-theme="dark"] .splash { background: var(--bg); }
/* ⚠️ 这里原来把 .stat-card.ok 和徽章写在一起：`background: var(--green-soft)` 是**徽章**要的，
   套到统计卡上就变成"整张卡被绿底淹没"（实测 dark 下 bg=rgba(48,209,88,.16)，同页其它卡是 rgba(43,43,46,.9)）。
   统计卡的语义色改由 ::after 的 tint 圆点 + 标签颜色承担，表面保持中性。 */
[data-theme="dark"] .badge.b-safe { background: var(--green-soft); color: var(--green-deep); }
[data-theme="dark"] .modal-host { background: rgba(0, 0, 0, .55); }
[data-theme="dark"] .modal-card { background: var(--card-solid); }
[data-theme="dark"] code { background: rgba(255,255,255,.08); }

/* ---------- 深色主题补缺口（2026-09-22 审计发现：这些元素写死了浅色 → 深色下看不见） ---------- */
/* 页面大标题：h2 用渐变裁切文字，浅色渐变在深色底上等于隐身 */
/* 说明：这里原来有一条 [data-theme="dark"] .page-head h2 的覆盖，是为了修"浅色渐变在深色下看不见"。
   标题改成实色 ink（用语义变量）之后不再需要，已删；谁要是再把渐变加回来，深色下会立刻不可读。 */
[data-theme="dark"] .page-head h2.legacy-gradient-guard {
  background-image: linear-gradient(120deg, var(--text) 30%, var(--text-2));
  -webkit-background-clip: text;
  background-clip: text;
}
/* 状态徽章/标签：白底 + 深红字 */
[data-theme="dark"] .mini.out { background: rgba(255, 255, 255, .08); border-color: var(--red-soft); }
[data-theme="dark"] .tag-static { background: rgba(10, 132, 255, .14); border-color: rgba(10, 132, 255, .3); color: #9ecbff; }
[data-theme="dark"] .kbd { background: rgba(255, 255, 255, .08); }
/* 提示框：写死的深棕/深红文字在深色底上对比不足 */
[data-theme="dark"] .advice-box.warn { color: #ffd9a8; }
[data-theme="dark"] .advice-box.danger { color: #ffc7c2; }
/* 云端未同步横幅 */
[data-theme="dark"] .cloud-banner { background: #3a3216; border-bottom-color: #6b5a1f; color: #ffe9b0; }
/* 曲线容器与时间线：原来是白色渐变底，深色下整块发白 */
[data-theme="dark"] .sc-wrap { background: linear-gradient(180deg, #232325 0%, #1c1c1e 100%); }
[data-theme="dark"] .timeline-chart { background: rgba(255, 255, 255, .05); }
[data-theme="dark"] .modal-close { background: rgba(255, 255, 255, .1); color: var(--text); }

html, body {
  /* 切主题时底色/文字淡入，而不是硬闪（globals.css 里 html/body 的惯例） */
  transition: background-color .3s var(--ease), color .3s var(--ease);
  scroll-behavior: smooth;
  height: 100%;
  font-family: var(--font);
  background: var(--bg);
  color: var(--text);
  font-size: 14px;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  letter-spacing: .01em;
}

::selection { background: var(--accent-soft); }

::-webkit-scrollbar { width: 6px; height: 6px; }
::-webkit-scrollbar-thumb { background: var(--scrollbar-thumb); border-radius: 999px; border: 0 solid transparent; background-clip: padding-box; }
::-webkit-scrollbar-thumb:hover { background: var(--scrollbar-thumb-hover); }
::-webkit-scrollbar-track { background: var(--scrollbar-track); }
html {
  /* 2026-10-19：预留滚动条空间 —— 否者切到短页面时滚动条消失、内容整体右移 15px（抖动） */
  scrollbar-gutter: stable; scrollbar-color: var(--scrollbar-thumb) transparent; scrollbar-width: thin; }

.hidden { display: none !important; }

/* ---------- 启动画面 ---------- */
.splash {
  position: fixed;
  inset: 0;
  z-index: 300;
  background: var(--bg);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 18px;
  transition: opacity .4s var(--ease);
}
.splash.fade-out { opacity: 0; pointer-events: none; }
.splash .logo { width: 84px; height: 84px; border-radius: 20px; box-shadow: 0 12px 34px rgba(16, 60, 110, .18); animation: splash-pop .6s var(--spring) both; }
.splash .bar {
  width: 140px;
  height: 4px;
  border-radius: 2px;
  background: rgba(0, 0, 0, .08);
  overflow: hidden;
}
.splash .bar i {
  display: block;
  width: 40%;
  height: 100%;
  border-radius: 2px;
  background: var(--accent);
  animation: splash-slide 1.1s ease-in-out infinite;
}
@keyframes splash-pop {
  from { transform: scale(.6); opacity: 0; }
  to { transform: scale(1); opacity: 1; }
}
@keyframes splash-slide {
  0% { transform: translateX(-100%); }
  100% { transform: translateX(360%); }
}

/* ---------- 登录 ---------- */
.auth-screen {
  min-height: 100vh;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px;
  background:
    radial-gradient(1200px 600px at 15% -10%, rgba(0, 102, 204, .10), transparent 60%),
    radial-gradient(1000px 500px at 110% 10%, rgba(88, 86, 214, .10), transparent 55%),
    radial-gradient(900px 600px at 50% 120%, rgba(52, 199, 89, .08), transparent 60%),
    var(--bg);
}

.auth-card {
  width: 100%;
  max-width: 420px;
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: 28px;
  padding: 44px 40px;
  box-shadow: var(--shadow-lg);
  text-align: center;
  animation: spring-in .55s var(--spring) both;
}

.auth-logo {
  width: 76px;
  height: 76px;
  margin: 0 auto 18px;
  border-radius: 20px;
  box-shadow: 0 10px 30px rgba(16, 60, 110, .18);
  animation: splash-pop .6s var(--spring) .08s both;
}
.auth-card h1 { font-size: 24px; font-weight: 700; letter-spacing: -.02em; margin-bottom: 6px; }
.auth-sub { color: var(--muted); font-size: 13.5px; margin-bottom: 28px; }
.auth-form { text-align: left; }

/* ---------- 表单 ---------- */
.field { margin-bottom: 16px; }
.field label {
  display: block;
  font-size: 13px;
  color: var(--text-2);
  margin-bottom: 7px;
  font-weight: 600;
}
.field input, .field select, .field textarea {
  width: 100%;
  padding: 11px 14px;
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-input);
  font-size: 14px;
  background: var(--surface-input);
  color: var(--text);
  font-family: inherit;
  transition: border-color var(--t-fast) var(--ease), box-shadow var(--t-fast) var(--ease), background var(--t-fast) var(--ease);
  appearance: none;
  -webkit-appearance: none;
}
.field input::placeholder, .field textarea::placeholder { color: var(--muted-2); }
.field input:hover, .field select:hover, .field textarea:hover { border-color: var(--line-strong); filter: brightness(.985); }
[data-theme="dark"] .field input:hover, [data-theme="dark"] .field select:hover, [data-theme="dark"] .field textarea:hover { filter: brightness(1.12); }
.field input:focus-visible, .field select:focus-visible, .field textarea:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 1px;
}
.field input:focus, .field select:focus, .field textarea:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-glow);
  background: var(--card-solid);
}
.field select {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8'%3E%3Cpath d='M1 1l5 5 5-5' stroke='%2386868b' stroke-width='1.8' fill='none' stroke-linecap='round'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 14px center;
  padding-right: 36px;
}
.field textarea { min-height: 100px; resize: vertical; font-family: ui-monospace, "SF Mono", Consolas, monospace; font-size: 13px; line-height: 1.6; }
.field .hint { font-size: 12px; color: var(--muted); margin-top: 5px; line-height: 1.6; }
.field .inline { display: flex; gap: 12px; align-items: center; }
.field .inline > * { flex: 1; }

/* ---------- 按钮 ---------- */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 7px;
  padding: 10px 20px;
  border-radius: var(--radius-btn);
  border: 1px solid transparent;
  font-size: 14px;
  font-weight: 600;
  cursor: pointer;
  background: var(--accent);
  color: #fff;
  transition: transform var(--t-fast) var(--ease), box-shadow var(--t-fast) var(--ease), background var(--t-fast) var(--ease), filter var(--t-fast) var(--ease), opacity var(--t-fast) var(--ease);
  font-family: inherit;
  white-space: nowrap;
  user-select: none;
  letter-spacing: .01em;
}
/* HIG：按钮悬浮只加深填充 + 轻上浮 + 柔和蓝影（光晕是"这是个可点的主操作"的暗示，强度克制） */
.btn:hover {
  background: var(--accent-press);
  transform: translateY(-1px);
  box-shadow: 0 4px 14px var(--accent-glow);
  filter: brightness(1.04);
}
.btn:active { transform: scale(.97); }
.btn:disabled { opacity: .5; cursor: not-allowed; box-shadow: none; transform: none; }
/* 键盘可达性：HIG 的焦点是"柔和外环"而不是系统默认虚线框（系统蓝 40% 透明，2px 外圈） */
.btn:focus-visible { outline: none; box-shadow: 0 0 0 2px var(--focus-ring); }
.btn-block { width: 100%; }
/* HIG Alt Gray 次级按钮：#E8E8ED 填充、**无描边**（描边是网页按钮的语法，不是 Apple 的） */
.btn-ghost { background: var(--fill-secondary); color: var(--text); border-color: transparent; }
.btn-ghost:hover { background: var(--fill-secondary); filter: brightness(.96); box-shadow: none; transform: translateY(-1px); }
[data-theme="dark"] .btn-ghost:hover { filter: brightness(1.25); }
.btn-danger { background: var(--red); }
.btn-danger:hover { background: var(--red-deep); box-shadow: 0 4px 14px var(--red-soft); }
.btn-success { background: var(--green); }
.btn-success:hover { background: var(--green-deep); box-shadow: 0 4px 14px var(--green-soft); }
.btn-sm { padding: 7px 14px; font-size: 13px; }
.btn-xs { padding: 5px 11px; font-size: 12px; border-radius: var(--radius-btn); }

/* ---------- 顶栏 ---------- */
.topbar {
  /* macOS 工具栏：毛玻璃 + 半透明；发丝线默认隐，滚动后浮现（app.js 切 .scrolled） */
  height: 52px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0 24px;
  position: sticky;
  top: 0;
  z-index: 60;
  background: var(--glass-topbar);
  -webkit-backdrop-filter: saturate(1.8) blur(20px);
  backdrop-filter: saturate(1.8) blur(20px);
  /* 0.5px 发丝线：用 1px 边框 + 向下 0.5px 阴影模拟（真 0.5px 在多数屏会被取整） */
  border-bottom: 1px solid transparent;
  box-shadow: 0 0.5px 0 var(--glass-border);
  transition: background-color .3s var(--ease), border-color .3s var(--ease), box-shadow .3s var(--ease);
}
/* 浅色默认：深字；滚动后发丝线加深 */
.topbar { color: var(--text); }
.topbar.scrolled {
  border-bottom-color: var(--hairline);
  box-shadow: 0 0.5px 0 var(--glass-border-strong);
  /* ⚠️ 2026-10-08 滚动卡顿修复：sticky 顶栏的 backdrop-filter blur(20px) 在滚动时
     每帧都要对下方内容重算模糊（真实 GPU 上就是掉帧主因）。滚动中降级为近不透明实底色
     —— 观感几乎无差（Apple 官方也这么做：滚动中降低材质），但省掉整屏模糊。 */
  -webkit-backdrop-filter: none;
  backdrop-filter: none;
  background: var(--surface-topbar-solid, rgba(250, 250, 252, .96));
}
.brand { display: flex; align-items: center; gap: 12px; }
.brand-icon {
  width: 32px;
  height: 32px;
  border-radius: 9px;
  box-shadow: 0 3px 10px rgba(16, 60, 110, .18);
}
.brand-name { font-size: 16px; font-weight: 700; letter-spacing: -.02em; color: var(--text); }
.brand-tag {
  font-size: 11px;
  font-weight: 600;
  color: var(--muted);
  background: var(--fill-secondary);
  padding: 3px 10px;
  border-radius: 999px;
}
.topbar-right { display: flex; align-items: center; gap: 14px; }
.global-search {
  width: 210px;
  padding: 7px 14px;
  border-radius: 999px;
  border: 1px solid var(--line-strong);
  background: var(--surface-input);
  color: var(--text);
  font-size: 13px;
  font-family: inherit;
  transition: background .18s var(--ease), box-shadow .18s var(--ease),
    border-color .18s var(--ease), width .25s var(--ease);
}
.global-search::placeholder { color: var(--muted-2); }
.global-search:focus {
  outline: none;
  background: var(--card-solid);
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-glow);
  width: 260px;
}
.today-label { font-size: 12.5px; color: var(--muted); font-weight: 400; }
.user-chip {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  background: var(--surface-chip);
  border: 1px solid var(--line);
  padding: 5px 14px;
  border-radius: 999px;
  font-size: 13px;
  font-weight: 600;
  color: var(--text);
  transition: background .18s var(--ease), border-color .18s var(--ease);
}
.user-chip:hover { background: var(--surface-input); border-color: var(--line-strong); }
/* 角色徽章：描边胶囊 + 同色圆点 + 语义色。
   2026-11-03 用户反馈「这些标特别丑」——原来只有 background/color，没有内边距和圆角，
   在表格里就是一块纯色方块；super 还是橙红渐变，浅色深色都显廉价。 */
.role-badge {
  --rb-bg: rgba(120, 120, 128, .1);
  --rb-fg: var(--text-2);
  --rb-line: rgba(120, 120, 128, .18);
  display: inline-flex;
  align-items: center;
  gap: 5px;
  height: 19px;
  padding: 0 8px;
  border-radius: 999px;
  border: 1px solid var(--rb-line);
  background: var(--rb-bg);
  color: var(--rb-fg);
  font-size: 11px;
  font-weight: 600;
  line-height: 1;
  letter-spacing: .01em;
  white-space: nowrap;
  vertical-align: 1px;
}
.role-badge::before {
  content: "";
  width: 5px;
  height: 5px;
  border-radius: 50%;
  background: currentColor;
  opacity: .7;
  flex: 0 0 auto;
}
.role-badge.super { --rb-bg: rgba(245, 158, 11, .13); --rb-fg: #9A5300; --rb-line: rgba(245, 158, 11, .3); }
.role-badge.admin { --rb-bg: rgba(109, 84, 255, .1); --rb-fg: #5540C8; --rb-line: rgba(109, 84, 255, .24); }
.role-badge.user { --rb-bg: rgba(0, 122, 255, .09); --rb-fg: var(--accent-ink, #0A63CC); --rb-line: rgba(0, 122, 255, .2); }
.role-badge.sys { --rb-bg: rgba(120, 120, 128, .1); --rb-fg: var(--muted); --rb-line: rgba(120, 120, 128, .18); }
/* 权限标（全部权限）：同一套胶囊语言，但不带角色圆点 */
.role-badge.perm { --rb-bg: rgba(0, 122, 255, .08); --rb-fg: var(--accent-ink, #0A63CC); --rb-line: rgba(0, 122, 255, .18); }
.role-badge.perm::before { display: none; }
[data-theme="dark"] .role-badge.perm { --rb-bg: rgba(10, 132, 255, .16); --rb-fg: #9ECBFF; --rb-line: rgba(10, 132, 255, .24); }
.user-chip .role-badge { font-size: 10.5px; height: 18px; padding: 0 7px; gap: 4px; }
[data-theme="dark"] .role-badge.super { --rb-bg: rgba(255, 179, 64, .16); --rb-fg: #FFC46B; --rb-line: rgba(255, 179, 64, .26); }
[data-theme="dark"] .role-badge.admin { --rb-bg: rgba(160, 123, 255, .18); --rb-fg: #C4B0FF; --rb-line: rgba(160, 123, 255, .26); }
[data-theme="dark"] .role-badge.user { --rb-bg: rgba(10, 132, 255, .18); --rb-fg: #9ECBFF; --rb-line: rgba(10, 132, 255, .26); }
[data-theme="dark"] .role-badge.sys { --rb-bg: rgba(255, 255, 255, .1); --rb-fg: #B9B9C0; --rb-line: rgba(255, 255, 255, .14); }
/* 深色：毛玻璃更深，文字转回浅色（浅色那套深字在深玻璃上不可读） */
[data-theme="dark"] .topbar { background: var(--glass-topbar); box-shadow: 0 0.5px 0 var(--glass-border); }
[data-theme="dark"] .topbar.scrolled { border-bottom-color: var(--glass-border-strong); box-shadow: 0 0.5px 0 var(--glass-border-strong); }
[data-theme="dark"] .brand-name { color: #f5f5f7; }
[data-theme="dark"] .brand-tag { color: rgba(255, 255, 255, .6); background: rgba(255, 255, 255, .12); }
[data-theme="dark"] .today-label { color: rgba(255, 255, 255, .65); }
[data-theme="dark"] .global-search { border-color: rgba(255, 255, 255, .16); background: rgba(255, 255, 255, .1); color: #f5f5f7; }
[data-theme="dark"] .global-search::placeholder { color: rgba(255, 255, 255, .5); }
[data-theme="dark"] .global-search:focus { background: rgba(255, 255, 255, .16); box-shadow: 0 0 0 3px rgba(255, 255, 255, .14); }
[data-theme="dark"] .user-chip { background: rgba(255, 255, 255, .12); border-color: rgba(255, 255, 255, .14); color: #f5f5f7; }
[data-theme="dark"] .user-chip:hover { background: rgba(255, 255, 255, .18); border-color: rgba(255, 255, 255, .2); }

/* ---------- 布局 ---------- */
.layout { display: flex; min-height: calc(100vh - 52px); }

.sidebar {
  width: 224px;
  flex-shrink: 0;
  padding: 16px 12px;
  position: sticky;
  top: 58px;
  height: calc(100vh - 58px);
  overflow-y: auto;
  /* macOS 侧栏：毛玻璃 + 半透明 + 右侧发丝线 */
  background: var(--glass-sidebar);
  -webkit-backdrop-filter: saturate(1.8) blur(20px);
  backdrop-filter: saturate(1.8) blur(20px);
  border-right: 1px solid var(--glass-border);
  transition: background-color .3s var(--ease), border-color .3s var(--ease);
}
.nav-item {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 11px 14px;
  border-radius: var(--radius-btn);
  color: var(--text-2);
  font-weight: 600;
  cursor: pointer;
  margin-bottom: 3px;
  user-select: none;
  transition: background .18s var(--ease), color .18s var(--ease), transform .14s var(--ease);
}
.nav-item:hover { background: var(--hover-overlay); color: var(--text); }
[data-theme="dark"] .nav-item:hover { background: var(--hover-overlay); }
.nav-item:active { transform: scale(.96); }
.nav-item.active {
  background: var(--accent);
  color: #fff;
  box-shadow: 0 1px 2px rgba(0, 0, 0, .12), 0 4px 12px var(--accent-glow);
}
.nav-item .nav-icon { font-size: 17px; width: 24px; text-align: center; }
.nav-sep { height: 1px; background: var(--line); margin: 12px 10px; }

.main {
  flex: 1;
  padding: 26px 32px 60px;
  max-width: 1560px;
  min-width: 0;
  margin: 0 auto;
}

/* 视图切换动画 */
.view-enter { animation: view-in .22s var(--ease) both; }
@keyframes view-in {
  from { opacity: 0; transform: translateY(10px); }
  to { opacity: 1; transform: none; }
}

/* ---------- 卡片 ---------- */
.card {
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: var(--radius-card);
  padding: 22px 24px;
  margin-bottom: 20px;
  box-shadow: var(--shadow-soft);
  /* 进场动画：只在「换页」时播（见下方 .view-enter .card）——
     2026-10-19 流畅性：原来 .card 自带 0.32s 入场 + stagger，而搜索/筛选/排序
     都会重建 DOM → 每点一次就重播 0.44s 动画，手感像"卡了一下"。
     现在同页更新完全不动画（只有 opacity/transform 的 hover 过渡）。
     transition 仍负责主题切换与 hover 的底色渐变。 */
  transition: box-shadow .25s var(--ease), transform .25s var(--ease),
    background-color .3s var(--ease), border-color .3s var(--ease), color .3s var(--ease);
}
/* 同级卡片 stagger：0 / 40 / 80ms，之后统一 120ms（纯 CSS，无需 JS） */
.view-enter .card { animation: card-in .26s var(--ease-std) both; }
.view-enter .card:nth-child(1) { animation-delay: 0ms; }
.view-enter .card:nth-child(2) { animation-delay: 30ms; }
.view-enter .card:nth-child(3) { animation-delay: 60ms; }
.view-enter .card:nth-child(n+4) { animation-delay: 80ms; }
@keyframes card-in {
  from { opacity: 0; transform: translateY(8px); }
  to { opacity: 1; transform: none; }
}
.card-title { font-size: var(--fs-title-2); font-weight: 600; letter-spacing: var(--tracking-display); margin-bottom: 5px; line-height: 1.35; }
.card-sub { color: var(--muted); font-size: var(--fs-footnote); margin-bottom: 16px; line-height: 1.55; }

.page-head {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 16px;
  margin-bottom: 20px;
  flex-wrap: wrap;
}
/* HIG：标题用**实色 ink**，不用渐变裁切文字。
   渐变 + background-clip:text 有两个真问题：① 深色主题下必须再写一条覆盖（浅色渐变在深底上看不见），
   ② 文字对比度随渐变变化、无法保证 4.5:1。改成实色后这两个问题一起消失。 */
.page-head h2 {
  font-size: var(--fs-large-title);
  font-weight: 700;
  letter-spacing: var(--tracking-display);
  color: var(--text);
  line-height: 1.2;
}
/* 榜单「走势」缩略图：放大版（带纵轴刻度 + 横轴日期 + 悬停十字线/数值） */
.rk-cell { min-width: 132px; }
.rk-svg { display: block; overflow: visible; }
.rk-grid { stroke: var(--line-soft, #ececec); stroke-width: 1; }
.rk-axis { stroke: var(--line-strong, #d6d6d6); stroke-width: 1; }
.rk-ylab, .rk-xlab { font-size: 9.5px; fill: var(--muted, #8a8a8a); }
.rk-line { fill: none; stroke: var(--accent, #0066cc); stroke-width: 1.6; stroke-linejoin: round; stroke-linecap: round; }
.rk-cross { stroke: var(--text-2, #6b6b6b); stroke-width: 1; stroke-dasharray: 2 2; opacity: 0; }
.rk-dot { fill: var(--accent, #0066cc); opacity: 0; }
.rk-mini { display: block; cursor: crosshair; pointer-events: all; }
/* SVG 的空区域默认不接收鼠标事件 —— 没有这层透明矩形，鼠标停在曲线上方就悬停不出来 */
.rk-hitbox { cursor: crosshair; }
.rk-area { fill: var(--accent-soft, rgba(0, 102, 204, .1)); stroke: none; }
.rk-ytitle { font-size: 10px; fill: var(--muted, #8a8a8a); }
.th-u { font-weight: 400; font-size: 11px; color: var(--muted); }
/* 悬停弹出的大曲线：只在指针停在小图上时出现，平时不占位 */
.rk-pop {
  position: fixed; z-index: 9998; padding: 10px 14px 8px; border-radius: 12px;
  background: var(--card-solid, #fff); border: 1px solid var(--line-strong, rgba(0, 0, 0, .14));
  box-shadow: 0 14px 36px rgba(0, 0, 0, .18);
}
.rk-pop-head { font-size: 12.5px; color: var(--text-2, #3a3a3c); margin-bottom: 6px; min-height: 18px; }
.rk-pop-head b { font-size: 14px; }
.rk-pop-foot { text-align: right; margin-top: 4px; }
.page-head .sub { color: var(--muted); font-size: 13.5px; margin-top: 5px; }
.page-head .actions { display: flex; gap: 10px; flex-wrap: wrap; }

/* ---------- 统计卡 ---------- */
.stat-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(158px, 1fr));
  gap: 14px;
  margin-bottom: 20px;
}
.stat-card {
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: var(--radius-card);
  padding: 18px 18px 16px;
  transition: transform .22s var(--spring), box-shadow .22s var(--ease);
  position: relative;
  overflow: hidden;
}
.stat-card::after {
  content: "";
  position: absolute;
  right: -24px;
  top: -24px;
  width: 78px;
  height: 78px;
  border-radius: 50%;
  background: var(--tint, rgba(0, 102, 204, .08));
}
.stat-card .num { font-size: 30px; font-weight: 600; letter-spacing: -.03em; line-height: 1.1; animation: num-pop .5s var(--spring) both; }
.stat-card .lbl { color: var(--muted); font-size: 12.5px; margin-top: 5px; font-weight: 400; }
@keyframes num-pop {
  from { transform: scale(.85); opacity: 0; }
  to { transform: scale(1); opacity: 1; }
}
.stat-card.danger { --tint: rgba(255, 59, 48, .12); }
.stat-card.warn { --tint: rgba(255, 149, 0, .16); }
.stat-card.ok { --tint: rgba(52, 199, 89, .14); }
.stat-card.info { --tint: rgba(0, 102, 204, .12); }
.stat-card.gray { --tint: rgba(0, 0, 0, .06); }
/* HIG：表面保持中性，语义色只给"关键元素"——这里给标签，
   这样"需补货 / 安全"一眼能分，又不会整块染色（深色下尤其明显）。 */
.stat-card.danger .lbl { color: var(--red-deep); }
.stat-card.warn .lbl { color: var(--orange-deep); }
.stat-card.ok .lbl { color: var(--green-deep); }
/* 深色下同一个 alpha 在深底上几乎看不见 → 圆点加浓一档 */
[data-theme="dark"] .stat-card.danger { --tint: rgba(255, 69, 58, .24); }
[data-theme="dark"] .stat-card.warn { --tint: rgba(255, 159, 10, .22); }
[data-theme="dark"] .stat-card.ok { --tint: rgba(48, 209, 88, .20); }
[data-theme="dark"] .stat-card.info { --tint: rgba(10, 132, 255, .22); }
[data-theme="dark"] .stat-card.gray { --tint: rgba(255, 255, 255, .07); }
.stat-card.clickable { cursor: pointer; }
.stat-card.active {
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-soft), var(--shadow-md);
  transform: translateY(-3px);
}
.badge-btn {
  border: none;
  cursor: pointer;
  font-family: inherit;
  transition: transform .12s var(--ease), box-shadow .15s var(--ease);
}
.badge-btn:hover { transform: scale(1.06); }

/* ---------- 站点分段控件 ---------- */
.site-strip {
  display: flex;
  gap: 10px;
  overflow-x: auto;
  padding: 2px 2px 8px;
  margin-bottom: 8px;
  scrollbar-width: none;
}
.site-strip::-webkit-scrollbar { display: none; }
.site-pill {
  display: flex;
  align-items: center;
  gap: 9px;
  padding: 10px 18px;
  border-radius: 999px;
  border: 1px solid var(--line);
  background: var(--card);
  cursor: pointer;
  white-space: nowrap;
  font-weight: 600;
  font-size: 13.5px;
  color: var(--text-2);
  transition: border-color .2s var(--ease), background .2s var(--ease), transform .18s var(--spring-soft);
  user-select: none;
  position: relative;
}
.site-pill:hover { border-color: rgba(0, 0, 0, .16); }
.site-pill:active { transform: scale(.96); }
.site-pill.active {
  background: #1d1d1f;
  border-color: #1d1d1f;
  color: #fff;
}
.site-pill .cnt {
  font-size: 11px;
  font-weight: 700;
  background: rgba(0, 0, 0, .07);
  color: var(--muted);
  border-radius: 999px;
  padding: 2px 8px;
}
.site-pill.active .cnt { background: rgba(255, 255, 255, .2); color: #fff; }
.site-pill .dot-alert {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--red);
  box-shadow: 0 0 0 3px var(--red-soft);
}

/* 站点总览卡 */
.site-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(210px, 1fr));
  gap: 14px;
  margin-bottom: 20px;
}
.site-card {
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: var(--radius-card);
  padding: 18px;
  cursor: pointer;
  transition: border-color .22s var(--ease), transform .18s var(--spring-soft);
  position: relative;
  overflow: hidden;
}
.site-card:hover { border-color: var(--line-strong); }
.site-card:active { transform: scale(.98); }
.site-card .site-name { font-size: 16px; font-weight: 700; display: flex; align-items: center; gap: 8px; }
.site-card .site-meta { color: var(--muted); font-size: 12px; margin: 4px 0 12px; }
.site-card .mini-row { display: flex; gap: 12px; flex-wrap: wrap; }
.site-card .mini {
  font-size: 12px;
  font-weight: 600;
  padding: 3px 10px;
  border-radius: 999px;
}
.mini.urgent { background: var(--red-soft); color: var(--red-deep); }
.mini.reorder { background: var(--orange-soft); color: var(--orange-deep); }
.mini.out { background: var(--card-solid); color: var(--red-deep); border: 1px solid var(--red-soft); }
.mini.safe { background: var(--green-soft); color: var(--green-deep); }
.mini.watch { background: var(--amber-soft); color: var(--amber-deep); }
.mini.total { background: rgba(0, 0, 0, .05); color: var(--text-2); }
.site-card .bar-track {
  height: 6px;
  border-radius: 3px;
  background: rgba(0, 0, 0, .06);
  margin-top: 14px;
  overflow: hidden;
  display: flex;
}
.site-card .bar-track i {
  height: 100%;
  transition: width .5s var(--ease);
}

/* ---------- 表格 ---------- */
.table-wrap {
  /* 布局隔离（滚动更稳）。⚠️ 不用 paint：paint 会裁掉溢出容器的绝对定位后代，
     而看板表格里的 .chart-tip 是 absolute 定位的悬停卡，可能被切掉。 */
  contain: layout style;
  overflow: auto;
  /* ⚠️ 2026-10-09 不能用 overscroll-behavior: contain：
     它会**切断滚动链**——鼠标在表格上滚到底后，滚轮不再传递给页面，
     用户看到的就是"鼠标滑不动页面"（表格内部滚动区占 66vh，鼠标大部分时间都悬在它上面）。
     默认行为（滚到底自动接力页面）才是用户期望的。弹窗内的 contain 保留（那里是要的）。 */
  border: 1px solid var(--hairline);
  border-radius: var(--radius-md);
  background: var(--surface-2);
  max-height: none;
}
.table-wrap table thead th {
  position: sticky;
  top: 0;
  z-index: 3;
  background: var(--bg, #f5f7fa);
  box-shadow: 0 1px 0 0 var(--line);
}
/* 需固定高度滚动的容器（看板/商品等长表） */
.table-wrap.scroll-v { max-height: 66vh; }
table { width: 100%; border-collapse: collapse; font-size: var(--fs-body); min-width: 860px; }
/* 弹窗里的窄表（头程批次详情等只有 3~4 列）不该继承 860px 的最小宽度 ——
   全局那条是为了让看板长表在窄屏下横向滚动，套到弹窗上会让最后一列被裁掉
   （2026-09-23 实测：modal 内宽 810px、表格被撑到 860px、横向溢出 52px，「实入数」列看不见）。 */
.modal table { min-width: 0; }
/* HIG 建议触摸目标 ≥44pt；桌面用指针时 40px 左右既好点又不浪费屏（原来 11px 内边距 ≈ 38px） */
th, td { padding: 12px 14px; text-align: left; border-bottom: 1px solid var(--hairline); vertical-align: middle; }
th {
  /* 不透明表头：这几张表能到几百行、还要 sticky，毛玻璃会让滚动时每帧重算模糊 → 明显掉帧。
     改成不透明底色后观感几乎无差，滚动顺滑。 */
  background: var(--bg, #f5f5f7);
  box-shadow: 0 1px 0 0 var(--line);
  /* HIG：表头属于"脚注级"信息 —— 次级色 + 半粗 + 不抢视线 */
  color: var(--muted);
  font-weight: 600;
  font-size: var(--fs-footnote);
  letter-spacing: .02em;
  white-space: nowrap;
  position: sticky;
  top: 0;
  z-index: 2;
}
/* 同上：去掉行过渡，滚动时不再连续触发重绘 */
tbody tr:hover td { background: var(--gray-soft); }
tbody tr:last-child td { border-bottom: none; }
/* 数字一律等宽（tabular-nums）：否则 1 和 8 宽度不同，列会随数据跳动 —— 数据表最刺眼的问题 */
td.num, th.num, .stat-card .num, .site-card .num, .kpi .num { text-align: right; font-variant-numeric: tabular-nums; }
.stat-card .num { text-align: left; letter-spacing: var(--tracking-display); }
td.center, th.center { text-align: center; }

.sku-cell { font-family: ui-monospace, "SF Mono", Consolas, monospace; font-size: 11.5px; color: var(--muted); word-break: break-all; }
.name-cell { max-width: 240px; }
.name-cell .main { font-weight: 600; color: var(--text); }
.name-cell .sub { color: var(--muted); font-size: 12px; margin-top: 2px; }

/* ---------- 内联 SVG 图标 ---------- */
.ic { display: inline-block; vertical-align: -3px; flex: 0 0 auto; }
.nav-icon .ic { vertical-align: -4px; }
.card-title .ic { margin-right: 6px; vertical-align: -3px; }
h2 .ic { margin-right: 8px; vertical-align: -4px; }
.btn .ic { margin-right: 5px; vertical-align: -2px; }

/* ---------- 商品标签 ---------- */
.tag-chip {
  display: inline-flex;
  align-items: center;
  padding: 2px 9px;
  font-size: 11.5px;
  line-height: 1.5;
  border-radius: 999px;
  border: 1px solid var(--line-strong, #ddd);
  background: var(--surface-chip, #f6f8fa);
  color: var(--muted, #555);
  cursor: pointer;
  user-select: none;
  /* 原来是 transition: all —— 会把布局属性也纳入过渡（多余的重排） */
  transition: background .12s var(--ease), border-color .12s, color .12s;
}
.tag-chip:hover { border-color: var(--blue-deep, #185FA5); color: var(--blue-deep, #185FA5); }
.tag-chip.on { background: var(--blue-deep, #185FA5); border-color: var(--blue-deep, #185FA5); color: #fff; }
.tag-static { cursor: default; background: #eef3fa; border-color: #d8e3f0; color: #185FA5; }
.tag-cell { min-width: 120px; }
.tag-cell .tag-chip { margin: 1px 3px 1px 0; }

/* ---------- SKU 图片 ---------- */
.sku-img {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: var(--sz, 34px);
  height: var(--sz, 34px);
  border: 1px dashed var(--line-strong, #ccc);
  border-radius: 8px;
  cursor: pointer;
  vertical-align: middle;
  background: var(--gray-soft, #fafafa);
  transition: border-color .15s, box-shadow .15s;
}
.sku-img:hover { border-color: var(--blue-deep, #185FA5); }
.sku-img.has-img { border-style: solid; border-color: transparent; cursor: pointer; background: transparent; }
.sku-img.pasting { border-color: #e6a23c; border-style: dashed; box-shadow: 0 0 0 3px rgba(230,162,60,.25); animation: sku-img-blink 1s ease-in-out infinite; }
@keyframes sku-img-blink { 0%,100% { opacity: 1; } 50% { opacity: .55; } }
.sku-img .sku-img-ph { display: flex; align-items: center; justify-content: center; font-size: 14px; color: #bbb; }
.sku-img-ro { cursor: default; }

/* ---------- 状态徽章 ---------- */
.badge {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 4px 12px;
  border-radius: 999px;
  font-size: 12px;
  font-weight: 700;
  white-space: nowrap;
  letter-spacing: .01em;
}
.badge .dot { width: 6px; height: 6px; border-radius: 50%; background: currentColor; }
.b-safe { background: var(--green-soft); color: var(--green-deep); }
.b-watch { background: var(--amber-soft); color: var(--amber-deep); }
.b-reorder { background: var(--orange-soft); color: var(--orange-deep); }
.b-urgent { background: var(--red-soft); color: var(--red-deep); }
.b-out { background: var(--red); color: #fff; }
.b-stagnant { background: rgba(0, 0, 0, .06); color: var(--muted); }
.b-clearing { background: rgba(0, 0, 0, .04); color: var(--muted); border: 1px dashed rgba(0, 0, 0, .2); }

.market-badge {
  display: inline-block;
  padding: 3px 11px;
  border-radius: 999px;
  font-size: 12px;
  font-weight: 700;
  background: var(--accent-soft);
  color: var(--accent);
}

/* 市场列（2026-10-30 用户定稿）：纯蓝色中文，横向排，不要胶囊/圆框。
   nowrap 是关键 —— 原来 64px 列宽 + 11px 左右内边距的胶囊放不下两个字，被挤成了竖排。 */
.market-cell {
  text-align: center;
  color: var(--accent);
  font-weight: 700;
  font-size: 12px;
  white-space: nowrap;
}
/* 看板长表（2026-10-30 用户要求「一屏放下，不要左右滑动」）：
   固定布局 + 瘦身列宽 + 收紧内边距，让 11 列在 1000px 内容区里放得下。
   原来 colgroup 固定 px 合计 824，再叠加每列 14px×2 内边距，必定横向溢出、右侧按钮被切掉。 */
.board-table { table-layout: fixed; min-width: 880px; }
/* 2026-11-03 审计：原来把 min-width 覆盖成 0（想让它自适应），结果是 375px 屏幕上
   11 列挤进 303px：市场列 13px、「详情」按钮叠在「方式」列上点不准，且整页无法横向滚动。
   恢复最小宽 + 让 .table-wrap 横滚（1024 以下也不会互相压字）。 */
@media (max-width: 1180px) {
  .table-wrap { overflow-x: auto; -webkit-overflow-scrolling: touch; }
  .table-wrap .board-table { min-width: 900px; }
  .board-table th:first-child, .board-table td:first-child { position: sticky; left: 0; z-index: 2; background: var(--card-solid, var(--card)); }
}
.board-table th, .board-table td { padding: 10px 8px; }
/* 只有「货号/名称」列可以裁切：其它列的 chip / 数字被裁会变成"206"显示成"20^" */
.board-table td:nth-child(2) { overflow: hidden; }
/* 「货号/名称」是唯一自适应列：内容再长也只省略，不撑破表格 */
.board-table td:nth-child(2) .sku-cell,
.board-table td:nth-child(2) .prod-name { display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.board-table .btn { white-space: nowrap; }
/* 建议方式那列要塞两种 chip（空运/主力），窄列下必须收紧，否则数字会被切 */
.board-table .method-stack { gap: 2px; }
.board-table .method-line { font-size: 11px; gap: 3px; white-space: nowrap; }
.board-table .method-line .chip,
.board-table .method-line .method-chip { padding: 1px 5px; font-size: 11px; }
/* 表格内不重复写「件」（列头已是「建议(件)」）：省下的宽度正好让三位数不被切 */
.board-table .method-line .small { display: none; }
.mkt-badge {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: 50%;
  overflow: hidden;
  vertical-align: -4px;
  flex: 0 0 auto;
  background: var(--card-solid);
  box-shadow: inset 0 0 0 1px rgba(0, 0, 0, .12), 0 1px 1px rgba(0, 0, 0, .06);
}
.mkt-badge svg { display: block; width: 100%; height: 100%; }
.mkt-fallback { background: var(--line-strong); color: var(--text-2); font-weight: 700; line-height: 1; }

/* 产品线库存走势图（2026-10-30：从表格迷你曲线升级到详情页完整图表） */
.line-chart svg { display: block; width: 100%; height: auto; }
.line-chart-legend { display: flex; flex-wrap: wrap; gap: 14px; font-size: 11.5px; color: var(--text-2); margin: 2px 0 8px; }
.line-chart-legend span { display: inline-flex; align-items: center; gap: 5px; }
.line-chart-legend i { display: inline-block; width: 14px; height: 3px; border-radius: 2px; }
.line-chart-legend .k-cur { background: var(--accent, #185fa5); }
.line-chart-legend .k-aft { background: var(--green, #1a9e5c); }
.line-chart-legend .k-target { height: 2px; background: repeating-linear-gradient(90deg, var(--red, #d7263d) 0 4px, transparent 4px 7px); }
.line-chart-legend .k-out { height: 10px; background: rgba(190, 30, 40, .16); }
.line-chart-foot { font-size: 11px; line-height: 1.65; margin-top: 6px; }

.method-chip {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 3px 11px;
  border-radius: 999px;
  font-size: 12px;
  font-weight: 700;
  color: #fff;
}
.method-chip::before { content: ""; width: 5px; height: 5px; border-radius: 50%; background: rgba(255, 255, 255, .85); }

/* ---------- 工具条 ---------- */
.toolbar {
  display: flex;
  gap: 10px;
  flex-wrap: wrap;
  align-items: center;
  margin-bottom: 14px;
}
.toolbar input[type="search"], .toolbar select {
  padding: 9px 14px;
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-input);
  font-size: 13.5px;
  background: var(--surface-input);
  font-family: inherit;
  transition: box-shadow var(--t-fast) var(--ease), border-color var(--t-fast) var(--ease), background var(--t-fast) var(--ease);
}
.toolbar input[type="search"] { flex: 1; min-width: 220px; }
.toolbar input[type="search"]:focus, .toolbar select:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-glow);
}
.toolbar select {
  appearance: none;
  -webkit-appearance: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8'%3E%3Cpath d='M1 1l5 5 5-5' stroke='%2386868b' stroke-width='1.8' fill='none' stroke-linecap='round'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 12px center;
  padding-right: 34px;
}
.toolbar .spacer { flex: 1; }

/* ---------- 弹窗 ---------- */
.modal-mask {
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, .38);
  -webkit-backdrop-filter: saturate(1.8) blur(20px);
  backdrop-filter: saturate(1.8) blur(20px);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 100;
  padding: 20px;
  animation: mask-in .25s var(--ease) both;
}
@keyframes mask-in { from { opacity: 0; } to { opacity: 1; } }
/* 2026-10-19：关闭也要有退场（原来瞬间消失、像被"掐掉"）。
   只做 160ms 的淡出 + 轻微下沉/缩小；.closing 期间禁用指针事件，避免误点。 */
@keyframes mask-out { from { opacity: 1; } to { opacity: 0; } }
@keyframes modal-out { from { opacity: 1; transform: scale(1) translateY(0); } to { opacity: 0; transform: scale(.985) translateY(6px); } }
.modal-mask.closing { pointer-events: none; animation: mask-out .16s ease forwards; }
.modal-mask.closing .modal { animation: modal-out .16s ease forwards; }
.modal {
  background: var(--surface-sheet);
  backdrop-filter: saturate(180%) blur(30px);
  -webkit-backdrop-filter: saturate(180%) blur(30px);
  border-radius: var(--radius-card);
  box-shadow: var(--shadow-lg);
  border: 1px solid var(--line);
  max-width: 760px;
  width: 100%;
  max-height: 88vh;
  max-height: 88dvh;
  display: flex;
  flex-direction: column;
  animation: spring-in .42s var(--ease-spring) both;
  overflow: hidden;
}
.modal.modal-wide { max-width: 860px; }
@keyframes spring-in {
  from { opacity: 0; transform: scale(.96); }
  to { opacity: 1; transform: none; }
}
.modal-head {
  padding: 20px 24px;
  border-bottom: 1px solid var(--line);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
}
.modal-head h3 { font-size: 17px; font-weight: 700; letter-spacing: -.01em; }
.modal-close {
  cursor: pointer;
  width: 30px;
  height: 30px;
  border-radius: 50%;
  font-size: 17px;
  color: var(--muted);
  background: rgba(0, 0, 0, .05);
  border: none;
  line-height: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: background .15s var(--ease), transform .15s var(--ease);
}
.modal-close:hover { background: rgba(0, 0, 0, .1); transform: rotate(90deg); }
.modal-body { padding: 22px 24px; overflow-y: auto; overscroll-behavior: contain; }
.modal-foot { padding: 16px 24px; border-top: 1px solid var(--line); display: flex; justify-content: flex-end; gap: 10px; }
/* 弹窗内裸输入框/下拉兜底样式（未套 .field/.toolbar 的控件；内联样式可覆盖尺寸） */
.modal input:not([type="checkbox"]):not([type="radio"]):not([type="color"]):not([type="range"]):not([type="button"]):not([type="submit"]),
.modal select,
.modal textarea {
  padding: 8px 12px;
  border: 1px solid var(--line-strong, #d8dce3);
  border-radius: var(--radius-input);
  background: var(--card-solid, #fff);
  color: var(--text);
  font-size: 13px;
  font-family: inherit;
  outline: none;
}
.modal select { cursor: pointer; padding-right: 28px; }
.modal input:focus, .modal select:focus, .modal textarea:focus {
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-glow);
}
.modal input:disabled { opacity: .55; cursor: not-allowed; background: var(--bg, #f6f7f9); }
[data-theme="dark"] .modal input:not([type="checkbox"]):not([type="radio"]):not([type="color"]):not([type="range"]):not([type="button"]):not([type="submit"]),
[data-theme="dark"] .modal select,
[data-theme="dark"] .modal textarea { background: #1f1f21; color: var(--text); border-color: #3a3a3c; }

/* ---------- 通知 ---------- */
#toast-root {
  position: fixed;
  top: 70px;
  left: 16px;
  right: 16px;
  display: flex;
  flex-direction: column;
  align-items: center;
  /* 2026-11-03 审计：原来是 300，而弹窗遮罩从 1000 起 → 弹窗里所有提示都被压住，
     用户看到的是"点了没反应"（保存成功、校验失败、撤销全部看不见）。必须高于弹窗栈。 */
  z-index: 3000;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
  pointer-events: none;
}
.toast {
  background: rgba(28, 28, 30, .88);
  backdrop-filter: saturate(180%) blur(20px);
  -webkit-backdrop-filter: saturate(180%) blur(20px);
  color: #fff;
  padding: 11px 22px;
  border-radius: 999px;
  font-size: 13.5px;
  font-weight: 600;
  box-shadow: var(--shadow-lg);
  animation: toast-in .42s var(--ease-spring) both;
  max-width: min(460px, 100%);
  text-align: center;
  will-change: transform, opacity;
}
.toast.success { background: rgba(36, 138, 61, .92); }
.toast.error { background: rgba(200, 30, 30, .92); }
.toast.warn { background: rgba(201, 52, 0, .92); }
@keyframes toast-in {
  from { opacity: 0; transform: translateY(-16px) scale(.96); }
  to { opacity: 1; transform: none; }
}

/* ---------- 详情 ---------- */
.detail-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  gap: 10px;
  margin: 14px 0;
}
.detail-item {
  background: rgba(0, 0, 0, .03);
  border-radius: 14px;
  padding: 12px 14px;
  transition: transform .2s var(--spring);
}
.detail-item:hover { transform: translateY(-2px); }
.detail-item .k { font-size: 12px; color: var(--muted); margin-bottom: 4px; font-weight: 400; }
.detail-item .v { font-size: 17px; font-weight: 600; letter-spacing: -.01em; font-variant-numeric: tabular-nums; }

.advice-box {
  border-radius: 16px;
  padding: 14px 16px;
  margin-top: 14px;
  font-size: 13.5px;
  line-height: 1.75;
  border: 1px solid transparent;
}
.advice-box.warn { background: var(--orange-soft); border-color: rgba(255, 149, 0, .3); color: #7c3a00; }
.advice-box.danger { background: var(--red-soft); border-color: rgba(255, 59, 48, .25); color: #7f1d1d; }
.advice-box.ok { background: var(--green-soft); border-color: rgba(52, 199, 89, .3); color: #14532d; }
.advice-box.info { background: var(--accent-soft); border-color: rgba(0, 102, 204, .25); color: #0b3d91; }

.timeline { margin-top: 14px; }
.timeline-item {
  display: flex;
  gap: 14px;
  padding: 10px 0;
  border-bottom: 1px dashed var(--line);
  font-size: 13px;
  align-items: baseline;
}
.timeline-item:last-child { border-bottom: none; }
.timeline-item .t-date { font-weight: 700; min-width: 104px; color: var(--text-2); font-variant-numeric: tabular-nums; }

/* 合并进「系统设置」的子视图：隐藏其自带页面标题，避免与外层重复 */
.settings-embedded > .page-head { display: none; }
.set-tabs { margin-bottom: 12px; }
.set-tabs button { min-width: 118px; }

/* 名称单元格：缩略图 + 名称/SKU 并排（保证「有 SKU 就有图」） */
.nc-flex { display: flex; align-items: center; gap: 8px; }
.nc-flex > .nc-txt { min-width: 0; overflow: hidden; }
.nc-flex .main { display: block; }
.nc-flex .sub { display: block; }

/* ---------- 可视化时间线 ---------- */
.timeline-chart {
  background: rgba(255, 255, 255, .65);
  border: 1px solid var(--line);
  border-radius: 16px;
  padding: 14px 16px 10px;
}
.timeline-svg {
  width: 100%;
  height: auto;
  display: block;
  min-height: 230px;
}
/* 销量曲线（详情弹窗）：与库存时间线共用同一套 tl-* 视觉，仅整体更紧凑 */
.sales-curve-svg {
  width: 100%;
  height: auto;
  display: block;
  min-height: 190px;
}
.tl-grid { stroke: var(--line-soft, rgba(0, 0, 0, .08)); stroke-width: 1; }
.tl-axis-label { font-size: 10.5px; fill: var(--muted); }
.tl-value-label {
  font-size: 11.5px;
  font-weight: 700;
  fill: var(--text-2);
  paint-order: stroke;
  stroke: rgba(255, 255, 255, .9);
  stroke-width: 3px;
  stroke-linejoin: round;
}
.tl-area { fill: rgba(0, 102, 204, .10); }
.tl-line { fill: none; stroke: var(--accent); stroke-width: 2.2; stroke-linejoin: round; stroke-linecap: round; }
.tl-out-band { fill: rgba(255, 59, 48, .14); }
.tl-arrival-line { stroke: rgba(255, 149, 0, .45); stroke-width: 1; stroke-dasharray: 3 3; }
.tl-arrival-dot { fill: var(--orange); stroke: #fff; stroke-width: 2; }
.tl-today-line { stroke: rgba(0, 0, 0, .35); stroke-width: 1.4; stroke-dasharray: 5 3; }
.tl-today-label { font-size: 10.5px; font-weight: 700; fill: var(--text-2); }
.tl-safety-line { stroke: rgba(134, 134, 139, .55); stroke-width: 1.2; }
.tl-safety-label { font-size: 10px; fill: var(--muted); }
.tl-date-label { font-size: 10px; fill: var(--muted); }
.tl-hover-line { stroke: rgba(20, 20, 24, .38); stroke-width: 1; stroke-opacity: 0; pointer-events: none; }
/* 通用曲线 hover tooltip（看板迷你曲线 / 详情时间线 / 销量曲线） */
.tip-host { position: relative; }
.chart-tip {
  position: absolute;
  top: calc(100% + 5px);
  left: 0;
  transform: translateX(-50%);
  z-index: 60;
  min-width: 90px;
  max-width: 230px;
  padding: 5px 9px;
  border-radius: 8px;
  background: rgba(24, 24, 30, .94);
  color: #fff;
  font-size: 11.5px;
  line-height: 1.5;
  font-variant-numeric: tabular-nums;
  pointer-events: none;
  /* ⚠️ 2026-10-08 滚动卡顿修复：
     backdrop-filter 会**强制创建合成层**，而这个 tip 是常驻 DOM 的
     （看板/趋势页每个图一个，实测 8+ 个）。即使 opacity:0，这些合成层依然存在，
     滚动时浏览器每帧都要对这 8 个层重算背景模糊 —— 这就是"滑动非常明显卡顿"的来源。
     背景本身是 rgba(24,24,30,.94)（近不透明），blur 几乎看不出，去掉零视觉损失。
     注意：显示/隐藏仍由 JS 切 style.opacity（不要改成 visibility，会破坏现有逻辑）。 */
  opacity: 0;
  transition: opacity .12s ease;
  box-shadow: 0 4px 16px rgba(0, 0, 0, .22);
}
.chart-tip b { color: #fff; font-weight: 600; }
/* 详情弹窗：晚到模拟条 */
.sim-banner {
  margin-bottom: 10px;
  padding: 7px 11px;
  border-radius: 10px;
  border: 1px solid rgba(255, 149, 0, .4);
  background: rgba(255, 165, 0, .10);
  color: var(--text-2, #333);
  font-size: 12px;
  line-height: 1.5;
}
.sim-banner b { color: var(--orange-deep, #c2700a); }
.tl-legend {
  display: flex;
  gap: 16px;
  flex-wrap: wrap;
  margin-top: 4px;
  font-size: 11.5px;
  color: var(--muted);
  padding: 4px 2px 2px;
}
.tl-legend span { display: inline-flex; align-items: center; gap: 5px; }
.tl-dot { width: 9px; height: 9px; border-radius: 50%; display: inline-block; }
.tl-dash {
  width: 16px;
  height: 0;
  border-top: 2px dashed var(--muted);
  display: inline-block;
}

/* ---------- 批量发货 ---------- */
.batch-preview { margin-top: 14px; }
.parse-note { font-size: 12.5px; color: var(--muted); margin: 8px 0; }
.parse-note .err { color: var(--red-deep); font-weight: 600; }
.batch-preview input[type="number"], .batch-preview input[type="text"] {
  padding: 7px 10px;
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-input);
  font-size: 13px;
  font-family: inherit;
  background: var(--card-solid);
  transition: box-shadow var(--t-fast) var(--ease), border-color var(--t-fast) var(--ease);
}
.batch-preview input:focus { outline: none; border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-glow); }

/* ---------- 配置表格 ---------- */
.config-table td input {
  width: 92px;
  padding: 7px 9px;
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-input);
  font-size: 13px;
  font-family: inherit;
  background: var(--card-solid);
  text-align: right;
  font-variant-numeric: tabular-nums;
  transition: box-shadow var(--t-fast) var(--ease), border-color var(--t-fast) var(--ease);
}
.config-table td input:focus { outline: none; border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-glow); }

/* iOS 风格开关 */
.switch {
  position: relative;
  display: inline-block;
  width: 46px;
  height: 28px;
  flex-shrink: 0;
}
.switch input { opacity: 0; width: 0; height: 0; }
.switch .track {
  position: absolute;
  inset: 0;
  border-radius: 999px;
  background: rgba(120, 120, 128, .28);
  transition: background .22s var(--ease);
  cursor: pointer;
}
.switch .track::after {
  content: "";
  position: absolute;
  top: 2px;
  left: 2px;
  width: 24px;
  height: 24px;
  border-radius: 50%;
  background: #fff;
  box-shadow: 0 2px 5px rgba(0, 0, 0, .25);
  transition: transform .24s var(--spring);
}
.switch input:checked + .track { background: var(--green); }
.switch input:checked + .track::after { transform: translateX(18px); }

/* ---------- 其他 ---------- */
.muted { color: var(--muted); }
.small { font-size: 12.5px; }
.mt8 { margin-top: 8px; }
.mt12 { margin-top: 12px; }
.mb12 { margin-bottom: 12px; }
.flex { display: flex; gap: 10px; align-items: center; flex-wrap: wrap; }
.flex-end { justify-content: flex-end; }
.grow { flex: 1; }
.empty-state { text-align: center; padding: 44px 20px; color: var(--muted); }
.empty-state .icon { font-size: 40px; margin-bottom: 10px; }
.kbd {
  background: rgba(0, 0, 0, .06);
  border: 1px solid var(--line-strong);
  border-bottom-width: 2px;
  border-radius: 6px;
  padding: 1px 7px;
  font-size: 12px;
  font-family: ui-monospace, "SF Mono", Consolas, monospace;
}
a { color: var(--accent); text-decoration: none; }
a:hover { text-decoration: underline; }

/* 分段控件（iOS 风格） */
/* iOS 分段控件：灰色容器 + 白色"滑块" + 滑块自己的投影（这是它像原生控件的关键） */
.seg {
  display: inline-flex;
  background: var(--fill-tertiary);
  border-radius: 10px;
  padding: 2px;
  gap: 2px;
}
.seg button {
  border: none;
  background: transparent;
  padding: 6px 16px;
  min-height: 30px;
  border-radius: 8px;
  font-size: 13px;
  font-weight: 600;
  cursor: pointer;
  color: var(--text-2);
  font-family: inherit;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  /* HIG 动效：iOS 分段滑块的切换是 250~300ms 的标准缓动，不是弹簧（弹簧会显得"晃"） */
  transition: background .25s var(--ease), color .25s var(--ease), box-shadow .25s var(--ease);
  white-space: nowrap;
}
.seg button.active {
  /* 原来是写死的 #fff：深色主题下白底 + 浅色字 = 选中项看不见 */
  background: var(--card-solid);
  color: var(--text);
  /* iOS 滑块的双层阴影：一层薄贴边 + 一层柔扩散 */
  box-shadow: 0 3px 8px rgba(0, 0, 0, .12), 0 1px 1px rgba(0, 0, 0, .04);
}
.seg button:focus-visible { outline: none; box-shadow: 0 0 0 4px var(--accent-soft); }

/* 响应式 */
@media (max-width: 1180px) {
  .stat-card .num { font-size: 26px; }
  .site-card .mini-row { flex-wrap: wrap; }
  .topbar-right { gap: 9px; }
  .global-search { width: 180px; }
}
@media (max-width: 640px) {
  .page-head { flex-direction: column; align-items: flex-start; gap: 10px; }
  .toolbar { flex-wrap: wrap; }
  .toolbar input, .toolbar select { flex: 1 1 120px; min-width: 0; }
  .stat-grid { grid-template-columns: repeat(auto-fit, minmax(132px, 1fr)); gap: 10px; }
  .stat-card { padding: 14px 14px 12px; }
  .stat-card .num { font-size: 22px; }
  .flex.actions { flex-wrap: wrap; }
}
@media (max-width: 900px) {
  .layout { flex-direction: column; }
  .sidebar {
    width: 100%;
    height: auto;
    position: static;
    display: flex;
    flex-wrap: wrap;
    gap: 4px;
    padding: 10px;
    border-right: none;
    border-bottom: 1px solid var(--line);
  }
  .nav-item { margin-bottom: 0; }
  .nav-sep { display: none; }
  .main { padding: 18px 16px 60px; }
  .topbar { padding: 0 14px; }
  .brand-tag, .today-label { display: none; }
  .page-head h2 { font-size: 23px; }
}

@media print {
  /* 2026-10-19 审计：深色主题下只把 body 背景改白、文字仍用 --text(#f5f5f7) →
     打印出来是白纸白字；表头用 --bg(#161618) 会印成黑块。
     这里把整套颜色变量重置为打印配色（含 [data-theme=dark] 覆盖）。 */
  :root, [data-theme="dark"], [data-theme="light"] {
    --bg: #fff !important;
    --card: #fff !important;
    --card-2: #fff !important;
    --text: #000 !important;
    --text-2: #222 !important;
    --muted: #444 !important;
    --line: #bbb !important;
    --line-soft: #ddd !important;
    --line-strong: #999 !important;
    --surface-2: #fff !important;
    --gray-soft: #f2f2f2 !important;
    /* 2026-11-03 审计：上一轮只重置了 7 个变量，--accent / --blue-deep / --green-deep /
       --red-deep / --orange-deep / --card-solid 仍是深色主题的亮色值
       （深蓝链接 #4da3ff、亮绿 #30d158 在白纸上几乎看不见）。 */
    --accent: #0057b8 !important;
    --accent-press: #004a9e !important;
    --accent-soft: #e8f0fb !important;
    --blue-deep: #0b4f8a !important;
    --green: #1a7f37 !important;
    --green-deep: #166534 !important;
    --red: #b42318 !important;
    --red-deep: #8f1414 !important;
    --orange: #a35a00 !important;
    --orange-deep: #8a4b00 !important;
    --purple: #5b21b6 !important;
    --card-solid: #fff !important;
  }
  /* 徽章 / 方式 chip 是「白字 + 彩色底」：Chrome 默认不打印背景色 → 白纸白字。
     这里强制打印背景，并把彩色 chip 反向成「白底黑字 + 描边」，纸面上才读得出来。 */
  * { -webkit-print-color-adjust: exact !important; print-color-adjust: exact !important; }
  .method-chip, .b-out, .b-urgent, .b-reorder, .b-safe, .b-watch, .b-stagnant, .b-clearing {
    color: #000 !important;
    background: #fff !important;
    box-shadow: inset 0 0 0 1px #666 !important;
    border-color: #666 !important;
  }
  .sidebar, .topbar, .toolbar, .page-head .actions, .site-strip,
  .seg, #cloud-banner, [data-detail], .badge-btn, .modal-close { display: none !important; }
  /* 全局 table{min-width:860px} 在 A4（约 697px 可打印宽）会溢出到纸外，
     商品页 15 列会被切掉右侧「启用 / 操作」。打印时一律取消最小宽。 */
  table, .board-table { min-width: 0 !important; width: 100% !important; }
  @page { margin: 12mm; }
  .layout { display: block; }
  .main { padding: 0; }
  body, .modal, .card, .table-wrap, table, th, td { background: #fff !important; color: #000 !important; }
  .card { box-shadow: none; border: none; }
  /* 看板/商品表容器限高 66vh + sticky 表头：打印时会被裁掉后半截数据，
     用户会以为数据不全。打印必须解除高度限制并让表头回到普通流。 */
  .table-wrap, .table-wrap.scroll-v { max-height: none !important; overflow: visible !important; height: auto !important; }
  thead th, .table-wrap th { position: static !important; }
  tr { break-inside: avoid; }
  .table-wrap thead { display: table-header-group; } /* 长表跨页时每页重复表头 */
}

/* ============== UI 动效 & 交互增强 ============== */

/* HIG：卡片是静态表面，hover 不抬升、不投影（分层靠发丝线描边，长表滚动更顺） */
/* 表格行 hover 背景
   ⚠️ 2026-10-08 滚动卡顿修复：原来 tr 上有 transition: background-color .14s。
   长表（287 行）滚动时鼠标停在表上，每一行从鼠标下经过都会**触发一次 0.14s 的过渡动画**，
   连续滚动 = 持续重绘 → 明显卡顿。hover 反馈本来就该是即时的，过渡在这里没有价值。 */
.table-wrap table tbody tr:hover {
  background: rgba(24,95,165,.04);
}
/* 按钮点击反馈 */
.btn {
  transition: transform .12s var(--ease), background .18s var(--ease), box-shadow .18s var(--ease), opacity .18s;
}
.btn:active { transform: scale(.97); }
/* 徽章 hover 提示 */
.badge {
  transition: transform .14s var(--ease), filter .14s var(--ease);
}
.badge:hover { filter: brightness(.95); transform: scale(1.04); }
/* 侧边导航项 hover */
.nav-item {
  transition: background var(--t-2) var(--e-out), color var(--t-2) var(--e-out);
  position: relative;
}
/* 选中竖条：位置由 top/height 固定，动画只做 scaleY。
   2026-11-03 修复：base 用 inset 指定上下边距（高度被拉伸），active 又带 translateY(-50%)，
   两条规则叠加后整条上移半个身位 → 顶部探出胶囊、底部留空，切页时尤其明显。
   现在竖条是 18px 定高 + 圆角，完全落在白色胶囊内部，不再受高度变化影响。 */
.nav-item::before {
  content: "";
  position: absolute;
  left: 0;
  top: 50%;
  margin-top: -9px;
  width: 3px;
  height: 18px;
  background: var(--accent);
  border-radius: 0 2px 2px 0;
  transform: scaleY(0);
  transform-origin: 50% 50%;
  opacity: 0;
  pointer-events: none;
  transition: transform var(--t-2) var(--e-out), opacity var(--t-1) linear;
}
.nav-item.active::before { transform: scaleY(1); opacity: 1; }
/* 输入框 focus 微动效 */
input, select, textarea {
  transition: border-color .18s var(--ease), box-shadow .18s var(--ease);
}
input:focus, select:focus, textarea:focus {
  box-shadow: 0 0 0 3px rgba(24,95,165,.10);
}
/* ---------- 裸输入框 / 下拉 / 文本域全局兜底 ----------
   未套 .field / .toolbar / .global-search 等组件样式的控件（如需求提交行、
   弹窗行内编辑、表格内输入框）统一为站内一致的边框、圆角、内边距。
   :where() 保持零特异性：所有组件级规则与内联样式都能正常覆盖。 */
input:where(:not([type="checkbox"], [type="radio"], [type="color"], [type="range"], [type="button"], [type="submit"], [type="reset"], [type="file"])),
select,
textarea {
  padding: 8px 12px;
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-input);
  background: var(--card-solid, #fff);
  color: var(--text);
  font-size: 13px;
  font-family: inherit;
  line-height: 1.4;
  outline: none;
  min-height: 34px;
  transition: border-color var(--t-fast) var(--ease), box-shadow var(--t-fast) var(--ease);
}
select { cursor: pointer; padding-right: 28px; }
input:focus, select:focus, textarea:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-glow);
}
input:where(:disabled), select:disabled, textarea:disabled {
  opacity: .55;
  cursor: not-allowed;
  background: var(--bg, #f6f7f9);
}
textarea { resize: vertical; }
/* 站点切换 pill 选中动画 */
.site-pill {
  transition: background .18s var(--ease), color .18s var(--ease), transform .14s var(--ease);
}
.site-pill:hover { transform: translateY(-1px); }
.site-pill.active { animation: pill-pop .3s var(--spring) both; }
@keyframes pill-pop {
  from { transform: scale(.92); }
  to { transform: scale(1); }
}
/* 搜索框聚焦时微放大 */
input[type="search"]:focus, input[type="text"]:focus { transform: scale(1.005); }

/* 整线行：名称单元格里直接列出全部成员 SKU（不必展开），每个 SKU 后面跟它的库存/分摊补货量 */
.merge-sku-list {
  display: flex;
  align-items: flex-start;
  gap: 4px 6px;
  line-height: 1.6;
  /* 表格单元格里的匿名 flex 容器会收缩到内容宽（实测 270/330），显式撑满才能排两列 */
  width: 100%;
}
/* 2026-11-03：SKU 改成「按列」的自适应网格 —— 宽屏两列、窄屏一列，每个 chip 完整可见，
   行高随成员数量自然增长。看板原有的 `td:nth-child(2) .sku-cell { nowrap + ellipsis }`
   会把这排 chip 压成一行、末尾裁掉（用户截图），这里用更高优先级覆盖掉。 */
.board-table tr.merge-line td:nth-child(2) .merge-sku-list {
  display: flex;
  white-space: normal;
  overflow: visible;
  text-overflow: clip;
}
.merge-sku-grid {
  flex: 1;
  min-width: 0;
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(142px, 1fr));
  gap: 4px 6px;
}
.merge-sku-grid .sku-chip { max-width: 100%; justify-content: space-between; }
/* 展开箭头：SVG 折角箭头，靠 class 旋转（原来用 ▾/▴ 文本切换，字重和基线都不稳） */
.merge-arrow {
  display: inline-flex;
  align-items: center;
  color: var(--muted);
  vertical-align: -2px;
  transition: transform 160ms var(--e-out, ease);
}
.merge-arrow.open { transform: rotate(180deg); }
/* 「仅异常」移到标题行右侧：留在 chip 行会吃掉一整列宽度，两个 SKU 只能竖排 */
.merge-abn { float: right; margin-top: -2px; }
.sku-chip {
  display: inline-flex;
  align-items: baseline;
  gap: 4px;
  padding: 0 6px;
  border-radius: 6px;
  background: rgba(0, 102, 204, .07);
  border: 1px solid rgba(0, 102, 204, .15);
  font-size: 11px;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.sku-chip .s { color: var(--text-2); }
.sku-chip b { font-weight: 600; color: var(--text); }
.sku-chip em { font-style: normal; font-weight: 700; color: var(--blue-deep, #185FA5); }
.sku-chip em::before { content: "·"; color: var(--muted); margin-right: 4px; font-weight: 400; }

/* ============== 销量趋势图（sc-wrap）专属样式 ============== */
.sc-wrap {
  background: linear-gradient(180deg, #fafcff 0%, #ffffff 100%);
  border: 1px solid var(--line-soft, #e8e8e8);
  border-radius: 12px;
  padding: 16px 18px 14px;
}
.sc-legend {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 12px;
  color: var(--muted, #666);
  padding: 4px 8px;
  border-radius: 6px;
  transition: background .15s var(--ease);
}
.sc-legend:hover { background: rgba(0,0,0,.03); }
.sc-legend i {
  width: 22px; height: 4px;
  display: inline-block;
  border-radius: 2px;
}
.sc-svg { overflow: visible; }
.sc-svg [class^="sc-line-"] {
  stroke-dasharray: 1000;
  stroke-dashoffset: 1000;
  animation: sc-draw 1.4s var(--ease) forwards;
  filter: drop-shadow(0 1px 1px rgba(0,0,0,.08));
}
.sc-svg .sc-line-uk { animation-delay: .15s; }
.sc-svg .sc-line-us { animation-delay: .3s; }
.sc-svg [class^="sc-area-"] {
  opacity: 0;
  animation: sc-fade-in .8s var(--ease) .6s forwards;
}
.sc-svg .sc-area-uk { animation-delay: .75s; }
.sc-svg .sc-area-us { animation-delay: .9s; }
@keyframes sc-draw {
  to { stroke-dashoffset: 0; }
}
@keyframes sc-fade-in {
  to { opacity: 1; }
}
.sc-svg g.sc-pt { cursor: pointer; }
.sc-svg g.sc-pt circle {
  transition: r .15s var(--spring), stroke-width .15s var(--ease), filter .15s var(--ease);
}
.sc-svg g.sc-pt:hover circle,
.sc-svg g.sc-pt.sc-active circle {
  r: 5;
  filter: drop-shadow(0 0 4px currentColor);
}
.sc-svg g.sc-pt.sc-active .sc-dot-de { fill: #0c447c; }
.sc-svg g.sc-pt.sc-active .sc-dot-uk { fill: #993c1d; }
.sc-svg g.sc-pt.sc-active .sc-dot-us { fill: #1B5E20; }
.sc-svg .sc-col {
  fill: transparent;
  cursor: crosshair;
}
.sc-svg .sc-cursor {
  transition: opacity .15s var(--ease);
}
.sc-tip {
  position: fixed;
  top: 0; left: 0;
  pointer-events: none;
  transform: translate(-50%, -100%) translateY(-8px);
  background: rgba(28,32,40,.96);
  color: #fff;
  padding: 8px 12px;
  border-radius: 8px;
  font-size: 12px;
  line-height: 1.6;
  box-shadow: 0 8px 24px rgba(0,0,0,.18);
  z-index: 9999;
  opacity: 0;
  transition: opacity .12s var(--ease);
  white-space: nowrap;
}
.sc-tip::after {
  content: "";
  position: absolute;
  bottom: -4px;
  left: 50%;
  transform: translateX(-50%);
  border: 4px solid transparent;
  border-top-color: rgba(28,32,40,.96);
}
.sc-tip-date { font-weight: 600; margin-bottom: 4px; color: #fff; }
.sc-tip-row { display: flex; align-items: center; gap: 6px; }
.sc-tip-row i { width: 10px; height: 3px; border-radius: 2px; display: inline-block; }
.sc-tip-row b { color: #fff; font-weight: 600; min-width: 24px; text-align: right; }
.sc-stats { font-size: 12px; }
.sc-stats > div {
  background: rgba(24,95,165,.04);
  padding: 8px 12px;
  border-radius: 8px;
  border-left: 3px solid var(--blue-deep, #185FA5);
  transition: transform .15s var(--ease), background .15s var(--ease);
}
.sc-stats > div:hover { background: rgba(24,95,165,.08); transform: translateX(2px); }
.sc-stats > div.sc-stat-uk { border-left-color: var(--orange-deep, #C2700A); background: rgba(194,112,10,.04); }
.sc-stats > div.sc-stat-uk:hover { background: rgba(194,112,10,.08); }
.sc-stats > div.sc-stat-us { border-left-color: #2E7D32; background: rgba(46,125,50,.04); }
.sc-stats > div.sc-stat-us:hover { background: rgba(46,125,50,.08); }
.sc-stats > div.sc-stat-sum { border-left-color: var(--muted, #888); background: rgba(0,0,0,.03); }
.sc-stats .lbl { display: block; color: var(--muted, #666); font-size: 11px; }
.sc-stats b { display: inline-block; font-size: 16px; font-weight: 600; margin: 0 4px; }
.sc-stats em { color: var(--muted, #888); font-style: normal; font-size: 11px; }

/* ============== 全局微动效 ============== */
/* 数字 cell hover 高亮 */
.num, td.num {
  font-variant-numeric: tabular-nums;
  transition: color .14s var(--ease);
}
.metric-card, .stat-tile {
  cursor: default;
}
/* 模态打开/关闭动画 */
.modal-content {
  animation: modal-in .25s var(--spring) both;
}
@keyframes modal-in {
  from { transform: scale(.94) translateY(8px); opacity: 0; }
  to { transform: scale(1) translateY(0); opacity: 1; }
}
.modal-back {
  animation: backdrop-in .18s ease both;
}
@keyframes backdrop-in { from { opacity: 0; } to { opacity: 1; } }

/* 数据加载骨架（占位） */
.skeleton {
  overflow: hidden; /* 微光改用 transform 位移后必须裁剪，否则会溢出到卡片外 */
  background: linear-gradient(90deg, #f0f1f4 25%, #e6e7eb 50%, #f0f1f4 75%);
  background-size: 200% 100%;
  animation: skeleton-shimmer 1.4s ease-in-out infinite;
  border-radius: 6px;
  color: transparent;
}
@keyframes skeleton-shimmer {
  /* 用伪元素位移做微光扫过（只动 transform）；原来动 background-position 每帧重绘 */
  0% { transform: translateX(-60%); }
  100% { transform: translateX(60%); }
}

/* 列表项入场 */
.fade-in-stagger > * {
  animation: fade-up .4s var(--ease) both;
}
.fade-in-stagger > *:nth-child(1) { animation-delay: 0ms; }
.fade-in-stagger > *:nth-child(2) { animation-delay: 40ms; }
.fade-in-stagger > *:nth-child(3) { animation-delay: 80ms; }
.fade-in-stagger > *:nth-child(4) { animation-delay: 120ms; }
.fade-in-stagger > *:nth-child(5) { animation-delay: 160ms; }
.fade-in-stagger > *:nth-child(6) { animation-delay: 200ms; }
.fade-in-stagger > *:nth-child(7) { animation-delay: 240ms; }
.fade-in-stagger > *:nth-child(8) { animation-delay: 280ms; }
.fade-in-stagger > *:nth-child(n+9) { animation-delay: 320ms; }
@keyframes fade-up {
  from { transform: translateY(6px); opacity: 0; }
  to { transform: translateY(0); opacity: 1; }
}

/* 数字变化时微高亮 */
/* fill-mode 写 both：动画结束后显式停在 100% 关键帧（透明），不靠「层叠碰巧对」 */
.num.flash { animation: num-flash 0.6s ease both; }
@keyframes num-flash {
  0% { background: rgba(24,95,165,.18); }
  100% { background: transparent; }
}

/* 页面切换容器 */
.page-body {
  animation: page-in .28s var(--ease) both;
}
@keyframes page-in {
  from { transform: translateY(4px); opacity: 0; }
  to { transform: translateY(0); opacity: 1; }
}

/* 小三角展开 */
details[open] summary ~ * { animation: details-open .25s var(--ease) both; }
@keyframes details-open {
  from { opacity: 0; transform: translateY(-4px); }
  to { opacity: 1; transform: translateY(0); }
}

/* 复选框 / 开关微动效 */
input[type="checkbox"] {
  transition: background .15s var(--ease), border-color .15s var(--ease);
}

/* 图片 SKU 缩略图 hover 缩放 */
.sku-img {
  transition: transform .2s var(--spring), box-shadow .2s var(--ease);
  cursor: pointer;
}
.sku-img:hover {
  transform: scale(1.08);
  box-shadow: 0 4px 12px rgba(0,0,0,.15);
}

/* 通用减少动画偏好（无障碍） */
/* toast 撤销按钮（2026-10-06）：破坏性操作后的反悔入口 */
.toast-actionable {
  display: flex; align-items: center; gap: 10px; max-width: 420px;
  /* 2026-10-19 审计 P0：父容器 #toast-root 设了 pointer-events:none 让普通提示穿透，
     但 `.toast` 没有恢复，导致带「撤销」按钮的 toast **整条都点不到**（按钮形同虚设）。
     只给可交互的这类恢复，普通提示仍然穿透、不挡下面内容。 */
  pointer-events: auto;
}
.toast-undo {
  flex: none; padding: 4px 10px; font-size: 12px; font-weight: 600; cursor: pointer;
  color: #fff; background: rgba(255, 255, 255, .22); border: 1px solid rgba(255, 255, 255, .38);
  border-radius: 999px; transition: background var(--t-fast, 150ms), transform var(--t-fast, 150ms);
}
.toast-undo:hover { background: rgba(255, 255, 255, .34); }
.toast-undo:active { transform: scale(.96); }
.toast-undo:focus-visible { outline: 2px solid #fff; outline-offset: 1px; }

/* 长表渲染优化（2026-10-06）：SKU 上千后一次性 innerHTML 生成上千行会明显卡顿。
   content-visibility 让屏外的行跳过布局与绘制（首次滚动到时才渲染），
   行为与原来完全一致（DOM 结构、滚动条、Ctrl+F 都不受影响），滚动中随渲染渐进变顺。 */
/* 长表渲染优化（2026-10-06 加，2026-10-08 校正）。
   content-visibility:auto 让屏外行跳过渲染，但 contain-intrinsic-size 声明的高度
   必须贴近**实际行高**——实测商品页行高是 146~203px，原来写 44px，
   首次滚动到新区域时浏览器要按 44px 估算再修正（滚动条会小幅跳动）。
   注：曾怀疑它是"滑动卡顿"主因，实测 scrollHeight 恒定（31800+ 不变）→ 已证伪，
   真凶是常驻毛玻璃合成层（见 .chart-tip / .topbar.scrolled 注释）。 */
.table-wrap tbody tr { content-visibility: auto; contain-intrinsic-size: auto 180px; }

/* 审计页字段级回溯标签（2026-10-08）：字段 旧值 → 新值 */
.diff-chip {
  display: inline-block; margin: 1px 3px 1px 0; padding: 1px 7px; font-size: 11px;
  border: 1px solid var(--line-soft, #e6e8ee); border-radius: 999px;
  background: var(--fill-quaternary, rgba(0,0,0,.02)); white-space: nowrap;
}
.diff-chip s { text-decoration: line-through; opacity: .75; }
.diff-chip b { color: var(--blue-deep, #185fa5); }

/* ==================== 2026-10-06 可达性与动效质量（多轮审计后统一补齐） ==================== */
/* 自定义可点控件的键盘焦点环：此前只有 .btn / .seg button 有，
   站点 pill、统计卡、站点卡、SKU 缩略图 Tab 过去完全看不见焦点 */
.site-pill:focus-visible,
.stat-card:focus-visible,
.site-card:focus-visible,
.sku-img:focus-visible,
.tag-chip:focus-visible,
.pv-chip:focus-visible {
  outline: none;
  box-shadow: 0 0 0 3px var(--accent-glow, rgba(0, 102, 204, .32));
  border-radius: inherit;
}
.stat-card:focus-visible,
.site-card:focus-visible { transform: translateY(-1px); }
/* .link-cell（<a> 无 href 的可点入口）此前既无样式也不可聚焦 */
.link-cell { cursor: pointer; color: var(--blue-deep, #185fa5); text-decoration: underline dotted; text-underline-offset: 2px; }
[data-vel], [data-open-detail] { cursor: pointer; }
/* 骨架屏：改用 transform 位移（原来动 background-position，每帧重绘） */
.skeleton-shimmer { background-size: 200% 100%; }

@media (prefers-reduced-motion: reduce) {
  /* 必须同时停掉 infinite：只把 duration 压到 0.01ms 会变成高频闪烁（反效果） */
  *, *::before, *::after { animation-iteration-count: 1 !important; }
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    transition-duration: 0.01ms !important;
  }
}

/* 云端未启用 banner */
.cloud-banner {
  background: #fff7e6;
  border-bottom: 1px solid #f0d9a8;
  color: #7a5b1e;
  padding: 9px 20px;
  font-size: 13px;
  text-align: center;
  cursor: pointer;
  transition: background .18s var(--ease);
}
.cloud-banner:hover { background: #ffefcc; }
.cloud-banner b { color: #b45309; }
.cloud-banner #cloud-banner-detail { margin-left: 8px; color: #8a6a25; }
.cloud-banner .cloud-banner-act { margin-left: 8px; color: #b45309; text-decoration: underline; white-space: nowrap; }

/* ============== 本周需求（demands） ============== */
.demand-rulebar {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 8px;
}
.demand-rulebar .dr-seg {
  border-radius: 10px;
  padding: 10px 12px;
  text-align: center;
  border: 1px solid var(--line-soft, #e8e8e8);
}
.demand-rulebar .dr-seg b { display: block; font-size: 14px; margin-bottom: 2px; }
.demand-rulebar .dr-seg span { font-size: 12px; color: var(--muted, #666); }
.dr-a { background: rgba(194,112,10,.08); border-color: rgba(194,112,10,.3) !important; }
.dr-b { background: rgba(24,95,165,.07); border-color: rgba(24,95,165,.3) !important; }
.dr-c { background: rgba(34,197,94,.07); border-color: rgba(34,197,94,.3) !important; }
.dr-d { background: rgba(163,45,45,.08); border-color: rgba(163,45,45,.35) !important; }
.dr-d b { color: var(--red-deep, #A32D2D); }

.demand-row {
  display: flex;
  gap: 8px;
  margin-bottom: 8px;
  align-items: center;
  padding: 8px 10px;
  background: var(--bg, #f6f7f9);
  border: 1px solid var(--line);
  border-radius: 12px;
  transition: border-color .18s var(--ease), box-shadow .18s var(--ease);
}
.demand-row:focus-within { border-color: var(--accent, #185fa5); box-shadow: 0 0 0 3px rgba(24, 95, 165, .08); }
.demand-row .d-sku { flex: 1; min-width: 180px; }
.demand-row .d-order { flex: 0 0 200px; }
.demand-row .d-qty { width: 110px; text-align: right; }
.demand-row [data-del-row] { flex: 0 0 auto; }

.d-users { line-height: 1.9; }
.d-user { font-size: 12px; color: var(--muted, #555); }
.d-user b { color: var(--blue-deep, #185FA5); font-weight: 600; }

.d-adjust {
  display: flex;
  gap: 6px;
  align-items: center;
  margin-top: 4px;
}
.d-adjust input { width: 110px; }

/* ============== 产品线合并（merge group） ============== */
.merge-line {
  background: linear-gradient(90deg, rgba(24,95,165,.07), rgba(24,95,165,.02));
  cursor: pointer;
}
.merge-line:hover td { background: rgba(24,95,165,.06); }
.merge-line td { padding-top: 10px; padding-bottom: 10px; }
/* 合并后的子行：原来写死 rgba(255,255,255,.6) → 深色下整行变白底、灰字几乎看不见
   （实测截图里"2-AL110601"那行就是它） */
.merge-child td { background: var(--surface-nested); }
.merge-child .name-cell { padding-left: 26px; position: relative; }
.merge-child .name-cell::before {
  content: "└";
  position: absolute;
  left: 8px; top: 12px;
  color: var(--muted, #999);
  font-size: 12px;
}
.b-info {
  background: rgba(24,95,165,.12);
  color: var(--blue-deep, #185FA5);
  font-weight: 600;
}
/* 汇总行单位小字（个） */
td .unit {
  font-size: 10px;
  color: var(--muted, #888);
  margin-left: 2px;
  font-weight: 400;
}
/* 产品线汇总行迷你曲线 hover */
tr.merge-line td svg circle { cursor: crosshair; transition: r .12s ease; }
tr.merge-line td svg circle:hover { r: 3; }
tr.merge-line td svg { display: block; }
/* 汇总行提示角标 */
.merge-warn {
  display: inline-block;
  margin-left: 6px;
  padding: 1px 7px;
  border-radius: 999px;
  background: var(--red-soft, rgba(200,30,30,.1));
  color: var(--red-deep, #c81e1e);
  font-size: 11px;
  font-weight: 700;
  vertical-align: middle;
}
/* 顶部 stat 卡片副文（紧急·断货） */
.stat-sub {
  font-size: 11px;
  color: var(--muted, #888);
  margin-top: 4px;
  font-weight: 600;
}
.stat-sub .sub-danger { color: var(--red-deep, #c81e1e); }
.stat-sub .sub-out { color: #c2700a; }
.stat-sub .mx4 { margin: 0 4px; color: var(--muted, #888); }
/* 趋势弹窗指标 chip */
.stat-chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 5px 10px;
  border-radius: 999px;
  border: 1px solid var(--line, #e5e7eb);
  background: rgba(127, 127, 127, .05);
  font-size: 12px;
  font-weight: 600;
  color: var(--text-2, #374151);
  white-space: nowrap;
}
.stat-chip i {
  width: 9px;
  height: 9px;
  border-radius: 50%;
  display: inline-block;
  flex: 0 0 auto;
}
/* 详情弹窗日期分组 */
.detail-item.detail-dates .v > div {
  font-size: 12px;
  line-height: 1.7;
  margin-bottom: 2px;
}
.detail-item.detail-dates .danger-text { color: var(--red-deep, #c81e1e); font-weight: 600; }
.detail-item.detail-dates .ok-text { color: var(--green, #1aa463); font-weight: 600; }
.detail-item.detail-dates .muted { color: var(--muted, #888); }

/* ---------- 定价计算器 ---------- */
.pv-f { display: flex; flex-direction: column; gap: 4px; font-size: 12px; }
.pv-f > span:first-child { color: var(--muted); }
.pv-f input {
  padding: 7px 10px; border: 1px solid var(--line-strong); border-radius: 10px;
  background: var(--card-solid); color: var(--text); font-size: 13px; font-family: inherit;
}
.pv-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(190px, 1fr)); gap: 10px; }
.pv-bar {
  display: flex; width: 100%; border-radius: 6px; overflow: hidden;
  background: var(--gray-soft); box-shadow: inset 0 0 0 1px var(--line);
}
.pv-bar > i { display: block; height: 100%; }
.pv-legend { display: flex; flex-wrap: wrap; gap: 8px 16px; font-size: 12px; }
.pv-lg { display: inline-flex; align-items: center; gap: 6px; color: var(--text-2); }
.pv-lg i { width: 10px; height: 10px; border-radius: 3px; display: inline-block; flex: none; }
.pv-lg b { font-weight: 600; }
.pv-lg em { color: var(--muted); font-style: normal; font-size: 11px; }
.pv-skus { display: flex; flex-wrap: wrap; gap: 6px; max-height: 220px; overflow: auto; }
.pv-chip {
  border: 1px solid var(--line-strong); background: var(--card-solid); color: var(--text-2);
  border-radius: 9px; padding: 5px 9px; font-size: 12px; cursor: pointer;
  display: inline-flex; gap: 6px; align-items: center; font-family: inherit;
  transition: border-color .18s, color .18s;
}
.pv-chip:hover { border-color: var(--accent); color: var(--accent); }
.pv-chip em { font-style: normal; color: var(--muted); font-size: 11px; }
.pv-est { font-size: 10px; background: var(--amber-soft); color: var(--amber-deep); border-radius: 4px; padding: 0 4px; }
[data-theme="dark"] .pv-chip { background: #1f1f21; }
.pv-cell {
  width: 68px; padding: 4px 6px; font-size: 12px; text-align: right;
  border: 1px solid var(--line-strong); border-radius: 7px;
  background: var(--card-solid); color: var(--text); font-family: inherit;
}
.pv-cell.pv-mod { border-color: var(--accent); color: var(--accent); font-weight: 600; }
[data-theme="dark"] .pv-cell { background: #1f1f21; }
.pv-src { display: inline-block; font-size: 11px; padding: 1px 6px; border-radius: 6px; margin-left: 4px; }
.pv-src-w { background: var(--green-soft); color: var(--green-deep); }
.pv-src-c { background: var(--amber-soft); color: var(--amber-deep); }
.pv-src-n { background: var(--red-soft); color: var(--red-deep); }
a.pv-more { cursor: pointer; text-decoration: underline dotted rgba(0, 0, 0, .28); text-underline-offset: 3px; }
a.pv-more:hover { text-decoration-color: var(--accent); }
a.pv-more-hi { color: var(--accent); font-weight: 600; }
.pv-modal-top { display: flex; align-items: center; gap: 8px; padding: 8px 0 12px; border-bottom: 1px solid var(--line); margin-bottom: 12px; }
.pv-step { margin-bottom: 14px; }
.pv-step-h { display: flex; align-items: center; gap: 8px; font-weight: 600; font-size: 13px; margin-bottom: 6px; }
.pv-step-h i {
  display: inline-flex; align-items: center; justify-content: center; width: 20px; height: 20px;
  border-radius: 50%; background: var(--accent-soft); color: var(--accent); font-style: normal; font-size: 11px; font-weight: 700; flex: none;
}
.pv-step-b { padding-left: 28px; font-size: 13px; color: var(--text-2); }
.pv-eq {
  font-family: ui-monospace, SFMono-Regular, Consolas, monospace; font-size: 12.5px;
  background: var(--gray-soft); border-radius: 8px; padding: 8px 10px; line-height: 1.9; word-break: break-word;
}
/* table-layout:fixed + 固定首末列宽：中间的公式再长也只换行，不会把「金额」列挤出弹窗
   （曾因此让第三列整列看不见 —— 数值在 DOM 里但被裁掉） */
/* min-width:0 是关键：全局 `table { min-width: 860px }` 会在弹窗里把表格撑破容器，
   导致最右边的「金额」列被 overflow:hidden 裁掉（数值在 DOM 里但看不见） */
.pv-calc { width: 100%; min-width: 0; font-size: 12.5px; table-layout: fixed; }
.pv-calc td:first-child { width: 84px; }
.pv-calc td.v { width: 104px; }
.pv-calc td { padding: 5px 6px; border-bottom: 1px dashed var(--line); vertical-align: top; }
.pv-calc td.m { color: var(--muted); font-family: ui-monospace, SFMono-Regular, Consolas, monospace; font-size: 12px; overflow-wrap: anywhere; word-break: break-word; }
.pv-calc td.v { text-align: right; font-variant-numeric: tabular-nums; white-space: nowrap; }
.pv-calc tr.sum td { border-bottom: none; border-top: 1px solid var(--line-strong); font-weight: 700; }

/* 定价页「悬停看算法」浮层：等宽数字 + 三列对齐（项目/公式/金额），扫一眼就能逐项对账。
   鼠标指着的那一项会高亮，所以看单项成本不用在长公式里找。 */
.pv-tip {
  position: fixed; z-index: 9999; width: 524px; max-width: calc(100vw - 24px);
  max-height: calc(100vh - 24px); overflow: auto;
  padding: 12px 14px 10px; border-radius: 14px;
  background: var(--card-solid, #fff); border: 1px solid var(--line-strong, rgba(0, 0, 0, .14));
  box-shadow: 0 18px 44px rgba(0, 0, 0, .22);
  font-size: 12.5px; color: var(--text);
}
.pv-tip-head { display: flex; align-items: center; gap: 8px; padding-bottom: 8px; border-bottom: 1px solid var(--line); }
.pv-tip-sec { font-weight: 600; font-size: 12px; color: var(--text-2); margin: 11px 0 3px; }
.pv-tip .pv-calc td:first-child { width: 96px; }
.pv-tip .pv-calc td { padding: 4px 6px; }
/* 高亮要一眼能看到：底色 + 左侧强调条 + 加粗（只靠 10% 淡蓝在浅色下太弱） */
.pv-tip .pv-calc td.m { color: var(--text-2); }
.pv-tip .pv-calc tr.hi td { background: var(--accent-soft); }
.pv-tip .pv-calc tr.hi td:first-child { box-shadow: inset 3px 0 0 var(--accent); font-weight: 700; }
.pv-tip .pv-eq { font-size: 12px; padding: 7px 9px; line-height: 1.85; margin-top: 3px; }
.pv-tip .pv-eq.hi { box-shadow: inset 0 0 0 2px var(--accent-soft); }
.pv-tip .hi-block { border-radius: 8px; box-shadow: 0 0 0 2px var(--accent-soft); }
.pv-tip-foot { margin-top: 9px; padding-top: 6px; border-top: 1px solid var(--line); color: var(--muted); font-size: 11.5px; }


/* ---------- 窄屏（2026-10-19 审计：375px 下顶栏溢出导致整页横向滚动） ---------- */
@media (max-width: 640px) {
  /* 搜索框是 210px 固定宽，窄屏上把右侧按钮挤出屏幕 */
  .global-search { display: none !important; }
  #user-chip { max-width: 96px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .topbar { padding-left: 10px; padding-right: 10px; gap: 6px; }
  .topbar-right { gap: 4px; min-width: 0; }
  .main { padding: 14px 12px 48px; }
  /* 表格宽（16 列）：允许横向滚动而不是压缩列宽（压缩会让数字换行不可读） */
  .table-wrap { overflow-x: auto; -webkit-overflow-scrolling: touch; }
  .modal { margin: 8px; max-width: calc(100vw - 16px); }
  .modal-wide { max-width: calc(100vw - 16px) !important; }
}


/* ---------- 全局键盘焦点（2026-10-19 无障碍） ---------- */
/* 按钮/分段已各自定义焦点环；这里兜底导航项、输入框、链接、表格可点行，
   保证纯键盘操作时始终能看清焦点在哪（鼠标点击不会出现，避免视觉噪音）。 */
:focus-visible { outline: 2px solid var(--focus-ring, #185FA5); outline-offset: 2px; }
.nav-item:focus-visible, .link:focus-visible, [tabindex]:focus-visible { outline: 2px solid var(--focus-ring, #185FA5); outline-offset: 2px; }
input:focus-visible, select:focus-visible, textarea:focus-visible { outline: 2px solid var(--focus-ring, #185FA5); outline-offset: 1px; }


/* ---------- 备货列表可读性（2026-10-19） ---------- */
/* 固定列宽：名称列拿剩余空间，其它列按内容给足 —— 原来自动布局把 150px 给了
   「市场/类型」这类低密度列，货号被折成 4 行、"呆滞库存"逐字竖排。 */
.board-table { table-layout: fixed; width: 100%; }
.board-table td, .board-table th { vertical-align: middle; }
/* 名称与 SKU 单行省略（悬停看全名；title 已在 nameCellBody 上） */
.board-table .nc-txt { min-width: 0; }
.board-table .nc-txt .main,
.board-table .nc-txt .sub,
.board-table .nc-txt .sku,
.board-table .nc-txt .sku2 {
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
/* 类型列禁止逐字换行（呆滞库存 → 一行） */
.board-table td:nth-child(3), .board-table th:nth-child(3) { white-space: nowrap; }
/* 库存为 0：用警示色而不是浅灰（这是最需要一眼看到的信号） */
.num-zero { color: var(--red); font-weight: 600; }
.num-zero::after { content: ""; }
/* 建议方式：每种一行，数字后带「件」（原来 "空运 25 + 海运 10" 的加号像 "25+"） */
.method-stack { display: flex; flex-direction: column; gap: 2px; align-items: flex-start; }
.method-line { display: inline-flex; align-items: center; gap: 5px; white-space: nowrap; font-size: 12px; }
.method-line b { font-variant-numeric: tabular-nums; }


/* ---------- 备货清单（2026-10-19 新增，行动视角） ---------- */
.rp-sum { display: grid; grid-template-columns: repeat(3, minmax(140px, 190px)) 1fr; gap: 12px; margin-bottom: 18px; }
@media (max-width: 900px) { .rp-sum { grid-template-columns: 1fr 1fr; } }
.rp-sum-card { background: var(--card); border: 1px solid var(--line); border-radius: var(--radius-card); padding: 14px 16px; }
.rp-sum-card .num { font-size: 26px; font-weight: 650; letter-spacing: -.02em; font-variant-numeric: tabular-nums; line-height: 1.15; }
.rp-sum-card .lbl { color: var(--muted); font-size: 12px; margin-top: 3px; }
.rp-sum-card.rp-tone-out .num { color: var(--red); }
.rp-sum-card.rp-tone-urgent .num { color: var(--orange-deep, #b25000); }
.rp-sum-hint { display: flex; flex-direction: column; justify-content: center; background: var(--surface-2, var(--card)); }
.rp-sum-hint .lbl { margin: 0 0 3px; }

.rp-group { margin-bottom: 14px; border: 1px solid var(--line); border-radius: var(--radius-card); background: var(--card); overflow: hidden; }
/* 2026-11-03 审计：≤1080 时行网格最小列合计 526px，而 overflow:hidden 会直接把
   「断货日 / 补货方式」两列裁掉（手机上完全看不到，也无法横滚）。
   窄屏改为单列堆叠，让核心行动信息不再被裁。 */
@media (max-width: 720px) {
  .rp-group { overflow: visible; }
  .rp-rows { overflow-x: auto; }
  .rp-row { grid-template-columns: 1fr !important; row-gap: 6px; }
  .rp-row > * { min-width: 0; }
}
.rp-group-head { display: flex; align-items: center; gap: 9px; width: 100%; padding: 11px 14px; background: none; border: 0; cursor: pointer; text-align: left; font: inherit; color: inherit; }
.rp-group-head:hover { background: var(--gray-soft, rgba(0,0,0,.025)); }
.rp-dot { width: 8px; height: 8px; border-radius: 50%; background: var(--muted); flex: none; }
.rp-tone-out .rp-dot { background: var(--red); }
.rp-tone-urgent .rp-dot { background: var(--orange); }
.rp-tone-warn .rp-dot { background: #d1a000; }
.rp-tone-ok .rp-dot { background: var(--green); }
.rp-group-title { font-weight: 600; font-size: 13.5px; }
.rp-count-qty { background: transparent; color: var(--muted); font-weight: 500; }
.rp-count { font-size: 11.5px; font-weight: 600; padding: 1px 7px; border-radius: 999px; background: var(--gray-soft, rgba(0,0,0,.06)); color: var(--text-2, var(--text)); font-variant-numeric: tabular-nums; }
.rp-hint { color: var(--muted); font-size: 11.5px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.rp-caret { margin-left: auto; color: var(--muted); display: inline-flex; transition: transform .18s var(--ease, ease); }
.rp-group.is-collapsed .rp-caret { transform: rotate(-90deg); }
.rp-group.is-collapsed .rp-rows { display: none; }
.rp-rows { border-top: 1px solid var(--line-soft, var(--line)); }

/* 一行一个 SKU：产品名 | 可售天数 | 缺口 | 断货日 | 方式 | 箭头 */
.rp-row {
  display: grid;
  grid-template-columns: minmax(220px, 1.6fr) 190px 108px 96px 150px 22px;
  gap: 14px;
  align-items: center;
  padding: 9px 14px;
  border-top: 1px solid var(--line-soft, var(--line));
  cursor: pointer;
  transition: background-color .14s ease;
}
.rp-row:first-child { border-top: 0; }
.rp-row:hover { background: var(--row-hover, rgba(0, 102, 204, .045)); }
.rp-row:focus-visible { outline: 2px solid var(--focus-ring, #185FA5); outline-offset: -2px; }
/* 左侧紧急度色条（比整行染色克制，扫一眼就能分出组） */
.rp-tone-out .rp-row { box-shadow: inset 3px 0 0 var(--red); }
.rp-tone-urgent .rp-row { box-shadow: inset 3px 0 0 var(--orange); }
.rp-tone-warn .rp-row { box-shadow: inset 3px 0 0 #e0b400; }
.rp-tone-muted .rp-row { box-shadow: inset 3px 0 0 var(--line-strong, #ccc); }

.rp-name { min-width: 0; }
.rp-runway-top { display: flex; align-items: baseline; gap: 4px; }
.rp-days { font-size: 19px; font-weight: 650; font-variant-numeric: tabular-nums; letter-spacing: -.02em; }
.rp-days.is-out { color: var(--red); }
.rp-unit { font-size: 11px; color: var(--muted); font-weight: 400; }
.rp-bar { display: block; height: 5px; border-radius: 999px; background: var(--gray-soft, rgba(0,0,0,.07)); overflow: hidden; margin: 5px 0 4px; }
.rp-bar > i { display: block; height: 100%; border-radius: 999px; background: var(--muted); transition: width .3s var(--ease, ease); }
.rp-bar-out > i { background: var(--red); }
.rp-bar-urgent > i { background: var(--orange); }
.rp-bar-warn > i { background: #e0b400; }
.rp-bar-ok > i { background: var(--green); }
.rp-bar-idle > i { background: var(--line-strong, #ccc); }
.rp-sub { font-size: 11px; color: var(--muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.rp-gap { text-align: right; }
.rp-qty { font-size: 21px; font-weight: 700; font-variant-numeric: tabular-nums; letter-spacing: -.02em; line-height: 1.1; }
.rp-gap .rp-sub { text-align: right; }
.rp-due { text-align: center; }
.rp-due-day { font-size: 13px; font-weight: 650; font-variant-numeric: tabular-nums; }
.rp-due-day.is-out { color: var(--red); }
.rp-modes { display: flex; flex-direction: column; gap: 3px; }
.rp-chip { display: inline-flex; align-items: center; gap: 5px; font-size: 11.5px; white-space: nowrap; }
.rp-chip b { font-variant-numeric: tabular-nums; }
.rp-chip.air b { color: var(--orange-deep, #b25000); }
.rp-chip.sea b { color: var(--green-deep, #0a7c32); }
.rp-go { color: var(--muted); text-align: right; font-size: 20px; line-height: 1; }
.rp-row:hover .rp-go { color: var(--accent); }

@media (max-width: 1080px) {
  /* 窄屏：折叠成两行（名称独占一行，数字并排） */
  .rp-row { grid-template-columns: minmax(160px, 1fr) 150px 90px 84px; grid-template-areas: "name name name name" "run gap due modes"; row-gap: 8px; }
  .rp-name { grid-area: name; }
  .rp-runway { grid-area: run; }
  .rp-gap { grid-area: gap; text-align: left; }
  .rp-gap .rp-sub { text-align: left; }
  .rp-due { grid-area: due; text-align: left; }
  .rp-modes { grid-area: modes; }
  .rp-go { display: none; }
}

/* ---------- 详情弹窗：订单规格分布（2026-10-28） ---------- */
/* 数据来自自动同步顺带累积（state.orderPcs），不再单独拉订单 */
.pcs-box { border: 1px solid var(--line); border-radius: var(--radius-card); background: var(--card); padding: 12px 14px; }
.pcs-head { font-size: 13px; font-weight: 600; margin-bottom: 8px; display: flex; gap: 8px; align-items: baseline; flex-wrap: wrap; }
.pcs-table { width: 100%; border-collapse: collapse; }
.pcs-table th, .pcs-table td { padding: 5px 8px; font-size: 12.5px; border-bottom: 1px solid var(--line-soft, var(--line)); }
.pcs-table th { color: var(--muted); font-weight: 500; text-align: left; }
.pcs-table .num { text-align: right; font-variant-numeric: tabular-nums; }
/* 主力规格轻底色，一眼找到主销装 */
.pcs-table tbody tr.is-main td { background: rgba(24, 95, 165, .07); font-weight: 600; }
.pcs-table tfoot td { font-weight: 600; border-bottom: 0; padding-top: 7px; }
.pcs-tag { font-size: 10px; font-weight: 600; color: var(--green-deep, #0a7c32); background: rgba(52, 199, 89, .16); padding: 1px 5px; border-radius: 999px; vertical-align: 1px; margin-left: 2px; }
.pcs-tip { margin-top: 8px; font-size: 12.5px; line-height: 1.55; color: var(--text-2, var(--text)); background: var(--gray-soft, rgba(0, 0, 0, .03)); padding: 7px 9px; border-radius: 8px; }

/* ---------- 详情弹窗 UI 打磨（2026-10-28 第二轮） ---------- */
/* 1) 指标卡不再被最高的那张拉齐：原来「断货预测」4 行文字会把同排的
      「主力补货 / 空运应急」撑成 200px 高的空盒子。 */
.detail-grid { align-items: start; }
/* 2) 断货预测已移到网格外（.detail-status 整行状态条），这里不再需要跨列 */
/* 3) 可动作的数字（主力补货 / 空运应急）用淡蓝底区分，一眼看出"这两个是要下单的量" */
.detail-item.is-action { background: rgba(0, 102, 204, .07); }
.detail-item.is-action .v { color: var(--accent-deep, #0b4f9e); }
/* 4) 有断货风险时，断货预测卡淡红底（仅提示，不喧宾夺主） */
.detail-item.is-warn { background: rgba(255, 59, 48, .06); }
.detail-item.detail-dates .v > div { white-space: normal; }
.nowrap { white-space: nowrap; }

/* 5) 建议区：由整段长文改为条目（>=3 句时） */
.advice-list { margin: 0; padding-left: 18px; }
.advice-list li { margin: 3px 0; }
.advice-list li::marker { opacity: .55; }
/* 2026-11-03：原来限宽 70ch，在 1300px 宽的卡片里像一条窄砖 —— 与 .card-sub 同批去掉 */

/* 6) 订单规格：占比数字 + 迷你占比条 */
.pcs-share { display: block; font-variant-numeric: tabular-nums; }
.pcs-mini { display: block; height: 4px; border-radius: 999px; background: var(--gray-soft, rgba(0, 0, 0, .07)); overflow: hidden; margin-top: 3px; }
.pcs-mini > i { display: block; height: 100%; border-radius: 999px; background: var(--accent, #185FA5); }
.pcs-table tr.is-main .pcs-mini > i { background: var(--green, #34c759); }
.pcs-table td:last-child, .pcs-table th:last-child { width: 96px; }

/* 详情弹窗顶部可编辑区（2026-10-28）：开关与输入同一行，说明独立小字 */
.det-edit { background: var(--primary-soft); border-color: rgba(0, 113, 227, .2); padding: 12px 14px; }
.det-edit-row { display: flex; gap: 14px; flex-wrap: wrap; align-items: flex-end; }
.det-edit-switch { margin-left: auto; display: flex; align-items: center; gap: 9px; padding: 5px 11px; border-radius: 10px; background: var(--card); border: 1px solid var(--line); }
.det-edit-hint { margin-top: 8px; font-size: 11px; line-height: 1.5; color: var(--muted); }
.det-sub { font-size: 11px; line-height: 1.3; color: var(--orange-deep, #b25000); margin-top: 3px; }

/* 断货预测：整行状态条（2026-10-28） */
.detail-status {
  display: flex; flex-wrap: wrap; align-items: baseline; gap: 8px 22px;
  padding: 10px 14px; margin: 2px 0 12px;
  border-radius: 14px; background: var(--gray-soft, rgba(0, 0, 0, .035));
}
.detail-status.is-warn { background: rgba(255, 59, 48, .06); }
.ds-item { display: inline-flex; align-items: baseline; gap: 6px; }
.ds-k { font-size: 12px; color: var(--muted); }
.ds-v { font-size: 13.5px; font-weight: 600; font-variant-numeric: tabular-nums; }
.ds-v.ds-bad { color: var(--red); }
.ds-v.ds-ok { color: var(--green, #1aa463); }
.ds-note { font-size: 11.5px; color: var(--muted); }

/* 暗色主题：新元素底色要提亮一点，否则 rgba 黑底在深色卡上等于没有 */
[data-theme="dark"] .detail-item.is-action { background: rgba(10, 132, 255, .15); }
[data-theme="dark"] .detail-item.is-action .v { color: #74b9ff; }
[data-theme="dark"] .detail-status.is-warn { background: rgba(255, 69, 58, .14); }
/* 深色主题下指标卡原本是 rgba(0,0,0,.03) → 与弹窗底色几乎同色，卡片边界消失 */
[data-theme="dark"] .detail-item { background: rgba(255, 255, 255, .055); }

/* ---------- 深度审计（2026-10-28 第二批）：无障碍 / 主题 / 窄屏 ---------- */
/* 深色主题：建议区 ok/info 原本沿用浅色文字色，在深色卡上对比度约 1.1:1（几乎看不清） */
[data-theme="dark"] .advice-box.ok { color: #8ce8a4; }
[data-theme="dark"] .advice-box.info { color: #9cc9ff; }
/* 开关（清仓处理）键盘聚焦时没有任何反馈 */
.switch input:focus-visible + .track { box-shadow: 0 0 0 3px var(--focus-ring, #185FA5); }
/* 指标卡里「1,234 个」的单位原来只有 td .unit 有样式，这里补上（否则 17px 粗体连写） */
.detail-item .unit { font-size: 11px; color: var(--muted); margin-left: 2px; font-weight: 400; }
/* 窄屏：订单规格表 5 列在 375px 下会溢出，允许横向滚动而不是把列压到看不见 */
@media (max-width: 640px) {
  .pcs-box { overflow-x: auto; -webkit-overflow-scrolling: touch; }
  .pcs-table { min-width: 360px; }
}

/* ============== 触屏与安全区（2026-11-03 审计） ============== */
/* 触控目标：WCAG 2.5.5 建议 ≥44px。桌面指针设备不受影响（只看 pointer:coarse）。 */
@media (pointer: coarse) {
  .btn, .btn-sm, .seg button, .site-pill, .modal-close, .badge-btn {
    min-height: 44px;
  }
  .btn-xs {
    min-height: 40px;
    padding: 8px 12px;
  }
  .modal-close {
    width: 44px;
    height: 44px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
  }
  .table-wrap td button, .table-wrap td .btn {
    min-height: 40px;
  }
  .link-cell {
    display: inline-block;
    min-height: 32px;
    line-height: 32px;
  }
  #toast-root {
    top: 56px;
  }
}

/* 刘海屏安全区（配合 viewport-fit=cover） */
.topbar {
  padding-left: max(10px, env(safe-area-inset-left));
  padding-right: max(10px, env(safe-area-inset-right));
}
.main {
  padding-bottom: max(24px, env(safe-area-inset-bottom));
}

/* ============================================================
   Design v2 层（2026-11-03）
   目的：把「同一件事有两套做法」收敛成一套，并补上质感细节。
   规则：本段只做**视觉**覆盖，不改任何布局结构与交互逻辑。
   顺序在文件末尾 → 同等特异性下优先生效。
   ============================================================ */

/* ---------- 1. 基础：光源、行高、字距 ---------- */
html,
body {
  letter-spacing: 0;
  line-height: 1.5;
  /* 极淡的顶部光源：纯平灰会让卡片像"贴在纸上" */
  background:
    radial-gradient(1100px 620px at 50% -22%, #ffffff 0%, rgba(255, 255, 255, 0) 58%),
    linear-gradient(180deg, #f7f7fa 0%, var(--bg) 42%);
  background-attachment: fixed;
}

html[data-theme="dark"] body {
  background:
    radial-gradient(900px 520px at 50% -16%, rgba(10, 132, 255, .055), transparent 62%),
    linear-gradient(180deg, #17171c 0%, var(--bg) 46%);
  background-attachment: fixed;
}

/* 深色下给卡片一点"顶部受光"，避免整块平面 */
[data-theme="dark"] .card,
[data-theme="dark"] .stat-card,
[data-theme="dark"] .site-card {
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .045), var(--shadow-sm);
}

/* ---------- 2. 排版阶梯（7 档，去掉半像素） ---------- */
.page-head h2 {
  font-size: 28px;
  font-weight: 700;
  letter-spacing: -.01em;
  line-height: 1.2;
}
.page-head .sub {
  font-size: 14px;
  line-height: 1.55;
  margin-top: 6px;
  /* 2026-11-03 回退 68ch 限宽：桌面卡片宽 1300+ 时，正文只有 ~570px，
     整块内容挤在左上角、右侧大片留白（用户截图反馈「内容都挤在一块了」）。
     中文段落不需要西文那种 70ch 行宽限制，这里交给 .main 的 1400 上限即可。 */
  color: var(--muted);
}
.card-title {
  font-size: 15px;
  font-weight: 600;
  letter-spacing: 0;
  line-height: 1.4;
  margin-bottom: 6px;
}
.card-sub {
  font-size: 13px;
  line-height: 1.6;
  /* 同上：72ch 在宽屏卡片里只有 ~560px，卡片越宽越像「窄栏」 */
}
/* 趋势页原来用了两个不存在的类名（.stat-value/.stat-label）→ 数字按正文 14px 渲染 */
.stat-value,
.rp-sum-card .num,
.stat-card .num {
  font-variant-numeric: tabular-nums;
  letter-spacing: -.01em;
}
.stat-value {
  font-size: 28px;
  font-weight: 600;
  line-height: 1.15;
  color: var(--text);
}
.stat-label {
  font-size: 12px;
  color: var(--muted);
  margin-bottom: 4px;
}
/* 表格/数字列统一等宽数位，小数点与千分位才对得齐 */
table,
.num,
td.num,
.pv-table td,
th {
  font-variant-numeric: tabular-nums;
}
th {
  letter-spacing: 0;
  font-weight: 600;
  color: var(--muted);
}

/* ---------- 3. 布局节奏：24 基线 ---------- */
.topbar {
  padding-left: max(24px, env(safe-area-inset-left));
  padding-right: max(24px, env(safe-area-inset-right));
}
.main {
  padding: 24px 24px 64px;
  max-width: 1400px;
  margin: 0;
}
.page-head {
  margin-bottom: 20px;
}
.card {
  padding: 20px 24px;
  margin-bottom: 24px;
  background: var(--card);
  border: 1px solid var(--hairline);
  border-radius: var(--radius-card);
  box-shadow: var(--shadow-sm);
  /* 上缘 1px 高光：让表面有"光从上面来"的一致方向（必须写在 background 简写之后） */
  background-image: linear-gradient(180deg, rgba(255, 255, 255, .7), rgba(255, 255, 255, 0) 72px);
}
[data-theme="dark"] .card {
  background-image: linear-gradient(180deg, rgba(255, 255, 255, .035), rgba(255, 255, 255, 0) 72px);
}
.stat-grid {
  grid-template-columns: repeat(5, minmax(0, 1fr));
  gap: 16px;
  margin-bottom: 24px;
}
.stat-card {
  padding: 16px 20px;
  border-radius: 14px;
}
.stat-card .num {
  font-size: 28px;
  font-weight: 600;
  line-height: 1.15;
}
/* 侧栏与顶栏严格接缝（原来 58 vs 52 会露出一条 6px 的内容缝） */
.sidebar {
  top: 52px;
  height: calc(100dvh - 52px);
}

/* ---------- 4. 侧栏选中态：浅色胶囊 + 蓝字 + 细竖条 ---------- */
.nav-item.active {
  background: var(--surface-nav-active);
  color: var(--accent-ink, var(--accent));
  box-shadow: var(--shadow-sm);
}
/* 选中竖条的几何在 §1626 统一定义（定高 + scaleY 动画），这里不再改 inset/height，
   只保留深色主题下的取色覆盖（见下方 [data-theme="dark"]）。 */
[data-theme="dark"] .nav-item.active {
  background: var(--surface-nav-active);
  color: #9ecbff;
  box-shadow: none;
}
.nav-item {
  border-radius: 10px;
  transition: background var(--t-2) var(--e-out), color var(--t-2) var(--e-out);
}
.nav-item:hover {
  background: var(--hover-overlay);
}

/* ---------- 5. 控件：3 档高度 + 4 档圆角 ---------- */
.btn {
  border-radius: var(--radius-btn);
  transition: background var(--t-2) var(--e-out), box-shadow var(--t-2) var(--e-out),
    transform var(--t-1) var(--e-out), border-color var(--t-2) var(--e-out);
}
.btn:hover {
  transform: none; /* 位移会让密集工具栏"抖"，改由亮度/边框表达 */
}
.btn:active {
  transform: scale(.97);
}
.btn:disabled:hover {
  transform: none;
  filter: none;
}
.btn-primary {
  background: var(--accent);
  color: #fff;
  box-shadow: 0 1px 2px rgba(0, 90, 200, .18);
}
.btn-primary:hover {
  background: var(--accent-ink, #0A63CC);
  color: #fff;
}
.field input,
.field select,
.field textarea,
.modal input,
.modal select,
.modal textarea,
input[type="text"],
input[type="number"],
input[type="search"],
select,
textarea {
  border-radius: var(--radius-input);
  transition: border-color var(--t-2) var(--e-out), box-shadow var(--t-2) var(--e-out),
    background var(--t-2) var(--e-out);
}
/* 焦点语言统一：一条外环，不再"实线 + 光晕"双环 */
.field input:focus,
.field select:focus,
.field textarea:focus,
.modal input:focus,
.modal select:focus,
.modal textarea:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-glow);
}
.badge,
.mini,
.tag-chip,
.market-badge,
.method-chip,
.stat-chip {
  border-radius: var(--radius-pill);
  letter-spacing: 0;
}
/* 代码里在用但 CSS 从未定义 → 之前渲染成裸文字 */
.b-warn {
  background: var(--amber-soft);
  color: var(--amber-deep);
}
.b-out {
  background: var(--red-soft);
  color: var(--red-deep);
}
.b-safe {
  background: var(--green-soft);
  color: var(--green-deep);
}
.b-urgent {
  background: var(--orange-soft);
  color: var(--orange-deep);
}
.b-reorder {
  background: var(--accent-soft);
  color: var(--accent-ink, var(--accent));
}

/* ---------- 6. 表格：方向性 hover + 发丝线 ---------- */
.table-wrap {
  border: 1px solid var(--hairline);
  border-radius: 12px;
  background: var(--card);
}
table,
th,
td {
  border-color: var(--hairline);
}
/* 原来的 tr:hover 与 td:hover 两条规则互相覆盖，实际只剩 3.5% 中性灰 → 扫行无感 */
tbody tr:hover td {
  background: linear-gradient(90deg, rgba(0, 122, 255, .07), rgba(0, 122, 255, .012));
}
tbody tr:hover td:first-child {
  box-shadow: inset 2px 0 0 var(--accent);
}
/* 组合行/子行的专属底色不该被 hover 抹平 */
tbody tr.merge-line:hover td {
  background: linear-gradient(90deg, rgba(0, 122, 255, .10), rgba(0, 122, 255, .03));
}
.link-cell {
  text-decoration-color: transparent;
  text-underline-offset: 3px;
  transition: color var(--t-2) var(--e-out), text-decoration-color var(--t-2) var(--e-out);
}
.link-cell:hover {
  color: var(--accent);
  text-decoration: underline;
  text-decoration-color: var(--accent);
}
.text-link {
  text-decoration-color: transparent;
  transition: text-decoration-color var(--t-2) var(--e-out);
}
.text-link:hover {
  text-decoration-color: currentColor;
}

/* ---------- 7. 动效：统一曲线 + 补上退场 ---------- */
@keyframes whc-card-in {
  from { opacity: 0; transform: translateY(6px) scale(.994); }
  to { opacity: 1; transform: none; }
}
@keyframes whc-rise-in {
  from { opacity: 0; transform: translateY(8px); }
  to { opacity: 1; transform: none; }
}
@keyframes whc-row-out {
  to { opacity: 0; transform: translateX(-8px); }
}
@keyframes whc-toast-out {
  to { opacity: 0; transform: translateY(-6px) scale(.98); }
}
@keyframes whc-mask-out {
  to { opacity: 0; }
}
@keyframes whc-spin {
  to { transform: rotate(360deg); }
}
@keyframes whc-shimmer {
  100% { transform: translateX(100%); }
}

/* 页面入场：卡片只淡入 6px（原来的 12px 位移在长页面上像"整页在动"） */
.view-enter .card,
.view-enter .stat-card {
  animation: whc-card-in var(--t-3) var(--e-out) both;
}
.view-enter .page-head {
  animation: whc-rise-in var(--t-3) var(--e-out) both;
}
/* 统计卡按顺序微错开：只给前 10 张，避免长列表尾部等待 */
.view-enter .stat-grid > *:nth-child(1) { animation-delay: 0ms; }
.view-enter .stat-grid > *:nth-child(2) { animation-delay: 18ms; }
.view-enter .stat-grid > *:nth-child(3) { animation-delay: 36ms; }
.view-enter .stat-grid > *:nth-child(4) { animation-delay: 54ms; }
.view-enter .stat-grid > *:nth-child(5) { animation-delay: 72ms; }
.view-enter .stat-grid > *:nth-child(6) { animation-delay: 90ms; }
.view-enter .stat-grid > *:nth-child(7) { animation-delay: 108ms; }
.view-enter .stat-grid > *:nth-child(8) { animation-delay: 126ms; }
.view-enter .stat-grid > *:nth-child(9) { animation-delay: 144ms; }
.view-enter .stat-grid > *:nth-child(10) { animation-delay: 162ms; }

/* 统计卡：悬停只动边框与阴影（苹果的卡片是"静态表面"），按下回弹 */
.stat-card {
  transition: transform var(--t-2) var(--e-out), box-shadow var(--t-2) var(--e-out),
    border-color var(--t-2) var(--e-out), background var(--t-2) var(--e-out);
}
.stat-card.clickable:hover {
  border-color: var(--line-strong);
  box-shadow: var(--shadow-md);
}
.stat-card.clickable:active {
  transform: scale(.985);
  transition-duration: var(--t-1);
}
.stat-card.active {
  transform: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-soft), var(--shadow-sm);
}
/* 数字只在换页时弹一次；筛选重建不再重播（原来每敲一个字都弹 10 张卡） */
.stat-card .num {
  /* 换页时由下面的 .view-enter 重播；筛选重建不再弹 */
  animation: num-pop 0s var(--e-out) both;
}
.view-enter .stat-card .num {
  animation: whc-num-pop var(--t-4) var(--e-spring) both;
}
@keyframes whc-num-pop {
  from { opacity: .4; transform: scale(.96); }
  to { opacity: 1; transform: none; }
}

/* 弹窗：入场 280ms（去超调），退场 200ms 加速 */
.modal-mask {
  background: rgba(0, 0, 0, .3);
  backdrop-filter: blur(10px) saturate(1.2);
  -webkit-backdrop-filter: blur(10px) saturate(1.2);
}
[data-theme="dark"] .modal-mask {
  background: rgba(0, 0, 0, .5);
}
.modal {
  background: var(--surface-sheet);
  border: 1px solid var(--hairline);
  box-shadow: var(--shadow-lg);
  animation: whc-sheet-in var(--t-3) var(--e-out) both;
}
@keyframes whc-sheet-in {
  from { opacity: 0; transform: scale(.965) translateY(8px); }
  to { opacity: 1; transform: none; }
}
.modal-mask.closing {
  animation: whc-mask-out .2s var(--e-in) forwards;
}
.modal-mask.closing .modal {
  animation: whc-sheet-out .2s var(--e-in) forwards;
}
@keyframes whc-sheet-out {
  to { opacity: 0; transform: scale(.98) translateY(4px); }
}
/* 一句话确认不该被拉成 760px 扁条 */
.modal.modal-sm {
  max-width: 440px;
}
.modal.modal-sm .modal-head {
  padding: 18px 20px;
}
.modal.modal-sm .modal-body {
  padding: 4px 20px 16px;
}
.modal.modal-sm .modal-foot {
  padding: 14px 20px;
}
.modal-head,
.modal-foot {
  flex: 0 0 auto;
}
.modal-body {
  flex: 1 1 auto;
  min-height: 0;
}
.modal-close {
  background: transparent;
  width: 30px;
  height: 30px;
  border-radius: 50%;
  transition: background var(--t-2) var(--e-out), color var(--t-2) var(--e-out);
}
.modal-close:hover {
  background: var(--fill-secondary);
  transform: none;
  color: var(--text);
}

/* toast：状态只体现在圆点，不再整块染高饱和色 */
.toast {
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(28, 28, 32, .9);
  backdrop-filter: saturate(1.6) blur(16px);
  -webkit-backdrop-filter: saturate(1.6) blur(16px);
  border: 1px solid rgba(255, 255, 255, .08);
  color: #fff;
  gap: 8px;
  padding: 10px 16px 10px 14px;
  font-weight: 500;
  box-shadow: 0 10px 30px -10px rgba(0, 0, 0, .5);
}
.toast::before {
  content: "";
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: rgba(255, 255, 255, .55);
  flex: none;
}
.toast.success::before { background: #4CC46A; }
.toast.error::before { background: #FF6B5E; }
.toast.warn::before { background: #E9A23B; }
.toast.success,
.toast.error,
.toast.warn {
  background: rgba(28, 28, 32, .9);
}
.toast.out {
  animation: whc-toast-out .18s var(--e-in) forwards;
}

/* 骨架：原来 keyframes 直接平移整块背景，看起来是"灰块在动" */
.skeleton {
  position: relative;
  overflow: hidden;
  background: var(--fill-tertiary);
  border-radius: 8px;
  color: transparent;
}
.skeleton::after {
  content: "";
  position: absolute;
  inset: 0;
  transform: translateX(-100%);
  background: linear-gradient(100deg, transparent 28%, rgba(255, 255, 255, .55) 50%, transparent 72%);
  animation: whc-shimmer 1.4s var(--e-out) infinite;
}
[data-theme="dark"] .skeleton::after {
  background: linear-gradient(100deg, transparent 28%, rgba(255, 255, 255, .09) 50%, transparent 72%);
}

/* 按钮 loading：加 spinner，并锁宽度避免每秒跳一次 */
.btn.is-loading {
  opacity: 1;
  cursor: progress;
  min-width: 132px;
  font-variant-numeric: tabular-nums;
}
.btn.is-loading::before {
  content: "";
  width: 13px;
  height: 13px;
  border-radius: 50%;
  border: 2px solid currentColor;
  border-top-color: transparent;
  animation: whc-spin .7s linear infinite;
  display: inline-block;
  vertical-align: -2px;
  margin-right: 6px;
}

/* 折叠面板：展开时给一段上浮淡入（收起仍是 display:none，避免高度动画不可控） */
@keyframes whc-rp-open {
  from { opacity: 0; transform: translateY(-4px); }
  to { opacity: 1; transform: none; }
}
.rp-group:not(.is-collapsed) .rp-rows {
  animation: whc-rp-open var(--t-2) var(--e-out) both;
}

/* ---------- 8. 图表：深色网格 / 统一 tooltip ---------- */
.tl-grid,
.rk-grid {
  stroke: var(--line-soft);
}
.tl-today-line {
  stroke: var(--text-2);
  stroke-opacity: .5;
  stroke-dasharray: 5 3;
}
.tl-hover-line {
  stroke: var(--text-2);
  stroke-opacity: .38;
  stroke-dasharray: 3 3;
}
.tl-value-label {
  stroke: var(--card-solid);
  stroke-width: 2.5;
}
.tl-arrival-dot {
  stroke: var(--card-solid);
  stroke-width: 1.5;
}
.tl-line {
  stroke-width: 2;
  stroke-linejoin: round;
  stroke-linecap: round;
}
.tl-area {
  fill: rgba(0, 122, 255, .10);
}
[data-theme="dark"] .tl-area {
  fill: rgba(10, 132, 255, .14);
}
.chart-tip,
.sc-tip {
  background: rgba(28, 32, 40, .94);
  border-radius: 10px;
  padding: 8px 11px;
  font-size: 12px;
  line-height: 1.55;
  box-shadow: 0 8px 24px rgba(0, 0, 0, .22);
  border: 1px solid rgba(255, 255, 255, .07);
}
.chart-tip::after,
.sc-tip::after {
  border-bottom-color: rgba(28, 32, 40, .94);
}
.rk-pop {
  border-radius: 12px;
  box-shadow: var(--shadow-lg);
  border: 1px solid var(--hairline);
}
.tl-legend,
.line-chart-legend,
.sc-legend {
  font-size: 11.5px;
  color: var(--muted);
}
/* uPlot 默认 14px 居中图例，与全站字号断层 */
.u-legend {
  font-size: 11.5px;
  text-align: left;
  color: var(--muted);
}
.u-legend .u-marker {
  width: 14px;
  height: 3px;
  border-radius: 2px;
}

/* ---------- 9. 空状态：一套骨架 ---------- */
.empty-state {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
  padding: 40px 20px;
  text-align: center;
  color: var(--muted);
}
.es-ico {
  width: 48px;
  height: 48px;
  border-radius: 50%;
  display: grid;
  place-items: center;
  background: var(--gray-soft);
  color: var(--muted);
  margin-bottom: 2px;
}
.es-title {
  font-size: 14px;
  font-weight: 600;
  color: var(--text);
}
.es-sub {
  font-size: 12.5px;
  color: var(--muted);
  line-height: 1.7;
  max-width: 42ch;
}
.es-actions {
  margin-top: 8px;
  display: flex;
  gap: 8px;
  flex-wrap: wrap;
  justify-content: center;
}

/* ---------- 10. 菜单/浮层质感 ---------- */
[data-theme="dark"] .modal-close {
  background: transparent;
}
[data-theme="dark"] .modal-close:hover {
  background: rgba(255, 255, 255, .1);
}
/* 顶栏滚动后的实色底：这个变量以前从未定义，深色下会闪成近白 */
.topbar.scrolled {
  background: var(--surface-topbar-solid, var(--glass-topbar));
}

/* ---------- 11. 窄屏视觉 ---------- */
@media (max-width: 1023px) {
  .stat-grid {
    grid-template-columns: repeat(4, minmax(0, 1fr));
    gap: 12px;
  }
  .main {
    padding: 18px 16px 56px;
  }
  .card {
    padding: 16px 16px;
    margin-bottom: 16px;
  }
  .page-head h2 {
    font-size: 24px;
  }
}
@media (max-width: 720px) {
  /* 备货行改成真正的单列：1080 段的 grid-template-areas 会覆盖 1fr，必须一并重置 */
  .rp-row {
    grid-template-columns: 1fr !important;
    grid-template-areas: "name" "run" "gap" "due" "modes" !important;
    row-gap: 6px;
  }
  .rp-go {
    display: none;
  }
}
@media (max-width: 640px) {
  .stat-grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 10px;
  }
  .stat-card {
    padding: 12px 14px;
  }
  .stat-card .num {
    font-size: 24px;
  }
  .brand-name {
    display: none;
  }
  .page-head h2 {
    font-size: 22px;
  }
  /* 手机弹窗：贴底抽屉，而不是"缩小版桌面弹窗" */
  .modal-mask {
    align-items: flex-end;
    padding: 0;
  }
  .modal {
    max-width: 100%;
    margin: 0;
    border-radius: 20px 20px 0 0;
    max-height: 92dvh;
  }
  .modal-foot {
    padding-bottom: max(16px, calc(env(safe-area-inset-bottom) + 12px));
  }
}

/* ---------- 12. 动效偏好：delay 也要压掉 ---------- */
@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: .01ms !important;
    animation-delay: 0ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .01ms !important;
    transition-delay: 0ms !important;
    scroll-behavior: auto !important;
  }
  .toast {
    will-change: auto;
  }
  .skeleton::after {
    display: none;
  }
}

/* ---------- 13. 精修（首轮截图后） ---------- */
/* 侧栏接缝只在桌面生效：≤900 时它是横排 chip，高度必须 auto（否则会被拉成一屏高的巨卡） */
@media (min-width: 901px) {
  .sidebar {
    top: 52px;
    height: calc(100dvh - 52px);
  }
}
@media (max-width: 900px) {
  .sidebar {
    height: auto;
    align-content: flex-start;
  }
  .nav-item {
    min-height: 40px;
  }
}

/* 深色选中态再收一档：原来接近实心蓝，在暗色侧栏里比页面标题还亮 */
[data-theme="dark"] .nav-item.active {
  background: rgba(10, 132, 255, .16);
  color: #9ecbff;
}

/* 统计卡右上角的装饰光斑：原尺寸 78px 且不透明，像一块脏印 */
.stat-card::after {
  width: 64px;
  height: 64px;
  right: -18px;
  top: -18px;
  opacity: .55;
  filter: blur(1px);
}
[data-theme="dark"] .stat-card::after {
  opacity: .3;
}

/* 详情弹窗里的指标块不可点，就不该有 hover 抬升（假可点） */
.detail-item {
  transition: background var(--t-2) var(--e-out), border-color var(--t-2) var(--e-out);
  border: 1px solid transparent;
}
.detail-item:hover {
  transform: none;
  background: var(--surface-2);
  border-color: var(--hairline);
}

/* uPlot 自带图例是 14px 居中 + "--" 占位，与全站图表语言不符；
   卡片副标题已用文字说明了实线/虚线含义 */
.u-legend {
  display: none !important;
}

/* 表头：给一条极淡的底，长表滚动时与数据区分离 */
thead th {
  background: var(--surface-2);
}

/* 手机顶栏：用户徽章会挤掉退出按钮，窄屏直接收起来（用户名在「系统设置」里可见） */
@media (max-width: 640px) {
  .topbar {
    padding-left: max(12px, env(safe-area-inset-left));
    padding-right: max(12px, env(safe-area-inset-right));
    gap: 4px;
  }
  #user-chip {
    display: none;
  }
  .topbar .btn {
    padding: 8px 12px;
  }
  .brand {
    gap: 6px;
  }
}

/* ---------- 14. 窄屏收尾 ---------- */
@media (max-width: 900px) {
  /* 站点筛选 pill 在手机上会横向溢出、右侧被裁 */
  .site-strip {
    flex-wrap: wrap;
    gap: 8px;
    overflow: visible;
  }
}

/* ---------- 15. 密度与控件收尾 ---------- */
/* 看板行高：40px 缩略图 + 双行名称把行撑到 90px，一屏只剩 8 行；压内距而不是压图 */
.table-wrap th,
.table-wrap td {
  padding: 9px 12px;
}
.name-cell .sub,
.name-cell .sku-cell {
  line-height: 1.35;
}
/* 顶栏搜索框原来是 999 胶囊，与其它输入框的 10px 圆角不是一套 */
.global-search {
  border-radius: var(--radius-input);
}
/* 页头右侧动作按钮统一 32px 高，避免"文字按钮"和实心按钮高度不齐 */
.page-head .actions .btn,
.page-head .actions .btn-sm {
  min-height: 32px;
  padding: 6px 12px;
  font-size: 13px;
}

/* ---------- 16. 修正：.main 是布局容器，也被名称单元格复用 ---------- */
/* 详情里 <div class="main"> 是商品名，套上布局容器的 padding 会把每行撑到 145px。
   布局内距只作用于 .layout 的直接子元素。 */
.layout > .main {
  padding: 24px 24px 64px;
  max-width: 1400px;
  margin: 0;
}
.name-cell .main,
.modal .main,
.nc-txt .main {
  padding: 0;
  max-width: none;
  margin: 0;
}

/* ---------- 17. 最后一层细节 ---------- */
/* 趋势 KPI 的单位（"0件"里的"件"）不该和数字同号 */
.stat-value .unit {
  font-size: 13px;
  font-weight: 500;
  color: var(--muted);
  letter-spacing: 0;
  margin-left: 3px;
}
/* 告警块：整块粉底太重，改成"淡底 + 左侧色条" */
.advice-box {
  border-radius: 12px;
  padding: 12px 14px;
  border-left: 3px solid transparent;
}
.advice-box.danger {
  border-left-color: var(--red);
}
.advice-box.warn {
  border-left-color: var(--orange);
}
.advice-box.info {
  border-left-color: var(--accent);
}
/* 详情里的指标块：灰块改成"卡片内嵌表面"（有发丝线，不再是脏灰） */
.detail-item {
  background: var(--surface-2);
  border: 1px solid var(--hairline);
  border-radius: 12px;
  padding: 12px 14px;
}
.detail-item:hover {
  background: var(--surface-2);
  border-color: var(--line-strong);
}

/* ---------- 16. 状态图标语义色（2026-11-03：界面不再用 emoji） ---------- */
.st-ok { color: var(--green-deep, #1a7f45); }
.st-bad { color: var(--red-deep, #b42318); }
.st-warn { color: var(--orange-deep, #b25e00); }
.st-info { color: var(--accent-ink, #0a63cc); }
.ic + .muted { margin-left: 4px; }

/* ---------- 17. 操作记录：头像 + 操作胶囊 + 详情排版 ---------- */
.aud-time {
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
  color: var(--text-2);
  font-size: 12px;
  letter-spacing: -.01em;
}
.aud-user {
  display: flex;
  align-items: center;
  gap: 8px;
  white-space: nowrap;
}
.aud-avatar {
  width: 24px;
  height: 24px;
  border-radius: 50%;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: 0 0 auto;
  font-size: 11px;
  font-weight: 700;
  color: #fff;
  letter-spacing: 0;
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, .18);
}
.aud-avatar.t1 { background: linear-gradient(135deg, #4b9bff, #0a63cc); }
.aud-avatar.t2 { background: linear-gradient(135deg, #34c07b, #17855a); }
.aud-avatar.t3 { background: linear-gradient(135deg, #a07bff, #6b46d6); }
.aud-avatar.t4 { background: linear-gradient(135deg, #ff9d4d, #d9720a); }
.aud-avatar.sys {
  background: var(--fill-2, rgba(120, 120, 128, .12));
  color: var(--text-2);
  box-shadow: none;
}
.aud-name { font-weight: 600; color: var(--text); }
.aud-act {
  display: inline-flex;
  align-items: center;
  padding: 2px 9px;
  border-radius: 999px;
  font-size: 11.5px;
  font-weight: 600;
  white-space: nowrap;
  background: var(--fill-2, rgba(120, 120, 128, .12));
  color: var(--text-2);
}
.aud-act.info { background: rgba(10, 99, 204, .09); color: var(--accent-ink, #0a63cc); }
.aud-act.bad { background: rgba(180, 35, 24, .08); color: var(--red-deep, #b42318); }
.aud-detail { color: var(--muted); font-size: 12px; line-height: 1.65; max-width: 560px; }
.aud-row td { transition: background-color 160ms var(--e-out, ease); }
.aud-row:hover td { background: rgba(10, 99, 204, .045); }
[data-theme="dark"] .aud-row:hover td { background: rgba(10, 132, 255, .1); }

/* ---------- 18. 自动同步记录：状态胶囊 + 步骤行 ---------- */
.asv-time {
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
  color: var(--text-2);
  font-size: 12px;
}
.asv-res {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 2px 9px;
  border-radius: 999px;
  font-size: 11.5px;
  font-weight: 600;
  white-space: nowrap;
}
.asv-res .ic { vertical-align: -2px; }
.asv-res.ok { background: rgba(26, 127, 69, .1); color: var(--green-deep, #1a7f45); }
.asv-res.part { background: rgba(180, 35, 24, .08); color: var(--red-deep, #b42318); }
.asv-res.abort { background: rgba(178, 94, 0, .1); color: var(--orange-deep, #b25e00); }
.asv-steps { display: flex; flex-direction: column; }
.asv-step {
  display: flex;
  align-items: baseline;
  gap: 6px;
  padding: 3px 0;
  font-size: 12px;
  line-height: 1.55;
}
.asv-step + .asv-step { border-top: 1px dashed var(--hairline, rgba(0, 0, 0, .07)); }
.asv-step .ic { vertical-align: -2px; }
.asv-step b { flex: 0 0 auto; font-weight: 600; color: var(--text); }
.asv-step .muted { min-width: 0; }
.asv-step.bad b { color: var(--red-deep, #b42318); }
[data-theme="dark"] .aud-avatar.sys { background: rgba(255, 255, 255, .14); color: #9ecbff; }
[data-theme="dark"] .aud-act { background: rgba(255, 255, 255, .08); color: #c9c9d0; }
[data-theme="dark"] .aud-act.info { background: rgba(10, 132, 255, .18); color: #9ecbff; }
[data-theme="dark"] .aud-act.bad { background: rgba(255, 69, 58, .16); color: #ff9a94; }
[data-theme="dark"] .asv-res.ok { background: rgba(48, 209, 88, .14); color: #7ee2a0; }
[data-theme="dark"] .asv-res.part { background: rgba(255, 69, 58, .16); color: #ff9a94; }
[data-theme="dark"] .asv-res.abort { background: rgba(255, 159, 10, .16); color: #ffc46b; }

/* ---------- 19. 趋势页：自定义时间范围 + 曲线悬停气泡 ---------- */
#trend-chart { position: relative; }
.trend-range {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
  margin: 0 0 12px;
  padding: 9px 12px;
  background: var(--surface-input, rgba(120, 120, 128, .06));
  border: 1px solid var(--line);
  border-radius: 10px;
}
.trend-range[hidden] { display: none; }
.trend-range label {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 12px;
  color: var(--muted);
}
.trend-range input[type="date"] {
  height: 28px;
  min-width: 136px;
  padding: 0 8px;
  font-size: 12px;
  color: var(--text);
  background: var(--card-solid, #fff);
  border: 1px solid var(--line-strong);
  border-radius: 7px;
}
.trend-tip {
  position: absolute;
  left: 0;
  top: 0;
  z-index: 3;
  pointer-events: none;
  display: flex;
  align-items: baseline;
  gap: 8px;
  padding: 5px 9px;
  border-radius: 999px;
  background: var(--card-solid, #fff);
  border: 1px solid var(--line);
  box-shadow: var(--shadow-sm);
  font-size: 11.5px;
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
}
.trend-tip[hidden] { display: none; }
.trend-tip b { font-weight: 600; color: var(--text-2); }
.trend-tip .q { font-weight: 700; color: var(--accent-ink, #0A63CC); }
.trend-tip .m { color: var(--muted); }
[data-theme="dark"] .trend-tip { background: #1E1E24; border-color: rgba(255, 255, 255, .14); }
[data-theme="dark"] .trend-tip .q { color: #9ECBFF; }

/* ---------- 20. 自定义日期选择器（替代原生方块日历） ---------- */
/* 原生日历弹层是浏览器画的，改不了圆角；这里把原生图标隐藏，统一走 .dp 面板 */
input[type="date"]::-webkit-calendar-picker-indicator {
  opacity: 0;
  width: 0;
  height: 0;
  margin: 0;
  padding: 0;
}
.dp {
  position: fixed;
  z-index: 2600; /* 高于弹窗栈（ui.js: 1000 + 10×深度），低于 toast(3000) */
  width: 268px;
  padding: 10px 10px 8px;
  background: var(--card-solid, #fff);
  border: 1px solid var(--line);
  border-radius: 14px;
  box-shadow: 0 18px 48px rgba(0, 0, 0, .16), 0 2px 8px rgba(0, 0, 0, .06);
  animation: dp-in 160ms var(--e-out, cubic-bezier(.22, 1, .36, 1)) both;
  -webkit-backdrop-filter: none;
  backdrop-filter: none;
}
.dp[hidden] { display: none; }
@keyframes dp-in {
  from { opacity: 0; transform: translateY(-4px) scale(.98); }
  to { opacity: 1; transform: none; }
}
.dp-head {
  display: flex;
  align-items: center;
  gap: 2px;
  margin-bottom: 4px;
}
.dp-title {
  flex: 1;
  text-align: center;
  font-size: 13px;
  font-weight: 600;
  color: var(--text);
  font-variant-numeric: tabular-nums;
  letter-spacing: .01em;
}
.dp-nav {
  width: 26px;
  height: 26px;
  padding: 0;
  border: 0;
  border-radius: 8px;
  background: transparent;
  color: var(--text-2);
  font-size: 15px;
  line-height: 1;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  transition: background 140ms var(--e-out, ease), color 140ms var(--e-out, ease);
}
.dp-nav:hover { background: var(--hover-overlay, rgba(0, 0, 0, .06)); color: var(--text); }
.dp-nav:active { transform: scale(.94); }
.dp-wd {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
}
.dp-wd span {
  text-align: center;
  font-size: 10.5px;
  color: var(--muted);
  padding: 4px 0 6px;
}
.dp-grid {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  gap: 2px;
}
.dp-day {
  height: 30px;
  padding: 0;
  border: 0;
  border-radius: 8px;
  background: transparent;
  color: var(--text-2);
  font-size: 12px;
  font-variant-numeric: tabular-nums;
  cursor: pointer;
  transition: background 120ms var(--e-out, ease), color 120ms var(--e-out, ease);
}
.dp-day:hover { background: var(--hover-overlay, rgba(0, 0, 0, .06)); color: var(--text); }
.dp-day.other { color: var(--muted); opacity: .5; }
.dp-day.today { box-shadow: inset 0 0 0 1px var(--accent); color: var(--accent-ink, #0A63CC); font-weight: 600; }
.dp-day.sel {
  background: var(--accent);
  color: #fff;
  font-weight: 600;
  box-shadow: 0 2px 6px var(--accent-glow, rgba(0, 122, 255, .3));
}
.dp-day.sel:hover { background: var(--accent); color: #fff; }
.dp-day.dis { opacity: .26; cursor: default; }
.dp-day.dis:hover { background: transparent; color: var(--text-2); }
.dp-foot {
  display: flex;
  justify-content: space-between;
  margin-top: 6px;
  padding-top: 6px;
  border-top: 1px solid var(--line-soft, var(--line));
}
.dp-link {
  border: 0;
  background: transparent;
  color: var(--accent-ink, #0A63CC);
  font-size: 12px;
  padding: 4px 6px;
  border-radius: 6px;
  cursor: pointer;
}
.dp-link:hover { background: var(--accent-soft, rgba(0, 122, 255, .09)); }
[data-theme="dark"] .dp {
  background: #1E1E24;
  border-color: rgba(255, 255, 255, .12);
  box-shadow: 0 18px 48px rgba(0, 0, 0, .55);
}
[data-theme="dark"] .dp-day.today { color: #9ECBFF; }

/* 跨月的“今天”不画环：10 月视图里给 11/4 画圈会让人误以为选错月份 */
.dp-day.other.today { box-shadow: none; color: var(--muted); font-weight: 400; }

/* ---------- 21. 原生控件统一（2026-11-04） ---------- */
/* 深色主题下让原生下拉列表 / 文件对话框也走深色，否则白底很跳 */
:root { color-scheme: light; }
[data-theme="dark"] { color-scheme: dark; }

/* 数字框：去掉上下箭头（45 处内联编辑框，常驻箭头很扎眼）；键盘 ↑↓ 仍可用 */
input[type="number"] { -moz-appearance: textfield; appearance: textfield; }
input[type="number"]::-webkit-outer-spin-button,
input[type="number"]::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }

/* 下拉：触发框统一自绘箭头（原生下拉弹层由系统绘制，改不了，但触发器必须和输入框一致） */
select:not([multiple]) {
  appearance: none;
  -webkit-appearance: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8'%3E%3Cpath d='M1 1l5 5 5-5' stroke='%2386868b' stroke-width='1.8' fill='none' stroke-linecap='round'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 12px center;
  padding-right: 32px;
}
[data-theme="dark"] select:not([multiple]) {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8'%3E%3Cpath d='M1 1l5 5 5-5' stroke='%239A9AA0' stroke-width='1.8' fill='none' stroke-linecap='round'/%3E%3C/svg%3E");
}

/* 搜索框：原生 × 换成细线图标，并给文字留出空间 */
input[type="search"]::-webkit-search-cancel-button {
  -webkit-appearance: none;
  width: 14px;
  height: 14px;
  background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12'%3E%3Cpath d='M2 2l8 8M10 2l-8 8' stroke='%2386868b' stroke-width='1.6' stroke-linecap='round'/%3E%3C/svg%3E") center / 12px no-repeat;
  opacity: .4;
  cursor: pointer;
}
input[type="search"]::-webkit-search-cancel-button:hover { opacity: .75; }
input[type="search"] { padding-right: 32px; }
.toolbar input[type="search"], .global-search { padding-right: 32px; }

/* 文件框：原生灰按钮换成与 .btn-ghost 一致的描边按钮 */
input[type="file"] { font-size: 12.5px; color: var(--muted); max-width: 100%; }
input[type="file"]::file-selector-button {
  margin-right: 10px;
  padding: 6px 12px;
  border-radius: 8px;
  border: 1px solid var(--line-strong);
  background: var(--surface-input);
  color: var(--text-2);
  font: inherit;
  font-size: 12.5px;
  font-weight: 500;
  cursor: pointer;
  transition: background 140ms var(--e-out, ease), border-color 140ms var(--e-out, ease), color 140ms var(--e-out, ease);
}
input[type="file"]::file-selector-button:hover { background: var(--card-solid); color: var(--text); }

/* 复选框 / 单选：跟随主题色（原生蓝在深色下尤其跳） */
input[type="checkbox"], input[type="radio"] { accent-color: var(--accent); }

/* 折叠面板：去掉原生三角，换成站内折角箭头 */
details > summary { list-style: none; position: relative; padding-left: 16px; }
details > summary::-webkit-details-marker { display: none; }
details > summary::before {
  content: "";
  position: absolute;
  left: 1px;
  top: .5em;
  width: 6px;
  height: 6px;
  border-right: 1.6px solid currentColor;
  border-bottom: 1.6px solid currentColor;
  transform: rotate(-45deg);
  opacity: .55;
  transition: transform 160ms var(--e-out, ease);
}
details[open] > summary::before { transform: rotate(45deg); }

/* ---------- 22. 头程台账 ---------- */
.fr-paste {
  width: 100%;
  min-height: 118px;
  font-family: ui-monospace, "SF Mono", Consolas, monospace;
  font-size: 12px;
  line-height: 1.55;
  white-space: pre;
  overflow: auto;
  resize: vertical;
  tab-size: 12;
}
.fr-preview-table { font-size: 11.5px; }
.fr-preview-table th, .fr-preview-table td { padding: 5px 8px; }
.fr-err {
  margin-top: 8px;
  padding: 8px 10px;
  border-radius: 8px;
  background: rgba(178, 94, 0, .08);
  color: var(--orange-deep, #b25e00);
  font-size: 11.5px;
  line-height: 1.7;
}
.fr-table td { vertical-align: top; }
.fr-table tbody tr:hover td { background: rgba(10, 99, 204, .04); }
.fr-no-main {
  font-family: ui-monospace, "SF Mono", Consolas, monospace;
  font-size: 11.5px;
  font-weight: 600;
  letter-spacing: -.01em;
}
.fr-date { font-variant-numeric: tabular-nums; color: var(--text-2); white-space: nowrap; }
.diff-over { color: var(--red-deep, #b42318); font-weight: 600; }
.diff-save { color: var(--green-deep, #1a7f45); font-weight: 600; }
.fr-acts { white-space: nowrap; }
.fr-acts .btn { padding: 2px 7px; }
[data-theme="dark"] .fr-err { background: rgba(255, 159, 10, .12); color: #FFC46B; }
[data-theme="dark"] .fr-table tbody tr:hover td { background: rgba(10, 132, 255, .08); }

/* ---------- 23. 运单轨迹弹窗 ---------- */
.trk-meta { display: flex; align-items: baseline; gap: 8px; margin-bottom: 10px; flex-wrap: wrap; }
.trk-meta b { font-family: ui-monospace, "SF Mono", Consolas, monospace; font-size: 13px; letter-spacing: -.01em; }
.trk-body { min-height: 64px; }
.trk-sum { display: flex; align-items: center; gap: 10px; margin-bottom: 10px; flex-wrap: wrap; }
.trk-list {
  list-style: none;
  margin: 0;
  padding: 0 0 0 16px;
  max-height: 46vh;
  overflow: auto;
  border-left: 2px solid var(--line);
}
.trk-ev { position: relative; padding: 6px 0 8px 10px; }
.trk-ev::before {
  content: "";
  position: absolute;
  left: -21px;
  top: 12px;
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--line-strong);
}
.trk-ev:first-child::before { background: var(--accent); box-shadow: 0 0 0 3px var(--accent-soft); }
.trk-time { display: block; font-size: 11px; color: var(--muted); font-variant-numeric: tabular-nums; }
.trk-desc { display: block; font-size: 12.5px; line-height: 1.55; color: var(--text); }
.trk-loc { display: block; font-style: normal; font-size: 11.5px; color: var(--muted); margin-top: 2px; }

/* 未配置 API 时的免费查询引导块 */
.trk-free {
  padding: 12px 14px;
  border: 1px solid var(--line);
  border-radius: 10px;
  background: var(--surface-input, rgba(120, 120, 128, .06));
}
