/* ============================================================
 * motion.css — 全局动效系统 v1.0
 * 色彩能量精油 · 一百零八瓶疗愈系统
 * ------------------------------------------------------------
 * 原则：
 *  ① 只动 transform / opacity / filter / clip-path（GPU 合成层）
 *  ② JS 只负责加/减类名与注入 CSS 变量，动画本体全在 CSS
 *  ③ prefers-reduced-motion 时全量降级为无动画
 * 依赖：app.js(APP) / enhance.js / breathe.js(BREATHE)
 * ============================================================ */

/* ============================================================
   0. 无障碍总闸：偏好减少动效 → 一切动画近乎关闭
   ============================================================ */
@media (prefers-reduced-motion: reduce) {
  .m-ghost, #view.m-in-fwd, #view.m-in-back, .m-dot, .m-glow,
  .confirm-card.fly-in, .hb, .m-ripple, .m-star, #theme-btn.m-spin,
  .toast, .m-grow, .m-img-in, .rv-left, .m-ambient, .bottle-sk::after {
    animation: none !important;
    transition: none !important;
  }
  .m-ghost, .m-dot, .m-glow, .m-ripple, .m-star, .m-ambient { display: none !important; }
  .rv-left, .m-img-in, .m-grow { opacity: 1 !important; transform: none !important; clip-path: none !important; filter: none !important; }
}

/* ============================================================
   1. 路由切换：Crossfade + 方向感知位移
   旧视图 ghost 反向滑出（淡出），新视图同向滑入
   ============================================================ */
.m-ghost {
  position: fixed; z-index: 40; pointer-events: none;
  overflow: hidden; background: var(--bg);
  will-change: transform, opacity;
}
.m-ghost .m-ghost-scroll { transform: translateY(var(--m-sy, 0px)); }
.m-ghost.m-out-fwd  { animation: m-out-fwd  .34s cubic-bezier(.4, .1, .6, 1) both; }
.m-ghost.m-out-back { animation: m-out-back .34s cubic-bezier(.4, .1, .6, 1) both; }
@keyframes m-out-fwd  { to { opacity: 0; transform: translateX(-46px); } }
@keyframes m-out-back { to { opacity: 0; transform: translateX(46px); } }

#view.m-in-fwd  { animation: m-in-fwd  .42s cubic-bezier(.22, .9, .3, 1) both; }
#view.m-in-back { animation: m-in-back .42s cubic-bezier(.22, .9, .3, 1) both; }
#view.m-in-fade { animation: m-in-fade .3s ease both; }
@keyframes m-in-fwd  { from { opacity: 0; transform: translateX(46px); }  to { opacity: 1; transform: none; } }
@keyframes m-in-back { from { opacity: 0; transform: translateX(-46px); } to { opacity: 1; transform: none; } }
@keyframes m-in-fade { from { opacity: 0; } to { opacity: 1; } }

/* ============================================================
   2. landing → home：精油粒子从四周汇聚到中心
   JS 生成 .m-dot（起点由 --x0/--y0 变量注入），.go 后飞向中心
   ============================================================ */
.m-layer {
  position: fixed; inset: 0; z-index: 1600;
  pointer-events: none; overflow: hidden;
}
.m-dot {
  position: absolute; left: 0; top: 0;
  width: 10px; height: 10px; margin: -5px 0 0 -5px;
  border-radius: 50%;
  background: radial-gradient(circle at 35% 30%,
    color-mix(in srgb, var(--dc, #c9a86a) 40%, #fff 60%),
    var(--dc, #c9a86a));
  box-shadow: 0 0 12px color-mix(in srgb, var(--dc, #c9a86a) 65%, transparent);
  transform: translate(var(--x0, -40px), var(--y0, -40px)) scale(var(--s0, 1));
  opacity: 0;
  transition: transform .92s cubic-bezier(.5, .05, .22, 1), opacity .92s ease;
  will-change: transform, opacity;
}
.m-dot.m-go {
  transform: translate(var(--x1, 50vw), var(--y1, 46vh)) scale(.18);
  opacity: 1;
  transition-timing-function: cubic-bezier(.34, .02, .18, 1);
}
.m-dot.m-vanish { opacity: 0; transform: translate(var(--x1, 50vw), var(--y1, 46vh)) scale(2.6); transition-duration: .5s, .5s; }
.m-glow {
  position: absolute; left: 50%; top: 46%;
  width: 130px; height: 130px; margin: -65px 0 0 -65px;
  border-radius: 50%;
  background: radial-gradient(circle,
    rgba(255, 249, 230, .9) 0%,
    rgba(201, 168, 106, .5) 34%,
    rgba(201, 168, 106, .1) 58%,
    transparent 74%);
  transform: scale(0); opacity: 0;
  will-change: transform, opacity;
}
.m-glow.m-burst { animation: m-glow-burst .9s ease-out both; }
@keyframes m-glow-burst {
  0% { transform: scale(.1); opacity: 0; }
  22% { opacity: 1; }
  100% { transform: scale(7.5); opacity: 0; }
}

/* ============================================================
   3. 选择 → 确认：三瓶从下方弧线飞入固定位置
   JS 注入 --mx/--my/--mr/--md（水平偏移/垂直起点/旋转/延迟）
   ============================================================ */
.confirm-card.fly-in {
  animation: m-fly-in .74s cubic-bezier(.18, .8, .26, 1) both;
  animation-delay: var(--md, 0s);
  will-change: transform, opacity;
}
@keyframes m-fly-in {
  from { opacity: 0; transform: translate(var(--mx, 0px), var(--my, 130px)) rotate(var(--mr, 0deg)) scale(.55); }
  60%  { opacity: 1; }
  to   { opacity: 1; transform: none; }
}

/* ============================================================
   4. 微交互：入选心跳 + 涟漪扩散
   ============================================================ */
.hb { animation: m-heartbeat .55s cubic-bezier(.36, .07, .19, .97) both; }
@keyframes m-heartbeat {
  0%   { transform: scale(1); }
  30%  { transform: scale(1.15); }
  55%  { transform: scale(.96); }
  75%  { transform: scale(1.04); }
  100% { transform: scale(1); }
}
.m-ripple {
  position: absolute; left: 50%; top: 50%;
  width: 56px; height: 56px; margin: -28px 0 0 -28px;
  border-radius: 50%; pointer-events: none;
  border: 2.5px solid color-mix(in srgb, var(--rc, #c9a86a) 75%, transparent);
  transform: scale(.2); opacity: .9;
  animation: m-ripple .7s cubic-bezier(.2, .7, .3, 1) forwards;
  will-change: transform, opacity;
}
@keyframes m-ripple {
  to { transform: scale(2.4); opacity: 0; }
}
.oil-card, .sel-slot { position: relative; overflow: visible; }

/* ============================================================
   5. 收藏：金色星星爆炸粒子（clip-path 星形）
   JS 注入 --tx/--ty/--rot/--sd
   ============================================================ */
.m-star {
  position: fixed; left: 0; top: 0;
  width: 13px; height: 13px; margin: -6.5px 0 0 -6.5px;
  background: linear-gradient(160deg, #ffe9a8, var(--gold, #c9a86a) 60%, #b8892f);
  clip-path: polygon(50% 0%, 61% 35%, 98% 35%, 68% 57%, 79% 91%,
                     50% 70%, 21% 91%, 32% 57%, 2% 35%, 39% 35%);
  pointer-events: none; z-index: 2200;
  animation: m-star-burst .82s cubic-bezier(.16, .84, .34, 1) var(--sd, 0s) forwards;
  will-change: transform, opacity;
}
@keyframes m-star-burst {
  0%   { transform: translate(0, 0) rotate(0deg) scale(1); opacity: 1; }
  70%  { opacity: 1; }
  100% { transform: translate(var(--tx, 0px), var(--ty, -60px)) rotate(var(--rot, 180deg)) scale(.1); opacity: 0; }
}

/* ============================================================
   6. 主题切换：图标 360° 旋转
   ============================================================ */
#theme-btn { transition: transform .2s ease; }
#theme-btn.m-spin { animation: m-spin .62s cubic-bezier(.45, .1, .25, 1); }
@keyframes m-spin {
  0%   { transform: rotate(0deg) scale(1); }
  50%  { transform: rotate(200deg) scale(1.18); }
  100% { transform: rotate(360deg) scale(1); }
}

/* ============================================================
   7. Toast：顶部弹入（过冲回弹）· 上浮消失
   覆盖 style.css 的 toast-in / .toast.out
   ============================================================ */
.toast {
  animation: m-toast-in .46s cubic-bezier(.34, 1.56, .64, 1) both;
  will-change: transform, opacity;
}
@keyframes m-toast-in {
  from { opacity: 0; transform: translateY(-26px) scale(.9); }
  to   { opacity: 1; transform: translateY(0) scale(1); }
}
.toast.out {
  opacity: 0;
  transform: translateY(-18px) scale(.94);
  transition: opacity .34s ease, transform .34s cubic-bezier(.5, 0, .7, .4);
}

/* ============================================================
   8. 图表生长：canvas 自底向上揭示（clip-path 合成器动画）
   ============================================================ */
.m-grow { animation: m-grow .95s cubic-bezier(.22, .9, .3, 1) both; will-change: clip-path, opacity; }
@keyframes m-grow {
  from { clip-path: inset(100% 0 0 0); opacity: .35; }
  to   { clip-path: inset(0 0 0 0); opacity: 1; }
}

/* ============================================================
   9. 图片渐进显示：blur(20px) → 清晰（配合瓶形骨架屏）
   ============================================================ */
.m-img-pend { opacity: 0; }
.m-img-in { animation: m-img-in .62s ease both; }
@keyframes m-img-in {
  from { opacity: 0; filter: blur(20px); transform: scale(1.06); }
  60%  { opacity: 1; }
  to   { opacity: 1; filter: blur(0); transform: none; }
}

/* 瓶形骨架屏：shimmer 扫光 */
.bottle-sk {
  position: absolute; inset: 12% 18%;
  background: color-mix(in srgb, var(--line, #ddd) 40%, transparent);
  clip-path: polygon(40% 0%, 60% 0%, 60% 20%, 74% 27%, 74% 100%, 26% 100%, 26% 27%, 40% 20%);
  overflow: hidden;
}
.bottle-sk::after {
  content: '';
  position: absolute; inset: 0;
  background: linear-gradient(105deg,
    transparent 30%,
    color-mix(in srgb, var(--gold, #c9a86a) 30%, transparent) 48%,
    transparent 66%);
  transform: translateX(-100%);
  animation: m-shimmer 1.3s linear infinite;
}
@keyframes m-shimmer { to { transform: translateX(100%); } }

/* ============================================================
   10. 滚动联动：章节标题从左滑入
   ============================================================ */
.rv-left { opacity: 0; transform: translateX(-28px); will-change: transform, opacity; }
.rv-left.in {
  opacity: 1; transform: none;
  transition: opacity .6s ease, transform .62s cubic-bezier(.22, .9, .3, 1);
}

/* ============================================================
   11. 呼吸增强：光晕随节律扩散/收缩 + 色彩过渡层
   ============================================================ */
.m-ambient {
  position: fixed; inset: 0; z-index: 0;
  pointer-events: none;
  background: radial-gradient(ellipse 70% 55% at 50% 42%,
    color-mix(in srgb, var(--ac, #c9a86a) 16%, transparent) 0%,
    transparent 68%);
  animation: m-ambient var(--adur, 8s) ease-in-out infinite;
  will-change: transform, opacity;
}
@keyframes m-ambient {
  0%, 100% { transform: scale(.96); opacity: .45; }
  50%      { transform: scale(1.06); opacity: .95; }
}
/* 呼吸球表面色彩过渡层（JS 每周期换 --bt，实现「实时变色」） */
.breathe-tint {
  position: absolute; inset: 0; border-radius: 50%;
  background: radial-gradient(circle at 35% 30%, var(--bt, transparent) 0%, transparent 74%);
  opacity: 0; transition: opacity 1.6s ease;
  pointer-events: none; mix-blend-mode: screen;
}
.breathe-tint.on { opacity: .85; }

/* ============================================================
   12. 计数器滚动（JS rAF 驱动，CSS 只保证等宽数字）
   ============================================================ */
.m-counting { font-variant-numeric: tabular-nums; will-change: contents; }

/* ============================================================
   13. Hero 视差 / 年轮滚动旋转：JS 写 CSS 变量，CSS 消费
   ============================================================ */
.term-banner .tb-name   { transform: translateY(calc(var(--plx, 0) * 1px * .18)); }
.term-banner .tb-sub    { transform: translateY(calc(var(--plx, 0) * 1px * .34)); }
.term-banner .tb-phrase { transform: translateY(calc(var(--plx, 0) * 1px * .1)); }
.term-banner .tb-name, .term-banner .tb-sub, .term-banner .tb-phrase { will-change: transform; }
#ch-ring { will-change: transform; }

@media (prefers-reduced-motion: reduce) {
  .term-banner .tb-name, .term-banner .tb-sub, .term-banner .tb-phrase { transform: none !important; }
  #ch-ring { transform: none !important; }
}
