/* ==========================================================================
   動態效果層

   **為什麼獨立成一個檔案而不是併進 base.css**:這裡面每一條都是「拿掉之後網站
   照樣能用」的東西。分開放,以後要調整或整層關掉都不必在版面規則裡翻找,也讓
   base.css 維持在「這個站長什麼樣子」而不是「這個站怎麼動」。

   ## 這裡的「酷炫」是有邊界的

   賣的是保養品,不是電競周邊。所以動效走的是**光澤、緩慢、留白**——玫瑰金的光
   掃過瓶身、卡片輕輕浮起——而不是彈跳、閃爍、霓虹。過度花俏的動畫在美妝電商上
   會直接讀成廉價,而「看起來廉價」對客單價 1,000 up 的商品是實質傷害。

   ## 無障礙:整層可以被使用者關掉

   檔案最後有一個 `prefers-reduced-motion: reduce` 的總開關,把所有動畫與位移
   歸零。這不是加分項——前庭功能障礙的人看到大面積位移會真的頭暈想吐,而作業系統
   裡那個「減少動態效果」就是他們表達「不要動」的方式。**新增任何動效都要確認
   它被那個區塊蓋得到。**
   ========================================================================== */

/* --------------------------------------------------------------------------
   1. 捲動進場

   元素預設是「已經淡出」的狀態,由 JS 加上 .is-in 才浮現。

   **`.js-on` 這個保險很重要**:如果 JS 掛掉或還沒載入,沒有人會來加 .is-in,
   整頁內容就永遠是透明的——一個純裝飾的功能不該有辦法讓整個網站變成空白頁。
   所以初始的隱藏樣式只在 <html> 拿到 .js-on 之後才生效,而 .js-on 是 JS 自己
   加上去的。
   -------------------------------------------------------------------------- */
.js-on [data-reveal] {
  opacity: 0;
  transform: translateY(18px);
}
.js-on [data-reveal].is-in {
  opacity: 1;
  transform: none;
  transition: opacity .7s cubic-bezier(.22, .61, .36, 1),
              transform .7s cubic-bezier(.22, .61, .36, 1);
}
/* 同一排卡片依序浮現,不要六張一起跳出來 */
.js-on [data-reveal].is-in { transition-delay: calc(var(--reveal-i, 0) * 70ms); }

/* --------------------------------------------------------------------------
   2. 頁面頂端的捲動進度條
   -------------------------------------------------------------------------- */
.scroll-progress {
  position: fixed;
  top: 0; left: 0;
  height: 2px;
  width: 100%;
  transform: scaleX(0);
  transform-origin: 0 50%;
  background: linear-gradient(90deg, var(--brand), #e0b98f, var(--brand-strong));
  z-index: 60;
  pointer-events: none;
}

/* --------------------------------------------------------------------------
   3. 頁首:捲動之後收窄並上毛玻璃

   `backdrop-filter` 沒支援的瀏覽器會退回不透明底色(下面那行 background 是
   寫在前面的一般宣告),不會變成看不清楚的半透明。
   -------------------------------------------------------------------------- */
.site-header {
  transition: box-shadow .3s ease, background-color .3s ease, padding .3s ease;
}
.site-header.is-stuck {
  background: rgba(255, 255, 255, .82);
  box-shadow: 0 1px 20px rgba(80, 58, 40, .10);
}
@supports (backdrop-filter: blur(10px)) {
  .site-header.is-stuck { backdrop-filter: blur(12px) saturate(1.4); }
}
.site-header.is-stuck .inner { padding-top: 8px; padding-bottom: 8px; }
.site-header .inner { transition: padding .3s ease; }

/* 購物車數量變動時彈一下 */
@keyframes cart-bump {
  0%   { transform: scale(1); }
  35%  { transform: scale(1.18); }
  70%  { transform: scale(.96); }
  100% { transform: scale(1); }
}
.cart-pill.is-bumped { animation: cart-bump .5s cubic-bezier(.34, 1.56, .64, 1); }

/* --------------------------------------------------------------------------
   4. Hero:玫瑰金光暈 + 標題的光掃過

   光暈用兩顆很大、很淡的徑向漸層慢慢飄。**24 秒一圈是刻意的慢**——快到看得出
   「它在動」就會變成干擾,現在的效果是餘光覺得畫面是活的,但盯著看才發現在飄。
   -------------------------------------------------------------------------- */
.hero { position: relative; overflow: hidden; }
.hero > * { position: relative; z-index: 1; }
.hero::before,
.hero::after {
  content: "";
  position: absolute;
  border-radius: 50%;
  pointer-events: none;
  filter: blur(60px);
  opacity: .55;
}
.hero::before {
  width: 46vw; height: 46vw;
  top: -18vw; left: -10vw;
  background: radial-gradient(circle, rgba(224, 185, 143, .55), transparent 70%);
  animation: drift-a 24s ease-in-out infinite;
}
.hero::after {
  width: 40vw; height: 40vw;
  bottom: -20vw; right: -8vw;
  background: radial-gradient(circle, rgba(245, 218, 224, .6), transparent 70%);
  animation: drift-b 30s ease-in-out infinite;
}
@keyframes drift-a {
  0%, 100% { transform: translate(0, 0) scale(1); }
  50%      { transform: translate(6vw, 4vw) scale(1.12); }
}
@keyframes drift-b {
  0%, 100% { transform: translate(0, 0) scale(1); }
  50%      { transform: translate(-5vw, -3vw) scale(1.08); }
}

/* 標題上的一道光,每隔一陣子掃過去一次 */
.hero h1 {
  background: linear-gradient(100deg,
              var(--ink) 0%, var(--ink) 40%,
              #c99a6e 48%, #e5c9a3 52%, #c99a6e 56%,
              var(--ink) 64%, var(--ink) 100%);
  background-size: 300% 100%;
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  animation: title-sheen 7s ease-in-out infinite;
}
@keyframes title-sheen {
  0%, 55% { background-position: 130% 0; }
  85%, 100% { background-position: -30% 0; }
}

/* Hero 內容依序進場 */
.js-on .hero .eyebrow,
.js-on .hero h1,
.js-on .hero p,
.js-on .hero .btn {
  animation: rise-in .8s cubic-bezier(.22, .61, .36, 1) backwards;
}
.js-on .hero .eyebrow { animation-delay: .05s; }
.js-on .hero h1       { animation-delay: .15s; }
.js-on .hero p        { animation-delay: .28s; }
.js-on .hero .btn     { animation-delay: .42s; }
@keyframes rise-in {
  from { opacity: 0; transform: translateY(16px); }
  to   { opacity: 1; transform: none; }
}

/* --------------------------------------------------------------------------
   5. 商品卡:浮起 + 圖片微推近 + 一道光掃過
   -------------------------------------------------------------------------- */
.product-card {
  transition: transform .38s cubic-bezier(.22, .61, .36, 1),
              box-shadow .38s ease,
              border-color .38s ease;
}
.product-card:hover {
  transform: translateY(-6px);
  box-shadow: var(--shadow-lift);
  border-color: var(--line-strong);
}
.product-card .thumb {
  position: relative;
  overflow: hidden;
}
.product-card .thumb img {
  transition: transform .55s cubic-bezier(.22, .61, .36, 1);
}
.product-card:hover .thumb img { transform: scale(1.06); }

/* 掃過去的那道光。用 ::after 疊在圖片上,不動 DOM。 */
.product-card .thumb::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(105deg,
              transparent 35%, rgba(255, 255, 255, .55) 50%, transparent 65%);
  transform: translateX(-120%);
  pointer-events: none;
}
.product-card:hover .thumb::after {
  transition: transform .9s ease;
  transform: translateX(120%);
}

/* 標籤在卡片浮起時跟著亮一下 */
.product-card .tag { transition: transform .3s ease; }
.product-card:hover .tag-save { transform: scale(1.06); }

/* --------------------------------------------------------------------------
   6. 按鈕:主要按鈕的光澤與按壓回饋
   -------------------------------------------------------------------------- */
.btn {
  position: relative;
  overflow: hidden;
  transition: transform .18s ease, background-color .25s ease,
              border-color .25s ease, box-shadow .25s ease;
}
.btn-primary:hover { box-shadow: 0 6px 18px rgba(150, 104, 66, .32); }
.btn:active:not(:disabled):not(.is-disabled) { transform: translateY(1px) scale(.99); }

.btn-primary::after {
  content: "";
  position: absolute;
  top: 0; bottom: 0;
  width: 45%;
  background: linear-gradient(100deg, transparent, rgba(255, 255, 255, .32), transparent);
  transform: translateX(-180%) skewX(-18deg);
  pointer-events: none;
}
.btn-primary:hover::after {
  transition: transform .75s ease;
  transform: translateX(320%) skewX(-18deg);
}

/* 送出中:給一個「已經收到」的回饋。表單送出後頁面就要換掉了,沒有這個回饋的話
   慢一點的連線上客人會以為沒按到,然後再按一次。 */
.btn.is-busy { pointer-events: none; opacity: .75; }
.btn.is-busy::before {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(90deg, transparent, rgba(255, 255, 255, .38), transparent);
  animation: busy-sweep 1.1s linear infinite;
}
@keyframes busy-sweep {
  from { transform: translateX(-100%); }
  to   { transform: translateX(100%); }
}

/* --------------------------------------------------------------------------
   7. 圖片載入淡入

   `.is-loaded` 由 JS 在圖片實際載完時加上。沒有 JS 的話 `.js-on` 不存在,
   圖片就是一般的顯示行為,不會卡在透明。
   -------------------------------------------------------------------------- */
.js-on img[data-fade] { opacity: 0; transition: opacity .6s ease; }
.js-on img[data-fade].is-loaded { opacity: 1; }

/* --------------------------------------------------------------------------
   8. 數字跑動 + 級距進度條

   進度條從 0 長到實際比例。夥伴每次打開儀表板最想知道的就是「離下一階還差多少」,
   讓那條線在眼前長出來,比一個靜止的長度更容易讀出「現在到哪了」。
   -------------------------------------------------------------------------- */
/* **進度條的動畫用 CSS 的 scaleX,不是用 JS 去改 width。**
   差別在壞掉的時候會怎樣:JS 的做法要先把寬度設成 0 再設回去,萬一那個「設回去」
   沒發生(分頁在背景、rAF 被暫停、腳本出錯),夥伴看到的就是一條 0% 的進度條——
   在一個算錢的頁面上顯示「你還沒有業績」。改用 scaleX 之後,真正的寬度自始至終
   都是後端算出來的那一個,動畫只是把它壓扁再放開;動畫沒跑 = 直接是正確的長度。 */
.tier-fill {
  transform-origin: left center;
  animation: tier-grow 1.4s cubic-bezier(.22, .61, .36, 1);
}
@keyframes tier-grow {
  from { transform: scaleX(0); }
  to   { transform: scaleX(1); }
}
.js-on .stat .value { font-variant-numeric: tabular-nums; }

.stat {
  transition: transform .35s cubic-bezier(.22, .61, .36, 1), box-shadow .35s ease;
}
.stat:hover { transform: translateY(-3px); box-shadow: var(--shadow-lift); }

/* --------------------------------------------------------------------------
   9. 回到頂端
   -------------------------------------------------------------------------- */
.to-top {
  position: fixed;
  right: 20px; bottom: 20px;
  width: 42px; height: 42px;
  display: grid; place-items: center;
  border: 1px solid var(--line-strong);
  border-radius: 50%;
  background: rgba(255, 255, 255, .9);
  color: var(--brand-strong);
  font-size: 1.1rem; line-height: 1;
  cursor: pointer;
  opacity: 0;
  transform: translateY(12px);
  pointer-events: none;
  transition: opacity .3s ease, transform .3s ease, box-shadow .3s ease;
  z-index: 55;
  box-shadow: var(--shadow);
}
.to-top.is-on { opacity: 1; transform: none; pointer-events: auto; }
.to-top:hover { box-shadow: var(--shadow-lift); }

/* --------------------------------------------------------------------------
   10. 橫幅與商品輪播的細節
   -------------------------------------------------------------------------- */
.banner img { transition: transform 8s ease-out; }
.banner:hover img { transform: scale(1.03); }

.gallery-thumb { transition: border-color .25s ease, transform .25s ease; }
.gallery-thumb:hover { transform: translateY(-2px); }
.gallery-arrow { transition: background-color .2s ease, transform .2s ease; }
.gallery-arrow:hover { transform: translateY(-50%) scale(1.08); }

/* --------------------------------------------------------------------------
   11. 提示訊息滑入
   -------------------------------------------------------------------------- */
.js-on .messages li { animation: rise-in .5s cubic-bezier(.22, .61, .36, 1) backwards; }

/* ==========================================================================
   總開關:使用者說了不要動,就真的不要動

   `!important` 在這裡是正確的用法——這一段的目的就是要壓過上面所有的動畫宣告,
   而且要壓過未來新增的。動畫時間設成 0.01ms 而不是 0 是慣例:有些瀏覽器在
   duration 為 0 時不會送出 animationend 事件,靠那個事件收尾的程式會卡住。
   ========================================================================== */
@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: .01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .01ms !important;
    scroll-behavior: auto !important;
  }
  .js-on [data-reveal] { opacity: 1 !important; transform: none !important; }
  .js-on img[data-fade] { opacity: 1 !important; }
  .hero::before, .hero::after { animation: none !important; }
  .hero h1 {
    /* 光掃過是靠背景位移做的,關掉動畫會停在某個中間位置、字變成一半金一半黑。
       所以這裡要把整個漸層文字還原成單色,而不是只停掉動畫。 */
    background: none !important;
    color: var(--ink) !important;
  }
}
