/* ═══════════════════════════════════════════════════════════════════════════
   Global Footprint ── index2.html 的 .pulse-band.gf（地球＋數字區塊）
   動態在 js/global-footprint.js，可調參數在 js/global-footprint.config.js。
   字體：英文一律 Jost；中文由同一個字體堆疊退到 Noto Sans TC（Jost 沒有中文字形）。

   圖層（由下到上）
     1 .gf-map      world.svg 世界地圖（淺色、半透明）
     2 .gf-texture  bg.webp 材質（原檔自帶 3% 不透明度，這裡用 opacity 還原）
     3 .gf-pins     台灣／日本／澳洲節點（跟地圖同一個框，一起縮放／平移）
     4 .gf-rail / .gf-orbit  中軸線、地球外的軌道圈
     5 .gf-copy / .gf-stats  左文案、右數據
     6 .gf-canvas   3D 地球（大地球階段會蓋在文字上，參考稿一）
   ═══════════════════════════════════════════════════════════════════════════ */
.pulse-band.gf {
    --gf-bg: #92a1b0;
    --gf-ink: #fff;
    --gf-ink-soft: rgba(255, 255, 255, .86);
    --gf-line: rgba(255, 255, 255, .45);
    --gf-mint: #8fdcc0;
    --gf-font: 'Jost', 'Noto Sans TC', 'PingFang TC', 'Microsoft JhengHei', sans-serif;
    /* 區塊總長：釘住的 100vh ＋ 主動畫（這裡 300vh）＋ 交棒給下一段的最後 100vh */
    --gf-length: 500vh;
    --gf-rail-x: 50%;
    --gf-pad-x: clamp(28px, 9.2vw, 190px);
    --gf-map-opacity: .3;
    --gf-texture-opacity: .0314;      /* bg.webp 原檔 alpha 8/255 */
    /* 尺寸 × 倍率（倍率由調參面板寫；預設 1） */
    --gf-node-size: calc(clamp(46px, 4vw, 84px) * var(--gf-node-scale, 1));
    --gf-deco-lg: calc(clamp(36px, 5.4vh, 64px) * var(--gf-deco-scale, 1));
    --gf-deco-sm: calc(clamp(12px, 1.9vh, 22px) * var(--gf-deco-scale, 1));
    height: var(--gf-length);
}
/* 底色換成設計稿的灰藍；原本的礦物紙紋（::before）這段不用 */
.pulse-band.gf .pulse-inner {
    display: block;
    background: var(--gf-bg);
}
.pulse-band.gf .pulse-inner::before { content: none; }

.gf-scene {
    position: absolute;
    inset: 0;
    overflow: hidden;
    color: var(--gf-ink);
    font-family: var(--gf-font);
    -webkit-font-smoothing: antialiased;
}
.gf-scene p, .gf-scene h2, .gf-scene h3, .gf-scene ul { margin: 0; }

/* ── 1–3 背景：地圖／材質／節點 ────────────────────────────── */
.gf-map, .gf-pins {
    position: absolute;
    left: 0;
    top: 0;
    /* 位置與尺寸由 JS（layoutMap）依 config.map 寫入；transform 由時間軸動 */
    will-change: transform;
    pointer-events: none;
}
/* 背景三層（地圖／材質／節點）的包裹層：交棒時整組淡出；本身不設 z-index，裡面三層的順序不變 */
.gf-bg { position: absolute; inset: 0; }
.gf-map { z-index: 1; }
.gf-map-img {
    display: block;
    width: 100%;
    height: 100%;
    opacity: var(--gf-map-opacity);
    user-select: none;
    -webkit-user-drag: none;
}
.gf-texture {
    position: absolute;
    inset: 0;
    z-index: 2;
    background: url('../images/global-footprint/gf-texture.webp') center / cover no-repeat;
    opacity: var(--gf-texture-opacity);
    pointer-events: none;
}
.gf-pins { z-index: 3; }
.gf-node {
    position: absolute;
    width: 0;
    height: 0;
}
.gf-node > i {
    position: absolute;
    left: 0;
    top: 0;
    border-radius: 50%;
    transform: translate(-50%, -50%);
}
/* 平面節點（參考稿二）：半透明薄荷圓盤＋細環＋實心點。
   「優雅閃爍」（使用者要求，跑時間、不跟捲動）：光暈慢慢呼吸，細環從中心向外擴散淡出；
   三個節點用 --gf-node-i 錯開相位，不會同時亮。節奏與幅度都是變數（config.style.twinkle）。 */
.gf-node-halo {
    width: var(--gf-node-size);
    height: var(--gf-node-size);
    background: var(--gf-node-halo, rgba(163, 226, 204, .42));
    animation: gf-halo-breathe var(--gf-twinkle, 4.2s) ease-in-out infinite;
    animation-delay: calc(var(--gf-node-i, 0) * var(--gf-twinkle-offset, 1.4s) * -1);
}
.gf-node::before {
    content: '';
    position: absolute;
    left: 0;
    top: 0;
    width: var(--gf-node-size);
    height: var(--gf-node-size);
    border: 1px solid var(--gf-ripple-color, #fff);
    border-radius: 50%;
    opacity: 0;
    transform: translate(-50%, -50%) scale(.32);
    pointer-events: none;
    animation: gf-ripple var(--gf-twinkle, 4.2s) cubic-bezier(.2, .65, .3, 1) infinite;
    animation-delay: calc(var(--gf-node-i, 0) * var(--gf-twinkle-offset, 1.4s) * -1);
}
@keyframes gf-halo-breathe {
    0%, 100% { transform: translate(-50%, -50%) scale(var(--gf-halo-min, .86)); opacity: var(--gf-halo-dim, .55); }
    50% { transform: translate(-50%, -50%) scale(var(--gf-halo-max, 1.06)); opacity: var(--gf-halo-bright, 1); }
}
@keyframes gf-ripple {
    0% { transform: translate(-50%, -50%) scale(.32); opacity: 0; }
    10% { opacity: var(--gf-ripple-alpha, .55); }
    62%, 100% { transform: translate(-50%, -50%) scale(var(--gf-ripple, 1.55)); opacity: 0; }
}
/* 區塊不在附近（JS 拿掉 .is-live）就暫停，不空轉 */
.pulse-band.gf:not(.is-live) .gf-node-halo,
.pulse-band.gf:not(.is-live) .gf-node::before { animation-play-state: paused; }
/* 面板改了閃爍節奏時重新起跑（JS 掛一幀） */
.pulse-band.gf.gf-restart .gf-node-halo,
.pulse-band.gf.gf-restart .gf-node::before { animation: none; }
.gf-node-ring {
    width: calc(var(--gf-node-size) * .46);
    height: calc(var(--gf-node-size) * .46);
    border: 1px solid var(--gf-node-ring, rgba(255, 255, 255, .55));
    background: var(--gf-node-ring-fill, rgba(173, 232, 211, .28));
    transition: transform .35s cubic-bezier(.22, .61, .36, 1), border-color .35s;
}
.gf-node-dot {
    width: 7px;
    height: 7px;
    background: var(--gf-node-dot, #6fd3ae);
    box-shadow: 0 0 0 2px var(--gf-node-ring, rgba(255, 255, 255, .55));
}
.gf-node.is-hot .gf-node-ring {
    transform: translate(-50%, -50%) scale(1.45);
    border-color: #fff;
}

/* ── 4 中軸線與軌道圈 ──────────────────────────────────────── */
.gf-rail {
    position: absolute;
    top: 0;
    bottom: 0;
    left: var(--gf-rail-x);
    width: 0;
    z-index: 4;
    pointer-events: none;
}
.gf-rail-line {
    position: absolute;
    top: 0;
    bottom: 0;
    left: -.5px;
    width: 1px;
    background: var(--gf-line);
    transform-origin: 50% 50%;
}
.gf-deco {
    position: absolute;
    left: 0;
    top: 0;
    width: 0;
    height: 0;
}
/* 平面薄荷圓點（參考稿三）：大圓約地球直徑的 1/3，小點約 1/8；位置由 JS 寫 translate */
.gf-deco > i {
    position: absolute;
    left: 0;
    top: 0;
    width: var(--gf-deco-sm);
    height: var(--gf-deco-sm);
    /* 用負邊界置中（不用 transform）：進場的 scale 由 GSAP 寫 transform，兩者才不互搶 */
    margin: calc(var(--gf-deco-sm) / -2) 0 0 calc(var(--gf-deco-sm) / -2);
    border-radius: 50%;
    background: var(--gf-deco, rgba(170, 224, 205, .85));
}
.gf-deco.is-large > i {
    width: var(--gf-deco-lg);
    height: var(--gf-deco-lg);
    margin: calc(var(--gf-deco-lg) / -2) 0 0 calc(var(--gf-deco-lg) / -2);
    background: var(--gf-deco-lg-color, rgba(170, 224, 205, .78));
}
.gf-orbit {
    position: absolute;
    left: 0;
    top: 0;
    width: 200px;
    height: 200px;
    margin: -100px 0 0 -100px;
    z-index: 4;
    overflow: visible;
    pointer-events: none;
    transform-origin: 50% 50%;
}
.gf-orbit circle {
    fill: none;
    vector-effect: non-scaling-stroke;
}
.gf-ring-solid { stroke: var(--gf-ring-solid, rgba(255, 255, 255, .62)); stroke-width: var(--gf-ring-solid-w, 1); stroke-dasharray: 1; }
.gf-ring-dots {
    stroke: var(--gf-ring-dots, rgba(255, 255, 255, .8));
    stroke-width: var(--gf-ring-dots-w, 2);
    stroke-linecap: round;
    stroke-dasharray: .0001 var(--gf-ring-dots-gap, .0125);
}

/* ── 5 左側文案 ───────────────────────────────────────────── */
.gf-copy {
    position: absolute;
    z-index: 5;
    left: var(--gf-pad-x);
    top: 50%;
    /* 右緣停在地球左邊（地球半徑 ≈ 8.25vh）再留 32px：中等寬度時文字不會跑進地球底下 */
    width: min(36vw, 600px, calc(50vw - var(--gf-pad-x) - 8.25vh - 32px));
    transform: translateY(-50%);
    pointer-events: none;
}
.gf-kicker {
    font-size: clamp(12px, .78vw, 15px);
    font-weight: 400;
    letter-spacing: .03em;
    line-height: 1;
    margin-bottom: 1em !important;
}
.gf-title {
    font-size: calc(clamp(40px, 3.4vw, 72px) * var(--gf-title-scale, 1));
    font-weight: 500;
    line-height: 1.1;
    letter-spacing: .005em;
}
.gf-line {
    display: block;
    overflow: hidden;
    /* 遮罩多留一點下緣，g／p 的下伸部不會被切 */
    padding-bottom: .06em;
    margin-bottom: -.06em;
}
.gf-line > span { display: block; }
.gf-subtitle {
    display: flex;
    align-items: center;
    gap: .7em;
    margin: 1.5em 0 1.05em !important;
    font-size: clamp(17px, 1.15vw, 24px);
    font-weight: 500;
    letter-spacing: .14em;
    line-height: 1;
}
.gf-bar {
    display: block;
    width: .36em;
    height: 1.1em;
    background: var(--gf-mint);
    transform-origin: 50% 100%;
}
.gf-lede {
    font-size: clamp(13px, .8vw, 16px);
    line-height: 1.95;
    letter-spacing: .06em;
    color: var(--gf-ink-soft);
    margin-bottom: 2.1em !important;
}
.gf-markets {
    list-style: none;
    padding: 0;
    width: clamp(200px, 13vw, 280px);
    margin-bottom: 3.4em !important;
}
.gf-market {
    position: relative;
    display: flex;
    align-items: center;
    justify-content: space-between;
    width: 100%;
    height: clamp(42px, 2.65vw, 56px);
    padding: 0 .2em;
    border: 0;
    background: none;
    color: inherit;
    font-family: var(--gf-font);
    font-size: clamp(13px, .82vw, 16px);
    font-weight: 400;
    letter-spacing: .05em;
    cursor: default;
    pointer-events: auto;
}
.gf-market svg { width: 12px; height: 12px; color: var(--gf-mint); transition: transform .3s cubic-bezier(.22, .61, .36, 1); }
.gf-market:hover svg { transform: translateX(4px); }
.gf-market-line {
    position: absolute;
    left: 0;
    right: 0;
    bottom: 0;
    height: 1px;
    background: var(--gf-market-line, rgba(255, 255, 255, .42));
    transform-origin: 0 50%;
}
.gf-cta {
    display: inline-flex;
    align-items: center;
    justify-content: space-between;
    width: clamp(200px, 12.4vw, 262px);
    height: clamp(52px, 3.3vw, 68px);
    padding: 0 1.5em;
    background: var(--gf-cta, #3a3a3a);
    color: #fff;
    font-family: var(--gf-font);
    font-size: clamp(12px, .74vw, 14px);
    font-weight: 500;
    letter-spacing: .1em;
    text-decoration: none;
    pointer-events: auto;
    transition: background-color .3s;
}
.gf-cta svg { width: 12px; height: 12px; color: var(--gf-mint); }
.gf-cta:hover, .gf-cta:focus-visible { background: var(--gf-cta-hover, #262626); }
.gf-cta:focus-visible { outline: 1px solid #fff; outline-offset: 3px; }

/* ── 5 右側數據：三組直排、全亮（設計稿）。捲到觸發點才浮上＋數字跑動（時間動畫，不跟捲軸） ── */
.gf-stats {
    position: absolute;
    top: 0;
    bottom: 0;
    left: var(--gf-rail-x);
    right: 0;
    z-index: 5;
    display: grid;
    grid-template-rows: repeat(3, 1fr);
    pointer-events: none;
}
.gf-stat {
    position: relative;
    display: flex;
    align-items: center;
    /* 左側留白至少要讓字從地球右緣之後開始（地球半徑 ≈ 8.25vh） */
    padding: 0 var(--gf-pad-x) 0 max(clamp(48px, 6.4vw, 140px), calc(8.25vh + 26px));
}
.gf-stat-rule {
    position: absolute;
    left: 0;
    right: 0;
    top: 0;
    height: 1px;
    background: var(--gf-line);
    transform-origin: 0 50%;
    /* 交棒退場：從右往左收回中軸（--gf-rule-out 由 JS 寫在 .gf-stats 上；進場的 scaleX 是 GSAP，兩者分開） */
    clip-path: inset(0 calc(var(--gf-rule-out, 0) * 100%) 0 0);
}
.gf-stat-en {
    font-size: clamp(11px, .74vw, 14px);
    font-weight: 400;
    letter-spacing: .02em;
    line-height: 1.3;
    text-transform: uppercase;
}
.gf-stat-zh {
    margin: .45em 0 .7em !important;
    font-size: clamp(14px, .9vw, 18px);
    font-weight: 500;
    letter-spacing: .08em;
    line-height: 1.4;
}
.gf-stat-figure {
    display: flex;
    align-items: baseline;
    gap: clamp(10px, 1.1vw, 22px);
}
.gf-stat-num {
    font-size: calc(clamp(46px, 3.9vw, 84px) * var(--gf-num-scale, 1));
    font-weight: 500;
    line-height: 1;
    letter-spacing: .01em;
    font-variant-numeric: tabular-nums;
}
.gf-stat-unit {
    font-size: clamp(12px, .8vw, 16px);
    font-weight: 400;
    letter-spacing: .04em;
    color: var(--gf-ink-soft);
}
.gf-stat-unit.is-strong { font-weight: 500; color: var(--gf-ink); }
.gf-stat-desc {
    margin-top: 1.05em !important;
    max-width: 34em;
    /* 中文只在標點處換行（不會把「精準」拆到兩行），行長再平衡一下 */
    word-break: keep-all;
    overflow-wrap: anywhere;
    text-wrap: balance;
    font-size: clamp(12px, .8vw, 15px);
    line-height: 1.85;
    letter-spacing: .06em;
    color: var(--gf-ink-soft);
}

/* ── 6 3D 地球 ────────────────────────────────────────────── */
.gf-canvas {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    z-index: 6;
    display: block;
    pointer-events: none;
}

/* ── 中等寬度：收一點字級 ─────────────────────────────────── */
@media (max-width: 1200px) {
    .gf-copy { width: min(38vw, calc(50vw - var(--gf-pad-x) - 8.25vh - 32px)); }
    /* 數據欄的字從地球右緣之後才開始（地球半徑 ≈ 8.25vh） */
    .gf-stat { padding-left: max(4vw, calc(8.25vh + 26px)); }
}
/* ── 窄幅（先做桌機；這裡只確保不跑版）：文案在上、地球在中、數據一次一組在下 ── */
@media (max-width: 900px) {
    .pulse-band.gf { --gf-pad-x: 22px; --gf-node-size: calc(40px * var(--gf-node-scale, 1)); }
    .gf-copy { top: 10svh; width: auto; right: 22px; transform: none; }
    .gf-title { font-size: 34px; }
    .gf-subtitle { margin: 1em 0 0 !important; font-size: 16px; }
    .gf-lede, .gf-markets, .gf-cta { display: none; }
    .gf-rail { display: none; }
    .gf-stats { top: auto; height: 30svh; left: 0; grid-template-rows: 1fr; }
    .gf-stat { grid-area: 1 / 1; padding: 0 22px; align-items: flex-start; transition: opacity var(--gf-mobile-fade, .6s) ease; }
    /* 窄幅一次只放得下一組：捲過 mobileSwitchAt 換下一組（淡入淡出跑時間） */
    .gf-stat:not(.is-active) { opacity: 0; }
    .gf-stat-rule { display: none; }
    .gf-stat-num { font-size: 44px; }
    .gf-stat-desc { font-size: 13px; }
}
/* 減少動態：不跑長跑道，直接呈現完成的構圖（JS 同步處理） */
@media (prefers-reduced-motion: reduce) {
    .pulse-band.gf { --gf-length: 200vh; }
    .gf-node-halo, .gf-node::before { animation: none; }
    .gf-stat { transition: none; }
}

/* ── 7 開洞時的大字跑馬燈（參考影片 global presence）：蓋在 3D 地球上面 ──────────
   位置、大小、字距、顏色由 JS 依 config.marquee 寫成變數；移動只寫 transform。 */
.gf-marquee { position: absolute; inset: 0; z-index: 7; visibility: hidden; pointer-events: none; }
.gf-marquee-mask { position: absolute; left: 0; right: 0; top: var(--gf-mq-y, 48.6%); height: calc(var(--gf-mq-size, 180px) * 1.2);
    transform: translateY(-50%); overflow: hidden; }
.gf-marquee-track { display: flex; width: max-content; white-space: nowrap; will-change: transform;
    font-family: var(--gf-font); font-size: var(--gf-mq-size, 180px); font-weight: var(--gf-mq-weight, 500); line-height: 1.2;
    letter-spacing: var(--gf-mq-tracking, .1em); text-transform: uppercase; color: var(--gf-mq-color, #fff); opacity: var(--gf-mq-opacity, 1); }
.gf-marquee-track > span { display: block; padding-right: var(--gf-mq-gap, 1.1em); }
/* 夾在字中間的圖（js/global-footprint.js 的 buildMarquee 生成）。
   ⚠ 尺寸一定要由 CSS 決定（height ＋ aspect-ratio），不能等 <img> 載完才有寬度 ——
     跑馬燈是先量「一個單位多寬」再決定要複製幾份，量到 0 整條就會排錯。
   垂直用 align-self: center 對齊字的中線；字本身有 padding-right 當間隔，圖再補自己那一邊。 */
.gf-marquee-track > .gf-mq-tile {
    flex: 0 0 auto;
    align-self: center;
    height: calc(var(--gf-mq-size, 180px) * var(--gf-mq-tile-h, .62));
    aspect-ratio: var(--gf-mq-tile-ar, 1.6);
    margin-right: var(--gf-mq-gap, 1.1em);
    overflow: hidden;
    border-radius: var(--gf-mq-tile-r, 2px);
}
.gf-marquee-track > .gf-mq-tile img { display: block; width: 100%; height: 100%; object-fit: cover; }

/* 效能（2026-09-27）：交棒退場期間（js 在 .gf 掛 .is-out）這幾個容器每幀改 opacity／translate／scale ——
   升成合成層，不必每幀重畫（場景縮放原本會連整張滿版的地圖底圖一起重畫）；平常不佔合成層 */
.gf.is-out .gf-scene { will-change: scale, opacity; }
.gf.is-out .gf-copy, .gf.is-out .gf-stats { will-change: opacity, translate; }
