/* 入场动画（2026-10-01）：等价于原版 framer-motion 的 initial/whileInView
   —— 静态页用一个 IntersectionObserver 还原，无需 React */
[data-reveal]{opacity:0;transform:translateY(var(--reveal-y,20px));transition:opacity .6s cubic-bezier(.22,.61,.36,1),transform .6s cubic-bezier(.22,.61,.36,1);will-change:opacity,transform}
[data-reveal].is-in{opacity:1;transform:none}
@media (prefers-reduced-motion:reduce){[data-reveal]{opacity:1;transform:none;transition:none}}
