/* ============================================================
   川合汇海 · 动效层  motion.css
   ------------------------------------------------------------
   设计原则：
   1) 一切动效都在 GPU 合成层上做（只动 transform / opacity /
      stroke-dashoffset），不触发布局重排
   2) 意象统一为「水」——流动、汇聚、呼吸，不做弹跳、闪烁那类廉价效果
   3) 全部包在 prefers-reduced-motion: no-preference 里，
      用户开了「减少动态效果」就彻底静音
   4) 依赖 JS 才生效的隐藏效果一律挂在 html.js-motion 下，
       JS 挂了内容依然可见（不能被动画藏死）
   ============================================================ */

/* ---------- 0. 无障碍：尊重系统「减少动态效果」 ----------
   原则一句话：**「减少动态效果」是「别动」，不是「别显示」。**
   本项目的降级必须落在"静止"，绝不能落在"消失"。
   这条原则已经被违反过三次，每次都是同一种错法 —— 把降级写成了删除：
     1) 徽标：stroke-dashoffset:100 写在媒体查询外，JS 没跑到 → 描边永久不可见
     2) 字标：<symbol> 缺 fill="currentColor" → 渲染成黑色，深色页脚上黑底黑字
     3) 首屏：这里曾写过 .hero-flows{display:none} → 整个视觉被拿掉

   所以本区块**只压动画时长，不设 display:none**。
   首屏视频同理：现在是「照播」（站长要求"打开就播放"，见 app.js 的 shouldAutoplay()）。
   将来若要改成不播，请改 shouldAutoplay() —— 不要用 CSS 藏。 */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .001ms !important;
    scroll-behavior: auto !important;
  }
  html.js-motion [data-reveal] {
    opacity: 1 !important;
    transform: none !important;
    filter: none !important;
  }
  /* 减少动态效果时，首屏视频**不隐藏**，只是不播（停在 poster 静帧上）。
     这条规则由 assets/app.js 执行 —— 它决定不调用 play()，而不是用 CSS 藏起来。
     之所以不写成 CSS display:none：那正是本项目栽过三次的"把降级写成删除"。 */
}

/* ---------- 1. 顶部滚动进度条 ---------- */
.scroll-progress {
  position: fixed; top: 0; left: 0; right: 0;
  height: 2.5px; z-index: 120; pointer-events: none;
  background: transparent;
}
.scroll-progress > span {
  display: block; height: 100%; width: 100%;
  transform: scaleX(0); transform-origin: 0 50%;
  background: linear-gradient(90deg, var(--amber), var(--sea-2), #7FC3D2);
  will-change: transform;
}
@media (prefers-reduced-motion: no-preference) {
  .scroll-progress > span { transition: transform .1s linear; }
}

/* ---------- 2. Hero 极光背景 ---------- */
@media (prefers-reduced-motion: no-preference) {
  .hero::before {
    content: "";
    position: absolute; inset: -25% -12%;
    z-index: 0; pointer-events: none;
    background:
      radial-gradient(38% 40% at 16% 24%, rgba(196,105,42,.20), transparent 62%),
      radial-gradient(44% 46% at 84% 16%, rgba(14,76,92,.24), transparent 64%),
      radial-gradient(52% 50% at 60% 92%, rgba(127,195,210,.22), transparent 66%);
    filter: blur(34px);
    animation: aurora 28s ease-in-out infinite alternate;
    will-change: transform;
  }
  .hero::after {
    content: "";
    position: absolute; inset: 0; z-index: 0; pointer-events: none;
    background: radial-gradient(120% 90% at 50% 0%, transparent 55%, rgba(247,244,238,.55) 100%);
  }
  @keyframes aurora {
    0%   { transform: translate3d(-2.5%, -1.5%, 0) scale(1.03); }
    50%  { transform: translate3d(2%, 2.5%, 0) scale(1.10); }
    100% { transform: translate3d(-1%, 1.5%, 0) scale(1.05); }
  }
}

/* ---------- 3. Hero 背景视频 ----------
   原来这里是 SVG 汇流线的虚线流动与光晕呼吸。
   现在首屏换成真实拍摄的视频，那些选择器已经没有对应元素了，所以整块删掉。
   （视频自己的播放就是动效；不播时停在 poster 静帧上，见 style.css 与应用逻辑。） */
@media (prefers-reduced-motion: no-preference) {
  /* 视频淡入：避免第一帧硬生生地"跳"出来 */
  .hero-video { transition: opacity .6s var(--ease); }
}

/* ---------- 4. 入场编排 ---------- */
html.js-motion [data-reveal] {
  opacity: 0;
  transform: translateY(24px);
  filter: blur(7px);
  transition:
    opacity .78s var(--ease),
    transform .78s var(--ease),
    filter .78s var(--ease);
  will-change: opacity, transform;
}
html.js-motion [data-reveal].is-in {
  opacity: 1;
  transform: none;
  filter: none;
}

/* Hero 内的元素按顺序入场（不用 IntersectionObserver，首屏直接播） */
@media (prefers-reduced-motion: no-preference) {
  html.js-motion .hero-in > * {
    animation: heroRise .85s var(--ease) both;
  }
  html.js-motion .hero-in > *:nth-child(1) { animation-delay: .05s; }
  html.js-motion .hero-in > *:nth-child(2) { animation-delay: .16s; }
  html.js-motion .hero-in > *:nth-child(3) { animation-delay: .26s; }
  html.js-motion .hero-in > *:nth-child(4) { animation-delay: .36s; }
  html.js-motion .hero-in > *:nth-child(5) { animation-delay: .46s; }
  html.js-motion .hero-in > *:nth-child(6) { animation-delay: .56s; }
  html.js-motion .hero-in > *:nth-child(7) { animation-delay: .66s; }
  @keyframes heroRise {
    from { opacity: 0; transform: translateY(26px); filter: blur(8px); }
    to   { opacity: 1; transform: none; filter: none; }
  }
}

/* ---------- 5. 标识：描边绘制 ----------
   ⚠ 这里有个曾经埋下的坑：`stroke-dashoffset: 100` 本身就会让描边完全不可见，
   而它原先写在媒体查询**外面**、也没挂在 html.js-motion 下。
   结果是——JS 没跑到（被禁用、脚本报错、或某个页面漏了内联脚本）时，
   页头标识会永久消失，而不是"没有动画但正常显示"。
   现在把"先藏起来"和"再画出来"绑在同一组条件里：
   只有『JS 已就绪』且『用户没有要求减少动效』时才隐藏并播放。 */
@media (prefers-reduced-motion: no-preference) {
  html.js-motion .nav .brand-mark [pathLength] {
    stroke-dasharray: 100;
    stroke-dashoffset: 100;
    animation: drawStroke 1s var(--ease) forwards;
  }
  html.js-motion .nav .brand-mark [pathLength]:nth-child(2) { animation-delay: .10s; }
  html.js-motion .nav .brand-mark [pathLength]:nth-child(3) { animation-delay: .30s; }
  html.js-motion .nav .brand-mark [pathLength]:nth-child(4) { animation-delay: .40s; }
  html.js-motion .nav .brand-mark [pathLength]:nth-child(5) { animation-delay: .50s; }
  @keyframes drawStroke { to { stroke-dashoffset: 0; } }
}
/* 动画跑完就撤掉 dasharray，避免缩放重绘时露出缺口 */
html.js-motion .nav .brand-mark.draw-done [pathLength] {
  stroke-dasharray: none;
  stroke-dashoffset: 0;
}

/* ---------- 6. 按钮：高光扫过 ---------- */
@media (prefers-reduced-motion: no-preference) {
  .btn-primary, .btn-sea { position: relative; overflow: hidden; }
  .btn-primary::after, .btn-sea::after {
    content: ""; position: absolute; top: -2px; bottom: -2px; left: 0;
    width: 42%; pointer-events: none;
    background: linear-gradient(100deg, transparent, rgba(255,255,255,.42), transparent);
    transform: translateX(-170%) skewX(-18deg);
  }
  .btn-primary:hover::after, .btn-sea:hover::after {
    animation: btnShine .85s var(--ease);
  }
  @keyframes btnShine {
    to { transform: translateX(330%) skewX(-18deg); }
  }
}

/* ---------- 7. 卡片：跟随鼠标的暖光 ---------- */
@media (hover: hover) and (prefers-reduced-motion: no-preference) {
  .card-hover { position: relative; }
  .card-hover::after {
    content: ""; position: absolute; inset: 0; border-radius: inherit;
    pointer-events: none; opacity: 0;
    transition: opacity .35s var(--ease);
    background: radial-gradient(58% 58% at var(--mx, 50%) var(--my, 0%),
                rgba(196,105,42,.16), rgba(14,76,92,.05) 55%, transparent 72%);
  }
  .card-hover:hover::after { opacity: 1; }
  .card-hover:hover {
    transform: translateY(-4px);
    box-shadow: 0 22px 50px rgba(11,42,51,.14);
    border-color: var(--line-2);
  }
}

/* ---------- 8. 数字：零态呼吸 + 有值后的高光扫过 ---------- */
@media (prefers-reduced-motion: no-preference) {
  .meter-v.zero { animation: zeroBreathe 3.6s ease-in-out infinite; }
  @keyframes zeroBreathe {
    0%, 100% { opacity: .55; }
    50%      { opacity: 1; }
  }
  .meter-v.has-value {
    background: linear-gradient(100deg, var(--sea) 30%, #7FC3D2 50%, var(--sea) 70%);
    background-size: 220% 100%;
    -webkit-background-clip: text; background-clip: text;
    -webkit-text-fill-color: transparent; color: transparent;
    animation: numSheen 4.5s linear infinite;
  }
  @keyframes numSheen {
    from { background-position: 120% 0; }
    to   { background-position: -120% 0; }
  }
}

/* ---------- 9. 区块分隔：流动的海浪 ---------- */
.wave-sep { display: block; width: 100%; height: 64px; overflow: hidden; line-height: 0; }
.wave-sep svg { width: 200%; height: 100%; display: block; }
@media (prefers-reduced-motion: no-preference) {
  .wave-sep svg { animation: waveSlide 19s linear infinite; }
  @keyframes waveSlide { to { transform: translateX(-50%); } }
}
@media (max-width: 640px) { .wave-sep { height: 40px; } }

/* ---------- 10. 运行中的状态点 ---------- */
@media (prefers-reduced-motion: no-preference) {
  .dot-pulse { animation: pulse 2.4s cubic-bezier(.4,0,.6,1) infinite; }
}

/* ---------- 11. 深色区块：跟随光标的柔光 ---------- */
.sec-deep, .sec-sea { position: relative; }
@media (hover: hover) and (prefers-reduced-motion: no-preference) {
  .sec-deep::after, .sec-sea::after {
    content: ""; position: absolute; inset: 0; pointer-events: none;
    opacity: 0; transition: opacity .5s var(--ease);
    background: radial-gradient(340px 340px at var(--mx, 50%) var(--my, 50%),
                rgba(127,195,210,.13), transparent 70%);
  }
  .sec-deep:hover::after, .sec-sea:hover::after { opacity: 1; }
}

/* ---------- 12. 页脚标识静默（不做绘制动画） ---------- */
.foot .brand-mark [pathLength] { stroke-dasharray: none; stroke-dashoffset: 0; }

/* ---------- 13. 窄屏：不自动播背景视频 ----------
   原来这里是"汇流线退回静态纹理"。首屏换成视频之后，同一条原则继续适用：
   窄屏（多半是手机、多半在用流量）**不自动播放**，停在 poster 静帧上；
   但静帧照样显示，不是把首屏视觉整个拿掉。
   是否自动播由 assets/app.js 判断（它还看省流量模式与连接质量），
   这里只负责窄屏这一条 CSS 层面的信号。 */
@media (max-width: 899px) {
  /* 媒体块保持可见，只是不会被自动播放 —— 见 app.js 的 shouldAutoplay() */
  .hero-media { opacity: 1; }
}
