/* ==========================================================================
   琪靈記帳 — 動畫共用層（所有 LIFF 頁面，緊接 colors.css 之後載入）
   ==========================================================================

   為什麼獨立成一支、而不是放進 app.css：home.html、billing.html、ops-usage.html
   沒有引用 app.css，但 home.html 是動畫最多的頁面；只有 colors.css 與這支是全站都載入的。

   維護規則
   1. 時間與緩動一律用下面的 token，不要在頁面裡再寫死 0.2s、cubic-bezier(...)。
   2. 只動 opacity 與 transform。LINE 內建瀏覽器（WebView）動 width／height／box-shadow
      會掉幀；進度條 width 是既有例外，新動畫不要再加。
   3. 這裡不寫任何色碼，顏色只引用 colors.css 的 token。
   4. 使用者開了「減少動態效果」就全部停掉（第三節），新動畫不需要各自處理。
   ========================================================================== */

/* 一、Token ---------------------------------------------------------------- */

:root {
  --dur-fast: 120ms;   /* 按壓、hover 回饋 */
  --dur-base: 200ms;   /* 一般狀態切換、彈窗、卡片出現 */
  --dur-slow: 320ms;   /* 進度、展開收合、較大的位移 */
  --dur-enter: 560ms;  /* 清單錯開進場：要讓人看得清楚一列一列進來，所以比 slow 慢 */
  --stagger-step: 70ms; /* 錯開進場每一個的間隔 */

  --ease-standard: ease;                          /* 一般過渡 */
  --ease-out: cubic-bezier(0.2, 0.8, 0.2, 1);     /* 元素進場（快進慢停） */
}

/* 二、載入中狀態 ------------------------------------------------------------ */

/* Skeleton：給一個區塊加上 .skeleton 就會變成灰色骨架並掃光；
   尺寸由使用處決定（height／width／border-radius），文字內容建議留空或放 &nbsp;。 */
.skeleton {
  display: block;
  min-height: 1em;
  border-radius: var(--radius, 10px);
  background-color: var(--line);
  background-image: linear-gradient(90deg, transparent, var(--disabled-soft), transparent);
  background-size: 200% 100%;
  background-repeat: no-repeat;
  color: transparent;
  pointer-events: none;
  user-select: none;
  animation: skeletonSweep 1.4s var(--ease-standard) infinite;
}

.skeleton-line { height: 14px; margin: var(--space-snug, 8px) 0; }
.skeleton-line.short { width: 40%; }
.skeleton-block { height: 72px; }

@keyframes skeletonSweep {
  from { background-position: 200% 0; }
  to   { background-position: -200% 0; }
}

/* Spinner：按鈕或小區塊的忙碌指示。用 <span class="spinner" role="status" aria-label="載入中"></span> */
.spinner {
  display: inline-block;
  width: 18px;
  height: 18px;
  border: 2px solid var(--line);
  border-top-color: var(--action);
  border-radius: 50%;
  vertical-align: middle;
  animation: spinnerTurn 0.8s linear infinite;
}

@keyframes spinnerTurn {
  to { transform: rotate(360deg); }
}

/* 三、減少動態效果 ---------------------------------------------------------- */

/* 三之一、換頁放大展開（設定頁任務磚 → 目的頁，見 page-zoom.js） ---------------- */

@keyframes pageZoomIn {
  from { opacity: 0; transform: scale(0.4); }
  to   { opacity: 1; transform: none; }
}
html.page-zoom-in body {
  transform-origin: var(--zoom-x, 50%) var(--zoom-y, 80px);
  animation: pageZoomIn .9s cubic-bezier(0.22, 1, 0.36, 1);
}

/* 作業系統層級的「減少動態效果」。不是 display:none，只是把時間壓到幾乎為 0，
   這樣依賴 transitionend／animationend 的程式碼仍然會被觸發。 */
@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    transition-delay: 0s !important;
    scroll-behavior: auto !important;
  }

  /* 骨架與轉圈本來就是無限循環，壓成 0.01ms 會變成閃一下；改成靜止。
     骨架保留灰底，轉圈留一段弧，仍然看得出「載入中」。 */
  .skeleton { animation: none !important; background-image: none; }
  .spinner  { animation: none !important; }
}

/* 金額骨架：數字還沒回來時佔位，避免版面在資料到達時跳動。
   搭配 .skeleton 使用，例如 class="skeleton skeleton-amount"。 */
.skeleton-amount { display: inline-block; min-width: 5em; }
.amount-display.skeleton-amount { min-width: 7em; }

/* 三之二、內頁進場淡入（項目：所有載入 motion.css 的頁面）
   換頁是整頁重載，沒有這層時畫面會白閃一下。純 CSS、只動 opacity，不需要各頁配合。
   設定頁任務磚進來的頁面由上面的 html.page-zoom-in body 覆蓋（選擇器較具體），兩者二選一。 */
body { animation: fadeIn var(--dur-base) var(--ease-out); }

/* 三之三、載入太久的提示（common.js 的 setupSlowLoadHint 會長出這個元素） */
.slow-load-hint {
  position: fixed;
  left: 50%;
  bottom: 96px;
  transform: translateX(-50%);
  max-width: calc(100% - 32px);
  padding: 8px 16px;
  border: 1px solid var(--line);
  border-radius: var(--radius-pill, 999px);
  background: var(--surface);
  color: var(--ink-2);
  font-size: 13px;
  pointer-events: none;
  z-index: 150;
  animation: fadeIn var(--dur-base) var(--ease-out);
}

/* 四、出現動畫 ----------------------------------------------------------- */

/* 原本在 home.html，搬到共用層，其他頁面要做進場動畫直接用同一組。
   搭配時間：彈窗 var(--dur-base)、卡片 var(--dur-slow)，緩動用 var(--ease-out)。 */
@keyframes fadeIn {
  from { opacity: 0; }
  to { opacity: 1; }
}
@keyframes modalSlideUp {
  from { transform: translateY(20px) scale(0.96); opacity: 0; }
  to { transform: translateY(0) scale(1); opacity: 1; }
}
@keyframes bubbleSlideIn {
  from { opacity: 0; transform: translateY(8px); }
  to { opacity: 1; transform: translateY(0); }
}
@keyframes cardFadeIn {
  from { opacity: 0; transform: translateY(12px) scale(0.97); }
  to { opacity: 1; transform: translateY(0) scale(1); }
}

/* 錯開進場（staggered entrance）：同一批元素用同一個動畫，靠 --i 決定誰晚一點開始。
   用法：給每個元素加 class="stagger-in" 與 style="--i:<第幾個，從 0 開始>"。
   只有前 10 個依序錯開（每個晚 --stagger-step），第 11 個起跟第 10 個同時進場，長清單不會讓人等。
   用 backwards 而不是 both：動畫結束後不留 transform，元素自己的 hover／active 才不會被蓋掉。 */
@keyframes rowSlideInRight {
  from { opacity: 0; transform: translateX(24px); }
  to   { opacity: 1; transform: translateX(0); }
}
.stagger-in {
  animation: rowSlideInRight var(--dur-enter) var(--ease-out) backwards;
  animation-delay: calc(min(var(--i, 0), 9) * var(--stagger-step));
}
