/* ============================================================
   effects.css —— 动效与氛围层（本次交付的核心竞争力）
   ------------------------------------------------------------------
   硬性约束：
   1) 动画**只改 transform 与 opacity**，绝不改 width/height/top/left/margin；
      渐入用 transform: translateY/scale + opacity；数据条用 scaleX。
   2) 无 JS 时内容必须可见 —— 隐藏态一律写作
      `html.js-anim .reveal:not(.is-visible)`，
      其中 .js-anim 由 <head> 内联脚本注入（JS 关闭时不会注入）。
   3) prefers-reduced-motion 下全部退化为直接显示终值。
   约束：本文件不得出现任何字面色值，一律引用 tokens.css 变量。
   ============================================================ */

/* ============================================================
   1. 渐入揭示（滚动进入视口触发 .is-visible）
   ============================================================ */
html.js-anim .reveal {
  opacity: 0;
  transform: translateY(28px);
}
html.js-anim .reveal.is-visible {
  opacity: 1;
  transform: none;
  transition:
    opacity 0.9s var(--ease-apple) var(--d, 0s),
    transform 0.9s var(--ease-apple) var(--d, 0s);
}

/* 图片揭示：scale(0.92) → 1，缓动 cubic-bezier(0.16,1,0.3,1)，1.1s */
html.js-anim .reveal--media {
  opacity: 0;
  transform: scale(0.92);
}
html.js-anim .reveal--media.is-visible {
  opacity: 1;
  transform: none;
  transition:
    opacity var(--dur-reveal-lg) var(--ease-apple) var(--d, 0s),
    transform var(--dur-reveal-lg) var(--ease-apple) var(--d, 0s);
}

/* 横向滑入（耗材集采分栏） */
html.js-anim .reveal--left {
  opacity: 0;
  transform: translate3d(-56px, 0, 0);
}
html.js-anim .reveal--right {
  opacity: 0;
  transform: translate3d(56px, 0, 0);
}
html.js-anim .reveal--left.is-visible,
html.js-anim .reveal--right.is-visible {
  opacity: 1;
  transform: none;
  transition:
    opacity var(--dur-reveal-lg) var(--ease-apple) var(--d, 0s),
    transform var(--dur-reveal-lg) var(--ease-apple) var(--d, 0s);
}

/* ---------- 逐行浮起（标题按行包裹） ---------- */
.line {
  display: block;
  overflow: hidden;
  padding-bottom: 0.06em;   /* 避免中文下沿被裁 */
}
.line__in {
  display: block;
}
html.js-anim .line__in {
  transform: translateY(105%);
  opacity: 0;
}
html.js-anim .is-visible .line__in {
  transform: none;
  opacity: 1;
  transition:
    transform 1s var(--ease-apple) var(--d, 0s),
    opacity 0.9s var(--ease-apple) var(--d, 0s);
}

/* ---------- 错峰延迟（最多 8 档，每档 80ms） ---------- */
.reveal-group > *:nth-child(1) { --d: 0.04s; }
.reveal-group > *:nth-child(2) { --d: 0.12s; }
.reveal-group > *:nth-child(3) { --d: 0.2s; }
.reveal-group > *:nth-child(4) { --d: 0.28s; }
.reveal-group > *:nth-child(5) { --d: 0.36s; }
.reveal-group > *:nth-child(6) { --d: 0.44s; }
.reveal-group > *:nth-child(7) { --d: 0.52s; }
.reveal-group > *:nth-child(8) { --d: 0.6s; }

/* 行级错峰 */
.line-group > .line:nth-child(1) .line__in { transition-delay: 0.06s; }
.line-group > .line:nth-child(2) .line__in { transition-delay: 0.14s; }
.line-group > .line:nth-child(3) .line__in { transition-delay: 0.22s; }
.line-group > .line:nth-child(4) .line__in { transition-delay: 0.3s; }

/* ============================================================
   2. 氛围层：网格 / 辉光 / 扫描光 / 噪点
   ============================================================ */
.field {
  position: absolute;
  inset: 0;
  pointer-events: none;
  overflow: hidden;
}
/* 网格层向外扩出一格，位移一个格距后无缝循环 —— 只动 transform */
.field--grid {
  inset: -60px;
  background-image:
    linear-gradient(var(--grid-line) 1px, transparent 1px),
    linear-gradient(90deg, var(--grid-line) 1px, transparent 1px);
  background-size: 60px 60px;
  opacity: 0.55;
  animation: gridDrift 40s linear infinite;
  will-change: transform;
}
.field--vignette {
  background-image: var(--vignette);
}
.field--top-fade {
  background-image: var(--fade-top);
}

.glow {
  position: absolute;
  width: var(--glow-size);
  height: var(--glow-size);
  border-radius: 50%;
  filter: blur(var(--glow-blur));
  pointer-events: none;
}
.glow--blue { background-image: var(--glow-radial); }
.glow--purple { background-image: var(--glow-purple); }
.glow--cyan { background-image: var(--glow-cyan); }

/* 扫描光（仅 Hero 一处） */
.scan {
  position: absolute;
  top: 28%;
  left: 0;
  width: 40%;
  height: 1px;
  background-image: linear-gradient(90deg, transparent, var(--brand-cyan-lt), transparent);
  opacity: 0.5;
  animation: scanSweep 8s var(--ease-out) infinite;
}

/* ============================================================
   3. Hero 动效
   ============================================================ */
/* 极缓慢持续缩放（20s 呼吸），只动 transform */
.hero__breath {
  animation: heroBreath var(--dur-breath) var(--ease-out) infinite alternate;
  transform-origin: 50% 46%;
  will-change: transform;
}

/* 鼠标跟随光晕（桌面端由 JS 写 transform）
   合成层纪律：未激活时既不绘制也不进合成层 —— visibility:hidden 阻止绘制，
   will-change 只在 .is-on（由 nav.js 真正启用光斑时同步挂上）期间生效，
   移动端 / 未悬停时该 640×640 层不占用合成层内存。 */
.hero__cursor-glow {
  position: absolute;
  top: 0; left: 0;
  width: 640px; height: 640px;
  margin: -320px 0 0 -320px;
  border-radius: 50%;
  background-image: var(--glow-radial);
  filter: blur(60px);
  opacity: 0;
  visibility: hidden;
  transition:
    opacity 0.6s var(--ease-out),
    visibility 0s linear 0.6s;
  pointer-events: none;
}
html.js-anim .hero__cursor-glow.is-on {
  opacity: 0.85;
  visibility: visible;
  will-change: transform;
  transition:
    opacity 0.6s var(--ease-out),
    visibility 0s linear 0s;
}

/* 滚动提示：细微上下浮动 */
.hero__cue-arrow { animation: cueFloat 2.4s var(--ease-out) infinite; }
.hero__cue-text { opacity: 0.7; }

/* ============================================================
   4. 粘性叙事（S3 设备租赁）
   ------------------------------------------------------------------
   两种状态：
   · 默认（无 JS / JS 失败）：非粘性普通流，四步全部可见；
   · html.js-anim（JS 就绪）：position: sticky + 步骤叠放切换。
   ============================================================ */
.scene {
  position: relative;
  background-color: var(--bg-void);
  padding-block: clamp(56px, 10vw, 96px);
}
.scene__sticky {
  position: relative;
  display: block;
}
.scene__stage {
  position: relative;
  aspect-ratio: 1536 / 904;
  margin-bottom: var(--sp-4);
  border-radius: var(--radius-lg);
  overflow: hidden;
  border: 1px solid var(--border-1);
  box-shadow: var(--shadow-plate);
}
.scene__img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  transform-origin: 50% 50%;
}
.scene__veil {
  position: absolute;
  inset: 0;
  background-image: var(--scrim-plate);
}
.scene__inner {
  position: relative;
  z-index: 2;
  width: 100%;
}
/* 无 JS：四步依次普通流排列，全部可见 */
.scene__steps { position: relative; margin-top: var(--sp-4); }
.scene__step { margin-bottom: var(--sp-3); }

/* ---------- JS 就绪：开启粘性 + 步骤切换 ---------- */
html.js-anim .scene {
  height: 340vh;
  height: 340svh;
  padding-block: 0;
}
html.js-anim .scene__sticky {
  position: sticky;
  top: 0;
  height: 100vh;
  height: 100svh;
  overflow: hidden;
  display: flex;
  align-items: center;
}
html.js-anim .scene__stage {
  position: absolute;
  inset: clamp(12px, 3vw, 48px);
  aspect-ratio: auto;
  margin-bottom: 0;
  transform-origin: 50% 50%;
}
/* 注意：.scene__stage 与 .scene__img 的 will-change **不在此静态声明**，
   统一由 scroll-engine.js 的 setWillChange() 按需挂载（滚动活跃时加、
   空闲 420ms 后撤），与 [data-drive] 元素共用同一套机制，
   避免常驻合成层。此处若写静态 will-change 会盖住 JS 的置空逻辑。 */
html.js-anim .scene__veil { background-image: var(--scrim-left); }

/* 步骤叠放在同一格，仅活跃项可见（只动 opacity / transform） */
html.js-anim .scene__steps {
  min-height: 176px;
  position: relative;
}
html.js-anim .scene__step {
  position: absolute;
  inset: 0;
  margin-bottom: 0;
  opacity: 0;
  transform: translateY(18px);
  transition:
    opacity 0.5s var(--ease-apple),
    transform 0.5s var(--ease-apple);
  pointer-events: none;
}
html.js-anim .scene__step.is-active {
  opacity: 1;
  transform: none;
}

.scene__step-no {
  display: block;
  font-size: var(--fs-caption);
  letter-spacing: 0.2em;
  color: var(--brand-blue-lt);
  margin-bottom: 6px;
}
.scene__step-name {
  font-size: var(--fs-h3);
  line-height: var(--lh-h3);
  margin-bottom: 6px;
}
.scene__step-desc {
  font-size: var(--fs-small);
  line-height: var(--lh-small);
  color: var(--text-3);
  max-width: 34ch;
}

/* 胶囊进度条 */
.scene__pills {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  margin-top: var(--sp-3);
}
.scene__pills .pill.is-active {
  color: var(--text-1);
  border-color: var(--border-hover);
  background: var(--bg-l3);
  box-shadow: var(--glow-sm);
}

/* ============================================================
   5. 移动端 / 解粘性降级（≤768px 简化粘性叙事）
   ============================================================ */
@media (max-width: 768px) {
  html.js-anim .scene { height: auto; padding-block: clamp(56px, 12vw, 88px); }
  html.js-anim .scene__sticky {
    position: static;
    height: auto;
    display: block;
    overflow: visible;
  }
  html.js-anim .scene__stage {
    position: relative;
    inset: auto;
    aspect-ratio: 1536 / 904;
    margin-bottom: var(--sp-4);
  }
  html.js-anim .scene__veil { background-image: var(--scrim-plate); }
  html.js-anim .scene__steps { min-height: 0; }
  html.js-anim .scene__step {
    position: static;
    opacity: 1;
    transform: none;
    margin-bottom: var(--sp-3);
    pointer-events: auto;
  }
}

/* ============================================================
   6. 关键帧
   ============================================================ */
@keyframes heroBreath {
  from { transform: scale(1) translate3d(0, 0, 0); }
  to   { transform: scale(1.06) translate3d(0, -1.2%, 0); }
}

@keyframes gridDrift {
  from { transform: translate3d(0, 0, 0); }
  to   { transform: translate3d(60px, 60px, 0); }
}

@keyframes scanSweep {
  0%   { transform: translate3d(-60%, 0, 0); opacity: 0; }
  18%  { opacity: 0.55; }
  82%  { opacity: 0.55; }
  100% { transform: translate3d(260%, 0, 0); opacity: 0; }
}

@keyframes cueFloat {
  0%, 100% { transform: translate3d(0, 0, 0); opacity: 0.55; }
  50%      { transform: translate3d(0, 8px, 0); opacity: 1; }
}

/* ============================================================
   7. 降级：prefers-reduced-motion
   所有动效退化为直接显示终值，不做位移
   ============================================================ */
@media (prefers-reduced-motion: reduce) {
  html.js-anim .reveal,
  html.js-anim .reveal--media,
  html.js-anim .reveal--left,
  html.js-anim .reveal--right {
    opacity: 1 !important;
    transform: none !important;
  }
  html.js-anim .line__in { transform: none !important; opacity: 1 !important; }
  .hero__breath,
  .field--grid,
  .scan,
  .hero__cue-arrow { animation: none !important; }
  .bar__fill { transform: scaleX(var(--w, 1)) !important; }
  .hero__cursor-glow { display: none; }

  /* 粘性叙事退化为普通块级，全部步骤直接可见 */
  html.js-anim .scene { height: auto; padding-block: var(--section-py); }
  html.js-anim .scene__sticky {
    position: static;
    height: auto;
    display: block;
    overflow: visible;
  }
  html.js-anim .scene__stage {
    position: relative;
    inset: auto;
    aspect-ratio: 1536 / 904;
    margin-bottom: var(--sp-4);
  }
  html.js-anim .scene__veil { background-image: var(--scrim-plate); }
  html.js-anim .scene__steps { min-height: 0; }
  html.js-anim .scene__step {
    position: static;
    opacity: 1 !important;
    transform: none !important;
    margin-bottom: var(--sp-3);
    pointer-events: auto;
  }
}
