/**
 * 动效层
 * ------------------------------------------------------------------
 * 原则：
 *  1. 只动 transform 与 opacity，绝不触发布局重排（不写 top/left/width/height 动画）
 *  2. 全站统一时长与缓动曲线，不出现「这里快那里慢」
 *  3. 文件末尾集中做 prefers-reduced-motion 降级，一处生效全站
 *  依赖：tokens.css
 */

/*
 * ==================================================================
 * ⚠️ 所有「默认不可见、靠 JS 显现」的样式，一律**限定在 html.js 之下**。
 *
 * 起因（真实故障）：`.reveal { opacity: 0 }` 原来是无条件的，于是
 * 「元素已经渲染、但永远没人给它加 .is-in」时，整页 HTML 都在、却全部不可见
 * —— 表现就是用户看到的「页面变成一片空白，反复刷新才偶尔正常」。
 *
 * 改成渐进增强后：脚本没加载、加载失败、或初始化中途抛错，
 * 页面只是**没有动画**，内容照常显示。动画是锦上添花，不该是显示内容的先决条件。
 * ==================================================================
 */

/* ================= 进场：淡入上浮 ================= */
/* 由 motion.js 用 IntersectionObserver 添加 .is-in */
.js .reveal {
  opacity: 0;
  transform: translateY(24px);
  transition:
    opacity var(--dur) var(--ease),
    transform var(--dur) var(--ease);
  will-change: opacity, transform;
}

.js .reveal.is-in {
  opacity: 1;
  transform: none;
}

/* 逐项延迟：给同一容器内的兄弟元素依次加 --i: 0/1/2... */
.js .reveal {
  transition-delay: calc(var(--i, 0) * 70ms);
}

/* 进场结束后移除 will-change，避免长期占用合成层 */
.js .reveal.is-done {
  will-change: auto;
}

/* ================= 首屏：逐字上浮 ================= */
/* 由 home.js 把标题拆成 <span class="char"> 并依次加 --i */
.js .char {
  display: inline-block;
  opacity: 0;
  transform: translateY(0.5em);
  animation: char-rise var(--dur-slow) var(--ease) forwards;
  animation-delay: calc(var(--i, 0) * 45ms);
}

@keyframes char-rise {
  to {
    opacity: 1;
    transform: none;
  }
}

/* 首屏其余元素的延迟出现 */
.js .hero-fade {
  opacity: 0;
  animation: hero-fade-in var(--dur-slow) var(--ease) forwards;
  animation-delay: calc(var(--d, 0) * 1ms);
}

@keyframes hero-fade-in {
  to { opacity: 1; }
}

/* ================= 兜底：让内容「无论如何都会出现」 ================= */
/*
 * 页面 <head> 里的内联看门狗负责在 2.5 秒后加上 `no-motion`；
 * 初始化成功则会先加 `mm-ready`，看门狗随即放弃。
 * 这是最后一道保险：只要 HTML 送达，内容一定看得见，不会白屏。
 * 用 !important 是因为它必须能压过任何一处的进场样式。
 */
.no-motion .reveal,
.no-motion .char,
.no-motion .hero-fade,
.no-motion .rule-grow {
  opacity: 1 !important;
  transform: none !important;
  transition: none !important;
  animation: none !important;
  will-change: auto !important;
}

/* ================= 细线延展（板块入场时的金色横线） ================= */
.rule-grow {
  transform: scaleX(0);
  transform-origin: left;
  transition: transform var(--dur-slow) var(--ease);
}

.rule-grow.is-in {
  transform: scaleX(1);
}

/* ================= 无线金色描边流动（按钮 / 卡片悬停） ================= */
/* 用两端点间的渐变位移模拟光线沿边框走过，不使用 box-shadow */
.glow-edge {
  position: relative;
}

.glow-edge::before {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  background:
    linear-gradient(90deg, transparent, var(--c-gold), transparent) top left / 0% 1px no-repeat,
    linear-gradient(180deg, transparent, var(--c-gold), transparent) top right / 1px 0% no-repeat,
    linear-gradient(270deg, transparent, var(--c-gold), transparent) bottom right / 0% 1px no-repeat,
    linear-gradient(0deg, transparent, var(--c-gold), transparent) bottom left / 1px 0% no-repeat;
  transition: background-size var(--dur) var(--ease);
}

.glow-edge:hover::before {
  background-size:
    100% 1px,
    1px 100%,
    100% 1px,
    1px 100%;
}

/* ================= 图片视差（由 motion.js 更新 --py） ================= */
.parallax {
  transform: translate3d(0, var(--py, 0px), 0);
  will-change: transform;
}

/* ================= 横向滚动条（音乐节名称条） ================= */
.marquee-track {
  display: flex;
  width: max-content;
}

/* ================= 页头隐藏（向下滚动时收起，向上滚动立刻出现） ================= */
.site-header.is-hidden {
  transform: translateY(-100%);
}

.site-header {
  transition:
    transform var(--dur-fast) var(--ease),
    height var(--dur-fast) var(--ease),
    background-color var(--dur-fast) var(--ease),
    border-color var(--dur-fast) var(--ease);
}

/* ================= 抽屉内逐项出现 ================= */
.drawer.is-open .drawer-nav a {
  animation: char-rise var(--dur) var(--ease) backwards;
  animation-delay: calc(var(--i, 0) * 40ms + 60ms);
}

/* ================= 数字滚动（由 motion.js 写入 textContent） ================= */
.counting {
  font-variant-numeric: tabular-nums;
}

/* ================= 降级：尊重系统「减少动态效果」 =================
 * 一处覆盖，全站生效：关闭位移、粒子、视差与逐字动画，只保留最简单的显隐。
 */
@media (prefers-reduced-motion: reduce) {
  html {
    scroll-behavior: auto;
  }

  *,
  *::before,
  *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
    scroll-behavior: auto !important;
  }

  .reveal,
  .hero-fade,
  .char {
    opacity: 1 !important;
    transform: none !important;
    animation: none !important;
  }

  .parallax {
    transform: none !important;
  }

  /* 粒子画布与噪点动画直接隐藏，避免无谓的绘制开销 */
  .hero-canvas {
    display: none !important;
  }

  .scroll-arrow {
    animation: none !important;
  }

  .skeleton {
    animation: none !important;
    background: var(--c-bg-soft);
  }

  .btn:hover,
  .artist-row:hover {
    transform: none !important;
  }
}

/* ================= 移动端进一步降载 ================= */
@media (max-width: 640px) {
  .reveal {
    /* 移动端减小位移量，避免滚动时晃动 */
    transform: translateY(14px);
  }

  .parallax {
    transform: none !important;
  }
}
