/* cut1 開場動畫。原型在 scratchpad/gift-anim，接線時整份加上 .screen--intro 前綴：
   原型的 class 名很通用（.layer／.gift／.qmark／.balloon／#stage），不加前綴會外溢到其他畫面。
   @keyframes 內容不動。動畫時間軸與可調參數在 js/gift-anim.js。 */
/* 賀卡開場動畫 原型樣式
   座標單位＝設計單位（720×1280），由 stage.css + stage-fit.js 整體等比縮放。
   動畫只碰 transform / opacity；版面位置一律 left/top 寫死不動畫。 */

/* 版面座標全部量自設計稿（scratchpad 的 2.webp）：
   以「滿版寬＝設計單位 720」為基準求出設計稿的像素比例（827.8px / 720 = 1.1497 px/單位），
   再用 logo 帶裡「Tednology」字樣的上下緣定出垂直原點，然後把 gift.webp / moon.webp
   縮到同一比例，在設計稿上滑動求最小平均色差（alpha>230 的像素）得到落點。
     禮物盒：left 0、top 506（誤差 2.5/255；原本 600 → 低了 94）
     月亮　：left 89、top 235、584×500＝素材原尺寸 1169×1001 的一半（原本 552×473 縮太小） */
.screen--intro {
  background: #8b87d4;   /* 背景圖載入前的底色，避免白閃 */
  --gift-top: 506px;

  /* ── 盒口（掀蓋後看到的開口）的四個頂點 ──────────────────────────────
     座標系＝設計單位，原點是 .gift / .gift-inner / .gift-lid-wrap 這三層的左上角
     （它們 left:0、top: var(--gift-top)，所以舞台座標 = 這裡的 y + var(--gift-top)）。
     刻意寫成不帶單位的數字：JS 可以 parseFloat 直接拿去算，CSS 這邊用 calc(... * 1px)。
     開口在幾何上只有四個頂點，四條邊全是直線，中間不准再插點（插了就是下面那種鋸齒）。

       left  ─ 盒子最左上角＝遠緣左段 ∩ 近緣左段
       far   ─ 遠緣頂點（盒子後緣在透視中最高的那點，被蝴蝶結擋住，由兩段外插求交點）
       right ─ 盒子最右上角＝遠緣右段 ∩ 近緣右段
       near  ─ 近緣 V 尖（盒蓋接縫最低點），與 .gift-body 的切線頂點同一點

     量法（2026-09-21 重量，腳本走 assets/src/cut1/gift@2x.png，1441px 寬＝設計 720）：
       遠緣：逐欄取 alpha 50% 的上輪廓做次像素定位，避開蝴蝶結佔住的 @2x x 365–1072，
             左段 x 240–360、右段 x 1080–1200 各自最小平方擬合直線（殘差 ≤0.18／0.49 @2x px），
             兩線交點＝ far。右段再往右到 @2x x≈1222 才開始倒角，所以 right 落在直線段上。
       近緣：沿 y 做高通（lum − 高斯模糊）取亮脊，避開緞帶欄位，左段擬合殘差 ≤0.9 @2x px，
             斜率 0.12838 對上 .gift-body 的 0.12796（差 0.3%）；右段被緞帶與右輪廓夾殺量不準，
             因此近緣一律採用 .gift-body 已經在用的那兩條線——開口與盒身本來就必須是同一條邊。
       遠緣的兩條線再整體往下讓 0.6px 才寫進下面：0.25 是「列索引 → 像素中心」的半格，
             0.35 是安全內縮。Chrome 把素材縮到 720px 寬時邊緣會再糊掉半格，不讓的話
             開口的反鋸齒邊會壓在盒子輪廓外面（量過：不讓＝整條邊外凸 0.43px，讓了＝內縮 0.08px）。*/
  --mouth-left-x: 120.3;    --mouth-left-y: 150.4;
  --mouth-far-x: 367.3;     --mouth-far-y: 119;
  --mouth-right-x: 605.1;   --mouth-right-y: 146;
  --mouth-near-x: 422;      --mouth-near-y: 189;

  /* 盒口的內框（＝真正的洞）。外框往內縮：遠緣 7.1px、近緣 13px（見 .gift-inner::after）。
     四個角是「外框兩條邊各自平移後的交點」，所以每條邊的厚度沿著邊固定不變
     （量過：遠緣 7.02～7.13px、近緣 12.98～13.04px，整條邊的寬窄差不到 0.1px）。 */
  --mouth-in-left: 199.1px 147.5px;
  --mouth-in-far: 367.3px 126.1px;
  --mouth-in-right: 547.5px 146.5px;
  --mouth-in-near: 422px 176px;

  /* 上面四個頂點的 px 版本，給 clip-path 直接用（改數值只改上面那四組，這裡自動跟著走） */
  --mouth-left: calc(var(--mouth-left-x) * 1px) calc(var(--mouth-left-y) * 1px);
  --mouth-far: calc(var(--mouth-far-x) * 1px) calc(var(--mouth-far-y) * 1px);
  --mouth-right: calc(var(--mouth-right-x) * 1px) calc(var(--mouth-right-y) * 1px);
  --mouth-near: calc(var(--mouth-near-x) * 1px) calc(var(--mouth-near-y) * 1px);
  /* 近緣再往下壓這麼多與盒身重疊，避免兩個 clip-path 的反鋸齒邊對接時透出一條背景。
     壓的是 V 尖；左右兩個角本來就落在 .gift-body 的切線上，重疊量從 0 線性長到這個值。 */
  --mouth-overlap: 10;
  --mouth-near-lap: calc(var(--mouth-near-x) * 1px)
                    calc((var(--mouth-near-y) + var(--mouth-overlap)) * 1px);
}

.screen--intro .layer {
  position: absolute;
  display: block;
  pointer-events: none;
  user-select: none;
  -webkit-user-drag: none;
}

/* ── 靜態層：不加 transform / will-change，維持在一般繪製層 ── */
.screen--intro .bg { left: 0;    top: 0;   width: 720px; height: 1280px; z-index: 0; }
/* 月亮素材的身體下緣是硬切的（灰色角色 y≈498、黃色角色 y≈462，素材內座標）。
   設計稿裡那條切邊本來就被禮物盒擋住，所以不要用遮罩淡出去補——照設計稿擺位，讓盒子真的蓋住它。
   量過：切邊落在畫面 y 697／732.5，盒身在那兩條 y 的不透明範圍是 x 101.5～617.5，
   而切邊只出現在 x 174～294 與 474～604，整段都在盒身後面。 */
.screen--intro .moon { left: 89px; top: 235px; width: 584px; height: 500px; z-index: 2; }
.screen--intro .logo { left: 0;    top: 0;   width: 720px; height: 96px;  z-index: 8; }

/* 由後往前的疊層（改動 z-index 前先看這張表）：
     0 .bg ─ 1 .balloon-layer.far ─ 2 .moon ─ 3 .gift-inner ─ 4 .gift-lid-wrap
     5 .balloon-layer.near ─ 6 .gift（盒身）─ 7 .qmark-layer ─ 8 .logo
     9 .band--bottom（頁尾白帶，規則在本檔最後）─ 10 .skip-hit
   關鍵是 4 < 5 < 6：氣球從盒身（6）後面升起，卻從盒蓋（4）前面飛過，
   才會是「從盒子裡跑出來」而不是「貼在盒子前面」，也不會被蓋子壓住。
   這張表由 tests/e2e/intro-layers.spec.mjs 的 T-50 逐項驗，改了要一起改。 */

/* ── 盒子內部（掀蓋後看到的開口）──
   素材裡沒有盒子內部的像素（本來被蓋子蓋住），整個開口是畫出來的。
   形狀＝盒蓋頂面那塊四邊形，四個頂點在 .screen--intro 上（--mouth-*，量法寫在那裡）。
   打光照真實情況分三段：遠側盒壁的頂面（::before）、看進去的洞（這一層的底色漸層）、
   近側盒壁的頂面 lip（::after），不是一塊平的深色。

   三層拼起來就是一個「相框」：外框＝ left→far→right→near 四個頂點，
   內框＝ --mouth-in-*（洞）。::before 與 ::after 各佔相框的遠半與近半，
   接在左右兩角與內框角的連線上（斜接，像相框的 45° 接角）——
   所以整個開口只有八個座標，邊與邊之間沒有任何多餘的中間點。

   ⚠ 2026-09-21 修：原本三個 clip-path 在每條邊中間都插了 2～4 個點
   （近緣 594,158 → 500,180 → 422,199 → 300,183 → 200,171 → 128,160 之類），
   而且 ::after 的內外兩條邊在 x=200／500 各有一個折角、::before 兩端是平頭不收尖，
   使用者回報「箱子的開口沒有切得很方正，看起來還是亂亂的」就是這些多餘的點。 */
.screen--intro .gift-inner {
  position: absolute;
  left: 0; top: var(--gift-top, 506px);
  width: 720px; height: 604px;
  z-index: 3;
  opacity: 0;
  pointer-events: none;
  transform-origin: 360px 510px;   /* 與 .gift 相同，開盒的預備擠壓要兩層同步（見 js/gift-anim.js） */
  /* 色階用 px，對齊開口實際落在的 y 範圍（119～199）。
     方向是有道理的：從遠緣往內看，視線先打到遠側內壁的最上緣（受光最多），愈往下愈深愈暗；
     開口左右兩個尖端剛好落在漸層的暗端，也就是看進去最深的地方。 */
  background: linear-gradient(to bottom,
    #8a7dc0 116px, #665aa2 130px, #453b78 148px,
    #2b2354 168px, #181233 188px, #0f0a22 202px);
  /* 外框本人：左角 → 遠緣頂點 → 右角 → 近緣 V 尖，四點四直邊。
     近緣那一點往下壓 --mouth-overlap 與盒身重疊；左右兩角不壓，它們本來就在 .gift-body
     的切線上，壓了反而會戳出盒子輪廓外面。重疊量因此從角上的 0 線性長到 V 尖的 10px。 */
  clip-path: polygon(
    var(--mouth-left), var(--mouth-far), var(--mouth-right), var(--mouth-near-lap)
  );
}
/* 遠側盒壁的頂面：沒有它就看不出「有厚度的盒子」。
   厚度 7.1px，不是隨便給的：把頂面當成一個正方形，用四個頂點解出平面的 homography，
   近緣 lip 取 13px（下面 ::after，原本就調到這個值）反推同一圈盒壁在遠緣的投影厚度，
   量到遠／近的透視壓縮比是 1.82，13 ÷ 1.82 = 7.1。亮度也比近側低一階，它離光源與鏡頭都更遠。 */
.screen--intro .gift-inner::before {
  content: '';
  position: absolute;
  left: 0; top: 0; width: 720px; height: 604px;
  background: linear-gradient(to right,
    rgba(180,171,216,.94), rgba(219,214,244,.96) 45%, rgba(193,185,229,.94));
  /* 外緣走 left→far→right（＝盒子的遠側輪廓），內緣走回內框的同三點，
     兩端在左右角與內框角之間斜接。厚度沿著邊固定：內緣就是外緣兩條直線各自往下平移 7.1px，
     兩條平移線的交點 x 不變，所以內框的遠點與外框的遠點同一個 x（367.3）。 */
  clip-path: polygon(
    var(--mouth-left), var(--mouth-far), var(--mouth-right),
    var(--mouth-in-right), var(--mouth-in-far), var(--mouth-in-left)
  );
}
/* 近側盒壁的頂面（lip）：蓋子掀開後才看得到的一條白邊，沿著接縫往上 13px。
   這條是「盒子真的開了」最強的視覺線索，要比遠側亮，但仍暗於正面（它被掀起的蓋子擋掉一些光）。 */
.screen--intro .gift-inner::after {
  content: '';
  position: absolute;
  left: 0; top: 0; width: 720px; height: 604px;
  background: linear-gradient(to right,
    rgba(203,196,233,.96), rgba(240,237,252,.97) 46%, rgba(211,204,240,.96));
  /* 內緣走 left→內框左→內框近→內框右→right，外緣沿著接縫（＝.gift-body 的切線）走回來。
     內緣就是接縫那兩條直線各自往上平移 13px，交點 x 不變，所以內框的近點與 V 尖同一個 x（422）。
     兩端收在左右角上：接縫與遠緣就在那裡交會，再往外素材上沒有頂面，畫過去會凸出盒子輪廓。
     內框的左右兩角落在「開口高度剛好等於 7.1+13」的位置（x 196.7／549.2），
     lip 與遠側盒壁在那裡自然併成一個尖角，不需要也不可以再補中間點。 */
  clip-path: polygon(
    var(--mouth-left), var(--mouth-in-left), var(--mouth-in-near), var(--mouth-in-right),
    var(--mouth-right), var(--mouth-near-lap)
  );
}
/* 盒子裡透出來的一點光（氣球要冒出來了）。故意放在開口偏上，別把內壁的深度洗掉 */
.screen--intro .gift-inner .glow {
  position: absolute;
  left: 215px; top: 124px;
  width: 290px; height: 74px;
  border-radius: 50%;
  background: radial-gradient(ellipse at 50% 58%, rgba(255,248,220,.6), rgba(198,184,252,.22) 46%, rgba(198,184,252,0) 74%);
  opacity: 0;
}

/* ── 氣球層 ── */
.screen--intro .balloon-layer {
  position: absolute;
  left: 0; top: 0; width: 720px; height: 1280px;
  z-index: 5;
  pointer-events: none;
  /* 氣球的可見範圍＝「盒口遠緣以上的整片天空」∪「盒口四邊形」。
     形狀由 js/gift-anim.js 的 mouthClipPath() 依開口幾何算出來寫進 --balloon-clip，
     開口的四個頂點來自 .screen--intro 上的 --mouth-*（讀不到會自己退路），所以開口調形狀這裡不用改。
     整理之後邊界只有一條折線：左右兩角之間走近緣（V 形接縫），兩角以外走遠緣的延伸線。
     為什麼要這一條（盒身 z-index 6 本來就蓋得住近緣以下）：那是靠素材的不透明度，
     素材一換、邊緣變半透明就穿幫；這條讓「還沒升出來的部分」變成真的沒畫出來的幾何保證。
     升出遠緣之後多邊形上半是整個舞台＝完全不受限制，所以「從盒蓋前面飛過」那段不受影響。
     這是靜態 clip-path（設定一次就不動），不會每格重算；疊層次序也完全不受它影響。
     退路值是舊的裁切：盒身不透明的下緣在畫面 y 1016，再往下只剩半透明陰影，氣球線會穿幫。 */
  clip-path: var(--balloon-clip, inset(0 0 264px 0));
}
/* 遠景氣球放在月亮之後：一前一後才有景深，不是一整排貼在同一個平面 */
.screen--intro .balloon-layer.far { z-index: 1; }
/* 旋轉支點放在球體上（素材是球＋繩，球佔元素上緣約四成），不是整張圖的正中央。
   支點在球上，搖擺時球幾乎留在原地、繩子像尾巴掃過去——上升中的氣球本來就是球在前、繩在後拖；
   支點在圖中央（等於繩子中段）的話整支會像被人拿著搖，不像飄。
   擺角在 js/gift-anim.js 的 CONFIG.balloonTilt（8–18°）。兩者是一組的：
   支點決定「誰在掃」，角度決定「掃多遠」＝ sin(角度) × 0.8 元素高，量到 74–189px。
   支點別再往上調，20% 已經在球體上緣附近，再上去旋轉中心就跑出素材外了。 */
.screen--intro .balloon { position: absolute; will-change: transform; transform-origin: 50% 20%; }
.screen--intro .balloon img { display: block; width: 100%; height: auto; }

/* ── 禮物盒：同一張圖切成盒身 / 盒蓋 ──
   .gift（盒身）與 .gift-lid-wrap（盒蓋）是兩個獨立的層，中間夾著近景氣球層。
   兩層的 left/top/width/height 與 transform-origin 必須完全一樣，開盒的預備擠壓才會同步（見 js/gift-anim.js）。 */
.screen--intro .gift,
.screen--intro .gift-lid-wrap {
  position: absolute;
  left: 0; top: var(--gift-top, 506px);
  width: 720px; height: 604px;
  transform-origin: 360px 510px;   /* 擠壓時以盒底為支點（素材裡盒身落地在 y≈1020@2x） */
  pointer-events: none;
}
.screen--intro .gift { z-index: 6; }
/* perspective 掛在蓋子這一層：只有蓋子用 rotateX，盒身是平的。
   （原本掛在 .gift 上，蓋子搬出來之後要跟著搬，否則 rotateX 會變成正交投影、立體感消失） */
.screen--intro .gift-lid-wrap {
  z-index: 4;
  perspective: 1000px;
  perspective-origin: 50% 20%;
}
.screen--intro .gift img,
.screen--intro .gift-lid-wrap img {
  position: absolute;
  left: 0; top: 0;
  width: 720px; height: 604px;
  display: block;
  -webkit-user-drag: none;
}

/* 切線＝「頂面 ↔ 正面」那條真正的接縫，不是水平線。
   量法：把 gift@2x.png 每一欄沿 y 做高通（lum − 高斯模糊），接縫是一條亮脊，逐欄取最大值，
   再避開蝴蝶結緞帶與盒身緞帶干擾的欄位（@2x x 380–558、1016–1123）之後分兩段擬合直線：
     左段 (265,304)→(845,377)  斜率 +0.1259
     右段 (845,377)→(1175,300) 斜率 −0.2333
   交會的 V 尖在 @2x (845,377)，換算設計單位 (422,189)——原本寫成 (368,193)，
   位置偏左又偏高，掀蓋後開口才會缺一角。下面的座標全是 @2x ÷2。
   盒身／盒蓋用完全互補的兩個 clip-path：蓋著的時候會原樣拼回整張圖，不會有接縫。 */
.screen--intro .gift-body {
  clip-path: polygon(
    0 135px, 102px 148px, 200px 161px, 300px 173px, 422px 189px,
    500px 170px, 604px 146px, 720px 119px,
    720px 604px, 0 604px
  );
}
.screen--intro .gift-lid {
  clip-path: polygon(
    0 0, 720px 0, 720px 119px,
    604px 146px, 500px 170px, 422px 189px, 300px 173px, 200px 161px, 102px 148px, 0 135px
  );
  transform-origin: 360px 178px;   /* 支點放在接縫上（x=360 的接縫 y≈178） */
  will-change: transform;
}
/* 陰影只在蓋子離開盒身後才加：蓋著的時候 drop-shadow 會沿著切線描出一條硬邊 */
.screen--intro .gift-lid.is-lifted { filter: drop-shadow(0 10px 14px rgba(32, 22, 66, .38)); }

/* ── 問號層 ── */
.screen--intro .qmark-layer {
  position: absolute;
  left: 0; top: 0; width: 720px; height: 1280px;
  z-index: 7;
  pointer-events: none;
}
.screen--intro .qmark { position: absolute; transform: translate(-50%, -50%); }
.screen--intro .qmark-float { display: block; will-change: transform; }
.screen--intro .qmark img {
  display: block;
  width: var(--qw, 52px);
  height: auto;
  opacity: 0;              /* 由 JS 逐顆彈出 */
  will-change: transform, opacity;
  filter: drop-shadow(0 2px 6px rgba(40, 30, 90, .35));
}

/* ── 點擊熱區（透明，蓋滿舞台）── */
.screen--intro .skip-hit {
  position: absolute;
  left: 0; top: 0; width: 720px; height: 1280px;
  z-index: 10;
  border: 0; padding: 0; margin: 0;
  background: transparent;
  appearance: none;
  cursor: pointer;
}
.screen--intro .skip-hit:focus-visible { outline: 3px solid #fff; outline-offset: -6px; }

/* ── 結束狀態（動畫跑完或 reduced-motion 直接跳到這裡）──
   .is-open 只負責「靜態的最終樣子」，JS 的動畫用 fill: 'forwards' 疊在上面。 */
.screen--intro.is-open .gift-inner { opacity: 1; }
.screen--intro.is-open .gift-inner .glow { opacity: .34; }
/* 停位要抬得夠高：開口在 V 尖最深 70px（接縫 189 − 遠緣 119），抬 60px 再加上 −9.5° 的旋轉，
   V 尖附近正好整個露出來；原本只抬 34px，開口只露一半，看起來像沒打開。 */
.screen--intro.is-open .gift-lid { transform: translate3d(36px, -60px, 0) rotate(-9.5deg); filter: drop-shadow(0 12px 16px rgba(32, 22, 66, .42)); }
.screen--intro.is-open .qmark img { opacity: 0; }

/* ── 減少動態：直接呈現結束狀態，完全不播動畫 ── */
@media (prefers-reduced-motion: reduce) {
  .screen--intro .gift-lid, .screen--intro .gift-lid-wrap, .screen--intro .gift, .screen--intro .qmark img, .screen--intro .qmark-float, .screen--intro .balloon, .screen--intro .gift-inner, .screen--intro .gift-inner .glow {
    animation: none !important;
    transition: none !important;
    will-change: auto;
  }
  .screen--intro .balloon-layer { display: none; }
}


/* ── 頁尾白帶（2026-09-21 補）───────────────────────────────────────────
   使用者回報 cut1 底部少了跟其他頁一樣的頁尾。設計稿 p-1 與 p-2 的底部 100 列逐像素相同
   （白帶起於 y1211、高 69.5，文字 1233–1257），簡報 P7 的 cut1 手機圖換算後也是同一組值，
   所以直接用 cut2 的共用元件 .band--bottom／.band__footer（版面數值在 css/screens.css），
   這裡只覆寫它在開場動畫這一層要站的位置。

   z-index 9：必須壓在近景氣球(5)與盒身(6)之上，否則氣球升到畫面下緣時會飛到白帶上面、蓋掉文字；
     放在 logo 條(8)與 .skip-hit(10) 之間，上下兩條白帶就都在場景之上、熱區仍然在最上面。
   pointer-events: none：.skip-hit 是整頁的跳過熱區。它 z-index 比較高，本來就收得到這塊的點擊，
     但白帶不吃事件才是真的保證——將來 .skip-hit 若縮小或換成別的元素，這裡不會變成一塊死區。 */
.screen--intro .band--bottom { z-index: 9; pointer-events: none; }
/* logo 素材的白底邊緣是半透明的（alpha 最低 32），直接貼在紫色背景上時最上面那一列會透出紫。
   cut2 的 .band--top 有一塊白底擋著，cut1 沒有——補一塊同樣的白底，兩頁的頁首才會一致。 */
.screen--intro .logo { background: #fff; }
