/* ==========================================================================
   幻方造梦 · 企业官网样式表
   设计基调：简约大气 —— 大面积留白 / 强对比字阶 / 克制的单一强调色
   ========================================================================== */

/* ---------- 1. 设计变量 ---------- */
:root {
  /* 主色：深靛。取代原来的近黑 —— 同样是「深」，但带色相，
     放在深色区里不会读成「黑」，放在正文里仍是 17.8:1 的对比度。 */
  --brand: #101828;
  --brand-600: #1d2939;
  --brand-400: #475467;

  /* 强调色：品牌蓝 */
  --accent: #0071e3;        /* 亮色：只用于图标 / 色块 / 图形 / 大字号 */
  --accent-ink: #0058b0;    /* 文字与按钮：白底 5.9:1，达 AA */
  --accent-soft: rgba(0, 113, 227, 0.08);
  /* 深色底上的强调色。与 --accent 同色相（≈215°），只是提亮到深底上够读。
     原来这个值以 #6aa8ff 硬编码散在 10 处 —— 同一个语义散落 10 份，
     改一次要找 10 个地方，而且没人知道它们本该是同一个颜色。 */
  --accent-lite: #6aa8ff;

  /* ---------- 四条业务线：全部指向同一族蓝 ----------
     ★ 这里推翻的是上一版的一个刻意选择。
     上一版写的是「颜色从业务分类里长出来，而不是全站一个蓝」——
     四条业务线各给一个色相（蓝 #0a84ff / 紫 #7c5cff / 青 #00b8a9 / 珊瑚 #ff6b4a），
     栅格里的卡片再按序轮换。当时的理由是「让业务线可辨识」。

     实测下来，这个理由站不住：**三张结构完全相同的卡片顶着蓝、紫、青三个
     不同的小方块和圆点，正是「模板批量生成」最典型的视觉特征。**
     业务线的区分本来就由图片和标题承担，再叠一层色相是重复信息，
     而且把整页的色相数从 1 拉到 4，一眼就「花」。

     对着大厂重新核了一遍（取它们的 CSS 数色值频次）：
       · Apple 中国首页：强调色只有一种色相 —— #0076df / #006edb / #0071e3，
         同一个蓝的三个明度档；其余全是中性色阶（#18181a / #ededf2 / #f5f5f7 / #86868b）。
         整个首页 CSS 里 box-shadow 出现 **0 次**。
       · 腾讯云：CSS 里 #0052d9 出现 **164 次**，配一整套蓝灰中性色阶
         （#4b5b76 / #97a3b7 / #d6dbe3 / #e6e9ef / #edeff1），
         红色只留给报错与警示这类语义用途，不参与装饰。
     两家都是「一个强调色 + 一套中性色阶 + 语义色单列」。

     所以四条业务线全部指向同一族蓝，视觉上不再有彩虹；
     业务线之间靠图片与文案区分，不靠色相。
     变量结构保留（全站 CSS 都引用 --tone*），改的只是取值 —— 风险最小。 */
  --c-fde: #0071e3;     --c-fde-ink: #0058b0;     --c-fde-soft: #eaf2fd;
  --c-agent: #0071e3;   --c-agent-ink: #0058b0;   --c-agent-soft: #eaf2fd;
  --c-dev: #0071e3;     --c-dev-ink: #0058b0;     --c-dev-soft: #eaf2fd;
  --c-sec: #0071e3;     --c-sec-ink: #0058b0;     --c-sec-soft: #eaf2fd;

  /* 整段区块用的极浅底纹。
     原来也是四个色相（蓝/紫/青/珊瑚），全站用了 49 次 ——
     按色相轮换的区块底色同样是模板感的重灾区。
     现在统一成一个极淡的蓝灰，只做「这一段和上一段不同」的分隔，
     不再承担「这一段是什么业务」的表意。 */
  --tint-blue: #e9eff6;
  --tint-violet: #e9eff6;
  --tint-teal: #e9eff6;
  --tint-coral: #e9eff6;

  /* ---------- 表面阶（surface ramp）----------
     ★ 这一版推翻的是「页面底色 = 纯白 #ffffff」。
     实测：首页 **51% 的面积是纯白** —— 因为大量区块不写背景，
     一路落到 body 的 --bg。于是整页读起来是「一片白 + 几块几乎看不出差别的浅斑」
     （#f5f7fa 与 #f7f7f9 只差 2 个色阶，肉眼分不出来，「交替分区」等于没做）。

     参考版的做法（design/配色与阅读层级.md）是**整条中性阶共用一个色相**：
       #f3f5f6 / #e6eff4 / #9aaebb / #3e5360 / #102e42 —— 每个灰都带蓝调，
       没有一个是纯灰或纯白。Apple 与腾讯云同理：强调色只用一个色相，
       其余交给一条**带色相的中性阶**。

     所以表面分四档，全部落在品牌蓝的色相上（与 #101828 / #0071e3 同族）：
       0 档 纯白   —— 只留给「浮起来」的卡片。★ 白不再是默认值，而是层级
       1 档 纸白   —— 页面底色，带极淡蓝调
       2 档 浅蓝灰 —— 交替分区，与纸白拉开到肉眼可辨
       3 档 蓝灰   —— 需要更明确分区的段落
     ★ 关键不是「换个颜色」，是**让白变成层级而不是默认值**。 */
  --surface: #ffffff;   /* 0 档：卡片等浮起表面 */
  --bg: #fbfcfd;        /* 1 档：页面底色（原为纯白 #ffffff） */
  --bg-alt: #f2f5f9;    /* 2 档：交替分区（原 #f7f7f9，与纸白几乎同色） */
  --bg-deep: #101828;
  --text: #101828;
  --text-2: #475467;
  /* ★ 原值 #6e6e73 是**暖灰**，而其余中性色（#101828 / #475467 / #c3c8d1）全是冷蓝调 ——
     同一条中性阶里混了一个异色相，灰阶之间会读成「互不相关」，
     这正是「没设计过」的来源。改成冷蓝调的灰。 */
  --muted: #55647a;   /* 对比度：纸白 5.5 / 浅蓝灰底 4.8，达 AA */
  /* ★ 线色是**按白底调的**，但页面底色不再是白 —— 这是上一版留下的隐患。
     实测（services.html）：--line #e4e9f0 在白底上 1.19、在浅蓝灰分区 #e9eff6 上只有 **1.05**
     —— 后者等于没有线。受影响最明显的是 .fit 这类**分隔线**：
     它没有填充、只靠一条 border-top 分隔，在分区色上就完全消失了。
     ⇒ 调到在**两种底上都读得出**：白底 1.45 / 分区色 1.28，仍是细线，但确实在起作用。 */
  --line: #cad4e1;
  --line-strong: #aab8cb;

  /* 形状与阴影：三层递进，越往上越柔、越散，避免生硬的「盒子感」 */
  --radius: 16px;
  --radius-sm: 10px;
  --radius-btn: 9px;
  --shadow-sm: 0 1px 2px rgba(16, 21, 28, 0.035), 0 14px 34px -22px rgba(16, 21, 28, 0.22);
  --shadow-md: 0 2px 6px rgba(16, 21, 28, 0.03), 0 34px 80px -46px rgba(16, 24, 40, 0.5);
  --shadow-lg: 0 4px 10px rgba(16, 21, 28, 0.04), 0 58px 120px -58px rgba(16, 24, 40, 0.6);

  /* 布局：加大纵向留白，是「高端」最直接的来源 */
  /* 栅格：12 列（对齐 Apple 的做法）。两栏一律用 12 的整数分割——
     5:7（左标题右说明）/ 7:5（左宽右窄）/ 6:6（均衡），不再出现 0.92fr 这类随手值 */
  --maxw: 1180px;
  --gutter: 24px;
  --section-y: 80px;--section-y-tight:56px;

  /* 缓动：交互用两端慢、中间快的曲线（nanfu.global 全站只用了这一条，出现 50+ 次）；
     入场另用 expo-out —— 起步快、收尾长，是「贵」的来源 */
  --ease: cubic-bezier(0.38, 0, 0, 1);
  --ease-out: cubic-bezier(0.22, 1, 0.36, 1);
  --ease-soft: cubic-bezier(0.4, 0, 0.2, 1);
  --ease-spring: cubic-bezier(0.34, 1.56, 0.64, 1);
  /* 对标 nanfu 的入场曲线：GSAP 的 power1.out。
     nanfu 的入场全部是 { opacity: 0, y: 50 } → { 1, 0 } + power1.out。 */
  --ease-power1: cubic-bezier(0.25, 0.46, 0.45, 0.94);
}

/* ---------- 2. 重置与基础 ---------- */
*,
*::before,
*::after {
  box-sizing: border-box;
}

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

body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font-family: "Noto Sans SC", -apple-system, BlinkMacSystemFont, "Segoe UI", "PingFang SC",
    "Hiragino Sans GB", "Microsoft YaHei", "Source Han Sans SC", "Noto Sans CJK SC",
    sans-serif;
  font-size: 1rem;
  line-height: 1.7;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  overflow-x: hidden;
}

img,
svg {
  display: block;
  max-width: 100%;
}

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

h1, h2, h3, h4 {
  margin: 0;
  color: var(--brand);
  font-weight: 600;
  line-height: 1.25;
  /* 标题折行时自动均分，避免出现只剩一两个字的「孤字」行 */
  text-wrap: balance;
}

p {
  margin: 0;
}

ul {
  margin: 0;
  padding: 0;
  list-style: none;
}

button {
  font: inherit;
  cursor: pointer;
}

::selection {
  background: rgba(0, 102, 255, 0.24);  /* 黄铜淡底 + 深蓝字，比实底更轻 */
  color: var(--brand);
}

/* 滚动条：细、浅、悬停才显色 —— 不抢视线 */
::-webkit-scrollbar { width: 10px; height: 10px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb {
  background: var(--line-strong);
  border: 3px solid transparent;
  background-clip: content-box;
  border-radius: 999px;
}
::-webkit-scrollbar-thumb:hover { background: var(--muted); background-clip: content-box; }

:focus-visible {
  outline: 2px solid var(--brand-400);
  outline-offset: 3px;
  border-radius: 4px;
}

/* 跳过导航：键盘用户第一个 Tab 即可直达正文，平时隐藏在视口外 */
.skip-link {
  position: fixed;
  left: 50%;
  top: -80px;
  transform: translateX(-50%);
  z-index: 200;
  padding: 12px 24px;
  border-radius: 0 0 var(--radius-sm) var(--radius-sm);
  background: var(--brand);
  color: #fff;
  font-size: 1rem;
  font-weight: 600;
  box-shadow: var(--shadow-md);
  transition: top 0.22s var(--ease);
}

.skip-link:focus {
  top: 0;
}

/* ---------- 3. 布局工具 ---------- */
.container {
  width: 100%;
  max-width: var(--maxw);
  margin: 0 auto;
  padding: 0 var(--gutter);
}

.section {
  padding: var(--section-y) 0;
}

.section--alt {
  background: var(--bg-alt);
}

/* 区块底纹：四个极浅色轮换，让整页有色彩节奏，
   而不是「白—灰—白—灰」这种中性重复。

   ★ 接缝过渡（2026-10-12 加）：
     大厂（Apple / 华为 / 腾讯云）相邻 section 底色硬切时，
     都用纵向渐变过渡带柔和接缝，而不是直接色块边界线。

     实现方式（v2，2026-10-12 修正）：
       直接在 section 的 background 上用三段 linear-gradient：
         上 80px  --bg → tint 色（上沿柔化）
         中间     纯 tint 色
         下 80px  tint 色 → --bg（下沿柔化）
       不依赖 ::before/::after 伪元素 —— headless Chrome 截图时
       伪元素的渲染时序不稳定，直接写在 background 上最可靠。

     渐变端色用 var(--bg) 而非 rgba(255,255,255,0)：
       前者色相与 --bg 一致（#fbfcfd 带蓝调），
       后者 alpha=0 在深色或彩色相邻段上会产生可见色相偏移。 */
.section--tint-blue {
  position: relative;
  background:
    linear-gradient(to bottom, var(--bg) 0px, var(--tint-blue) 80px, var(--tint-blue) calc(100% - 80px), var(--bg) 100%);
}
.section--tint-violet {
  position: relative;
  background:
    linear-gradient(to bottom, var(--bg) 0px, var(--tint-violet) 80px, var(--tint-violet) calc(100% - 80px), var(--bg) 100%);
}
.section--tint-teal {
  position: relative;
  background:
    linear-gradient(to bottom, var(--bg) 0px, var(--tint-teal) 80px, var(--tint-teal) calc(100% - 80px), var(--bg) 100%);
}
.section--tint-coral {
  position: relative;
  background:
    linear-gradient(to bottom, var(--bg) 0px, var(--tint-coral) 80px, var(--tint-coral) calc(100% - 80px), var(--bg) 100%);
}

/* ---------- 3b. 业务线色调 ----------
   这一版配色的核心：颜色从「业务分类」里长出来，而不是全站一个蓝。

   取色分两级，靠两个中间变量合成，避免用优先级去硬碰：
     --tone-explicit  写在区块上（data-tone），**会继承**，代表「这一整块属于哪条业务线」
     --tone-rot       写在栅格子元素上，按位置轮换，代表「没有指定时按顺序取色」
   合成点在「色调根元素」上做一次：显式优先，其次轮换，最后兜底品牌蓝。
   后代只继承 --tone，不再重复合成，否则子元素会因为自己没有 --tone-rot 而被兜底色覆盖。 */
:where(.grid--2) > *:nth-child(2n+1) { --tone-rot: var(--c-fde);   --tone-ink-rot: var(--c-fde-ink);   --tone-soft-rot: var(--c-fde-soft); }
:where(.grid--2) > *:nth-child(2n+2) { --tone-rot: var(--c-agent); --tone-ink-rot: var(--c-agent-ink); --tone-soft-rot: var(--c-agent-soft); }
:where(.grid--3) > *:nth-child(3n+1) { --tone-rot: var(--c-fde);   --tone-ink-rot: var(--c-fde-ink);   --tone-soft-rot: var(--c-fde-soft); }
:where(.grid--3) > *:nth-child(3n+2) { --tone-rot: var(--c-agent); --tone-ink-rot: var(--c-agent-ink); --tone-soft-rot: var(--c-agent-soft); }
:where(.grid--3) > *:nth-child(3n+3) { --tone-rot: var(--c-dev);   --tone-ink-rot: var(--c-dev-ink);   --tone-soft-rot: var(--c-dev-soft); }
:where(.grid--4) > *:nth-child(4n+1) { --tone-rot: var(--c-fde);   --tone-ink-rot: var(--c-fde-ink);   --tone-soft-rot: var(--c-fde-soft); }
:where(.grid--4) > *:nth-child(4n+2) { --tone-rot: var(--c-agent); --tone-ink-rot: var(--c-agent-ink); --tone-soft-rot: var(--c-agent-soft); }
:where(.grid--4) > *:nth-child(4n+3) { --tone-rot: var(--c-dev);   --tone-ink-rot: var(--c-dev-ink);   --tone-soft-rot: var(--c-dev-soft); }
:where(.grid--4) > *:nth-child(4n+4) { --tone-rot: var(--c-sec);   --tone-ink-rot: var(--c-sec-ink);   --tone-soft-rot: var(--c-sec-soft); }

[data-tone="fde"],   [data-tone="blue"]   { --tone-explicit: var(--c-fde);   --tone-ink-explicit: var(--c-fde-ink);   --tone-soft-explicit: var(--c-fde-soft); }
[data-tone="agent"], [data-tone="violet"] { --tone-explicit: var(--c-agent); --tone-ink-explicit: var(--c-agent-ink); --tone-soft-explicit: var(--c-agent-soft); }
[data-tone="dev"],   [data-tone="teal"]   { --tone-explicit: var(--c-dev);   --tone-ink-explicit: var(--c-dev-ink);   --tone-soft-explicit: var(--c-dev-soft); }
[data-tone="sec"],   [data-tone="coral"]  { --tone-explicit: var(--c-sec);   --tone-ink-explicit: var(--c-sec-ink);   --tone-soft-explicit: var(--c-sec-soft); }

/* 合成点：栅格子元素，以及任何显式带 data-tone 的元素 */
:where(.grid--2, .grid--3, .grid--4) > *,
[data-tone] {
  --tone: var(--tone-explicit, var(--tone-rot, var(--accent)));
  --tone-ink: var(--tone-ink-explicit, var(--tone-ink-rot, var(--accent-ink)));
  --tone-soft: var(--tone-soft-explicit, var(--tone-soft-rot, var(--accent-soft)));
}

/* 把色调接到具体元素上。凡是「文字」一律用 ink 版，亮色只做面。 */
.card-icon,
.product-icon {
  background: var(--tone-soft, var(--accent-soft));
  color: var(--tone-ink, var(--brand));
}

.card-list li::before { background: var(--tone, var(--accent)); }
.ind-list li::before { background: var(--tone, var(--accent)); }
.ind-q { border-left-color: var(--tone, var(--accent)); }
.why-no { color: var(--tone-ink, var(--muted)); }
.case-ind { color: var(--tone-ink, var(--accent-ink)); }
.step-no,
.flow-no,
.q-item .qn { color: var(--tone-ink, var(--accent-ink)); }
.step-no::before,
.flow-no::before { background: var(--tone, var(--accent)); }
.deliv-item svg { color: var(--tone, var(--accent)); }
.product-tags span,
.case-tags span { background: var(--tone-soft, var(--bg-alt)); color: var(--tone-ink, var(--text-2)); }

/* 卡片顶部一道细色条：最省事的「分类感」，不需要改 HTML。
   只加在栅格子元素上 —— 栅格里的卡一定有 --tone，不会出现「无色条却多出 3px 边框」。 */
:where(.grid--2, .grid--3, .grid--4) > .card,
:where(.grid--2, .grid--3, .grid--4) > .product-card,
:where(.grid--2, .grid--3, .grid--4) > .why-card {
  border-top: 3px solid var(--tone, var(--line));
}

/* 卡片标题前的小色块：已移除
   --------------------------------------------------------------------------
   原来每个卡片标题前有一个 9×9px 的圆角色块（`.card h3::before` 等）。
   它当初的作用是「给每张卡一个颜色锚点」—— 但那是在四条业务线各一个色相
   的前提下才成立的；色相收敛成一个蓝之后，它变成**同一个蓝方块重复出现
   十几次**，不再传递任何信息。

   而且本站已经把「小色块 + 文字」这个手法用在了三处：
     ① eyebrow 前一道 22px 短横
     ② 卡片标题前这个 9px 方块
     ③ 列表项前的方块符号
   同一个手法出现三次就廉价了。保留 ①（每屏只有一处，是版式的起手式）
   和 ③（列表项需要符号，是功能性的），去掉 ②（标题本身就够重，
   再挂一个方块只是装饰）。

   顺带：这也是「模板感」的一处来源 —— 标题前挂个小方块是组件库的默认行为，
   真实设计师排版时通常不会每张卡都加。 */

.section--tight{padding:var(--section-y-tight) 0}

.section-head {
  max-width: 680px;
  margin-bottom: 56px;
}

/* ★ 段落头改「横向对分」：小标通栏 → 标题在左、导语在右。
   由来：用户指出的「太普遍了 / 一股 AI 味道」。
   原来所有段落头都是「小标 + 标题 + 导语」竖排、只占左边 680px，
   **右边半屏是空的** —— 一屏里有一半没内容，读起来像没做完。
   对照版（huanfang-redesign-v5）是标题左、导语右的横向对分：
   同样一块地方，信息铺满了，横向的节奏也出来了。

   纯 CSS 实现，不动 HTML：用 grid 的显式定位把小标通栏、
   标题放左列、导语放右列。

   ★★ 分栏的前提是「右栏真有东西」—— 所以容器规则上挂了 :has(> .lead)。
     这里踩过一次：最初对**所有** .section-head 分栏，于是只有标题、没有导语的那种
     （services 页每个业务段都是）被压进 50% 宽的左栏，中文标题折成三行窄条，
     右半屏整片空着 —— 比不分栏还难看。截图才看出来，静态检查全绿。
     :has() 站上已在用（§64 的 .card:has(.card-link)），不是新依赖。
     下面三条子规则不用跟着改：容器不是 grid 时，grid-column 本身就会被忽略。 */
.section-head:not(.section-head--center):has(> .lead) {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  column-gap: 72px;
  align-items: start;
  max-width: none;
}

/* ★ 680px 是**正文**的阅读上限，对标题太窄。
   只有标题、没有导语的那些段落头（services 每个业务段）留在 680px 里，
   47px 的中文标题一行只放得下 14 个字 —— 稍长的标题就被折成三行，
   右半屏依然是空的，等于「分栏」只解决了有导语的那一半。
   这里把上限放开，再给标题一个按**它自己字号**算的宽度（20em ≈ 944px）。
   标题本身有 text-wrap: balance（见 h1-h4 基础规则），所以两行会均分，
   视觉上仍是「一眼扫完的两行」，不会因为盒子变宽就拉成长条。
   实测（services 三个无导语段落头）：标题盒 680px → 944px，行数不变或更少。 */
.section-head:not(.section-head--center) { max-width: none; }

.section-head:not(.section-head--center):not(:has(> .lead)) > .h2 {
  max-width: 20em;
}

.section-head:not(.section-head--center) > .eyebrow { grid-column: 1 / -1; }

.section-head:not(.section-head--center) > .h2 { grid-column: 1; }

.section-head:not(.section-head--center) > .lead {
  grid-column: 2;
  margin-top: 0;   /* 原来 .lead 有 20px 上边距，在栅格里会和标题错开 */
}

.section-head--center {
  margin-left: auto;
  margin-right: auto;
  text-align: center;
}

.eyebrow {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 16px;
  color: var(--accent-ink);
  font-size: 0.75rem;
  font-weight: 600;
  /* ★ 原来是 0.16em（很宽的字距）+ uppercase。
     字距 0.16em 用在**中文**上是把每个字硬拉开，读起来是散的；
     而 uppercase 对中文完全无作用，只在英文版把每个标签变成全大写 ——
     两个设定叠起来就是「套了个模板」的观感。
     实测 Apple 首页 CSS：letter-spacing 出现 90 次里 90 次是 0em，
     只有大标题用 -.022em 这类负值收字。
     这里收到 0.06em：还看得出是「标签」而不是正文，但不再散。 */
  letter-spacing: 0.06em;
}

.eyebrow::before {
  content: "";
  width: 22px;
  height: 1px;
  background: var(--accent);
}

.section-head--center .eyebrow::before {
  display: none;
}

.h2 {
  font-size: clamp(1.85rem, 3.5vw, 2.95rem);
  /* 1.18 → 1.25。实测 Apple 中文标题（28px 字号 / 35px 行高）= 1.25。
     汉字是满字身框的方块，同样比值下比拉丁字母「更满」，
     所以中文标题需要比拉丁多一点点行距，1.18 对中文偏挤。 */
  line-height: 1.25;
  /* 避免标题最后一行只剩一两个字（中文里这叫「孤字」，
     比英文的孤词更刺眼，因为一个字也占一格）。 */
  text-wrap: balance;
}

.h3 {
  font-size: clamp(1.15rem, 1.6vw, 1.35rem);
  line-height: 1.4;
  text-wrap: balance;
}

.lead {
  margin-top: 20px;
  color: var(--muted);
  font-size: 1.1875rem;
  line-height: 1.8;
}

.text-center {
  text-align: center;
}

/* ---------- 4. 按钮 ---------- */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  padding: 12px 24px;
  border: 1px solid transparent;
  border-radius: var(--radius-btn);
  font-size: 1rem;
  font-weight: 500;
  letter-spacing: 0.02em;
  white-space: nowrap;
  transition: background-color 0.24s var(--ease), color 0.24s var(--ease),
    border-color 0.3s var(--ease), transform 0.5s var(--ease);
}

.btn svg {
  transition: transform 0.5s var(--ease);
}

.btn:hover svg {
  transform: translateX(3px);
}

/* ★ 按钮去掉投影与悬停上浮。
   原来是「实心按钮常驻一层细影，悬停时再上浮 2px 并加一层大柔影」。
   按钮的投影是在模拟「凸起的实体按键」，但网页按钮本来就不存在这个物理事实；
   Apple 与腾讯云的主按钮都是**平的**，悬停只改底色。
   去掉之后主按钮反而更明确 —— 深色实心块本身就够重，不需要再靠阴影加码。 */
/* ★ 主按钮统一用强调蓝。
   原来全站 .btn--primary 是深色（--brand），只有 hero 里被单独覆盖成蓝色 ——
   同一个「主要行动」在页头和首屏是两个颜色，读者得猜哪个更重。
   一个强调色的前提是：这个颜色**只代表一件事**。这里它代表「主要行动」。
   Apple 的购买按钮、腾讯云的主按钮都是蓝的，深色留给文字和区块底。 */
.btn--primary {
  background: var(--accent);
  color: #fff;
}

.btn--primary:hover {
  background: var(--accent-ink);
}

.btn--ghost {
  background: transparent;
  border-color: var(--line-strong);
  color: var(--brand);
}

.btn--ghost:hover {
  border-color: var(--brand);
  background: rgba(16, 24, 40, 0.04);
}

.btn--light {
  background: var(--surface);
  color: var(--brand);
}

.btn--light:hover {
  background: rgba(255, 255, 255, 0.86);
}

.btn--outline-light {
  border-color: rgba(255, 255, 255, 0.32);
  color: #fff;
}

.btn--outline-light:hover {
  border-color: #fff;
  background: rgba(255, 255, 255, 0.12);
  transform: translateY(-2px);
}

.btn--lg {
  padding: 16px 32px;
  font-size: 1rem;
}

.btn--sm {
  padding: 8px 16px;
  font-size: 0.875rem;
}

.btn--block {
  width: 100%;
}

/* 文字链接（带箭头） */
.link-arrow {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  color: var(--brand);
  font-size: 1rem;
  font-weight: 500;
}

.link-arrow svg {
  transition: transform 0.5s var(--ease);
}

.link-arrow:hover svg {
  transform: translateX(4px);
}

/* ---------- 5. 页头 ---------- */
.site-header {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: 100;
  background: rgba(255, 255, 255, 0.86);
  backdrop-filter: saturate(180%) blur(18px);
  -webkit-backdrop-filter: saturate(180%) blur(18px);
  border-bottom: 1px solid transparent;
  transition: border-color 0.3s var(--ease), background-color 0.24s var(--ease);
}

.site-header.is-scrolled {
  border-bottom-color: var(--line);
  background: rgba(255, 255, 255, 0.86);
}

.header-inner {
  /* ★ 从 flex 改成三栏栅格，让主导航**居中**。
     用户那一版（huanfang-redesign-v5）的页头是「品牌在左、导航居中、
     联系与语言在右」—— 这是国际品牌官网的常见版式，
     也是他那版「国外大企业感觉」的一部分。
     我原来是 flex + space-between，导航紧跟在品牌后面靠左，
     读起来像落地页的工具栏，不像品牌官网的导航。

     1fr auto 1fr：两侧等宽，中间那栏自然落在容器正中。
     实测品牌 173px、右侧（语言 + 联系）182px，只差 9px，
     所以导航居中后几乎不偏。 */
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  height: 72px;
}

.header-inner > .brand { justify-self: start; }
.header-inner > .nav { justify-self: center; }
.header-inner > .header-actions { justify-self: end; }

.brand {
  display: inline-flex;
  align-items: center;
  gap: 12px;
}

/* 标识本体：用 currentColor 取色，页头（浅底）与页脚（深底）共用同一段 SVG。
   这里刻意不再有圆角与投影 —— 那是「圆角方块容器」时代的写法，
   现在的标识是独立图形，加圆角/投影会把四角的虚位框住，反而看不清结构。 */
/* 品牌标记：现在是公司正式 logo 的透明底 PNG，不再是内联 SVG。
   ★ 尺寸写死 34px 而不是靠 width/height 属性：
     属性只在样式表加载前起作用，一旦 CSS 里有别的规则（比如 flex 拉伸）
     就会把 logo 拉变形。 */
.brand-mark {
  flex: none;
  display: block;
  width: 34px;
  height: 34px;
}

/* 页脚用横版组合（标记 + 字标）。
   ★ 横版只能在深色底上用 —— 它的字标是白色的，放白底页头上会看不见。
     所以页头用「标记 + HTML 文字」，页脚才用横版。 */
.brand-lockup {
  display: block;
  width: 176px;
  height: auto;
}

.brand-name {
  color: var(--brand);
  font-size: 1.0625rem;
  font-weight: 600;
  letter-spacing: 0.02em;
  /* 品牌名与副标都不换行 —— 它们是「标识」，不是可以折行的正文。
     实测：窄屏下不加这条，「海南 · 中国」会断成「海南 · 中」+「国」。 */
  white-space: nowrap;
}

.brand-sub { white-space: nowrap; }

.brand-sub {
  display: block;
  margin-top: -3px;
  color: var(--muted);
  font-size: 0.75rem;
  font-weight: 500;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.nav {
  display: flex;
  align-items: center;
  gap: 0;
}

/* ★ 导航项用紧凑尺寸（14px / 左右 12px / 无间隔），而不是原来的 16px / 16px / 4px。
   原来的紧凑尺寸写在 `@media (max-width: 1180px)` 里 —— 那是按**视口宽度**判的，
   但内容容器在视口 ≥1228px 时就已经封顶在 1180px 了。
   结果是：**最常见的 1440px 视口下，容器已是最大宽度，导航却是全尺寸**
   ⇒ 英文版实测总需求 1227px、可用 1132px，**超出 95px**，
     八项里有五项折成两行，页头一片拥挤。
   （中文版标签短，一直没暴露这个问题。）

   容器封顶意味着「窄」是常态，不是某个断点的特例，所以紧凑尺寸应该是基础值。
   另外加 nowrap：宁可让容器不够时溢出（下方还有 860px 的移动端菜单兜底），
   也不要让导航项折行 —— 折行的页头比溢出的页头难看得多。 */
.brand-name { white-space: nowrap; }

.nav-link {
  position: relative;
  padding: 8px 8px;
  border-radius: 6px;
  color: var(--text-2);
  font-size: 0.875rem;
  font-weight: 500;
  white-space: nowrap;
  transition: color 0.24s var(--ease), background-color 0.24s var(--ease);
}

.nav-link::after {
  content: "";
  position: absolute;
  left: 16px;
  right: 16px;
  bottom: 3px;
  height: 1.5px;
  background: var(--accent);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform 0.5s var(--ease);
}

.nav-link:hover {
  color: var(--brand);
}

.nav-link:hover::after,
.nav-link.is-active::after {
  transform: scaleX(1);
}

.nav-link.is-active {
  color: var(--brand);
  font-weight: 600;
}

.header-actions {
  display: flex;
  align-items: center;
  gap: 12px;
}

.nav-toggle {
  display: none;
  width: 42px;
  height: 42px;
  padding: 0;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  background: var(--surface);
  position: relative;
}

.nav-toggle span {
  position: absolute;
  left: 12px;
  right: 12px;
  height: 1.6px;
  background: var(--brand);
  border-radius: 2px;
  transition: transform 0.5s var(--ease), opacity 0.32s var(--ease);
}

.nav-toggle span:nth-child(1) { top: 15px; }
.nav-toggle span:nth-child(2) { top: 20px; }
.nav-toggle span:nth-child(3) { top: 25px; }

.nav-toggle[aria-expanded="true"] span:nth-child(1) { transform: translateY(5px) rotate(45deg); }
.nav-toggle[aria-expanded="true"] span:nth-child(2) { opacity: 0; }
.nav-toggle[aria-expanded="true"] span:nth-child(3) { transform: translateY(-5px) rotate(-45deg); }

/* ---------- 6. 首页 Hero：居中声明 + 全宽图 ----------
   ★ 这一节是按用户自己那一版（huanfang-redesign-v5）的版面语言重写的。
     用户的原话：「你做出来的一股 AI 味道……给人一种太普遍了，
     我做的这个版本就有一股国外大企业的感觉。」

     两边摆在一起，差别不在内容，在**版面语言**：
       他：居中构图 / 完整句子带标点 / 一个实心按钮 + 一条文字链 / 照片独立成全宽块
       我：左对齐 / 两行短语 / 两个按钮 / 照片压在文字后面当背景
     我那个是标准 SaaS 落地页版式 —— 这正是「太普遍」的来源。
     改的是**版面语言，不是信息量**（用户明确说内容满意）。

   ★ 顺带一个技术收益：照片从 `background-image` 改成真正的 `<img>`，
     于是它可以被预加载（fetchpriority="high"）、可以给宽高避免布局抖动、
     也能被浏览器的懒加载策略正确识别 —— CSS 背景三样都做不到。 */
.hero {
  position: relative;
  display: flex;
  flex-direction: column;
  justify-content: center;
  /* ★ 首屏铺满一整屏：照片当背景，文字压在上面。
     原来照片是「文字下方的独立块」，首屏下半截是空的，看起来像首页没内容。 */
  min-height: 100svh;
  padding: 128px 0 56px;
  text-align: center;
  overflow: clip;
  background: var(--bg-alt);
}

/* 文字层抬到照片之上 */
.hero > .container {
  position: relative;
  z-index: 1;
}

.hero-inner {
  max-width: 880px;
  margin: 0 auto;
}

.hero h1 {
  font-size: clamp(2rem, 5vw, 3.75rem);
  font-weight: 600;
  line-height: 1.2;
}

.hero .lead {
  max-width: 640px;
  margin: 24px auto 0;
  font-size: 1.1875rem;
  line-height: 1.7;
  /* 首屏是照片背景：正文灰压在照片上实测只有 3.07:1，改用正文色。 */
  color: var(--text);
  /* 两行的导语如果自然折行，末行常只剩两三个字 ——
     实测中文会断在「……我们每／天都在解决。」这种把词切开的地方。
     balance 让两行长度接近，读起来是一个整块。不支持的浏览器直接忽略，无副作用。 */
  text-wrap: balance;
}

/* 行动区居中。★ 次要行动是**文字链**，不是描边按钮 ——
   两个实心/描边按钮并列是落地页的写法；
   一个实心按钮 + 一条安静的文字链，主次一眼分得开。 */
.hero-cta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: 16px 32px;
  margin-top: 40px;
}

.hero-link {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding-bottom: 3px;
  border-bottom: 1px solid var(--line-strong);
  color: var(--brand);
  font-size: 1.0625rem;
  font-weight: 500;
  transition: gap 0.25s var(--ease-soft), border-color 0.25s var(--ease-soft);
}

.hero-link:hover {
  gap: 12px;
  border-bottom-color: var(--brand);
}

/* 全屏背景：铺满整个首屏，文字压在它上面。
   ★ 仍然用真正的 <img>（不是 CSS background-image）：
     可以预加载、可以给宽高避免抖动、能被懒加载策略正确识别。 */
.hero-media {
  position: absolute;
  inset: 0;
  z-index: 0;
  margin: 0;
  padding: 0;
  max-width: none;
}

.hero-media img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  /* 取景偏上一点：把照片里的窗户和桌面留在画面里，别只露地毯。 */
  object-position: center 42%;
  border-radius: 0;
  background: var(--bg-alt);
}

/* 白色薄纱。★ 强度是量出来的，不是拍的：
   照片下半部分有深色桌面，深色文字压上去实测只有 1.34:1（要求 4.5:1）。
   0.45 之后最暗处被抬到约 0.62 亮度，正文灰与强调色都能稳过 4.5:1。 */
.hero-media::after {
  content: '';
  position: absolute;
  inset: 0;
  background: rgba(255, 255, 255, 0.44);
}

/* 照片标注：放在**照片下方**，不是压在照片上。
   ★ 对照版是把「业务场景配图」压在照片右上角的，我一开始也照做了。
     但对比度检查立刻抓到：白字压在**明亮的照片**上，实际对比度接近 1:1
     （现在这张首屏图是阳光办公室，右上角正对着一片亮窗）。
     他那版能压是因为他的照片偏暗；照片亮度不同，同一套做法不成立。
     ⇒ 放到图下方当图注：深色小字，任何照片上都能读，
       而且语义上也更对 —— figcaption 本来就在 figure 里。 */
.hero-credit {
  position: absolute;
  right: 18px;
  bottom: 12px;
  /* 抬到薄纱之上，否则会被 ::after 盖住 */
  z-index: 1;
  display: block;
  margin: 0;
  /* 图注在右下角，正好压在照片的深色桌面上 —— 同样改用正文色 */
  color: var(--text);
  font-size: 0.75rem;
  letter-spacing: 0.06em;
  text-align: right;
}

/* 照片之后的两条辅助文案。
   它们本来跟在按钮下面，但那样首屏文字块太高、照片被挤出视口。
   移到这里之后阅读顺序变成：声明 → 导语 → 行动 → 照片 → 细则，
   既保住了全部内容，也让照片进得了首屏。 */
.hero-fine {
  max-width: 780px;
  margin: 24px auto 0;
  padding-bottom: 8px;
}

.hero-fine .hero-meta,
.hero-fine .hero-cta-note {
  margin: 0;
  /* ★ 正文色而不是 --muted。首屏现在是照片背景，--muted 那种浅灰
     压在照片的深色区域上实测只有 1.34:1；小字换成正文色才站得住。 */
  color: var(--text);
  font-size: 0.875rem;
  line-height: 1.7;
}

.hero-fine .hero-cta-note { margin-top: 8px; }

/* ★ 窄屏必须回到 flex 布局。
   三栏栅格在 860px 以下会把品牌那栏压得太窄，
   「幻方造梦 / 海南 · 中国」被挤成三行。
   而窄屏下主导航本来就是 position:fixed 的下拉面板（脱离栅格流），
   栅格只剩「品牌 + 操作区」两栏，用 flex + space-between 更简单也更稳。 */
@media (max-width: 860px) {
  .header-inner {
    display: flex;
    justify-content: space-between;
  }

  /* 窄屏段落头收起为单栏：两栏在手机上每栏只剩 160px，中文一行放不下五个字 */
  /* ★ 必须带上 :has(> .lead)：桌面那条分栏规则 .section-head:not(...):has(> .lead)
     特异性是 (0,3,0)，比这里的 (0,2,0) 高 —— 不带它就压不住，移动端会一直停在
     「两栏」上，标题被挤进左半屏、右半屏全空（实测 390px 下标题栏只有 139px）。 */
  .section-head:not(.section-head--center),
  .section-head:not(.section-head--center):has(> .lead) {
    grid-template-columns: minmax(0, 1fr);
    row-gap: 16px;
  }

  .section-head:not(.section-head--center) > .eyebrow,
  .section-head:not(.section-head--center) > .h2,
  .section-head:not(.section-head--center) > .lead { grid-column: 1; }

  .section-head:not(.section-head--center) > .lead { margin-top: 0; }
}

@media (max-width: 720px) {
  .hero { padding: 112px 0 44px; }
  .hero-media img { object-position: center 38%; }
}

/* 数据条 */
.stats {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 1px;
  margin-top: 84px;
  background: var(--line);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  overflow: hidden;
}

.stat {
  padding: 32px 24px;
  background: var(--surface);
}

.stat-num {
  display: flex;
  align-items: baseline;
  gap: 2px;
  color: var(--brand);
  font-size: clamp(1.75rem, 3vw, 2.3rem);
  font-weight: 600;
  letter-spacing: -0.03em;
  line-height: 1.1;
}

.stat-num .unit {
  font-size: 0.5em;
  font-weight: 600;
  color: var(--accent-ink);
}

.stat-label {
  margin-top: 8px;
  color: var(--muted);
  font-size: 0.875rem;
}

/* ---------- 7. 客户条 ---------- */
.logo-strip{padding:var(--section-y-tight) 0;
  border-top: 1px solid var(--line);
  border-bottom: 1px solid var(--line);
}

.logo-strip p {
  margin-bottom: 24px;
  color: var(--muted);
  font-size: 0.875rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  text-align: center;
}

.logo-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: 16px 52px;
}

.logo-item {
  color: var(--muted);
  font-size: 1.0625rem;
  font-weight: 600;
  letter-spacing: 0.04em;
  transition: color 0.24s var(--ease);
}

/* ---------- 8. 卡片网格 ---------- */
.grid {
  display: grid;
  gap: 24px;
}

.grid--2 { grid-template-columns: repeat(2, 1fr); }
.grid--3 { grid-template-columns: repeat(3, 1fr); }
.grid--4 { grid-template-columns: repeat(4, 1fr); }

.card {
  position: relative;
  padding: 32px 32px;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  transition: border-color 0.3s var(--ease-soft);
}

/* ★ 悬停不再上浮、不再加阴影。
   原来这里是 translateY(-5px) + 双层阴影（一层贴地细影、一层大范围柔影），
   当时的说明是「两层的阴影比一层黑边高级」。
   但阴影 = 卡片离开纸面，而这里的内容（服务说明、行业口径、验收指标）
   本来就在同一个平面上，让它们「浮起来」是在表达一种并不存在的层级。
   Apple 首页 CSS 里 box-shadow 出现 0 次 —— 分层靠边框、留白和背景色差，
   不靠投影。腾讯云同样如此。
   现在悬停只让边框变深一档：最轻的「我收到了」。 */
.card:has(.card-link):hover {
  border-color: var(--line-strong);
}

.card-icon {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 48px;
  height: 48px;
  margin-bottom: 24px;
  border-radius: 12px;
  background: var(--accent-soft);
  color: var(--brand);
}

.card h3 {
  font-size: 1.1875rem;
}

.card p {
  margin-top: 12px;
  color: var(--muted);
  font-size: 1rem;
  line-height: 1.8;
}

.card-list {
  margin-top: 16px;
  padding-top: 16px;
  border-top: 1px dashed var(--line);
}

.card-list li {
  position: relative;
  padding-left: 20px;
  color: var(--text-2);
  font-size: 0.875rem;
  line-height: 1.7;
  text-wrap: balance;
}

.card-list li + li {
  margin-top: 6px;
}

.card-list li::before {
  content: "";
  position: absolute;
  left: 0;
  top: 11px;
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--tone, var(--accent));
}

/* ---------- 9. 分栏（图文） ---------- */
.split {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 72px;
  align-items: center;
}

.split--wide-left {
  grid-template-columns: minmax(0, 7fr) minmax(0, 5fr);   /* 7:5 */
}

.split h2 {
  font-size: clamp(1.6rem, 2.8vw, 2.25rem);
}

.split .lead {
  font-size: 1rem;
}

.check-list {
  margin-top: 28px;
}

.check-list li {
  display: flex;
  gap: 12px;
  align-items: flex-start;
  color: var(--text-2);
  font-size: 1rem;
  line-height: 1.7;
}

.check-list li + li {
  margin-top: 16px;
}

.check-list svg {
  flex: none;
  margin-top: 4px;
  color: var(--accent-ink);
}

/* 视觉块（纯 CSS 构成，无外部图片依赖） */
.visual {
  position: relative;
  border-radius: var(--radius);
  overflow: hidden;
  aspect-ratio: 4 / 3.2;
  /* 斜向渐变改实色：四角各偏一个色会让这块「浮」起来，且和真正的照片并列时不像一类东西 */
  background: var(--brand);
}

.visual::before {
  content: "";
  position: absolute;
  inset: 0;
  /* 网格保留：这是「工程图纸」的语汇，和公司做系统集成这件事对得上，
     不是装饰性花纹。但它只是 7% 白的一层纹理，不参与配色。 */
  background-image:
    linear-gradient(rgba(255, 255, 255, 0.07) 1px, transparent 1px),
    linear-gradient(90deg, rgba(255, 255, 255, 0.07) 1px, transparent 1px);
  background-size: 44px 44px;
}

/* 原来的右下角发光圆（320px 蓝色径向渐变）已删除 —— 见 §14 CTA 处的说明 */

.visual-inner {
  position: relative;
  z-index: 1;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  height: 100%;
  padding: 32px;
  color: #fff;
}

.visual-tag {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  align-self: flex-start;
  padding: 6px 12px;
  border: 1px solid rgba(255, 255, 255, 0.24);
  border-radius: 999px;
  font-size: 0.75rem;
  letter-spacing: 0.08em;
}

.visual-title {
  font-size: 1.5rem;
  font-weight: 600;
  line-height: 1.4;
}

.visual-bars {
  display: flex;
  align-items: flex-end;
  gap: 8px;
  height: 96px;
  margin-top: 24px;
}

.visual-bars span {
  flex: 1;
  border-radius: 4px 4px 0 0;
  background: linear-gradient(180deg, rgba(255, 255, 255, 0.86), rgba(255, 255, 255, 0.24));
  transform-origin: bottom;
  animation: barGrow 1.1s var(--ease) both;
}

.visual-bars span:nth-child(1) { height: 38%; animation-delay: 0.05s; }
.visual-bars span:nth-child(2) { height: 58%; animation-delay: 0.12s; }
.visual-bars span:nth-child(3) { height: 46%; animation-delay: 0.19s; }
.visual-bars span:nth-child(4) { height: 78%; animation-delay: 0.26s; }
.visual-bars span:nth-child(5) { height: 100%; background: linear-gradient(180deg, #7ab3ff, rgba(0, 102, 255, 0.35)); animation-delay: 0.33s; }

@keyframes barGrow {
  from { transform: scaleY(0.04); opacity: 0; }
  to { transform: scaleY(1); opacity: 1; }
}

/* 深色数据卡 */
.panel-dark {
  padding: 44px 40px;
  border-radius: var(--radius);
  /* 斜向渐变 + 大阴影 → 实色。同 §14 CTA 的说明 */
  background: var(--brand);
  color: #fff;
}

/* ★ 原来是 #d8bd8c（暖金）—— 这是早期「黄铜」主题的残留，
   全站只剩这 3 处，等于多出来第五个色相。
   深色底上的标签统一用 var(--accent-lite)（与 .section--dark .eyebrow 同色）。 */
.panel-dark .eyebrow {
  color: var(--accent-lite);
}

.panel-dark .eyebrow::before {
  background: var(--accent-lite);
}

.panel-dark h3 {
  color: #fff;
  font-size: 1.5rem;
}

.panel-dark p {
  margin-top: 12px;
  color: rgba(255, 255, 255, 0.70);
  font-size: 1rem;
}

.panel-dark .check-list li {
  color: rgba(255, 255, 255, 0.86);
}

.panel-dark .check-list svg {
  color: var(--accent-lite);
}

/* 数据口径说明：小字、弱化，但仍需过 WCAG AA（实测 8.9:1） */
.panel-dark .panel-note {
  margin-top: 24px;
  padding-top: 16px;
  border-top: 1px solid rgba(255, 255, 255, 0.12);
  color: rgba(255, 255, 255, 0.70);
  font-size: 0.875rem;
  line-height: 1.7;
}

/* ---------- 10. 服务/产品大卡 ---------- */
.feature {
  display: grid;
  grid-template-columns: minmax(0, 5fr) minmax(0, 7fr);   /* 5:7 */
  gap: 0;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  overflow: hidden;
  background: var(--surface);
  transition: border-color 0.3s var(--ease);
}

.feature + .feature {
  margin-top: 24px;
}

.feature-body {
  padding: 44px 40px;
}

.feature-no {
  color: var(--accent-ink);
  font-size: 0.875rem;
  font-weight: 600;
  letter-spacing: 0.06em;
}

.feature h3 {
  margin-top: 16px;
  font-size: clamp(1.25rem, 2vw, 1.55rem);
}

.feature p {
  margin-top: 16px;
  color: var(--muted);
  font-size: 1rem;
  line-height: 1.8;
}

.feature-tags {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-top: 24px;
}

.tag {
  padding: 5px 12px;
  border: 1px solid var(--line-strong);
  border-radius: 999px;
  color: var(--text-2);
  font-size: 0.875rem;
}

.feature-visual {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 40px;
  background: linear-gradient(150deg, var(--bg-alt), var(--tint-blue));
  background-color: var(--bg-alt);
  border-left: 1px solid var(--line);
}

.feature-visual svg {
  width: 100%;
  max-width: 300px;
  height: auto;
}

/* ---------- 11. 流程步骤 ---------- */
.steps {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 32px;
  counter-reset: step;
}

.step {
  position: relative;
  padding-top: 32px;
  border-top: 2px solid var(--line);
}

.step::before {
  content: "";
  position: absolute;
  top: -2px;
  left: 0;
  width: 46px;
  height: 2px;
  background: var(--accent);
}

.step-no {
  color: var(--accent-ink);
  font-size: 0.875rem;
  font-weight: 600;
  letter-spacing: 0.06em;
}

.step h3 {
  margin-top: 8px;
  font-size: 1.1875rem;
}

.step p {
  margin-top: 8px;
  color: var(--muted);
  font-size: 0.875rem;
  line-height: 1.8;
}

/* ---------- 12. 时间轴 ---------- */
.timeline {
  position: relative;
  margin-top: 12px;
  padding-left: 32px;
}

.timeline::before {
  content: "";
  position: absolute;
  left: 5px;
  top: 8px;
  bottom: 8px;
  width: 1px;
  background: linear-gradient(180deg, var(--accent), var(--line) 85%);
}

.tl-item {
  position: relative;
  padding-bottom: 40px;
}

.tl-item:last-child {
  padding-bottom: 0;
}

.tl-item::before {
  content: "";
  position: absolute;
  left: -30px;
  top: 7px;
  width: 11px;
  height: 11px;
  border: 2px solid var(--accent);
  border-radius: 50%;
  background: var(--surface);
}

.tl-year {
  color: var(--accent-ink);
  font-size: 0.875rem;
  font-weight: 600;
  letter-spacing: 0.06em;
}

.tl-item h3 {
  margin-top: 6px;
  font-size: 1.1875rem;
}

.tl-item p {
  margin-top: 8px;
  color: var(--muted);
  font-size: 1rem;
  line-height: 1.8;
}

/* ---------- 13. 引用 ---------- */
.quote {
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  height: 100%;
  padding: 32px 32px;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--surface);
}

.quote-mark {
  color: var(--accent-ink);
  font-size: 2.5rem;
  line-height: 1;
  font-family: Georgia, serif;
}

.quote p {
  margin-top: 16px;
  color: var(--text-2);
  font-size: 1rem;
  line-height: 1.8;
}

.quote-by {
  display: flex;
  align-items: center;
  gap: 12px;
  margin-top: 24px;
  padding-top: 24px;
  border-top: 1px solid var(--line);
}

.avatar {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 40px;
  height: 40px;
  flex: none;
  border-radius: 50%;
  background: var(--brand);
  color: #fff;
  font-size: 0.875rem;
  font-weight: 600;
}

.quote-by strong {
  display: block;
  color: var(--brand);
  font-size: 1rem;
  font-weight: 600;
}

.quote-by span {
  color: var(--muted);
  font-size: 0.875rem;
}

/* ---------- 14. CTA 横幅 ---------- */
.cta{position:relative;overflow:hidden;padding:var(--section-y) 0;
  /* ★ 原来这里是两层彩色径向光晕 + 一层 140° 斜向深色渐变，
     右上角还额外挂了一个 460px 的发光圆（.cta::after）。
     一个深色横幅同时叠三样东西，是「用力过猛」的典型：
     斜向渐变让底色在四角各偏一个色，光晕再叠上去，整块就不干净了。
     Apple 的深色区块是**一个实色**铺满（#1d1d1f 一类的近黑），
     对比靠留白与字重给，不靠底色本身做文章。 */
  background: var(--brand);
  color: #fff;
}

.cta-inner {
  position: relative;
  z-index: 1;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 40px;
}

.cta h2 {
  color: #fff;
  font-size: clamp(1.5rem, 2.8vw, 2.15rem);
}

.cta p {
  margin-top: 16px;
  max-width: 520px;
  color: rgba(255, 255, 255, 0.70);
  font-size: 1rem;
}

.cta-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  flex: none;
}

/* ---------- 15. 内页 Hero ---------- */
.page-hero {
  position: relative;
  /* ★ 2026-10-17 · 去掉 border-bottom。
     用户反馈三页「分割感太重」。实测根因之一：
     faq / delivery 的 hero 底部有一条 1px var(--line)，而紧随其后的
     `.localnav` 顶部**也有一条** 1px var(--line) —— 两条同色线贴在一起，
     中间还夹着一层 `rgba(255,255,255,.86)` 的半透明条带，
     滚过去是一道「灰条 + 双线」的厚重分隔，把 hero 和正文切成两块。

     Apple 的内页 hero 与正文之间**只有一道线**，而且线是唯一的分隔手段。
     所以这里把 hero 的底边线去掉，分隔由紧随其后的那条
     `.localnav`（有 localnav 的页）或第一个 section 承担；
     没有 localnav 的页（cases.html）改为用**留白 + 极淡的底色过渡**分隔，
     见 .page-hero + section 的规则。
     ★ 去掉后两页高度差也一并收窄：原来 hero 470 / 604px 里有一部分
       是被那条线和它的外边距撑出来的。 */
  padding: 160px 0 68px;
  /* 内页 hero 保持浅色：整站只有首页首屏是深色，否则会「一半是黑的」。
     原来是「右上角一团蓝色光晕 + 纵向白渐变」，现在只留平的底色 ——
     内页 hero 上有面包屑、大标题、导语，本来就有层次，
     再垫一层光晕只是让底色不干净。 */
  background: var(--bg);
}

/* 没有 localnav 的内页（如 cases.html）：hero 与第一个 section 之间
   用留白分隔，不再画线。若第一个 section 自带底色（tint），
   底色边缘本身就是分隔，比一条 1px 线更自然。 */
.page-hero + section { margin-top: 0; }

.breadcrumb {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 16px;
  color: var(--muted);
  font-size: 0.875rem;
}

.breadcrumb a:hover {
  color: var(--brand);
}

.breadcrumb span {
  color: var(--muted);   /* 浅色内页 hero 上 --line-strong 只有 1.68:1 */
}

.page-hero h1 {
  max-width: 820px;
  /* ★ 2026-10-16 · 对齐 Apple 的内页首屏尺度：原 clamp(2rem,4.4vw,3.15rem)
     在 1440 下只有 50.4px，与首页 88px 的 h1 断层太大，内页显得「小气」。
     提到 clamp(2.1rem,5vw,3.75rem)=60px，并收紧行高与字距（大字必需）。
     与 home.css 里同名规则同值，两套样式表保持一致（twin-stylesheet）。 */
  font-size: clamp(2.1rem, 5vw, 3.75rem);
  line-height: 1.1;
  letter-spacing: -0.02em;
}

.page-hero .lead {
  max-width: 620px;
  color: var(--text-2);
}

/* 内页 hero 是浅色的，文字保持深色 */
.page-hero h1 { color: var(--text); }
.page-hero .eyebrow { color: var(--accent-ink); }
.page-hero .breadcrumb,
.page-hero .breadcrumb a { color: var(--muted); }
.page-hero .breadcrumb a:hover { color: var(--brand); }

/* ---------- 16. 表单 ---------- */
.form-card {
  padding: 44px 40px;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius);
}

.form-row {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 20px;
}

.field {
  padding-top:var(--section-y-tight);margin-bottom:20px;
}

.field label {
  display: block;
  margin-bottom: 8px;
  color: var(--brand);
  font-size: 0.875rem;
  font-weight: 500;
}

.field label .req {
  color: #c0392b;
  margin-left: 3px;
}

.field input,
.field select,
.field textarea {
  width: 100%;
  padding: 12px 16px;
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-sm);
  background: var(--surface);
  color: var(--text);
  font-family: inherit;
  font-size: 1rem;
  transition: border-color 0.3s var(--ease), background-color 0.24s var(--ease);
}

.field textarea {
  min-height: 128px;
  resize: vertical;
  line-height: 1.7;
}

.field input::placeholder,
.field textarea::placeholder {
  color: var(--muted);
  opacity: 1;   /* Firefox 默认会再压一层透明度 */
}

.field input:focus,
.field select:focus,
.field textarea:focus {
  outline: none;
  border-color: var(--brand-400);
  box-shadow: 0 0 0 3px rgba(43, 84, 128, 0.16);
  background: var(--surface);
  box-shadow: 0 0 0 3px rgba(43, 84, 128, 0.12);
}

.field.has-error input,
.field.has-error select,
.field.has-error textarea {
  border-color: #c0392b;
  background: #fdf6f5;
}

.field-error {
  display: none;
  margin-top: 7px;
  color: #c0392b;
  font-size: 0.875rem;
}

.field.has-error .field-error {
  display: block;
}

.form-hint {
  margin-top: 16px;
  color: var(--muted);
  font-size: 0.875rem;
  line-height: 1.7;
}

/* 表单降级兜底：未配置后端时，把内容直接显示出来供复制。
   移动端与 WebView 里 mailto: 常常静默失败，这一层保证访客有路可走。 */
.form-fallback {
  margin-top: 20px;
  padding: 18px 20px;
  border: 1px solid var(--line, #cad4e1);
  border-radius: var(--radius-sm, 10px);
  background: var(--bg-alt, #f2f5f9);
}

.form-fallback__head {
  margin-bottom: 10px;
  color: var(--text-2, #475467);
  font-size: 0.875rem;
  font-weight: 600;
}

.form-fallback__body {
  max-height: 220px;
  margin: 0 0 14px;
  padding: 12px 14px;
  overflow: auto;
  border: 1px solid var(--line, #cad4e1);
  border-radius: 8px;
  background: var(--surface, #fff);
  color: var(--text, #101828);
  font-family: var(--mono, ui-monospace, SFMono-Regular, Menlo, Consolas, monospace);
  font-size: 0.8125rem;
  line-height: 1.65;
  white-space: pre-wrap;
  word-break: break-word;
}

.form-fallback__copy {
  min-width: 96px;
}

.form-success {
  display: none;
  align-items: flex-start;
  gap: 16px;
  margin-bottom: 24px;
  padding: 16px 20px;
  border: 1px solid #b7dfc4;
  border-radius: var(--radius-sm);
  background: #f1faf4;
}

.form-success.is-shown {
  display: flex;
}

.form-success svg {
  flex: none;
  margin-top: 2px;
  color: #1e7a45;
}

.form-success strong {
  display: block;
  color: #1e7a45;
  font-size: 1rem;
}

.form-success p {
  margin-top: 3px;
  color: #3f6b51;
  font-size: 0.875rem;
}

/* ---------- 17. 联系信息列表 ---------- */
.info-list li {
  display: flex;
  gap: 16px;
  padding: 20px 0;
  border-bottom: 1px solid var(--line);
}

.info-list li:first-child {
  padding-top: 0;
}

.info-icon {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 40px;
  height: 40px;
  flex: none;
  border-radius: var(--radius-sm);
  background: var(--bg-alt);
  color: var(--brand);
}

.info-list h3 {
  font-size: 1rem;
}

.info-list p {
  margin-top: 4px;
  color: var(--muted);
  font-size: 1rem;
  line-height: 1.7;
}

.info-list a:hover {
  color: var(--brand);
  text-decoration: underline;
  text-underline-offset: 3px;
}

.office {
  padding: 28px 24px;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--surface);
  transition: border-color 0.3s var(--ease);
}

.office-city {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
}

.office h3 {
  font-size: 1.1875rem;
}

.badge {
  padding: 3px 8px;
  border-radius: 999px;
  background: var(--accent-soft);
  color: var(--accent-ink);
  font-size: 0.75rem;
  font-weight: 600;
}

.office p {
  margin-top: 12px;
  color: var(--muted);
  font-size: 0.875rem;
  line-height: 1.8;
}

.office dl {
  margin: 16px 0 0;
  padding-top: 16px;
  border-top: 1px dashed var(--line);
  font-size: 0.875rem;
}

.office dl div {
  display: flex;
  gap: 8px;
}

.office dl div + div {
  margin-top: 7px;
}

.office dt {
  flex: none;
  width: 62px;
  color: var(--muted);
}

.office dd {
  margin: 0;
  color: var(--text-2);
}

/* ---------- 18. 折叠面板 ---------- */
.faq-item {
  border-bottom: 1px solid var(--line);
}

.faq-q {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 20px;
  width: 100%;
  padding: 24px 0;
  border: 0;
  background: none;
  color: var(--brand);
  font-size: 1.1875rem;
  font-weight: 500;
  text-align: left;
}

.faq-q:hover {
  color: var(--brand-400);
}

.faq-icon {
  position: relative;
  flex: none;
  width: 18px;
  height: 18px;
}

.faq-icon::before,
.faq-icon::after {
  content: "";
  position: absolute;
  top: 50%;
  left: 0;
  width: 100%;
  height: 1.6px;
  background: currentColor;
  border-radius: 2px;
  transition: transform 0.5s var(--ease);
}

.faq-icon::after {
  transform: rotate(90deg);
}

.faq-item.is-open .faq-icon::after {
  transform: rotate(0deg);
}

.faq-a {
  display: grid;
  grid-template-rows: 0fr;
  transition: grid-template-rows 0.4s var(--ease);
}

.faq-item.is-open .faq-a {
  grid-template-rows: 1fr;
}

.faq-a > div {
  overflow: hidden;
}

.faq-a p {
  padding-bottom: 24px;
  color: var(--muted);
  font-size: 1rem;
  /* 行长收到 43 字之后，行高可以收一档：
     行越长需要的行距越大，反过来行长收短了行距也该跟着收，
     否则字与字之间的呼吸反而比行与行还多。 */
  line-height: 1.7;
}

/* ---------- 19. 产品矩阵卡片 ---------- */
.product-card {
  position: relative;
  display: flex;
  flex-direction: column;
  padding: 24px 24px;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  transition: transform 0.5s var(--ease),
    border-color 0.3s var(--ease);
}

/* 与 .card 同一套悬停语言：只让边框变深一档，不上浮、不加影 */
.product-card:has(.card-link):hover {
  border-color: var(--line-strong);
}

.product-head {
  display: flex;
  align-items: center;
  gap: 12px;
  margin-bottom: 16px;
}

.product-icon {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 40px;
  height: 40px;
  flex: none;
  border-radius: var(--radius-sm);
  background: var(--bg-alt);
  color: var(--brand);
}

.product-card h3 {
  margin: 0;
  color: var(--brand);
  font-size: 1rem;
  font-weight: 600;
  line-height: 1.4;
  text-wrap: balance;
}

.product-card p {
  flex: 1;
  color: var(--muted);
  font-size: 0.875rem;
  line-height: 1.7;
}

.product-tags {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin-top: 16px;
}

.product-tags span {
  padding: 3px 8px;
  border-radius: 999px;
  background: var(--bg-alt);
  color: var(--text-2);
  font-size: 0.75rem;
  line-height: 1.6;
}

/* ---------- 19b. 资质认证 ---------- */
.cert-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 16px;
}

.cert {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 16px 16px;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  background: var(--surface);
  transition: border-color 0.3s var(--ease);
}

.cert svg {
  flex: none;
  color: var(--accent-ink);
}

.cert span {
  color: var(--text-2);
  font-size: 0.875rem;
  line-height: 1.6;
  /* 折行时自动均分两行，避免出现只有一个字的「孤字」行 */
  text-wrap: balance;
}

/* ---------- 19c. 对比表 ---------- */
.cmp-wrap {
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
}

.cmp {
  width: 100%;
  min-width: 600px;
  border-collapse: separate;
  border-spacing: 0;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  overflow: hidden;
  font-size: 1rem;
}

.cmp th,
.cmp td {
  padding: 16px 24px;
  text-align: left;
  vertical-align: top;
  border-bottom: 1px solid var(--line);
  line-height: 1.7;
}

.cmp tbody tr:last-child th,
.cmp tbody tr:last-child td {
  border-bottom: 0;
}

.cmp thead th {
  background: var(--bg-alt);
  color: var(--brand);
  font-size: 0.875rem;
  font-weight: 600;
  white-space: nowrap;
}

.cmp thead th.is-accent {
  background: var(--brand);
  color: #fff;
}

.cmp tbody th {
  width: 18%;
  background: var(--bg-alt);
  color: var(--muted);
  font-size: 0.875rem;
  font-weight: 500;
  white-space: nowrap;
}

.cmp td {
  color: var(--text-2);
}

.cmp td.is-accent {
  background: rgba(0, 102, 255, 0.07);
  color: var(--brand);
  font-weight: 500;
}

/* ---------- 19d. 代理品牌面板 ---------- */
.brands {
  display: grid;
  grid-template-columns: minmax(0, 5fr) minmax(0, 7fr);   /* 5:7 */
  gap: 48px;
  align-items: center;
  padding: 40px 40px;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--surface);
}

.brands-label .eyebrow {
  margin-bottom: 16px;
}

.brands-label h3 {
  font-size: 1.1875rem;
  line-height: 1.4;
}

.brands-label p {
  margin-top: 12px;
  color: var(--muted);
  font-size: 1rem;
  line-height: 1.8;
}

.brand-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 8px;
}

.brand-chip {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 52px;
  padding: 8px 8px;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  background: var(--bg-alt);
  color: var(--brand);
  font-size: 1rem;
  font-weight: 600;
  letter-spacing: 0.02em;
  text-align: center;
  transition: background-color 0.24s var(--ease), border-color 0.3s var(--ease),
    transform 0.5s var(--ease);
}

.brand-chip--more {
  border-style: dashed;
  background: none;
  color: var(--muted);
  font-size: 0.875rem;
  font-weight: 500;
}

.brand-chip--more:hover {
  background: none;
  border-color: var(--line-strong);
  color: var(--text-2);
}

/* ---------- 19e. 能力标签行 ---------- */
.cap-row {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}

.cap-chip {
  padding: 12px 20px;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: var(--surface);
  color: var(--brand);
  font-size: 1rem;
  font-weight: 500;
  white-space: nowrap;
  transition: border-color 0.3s var(--ease), background-color 0.24s var(--ease),
    transform 0.5s var(--ease);
}

/* ---------- 19f. 方法论页专用组件 ---------- */

/* 双角色卡（Echo / Delta） */
.role-card {
  padding: 32px 28px;
  border: 1px solid var(--line);
  border-top: 4px solid var(--brand);
  border-radius: var(--radius);
  background: var(--surface);
}

.role-card--alt {
  border-top-color: var(--accent-ink);
}

.role-card h3 {
  display: flex;
  align-items: baseline;
  gap: 8px;
  font-size: 1.1875rem;
}

.role-card h3 em {
  font-style: normal;
  color: var(--muted);
  font-size: 0.75rem;
  font-weight: 500;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}

.role-card > p {
  margin-top: 12px;
  color: var(--muted);
  font-size: 1rem;
  line-height: 1.8;
}

.role-card .role-note {
  margin-top: 16px;
  padding: 16px 16px;
  border-radius: var(--radius-sm);
  background: var(--accent-soft);
  color: #7d5f30;
  font-size: 0.875rem;
  line-height: 1.7;
}

/* 五列步骤 */
.steps--5 {
  grid-template-columns: repeat(5, 1fr);
  gap: 20px;
}

/* 步骤的交付物行 */
.step-out {
  margin-top: 16px;
  padding-top: 12px;
  border-top: 1px dashed var(--line);
  color: var(--brand);
  font-size: 0.875rem;
  font-weight: 500;
  line-height: 1.7;
}

/* 案例卡 */
.case-card {
  display: grid;
  grid-template-columns: 258px 1fr;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  overflow: hidden;
  background: var(--surface);
  transition: border-color 0.3s var(--ease);
}

.case-card + .case-card {
  margin-top: 24px;
}

.case-side {
  padding: 24px 24px;
  background: var(--bg-alt);
  border-right: 1px solid var(--line);
}

.case-ind {
  color: var(--tone-ink, var(--accent-ink));
  font-size: 0.75rem;
  font-weight: 600;
  letter-spacing: 0.06em;
}

.case-co {
  margin-top: 8px;
  color: var(--brand);
  font-size: 1.1875rem;
  font-weight: 600;
}

.case-scale {
  margin-top: 4px;
  color: var(--muted);
  font-size: 0.875rem;
  line-height: 1.6;
}

.case-meta {
  margin-top: 16px;
  padding-top: 16px;
  border-top: 1px dashed var(--line-strong);
}

.case-meta div + div {
  margin-top: 8px;
}

.case-meta dt {
  color: var(--muted);
  font-size: 0.75rem;
}

.case-meta dd {
  margin: 2px 0 0;
  color: var(--brand);
  font-size: 1rem;
  font-weight: 600;
}

.case-body {
  padding: 24px 28px;
}

.case-body h3 {
  font-size: 1.1875rem;
}

.case-body > p {
  margin-top: 6px;
  color: var(--muted);
  font-size: 0.875rem;
}

.case-pain {
  margin: 16px 0 0;
  padding: 16px 16px;
  border-left: 3px solid #c0392b;
  border-radius: 0 var(--radius-sm) var(--radius-sm) 0;
  background: #fdf6f5;
  color: #8f2222;
  font-size: 0.875rem;
  line-height: 1.8;
}

.case-pain strong {
  color: #c0392b;
}

.case-metrics {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 12px;
  margin-top: 24px;
  padding-top: 20px;
  border-top: 1px solid var(--line);
}

.case-metrics div {
  text-align: center;
}

.case-metrics .cm-v {
  color: var(--brand);
  font-size: 1.5rem;
  font-weight: 600;
  letter-spacing: -0.02em;
  line-height: 1.2;
}

.case-metrics .cm-l {
  margin-top: 4px;
  color: var(--muted);
  font-size: 0.75rem;
  line-height: 1.5;
}

.case-tags {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin-top: 16px;
}

.case-tags span {
  padding: 3px 8px;
  border-radius: 999px;
  background: var(--bg-alt);
  color: var(--text-2);
  font-size: 0.75rem;
}

/* 问答卡（六个必答问题） */
.q-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 16px;
}

.q-item {
  padding: 24px 24px;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--surface);
}

.q-item .qn {
  color: var(--accent-ink);
  font-size: 0.75rem;
  font-weight: 600;
  letter-spacing: 0.06em;
}

.q-item h3 {
  margin-top: 8px;
  font-size: 1rem;
}

.q-item p {
  margin-top: 8px;
  color: var(--muted);
  font-size: 0.875rem;
  line-height: 1.7;
}

/* 交付物清单 */
.deliv-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 12px;
}

.deliv-item {
  display: flex;
  gap: 12px;
  align-items: flex-start;
  padding: 16px 16px;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  background: var(--surface);
}

.deliv-item svg {
  flex: none;
  margin-top: 3px;
  color: var(--tone-ink, var(--accent-ink));
}

.deliv-item strong {
  display: block;
  color: var(--brand);
  font-size: 1rem;
  font-weight: 600;
}

.deliv-item span {
  display: block;
  margin-top: 3px;
  color: var(--muted);
  font-size: 0.875rem;
  line-height: 1.6;
}

/* 边界说明 */
.limits {
  padding: 32px 32px;
  border: 1px solid var(--line);
  border-left: 4px solid var(--accent);
  border-radius: var(--radius);
  background: var(--surface);
}

.limits h3 {
  font-size: 1.1875rem;
  color: var(--accent-ink);
}

.limits ul {
  margin-top: 16px;
}

.limits li {
  position: relative;
  padding-left: 20px;
  color: var(--text-2);
  font-size: 1rem;
  line-height: 1.8;
}

.limits li + li {
  margin-top: 12px;
}

.limits li::before {
  content: "";
  position: absolute;
  left: 0;
  top: 12px;
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--accent);
}

.limits strong {
  color: var(--brand);
}

/* ---------- 19g. 语言切换 ---------- */
.lang {
  position: relative;
}

.lang-btn {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  height: 34px;
  padding: 0 8px;
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-sm);
  background: var(--surface);
  color: var(--brand);
  font-size: 0.875rem;
  font-weight: 600;
  letter-spacing: 0.04em;
  transition: border-color 0.3s var(--ease), background-color 0.24s var(--ease);
}

.lang-btn:hover {
  border-color: var(--brand);
}

.lang-btn svg {
  flex: none;
  color: var(--muted);
}

.lang-btn .lang-caret {
  transition: transform 0.5s var(--ease);
}

.lang.is-open .lang-btn .lang-caret {
  transform: rotate(180deg);
}

.lang-menu {
  position: absolute;
  top: calc(100% + 8px);
  right: 0;
  min-width: 152px;
  padding: 6px;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  background: var(--surface);
  box-shadow: var(--shadow-md);
  opacity: 0;
  visibility: hidden;
  transform: translateY(-6px);
  transition: opacity 0.32s var(--ease), transform 0.5s var(--ease),
    visibility 0.22s var(--ease);
  z-index: 120;
}

.lang.is-open .lang-menu {
  opacity: 1;
  visibility: visible;
  transform: none;
}

.lang-menu button {
  display: block;
  width: 100%;
  padding: 8px 12px;
  border: 0;
  border-radius: 6px;
  background: none;
  color: var(--text-2);
  font-size: 0.875rem;
  text-align: left;
  transition: background-color 0.24s var(--ease), color 0.24s var(--ease);
}

.lang-menu button:hover {
  background: var(--bg-alt);
  color: var(--brand);
}

.lang-menu button.is-active {
  background: var(--accent-soft);
  color: var(--brand);
  font-weight: 600;
}

/* 切换语言时先隐藏，避免中文闪现 */
html[data-i18n-pending] body {
  visibility: hidden;
}.stat-num, .case-metrics .cm-v, .metric .mv, .metric-cards__v, .cm-v, .cal-no, .dl-num, .step-no, .tl-year, .ind-band-num, .stat-v, .why-no, .case-hero-meta dd{
  font-variant-numeric: tabular-nums;
  font-feature-settings: "tnum" 1;
}

/* 卡片悬停：已收敛为「边框变深 + 图片轻放」两件事。
   --------------------------------------------------------------------------
   原来这里还有一道 2px 的顶部细线自左扫入（.card::after，蓝色渐变）。
   加它的理由是「像仪器面板，比整体变色克制」——但那是把效果当成风格了。

   实际数下来，一张卡片上原本同时挂着四个悬停反馈：
     ① 顶部细线扫入  ② 跟随指针的光晕  ③ 卡片上浮 5px + 阴影变深
     ④ 图片放大 1.055 倍 + 标题着色
   四个一起动，反馈就过剩了：读者分不清哪一下才是「可以点」的信号，
   而且阴影浮起 + 光晕 + 扫线这套组合正是模板站的标准配置。

   现在只留两件：
     · 边框从 --line 变到 --line-strong（最轻的「我收到了」）
     · 图片放大 1.02 倍（几乎察觉不到，但让卡片活一点）
   Apple 首页 CSS 里 box-shadow 出现 0 次，卡片类组件靠边框和留白分层。 */
.card {
  position: relative;
  overflow: hidden;
}

/* 页脚链接：下划线自右收、自左展 */
.footer-col a {
  position: relative;
  display: inline-block;
}

.footer-col a::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: -1px;
  height: 1px;
  background: currentColor;
  transform: scaleX(0);
  transform-origin: right center;
  transition: transform 0.5s var(--ease-out);
}

.footer-col a:hover::after {
  transform: scaleX(1);
  transform-origin: left center;
}

/* ---------- 22. 数字带 ----------
   参考 Apple / nanfu 的做法：数字不套卡片，直接排版。
   卡片会削弱数字的分量——去掉框，数字本身才是视觉。 */
.band{padding:var(--section-y-tight) 0}

.band-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 44px 36px;
}

.band-num {
  display: block;
  font-size: clamp(2.4rem, 4.6vw, 3.35rem);
  font-weight: 700;
  line-height: 1;
  letter-spacing: -0.04em;
  color: var(--brand);
  font-variant-numeric: tabular-nums;
}

.band-num .unit {
  margin-left: 3px;
  font-size: 0.42em;
  font-weight: 600;
  letter-spacing: 0;
  color: var(--accent-ink);
}

.band-label {
  display: block;
  margin-top: 16px;
  color: var(--muted);
  font-size: 0.875rem;
  line-height: 1.6;
}

.band-note {
  position: relative;
  margin-top: 32px;
  padding-top: 20px;
  color: var(--muted);
  font-size: 0.875rem;
  line-height: 1.7;
}

/* 细线随滚动到来自左展开——比直接出现多一拍节奏。
   默认是展开状态，只有 JS 可用时才收起来等待入场（渐进增强：无 JS 时线仍在）。 */
.band-note::before {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 1px;
  background: var(--line);
  transform-origin: left center;
  transition: transform 1.3s var(--ease-out);
}

.js .band-note::before { transform: scaleX(0); }
.js .band-note.is-visible::before { transform: scaleX(1); }

/* ---------- 23. 双栏标题 ----------
   打破「eyebrow + h2 + lead」三段式：标题占左，说明在右，同一行起步。 */
.split-head {
  display: grid;
  grid-template-columns: minmax(0, 5fr) minmax(0, 7fr);   /* 5:7 = 12 列里的 5+7 */
  gap: 28px 72px;
  align-items: start;
  margin-bottom: 60px;
}

.split-head__body {
  color: var(--text-2);
  font-size: 1.1875rem;
  line-height: 1.8;
}

.split-head__body p + p { margin-top: 16px; }

.split-head__body strong { color: var(--brand); font-weight: 600; }

/* ---------- 24. 一行式标题 ----------
   标题占左、说明占右，同一行起步，底部一道细线收口。
   用于次要区块——把完整的「eyebrow + h2 + lead」三段式留给真正重要的内容。 */
.line-head {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 16px 56px;
  flex-wrap: wrap;
  margin-bottom: 40px;
  padding-bottom: 24px;
  border-bottom: 1px solid var(--line);
}

.line-head > div > .h2,
.line-head > .h2 { margin-bottom: 0; }

.line-head > div > .eyebrow { margin-bottom: 8px; }

.line-head__meta {
  color: var(--muted);
  font-size: 1rem;
  line-height: 1.7;
  max-width: 480px;
}

/* ---------- 25. 横向流程 ----------
   大序号当排版元素（浅色，不抢内容），顶部一道细线串起四步。 */
.flow {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 0 40px;
  border-top: 1px solid var(--line);
}

.flow-step {
  position: relative;
  padding-top: 32px;
}

.flow-step::before {
  content: "";
  position: absolute;
  top: -1px;
  left: 0;
  width: 40px;
  height: 2px;
  background: var(--accent);
}

.flow-no {
  display: block;
  font-size: clamp(2.6rem, 4vw, 3.2rem);
  font-weight: 700;
  line-height: 0.9;
  letter-spacing: -0.04em;
  color: #74829b;   /* 白底 3.2:1，大字达标 */
  font-variant-numeric: tabular-nums;
}

.flow-step h3 {
  margin-top: 20px;
  font-size: 1.1875rem;
}

.flow-step p {
  margin-top: 8px;
  color: var(--text-2);
  font-size: 1rem;
  line-height: 1.8;
}

@media (max-width: 900px) {
  .band-grid { grid-template-columns: repeat(2, 1fr); gap: 36px 28px; }
  .split-head { grid-template-columns: 1fr; gap: 24px; margin-bottom: 44px; }
  .flow { grid-template-columns: repeat(2, 1fr); gap: 40px 32px; }
}

@media (max-width: 560px) {
  .band { padding-bottom: var(--section-y-tight); }
  .band-grid { grid-template-columns: 1fr; gap: 32px; }
  .flow { grid-template-columns: 1fr; gap: 32px; }
}

/* ---------- 27. 卡片光晕：已移除 ----------
   原来鼠标在卡片上移动时，会有一层极淡的蓝色径向光跟着走
   （260px 圆，透明度 0.09，用 --mx / --my 跟随）。当时的说明是
   「能被感觉到，但说不清哪里在动，这是大厂详情页的常见手感」。

   实测下来这条判断是错的：**大厂不做这个**。
   Apple 首页 CSS 里 box-shadow 出现 0 次，也没有任何跟随指针的光晕；
   腾讯云同样没有。跟随指针的高光是 2023 年前后一批「Awwwards 风格」
   模板的产物，现在它是识别生成式页面的一条可靠线索。

   而且它和这张卡片上已有的悬停反馈（顶部细线扫入 + 图片放大 + 标题着色）
   叠在一起，四个效果同时动 —— 反馈过剩反而让「可点击」这件事不明确了。

   现在卡片悬停只保留两件事：边框变深、图片轻微放大。CSS 与 JS 一并删除
   （main.js 的 initCardGlow 也已移除）。 */

/* ---------- 35. 首屏背景图 ----------
   用生成的真实视觉替代纯 CSS 图形 —— 大厂的「质感」主要来自图片，不是渐变。 */
/* .hero-photo 已删除：照片改成 §6 里的全宽 <figure> 真图片 */

/* ---------- 36. 网格防撑破 ----------
   grid item 默认 min-width:auto，不会小于内容固有宽度 —— 图片会把网格撑破。 */
.grid > * { min-width: 0; }

/* ---------- 37. 图文卡 ----------
   卡片上半是图、下半是字，hover 时图片缓慢放大 —— 比图标卡有分量得多。 */
.card--media {
  padding: 0;
  overflow: hidden;
}

.card-media {
  position: relative;
  aspect-ratio: 16 / 10;
  overflow: hidden;
  background: var(--bg-alt);
}

.card-media img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform 0.9s var(--ease-out);
}

.card:has(.card-link):hover .card-media img { transform: scale(1.055); }

.card-body { padding: 24px 28px 32px; }

@media (max-width: 720px) {
  .card-media { aspect-ratio: 16 / 9; }
  .card-body { padding: 24px 24px 24px; }
}

/* ---------- 38. 宽幅图片区块 ----------
   Apple / 腾讯云常用的整幅视觉，用来打断纯文字节奏。 */
.wide-media {
  margin: 0 0 52px;
  border-radius: var(--radius);
  overflow: hidden;
  background: var(--bg-alt);
  aspect-ratio: 21 / 9;
}

.wide-media img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

@media (max-width: 720px) {
  .wide-media { aspect-ratio: 16 / 9; margin-bottom: 36px; }
}

/* ---------- 39. 图片视差 ----------
   滚动时图片以略慢于容器的速度移动，产生纵深。幅度刻意做小（±18px），
   大了会晕，小了才「有空气感」。 */
.parallax-media {
  position: relative;
  overflow: hidden;
}

.parallax-media img {
  will-change: transform;
  transform: scale(1.12);   /* 预留位移余量，避免边缘露白 */
}

/* ★ 案例图容器自带 0.9s 的 transform 过渡（给悬停缩放用），
   而视差是**每帧**写 transform —— 两者叠加会互相打架：
   每一帧都重新起一次 0.9s 过渡，看起来是橡皮筋一样的拖尾，而且永远追不上滚动。
   做视差时必须把过渡关掉（位移本身由 JS 每帧驱动，不需要过渡）。 */
.case-media.parallax-media img {
  transition: none;
}

/* ---------- 40. （已移除）卡片入场增强 ----------
   这里原来是 .reveal-scale：在位移之外再叠一点缩放（translateY(22px) scale(0.985)，
   1.05s）。HTML 与 JS 里已经**一处都不再引用**，是纯死代码 ——
   留着最坏的地方不是多几行，而是它写着**上一版的入场参数**（22px / 1.05s），
   和 §21 现在真正生效的 14px / 0.52s 冲突。后人看到会不知道该信哪个。
   删掉，入场参数只保留 §21 一处。 */

/* ---------- 41. 深色区块 ----------
   整站需要 2-3 处「重音」。纯白 + 浅灰交替太久会显得平，深色区块用来打断。 */
.section--dark {
  background: var(--bg-deep);
  color: rgba(255, 255, 255, 0.70);
}

.section--dark .h2,
.section--dark h2,
.section--dark h3 { color: #ffffff; }

.section--dark .eyebrow { color: var(--accent-lite); }

.section--dark .lead,
.section--dark p { color: rgba(255, 255, 255, 0.70); }

.section--dark .stat-card {
  background: rgba(255, 255, 255, 0.07);
  border-color: rgba(255, 255, 255, 0.12);
}

.section--dark .stat-v { color: #ffffff; }
.section--dark .stat-l { color: rgba(255, 255, 255, 0.70); }
.section--dark .stat-b { color: rgba(255, 255, 255, 0.56); }

.section--dark .link-arrow { color: var(--accent-lite); }
.section--dark .link-arrow:hover { color: #ffffff; }

/* ---------- 42. 案例配图 ----------
   跨两栏的顶部大图，让案例卡有「项目实拍」的分量。 */
.case-media {
  grid-column: 1 / -1;
  aspect-ratio: 21 / 9;
  overflow: hidden;
  background: var(--bg-alt);
}

.case-media img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform 0.9s var(--ease-out);
}

/* ---------- 案例筛选栏 ----------
   参考实现用的是「行业 × 服务」两个正交维度；本站案例卡只有行业一个维度，
   所以只做行业筛选 —— 不为了对称而造一个用不上的维度。 */
.case-filter {
  /* ★ 2026-10-17 · 重做（用户反馈「筛选器的位置怪怪的」）
     改前的三个问题（实测）：
     ① `top:72px` 让它吸在**页头正下方** —— 两个半透明毛玻璃条上下叠着
        （页头 blur(18) + 筛选条 blur(18)），滚动态有两层重影，
        而且筛选条压在页面照片上，透出底下的图，读起来浮。
     ② `justify-content:space-between` 把「8 个案例」这个状态文字
        甩到最右侧，和 9 个按钮挤在同一行 —— 一行里既有控件又有数据，
        没有主次。
     ③ 半透明白底 + blur 是「浮层」的做法，但筛选条不是浮层，
        它属于案例区的一部分，应该有自己的实体边界。

     改法（对齐 Apple 的做法）：
       · **不再吸顶**。页头已经是吸顶的，再叠一条吸顶筛选条是重复的
         导航层；Apple 的筛选用普通行内工具条，跟着内容滚。
       * **改为实体白底 + 上下细线**，与全站的 .localnav / section-head
         用同一套「一条线 + 白底」的语言，不再是浮在内容上的毛玻璃。
       * **状态文字移到按钮行下方**，与按钮分组，不再抢同一行。
       * 上下留白收紧，让它成为一个「工具条」而不是「一个区块」。 */
  position: relative;
  top: auto;
  z-index: 5;
  background: var(--surface);
  border-top: 1px solid var(--line);
  border-bottom: 1px solid var(--line);
  padding: 16px 0;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 12px;
  /* 窄屏：9 个按钮折成 3 行、加上状态文字，工具条会到 218px 高，
     比它要筛选的内容还占地方。收紧上下留白与行距，
     并把状态文字改为与按钮同一视觉重量的小字。 */
  @media (max-width: 720px) {
    padding: 12px 0;
    gap: 8px;
    margin-bottom: 24px;
  }
  margin: 4px 0 32px;         /* 原 20px，与上下文的呼吸重新分配 */
}

.case-filter__btns {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}

.case-filter__btn {
  padding: 8px 16px;
  border: 1px solid var(--line-strong);
  border-radius: 999px;
  background: var(--surface);
  color: var(--text-2);
  font-size: 0.875rem;
  line-height: 1.4;
  cursor: pointer;
  transition: color 0.2s var(--ease), border-color 0.2s var(--ease), background-color 0.2s var(--ease);
}

.case-filter__btn:hover { color: var(--text); border-color: var(--brand); }

/* 按下态靠 aria-pressed 表达，不另加 class —— 状态只有一个来源 */
.case-filter__btn[aria-pressed="true"] {
  background: var(--brand);
  border-color: var(--brand);
  color: #fff;
}

.case-filter__status {
  margin: 0;
  color: var(--muted);
  font-size: 0.875rem;
  font-variant-numeric: tabular-nums;
}

.case-filter__empty {
  margin: 0 0 32px;
  padding: 24px 24px;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  background: var(--surface);
  color: var(--text-2);
  font-size: 0.9375rem;
  line-height: 1.7;
}

/* 筛掉时用 hidden 收起。给一个显式兜底，避免某些 display 值把 hidden 顶掉。 */
.case-card[hidden],
section[hidden] { display: none !important; }

/* ---------- 34. 页头配色 ----------
   默认浅色（内页 hero 是浅色的）；只有首页首屏是深色，所以只有首页用深色页头。 */
.site-header .brand-name { color: var(--text); }
.site-header .brand-sub { color: var(--muted); }
.site-header .nav-link { color: var(--text-2); }
.site-header .nav-link:hover,
.site-header .nav-link.is-active { color: var(--brand); }
.site-header .lang-btn { color: var(--text-2); background: var(--surface); border-color: var(--line-strong); }
.site-header .lang-btn:hover { color: var(--text); background: var(--bg-alt); }
/* ★ 页头这颗按钮回到深色（--brand），不跟主按钮的蓝。
   我一开始把它也统一成蓝色，理由是「一个强调色要只代表一件事」。
   截图之后发现这是过度统一：页头按钮和首屏按钮**同时变成蓝色实心**，
   一屏里出现两个同等重量的主行动，读者得停下来判断哪个更重要。

   它们本来就不是同一类东西：
     · 页头那颗是**常驻的工具入口**（每个页面都在），不指向本页的任何内容
     · 首屏那颗是**本页的行动号召**，它才是这一屏的主角
   所以层级应该由颜色分开：常驻元素用品牌深靛（identity），
   页内行动用强调蓝（action）。深靛不是第二个「强调色」，
   它是品牌色本身，不参与「什么最重要」的表达。 */
.site-header .btn--primary { background: var(--brand); color: #ffffff; }
.site-header .btn--primary:hover { background: var(--brand-600); }

/* 首页：首屏已改为浅色，页头不再需要「深色反白」那一套，
   未滚动时透明浮在浅色首屏上，文字直接用深色。 */
.page-home .site-header:not(.is-scrolled) {
  background: transparent;
  backdrop-filter: none;
  border-bottom-color: transparent;
}

/* 滚动之后一律转白 */
.site-header.is-scrolled { background: rgba(255, 255, 255, 0.86); }

/* 滚动之后：页头转白，文字回深色 */
.site-header.is-scrolled .brand-name { color: var(--text); }
.site-header.is-scrolled .brand-sub { color: var(--muted); }
.site-header.is-scrolled .nav-link { color: var(--text-2); }
.site-header.is-scrolled .nav-link:hover,
.site-header.is-scrolled .nav-link.is-active { color: var(--brand); }
.site-header.is-scrolled .lang-btn { color: var(--text-2); background: var(--surface); border-color: var(--line-strong); }
.site-header.is-scrolled .lang-btn:hover { color: var(--text); background: var(--bg-alt); }
.site-header.is-scrolled .btn--primary { background: var(--brand); color: #ffffff; }
.site-header.is-scrolled .btn--primary:hover { background: var(--brand-600); }

/* ---------- 33. 浅色首屏上的文字与按钮 ---------- */
/* 小标用灰字，不用强调蓝 —— 对照版就是灰的。
   首屏只有「主行动按钮」用强调色，小标跟着抢色会削弱那个唯一的重心。 */
/* 首屏 eyebrow 现在是「品牌 lockup」（幻方造梦 / FIELD TO SYSTEM），不是服务清单。
   原来这里把它压成 --muted，理由是「清单不该抢标题」。换成 lockup 之后这个理由不成立了 ——
   它就是一个品牌标签，应该和全站其它 eyebrow 一样用强调色，给首屏一个颜色落点。
   只加一点字距：中英混排时 0.06em 让两段之间不至于挤在一起。 */
.hero .eyebrow { letter-spacing: 0.06em; }

.hero h1 { color: var(--text); }

/* 第二行与第一行同色（原来这里是第二处渐变文字覆盖，见 §3 处的说明） */

/* ★ 这条写在 §3 之后，特异性与前面那条 .hero .lead 相同 ⇒ **它才是生效的那条**。
   首屏改成照片背景后，正文灰在照片最暗处实测只有 3.07:1，改用正文色。 */
.hero .lead { color: var(--text); }

.hero-meta { color: var(--muted); }   /* 白底 5.07:1 */

/* 首屏主按钮不再单独覆盖配色。
   原来它比别处更深一档，还带一层**蓝色发光投影**
   （0 16px 32px -16px rgba(0,96,206,0.6)）—— 按钮底下透出一圈蓝光，
   是模板站很典型的做法。去掉之后按钮回到统一的主按钮样式。 */

.hero .btn--primary:focus-visible,

/* ---------- 30. 首屏合作方式行 ---------- */
.hero-meta {
  margin-top: 24px;
  font-size: 0.875rem;
  line-height: 1.7;
}

/* ---------- 32. 为什么选我们 ----------
   ★ 2026-10-16（Apple 对齐）：从「盒子」改成「开放版式」。

   改前：padding + 1px 边框 + 圆角 + 自上而下的浅渐变底 —— 四张**带边框的小盒子**
   等宽并排。这是组件库的默认形态，也是整站最明显的「模板感」来源：
     · 边框把 4 段本该连贯的文字切成 4 个孤岛，读者被迫逐个进入再退出；
     · 圆角 + 渐变底是「卡片」的signature，出现一次就贴上"Bootstrap 味"的标签；
     · 1440 下每张卡仅 253px 宽，中文一行只放 ~17 字，四张卡的高度参差却要拉平
       （height:100%），于是窄卡里出现大段空白。

   Apple 的做法：**不画盒子，用一条细规则线 + 大留白来分隔**。
   本站「每一步都有交付物」的 .step 已经是这个做法（border-top + padding），
   视觉上明显更高级 —— 这里改成与它同一套语言，全站两处不再各说各话。
   注意：rule 线用 --line（浅灰），而**不是** grid 子元素上那条 3px 的 --tone 色条
   （见 §337）—— 那条 3px 彩条是「分类感」，与这里的结构线语义不同，
   两者叠加会变成「一道灰线 + 一道蓝线」的脏边，所以这里显式给 .why-card
   一个 border-top 覆盖，让顶部只留一条线。 */
.why-card {
  padding: 28px 0 0;
  border: 0;
  border-top: 1px solid var(--line);
  border-radius: 0;
  background: none;
  height: 100%;
}

/* 覆盖 §337 那条 3px 的 --tone 顶条（同特异性、后写生效）。
   .why-card 只在 index.html 出现，影响面可控。 */
:where(.grid--2, .grid--3, .grid--4) > .why-card {
  border-top: 1px solid var(--line);
}

.why-no {
  display: block;
  margin-bottom: 18px;
  color: var(--tone-ink, #74829b);   /* 白底 3.2:1，大字达标（原 --line-strong 只有 2.15） */
  font-size: 1.0625rem;              /* 从 1.5rem 收到 17px：序号是路标，不是主角 */
  font-weight: 700;
  letter-spacing: 0;
  font-variant-numeric: tabular-nums;
}

/* 标题与正文都放大一档：盒子去掉后，文字要自己撑起版面的重量。
   原来 1.1875rem 标题 + 0.875rem 正文是「卡片内的字号」，
   开放版式下 14px 正文在 1440 的宽栏里显得碎。 */
.why-card h3 {
  font-size: 1.3125rem;
  line-height: 1.45;
  letter-spacing: -0.01em;
}

.why-card p {
  margin-top: 10px;
  color: var(--text-2);
  font-size: 1rem;
  line-height: 1.75;
  text-wrap: pretty;
}

/* 开放版式靠留白分隔，栏间距要相应加大（盒子时代靠边框分隔，缝隙可以小） */
@media (min-width: 861px) {
  #why-us .grid--4 { gap: 40px 40px; }
}

/* ---------- 29. 行业方案 ----------
   B2B 官网的关键板块：客户是按「我的行业」找方案的，不是按「你有哪些服务」。
   卡片结构固定为 行业 → 典型问题 → 应对方式，扫一眼就能对上号。 */
.ind-q {
  margin-bottom: 16px;
  padding-left: 16px;
  border-left: 2px solid var(--accent);
  color: var(--text-2);
  font-size: 0.875rem;
  line-height: 1.7;
}

.ind-list {
  list-style: none;
  padding: 0;
  margin: 0;
  display: grid;
  gap: 8px;
}

.ind-list li {
  position: relative;
  padding-left: 16px;
  color: var(--muted);
  font-size: 0.875rem;
  line-height: 1.7;
}

.ind-list li::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0.62em;
  width: 6px;
  height: 1px;
  background: var(--tone, var(--line-strong));
}.card, .quote, .office, .btn{
  backface-visibility: hidden;
}

/* ---------- 20. 页脚 ---------- */
.site-footer {
  padding: 72px 0 0;
  background: var(--bg-deep);
  color: rgba(255, 255, 255, 0.70);
  font-size: 0.875rem;
}

.footer-top {
  display: grid;
  grid-template-columns: 2fr 1fr 1fr 1fr;                 /* 6:2:2:2 */
  gap: 48px;
  padding-bottom: 56px;
}

.footer-brand .brand-name {
  color: #fff;
}

.footer-brand .brand-sub {
  color: rgba(255, 255, 255, 0.56);
}

.footer-brand p {
  margin-top: 20px;
  max-width: 300px;
  line-height: 1.8;
}

.footer-col h3 {
  margin-bottom: 16px;
  color: #fff;
  font-size: 1rem;
  font-weight: 600;
}

.footer-col li + li {
  margin-top: 12px;
}

.footer-col a {
  transition: color 0.24s var(--ease);
}

.footer-col a:hover {
  color: #fff;
}

.footer-bottom {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 20px;
  padding: 24px 0;
  border-top: 1px solid rgba(255, 255, 255, 0.12);
  font-size: 0.875rem;
  color: rgba(255, 255, 255, 0.56);
}

.footer-bottom a:hover {
  color: #fff;
}

/* ---------- 21. 滚动入场动画 ----------
   注意：隐藏规则挂在 .js 之下。若脚本被禁用或加载失败，
   html 上不会出现 .js，内容直接可见 —— 避免整页空白。

   ★★ 入场只留给「结构性的开场」：首屏 / 页首 / 章节标题组。
     改前 HTML 里带 .reveal 的元素有 934 处 —— 卡片、列表项、面包屑、
     连主导航都挂着它。全都随滚动往上飘，结果是**满屏都在动**：读者分不清
     哪里是重点，页面反而更像套了个滚动动画库，也就是「模板味」的来源。
     对照实测（同一把尺子数两边的入场点）：对标的国外企业站整站只有 40 余处，
     且只落在**章节级**的块上；单张卡片、单个列表项一律不动。
   ⇒ 所以这里把「隐藏态」限定在白名单内。白名单外的 .reveal 永远可见 ——
     不必去改 934 处 HTML，也不会因为漏改而留下永远不出现的空白。
   ⇒ 用 :where() 把特异性压回 (0,2,0)，和原来的 .js .reveal 完全一致：
     下面「降低动效 / 打印 / motion-off」三处覆盖规则照旧靠「后写的赢」生效。
     ★ 改这里时别把 :where() 换成 :is() —— 特异性会涨到 (0,3,0)，
       那三处覆盖会集体失效，开启「减少动态效果」的用户将看到大片空白。 */
.js :where(.hero, .page-hero) .reveal,
.js :where(.section-head, .split-head, .line-head).reveal {
  opacity: 0;
  /* 位移 14px + 520ms + expo-out。
     原来是 50px / 0.5s —— 位移一大，「往上飘」的感觉就出来了，那是模板的观感。
     对标的几个站普遍在 12–16px：只做一个「轻微落位」，读者几乎意识不到，但层次还在。 */
  transform: translateY(14px);
  transition: opacity 0.52s var(--ease-out), transform 0.52s var(--ease-out);
  transition-delay: var(--d, 0ms);
}

.js :where(.hero, .page-hero) .reveal.is-visible,
.js :where(.section-head, .split-head, .line-head).reveal.is-visible {
  opacity: 1;
  transform: none;
}

/* 面包屑是「定位信息」，不是内容 —— 进门就该看得见，不参与入场排队。
   特异性 (0,3,0) 高于上面两条，所以写在前面也能赢。 */
.js .page-hero .breadcrumb.reveal {
  opacity: 1;
  transform: none;
  transition: none;
}

/* ---------- 22. 响应式 ---------- */
@media (max-width: 1024px) {
  :root {
    --section-y: 64px;--section-y-tight:40px;
  }

  .grid--4 { grid-template-columns: repeat(2, 1fr); }
  .stats { grid-template-columns: repeat(2, 1fr); }
  .steps { grid-template-columns: repeat(2, 1fr); gap: 32px 32px; }
  .footer-top { grid-template-columns: 1fr 1fr; gap: 40px; }
  .split { gap: 48px; }
  .split--wide-left { grid-template-columns: 1fr; }
  .cert-grid { grid-template-columns: repeat(2, 1fr); }
  .brands { grid-template-columns: 1fr; gap: 32px; padding: 32px 32px; }
  .steps--5 { grid-template-columns: repeat(3, 1fr); }
  .q-grid { grid-template-columns: repeat(2, 1fr); }
  .deliv-grid { grid-template-columns: repeat(2, 1fr); }
}

/* ---------- 导航宽度适配（2026-10-11 加第 8 项「常见问题」后补）----------
   实测：8 项横向导航要 1145px 以上才放得下，而汉堡菜单原来在 860px 才出现
   ⇒ 861–1144px 之间导航会挤到与品牌/右侧按钮重叠（860px 处实测重叠 134px）。
   两道处理：
     ≤1180px  收紧导航内边距与字号（省下约 150px）
     ≤1024px  提前切汉堡菜单
   这个区间在 1440px 的窗口里完全看不出来，只有按宽度逐个量才会暴露。 */
@media (max-width: 1180px) {
  /* 基础值已经是紧凑尺寸（见 §5），这里再收一档左右内边距 */
  .nav-link { padding: 8px 8px; }
}

@media (max-width: 1024px) {
  .nav-toggle { display: block; }

  .nav {
    position: fixed;
    top: 72px;
    left: 0;
    right: 0;
    flex-direction: column;
    align-items: stretch;
    gap: 2px;
    padding: 16px var(--gutter) 24px;
    background: rgba(255, 255, 255, 1);
    backdrop-filter: blur(18px);
    -webkit-backdrop-filter: blur(18px);
    border-bottom: 1px solid var(--line);
    box-shadow: 0 24px 40px -30px rgba(16, 24, 40, 0.5);
    transform: translateY(-12px);
    opacity: 0;
    visibility: hidden;
    transition: opacity 0.32s var(--ease), transform 0.5s var(--ease),
      visibility 0.28s var(--ease);
  }

  .nav.is-open {
    transform: none;
    opacity: 1;
    visibility: visible;
    /* ★ visibility 必须立即生效，覆盖基态的 0.28s 延迟。
       基态那条 `visibility 0.28s` 是给**收起**用的：让面板淡出的过程中仍然可见。
       但展开时不能延迟 —— 否则展开后的头 0.28s 里面板还是 visibility:hidden，
       此时对它内部的链接调 focus() 会**静默失败**（焦点留在 body 上），
       键盘用户点开菜单后按 Tab 得从头绕一圈才进得去。
       实测：点开瞬间 nav 计算样式是 hidden、焦点在 BODY；60ms 后才是 visible。 */
    transition: opacity 0.32s var(--ease), transform 0.5s var(--ease), visibility 0s;
  }

  .nav-link {
    padding: 12px 16px;
    font-size: 1rem;
  }

  .nav-link::after { display: none; }

  .nav-link.is-active {
    background: var(--bg-alt);
    border-radius: var(--radius-sm);
  }
}

@media (max-width: 860px) {
  /* 重复的 nav-toggle/.nav/.nav-link 在 1024px 块里已经写过一份,这里不再复制。
     ★ 教训(第 20 轮诊断发现):上一版这段是 1024 块整段复制过来,
       导致同权重后写盖前写、且 860 没有任何真正差异化收紧。
     只保留 860 专属的差异化收紧(更窄的字号、收更紧的内边距、更低的 hero)。 */

  .header-actions .btn { display: none; }

  .hero { padding: 136px 0 72px; }
  .page-hero { padding: 132px 0 56px; }

  .split { grid-template-columns: 1fr; gap: 40px; }
  .grid--3 { grid-template-columns: repeat(2, 1fr); }
  .grid--2 { grid-template-columns: 1fr; }
  .case-card { grid-template-columns: 1fr; }
  .case-side { border-right: 0; border-bottom: 1px solid var(--line); }
  .steps--5 { grid-template-columns: repeat(2, 1fr); }
  .feature { grid-template-columns: 1fr; }
  .feature-visual { border-left: 0; border-top: 1px solid var(--line); }
  .cta-inner { flex-direction: column; align-items: flex-start; }
  .form-card { padding: 32px 24px; }
  .section-head { margin-bottom: 40px; }
}

/* 窄屏下对比表改为纵向堆叠：避免关键列被挤出视口，需要横向拖动才能看到 */
@media (max-width: 680px) {
  .cmp-wrap {
    overflow-x: visible;
  }

  .cmp {
    min-width: 0;
    border: 0;
    border-radius: 0;
  }

  .cmp thead {
    display: none;
  }

  .cmp tbody,
  .cmp tbody tr,
  .cmp tbody th,
  .cmp tbody td {
    display: block;
    width: auto;
  }

  .cmp tbody tr {
    padding: 20px 0;
    border-bottom: 1px solid var(--line);
  }

  .cmp tbody tr:first-child {
    border-top: 1px solid var(--line);
  }

  .cmp tbody tr:last-child {
    border-bottom: 0;
  }

  .cmp tbody th {
    padding: 0 0 16px;
    background: none;
    color: var(--brand);
    font-size: 1rem;
    font-weight: 600;
    white-space: normal;
  }

  .cmp tbody td {
    padding: 0;
    border-bottom: 0;
    background: none;
  }

  .cmp tbody td + td {
    margin-top: 8px;
  }

  .cmp tbody td::before {
    content: attr(data-label) "：";
    display: block;
    margin-bottom: 2px;
    color: var(--muted);
    font-size: 0.875rem;
    font-weight: 400;
  }

  .cmp tbody td.is-accent {
    background: none;
  }

  .cmp tbody td.is-accent::before {
    color: var(--accent-ink);
  }
}

@media (max-width: 560px) {
  :root {
    --gutter: 20px;
    --section-y: 48px;--section-y-tight:32px;
  }

  .stats { grid-template-columns: 1fr; }
  .steps { grid-template-columns: 1fr; }
  .grid--4 { grid-template-columns: 1fr; }
  .grid--3 { grid-template-columns: 1fr; }
  .cert-grid { grid-template-columns: 1fr; }
  .brands { padding: 28px 24px; }
  .brand-grid { grid-template-columns: repeat(2, 1fr); }
  .steps--5 { grid-template-columns: 1fr; }
  .q-grid { grid-template-columns: 1fr; }
  .deliv-grid { grid-template-columns: 1fr; }
  .case-body { padding: 24px 20px; }
  .case-side { padding: 24px 20px; }
  .limits { padding: 24px 24px; }
  .form-row { grid-template-columns: 1fr; gap: 0; }
  .footer-top { grid-template-columns: 1fr; gap: 32px; }
  .footer-bottom { flex-direction: column; align-items: flex-start; gap: 8px; }
  .hero-cta .btn { width: 100%; }
  .cta-actions { width: 100%; }
  .cta-actions .btn { flex: 1; }
  .logo-row { gap: 16px 32px; }
  .logo-item { font-size: 1rem; }
}

/* ---------- 23. 动效降级 ---------- */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }

  *,
  *::before,
  *::after {
    animation-duration: 0.001ms !important;
    animation-delay: 0s !important;      /* 少了这条，错峰动画会白等一秒多 */
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
    transition-delay: 0s !important;
  }

  .js .reveal {
    opacity: 1;
    transform: none;
  }
}

/* ---------- 24. 打印 ---------- */
@media print {
  .site-header,
  .nav-toggle,
  .cta,
  .site-footer { display: none; }

  .reveal,
  .js .reveal {
    opacity: 1;
    transform: none;
  }
}

/* ==========================================================================
   补充：页脚服务承诺条 · 表单错误提示 · 首屏补充说明
   说明：配色沿用既有变量与 .form-success 的配色口径，不引入新色值体系。
   ========================================================================== */

/* ---------- 页脚服务承诺条 ---------- */
.footer-promise {
  display: flex;
  flex-wrap: wrap;
  gap: 8px 28px;
  padding: 16px 0 24px;
  border-bottom: 1px solid rgba(255, 255, 255, 0.12);
  margin-bottom: 32px;
}

.footer-promise__item {
  position: relative;
  padding-left: 20px;
  color: rgba(255, 255, 255, 0.86);
  font-size: 0.875rem;
  line-height: 1.5;
}

.footer-promise__item::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0.42em;
  width: 10px;
  height: 6px;
  border-left: 1.8px solid var(--accent);
  border-bottom: 1.8px solid var(--accent);
  transform: rotate(-45deg);
}

/* ---------- 表单提交失败提示 ---------- */
.form-error {
  display: none;
  align-items: flex-start;
  gap: 16px;
  margin-bottom: 24px;
  padding: 16px 20px;
  border: 1px solid #f0c4c4;
  border-radius: var(--radius-sm);
  background: #fdf3f3;
}

.form-error.is-shown {
  display: flex;
}

.form-error svg {
  flex: none;
  margin-top: 2px;
  color: #b3261e;
}

.form-error span {
  color: #8c2b25;
  font-size: 0.875rem;
  line-height: 1.6;
}

/* ---------- 首屏 CTA 补充说明 ---------- */
.hero-cta-note {
  margin-top: 16px;
  color: var(--muted);
  font-size: 0.875rem;
}

.hero-cta-note a {
  color: var(--accent-ink);
  text-decoration: underline;
  text-underline-offset: 3px;
}

.hero-cta-note a:hover {
  color: var(--brand);
}

@media (max-width: 734px) {
  .footer-promise {
    gap: 8px 16px;
    padding: 16px 0 20px;
    margin-bottom: 24px;
  }

  .footer-promise__item {
    font-size: 0.875rem;
  }

  .hero-cta-note {
    margin-top: 16px;
    font-size: 0.875rem;
  }
}

/* ---------- 表单中性提示（降级为邮件草稿时使用） ---------- */
.form-notice {
  display: none;
  align-items: flex-start;
  gap: 16px;
  margin-bottom: 24px;
  padding: 16px 20px;
  border: 1px solid #d9c9a8;
  border-radius: var(--radius-sm);
  background: #fdf9f1;
}

.form-notice.is-shown {
  display: flex;
}

.form-notice svg {
  flex: none;
  margin-top: 2px;
  color: #8a6a2f;
}

.form-notice span {
  color: #6b5320;
  font-size: 0.875rem;
  line-height: 1.6;
}

/* ---------- 首页效果数据卡（对标：案例效果而非公司规模） ---------- */
.stat-card {
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding: 24px 24px;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--surface);
}

.stat-v {
  font-size: 2.25rem;
  font-weight: 650;
  line-height: 1.1;
  letter-spacing: -0.02em;
  color: var(--brand);
}

.stat-l {
  font-size: 0.875rem;
  font-weight: 600;
  color: var(--text);
}

.stat-b {
  font-size: 0.875rem;
  color: var(--muted);
}

@media (max-width: 734px) {
  .stat-card { padding: 20px 16px; }
  .stat-v { font-size: 1.75rem; }
}

/* ---------- 43. 交付方法示意图 ----------
   原来这里放的是 AI 生成的「概念图」，跟文案对不上（alt 写着三阶段交付方法，
   图里却是一团光效）。改成真正的示意图：三阶段 + 每阶段的产出，用业务线配色区分。 */
.method {
  display: grid;
  grid-template-columns: 1fr auto 1fr auto 1fr;
  align-items: start;
  margin-bottom: 52px;
  padding: 36px 32px;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--surface);
}

.method-step { min-width: 0; }

.method-en {
  display: block;
  margin-bottom: 8px;
  color: var(--tone-ink, var(--accent-ink));
  font-size: 0.75rem;
  font-weight: 700;
  /* 与 .eyebrow 统一到 0.06em（原来是 0.16em，全站最后一处宽字距） */
  letter-spacing: 0.06em;
}

.method-step h3 {
  font-size: 1.1875rem;
}

/* 标题前的小方块已移除：这一块已经有 .method-en 的英文阶段名（AUDIT 等）
   充当锚点，再挂一个方块是同一件事说两遍。 */

.method-step p {
  margin-top: 8px;
  color: var(--text-2);
  font-size: 0.875rem;
  line-height: 1.7;
}

.method-out {
  margin-top: 12px;
  padding-top: 12px;
  border-top: 1px dashed var(--line);
  color: var(--tone-ink, var(--accent-ink));
  font-size: 0.875rem;
  font-weight: 600;
}

.method-arrow {
  display: flex;
  align-items: center;
  align-self: center;
  padding: 0 16px;
  color: var(--line-strong);
}

@media (max-width: 860px) {
  .method {
    grid-template-columns: 1fr;
    gap: 24px;
    padding: 28px 24px;
  }
  .method-arrow { display: none; }
}

/* ---------- 44. 拉伸链接（让整张卡可点，但不动 DOM 结构） ----------
   卡片网格的选择器是 :where(.grid--3) > .card 这类「栅格子元素」写法，
   如果把整张卡塞进 <a>，栅格子元素就变成了 <a>，这些规则会全部失效。
   所以改成：标题里放 <a>，再用 ::after 铺满整张卡。
   只有带 .card-link 的卡才有 hover 位移 —— 没链接的卡不给任何反馈，
   否则用户会以为能点（这正是「点了没反应」的根因）。 */
.card:has(.card-link),
.product-card:has(.card-link) { cursor: pointer; }

.card-link {
  color: inherit;
  text-decoration: none;
}

.card-link::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
}

.card-link:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 4px;
  border-radius: 4px;
}

/* 卡片右上角的箭头：只在有链接时出现，进一步说明「这张能点」。
   ⚠️ 必须挂在 .card-link 的伪元素上 —— .card 的 ::before 已被「跟随鼠标的光晕」
   占用、::after 已被「顶部渐变线」占用，再用就打架。 */
.card-link::before,
.product-card .card-link::before {
  content: "";
  position: absolute;
  top: 20px;
  right: 20px;
  width: 8px;
  height: 8px;
  border-top: 1.6px solid var(--line-strong);
  border-right: 1.6px solid var(--line-strong);
  transform: rotate(45deg);
  transition: transform 0.4s var(--ease-out), border-color 0.3s var(--ease);
  pointer-events: none;
}

.card:has(.card-link):hover .card-link::before,
.product-card:has(.card-link):hover .card-link::before {
  border-color: var(--tone-ink, var(--accent-ink));
  transform: translate(3px, -3px) rotate(45deg);
}

/* 带图的卡：图在上面，箭头要压在图的上方（浅色描边才看得见） */
.card--media .card-link::before {
  top: 18px;
  right: 18px;
  border-color: rgba(255, 255, 255, 0.86);
  filter: drop-shadow(0 1px 2px rgba(16, 24, 40, 0.5));
}

.card--media:has(.card-link):hover .card-link::before {
  border-color: #ffffff;
}

/* 「适合什么阶段」：给每个行业一个明确的适用边界，而不是一律说「我们都行」 */
.ind-fit {
  margin-top: 32px;
  padding: 16px 24px;
  border-left: 3px solid var(--tone, var(--accent));
  border-radius: 0 12px 12px 0;
  background: var(--tone-soft, var(--accent-soft));
  color: var(--text-2);
  font-size: 0.875rem;
  line-height: 1.7;
}

.ind-fit strong { color: var(--tone-ink, var(--accent-ink)); }

/* ---------- 46. 案例详情页 ---------- */
/* 首屏的四项基本信息：行业 / 规模 / 周期 / 团队 */
.case-hero-meta {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 20px;
  margin-top: 40px;
  padding-top: 28px;
  border-top: 1px solid var(--line);
}

.case-hero-meta dt {
  color: var(--text-2);
  font-size: 0.75rem;
  letter-spacing: 0.06em;
}

.case-hero-meta dd {
  margin-top: 7px;
  color: var(--brand);
  font-size: 1rem;
  font-weight: 600;
}

/* 首屏下方的指标条：数字要比卡片里的更大，因为它就是这个页面的结论 */
.case-metrics--hero {
  margin-top: 24px;
  padding-top: 0;
  border-top: 0;
  gap: 24px;
}

.case-metrics--hero .cm-v {
  font-size: clamp(2rem, 4vw, 2.75rem);
  letter-spacing: -0.03em;
}

.case-metrics--hero .cm-l {
  margin-top: 8px;
  font-size: 0.875rem;
  line-height: 1.6;
}

/* 深色区块里的指标：默认 .cm-v 是 --brand（深色），在深底上会看不见 */
.section--dark .case-metrics .cm-v { color: #ffffff; }
.section--dark .case-metrics .cm-l { color: rgba(255, 255, 255, 0.70); }

/* 数字口径说明：避免「这些数怎么来的」被反复追问 */
.case-note {
  /* 780px 配 13px 小字 = 每行 60 个汉字 —— 比正文还宽。
     小字更需要短行：字越小，读者越难在换行时定位。
     580px → 45 字/行。 */
  max-width: 580px;
  margin-top: 32px;
  padding-top: 24px;
  border-top: 1px solid rgba(255, 255, 255, 0.12);
  color: rgba(255, 255, 255, 0.56);
  font-size: 0.875rem;
  line-height: 1.7;
}

/* The technical-foundation note sits on the light alternate surface, so it
   must not inherit the white-on-dark treatment used by dark evidence bands. */
.section--alt .case-note {
  border-top-color: var(--line);
  color: var(--text-2);
}

@media (max-width: 720px) {
  .case-hero-meta { grid-template-columns: repeat(2, 1fr); gap: 16px; }
  /* ★ 普通 .case-metrics（案例索引页的卡片里，共 8 处）原先漏了这一条：
     它一直保持 repeat(4, 1fr)，390px 下每列只剩 66px ——「首答时长下降」被拆成
     「首答时长下 / 降」，金额「¥18.5 → ¥7.2」也断成两行。
     基础类和 --hero 变体一起收成两列。 */
  .case-metrics,
  .case-metrics--hero { grid-template-columns: repeat(2, 1fr); }
}

/* 案例索引页：标题与「查看完整案例」都指向详情页 */
.case-body h3 a {
  color: inherit;
  text-decoration: none;
  transition: color 0.24s var(--ease);
}

.case-body h3 a:hover { color: var(--accent-ink); }

.case-more { margin-top: 24px; }

/* ---------- 47. 数字形象导览员 ----------
   形象取自公司标识的九宫格：四角虚位保留结构、十字做实、中排两格变成眼睛。
   动效全部用 CSS + 少量 JS，无 3D、无外部依赖 —— 首屏不加载任何额外资源。 */
.dh-widget {
  position: fixed;
  right: 26px;
  bottom: 26px;
  z-index: 260;
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 16px;
}

/* ---- 入口：形象本体就是按钮 ---- */
.dh-entry {
  position: relative;
  width: 84px;
  height: 92px;
  padding: 0;
  border: 0;
  background: none;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}

.dh-entry svg { display: block; width: 100%; height: 100%; overflow: visible; }

.dh__body {
  transform-box: fill-box;
  transform-origin: center;
  animation: dh-breathe 3.4s var(--ease) infinite;
}

@keyframes dh-breathe {
  0%, 100% { transform: translateY(0); }
  50%      { transform: translateY(-4px); }
}

.dh__eye {
  transform-box: fill-box;
  transform-origin: center;
}

.dh.is-blink .dh__eye { animation: dh-blink 0.16s ease-in-out; }

@keyframes dh-blink {
  0%, 100% { transform: scaleY(1); }
  50%      { transform: scaleY(0.1); }
}

.dh__eyes { transition: transform 0.28s var(--ease-out); }
.dh__glow { opacity: 0.3; transition: opacity 0.4s var(--ease-soft); }
.dh-entry:hover .dh__glow { opacity: 0.62; }

.dh-entry:hover .dh__body {
  animation-play-state: paused;
  transform: translateY(-5px);
  transition: transform 0.4s var(--ease-out);
}

.dh-entry.is-poke .dh__body { animation: dh-poke 0.42s var(--ease-spring); }

@keyframes dh-poke {
  0%   { transform: translateY(0) scale(1); }
  40%  { transform: translateY(-9px) scale(1.05); }
  100% { transform: translateY(0) scale(1); }
}

/* 首次进入的小气泡 */
.dh-hint {
  position: absolute;
  right: 96px;
  bottom: 34px;
  padding: 8px 16px;
  border-radius: 13px 13px 3px 13px;
  background: var(--surface);
  border: 1px solid var(--line);
  box-shadow: 0 14px 32px -18px rgba(16, 24, 40, 0.45);
  color: var(--brand);
  font-size: 0.875rem;
  font-weight: 600;
  white-space: nowrap;
  opacity: 0;
  transform: translateX(8px);
  transition: opacity 0.34s var(--ease-soft), transform 0.34s var(--ease-out);
  pointer-events: none;
}

.dh-hint.is-on { opacity: 1; transform: translateX(0); }

/* ---- 面板 ---- */
/* ★ max-height 必须给固定页头留出 clearance。
   原来只写了 calc(100vh - 132px)（入口按钮 92 + 间距 14 + 底边 26），
   忘了页头还有 73px —— 矮视口遇上长文案（日语/韩语的问候语与 chips 更高）
   时面板会一直顶到视口顶端，把固定页头整个盖住：语言切换、导航、
   「聊聊需求」全部点不到。132 + 100（页头 73 + 余量 27）= 232。 */
.dh-panel {
  width: min(392px, calc(100vw - 40px));
  max-height: min(604px, calc(100vh - 232px));
  display: flex;
  flex-direction: column;
  overflow: hidden;
  border: 1px solid var(--line);
  border-radius: 20px;
  background: var(--surface);
  box-shadow: 0 30px 70px -30px rgba(16, 24, 40, 0.42);
  transform-origin: bottom right;
  animation: dh-open 0.36s var(--ease-out);
}

@keyframes dh-open {
  from { opacity: 0; transform: translateY(14px) scale(0.96); }
  to   { opacity: 1; transform: translateY(0) scale(1); }
}

.dh-panel[hidden] { display: none; }

.dh-panel__head {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 16px 16px;
  border-bottom: 1px solid var(--line);
  background: linear-gradient(180deg, var(--surface) 0%, var(--bg) 100%);
}

.dh-panel__head .dh-mini { flex: none; width: 38px; height: 41px; }

.dh-panel__id { display: flex; flex-direction: column; gap: 2px; margin-right: auto; min-width: 0; }
.dh-panel__id b { color: var(--brand); font-size: 0.875rem; font-weight: 600; }
.dh-panel__id i {
  color: var(--muted);
  font-size: 0.75rem;
  font-style: normal;
  letter-spacing: 0.04em;
}

.dh-panel__close {
  flex: none;
  width: 30px; height: 30px;
  display: grid; place-items: center;
  border: 0; border-radius: 8px;
  background: none; color: var(--muted);
  cursor: pointer;
  transition: background-color 0.2s var(--ease), color 0.2s var(--ease);
}

.dh-panel__close:hover { background: var(--bg-alt); color: var(--brand); }

.dh-panel__log {
  flex: 1;
  /* 下限不能太高：面板被 max-height 卡住时，flex 得能把它压下去，
     否则底部的说明文字会被挤出面板（实测溢出 20px）。 */
  min-height: 124px;
  overflow-y: auto;
  padding: 16px 16px 8px;
  display: flex;
  flex-direction: column;
  gap: 12px;
  overscroll-behavior: contain;
}

.dh-msg {
  max-width: 88%;
  padding: 12px 16px;
  border-radius: 14px;
  font-size: 0.875rem;
  line-height: 1.7;
}

.dh-msg--bot {
  align-self: flex-start;
  background: var(--bg-alt);
  color: var(--text-2);
  border-bottom-left-radius: 4px;
}

.dh-msg--me {
  align-self: flex-end;
  background: var(--accent-ink);
  color: #fff;
  border-bottom-right-radius: 4px;
}

.dh-msg a {
  color: var(--accent-ink);
  font-weight: 600;
  text-decoration: underline;
  text-underline-offset: 3px;
}

.dh-msg--me a { color: #fff; }

.dh-msg--wait { display: inline-flex; gap: 4px; align-items: center; }

.dh-msg--wait s {
  width: 5px; height: 5px; border-radius: 50%;
  background: var(--muted); text-decoration: none;
  animation: dh-dot 1.1s var(--ease-soft) infinite;
}

.dh-msg--wait s:nth-child(2) { animation-delay: 0.16s; }
.dh-msg--wait s:nth-child(3) { animation-delay: 0.32s; }

@keyframes dh-dot {
  0%, 60%, 100% { opacity: 0.28; transform: translateY(0); }
  30%           { opacity: 1; transform: translateY(-3px); }
}

.dh-panel__chips {
  display: flex;
  flex-wrap: wrap;
  gap: 7px;
  padding: 4px 16px 12px;
}

.dh-panel__chips button {
  padding: 7px 12px;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: var(--surface);
  color: var(--text-2);
  font-size: 0.875rem;
  cursor: pointer;
  transition: border-color 0.24s var(--ease), color 0.24s var(--ease),
    background-color 0.24s var(--ease);
}

.dh-panel__chips button:hover {
  border-color: var(--accent);
  color: var(--accent-ink);
  background: var(--accent-soft);
}

.dh-panel__form {
  display: flex;
  gap: 8px;
  padding: 0 16px 12px;
}

.dh-panel__form input {
  flex: 1;
  min-width: 0;
  padding: 12px 16px;
  border: 1px solid var(--line);
  border-radius: 11px;
  background: var(--surface);
  color: var(--text);
  font-size: 0.875rem;
  font-family: inherit;
  transition: border-color 0.24s var(--ease);
}

.dh-panel__form input:focus {
  outline: none;
  border-color: var(--accent);
}

.dh-panel__form button {
  flex: none;
  width: 42px;
  display: grid;
  place-items: center;
  border: 0;
  border-radius: 11px;
  background: var(--accent-ink);
  color: #fff;
  cursor: pointer;
  transition: background-color 0.24s var(--ease);
}

.dh-panel__form button:hover { background: #0052b3; }
.dh-panel__form button:disabled { background: var(--line-strong); cursor: default; }

.dh-panel__note {
  padding: 0 16px 16px;
  color: var(--muted);
  font-size: 0.75rem;
  line-height: 1.6;
}

@media (max-width: 720px) {
  .dh-widget { right: 16px; bottom: 16px; }
  .dh-entry { width: 68px; height: 74px; }
  .dh-hint { display: none; }
  .dh-panel { max-height: calc(100vh - 120px); }
}

@media (prefers-reduced-motion: reduce) {
  .dh__body { animation: none; }
  .dh.is-blink .dh__eye { animation: none; }
  .dh-panel { animation: none; }
}

/* ---------- 48. 卡片视频：鼠标停留才播 ----------
   静态图是海报，视频首次悬停才加载（单条 90–120KB），离开即停并回到首帧。
   触屏设备没有 hover，JS 直接不启用，不会白费流量。 */
.card-video {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.55s var(--ease-soft), transform 0.9s var(--ease-out);
}

.card-media img {
  transition: opacity 0.55s var(--ease-soft), transform 0.9s var(--ease-out);
}

.card-media.is-playing .card-video { opacity: 1; }
.card-media.is-playing img { opacity: 0; }

/* 播放时整体轻微推近，和静态图的悬停缩放保持一致 */
.card:has(.card-link):hover .card-video { transform: scale(1.055); }

/* ---------- 49. 实际效果的数字单位 ----------
   原来 27% → 8% 这种「前→后」的值没法直接数数，所以那一栏一直是写死的静态文本，
   和上面的「数字带」不一致。拆成「大数字 + 小基线」后统一成可滚动。 */
.stat-v .unit {
  margin-left: 3px;
  font-size: 0.46em;
  font-weight: 600;
  letter-spacing: 0;
  color: var(--accent-ink);
}

.section--dark .stat-v .unit { color: var(--accent-lite); }   /* 深底 7.32:1 */

/* ---------- 50. 能力标签变成跳转入口 ----------
   这 8 个标签原来是没有去处的 <span>，上一轮为了不「骗人」把它们的 hover 删掉了。
   现在每张能力卡都有了锚点，标签改成链接、并把 hover 反馈加回来。 */
a.cap-chip { text-decoration: none; }

a.cap-chip:hover {
  border-color: var(--accent);
  color: var(--accent-ink);
  background: var(--accent-soft);
  transform: translateY(-2px);
}

/* 能力卡的交付物：贴在卡片底部，让跳过去的人有东西可看 */
.product-out {
  margin-top: auto;
  padding-top: 16px;
  border-top: 1px dashed var(--line);
  color: var(--tone-ink, var(--accent-ink));
  font-size: 0.875rem;
  font-weight: 600;
  line-height: 1.7;
}

/* ---------- 51. 全宽下拉面板（mega menu） ----------
   仿苹果官网：悬停一级导航，整幅面板从页头下方展开。
   面板挂在 <header> 里（header 是 position:fixed），所以绝对定位直接以页头为基准。 */
.nav-item { display: inline-flex; }

.mega {
  position: absolute;
  left: 0;
  right: 0;
  top: 100%;
  /* ★ 2026-10-16 · 收紧面板留白（原 32px 0 36px）。
     用户反馈「行业方案和项目案例的下拉菜单太大、太占页面、很丑」。
     实测改前：行业方案 630px、项目案例 674px —— 在 900px 高的视口里
     占到 70~75%，张开时几乎盖满整屏，白色面板里却只有十几行字。
     面板上下留白合计 68px 是这块体积的一部分，先压到 46px。 */
  padding: 22px 0 24px;
  background: var(--surface);
  border-top: 1px solid var(--line);
  border-bottom: 1px solid var(--line);
  box-shadow: 0 34px 60px -34px rgba(16, 24, 40, 0.34);
  opacity: 0;
  visibility: hidden;
  transform: translateY(-10px);
  transition: opacity 0.26s var(--ease-soft), transform 0.34s var(--ease-out),
    visibility 0s linear 0.34s;
}

.mega.is-open {
  opacity: 1;
  visibility: visible;
  transform: translateY(0);
  transition: opacity 0.26s var(--ease-soft), transform 0.34s var(--ease-out),
    visibility 0s;
}

.mega-grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 24px 44px;
}

/* ★ 2026-10-16 · 行业列内部改两栏（8 行 → 4+4）
   用户反馈「行业方案和项目案例的下拉菜单太大、太占页面」。
   收紧行高之后行业面板仍是 507px —— 因为**第一列是 8 个行业纵向堆叠**，
   8 × 53px = 424px，光这一列就把面板顶高了。

   面板总宽 1180px，三列各 348px 其实**横向还有余量没利用**：
   把「八个行业」这一列内部再分成两栏（每栏 ~150px），
   8 行变 4+4，这一列的高度直接砍半（424 → 212px），
   面板高度从「由最长列决定」变成由其余两列决定。

   ★ 为什么用 :has() 限定而不是给那一列加新 class：
     导航 mega 面板在 195 个页面里重复出现，加 class 要改 195 个文件；
     这里靠「列内链接数 ≥8」这一个特征命中那几列（八个行业 / 八个案例 / 按行业），
     其余列（1~5 条）不受影响。实测全站命中 3 列，其余 8 列不动。
     判据是 `.mega-a:nth-child(9)` 存在 —— 即第 9 个子元素仍是链接，
     等价于「链接数 ≥8」，与 `.mega-h` 标题占 1 个子元素相符。 */
/* ★ 两栏后每栏约 164px。实测（canvas measureText）：13px 字号下每个汉字宽 13px，
   标题盒 160px 上限 = 12 字。站内有 3 个标题 13~19 字，会折成两行。
   ★ 试过把两栏改成 1.35fr/1fr「宽+窄」——**更差**：折行取决于 DOM 顺序而非标题长度，
   11 字的标题落进窄栏反而开始折。所以回到等分。
   折行在中文导航里是可接受的（Apple 中国官网的导航同样有折行条目），
   真正的收益来自「8 行变 4+4」这个纵向压缩，而不是消灭最后一两处折行。 */
.mega-col:has(> .mega-a:nth-child(9)) {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 0 20px;
  align-items: start;
}
/* 两栏后列标题（「八个行业」）要横跨整列 */
.mega-col:has(> .mega-a:nth-child(9)) > .mega-h { grid-column: 1 / -1; }
/* 副标题在窄栏里容易折行、反而把行撑高 —— 两栏模式下只留主标题，
   副标题信息在行业页首页就有，导航里不重复。 */
.mega-col:has(> .mega-a:nth-child(9)) .mega-a span { display: none; }
/* ★ 两栏后每栏只有约 164px，长标题会折成两行（实测 12 个字的
   「执法文书智能生成与合规校验」必折），又重新把列撑高 24px。
   这里把标题字号收到 0.8125rem、并允许按容器收缩 ——
   导航里的标题是「路标」，不必与正文同号字；
   真正用于阅读的标题在目标页面里，那里不受影响。 */
.mega-col:has(> .mega-a:nth-child(9)) .mega-a {
  padding-left: 6px;
  padding-right: 6px;
}
.mega-col:has(> .mega-a:nth-child(9)) .mega-a b {
  font-size: 0.8125rem;
  line-height: 1.3;
  letter-spacing: -0.01em;
}

.mega-col { min-width: 0; }

.mega-h {
  margin-bottom: 12px;
  color: var(--muted);
  font-size: 0.75rem;
  font-weight: 600;
  letter-spacing: 0.06em;
}

.mega-a {
  display: block;
  margin-left: -8px;
  /* ★ 2026-10-16 · 收紧行高（原 padding 8px 8px）。
     实测改前：一条链接 = 16px 内边距 + 标题 21px + (3px 间距 + 副标题 22px)
     ≈ 62~70px。**8 个行业堆起来就是 528px**，这是面板高达 630px 的主因。
     Apple 的导航下拉是一行一个条目、行高约 36~44px，不是 66px。
     改法：
       ① 纵向内边距 8px → 5px（仍保留舒适的点选热区 ≥32px）
       ② 副标题缩到 0.8125rem 并去掉 margin-top，让它紧贴标题
       ③ 标题行高 1.5 → 1.35 —— 大块文字堆叠时行高是主要的纵向开销 */
  padding: 5px 8px;
  border-radius: var(--radius-btn);
  color: var(--text-2);
  font-size: 0.875rem;
  line-height: 1.35;
  text-decoration: none;
  transition: background-color 0.2s var(--ease), color 0.2s var(--ease);
}

.mega-a b {
  display: block;
  color: var(--brand);
  font-weight: 600;
  transition: color 0.2s var(--ease);
}

.mega-a span {
  display: block;
  margin-top: 0;
  color: var(--muted);
  font-size: 0.8125rem;
  line-height: 1.45;
}

.mega-a:hover { background: var(--bg-alt); }
.mega-a:hover b { color: var(--accent-ink); }
.mega-a:hover span { color: var(--text-2); }

.nav-item[data-mega] .nav-link[aria-expanded="true"] { color: var(--brand); }

/* ---------- 52. 服务面板：主从式（master-detail） ----------
   左边 6 行先看全，右边只展开当前那一行。
   为什么不用「一次看全」：二级项有 19 条，一屏铺出来扫不动；
   先给 6 个短标题，用户挑一条再看细节，读起来省力。 */
.mega-split {
  display: grid;
  grid-template-columns: 268px minmax(0, 1fr);
  gap: 40px;
  align-items: start;
}

.mega-side {
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding-right: 32px;
  border-right: 1px solid var(--line);
}

/* ★ 按钮的 color 兜底。
   <button> 的 UA 默认色是 buttontext（纯黑），而且**不继承**父级颜色；
   而 `font: inherit` 只继承字体属性、**不含颜色** —— 这两条合起来，
   只要哪个按钮忘了写 color，就会渲染成纯黑，和旁边 --text(#101828) 的正文对不上。
   实测全站抓到 8 个（页头下拉 7 个 + 对话入口 1 个），都是「漏了」而不是「设计成黑」。

   逐个补 color 治标 —— 新增按钮还会再犯。所以在这里兜一次底：
   按钮默认继承文字色，需要别的颜色时由各自的规则覆盖（.btn--primary 等都有显式 color，不受影响）。 */
button { color: inherit; }

.mega-pick {
  position: relative;
  display: block;
  width: 100%;
  /* ★ 2026-10-16 · 收紧（原 padding 12px 12px）。
     「服务」面板的高度由左侧这 6 行决定：改前每行 65~83px，6 行 = 434px，
     加上面板留白就是 482px —— 是 5 个下拉里最高的一个。
     与 .mega-a 同一套收紧逻辑：纵向内边距 12 → 7px，标题行高 1.4 → 1.35，
     副标题字号 0.75rem 保持、行高 1.5 → 1.45、去掉 margin-top。 */
  padding: 7px 12px;
  border: 0;
  border-radius: var(--radius-sm);
  background: transparent;
  font: inherit;
  /* ★ 必须显式给 color。
     `font: inherit` 只继承字体属性，**不含颜色**；<button> 的 UA 默认色是 buttontext（纯黑），
     而它旁边所有文字都是 --text(#101828)。实测全站有 7 个这样的按钮渲染成 rgb(0,0,0) ——
     这正是「不是黑就是白」的一个具体实例：不是设计选的黑，是**漏了**。 */
  color: var(--text);
  text-align: left;
  cursor: pointer;
  transition: background-color 0.2s var(--ease);
}

/* 选中标记单独画一条短竖条。
   别用 inset box-shadow：圆角 10px 会把 3px 的阴影切成一个「括号」，
   看着像没画完的边框，不像「当前选中」。 */
.mega-pick::before {
  content: '';
  position: absolute;
  left: 0;
  top: 50%;
  width: 3px;
  height: 0;
  border-radius: 0 3px 3px 0;
  background: var(--accent);
  transform: translateY(-50%);
  transition: height 0.22s var(--ease-out);
}

.mega-pick b {
  display: block;
  color: var(--brand);
  font-size: 0.875rem;
  font-weight: 600;
  line-height: 1.35;
  transition: color 0.2s var(--ease);
}

.mega-pick span {
  display: block;
  margin-top: 0;
  color: var(--muted);
  font-size: 0.75rem;
  line-height: 1.45;
}

.mega-pick:hover { background: var(--bg-alt); }

.mega-pick.is-active { background: var(--bg-alt); }

.mega-pick.is-active::before { height: 56%; }

.mega-pick.is-active b { color: var(--accent-ink); }

.mega-pick:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: -2px;
}

.mega-main { min-width: 0; }

.mega-lead {
  margin-bottom: 16px;
  color: var(--text-2);
  font-size: 0.875rem;
  line-height: 1.6;
}

.mega-pane { display: none; }

.mega-pane.is-active {
  display: block;
  animation: megaPaneIn 0.3s var(--ease-out) both;
}

@keyframes megaPaneIn {
  from { opacity: 0; transform: translateX(10px); }
  to { opacity: 1; transform: none; }
}

.mega-cols {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 2px 24px;
}

.mega-more {
  display: inline-block;
  margin-top: 16px;
  color: var(--accent-ink);
  font-size: 0.875rem;
  font-weight: 600;
  text-decoration: none;
}

.mega-more:hover { text-decoration: underline; }

@media (prefers-reduced-motion: reduce) {
  .mega-pane.is-active { animation: none; }
  .mega-pick::before { transition: none; }
}

/* 窄屏走汉堡菜单，面板不出现 */
@media (max-width: 900px) {
  .mega { display: none; }
}

/* ---------- 53. 行业方案页：按苹果 solution 页的编排重做 ----------
   骨架对着 apple.com.cn/business 拆出来的：
     内页 Hero → 吸顶本地导航（localnav）→ 主题磁贴（图文左右交替）
     → 深色重音带 → 案例章节 → FAQ → router 三入口

   改动的要害不是「长得像苹果」，是**节奏**。
   原来七个行业如果做成一排七张一模一样的卡，一屏扫过去分不出差别，
   读者只能一张张读，读到第三张就放弃了。
   现在每个行业占一整屏、图与文左右交替，靠「翻转」把视线往下带。

   内页 Hero 仍保持浅色：这是本站 17 个内页的共同约定，
   全站只有首页首屏是深色，这里破例会让整站看起来「一半是黑的」。 */

/* ---- 吸顶本地导航（Apple 的 localnav）----
   长页面必须有「现在读到哪、还能去哪」的出口，否则读者只能一路滚到底再往回找。 */
.localnav {
  position: sticky;
  top: 72px;                    /* 页头高度 */
  z-index: 60;
  background: rgba(255, 255, 255, 0.86);
  backdrop-filter: saturate(180%) blur(18px);
  -webkit-backdrop-filter: saturate(180%) blur(18px);
  border-top: 1px solid var(--line);
  border-bottom: 1px solid var(--line);
}

.localnav__inner {
  display: flex;
  align-items: center;
  gap: 24px;
  height: 56px;
}

.localnav__title {
  flex: none;
  color: var(--brand);
  font-size: 1rem;
  font-weight: 600;
}

.localnav__links {
  display: flex;
  flex: 1;
  gap: 2px;
  min-width: 0;
  overflow-x: auto;
  scrollbar-width: none;
  -ms-overflow-style: none;
}

.localnav__links::-webkit-scrollbar { display: none; }

.localnav__links a {
  flex: none;
  padding: 7px 12px;
  border-radius: 8px;
  color: var(--text-2);
  font-size: 0.875rem;
  font-weight: 500;
  white-space: nowrap;
  text-decoration: none;
  transition: background-color 0.2s var(--ease), color 0.2s var(--ease);
}

.localnav__links a:hover { background: var(--bg-alt); color: var(--brand); }

.localnav__links a.is-current {
  background: var(--accent-soft);
  color: var(--accent-ink);
}

.localnav__cta {
  flex: none;
  padding: 8px 16px;
  border-radius: var(--radius-btn);
  background: var(--accent-ink);
  color: #fff;
  font-size: 0.875rem;
  font-weight: 600;
  white-space: nowrap;
  text-decoration: none;
  transition: background-color 0.2s var(--ease);
}

.localnav__cta:hover { background: var(--brand); }

/* ---- 行业磁贴：一整屏讲一个行业 ---- */
.ind-tile {
  padding: 104px 0;
  border-bottom: 1px solid var(--line);
  /* 吸顶导航会盖住锚点，留出 72 页头 + 56 导航 + 16 余量 */
  scroll-margin-top: 144px;
}

.ind-tile__inner {
  display: grid;
  grid-template-columns: minmax(0, 5fr) minmax(0, 7fr);   /* 12 列的 5:7 */
  gap: 72px;
  align-items: center;
}

/* 隔一个翻一次：图文左右交替，视线被迫跟着走 */
.ind-tile--flip .ind-tile__inner {
  grid-template-columns: minmax(0, 7fr) minmax(0, 5fr);
}

.ind-tile--flip .ind-tile__copy { order: 2; }
.ind-tile--flip .ind-tile__media { order: 1; }

.ind-tile__copy { min-width: 0; }

.ind-tile__copy h2 {
  font-size: clamp(1.7rem, 3vw, 2.4rem);
  line-height: 1.2;
}

.ind-tile__lead {
  margin-top: 16px;
  color: var(--text-2);
  font-size: 1.1875rem;
  line-height: 1.8;
}

.ind-tile .ind-list { margin-top: 24px; }

.ind-tile .ind-fit { margin-top: 28px; }

.ind-tile .link-arrow { margin-top: 28px; }

.ind-tile__media {
  margin: 0;
  border-radius: var(--radius);
  overflow: hidden;
  background: var(--bg-alt);
  aspect-ratio: 3 / 2;
}

.ind-tile__media img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform 1.1s var(--ease-out);
}

.ind-tile:hover .ind-tile__media img { transform: scale(1.035); }

/* ---- 深色重音带：七个行业其实是同一件事 ---- */
.ind-band-grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 44px;
}

.ind-band-grid h3 {
  font-size: 1.1875rem;
  line-height: 1.4;
}

.ind-band-grid p {
  margin-top: 12px;
  font-size: 0.875rem;
  line-height: 1.8;
}

.ind-band-num {
  display: block;
  margin-bottom: 16px;
  color: var(--accent-lite);
  font-size: 0.875rem;
  font-weight: 700;
  letter-spacing: 0.06em;
}

/* ---- FAQ：复用 §18 的折叠面板，这里只补排版 ---- */
/* ★ 880px → 700px。
   880px 配 16px 字号 = **每行 55 个汉字**。中文排版的经验区间是 25–40 字/行，
   超过 45 字读者换行时容易串行（找不到下一行的开头）。
   700px → 43 字/行，落回可用区间。

   这一条是照着用户自己那一版（huanfang-redesign-v5）学的 ——
   它的正文栏是 700px，实测每行 26–48 字，控制住了；
   我这边全站扫下来只有 FAQ 这一处超标（16 个段落，全 55 字），
   其余页面的 .lead 是 620px / 36 字，本来就合格。
   ⇒ 教训：**「页面看着没问题」不等于没问题 —— 量了才知道问题集中在哪一处。** */
.faq-list { max-width: 700px; }

/* ---- router：Apple 每个 solution 页结尾都有这么一段「下一步去哪」---- */
.router-grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 24px;
  margin-top: 52px;
}

.router-card {
  display: block;
  padding: 32px 28px 28px;
  border: 1px solid rgba(255, 255, 255, 0.12);
  border-radius: var(--radius);
  background: rgba(255, 255, 255, 0.07);
  color: inherit;
  text-decoration: none;
  transition: background-color 0.24s var(--ease), border-color 0.24s var(--ease),
    transform 0.24s var(--ease);
}

.router-card:hover {
  background: rgba(255, 255, 255, 0.12);
  border-color: rgba(255, 255, 255, 0.24);
  transform: translateY(-3px);
}

.router-card b {
  display: block;
  color: #fff;
  font-size: 1.1875rem;
  font-weight: 600;
}

.router-card span {
  display: block;
  margin-top: 8px;
  color: rgba(255, 255, 255, 0.56);
  font-size: 0.875rem;
  line-height: 1.7;
}

.router-card i {
  display: inline-block;
  margin-top: 20px;
  color: var(--accent-lite);
  font-size: 0.875rem;
  font-style: normal;
  font-weight: 600;
}

/* ---- 响应式 ---- */
@media (max-width: 1000px) {
  .ind-tile__inner,
  .ind-tile--flip .ind-tile__inner { grid-template-columns: minmax(0, 1fr); gap: 40px; }
  .ind-tile--flip .ind-tile__copy { order: 1; }
  .ind-tile--flip .ind-tile__media { order: 2; }
  .ind-band-grid,
  .router-grid { grid-template-columns: minmax(0, 1fr); }
}

@media (max-width: 900px) {
  /* 窄屏走汉堡菜单，页头之下没有吸顶位，导航改为静态 */
  .localnav { position: static; }
  .localnav__inner { height: auto; flex-wrap: wrap; padding-top: 12px; padding-bottom: 12px; }
  .localnav__links { flex-basis: 100%; order: 3; }
  .localnav__cta { margin-left: auto; }
  .ind-tile { padding: 72px 0; scroll-margin-top: 84px; }
}

@media (prefers-reduced-motion: reduce) {
  .ind-tile:hover .ind-tile__media img { transform: none; }
  .router-card:hover { transform: none; }
}

/* ---- 行业方案页 · 案例卡上的「行业 · 客户」小标签 ---- */
.card-tag {
  margin-bottom: 8px;
  color: var(--accent-ink);
  font-size: 0.75rem;
  font-weight: 600;
  letter-spacing: 0.06em;
}

/* ---------- 54. 交付标准页（按行业 / 按业务线）----------
   这一组页面是 B2B 的「信任状」：客户在评估阶段真正想看的不是「你能做什么」，
   而是「交付到什么程度算完、谁签字、不达标怎么办」。
   所以版式刻意选**信息密度优先**（编号卡 + 验收表），不学 Apple 那种大留白 ——
   苹果是消费品官网，打动的是「想买东西的人」；这里要说服的是「要签字的人」。 */
.dl-num {
  display: block;
  margin-bottom: 16px;
  color: var(--accent-ink);
  font-size: 0.875rem;
  font-weight: 700;
  letter-spacing: 0.06em;
}

/* 吸顶本地导航会盖住锚点，给每个锚点区留出 72 页头 + 56 导航 + 16 余量 */
#dl-generic, #dl-industry, #dl-service, #dl-output,
#dl-extra, #dl-accept, #dl-fail, #dl-src, #dl-next {
  scroll-margin-top: 144px;
}

/* 验收表在窄屏可以横滑，别把页面撑破 */
@media (max-width: 720px) {
  #dl-generic, #dl-industry, #dl-service, #dl-output,
  #dl-extra, #dl-accept, #dl-fail, #dl-src, #dl-next { scroll-margin-top: 84px; }
}

/* ---------- 55. 常见问题页 ----------
   面板与卡片会深链到具体某一条（faq.html#faq-q7）。
   不加偏移的话，跨页跳转用的是浏览器原生锚点滚动，问题会正好落在
   固定页头（72px）底下 —— 点进去先看到答案，看不到问题。 */
.faq-item { scroll-margin-top: 152px; }   /* 72 页头 + 56 吸顶导航 + 24 余量 */

@media (max-width: 1024px) {
  .faq-item { scroll-margin-top: 96px; }  /* 窄屏导航收进抽屉，只剩页头 */
}

/* ---------- 56. 首页行业卡上的短标签 ----------
   首页只给「短语」，行业总页给「一句」，详情页给「做法说明」——
   三层颗粒度逐级变细，同一批内容不再一字不差地出现三遍。 */
.ind-tags {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-top: 20px;
}

.ind-tags li {
  padding: 5px 12px;
  border-radius: 999px;
  background: var(--tone-soft, var(--accent-soft));
  color: var(--tone-ink, var(--accent-ink));
  font-size: 0.875rem;
  font-weight: 600;
  line-height: 1.5;
}

/* ==========================================================================
   58. 动效层 · 对标 nanfu.global
   --------------------------------------------------------------------------
   参数来自对 nanfu 的实测（反解 232KB CSS + 1.9MB JS），不是凭感觉：
     入场      { opacity: 0, y: 14 } → { 1, 0 }，0.52s，expo-out   ← 见 §21
     错开      stagger 0.03
     转场      clip-path: inset() 擦除
     滚动驱动  scrub 0.9（JS 在 motion.js 里，用 lerp 追平）
     平滑滚动  Lenis（motion.js）

   ★ 一个实测出来的节奏问题：
     nanfu 是「**入场快、状态变化慢**」—— 入场 0.5s，hover/状态 0.5–1.2s。
     我们原来正好反过来：入场 1.05s、hover 0.24s。
     这一节把入场扳到 0.5s，节奏就对上了。
   ★ 位移那条后来又从 50px 收到 14px，且**只有章节级元素才入场**，
     理由与实测对照写在 §21。入场参数现在只此一处，不要再在这里重复声明。
   ========================================================================== */

/* 擦除转场：nanfu 的 pageFn / chunkFn 用的是 clip-path: inset()，不是位移。
   用在媒体块上 —— 图片从左往右擦开，比淡入有分量，也不影响布局。 */
.motion-on .reveal-wipe {
  clip-path: inset(0 100% 0 0);
  transition: clip-path 0.8s var(--ease);
}

.motion-on .reveal-wipe.is-visible {
  clip-path: inset(0 0 0 0);
}

/* ★ 擦除方向跟着版面走，不是所有图块都从左往右。
   由来：行业页 6 个图块是**左右交替**的整幅版面（.ind-tile / .ind-tile--flip），
   但原来 6 个的擦除方向完全一样 —— 图在右边时，擦除是从屏幕最远端扫过来的，
   和版面读不到一起去，看下来就是「同一个动效复制了 6 遍」。
   现在图在左就从左擦开、图在右就从右擦开：动画呼应版面，而不是叠在版面上。
   ⇒ 通法：**同一个动效复用多次时，至少要有一个维度由「元素自身的位置」决定**，
     否则它就只是复制粘贴。位置、方向、顺序任选其一，但不能全都写死。 */
.motion-on .ind-tile--flip .reveal-wipe {
  clip-path: inset(0 0 0 100%);
}

.motion-on .ind-tile--flip .reveal-wipe.is-visible {
  clip-path: inset(0 0 0 0);
}

/* 列表错开：容器带 data-stagger，子元素自动排 --d（默认 30ms，同 nanfu） */
.motion-on [data-stagger] > * {
  transition-delay: var(--d, 0ms);
}

/* 降低动效：全部退回原生，不加任何位移与擦除 */
.motion-off .reveal,
.motion-off .reveal-wipe {
  opacity: 1;
  transform: none;
  clip-path: none;
  transition: none;
}

@media (prefers-reduced-motion: reduce) {
  .motion-on .reveal,
  .motion-on .reveal-wipe,
  /* ★ 必须把 --flip 这条也列进来。
     它的特异性是 (0,3,0)，比上面两条 (0,2,0) 高 ——
     不列的话，开了「减少动态效果」之后反向擦除的图**会永远停在裁切状态**，
     看起来就是「图没加载出来」。这类「新增高特异性规则压掉重置规则」的坑，
     在动效里代价特别大：它不报错，只是内容不见了。 */
  .motion-on .ind-tile--flip .reveal-wipe {
    transform: none;
    clip-path: none;
    transition: none;
    opacity: 1;
  }
}

/* 常见问题页的分类锚点：吸顶导航同样会盖住，要给偏移。
   （交付标准页与行业页各自在 §54 / §53 里写过了，这里是最后一处漏掉的。
     漏掉的原因很典型：锚点偏移是**逐页手写**的，新增页面时最容易忘。
     现在由动效探针的 B1 统一验：它会遍历每条吸顶导航链接，逐个点一遍看落点。） */
#faq-deal, #faq-service, #faq-industry, #faq-security {
  scroll-margin-top: 144px;
}

@media (max-width: 1024px) {
  #faq-deal, #faq-service, #faq-industry, #faq-security {
    scroll-margin-top: 84px;
  }
}

/* ==========================================================================
   59. 指标卡：让数字当视觉锚点
   --------------------------------------------------------------------------
   改前「验收看这三个数」是一列 16px 的等重文字，读者没有落点。
   改后把值单独放大到 2rem 做主视觉，说明与主体降为小字 ——
   读的人先看到数，需要细看再看字。
   这不是「少写点字」，是**把层次做出来**：一屏里必须有一个先被看见的东西。
   ========================================================================== */
.metric-cards {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 16px;
  margin: 0;
  padding: 0;
  list-style: none;
}

.metric-cards li {
  padding: 24px 24px 20px;
  border: 1px solid var(--line);
  border-top: 3px solid var(--tone, var(--accent));
  border-radius: var(--radius);
  background: var(--surface);
}

.metric-cards__v {
  display: block;
  color: var(--tone-ink, var(--accent-ink));
  font-size: clamp(1.375rem, 2.4vw, 1.875rem);
  font-weight: 700;
  letter-spacing: -0.02em;
  line-height: 1.2;
}

.metric-cards__l {
  display: block;
  margin-top: 8px;
  color: var(--text);
  font-size: 0.875rem;
  line-height: 1.6;
}

.metric-cards__m {
  display: block;
  margin-top: 8px;
  color: var(--muted);
  font-size: 0.875rem;
  font-style: normal;
  line-height: 1.5;
}

@media (max-width: 1000px) {
  .metric-cards { grid-template-columns: minmax(0, 1fr); }
}

/* ==========================================================================
   60. 降低卡片的阅读疲劳
   --------------------------------------------------------------------------
   问题（量过）：services.html 的 4 列网格里，每张卡是「图标 + 标题 + 1 段说明 + 4 条明细」
   ≈ 10 行小字，4 张并排 ⇒ **一屏 40 行等重小字**。字都不长（平均 14 字），
   问题不在字数，在**同屏行数**与**没有层次**。

   两道处理：
     ① 带明细列表的网格改 2 列 —— 卡片宽度翻倍，每行容字翻倍，同屏行数减半。
        用 :has() 精确命中「有 .card-list 的网格」，没明细的网格保持原样。
     ② 明细本身降一档重量（字号 −1px、行距收紧、条间距减半），
        让它读起来是「附注」而不是「正文」。
   ========================================================================== */

.grid--4:has(.card-list) {
  grid-template-columns: repeat(2, minmax(0, 1fr));
}

.grid--3:has(.card-list) {
  grid-template-columns: repeat(3, minmax(0, 1fr));
}

/* 明细降一档：从「正文」变成「附注」 */
.card-list {
  margin-top: 16px;
  padding-top: 16px;
}

.card-list li {
  font-size: 0.875rem;      /* 14 → 13px */
  line-height: 1.6;          /* 1.75 → 1.6 */
  color: var(--muted);
}

.card-list li + li { margin-top: 3px; }

.card-list li::before {
  width: 5px;
  height: 5px;
  top: 9px;
}

@media (max-width: 1000px) {
  .grid--4:has(.card-list),
  .grid--3:has(.card-list) { grid-template-columns: minmax(0, 1fr); }
}

/* ---------- 61. FAQ 长答案的分块列表 ----------
   三条答案原文分别是 242 / 216 / 359 字，挤在一个 <p> 里就是一堵墙。
   它们本来就是「一是…二是…三是…」的结构，拆成小标题列表即可：
   读的人先扫小标题，需要细看再看正文。 */
.faq-sub {
  display: grid;
  gap: 8px;
  margin: 0;
  padding: 0 0 24px;
  list-style: none;
}

.faq-sub li {
  position: relative;
  padding-left: 16px;
  color: var(--muted);
  font-size: 1rem;
  line-height: 1.7;
}

.faq-sub li::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0.72em;
  width: 7px;
  height: 1px;
  background: var(--line-strong);
}

.faq-sub b {
  color: var(--brand);
  font-weight: 600;
}

/* 引导句后面紧跟列表时，不要再多留一段的间距 */
.faq-a p:has(+ .faq-sub) { padding-bottom: 16px; }

/* 额外四条：全宽后改用两列，避免四条拉成一条长竖线 */
#acceptance .check-list {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 12px 32px;
}

@media (max-width: 1000px) {
  #acceptance .check-list { grid-template-columns: minmax(0, 1fr); }
}

/* ==========================================================================
   62. 移动端点击目标
   --------------------------------------------------------------------------
   Apple / Google 的触控指南是 44×44。实测 390px 宽下有几处不够：
     .link-arrow           27px  （正文里的文字链 + 箭头）
     .ind-nav a            38px  （行业芯片）
     .localnav__links a    38px  （吸顶子导航）
     .localnav__cta        40px
   桌面用鼠标没问题，手机上手指点不准 —— 用 padding 撑到 44px，
   **不改字号**（改字号会让排版跟着变，撑 padding 只影响点击区）。
   ========================================================================== */

@media (max-width: 1024px) {
  .localnav__links a { padding: 12px 16px; }   /* 38 → 46 */
  .localnav__cta { padding: 12px 16px; }       /* 40 → 46 */
  .localnav__inner { height: auto; padding-top: 4px; padding-bottom: 4px; }
}

@media (max-width: 720px) {
  .link-arrow { padding: 8px 0; }           /* 38 → 46 */
  .faq-q { padding-top: 16px; padding-bottom: 16px; }

  /* 11px 的步骤标签在手机上读不了，抬到 12px */
  .step-no,
  .flow-no { font-size: 0.75rem; }
}

/* 11px 的英文步骤标签（.method-en）在手机上读不了，抬到 12px */
@media (max-width: 720px) {
  .method-en { font-size: 0.75rem; }
}

/* 右下角的数字人入口是 position:fixed，会盖住视口右下角 —— 这是浮窗的固有行为。
   但它不能把**页面最后的内容**永久挡住（页脚链接、表单按钮）。
   窄屏给页脚补一段底部留白，保证那些内容能滚到浮窗上方被完整读到。 */
@media (max-width: 720px) {
  .site-footer { padding-bottom: 104px; }
}

/* ==========================================================================
   63. 转场、按压与进度
   ========================================================================== */

/* 页面进入：整页从左擦开（对标 nanfu 的 pageFn）。
   遮罩由 JS 现场创建、1s 后摘除 —— 不用常驻全屏层，JS 挂了也不会白屏。
   transform-origin 放右：scaleX 1→0 时遮罩朝右收，内容就是「从左被擦出来」。 */
.page-veil {
  position: fixed;
  inset: 0;
  z-index: 300;
  background: var(--bg);
  transform-origin: right center;
  transform: scaleX(1);
  transition: transform 0.62s var(--ease);
  pointer-events: none;
}

.page-veil.is-done { transform: scaleX(0); }

/* 滚动进度：2px 细线，只在滚起来之后出现 */
.scroll-progress {
  position: fixed;
  top: 0;
  left: 0;
  z-index: 120;
  width: 100%;
  height: 2px;
  background: var(--accent);
  transform: scaleX(0);
  transform-origin: left center;
  opacity: 0;
  transition: opacity 0.3s var(--ease);
  pointer-events: none;
}

.scroll-progress.is-on { opacity: 1; }

/* 按压反馈：鼠标有 hover，触屏没有 —— 触屏只有按下这一下，
   没有反馈就会让人怀疑「点到了没有」。 */
.btn:active { transform: translateY(1px) scale(0.985); }
.btn { transition: transform 0.16s var(--ease-soft); }

.card:has(.card-link):active { transform: translateY(-1px) scale(0.994); }
.router-card:active { transform: translateY(-1px) scale(0.994); }

@media (prefers-reduced-motion: reduce) {
  .page-veil { display: none; }
  .scroll-progress { display: none; }
}

/* 行业口径卡片的序号：和 §32 的 why-card 同一套语言，不另造一套视觉 */
.cal-no {
  display: block;
  margin-bottom: 12px;
  color: var(--tone-ink, var(--accent-ink));
  font-size: 0.875rem;
  font-weight: 700;
  letter-spacing: 0.06em;
}

/* ==========================================================================
   64. 交互细化：首屏让位、擦除揭示、落点反馈、图片淡入
   --------------------------------------------------------------------------
   这一节全部是「读者能感觉到但说不出」的那一类。四条各自的由来：

   ① 首屏入场让位给遮罩
      原来 .page-veil 用 0.62s 从左擦开，而首屏 .reveal 在 DOMContentLoaded
      那一刻就开始跑（0.5s + 最多 0.32s 的 --d）。两者几乎同时起跑 ⇒
      **首屏入场有大约六成是盖在白布后面播完的**，读者只看到结果。
      给首屏加一个基础延迟，让内容追着擦除的边界出来。

   ② 擦除揭示绑到滚动（[data-wipe-scrub]）
      .reveal-wipe 是一次性触发 —— 只回答「进没进视口」，滚动过程中图是死的。
      绑到滚动后，擦开多少 = 读到多少，与 nanfu 的 scrub 手感一致。
      分工：卡片内小图用 reveal-wipe（轻），大图用 wipe-scrub（重）。
      ★ 初始的裁切态**只在 JS 里写**，CSS 里不给被裁的初始值 ——
        JS 挂了图就是完整的，不会留下一块永远不出现的空白。

   ③ 锚点落点脉冲（.is-flash）
      点目录里的一条，只靠「滚动停下来」是看不出到了没有的，
      尤其相邻两段结构相似时。给目标一次高亮脉冲。
      ★ 用 box-shadow 而不是 background-color：
        background 动画的终态会覆盖元素自己的底色，深色区块上会闪一下。

   ④ 图片解码后淡入（.img-pending / .is-loaded）
      解码没完就上屏，会看到「上半截清晰、下半截空白」的中间态。
      ★ 只给 JS 跑起来时**还没加载完**的图加类；已经 complete 的图一个类都不加。
   ========================================================================== */

/* ① 首屏入场：基础延迟 0.30s ≈ 遮罩擦到七成时开始，内容追着边界出来 */
.motion-on .hero .reveal,
.motion-on .page-hero .reveal {
  transition-delay: calc(0.3s + var(--d, 0ms));
}

/* ② 擦除揭示（[data-wipe-scrub]）：CSS 里**故意什么都不写**。
     裁切态只在 JS 里逐帧内联写上，于是：
       · JS 挂了 → 没有裁切态 → 图就是完整的，不会留一块永远不出现的空白
       · 降低动效 → motion.js 直接 return → 同样不写裁切态
     也想过加 `will-change: clip-path`，但它是**长期**生效的 —— 21 个大图
     会因此一直各占一个合成层，移动端内存代价不小；而擦除只跑几百毫秒，
     省下的那点合成开销换不回这个代价。
     （写下来是因为「顺手加个 will-change」几乎不用思考，很容易被后人补回去。） */

/* ③ 锚点落点脉冲 */
.is-flash {
  animation: qy-flash 1s var(--ease-out);
}

@keyframes qy-flash {
  0%   { box-shadow: inset 0 0 0 3px rgba(10, 132, 255, 0.55); }
  55%  { box-shadow: inset 0 0 0 3px rgba(10, 132, 255, 0.20); }
  100% { box-shadow: inset 0 0 0 3px rgba(10, 132, 255, 0); }
}

/* ④ 图片淡入 */
.motion-on img.img-pending {
  opacity: 0;
  transition: opacity 0.5s var(--ease-out);
}

.motion-on img.img-pending.is-loaded {
  opacity: 1;
}

/* 卡片标题的悬停反馈：按业务线着色。
   卡片本来已经有「顶部细线扫入 + 图片放大」，但**标题本身没反应** ——
   而读者的视线是落在标题上的，标题不动，悬停就少了一半的确认感。 */
.card:has(.card-link):hover .card-link {
  color: var(--tone-ink, var(--accent-ink));
}

.card-link {
  transition: color 0.32s var(--ease-soft);
}

/* 降低动效：上面这些一律不加 */
.motion-off .is-flash {
  animation: none;
}

@media (prefers-reduced-motion: reduce) {
  .motion-on .hero .reveal,
  .motion-on .page-hero .reveal { transition-delay: 0ms; }
  .motion-on img.img-pending { opacity: 1; transition: none; }
  .is-flash { animation: none; }
}

/* ==========================================================================
   65. 待填标记（.ph-tag）
   --------------------------------------------------------------------------
   站上还有几处是**编的**，不能让它看起来像既成事实：
     · 页脚电话 176-0899-2954 —— 一个打不通的号码
     · 「安全应急响应 7×24 值守」—— 一条没确认过的服务承诺

   这一条学的是用户自己那一版的做法。它在《主设计判断与内容取舍》里写明
   「不把响应时限、赔偿承诺当作已经确认的公司事实」「去掉占位 400 电话」。
   本项目的处理是**保留版式、加明显标记**：等真实资料到位，
   全局搜一次 ph-tag 就能把标记全摘掉，版式不用动。

   用 dashed 边框而不是实心色块：它要读起来是「这里还没定」，
   不是一个正式标签 —— 实心色块会被当成设计元素，反而不提醒人。
   ========================================================================== */
.ph-tag {
  display: inline-block;
  margin-left: 6px;
  padding: 0 7px;
  border: 1px dashed currentColor;
  border-radius: 999px;
  font-size: 0.75rem;
  font-weight: 600;
  letter-spacing: 0.06em;
  line-height: 1.6;
  white-space: nowrap;
  vertical-align: 1px;
  opacity: 0.72;
}

/* 深色区块（页脚、深色 CTA 段）上 currentColor 是浅色，标记同样成立，
   不用另写一套 —— 这也是选 currentColor 而不是写死颜色的原因。 */

/* ==========================================================================
   66. 照片统一低饱和
   --------------------------------------------------------------------------
   站内 21 张照片全部是亮调的通用商务场景（办公室、笔记本、显示器、绿植）。
   这类图库照片的共同特征是**饱和度偏高、色温偏暖**——
   单独看一张没问题，三张并排出现时就会把整页的色调往暖黄拉，
   而本站的主色是冷蓝，两边打架。

   同时它们也是「这页是套模板生成的」最直观的信号：
   生成式页面几乎必然配这种亮调图库照。

   处理方式：全站统一压一档饱和度（0.82），而不是逐张去调 ——
   逐张调会得到 21 个不同的结果，反而不统一。
   压一档之后照片仍然是彩色的、可读的，但不再抢主色的戏。

   ★ 用 CSS filter 而不是重新编码图片，有三个理由：
     ① 一处生效、一处可撤，不用改动 21 个源文件；
     ② 以后新增图片自动获得同样的处理，不会漏；
     ③ 不做有损重编码，原始素材保持原样（用户后面可能要换真图）。
     代价是这些图会各自占一个合成层，21 张的量级可以接受。

   ★ 必须排除品牌标记（.brand-mark / .brand-lockup）：
     这条规则写的是裸 `img`，logo 也是 img —— 会被一起降饱和。
     照片降饱和是为了让它别抢主色；而**品牌色本身就是主色**，
     把 logo 压灰是把品牌压灰，性质完全相反。
     （实测：不排除的话页头那颗立方体会明显发闷。）
   ========================================================================== */
img:not(.brand-mark):not(.brand-lockup) {
  filter: saturate(0.82) contrast(1.02);
}

/* ==========================================================================
   67. FAQ 双栏：左栏段标题 + 右栏问题列表
   --------------------------------------------------------------------------
   上一节把 `.faq-list` 从 880px 收到 700px（每行 55 字 → 43 字，必要），
   但收窄之后冒出一个新问题：**700px 的单栏浮在 1180px 的容器里，右侧空掉约 40%**。
   页头和吸顶目录是通栏的，内容却只占左边六成，构图是斜的。

   解法学自用户自己那一版（huanfang-redesign-v5）：它的行业页用
   「左侧窄栏（行业选择器）+ 右侧内容列」把宽度填满，同时保住阅读行长。
   这里照做，只是左栏放的是段标题与导语：

     左栏 5fr   段标题 + 导语，**吸顶跟随**
     右栏 7fr   问题列表

   1132px 内容宽按 5:7 分、扣掉 56px 间距 ⇒ 右栏约 628px ≈ 每行 39 字，正好落在区间内。
   左栏吸顶还有个额外好处：FAQ 页很长，翻到第 5 个问题时，
   「现在读的是哪一类」一直挂在左边，不用滚回去看吸顶目录。
   ========================================================================== */
.faq-cols {
  display: grid;
  grid-template-columns: minmax(0, 5fr) minmax(0, 7fr);
  gap: 56px;
  align-items: start;
}

.faq-rail {
  /* 72px 页头 + 56px 吸顶目录 + 16px 呼吸 */
  position: sticky;
  top: 144px;
}

.faq-rail .lead {
  margin-top: 16px;
  font-size: 1rem;
  line-height: 1.7;
}

/* 栅格已经决定了列宽,700px 兜底在 L4998 已经写过一份(同值同权重,
   后写生效),这里再写一遍是纯冗余。第 20 轮诊断删掉。
   主定义保留在 L4998(注释也在那边)。 */

@media (max-width: 1000px) {
  /* 这个断点以下吸顶目录变成 static（见 §54），所以吸顶基准只剩页头 */
  .faq-cols { grid-template-columns: minmax(0, 1fr); gap: 24px; }
  .faq-rail { position: static; }
}

/* ==========================================================================
   68. 满幅章节（.field）：把「核心业务」从卡片网格改成照片压字
   --------------------------------------------------------------------------
   这一节学的是用户自己那一版（huanfang-redesign-v5）的**审美**：
   满幅摄影 + 文字压在图上 + 底部一条章节切换条（带随滚动填充的进度线）。
   他那版靠这个建立了整站的辨识度，我那版是卡片网格，信息清楚但不动人。

   ★ 但只拿形式，不拿信息密度。
     他那版每个章节只有「小标 + 标题 + 一行说明 + 链接」，密度很低；
     本站原来的卡片带 4 条服务范围 —— **那是信息不是装饰**。
     所以这里把 4 条压成一行紧凑标签留在下面：形式学他，密度留自己的。

   ★ 保留自己的设计语言：
     · 深靛（--brand）作遮罩与章节条底色，不另造一套深色
     · 编号 01/02/03 用等宽数字（§19h）—— 和站内其它编号同一套语汇
     · 进度线用 1px 规线，不用发光/渐变

   遮罩为什么必须这么重：正文压在照片上，对比度不能靠运气。
   底部收到 0.92 的深靛，保证白字在**任何照片**上都能过 AA。
   ========================================================================== */

/* ★ 引子段**留在浅色底上**，不要给整个 .field 铺深色。
   我第一版给 .field 铺了 var(--brand)，结果引子里的 .h2 用 var(--text) ——
   两个都是 #101828，**标题直接变成不可见的**（截图里那片空白就是它）。
   现在只有章节和章节条是深色，引子在白底上，顺带得到一次「浅 → 深」的节奏切换。
   章节舞台使用同一深色底面，照片遮罩和章节条都收在这一颜色上。
   离场后直接进入行业内容，不叠加空的渐变色带。 */
.field { padding-bottom: 0; margin-bottom: 0; }

.field .section-head { margin-bottom: 56px; }

.field-stage {
  position: relative;
  --field-tabs-h: 96px;
  background: var(--brand);
}

/* ---------- 单个章节 ---------- */
.field-chapter {
  position: relative;
  display: flex;
  align-items: flex-end;
  min-height: 74vh;
  /* ★ 给底部章节条留出空间。
     章节条是 sticky 的，会一直挂在视口底部；而章节的正文是贴底的（align-items:flex-end）。
     不预留的话，正文就会被那排标签压住。
     参考实现也是这个思路 —— 它量出标签高度写进 --cinema-bottom-room，
     给正文留位，而不是靠一块底板把正文盖掉。 */
  padding-bottom: var(--field-tabs-h, 88px);
  overflow: hidden;
  background: var(--brand);   /* 图片未加载时的兜底底色，也是对比度的基准 */
}

.field-media {
  position: absolute;
  inset: 0;
  z-index: 0;
}

.field-media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  /* 章节图比卡片图再压一档：满幅之后饱和度的影响会被放大 */
  filter: saturate(0.7) contrast(1.04);
}

/* 遮罩：上浅下深，把文字压在底部 */
.field-media::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(
    180deg,
    rgba(16, 24, 40, 0.42) 0%,
    rgba(16, 24, 40, 0.66) 46%,
    rgba(16, 24, 40, 0.90) 82%,
    var(--brand) 100%
  );
}

/* 照片角标：学他那版的「业务场景配图」标注 ——
   既不宣称照片里的人或场地属于本公司，也是一个安静的版式细节 */
.field-credit {
  position: absolute;
  top: 20px;
  right: 24px;
  z-index: 1;
  color: rgba(255, 255, 255, 0.56);
  font-size: 0.75rem;
  letter-spacing: 0.06em;
}

.field-copy {
  position: relative;
  z-index: 1;
  width: 100%;
  max-width: var(--maxw);
  margin: 0 auto;
  padding: 0 var(--gutter) 108px;
  color: #fff;
}

.field-eyebrow {
  margin: 0 0 16px;
  color: var(--accent-lite);
  font-size: 0.875rem;
  font-weight: 600;
  letter-spacing: 0.06em;
}

.field-title {
  /* ★ 必须显式给白色。
     基础规则 `h1, h2, h3, h4 { color: var(--brand) }` 是**直接规则**，
     它会压过从 .field-copy 继承来的白色 —— 而 var(--brand) 正好等于
     章节底色，标题会变成完全不可见。
     （对比度检查抓到的就是这个：rgb(16,24,40) on rgb(16,24,40)，比值 1.00。）
     同一个坑在这个文件里出现过两次了（引子段的 .h2 也是），
     所以凡是「深色区里的标题」，都要显式写颜色，不能靠继承。 */
  color: #fff;
  max-width: 16em;
  margin: 0;
  font-size: clamp(1.75rem, 3.6vw, 2.75rem);
  font-weight: 600;
  letter-spacing: -0.02em;
  line-height: 1.25;
  text-wrap: balance;
}

.field-desc {
  max-width: 34em;
  margin: 20px 0 0;
  color: rgba(255, 255, 255, 0.86);
  font-size: 1rem;
  line-height: 1.7;
}

/* 服务范围：一行紧凑标签，保留原来的信息密度 */
.field-tags {
  display: flex;
  flex-wrap: wrap;
  gap: 8px 8px;
  margin: 24px 0 0;
  padding: 0;
  list-style: none;
}

.field-tags li {
  padding: 5px 12px;
  border: 1px solid rgba(255, 255, 255, 0.24);
  border-radius: 999px;
  color: rgba(255, 255, 255, 0.86);
  font-size: 0.875rem;
  line-height: 1.5;
}

.field-link {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  margin-top: 24px;
  padding-bottom: 3px;
  border-bottom: 1px solid rgba(255, 255, 255, 0.44);
  color: #fff;
  font-size: 1rem;
  font-weight: 500;
  transition: border-color 0.25s var(--ease-soft), gap 0.25s var(--ease-soft);
}

.field-link:hover {
  gap: 12px;
  border-bottom-color: #fff;
}

/* ---------- 章节目录：照片、目录共享深靛底面 ----------
   sticky 目录脱离照片时依然落在舞台的深色背景上，透明上缘不会露出页面白底。
   当前章节只使用一段短进度线，已读章节不拼成全幅亮白规线。 */
.field-tabs {
  position: sticky;
  bottom: 0;
  z-index: 2;
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: clamp(24px, 4vw, 56px);
  margin: 0;
  padding: 16px max(var(--gutter), calc((100% - var(--maxw)) / 2 + var(--gutter))) 24px;
  background: var(--brand);
}

/* 这段遮罩只叠在照片里；目录自身始终有不透明底色。 */
.field-tabs::before {
  content: "";
  position: absolute;
  bottom: 100%;
  left: 0;
  right: 0;
  height: 40px;
  background: linear-gradient(180deg, rgba(16, 24, 40, 0), var(--brand));
  pointer-events: none;
}

.field-tab {
  position: relative;
  min-width: 0;
  display: flex;
  align-items: baseline;
  gap: 16px;
  min-height: 58px;
  padding: 16px 0 24px;
  color: #b5bfce;
  text-decoration: none;
  transition: color 0.25s var(--ease-soft);
}

.field-tab:hover,
.field-tab.is-active { color: #f4f7fc; }

.field-tab:focus-visible {
  outline-color: var(--accent-lite);
  outline-offset: 5px;
}

.field-tab__n {
  flex-shrink: 0;
  font-size: 0.8125rem;
  font-weight: 600;
  letter-spacing: 0.04em;
  font-variant-numeric: tabular-nums;
  font-feature-settings: "tnum" 1;
  color: #94a3b8;
}

.field-tab.is-active .field-tab__n { color: var(--accent-lite); }

.field-tab__t {
  min-width: 0;
  font-size: 1.125rem;
  line-height: 1.5;
  font-weight: 500;
  overflow-wrap: anywhere;
}

.field-tab__bar {
  position: absolute;
  left: 0;
  bottom: 4px;
  width: 56px;
  height: 2px;
  overflow: hidden;
  background: #52647d;
  opacity: 0;
  transition: opacity 0.25s var(--ease-soft);
}

.field-tab.is-active .field-tab__bar { opacity: 1; }
.field-tab:hover .field-tab__bar { opacity: 0.65; }

.field-tab__bar::after {
  content: "";
  position: absolute;
  inset: 0;
  background: var(--accent-lite);
  transform: scaleX(var(--p, 0));
  transform-origin: left center;
}

/* ---------- 响应式 ---------- */
@media (max-width: 1024px) {
  .field-chapter { min-height: 64vh; }
  .field-copy { padding-bottom: 92px; }
  .field-title { max-width: 100%; }
}

@media (max-width: 720px) {
  .field-stage { --field-tabs-h: 120px; }
  .field-chapter { min-height: 0; padding: 96px 0 calc(var(--field-tabs-h) + 24px); }
  .field-copy { padding-bottom: 0; }
  .field-desc { font-size: 0.9375rem; }
  .field-tabs {
    gap: 8px;
    padding: 8px 16px max(16px, env(safe-area-inset-bottom));
  }
  .field-tabs::before { height: 28px; }
  .field-tab {
    flex-direction: column;
    align-items: flex-start;
    gap: 5px;
    min-height: 82px;
    padding: 8px 0 20px;
  }
  .field-tab__n { font-size: 0.75rem; }
  .field-tab__t { font-size: 0.875rem; }
  .field-tab__bar { width: 40px; }
}

@media (prefers-reduced-motion: reduce) {
  .field-link, .field-tab, .field-tab__bar { transition: none; }
}

/* 满幅章节的视频层：复用 §48 的悬停播放，容器换成 .field-media。
   视频同样是「首次悬停才加载、离开即停回首帧」，触屏不启用。 */
.field-media .card-video {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  opacity: 0;
  pointer-events: none;
  filter: saturate(0.7) contrast(1.04);   /* 与静态图同一档处理，切换时不跳色 */
  transition: opacity 0.55s var(--ease-soft);
}

.field-media.is-playing .card-video { opacity: 1; }
.field-media.is-playing img { opacity: 0; }

/* ---------- 深色章节的入口 ----------
   入口遮罩保留在照片内部。出口不再使用灰白渐变，目录结束后进入行业浅底。 */
.field-stage::before {
  content: "";
  position: absolute;
  z-index: 1;
  left: 0;
  right: 0;
  top: -56px;
  height: 360px;
  background: linear-gradient(
    180deg,
    rgba(16, 24, 40, 0) 0%,
    rgba(16, 24, 40, 0.42) 16%,
    rgba(16, 24, 40, 0.85) 42%,
    rgba(16, 24, 40, 0.34) 74%,
    rgba(16, 24, 40, 0) 100%
  );
  pointer-events: none;
}

/* 只调整紧接业务章节的行业区，避免通用浅底渐变在交界处产生第二道白边。 */
.field + #industries {
  padding-top: clamp(76px, 8vw, 112px);
  background: linear-gradient(
    180deg,
    var(--tint-blue) 0,
    var(--tint-blue) calc(100% - 80px),
    var(--bg) 100%
  );
}

@media (max-width: 720px) {
  .field-stage::before { top: -40px; height: 240px; }
  .field + #industries { padding-top: 64px; }
}

/* ==========================================================================
   69. 服务页「适合什么情况」（.fit）
   --------------------------------------------------------------------------
   学自用户自己那一版（huanfang-redesign-v5/services.html#software）。
   他那版每个服务段的第一件事是「适合什么情况」，下面 3 个编号场景 ——
   让访客先自我判断「这服务是不是给我的」，再往下读能力。

   我这边原来是 section-head → 宽幅图 → feature → 4 张能力卡（16 条能力项），
   **信息量更大，但全在回答「我们能做什么」，没有回答「我适不适合」。**
   补的就是缺的这一环。

   ★ 只补这一环，没有照搬他另外三节：
     「典型交付内容」在本站已经散在 4 张能力卡的分项里，
     「一起确认什么」在 delivery-*.html 的验收标准页里（还更细，带签字人）。
     再抄一遍会让同一件事在两处说，口径还容易走岔。

   ★ 视觉上刻意**不用卡片**：
     下面紧跟着就是 4 张带边框的能力卡，这里再用卡片会分不清主次。
     只用一道上规线 + 三栏排布 —— 读起来像「判断条件」，不像「又一个功能块」。
   ========================================================================== */
.fit {
  margin-top: 48px;
  padding-top: 32px;
  border-top: 1px solid var(--line);
}

.fit__h {
  margin: 0;
  color: var(--text);
  font-size: 1rem;
  font-weight: 600;
  letter-spacing: 0.02em;
}

.fit__list {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 32px 44px;
  margin: 24px 0 0;
  padding: 0;
  list-style: none;
}

.fit__n {
  display: block;
  margin-bottom: 8px;
  color: var(--accent-ink);
  font-size: 0.75rem;
  font-weight: 700;
  letter-spacing: 0.06em;
  /* 与站内其它编号同一套语汇（§19h） */
  font-variant-numeric: tabular-nums;
  font-feature-settings: "tnum" 1;
}

.fit__list h3 {
  margin: 0;
  color: var(--text);
  font-size: 1rem;
  font-weight: 600;
  line-height: 1.5;
  letter-spacing: 0;
  text-wrap: balance;
}

.fit__list p {
  margin: 8px 0 0;
  color: var(--muted);
  font-size: 0.875rem;
  line-height: 1.7;
}

@media (max-width: 1024px) {
  .fit__list { gap: 24px 32px; }
}

@media (max-width: 720px) {
  .fit { margin-top: 36px; padding-top: 24px; }
  .fit__list { grid-template-columns: minmax(0, 1fr); gap: 24px; }
}

/* ==========================================================================
   70. 页头 CTA：从「填充按钮」退回「文字链接」
   --------------------------------------------------------------------------
   填充按钮是 SaaS 落地页的通用语汇。它本身没错，但摆在页头，整站的第一眼
   就落到了「又一个模板」那一档 —— 而这正是要改掉的那种观感。
   对标的几个站（Apple / OpenAI / 腾讯云）页头都只有一个安静的文字入口，
   视觉重量交给导航本身。
   仍然保留「这里能点」的信号，没有变成纯装饰：
     字重 600 + 悬停时下划线从左扫入（复用 .nav-link 已有的语汇，读者不用重新学）。
   ★ 用祖先选择器限定，不动 33 个页面的 HTML；≤1024px 时该元素本来就 display:none，
     所以这次只影响桌面端。
   ========================================================================== */
.header-actions .btn {
  position: relative;
  padding: 8px 2px;
  border: 0;
  background: transparent;
  box-shadow: none;
  color: var(--brand);
  font-weight: 600;
}

.header-actions .btn::after {
  content: "";
  position: absolute;
  left: 2px;
  right: 2px;
  bottom: 3px;
  height: 1.5px;
  background: var(--accent);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform 0.5s var(--ease);
}

.header-actions .btn:hover {
  background: transparent;
  border-color: transparent;
  color: var(--accent-ink);
  transform: none;
}

.header-actions .btn:hover::after { transform: scaleX(1); }

@media (prefers-reduced-motion: reduce) {
  .header-actions .btn::after { transition: none; }
}

/* ---------- 移动端触控与输入修正 ----------
   在 390×844 真机视口下量出来的四个问题（见 site-qa/_probe_mobile_audit.js）：
     ① .dh-panel__form input 是 14px —— **iOS 聚焦时会自动放大整个页面**，这是硬缺陷；
     ② .lang-btn 34px、③ .nav-toggle 42px、④ 案例筛选按钮 38px —— 都低于 44px 的推荐触控尺寸。
   注：这四处在 WCAG 2.5.8（最小 24×24）下都算通过，所以不是"不合规"，
   而是低于 iOS/Android 人机指南推荐的 44px —— 手指点起来容易偏。
   只在窄屏加高：桌面用鼠标，34px 的按钮更紧凑，没必要一起放大。 */
@media (max-width: 720px) {
  .dh-panel__form input { font-size: 1rem; }
  .lang-btn { height: 44px; }
  .nav-toggle { width: 44px; height: 44px; }
  .case-filter__btn { min-height: 44px; }
  .hero-link { min-height: 44px; }
}

/* ---------- 整张案例卡可点（拉伸链接）----------
   参考版把图片本身做成链接（<a class="project-image" data-project-open>）；
   我这边只有卡片标题是链接 —— 实测手机上一张卡的标题是 209×27px，
   虽然过 WCAG 2.5.8 的 24px 下限，但**手指点在卡片空白处完全没反应**，体验像「点不动」。

   做法：把标题链接的伪元素拉伸到整张卡。不新增 DOM、不动布局，
   读屏软件读到的仍然只是一个标题链接（不会变成「整卡是一个大按钮」）。
   ★ 卡内的「查看完整案例」按钮必须浮在拉伸层之上，否则会被盖住点不到。 */
.case-card { position: relative; }
.case-card h3 a::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 1;
}
.case-card .case-more { position: relative; z-index: 2; }

/* ── 核心业务满幅章节：补齐 8930 版被丢掉的细节 + 修悬停死区 ─────────────
   1) .field-credit 图注：恢复（上一轮恢复首页时漏了）
   2) .field-media img 降饱和：与 style.css 对齐，避免照片抢文字
   3) 悬停播放：.field-copy 覆盖了章节下半部，指针打不到 .field-media，
      导致「悬停整段没反应」。把非交互子元素设为 pointer-events:none，
      指针就能穿透到 .field-media；链接仍可点。
   4) 淡出静帧：.motion-on img.img-pending.is-loaded{opacity:1} 特异性(0,3,1)
      高于 .field-media.is-playing img(0,2,1)，静帧永远不淡出 —— 补一条同级的。
   ──────────────────────────────────────────────────────────────────── */
.field-credit{position:absolute;top:20px;right:24px;z-index:1;color:rgba(255,255,255,.56);font-size:.75rem;letter-spacing:.06em}
.field-media img{filter:saturate(.7) contrast(1.04)}
.field-copy{pointer-events:none}
.field-copy a,.field-copy button{pointer-events:auto}
.field-media.is-playing img.img-pending.is-loaded{opacity:0}

/* ── 数字带：做成整屏段落（滑下来刚好一屏）─────────────────────────────
   原来它是一条 248px 的薄条，夹在合作说明与客户条之间，扫过去没有存在感。
   改成 min-height:100svh + 垂直居中后，滚动到位就是完整一屏统计。
   ────────────────────────────────────────────────────────────────── */
.band{min-height:100svh;display:flex;flex-direction:column;justify-content:center}
.band-num .unit{margin-left:3px;font-size:.42em;font-weight:600;letter-spacing:0;color:var(--accent-ink)}

/* 整屏段落里数字要撑得住画面：原来 clamp(2.4rem,4.6vw,3.35rem) 只有 54px，
   在 900px 高的整屏里显得空。放大到 88px 并加大标签。 */
.band-num{font-size:clamp(3rem,6.5vw,5.5rem)}
.band-label{margin-top:20px;font-size:1rem}
.band-note{margin-top:44px}
@media (max-width:720px){
  .band-num{font-size:clamp(2.75rem,12vw,4rem)}
  .band-label{margin-top:12px;font-size:.9375rem}
  .band-note{margin-top:32px}
}

/* 数字带 · 收尾：移动端 4 行堆叠会超过一屏，改 2×2；
   英文 "8 years" 需要比中文更大的数字/单位间距。 */
.band-num .unit{margin-left:6px}
@media (max-width:720px){
  .band-grid{grid-template-columns:repeat(2,minmax(0,1fr));gap:28px 20px}
}

/* ── 行业方案页：hero 做成整屏封面 + 吸顶导航去标题并居中 ────────────────
   用户要求：① hero 像首页一样占满一屏，下滑才进入内容与吸顶导航
             ② 去掉吸顶导航左侧的「行业方案」标题，让行业标签居中
   只加 page-hero--cover 一个类，其余内页（about / cases / faq / delivery…）
   的 .page-hero 不受影响。
   ──────────────────────────────────────────────────────────────────── */
.page-hero--cover{min-height:100svh;display:flex;flex-direction:column;justify-content:center;text-align:center;padding:160px 0}
.page-hero--cover .breadcrumb{justify-content:center}
.page-hero--cover h1,.page-hero--cover .lead{margin-inline:auto}
/* 桌面：标题去掉后，用绝对定位把 CTA 固定到右侧，标签才能真正居中 */
/* 只作用于行业方案页：.localnav 在 15 个页面复用（12 个 delivery 页 + faq），
   那些页的导航左侧有页名标题，不该跟着变。
   .localnav__links 是 flex:1（占满整行），居中要加在它身上；
   加在 .localnav__inner 上无效（子项被拉伸填满，无从居中）。 */
@media (min-width:901px){
  .localnav--centered .localnav__inner{position:relative}
  .localnav--centered .localnav__links{justify-content:center}
  .localnav--centered .localnav__cta{position:absolute;right:0;top:50%;transform:translateY(-50%)}
}
@media (max-width:720px){
  .page-hero--cover{min-height:0;padding:132px 0 0;text-align:left}
  .page-hero--cover .breadcrumb{justify-content:flex-start}
}

/* ── 数字带一屏：合作方式（上）+ 统计（下）──────────────────────────────
   原来「合作说明」是独立的一条灰底 291px 薄条，紧接一整屏白底统计，
   于是出现三重突变：灰→白硬边、14px→88px 字号、291px→900px 高度，
   并且统计上方空了 339px。合并成同一屏、同一白底、同一条网格后，
   三处突变与空洞一起消失，仍然保持「刚好一整页」。

   网格对齐：统计是 repeat(4,1fr) gap:36px ⇒ 列边界 0 / 304 / 608 / 912；
   合作方式用 repeat(2,1fr) 同样 gap:36px ⇒ 列边界 0 / 608 —— 第 2 栏
   正好落在统计第 3 栏的位置，两者共享同一条栅格。
   ──────────────────────────────────────────────────────────────────── */
/* 左右两栏：左 = 计价方式（两项竖排），右 = 两段说明 —— 上半屏填满，
   不再出现「两项被拉到 1132px 两端、中间空 386px」的稀疏感。
   ★ 不要用 repeat(2,1fr) + max-width:none 去拉满（会空出 386px），
     也不要用 width:max-content 去收紧（窄容器下会溢出自己的轨道、让两项重叠）。 */
.band>.container{display:grid;grid-template-columns:calc(50% - 18px) 1fr;gap:0 36px;align-items:start}
.band .hero-commercial{grid-column:1;grid-template-columns:1fr;max-width:none;margin:0;padding-top:0;border-top:0;gap:24px}
.band .hero-commercial dt{font-size:14px}
.band .hero-commercial dd{font-size:18px}
.band .hero-fine{grid-column:2;max-width:none;margin:0;padding:0;border-top:0;text-align:left}
.band .band-grid,.band .band-note{grid-column:1/-1}
@media(max-width:720px){
  .band>.container{grid-template-columns:1fr;gap:0}
  .band .hero-commercial,.band .hero-fine,.band .band-grid,.band .band-note{grid-column:1}
  .band .hero-fine{margin-top:24px}
}
.band .hero-fine .hero-meta,.band .hero-fine .hero-cta-note{margin:0;font-size:15px;color:var(--text-2);text-wrap:pretty}
.band .hero-fine .hero-cta-note{margin-top:6px}
/* 合作方式与统计之间的分隔线 */
.band .band-grid{border-top:1px solid var(--line);margin-top:36px;padding-top:36px}
@media (max-width:720px){
  .band .hero-commercial{grid-template-columns:1fr;gap:16px}
  .band .hero-commercial dd{font-size:16px}
  .band .band-grid{margin-top:28px;padding-top:28px}
}

/* ── 行业方案页首屏：文字在上、照片墙在下 ────────────────────────────────
   为什么这么做：「文字在上 + 视觉在下」是 Stripe / Linear / Vercel 首屏的
   主流构图（Cloudflare 的方案页更彻底，直接把内容索引当首屏）。
   删掉面包屑后首屏只剩 249px 文字、占 900px 视口的 28%，背景一片空白。
   这里用 8 个行业的实景照铺满下半屏：既填了背景，又直接说出「八个行业」。
   素材复用页面下方已有的 8 张 industry-*.webp，不新增任何资源。
   ──────────────────────────────────────────────────────────────────── */
.page-hero--cover{padding:clamp(124px,17svh,160px) 0 0;justify-content:flex-start}
.page-hero--cover>.container{flex:1;display:flex;flex-direction:column;justify-content:center;padding-bottom:clamp(28px,5svh,56px)}
.page-hero__mosaic{flex:none;display:grid;grid-template-columns:repeat(4,minmax(0,1fr));grid-template-rows:repeat(2,minmax(0,1fr));height:clamp(240px,42svh,420px);overflow:hidden}
.page-hero__mosaic img{display:block;width:100%;height:100%;object-fit:cover;filter:saturate(.72) contrast(1.03)}
@media (max-width:720px){
  .page-hero--cover{padding:132px 0 0}
  .page-hero--cover>.container{padding-bottom:32px}
  .page-hero__mosaic{grid-template-columns:repeat(2,minmax(0,1fr));grid-template-rows:repeat(4,minmax(0,1fr));height:clamp(300px,44svh,440px)}
}

/* 触控目标 ≥24px（WCAG 2.2 SC 2.5.8）—— 完整版
   实测三种情形，需要三种写法：
     · .breadcrumb a          display:block        → min-height 生效
     · .footer-col a          display:inline-block → min-height 生效
     · .footer-bottom a       display:inline       → **min-height 被忽略**，
                                只能用 padding-block 撑开盒子
   行高统一 1.75（14px→24.5 / 13px→22.75，13px 的再由 min-height 兜底）。
   注：正文段落里的内联链接（如 .hero-cta-note a）按 WCAG 属 inline
   例外，不处理。 */
.breadcrumb a,.mega-a,.site-footer a{line-height:1.75}
.breadcrumb a,.site-footer a{min-height:24px}
.footer-bottom a{padding-block:2px}

/* 避让吸底标签栏：--dh-lift 由 main.js 的 initDhWidget → liftOverStickyBar 写入，
   标签栏吸底时等于它的高度，否则为 0。用 transform 而不是 bottom，
   这样不必再动各断点上已经定好的 bottom 值。 */
.dh-widget{transform:translateY(calc(var(--dh-lift,0px) * -1));transition:transform .28s var(--ease-soft)}
@media (prefers-reduced-motion:reduce){.dh-widget{transition:none}}


/* ============================================================
   工程实例库（projects.html）
   复用现有变量与栅格，只补下面这几块本项目专属的样式。
   ============================================================ */

/* 真实界面截图：保持原始宽高比，不做 object-fit 裁切 */
.proj-shot{margin:0;border:1px solid var(--line);border-radius:var(--radius);overflow:hidden;background:var(--bg-alt)}
.proj-shot img{display:block;width:100%;height:auto}

/* 项目锚点导航 */
.proj-nav{display:flex;flex-wrap:wrap;gap:8px;margin:0;padding:0;list-style:none}
.proj-nav a{display:block;padding:7px 14px;border:1px solid var(--line);border-radius:999px;
  font-size:0.875rem;line-height:1.4;color:var(--text-2);text-decoration:none;
  transition:border-color .2s var(--ease-out),color .2s var(--ease-out),background .2s var(--ease-out)}
.proj-nav a:hover{border-color:var(--accent-ink);color:var(--accent-ink);background:var(--accent-soft)}

/* 行业决策链：用一张可扫描的矩阵替代重复卡片，说明项目如何进入真实业务责任链 */
.section--industry-map{padding-top:clamp(44px,6vw,88px);padding-bottom:clamp(48px,7vw,96px);background:var(--surface-2)}
.industry-map{margin-top:30px;border-top:1px solid var(--line);border-bottom:1px solid var(--line)}
.industry-map-table{width:100%;border-collapse:collapse;table-layout:fixed;font-size:.9375rem}
.industry-map-table th,.industry-map-table td{padding:17px 16px;text-align:left;vertical-align:top;border-bottom:1px solid var(--line);line-height:1.65}
.industry-map-table thead th{padding-top:13px;padding-bottom:13px;color:var(--muted);font-size:.75rem;font-weight:600;letter-spacing:.08em;white-space:nowrap}
.industry-map-table thead th:first-child{width:13%}
.industry-map-table thead th:nth-child(2){width:23%}
.industry-map-table thead th:nth-child(3){width:22%}
.industry-map-table thead th:nth-child(4){width:24%}
.industry-map-table thead th:nth-child(5){width:18%}
.industry-map-table tbody tr{transition:background-color 180ms ease}
.industry-map-table tbody tr:hover{background:var(--accent-soft)}
.industry-map-table tbody tr:last-child th,.industry-map-table tbody tr:last-child td{border-bottom:0}
.industry-map-table tbody th{color:var(--accent-ink);font-weight:650;white-space:nowrap}
.industry-map-table tbody td{color:var(--text-2)}
.industry-map-note{margin:0;padding:18px 0 20px;color:var(--muted);font-size:.875rem;line-height:1.8}

/* 项目四段说明 */
.proj-notes{margin:24px 0 0;padding:0;list-style:none;display:grid;gap:16px}
.proj-notes li{position:relative;padding-left:16px;color:var(--text-2);font-size:0.9375rem;line-height:1.8}
.proj-notes li::before{content:"";position:absolute;left:0;top:0.68em;width:6px;height:6px;
  border-radius:50%;background:var(--accent-ink)}
.proj-notes b{color:var(--text);font-weight:600}

/* 「最硬的一块」强调块 */
.proj-hard{margin-top:26px;padding:20px 22px;border-left:3px solid var(--accent-ink);
  background:var(--bg-alt);border-radius:0 var(--radius-sm) var(--radius-sm) 0}
.proj-hard b{display:block;color:var(--accent-ink);font-size:0.75rem;font-weight:600;letter-spacing:0.06em}
.proj-hard p{margin:8px 0 0;color:var(--text-2);font-size:0.9375rem;line-height:1.8}

/* 项目之间的分隔 */
.proj-block{padding-top:var(--section-y-tight);border-top:1px solid var(--line)}

/* 技术基座 / 证据明细表 */
.spec-wrap{overflow-x:auto;-webkit-overflow-scrolling:touch}
.spec-table{width:100%;border-collapse:collapse;margin-top:8px;font-size:0.9375rem}
.spec-table th,.spec-table td{padding:13px 14px;border-bottom:1px solid var(--line);
  text-align:left;vertical-align:top}
.spec-table th{color:var(--text);font-weight:600;font-size:0.8125rem;letter-spacing:0.04em;white-space:nowrap}
.spec-table td{color:var(--text-2);line-height:1.7}
.spec-table tr:last-child td{border-bottom:0}
.spec-table code{font-size:0.875em;color:var(--text)}

@media(max-width:720px){
  .proj-hard{padding:18px 18px}
  .spec-table{font-size:0.875rem}
  .spec-table th,.spec-table td{padding:11px 10px}
  .industry-map{margin-top:24px}
  .industry-map-table,.industry-map-table tbody,.industry-map-table tr,.industry-map-table th,.industry-map-table td{display:block}
  .industry-map-table thead{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}
  .industry-map-table tbody tr{padding:17px 0;border-bottom:1px solid var(--line)}
  .industry-map-table tbody tr:last-child{border-bottom:0}
  .industry-map-table tbody th{padding:0 0 9px;border:0;font-size:1rem}
  .industry-map-table tbody td{padding:5px 0 5px 78px;border:0;position:relative;min-height:1.7em}
  .industry-map-table tbody td::before{content:attr(data-label);position:absolute;left:0;top:5px;width:68px;color:var(--muted);font-size:.75rem;font-weight:600;letter-spacing:.03em}
  .industry-map-note{padding-top:16px;font-size:.8125rem}
}

/* ══════════════════════════════════════════════════════════════════════
   2026-10-16 · 纯文字四卡行去盒子化（Apple 对齐）
   ──────────────────────────────────────────────────────────────────────
   与 home.css 的 .why-card 同一处理，理由相同（见 §32）：
   等宽、带边框、圆角、渐变底的四个小盒子 = 组件库默认形态 = 模板感来源。
   实测 1440 下每张仅 253px 宽，中文一行 ~17 字，读起来是「四张小卡片」
   而不是「一段话分四点讲」。

   ★ 作用域刻意收窄：只在 `.grid--4` 里、且**不含图片**的纯文字卡生效。
     为什么必须排除图片卡：`industries.html` 的 grid--4 是 4 张 `card--media`
     （整幅照片 + 文字叠压），那种卡必须保留实体边界，去掉盒子会让照片
     与背景糊在一起。`cases.html` 的 grid--4 是 4 张纯文字卡 —— 只改这一类。
     判据：`:not(:has(.card-media))`。

   保留卡片原有的「右上角箭头 + 整卡可点」交互（.card-link::before），
   只去掉视觉上的盒子。 */
.grid--4 > .card:not(:has(.card-media)):not(.card--media) {
  padding: 28px 0 0;
  border: 0;
  border-top: 1px solid var(--line);
  border-radius: 0;
  background: none;
}
/* 顶部的 3px --tone 色条一并收掉，避免「灰线 + 彩线」双线 */
:where(.grid--2, .grid--3, .grid--4) > .card:not(:has(.card-media)) {
  border-top: 1px solid var(--line);
}
/* 标题与正文放大一档，让文字自己撑起版面 */
.grid--4 > .card:not(:has(.card-media)) h3 {
  font-size: 1.3125rem;
  line-height: 1.45;
  letter-spacing: -0.01em;
}
.grid--4 > .card:not(:has(.card-media)) p {
  margin-top: 10px;
  font-size: 1rem;
  line-height: 1.75;
  text-wrap: pretty;
}
/* 盒子去掉后，卡内右上角的箭头失去依托（原本贴在卡片内边距上），
   移到标题行的右侧垂直居中位置，仍然是「可点」的提示。 */
.grid--4 > .card:not(:has(.card-media)) .card-link::before {
  top: 6px;
  right: 0;
}
/* 开放版式靠留白分隔 ⇒ 栏间距加大（对齐 home.css 的 #why-us 处理）
   ★★ 坑（本轮踩到，静默失效）：不要写
        .grid--4:has(> .card:not(:has(.card-media))) { gap: ... }
      —— **`:has()` 嵌在 `:has()` 里不是合法选择器**，Chrome 会把**整条规则丢弃**，
      既不报错也不警告。实测该写法 `element.matches()` 直接抛
      "is not a valid selector"。
      而 `.grid--4 > .card:not(:has(.card-media))`（`:has()` 只在 `:not()` 里）
      **是合法的** —— 已验证匹配到 4 张卡。区别就在「有没有嵌套两层 :has」。
      但 gap 必须加在**父容器**上，子元素选择器命中不到父级；
      所以这里改用「父级 :has 不含 media 卡」这一条合法的单层 :has 写法。 */
.grid--4:not(:has(.card-media)) { gap: 40px 40px; }

/* ══════════════════════════════════════════════════════════════════════
   2026-10-17 · 下拉面板：把「右侧详情」补充为有信息的版面
   ──────────────────────────────────────────────────────────────────────
   用户反馈「项目案例这个下拉还是不到要求」。
   实测根因（不是高度问题，是**右侧内容太空**）：
   | 面板 | 面板高 | 右侧内容高 | 空白 | 内容/目录比 |
   | 服务 | 486 | 162 | 324 | 39% |
   | 行业方案 | 601 | 162 | 439 | 30% |
   | 项目案例 | 601 | 162 | 439 | 30% |
   | 交付标准 | 401 | 162 | 239 | 49% |
   左侧 8 行 × 65px = 531px 把面板撑高，右侧却只有 3 行链接 + 一句导语 = 162px，
   于是右边 824×439px 是纯空白 —— 看着像「没做完」。

   修法不是继续往右侧塞链接（那会变成第二堆清单），
   而是把**站内已有的真实数据**填进去：每个案例在 cases.html 里本来就有
   客户、规模、周期、团队、4 项成果数字、标签，只是下拉里没展示。
   ⇒ 新增 3 个小类承载这些信息，全部复用现有设计令牌，不引入新色相。
   ══════════════════════════════════════════════════════════════════════ */

/* 客户与规模行：一句话交代「给谁做的、多大体量」 */
.mega-client {
  margin: -8px 0 14px;
  color: var(--muted);
  font-size: 0.8125rem;
  line-height: 1.5;
}
.mega-client b {
  color: var(--brand);
  font-weight: 600;
}

/* 成果数字：四格横排，数字用 --accent-ink（白底 5.9:1） */
.mega-stats {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 0 16px;
  margin: 4px 0 16px;
  padding: 14px 0 0;
  border-top: 1px solid var(--line);
}
.mega-stats div { min-width: 0; }
.mega-stats b {
  display: block;
  color: var(--accent-ink);
  font-size: 1.25rem;
  font-weight: 600;
  line-height: 1.15;
  letter-spacing: -0.02em;
  font-variant-numeric: tabular-nums;
}
.mega-stats span {
  display: block;
  margin-top: 4px;
  color: var(--muted);
  font-size: 0.75rem;
  line-height: 1.45;
}

/* 标签行：技术/能力关键词，与案例卡口径一致 */
.mega-tags {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin: 0 0 14px;
}
.mega-tags span {
  padding: 3px 9px;
  border: 1px solid var(--line);
  border-radius: 999px;
  color: var(--text-2);
  font-size: 0.75rem;
  line-height: 1.5;
}

/* 右侧面板内的链接组改为三列（案例/行业中「三个相关入口」并排更紧凑） */
.mega-pane .mega-cols--3 {
  grid-template-columns: repeat(3, minmax(0, 1fr));
  margin-bottom: 12px;
}
@media (max-width: 1000px) {
  .mega-pane .mega-cols--3 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

/* ══════════════════════════════════════════════════════════════════════
   2026-10-17 · 主从面板：让右侧详情在垂直方向撑满
   ──────────────────────────────────────────────────────────────────────
   改前 `.mega-split{align-items:start}` 让 `.mega-main` 只占内容高度，
   于是左侧 8 行把面板撑到 620px，右侧内容只有 305px —— 底下 315px 是空白。
   现在让 main 撑满行高，用 flex 把「相关入口」推到底部：
   顶部是客户/问题/数字，中间留白，底部是入口链接 —— 空白变成**呼吸**，
   而不是「内容没写完」。这是大厂下拉面板常见的纵向分布。
   ★ 只对 mine 内的 .mega-pane 生效，不影响左侧目录与其它组件。 */
.mega-split > .mega-main {
  display: flex;
  flex-direction: column;
  align-self: stretch;
}
.mega-split > .mega-main > .mega-pane.is-active {
  display: flex;
  flex-direction: column;
  flex: 1 1 auto;
}
/* 把末尾的「进入 XX →」推到面板底部 */
.mega-split > .mega-main > .mega-pane.is-active > .mega-more {
  margin-top: auto;
  padding-top: 12px;
}
/* 没有 .mega-more 的面板（如交付标准某些组）也要有底部留白 */
.mega-split > .mega-main > .mega-pane.is-active > .mega-cols:last-child {
  margin-bottom: 8px;
}

/* 面板内「交付前卡点」：一段正文色的短说明，把右侧详情的信息密度补足 */
.mega-pain {
  margin: 0 0 14px;
  padding: 12px 14px;
  border-left: 2px solid var(--line-strong);
  color: var(--text-2);
  font-size: 0.8125rem;
  line-height: 1.7;
}

/* 「全部 N 个案例 →」入口：左侧目录末尾的一条链接，形态接近 .mega-pick */
.mega-all {
  display: block;
  margin-top: 6px;
  padding: 12px 12px 4px;
  border-top: 1px solid var(--line);
  border-radius: 0 0 var(--radius-sm) var(--radius-sm);
  text-decoration: none;
  transition: background-color 0.2s var(--ease);
}
.mega-all:hover { background: var(--bg-alt); }
.mega-all b {
  display: block;
  color: var(--accent-ink);
  font-size: 0.875rem;
  font-weight: 600;
  line-height: 1.35;
}
.mega-all span {
  display: block;
  margin-top: 2px;
  color: var(--muted);
  font-size: 0.75rem;
  line-height: 1.45;
}
/* ══════════════════════════════════════════════════════════════════════
   2026-10-17 · 面板「相关入口」改为带边框的卡片组
   ──────────────────────────────────────────────────────────────────────
   原来三个入口是裸链接，横排在 logo 下方留出大片空白。
   改成三张等高的浅色卡片：每张有主标签 + 一句说明，
   既把纵向空间用起来，也让「同一案例的三个相关页面」有明确的归属感。
   复用既有令牌（--surface / --line / --bg-alt / --accent-ink），不引入新色。
   ---------------------------------------------------------------- */
.mega-pane .mega-cols--3 {
  gap: 10px;
  margin-top: 4px;
}
.mega-pane .mega-cols--3 .mega-a {
  display: flex;
  flex-direction: column;
  justify-content: center;
  min-height: 62px;
  padding: 10px 14px;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  background: var(--surface);
  color: var(--text-2);
  font-size: 0.8125rem;
  line-height: 1.4;
  transition: border-color 0.2s var(--ease), background-color 0.2s var(--ease);
}
.mega-pane .mega-cols--3 .mega-a:hover {
  border-color: var(--accent);
  background: var(--accent-soft);
  color: var(--accent-ink);
}
.mega-pane .mega-cols--3 .mega-a b,
.mega-pane .mega-cols--3 .mega-a:not(:has(b)) {
  font-weight: 600;
  color: var(--brand);
}

/* 让「相关入口卡片组」也贴到底部（与 .mega-more 一起构成面板下缘），
   空白集中到正文与卡片之间，看起来是刻意的分组间距而不是没写完 */
.mega-split > .mega-main > .mega-pane.is-active > .mega-cols--3 { margin-top: auto; }
.mega-split > .mega-main > .mega-pane.is-active > .mega-more { margin-top: 14px; }
