@charset "UTF-8";
/* =========================================================
   animations.css — 动效层（PLAN.md §2.4）
   ---------------------------------------------------------
   加载顺序：theme → base → components → animations（本文件最后）
   分工：components.css 只写静态形态与状态过渡，本文件独占 @keyframes
        以及「动起来」的应用规则。

   并发克制（移动端 60fps 底线）：
     · 只对 transform / opacity / background-position / text-shadow 动画
     · 花瓣同屏最多 16 片，密码门只放 8 片，≤340px 收到 10 片
     · 循环动画均带静止停顿帧，避免整屏持续闪动
     · 单次入场动画一律 forwards / both，播完即止
   ========================================================= */


/* =========================================================
   1. @keyframes
   ========================================================= */

/* 花瓣飘落：下落 + 自转 + 两端淡出；--dx 控制左右摆幅，--fall 控制落距 */
@keyframes petal-fall {
  0% {
    transform: translate3d(0, 0, 0) rotate(0deg);
    opacity: 0;
  }
  10% { opacity: var(--o, .55); }
  50% {
    transform: translate3d(var(--dx, 16px), calc(var(--fall, 108vh) * .5), 0)
               rotate(180deg);
  }
  85% { opacity: var(--o, .55); }
  100% {
    transform: translate3d(calc(var(--dx, 16px) * -1), var(--fall, 108vh), 0)
               rotate(360deg);
    opacity: 0;
  }
}

/* 金光扫过：只移动渐变位置（背景或 background-clip:text 皆可用）
   后 45% 为静止停顿，一轮一道光，不做连续跑马灯 */
@keyframes gold-sweep {
  0%   { background-position: 118% 0; }
  55%  { background-position: -18% 0; }
  100% { background-position: -18% 0; }
}

/* 霓虹呼吸：两帧 text-shadow 明暗，不动尺寸与位置 */
@keyframes neon-breathe {
  0%, 100% { text-shadow: 0 0 6px rgba(255, 45, 85, .40); }
  50%      { text-shadow: 0 0 14px rgba(255, 45, 85, .85),
                          0 0 26px rgba(255, 45, 85, .30); }
}

/* 密码错误抖动：纯横向位移 */
@keyframes shake {
  0%, 100%      { transform: translate3d(0, 0, 0); }
  15%, 45%, 75% { transform: translate3d(-7px, 0, 0); }
  30%, 60%, 90% { transform: translate3d(7px, 0, 0); }
}

/* 入场浮现 */
@keyframes fade-up {
  from { opacity: 0; transform: translate3d(0, 24px, 0); }
  to   { opacity: 1; transform: translate3d(0, 0, 0); }
}

/* 欢迎值进度条生长：终点取 render.js 注入的 --w */
@keyframes bar-grow {
  from { width: 0; }
  to   { width: var(--w, 100%); }
}

/* Hero 滚动提示：一道金线自上而下坠落（components.css 已引用 cue-drop） */
@keyframes cue-drop {
  0%        { transform: translate3d(0, -100%, 0); opacity: 0; }
  25%       { opacity: 1; }
  75%       { opacity: 1; }
  100%      { transform: translate3d(0, 240%, 0); opacity: 0; }
}

/* ---- 兼容别名：components.css 里已写死的动画名 ---- */
@keyframes neon-pulse {
  0%, 100% { text-shadow: 0 0 6px rgba(255, 45, 85, .40); }
  50%      { text-shadow: 0 0 14px rgba(255, 45, 85, .85),
                          0 0 26px rgba(255, 45, 85, .30); }
}

@keyframes gate-shake {
  0%, 100%      { transform: translate3d(0, 0, 0); }
  15%, 45%, 75% { transform: translate3d(-7px, 0, 0); }
  30%, 60%, 90% { transform: translate3d(7px, 0, 0); }
}


/* =========================================================
   2. 花瓣层 .petals span
   ---------------------------------------------------------
   JS 只需生成 16 个空 <span>，错落全部由 nth-child 写死：
   delay / duration / left / 大小 / 摆幅 / 起始角度 / 透明度
   ========================================================= */

.petals span {
  position: absolute;
  top: -8%;
  animation-name: petal-fall;
  animation-timing-function: linear;
  animation-iteration-count: infinite;
  animation-fill-mode: none;
  will-change: transform, opacity;
}

.petals span:nth-child(1) {
  left: 4%;  width: 9px;  height: 12px;
  --dx: 22px;  --o: .55;  --fall: 106vh;
  animation-duration: 9.5s;   animation-delay: -0.3s;
}
.petals span:nth-child(2) {
  left: 11%; width: 7px;  height: 10px;
  --dx: -14px; --o: .42;  --fall: 110vh;
  animation-duration: 12.5s;  animation-delay: -2.1s;
}
.petals span:nth-child(3) {
  left: 19%; width: 11px; height: 14px;
  --dx: 30px;  --o: .60;  --fall: 104vh;
  animation-duration: 8.2s;   animation-delay: -5.4s;
}
.petals span:nth-child(4) {
  left: 26%; width: 6px;  height: 9px;
  --dx: -24px; --o: .36;  --fall: 112vh;
  animation-duration: 14.0s;  animation-delay: -1.2s;
}
.petals span:nth-child(5) {
  left: 33%; width: 10px; height: 13px;
  --dx: 12px;  --o: .52;  --fall: 108vh;
  animation-duration: 10.4s;  animation-delay: -7.8s;
}
.petals span:nth-child(6) {
  left: 41%; width: 8px;  height: 11px;
  --dx: -32px; --o: .48;  --fall: 105vh;
  animation-duration: 11.6s;  animation-delay: -3.6s;
}
.petals span:nth-child(7) {
  left: 48%; width: 12px; height: 15px;
  --dx: 18px;  --o: .62;  --fall: 103vh;
  animation-duration: 7.6s;   animation-delay: -9.1s;
}
.petals span:nth-child(8) {
  left: 55%; width: 7px;  height: 10px;
  --dx: -10px; --o: .40;  --fall: 111vh;
  animation-duration: 13.2s;  animation-delay: -4.7s;
}
.petals span:nth-child(9) {
  left: 62%; width: 9px;  height: 12px;
  --dx: 26px;  --o: .56;  --fall: 107vh;
  animation-duration: 9.0s;   animation-delay: -6.3s;
}
.petals span:nth-child(10) {
  left: 68%; width: 6px;  height: 8px;
  --dx: -20px; --o: .34;  --fall: 113vh;
  animation-duration: 15.0s;  animation-delay: -0.9s;
}
.petals span:nth-child(11) {
  left: 74%; width: 11px; height: 14px;
  --dx: 34px;  --o: .58;  --fall: 104vh;
  animation-duration: 8.8s;   animation-delay: -11.2s;
}
.petals span:nth-child(12) {
  left: 80%; width: 8px;  height: 11px;
  --dx: -16px; --o: .46;  --fall: 109vh;
  animation-duration: 12.0s;  animation-delay: -2.8s;
}
.petals span:nth-child(13) {
  left: 86%; width: 10px; height: 13px;
  --dx: 20px;  --o: .50;  --fall: 106vh;
  animation-duration: 10.0s;  animation-delay: -8.4s;
}
.petals span:nth-child(14) {
  left: 91%; width: 7px;  height: 9px;
  --dx: -28px; --o: .38;  --fall: 112vh;
  animation-duration: 13.8s;  animation-delay: -5.9s;
}
.petals span:nth-child(15) {
  left: 95%; width: 9px;  height: 12px;
  --dx: 14px;  --o: .54;  --fall: 105vh;
  animation-duration: 9.8s;   animation-delay: -3.1s;
}
.petals span:nth-child(16) {
  left: 99%; width: 6px;  height: 8px;
  --dx: -12px; --o: .32;  --fall: 114vh;
  animation-duration: 15.6s;  animation-delay: -10.5s;
}

/* 起始角度错落：奇偶两组反向自转，避免整屏同步 */
.petals span:nth-child(2n) { animation-direction: reverse; }

/* 并发克制：密码门只留 8 片，窄屏再收到 10 片 */
.petals--gate span:nth-child(n + 9) { display: none; }

@media (max-width: 340px) {
  .petals span:nth-child(n + 11) { display: none; }
}


/* =========================================================
   3. 滚动入场
   ========================================================= */

.reveal {
  opacity: 0;
  transform: translate3d(0, 24px, 0);
  transition: opacity .6s ease, transform .6s ease;
}

.reveal.in-view,
.in-view > .reveal {
  opacity: 1;
  transform: none;
  animation: fade-up .6s ease both;
}


/* =========================================================
   4. 欢迎值进度条生长
   ========================================================= */

.wbar-fill { width: 0; }

.in-view .wbar-fill,
.rank-row.in-view .wbar-fill {
  animation: bar-grow 1.2s ease forwards;
}


/* =========================================================
   5. 金光扫过：TOP1 名字 + 金色按钮
   ========================================================= */

/* 名字/称号：渐变裁进文字 */
.rank-1 .rank-info__title,
.rank-1 .podium__title,
.podium__slot--1 .podium__title {
  background-image: linear-gradient(100deg,
    var(--ink) 20%,
    var(--gold-bright) 45%,
    #fff8dc 50%,
    var(--gold-bright) 55%,
    var(--ink) 80%);
  background-size: 300% 100%;
  background-repeat: no-repeat;
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
  animation: gold-sweep 3s ease-in-out infinite;
}

/* 按钮：在原底色之上叠一层斜向高光，光带扫过 */
.btn-gold {
  background-image:
    linear-gradient(100deg,
      transparent 38%,
      rgba(240, 214, 117, .18) 50%,
      transparent 62%),
    linear-gradient(180deg, rgba(201, 162, 39, .12), rgba(201, 162, 39, .04));
  background-size: 260% 100%, 100% 100%;
  background-repeat: no-repeat, no-repeat;
  animation: gold-sweep 3s ease-in-out infinite;
}

.btn-gold[disabled] { animation: none; }


/* =========================================================
   6. 霓虹呼吸：欢迎值 ♥ 与 NO.001 徽标
   ========================================================= */

.welcome-heart,
.heart {
  color: var(--rose-neon);
  animation: neon-breathe 2.5s ease-in-out infinite;
}

.card__rank-badge {
  animation: neon-breathe 2.5s ease-in-out infinite;
}


/* =========================================================
   7. 密码错误抖动
   ========================================================= */

#gate .gate__card.gate-shake,
#gate .gate__card.is-shake {
  animation: shake .5s ease both;
}


/* =========================================================
   8. 卡片翻面
   ========================================================= */

.card.flipped .card-inner,
.card-inner.flipped {
  transform: rotateY(180deg);
}

.card-inner {
  transition: transform .7s cubic-bezier(.4, .1, .2, 1);
}


/* =========================================================
   9. prefers-reduced-motion：全部关停
   ---------------------------------------------------------
   统一用 * 兜底，任何后加的动画都自动被覆盖；
   同时把入场态强制为终态，避免元素停在 opacity:0 上看不见。
   ========================================================= */

@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: .001ms !important;
    animation-delay: 0ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .001ms !important;
    transition-delay: 0ms !important;
    scroll-behavior: auto !important;
  }

  .petals { display: none; }

  .reveal,
  .card,
  .rank-row {
    opacity: 1 !important;
    transform: none !important;
  }

  .wbar-fill { width: var(--w, 0%) !important; }

  .rank-1 .rank-info__title,
  .rank-1 .podium__title,
  .podium__slot--1 .podium__title {
    background-image: none;
    -webkit-text-fill-color: var(--gold-bright);
    color: var(--gold-bright);
  }

  .btn-gold { background-image: none; }
}
