/* ============================================================
   大榆智信 ELMORA — 官网样式 v2
   品牌主色 #C1282E（取自 logo 实测）；封面渐变取自用户提供的封面图
   设计取向：编辑式排版、克制的用色、细分割线、大量留白
   ============================================================ */

:root{
  --red:#C1282E;
  --red-2:#E23A3F;
  --red-deep:#8E1418;
  --ink:#141419;
  --ink-2:#2A2A32;
  --body:#585862;
  --muted:#6E6E7A;
  --line:#E6E2E2;
  --line-2:#F0ECEC;
  --tint:#FAF8F8;
  --white:#fff;
  --maxw:1240px;
  --navh:74px;
  --ease:cubic-bezier(.22,.68,.24,1);
  /* 分层出场的节拍：同级相邻元素错开这么多毫秒 */
  --seq:88ms;
  /* 阴影一律走这两档：单层大模糊的中性黑在屏幕上是"发灰的一团"，
     双层（一小片紧贴 + 一大片带负 spread 的落影）才读作"贴着纸面"。 */
  --sh-1:0 1px 2px rgba(20,20,25,.05),0 8px 18px -10px rgba(20,20,25,.16);
  --sh-2:0 2px 4px rgba(20,20,25,.06),0 18px 34px -14px rgba(20,20,25,.22);
  /* hover 底色原来和色带共用 --tint（离白只差 2%），鼠标落上去几乎看不出，
     所以另立一档带红味的 hover 反馈。色带本身不动。 */
  --tint-hover:rgba(193,40,46,.045);
  --font:"PingFang SC","Microsoft YaHei","Hiragino Sans GB","Source Han Sans SC","Noto Sans CJK SC","WenQuanYi Micro Hei",system-ui,-apple-system,"Segoe UI",Roboto,Arial,sans-serif;
}

*,*::before,*::after{box-sizing:border-box}
html{scroll-behavior:smooth;-webkit-text-size-adjust:100%}
/* 锚点落点要让开 74px 的固定导航。之前全站 0 处 scroll-margin，
   点导航/目录跳过去时章节顶部那截大数字被导航整条盖住，
   实测落点偏差 133–151px——"点了不准"比任何配色都掉价。 */
section[id],.news-section,[id].opener{scroll-margin-top:calc(var(--navh) + 18px)}
body{margin:0;font-family:var(--font);color:var(--body);background:var(--white);font-size:16px;line-height:1.85;-webkit-font-smoothing:antialiased;overflow-x:hidden}
/* 中文断行兜底：长句走 pretty 避免最后一行只剩一两个字
   （实测目录里"…关键业绩数据展 / 示"就是这种孤字），
   两行的短句走 balance 把两行拉齐。不支持的浏览器整条忽略，不影响可读性。 */
p,li{text-wrap:pretty}
img{max-width:100%;height:auto;display:block}
a{color:inherit;text-decoration:none}
/* 全站键盘焦点环。之前只有 9 个组件自己写了 :focus-visible，
   导航、目录四格、案例卡、平台卡、资讯标题这些都能 Tab 到却没有环，
   键盘用户看不出焦点在哪——这是"不高级"里最实的一条。
   用 :where() 把特异性压到 0，后面任何组件自己的 focus 样式都能盖住它，
   所以这条只是兜底，不会把已经调好的那 9 处顶掉。 */
:where(a,button,input,summary,[tabindex]):focus-visible{
  outline:2px solid var(--red);outline-offset:3px;border-radius:2px}
/* 深色底（章节开篇带、页脚）上红环对比不足，换成白环。
   .figures 已翻成白底，所以从这条列表里拿掉了 */
.opener :where(a,button,[tabindex]):focus-visible,
.footer :where(a,button,[tabindex]):focus-visible{
  outline-color:rgba(255,255,255,.8)}
ul,ol{margin:0;padding:0;list-style:none}
h1,h2,h3,h4,h5,p,dl,dd,dt,figure{margin:0}
table{border-collapse:collapse}
.wrap{width:100%;max-width:var(--maxw);margin:0 auto;padding:0 32px}
.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0}

/* ---------- 颗粒质感 ----------
   一层极淡的噪点，压掉纯色块的"印刷平感"。
   用内联 SVG feTurbulence 生成，不引入任何图片文件；pointer-events:none 且
   z-index 低于导航/返回顶部，所以只改质感不改交互。 */
body::after{content:"";position:fixed;inset:0;z-index:80;pointer-events:none;opacity:.038;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='170' height='170' viewBox='0 0 170 170'%3E%3Cfilter id='g'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.86' numOctaves='3' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='170' height='170' filter='url(%23g)'/%3E%3C/svg%3E");
  background-size:170px 170px;background-repeat:repeat}

/* ---------- 滚动进度 ---------- */
.progress{position:fixed;left:0;top:0;height:2px;width:100%;transform:scaleX(0);transform-origin:0 50%;
  background:linear-gradient(90deg,var(--red),var(--red-2));z-index:120;transition:transform .1s linear}

/* ---------- 导航 ---------- */
.nav{position:fixed;inset:0 0 auto 0;z-index:100;height:var(--navh);background:#fff;border-bottom:1px solid var(--line-2);transition:box-shadow .3s}
.nav.is-stuck{box-shadow:var(--sh-1)}
.nav-inner{max-width:var(--maxw);margin:0 auto;padding:0 32px;height:100%;display:flex;align-items:center;justify-content:space-between;gap:24px}
.brand img{height:34px;width:auto}
.menu{display:flex;align-items:center;gap:2px}
.menu-link{position:relative;padding:10px 18px;font-size:15px;color:#43434D;transition:color .22s}
.menu-link::after{content:"";position:absolute;left:18px;right:18px;bottom:2px;height:2px;background:var(--red);
  transform:scaleX(0);transform-origin:0 50%;transition:transform .3s var(--ease)}
.menu-link:hover{color:var(--ink)}
.menu-link:hover::after,.menu-link.is-active::after{transform:scaleX(1)}
.menu-link.is-active{color:var(--red);font-weight:600}
.burger{display:none;width:40px;height:40px;border:0;background:transparent;cursor:pointer;padding:11px;flex-direction:column;justify-content:space-between}
.burger span{display:block;height:2px;background:var(--ink);transition:transform .26s,opacity .2s}
.burger.is-open span:nth-child(1){transform:translateY(8px) rotate(45deg)}
.burger.is-open span:nth-child(2){opacity:0}
.burger.is-open span:nth-child(3){transform:translateY(-8px) rotate(-45deg)}

/* ---------- 首屏（对齐用户提供的封面图） ---------- */
.hero{
  position:relative;overflow:hidden;color:#fff;
  min-height:clamp(560px,64vw,860px);
  background:
    radial-gradient(110% 80% at 100% 100%, rgba(48,0,0,.62) 0%, rgba(48,0,0,0) 58%),
    radial-gradient(80% 60% at 12% 0%, rgba(255,180,170,.28) 0%, rgba(255,180,170,0) 60%),
    linear-gradient(to bottom,#FF0000 0%,#FA0000 18%,#E80000 42%,#C00000 64%,#940000 84%,#720000 100%);
}
.hero::after{content:"";position:absolute;inset:0;pointer-events:none;
  background:radial-gradient(70% 55% at 74% 46%, rgba(255,255,255,.13) 0%, rgba(255,255,255,0) 62%)}
/* 缓慢漂移的光晕：两团暖光错开周期呼吸，给纯色渐变一点空气 */
.hero::before{content:"";position:absolute;inset:-14%;pointer-events:none;
  background:
    radial-gradient(34% 42% at 28% 38%, rgba(255,220,205,.26) 0%, rgba(255,220,205,0) 70%),
    radial-gradient(26% 34% at 74% 68%, rgba(255,255,255,.15) 0%, rgba(255,255,255,0) 72%);
  animation:bloom 26s ease-in-out infinite alternate}
@keyframes bloom{
  0%{transform:translate3d(-2.2%,1.4%,0) scale(1)}
  50%{transform:translate3d(2.6%,-1.8%,0) scale(1.07)}
  100%{transform:translate3d(-1%,2.4%,0) scale(1.02)}
}
.hero-inner{
  position:relative;z-index:1;width:min(1400px,100%);margin:0 auto;
  padding:calc(var(--navh) + 46px) 56px 64px;
  min-height:inherit;
  display:grid;grid-template-columns:minmax(0,1.08fr) minmax(0,.92fr);
  grid-template-rows:auto 1fr auto;gap:20px 32px;
}
.hero-lockup{grid-area:1/1/2/2;align-self:start;justify-self:start;height:42px;width:auto;opacity:.96}
.hero-head{grid-area:2/1/3/2;align-self:center}
.hero-title{font-size:clamp(48px,7.2vw,96px);font-weight:800;line-height:1.04;letter-spacing:clamp(2px,.3vw,4px);
  text-shadow:0 18px 44px rgba(60,0,0,.35)}
/* 首屏唯一的标题：2026-10-10 他要"单行、位置不变、更突出、更高级、带 3D"。
   —— 更突出（先把字号这件事做对）：上一版按视口宽推 3.9vw，实测两端都偏——
      手机上只有 17px 而左栏还空着 114px；≥1025px 两列时文字反而比栏宽挤出 5px。
      单行的上限只取决于它所在那一栏的宽度，所以改成按容器量：.hero-head 给
      container-type:inline-size，字号走 8.1cqw。系数是倒推的：56px 字号下 11 个字的
      行盒实测 683px（=12.2 倍字号），1/12.2≈8.2% 再留一点余量 = 8.1%。
      结果：390px 手机 17→28px，1440px 桌面 55px 且回到栏内不再挤中缝。
      容器查询不支持时退回到下面那条 vw clamp，不会出现取不到字号。
   —— 3D：十六层挤出。同样 10px 的厚度，9 层（每层 1.1px）能看出一道道台阶，
      像 WordArt；16 层（每层 0.6px）壁面就是一条连续的渐变，读作实心材质。
      竖直走得比水平快（光在上偏左，厚度往下坠），色阶 #C8262C→#3A060B，
      最后叠一道落地软影；整个字面用 perspective + rotateY/rotateX 缓慢来回转，
      厚度跟着转，所以读作一块实心的字在动，不是贴纸。
      挤出量 --d3 用 .016em（下限 .4px）而不是写死 1px：16 层的总厚度是 9×d3，
      写死像素的话 28px 字号上会挤出 9px 的墙（比笔画本身还粗一倍），字被淹掉；
      按 .016em 走，厚度≈笔画的 1.15 倍，桌面和手机上同一个比例。
   —— 为什么字面是纯白而不是渐变：试过把渐变裁进字形（background-clip:text），
      实测无效——元素背景画在 text-shadow 之下，十几层挤出会把渐变面整个盖掉。
      对照量过：同一行字，只加一层 2px 实心 text-shadow，被裁进字形的绿色覆盖率
      就从 36% 掉到 18%。所以字面必须是真正不透明的 color 填充，光感受交给
      背后的暗垫和挤出的色阶去做。
   注意：这个元素已从 main.js 的切行名单里摘掉——切行套的 .ln 是 overflow:hidden，
   会把这一圈挤出阴影直接裁掉。 */
.hero-sub{position:relative;font-size:clamp(17px,3.9vw,56px);font-weight:800;letter-spacing:.02em;line-height:1.16;
  white-space:nowrap;transform-origin:50% 62%;color:#fff;
  --d3:max(.3px,.016em);
  text-shadow:
    calc(var(--d3)*.43) calc(var(--d3)*.56) 0 #BF242A,
    calc(var(--d3)*.86) calc(var(--d3)*1.12) 0 #B62228,
    calc(var(--d3)*1.29) calc(var(--d3)*1.68) 0 #AE2026,
    calc(var(--d3)*1.72) calc(var(--d3)*2.24) 0 #A51E24,
    calc(var(--d3)*2.15) calc(var(--d3)*2.80) 0 #9C1C22,
    calc(var(--d3)*2.58) calc(var(--d3)*3.36) 0 #931A1F,
    calc(var(--d3)*3.01) calc(var(--d3)*3.92) 0 #8A181D,
    calc(var(--d3)*3.44) calc(var(--d3)*4.48) 0 #81161B,
    calc(var(--d3)*3.87) calc(var(--d3)*5.04) 0 #781419,
    calc(var(--d3)*4.30) calc(var(--d3)*5.60) 0 #6F1217,
    calc(var(--d3)*4.73) calc(var(--d3)*6.16) 0 #671015,
    calc(var(--d3)*5.16) calc(var(--d3)*6.72) 0 #5E0E13,
    calc(var(--d3)*5.59) calc(var(--d3)*7.28) 0 #550C11,
    calc(var(--d3)*6.02) calc(var(--d3)*7.84) 0 #4C0A0F,
    calc(var(--d3)*6.45) calc(var(--d3)*8.40) 0 #43080D,
    calc(var(--d3)*6.88) calc(var(--d3)*8.96) 0 #3A060B,
    max(2px,.16em) max(5px,.3em) max(12px,.6em) rgba(24,0,0,.5);
  animation:hero3d 9s ease-in-out infinite alternate}
@supports (container-type:inline-size){
  .hero-head{container-type:inline-size}
  .hero-sub{font-size:clamp(19px,8.1cqw,60px)}
}
/* 2026-10-10 他要"再大一点、还是一行、位置不变"。单行的天花板就是栏宽，
   而 8.1cqw 已经把栏用满了（390px 上文字 347/栏 350，只剩 3px）——手机上没有余量。
   桌面右边可借多少，取决于树标在它那一栏里往右缩进了多少：
     col2 = (视口 − 144) × 0.46，树标宽 = min(col2, 470)，中缝 32px；
     1025px：col2 只有 405，树标把整栏占满 → 除了那道缝没有余量；
     1440px：col2 有 578，树标只吃 470 → 缝外还多出 108。
   所以可借量 = 32 + max(0, col2 − 470) − 25（留 25px 给光晕和呼吸），
   化简就是 clamp(7px, 46vw − 529.2px, 115px)。写成随 vw 连续走而不是几个断点，
   是为了避免拖窗口时在 1280 上出现 15% 的字号跳档。
   坑记一笔：这里必须写 46vw 不能写 0.46vw——CSS 里 0.46vw 是"视口的 0.46%"
   （1025px 上只有 4.7px），而且合法、不报错，clamp 会一直贴在 7px 下限上，
   看上去就像"改了没反应"。
   容器的 inline-size 跟着变宽，cqw 量的是容器，字号自己涨上去：
   字仍然一行、左边缘一个像素没动。字号上限 60px 是最后一道保险，
   ≥1400px 之后由它封顶，多借出来的宽度正好变成净距。
   只在两列布局生效：单列时右边没有缝可借，负边距会顶穿页面内边距。
   100vw 含滚动条，比容器实际宽度多约 17px → 最坏情况多借 7.8px。
   实测（hero_clear.js，量的是字尾到光晕左沿）：1025/1060/1100/1180/1240/1280 净距
   恒为 21px（我留的 25px 被光晕超出 stage 的 2% 吃掉 4px），1366 起 40px，
   1440 及以上 74px；字号 1025→39.1px、1280→54.5px、1440→60px（受上限封顶）。 */
@media (min-width:1025px){
  .hero-head{margin-right:calc(clamp(7px, 46vw - 529.2px, 115px) * -1)}
}
/* 字后压一层暗垫。实测（把字擦成透明、去掉挤出，只量同一块矩形的底；
   注意不能用 visibility:hidden 藏字，那会连伪元素一起藏掉，量出来三条一样）：
   无垫 底均色 rgb(230,34,32)、白字对比 4.56:1；有垫 rgb(206,29,28)、5.49:1；
   垫子加倍 rgb(191,27,25)、6.21:1——再深就开始看出一个黑团而不是一层空气了，停在 .34。
   WCAG 大号字的 AA 线是 3:1，所以这不是合规问题，是让白字从红底里"浮"出来。
   垫子挂在 .hero-sub 而不是 .hero-head 上：.hero-head 还包含下面那道线，
   挂在它身上时垫子的下沿会拖到文字下面一大截，手机上看得很清楚是一块脏影。
   .hero-sub 有 transform，本身就是层叠上下文，所以 z-index:-1 只会落到文字之下。 */
.hero-sub::before{content:"";position:absolute;z-index:-1;pointer-events:none;
  left:0;right:0;top:-16%;bottom:-24%;
  background:radial-gradient(74% 58% at 50% 46%,rgba(52,0,0,.34) 0%,rgba(52,0,0,.15) 52%,rgba(52,0,0,0) 78%)}
/* 小屏把墙再收薄一档。--d3 本来就按字号等比走，比例没变，但 28px 的字笔画只有 3px，
   同样 1.15 倍的墙落在这么少的像素上会糊成一团黑。收到 .012em（约笔画的 0.9 倍），
   读起来仍是实心的一块，只是不糊字。 */
@media (max-width:640px){
  .hero-sub{--d3:.012em}
}
@keyframes hero3d{
  from{transform:perspective(900px) rotateY(-6.5deg) rotateX(2.4deg)}
  to{transform:perspective(900px) rotateY(6.5deg) rotateX(-2.4deg)}
}
/* 标题下那道线跟着加粗到 2px 并收成一个渐隐的尾巴：1px 的匀质细线
   压不住现在这块 3D 字面，读起来像漏了一条边。 */
.hero-rule{display:block;width:min(430px,68%);height:2px;margin-top:38px;
  background:linear-gradient(90deg,rgba(255,255,255,.94),rgba(255,255,255,.18) 82%,rgba(255,255,255,0))}
.hero-en{grid-area:3/1/4/2;align-self:end;font-size:clamp(34px,5.2vw,68px);font-weight:800;letter-spacing:-.012em;line-height:1;
  text-shadow:0 14px 34px rgba(60,0,0,.3)}
/* 他给的新英文口号整句有 47 个字符，和 ELMORA 一样大的话在 678px 的左栏里要排三行，
   首屏会被撑破。所以拆成两级：ELMORA 保持原字号当品牌字，破折号起接的这句走小字＋宽字距。
   字符一个没删也没改，只是换了排法——破折号留在第二行行首，读序仍是"ELMORA — Rooted…"。
   字号这里用独立 clamp 而不是 .3em：em 会跟着 34px 的最小档缩到 10px 以下，手机上读不了。 */
.hero-en-sub{display:block;margin-top:.36em;font-size:clamp(13px,1.5vw,21px);font-weight:600;
  letter-spacing:.16em;line-height:1.5;text-shadow:0 6px 18px rgba(60,0,0,.28)}
.hero-tag{grid-area:3/2/4/3;align-self:end;justify-self:end;text-align:right;position:relative;padding-bottom:16px;
  font-size:12px;letter-spacing:2.2px;opacity:.9}
.hero-tag::after{content:"";position:absolute;right:0;bottom:0;width:min(280px,100%);height:1px;background:rgba(255,255,255,.6)}
.hero-mark{grid-area:1/2/3/3;align-self:center;justify-self:end;width:min(100%,470px);
  /* 视差：JS 按滚动比例写 --par，用独立的 translate 属性，
     这样不会覆盖 transform 上的浮动动画，两者叠加而不是互相取消 */
  translate:0 var(--par,0px);
  filter:drop-shadow(0 30px 60px rgba(50,0,0,.4));
  animation:drift 9s ease-in-out infinite}
@keyframes drift{0%,100%{transform:translateY(0)}50%{transform:translateY(-16px)}}
@keyframes heroFade{from{opacity:0;scale:.965}to{opacity:1;scale:1}}
@keyframes heroRise{from{opacity:0;translate:0 20px}to{opacity:1;translate:none}}
@keyframes ruleGrow{from{transform:scaleX(0)}to{transform:scaleX(1)}}
/* 首屏分层入场：字标 → 主标题 → 副标 → 短线 → 英文 → 角标，各走各的节拍 */
.js .hero-lockup,.js .hero-title,.js .hero-sub,.js .hero-en,.js .hero-tag,.js .hero-mark,.js .hero-scroll{opacity:0}
.js .hero-lockup{animation:heroRise .95s var(--ease) .05s both}
.js .hero-title{animation:heroRise .95s var(--ease) .16s both}
/* 入场 heroRise 走 translate，3D 摆动 hero3d 走 transform，两条各管一个属性，
   并列写在同一个 animation 列表里互不覆盖；只写一条的话，
   .js .hero-sub 的特异性高于 .hero-sub，会把 3D 那条整个吃掉。 */
.js .hero-sub{animation:heroRise .95s var(--ease) .3s both,hero3d 9s ease-in-out infinite alternate}
.js .hero-rule{transform:scaleX(0);transform-origin:0 50%;animation:ruleGrow 1.1s var(--ease) .46s both}
.js .hero-en{animation:heroRise .95s var(--ease) .5s both}
.js .hero-tag{animation:heroRise .95s var(--ease) .62s both}
.js .hero-mark{animation:heroFade 1.3s var(--ease) .28s both,drift 9s ease-in-out infinite}
.js .hero-scroll{animation:heroFade .8s var(--ease) 1.1s both}
.hero-scroll{position:absolute;left:50%;bottom:22px;transform:translateX(-50%);z-index:2;
  width:24px;height:40px;border:1.5px solid rgba(255,255,255,.5);border-radius:12px;display:flex;justify-content:center}
.hero-scroll span{width:2px;height:8px;margin-top:7px;border-radius:2px;background:#fff;animation:tick 1.8s ease-in-out infinite}
@keyframes tick{0%{opacity:0;transform:translateY(0)}35%{opacity:1}100%{opacity:0;transform:translateY(13px)}}

/* ---------- 通用节奏 ----------
   纵向节奏刻意拉开：常规段最松，tint 段收紧一档，深色带和章节开篇再拉开，
   相邻两段不再同一密度。 */
.section{padding:clamp(88px,10.4vw,146px) 0;position:relative}
.section-tint{background:var(--tint);padding:clamp(70px,7.8vw,110px) 0}
.block-head{max-width:880px;margin-bottom:clamp(46px,5.8vw,80px)}
.block-head.center{text-align:center;margin-left:auto;margin-right:auto}
.kicker{display:inline-flex;align-items:center;gap:10px;font-size:12.5px;font-weight:700;letter-spacing:2.6px;
  color:var(--red);text-transform:uppercase;margin-bottom:18px}
.kicker::before{content:"";width:26px;height:2px;background:var(--red);opacity:.6}
.block-head.center .kicker{justify-content:center}
.block-head.center .kicker::before{display:none}
/* 大字号中文标题收紧：原来 .5px/1px 的松字距在 40px+ 上会显散 */
.block-title{font-size:clamp(26px,3.5vw,44px);line-height:1.24;font-weight:800;color:var(--ink);letter-spacing:0}
.title-inv{color:#fff}
.block-note{display:inline-block;margin-top:20px;font-size:13.5px;font-weight:700;letter-spacing:2px;color:var(--red);
  padding-left:14px;border-left:2px solid var(--red)}
.display{font-size:clamp(28px,3.8vw,48px);line-height:1.22;font-weight:800;color:var(--ink);letter-spacing:-.005em}
.prose{font-size:16.5px;line-height:2.05;color:var(--body);text-align:justify}
.statement{margin-top:clamp(52px,6vw,84px);padding-top:32px;border-top:1px solid var(--line);
  text-align:center;font-size:clamp(17px,2vw,24px);font-weight:700;letter-spacing:1.4px;color:var(--red-deep)}
.statement-inv{color:#fff;border-top-color:rgba(255,255,255,.18)}

/* ---------- 内容索引 ----------
   2026-10-10 他点名的两处小改，别的一律没动：
   ① 序号放大成实色红的大字（不是上一版那种空心描边大字）；
   ② 四条上面压一条粗红线，替掉原来那道 1px 灰线。 */
.index{padding-top:clamp(84px,10vw,132px)}
.index-grid{display:grid;grid-template-columns:repeat(4,1fr);border-top:5px solid var(--red)}
.index-item{position:relative;display:block;padding:38px 26px 34px;border-right:1px solid var(--line);
  transition:background .35s var(--ease)}
.index-item:last-child{border-right:0}
/* 粗红线已经压在整条边上了，悬停那道线改成从粗线往下再补一段，才不至于红盖红看不见 */
.index-item::before{content:"";position:absolute;left:0;right:0;top:-5px;height:5px;background:var(--red-deep);
  transform:scaleX(0);transform-origin:0 50%;transition:transform .4s var(--ease)}
.index-item:hover{background:var(--tint-hover)}
.index-item:hover::before{transform:scaleX(1)}
.index-num{display:block;font-size:clamp(40px,3.9vw,54px);line-height:1;font-weight:800;letter-spacing:-1px;
  color:var(--red);opacity:.55;
  transition:opacity .35s var(--ease),transform .4s var(--ease)}
.index-item h3{margin-top:20px;font-size:23px;font-weight:800;color:var(--ink);letter-spacing:.4px;
  transition:transform .42s var(--ease)}
.index-item p{margin-top:14px;font-size:14px;line-height:1.95;color:var(--muted);transition:transform .48s var(--ease)}
.index-go{position:absolute;right:24px;bottom:26px;font-size:17px;color:var(--red);
  opacity:0;transform:translateX(-10px);transition:.35s var(--ease)}
.index-item:hover .index-go{opacity:1;transform:none}
/* 悬停：序号上浮、标题走一点、说明走更多，三段不同速 */
.index-item:hover .index-num{opacity:1;transform:translateY(-4px)}
.index-item:hover h3{transform:translateX(6px)}
.index-item:hover p{transform:translateX(11px)}

/* ---------- 章节开篇 ---------- */
.opener{position:relative;background:var(--ink);color:#fff;overflow:hidden}
.opener::before{content:"";position:absolute;inset:0;
  background:radial-gradient(60% 120% at 88% 50%, rgba(193,40,46,.42) 0%, rgba(193,40,46,0) 62%)}
.opener-inner{position:relative;display:flex;align-items:center;gap:clamp(28px,5vw,68px);
  padding-top:clamp(74px,9vw,120px);padding-bottom:clamp(74px,9vw,120px)}
.opener-num{flex:none;font-size:clamp(76px,12vw,176px);font-weight:800;line-height:.82;letter-spacing:-4px;
  color:transparent;-webkit-text-stroke:1.5px rgba(255,255,255,.34);
  /* 描边"被画出来"靠这条带软边的遮罩横扫：入场时遮罩从右往左移，
     同时 -webkit-text-stroke-width 由 0 涨到 1.5px，读起来像笔尖沿轮廓走字 */
  -webkit-mask-image:linear-gradient(100deg,#000 0 46%,rgba(0,0,0,.32) 60%,transparent 72%);
  mask-image:linear-gradient(100deg,#000 0 46%,rgba(0,0,0,.32) 60%,transparent 72%);
  -webkit-mask-size:230% 100%;mask-size:230% 100%;
  -webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;
  /* 静止位就是"已经画完"（0 0）：没 JS 时数字整颗都在。
     未进场的起手位由下面 .js .opener:not(.is-in) 那条规则给。 */
  -webkit-mask-position:0 0;mask-position:0 0}
.opener-body{max-width:760px}
.opener-title{font-size:clamp(26px,3.6vw,46px);font-weight:800;letter-spacing:0;line-height:1.18}
.opener-lede{margin-top:18px;font-size:clamp(14.5px,1.7vw,19px);line-height:1.85;letter-spacing:.4px;color:rgba(255,255,255,.72)}
.opener-body::after{content:"";display:block;width:56px;height:2px;background:var(--red-2);margin-top:26px;
  transform:scaleX(0);transform-origin:0 50%;transition:transform .9s var(--ease) .45s}
/* 入场：描边数字先落笔，标题跟上，导语再跟，最后红杠向右生长 */
.js .opener:not(.is-in) .opener-num,
.js .opener:not(.is-in) .opener-title,
.js .opener:not(.is-in) .opener-lede{opacity:0}
.opener.is-in .opener-num{animation:numDraw 1.5s var(--ease) both}
.opener.is-in .opener-title{animation:seqRise .85s var(--ease) .2s both}
.opener.is-in .opener-lede{animation:seqRise .85s var(--ease) .38s both}
.opener.is-in .opener-body::after{transform:scaleX(1)}
@keyframes numDraw{
  0%{opacity:0;-webkit-text-stroke-width:0px;translate:0 16px;
    -webkit-mask-position:100% 0;mask-position:100% 0}
  22%{opacity:1}
  100%{opacity:1;-webkit-text-stroke-width:1.5px;translate:none;
    -webkit-mask-position:0 0;mask-position:0 0}
}

/* ---------- 公司介绍 ---------- */
.about{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1.02fr);gap:clamp(48px,6vw,88px);align-items:start}
.about-main .display{margin-bottom:8px}
.sub-h{margin-top:clamp(38px,4vw,54px);font-size:15px;font-weight:800;letter-spacing:3px;color:var(--red);
  padding-bottom:14px;border-bottom:1px solid var(--line)}
.about-main .prose{margin-top:24px}
.mv{margin-top:38px;border-top:1px solid var(--line)}
.mv-row{display:grid;grid-template-columns:132px 1fr;gap:24px;padding:24px 0;border-bottom:1px solid var(--line);
  transition:background .35s var(--ease)}
.mv-row:hover{background:var(--tint-hover)}
.mv-row dt{display:flex;align-items:center;gap:10px;font-size:17px;font-weight:800;color:var(--ink);letter-spacing:1px;
  transition:color .3s var(--ease)}
.mv-row:hover dt{color:var(--red)}
.mv-row dt img{width:22px;height:auto}
.mv-row dd{font-size:15px;line-height:1.95;color:var(--body)}
.about-caps{border-top:1px solid var(--line)}
.cap{position:relative;display:grid;grid-template-columns:64px 1fr;gap:20px;align-items:start;padding:30px 0;
  border-bottom:1px solid var(--line)}
/* 悬停：序号整体右移让出一条红签，标题走 6px、正文走 11px，行本身不动 */
.cap::before{content:"";position:absolute;left:0;top:39px;width:10px;height:2px;background:var(--red);
  transform:scaleX(0);transform-origin:0 50%;transition:transform .42s var(--ease)}
.cap:hover::before{transform:scaleX(1)}
.cap-idx{font-size:14px;font-weight:800;letter-spacing:1px;color:var(--red);opacity:.5;padding-top:6px;
  transition:transform .42s var(--ease),opacity .42s var(--ease)}
.cap h4{font-size:19px;font-weight:800;color:var(--ink);letter-spacing:1px;transition:transform .46s var(--ease)}
.cap p{margin-top:10px;font-size:15px;line-height:1.95;color:var(--body);transition:transform .52s var(--ease)}
.cap:hover .cap-idx{transform:translateX(16px);opacity:1}
.cap:hover h4{transform:translateX(6px)}
.cap:hover p{transform:translateX(11px)}

/* ---------- 业绩数据（浅色数据带） ----------
   2026-10-10：这块原本是深色带，和紧跟其后的「02 市场洞察」开篇带连成一片，
   他两次圈出来。先试了把深色抬一档（#252530 对 #141419）仍然读作粘在一起，
   最终按他的意思翻成和上面一样的白底——深色从此只留给四个章节开篇带和页脚。
   整带从深翻浅，跟着一起翻的一串：格子底色、1px 缝、数字/标题/注释字色、
   后缀的浅粉、kicker 的浅粉、深色专用的那团红晕、以及深色用的白色焦点环。 */
.figures{position:relative;background:#fff;color:var(--body);padding:clamp(88px,10vw,142px) 0;overflow:hidden}
.figures .wrap{position:relative}
/* 与 .block-head 同一套值：同一个段头不该有两套留白 */
.block-head-dark{margin-bottom:clamp(46px,5.8vw,80px)}
/* .kicker-red 那个浅粉是给深色底配的，这里按容器局部改回品牌红——
   不能直接动 .kicker-red 本身，「生态概览」那块深色带还在用它 */
.figures .kicker-red{color:var(--red)}
.figures .kicker-red::before{background:var(--red)}
.kicker-red{color:#FF8E92}
.kicker-red::before{background:#FF8E92}
/* 格子从"靠 1px 缝隙分隔"改成独立卡片：灰底 + 描边 + 沿边框流动的一道光，
   内容整体居中。缝隙法不再需要，换成真正的间距让卡片之间透气。 */
.fig-grid{display:grid;grid-template-columns:repeat(4,1fr);gap:clamp(12px,1.4vw,20px)}
/* 7 个格子铺不满 4 列，末尾会露出一块空格。
   让最后一格（累计保费 GMV）横向占两列补上，两列断点下同样刚好填满。 */
@media (min-width:601px){
  .fig-grid > .fig:last-child{grid-column:span 2}
}
.fig{position:relative;background:#F4F1F1;border:1px solid var(--line);
  padding:clamp(30px,3vw,40px) 24px;text-align:center;
  transition:background .4s var(--ease),border-color .4s var(--ease)}
.fig:hover{background:#fff;border-color:rgba(193,40,46,.42)}
/* 沿边框跑的那道光：一个 2px 厚的渐变环。两层遮罩相减只留边线那一圈，
   背景横向位移就读作"灯带在边框上走"；中心被挖空，绝不糊住格子里的字。
   每格按列错开 0.6s 起步，整排读作一道光从左往右扫过去，而不是七盏各闪各的。
   —— 灯带颜色：我提过 RGB 七色是电竞硬件的语言、和全站单一主色打架，
   他看过红色版之后明确要七彩，那就七彩。别再换回红色，也别再提这个建议。
   两头各留一段透明过渡，让它读作"一道光扫过去"而不是"给卡片套了个彩虹框"。
   —— 挂在这条规则上的是全站所有"自带描边的独立卡片"：业绩数据格 .fig、
      案例卡 .case、准入 .admit、材料 .doc。
      刻意不给 .platform / .step / .news-card / .index-item：那些是"1px 缝隙画分隔线"
      的紧挨网格，环会糊到邻格身上；要加得先把它们改成有间距的卡片，那是重排。
      .mode 也不加——它 overflow:hidden 会把环裁掉一半，且自身已是饱和红/墨渐变。 */
.fig::after,.case::after,.admit::after,.doc::after{
  content:"";position:absolute;inset:-1px;pointer-events:none;padding:2px;
  background:linear-gradient(100deg,
    rgba(255,255,255,0) 0%,
    rgba(124,58,237,.8) 28%,rgba(37,99,235,.9) 34%,rgba(14,165,233,.95) 40%,
    rgba(16,185,129,.95) 45%,rgba(163,230,53,.95) 50%,rgba(250,204,21,.95) 55%,
    rgba(249,115,22,.95) 60%,rgba(239,68,68,.9) 66%,rgba(236,72,153,.8) 72%,
    rgba(255,255,255,0) 82%) no-repeat;
  background-size:260% 100%;
  /* 两层遮罩相减只留边线那一圈。两个坑都实测踩过：
     ① 简写里只写一个 padding-box 时，它被当成 mask-origin，mask-clip 仍是默认的
        border-box，于是两层遮罩完全重合，相减之后一个像素都不剩（灯带完全不出现，
        把渐变涂成纯红也看不见）。必须把 mask-clip 显式写成 content-box, border-box。
     ② 两层都要 no-repeat，否则实心遮罩会平铺满整格，同样相减为空。 */
  -webkit-mask-image:linear-gradient(#000 0 0),linear-gradient(#000 0 0);
          mask-image:linear-gradient(#000 0 0),linear-gradient(#000 0 0);
  -webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;
  -webkit-mask-clip:content-box,border-box;mask-clip:content-box,border-box;
  -webkit-mask-composite:destination-out;
          mask-composite:exclude;
  animation:figFlow 6s linear infinite}
@keyframes figFlow{from{background-position:130% 0}to{background-position:-130% 0}}
/* 按列错开起步相位：整排读作一道光从左扫到右，而不是七盏各闪各的 */
.fig:nth-child(4n+2)::after{animation-delay:-.6s}
.fig:nth-child(4n+3)::after{animation-delay:-1.2s}
.fig:nth-child(4n)::after{animation-delay:-1.8s}
/* 案例 / 准入 / 材料都是两列卡，右列错开半拍，免得两边完全同步 */
.case:nth-child(2n)::after,.admit:nth-child(2n)::after,.doc:nth-child(2n)::after{animation-delay:-1.5s}
.fig:hover::after,.case:hover::after,.admit:hover::after,.doc:hover::after{animation-duration:2.6s}
/* 数字加大光学重量：字号涨一档、字距收紧、等宽数字防止滚动时抖动 */
.fig strong{display:block;font-size:clamp(38px,5vw,64px);font-weight:800;line-height:.98;letter-spacing:-.035em;
  color:var(--ink);font-variant-numeric:tabular-nums;transition:transform .5s var(--ease)}
.fig strong i{font-style:normal;font-variant-numeric:tabular-nums}
/* 后缀（+ / % / 万+ / 亿+）比数字晚到一步，让数字先站住 */
.fig-suf{display:inline-block;margin-left:.05em;font-size:.44em;font-weight:700;letter-spacing:0;line-height:1;
  color:var(--red);vertical-align:.66em;transition:transform .5s var(--ease)}
.fig.is-in .fig-suf{animation:sufArrive .62s var(--ease) 1.05s both}
@keyframes sufArrive{from{opacity:0;translate:0 .34em}to{opacity:1;translate:none}}
.fig h4{margin-top:24px;font-size:15px;font-weight:700;color:var(--ink);letter-spacing:.5px;
  transition:transform .5s var(--ease)}
.fig p{margin-top:8px;font-size:13px;color:var(--muted);transition:transform .5s var(--ease) .05s}
/* 悬停：数字、标题、注释各走各的量，整格不平移 */
.fig:hover strong{transform:translateY(-4px)}
.fig:hover h4{transform:translateX(5px)}
.fig:hover p{transform:translateX(9px)}
.fig:hover .fig-suf{transform:translateY(-3px)}

/* ---------- 行业痛点 ---------- */
.pain-grid{display:grid;grid-template-columns:1fr 1fr;gap:1px;background:var(--line);border:1px solid var(--line)}
.pain{position:relative;background:#fff;padding:clamp(32px,3.6vw,46px);overflow:hidden;transition:background .3s}
.pain:hover{background:var(--tint-hover)}
.pain-ghost{position:absolute;right:18px;top:2px;font-size:78px;font-weight:800;line-height:1;
  color:var(--red);opacity:.07;letter-spacing:-3px;transition:opacity .35s,transform .35s var(--ease)}
.pain:hover .pain-ghost{opacity:.14;transform:translateY(4px)}
.pain h4{position:relative;font-size:20px;font-weight:800;color:var(--ink);letter-spacing:.5px;padding-bottom:16px;
  transition:transform .42s var(--ease)}
.pain h4::after{content:"";position:absolute;left:0;bottom:0;width:32px;height:2px;background:var(--red);
  transition:width .42s var(--ease)}
.pain p{margin-top:16px;font-size:15px;line-height:1.95;color:var(--body);transition:transform .5s var(--ease)}
/* 悬停：幽灵序号上浮、标题走一点、正文走更多、红杠拉长 */
.pain:hover h4{transform:translateX(6px)}
.pain:hover h4::after{width:56px}
.pain:hover p{transform:translateX(10px)}

/* ---------- 解决方案 ---------- */
.solve{display:grid;grid-template-columns:minmax(0,1.05fr) minmax(0,.95fr);gap:clamp(40px,5vw,72px);align-items:center}
.solve-list{display:grid;gap:8px}
.solve-item{display:grid;grid-template-columns:56px 1fr;gap:22px;align-items:start;
  padding:28px 0;border-bottom:1px solid var(--line)}
.solve-item:first-child{border-top:1px solid var(--line)}
.solve-item img{width:38px;height:auto;margin-top:4px;transition:transform .4s var(--ease)}
.solve-item h4{font-size:20px;font-weight:800;color:var(--ink);letter-spacing:.5px;transition:transform .4s var(--ease)}
.solve-item p{margin-top:12px;font-size:15px;line-height:1.95;color:var(--body);transition:transform .46s var(--ease)}
.solve-item:hover img{transform:translateX(-4px) scale(1.06)}
.solve-item:hover h4{transform:translateX(7px)}
.solve-item:hover p{transform:translateX(11px)}
.solve-list .statement{margin-top:34px;padding-top:0;border-top:0;text-align:left;color:var(--red-deep);letter-spacing:1px}
.solve-art{padding:clamp(24px,3vw,44px);background:#fff;border:1px solid var(--line)}
.solve-art img{width:100%}

/* ---------- 三大平台 ---------- */
.platform-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:1px;background:var(--line);border:1px solid var(--line)}
.platform{background:#fff;padding:clamp(32px,3.2vw,44px) clamp(26px,2.6vw,34px);position:relative;transition:background .3s}
.platform::before{content:"";position:absolute;left:0;top:0;width:100%;height:3px;background:var(--red);
  transform:scaleX(0);transform-origin:0 50%;transition:transform .45s var(--ease)}
.platform:hover{background:var(--tint-hover)}
.platform:hover::before{transform:scaleX(1)}
.platform h4{text-align:center;font-size:23px;font-weight:800;color:var(--ink);letter-spacing:.4px;
  transition:transform .4s var(--ease)}
.platform-tag{margin:18px 0 26px;text-align:center;font-size:14px;font-weight:700;letter-spacing:1px;color:var(--red);
  padding:9px 0;border-top:1px solid var(--line);border-bottom:1px solid var(--line);
  transition:transform .44s var(--ease),letter-spacing .44s var(--ease)}
.rule-list li{padding:13px 0;font-size:15px;line-height:1.85;color:var(--body);text-align:center;
  border-bottom:1px solid var(--line-2);transition:color .35s var(--ease),border-color .35s var(--ease)}
.rule-list li:last-child{border-bottom:0}
/* 悬停：标题上浮、副标字距拉开、分隔线泛红——居中排版不做横向位移。
   分隔线原来是 1px 虚线，2026-10-10 精修时改成实线：虚线发丝在屏幕上是碎点，
   读起来像"表格线没对齐"，实线才压得住。 */
.platform:hover h4{transform:translateY(-3px)}
.platform:hover .platform-tag{transform:translateY(-2px);letter-spacing:3px}
.platform:hover .rule-list li{color:var(--ink);border-bottom-color:rgba(193,40,46,.3)}

/* ---------- 生态概览（深色） ---------- */
.section-ink{background:var(--ink);color:#fff}
.eco{display:grid;grid-template-columns:300px minmax(0,1fr);gap:clamp(28px,4vw,56px);align-items:center}
.eco-legend{display:grid;gap:26px}
.eco-row{padding-left:16px;border-left:2px solid var(--red)}
.eco-key{display:block;font-size:14.5px;font-weight:800;letter-spacing:1px;color:#FF8E92}
.eco-val{display:grid;gap:4px;margin-top:8px;font-size:14px;line-height:1.85;color:rgba(255,255,255,.66)}
.eco-val i{font-style:normal}
.eco-art{padding:clamp(20px,2.6vw,34px);background:rgba(255,255,255,.04);border:1px solid rgba(255,255,255,.1)}
.eco-art img{width:100%}

/* ---------- 数智应用 ---------- */
.ai{display:grid;grid-template-columns:minmax(0,220px) minmax(0,1fr) minmax(0,240px);gap:clamp(20px,3vw,44px);align-items:center}
.ai-dims,.ai-apps{display:grid;gap:12px}
.ai-dims li,.ai-apps li{padding:13px 18px;text-align:center;font-size:14.5px;font-weight:700;color:var(--ink);
  background:#fff;border:1px solid var(--line);border-radius:0;transition:.3s var(--ease)}
.ai-apps li{color:var(--red-deep);border-color:rgba(193,40,46,.24);background:#fff}
.ai-dims li:hover,.ai-apps li:hover{transform:translateY(-3px);box-shadow:var(--sh-2);border-color:var(--red)}
.ai-core{position:relative;min-height:280px;display:flex;align-items:center;justify-content:center;
  background:linear-gradient(150deg,#D8232A 0%,#A8121A 55%,#5C0C11 100%);overflow:hidden}
.ai-ring{position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);width:190px;height:190px;border-radius:50%;
  border:1px solid rgba(255,255,255,.3);box-shadow:0 0 0 40px rgba(255,255,255,.06),0 0 0 80px rgba(255,255,255,.035)}
.ai-badge{position:relative;z-index:1;padding:15px 34px;font-size:clamp(18px,2vw,24px);font-weight:800;letter-spacing:.4px;
  color:#fff;background:rgba(20,20,25,.55);border:1px solid rgba(255,255,255,.3);backdrop-filter:blur(3px)}

/* ---------- 目标成效 ---------- */
.target{display:grid;grid-template-columns:280px minmax(0,1fr);gap:clamp(28px,4vw,56px);align-items:start}
.target-side{padding:30px 24px;background:#fff;border:1px solid var(--line);text-align:center}
.target-side img{width:min(100%,180px);margin:0 auto;opacity:.92}
.target-tags{margin-top:24px;display:grid;gap:1px;background:var(--line);border-top:1px solid var(--line);border-bottom:1px solid var(--line)}
.target-tags li{background:#fff;padding:12px 8px;font-size:13.5px;font-weight:600;color:var(--muted)}
.target-tags .is-key{background:var(--ink);color:#fff;font-weight:700;font-size:14.5px;letter-spacing:1px}
.target-grid{display:grid;grid-template-columns:1fr 1fr;gap:1px;background:var(--line);border:1px solid var(--line)}
.tcard{background:#fff;padding:clamp(26px,3vw,36px);transition:background .3s}
.tcard:hover{background:var(--tint-hover)}
.tcard h4{position:relative;font-size:18px;font-weight:800;color:var(--red);letter-spacing:1px;padding-bottom:16px;
  border-bottom:1px solid var(--line);transition:transform .4s var(--ease)}
/* 标题下的发丝线在悬停时用品牌红重新描一遍 */
.tcard h4::after{content:"";position:absolute;left:0;right:0;bottom:-1px;height:2px;background:var(--red);
  transform:scaleX(0);transform-origin:0 50%;transition:transform .5s var(--ease)}
.tcard p{margin-top:16px;font-size:15px;line-height:1.95;color:var(--body);transition:transform .46s var(--ease)}
.tcard:hover h4{transform:translateX(5px)}
.tcard:hover h4::after{transform:scaleX(1)}
.tcard:hover p{transform:translateX(3px)}

/* ---------- 产品要素表 ---------- */
.table-shell{border:1px solid var(--line);background:#fff}
.spec{width:100%;font-size:15px}
.spec caption{caption-side:top}
.spec thead th{padding:20px 28px;text-align:left;color:#fff;background:var(--ink);font-weight:700;letter-spacing:2px;font-size:14px}
.spec thead th:first-child{width:238px}
.spec tbody th{position:relative;padding:18px 28px;text-align:left;font-weight:700;color:var(--ink);background:var(--tint);
  border-bottom:1px solid var(--line-2);border-right:1px solid var(--line-2);white-space:nowrap;font-size:14.5px;
  transition:color .3s var(--ease),transform .3s var(--ease)}
.spec tbody td{padding:18px 28px;border-bottom:1px solid var(--line-2);color:var(--body);line-height:1.9;
  font-variant-numeric:tabular-nums;transition:color .3s var(--ease)}
.spec tbody tr:last-child th,.spec tbody tr:last-child td{border-bottom:0}
.spec tbody tr{transition:background .25s}
/* 行悬停：左侧沟槽里长出一条红标、要素名变红并右移一点、说明文字提亮——
   不是整行换个底色就完事 */
.spec tbody tr:hover th,.spec tbody tr:hover td{background:#FDF6F6}
.spec tbody tr:hover th{color:var(--red);transform:translateX(3px)}
.spec tbody tr:hover td{color:var(--ink-2)}
.spec tbody th::before{content:"";position:absolute;left:0;top:0;bottom:0;width:3px;background:var(--red);
  transform:scaleY(0);transform-origin:50% 0;transition:transform .34s var(--ease)}
.spec tbody tr:hover th::before{transform:scaleY(1)}

/* ---------- 合作方墙 ---------- */
.wall{display:grid;grid-template-columns:minmax(0,1.25fr) minmax(0,1fr) minmax(0,1fr);gap:1px;background:var(--line);
  border:1px solid var(--line)}
.wall-col{background:#fff;padding:clamp(26px,3vw,38px)}
.wall-col h4{font-size:16px;font-weight:800;color:var(--ink);letter-spacing:3px;text-align:center;
  padding-bottom:20px;border-bottom:1px solid var(--line);margin-bottom:26px}
.wall-group{padding:20px 0;border-bottom:1px solid var(--line-2);transition:border-color .35s var(--ease)}
.wall-group:last-child{border-bottom:0;padding-bottom:0}
.wall-group:hover{border-bottom-color:rgba(193,40,46,.42)}
.wall-label{font-size:13px;font-weight:700;letter-spacing:2px;color:var(--red);margin-bottom:18px;text-align:center;
  transition:color .35s var(--ease),letter-spacing .35s var(--ease)}
.wall-group:hover .wall-label{color:var(--ink);letter-spacing:3.4px}
.logos{display:flex;flex-wrap:wrap;align-items:center;justify-content:center;gap:18px 22px}
.logos img{height:26px;width:auto;opacity:.9;transition:.35s var(--ease);filter:saturate(.55)}
/* 标志墙：整排先压成灰调，鼠标落在哪只哪只恢复品牌色并抬起来——聚光灯，不是各抬各的 */
.logos:hover img{opacity:.4;filter:grayscale(1)}
.logos img:hover{opacity:1;filter:none;transform:translateY(-4px) scale(1.05)}
.logos-col{flex-direction:column;gap:30px}
.logos-col img{height:auto;max-height:58px}

/* ---------- 案例 ---------- */
.case-grid{display:grid;grid-template-columns:1fr 1fr;gap:clamp(24px,3vw,40px)}
.case{position:relative;background:#fff;border:1px solid var(--line);transition:border-color .45s var(--ease)}
/* 案例卡不做整块抬起 + 投影那套，改成描边转墨、内件分层位移，和站内其他卡片一致 */
.case:hover{border-color:var(--ink)}
.case-art{overflow:hidden;height:250px}
.case-art img{width:100%;height:100%;object-fit:cover;transition:transform .8s var(--ease)}
.case:hover .case-art img{transform:scale(1.05)}
.case-body{padding:clamp(26px,3vw,38px)}
.case-logo{height:38px;width:auto;margin-bottom:20px;transition:transform .45s var(--ease),opacity .45s var(--ease)}
.case h4{font-size:21px;font-weight:800;color:var(--ink);letter-spacing:.5px;padding-bottom:18px;
  border-bottom:1px solid var(--line);transition:transform .45s var(--ease)}
.dot-list{margin-top:18px;display:grid;gap:12px}
.dot-list li{position:relative;padding-left:18px;font-size:15px;line-height:1.9;color:var(--body);
  transition:transform .5s var(--ease)}
.dot-list li::before{content:"";position:absolute;left:0;top:12px;width:6px;height:6px;border-radius:50%;
  background:var(--red);opacity:.7;transition:transform .4s var(--ease),opacity .4s var(--ease)}
.case:hover .case-logo{transform:translateY(-3px)}
.case:hover h4{transform:translateX(7px)}
.case:hover .dot-list li{transform:translateX(10px)}
.case:hover .dot-list li::before{transform:scale(1.35);opacity:1}

/* ---------- 准入 / 材料 列表 ---------- */
.admit-grid,.doc-grid{display:grid;grid-template-columns:1fr 1fr;gap:clamp(24px,3vw,40px)}
.admit,.doc{position:relative;background:#fff;border:1px solid var(--line);padding:clamp(28px,3.2vw,42px);
  transition:border-color .45s var(--ease)}
.admit:hover,.doc:hover{border-color:rgba(193,40,46,.5)}
.admit-note{font-size:14.5px;font-weight:700;color:var(--red-deep);letter-spacing:.5px;
  padding-bottom:20px;border-bottom:1px solid var(--line);margin-bottom:6px}
.num-list{display:grid}
.num-list li{display:flex;gap:16px;align-items:flex-start;padding:16px 0;font-size:15px;line-height:1.85;
  color:var(--body);border-bottom:1px solid var(--line-2);transition:color .3s var(--ease),transform .4s var(--ease)}
.num-list li:last-child{border-bottom:0}
.num-list li:hover{color:var(--ink);transform:translateX(5px)}
.num-list i{flex:none;font-style:normal;font-size:12.5px;font-weight:800;color:var(--red);letter-spacing:.5px;
  padding-top:4px;min-width:22px;transition:transform .4s var(--ease)}
.num-list li:hover i{transform:translateY(-3px)}
.doc h4{font-size:19px;font-weight:800;color:var(--ink);letter-spacing:1.5px;padding-bottom:18px;
  border-bottom:2px solid var(--ink);margin-bottom:6px;transition:border-color .4s var(--ease)}
.doc:hover h4{border-bottom-color:var(--red)}
.doc-foot{margin-top:22px;padding-top:18px;border-top:1px solid var(--line);font-size:13.5px;line-height:1.85;color:var(--muted)}

/* ---------- 流程 ---------- */
.phase{margin-bottom:clamp(40px,5vw,60px)}
.phase:last-child{margin-bottom:0}
.phase-label{display:flex;align-items:center;gap:14px;font-size:16px;font-weight:800;letter-spacing:2px;
  color:var(--ink);margin-bottom:28px}
.phase-line{width:28px;height:2px;background:var(--red);flex:none;transition:width .45s var(--ease)}
.phase:hover .phase-line{width:66px}
.phase-body{display:grid;grid-template-columns:minmax(0,1fr) 190px;gap:clamp(20px,3vw,40px);align-items:stretch}
.steps{display:grid;grid-template-columns:repeat(4,1fr);gap:1px;background:var(--line);border:1px solid var(--line);position:relative}
.step{position:relative;background:#fff;padding:28px 22px 26px;transition:background .3s}
.step:hover{background:var(--tint-hover)}
.step-dot{position:absolute;left:22px;top:-5px;width:9px;height:9px;border-radius:50%;background:var(--red);
  transition:transform .4s var(--ease),box-shadow .4s var(--ease)}
.step-idx{font-size:12.5px;font-weight:800;letter-spacing:1px;color:var(--red);opacity:.65;
  transition:opacity .35s var(--ease),transform .4s var(--ease)}
.step h5{margin-top:16px;font-size:17.5px;font-weight:800;color:var(--ink);letter-spacing:.5px;
  transition:transform .42s var(--ease)}
.step p{margin-top:10px;font-size:14px;line-height:1.85;color:var(--body);transition:transform .5s var(--ease)}
/* 流程格：节点胀开一圈红晕，序号上浮，标题和说明分头走，右侧浮出续接箭头 */
.step:hover .step-dot{transform:scale(1.35);box-shadow:0 0 0 5px rgba(193,40,46,.18)}
.step:hover .step-idx{opacity:1;transform:translateY(-3px)}
.step:hover h5{transform:translateX(5px)}
.step:hover p{transform:translateX(9px)}
.step:not(:last-child)::after{content:"";position:absolute;right:10px;top:50%;width:6px;height:6px;
  border-top:1.5px solid var(--red);border-right:1.5px solid var(--red);
  transform:translateY(-50%) rotate(45deg);opacity:0;transition:opacity .35s var(--ease)}
.step:hover:not(:last-child)::after{opacity:.7}
.outcome{display:flex;flex-direction:column;justify-content:center;gap:14px}
.outcome-pill{padding:16px 14px;text-align:center;font-size:14.5px;font-weight:700;letter-spacing:1.5px;color:#fff;
  background:var(--ink);position:relative;transition:transform .4s var(--ease),letter-spacing .4s var(--ease)}
.outcome-pill::before{content:"";position:absolute;left:0;top:0;bottom:0;width:3px;background:var(--red);
  transform:scaleY(.42);transform-origin:50% 50%;transition:transform .45s var(--ease)}
.outcome-pill:hover{transform:translateX(-5px);letter-spacing:2.5px}
.outcome-pill:hover::before{transform:scaleY(1)}
.outcome-note{font-size:13.5px;font-weight:700;color:var(--red-deep);letter-spacing:.5px;text-align:center}

/* ---------- 业务模式 ---------- */
.mode-grid{display:grid;grid-template-columns:1fr 1fr;gap:clamp(24px,3vw,40px);align-items:stretch}
.mode{position:relative;padding:clamp(32px,3.6vw,48px);color:#fff;overflow:hidden}
.mode-red{background:linear-gradient(150deg,#E0242B 0%,#A8121A 55%,#4A0A0E 100%)}
.mode-ink{background:linear-gradient(150deg,#2E2E36 0%,#1B1B21 60%,#0E0E12 100%)}
.mode::after{content:"";position:absolute;right:-90px;top:-90px;width:280px;height:280px;border-radius:50%;
  background:radial-gradient(circle,rgba(255,255,255,.1),transparent 68%)}
.mode-tag{display:inline-block;font-size:13px;font-weight:700;letter-spacing:2px;padding:7px 16px;
  border:1px solid rgba(255,255,255,.4);color:#fff}
.mode h3{margin-top:24px;font-size:clamp(24px,2.7vw,32px);font-weight:800;letter-spacing:2px;line-height:1.35}
.mode-desc{margin-top:14px;font-size:15px;line-height:1.95;color:rgba(255,255,255,.8)}
.mode-list{margin-top:30px;padding-top:26px;border-top:1px solid rgba(255,255,255,.16);
  display:grid;grid-template-columns:1fr 1fr;gap:18px 26px}
.mode-list li{position:relative;padding-left:16px;font-size:14.5px;font-weight:600;line-height:1.7;color:rgba(255,255,255,.94)}
.mode-list li::before{content:"";position:absolute;left:0;top:9px;width:5px;height:5px;background:var(--red-2);
  box-shadow:0 0 0 3px rgba(226,58,63,.22)}
.mode-foot{margin-top:26px;display:grid;gap:12px}
.mode-foot p{padding:14px 18px;font-size:14px;font-weight:600;color:rgba(255,255,255,.9);
  background:rgba(255,255,255,.07);border:1px solid rgba(255,255,255,.14)}

/* ---------- 页脚 ---------- */
.footer{background:var(--ink);color:#fff}
.footer-top{position:relative;overflow:hidden;
  background:linear-gradient(120deg,#C11B23 0%,#7C0D12 45%,#2A0507 100%)}
.footer-top::after{content:"";position:absolute;inset:0;background:radial-gradient(60% 90% at 82% 50%,rgba(255,255,255,.12),transparent 62%)}
.footer-cta{position:relative;display:flex;align-items:center;justify-content:space-between;gap:40px;
  padding-top:clamp(60px,7vw,96px);padding-bottom:clamp(60px,7vw,96px)}
/* 原来 0 24px 44px / .4 那团影子在红底上糊成一块脏影，读作"图没抠干净"而不是"浮起来"。
   收到 12/26/.26：只留一点点接地感，边缘不再发灰。 */
.footer-mark{width:min(38%,300px);filter:drop-shadow(0 12px 26px rgba(46,0,0,.26))}
.footer-words{text-align:right}
.footer-title{font-size:clamp(28px,4.2vw,54px);font-weight:800;letter-spacing:0;line-height:1.14}
.footer-sub{margin-top:18px;font-size:clamp(15px,1.9vw,22px);font-weight:600;letter-spacing:1.5px}
.footer-en{margin-top:14px;font-size:12px;letter-spacing:2.4px;color:rgba(255,255,255,.72)}
.footer-bar{display:flex;align-items:center;justify-content:space-between;flex-wrap:wrap;gap:22px;
  padding-top:38px;padding-bottom:44px}
.footer-logo{height:34px;width:auto}
.footer-nav{display:flex;flex-wrap:wrap;gap:8px 30px}
.footer-nav a{font-size:14px;letter-spacing:1px;color:rgba(255,255,255,.68);transition:color .22s}
.footer-nav a:hover{color:#fff}
.footer-copy{font-size:12.5px;color:rgba(255,255,255,.42);letter-spacing:.5px}

/* ---------- 底部法务行（版权 + ICP 备案） ----------
   国内站惯例：备案号单独占一行，字号小、颜色淡，但必须能点进工信部查询站。
   与上方品牌导航行用一条极淡的分割线隔开，避免和 nav 挤在同一基线上。 */
.footer-legal{display:flex;align-items:center;justify-content:space-between;flex-wrap:wrap;gap:8px 22px;
  padding-top:20px;padding-bottom:34px;margin-top:-6px;border-top:1px solid rgba(255,255,255,.09)}
.footer-legal .footer-copy{margin:0}
.icp{font-size:12.5px;letter-spacing:.5px;color:rgba(255,255,255,.5);
  border-bottom:1px solid transparent;transition:color .22s,border-color .22s}
.icp:hover,.icp:focus-visible{color:#fff;border-bottom-color:rgba(255,255,255,.5)}
.icp:focus-visible{outline:2px solid rgba(255,255,255,.35);outline-offset:3px}
/* 两个备案号并成一组放右侧：工信部 ICP 在前、公安备案在后，窄屏换行也不挤 */
.footer-marks{display:flex;align-items:center;flex-wrap:wrap;gap:6px 18px;margin:0}
/* 公安备案的官方徽标放在号码前面（国内通行做法）。
   全局 img 是 display:block，直接塞进行内链接会把整条撑断行，所以链接本身走 flex。
   徽标原图 36×40 带 alpha，等比缩到 18px 高，和 12.5px 的字排同一条视觉基线。 */
.icp-police{display:inline-flex;align-items:center;gap:5px}
.beian-ico{flex:none;display:inline-block;height:18px;width:auto}
@media (max-width:600px){
  .footer-legal{flex-direction:column;justify-content:center;text-align:center;gap:6px}
  .footer-marks{justify-content:center}
}

/* ---------- 返回顶部 ---------- */
.totop{position:fixed;right:33px;bottom:96px;z-index:90;width:38px;height:38px;border:0;border-radius:0;cursor:pointer;
  color:#fff;font-size:15px;background:var(--red);box-shadow:0 12px 26px rgba(193,40,46,.32);
  opacity:0;transform:translateY(14px);pointer-events:none;transition:opacity .3s,transform .3s}
.totop.is-on{opacity:1;transform:none;pointer-events:auto}
.totop:hover{background:var(--red-deep)}

/* ---------- 右下角弧形快捷导航 ----------
   弹出让位给主按钮：主按钮占角落，返回顶部叠在它上方。
   展开位置写在行内 --ax/--ay 上（不用 CSS trig 函数，避免旧内核算不出来导致
   五个点全挤在原位）。收回走同一条路径，只是把错峰顺序反过来。 */
.fab{position:fixed;right:26px;bottom:26px;z-index:95;width:56px;height:56px}
.fab-btn{
  position:relative;z-index:2;width:56px;height:56px;border:0;border-radius:50%;cursor:pointer;padding:0;
  background:linear-gradient(140deg,var(--red-2),var(--red) 45%,var(--red-deep));
  box-shadow:0 14px 30px rgba(193,40,46,.36),0 2px 0 rgba(255,255,255,.18) inset;
  transition:transform .34s var(--ease),box-shadow .34s var(--ease),filter .25s;
}
.fab-btn:hover{filter:brightness(1.07);box-shadow:0 18px 38px rgba(193,40,46,.46),0 2px 0 rgba(255,255,255,.18) inset}
.fab-btn:focus-visible{outline:2px solid var(--ink);outline-offset:3px}
.fab.is-open .fab-btn{transform:rotate(45deg)}        /* 加号转 45° 即成叉号 */

.fab-plus{position:absolute;inset:0;display:block}
.fab-plus i{position:absolute;left:50%;top:50%;display:block;width:20px;height:2px;border-radius:2px;background:#fff;
  transform:translate(-50%,-50%)}
.fab-plus i:nth-child(2){transform:translate(-50%,-50%) rotate(90deg)}

/* 菜单项 */
.fab-menu{position:absolute;right:0;bottom:0;width:56px;height:56px;pointer-events:none}
.fab-item{
  position:absolute;right:0;bottom:0;display:flex;align-items:center;gap:10px;
  transform:translate(0,0) scale(.35);opacity:0;pointer-events:none;
  transition:transform .38s var(--ease),opacity .26s ease;
  transition-delay:calc(var(--i) * 42ms);            /* 弹出：由近及远依次 */
}
.fab.is-open .fab-item{
  transform:translate(var(--ax),var(--ay)) scale(1);opacity:1;pointer-events:auto;
  transition-delay:calc(var(--i) * 42ms);
}
.fab.is-closing .fab-item{                          /* 收回：反过来，最后一个先走 */
  transition-delay:calc((4 - var(--i)) * 34ms);
}
.fab-ico{
  flex:none;width:44px;height:44px;border-radius:50%;display:grid;place-items:center;
  background:#fff;border:1px solid var(--line);
  box-shadow:var(--sh-2);
  transition:border-color .25s,box-shadow .25s,background .25s;
}
.fab-ico svg{width:21px;height:21px;fill:none;stroke:var(--red);stroke-width:1.6;
  stroke-linecap:round;stroke-linejoin:round;transition:stroke .25s}
.fab-item:hover .fab-ico,.fab-item:focus-visible .fab-ico{
  background:var(--red);border-color:var(--red);box-shadow:0 14px 26px rgba(193,40,46,.34)}
.fab-item:hover .fab-ico svg,.fab-item:focus-visible .fab-ico svg{stroke:#fff}
.fab-item:focus-visible{outline:2px solid var(--ink);outline-offset:4px;border-radius:50%}
.fab-label{
  order:-1;white-space:nowrap;font-size:13px;font-weight:700;letter-spacing:1px;color:var(--ink);
  padding:6px 12px;border-radius:0;background:#fff;border:1px solid var(--line);
  box-shadow:var(--sh-1);
  opacity:0;transform:translateX(6px);transition:opacity .25s,transform .25s}
.fab.is-open .fab-item:hover .fab-label,.fab.is-open .fab-item:focus-visible .fab-label{opacity:1;transform:none}

/* 窄屏收小半径，避免最左那个点顶到屏幕外 */
@media (max-width:600px){
  .fab{right:16px;bottom:16px}
  .totop{right:22px;bottom:84px}
  .fab-item{--ax:0;--ay:0}
  .fab-item[style*="--i:0"]{--ax:-14px;--ay:-84px}
  .fab-item[style*="--i:1"]{--ax:-43px;--ay:-74px}
  .fab-item[style*="--i:2"]{--ax:-66px;--ay:-55px}
  .fab-item[style*="--i:3"]{--ax:-80px;--ay:-29px}
  .fab-item[style*="--i:4"]{--ax:-84px;--ay:0}
  .fab-ico{width:40px;height:40px}
  .fab-label{display:none}
}

@media (prefers-reduced-motion:reduce){
  .fab-btn,.fab-item,.fab-ico,.fab-label{transition-duration:.01ms !important;transition-delay:0ms !important}
}

/* ---------- 出场动画 ----------
   分层，不是整块平移：容器只负责透明度淡入，位移交给子元素按阅读顺序错开——
   标签先到、标题跟上、正文最后，杜绝"一整块板子浮起来"。
   关键：入场走 translate，hover 走 transform。两个独立属性会叠加，
   而动画的 both 填充不会像以前那样把 hover 的 transform 吃掉。
   所有隐藏初态都挂在 .js 上：没有 JS（或 JS 挂掉）时内容照常可见。 */
.js .reveal,.js .block-head{opacity:0}
.reveal,.block-head{transition:opacity .62s var(--ease) var(--rd,0ms)}
/* 纯文本节点、没有元素子节点的块（例如 .statement）自己抬一下 */
.js .reveal:not(:has(*)){translate:0 16px;
  transition:opacity .62s var(--ease) var(--rd,0ms),translate .8s var(--ease) var(--rd,0ms)}
.reveal.is-in,.block-head.is-in{opacity:1}
.js .reveal.is-in:not(:has(*)){translate:none}
.reveal.is-in > *,.block-head.is-in > *{animation:seqRise .8s var(--ease) both}
.reveal.is-in > :nth-child(1),.block-head.is-in > :nth-child(1){animation-delay:calc(var(--rd,0ms) + 0ms)}
.reveal.is-in > :nth-child(2),.block-head.is-in > :nth-child(2){animation-delay:calc(var(--rd,0ms) + var(--seq))}
.reveal.is-in > :nth-child(3),.block-head.is-in > :nth-child(3){animation-delay:calc(var(--rd,0ms) + var(--seq) * 2)}
.reveal.is-in > :nth-child(4),.block-head.is-in > :nth-child(4){animation-delay:calc(var(--rd,0ms) + var(--seq) * 3)}
.reveal.is-in > :nth-child(5),.block-head.is-in > :nth-child(5){animation-delay:calc(var(--rd,0ms) + var(--seq) * 4)}
.reveal.is-in > :nth-child(6),.block-head.is-in > :nth-child(6){animation-delay:calc(var(--rd,0ms) + var(--seq) * 5)}
.reveal.is-in > :nth-child(n+7),.block-head.is-in > :nth-child(n+7){animation-delay:calc(var(--rd,0ms) + var(--seq) * 6)}
@keyframes seqRise{from{translate:0 22px}to{translate:none}}
@keyframes fadeRise{from{opacity:0;translate:0 20px}to{opacity:1;translate:none}}
@media (prefers-reduced-motion:reduce){
  /* 总闸：所有动效时长压到不可感知，动画停在终态 */
  *,*::before,*::after{animation-duration:.01ms!important;animation-iteration-count:1!important;
    transition-duration:.01ms!important;transition-delay:0ms!important;scroll-behavior:auto!important}
  html{scroll-behavior:auto}
  /* important 在层叠里优先级高于 animation 填充值，
     所以这里能把"入场初态"整体按回终态，绝不出现内容看不见 */
  .reveal,.block-head,.opener-num,.opener-title,.opener-lede,
  .hero-lockup,.hero-title,.hero-sub,.hero-en,.hero-tag,.hero-mark,.hero-scroll,.hero-rule,
  .news-page-inner>*,.news-page-inner::after,.fig-suf{
    opacity:1!important;translate:none!important}
  /* 需要清掉入场 transform 的才列在这里；.hero-scroll 的 transform 是居中用的
     （translateX(-50%)），不能被这条连带清掉 */
  .hero-lockup,.hero-title,.hero-sub,.hero-en,.hero-tag,.hero-mark,.hero-rule,
  .opener-num,.opener-title,.opener-lede,.news-page-inner>*,.news-page-inner::after,.fig-suf{
    transform:none!important}
  .reveal,.block-head{transition:none!important}
  /* 新增的三处动效一并关掉，并且是把"初态"按回终态，不是跳过动画停在被遮住的样子 */
  .opener::after{animation:none!important}
  /* 减弱动效下 JS 根本不会切行；这里再上一道锁，覆盖中途切换系统设置的情况 */
  .js .has-lines .ln{overflow:visible!important;transform:none!important}
  .js .has-lines .ln-i{transform:none!important;opacity:1!important;will-change:auto}
  .js .odo-l{visibility:hidden!important}
  .js .odo-s{visibility:visible!important}
  .opener-num{-webkit-text-stroke-width:1.5px!important;
    -webkit-mask-position:0 0!important;mask-position:0 0!important}
  .opener-body::after{transform:none!important}
  .hero-mark{--par:0px!important}
  .hero::before{animation:none!important}
  /* ---- 签名动效在减弱动效下的终态（逐条给，都是"按回已完成的样子"） ---- */
  /* 首屏树标：三层装饰是纯叠加的光，直接关掉；包裹层的位移清零，
     旋转层按回 0 度（logo 正立），入场动画的 opacity/scale 初态按回终态，
     树标本体照常可见 */
  .mark-stage{opacity:1!important;translate:none!important;scale:1!important;--mx:0px;--my:0px}
  .mark-spin{animation:none!important;rotate:none!important}
  .mark-halo,.mark-sweep,.mark-pulse{animation:none!important;opacity:0!important}
  /* 章节大数字：灌红拉满，不依赖滚动 */
  .opener-num{--fill:1!important}
  /* 首屏标题掠光：掠光层移出文字范围，只留纯白底，描边归零 ——
     文字仍然是实心白，一个像素都不靠动画才看得见 */
  .hero-title,.js .hero-title .ln-i{background-position:-60% 0,0 0!important;
    -webkit-text-stroke-width:0px!important}
  /* 首屏主张：3D 摆动已经被上面的 transform:none 按回终态，
     这里再显式停掉动画；字面是实心白 + 静态挤出，不依赖任何一帧动画才看得见 */
  .hero-sub{animation:none!important}
  /* 标志墙：漂移/呼吸全停，克隆出来的那批 logo 从 DOM 视觉上撤掉，
     只留原始那一组，排布回到静止居中的老样子 */
  .logos.is-drift{overflow:visible!important;height:auto!important;
    -webkit-mask-image:none!important;mask-image:none!important}
  .logos-run{animation:none!important;transform:none!important}
  .logos-clone{display:none!important}
  .logos-wave{animation:none!important}
}

/* ---------- 标题按行遮罩上升 ----------
   .ln 是裁剪框、.ln-i 是被抬起来的那一行，两种节点都是 JS 真的切成行之后才插进来的，
   所以隐藏初态全部挂在 .js .has-lines 上：没 JS / 脚本抛错 / 量行失败时
   DOM 里根本没有 .ln，标题整段照常可见，不存在"卡在遮罩里"的标题。
   裁剪框就取行盒本身，不加 padding：负 margin 会和父元素折叠掉，
   一 padding 反而把标题的盒子撑高几像素；行盒裁剪才是零布局改动，
   抬起的量给到 120% 足够把整行藏出框外。 */
.js .has-lines .ln{display:block;overflow:hidden}
.js .has-lines .ln-i{display:block;transform:translateY(120%);will-change:transform;
  transition:transform .7s var(--ease) calc(var(--ln-base,0ms) + var(--ln,0) * 72ms)}
.js .has-lines.is-lit .ln-i{transform:none}
/* 走到位就把裁剪框放开：首屏标题挂着 18px 的大投影，一直 clip 着会把投影切齐边 */
.js .has-lines.is-done .ln{overflow:visible}
.js .has-lines.is-done .ln-i{will-change:auto}
/* 起手延迟接回原来那套分层的节拍，标题不另起一拍 */
.js .hero-title.has-lines{--ln-base:150ms}
.js .hero-sub.has-lines{--ln-base:290ms}
.js .opener-title.has-lines{--ln-base:210ms}
.js .news-page-title.has-lines{--ln-base:140ms}
.js .footer-title.has-lines{--ln-base:60ms}
.js .block-title.has-lines,.js .display.has-lines{--ln-base:var(--seq)}
/* 切成行的标题不再参加原来那层位移，位移全交给行遮罩，避免两套动作叠着走 */
.js .hero-title.has-lines,.js .hero-sub.has-lines{animation:none;opacity:1}
.js .opener.is-in .opener-title.has-lines{animation:none}
.js .reveal.is-in > .has-lines,.js .block-head.is-in > .has-lines{animation:none}
.js .news-page-inner > .has-lines{animation:none}

/* ---------- 业绩数字：逐位滚轮 ----------
   .odo-s 是撑住宽高和基线的影子文本（滚动那一下藏起来，收尾原样读回来）；
   .odo-l 是绝对定位的字带层，格子高度由 JS 按行盒高度写死，滚完整个层删掉，不留壳。
   字带不另设行高，继承 .fig strong 的 .98 行高，落点与影子文本逐字重合。 */
.js .odo{position:relative;display:inline-block}
.js .odo-l{position:absolute;left:0;top:0;display:flex;justify-content:flex-start;
  visibility:hidden;pointer-events:none}
.js .odo.is-roll .odo-l{visibility:visible}
.js .odo.is-roll .odo-s{visibility:hidden}
.odo-c{flex:0 0 auto;overflow:hidden}
.js .odo-r{display:block;transform:translateY(0);
  transition:transform 1s cubic-bezier(.18,.72,.24,1) var(--odo-delay,0ms)}
.js .odo.is-roll .odo-r{transform:translateY(var(--odo-to,0))}
/* 靠左排，不居中：格子宽 = 影子文本这一位的实测宽，数字带的行宽和它一模一样，
   左边缘一对齐字形就完全重合；居中的话 letter-spacing 的那半格尾距会把字推偏 */
.odo-g{display:block}

/* ---------- 章节开篇：一层缓慢漂移的淡网格 ----------
   深色带上唯一的新增动作，只做一个 ::after（::before 已经被那团红色辉光占了）。
   网格 34px 见方、线宽 1px、白色 5% 不透明度，外面再套一条斜向的软遮罩，
   于是只有中间一窄条看得见，整块平移一格（34px）循环 —— 网格是周期的，
   平移一格等于没动，接缝看不出来；慢到几乎察觉不到，纯装饰。
   z-index 压到 0、内容层抬到 1，就不会盖住 .opener-num 的描边书写动画。 */
.opener::after{content:"";position:absolute;inset:-40px;z-index:0;pointer-events:none;opacity:.7;
  background-image:linear-gradient(rgba(255,255,255,.055) 1px,transparent 1px),
    linear-gradient(90deg,rgba(255,255,255,.055) 1px,transparent 1px);
  background-size:34px 34px;
  -webkit-mask-image:linear-gradient(104deg,transparent 0 22%,#000 46% 54%,transparent 78% 100%);
  mask-image:linear-gradient(104deg,transparent 0 22%,#000 46% 54%,transparent 78% 100%);
  animation:gridDrift 15s linear infinite}
.opener-inner{z-index:1}
@keyframes gridDrift{from{transform:translate3d(0,0,0)}to{transform:translate3d(-34px,-34px,0)}}

/* ---------- 响应式 ---------- */
@media (max-width:1180px){
  .ai{grid-template-columns:190px minmax(0,1fr) 200px;gap:18px}
  .wall{grid-template-columns:minmax(0,1fr) minmax(0,1fr)}
  .wall-col:first-child{grid-column:1 / -1}
}
@media (max-width:1024px){
  .hero-inner{grid-template-columns:1fr;grid-template-rows:auto auto 1fr auto;padding:calc(var(--navh) + 44px) 32px 72px}
  .hero-lockup{grid-area:1/1/2/2}
  .hero-head{grid-area:2/1/3/2}
  /* 树标的宽高/外边距交给包裹层 .mark-stage 统一管（见本文件末尾的签名动效段）。
     这里若再给 img 写 width/margin，img 会缩到旋转层的 74%，
     而 .mark-stage 的高度被 margin 撑高 48px，两圈光环就压成了椭圆。 */
  .hero-mark{grid-area:3/1/4/2}
  .hero-en{grid-area:4/1/5/2}
  .hero-tag{grid-area:5/1/6/2;justify-self:start;text-align:left;margin-top:22px}
  .hero-tag::after{left:0;right:auto}
  .about,.solve,.target,.eco,.case-grid,.admit-grid,.doc-grid,.mode-grid,.phase-body{grid-template-columns:1fr}
  .target-side{max-width:520px}
  .solve-art{order:-1}
  .fig-grid,.pain-grid,.target-grid,.index-grid,.platform-grid{grid-template-columns:1fr 1fr}
  .index-item{border-bottom:1px solid var(--line)}
  .index-item:nth-child(2n){border-right:0}
  .outcome{flex-direction:row;flex-wrap:wrap;align-items:center}
  .outcome-pill{flex:1 1 auto}
  .outcome-note{flex:1 1 100%}
  .ai{grid-template-columns:1fr;gap:24px}
  .ai-dims,.ai-apps{grid-template-columns:repeat(auto-fit,minmax(150px,1fr))}
  .footer-cta{flex-direction:column;text-align:center}
  .footer-words{text-align:center}
  .footer-mark{width:min(60%,240px)}
}
@media (max-width:820px){
  .menu{position:fixed;left:0;right:0;top:var(--navh);flex-direction:column;align-items:stretch;gap:0;
    background:#fff;border-bottom:1px solid var(--line);box-shadow:var(--sh-2);
    padding:8px 20px 18px;transform:translateY(-14px);opacity:0;pointer-events:none;transition:.3s var(--ease)}
  .menu.is-open{transform:none;opacity:1;pointer-events:auto}
  .menu-link{padding:15px 8px;border-bottom:1px solid var(--line-2);font-size:16px}
  .menu-link::after{display:none}
  .burger{display:flex}
  .opener-inner{flex-direction:column;align-items:flex-start;gap:18px}
  .steps{grid-template-columns:1fr 1fr}
  /* 两列/单列时右向续接箭头会指错方向，收掉 */
  .step::after{display:none}
  .spec thead th:first-child,.spec tbody th{width:auto}
}
@media (max-width:600px){
  :root{--navh:62px;--seq:58ms}
  .wrap{padding:0 20px}
  .hero-inner{padding:calc(var(--navh) + 36px) 20px 64px}
  .opener-num{letter-spacing:-2px}
  .fig-grid,.pain-grid,.target-grid,.index-grid,.platform-grid,.mode-list,.steps,.wall{grid-template-columns:1fr}
  .index-item,.wall-col{border-right:0}
  .spec thead th,.spec tbody th,.spec tbody td{padding:14px 18px;font-size:14px}
  .mv-row{grid-template-columns:1fr;gap:8px}
  .footer-cta{gap:28px}
  .totop{right:22px;bottom:88px}
  .statement{letter-spacing:0}
  .news-filter{grid-auto-flow:row;grid-template-columns:1fr 1fr;width:100%}
  .news-card h3{font-size:17px}
  /* 窄屏下收紧字距，元信息行不至于挤成三行 */
  .news-meta-line{letter-spacing:1px;padding-bottom:11px}
  .news-meta-line::before{width:14px;margin-right:8px}
}

/* ---------- 行业资讯 ----------
   沿用站内既有的"发丝线网格"语言：1px 缝隙、无阴影无圆角、细分类标签 + 短红杠 */
.news-filter{display:inline-grid;grid-auto-flow:column;gap:1px;background:var(--line);
  border:1px solid var(--line);margin-bottom:clamp(20px,2.2vw,28px);max-width:100%}
.news-filter[hidden]{display:none}
.news-filter button{font-family:inherit;padding:13px 24px;font-size:14.5px;font-weight:700;letter-spacing:1.5px;
  color:var(--muted);background:#fff;border:0;cursor:pointer;transition:color .24s,background .24s}
.news-filter button:hover{color:var(--ink);background:var(--tint)}
.news-filter button.is-active{color:#fff;background:var(--ink)}
.news-filter button.is-active:hover{background:var(--ink-2)}
.news-filter button:focus-visible{outline:2px solid var(--red);outline-offset:-3px}

/* 更新时间 / 条数这一行原先是没样式的裸文本。做成一条安静的元信息行：
   一截红签起头 + 小字距 + 一条和网格同宽的发丝底线。
   用普通行内排版而非 flex，免得 "更新于 / 日期 / · 共 / 数字" 被拆成碎片各撑一段间距。 */
.news-meta-line{display:block;margin-bottom:clamp(24px,2.8vw,34px);padding-bottom:13px;
  border-bottom:1px solid var(--line);font-size:13px;font-weight:600;letter-spacing:1.6px;color:var(--muted)}
.news-meta-line::before{content:"";display:inline-block;width:22px;height:2px;background:var(--red);
  vertical-align:middle;margin-right:12px}
.news-meta-line .news-updated-date,
.news-meta-line .news-count{font-style:normal;font-weight:700;letter-spacing:.8px;
  font-variant-numeric:tabular-nums;color:var(--ink)}
/* 亮底上不能用深底那支粉色（#FF8E92 在白底只有 2.3:1），换成品牌红 */
.news-meta-line .news-count{color:var(--red)}

.news-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:1px;background:var(--line);border:1px solid var(--line)}
.news-grid.is-empty{display:block;background:transparent;border:0}
.news-card{display:flex;flex-direction:column;background:#fff;
  padding:clamp(26px,2.9vw,38px) clamp(22px,2.5vw,32px);transition:background .3s}
.news-card:hover{background:var(--tint-hover)}
.news-cat{display:inline-flex;align-items:center;gap:8px;font-size:12px;font-weight:700;letter-spacing:2.2px;
  color:var(--red);transition:transform .4s var(--ease)}
.news-cat::before{content:"";width:18px;height:2px;background:var(--red);opacity:.6;transition:width .4s var(--ease)}
.news-card h3{margin-top:22px;font-size:18.5px;line-height:1.6;font-weight:800;letter-spacing:.2px;color:var(--ink);
  transition:transform .45s var(--ease)}
.news-card:hover .news-cat{transform:translateX(5px)}
.news-card:hover .news-cat::before{width:30px}
.news-card:hover h3{transform:translateY(-2px)}
.news-card h3 a{display:inline;color:var(--ink);transition:color .22s;
  background-image:linear-gradient(var(--red),var(--red));background-size:0 1px;background-repeat:no-repeat;
  background-position:0 100%;transition:background-size .4s var(--ease),color .22s}
.news-card h3 a:hover{color:var(--red);background-size:100% 1px}
.news-meta{margin-top:14px;padding-bottom:18px;border-bottom:1px solid var(--line-2);
  font-size:13px;letter-spacing:.6px;color:var(--muted);font-variant-numeric:tabular-nums;
  transition:transform .5s var(--ease)}
.news-meta i{font-style:normal}
.news-meta span{margin:0 10px;opacity:.45}
.news-sum{margin-top:18px;font-size:15px;line-height:1.95;color:var(--body);text-align:justify;
  transition:transform .55s var(--ease)}
.news-card:hover .news-meta{transform:translateX(4px)}
.news-card:hover .news-sum{transform:translateX(7px)}
/* 「查看原文」从装饰性 span 改成了真链接，样式跟着补三件：
   链接自身要有悬停/聚焦反馈；键盘 Tab 过来必须看得见（不然焦点跑进一个 opacity:0 的元素里）；
   触屏没有 hover，这条 CTA 不能只靠悬停才现身。
   flex 项默认拉伸，所以整行都是点击区域，而下划线只跟着文字宽度走。 */
.news-go{margin-top:auto;padding-top:22px;font-size:13px;font-weight:700;letter-spacing:1.5px;color:var(--red);
  opacity:0;transform:translateX(-8px);transition:.35s var(--ease);text-decoration:none}
.news-card:hover .news-go,.news-go:hover,.news-go:focus{opacity:1;transform:none}
.news-go:hover{color:var(--red-deep);text-decoration:underline;text-underline-offset:5px}
.news-go:focus-visible{outline:2px solid var(--red);outline-offset:5px}
@media (hover:none){.news-go{opacity:1;transform:none}}

.news-note{margin-top:26px;font-size:12.5px;line-height:1.9;color:var(--muted);letter-spacing:.3px}
.news-empty{padding:clamp(38px,5vw,64px) clamp(24px,3vw,40px);text-align:center;font-size:15px;
  color:var(--muted);background:#fff;border:1px solid var(--line);letter-spacing:1px}
/* 诊断行：只有资讯数据真出问题才会被脚本插进来。
   做成站内一致的红边提示，而不是随手糊一行内联样式 */
.news-diag{margin-top:22px;padding:14px 18px;font-size:13px;line-height:1.85;letter-spacing:.3px;
  color:var(--red-deep);background:var(--tint);border:1px solid rgba(193,40,46,.32);border-left:3px solid var(--red);
  word-break:break-all}

/* 资讯列表页 */
.news-page-head{background:var(--ink);color:#fff;position:relative;overflow:hidden}
.news-page-head::before{content:"";position:absolute;inset:0;
  background:radial-gradient(58% 120% at 86% 40%,rgba(193,40,46,.42) 0%,rgba(193,40,46,0) 62%)}
.news-page-inner{position:relative;padding-top:calc(var(--navh) + clamp(52px,6vw,86px));
  padding-bottom:clamp(48px,5.5vw,78px)}
.news-page-inner .kicker{color:#FF8E92}
.news-page-inner .kicker::before{background:#FF8E92}
.news-page-title{font-size:clamp(30px,4.2vw,56px);font-weight:800;letter-spacing:0;line-height:1.16;color:#fff}
.news-page-sub{margin-top:18px;font-size:clamp(14px,1.6vw,17px);line-height:1.9;letter-spacing:.5px;
  color:rgba(255,255,255,.7);max-width:760px}
.news-page-inner::after{content:"";display:block;width:56px;height:2px;background:var(--red-2);margin-top:30px}
.news-updated{margin-top:22px;font-size:12.5px;letter-spacing:1.5px;color:rgba(255,255,255,.6);
  font-variant-numeric:tabular-nums}
/* .news-count 的默认色是给深底页头用的；落在亮底的元信息行上时，
   由上面 .news-meta-line .news-count 覆盖成品牌红（粉字在白底只有 2.3:1） */
.news-count{font-style:normal;color:#FF8E92;font-weight:700}
/* 资讯头图区：四行文字进场后红杠再长出来 */
.js .news-page-inner > *{animation:fadeRise .9s var(--ease) both}
.js .news-page-inner > :nth-child(1){animation-delay:.05s}
.js .news-page-inner > :nth-child(2){animation-delay:.14s}
.js .news-page-inner > :nth-child(3){animation-delay:.26s}
.js .news-page-inner > :nth-child(4){animation-delay:.4s}
.js .news-page-inner::after{transform:scaleX(0);transform-origin:0 50%;animation:ruleGrow 1s var(--ease) .55s both}
.news-grid-list{grid-template-columns:1fr 1fr}
.news-grid-list .news-card h3{font-size:19.5px}
.news-page-links{margin-top:clamp(36px,4vw,54px);padding-top:26px;border-top:1px solid var(--line);
  display:flex;flex-wrap:wrap;gap:10px 28px}
.news-page-links a{font-size:14px;letter-spacing:1.5px;color:var(--red);font-weight:700}
.news-page-links a:hover{color:var(--red-deep)}

@media (max-width:1024px){
  .news-grid,.news-grid-list{grid-template-columns:1fr 1fr}
}
@media (max-width:600px){
  .news-grid,.news-grid-list{grid-template-columns:1fr}
  .news-page-title{letter-spacing:1px}
  .news-page-inner{padding-bottom:clamp(40px,9vw,54px)}
}

/* ============================================================
   签名动效 SIGNATURE MOTION
   一句话：品牌红随滚动生长。同一个概念用满四次，不另起别的装饰体系
   （没有粒子、没有 3D、没有彩带、没有滚动劫持）。
     1 首屏榆树标记 —— 绕着形状走的一圈光 + 从圆心散出的红环 + 跟手的双轴视差
     2 章节大数字 01–04 —— 从带子底部往上被灌满品牌红，滚过即灌满（核心）
     3 首屏标题 大榆智信 —— 一道窄掠光横向扫过，同时一根红发丝描边淡入
     4 合作方标志墙 —— 不断的慢漂移，悬停/键盘聚焦即停
   ============================================================ */

/* ---------- 1. 首屏榆树标记 ----------
   位移分三层挂在三个互不覆盖的属性上，所以"缓慢浮动"和"跟手视差"和"入场过冲"
   是三件事，不是互相抢一条 transform：
     translate （.mark-stage）= 滚动视差 --par + 鼠标视差 --mx/--my
     rotate    （.mark-spin） = 树标顺时针慢转一整圈
     transform （img 本体）   = 原有的 drift 浮动动画
   装饰三层都是 pointer-events:none，不吃点击。 */
/* 网格列写成 100% 定死：树标的宽度是 min(100%,470px)，
   如果列宽要靠这个子元素来定，百分比就成了自我参照（量出来 447.5，比原来小一圈）。
   justify-items 用 stretch，让 img 真正铺满这条列。 */
.mark-stage{position:relative;display:grid;grid-template-columns:100%;
  justify-items:stretch;align-items:center;
  grid-area:1/2/3/3;justify-self:end;align-self:center;width:min(100%,470px);
  translate:var(--mx,0px) calc(var(--par,0px) + var(--my,0px))}
/* 旋转层单独一个盒子：rotate 挂在它身上，img 的 drift（transform）和
   包裹层的视差（translate）都各自独立，三层叠加而不是互相覆盖。
   120s 一整圈 = 边缘约 12px/s，看得见在转，但不会抢正文的注意力。
   图元本身是中心对称的（alpha 质心离画布中心 0.7px），
   所以 origin 用默认的 50% 50% 就够，不会转成"画框在晃"。 */
.mark-spin{grid-area:auto;justify-self:stretch;position:relative;z-index:1;
  animation:markTurn 120s linear infinite}
@keyframes markTurn{from{rotate:0deg}to{rotate:360deg}}
.mark-stage .hero-mark{
  /* 首屏那条老规则 .hero-mark{grid-area:1/2/3/3} 现在会把 img 塞进包裹层网格的
     第二列（隐式的 0 宽列），img 直接塌成 0x0，装饰层的百分比也跟着塌。
     回到自动放置，宽度交给旋转层。 */
  display:block;grid-area:auto;justify-self:stretch;
  width:100%;height:auto;
  /* --par 会继承下来，而 .hero-mark 自己那条 translate 也认 --par：
     位移统一交给包裹层，这里必须把它自己的关掉，否则视差会走两遍 */
  translate:0 0;
  /* 老规则是 0 30px 60px：图一转，这团影子就会绕着树标转半圈，读成"光从下面打上来"。
     偏移压到 10px 后角速度只有 0.5px/s，混在一直变形的轮廓里看不出来。 */
  filter:drop-shadow(0 10px 26px rgba(52,0,0,.34))}
/* 绕环的光：conic-gradient 被一条环形遮罩裁成一圈，转起来读作"光沿着形状走"，
   而不是一张在转的盘子。遮罩内侧全空，所以树标中心始终是干净的。 */
.mark-halo,.mark-sweep,.mark-pulse{position:absolute;left:50%;top:50%;border-radius:50%;pointer-events:none}
.mark-halo{width:104%;height:104%;margin:-52% 0 0 -52%;z-index:0;opacity:.72;
  background:conic-gradient(from 0deg,
    rgba(255,233,222,0) 0deg,rgba(255,240,230,.92) 34deg,rgba(255,206,188,.22) 74deg,
    rgba(255,233,222,0) 108deg,rgba(255,233,222,0) 208deg,
    rgba(226,58,63,.6) 246deg,rgba(255,233,222,0) 302deg,rgba(255,233,222,0) 360deg);
  -webkit-mask-image:radial-gradient(closest-side,transparent 0 62%,#000 71% 87%,transparent 95%);
          mask-image:radial-gradient(closest-side,transparent 0 62%,#000 71% 87%,transparent 95%);
  -webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;
  animation:markSpin 34s linear infinite}
/* 另一道更快的光走形状前面：screen 混合，只提亮不压暗，窄窄一条 */
.mark-sweep{width:98%;height:98%;margin:-49% 0 0 -49%;z-index:2;opacity:.46;mix-blend-mode:screen;
  background:conic-gradient(from 0deg,
    rgba(255,255,255,0) 0deg,rgba(255,255,255,0) 262deg,rgba(255,246,240,.34) 292deg,
    rgba(255,255,255,.6) 304deg,rgba(255,246,240,.3) 316deg,rgba(255,255,255,0) 344deg,
    rgba(255,255,255,0) 360deg);
  -webkit-mask-image:radial-gradient(closest-side,transparent 0 40%,#000 52% 80%,transparent 92%);
          mask-image:radial-gradient(closest-side,transparent 0 40%,#000 52% 80%,transparent 92%);
  -webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;
  animation:markSpin 21s linear infinite}
@keyframes markSpin{from{rotate:0deg}to{rotate:360deg}}
/* 脉冲红环：从圆心散出去，4s 一拍，两环错开 2s，峰值透明度只有 .5 */
.mark-pulse{width:56%;height:56%;margin:-28% 0 0 -28%;z-index:3}
.mark-pulse::before,.mark-pulse::after{content:"";position:absolute;inset:0;border-radius:50%;
  border:1.5px solid var(--red-2);opacity:0;animation:markPulse 4s var(--ease) infinite}
.mark-pulse::after{animation-delay:2s}
@keyframes markPulse{
  0%{transform:scale(.4);opacity:.5}
  70%{opacity:0}
  100%{transform:scale(1.85);opacity:0}
}
/* 入场：整台（树标 + 三层光）一起过冲到位，img 自己只保留 drift 浮动 */
.js .mark-stage{opacity:0;animation:markEnter 1.25s var(--ease) .25s both}
@keyframes markEnter{0%{opacity:0;scale:.84}58%{opacity:1;scale:1.04}100%{opacity:1;scale:1}}
.js .mark-stage .hero-mark{opacity:1;animation:drift 9s ease-in-out infinite}
@media (max-width:1024px){
  .mark-stage{grid-area:3/1/4/2;width:min(74%,340px);justify-self:center;align-self:center;margin:24px 0}
}

/* ---------- 2. 章节大数字：滚动灌红（核心） ----------
   数字本来只有描边（color:transparent + -webkit-text-stroke）。这里给它叠两层
   背景并裁到字形里：第二层是一层极淡的白底（描边之外先有个可读的字腔），
   第一层才是从底部往上灌的品牌红，灌到哪全靠 --fill 这个 0–1 的数。
   和红杠那条 numDraw 描边书写动画各管一头：它动 mask-position 与 stroke-width
   （横向、一次性），这里动背景渐变的百分比（纵向、跟着滚动），互不覆盖。
   --fill 默认 1 = 无 JS 就是灌满；html.js 才压回 0 交给 JS 往上灌；
   滚动算不出来（NaN）时 JS 也写 1，终态永远是"看得见、灌满的"。 */
/* 描边书写的"起手位"挪到只挂在 .js 上：
   原来 .opener-num 的初态就是 mask-position:100%（字被扫走一大半），
   没有 JS 时数字就永远少一半。现在默认是"已经画完"的 0 0，
   只有 JS 在位、且这条带子还没进场时，才把它按回未画的状态。 */
.js .opener:not(.is-in) .opener-num{-webkit-mask-position:100% 0;mask-position:100% 0}
.opener-num{
  /* 无 JS / JS 挂掉时读到的就是这个 1：灌满、看得见。
     html.js 才把它压回 0，交给滚动往上灌。 */
  --fill:1;
  background-image:
    linear-gradient(to top,
      var(--red) 0 calc(var(--fill,1) * 100% - 10%),
      var(--red-2) calc(var(--fill,1) * 100% - 4%),
      rgba(226,58,63,.34) calc(var(--fill,1) * 100%),
      rgba(226,58,63,0) calc(var(--fill,1) * 100% + 2.5%)),
    linear-gradient(rgba(255,255,255,.08),rgba(255,255,255,.08));
  background-repeat:no-repeat;
  background-size:100% 100%,100% 100%;
  -webkit-background-clip:text;background-clip:text}
html.js .opener-num{--fill:0}
@supports not (background-clip:text){
  /* 背景裁剪不支持 → 字形灌不进颜色，那就直接给实心品牌红，
     绝不让 --fill 这套依赖背景裁剪的写法把数字变成透明的 */
  .opener-num{color:var(--red);--fill:1}
}

/* ---------- 3. 首屏标题掠光 ----------
   两层背景一起裁进字形：下层是永远铺满的实心白（文字的颜色由它负责），
   上层才是一道窄亮带在横向走。掠光层失败/关键帧失败 → 只剩纯白字；
   背景裁剪整个不支持 → 下面 @supports 把字色交还给 #fff。
   切行之后文字在 .ln-i 里，所以这条规则同时写给 .hero-title 和 .ln-i 两个节点，
   哪一层真的持有文字就在哪一层上色。 */
.hero-title,.js .hero-title .ln-i{
  background-image:
    linear-gradient(100deg,
      rgba(255,255,255,0) 0 43%,rgba(255,242,235,.9) 47%,rgba(255,255,255,1) 50%,
      rgba(255,242,235,.9) 53%,rgba(255,255,255,0) 57% 100%),
    linear-gradient(#fff,#fff);
  background-repeat:no-repeat;
  background-size:300% 100%,100% 100%;
  background-position:100% 0,0 0;
  -webkit-background-clip:text;background-clip:text;
  -webkit-text-fill-color:transparent;
  -webkit-text-stroke:0px rgba(193,40,46,.72);
  animation:titleSheen 7.4s linear infinite}
@keyframes titleSheen{
  0%,3%{background-position:100% 0,0 0;-webkit-text-stroke-width:0px}
  13%{-webkit-text-stroke-width:1px}
  23%,100%{background-position:0% 0,0 0;-webkit-text-stroke-width:0px}
}
@supports not (background-clip:text){
  .hero-title,.js .hero-title .ln-i{-webkit-text-fill-color:#fff;background-image:none;animation:none}
}

/* ---------- 4. 合作方标志墙：慢漂移 ----------
   JS 把每组的 logo 挪进轨道 .logos-run 里的两份 .logos-set（原件 + 克隆），
   轨道平移整整一个"周期"（一组宽 + 一个缝）再无缝接上，周期宽度 --p 由 JS 量出来写。
   横向行走 X，竖排的那两列走 Y（竖排改成横排会把整列高度压扁，三栏就不齐了）。
   铺不满这扇窗的组（601–1180px 首列横跨两栏时会发生）退成整组的错峰起伏 .is-wave，
   起伏只动 translate，不碰透明度和滤镜，所以原有的"聚光灯"悬停照旧。
   没有 JS 时这些节点根本不存在，标志墙还是静止居中的老样子。 */
.logos.is-drift,.logos.is-wave{position:relative;overflow:hidden;min-width:0}
.logos.is-drift{max-width:100%}
/* 一条 nowrap 的长轨道会把格子的 min-content 宽度顶到天上去（591px 下整页横向溢出）。
   网格项的自动最小尺寸就是那条 min-content，min-width:0 把它掐掉，
   轨道改由 .logos 的 overflow:hidden 裁，宽度回到栏宽本身。 */
.wall-col{min-width:0}
.logos.is-drift{
  -webkit-mask-image:linear-gradient(90deg,transparent 0,#000 26px calc(100% - 26px),transparent 100%);
          mask-image:linear-gradient(90deg,transparent 0,#000 26px calc(100% - 26px),transparent 100%)}
.logos.is-drift.logos-col{
  -webkit-mask-image:linear-gradient(180deg,transparent 0,#000 34px calc(100% - 34px),transparent 100%);
          mask-image:linear-gradient(180deg,transparent 0,#000 34px calc(100% - 34px),transparent 100%)}
.logos-run{display:flex;flex:0 0 auto;align-items:center;gap:18px 22px;width:max-content;
  animation:logoDriftX var(--mdur,42s) linear infinite;will-change:transform}
.logos-set{display:flex;flex:0 0 auto;align-items:center;gap:18px 22px}
/* 竖排的那两列走纵向：窗口高度就取"一组"的高度，和改造前一模一样，
   但起点必须顶到框顶（默认的 justify-content:center 会把整条轨道居中，
   平移一个周期就不接得上）；轨道/组的朝向由 JS 用行内样式定，
   这样量尺寸的时候不必等 class 落地 */
.logos-col.is-drift{justify-content:flex-start}
.logos-col.is-drift .logos-run{animation-name:logoDriftY}
@keyframes logoDriftX{from{transform:translate3d(0,0,0)}to{transform:translate3d(calc(var(--p,0px) * -1),0,0)}}
@keyframes logoDriftY{from{transform:translate3d(0,0,0)}to{transform:translate3d(0,calc(var(--p,0px) * -1),0)}}
/* 悬停或键盘聚焦就停住，让人看清具体是哪一家 */
.logos:hover .logos-run,.logos:focus-within .logos-run{animation-play-state:paused}
.logos.is-wave img{animation:logoWave 5.8s var(--ease) infinite;
  animation-delay:calc(var(--k,0) * .42s)}
@keyframes logoWave{0%,70%,100%{translate:0 0}24%{translate:0 -6px}}
.logos.is-wave:hover img,.logos.is-wave:focus-within img{animation-play-state:paused}
/* 漂移中的 logo 不许再被悬停抬起：整排在走，个别抬起来会脱开轨道 */
.logos.is-drift .logos-set img:hover{transform:none}
@media (max-width:600px){
  /* 单栏时同样不许被轨道顶开：1fr 的自动最小尺寸换成 0 */
  .wall{grid-template-columns:minmax(0,1fr)}
}

/* ============================================================
   2026-10-10 精修轮 · 第二批：只补状态与排版细节，不动任何版式结构
   ============================================================ */

/* 数字等宽。目录四格、卡片序号、步骤序号、痛点背景大数、列表编号都是
   "横向读不齐"的重灾区，tabular-nums 让每个数字占同一格宽。
   刻意不给 .opener-num 和 .fig strong 加：前者的灌红遮罩与描边共用一套几何，
   后者按实测字宽排滚轮格位，加了会露缝。 */
.index-num,.cap-idx,.step-idx,.pain-ghost,.num-list i{font-variant-numeric:tabular-nums}

/* 目录四格是 <a>，Tab 能走过去，但箭头 .index-go 平时 opacity:0，
   焦点落在上面等于掉进黑洞。补聚焦态：给环 + 把箭头露出来 + 序号提亮。
   outline-offset 用负值，否则环会压到相邻那一格的 1px 缝上。 */
.index-item:focus-visible{outline:2px solid var(--red);outline-offset:-5px}
.index-item:focus-visible .index-go{opacity:1;transform:none}
.index-item:focus-visible .index-num{opacity:1}

/* 触屏没有 hover，藏起来的箭头等于不存在，一律露出来 */
@media (hover:none){.index-go{opacity:1;transform:none}}

/* 两行的短说明用 balance 把两行拉齐。
   实测目录里出现过"…关键业绩数据展 / 示"这种最后一行只剩一个孤字的情况。 */
.index-item p,.rule-list li,.step p,.cap p,.num-list li,.dot-list li{text-wrap:balance}

