/* ==========================================================================
   Scrilab Motion — 動效層
   所有 keyframes、進場、捲動揭露、跨頁轉場、點擊回饋集中於此。
   鐵則：只動 transform / opacity；will-change 只在互動當下加。
   ========================================================================== */

/* --------------------------------------------------------------------------
   1. Keyframes
   -------------------------------------------------------------------------- */
@keyframes fade-in {
  from { opacity: 0; }
  to   { opacity: 1; }
}

@keyframes fade-up {
  from { opacity: 0; transform: translate3d(0, 24px, 0); }
  to   { opacity: 1; transform: translate3d(0, 0, 0); }
}

@keyframes fade-down {
  from { opacity: 0; transform: translate3d(0, -16px, 0); }
  to   { opacity: 1; transform: translate3d(0, 0, 0); }
}

@keyframes scale-in {
  from { opacity: 0; transform: scale(.96); }
  to   { opacity: 1; transform: scale(1); }
}

@keyframes slide-in-right {
  from { opacity: 0; transform: translate3d(24px, 0, 0); }
  to   { opacity: 1; transform: translate3d(0, 0, 0); }
}

@keyframes shake {
  0%, 100%     { transform: translate3d(0, 0, 0); }
  20%, 60%     { transform: translate3d(-4px, 0, 0); }
  40%, 80%     { transform: translate3d(4px, 0, 0); }
}

@keyframes pulse-dot {
  0%, 100% { opacity: 1;   transform: scale(1); }
  50%      { opacity: .45; transform: scale(.85); }
}

@keyframes spin {
  to { transform: rotate(360deg); }
}

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

/* 主 CTA 的極慢光暈掃過 */
@keyframes sweep {
  from { transform: translate3d(-120%, 0, 0) skewX(-20deg); }
  to   { transform: translate3d(320%, 0, 0)  skewX(-20deg); }
}

/* 打勾描邊（付款成功） */
@keyframes draw-check {
  to { stroke-dashoffset: 0; }
}

/* Ripple */
@keyframes ripple-out {
  from { opacity: .45; transform: scale(0); }
  to   { opacity: 0;   transform: scale(2.6); }
}

/* --------------------------------------------------------------------------
   2. 首屏進場
   body 預設帶 .is-loading（CSS 先藏），head 內同步 JS 移除以避免 FOUC。
   -------------------------------------------------------------------------- */
/* 只有在 JS 可用時才預先隱藏 —— html.js 由 <head> 內的同步腳本加上。
   JS 停用或掛掉時這條選擇器不成立，內容維持可見，絕不留白頁。 */
.js [data-enter] {
  opacity: 0;
  transform: translate3d(0, 16px, 0);
}

.js body:not(.is-loading) [data-enter] {
  animation: fade-up var(--dur-slow) var(--ease-out) forwards;
  animation-delay: calc(var(--enter-i, 0) * 60ms);
}

/* 超過 6 項就別再排隊了，會拖沓 */
.js body:not(.is-loading) [data-enter][style*="--enter-i: 6"],
.js body:not(.is-loading) [data-enter][style*="--enter-i: 7"],
.js body:not(.is-loading) [data-enter][style*="--enter-i: 8"] {
  animation-delay: 360ms;
}

/* --------------------------------------------------------------------------
   3. 捲動揭露
   motion.js 的單一 IntersectionObserver 加上 .is-visible，只觸發一次。
   -------------------------------------------------------------------------- */
.js [data-reveal] {
  opacity: 0;
  transform: translate3d(0, 24px, 0);
  transition:
    opacity   var(--dur-slow) var(--ease-out),
    transform var(--dur-slow) var(--ease-out);
  transition-delay: calc(var(--reveal-i, 0) * 70ms);
}

.js [data-reveal="left"]  { transform: translate3d(-28px, 0, 0); }
.js [data-reveal="right"] { transform: translate3d(28px, 0, 0); }
.js [data-reveal="scale"] { transform: scale(.96); }
.js [data-reveal="fade"]  { transform: none; }

.js [data-reveal].is-visible {
  opacity: 1;
  transform: translate3d(0, 0, 0) scale(1);
}

/* 窄螢幕上左右位移會把元素推到視窗外（實測 intro 頁 −12px / +392px），
   雖然 body 的 overflow-x:hidden 會裁掉，但那是遮掩不是修正。
   小螢幕一律退回單純的上浮淡入。 */
@media (max-width: 768px) {
  .js [data-reveal="left"],
  .js [data-reveal="right"] {
    transform: translate3d(0, 24px, 0);
  }
}

/* 最後防線：使用者關閉動畫時直接顯示，不等 observer */
@media (prefers-reduced-motion: reduce) {
  .js [data-reveal],
  .js [data-enter] {
    opacity: 1 !important;
    transform: none !important;
  }
}

/* --------------------------------------------------------------------------
   4. 跨頁轉場（View Transitions API）
   Chromium / Safari 18.2+ 原生支援；其餘瀏覽器自動降級為一般跳頁。
   純 CSS，零 JS，不需 polyfill。
   -------------------------------------------------------------------------- */
@view-transition {
  navigation: auto;
}

::view-transition-old(root) {
  animation: vt-out 180ms var(--ease-in) both;
}

::view-transition-new(root) {
  animation: vt-in 320ms var(--ease-out) both;
}

@keyframes vt-out {
  to { opacity: 0; transform: translate3d(0, -8px, 0); }
}

@keyframes vt-in {
  from { opacity: 0; transform: translate3d(0, 12px, 0); }
}

/* 導覽列與頁尾在轉場中保持不動，避免整頁閃爍 */
.navbar { view-transition-name: site-nav; }
.footer { view-transition-name: site-footer; }

::view-transition-old(site-nav),
::view-transition-new(site-nav),
::view-transition-old(site-footer),
::view-transition-new(site-footer) {
  animation: none;
  mix-blend-mode: normal;
}

@media (prefers-reduced-motion: reduce) {
  ::view-transition-old(root),
  ::view-transition-new(root) {
    animation: none;
  }
}

/* --------------------------------------------------------------------------
   5. 點擊回饋 — 全站統一 ripple
   JS 只負責設 --x / --y 兩個變數，其餘純 CSS。
   -------------------------------------------------------------------------- */
[data-ripple] {
  position: relative;
  overflow: hidden;
  isolation: isolate;
}

[data-ripple]::after {
  content: '';
  position: absolute;
  left: var(--x, 50%);
  top: var(--y, 50%);
  width: 140%;
  aspect-ratio: 1;
  translate: -50% -50%;
  border-radius: 50%;
  background: radial-gradient(circle, currentColor 0%, transparent 65%);
  opacity: 0;
  transform: scale(0);
  pointer-events: none;
  z-index: -1;
}

[data-ripple].is-rippling::after {
  animation: ripple-out var(--dur-slow) var(--ease-out);
}

/* 觸控裝置不做 ripple 位移（手指遮住了，只是干擾） */
@media (hover: none) {
  [data-ripple]::after { display: none; }
}

/* --------------------------------------------------------------------------
   6. 微互動
   -------------------------------------------------------------------------- */

/* 可浮起的卡片 */
.lift {
  transition:
    transform  var(--dur-base) var(--ease-out),
    box-shadow var(--dur-base) var(--ease-out),
    border-color var(--dur-base) var(--ease-out);
}

@media (hover: hover) and (pointer: fine) {
  .lift:hover {
    transform: translate3d(0, -4px, 0);
    box-shadow: var(--elev-3);
  }
}

.lift:active {
  transform: translate3d(0, -1px, 0);
  transition-duration: var(--dur-instant);
}

/* 指針視差 — motion.js 設 --px / --py，僅精準指針裝置啟用 */
@media (hover: hover) and (pointer: fine) {
  [data-tilt] {
    transform:
      perspective(1200px)
      rotateX(calc(var(--py, 0) * -4deg))
      rotateY(calc(var(--px, 0) * 6deg));
    transition: transform var(--dur-base) var(--ease-out);
    transform-style: preserve-3d;
  }

  [data-tilt].is-tilting {
    transition: transform 80ms linear;
  }
}

/* 呼吸的狀態點 */
.dot-pulse {
  animation: pulse-dot 2.4s var(--ease-in-out) infinite;
}

/* 骨架載入 */
.skeleton {
  background: linear-gradient(
    90deg,
    var(--bg-raised) 0%,
    var(--bg-overlay) 50%,
    var(--bg-raised) 100%
  );
  background-size: 200% 100%;
  animation: shimmer 1.6s linear infinite;
  border-radius: var(--r-sm);
  color: transparent;
  user-select: none;
}

/* 表單錯誤震動 */
.is-invalid {
  animation: shake 300ms var(--ease-in-out);
}

/* 旋轉載入 */
.spinner {
  display: inline-block;
  width: 1em;
  height: 1em;
  border: 2px solid currentColor;
  border-top-color: transparent;
  border-radius: 50%;
  animation: spin 700ms linear infinite;
}

/* --------------------------------------------------------------------------
   7. 高度過渡（FAQ 手風琴、切換區塊）
   grid-template-rows 0fr→1fr 是唯一能對 auto 高度做平滑過渡的做法。
   -------------------------------------------------------------------------- */
.collapse {
  display: grid;
  grid-template-rows: 0fr;
  transition: grid-template-rows var(--dur-base) var(--ease-in-out);
}

/* 直接子層是 grid item，必須零 padding。
   min-height:0 只消得掉內容高度，消不掉 padding —— padding 放這裡的話
   收合狀態仍會留下該 padding 的高度（實測殘留 20px，露出半行字）。
   要留白請寫在再內一層的 .collapse__inner。 */
.collapse > * {
  overflow: hidden;
  min-height: 0;
  padding: 0;
}

.collapse.is-open {
  grid-template-rows: 1fr;
}
