/**
 * animations.css — 艾速背单词系统 · 过渡动画库
 * ──────────────────────────────────────────────
 * ① .page-enter / .page-exit  — 路由切换 fade 滑入动画
 * ② .card-flip                — 学习卡片 3D 翻转优化
 * ③ .modal-enter / .modal-exit — 弹窗打开/关闭动画
 * ④ .tab-slide                — Tab 切换滑动指示器
 * ⑤ .btn-active               — 按钮触摸缩放反馈
 *
 * 性能原则：
 *   • 仅使用 transform / opacity（GPU 合成层属性，不触发 layout / paint）
 *   • will-change 在动画开始前添加，结束后移除（避免常驻 GPU 占用）
 *   • 所有缓动统一 cubic-bezier(0.4, 0, 0.2, 1)（Material ease-out）
 *   • prefers-reduced-motion: reduce 时全部降级为瞬时切换
 *
 * ⚠️ 未使用类清单（2026-02 全项目 Select-String 复核，除本文件外 0 命中）：
 *   ① 路由：.fade-enter/.fade-enter-active/.fade-exit/.fade-exit-active、
 *           .page-enter*/.page-exit*（含 -reverse/-scale）、.gpu-layer
 *   ② 翻转：.card-flip/.card-flip-active/.card-flip-reset、.card-flip-bounce-*
 *           （实际翻转由 index.html 的 .flipper/.flipper.flipped 承担，见 studyPage.js:45-48）
 *   ③ 弹窗：.modal-enter/.modal-exit/.modal-enter-task/.modal-exit-task、
 *           .modal-panel-enter/.modal-panel-exit
 *   ④ Tab：.tab-bar/.tab-item/.tab-indicator/.tab-radio/.tab-panel
 *           （实际 Tab 由 index.html 的 .dd-tabs/.dash-tab + utils/uiHelpers.js createTabs 实现）
 *   ⑤ 按钮：.btn-feedback/.btn-active（按钮反馈由 index.html .btn:active 实现）
 *   ⑥ 工具：.slide-up-in/.pulse-scale/.fade-in/.fade-out/.toast-enter/.toast-exit、
 *           .skeleton-shimmer/.skeleton-text*/.skeleton-circle
 *           （骨架屏由 homePage.js 内联 <style> 的 .sk-bone 实现）
 *   处置决策：本轮「仅标记、不删除」。原因：这些类是本文件导出的公共 class 名，
 *   项目外（构建产物 / 后续页面）可能仍有引用，而删除对收益（CSS 体积）影响极小，
 *   却会与其它并行改动产生选择器失效风险；本注释给出可安全删除的依据，留待专门清理轮次。
 */

/* ═══════════════════════════════════════════════
   0. 性能 & 工具类
   ═══════════════════════════════════════════════ */

/* 预创建合成层，减少首次动画的光栅化延迟 */
.gpu-layer {
  will-change: transform, opacity;
  contain: layout style;
}

/* ═══════════════════════════════════════════════
   1. 路由切换 · fade-enter / fade-exit / page-enter / page-exit
   ═══════════════════════════════════════════════ */

/* — SPA hash 路由切换：fade 淡入淡出（Vue-style 类名兼容） — */
.fade-enter {
  opacity: 0;
}
.fade-enter-active {
  animation: fadeRouteIn 0.35s cubic-bezier(0.4, 0, 0.2, 1) forwards;
}
.fade-exit {
  opacity: 1;
}
.fade-exit-active {
  animation: fadeRouteOut 0.25s cubic-bezier(0.4, 0, 0.2, 1) forwards;
}

@keyframes fadeRouteIn {
  0%   { opacity: 0; }
  100% { opacity: 1; }
}

@keyframes fadeRouteOut {
  0%   { opacity: 1; }
  100% { opacity: 0; }
}

/* — 进入：从右侧 24px 淡入 — */
.page-enter {
  animation: pageSlideIn 0.38s cubic-bezier(0.4, 0, 0.2, 1) forwards;
}

/* — 退出：向左侧 24px 淡出 — */
.page-exit {
  animation: pageSlideOut 0.32s cubic-bezier(0.4, 0, 0.2, 1) forwards;
}

/* — 进入（反向）：从左侧滑入 — */
.page-enter-reverse {
  animation: pageSlideInLeft 0.38s cubic-bezier(0.4, 0, 0.2, 1) forwards;
}

@keyframes pageSlideIn {
  0% {
    opacity: 0;
    transform: translateX(24px);
  }
  100% {
    opacity: 1;
    transform: translateX(0);
  }
}

@keyframes pageSlideOut {
  0% {
    opacity: 1;
    transform: translateX(0);
  }
  100% {
    opacity: 0;
    transform: translateX(-24px);
  }
}

@keyframes pageSlideInLeft {
  0% {
    opacity: 0;
    transform: translateX(-24px);
  }
  100% {
    opacity: 1;
    transform: translateX(0);
  }
}

/* 叠加轻微缩放（进出时尺寸呼吸感） */
.page-enter-scale {
  animation: pageScaleIn 0.42s cubic-bezier(0.22, 1, 0.36, 1) forwards;
}

.page-exit-scale {
  animation: pageScaleOut 0.32s cubic-bezier(0.4, 0, 0.2, 1) forwards;
}

@keyframes pageScaleIn {
  0% {
    opacity: 0;
    transform: translateX(20px) scale(0.97);
  }
  100% {
    opacity: 1;
    transform: translateX(0) scale(1);
  }
}

@keyframes pageScaleOut {
  0% {
    opacity: 1;
    transform: scale(1);
  }
  100% {
    opacity: 0;
    transform: scale(0.97);
  }
}

/* ═══════════════════════════════════════════════
   2. 卡片翻转 · card-flip（3D 翻转优化）
   ═══════════════════════════════════════════════ */

/*
 * 结构假设（与 studyPage.js 一致）：
 *   .flip-container  → perspective 容器
 *     .flipper       → 翻转主体（transform-style: preserve-3d）
 *       .card-face.card-front → 正面
 *       .card-face.card-back  → 背面（已 rotateY(180deg)）
 *
 * 使用者只需在 .flipper 上切换 .card-flip-active class。
 */

.flip-container {
  perspective: 1200px;
  perspective-origin: 50% 50%;
  /* will-change 由 JS 翻转前动态添加 */
}

/* 翻转过渡主体（.card-flip class 或 .flipper class 均可触发） */
.card-flip,
.flipper {
  position: relative;
  width: 100%;
  height: 100%;
  transform-style: preserve-3d;
  backface-visibility: hidden;
  -webkit-backface-visibility: hidden;
  /* ★ 缓动优化：ease-out-back 弹性曲线（轻微回弹感） */
  transition: transform 0.6s cubic-bezier(0.4, 0, 0.2, 1);
  /* will-change 由 studyPage.js:40-43 在翻转前动态添加、结束后移除（本文件性能原则第 2 条）；
     此处原为常驻声明，与 JS 动态版本并存，已删除。 */
}

/* 展开背面 */
.card-flip-active {
  transform: rotateY(180deg);
}

/* 背面翻回正面（取消翻转时的缓动，更干脆） */
.card-flip.card-flip-reset {
  transition: transform 0.45s cubic-bezier(0.4, 0, 0.2, 1);
}

/* 正/背面共用：隐藏非活动面 */
.card-face {
  position: absolute;
  top: 0; left: 0; right: 0; bottom: 0;
  backface-visibility: hidden;
  -webkit-backface-visibility: hidden;
}

.card-back {
  transform: rotateY(180deg);
}

/* 翻转过程中的缩放微抖（视觉层次感） */
@keyframes flipBounce {
  0%   { transform: scale(1)      rotateY(0deg); }
  50%  { transform: scale(0.985)  rotateY(90deg); }
  100% { transform: scale(1)      rotateY(180deg); }
}

/* 附加弹性类：在 .card-flip-active 基础上追加此 class 可获得回弹感 */
.card-flip-bounce-active {
  animation: flipBounceForward 0.72s cubic-bezier(0.34, 1.56, 0.64, 1) forwards;
}

@keyframes flipBounceForward {
  0%   { transform: rotateY(0deg); }
  100% { transform: rotateY(180deg); }
}

@keyframes flipBounceBackward {
  0%   { transform: rotateY(180deg); }
  100% { transform: rotateY(0deg); }
}

.card-flip-bounce-reset {
  animation: flipBounceBackward 0.52s cubic-bezier(0.4, 0, 0.2, 1) forwards;
}

/* ═══════════════════════════════════════════════
   3. 弹窗 · modal-enter / modal-exit
   ═══════════════════════════════════════════════ */

/* — 遮罩层 — */
.modal-enter {
  animation: overlayFadeIn 0.28s cubic-bezier(0.4, 0, 0.2, 1) forwards;
}

.modal-exit {
  animation: overlayFadeOut 0.24s cubic-bezier(0.4, 0, 0.2, 1) forwards;
}

@keyframes overlayFadeIn {
  0%   { opacity: 0; }
  100% { opacity: 1; }
}

@keyframes overlayFadeOut {
  0%   { opacity: 1; }
  100% { opacity: 0; }
}

/* — 面板（移动端从底部弹出）— */
.modal-panel-enter {
  animation: modalSlideUp 0.4s cubic-bezier(0.22, 1, 0.36, 1) forwards;
}

.modal-panel-exit {
  animation: modalSlideDown 0.3s cubic-bezier(0.4, 0, 0.2, 1) forwards;
}

@keyframes modalSlideUp {
  0% {
    opacity: 0;
    transform: translateY(48px) scale(0.96);
  }
  60% {
    opacity: 1;
    transform: translateY(-2px) scale(1.005);
  }
  100% {
    opacity: 1;
    transform: translateY(0) scale(1);
  }
}

@keyframes modalSlideDown {
  0% {
    opacity: 1;
    transform: translateY(0) scale(1);
  }
  100% {
    opacity: 0;
    transform: translateY(48px) scale(0.96);
  }
}

/* — 桌面端：居中缩放弹出 — */
@media (min-width: 520px) and (min-height: 640px) {
  .modal-panel-enter {
    animation: modalZoomIn 0.32s cubic-bezier(0.22, 1, 0.36, 1) forwards;
  }

  .modal-panel-exit {
    animation: modalZoomOut 0.25s cubic-bezier(0.4, 0, 0.2, 1) forwards;
  }
}

@keyframes modalZoomIn {
  0% {
    opacity: 0;
    transform: scale(0.88) translateY(12px);
  }
  100% {
    opacity: 1;
    transform: scale(1) translateY(0);
  }
}

@keyframes modalZoomOut {
  0% {
    opacity: 1;
    transform: scale(1);
  }
  100% {
    opacity: 0;
    transform: scale(0.88) translateY(12px);
  }
}

/* ═══════════════════════════════════════════════
   4. Tab 切换 · tab-slide
   ═══════════════════════════════════════════════ */

/*
 * 结构假设：
 *   .tab-bar { position: relative; }
 *     .tab-item           → 各 Tab 项
 *     .tab-indicator      → 滑动指示条（absolute，由 JS 更新 left/width）
 */

.tab-bar {
  position: relative;
  display: flex;
  gap: 2px;
  background: var(--input-bg);
  border-radius: 14px;
  padding: 3px;
}

.tab-item {
  flex: 1;
  padding: 8px 12px;
  font-size: 14px;
  font-weight: 600;
  text-align: center;
  color: var(--text-3);
  background: transparent;
  border: none;
  border-radius: 11px;
  cursor: pointer;
  position: relative;
  z-index: 1;
  transition: color 0.25s cubic-bezier(0.4, 0, 0.2, 1);
  touch-action: manipulation;
  user-select: none;
  -webkit-user-select: none;
  font-family: inherit;
}

.tab-item.active {
  color: var(--text);
}

/* 滑动指示器（绝对定位，JS 控制 left & width） */
.tab-indicator {
  position: absolute;
  top: 3px;
  bottom: 3px;
  height: auto;
  background: var(--hover);
  border-radius: 11px;
  /* ★ 关键：transform: translateX + width 的过渡 */
  transition:
    left  0.32s cubic-bezier(0.4, 0, 0.2, 1),
    width 0.32s cubic-bezier(0.4, 0, 0.2, 1);
  will-change: left, width;
  z-index: 0;
  box-shadow: 0 0 8px rgba(255, 45, 123, 0.08);
}

/* 无 JS 时的纯 CSS 指示器方案（用 :checked 模拟） */
.tab-radio { display: none; }
.tab-radio:checked + .tab-item {
  color: var(--text);
}

/* Tab 内容面板淡入 */
.tab-panel {
  opacity: 0;
  transform: translateY(4px);
  transition: opacity 0.28s cubic-bezier(0.4, 0, 0.2, 1),
              transform 0.28s cubic-bezier(0.4, 0, 0.2, 1);
  display: none;
}

.tab-panel.active {
  opacity: 1;
  transform: translateY(0);
  display: block;
}

/* ═══════════════════════════════════════════════
   5. 按钮触摸反馈 · btn-active
   ═══════════════════════════════════════════════ */

/*
 * 使用方式：添加 .btn-active 类到任意可点击元素，
 * 触摸/点击时自动播放缩放反馈动画。
 *
 * 也可通过 :active 伪类直接使用（见下方 .btn-feedback）。
 */

/* — 缩放反馈（:active 时刻触发）— */
.btn-feedback {
  transition: transform 0.15s cubic-bezier(0.4, 0, 0.2, 1),
              box-shadow 0.15s cubic-bezier(0.4, 0, 0.2, 1);
  touch-action: manipulation;
  -webkit-tap-highlight-color: transparent;
}

.btn-feedback:active {
  transform: scale(0.93);
}

/* 带发光反馈的版本（霓虹主题增强） */
.btn-active {
  position: relative;
  transition: transform 0.18s cubic-bezier(0.4, 0, 0.2, 1);
  touch-action: manipulation;
  -webkit-tap-highlight-color: transparent;
}

.btn-active:active {
  transform: scale(0.93);
}

/* 触摸涟漪效果（::after pseudo） */
.btn-active::after {
  content: '';
  position: absolute;
  inset: 0;
  border-radius: inherit;
  background: radial-gradient(circle at var(--ripple-x, 50%) var(--ripple-y, 50%),
    rgba(255, 255, 255, 0.18) 0%,
    transparent 60%
  );
  opacity: 0;
  transition: opacity 0.4s ease;
  pointer-events: none;
}

.btn-active:active::after {
  opacity: 1;
}

/* 按下时边框微发光（兼容无 :has 选择器的浏览器） */
.btn-active:active {
  box-shadow: 0 0 0 2px rgba(255, 45, 123, 0.25);
}

/* ═══════════════════════════════════════════════
   6. 辅助动画（工具类）
   ═══════════════════════════════════════════════ */

/* 淡入 */
.fade-in {
  animation: fadeIn 0.3s cubic-bezier(0.4, 0, 0.2, 1) forwards;
}

@keyframes fadeIn {
  0%   { opacity: 0; }
  100% { opacity: 1; }
}

/* 淡出 */
.fade-out {
  animation: fadeOut 0.25s cubic-bezier(0.4, 0, 0.2, 1) forwards;
}

@keyframes fadeOut {
  0%   { opacity: 1; }
  100% { opacity: 0; }
}

/* 从下方滑入 */
.slide-up-in {
  animation: slideUpIn 0.35s cubic-bezier(0.22, 1, 0.36, 1) forwards;
}

@keyframes slideUpIn {
  0% {
    opacity: 0;
    transform: translateY(16px);
  }
  100% {
    opacity: 1;
    transform: translateY(0);
  }
}

/* 脉冲微缩放 */
.pulse-scale {
  animation: pulseScale 0.5s cubic-bezier(0.34, 1.56, 0.64, 1);
}

@keyframes pulseScale {
  0%   { transform: scale(1); }
  40%  { transform: scale(1.04); }
  100% { transform: scale(1); }
}

/* — 任务要求：modalIn / modalOut 缩放弹出 — */
.modal-enter-task {
  animation: modalIn 0.3s ease-out forwards;
}
.modal-exit-task {
  animation: modalOut 0.2s ease-in forwards;
}

@keyframes modalIn {
  0%   { transform: scale(0.9); opacity: 0; }
  100% { transform: scale(1);   opacity: 1; }
}

@keyframes modalOut {
  0%   { transform: scale(1);   opacity: 1; }
  100% { transform: scale(0.9); opacity: 0; }
}

/* ═══════════════════════════════════════════════
   6b. Toast 滑入动画
   ═══════════════════════════════════════════════ */

/* Toast 从右侧滑入 */
.toast-enter {
  animation: toastSlideIn 0.3s cubic-bezier(0.4, 0, 0.2, 1) forwards;
}

@keyframes toastSlideIn {
  0% {
    opacity: 0;
    transform: translateX(100%);
  }
  100% {
    opacity: 1;
    transform: translateX(0);
  }
}

/* 任务要求的精确 keyframe 名 toastIn（与 toastSlideIn 相同） */
@keyframes toastIn {
  0%   { transform: translateX(100%); opacity: 0; }
  100% { transform: translateX(0);    opacity: 1; }
}

/* Toast 滑出 */
.toast-exit {
  animation: toastSlideOut 0.25s cubic-bezier(0.4, 0, 0.2, 1) forwards;
}

@keyframes toastSlideOut {
  0% {
    opacity: 1;
    transform: translateX(0);
  }
  100% {
    opacity: 0;
    transform: translateX(100%);
  }
}

/* ═══════════════════════════════════════════════
   6c. 骨架屏闪烁动画
   ═══════════════════════════════════════════════ */

/* 骨架屏闪烁效果 - 使用 background-position 动画 */
.skeleton-shimmer {
  background: linear-gradient(
    90deg,
    var(--soft-2) 25%,
    var(--soft-3) 50%,
    var(--soft-2) 75%
  );
  background-size: 200% 100%;
  animation: shimmer 1.5s infinite;
  border-radius: 8px;
}

@keyframes shimmer {
  0% {
    background-position: 200% 0;
  }
  100% {
    background-position: -200% 0;
  }
}

/* 骨架屏占位符变体 */
.skeleton-text {
  height: 14px;
  margin-bottom: 8px;
  border-radius: 4px;
}

.skeleton-text-lg {
  height: 20px;
  margin-bottom: 10px;
  border-radius: 6px;
}

.skeleton-circle {
  width: 48px;
  height: 48px;
  border-radius: 50%;
}

/* ═══════════════════════════════════════════════
   6d. 按钮触摸反馈增强 (CSS 伪类)
   ═══════════════════════════════════════════════ */

/* 通用按钮触摸缩放 - 使用 :active 伪类 */
.btn:active {
  transform: scale(0.96);
  transition: transform 0.1s cubic-bezier(0.4, 0, 0.2, 1);
}

/* 主按钮触摸反馈 */
.btn-primary:active {
  transform: scale(0.96);
  transition: transform 0.1s cubic-bezier(0.4, 0, 0.2, 1);
}

/* 危险按钮触摸反馈 */
.btn-danger:active {
  transform: scale(0.96);
  transition: transform 0.1s cubic-bezier(0.4, 0, 0.2, 1);
}

/* 成功按钮触摸反馈 */
.btn-success:active {
  transform: scale(0.96);
  transition: transform 0.1s cubic-bezier(0.4, 0, 0.2, 1);
}

/* ═══════════════════════════════════════════════
   7. 无障碍 · prefers-reduced-motion
   ═══════════════════════════════════════════════ */

@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;
  }

  /* 覆盖所有关键帧为静态 */
  @keyframes pageSlideIn     { 0%, 100% { opacity: 1; transform: none; } }
  @keyframes pageSlideOut    { 0%, 100% { opacity: 1; transform: none; } }
  @keyframes pageSlideInLeft { 0%, 100% { opacity: 1; transform: none; } }
  @keyframes pageScaleIn     { 0%, 100% { opacity: 1; transform: none; } }
  @keyframes pageScaleOut    { 0%, 100% { opacity: 1; transform: none; } }
  @keyframes flipBounce          { 0%, 100% { transform: none; } }
  @keyframes flipBounceForward   { 0%, 100% { transform: rotateY(180deg); } }
  @keyframes flipBounceBackward  { 0%, 100% { transform: rotateY(0deg); } }
  @keyframes overlayFadeIn  { 0%, 100% { opacity: 1; } }
  @keyframes overlayFadeOut { 0%, 100% { opacity: 1; } }
  @keyframes modalSlideUp   { 0%, 100% { opacity: 1; transform: none; } }
  @keyframes modalSlideDown { 0%, 100% { opacity: 1; transform: none; } }
  @keyframes modalZoomIn    { 0%, 100% { opacity: 1; transform: none; } }
  @keyframes modalZoomOut   { 0%, 100% { opacity: 1; transform: none; } }
  @keyframes fadeIn         { 0%, 100% { opacity: 1; } }
  @keyframes fadeOut        { 0%, 100% { opacity: 1; } }
  @keyframes slideUpIn      { 0%, 100% { opacity: 1; transform: none; } }
  @keyframes pulseScale     { 0%, 100% { transform: none; } }
  @keyframes modalIn        { 0%, 100% { opacity: 1; transform: none; } }
  @keyframes modalOut       { 0%, 100% { opacity: 1; transform: none; } }
  @keyframes toastIn        { 0%, 100% { opacity: 1; transform: none; } }
  @keyframes fadeRouteIn    { 0%, 100% { opacity: 1; } }
  @keyframes fadeRouteOut   { 0%, 100% { opacity: 1; } }
  @keyframes toastSlideIn   { 0%, 100% { opacity: 1; transform: none; } }
  @keyframes toastSlideOut  { 0%, 100% { opacity: 1; transform: none; } }
  @keyframes shimmer        { 0%, 100% { background-position: 0 0; } }

  /* 禁用所有动画类 */
  .page-enter, .page-exit, .page-enter-reverse,
  .page-enter-scale, .page-exit-scale,
  .fade-enter, .fade-enter-active, .fade-exit, .fade-exit-active,
  .card-flip, .flipper,
  .card-flip-bounce-active, .card-flip-bounce-reset,
  .modal-enter, .modal-exit, .modal-enter-task, .modal-exit-task,
  .modal-panel-enter, .modal-panel-exit,
  .tab-panel, .fade-in, .fade-out,
  .slide-up-in, .pulse-scale,
  .toast-enter, .toast-exit,
  .skeleton-shimmer {
    animation: none !important;
  }

  /* Tab 指示器瞬移 */
  .tab-indicator {
    transition: none !important;
  }

  /* 卡片翻转瞬切 */
  .card-flip,
  .flipper {
    transition: transform 0.01ms !important;
  }

  /* 按钮反馈归零 */
  .btn:active,
  .btn-active:active,
  .btn-feedback:active {
    transform: none !important;
    box-shadow: none !important;
  }
}
