/* ============================================================
   佰壹新能源云平台 2.0 · 设计系统
   令牌抽取自原系统并做现代化重构
   ============================================================ */
/* ===== 设计令牌：主题由三个正交维度组成 =====
   ① [data-theme]   明暗：light / dark
                    —— 只改中性色（文字、底色、描边）与阴影
   ② [data-skin]    品牌色系：jade / ocean / violet / amber / teal / graphite
                    —— 只改品牌色、辅助色、侧边栏与登录页品牌区；
                       语义色（成功 / 警告 / 危险）刻意**不跟随**，否则「危险」会变成紫色
   ③ [data-density] 密度：normal / compact / loose
                    —— 只改内边距类令牌，不动字号，避免文字换行错位
   三个维度互不覆盖，2 × 6 × 3 = 36 套组合；新增一个色系只需加一个 [data-skin] 块。
   淡底色（--brand-1 等）与侧边栏的深浅层次不从 :root 写死，而在文件末尾用 color-mix
   从主色 + --surface / --side-hue 派生 —— 一处规则同时适配明暗与全部色系；
   此处保留字面量仅作不支持 color-mix 时的兜底。 */
:root{
  /* ---- 品牌色系：默认 jade（松绿），被 [data-skin] 覆盖 ---- */
  --brand:#2f9e6e; --brand-6:#268459;
  --info:#3d7eff; --purple:#7c5cff;
  /* ---- 侧边栏与登录页品牌区：色系由 --side-hue 与 --lh* 两个入口表达 ---- */
  --side-hue:#08355c;
  --side-bg:#08355c; --side-bg-2:#062a4a; --side-on:#0b4a7d;
  --side-ink:#c3d6e8; --side-ink-2:#7fa3c4;
  /* 侧边栏强调色（激活项左侧竖条、子项选中文字、计数徽标）：
     深底上需要比 --brand 更亮才醒目，所以单独一个入口 */
  --side-accent:#3ec98a;
  /* 品牌色外发光（徽标阴影），随色系深浅自动调整 */
  --brand-glow:rgba(47,158,110,.34);
  --lh1:#062a4a; --lh2:#0a4a78; --lh3:#0d5f8f;
  --lg1:rgba(58,164,116,.42); --lg2:rgba(61,126,255,.3);

  /* ---- 语义色：状态含义固定，绝不随品牌色系变化 ---- */
  --warn:#e8892b; --danger:#e5484d; --ok:#12a150;

  /* ---- 中性色：浅色底 ---- */
  --ink:#161a1f; --ink-2:#3f4753; --ink-3:#6b7480; --ink-4:#9aa2ae;
  --bg:#f4f6f8; --surface:#fff; --surface-2:#fafbfc;
  --line:#e6e9ee; --line-2:#eef1f5;

  /* ---- 淡底色：兜底字面量（现代浏览器走文件末尾的 color-mix 派生版） ---- */
  --brand-1:#eaf7f1; --brand-2:#d3edde;
  --info-1:#eaf1ff; --purple-1:#f0ecff;
  --warn-1:#fdf3e7; --danger-1:#fdeded; --ok-1:#e9f8ef;

  /* ---- 圆角 / 阴影 / 字体 ---- */
  --r:8px; --r-lg:12px; --r-sm:6px;
  --sh-1:0 1px 2px rgba(16,24,40,.05);
  --sh-2:0 3px 10px rgba(16,24,40,.07);
  --sh-3:0 12px 32px rgba(16,24,40,.13);
  --font:"Microsoft YaHei","微软雅黑",-apple-system,"Segoe UI",Arial,sans-serif;
  --mono:"JetBrains Mono",Consolas,"Courier New",monospace;

  /* ---- 密度令牌（normal）：表格与容器的内边距一律从这里取 ---- */
  --row-pad-y:10.5px; --th-pad-y:10px; --cell-pad-x:13px;
  --page-pad:19px; --card-pad-y:15px; --card-pad-x:17px;
  --hd-pad-y:13px; --hd-pad-x:17px; --bar-pad-y:13px; --gap:13px;
  --ctl-h:33px; --ctl-h-sm:27px;
}
/* ===== 明暗维度：只覆盖中性色、阴影与侧边栏的压暗程度 =====
   品牌色与语义色不在这里出现，所以 6 个色系共用这一套明暗规则。 */
[data-theme=dark]{
  --ink:#e8ecf1; --ink-2:#b8c1cd; --ink-3:#8b95a3; --ink-4:#69737f;
  --bg:#0e1216; --surface:#161b21; --surface-2:#1b2128;
  --line:#252c34; --line-2:#1f262d;
  --side-bg:#0b141c; --side-bg-2:#080f15; --side-on:#132c42;
  --side-ink:#a8bccf; --side-ink-2:#68839b;
  --lh1:#0b141c; --lh2:#0f2b3d; --lh3:#123a52;
  --brand-1:#12291f; --brand-2:#17392a;
  --info-1:#131f36; --purple-1:#1d1936; --warn-1:#2e2113; --danger-1:#2e1617; --ok-1:#122a1c;
  --sh-1:0 1px 2px rgba(0,0,0,.4);
  --sh-2:0 3px 10px rgba(0,0,0,.45);
  --sh-3:0 12px 32px rgba(0,0,0,.5);
}
/* ===== 色系维度：每块只列主色、侧边栏基色与登录页渐变 =====
   加深色系照抄一块即可，不必动明暗与密度；纯色值写法便于直接微调。
   --brand     品牌主色（按钮、激活态、图表主序列）
   --brand-6   主色的深一档（hover）
   --info/--purple  辅助序列色，跟随色系以免图表配色打架
   --side-hue  侧边栏基色，其余侧边栏层次由末尾 color-mix 派生
   --lh1/2/3   登录页品牌区渐变的三档
   --lg1/--lg2 登录页品牌区的两团光晕 */
[data-skin=jade]{
  --brand:#2f9e6e; --brand-6:#268459;
  --info:#3d7eff; --purple:#7c5cff;
  --side-hue:#08355c; --lh1:#062a4a; --lh2:#0a4a78; --lh3:#0d5f8f;
  --lg1:rgba(58,164,116,.42); --lg2:rgba(61,126,255,.3);
}
[data-skin=ocean]{
  --brand:#2c6fd6; --brand-6:#2258ad;
  --info:#0ea5e9; --purple:#6366f1;
  --side-hue:#0a2a52; --lh1:#08213f; --lh2:#0c3a6b; --lh3:#11508f;
  --lg1:rgba(44,111,214,.44); --lg2:rgba(14,165,233,.3);
}
[data-skin=violet]{
  --brand:#7c5cff; --brand-6:#6344e0;
  --info:#3d7eff; --purple:#c026d3;
  --side-hue:#241a4d; --lh1:#1d1440; --lh2:#2e2166; --lh3:#402d8c;
  --lg1:rgba(124,92,255,.44); --lg2:rgba(192,38,211,.28);
}
[data-skin=amber]{
  --brand:#d9760f; --brand-6:#b25f08;
  --info:#3d7eff; --purple:#a855f7;
  --side-hue:#40260c; --lh1:#331e09; --lh2:#5c3611; --lh3:#7d4a17;
  --lg1:rgba(217,118,15,.42); --lg2:rgba(214,90,48,.28);
}
[data-skin=teal]{
  --brand:#0f9494; --brand-6:#0b7676;
  --info:#0ea5e9; --purple:#6366f1;
  --side-hue:#07383a; --lh1:#062c2e; --lh2:#0a4a4d; --lh3:#0d6165;
  --lg1:rgba(15,148,148,.44); --lg2:rgba(14,165,233,.28);
}
[data-skin=graphite]{
  --brand:#5f6b7a; --brand-6:#4b5563;
  --info:#3d7eff; --purple:#7c5cff;
  --side-hue:#1f242b; --lh1:#181c21; --lh2:#262c34; --lh3:#333b45;
  --lg1:rgba(95,107,122,.4); --lg2:rgba(61,126,255,.22);
}
/* ===== 密度维度：只调整内边距令牌 =====
   compact 用于一屏看更多行（数据巡查），loose 用于演示投屏。 */
[data-density=compact]{
  --row-pad-y:6px; --th-pad-y:6px; --cell-pad-x:10px;
  --page-pad:12px; --card-pad-y:10px; --card-pad-x:12px;
  --hd-pad-y:9px; --hd-pad-x:12px; --bar-pad-y:9px; --gap:9px;
  --ctl-h:29px; --ctl-h-sm:24px;
}
[data-density=loose]{
  --row-pad-y:14px; --th-pad-y:13px; --cell-pad-x:16px;
  --page-pad:24px; --card-pad-y:20px; --card-pad-x:22px;
  --hd-pad-y:17px; --hd-pad-x:22px; --bar-pad-y:17px; --gap:17px;
  --ctl-h:38px; --ctl-h-sm:31px;
}
*{box-sizing:border-box;margin:0;padding:0}
html,body{height:100%}
body{font-family:var(--font);font-size:13px;color:var(--ink);background:var(--bg);
  -webkit-font-smoothing:antialiased;line-height:1.5}
a{color:inherit;text-decoration:none}
button,input,select,textarea{font-family:inherit;font-size:inherit;color:inherit}
::-webkit-scrollbar{width:9px;height:9px}
::-webkit-scrollbar-thumb{background:#c6ccd4;border-radius:5px;border:2px solid transparent;background-clip:padding-box}
[data-theme=dark] ::-webkit-scrollbar-thumb{background:#39424d;background-clip:padding-box}
::-webkit-scrollbar-thumb:hover{background:#a8b0ba;background-clip:padding-box}
::-webkit-scrollbar-track{background:transparent}

/* ---------------- 登录页 ---------------- */
#login{position:fixed;inset:0;display:flex;background:var(--bg);z-index:100}
#login .lf{flex:1.15;background:linear-gradient(135deg,var(--lh1),var(--lh2) 55%,var(--lh3));
  position:relative;overflow:hidden;display:flex;flex-direction:column;justify-content:center;padding:0 84px;color:#fff}
#login .lf:before{content:"";position:absolute;width:620px;height:620px;border-radius:50%;
  background:radial-gradient(circle,var(--lg1),transparent 68%);top:-190px;right:-170px}
#login .lf:after{content:"";position:absolute;width:460px;height:460px;border-radius:50%;
  background:radial-gradient(circle,var(--lg2),transparent 68%);bottom:-180px;left:-120px}
#login .lf .inner{position:relative;z-index:2;max-width:520px}
#login h1{font-size:34px;font-weight:750;letter-spacing:-.5px;margin-bottom:14px}
#login .sub{font-size:15px;color:#b9d4ea;line-height:1.85;margin-bottom:38px}
#login .pts{display:flex;flex-direction:column;gap:15px}
#login .pt{display:flex;gap:11px;align-items:center;font-size:13.5px;color:#d3e6f5}
#login .pt i{width:22px;height:22px;border-radius:50%;background:rgba(255,255,255,.16);
  display:grid;place-items:center;flex:none;font-style:normal;font-size:11px}
#login .rt{flex:.85;display:flex;align-items:center;justify-content:center;padding:40px}
#login .card{width:100%;max-width:352px}
#login .logo{display:flex;align-items:center;gap:11px;margin-bottom:30px}
#login .logo .mk{width:36px;height:36px;border-radius:9px;background:linear-gradient(135deg,var(--brand),var(--brand-6));
  display:grid;place-items:center;box-shadow:0 5px 14px var(--brand-glow)}
#login .logo b{font-size:17px;font-weight:700;display:block;letter-spacing:.2px}
#login .logo span{font-size:11.5px;color:var(--ink-4);letter-spacing:1.4px}
#login h2{font-size:20px;font-weight:700;margin-bottom:5px}
#login .tip{font-size:12.5px;color:var(--ink-4);margin-bottom:26px}
#login .fg{margin-bottom:15px}
#login label{display:block;font-size:12.5px;color:var(--ink-2);margin-bottom:6px;font-weight:500}
#login input{width:100%;height:41px;border:1px solid var(--line);border-radius:var(--r);
  padding:0 13px;background:var(--surface);outline:none;transition:.15s}
#login input:focus{border-color:var(--brand);box-shadow:0 0 0 3px var(--brand-1)}
#login .row2{display:flex;gap:9px}
#login .row2 input{flex:1}
#login .captcha{width:104px;height:41px;border-radius:var(--r);border:1px solid var(--line);
  background:var(--surface-2);display:flex;align-items:center;justify-content:center;cursor:pointer;
  font-family:var(--mono);font-size:19px;font-weight:700;letter-spacing:3px;color:var(--brand);
  user-select:none;flex:none;
  background-image:repeating-linear-gradient(45deg,transparent,transparent 3px,var(--brand-1) 3px,var(--brand-1) 6px)}
#login .btn-login{width:100%;height:43px;border:none;border-radius:var(--r);background:var(--brand);
  color:#fff;font-size:14px;font-weight:600;cursor:pointer;margin-top:9px;transition:.15s;
  box-shadow:0 3px 12px var(--brand-glow)}
#login .btn-login:hover{background:var(--brand-6)}
#login .btn-login:active{transform:translateY(1px)}
#login .err{color:var(--danger);font-size:12.5px;min-height:18px;margin-top:9px}
#login .quick{margin-top:24px;padding-top:19px;border-top:1px dashed var(--line)}
#login .quick p{font-size:12px;color:var(--ink-4);margin-bottom:10px}
#login .quick .btns{display:flex;gap:8px}
#login .quick button{flex:1;height:33px;border:1px solid var(--line);background:var(--surface);
  border-radius:var(--r-sm);font-size:12.5px;cursor:pointer;color:var(--ink-2);transition:.15s}
#login .quick button:hover{border-color:var(--brand);color:var(--brand);background:var(--brand-1)}

/* ---------------- 布局 ---------------- */
#app{display:none;height:100%}
#app.on{display:flex}
.side{width:212px;background:var(--side-bg);display:flex;flex-direction:column;flex:none;
  transition:width .2s;overflow:hidden}
.side.shut{width:0}
.side .brand{display:flex;align-items:center;gap:9px;padding:15px 17px 15px 19px;flex:none}
.side .brand .mk{width:29px;height:29px;border-radius:8px;background:linear-gradient(135deg,var(--brand),var(--brand-6));
  display:grid;place-items:center;flex:none}
.side .brand b{color:#fff;font-size:14.5px;font-weight:700;display:block;line-height:1.2}
.side .brand span{color:var(--side-ink-2);font-size:9.5px;letter-spacing:1.3px}
.side nav{flex:1;overflow-y:auto;padding:6px 0 18px}
.side nav::-webkit-scrollbar{width:0}
.ngrp{margin-bottom:1px}
.ni{display:flex;align-items:center;gap:10px;padding:9.5px 17px 9.5px 19px;color:var(--side-ink);
  font-size:13px;cursor:pointer;transition:.14s;position:relative;white-space:nowrap}
.ni:hover{background:rgba(255,255,255,.055);color:#fff}
.ni.on{background:var(--side-on);color:#fff;font-weight:600}
.ni.on:before{content:"";position:absolute;left:0;top:0;bottom:0;width:3px;background:var(--side-accent)}
.ni svg{flex:none;opacity:.92}
.ni .arw{margin-left:auto;transition:transform .2s;opacity:.55}
.ni.open .arw{transform:rotate(90deg)}
.nsub{max-height:0;overflow:hidden;transition:max-height .22s ease}
.nsub.open{max-height:420px}
.ns{display:flex;align-items:center;padding:7.5px 17px 7.5px 47px;color:var(--side-ink-2);
  font-size:12.5px;cursor:pointer;transition:.14s;white-space:nowrap}
.ns:hover{color:#fff;background:rgba(255,255,255,.04)}
.ns.on{color:var(--side-accent);font-weight:600}
.ns .tag{margin-left:auto;font-size:9.5px;padding:1.5px 5px;border-radius:8px;
  background:rgba(229,72,77,.85);color:#fff;font-weight:600;min-width:17px;text-align:center}
.ns .tag.g{background:var(--side-accent)}
.side .foot{padding:11px 17px;border-top:1px solid rgba(255,255,255,.07);flex:none}
.side .foot .u{display:flex;align-items:center;gap:9px}
.side .foot .av{width:29px;height:29px;border-radius:50%;background:linear-gradient(135deg,var(--side-accent),var(--brand));
  display:grid;place-items:center;color:#fff;font-size:12px;font-weight:700;flex:none}
.side .foot b{color:#fff;font-size:12.5px;display:block;line-height:1.3}
.side .foot span{color:var(--side-ink-2);font-size:10.5px}
/* 必须显式写 background:none —— 全局重置里只归了字体与颜色，
   不写的话 <button> 会带出 UA 默认的浅灰底，在深色侧边栏上非常突兀。 */
.side .foot .out{margin-left:auto;color:var(--side-ink-2);cursor:pointer;padding:4px;border-radius:5px;
  background:none;border:none;font-size:12px}
.side .foot .out:hover{color:#ff8b8f;background:rgba(255,255,255,.07)}

.main{flex:1;display:flex;flex-direction:column;min-width:0}
/* .top 需要 position:relative —— 主题面板 #themePop 是它的绝对定位子元素 */
.top{height:53px;background:var(--surface);border-bottom:1px solid var(--line);position:relative;
  display:flex;align-items:center;gap:13px;padding:0 19px;flex:none}
#burger{background:none;border:none;cursor:pointer;color:var(--ink-3);padding:5px;border-radius:6px;
  display:grid;place-items:center}
#burger:hover{background:var(--bg);color:var(--ink)}
.crumb{display:flex;align-items:center;gap:7px;font-size:13.5px;color:var(--ink-3)}
.crumb b{color:var(--ink);font-weight:600}
.crumb .sep{color:var(--ink-4)}
.top .sp{flex:1}
.role{display:flex;background:var(--bg);border-radius:7px;padding:2.5px;gap:1px}
.role button{border:none;background:none;padding:5.5px 13px;border-radius:5.5px;font-size:12.5px;
  color:var(--ink-3);cursor:pointer;transition:.14s;font-weight:500}
.role button.on{background:var(--surface);color:var(--brand);font-weight:600;box-shadow:var(--sh-1)}
.ibtn{width:33px;height:33px;border-radius:8px;border:none;background:none;cursor:pointer;
  color:var(--ink-3);display:grid;place-items:center;position:relative;transition:.14s}
.ibtn:hover{background:var(--bg);color:var(--ink)}
.ibtn .dot{position:absolute;top:6px;right:6px;width:6.5px;height:6.5px;border-radius:50%;
  background:var(--danger);border:1.5px solid var(--surface)}
.tuser{display:flex;align-items:center;gap:8px;padding-left:13px;border-left:1px solid var(--line)}
.tuser .av{width:29px;height:29px;border-radius:50%;background:linear-gradient(135deg,var(--brand),var(--brand-6));
  display:grid;place-items:center;color:#fff;font-size:11.5px;font-weight:700}
.tuser b{font-size:12.5px;display:block;line-height:1.25}
.tuser span{font-size:10.5px;color:var(--ink-4)}

#pages{flex:1;overflow-y:auto;padding:var(--page-pad)}
.page{display:none}
.page.on{display:block;animation:fade .22s ease}
@keyframes fade{from{opacity:0;transform:translateY(5px)}to{opacity:1;transform:none}}

/* ---------------- 通用组件 ---------------- */
.ph{display:flex;align-items:flex-start;margin-bottom:17px;gap:14px}
.ph h2{font-size:20px;font-weight:700;letter-spacing:-.2px;margin-bottom:3px}
.ph p{font-size:12.5px;color:var(--ink-4)}
.ph .sp{flex:1}
.acts{display:flex;gap:8px;align-items:center;flex-wrap:wrap}

.btn{height:var(--ctl-h);padding:0 14px;border-radius:var(--r-sm);border:1px solid var(--line);
  background:var(--surface);color:var(--ink-2);font-size:12.5px;cursor:pointer;transition:.14s;
  display:inline-flex;align-items:center;gap:6px;white-space:nowrap;font-weight:500}
.btn:hover{border-color:var(--ink-4);color:var(--ink)}
.btn.pri{background:var(--brand);border-color:var(--brand);color:#fff;box-shadow:0 1px 3px var(--brand-glow)}
.btn.pri:hover{background:var(--brand-6);border-color:var(--brand-6)}
.btn.dan{color:var(--danger);border-color:#f3c9ca}
.btn.dan:hover{background:var(--danger-1);border-color:var(--danger)}
.btn.sm{height:var(--ctl-h-sm);padding:0 10px;font-size:12px}
.btn:disabled{opacity:.5;cursor:not-allowed}

/* 汇总条：表格上方的口径提示（与 evcs-ops 保持同名同款，便于两套系统互相对照） */
.sum{display:flex;gap:9px;flex-wrap:wrap;padding:10px 17px;
  border-bottom:1px solid var(--line-2);background:var(--surface-2)}
.chip{display:inline-flex;align-items:center;gap:5px;padding:3px 10px;border-radius:20px;
  background:var(--surface);border:1px solid var(--line);font-size:12px;color:var(--ink-3);
  white-space:nowrap;line-height:1.6}
.chip b{color:var(--ink);font-weight:650;font-variant-numeric:tabular-nums}

.card{background:var(--surface);border:1px solid var(--line);border-radius:var(--r-lg);
  box-shadow:var(--sh-1)}
.card+.card{margin-top:var(--gap)}
.card .chd{display:flex;align-items:center;gap:10px;padding:var(--hd-pad-y) var(--hd-pad-x);
  border-bottom:1px solid var(--line-2)}
.card .chd h3{font-size:13.5px;font-weight:650;flex:1}
.card .chd .sub{font-size:11.5px;color:var(--ink-4);font-weight:400}
.card .cbd{padding:var(--card-pad-y) var(--card-pad-x)}
.card .cbd.nop{padding:0}

/* KPI */
.kpis{display:grid;grid-template-columns:repeat(auto-fit,minmax(178px,1fr));gap:var(--gap);
  margin-bottom:var(--gap)}
.kpi{background:var(--surface);border:1px solid var(--line);border-radius:var(--r-lg);
  padding:var(--card-pad-y) var(--card-pad-x);
  box-shadow:var(--sh-1);position:relative;overflow:hidden}
.kpi .t{font-size:12.5px;color:var(--ink-3);display:flex;align-items:center;gap:6px;margin-bottom:9px}
.kpi .v{font-size:25px;font-weight:750;letter-spacing:-.7px;font-variant-numeric:tabular-nums;line-height:1.15}
.kpi .v small{font-size:13px;font-weight:600;color:var(--ink-4);margin-left:2px;letter-spacing:0}
.kpi .d{font-size:11.5px;color:var(--ink-4);margin-top:6px;display:flex;align-items:center;gap:5px}
.kpi .d .up{color:var(--danger);font-weight:600}
.kpi .d .dn{color:var(--ok);font-weight:600}
.kpi .glow{position:absolute;right:-26px;top:-26px;width:82px;height:82px;border-radius:50%;
  background:radial-gradient(circle,var(--brand-1),transparent 70%)}

.tabs{display:flex;gap:2px;border-bottom:1px solid var(--line);padding:0 17px}
.tab{padding:11px 15px;font-size:13px;color:var(--ink-3);cursor:pointer;border-bottom:2px solid transparent;
  transition:.14s;font-weight:500;background:none;border-top:none;border-left:none;border-right:none}
.tab:hover{color:var(--ink)}
.tab.on{color:var(--brand);border-bottom-color:var(--brand);font-weight:600}
.tab .n{font-size:11px;color:var(--ink-4);margin-left:3px}

/* 查询栏 */
.bar{display:flex;flex-wrap:wrap;gap:9px;align-items:center;padding:var(--bar-pad-y) var(--hd-pad-x);
  border-bottom:1px solid var(--line-2)}
.bar .f{display:flex;align-items:center;gap:6px}
.bar label{font-size:12.5px;color:var(--ink-3);white-space:nowrap}
.bar input,.bar select{height:31px;border:1px solid var(--line);border-radius:var(--r-sm);
  padding:0 10px;background:var(--surface);outline:none;transition:.14s;font-size:12.5px;min-width:0}
.bar input:focus,.bar select:focus{border-color:var(--brand);box-shadow:0 0 0 3px var(--brand-1)}
.bar input[type=text]{width:158px}
.bar input[type=date]{width:135px}
.bar .sp{flex:1}

/* 表格 */
.tw{overflow-x:auto}
table{width:100%;border-collapse:collapse;font-size:12.5px}
thead th{background:var(--surface-2);color:var(--ink-3);font-weight:600;text-align:left;
  padding:var(--th-pad-y) var(--cell-pad-x);white-space:nowrap;border-bottom:1px solid var(--line);
  font-size:12px;position:sticky;top:0;z-index:2}
tbody td{padding:var(--row-pad-y) var(--cell-pad-x);border-bottom:1px solid var(--line-2);
  white-space:nowrap;color:var(--ink-2);vertical-align:middle}
tbody tr{transition:background .12s}
tbody tr:hover{background:var(--surface-2)}
tbody tr:last-child td{border-bottom:none}
tbody tr.clickable{cursor:pointer}
td.num{text-align:right;font-variant-numeric:tabular-nums;font-weight:500}
td.mono{font-family:var(--mono);font-size:11.5px}
td.mut{color:var(--ink-4)}
.empty{padding:52px;text-align:center;color:var(--ink-4);font-size:13px}
.empty svg{opacity:.32;margin-bottom:11px}

/* 徽标 */
.bg{display:inline-flex;align-items:center;gap:4.5px;padding:2.5px 9px;border-radius:20px;
  font-size:11.5px;font-weight:600;white-space:nowrap;line-height:1.5}
.bg:before{content:"";width:5px;height:5px;border-radius:50%;background:currentColor;flex:none}
.bg.ok{background:var(--ok-1);color:var(--ok)}
.bg.warn{background:var(--warn-1);color:#c4741f}
.bg.dg{background:var(--danger-1);color:var(--danger)}
.bg.info{background:var(--info-1);color:var(--info)}
.bg.pu{background:var(--purple-1);color:var(--purple)}
.bg.mut{background:var(--bg);color:var(--ink-4)}
.bg.plain:before{display:none}

/* 图表容器 */
.chart{width:100%}
.h180{height:180px}
.h200{height:200px}
.h220{height:220px}
.h240{height:240px}
.h260{height:260px}
.legend{display:flex;flex-wrap:wrap;gap:13px;margin-top:11px;font-size:12px;color:var(--ink-2)}
.legend i{width:9px;height:9px;border-radius:3px;display:inline-block;margin-right:5px}

/* 抽屉 */
#mask{position:fixed;inset:0;background:rgba(12,18,24,.42);opacity:0;pointer-events:none;
  transition:.22s;z-index:80;backdrop-filter:blur(1.5px)}
#mask.on{opacity:1;pointer-events:auto}
#drawer{position:fixed;top:0;right:0;bottom:0;width:588px;max-width:94vw;background:var(--surface);
  box-shadow:var(--sh-3);transform:translateX(100%);transition:transform .25s cubic-bezier(.4,0,.2,1);
  z-index:81;display:flex;flex-direction:column}
#drawer.on{transform:none}
#drawer .dh{display:flex;align-items:center;padding:15px 19px;border-bottom:1px solid var(--line);flex:none}
#drawer .dh h3{font-size:15px;font-weight:700;flex:1}
#drawer .dh .x{background:none;border:none;cursor:pointer;color:var(--ink-4);padding:5px;border-radius:6px;
  display:grid;place-items:center}
#drawer .dh .x:hover{background:var(--bg);color:var(--ink)}
#drawer .db{flex:1;overflow-y:auto;padding:19px}
#drawer .df{padding:13px 19px;border-top:1px solid var(--line);display:flex;gap:9px;justify-content:flex-end;flex:none}

/* 描述列表 */
.dl{display:grid;grid-template-columns:96px 1fr;gap:9px 15px;font-size:12.5px}
.dl dt{color:var(--ink-4)}
.dl dd{color:var(--ink);font-weight:500;word-break:break-all}
.sect{font-size:12px;font-weight:700;color:var(--ink-4);letter-spacing:.6px;
  margin:19px 0 11px;text-transform:uppercase}
.sect:first-child{margin-top:0}

/* 表单 */
.frm{display:grid;grid-template-columns:repeat(2,1fr);gap:13px}
.frm .full{grid-column:1/-1}
.fg label{display:block;font-size:12.5px;color:var(--ink-2);margin-bottom:5px;font-weight:500}
.fg label .rq{color:var(--danger)}
.fg input,.fg select,.fg textarea{width:100%;height:35px;border:1px solid var(--line);
  border-radius:var(--r-sm);padding:0 11px;background:var(--surface);outline:none;transition:.14s}
.fg textarea{height:auto;padding:9px 11px;resize:vertical;min-height:70px;line-height:1.55}
.fg input:focus,.fg select:focus,.fg textarea:focus{border-color:var(--brand);box-shadow:0 0 0 3px var(--brand-1)}

/* 提示条 */
.alert{display:flex;gap:10px;padding:12px 15px;border-radius:var(--r);font-size:12.5px;
  margin-bottom:15px;align-items:flex-start;line-height:1.6}
.alert.warn{background:var(--warn-1);color:#a8620f;border:1px solid #f2ddbe}
.alert.dg{background:var(--danger-1);color:#b8383c;border:1px solid #f5cdce}
.alert.info{background:var(--info-1);color:#2b5fd0;border:1px solid #cfe0ff}
.alert b{font-weight:700}
.alert svg{flex:none;margin-top:2px}

/* 弹窗 */
#modal{position:fixed;inset:0;background:rgba(12,18,24,.45);display:none;place-items:center;z-index:95;
  backdrop-filter:blur(2px)}
#modal.on{display:grid}
#modal .box{background:var(--surface);border-radius:var(--r-lg);box-shadow:var(--sh-3);
  width:440px;max-width:92vw;max-height:88vh;display:flex;flex-direction:column}
#modal .mh{padding:16px 19px;border-bottom:1px solid var(--line);font-size:15px;font-weight:700}
#modal .mb{padding:19px;overflow-y:auto;font-size:13px;color:var(--ink-2);line-height:1.7}
#modal .mf{padding:13px 19px;border-top:1px solid var(--line);display:flex;gap:9px;justify-content:flex-end}

#toast{position:fixed;left:50%;bottom:34px;transform:translateX(-50%) translateY(14px);
  background:#161a1f;color:#fff;padding:11px 20px;border-radius:9px;font-size:13px;
  box-shadow:0 10px 30px rgba(0,0,0,.3);z-index:200;opacity:0;transition:.24s;pointer-events:none;
  display:flex;align-items:center;gap:8px;max-width:80vw}
#toast.on{opacity:1;transform:translateX(-50%)}
#toast.ok{background:#0f7a45}
#toast.err{background:#b8383c}
#toast.warn{background:#b8860b}

.loading{display:flex;align-items:center;justify-content:center;gap:9px;padding:44px;
  color:var(--ink-4);font-size:13px}
.spin{width:16px;height:16px;border:2px solid var(--line);border-top-color:var(--brand);
  border-radius:50%;animation:sp .7s linear infinite}
@keyframes sp{to{transform:rotate(360deg)}}

.pager{display:flex;align-items:center;gap:9px;padding:13px 17px;border-top:1px solid var(--line-2);
  font-size:12.5px;color:var(--ink-3)}
.pager .sp{flex:1}
.pager button{height:29px;min-width:29px;padding:0 9px;border:1px solid var(--line);background:var(--surface);
  border-radius:var(--r-sm);cursor:pointer;color:var(--ink-2);font-size:12.5px}
.pager button:hover:not(:disabled){border-color:var(--brand);color:var(--brand)}
.pager button.on{background:var(--brand);border-color:var(--brand);color:#fff;font-weight:600}
.pager button:disabled{opacity:.42;cursor:not-allowed}

.g2{display:grid;grid-template-columns:1fr 1fr;gap:15px}
.g3{display:grid;grid-template-columns:repeat(3,1fr);gap:15px}
.g21{display:grid;grid-template-columns:2fr 1fr;gap:15px}
.g12{display:grid;grid-template-columns:1fr 2fr;gap:15px}
@media(max-width:1180px){.g21,.g12,.g3{grid-template-columns:1fr}}

.mk-list{display:flex;flex-direction:column;gap:9px}
.mk-item{display:flex;align-items:center;gap:11px;padding:11px 13px;border:1px solid var(--line);
  border-radius:var(--r);transition:.14s;cursor:pointer}
.mk-item:hover{border-color:var(--brand);background:var(--brand-1)}
.mk-item .ic{width:31px;height:31px;border-radius:8px;display:grid;place-items:center;flex:none;font-size:14px}
.mk-item .tx{flex:1;min-width:0}
.mk-item .tx b{font-size:13px;display:block;margin-bottom:1.5px}
.mk-item .tx span{font-size:11.5px;color:var(--ink-4)}
.mk-item .val{font-size:14px;font-weight:700;font-variant-numeric:tabular-nums}

.rank{display:flex;flex-direction:column;gap:11px}
.rank .r{display:flex;align-items:center;gap:11px}
.rank .n{width:19px;height:19px;border-radius:5px;background:var(--bg);color:var(--ink-4);
  display:grid;place-items:center;font-size:11px;font-weight:700;flex:none}
.rank .r:nth-child(1) .n{background:var(--brand);color:#fff}
.rank .r:nth-child(2) .n{background:var(--brand-2);color:var(--brand-6)}
.rank .r:nth-child(3) .n{background:var(--warn-1);color:var(--warn)}
.rank .tx{flex:1;min-width:0}
.rank .tx .tp{display:flex;justify-content:space-between;font-size:12.5px;margin-bottom:5px;gap:9px}
.rank .tx .tp b{font-variant-numeric:tabular-nums;font-weight:650}
.rank .tx .tp span{color:var(--ink-3);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.rank .bar{height:5.5px;background:var(--bg);border-radius:3px;overflow:hidden}
.rank .bar i{display:block;height:100%;border-radius:3px;background:linear-gradient(90deg,var(--brand),#43c08a)}

.tl{position:relative;padding-left:22px}
.tl:before{content:"";position:absolute;left:5px;top:5px;bottom:5px;width:1.5px;background:var(--line)}
.tl .it{position:relative;padding-bottom:17px}
.tl .it:last-child{padding-bottom:0}
.tl .it:before{content:"";position:absolute;left:-21px;top:4px;width:8px;height:8px;border-radius:50%;
  background:var(--brand);box-shadow:0 0 0 3px var(--brand-1)}
.tl .it.dg:before{background:var(--danger);box-shadow:0 0 0 3px var(--danger-1)}
.tl .it .tm{font-size:11.5px;color:var(--ink-4);margin-bottom:2px}
.tl .it .tx{font-size:12.5px;color:var(--ink-2)}
.tl .it .tx b{color:var(--ink);font-weight:600}

.tagline{display:inline-flex;align-items:center;gap:5px;font-size:11.5px;padding:2.5px 9px;
  border-radius:6px;background:var(--bg);color:var(--ink-3);font-weight:500}
.hint{font-size:11.5px;color:var(--ink-4);margin-top:6px;display:flex;align-items:center;gap:5px}
.chk{display:flex;align-items:center;gap:7px;font-size:12.5px;color:var(--ink-2);cursor:pointer}
.chk input{width:15px;height:15px;accent-color:var(--brand);cursor:pointer}
.vt{display:flex;flex-direction:column;gap:15px}
.vt .v{position:relative;padding-left:19px}
.vt .v:before{content:"";position:absolute;left:4px;top:5px;bottom:5px;width:2px;background:var(--line);border-radius:1px}
.vt .v.on:before{background:var(--brand)}
.vt .v .t{font-size:12.5px;font-weight:600;margin-bottom:2px}
.vt .v .s{font-size:11.5px;color:var(--ink-4)}

/* ---------------- 充电枪卡片（协议对接：远程启停） ---------------- */
.proto-tag{display:inline-block;padding:2px 7px;border-radius:5px;font-size:11.5px;
  background:var(--info-1);color:var(--info);font-weight:600;font-family:var(--mono)}
.conn-dot{display:inline-block;width:7px;height:7px;border-radius:50%;margin:0 4px 0 2px;
  vertical-align:middle}
.conn-dot.on{background:var(--ok);box-shadow:0 0 0 3px var(--ok-1)}
.conn-dot.off{background:var(--danger);box-shadow:0 0 0 3px var(--danger-1)}

#gunBox{display:flex;flex-direction:column;gap:10px;margin-top:4px}
.gun-card{border:1px solid var(--line);border-radius:var(--r);background:var(--surface-2);
  padding:12px 14px}
.gun-hd{display:flex;align-items:center;gap:9px;margin-bottom:9px}
.gun-hd b{font-size:13.5px}
.gun-metrics{display:flex;flex-wrap:wrap;gap:16px;font-size:12px;color:var(--ink-3);
  padding:8px 0;border-top:1px dashed var(--line-2);border-bottom:1px dashed var(--line-2)}
.gun-metrics b{color:var(--ink);font-weight:600}
.gun-act{display:flex;align-items:center;gap:10px;margin-top:10px}

/* ============================================================
   主题面板（顶栏 #themeBtn 弹出）
   ============================================================ */
#themePop{position:absolute;top:60px;right:14px;width:268px;z-index:80;display:none;
  background:var(--surface);border:1px solid var(--line);border-radius:var(--r-lg);
  box-shadow:var(--sh-3);padding:14px 15px 15px}
#themePop.on{display:block}
#themePop h4{font-size:11px;font-weight:500;color:var(--ink-4);letter-spacing:.7px;margin-bottom:8px}
#themePop section+section{margin-top:14px}
#themePop .sw{display:flex;flex-wrap:wrap;gap:6px}
#themePop .opt{height:28px;padding:0 11px;border-radius:var(--r-sm);border:1px solid var(--line);
  background:var(--surface);color:var(--ink-2);font-size:12px;cursor:pointer;transition:.14s}
#themePop .opt:hover{border-color:var(--ink-4);color:var(--ink)}
#themePop .opt.on{background:var(--brand-1);border-color:var(--brand);color:var(--brand);font-weight:600}
/* 色系色卡：上半是品牌主色，下缘一条细杠是侧边栏基色，一眼看出整套配色 */
#themePop .sk{width:36px;height:36px;border-radius:var(--r-sm);border:2px solid transparent;
  cursor:pointer;padding:0;position:relative;transition:.14s}
#themePop .sk:hover{transform:translateY(-1px)}
#themePop .sk.on{border-color:var(--ink-2)}
#themePop .sk i{position:absolute;left:5px;right:5px;bottom:5px;height:4px;border-radius:2px;opacity:.9}
#themePop .note{font-size:11.5px;color:var(--ink-4);margin-top:12px;line-height:1.65;
  border-top:1px solid var(--line-2);padding-top:10px}
#themePop .note.bad{color:var(--danger)}

/* ============================================================
   页脚：ICP 备案等合规信息
   ============================================================ */
.site-foot{padding:16px 19px 20px;text-align:center;font-size:11.5px;color:var(--ink-4);line-height:2}
.site-foot a{color:var(--ink-4);transition:.14s}
.site-foot a:hover{color:var(--brand)}
.site-foot .sep{margin:0 8px;opacity:.5}

/* ============================================================
   派生令牌：仅在支持 color-mix() 的浏览器上生效
   —— 放在文件最后，靠源码顺序覆盖上面的字面量兜底；
      不支持的浏览器直接跳过整块，退回 :root / [data-theme=dark] 里的固定色值。
   这样一处规则同时适配「明暗 × 色系」全部组合：改一个 --brand 或 --surface，
   淡底色与侧边栏层次会自动跟着重算，不必为每个色系各写一遍深色版。
   ============================================================ */
@supports (color: color-mix(in srgb, red 10%, white)){
  :root{
    /* 淡底色：主色与当前底色混合 —— --surface 变深即自动得到深色模式的淡底 */
    --brand-1:color-mix(in srgb, var(--brand) 10%, var(--surface));
    --brand-2:color-mix(in srgb, var(--brand) 20%, var(--surface));
    --info-1:color-mix(in srgb, var(--info) 10%, var(--surface));
    --purple-1:color-mix(in srgb, var(--purple) 10%, var(--surface));
    --warn-1:color-mix(in srgb, var(--warn) 12%, var(--surface));
    --danger-1:color-mix(in srgb, var(--danger) 10%, var(--surface));
    --ok-1:color-mix(in srgb, var(--ok) 10%, var(--surface));
    --brand-glow:color-mix(in srgb, var(--brand) 34%, transparent);
    /* 侧边栏层次：由 --side-hue 一个基色派生，色系换了整套自动跟着换 */
    --side-bg:var(--side-hue);
    --side-bg-2:color-mix(in srgb, var(--side-hue) 84%, #000);
    --side-on:color-mix(in srgb, var(--side-hue) 72%, #fff);
    --side-ink:color-mix(in srgb, var(--side-hue) 20%, #fff);
    --side-ink-2:color-mix(in srgb, var(--side-hue) 45%, #fff);
    /* 深色底上品牌主色偏暗，强调色提亮后才醒目 */
    --side-accent:color-mix(in srgb, var(--brand) 58%, #fff);
  }
  [data-theme=dark]{
    /* 深色下侧边栏压暗，并保留一点品牌色倾向，让色系差异仍然可辨 */
    --side-bg:color-mix(in srgb, var(--brand) 12%, #090e13);
    --side-bg-2:color-mix(in srgb, var(--brand) 8%, #060a0e);
    --side-on:color-mix(in srgb, var(--brand) 24%, #141c25);
    --side-ink:color-mix(in srgb, var(--brand) 12%, #b6c6d4);
    --side-ink-2:color-mix(in srgb, var(--brand) 12%, #6d7f8f);
    --side-accent:color-mix(in srgb, var(--brand) 62%, #fff);
    /* 登录页品牌区在深色下再压一档，避免整页过亮 */
    --lh1:color-mix(in srgb, var(--lh1) 88%, #000);
    --lh2:color-mix(in srgb, var(--lh2) 84%, #000);
    --lh3:color-mix(in srgb, var(--lh3) 80%, #000);
  }
}

/* ============================================================
   角色权限页（sy-perm）
   ------------------------------------------------------------
   左侧角色列表 + 右侧权限/菜单勾选树。所有颜色走主题令牌，
   因此 6 个色系、明暗、三档密度下都不用另写覆盖规则。
   ============================================================ */
.perm-wrap{display:grid;grid-template-columns:246px 1fr;gap:var(--gap);align-items:start}
@media(max-width:1100px){.perm-wrap{grid-template-columns:1fr}}

/* 左：角色列表 */
.perm-roles{padding:6px}
.perm-roles .pr{display:flex;align-items:center;gap:8px;padding:9px 11px;border-radius:8px;
  cursor:pointer;transition:background .16s,box-shadow .16s}
.perm-roles .pr:hover{background:var(--brand-1)}
.perm-roles .pr.on{background:var(--brand-1);box-shadow:inset 0 0 0 1px var(--brand)}
.perm-roles .pr b{font-size:13px;font-weight:600}
.perm-roles .pr .sm{font-size:11px;opacity:.6;margin-left:auto;white-space:nowrap}
/* 超级角色角标：提示它不可逐项配置 */
.perm-roles .pr .sup{font-size:10px;line-height:1.6;padding:0 5px;border-radius:4px;
  background:var(--brand);color:#fff;font-weight:600}

/* 右：说明条 */
.perm-note{font-size:12px;line-height:1.75;padding:9px 12px;border-radius:8px;
  background:var(--brand-1);margin-bottom:var(--gap)}

/* 分组（模块标题 + 该组权限点） */
.perm-sec{margin-bottom:14px}
.perm-sec>h4{font-size:12.5px;margin:0 0 6px;display:flex;align-items:center;gap:8px;font-weight:600}
.perm-sec>h4 .n{font-size:11px;opacity:.55;font-weight:400}
.perm-sec>h4 .sp{flex:1}
.perm-sec>h4 button{font-size:11px;height:22px;padding:0 8px}
/* auto-fill 让不同宽度下都能排满，不用手写断点 */
.perm-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(196px,1fr));gap:1px 8px}
.perm-grid label{display:flex;align-items:center;gap:6px;font-size:12.5px;padding:4px 6px;
  border-radius:6px;cursor:pointer;user-select:none}
.perm-grid label:hover{background:var(--brand-1)}
.perm-grid input[type=checkbox]{width:14px;height:14px;accent-color:var(--brand);cursor:pointer;flex:none}
/* 禁用态（超级角色）：视觉上明确区分「不可改」而不是「没勾」 */
.perm-grid label.dis{opacity:.45;cursor:not-allowed}
.perm-empty{font-size:12.5px;opacity:.6;padding:8px 2px}
/* 已改动提示 */
.perm-dirty{font-size:11.5px;padding:2px 8px;border-radius:10px;
  background:var(--warn-1, var(--brand-1));color:var(--warn)}
/* 由通配符（asset:* / * 等）覆盖的权限点：勾选来自通配而非逐项授权。
   虚线下划线提示「它不对应库里的一条独立记录，取消单项不会生效」。 */
.perm-grid label.wild span{border-bottom:1px dashed var(--brand)}
