@charset "utf-8";
/* finesse · register=commerce+product · A=冷白工业蓝·单强调色·双轨用形状区分 · B=系统中文栈·价格即最大的字 · C=目录式楼层壳 · D=零依赖·单层光晕+首屏全息核心+器件细节·Canvas2D 工地蓝图 · E=建材样本卡程序化 SVG · SOUL=4 SPECTACLE=5 DENSITY=7
   第 2 版（客户 2026-09-30：「统一要科幻 AI 高科技装逼风格的」）：火力全压背景，
   六个固定层铺满全站；后来发现 .hero 一块 `var(--page)` 不透明底把它们整片盖死，
   撤掉之后首屏才见得到。
   第 3 版（2026-10-07）：六层平铺还是被否 ——「这个背景太乱了 换种方案 要AI科幻风的」。
   整组撤成一层光晕，「AI 感」改做进首屏一个核心 + 器件级细节，见 §12。 */

/* ════════════════════════════════════════════════════════════════════
   全站唯一的样式表。十一个页面共用。

   底色不是纯白也不是纯灰：纸面是向蓝偏的冷灰，卡片是带一点冷调的
   近白。这是 product-ui 里最要紧的一条 —— 纯灰底 + 纯白卡 + 硬描边，
   是「廉价后台」最典型的三个信号凑在一起。

   **全站一套令牌，包括数据大屏。** 大屏原先在 .screen 作用域里换了一整套
   暗色令牌，于是全站就那一页颜色不一样 —— 客户 2026-09-30 说不好看，
   撤了。现在大屏跟着 :root 走浅色，蓝色这一支在哪儿都一样。
   ════════════════════════════════════════════════════════════════════ */

/* ══ 1. 令牌 ═══════════════════════════════════════════════════════ */
:root {
  /* 不引任何 webfont。商品名是联盟同步刷进来的，每同步一次就可能冒出新字，
     子集化在这里是维护陷阱：漏字会静默回退成另一种中文字体，同页两种字体挨着排。 */
  --font: -apple-system, BlinkMacSystemFont, "PingFang SC", "HarmonyOS Sans SC",
    "Microsoft YaHei", "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  --mono: ui-monospace, "SF Mono", "Cascadia Mono", Consolas, "Liberation Mono", monospace;

  --page: #eaeef7;
  --bg: #f7faff;
  --panel-2: #f2f5fa;
  --panel-3: #e6ebf4;

  --border: rgba(20, 32, 56, .08);
  --border-2: rgba(20, 32, 56, .17);
  --border-3: rgba(20, 32, 56, .27);

  --ink-1: #121a2b;
  --ink-2: #3a465c;
  --ink-3: #69768c;
  --ink-4: #8e99ac;

  --accent: #2B54D6;
  --accent-2: #2249B4;
  --accent-ink: #1B3A8F;
  --accent-soft: rgba(45, 91, 216, .09);
  --accent-line: rgba(45, 91, 216, .22);
  --on-accent: #fbfcfe;
  --glow: rgba(45, 91, 216, .28);

  /* 科技风的两支辅色。**只用这两支，不许彩虹渐变** —— 炫酷和廉价的
     差别一半就在这条上。青色只用在「活的」东西上（实时、脉冲、光带），
     静态的界面元素一律走 --accent。 */
  --cyan: #2FC3DE;
  --accent-lt: #5FE3F5;
  --cyan-soft: rgba(47, 195, 222, .16);
  --live: #1E9DB8;
  /* 背景层的网格线。大屏的 Canvas 蓝图也读它，两边必须是同一个值。 */
  --grid: rgba(45, 91, 216, .16);

  --up: #2F7A55;   --up-soft: rgba(47, 122, 85, .10);
  --down: #C0453C; --down-soft: rgba(192, 69, 60, .10);
  --warn: #B77A16; --warn-soft: rgba(183, 122, 22, .11);

  --shadow: 0 1px 2px rgba(20, 34, 64, .05), 0 10px 26px -20px rgba(20, 34, 64, .22);
  --shadow-md: 0 2px 4px rgba(20, 34, 64, .05), 0 18px 42px -26px rgba(20, 34, 64, .30);
  --shadow-lg: 0 40px 90px -50px rgba(20, 34, 64, .34);

  --r-xs: 9px; --r-sm: 13px; --r: 20px; --r-lg: 32px; --r-pill: 999px;

  /* 后台/工作台外壳的深色窄栏。跟纸面同色相（蓝），不是中性黑。 */
  --rail: #101725; --rail-2: #18202f;
  --rail-line: rgba(255, 255, 255, .07);
  --rail-ink: #8b98ad; --rail-ink-2: #5f6d84; --rail-active: #fbfcfe;

  --wrap: 1280px;
  --head-h: 64px;
  /* .93 —— 撤掉顶栏的 blur(14px) 之后靠它自己挡住底下滚过的内容 */
  --head-bg: rgba(251, 252, 254, .93);

  --t-xs: 12px; --t-sm: 13px; --t-md: 14px; --t-base: 15px;
  --t-lg: 17px; --t-xl: 20px; --t-2xl: 26px; --t-3xl: 34px;
}

/* ══ 2. 基底 ═══════════════════════════════════════════════════════ */
*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; }
body {
  margin: 0;
  font-family: var(--font);
  font-size: var(--t-base);
  line-height: 1.65;
  color: var(--ink-1);
  /* 全站科技风：蓝白渐变 + 右上青蓝光晕 + 左下冷光。
     **不要 background-attachment: fixed** —— iOS Safari 上这个是坏的
     （背景会跟着滚动并抖动），而且这里根本不需要：body 的背景会传播到
     画布上，定位区本来就是一整个视口。 */
  background:
    radial-gradient(1200px 620px at 85% -8%, rgba(45, 91, 216, .13), transparent 60%),
    radial-gradient(950px 520px at -8% 108%, rgba(63, 197, 232, .11), transparent 55%),
    linear-gradient(160deg, #f7faff 0%, #eef3fd 45%, #e7eefc 100%);
  /* clip 而不是 hidden：hidden 会把 sticky 顶栏一起废掉 */
  overflow-x: clip;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

/* ══ 2.5 背景：一层光晕 ═══════════════════════════════════════════
   2026-10-07 客户否了上一版：「这个背景太乱了 换种方案 要AI科幻风的」。
   病根不是不够花，是**花铺得太满** —— 极光 / 全息网 / 扫描线 / 星点 /
   收边 / 扫光六层平铺满全站、各动各的，没有主次，看着就是乱。

   这一轮先做减法：**铺满的纹样整组撤掉**（连同 fx-1/2/3 强度开关），
   全站只留下面这一层很淡的光晕。「AI 感」分两处落地：
     · 首屏一个主视觉 —— index.html 的 .ai-core（样式在 §12）
     · 其余全落到器件级细节上 —— 顶栏电源线 / 仪表格数据条 / 终端页脚（§12）

   ⚠ 上一版的教训还适用：背景持续动画 = 全站每个 backdrop-filter 的
   背景永远在动、永远缓存不了。所以这层照旧**只走 transform**，
   全部 fixed + pointer-events:none + z-index:0（内容层 main/.site-foot 是 1）。 */
.ai-wash { position: fixed; inset: 0; z-index: 0; pointer-events: none; overflow: hidden; }
.ai-wash i { position: absolute; display: block; will-change: transform; }
.ai-wash i:nth-child(1) {
  left: -20vw; top: -32vh; width: 92vw; height: 92vh;
  background: radial-gradient(closest-side, rgba(43, 84, 214, .26), rgba(43, 84, 214, 0) 74%);
  animation: aiw-a 78s ease-in-out infinite alternate;
}
.ai-wash i:nth-child(2) {
  right: -22vw; top: -10vh; width: 84vw; height: 84vh;
  background: radial-gradient(closest-side, rgba(47, 195, 222, .20), rgba(47, 195, 222, 0) 72%);
  animation: aiw-b 96s ease-in-out infinite alternate;
}
.ai-wash i:nth-child(3) {
  left: 4vw; bottom: -36vh; width: 88vw; height: 74vh;
  background: radial-gradient(closest-side, rgba(76, 123, 255, .15), rgba(76, 123, 255, 0) 75%);
  animation: aiw-a 124s ease-in-out infinite alternate-reverse;
}
@keyframes aiw-a {
  from { transform: translate3d(0, 0, 0) scale(1); }
  to   { transform: translate3d(9vw, 7vh, 0) scale(1.15); }
}
@keyframes aiw-b {
  from { transform: translate3d(0, 0, 0) scale(1.12); }
  to   { transform: translate3d(-10vw, -8vh, 0) scale(.92); }
}
@media (prefers-reduced-motion: reduce) { .ai-wash i { animation: none; } }

/* 背景全在 z-index 0：正文内容抬到它上面（顶栏 z-index 60 已在最上） */
main, .site-foot { position: relative; z-index: 1; }
img, svg, canvas, video { max-width: 100%; display: block; }
a { color: inherit; text-decoration: none; }
button, input, select, textarea { font: inherit; color: inherit; }
button { cursor: pointer; }
h1, h2, h3, h4, p, figure { margin: 0; }
ul, ol { margin: 0; padding: 0; list-style: none; }
table { border-collapse: collapse; width: 100%; }
hr { border: 0; border-top: 1px solid var(--border); margin: 0; }
::selection { background: var(--accent-soft); }

/* 所有能点的东西共享同一套可见焦点环。键盘用户能看见自己在哪。 */
:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
:focus:not(:focus-visible) { outline: none; }

.wrap { width: 100%; max-width: var(--wrap); margin: 0 auto; padding: 0 24px; }
.wrap-narrow { max-width: 860px; }
.sec { padding: 56px 0; }
.sec-tight { padding: 36px 0; }
.skip { position: absolute; left: -9999px; top: 0; z-index: 200; }
.skip:focus {
  left: 12px; top: 12px; padding: 10px 16px; background: var(--bg);
  border: 1px solid var(--accent); border-radius: var(--r-sm); font-size: var(--t-sm);
}

/* 排版 */
.h1 { font-size: var(--t-3xl); font-weight: 700; letter-spacing: -.02em; line-height: 1.22; overflow-wrap: anywhere; }
.h2 { font-size: var(--t-2xl); font-weight: 700; letter-spacing: -.015em; line-height: 1.3; overflow-wrap: anywhere; }
.h3 { font-size: var(--t-lg); font-weight: 600; line-height: 1.4; overflow-wrap: anywhere; }
.h4 { font-size: var(--t-base); font-weight: 600; line-height: 1.45; }
.lede { font-size: var(--t-lg); color: var(--ink-2); line-height: 1.7; }
.body { color: var(--ink-2); }
.sub { font-size: var(--t-md); color: var(--ink-3); }
.tiny { font-size: var(--t-xs); color: var(--ink-3); }
.num { font-variant-numeric: tabular-nums; font-feature-settings: "tnum"; }
.eyebrow {
  font-size: var(--t-xs); font-weight: 600; letter-spacing: .1em;
  text-transform: uppercase; color: var(--ink-3);
}
.mono { font-family: var(--mono); font-size: var(--t-sm); }

.sec-head { display: flex; align-items: flex-end; justify-content: space-between; gap: 20px; margin-bottom: 22px; flex-wrap: wrap; }
.sec-head .h2 { margin-bottom: 4px; }
.rule { height: 1px; background: var(--border); }

/* ══ 3. 按钮 ═══════════════════════════════════════════════════════ */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 7px;
  height: 44px; padding: 0 20px;
  border: 1px solid transparent; border-radius: var(--r-sm);
  background: transparent; color: var(--ink-1);
  font-size: var(--t-md); font-weight: 600; line-height: 1; white-space: nowrap;
  text-decoration: none; cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  transition: background .16s ease, border-color .16s ease, color .16s ease,
              box-shadow .16s ease, transform .1s ease;
}
.btn:active { transform: translateY(1px); }
.btn[disabled], .btn[aria-disabled="true"] { opacity: .42; cursor: not-allowed; transform: none; pointer-events: none; }
.btn svg { width: 16px; height: 16px; flex: none; }

.btn-primary {
  background: var(--accent); color: var(--on-accent);
  box-shadow: 0 1px 2px rgba(20, 34, 64, .10), 0 12px 26px -16px var(--glow);
}
.btn-primary:hover { background: var(--accent-2); }
.btn-outline { background: var(--bg); color: var(--ink-1); border-color: var(--border-2); }
.btn-outline:hover { border-color: var(--accent-line); color: var(--accent); background: var(--accent-soft); }
.btn-ghost { color: var(--ink-2); }
.btn-ghost:hover { background: var(--panel-2); color: var(--ink-1); }
.btn-quiet { color: var(--ink-3); font-weight: 500; }
.btn-quiet:hover { color: var(--accent); }
.btn-sm { height: 36px; padding: 0 14px; font-size: var(--t-sm); border-radius: var(--r-xs); }
.btn-lg { height: 52px; padding: 0 30px; font-size: var(--t-base); border-radius: var(--r); }
.btn-block { width: 100%; }
.btn-row { display: flex; gap: 10px; flex-wrap: wrap; }

/* ══ 4. 标签 · 徽标 · 价格 ═════════════════════════════════════════ */
.tag {
  display: inline-flex; align-items: center; gap: 5px;
  padding: 3px 10px; border-radius: var(--r-pill);
  background: var(--panel-2); border: 1px solid var(--border);
  font-size: var(--t-xs); color: var(--ink-2); line-height: 1.6; white-space: nowrap;
}
.tag-accent { background: var(--accent-soft); border-color: var(--accent-line); color: var(--accent-ink); }
.tag-up { background: var(--up-soft); border-color: transparent; color: var(--up); }
.tag-warn { background: var(--warn-soft); border-color: transparent; color: var(--warn); }
.tag-down { background: var(--down-soft); border-color: transparent; color: var(--down); }
.tag-flat { background: transparent; border-color: var(--border-2); color: var(--ink-3); }
.tag-row { display: flex; flex-wrap: wrap; gap: 6px; }

/* 双轨制的两种标 —— 靠形状和图标分，不靠第二个色相。
   灰度和色盲模式下：联盟是描边空心的，自营是实心填充的。 */
.src {
  display: inline-flex; align-items: center; gap: 5px;
  padding: 3px 9px 3px 7px; border-radius: var(--r-pill);
  font-size: 11px; font-weight: 600; letter-spacing: .01em; line-height: 1.55; white-space: nowrap;
}
.src svg { width: 12px; height: 12px; flex: none; }
.src-alliance { background: transparent; border: 1px solid var(--border-2); color: var(--ink-2); }
.src-merchant { background: var(--accent-soft); border: 1px solid var(--accent-line); color: var(--accent-ink); }

/* 价格是全站最大的字。800 字重 + 等宽数字，同一套字体，不引等宽字体。 */
.price {
  display: inline-flex; align-items: baseline; gap: 1px;
  font-weight: 800; font-size: 26px; letter-spacing: -.025em;
  color: var(--ink-1); font-variant-numeric: tabular-nums;
}
.price .cur { font-size: .56em; font-weight: 700; }
.price .unit { font-size: var(--t-xs); font-weight: 500; color: var(--ink-3); letter-spacing: 0; margin-left: 3px; }
.price-lg { font-size: 36px; }
/* 市场参考价，平铺一行小字。不做划线 —— 划线价必须是真收过的价。 */
.market { font-size: var(--t-xs); color: var(--ink-3); }
.market b { font-weight: 600; color: var(--ink-2); font-variant-numeric: tabular-nums; }

/* ══ 5. 外壳：顶栏 · 导航 · 页脚 · 购物车抽屉 ══════════════════════ */
.site-head {
  position: sticky; top: 0; z-index: 60;
  background: var(--head-bg);
  border-bottom: 1px solid var(--border);
}
.site-head .bar {
  height: var(--head-h); display: flex; align-items: center; gap: 20px;
}
.brand { display: flex; align-items: center; gap: 12px; flex: none; }
.brand-mark {
  width: 40px; height: 40px; flex: none;
  display: grid; place-items: center;
  filter: drop-shadow(0 0 10px rgba(62, 107, 232, .38));
}
.brand-mark svg { display: block; }
.brand-txt { display: flex; flex-direction: column; line-height: 1.15; min-width: 0; }
.brand-name {
  font-size: 20px; font-weight: 800; letter-spacing: -.01em;
  color: var(--accent);
  text-shadow: 0 0 16px var(--glow);
}
.brand-sub { font-size: 11px; color: var(--ink-3); letter-spacing: .02em; }

.nav { display: flex; align-items: center; gap: 2px; margin-left: 16px; flex: 1; min-width: 0; justify-content: space-between; }
.nav a {
  padding: 9px 16px; border-radius: var(--r-xs);
  font-size: var(--t-base); font-weight: 600; color: var(--ink-2);
  transition: background .15s ease, color .15s ease;
}
.nav a:hover { background: var(--panel-2); color: var(--ink-1); }
.nav a[aria-current="page"] { color: var(--accent); background: var(--accent-soft); font-weight: 600; }

.head-acts { display: flex; align-items: center; gap: 8px; flex: none; }
.icon-btn {
  position: relative; width: 40px; height: 40px; border-radius: var(--r-sm);
  border: 1px solid var(--border); background: var(--bg); color: var(--ink-2);
  display: grid; place-items: center;
  transition: border-color .15s ease, color .15s ease, background .15s ease;
}
.icon-btn:hover { border-color: var(--accent-line); color: var(--accent); background: var(--accent-soft); }
.icon-btn svg { width: 18px; height: 18px; }
.cart-badge {
  position: absolute; top: -5px; right: -5px; min-width: 18px; height: 18px;
  padding: 0 5px; border-radius: var(--r-pill);
  background: var(--accent); color: var(--on-accent);
  font-size: 11px; font-weight: 700; line-height: 18px; text-align: center;
  font-variant-numeric: tabular-nums; display: none;
}
.burger { display: none; }

/* 手机抽屉导航 */
.m-nav {
  display: none; border-top: 1px solid var(--border); background: var(--bg);
  padding: 8px 0 14px;
}
.m-nav.open { display: block; }
.m-nav a {
  display: block; padding: 12px 24px; font-size: var(--t-base); color: var(--ink-2);
  border-radius: 0;
}
.m-nav a:hover, .m-nav a[aria-current="page"] { background: var(--accent-soft); color: var(--accent); font-weight: 600; }

/* 页脚：只有著作权。全站不出现地址、电话、邮箱 —— tools/check.mjs 会硬拦。 */
.site-foot { margin-top: 72px; border-top: 1px solid var(--border); background: var(--bg); }
.foot-in {
  padding: 40px 0 44px; display: flex; align-items: center;
  justify-content: space-between; gap: 24px; flex-wrap: wrap;
}
.foot-slogan { font-size: var(--t-md); color: var(--ink-3); }
.copyright {
  font-size: var(--t-sm); color: var(--ink-3);
  font-variant-numeric: tabular-nums; letter-spacing: .01em;
}
.foot-links { display: flex; gap: 18px; flex-wrap: wrap; }
.foot-links a { font-size: var(--t-sm); color: var(--ink-3); }
.foot-links a:hover { color: var(--accent); }

/* 遮罩 + 右侧抽屉 */
.mask {
  position: fixed; inset: 0; z-index: 80;
  background: rgba(12, 20, 36, .34);
  backdrop-filter: blur(2px); -webkit-backdrop-filter: blur(2px);
}
.drawer {
  position: fixed; top: 0; right: 0; bottom: 0; z-index: 81;
  width: min(420px, 100%);
  background: var(--bg); border-left: 1px solid var(--border);
  box-shadow: var(--shadow-lg);
  display: flex; flex-direction: column;
  transform: translateX(102%);
  transition: transform .28s cubic-bezier(.32, .72, 0, 1);
}
.drawer.open { transform: none; }
.drawer-head {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  padding: 18px 20px; border-bottom: 1px solid var(--border); flex: none;
}
.drawer-body { flex: 1; overflow-y: auto; padding: 16px 20px; min-height: 0; }
.drawer-foot {
  flex: none; padding: 16px 20px 20px; border-top: 1px solid var(--border);
  background: var(--panel-2);
}
.drawer-foot .sum { display: flex; align-items: baseline; justify-content: space-between; margin-bottom: 12px; }
.hide { display: none !important; }

/* ══ 6. 面板 · 卡片 · 表格（product register）═════════════════════ */
/* ⚠ **这些面上不许再加 backdrop-filter。**（2026-09-30 撤掉一整批，理由记这儿）
   模糊的代价是每帧「读背景 → 糊 → 合成」。底下那六个背景层是**一直在动**的，
   于是这层模糊**永远没法缓存，逐帧重算** —— 首页当时有 90 张卡各带一个
   blur(12px)，直接把页面拖卡。改背景之前它们算一次就存住了，是背景开始
   持续动画之后才变成这样，所以「加了背景特效反而卡了」。
   而且底色到 .84 之后，12px 的模糊在视觉上本来就几乎不存在：
   0.76×251+0.24×234=247.0 vs 0.84×251+0.16×234=248.3，差 1.3/255。
   只有**瞬态遮罩**（.mask / .ai-scrim）和**单个小元素**（.aiv-tag）才留模糊 ——
   那儿是真看得见的效果，且不是每帧都在。check.mjs 有闸盯着这个数。 */
.panel {
  background: rgba(251, 252, 254, .84); border: 1px solid rgba(255, 255, 255, .55);
  border-radius: var(--r); box-shadow: 0 1px 2px rgba(20, 34, 64, .05), 0 10px 26px -20px rgba(20, 34, 64, .22);
}
.panel-pad { padding: 22px 24px; }
.panel-head {
  display: flex; align-items: center; justify-content: space-between; gap: 14px;
  padding: 16px 22px; border-bottom: 1px solid var(--border); flex-wrap: wrap;
}
.panel-head .h4 { flex: none; }

.grid { display: grid; gap: 18px; }
.g2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.g3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.g4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }

/* KPI 卡：图标 chip + 标签 + 大数字。解剖照 product-ui §0.3。 */
.kpi { background: rgba(251, 252, 254, .84); border: 1px solid rgba(255, 255, 255, .55); border-radius: var(--r); padding: 18px 20px; min-width: 0; box-shadow: 0 1px 2px rgba(20, 34, 64, .05), 0 10px 26px -20px rgba(20, 34, 64, .22); }
.kpi-top { display: flex; align-items: center; gap: 9px; margin-bottom: 12px; }
.kpi-ico {
  width: 30px; height: 30px; border-radius: 9px; flex: none;
  display: grid; place-items: center;
  background: var(--accent-soft); color: var(--accent);
}
.kpi-ico svg { width: 16px; height: 16px; }
.kpi-label { font-size: var(--t-sm); color: var(--ink-3); }
.kpi-val {
  font-size: 30px; font-weight: 800; letter-spacing: -.03em; line-height: 1.1;
  font-variant-numeric: tabular-nums;
}
.kpi-val .u { font-size: var(--t-sm); font-weight: 600; color: var(--ink-3); letter-spacing: 0; margin-left: 3px; }
.kpi-foot { margin-top: 8px; font-size: var(--t-xs); color: var(--ink-3); }

/* 表格：数字右对齐，密度锁一行 */
.tbl { font-size: var(--t-md); }
.tbl th {
  text-align: left; font-size: var(--t-xs); font-weight: 600; color: var(--ink-3);
  letter-spacing: .04em; padding: 10px 14px; border-bottom: 1px solid var(--border);
  background: var(--panel-2); white-space: nowrap;
}
.tbl td { padding: 11px 14px; border-bottom: 1px solid var(--border); color: var(--ink-2); vertical-align: middle; }
.tbl tbody tr:last-child td { border-bottom: 0; }
.tbl tbody tr:hover { background: var(--panel-2); }
.tbl .r { text-align: right; font-variant-numeric: tabular-nums; }
.tbl .n { color: var(--ink-1); font-weight: 600; }
.tbl-wrap { overflow-x: auto; border: 1px solid var(--border); border-radius: var(--r); background: var(--bg); }

/* 空状态：构图过的，不是一行灰字 */
.empty {
  display: flex; flex-direction: column; align-items: center; gap: 10px;
  padding: 44px 24px; text-align: center;
}
.empty img { width: 190px; opacity: .92; margin-bottom: 2px; }
.empty p { color: var(--ink-3); font-size: var(--t-md); max-width: 34em; }

/* 进度条（类目占比用） */
.bar { height: 7px; border-radius: var(--r-pill); background: var(--panel-3); overflow: hidden; }
.bar > i { display: block; height: 100%; background: var(--accent); border-radius: inherit; transition: width .6s cubic-bezier(.32, .72, 0, 1); }

/* ══ 7. 表单 ═══════════════════════════════════════════════════════ */
.field { display: flex; flex-direction: column; gap: 7px; min-width: 0; }
.field > label { font-size: var(--t-sm); font-weight: 600; color: var(--ink-2); }
.field .req { color: var(--down); margin-left: 3px; }
.field .hint { font-size: var(--t-xs); color: var(--ink-3); line-height: 1.6; }
.input, .textarea, .select {
  width: 100%; height: 44px; padding: 0 13px;
  background: var(--bg); color: var(--ink-1);
  border: 1px solid var(--border-2); border-radius: var(--r-sm);
  transition: border-color .15s ease, box-shadow .15s ease, background .15s ease;
  -webkit-appearance: none; appearance: none;
}
.textarea { height: auto; min-height: 104px; padding: 11px 13px; line-height: 1.65; resize: vertical; }
.select { padding-right: 34px; background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'%3E%3Cpath d='M1 1.5 6 6.5 11 1.5' fill='none' stroke='%2369768c' stroke-width='1.6' stroke-linecap='round'/%3E%3C/svg%3E"); background-repeat: no-repeat; background-position: right 13px center; }
.input::placeholder, .textarea::placeholder { color: var(--ink-4); }
.input:hover, .textarea:hover, .select:hover { border-color: var(--border-3); }
.input:focus, .textarea:focus, .select:focus {
  outline: none; border-color: var(--accent); background: var(--bg);
  box-shadow: 0 0 0 3px var(--accent-soft);
}
.input[disabled], .textarea[disabled], .select[disabled] { background: var(--panel-2); color: var(--ink-4); cursor: not-allowed; }
.input[aria-invalid="true"] { border-color: var(--down); box-shadow: 0 0 0 3px var(--down-soft); }
.err { font-size: var(--t-xs); color: var(--down); display: flex; align-items: center; gap: 5px; }

/* 单选卡组：选项之间有真实差别的时候用它，不是普通 radio 列表 */
.radiocards { display: grid; grid-template-columns: repeat(auto-fit, minmax(210px, 1fr)); gap: 12px; }
.rcard {
  position: relative; display: block; cursor: pointer;
  padding: 15px 16px 15px 42px;
  background: var(--bg); border: 1px solid var(--border-2); border-radius: var(--r-sm);
  transition: border-color .15s ease, background .15s ease, box-shadow .15s ease;
}
.rcard:hover { border-color: var(--border-3); }
.rcard input { position: absolute; opacity: 0; width: 0; height: 0; }
.rcard .dot {
  position: absolute; left: 16px; top: 17px; width: 17px; height: 17px;
  border-radius: 50%; border: 1.5px solid var(--border-3); background: var(--bg);
  transition: border-color .15s ease, box-shadow .15s ease;
}
.rcard .dot::after {
  content: ""; position: absolute; inset: 3px; border-radius: 50%;
  background: var(--accent); transform: scale(0); transition: transform .16s cubic-bezier(.32, .72, 0, 1);
}
.rcard .t { font-size: var(--t-md); font-weight: 600; display: block; }
.rcard .c { font-size: var(--t-xs); color: var(--ink-3); margin-top: 3px; line-height: 1.6; display: block; }
.rcard:has(input:checked) { border-color: var(--accent); background: var(--accent-soft); box-shadow: 0 0 0 1px var(--accent-line); }
.rcard:has(input:checked) .dot { border-color: var(--accent); }
.rcard:has(input:checked) .dot::after { transform: scale(1); }
.rcard:has(input:focus-visible) { outline: 2px solid var(--accent); outline-offset: 2px; }

/* ══ 8. 商城 ═══════════════════════════════════════════════════════ */

/* ── 首页：目录式，不是海报式。没有全屏轮播。── */
.hero {
  padding: 52px 0 40px;
  border-bottom: 1px solid var(--border);
  /* 这里原先是 `var(--page)` 打底 —— 一块**不透明**的浅蓝。它正好盖在
     首屏正中，六个背景层全被它挡死，站上看起来就像根本没做背景。
     首屏是访客看最久的一块，特效必须在这儿看得见，所以底色撤掉：
     极光、网格、星点直接透上来。分界靠下面那条 border 就够了。 */
  background: radial-gradient(1100px 340px at 12% -20%, var(--accent-soft), transparent 70%);
}
.hero-in { display: grid; grid-template-columns: minmax(0, 1.35fr) minmax(0, 1fr); gap: 48px; align-items: center; }
.hero .h1 { margin-bottom: 14px; font-size: 46px; line-height: 1.16; letter-spacing: -.02em; }
.hero .lede { max-width: 32em; }
.hero-acts { display: flex; gap: 12px; margin-top: 26px; flex-wrap: wrap; }
/* 数据条：四个真数字，直接从 seed 数出来 */
.databar { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 1px; background: rgba(255, 255, 255, .72); border: 1px solid rgba(255, 255, 255, .55); border-radius: var(--r); overflow: hidden; }
/* 格子 .72 → .88：容器不糊了，格子透出来的背景网格线会变清晰，提不透明度压回去。
   0.12×20≈2.4/255 的残留，跟原来糊过的观感对齐。见 §6 顶上那段说明。 */
.databar div { background: rgba(251, 252, 254, .88); padding: 12px 14px; }
.databar .v { font-size: 22px; font-weight: 800; letter-spacing: -.03em; font-variant-numeric: tabular-nums; }
.databar .v .u { font-size: 11px; font-weight: 600; color: var(--ink-3); letter-spacing: 0; margin-left: 2px; }
.databar .k { font-size: 11px; color: var(--ink-3); margin-top: 2px; }

/* 厂家详情页头那一块。行内写 grid-template-columns 会压过所有媒体查询，
   所以尺寸放这儿：两列时每格至少要有 146px，不然 27px 的六位销量（12,480单）
   就把格子顶破。窄屏让它独占一行，再窄走上面那条单列规则。 */
.databar-side { flex: 0 1 320px; min-width: 0; }

/* 分类树 */
/* 分类树。类目几个由 seed.cats 决定，这里不写死数字（客户 2026-09-30：
   「类目几个就是几个」）。分隔线画在格子上（1px 投影），不靠容器底色透出来 ——
   容器底色那套在最后一行不满时会露出灰带（格子数分不到整数行时就会）。
   投影画在 gap 里，相邻两格的投影落在同一个像素上，不会double。 */
.catgrid { display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 1px; background: rgba(251, 252, 254, .72); border: 1px solid rgba(255, 255, 255, .55); border-radius: var(--r); overflow: hidden; }
/* 同 .databar：容器撤了 blur，格子提不透明度把透出来的网格线压回去 */
.catgrid a, .catgrid button.cat-svc { background: rgba(251, 252, 254, .88); padding: 15px 16px; transition: background .15s ease; min-width: 0; box-shadow: 0 0 0 1px var(--border); }
.catgrid button.cat-svc { border: 0; font: inherit; text-align: left; cursor: pointer; color: inherit; }
.catgrid a:hover, .catgrid button.cat-svc:hover { background: var(--accent-soft); }
.catgrid .n { font-size: var(--t-md); font-weight: 600; }
.catgrid .d { font-size: var(--t-xs); color: var(--ink-3); margin-top: 2px; overflow-wrap: anywhere; }
.catgrid .c { font-size: var(--t-xs); color: var(--ink-4); margin-top: 6px; font-variant-numeric: tabular-nums; }

/* 楼层：头带 + 横向商品轨道 */
.floor { margin-bottom: 46px; }
.floor-head {
  position: relative; overflow: hidden; isolation: isolate;
  border: 1px solid var(--border); border-radius: var(--r-lg);
  min-height: 176px; display: flex; flex-direction: column;
  align-items: flex-start; justify-content: center;
  padding: 30px 40px; margin-bottom: 20px;
}
.floor-head > img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; z-index: -1; }
.floor-txt { min-width: 0; max-width: min(100%, 40em); }
.floor-head .h2 { margin-bottom: 5px; }
.floor-head .sub { max-width: 34em; }
.floor-head .note { margin-top: 10px; }
.floor-head .go { position: absolute; right: 40px; bottom: 30px; }

.track {
  display: grid; grid-auto-flow: column; grid-auto-columns: 244px; gap: 18px;
  overflow-x: auto; overscroll-behavior-x: contain;
  scroll-snap-type: x proximity; padding: 4px 4px 14px; margin: -4px -4px 0;
  scrollbar-width: thin;
}
.track > * { scroll-snap-align: start; }
.track::-webkit-scrollbar { height: 8px; }
.track::-webkit-scrollbar-thumb { background: var(--panel-3); border-radius: var(--r-pill); }
.track::-webkit-scrollbar-track { background: transparent; }

/* ── 商品卡 ── */
.gcard {
  position: relative; display: flex; flex-direction: column; min-width: 0;
  /* 这里原先是 `backdrop-filter: blur(12px)` —— 全站最贵的一处：首页 90 张、
     商城页 91 张，每张每帧糊一次背景。撤掉，底 .76 → .84 补等效不透明度。
     见 §6 顶上那段。**别再给商品卡加回来。** */
  background: rgba(251, 252, 254, .84); border: 1px solid rgba(255, 255, 255, .55); border-radius: var(--r);
  overflow: hidden;
  box-shadow: 0 1px 2px rgba(20, 34, 64, .05), 0 10px 26px -20px rgba(20, 34, 64, .22);
  transition: border-color .18s ease, box-shadow .18s ease, transform .18s ease;
}
.gcard:hover { border-color: var(--accent-line); box-shadow: var(--shadow-md); transform: translateY(-2px); }
.gcard:hover .gcard-title { color: var(--accent); }
.gcard-img { position: relative; display: block; aspect-ratio: 4 / 3; background: var(--panel-2); overflow: hidden; }
.gcard-img img { width: 100%; height: 100%; object-fit: cover; }
/* 这处 blur(6px) 是**纯白做**：自己的底 `var(--bg)` 根本不透明，透不出任何东西，
   视觉上一点用都没有 —— 但每张卡一个，首页 90 个、商城页 91 个，每帧照糊。删。 */
.gcard-img .src { position: absolute; left: 10px; top: 10px; background: var(--bg); }
.gcard-img .src-alliance { background: rgba(251, 252, 254, .9); }
.gcard-body { display: flex; flex-direction: column; gap: 7px; padding: 13px 15px 15px; flex: 1; min-width: 0; }
.gcard-title { font-size: var(--t-md); font-weight: 600; line-height: 1.5; color: var(--ink-1); overflow-wrap: anywhere; }
.gcard-spec { font-size: var(--t-xs); color: var(--ink-3); overflow-wrap: anywhere; }
.gcard-meta { margin-top: 4px; font-size: var(--t-xs); color: var(--ink-3); }
.gcard-meta b { color: var(--accent); font-weight: 600; }
.gcard-brief {
  font-size: var(--t-xs); color: var(--ink-3); line-height: 1.6;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}
/* 挤不下就换行。价格和按钮排在一行、按钮又不肯缩的时候，
   卡片的 min-content 会顶到 154px —— 320px 屏上两列只有 131px，整页就被顶宽。 */
.gcard-foot {
  display: flex; align-items: flex-end; justify-content: space-between;
  gap: 10px; margin-top: auto; padding-top: 4px; flex-wrap: wrap;
}
.gcard-acts { display: flex; gap: 6px; flex: 0 1 auto; min-width: 0; }
.gcard-acts .btn { padding-left: 11px; padding-right: 11px; min-width: 0; }

/* minmax 的下限不能是死数：236px 塞不进 275px 的可用宽度时，
   轨道宁可撑破容器也不缩（1fr 的 min-width 是 auto）。min(236px, 100%) 才是「至少 236，塞不下就占满」。 */
.grid-goods { display: grid; grid-template-columns: repeat(auto-fill, minmax(min(236px, 100%), 1fr)); gap: 18px; }
.grid-goods > * { min-width: 0; }

/* ── 列表页：左筛选栏 ── */
.listing { display: grid; grid-template-columns: 240px minmax(0, 1fr); gap: 26px; align-items: start; }
.filters { position: sticky; top: calc(var(--head-h) + 18px); display: flex; flex-direction: column; gap: 4px; }
.fgroup { border-bottom: 1px solid var(--border); padding: 14px 0; }
.fgroup:last-child { border-bottom: 0; }
.fgroup > .t { font-size: var(--t-sm); font-weight: 600; color: var(--ink-2); margin-bottom: 10px; }
.fopt { display: flex; align-items: center; gap: 8px; padding: 6px 0; cursor: pointer; font-size: var(--t-md); color: var(--ink-2); }
.fopt input { width: 16px; height: 16px; accent-color: var(--accent); flex: none; margin: 0; }
.fopt:hover { color: var(--ink-1); }
.fopt .c { margin-left: auto; font-size: var(--t-xs); color: var(--ink-4); font-variant-numeric: tabular-nums; }
.fopt:has(input:checked) { color: var(--accent); font-weight: 600; }

.listbar {
  display: flex; align-items: center; justify-content: space-between; gap: 14px;
  padding: 0 0 14px; border-bottom: 1px solid var(--border); margin-bottom: 18px; flex-wrap: wrap;
}
.listbar .cnt { font-size: var(--t-md); color: var(--ink-3); }
.listbar .cnt b { color: var(--ink-1); font-weight: 700; font-variant-numeric: tabular-nums; }
.search { position: relative; flex: 1 1 240px; max-width: 380px; min-width: 0; }
.search .input { padding-left: 38px; }
.search svg { position: absolute; left: 13px; top: 50%; transform: translateY(-50%); width: 16px; height: 16px; color: var(--ink-3); pointer-events: none; }

/* ── 详情页 ── */
.pdp { display: grid; grid-template-columns: minmax(0, 1.08fr) minmax(0, 1fr); gap: 44px; align-items: start; }
.gallery { display: flex; flex-direction: column; gap: 12px; position: sticky; top: calc(var(--head-h) + 18px); }
.gallery-main {
  border: 1px solid var(--border); border-radius: var(--r-lg); overflow: hidden;
  background: var(--panel-2); aspect-ratio: 4 / 3;
}
.gallery-main img { width: 100%; height: 100%; object-fit: cover; }
.thumbs { display: flex; gap: 10px; flex-wrap: wrap; }
.thumbs button {
  width: 72px; height: 72px; padding: 0; border-radius: var(--r-sm); overflow: hidden;
  border: 1px solid var(--border); background: var(--panel-2);
  transition: border-color .15s ease, box-shadow .15s ease;
}
.thumbs button[aria-pressed="true"] { border-color: var(--accent); box-shadow: 0 0 0 2px var(--accent-soft); }
.thumbs img { width: 100%; height: 100%; object-fit: cover; }

.pdp-info { display: flex; flex-direction: column; gap: 18px; min-width: 0; }
.pdp-price {
  display: flex; align-items: baseline; gap: 14px; flex-wrap: wrap;
  padding: 20px 22px; border: 1px solid var(--border); border-radius: var(--r);
  background: var(--bg); box-shadow: var(--shadow);
}
.spec-tbl { border: 1px solid var(--border); border-radius: var(--r); overflow: hidden; background: var(--bg); }
.spec-tbl dt, .spec-tbl dd { margin: 0; padding: 11px 16px; font-size: var(--t-md); border-bottom: 1px solid var(--border); }
.spec-tbl dt { color: var(--ink-3); background: var(--panel-2); width: 132px; }
.spec-tbl dd { color: var(--ink-1); }
.spec-row { display: grid; grid-template-columns: 132px minmax(0, 1fr); }
.spec-row:last-child dt, .spec-row:last-child dd { border-bottom: 0; }

.factline { display: flex; align-items: center; gap: 12px; padding: 14px 0; }
.factline .mark { width: 46px; height: 46px; border-radius: var(--r-sm); overflow: hidden; flex: none; border: 1px solid var(--border); }
.factline .mark img { width: 100%; height: 100%; object-fit: cover; }

/* 保障条 */
.guars { display: grid; grid-template-columns: repeat(auto-fit, minmax(224px, 1fr)); gap: 1px; background: var(--border); border: 1px solid var(--border); border-radius: var(--r); overflow: hidden; }
.guars > div { background: var(--bg); padding: 18px 20px; min-width: 0; }
.guars .t { font-size: var(--t-md); font-weight: 600; display: flex; align-items: center; gap: 7px; }
.guars .t svg { width: 16px; height: 16px; color: var(--up); flex: none; }
.guars .d { font-size: var(--t-sm); color: var(--ink-3); margin-top: 5px; line-height: 1.65; }

/* 厂家 / 装修公司卡 */
.fcard { display: flex; flex-direction: column; gap: 12px; padding: 20px; background: var(--bg); border: 1px solid var(--border); border-radius: var(--r); box-shadow: var(--shadow); min-width: 0; transition: border-color .18s ease, box-shadow .18s ease; }
.fcard:hover { border-color: var(--accent-line); box-shadow: var(--shadow-md); }
.fcard-top { display: flex; align-items: center; gap: 13px; min-width: 0; }
.fcard-mark { width: 54px; height: 54px; border-radius: var(--r-sm); overflow: hidden; flex: none; border: 1px solid var(--border); }
.fcard-mark img { width: 100%; height: 100%; object-fit: cover; }
.fcard-name { font-size: var(--t-lg); font-weight: 700; letter-spacing: -.01em; overflow-wrap: anywhere; }
.fcard-brief { font-size: var(--t-sm); color: var(--ink-2); line-height: 1.7; }
.fcard-foot { display: flex; align-items: center; justify-content: space-between; gap: 12px; margin-top: auto; padding-top: 4px; flex-wrap: wrap; }

/* ══ 9. 资讯 · 步骤 · 检查卡 ═══════════════════════════════════════ */
.newsgrid { display: grid; grid-template-columns: repeat(auto-fill, minmax(min(300px, 100%), 1fr)); gap: 20px; }
.ncard { display: flex; flex-direction: column; background: var(--bg); border: 1px solid var(--border); border-radius: var(--r); overflow: hidden; min-width: 0; transition: border-color .18s ease, box-shadow .18s ease, transform .18s ease; text-align: left; }
.ncard:hover { border-color: var(--accent-line); box-shadow: var(--shadow-md); transform: translateY(-2px); }
.ncard-img { aspect-ratio: 8 / 5; background: var(--panel-2); overflow: hidden; }
.ncard-img img { width: 100%; height: 100%; object-fit: cover; }
.ncard-body { display: flex; flex-direction: column; gap: 8px; padding: 16px 18px 18px; flex: 1; min-width: 0; }
.ncard-title { font-size: var(--t-base); font-weight: 600; line-height: 1.5; overflow-wrap: anywhere; }
.ncard-brief { font-size: var(--t-sm); color: var(--ink-3); line-height: 1.7; display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden; }

.modal {
  position: fixed; inset: 0; z-index: 90; display: grid; place-items: center; padding: 24px;
  background: rgba(12, 20, 36, .42); backdrop-filter: blur(3px); -webkit-backdrop-filter: blur(3px);
}
.modal-box {
  width: min(720px, 100%); max-height: min(84vh, 800px); overflow-y: auto;
  background: var(--bg); border: 1px solid var(--border); border-radius: var(--r-lg);
  box-shadow: var(--shadow-lg); padding: 32px 34px 36px;
}
.modal-box .prose p { margin: 0 0 1em; color: var(--ink-2); line-height: 1.85; }
.modal-box .prose p:last-child { margin-bottom: 0; }

/* 编号步骤：no 是真的顺序，发布前检查卡会引用回头 */
.steps { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 1px; background: var(--border); border: 1px solid var(--border); border-radius: var(--r); overflow: hidden; }
.step { background: var(--bg); padding: 20px; min-width: 0; }
.step .no {
  display: grid; place-items: center; width: 28px; height: 28px; border-radius: var(--r-xs);
  background: var(--accent-soft); color: var(--accent-ink);
  font-size: var(--t-sm); font-weight: 700; font-variant-numeric: tabular-nums; margin-bottom: 12px;
}
.step .n { font-size: var(--t-md); font-weight: 600; }
.step .d { font-size: var(--t-sm); color: var(--ink-3); margin-top: 5px; line-height: 1.65; }
.step .w { font-size: var(--t-xs); color: var(--ink-4); margin-top: 9px; }

/* 发布前检查卡：每一行写的是「值」，不是「OK」 */
.checks { border: 1px solid var(--border); border-radius: var(--r); overflow: hidden; background: var(--bg); }
.checks-head { display: flex; align-items: center; gap: 10px; padding: 14px 18px; background: var(--panel-2); border-bottom: 1px solid var(--border); }
.checks-head .n { font-size: var(--t-md); font-weight: 600; }
.checks-head .s { margin-left: auto; font-size: var(--t-xs); color: var(--ink-3); }
.check { display: flex; align-items: center; gap: 10px; padding: 11px 18px; border-bottom: 1px solid var(--border); font-size: var(--t-sm); }
.check:last-child { border-bottom: 0; }
.check .k { color: var(--ink-3); width: 96px; flex: none; }
.check .v { color: var(--ink-1); min-width: 0; flex: 1; overflow-wrap: anywhere; }
.check .i { width: 16px; height: 16px; flex: none; }
.check.ok .i { color: var(--up); }
.check.warn .i { color: var(--warn); }
.check.no { background: var(--down-soft); }
.check.no .i { color: var(--down); }
.check.no .v { color: var(--down); font-weight: 600; }
.check .fix { font-size: var(--t-xs); color: var(--accent); font-weight: 600; flex: none; }

/* 编号分区卡（后台 / 表单） */
.scard { border: 1px solid var(--border); border-radius: var(--r); background: var(--bg); overflow: hidden; }
.scard-head { display: flex; align-items: center; gap: 12px; padding: 16px 20px; border-bottom: 1px solid var(--border); flex-wrap: wrap; }
.scard-no {
  display: grid; place-items: center; width: 26px; height: 26px; border-radius: var(--r-xs); flex: none;
  background: var(--accent-soft); color: var(--accent-ink); font-size: var(--t-sm); font-weight: 700;
  font-variant-numeric: tabular-nums;
}
.scard-head .t { font-size: var(--t-base); font-weight: 600; }
.scard-head .x { margin-left: auto; font-size: var(--t-xs); color: var(--ink-3); }
.scard-body { padding: 20px; display: flex; flex-direction: column; gap: 16px; }

/* 后台外壳：深色窄栏 + 浅色内容区（同色相，不是中性黑） */
/* 后台门帘。记住：这是帘子不是锁 —— 静态站没有服务端，密码校验发生在浏览器里。
   它挡的是误点进来的人。真正的防线是这一页的地址不公开。 */
.lock-wrap { min-height: 100vh; display: grid; place-items: center; padding: 40px 20px; background: var(--page); }
.lock {
  width: 100%; max-width: 400px; background: var(--bg);
  border: 1px solid var(--border); border-radius: var(--r-lg);
  padding: 30px 30px 26px; box-shadow: var(--shadow-md);
}
.lock-brand { display: flex; align-items: center; gap: 12px; }
.lock-brand .brand-mark { width: 42px; height: 42px; border-radius: 13px; font-size: 19px; }
.lock a { color: var(--accent); }

/* 线索表里的手机号：默认打码，点一下才给完整号码 */
.lk {
  background: none; border: 0; padding: 0; cursor: pointer;
  font: inherit; color: var(--ink-1); font-weight: 600;
  border-bottom: 1px dashed var(--border-3);
}
.lk:hover { color: var(--accent); border-bottom-color: var(--accent-line); }

.admin { display: grid; grid-template-columns: 236px minmax(0, 1fr); min-height: 100vh; background: var(--page); }
.rail { background: var(--rail); color: var(--rail-ink); display: flex; flex-direction: column; position: sticky; top: 0; height: 100vh; }
.rail-brand { display: flex; align-items: center; gap: 10px; padding: 20px 20px 18px; border-bottom: 1px solid var(--rail-line); }
.rail-brand .brand-mark { box-shadow: none; background: linear-gradient(155deg, #3E6BE8, #2249B4); }
.rail-brand .brand-name { color: var(--rail-active); }
.rail-brand .brand-sub { color: var(--rail-ink-2); }
.rail-nav { padding: 14px 12px; display: flex; flex-direction: column; gap: 2px; flex: 1; overflow-y: auto; }
.rail-nav a {
  display: flex; align-items: center; gap: 10px; padding: 10px 12px;
  border-radius: var(--r-xs); font-size: var(--t-md); color: var(--rail-ink);
  transition: background .15s ease, color .15s ease;
}
.rail-nav a svg { width: 16px; height: 16px; flex: none; opacity: .8; }
.rail-nav a:hover { background: rgba(255, 255, 255, .05); color: var(--rail-active); }
.rail-nav a[aria-current="page"] { background: rgba(255, 255, 255, .09); color: var(--rail-active); font-weight: 600; }
.rail-nav a[aria-current="page"] svg { opacity: 1; }
.rail-nav .grp { font-size: 11px; letter-spacing: .1em; text-transform: uppercase; color: var(--rail-ink-2); padding: 16px 12px 6px; }
.rail-foot { padding: 14px 16px 18px; border-top: 1px solid var(--rail-line); font-size: var(--t-xs); color: var(--rail-ink-2); line-height: 1.7; }
.admin-main { min-width: 0; padding: 26px 30px 60px; }
.admin-head { display: flex; align-items: flex-end; justify-content: space-between; gap: 18px; margin-bottom: 22px; flex-wrap: wrap; }
.admin-sec { margin-bottom: 26px; }

/* 提示条：跟买家有关的约定必须写在页面上，不能只写在文档里 */
.notice {
  display: flex; gap: 11px; align-items: flex-start;
  padding: 14px 16px; border-radius: var(--r-sm);
  border: 1px solid var(--accent-line); background: var(--accent-soft);
  font-size: var(--t-sm); color: var(--ink-2); line-height: 1.7;
}
.notice svg { width: 17px; height: 17px; flex: none; color: var(--accent); margin-top: 2px; }
.notice-warn { border-color: rgba(183, 122, 22, .3); background: var(--warn-soft); }
.notice-warn svg { color: var(--warn); }
.notice b { color: var(--ink-1); }

/* 登录门帘 */
.gate { min-height: 100vh; display: grid; place-items: center; padding: 24px; background: var(--rail); }
.gate-box { width: min(410px, 100%); background: var(--bg); border-radius: var(--r-lg); padding: 36px 34px; box-shadow: var(--shadow-lg); }
.gate-box form { display: flex; flex-direction: column; gap: 15px; margin-top: 24px; }

/* ══ 10. 吐司 ══════════════════════════════════════════════════════ */
.toast-holder {
  position: fixed; left: 0; right: 0; bottom: 40px; z-index: 95;
  display: flex; justify-content: center; pointer-events: none; padding: 0 16px;
}
.toast {
  max-width: 92vw; padding: 11px 20px; border-radius: var(--r-sm);
  background: rgba(16, 23, 37, .95); color: #f2f5fa;
  font-size: var(--t-sm); line-height: 1.6;
  border: 1px solid rgba(255, 255, 255, .09);
  box-shadow: 0 20px 44px -26px rgba(8, 14, 26, .7);
  opacity: 0; transform: translateY(12px);
  transition: opacity .28s ease, transform .28s cubic-bezier(.32, .72, 0, 1);
}
.toast.on { opacity: 1; transform: none; }

/* ══ 11. 数据中心大屏 ══════════════════════════════════════════════ */
/* 这一页不再自己铺底 —— 底由 body 的渐变和上面那几层背景特效负责。
   原先它铺一层 --page 是为了把全站的浅色渐变盖成深色，现在全站同一套色，
   再铺一层就只是把背景特效挡掉了。 */
.screen-page { min-height: 100vh; }
.sc-head { display: flex; align-items: center; gap: 18px; padding: 20px 0 16px; flex-wrap: wrap; border-bottom: 1px solid var(--border); }
.sc-head .brand-name { color: var(--ink-1); }
.sc-head .brand-sub { color: var(--ink-3); }
.sc-live {
  display: inline-flex; align-items: center; gap: 7px; margin-left: auto;
  font-size: var(--t-xs); color: var(--live); letter-spacing: .08em; text-transform: uppercase;
}
.sc-live i { width: 7px; height: 7px; border-radius: 50%; background: var(--live); box-shadow: 0 0 0 0 currentColor; animation: pulse 2.4s ease-out infinite; }
@keyframes pulse {
  0% { box-shadow: 0 0 0 0 rgba(47, 195, 222, .45); }
  70%, 100% { box-shadow: 0 0 0 9px rgba(47, 195, 222, 0); }
}
.sc-stage {
  position: relative; margin-top: 22px; border: 1px solid var(--border);
  border-radius: var(--r-lg); overflow: hidden; background: var(--bg);
  /* 蓝图要有地方画：这里不给高度，canvas 拿到的就是 0。 */
  height: clamp(320px, 46vh, 540px);
}
.sc-stage canvas { width: 100%; height: 100%; display: block; }
.sc-stage-cap {
  position: absolute; left: 22px; bottom: 18px; z-index: 2;
  font-size: var(--t-xs); color: var(--ink-3); letter-spacing: .04em;
}
.sc-stage-tag {
  position: absolute; right: 22px; top: 18px; z-index: 2;
  font-size: 11px; font-weight: 600; letter-spacing: .12em; text-transform: uppercase;
  color: var(--accent); border: 1px solid var(--accent-line); border-radius: var(--r-pill);
  padding: 4px 11px; background: var(--accent-soft);
}
.sc-grid { display: grid; gap: 18px; margin-top: 22px; }
.sc-grid.c2 { grid-template-columns: minmax(0, 1.15fr) minmax(0, 1fr); }
.sc-grid.c3 { grid-template-columns: minmax(0, 1.1fr) minmax(0, 1fr) minmax(0, 1fr); }
.sc-grid.c4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }
.sc-panel { background: var(--bg); border: 1px solid var(--border); border-radius: var(--r); padding: 18px 20px; min-width: 0; }

/* KPI 行：解剖沿用 §0.3，只换列数 */
.sc-kpis { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 14px; margin-top: 22px; }
.sc-panel > .t { font-size: var(--t-sm); font-weight: 600; color: var(--ink-2); display: flex; align-items: center; justify-content: space-between; gap: 10px; margin-bottom: 16px; }
.sc-panel > .t .x { font-size: var(--t-xs); color: var(--ink-4); font-weight: 500; }

/* AI 台账那一行。台账的行不用 .checks —— 那是个带边框的盒子，套在
   .sc-panel 里就是两层框。这里只要横线。 */
.sc-lz { display: flex; flex-direction: column; }
.sc-lz-row { display: flex; align-items: baseline; gap: 10px; padding: 9px 0; border-bottom: 1px solid var(--border); font-size: var(--t-sm); }
.sc-lz-row:last-child { border-bottom: 0; }
.sc-lz-row .k { color: var(--ink-3); flex: none; }
.sc-lz-row .v { margin-left: auto; text-align: right; color: var(--ink-1); font-weight: 600; font-variant-numeric: tabular-nums; overflow-wrap: anywhere; }
.sc-lz-say { font-size: var(--t-sm); line-height: 1.75; color: var(--ink-3); }

/* 横向条形图：从零基线起、每根柱子下面有标签、宽度即占比 */
.hbars { display: flex; flex-direction: column; gap: 11px; }
.hbar { display: grid; grid-template-columns: 78px minmax(0, 1fr) 46px; align-items: center; gap: 12px; font-size: var(--t-sm); }
.hbar .k { color: var(--ink-2); overflow-wrap: anywhere; }
.hbar .t { height: 9px; border-radius: var(--r-pill); background: var(--panel-2); overflow: hidden; }
.hbar .t > i { display: block; height: 100%; border-radius: inherit; background: linear-gradient(90deg, var(--accent), var(--live)); transition: width .8s cubic-bezier(.32, .72, 0, 1); }
.hbar .v { text-align: right; color: var(--ink-1); font-weight: 600; font-variant-numeric: tabular-nums; }

/* 环形占比 */
.donut-wrap { display: flex; align-items: center; gap: 20px; flex-wrap: wrap; }
.donut { position: relative; width: 132px; height: 132px; flex: none; }
/* 尺寸只由 .donut 决定。svg 上写死 width/height 的话，窄屏把 .donut 收到 112px
   它还是 132px，多出来的 20px 顶破面板。 */
.donut svg { display: block; width: 100%; height: 100%; transform: rotate(-90deg); }
.donut .mid { position: absolute; inset: 0; display: grid; place-content: center; text-align: center; }
.donut .mid b { font-size: 25px; font-weight: 800; letter-spacing: -.03em; font-variant-numeric: tabular-nums; display: block; }
.donut .mid span { font-size: 11px; color: var(--ink-3); }
.legend { display: flex; flex-direction: column; gap: 9px; flex: 1; min-width: 160px; }
.legend div { display: flex; align-items: center; gap: 8px; font-size: var(--t-sm); color: var(--ink-2); }
.legend i { width: 9px; height: 9px; border-radius: 3px; flex: none; }
.legend .n { margin-left: auto; font-variant-numeric: tabular-nums; color: var(--ink-1); font-weight: 600; }

/* 实时事件流 */
.feed { display: flex; flex-direction: column; gap: 2px; max-height: 268px; overflow-y: auto; }
.feed-row { display: flex; align-items: center; gap: 10px; padding: 8px 0; border-bottom: 1px solid var(--border); font-size: var(--t-sm); }
.feed-row:last-child { border-bottom: 0; }
.feed-row .d { width: 6px; height: 6px; border-radius: 50%; background: var(--accent); flex: none; }
.feed-row .n { color: var(--ink-2); min-width: 0; flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.feed-row .t { color: var(--ink-4); font-size: var(--t-xs); font-variant-numeric: tabular-nums; flex: none; }

/* 地市分布：小方块点阵 */
.citydots { display: grid; grid-template-columns: repeat(auto-fill, minmax(88px, 1fr)); gap: 10px; }
.citydot { display: flex; align-items: center; gap: 8px; font-size: var(--t-xs); color: var(--ink-3); }
.citydot i { width: 10px; height: 10px; border-radius: 3px; flex: none; background: var(--accent); }
.citydot .n { color: var(--ink-1); font-weight: 600; margin-left: auto; font-variant-numeric: tabular-nums; }

/* 无 JS 时的静态兜底 */
.noscript { padding: 28px; border: 1px dashed var(--border-2); border-radius: var(--r); color: var(--ink-2); font-size: var(--t-sm); }

/* ══ 12. 动效降级 ══════════════════════════════════════════════════
   大屏在 prefers-reduced-motion 下停在构图最好的一帧，而不是变成空白。 */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .001ms !important; animation-iteration-count: 1 !important;
    transition-duration: .001ms !important; scroll-behavior: auto !important;
  }
  .gcard:hover, .ncard:hover { transform: none; }
}

/* ══ 13. 响应式 ════════════════════════════════════════════════════ */
@media (max-width: 1180px) {
  .hero-in { grid-template-columns: minmax(0, 1fr); gap: 34px; }
  .pdp { grid-template-columns: minmax(0, 1fr); gap: 30px; }
  .gallery { position: static; }
  .sc-grid.c4 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

/* 961–1080 这一段最窄：汉堡到 960 才出来，而站名「AI豫筑产业智汇商城」
   加上八个导航项在这时候已经挤满了 —— 961px 处每一项都折成两行（量过）。
   把导航项的左右内边距各收 3px，八个项省下 48px，这一段就够用了。
   收内边距而不是收字号：3px 几乎看不出来，字号一动整条导航都变样。
   再窄就交给 960 的汉堡，不用在这里继续硬挤。 */
@media (max-width: 1080px) {
  .nav a { padding: 8px 9px; }
}

@media (max-width: 960px) {
  :root { --head-h: 58px; }
  .wrap { padding: 0 18px; }
  .sec { padding: 40px 0; }

  .nav { display: none; }
  .burger { display: grid; margin-left: auto; }

  /* 三栏永远不许活到平板以下 */
  .admin { grid-template-columns: minmax(0, 1fr); }
  .rail { position: static; height: auto; }
  .rail-nav { flex-direction: row; overflow-x: auto; padding: 10px 12px; gap: 6px; }
  .rail-nav .grp { display: none; }
  .rail-nav a { white-space: nowrap; }
  .rail-foot { display: none; }
  .admin-main { padding: 20px 18px 48px; }

  .listing { grid-template-columns: minmax(0, 1fr); gap: 18px; }
  .filters { position: static; flex-direction: row; flex-wrap: wrap; gap: 16px; }
  .fgroup { border-bottom: 0; border-right: 1px solid var(--border); padding: 0 16px 0 0; flex: 1 1 200px; }
  .fgroup:last-child { border-right: 0; }

  .g4 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .g3 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .sc-grid.c2, .sc-grid.c3, .sc-grid.c4 { grid-template-columns: minmax(0, 1fr); }
  .sc-kpis { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .track { grid-auto-columns: 68vw; }
  .floor-head { padding: 24px 22px; min-height: 150px; }
  .floor-head .go { position: static; margin-top: 16px; }
  .hero { padding: 36px 0 30px; }
}

@media (max-width: 620px) {
  .wrap { padding: 0 15px; }
  :root { --t-3xl: 27px; --t-2xl: 22px; }
  .h1 { line-height: 1.28; }
  .hero .h1 { font-size: 34px; }
  .btn { height: 46px; }
  .btn-sm { height: 40px; }
  .g2, .g3, .g4 { grid-template-columns: minmax(0, 1fr); }
  .grid-goods { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px; }
  .grid-goods .gcard-body { padding: 11px 12px 13px; }
  .grid-goods .gcard-brief { display: none; }
  .grid-goods .price { font-size: 20px; }
  .databar { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .databar-side { flex: 1 1 100%; }
  .spec-row { grid-template-columns: 108px minmax(0, 1fr); }
  .spec-tbl dt { width: 108px; }
  .hero-acts .btn { flex: 1 1 auto; }
  .track { grid-auto-columns: 76vw; }
  .modal-box { padding: 24px 20px 28px; border-radius: var(--r); }
  /* 100vw 含滚动条那条沟，100% 不含。抽屉贴着右边展开时，
     多出来的那 15px 会把左边的内边距推出屏幕外。 */
  .drawer { width: 100%; }
  .donut { width: 112px; height: 112px; }
  .hbar { grid-template-columns: 62px minmax(0, 1fr) 40px; gap: 9px; }
  .sc-stage { height: clamp(300px, 52vh, 420px); border-radius: var(--r); }
  .sc-stage-cap, .sc-stage-tag { display: none; }
  .sc-head { gap: 12px; }
  .sc-live { margin-left: 0; width: 100%; }
}

/* 再窄就一列。320px 屏上两列各 131px，扣掉内边距剩 106px ——
   价格和「加购 / 立即咨询」两个按钮摆不下，硬塞就是每张卡都换行、都不好点。 */
@media (max-width: 400px) {
  .grid-goods { grid-template-columns: minmax(0, 1fr); }
  .databar { grid-template-columns: minmax(0, 1fr); }
  .newsgrid { grid-template-columns: minmax(0, 1fr); }
}

/* ══ 14. AI 助手（全站悬浮）═══════════════════════════════════════
   三个智能体 + 一个数字人。样式并进这张表，不另开文件 —— 「全站唯一
   CSS」的规矩不能破。断点也写在这一节里，跟别的组件牵扯不上。

   层级：浮球 70 · 遮罩 85 · 面板 86。现有阶梯是 head 60 / mask 80 /
   drawer 81 / modal 90 / toast 95 —— 助手排在购物车抽屉之上、弹窗之下。
   它自己带一块遮罩，不去抢 cart.js 的 #mask：那个 close() 会无条件把
   #mask 藏起来，两边共用一个节点必然出现「关掉一个另一个也黑了」。

   数字人只有一条动效：方块呼吸（纯 transform，不动布局，不占新 rAF）。
   基础样式本身就是构图最好看的那一帧 —— 全局 prefers-reduced-motion
   会把 animation 掐到 .001ms，那时页面上留下的就是这里写死的静态样子，
   不能是「动画跑起来才好看」。
   ═══════════════════════════════════════════════════════════════ */

/* ── 浮球。它同时在亮色页面和大屏上出现，所以颜色全走令牌：
     大屏作用域里 --bg 是深色、--accent-ink 是浅蓝，这里一个字都不用改。 ── */
.ai-ball {
  position: fixed; z-index: 70;
  right: 22px; bottom: calc(22px + env(safe-area-inset-bottom, 0px));
  display: inline-flex; align-items: center; gap: 9px;
  height: 52px; padding: 0 18px 0 12px;
  border-radius: var(--r-pill);
  border: 1px solid var(--accent-line);
  background: var(--bg); color: var(--accent-ink);
  font-size: var(--t-sm); font-weight: 700; letter-spacing: .01em;
  box-shadow: 0 1px 2px rgba(20, 34, 64, .05), 0 20px 44px -24px var(--glow);
  -webkit-tap-highlight-color: transparent;
  transition: transform .18s cubic-bezier(.32, .72, 0, 1), border-color .18s ease,
              box-shadow .18s ease;
}
.ai-ball:hover { transform: translateY(-2px); border-color: var(--accent); }
.ai-ball-fig {
  flex: none; width: 30px; height: 30px; border-radius: 50%;
  display: grid; place-items: center;
  background: var(--accent-soft); color: var(--accent);
  font-size: 12px; font-weight: 800; letter-spacing: .02em;
}

/* ── 遮罩。跟 .mask 同配方但不共享节点 ── */
.ai-scrim {
  position: fixed; inset: 0; z-index: 85;
  background: rgba(12, 20, 36, .34);
  backdrop-filter: blur(2px); -webkit-backdrop-filter: blur(2px);
}

/* ── 面板：右侧抽屉 ── */
.ai-panel {
  position: fixed; top: 0; right: 0; bottom: 0; z-index: 86;
  width: min(440px, 100%);
  display: flex; flex-direction: column;
  background: var(--bg); border-left: 1px solid var(--border);
  box-shadow: var(--shadow-lg);
  transform: translateX(102%);
  transition: transform .3s cubic-bezier(.32, .72, 0, 1);
}
.ai-panel.open { transform: none; }

.ai-head {
  flex: none; display: flex; align-items: center; gap: 12px;
  padding: 15px 18px; border-bottom: 1px solid var(--border);
}
.ai-avatar {
  flex: none; width: 42px; height: 42px; border-radius: 13px;
  display: grid; place-items: center;
  background: linear-gradient(155deg, var(--accent-soft), transparent 78%);
  border: 1px solid var(--accent-line); color: var(--accent);
  font-size: 15px; font-weight: 800; letter-spacing: .01em;
}
.ai-who { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.ai-name {
  display: flex; align-items: center; gap: 8px;
  font-size: var(--t-base); font-weight: 700; letter-spacing: -.01em;
}
.ai-sub { font-size: 11px; color: var(--ink-3); letter-spacing: .02em; }
.ai-head .icon-btn { flex: none; width: 34px; height: 34px; }
.ai-head .icon-btn svg { width: 16px; height: 16px; }
.ai-reset {
  flex: none; height: 30px; padding: 0 11px;
  border: 1px solid var(--border); border-radius: var(--r-pill);
  background: var(--bg); color: var(--ink-3);
  font-size: 11px; font-weight: 600; letter-spacing: .02em;
}
.ai-reset:hover { border-color: var(--accent-line); color: var(--accent); background: var(--accent-soft); }

/* ── 面板主体。min-height:0 必须有，否则 flex 子项撑破容器、滚不动 ── */
.ai-body {
  flex: 1; min-height: 0; overflow-y: auto;
  overscroll-behavior: contain;
  padding: 16px 18px 22px;
  display: flex; flex-direction: column; gap: 14px;
}

/* ── 消息流。只追加不重画 —— 重画会把图片、按钮和滚动位置一起丢掉 ── */
.ai-msg {
  /* flex:none —— 不加的话内容超过面板高度时，浏览器会先把每条消息压扁，
     而不是让 .ai-body 滚起来 */
  flex: none; display: flex; gap: 9px; align-items: flex-end;
  max-width: 100%;
  animation: ai-in .22s cubic-bezier(.32, .72, 0, 1) both;
}
@keyframes ai-in { from { opacity: 0; transform: translateY(6px); } }
.ai-msg-me { flex-direction: row-reverse; }
.ai-msg-fig {
  flex: none; width: 26px; height: 26px; border-radius: 9px;
  display: grid; place-items: center;
  background: var(--accent-soft); border: 1px solid var(--accent-line);
  color: var(--accent); font-size: 10px; font-weight: 800; letter-spacing: .01em;
}
/* 回答的气泡几乎占满一行 —— 里面要摆商品行（图 56 + 标题 + 价格 + 按钮），
   留窄了标题会被挤成一条。用户那句话反过来，按内容宽度走。
   min-width:0 是给里面那些 .ai-row 用的，不然长标题会把气泡顶出面板。 */
.ai-bub {
  min-width: 0; max-width: calc(100% - 35px);
  padding: 12px 14px; border-radius: 14px 14px 14px 4px;
  background: var(--panel-2); border: 1px solid var(--border);
  font-size: var(--t-sm); line-height: 1.7; color: var(--ink-2);
}
.ai-bub-me {
  max-width: 84%;
  border-radius: 14px 14px 4px 14px;
  background: var(--accent); border-color: var(--accent);
  color: var(--on-accent); overflow-wrap: anywhere;
}
/* .ai-said 的底色跟气泡一样，直接摆进去就看不见了 —— 换回页面底色 */
.ai-bub .ai-said { background: var(--bg); }
.ai-bub .ai-said-warn { background: var(--warn-soft); }
.ai-bub .ai-said-quiet { background: transparent; }
.ai-bub .ai-said-strict { background: var(--accent-soft); }
/* 气泡里第一个和最后一个子块不留外距 —— 否则气泡看着比内容大一圈 */
.ai-bub > :first-child { margin-top: 0; }
.ai-bub > :last-child { margin-bottom: 0; }

/* 「听到了」那张卡。解析结果摊开 —— 对话版的「亮出算式」 */
.ai-heard {
  display: flex; flex-wrap: wrap; align-items: baseline; gap: 6px 8px;
  margin-bottom: 10px; padding-bottom: 10px;
  border-bottom: 1px dashed var(--border);
}
.ai-heard-t { font-size: 11px; font-weight: 700; color: var(--accent); letter-spacing: .04em; }
.ai-heard-i { font-size: 11px; color: var(--ink-3); }
.ai-heard-i b { font-size: 11px; font-weight: 700; color: var(--ink-1); }

/* 气泡里的芯片。跟 .ai-chips 同一套样子，只是外面多留一道上边距 */
.ai-chips-in { margin-top: 12px; }
.ai-chips-in .ai-chip { background: var(--bg); }

/* ── 输入区。钉在底部，跟 .ai-foot 上下挨着 ── */
.ai-compose {
  flex: none; display: flex; gap: 8px; align-items: center;
  padding: 12px 18px 0;
}
.ai-compose .input { flex: 1; min-width: 0; height: 42px; }
.ai-compose .btn { flex: none; height: 42px; padding: 0 18px; }

/* ── 常驻明标：算式全部摊开，点开能核。钉在底部，跟着面板一直在 ── */
.ai-foot {
  flex: none; display: flex; gap: 8px; align-items: flex-start;
  padding: 11px 18px calc(13px + env(safe-area-inset-bottom, 0px));
  border-top: 1px solid var(--border); background: var(--panel-2);
  font-size: 11px; line-height: 1.6; color: var(--ink-3);
}
.ai-foot svg { width: 14px; height: 14px; flex: none; margin-top: 2px; color: var(--accent); }

.ai-chips { display: flex; flex-wrap: wrap; gap: 7px; }
.ai-chip {
  height: 32px; padding: 0 12px; border-radius: var(--r-pill);
  border: 1px solid var(--border-2); background: var(--bg); color: var(--ink-2);
  font-size: var(--t-sm); font-weight: 500;
  -webkit-tap-highlight-color: transparent;
  transition: border-color .15s ease, background .15s ease, color .15s ease;
}
.ai-chip:hover { border-color: var(--accent-line); color: var(--accent); }

/* ── 助手说的话。左边一道竖线，跟商品行分开 ── */
.ai-said {
  margin: 12px 0; padding: 11px 14px;
  border-left: 2px solid var(--accent-line); border-radius: 0 var(--r-sm) var(--r-sm) 0;
  background: var(--panel-2); color: var(--ink-2);
  font-size: var(--t-sm); line-height: 1.72;
}
.ai-said b { color: var(--ink-1); }
.ai-said-warn {
  border-left-color: var(--warn); background: var(--warn-soft); color: var(--ink-2);
}
.ai-said-warn b { color: var(--warn); }
/* 红线：预算那一栏只拆建材、不报施工价。整块加框，是这一页最重的一段话。 */
.ai-said-strict {
  margin: 16px 0 12px; padding: 14px 16px;
  border: 1px solid var(--accent-line); border-left: 3px solid var(--accent);
  border-radius: var(--r-sm); background: var(--accent-soft); color: var(--ink-2);
}
.ai-said-strict b { color: var(--accent-ink); }
/* 自曝短处的话。不抢眼，但不能省 —— 留白 + 一条虚线，跟别的方块区分开 */
.ai-said-quiet {
  margin: 14px 0 0; padding: 11px 0 0;
  border: 0; border-top: 1px dashed var(--border-2); border-radius: 0;
  background: transparent; color: var(--ink-3); font-size: var(--t-xs);
}

/* ── 结果行 ── */
.ai-row {
  display: grid; grid-template-columns: 56px minmax(0, 1fr) auto;
  gap: 12px; align-items: start;
  padding: 15px 0; border-top: 1px solid var(--border);
}
.ai-row-img {
  display: block; width: 56px; height: 56px; border-radius: var(--r-xs); overflow: hidden;
  border: 1px solid var(--border); background: var(--panel-2);
}
.ai-row-img img { width: 100%; height: 100%; object-fit: cover; }
.ai-row-main { display: flex; flex-direction: column; gap: 6px; min-width: 0; }
.ai-row-t {
  font-size: var(--t-md); font-weight: 600; line-height: 1.5; color: var(--ink-1);
  overflow-wrap: anywhere;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}
.ai-row-t:hover { color: var(--accent); }
.ai-row-m { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }
.ai-row-side {
  display: flex; flex-direction: column; align-items: flex-end; gap: 6px;
  text-align: right; min-width: 0;
}
/* 价格在全站是最大的字，但这里是一行结果的附注，收回正文尺寸 —— 否则
   一个 ¥268 就把标题挤成两行。 */
.ai-row-side .price { font-size: 17px; }

/* 算式。本地算出来的东西敢把过程摆出来，这是全站「AI 感」最实的一处 ——
   等宽字体让数字对齐，一眼看得出是算的，不是写死的文案。 */
.ai-calc {
  display: flex; flex-wrap: wrap; align-items: baseline; gap: 4px 8px;
  padding: 7px 10px; border-radius: var(--r-xs);
  background: var(--accent-soft); border: 1px solid var(--accent-line);
  color: var(--ink-2); font-size: 11px; line-height: 1.6;
  font-variant-numeric: tabular-nums;
}
.ai-calc b { font-size: var(--t-md); font-weight: 800; color: var(--accent-ink); letter-spacing: -.02em; }
.ai-calc > .tiny { flex: 1 1 100%; color: var(--ink-3); }
.ai-calc-no {
  background: transparent; border-color: var(--border); border-style: dashed;
  color: var(--ink-3);
}

/* ── 算量的结果块。一个客户自己算不清的数 + 摆出来的算式 ── */
.ai-out {
  margin: 4px 0 12px; padding: 16px;
  border: 1px solid var(--accent-line); border-radius: var(--r-sm);
  background: linear-gradient(180deg, var(--accent-soft), transparent 72%), var(--bg);
}
.ai-out-n {
  display: flex; align-items: baseline; gap: 5px;
  font-size: 44px; font-weight: 800; letter-spacing: -.04em; line-height: 1;
  color: var(--accent-ink); font-variant-numeric: tabular-nums;
}
.ai-out-n .u { font-size: var(--t-md); font-weight: 600; color: var(--ink-3); letter-spacing: 0; }
.ai-out-calc {
  margin-top: 11px; font-size: var(--t-xs); color: var(--ink-2);
  font-family: var(--mono); overflow-wrap: anywhere; line-height: 1.7;
}
.ai-out-sub { margin-top: 6px; font-size: var(--t-sm); color: var(--ink-3); line-height: 1.65; }
.ai-out-sub b { color: var(--ink-1); }
.ai-out-act { display: flex; gap: 8px; flex-wrap: wrap; margin-top: 14px; }
.ai-said-strict .ai-out-act { margin-top: 12px; }

/* ── 预算拆分。条形从零基线起，宽度 = 占比，标签在左边 —— 不画饼图 ── */
.ai-split { display: flex; flex-direction: column; }
.ai-split-row {
  display: grid; grid-template-columns: minmax(0, 1fr) auto;
  grid-template-areas: "k v" "t t" "x x";
  gap: 0 10px; align-items: center;
  padding: 11px 0; border-bottom: 1px solid var(--border);
}
.ai-split-row .k {
  grid-area: k; display: flex; align-items: baseline; gap: 7px;
  font-size: var(--t-sm); font-weight: 600; color: var(--ink-1);
}
.ai-split-row .k i.num {
  font-style: normal; font-size: 11px; font-weight: 500; color: var(--ink-4);
  border: 1px solid var(--border); border-radius: var(--r-pill); padding: 1px 6px;
}
.ai-split-row .t {
  grid-area: t; display: block; height: 6px; margin-top: 7px;
  border-radius: var(--r-pill); background: var(--panel-3); overflow: hidden;
}
.ai-split-row .t > i {
  display: block; height: 100%; border-radius: inherit;
  background: linear-gradient(90deg, var(--accent), var(--live, var(--accent)));
  transition: width .5s cubic-bezier(.32, .72, 0, 1);
}
.ai-split-row .v { grid-area: v; font-weight: 700; font-size: var(--t-base); font-variant-numeric: tabular-nums; }
.ai-split-row .x { grid-area: x; margin-top: 6px; overflow-wrap: anywhere; }
.ai-split-no .t > i { background: var(--warn); }
.ai-split-no .x { color: var(--warn); }

/* ── ≤620：右侧抽屉换成底部上滑面板 ─────────────────────────────── */
@media (max-width: 620px) {
  .ai-panel {
    top: auto; left: 0; right: 0; bottom: 0; width: 100%;
    max-height: min(78vh, 640px);
    border-left: 0; border-top: 1px solid var(--border);
    border-radius: var(--r) var(--r) 0 0;
    transform: translateY(102%);
    box-shadow: 0 -30px 70px -40px rgba(20, 34, 64, .5);
  }
  /* 高度是上限不是定值：聊得长就顶到上限再滚，聊得短就贴着底。
     .ai-body 的 flex:1 + min-height:0 负责在超过上限时滚动。 */
  .ai-body { max-height: 100%; padding: 14px 15px 18px; }
  .ai-head, .ai-compose, .ai-foot { padding-left: 15px; padding-right: 15px; }
  /* 16px：再小 iOS 会在聚焦时把整页放大，关掉键盘页面还留在放大态 */
  .ai-compose .input { height: 46px; font-size: 16px; }
  .ai-compose .btn { height: 46px; }
  .ai-msg-fig { width: 24px; height: 24px; }
  .ai-out-n { font-size: 38px; }
  /* 一行放不下三栏了，价格和按钮挪到下面整行铺开，别把标题挤成一条 */
  .ai-row { grid-template-columns: 52px minmax(0, 1fr); gap: 11px; }
  .ai-row-img { width: 52px; height: 52px; }
  .ai-row-side {
    grid-column: 1 / -1; flex-direction: row; align-items: center;
    justify-content: space-between; gap: 10px;
  }
  .ai-row-side .price { font-size: 19px; }
}

/* 400px 以下浮球收成一个圆：再往外伸一截「AI 助手」，就把单列卡片右下角
   那颗按钮压住了。方标还在，认得出是谁。 */
@media (max-width: 400px) {
  .ai-ball { right: 14px; bottom: calc(14px + env(safe-area-inset-bottom, 0px)); width: 52px; padding: 0; justify-content: center; }
  .ai-ball-txt { display: none; }
  .ai-ball-fig { background: transparent; }
  .ai-split-row .k { font-size: 13px; }
}

/* ══ 15. 首页 · AI 导购区 ══════════════════════════════════════════
   一台**会回话的导购台**，不是第二个货架。阅读顺序是：
     左：看演示（视频占满整列）→ 知道它会算什么
     右：点一颗芯片 → 这三件就是它当场挑出来的结论
   所以左列只放视频和三句能力说明，商品全部收到右列、做成横向行卡 ——
   卡是「输出」不是「货架」。

   整个区块只在 assets/video/ 里有视频时才由 pages.js 渲染，
   没有就一个空 div 都不占位 —— 所以这里不用写「空状态」的样式。 */
.aishop-grid {
  display: grid; grid-template-columns: minmax(0, 1.15fr) minmax(0, .85fr);
  gap: 28px;
  /* stretch 而不是 start：视频是 16:9，天然比右边那三行高一大截。
     让它俩一样高、把芯片压到底，两列才像个整体；start 会在右列下面
     留一块比芯片还高的空白，看着像没做完。 */
  align-items: stretch;
}
.aishop-lead { min-width: 0; }

/* ── 视频位 ── */
.aiv {
  position: relative; overflow: hidden;
  border: 1px solid var(--border); border-radius: var(--r);
  /* 跟封面同一个暗场：浏览器撤封面换视频的那一下不闪白 */
  background: #191c23; box-shadow: var(--shadow);
}
/* 左列整列给视频 —— 它是这一屏的演示，面积该配得上。
   外面套一圈发光边做成展柜，别让它看起来像一张放大的缩略图。 */
.aishop-lead .aiv {
  border-radius: var(--r-lg);
  box-shadow:
    0 0 0 1px var(--accent-line),
    0 1px 2px rgba(20, 34, 64, .05),
    0 26px 60px -30px var(--glow),
    0 0 46px -12px var(--cyan-soft);
}
.aiv-v { display: block; width: 100%; height: auto; object-fit: cover; background: #191c23; }
.aiv-cover {
  position: absolute; inset: 0; width: 100%; height: 100%;
  object-fit: cover; display: block; transition: opacity .45s ease;
}
.aiv-cover.off { opacity: 0; pointer-events: none; }

/* 这块牌子不跟封面一起撤，一直在。按《互联网信息服务深度合成管理规定》
   第 17 条，AI 生成的数字人必须显著标出来 —— 在这儿它是卖点，不是免责。 */
.aiv-tag {
  position: absolute; left: 12px; top: 12px; z-index: 2;
  display: inline-flex; align-items: center; gap: 6px;
  padding: 5px 11px; border-radius: var(--r-pill);
  background: rgba(15, 17, 22, .74); border: 1px solid rgba(232, 236, 244, .24);
  color: #e8ecf4; font-size: var(--t-xs); font-weight: 600; letter-spacing: .02em;
  white-space: nowrap; backdrop-filter: blur(6px);
}
/* 只有「不自动播」和「播不了」两种情况才出现 —— 平时点开就该动 */
.aiv-play {
  position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%); z-index: 3;
  display: inline-flex; align-items: center; gap: 9px;
  height: 44px; padding: 0 20px 0 17px; border-radius: var(--r-pill);
  background: rgba(20, 23, 29, .86); border: 1px solid rgba(232, 236, 244, .32);
  color: #e8ecf4; font-size: var(--t-sm); font-weight: 600; cursor: pointer;
}
.aiv-play[hidden] { display: none; }
.aiv-play-i {
  width: 0; height: 0; flex: none;
  border-left: 11px solid currentColor;
  border-top: 7px solid transparent; border-bottom: 7px solid transparent;
}
/* 音量开关：和左上角的 AI 标签对称，放右上角 */
.aiv-mute {
  position: absolute; right: 12px; top: 12px; z-index: 2;
  width: 34px; height: 34px; border-radius: 50%;
  display: grid; place-items: center;
  background: rgba(15, 17, 22, .74); border: 1px solid rgba(232, 236, 244, .24);
  color: #e8ecf4; cursor: pointer;
  transition: background .15s ease, color .15s ease;
}
.aiv-mute:hover { background: rgba(45, 60, 82, .88); color: #fff; }
.aiv-mute svg { width: 17px; height: 17px; }

/* 视频下面那三句：写的都是助手真做得到的事，不是形容词。 */
.aishop-list { display: flex; flex-direction: column; gap: 9px; margin: 18px 0 0; padding: 0; list-style: none; }
.aishop-list li { display: flex; align-items: flex-start; gap: 9px; font-size: var(--t-sm); color: var(--ink-2); line-height: 1.6; }
.aishop-list li > svg { width: 16px; height: 16px; flex: none; margin-top: 3px; color: var(--accent); }
.aishop-list li > span { min-width: 0; }

/* ── 右列：助手的输出栏 ──────────────────────────────────────────
   三件商品、一句标题、一排芯片。整块做成一个面板，跟左边视频的展柜
   是一对 —— 左边是「它怎么说话」，右边是「它说的话长什么样」。 */
.aishop-out {
  min-width: 0;
  display: flex; flex-direction: column;
  padding: 18px 18px 16px;
  border: 1px solid var(--border); border-radius: var(--r-lg);
  background: var(--bg); box-shadow: var(--shadow);
}
.aishop-out-h {
  display: flex; align-items: center; gap: 8px;
  font-size: var(--t-sm); font-weight: 700; color: var(--ink-1);
  letter-spacing: .01em; margin-bottom: 12px;
}
/* 那颗点是「活的」—— 走 --live，不是装饰用的强调色 */
.aishop-out-h > i {
  width: 7px; height: 7px; border-radius: 50%; flex: none;
  background: var(--live); box-shadow: 0 0 0 3px var(--cyan-soft);
  animation: pulse 2.4s ease-in-out infinite;
}

.aipicks { display: flex; flex-direction: column; gap: 8px; }
.aipick {
  display: flex; align-items: center; gap: 12px; min-width: 0;
  padding: 8px; border-radius: var(--r-sm);
  border: 1px solid var(--border); background: var(--panel-2);
  text-decoration: none; color: inherit;
  transition: border-color .16s ease, background .16s ease, transform .16s ease;
}
.aipick:hover { border-color: var(--accent-line); background: var(--bg); transform: translateX(2px); }
.aipick img { width: 56px; height: 56px; flex: none; border-radius: var(--r-sm); object-fit: cover; background: var(--panel-3); }
/* min-width:0 —— 少了这个，长标题会把整行顶宽，320px 下直接横向溢出 */
.aipick-b { display: flex; flex-direction: column; gap: 3px; min-width: 0; flex: 1; }
.aipick-t {
  font-size: var(--t-sm); font-weight: 600; color: var(--ink-1); line-height: 1.45;
  display: -webkit-box; -webkit-line-clamp: 2; line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}
.aipick-p { font-size: var(--t-md); font-weight: 800; color: var(--ink-1); letter-spacing: -.02em; font-variant-numeric: tabular-nums; }
.aipick-u { font-size: var(--t-xs); font-weight: 600; color: var(--ink-3); letter-spacing: 0; }
.aipick-g { flex: none; width: 18px; height: 18px; color: var(--ink-4); }
.aipick-g svg { display: block; width: 100%; height: 100%; }
.aipick:hover .aipick-g { color: var(--accent); }

/* margin-top:auto 把它推到面板底部，跟左边视频的下沿对齐 */
.aishop-chips { display: flex; flex-wrap: wrap; gap: 7px; margin-top: auto; padding-top: 14px; }
.aishop-chips .ai-chip { background: var(--bg); }

@media (max-width: 960px) {
  .aishop-grid { grid-template-columns: minmax(0, 1fr); gap: 26px; }
}
/* 320px：缩略图收到 48px，价格那行字号降一档 —— 行卡天生横向，
   这里只要保证它不撑破容器就行。 */
@media (max-width: 380px) {
  .aipick img { width: 48px; height: 48px; }
  .aipick-p { font-size: var(--t-base); }
}

/* ══ 12. 首屏核心 + 器件细节（2026-10-07 第三轮背景）═══════════════
   「二的环 + 三的细节」。亮底上背景做不出多明显的设计 —— 这个事实
   认了，把设计重量分两处落地：

   ① 首屏一个主视觉：右侧数据卡后面悬着一个纯 CSS 全息核心（同心环 /
      双弧光 / 刻度环 / 呼吸光核 / 三颗卫星 / 扩散波纹），外面配四角
      取景角标 + 底边数据基线。卡是不透明的，环从卡后穿过去，看起来
      像卡片浮在一块仪表上。节点只写在 index.html 里，其它页不渲染。
   ② 其余全落到器件细节上：顶栏电源线、eyebrow 呼吸点、按钮对角括号、
      数据条仪表格（四角括号 + 刻度尺 + 慢扫光）、区块标题等宽编号、
      分隔线变数据线、页脚深色终端带。近看全是活儿，远看还是干净的。

   数据条「数字从 0 滚到目标值」在 assets/pages.js 的 fillBar() 里；
   页脚的「AI 服务在线」芯片写在 assets/layout.js 的 footer() 里。
   ⚠ .databar 的结构是「外层 cell div + 内层 .v/.k div」，§8 的
     `.databar div` 三层都刷底 —— 这里用 `.databar>div` 照顾到每一层，
     漏一层就露白（撤掉背景那轮在深色带里踩过同一个坑）。
   ═══════════════════════════════════════════════════════════════ */

/* ── 12.1 首屏壳：核心夹在中间层（z1），文案在最上层（z2）───────── */
.hero { position: relative; isolation: isolate; overflow: hidden; }
.hero > .wrap { position: relative; z-index: 2; }

/* ── 12.2 全息核心（纯 CSS，零脚本）─────────────────────────────── */
.ai-core { position: absolute; top: 50%; left: 71%; width: min(50vw, 640px); aspect-ratio: 1;
  transform: translate(-50%, -50%); z-index: 1; pointer-events: none; }
.ai-core i { position: absolute; display: block; border-radius: 50%; }
/* 雷达刷：一道很淡的扇形，22 秒一圈 */
.c-sweep { inset: 3%; background: conic-gradient(from 0deg, rgba(47, 195, 222, .20), rgba(47, 195, 222, .03) 16%, transparent 30%);
  -webkit-mask: radial-gradient(closest-side, transparent 12%, #000 36%, #000 96%, transparent);
  mask: radial-gradient(closest-side, transparent 12%, #000 36%, #000 96%, transparent);
  animation: cSpin 22s linear infinite; }
/* 扩散波纹：9 秒一圈，两颗错开 */
.c-rip { inset: 3%; border: 1px solid rgba(47, 195, 222, .62); opacity: 0;
  animation: cRip 9s cubic-bezier(.25, .6, .35, 1) infinite; }
.c-rip.r2 { animation-delay: 4.5s; }
/* 三条环：静环 + 双弧光（缓转）+ 刻度环（反向慢转） */
.c-ring { inset: 3%; border: 1px solid rgba(76, 123, 255, .30); }
.c-arc { inset: 10%; background: conic-gradient(from 0deg,
  rgba(47, 195, 222, 0), rgba(47, 195, 222, .68) 10%, rgba(47, 195, 222, 0) 32%,
  rgba(76, 123, 255, 0) 46%, rgba(76, 123, 255, .58) 60%, rgba(76, 123, 255, 0) 82%, rgba(47, 195, 222, 0));
  -webkit-mask: radial-gradient(closest-side, transparent calc(100% - 1.6px), #000 calc(100% - 1.1px));
  mask: radial-gradient(closest-side, transparent calc(100% - 1.6px), #000 calc(100% - 1.1px));
  animation: cSpin 88s linear infinite; }
.c-tick { inset: 19%; border: 1px dotted rgba(76, 123, 255, .42); animation: cSpin 150s linear infinite reverse; }
/* 光核：呼吸 */
.c-orb { inset: 34%; filter: blur(2px);
  background: radial-gradient(circle, rgba(95, 227, 245, .46), rgba(76, 123, 255, .30) 42%, rgba(76, 123, 255, .10) 62%, rgba(76, 123, 255, 0) 74%);
  animation: cBreath 7.5s ease-in-out infinite; }
/* 三颗小卫星：整个 wrapper 转，点在轨道上 */
.c-sat { inset: 0; animation: cSpin 46s linear infinite; }
.c-sat.s2 { animation-duration: 68s; animation-direction: reverse; }
.c-sat.s3 { animation-duration: 98s; }
.c-sat b { position: absolute; left: 50%; top: 4%; width: 8px; height: 8px; margin: -4px 0 0 -4px; border-radius: 50%;
  background: radial-gradient(circle, #f2fbff, rgba(95, 227, 245, .95) 42%, rgba(95, 227, 245, 0) 72%);
  box-shadow: 0 0 11px 1px rgba(95, 227, 245, .65); }
.c-sat.s2 b { top: 14%; width: 7px; height: 7px; margin: -3.5px 0 0 -3.5px;
  background: radial-gradient(circle, #f4f8ff, rgba(76, 123, 255, .95) 42%, rgba(76, 123, 255, 0) 72%);
  box-shadow: 0 0 10px 1px rgba(76, 123, 255, .6); }
.c-sat.s3 b { top: 25%; width: 6px; height: 6px; margin: -3px 0 0 -3px; opacity: .9; }
@keyframes cSpin { to { transform: rotate(1turn); } }
@keyframes cBreath { 0%, 100% { transform: scale(.95); opacity: .8; } 50% { transform: scale(1.06); opacity: 1; } }
@keyframes cRip { 0% { transform: scale(.3); opacity: 0; } 7% { opacity: .5; } 42% { opacity: 0; transform: scale(1); } 100% { opacity: 0; transform: scale(1); } }
/* 四角取景角标 + 底边数据基线（上面有一颗跑动的亮点） */
.cnr { position: absolute; width: 22px; height: 22px; z-index: 3; pointer-events: none; opacity: .85; }
.cnr.tl { left: 16px; top: 16px; border-left: 1px solid rgba(76, 123, 255, .58); border-top: 1px solid rgba(76, 123, 255, .58); }
.cnr.tr { right: 16px; top: 16px; border-right: 1px solid rgba(76, 123, 255, .58); border-top: 1px solid rgba(76, 123, 255, .58); }
.cnr.bl { left: 16px; bottom: 16px; border-left: 1px solid rgba(76, 123, 255, .58); border-bottom: 1px solid rgba(76, 123, 255, .58); }
.cnr.br { right: 16px; bottom: 16px; border-right: 1px solid rgba(76, 123, 255, .58); border-bottom: 1px solid rgba(76, 123, 255, .58); }
.ai-horizon { position: absolute; left: 0; right: 0; bottom: 0; height: 12px; z-index: 3; pointer-events: none; }
.ai-horizon::before { content: ''; position: absolute; left: 0; right: 0; bottom: 0; height: 1px;
  background: linear-gradient(90deg, transparent, rgba(76, 123, 255, .5) 16%, rgba(47, 195, 222, .65) 50%, rgba(76, 123, 255, .5) 84%, transparent); }
.ai-horizon::after { content: ''; position: absolute; left: 0; right: 0; bottom: 1px; height: 8px;
  background-image: repeating-linear-gradient(90deg, rgba(76, 123, 255, .38) 0 1px, transparent 1px 56px);
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 12%, #000 88%, transparent);
  mask-image: linear-gradient(90deg, transparent, #000 12%, #000 88%, transparent); }
.ai-horizon i { position: absolute; bottom: -2px; left: 0; width: 26px; height: 5px; border-radius: 3px;
  background: linear-gradient(90deg, rgba(95, 227, 245, 0), rgba(95, 227, 245, .85), rgba(95, 227, 245, 0));
  filter: blur(1px); animation: cRun 11s linear infinite; }
@keyframes cRun { from { transform: translateX(-30px); } to { transform: translateX(calc(100vw + 30px)); } }
@media (max-width: 980px) { .ai-core { left: 50%; top: 44%; width: min(92vw, 460px); opacity: .8; } }
@media (prefers-reduced-motion: reduce) { .ai-core i, .ai-horizon i { animation: none !important; } }

/* ── 12.3 器件细节 ───────────────────────────────────────────────
   ⚠ .site-head 是 sticky（定位元素），电源线用 ::before 吊在它顶边；
     .site-foot 的深色带必须写在这份样式表**靠后**的位置，才压得住 §5 的浅色页脚。 */
:root { --hud: 76, 123, 255; --hud2: 47, 195, 222; }
/* ① 顶栏顶边一条「电源线」 */
.site-head::before { content: ''; position: absolute; left: 0; right: 0; top: -1px; height: 2px; pointer-events: none;
  background: linear-gradient(90deg, transparent, rgba(var(--hud), .6) 18%, rgba(var(--hud2), .78) 50%, rgba(var(--hud), .6) 82%, transparent); }
/* ② 首屏 eyebrow：呼吸的小方点 */
.eyebrow { position: relative; padding-left: 15px; }
.eyebrow::before { content: ''; position: absolute; left: 0; top: 50%; width: 7px; height: 7px; margin-top: -3.5px;
  background: rgba(var(--hud2), .9); box-shadow: 0 0 9px rgba(var(--hud2), .8);
  animation: dtBlink 2.2s ease-in-out infinite; }
@keyframes dtBlink { 0%, 100% { opacity: 1; } 50% { opacity: .22; } }
/* ③ 首屏两个按钮：对角括号 */
.hero-acts .btn { position: relative; }
.hero-acts .btn::before, .hero-acts .btn::after { content: ''; position: absolute; width: 8px; height: 8px; pointer-events: none; }
.hero-acts .btn::before { left: 6px; top: 6px; border-left: 1.5px solid rgba(255, 255, 255, .7); border-top: 1.5px solid rgba(255, 255, 255, .7); }
.hero-acts .btn::after { right: 6px; bottom: 6px; border-right: 1.5px solid rgba(255, 255, 255, .7); border-bottom: 1.5px solid rgba(255, 255, 255, .7); }
/* 浅色按钮上的括号改用蓝青，白括号在浅底上看不见 */
.hero-acts .btn-outline::before, .hero-acts .btn-ghost::before { border-color: rgba(var(--hud), .75); }
.hero-acts .btn-outline::after, .hero-acts .btn-ghost::after { border-color: rgba(var(--hud2), .75); }
/* ④ 数据条 → 仪表格：四角括号 + 等宽单位 + 数字辉光 + 底部刻度尺 + 一道慢扫光 */
.databar { position: relative; }
.databar::after { content: ''; position: absolute; top: -20%; bottom: -20%; width: 150px; pointer-events: none; z-index: 2;
  background: linear-gradient(100deg, transparent, rgba(var(--hud2), .10) 35%, rgba(var(--hud2), .17) 50%, rgba(var(--hud2), .10) 65%, transparent);
  transform: translateX(-220px); animation: dtSweep 8s linear infinite; }
@keyframes dtSweep { 0% { transform: translateX(-220px); } 55%, 100% { transform: translateX(720px); } }
.databar > div { position: relative;
  background-image: repeating-linear-gradient(90deg, rgba(var(--hud), .30) 0 1px, transparent 1px 9px),
                    linear-gradient(90deg, rgba(var(--hud), .22), rgba(var(--hud2), .26));
  background-size: calc(100% - 28px) 4px, calc(100% - 28px) 1px;
  background-position: 14px calc(100% - 10px), 14px calc(100% - 10px);
  background-repeat: repeat-x, no-repeat; }
.databar > div::before { content: ''; position: absolute; left: 9px; top: 9px; width: 9px; height: 9px;
  border-left: 1.5px solid rgba(var(--hud), .45); border-top: 1.5px solid rgba(var(--hud), .45); }
.databar > div::after { content: ''; position: absolute; right: 9px; bottom: 9px; width: 9px; height: 9px;
  border-right: 1.5px solid rgba(var(--hud2), .5); border-bottom: 1.5px solid rgba(var(--hud2), .5); }
.databar .v.num { text-shadow: 0 0 18px rgba(var(--hud), .30); }
.databar .v .u { font-family: var(--mono); font-weight: 700; color: rgba(var(--hud), .85); }
.databar .k { font-family: var(--mono); letter-spacing: .05em; }
/* ⑤ 区块标题：等宽编号 + 一条刻度尺跟在标题后面 */
main { counter-reset: dsec; }
.sec-head .h2::before { counter-increment: dsec; content: counter(dsec, decimal-leading-zero) " / ";
  font: 700 .58em/1 var(--mono); letter-spacing: .14em; color: rgba(var(--hud), .95); vertical-align: .24em; }
.sec-head .h2::after { content: ''; display: inline-block; width: min(150px, 16vw); height: 5px; margin-left: 16px; vertical-align: .14em;
  background: repeating-linear-gradient(90deg, rgba(var(--hud), .30) 0 1px, transparent 1px 9px),
             linear-gradient(90deg, rgba(var(--hud), .28), rgba(var(--hud2), .34));
  background-size: 100% 4px, 100% 1px; background-position: 0 bottom, 0 bottom; background-repeat: repeat-x, no-repeat; }
/* ⑥ 两条普通分隔线 → 数据线（页面里写成行内 border 的那两条） */
.sec[style*="border-bottom"], .sec-tight[style*="border-top"] { border-bottom: 0 !important; border-top: 0 !important; position: relative; }
.sec[style*="border-bottom"]::after, .sec-tight[style*="border-top"]::before { content: ''; position: absolute; left: 0; right: 0; height: 5px; pointer-events: none;
  background: repeating-linear-gradient(90deg, rgba(var(--hud), .26) 0 1px, transparent 1px 64px),
             linear-gradient(90deg, transparent, rgba(var(--hud), .40) 15%, rgba(var(--hud2), .48) 50%, rgba(var(--hud), .40) 85%, transparent);
  background-size: 100% 4px, 100% 1px; background-position: 0 bottom, 0 bottom; background-repeat: repeat-x, no-repeat; }
.sec[style*="border-bottom"]::after { bottom: 0; }
.sec-tight[style*="border-top"]::before { top: 0; }
/* ⑦ 页脚 → 深色终端带 */
.site-foot { margin-top: 88px; position: relative; overflow: hidden; border-top: 0;
  background: linear-gradient(180deg, #0A1122, #070B16); }
.site-foot::before { content: ''; position: absolute; left: 0; right: 0; top: 0; height: 1px;
  background: linear-gradient(90deg, transparent, rgba(var(--hud2), .8), transparent);
  box-shadow: 0 0 24px 2px rgba(var(--hud2), .4); }
.site-foot::after { content: ''; position: absolute; inset: 0; pointer-events: none;
  background: radial-gradient(620px 210px at 82% 130%, rgba(var(--hud), .18), transparent 70%); }
.site-foot .foot-in { position: relative; z-index: 1; }
.site-foot .foot-slogan { color: #dbe7ff; }
.site-foot .copyright { color: #63779c; font-family: var(--mono); }
.site-foot .foot-links a { color: #8fa4c8; font-family: var(--mono); letter-spacing: .04em; }
.site-foot .foot-links a:hover { color: #fff; text-shadow: 0 0 12px rgba(var(--hud2), .8); }
.dt-status { display: inline-flex; align-items: center; gap: 8px; margin-top: 8px;
  font: 12px var(--mono); color: #9db2d8; letter-spacing: .08em; }
.dt-status i { width: 7px; height: 7px; border-radius: 50%; background: #2FC3DE;
  box-shadow: 0 0 10px rgba(47, 195, 222, .9); animation: dtBlink 2s ease-in-out infinite; }
/* ── 12.4 后台同步 ────────────────────────────────────────────────
   门帘与面板原来自刷不透明底色（var(--page)），把全站光晕整片盖死，
   后台看着像另一个站。放通这两处，后台和前台共用同一片底。
   ⚠ 两条必须留在 §12（表尾）：.lock-wrap/.admin 的底色写在本表前面，
   同特异性下靠「后来居上」才压得住。 */
.lock-wrap, .admin { background: transparent; }
/* 门帘的「登录」= 全页唯一主按钮，补上首屏按钮同款的白括号 */
.lock .btn { position: relative; }
.lock .btn::before, .lock .btn::after { content: ''; position: absolute; width: 8px; height: 8px; pointer-events: none; }
.lock .btn::before { left: 6px; top: 6px; border-left: 1.5px solid rgba(255, 255, 255, .7); border-top: 1.5px solid rgba(255, 255, 255, .7); }
.lock .btn::after { right: 6px; bottom: 6px; border-right: 1.5px solid rgba(255, 255, 255, .7); border-bottom: 1.5px solid rgba(255, 255, 255, .7); }
@media (prefers-reduced-motion: reduce) { .eyebrow::before, .databar::after, .dt-status i { animation: none; } }
