/* ═══════════════════════════════════════════════════════════════════════════
   index2.html 的頁面樣式（原本寫在 <head> 的 <style> 與幾支小 CSS，2026-09-25 整理成這一支）
   段落順序＝原本的層疊順序，不要任意調換：
     1. 基底：token、reset、body、Lenis、跳到內容連結
     2. 地球段（.pulse-band）的開窗骨架 —— 內容樣式在 css/global-footprint.css
     3. 第一塊 KV（banner、3D 閃電 LOGO）＋ 第二塊圓盤（同心圓、儀表、照片扇形、中央軸線閃電）
     4. LOGO 開窗（js/index2-brand-reveal.js）
     5. KV 字體
     6. 動態暫停（分頁不在前景、減少動態）
   其他段：css/global-footprint.css（地球）、css/index2-solutions.css（SOLUTIONS 父頁這側）、
           css/site-nav.css（頂端選單）；SOLUTIONS 畫面本身在 iframe（css/line-solutions.css）。
   ═══════════════════════════════════════════════════════════════════════════ */

/* ── 1. 基底 ─────────────────────────────────────────────────────────────── */
:root {
    --bg-light: #f8fafc;
    --text-dark: #0f172a;
    /* 原本 index2-studio.css 在後面把它改成這一組（實際生效的值），整理時直接寫成這樣 */
    --font-main: 'Jost', 'Noto Sans TC', sans-serif;
}
* {
    box-sizing: border-box;
    margin: 0;
    padding: 0;
}
body {
    font-family: var(--font-main);
    background-color: var(--bg-light);
    color: var(--text-dark);
    overflow-x: hidden;
    min-height: 100vh;
    display: flex;
    flex-direction: column;
    -webkit-font-smoothing: antialiased;
}

/* Lenis（js/index2-scroll-runtime.js）與無障礙小工具 */
html.lenis, html.lenis body { height: auto; }
.lenis.lenis-smooth { scroll-behavior: auto !important; }
.lenis.lenis-stopped { overflow: hidden; }
.lenis.lenis-smooth [data-lenis-prevent] { overscroll-behavior: contain; }
.studio-main { display: block; flex: 0 0 auto; width: 100%; min-width: 0; }
.studio-sr-only { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0,0,0,0); white-space: nowrap; border: 0; }
.studio-skip { position: fixed; left: 20px; top: 16px; z-index: 1001; padding: 12px 18px; background: #fff; color: #222; transform: translateY(-180%); font: 500 14px/1.4 'Jost','Noto Sans TC',sans-serif; }
.studio-skip:focus { transform: none; }
.studio-skip:focus-visible { outline: 2px solid #76c5af; outline-offset: 3px; }
@media print { .studio-skip { display: none; } }

/* ── 2. 地球段的開窗骨架 ＋ 3. KV・第二塊圓盤 ────────────────────────────────── */
/* ── 地球過場 .pulse-band（2026-09-25 起是 Global Footprint）──────
   內容、樣式、動態都在 css/global-footprint.css ／ js/global-footprint.js ／
   js/global-footprint.config.js；這裡只留開窗機制需要的骨架（sticky／fixed／z-index）。 */
.pulse-band {
    position: relative;
    /* 高度由 css/global-footprint.css 的 --gf-length 決定（最後 100vh 固定留給交棒） */
    height: 340vh;
    /* ⚠ 這裡不能設 z-index：band 一旦成為堆疊脈絡，內層開洞時的
       z-5 會被困在 z-3 裡，整體壓在儀表（z-4）底下 ——
       圓點就蓋不掉弧線／小地球／文字圈（實際踩過）。
       下一段 .line-track 是 z-0 的堆疊脈絡，交棒時才升到 z-2（css/index2-solutions.css）。 */
    /* 這段沒有可互動元素；收成圓點後別擋住底下場景的滑鼠 */
    pointer-events: none;
    /* 底色掛在 inner（被 clip 的那層）：band 本體必須透明，
       圓點收場時圓外才看得到底下滑入的 3D 場景 */
    background: transparent;
}
.pulse-inner {
    /* sticky：交棒（開窗的 fixed 解除）後無縫接手釘住 —— 兩者在交棒點
       的視覺位置相同。釘到跑道走完（band 底到視窗底）才放行。 */
    position: sticky;
    top: 0;
    /* 平常 z-1（壓在下一段 .line-track 的 z-0 脈絡上）；開洞時 .is-revealing
       會覆寫成 z-5（壓過儀表 z-4） */
    z-index: 1;
    display: flex;
    align-items: center;
    justify-content: center;
    height: 100vh;
    /* 底色要掛在這一層：開窗時被裁成圓形露出來的是它 */
    background: #f1f0ec;
    overflow: hidden;
}

/* ══ 以下移植自 3d-logo5.before-restore-20260723-2140.html 的前兩塊 ══
   來源 CSS：39-50（:root 五顆 token）、305-1158（.kv / .story / .stat-*）、
   1595-1597 與 1631-1848（兩段 RWD）。
   來源的 51-302 是 header/nav 外框，刻意不取 —— 那是兩檔唯一的
   class 撞名（.site-header）來源，不取就整組問題消失。
   --en / --tc 改名為 --rp-en / --rp-tc，避免與本頁變數混淆。 */
.kv {
    --green: #12a15b;
    --ink: #070707;
    --paper: #fff;
    --soft: #f5f5f5;
    --carbon: #0f1211;
    --line: rgba(7, 7, 7, .14);
    --gutter: clamp(20px, 4.27vw, 82px);
    --radius: 8px;
    /* ── 毛玻璃（影片淡到第二區塊時掛上，見 JS 的 KV_VIDEO_BLUR）──
       --kv-blur   高斯標準差的最大值（就是 blur() 括號裡那個數）
       --kv-bleed  影片往四邊多長出來的量，規則：必須 ≥ 3 × --kv-blur。
                   blur 會採樣到元素邊界外（那裡是空的），四邊會長出寬約 3σ
                   的透明軟邊；把元素本身長大 3σ，軟邊就落在 .kv 的
                   overflow: clip 之外看不到。兩個值要一起改。
                   外擴用固定 px 而不是 scale：scale 的外擴量跟視窗尺寸綁死，
                   手機上要放到 1.28 才夠，構圖整個變掉。 */
    --kv-blur: 16px;
    --kv-bleed: 48px;
    --rp-en: 'Jost', 'Pretendard Variable', 'Pretendard', sans-serif;
    --rp-tc: 'Jost', 'Pretendard Variable', 'Noto Sans TC', sans-serif;
}
/* ── Banner 捲動跑道 ──────────────────────────────────────
   做法對齊 officework.skgh.jp：影片固定在底，往下捲時先停留，
   內容最後才蓋上來。.kv 本體 sticky 釘在視窗裡，外層 .kv-track
   撐出 300vh —— 前 200vh 的捲動影片都還在畫面上。
   3D 閃電的拆解、下墜、收攏，以及接下來「圓點開窗露出 3D 場站」
   全部壓在這段跑道內完成（見 kvExit / revealTl 與頁尾模組的
   measureMotion）。第二區塊已移除，banner 直接接場站導覽。 */
.kv-track {
    position: relative;
    z-index: 2;
    height: 300vh;
}
@media (max-width: 1024px) {
    .kv-track {
        height: 240vh;
    }
    /* 模糊成本由全視窗像素數決定，行動 GPU 的 fill rate 便宜不了；
       而且螢幕小、影片本來就看不清楚，σ 不需要那麼大。
       bleed 一定要跟著降（維持 ≥ 3σ 的關係），不然邊緣會露白。 */
    .kv {
        --kv-blur: 10px;
        --kv-bleed: 30px;
    }
}
.kv {
    position: sticky;
    top: 0;
    z-index: 2;
    width: 100%;
    height: 100svh;
    /* 防跑版：原本有 min-height: 680px（≤700 寬是 700px）。視窗比它矮時（筆電縮小的視窗、
       手機的可視高度多半 < 700）.kv 比視窗高 → sticky 釘不住、開洞前整塊往上滑，
       開洞那一刻又被 position:fixed 拉回頂端 —— 畫面跳一下（實測 390 高時跳 145px）。
       現在永遠等於視窗高；文案與 LOGO 的空間由 CSS clamp 與 hero3d 的 layoutLogo 處理。 */
    /* clip 比 hidden 好：不會生出捲動容器，也不會把子層的
       position: fixed（3D LOGO 畫布）綁進來 */
    overflow: clip;
    color: #c9ccce;
    /* 影片的底色：#71c4d4 → #c4e7bc 青→綠漸層（使用者指定）。影片在閃電階段
       壓到 .5 透明度時，透出來的就是這層；影片沒載入時也是它。 */
    /* background: linear-gradient(90deg, #71c4d4 0%, #c4e7bc 100%); */
    /* 影片淡掉之後露出的「地」：圓形區是全白文字／線條，地要有顏色白才看得見。
       改用 #5fb6c8（比原本的 #71c4d4 深一階）：毛玻璃的乳白層（.kv-tint）
       在第二區塊會疊上 .2 的白，複合回 ≈ #7fc4d3 —— 也就是原本那個青，
       白字對比一格都沒少。沒有乳白層時（頂端、窄版）則比以前深，白字更跳。 */
    background: #000000;
}
/* Banner 遮罩：用第二區塊（.story-sticky）那組網狀漸層蓋上來。
   漸層必須逐字相同，交界處才會無縫 —— 差一點色階就看得到邊。
   掛在 .kv 底下但在 .kv-parallax 之外：位移層被抽走時它不跟著動，
   露出來的正好是下一段的底色。 */
.kv-veil {
    position: absolute;
    inset: 0;
    /* 3：壓在影片（無 z-index）之上、文字與面板（z-4）之下。
       設 6 會連字標一起蓋掉，那不是遮罩是整面貼紙。 */
    z-index: 3;
    pointer-events: none;
    opacity: 0;
    /* will-change 拿掉（2026-09-27 效能）：這層的淡入已停用（js 的 matchMedia 'not all'），常駐合成層只是白佔一張全螢幕 */
    /* 第二塊改成白底型錄風，遮罩／底色跟著換才無縫 */
    background: #fbfcfd;
}
/* 差速視差：這一層被 GSAP 綁 translateY，速度比捲動快且會加速。
   will-change 讓它獨立成合成層，位移全程只做合成不觸發重繪。 */
.kv-parallax {
    position: absolute;
    inset: 0;
    will-change: transform;
}
/* .kv-media 由 js 依捲動縮放（影片的進退）：transform-origin 置中、自成合成層 */
.kv-media { transform-origin: 50% 50%; will-change: transform; }
.kv-media,
.kv-media::after,
.kv-video {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
}
/* 影片原樣播：原本的 opacity .78 與去飽和／降對比 filter 是為了讓
   BESS 去背圖退到背景，換成影片之後不需要 */
.kv-video {
    object-fit: cover;
    /* 透明度一開始是 1（使用者要求）。
       rotate(.001deg)：讓影片不被 Windows Chrome 升成硬體疊加層（overlay 只接受
       軸對齊、完全不透明的圖層）—— 升成 overlay 後，疊在影片上方的固定圖層
       （同心圓文字、色罩）在部分顯示驅動上會整個不畫或閃爍。千分之一度肉眼看不出來。 */
    transform: scale(1.025) rotate(.001deg);
    opacity: 1;
    /* 毛玻璃的外擴（理由與換算見 .kv 的 --kv-bleed）：全程都掛著、不跟著
       模糊變動 —— 邊界一變動合成器就要重配貼圖，而且模糊變大的那一瞬間
       若 bleed 還沒跟上，四邊會閃出一圈軟邊。
       這三行覆蓋上面群組規則的 inset/width/height（同特異性、寫在後面）。 */
    inset: calc(var(--kv-bleed) * -1);
    width: calc(100% + var(--kv-bleed) * 2);
    height: calc(100% + var(--kv-bleed) * 2);
    /* 這裡刻意「沒有」filter 宣告。連 blur(0px) 都不能寫 —— 只要 filter 不是
       none，<video> 就永久走離屏 filter surface、失去硬體疊加快路徑，
       連跑道最上方影片最該清晰的那一整段也要每個解碼影格重新光柵化。
       毛玻璃由 JS 在 .22 之後才 inline 掛上、捲回頂端再清掉（見 KV_VIDEO_BLUR）。 */
}
/* 影片層不做任何每幀會變的 transform（曾試過綁捲動的 dolly zoom）：
   <video> 的祖先一有動態 transform，Chrome 就會把影片踢出硬體疊加路徑，
   捲動時整段閃爍。要「推進感」一律做在不含影片的圖層（暗角、同心圓、洞口）。 */
/* 毛玻璃的「乳白散射層」：光靠 blur 只會得到一支失焦的影片，讓它讀成「玻璃」
   的是這層半透明白。原本是藍綠色罩、opacity 一直掛 0、全檔沒有任何 JS 讀它，
   徵用不會撞到任何動畫。z-2 的位置剛好：影片之上、veil/dim/文字之下。
   起點 0：banner 開頭要影片原色（使用者要求）；由 JS 跟著模糊一起淡到
   KV_GLASS_TINT（見 KV_VIDEO_BLUR 那段）。濃淡改那個常數，不要改這裡。 */
.kv-tint {
    position: absolute;
    inset: 0;
    z-index: 2;
    pointer-events: none;
    /* 冷白 → 帶一點品牌綠的白，方向沿用原本的 135deg：
       玻璃有色溫變化才不會是死白，也還在原本青→綠的品牌軸上。 */
    background: linear-gradient(135deg, #ffffff 0%, #eaf7fa 46%, #e4f2df 100%);
    opacity: 0;
    /* will-change 拿掉（2026-09-27 效能）：LOGO 開窗時 css 把它鎖在 opacity 0（見 has-index2-brand-reveal），常駐合成層白佔一張全螢幕 */
}
/* 暗角：洞開時壓暗四周，把視線收到洞口；只動 opacity */
.kv-dim {
    position: absolute;
    inset: 0;
    z-index: 3;
    pointer-events: none;
    opacity: 0;
    /* 青色地上的暗角：適度聚焦到洞口 */
    background: radial-gradient(circle at 50% 50%,
            rgba(4, 9, 16, 0) 30%,
            rgba(4, 9, 16, .22) 64%,
            rgba(4, 9, 16, .42) 100%);
    will-change: opacity;
}
/* 換成影片之後不壓暗，規則保留但關掉 */
.kv-media::after {
    display: none;
    content: '';
    z-index: 2;
    pointer-events: none;
    background: linear-gradient(180deg,
            transparent 76%,
            rgba(255, 255, 255, .16) 84%,
            rgba(255, 255, 255, .72) 94%,
            #fff 100%);
}
.kv-orbit {
    position: absolute;
    top: 49%;
    left: 51%;
    width: min(42vw, 650px);
    aspect-ratio: 1;
    border: 1px solid rgba(228, 255, 237, .22);
    border-radius: 50%;
    background:
        radial-gradient(circle, rgba(0, 255, 112, .1), transparent 54%),
        repeating-radial-gradient(circle, transparent 0 19%, rgba(225, 255, 236, .055) 19.2% 19.5%, transparent 19.8% 34%);
    box-shadow: inset 0 0 110px rgba(0, 255, 112, .045);
    transform: translate(-50%, -50%);
    pointer-events: none;
}
.kv-title-cluster {
    position: absolute;
    top: 24%;
    left: var(--gutter);
    z-index: 4;
    width: min(34vw, 560px);
}
.kv-eyebrow {
    position: static;
    display: flex;
    align-items: center;
    gap: 10px;
    margin: 0;
    font-family: var(--rp-en);
    font-size: 11px;
    font-weight: 650;
    letter-spacing: .11em;
    text-transform: uppercase;
}
.kv-eyebrow::before {
    content: '';
    width: 22px;
    height: 1px;
    background: currentColor;
}
.kv-ai-badge {
    display: inline-flex;
    align-items: center;
    min-height: 24px;
    padding: 4px 9px;
    border: 1px solid rgba(245, 255, 248, .32);
    border-radius: 999px;
    background: rgba(234, 242, 232, .13);
    font-family: var(--rp-en);
    font-size: 9px;
    font-weight: 700;
    letter-spacing: .06em;
    text-transform: uppercase;
    -webkit-backdrop-filter: blur(10px);
    backdrop-filter: blur(10px);
}
.kv-panel-status {
    top: 118px;
    right: var(--gutter);
    width: min(30vw, 430px);
    padding: 18px 18px 15px;
}
.kv-mini-grid {
    position: absolute;
    top: 305px;
    right: var(--gutter);
    z-index: 4;
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 10px;
    width: min(30vw, 430px);
}
.kv-panel-chart {
    bottom: 92px;
    left: var(--gutter);
    width: min(30vw, 430px);
    padding: 18px;
}
.kv-meta {
    display: flex;
    align-items: flex-end;
    justify-content: flex-end;
    gap: 24px;
    padding: 0;
    border: 0;
}
/* ── 圓形開窗：第二塊圓盤的中央開一個圓洞，露出下一段 Global Footprint（地球）──
   開窗期間地球段的內層（.pulse-inner）暫時 fixed 疊到 banner「上面」，用 clip-path: circle() 只露出圓形內
   （clip 字串由主腳本的 applyHole 每幀寫入）；.kv 也一起 fixed —— 它只 sticky 到跑道結束，
   不一起釘的話洞外的影片會跟著頁面往上滑。.kv 是 .kv-track 唯一的子節點、跑道高度寫死，
   抽出文流不改變任何量測值，ScrollTrigger 與 Lenis 都不必 resize。所有寬度都走這一套。
   為什麼是 clip-path 不是 mask：
     ・正在播放的 <video> 的祖先一旦掛 mask／clip 又每幀在換，Chrome 會把影片踢出硬體合成路徑；被裁的這層是一般 DOM。
     ・mask-image 的 radial-gradient 每幀都是新的 paint image，要丟給 raster 執行緒重畫，畫不及的那一幀
       合成器會先畫沒遮罩的圖層（「圓點打開一直閃」）；circle() 是幾何裁切，合成器直接算。 */
.pulse-inner.is-revealing {
    position: fixed;
    top: 0;
    left: 0;
    width: 100%;
    height: 100vh;
    /* 5：壓在同心圓（.kv-halo z-4）之上 —— 洞打開時直接把字蓋過去，
       字維持原尺寸不動；洞緣線（.kv-portal z-6）仍在最上面。 */
    z-index: 5;
}
/* 這個 class 由 3D Logo 淡出期提早掛上（原本用來預建 clip-path 的合成層，
   那時洞裡是 WebGL iframe）。現在洞裡是一般 DOM，這裡一定不能再做
   任何層提升 —— will-change: clip-path 會讓被裁層變成獨立合成層，
   裡面「有圓角裁切」的圖片就整塊不被光柵化（實測圖片會變空白）。
   規則留著當標記，不給任何屬性。 */
.pulse-inner.is-reveal-ready {
    /* intentionally empty：不要 will-change / backface-visibility / contain */
}
/* .kv 仍要釘住：它只 sticky 到跑道結束，之後會跟頁面往上跑，
   洞外露出的影片就會滑動。不掛任何 mask。 */
.kv.is-revealing {
    position: fixed;
    top: 0;
    left: 0;
    pointer-events: none;
}
/* 同心圓弧層：fixed 圖層，放在 body 層級（不能收在 .kv-track 裡 ——
   那是 z-index 2 的堆疊脈絡）。
   z-4：高於 banner(2)，低於開窗中的地球段（z-5）—— 洞打開時直接把
   圈與字蓋過去，字維持原尺寸。3D 閃電畫布（z-5）在圈出現後不久就淡掉了。
   .kv-track 捲出視野時由 IO 關閉 visibility。 */
.kv-halo {
    position: fixed;
    inset: 0;
    z-index: 4;
    display: flex;
    align-items: center;
    justify-content: center;
    pointer-events: none;
    opacity: 0;
}
/* 線框與環形文字整組內縮約 50px（使用者要求）：只縮 halo 這一層 ——
   照片扇形（.kv-wedges）與中央儀表（.kv-core）在別的層、不受影響。
   縮的是 wrapper（CSS transform），跟 JS 寫在 SVG 內部的推擠／旋轉互不干擾。 */
.kv-halo .ring-wrapper {
    transform: scale(var(--rk-halo-scale, .91));
    transform-origin: 50% 50%;
    /* 原本 soft-light（白字壓在影片上用）；影片淡到 .1、地改淺色後，改成一般合成、
       文字用深藍墨色 —— 淺地上 soft-light 的白字幾乎看不見。 */
    /* 不強制合成層（translateZ / will-change）：壓在硬體疊加的 <video> 上方時，
       強制合成的層在 Windows Chrome 有機會被影片蓋掉。交給瀏覽器自己決定。 */
}
/* ── 圓形區配色（淺色地・深藍墨線・品牌綠・萊姆強調）──────────────
   四個圖層共用；改這幾個變數就能整組換色。 */
.kv-halo,
.kv-core,
.kv-wedges,
.kv-portal {
    /* 全白版（使用者要「文字線條都要是白色」）：層次只靠透明度與字重。
       想要有色版：ink #46627f / green #3db483 / steel #8fb0cf（淡）或 #12304d / #12a15b / #4f7fb5（深）。 */
    --rk-ink: #fff;
    --rk-ink-rgb: 255, 255, 255;
    --rk-green: #fff;
    --rk-lime: #fff;
    --rk-steel: #fff;
}
/* 構圖細節層（JS 生成，見 buildDeco）：
   ・.ring-deco  四條虛線構圖軸、軸與輔助圓交點的節點、破弧色塊（靜態，只做視差）
   ・.ring-scale 方位刻度環（r=560：每 2° 短刻、10° 長刻、30° 數字）＋ 12 點的綠色指標，慢速自轉 */
.ring-deco .deco-axis {
    stroke: var(--rk-ink);
    stroke-opacity: .1;
    stroke-width: 1;
    stroke-dasharray: 2 6;
}
.ring-deco .deco-node {
    fill: var(--rk-ink);
    fill-opacity: .4;
}
.ring-deco .deco-node.is-hollow {
    fill: #fff;
    fill-opacity: 1;
    stroke: var(--rk-ink);
    stroke-opacity: .45;
    stroke-width: 1.2;
}
.ring-deco .deco-tone {
    fill: none;
    stroke: var(--rk-ink);
    stroke-opacity: .05;
}
.ring-deco .deco-tone.is-green {
    stroke: var(--rk-green);
    stroke-opacity: .3;
}
.ring-scale .scale-base {
    fill: none;
    stroke: var(--rk-ink);
    stroke-opacity: .28;
    stroke-width: 1;
    stroke-dasharray: 3 9;
}
.ring-scale line {
    stroke: var(--rk-ink);
    stroke-opacity: .3;
    stroke-width: .8;
}
.ring-scale line.is-major {
    stroke-opacity: .6;
    stroke-width: 1.2;
}
.ring-scale text {
    fill: var(--rk-ink);
    fill-opacity: .5;
    font-family: 'Jost', sans-serif;
    font-size: 9.5px;
    font-weight: 500;
    letter-spacing: 1px;
    text-anchor: middle;
}
.ring-scale .scale-index {
    fill: var(--rk-green);
}
/* 洞緣層：跟 .kv-halo 同尺寸、同圓心的另一張 fixed SVG，
   畫「洞口的發光邊」—— 一道細亮線＋一道寬而淡的光暈。
   不放進 .kv-halo：那層的 opacity 會在 1.05 淡掉，洞還要開到 1.5。
   半徑每幀由 applyHole 用 transform scale 同步到洞的像素半徑，
   線寬靠 non-scaling-stroke 鎖住。 */
.kv-portal {
    position: fixed;
    inset: 0;
    /* 放在 body 層級、壓在開窗中的地球段（z-5）之上，洞緣線永遠看得到 */
    z-index: 6;
    display: flex;
    align-items: center;
    justify-content: center;
    pointer-events: none;
    visibility: hidden;
    transform: translateZ(0);
}
/* 重整同步完成前只關閉繪製，不可用 display:none：SVG 必須保留尺寸與
   CTM，ScrollTrigger refresh 才能正確計算 svgOrigin 與線寬。 */
html.is-recharge-restoring .kv-halo,
html.is-recharge-restoring .kv-core,
html.is-recharge-restoring .kv-wedges,
html.is-recharge-restoring .kv-portal {
    visibility: hidden !important;
}
/* 影片的毛玻璃是 inline style（見 JS 的 KV_VIDEO_BLUR）。bfcache 回來時
   DOM 連 inline filter 一起被還原，而捲動已被 __rechargeReloading 拉回 0 ——
   這裡硬性清掉，不去賭 ScrollTrigger 的 onToggle 在還原那一幀一定會觸發。 */
html.is-recharge-restoring .kv-video {
    filter: none !important;
}
.kv-portal svg {
    width: 110vmax;
    height: 110vmax;
    overflow: visible;
    contain: paint;
}
/* 光暈（.kv-hole-glow）已拿掉：淺色地上看起來像陰影，只留細亮線 */
.kv-hole-rim {
    /* 白色 20% 的圓形底（使用者要求）：洞開多大這片就多大，
       露出來的地球段 隔著一層淡白，跟毛玻璃方向一致。
       fill 畫在單位圓上、隨 setRim 的 scale 一起長，不用另外同步。 */
    fill: #fff;
    fill-opacity: .2;
    stroke: var(--rk-ink, #12304d);
    stroke-linecap: round;
    stroke-width: 1.4;
    stroke-opacity: .55;
}
/* ── 同心圓（靜態 SVG，GSAP 驅動）──────────────────────────────
   固定大小的正方形容器置中，viewBox 1400×1400、圓心 (700,700)。
   四圈 textPath 重複字 ＋ 五道細線輔助圓 ＋ 儀表細節：刻度、輔助圓上的
   衛星點、中央準星、充能弧與 00→100 計數。
   所有動態（進場、scrub 旋轉、捲動速度慣性、光帶、洞口推擠）都做在
   SVG 內部 <g> 的屬性變形上，不在 HTML 元素掛 CSS transform ——
   壓在硬體疊加 <video> 上的強制合成層在 Windows Chrome 會被影片蓋掉
   （見 .kv-halo 註解）。
   分層：.ring-stage（洞口推擠）> .ring-group（scrub 旋轉）
         > .ring-dyn（捲動速度慣性）> .text-ring（進場落定）。 */
/* 整組圓形（照片扇形 .kv-wedges ／ 同心圓 .kv-halo ／ 中央儀表 .kv-core）
   共用這個尺寸框 —— 改這裡就是整組等比縮放。
   ⚠ 原本寫 186vmin，但三個父層都是 display:flex 且寬只有 100vw，
   橫式視窗下 186vmin 一定溢出 → flex-shrink 把寬壓回 100vw，
   SVG 又是 meet 貼合，實際直徑等於 min(186vmin, 100vw) ＝ 幾乎永遠是 100vw。
   所以「縮 20%」不能只把 186 改成 148.8（那只縮了 7%），
   要對「實際生效值」打八折：min(186vmin, 100vw) × .8 ＝ min(148.8vmin, 80vw)。
   flex-shrink:0 讓這個值不再被父層二次壓縮。 */
.ring-wrapper {
    position: relative;
    flex-shrink: 0;
    /* 尺寸由調參面板的變數控制（預設 148.8vmin／80vw，跟原本一樣） */
    width: min(calc(var(--rk-size-vmin, 148.8) * 1vmin), calc(var(--rk-size-vw, 80) * 1vw));
    height: min(calc(var(--rk-size-vmin, 148.8) * 1vmin), calc(var(--rk-size-vw, 80) * 1vw));
    display: flex;
    justify-content: center;
    align-items: center;
}
.ring-wrapper svg {
    position: absolute;
    width: 100%;
    height: 100%;
    overflow: visible;
}
/* 同心圓文字：全大寫、Poppins，用字重＋透明度做層次。
   fill 接 <defs> 裡的線性漸層（userSpaceOnUse）：JS 每幀把漸層反向旋轉、
   抵銷該圈自己的旋轉，讓一道「光帶」固定在螢幕空間、隨捲動掃過四圈 ——
   像金屬錶盤上的反光。url() 後面是沒有漸層時的後備色。
   ── 要改字級就改下面四條的 font-size（r1 最外圈 → r4 最內圈）──
   單位是 SVG user unit（viewBox 1400），實際大小 ＝ font-size ÷ 1400 × 圓框直徑，
   會跟著視窗等比縮放。
   注意：字距不是 letter-spacing，是 <textPath> 的 textLength 把整句均分撐滿整圈，
   所以字級改小字距會變鬆 —— 要維持密度就把該圈 <textPath> 的句子加長。 */
.text-ring {
    fill: rgba(255, 255, 255, .92);
    text-transform: uppercase;
    font-family: 'Jost', sans-serif;
}
.text-ring.r1 {
    font-weight: 500;
    font-size: 60px;
    fill: url(#ring-sheen-1) #fff;
    /* 透明度：進場 GSAP 動的是 opacity，這裡用 fill-opacity 疊乘，才不會被覆寫 */
    fill-opacity: .5;
}
/* 只留兩圈：外圈白色品牌句、內圈綠色關鍵字（原本四圈，中間與最內圈文字太滿已拿掉；
   空出的 250–430 環帶給長條群與照片扇形呼吸）。 */
.text-ring.r2 {
    font-weight: 500;
    font-size: 20px;
    fill: url(#ring-sheen-2) #fff;
}
/* 輔助圓：pathLength="1" 讓 dasharray / dashoffset 用 0–1 表示，
   進場時 haloTl 把 dashoffset 由 1 → 0，線條從 12 點方向順時針畫出。
   stroke-dashoffset 只能寫在標籤屬性上（GSAP 改的是屬性；CSS 宣告會壓過屬性，
   寫在這裡線就永遠不會畫出來）。 */
.ring-line {
    fill: none;
    stroke: var(--rk-ink);
    stroke-opacity: .32;
    /* 蓋過標籤上的 stroke-opacity */
    stroke-dasharray: 1;
}
/* 刻度（JS 依 data-* 生成）：墨線，長刻度較深較粗 */
.ring-ticks line {
    stroke: var(--rk-ink);
    stroke-width: 1.2;
    stroke-opacity: .4;
}
.ring-ticks line.is-major {
    stroke-width: 1.6;
    stroke-opacity: .75;
}
/* ── 精密尺標 .ring-rule ──────────────────────────────────────
   跟拿掉的方位刻度環（r=560、每 2°／10°）刻意走反方向：更細、更密、更淡，
   是游標卡尺／光圈環的尺規，不是羅盤。
   幾何全部靠 dasharray、沒有 JS 生成：pathLength="360" 讓 dash 直接以「度」
   為單位（手法同 .kv-hole-ticks），一個 <circle> 就是一整梳刻度 ——
   720 支刻度只花 1 個節點。這層每幀被 .ring-stage 的推擠與自轉重寫，
   節點數直接等於每幀的 paint 成本，所以不能用 720 個 <line>。
     stroke-width  ＝ 刻度長度（不是線寬！）
     dash 長度      ＝ 刻度寬度
     dashoffset     ＝ dash 的一半，把刻度置中在角度線上
   刻度寬換算（user unit）＝ dash° × r × π/180。
   ⚠ 絕對不能加 vector-effect: non-scaling-stroke —— stroke-width 是刻度長度，
     鎖成固定像素的話視窗一縮尺標就爆長。
   ⚠ 也不要加 shape-rendering: crispEdges —— 自轉時刻度會集體一格一格跳。
   ⚠ stroke-width 只寫在標籤屬性上、不寫在這裡：進場動畫補的是屬性，
     CSS 宣告會壓過屬性（同 .ring-line 的 stroke-dashoffset 陷阱）。 */
/* 暫時隱藏（使用者要求：離外圈文字最近的那組尺標 r=428）——
   整組收起來，JS 的進場／自轉照跑但不畫，要拉回來就刪掉這條 display。 */
.ring-rule {
    display: none;
}
.ring-rule circle {
    fill: none;
    stroke: var(--rk-ink);
    stroke-linecap: butt;
}
.ring-rule .rule-fine {
    /* 每 0.5°：720 支 */
    stroke-dasharray: .1 .4;
    stroke-dashoffset: .05;
    stroke-opacity: .28;
}
.ring-rule .rule-step {
    /* 每 5°：72 支 */
    stroke-dasharray: .15 4.85;
    stroke-dashoffset: .075;
    stroke-opacity: .34;
}
.ring-rule .rule-mark {
    /* 每 30°：12 支 —— 覺得又開始像羅盤，第一個刪這條 */
    stroke-dasharray: .2 29.8;
    stroke-dashoffset: .1;
    stroke-opacity: .4;
}
/* 尺標的兩道髮絲基準線：內線＝刻度根部(318)、外線＝尺規槽收邊(336)。
   比四道結構圓再淡一階、細一半。選擇器要比 .ring-line 更具體，
   否則 .ring-line 的 stroke-opacity 會壓過來。 */
.ring-line.rule-datum {
    stroke-width: .6;
    stroke-opacity: .2;
}
.ring-line.rule-datum.is-outer {
    stroke-width: .5;
    stroke-opacity: .12;
}
/* 小螢幕：1 user unit 只剩 ~0.5px，0.5° 的梳子會糊成一條均勻灰帶
   （那就不是刻度、是一圈莫名其妙的髒帶子）—— 放粗節距。 */
@media (max-width: 900px) {
    .ring-rule .rule-fine {
        /* 每 1°：360 支 */
        stroke-dasharray: .25 .75;
        stroke-dashoffset: .125;
    }
}
@media (max-width: 600px) {
    .ring-rule .rule-fine {
        /* 每 2°：180 支 */
        stroke-dasharray: .4 1.6;
        stroke-dashoffset: .2;
    }
}
/* 衛星點：在輔助圓上跑的小點，外圈柔暈＋內圈實心 */
.ring-sat-glow {
    fill: var(--rk-ink);
    fill-opacity: .16;
}
.ring-sat-dot {
    fill: var(--rk-ink);
}
.ring-sat.is-green .ring-sat-glow {
    fill: var(--rk-green);
    fill-opacity: .2;
}
.ring-sat.is-green .ring-sat-dot {
    fill: var(--rk-green);
}
/* ── 中央充能儀表層 .kv-core ──────────────────────────────
   跟 .kv-halo 同尺寸、同圓心、同 viewBox 的另一張 fixed SVG。
   獨立一層的理由：.kv-halo 整層是 soft-light 混合，白色大數字與萊姆綠弧會被
   底下的影片洗淡；這層不混合，數字與弧線才像參考稿那樣乾淨、飽和。
   opacity／visibility／display／洞口外推全部由 JS 跟 .kv-halo 同步。
   跟 .kv-halo 一樣不強制合成層（理由見 .kv-halo 註解）。 */
.kv-core {
    position: fixed;
    inset: 0;
    z-index: 4;
    display: flex;
    align-items: center;
    justify-content: center;
    pointer-events: none;
    opacity: 0;
}
/* ── 照片扇形層 .kv-wedges ──────────────────────────────────
   壓在影片上、同心圓（.kv-halo）之下的 fixed SVG（DOM 順序在 .kv-halo 前面）。
   三個扇形窗各放一張站內照片 —— 參考稿「圓形資訊圖」的語彙；幾何由 JS 依
   WEDGES 設定生成（角度、內外半徑、圖片），進場時沿角度掃開、隨捲動微轉、
   跟滑鼠做視差、開洞時跟著外推。opacity／visibility／display 與 .kv-halo 同步。 */
.kv-wedges {
    position: fixed;
    inset: 0;
    z-index: 4;
    display: flex;
    align-items: center;
    justify-content: center;
    pointer-events: none;
    opacity: 0;
}
/* ── 中央水平軸線 .kv-axis ────────────────────────────────
   橫貫視窗的髮絲線，字標坐在線的上緣（參考稿）。
   z-index 跟其他三層一樣是 4：開洞時一起被 z-5 的地球段 蓋掉。 */
.kv-axis {
    position: fixed;
    inset: 0;
    z-index: 4;
    pointer-events: none;
    opacity: 0;
}
.kv-axis-line {
    position: absolute;
    left: 0;
    right: 0;
    top: 50%;
    height: 1px;
    /* 兩端淡出：線不要硬碰到視窗邊 */
    background: linear-gradient(90deg,
            rgba(255, 255, 255, 0) 0%,
            rgba(255, 255, 255, .5) 10%,
            rgba(255, 255, 255, .5) 90%,
            rgba(255, 255, 255, 0) 100%);
    /* 進場由中央往兩側拉開；起點就寫在這裡，時間軸還沒進區間也不會先露出整條 */
    transform: scaleX(0);
    transform-origin: 50% 50%;
}
/* 軸線上的橫向電流：canvas 疊在髮絲線上，寬度跟著視窗，
   高度給抖動留空間（線本身還是上面那條 CSS 髮絲線，
   電流是加在它上面的那層「通電」）。 */
.kv-axis-bolt {
    position: absolute;
    left: 0;
    top: 50%;
    width: 100%;
    height: 120px;
    transform: translateY(-50%);
    pointer-events: none;
}
/* 字標坐在線上方一點點，不跟線交叉 */
.kv-axis-tag {
    position: absolute;
    bottom: 50%;
    margin-bottom: 9px;
    font-family: 'Jost', sans-serif;
    font-size: 12px;
    font-weight: 700;
    letter-spacing: .22em;
    color: rgba(255, 255, 255, .92);
    white-space: nowrap;
    opacity: 0;
}
.kv-axis-tag.is-left {
    left: clamp(20px, 6vw, 96px);
}
.kv-axis-tag.is-right {
    right: clamp(20px, 6vw, 96px);
}
/* 扇形照片上的文案（使用者要求）：白字＋深色描邊當底，
   照片深淺不一也讀得到。文字水平不隨環帶旋轉（放在 .wedge-labels，
   不在會轉 −10° 的 .wedge-group 裡）。 */
.wedge-label {
    fill: #fff;
    font-family: 'Jost', 'Noto Sans TC', sans-serif;
    font-size: 14px;
    letter-spacing: .08em;
}
/* 扇形窗內的照片略壓暗，白色文字圈蓋在上面才讀得到 */
.wedge-tint {
    fill: rgba(6, 24, 34, .16);
    /* 照片微壓暗，白字蓋在上面讀得到 */
}
/* 扇形邊緣：白色粗邊 ＝ 照片與地之間的留白（參考稿扇形與圓之間有一圈白縫） */
.wedge-edge {
    fill: none;
    stroke: none;
    /* 照片不要描邊（使用者要求）。要加回白色留白邊：stroke: #fff; stroke-width: 3; */
    stroke-linejoin: round;
}
/* 扇形外側 10 單位的回聲弧，跟著扇形一起掃開 */
.wedge-echo {
    fill: none;
    stroke: var(--rk-ink);
    stroke-opacity: .22;
    stroke-width: 1;
}
/* 扇形註記：綠點＋水平引線＋小標（01 — BESS STORAGE） */
.wedge-note circle {
    fill: var(--rk-green);
}
.wedge-note line {
    stroke: var(--rk-ink);
    stroke-opacity: .4;
    stroke-width: 1;
}
.wedge-note text {
    fill: var(--rk-ink);
    fill-opacity: .75;
    font-family: 'Jost', sans-serif;
    font-size: 11px;
    font-weight: 600;
    letter-spacing: 1.6px;
}
/* 輻射長條群＋弧線碎片（JS 以固定種子生成，落在不碰文字的四條環帶）：
   白／萊姆綠／深藍三色，線條清晰（在不混合的 .kv-core 層）。 */
.core-orn line,
.core-orn path {
    fill: none;
}
/* 長條三色：墨藍（主）、品牌綠、鋼藍（class 名沿用 c-w / c-l / c-n） */
.core-orn .c-w {
    stroke: var(--rk-ink);
}
.core-orn .c-l {
    stroke: var(--rk-green);
}
.core-orn .c-n {
    stroke: var(--rk-steel);
}
/* 長條群括弧：群的內側一道細弧，標出這一群的角度範圍 */
.core-orn .orn-bracket {
    fill: none;
    stroke: var(--rk-ink);
    stroke-opacity: .3;
    stroke-width: 1;
}
/* 儀表面：中央一片白色柔光盤，數字與弧線壓在乾淨的面上 */
/* 中央暗影（.ring-core-shade）已拿掉：使用者要求 UI 無陰影、地保持乾淨 */
/* 軌道：與弧同寬的淡白粗圓，弧疊在它上面（參考稿的淺灰軌道） */
.ring-core-track {
    fill: none;
    stroke: var(--rk-ink);
    stroke-opacity: .3;
    stroke-width: 8;
}
/* 外圈髮絲線：貼著軌道外側的一圈淡白細線（參考稿的細節） */
.ring-core-orbit {
    fill: none;
    stroke: var(--rk-ink);
    stroke-opacity: .3;
    stroke-width: 1;
}
/* ── 儀表迷你尺標 .core-rule ──────────────────────────────
   halo 精密尺標（.ring-rule）的縮小版，套在儀表髮絲線（r=126）外緣。
   手法完全相同：pathLength="360" 讓 dash 以「度」為單位，一個 <circle>
   就是一整梳刻度；stroke-width ＝ 刻度長度、dash ＝ 刻度寬度。
   半徑只有 halo 的 1/2.3，節距照抄 0.5° 會糊成灰帶，所以放粗到 2°。
   ⚠ 同 .ring-rule：不能加 vector-effect / crispEdges；
     stroke-width 只寫在標籤屬性上（進場動畫補的是屬性）。 */
.core-rule circle {
    fill: none;
    stroke: var(--rk-ink);
    stroke-linecap: butt;
}
.core-rule .rule-fine {
    /* 每 2°：180 支 */
    stroke-dasharray: .3 1.7;
    stroke-dashoffset: .15;
    stroke-opacity: .3;
}
.core-rule .rule-step {
    /* 每 10°：36 支 */
    stroke-dasharray: .45 9.55;
    stroke-dashoffset: .225;
    stroke-opacity: .38;
}
.core-rule .rule-mark {
    /* 每 30°：12 支 */
    stroke-dasharray: .6 29.4;
    stroke-dashoffset: .3;
    stroke-opacity: .45;
}
/* 尺標的兩道髮絲基準線：內線＝刻度根部(134)、外線＝尺規槽收邊(150)。
   跟著 .ring-core 一起彈出，不走 .ring-line 的掃線進場。 */
.core-rule-datum {
    fill: none;
    stroke: var(--rk-ink);
    stroke-width: .6;
    stroke-opacity: .2;
}
.core-rule-datum.is-outer {
    stroke-width: .5;
    stroke-opacity: .12;
}
/* 內圈底盤：弧線裡側的一片微亮圓盤（使用者參考稿）。
   平塗淡白、邊緣乾淨，跟著 .ring-core 一起彈出；閃電畫布 z-5 蓋在上面。 */
.ring-core-plate {
    fill: var(--rk-ink);
    /* 3D 迷你地球墊在下面（.dial-globe）：底盤壓到極淡，球才立體 */
    fill-opacity: .05;
}
/* 儀表迷你 3D 地球（使用者要求：要自轉、要立體）：
   獨立的小 three.js 球體，插在 .kv-core 的 SVG「下面」——
   充能弧、刻度、計數照樣畫在球前面；閃電畫布（z-5）在最上。
   尺寸＝內圓 r90 佔 viewBox 1400 的比例（12.86%）。 */
.dial-globe {
    position: absolute;
    left: 50%;
    top: 50%;
    width: 12.86%;
    aspect-ratio: 1;
    transform: translate(-50%, -50%);
    pointer-events: none;
}
/* 充能弧：粗品牌綠、圓頭，12 點方向順時針長滿，與中央計數同步、
   正好在洞打開那刻到 100。stroke-dashoffset 寫在標籤屬性（理由見 .ring-line）。 */
.ring-arc {
    fill: none;
    /* 後面那個是不支援 url() 時的退路色，要跟漸層的 stop 一致，不然降級會變藍 */
    stroke: url(#core-arc-grad) #76c5af;
    /* 顏色改在 <linearGradient id="core-arc-grad"> 的三個 stop（現在是 --sn-mint 純色） */
    stroke-width: 8;
    stroke-linecap: round;
    stroke-dasharray: 1;
}
/* 中央雜訊（雷達扇面、準星短線、核心亮點、脈衝環、內圈刻度）已拿掉：
   參考稿的中央只有標題／小標／大數字，乾淨留白 */
.ring-core-label,
.ring-core-num {
    fill: var(--rk-ink);
    text-anchor: middle;
    font-family: 'Jost', 'Noto Sans TC', sans-serif;
}
/* 參考稿樣式：小標 ／ 粗體大數字 ＋ 小粗體單位。
   單位是 SVG user unit（viewBox 1400）：46 ≈ 55px @1440×900。
   數字若改成較寬的值（例：510,000），font-size 請調到 34–38 才不會碰到內圈文字。 */
/* 標題與小標都固定不變（使用者要求：文字統一，不要充滿那刻突然換字或變樣）。
   以前是 CHARGING → 累積建置 的切換 ＋ 加粗放大 ＋ 小標淡入，全部拿掉；
   要改文案改 .ring-core 的 data-label（見該處註解）。 */
.ring-core-label {
    font-size: 15px;
    font-weight: 700;
    fill-opacity: 1;
}
/* 數字上方的小標（參考稿：「全球儲能建置功率」貼在大數字上緣）：
   從頭到尾都在，跟標題一起構成第二區塊的統計版面 */
.ring-core-cap {
    fill: var(--rk-ink);
    fill-opacity: .78;
    text-anchor: middle;
    font-family: 'Jost', 'Noto Sans TC', sans-serif;
    font-size: 12px;
    font-weight: 500;
    letter-spacing: 2px;
}
/* 里程計式計數（JS 生成）：每位數一欄直排 0–9，clipPath 只露出一行，
   值改變時整欄上滑。.ring-core-odo 整組帶一點投影。 */
.ring-core-odo {
    filter: none;
    /* 淺色地不需要投影 */
}
/* 計數的數字欄。Poppins 沒有等寬數字（實測「1」17.3 寬、「0」30、「4」31.2），
   font-variant-numeric: tabular-nums 對它完全沒作用 —— 留著沒用但無害，
   哪天換成有 tnum 的字體就會自動生效。
   所以每一格配的是「最寬字形」的寬度（見 JS measure()），字再置中在格子裡：
   靠左對齊的話「1」右邊會空出一大塊，看起來像排版壞掉。
   ⚠ text-anchor 跟 JS set() 裡的 translate 是一組的 —— 改成 start／end
     就要同步改那邊的落點，不然數字會整排偏掉。 */
.ring-core-num {
    fill: var(--rk-ink);
    font-family: 'Jost', sans-serif;
    font-size: 46px;
    font-variant-numeric: tabular-nums;
    text-anchor: middle;
    display: none;
}
.ring-core-unit {
    fill: var(--rk-ink);
    fill-opacity: .8;
    font-family: 'Jost', sans-serif;
    font-size: 14px;
    font-weight: 300;
    text-anchor: start;
    display: none;
}
/* 洞緣外側的刻度環：pathLength="360" 讓 dasharray 以「度」計，半徑由 setRim
   直接寫 r（不用 scale），刻度角距因此恆定；線寬由 measurePortalUnit 換算成 px。
   隨開洞進度慢慢轉，像鏡頭光圈環。 */
.kv-hole-ticks {
    fill: none;
    stroke: var(--rk-ink, #12304d);
    stroke-opacity: .5;
    stroke-dasharray: 1.4 6.6;
}
/* 釋放震波：一圈細線跑在洞緣前方，洞越大跑得越遠、越淡（半徑與透明度由 setRim 寫） */
.kv-hole-wave {
    fill: none;
    stroke: var(--rk-ink, #12304d);
    stroke-width: 1.2;
    stroke-opacity: 0;
}
/* 衛星拖尾（JS 生成兩段弧）：短而亮、長而淡，拖在運動方向後方 */
.ring-sat-tail {
    fill: none;
    stroke: var(--rk-ink);
    stroke-linecap: round;
}
.ring-sat-tail.is-short {
    stroke-width: 2.2;
    stroke-opacity: .3;
}
.ring-sat-tail.is-long {
    stroke-width: 1.3;
    stroke-opacity: .1;
}
.ring-sat.is-green .ring-sat-tail {
    stroke: var(--rk-green);
}
/* 文字圈進場的「掃描顯示」遮罩：一道粗描邊圓從 12 點方向順時針畫出，
   字被它蓋到才顯示（JS 補間 stroke-dashoffset 1 → 0）。 */
.ring-wipe {
    fill: none;
    stroke: #fff;
    stroke-dasharray: 1;
    filter: blur(4px);
    /* 掃描前緣柔一點（只在進場那段有效，之後 mask 會被拿掉） */
}
@media (max-width: 1024px) {
    .kv-eyebrow {
        top: 112px;
    }
}
@media (max-width: 700px) {
    /* （原本這裡有 .kv { min-height: 700px }，理由見上面 .kv 的註解，已拿掉） */
    .kv-orbit {
        top: 45%;
        left: 54%;
        width: 92vw;
    }
    .kv-title-cluster {
        top: 112px;
        right: 20px;
        left: 20px;
        width: auto;
    }
    .kv-eyebrow {
        font-size: 9px;
    }
    .kv-ai-badge {
        min-height: 21px;
        padding: 3px 7px;
        font-size: 8px;
    }
    .kv-panel-status {
        top: auto;
        right: 20px;
        bottom: 90px;
        left: 20px;
        width: auto;
        padding: 14px;
        border-radius: 18px;
    }
    .kv-mini-grid,
    .kv-panel-chart {
        display: none;
    }
    .kv-meta {
        align-items: flex-end;
        flex-direction: row;
        padding: 0;
    }
    .story {
        height: 560vh;
        min-height: 3500px;
    }
}
/* ── 第一塊的文案群組：LOGO 在上，字標／中文主標／中文副標依序往下 ──
   整組用 flex 直排並以 .kv 為錨點置中，垂直位置往下推讓出上方給 LOGO
   （LOGO 是全螢幕 fixed 畫布，高度由模組的 CFG.logoY 決定）。 */
.kv-title-cluster {
    position: absolute;
    z-index: 4;
    left: 0;
    right: 0;
    /* 原版規則有 width: min(34vw,560px)，不覆蓋的話字標會溢出 */
    width: auto;
    /* 58%：LOGO 佔上半，文案掛在它下面 */
    top: 55%;
    transform: translateY(-50%);
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 1.6vh;
    pointer-events: none;
    user-select: none;
}
/* 字標：左到右青綠漸層。background-clip:text 需要文字本身透明，
   所以 color 一定要 transparent，不能只靠 -webkit- 前綴。 */
.kv-wordmark {
    font-family: var(--rp-en);
    font-size: clamp(40px, 7.6vw, 80px);
    font-weight: 600;
    text-align: center;
    line-height: 1;
    white-space: nowrap;
}
/* 漸層必須掛在真正含有文字的那一層 —— 文字移到 .kv-rv 之後，
   <h1> 自己已經沒有文字節點，background-clip:text 會裁到空的。 */
/* .kv-wordmark .kv-rv {
    background: linear-gradient(90deg, #6ec3d6 0%, #86cfcb 34%, #a9dcbe 64%, #c9e8bb 100%);
    -webkit-background-clip: text;
    background-clip: text;
    color: transparent;
} */
.kv-lead {
    font-family: var(--rp-tc);
    font-size: clamp(15px, 1.42vw, 27px);
    font-weight: 700;
    letter-spacing: .04em;
    color: #fff;
}
.kv-sub {
    font-family: var(--rp-tc);
    font-size: clamp(12px, 1vw, 19px);
    font-weight: 400;
    letter-spacing: .04em;
    color: #fff;
}
/* ── 退場容器 ──────────────────────────────────────
   這組 overflow + padding/margin 對是舊「遮罩上滑」退場留下的；
   退場現已改成純淡出（見 kvExit 的註解），小字三行的窗口
   留著無妨（純 opacity 不位移，不會撞到邊），字標則在下面
   覆寫回 visible，讓重複切片能出框上下散開。
   padding/margin 成對抵銷：外層要留一點餘裕才不會削到字腔，
   但版面位置必須和原本一模一樣（文案群組是 flex + gap）。 */
.kv-wordmark,
.kv-lead,
.kv-sub,
.kv-footline {
    overflow: hidden;
    padding-block: .12em;
    margin-block: -.12em;
}
.kv-rv {
    display: block;
    will-change: transform;
    font-size: 23px;
    font-weight: 500;
}
/* ── 字標重複描邊殘影（Codrops TextRepetitionEffect demo3 移植）──
   JS 把 .kv-wordmark .kv-rv 的內容換成 5 份同文字疊在同一個
   grid 格：最後一份是原本的漸層主字，前 4 份只留描邊，
   捲動時上下各散開「兩層」殘影（yPercent ±14% 遞增）＋淡入。
   字標的 overflow 開回 visible：殘影要在字標框外上下散開
   （最遠 ±28% 字高，退場再外推一段），任何遮罩窗口都只會
   裁到它；退場是純淡出（見 kvExit），不需要「滑出遮罩邊」
   那套裁切。 */
.kv-wordmark {
    overflow: visible;
}
/* 漸層必須掛在真正含有文字的那一層：疊起來之後 .kv-rv 自己
   沒有文字節點；而且掛在 .kv-rv 上 background-clip:text 會把
   「所有」後代文字都裁出漸層，描邊份的透明填色反而露出漸層
   變實心。所以漸層改掛到最後一份 span 上，.kv-rv 本身關掉。 */
.kv-wordmark .kv-rv.text-rep {
    display: grid;
    background: none;
}
.kv-wordmark .text-rep>span {
    grid-area: 1 / 1 / 2 / 2;
    will-change: transform, opacity;
}
.kv-wordmark .text-rep>span:last-child {
    background: linear-gradient(90deg, #6ec3d6 0%, #86cfcb 34%, #a9dcbe 64%, #c9e8bb 100%);
    -webkit-background-clip: text;
    background-clip: text;
    color: transparent;
}
/* 初始收合隱藏，捲動才淡入散開（JS 接手）：tween 帶延遲，
   時間軸倒回 0 時延遲層可能從未初始化（同 kvExit 註解裡的坑），
   CSS 先寫好靜止值。 */
.kv-wordmark .text-rep>span:not(:last-child) {
    opacity: 0;
    -webkit-text-stroke: 1px rgba(134, 207, 203, .5);
    -webkit-text-fill-color: transparent;
    color: transparent;
}
/* 底部落款：兩行置中、字距拉開 */
.kv-footline {
    position: absolute;
    z-index: 4;
    left: 0;
    right: 0;
    bottom: 7vh;
    text-align: center;
    font-family: var(--rp-en);
    font-size: clamp(10px, .82vw, 15px);
    font-weight: 400;
    letter-spacing: .16em;
    line-height: 2.1;
    color: #6b7570;
    pointer-events: none;
    user-select: none;
}
/* 槽位比字高略大，LOGO 才不會被上下擠扁 */
/* 3D LOGO 畫布：全螢幕 fixed（黑件飛離時會出到 .kv 的邊界外）。
   z-5 高於 .kv；閃電在 .kv-track 跑道
   尾段收攏，畫布跟著 banner 退場一起淡掉（見 kvCanvasExit） */
#kv-canvas-container {
    position: fixed;
    inset: 0;
    z-index: 5;
    pointer-events: none;
}
#kv-canvas-container canvas {
    display: block;
    width: 100%;
    height: 100%;
}

/* ── 4. LOGO 開窗（js/index2-brand-reveal.js）──────────────────────────────── */
/* Only index2 loads this hero treatment; its original disc owns the handoff. */
.index2-brand-scrim {
  position: absolute;
  inset: 0;
  z-index: 2;
  pointer-events: none;
  /* Match index.html: the lower shade rises behind the title and closes to
     solid black before the bottom edge, while the upper video stays clear. */
  background: linear-gradient(180deg,
      rgba(0, 0, 0, 0) 20%,
      rgba(2, 3, 5, .50) 40%,
      rgba(1, 2, 3, .70) 60%,
      rgba(0, 0, 0, .85) 76%,
      rgba(0, 0, 0, .90) 100%);
}
.index2-brand-reveal {
  position: fixed;
  inset: 0;
  width: 100%;
  height: 100%;
  z-index: 3;
  pointer-events: none;
  opacity: 0;
  visibility: hidden;
}
body.has-index2-brand-reveal .kv-video {
  opacity: .95 !important;
  filter: none !important;
}
body.has-index2-brand-reveal .kv-tint {
  opacity: 0 !important;
}
body.has-index2-brand-reveal .kv-title-cluster,
        body.has-index2-brand-reveal .kv-footline,
        body.has-index2-brand-reveal .kv-mini-grid  {
  opacity: var(--index2-copy-opacity, 1) !important;
}
@media (prefers-reduced-motion: reduce) {
  .index2-brand-reveal {
    display: none;
  }
}

/* ── 5. KV 字體：兩行字標（原 index2-typography.css）──────────────────────── */
/* index2's two-line hero lockup, matching the supplied typography reference. */
.kv-title-cluster {
  padding-inline: 4vw;
  gap: clamp(18px, 2.2vh, 30px);
  text-align: center;
}
/* 大標英文的字體參數（照使用者提供的 Photoshop 設定，2026-09-26）：
     Jost Medium(500) / 120pt / 字距 100 / 全大寫(TT) / 白
   ・字距：Photoshop 的 VA 單位是 1/1000 em，所以 100 ＝ .1em。
   ・letter-spacing 會在最後一個字後面也加一份空白，置中的字會被推左半格 ——
     補 padding-left 同量抵銷（跟下面 .kv-lead 的 .2em 是同一個做法）。
   ・120pt ＝ 160px。設計稿量到大標約佔畫面寬 5.8%~6.3%，所以 vw 項維持 6.25vw，
     上限放寬到 160px 讓大螢幕吃得到設計稿的級數。 */
.kv-wordmark {
  font-family: 'Jost', sans-serif;
  font-size: clamp(28px, 6.25vw, 160px);
  font-weight: 500;
  line-height: 1.04;
  letter-spacing: .1em;
  padding-left: .1em;
  text-transform: uppercase;
  text-align: center;
  color: #fff;
}
/* 大標漸層（設計稿的青→綠）。
   ⚠ 為什麼要同時掛在兩個選擇器上：頁面剛載入時文字在 .kv-rv 裡；
     js/index2-kv.js 之後會把它拆成 5 份疊在同一格（.text-rep），
     那時真正有文字節點的是最後一份 span。兩個都掛，才不會在拆解那一幀閃成白字。
     （.kv-rv.text-rep 本身的漸層由下面那條關掉 —— 掛在容器上會把描邊殘影一起填實。） */
.kv-wordmark .kv-rv,
.kv-wordmark .text-rep>span:last-child {
  background: linear-gradient(90deg, #6ec3d6 0%, #86cfcb 34%, #a9dcbe 64%, #c9e8bb 100%);
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
  color: transparent;
  /* ⚠ 這一行不能省：上面有一條通用的 .kv-rv { font-size: 23px }（那是給 .kv-lead /
     .kv-sub 的內層用的），不覆寫的話大標內層會掉回 23px。
     原本這裡寫的是 75px —— 壓得過 23px，但等於把 clamp 廢掉、大標完全不隨視窗縮放。
     改成 inherit：既壓得過 23px，又跟著 .kv-wordmark 的 clamp 走。 */
  font-size: inherit;
}
.kv-wordmark .text-rep>span:not(:last-child) {
  -webkit-text-stroke-color: rgba(255, 255, 255, .5);
}
/* 粗體訴求句：設計稿的字距比原本窄很多（原本 .2em 是上一版大標式的排法）。 */
.kv-lead {
  font-family: 'Jost', 'Noto Sans TC', sans-serif;
  font-size: clamp(16px, 1.75vw, 27px);
  font-weight: 700;
  line-height: 1.5;
  letter-spacing: .06em;
  padding-left: .06em;
  color: #fff;
}
/* 細體說明：原本被 display:none 藏起來（上一版文案沒有這行），設計稿有，放回來。 */
.kv-sub {
  display: block;
  font-family: 'Jost', 'Noto Sans TC', sans-serif;
  font-size: clamp(12px, 1.05vw, 17px);
  font-weight: 400;
  line-height: 1.7;
  letter-spacing: .05em;
  color: rgba(255, 255, 255, .82);
}
@media (max-width: 700px) {
  .kv-title-cluster {
    top: 48%;
    padding-inline: 4vw;
    gap: 18px;
  }
  .kv-wordmark {
    font-size: clamp(20px, 6.15vw, 40px);
    /* 設計稿是 .1em，但手機寬度吃不下整行（最長那行 21 個字）。
       實測 430px 寬：.1em 會貼到邊，.06em 之後左右還各留 34px，是放得下的最大值。 */
    letter-spacing: .06em;
    padding-left: .06em;
  }
  .kv-lead {
    font-size: clamp(13px, 3.35vw, 18px);
    letter-spacing: .14em;
  }
}
/* （原本這裡有一條 ≤1024 的 font-size: inherit，用來繞過寫死的 75px；
   上面已經改成無條件 inherit，這條就多餘了，移除。） */
@media (max-width: 600px) {
  .kv-wordmark { max-width: 100%; }
}

/* ── 6. 動態暫停（原 index2-motion-polish.css）：分頁不在前景時暫停裝飾動畫、減少動態時停住 ── */
.index2-motion-paused :is(.kv-halo, .kv-core, .kv-wedges, .kv-axis),
.index2-motion-paused :is(.kv-halo, .kv-core, .kv-wedges, .kv-axis) * {
    animation-play-state: paused !important;
}

@media (prefers-reduced-motion: reduce) {
    :is(.kv-halo, .kv-core, .kv-wedges, .kv-axis),
    :is(.kv-halo, .kv-core, .kv-wedges, .kv-axis) * {
        animation-play-state: paused !important;
    }
    .kv-axis-bolt,
    .kv-wordmark .text-rep > span[aria-hidden="true"] {
        visibility: hidden !important;
    }
}

/* ══ 文字進場引擎的兩個結構類別（js/index2-text-reveal.js）══════════════════
   .rt-win 是「窗口」：只負責裁掉窗外的部分，自己永遠不動。
   .rt-in  是「被拉出來的那層」：GSAP 只動它的 transform。
   窗口與內層都要 inline-block，字才量得到自己的行高；vertical-align 對齊基線，
   不然一包起來整行會往下掉幾 px。
   overflow: clip 比 hidden 好：不會生出捲動容器（hidden 在某些瀏覽器會）。 */
.rt-win { display: inline-block; overflow: clip; vertical-align: top; }
.rt-in { display: inline-block; will-change: auto; }
/* 跑完就把窗口的裁切拿掉：字如果有下伸部（g、y）或斜體，留著裁切會被切到一點點。 */
.rt-done .rt-win, .rt-win.rt-done { overflow: visible; }

/* ── banner 底部落款（設計稿：STABLE POWER. / FUTURE INNOVATION.）─────────
   兩行置中、小字、字距拉開。壓在文案群組下方，與大標同一個中線。 */
.kv .kv-footline {
    position: absolute;
    left: 0;
    right: 0;
    bottom: clamp(48px, 9svh, 110px);
    z-index: 4;
    margin: 0;
    text-align: center;
    font-family: 'Jost', 'Noto Sans TC', sans-serif;
    font-size: clamp(10px, .82vw, 14px);
    font-weight: 500;
    line-height: 2;
    letter-spacing: .14em;
    color: rgba(255, 255, 255, .9);
}
.kv .kv-footline .kv-rv { font-size: inherit; font-weight: inherit; }

/* ══ 7. banner：index-original.html 的 hero 樣式（c-video-banner；使用者 2026-09-27 指定）══════════
   背景六條垂直參考線、等寬小標（終端機亂碼收斂）、兩行大標（逐字亂序閃現）、中文一行、薄荷按鈕（四點散開＋中心閃爍）。
   切字與播放時機在 js/index2-vb.js；keyframes 一律加 vb- 前綴。
   字體：index-original 用 Poppins；這裡沿用全站統一的 Jost（2026-09-25 使用者要求英文全部 Jost）。 */

/* ── 背景參考線：左右各留 4.4%，中間五等分 ── */
.kv-guides {
    --edge: 4.4%;
    --gap: 18.24%;
    position: absolute;
    inset: 0;
    z-index: 3;
    pointer-events: none;
}
.kv-guides i {
    position: absolute;
    top: 0;
    bottom: 0;
    width: 1px;
    background: linear-gradient(180deg, rgba(255, 255, 255, 0) 0, rgba(255, 255, 255, .085) 9%, rgba(255, 255, 255, .085) 91%, rgba(255, 255, 255, 0) 100%);
}
.kv-guides i:nth-child(1) { left: var(--edge); }
.kv-guides i:nth-child(2) { left: calc(var(--edge) + var(--gap)); }
.kv-guides i:nth-child(3) { left: calc(var(--edge) + var(--gap) * 2); }
.kv-guides i:nth-child(4) { left: calc(var(--edge) + var(--gap) * 3); }
.kv-guides i:nth-child(5) { left: calc(var(--edge) + var(--gap) * 4); }
.kv-guides i:nth-child(6) { left: calc(var(--edge) + var(--gap) * 5); }

/* ── 文案群組：置中直排，節奏照 index-original ──
   數值一律以 index-original 實際算出來的樣式為準（2026-09-27 複審 F7）；唯一例外是英文字體沿用 Jost
   （使用者規定），等寬小標維持等寬字。顏色／小標字級可在 ?tune「Hero｜文案顏色・字級」調：
   js/index2-vb.js 只在調過時才把 --vb-* 變數寫到 .kv-title-cluster 上，平常走 var() 的後備值（＝原版）。 */
.kv-title-cluster { gap: 0; }
.kv-title-cluster .kv-rv { font-size: inherit; font-weight: inherit; }
/* JS 跑之前先藏（QA-7）：index2.html <head> 的第一段 inline script 只在「intro 會播」時掛 html.kv-intro-pending，
   全頁第一個 DOMContentLoaded 監聽就拿掉，緊接著 index2-kv.js 的 intro 用 .from() 接手（同一個工作，不會閃）。
   沒有這條，HTML 一畫出來小標就以原字全亮，等 DOMContentLoaded 才被打回 0、再淡入跑亂碼。
   只用 opacity（不動 display／visibility）：版面照常排，hero3d 的 layoutLogo 量得到文案群組。 */
html.kv-intro-pending .kv-title-cluster .kv-eyebrow,
html.kv-intro-pending .kv-title-cluster .kv-wordmark,
html.kv-intro-pending .kv-title-cluster .kv-sub,
html.kv-intro-pending .kv-title-cluster .kv-lead { opacity: 0; }
/* 小標：原版 .kv-eyebrow.vb-mono 同一個元素 —— 11px、字重 650、字距 .14em（.vb-mono 那條蓋過 .11em）、
   顏色繼承 .kv 的 #c9ccce、上下不留距（原版群組 gap 0、margin 0；大標的 −.12em 外距剛好吃掉自己的內距） */
.kv-eyebrow {
    display: block;
    margin: 0;
    font-size: var(--vb-eyebrow-size, 11px);
    font-weight: 650;
    letter-spacing: .14em;
    color: var(--vb-eyebrow-color, #c9ccce);
}
.kv-eyebrow::before { content: none; }
.kv-wordmark {
    font-family: 'Jost', sans-serif;
    font-size: clamp(30px, 3.65vw, 70px);
    font-weight: 500;
    line-height: 1.08;
    letter-spacing: -.018em;
    padding-left: 0;
    text-transform: uppercase;
    color: var(--vb-head-color, #c9ccce);
}
/* 大標顏色：原版 h1 裡沒有 .kv-rv，那條 `.kv-wordmark .kv-rv { color:#fff }` 其實沒套到任何東西，
   實際是繼承 .kv 的 #c9ccce（-webkit-text-fill-color 是預設的 currentColor）—— 這裡照實際值。
   同時蓋掉前面舊版的青→綠漸層（background-clip:text 會讓逐字的透明度失效）。 */
.kv-wordmark .kv-rv.vb-head {
    background: none;
    -webkit-background-clip: initial;
    background-clip: initial;
    color: var(--vb-head-color, #c9ccce);
    -webkit-text-fill-color: currentColor;
}
/* 中文行：原版是 h1 的第三個 .vb-line（index-original.html:6277 的 inline 樣式），跟英文兩行一起逐字閃現。
   index2 放在自己的 <p class="kv-sub">（kvExit 抓 .kv-sub .kv-rv），字級／字重／字距／顏色／上距照那行 inline 樣式，
   行高 1.08 是原版從 h1 繼承來的。外框歸零、overflow 放開：原版這行上面沒有別的間距（h1 的 −.12em 外距已經
   抵掉自己的內距），這裡再留 margin／padding 就會多一截；退場是純淡出，不需要窗口裁切
   （行高 1.08 時中文字身會超出行框，裁了會削到字）。 */
.kv-sub {
    display: block;
    margin: 0;
    padding: 0;
    overflow: visible;
}
.kv-title-cluster .kv-sub .vb-head {
    font-family: var(--tc, 'Jost', 'Noto Sans TC', sans-serif);
    font-size: clamp(16px, 1.3vw, 22px);
    font-weight: 500;
    line-height: 1.08;
    letter-spacing: .1em;
    color: rgba(255, 255, 255, .85);
}
.kv-sub .vb-head .vb-line { margin-top: 12px; }
/* 按鈕列：群組本身不接滑鼠，這裡開回來；overflow 放開（按鈕的浮起與散開的點不能被切） */
.kv-lead {
    margin-top: clamp(18px, 2.4vh, 28px);
    padding: 0;
    overflow: visible;
    letter-spacing: 0;
    pointer-events: auto;
}
/* 文案淡掉之後按鈕要一起失效（複審 F1／F5）：opacity 0 擋不住命中測試，Tab 也還停得到。
   js/index2-brand-reveal.js 在文案透明度 < .35 時掛 body.index2-copy-off。
   不能用 display:none —— hero3d 的 layoutLogo 要量文案群組的框。 */
.index2-copy-off .kv-title-cluster .kv-lead { visibility: hidden; pointer-events: none; }
/* 按鈕：底色、字色、padding、圓角、字距、字級照原版。行高寫死 1.5：原版是 Poppins 的 line-height:normal（≈1.5），
   Jost 的 normal 比較矮（≈1.45），不寫死的話按鈕會矮約 1px。 */
.kv-cta {
    display: inline-flex;
    align-items: center;
    padding: 1.05em 1.5em;
    border-radius: 3px;
    background: var(--vb-cta-bg, #76c5af);          /* 品牌薄荷（跟 LANGUAGE 按鈕同色；預設值跟 js/index2-vb.js 的 style.ctaBg 一起改） */
    color: var(--vb-cta-ink, #ffffff);
    font-family: 'Jost', sans-serif;
    font-size: clamp(11px, .8vw, 14px);
    font-weight: 600;
    line-height: 1.5;
    letter-spacing: .12em;
    text-transform: uppercase;
    text-decoration: none;
    transition: background-color .25s ease, transform .25s ease;
}
.kv-cta:hover { background: var(--vb-cta-hover, #63b89f); transform: translateY(-2px); }
.kv-cta:focus-visible { outline: 2px solid #fff; outline-offset: 3px; }
/* 按鈕／「跳過片頭」把焦點移到 SOLUTIONS（js/index2-boot.js 的 __goSolutions）：
   那是一整段很高的跑道，程式移過去的焦點不需要畫框（鍵盤接下來 Tab 到的按鈕自己有框） */
#energy-applications:focus { outline: none; }

/* ── 大標逐字：亂序浮現，部分字多閃一下（.vb-char 的 opacity:0 只在 JS 切好字之後才存在） ── */
.vb-head .vb-line { display: block; }
.vb-head .vb-word { display: inline-block; }
.vb-head .vb-char { display: inline-block; opacity: 0; }
.vb-head.is-inview .vb-char {
    animation: vb-char .25s ease both;
    animation-delay: calc(var(--vb-base, 0) * .25s + var(--i, 0) * .04s + .35s);
}
.vb-head.is-inview .vb-char.is-blink { animation-name: vb-char-blink; }
@keyframes vb-char { 0% { opacity: 0; } 20% { opacity: 1; } 100% { opacity: 1; } }
@keyframes vb-char-blink { 0% { opacity: 0; } 20% { opacity: 1; } 40% { opacity: 0; } 60% { opacity: 1; } 100% { opacity: 1; } }

/* ── 等寬小標：原字隱形佔位、亂碼那份疊上去（跑動畫時版面一個像素都不跳） ──
   display:block、字距 .14em 照原版（原版 .vb-mono 就是 block；外層 p 是置中群組裡的 fit-content，寬度一樣貼字）。
   原字用 opacity:0 藏、不用 visibility:hidden：佔位一樣，但原字留在無障礙樹裡 ——
   報讀器念的是「Recharge Power · The Platform」，亂碼層 .vb-clone 由 JS 掛 aria-hidden（複審 F3）。 */
.vb-mono {
    position: relative;
    display: block;
    font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
    letter-spacing: .14em;
    text-transform: uppercase;
    white-space: pre-line;
}
.vb-mono .vb-orig { opacity: 0; }
.vb-mono .vb-clone { position: absolute; inset: 0; overflow: visible; white-space: pre; }
.vb-mono.is-typing .vb-clone::after {
    content: '';
    display: inline-block;
    width: .45em;
    height: .8em;
    background-color: currentColor;
    animation: vb-cursor .5s ease infinite;
    vertical-align: -.05em;
}
@keyframes vb-cursor { 50% { opacity: 0; } }

/* ── 按鈕右側的點：四顆沿各自的軸彈出再收回、中心那顆閃爍、整組轉 90° ── */
.vb-cta { --vb-dur: 2s; gap: 0; }
.vb-dots {
    position: relative;
    width: .25em;
    height: .25em;
    margin-left: 3em;
    animation: vb-btn-rotate calc(var(--vb-dur) * 2) cubic-bezier(.77, 0, .175, 1) infinite;
    animation-delay: calc(var(--vb-dur) * .2);
}
.vb-dot { top: 0; left: 0; display: block; width: 100%; height: 100%; }
.vb-dot::before { content: ''; position: absolute; inset: 0; background-color: currentColor; border-radius: 100%; }
.vb-dot-s { --r: calc(var(--i) * 90deg); position: absolute; transform: rotate(var(--r)); }
.vb-dot-s::before {
    --offset: 220%;
    opacity: 0;
    transform: translateY(0);
    animation: vb-btn-spread calc(var(--vb-dur) * 2) cubic-bezier(.77, 0, .175, 1) infinite;
    animation-delay: calc(var(--vb-dur) * .1 + .05s * var(--i));
}
.vb-dot-s:nth-child(1) { --i: 1; }
.vb-dot-s:nth-child(2) { --i: 2; }
.vb-dot-s:nth-child(3) { --i: 3; }
.vb-dot-s:nth-child(4) { --i: 4; }
.vb-dot-c::before { animation: vb-btn-blink var(--vb-dur) infinite; }
@keyframes vb-btn-spread {
    0% { opacity: 0; transform: translateY(0); }
    40% { opacity: 0; transform: translateY(0); }
    50% { opacity: 1; transform: translateY(var(--offset)); }
    90% { opacity: 1; transform: translateY(var(--offset)); }
    100% { opacity: 0; transform: translateY(0); }
}
@keyframes vb-btn-blink { 84% { opacity: 1; } 88% { opacity: 0; } 92% { opacity: 1; } 96% { opacity: 0; } 100% { opacity: 1; } }
@keyframes vb-btn-rotate { 0% { transform: rotate(-90deg); } 38% { transform: rotate(-90deg); } 50% { transform: rotate(0deg); } 88% { transform: rotate(0deg); } 100% { transform: rotate(90deg); } }

/* 分頁不在前景時停掉按鈕的循環動畫 */
.index2-motion-paused .vb-dots, .index2-motion-paused .vb-dot::before { animation-play-state: paused; }

@media (max-width: 700px) {
    /* 小標：原版 ≤700px 是 9px（調參面板的字級只管桌機） */
    .kv-eyebrow { font-size: 9px; }
    .kv-wordmark { font-size: clamp(22px, 6.4vw, 34px); line-height: 1.15; letter-spacing: -.012em; padding-left: 0; }
    /* 中文行的字級照原版 inline 樣式 clamp(16px, 1.3vw, 22px)，手機也是 16px（寫在上面的 .kv-sub .vb-head） */
    .kv-cta { padding: .95em 1.25em; }
    .vb-dots { margin-left: 1.8em; }
}
/* 矮的橫式視窗（筆電縮小的視窗）：照原版把大標縮一級、按鈕上距收一點 */
@media (min-width: 701px) and (max-height: 720px) {
    .kv-wordmark { font-size: clamp(30px, 3.35vw, 58px); }
    .kv-lead { margin-top: 15px; }
}
/* reduce：不逐字、不閃，直接顯示；點也不轉。
   四顆側點停在「散開」的位置（--offset 寫在 .vb-dot-s::before 上，配合 .vb-dot-s 各自的 rotate），
   靜態時看得到十字四點＋中心點，不會全疊在中間只剩一顆（複審 F7）。 */
@media (prefers-reduced-motion: reduce) {
    .vb-head .vb-char { opacity: 1 !important; animation: none !important; }
    .vb-dots, .vb-dot-s::before, .vb-dot-c::before { animation: none !important; }
    .vb-dot-s::before { opacity: 1; transform: translateY(var(--offset)); }
}

/* ── 手機精簡模式（<html class="rp-lite">，index2.html <head> 依螢幕決定；?lite=1／0 可強制）────────────
   圓盤段只留中央小地球（js/index2-kv.js 的 haloEl 分支不建四周裝飾，只把 .kv-core 淡入淡出）：
   文字圈、照片扇形、軸線、儀表的 SVG 都不顯示。節點不刪 —— .kv-core 本身與 .kv-portal（洞緣）照常用。
   洞緣只留細線：外側刻度環與釋放震波是裝飾，不畫。 */
html.rp-lite :is(.kv-halo, .kv-wedges, .kv-axis) { display: none; }
html.rp-lite .kv-core .ring-wrapper > svg { display: none; }
html.rp-lite :is(.kv-hole-ticks, .kv-hole-wave) { display: none; }
