/* ============================================================================
   theme.css —— C 客户前台的设计系统层（最后加载，负责"统一")
   
   为什么需要这一层：
   · 改造前全站散落 145 个不同色值、43 处手写毛玻璃、83 处阴影、145 处圆角，
     styles.css 一套灰、web/pages/_factory.js 又一套灰，所以看着不统一。
   · 这里做三件事：① 补全设计令牌（tokens）；② 把"应该长得一样"的组件
     统一声明一遍，全部走变量；③ 统一交互动效与毛玻璃规格。
   
   纪律：
   · 只改**皮肤属性**（color / background / border / shadow / radius / transition），
     不改布局属性（display / position / width / height），避免把页面搞乱。
   · 新页面/新组件一律用这里的变量，不准再写死十六进制色值。
   · 想整体换主题，只改这一段的令牌区即可。
   ========================================================================== */

/* ---------------------------------------------------------------- 1. 令牌 */
:root {
  /* 品牌色阶（由主色 #19BE6D 派生，统一 7 档） */
  --brand-50:  #F1FBF6;
  --brand-100: #E3F7EC;
  --brand-200: #C6EFD9;
  --brand-300: #93E1BC;
  --brand-400: #4FCE95;
  --brand-500: #19BE6D;
  --brand-600: #0FA35B;
  --brand-700: #0B7D45;

  /* 中性灰阶（原来的 #909399/#606266/#DCDFE6/#EBEEF5… 全部归到这 8 档） */
  --ink-900: #17233D;   /* 主标题 */
  --ink-700: #303133;   /* 正文强调 */
  --ink-500: #606266;   /* 正文 */
  --ink-400: #8A9099;   /* 次要说明 */
  --ink-300: #B4BAC4;   /* 占位/禁用 */
  --line-100: #EEF1F3;  /* 极浅分隔 */
  --line-200: #E4E8EC;  /* 常规边框 */
  --line-300: #D6DBE1;  /* 强调边框 */

  /* 表面 */
  --surface:        #FFFFFF;
  --surface-soft:   #F7F9FA;
  --surface-glass:  rgba(255, 255, 255, .72);
  --surface-glass2: rgba(255, 255, 255, .88);

  /* 语义色 */
  --sem-ok:     #19BE6D;
  --sem-info:   #2D8CF0;
  --sem-warn:   #F5A623;
  --sem-danger: #F0524D;
  /* 语义色的「文字专用」深档：原色白底只有 2:1 左右，当文字读不清。
     色块/图标/描边继续用上面那组原色，文字一律用这组。 */
  --sem-warn-text:   #B25E00;   /* 4.7:1 */
  --sem-ok-text:     var(--brand-700);
  --sem-danger-text: #C22F2A;   /* 4.9:1 */
  --sem-info-text:   #1A6BC4;   /* 5.4:1 */

  /* 圆角（原来 4/6/8/10/12 混用，收成 4 档） */
  --r-xs: 4px;
  --r-sm: 6px;
  --r-md: 10px;
  --r-lg: 14px;
  --r-pill: 999px;

  /* 阴影（统一色相 + 分 4 档） */
  --sh-1: 0 1px 2px rgba(23, 35, 61, .04), 0 1px 1px rgba(23, 35, 61, .03);
  --sh-2: 0 2px 6px rgba(23, 35, 61, .06), 0 1px 2px rgba(23, 35, 61, .04);
  --sh-3: 0 6px 20px rgba(23, 35, 61, .08), 0 2px 6px rgba(23, 35, 61, .04);
  --sh-4: 0 16px 44px rgba(23, 35, 61, .14), 0 4px 12px rgba(23, 35, 61, .06);

  /* 毛玻璃规格（全站唯一一份，原来 43 处各写各的）
     四档按景深分级：遮罩 < 小控件 < 主卡片 < 弹层，不再各处混写数值。 */
  --glass-blur-xs: blur(6px);
  --glass-blur-sm: blur(10px) saturate(1.25);
  --glass-blur:    blur(18px) saturate(1.6);
  --glass-blur-lg: blur(24px) saturate(1.8);
  --glass-brd: 1px solid rgba(255, 255, 255, .85);

  /* 焦点环（全站一份，原来 2px/3px/4px 三种写法混用） */
  --focus-ring: 0 0 0 3px rgba(25, 190, 109, .18);

  /* ---- 旧变量兼容别名 ----
     styles.css 自带一套 --accent / --radius / --blur / --line，
     与这里的令牌并存且取值不同（16px vs 18px 模糊、6px vs 14px 大圆角），
     是"同一个组件在不同页面长得不一样"的根源。
     这里让旧名字指向新令牌：只保留一份刻度，改一处全站生效。 */
  --accent:        var(--brand-500);
  --accent-pale:   var(--brand-100);
  --accent-soft:   var(--brand-50);
  --panel:         var(--surface);
  --line:          var(--line-100);
  --line-strong:   var(--line-200);
  --radius:        var(--r-xs);
  --radius-lg:     var(--r-sm);
  --radius-pill:   var(--r-pill);
  --blur:          var(--glass-blur);

  /* 动效 */
  --ease: cubic-bezier(.22, .61, .36, 1);
  --dur-1: 140ms;
  --dur-2: 220ms;

  /* 图表分类色（大屏环形图 / 饼图按序取用）
     注意：原来 console.js 的环形图直接按下标拼变量名，但全站从没定义过这组变量，
     导致 conic-gradient 整体失效、环形图一直是空的 —— 这里补齐 10 档。 */
  --dash-slice-0: #19BE6D;
  --dash-slice-1: #2D8CF0;
  --dash-slice-2: #F5A623;
  --dash-slice-3: #8E7BE8;
  --dash-slice-4: #F0524D;
  --dash-slice-5: #13C2C2;
  --dash-slice-6: #FA8C16;
  --dash-slice-7: #52C41A;
  --dash-slice-8: #EB2F96;
  --dash-slice-9: #909399;

  /* 背景：极浅的青灰渐变 + 两团柔光，比纯 #FAFAFA 更有层次 */
  --app-bg:
    radial-gradient(1100px 520px at 12% -8%,  rgba(25, 190, 109, .10), transparent 62%),
    radial-gradient(900px 480px at 92% 4%,   rgba(45, 140, 240, .07), transparent 58%),
    linear-gradient(180deg, #F6FAF8 0%, #F2F6F5 100%);
}

/* ---------------------------------------------------------------- 2. 基底 */
body.console {
  background: var(--app-bg, var(--bg)) !important;
  background-attachment: fixed;
  color: var(--ink-700);
  -webkit-font-smoothing: antialiased;
}

/* 统一滚动条，避免各区域粗细不一 */
body.console *::-webkit-scrollbar { width: 8px; height: 8px; }
body.console *::-webkit-scrollbar-thumb {
  background: #CBD5D1; border-radius: var(--r-pill);
  border: 2px solid transparent; background-clip: content-box;
}
body.console *::-webkit-scrollbar-thumb:hover { background: #A9B7B2; background-clip: content-box; }
body.console *::-webkit-scrollbar-track { background: transparent; }

/* 焦点环统一：绿色柔光，键盘可达 */
body.console :focus-visible {
  outline: 2px solid rgba(25, 190, 109, .55);
  outline-offset: 2px;
  border-radius: var(--r-xs);
}

/* ---------------------------------------------------------------- 2.5 地图页两处布局修正
   这两条不是"换皮"，是实机截图暴露的真 bug：
   ① KPI 条原先在 .mapwrap 里走普通流，被绝对定位的地图盖住、并且溢出到容器底部被裁掉；
   ② 在途订单监控的底表原先是 position:fixed + bottom:62px，浮在地图中间挡视野，
      那个 62px 是给旧版底部 KPI 让位的，KPI 挪进地图后就成了空洞。 */
body.console.b-shell .metrics {
  position: absolute;
  left: 0; right: 0; bottom: 0;
  z-index: 500;
  padding: 8px 92px 10px 12px;
  background: linear-gradient(180deg, rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, .55) 100%);
  pointer-events: none;
}
body.console.b-shell .metrics .metric { pointer-events: auto; }

body.console.b-shell[data-view=overview] .bottom,
body.console.b-shell[data-view=monitor-vehicles] .bottom {
  position: relative !important;
  left: auto !important; right: auto !important;
  bottom: auto !important; top: auto !important;
  margin: 0 12px 10px !important;
  max-height: 34vh;
  background: var(--surface-glass2) !important;
  -webkit-backdrop-filter: var(--glass-blur);
  backdrop-filter: var(--glass-blur);
  border: var(--glass-brd) !important;
  border-radius: var(--r-md) !important;
  box-shadow: var(--sh-3) !important;
}

/* ---------------------------------------------------------------- 3. 顶栏 */body.console.b-shell .app-header {
  background: var(--surface-glass2) !important;
  -webkit-backdrop-filter: var(--glass-blur);
  backdrop-filter: var(--glass-blur);
  border-bottom: 1px solid rgba(23, 35, 61, .06) !important;
  box-shadow: 0 1px 0 rgba(255, 255, 255, .9) inset, var(--sh-2);
}

body.console.b-shell .nav-top,
body.console.b-shell .brand-name,
body.console.b-shell .account-text { color: var(--ink-700); }

body.console.b-shell .nav-item.on .nav-top,
body.console.b-shell .nav-item.has-menu:hover .nav-top { color: var(--brand-600); }

/* 下拉菜单：玻璃 + 浮起 */
body.console.b-shell .nav-drop,
body.console.b-shell .account-drop {
  background: var(--surface-glass2) !important;
  -webkit-backdrop-filter: var(--glass-blur);
  backdrop-filter: var(--glass-blur);
  border: var(--glass-brd) !important;
  border-radius: var(--r-md) !important;
  box-shadow: var(--sh-4) !important;
  padding: 6px !important;
  animation: cfPop var(--dur-2) var(--ease);
}
body.console.b-shell .nav-drop button,
body.console.b-shell .account-drop button {
  border-radius: var(--r-sm) !important;
  transition: background var(--dur-1) var(--ease), color var(--dur-1) var(--ease);
}
body.console.b-shell .nav-drop button:hover,
body.console.b-shell .account-drop button:hover { background: var(--brand-50) !important; color: var(--brand-600) !important; }

/* 右上报警卡片：统一玻璃与描边 */
body.console.b-shell .alarm-caps {
  border-radius: var(--r-md) !important;
  border: var(--glass-brd) !important;
  background: var(--surface-glass2) !important;
  -webkit-backdrop-filter: var(--glass-blur);
  backdrop-filter: var(--glass-blur);
  box-shadow: var(--sh-1) !important;
  transition: box-shadow var(--dur-2) var(--ease), transform var(--dur-2) var(--ease);
}
body.console.b-shell .alarm-caps:hover { box-shadow: var(--sh-3) !important; transform: translateY(-1px); }

/* ---------------------------------------------------------------- 4. 页签条 */
body.console.b-shell .subtabs {
  background: var(--surface-glass) !important;
  -webkit-backdrop-filter: var(--glass-blur);
  backdrop-filter: var(--glass-blur);
  border-bottom: 1px solid rgba(23, 35, 61, .05) !important;
}

body.console.b-shell .subtab {
  border-radius: var(--r-pill) !important;
  border: 1px solid transparent !important;
  color: var(--ink-500) !important;
  background: transparent !important;
  transition: all var(--dur-2) var(--ease);
}
body.console.b-shell .subtab:hover { background: var(--brand-50) !important; color: var(--brand-600) !important; }
body.console.b-shell .subtab.on {
  background: linear-gradient(135deg, var(--brand-500), var(--brand-600)) !important;
  color: #fff !important;
  border-color: transparent !important;
  box-shadow: 0 2px 8px rgba(25, 190, 109, .32), 0 1px 0 rgba(255, 255, 255, .3) inset;
}
body.console.b-shell .subtab.on .tab-close { color: rgba(255, 255, 255, .8); }
body.console.b-shell .subtab.on #navAnomalyCount {
  background: rgba(255, 255, 255, .28) !important; color: #fff !important;
}

/* ---------------------------------------------------------------- 5. 左栏 */
body.console.b-shell .tree {
  background: var(--surface-glass) !important;
  -webkit-backdrop-filter: var(--glass-blur);
  backdrop-filter: var(--glass-blur);
  border-right: 1px solid rgba(23, 35, 61, .05) !important;
}

/* ---------------------------------------------------------------- 6. 页面容器 */
body.console.b-shell .page-host,
body.console.b-shell .b-page { background: transparent; }

/* ---------------------------------------------------------------- 7. 筛选条 */
body.console.b-shell .b-filters,
body.console.b-shell .page-tabs {
  background: var(--surface-glass2) !important;
  -webkit-backdrop-filter: var(--glass-blur);
  backdrop-filter: var(--glass-blur);
  border: var(--glass-brd) !important;
  border-radius: var(--r-md) !important;
  box-shadow: var(--sh-1) !important;
  padding: 12px 14px !important;
  margin-bottom: 12px !important;
}

body.console.b-shell .b-field,
body.console.b-shell .page-tabs label { color: var(--ink-500); font-size: 13px; }

/* 输入/下拉：统一高度、圆角、聚焦状态 */
body.console.b-shell .b-field input,
body.console.b-shell .b-field select,
body.console.b-shell .page-tabs input,
body.console.b-shell .page-q,
body.console.b-shell .b-dt {
  height: 30px !important;
  border: 1px solid var(--line-200) !important;
  border-radius: var(--r-sm) !important;
  background: #fff !important;
  color: var(--ink-700) !important;
  padding: 0 9px !important;
  font-size: 13px !important;
  box-shadow: none !important;
  transition: border-color var(--dur-1) var(--ease), box-shadow var(--dur-1) var(--ease);
}
body.console.b-shell .b-field input::placeholder,
body.console.b-shell .page-q::placeholder { color: var(--ink-300) !important; }
body.console.b-shell .b-field input:hover,
body.console.b-shell .b-field select:hover { border-color: var(--line-300) !important; }
body.console.b-shell .b-field input:focus,
body.console.b-shell .b-field select:focus,
body.console.b-shell .page-q:focus {
  border-color: var(--brand-400) !important;
  box-shadow: 0 0 0 3px rgba(25, 190, 109, .13) !important;
  outline: none !important;
}

/* ---------------------------------------------------------------- 8. 按钮 */
body.console.b-shell .b-btn,
body.console.b-shell .btn {
  height: 30px;
  padding: 0 14px;
  border-radius: var(--r-sm) !important;
  border: 1px solid var(--line-200) !important;
  background: #fff !important;
  color: var(--ink-500) !important;
  font-size: 13px;
  box-shadow: var(--sh-1);
  transition: all var(--dur-2) var(--ease);
}
body.console.b-shell .b-btn:hover,
body.console.b-shell .btn:hover {
  border-color: var(--brand-300) !important;
  color: var(--brand-600) !important;
  background: var(--brand-50) !important;
  transform: translateY(-1px);
  box-shadow: var(--sh-2);
}
body.console.b-shell .b-btn.primary,
body.console.b-shell .btn.primary {
  background: linear-gradient(135deg, var(--brand-500) 0%, var(--brand-600) 100%) !important;
  border-color: var(--brand-600) !important;
  color: #fff !important;
  box-shadow: 0 2px 8px rgba(25, 190, 109, .30), 0 1px 0 rgba(255, 255, 255, .28) inset;
}
body.console.b-shell .b-btn.primary:hover,
body.console.b-shell .btn.primary:hover {
  background: linear-gradient(135deg, var(--brand-600) 0%, var(--brand-700) 100%) !important;
  color: #fff !important;
  box-shadow: 0 6px 16px rgba(25, 190, 109, .36), 0 1px 0 rgba(255, 255, 255, .3) inset;
}
body.console.b-shell .b-btn:active,
body.console.b-shell .btn:active { transform: translateY(0); }

/* 状态胶囊（单据状态筛选） */
body.console.b-shell .b-status-pills {
  border-radius: var(--r-pill) !important;
  background: var(--surface-soft) !important;
  border: 1px solid var(--line-200) !important;
  padding: 2px !important;
  gap: 2px !important;
}
body.console.b-shell .b-status-pills button {
  border: 0 !important;
  border-radius: var(--r-pill) !important;
  background: transparent !important;
  color: var(--ink-500) !important;
  padding: 3px 12px !important;
  font-size: 12.5px !important;
  transition: all var(--dur-1) var(--ease);
}
body.console.b-shell .b-status-pills button:hover { color: var(--brand-600) !important; }
body.console.b-shell .b-status-pills button.on {
  background: #fff !important;
  color: var(--brand-600) !important;
  font-weight: 600;
  box-shadow: var(--sh-1);
}

/* ---------------------------------------------------------------- 9. 表格卡片 */
body.console.b-shell .b-sheet {
  background: var(--surface-glass2) !important;
  -webkit-backdrop-filter: var(--glass-blur);
  backdrop-filter: var(--glass-blur);
  border: var(--glass-brd) !important;
  border-radius: var(--r-md) !important;
  box-shadow: var(--sh-2) !important;
  overflow: hidden;
}

body.console.b-shell .b-sheet-head {
  background: transparent !important;
  border-bottom: 1px solid var(--line-100) !important;
  padding: 12px 16px !important;
}
body.console.b-shell .b-sheet-head > span:first-child {
  color: var(--ink-900);
  font-size: 14px;
  font-weight: 600;
  position: relative;
  padding-left: 10px;
}
/* 标题前一条品牌色竖线（B 实站有这个细节） */
body.console.b-shell .b-sheet-head > span:first-child::before {
  content: '';
  position: absolute; left: 0; top: 50%; transform: translateY(-50%);
  width: 3px; height: 14px; border-radius: 2px;
  background: linear-gradient(180deg, var(--brand-400), var(--brand-600));
}

/* 表头 */
body.console.b-shell .b-group-table thead th,
body.console.b-shell table.grid thead th {
  background: linear-gradient(180deg, #F8FBFA 0%, #F3F7F5 100%) !important;
  color: var(--ink-500) !important;
  font-weight: 600 !important;
  font-size: 12.5px !important;
  border-bottom: 1px solid var(--line-200) !important;
  white-space: nowrap;
}

/* 数据行：斑马纹 + hover 主色淡底 */
body.console.b-shell .b-group-table tbody tr,
body.console.b-shell table.grid tbody tr {
  transition: background var(--dur-1) var(--ease);
}
body.console.b-shell .b-group-table tbody tr:nth-child(even),
body.console.b-shell table.grid tbody tr:nth-child(even) { background: rgba(247, 250, 249, .72); }
body.console.b-shell .b-group-table tbody tr:hover,
body.console.b-shell table.grid tbody tr:hover { background: var(--brand-50) !important; }
body.console.b-shell .b-group-table tbody td,
body.console.b-shell table.grid tbody td {
  border-bottom: 1px solid var(--line-100) !important;
  color: var(--ink-700);
}

/* 空态文案统一 */
body.console.b-shell .b-empty,
body.console.b-shell .empty,
body.console.b-shell .cf-chart-empty { color: var(--ink-300) !important; }

/* 行内文字操作按钮：统一配色分级 */
body.console.b-shell .b-op {
  border: 0 !important;
  background: transparent !important;
  color: var(--brand-600) !important;
  font-size: 12.5px !important;
  padding: 0 6px !important;
  cursor: pointer;
  transition: color var(--dur-1) var(--ease);
}
body.console.b-shell .b-op:hover { color: var(--brand-700) !important; text-decoration: underline; }
body.console.b-shell .b-op[data-tone="danger"] { color: var(--sem-danger) !important; }

/* 分页 */
body.console.b-shell .pager,
body.console.b-shell .b-pager {
  background: transparent !important;
  border-top: 1px solid var(--line-100) !important;
  color: var(--ink-400);
}

/* ---------------------------------------------------------------- 10. 统计卡 & 图表卡 */
body.console.b-shell .cf-stat {
  background: var(--surface-glass2) !important;
  -webkit-backdrop-filter: var(--glass-blur);
  backdrop-filter: var(--glass-blur);
  border: var(--glass-brd) !important;
  border-radius: var(--r-md) !important;
  box-shadow: var(--sh-1) !important;
  transition: transform var(--dur-2) var(--ease), box-shadow var(--dur-2) var(--ease);
}
body.console.b-shell .cf-stat:hover { transform: translateY(-2px); box-shadow: var(--sh-3) !important; }
body.console.b-shell .cf-stat-k { color: var(--ink-400) !important; }
body.console.b-shell .cf-stat-v { color: var(--ink-900) !important; font-variant-numeric: tabular-nums; }
body.console.b-shell .cf-stat-v small { color: var(--ink-400) !important; }

body.console.b-shell .cf-card {
  background: var(--surface-glass2) !important;
  -webkit-backdrop-filter: var(--glass-blur);
  backdrop-filter: var(--glass-blur);
  border: var(--glass-brd) !important;
  border-radius: var(--r-md) !important;
  box-shadow: var(--sh-2) !important;
}
body.console.b-shell .cf-card-head h3 { color: var(--ink-900) !important; }
body.console.b-shell .cf-card-tabs {
  border-radius: var(--r-pill) !important;
  border: 1px solid var(--line-200) !important;
  background: var(--surface-soft);
  padding: 2px;
  gap: 2px;
}
body.console.b-shell .cf-card-tabs button {
  border-radius: var(--r-pill) !important;
  color: var(--ink-500) !important;
  background: transparent !important;
  transition: all var(--dur-1) var(--ease);
}
body.console.b-shell .cf-card-tabs button.on {
  background: #fff !important;
  color: var(--brand-600) !important;
  font-weight: 600;
  box-shadow: var(--sh-1);
}

/* ---------------------------------------------------------------- 11. KPI 条 */
body.console.b-shell .metric {
  background: var(--surface-glass2) !important;
  -webkit-backdrop-filter: var(--glass-blur);
  backdrop-filter: var(--glass-blur);
  border: var(--glass-brd) !important;
  border-radius: var(--r-md) !important;
  box-shadow: var(--sh-1) !important;
  transition: transform var(--dur-2) var(--ease), box-shadow var(--dur-2) var(--ease);
}
body.console.b-shell .metric:hover { transform: translateY(-1px); box-shadow: var(--sh-2) !important; }
body.console.b-shell .metric .k { color: var(--ink-400) !important; }
body.console.b-shell .metric .v { color: var(--ink-900) !important; }

/* ---------------------------------------------------------------- 12. 弹层 */
body.console.b-shell .modal {
  background: rgba(16, 30, 27, .38) !important;
  -webkit-backdrop-filter: blur(3px);
  backdrop-filter: blur(3px);
}
body.console.b-shell .modal-card {
  background: var(--surface-glass2) !important;
  -webkit-backdrop-filter: var(--glass-blur);
  backdrop-filter: var(--glass-blur);
  border: var(--glass-brd) !important;
  border-radius: var(--r-lg) !important;
  box-shadow: var(--sh-4) !important;
  animation: cfModal var(--dur-2) var(--ease);
}

/* Toast：浮起 + 玻璃 */
body.console .toast {
  border-radius: var(--r-md) !important;
  box-shadow: var(--sh-4) !important;
  animation: cfSlideUp var(--dur-2) var(--ease);
}

/* ---------------------------------------------------------------- 13. 「待数据源」角标 */
.cf-stub {
  background: #FFF8E8; color: #C97E12;
  border: 1px solid #FBE3B4;
  border-radius: var(--r-pill);
  padding: 2px 10px;
  font-weight: 500;
}

/* ---------------------------------------------------------------- 14. 安全看板两屏：并入浅色体系
   原状：这两个视图是整屏深色（B 的原始形态），与其余 23 页的白底完全割裂，
   用户第一眼就是"这俩不是同一个系统"。
   这里保留 B 的宫格结构（左统计 / 中视频 / 右报警 / 下趋势），只把皮肤换成
   与全站同一套令牌：白卡 + 同一份毛玻璃 + 同一档圆角阴影 + 同一组文字灰阶。
   布局属性一律不动，避免把宫格挤坏。 */
body.console.b-shell.dash-theme .page-host {
  background: transparent !important;
  color: var(--ink-700) !important;
}
body.console.b-shell.dash-theme .dash-hud { padding-bottom: 20px; }

/* 标题与顶部按钮：与列表页标题同一口径 */
body.console.b-shell.dash-theme .dash-title {
  font-size: 20px !important;
  letter-spacing: 1px !important;
  font-weight: 700 !important;
  background: none !important;
  color: var(--ink-900) !important;
  -webkit-text-fill-color: var(--ink-900);
}
body.console.b-shell.dash-theme .dash-btn,
body.console.b-shell.dash-theme .dash-range button {
  background: var(--surface) !important;
  border: 1px solid var(--line-200) !important;
  color: var(--ink-500) !important;
  border-radius: var(--r-sm) !important;
  padding: 4px 12px !important;
  font-size: 12px !important;
  box-shadow: var(--sh-1);
  transition: all var(--dur-1) var(--ease);
}
body.console.b-shell.dash-theme .dash-btn:hover,
body.console.b-shell.dash-theme .dash-range button:not([disabled]):hover {
  background: var(--brand-50) !important;
  border-color: var(--brand-300) !important;
  color: var(--brand-700) !important;
}
body.console.b-shell.dash-theme .dash-range button.on {
  background: var(--brand-500) !important;
  border-color: var(--brand-500) !important;
  color: #FFFFFF !important;
}
body.console.b-shell.dash-theme .dash-range button[disabled] { opacity: .55; }

/* 面板：全站同一张白卡 */
body.console.b-shell.dash-theme .dash-panel {
  background: var(--surface-glass2) !important;
  border: 1px solid var(--line-200) !important;
  border-radius: var(--r-md) !important;
  -webkit-backdrop-filter: var(--glass-blur);
  backdrop-filter: var(--glass-blur);
  box-shadow: var(--sh-2) !important;
}
body.console.b-shell.dash-theme .dash-panel h2 {
  color: var(--ink-900) !important;
  border-bottom: 1px solid var(--line-100) !important;
  padding-bottom: 8px !important;
  margin-bottom: 12px !important;
  font-weight: 600 !important;
}
/* 标题前的菱形换成其他页统一的品牌竖条 */
body.console.b-shell.dash-theme .dash-panel h2::before {
  content: "" !important;
  width: 3px !important;
  height: 14px !important;
  border: 0 !important;
  transform: none !important;
  border-radius: var(--r-pill);
  background: var(--brand-500);
}
body.console.b-shell.dash-theme .dash-trend-svg { width: 100%; height: 150px; display: block; }
body.console.b-shell.dash-theme .dash-bars { min-height: 150px; }

/* 运营分析宫格：B 是「上三下二」且下面两块各占一半宽、整屏撑满；
   C 原来沿用三列布局，第二行只剩两块、右下空一格，下方还空半屏。
   改成 6 列栅格：上排每块占 2 列（三等分），下排每块占 3 列（二等分）。 */
body.console.b-shell.dash-theme .dash-ops-grid {
  grid-template-columns: repeat(6, minmax(0, 1fr)) !important;
  grid-template-rows: minmax(230px, .92fr) minmax(240px, 1fr) !important;
  min-height: calc(100vh - 250px);
}
body.console.b-shell.dash-theme .dash-ops-grid > .dash-panel:nth-child(-n+3) { grid-column: span 2; }
body.console.b-shell.dash-theme .dash-ops-grid > .dash-panel:nth-child(n+4) { grid-column: span 3; }
body.console.b-shell.dash-theme .dash-ops-grid > .dash-panel { min-height: 0; }

/* 视频占位：浅灰虚线框，不再是黑洞 */
body.console.b-shell.dash-theme .dash-video-tile {
  border-radius: var(--r-sm) !important;
  background: var(--surface-soft) !important;
  border: 1px dashed var(--line-300) !important;
  color: var(--ink-300) !important;
}

/* 「今日报警数」四块 */
body.console.b-shell.dash-theme .dash-stat { gap: 14px; padding: 4px 0; }
body.console.b-shell.dash-theme .dash-stat b {
  font-size: 26px; line-height: 1.1; color: var(--ink-900);
  font-variant-numeric: tabular-nums;
}
body.console.b-shell.dash-theme .dash-stat span { color: var(--ink-400); font-size: 12px; }

/* 百分环：底圈改浅灰，内圈改白 */
body.console.b-shell.dash-theme .dash-ring {
  background: conic-gradient(var(--brand-500) calc(var(--p) * 1%), var(--line-100) 0);
}
body.console.b-shell.dash-theme .dash-ring::after { background: var(--surface); }
body.console.b-shell.dash-theme .dash-ring b { color: var(--ink-900); }
body.console.b-shell.dash-theme .dash-donut::after { background: var(--surface); }

/* 三个迷你装饰环：深色发光 → 浅色淡彩 */
body.console.b-shell.dash-theme .dash-gauge,
body.console.b-shell.dash-theme .dash-dot-chart,
body.console.b-shell.dash-theme .dash-donut.sm {
  width: 44px; height: 44px; flex: 0 0 44px; border-radius: 50%;
  border: 3px solid var(--brand-200);
  background: radial-gradient(circle at 50% 40%, rgba(25, 190, 109, .22), rgba(25, 190, 109, .04) 74%);
  box-shadow: 0 0 0 4px rgba(25, 190, 109, .05);
}
body.console.b-shell.dash-theme .dash-gauge {
  border-color: #C3DEFB;
  background: radial-gradient(circle at 50% 40%, rgba(45, 140, 240, .22), rgba(45, 140, 240, .04) 74%);
  box-shadow: 0 0 0 4px rgba(45, 140, 240, .05);
}
body.console.b-shell.dash-theme .dash-dot-chart {
  border-color: #FAE2B4;
  background: radial-gradient(circle at 50% 40%, rgba(245, 166, 35, .22), rgba(245, 166, 35, .04) 74%);
  box-shadow: 0 0 0 4px rgba(245, 166, 35, .05);
}
body.console.b-shell.dash-theme .dash-donut.sm {
  border-color: #DBD5F7;
  background: radial-gradient(circle at 50% 40%, rgba(142, 123, 232, .22), rgba(142, 123, 232, .04) 74%);
  box-shadow: 0 0 0 4px rgba(142, 123, 232, .05);
}

/* KPI 卡（运营分析大屏顶部 7 张） */
body.console.b-shell.dash-theme .dash-kpi {
  background: var(--surface-glass2) !important;
  border: 1px solid var(--line-200) !important;
  border-radius: var(--r-md) !important;
  box-shadow: var(--sh-2) !important;
  transition: transform var(--dur-1) var(--ease), box-shadow var(--dur-1) var(--ease);
}
body.console.b-shell.dash-theme .dash-kpi:hover { transform: translateY(-2px); box-shadow: var(--sh-3) !important; }
body.console.b-shell.dash-theme .dash-kpi b { color: var(--ink-900); }
body.console.b-shell.dash-theme .dash-kpi b small { color: var(--ink-400); }
body.console.b-shell.dash-theme .dash-kpi span { color: var(--ink-400); }

/* 表格：与列表页同一套表头/行/空态 */
body.console.b-shell.dash-theme .dash-table th {
  color: var(--ink-500);
  background: var(--brand-50);
  border-bottom: 1px solid var(--line-200);
  font-weight: 600;
  padding: 8px 6px;
}
body.console.b-shell.dash-theme .dash-table td {
  color: var(--ink-700);
  border-bottom: 1px solid var(--line-100);
  padding: 8px 6px;
}
body.console.b-shell.dash-theme .dash-table tbody tr:hover td { background: var(--brand-50); }
body.console.b-shell.dash-theme .dash-table td.empty,
body.console.b-shell.dash-theme .dash-panel .empty { color: var(--ink-400); }
body.console.b-shell.dash-theme .dash-plate {
  background: #FDF3D8; color: #8A5A00; border: 1px solid #F3DFAE; border-radius: var(--r-xs);
}

/* 柱状趋势 / 图例 / 空态文字 */
body.console.b-shell.dash-theme .dash-bar i { background: linear-gradient(180deg, var(--brand-300), var(--brand-500)); border-radius: var(--r-xs) var(--r-xs) 0 0; }
body.console.b-shell.dash-theme .dash-bar span { color: var(--ink-400); }
body.console.b-shell.dash-theme .dash-legend,
body.console.b-shell.dash-theme .dash-line-empty { color: var(--ink-500); }
body.console.b-shell.dash-theme .dash-line-empty span { color: var(--ink-400); }
body.console.b-shell.dash-theme .b-range-dash { color: var(--ink-300); }

/* 空态居中：.dash-bars 是 align-items:flex-end 的 flex 容器，
   里面的「暂无数据」会被拽到左下角，一整条面板只剩角落里几个字。 */
body.console.b-shell.dash-theme .dash-bars > .empty {
  width: 100%; align-self: center;
  display: flex; align-items: center; justify-content: center;
  min-height: 120px; padding: 0;
  color: var(--ink-300); font-size: 13px;
}
body.console.b-shell.dash-theme .dash-panel > .empty,
body.console.b-shell.dash-theme .dash-donut-wrap ~ .empty {
  display: flex; align-items: center; justify-content: center;
  min-height: 120px; color: var(--ink-300); font-size: 13px;
}

/* ---------------------------------------------------------------- 14.5 登录页
   登录页是独立文件，也要跟后台同一套色板，否则客户第一眼就觉得"两个产品"。 */
body.login {
  background: var(--app-bg) !important;
  background-attachment: fixed;
}
body.login .login-card {
  border-radius: var(--r-lg) !important;
  border: var(--glass-brd) !important;
  box-shadow: var(--sh-4) !important;
  overflow: hidden;
  animation: cfModal var(--dur-2) var(--ease);
}
body.login .login-brand {
  background:
    radial-gradient(320px 180px at 20% 12%, rgba(255, 255, 255, .22), transparent 70%),
    linear-gradient(155deg, var(--brand-500) 0%, var(--brand-600) 55%, var(--brand-700) 100%) !important;
}
body.login .login-logo {
  background: rgba(255, 255, 255, .18) !important;
  border: 1px solid rgba(255, 255, 255, .32) !important;
  border-radius: var(--r-md) !important;
  -webkit-backdrop-filter: blur(6px);
  backdrop-filter: blur(6px);
}
body.login .login-form input {
  height: 38px !important;
  border-radius: var(--r-sm) !important;
  border: 1px solid var(--line-200) !important;
  transition: border-color var(--dur-1) var(--ease), box-shadow var(--dur-1) var(--ease);
}
body.login .login-form input:focus {
  border-color: var(--brand-400) !important;
  box-shadow: 0 0 0 3px rgba(25, 190, 109, .13) !important;
  outline: none !important;
}
body.login .login-form .btn.primary {
  height: 38px !important;
  border-radius: var(--r-sm) !important;
  background: linear-gradient(135deg, var(--brand-500) 0%, var(--brand-600) 100%) !important;
  box-shadow: 0 4px 14px rgba(25, 190, 109, .34), 0 1px 0 rgba(255, 255, 255, .3) inset !important;
  letter-spacing: 2px;
}

/* ---------------------------------------------------------------- 15. 入场动画 */@keyframes cfPop {
  from { opacity: 0; transform: translateY(-6px) scale(.98); }
  to   { opacity: 1; transform: translateY(0) scale(1); }
}
@keyframes cfModal {
  from { opacity: 0; transform: translateY(10px) scale(.985); }
  to   { opacity: 1; transform: translateY(0) scale(1); }
}
@keyframes cfSlideUp {
  from { opacity: 0; transform: translateY(8px); }
  to   { opacity: 1; transform: translateY(0); }
}

/* 内容区首帧轻微上浮，翻页时不生硬 */
body.console.b-shell .b-page { animation: cfSlideUp var(--dur-2) var(--ease); }

/* 尊重系统"减少动效"设置 */
@media (prefers-reduced-motion: reduce) {
  body.console.b-shell *,
  body.console.b-shell *::before,
  body.console.b-shell *::after {
    animation-duration: .01ms !important;
    transition-duration: .01ms !important;
  }
}

/* ============================================================================
   16. 个人偏好（设置抽屉）—— 通过 body[data-*] 覆盖令牌，不改布局
   ========================================================================== */

/* 派生变量必须在 body 作用域重新声明：:root 里求值一次就固化了，
   换色板时不会跟着变（--sem-ok-text 原来就踩了这个坑）。 */
body {
  --sem-ok-text: var(--brand-700);
}

/* 三套色板：只改品牌色阶，语义色/中性色不动 */
body[data-brand="b"] {
  --brand-50:  #F1FBF6;
  --brand-100: #E3F7EC;
  --brand-200: #C6EFD9;
  --brand-300: #93E1BC;
  --brand-400: #4FCE95;
  --brand-500: #19BE6D;
  --brand-600: #0FA35B;
  --brand-700: #0B7D45;
}
body[data-brand="wp"] {
  --brand-50:  #F3F9F6;
  --brand-100: #E6F3EC;
  --brand-200: #C9E7D9;
  --brand-300: #98D2BA;
  --brand-400: #6FBC9C;
  --brand-500: #4F9D7E;
  --brand-600: #3E8A6C;
  --brand-700: #2F6B53;
}
body[data-brand="deep"] {
  --brand-50:  #F1F6F4;
  --brand-100: #E1ECE7;
  --brand-200: #C2D9D1;
  --brand-300: #8FB8AA;
  --brand-400: #5E9483;
  --brand-500: #2F6B53;
  --brand-600: #275B46;
  --brand-700: #1C4534;
}

/* 毛玻璃三档：只动模糊与透明度 */
body[data-glass="off"] {
  --glass-blur-xs: none;
  --glass-blur-sm: none;
  --glass-blur: none;
  --glass-blur-lg: none;
  --surface-glass: #FFFFFF;
  --surface-glass2: #FFFFFF;
  --glass-brd: 1px solid var(--line-200);
}
body[data-glass="strong"] {
  --glass-blur: blur(26px) saturate(1.85);
  --glass-blur-lg: blur(34px) saturate(2);
  --surface-glass: rgba(255, 255, 255, .64);
  --surface-glass2: rgba(255, 255, 255, .80);
}

/* 密度三档：只压行高与内边距，不碰字号（改字号会把表格列宽撑乱） */
body[data-density="compact"] .b-sheet td,
body[data-density="compact"] .b-sheet th { padding-top: 5px !important; padding-bottom: 5px !important; }
body[data-density="compact"] .cf-stat { padding-top: 9px !important; padding-bottom: 9px !important; }
body[data-density="compact"] .cf-card-head { padding-top: 8px !important; padding-bottom: 4px !important; }
body[data-density="loose"] .b-sheet td,
body[data-density="loose"] .b-sheet th { padding-top: 13px !important; padding-bottom: 13px !important; }
body[data-density="loose"] .cf-stat { padding-top: 18px !important; padding-bottom: 18px !important; }

/* ---------------------------------------------------------------- 账号菜单 */
body.console.b-shell .account-role {
  display: block;
  font-style: normal;
  font-size: 11px;
  color: var(--ink-400);
  margin-top: 2px;
}
body.console.b-shell .account-drop button { display: flex; align-items: center; gap: 8px; }
body.console.b-shell .account-drop button .mi { flex: 0 0 14px; color: var(--ink-400); }
body.console.b-shell .account-drop button:hover .mi { color: var(--brand-600); }
body.console.b-shell .account-drop button.danger { color: var(--sem-danger-text); }
body.console.b-shell .account-drop button.danger:hover {
  background: color-mix(in srgb, var(--sem-danger) 8%, #fff);
  color: var(--sem-danger-text);
}
body.console.b-shell .account-sep {
  height: 1px;
  margin: 4px 0;
  background: var(--line-200);
}

/* ---------------------------------------------------------------- 设置抽屉 */
.sd-host { position: fixed; inset: 0; z-index: 9000; }
.sd-mask {
  position: absolute; inset: 0;
  background: rgba(23, 35, 61, .26);
  -webkit-backdrop-filter: blur(2px);
  backdrop-filter: blur(2px);
  opacity: 0;
  transition: opacity var(--dur-2) var(--ease);
}
.sd-host.on .sd-mask { opacity: 1; }

.sd {
  position: absolute; top: 0; right: 0; bottom: 0;
  width: 384px; max-width: calc(100vw - 40px);
  display: flex; flex-direction: column;
  background: var(--surface-glass2);
  -webkit-backdrop-filter: var(--glass-blur-lg);
  backdrop-filter: var(--glass-blur-lg);
  border-left: var(--glass-brd);
  box-shadow: var(--sh-4);
  border-radius: var(--r-lg) 0 0 var(--r-lg);
  transform: translateX(102%);
  transition: transform var(--dur-2) var(--ease);
}
.sd-host.on .sd { transform: translateX(0); }

.sd-head {
  display: flex; align-items: flex-start; justify-content: space-between;
  gap: 12px;
  padding: 18px 20px 14px;
  border-bottom: 1px solid var(--line-200);
}
.sd-title { display: flex; flex-direction: column; gap: 3px; }
.sd-title strong { font-size: 15px; font-weight: 600; color: var(--ink-900); }
.sd-title span { font-size: 12px; color: var(--ink-400); }
.sd-x {
  width: 28px; height: 28px; flex: 0 0 28px;
  display: inline-flex; align-items: center; justify-content: center;
  border: 1px solid var(--line-200);
  border-radius: var(--r-sm);
  background: var(--surface);
  color: var(--ink-500);
  cursor: pointer;
  transition: all var(--dur-1) var(--ease);
}
.sd-x:hover { color: var(--brand-600); border-color: var(--brand-200); background: var(--brand-50); }

.sd-body { flex: 1; overflow-y: auto; padding: 4px 20px 24px; }
.sd-sec { padding: 16px 0; border-bottom: 1px solid var(--line-100); }
.sd-sec:last-child { border-bottom: 0; }
.sd-sec h4 {
  margin: 0 0 12px;
  font-size: 12px; font-weight: 600; letter-spacing: .06em;
  color: var(--ink-400);
  text-transform: uppercase;
}
.sd-row { display: flex; align-items: center; justify-content: space-between; gap: 12px; margin-bottom: 10px; }
.sd-row:last-child { margin-bottom: 0; }
.sd-row > label { font-size: 13px; color: var(--ink-700); flex: 0 0 auto; }
.sd-row-col { flex-direction: column; align-items: stretch; gap: 8px; }

/* 色块选择 */
.sd-swatch { display: flex; gap: 8px; }
.sd-swatch button {
  flex: 1; display: flex; align-items: center; gap: 6px;
  padding: 7px 9px;
  border: 1px solid var(--line-200);
  border-radius: var(--r-sm);
  background: var(--surface);
  font-size: 12px; color: var(--ink-500);
  cursor: pointer;
  transition: all var(--dur-1) var(--ease);
}
.sd-swatch button i { width: 14px; height: 14px; border-radius: 50%; flex: 0 0 14px; box-shadow: inset 0 0 0 1px rgba(0,0,0,.06); }
.sd-swatch button.on { border-color: var(--brand-400); background: var(--brand-50); color: var(--brand-700); font-weight: 600; }
.sd-swatch button:hover { border-color: var(--brand-300); }

/* 分段选择 */
.sd-seg { display: inline-flex; border: 1px solid var(--line-200); border-radius: var(--r-sm); overflow: hidden; }
.sd-seg button {
  border: 0; padding: 6px 12px;
  background: var(--surface);
  font-size: 12px; color: var(--ink-500);
  cursor: pointer;
  transition: all var(--dur-1) var(--ease);
}
.sd-seg button + button { border-left: 1px solid var(--line-200); }
.sd-seg button.on { background: var(--brand-50); color: var(--brand-700); font-weight: 600; }
.sd-seg button:hover:not(.on) { background: var(--surface-soft); }

/* 键值行 */
.sd-kv { display: flex; align-items: center; justify-content: space-between; gap: 12px; padding: 6px 0; font-size: 13px; }
.sd-kv span { color: var(--ink-400); }
.sd-kv b { color: var(--ink-900); font-weight: 500; text-align: right; }

.sd-act {
  width: 100%; margin-top: 10px;
  display: inline-flex; align-items: center; justify-content: center; gap: 7px;
  height: 34px;
  border: 1px solid var(--brand-300);
  border-radius: var(--r-sm);
  background: var(--brand-50);
  color: var(--brand-700);
  font-size: 13px; font-weight: 500;
  cursor: pointer;
  transition: all var(--dur-1) var(--ease);
}
.sd-act:hover { background: var(--brand-100); border-color: var(--brand-400); }
.sd-act:disabled { opacity: .6; cursor: default; }

.sd-hint { margin: 8px 0 0; font-size: 11.5px; line-height: 1.6; color: var(--ink-400); }

.sd-links { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; }
.sd-links button {
  padding: 9px 10px;
  border: 1px solid var(--line-200);
  border-radius: var(--r-sm);
  background: var(--surface);
  font-size: 12.5px; color: var(--ink-700);
  text-align: left;
  cursor: pointer;
  transition: all var(--dur-1) var(--ease);
}
.sd-links button:hover { border-color: var(--brand-300); background: var(--brand-50); color: var(--brand-700); }

@media (max-width: 480px) {
  .sd { width: 100%; border-radius: 0; }
}

/* ============================================================================
   17. 车辆图标：卡车剪影 + 四态配色（2026-11-10）
   ----------------------------------------------------------------------------
   原来 `.pin` 是 22px 的圆形水滴块，低缩放还会被聚合圆点吞掉，客户原话
   "车辆的图标应该不要用原点"。这里换成侧视卡车剪影，方向、车型一眼可辨。
   四态色：待装货 橙 / 在途 浅绿 / 等待卸货 深绿 / 定位过期 灰。
   SVG 里必须用 fill="currentColor"，颜色由容器 color 传下去——
   SVG 的 fill 属性不支持 var()，写成 style="fill:变量" 才生效。
   ========================================================================== */

.vmark {
  position: relative;
  display: flex; align-items: center; justify-content: center;
  width: 32px; height: 32px;
}
.vmark .truck {
  width: 30px; height: 20px;
  color: var(--brand-400);                 /* 默认 = 在途（浅绿） */
  filter: drop-shadow(0 2px 3px rgba(23, 35, 61, .22));
  transition: transform var(--dur-1) var(--ease), color var(--dur-1) var(--ease);
  transform-origin: 50% 80%;
}
.vmark .truck svg { width: 100%; height: 100%; display: block; }

/* 四态：只改颜色，不改形状（形状一致才好一眼扫读） */
.vmark .truck.vs-pending        { color: var(--sem-warn); }
.vmark .truck.vs-in_transit     { color: var(--brand-400); }
.vmark .truck.vs-waiting_unload { color: var(--brand-700); }
.vmark .truck.vs-unlocated      { color: var(--ink-300); }
/* 定位过期：压暗 + 虚线外框，仍是同色系，不与"无定位"混淆 */
.vmark.is-stale .truck { opacity: .55; }
.vmark.is-stale::after {
  content: ''; position: absolute; inset: 2px;
  border: 1px dashed var(--ink-300); border-radius: 50%;
  pointer-events: none;
}

/* 选中态：放大 + 光圈 + 抬到最上层（否则被旁边车压住，看不出点了哪台） */
.vmark.is-on .truck { transform: scale(1.32); }
.vmark.is-on::before {
  content: ''; position: absolute; inset: -5px;
  border-radius: 50%;
  background: color-mix(in srgb, var(--brand-500) 16%, transparent);
  box-shadow: 0 0 0 2px color-mix(in srgb, var(--brand-500) 45%, transparent);
  animation: vmPulse 1.8s var(--ease) infinite;
  pointer-events: none;
}
@keyframes vmPulse {
  0%, 100% { transform: scale(1); opacity: .85; }
  50%      { transform: scale(1.12); opacity: .45; }
}

.vmark .flag {
  position: absolute; top: 0; right: 1px;
  width: 9px; height: 9px; border-radius: 50%;
  background: var(--sem-danger); border: 1.5px solid #fff;
  box-shadow: 0 0 0 2px color-mix(in srgb, var(--sem-danger) 18%, transparent);
}
.vmark .plate {
  position: absolute; top: 25px; left: 50%; transform: translateX(-50%);
  font-size: 10px; line-height: 15px;
  background: rgba(255, 255, 255, .95);
  padding: 0 4px; border-radius: var(--r-xs);
  white-space: nowrap; color: var(--ink-700);
  box-shadow: 0 1px 4px rgba(23, 35, 61, .14);
  font-variant-numeric: tabular-nums;
}
.vmark.is-on .plate {
  color: #fff; background: var(--brand-600); font-weight: 600;
  box-shadow: 0 2px 8px color-mix(in srgb, var(--brand-600) 40%, transparent);
}

/* 选中车辆的联动卡片（地图上点图标弹出） */
.vm-pop {
  position: absolute; z-index: 800; width: 268px;
  background: var(--surface-glass2);
  -webkit-backdrop-filter: var(--glass-blur-lg); backdrop-filter: var(--glass-blur-lg);
  border: var(--glass-brd); border-radius: var(--r-md);
  box-shadow: var(--sh-3);
  padding: 11px 13px 12px;
  animation: cfSlideUp var(--dur-2) var(--ease);
}
.vm-pop h5 {
  margin: 0 0 6px; font-size: 13.5px; font-weight: 650; color: var(--ink-900);
  display: flex; align-items: center; gap: 7px;
}
.vm-pop h5 .st {
  font-size: 11px; font-weight: 600; padding: 1px 7px; border-radius: var(--r-pill);
  background: var(--brand-50); color: var(--brand-700); border: 1px solid var(--brand-200);
}
.vm-pop h5 .st.warn { background: color-mix(in srgb, var(--sem-warn) 12%, #fff); color: var(--sem-warn-text); border-color: color-mix(in srgb, var(--sem-warn) 34%, #fff); }
.vm-pop h5 .st.deep { background: color-mix(in srgb, var(--brand-700) 12%, #fff); color: var(--brand-700); border-color: var(--brand-300); }
.vm-pop .row { display: flex; justify-content: space-between; gap: 10px; font-size: 12px; padding: 2px 0; }
.vm-pop .row span { color: var(--ink-400); }
.vm-pop .row b { color: var(--ink-700); font-weight: 500; text-align: right; }
.vm-pop .acts { display: flex; gap: 7px; margin-top: 9px; }
.vm-pop .acts button {
  flex: 1; height: 30px; border-radius: var(--r-sm); cursor: pointer;
  font-size: 12.5px; font-weight: 500;
  border: 1px solid var(--brand-300); background: var(--brand-50); color: var(--brand-700);
  transition: all var(--dur-1) var(--ease);
}
.vm-pop .acts button.ghost { border-color: var(--line-200); background: var(--surface); color: var(--ink-500); }
.vm-pop .acts button:hover { background: var(--brand-100); border-color: var(--brand-400); }
.vm-pop .acts button.ghost:hover { background: var(--surface-soft); color: var(--ink-700); }
.vm-pop .x {
  position: absolute; top: 7px; right: 8px; width: 20px; height: 20px;
  border: 0; background: none; color: var(--ink-300); cursor: pointer; font-size: 15px;
  line-height: 1;
}
.vm-pop .x:hover { color: var(--ink-700); }

/* ============================================================================
   18. 面板折叠：左树 / 右侧详情 / 底部表 三处统一
   ----------------------------------------------------------------------------
   原来只有左树有按钮，且是筛选区里一行 12px 的纯文字"收起"，被勾选框挤住，
   客户原话"侧边栏哪里有收起按钮呀？找不到"。三处统一成图标按钮 + 收起后留竖条。
   ========================================================================== */

/* 通用折叠钮：栏头右上角一个图标，36×24 点击区（不是 12px 文字） */
.pane-btn {
  flex: 0 0 auto;
  width: 24px; height: 24px;
  display: inline-flex; align-items: center; justify-content: center;
  border: 1px solid var(--line-200); border-radius: var(--r-xs);
  background: var(--surface); color: var(--ink-400);
  cursor: pointer; transition: all var(--dur-1) var(--ease);
}
.pane-btn:hover { color: var(--brand-600); border-color: var(--brand-300); background: var(--brand-50); }
.pane-btn svg { width: 12px; height: 12px; }
.pane-btn.on { color: var(--brand-700); border-color: var(--brand-300); background: var(--brand-50); }

/* 左树收起后：留一条 34px 竖条，竖条上有一个"展开"钮，永远点得到 */
body.tree-collapsed .tree-reopen,
body:not(.tree-collapsed) .tree-reopen { display: none; }
body.tree-collapsed .tree-reopen {
  display: flex; flex-direction: column; align-items: center; gap: 8px;
  padding-top: 8px;
}
.tree-reopen .pane-btn { writing-mode: vertical-rl; width: 24px; height: 40px; }

/* 右侧详情收起后同样留竖条（原来 panel-collapsed 会把入口一起藏掉，回不来） */
body.panel-collapsed .panel-reopen { display: flex; }
.panel-reopen {
  display: none; flex-direction: column; align-items: center; padding-top: 8px;
}
.panel-reopen .pane-btn { writing-mode: vertical-rl; width: 24px; height: 40px; }

/* 底部车辆表：加折叠（原来只有 CSS 写了 .bottom.collapsed，没有入口） */
.bottom.is-collapsed .dt-body { display: none; }
.bottom.is-collapsed .dt-head { border-bottom: 0; }
.dt-fold {
  margin-left: auto;
  display: inline-flex; align-items: center; gap: 4px;
  font-size: 11.5px; color: var(--ink-400); cursor: pointer;
  border: 0; background: none; padding: 2px 4px;
}
.dt-fold:hover { color: var(--brand-600); }
.dt-fold svg { width: 11px; height: 11px; transition: transform var(--dur-1) var(--ease); }
.bottom.is-collapsed .dt-fold svg { transform: rotate(180deg); }

/* ============================================================================
   19. 地图起终点气泡 + 线路红色细虚线
   ----------------------------------------------------------------------------
   客户要"庄一矿 → 卸灵台"这种一眼看得懂的标注，而不是只有车牌。
   线路用红色细虚线（1.5px、dash 6/6），与实线的实际轨迹区分开。
   ========================================================================== */
.anchor-pin {
  display: inline-flex; align-items: center; gap: 5px;
  padding: 3px 8px 3px 4px;
  background: var(--surface-glass2);
  -webkit-backdrop-filter: var(--glass-blur-sm); backdrop-filter: var(--glass-blur-sm);
  border: 1px solid var(--line-200); border-radius: var(--r-pill);
  box-shadow: var(--sh-2); white-space: nowrap;
  font-size: 11.5px; font-weight: 600; color: var(--ink-700);
  transform: translate(-50%, -50%);
}
.anchor-pin .dot {
  width: 16px; height: 16px; flex: 0 0 16px; border-radius: 50%;
  display: inline-flex; align-items: center; justify-content: center;
  color: #fff; font-size: 9px; font-weight: 700;
}
.anchor-pin.start .dot { background: var(--sem-info); }
.anchor-pin.end .dot   { background: var(--brand-600); }
.anchor-pin .sub { font-size: 10px; font-weight: 400; color: var(--ink-400); }

.leaflet-overlay-pane path.route-line {
  stroke: var(--sem-danger); stroke-width: 1.5;
  stroke-dasharray: 6 6; fill: none;
  stroke-linecap: round;
}

/* ============================================================================
   20. 三处折叠钮的最终尺寸修正
   ----------------------------------------------------------------------------
   styles.css 里 .tree-reopen 是「26px 高的文字按钮」、.panel-reopen 是「固定定位的
   文字按钮」，都跟新换的图标钮（.pane-btn）尺寸冲突。这里统一成竖条：
   宽 26、高 44，内部只放一个 24×40 的图标钮，点起来够大，视觉上也不抢戏。
   ========================================================================== */
body.console.b-shell .tree-reopen,
body.console.b-shell .panel-reopen {
  width: 26px; height: 44px;
  padding: 0; border-radius: var(--r-sm);
  align-items: center; justify-content: center;
  background: var(--surface); border: 1px solid var(--line-200);
  box-shadow: var(--sh-1);
}
body.console.b-shell .tree-reopen:hover,
body.console.b-shell .panel-reopen:hover { border-color: var(--brand-300); background: var(--brand-50); }
body.console.b-shell .tree-reopen .pane-btn,
body.console.b-shell .panel-reopen .pane-btn {
  width: 24px; height: 40px; border: 0; background: none;
}
body.console.b-shell .tree-reopen .pane-btn:hover,
body.console.b-shell .panel-reopen .pane-btn:hover { background: none; }
body.console.b-shell .panel-reopen { padding: 0; }
body.console.b-shell.panel-collapsed .panel-reopen { display: flex; }

/* 右面板收起钮压在异常工具条上方，给工具条右侧留出让位 */
body.console.b-shell .panel .anomaly-toolbar { padding-right: 36px; }

/* 底部表折叠钮：与页签同一行右侧 */
body.console.b-shell .bottom .dt-fold { margin-left: 10px; }

/* 左树线路行的「N 单」角标：提示这条线在平台上挂了多张单 */
.lane-multi {
  flex: 0 0 auto; margin-left: 4px;
  font-size: 10.5px; font-weight: 600; padding: 0 5px; line-height: 15px;
  border-radius: var(--r-xs);
  background: color-mix(in srgb, var(--sem-info) 10%, #fff);
  color: var(--sem-info-text);
  border: 1px solid color-mix(in srgb, var(--sem-info) 26%, #fff);
}
