/* ==========================================================================

   animations.css · trackandreact.com

   动效系统 — 页面加载/滚动触发/悬停/聚焦/过渡/减少动效偏好

   生成者：Crystal Yifei Liu · 2026-09-25

   依赖：tokens.css

   核心原则：所有动效只使用opacity和transform，不改变布局，不阻塞交互

   ========================================================================== */



/* ==========================================================================

   一、页面加载动效

   ========================================================================== */



/* --- 内容淡入 + 上移 --- */

@keyframes fadeInUp {

  from {

    opacity: 0;

    transform: translateY(10px);

  }

  to {

    opacity: 1;

    transform: translateY(0);

  }

}



/* --- 内容淡入（无位移） --- */

@keyframes fadeIn {

  from { opacity: 0; }

  to { opacity: 1; }

}



/* --- 内容淡入 + 下移 --- */

@keyframes fadeInDown {

  from {

    opacity: 0;

    transform: translateY(-10px);

  }

  to {

    opacity: 1;

    transform: translateY(0);

  }

}



/* --- 内容淡入 + 左移 --- */

@keyframes fadeInLeft {

  from {

    opacity: 0;

    transform: translateX(-10px);

  }

  to {

    opacity: 1;

    transform: translateX(0);

  }

}



/* --- 内容淡入 + 右移 --- */

@keyframes fadeInRight {

  from {

    opacity: 0;

    transform: translateX(10px);

  }

  to {

    opacity: 1;

    transform: translateX(0);

  }

}



/* --- 内容缩放进入 --- */

@keyframes scaleIn {

  from {

    opacity: 0;

    transform: scale(0.96);

  }

  to {

    opacity: 1;

    transform: scale(1);

  }

}



/* --- 页面进入（应用于main元素） --- */

.page-enter {

  animation: fadeInUp var(--duration-slow) var(--ease-out) both;

}



/* --- 首屏内容不延迟 --- */

.hero,

.page-enter > *:first-child {

  animation: none;

}



/* ==========================================================================

   二、滚动触发动效

   ========================================================================== */



/* --- 滚动触发基础类（需配合Intersection Observer） --- */

.reveal {

  opacity: 0;

  transform: translateY(20px);

  transition: opacity 400ms var(--ease-out),

              transform 400ms var(--ease-out);

  will-change: opacity, transform;

}



.reveal.visible {

  opacity: 1;

  transform: translateY(0);

}



/* --- 延迟变体 --- */

.reveal-delay-1 { transition-delay: 100ms; }

.reveal-delay-2 { transition-delay: 200ms; }

.reveal-delay-3 { transition-delay: 300ms; }

.reveal-delay-4 { transition-delay: 400ms; }

.reveal-delay-5 { transition-delay: 500ms; }



/* --- 滚动触发：从左进入 --- */

.reveal-left {

  opacity: 0;

  transform: translateX(-20px);

  transition: opacity 400ms var(--ease-out),

              transform 400ms var(--ease-out);

}



.reveal-left.visible {

  opacity: 1;

  transform: translateX(0);

}



/* --- 滚动触发：从右进入 --- */

.reveal-right {

  opacity: 0;

  transform: translateX(20px);

  transition: opacity 400ms var(--ease-out),

              transform 400ms var(--ease-out);

}



.reveal-right.visible {

  opacity: 1;

  transform: translateX(0);

}



/* --- 滚动触发：缩放进入 --- */

.reveal-scale {

  opacity: 0;

  transform: scale(0.96);

  transition: opacity 400ms var(--ease-out),

              transform 400ms var(--ease-out);

}



.reveal-scale.visible {

  opacity: 1;

  transform: scale(1);

}



/* ==========================================================================

   三、悬停动效

   ========================================================================== */



/* --- 卡片悬停上移 --- */

.hover-lift {

  transition: transform var(--duration-normal) var(--ease-out),

              box-shadow var(--duration-normal) var(--ease-out);

}



.hover-lift:hover {

  transform: translateY(-2px);

  box-shadow: var(--shadow-md);

}



/* --- 卡片悬停放大 --- */

.hover-scale {

  transition: transform var(--duration-normal) var(--ease-spring);

}



.hover-scale:hover {

  transform: scale(1.02);

}



/* --- 链接下划线滑入 --- */

.link-underline {

  position: relative;

}



.link-underline::after {

  content: '';

  position: absolute;

  bottom: -2px;

  left: 0;

  width: 0;

  height: 2px;

  background-color: var(--color-primary-500);

  transition: width var(--duration-normal) var(--ease-out);

}



.link-underline:hover::after {

  width: 100%;

}



/* --- 图标悬停右移 --- */

.hover-arrow {

  display: inline-flex;

  align-items: center;

  transition: transform var(--duration-fast) var(--ease-out);

}



.hover-arrow::after {

  content: '→';

  margin-left: var(--space-1);

  transition: transform var(--duration-fast) var(--ease-out);

}



.hover-arrow:hover::after {

  transform: translateX(3px);

}



/* ==========================================================================

   四、聚焦动效

   ========================================================================== */



/* --- 焦点环脉冲（用于重要输入/按钮） --- */

@keyframes focusPulse {

  0% {

    box-shadow: 0 0 0 0 var(--color-primary-alpha-20);

  }

  70% {

    box-shadow: 0 0 0 10px transparent;

  }

  100% {

    box-shadow: 0 0 0 0 transparent;

  }

}



.focus-pulse:focus-visible {

  animation: focusPulse 1s var(--ease-out);

}



/* ==========================================================================

   五、光点闪烁动画（封面图专用）

   ========================================================================== */



/* --- 基础闪烁 --- */

@keyframes lightDot {

  0%, 100% { opacity: 0.3; }

  50% { opacity: 1; }

}



/* --- 缓慢闪烁 --- */

@keyframes lightDotSlow {

  0%, 100% { opacity: 0.4; }

  50% { opacity: 0.9; }

}



/* --- 快速闪烁 --- */

@keyframes lightDotFast {

  0%, 100% { opacity: 0.2; }

  50% { opacity: 1; }

}



/* --- 呼吸闪烁 --- */

@keyframes lightDotBreathe {

  0%, 100% { opacity: 0.3; transform: scale(1); }

  50% { opacity: 0.9; transform: scale(1.3); }

}



/* --- 光点动画类（时长2-4秒随机分布） --- */

.light-dot {

  animation: lightDot 3s var(--ease-in-out) infinite;

}



.light-dot-1 { animation-duration: 2s; animation-delay: 0s; }

.light-dot-2 { animation-duration: 3s; animation-delay: 0.5s; }

.light-dot-3 { animation-duration: 4s; animation-delay: 1s; }

.light-dot-4 { animation-duration: 2.5s; animation-delay: 1.5s; }

.light-dot-5 { animation-duration: 3.5s; animation-delay: 2s; }



/* ==========================================================================

   六、骨架屏动画

   ========================================================================== */



/* --- 微光扫描 --- */

@keyframes skeletonShimmer {

  0% { background-position: 200% 0; }

  100% { background-position: -200% 0; }

}



/* --- 脉冲闪烁 --- */

@keyframes skeletonPulse {

  0%, 100% { opacity: 1; }

  50% { opacity: 0.6; }

}



.skeleton {

  background: linear-gradient(

    90deg,

    var(--skeleton-bg) 0%,

    var(--skeleton-shimmer) 50%,

    var(--skeleton-bg) 100%

  );

  background-size: 200% 100%;

  animation: skeletonShimmer var(--loading-shimmer) var(--ease-in-out) infinite;

  border-radius: var(--radius-sm);

}



.skeleton-pulse {

  background-color: var(--skeleton-bg);

  animation: skeletonPulse var(--loading-pulse) var(--ease-in-out) infinite;

  border-radius: var(--radius-sm);

}



/* ==========================================================================

   七、FAQ 折叠动效

   ========================================================================== */



.faq-answer {

  max-height: 0;

  overflow: hidden;

  transition: max-height var(--duration-slow) var(--ease-in-out);

}



.faq-item.open .faq-answer {

  max-height: 1000px;

}



.faq-icon {

  transition: transform var(--duration-normal) var(--ease-out);

}



.faq-item.open .faq-icon {

  transform: rotate(45deg);

}



/* ==========================================================================

   八、加载旋转动画

   ========================================================================== */



@keyframes spin {

  from { transform: rotate(0deg); }

  to { transform: rotate(360deg); }

}



.spinner {

  display: inline-block;

  width: 20px;

  height: 20px;

  border: 2px solid var(--color-neutral-200);

  border-top-color: var(--color-primary-500);

  border-radius: var(--radius-full);

  animation: spin 0.8s linear infinite;

}



/* ==========================================================================

   九、进度条动画

   ========================================================================== */



@keyframes progressGrow {

  from { width: 0; }

}



.progress-bar {

  height: 8px;

  background-color: var(--color-neutral-200);

  border-radius: var(--radius-full);

  overflow: hidden;

}



.progress-fill {

  height: 100%;

  background-color: var(--color-primary-500);

  border-radius: var(--radius-full);

  animation: progressGrow var(--duration-slower) var(--ease-out);

}



/* ==========================================================================

   十、脉冲通知动画

   ========================================================================== */



@keyframes pulse {

  0%, 100% {

    transform: scale(1);

    opacity: 1;

  }

  50% {

    transform: scale(1.05);

    opacity: 0.85;

  }

}



.pulse {

  animation: pulse 2s var(--ease-in-out) infinite;

}



/* ==========================================================================

   十一、弹跳动画（用于强调元素）

   ========================================================================== */



@keyframes bounce {

  0%, 100% {

    transform: translateY(0);

  }

  50% {

    transform: translateY(-6px);

  }

}



.bounce {

  animation: bounce 1.5s var(--ease-in-out) infinite;

}



/* ==========================================================================

   十二、抖动动画（用于错误提示）

   ========================================================================== */



@keyframes shake {

  0%, 100% { transform: translateX(0); }

  20% { transform: translateX(-4px); }

  40% { transform: translateX(4px); }

  60% { transform: translateX(-4px); }

  80% { transform: translateX(4px); }

}



.shake {

  animation: shake var(--duration-slow) var(--ease-out);

}



/* ==========================================================================

   十三、滚动提示动画（用于长文阅读指示）

   ========================================================================== */



@keyframes scrollHint {

  0%, 100% {

    opacity: 0.3;

    transform: translateY(0);

  }

  50% {

    opacity: 1;

    transform: translateY(4px);

  }

}



.scroll-hint {

  animation: scrollHint 1.8s var(--ease-in-out) infinite;

}



/* ==========================================================================

   十四、渐变流动动画（用于探索入口）

   ========================================================================== */



@keyframes gradientShift {

  0% { background-position: 0% 50%; }

  50% { background-position: 100% 50%; }

  100% { background-position: 0% 50%; }

}



.gradient-flow {

  background-size: 200% 200%;

  animation: gradientShift 8s var(--ease-in-out) infinite;

}



/* ==========================================================================

   十五、淡出动画（用于提示消失）

   ========================================================================== */



@keyframes fadeOut {

  from { opacity: 1; }

  to { opacity: 0; }

}



.fade-out {

  animation: fadeOut var(--duration-slow) var(--ease-in) forwards;

}



/* ==========================================================================

   十六、打字机效果（谨慎使用，仅用于特殊场景）

   ========================================================================== */



@keyframes typing {

  from { width: 0; }

  to { width: 100%; }

}



@keyframes blink {

  50% { border-color: transparent; }

}



.typing {

  overflow: hidden;

  white-space: nowrap;

  border-right: 2px solid var(--color-primary-500);

  animation: typing 3s steps(40, end), blink 0.8s step-end infinite;

}



/* ==========================================================================

   十七、滚动触发观察器辅助类

   ========================================================================== */



/* 首屏元素不加滚动触发动效，防止LCP延迟 */

.above-fold .reveal,

.above-fold .reveal-left,

.above-fold .reveal-right,

.above-fold .reveal-scale {

  opacity: 1;

  transform: none;

  transition: none;

}



/* 长文阅读的滚动进度条 */

.reading-progress {

  position: fixed;

  top: 0;

  left: 0;

  height: 3px;

  background: var(--color-primary-500);

  z-index: var(--z-fixed);

  transition: width 100ms linear;

  will-change: width;

}



/* 回到顶部按钮 */

.back-to-top {

  position: fixed;

  bottom: var(--space-6);

  right: var(--space-6);

  width: 48px;

  height: 48px;

  border-radius: var(--radius-full);

  background-color: var(--color-surface);

  border: 1px solid var(--color-border);

  box-shadow: var(--shadow-md);

  display: flex;

  align-items: center;

  justify-content: center;

  cursor: pointer;

  opacity: 0;

  visibility: hidden;

  transform: translateY(10px);

  transition: all var(--duration-normal) var(--ease-out);

  z-index: var(--z-fixed);

}



.back-to-top.visible {

  opacity: 1;

  visibility: visible;

  transform: translateY(0);

}



.back-to-top:hover {

  box-shadow: var(--shadow-lg);

  border-color: var(--color-primary-300);

}



.back-to-top::before {

  content: '↑';

  font-size: var(--text-lg);

  color: var(--color-text-primary);

  font-weight: var(--font-bold);

}



/* ==========================================================================

   十八、移动端动效简化

   ========================================================================== */

@media (max-width: 768px) {

  /* 移动端减少滚动触发动效 */

  .reveal,

  .reveal-left,

  .reveal-right,

  .reveal-scale {

    transform: none;

    transition: opacity 300ms var(--ease-out);

  }



  /* 移动端光点数量减半（由 cover.css 配合实现） */

  .light-dot-6,

  .light-dot-7,

  .light-dot-8 {

    display: none;

  }



  /* 移动端禁用 hover 动效 */

  .hover-lift:hover,

  .hover-scale:hover {

    transform: none;

  }

}



/* ==========================================================================

   十九、减少动效偏好（强制性）

   ========================================================================== */

@media (prefers-reduced-motion: reduce) {

  *,

  *::before,

  *::after {

    animation-duration: 0.01ms !important;

    animation-iteration-count: 1 !important;

    transition-duration: 0.01ms !important;

    scroll-behavior: auto !important;

  }



  /* 保留关键可见状态，仅移除动画过程 */

  .reveal,

  .reveal-left,

  .reveal-right,

  .reveal-scale {

    opacity: 1;

    transform: none;

  }



  .light-dot,

  .light-dot-1,

  .light-dot-2,

  .light-dot-3,

  .light-dot-4,

  .light-dot-5 {

    animation: none;

    opacity: 0.6;

  }



  .skeleton,

  .skeleton-pulse {

    animation: none;

    background: var(--skeleton-bg);

  }



  .spinner {

    animation: none;

    border-top-color: var(--color-primary-500);

  }



  .pulse,

  .bounce,

  .scroll-hint,

  .gradient-flow {

    animation: none;

  }

}



/* ==========================================================================

   二十、性能优化

   ========================================================================== */



/* 仅对动画元素启用GPU加速 */

.reveal,

.reveal-left,

.reveal-right,

.reveal-scale,

.hover-lift,

.hover-scale,

.light-dot,

.reading-progress,

.back-to-top {

  transform: translateZ(0);

  backface-visibility: hidden;

}



/* 动画完成后移除will-change（由JS配合） */

.reveal.visible,

.reveal-left.visible,

.reveal-right.visible,

.reveal-scale.visible {

  will-change: auto;

}



/* ==========================================================================

   animations.css 结束

   ========================================================================== */