/* 过渡动画关键帧 */
@keyframes orb-drift-a {
  0% { transform: translate(0, 0) scale(1); }
  100% { transform: translate(9vw, 7vh) scale(1.12); }
}

@keyframes orb-drift-b {
  0% { transform: translate(0, 0) scale(1); }
  100% { transform: translate(-8vw, -6vh) scale(1.08); }
}

@keyframes orb-drift-c {
  0% { transform: translate(0, 0) scale(1); }
  100% { transform: translate(6vw, -8vh) scale(0.94); }
}

/* 卡片入场 */
@keyframes card-in {
  from {
    opacity: 0;
    transform: translateY(16px) scale(0.97);
  }
  to {
    opacity: 1;
    transform: translateY(0) scale(1);
  }
}

/* 弹窗弹入（轻微回弹） */
@keyframes pop-in {
  from {
    opacity: 0;
    transform: translateY(14px) scale(0.94);
  }
  to {
    opacity: 1;
    transform: translateY(0) scale(1);
  }
}

/* 遮罩淡入 */
@keyframes fade-in {
  from { opacity: 0; }
  to { opacity: 1; }
}

/* 上浮淡入 */
@keyframes fade-up {
  from {
    opacity: 0;
    transform: translateY(10px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

/* 骨架屏流光 */
@keyframes shimmer {
  0% { transform: translateX(-100%); }
  100% { transform: translateX(100%); }
}

/* 密码错误抖动 */
@keyframes shake {
  0%, 100% { transform: translateX(0); }
  20% { transform: translateX(-9px); }
  40% { transform: translateX(8px); }
  60% { transform: translateX(-6px); }
  80% { transform: translateX(4px); }
}

/* 旋转加载 */
@keyframes spin {
  to { transform: rotate(360deg); }
}

/* Toast 滑入 */
@keyframes toast-in {
  from {
    opacity: 0;
    transform: translateX(24px);
  }
  to {
    opacity: 1;
    transform: translateX(0);
  }
}

/* 登录徽章悬浮呼吸 */
@keyframes badge-float {
  0%, 100% { transform: translateY(0) rotate(-2deg); }
  50% { transform: translateY(-7px) rotate(2deg); }
}

/* 渐变文字流光（背景位移动画） */
@keyframes grad-shift {
  0% { background-position: 0% 50%; }
  100% { background-position: 200% 50%; }
}

/* 骨架行微光 */
@keyframes skeleton-pulse {
  0%, 100% { opacity: 0.55; }
  50% { opacity: 1; }
}

/* 统计数字弹入 */
@keyframes stat-pop {
  from {
    opacity: 0;
    transform: translateY(8px) scale(0.92);
  }
  to {
    opacity: 1;
    transform: translateY(0) scale(1);
  }
}

/* 动效应用类 */
.anim-card-in {
  animation: card-in 0.5s var(--ease-smooth) backwards;
}

.anim-pop-in {
  animation: pop-in 0.3s var(--ease-spring);
}

.anim-fade-in {
  animation: fade-in 0.25s var(--ease-smooth);
}

.anim-fade-up {
  animation: fade-up 0.4s var(--ease-smooth) backwards;
}

.anim-shake {
  animation: shake 0.45s var(--ease-smooth);
}

/* 减少动效偏好 */
@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
}
