/* 以交接包 Token 为基础；字体、标题级差与分区间距已按后续页面反馈校准。
 * 正文字号保持 16px，标题和留白节奏以当前站点截图为准。
 *
 * 本文件是全站颜色的**唯一真源**（DESIGN.md §4/§6）：
 *   · styles/experience.css 不再声明 :root 颜色覆写，只引用这里的语义变量；
 *   · 新增语义色请加在这里，不要在组件里写十六进制近似色。
 *   · 外观（modern/classic）已固定为 modern 常驻，本文件不再有 classic 分支。
 *   · **主题（浅色/深色）也只有这一个入口**：浅色是 :root 的默认值，
 *     深色是文件下半部分的 `[data-theme='dark']` 覆写块。
 *     组件里不要写 `[data-theme='dark'] .xxx { background: #000 }` ——
 *     那样子类会散落两套配色，切换主题时必然有人漏改（这条规矩和"颜色单一真源"是同一条）。
 * 数值与档位（圆角 10/16/20、手机 23px 边距）见下方注释。 */

/* 调色板：**只在本文件内部使用**，组件一律引用下面的语义变量。
 * 把它们写成变量而不是散落的字面量，是因为同一个蓝在浅色与深色下要出现在
 * 十来处（边框、焦点环、柔光、文字），写死就意味着十几处一起改。
 * 命名前缀 --palette 属于本文件，不属于公共 API。 */
:root {
  /* 组件底色轻微透光：普通面 88%，浮层/输入面 94%；不降低内容 opacity。 */
  --border-card: 1px solid var(--color-border);
  /* 页面材质上的透光分区；深浅颜色随已有语义变量解析。 */
  --color-page-header: color-mix(in srgb, var(--color-bg) 8%, transparent);
  --color-page-footer: color-mix(in srgb, var(--color-bg) 94%, transparent);
  --color-page-section: transparent;
  /* 主蓝族：浅色用原始品牌蓝；深色提到 400 档，
     因为 #4063FB 压在近黑底上只有约 3.3:1 —— 不到 AA 正文的 4.5:1。 */
  --palette-blue: #4063FB;
  --palette-blue-hover: #3152E5;
  --palette-blue-deep: #234FC4;   /* 深底上的按钮底色（白字 ≥4.5:1） */
  --palette-blue-bright: #6B8BFF; /* 深底上的文字与描边 */
  --palette-blue-soft: #EEF2FF;
  --palette-blue-line: #CBD4F5;   /* 浅色下的装饰连线，同 --color-topology-line */
  --palette-blue-line-dark: #3A4A7A;
  --palette-blue-ink: #304FC9;    /* 浅蓝底上的深蓝文字 */
  --palette-blue-ink-bright: #A9BCFF; /* 深色下的同一角色 */
  /* 青绿族：品牌强调色。浅色下的小字号青色对比度不足，
     所以"当文字用"的那一档单独取深值（--color-status-forest 已经是这个角色）。 */
  --palette-teal: #0FDBBA;
  --palette-teal-soft: #D9FAF4;
  /* 中性族 */
  --palette-ink: #17191D;
  --palette-ink-soft: #2B2F36;    /* 深中性填充：主按钮 hover */
  --palette-gray: #626872;
  --palette-line: #E3E6EA;
  --palette-line-soft: #E6EAF4;
  --palette-line-muted: #E3E8F3;
  --palette-surface-muted: #F8FAFF;
  --palette-surface-soft: #F7F9FC;
  --palette-surface-tint: #F1F4FC;
  --palette-section: #F5F7FB;
  /* 深色中性族 */
  --palette-dark-bg: #0F1115;
  --palette-dark-section: #151922;
  --palette-dark-surface: #171B24;
  --palette-dark-raised: #232830;
  --palette-dark-text: #F2F4F8;
  --palette-dark-secondary: #A2A9B6;
  /* 阴影：浅色是"黑影子"，深色只能靠更深的黑加不透明度 ——
     照搬浅色的 rgba(23,25,29,.06) 在深底上等于没画。 */
  --palette-shadow-soft: rgba(23, 25, 29, .06);
  --palette-shadow-strong: rgba(27, 48, 115, .11);
  --palette-shadow-dark: rgba(0, 0, 0, .45);
}
:root {
  /* 让浏览器知道本页支持两套主题：没有它，深色页面里的滚动条、
     原生 <input> 与 <dialog> 仍是浅色 chrome，看起来像"没做完"。
     实际值先由 <head> 的预置脚本写成 'light dark'，这里是 CSS 侧的兜底声明。 */
  color-scheme: light;
  --font-sans: 'Noto Sans SC', 'PingFang SC', 'Microsoft YaHei', sans-serif;
  --color-bg: #ffffff;
  --color-section: color-mix(in srgb, var(--palette-section) 88%, transparent);
  --color-surface: rgba(255, 255, 255, .72);
  --color-text: var(--palette-ink);
  --color-secondary: var(--palette-gray);
  --color-border: var(--palette-line);
  /* ── 颜色单一真源（DESIGN.md §4 / §6）─────────────────────────────
     本节是全站唯一的颜色定义处。styles/experience.css 不得再覆写
     :root 颜色，也不得散落语义色的十六进制字面量。
     主蓝、主按钮、焦点环、当前导航共用同一主蓝，避免"蓝色近似的
     三套值"在切换页面时产生色差。 */
  --color-action: var(--palette-blue);
  --color-action-text: #ffffff;
  --color-focus: var(--palette-blue);
  --color-brand-primary: var(--palette-blue);
  --color-brand-primary-hover: var(--palette-blue-hover);
  --color-brand-accent: var(--palette-teal);
  /* 主蓝的浅色渲染：浅底块、序号徽标、装饰条。 */
  --color-brand-soft: var(--palette-blue-soft);
  /* 青绿的浅色渲染：光引导/已识别状态的浅底。 */
  --color-accent-soft: var(--palette-teal-soft);
  /* ── 交互与面层（深色模式新增的语义层）────────────────────────────
     这四组存在的理由：浅色下"白卡""浅分区""半透明浮层""深中性 hover"
     都是直接写 #fff / rgba(255,255,255,.97) / #2b2f36 的，
     深色下它们必须各自变成另一种颜色，而且**不能共用一个变量** ——
     卡片底和浮层底在深色下不是同一个灰（浮层要更亮才有"浮起来"的观感）。 */
  --color-surface-raised: rgba(255, 255, 255, .86);           /* 白卡、对话框、编辑输入框 */
  --color-surface-glass: rgba(255, 255, 255, .94); /* 顶栏、浮层 */
  --color-surface-overlay: rgba(255, 255, 255, .74); /* 卡内小结区 */
  --color-surface-wash: rgba(255, 255, 255, .55);  /* 图解面上的淡洗 */
  --color-control-hover: var(--palette-ink-soft);  /* 深中性按钮 hover */
  --color-control-hover-soft: #F2F3F5;
  /* 青蓝强调文字：浅蓝底上的小字（拓扑节点种类、工位名、当前项）。
     浅色下是深蓝，深色下必须整族提亮，否则这十来处一起看不清。 */
  --color-accent-text: var(--palette-blue-ink);
  --color-accent-line: #9EAFFF;              /* 软件/运行中节点的描边 */
  --color-accent-line-soft: #92A5FF;
  /* 控件层的轻边界与浅底：用于部署配置器等交互区域。 */
  --color-border-muted: var(--palette-line-muted);
  --color-border-light: var(--palette-line-soft);
  --color-surface-muted: color-mix(in srgb, var(--palette-surface-muted) 72%, transparent);
  --color-surface-soft: color-mix(in srgb, var(--palette-surface-soft) 72%, transparent);
  --color-surface-tint: color-mix(in srgb, var(--palette-surface-tint) 72%, transparent);
  /* 部署拓扑连线（装饰性连线，非状态色）。 */
  --color-topology-line: var(--palette-blue-line);
  /* 青绿浅底上的深青文字（保证对比度）。 */
  --color-status-forest: #087A68;
  /* 图片上的遮罩与深色玻璃卡：**刻意不跟随主题**。
     它们压在照片上，不是"页面的底"，翻成浅色会让照片上的白字失去依托。
     登记在这里而不是留在组件里，是为了让"不跟随主题的那些色"有一处名单。 */
  --color-scrim-weak: rgba(7, 18, 32, .02);
  --color-scrim-strong: rgba(7, 18, 32, .22);
  --color-glass-fill: rgba(12, 26, 45, .28);
  --color-glass-border: rgba(255, 255, 255, .28);
  --color-on-media: #ffffff;
  --color-on-media-dim: rgba(255, 255, 255, .88);
  --color-on-media-kicker: rgba(255, 255, 255, .92);
  --color-dialog-backdrop: rgba(23, 25, 29, .38);
  /* 提醒色：仅用于错误/必要提醒，不作日常装饰（DESIGN.md §4）。
     当前界面尚无错误态，先登记备用；使用时应配文字说明，不单独依赖颜色传达含义。
     `--color-alert` 为原色，实际落地的文字/描边用下面两个派生值以保证对比度。 */
  --color-alert: #FF6B5B;
  --color-alert-border: #F0C5C5;
  --color-alert-text: #C04040;
  /* ── 页面质感层（2026-09-30）──────────────────────────────────────
     参考站（DeepSeek Harness）的"质感"不是靠图，是三层 CSS 叠出来的：
       ① 片状柔光：几块大半径 radial-gradient，用 blur 之外的方式晕开
          （radial-gradient 本身就是柔的，不必再加 filter）；
       ② 上下压薄的纱：一层极淡的线性渐变，把页面两端收住；
       ③ 细网格：1px 网格 + 径向遮罩，只在视觉中心附近可见。
     三层都画在 `html` 上（`background-image`，不是额外元素）——
     这样它们永远在所有内容之下，不参与布局、不产生新的定位层，
     也不会被 site-shots 的"仅一层背景"断言误判。
     值按主题各一套：浅色是"纸上的淡蓝灰印花"，深色才是真正的发光。
     浅色使用低浓度的全高环境光，页面分区不再遮挡，避免局部光源过亮。 */
  --page-sheen:
    /* 全高环境光不断层；浅色降低浓度，局部柔光只提供轻微层次。 */
    linear-gradient(178deg, rgba(64, 99, 251, .06) 0%, rgba(64, 99, 251, .045) 38%, rgba(15, 219, 186, .035) 68%, rgba(64, 99, 251, .05) 100%),
    radial-gradient(62% 34% at 50% -4%, rgba(64, 99, 251, .10), transparent 78%),
    radial-gradient(40% 26% at 2% 1%, rgba(15, 219, 186, .06), transparent 76%),
    radial-gradient(44% 30% at 100% 0%, rgba(64, 99, 251, .07), transparent 78%),
    radial-gradient(64% 24% at 50% 104%, rgba(64, 99, 251, .06), transparent 80%);
  --page-veil: linear-gradient(180deg, rgba(64, 99, 251, .025), rgba(64, 99, 251, 0) 24%, rgba(23, 25, 29, 0) 70%, rgba(23, 25, 29, .02));
  /* 网格的渐隐层 + 混色方式：浅色网格是黑线，用 multiply 渐隐（白＝不改变下层）。
     深色网格是白线，改用 screen（黑＝不改变下层）。见本文件「页面质感」一节。 */
  /* 品牌 Logo 的受色面：**字标跟随主题，青绿强调保留品牌原色**。
     原始 SVG 里圆标 + 7 个字形 + 「中军视觉」都是 #4065fc，圆标内是白色图形。
     内联之后（见 scripts/brand-mark.js 与工具「品牌图形提取」）：
       · --logo-wordmark  圆标与全部字标（浅底近黑 / 深底反白）——
                          深底上 #4065fc 只有约 2.7:1，蓝字读不清；
       · --logo-mark-inner 圆标**内部**的图形，取页面底色才能读出缺口；
       · --logo-accent    字标里的青绿强调（浅色下取深青以保住小字号对比度）。 */
  --logo-wordmark: var(--palette-ink);
  --logo-mark-inner: var(--color-bg);
  --logo-accent: var(--color-status-forest);
  --space-1: 4px;
  --space-2: 8px;
  --space-3: 12px;
  --space-4: 16px;
  --space-5: 24px;
  --space-6: 32px;
  --space-7: 40px;
  --space-8: 48px;
  --space-9: 64px;
  --space-10: 96px;
  --space-11: 128px;
  --container-max: 1200px;
  --page-gutter: 40px;
  --header-height: 76px;
  --logo-box-height: 32px;
  --hero-gap: 32px;
  /* 首屏标题（2026-09-29 第三轮放大：56px → 68px 上限），首页与内页共用一把尺。
     三个数都是算出来的，不是随手定的：
       · 上限 68px：最长的标题行是 8 个全角字（「看清每一步作业。」），
         桌面内容列宽约 564px，8 × 68 × 0.965 ≈ 525px，放得下；再大就挤成三行。
       · 下限 48px：768~1000px 之间仍是两栏布局，列宽只有约 395~480px，
         8 字 × 48px ≈ 371px 是这一档的安全值。
       · 4.4vw 中段：让字号跟着列宽一起长，避免"列变宽了字还那么小"。
     改标题文案（尤其把某一行写到 8 字以上）要回来复算这三个数。 */
  --hero-title-size: clamp(48px, 4.4vw, 68px);
  --hero-title-line: 1.18;
  --hero-title-tracking: -.035em;
  --section-title-size: clamp(34px, 3.1vw, 44px);
  --module-title-size: 26px;
  --body-size: 16px;
  --body-line: 1.65;
  --label-size: 15px;
  --caption-size: 14px;
  /* 区块上下内距（桌面）。**2026-09-30 收紧**：原 `clamp(64px, 5.6vw, 80px)`
     在 1440px 就顶到上限 80px，上下合计 160px —— 一屏里"空白比内容还多"，
     用户明确要求桌面更紧凑。现取 `clamp(48px, 4.2vw, 60px)`：1024px≈48px、
     1440px≈60px、1920px 仍是 60px（不再随视口无限长大）。
     手机档在下面的断点里单独给 52px，不受这条影响。 */
  --section-pad-block: clamp(48px, 4.2vw, 60px);
  /* 首屏上下内距：**首页与内页共用这一对变量**（2026-09-29）。
     原先首页由 config/geometry.js 写成 24/16（那是为了对齐原型图里媒体的 y 坐标，
     geometry.js 里也注明了"约 30px 的固定偏差"），内页自己写 clamp(64px,6vw,84px) ——
     两边各一套，结果两页首屏高度差了 180px，用户明确要求对齐。
     现在合成一处：桌面取原来内页那套（它更好看、也更接近"首屏要放大"的规范），
     手机取 48/52。改这里就是改两页，不要再回到按页写死的做法。 */
  /* 首屏上内距：导航下方到标题。桌面 24px（原 `clamp(24px,3vw,40px)` 在 1440px 会
     涨到 40px，与"首屏要紧凑"相抵）。 */
  --hero-pad-block-top: clamp(20px, 2.2vw, 28px);
  /* 首屏下内距：标题/正文到下一区块。**2026-09-30 收紧**：原上限 80px 是
     整页最大的单块留白（1440px 实测 hero 下内距 80px），现取 52px 上限。
     上内距 + 下内距从 24+80=104 收到 24+52=76。 */
  --hero-pad-block-bottom: clamp(40px, 4vw, 52px);
  /* 首屏高度下限（≥960px 生效）：**两页首屏等高靠它保证，而不是靠凑内容**。
     2026-09-29 实测：两页内距统一后仍差 11px —— 来源是两页正文行数（53 / 58px）、
     标题行高与按钮上边距的细小差异。逐像素去追这些差异既脆弱又没意义
     （改一句文案就会破），所以给首屏一条共同的下限、内容垂直居中：
     内容短的那页留白多一点，两页的**外框高度一定相同**。
     2026-09-30 桌面收紧：600 → 540。原值比两页当前内容高度（574 / 563）还高，
     等于**凭空多留 30–40px 空白**；540 仍高于内容高度，"两页等高"的作用不变，
     但首屏整体矮一截。 */
  --hero-screen-min: 540px;
  --weight-regular: 400;
  --weight-medium: 500;
  --weight-semibold: 600;
  --radius-control: 10px;
  --radius-card: 16px;
  --radius-media: 20px;
  --radius-pill: 999px;
  --button-height: 48px;
  --nav-button-height: 40px;
  --tab-height: 44px;
  --shadow-media: 0 16px 48px var(--palette-shadow-soft);
  --motion-fast: 160ms;
  --motion-standard: 240ms;
  --motion-ease: ease-out;
}

/* ── 深色主题 ───────────────────────────────────────────────────────────
 *
 * 唯一钩子是 `<html data-theme='dark'>`，由两处写入：
 *   · 页面 `<head>` 里的同步预置脚本（首帧之前，见 scripts/theme.js）；
 *   · 运行时切换按钮（scripts/theme.js 的 initTheme）。
 * 两者解析的是同一个偏好（localStorage 的 kvisio-theme，缺省跟随系统）。
 *
 * 设计判断（照参考站 DS 的做法，见 https://www.deepseek.com/harness/ ）：
 *   1. **只覆写语义变量，不写任何组件选择器。** 组件照旧引用 var(--color-*)，
 *      所以"深色下漏了一块白"这种缺陷只会来自这里漏了一个变量，
 *      而不是散落在 3000 行里的某一个选择器。
 *   2. **不是把浅色反相。** 底色用近黑而非纯黑（#0F1115），
 *      分区比底色**浅**（#151922）：深色下"分区"靠变亮来表达层次，
 *      照搬浅色那套"分区比页面深一点"会得到一堆看不见的块。
 *   3. **主蓝提亮。** #4063FB 在近黑底上约 3.3:1，不到正文 AA；
 *      深色下按钮底用 #234FC4、文字与描边用 #6B8BFF。
 *   4. **照片上的遮罩与玻璃卡不跟着变**（--color-scrim-*、--color-glass-*、
 *      --color-on-media-* 定义在 :root 且此处不覆写）：
 *      它们压在图片上，翻成浅色会让图上的白字失去依托。
 *   5. 阴影改用更深的黑加更高不透明度 —— 浅色那套淡黑影子在深底上看不见。
 */
[data-theme='dark'] {
  color-scheme: dark;
  --color-bg: var(--palette-dark-bg);
  --color-section: color-mix(in srgb, var(--palette-dark-section) 88%, transparent);
  --color-surface: color-mix(in srgb, var(--palette-dark-surface) 88%, transparent);
  --color-text: var(--palette-dark-text);
  --color-secondary: var(--palette-dark-secondary);
  --color-border: #2A2F3A;

  --color-action: var(--palette-blue-deep);
  --color-focus: var(--palette-blue-bright);
  --color-brand-primary: var(--palette-blue-deep);
  --color-brand-primary-hover: var(--palette-blue);
  --color-brand-accent: var(--palette-teal);

  --color-brand-soft: #1B2136;
  --color-accent-soft: #102B27;

  --color-surface-raised: color-mix(in srgb, var(--palette-dark-raised) 94%, transparent);
  --color-surface-glass: rgba(23, 27, 36, .94);
  --color-surface-overlay: rgba(23, 27, 36, .82);
  --color-surface-wash: rgba(255, 255, 255, .06);
  --color-control-hover: #333A46;
  --color-control-hover-soft: #232833;

  --color-accent-text: var(--palette-blue-ink-bright);
  --color-accent-line: #46579B;
  --color-accent-line-soft: #3E4E8C;

  --color-border-muted: #2E3542;
  --color-border-light: #262C38;
  --color-surface-muted: rgba(23, 28, 37, .88);
  --color-surface-soft: rgba(20, 25, 34, .88);
  --color-surface-tint: rgba(26, 31, 41, .88);
  --color-topology-line: var(--palette-blue-line-dark);

  --color-status-forest: #4FD6BE;

  --color-alert-border: #6B3A38;
  --color-alert-text: #FF8C7E;

  --color-dialog-backdrop: rgba(0, 0, 0, .62);

  --shadow-media: 0 16px 48px var(--palette-shadow-dark);

  --logo-wordmark: var(--palette-dark-text);
  --logo-accent: var(--palette-teal);

  /* 质感层在深色下才是它真正的样子：柔光要能看见、纱要往下收、
     网格线要反过来（深底上用白线，浅色那套黑线在近黑底上什么都看不见）。 */
  --page-sheen:
    linear-gradient(180deg, rgba(64, 99, 251, .06), rgba(15, 219, 186, .04) 45%, rgba(107, 139, 255, .055)),
    radial-gradient(58% 44% at 50% -6%, rgba(64, 99, 251, .15), transparent 72%),
    radial-gradient(46% 34% at 4% 6%, rgba(15, 219, 186, .06), transparent 70%),
    radial-gradient(50% 38% at 100% 4%, rgba(107, 139, 255, .11), transparent 72%),
    radial-gradient(64% 34% at 50% 106%, rgba(64, 99, 251, .10), transparent 74%);
  --page-veil: linear-gradient(180deg, rgba(107, 139, 255, .07), rgba(107, 139, 255, 0) 26%, rgba(0, 0, 0, 0) 66%, rgba(0, 0, 0, .14));
}@media (max-width: 1279px) { :root { --page-gutter: 32px; } }
@media (max-width: 959px) { :root { --header-height: 68px; } }
@media (max-width: 767px) {
  :root {
    /* 手机内容边距 23px：与已确认的手机截图内容边缘一致（DESIGN.md §4）。
       此前 tokens 写 20px、site.css 又硬编码 23px 覆写，属同值双重定义，已收敛到此。 */
    --page-gutter: 23px;
    --logo-box-height: 30px;
    /* 手机首屏标题：内容宽 390 - 23×2 = 344px，8 个全角字 × 40px = 320px，放得下；
       42px 就顶到 336px 了，没有余量。 */
    --hero-title-size: clamp(18px, calc((100vw - var(--page-gutter) * 2) * .082), 32px);
    --hero-title-line: 1.35;
    --section-title-size: clamp(18px, calc((100vw - var(--page-gutter) * 2) * .07), 28px);
    --module-title-size: 18px;
    --body-size: 14px;
    --label-size: 14px;
    --radius-media: 16px;
    --section-pad-block: 52px;
  }
}
@media (max-width: 360px) { :root { --logo-box-height: 28px;  } }
/* These are reusable foundations, not a complete website implementation. */

/* ── 页面质感：三层画在 html 上 ─────────────────────────────────────────
 *
 * 为什么放在 `html` 而不是新加一个装饰元素：
 *   · 它是**背景**，不是内容。画在根元素的 `background-image` 上，
 *     天然在所有内容之下，不需要 z-index、不产生新的层叠上下文；
 *   · 不增加 DOM，因此不参与任何"顶层分区顺序""仅一层背景"之类的结构断言；
 *   · **随页面铺开**（不要加 `background-attachment: fixed`，理由写在下面的规则里）：
 *     固定在视口上会让整页只有"第一屏"那一带有光，往下滚是纯白 ——
 *     这正是"光晕没有全局生效"的原因。实测证据见下方规则内注释。
 *
 * 顺序（先写的在上层）：纱 → 柔光 → 底色。纱在柔光之上，才能把页面两端压住。
 *
 * 性能：全是 CSS 渐变，没有滤镜、没有 canvas、没有额外资源；
 * 首屏绘制不依赖任何脚本。
 *
 * ⚠️ 减弱动效 / 弱网下**不需要降级**：这几层是静态的，与动效无关。
 *    唯一要守的是 `body` 必须保持透明，否则会把这三层全盖住。
 */
html {
  background-color: var(--color-bg);
  /* 三层，先写的在上：纱 → 柔光 → 底色。
     ⚠️ 这里**刻意没有点阵/网格纹理**。试过两版（1px 线、1px 点，22–40px 间距），
     都因为同一个原因撤掉：纹理固定在视口上，而站内多个分区的底色是**透明**的
     （关键数据条本身就没有底色），纹理从这些分区底下透出来后会读成"一格格方块"，
     比纹理本身显眼得多。而给分区逐块补不透明底色，等于把"统一底纹"拆散到十来个选择器里。
     结论：**质感靠柔光的连续过渡，不靠可辨的规则图案** —— 连续渐变不与任何分区边界打架。
     （另一条踩过的坑：不要用 `html { mask }` 做纹理渐隐 —— 根元素加遮罩会把整页提成合成层，
       实测深色下整页被抬成灰白，不报错、控制台干净，只有肉眼能发现。） */
  background-image:
    var(--page-veil),
    var(--page-sheen),
    linear-gradient(var(--color-bg), var(--color-bg));
  /* ⚠️ **不要加 `background-attachment: fixed`。**
     加了它，这层背景就固定在**视口**上：径向柔光的尺寸按视口算，
     于是整页只有"第一屏"那一带有光，往下滚是纯白。实测证据：2400px 高的页面上，
     滚动到 0 / 400 / 800 / 1200 / 1600 / 2000 时，同一位置的像素**完全相同**
     （都是 rgb(211,235,247)）—— 背景没跟着页面走，所以"光晕没有全局生效"。
     不加 fixed 时背景按**页面**铺开、随页面滚动，柔光才是整页的环境光。
     代价是失去视差感；对本站这种"长页面 + 分区底色"的构成，全局一致更重要。 */
  background-size: auto;
  background-repeat: no-repeat;
}
body { background: transparent; }

.site-container { width: min(var(--container-max), calc(100% - var(--page-gutter) * 2)); margin-inline: auto; }
.hero-grid { display: grid; grid-template-columns: minmax(0,.374fr) minmax(0,.626fr); gap: var(--hero-gap); align-items: center; }
/* 2026-09-29 删除 .module-grid：它是交接包时期的模块区两栏网格，
   现在的平台模块区用 .platform__panel 自己的栅格，这个类源码与运行时 DOM 里都不存在。 */
.module-tabs { display: flex; gap: 8px; overflow-x: auto; scrollbar-width: thin; }
.module-tabs > * { flex: 0 0 auto; min-height: var(--tab-height); }
@media (max-width: 959px) { .hero-grid { grid-template-columns: minmax(0,1fr); } }
@media (prefers-reduced-motion: reduce) {
  :root { --motion-fast: 0ms; --motion-standard: 0ms; }
}
/* 共享组件的语义字号、间距；专题图解使用独立角色。 */
:root {
  --weight-heading: 650;
  --section-title-line: 1.2;
  --card-title-size: 17px;
  --module-title-line: 1.35;
  --title-tracking: -.025em;
  --copy-tracking: 0em;
  --title-intro-gap: 16px;
  --heading-content-gap: 32px;
  --card-gap: 24px;
  --card-padding: 24px;
  --compact-padding: 16px;
  --compact-section-padding: 32px;
  --control-touch-height: 44px;
  --wordcloud-major-size: clamp(18px, 2.4vw, 28px);
  --wordcloud-medium-size: clamp(14px, 1.6vw, 18px);
  --wordcloud-small-size: 12px;
}
@media (max-width: 767px) { :root {
  --section-title-line: 1.35;
  --card-title-size: 16px;
  --caption-size: 12px;
  --title-intro-gap: 12px;
  --heading-content-gap: 24px;
  --card-gap: 16px;
  --card-padding: 16px;
  --compact-padding: 12px;
  --compact-section-padding: 24px;
} }

/* 图解、数量与词云独立于正文角色。 */
:root { --diagram-label-size:12px; --diagram-title-size:14px; --metric-number-size:clamp(38px,3.6vw,54px); }
@media (max-width:767px) { :root { --diagram-label-size:11px; --diagram-title-size:12px; } }

:root { --product-tab-width:128px; --product-tab-step:140px; }
