/* Homepage-only motion: light from the central star, quiet supporting feedback.
   暂停入口已移除（用户 2026-10-12 要求）：首屏观感已定稿，不再给访客一个
   会把整页动画掐停的按钮。系统级的 `prefers-reduced-motion` 仍然生效，
   见 motion.js 的 `paused()`。 */

.space { transform-origin: 50% var(--star-y, 41%); }

.space { translate: var(--look-x, 0px) var(--look-y, 0px); }

.depth-field { position:absolute; inset:0; width:100%; height:100%; pointer-events:none; }

.motion-ready .space { animation: galaxy-drift 12s ease-in-out -4s infinite alternate; }

.star-bloom {
  position: absolute;
  left: 50%;
  top: var(--star-y, 41%);
  width: 320px;
  height: 320px;
  margin: -160px 0 0 -160px;
  border-radius: 50%;
  pointer-events: none;
  background: radial-gradient(circle, #f4faff80 0, #bbdeff42 4%, #70b1ff19 24%, transparent 66%);
  opacity: 0;
}

.motion-ready .star-bloom { animation: star-breathe 4s ease-in-out -1s infinite; }

.stardust { position: absolute; width: 2px; height: 2px; border-radius: 50%; background: #d0e7ff; opacity: 0; pointer-events: none; }

.motion-ready .stardust { animation: star-shimmer var(--duration, 5s) ease-in-out var(--delay, 0s) infinite alternate; }

.motion-ready .space, .motion-ready .star-bloom, .motion-ready .stardust { animation-play-state: paused; }

.motion-ready:not(.motion-paused) .hero.motion-active .space,
.motion-ready:not(.motion-paused) .hero.motion-active .star-bloom,
.motion-ready:not(.motion-paused) .hero.motion-active .stardust { animation-play-state: running; }

/* 技术开发图在 index.html 已内联成 <svg>（带 .dev-plane / .dev-link 类），
   不再走 <img>，所以 hover 目标从 img 改成 svg。 */
.development-art svg { display: block; width: 100%; height: 100%; }

.motion-ready .development-art svg { transition: transform .8s cubic-bezier(.16,1,.3,1); }

.motion-ready:not(.motion-paused) .development:hover .development-art svg,
.motion-ready:not(.motion-paused) .development:focus-within .development-art svg { transform: translateY(-7px) rotate(-3deg); }

.motion-ready .geo .orbit { transition: border-color .4s; }

.motion-ready:not(.motion-paused) .geo.motion-active:is(:hover,:focus-within) .o1 { animation: orbit-signal 14s linear infinite; border-color: #bddaffbb; }

.motion-paused *, .motion-paused *::before, .motion-paused *::after { animation-play-state: paused !important; }

@keyframes galaxy-drift { from { transform: scale(1.015) rotate(-.35deg); } to { transform: scale(1.115) rotate(.65deg); } }

@keyframes star-breathe { 0%,100% { opacity: .08; transform: scale(.6); } 50% { opacity: 1; transform: scale(1.85); } }

@keyframes star-shimmer { 0%,100% { opacity: .12; transform: translate(-12px, 9px) scale(.6); } 50% { opacity: .9; transform: translate(14px, -12px) scale(1.4); } }

@keyframes orbit-signal { from { transform: rotate(-30deg) scaleY(.55); } to { transform: rotate(330deg) scaleY(.55); } }

/* V2: visible depth travel and a sparse passing streak, not only twinkling. */
.meteor { position:absolute; left:4%; top:17%; width:150px; height:1px; background:linear-gradient(90deg,transparent,#b9dcff); opacity:0; pointer-events:none; }

.motion-ready .meteor { animation:meteor-pass 10s linear -1s infinite paused; }

.motion-ready:not(.motion-paused) .hero.motion-active .meteor { animation-play-state:running; }

@keyframes meteor-pass { 0% {opacity:0;transform:rotate(24deg) translateX(-160px)} 5%{opacity:.65} 27%{opacity:0;transform:rotate(24deg) translateX(75vw)} 100%{opacity:0;transform:rotate(24deg) translateX(75vw)} }

/* 这里原来挂着 .business{overflow:clip; overflow-clip-margin:max(var(--gutter),
   calc((100vw - 100%) / 2))}，想拦住 nebula-flow 的 scale(1.04→1.1)。
   实测两条都不成立，已撤掉：
   1) overflow-clip-margin 只接受纯 length，含 % 或 calc() 的写法整条被丢弃，
      裁切边界实际贴在 1248px 盒边——氛围图在宽屏下被横切，两侧还是黑的。
   2) overflow:clip 两轴同裁，把氛围图 ::before 的 -120px 上出血也剪掉了。
   现在改由 style.css 的 body{overflow-x:clip} 在视口级裁横向；
   nebula-flow 的 translateX(±16px) scale(1.1) 因此可以正常溢出——这正是想要的效果。 */

.motion-ready .business::before { animation:nebula-flow 13s ease-in-out -3s infinite alternate paused; }

.motion-ready:not(.motion-paused) .business.motion-active::before { animation-play-state:running; }

@keyframes nebula-flow { from{transform:translateX(-16px) scale(1.04);opacity:.24} to{transform:translateX(16px) scale(1.1);opacity:.42} }

/* V3: scroll-linked depth — the sky keeps opening as the headline recedes. */
.space { scale: calc(1 + var(--hero-p, 0) * .085); }

/* 星场随滚动优雅退场：--hero-p 由 motion.js 每帧写入 :root（0→1，约滚过首屏 82% 高度时到 1）。
   整片星海（canvas + bloom + 16 颗 stardust + meteor 都挂在 .space 下）随它淡出，
   与下方 business 的「到位爆发」形成交接而非互吼（节奏复核发现的唯一过密点 hero↔business）。
   用 1 - --hero-p（比 .hero-copy 的 1 - 1.45·hero-p 更缓），让文案先退、星空后隐，
   贴合「文案后退、天空继续展开」的原意。父级 opacity 与子元素关键帧 opacity 相乘，不冲突。
   reduced-motion 下 --hero-p 被强制 0，此处 opacity 恒为 1，无副作用。 */
.space { opacity: calc(1 - var(--hero-p, 0)); }

.hero-copy { transform: translateY(calc(var(--hero-p, 0) * -70px)); opacity: calc(1 - var(--hero-p, 0) * 1.45); }

.hero::before, .hero::after { opacity: calc(1 - var(--hero-p, 0) * .3); }

.business::after { opacity: calc(.55 + var(--hero-p, 0) * .45); }

/* ── 第 1 档动效：翻页信号 + 每屏一个活的焦点 ──────────────────────────
   三条纪律（都踩过坑，别破）：
   1) 只挂内容物，不挂背景光——L1(body::before) 与 L2(各屏 ::before/::after 的
      --lt-* 配方) 是逐像素调出来的，禁止给它们加 opacity/transform/animation。
   2) 只在屏内跑：一律用 .motion-active 门控（IntersectionObserver threshold .08）。
   3) 两套暂停都要听：html.motion-paused 还覆盖「标签页被切走」，
      单靠 @media(prefers-reduced-motion) 挡不住。 */

/* 2a 章首横线扫入：屏进入视口时从 0 扫到满宽。
   无 JS 时（:not(.motion-ready)）保持满宽——否则 motion.js 一旦加载失败，
   五个屏的章首横线会永远停在 0 宽，是条静默消失的分隔线。 */
.business,.about,.approach,.scope-section,.contact{background-size:0 1px;transition:background-size .9s cubic-bezier(.16,1,.3,1)}

html:not(.motion-ready) .business,html:not(.motion-ready) .about,html:not(.motion-ready) .approach,html:not(.motion-ready) .scope-section,html:not(.motion-ready) .contact{background-size:100% 1px}

.business.motion-active,.about.motion-active,.approach.motion-active,.scope-section.motion-active,.contact.motion-active{background-size:100% 1px}

/* 2b 章节标签唤醒：只动 color。enter() 已经在用 WAAPI 动这些元素的
   opacity/transform 了，这里再碰就会打架。基色 style.css:473 的 #96abc7。 */
html.motion-ready:not(.motion-paused) .business.motion-active .kicker,
html.motion-ready:not(.motion-paused) .about.motion-active .kicker,
html.motion-ready:not(.motion-paused) .approach.motion-active .kicker,
html.motion-ready:not(.motion-paused) .scope-section.motion-active .kicker,
html.motion-ready:not(.motion-paused) .contact.motion-active .kicker{animation:kicker-wake 1.1s ease-out}

@keyframes kicker-wake{0%{color:var(--line-strong)}30%{color:#c4e3ff}100%{color:#96abc7}}

/* 3-1 业务屏：signal 图形。nucleus 呼吸 + o2 慢转。
   o2 的关键帧必须带上 scaleY(.6)——基值 .o2{transform:rotate(34deg) scaleY(.6)}，
   丢了椭圆就塌成正圆。o1 留给 hover 的 orbit-signal，不抢。 */
html.motion-ready:not(.motion-paused) .business.motion-active .geo .nucleus{animation:nucleus-breathe 5.5s ease-in-out infinite}

@keyframes nucleus-breathe{
  0%,100%{box-shadow:0 0 36px 10px #457ee64d;transform:scale(1)}
  50%{box-shadow:0 0 52px 16px #457ee680;transform:scale(1.12)}
}

html.motion-ready:not(.motion-paused) .business.motion-active .geo .o2{animation:orbit-drift 44s linear infinite}

@keyframes orbit-drift{from{transform:rotate(34deg) scaleY(.6)}to{transform:rotate(394deg) scaleY(.6)}}

/* 3-2 关于屏：事实表分隔细线上依次扫过一段亮线。
   两层背景——第 1 层暗线恒在（分隔线任何时候都不能消失），第 2 层才是亮段；
   keyframes 里两层 background-position 都要写全，漏一层等于把它重置。
   .about-facts>div+div 命中的是第 2/3/4 个子项，共 3 条线（4 行只有 3 条分隔线）。 */
html.motion-ready:not(.motion-paused) .about.motion-active .about-facts>div+div{
  background-image:linear-gradient(90deg,transparent,#c4e3ff,transparent),var(--rule);
  background-size:22% 1px,100% 1px;
  animation:fact-line-sweep 6s ease-in-out infinite}

html.motion-ready:not(.motion-paused) .about.motion-active .about-facts>div:nth-child(2){animation-delay:0s}
html.motion-ready:not(.motion-paused) .about.motion-active .about-facts>div:nth-child(3){animation-delay:.5s}
html.motion-ready:not(.motion-paused) .about.motion-active .about-facts>div:nth-child(4){animation-delay:1s}

@keyframes fact-line-sweep{
  0%{background-position:-30% top,left top}
  100%{background-position:110% top,left top}
}

/* 3-3 方法屏：01–04 序号下那条 24px 短横线依次点亮。
   必须限定在 .approach-steps 下——.step 在 geo.css:35（.geo-process .step）里
   另有一份、子页在用，选择器放宽会误伤 geo.html / development.html。 */
html.motion-ready:not(.motion-paused) .approach.motion-active .approach-steps li .step::before{animation:step-tick 4.8s ease-in-out infinite}

html.motion-ready:not(.motion-paused) .approach.motion-active .approach-steps li:nth-child(1) .step::before{animation-delay:0s}
html.motion-ready:not(.motion-paused) .approach.motion-active .approach-steps li:nth-child(2) .step::before{animation-delay:.35s}
html.motion-ready:not(.motion-paused) .approach.motion-active .approach-steps li:nth-child(3) .step::before{animation-delay:.7s}
html.motion-ready:not(.motion-paused) .approach.motion-active .approach-steps li:nth-child(4) .step::before{animation-delay:1.05s}

@keyframes step-tick{
  0%,100%{background:var(--line-strong);width:24px}
  50%{background:#c4e3ff;width:34px}
}

/* 3-4 服务范围屏：表格上方那条线，单条慢扫（跟关于屏三条快扫区分开）。 */
html.motion-ready:not(.motion-paused) .scope-section.motion-active .scope-wrap{
  background-image:linear-gradient(90deg,transparent,#c4e3ff,transparent),var(--rule);
  background-size:18% 1px,100% 1px;
  animation:scope-line-sweep 7.5s ease-in-out infinite}

@keyframes scope-line-sweep{
  0%{background-position:-30% top,left top}
  100%{background-position:110% top,left top}
}

/* 3-5 联系屏：星点呼吸。不动它上面那条 132px 线——一屏只一个焦点。 */
html.motion-ready:not(.motion-paused) .contact.motion-active .contact-channel::after{animation:contact-star-breathe 4.5s ease-in-out infinite}

@keyframes contact-star-breathe{
  0%,100%{opacity:1;box-shadow:0 0 14px 5px #457ee659}
  50%{opacity:.62;box-shadow:0 0 22px 9px #457ee699}
}

/* ── 第 2 档动效：滚动联动深度 + 到位事件 ──────────────────────────
   纪律沿用第 1 档：只动内容物、只在屏内/系统允许时跑、两套暂停都听。
   新增一条：--dp 是 scroll 每帧写入的连续倍率（不是进出开关），
   所以走 html.motion-ready:not(.motion-paused) 即可，不再叠 .motion-active。 */

/* ① 滚动联动深度：--dp 由 motion.js 写入（-1 离场 → +1 入场，居中 0）。
   正倍率 = 跟着滚动「往前走」（前景），负倍率 =「往后退」（背景）。
   这些容器本身没有 transform 动画——背景光在 ::before/::after，第 1 档动画在子元素或
   background-position——所以 translateY 不会和任何既有 transform 抢。 */
html.motion-ready:not(.motion-paused) .business .signal { transform: translateY(calc(var(--dp, 0) * 30px)); }
html.motion-ready:not(.motion-paused) .business .development-art { transform: translateY(calc(var(--dp, 0) * -52px)); }
html.motion-ready:not(.motion-paused) .about .about-facts { transform: translateY(calc(var(--dp, 0) * -10px)); }
html.motion-ready:not(.motion-paused) .about .about-story { transform: translateY(calc(var(--dp, 0) * 10px)); }
html.motion-ready:not(.motion-paused) .approach .approach-steps li:nth-child(2) { transform: translateY(calc(var(--dp, 0) * 5px)); }
html.motion-ready:not(.motion-paused) .approach .approach-steps li:nth-child(3) { transform: translateY(calc(var(--dp, 0) * 10px)); }
html.motion-ready:not(.motion-paused) .approach .approach-steps li:nth-child(4) { transform: translateY(calc(var(--dp, 0) * 15px)); }
html.motion-ready:not(.motion-paused) .scope-section .scope-head { transform: translateY(calc(var(--dp, 0) * -8px)); }
html.motion-ready:not(.motion-paused) .scope-section .scope-wrap { transform: translateY(calc(var(--dp, 0) * 8px)); }
html.motion-ready:not(.motion-paused) .contact .contact-channel { transform: translateY(calc(var(--dp, 0) * 14px)); }

/* .art 自带 transform .65s 过渡（style.css:328），--dp 每帧改 transform 会被它缓动成
   拖影。motion 态下撤掉 transform 过渡、只留 opacity，让视差干净跟手。 */
html.motion-ready:not(.motion-paused) .business .art { transition: opacity .5s ease; }

/* ② 到位事件：每屏进入视口（.motion-active）时，内容物做一次「落位 / 点亮」的爆发。
   与第 1 档的区别：第 1 档是「屏内持续呼吸」，第 2 档是「刚到位那一下」的层次感。
   所有爆发都避开被占用的属性——--dp 占了 transform，这里改用独立 scale / opacity /
   transition，互不打架。 */

/* 2-1 业务屏图形点亮：整组图形快速「亮一下」再归位。scale 独立属性不与 --dp 的
   transform 冲突；opacity 走 .art 既有过渡。两张卡 stagger 70ms。 */
html.motion-ready:not(.motion-paused) .business.motion-active .art { animation: art-pop 1.2s cubic-bezier(.16,1,.3,1) both; }
html.motion-ready:not(.motion-paused) .business.motion-active .development .art { animation-delay: .07s; }

@keyframes art-pop {
  0% { opacity: .5; scale: .94; }
  55% { opacity: 1; scale: 1.05; }
  100% { opacity: 1; scale: 1; }
}

/* 2-2 关于屏四事实依次落位：未进入时压低+半透明，进入后回落归位，按行 stagger。
   transform/opacity 走 transition，与第 1 档的 background-position 扫线（div+div）各管各的属性。 */
html.motion-ready:not(.motion-paused) .about .about-facts > div {
  transition: opacity .7s cubic-bezier(.16,1,.3,1), transform .7s cubic-bezier(.16,1,.3,1);
}
html.motion-ready:not(.motion-paused) .about:not(.motion-active) .about-facts > div { opacity: .28; transform: translateY(18px); }
html.motion-ready:not(.motion-paused) .about .about-facts > div:nth-child(1) { transition-delay: 0s; }
html.motion-ready:not(.motion-paused) .about .about-facts > div:nth-child(2) { transition-delay: .09s; }
html.motion-ready:not(.motion-paused) .about .about-facts > div:nth-child(3) { transition-delay: .18s; }
html.motion-ready:not(.motion-paused) .about .about-facts > div:nth-child(4) { transition-delay: .27s; }

/* 2-3 方法屏四步依次落位：--dp 已占用 li 的 transform（逐屏视差），到位改用
   opacity + 独立 scale。第 1 档的 24px 短横线仍在各自脉冲。 */
html.motion-ready:not(.motion-paused) .approach .approach-steps li {
  transition: opacity .7s cubic-bezier(.16,1,.3,1), scale .7s cubic-bezier(.16,1,.3,1);
}
html.motion-ready:not(.motion-paused) .approach:not(.motion-active) .approach-steps li { opacity: .25; scale: .96; }
html.motion-ready:not(.motion-paused) .approach .approach-steps li:nth-child(1) { transition-delay: 0s; }
html.motion-ready:not(.motion-paused) .approach .approach-steps li:nth-child(2) { transition-delay: .1s; }
html.motion-ready:not(.motion-paused) .approach .approach-steps li:nth-child(3) { transition-delay: .2s; }
html.motion-ready:not(.motion-paused) .approach .approach-steps li:nth-child(4) { transition-delay: .3s; }

/* 2-4 范围屏表格区块轻浮入：--dp 占用 .scope-wrap 的 transform，到位用 opacity + 独立 scale。
   第 1 档的连线扫光（background-position）照常跑，不冲突。 */
html.motion-ready:not(.motion-paused) .scope-section .scope-wrap {
  transition: opacity .8s cubic-bezier(.16,1,.3,1), scale .8s cubic-bezier(.16,1,.3,1);
}
html.motion-ready:not(.motion-paused) .scope-section:not(.motion-active) .scope-wrap { opacity: .3; scale: .985; }

/* 2-5 联系屏星点扩：在「呼吸」（opacity+box-shadow，第 1 档）之外叠一次 scale 爆发。
   两个 animation 各管各的属性（breathe 管 opacity/box-shadow，pop 管 scale），并存。 */
html.motion-ready:not(.motion-paused) .contact.motion-active .contact-channel::after {
  animation: contact-star-breathe 4.5s ease-in-out infinite, contact-star-pop 1.3s cubic-bezier(.16,1,.3,1) both;
}
@keyframes contact-star-pop {
  0% { scale: .6; }
  45% { scale: 1.9; }
  100% { scale: 1; }
}

/* ②之二 技术开发图（已内联 SVG）：三层平面随进入轻微分离合拢，连接虚线持续流动。
   动 .development-art 里的 svg 子元素，不与 .development-art 自身的 --dp translateY 冲突。 */
html.motion-ready:not(.motion-paused) .development.motion-active .development-art .dev-plane-top { animation: plane-lift 8s ease-in-out infinite alternate; }
html.motion-ready:not(.motion-paused) .development.motion-active .development-art .dev-plane-bottom { animation: plane-sink 8s ease-in-out infinite alternate; }
html.motion-ready:not(.motion-paused) .development.motion-active .development-art .dev-link { animation: dash-flow 3s linear infinite; }

@keyframes plane-lift { from { transform: translateY(0); } to { transform: translateY(-8px); } }
@keyframes plane-sink { from { transform: translateY(0); } to { transform: translateY(8px); } }
@keyframes dash-flow { from { stroke-dashoffset: 0; } to { stroke-dashoffset: -32; } }

@media(max-width:700px) {
  .stardust:nth-of-type(n+10) { display: none; }
  .star-bloom { width: 200px; height: 200px; margin: -100px 0 0 -100px; }
}

/* Mobile keeps the authored sky and layout, with stable scrolling surfaces.
   No repeated dim/reveal, scroll fade, parallax, or decorative paint loops.
   Scope to the homepage; service-page interactions retain their own behavior. */
@media (max-width:700px), (pointer:coarse) {
  html.home-page main *,
  html.home-page main *::before,
  html.home-page main *::after {
    animation: none !important;
  }
  html.home-page .depth-field,
  html.home-page .star-bloom,
  html.home-page .stardust,
  html.home-page .meteor { display:none; }
  html.home-page .space {
    opacity:.94; transform:none; translate:none; scale:none;
  }
  html.home-page .hero-copy { opacity:1; transform:none; }
  html.home-page .hero::before,
  html.home-page .hero::after,
  html.home-page .business::after { opacity:1; }
  html.home-page .business,
  html.home-page .about,
  html.home-page .approach,
  html.home-page .scope-section,
  html.home-page .contact { background-size:100% 1px; transition:none; }
  html.home-page .about .about-facts > div,
  html.home-page .approach .approach-steps li,
  html.home-page .scope-section .scope-wrap {
    opacity:1 !important; transform:none !important; scale:none !important;
    transition:none !important;
  }
}

@media(prefers-reduced-motion:reduce){.star-bloom, .stardust, .depth-field { display: none; }
  .motion-ready .space { animation: none; transform: none; } .meteor{display:none} .motion-ready .business::before{animation:none;transform:none} .space { scale: none; }
  .hero-copy { transform: none; opacity: 1; }
  .hero::before, .hero::after, .business::after { opacity: 1; }
  /* 章首横线必须还原成满宽——关动效的用户若停在 0 宽，分隔线就永远不出现。 */
  .business,.about,.approach,.scope-section,.contact{background-size:100% 1px;transition:none}
  /* 第 1 档动效：全部关掉，并还原静态基值。 */
  .kicker{animation:none}
  .geo .nucleus,.geo .o2,.approach-steps li .step::before,.contact-channel::after,.scope-wrap{animation:none}
  .about-facts>div+div,.scope-wrap{background-image:var(--rule);background-size:100% 1px;background-position:left top;animation:none}
  .approach-steps li .step::before{background:var(--line-strong);width:24px}
  /* 第 2 档动效：--dp / 到位全部关掉，并还原基值（transform 不是 animation/transition，
     上面的全局 !important 拦不住，这里显式归零）。 */
  .business .signal,.business .development-art,.about .about-facts,.about .about-story,.approach .approach-steps li,.scope-section .scope-head,.scope-section .scope-wrap,.contact .contact-channel{transform:none}
  .about .about-facts>div,.approach .approach-steps li,.scope-section .scope-wrap{opacity:1;scale:1;transition:none;animation:none}
  .business .art,.development-art .dev-plane-top,.development-art .dev-plane-bottom,.development-art .dev-link,.contact-channel::after{animation:none}
  .development-art .dev-plane-top,.development-art .dev-plane-bottom{transform:none}
}
