/* =============================================================
   中军视觉官网 — 站点样式
   只消费 styles/tokens.css 的 Token 变量；不在此散落近似灰/圆角/间距。
   分区顺序：基础 → 布局 → 导航 → 首屏 → 客户带 → 平台区 → 光引导
             → 延展区 → 联系弹层 → 页脚 → 工具类
   ============================================================= */

/* 校准变量：默认值与 config/geometry.js 保持一致；
   main.js 会用同一份配置覆盖这些变量，保证"改一处即生效"。 */
:root {
  --hero-align-offset: -12px;
  --hero-visual-width: 771px;
  --hero-media-max-width: 735px;
  --light-visual-width: 702px;
  --light-media-max-width: 702px;
  --platform-pad-top: 48px;
  --platform-pad-bottom: 43px;
  --platform-heading-to-eyebrow: 24px;
  --platform-heading-to-tabs: 32px;
  --platform-tab-row-height: 40px;
  --platform-tabs-to-panel: 24px;
  --module-panel-height: 198px;
  --module-panel-height-mobile: 185px;
  --light-pad-top: 96px;
  --light-pad-bottom: 96px;
  --platform-pad-top-mobile: 48px;
  --platform-pad-bottom-mobile: 64px;
  --light-pad-top-mobile: 56px;
  --light-pad-bottom-mobile: 64px;
}

/* ---------- 1. 基础 ---------- */
*,
*::before,
*::after { box-sizing: border-box; }

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
}

body {
  margin: 0;
  /* **保持透明**：页面的底色与质感层（柔光/纱/网格）画在 `html` 上，
     见 tokens.css 的「页面质感」一节。给 body 上不透明底色会把那三层整个盖住 ——
     那时页面看起来"还是白的"，而且不报错、不溢出，只有肉眼能发现。 */
  background: transparent;
  color: var(--color-text);
  font-family: var(--font-sans);
  font-size: var(--body-size);
  line-height: var(--body-line);
  font-weight: var(--weight-regular);
  letter-spacing: normal; /* 中文不使用负字距 */
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

h1, h2, h3, h4, p, figure, blockquote, dl, dd { margin: 0; }
ul, ol { margin: 0; padding: 0; list-style: none; }

/* 任何带 display 的组件都可能覆盖 hidden 属性的默认 display:none
   （例如 .product-line-panel 用 display:grid），使 [hidden] 的 tabpanel 仍然可见。
   这里统一兜底：hidden 必须生效，不依赖各组件单独补 [hidden] 规则。 */
[hidden] { display: none !important; }

img {
  max-width: 100%;
  height: auto;
  border-style: none;
}

button {
  font: inherit;
  color: inherit;
  background: none;
  border: 0;
  padding: 0;
  cursor: pointer;
}

a { color: inherit; text-decoration: none; }

:focus-visible {
  outline: 2px solid var(--color-focus);
  outline-offset: 2px;
  border-radius: 4px;
}
:focus:not(:focus-visible) { outline: none; }

/* 非全局 overflow 掩盖：仅用于确认区域存在的横向滚动容器 */
.visually-hidden {
  position: absolute;
  width: 1px; height: 1px;
  margin: -1px; padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  white-space: nowrap;
}

.skip-link {
  position: absolute;
  left: var(--page-gutter);
  top: -60px;
  z-index: 100;
  padding: 10px 16px;
  background: var(--color-action);
  color: var(--color-action-text);
  border-radius: var(--radius-control);
  transition: top var(--motion-fast) var(--motion-ease);
}
.skip-link:focus { top: 8px; }

/* ---------- 2. 布局 ---------- */
.site-container {
  width: min(var(--container-max), calc(100% - var(--page-gutter) * 2));
  margin-inline: auto;
}

/* 锚点定位时不落在 sticky 导航下面 */
[id] { scroll-margin-top: var(--header-height); }

.section { border-top: 1px solid transparent; }
.section--light { background: var(--color-bg); }
.section--tinted { background: var(--color-section); }
.section__inner { padding-block: var(--section-pad-block, 96px); }
.section-head__eyebrow {
  display: block;
  font-size: var(--label-size);
  line-height: 1.4;
  font-weight: var(--weight-medium);
  color: var(--color-secondary);
  margin-bottom: var(--space-3);
}
.section-head__intro {;
  max-width: 62ch;
}

.extension-badge {
  display: inline-block;
  font-size: var(--caption-size);
  line-height: 1.5;
  color: var(--color-secondary);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-pill);
  padding: 2px 10px;
  margin-bottom: var(--space-3);
}

/* ---------- 3. 导航 ---------- */
/* 挂载点必须自己 sticky（2026-09-29 刷新后顶栏消失）：
   `.site-header` 的父节点只有 76px 高，sticky 的活动范围被限制在父盒子里，
   一滚动就跟着盒子滑出视口（实测 scrollY=76 时 header rect.top=-76）。
   粘性做在挂载点上：它的父级是 body，才有整页高度可粘。 */
[data-component="header"] {
  position: sticky;
  top: 0;
  z-index: 40;
}
.site-header {
  height: var(--header-height);
  background: var(--color-bg);
  border-bottom: 1px solid var(--color-border);
}
.site-header__inner {
  height: 100%;
  display: flex;
  align-items: center;
  gap: var(--space-5);
}

.brand { display: flex; align-items: center; gap: var(--space-2); flex: 0 0 auto; }
/* 真实 Logo：按统一品牌尺度缩放（当前高 32px），contain 保证任何比例都不变形。
   已裁掉原文件的透明边距，因此视觉高度即占满适配区，不会显得比导航文字小一圈。 */
.brand__logo-slot {
  display: flex;
  align-items: center;
  height: var(--logo-box-height, 32px);
}
.brand__logo-slot img {
  display: block;
  height: 100%;
  width: auto;
  max-width: none;
  object-fit: contain;
}
/* 内联 Logo（scripts/brand-mark.js 生成的真实 DOM）。
   尺寸与槽位里的 `<img>` 一致：高度来自 --logo-box-height，宽度由 viewBox 比例决定，
   所以两者互换时页头不跳动。它内部没有 currentColor，
   颜色由每个槽位自己的 fill 决定（见 tokens.css 的 --logo-*），所以这里不写 color。 */
.brand__logo-slot svg { display: block; height: 100%; width: auto; }
/* 槽位里的 `<img>` 是**同一份图形**的位图式回退：内联 SVG 正常渲染时它是多余的，
   所以隐藏它；它存在的意义是 DOM 完整性（"六个页面共用一个页头"这条不变量的兜底），
   以及在样式表未加载时仍能靠 img 的固有尺寸占位。 */
.brand__logo-slot .brand__logo-fallback { display: none; }

.site-nav { margin-left: auto; }
.site-nav__list { display: flex; align-items: center; gap: var(--space-6); }
.site-nav__link {
  display: inline-flex;
  align-items: center;
  height: var(--nav-button-height);
  
  
  
  color: var(--color-text);
  border-radius: var(--radius-control);
  padding-inline: 4px;
  transition: color var(--motion-fast) var(--motion-ease);
}
.site-nav__link:hover { color: var(--color-secondary); }

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  height: var(--button-height);
  padding-inline: var(--space-5);
  border-radius: var(--radius-control);
  
  
  
  white-space: nowrap;
  cursor: pointer;
  transition: background-color var(--motion-fast) var(--motion-ease),
              color var(--motion-fast) var(--motion-ease),
              border-color var(--motion-fast) var(--motion-ease);
}
.btn--primary {
  background: var(--color-action);
  color: var(--color-action-text);
  border: 1px solid var(--color-action);
}
.btn--primary:hover { background: var(--color-control-hover); border-color: var(--color-control-hover); }

.btn--nav {
  height: var(--nav-button-height);
  padding-inline: var(--space-5);
  background: var(--color-action);
  color: var(--color-action-text);
  border: 1px solid var(--color-action);
}
.btn--nav:hover { background: var(--color-control-hover); border-color: var(--color-control-hover); }

.btn--quiet {
  background: var(--color-surface);
  color: var(--color-text);
  border: 1px solid var(--color-border);
}
.btn--quiet:hover { background: var(--color-control-hover-soft); }

.link-arrow {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  min-height: 44px;
  
  
  
  color: var(--color-text);
  border-bottom: 1px solid transparent;
  transition: color var(--motion-fast) var(--motion-ease);
}
.link-arrow:hover { color: var(--color-secondary); }
.link-arrow svg { flex: 0 0 auto; transition: transform var(--motion-fast) var(--motion-ease); }
.link-arrow:hover svg { transform: translateX(2px); }

.menu-toggle {
  display: none;
  margin-left: auto;
  width: 44px;
  height: 44px;
  align-items: center;
  justify-content: center;
  border-radius: var(--radius-control);
  color: var(--color-text);
}
.menu-toggle:hover { background: var(--color-section); }

/* ── 页头控件：主题 + 语言（2026-09-30）──────────────────────────────────
   两个控件共用同一套"胶囊"语汇：同样的高度、同样的圆角、同样的边线，
   摆在「预约交流」右侧，与它保持一个按钮的间距。
   边框用 --color-border-muted 而不是 --color-border：页头本身有一条底线，
   控件再画一条同深的边会跟它抢视觉重量。

   语言控件是**一个分段胶囊**（当前语言高亮 + 另一种语言置灰），
   不是两个按钮：这样它在"未上线"与"已上线"两种状态下占位完全一致，
   不会因为 batch 2 接通 /en/ 而让页头重新排一次版。 */
.site-header__controls { display: flex; align-items: center; gap: var(--space-2); flex: 0 0 auto; }

.control-button {
  width: 36px;
  height: 36px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border: 1px solid var(--color-border-muted);
  border-radius: var(--radius-control);
  background: transparent;
  color: var(--color-secondary);
  transition: background var(--motion-fast) var(--motion-ease), border-color var(--motion-fast) var(--motion-ease), color var(--motion-fast) var(--motion-ease);
}
.control-button:hover {
  background: var(--color-control-hover-soft);
  border-color: var(--color-border);
  color: var(--color-text);
}

.control-group {
  display: inline-flex;
  align-items: center;
  height: 30px;
  padding-inline: 11px;
  border: 1px solid var(--color-border-muted);
  /* 胶囊档位来自 tokens（--radius-pill）；不要写 13px 这类中间值 ——
     design-consistency.mjs 只允许 10/16/20 与 50%/999px 三档之外的值为 0。 */
  border-radius: var(--radius-pill);
  font-size: 12px;
  font-weight: var(--weight-semibold);
  letter-spacing: .02em;
  color: var(--color-secondary);
  transition: background var(--motion-fast) var(--motion-ease), color var(--motion-fast) var(--motion-ease), border-color var(--motion-fast) var(--motion-ease);
}
.control-group__current {
  color: var(--color-text);
}
/* 有目标语言时是链接：给悬停反馈，让它读起来像"可以去"。 */
a.control-group:hover { background: var(--color-control-hover-soft); border-color: var(--color-border); }
/* 目标语言未上线时：**保持可读但明确不可点**。
   用 opacity 压权重而不是藏起来 —— 藏起来会让"将来会有英文版"这件事在页面上消失，
   而 batch 2 上线时控件从"置灰"变成"可点"，位置不变。 */
.control-group.is-disabled { opacity: .55; cursor: default; }

@media (max-width: 559px) {
  /* 极窄屏：品牌 + 语言 + 主题 + 菜单要挤进 344px。
     把控件收小一档并让语言控件只剩文字，不做换行（换行会让页头高于 --header-height）。 */
  .site-header__controls { gap: var(--space-1); }
  .control-button { width: 32px; height: 32px; }
  .control-group { height: 28px; padding-inline: 9px; }
}

/* 手机菜单：菜单按钮下方靠右的紧凑列表。 */
.mobile-menu {
  display: none;
  position: absolute;
  right: var(--page-gutter);
  top: 8px;
  width: min(200px, calc(100vw - var(--page-gutter) * 2));
  z-index: 5;
  background: var(--color-bg);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-card);
  box-shadow: var(--shadow-media);
  padding: var(--space-2);
}
.mobile-menu[data-open='true'] { display: block; }
.mobile-menu__list { display: grid; gap: 2px; }
.mobile-menu__link {
  display: flex;
  align-items: center;
  min-height: 44px;
  padding: 8px 12px;
  
  
  color: var(--color-text);
  border-radius: var(--radius-control);
}
.mobile-menu__link:hover { background: var(--color-section); }
.mobile-menu__link[aria-current='page'] { color: var(--color-accent-text); background: var(--color-brand-soft); }
.mobile-menu__cta { padding: var(--space-2) 0 0; margin-top: var(--space-2); border-top: 1px solid var(--color-border); }
.mobile-menu__cta .btn { width: 100%; }

.site-header__menu-region { position: relative; }

/* ---------- 3b. 编号行列表（全站招牌组件） ----------
   形态：编号 + 标题（+ 说明）+ 右端副文本 + 箭头，一行一条、行间发丝线。
   参考站用它撑起四个区块（能做什么 / 论文 / 博客 / 招聘），访客看两页就认得出来。
   渲染见 scripts/row-list.js；用在首页工作三步、交付页实施计划、关于页事实表。

   **发丝线用主文字色，不用浅灰**（2026-09-29 对齐参考站）：
   他们的是 `border-right:1px solid #000` / `border-left:1px solid #000`，
   编号列固定 `120 → 80 → 60 → 50px`。那种"印刷索引"的观感主要来自这条实线 ——
   浅灰细线会退化成"卡片之间的分隔线"，整块就没有形状了。
   我们的密度比他们高（17px 标题 vs 他们 28px），所以编号列取 48px 而不是 120px。

   两条规矩写在这里，改样式时别破坏：
     · **行不是按钮**：不可点的行没有 hover、没有 cursor:pointer、没有箭头 ——
       做得像可点却点不动比朴素更糟。
     · 可点的行**整行是链接**，点哪儿都行，箭头只是"这里可点"的视觉承诺。 */
.row-list {
  margin: 0;
  padding: 0;
  list-style: none;
  border-top: 1px solid var(--color-text);
}
.row-list__item {
  border-bottom: 1px solid var(--color-text);
}
/* 栅格在**行内容器**上，不在 <a> 上：可点的行与不可点的行排版必须完全一致，
   差别只在于有没有交互与箭头（见 scripts/row-list.js 的注释）。
   第一列固定宽度，编号才对得齐成一列（自适应宽度会让每行的编号缩进都不一样）。 */
.row-list__row {
  display: grid;
  grid-template-columns: 48px minmax(0, 1fr) auto auto;
  gap: 4px 18px;
  align-items: baseline;
  padding: 16px 0;
}
.row-list__link {
  color: inherit;
  text-decoration: none;
  transition: padding-inline var(--motion-standard) var(--motion-ease),
              background-color var(--motion-standard) var(--motion-ease);
}
/* 可点行：整行抬起 + 底色浮现，箭头右移。位移很小 —— 它是"可点"的反馈，不是动效表演。 */
.row-list__link:hover,
.row-list__link:focus-visible {
  padding-inline: 14px;
  background: var(--color-surface-muted);
}
.row-list__link:focus-visible { outline: 2px solid var(--color-focus); outline-offset: -2px; }
.row-list__index {
  color: var(--color-accent-text);
  font-size: 12px;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
}
.row-list__main { display: grid; gap: 5px; min-width: 0; }
.row-list__meta {
  margin: 0;
  color: var(--color-secondary);
  font-size: 13px;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.row-list__arrow {
  display: inline-flex;
  color: var(--color-accent-text);
  transition: transform var(--motion-standard) var(--motion-ease);
}
.row-list__link:hover .row-list__arrow,
.row-list__link:focus-visible .row-list__arrow { transform: translateX(4px); }
/* 事实表形态（关于页）：只有「标签 + 值」两列，没有编号与箭头。 */
.row-list--spec .row-list__item--spec {
  grid-template-columns: minmax(0, 1fr) auto;
  align-items: center;
  padding: 15px 0;
}
/* 事实表的值可以很长（如五条产品线名），必须允许折行 —— nowrap 会在 390px 撑破页面。 */
.row-list--spec .row-list__meta {
  font-size: 15px;
  font-weight: 600;
  color: var(--color-text);
  white-space: normal;
  overflow-wrap: anywhere;
}

@media (max-width: 767px) {
  /* 手机：编号与标题各占一行，副文本（工期/数值）折到标题下面 —— 
     挤在一行会把标题压成两三个字一断行。 */
  .row-list__row { grid-template-columns: 34px minmax(0, 1fr); }
  .row-list__row .row-list__meta { grid-column: 2; }
  .row-list__row .row-list__arrow { grid-column: 2; justify-self: start; }
  /* 事实表形态在手机上只有一列，标签在上、值在下，都左对齐。
     ⚠️ `grid-column: 1` 这一句**必须写**：上面那条 `.row-list__row .row-list__meta`
     会把值放进第 2 列，而这里只有一列 —— 浏览器会补一个隐式列，
     把标签那一列挤到只剩一个字宽，于是「主要场景」竖着排成四行
     （2026-09-29 手机截图复核时发现）。 */
  .row-list--spec .row-list__item--spec { grid-template-columns: minmax(0, 1fr); gap: 4px; }
  .row-list--spec .row-list__item--spec .row-list__meta { grid-column: 1; }
}

/* ---------- 3c. 关键数据条（数字带） ----------
   大号数字 + 一行标签 + 一行小字口径。数字是结论，口径是它凭什么成立 ——
   口径那行不是装饰，删掉它数字就变成无法核实的主张（见 config/metrics.js 的四条规矩）。
   视觉上刻意不做卡片、不做底色：这是一条"数据带"，不是四个盒子。 */
.metric-band {
  padding-block: clamp(34px, 3.6vw, 52px);
  border-top: 1px solid var(--color-border-light);
}
/* 并入首屏：去掉顶部分隔线与自身留白，间距全部由首屏自己的下留白提供 ——
   这样"左文字、右图片、下方数据"是一个整块，而不是"首屏 + 另一段"。
   首页与产品页用它；交付页不用（那条夹在拓扑与规范之间，本来就该独立分段）。 */
.metric-band--attached {
  padding-top: 0;
  border-top: 0;
}
.metric-band__list {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 26px 32px;
  margin: 0;
  padding: 0;
  list-style: none;
}
.metric { display: grid; gap: 6px; align-content: start; }
/* 数字与后面几格之间留一条发丝线：四格并排时读起来是一条数据带，而不是四段文字。 */
.metric + .metric {
  padding-left: 32px;
  border-left: 1px solid var(--color-border-light);
}
.metric__value {
  margin: 0;
  color: var(--color-text);
  font-size: clamp(38px, 3.6vw, 54px);
  font-weight: 700;
  line-height: 1;
  letter-spacing: -.035em;
  font-variant-numeric: tabular-nums;
}
/* 单位小一号：整串一个字号会把"天/家/+"撑得和数字一样重，读起来像口号而不是数据。 */
.metric__unit { font-size: .52em; font-weight: 600; letter-spacing: 0; }
.metric__label {
  margin: 0;
  color: var(--color-text);
  font-size: 15px;
  font-weight: 600;
}
.metric__basis {
  margin: 0;
  max-width: 30ch;
  color: var(--color-secondary);
  font-size: 12px;
  line-height: 1.6;
}

@media (max-width: 959px) {
  .metric-band__list { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 24px; }
  .metric + .metric { padding-left: 0; border-left: 0; }
}
@media (max-width: 559px) {
  /* 四项数据一律按 2×2 组阅读（2026-09-30：产品页与首页同一套），
     不拆成四段长列表；单列只留给不是四项的条（如交付三工期）。 */
  .metric-band[data-band='home'] .metric-band__list,
  .metric-band[data-band='ai-sop'] .metric-band__list,
  .metric-band[data-band='delivery'] .metric-band__list {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 0;
    border-block: 1px solid var(--color-border-light);
  }
  .metric-band[data-band='home'] .metric,
  .metric-band[data-band='ai-sop'] .metric,
  .metric-band[data-band='delivery'] .metric {
    min-width: 0;
    gap: 5px;
    padding: 16px 12px;
  }
  .metric-band[data-band='home'] .metric:nth-child(2n),
  .metric-band[data-band='ai-sop'] .metric:nth-child(2n),
  .metric-band[data-band='delivery'] .metric:nth-child(2n) {
    border-left: 1px solid var(--color-border-light);
  }
  .metric-band[data-band='home'] .metric:nth-child(-n+2),
  .metric-band[data-band='ai-sop'] .metric:nth-child(-n+2),
  .metric-band[data-band='delivery'] .metric:nth-child(-n+2) {
    border-bottom: 1px solid var(--color-border-light);
  }
  .metric-band[data-band='home'] .metric__value,
  .metric-band[data-band='ai-sop'] .metric__value,
  .metric-band[data-band='delivery'] .metric__value { font-size: clamp(30px, 8vw, 38px); }
  .metric-band[data-band='home'] .metric__label,
  .metric-band[data-band='ai-sop'] .metric__label,
  .metric-band[data-band='delivery'] .metric__label { font-size: 12px; line-height: 1.3; }
  .metric-band[data-band='home'] .metric__basis,
  .metric-band[data-band='ai-sop'] .metric__basis,
  .metric-band[data-band='delivery'] .metric__basis { font-size: 11px; line-height: 1.45; }
  .metric-band:not([data-band='home']):not([data-band='ai-sop']):not([data-band='delivery']) .metric-band__list {
    grid-template-columns: minmax(0, 1fr);
    gap: 20px;
  }
}

/* ---------- 4. 首屏 ---------- */
.hero {
  position: relative;
  overflow: hidden; /* 排版底纹的轨道比视口宽，必须在这一层裁掉 */
  /* 内距来自 tokens.css 的 --hero-pad-block-*：首页与内页首屏共用同一对值，
     两页首屏高度才会一致（2026-09-29 用户要求对齐，原先各写一套差了 180px）。 */
  padding-top: var(--hero-pad-block-top);
  padding-bottom: var(--hero-pad-block-bottom);
}
/* 首屏统一高度（≥960px）：首页与产品页首屏**外框等高**，内容垂直居中。
   两页的内距与组成部件（说明卡、本页内容索引、数据条）都已收敛成同一套，
   剩下的差异只有正文行数带来的几像素 —— 那不该用"凑内容"去追，
   一条共同的高度下限更稳，也不会被改文案打破。
   手机（<960px）不加：那里首屏是堆叠的，高度由内容决定。
   **联系页排除在外**：它的任务是"最短路径拿到号码"，人为撑到 600px
   会把联系方式推到折线以下 —— 那正是这一轮要修的问题。 */
@media (min-width: 960px) {
  .hero,
  .page-hero:not(.page-hero--contact) {
    min-height: var(--hero-screen-min);
    display: grid;
    align-content: center;
  }
}

.hero-grid {
  display: grid;
  /* 图文各占 50%（全站统一比例，见 DESIGN.md §4「网格与留白」）；
     窄屏时由断点堆叠为文字→画面。 */
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: clamp(40px, 5vw, 72px);
  align-items: center;
  justify-content: end;
}

.hero__copy { transform: translateY(var(--hero-align-offset, 0px)); }
.hero__eyebrow {
  font-size: var(--label-size);
  line-height: 1.4;
  font-weight: var(--weight-medium);
  color: var(--color-secondary);
  margin-bottom: var(--space-4);
}
.hero__title {;
  
  /* 字号提到 68px 后必须放宽这里的上限：最长的标题行是 8 个全角字
     （如「看清每一步作业。」），8 × 68px ≈ 525px —— 再卡在 440px 会把标题
     挤成三行。上限跟着 `--hero-title-size` 的上限走，改字号要一起看这里。 */
  max-width: 560px;
}
.hero__title span { display: block; }

/* 首屏标题的打字机效果（2026-09-29，对齐参考站的 typewriter）。
   为什么用 CSS 裁切而不是"逐字插入节点"：
     · 参考站的做法是 ghost 层 + typed 层 + `aria-label`，代价是**同一句话在 DOM 里存在两份**
       （影响抓取与复制）；
     · 这里用 `max-width` 从 0 收到文字宽度 + `steps()`，文字**始终只有一个节点**，
       只是被裁掉一部分。抓取、复制、屏幕阅读器读到的都是完整的一句话。
   三个必须同时成立的点：
     1. `--type-steps` 要等于该行的**字符数**，`steps()` 才有逐字节奏；
     2. 光标用 `::after` 画，`steps()` 的最后一帧正好把它推到行尾；
     3. `prefers-reduced-motion` 下**必须直接显示完整**（不是变快）——
        动画不承载信息，关掉动效后信息必须 100% 可用。

   ⚠️ **`max-width` 必须按字符数算，不能写 `100%`**（2026-09-30 修）。
   写 `100%` 时动画的中间帧是"可用宽度 = 40%"，而 `.is-typed` 是 `inline-block` ——
   **可用宽度一旦小于文字宽度，文字就折行**；`overflow: hidden` 只裁高度，
   裁不掉这个折行。实测首屏 H1 在 t≈839ms 由 75px 跳成 150px，
   并把后面所有分区整体推下 40px —— 这正是用户报的"服务客户覆盖一直在抖动"。
   改成按 `--type-steps` 收边后，每一帧的可用宽度**刚好等于已打出的字数**：
   既不折行，也不多留空白。
   ⚠️ 单位必须是 **`em`，不能用 `ch`**：`ch` 是"0"的字宽（本站 68px 字号下约 37.5px），
   而中文全角字宽约 **62px** —— 按 `ch` 算出来的上限只有实际需要的六成，
   文字会被 `overflow: hidden` 从右边裁掉（实测「让标准作业，」6 字被裁到 230px）。
   `em` = 当前字号，中文正好一字一 em，是**安全上界**；
   英文小写窄于一 em，会多留一点空白，但绝不会裁字 —— 宁可多留，不可裁掉。 */
.hero__title .is-typed {
  display: inline-block;
  overflow: hidden;
  white-space: nowrap;
  /* 静态终值同样按字符数给足，否则动画结束后仍贴着旧上限。 */
  max-width: calc(var(--type-steps, 6) * 1em + 6px);
  vertical-align: bottom;
  animation: hero-typing 620ms steps(var(--type-steps, 6), end) both;
}
.hero__title .is-typed + .is-typed { animation-delay: 420ms; }
/* 光标**只淡出一次**，不常驻闪烁。两个原因：
   · 常驻闪烁属于"自动播放且不停"的动效，读起来分心，也让截图取证变得不确定
     （2026-09-29 就拍到过半闪状态）；
   · 淡出是单向的，`opacity` 可以从 0 变到 1 再也不会回去 —— 所以门禁可以
     "等它变得不可见"再截图，结果可复现；闪烁会在两个半周期里都出现 opacity:0，
     等它等于 0 会提前放行。 */
.hero__title .is-typed::after {
  content: "";
  display: inline-block;
  width: 2px;
  height: .82em;
  margin-left: .06em;
  vertical-align: -.06em;
  background: var(--color-brand-primary);
  opacity: 0;
  animation: hero-caret 240ms ease-out 700ms both;
}
/* 终值是 `n × 1ch`，**不是 100%** —— 理由见上面 `.is-typed` 的注释：
   写成 100% 时中间帧的可用宽度会小于文字宽度，文字折行、整页被推下去。 */
@keyframes hero-typing {
  from { max-width: 0; }
  to { max-width: calc(var(--type-steps, 6) * 1em + 6px); }
}
@keyframes hero-caret {
  from { opacity: 1; }
  to { opacity: 0; }
}
@media (prefers-reduced-motion: reduce) {
  /* 减弱动效下直接给足宽度：`animation: none` 会回落到元素自身声明的那条
     （同样按字符数算），这里再写一次是防止将来有人只改上面那条。 */
  .hero__title .is-typed { animation: none; max-width: calc(var(--type-steps, 6) * 1em + 6px); }
  .hero__title .is-typed::after { animation: none; opacity: 0; }
}
.hero__body {;
  /* 第 08 节允许不超过 440px；取 406px 与原型一致，使首屏正文按原型在逗号后自然折行。 */
  max-width: 406px;
}
.hero__actions {
  margin-top: var(--space-7);
  display: flex;
  align-items: center;
  gap: var(--space-5) 28px;
  flex-wrap: wrap;
}
/* 文字链与实心主按钮同高对齐（2026-09-30）：补上下 padding，避免视觉上“掉”在按钮旁。 */
.hero__actions .link-arrow {
  display: inline-flex;
  align-items: center;
  min-height: 48px;
  padding-block: 12px;
}

/* ---------- 5. 参考媒体（原图视窗） ---------- */
/* <picture> 只负责选源，**不参与布局**。
   2026-09-29 批次 2 起 img 外面多了一层 picture（WebP + PNG 回退），
   而下面那张图是绝对定位 + 百分比尺寸的：多一层元素会让 height: 100% 改挂到
   picture 上（它自身高度是 auto）→ 图高度塌成 0。
   这和 2026-09-29「首屏主图整个不可见」那条缺陷是同一种坏法，
   所以用 display: contents 把 picture 从盒模型里摘掉，
   **img 在布局上仍然是 .reference-media 的直接子元素**。
   对应的失败断言在 工具链/site-shots.mjs（首屏主图实测高度 > 200px）。 */
.reference-media > picture { display: contents; }
.reference-media {
  position: relative;
  overflow: hidden;
  isolation: isolate;
  background: var(--color-section);
  border-radius: var(--radius-media);
}
.reference-media img {
  display: block;
  position: absolute;
  max-width: none;
  height: auto;
  pointer-events: none;
}
/* 比例与偏移来自交接包 design/reference-media.css，按 2 倍裁图（1094×648 / 1046×374）等比换算。
   说明：当容器用 aspect-ratio 定出固有比例时，绝对定位且设置了 top 的 <img> 会改用容器比例
   推算高度，导致 reference-media.css 的百分比偏移公式失真。因此这里改为
   width:100% + height:100% + object-fit:cover + object-position，语义等价且结果可预测：
   视窗内显示的就是裁图对应区域，主体与比例与原型一致。 */
.reference-media img {
  position: absolute;
  inset: 0;
  display: block;
  width: 100%;
  height: 100%;
  max-width: none;
  object-fit: cover;
  object-position: center;
  pointer-events: none;
}



.media-figure { display: block; }
.media-figure--hero { flex: 0 0 auto; width: 100%; max-width: var(--hero-media-max-width, 735px); }
/* 原图左上/右上为圆角外框，浏览器内裁切留出的直角边由容器圆角统一处理 */
.reference-media--hero > img { border-radius: var(--radius-media) var(--radius-media) 0 0; }

.media-figure__caption{
  display: block;
  margin-top: var(--space-2);
  
}

.media-caption {
  display: block;
  margin-top: var(--space-2);
  font-size: var(--caption-size);
  line-height: 1.5;
  color: var(--color-secondary);
}

/* 媒体加载失败：容器尺寸由 aspect-ratio 固定，不破图、不跳版 */
.reference-media[data-media-failed='true']::after {
  content: '画面待补充';
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: var(--caption-size);
  color: var(--color-secondary);
}

/* ---------- 6. 客户带 ---------- */
.customer-strip {
  position: relative;
  isolation: isolate;
  overflow: hidden;
  background: var(--color-bg);
  border-bottom: 1px solid var(--color-border);
}
.customer-strip__inner {
  position: relative;
  z-index: 1;
  /* 首页客户区改为两行（标题+行业说明 / 名称+CTA），高度由内容决定，
     不再钉 74px。原先的 74px 是"单行名称带"时代的原型目标。 */
  padding-block: var(--space-6);
  display: block;
}
/* 首页客户区的新结构（标题 + 说明 + CTA / 走马灯）由 experience.css 接管，
   这里只留区块外壳。原 `.customer-strip__list` / `__name`（静态名称带）
   与 `__more` 的分隔线样式已随走马灯改造删除（2026-09-29）。 */
.customer-strip__label {
  font-size: var(--label-size);
  line-height: 1.4;
  font-weight: var(--weight-medium);
  color: var(--color-secondary);
}

/* ---------- 7. 平台模块区 ---------- */
.platform.section { padding-top: var(--platform-pad-top, 64px); padding-bottom: var(--platform-pad-bottom, 96px); }
.platform__heading {
  font-size: var(--section-title-size);
  line-height: 1.25;
  font-weight: var(--weight-semibold);
  color: var(--color-text);
  margin: 0;
}
.platform__eyebrow {
  display: block;
  font-size: var(--label-size);
  font-weight: var(--weight-medium);
  line-height: 1.4;
  color: var(--color-secondary);
  margin-bottom: var(--space-2);
  height: var(--platform-heading-to-eyebrow, 24px);
}

.module-tabs {
  display: flex;
  gap: var(--space-3);
  overflow-x: auto;
  overflow-y: hidden;
  scrollbar-width: thin;
  margin-top: var(--platform-heading-to-tabs, 32px);
  /* 标签行按 40px 计入纵向节奏。
     注意：flex 容器内相邻 margin 不合并，标签的 margin-bottom 会与面板的 margin-top 相加，
     因此这里把"标签行-面板"的净间距全部交给面板 margin-top 表达，标签只补足 4px 显示微调。 */
  margin-bottom: 4px;
  padding-bottom: 0;
  -webkit-overflow-scrolling: touch;
}
.module-tabs > * { flex: 0 0 auto; min-height: var(--tab-height); }

.module-tab {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  height: var(--tab-height);
  padding-inline: var(--space-5);
  border-radius: var(--radius-pill);
  border: 1px solid var(--color-border);
  background: var(--color-surface);
  color: var(--color-text);
  
  
  
  white-space: nowrap;
  transition: background-color var(--motion-fast) var(--motion-ease),
              color var(--motion-fast) var(--motion-ease),
              border-color var(--motion-fast) var(--motion-ease);
}
.module-tab:hover { border-color: var(--color-border-muted); }
.module-tab[aria-selected='true'] {
  background: var(--color-action);
  border-color: var(--color-action);
  color: var(--color-action-text);
}

.platform__panel {
  margin-top: var(--platform-tabs-to-panel, 24px);
  display: grid;
  grid-template-columns: minmax(0, 2fr) minmax(0, 3fr);
  gap: var(--space-6);
  align-items: center;
}
.module-panel { min-width: 0; }
/* 阶段标签：这个模块处在数据链路的哪一段（数据输入 / 数据处理 / 业务应用 / 统一管理）。
   视觉上用「透明底 + 虚线边 + 主蓝文字」——与行业卡片的能力标签同一套语言，
   两者都是**分类标签**（不是按钮、不是可点的东西），全站分类标签长一个样。
   放在标题之上、字号更小：先归位，再读它是什么。 */
.module-panel__stage {
  display: inline-flex;
  align-items: center;
  min-height: 22px;
  margin-bottom: var(--space-3);
  padding: 0 9px;
  border: 1px dashed var(--color-topology-line);
  border-radius: var(--radius-control);
  color: var(--color-accent-text);
  font-size: 12px;
  line-height: 1.5;
  white-space: nowrap;
}
.module-panel__summary {
  margin-top: var(--space-4);
  color: var(--color-secondary);
}
/* 现场对应的作业：把模块名翻成访客车间里的活（config 的 modules[].onsiteTasks）。
   与行业卡的具体作业同一套语汇：一行一条、短横线引导、次要色小字。
   `min-height` 是**必须的**：六个模块的面板共用同一个容器，切换标签不能让整节高度跳动
   （设计规范 §5「容器尺寸与滚动位置保持稳定」）。三条作业在桌面与手机都是一行，
   所以这里按三条的高度预留；少一条也不会让区块缩一下。 */
.module-panel__onsite { margin-top: var(--space-4); }
.module-panel__onsite-label {
  margin: 0 0 var(--space-2);
  color: var(--color-secondary);
  font-size: 12px;
  font-weight: 600;
}
.module-panel__onsite-list {
  display: grid;
  gap: 4px;
  min-height: 70px;
  margin: 0;
  padding: 0;
  list-style: none;
}
.module-panel__onsite-item {
  position: relative;
  padding-left: 16px;
  color: var(--color-secondary);
  font-size: 13px;
  line-height: 1.6;
}
/* 标记沿用站内已有的列表语汇（`.home-proof__note` 的 6px 主蓝圆点），
   不另发明一种 —— 全站同一个"这是一条"的记号。
   2026-09-29 试过 1px 淡蓝短横，实测在截图里几乎看不见，等于没有标记。 */
.module-panel__onsite-item::before {
  content: "";
  position: absolute;
  top: .55em;
  left: 0;
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--color-brand-primary);
}

.module-media {
  min-width: 0;
  border-radius: var(--radius-media);
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  min-height: var(--module-panel-height, 198px);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  padding: var(--space-4);
  text-align: center;
}




/* ---------- 11. 页脚 ----------
   形态照参考站（DeepSeek Harness）：**一条 1px 发丝线 + 一行居中公司名**。
   三个决定：
     · 底色用页面底色而不是浅分区 —— 页脚不再是"另一个色块"，只是页面的收束；
       参考站那条线之下就是页面本身。
     · 发丝线用 --color-border-subtle 级别的轻边界：它是一条分隔，不是边界框。
     · 文字用次文字色、居中：页脚是落款，不该比正文更响。
   备案号（取得后）跟在公司名下方一行，仍是次文字色。 */
.site-footer {
  background: var(--color-bg);
  border-top: 1px solid var(--color-border-light);
  padding-block: var(--space-6);
}
.site-footer__inner {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-2);
  text-align: center;
}
.site-footer__company {
  font-size: var(--label-size);
  font-weight: var(--weight-medium);
  color: var(--color-secondary);
  letter-spacing: .01em;
}
.site-footer__legal { display: flex; flex-wrap: wrap; justify-content: center; gap: 2px var(--space-4); min-height: 0; color: var(--color-secondary); }
/* 备案号：只有取得备案后才由脚本渲染（留空则整块不存在）。
   刻意做得比公司名更轻 —— 它是合规信息，不是行动入口。 */
.site-footer__filing {
  display: inline-block;
  margin: 0;
  color: var(--color-secondary);
  font-size: var(--caption-size);
  line-height: 1.5;
  text-decoration: none;
}
.site-footer__filing:hover { color: var(--color-text); }
/* 空容器不占高：没有备案号时页脚就只有一行。 */
.site-footer__legal:empty { display: none; }

/* ---------- 12. 断点 ---------- */

/* 960–1279px：仍为两列，但右列按比例收缩。
   固定 735px 会在 1024/960px 把文字列挤到 193/129px，首屏标题被压成 4–6 行；
   第 06 节要求 ≥960px 保持两列，故此处改为比例列，1279px 以上回到 735px 实测宽度。 */
@media (max-width: 1279px) and (min-width: 960px) {
  .hero-grid {
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    justify-content: stretch;
  }
  .media-figure--hero { max-width: 100%; }
}

/* 768–959px：菜单收起，各区分区堆叠 */
@media (max-width: 959px) {
  .site-nav { display: none; }
  .btn--nav { display: none; }
  .menu-toggle { display: inline-flex; }

  .hero-grid,
  .platform__panel,
  .light-guide__grid,
  .company-grid { grid-template-columns: minmax(0, 1fr); }

  .hero-grid { gap: var(--hero-gap-mobile, 24px); }
  .hero__copy { transform: none; }          /* 堆叠后文字在上，不需要垂直居中偏移 */
  .hero__title{ max-width: 640px; }
 .hero__body { max-width: 640px; }
  .hero__body { max-width: 406px; }

  /* 堆叠布局下媒体改为跟随容器宽度；否则 735px 的固有宽度会在 960px 视口
     把文字列挤成约 190px，标题被压成 4 行。 */
  .media-figure--hero,
  .media-figure--light { max-width: 100%; }


  /* 页脚在新形态下只有"一行居中公司名"，堆叠断点不需要额外规则。 */


}

/* ≤767px：手机排版 */
@media (max-width: 767px) {
  :root {
    /* --page-gutter: 23px 已上移到 styles/tokens.css 的手机断点（唯一真源）；
       第 05 节手机目标：标题左边缘 x=25、媒体 x=23 → 两侧 23px 与原型实测一致。
       此处只保留由 config/geometry.js 运行时写入的分区内距。
       首屏内距不再在这里覆写 —— 它由 tokens.css 的 --hero-pad-block-* 统一给
       首页与内页，见那里的注释。 */
    --platform-pad-top-mobile: 48px;
    --platform-pad-bottom-mobile: 32px;
  }
  .section__inner { padding-block: var(--section-pad-block); }
  .platform.section {
    padding-top: var(--platform-pad-top-mobile, 48px);
    padding-bottom: var(--platform-pad-bottom-mobile, 64px);
  }


  .hero__title{ max-width: 100%; }
 .hero__body { max-width: 100%; }
  /* 手机首屏文字块按原型实测收紧（第 05 节：眉标 y=100、标题 y=135、主按钮 y=308） */
  .hero__eyebrow { margin-bottom: var(--space-2); }
  .hero__body {; max-width: var(--hero-body-max-width-mobile, 344px); }
  .hero__actions {
    margin-top: var(--space-4);
    gap: 12px;
    flex-direction: column;
    align-items: stretch;
  }
  .hero__actions .btn { width: 100%; }
  .hero__actions .link-arrow {
    align-self: flex-start;
    min-height: 44px;
    padding-block: 10px;
  }
  .btn { height: 46px; padding-inline: var(--space-5); }
  .btn--nav, .btn--quiet { height: 46px; }

  .customer-strip__inner {
    display: block;
    min-height: 0;
    padding-block: var(--space-5);
  }
  /* 手机：标题 / 说明 / CTA 依次左对齐成列，走马灯跟在下面。
     原先把名称居中排两行、CTA 另起一行居中 —— 走马灯改造后名称不再换行，
     这类居中规则随之删除（2026-09-29）。 */
  .customer-strip__head {
    flex-direction: column;
    align-items: flex-start;
    gap: var(--space-3);
  }

  .module-tabs { margin-inline: calc(var(--page-gutter) * -1); padding-inline: var(--page-gutter); }
  .module-panel__summary { margin-top: var(--space-3); }
  .module-media { aspect-ratio: auto; min-height: var(--module-panel-height-mobile, 140px); padding: var(--space-5) var(--space-4); }
  .platform__panel { margin-top: var(--platform-tabs-to-panel-mobile, 20px); }


  .site-footer { padding-block: var(--space-5); }
}

/* ≤360px：首屏标题收得更小（值在 tokens.css），仍保两行与可读性 */
@media (max-width: 360px) {
  .customer-marquee__name { font-size: 15px; }
}

/* 首页手机阅读：优先把主张、画面和四项数据放进第一屏。 */
@media (max-width: 767px) {
  main[data-page='home'] .hero {
    padding-top: 24px;
    padding-bottom: 20px;
  }
  main[data-page='home'] .hero-grid { gap: 12px; }
  main[data-page='home'] .site-container { container-type: inline-size; }
  /* 用实际内容宽度定字号，滚动条与窄窗口不会把末字挤到下一行。 */
  main[data-page='home'] .hero__title {;
    
    white-space: nowrap;
  }
  main[data-page='home'] .hero__title .is-typed {
    display: inline;
    overflow: visible;
    white-space: inherit;
    animation: none;
  }
  main[data-page='home'] .hero__title .is-typed::after { display: none; }
  main[data-page='home'] .hero .page-index { display: none; }
  main[data-page='home'] .media-figure--hero { margin-inline: auto; justify-self: stretch; }
  main[data-page='home'] .reference-media--hero { width: 100%; height: 180px; }
  main[data-page='home'] .metric-band { padding-bottom: 10px; }
  main[data-page='home'] .metric-band__list { gap: 0; }
  main[data-page='home'] .customer-strip__inner { padding-block: 12px; }
  main[data-page='home'] .customer-strip__head {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto;
    grid-template-areas: 'label more' 'intro intro';
    gap: 3px 10px;
    margin-bottom: 10px;
  }
  main[data-page='home'] .customer-strip__label { grid-area: label; }
  main[data-page='home'] .customer-strip__intro { grid-area: intro; font-size: 13px; line-height: 1.5; }
  main[data-page='home'] .customer-strip__more { grid-area: more; justify-self: end; }
}
@media (max-width: 360px) {
  main[data-page='home'] .reference-media--hero { height: 160px; }
}

/* 200% 文本放大与窄屏下不出现横向溢出 */
@media (max-width: 767px) {
  .hero__actions .btn,
  .hero__actions .link-arrow { flex: 0 1 auto; }
}

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    transition-duration: 1ms !important;
    animation-duration: 1ms !important;
  }
}/* 共享文字角色：页面 CSS 只保留结构，字号与阅读节奏在此维护。 */
.section-exit { margin-top: var(--space-5); }
.sector-cards__grid { gap: var(--card-gap); }
.sector-card { padding: var(--card-padding); border-radius: var(--radius-card); }
.scenario-case-gallery { gap: var(--card-gap); }
.scenario-case-card { padding: var(--compact-padding); gap: var(--space-3); border-radius: var(--radius-card); }
.disclosure-icon { display: inline-flex; margin-left: auto; flex: 0 0 auto; transition: transform var(--motion-fast) var(--motion-ease); }
.pl-drill__summary { gap: var(--space-2); }
.pl-drill__summary .disclosure-icon { order: 2; }
details[open] > summary .disclosure-icon { transform: rotate(180deg); }
.content-disclosure { border-top: 1px solid var(--color-border); padding-top: var(--space-3); }
.content-disclosure__summary { display: flex; align-items: center; gap: var(--space-2); cursor: pointer; font-size: var(--label-size); line-height: 1.4; }
.content-disclosure__summary::-webkit-details-marker { display: none; }
.content-disclosure__summary:focus-visible, .pl-drill__summary:focus-visible { outline: 2px solid var(--color-focus); outline-offset: 4px; border-radius: var(--radius-control); }
.image-viewer-trigger { border: 0; padding: 0; width: 100%; cursor: zoom-in; background: var(--color-surface); }
.image-viewer-trigger:focus-visible { outline: 2px solid var(--color-focus); outline-offset: 4px; }
.image-viewer { width: min(96vw, 1100px); max-height: 94dvh; margin: auto; padding: var(--card-padding); border: 1px solid var(--color-border); border-radius: var(--radius-media); background: var(--color-surface-raised); color: var(--color-text); }
.image-viewer::backdrop { background: var(--color-dialog-backdrop); }
.image-viewer .btn { display: flex; margin: 0 0 var(--space-3) auto; }
.image-viewer__image { display: block; width: 100%; height: auto; max-height: 78dvh; object-fit: contain; }
.voices-cloud__relation { margin-top: var(--space-4); }
@media (max-width: 767px), (pointer: coarse) { .topology-workcell-chip { min-height: var(--control-touch-height); } }/* 文字颜色与标题组间距也由角色统一。 */

.section-head, .scenario-feature__head { margin-bottom: var(--heading-content-gap); }
.section-head__intro{ margin-top: var(--title-intro-gap); }
 .page-hero__body{ margin-top: var(--title-intro-gap); }
 .hero__body{ margin-top: var(--title-intro-gap); }
 .home-product__lead{ margin-top: var(--title-intro-gap); }
 .home-proof__lead{ margin-top: var(--title-intro-gap); }
 .home-close__body { margin-top: var(--title-intro-gap); }

@media (max-width: 767px) { .page-content-section { padding-block: var(--section-pad-block); } .scenario-feature, .page-close, .home-close { padding-block: var(--compact-section-padding); } }

/* 语义文字契约（公共样式唯一落点）。 */
.hero__title,
.page-hero__title,
.section-head__title--hero {font-size:var(--hero-title-size);line-height:var(--hero-title-line);font-weight:600;letter-spacing:var(--hero-title-tracking);color:var(--color-text);}
.section-head__title:not(.section-head__title--hero),
.editorial-split__title,
.home-product__title,
.home-proof__title,
.home-close__title,
.site-problems__title-main,
.join-us-section__title {font-size:var(--section-title-size);line-height:var(--section-title-line);font-weight:650;letter-spacing:var(--title-tracking);color:var(--color-text);}
.product-line__title,
.module-panel__title,
.voices-cloud__title,
.voices-graph__title,
.pl-drill__title,
.scenario-feature__title {font-size:var(--module-title-size);line-height:1.35;font-weight:650;letter-spacing:var(--title-tracking);color:var(--color-text);}
.row-list__title,
.product-line__cap-title,
.pl-drill__label,
.sector-card__title,
.scenario-case-card__title,
.site-problems__title,
.home-process__title,
.process-step__title,
.project-boundary__title,
.project-phase__title,
.dspec-deliverable__title,
.dspec-inputs__title,
.home-proof__shared-title,
.editorial-list__item h3 {font-size:var(--card-title-size);line-height:1.4;font-weight:650;letter-spacing:0px;color:var(--color-text);}
.hero__body,
.page-hero__body,
.section-head__intro,
.editorial-split__body,
.editorial-list__item p,
.home-product__lead,
.home-proof__lead,
.home-close__body,
.row-list__body,
.product-line__summary,
.product-line__cap-body,
.pl-drill__lead,
.pl-drill__text,
.pl-drill__points,
.scenario-feature__lead,
.scenario-case-card__summary,
.sector-card__subtitle,
.sector-card__facts dd,
.sector-card__task,
.site-problems__body,
.project-phase__body,
.project-boundary__body,
.process-step__body,
.dspec-param__body,
.dspec-deliverable__body,
.dspec-integrations__note,
.voices-cloud__relation {font-size:var(--body-size);line-height:var(--body-line);font-weight:400;letter-spacing:0px;color:var(--color-secondary);}
.product-line__note,
.pl-figure__caption,
.pl-figure__note,
.media-figure__caption,
.module-media__caption,
.scenario-case-gallery__note,
.voices-cloud__caption,
.voices-graph__note,
.home-proof__note,
.project-proof__note,
.contact-page-item__note,
.sector-card__industries {font-size:var(--caption-size);line-height:1.5;font-weight:400;letter-spacing:0px;color:var(--color-secondary);}

.sector-card__fact dd { font-size:var(--body-size);line-height:var(--body-line);font-weight:400;letter-spacing:0px;color:var(--color-secondary); }

/* 共享控件文字与内容到行动入口的距离。 */
.btn,.link-arrow,.module-tab,.site-nav__link,.mobile-menu__link,.topology-btn {font-size:var(--label-size);font-weight:500;line-height:1.4;letter-spacing:0px;}
.hero__actions, .home-product__actions, .home-close__actions { margin-top:var(--space-5); }
