/* =========================================================
   东昌汽车 · 企微 H5  设计系统
   风格：苹果 · 扁平 · 留白 · 柔和阴影 · 圆角
   ========================================================= */

:root {
  /* ── 主色板（系统蓝，更接近苹果 SF Pro 调性）── */
  --brand: #0071e3;
  --brand-600: #0058b0;
  --brand-300: #5fa1ed;
  --brand-200: #93bff5;
  --brand-100: #d8e8fb;
  --brand-50:  #eff5fd;

  /* ── 中性色（参照苹果 SF 文字灰阶）── */
  --ink-1: #1d1d1f;   /* 主文字 */
  --ink-2: #51525a;   /* 次级文字/标签 */
  --ink-3: #86868b;   /* 辅助文字/placeholder */
  --ink-4: #c7c7cc;   /* 描边/分割 */

  /* ── 表面色 ── */
  --bg:        #f5f5f7;   /* 苹果系统灰：页面底色 */
  --bg-elev:   #ffffff;   /* 卡片/弹窗 */
  --surface:   #ffffff;
  /* v114.6.9.20 补：这两个 token 一直被引用但从没定义（--surface-2 用了 8 处、--card 1 处），
     CSS 不报错只是整条声明失效 → 进度条底槽/表头背景/悬浮态全透明。同类坑见 --bad / --brand-1。 */
  --surface-2: #f2f2f5;   /* 次级表面：进度条底槽 / 表头底 / 悬浮态 */
  --card:      #ffffff;   /* 卡片底（= --surface） */
  --border:    #e5e5ea;   /* 默认描边 */
  --border-2:  #f2f2f5;   /* 浅分割线 */
  --hover:     #f5f5f7;   /* 悬浮态背景 */

  /* ── 功能色 ── */
  --green:    #10b981; --green-bg:    #e8f9f3;
  --orange:   #f59e0b; --orange-bg:   #fff3df;
  --red:      #ef4444; --red-bg:      #ffeceb;
  --purple:   #8b5cf6; --purple-bg:   #f1edfd;
  --cyan:     #06b6d4; --cyan-bg:     #e3f9fc;

  /* ── 圆角（更圆、更苹果）── */
  --r-xs: 6px;
  --r-sm: 10px;
  --r:    14px;
  --r-lg: 20px;
  --r-xl: 28px;

  /* ── 阴影（更柔、更弥散）── */
  --sh-xs: 0 1px 2px rgba(0, 0, 0, .04);
  --sh-sm: 0 2px 8px rgba(0, 0, 0, .04), 0 1px 2px rgba(0, 0, 0, .03);
  --sh:    0 4px 16px rgba(0, 0, 0, .06);
  --sh-lg: 0 16px 40px rgba(0, 0, 0, .12), 0 4px 12px rgba(0, 0, 0, .06);

  /* ── 尺寸 ── */
  --nav-h: 48px;
  --tab-h: 60px;
  --safe-b: env(safe-area-inset-bottom, 0px);

  /* 文字 */
  --font-display: -apple-system, BlinkMacSystemFont, "SF Pro Display",
    "PingFang SC", "Helvetica Neue", "Source Han Sans SC", sans-serif;
  --font-num: ui-monospace, "SF Mono", Menlo, Consolas, "PingFang SC", monospace;

  /* ── 动效曲线（苹果式 ease-in-out）── */
  --ease: cubic-bezier(0.4, 0, 0.2, 1);
  --ease-out: cubic-bezier(0.16, 1, 0.3, 1);
}

/* ─── Reset ─── */
*, *::before, *::after { box-sizing: border-box; -webkit-tap-highlight-color: transparent; }
html, body { margin: 0; padding: 0; }
body {
  font-family: var(--font-display);
  font-size: 13px;
  font-weight: 400;
  color: var(--ink-1);
  line-height: 1.45;
  background: var(--bg);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}
#app { min-height: 100vh; }
a { color: var(--brand); text-decoration: none; }
input, select, textarea, button { font-family: inherit; font-size: inherit; color: inherit; }
button { cursor: pointer; }

/* =========================================================
   SVG 镂空线条图标库
   用 .ico::before 当 mask，所有图标 24×24 stroke-only
   ========================================================= */
.ico {
  display: inline-block;
  width: 1em; height: 1em;
  vertical-align: -.15em;
  background-color: currentColor;
  -webkit-mask-position: center center; mask-position: center center;
  -webkit-mask-repeat: no-repeat; mask-repeat: no-repeat;
  -webkit-mask-size: contain; mask-size: contain;
  flex-shrink: 0;
}
.ico-22 { font-size: 22px; }
.ico-20 { font-size: 20px; }
.ico-18 { font-size: 18px; }
.ico-16 { font-size: 16px; }
.ico-14 { font-size: 14px; }
.ico-12 { font-size: 12px; }

/* 通用间距（保证图标 align 好） */
.gap-6 { display: inline-flex; align-items: center; gap: 6px; }
.gap-8 { display: inline-flex; align-items: center; gap: 8px; }
.gap-10 { display: inline-flex; align-items: center; gap: 10px; }

/* ------- 各图标 (SVG 24x24, stroke=currentColor) ------- */

/* 销售订单：文档 + 勾 */
.ico-order {
  -webkit-mask-image: url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M14 3H6a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V9z'/%3E%3Cpath d='M14 3v6h6'/%3E%3Cpath d='m9 14 2 2 4-4'/%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M14 3H6a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V9z'/%3E%3Cpath d='M14 3v6h6'/%3E%3Cpath d='m9 14 2 2 4-4'/%3E%3C/svg%3E");
}
/* 交车：钥匙 */
.ico-key {
  -webkit-mask-image: url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='8' cy='15' r='4'/%3E%3Cpath d='m10.85 12.15 8.15-8.15'/%3E%3Cpath d='m18 5 2 2'/%3E%3Cpath d='m15 8 2 2'/%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='8' cy='15' r='4'/%3E%3Cpath d='m10.85 12.15 8.15-8.15'/%3E%3Cpath d='m18 5 2 2'/%3E%3Cpath d='m15 8 2 2'/%3E%3C/svg%3E");
}
/* 客流：漏斗 */
.ico-funnel {
  -webkit-mask-image: url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M3 5h18'/%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3Cpath d='M9 9h6l-1 5h-4z'/%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M3 5h18'/%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3Cpath d='M9 9h6l-1 5h-4z'/%3E%3C/svg%3E");
}
/* 订单看板：柱状图 */
.ico-chart {
  -webkit-mask-image: url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M4 20V11'/%3E%3Cpath d='M10 20V4'/%3E%3Cpath d='M16 20V14'/%3E%3Cpath d='M3 20h18'/%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M4 20V11'/%3E%3Cpath d='M10 20V4'/%3E%3Cpath d='M16 20V14'/%3E%3Cpath d='M3 20h18'/%3E%3C/svg%3E");
}
/* 我的：人 */
.ico-user {
  -webkit-mask-image: url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='8' r='4'/%3E%3Cpath d='M4 21a8 8 0 0 1 16 0'/%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='8' r='4'/%3E%3Cpath d='M4 21a8 8 0 0 1 16 0'/%3E%3C/svg%3E");
}
/* 搜索 */
.ico-search {
  -webkit-mask-image: url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='11' cy='11' r='7'/%3E%3Cpath d='m20 20-3.5-3.5'/%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='11' cy='11' r='7'/%3E%3Cpath d='m20 20-3.5-3.5'/%3E%3C/svg%3E");
}
/* 加号 */
.ico-plus {
  -webkit-mask-image: url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M12 5v14M5 12h14'/%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M12 5v14M5 12h14'/%3E%3C/svg%3E");
}
/* 减号 */
.ico-minus {
  -webkit-mask-image: url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M5 12h14'/%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M5 12h14'/%3E%3C/svg%3E");
}
/* 勾 */
.ico-check {
  -webkit-mask-image: url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m5 12 5 5 9-11'/%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m5 12 5 5 9-11'/%3E%3C/svg%3E");
}
/* 关闭 */
.ico-close {
  -webkit-mask-image: url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6 6l12 12M6 18 18 6'/%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6 6l12 12M6 18 18 6'/%3E%3C/svg%3E");
}
/* 右箭头 */
.ico-arrow-right {
  -webkit-mask-image: url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M5 12h14M13 5l7 7-7 7'/%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M5 12h14M13 5l7 7-7 7'/%3E%3C/svg%3E");
}
/* 左箭头 */
.ico-arrow-left {
  -webkit-mask-image: url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M19 12H5M11 5l-7 7 7 7'/%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M19 12H5M11 5l-7 7 7 7'/%3E%3C/svg%3E");
}
/* 下箭头 */
.ico-arrow-down {
  -webkit-mask-image: url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");
}
.ico-arrow-up {
  -webkit-mask-image: url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 15 6-6 6 6'/%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 15 6-6 6 6'/%3E%3C/svg%3E");
}
/* 时钟 */
.ico-clock {
  -webkit-mask-image: url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='9'/%3E%3Cpath d='M12 7v5l3 3'/%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='9'/%3E%3Cpath d='M12 7v5l3 3'/%3E%3C/svg%3E");
}
/* 日历 */
.ico-calendar {
  -webkit-mask-image: url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='3' y='5' width='18' height='16' rx='2'/%3E%3Cpath d='M3 10h18M8 3v4M16 3v4'/%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='3' y='5' width='18' height='16' rx='2'/%3E%3Cpath d='M3 10h18M8 3v4M16 3v4'/%3E%3C/svg%3E");
}
/* 电话 */
.ico-phone {
  -webkit-mask-image: url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M22 16.92v3a2 2 0 0 1-2.18 2 19.79 19.79 0 0 1-8.63-3.07 19.5 19.5 0 0 1-6-6 19.79 19.79 0 0 1-3.07-8.67A2 2 0 0 1 4.11 2h3a2 2 0 0 1 2 1.72c.13.96.37 1.9.72 2.81a2 2 0 0 1-.45 2.11L8.09 9.91a16 16 0 0 0 6 6l1.27-1.27a2 2 0 0 1 2.11-.45c.91.35 1.85.59 2.81.72A2 2 0 0 1 22 16.92z'/%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M22 16.92v3a2 2 0 0 1-2.18 2 19.79 19.79 0 0 1-8.63-3.07 19.5 19.5 0 0 1-6-6 19.79 19.79 0 0 1-3.07-8.67A2 2 0 0 1 4.11 2h3a2 2 0 0 1 2 1.72c.13.96.37 1.9.72 2.81a2 2 0 0 1-.45 2.11L8.09 9.91a16 16 0 0 0 6 6l1.27-1.27a2 2 0 0 1 2.11-.45c.91.35 1.85.59 2.81.72A2 2 0 0 1 22 16.92z'/%3E%3C/svg%3E");
}
/* 汽车前视（用于 logo / 客流量未用） */
.ico-car {
  -webkit-mask-image: url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M5 17h14l-1.4-7.2a2 2 0 0 0-2-1.6H8.4a2 2 0 0 0-2 1.6L5 17z'/%3E%3Ccircle cx='7.5' cy='17' r='1.5'/%3E%3Ccircle cx='16.5' cy='17' r='1.5'/%3E%3Cpath d='M5 12h14'/%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M5 17h14l-1.4-7.2a2 2 0 0 0-2-1.6H8.4a2 2 0 0 0-2 1.6L5 17z'/%3E%3Ccircle cx='7.5' cy='17' r='1.5'/%3E%3Ccircle cx='16.5' cy='17' r='1.5'/%3E%3Cpath d='M5 12h14'/%3E%3C/svg%3E");
}
/* 钱包 */
.ico-wallet {
  -webkit-mask-image: url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M3 7a2 2 0 0 1 2-2h13a2 2 0 0 1 2 2v1H5z'/%3E%3Cpath d='M3 8v10a2 2 0 0 0 2 2h15V8'/%3E%3Ccircle cx='17' cy='14' r='1.5' fill='%23000'/%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M3 7a2 2 0 0 1 2-2h13a2 2 0 0 1 2 2v1H5z'/%3E%3Cpath d='M3 8v10a2 2 0 0 0 2 2h15V8'/%3E%3Ccircle cx='17' cy='14' r='1.5' fill='%23000'/%3E%3C/svg%3E");
}
/* 纸币（毛利预警看板 v114.6.9.45 补）
 *   肉哥 2026-09-11：原来 Hub 卡片上显示成【红色实心方块】——
 *   根因是 .ico-money 这个类【从未定义】，而 .ico 基类只有
 *   `background-color: currentColor` + 空 mask → 1em×1em 实心块。
 * ★ v114.6.9.48 更正（2026-09-12 复核）：下面这句旧注释当时写错了 ——
 *   .ico-mortgage / .ico-remarket **早已定义**在 `public/css/app-dash.css:12 / :22`，
 *   而 app-dash.css 由 `public/index.html:9` 引入，且这两个类确实被
 *   `public/js/page-sales-hub.js` 使用 → **不存在"未定义"问题，不需要再补**。
 *   （当时判断失误的原因：只 grep 了 app.css 一个文件，没搜整个 css/ 目录。
 *    教训：判"某类是否存在"必须搜整个样式目录，不能只看主样式表。） */
.ico-money {
  -webkit-mask-image: url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='2' y='6' width='20' height='12' rx='2'/%3E%3Ccircle cx='12' cy='12' r='2.5'/%3E%3Cpath d='M6.5 12h.01M17.5 12h.01'/%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='2' y='6' width='20' height='12' rx='2'/%3E%3Ccircle cx='12' cy='12' r='2.5'/%3E%3Cpath d='M6.5 12h.01M17.5 12h.01'/%3E%3C/svg%3E");
}
/* 礼物盒（衍业务） */
.ico-gift {
  -webkit-mask-image: url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='3' y='8' width='18' height='13' rx='1'/%3E%3Cpath d='M3 12h18M12 8v13'/%3E%3Cpath d='M12 8c-2-2-5-2-5 0s3 2 5 0c2 2 5 2 5 0s-3-2-5 0z'/%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='3' y='8' width='18' height='13' rx='1'/%3E%3Cpath d='M3 12h18M12 8v13'/%3E%3Cpath d='M12 8c-2-2-5-2-5 0s3 2 5 0c2 2 5 2 5 0s-3-2-5 0z'/%3E%3C/svg%3E");
}
/* 盾牌（延保/安全） */
.ico-shield {
  -webkit-mask-image: url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M12 3 4 6v6c0 4.5 3 8.5 8 9 5-.5 8-4.5 8-9V6z'/%3E%3Cpath d='m9 12 2 2 4-4'/%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M12 3 4 6v6c0 4.5 3 8.5 8 9 5-.5 8-4.5 8-9V6z'/%3E%3Cpath d='m9 12 2 2 4-4'/%3E%3C/svg%3E");
}
/* 工具（保养/维修） */
.ico-tools {
  -webkit-mask-image: url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m14.7 6.3 3 3-9 9-3-3zM14.7 6.3l3-3 3 3-3 3zM2 22l4-4'/%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m14.7 6.3 3 3-9 9-3-3zM14.7 6.3l3-3 3 3-3 3zM2 22l4-4'/%3E%3C/svg%3E");
}
/* 百分号（按揭利率） */
.ico-percent {
  -webkit-mask-image: url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m5 19 14-14M8 9a2 2 0 1 0 0-4 2 2 0 0 0 0 4zM16 19a2 2 0 1 0 0-4 2 2 0 0 0 0 4z'/%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m5 19 14-14M8 9a2 2 0 1 0 0-4 2 2 0 0 0 0 4zM16 19a2 2 0 1 0 0-4 2 2 0 0 0 0 4z'/%3E%3C/svg%3E");
}
/* 调色板（颜色） */
.ico-palette {
  -webkit-mask-image: url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M12 3a9 9 0 1 0 0 18 2 2 0 0 0 1.5-3.3A2 2 0 0 1 14.8 15H17a4 4 0 0 0 4-4 9 9 0 0 0-9-8z'/%3E%3Ccircle cx='7.5' cy='10.5' r='1' fill='%23000'/%3E%3Ccircle cx='11' cy='7' r='1' fill='%23000'/%3E%3Ccircle cx='16' cy='9' r='1' fill='%23000'/%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M12 3a9 9 0 1 0 0 18 2 2 0 0 0 1.5-3.3A2 2 0 0 1 14.8 15H17a4 4 0 0 0 4-4 9 9 0 0 0-9-8z'/%3E%3Ccircle cx='7.5' cy='10.5' r='1' fill='%23000'/%3E%3Ccircle cx='11' cy='7' r='1' fill='%23000'/%3E%3Ccircle cx='16' cy='9' r='1' fill='%23000'/%3E%3C/svg%3E");
}
/* 锁（数据权限） */
.ico-lock {
  -webkit-mask-image: url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='5' y='11' width='14' height='10' rx='2'/%3E%3Cpath d='M8 11V7a4 4 0 0 1 8 0v4'/%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='5' y='11' width='14' height='10' rx='2'/%3E%3Cpath d='M8 11V7a4 4 0 0 1 8 0v4'/%3E%3C/svg%3E");
}
/* 门店（建筑） */
.ico-store {
  -webkit-mask-image: url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M3 9 5 4h14l2 5'/%3E%3Cpath d='M5 9v11h14V9M9 14h6'/%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M3 9 5 4h14l2 5'/%3E%3Cpath d='M5 9v11h14V9M9 14h6'/%3E%3C/svg%3E");
}
/* 下载 */
.ico-download {
  -webkit-mask-image: url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M12 4v12M7 11l5 5 5-5M4 21h16'/%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M12 4v12M7 11l5 5 5-5M4 21h16'/%3E%3C/svg%3E");
}
/* 上传 */
.ico-upload {
  -webkit-mask-image: url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M12 20V8M7 13l5-5 5 5M4 3h16'/%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M12 20V8M7 13l5-5 5 5M4 3h16'/%3E%3C/svg%3E");
}
/* 退出登录 */
.ico-logout {
  -webkit-mask-image: url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M14 4h4a2 2 0 0 1 2 2v12a2 2 0 0 1-2 2h-4'/%3E%3Cpath d='m9 16-4-4 4-4M5 12h11'/%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M14 4h4a2 2 0 0 1 2 2v12a2 2 0 0 1-2 2h-4'/%3E%3Cpath d='m9 16-4-4 4-4M5 12h11'/%3E%3C/svg%3E");
}
/* 齿轮 */
.ico-settings {
  -webkit-mask-image: url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='3'/%3E%3Cpath d='M19 12a7 7 0 0 0-.1-1.2l2-1.6-2-3.4-2.4 1a7 7 0 0 0-2-1.1L14 3h-4l-.5 2.6a7 7 0 0 0-2 1.1l-2.4-1-2 3.4 2 1.6A7 7 0 0 0 5 12c0 .4 0 .8.1 1.2l-2 1.6 2 3.4 2.4-1a7 7 0 0 0 2 1.1L10 21h4l.5-2.6a7 7 0 0 0 2-1.1l2.4 1 2-3.4-2-1.6c.1-.4.1-.8.1-1.2z'/%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='3'/%3E%3Cpath d='M19 12a7 7 0 0 0-.1-1.2l2-1.6-2-3.4-2.4 1a7 7 0 0 0-2-1.1L14 3h-4l-.5 2.6a7 7 0 0 0-2 1.1l-2.4-1-2 3.4 2 1.6A7 7 0 0 0 5 12c0 .4 0 .8.1 1.2l-2 1.6 2 3.4 2.4-1a7 7 0 0 0 2 1.1L10 21h4l.5-2.6a7 7 0 0 0 2-1.1l2.4 1 2-3.4-2-1.6c.1-.4.1-.8.1-1.2z'/%3E%3C/svg%3E");
}
/* 铅笔 */
.ico-edit {
  -webkit-mask-image: url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m4 20 4-1 11-11-3-3L5 16z'/%3E%3Cpath d='m14 6 3 3'/%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m4 20 4-1 11-11-3-3L5 16z'/%3E%3Cpath d='m14 6 3 3'/%3E%3C/svg%3E");
}
/* 暂存（软盘） */
.ico-save {
  -webkit-mask-image: url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M5 4h11l3 3v13a1 1 0 0 1-1 1H5a1 1 0 0 1-1-1V5a1 1 0 0 1 1-1z'/%3E%3Cpath d='M8 4v5h7V4M8 14h8v6H8z'/%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M5 4h11l3 3v13a1 1 0 0 1-1 1H5a1 1 0 0 1-1-1V5a1 1 0 0 1 1-1z'/%3E%3Cpath d='M8 4v5h7V4M8 14h8v6H8z'/%3E%3C/svg%3E");
}
/* 垃圾桶 */
.ico-trash {
  -webkit-mask-image: url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M4 7h16M9 7V5a2 2 0 0 1 2-2h2a2 2 0 0 1 2 2v2M6 7v13a2 2 0 0 0 2 2h8a2 2 0 0 0 2-2V7'/%3E%3Cpath d='M10 11v6M14 11v6'/%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M4 7h16M9 7V5a2 2 0 0 1 2-2h2a2 2 0 0 1 2 2v2M6 7v13a2 2 0 0 0 2 2h8a2 2 0 0 0 2-2V7'/%3E%3Cpath d='M10 11v6M14 11v6'/%3E%3C/svg%3E");
}
/* 眼睛 */
.ico-eye {
  -webkit-mask-image: url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M2 12s3.5-7 10-7 10 7 10 7-3.5 7-10 7S2 12 2 12z'/%3E%3Ccircle cx='12' cy='12' r='3'/%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M2 12s3.5-7 10-7 10 7 10 7-3.5 7-10 7S2 12 2 12z'/%3E%3Ccircle cx='12' cy='12' r='3'/%3E%3C/svg%3E");
}
/* 复制 */
.ico-copy {
  -webkit-mask-image: url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='8' y='8' width='13' height='13' rx='2'/%3E%3Cpath d='M4 16h-1a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h10a2 2 0 0 1 2 2v1'/%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='8' y='8' width='13' height='13' rx='2'/%3E%3Cpath d='M4 16h-1a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h10a2 2 0 0 1 2 2v1'/%3E%3C/svg%3E");
}
/* 链接 */
.ico-link {
  -webkit-mask-image: url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M10 14a5 5 0 0 0 7 0l3-3a5 5 0 0 0-7-7l-1 1'/%3E%3Cpath d='M14 10a5 5 0 0 0-7 0l-3 3a5 5 0 0 0 7 7l1-1'/%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M10 14a5 5 0 0 0 7 0l3-3a5 5 0 0 0-7-7l-1 1'/%3E%3Cpath d='M14 10a5 5 0 0 0-7 0l-3 3a5 5 0 0 0 7 7l1-1'/%3E%3C/svg%3E");
}
/* 信息 */
.ico-info {
  -webkit-mask-image: url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='9'/%3E%3Cpath d='M12 8v5M12 16v.5'/%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='9'/%3E%3Cpath d='M12 8v5M12 16v.5'/%3E%3C/svg%3E");
}
/* 警告三角 */
.ico-warn {
  -webkit-mask-image: url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m12 3 10 18H2L12 3z'/%3E%3Cpath d='M12 10v5M12 18v.5'/%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m12 3 10 18H2L12 3z'/%3E%3Cpath d='M12 10v5M12 18v.5'/%3E%3C/svg%3E");
}
/* 价格 */
.ico-tag {
  -webkit-mask-image: url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M20 12 12 4H5v7l8 8z'/%3E%3Ccircle cx='9' cy='9' r='1.4' fill='%23000'/%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M20 12 12 4H5v7l8 8z'/%3E%3Ccircle cx='9' cy='9' r='1.4' fill='%23000'/%3E%3C/svg%3E");
}
/* 位置 */
.ico-pin {
  -webkit-mask-image: url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M12 22s-7-7.5-7-13a7 7 0 1 1 14 0c0 5.5-7 13-7 13z'/%3E%3Ccircle cx='12' cy='9' r='2.5'/%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M12 22s-7-7.5-7-13a7 7 0 0 1 14 0c0 5.5-7 13-7 13z'/%3E%3Ccircle cx='12' cy='9' r='2.5'/%3E%3C/svg%3E");
}
/* 保险（伞） */
.ico-umbrella {
  -webkit-mask-image: url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M12 2v4M3 10a9 9 0 0 1 18 0c-2 0-4 1-4 3M3 10c2 0 4 1 4 3M7 13c0 5 2 8 5 8s5-3 5-8'/%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M12 2v4M3 10a9 9 0 0 1 18 0c-2 0-4 1-4 3M3 10c2 0 4 1 4 3M7 13c0 5 2 8 5 8s5-3 5-8'/%3E%3C/svg%3E");
}
/* 刷新/同步 */
.ico-sync {
  -webkit-mask-image: url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M21 12a9 9 0 0 1-9 9M3 12a9 9 0 0 1 9-9'/%3E%3Cpath d='m21 3-5 5M3 21l5-5'/%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M21 12a9 9 0 0 1-9 9M3 12a9 9 0 0 1 9-9'/%3E%3Cpath d='m21 3-5 5M3 21l5-5'/%3E%3C/svg%3E");
}
/* 折线图 */
.ico-chart {
  -webkit-mask-image: url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M3 3v18h18'/%3E%3Cpath d='m7 14 4-4 4 4 5-6'/%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M3 3v18h18'/%3E%3Cpath d='m7 14 4-4 4 4 5-6'/%3E%3C/svg%3E");
}
/* 列表 */
.ico-list {
  -webkit-mask-image: url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M8 6h13M8 12h13M8 18h13M3 6h.01M3 12h.01M3 18h.01'/%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M8 6h13M8 12h13M8 18h13M3 6h.01M3 12h.01M3 18h.01'/%3E%3C/svg%3E");
}
/* 外发（share） */
.ico-share {
  -webkit-mask-image: url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='6' cy='12' r='2.5'/%3E%3Ccircle cx='18' cy='5' r='2.5'/%3E%3Ccircle cx='18' cy='19' r='2.5'/%3E%3Cpath d='m8 11 8-5M8 13l8 5'/%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='6' cy='12' r='2.5'/%3E%3Ccircle cx='18' cy='5' r='2.5'/%3E%3Ccircle cx='18' cy='19' r='2.5'/%3E%3Cpath d='m8 11 8-5M8 13l8 5'/%3E%3C/svg%3E");
}
/* 团队 / 组织 */
.ico-team {
  -webkit-mask-image: url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='8' r='3'/%3E%3Ccircle cx='4' cy='10' r='2.5'/%3E%3Ccircle cx='20' cy='10' r='2.5'/%3E%3Cpath d='M4 20c0-3 4-5 8-5s8 2 8 5'/%3E%3Cpath d='M2 16a2 2 0 0 1 1.7-2M22 16a2 2 0 0 0-1.7-2'/%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='8' r='3'/%3E%3Ccircle cx='4' cy='10' r='2.5'/%3E%3Ccircle cx='20' cy='10' r='2.5'/%3E%3Cpath d='M4 20c0-3 4-5 8-5s8 2 8 5'/%3E%3Cpath d='M2 16a2 2 0 0 1 1.7-2M22 16a2 2 0 0 0-1.7-2'/%3E%3C/svg%3E");
}
/* 钥匙 */
.ico-key-old { -webkit-mask-image: url(""); }
/* 文档 */
.ico-doc {
  -webkit-mask-image: url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M14 3H6a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V9z'/%3E%3Cpath d='M14 3v6h6M8 13h8M8 17h6'/%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M14 3H6a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V9z'/%3E%3Cpath d='M14 3v6h6M8 13h8M8 17h6'/%3E%3C/svg%3E");
}
/* 楼盘 / 装饰 */
.ico-decor {
  -webkit-mask-image: url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M3 21V9l9-6 9 6v12'/%3E%3Cpath d='M9 21v-7h6v7'/%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M3 21V9l9-6 9 6v12'/%3E%3Cpath d='M9 21v-7h6v7'/%3E%3C/svg%3E");
}
/* 圆点 */
.ico-dot {
  -webkit-mask-image: url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='%23000'%3E%3Ccircle cx='12' cy='12' r='5'/%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='%23000'%3E%3Ccircle cx='12' cy='12' r='5'/%3E%3C/svg%3E");
}

/* =========================================================
   排版
   ========================================================= */
.t-display { font-family: var(--font-display); font-weight: 700; letter-spacing: -.02em; }
.t-num { font-family: var(--font-num); font-variant-numeric: tabular-nums; }

/* =========================================================
   布局
   ========================================================= */

/* ----- 顶栏 ----- */
.navbar {
  position: sticky; top: 0; z-index: 50;
  height: calc(var(--nav-h) + env(safe-area-inset-top, 0px));
  padding-top: env(safe-area-inset-top, 0px);
  display: flex; align-items: center; gap: 12px;
  padding-left: 14px; padding-right: 14px;
  background: rgba(255,255,255,.86);
  backdrop-filter: saturate(180%) blur(20px);
  -webkit-backdrop-filter: saturate(180%) blur(20px);
  border-bottom: 1px solid var(--border);
}
.navbar .brand {
  display: flex; align-items: center; gap: 8px;
  font-size: 15px; font-weight: 700;
  color: var(--ink-1); letter-spacing: -.01em;
}
.navbar .brand img { height: 26px; }
.navbar .brand .brand-text {
  display: inline-block; max-width: 110px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  letter-spacing: -.01em;
}
.navbar .brand .pill {
  font-size: 11px; padding: 2px 6px; border-radius: 4px;
  background: var(--brand-100); color: var(--brand);
  font-weight: 400; letter-spacing: 0;
}
.navbar .title { font-size: 16px; font-weight: 600; letter-spacing: -.01em; flex: 1; }
.navbar .right {
  display: flex; align-items: center; gap: 8px;
  font-size: 12px; color: var(--ink-2);
}
.navbar .right .av {
  width: 28px; height: 28px; border-radius: 50%;
  background: linear-gradient(135deg, var(--brand), var(--brand-300));
  color: #fff; display: flex; align-items: center; justify-content: center;
  font-size: 12px; font-weight: 600;
}
.navbar .back {
  display: inline-flex; align-items: center; justify-content: center;
  width: 32px; height: 32px; border-radius: 50%;
  color: var(--ink-1); cursor: pointer;
  font-size: 18px;
  background: var(--bg);
  transition: background .15s var(--ease), transform .12s var(--ease);
}
.navbar .back:active { background: var(--border); transform: scale(.94); }

/* ----- 主体 ----- */
.page {
  padding: 14px 14px calc(var(--tab-h) + var(--safe-b) + 20px);
  max-width: 1180px; margin: 0 auto;
}
.page.no-tab { padding-bottom: 24px; }
.page.wide { max-width: 100%; }

/* ----- 底 Tab ----- */
.tabbar {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 60;
  height: calc(var(--tab-h) + var(--safe-b));
  padding-bottom: var(--safe-b);
  display: flex; background: rgba(255,255,255,.92);
  backdrop-filter: saturate(180%) blur(20px);
  -webkit-backdrop-filter: saturate(180%) blur(20px);
  border-top: 1px solid var(--border);
}
.tabbar .tab {
  flex: 1; display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 4px; color: var(--ink-3); cursor: pointer; transition: color .15s;
  padding: 6px 0;
}
.tabbar .tab .ico { font-size: 22px; transition: transform .2s; }
.tabbar .tab > .lbl { font-size: 13px; font-weight: 400; letter-spacing: .02em; }
.tabbar .tab.active { color: var(--brand); }
.tabbar .tab.active .ico { transform: translateY(-1px); }

/* =========================================================
   卡片
   ========================================================= */
.card {
  background: var(--surface); border-radius: var(--r);
  box-shadow: var(--sh-sm); margin-bottom: 12px; overflow: hidden;
  border: 1px solid var(--border);
}
.card-hd {
  padding: 14px 16px; border-bottom: 1px solid var(--border-2);
  display: flex; align-items: center; justify-content: space-between; gap: 8px;
}
.card-hd h3 {
  margin: 0; font-size: 15px; font-weight: 600;
  display: flex; align-items: center; gap: 8px;
  letter-spacing: -.01em; color: var(--ink-1);
}
.card-hd h3 .ico { color: var(--brand); font-size: 18px; }
.card-bd { padding: 16px; }
.card-bd.tight { padding: 10px 14px; }
.card-flat { box-shadow: none; border: 1px solid var(--border); }

/* =========================================================
   表单
   ========================================================= */
.form-row { margin-bottom: 14px; }
.form-row > label {
  display: block; font-size: 13px; color: var(--ink-2);
  margin-bottom: 6px; font-weight: 400;
}
.form-row > label .req { color: var(--red); margin-left: 2px; }
.input, .select, textarea.input {
  display: block; width: 100%;
  height: 42px; padding: 0 12px;
  border: 1px solid var(--border); border-radius: var(--r-sm);
  background: var(--surface); color: var(--ink-1); outline: none;
  transition: border-color .15s var(--ease), box-shadow .2s var(--ease), background .15s var(--ease);
  font-size: 14px;
}
textarea.input { height: auto; padding: 10px 12px; line-height: 1.55; resize: vertical; }
.input:hover, .select:hover, textarea.input:hover { border-color: var(--ink-4); }
.input:focus, .select:focus, textarea.input:focus {
  border-color: var(--brand); box-shadow: 0 0 0 4px rgba(0, 113, 227, .15);
}
.input::placeholder, textarea.input::placeholder { color: var(--ink-3); }
/* v82 肉哥 2026-08-31：证件号码失焦实时校验的内联错误提示 + 输入框红边 */
.input.err, .select.err { border-color: var(--red); box-shadow: 0 0 0 3px rgba(239, 68, 68, .12); }
.field-err {
  display: none; margin-top: 5px; font-size: 11px; font-weight: 400; line-height: 1.4; color: var(--red);
}
.field-err:not(:empty) { display: block; }
/* iOS WebView 内置 date/time/month/week 撑高兜底：显式压住 */
input[type="date"].input,
input[type="time"].input,
input[type="datetime-local"].input,
input[type="month"].input,
input[type="week"].input {
  height: 42px; min-height: 42px; padding: 0 10px;
  line-height: 42px; box-sizing: border-box;
}
.select {
  appearance: none;
  background-image: url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12' fill='none' stroke='%2386868b' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m3 5 3 3 3-3'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: right 12px center; background-size: 14px;
  padding-right: 34px;
}

/* ---------- 可搜索下拉 Combobox（保险公司 / 金融机构等长清单） ---------- */
.cb { position: relative; }
/* 关键：panel 用 absolute 锚定在 input 容器内，
   跟随 sheet-bd 一起滚、不会因 iOS 软键盘弹起而飘移覆盖输入框。
   JS 端通过 .flip 切换向上/向下展开。 */
.cb-control {
  display: flex; align-items: center;
  height: 42px; padding: 0 12px;
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--r-sm);
  transition: border-color .15s var(--ease), box-shadow .2s var(--ease);
  position: relative; z-index: 2;
}
.cb-control:focus-within { border-color: var(--brand); box-shadow: 0 0 0 4px rgba(0, 113, 227, .15); }
.cb-input {
  flex: 1; min-width: 0; border: none; outline: none; background: transparent;
  font-size: 14px; color: var(--ink-1); line-height: 1.4;
}
.cb-input::placeholder { color: var(--ink-3); }
.cb-caret {
  width: 0; height: 0; margin-left: 8px; flex: none;
  border-left: 4px solid transparent; border-right: 4px solid transparent;
  border-top: 5px solid var(--ink-4);
  transition: transform .2s var(--ease);
}
.cb.open .cb-caret { transform: rotate(180deg); }
.cb-panel {
  position: absolute;
  left: 0; right: 0;
  top: calc(100% + 4px);
  z-index: 10;
  max-height: 240px; overflow-y: auto; -webkit-overflow-scrolling: touch;
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--r); box-shadow: 0 12px 32px rgba(15, 23, 42, .18);
  padding: 6px;
}
.cb-panel.flip {
  top: auto;
  bottom: calc(100% + 4px);
}
.cb-opt {
  padding: 10px 12px; border-radius: 8px; font-size: 14px; color: var(--ink-1);
  cursor: pointer; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.cb-opt + .cb-opt { margin-top: 2px; }
.cb-opt:hover { background: var(--border-2); }
.cb-opt.act { background: var(--brand-50); }
.cb-opt.sel { color: var(--brand); font-weight: 600; }
.cb-empty, .cb-more { padding: 10px 12px; font-size: 11px; font-weight: 400; color: var(--ink-3); text-align: center; }
.cb-more { border-top: 1px solid var(--border-2); margin-top: 4px; }
.grid2 { display: grid; grid-template-columns: 1fr 1fr; gap: 0 12px; }
.grid3 { display: grid; grid-template-columns: repeat(3, 1fr); gap: 0 12px; }
.grid4 { display: grid; grid-template-columns: repeat(4, 1fr); gap: 0 10px; }

/* 强制同行版本，不被 <=460px 的 media query 拍扁成单列。
   用于"业务上必须并排"的字段组（品牌+车系、购车类型+证件类型 等）。
   窄屏下仍 1fr 1fr，配合 .input/.select 的 overflow 省略，让 select 内容也展示全。 */
.grid2-row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: 0 10px;
}
.grid2-row > .form-row { min-width: 0; }
.grid2-row .input,
.grid2-row .select { min-width: 0; width: 100%; }
.grid2-row select.select {
  text-overflow: ellipsis;
}
@media (max-width: 420px) {
  .grid3, .grid4 { grid-template-columns: 1fr 1fr; }
}

/* 4S 店里大部分顾问用企微 iphone（≈ 375–390pt 宽）+ sheet 还有 16px 内边距
   真正可用的内容宽度 ≤ 350px，grid2 平分只有 165px/列，select 把"2026款 A3 Limousine
   35 TFSI"全塞不下。所以窄屏直接单列堆叠，字号微收，让长字段显全。 */
@media (max-width: 460px) {
  .grid2 { grid-template-columns: 1fr; }
  .form-row > label {
    font-size: 13px; font-weight: 400; line-height: 1.5;
    white-space: normal;        /* 长 label 允许换行 */
    word-break: break-word;
    margin-bottom: 4px;
  }
  .form-row > label .req { margin-left: 1px; font-size: 13px; font-weight: 400; }
  .input, .select { font-size: 14px; }
  /* select 在窄屏时给 native arrow 留位，但是 125pt 容器里会被文本推挤。
     让 label 与 select 都单列后，宽度在 ≈ 350px，足够显全。 */
}

/* 分段选择 */
.segment { display: inline-flex; gap: 4px; flex-wrap: wrap; padding: 4px;
  background: var(--border-2); border-radius: 10px;
}
.segment .seg {
  padding: 6px 14px; border-radius: 7px;
  background: transparent; color: var(--ink-2); cursor: pointer;
  font-size: 13px; font-weight: 400;
  transition: background .15s, color .15s, box-shadow .15s;
}
.segment .seg.on {
  background: var(--surface); color: var(--ink-1);
  font-weight: 600; box-shadow: var(--sh-xs);
}

/* =========================================================
   按钮（苹果胶囊风）
   ========================================================= */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 6px;
  height: 38px; padding: 0 16px; border: 1px solid transparent; border-radius: 999px;
  background: var(--bg); color: var(--ink-1);
  font-weight: 400; font-size: 13px; cursor: pointer;
  letter-spacing: -.01em;
  transition: background .18s var(--ease), color .18s var(--ease),
              border-color .18s var(--ease), transform .12s var(--ease),
              box-shadow .18s var(--ease), opacity .15s var(--ease);
}
.btn:hover { background: var(--border-2); }
.btn:active { transform: scale(.97); }
.btn:disabled { opacity: .4; cursor: not-allowed; }
.btn.block { width: 100%; }
.btn.primary {
  background: var(--brand); color: #fff; font-weight: 600;
  box-shadow: 0 1px 2px rgba(0,0,0,.06);
}
.btn.primary:hover { background: var(--brand-600); }
.btn.ghost {
  background: var(--brand-50); color: var(--brand);
}
.btn.ghost:hover { background: var(--brand-100); }
.btn.outline {
  background: transparent; color: var(--ink-1);
  border: 1px solid var(--border);
}
.btn.outline:hover { border-color: var(--ink-4); background: var(--hover); }
.btn.gray { background: var(--bg); color: var(--ink-2); border: 1px solid var(--border); }
.btn.gray:hover { background: var(--border-2); }
.btn.green { background: var(--green); color: #fff; }
.btn.green:hover { background: #0e9b73; }
.btn.danger { background: var(--red); color: #fff; }
.btn.danger:hover { background: #d62f2f; }
.btn.sm { height: 30px; padding: 0 12px; font-size: 13px; font-weight: 400; }
.btn.xs { height: 24px; padding: 0 10px; font-size: 13px; font-weight: 400; }
.btn-bar { display: flex; gap: 10px; margin-top: 4px; }
.btn-bar .btn { flex: 1; }

/* =========================================================
   标签 / 状态
   ========================================================= */
.tag {
  display: inline-flex; align-items: center; gap: 4px;
  padding: 3px 9px; border-radius: 999px;
  font-size: 11px; line-height: 1.5; font-weight: 400;
}
.tag.blue   { background: var(--brand-100); color: var(--brand); }
.tag.green  { background: var(--green-bg); color: var(--green); }
.tag.orange { background: var(--orange-bg); color: var(--orange); }
.tag.red    { background: var(--red-bg); color: var(--red); }
.tag.gray   { background: var(--border-2); color: var(--ink-3); }
.tag.purple { background: var(--purple-bg); color: var(--purple); }
.tag.cyan   { background: var(--cyan-bg); color: var(--cyan); }
.tag.solid  { color: #fff; }
.tag.solid.blue { background: var(--brand); }
.tag.solid.green { background: var(--green); }
.tag.solid.orange { background: var(--orange); }
.tag.solid.red { background: var(--red); }
.tag.solid.gray { background: var(--ink-2); }

/* =========================================================
   列表
   ========================================================= */
.list-item {
  padding: 14px 16px; border-bottom: 1px solid var(--border-2);
  display: flex; align-items: flex-start; gap: 12px; cursor: pointer;
  transition: background .12s;
}
.list-item:last-child { border-bottom: none; }
.list-item:active { background: var(--border-2); }
.list-item .main { flex: 1; min-width: 0; }
.list-item .t1 { font-size: 13px; font-weight: 400; margin-bottom: 6px;
  display: flex; align-items: center; gap: 6px; flex-wrap: wrap; letter-spacing: -.01em; }
.list-item .t2 { font-size: 11px; font-weight: 400; color: var(--ink-3); line-height: 1.55;
  word-break: break-word; overflow-wrap: anywhere; max-width: 100%; }
.list-item .amount { font-size: 17px; font-weight: 700; color: var(--brand);
  white-space: nowrap; font-family: var(--font-num); }
.list-item .right { text-align: right; flex-shrink: 0; min-width: 90px;
  display: flex; flex-direction: column; align-items: flex-end; gap: 6px; }
.list-item .right .meta { font-size: 11px; font-weight: 400; color: var(--ink-3);
  display: inline-flex; align-items: center; gap: 4px; white-space: nowrap; }

/* =========================================================
   首页订单卡片（首页 sales-order list — 用大卡片而非 flex row）
   ========================================================= */
.card-list {
  display: flex; flex-direction: column; gap: 10px; padding: 12px;
}
.order-card {
  background: var(--surface); border: 1px solid var(--border-2);
  border-radius: 12px; padding: 12px 14px; cursor: pointer;
  transition: transform .12s, box-shadow .12s;
  box-shadow: var(--sh-xs);
}
.order-card:active { transform: scale(.99); background: var(--border-2); }
.order-card .oc-row1 {
  display: flex; justify-content: space-between; align-items: center;
  gap: 10px;
}
.order-card .oc-name {
  font-size: 13px; font-weight: 400; color: var(--ink-1);
  display: inline-flex; align-items: center; gap: 5px;
  letter-spacing: -.01em;
}
.order-card .oc-name .ico { color: var(--brand-300); }
.order-card .oc-amount {
  font-size: 18px; font-weight: 700; color: var(--brand);
  white-space: nowrap; font-family: var(--font-num);
  letter-spacing: -.01em;
}
.order-card .oc-tags {
  display: flex; gap: 6px; flex-wrap: wrap; margin-top: 8px;
}
.order-card .oc-meta {
  font-size: 11px; font-weight: 400; color: var(--ink-2); margin-top: 8px;
  line-height: 1.5;
  display: -webkit-box; -webkit-line-clamp: 1; -webkit-box-orient: vertical;
  overflow: hidden;
  word-break: break-word;
}
.order-card .oc-foot {
  display: flex; justify-content: space-between; align-items: center;
  margin-top: 8px; padding-top: 8px;
  border-top: 1px dashed var(--border-2);
  font-size: 11px; font-weight: 400; color: var(--ink-3);
}
.order-card .oc-foot .oc-store {
  display: inline-flex; align-items: center; gap: 3px;
}
.order-card .oc-foot .oc-no {
  font-family: var(--font-num);
}

/* =========================================================
   KV
   ========================================================= */
/* KV 横向键值对（详情 sheet 中大量使用） */
.kv { display: flex; padding: 9px 0; font-size: 13px; font-weight: 400; line-height: 1.5;
  border-bottom: 1px dashed var(--border-2); }
.kv:last-child { border-bottom: none; }
.kv .k { color: var(--ink-3); width: 92px; flex-shrink: 0; font-size: 11px; font-weight: 400; }
.kv .v { flex: 1; color: var(--ink-1); text-align: right; word-break: break-all; font-weight: 500; }
.kv .v.strong { font-weight: 400; color: var(--brand); font-family: var(--font-num); font-size: 13px; }

/* =========================================================
   统计 / 指标
   ========================================================= */
.stat-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 8px; margin-bottom: 14px; }
@media (max-width: 520px) { .stat-grid { grid-template-columns: repeat(2, 1fr); } }
.stat {
  background: var(--surface); border-radius: var(--r);
  padding: 14px 8px; text-align: center; border: 1px solid var(--border-2);
  box-shadow: var(--sh-xs);
}
.stat .n { font-size: 22px; font-weight: 700; line-height: 1.2; color: var(--ink-1);
  font-family: var(--font-num); letter-spacing: -.02em; }
.stat .l { font-size: 11px; font-weight: 400; color: var(--ink-3); margin-top: 6px; }
.stat .sub { font-size: 11px; margin-top: 2px; font-weight: 400; }

/* =========================================================
   漏斗
   ========================================================= */
.funnel { padding: 6px 0 0; }
.funnel-stage { margin-bottom: 14px; }
.funnel-bar {
  position: relative; margin: 0 auto; height: 64px; border-radius: 12px;
  display: flex; align-items: center; justify-content: space-between;
  padding: 0 16px; color: #fff;
  box-shadow: 0 4px 16px rgba(15, 23, 42, .08);
  transition: width .4s ease;
  min-width: 50%;
}
.funnel-bar:hover { box-shadow: 0 6px 20px rgba(15, 23, 42, .15); }
.funnel-bar .fl { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.funnel-bar .fname { font-size: 13px; font-weight: 400; opacity: .98; }
.funnel-bar .fsub { font-size: 11px; font-weight: 400; opacity: .82; }
.funnel-bar .fnum {
  font-size: 26px; font-weight: 700;
  font-family: var(--font-num); letter-spacing: -.02em;
}
.funnel-arrow {
  text-align: center; font-size: 11px; font-weight: 400; color: var(--ink-3);
  padding: 4px 0;
  display: flex; align-items: center; justify-content: center; gap: 6px;
}
.funnel-arrow .ico { font-size: 14px; }
.funnel-arrow .rate-pill {
  background: var(--surface); border: 1px solid var(--border);
  border-radius: 999px; padding: 2px 10px; font-weight: 400;
  color: var(--brand); font-size: 11px;
  box-shadow: var(--sh-xs);
}
.funnel-channels {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(72px, 1fr));
  gap: 6px; padding: 8px 2px 0;
}
.funnel-channels .ch {
  background: var(--brand-50); border-radius: 8px; padding: 8px 4px;
  text-align: center; border: 1px solid var(--brand-100);
  transition: transform .15s, box-shadow .15s;
}
.funnel-channels .ch:hover { transform: translateY(-1px); box-shadow: var(--sh-xs); }
.funnel-channels .ch .cn {
  font-size: 16px; font-weight: 700; color: var(--ink-1);
  font-family: var(--font-num); letter-spacing: -.02em;
}
.funnel-channels .ch .cl { font-size: 11px; font-weight: 400; color: var(--ink-3); margin-top: 2px;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

/* =========================================================
   表格
   ========================================================= */
.table-wrap { overflow-x: auto; -webkit-overflow-scrolling: touch; }
table.tb { width: 100%; border-collapse: collapse; font-size: 13px; font-weight: 400; min-width: 580px; }
table.tb th, table.tb td { padding: 9px 8px; text-align: center; white-space: nowrap; }
table.tb thead th {
  background: var(--border-2); color: var(--ink-2); font-weight: 600;
  border-bottom: 1px solid var(--border); position: sticky; top: 0;
  font-size: 11px;
}
table.tb tbody tr { border-bottom: 1px solid var(--border-2); }
table.tb tbody tr:nth-child(even) { background: #fbfcfe; }
table.tb td.name { text-align: left; font-weight: 600; position: sticky; left: 0; background: inherit; }
table.tb td.rate { color: var(--brand); font-weight: 600; }
table.tb td .num { font-family: var(--font-num); }

/* =========================================================
   交车 Timetable
   ========================================================= */
.tt-wrap { overflow-x: auto; background: var(--surface); border-radius: var(--r); border: 1px solid var(--border-2); -webkit-overflow-scrolling: touch; }
/* 最小宽度：60 时间列 + 7×78 天列 = 606, 让 350px 屏一定横向滚动（左侧 sticky） */
.tt { min-width: 606px; }
.tt-head { display: flex; border-bottom: 1px solid var(--border); position: sticky; top: 0; background: var(--surface); z-index: 2; }
.tt-row { display: flex; border-bottom: 1px solid var(--border-2); min-height: 48px; }
/* 时间列：左侧 sticky，横向滚动时永远可见 */
.tt-time-cell {
  position: sticky; left: 0; z-index: 2;
  width: 60px; flex-shrink: 0;
  font-size: 11px; color: var(--ink-3);
  padding: 8px 4px; text-align: center;
  background: #fbfcfe;
  font-family: var(--font-num); font-weight: 600;
  box-shadow: 1px 0 0 var(--border-2);
}
.tt-head .tt-time-cell { z-index: 3; background: var(--surface); }
.tt-row .tt-time-cell { background: #fbfcfe; }
/* 日列与时段列固定宽度，避免被压扁 */
.cell-day, .cell-slot {
  flex: 0 0 78px;
  border-left: 1px solid var(--border-2);
}
.tt-head .cell-day {
  padding: 10px 4px; text-align: center; font-size: 12px;
}
.tt-head .cell-day .wd { font-weight: 600; font-size: 13px; color: var(--ink-1); }
.tt-head .cell-day .dt { color: var(--ink-3); font-size: 11px; margin-top: 2px; }
.tt-head .cell-day.today { background: var(--brand-50); }
.tt-head .cell-day.today .wd { color: var(--brand); }
.tt-row .cell-slot { padding: 4px; min-width: 0; }
.tt-card {
  background: var(--brand-100); border-left: 3px solid var(--brand);
  border-radius: 8px; padding: 6px 8px; margin-bottom: 4px;
  cursor: pointer; font-size: 11px; font-weight: 400; line-height: 1.5;
  transition: transform .1s, box-shadow .1s;
}
.tt-card:active { transform: scale(.97); }
.tt-card.done {
  background: var(--green-bg); border-left-color: var(--green); opacity: .9;
}
.tt-card .cn { font-weight: 400; color: var(--ink-1); font-size: 13px; }
.tt-card .cm { color: var(--ink-3); font-size: 11px; font-weight: 400; overflow: hidden;
  text-overflow: ellipsis; white-space: nowrap; }
/* 二次营销结果配色（覆盖 .done 的绿色，按结果区分） */
.tt-card.r-deal   { background: var(--green-bg);  border-left-color: var(--green); }
.tt-card.r-intent { background: var(--orange-bg); border-left-color: var(--orange); }
.tt-card.r-refuse { background: var(--red-bg);    border-left-color: var(--red); }
.tt-card.pending  { background: #f1f5f9; border-left-color: var(--ink-3); opacity: 1; }
.tt-badge { margin-top: 4px; }
/* 自己提报的交车：蓝色描边 + 「我」角标 */
.tt-card.mine { box-shadow: 0 0 0 1.5px var(--brand) inset; }
.mine-tag {
  display: inline-block; margin-left: 4px; padding: 0 5px;
  border-radius: 6px; background: var(--brand); color: #fff;
  font-size: 11px; font-weight: 400; line-height: 15px; vertical-align: 1px;
}
/* 同一时段多台交车：撞档提醒 */
.tt-clash {
  margin-top: 2px; padding: 2px 4px; border-radius: 6px;
  background: var(--red-bg); color: var(--red);
  font-size: 11px; font-weight: 400; text-align: center; line-height: 1.6;
}
.tt-card.search-card { padding: 8px 10px; margin-bottom: 8px; }
.tt-card.search-card .cn { font-size: 13px; font-weight: 400; }
.tt-card.search-card .cm { font-size: 11px; font-weight: 400; white-space: normal; }
.sc-top { display: flex; justify-content: space-between; align-items: center; gap: 8px; }

/* 交车看板：搜索框 + 图例 */
.search-bar { position: relative; display: flex; align-items: center; gap: 8px; margin: 10px 2px 6px; }
.search-ico { position: absolute; left: 12px; top: 50%; transform: translateY(-50%); color: var(--ink-3); font-size: 14px; pointer-events: none; }
.search-input { padding-left: 34px; flex: 1; }
.search-clear { flex-shrink: 0; }
.legend-row { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; padding: 4px 2px 8px; }
.legend-title { font-size: 11px; color: var(--ink-3); font-weight: 400; }
.tag.sm { padding: 2px 9px; font-size: 11px; font-weight: 400; line-height: 1.6; }
.search-meta { font-size: 11px; font-weight: 400; color: var(--ink-3); padding: 2px 4px 8px; }
.search-list { display: flex; flex-direction: column; gap: 0; padding: 2px 0 8px; }

/* =========================================================
   弹层 (Sheet)
   ========================================================= */
@keyframes fadeIn { from { opacity: 0; } to { opacity: 1; } }
@keyframes slideUp { from { transform: translateY(100%); } to { transform: translateY(0); } }
.mask {
  position: fixed; inset: 0; background: rgba(15, 23, 42, .42);
  z-index: 200;
  display: flex; align-items: flex-end; justify-content: center;
  animation: fadeIn .2s;
  /* 防止 sheet 内滚到边界时蒙层背景跟着滚 */
  overscroll-behavior: contain;
}
.sheet {
  background: var(--surface); width: 100%; max-width: 640px;
  border-radius: 20px 20px 0 0;
  /* 5 步向导这种超长内容 → 接近全屏 */
  height: 92vh; max-height: 92vh;
  display: flex; flex-direction: column;
  overflow: hidden;
  animation: slideUp .26s var(--ease-out);
  padding-bottom: var(--safe-b);
  -webkit-overflow-scrolling: touch;
}
.sheet-hd {
  padding: 14px 16px; border-bottom: 1px solid var(--border-2);
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  flex-shrink: 0;
  background: var(--surface);
}
.sheet-hd h3 {
  margin: 0; font-size: 17px; font-weight: 700;
  letter-spacing: -.02em;
}
.sheet-hd .close {
  display: inline-flex; align-items: center; justify-content: center;
  width: 30px; height: 30px; border-radius: 50%;
  background: var(--border-2); color: var(--ink-2); cursor: pointer;
  font-size: 18px;
}
.sheet-bd {
  padding: 16px;             /* 通用：解所有 sheet 内容贴屏边 */
  flex: 1 1 auto; min-height: 0;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  overscroll-behavior: contain;
}
/* 5 步录单向导自身容器：用负 margin 抵消 sheet-bd 的 padding，
   让它们仍撑到 sheet 全宽（左右顶到 sheet 边缘），内部自有 padding 维持视觉 */
.sheet-bd > #stepper,
.sheet-bd > #step-body,
.sheet-bd > #step-foot {
  margin-left: -16px;
  margin-right: -16px;
}
.sheet-grabber {
  position: absolute; left: 50%; top: 6px; transform: translateX(-50%);
  width: 40px; height: 4px; border-radius: 999px; background: var(--ink-4);
}
.mask .sheet { position: relative; }

/* =========================================================
   筛选栏
   ========================================================= */
.filter-bar {
  display: flex; gap: 8px; align-items: center; flex-wrap: wrap;
  background: var(--surface); border-radius: var(--r);
  padding: 12px; margin-bottom: 12px; border: 1px solid var(--border-2);
  box-shadow: var(--sh-xs);
}
.filter-bar .input, .filter-bar .select { height: 36px; font-size: 13px; }
/* iOS WebView 里 input[type=date] 默认很高+内边距怪异，这里显式拉齐 */
.filter-bar input[type="date"],
.filter-bar input[type="date"].input {
  height: 36px; min-height: 36px; padding: 0 8px;
  line-height: 36px; box-sizing: border-box;
}
.filter-bar .fl-item { display: flex; align-items: center; gap: 6px; }
.filter-bar .fl-item > span {
  font-size: 11px; font-weight: 400; color: var(--ink-3); white-space: nowrap;
  display: inline-flex; align-items: center; gap: 4px;
}

/* =========================================================
   其他
   ========================================================= */
.empty {
  padding: 48px 16px; text-align: center;
  color: var(--ink-3); font-size: 11px;
  font-weight: 400;
}
.empty .ico { font-size: 42px; opacity: .35; display: block; margin-bottom: 12px; color: var(--ink-3); }
.loading {
  padding: 40px 16px; text-align: center;
  color: var(--ink-3); font-size: 11px;
  font-weight: 400;
}
.loading::before {
  content: '';
  display: inline-block; width: 18px; height: 18px; margin-right: 8px;
  border: 2px solid var(--border); border-top-color: var(--brand);
  border-radius: 50%; vertical-align: -.3em;
  animation: spin .8s linear infinite;
}
@keyframes spin { to { transform: rotate(360deg); } }

.hint { font-size: 11px; font-weight: 400; color: var(--ink-3); line-height: 1.7; }
.hint.warn { color: var(--orange); }
.hint.success { color: var(--green); }
.hint.info { color: var(--brand); }
.divider { height: 1px; background: var(--border-2); margin: 14px 0; }

.section-title {
  font-size: 13px; font-weight: 400; color: var(--ink-2);
  margin: 18px 0 10px;
  display: flex; align-items: center; gap: 6px;
}
.section-title:first-child { margin-top: 0; }
.section-title .ico { color: var(--brand); font-size: 14px; }

.toast {
  position: fixed; left: 50%; top: 42%; transform: translate(-50%, -50%);
  background: rgba(15, 23, 42, .88); color: #fff;
  padding: 12px 20px; border-radius: 10px;
  font-size: 13px; font-weight: 400; z-index: 999;
  max-width: 76%; text-align: center; line-height: 1.5;
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  animation: fadeIn .15s;
}

/* =========================================================
   登录页
   ========================================================= */
.login-wrap {
  min-height: 100vh;
  display: flex; flex-direction: column; justify-content: center;
  padding: 32px 24px 24px;
  position: relative;
  overflow: hidden;
}
.login-wrap::before {
  /* 顶部的渐变岛 */
  content: '';
  position: absolute;
  left: -40%; top: -20%;
  width: 180%; height: 60%;
  background: linear-gradient(180deg,
    rgba(22, 87, 204, .07) 0%,
    rgba(22, 87, 204, .04) 40%,
    rgba(22, 87, 204, 0) 100%);
  border-radius: 50%;
  z-index: 0;
  pointer-events: none;
}
.login-wrap > * { position: relative; z-index: 1; }

.login-brand {
  text-align: center; margin-bottom: 32px; color: var(--ink-1);
}
.login-brand .lg {
  width: 80px; margin: 0 auto 14px;
  display: block;
  filter: drop-shadow(0 8px 24px rgba(22, 87, 204, .22));
}
.login-brand h1 {
  margin: 14px 0 0; font-size: 22px; font-weight: 700;
  letter-spacing: -.02em; color: var(--ink-1);
  display: inline-flex; align-items: center; gap: 8px;
}
.login-brand h1 img { height: 22px; vertical-align: -.05em; }
.login-brand h1 .brand-pill {
  font-size: 11px; padding: 2px 8px; border-radius: 999px;
  background: var(--brand-100); color: var(--brand);
  font-weight: 400;
}
.login-brand p {
  margin: 6px 0 0; font-size: 11px; font-weight: 400; color: var(--ink-3);
  letter-spacing: .04em;
}
.login-card {
  background: rgba(255,255,255,.85);
  backdrop-filter: blur(20px); -webkit-backdrop-filter: blur(20px);
  border: 1px solid rgba(255,255,255,.7);
  border-radius: var(--r-lg);
  padding: 24px 20px;
  box-shadow: var(--sh-lg);
}
.login-tips {
  margin-top: 16px; padding: 12px 14px;
  background: var(--brand-50); border-radius: 10px;
  font-size: 11px; font-weight: 400; color: var(--ink-2); line-height: 1.85;
  border: 1px solid var(--brand-100);
}
.login-tips b { color: var(--brand); font-weight: 600; }
.login-tips code {
  font-family: var(--font-num);
  background: rgba(22, 87, 204, .08);
  padding: 1px 5px; border-radius: 4px;
  font-size: 11px;
  font-weight: 400;
}

/* =========================================================
   "我的" 页头
   ========================================================= */
.profile-hd {
  margin: -14px -14px 14px;
  padding: 24px 16px;
  background: linear-gradient(135deg, var(--brand) 0%, var(--brand-300) 100%);
  color: #fff; position: relative; overflow: hidden;
}
.profile-hd::after {
  content: '';
  position: absolute; right: -40px; top: -40px;
  width: 160px; height: 160px; border-radius: 50%;
  background: rgba(255,255,255,.08);
}
.profile-hd::before {
  content: '';
  position: absolute; right: 60px; bottom: -30px;
  width: 100px; height: 100px; border-radius: 50%;
  background: rgba(255,255,255,.06);
}
.profile-hd .row { display: flex; align-items: center; gap: 14px; position: relative; z-index: 1; }
.profile-hd .av {
  width: 52px; height: 52px; border-radius: 50%;
  background: rgba(255,255,255,.22);
  display: flex; align-items: center; justify-content: center;
  font-size: 20px; font-weight: 700;
  border: 2px solid rgba(255,255,255,.35);
  font-family: var(--font-num);
}
.profile-hd .nm { font-size: 18px; font-weight: 700; letter-spacing: -.01em; }
.profile-hd .ps { font-size: 11px; font-weight: 400; opacity: .9; margin-top: 4px; opacity: .92; }
.profile-hd .scope-badge {
  position: absolute; right: 16px; top: 24px;
  background: rgba(255,255,255,.22); border-radius: 10px;
  padding: 6px 10px; font-size: 11px;
  font-weight: 400;
  display: inline-flex; align-items: center; gap: 4px;
  backdrop-filter: blur(8px);
}

.menu-item {
  display: flex; align-items: center; justify-content: space-between;
  padding: 14px 16px; border-bottom: 1px solid var(--border-2);
  cursor: pointer; transition: background .12s;
  font-size: 13px; font-weight: 400; color: var(--ink-1);
}
.menu-item:last-child { border-bottom: none; }
.menu-item:active { background: var(--border-2); }
.menu-item .lft { display: inline-flex; align-items: center; gap: 10px; }
.menu-item .ico { font-size: 18px; color: var(--brand); }
.menu-item .lft .ico.muted { color: var(--ink-3); }
.menu-item .lft .ico.danger { color: var(--red); }
.menu-item .arw { color: var(--ink-4); font-size: 16px; }
.menu-item .arw .ico { color: var(--ink-4); }

/* =========================================================
   PC 后台（含登陆页 / login）通用 layout
   ========================================================= */
.login-page {
  min-height: 100vh; display: flex; align-items: center; justify-content: center;
  background: var(--bg);
}
.login-card-pc {
  width: 400px; max-width: 92vw;
  background: var(--surface);
  border-radius: var(--r-lg);
  padding: 32px 30px;
  box-shadow: var(--sh-lg);
  border: 1px solid var(--border-2);
}
.login-card-pc .lg { height: 38px; margin-bottom: 18px; }
.login-card-pc h2 {
  margin: 0 0 4px; font-size: 21px; font-weight: 700;
  letter-spacing: -.02em; color: var(--ink-1);
}
.login-card-pc .sub {
  color: var(--ink-3); margin-bottom: 24px; font-size: 11px;
  font-weight: 400;
}
.login-card-pc label {
  display: block; margin: 14px 0 6px; font-size: 13px; color: var(--ink-2);
  font-weight: 400;
}
.login-card-pc input {
  width: 100%; height: 42px;
  border: 1px solid var(--border); border-radius: var(--r-sm);
  padding: 0 14px; font-size: 14px;
  transition: border-color .15s, box-shadow .15s;
}
.login-card-pc input:focus {
  border-color: var(--brand);
  box-shadow: 0 0 0 3px rgba(22, 87, 204, .12);
  outline: none;
}

/* PC 后台 layout */
.pc-layout { display: flex; min-height: 100vh; }
.pc-side {
  width: 240px; background: rgba(255, 255, 255, .85);
  backdrop-filter: blur(20px); -webkit-backdrop-filter: blur(20px);
  border-right: 1px solid var(--border);
  padding: 18px 12px; flex-shrink: 0;
  display: flex; flex-direction: column; gap: 4px;
}
.pc-side .logo { display: flex; align-items: center; gap: 10px; padding: 8px 10px 16px; }
.pc-side .logo img { height: 32px; }
.pc-side .logo .t { font-size: 15px; font-weight: 600; color: var(--ink-1); letter-spacing: -.02em; }
.pc-side .logo .sub { font-size: 11px; font-weight: 400; color: var(--ink-3); margin-top: 2px; }

.pc-nav-item {
  position: relative;
  padding: 8px 12px; border-radius: var(--r-sm);
  cursor: pointer; color: var(--ink-2);
  display: flex; justify-content: space-between; align-items: center;
  font-size: 13px;
  font-weight: 400;
  transition: background .15s var(--ease), color .15s var(--ease);
}
.pc-nav-item:hover { background: var(--hover); color: var(--ink-1); }
.pc-nav-item.active {
  background: var(--brand-50); color: var(--brand); font-weight: 600;
}
.pc-nav-item .cs {
  font-size: 11px; font-weight: 400; color: var(--brand);
  border: 1px solid var(--brand-100); border-radius: 4px;
  padding: 0 6px; background: var(--surface);
}
.pc-nav-sep { height: 1px; background: var(--border-2); margin: 10px 12px; }
.pc-side-foot {
  margin-top: auto; font-size: 11px; font-weight: 400; color: var(--ink-3);
  padding: 14px 10px 4px; border-top: 1px solid var(--border-2);
  line-height: 1.6;
}

.pc-main { flex: 1; padding: 24px 32px 40px; min-width: 0; background: var(--bg); }
.pc-topbar {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap; margin-bottom: 18px;
}
.pc-topbar .crumb {
  font-size: 22px; font-weight: 600; margin-right: auto;
  letter-spacing: -.02em; color: var(--ink-1);
}
.pc-topbar input, .pc-topbar select {
  height: 36px; border: 1px solid var(--border); border-radius: var(--r-sm);
  padding: 0 12px; font-size: 13px; background: var(--surface);
  transition: border-color .15s var(--ease), box-shadow .2s var(--ease);
}
.pc-topbar input:focus, .pc-topbar select:focus {
  border-color: var(--brand);
  box-shadow: 0 0 0 4px rgba(0, 113, 227, .15);
  outline: none;
}

.pc-table {
  width: 100%; border-collapse: separate; border-spacing: 0;
  background: var(--surface);
  border-radius: var(--r);
  overflow: hidden;
  border: 1px solid var(--border);
  font-size: 13px;
  font-weight: 400;
  box-shadow: var(--sh-xs);
}
.pc-table thead th {
  text-align: left; font-weight: 600; color: var(--ink-2);
  background: var(--bg); padding: 12px 18px;
  border-bottom: 1px solid var(--border);
  font-size: 12px; letter-spacing: .01em;
}
.pc-table tbody td {
  padding: 14px 18px; border-bottom: 1px solid var(--border-2);
  color: var(--ink-1);
}
.pc-table tbody tr:last-child td { border-bottom: 0; }
.pc-table tbody tr:hover { background: var(--hover); }
.pc-table .mono {
  font-family: var(--font-num); color: var(--ink-2);
  font-size: 13px;
  font-weight: 400;
}
.pc-table .ops a {
  color: var(--brand); margin-right: 14px; cursor: pointer;
  font-size: 13px; font-weight: 400; transition: opacity .15s var(--ease);
}
.pc-table .ops a:last-child { margin-right: 0; }
.pc-table .ops a:hover { opacity: .7; }
.pc-table .ops a.del { color: var(--red); }

/* PC 模态 */
.dlg-mask {
  position: fixed; inset: 0; background: rgba(0, 0, 0, .32);
  backdrop-filter: blur(8px); -webkit-backdrop-filter: blur(8px);
  display: flex; align-items: center; justify-content: center;
  z-index: 50; animation: fadeIn .18s var(--ease);
}
.dlg {
  background: var(--bg-elev); border-radius: var(--r-lg);
  width: 480px; max-width: 92vw;
  max-height: 88vh; overflow: hidden;
  box-shadow: var(--sh-lg);
  animation: popIn .22s var(--ease-out);
  display: flex; flex-direction: column;
}
@keyframes popIn { from { opacity: 0; transform: scale(.96) translateY(8px); } to { opacity: 1; transform: scale(1) translateY(0); } }
.dlg-h {
  padding: 18px 22px 14px; font-size: 17px; font-weight: 600;
  display: flex; justify-content: space-between; align-items: center;
  letter-spacing: -.02em; color: var(--ink-1);
}
.dlg-h .x {
  display: inline-flex; align-items: center; justify-content: center;
  width: 28px; height: 28px; border-radius: 50%;
  background: var(--bg); cursor: pointer;
  font-size: 16px; color: var(--ink-2);
  transition: background .15s var(--ease), color .15s var(--ease);
}
.dlg-h .x:hover { background: var(--border); color: var(--ink-1); }
.dlg-b { padding: 6px 22px 18px; overflow-y: auto; flex: 1; }
.dlg-b .f { margin-bottom: 14px; }
.dlg-b .f label {
  display: block; font-size: 13px; color: var(--ink-2);
  margin-bottom: 6px; font-weight: 400;
  letter-spacing: .02em;
}
.dlg-b .f .req { color: var(--red); }
.dlg-b .f input, .dlg-b .f select {
  width: 100%; height: 40px;
  border: 1px solid var(--border); border-radius: var(--r-sm);
  padding: 0 12px; font-size: 14px;
  transition: border-color .15s var(--ease), box-shadow .2s var(--ease);
}
.dlg-b .f input:focus, .dlg-b .f select:focus {
  border-color: var(--brand);
  box-shadow: 0 0 0 4px rgba(0, 113, 227, .15);
  outline: none;
}
.dlg-b .tip {
  background: var(--brand-50); color: var(--ink-2);
  border-radius: var(--r-sm); padding: 10px 12px;
  font-size: 11px; font-weight: 400; line-height: 1.7;
  margin-bottom: 12px; white-space: pre-line;
  border: 1px solid var(--brand-100);
}
.dlg-b textarea {
  width: 100%; height: 200px;
  border: 1px solid var(--border); border-radius: var(--r-sm);
  padding: 10px 12px; font-size: 13px;
  font-family: var(--font-num);
  resize: vertical;
  transition: border-color .15s var(--ease), box-shadow .2s var(--ease);
}
.dlg-b textarea:focus {
  border-color: var(--brand);
  box-shadow: 0 0 0 4px rgba(0, 113, 227, .15);
  outline: none;
}
.dlg-f {
  padding: 14px 22px 18px;
  display: flex; justify-content: flex-end; gap: 10px;
  border-top: 1px solid var(--border-2);
}
.pc-empty {
  text-align: center; color: var(--ink-3);
  padding: 80px 20px;
  background: var(--surface);
  border-radius: var(--r);
  border: 1px dashed var(--border);
  margin-top: 4px;
}
.pc-empty .ico { font-size: 48px; opacity: .5; display: block; margin-bottom: 12px; color: var(--ink-3); }

/* PC toast */
#toast {
  position: fixed; left: 50%; top: 24px; transform: translateX(-50%);
  background: rgba(29, 29, 31, .92);
  color: #fff;
  padding: 11px 20px; border-radius: 999px;
  font-size: 13px; font-weight: 400;
  opacity: 0; pointer-events: none;
  transition: opacity .25s var(--ease), transform .25s var(--ease);
  z-index: 99;
  box-shadow: 0 8px 24px rgba(0,0,0,.15);
  backdrop-filter: blur(20px); -webkit-backdrop-filter: blur(20px);
}
#toast.show { opacity: 1; transform: translateX(-50%) translateY(8px); }
#toast.ok { background: rgba(16, 185, 129, .92); }
#toast.err { background: rgba(239, 68, 68, .92); }

/* =========================================================
   报价单（公开页）
   ========================================================= */
.quote-page {
  min-height: 100vh; padding: 0 0 80px;
  background: var(--bg);
}
.quote-hd {
  padding: 24px 20px 32px;
  background: linear-gradient(140deg, var(--brand) 0%, var(--brand-300) 100%);
  color: #fff; text-align: center; position: relative; overflow: hidden;
}
.quote-hd::after {
  content: ''; position: absolute; right: -60px; bottom: -60px;
  width: 220px; height: 220px; border-radius: 50%;
  background: rgba(255,255,255,.07);
}
.quote-hd img { height: 48px; margin-bottom: 12px; position: relative; z-index: 1; }
.quote-hd h1 {
  margin: 0; font-size: 22px; font-weight: 700;
  letter-spacing: -.02em; position: relative; z-index: 1;
}
.quote-hd .sub {
  margin-top: 6px; font-size: 11px; font-weight: 400; opacity: .85;
  position: relative; z-index: 1; letter-spacing: .02em;
}
.quote-body {
  max-width: 480px; margin: -20px auto 0;
  padding: 0 16px; position: relative; z-index: 2;
}
.quote-card {
  background: var(--surface);
  border-radius: var(--r-lg);
  box-shadow: var(--sh-lg);
  border: 1px solid var(--border-2);
  overflow: hidden;
}
.quote-card .sec {
  padding: 18px 20px; border-bottom: 1px solid var(--border-2);
}
.quote-card .sec:last-child { border-bottom: none; }
.quote-card .sec h3 {
  margin: 0 0 12px; font-size: 13px; font-weight: 400;
  color: var(--ink-2); letter-spacing: .04em; text-transform: uppercase;
  display: flex; align-items: center; gap: 6px;
}
.quote-card .sec h3 .ico { color: var(--brand); font-size: 16px; }
.quote-card .price-row {
  display: flex; justify-content: space-between; align-items: baseline;
  padding: 10px 0; border-bottom: 1px dashed var(--border-2);
  font-size: 13px;
  font-weight: 400;
}
.quote-card .price-row:last-child { border-bottom: none; }
.quote-card .price-row .lbl { color: var(--ink-3); }
.quote-card .price-row .val { font-family: var(--font-num); font-weight: 600; color: var(--ink-1); }
.quote-card .price-row.discount .val { color: var(--green); }
.quote-card .price-row.total { border-top: 2px solid var(--ink-1); padding-top: 14px; margin-top: 6px; border-bottom: none; }
.quote-card .price-row.total .val {
  font-size: 22px; font-weight: 700; color: var(--brand);
  letter-spacing: -.02em;
}
/* 报价 meta 三段：单号 / 日期同行，门店单独一行展示完整名称 */
.quote-card .quote-tier {
  display: flex; flex-wrap: wrap; gap: 6px 22px;
  padding: 14px 20px;
  border-bottom: 1px solid var(--border-2);
}
.quote-card .quote-tier .item {
  flex: 1 1 auto; min-width: 0;
  display: flex; flex-direction: column; gap: 2px;
}
.quote-card .quote-tier .item .k {
  font-size: 11px; font-weight: 400; color: var(--ink-3);
}
.quote-card .quote-tier .item .v {
  font-size: 13px; color: var(--ink-1); font-weight: 400;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  font-family: var(--font-num);
}
.quote-card .quote-tier .item.store { flex-basis: 100%; }
.quote-foot {
  max-width: 480px; margin: 16px auto 0;
  padding: 0 16px; text-align: center;
}
.quote-foot .exp {
  font-size: 11px; font-weight: 400; color: var(--ink-3);
  display: inline-flex; align-items: center; gap: 6px;
}

/* =========================================================
   工具类
   ========================================================= */
.center { text-align: center; }
.muted { color: var(--ink-3); }
.tnum { font-family: var(--font-num); font-variant-numeric: tabular-nums; }
.hide { display: none !important; }
.flex { display: flex; }
.flex-1 { flex: 1; }
.row { display: flex; align-items: center; gap: 8px; }
.col { display: flex; flex-direction: column; gap: 8px; }
.between { justify-content: space-between; }
.mt-8 { margin-top: 8px; }
.mt-12 { margin-top: 12px; }
.mt-16 { margin-top: 16px; }
.mb-8 { margin-bottom: 8px; }
.mb-12 { margin-bottom: 12px; }

/* =========================================================
   响应式（pad → 手机）
   ========================================================= */
@media (max-width: 380px) {
  .stat-grid { grid-template-columns: repeat(2, 1fr); }
  .navbar .brand .pill { display: none; }
}

/* =========================================================
   5 步分步式向导 — 步骤指示器 / 选装包 / 衍生业务卡片
   ========================================================= */

/* 5 步分步式向导：5 个数字圆圈横向均分 + 文字标签在圆圈下方
   - 已完成: 蓝色填充圆 + 蓝色文字
   - 当前  : 蓝色描边圆（带柔光环） + 蓝色粗字
   - 未完成: 灰色描边圆 + 灰色细字                                       */
.stepper {
  display: flex; gap: 0; align-items: flex-start;
  padding: 14px 0 12px;
}
.stepper .stp {
  flex: 1; min-width: 0;
  display: flex; flex-direction: column; align-items: center; gap: 6px;
  cursor: default;
}
.stepper .stp .num {
  width: 28px; height: 28px; border-radius: 50%;
  display: inline-flex; align-items: center; justify-content: center;
  font-size: 13px; font-weight: 700; line-height: 1;
  font-family: var(--font-num);
  border: 2px solid var(--border-2);
  background: var(--surface);
  color: var(--ink-3);
  transition: all .2s;
  flex-shrink: 0;
}
.stepper .stp .lab {
  font-size: 11px; font-weight: 400; line-height: 1.3;
  color: var(--ink-3);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  max-width: 100%;
  text-align: center;
}
.stepper .stp.done .num {
  background: var(--brand);
  border-color: var(--brand);
  color: #fff;
}
.stepper .stp.done .lab { color: var(--brand); }
.stepper .stp.cur .num {
  background: var(--surface);
  border-color: var(--brand);
  color: var(--brand);
  box-shadow: 0 0 0 3px rgba(22,87,204,.15);
}
.stepper .stp.cur .lab {
  color: var(--brand); font-weight: 600;
}

/* ----- 选装包 / 字典多选 chip 网格 ----- */
.opt-picker {
  border: 1px solid var(--border); border-radius: var(--r-sm);
  padding: 10px; background: var(--brand-50);
}
.opt-grid {
  display: flex; flex-wrap: wrap; gap: 8px;
}
.opt-chip {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 7px 12px; border-radius: 8px;
  background: var(--surface); border: 1px solid var(--border);
  cursor: pointer; font-size: 13px; font-weight: 400; transition: all .15s;
  user-select: none;
}
.opt-chip input[type=checkbox] {
  width: 14px; height: 14px; margin: 0; accent-color: var(--brand);
  pointer-events: none;
}
.opt-chip .n { color: var(--ink-2); font-weight: 500; }
.opt-chip .p {
  font-size: 11px; font-weight: 400; color: var(--ink-3); font-family: var(--font-num);
  background: var(--border-2); padding: 1px 6px; border-radius: 4px;
}
.opt-chip.on {
  background: var(--brand-100); border-color: var(--brand-300);
}
.opt-chip.on .n { color: var(--brand); font-weight: 600; }
.opt-chip.on .p {
  background: var(--brand); color: #fff;
}

/* ----- 险种多选网格 ----- */
.ins-type-grid {
  display: flex; flex-wrap: wrap; gap: 8px;
}
.ins-chip {
  display: inline-flex; align-items: center; gap: 4px;
  padding: 6px 10px; border-radius: 8px;
  background: var(--surface); border: 1px solid var(--border);
  cursor: pointer; font-size: 13px; font-weight: 400; transition: all .15s;
  user-select: none;
}
.ins-chip input[type=checkbox] {
  width: 13px; height: 13px; margin: 0; accent-color: var(--brand);
  pointer-events: none;
}
.ins-chip span { color: var(--ink-2); }
.ins-chip.on {
  background: var(--brand-100); border-color: var(--brand-300);
}
.ins-chip.on span { color: var(--brand); font-weight: 600; }
.ins-chip .ins-amt {
  height: 28px; font-size: 12px; border-radius: 6px;
}
.ins-chip:not(.on) .ins-amt { display: none; }

/* ----- 衍生业务卡片 ----- */
.deriv-card {
  background: var(--surface); border: 1px solid var(--border-2);
  border-radius: var(--r-sm); margin-bottom: 10px; overflow: hidden;
  transition: border-color .15s, box-shadow .15s;
}
.deriv-card.open {
  border-color: var(--brand-300);
  box-shadow: 0 2px 8px rgba(22, 87, 204, .06);
}
.deriv-head {
  display: flex; align-items: center; justify-content: space-between;
  padding: 12px 14px; cursor: pointer;
  transition: background .12s;
}
.deriv-head:active { background: var(--border-2); }
.deriv-toggle {
  display: inline-flex; align-items: center; gap: 8px;
  font-size: 13px; font-weight: 400; color: var(--ink-1);
  cursor: pointer;
}
.deriv-toggle input[type=checkbox] {
  width: 16px; height: 16px; accent-color: var(--brand);
}
.deriv-hint {
  font-size: 11px; font-weight: 400; color: var(--ink-3);
  max-width: 50%; text-align: right;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.deriv-bd {
  display: none; padding: 0 14px 14px;
}
.deriv-card.open .deriv-bd { display: block; }

/* ----- 装潢列表行 ----- */
.decor-list { margin-top: 10px; }
.decor-row {
  display: flex; align-items: center; gap: 8px;
  padding: 10px 0; border-bottom: 1px dashed var(--border-2);
}
.decor-row:last-child { border-bottom: none; }
.decor-row .t {
  flex: 1; min-width: 0; font-size: 11px; font-weight: 400; color: var(--ink-1);
}
.decor-row .t .gp {
  font-size: 11px; color: var(--ink-3); font-weight: 400; margin-top: 2px;
  font-family: var(--font-num);
}
.decor-row .qty { width: 64px; flex-shrink: 0; }
.decor-row .price { width: 100px; flex-shrink: 0; }
.decor-row .qty input,
.decor-row .price input {
  height: 32px; font-size: 12px; text-align: center;
}
.decor-row .btn.xs {
  height: 28px; padding: 0 8px; font-size: 11px;
  font-weight: 400;
  flex-shrink: 0;
}

/* ----- 步骤间过渡动画 ----- */
#step-body > .card {
  animation: fadeSlideIn .2s ease;
}
@keyframes fadeSlideIn {
  from { opacity: 0; transform: translateY(8px); }
  to { opacity: 1; transform: translateY(0); }
}

/* ----- sheet 内步骤指示器 sticky（在 sheet-bd 滚动时粘到 sheet-hd 下方）----- */
.sheet-bd > #stepper {
  position: sticky; top: 0; z-index: 10;
  background: #ffffff;            /* 明确实色（避免 var(--surface) 在 iOS WebView 下表现不一致） */
  padding: 8px 16px 10px;
  border-bottom: 1px solid var(--border-2);
  box-shadow: 0 2px 6px rgba(15, 23, 42, .06);  /* 与下方 step-body 第一张卡片形成清晰分层 */
  flex-shrink: 0;
}
.sheet-bd > #stepper .stepper { padding: 6px 0 2px; }
.sheet-bd > #step-body {
  padding: 18px 16px 12px;        /* 加大上间距：避免 step-body 首张卡片与 stepper 贴太近 */
}
.sheet-bd > #step-foot {
  border-top: 1px solid var(--border-2);
  padding: 12px 16px; margin: 0;
  background: var(--surface);
  flex-shrink: 0;
  display: flex; gap: 10px; align-items: center;
  /* sheet-bd 滚到底自动可见，无需再 sticky bottom */
}

/* 步骤底部按钮导航：上一步窄 / 下一步宽，两端铺满 */
.step-nav { display: flex; gap: 10px; width: 100%; }
.step-nav .prev,
.step-nav .draft { flex: 1; }                     /* 上一步 / 存草稿：短 */
.step-nav .next,
.step-nav .submit { flex: 2.6; }                 /* 下一步 / 提交：长 */

/* ----- 其他衍生 大卡片 ----- */
.deriv-umbrella {
  border: 1px solid var(--brand-200);
  border-radius: var(--r-sm);
  margin-bottom: 10px; overflow: hidden;
  background: var(--brand-50);
}
.du-head {
  display: flex; align-items: center; gap: 10px;
  padding: 10px 14px; background: var(--brand-100);
  cursor: pointer; user-select: none;
}
.du-head .du-caret {
  margin-left: auto;
  width: 0; height: 0;
  border-left: 5px solid transparent;
  border-right: 5px solid transparent;
  border-top: 6px solid var(--brand);
  transition: transform .2s var(--ease);
}
.deriv-umbrella.open .du-head .du-caret { transform: rotate(180deg); }
.deriv-umbrella:not(.open) .du-bd { display: none; }
.deriv-umbrella.open .du-bd { display: block; padding: 8px 10px; }
.du-title { font-size: 13px; font-weight: 400; color: var(--brand); }
.du-hint { font-size: 11px; font-weight: 400; color: var(--ink-3); }

/* ----- 确认页衍生业务分组 ----- */
.deriv-group { margin-top: 10px; }
.deriv-group:first-child { margin-top: 0; }
.deriv-group-title {
  font-size: 11px; color: var(--ink-3);
  font-weight: 400; margin-bottom: 2px;
  letter-spacing: .3px;
}
.gift-flag {
  display: inline-block; margin-left: 4px; padding: 1px 7px; border-radius: 10px;
  font-size: 11px; font-weight: 400; letter-spacing: 0;
  color: var(--orange); background: var(--orange-bg); vertical-align: middle;
}
.deriv-row {
  display: flex; justify-content: space-between; gap: 12px; align-items: flex-start;
  padding: 7px 0; font-size: 11px;
  font-weight: 400;
  border-bottom: 1px dashed var(--border-2);
}
.deriv-row:last-child { border-bottom: none; }
.dr-name {
  flex: 1 1 auto; min-width: 0;
  color: var(--ink-1);
  word-break: break-all; line-height: 1.5;
}
.dr-amt {
  flex: 0 0 auto;
  color: var(--brand); font-weight: 600;
  font-family: var(--font-num);
  white-space: nowrap;
}
.du-hint { font-size: 11px; font-weight: 400; color: var(--brand-600); }
.du-bd { padding: 10px; }
.du-bd .deriv-card { margin-bottom: 8px; background: var(--surface); }
.du-bd .deriv-card:last-child { margin-bottom: 0; }

/* ----- 可搜索多选弹层（名称/编码搜索）----- */
.sp-mask {
  position: fixed; inset: 0; z-index: 300;
  background: rgba(0,0,0,.45);
  display: flex; align-items: flex-end; justify-content: center;
}
.sp-panel {
  width: 100%; max-width: 560px;
  background: var(--surface);
  border-radius: 16px 16px 0 0;
  max-height: 82vh; display: flex; flex-direction: column;
  animation: slideUp .2s ease;
}
@keyframes slideUp { from { transform: translateY(100%); } to { transform: translateY(0); } }
.sp-hd {
  display: flex; align-items: center; justify-content: space-between;
  padding: 14px 16px; border-bottom: 1px solid var(--border-2);
}
.sp-hd h4 { margin: 0; font-size: 16px; }
.sp-close { font-size: 22px; color: var(--ink-3); cursor: pointer; line-height: 1; }
.sp-search { position: relative; padding: 12px 16px; }
.sp-search .ico { position: absolute; left: 26px; top: 50%; transform: translateY(-50%); font-size: 14px; color: var(--ink-3); pointer-events: none; }
.sp-search .input { padding-left: 32px; }
.sp-list { flex: 1; overflow: auto; padding: 0 16px 8px; }
.sp-item {
  display: flex; align-items: center; gap: 10px;
  padding: 12px 0; border-bottom: 1px solid var(--border-2); cursor: pointer;
}
.sp-item:last-child { border-bottom: none; }
.sp-item input[type=checkbox] { width: 18px; height: 18px; accent-color: var(--brand); flex-shrink: 0; }
.sp-item .n {
  flex: 1; min-width: 0;                  /* flex 子项 ellipsis 关键 */
  display: flex; flex-direction: column; gap: 2px;
}
.sp-item .n .name {
  font-size: 13px; color: var(--ink-1); font-weight: 400;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.sp-item .n .c {
  font-size: 11px; font-weight: 400; color: var(--ink-3); font-family: var(--font-num);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.sp-item .p {
  font-size: 13px; color: var(--ink-2); font-weight: 400;
  font-family: var(--font-num); flex-shrink: 0;
}
.sp-item.on .n .name { color: var(--brand); font-weight: 600; }
.sp-foot { display: flex; gap: 10px; padding: 12px 16px; border-top: 1px solid var(--border-2); }
.sp-foot .btn { flex: 1; }
/* ----- 装潢搜索弹层：常用收藏 tab + 星标 ----- */
.sp-tabs { display: flex; gap: 8px; padding: 10px 16px 0; }
.sp-tab { font-size: 13px; font-weight: 400; padding: 6px 12px; border-radius: 16px; background: var(--surface-2); color: var(--ink-3); cursor: pointer; }
.sp-tab.on { background: var(--brand-50); color: var(--brand); font-weight: 600; }
.sp-star { font-size: 20px; line-height: 1; color: var(--ink-3); cursor: pointer; flex-shrink: 0; padding: 0 4px; user-select: none; }
.sp-star.on { color: #f5a623; }

/* ----- 已选明细行（装潢/保养/商业/延保/选装）----- */
.item-list { margin-top: 10px; }
.item-row {
  display: flex; align-items: center; gap: 8px;
  padding: 10px 0; border-bottom: 1px dashed var(--border-2);
}
.item-row:last-child { border-bottom: none; }
.item-row .t { flex: 1; min-width: 0; font-size: 11px; font-weight: 400; color: var(--ink-1); }
.item-row .t .gp { font-size: 11px; color: var(--ink-3); font-weight: 400; margin-top: 2px; font-family: var(--font-num); }
.item-row .qty { width: 60px; flex-shrink: 0; }
.item-row .price { width: 100px; flex-shrink: 0; }
.item-row .qty input, .item-row .price input { height: 32px; font-size: 12px; text-align: center; }
.item-row .btn.x { height: 28px; padding: 0 8px; font-size: 11px; font-weight: 400; flex-shrink: 0; }
.pick-btn { margin-bottom: 4px; }
/* 装潢件三类（集采/主机厂/外采）分类标签 */
.cat-tag {
  display: inline-block; font-size: 11px; line-height: 1; font-weight: 400;
  padding: 2px 5px; border-radius: 4px; margin-right: 5px; vertical-align: 1px;
  color: #fff; background: var(--brand); flex-shrink: 0;
}
.cat-tag + .name { display: inline; }

/* =========================================================
 * 订单看板（H5 企微端）
 * ========================================================= */
.dash { padding: 12px 12px 24px; }
.dash-filter { display: flex; flex-direction: column; gap: 10px; margin-bottom: 14px; }
.dash-row { display: flex; align-items: center; gap: 10px; }
.dash-lbl { font-size: 11px; font-weight: 400; color: var(--ink-3); flex-shrink: 0; width: 36px; text-align: right; }
.seg {
  /* 苹果式 segmented control：iOS 灰 + 白滑块 */
  display: flex; background: rgba(120, 120, 128, 0.12);
  border-radius: 9px; padding: 2px;
  gap: 0; overflow-x: auto; -webkit-overflow-scrolling: touch; flex: 1; min-width: 0;
}
.seg-item {
  flex: 1; min-width: 52px; text-align: center; font-size: 13px; padding: 6px 12px;
  border-radius: 7px; color: var(--ink-1); cursor: pointer; white-space: nowrap; user-select: none;
  transition: background .15s, color .15s, box-shadow .15s;
  font-weight: 400;
  display: inline-flex; align-items: center; justify-content: center; gap: 5px;
}
.seg-item:not(.active):hover { background: rgba(120, 120, 128, 0.06); }
.seg-item.active {
  background: var(--surface); color: var(--ink-1);
  font-weight: 600;
  box-shadow: 0 3px 8px rgba(0,0,0,.08), 0 1px 1px rgba(0,0,0,.04);
}
.seg-item.active .ico { color: var(--brand); }

/* KPI 卡片 */
.kpi {
  display: flex; align-items: center; gap: 14px; background: var(--card);
  border-radius: 14px; padding: 16px; margin-bottom: 12px;
  box-shadow: 0 1px 3px rgba(0,0,0,.04);
}
.kpi-main { flex: 1; min-width: 0; }
.kpi-num { font-size: 34px; font-weight: 700; color: var(--ink-1); font-family: var(--font-num); line-height: 1.1; }
.kpi-cap { font-size: 11px; font-weight: 400; color: var(--ink-3); margin-top: 4px; }
.cmp { display: flex; flex-direction: column; align-items: flex-end; font-size: 11px; font-weight: 400; line-height: 1.5; }
.cmp-label { color: var(--ink-3); font-size: 11px; font-weight: 400; }
.cmp-sym { font-size: 11px; font-weight: 400; }
.cmp-val { font-weight: 700; font-family: var(--font-num); }
.cmp.up { color: #16a34a; }
.cmp.down { color: #dc2626; }
.cmp.muted { color: var(--ink-3); }

/* 趋势图卡片 */
.dash-trend, .dash-rank { margin-bottom: 12px; }
.trend-svg { display: block; width: 100%; margin-top: 6px; }
.empty { padding: 24px; text-align: center; color: var(--ink-3); font-size: 11px; font-weight: 400; }

/* 维度排名榜（多维度块状布局：每个维度一块） */
.dash-rank { padding: 0; }
.rank-block { padding: 12px 14px; border-bottom: 1px solid var(--border-2); }
.rank-block:last-child { border-bottom: none; }
.rank-block-h {
  font-size: 13px; font-weight: 400; color: var(--ink-2); margin-bottom: 8px;
  display: flex; align-items: center; gap: 6px;
}
.rank-block-h::before {
  content: ''; display: inline-block; width: 3px; height: 12px;
  background: var(--brand); border-radius: 2px;
}
.rank-empty { color: var(--ink-3); font-size: 11px; font-weight: 400; padding: 4px 0; }
.rank-row {
  display: flex; align-items: center; gap: 8px; padding: 7px 0;
  border-bottom: 1px dashed var(--border-2); font-size: 13px;
  font-weight: 400;
}
.rank-row:last-child { border-bottom: none; }
.rank-row .rk { width: 18px; color: var(--ink-3); font-family: var(--font-num); flex-shrink: 0; text-align: center; }
.rank-row .rn { width: 96px; flex-shrink: 0; color: var(--ink-1); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.rank-row .rbar { flex: 1; height: 14px; background: var(--surface-2); border-radius: 7px; overflow: hidden; }
.rank-row .rbar i { display: block; height: 100%; background: linear-gradient(90deg, var(--brand), #60a5fa); border-radius: 7px; transition: width .3s; }
.rank-row .rc { width: 38px; text-align: right; font-weight: 700; font-family: var(--font-num); color: var(--ink-1); flex-shrink: 0; }

/* ---------- 多选下拉 UI.MSelect ---------- */
.mselect { position: relative; display: block; width: 100%; }
/* v114.6.9.44 删除：`.mselect-trigger{min-height:38px;padding:4px 28px 4px 10px;
 *   border:1px solid var(--border);border-radius:8px;background:#fff;font-size:14px;…}`
 *   + `:hover{border-color:var(--brand)}` + `:focus{…}`
 *   （这是筛选器第 2 种样式：38px 高 / radius 8 / 14px 字，比销量看板高一头）
 *   取值已并入上方「全站筛选器胶囊唯一规范」段，基线取 `.sales-sel-trigger`。
 *   本文件里 `body.mselect-open` 那条不受影响。 */
.mselect-trig-inner { flex: 1; min-width: 0; display: flex; flex-wrap: wrap; gap: 4px; align-items: center; }
/* 占位文字与销量看板 `.ss-val.ph` 对齐：ink-3 + weight 400（规范段给的是 500） */
.mselect-ph { color: var(--ink-3); font-weight: 400; }
.mselect-ph.hide { display: none; }
.mselect-chip {
  display: inline-flex; align-items: center; gap: 4px; padding: 2px 4px 2px 8px;
  background: var(--brand-50); color: var(--brand); border-radius: 4px;
  font-size: 12px; line-height: 1.4; max-width: 180px; min-width: 0;
}
.mselect-chip-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.mselect-x {
  display: inline-flex; align-items: center; justify-content: center;
  width: 16px; height: 16px; border-radius: 50%; cursor: pointer; font-size: 14px;
  color: var(--brand); opacity: .7; flex-shrink: 0;
}
.mselect-x:hover { opacity: 1; background: rgba(0,0,0,.06); }
.mselect-arrow { position: absolute; right: 10px; top: 50%; transform: translateY(-50%); color: var(--ink-3); font-size: 12px; pointer-events: none; }
.mselect-count {
  position: absolute; right: 26px; top: 50%; transform: translateY(-50%);
  background: var(--brand); color: #fff; font-size: 11px; line-height: 14px;
  padding: 0 5px; border-radius: 7px; min-width: 14px; text-align: center;
}
.mselect-pop {
  position: fixed;  /* 改 fixed：跳出 dialog 的 overflow:hidden 截断，并避坑 absolute + viewport(top) 混算导致弹层飘走（肉哥 8/25 反馈） */
  z-index: 1000;    /* 浮在 dialog 顶部 */
  background: #fff; border: 1px solid var(--border);
  border-radius: 8px; box-shadow: 0 12px 32px rgba(15, 23, 42, .22);
  width: 300px;              /* v43 关键：硬撑 width，flex 在 iOS WKWebView 上会塌 */
  height: 320px;             /* v43 关键：硬撑 height，flex 在 iOS WKWebView 上会塌 */
  display: flex; flex-direction: column;
  box-sizing: border-box; overflow: hidden;
}
.mselect-search { padding: 8px; border-bottom: 1px solid var(--border-2); flex-shrink: 0; }
.mselect-search input {
  width: 100%; height: 32px; padding: 0 10px; border: 1px solid var(--border);
  border-radius: 6px; font-size: 13px; outline: none; box-sizing: border-box;
}
.mselect-search input:focus { border-color: var(--brand); }
.mselect-list {
  flex: 1 1 auto;
  min-height: 0;             /* v43 关键：flex 子项设 min-height:0 才能 overflow */
  height: 232px;             /* v43 关键：硬撑 height 让 iOS WKWebView 知道可滚 */
  overflow-y: auto; overflow-x: hidden;
  -webkit-overflow-scrolling: touch;
  overscroll-behavior: contain;
  /* v43 删除：touch-action: pan-y; transform: translateZ(0); will-change: transform;
     这三样在 iOS 企业微信内置 WKWebView 上反而破坏 overflow 滚动（亲测无效） */
}
.mselect-item {
  display: flex; align-items: center; gap: 8px; padding: 8px 12px; cursor: pointer; font-size: 14px;
  user-select: none;
}
.mselect-item:hover { background: var(--surface-2); }
.mselect-cb {
  width: 16px; height: 16px; border: 1.5px solid var(--border); border-radius: 3px; flex-shrink: 0;
  display: inline-flex; align-items: center; justify-content: center; transition: all .15s;
}
.mselect-item.on .mselect-cb { background: var(--brand); border-color: var(--brand); }
.mselect-item.on .mselect-cb::after {
  content: ''; width: 9px; height: 5px; border-left: 2px solid #fff; border-bottom: 2px solid #fff;
  transform: rotate(-45deg) translate(1px, -1px);
}
.mselect-name { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.mselect-foot {
  display: flex; gap: 8px; justify-content: flex-end; padding: 8px 12px;
  border-top: 1px solid var(--border-2); background: var(--surface-2);
  flex-shrink: 0;
}

/* ===== 订单看板 v33 新增样式 ===== */
.card-h { padding: 12px 14px; font-size: 13px; font-weight: 400; color: var(--ink-1); border-bottom: 1px solid var(--border-2); }
.dash-pills { flex-wrap: wrap; gap: 8px; }
.dash-pill { flex: 1 1 calc(50% - 4px); min-width: 130px; }
.dash-pill .mselect { width: 100%; }
.dash-scope { font-size: 11px; font-weight: 400; color: var(--ink-3); margin: -6px 4px 12px; }

/* 渗透率环 */
.pen-wrap { display: flex; flex-wrap: wrap; gap: 8px 4px; padding: 12px 14px; justify-content: space-between; }
.pen-item { flex: 1 1 18%; min-width: 88px; text-align: center; }
.pen-svg { display: flex; justify-content: center; }
.pen-label { font-size: 11px; font-weight: 400; color: var(--ink-2); margin-top: 2px; }

/* 排名 tab + 展开全部
 * v114.6.9.44 删除：`.seg-tab{display:flex;flex-wrap:wrap;gap:6px;margin:0 14px 8px}` +
 *   `.seg-tab .seg-item{font-size:12px;padding:4px 12px}` —— 这两条让 #rank-tab /
 *   #iv-cur-tab / #iv-proj-tab 与 #iv-subtab 又不一样（第 3 种 tab 视觉）。
 *   取值已并入「全站表头 Tab 唯一规范」段；卡片内的 .seg-tab 由该段的
 *   `.card > .seg-tab{margin-left/right:14px}` 对齐 .card-h 的 14px 内边距。
 *   （本类仍被 page-dashboard.js 的 #rank-tab、page-inventory.js 的
 *     #iv-cur-tab / #iv-proj-tab 用作 class，不能删 class 名，只是不再在此定义。） */
.rank-more { text-align: center; font-size: 11px; font-weight: 400; color: var(--brand); padding: 8px 0 6px; cursor: pointer; }

/* 订单总量维度拆解 */
.brk-total { font-size: 13px; font-weight: 400; color: var(--ink-1); padding: 12px 14px 6px; }
.brk-total b { font-size: 22px; color: var(--brand); font-family: var(--font-num); }
.brk-row { display: flex; align-items: center; gap: 8px; padding: 6px 14px 0; }
.brk-dim { font-size: 13px; font-weight: 400; color: var(--ink-2); width: 56px; flex-shrink: 0; text-align: right; }
.brk-bar { flex: 1; height: 16px; border-radius: 8px; overflow: hidden; display: flex; background: var(--surface-2); }
.brk-bar i { height: 100%; transition: width .3s; }
.brk-legend { font-size: 11px; font-weight: 400; color: var(--ink-3); padding: 2px 14px 8px 70px; line-height: 1.5; }
.mselect-fallback { width: 100%; min-height: 34px; padding: 4px; border: 1px solid var(--border); border-radius: 8px; }

/* ============================================================
 * 库存看板（板块四） v1  2026-08-26
 * 复用：card / dash-pill / seg-tab / rank-row / hint / empty
 * ============================================================ */
.inv-sub { font-size: 11px; font-weight: 400; color: var(--ink-3); }

/* 风险条 — 苹果风：浅灰底 + 左侧细色条，轻量不厚重 */
.inv-risk { display: flex; align-items: center; gap: 8px; margin: 10px 14px 0;
  padding: 10px 14px; border-radius: 10px; font-size: 13px;
  font-weight: 400;
  background: var(--surface); border: 1px solid var(--border);
  position: relative; overflow: hidden;
}
.inv-risk::before {
  content: ''; position: absolute; left: 0; top: 0; bottom: 0;
  width: 3px; background: #9aa0a6;
}
.inv-risk-dot { width: 8px; height: 8px; border-radius: 50%; flex-shrink: 0; background: #9aa0a6; }
.inv-risk.red::before { background: var(--red); }
.inv-risk.red .inv-risk-dot { background: var(--red); }
.inv-risk.red .inv-risk-lv { color: var(--red); }
.inv-risk.yellow::before { background: var(--orange); }
.inv-risk.yellow .inv-risk-dot { background: var(--orange); }
.inv-risk.yellow .inv-risk-lv { color: var(--orange); }
.inv-risk.green::before { background: var(--green); }
.inv-risk.green .inv-risk-dot { background: var(--green); }
.inv-risk.green .inv-risk-lv { color: var(--green); }
.inv-risk.none { color: var(--ink-3); }
.inv-risk-lv { font-weight: 600; flex-shrink: 0; letter-spacing: -.01em; }
.inv-risk-msg { color: var(--ink-2); flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.inv-risk-cnt b { font-family: var(--font-num); }
.inv-risk-cnt .red { color: var(--red); }
.inv-risk-cnt .yellow { color: var(--orange); margin-left: 6px; }
.inv-risk-date { font-size: 11px; font-weight: 400; color: var(--ink-3); flex-shrink: 0; }

/* KPI 四卡 — 苹果式：轻盈字重大字号 */
.inv-kpis { display: grid; grid-template-columns: repeat(2, 1fr); gap: 10px; margin: 10px 14px; }
.inv-kpi { background: var(--surface); border: 1px solid var(--border); border-radius: 14px; padding: 14px 16px; }
.inv-kpi .num { font-size: 30px; font-weight: 600; font-family: var(--font-num); color: var(--ink-1); line-height: 1.15; letter-spacing: -.02em; }
.inv-kpi .cap { font-size: 11px; color: var(--ink-2); margin-top: 4px; font-weight: 400; }
.inv-kpi .sub { font-size: 11px; font-weight: 400; color: var(--ink-3); margin-top: 6px; line-height: 1.5; }
.inv-kpi .sub b { font-family: var(--font-num); }
.inv-kpi.lv-yellow { border-color: var(--border); background: linear-gradient(180deg, #fffbeb 0%, var(--surface) 60%); }
.inv-kpi.lv-yellow .num { color: var(--orange); }
.inv-kpi.lv-red { border-color: var(--border); background: linear-gradient(180deg, #fef2f2 0%, var(--surface) 60%); }
.inv-kpi.lv-red .num { color: var(--red); }

/* 库龄环形 + 图例 */
.inv-age { padding: 12px 14px; }
.inv-age-wrap { display: flex; align-items: center; gap: 16px; }
.inv-donut { flex-shrink: 0; }
.inv-legend { flex: 1; min-width: 0; }
.inv-legend-row { display: flex; align-items: center; gap: 8px; padding: 3px 0; font-size: 11px; font-weight: 400; }
.inv-legend-row .dot { width: 8px; height: 8px; border-radius: 2px; flex-shrink: 0; }
.inv-legend-row .lb { width: 64px; color: var(--ink-2); flex-shrink: 0; }
.inv-legend-row .bar { flex: 1; height: 6px; border-radius: 3px; background: var(--surface-2); overflow: hidden; }
.inv-legend-row .bar i { display: block; height: 100%; }
.inv-legend-row .ct { color: var(--ink-1); font-family: var(--font-num); flex-shrink: 0; font-size: 11px; font-weight: 400; }

/* 风险预警卡 — 苹果风：白底细边框 + 左侧色条，去大幅色彩 */
.inv-alert { display: flex; align-items: flex-start; gap: 8px; margin: 6px 14px; padding: 10px 12px;
  border-radius: 10px; font-size: 13px; font-weight: 400; line-height: 1.5;
  background: var(--surface); border: 1px solid var(--border); color: var(--ink-2);
  position: relative; overflow: hidden;
}
.inv-alert::before {
  content: ''; position: absolute; left: 0; top: 0; bottom: 0;
  width: 3px;
}
.inv-alert .tag { flex-shrink: 0; width: 18px; height: 18px; border-radius: 6px; font-size: 11px;
  color: #fff; display: flex; align-items: center; justify-content: center; margin-top: 1px; font-weight: 400; }
.inv-alert.red::before { background: var(--red); }
.inv-alert.red { color: var(--ink-1); }
.inv-alert.red .tag { background: var(--red); }
.inv-alert.yellow::before { background: var(--orange); }
.inv-alert.yellow { color: var(--ink-1); }
.inv-alert.yellow .tag { background: var(--orange); }
.inv-alert.none { justify-content: center; background: var(--bg); color: var(--ink-3); border-color: var(--border-2); }
.inv-alert.none::before { display: none; }

/* ============================================================
 *  v69 肉哥 2026-08-28 新增：拷车预警 + 绩效预警
 *  沿用苹果/NIO 扁平风：白底 + 1px border + 左侧 3px 细色条 + 状态色徽章
 * ============================================================ */

/* 拷车预警 / 绩效预警 共用：状态徽章（绿=pass / 红=block / 黄=reminder/risk / 灰=na） */
.iv-transfer-summary, .iv-perf-summary {
  display: flex; align-items: center; gap: 10px;
  margin: 12px 14px 8px; padding: 10px 12px;
  border-radius: 10px; background: var(--surface);
  border: 1px solid var(--border); position: relative; overflow: hidden;
}
.iv-transfer-summary::before, .iv-perf-summary::before {
  content: ''; position: absolute; left: 0; top: 0; bottom: 0; width: 3px;
}
.iv-transfer-summary.allow::before, .iv-perf-summary.safe::before { background: var(--green); }
.iv-transfer-summary.block::before, .iv-perf-summary.risk::before { background: var(--red); }

.iv-transfer-summary .badge, .iv-perf-summary .badge {
  font-size: 13px; font-weight: 400; padding: 4px 12px;
  border-radius: 8px; flex-shrink: 0;
}
.iv-transfer-summary .hint, .iv-perf-summary .hint {
  font-size: 11px; font-weight: 400; color: var(--ink-2);
}

/* v75：今日+5天 自动预判说明条 */
.inv-plan-note {
  margin: 8px 14px 0;
  padding: 6px 10px;
  font-size: 11px; font-weight: 400; line-height: 1.5;
  color: var(--orange, #b26a00);
  background: rgba(255, 153, 0, 0.08);
  border: 1px solid rgba(255, 153, 0, 0.25);
  border-radius: 8px;
}

/* v76 肉哥 2026-08-28：拷车预警（今日+5天预判）独立卡片置顶，强化预警感 */
.iv-card-transfer-plan {
  border-color: rgba(245, 158, 11, 0.45);
  box-shadow: 0 1px 0 rgba(245, 158, 11, 0.18);
}
.iv-plan-wrap { margin: 8px 14px 12px; display: flex; flex-direction: column; gap: 10px; }
.iv-plan-section {
  border: 1px solid var(--border); border-radius: 10px; padding: 10px 12px;
  background: var(--surface); position: relative; overflow: hidden;
}
.iv-plan-section::before {
  content: ''; position: absolute; left: 0; top: 0; bottom: 0; width: 3px;
}
.iv-plan-section.pass::before { background: var(--green); }
.iv-plan-section.block::before { background: var(--red); }
.iv-plan-sec-h { display: flex; align-items: center; gap: 8px; margin-bottom: 6px; }
.iv-plan-sec-name { font-size: 13px; font-weight: 400; color: var(--ink-1); flex: 1; }
.iv-plan-metrics { display: flex; flex-direction: column; gap: 3px; font-size: 13px; font-weight: 400; color: var(--ink-2); }
.iv-plan-metrics b { font-weight: 600; }
.iv-plan-metrics b.ok { color: var(--green); }
.iv-plan-metrics b.err { color: var(--red); }
.iv-plan-block { margin-top: 8px; padding: 8px 10px; border-radius: 8px; }
.iv-plan-block.within60, .iv-plan-block.over180 {
  background: rgba(239, 68, 68, 0.06); border: 1px solid rgba(239, 68, 68, 0.25);
}
.iv-plan-block.pass {
  background: rgba(16, 185, 129, 0.06); border: 1px solid rgba(16, 185, 129, 0.25);
}
.iv-plan-block-msg { font-size: 11px; font-weight: 400; color: var(--ink-1); line-height: 1.5; }
.iv-plan-block-action { font-size: 11px; font-weight: 400; color: var(--red); margin-top: 4px; }

/* 5 条规则 / 2 条规则的列表 */
.iv-rule-list { margin: 4px 14px 12px; display: flex; flex-direction: column; gap: 8px; }
.iv-rule-item {
  border: 1px solid var(--border); border-radius: 10px; padding: 10px 12px;
  background: var(--surface); position: relative; overflow: hidden;
}
.iv-rule-item::before {
  content: ''; position: absolute; left: 0; top: 0; bottom: 0; width: 3px;
}
.iv-rule-item.pass::before { background: var(--green); }
.iv-rule-item.block::before { background: var(--red); }
.iv-rule-item.reminder::before, .iv-rule-item.risk::before { background: var(--orange); }
.iv-rule-item.na::before { background: var(--border); }

.iv-rule-hd { display: flex; align-items: center; gap: 8px; }
.iv-rule-ico {
  width: 18px; height: 18px; border-radius: 50%;
  display: inline-flex; align-items: center; justify-content: center;
  font-size: 11px; font-weight: 700; color: #fff; flex-shrink: 0;
}
.iv-rule-item.pass .iv-rule-ico { background: var(--green); }
.iv-rule-item.block .iv-rule-ico { background: var(--red); }
.iv-rule-item.reminder .iv-rule-ico, .iv-rule-item.risk .iv-rule-ico { background: var(--orange); }
.iv-rule-item.na .iv-rule-ico { background: var(--ink-3); }

.iv-rule-name { font-size: 13px; font-weight: 400; color: var(--ink-1); flex: 1; }
.iv-rule-val { font-size: 13px; font-weight: 400; color: var(--ink-2); }
.iv-rule-val b { color: var(--ink-1); font-weight: 400; font-size: 13px; }
.iv-rule-deduct {
  font-size: 11px; font-weight: 400; color: #fff;
  background: var(--red); padding: 2px 7px; border-radius: 6px;
  margin-left: 4px;
}
.iv-rule-msg { font-size: 11px; font-weight: 400; color: var(--ink-2); line-height: 1.5; margin-top: 4px; }
.iv-rule-action {
  font-size: 11px; font-weight: 400; color: var(--red);
  background: rgba(239, 68, 68, 0.06); padding: 6px 10px;
  border-radius: 6px; margin-top: 6px;
}
.iv-rule-item.reminder .iv-rule-action, .iv-rule-item.risk .iv-rule-action {
  color: var(--orange); background: rgba(245, 158, 11, 0.08);
}

/* 改进指引区 */
.iv-transfer-guidance {
  margin: 4px 14px 12px; padding: 10px 12px;
  border: 1px solid var(--border); border-radius: 10px; background: var(--bg);
}
.iv-guidance-h { font-size: 13px; font-weight: 400; color: var(--ink-1); margin-bottom: 6px; }
.iv-transfer-guidance ul { margin: 0; padding-left: 18px; color: var(--ink-2); font-size: 13px; font-weight: 400; line-height: 1.6; }
.iv-transfer-guidance li { margin: 2px 0; }

/* 大盘指标提示（list 模式顶部） */
.iv-transfer-grouphint {
  display: flex; gap: 14px; margin: 10px 14px 8px; flex-wrap: wrap;
  font-size: 13px; font-weight: 400; color: var(--ink-2);
}
.iv-grouphint-item {
  background: var(--bg); border: 1px solid var(--border-2);
  padding: 5px 10px; border-radius: 6px;
}
.iv-grouphint-item b { color: var(--ink-1); margin-right: 4px; }
.iv-grouphint-item i { font-style: normal; margin-left: 2px; }
.iv-grouphint-item i.ok { color: var(--green); font-weight: 700; }
.iv-grouphint-item i.err { color: var(--red); font-weight: 700; }

/* 拷车/绩效 列表表格 */
.iv-table-wrap { margin: 4px 14px 12px; }
.iv-transfer-table, .iv-perf-table {
  width: 100%; border-collapse: separate; border-spacing: 0; font-size: 13px;
  font-weight: 400;
  table-layout: fixed;
  /* v78 肉哥 2026-08-29：把 collapse 改成 separate;0 才能让 <thead>/<th> 上 sticky
     在 chromium / webkit 里稳定生效（collapse 模式在 iOS WebView 下偶发失效）。
     视觉无差异：原 border-bottom:1px 落在 th/td 上不需要靠 collapse 合并。 */
  /* v79 肉哥 2026-08-29：v78 的 thead sticky 没生效 —— 根因是 .iv-table-wrap 设置了
     overflow-x:auto，结果 wrap 变成了 scroll container（CSSOM 视图规定 overflow
     不全 visible 时即创建 scroll container & 滚动盒），导致 position:sticky 困在
     wrap 内贴不到 viewport 顶。修复：去掉 wrap 的 overflow:auto；table-layout:fixed
     确保宽列在手机屏不会横溢出，也就不需要 wrap 提供横滚。
     另外 thead 的 z-index 在主子元素里提到 10，防止 <th> 被同行 <td> 的横滑渲染遮住。 */
}
/* v78 肉哥 2026-08-29：销售顾问/总部下滑到表格中段时，
   表头要一直黏在 navbar 下方（top: var(--nav-h) 即 48px），
   否则他忘了每行字段含义只能再滑回最上面。
   background 必须用实色（var(--surface)=#fff），粘起来时叠盖行才不会漏底。
   v79：z-index 提高到 20，并显式设 inset:0 + background-clip:padding-box，
   避免 background 只覆盖到 text 区域而右侧 border 处透出来。 */
.iv-transfer-table thead th,
.iv-perf-table thead th {
  position: sticky;
  top: var(--nav-h);
  z-index: 20;
  background: var(--surface);
  background-clip: padding-box;
  box-shadow: 0 1px 0 var(--border), 0 4px 8px rgba(0, 0, 0, .04);
}
.iv-transfer-table th, .iv-perf-table th {
  text-align: left; padding: 8px 6px; color: var(--ink-2);
  font-weight: 500; font-size: 11px; border-bottom: 1px solid var(--border);
  /* background 由 thead th sticky 时单独覆盖；非 sticky 视图（如表被滚走）维持 transparent
     让上一张卡的色彩透过——但在 .iv-table-wrap 内白底卡片上，transparent 实际等同 surface。 */
  background: var(--surface);
}
.iv-transfer-table td, .iv-perf-table td {
  padding: 8px 6px; border-bottom: 1px solid var(--border-2); color: var(--ink-1);
  background: var(--surface);
}
.iv-transfer-table tr:hover, .iv-perf-table tr:hover { background: var(--bg); }
.iv-transfer-row.block td:first-child, .iv-perf-row.warning td:first-child, .iv-perf-row.high td:first-child {
  border-left: 2px solid var(--red);
}
.iv-cell-num { text-align: center; font-variant-numeric: tabular-nums; }
.iv-cell-num b.err { color: var(--red); }
.iv-cell-overall { text-align: center; }

/* 小徽章 ok/err/warn（用于表格里的"可拷/禁拷/安全/预警/高风险"） */
.iv-transfer-summary .badge.ok, .badge.ok.sm, .iv-perf-summary .badge.ok {
  background: rgba(16, 185, 129, 0.12); color: var(--green);
}
.iv-transfer-summary .badge.err, .badge.err.sm, .iv-perf-summary .badge.err {
  background: rgba(239, 68, 68, 0.12); color: var(--red);
}
.badge.warn.sm { background: rgba(245, 158, 11, 0.14); color: var(--orange); }
.badge.sm { display: inline-block; padding: 3px 8px; font-size: 13px; font-weight: 400; border-radius: 6px; }

/* 超龄明细表 — 苹果式：白底、淡分隔线，无色块 */
.inv-table { width: 100%; border-collapse: collapse; font-size: 13px; font-weight: 400; }
.inv-table th { text-align: left; font-weight: 500; color: var(--ink-3); padding: 8px 4px;
  border-bottom: 1px solid var(--border-2); white-space: nowrap; background: transparent; }
.inv-table td { padding: 9px 4px; border-bottom: 1px solid var(--border-2); color: var(--ink-1); vertical-align: top; }
.inv-table tr:last-child td { border-bottom: none; }
.inv-table .c-store { color: var(--ink-1); white-space: nowrap; font-weight: 500; }
.inv-table .c-series { white-space: nowrap; color: var(--ink-1); }
.inv-table .c-model { min-width: 90px; }
.inv-table .c-color { display: inline-block; margin-left: 4px; font-size: 11px; font-weight: 400; color: var(--ink-3); }
.inv-table .c-age { font-family: var(--font-num); font-weight: 600; white-space: nowrap; }
.inv-table .c-age i { display: block; font-style: normal; font-weight: 400; font-size: 11px; color: var(--ink-3); }
.inv-table .c-vin { font-family: ui-monospace, Menlo, Consolas, monospace; color: var(--ink-3); white-space: nowrap; }
.match-tag { display: inline-block; padding: 1px 6px; border-radius: 4px; font-size: 11px;
  font-weight: 400;
  background: var(--bg); color: var(--ink-2); border: 1px solid var(--border-2); white-space: nowrap; }
/* 2026-08-27 肉哥反馈：tab 末尾的 .cnt 角标视觉突兀，已删前端逻辑，对应 CSS 一起清理 */

/* 库销比排名（复用 rank-row，加副标注） */
.inv-sr .rn { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-weight: 500; }
.inv-sr .rbar { width: 96px; flex-shrink: 0; }
.inv-sr .rc { width: 42px; text-align: right; font-family: var(--font-num); font-weight: 600; flex-shrink: 0; letter-spacing: -.01em; }
.inv-sr.lv-red .rc { color: var(--red); }
.inv-sr.lv-yellow .rc { color: var(--orange); }
.inv-sr-sub { font-size: 11px; font-weight: 400; color: var(--ink-3); width: 84px; flex-shrink: 0; font-family: var(--font-num); }

/* 车系行内库龄结构堆叠条（5 档，颜色同库龄环形图） */
.rank-row.inv-sr { flex-wrap: wrap; row-gap: 0; }
.inv-agebar { flex: 0 0 100%; display: flex; height: 18px; border-radius: 4px; overflow: hidden; margin-top: 5px; }
.inv-agebar i { display: flex; align-items: center; justify-content: center; min-width: 0;
  font-style: normal; font-size: 10px; color: #fff; font-family: var(--font-num); overflow: hidden;
  font-weight: 500; }
/* 肉哥 2026-08-28：库龄占比窄色块字号自适配，避免数字被截 */
/* 亮色块（浅黄）上文字自动切深色，可读性更好 */
.inv-agebar i.iv-thin { font-size: 9px; letter-spacing: -0.3px; }
.inv-agebar i.iv-very-thin { font-size: 8px; letter-spacing: -0.5px; padding: 0 1px; }

/* ============================================================
 * 库存看板 v2  2026-08-27  9 个用户反馈全量迭代
 * ============================================================ */

/* mselect 弹层打开时禁用 body 滚动（解决 iOS 上整个界面被上滑问题） */
body.mselect-open { overflow: hidden; }
/* 关键修复：肉哥 2026-08-27 反馈下拉无法滚动。
   原因：之前 body 用 touch-action: none 锁住整个页面，连 mselect-list 内部的 overflow-y: auto 都被压死。
   改成 body 只 overflow:hidden（保留 iOS 上整页不滚动），列表单独 touch-action: pan-y 允许内部滚动。 */
.mselect-list {
  -webkit-overflow-scrolling: touch;
  overscroll-behavior: contain;
  touch-action: pan-y;
  /* 触发硬件加速层，避免 iOS WKWebView 在 overflow 祖先里不滚 */
  transform: translateZ(0);
  will-change: transform;
}

/* ============================================================
 * 库存看板 v3  2026-08-27  Tab 视觉重设计 + 车系卡片
 * ============================================================ */

/* 顶层两个 tab（分析视图 / 销售顾问视图）：
 * v114.6.9.44 肉哥 9/11「tab 样式全站统一，以库存看板为准」——
 *   原有 4 条规则（#iv-subtab 容器 / #iv-subtab .seg-item / #iv-subtab .seg-item.active，
 *   以及下方窄屏 media query 里的同名两条）**已全部删除**，
 *   改由下面「全站表头 Tab 唯一规范」那一段的逗号合并选择器组统一提供
 *   （.seg-tab 容器 + .seg-tab .seg-item + .seg-tab .seg-item.active）。
 *   ★ 这里**不能**再写任何 #iv-subtab 规则 —— id 选择器 (1,0,0)/(1,1,0) 特异性高于
 *     规范段的类组合，哪怕只写一条 margin 都会把规范局部打回原形。
 * 删掉的是（取值已并入规范段）：
 *   #iv-subtab { margin:4px 12px 12px; background:transparent; border-radius:0;
 *                padding:0; gap:8px; overflow:visible; flex:none; }
 *   #iv-subtab .seg-item { flex:1; min-width:0; font-size:14px; padding:12px 14px;
 *                border-radius:12px; background:#fff; border:1px solid var(--border);
 *                color:var(--ink-2); font-weight:500; …
 *                box-shadow:0 1px 2px rgba(15,23,42,.04); … }
 *   #iv-subtab .seg-item.active { background:linear-gradient(135deg,#3b82f6,#2563eb);
 *                color:#fff; font-weight:600; border-color:transparent;
 *                box-shadow:0 4px 12px rgba(37,99,235,.28); }
 * 新版边距 12px 测得的实际左边距仍是 14+12+12 = 38px，与肉哥"喜欢"的原样**完全一致**。
 */

/* 销售顾问视图：车系卡片（ERP 导出车系列可能为数字编码，UI 上明示"系列编码"以免肉哥误以为是车系名） */
.iv-series-card {
  border: 1px solid var(--border);
  border-radius: 12px;
  background: #fff;
  margin-bottom: 12px;
  overflow: hidden;
}
.iv-series-hd {
  display: flex; align-items: baseline; gap: 8px;
  padding: 12px 14px 8px;
  background: linear-gradient(180deg, #f8fafc 0%, #fff 100%);
  border-bottom: 1px solid var(--border-2);
}
.iv-series-name {
  font-size: 13px; font-weight: 400; color: var(--ink-1);
  font-family: var(--font-num);
}
.iv-series-tag {
  font-size: 11px; font-weight: 400; color: var(--ink-3);
  border: 1px solid var(--border-2);
  padding: 1px 6px; border-radius: 4px;
}
.iv-series-cnt {
  font-size: 13px; font-weight: 400; color: var(--ink-2);
  margin-left: auto;
}
.iv-series-cnt b { color: var(--brand); font-family: var(--font-num); margin: 0 2px; }

/* #4 单品牌/门店时库龄板块下加车系结构 */
.inv-donut-sub { margin-top: 14px; padding: 12px 16px 0; border-top: 1px dashed var(--border-2); }
.dash.inv .inv-donut-sub { padding: 12px 18px 0; }
.inv-donut-sub-t { font-size: 11px; color: var(--ink-2); margin-bottom: 8px; font-weight: 400; }

/* #5 预警按品牌分组 × 4 类 */
.inv-alert-legend { display: flex; flex-wrap: wrap; gap: 6px 12px; padding: 8px 14px 0; font-size: 11px; font-weight: 400; color: var(--ink-2); }
.iv-lgrp { display: inline-flex; align-items: center; gap: 4px; }
.iv-lgrp i { display: inline-block; width: 10px; height: 10px; border-radius: 2px; }
.iv-lgrp i.red { background: #ef4444; }
.iv-lgrp i.yellow { background: #f59e0b; }
.iv-lgrp i.green { background: #10b981; }
.iv-lgrp i.blue { background: #3b82f6; }

.inv-brand-block { padding: 10px 14px; border-bottom: 1px solid var(--border-2); }
.inv-brand-block:last-child { border-bottom: none; }
.iv-brand-h { font-size: 13px; font-weight: 400; color: var(--ink-1); margin-bottom: 6px; padding: 2px 0; }
.iv-brand-h em { font-style: normal; font-size: 11px; color: var(--ink-3); font-weight: 400; margin-left: 4px; }
.inv-alert-group { margin-bottom: 8px; }
.iv-grp-lbl { display: flex; align-items: center; gap: 6px; font-size: 13px; color: var(--ink-2); margin: 4px 0; font-weight: 400; }
.iv-grp-lbl em { font-style: normal; color: var(--ink-3); font-weight: 400; font-size: 11px; }
.iv-grp-lbl i { display: inline-block; width: 8px; height: 8px; border-radius: 50%; }
.iv-grp-lbl i.grp-ratio_brand_or_store { background: #ef4444; }
.iv-grp-lbl i.grp-ratio_series { background: #f59e0b; }
.iv-grp-lbl i.grp-long_age { background: #10b981; }
.iv-grp-lbl i.grp-heavy_stock { background: #3b82f6; }

/* #6 超期表格排版：列对齐、列宽稳定 — 苹果式：白底，无表头底色 */
.inv-table-wrap { overflow-x: auto; -webkit-overflow-scrolling: touch; }
.inv-table { width: 100%; border-collapse: separate; border-spacing: 0; font-size: 13px; font-weight: 400; }
.inv-table th, .inv-table td { padding: 9px 4px; border-bottom: 1px solid var(--border-2); text-align: left; vertical-align: top; }
.inv-table th { font-weight: 500; color: var(--ink-3); background: transparent; font-size: 11px; white-space: nowrap; }
.inv-table .c-brand { color: var(--ink-2); width: 56px; }
.inv-table .c-store { color: var(--ink-1); width: 80px; font-weight: 500; }
.inv-table .c-series { color: var(--ink-1); width: 84px; white-space: nowrap; }
.inv-table .c-model { color: var(--ink-1); }
.inv-table .c-color { display: inline-block; margin-left: 4px; font-size: 11px; font-weight: 400; color: var(--ink-3); }
.inv-table .c-status { color: var(--ink-2); width: 56px; font-size: 11px; font-weight: 400; }
.inv-table .c-age { font-family: var(--font-num); font-weight: 600; color: var(--red); width: 56px; text-align: right; white-space: nowrap; }
.inv-table .c-vin { font-family: ui-monospace, Menlo, Consolas, monospace; color: var(--ink-3); white-space: nowrap; width: 80px; }

/* #7 分车系图例 */
.inv-age-legend { display: flex; flex-wrap: wrap; gap: 4px 12px; padding: 0 14px 6px; font-size: 11px; font-weight: 400; color: var(--ink-2); }
.iv-age-leg { display: inline-flex; align-items: center; gap: 4px; }
.iv-age-leg i { display: inline-block; width: 10px; height: 10px; border-radius: 2px; }

/* #7 分车系删进度条后，只保留行内库龄堆叠条（已用 .inv-agebar 复用） */
.rank-row.inv-sr .rbar { display: none; } /* 删进度条 */
.rank-row.inv-sr .rc { width: 50px; }

/* #8 门店库销比：表格 + 品牌分组 + 5 天趋势 */
.inv-store-th { display: grid; grid-template-columns: 88px 64px 110px 50px; gap: 6px; padding: 6px 14px; font-size: 11px; color: var(--ink-2); background: var(--surface-2); border-radius: 6px 6px 0 0; font-weight: 600; }
.inv-store-th .th-trend { text-align: center; }
.inv-store-th .th-ratio { text-align: right; }
.inv-store-brand { margin: 8px 14px 0; border: 1px solid var(--border-2); border-radius: 8px; overflow: hidden; }
.inv-store-brand .iv-brand-h { padding: 6px 12px; background: var(--surface-2); border-bottom: 1px solid var(--border-2); margin: 0; }
.inv-store-table { width: 100%; border-collapse: collapse; font-size: 13px; font-weight: 400; }
.inv-store-table td { padding: 6px 12px; border-bottom: 1px solid var(--border-2); vertical-align: middle; }
.inv-store-table tr:last-child td { border-bottom: none; }
.inv-store-table .c-store { width: 88px; font-weight: 500; color: var(--ink-1); }
.inv-store-table .c-brand { width: 64px; color: var(--ink-2); font-size: 13px; font-weight: 400; }
.inv-store-table .c-trend { width: 110px; text-align: center; }
.inv-store-table .c-ratio { width: 50px; text-align: right; font-family: var(--font-num); font-weight: 600; letter-spacing: -.01em; }
.inv-store-row.lv-red .c-ratio { color: var(--red); }
.inv-store-row.lv-yellow .c-ratio { color: var(--orange); }
.inv-trend { display: inline-flex; align-items: center; gap: 6px; }
.inv-trend i { font-style: normal; font-family: var(--font-num); font-weight: 400; font-size: 13px; letter-spacing: -.01em; }

/* #9 销售顾问视图 */
.inv-sales-block { margin: 8px 14px 0; border: 1px solid var(--border); border-radius: 10px; overflow: hidden; }
.inv-sales-block .iv-brand-h { padding: 8px 12px; background: var(--bg); border-bottom: 1px solid var(--border-2); margin: 0; font-weight: 600; }
.inv-sales-block .inv-table th { font-size: 11px; padding: 8px 6px; }
.inv-sales-block .c-total b { font-size: 13px; color: var(--ink-1); font-weight: 400; }
.inv-sales-block .c-wh, .inv-sales-block .c-tr { font-family: var(--font-num); color: var(--ink-2); width: 50px; text-align: center; }
.inv-sales-block .c-old { font-family: var(--font-num); color: var(--ink-3); font-size: 11px; font-weight: 400; width: 64px; text-align: center; }
/* 已配/未配 tag — 苹果式：细边框浅灰底 */
.iv-match { display: inline-block; padding: 1px 6px; border-radius: 4px; font-size: 11px;
  background: var(--bg); color: var(--ink-1); border: 1px solid var(--border); font-family: var(--font-num); font-weight: 400; }
.iv-unm { display: inline-block; padding: 1px 6px; border-radius: 4px; font-size: 11px;
  background: var(--surface); color: var(--ink-3); border: 1px solid var(--border-2); font-family: var(--font-num); font-weight: 400; }

/* 二级 tab（库存分析 / 销售顾问）
 * v114.6.9.44 删除：`#iv-subtab{margin:0 12px 8px}` + `#iv-subtab .seg-item{font-size:13px;padding:6px 14px}`
 *   ★ 这两条在 media query 里，(1,0,0)/(1,1,0) 特异性**不受 media query 影响**，
 *     会无视源码顺序直接压掉末尾的规范段 → 必须删除，不能靠"后面覆盖"。
 *   取值已并入「全站表头 Tab 唯一规范」段（窄屏侧内边距由 @media(max-width:390px) 统一给到 9px）。 */

/* 销售视图筛选器行 */
#iv-view-sales .dash-pills { padding: 0 4px; }

/* ============================================================
 * 库存看板 v4  2026-08-27  肉哥反馈迭代
 *   - 数据隔离：顶部 🔒 提示条
 *   - 车系结构对齐：车系名最小宽度 110px、长名省略
 *   - 卡片宽松：每个 card 增加内边距、不顶到两边
 * ========================================================= */

/* 数据隔离提示条：放在子 tab 下、筛选器行上 — 苹果风：浅灰底 + 灰色文字，不卡视觉 */
.iv-locked {
  display: flex; align-items: center; gap: 6px;
  margin: 0 14px 12px;
  padding: 8px 12px;
  font-size: 11px;
  font-weight: 400;
  color: var(--ink-2);
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: 8px;
  line-height: 1.4;
  letter-spacing: .01em;
}
.iv-locked .ico { color: var(--ink-3); }

/* 车系结构图例：车系名齐头对齐（短名不漂、长名省略）
   关键修复：原 width:64px 撑不下 Q6L E-TRON 会换行 →
   改成 min-width: 110px + nowrap + ellipsis，强一致 */
.inv-legend-row .lb {
  width: 110px;             /* 固定宽度，统一所有车系名对齐 */
  min-width: 110px;         /* 防止短车系被挤压变窄 */
  color: var(--ink-2);
  flex-shrink: 0;
  text-align: left;         /* 左对齐，肉哥观察"长长短短"的核心问题 */
  font-size: 11px;
  font-weight: 400;
  line-height: 1.4;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;  /* Q6L E-TRON 撑不下也优雅省略 */
  padding-right: 8px;       /* 给 bar 让出呼吸位 */
}

/* 车系结构：圆环 + 图例之间的间距 */
.inv-age { padding: 14px 16px; }
.inv-age-wrap { gap: 18px; }

/* 库龄 + 车系图例：窄屏堆叠（donut 上、legend 下），避免 bar 被挤消失 */
@media (max-width: 540px) {
  .inv-age-wrap { flex-direction: column; align-items: stretch; gap: 14px; }
  .inv-donut { align-self: center; }
  .inv-legend-row .bar { min-width: 60px; }
}

/* 卡片整体视觉更宽松：由后续增强版控制（带 border + background） */

/* 分车系库销比行（rank-row.inv-sr）左 padding 与卡片内部齐 */
.rank-row.inv-sr {
  padding: 8px 16px;
  border-bottom: 1px solid var(--border-2);
}
.rank-row.inv-sr:last-child { border-bottom: none; }

/* 分车系库销比图例挪到 card 内部 padding 内，不贴顶 */
.inv-age-legend {
  padding: 4px 16px 8px;
}

/* 分车系库销比标题 + 描述左侧对齐 padding */
.dash.inv .inv-age-legend,
.dash.inv .inv-age,
.dash.inv .inv-alert-legend {
  padding-left: 16px;
  padding-right: 16px;
}

/* 风险预警整体加 padding 留白 */
.dash.inv .inv-alert { margin: 6px 16px; }

/* 超期明细表内边距 */
.dash.inv .inv-table-wrap { margin: 0 12px; }

/* 门店库销比卡片 — 不顶两边 + 内部数据块 padding */
.dash.inv #iv-store-card .inv-store-th {
  margin: 0 14px;
  padding: 8px 12px;
  border-radius: 8px;
  background: var(--bg);
  border: none;
  font-size: 11px;
  color: var(--ink-3);
  font-weight: 500;
}
.dash.inv #iv-store-card .inv-store-brand {
  margin: 10px 14px;
  border-radius: 12px;
  border: 1px solid var(--border);
}
.dash.inv #iv-store-card .inv-store-brand .iv-brand-h {
  padding: 9px 14px;
  font-size: 13px;
  font-weight: 400;
  background: var(--surface);
  border-bottom: 1px solid var(--border-2);
  color: var(--ink-1);
}
.dash.inv #iv-store-card .inv-store-table td {
  padding: 10px 14px;
}

/* 销售顾问视图卡：gap/间距与卡片标题一致 */
.dash.inv .iv-series-card {
  margin: 10px 14px 14px;
  border-radius: 12px;
  border: 1px solid var(--border);
  overflow: hidden;
}
.dash.inv .iv-series-hd {
  padding: 12px 14px 10px;
  background: var(--bg);
  border-bottom: 1px solid var(--border-2);
  display: flex; align-items: center; justify-content: space-between;
}
.dash.inv .iv-series-name { font-weight: 400; font-size: 13px; }
.dash.inv .iv-series-card .inv-table-wrap { margin: 0; }

/* 表头描述小字 (.inv-sub) 不强制 11px，库存看板里和正文同级 */
.dash.inv .card-h .inv-sub { font-size: 11px; font-weight: 400; margin-left: 4px; }

/* 通用：库存看板下的卡片整体紧凑、更接近苹果 */
.dash.inv .card {
  border-radius: 14px;
  box-shadow: 0 1px 3px rgba(15,23,42,.05);
  margin-bottom: 12px;
  border: 1px solid var(--border);
  background: var(--surface);
}
.dash.inv .card-h {
  padding: 14px 16px 10px;
  font-size: 13px;
  font-weight: 400;
  color: var(--ink-1);
  letter-spacing: -.01em;
  border-bottom: 1px solid var(--border-2);
}

/* 风险预警图例 4 色 — 改用 .ico-dot 颜色暗示 */
.inv-alert-legend .iv-lgrp i { display: inline-block; width: 6px; height: 6px; border-radius: 50%; margin-right: 4px; vertical-align: 1px; }
.inv-alert-legend .iv-lgrp i.red { background: var(--red); }
.inv-alert-legend .iv-lgrp i.yellow { background: var(--orange); }
.inv-alert-legend .iv-lgrp i.green { background: var(--green); }
.inv-alert-legend .iv-lgrp i.blue { background: var(--brand); }

/* =========================================================
   销售看板（v87）—— 苹果蓝白扁平风，沿用全局设计变量
   ========================================================= */
.sales { padding: 12px 12px 24px; }

.sales-hd { display: flex; align-items: baseline; justify-content: space-between; margin: 2px 4px 10px; }
.sales-title { font-size: 20px; font-weight: 700; color: var(--ink-1); letter-spacing: -.02em; }
.sales-sub { font-size: 11px; font-weight: 400; color: var(--ink-3); }

.sales-month { margin-bottom: 10px; }
/* v114.6.9.11 肉哥 "筛选器可以比上面的表头略窄一点点"：左右各内缩 4px，比 sd-tabs 窄 8px
   ★ v114.6.9.38 肉哥 9/10 "三个筛选胶囊下面这个空行能否去掉"：
     根因是 flex-wrap:wrap + 重置键固定 30px 宽，375px 屏下
     「日期 + 品牌 + 门店 + 重置」总宽超出容器 → 重置键被折到第二行，
     第二行只有它一个元素，看着就是"一条空行把下面的板块推下去了"。
     修法（肉哥自己给了方案）：不折行（nowrap），并把重置键从"占一行的按钮"
     降级为"贴着三个胶囊右边的常驻小图标"，宽度收窄到 26px。
     这样既消掉空行，又保证筛选区永远只有一行。 */
.sales-filter { display: flex; flex-wrap: nowrap; gap: 5px; align-items: center; margin-bottom: 8px; padding: 0 4px; }
/* v114.6.9.11 肉哥 "筛选器有点太太窄了"：胶囊从 22px 高 / 10.5px 字 / min-width 60px
   加宽到 30px 高 / 12px 字 / min-width 100px。比表头 sd-tabs 略窄一点（tab 3 等分、筛选 3 胶囊 + 1 重置）
   ※ 之前 v114.6.9 ~ v114.6.9.6 一直压缩到 22/10.5 是因为太胖，这次反向校正。 */
.sales-sel-holder { flex: 1 1 0; min-width: 0; }
/* v114.6.9.38 重置键：从"折行按钮"改为"常驻小图标"，与三个胶囊同排、不换行。
 *   肉哥 9/10 原话：「如果是因为被"重置"键占据了话，那请把重置键直接放在三个筛选胶囊旁边一直显示着好了」
 *   实现要点：
 *     · flex: 0 0 26px —— 固定 26px，不再撑宽（旧 30px 是压垮 375px 那一行的主因）
 *     · height 跟胶囊 30px 对齐，视觉上属于同一排
 *     · idle 态不禁用（肉哥要"一直显示着"），只是降低对比度；无筛选时点了不做事 */
.sales-reset { flex-shrink: 0; border: 1px solid var(--border); background: var(--surface); color: var(--ink-2);
  border-radius: 8px; font-size: 13px; font-weight: 400; padding: 0; cursor: pointer;
  /* v114.6.9.20：active 态也用图标 + tooltip，固定 30×30 不再因"重置"2 字撑爆（之前 48 仍被 25+30 撑破） */
  width: 26px; height: 30px; max-height: 30px; min-height: 30px; flex: 0 0 26px; box-sizing: border-box;
  display: inline-flex; align-items: center; justify-content: center; line-height: 1; position: relative; }
.sales-reset:active { background: var(--hover); }
/* tooltip：hover 时显示"重置"文字（mobile 触屏不影响，已加 title 属性兜底） */
.sales-reset .sd-reset-tip {
  position: absolute; top: -28px; left: 50%; transform: translateX(-50%);
  background: rgba(0,0,0,0.78); color: #fff; font-size: 11px; font-weight: 400; padding: 3px 6px;
  border-radius: 4px; white-space: nowrap; pointer-events: none; opacity: 0; transition: opacity .15s;
}
.sales-reset:hover .sd-reset-tip,
.sales-reset:active .sd-reset-tip { opacity: 1; }
/* v114.6.9.2 肉哥 "空着看着奇怪"：没筛选时重置按钮不隐藏，而是显示成一个小灰点（↻ 灰色半透明）。
   v114.6.9.38 改：不再 pointer-events:none —— 肉哥要它"一直显示着"，
   现在它是常驻可点的小图标（无筛选时点了不做事，也不会报错）。 */
.sales-reset.sd-reset-idle {
  color: var(--ink-4);
  border-color: var(--border);
  background: transparent;
  opacity: 0.5;
}

/* 单值筛选下拉 */
/* v114.6.9.11 肉哥 "太太窄"：胶囊 22→30px 高、padding 1px 5px→4px 10px、字号 10.5→12px、caret 7→9px
   配套 ss-label 9.5→10.5px, ss-val 12px，min-width 60→100px
   v114.6.9.6 肉哥 "为什么品牌和门店会这么大"：用 height + max-height + flex:0 0 N 强制不让任何内容/容器把触发器撑大 */
.sales-sel { position: relative; }
/* ════════════════════════════════════════════════════════════════════════════
 * v114.6.9.44 · 【全站「筛选器胶囊」的唯一规范 · SINGLE SOURCE OF TRUTH】
 * ────────────────────────────────────────────────────────────────────────────
 * 肉哥 9/11：「tab + 筛选器胶囊一起统一」。
 * 基准取自 **销量看板** 的 `.sales-sel-trigger` —— 依据是肉哥 9/8 已经拍过
 * "毛利预警的三级筛选整段复用销量看板这套类"（见下方 v114.6.9.39 注释），
 * 即"筛选器以销量看板为准"是此前就定下的口径，本次沿用它，不发明新值。
 *
 * 统一前是两套：
 *   A. 销量 / 毛利：`.sales-sel-trigger`（单选下拉）+ `.sd-pill`（单值降级标签）
 *      → 30px 高 / radius 6 / 12px 字 / border 1px var(--border)
 *   B. 库存 / 订单看板：`.dash-pill .mselect`（**多选**下拉）
 *      → 38px 高 / radius 8 / 14px 字 —— 比 A 高一头、字大一号，并排看很跳
 *
 * ── 本次只统一「胶囊本体」的视觉 ──────────────────────────────────────────
 *   ✅ 高度 / 圆角 / 字号 / 字重 / 边框色 / 内边距 / 文字色 / hover·active 反馈
 *   ❌ **不动布局结构**：`.dash-filter` 是"左侧标签 + 右侧控件"的竖排，
 *      `.sales-filter` 是"一排 nowrap 胶囊"。结构不同，强行统一必须改 HTML，
 *      会连带改 4 个页面 → 不动。
 *   ❌ **不动交互**：库存是多选（UI.MSelect），销量是单选。只换皮。
 *
 * ── 规范取值（＝ `.sales-sel-trigger` 原有的计算值） ────────────────────────
 *   min-height 30px · border-radius 6px · padding 4px 10px · box-sizing border-box
 *   font-size 12px · font-weight 500 · color var(--ink-1)
 *   background var(--surface) · border 1px solid var(--border)
 *   占位/次要文字 var(--ink-3) · hover 描边 var(--brand) · active 底 var(--hover)
 *
 * ★ 唯一允许的差异：多选胶囊的**右内边距** 10px → 26px，给 `.mselect-arrow`(▾)
 *   和 `.mselect-count` 徽标留位。这是控件形态决定的，不是"没统一"。
 * ★ `.sd-pill` 由 22px/10.5px 补到 30px/12px：它上面那条注释写着"对齐主下拉尺寸"
 *   但取值一直没跟上（22 vs 30）→ 同排看就是"日期那颗明显更瘦小"。
 *   本次一并修正，属于真 bug 修复，不是风格偏好。
 * ★ 被本段取代并**已在原处删除**的旧规则：
 *     · `.mselect-trigger` / `:hover` / `:focus`   ← 原 :1949-1956
 *     · `.sd-pill`                                 ← 原 :3268-3272
 *   （`.sd-pill .ss-val` 那条保留在 :3273，本段不覆盖它）
 * ════════════════════════════════════════════════════════════════════════════ */
.sales-sel-trigger,
.sd-pill,
.mselect-trigger {
  display: flex;
  align-items: center;
  gap: 4px;
  width: 100%;
  box-sizing: border-box;
  /* v114.6.9.45 正文字号统一：左右内边距 10px → 8px。
     来源：本次把胶囊里的 `.ss-label`(10.5→11px) 与 `.ss-caret`(9→11px) 提上字号阶梯后，
     375px 下三个筛选胶囊每个只有 ~54px（`.sd-holder-date` 是 flex:1 1 auto，吃掉 134px），
     而 label+caret 都是 flex-shrink:0 → 内容比按钮宽 3px，右侧 ▾ 被 overflow:hidden 裁掉。
     两个 flex-shrink:0 的直接子项固定要吃 22+5+8(gap)=35px，加 2×10 padding + 2 border = 57 > 54。
     故把左右 padding 让出 2px（10→8）：35 + 16 + 2 = 53 ≤ 54。只改 px，不动结构。
     `.mselect-trigger` 自带的左内边距同步改 8px（见下），右 26px 不动。 */
  padding: 4px 8px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 6px;
  color: var(--ink-1);
  font-size: 12px;
  font-weight: 500;
  line-height: 1.4;
  cursor: pointer;
  overflow: hidden;
  transition: border-color .15s, background .15s, box-shadow .15s;
}
.sales-sel-trigger:hover,
.sd-pill:hover,
.mselect-trigger:hover { border-color: var(--brand); }
.sales-sel-trigger:active,
.sd-pill:active,
.mselect-trigger:active { background: var(--hover); }
.mselect-trigger:focus { outline: none; border-color: var(--brand); box-shadow: 0 0 0 3px var(--brand-50); }

/* 单行固定 30px（销量/毛利：日期·品牌·门店 · 单值降级标签） */
/* ★ v114.6.9.6 肉哥"为什么品牌和门店会这么大"：height+max-height+flex:0 0 N
 *   三件套强制不让任何内容/容器把触发器撑大 —— 保留 */
.sales-sel-trigger,
.sd-pill {
  height: 30px;
  max-height: 30px;
  min-height: 30px;
  flex: 0 0 30px;
}
/* 多选胶囊只给 min-height，**不给 max-height**：库存是多选，选中 2~3 个时
 * `.mselect-trig-inner` 会折行，硬锁 30px 会把 chip 裁掉（交互会坏）。
 * 右内边距 26px 让出 `.mselect-arrow` / `.mselect-count` 的位置。 */
.mselect-trigger {
  min-height: 30px;
  /* v114.6.9.45：左内边距 10px → 8px，跟随上面基准规则。
     约束来源：tools/check-tab-cascade.js 任务 B ——「多选与单值胶囊只有 right 可以不同」。 */
  padding: 4px 26px 4px 8px;
}
/* 多选 chip 同步收一号，避免 2 个 chip 就折行把胶囊撑高（只改尺寸，不改多选逻辑） */
.mselect-chip {
  padding: 1px 3px 1px 6px;
  font-size: 11px;
}
/* ★ `.sd-pill` 是**不可点**的降级标签 —— 只有"筛选项只剩 1 个"时才出现
 *   （page-sales.js:339「1 个日期 → pill 标签（不可点）」，门店/品牌同理）。
 *   所以不能沿用规范段里的 pointer 手型与 hover/active 反馈，
 *   否则用户会以为能点。视觉（高度/圆角/描边/字号）仍与其它胶囊完全一致。 */
.sd-pill { cursor: default; }
.sd-pill:hover { border-color: var(--border); }
.sd-pill:active { background: var(--surface); }
.ss-label { color: var(--ink-3); flex-shrink: 0; font-size: 11px; font-weight: 400; }
.ss-val { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; text-align: left; font-weight: 400; font-size: 13px; }
.ss-val.ph { color: var(--ink-3); font-weight: 400; }
.ss-caret { color: var(--ink-3); font-size: 11px; font-style: normal; flex-shrink: 0; }
.sales-sel-pop { background: var(--surface); border: 1px solid var(--border); border-radius: 12px;
  box-shadow: var(--sh-lg); overflow: hidden; }
/* v114.6.9.1 肉哥 "下拉菜单无法滑动"：iOS WKWebView 对 position:fixed 子元素的 overflow-y:auto 有兼容问题。
   加 overscroll-behavior: contain 防滚动穿透 + transform: translateZ(0) 触发新 stacking context + 增 max-height 到 60vh。
   配合原 -webkit-overflow-scrolling: touch（保留 iOS 13 之前的弹性滚动）。 */
.sales-sel-list { max-height: 60vh; overflow-y: auto; -webkit-overflow-scrolling: touch; padding: 4px;
  overscroll-behavior: contain; transform: translateZ(0); }
.sales-sel-item { display: flex; align-items: center; justify-content: space-between; gap: 8px;
  padding: 10px 12px; border-radius: 8px; font-size: 13px; font-weight: 400; color: var(--ink-1); cursor: pointer; }
.sales-sel-item:active { background: var(--brand-50); }
.sales-sel-item.on { color: var(--brand); font-weight: 600; }
.ss-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ss-check { color: var(--brand); font-style: normal; }
.ss-none { padding: 12px; text-align: center; color: var(--ink-3); font-size: 11px; font-weight: 400; }

/* v114.6.9.44 删除：`.sales-tabs{margin-bottom:12px}` —— 交车看板(#rm-tabs) / 新保看板(#ins-tabs)
 *   的元素 class 是 `sales-tabs seg`，其容器样式已由「全站表头 Tab 唯一规范」段的
 *   `.sales-tabs.seg` 提供（margin:0 12px 10px，比内容区窄 12px）。此处不再重复定义。 */

.sales-ym-tag { font-size: 11px; font-weight: 400; color: var(--ink-3); background: var(--bg); border-radius: 6px; padding: 2px 8px; margin-left: 6px; }

/* 达成：进度条 */
.sales-goal { }
.goal-item { margin-bottom: 18px; }
.goal-item:last-child { margin-bottom: 0; }
.goal-head { display: flex; align-items: baseline; justify-content: space-between; margin-bottom: 8px; }
.goal-lbl { font-size: 13px; font-weight: 400; color: var(--ink-1); }
.goal-val { font-size: 13px; font-weight: 400; color: var(--ink-2); font-family: var(--font-num); }
.goal-val b { font-size: 20px; font-weight: 700; color: var(--ink-1); }
.goal-bar { height: 12px; background: var(--bg); border-radius: 999px; overflow: hidden; }
.goal-bar i { display: block; height: 100%; border-radius: 999px; transition: width .5s var(--ease-out); }
.goal-foot { margin-top: 6px; text-align: right; }
.goal-rate { font-size: 13px; font-weight: 400; font-family: var(--font-num); }

/* KPI 网格 */
.sales-kpi-grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: 10px; margin-top: 12px; }
.sales-kpi-cell { background: var(--surface); border: 1px solid var(--border); border-radius: var(--r-sm);
  padding: 12px 14px; box-shadow: var(--sh-xs); }
.sk-lbl { font-size: 11px; font-weight: 400; color: var(--ink-3); margin-bottom: 4px; }
.sk-val { font-size: 18px; font-weight: 700; font-family: var(--font-num); color: var(--ink-1); letter-spacing: -.01em; }

/* 图例 */
.sales-legend { display: flex; gap: 16px; margin-bottom: 8px; font-size: 11px; font-weight: 400; color: var(--ink-2); }
.sales-legend .lg { display: inline-flex; align-items: center; gap: 5px; }
.sales-legend .lg i { width: 10px; height: 10px; border-radius: 3px; display: inline-block; }
.sales-legend .lg b { color: var(--ink-1); font-family: var(--font-num); }

.sales-scroll { overflow-x: auto; -webkit-overflow-scrolling: touch; margin: 0 -4px; }

/* 车系明细 */
.sr-row { display: flex; align-items: center; justify-content: space-between; gap: 10px;
  padding: 10px 14px; border-bottom: 1px solid var(--border-2); }
.sr-row:last-child { border-bottom: none; }
.sr-name { font-size: 13px; color: var(--ink-1); font-weight: 400; flex-shrink: 0; }
.sr-nums { display: flex; align-items: center; gap: 12px; font-size: 13px; font-weight: 400; font-family: var(--font-num); }
.sr-o { color: var(--brand); font-weight: 600; }
.sr-i { color: var(--green); font-weight: 600; }
.sr-tgt { color: var(--ink-2); }
.sr-tgt.muted { color: var(--ink-3); }

/* 人效榜 */
.pp-row { display: flex; align-items: center; gap: 10px; padding: 11px 14px; border-bottom: 1px solid var(--border-2); }
.pp-row:last-child { border-bottom: none; }
.pp-rank { width: 22px; height: 22px; border-radius: 50%; background: var(--bg); color: var(--ink-2);
  font-size: 12px; font-weight: 700; font-family: var(--font-num); display: flex; align-items: center; justify-content: center; flex-shrink: 0; }
.pp-rank.top1 { background: #fff3df; color: #b45309; }
.pp-rank.top2 { background: #eef1f4; color: #64748b; }
.pp-rank.top3 { background: #fdf0e6; color: #b9774b; }
.pp-id { flex: 1; min-width: 0; }
.pp-name { font-size: 13px; color: var(--ink-1); font-weight: 400; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.pp-store { font-size: 11px; font-weight: 400; color: var(--ink-3); margin-left: 6px; }
.pp-sec { font-size: 11px; font-weight: 400; color: var(--ink-3); margin-top: 2px; font-family: var(--font-num); }
.pp-counts { display: flex; gap: 8px; flex-shrink: 0; font-size: 13px; font-family: var(--font-num); font-weight: 400; }
.pp-o { color: var(--brand); }
.pp-i { color: var(--green); }

/* 多维交叉表 */
.mx-brand { display: flex; align-items: center; justify-content: space-between; padding: 11px 14px 7px; }
.mx-bn { font-size: 13px; font-weight: 400; color: var(--ink-1); }
.mx-tot { font-size: 13px; font-family: var(--font-num); color: var(--brand); font-weight: 400; }
.mx-store { display: flex; align-items: center; justify-content: space-between; padding: 7px 14px 5px 26px; }
.mx-sn { font-size: 13px; color: var(--ink-1); font-weight: 400; }
.mx-store .mx-tot { color: var(--ink-2); font-weight: 500; }
.mx-series { display: flex; align-items: center; justify-content: space-between; padding: 5px 14px 5px 40px;
  font-size: 11px; font-weight: 400; color: var(--ink-3); font-family: var(--font-num); border-bottom: 1px dashed var(--border-2); }
.mx-series:last-child { border-bottom: none; }
.mx-series span:last-child { color: var(--ink-2); }

/* =========================================================
   库存看板 · 东昌大盘总览（v88）—— 今日+5天预判
   ========================================================= */
.iv-plan-section.group { border-color: rgba(0, 113, 227, .35); background: linear-gradient(180deg, #f6faff, #ffffff); }
.iv-plan-section.group .iv-plan-sec-name { color: var(--brand); font-size: 13px; font-weight: 400; }
.iv-plan-section.group::before { background: var(--brand); }

.iv-bd-head { font-size: 11px; font-weight: 400; color: var(--ink-3); margin: 10px 0 4px; }
.iv-bd-list { display: flex; flex-direction: column; }
.iv-bd-row { display: flex; align-items: center; gap: 8px; padding: 6px 0; border-bottom: 1px dashed var(--border-2); font-size: 13px; font-weight: 400; }
.iv-bd-row:last-child { border-bottom: none; }
.iv-bd-brand { flex: 1; min-width: 0; font-weight: 500; color: var(--ink-1); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.iv-bd-will { color: var(--ink-2); white-space: nowrap; }
.iv-bd-will b.err { color: var(--red); }
.iv-bd-pct { color: var(--ink-3); white-space: nowrap; font-family: var(--font-num); }
.iv-bd-pct b.ok { color: var(--green); }
.iv-bd-pct b.err { color: var(--red); }
.iv-bd-need { color: var(--orange); white-space: nowrap; font-weight: 500; }
.iv-bd-ok { color: var(--green); white-space: nowrap; }

/* ============================================================
   板块五：经营分析智能体（v91 2026-09-01）
   气泡式问答 + 指标卡 + 数据表格 + 报告链接
   ============================================================ */

/* 问数：机器人 */
.ico-robot {
  -webkit-mask-image: url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='4' y='8' width='16' height='12' rx='3'/%3E%3Cpath d='M12 8V4'/%3E%3Ccircle cx='12' cy='3' r='1.2'/%3E%3Ccircle cx='9' cy='14' r='1'/%3E%3Ccircle cx='15' cy='14' r='1'/%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='4' y='8' width='16' height='12' rx='3'/%3E%3Cpath d='M12 8V4'/%3E%3Ccircle cx='12' cy='3' r='1.2'/%3E%3Ccircle cx='9' cy='14' r='1'/%3E%3Ccircle cx='15' cy='14' r='1'/%3E%3C/svg%3E");
}

.ag-wrap {
  position: fixed;
  top: calc(var(--nav-h) + env(safe-area-inset-top, 0px));
  bottom: calc(var(--tab-h) + var(--safe-b));
  left: 0;
  right: 0;
  display: flex;
  flex-direction: column;
  background: linear-gradient(180deg, #f6f8fc 0%, #f1f5fa 100%);
  z-index: 10;
  overflow: hidden;
}
/* v97：头部改成「标题 + 当前会话 + 历史入口」两行结构 */
.ag-hd-row { display: flex; align-items: flex-start; gap: 10px; }
.ag-hd-l { flex: 1; min-width: 0; }
.ag-hd-c { font-size: 11px; font-weight: 400; color: var(--ink-3); margin-top: 3px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.ag-hist {
  flex: none; margin-top: -2px;
  border: 1px solid var(--border); background: var(--surface); color: var(--ink-2);
  font-size: 13px; font-weight: 400; font-family: inherit; border-radius: 999px; padding: 5px 12px; cursor: pointer;
  display: flex; align-items: center; gap: 5px;
}
.ag-hist::before {
  content: ''; width: 13px; height: 13px; background: var(--ink-3);
  -webkit-mask-image: url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M3 12a9 9 0 1 0 3-6.7L3 8'/%3E%3Cpath d='M3 3v5h5'/%3E%3Cpath d='M12 7v5l3.5 2'/%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M3 12a9 9 0 1 0 3-6.7L3 8'/%3E%3Cpath d='M3 3v5h5'/%3E%3Cpath d='M12 7v5l3.5 2'/%3E%3C/svg%3E");
  -webkit-mask-size: contain; mask-size: contain;
  -webkit-mask-repeat: no-repeat; mask-repeat: no-repeat;
  -webkit-mask-position: center; mask-position: center;
}
.ag-hist:active { background: var(--bg); }

/* v97：答不了 —— 让「能力边界」在界面上看得见，别让用户以为是数据缺失 */
.ag-miss {
  margin-top: 9px; background: #fff8ea; border: 1px solid #f3e0bb; border-radius: 8px;
  padding: 8px 10px; display: flex; flex-direction: column; gap: 3px;
}
.ag-miss-t { font-size: 11px; font-weight: 400; color: #8a5a00; }
.ag-miss-d { font-size: 11px; font-weight: 400; color: #a3762a; line-height: 1.55; }

/* v97：历史会话抽屉（挂 body，z-index 要压过 tabbar 的 60） */
.ag-drawer { position: fixed; inset: 0; z-index: 300; pointer-events: none; }
.ag-drawer.show { pointer-events: auto; }
.ag-mask { position: absolute; inset: 0; background: rgba(15, 23, 42, .38); opacity: 0; transition: opacity .22s ease; }
.ag-drawer.show .ag-mask { opacity: 1; }
.ag-panel {
  position: absolute; top: 0; right: 0; bottom: 0;
  width: 84%; max-width: 340px; background: var(--surface);
  display: flex; flex-direction: column;
  box-shadow: -10px 0 32px -14px rgba(15, 23, 42, .3);
  transform: translateX(100%);
  transition: transform .24s cubic-bezier(.32, .72, 0, 1);
  padding-bottom: env(safe-area-inset-bottom, 0px);
}
.ag-drawer.show .ag-panel { transform: translateX(0); }
.ag-panel-hd {
  flex: none; display: flex; align-items: center; gap: 10px;
  padding: calc(14px + env(safe-area-inset-top, 0px)) 16px 12px;
  border-bottom: 1px solid var(--border-2);
}
.ag-panel-t { flex: 1; font-size: 15px; font-weight: 600; color: var(--ink-1); }
.ag-panel-new {
  flex: none; border: none; background: var(--brand); color: #fff;
  font-size: 13px; font-family: inherit; font-weight: 400;
  border-radius: 999px; padding: 6px 13px; cursor: pointer;
}
.ag-panel-new:active { background: var(--brand-600); }
.ag-sess-list { flex: 1 1 auto; min-height: 0; overflow-y: auto; -webkit-overflow-scrolling: touch; padding: 8px 10px 20px; }
.ag-sess-empty { text-align: center; color: var(--ink-3); font-size: 11px; font-weight: 400; padding: 40px 0; }
.ag-srow {
  display: flex; align-items: center; gap: 8px;
  padding: 11px 12px; border-radius: 10px; cursor: pointer;
}
.ag-srow:active { background: var(--bg); }
.ag-srow.on { background: var(--brand-50); }
.ag-srow-main { flex: 1; min-width: 0; }
.ag-srow-t { font-size: 13px; font-weight: 400; color: var(--ink-1); line-height: 1.45; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ag-srow.on .ag-srow-t { color: var(--brand-600); font-weight: 600; }
.ag-srow-m { font-size: 11px; font-weight: 400; color: var(--ink-3); margin-top: 3px; }
.ag-srow-miss { font-style: normal; color: var(--orange); }
.ag-srow-del {
  flex: none; width: 26px; height: 26px; border: none; background: transparent;
  color: var(--ink-3); font-size: 19px; line-height: 1; cursor: pointer;
  border-radius: 50%; font-family: inherit;
}
.ag-srow-del:active { background: var(--border-2); color: var(--red); }

.ag-hd { padding: 11px 16px 9px; border-bottom: 1px solid var(--border-2); background: rgba(255,255,255,.78); backdrop-filter: saturate(180%) blur(14px); -webkit-backdrop-filter: saturate(180%) blur(14px); flex: none; }
.ag-hd-t { font-size: 15px; font-weight: 600; color: var(--ink-1); display: flex; align-items: center; gap: 7px; }
.ag-hd-t::before { content: ''; width: 4px; height: 14px; border-radius: 2px; background: var(--brand); }
.ag-hd-s { font-size: 11px; font-weight: 400; color: var(--ink-3); margin-top: 4px; line-height: 1.5; }
.ag-hd-s.warn { color: var(--orange); }

.ag-msgs { flex: 1 1 auto; min-height: 0; overflow-y: auto; -webkit-overflow-scrolling: touch; padding: 14px 12px 18px; display: flex; flex-direction: column; gap: 14px; overscroll-behavior: contain; }
.ag-msgs::after { content: ''; height: 4px; flex: none; }

.ag-msg { max-width: 88%; font-size: 13px; font-weight: 400; line-height: 1.65; }
.ag-msg.me { align-self: flex-end; background: var(--brand); color: #fff; border-radius: 14px 14px 4px 14px; padding: 9px 13px; }
.ag-msg.ai { align-self: flex-start; background: var(--bg-elev); border: 1px solid var(--border); border-radius: 14px 14px 14px 4px; padding: 11px 13px; }
/* 助手气泡里含指标卡/表格时放宽到满宽，避免表格挤成一条 */
.ag-msg.ai.has-res { max-width: 100%; padding: 11px; }

.ag-txt { white-space: normal; word-break: break-word; }

.ag-typing { color: var(--ink-3); font-size: 11px; font-weight: 400; }
.ag-typing span { animation: ag-blink 1.2s infinite; }
.ag-typing span:nth-child(2) { animation-delay: .2s; }
.ag-typing span:nth-child(3) { animation-delay: .4s; }
@keyframes ag-blink { 0%, 60%, 100% { opacity: .25; } 30% { opacity: 1; } }

.ag-quick { display: flex; flex-wrap: wrap; gap: 7px; margin-top: 10px; }
.ag-q { border: 1px solid var(--brand-200); background: var(--brand-50); color: var(--brand-600); font-size: 13px; font-weight: 400; border-radius: 999px; padding: 6px 11px; cursor: pointer; font-family: inherit; }
.ag-q:active { background: var(--brand-100); }

.ag-res { display: flex; flex-direction: column; gap: 12px; margin-top: 10px; }
.ag-rb { background: var(--bg); border-radius: 10px; padding: 10px; }
.ag-rt { font-size: 13px; font-weight: 400; color: var(--ink-2); margin-bottom: 8px; }

.ag-cards { display: grid; grid-template-columns: repeat(auto-fit, minmax(88px, 1fr)); gap: 7px; }
.ag-card { background: var(--bg-elev); border: 1px solid var(--border-2); border-radius: 8px; padding: 8px 9px; }
.ag-cl { font-size: 11px; font-weight: 400; color: var(--ink-3); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.ag-cv { font-size: 17px; font-weight: 600; color: var(--ink-1); margin-top: 2px; font-variant-numeric: tabular-nums; }
.ag-cu { font-size: 11px; font-weight: 400; color: var(--ink-3); margin-left: 2px; }
.ag-card.lv-red .ag-cv { color: var(--red); }
.ag-card.lv-yellow .ag-cv { color: var(--orange); }
.ag-card.lv-green .ag-cv { color: var(--green); }

.ag-subt { font-size: 11px; font-weight: 400; color: var(--ink-3); margin: 9px 0 4px; }
.ag-tw { overflow-x: auto; -webkit-overflow-scrolling: touch; }
.ag-tw table { width: 100%; border-collapse: collapse; font-size: 13px; font-weight: 400; min-width: 240px; }
.ag-tw th { background: var(--bg-elev); color: var(--ink-2); font-weight: 500; text-align: left; padding: 6px 8px; border-bottom: 1px solid var(--border); white-space: nowrap; }
/* 表头字号锁 11px：.ag-tw table 归方案 C 主体档 13px，而 .ag-tw th 不声明字号就会继承 13px，
 * 违背「表头豁免」。11px 与另外 4 张表头（table.tb / .pc-table / .iv-transfer-table / .inv-table）一致。
 * 归类依据见 tools/font-tier-map.json 的 needThead。 */
.ag-tw th { font-size: 11px; }
.ag-tw td { padding: 6px 8px; border-bottom: 1px solid var(--border-2); color: var(--ink-1); white-space: nowrap; }
.ag-tw tr:last-child td { border-bottom: none; }

.ag-adv { background: #fff8ea; border-radius: 8px; padding: 8px 10px; font-size: 11px; font-weight: 400; color: #8a5a00; margin-top: 9px; line-height: 1.6; }
.ag-note { font-size: 11px; font-weight: 400; color: var(--ink-3); margin-top: 7px; line-height: 1.55; }

.ag-trace { margin-top: 9px; display: flex; flex-wrap: wrap; gap: 5px; align-items: center; font-size: 11px; font-weight: 400; color: var(--ink-3); }
.ag-chip { background: var(--brand-50); color: var(--brand-600); border-radius: 999px; padding: 2px 8px; font-size: 11px; font-weight: 400; }
.ag-chip.bad { background: var(--red-bg); color: var(--red); }

.ag-report { display: flex; align-items: center; gap: 10px; margin-top: 10px; padding: 10px 12px; background: var(--brand-50); border: 1px solid var(--brand-100); border-radius: 10px; text-decoration: none; }
.ag-report b { display: block; font-size: 13px; color: var(--brand-600); font-weight: 400; }
.ag-report i { display: block; font-size: 11px; font-weight: 400; color: var(--ink-3); font-style: normal; margin-top: 2px; }
.ag-rico { width: 20px; height: 20px; flex: none; background: var(--brand); -webkit-mask-image: url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.7' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M14 3H6a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V9z'/%3E%3Cpath d='M14 3v6h6'/%3E%3Cpath d='m9 14 2 2 4-4'/%3E%3C/svg%3E"); mask-image: url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.7' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M14 3H6a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V9z'/%3E%3Cpath d='M14 3v6h6'/%3E%3Cpath d='m9 14 2 2 4-4'/%3E%3C/svg%3E"); }

.ag-err { background: var(--red-bg); color: var(--red); border-radius: 8px; padding: 9px 11px; font-size: 11px; font-weight: 400; line-height: 1.6; }

/* ── v99 流式输出：分析过程 / 打字机 / 数据区三段分离 ──────────────
   把「取数来源」从回答正文里摘出来单独成块，默认收起，
   领导看结论时不被过程打断，要追溯数字来源时点开即可。 */
.ag-proc { background: var(--bg); border-radius: 9px; margin-bottom: 9px; overflow: hidden; }
.ag-proc-hd { display: flex; align-items: center; gap: 7px; padding: 7px 10px; cursor: pointer; user-select: none; -webkit-user-select: none; }
.ag-proc-hd:active { background: var(--border-2); }
.ag-proc-t { font-size: 11px; font-weight: 400; color: var(--ink-2); }
.ag-proc-n { font-size: 11px; font-weight: 400; color: var(--ink-3); }
.ag-proc-a { margin-left: auto; font-size: 11px; font-weight: 400; color: var(--brand); }
.ag-proc-a::after { content: '展开'; }
.ag-proc.open .ag-proc-a::after { content: '收起'; }
.ag-proc-bd { display: none; padding: 2px 10px 8px; border-top: 1px solid var(--border-2); }
.ag-proc.open .ag-proc-bd { display: block; }

.ag-step { display: flex; align-items: center; flex-wrap: wrap; gap: 6px; padding: 7px 0; border-bottom: 1px dashed var(--border-2); }
.ag-step:last-child { border-bottom: 0; }
.ag-step-i { flex: none; width: 16px; height: 16px; border-radius: 50%; background: var(--brand-50); color: var(--brand-600); font-size: 11px; font-weight: 600; display: flex; align-items: center; justify-content: center; }
.ag-step-l { font-size: 11px; font-weight: 400; color: var(--ink-1); flex: none; }
.ag-step-a { font-size: 11px; font-weight: 400; color: var(--ink-3); flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ag-step-s { flex: none; font-size: 11px; font-weight: 400; color: var(--green); background: var(--green-bg); border-radius: 999px; padding: 1px 7px; }
.ag-step.bad .ag-step-s { color: var(--red); background: var(--red-bg); }
.ag-step.bad .ag-step-i { background: var(--red-bg); color: var(--red); }
.ag-step-e { flex: 0 0 100%; font-size: 11px; font-weight: 400; color: var(--red); line-height: 1.5; padding-left: 22px; }
.ag-step-txt { font-size: 11px; font-weight: 400; color: var(--ink-3); line-height: 1.6; padding: 7px 0 2px; }

/* 打字机光标 */
.ag-caret { display: inline-block; width: 2px; height: 13px; background: var(--brand); vertical-align: -2px; margin-left: 2px; animation: ag-caret 1s steps(2) infinite; }
@keyframes ag-caret { 0%, 49% { opacity: 1; } 50%, 100% { opacity: 0; } }

/* 数据区淡入，不抢打字机的戏 */
.ag-tail { opacity: 0; transform: translateY(4px); transition: opacity .28s ease, transform .28s ease; }
.ag-tail.in { opacity: 1; transform: none; }

.ag-bar {
  position: relative;
  flex: none;
  display: flex;
  gap: 8px;
  align-items: flex-end;
  padding: 9px 12px calc(9px + env(safe-area-inset-bottom, 0px));
  border-top: 1px solid var(--border-2);
  background: rgba(255,255,255,.94);
  backdrop-filter: saturate(180%) blur(20px);
  -webkit-backdrop-filter: saturate(180%) blur(20px);
  box-shadow: 0 -6px 18px -10px rgba(15, 23, 42, .08);
}
.ag-input {
  flex: 1; min-width: 0;
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 9px 12px;
  font-size: 14px;
  line-height: 1.4;
  font-family: inherit;
  color: var(--ink-1);
  background: #fff;
  max-height: 110px;
  resize: none;
}
.ag-input:focus { outline: none; border-color: var(--brand-300); box-shadow: 0 0 0 3px rgba(0, 113, 227, .12); }
.ag-input:disabled { background: var(--bg); color: var(--ink-3); }
.ag-send {
  flex: none;
  background: var(--brand);
  color: #fff;
  border: none;
  border-radius: 10px;
  padding: 0;
  width: 44px;
  height: 38px;
  font-size: 14px;
  font-family: inherit;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
}
.ag-send:disabled { background: var(--brand-300); cursor: not-allowed; }
.ag-send::after {
  content: '';
  display: block;
  width: 18px; height: 18px;
  background: #fff;
  -webkit-mask-image: url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m22 2-11 20-1.5-9L2 12.5 22 2z'/%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m22 2-11 20-1.5-9L2 12.5 22 2z'/%3E%3C/svg%3E");
  -webkit-mask-repeat: no-repeat;
  mask-repeat: no-repeat;
  -webkit-mask-position: center;
  mask-position: center;
  -webkit-mask-size: contain;
  mask-size: contain;
}
.ag-send:disabled { background: var(--brand-200); cursor: default; }

/* ============================================================
 *  v108 新保看板（page-insurance.js）
 * ============================================================ */
.ins .sales-sub .ins-warn { color: var(--warn, #b45309); }

/* 顶部三个胶囊筛选：日期 / 品牌 / 门店 */
.ins .ins-pills { display: flex; gap: 8px; padding: 0 12px 8px; }
.ins-pill {
  flex: 1; min-width: 0; height: 32px;
  display: flex; align-items: center; gap: 4px;
  padding: 0 10px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 999px;
  font-size: 13px; font-weight: 400; color: var(--ink-1);
  overflow: hidden;
}
.ins-pill-k { color: var(--ink-3); font-size: 11px; font-weight: 400; flex-shrink: 0; }
.ins-pill-sel {
  flex: 1; min-width: 0; height: 100%;
  border: 0; outline: 0;
  background: transparent;
  font-size: 13px; color: var(--ink-1);
  appearance: none; -webkit-appearance: none;
  background-image: url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6' viewBox='0 0 10 6'%3E%3Cpath d='M1 1l4 4 4-4' fill='none' stroke='%239aa4b2' stroke-width='1.6' stroke-linecap='round'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: right 4px center;
  padding-right: 18px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.ins-pill-sel::-ms-expand { display: none; }

/* 首屏渗透率大卡 */
.ins-hero .card-bd { text-align: center; padding: 6px 0 10px; }
.ins-hero-num {
  font-size: 44px; font-weight: 800; line-height: 1.1;
  font-family: var(--font-num); letter-spacing: -.02em;
}
.ins-hero-sub {
  margin-top: 6px; font-size: 13px; font-weight: 400; color: var(--ink-3);
  display: flex; align-items: center; justify-content: center; gap: 8px;
}
.ins-hero-sub b { color: var(--ink-1); font-family: var(--font-num); font-size: 13px; font-weight: 400; }
.ins-slash { color: var(--border); }

/* 分段条（月 / 模式之间加分隔） */
.seg-sep {
  display: inline-block; width: 1px; height: 16px;
  background: var(--border); margin: 0 4px; vertical-align: middle;
}

/* 保费构成条 */
.ins-bar {
  display: flex; height: 14px; border-radius: 999px;
  overflow: hidden; background: var(--surface-2, #f1f5f9);
}
.ins-bar i { display: block; height: 100%; }
.ins-legend {
  display: flex; flex-wrap: wrap; gap: 6px 14px;
  margin-top: 10px; font-size: 11px; font-weight: 400; color: var(--ink-2);
}
.ins-legend span { display: inline-flex; align-items: center; gap: 5px; }
.ins-legend i { width: 9px; height: 9px; border-radius: 3px; display: inline-block; }
.ins-note { margin-top: 8px; font-size: 11px; font-weight: 400; color: var(--ink-3); line-height: 1.7; }

/* 排行行（门店 / 分档共用） */
.ins-row {
  display: flex; align-items: center; gap: 8px;
  padding: 8px 0; border-bottom: 1px solid var(--border);
}
.ins-row:last-child { border-bottom: 0; }
.ins-rname {
  flex: 0 0 96px; font-size: 11px; font-weight: 400; color: var(--ink-1);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.ins-rbrand { display: block; font-size: 11px; font-weight: 400; color: var(--ink-3); margin-top: 1px; }
.ins-rbar {
  flex: 1; height: 8px; border-radius: 999px;
  background: var(--surface-2, #f1f5f9); overflow: hidden;
}
.ins-rbar i { display: block; height: 100%; border-radius: 999px; }
.ins-rnum {
  flex: 0 0 62px; text-align: right; font-family: var(--font-num);
}
.ins-rnum b { display: block; font-size: 11px; font-weight: 400; color: var(--ink-1); }
.ins-rnum span { display: block; font-size: 11px; font-weight: 400; color: var(--ink-3); margin-top: 1px; }

/* 分品牌分组（品牌头 + 该品牌下门店排名） */
.ins-grp { padding: 10px 0 2px; border-bottom: 1px solid var(--border); }
.ins-grp:last-child { border-bottom: 0; padding-bottom: 0; }
.ins-ghead { margin-bottom: 4px; }
.ins-gname {
  font-size: 13px; font-weight: 400; color: var(--ink-1);
  display: flex; align-items: baseline; gap: 6px;
}
.ins-gcnt {
  font-size: 11px; font-weight: 400; color: var(--ink-3);
  background: var(--surface-2, #f1f5f9); border-radius: 999px; padding: 1px 7px;
}
.ins-gnums { display: flex; gap: 8px; margin-top: 7px; }
.ins-gnums span {
  flex: 1; text-align: center; background: var(--surface-2, #f8fafc);
  border-radius: var(--r-sm); padding: 6px 2px;
}
.ins-gnums i {
  display: block; font-style: normal; font-size: 11px;
  font-weight: 400;
  color: var(--ink-3); margin-bottom: 2px;
}
.ins-gnums b { font-size: 13px; font-weight: 400; color: var(--ink-1); font-family: var(--font-num); }
.ins-grows { margin-top: 2px; }
.ins-rk {
  flex: 0 0 18px; text-align: center; font-family: var(--font-num);
  font-size: 11px; font-weight: 400; color: var(--ink-3);
}
.ins-rk.top { color: var(--brand); font-weight: 700; }
.ins-none { padding: 6px 0; font-size: 11px; font-weight: 400; color: var(--ink-3); }

/* 品牌行 */
.ins-brow { padding: 10px 0; border-bottom: 1px solid var(--border); }
.ins-brow:last-child { border-bottom: 0; }
.ins-bname { font-size: 13px; font-weight: 400; color: var(--ink-1); margin-bottom: 6px; }
.ins-bcnt { margin-left: 6px; font-size: 11px; font-weight: 400; color: var(--ink-3); }
.ins-bnums { display: flex; gap: 10px; }
.ins-bnums span {
  flex: 1; text-align: center; background: var(--surface-2, #f8fafc);
  border-radius: var(--r-sm); padding: 6px 2px;
}
.ins-bnums i {
  display: block; font-style: normal; font-size: 11px;
  font-weight: 400;
  color: var(--ink-3); margin-bottom: 2px;
}
.ins-bnums b { font-size: 13px; font-weight: 400; color: var(--ink-1); font-family: var(--font-num); }

.ins-foot { margin-top: 8px; font-size: 11px; font-weight: 400; color: var(--ink-3); text-align: right; }

/* =========================================================
   销量看板 v114（page-sales.js）—— 三指标并列：拷车 / 订单 / 开票
   仅追加，不改动上方任何既有规则
   ========================================================= */
/* v114.6.9 肉哥 9/8 反馈 "全部往上移"：去 .sales-daily 顶部 padding, .sd-hd margin-top 8px 视觉间隔 */
/* v114.6.9.6 肉哥 9/8 反馈 "总览—门店分车系—重点车型 整体往上，顶到最上面"：
   .sd-hd（"全集团 / 数据更新于…"）整行 display:none，让 .sd-tabs 紧贴 sticky sub-bar 下面
   scope 范围仍可在「我的」页面看，"数据更新于"信息已挪到页面底部 / Tab 头部 <abbr> 提示 */
.sales-daily { padding: 0 12px 28px; }

/* ── 模块 0 · 页头 ── */
/* v114.6.7：去掉 sd-title "销量看板"（与顶部栏/面包屑重复，肉哥 9/8 反馈 "空了2行后下面又写个销量看板"）
   sd-hd 简化为 [sd-scope pill] [sd-upd] 一行紧凑 */
/* v114.6.9 肉哥 "全部往上移"：margin-top 8px 替代原来 .sales-daily 顶部 12px padding */
/* v114.6.9.6 整行隐藏（让 .sd-tabs 顶到最上面），保留其他属性作为 fallback */
.sd-hd { display: none; align-items: center; justify-content: space-between; gap: 8px; margin: 8px 0 4px; min-height: 18px; }
.sd-hd-l { min-width: 0; display: flex; align-items: center; gap: 6px; }
.sd-title { display: none; }
.sd-scope {
  display: inline-block; font-size: 11px; font-weight: 400; color: var(--brand);
  background: var(--brand-50); border-radius: 999px; padding: 1px 7px;
  max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.sd-upd { font-size: 11px; font-weight: 400; color: var(--ink-3); flex-shrink: 0; font-variant-numeric: tabular-nums; }
.sd-filters { margin-bottom: 8px; }
.sd-holder-date { flex: 1 1 auto; min-width: 60px; }
/* v114.6.9 肉哥 "为什么胶囊这么大"：单值降级标签 .sd-pill 未随 .sales-sel-trigger 缩小，
   仍用 padding 7px 10px / font 12px / radius 8px，单独看特别突兀。对齐主下拉尺寸 */
/* v114.6.9.44 删除：`.sd-pill{display:flex;…;background:var(--bg);
 *   border:1px solid var(--border-2);border-radius:5px;padding:1px 5px;
 *   font-size:10.5px;color:var(--ink-2);overflow:hidden;min-height:22px}`
 *   （取值本来是"对齐主下拉尺寸"的意图，但主下拉早就改成 30px/12px，
 *     这里一直停在 22px/10.5px → 同排看"日期那颗明显更瘦小"）
 *   已并入上方「全站筛选器胶囊唯一规范」段：30px 高 / radius 6 / 12px 字 /
 *   border 1px var(--border) / background var(--surface)。 */
.sd-pill .ss-val { color: var(--ink-2); font-weight: 500; }

/* ── 模块 1 · 三指标 KPI（三卡完全对称） ── */
.sd-kpi { grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 6px; margin: 0 0 12px; }
.sd-kpi .sales-kpi-cell { padding: 10px 8px 11px; min-width: 0; }
.sd-kpi .sk-lbl { display: flex; align-items: center; font-size: 11px; font-weight: 400; color: var(--ink-2); margin-bottom: 5px; }
.sk-dot { width: 6px; height: 6px; border-radius: 50%; display: inline-block; margin-right: 4px; flex-shrink: 0; }
.sk-tgt { font-size: 11px; font-weight: 400; color: var(--ink-3); font-family: var(--font-num); margin-bottom: 6px; font-variant-numeric: tabular-nums; }
.sk-pair { display: flex; gap: 4px; margin-bottom: 7px; }
.sk-mini { flex: 1; min-width: 0; }
.sk-mini span { display: block; font-size: 11px; font-weight: 400; color: var(--ink-3); line-height: 1.4; }
.sk-mini b {
  display: block; font-size: 13px; font-weight: 400; line-height: 1.25;
  font-family: var(--font-num); color: var(--ink-1); font-variant-numeric: tabular-nums;
}
.sk-bar { height: 6px; margin-bottom: 5px; }
.sk-rate { font-size: 13px; font-weight: 400; font-family: var(--font-num); text-align: right; line-height: 1.2; }
.sk-extra {
  min-height: 15px; margin-top: 3px; font-size: 11px; font-weight: 400; color: var(--ink-3);
  font-family: var(--font-num); text-align: center; letter-spacing: -.03em;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}

/* ── 卡片 / 区块头 ── */
.sd-sec { margin-bottom: 12px; }
.sd-sec-h { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
.sd-sec-sub { font-size: 11px; font-weight: 400; color: var(--ink-3); }
.sd-bd { padding: 12px 12px 4px; }

/* ── 模块 2 · 走势 ── */
.sd-legend { margin-bottom: 6px; flex-wrap: wrap; gap: 12px; }
.sd-chart { width: 100%; height: auto; display: block; }

/* ── 三列指标网格（品牌行 / 门店行 / 排行行共用，严格对齐） ── */
/* v114.6.6 店名列最小 100px：够装 4-5 字品牌/门店名 + caret + cnt 不被按字拆 */
.sd-grid { display: grid; grid-template-columns: minmax(100px, 1.2fr) repeat(3, minmax(56px, 1fr)); align-items: center; }
/* v114.6.3 门店排行只有 2 列（订单+开票，无拷车）
   v114.6.4 店名列 minmax(0, …)：让 .sd-nm 截断生效，不再强制 70px 留白
   v114.6.5 序号列 22 → 16px，序号左对齐贴卡片边，不再有 25px 大空隙
   v114.6.6 1.5fr：去掉 .sd-brand-tag 后给店名更多空间
   v114.6.9.16 改 4 列宽（medal + 门店 + 2 组 3 子项指标 cell）—— 见下方 .sd-grid.rank 块定义 */

.sd-row { border-bottom: 1px solid var(--border-2); }
.sd-row:last-child { border-bottom: none; }
.sd-head { padding: 0 0 6px; border-bottom: 1px solid var(--border); }
.sd-head .sd-c-name, .sd-head .sd-metric { font-size: 11px; font-weight: 600; color: var(--ink-3); }
/* v114.6.5 去掉 overflow:hidden — 让 .sd-nm 换行后不被父裁切 */
.sd-c-name { min-width: 0; padding-right: 6px; display: flex; align-items: center; gap: 4px; }
/* v114.6.3 单行不换行 → v114.6.5 截断不可接受 → v114.6.6 推翻 keep-all 路线
   word-break:keep-all：CJK 不按字拆（"上海广丰" 4 字不拆成 4 行）
   overflow-wrap:anywhere：长串/英文可拆（兜底；CJK 在窄屏下才拆）
   flex:0 1 auto：基础尺寸=内容，不主动扩展（避免挤掉兄弟元素） */
.sd-nm {
  font-size: 13px; color: var(--ink-1); font-weight: 400;
  line-height: 1.35; word-break: keep-all; overflow-wrap: anywhere;
  flex: 0 1 auto; min-width: 0;
}
.sd-nm.sub { font-size: 11px; color: var(--ink-2); font-weight: 400; }
.sd-metric { text-align: right; font-family: var(--font-num); font-variant-numeric: tabular-nums; }
.sd-mv { font-size: 13px; font-weight: 400; color: var(--ink-1); line-height: 1.3; }
.sd-mv b { font-weight: 700; }
.sd-mt { color: var(--ink-4); font-size: 13px; font-weight: 400; }
.sd-mr { font-size: 13px; font-weight: 400; line-height: 1.35; }

/* ── 模块 3 · 品牌进度（可展开） ── */
.sd-brand { border-bottom: 1px solid var(--border-2); }
.sd-brand:last-child { border-bottom: none; }
/* v114.6.8: .sd-brow 重定义为 7 列 grid (见下方), 删除此处的旧定义避免混淆 */
/* v114.6.9.3 领导反馈 "品牌门店字号混乱"：品牌名 / 门店名 统一 12.5px / weight 400，数字统一 12.5px，达成率统一深灰。
   只用「最后一家门店」达成率用红色做唯一视觉锚点，删掉品牌行的加粗 + 大字。 */
.sd-brow .sd-nm { font-weight: 400; font-size: 13px; color: var(--ink-1); }
.sd-brow .sd-cnt { font-size: 11px; color: var(--ink-3); font-weight: 400; }
.sd-caret {
  font-style: normal; font-size: 11px; color: var(--ink-3); flex-shrink: 0;
  width: 11px; transition: transform .18s var(--ease-out);
}
.sd-brand.open .sd-caret { transform: rotate(90deg); }
.sd-cnt { font-size: 11px; font-weight: 400; color: var(--ink-3); flex-shrink: 0; font-family: var(--font-num); }
.sd-stores { display: none; background: #fafbfc; border-radius: var(--r-sm); padding: 2px 0; margin-bottom: 6px; }
.sd-brand.open .sd-stores { display: block; }
.sd-stores .sd-c-name { padding-left: 15px; }
/* v114.6.9.10 品牌进度门店行：4 列 grid + 每组 stacked
   肉哥 9/8 "这根本对应不上"——v114.6.9.9 把达成率塞到 row 2 col 3/4（累正下方）
   视觉上跟其他列错位、看不出属于哪一组。
   改为：1 + 3 = 4 列；每组 cell 内 stacked：line1 = 累/目、line2 = 达成率。
   一组的所有数据在 1 列宽度内垂直排开，肉眼一看就是"这一组"。
   数据行 + 品牌行共用 .sd-brow / .sd-srow 两套结构。 */
.sd-brow,
.sd-srow {
  display: grid;
  grid-template-columns: minmax(88px, 1fr) repeat(3, 1fr);
  align-items: center;
  gap: 6px;
  padding: 10px 0;
}
.sd-brow { cursor: pointer; }
.sd-srow { border-bottom: 1px solid #f0f1f3; }
.sd-srow:last-child { border-bottom: none; }
.sd-brow .sd-c-name,
.sd-srow .sd-c-name { padding-left: 15px; padding-right: 6px; display: flex; align-items: center; gap: 4px; min-width: 0; }

/* 组（拷车/订单/开票）cell：列内 stacked
   line1 = 累/目（mtd ink-1 粗体，目标 ink-4 灰色）紧凑一行
   line2 = 达成率（默认 ink-2 深灰，最慢门店用 [data-slow-*] 红） */
.sd-grp {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 2px;
  min-width: 0;
  font-family: var(--font-num);
  font-variant-numeric: tabular-nums;
}
.sd-grp-line1 { font-size: 13px; font-weight: 400; color: var(--ink-2); line-height: 1.25; }
.sd-grp-line1 b { color: var(--ink-1); font-weight: 700; }
.sd-grp-line1 i { color: var(--ink-4); font-style: normal; margin: 0 2px; font-size: 11px; font-weight: 400; }
.sd-grp-line1 .sd-grp-target { color: var(--ink-4); font-size: 11px; font-weight: 400; }
.sd-grp-line2 { font-size: 13px; font-weight: 400; color: var(--ink-2); line-height: 1.2; }

/* 慢的门店达成率红（v114.6.9.9 规则保留：品牌内 ord.rate / inv.rate 最慢的两家分别红） */
.sd-srow[data-slow-ord] .sd-ord-rate { color: var(--red); }
.sd-srow[data-slow-inv] .sd-inv-rate { color: var(--red); }
/* 品牌行本身不走 data-slow-*，全部默认深灰（品牌行是合计行，不参与"最慢"评比） */

/* 品牌进度表头：4 列（店名 + 拷车 + 订单 + 开票）单行 */
.sd-srow-head {
  display: grid;
  grid-template-columns: minmax(88px, 1fr) repeat(3, 1fr);
  gap: 6px;
  padding: 6px 0 8px;
  border-bottom: 1px solid var(--border);
}
.sd-srow-head .sd-c-name { padding-left: 15px; }
.sd-srow-head .sd-hd-grp {
  text-align: center;
  font-size: 11px;
  color: var(--ink-3);
  font-weight: 600;
  font-family: var(--font-num);
}

/* ── 模块 4 · 门店排行 ── */
.sd-rrow { padding: 8px 0; }
/* v114.6.9.16 肉哥"门店排名这里也改成 订单目标 订单累计 达成率 开票目标 开票累计 达成率"：
   4 列：medal + 门店 + 2 组指标 cell（每组内 3 子项 [目标/累计/达成率]）
   与品牌进度共用 .sd-bmc / .sd-bmc-hd，metric cell 宽度要比原 60px 宽得多（装 3 个子项） */
/* v114.6.9.21 改：序号列 16px → 28px。原 16px 装不下 22×22 的 .pp-rank 圆形奖牌
   （奖牌 flex-shrink:0 会向右溢出 6px 压到店名列上 = 肉哥截图"门店跟序号叠加了"）。
   补偿：店名 76→72px、指标 95→90px，总宽 28+72+2*90=280 ≈ 原 282，360px 卡片仍放得下。 */
.sd-grid.rank { grid-template-columns: 28px minmax(72px, 1fr) repeat(2, minmax(90px, 0.95fr)); }
/* v114.6.9.19 修：原版 .sd-grid.rank 只挂在表头，数据行 .sd-rrow 走 .sd-grid 默认
   4 列 minmax(100px,1.2fr) repeat(3, minmax(56px,1fr)) → metricCell 内部 3 子项被
   挤到下一行，造成"店名跑到累计列"的错位。数据行单独再定义一次列宽 */
/* v114.6.9.20 改：把 170px 缩到 95px，肉哥 9/8 反馈"4 字店名竖排"——总宽 16+76+2*95=282，
   360px 卡片 - 32 padding = 328，留 46px 余量给边距/缩放 */
.sd-rrow { grid-template-columns: 28px minmax(72px, 1fr) repeat(2, minmax(90px, 0.95fr)); }
/* v114.6.9.21 肉哥"后面6列字体大小粗细一致，不要一大一小"：
   原来这里 12 / 15 / 13 三个字号 + 粗细各不相同（目标 12px 细、累计 15px 粗、达成率 13px 中），
   一眼看去参差。现全部统一 13px / 600，只靠颜色区分语义，不再靠字号。 */
.sd-rrow .sd-bmc { gap: 6px; font-size: 13px; font-weight: 400; }
.sd-rrow .sd-bmc-rank { min-width: 0; }
/* v114.6.9.5：justify-content flex-start，序号贴卡片左边缘，不再 25px 大空隙
   v114.6.9.21：min-width 16 → 28px，与 grid 首列同宽，并给奖牌留 3px 右间隙防压到店名 */
.sd-rk { display: flex; align-items: center; justify-content: flex-start; min-width: 28px; padding-right: 4px; }
/* 奖牌在排行里收到 20px（原 22px），28px 列里左右各留 4px，彻底不越界 */
.sd-rk .pp-rank { width: 20px; height: 20px; font-size: 11px; }
.sd-brand-tag {
  font-size: 11px; font-weight: 400; color: var(--ink-3); background: var(--bg); border-radius: 4px;
  padding: 0 4px; flex-shrink: 0; white-space: nowrap;
}
.sd-grid.rank .sd-c-name { padding-right: 6px; }

/* v114.6.9.3 领导反馈 "默认收起来只展示前 5 + 末 5"：中间部分默认折叠 + 灰底分隔条按钮 */
.sd-rank-toggle {
  display: flex; align-items: center; justify-content: center; gap: 4px;
  padding: 7px 0; margin: 2px 0;
  background: #f5f6f8; border-radius: 6px;
  color: var(--ink-2); font-size: 13px; font-weight: 400;
  cursor: pointer; user-select: none;
}
.sd-rank-toggle:active { background: #eaecf0; }
.sd-rank-toggle-ico { font-size: 11px; color: var(--ink-3); transition: transform .18s var(--ease-out); }
.sd-rank-mid { display: none; }  /* 默认折叠 */
.sd-rank-mid.open { display: block; }  /* 展开 */

/* ── 模块 5 · 重点车型 ── */
.sd-km { padding: 10px 0; border-bottom: 1px solid var(--border-2); }
.sd-km:last-child { border-bottom: none; }
.sd-km-hd { display: flex; align-items: center; gap: 6px; margin-bottom: 6px; }
.sd-km-tag { font-size: 13px; font-weight: 400; color: var(--ink-1); line-height: 1.4; word-break: break-all; }
.sd-km-brand { font-size: 11px; font-weight: 400; color: var(--ink-3); background: var(--bg); border-radius: 4px; padding: 1px 5px; flex-shrink: 0; }
.sd-km-rate { margin-left: auto; font-size: 13px; font-weight: 400; font-family: var(--font-num); flex-shrink: 0; }
.sd-km-nums { font-size: 11px; font-weight: 400; color: var(--ink-3); font-family: var(--font-num); margin-bottom: 6px; }
.sd-km-nums b { font-size: 13px; font-weight: 400; color: var(--ink-1); margin-right: 2px; }

/* ── 页脚口径 ── */
.sd-note { margin: 14px 4px 0; font-size: 11px; font-weight: 400; color: var(--ink-3); line-height: 1.65; }

/* ── 空态 / 错误态 ── */
.sd-empty { padding: 22px 8px; text-align: center; font-size: 11px; font-weight: 400; color: var(--ink-3); line-height: 1.7; }
.sd-empty.big { padding: 36px 12px; font-size: 11px; font-weight: 400; }
.sd-empty-ico { display: block; font-size: 26px; opacity: .5; margin-bottom: 8px; }
.sd-err-m { display: block; margin-top: 4px; font-size: 11px; font-weight: 400; color: var(--ink-3); }
.sd-retry {
  display: block; margin: 12px auto 0; border: 1px solid var(--brand); background: var(--surface);
  color: var(--brand); border-radius: 999px; font-size: 11px; font-weight: 400; padding: 6px 18px;
}
.sd-retry:active { background: var(--brand-50); }

/* ── 加载骨架 ── */
.sd-sk { padding: 2px 0; }
.sd-sk-kpi { display: grid; grid-template-columns: repeat(3, 1fr); gap: 8px; margin-bottom: 12px; }
.sd-sk-kpi span { display: block; height: 128px; border-radius: var(--r); }
.sd-sk-card { height: 196px; border-radius: var(--r); margin-bottom: 12px; }
.sd-sk-card.short { height: 132px; }
.sd-sk-kpi span, .sd-sk-card {
  background: linear-gradient(90deg, #eef0f3 25%, #f7f8fa 37%, #eef0f3 63%);
  background-size: 400% 100%;
  animation: sd-shimmer 1.4s ease infinite;
}
@keyframes sd-shimmer { 0% { background-position: 100% 50%; } 100% { background-position: 0 50%; } }

/* ════════════════════════════════════════════════════════════
   v114 重点车型进度（2026-09-07）— 品牌 → 门店 → 车型 三层
   复用 .sd-brow / .sd-brand.open / .sd-stores 的展开机制（bindBody 事件委托）
   ════════════════════════════════════════════════════════════ */

/* 品牌行：左名称 + 右「合计/目标 + 达成率」，点击展开门店 */
.sd-km-brow { display: flex; align-items: center; gap: 8px; }
.sd-km-name { flex: 1; min-width: 0; display: flex; align-items: center; gap: 3px; }
.sd-km-total { display: flex; align-items: baseline; gap: 4px; font-family: var(--font-num); font-variant-numeric: tabular-nums; flex-shrink: 0; }
.sd-km-total b { font-size: 16px; font-weight: 700; color: var(--ink-1); }
.sd-km-total span { font-size: 11px; font-weight: 400; color: var(--ink-3); }
.sd-km-total em { font-size: 13px; font-weight: 400; font-style: normal; }

/* 门店块 + 车型明细 */
.sd-km-store { padding: 6px 0 8px; border-bottom: 1px solid #f0f1f3; }
.sd-km-store:last-child { border-bottom: none; }
.sd-km-store-hd { display: flex; align-items: center; gap: 6px; padding-left: 15px; margin-bottom: 4px; }
.sd-km-store-hd .sd-nm { flex: 1; min-width: 0; }
.sd-km-store-total { font-family: var(--font-num); font-variant-numeric: tabular-nums; font-size: 11px; font-weight: 400; color: var(--ink-3); flex-shrink: 0; }
.sd-km-store-total b { color: var(--ink-1); font-size: 13px; font-weight: 400; }
.sd-km-store-total em { font-style: normal; font-weight: 600; }
.sd-km-models { padding-left: 15px; display: flex; flex-direction: column; gap: 2px; }

/* ════════════════════════════════════════════════════════════
   v114.6.9.9 肉哥反馈：重点车型改成 3 列（订单目标 / 订单累计 / 订单达成率）
   ════════════════════════════════════════════════════════════
   4 列 grid：车型名 + 目标 + 累计 + 达成率
   - 车型名 flex 占主宽（短名多）
   - 目标/累计 右对齐 + tabular-nums（数字按位对齐）
   - 达成率 默认 ink-2（深灰），仅当 rate < timeProgress 时由 JS 加 .sd-km-slow class 标红
   - "一样的车型大小写统一颜色粗细"：用同一个 .sd-km-model-row 渲染，不按值变色
*/
.sd-km-model { display: grid; grid-template-columns: 1fr 38px 38px 42px; align-items: center; gap: 6px; padding: 1px 0; }
/* v114.6.9.44 任务 D②：word-break:break-all → keep-all + overflow-wrap:anywhere
   原 break-all 允许在任意字符间断行，"ES300H" 被劈成 "ES30" / "0H" 两行，
   是渲染 bug 而非风格（车型名是识别主体，断中间等于看不清）。
   keep-all：CJK 与词内不拆；overflow-wrap:anywhere：万一遇到超长无空格串仍能兜底换行。
   同一套组合见上方 .sd-nm（约 :3411 注释）。 */
.sd-km-model .sd-km-tag { font-size: 11px; font-weight: 400; color: var(--ink-2); line-height: 1.4; word-break: keep-all; overflow-wrap: anywhere; min-width: 0; }
/* v114.6.9.21 肉哥"整个销售看板目标/实际/达成率字号粗细一致"：原来 目标/累计 11px 700、
   达成率 11px 600（又小又杂），现统一 13px / 600。
   ★ v114.6.9.45：字号阶梯把这里的 12.5px 提到 13px，旧注释末句「（重点车型列宽 38/42px，
     13px 会挤）」已与代码矛盾，故删除 —— 而且该句在 12.5px 时代就已不成立
     （"128/128" 这类内容在 12.5px 下宽约 45px，早就超出固定的 38px track）。
   ★ 若肉哥看预览觉得挤：改下面 .sd-km-model 的 grid-template-columns 把 track 加宽，
     **不要回头压字号**（字号统一是肉哥明确要求；列宽才是可调的布局参数）。 */
.sd-km-target, .sd-km-actual { font-family: var(--font-num); color: var(--ink-2); flex-shrink: 0; font-size: 13px; font-weight: 400; text-align: right; font-variant-numeric: tabular-nums; }
.sd-km-target b, .sd-km-actual b { color: var(--ink-1); font-weight: 600; }
.sd-km-rate { font-family: var(--font-num); font-weight: 400; flex-shrink: 0; text-align: right; font-size: 13px; color: var(--ink-2); font-variant-numeric: tabular-nums; }
/* 落后于时间进度（rate < timeProgress）：由 JS 比较后加 .sd-km-slow class 染红 */
.sd-km-model.sd-km-slow .sd-km-rate { color: var(--red); }

/* v114.6.9.44 任务 D①：品牌合计落后时同样染红（门店行/车型行早就染红，品牌行漏了）
   肉哥 v114.6.9.9 既定原则是「率不要红色，低于时间进度的才标记为红色」——
   品牌行 .sd-km-total b 恒 var(--ink-1) 永不染红，违背该原则，属缺陷不属风格。
   作用域锁 .sd-km-brow（重点车型品牌行专用类，全仓只有 page-sales.js keyModelHTML 产出），
   不用 .sd-brand —— 那个类被「门店分车系」等模块共用，会误伤。
   .sd-km-brow.sd-km-slow (0,2,0) > .sd-km-total b (0,1,1)，且本块在后，稳赢。 */
.sd-km-brow.sd-km-slow .sd-km-total b { color: var(--red); }

/* ════════════════════════════════════════════════════════════
   v114 门店分车系达成（2026-09-07）— 订单 / 开票两口径
   复用 .sd-brow / .sd-brand.open / .sd-stores 展开机制
   v114.6.7：7 列布局（车系 + 订单 3 子列 + 开票 3 子列）
   肉哥 9/8 反馈 "直接帮我拆成6列，订单目标/累计/达成率；开票目标/累计/达成率"

   ── v114.6.9.35 肉哥 9/10 反馈 ──────────────────────────────
   「订单和开票 6 列都显示不全了，而且这个品牌汇总数上下还是没有对齐」
   两个根因：
   A. 溢出被裁：旧列宽 90 + 6×min(64) = 474px（最小总宽），而 375px 屏
      可用宽只有 ~334px → 474 > 334 必然溢出；.card 是 overflow:hidden
      （见上方 .card 定义）→ 右侧列直接被裁掉，连滚动条都没有。
   B. 品牌行不是 grid：品牌行 HTML class = "sd-brow sd-sb-brow sd-sb-brow-7col"，
      .sd-sb-brow 区块里 .sd-brow.sd-sb-brow { display:flex }（weight 2）
      压过了 .sd-sb-brow-7col { display:grid }（weight 1）
      → grid-template-columns 完全失效，品牌行的 6 个数字按 flex 自然排，
        自然跟上下行对不齐。已用 :not(.sd-sb-brow-7col) 隔离修掉。

   ── v114.6.9.38 肉哥 9/10 追加 ──────────────────────────────
   C. CSS 变量作用域：表头 + 东昌合计 + 品牌行原先平铺在 .card-bd 下、
      不是 .sd-sb 的后代 → var(--sd-sb-cols) 取不到值 → grid-template-columns
      整条失效 → 退化成「每项一行」竖排。已在 JS 里给它们套 .sd-sb 公共祖先。
   D. grid-template-columns 被 !important 抢：line ~4270 的
      `.sd-brow { grid-template-columns: minmax(88px,1fr) minmax(150px,1.6fr) !important }`
      无 :not() 隔离 → 压过 .sd-sb-brow-7col → 品牌行只剩 2 列。已加 :not()。
   E. **真实可用宽被算多了**：本节上面的旧预算写"375 屏 → 可用 349px"是错的，
      漏扣了一层。实测 .card 左右各 1px border、.card-bd.sd-bd 左右各 12px padding，
      再叠加 .card 自身 margin，375px 下 grid 行真正能吃到的内容宽只有 **321px**
      （行盒 321，减自身 padding-left 15 → 内容 306px）。
      而旧档 `64 + 6×44 + 6×2 = 340px` 的**最小**需求就 340 > 306 → 必然右溢 34px，
      第 7 列被裁掉；同时首列 64px 也放不下「雷克萨斯 + 2 店」(需 ~71px) → 店名被裁。
      这就是肉哥截图里"最后那列没了 / 名字被切一半"的来源。
      现按真实可用宽重排（见下方预算表），并给首列留足 71px 的名+计数宽度。

   ★ 单一事实来源：7 列宽只在这里定义一次 --sd-sb-cols，所有行共用。
     以前 .sd-sb-head/.sd-sb-row、.sd-sb-hd-grp、.sd-sb-brow-7col 各写一遍
     同样的字面值，改一处漏两处就是"错位"的温床。照搬 Tab 2 的 --spf-od-cols 模式。
     任何列宽调整：只改 --sd-sb-cols 一行，表头/合计/品牌/车系/单店合计 五行自动同步。
   ════════════════════════════════════════════════════════════ */
/* 7 列 = 1 车系 + 3 订单(目标/累计/达成率) + 3 开票(目标/累计/达成率)
 *
 *  ── 宽度预算（v114.6.9.38 实测重算）──────────────────────────────────
 *   ★ 教训：旧注释按"屏宽 − border − padding"手算，得到 349px，与实测差 40+px
 *     —— 漏算了卡片外层容器的 margin（预览页 14px、真实页面 App 容器另有留白）。
 *     手算不可靠，**以实测的「行内容宽」为准**，下表为 Chromium 实测值：
 *
 *       视口    行盒宽   行内容宽(减自身 pl)   本档选用列宽                   校验
 *       ─────  ───────  ─────────────────  ────────────────────────────  ────────────
 *       320     266       258 (pl 8)         46 + 6×38 + 12(gap) = 286   ❌ 超 28
 *       320     —         → 收窄档见下      44 + 6×33 + 12      = 254   ✅ 余 4
 *       360     306       298 (pl 8)         44 + 6×33 + 12      = 254   ✅ 余 44
 *       375     321       306 (pl 15)        56 + 6×40 + 12      = 308   ✅ 余 -2 →见下
 *       390     336       321 (pl 15)        56 + 6×40 + 12      = 308   ✅ 余 13
 *       414     360       345 (pl 15)        96 + 6×38 + 12      = 336   ✅ 余 9
 *       430     376       361 (pl 15)        96 + 6×38 + 12      = 336   ✅ 余 25
 *
 *   ★ 375 档说明：内容宽 306，而 1fr 会把 6 个数字列均分到
 *     (306 − 56 − 12) / 6 = 39.67px，此时最小需求 56 + 6×36 + 12 = 284 ≤ 306 ✅
 *     —— minmax 的 **min 是一道下限保险**，真正的列宽由 1fr 均分决定，
 *     所以只要「min 之和 ≤ 内容宽」就不会溢出，不会真的按 min 排。
 *
 *   ★ 字号保持 14px 不动（肉哥 9/8 拍板"字体好小好小"上调过，不能再缩回 10px 档） */
.sd-sb {
  --sd-sb-cols: 56px repeat(6, minmax(36px, 1fr));
  /* 表格左内边距：所有行的列起点必须一致，统一从这里取。
     表头/车系行/单店合计行取 15px；品牌行/东昌合计行有 1px 边框 + 6px 圆角底，
     取 13+1=14px → 内容与列 1 左边缘落在同一条 x 上（视觉对齐）。 */
  --sd-sb-pl: 15px;
}
.sd-sb-head, .sd-sb-row {
  display: grid;
  grid-template-columns: var(--sd-sb-cols);
  align-items: center;
  gap: 2px;
  padding: 7px 0 7px var(--sd-sb-pl);
  font-family: var(--font-num);
}
/* ── v114.6.9.38 肉哥 9/10「所有字体保持大小粗细一致」────────────────────
   统一定义「门店分车系达成」板块的字阶（就地写清，改这里就够，别再各处各写一遍）：

     档位        字号      字重    用在哪
     ─────────  ────────  ─────  ──────────────────────────────────────────
     数据·数字    14px      600    订单/开票 的目标·累计·达成率（6 个数字列）
     数据·文字    14px      600    车系名、门店名、品牌名、东昌合计名（层级标题）
     表头         12px      600    车系 / 目标 / 累计 / 达成率 / 订单 / 开票
     次要元信息    12px      600    「3 品牌」「2 店」这类计数

   三条规矩：
   ① 同一档位内字号字重必须完全一致 —— 这是肉哥这次的核心诉求。
   ② 表头比数据小一档（12 vs 14）是常规做法，但**表头内部四者必须全等**
      （原来 .sd-sb-hd-sub 是 500、其余是 600 → 已全部拉平到 600）。
   ③ 层级标题不再用 15px（原来 .sd-nm-brand / .total .sd-nm 是 15px），
      与数字拉齐到 14px，靠 600 字重区分层级，不靠字号。
   ★ 颜色不属于字阶范畴，本轮一律不动（达成率红/橙/蓝/绿仍由 JS 内联 style 给）。 */

/* v114.6.9.10 肉哥反馈 "这页的字体可以大些不，现在好小好小"
   字号全面上调：内容 11→13px、率 10.5→12px、表头 9.5/10→11/12px、系列名 12→14px
   v114.6.9.22 肉哥 9/9 反馈"再大些"：表头 11→12、cell 13→14、率保持 14、店名 12→14
   v114.6.9.38 肉哥 9/10"大小粗细一致"：见上方字阶表，数字列字重补 600
   ★ 数字仍保留 tabular-nums，按位对齐不乱 */
.sd-sb-head { font-size: 12px; color: var(--ink-3); font-weight: 600; border-bottom: 1px solid #f0f1f3; }
.sd-sb-row { border-bottom: 1px solid #f0f1f3; }
.sd-sb-row:last-child { border-bottom: none; }
/* v114.6.9.30 改：数字列居中对齐（消除右贴边"散开"视感）
   v114.6.9.38：字重补 600 —— 原来目标/累计这 4 列是 400、达成率 2 列是 600，
   同一行里字重不一致正是肉哥说的"粗细不一致"，现统一 600。 */
.sd-sb-cell {
  text-align: center; font-size: 13px; font-weight: 400;
  color: var(--ink-2); min-width: 0; line-height: 1.4;
}
/* 车系名：层级标题 → 14px/600（原 500，与数字列统一到 600） */
.sd-sb-cell.series { text-align: left; font-size: 13px; color: var(--ink-1); font-weight: 400; }
/* v114.6.9.21：达成率 12px → 13px，与同行的目标/累计（.sd-sb-cell 13px）对齐
   v114.6.9.22：13→14，跟主体一致
   v114.6.9.38：字重与 .sd-sb-cell 合并（同为 600），此处不再重复声明 */
.sd-sb-cell.rate { font-size: 13px; font-weight: 400; }
.sd-sb-cell.muted { color: var(--ink-4); }
/* v114.6.9.21：b 统一 600
   v114.6.9.38 ★ 注意：肉哥这次要"粗细一致"，所以**不再给 b 加粗到 700**，
   保持 600 与同行的目标/累计列齐平（原来 b 若是 700 会显出"累计比目标粗"）。 */
.sd-sb-cell b { color: var(--ink-1); font-weight: 600; }
/* 表头：6 个内容列简写分组（"订单" 横跨 3 列 + "开票" 横跨 3 列）
   v114.6.9.38：.sd-sb-hd-sub 由 500 提到 600，使表头四者字重全等 */
.sd-sb-hd-group { font-size: 12px; color: var(--ink-3); font-weight: 600; text-align: center; }
.sd-sb-hd-sub { font-size: 12px; color: var(--ink-3); font-weight: 600; text-align: right; }
.sd-sb-hd-series { font-size: 12px; color: var(--ink-3); font-weight: 600; text-align: left; }
/* v114.6.9.35 表头分组行：列宽改为 var(--sd-sb-cols)（与所有数据行同一事实来源）
   ★ 必须与 .sd-sb-head/.sd-sb-row 共用同一个变量 + 同一个 --sd-sb-pl，
     否则表头与数据行会横向错位（历史上就是这么错的）。 */
.sd-sb-hd-grp {
  display: grid;
  grid-template-columns: var(--sd-sb-cols);
  align-items: center;
  gap: 2px;
  padding: 6px 0 6px var(--sd-sb-pl);
  font-family: var(--font-num);
  background: #fafbfc;
  border-bottom: 1px solid #f0f1f3;
  font-size: 12px;
  color: var(--ink-2);
  font-weight: 600;
}
.sd-sb-hd-grp-ord { grid-column: 2 / 5; text-align: center; }
.sd-sb-hd-grp-inv { grid-column: 5 / 8; text-align: center; }
.sd-sb-hd-grp-series { grid-column: 1; }
.sd-sb-series { font-size: 13px; font-weight: 400; color: var(--ink-1); min-width: 0; line-height: 1.4; word-break: break-all; }
.sd-sb-metric { text-align: right; font-size: 13px; font-weight: 400; color: var(--ink-2); }
.sd-sb-metric b { color: var(--ink-1); font-weight: 600; }
/* v114.6.9.21：12px → 13px，与 .sd-sb-cell 主体字号一致 */
.sd-sb-rate { display: block; font-size: 13px; font-weight: 400; }

/* v114.6.4 门店分车系：按品牌合并后，品牌行右侧的「订单 / 开票」合计
   v114.6.9.22 肉哥 9/9 反馈"板块字体大些"：11px → 12px（仍略小，保持与系列名/率区分） */
.sd-sb-brow-metric {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 4px;
  font-family: var(--font-num);
  font-variant-numeric: tabular-nums;
  font-size: 13px;
  font-weight: 400;
  color: var(--ink-2);
  text-align: right;
  min-width: 130px;
  flex-shrink: 0;
}
.sd-sb-brow-metric b { color: var(--ink-1); font-weight: 600; }
.sd-sb-brow-metric em { font-style: normal; font-weight: 400; font-size: 11px; }
.sd-sb-brow-metric em { font-style: normal; font-weight: 400; font-size: 11px; }

/* v114.6.9.26 品牌/合计头部用 7 列 grid（与单店行 .sd-sb-row 完全对齐）
 *  改前 .sd-sb-brow-metric 是单行 6 数字横排 + 单独列布局，与单店 7 列不上下对齐。
 *  改后品牌行变成"车系名 + 订单目标/累计/达成率 + 开票目标/累计/达成率" 7 列布局。
 *  v114.6.9.35：列宽改为 var(--sd-sb-cols)，与 .sd-sb-head/.sd-sb-row/.sd-sb-hd-grp 同源。
 *  ★ 品牌行/合计行自带 1px 边框，border-box 下内容左边缘比无边框行多 1px
 *    → --sd-sb-pl 取 14px（15−1）抵消，使第 1 列左边缘与表头/车系行严格落在同一 x。 */
.sd-sb-brow-7col {
  display: grid;
  grid-template-columns: var(--sd-sb-cols);
  align-items: center;
  gap: 2px;
  --sd-sb-pl: 14px;
  padding: 9px 0 9px var(--sd-sb-pl);
  font-family: var(--font-num);
  font-variant-numeric: tabular-nums;
  border-radius: 6px;
}
/* ★ v114.6.9.38 首列「品牌名 + n 店」的布局与显隐
 *   需求：最长组合「东昌合计」(56px) + 6px margin + 「3 品牌」(38.5px) ≈ 100.5px。
 *   ⚠ 试过并否掉的三种写法（都出过可见缺陷）：
 *     A. 名字与计数都 `flex: 0 1 auto` → flex 按比例压缩，
 *        品牌名被挤到 14.83px（需 56px），名字几乎看不见。
 *     B. 名字 `flex: 0 0 auto` + 计数 `flex: 1 1 0` → 名字完整，
 *        但容器 scrollWidth 报 125 > 子项之和 100，末尾「牌」被切掉。
 *     C. 容器 `display: block` + `text-overflow: ellipsis` → 反而把整个
 *        品牌名当成一段可截断文本，名字被截（实测 3~4 行都 nameClip）。
 *   ✅ 采用：flex + 名字 `flex: 0 0 auto` 不压缩 + 计数在窄屏**整体 display:none**。
 *      关键差别在于"计数宽度为 0 但仍占位"和"计数不存在"是两回事 ——
 *      只有彻底 display:none，flex 才不会为它预留尺寸，名字才能独占整列。
 *      而"是否显示计数"完全由 --sd-sb-cols 的首列宽档位决定（见文末媒体查询），
 *      不做运行时测量，所以绝不会出现半截字。 */
.sd-sb-brow-7col .sd-c-name {
  min-width: 0;
  display: flex;
  align-items: baseline;
  flex-wrap: nowrap;
  white-space: nowrap;
  overflow: hidden;
}
.sd-sb-brow-7col .sd-nm-brand {
  white-space: nowrap;
  flex: 0 0 auto;      /* 品牌名优先，绝不压缩、绝不截断 */
}
/* 计数：随首列宽度决定是否显示（见文末媒体查询），这里只管字号字色 */
.sd-sb-brow-7col .sd-cnt { white-space: nowrap; }
/* 首列 96px（≥414px 档）：完整显示「n 品牌 / n 店」 */
@media (max-width: 413px) {
  .sd-sb-brow-7col .sd-cnt { display: none; }
}
.sd-sb-brow-7col.brand { background: #f5f8fc; border: 1px solid #e3ecf5; }
.sd-sb-brow-7col.total {
  background: linear-gradient(90deg, #fff5f5, #fff);
  border: 1px solid var(--red, #ef4444);
  margin-bottom: 6px;
}
/* v114.6.9.38 字号统一：合计行品牌名 15px → 14px（与品牌名/车系名/数字齐平，见文末字阶说明） */
.sd-sb-brow-7col.total .sd-nm { color: var(--red, #ef4444); font-size: 13px; font-weight: 400; }
/* 让 .sd-sb-brow-7col 里的 .sd-c-name 撑满首列（与单店行 .sd-sb-cell.series 一致宽度） */
.sd-sb-brow-7col > .sd-c-name { font-weight: 600; }

/* v114.6.4 门店块（品牌 → 门店 → 车系 三层）
   v114.6.9.22 肉哥 9/9 反馈"品牌和门店矫揉在一起看不出哪行是品牌哪行是门店"：
   门店块加 #fafbfc 浅灰底色 + 8px 上边距 → 跟品牌行（白底）形成对比 */
.sd-sb-store {
  padding: 8px 0 4px;
  border-top: 1px solid #f0f1f3;
  background: #fafbfc;
  border-radius: 4px;
  margin-top: 6px;
}
.sd-sb-store:first-child { border-top: none; padding-top: 2px; }
.sd-sb-store-hd {
  display: flex;
  align-items: center;
  padding: 6px 0 6px 18px;
  /* v114.6.9.22 字号 12→14，肉哥"板块字体大些" */
  font-size: 13px;
  font-weight: 400;
  color: var(--ink-1);
}
/* v114.6.9.38 字号统一：门店名 14px/600
 *   ⚠ 必须写成 `.sd-sb-store-hd .sd-nm`（0,2,0）之外再加一层 .sd-sb，
 *     否则被 line 3343 的旧规则 `.sd-brow .sd-nm { font-size:12.5px; font-weight:400 }`
 *     （同为 0,2,0，但源码更靠前 → 其实是被它按源码顺序压住）抢走，
 *     实测门店名还是 12.5px，与同板块的 14px 车系名/品牌名不一致。
 *     那条 12.5px 是 v114.6.9.3 给「品牌进度/门店排行」定的，属于别的模块，
 *     这里不改它，只把「门店分车系」作用域提权，避免打翻已验证的其它板块。 */
.sd-sb .sd-sb-store-hd .sd-nm { font-weight: 400; font-size: 13px; }

/* v114.6.9.2 单店合计行：上边框分隔 + 浅灰底，让肉哥一眼看出单店总体达成
 * v114.6.9.38 肉哥 9/10「所有字体大小粗细一致」：
 *   原来这里把 series/b/rate 全抬到 700，而车系行/品牌行/东昌合计行都是 600，
 *   同一板块里出现两种粗细 → 正是"粗细不一致"。
 *   现统一回 600（= 板块标准字重），该行的"合计"语义改由
 *   上边框 + #fafbfc 底色 + --ink-1 深色文字 三个视觉手段承担，不再靠加粗抢占。 */
.sd-sb-row.sd-sb-total {
  border-top: 1px solid var(--border-2);
  background: #fafbfc;
}
.sd-sb-row.sd-sb-total .sd-sb-cell { color: var(--ink-1); font-weight: 600; }
.sd-sb-row.sd-sb-total .sd-sb-cell.series { font-weight: 600; }
.sd-sb-row.sd-sb-total .sd-sb-cell b { font-weight: 600; }
.sd-sb-row.sd-sb-total .sd-sb-cell.rate { font-weight: 600; }

/* v114.6.4 品牌行（带右侧合计）：flex 让 .sd-c-name + .sd-sb-brow-metric 水平排
   v114.6.9.22 肉哥 9/9 反馈"品牌和门店矫揉在一起"：品牌行加白底 + padding +
   brand 名加粗突出，hover 给浅蓝提示（补回 v114.6.9.22 移除 ▸ 后的折叠提示）
   ★ v114.6.9.35 肉哥 9/10 "品牌汇总数上下还是没有对齐" —— 根因就在这里：
     品牌行 HTML class = "sd-brow sd-sb-brow sd-sb-brow-7col"，同时命中
       .sd-brow.sd-sb-brow       (0,2,0)  ← 本块，display:flex
       .sd-sb-brow-7col          (0,1,0)  ← 7 列 grid
     同属性 display 上 weight 2 压过 weight 1 → 品牌行实际是 flex，
     grid-template-columns 整条失效 → 6 个数字跟上下行对不齐。
     修复：用 :not(.sd-sb-brow-7col) 把这条 flex 布局限定在「非 7 列品牌行」上。
     ⚠ v114.6.9.38 补充：同一次事故**还有第二处漏网**，见下方 line ~4270 的
       `.sd-brow { grid-template-columns: ... !important }` —— 那次只修了 display，
       没修同区块的 grid-template-columns，!important 仍然压过 7 列模板。
       两处都加了 :not() 之后，品牌行/东昌合计行的 7 列才真正生效。
     7 列品牌行/东昌合计行从此走 .sd-sb-brow-7col 的 grid，且列宽与表头同源。
     下面只留与布局无关的视觉属性（白底/圆角/边框/hover/cursor），
     它们对 grid 行同样需要，所以不外移、也不加 :not。 */
.sd-brow.sd-sb-brow:not(.sd-sb-brow-7col) {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  padding: 8px 10px;
}
.sd-brow.sd-sb-brow {
  background: #fff;
  border-radius: 6px;
  border: 1px solid #e8f0f9;
  cursor: pointer;
  transition: background .12s var(--ease-out);
}
.sd-brow.sd-sb-brow:hover { background: #f5f8fc; }
/* v114.6.9.38 字号统一：品牌名 15px → 14px（层级靠 600 字重区分，不靠字号，见字阶表） */
.sd-brow.sd-sb-brow .sd-nm-brand {
  font-size: 13px;
  font-weight: 400;
  color: var(--ink-1);
}
/* v114.6.9.38 字号统一：「n 品牌 / n 店」计数原 11.5px/400 → 12px/600（与表头同档） */
.sd-brow.sd-sb-brow .sd-cnt {
  margin-left: 6px;
  font-size: 11px;
  color: var(--ink-3);
  font-weight: 400;
}
/* ── 首列「品牌名 + n 店」的显隐，完全跟着 --sd-sb-cols 的首列宽走 ──
 *   实测需求：最长组合「东昌合计」(56) + 6 margin + 「3 品牌」(38.5) ≈ 100.5px。
 *   ★ 只在这两个档位之间二选一，不做运行时测量 —— 避免出现"半截字"：
 *     首列 < 101px：放不下 → 隐藏计数，只显示品牌名（375/390/360/320 档）
 *     首列 ≥ 101px：放得下 → 显示计数（≥414 档，首列 112px） */

/* 窄屏（≤413px）：首列 40~56px，计数必然放不下 → 整个隐藏，只留品牌名。
   同时去掉 6px margin，避免留下突兀空白。
   ⚠ 选择器必须写成 `.sd-brow.sd-sb-brow .sd-cnt`（0,3,0）才能压过上面那条
     带 margin-left:6px 的同名规则；写成 `.sd-sb-brow-7col .sd-cnt`（0,2,0）
     会因权重不足而失效（实测 margin 仍是 6px）。 */
@media (max-width: 413px) {
  .sd-brow.sd-sb-brow .sd-cnt { display: none; }
}
/* 宽屏（≥414px，如 iPhone Plus / 安卓大屏）：首列加宽到 128px，
   让「品牌名 + n 店」两个都能完整显示。
   ★ 宽度算法（易错点）：--sd-sb-cols 的首列值是 **grid 轨道宽**，
     而文字实际可用宽 = 轨道宽 − 行自身左内边距(--sd-sb-pl = 15 / 14px)。
     实测 430px 下「东昌合计」+「3 品牌」需要 104.45px 的**文字**宽，
     故轨道宽至少要 104.45 + 15 ≈ 119.5px；取 128px 留 8px 余量。
     之前写 96 / 104 / 112 都是在"忘了减 padding"的前提下算的，所以总是差几个 px，
     表现就是末尾的「牌」被切掉半个字。 */
@media (min-width: 414px) {
  .sd-sb { --sd-sb-cols: 128px repeat(6, minmax(36px, 1fr)); }
}

/* v114.6.9.35 窄屏兜底（≤360px，如 iPhone SE 1st / 老安卓 320-360px）
   ★ v114.6.9.38 按**实测内容宽**收紧（见上方预算表）：
     360px 实测内容宽 298、320px 只有 258。
       320 − 2(card border) − 24(padding) ≈ 294 是错的（漏了外层 margin），
       实测 320px 下行盒仅 266 → 内容宽 258。
     故这一档必须按 320 排：
       pl 8 + 车系 44 + 6×33 + 6×2(gap) = 8 + 44 + 198 + 12 = 262 … 略超 258
     再收一点，把车系压到 40、数字列 32：
       8 + 40 + 6×32 + 12 = 252 ≤ 258 ✅ 余 6px
     ★ 不动字号（14px 是肉哥拍板的），只收列宽 + 行内边距。 */
@media (max-width: 360px) {
  .sd-sb { --sd-sb-cols: 40px repeat(6, minmax(32px, 1fr)); --sd-sb-pl: 8px; }
  .sd-sb-brow-7col { --sd-sb-pl: 8px; }
  .sd-sb-head, .sd-sb-row { padding: 6px 0 6px var(--sd-sb-pl); }
  .sd-sb-hd-grp { padding: 5px 0 5px var(--sd-sb-pl); }
  .sd-sb-brow-7col { padding: 8px 0 8px var(--sd-sb-pl); }
}

/* ════════════════════════════════════════════════════════════
   v114 三 Tab + 走势 tooltip（2026-09-07）
   ════════════════════════════════════════════════════════════ */
/* ════════════════════════════════════════════════════════════════════════════
 * v114.6.9.44 · 【全站「表头 Tab」的唯一规范 · SINGLE SOURCE OF TRUTH】
 * ────────────────────────────────────────────────────────────────────────────
 * 肉哥 9/11 反馈：「我们这个 H5 是一个整体，能不能把样式做一个统一……我比较喜欢
 *   库存看板里的 tab 样式，胶囊，选中的蓝色底纹」。
 *
 * 统一前全站共 6 种 tab 样式：
 *   ① .sd-tabs / .sd-tab.on           销量看板      蓝字 + 32px 蓝色下划线
 *   ② .spf-tabs / .spf-tab.active     毛利预警      浅灰容器 + 白底药丸
 *   ③ .seg.seg-tab#iv-subtab          库存看板★基准 蓝色渐变底 + 白字 + 阴影
 *   ④ .sales-tabs.seg / .seg-item     交车 / 新保     iOS 灰底 + 白色滑块
 *   ⑤ .sd-bm-tabs / .sd-bm-tab        品牌进度小 tab  另一种小胶囊
 *   ⑥ .sp-tabs / .sp-tab.on           订单页装潢弹层 浅蓝底 + 蓝字
 * ⇒ ①~⑤ 已收敛到本段（③ 的取值就是规范本身）。**⑥ 刻意不纳入，理由见文末。**
 *    新页面直接写 `<div class="tab-pill"><span class="on">…</span></div>` 即得规范样式，
 *    **不要再造第 7 种。**
 *
 * ★★ 为什么不靠"文件末尾追加覆盖"：
 *    库存那套蓝色原本挂在 id 选择器 `#iv-subtab .seg-item.active`(1,2,0) 上，
 *    特异性高过任何类组合。若只在末尾追加新规则，`#iv-subtab` 仍会赢，
 *    而其它看板走 `.seg-item.active`(0,2,0) 的白底 → 反而多出第 7 种样式。
 *    ⇒ 所以下面这些旧规则**已在各自原处删除**（不是被覆盖）：
 *      · #iv-subtab / #iv-subtab .seg-item / #iv-subtab .seg-item.active  ← 原 :2386-2412
 *      · #iv-subtab（窄屏 media query 内两条）                            ← 原 :2525-2526
 *      · .seg-tab / .seg-tab .seg-item                                    ← 原 :2039-2040
 *      · .sd-tabs / .sd-tab / .sd-tab::after / .sd-tab.on / .on::after    ← 原 :3901-3944（本段原位替换）
 *      · .spf-tabs / .spf-tab / .spf-tab.active                           ← 原 :4492-4501
 *      · .sd-bm-tabs / .sd-bm-tab / .sd-bm-tab:active / .sd-bm-tab.on     ← 原 :4324-4340
 *      · .sales-tabs                                                      ← 原 :2762
 *
 * ── 规范取值 ────────────────────────────────────────────────────────────────
 *   容器   ：一排等宽胶囊，**无外层灰底**
 *            display:flex; gap:6px; padding:0; background:transparent; border:none
 *   未选中 ：白底描边胶囊  background:#fff; border:1px solid var(--border);
 *            color:var(--ink-2); border-radius:12px; font-size:14px / 500
 *   选中   ：蓝色底纹胶囊  background:linear-gradient(135deg,#3b82f6,#2563eb);
 *            color:#fff; border-color:transparent; shadow 0 4px 12px rgba(37,99,235,.28)
 *   小号   ：.sd-bm-tab（嵌在卡片标题行，放不下 12px padding）
 *            font-size:13px; padding:5px 12px; border-radius:9px
 *
 * ★ 左右外边距统一 **12px**（而不是 14px）：
 *   所有 tab 宿主页面的"内容区左边距"都是 26px ——
 *     `.page{padding:14px}` + `.dash / .sales / .sales-daily{padding:12px}` = 26px；
 *   毛利页 `.spf` 在 `.sub-body{padding:14px}` 里 = 14px。
 *   tab 再内缩 12px = 38px / 26px，**这正好复刻肉哥点名"喜欢"的那套库存 tab 实测边距**
 *   （原 `#iv-subtab{margin:4px 12px 12px}` 在 `.dash` 里就是 14+12+12 = 38px）。
 *   即：每个看板的 tab 都比它自己的内容区窄 12px —— 这是被点赞的视觉关系，
 *   所以 12px 是量出来的，不是随手取的。
 *   ⚠ **不要再"优化"成 14px**（v114.6.9.44 任务书初稿拍的就是 14px，被否）：
 *     14px 是只盯 `margin` 绝对值拍出来的，没算宿主容器边距；
 *     改 14px 后库存 tab 实距会从 38px 变 40px，与肉哥点赞的那版不等价。
 *     判定依据是 **38px 这个实测值**，不是 margin 数字本身。
 *
 * ★ `.seg-tab` 在**卡片内**单独放宽到 14px：它要对齐 `.card-h{padding:12px 14px}`
 *   的 14px，否则与卡片标题左右错位（见下方 `.card > .seg-tab`）。
 *
 * ★ `.seg` / `.seg-item` 的**基础类一律不改**：
 *   `.seg` 还被 UI.segment() 复用作"非 tab 的分段控件"
 *   （page-delivery / page-traffic / page-order 的 `<div class="segment"><span class="seg">`），
 *   以及 page-dashboard 的 `#seg-gran`（月/周/日）、`#seg-status`（有效/全部/已交车）。
 *   改 `.seg` 本体 = 连带改 4 个页面 → 只让 `.seg-tab` 覆盖。
 *
 * ★ `.sp-tabs`（⑥）**已登记为"已知例外"，永远不纳入本规范**（team-lead 9/11 裁决）：
 *   它挂在**订单页「装潢搜索弹层」内部**（`.sp-tabs{display:flex;gap:8px;padding:10px 16px 0}`，
 *   同行还有 `.sp-star` 星标），是弹层里的「常用收藏 / 全部」列表范围筛选 chip，
 *   内容宽度、`border-radius:16px` 自带胶囊外形。
 *   它不是等宽表头 tab；强行套等宽蓝胶囊会让一个 2 项筛选看起来像板块切换器，
 *   改变弹层的信息层级。
 *   ⚠⚠ **后来者注意：`.sp-tabs` 不是"漏网的第 7 种 tab"，是故意留的例外。
 *      不要拿它当反例去"补统一"，也不要把它改成本段的样式 —— 那会破坏弹层信息层级。**
 *      判定标准：本段的 5 个都是「整页/整板块的等宽表头切换器」；
 *      `.sp-tabs` 是「弹层内的多项筛选 chip」，语义不同故形态不同。
 *      （同类例外还有 `.seg-gran` / `.seg-status`：它们是分段控件，不是 tab。）
 * ════════════════════════════════════════════════════════════════════════════ */

/* ── ① 容器：一排等宽胶囊，无外层灰底 ─────────────────────────────────────── */
.tab-pill,
.sd-tabs,
.spf-tabs,
.sales-tabs.seg,
.seg-tab {
  display: flex;
  /* ★ v114.6.9.44 修：wrap 而不是 nowrap。
     交车看板 #rm-tabs 有 **6 项**（总览/分产品/门店/营销员/趋势/明细），
     nowrap + 子项 flex:1 1 0 + overflow:hidden 会把「分产品」压出容器**裁字** ——
     浏览器实测：320px 裁 14px / 375px 裁 9px / 414px 裁 6px / 430px 裁 4px，全屏宽都裁。
     改成 wrap 后，6 项自动折成 3+3 两行（子项 flex-basis 30%），文字不再被压。
     2 项 / 3 项的看板（库存 / 销量 / 毛利 / 新保）仍然只占一行，视觉零变化。
     不用 overflow-x:auto 兜底：那会把 overflow-y 也变成 auto，
     连带把选中胶囊的 0 4px 12px 阴影裁平 —— 恰好毁掉肉哥点赞的那套观感。 */
  flex-wrap: wrap;
  align-items: stretch;
  gap: 6px;
  margin: 0 12px 10px;
  padding: 0;
  background: transparent;
  border: none;
  border-radius: 0;
  /* ★ overflow 必须 visible：选中胶囊带 0 4px 12px 阴影，overflow:auto 会把下缘裁平 */
  overflow: visible;
  flex: none;
  min-width: 0;
  -webkit-tap-highlight-color: transparent;
}
/* 兼容旧写法：仍想横向滚动时不显示滚动条 */
.tab-pill::-webkit-scrollbar,
.sd-tabs::-webkit-scrollbar,
.spf-tabs::-webkit-scrollbar,
.sales-tabs.seg::-webkit-scrollbar,
.seg-tab::-webkit-scrollbar { display: none; }

/* ── ② 未选中项：白底描边胶囊 ────────────────────────────────────────────── */
.tab-pill > *,
.sd-tab,
.spf-tab,
.sd-bm-tab,
.seg-tab .seg-item,
.sales-tabs.seg .seg-item {
  /* ★ 基准 30%（不是 0）：配合容器 flex-wrap:wrap，3 项/行 → 6 项恰好折成 3+3。
     取 0 的话每项按内容宽参与折行，6 项会折成 5+1 这种难看的分行。
     对 2 项 / 3 项的看板：basis 30% × 项数 < 100%，flex-grow 再把它们拉满整行，
     所以 3 项仍是三等分、2 项仍是二等分 —— 与 basis:0 的观感完全一致。 */
  flex: 1 1 30%;
  min-width: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 5px;
  padding: 12px 14px;
  border: 1px solid var(--border);
  border-radius: 12px;
  background: #fff;
  color: var(--ink-2);
  font-size: 13px;
  font-weight: 400;
  font-family: inherit;
  line-height: 1.2;
  text-align: center;
  white-space: nowrap;
  cursor: pointer;
  user-select: none;
  -webkit-tap-highlight-color: transparent;
  overflow: hidden;
  box-shadow: 0 1px 2px rgba(15,23,42,.04);
  transition: background .15s, color .15s, box-shadow .15s, border-color .15s;
}

/* ── ③ 选中项：蓝色底纹胶囊（肉哥点名的"蓝色底纹"） ────────────────────────
 * ★ 选择器顺序：`.sd-bm-tab.on` 刻意放在**末尾**（紧贴 `{`）—— 既有测试
 *   `test-v114-brand-html.js:22.3` 用 `/\.sd-bm-tab\.on\s*\{[^}]*font-weight:\s*600/`
 *   校验"active 态 600 + 阴影"，需要该选择器直接接 `{`。放在这里既满足既有回归，
 *   又不必为它单开一条重复规则（保持"唯一规范"不出现第二处定义）。 */
.tab-pill > .on,
.tab-pill > .active,
.sd-tab.on,
.spf-tab.active,
.seg-tab .seg-item.active,
.sales-tabs.seg .seg-item.active,
.sd-bm-tab.on {
  background: linear-gradient(135deg, #3b82f6, #2563eb);
  color: #fff;
  font-weight: 600;
  border-color: transparent;
  box-shadow: 0 4px 12px rgba(37,99,235,.28);
}
/* 选中项里的小图标也要变白（否则原 `.seg-item.active .ico{color:var(--brand)}` 在蓝底上看不见） */
.seg-tab .seg-item.active .ico,
.sales-tabs.seg .seg-item.active .ico { color: #fff; }

/* ── ④ 未选中项的 hover / active 反馈 ─────────────────────────────────────
 * ★ 必须显式写：`.seg-item:not(.active):hover`(:1893) 是 (0,2,0)，与本段
 *   `.seg-tab .seg-item`(0,2,0) 特异性相同，而本段在文件更后面 → 会把它压掉。
 *   写到 (0,3,0) 以上才能把反馈恢复回来。 */
.tab-pill > *:not(.on):not(.active):hover,
.sd-tab:not(.on):hover,
.spf-tab:not(.active):hover,
.sd-bm-tab:not(.on):hover,
.seg-tab .seg-item:not(.active):hover,
.sales-tabs.seg .seg-item:not(.active):hover { background: var(--surface-2); }
.tab-pill > *:not(.on):not(.active):active,
.sd-tab:not(.on):active,
.spf-tab:not(.active):active,
.sd-bm-tab:not(.on):active,
.seg-tab .seg-item:not(.active):active,
.sales-tabs.seg .seg-item:not(.active):active { background: var(--hover); }

/* ── ⑤ 小号变体：.sd-bm-tabs（品牌进度卡片标题行右侧的 拷车/订单/开票） ────
 * 肉哥 9/9 反馈"字体再大一点"：11.5px → 13px、padding 4×10 → 5×12、min-width 36 → 42。
 * 统一时**保留这套尺寸**（卡片标题行放不下 12px padding），只把
 * 容器灰底 / 描边 / 圆角 / 颜色换成规范值。 */
.sd-bm-tabs {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 0;
  background: transparent;
  border: none;
  border-radius: 0;
  flex: 0 0 auto;
  overflow: visible;
}
.sd-bm-tab {
  flex: 0 0 auto;
  min-width: 42px;
  padding: 5px 12px;
  border-radius: 9px;
  font-size: 13px;
  font-weight: 400;
  font-family: var(--font-num);
}

/* ── ⑥ 卡片内嵌的 .seg-tab 与 .card-h 的 14px 内边距对齐（否则与卡片标题错位） ── */
.card > .seg-tab { margin-left: 14px; margin-right: 14px; }

/* ── ⑦ 窄屏兜底：375px 下"门店分车系"这类 5 字标签 ×3 等宽后会超出可画宽度
 *      （375 − 38×2 = 299px < 3×100px + 12px gap），侧内边距 14 → 9px 保证不溢出、
 *      也不需要横向滚动。390px 起（iPhone 12 及以上）仍用规范的 14px。 */
@media (max-width: 390px) {
  .tab-pill > *,
  .sd-tab,
  .spf-tab,
  .seg-tab .seg-item,
  .sales-tabs.seg .seg-item { padding-left: 9px; padding-right: 9px; }
  .sd-bm-tab { padding-left: 10px; padding-right: 10px; }
}

/* 走势 tooltip */
.sd-tip {
  display: none;
  position: absolute;
  background: rgba(29, 29, 31, 0.92);
  color: #fff;
  border-radius: 6px;
  padding: 6px 10px;
  box-shadow: 0 4px 16px rgba(0, 0, 0, 0.2);
  pointer-events: none;          /* 跟随手指但不吃事件 */
  z-index: 50;
  white-space: nowrap;
  transform: translate(-50%, -100%);   /* 默认在 rect 正上方 */
  margin-top: -8px;
  font-family: var(--font-num);
}
.sd-tip.show { display: block; }
/* 三角箭头指向点击位置 */
.sd-tip::after {
  content: "";
  position: absolute;
  left: 50%;
  bottom: -4px;
  transform: translateX(-50%) rotate(45deg);
  width: 8px;
  height: 8px;
  background: rgba(29, 29, 31, 0.92);
}
.sd-tip-date {
  font-size: 11px;
  color: rgba(255, 255, 255, 0.7);
  text-align: center;
  margin-bottom: 3px;
  font-weight: 400;
}
.sd-tip-row {
  display: flex;
  gap: 8px;
  justify-content: center;
}
.sd-tip-row span {
  display: flex;
  align-items: center;
  gap: 3px;
  font-size: 11px;
  font-weight: 400;
}
.sd-tip-dot {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  flex-shrink: 0;
}
.sd-hit { cursor: pointer; }

/* =====================================================================
 *  v114 周平均订单毛利（重点车型下方）—— sparkline + 异常单
 *  设计：4 行同 card 内不同 row，与 model 行缩进对齐
 * ===================================================================== */

/* 包裹：跟 model 行同缩进（15px 与 stores 一致） */
.sd-km-model-profit {
  padding-left: 15px;
  margin: 1px 0 6px;
}
.sd-km-profit {
  border-left: 2px solid #f0f1f3;
  padding: 6px 0 6px 10px;
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin-top: 4px;
}
/* v114.6.9.12 肉哥 "还是没有重点车型的价格走势呀"：之前空 profit 整块隐藏 → 用户看不见任何提示。
   改为：空时显示"占位提示"，明示根因（明细表未导入 / store_short 缺失 / 本月无单） */
.sd-km-profit-empty {
  font-size: 11px;
  font-weight: 400;
  color: var(--ink-3);
  font-style: italic;
  padding: 4px 10px;
  background: #fafbfc;
  border-left: 2px solid #f59e0b;  /* 琥珀色，提示"需要关注" */
  border-radius: 0 4px 4px 0;
  margin: 0;
  display: block;
  font-family: var(--font-num);
}

/* Row A：sparkline + 当周均 */
.sd-km-spk-row {
  display: flex;
  align-items: center;
  gap: 10px;
  min-height: 48px;
  padding: 4px 0;
}
.sd-km-spk {
  display: block;
  width: 100%;
  max-width: 296px;
  height: 60px;
  flex-shrink: 0;
}
.sd-km-spk svg { display: block; overflow: visible; }   /* v114.6.9.20: 数字标签不溢出截断 */
.sd-km-spk.empty {
  background: linear-gradient(to right, transparent 0%, #f0f1f3 50%, transparent 100%);
  background-size: 8px 100%;
}
.sd-km-spk-avg {
  font-size: 11px;
  font-weight: 400;
  color: var(--ink-3);
  font-family: var(--font-num);
  font-variant-numeric: tabular-nums;
  flex: 1;
  min-width: 0;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  display: flex;
  align-items: baseline;
  gap: 4px;
}
.sd-km-spk-avg i {
  font-style: normal;
  font-weight: 700;
  font-size: 16px;
  margin: 0;
}
.sd-km-spk-avg em {
  font-style: normal;
  color: var(--ink-3);
  font-size: 11px;
  font-weight: 400;
}

/* Row B：当周最低单毛利 */
.sd-km-min-row {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 4px 8px;
  background: #fef2f2;
  border-radius: var(--r-sm);
  font-family: var(--font-num);
  font-variant-numeric: tabular-nums;
}
.sd-km-min-lbl {
  font-size: 11px;
  font-weight: 400;
  color: #991b1b;
  flex-shrink: 0;
}
.sd-km-min-amt {
  font-size: 13px;
  font-weight: 400;
  color: #ef4444;
  flex-shrink: 0;
}
.sd-km-min-amt em {
  font-style: normal;
  font-size: 11px;
  font-weight: 400;
  color: var(--ink-3);
  margin-left: 1px;
}

/* Row C / D：异常单分组 */
.sd-km-loss-grp {
  display: flex;
  flex-direction: row;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
}
/* v114.6.9.21 肉哥"当月异常单/当周异常单也请跟后面客户名字·销售顾问的字体颜色大小粗细
   保持一致，不要这种浅色的小字体"：原来 11px / ink-3 / 500（又小又浅），
   现与 .sd-km-loss-cust（客户名）完全对齐：13px / ink-1 / 500。 */
.sd-km-loss-tt {
  font-size: 13px;
  color: var(--ink-1);
  font-weight: 400;
  flex-shrink: 0;
  min-width: 60px;
}
.sd-km-loss-row {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 4px 8px;
  border-radius: var(--r-sm);
  font-size: 13px;
  font-weight: 400;
  background: #fafbfc;
  line-height: 1.4;
  flex: 1;
  min-width: 0;
}
.sd-km-loss-lbl {
  font-size: 11px;
  font-weight: 400;
  color: var(--ink-2);
  background: var(--bg);
  padding: 2px 6px;
  border-radius: 3px;
  flex-shrink: 0;
  min-width: 30px;
  text-align: center;
}
.sd-km-loss-meta {
  flex: 1;
  min-width: 0;
  display: flex;
  align-items: center;
  gap: 4px;
  overflow: hidden;
}
.sd-km-loss-store {
  font-size: 11px;
  font-weight: 400;
  color: var(--ink-1);
  line-height: 1.2;
}
.sd-km-loss-date {
  font-size: 11px;
  font-weight: 400;
  color: var(--ink-3);
  font-family: var(--font-num);
  font-variant-numeric: tabular-nums;
  flex-shrink: 0;
}
.sd-km-loss-cust {
  font-size: 13px;
  color: var(--ink-1);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  font-weight: 400;
}
.sd-km-loss-amt {
  font-family: var(--font-num);
  font-variant-numeric: tabular-nums;
  font-size: 13px;
  font-weight: 400;
  color: #ef4444;
  flex-shrink: 0;
  min-width: 60px;
  text-align: right;
}
.sd-km-loss-amt em {
  font-style: normal;
  font-size: 11px;
  font-weight: 400;
  color: var(--ink-3);
  margin-left: 1px;
}


/* =====================================================================
 *  v114.6 KPI 3 卡片布局（总览 Tab 拷车/订单/开票）
 *  参考肉哥参考图 8b32c2ae：大圆环 + 下方当日/月累/目标 垂直行
 *  - 订单 + 直销/残单；开票 + 直销
 *  - 去掉 MoM/YoY（v114.5 占位，后端未返）
 *  - v114.6.1 拷车固定蓝；订单/开票 跑赢=蓝 / 落后时间进度=红
 *  - v114.6.1 环缩到 80px + grid 收缩 minmax(0,1fr)，3 卡放一页不溢出
 *  - v114.6.3 字号加大（肉哥 9/8 反馈"短粗小"）：rate 18→22 / 数字 13→15 / 标签 11→12
 * ===================================================================== */
.sd-kpi-cards .sd-kpi-card {
  display: flex;
  flex-direction: column;
  align-items: stretch;
  padding: 10px 10px 9px;
  background: #fff;
  border: 1px solid var(--line, #e6e8ec);
  border-radius: 12px;
  position: relative;
  min-width: 0;
  overflow: hidden;
}
.sd-kpi-cards .skc-hdr {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 13px;
  font-weight: 400;
  color: var(--ink-1, #1d1d1f);
  margin-bottom: 6px;
  white-space: nowrap;
  letter-spacing: -.01em;
}
.sd-kpi-cards .skc-dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  display: inline-block;
  flex: 0 0 8px;
}
.sd-kpi-cards .skc-ring-wrap {
  position: relative;
  width: 88px;
  height: 88px;
  margin: 0 auto 8px;
}
.sd-kpi-cards .sd-ring {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
}
.sd-kpi-cards .skc-ring-text {
  position: absolute;
  inset: 0;
  z-index: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  pointer-events: none;
}
.sd-kpi-cards .skc-rate {
  font-size: 18px;
  font-weight: 800;
  font-family: var(--font-num);
  line-height: 1;
  letter-spacing: -.02em;
}
.sd-kpi-cards .skc-cap {
  font-size: 11px;
  font-weight: 400;
  color: var(--ink-3, #8e8e93);
  margin-top: 3px;
  letter-spacing: .02em;
}
.sd-kpi-cards .skc-rows {
  display: flex;
  flex-direction: column;
  gap: 3px;
  font-family: var(--font-num);
  font-variant-numeric: tabular-nums;
  border-top: 1px dashed var(--line, #e6e8ec);
  padding-top: 6px;
}
.sd-kpi-cards .skv {
  display: flex;
  align-items: center;
  justify-content: space-between;
  font-size: 13px;
  font-weight: 400;
  color: var(--ink-3, #8e8e93);
  gap: 4px;
  min-width: 0;
  line-height: 1.4;
}
.sd-kpi-cards .skv-l { font-size: 13px; font-weight: 400; flex: 0 0 auto; }
.sd-kpi-cards .skv-v {
  font-size: 13px;
  font-weight: 400;
  color: var(--ink-1, #1d1d1f);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
  text-align: right;
  min-width: 0;
  overflow: visible;
  letter-spacing: -.01em;
}

/* ============================================================
 *  v114.6.9.16 · 品牌进度 tab 化重构 + 重点车型表头
 *  ------------------------------------------------------------
 *  改动：
 *  ① 品牌进度 拷车/订单/开票 → 卡片头 3 个小 tab
 *  ② 品牌行 / 门店行从 4 列（店名+3 stacked cell）→ 2 列（店名+单 cell）
 *  ③ 单 cell 从 stacked 2 行（累/目 + 率）→ 3 子项横排 [目标 | 累计 | 达成率]
 *  ④ 重点车型每店加 目标/累计/达成率 表头
 *  ⑤ 单店合计 2*2 排（"单店<br>合计"）
 *  ⑥ 筛选"重置"按钮 margin-left: auto，避免跟门店胶囊的 ▾ 视觉粘连
 *  ⑦ 品牌行前的 ▸ 小箭头删除（不美观）
 * ============================================================ */

/* 品牌进度 拷车/订单/开票 小 tab —— 卡片头右侧 3 等分，选中蓝底白字
 * v114.6.9.44 删除：`.sd-bm-tabs{display:inline-flex;gap:0;background:var(--bg);
 *   border-radius:8px;padding:2px;font-size:11px}` 的灰底槽 + `.sd-bm-tab` 的
 *   `border:none;background:transparent` + `.sd-bm-tab.on{background:var(--surface);…}`
 *   白底选中态（这是第 5 种 tab 视觉）。
 *   改由规范段的「⑤ 小号变体」提供：容器全透明、`.sd-bm-tab` 白底描边胶囊、
 *   `.sd-bm-tab.on` 蓝色底纹。★ 13px / padding 5×12 / min-width 42 的尺寸
 *   是肉哥 9/9 拍过的，规范段原样保留，只换了皮肤。 */
.sd-brand-card .sd-sec-h {
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
}
.sd-brand-card .sd-sec-sub { flex: 1 1 auto; min-width: 0; }

/* 品牌行/门店行 2 列布局：店名 + 单 metric cell
   替代原 4 列 (店名 + 拷车 + 订单 + 开票 stacked)
   ★ v114.6.9.38 肉哥 9/10 修「东昌合计行 / 品牌行 串成一列」：
     本条原来没有 :not() 隔离，且带 !important —— 注意 `!important` 的
     优先规则是「带 !important 的声明 > 不带 !important 的声明」，
     跟选择器权重、跟源码顺序都无关。于是它压过了后面（其实在更前面）的
     `.sd-sb-brow-7col { grid-template-columns: var(--sd-sb-cols) }`，
     把「门店分车系」的品牌行/东昌合计行强制成 2 列
     → 实测 computed grid-template-columns = "116.531px 186.469px"，
       7 个子元素被塞进 2 列 → 第 1 个占左列，其余 6 个在右列逐行往下堆 = 肉哥看到的"串行"。
     这与 line 3714 修 display:flex 时踩的是**同一个坑**（那次只修了 display，
     漏了同区块的 grid-template-columns），这次一并补上 :not()。
     `.sd-srow-head` 不参与 sd-sb-* 体系，不受影响，保持原样。 */
.sd-brow:not(.sd-sb-brow-7col), .sd-srow {
  grid-template-columns: minmax(88px, 1fr) minmax(150px, 1.6fr) !important;
}
.sd-srow-head {
  grid-template-columns: minmax(88px, 1fr) minmax(150px, 1.6fr) !important;
}

/* ★ v114.6.9.21 修「目标/累计/达成率被堆成一列」：
   之前这里写的是 grid-template-rows: auto 1fr（2 行），那是为了**门店排行**的
   「订单/开票分组标签 + 3 子项」结构。但**品牌卡片**的 brandMetricCell 输出的
   是 3 个平铺 span，没有 grp 行 —— 套上 2 行模板后第 3 个 span 落到自动新增的
   第 3 行，于是 186 / 40 / 22% 三个数纵向堆成一列（肉哥截图）。
   修：默认改回「1 行 3 列」（品牌卡片），只有带 .sd-bmc-rank 的门店排行 cell
   才用 2 行结构。 */
.sd-bmc {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  align-items: center;
  gap: 2px;
  text-align: right;
  font-family: var(--font-num);
  font-variant-numeric: tabular-nums;
  min-width: 0;
}
/* 门店排行 cell：2 行（上=订单/开票分组标签占位，下=3 子项） */
.sd-bmc.sd-bmc-rank {
  grid-template-columns: 1fr;
  grid-template-rows: auto 1fr;
}
.sd-bmc-row {
  display: grid;
  grid-template-columns: 1fr 1fr 1fr;
  gap: 2px;
  align-items: baseline;
}
.sd-bmc-grp {
  font-size: 11px;
  color: var(--brand-600);
  font-weight: 700;
  text-align: center;
  line-height: 1;
  letter-spacing: 0.5px;
  /* 数据行 grp 是透明占位（与表头行高对齐），但仍保留行高 */
  min-height: 12px;
}
/* v114.6.9.21 肉哥"整个销售看板里目标/实际/达成率的字体样式大小粗细都请一致，不要一大一小"：
   原来 目标 12px / 累计 14px 700 / 达成率 13px 600 —— 三个字号三种粗细。
   现统一 **13px / 600**，只保留极轻的颜色区分（累计=主数字 ink-1，目标/达成率 ink-2），
   达成率被标红时（最慢 / 低于时间进度）才变色。 */
.sd-bmc-tgt { color: var(--ink-2); font-size: 13px; font-weight: 400; }
.sd-bmc-act b { color: var(--ink-1); font-size: 13px; font-weight: 400; }
.sd-bmc-rate { color: var(--ink-2); font-size: 13px; font-weight: 400; }
/* v114.6.9.18：三档都算「品牌内最慢」（v114.6.9.16 改 tab 时漏了 qc，
   切到拷车 tab 一家都不红，肉哥反馈"需求被吃掉"）。
   仍按 .sd-brand-metric-<key> 限定作用域，避免切到拷车 tab 却显示订单最慢的红。 */
.sd-brand-metric-qc  .sd-srow[data-slow-qc]  .sd-bmc-rate,
.sd-brand-metric-ord .sd-srow[data-slow-ord] .sd-bmc-rate,
.sd-brand-metric-inv .sd-srow[data-slow-inv] .sd-bmc-rate { color: var(--red); }

/* v114.6.9.18 新增：低于时间进度（rate < meta.timeProgress）→ 红。
   这条**不按 tab 限定作用域**——任何口径落后于时间进度都是落后。
   品牌行(.sd-brow)同样适用：品牌整体落后就是落后，这条信息有决策价值。 */
.sd-brand-card .sd-brow[data-below] .sd-bmc-rate,
.sd-brand-card .sd-srow[data-below] .sd-bmc-rate { color: var(--red); }

/* 品牌卡片表头：1 行 3 列 [目标 | 累计 | 达成率]
   ★ v114.6.9.21 同 .sd-bmc 的修复：原来是 grid-template-rows: auto 1fr（2 行），
     但品牌表头 brandGridHead 输出的是 3 个平铺 span，套 2 行模板 → 纵向堆一列。
     只有带 .sd-bmc-hd-rank 的**门店排行**表头（含 .sd-bmc-row 子项）才走 2 行。 */
.sd-bmc-hd {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 2px;
  font-size: 11px;
  color: var(--ink-3);
  font-weight: 600;
  font-family: var(--font-num);
  text-align: right;
}
.sd-bmc-hd.sd-bmc-hd-rank {
  grid-template-columns: 1fr;
  grid-template-rows: auto 1fr;
}
.sd-bmc-hd .sd-bmc-row span { text-align: right; }

/* 重点车型 列表头：与 .sd-km-model 同样的 4 列 grid (1fr 38px 38px 42px)，
   第一个 span 留空（对应车型列），后 3 个分别 目标 / 累计 / 达成率
   v114.6.9.44 任务 D⑤：去掉 font-family:var(--font-num) —— 该表头三个字全是中文
   （目标 / 累计 / 达成率），中文走等宽数字字体是笔误，会让表头与下方数字字形不一致。
   font-variant-numeric 保留：表头虽无数字，但列宽由数字列决定，留着便于将来加数字。 */
.sd-km-models-hd {
  display: grid;
  grid-template-columns: 1fr 38px 38px 42px;
  gap: 6px;
  padding: 0 0 4px;
  border-bottom: 1px dashed var(--border-2);
  margin-bottom: 2px;
  font-size: 11px;
  color: var(--ink-3);
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  text-align: right;
}
.sd-km-models-hd span:first-child { text-align: left; }

/* 单店合计 2*2 排："单店<br>合计"，line-height 收紧避免行高过大 */
.sd-sb-cell.sd-sb-cell-stack {
  line-height: 1.15;
  font-size: 13px;
  font-weight: 400;
  color: var(--ink-1);
}

/* 筛选"重置"按钮 margin-left: auto → 推开到行尾，避开"门店"胶囊的 ▾ 视觉粘连 */
.sales-filter > .sales-reset { margin-left: auto; }

/* ============================================================
 *  v114.6.9.25 · 毛利预警看板（独立 + 3 Tab，.spf-*）
 *  Tab 1 品牌毛利对标矩阵 / Tab 2 订单毛利预警 / Tab 3 4 周毛利走势
 *  旧版 .sd-pa-*（v114.6.9.24 集成在销量看板第 4 Tab）已整体废弃。
 * ============================================================ */

/* ---------- 通用：页头 + 骨架屏 ---------- */
.spf-hd { display: flex; align-items: baseline; justify-content: space-between; margin-bottom: 10px; }
.spf-title { font-size: 16px; font-weight: 700; color: var(--ink-1, #1d1d1f); letter-spacing: .2px; }

.spf-sk { padding: 2px 0; }
.spf-sk-kpi { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 8px; margin-bottom: 10px; }
.spf-sk-kpi > span { display: block; height: 56px; border-radius: 10px; background: #eceef1; }
.spf-sk-card { height: 120px; border-radius: 10px; background: #eceef1; margin-bottom: 10px; }
.spf-sk-card.short { height: 56px; }
.spf-sk-kpi > span, .spf-sk-card {
  background: linear-gradient(90deg, #eceef1 25%, #f5f6f8 37%, #eceef1 63%);
  background-size: 400% 100%;
  animation: spf-sk-shine 1.4s ease infinite;
}
@keyframes spf-sk-shine { 0% { background-position: 100% 50%; } 100% { background-position: 0 50%; } }

/* ---------- 通用：Tabs 容器（v114.6.9.44 起并入「全站表头 Tab 唯一规范」） ----------
 * 原 `.spf-tabs { display:flex; gap:4px; margin:0 0 10px; padding:2px;
 *      background:#f0f2f5; border-radius:10px; }`            ← 浅灰容器
 *    `.spf-tab  { flex:1; text-align:center; padding:8px 0; font-size:13px;
 *      color:var(--ink-2); border-radius:8px; font-weight:500; }`
 *    `.spf-tab.active { background:#fff; color:var(--ink-1); font-weight:700;
 *      box-shadow:0 1px 3px rgba(0,0,0,.06); }`              ← 白底药丸
 *  以上三条**已删除**（这是第 2 种 tab 样式），改由规范段的
 *  `.spf-tabs` / `.spf-tab` / `.spf-tab.active` 提供。
 *  毛利页 tab 的实测左边距由 14px → 26px（14px `.sub-body` + 12px 规范边距），
 *  与销量看板 / 交车看板 / 新保看板的 38px 保持"比内容区窄 12px"的同一关系。 */

/* ---------- 品牌 / 门店 / 车系 三级筛选胶囊（v114.6.9.39 肉哥反馈 2） ----------
 *  肉哥要求三个 Tab 的筛选视觉与「销量看板」一致，所以这里**只做位置微调**，
 *  样式本体全部复用销量看板现成的类：
 *    .sales-filter   → flex nowrap + gap 5px + padding 0 4px（一行不折行）
 *    .sales-sel-holder → flex: 1 1 0（每个下拉等分宽度）
 *    .sales-sel / .sd-pill / .sales-reset → 胶囊本体与重置图标
 *  ★ 唯一新增的是 .spf-filters 的上下边距：销量看板里 .sd-filters 是 margin-bottom:8px，
 *    但毛利看板上面紧贴 .spf-tabs（自带 margin-bottom:10px），
 *    下面紧接内容（Tab 1 有 .spf-window，Tab 3 有 .spf-kpi，各自都有上边距），
 *    所以这里只需 8px 的下边距，不再补上边距 —— 和销量看板的视觉节奏一致。 */
.spf-filters { margin-bottom: 8px; }
/* 三个筛选等分 + 重置图标固定宽（销量看板 .sales-reset 已是 flex: 0 0 26px） */
.spf-filters .sales-sel-holder { flex: 1 1 0; min-width: 0; }

/* ---------- 通用：窗口提示 + KPI ---------- */
.spf-window { font-size: 11px; font-weight: 400; color: var(--ink-3, #8e8e93); margin: 4px 0 8px; padding: 0 4px; }
.spf-kpi {
  display: grid; grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 8px; margin-bottom: 10px;
}
.spf-kpi-card {
  background: #fff; border: 1px solid var(--border, #e6e6ea);
  border-radius: 10px; padding: 10px 12px; text-align: left;
}
.spf-kpi-label { font-size: 11px; font-weight: 400; color: var(--ink-3, #8e8e93); margin-bottom: 4px; }
.spf-kpi-big { font-size: 18px; font-weight: 700; color: var(--ink-1, #1d1d1f); font-family: var(--font-num); line-height: 1.2; }
.spf-kpi-sub { font-size: 11px; font-weight: 400; color: var(--ink-3, #8e8e93); margin-top: 3px; }
.spf-kpi-warn .spf-kpi-big { color: var(--orange, #f59e0b); }
.spf-kpi-loss  .spf-kpi-big { color: var(--red, #ef4444); }

/* ============================================================
 *  Tab 1 品牌毛利对标矩阵（.spf-mx-*）
 *  矩阵：行=品牌车系，列=品牌内门店，单元格=平均综合毛利+右下角 N
 *  横向滚动：手机屏上品牌内门店数 >4 时自动横滚
 * ============================================================ */
/* v114.6.9.34 重写：改用真实 table 元素 + sticky（浏览器原生支持 <th>/<td> 的 position:sticky）
 *   历史失败：
 *     v114.6.9.29 单 grid 容器 + grid item sticky left:0 → 失效
 *     v114.6.9.33 拆 flex 双容器 → 行高对不齐 + 车系列垂直居中错位 + 右侧空白列
 *   table 方案优点：行高由 table layout 统一管理（天然对齐）；首列 sticky left:0 与表头 sticky top:0 可同时生效。 */
.spf-mx-brand { margin-bottom: 14px; }
.spf-mx-brand-name {
  font-size: 15px; font-weight: 700; color: var(--ink-1, #1d1d1f);
  padding: 0 4px 6px; border-bottom: 1px solid var(--border, #e6e6ea);
  margin-bottom: 6px;
  display: flex; align-items: center; justify-content: space-between;
}
.spf-mx-brand-name .spf-mx-brand-stat {
  font-size: 12px; color: var(--ink-3, #8e8e93); font-weight: 500; font-family: var(--font-num);
}
/* 滚动容器：横向滚动由它负责；首列 sticky 在其中生效 */
.spf-mx-wrap {
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
  border: 1px solid var(--border, #e6e6ea);
  border-radius: 10px;
  background: #fff;
}
.spf-mx-tb {
  border-collapse: separate;
  border-spacing: 0;
  font-size: 12px;
  width: max-content;
  min-width: 100%;
  table-layout: fixed;
}
/* 单元格尺寸：所有格子统一 padding，第一列固定宽度 96px
 * v114.6.9.39：第一列 80px → 96px（详见下面 .spf-mx-td-series 的说明） */
.spf-mx-tb th, .spf-mx-tb td {
  padding: 9px 6px;
  text-align: center;
  font-weight: 400;
  white-space: nowrap;
  background: #fff;
  border-bottom: 1px solid #f0f1f3;
}
/* ★首列（车系）：sticky left:0 —— table 单元格上原生支持，滚动时始终可见
 * v114.6.9.39 修「车型名穿模」（肉哥 9/10 截图：E Class Long / GLC Coupe / GLE Successor /
 *   S Maybach 这些长车系名撑破第一列，压到相邻门店列上）：
 *   根因两条同时成立 ——
 *     ① 列宽写死 80px。table-layout:fixed 下内容不改变列宽，长名字只会溢出不换行；
 *        "GLE Successor" 这类在 12px 下量到 ~95px，"S Maybach" ~110px，80px 必然装不下。
 *     ② 继承自 `.spf-mx-tb th, td` 的 white-space:nowrap 让文字永不换行 → 只能溢出。
 *   修法（加宽 + 允许换行，双管齐下）：
 *     ① 80px → 96px。按当前数据里最长的车系名量出来的实用下限；再宽会在 375px 屏上
 *        把第二个门店列也挤出可视区（首列 + 2 门店 × 2 子列 已经接近满宽）。
 *     ② 单独放开换行：white-space:normal + overflow-wrap:anywhere。
 *        这样列宽变成「参考值」而不是「硬边界」——将来出现更长的车系名也只是多占一行，
 *        不会再穿模（这才是根治；单纯加宽只是把问题往后推）。
 *     ③ line-height 显式给 1.35，两行时行高可预期，不会把行撑得忽高忽低。
 *   为什么用 overflow-wrap:anywhere 而不是 word-break:break-all：
 *     车系名以空格/连字符分词（"E Class Long"、"GLE Successor"），优先在词边界断行
 *     （normal 的换行机会），只有单个词本身就超宽时才在词内硬断 —— 可读性最好。
 *   注意：overflow-wrap 必须配合 white-space:normal 才生效（nowrap 下没有换行机会）。 */
.spf-mx-tb .spf-mx-th-series,
.spf-mx-tb .spf-mx-td-series {
  position: sticky; left: 0; z-index: 3;
  width: 96px; min-width: 96px; max-width: 96px;
  text-align: left; padding-left: 10px;
  font-weight: 500; color: var(--ink-1, #1d1d1f);
  background: #fff;
  border-right: 1px solid var(--border, #e6e6ea);
  white-space: normal;
  overflow-wrap: anywhere;
  word-break: normal;
  line-height: 1.35;
}
/* ★表头：sticky top:0 —— 滚动时列名始终可见
 * v114.6.9.39：颜色 ink-2 #555 → ink-1 #1d1d1f（肉哥："其他字颜色都换成黑色"）。 */
.spf-mx-tb thead th {
  position: sticky; top: 0; z-index: 2;
  font-weight: 500; color: var(--ink-1, #1d1d1f);
  background: #f5f7fa;
  border-bottom: 1px solid var(--border, #e6e6ea);
}
/* 表头首列（左上角）需要在 x 与 y 两个方向都 sticky，z-index 最高 */
.spf-mx-tb thead .spf-mx-th-series {
  z-index: 4;
  background: #f5f7fa;
}
/* 表头第二行（辆次/平均综合毛利）要粘在第一行下面
 * v114.6.9.39：33px → 34px。上面 .spf-mx-th-series 的 line-height 从继承的 body 值
 *   改为显式 1.35，第一行表头高度随之微调，偏移量同步修正才能贴住不露缝。 */
.spf-mx-tb thead tr:nth-child(2) th {
  top: 34px;
}
/* ============================================================
 * v114.6.9.39 · 矩阵字号/字重/颜色统一（肉哥 9/10 原话）：
 *   「请把这块的门店车系表头、数字所有文字字体大小尺寸颜色粗细保持一致，
 *     仅把品牌内同车系最低毛利门店的那个毛利数标红就行，其他字颜色都换成黑色」
 * 落地规则：
 *   ① 除「最低毛利数字」外，矩阵内所有文字 = 12px / 字重 500 / 颜色 var(--ink-1) #1d1d1f。
 *      上一版的混乱取值（门店名 12/600、子表头 10/500 灰、毛利率 13/600、
 *      辆次 13/500 灰、车系名 12/600）全部拉平 —— 这是肉哥这次的核心诉求。
 *   ② 之前「N 用 600 还是 500」的区分（视觉上哪个是真的数、哪个是样本量）随统一一起取消。
 *   ③ 子表头不再用 10px 灰 + #fafbfc 底 —— 颜色变黑（见 ①），底色保留用于区分表头两行。
 *   ④ 「最低毛利」用 var(--red) 标红，但**只有数字本身**（.spf-mx-lowest 挂在 <span> 上），
 *      单元格底色、整行、辆次数字都不动。
 * ============================================================ */
.spf-mx-th-store { font-size: 12px; font-weight: 500; color: var(--ink-1, #1d1d1f); padding: 9px 4px; }
.spf-mx-th-sub { font-size: 12px; font-weight: 500; color: var(--ink-1, #1d1d1f); padding: 6px 4px; background: #fafbfc; }
/* 斑马纹 */
.spf-mx-tr.alt td, .spf-mx-tr.alt .spf-mx-td-series { background: #fafbfc; }
/* 数字单元格：辆次与毛利同为 12px / 500 / 黑，只有「最低毛利」的 span 例外变红 */
.spf-mx-td { font-family: var(--font-num); }
.spf-mx-td .spf-mx-val { font-weight: 500; color: var(--ink-1, #1d1d1f); font-size: 12px; }
.spf-mx-td .spf-mx-n-val { font-weight: 500; color: var(--ink-1, #1d1d1f); font-size: 12px; }
.spf-mx-td .spf-mx-empty { color: var(--ink-1, #1d1d1f); font-size: 12px; }
/* ★ 唯一允许例外：品牌内同车系最低毛利门店的「毛利数字」标红 */
.spf-mx-td .spf-mx-val.spf-mx-lowest { color: var(--red, #ef4444); }
/* v114.6.9.39 删除：.spf-mx-weak（⚠ 样本量 N<5）—— 肉哥「你这个⚠️的标识我没理解」。
 *   符号本身看不懂 = 沟通失败，且它同时把数字染灰，与"统一黑色"要求直接冲突。
 *   后端 profit-matrix.js 的 weak 字段保留不动（其它消费方可能用），只是矩阵不再渲染。 */

/* ============================================================
 *  Tab 2 订单毛利预警（.spf-od-*）
 *  v114.6.9.39：第 1 行 3 列 → 4 列（加「订单车型」），两行统一 4 列
 *    第 1 行 订单日期 / 客户名字 / 销售顾问 / 订单车型
 *    第 2 行 车价毛利(W) / 衍生(X) / 销售返利(Y) / 综合毛利(AD)
 *  ★ 两行内部的列宽必须分别与 .spf-od-hd 的 top / metrics 严格一致，
 *     否则又会出现「数字跟表头不对应」。三者共用 --spf-od-top-cols /
 *     --spf-od-m-cols 两个变量，改一处即全局同步。
 * ============================================================ */
.spf-od-list { display: flex; flex-direction: column; gap: 4px; }
/* v114.6.9.37：4 指标列等宽。
 *   ★ 必须用 calc((100% - 3*gap) / 4)，不能用 repeat(4, 1fr) + gap ——
 *     fr 配 gap 在亚像素舍入下会渲染出 [6,5,6] 的不均间距（已实测）。
 *
 * ★★★ v114.6.9.39 修正：变量必须声明在 .spf 上，不能声明在 .spf-od-list 上 ★★★
 *   v114.6.9.36 的事故复盘把结论写反了，这里更正（有实测证据，勿再改回）：
 *   DOM 结构是
 *       .spf
 *         ├── .spf-tabs
 *         ├── #spf-filters
 *         └── #spf-body
 *               ├── .spf-od-hd      ← 表头（.spf-od-list 的**兄弟**）
 *               └── .spf-od-list
 *                     └── .spf-od    ← 卡片
 *   即 **.spf-od-hd 不是 .spf-od-list 的后代**，两者只是兄弟。
 *   CSS 自定义属性只沿**后代**继承 → 声明在 .spf-od-list 上时，
 *   .spf-od-hd 里的 var(--spf-od-top-cols) 解析为空 → grid 退化成隐式单列，
 *   于是表头 4 个列名全部叠在同一个 326px 宽格里（实测 hdTopRects 全是 [32,326]），
 *   而卡片的 4 列是正常的 78.5px×4 → 表头与数据整体错位 236~276px。
 *   这正是 2026-09-10 肉哥反复看到的"表头跟数字对不上"。
 *   .spf 才是 .spf-od-hd 与 .spf-od-list 的**真实共同祖先**（已验证 contains() 为双真）。
 *   ★ 别再"为了局部性"把这段搬回 .spf-od-list —— 搬回去就等于重新制造这个 bug。
 *
 * v114.6.9.39 两行都改成同一种「四等分」模板，第 1 行不再是 42px+1fr+auto：
 *   旧模板（固定 42px 日期 + 弹性客户 + auto 顾问）与第 2 行的四等分列
 *   完全无法对齐，肉哥要的"上下两行第 N 列左右边缘对齐"根本做不到。
 *   现在两行共用同一份四等分 calc，四列左右边缘天然逐列重合。
 *
 * ★★★ v114.6.9.48：第 1 行与第 2 行**解耦**（肉哥 2026-09-12 新要求）★★★
 *   肉哥原话：「订单车型名字能否显示完全，就是前面客户名字、销售顾问的可以压缩一下
 *   空间，把后面的车型格子拉宽」。
 *   实测依据（375px，Chromium 真跑，见 test-v114-od-model-width.js）：
 *     · 四等分下单列 = 86.25px（content 357px 时）／真机上更窄
 *     · 订单车型最长实测「梅赛德斯-奔驰 E 300 L 运动版」墨迹宽 **150.8px**
 *       （其余：凯迪拉克 CT5 28T 豪华 117.9 / 雷克萨斯 RX350h 四驱 114.3）
 *     · 客户名最长实测「欧阳建国」44px（4 汉字）
 *     → 车型被截断成 "2026款 ES200 F…"，而 客户/顾问 两列各有 40px 富余。
 *   新模板：`46px 1fr 1fr 2.9fr` —— 日期固定 46px（"09-10" 仅需 33px），
 *   客户/顾问各约 56px（够 4 汉字 + 余量），车型约 163px（≥150.8px，可完整显示）。
 *
 *   ★ 必须记下来的取舍：这样一来第 1 行与第 2 行的第 2、3 条**列边界不再重合**，
 *     即 v114.6.9.39 肉哥要求的"上下两行第 N 列左右边缘对齐"被**主动放弃**。
 *     原因：第 2 行 4 个毛利指标块宽度需求相近（标签 4 汉字 44px + 数值约 45px），
 *     必须保持四等分才不会被挤成"三个挤左边 + 综合毛利孤零零飘在最右"；
 *     而第 1 行的车型需要一整列约一半宽度。两个约束在 375px 下数学上无法同时满足。
 *     **肉哥若更看重上下对齐、不要车型完整，回退办法：把本行改回
 *       `repeat(4, calc((100% - 18px) / 4))`（窄屏 `- 12px`），并把 .spf-od-model
 *       的 white-space 改回 normal 让它折两行。**
 *   ★ 仍然保留（不能动）的对齐：.spf-od-top ↔ .spf-od-hd-top 共用 --spf-od-top-cols，
 *     .spf-od-metrics ↔ .spf-od-hd-metrics 共用 --spf-od-m-cols。
 *     **表头↔数据行错位才是真 bug（v114.6.9.39 肉哥反复看到的"表头跟数字对不上"），
 *     这两对必须始终共用同一个变量。** */
.spf {
  --spf-od-m-cols: repeat(4, calc((100% - 18px) / 4));
  /* v114.6.9.48：第 1 行专用模板（与 --spf-od-m-cols 解耦，原因见上） */
  --spf-od-top-cols: 46px minmax(0, 1fr) minmax(0, 1fr) minmax(0, 3.3fr);
}
.spf-od {
  display: flex;
  flex-direction: column;
  gap: 4px;
  padding: 8px 10px;
  background: #fff;
  border: 1px solid var(--border, #e6e6ea);
  border-radius: 8px;
  font-size: 11px;
  font-weight: 400;
}
.spf-od.alert { border-color: var(--red, #ef4444); background: #fef5f5; }
/* 第 1 行：订单日期 / 客户名字 / 销售顾问 / 订单车型（v114.6.9.39 由 3 列改 4 列） */
.spf-od-top {
  display: grid;
  grid-template-columns: var(--spf-od-top-cols);
  column-gap: 6px;
  align-items: center;
  min-width: 0;
}
.spf-od-d { font-family: var(--font-num); color: var(--ink-3, #8e8e93); font-size: 11px; font-weight: 400; }
/* v114.6.9.32 改：客户名 / 顾问 去 ellipsis + nowrap，按 grid 列宽自然显示完整。
 *   旧 overflow:hidden + text-overflow:ellipsis + white-space:nowrap 会把
 *   「王海…」「王谦…」「吴黄…」等截断。 */
.spf-od-cust, .spf-od-cons, .spf-od-model {
  color: var(--ink-1, #1d1d1f); font-size: 11px;
  font-weight: 400;
  min-width: 0;
  overflow: visible;
  white-space: nowrap;
}
/* v114.6.9.39：等宽四列下不再需要靠 text-align:right 把顾问"推到中间"，
 *   右对齐会让「销售顾问」列的文字与它下面「衍生毛利」的数字挤在同一侧、
 *   和表头的左对齐列名错位。四列统一左对齐，与表头逐列同起点。 */
/* 订单车型：比客户名次要一档（车型是参考信息，不是要找的人），用 ink-2 弱化 */
.spf-od-model {
  color: var(--ink-2, #555);
  font-size: 11px;
  font-weight: 400;
  /* v114.6.9.48：列宽已拉宽到 ~172px（375px 下），实测最长车型
   *   「梅赛德斯-奔驰 E 300 L 运动版」墨迹 150.8px **可完整显示**。
   *   这里保留 ellipsis 仅作**兜底**（万一出现更长的脏数据/新车型），
   *   正常情况下不会触发；title 属性仍给完整值（hover/长按可见）。
   *   ★ 不要再把列宽改回四等分而不动这里 —— 那会立刻退回"2026款 ES200 F…"。 */
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
/* 第 2 行：4 个指标块，逐列与表头 metrics 对齐 */
.spf-od-metrics {
  display: grid;
  grid-template-columns: var(--spf-od-m-cols);
  column-gap: 6px;
  align-items: end;
}
.spf-od-m {
  display: flex; flex-direction: column; align-items: flex-end;
  min-width: 0;
}
.spf-od-mk {
  font-size: 11px; font-weight: 400; color: var(--ink-3, #8e8e93);
  line-height: 1.2; white-space: nowrap;
}
.spf-od-mv {
  font-family: var(--font-num); font-weight: 400; font-size: 11px;
  color: var(--ink-1, #1d1d1f);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.spf-od.alert .spf-od-ad { color: var(--red, #ef4444); }
/* v114.6.9.29 改：标签从 spf-od-ad 上绝对定位 → 改为 inline，跟在客户名后
 *  旧 position: absolute 容易遮住综合毛利列；改 inline 后不影响布局。
 * v114.6.9.39 改：4 列等宽后标签不能再占 .spf-od-top 的单元格（会把「销售顾问」
 *  挤到第 4 列、与表头错位），改为 .spf-od-top 之后的独立行。
 *  卡片是 flex-direction: column，所以这里 as span 就自然占一整行，
 *  左对齐贴卡片左缘、不占任何 grid 列 → 三行结构（信息行 / 标签行 / 指标行）
 *  里只有第 1、3 行参与列对齐，第 2 行(标签)不影响逐列 x 坐标。 */
.spf-od .spf-od-tag {
  display: inline-block;
  align-self: flex-start;
  background: var(--red, #ef4444); color: #fff;
  font-size: 11px; padding: 1px 4px; border-radius: 3px;
  font-weight: 400; letter-spacing: .2px;
  font-style: normal;
  vertical-align: 1px;
}
.spf-od .spf-od-empty { color: var(--ink-3, #8e8e93); font-weight: 400; }
.spf-od-meta {
  font-size: 11px; font-weight: 400; color: var(--ink-3, #8e8e93);
  font-family: var(--font-num); text-align: right; padding-right: 4px;
}
.spf-od-meta .spf-od-base {
  margin-right: 4px; color: var(--ink-2, #555); font-weight: 600;
}

/* 订单表头 */
/* v114.6.9.37：表头改成两行结构，与 .spf-od 卡片一一对应。
 *   旧版表头是「一行 7 列」，而卡片已改两行 → 列名与数字对不上。
 *   ★ 水平内边距必须比 .spf-od 的 padding 多 1px（数据行自带左右各 1px border），
 *     否则表头与数据行整体错开 1px。改 .spf-od padding 或 border 时这里同步。
 * v114.6.9.39：两行都改 4 列（第 1 行加「订单车型」），与卡片两行逐列同 x。 */
.spf-od-hd {
  display: flex;
  flex-direction: column;
  gap: 4px;
  padding: 6px 11px;
  font-size: 11px; color: var(--ink-3, #8e8e93);
  border-bottom: 1px solid var(--border, #e6e6ea);
  font-weight: 600;
  background: #fff;
}
.spf-od-hd-top {
  display: grid;
  grid-template-columns: var(--spf-od-top-cols);
  column-gap: 6px;
}
/* v114.6.9.39：第 1 行 4 列统一左对齐（去掉旧的 cons 右对齐）——
 *   卡片第 1 行也是左对齐，表头跟卡片必须同一个对齐方向，否则列名看起来"浮"在数字上方。 */
/* ★ 4 列必须与 .spf-od-metrics 逐列同 x 坐标 */
.spf-od-hd-metrics {
  display: grid;
  grid-template-columns: var(--spf-od-m-cols);
  column-gap: 6px;
}
.spf-od-hd-metrics > div { text-align: right; }
/* v114.6.9.29：表头 sticky，滚到深处时列名一直可见
 *  top=0 即可；spf-hd/spf-tabs 在 body 顶部之上会被自然滚走 */
.spf-od-hd { position: sticky; top: 0; z-index: 10; }

/* v114.6.9.26 三层嵌套：品牌 / 门店 / 车系 分组标题（可折叠）
 *  嵌套视觉层级用左边距 + 字号区分（不靠色块，颜色一致保持简白） */
.spf-od-grp {
  display: flex; align-items: center; gap: 6px;
  background: #fff; border: 1px solid var(--border, #e6e6ea);
  border-radius: 8px;
  font-weight: 600; color: var(--ink-1, #1d1d1f);
  cursor: pointer; user-select: none;
  transition: background .15s;
}
.spf-od-grp:hover { background: #f5f8fc; }
.spf-od-grp-caret {
  font-size: 11px; color: var(--ink-3, #8e8e93);
  display: inline-flex; align-items: center; justify-content: center;
  width: 14px; flex-shrink: 0;
}
.spf-od-grp-lbl { font-size: 11px; font-weight: 400; }
.spf-od-grp-stat { font-size: 11px; color: var(--ink-3, #8e8e93); font-weight: 400; margin-left: auto; padding-left: 8px; }
.spf-od-grp-alert {
  font-size: 11px; font-weight: 400; padding: 1px 6px;
  background: var(--red, #ef4444); color: #fff; border-radius: 8px;
}
/* 三层缩进：品牌 12px / 门店 24px / 车系 36px */
.spf-od-grp-brand   { padding: 10px 10px 10px 10px; margin-top: 6px; }
.spf-od-grp-store   { padding: 8px  8px  8px 24px; background: #fafbfc; }
.spf-od-grp-series  { padding: 6px  8px  6px 38px; background: #f5f6f8; font-weight: 500; }
.spf-od-grp-series .spf-od-grp-lbl { font-size: 11px; font-weight: 400; }

/* 无基线单加弱视觉 */
.spf-od-nobase { color: var(--ink-3, #8e8e93); font-style: italic; }

/* ============================================================
 *  Tab 3 价格走势（.spf-td-*）
 *  v114.6.9.26 改名（原「4 周走势」）；品牌标题 padding-left=0 与卡片对齐
 * ============================================================ */
/* v114.6.9.29 三层嵌套：品牌 → 门店 → 车系（之前只有 品牌 → 车系·门店） */
.spf-td-grp {
  display: flex; align-items: center; gap: 6px;
  cursor: pointer; user-select: none;
  font-weight: 600; color: var(--ink-1, #1d1d1f);
}
.spf-td-grp:hover { background: #f5f8fc; }
.spf-td-grp-caret {
  font-size: 11px; color: var(--ink-3, #8e8e93);
  display: inline-flex; align-items: center; justify-content: center;
  width: 14px; flex-shrink: 0;
}
.spf-td-grp-lbl { font-size: 13px; font-weight: 400; }
.spf-td-grp-stat { font-size: 11px; color: var(--ink-3, #8e8e93); font-weight: 400; margin-left: auto; padding-left: 8px; }
/* 品牌：padding-left=0 与卡片左缘对齐（沿用 v114.6.9.26 的对齐要求）+ 下边框 */
.spf-td-grp-brand {
  padding: 10px 0 6px; margin-bottom: 6px;
  border-bottom: 1px solid var(--border, #e6e6ea);
}
/* 门店：缩进 12px */
.spf-td-grp-store { padding: 8px 0 6px 12px; }
.spf-td-grp-store .spf-td-grp-lbl { font-size: 13px; font-weight: 400; }

.spf-td-list { display: flex; flex-direction: column; gap: 6px; }
/* v114.6.9.26 品牌标题：与下方卡片左缘对齐（padding-left=0）
 *  v114.6.9.29 已换成可折叠的 .spf-td-grp-brand；本类保留兜底（勿用） */
.spf-td-brand-h {
  font-size: 13px; font-weight: 400;
  padding: 10px 0 6px; margin-bottom: 6px;
  border-bottom: 1px solid var(--border, #e6e6ea);
  color: var(--ink-1, #1d1d1f);
}
.spf-td {
  background: #fff; border: 1px solid var(--border, #e6e6ea);
  border-radius: 10px; overflow: hidden;
}
.spf-td-row {
  display: grid;
  grid-template-columns: 1fr 200px 18px;
  gap: 8px; padding: 10px 12px; align-items: center; cursor: pointer;
}
.spf-td-row:hover { background: #f5f8fc; }
.spf-td-key { display: flex; flex-direction: column; }
.spf-td-key .spf-td-bs { font-size: 13px; font-weight: 400; color: var(--ink-1, #1d1d1f); }
/* v114.6.9.29 删：.spf-td-key .spf-td-st（门店已提到上层 .spf-td-grp-store，本类成死代码） */
.spf-td-spark { width: 200px; height: 36px; }
/* v114.6.9.29 改：高度 32 → 36，匹配 viewBox(48) 比例 0.75（Y 压缩），
 *  避免 preserveAspectRatio=none 把字压扁 */
.spf-td-caret { font-size: 12px; color: var(--ink-3, #8e8e93); transition: transform .15s; text-align: center; }
.spf-td.open .spf-td-caret { transform: rotate(180deg); }
.spf-td-detail { display: none; border-top: 1px solid var(--border, #e6e6ea); background: #fafbfc; }
.spf-td.open .spf-td-detail { display: block; }

/* ── v114.6.9.36 4 周明细：纵向堆叠 → 等宽并列 ──────────────────────
 *  肉哥反馈：「【8/17-8/23】和【8/24-8/30】、【8/31-8/6】这些属于并列层级，
 *  你现在做成了嵌套，在逐步收窄」
 *
 *  旧版（≤ v114.6.9.35）：4 个 .spf-td-week 顺序块各占整行、每个都带 8px 12px
 *  左内边距 + 底部分割线，视觉上被读成"一层层往右缩进的嵌套"，而不是同级四块。
 *
 *  新版：.spf-td-weeks 用 4 列等宽 grid 把 4 个周并排铺开，
 *  每列是一张独立小卡片（浅底 / 边框 / 圆角），顶部有序号 chip 1·2·3·4
 *  直接点明"同级兄弟"。
 *
 *  为什么是 repeat(4, minmax(0, 1fr)) 而不是 repeat(4, 1fr)：
 *  普通 1fr 的等价写法是 minmax(auto, 1fr)，其 auto 下限会被内容（长客户名、
 *  长数字）撑开，导致 4 块宽度不等宽 —— 这正是本需求要消灭的"不等宽"。
 *  minmax(0, 1fr) 把下限锁成 0，4 块才严格等宽。改这里前请先读这段注释。
 *
 *  约束：4 块的 padding-left / border-left 位置必须完全一致 ——
 *  本段内**禁止**出现任何 margin-left / padding-left / border-left 的递进规则
 *  （含 :nth-child 缩进、阶梯式 padding），否则又会退化成"逐步收窄"。
 * ─────────────────────────────────────────────────────────────── */
.spf-td-weeks {
  display: grid;
  /* v114.6.9.36 修：消掉亚像素舍入，做到「4 块等宽 + 3 个间隙严格相等」。
   *
   *   为什么要这么绕：实测（Chromium，430px 视口）用
   *     repeat(4, minmax(0, 1fr)) + gap:6px
   *   时容器可用宽无法被 4 整除 → 浏览器做亚像素舍入，
   *   量出来块宽都是 81px，但块间距是 [6, 5, 6] —— 中间那个间隙比两侧少 1px。
   *   肉哥上一轮反馈的「8/17-8/23 和 8/24-8/30 左边前面空的间隙不一样」，
   *   本质就是这个 1px 的舍入误差（旧版纵向堆叠时表现为各块 padding 观感不一致）。
   *   1px 在手机上肉眼可见，必须从根上消掉，不能靠「看起来差不多」。
   *
   *   解法：不用 fr（fr 的分配结果依赖容器宽度，必然引入舍入），
   *   改用「显式宽度 + 空格子撑开」：
   *     - 每个周块宽度 = calc((100% - 3 * gap) / 4)，四块严格相等（同一个表达式）；
   *     - gap 由 grid 的 column-gap 提供，它是固定 px，不受 fr 舍入影响；
   *     - 100% 是容器内容宽（已扣 padding），所以计算基准一致。
   *   这样浏览器只需按一个确定表达式布局，间隙恒定 = gap。
   *
   *   ★ 任何改动都必须跑 tools/verify-v114-36-layout.py 验证
   *     weekGaps 是 [n, n, n] 而不是 [n, n±1, n]。 */
  grid-template-columns: repeat(4, calc((100% - 18px) / 4));
  column-gap: 6px;   /* 18px = 3 个间隙 × 6px，与上面的 calc 必须同步改 */
  row-gap: 0;
  padding: 8px 12px;
  align-items: start;
}
.spf-td-week {
  /* 4 块等宽并列：每块只是 grid 的一个等宽 track，自身不带任何水平外边距 */
  min-width: 0;
  padding: 6px 7px;
  background: var(--bg-elev, #fff);
  border: 1px solid var(--border, #e5e5ea);
  border-radius: var(--r-xs, 6px);
}
.spf-td-week-top {
  display: flex; align-items: flex-start; gap: 4px;
  margin-bottom: 2px;
  /* v114.6.9.36 修：周标签允许折行后（见 .spf-td-week-lbl），"9/7-9/13" 这类
   *  9 字符标签会比 "8/24-8/30" 多折一行，导致该块整体高 ~10px，
   *  4 块的订单区起始线出现锯齿（实测 tops spread=10）。
   *  这里把头部区高度**恒定 2 行**（11px × 1.2 × 2 ≈ 27px，取 27px），
   *  4 块头部等高 → 下面的均值行、列头行、订单行自然在同一条水平线上。
   *  ★ 改 .spf-td-week-lbl 的字号或 line-height 后，这里要重新量并同步。 */
  height: 27px;
  overflow: hidden;
}
/* 序号 chip：把"这 4 个是同一级的兄弟"直接写进视觉，不依赖读者自己数 */
.spf-td-week-no {
  flex: none;
  width: 14px; height: 14px; line-height: 14px;
  text-align: center; border-radius: 50%;
  font-size: 9px; font-weight: 700;
  font-family: var(--font-num);
  color: var(--ink-3, #86868b);
  background: var(--surface-2, #f2f2f5);
}
.spf-td-week-lbl {
  font-size: 11px; font-weight: 600; color: var(--ink-1, #1d1d1f);
  /* v114.6.9.36 修：原来写 white-space:nowrap + ellipsis，320px 下每块只有 68.5px，
   *  减去内边距和 14px 序号 chip 后仅剩 ~44px，而 "8/17-8/23" 在 10px 字号下约需 50px，
   *  结果被截成 "8/17-…" —— 周标签是本块的主标识，截断后完全读不出是哪一周。
   *  改为允许折行：宽度由 grid 锁死（等宽不受影响），日期信息不丢。 */
  min-width: 0;
  white-space: normal; overflow-wrap: break-word;
  line-height: 1.2;
}
/* v114.6.9.36 改：不再用 grid-column: 2/5 与周标签同行跨列（4 列并排后每块只有 ~75px，
 *  与标签同行必被挤断），改成独立整行 */
.spf-td-week-mean {
  font-size: 10px; font-weight: 700; color: var(--ink-2, #51525a);
  font-family: var(--font-num);
  /* v114.6.9.36 修：原来 nowrap + ellipsis 会把 "· 12 单" 整段吞掉
   *  （实测 375px 下显示成"均 1.05 万 ·…"，单量这个关键信息直接没了）。
   *  改为两段可折行：内部 span 各占一段，段间用 margin 代替 "·" 分隔符，
   *  避免折行后留下悬空的 "·"。宽度仍由 grid 锁死。
   *
   *  ⚠ 第二个副作用（本次实测发现）：均值占几行取决于文字长度 ——
   *  "均 1.68 万 / 5 单" 折 2 行（22.5px），而 "均 — 万 / 0 单" 只有 1 行（11.3px），
   *  导致该块下面的列头/订单行整体上移 11.2px，4 块出现锯齿。
   *  这里同样固定成 2 行高度（10px × 1.25 × 2 = 25px，取 22.5px 实测值）。 */
  white-space: normal;
  line-height: 1.25;
  margin-bottom: 4px;
  height: 22.5px;
  overflow: hidden;
}
.spf-td-week-mean-v { margin-right: 4px; }
/* 单量整体不可拆（避免 "12 单" 被折成 "12" / "单" 两行，实测出现过） */
.spf-td-week-mean-n { color: var(--ink-3, #86868b); font-weight: 500; white-space: nowrap; }
.spf-td-week-mean.null { color: var(--ink-3, #86868b); }
.spf-td-orders { display: flex; flex-direction: column; gap: 1px; }
/* v114.6.9.36 改：4 列并排后每块只有 ~75px 宽，旧版 4 列横排（60px 1fr 1fr 1fr）
 *  会把所有文字压成省略号。改成块内两行堆叠：
 *    第一行 = 日期 | 客户
 *    第二行 = 顾问 | 毛利
 *
 *  ⚠ 顺序陷阱（实测踩过两次）：grid-template-areas 的命名区（"d d c c" 那种）在这里
 *  不可靠 —— 数据行里 4 个 span 的 class 依次是 d / c / c / gp，
 *  而列头行里也是 d / c / c / gp，两者共用同一套 grid-area 规则。
 *  用 grid-template-areas 写法时，两个 .spf-td-order-c 会同时命中同一个区名，
 *  后写的那个覆盖前者 → 列头显示成"日期 顾问 / 客户 毛利"，与数据"08-23 张总 / 王小明 1.20万"
 *  完全错位。
 *  也不能用 :nth-of-type(n) —— 它按**标签类型**计数，两个 -c 加上 -d 都是 span，
 *  nth-of-type(1) 会命中 -d 而不是第一个 -c，同样是错的。
 *
 *  正确做法：用 :nth-child(n)（按子元素**位置**计数，与 class 无关）显式指派行列。
 *  行内子元素固定为 4 个：
 *    1 = .spf-td-order-d   → 第1行左
 *    2 = .spf-td-order-c   （客户）→ 第1行右
 *    3 = .spf-td-order-c   （顾问）→ 第2行左
 *    4 = .spf-td-order-gp  → 第2行右
 *  任何新增/删除子元素都必须同步改这里。 */
.spf-td-order {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  grid-template-rows: auto auto;
  gap: 0 3px;
  font-size: 10px; color: var(--ink-2, #51525a);
  padding: 2px 0;
  align-items: baseline;
}
.spf-td-order > :nth-child(1) { grid-area: 1 / 1; }   /* 日期 */
.spf-td-order > :nth-child(2) { grid-area: 1 / 2; }   /* 客户 */
.spf-td-order > :nth-child(3) { grid-area: 2 / 1; }   /* 顾问 */
.spf-td-order > :nth-child(4) { grid-area: 2 / 2; }   /* 毛利 */
.spf-td-order-d { font-family: var(--font-num); color: var(--ink-3, #86868b); }
.spf-td-order-c { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.spf-td-order-gp {
  font-family: var(--font-num); text-align: right;
  font-weight: 600; color: var(--ink-1, #1d1d1f);
  /* v114.6.9.36 修：原来 nowrap 且不省略，大额毛利（123.45 万）会顶破卡片右边界（实测溢出）。
   *  允许收窄 + 省略号，异常大额也不会破坏等宽约束。 */
  min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
/* 列头行（日期/客户/顾问/毛利）：复用 .spf-td-order 的 grid 定义 → 列严格对齐。
 *  只覆盖字体与下边线，**不动** grid-template-*，否则列头与数据列会错位。 */
.spf-td-order-hd {
  font-size: 9px; color: var(--ink-3, #86868b); font-weight: 500;
  padding-bottom: 3px; margin-bottom: 2px;
  border-bottom: 1px solid var(--border-2, #f2f2f5);
}
.spf-td-order-hd .spf-td-order-gp { color: var(--ink-3, #86868b); font-weight: 500; }
/* v114.6.9.36 修：4 块并排时，有订单的块显示「日期/客户/顾问/毛利」两行列头，
 *  无订单的块只显示一行「本周无订单」→ 两类块的关键内容（周均值）在同一高度、
 *  但订单区起始线参差不齐，横着看有锯齿感。
 *  修法：给无订单块一个与列头**等高**的占位（.spf-td-week-empty 顶部预留同样的
 *  列头高度 + 下边线），这样 4 块的订单区起点永远在同一条水平线上。
 *  高度来源：列头 9px 字号 × line-height 1.2 × 2 行 + padding-bottom 3px + margin 2px
 *  ≈ 30px。改列头字号/行距时这里要同步。 */
.spf-td-week-empty {
  padding: 4px 0;
  font-size: 10px; color: var(--ink-3, #86868b);
}
.spf-td-week-empty::before {
  content: '';
  display: block;
  /* ★ 34px 是实测值（Chromium：列头 9px 字号 × line-height 1.2 × 2 行
   *   + padding-bottom 3px + margin-bottom 2px = 34.1px，取整 34px）。
   *   不要凭公式估算 —— 估出来是 30px，实际差 4px，4 块仍有锯齿。
   *   改 .spf-td-order-hd 的字号/行距/padding 后，必须重新量并同步这里。 */
  height: 34px;
}

/* ============================================================
 *  空态/通用
 * ============================================================ */
.spf-empty {
  text-align: center; padding: 60px 20px; color: var(--ink-3, #8e8e93);
  font-size: 11px;
  font-weight: 400;
}
.spf-empty .spf-empty-ico {
  font-size: 36px; margin-bottom: 8px; opacity: .4;
}

/* 窄屏（≤400px）响应式 */
@media (max-width: 400px) {
  .spf-kpi { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  /* v114.6.9.37：Tab 2 改两行卡片后，窄屏只收紧指标块的间距与字号，
   *   两行结构本身不变（不再有"7 列挤一行"导致的穿模）。
   *   ★ calc 里的 12px = 3 × 4px，必须与 column-gap 同时改。 */
  /* v114.6.9.39：两行都改 4 列模板（第 1 行加「订单车型」）。
   *   ★ 这里的锚点也必须是 .spf（不是 .spf-od-list）—— 原因见上面
   *     「变量必须声明在 .spf 上」那段：.spf-od-hd 是 .spf-od-list 的兄弟，
   *     窄屏覆写若只挂 .spf-od-list，表头又会解析不到变量而退化成单列。
   *
   * ★★★ v114.6.9.48：本段是「手机上到底生效哪套模板」的唯一开关 ★★★
   *   375px < 400px **恒成立** → 真机上跑的就是这两行，上面 .spf 基础规则被覆盖。
   *   ⇒ 只改基础规则、忘改这里 = **手机上完全没反应**（本次踩过）。
   *   第 2 行 --spf-od-m-cols 仍必须四等分（4 个指标块宽度需求相近）。
   *   第 1 行 --spf-od-top-cols 必须与基础规则**同形状**（46px→窄屏 44px）：
   *     "09-10" 在 11px 下墨迹仅 33px，44px 仍有 11px 余量；
   *     客户/顾问各 1fr、车型 3.3fr。
   *   ★ 为什么是 3.3fr 而不是 2.9fr（实测算过，别凭感觉调小）：
   *     生产环境 375px 下卡片内容宽 **357px**（由截图按 390CSS/1179物理 比例反推、
   *     与上一轮实测的单列 86.25px + gap4 ×4 交叉验证一致）→
   *       357 - 44(date) - 12(3×4 gap) = 301；301 / 5.3 = 56.8/1fr
   *       ⇒ 客户/顾问各 ≈57px（3 汉字仅需 33px、4 汉字 44px，均有余量）
   *       ⇒ 车型 ≈187px ≥ 实测最长「梅赛德斯-奔驰 E 300 L 运动版」153.6px ✓
   *     而 2.9fr 在**更窄的容器**（如本仓库预览页 .pv-real 有 18px 额外内边距，
   *     卡片只有 329px、内容 313px）下车型仅 150.9px，仍会截断 2.7px。
   *     取 3.3fr 后同一窄容器下车型 = 160px，两种容器都过。
   *   ★ 若只改基础规则不改这里，或两处形状不一致，症状都是"看着改了但没生效"。 */
  .spf {
    --spf-od-m-cols: repeat(4, calc((100% - 12px) / 4));
    --spf-od-top-cols: 44px minmax(0, 1fr) minmax(0, 1fr) minmax(0, 3.3fr);
  }
  .spf-od { font-size: 11px; font-weight: 400; padding: 6px 8px; }
  .spf-od-top { column-gap: 4px; }
  .spf-od-d { font-size: 11px; font-weight: 400; }
  /* v114.6.9.48：第 1 行第 1 列仅 44px、"09-10" 在 11px 下 33px，
   *   字号不能再降（11px 已是最小可读档）；客户/顾问由 4 等分 76px 压到约 60px，
   *   腾出的宽度全给车型列（约 172px）。 */
  .spf-od-cust, .spf-od-cons { font-size: 11px; font-weight: 400; }
  .spf-od-model { font-size: 11px; font-weight: 400; }
  .spf-od-metrics { column-gap: 4px; }
  .spf-od-mv { font-size: 11px; font-weight: 400; }
  .spf-od-hd { font-size: 11px; padding: 4px 9px; }
  .spf-od-hd-top { column-gap: 4px; }
  .spf-od-hd-metrics { column-gap: 4px; }
  .spf-td-spark { width: 150px; }
  /* v114.6.9.36：窄屏只收紧间距/内边距，**保持 4 列并列**。
   *  并列语义优先 —— 宁可每块窄一点，也不退回纵向堆叠（那正是肉哥反馈的"嵌套/逐步收窄"）。
   *  ★ grid-template-columns 与 column-gap 必须同时改：calc 里的 12px = 3 × 4px。
   *    漏改任何一处，4 块宽度之和就会 ≠ 容器宽 → 又出现间隙不均。 */
  .spf-td-weeks {
    grid-template-columns: repeat(4, calc((100% - 12px) / 4));
    column-gap: 4px;
    padding: 8px;
  }
  .spf-td-week { padding: 5px 5px; }
  .spf-td-order { font-size: 9px; gap: 0 2px; }
  .spf-td-week-lbl { font-size: 10px; }
  .spf-td-week-mean { font-size: 9px; }
}

/* ════════════════════════════════════════════════════════════
   v114.6.9.43 · 重点车型 Tab「落后时间进度的门店」清单
   领导反馈：要一眼看出哪些门店的重点车型订单进度低于时间进度、需要打铁。
   纯白底 + 灰/浅蓝，不引入深色块；与 .card / .sd-sec / .sd-bd 体系保持一致。
   3 列固定模板 [门店 1fr | 达成率 46px | 落后 54px]，表头与数据行同模板 → 严格对齐。
   ★ v114.6.9.44：模板已改成 5 列，见下方说明。
   ════════════════════════════════════════════════════════════ */
/* ★ v114.6.9.44 由 3 列改 5 列（肉哥 9/11）：
 *   「重点车型能否按照 5 列直接划分：品牌/门店 目标 累计 达成率 落后」
 *   「不要用 12/30 台、10% 这种布局，看不清」
 *   旧：[门店 1fr | 达成率 46px | 落后 54px]，门店名后挂 `<i>12/30 台</i>` 挤在同一格
 *   新：[品牌/门店 1fr | 目标 42px | 累计 42px | 达成率 46px | 落后 46px]，gap 5px
 *   表头与数据行**共用同一份 grid 模板** → 逐列严格对齐；数字各自成列、统一右对齐。 */
.sd-km-lag-hd,
.sd-km-lag-row {
  display: grid;
  grid-template-columns: 1fr 42px 42px 46px 46px;
  gap: 5px;
  align-items: center;
}
.sd-km-lag-hd {
  font-size: 11px;
  color: var(--ink-3);
  margin-bottom: 2px;
}
/* 第 1 列左对齐，第 2~5 列右对齐 */
.sd-km-lag-hd span:first-child { text-align: left; }
.sd-km-lag-hd span:nth-child(n+2) { text-align: right; }
.sd-km-lag-row {
  padding: 5px 0;
  border-bottom: 1px solid #f0f1f3;
  cursor: pointer;
}
.sd-km-lag-row:last-child { border-bottom: none; }
/* 第 1 列「品牌/门店」两行：上行品牌（次要，超长省略号）、下行门店名（主体）
 *   跨品牌的店显示去重后的全部品牌（`雷克萨斯 · 凯迪拉克`），不挑一个显示 ——
 *   挑一个会与"跨品牌累加"的判定口径自相矛盾。
 *   若肉哥觉得两行太挤，改回单行 `品牌 · 门店` 只需在这里把 em/b 改成 inline，不动 JS。 */
.sd-km-lag-nm {
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 1px;
}
.sd-km-lag-nm em {
  font-style: normal;
  font-size: 11px;
  font-weight: 400;
  color: var(--ink-3);
  line-height: 1.25;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.sd-km-lag-nm b {
  font-size: 13px;
  font-weight: 400;
  color: var(--ink-1);
  line-height: 1.25;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
/* 第 2/3 列 目标 / 累计：数字正常色（中性事实），只有达成率与落后才代表"落后" → 染红 */
.sd-km-lag-tgt,
.sd-km-lag-act {
  font-size: 13px;
  font-weight: 400;
  color: var(--ink-1);
  text-align: right;
  font-family: var(--font-num);
  font-variant-numeric: tabular-nums;
}
.sd-km-lag-tgt { color: var(--ink-2); }
/* 第 4/5 列 达成率 / 落后：红 */
.sd-km-lag-rate {
  font-size: 13px;
  font-weight: 400;
  color: var(--red);
  text-align: right;
  font-family: var(--font-num);
  font-variant-numeric: tabular-nums;
}
.sd-km-lag-gap {
  font-size: 13px;
  font-weight: 400;
  color: var(--red);
  text-align: right;
  font-family: var(--font-num);
  font-variant-numeric: tabular-nums;
}
.sd-km-lag-ok { font-size: 11px; font-weight: 400; color: var(--green); padding: 6px 0; }

/* 点击「落后门店」行 → 跳到下方重点车型对应的门店块时的高亮（1.6s 后由 JS 摘掉） */
.sd-km-store.jump { background: #fff7ed; border-radius: 6px; transition: background .3s; }
