/* ==========================================================================
   大屏 · 统一视觉主题 v1（2026-09-12 立）
   --------------------------------------------------------------------------
   红线（与整个大屏一致）：
     ① 零外链 —— 字体只用系统自带，无 @import、无 CDN、无 canvas 依赖
     ② 令牌化 —— 各页只准用本文件变量，禁止再写裸色值
     ③ 性能   —— 动效一律走 transform / opacity（GPU 合成），
                 禁 setInterval 每帧重画；低配机可整档降级（body.fx-lite）
   引入： <link rel="stylesheet" href="libs/hq-theme.css">
   降级： URL 带 ?fx=lite 或给 body 加 class="fx-lite"
   ========================================================================== */

/* --------------------------------------------------------------------------
   一、设计令牌
   -------------------------------------------------------------------------- */
:root{
  /* 底色阶：从最深到最亮，大屏所有背景只准从这里取 */
  --bg-0:#04070F;
  --bg-1:#071120;
  --bg-2:#0B1A2E;
  --bg-3:#10243C;

  /* 描边 */
  --line-1:rgba(0,180,255,.16);
  --line-2:rgba(0,200,255,.45);

  /* 语义色：**每个颜色都有唯一含义**，不许当装饰乱用 */
  --cyan:#00D4FF;   /* 当前项目 / 主强调 */
  --teal:#22E6B8;   /* 正常 · 已接入 */
  --gold:#FFC247;   /* 世界遗产 · 预警 */
  --violet:#8B5CF6; /* 数据流 · 飞线 */
  --red:#FF4D5E;    /* 告警 */

  /* 语义别名（写页面时用这个，别直接写 --cyan） */
  --c-now:var(--cyan);        /* 当前项目 */
  --c-ok:var(--teal);         /* 已接入监测 */
  --c-heritage:var(--gold);   /* 世界文化遗产 */
  --c-flow:var(--violet);     /* 数据流 */
  --c-alarm:var(--red);       /* 告警 */
  --c-off:#5A7392;            /* 未接入 */

  /* 文字三级 */
  --tx-1:#EAF4FF;   /* 主信息：标题、数字 */
  --tx-2:#93A9C4;   /* 次信息：标签、说明 */
  --tx-3:#5B7392;   /* 弱信息：单位、脚注 */

  /* ★ 字体（零外链，全部系统自带）
     Bahnschrift 是 Windows 10+ 自带的可变字体，SemiCondensed 窄体最像工业仪表；
     退到 DIN Alternate（部分 Win 也带）→ Consolas → 系统等宽。
     ★★ 关键暗功：数字必须走与中文不同的字体族，否则「4.24 MPa」和中文标签
        糊成一片，远看完全没有仪表感。 */
  --ff-num:"Bahnschrift SemiCondensed","Bahnschrift","DIN Alternate",
           Consolas,"Cascadia Mono","MS Gothic",monospace;
  --ff-cn:"Microsoft YaHei","PingFang SC","Hiragino Sans GB",system-ui,sans-serif;
  --ff-title:"Microsoft YaHei","PingFang SC",system-ui,sans-serif;

  /* 字号阶 */
  --fs-hero:40px;  /* 首屏主角数字 */
  --fs-num:34px;   /* 指标卡主数字 */
  --fs-num2:26px;  /* 次级数字 */
  --fs-title:15px; /* 面板标题 */
  --fs-body:12.5px;
  --fs-tag:10.5px; /* 标注（配 letter-spacing:2~3px） */

  /* 发光（炫彩档；lite 档会被压掉） */
  --glow-cyan:0 0 12px rgba(0,212,255,.55),0 0 32px rgba(0,212,255,.20);
  --glow-teal:0 0 12px rgba(34,230,184,.55),0 0 32px rgba(34,230,184,.20);
  --glow-gold:0 0 12px rgba(255,194,71,.55),0 0 32px rgba(255,194,71,.20);
  --glow-red:0 0 12px rgba(255,77,94,.70),0 0 34px rgba(255,77,94,.28);
  --txt-glow-cyan:0 0 10px rgba(0,212,255,.75),0 0 26px rgba(0,212,255,.35);

  /* 节奏 */
  --ease-out:cubic-bezier(.22,.68,.36,1);
  --dur:600ms;
  --breath:2.4s;   /* 状态呼吸：正常 */
  --breath-alarm:1s; /* 告警呼吸 */

  /* 面板材质 */
  --panel-bg:linear-gradient(158deg,rgba(11,26,46,.92) 0%,rgba(7,17,32,.86) 100%);
  --panel-blur:blur(8px);
  --corner:16px;   /* 角标臂长 */
  --corner-w:2px;  /* 角标粗细 */

  /* --------------------------------------------------------------------------
     地图层（2026-09-21 新增 · 见 _docs/地图页科技感提升方案_20260921.md）
     ★ 用途：地图页（gis-globe.html / map3d-test.html）**只准从这里取色**。
     ★ 为什么单列一节：地图底图与 UI 必须同族，否则"深色网页里嵌了张别人的地图"。
       底图阶全部取自 --bg-0 #04070F 一族，只做明度/色相微调，保证同色温。
     ★ 两段式地形着色（来自参考案例 art1）：先 colorize(elevation) 定地貌色，
       再乘 hillshade 的受光系数（azimuth 315° / altitude 48°）——
       所以同一块地形靠光照立起来，这是"舆图感"的来源。明暗两端就是下面
       --map-relief-hi / --map-relief-lo 两个值。
     -------------------------------------------------------------------------- */
  /* 底图阶（深色同族，由深到浅） */
  --map-space:#02050C;      /* 宇宙底（地球外部） */
  --map-relief-lo:#050D18;  /* 地形晕渲 · 背光面 */
  --map-water:#061426;      /* 海洋 / 水系 */
  --map-land:#0A1E33;       /* 陆地 */
  --map-land-hi:#12304B;    /* 陆地抬升（当前区域底） */
  --map-relief-hi:#1B4568;  /* 地形晕渲 · 受光面 */

  /* 线 / 界 / 网格 */
  --map-bound-now:rgba(0,212,255,.55);   /* 当前层级行政界 */
  --map-bound:rgba(90,115,146,.28);      /* 普通行政界 */
  --map-grid:rgba(0,180,255,.055);       /* 经纬网（默认档） */
  --map-grid-hi:rgba(0,180,255,.14);     /* 经纬网（高亮档） */
  --map-fill:rgba(0,212,255,.10);        /* 区域填充（半透明，别实心铺） */
  --globe-atmo:rgba(0,212,255,.42);      /* 大气辉光 */
  --map-mask:rgba(2,5,12,.62);           /* 底图压暗蒙版 */
  /* 底图压暗/降饱和滤镜 —— 让电子地图默认的灰褐纸色归队到深蓝族 */
  --map-dim:saturate(.35) brightness(.72);
  /* ★ S31h 新增：**地图背景**专用底色。以前 bg 图层直接借 --bg-0（整页宣纸色，明度 235），
     80% 透过率把整张图托得很白 —— 这是「洗白」的来源之一。地图要有自己的、更深的底。 */
  --map-bg:#0A1526;
  /* ★ S30：地形晕渲三色（与区划配色解耦）
     ★ 深色档**回落旧值**（= --map-relief-* / --map-water），所以深色观感一字不变；
       浅色/古风档覆盖为**带 alpha 的半透明色** —— 因为浅色档的晕渲叠在板块**之上**，
       不透明会把整块视口涂满、把底图彻底压死。 */
  /* 板块（fill-extrusion）不透明度：★ 它是"辖区里能不能看见地形"的唯一旋钮 ——
     地形晕渲在板块**之下**，板块越透明、地形越清楚。
     深色档回落到改动前的 0.55（观感一字不动）。 */
  --map-face-opacity:0.55;
  /* ★ S30 古风档构件色（匾额 / 瓦檐 / 胶囊按钮）——
     深色档给一组**同义回落值**，保证这两档永远不会"变量未定义 ⇒ 静默继承"。 */
  --ink-plaque-lo:#071423; --ink-plaque:#0E3358; --ink-plaque-hi:#144A7C;
  --ink-plaque-tx:#EAF4FF; --ink-eave:#1B6EA8;
  --ink-pill-hi:#144A7C; --ink-pill-lo:#0E3358; --ink-pill-tx:#EAF4FF;
  --map-hs-shadow:var(--map-relief-lo);
  --map-hs-hi:var(--map-relief-hi);
  --map-hs-accent:var(--map-water);
  /* 区划板块色板的「第 4 档」（见 map3d-test.html 的 palette()）——
     ★ 必须在三个色档块里都定义：任一档漏写 ⇒ CSSV('--ink-p4') 读到"未定义"，
       于是静默继承成别的颜色（本页踩过这个坑），而**不报任何错**。
     深色档实际不用它（palette() 只在 ink 档取这个值），这里给一个同族回落而已。 */
  --ink-p4:#7E9A6E;
}

/* --------------------------------------------------------------------------
   一·B、浅色档 / 古风档（2026-09-24 新增）
   参考案例：微信公众号「姝斐聊设计」两篇 —— 浅色大屏(冰雪感) / 古风大屏
   方案：_docs/地图页风格转向方案_20260924.md
   --------------------------------------------------------------------------
   ★ 为什么做成"覆盖层"而不是直接改 :root 的值：
     老板 2026-09-24 拍板「全站统一」转浅色。但**深色本身没有错**（投屏场景更
     合适，原作者也说了"投到大屏时更愿意看深色"），所以这里**一个字都不动
     :root 的深色值**，另开覆盖层：
       <html data-skin="light">  → 浅色（冰雪调性，中性、不带具象纹样）
       <html data-skin="ink">    → 古风（只在三维一张图的「安阳市」级使用）
       不加属性                   → 原深色档，随时可整体回退
   ★ 覆盖层的最大收益：全站 1300+ 处 var(--x) 引用**不用改任何页面代码**就跟着变。
     只有页面里写死的裸色值不受影响 —— 那才是"全站统一"要逐页补令牌的原因。
   ★ 特异性：:root = (0,1,0)，html[data-skin="…"] = (0,1,1)，能够覆盖。
   ★★ light 与 ink **共用"浅色基座"**（选择器并写），古风档只覆盖差异项。
      否则古风档里没写的令牌会**回落到 :root 的深色值** —— 例如漏写 --tx-1，
      就变成"近白文字配宣纸底"，等于白底白字，而且**不报错**。
   -------------------------------------------------------------------------- */

/* ① 浅色基座（light 与 ink 共用） */
html[data-skin="light"],
html[data-skin="ink"]{
  /* 底：冰白族 —— 与深色档一样"同族、只做明度差"，不做彩底
     （参考案例的反例：地图涂成多色相被判"像儿童游乐园"） */
  --bg-0:#EEF5FB;
  --bg-1:#F7FAFD;
  --bg-2:#E7F1F9;
  --bg-3:#D8E8F4;

  /* 描边 */
  --line-1:rgba(140,180,215,.36);
  --line-2:rgba(46,155,222,.58);

  /* 语义色：**分工不变，只换明度** —— 原 --cyan 的亮青在白底上对比度不足
     （看着像荧光笔描过），浅色档整体压深。 */
  --cyan:#1B7FC4;   /* 当前项目 / 主强调 */
  --teal:#2FA98C;   /* 正常 · 已接入 */
  --gold:#C98A1E;   /* 世界遗产 · 预警 */
  --violet:#6D4FD0; /* 数据流 · 飞线 */
  --red:#D2453F;    /* 告警 */
  --c-off:#93A9BC;  /* 未接入 */

  /* 文字：深色档是"浅字配深底"，这里整体翻转成"深字配浅底" */
  --tx-1:#123A5C;
  --tx-2:#4A7396;
  --tx-3:#8AA6BF;

  /* 面板：浅色档靠"白 + 淡投影"分层，不靠明度差 */
  --panel-bg:linear-gradient(158deg,rgba(255,255,255,.94) 0%,rgba(247,250,253,.88) 100%);
  --panel-blur:blur(6px);

  /* ★★ 发光 → 柔投影。深色档"发光"是为了在深底上亮起来；浅底上照搬只会把
     画面弄脏（光晕糊成一片）。这里**保留令牌名、换掉语义** ——
     所有 hq-* 构件自动跟着变，不必改构件代码。 */
  --glow-cyan:0 1px 3px rgba(27,127,196,.28);
  --glow-teal:0 1px 3px rgba(47,169,140,.28);
  --glow-gold:0 1px 3px rgba(201,138,30,.30);
  --glow-red:0 1px 3px rgba(210,69,63,.32);
  --txt-glow-cyan:none;

  /* 地图层（冰雪调性：雪原 + 冰晶板块）
     ★ 板块三档刻意比 --bg-0 深一档：实测第一版（#C2DFF2 一族）与浅底几乎同色，
       板块"浮不起来"、省界糊成一片。案例里板块是**半透明冰晶**，
       要能一眼看出"这是块地形"而不是"底图上的色差"。 */
  --map-space:#DCEAF5;      /* 地球外部天幕（浅色档下星空要关，见页面 JS） */
  --map-relief-lo:#8FC2E2;  /* 背光面 / 板块暗档（晕渲的「暗」端） */
  --map-water:#A8CCE6;      /* 海洋 · 水系 */
  --map-land:#A9D3EE;       /* 陆地 / 板块中档 */
  --map-land-hi:#C9E4F6;    /* 抬升 / 板块亮档 */
  --map-relief-hi:#F2F9FE;  /* 受光面（雪；晕渲的「亮」端） */
  --map-bound-now:rgba(27,127,196,.62);
  --map-bound:rgba(120,155,190,.34);
  --map-grid:rgba(27,127,196,.09);
  --map-grid-hi:rgba(27,127,196,.18);
  --map-fill:rgba(255,255,255,.55);  /* ★ 浅色档的"填充"是白色半透明（冰晶感），不是青色 */
  --globe-atmo:rgba(126,196,238,.60);
  --map-mask:rgba(238,245,251,.52);
  --map-dim:saturate(.62) brightness(1.04);  /* ★ 深色档是"压暗"，浅色档是"提亮降饱和" */
  --map-bg:#DCD6C6;
  /* 晕渲三色（浅色档必须显式覆盖 —— 不写就回落到 :root 的**不透明深色**，
     在浅色底图上会变成一块死黑）。
     ★★ 位置说明（2026-09-24 实测修正，别再按旧注释理解）：
        晕渲**恒在板块之下**，不随皮肤挪。因为板块是 `fill-extrusion`（3D 图层，
        写深度缓冲且最后一遍绘制），把 2D 的 hillshade 在 style 里排到它之后**盖不住它**。
        ⇒ "辖区里看得见地形"只能靠**板块更透明**把地形从底下透出来
          （见 --map-face-opacity）。
     ★ 浓度必须偏高：这层晕渲是**被板块的 alpha 调制后**才可见的
        （板块 0.44 ⇒ 晕渲只剩 56% 参与合成），半透明的 0.4x 透出来等于没有。 */
  --map-hs-shadow:rgba(96,148,196,.78);
  --map-hs-hi:rgba(255,255,255,.86);
  --map-hs-accent:rgba(140,190,228,.60);
  /* 区划板块色板第 4 档（浅色基座同样要有定义，理由见 :root 那段） */
  --ink-p4:#B9CBA6;
  /* 板块透明度：0.55 → 0.44 —— 让地形从底下透出来 */
  --map-face-opacity:0.44;

  /* ★★ 旧色板兼容（2026-09-24 全站铺开时新增）
     下面这批名字**不是主题令牌**，是 video-wall / hik_dashboard_v2 / l2
     三张页自带色板里的变量名。它们的 :root 是 (0,1,0)，这里是 (0,1,1)，能盖住；
     不补这一段，那三页会停在深色档 —— 表现为"外壳白了、内容还是深蓝"的夹生状态。
     ★ 取值刻意与上面同源，避免同一页出现两套"浅"。 */
  --bg-deep:#EEF5FB;
  --bg-dark:#F7FAFD;
  --bg-panel:rgba(255,255,255,.92);
  --bg-card:rgba(255,255,255,.88);
  --blue:#2E7FD4;
  --glow:0 2px 10px rgba(40,90,130,.18);
  --cyan-glow:#2E9BDE;
  --green:#2FA98C;
  --yellow:#C98A1E;
  --orange:#D9822B;
  --purple:#6D4FD0;
  --text:#123A5C;
  --text-dim:#4A7396;
  --text-bright:#0E2C46;
  --border:rgba(140,180,215,.40);
  --border-bright:rgba(46,155,222,.62);
}

/* ② 构件内的硬编码色覆盖（浅色基座）
   ★ 上一轮只把构件里"能用令牌的部分"替换了，构件内部仍有写死的 rgba
     （如 .hq-kpi 的深色渐变、.hq-badge 的深蓝底、.hq-corners 的青色光晕）。
     浅色档下必须一并覆盖，否则会出现"白面板里嵌了个黑方块"这种拼贴感。 */
html[data-skin="light"] .hq-title-grad,
html[data-skin="ink"] .hq-title-grad{
  background:linear-gradient(96deg,#0B2C46 6%,#1A6C9C 42%,var(--cyan) 88%);
  -webkit-background-clip:text;background-clip:text;color:transparent;
  filter:none;   /* 浅底上 drop-shadow 会在字四周糊一圈灰 */
}
html[data-skin="light"] .hq-watermark,
html[data-skin="ink"] .hq-watermark{color:rgba(38,88,128,.085);}
html[data-skin="light"] .hq-grid,
html[data-skin="ink"] .hq-grid{
  background-image:
    linear-gradient(rgba(27,127,196,.075) 1px,transparent 1px),
    linear-gradient(90deg,rgba(27,127,196,.075) 1px,transparent 1px);
}
html[data-skin="light"] .hq-radar,
html[data-skin="ink"] .hq-radar{border-color:rgba(27,127,196,.16);}
html[data-skin="light"] .hq-radar::before,
html[data-skin="ink"] .hq-radar::before{border-color:rgba(27,127,196,.13);}
html[data-skin="light"] .hq-radar::after,
html[data-skin="ink"] .hq-radar::after{border-color:rgba(27,127,196,.10);}
/* ★ 扫描扇：深色档里它是"光"（深底上越亮越像在扫描）；浅色档照搬会变成一个
   **实心蓝块** —— 深色放在浅底上对比太强。透明度要再压一半以上、衰减也收紧，
   实拍确认过（放大右上的罗盘：扇形整块实心，很抢眼）。 */
html[data-skin="light"] .hq-radar>.hq-sweep-fan,
html[data-skin="ink"] .hq-radar>.hq-sweep-fan{
  background:conic-gradient(from 0deg,rgba(27,127,196,.09) 0deg,
    rgba(27,127,196,.03) 20deg,rgba(27,127,196,0) 46deg,rgba(27,127,196,0) 360deg);
}
html[data-skin="light"] .hq-beam,
html[data-skin="ink"] .hq-beam{
  background:linear-gradient(90deg,transparent,rgba(27,127,196,0) 12%,
    rgba(27,127,196,.55) 50%,rgba(27,127,196,0) 88%,transparent);
}
/* 角标：浅底上不要光晕，改成"描边 + 极淡投影" */
html[data-skin="light"] .hq-corners::before,html[data-skin="light"] .hq-corners::after,
html[data-skin="light"] .hq-corners>.hq-c4a,html[data-skin="light"] .hq-corners>.hq-c4b,
html[data-skin="ink"] .hq-corners::before,html[data-skin="ink"] .hq-corners::after,
html[data-skin="ink"] .hq-corners>.hq-c4a,html[data-skin="ink"] .hq-corners>.hq-c4b{filter:none;}
/* 光扫：浅底上的"白光"扫过是隐形的，换成深色淡扫 */
html[data-skin="light"] .hq-sweep::after,
html[data-skin="ink"] .hq-sweep::after{
  background:linear-gradient(90deg,transparent,rgba(27,127,196,.14),transparent);
}
/* 状态灯：浅底上"发光"等于没有，改用实色 + 淡环 */
html[data-skin="light"] .hq-dot.on,html[data-skin="ink"] .hq-dot.on{box-shadow:none;}
html[data-skin="light"] .hq-dot.warn,html[data-skin="ink"] .hq-dot.warn{box-shadow:none;}
html[data-skin="light"] .hq-dot.alarm,
html[data-skin="ink"] .hq-dot.alarm{box-shadow:0 0 0 3px rgba(210,69,63,.18);}
/* 徽标 */
html[data-skin="light"] .hq-badge,
html[data-skin="ink"] .hq-badge{background:rgba(255,255,255,.80);}
html[data-skin="light"] .hq-badge.b-cyan{border-color:rgba(27,127,196,.42);color:#1B6E9E;background:rgba(46,155,222,.10);}
html[data-skin="light"] .hq-badge.b-teal{border-color:rgba(47,169,140,.42);color:#22806C;background:rgba(47,169,140,.10);}
html[data-skin="light"] .hq-badge.b-gold{border-color:rgba(201,138,30,.42);color:#9A6A14;background:rgba(201,138,30,.10);}
/* 面板：浅色档补一层淡投影（白面板在白底上，没有投影就"糊"在一起） */
html[data-skin="light"] .hq-panel,
html[data-skin="ink"] .hq-panel{box-shadow:0 2px 12px rgba(70,120,170,.10);}
/* 指标卡 */
html[data-skin="light"] .hq-kpi,
html[data-skin="ink"] .hq-kpi{
  background:linear-gradient(158deg,rgba(255,255,255,.92),rgba(244,249,253,.72));
  box-shadow:0 1px 4px rgba(70,120,170,.10);
}
html[data-skin="light"] .hq-kpi .k-val.v-cyan{color:#0E4C77;}
html[data-skin="light"] .hq-kpi .k-val.v-teal{color:#1B6B58;}
html[data-skin="light"] .hq-kpi .k-val.v-gold{color:#8A5E12;}

/* ③ 古风档 —— **只写与浅色基座的差异**
   （案例 art2：宣纸底 + 立体青绿山地 + 金边 + 宋体 + 匾额） */
html[data-skin="ink"]{
  /* 底：宣纸（暖） */
  --bg-0:#EFEBE0;
  --bg-1:#F7F4EC;
  --bg-2:#E9E4D6;
  --bg-3:#DDD6C2;

  --line-1:rgba(120,145,110,.36);
  --line-2:rgba(199,154,62,.58);

  /* 主强调换「深青绿」，金留给世界遗产 —— 与案例的分工一致 */
  --cyan:#3E6B4A;
  --teal:#5E8C63;
  --gold:#C79A3E;
  --violet:#8A6A4A;
  --red:#B8483C;
  --c-off:#9A9A88;

  --tx-1:#2C3A2A;
  --tx-2:#5C6B52;
  --tx-3:#8E9A82;

  --panel-bg:linear-gradient(158deg,rgba(255,253,247,.94) 0%,rgba(247,244,236,.90) 100%);
  --panel-blur:blur(4px);

  --glow-cyan:0 1px 3px rgba(62,107,74,.30);
  --glow-teal:0 1px 3px rgba(94,140,99,.30);
  --glow-gold:0 1px 3px rgba(199,154,62,.34);
  --glow-red:0 1px 3px rgba(184,72,60,.34);

  /* 地图层：立体山地（受光嫩绿 / 背光墨绿）＋ 金边 */
  --map-space:#E8E2D2;
  --map-relief-lo:#547A52;
  --map-water:#A8CEDC;
  /* ★ S31h：板块三色各压深一档 —— 底（地图）变深后，板块若不动就会"跳出来"，
     整体反而更花。压深后与加深的山色重新咬合，仍是"青绿山峦 + 略亮板块"的关系。 */
  --map-land:#6E8F58;
  --map-land-hi:#B6CCA4;
  --map-relief-hi:#CFDDBE;
  --map-bound-now:rgba(199,154,62,.75);
  --map-bound:rgba(110,135,95,.42);
  --map-grid:rgba(140,160,120,.14);
  --map-grid-hi:rgba(199,154,62,.24);
  --map-fill:rgba(255,252,240,.40);
  --globe-atmo:rgba(198,190,152,.55);
  --map-mask:rgba(239,235,224,.50);
  --map-dim:saturate(.72) brightness(1.02);
  /* ★ S31h：地图底从"整页宣纸色 #EFEBE0（明度 235）"换成**更暖更深的宣纸**。
     为什么必须独立成一个令牌：整页 --bg-0 同时管着顶栏/面板的底色，
     直接改它会把 UI 一起压暗；而地图底只需要压这一处。
     取值依据：_s31e 量到本页明度均值比案例高 31.9，其中约一半来自这层底。
     #E3DCC8 明度 220 —— 压 15，同时色相更暖（R>G>B 的间距拉大），宣纸的暖调更明确。 */
  --map-bg:#E3DCC8;
  /* 古风档晕渲三色 —— ★ 2026-09-24 改为按**参考案例实测采样**定值，不再凭感觉。
     从 _refs/case_20260924/img/art2_02.png 的地图主体区采 14687 个绿色像素，
     按明度排序分五档求均值，得到案例的"青绿山峦"色阶：
         背光最暗 20%  rgb(62, 91, 57)   #3D5B39
         次暗     20%  rgb(98,130, 92)
         中间     20%  rgb(130,160,116)
         次亮     20%  rgb(164,188,139)
         受光最亮 20%  rgb(197,213,168)  #C4D5A7
     ⇒ shadow 取背光端、hi 取受光端、accent 取中间端。
     ★★ 上一版的两个错（画面表现 = "山是灰白的、还泛蓝"，老板一眼看出来）：
        · hi 用了**宣纸白** rgba(250,247,228,.88) ⇒ 受光面变米白、整片山**失绿变灰**；
          案例里受光面是**嫩绿**，不是白。
        · accent 用了**青灰** rgba(150,186,170,.62) ⇒ 陡坡上一层蓝雾。
        ★ 关键认知：MapLibre 的 accent 是给**陡坡**加权的（越陡越重），
          所以"山的绿"主要由它决定，hi/shadow 只管山脊与沟谷的明暗两端。
     ★ 浓度偏高是被板块 alpha 调制后才可见所迫（板块 0.44 ⇒ 只剩 56% 参与合成）。 */
  /* ★★★ S31h「再浓一些」第一轮 —— 全部按 _s31e 的量化差定向调，不凭感觉。
     _s31e 实测（市级太行山区同 ROI，绿优势像素）：
        明度均值 案例 154.2 / 本页 186.1（偏白 +31.9）
        反差 std 案例  42.7 / 本页  20.7（只有一半）
        分档 ΔL  +65.3 +47.7 +29.7 +14.9 +2.1
     ⇒ 最亮档只差 2.1（受光面已经对），差的全在暗部。
     ★ 为什么加大 alpha 没用：shade 的 alpha ∝ sin(slope)，太行山在市级 306 m/px 的
       屏幕尺度上 sin(slope) 顶多 0.2~0.3 ⇒ alpha 封顶 ~0.26，抬不动。
     ⇒ 那就**加大颜色跨度**：shadow 明度从 75 压到 34，同样 0.26 的 alpha
       能把 ΔL 从 41 拉到 57。三个色同时把 alpha 提到接近 1（减少"半透明冲淡"）。
     ⚠️ hi 的亮度**只微降**：最亮档已与案例齐平，压多了受光面会发灰
        —— 那就是上一轮"山是灰白的"那个错的翻版。 */
  /* ★ S31k 第二轮微调（依据第一轮实测：最亮档 198 反比案例 208 暗了 10 ⇒ 压过头）：
     hi 提回一档到明度 203（贴近案例受光档 208），shadow 再压一档到明度 24。
     ★ hi 只提回**一档**，不回到最初那个近白值 —— 那正是"整片山失绿变灰"的病根。 */
  --map-hs-shadow:rgba(16,32,16,1);
  --map-hs-hi:rgba(196,214,168,.96);
  --map-hs-accent:rgba(92,124,82,.94);
  /* ★★ 板块色板第 4 档：古风档必须换掉 `--map-water`（浅蓝）。
     实拍：市级图**林州市整块发蓝灰**、省级/全国约 1/6 的省也是浅蓝 ——
     因为 palette() 把第 4 档设成了水系色，1/6 的区划会抽中它。
     在"青绿山峦 + 青绿板块"里那就是一块蓝斑，与参考案例（统一青绿 + 金边）不符。
     ⇒ 换成青绿次亮档（比 --map-land 亮、比 --map-land-hi 深，仍与相邻档可区分）。 */
  --ink-p4:#93AC7F;
  /* ★ S31h：板块面从 0.44 放到 0.38 —— 山从板块下透出来的比例从 56% 提到 62%。
     配套：--ink-p4（色板第 4 档）跟着压深，否则它比周围板块亮、会浮起来。 */
  --map-face-opacity:0.38;

  /* ★ 旧色板兼容（古风档取值，与 ① 段末的浅色值一一对应） */
  --bg-deep:#EFEBE0;
  --bg-dark:#F7F4EC;
  --bg-panel:rgba(255,253,247,.94);
  --bg-card:rgba(255,253,247,.90);
  --blue:#4A6F8C;
  --glow:0 2px 10px rgba(120,110,80,.20);
  --cyan-glow:#5E8C63;
  --green:#5E8C63;
  --yellow:#C79A3E;
  --orange:#B8802F;
  --purple:#8A6A4A;
  --text:#2C3A2A;
  --text-dim:#5C6B52;
  --text-bright:#22301F;
  --border:rgba(120,145,110,.40);
  --border-bright:rgba(199,154,62,.62);

  /* 字体：宋体（案例 art2 的做法）
     ★ 零外链 —— 只用系统字体：Windows 有 SimSun，macOS 有 Songti SC。 */
  /* 古风档构件色：匾额（深绿石板三段）+ 瓦檐 + 胶囊选中态 */
  --ink-plaque-lo:#2B4632; --ink-plaque:#3E6B4A; --ink-plaque-hi:#4C7E58;
  --ink-plaque-tx:#F7F0DC; --ink-eave:#58905F;
  --ink-pill-hi:#4E8659; --ink-pill-lo:#3A6446; --ink-pill-tx:#FAF4E2;
  --ff-cn:"SimSun","Songti SC","Source Han Serif SC","Noto Serif SC",serif;
  --ff-title:"SimSun","Songti SC","Source Han Serif SC",serif;
  /* ★★ 宋体小字号发虚 —— 字号整体 +1px 补偿。这是"古风页看不清"的根因。 */
  --fs-body:13.5px;
  --fs-tag:11.5px;
  --fs-title:16px;
}
html[data-skin="ink"] .hq-watermark{color:rgba(120,104,70,.10);}
html[data-skin="ink"] .hq-badge.b-cyan{border-color:rgba(62,107,74,.42);color:#33583C;background:rgba(94,140,99,.10);}
html[data-skin="ink"] .hq-badge.b-teal{border-color:rgba(94,140,99,.42);color:#33583C;background:rgba(94,140,99,.10);}
html[data-skin="ink"] .hq-badge.b-gold{border-color:rgba(199,154,62,.42);color:#8A6A22;background:rgba(199,154,62,.12);}
html[data-skin="ink"] .hq-kpi .k-val.v-cyan{color:#2C3A2A;}
html[data-skin="ink"] .hq-kpi .k-val.v-teal{color:#33583C;}
html[data-skin="ink"] .hq-kpi .k-val.v-gold{color:#8A6A22;}

/* --------------------------------------------------------------------------
   二、基础字体工具类
   -------------------------------------------------------------------------- */
.hq-num{
  font-family:var(--ff-num);
  font-variant-numeric:tabular-nums;   /* 等宽数字：跳数时不左右抖 */
  font-feature-settings:"tnum" 1;
  letter-spacing:.02em;
  line-height:1;
}
.hq-num-unit{font-family:var(--ff-num);font-size:.42em;color:var(--tx-3);
  letter-spacing:.08em;margin-left:3px;font-weight:400;}
.hq-cn{font-family:var(--ff-cn);}
.hq-tag{font-family:var(--ff-num);font-size:var(--fs-tag);letter-spacing:2.6px;
  color:var(--tx-3);text-transform:uppercase;}

/* 渐变文字（白→青），用于主标题 */
.hq-title-grad{
  background:linear-gradient(96deg,#FFFFFF 6%,#BEE9FF 42%,var(--cyan) 88%);
  -webkit-background-clip:text;background-clip:text;color:transparent;
  filter:drop-shadow(0 0 18px rgba(0,212,255,.35));
}
/* 发光数字（炫彩档：三层 shadow 叠出"灯牌"感） */
.hq-glow{ text-shadow:var(--txt-glow-cyan); }
.hq-glow-teal{ text-shadow:0 0 10px rgba(34,230,184,.75),0 0 26px rgba(34,230,184,.35); }
.hq-glow-gold{ text-shadow:0 0 10px rgba(255,194,71,.75),0 0 26px rgba(255,194,71,.35); }
.hq-glow-red{ text-shadow:0 0 10px rgba(255,77,94,.85),0 0 28px rgba(255,77,94,.40); }

/* --------------------------------------------------------------------------
   三、装饰五件套
   -------------------------------------------------------------------------- */

/* ① 四角 L 形角标 —— 用多重 linear-gradient 画，零额外 DOM */
.hq-corners{position:relative;}
.hq-corners::before,
.hq-corners::after,
.hq-corners>.hq-c4a,
.hq-corners>.hq-c4b{
  content:"";position:absolute;width:var(--corner);height:var(--corner);
  pointer-events:none;z-index:2;
}
.hq-corners::before{top:0;left:0;border-top:var(--corner-w) solid var(--cyan);
  border-left:var(--corner-w) solid var(--cyan);
  filter:drop-shadow(0 0 6px rgba(0,212,255,.85));}
.hq-corners::after{top:0;right:0;border-top:var(--corner-w) solid var(--cyan);
  border-right:var(--corner-w) solid var(--cyan);
  filter:drop-shadow(0 0 6px rgba(0,212,255,.85));}
.hq-corners>.hq-c4a{bottom:0;left:0;border-bottom:var(--corner-w) solid var(--cyan);
  border-left:var(--corner-w) solid var(--cyan);
  filter:drop-shadow(0 0 6px rgba(0,212,255,.85));}
.hq-corners>.hq-c4b{bottom:0;right:0;border-bottom:var(--corner-w) solid var(--cyan);
  border-right:var(--corner-w) solid var(--cyan);
  filter:drop-shadow(0 0 6px rgba(0,212,255,.85));}
/* 只用两个伪元素时的简化版（不带 <i class="hq-c4a"> 两个子元素时） */
.hq-corners.hq-corners-2>.hq-c4a,
.hq-corners.hq-corners-2>.hq-c4b{display:none;}
/* 角标换色 */
.hq-corners.c-teal::before,.hq-corners.c-teal::after,
.hq-corners.c-teal>.hq-c4a,.hq-corners.c-teal>.hq-c4b{
  border-color:var(--teal);filter:drop-shadow(0 0 6px rgba(34,230,184,.85));}
.hq-corners.c-gold::before,.hq-corners.c-gold::after,
.hq-corners.c-gold>.hq-c4a,.hq-corners.c-gold>.hq-c4b{
  border-color:var(--gold);filter:drop-shadow(0 0 6px rgba(255,194,71,.85));}
.hq-corners.c-red::before,.hq-corners.c-red::after,
.hq-corners.c-red>.hq-c4a,.hq-corners.c-red>.hq-c4b{
  border-color:var(--red);filter:drop-shadow(0 0 6px rgba(255,77,94,.9));}

/* ② 标题栏 —— 3px 发光竖条 + 中文标题 + 右侧英文小字 */
.hq-titlebar{display:flex;align-items:center;gap:10px;position:relative;
  padding:0 0 0 12px;min-height:22px;}
.hq-titlebar::before{content:"";position:absolute;left:0;top:50%;
  transform:translateY(-50%);width:3px;height:14px;border-radius:1px;
  background:var(--cyan);box-shadow:var(--glow-cyan);}
.hq-titlebar b{font-family:var(--ff-title);font-size:var(--fs-title);
  font-weight:700;color:var(--tx-1);letter-spacing:1.4px;}
.hq-titlebar em{font-family:var(--ff-num);font-style:normal;
  font-size:var(--fs-tag);letter-spacing:2.2px;color:var(--tx-3);margin-left:auto;}
.hq-titlebar.t-teal::before{background:var(--teal);box-shadow:var(--glow-teal);}
.hq-titlebar.t-gold::before{background:var(--gold);box-shadow:var(--glow-gold);}
.hq-titlebar.t-red::before{background:var(--red);box-shadow:var(--glow-red);}

/* ③ 同心雷达环 —— 三层环 + 旋转扫描扇（纯 CSS，GPU 合成） */
.hq-radar{position:absolute;pointer-events:none;border-radius:50%;
  border:1px solid rgba(0,212,255,.13);}
.hq-radar::before{content:"";position:absolute;inset:18%;border-radius:50%;
  border:1px solid rgba(0,212,255,.10);}
.hq-radar::after{content:"";position:absolute;inset:36%;border-radius:50%;
  border:1px solid rgba(0,212,255,.08);}
.hq-radar>.hq-sweep-fan{position:absolute;inset:0;border-radius:50%;
  background:conic-gradient(from 0deg,rgba(0,212,255,.20) 0deg,
    rgba(0,212,255,.06) 26deg,rgba(0,212,255,0) 62deg,rgba(0,212,255,0) 360deg);
  animation:hqRotate 8s linear infinite;will-change:transform;}
@keyframes hqRotate{from{transform:rotate(0)}to{transform:rotate(360deg)}}

/* ④ 细网格底 —— 44px 格，中心向外淡出 */
.hq-grid{position:absolute;inset:0;pointer-events:none;
  background-image:
    linear-gradient(rgba(0,180,255,.055) 1px,transparent 1px),
    linear-gradient(90deg,rgba(0,180,255,.055) 1px,transparent 1px);
  background-size:44px 44px;
  -webkit-mask-image:radial-gradient(ellipse 70% 62% at 50% 46%,#000 12%,transparent 78%);
  mask-image:radial-gradient(ellipse 70% 62% at 50% 46%,#000 12%,transparent 78%);}

/* ⑤ 水印大字 —— 极低透明度的中/英文衬底，撑住画面不空 */
.hq-watermark{position:absolute;pointer-events:none;user-select:none;
  font-family:var(--ff-num);font-weight:700;letter-spacing:.06em;
  color:rgba(130,196,255,.075);white-space:nowrap;line-height:.86;}

/* --------------------------------------------------------------------------
   四、常用构件
   -------------------------------------------------------------------------- */

/* 面板（直角，不圆角 —— 圆角会立刻"软"掉，不像工程仪表） */
.hq-panel{position:relative;background:var(--panel-bg);
  border:1px solid var(--line-1);backdrop-filter:var(--panel-blur);
  -webkit-backdrop-filter:var(--panel-blur);}

/* 切角容器 clip-path */
.hq-cut{clip-path:polygon(10px 0,100% 0,100% calc(100% - 10px),
  calc(100% - 10px) 100%,0 100%,0 10px);}
.hq-cut-sm{clip-path:polygon(6px 0,100% 0,100% calc(100% - 6px),
  calc(100% - 6px) 100%,0 100%,0 6px);}

/* 光扫：悬停时一道斜光从左扫到右（只动 transform，不触发布局） */
.hq-sweep{position:relative;overflow:hidden;}
.hq-sweep::after{content:"";position:absolute;top:-60%;left:-70%;width:46%;height:220%;
  background:linear-gradient(90deg,transparent,rgba(190,235,255,.16),transparent);
  transform:skewX(-22deg) translateX(0);opacity:0;pointer-events:none;
  transition:transform .78s var(--ease-out),opacity .4s;}
.hq-sweep:hover::after{transform:skewX(-22deg) translateX(430%);opacity:1;}

/* 状态灯（呼吸） */
.hq-dot{display:inline-block;width:7px;height:7px;border-radius:50%;
  flex:none;vertical-align:middle;}
.hq-dot.on{background:var(--teal);box-shadow:0 0 8px rgba(34,230,184,.9);
  animation:hqBreath var(--breath) ease-in-out infinite;}
.hq-dot.warn{background:var(--gold);box-shadow:0 0 8px rgba(255,194,71,.9);
  animation:hqBreath var(--breath) ease-in-out infinite;}
.hq-dot.alarm{background:var(--red);box-shadow:0 0 10px rgba(255,77,94,.95);
  animation:hqBreath var(--breath-alarm) ease-in-out infinite;}
.hq-dot.off{background:var(--tx-3);}

/* 徽标 */
.hq-badge{display:inline-flex;align-items:center;gap:5px;padding:2px 8px;
  font-family:var(--ff-num);font-size:var(--fs-tag);letter-spacing:1.4px;
  border:1px solid var(--line-1);color:var(--tx-2);background:rgba(9,32,58,.6);}
.hq-badge.b-cyan{border-color:rgba(0,212,255,.42);color:#9FE6FF;
  background:rgba(0,212,255,.10);}
.hq-badge.b-teal{border-color:rgba(34,230,184,.42);color:#A6F2DE;
  background:rgba(34,230,184,.10);}
.hq-badge.b-gold{border-color:rgba(255,194,71,.42);color:#FFE0A6;
  background:rgba(255,194,71,.10);}

/* 指标卡（大屏最常见的构件） */
.hq-kpi{position:relative;padding:9px 13px;border:1px solid var(--line-1);
  background:linear-gradient(158deg,rgba(11,26,46,.72),rgba(7,17,32,.52));}
.hq-kpi .k-lab{font-family:var(--ff-cn);font-size:11px;color:var(--tx-2);
  letter-spacing:.6px;}
.hq-kpi .k-val{font-family:var(--ff-num);font-size:var(--fs-num);font-weight:700;
  color:var(--tx-1);letter-spacing:.02em;line-height:1.06;
  font-variant-numeric:tabular-nums;display:flex;align-items:baseline;gap:2px;}
.hq-kpi .k-val.v-cyan{color:#EAF7FF;text-shadow:var(--txt-glow-cyan);}
.hq-kpi .k-val.v-teal{color:#DDFBF3;
  text-shadow:0 0 10px rgba(34,230,184,.75),0 0 26px rgba(34,230,184,.32);}
.hq-kpi .k-val.v-gold{color:#FFF3D8;
  text-shadow:0 0 10px rgba(255,194,71,.75),0 0 26px rgba(255,194,71,.32);}

/* --------------------------------------------------------------------------
   五、动效库（全部 transform/opacity，GPU 合成）
   -------------------------------------------------------------------------- */
/* 呼吸（状态灯、重点数字） */
@keyframes hqBreath{
  0%,100%{opacity:1;transform:scale(1);}
  50%{opacity:.52;transform:scale(.90);}
}
/* 告警脉冲（向外扩散的光圈，用 box-shadow 会重绘；这里用 scale+opacity 的伪元素） */
@keyframes hqPulse{
  0%{transform:scale(.62);opacity:.85;}
  70%{transform:scale(1.5);opacity:0;}
  100%{transform:scale(1.5);opacity:0;}
}
/* 扫描线（视频空态 / 面板装饰） */
@keyframes hqScanY{
  0%{transform:translateY(-100%);}
  100%{transform:translateY(1100%);}
}
/* 流动虚线（管线 / 飞线底座） */
@keyframes hqDash{
  to{stroke-dashoffset:-64;}
}
/* 生长（面板/列表进场：向右展开 + 淡入） */
@keyframes hqRise{
  from{opacity:0;transform:translateY(10px);}
  to{opacity:1;transform:translateY(0);}
}
@keyframes hqWipe{
  from{opacity:0;transform:translateX(-14px);}
  to{opacity:1;transform:translateX(0);}
}
/* 数据流（沿 X 匀速平移，配 background-size 做流动光带） */
@keyframes hqFlow{
  to{background-position:220% 0;}
}

.hq-ani-rise{animation:hqRise 600ms var(--ease-out) both;}
.hq-ani-wipe{animation:hqWipe 600ms var(--ease-out) both;}
/* 依次进场：给同一批元素加 data-i 或用 nth-child 延时 */
.hq-stagger>*{animation:hqRise 600ms var(--ease-out) both;}
.hq-stagger>*:nth-child(1){animation-delay:40ms}
.hq-stagger>*:nth-child(2){animation-delay:110ms}
.hq-stagger>*:nth-child(3){animation-delay:180ms}
.hq-stagger>*:nth-child(4){animation-delay:250ms}
.hq-stagger>*:nth-child(5){animation-delay:320ms}
.hq-stagger>*:nth-child(6){animation-delay:390ms}
.hq-stagger>*:nth-child(7){animation-delay:460ms}
.hq-stagger>*:nth-child(8){animation-delay:530ms}

/* 顶部滚动光带（标题栏装饰，一个元素搞定） */
.hq-beam{position:absolute;left:0;right:0;height:1px;pointer-events:none;
  background:linear-gradient(90deg,transparent,rgba(0,212,255,0) 12%,
    rgba(0,212,255,.75) 50%,rgba(0,212,255,0) 88%,transparent);
  background-size:220% 100%;animation:hqFlow 5.5s linear infinite;}

/* --------------------------------------------------------------------------
   六、降级档（低配机 / 老板本机跑 62M 泼溅点时）
   -------------------------------------------------------------------------- */
body.fx-lite .hq-ani-rise,
body.fx-lite .hq-ani-wipe,
body.fx-lite .hq-stagger>*,
body.fx-lite .hq-dot,
body.fx-lite .hq-radar>.hq-sweep-fan,
body.fx-lite .hq-beam{animation:none!important;}
body.fx-lite .hq-beam{opacity:.5;}
body.fx-lite .hq-sweep::after{display:none;}
body.fx-lite .hq-glow,
body.fx-lite .hq-glow-teal,
body.fx-lite .hq-glow-gold,
body.fx-lite .hq-glow-red,
body.fx-lite .hq-kpi .k-val{text-shadow:none;}
body.fx-lite .hq-title-grad{filter:none;}
body.fx-lite .hq-corners::before,body.fx-lite .hq-corners::after,
body.fx-lite .hq-corners>.hq-c4a,body.fx-lite .hq-corners>.hq-c4b{filter:none;}
@media (prefers-reduced-motion:reduce){
  .hq-ani-rise,.hq-ani-wipe,.hq-stagger>*,.hq-dot,
  .hq-radar>.hq-sweep-fan,.hq-beam{animation:none!important;}
}

/* ==========================================================================
   一·C  深浅色一键切换按钮（S29，2026-09-24）
   --------------------------------------------------------------------------
   8 个页面都要这个按钮，样式写 8 份必然分叉（S28 的教训）。
   ★ 只写外观、不写位置：各页右上角被不同东西占着（地球页 gear/snd、一张图
     罗盘、驾驶舱 tab 栏、组态页 pin-x），统一位置必然撞车 ⇒ 由各页调用
     HQ_SKIN.mount({right:'90px',top:'12px'}) 给位置（见 libs/hq-skin.js）。
   ★ 颜色全走令牌 ⇒ 按钮自身在浅色/深色两档下自动协调，不必写两套。
   ========================================================================== */
#hq-skin-btn{
  position:fixed;z-index:60;
  right:14px;top:12px;                 /* 安全默认；浮层档由调用方覆盖 */
  display:inline-flex;align-items:center;gap:6px;
  height:28px;padding:0 10px;
  font:400 11.5px/1 var(--ff-cn);
  letter-spacing:.5px;
  color:var(--tx-2);
  background:var(--panel-bg);
  border:1px solid var(--line-1);
  border-radius:0;
  cursor:pointer;
  backdrop-filter:var(--panel-blur);
  -webkit-backdrop-filter:var(--panel-blur);
  box-shadow:var(--glow-cyan);
  transition:color .18s,border-color .18s,box-shadow .18s;
  -webkit-user-select:none;user-select:none;
}
#hq-skin-btn:hover{color:var(--tx-1);border-color:var(--line-2);}
#hq-skin-btn:focus-visible{outline:1px solid var(--line-2);outline-offset:2px;}
#hq-skin-btn .hqs-ico{
  width:12px;height:12px;flex:none;border-radius:50%;
  border:1.4px solid currentColor;
  background:linear-gradient(90deg,currentColor 0 50%,transparent 50% 100%);
  opacity:.9;
}
/* 深色档把明暗对调 —— 同一个圆，亮面在哪边就是"现在哪一半占主导" */
#hq-skin-btn[data-mode="dark"] .hqs-ico{
  background:linear-gradient(90deg,transparent 0 50%,currentColor 50% 100%);
}
/* 窄处（视频墙顶栏 / 组态页角标）只留图标 */
#hq-skin-btn.hqs-compact{padding:0 7px;}
#hq-skin-btn.hqs-compact .hqs-lb{display:none;}
/* 浅色档：把发光换成柔投影（与 S28 全站口径一致 —— 浅底上发光只会弄脏画面） */
html[data-skin="light"] #hq-skin-btn,
html[data-skin="ink"] #hq-skin-btn{
  box-shadow:0 1px 3px rgba(20,70,110,.16);
}
html[data-skin="light"] #hq-skin-btn:hover,
html[data-skin="ink"] #hq-skin-btn:hover{
  box-shadow:0 2px 6px rgba(20,70,110,.22);
}

/* 进容器自然流（驾驶舱 tab 栏 / 视频墙顶栏 / 组态页顶栏 / 门户快捷条 / 一张图层级组）：
   取消浮层定位，位置交给容器的 flex 排版 —— 这样永远不会和页面上已有的浮层撞车。 */
#hq-skin-btn.hqs-inline{position:relative;right:auto;top:auto;left:auto;bottom:auto;}
