/* animations.css — R102 动画集 */
@keyframes topCardPopIn {
  0%   { opacity: 0; transform: scale(0.7) translateY(20px); }
  70%  { transform: scale(1.05) translateY(-4px); }
  100% { opacity: 1; transform: scale(1) translateY(0); }
}
.top-card--gold { animation: topCardPopIn 0.5s var(--ease-spring) both; }
.top-card--silver { animation: topCardPopIn 0.5s var(--ease-spring) 0.15s both; }
.top-card--bronze { animation: topCardPopIn 0.5s var(--ease-spring) 0.3s both; }

.leaderboard-item { transition: transform 0.6s cubic-bezier(0.34,1.56,0.64,1); }

@keyframes fabPulse {
  0%, 100% { box-shadow: 0 4px 16px rgba(74,144,255,0.4); }
  50%      { box-shadow: 0 4px 28px rgba(74,144,255,0.7); }
}

@keyframes circleReveal {
  from { clip-path: circle(0% at 50% 100%); }
  to   { clip-path: circle(150% at 50% 100%); }
}
.record-form--enter { animation: circleReveal 0.35s ease-out; }

@keyframes bounceIn {
  0%   { transform: scale(0.3); opacity: 0; }
  50%  { transform: scale(1.08); }
  70%  { transform: scale(0.95); }
  100% { transform: scale(1); opacity: 1; }
}

@keyframes badgeUnlock {
  0%   { transform: scale(0) rotate(-180deg); opacity: 0; }
  60%  { transform: scale(1.3) rotate(10deg); }
  100% { transform: scale(1) rotate(0); opacity: 1; }
}
.badge-unlock { animation: badgeUnlock 0.8s var(--ease-spring) forwards; }

@keyframes confettiFall {
  0%   { transform: translateY(-100vh) rotate(0deg); opacity: 1; }
  100% { transform: translateY(100vh) rotate(720deg); opacity: 0; }
}

.page-fade-enter { animation: fadeIn 0.2s ease; }
@keyframes fadeIn {
  from { opacity: 0; }
  to   { opacity: 1; }
}

@keyframes rankUp {
  0%   { transform: translateY(30px); opacity: 0; }
  100% { transform: translateY(0); opacity: 1; }
}
@keyframes rankDown {
  0%   { transform: translateY(-30px); opacity: 0; }
  100% { transform: translateY(0); opacity: 1; }
}

@keyframes shimmer {
  0%   { background-position: -200% 0; }
  100% { background-position: 200% 0; }
}
.skeleton {
  background: linear-gradient(90deg, var(--bg-card) 25%, var(--divider) 50%, var(--bg-card) 75%);
  background-size: 200% 100%;
  animation: shimmer 1.5s infinite;
  border-radius: var(--radius-sm);
}

@keyframes raceProgress { from { width: 0%; } }
.pk-bar__fill { animation: raceProgress 1.5s ease-out forwards; }

@keyframes spin { to { transform: rotate(360deg); } }
.loading-spinner {
  width: 24px; height: 24px; border: 2px solid var(--divider);
  border-top-color: var(--accent); border-radius: 50%;
  animation: spin 0.8s linear infinite;
}

.badge-item { animation: badgePopIn 0.4s var(--ease-spring) both; }
@keyframes badgePopIn {
  from { opacity: 0; transform: scale(0.6); }
  to   { opacity: 1; transform: scale(1); }
}

@keyframes dropdownSlide {
  from { max-height: 0; opacity: 0; transform: translateY(-8px); }
  to   { max-height: 300px; opacity: 1; transform: translateY(0); }
}
.dropdown--open { animation: dropdownSlide 0.25s ease-out; }

@keyframes cellFadeIn {
  from { opacity: 0; transform: scale(0.5); }
  to   { opacity: 1; transform: scale(1); }
}
.calendar-cell { animation: cellFadeIn 0.3s ease-out both; }

@keyframes badgeBounce {
  0%, 100% { transform: scale(1); }
  50%      { transform: scale(1.4); }
}
.notification-badge { animation: badgeBounce 0.4s ease; }

@keyframes highlightPulse {
  0%, 100% { background: transparent; }
  50%      { background: rgba(245,166,35,0.15); }
}
.leaderboard-item--changed { animation: highlightPulse 0.5s ease 3; }

@keyframes tvScroll {
  from { transform: translateY(0); }
  to   { transform: translateY(-100%); }
}

@keyframes pageSlideIn {
  from { opacity: 0; transform: translateY(10px); }
  to   { opacity: 1; transform: translateY(0); }
}
#main-content > * { animation: pageSlideIn 0.25s ease-out; }

:root {
  --ease-spring: cubic-bezier(0.34,1.56,0.64,1);
  --ease-out: cubic-bezier(0,0,0.2,1);
  --ease-in-out: cubic-bezier(0.4,0,0.2,1);
}
