/* ========================================
   FONTS
   ======================================== */
@font-face {
  font-family: 'GlowSansTC';
  src: url('../fonts/GlowSansTC-Normal-Regular.woff2') format('woff2');
  font-weight: 400;
  font-style: normal;
}

@font-face {
  font-family: 'GlowSansTC';
  src: url('../fonts/GlowSansTC-Normal-Medium.woff2') format('woff2');
  font-weight: 500;
  font-style: normal;
}

@font-face {
  font-family: 'GlowSansTC';
  src: url('../fonts/GlowSansTC-Normal-Bold.woff2') format('woff2');
  font-weight: 700;
  font-style: normal;
}

@font-face {
  font-family: 'GlowSansTC';
  src: url('../fonts/GlowSansTC-Normal-Light.woff2') format('woff2');
  font-weight: 300;
  font-style: normal;
}

@font-face {
  font-family: 'GlowSansTC Condensed';
  src: url('../fonts/GlowSansTC-Condensed-Bold.woff2') format('woff2');
  font-weight: 700;
  font-style: normal;
}

@font-face {
  font-family: 'Helvetica Condensed';
  src: url('../fonts/Helvetica Condensed Bold.woff2') format('woff2');
  font-weight: 700;
  font-style: normal;
}

@font-face {
  font-family: 'Helvetica Condensed';
  src: url('../fonts/Helvetica Condensed.woff2') format('woff2');
  font-weight: 400;
  font-style: normal;
}

/* ========================================
   CUSTOM PROPERTIES
   ======================================== */
:root {
  --color-primary: #F93822;
  --color-bg: #2D333A;
  --color-text-dark: #252a36;   /* 紅底/淺底上的深色文字（比背景 --color-bg 略深） */
  --color-card: #F93822;
  --font-en: 'Helvetica Condensed', sans-serif;
  --font-zh: 'GlowSansTC', sans-serif;
  --nav-right: 160px;
  --page-padding-left: 165px;
  --back-btn-size: 55px;
  /* Reserved area on the right for the fixed nav column.
     Content rectangle = viewport width minus this. */
  --content-right-reserve: 260px;
}

/* ========================================
   RESET & BASE
   ======================================== */
*, *::before, *::after {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

/* Brand text-selection highlight — red background, dark text */
::selection {
  background: var(--color-primary);
  color: var(--color-text-dark);
}
::-moz-selection {
  background: var(--color-primary);
  color: var(--color-text-dark);
}

html {
  background: var(--color-bg);
  scroll-behavior: smooth;
  scrollbar-width: none;          /* Firefox */
}

html::-webkit-scrollbar {
  display: none;                  /* Chrome, Safari, Edge */
}

html, body {
  width: 100%;
  color: var(--color-primary);
  font-family: var(--font-zh);
  /* Block horizontal touch-pan / back-gesture. pinch-zoom stays enabled. */
  touch-action: pan-y pinch-zoom;
  overscroll-behavior-x: none;
}

/* overflow-x: hidden ONLY on body. Putting it on html breaks
   `position: sticky` (about-pin-wrap horizontal-scroll relies on it). */
body {
  overflow-x: hidden;
}

a {
  color: inherit;
  text-decoration: none;
}

/* ========================================
   RIGHT-SIDE NAVIGATION
   ======================================== */
#main-nav {
  position: fixed;
  right: var(--nav-right);
  top: 125px;
  bottom: 120px;
  z-index: 100;
  display: flex;
  flex-direction: column;
  justify-content: flex-start;
  /* 組間視覺距離 = 組內的 3 倍。注意 .nav-en/.nav-zh 的 line-height 比字高大，
     上下各多約 3px 行距留白，會同時灌進組內與組間，所以 gap 數字 ≠ 視覺距離：
       組內視覺 ≈ 3(英下) + 4(margin) + 3.7(中上) ≈ 10.7px
       組間視覺 ≈ 3.7(中下) + gap + 3(英上)
     要組間 ≈ 32px（10.7×3），gap 設 25px。 */
  gap: 25px;
  text-align: right;
}

.nav-item {
  display: block;
  transition: opacity 0.3s;
  opacity: 0.3;
  margin-bottom: 0;
}

.nav-item:hover,
.nav-item.active {
  opacity: 1;
}

.nav-en {
  display: block;
  font-family: var(--font-en);
  font-weight: 700;
  font-size: 26px;
  letter-spacing: 0.09em;
  /* max(1em, 24pt): 行盒永不小於字高（1em）→ 保證不會和下一行的中文疊到一起；
     24pt 則維持目前想要的行距。改小於 1em 也不會撞字。 */
  line-height: max(1em, 24pt);
}

.nav-zh {
  display: block;
  font-family: 'GlowSansTC Condensed', var(--font-zh);
  font-weight: 700;
  font-size: 14px;
  letter-spacing: 0.1em;
  /* 同上：行盒下限 = 1em，維持目前 16pt 行距。 */
  line-height: max(1em, 16pt);
  /* 負值會讓中文往上疊，用 max(..., 0px) 把間距下限鎖在 0，永不撞到英文。 */
  margin-top: max(4px, 0px);
}

/* ========================================
   BARCODE LOGO
   ======================================== */
#barcode-logo {
  position: fixed;
  bottom: 40px;
  right: var(--nav-right);
  z-index: 100;
  width: 114px;            /* 0.95× of the previous 120px */
  cursor: pointer;
}

#barcode-logo img {
  width: 100%;
  height: auto;
  transform-origin: center center;
  will-change: transform, filter;  /* click-to-swap shake (see js/main.js) */
}

/* JS toggles this class when the logo's bounding box overlaps the nav. */
#barcode-logo.collide-hidden {
  visibility: hidden;
}

/* Mobile top logo - hidden on desktop */
#mobile-top-logo {
  display: none;
}

/* ========================================
   VIDEO BACKGROUND
   ======================================== */
#bg-video {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  z-index: 0;
  /* Crop baked-in letterbox bars so the video looks edge-to-edge. */
  transform: scale(1.12);
}

/* Haze overlay over bg-video.
   On index.html the haze is hidden while viewing the home section and
   fades in once the user scrolls into about/artists/collab/join/contact. */
.bg-haze {
  position: fixed;
  inset: 0;
  /* 毛玻璃：深色 0.55 壓暗背景影片，剩下的遮蓋力交給高斯模糊。
     opacity 淡入淡出時 blur 也會跟著一起出現/消失。 */
  background: rgba(45, 51, 58, 0.55);
  backdrop-filter: blur(20px);
  -webkit-backdrop-filter: blur(20px);
  z-index: 1;
  pointer-events: none;
  opacity: 1;
  transition: opacity 0.4s ease;
}

body[data-active-page="home"] .bg-haze {
  opacity: 0;
}

/* ========================================
   RED GLOW (right edge)
   ======================================== */
#red-glow {
  position: fixed;
  top: 0;
  right: 0;
  width: 80px;
  height: 100%;
  background: linear-gradient(to left, rgba(249, 56, 34, 0.6), transparent);
  z-index: 50;
  pointer-events: none;
}

/* ========================================
   SCROLL SECTIONS (replaces .page)
   ======================================== */
.scroll-section {
  position: relative;
  min-height: 100vh;
  z-index: 1;
}

.page-content {
  min-height: 100vh;
  position: relative;
}

/* ========================================
   BACK BUTTON (only used in overlay)
   ======================================== */
.back-btn {
  position: absolute;
  top: var(--back-btn-size);
  left: var(--back-btn-size);
  width: var(--back-btn-size);
  height: var(--back-btn-size);
  border: none;
  background: transparent;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 10;
  padding: 0;
  transition: opacity 0.3s;
}

.back-btn img {
  width: 100%;
  height: 100%;
  object-fit: contain;
}

.back-btn:hover {
  opacity: 0.7;
}

/* ========================================
   SECTION 1: HOME
   ======================================== */
.home-content {
  height: 100vh;
  overflow: hidden;
  display: flex;
  align-items: center;
  justify-content: flex-start;
  padding-left: 120px;
}

/* Screen-reader only (for SEO) */
.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

/* Credits wrapper - masks the scroll area */
.credits-wrapper {
  width: 100%;
  max-width: 600px;
  height: 100vh;
  overflow: hidden;
  position: relative;
  z-index: 2;
  /* Fade edges */
  mask-image: linear-gradient(to bottom, transparent 0%, #000 25%, #000 75%, transparent 100%);
  -webkit-mask-image: linear-gradient(to bottom, transparent 0%, #000 25%, #000 75%, transparent 100%);
}

/* Credits scroll - duplicated content for seamless loop */
.credits-scroll {
  text-align: left;
  padding: 20px 40px;
  animation: credits-roll 30s linear infinite;
}

.credits-block {
  padding-bottom: 50vh;
}

@keyframes credits-roll {
  0% {
    transform: translateY(0);
  }
  100% {
    transform: translateY(-50%);
  }
}

.credits-scroll h3 {
  font-family: var(--font-en);
  font-weight: 700;
  font-size: 18px;
  letter-spacing: 0.5px;
  margin-bottom: 4px;
  line-height: 1.4;
}

.credits-scroll .zh {
  font-family: var(--font-zh);
  font-size: 14px;
  font-weight: 700;
  margin-bottom: 16px;
  /* 調淡改用字色 alpha 而非 opacity：opacity 會連同反白底色一起半透明，
     反白時看起來「更透」。字色帶 alpha 視覺相同，但 ::selection 可完全蓋過。
     （以下同類改動皆同此理由。） */
  color: rgba(249, 56, 34, 0.9);
}

.credits-scroll .statement {
  font-family: var(--font-en);
  font-weight: 700;
  font-size: 18px;
  margin-bottom: 4px;
}

.home-subtitle {
  font-size: 16px;
  font-style: normal;
  font-weight: 700;
  margin-bottom: 4px;
}

.home-subtitle-zh {
  font-size: 14px;
  font-weight: 700;
  margin-bottom: 16px;
}

.home-tagline {
  font-size: 16px;
  font-style: normal;
  font-weight: 700;
  color: rgba(249, 56, 34, 0.85);
  margin-top: 8px;
}

.home-tagline-zh {
  font-family: var(--font-zh);
  font-size: 14px;
  font-weight: 700;
  color: rgba(249, 56, 34, 0.85);
  margin-top: 4px;
}

.credits-scroll br {
  display: block;
  margin-top: 20px;
}

/* ========================================
   SECTION 2: ABOUT
   ======================================== */
.about-content {
  height: auto;
  min-height: 100vh;
  overflow: visible;
  display: block;
  padding: 0;
}

.about-panel {
  position: relative;
  width: 100%;
  min-height: 100vh;
  box-sizing: border-box;
  overflow: hidden;
}

/* ============================================================
   Desktop horizontal-scroll for About panels 1-9.
   The pin-wrap is 9 × 100vh tall (drives total scroll length);
   inside it the sticky element pins for the duration; the track
   inside is laid out as a horizontal flex row of 9 panels and
   gets translated by JS based on scroll progress.
   Panels 10-13 (STRUCTURE) live OUTSIDE the pin-wrap inside
   .about-vertical and scroll normally as full-height sections.
   Mobile/tablet resets all of this to a normal vertical block flow.
   ============================================================ */
@media (min-width: 1025px) {
  .about-pin-wrap {
    position: relative;
    height: 900vh; /* 9 panels × 100vh of vertical scroll */
  }
  .about-sticky {
    position: sticky;
    top: 0;
    height: 100vh;
    overflow: hidden;
    /* Fade the right edge so content sliding in from the right appears to be
       partially veiled by the right-side nav (which sits over this column).
       Fade region is pulled right (less coverage on the left of the nav)
       and ends near the nav's left edge (~viewport-280).
       實際的漸層與 .structure-sticky 共用一條規則，見本 media query 末尾。 */
  }
  .about-track {
    display: flex;
    flex-direction: row;
    height: 100vh;
    width: 900vw; /* 9 panels × 100vw */
    will-change: transform;
  }
  /* Panels 10-13 — vertical full-height sections after the pin-wrap */
  .about-vertical > .about-panel {
    width: 100%;
    min-height: 100vh;
    height: 100vh;
  }
  /* Panel 10 (STRUCTURE intro) — exactly 100vh. It used to be 150vh, which put
     its centered snap stop 25vh into the block and so made BOTH neighbouring
     wheel steps 125vh (1.25 screens) instead of one clean screen. At 100vh every
     step in the STRUCTURE range is exactly one viewport. The centered-title dwell
     that the extra 50vh used to buy now comes from PIN_LEAD in js/main.js. */
  .about-vertical > .panel-structure-intro {
    height: 100vh;
    min-height: 100vh;
  }
  .about-track > .about-panel {
    flex: 0 0 100vw;
    width: 100vw;
    min-height: 100vh;
    height: 100vh;
  }

  /* ── STRUCTURE cards (Panels 11/12/13) — pinned cross-fade + text slide ──
     300vh of vertical scroll inside the wrap drives the run, but the cards no
     longer travel: all three are stacked on the SAME 100vw × 100vh screen and
     JS gives each a --p (-1 = 還沒進場、0 = 置中、+1 = 已離場).
       圖示：原地淡入淡出（--icon-opacity），完全不位移。
       文字：吃 --p 從右往左滑進來（見下方 .panel-text 的 transform）。
     The title is NOT part of the stack — it stays pinned at the top for the
     whole run (see #structure-title / PIN_LEAD in js/main.js). */
  .structure-pin-wrap {
    position: relative;
    height: 300vh; /* 3 cards × 100vh of vertical scroll */
  }
  .structure-sticky {
    position: sticky;
    top: 0;
    height: 100vh;
    overflow: hidden;
  }
  .structure-stack {
    display: block;
    position: relative;
    height: 100vh;
    width: 100vw;
  }
  .structure-stack > .about-panel {
    /* 三張卡疊在同一格 —— 不再是 300vw 的橫向 flex row。 */
    position: absolute;
    inset: 0;
    width: 100vw;
    min-height: 100vh;
    height: 100vh;
    /* 文字會滑到卡片框外（最多 ±100vw），所以卡片本身不能裁切；
       裁切交給 .structure-sticky 的 overflow + 右側遮罩。 */
    overflow: visible;
    /* 三張卡互相重疊，最上層那張會擋住下面可見卡片的文字選取。
       卡片本身不收事件，只有 JS 判定「目前可見」的那段文字把
       pointer-events 收回來（--text-pe，見 .panel-text）。 */
    pointer-events: none;
  }

  /* 右側邊欄遮罩 —— 與 .about-sticky 同一條漸層：從右側滑進來的文字在
     nav 覆蓋的範圍內逐漸透明，看起來像是被邊欄擋住，而不是硬生生冒出來。 */
  .about-sticky,
  .structure-sticky {
    -webkit-mask-image: linear-gradient(
      to right,
      black 0%,
      black calc(100% - clamp(300px, 22vw, 460px)),
      transparent calc(100% - 240px),
      transparent 100%
    );
    mask-image: linear-gradient(
      to right,
      black 0%,
      black calc(100% - clamp(300px, 22vw, 460px)),
      transparent calc(100% - 240px),
      transparent 100%
    );
  }
}

@media (max-width: 1024px) {
  /* On mobile/tablet, the wrapper divs are transparent — panels stack vertically as before. */
  .about-pin-wrap,
  .about-sticky,
  .about-track,
  .about-vertical,
  .structure-pin-wrap,
  .structure-sticky,
  .structure-stack {
    display: contents;
  }
  /* On mobile there is no right-side nav strip — center on full viewport
     and offset top for the mobile top-logo bar (~70px). !important wins
     over the desktop rules that come later in source order. */
  .structure-title-element.is-centered {
    left: 50% !important;
  }
  .structure-title-element.is-pinned {
    top: 90px !important;
    left: 50% !important;
  }
  .structure-title-element.is-hidden.was-pinned {
    top: 90px !important;
    left: 50% !important;
  }
  .structure-title-element.is-hidden.was-centered {
    left: 50% !important;
  }
}

.panel-inner {
  position: relative;
  width: 100%;
  height: 100%;
  min-height: 100vh;
}

/* All panels visible now; initial positions below, fine-tune via edit mode (press E) */
.panel-inner img {
  display: block;
  position: absolute;
  pointer-events: auto;
  user-select: none;
}

/* Part 1: Text-only panels (Core Mission, Journey, Structure Intro)
   Positioned at the center of the content rectangle (viewport minus right nav). */
.panel-mission .panel-text,
.panel-journey-intro .panel-text,
.panel-structure-intro .panel-text {
  position: absolute;
  top: 50%;
  left: calc((100vw - var(--content-right-reserve)) / 2);
  transform: translate(-50%, -50%);
  text-align: center;
  width: min(520px, 45vw);
}

/* ============================================================
   Graphic-based panels: centered stage with ref aspect ratio.
   ============================================================ */
.panel-stage,
.panel-collab-intro,
.panel-integrate,
.panel-believe,
.panel-part-1,
.panel-part-2,
.panel-part-3,
.panel-structure-a,
.panel-structure-b,
.panel-structure-c {
  display: flex;
  align-items: center;
  justify-content: center;
}

.panel-stage .panel-inner,
.panel-collab-intro .panel-inner,
.panel-integrate .panel-inner,
.panel-believe .panel-inner,
.panel-part-1 .panel-inner,
.panel-part-2 .panel-inner,
.panel-part-3 .panel-inner,
.panel-structure-a .panel-inner,
.panel-structure-b .panel-inner,
.panel-structure-c .panel-inner {
  position: relative;
  /* 80vh (was 85vh) leaves 10vh top + 10vh bottom padding inside the 100vh
     panel — enough headroom for the largest negative-top graphic
     (Panel 9 .g-d03 at top: -8.86% × 80vh = 7.09vh, < 10vh padding). */
  width: min(90vw, calc(80vh * 3000 / 2133));
  aspect-ratio: 3000 / 2133;
  /* Override base `.panel-inner { height: 100% }` so aspect-ratio actually
     drives the height. Without this, the inner becomes 100vh tall (full
     parent height) and aspect-ratio is ignored, stretching the composition
     vertically — most visible in horizontal-scroll mode where the parent
     is forced to exactly 100vh. */
  height: auto;
  min-height: 0;
}

/* The STRUCTURE cards' text and icons are absolutely positioned, and every
   tuned left/top they use is viewport-relative ((100vw − nav-reserve)/2, 50vw,
   60vh …) — those only resolve correctly against the full-width CARD. Left as
   `relative`, .panel-inner (a min(90vw, 80vh×aspect) sizing box — ~1012px
   inside a 1440px card) becomes their containing block instead and shifts the
   whole composition right by half the leftover space: 214px at 1440×900.
   This block MUST stay AFTER the rule above — identical specificity, so source
   order is what decides the winner. Mobile deliberately keeps `relative`: its
   .panel-text is positioned at 50%/55% OF the inner box. */
@media (min-width: 1025px) {
  .panel-structure-a .panel-inner,
  .panel-structure-b .panel-inner,
  .panel-structure-c .panel-inner {
    position: static;
  }
}

/* Panel 2 specific: overall 1.2× scale of the already-tuned composition */
.panel-stage .panel-inner {
  transform: scale(1.2);
  transform-origin: center center;
}

/* Composition: 4 material pieces, each used once.
   a_01 = LEFT, a_02 = CENTER, a_03 = RIGHT, a_04 = BOTTOM
   Center is 29.93% wide (0.95× previous 31.5%).
   Sides flush against center (visible red edges touch the cone's edges).
   a_04 width = 1.1× center's visible base width.
   Side bases align with center's base. */
/* Panel 2 — composition: 4 material pieces. a_01 LEFT, a_02 CENTER, a_03 RIGHT, a_04 BOTTOM. */
/* Panel 2 graphics — moved down +6.56% to follow text shift.
   Text used to render with center at 52% (translateY(-50%)), so visual top
   was at ~43.65% (52 − text_height/2 where 4-line text ≈ 16.7% of inner_h).
   Now text top is directly at 50.21% → text shifted DOWN by 6.56%. */
.panel-stage .g-a01 { left: 30%;    top: 17.56%; width: 24%;    z-index: 2; }
.panel-stage .g-a02 { left: 35.04%; top: 11.56%; width: 29.93%; z-index: 3; }
.panel-stage .g-a03 { left: 45.9%;  top: 17.56%; width: 24%;    z-index: 2; }
.panel-stage .g-a04 { left: 31.62%; top: 61.56%; width: 36.76%; z-index: 1; }

/* Panel 3 — COLLAB */
.panel-collab-intro .g-b01 { left: 9.47%;  top: 19.75%; width: 77.77%; z-index: 1; }
.panel-collab-intro .g-b02 { left: 11.84%; top: 7.46%;  width: 86.04%; z-index: 2; }
.panel-collab-intro .g-b03 { left: 41.82%; top: -3.10%; width: 58.72%; z-index: 3; }

/* Panel 4 — INTEGRATE
   c01 bottom flush to c04 top (上半圓貼齊正方形頂邊):
     c01.top = (c04.top% × inner_h − c01.height) / inner_h
            = (24.81% × 720 − 89) / 720 = 12.50%
   c02 flat-top flush to c04 top (下半圓平邊貼齊正方形頂邊):
     c02.top = c04.top% = 24.81%
   c05 top flush to c04 bottom (立方體頂邊貼齊正方形底邊):
     c05.top = c04.top% + c04.height_in_inner_h%
            = 24.81% + (33.98% × 1012/720) = 24.81% + 47.76% = 72.57% */
/* item 3: the WHOLE c-image composition (上下半圓 + 正方形 + 立方體, c01–c05)
   shifted LEFT as one group — uniform −15% from the previous rightmost layout
   (where c04 reached the inner edge at 100.05% and bled under the right nav
   reserve). All five pieces move together so the composition stays intact;
   c04's right edge now lands ≈85%, inside the content area.
   NOTE: the exact left offset still needs your visual confirmation. */
.panel-integrate .g-c01 { left: 57.84%; top: 12.50%; width: 15.23%; z-index: 3; }
.panel-integrate .g-c02 { left: 48.97%; top: 24.81%; width: 30.50%; z-index: 1; }
.panel-integrate .g-c03 { left: 47.00%; top: 36.00%; width: 10.60%; z-index: 2; }
.panel-integrate .g-c04 { left: 51.07%; top: 24.81%; width: 33.98%; z-index: 2; }
.panel-integrate .g-c05 { left: 56.53%; top: 70.30%; width: 20.10%; z-index: 4; }

/* Panel 5 — BELIEVE (same vertical alignment as Panel 4) */
.panel-believe .g-c01 { left: 63.79%; top: 12.50%; width: 15.23%; z-index: 3; }
.panel-believe .g-c02 { left: 54.56%; top: 24.81%; width: 30.50%; z-index: 1; }
.panel-believe .g-c03 { left: 49.00%; top: 36.00%; width: 10.60%; z-index: 2; }
.panel-believe .g-c04 { left: 53.07%; top: 24.81%; width: 33.98%; z-index: 2; }
.panel-believe .g-c05 { left: 61.85%; top: 70.30%; width: 20.13%; z-index: 4; }

/* Panels 7-9 — PART I/II/III */
.panel-part-1 .g-d01 { left: -10.04%; top: -12.32%; width: 132%; z-index: 1; }
.panel-part-2 .g-d02 { left: -19.23%; top: -14.87%; width: 130.91%; z-index: 1; }
/* Panel 9 d-03: visual centroid (image content centroid 41.90%, 52.32% of
   canvas) aligned to the text-block center (38.30%, 47.43% of inner).
   Width 130% — bottom tip fits within 100vh panel; top tip clipped ~57px
   on a 880px-tall viewport (acceptable since the diamond's pointy tip is
   the most-clippable part of the shape).
     left = 38.30 - 130 × 0.4190 = -16.17%
     top  = 47.43 - 130 × 0.5232 = -20.59% */
.panel-part-3 .g-d03 { left: -10.67%; top: -10%; width: 119%; z-index: 1; }

/* Shared positioning context — left/top/width are tuned per-panel below */
.panel-collab-intro .panel-text,
.panel-integrate .panel-text,
.panel-believe .panel-text,
.panel-part-1 .panel-text,
.panel-part-2 .panel-text,
.panel-part-3 .panel-text {
  position: absolute;
  z-index: 5;
}

/* Panel 3 — COLLAB text */
.panel-collab-intro .panel-text { left: 5.00%;  top: 50.21%; width: 57.11%; }
/* Panel 4 — INTEGRATE text — aligned to Panel 3 (COLLAB) position per design */
.panel-integrate .panel-text    { left: 5.00%; top: 50.21%; width: 57.11%; }
/* Panel 5 — BELIEVE text — aligned to Panel 3 (COLLAB) position per design */
.panel-believe .panel-text      { left: 5.00%; top: 50.21%; width: 57.11%; }

/* Panels 7-9 — PART I/II/III text */
.panel-part-1 .panel-text,
.panel-part-2 .panel-text,
.panel-part-3 .panel-text {
  left: 17.07%;
  width: 42.49%;
  text-align: center;
}
/* 齊頭: all three Part headings share ONE top line at every viewport.
   With position:absolute top:t inside a panel-inner of height H centered in
   the 100vh panel, the heading's absolute top = 50vh − H·(0.5 − t). Writing
   top as calc(50% − X) makes that = 50vh − X for ANY H (the 0.5·H cancels), so
   Part.III's larger (≥1080px) inner no longer floats its heading higher than
   Part.I/II. X = 0.17·H1 = 0.17·min(90vw/aspect, 80vh) = min(10.88vw, 13.6vh),
   chosen so Part.I/II stay exactly where they were (their old top:33%). */
.panel-part-1 .panel-text,
.panel-part-2 .panel-text,
.panel-part-3 .panel-text { top: calc(50% - min(10.88vw, 13.6vh)); }

/* Part.III: the TEXT stays a FIXED size — the DIAMOND (background) is what
   resizes. The clipping happened because the diamond is sized as a % of
   .panel-inner (= min(90vw, 80vh × aspect)); on short viewports the inner — and
   so the diamond — shrank below the fixed-size text, the long line wrapped and
   the concave edge clipped it. Fix: FLOOR the inner so the diamond never shrinks
   below the size that holds the fixed text. On short/narrow viewports the
   diamond's tips just clip a little more — the background gives, not the text.
   (The previous attempt scaled the font with min(90vw,80vh×…); since large 16:9
   screens are height-bound, that made the text look small even on big screens.) */
@media (min-width: 1025px) {
  .panel-part-3 .panel-inner {
    /* 1080px floor → text column (42.49%) ≈ 459px, wide enough that the long
       English line never wraps; diamond (130%) stays large enough to contain it. */
    width: max(1080px, min(90vw, calc(80vh * 3000 / 2133)));
  }
}

/* Panel 2 text: top edge at 50.21% to align with Panel 3 text top edge (齊頭) */
.panel-stage .panel-text {
  position: absolute;
  left: 23%;
  top: 50.21%;
  width: min(300px, 22vw);
  z-index: 5;
}

/* ============================================================
   Panels 11/12/13 — STRUCTURE behind WOTM (REIMAGINE/PROTECTED/SUSTAIN)
   Each has a small fixed title at the top + subheading + body text +
   decorative outline icons positioned around the text block.
   ============================================================ */

/* ONE title element for the entire STRUCTURE section (Panels 10/11/12/13).
   JS toggles between three states:
     .is-centered : Panel 10 in view  → centered in viewport
     .is-pinned   : Panels 11/12/13 in view → fixed at top of viewport
     .is-hidden   : outside structure section → opacity 0
   Smooth CSS transition morphs between centered ↔ pinned states. */
.structure-stack {
  position: relative;
}

.structure-title-element {
  position: fixed;
  z-index: 100;
  text-align: center;
  pointer-events: none;
  left: calc((100vw - var(--content-right-reserve)) / 2);
  /* Defaults match is-centered so initial frame is sane. */
  top: 50%;
  transform: translate(-50%, -50%);
  opacity: 0;
  /* Only opacity transitions on .is-hidden — position SNAPS to whichever
     "frozen" variant the JS picks, preventing a center-bound morph that
     would visually cross over Part.III. */
  transition: opacity 0.18s ease;
}

.structure-title-element .about-heading {
  margin-bottom: 0;
}

/* 標題永遠一整行：元素是 fixed、無固定寬，窄視窗時 shrink-to-fit 會把
   「STRUCTURE behind WOTM」擠成兩行。nowrap + translate 置中，超出左右對稱外溢。 */
.structure-title-element .about-heading .h-en,
.structure-title-element .about-heading .h-zh {
  white-space: nowrap;
}

/* While in is-centered or is-pinned, transition position too so the
   center ↔ top morph is smooth. */
.structure-title-element.is-centered,
.structure-title-element.is-pinned {
  transition: top 0.45s cubic-bezier(0.4, 0, 0.2, 1),
              transform 0.45s cubic-bezier(0.4, 0, 0.2, 1),
              opacity 0.25s ease;
  opacity: 1;
}

.structure-title-element.is-centered {
  top: 50%;
  transform: translate(-50%, -50%);
}

.structure-title-element.is-pinned {
  top: 40px;
  transform: translate(-50%, 0);
}

/* Hidden variants — JS picks one based on the last visible state so the
   title fades OUT in place (no morph through Part.III). */
.structure-title-element.is-hidden {
  opacity: 0;
}
.structure-title-element.is-hidden.was-centered {
  top: 50%;
  transform: translate(-50%, -50%);
}
.structure-title-element.is-hidden.was-pinned {
  top: 40px;
  transform: translate(-50%, 0);
}

/* Body text block — centered around 36% horizontally, below title.
   Opacity is driven by JS as the panel enters / exits the viewport
   (var --text-opacity), giving a fade-in / fade-out effect tied to scroll. */
.panel-structure-a .panel-text,
.panel-structure-b .panel-text,
.panel-structure-c .panel-text {
  /* Anchor text to the SAME center as the icons: ((100vw - nav-reserve) / 2,
     60vh). 60vh (was 56vh) leaves more headroom from the pinned title at
     top:40 — the bigger scale-2.0 icon would clip into the title at typical
     desktop heights.
     `absolute` (was `fixed`) against the CARD: each card in the horizontal
     track is exactly 100vw × 100vh, so these viewport-unit offsets resolve to
     the very same on-screen point they did when the cards were stacked
     vertically and everything was viewport-fixed — the tuned values all still
     hold, they now travel with their card instead of cross-fading in place. */
  position: absolute;
  left: calc((100vw - var(--content-right-reserve)) / 2);
  /* --st-anchor: 共用的垂直錨點（短視窗時改 65vh，見下方 media query）。
     --st-title-align: 各面板為了「標題齊平」而做的微調（見下方說明）。 */
  top: calc(var(--st-anchor, 60vh) + var(--st-title-align, 0px));
  transform: translate(-50%, -50%);
  /* 下限 500px：nowrap 下最長那句是 p13 第三句英文（實測 482.4px）。
     欄寬比它窄時，text-align:center 不會左右對稱外溢 —— 置中位移被夾在 ≥0，
     整條線只往右溢，視覺上就偏右（實測偏 17.4px = 超出量的一半）。
     基準值跟螢幕高度綁定，短螢幕會縮到 350px 上下，所以下限不能省。 */
  width: max(500px, calc(0.48 * min(90vw, 80vh * 3000 / 2133)));
  text-align: center;
  z-index: 5;
  opacity: var(--text-opacity, 0);
  /* 三段文字疊在同一位置、靠 --text-opacity 切換。fallback 必須是 0：JS 尚未寫入
     --text-opacity 前（首幀競態或 init 出錯），三段 fixed 文字才不會同時以 opacity 1
     疊在同一定點，造成「不同面板文字疊加」。pointer-events 由 JS 依可見度設
     --text-pe：只有當前可見那段 = auto（可反白選取），淡掉的兩段 = none（不擋）。 */
  pointer-events: var(--text-pe, none);
}

/* 桌機：文字從右往左滑進來。三張卡現在疊在同一格不動（見 .structure-stack），
   位移改由文字自己吃 --p：
     p = -1 → translateX(+100vw)  還在右邊、被右側邊欄遮罩蓋住
     p =  0 → 0                   置中
     p = +1 → translateX(-100vw)  已往左離場
   100vw 與改版前整張卡橫推的行程相同，所以文字的進出節奏維持不變，
   只有圖示改成原地淡入淡出。 */
@media (min-width: 1025px) {
  .panel-structure-a .panel-text,
  .panel-structure-b .panel-text,
  .panel-structure-c .panel-text {
    transform: translate(-50%, -50%) translateX(calc(var(--p, 0) * -100vw));
    will-change: transform;
  }
}

/* Panels 11 & 12 icons (a01 + b01-03) are LOCKED at fixed viewport center
   (content-area midpoint) and only become fully opaque while their panel's
   text is near the viewport center. Width uses the same min(90vw, 80vh ×
   inner-aspect) formula as panel-inner so visual size matches the previous
   absolute-positioned layout. */
.panel-structure-a .panel-inner img,
.panel-structure-b .panel-inner img {
  /* absolute against the CARD (see .panel-text above). Because every card is
     100vw wide, `left: (100vw - reserve)/2` lands on the same screen point for
     card 11 and card 12 when each is centred — so the concentric circles still
     sit exactly where the starburst sat, which is what --st-icon-align tunes. */
  position: absolute !important;
  /* 圓心與文字「脫鉤」：文字各自吃 --st-title-align 做標題齊平，圖示統一吃
     --st-icon-align（js/main.js 寫在 .structure-stack 上，值 = 面板 11 的
     align），所以面板 12 的三個同心圓與面板 11 星芒的圓心疊在同一點。 */
  top: calc(var(--st-anchor, 60vh) + var(--st-icon-align, 0px)) !important;
  /* Center of the content area (viewport minus right-nav reserve). The text
     above is anchored to the same point, so they stay aligned at any width. */
  left: calc((100vw - var(--content-right-reserve)) / 2) !important;
  opacity: var(--icon-opacity, 0);
  pointer-events: none;
}

/* On short viewports the icon (now scale 2.0) gets close enough to the
   pinned title that the rotation's 45° max-diagonal clips it. Push the
   icon-text center further down. */
@media (max-height: 720px) and (min-width: 1025px) {
  /* 改錨點變數即可，文字與圖片一起下移（各自的 align 補償值都保留）。 */
  .panel-structure-a,
  .panel-structure-b,
  .panel-structure-c {
    --st-anchor: 65vh;
  }
}

/* ── STRUCTURE 內文不折行（桌機）────────────────────────────────────
   文字欄寬 = 0.48 × min(90vw, 80vh×3000/2133)，跟螢幕「高度」綁定；實測
   高 ≤ 864 的解析度（1536×864 / 1366×768 / 1280×800 / 1280×720 / 1152×864）
   最長的兩句英文會折行。改成 nowrap 讓句子併回一行。
   注意：超出行框時 text-align:center 並不會左右對稱外溢（只往右溢），
   所以欄寬另外設了 500px 下限把最長句包住，見上方 .panel-text 的 width。
   最長句 ~482px 在最窄桌機 (1025px) 的內容區 (765px) 也放得下。 */
@media (min-width: 1025px) {
  .panel-structure-a .about-body p,
  .panel-structure-b .about-body p,
  .panel-structure-c .about-body p {
    white-space: nowrap;
  }
}

/* ── STRUCTURE 三頁「標題齊平」──────────────────────────────────────
   三段文字都是以「區塊中心」對齊 --st-anchor，所以區塊越矮、標題就越低。
   各段內文行數不同，而且視窗變窄時英文句子會折行、高度還會再變，
   所以補償值不能寫死 —— 由 js/main.js 的 alignStructureHeadings() 實測
   三個區塊高度後寫入各面板的 --st-title-align（以 PROTECTED / p12 為基準），
   並在 resize 時重算。位移只掛在文字上；圖示（.panel-inner img）改吃
   --st-icon-align（見上），三頁圓心因此固定同一點、不隨各頁文字高度浮動。 */

/* STRUCTURE icon base size — the original viewport formula, scaled × 1.25.
   Each icon keeps its per-icon ratio (a01 0.28, b01/b03 0.3602, b02 0.3798),
   so panels 11/12 are simply 1.25× their original size. c01/c02 (panel 13)
   keep their own original sizing — not touched. */
:root { --st-base: calc(min(90vw, 80vh * 3000 / 2133) * 1.25); }

.panel-structure-a .g-st-a01 { width: calc(var(--st-base) * 0.285) !important; }
.panel-structure-b .g-st-b01 { width: calc(var(--st-base) * 0.3602) !important; }
.panel-structure-b .g-st-b02 { width: calc(var(--st-base) * 0.3798) !important; }
.panel-structure-b .g-st-b03 { width: calc(var(--st-base) * 0.3602) !important; }

/* Short-viewport guard (landscape phones/tablets ≤1024). At aspect ≥ 5/4 the
   --st-base min() switches to the HEIGHT term, and the 1.25 × spin-scale then
   makes the panel 11/12 icons ~69% of viewport height — their bottom edge drops
   onto the bottom barcode-logo. Trim the base to 0.85 here so the largest icon
   (b02) clears it; this lands them back near their pre-merge landscape size.
   Portrait phones are width-driven (already small), so they keep the full 1.25. */
@media (max-width: 1024px) and (min-aspect-ratio: 5 / 4) {
  :root { --st-base: calc(min(90vw, 80vh * 3000 / 2133) * 0.85); }
}

/* Panel 13 icons (c01 / c02) — same treatment as Panels 11/12: LOCKED at the
   viewport position they occupy when the panel is centered (editor-tuned
   panel-inner percentages converted to viewport coords: inner is a
   min(90vw, 80vh×aspect) box centered at 50vw/50vh), so they only fade
   in/out instead of scrolling up with the panel. */
.panel-structure-c .panel-inner img {
  position: absolute !important;  /* against the card — see .panel-text above */
  --st-cw: min(90vw, calc(80vh * 3000 / 2133));
  --st-ch: calc(var(--st-cw) * 2133 / 3000);
  opacity: var(--icon-opacity, 0);
  pointer-events: none;
}

/* Decorative outline icons — all sit BEHIND text (z-index 1).
   left/top/width are the editor-tuned base values; the 1.5× visual scale
   is applied via transform below so the visual center stays exactly where
   the editor placed it (instead of growing toward bottom-right). */
/* Panel 11 — REIMAGINE: starburst behind text */
.panel-structure-a .g-st-a01 { left: 22%; top: 32%; width: 28%; z-index: 1; }

/* Panel 12 — PROTECTED: 3 overlapping outline polygons stacked behind text */
.panel-structure-b .g-st-b01 { left: 17.83%; top: 24.64%; width: 36.02%; z-index: 1; }
.panel-structure-b .g-st-b02 { left: 16.85%; top: 23.26%; width: 37.98%; z-index: 1; }
.panel-structure-b .g-st-b03 { left: 17.83%; top: 24.64%; width: 36.02%; z-index: 1; }

/* Panel 13 — SUSTAIN: rotated rectangle (top-right) + heptagon (lower-left).
   Editor values were inner-relative (c01 37.69%/7.76%/40.93%,
   c02 -0.15%/36.45%/45.71%); here converted to fixed viewport coords:
   left = 50vw + (pct − 0.5) × innerW, top = 50vh + (pct − 0.5) × innerH. */
.panel-structure-c .g-st-c01 {
  left: calc(50vw - 0.1231 * var(--st-cw));
  top:  calc(50vh - 0.4224 * var(--st-ch));
  width: calc(0.4093 * var(--st-cw));
  z-index: 1;
}
.panel-structure-c .g-st-c02 {
  left: calc(50vw - 0.5015 * var(--st-cw));
  top:  calc(50vh - 0.1355 * var(--st-ch));
  width: calc(0.4571 * var(--st-cw));
  z-index: 1;
}

/* Continuously rotating icons — each keyframe set bakes the icon's
   per-element scale AND a translate(-50%, -50%) into the from/to transform
   so the icon stays anchored on the fixed viewport-center point while
   spinning. */
@keyframes structure-spin-195 {
  from { transform: translate(-50%, -50%) scale(1.7) rotate(0deg); }
  to   { transform: translate(-50%, -50%) scale(1.7) rotate(360deg); }
}
@keyframes structure-spin-1 {
  /* For absolute-positioned icons (Panel 13 c01/c02) — no centering
     translate, just rotate around the icon's own center. */
  from { transform: rotate(0deg); }
  to   { transform: rotate(360deg); }
}
@keyframes structure-spin-1-rev {
  /* Counter-clockwise variant — so c01 spins opposite to c02. */
  from { transform: rotate(0deg); }
  to   { transform: rotate(-360deg); }
}

/* b01-03 — Panel 12 concentric layers. Numbered 1→3 from inside to
   outside; inner spins fastest, outer slowest (≈ 1:2:3 ratio).
   Each polygon's artwork sits at a slightly different vertical spot inside its
   square PNG (measured: b01 art 1.31% high, b02 ~centred, b03 1.18% low). To
   keep the three truly CONCENTRIC and stop each from orbiting as it spins, every
   icon pivots on — and is centred by — its OWN artwork centre, not the padded
   canvas centre. transform-origin marks that centre (50% horiz since dx≈0); the
   keyframe's translateY shifts the element so that same centre lands on the
   anchor point. Centre is size-independent, so it holds at any --st-base. */
/* item 11: translate = −(measured artwork centroid) so each ring's centroid
   lands exactly on the shared anchor → all three truly concentric. */
@keyframes structure-spin-b01 {
  from { transform: translate(-49.97%, -49.86%) scale(1.7) rotate(0deg); }
  to   { transform: translate(-49.97%, -49.86%) scale(1.7) rotate(360deg); }
}
@keyframes structure-spin-b02 {
  from { transform: translate(-49.97%, -49.65%) scale(1.7) rotate(0deg); }
  to   { transform: translate(-49.97%, -49.65%) scale(1.7) rotate(360deg); }
}
@keyframes structure-spin-b03 {
  from { transform: translate(-49.97%, -49.90%) scale(1.7) rotate(0deg); }
  to   { transform: translate(-49.97%, -49.90%) scale(1.7) rotate(360deg); }
}
.panel-structure-b .g-st-b01 {
  animation: structure-spin-b01 6s linear infinite;
  transform-origin: 49.97% 49.86%;
}
.panel-structure-b .g-st-b02 {
  animation: structure-spin-b02 12s linear infinite;
  transform-origin: 49.97% 49.65%;
}
.panel-structure-b .g-st-b03 {
  animation: structure-spin-b03 18s linear infinite;
  transform-origin: 49.97% 49.90%;
}

/* c02 — base 20s spin (SUSTAIN heptagon, left untouched per request). */
.panel-structure-c .g-st-c02 {
  animation: structure-spin-1 20s linear infinite;
  transform-origin: center center;
}

/* c01 — slightly faster (17s). Coprime-ish vs c02's 20s (LCM = 340s),
   so the two icons don't repeat the same relative phase often, which
   prevents their rotated bounding boxes from "locking" into a recurring
   collision pattern. */
.panel-structure-c .g-st-c01 {
  animation: structure-spin-1-rev 17s linear infinite;
  transform-origin: center center;
}

/* Panel 11 starburst — 2.0× scale + continuous spin (own keyframes) */
@keyframes structure-spin-234 {
  from { transform: translate(-50%, -50%) scale(2.0) rotate(0deg); }
  to   { transform: translate(-50%, -50%) scale(2.0) rotate(360deg); }
}
.panel-structure-a .g-st-a01 {
  animation: structure-spin-234 20s linear infinite;
  transform-origin: center center;
}

/* ============================================================
   PARALLAX DEPTH (desktop horizontal-scroll only)
   Each panel gets --p from JS: -1 (incoming from right) → 0 (centered) → +1 (outgoing left).
   Each child sets its own --dx / --dy / --ds to define how strongly it parallaxes.
   Convention: positive --dx makes element APPEAR SLOWER (drifts opposite to panel),
   creating a "background" / "deep" feel. Negative makes it appear faster ("foreground").
   ============================================================ */
@media (min-width: 1025px) {
  /* PARALLAX: only ENTRY phase animates (p < 0). Past center (p ≥ 0) the
     element locks to its base position and rides out with the panel — so
     "post-center has no movement" matches the design intent.
     `min(var(--p), 0)` clamps p to ≤0; when p > 0 the multiplier is 0. */

  /* GENERIC parallax for any graphic in any about panel without an existing transform */
  .about-track .panel-inner img {
    transform: translate(
      calc(min(var(--p, 0), 0) * var(--dx, 0px) * -1),
      calc(min(var(--p, 0), 0) * var(--dy, 0px) * -1)
    );
    transition: opacity 0.3s ease;
  }

  /* Panel 2 STAGE — exaggerated depth: side triangles drift FAR slower (deep
     background), center holds steady, bottom banner zooms FAR faster
     (foreground). Spread roughly doubled for more parallax separation. */
  .panel-stage .g-a01 { --dx: 500px;  --dy: -150px; }   /* deep background */
  .panel-stage .g-a02 { --dx: 0px;    --dy: 30px; }     /* center, near-locked */
  .panel-stage .g-a03 { --dx: 500px;  --dy: -150px; }   /* deep background mirror */
  .panel-stage .g-a04 { --dx: -800px; --dy: 300px; }    /* fast foreground sweep */

  /* Panel 3 COLLAB — large parallax magnitudes for visible motion on the
     two big rotated/flipped graphics. g-b03 enters from upper-right and
     drifts to lower-left (positive --dx for right-start, negative --dy
     for upper-start). */
  /* Specificity bumped (.about-track + .panel-collab-intro + .g-b0x → 0,3,0) so
     these win over the generic .about-track .panel-inner img rule (0,2,1).
     No rotate/scaleX — preserve the CSS-positioned visual layout the user expects;
     only the scroll-driven scale animates. */
  .about-track .panel-collab-intro .g-b01 {
    /* small star: scale 0.5 → 1 on entry (p < 0), then 1 → 2.0 on exit (p > 0) */
    transform: scale(calc(1 + min(var(--p, 0), 0) * 0.5 + max(var(--p, 0), 0) * 1.0));
    transform-origin: center center;
  }
  .about-track .panel-collab-intro .g-b02 {
    /* big star: faster entry (1 reached by p=-0.7), larger exit (1 → 2.5) */
    transform: scale(calc(1 + max(min(calc(var(--p, 0) / 0.7), 0), -1) * 0.8 + max(var(--p, 0), 0) * 1.5));
    transform-origin: center center;
  }
  .panel-collab-intro .g-b03 {
    /* foreground — entry from RIGHT-UPPER, drifts to lower-left */
    --dx: 700px;     /* +x: starts to the right */
    --dy: -350px;    /* -y: starts above */
  }

  /* Panel 4 INTEGRATE — c-cluster STICKS at viewport position from Panel 4
     center through Panel 5 center, only exits when Panel 5 exits.
     Compensation translate counters the track's leftward motion while
     p ∈ [0, 1]; for p > 1 (Panel 5 exiting), comp clamps at 100vw so the
     cluster slides out together with the track. */
  .panel-integrate {
    /* Override .about-panel { overflow: hidden } — needed so the +100vw
       translate doesn't get clipped at Panel 4's right edge while the
       c-cluster is supposed to be visible in Panel 5's slot. */
    overflow: visible;
  }
  .panel-integrate .panel-inner img {
    transform: translate(
      calc(min(var(--p, 0), 0) * var(--dx, 0px) * -1 + clamp(0px, calc(var(--p, 0) * 100vw), 100vw)),
      calc(min(var(--p, 0), 0) * var(--dy, 0px) * -1)
    );
    /* Opacity:
         entry  (p<0):    ramp 0→1 between p=-0.35 and p=-0.10
         center (0≤p≤1):  full 1
         exit   (p>1):    ramp 1→0 between p=1.10 and p=1.35
       min() picks the smaller of the entry and exit ramps so both
       boundaries clamp correctly. */
    opacity: clamp(0, min(calc(1.4 + var(--p, 0) * 4), calc(5.4 - var(--p, 0) * 4)), 1);
  }
  .panel-integrate .g-c01 { --dx: 290px;  --dy: 0px; }
  .panel-integrate .g-c02 { --dx: 390px;  --dy: 0px; }
  .panel-integrate .g-c03 { --dx: -150px; --dy: 75px; }
  .panel-integrate .g-c04 { --dx: 0px;    --dy: 0px; }
  .panel-integrate .g-c05 { --dx: 500px;  --dy: 0px; }

  /* 上下半圓 (item 4): g-c01 / g-c02 share the same entry offset (340px) and
     sticky compensation. 兩顆半圓的 drift 起訖「時間」對齊在 p = 0 → 1
     (Panel 4 置中 → Panel 5 置中，和 g-c05 立方體同區間)；起訖「位置」維持原設計，
     所以速度不同是刻意的：
       g-c01  0px      →  22.5px LEFT   (22.5px 行程)
       g-c02  27.5px R →  60px   LEFT   (87.5px 行程) */
  .about-track .panel-integrate .g-c01 {
    transform: translate(
      calc(
        min(var(--p, 0), 0) * 340px * -1 +
        clamp(0px, calc(var(--p, 0) * 100vw), 100vw) -
        clamp(0px, calc(var(--p, 0) * 22.5px), 22.5px)
      ),
      0px
    );
  }
  .about-track .panel-integrate .g-c02 {
    transform: translate(
      calc(
        min(var(--p, 0), 0) * 340px * -1 +
        clamp(0px, calc(var(--p, 0) * 100vw), 100vw) -
        clamp(-27.5px, calc(-27.5px + var(--p, 0) * 87.5px), 60px)
      ),
      0px
    );
  }

  /* g-c05 (cube): drifts RIGHT (positive offset) during sticky so it moves
     out from behind the panel-believe text block (text spans 18-68% width;
     cube base spans 58-78% — leftward drift just pushes cube deeper into
     text). Total right drift +60px keeps cube right edge inside g-c04's
     right edge (78.63 + 5.9 = 84.5% < 87.05%). Rotation unchanged. */
  .about-track .panel-integrate .g-c05 {
    transform:
      translate(
        calc(
          min(var(--p, 0), 0) * 500px * -1 +
          clamp(0px, calc(var(--p, 0) * 100vw), 100vw) +
          clamp(0px, calc(var(--p, 0) * 60px), 60px)
        ),
        0px
      )
      rotate(calc(clamp(-1, var(--p, 0), 1) * -90deg));
    transform-origin: center center;
  }

  /* Panel 5 BELIEVE c-cluster: hidden because Panel 4's c-cluster is sticking
     through Panel 5's slot via the compensation transform above. Only Panel 5's
     TEXT changes between Panels 4 and 5; the visual graphic composition is
     a single persistent scene. */
  .panel-believe .panel-inner img {
    opacity: 0;
  }

  /* Panel 5 BELIEVE */
  .panel-believe .g-c01 { --dx: -250px; --dy: 75px; }
  .panel-believe .g-c02 { --dx: 125px;  --dy: -50px; }
  .panel-believe .g-c03 { --dx: 200px;  --dy: 0px; }
  .panel-believe .g-c04 { --dx: -50px;  --dy: 0px; }
  .panel-believe .g-c05 { --dx: 350px;  --dy: -125px; }

  /* Panels 7-9 PART I/II/III — graphic pinned to one viewport spot, fades in
     place, never travels with the track (same trick as .panel-integrate's
     sticky c-cluster above: a FULL-range compensation term, var(--p,0) *
     100vw, cancels the track's own leftward drift for the entire fade
     window on both sides of center, not just on entry). overflow:visible
     overrides .about-panel { overflow: hidden } so the compensated image
     isn't clipped at the panel's own edge while pinned in place — without
     it, the image would appear to get cut off against the panel boundary
     right as it's fading out, instead of just fading to transparent. */
  .panel-part-1,
  .panel-part-2,
  .panel-part-3 {
    overflow: visible;
  }
  .about-track .panel-part-1 .g-d01,
  .about-track .panel-part-2 .g-d02,
  .about-track .panel-part-3 .g-d03 {
    transform: translateX(calc(var(--p, 0) * 100vw));
    /* Entry ramp (1.4 + p*4): 0→1 between p=-0.35 and p=-0.10.
       Exit ramp  (1.4 - p*4): 1→0 between p=+0.10 and p=+0.35.
       min() of both forms a symmetric tent around p=0, same shape as
       .panel-integrate's sticky fade above — fades in AND back out
       instead of staying opaque and getting cut off by the track. */
    opacity: clamp(0, min(calc(1.4 + var(--p, 0) * 4), calc(1.4 - var(--p, 0) * 4)), 1);
  }

  /* Text: also entry-only parallax. After center, text stays at full opacity
     and base position while panel scrolls out. */
  .about-track .panel-text {
    transform: translate(calc(min(var(--p, 0), 0) * 150px * -1), 0);
    opacity: clamp(0, calc(1.4 - max(0, calc(var(--p, 0) * -1)) * 2.5), 1);
    transition: opacity 0.15s linear;
  }
  /* Panel 2 text — top: 50.21% is direct top edge (no translateY base anymore),
     just apply parallax horizontal drift */
  .panel-stage .panel-text {
    transform: translate(calc(min(var(--p, 0), 0) * 150px * -1), 0);
  }
  /* Panel 1 / 6 / 10 text use translate(-50%, -50%) base */
  .panel-mission .panel-text,
  .panel-journey-intro .panel-text,
  .panel-structure-intro .panel-text {
    transform: translate(calc(-50% + min(var(--p, 0), 0) * 150px * -1), -50%);
  }

  /* Panels 11/12/13 — title-top stays fixed (no parallax); icons + body
     text get standard entry parallax via .about-track .panel-inner img and
     .about-track .panel-text rules above. Set per-icon --dx/--dy for depth. */
  .panel-structure-a .g-st-a01 { --dx: 600px;  --dy: 0px; }

  .panel-structure-b .g-st-b01 { --dx: 700px;  --dy: -100px; }
  .panel-structure-b .g-st-b02 { --dx: 500px;  --dy: 50px; }
  .panel-structure-b .g-st-b03 { --dx: 900px;  --dy: -150px; }

  .panel-structure-c .g-st-c01 { --dx: 800px;  --dy: -120px; }
  .panel-structure-c .g-st-c02 { --dx: 500px;  --dy: 80px; }
}

/* Headings */
.about-heading {
  margin-bottom: 60px;
}

/* 置中標題通則：letter-spacing 會在最後一個字後面也多一格，置中時整行
   盒子偏寬、可見文字往左偏 spacing/2；中英 spacing 不同就互相對不齊
   （SPINE 看起來偏右、PIECES 看起來偏左都是這個）。每行補等量
   text-indent 在行首，左右對稱、真正置中。（下同） */
.about-heading .h-en {
  display: block;
  font-family: var(--font-en);
  font-weight: 700;
  font-size: 32px;
  letter-spacing: 3px;
  text-indent: 3px;
  margin-bottom: 8px;
}

.about-heading .h-zh {
  display: block;
  font-family: var(--font-zh);
  font-size: 15px;
  font-weight: 700;
  letter-spacing: 6px;
  text-indent: 6px;
}

.about-subheading {
  margin-bottom: 52.5px;
}

.about-subheading .h-en {
  display: block;
  font-family: var(--font-en);
  font-weight: 700;
  font-size: 24px;
  letter-spacing: 2px;
  text-indent: 2px;
  margin-bottom: 6px;
}

.about-subheading .h-zh {
  display: block;
  font-family: var(--font-zh);
  font-size: 13px;
  font-weight: 700;
  letter-spacing: 4px;
  text-indent: 4px;
}

/* Italic subheading variant used by Panels 11/12/13 (REIMAGINE / PROTECTED / SUSTAIN) */
.structure-subheading {
  margin-bottom: 42px;
}

.structure-subheading .h-en {
  display: block;
  font-family: var(--font-en);
  font-style: italic;
  font-weight: 700;
  font-size: 18px;
  letter-spacing: 2px;
  text-indent: 2px;
  margin-bottom: 6px;
}

.structure-subheading .h-zh {
  display: block;
  font-family: var(--font-zh);
  font-style: italic;
  font-size: 13px;
  font-weight: 500;
  letter-spacing: 3px;
  text-indent: 3px;
}

/* 標題光暈（中英皆套，text-shadow 會繼承給子 span）— 僅指定面板：
   CORE MISSION / Journey / Part.I-III 面板 / REIMAGINE / PROTECTED / SUSTAIN。
   排除 Journey 清單內的 Part.I-III（p6 .journey-list）及 STRUCTURE / SPINE / WOTM？？？。 */
.text-p1 .about-heading,
.text-p6 .about-heading,
.text-p7 .about-subheading,
.text-p8 .about-subheading,
.text-p9 .about-subheading,
.text-p11 .structure-subheading,
.text-p12 .structure-subheading,
.text-p13 .structure-subheading {
  text-shadow: 0 0 12px rgba(255, 40, 40, 0.85),
               0 0 28px rgba(255, 0, 0, 0.55);
  animation: heading-glow-red 2.4s ease-in-out infinite;
}

/* 光暈維持純紅，只在強弱之間呼吸閃爍（不回白） */
@keyframes heading-glow-red {
  0%, 100% {
    text-shadow: 0 0 8px rgba(255, 40, 40, 0.4),
                 0 0 16px rgba(255, 0, 0, 0.25);
  }
  50% {
    text-shadow: 0 0 14px rgba(255, 40, 40, 1),
                 0 0 32px rgba(255, 0, 0, 0.7);
  }
}

@media (prefers-reduced-motion: reduce) {
  .text-p1 .about-heading,
  .text-p6 .about-heading,
  .text-p7 .about-subheading,
  .text-p8 .about-subheading,
  .text-p9 .about-subheading,
  .text-p11 .structure-subheading,
  .text-p12 .structure-subheading,
  .text-p13 .structure-subheading {
    animation: none;
  }
}

/* Bilingual body text — alternating en/zh lines */
.about-body {
  font-family: var(--font-en);
}

.about-body .line-en {
  font-family: var(--font-en);
  font-weight: 700;
  font-size: 18px;
  letter-spacing: 0.5px;
  line-height: 1.45;
  margin-top: 14px;
}

.about-body .line-en:first-child {
  margin-top: 0;
}

.about-body .line-zh {
  font-family: var(--font-zh);
  font-weight: 500;
  font-size: 13px;
  letter-spacing: 1px;
  line-height: 1.7;
  margin-top: 3px;
}

/* Journey intro list */
.journey-list {
  list-style: none;
  padding: 0;
  margin-top: 60px;
}

.journey-list li {
  margin-bottom: 26px;
}

.journey-list li .j-en {
  display: block;
  font-family: var(--font-en);
  font-weight: 700;
  font-size: 18px;
  letter-spacing: 1px;
  margin-bottom: 4px;
}

.journey-list li .j-zh {
  display: block;
  font-family: var(--font-zh);
  font-size: 13px;
  font-weight: 500;
  letter-spacing: 3px;
}

/* Wrapper for trust/team/FAQ (below panels). Right padding reserves space
   for the fixed right-side nav; inner blocks are centered within the
   remaining (viewport − right-nav) area so the visual center sits at the
   midpoint of the visible page, not skewed left. */
.about-content > .about-inner {
  width: 100%;
  padding: 0 var(--content-right-reserve, 260px) 80px 0;
  box-sizing: border-box;
}

.about-content > .about-inner > .about-trust,
.about-content > .about-inner > .about-team,
.about-content > .about-inner > .about-faq {
  max-width: 800px;
  margin-left: auto;
  margin-right: auto;
}

.about-section-title {
  font-family: var(--font-zh);
  font-weight: 700;
  font-size: 24px;
  letter-spacing: 4px;
  margin-bottom: 50px;
  text-align: center;
}

/* Full-screen centered section titles (脊椎 / WOTM???). Each title is a fixed
   element that morphs centered → pinned-at-top → hidden via JS (same behaviour
   as "STRUCTURE behind WOTM"). The .pin-title-intro is a 100vh spacer — one
   clean wheel step. It was 150vh, which pushed its centered snap stop 25vh into
   the block and made the surrounding steps 1.25 screens; the centered-title
   dwell now comes from PIN_LEAD in js/main.js instead of from spacer height.
   (Mobile keeps 130vh — see the ≤1024px block; the stepper is desktop-only.) */
.pin-title-intro {
  min-height: 100vh;
}
.pin-title-element {
  position: fixed;
  z-index: 100;
  text-align: center;
  pointer-events: none;
  left: calc((100vw - var(--content-right-reserve)) / 2);
  top: 50%;
  transform: translate(-50%, -50%);
  opacity: 0;
  transition: opacity 0.18s ease;
}
.pin-title-element.is-centered,
.pin-title-element.is-pinned {
  transition: top 0.45s cubic-bezier(0.4, 0, 0.2, 1),
              transform 0.45s cubic-bezier(0.4, 0, 0.2, 1),
              opacity 0.25s ease;
  opacity: 1;
}
.pin-title-element.is-centered { top: 50%; transform: translate(-50%, -50%); }
.pin-title-element.is-pinned   { top: 40px; transform: translate(-50%, 0); }
.pin-title-element.is-hidden   { opacity: 0; }
.pin-title-element.is-hidden.was-centered { top: 50%; transform: translate(-50%, -50%); }
.pin-title-element.is-hidden.was-pinned   { top: 40px; transform: translate(-50%, 0); }
/* 脊椎 / WOTM??? pinned titles reuse the STRUCTURE heading style (.about-heading,
   上大下小兩行). Zero the heading's default 40px bottom margin so the fixed
   element stays optically centered under translate(-50%, -50%). */
.pin-title-element .about-heading {
  margin-bottom: 0;
}

/* Trust / Responsibility */
.about-trust {
  padding: 80px 0;
}

.trust-cards {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 25px;
}

.trust-card {
  background: var(--color-card);
  color: var(--color-text-dark);
  padding: 35px 30px;
}

.trust-card h3 {
  font-family: var(--font-zh);
  font-weight: 700;
  font-size: 18px;
  letter-spacing: 2px;
  margin-bottom: 14px;
}

.trust-card p {
  font-size: 14px;
  line-height: 1.8;
}

/* Team */
.about-team {
  /* Extra bottom padding grows the section so the bottom-anchored portraits sit
     lower (page expands downward, no FAQ overlap). */
  padding: 80px 0 240px;
  position: relative;   /* anchor for the member portraits */
}

/* Keep the text above the portraits so overlap never covers the content. */
.about-team-text {
  position: relative;
  z-index: 1;
}

/* .about-team-bg is the MOBILE-only video (see mobile block); hidden here.
   .team-members-bg is the DESKTOP-only video backdrop behind the portraits. */
.about-team-bg {
  display: none;
}

/* Desktop: video backdrop sitting behind the portrait group ONLY. The group's
   box is ~483×460 (near-square), so instead of filling it (which crops the
   video square) we crop the video to a horizontal 16:9 rectangle spanning the
   group width, vertically centred behind the portraits. It's the first child
   of .team-members so it paints behind the portrait <img>s. */
.team-members-bg {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 15px;         /* 抬到人物腳底線：照片框底有約 4%(≈15px) 透明留白，
                           扣掉才貼合人物腳底，不受螢幕比例影響 */
  width: 100%;
  height: auto;
  aspect-ratio: 16 / 9;
  object-fit: cover;
  z-index: 0;
  pointer-events: none;
}

/* Member portraits parked in the bottom-right corner, BEHIND the text. */
.team-members {
  position: absolute;
  /* Push right when there's room, but pull back as the viewport narrows so the
     group never overlaps the reserved right nav column (or overflows).
     -160px on wide screens → eases toward +8px (just inside the text column)
     once space runs out. Derivation: column right edge ≈ 50vw+270px; the nav
     reserve starts at 100vw−260px, so cap the overhang at 50vw−550px.
     Settled spot nudged toward the top-right corner (was right ≥ -65px,
     bottom 0). NOTE: pushed a further 100px right + up per request — this now
     overhangs into the right nav reserve on narrower desktops; tighten the
     clamp bounds back if it collides with the nav. */
  right: clamp(-195px, calc(420px - 50vw), -92px);
  bottom: 228px;
  z-index: 0;
  display: flex;
  align-items: flex-end;
  gap: 0;
  pointer-events: none;   /* never block clicks on the content */
}
.team-member {
  display: block;
  width: auto;
  /* 再等比例縮小一次：460px → 390px（約 85%）。群組是 align-items:flex-end
     且外層 bottom:228px，所以只會往上縮、底部位置維持不動。 */
  height: 390px;
  position: relative;   /* enable stacking order for the overlap */
}
/* Overlap the portraits so they sit close together — scaled to keep the same
   visual closeness as mobile now that the desktop images are larger. */
.team-member-leader,
.team-member-engineer { margin-left: -81px; }   /* 隨高度 460→390 等比例縮 */
/* Leader (middle) always on top, never covered by the others. */
.team-member-leader { z-index: 2; }

/* ── 脊椎: scroll-LINKED portrait entry — same model as the About panels ──
   JS writes --p on the group every scroll frame: -1 (incoming, fully offset +
   transparent) → 0 (settled). Each portrait's transform is driven by --p × its
   own --dx/--dy, with NO transition, so the portraits track the scroll exactly
   (move in as you scroll down, back out as you scroll up). Default --p:-1 keeps
   them offset/hidden before JS runs (so nothing "plays" on load). */
.team-members { --p: -1; }
.team-members .team-member {
  /* 位移仍完全跟隨捲動（scroll-linked）。旋轉不放這裡 —— 見下方 .team-wiggle-in 的
     keyframe，用獨立的 rotate: 屬性做固定時間的順逆時針擺動，才不會被吸附式跳轉抹平。 */
  transform: translate(
    calc(min(var(--p), 0) * var(--dx, 0px) * -1),
    calc(min(var(--p), 0) * var(--dy, 0px) * -1)
  );
  /* item 9: portraits stay FULLY OPAQUE the whole time — including the moment
     they enter. No transparency / fade; they only translate + tilt into place. */
  opacity: 1;
  /* JS quantizes --p into steps; this short ease moves the portrait one segment
     each time a step is crossed, so it reads as "move a bit → pause → move a bit"
     (the頓挫/卡頓 feel) rather than a smooth glide. */
  transition: transform 0.3s ease-out;
}
/* Desktop drag must feel 1:1 — kill the lag while a portrait is being dragged. */
.team-members .team-member.is-dragging { transition: none; }
.team-member-designer { --dx: -240px; --dy: 0px; }  /* in from the left  */
.team-member-leader   { --dx: 0px;    --dy: 160px; } /* in from below     */
.team-member-engineer { --dx: 240px;  --dy: 0px; }   /* in from the right */

/* Stagger the step transitions so the three don't hitch in unison — designer
   moves first, then leader, then engineer (各圖片階段錯開). Specificity matches
   the shorthand rule above and comes later, so the delay wins. */
.team-members .team-member-designer { transition-delay: 0s; }
.team-members .team-member-leader   { transition-delay: 0.13s; }
.team-members .team-member-engineer { transition-delay: 0.26s; }

/* 扭來扭去進場：JS 在團隊區進場時於 .team-members 加上 .team-wiggle-in，
   觸發一段固定時間的旋轉擺動。用獨立的 rotate: 屬性（非 transform），所以與上面
   scroll-linked 的位移各走各的、互不覆蓋；順時針 16° → 逆時針 -13° → +9° → -6° → +3° → 站正，
   幅度遞減收斂。三張用 animation-delay 錯開，依序扭進來。 */
@keyframes team-wiggle {
  0%   { rotate: 0deg; }
  12%  { rotate: 16deg; }    /* 順時針 */
  30%  { rotate: -13deg; }   /* 逆時針 */
  48%  { rotate: 9deg; }
  66%  { rotate: -6deg; }
  82%  { rotate: 3deg; }
  100% { rotate: 0deg; }
}
.team-members.team-wiggle-in .team-member {
  animation: team-wiggle 1.1s ease-out both;
  transform-origin: center center;
}
.team-members.team-wiggle-in .team-member-designer { animation-delay: 0s; }
.team-members.team-wiggle-in .team-member-leader   { animation-delay: 0.12s; }
.team-members.team-wiggle-in .team-member-engineer { animation-delay: 0.24s; }

@media (prefers-reduced-motion: reduce) {
  .team-members { --p: 0; }   /* no motion → just sit settled */
  .team-members.team-wiggle-in .team-member { animation: none; }
}

/* Desktop only: portraits are grabbable & draggable (behavior added in JS). */
@media (min-width: 1025px) {
  /* The base .team-members sets pointer-events:none (so it never blocks the
     text). Re-enable it here so the portraits are actually hit-testable and
     grabbable on desktop — without this, clicks pass straight through them. */
  .team-members { pointer-events: auto; }
  .team-member {
    cursor: grab;
    pointer-events: auto;
    touch-action: none;       /* pointer-drag without the browser hijacking it */
    user-select: none;
    -webkit-user-drag: none;  /* no native image ghost while dragging */
  }
  .team-member.is-dragging { cursor: grabbing; }
  /* Once a portrait is grabbed, lift the whole group above .about-team-text
     (z-index 1) so dragged portraits stay visible instead of hiding behind it. */
  .team-members.is-dragging-active { z-index: 3; }
  /* Let clicks pass THROUGH the intro text to the portraits sitting behind it,
     so the whole portrait is grabbable — not just the slice below the text.
     (Trade-off: this paragraph block isn't text-selectable on desktop.) */
  .about-team-text { pointer-events: none; }
}

/* Bilingual lines — match the en/zh font convention used across the site:
   English in --font-en (Helvetica Condensed), Chinese in --font-zh (GlowSansTC). */
.about-team-text .line-en {
  font-family: var(--font-en);
  font-weight: 700;
  font-size: 15px;
  letter-spacing: 0.5px;
  line-height: 1.5;
  margin-top: 18px;
}

.about-team-text .line-en:first-child {
  margin-top: 0;
}

.about-team-text .line-zh {
  font-family: var(--font-zh);
  font-weight: 500;
  font-size: 13px;
  letter-spacing: 1px;
  line-height: 1.7;
  margin-top: 3px;
}

/* Larger gap before the closing "To us / 在我們心中" block. */
.about-team-break {
  margin-top: 44px;
}

.about-team-closing {
  margin-top: 20px;
  font-weight: 700;
  color: rgba(249, 56, 34, 0.9);
}

/* FAQ */
.about-faq {
  padding: 80px 0 40px;
}

.faq-list {
  display: flex;
  flex-direction: column;
}

.faq-item {
  border-bottom: 1px solid rgba(249, 56, 34, 0.3);
}

.faq-question {
  width: 100%;
  background: transparent;
  border: none;
  color: var(--color-primary);
  font-family: var(--font-zh);
  font-weight: 700;
  font-size: 16px;
  text-align: left;
  /* 上下留白用真的 padding，不要只靠 min-height 的剩餘空間 —— 題目一旦折行
     （手機版多數題目的英文副標會折兩行）文字就會撐滿 min-height，剩餘歸零、
     題與題之間只剩 1px 分隔線。min-height 保留當最短題目的下限。 */
  padding: 11px 30px 11px 0;
  cursor: pointer;
  position: relative;
  line-height: 24px;
  letter-spacing: 0.5px;
  transition: opacity 0.3s;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: flex-start;
  gap: 4px;              /* 問題中↔英 組內間距 */
  min-height: 68px;
}

/* hover 調淡也改字色（游標拖曳反白時必定處於 hover，opacity 會讓反白跟著變透）。
   q-en 已有自己的字色，另補一條重現原本 0.7×0.7 的疊乘效果。 */
.faq-question:hover {
  color: rgba(249, 56, 34, 0.7);
}
.faq-question:hover .faq-q-en {
  color: rgba(249, 56, 34, 0.49);
}

.faq-question::after {
  content: '+';
  position: absolute;
  right: 0;
  top: 50%;
  transform: translateY(-50%);
  font-family: var(--font-en);
  font-size: 22px;
  font-weight: 700;
  transition: transform 0.3s;
}

.faq-item.open .faq-question::after {
  content: '−';
}

.faq-answer {
  max-height: 0;
  overflow: hidden;
  /* Height is driven inline by JS (real content height) so closing slides up
     in one continuous motion. This collapsing layer has NO padding so it truly
     reaches 0 when closed; the bottom spacing lives on .faq-answer-inner (a
     wrapper JS inserts), which never changes — so nothing snaps mid-animation. */
  transition: max-height 0.4s ease;
  padding: 0;
}

.faq-answer-inner {
  padding-bottom: 22px;
}

/* 中英文答案統一行距 1.75（消除中 1.9 / 英 1.7 的落差）。 */
.faq-answer p {
  font-size: 14px;
  line-height: 1.75;
  color: rgba(249, 56, 34, 0.85);
  margin: 0;
}

/* FAQ 中文折行不切語意：word-break: keep-all 讓中文只在標點（，、。！？）
   與空格處換行，不會斷在詞句中間；英文本來就以空格斷詞，不受影響。
   overflow-wrap: break-word 當保險 —— 萬一某個子句比整行還長（窄螢幕），
   仍允許斷開，避免文字溢出容器。 */
.faq-q-zh,
.faq-answer .faq-a-zh {
  word-break: keep-all;
  overflow-wrap: break-word;
}

/* FAQ bilingual — English sub-text under each Chinese question / answer line */
.faq-q-en {
  font-family: var(--font-en);
  font-weight: 600;
  font-size: 13px;
  letter-spacing: 0.3px;
  line-height: 1.4;
  color: rgba(249, 56, 34, 0.7);
}

/* 回答內容：中文段落集中在上、英文段落集中在下（比照第一題的中→英排法）。
   垂直節奏統一：同語言連續段落 2px；中文區塊→英文區塊的語言切換 8px。 */
.faq-answer p { margin-top: 2px; }                       /* 同語言連續段落 */
.faq-answer p:first-child { margin-top: 0; }             /* 第一段（中文） */
.faq-answer .faq-a-zh + .faq-a-en { margin-top: 8px; }   /* 中文區塊 → 英文區塊 */
.faq-answer .faq-a-en {
  font-family: var(--font-en);
  font-size: 13px;
  /* line-height 繼承 .faq-answer p 的 1.75，與中文一致 */
  color: rgba(249, 56, 34, 0.72);
}

/* ========================================
   SECTION 3: JOIN (Form)
   ======================================== */
.join-content {
  display: flex;
  align-items: stretch;
  /* item 10: center the card in the content area (viewport minus the right nav
     reserve), matching the Journey section. With left padding = page gutter and
     right padding = gutter + reserve, the flex content box is centered on
     (100vw − reserve)/2 — the same midpoint the STRUCTURE/Journey titles use. */
  justify-content: center;
  padding: 55px calc(var(--page-padding-left) + var(--content-right-reserve)) 55px var(--page-padding-left);
  min-height: 100vh;
}

.join-card {
  background: var(--color-card);
  color: var(--color-text-dark);
  width: 800px;
  max-width: 100%;
  padding: 45px 45px 32px;   /* a bit of breathing room below the SUBMIT button */
}

.form-row {
  display: flex;
  align-items: center;
  gap: 45px;
  padding-bottom: 0;
  /* 13→15：NAME 底線(row頂+93) 到下一條線(row頂+143+margin+43) 的距離
     = 106 → 108 = 4 的倍數，與 .form-field 的 104 節距同相位（見該處註解）。 */
  margin-bottom: 15px;
  position: relative;
}

.form-row::after {
  content: '';
  position: absolute;
  top: 93px;
  left: 410px;
  right: 0;
  /* NAME 欄的底線與其他欄位不同源（.form-row 不是 .join-card 直接子元素，
     吃不到 .join-card > .form-field::after）——粗細顏色必須跟該規則同步：
     1px + --color-text-dark。 */
  height: 1px;
  background: var(--color-text-dark);
}

.form-photo-placeholder {
  width: 120px;
  height: 143px;
  flex-shrink: 0;
  overflow: hidden;
}

.form-photo-placeholder img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.form-row .form-field {
  margin-bottom: 0;
  border-bottom: none;
  padding-bottom: 0;
}

.form-field {
  flex: 1;
  display: flex;
  align-items: flex-start;
  gap: 45px;
  /* 30→31：欄位垂直節距 = 43(標籤) + 31 + 30 = 104 = 4 的倍數。
     1px 底線在 125%/150%/175% 系統縮放下的實體像素相位才會條條相同
     （4 × 1.25/1.5/1.75/2 皆為整數），否則有的線實、有的線糊，
     看起來粗細不一。搭配 .form-row 的 margin 調整（見該處註解）。 */
  padding-bottom: 31px;
  margin-bottom: 30px;
  position: relative;
}

.join-card > .form-field::after {
  content: '';
  position: absolute;
  top: 43px;
  left: 245px;
  right: 0;
  /* 細底線（2px → 1px），顏色用反白選取的灰黑 --color-text-dark，不用全黑 */
  height: 1px;
  background: var(--color-text-dark);
}

.join-card > .form-field {
  margin-left: var(--page-padding-left);
}

.form-field label {
  flex-shrink: 0;
  width: 200px;
}

.field-en {
  font-family: var(--font-en);
  font-weight: 700;
  font-size: 20px;
  letter-spacing: 3px;
  display: block;
  line-height: 24px;
}

.field-zh {
  font-family: var(--font-zh);
  font-size: 13px;
  display: block;
  margin-top: 3px;
  line-height: 16px;
}

.form-field input {
  flex: 1;
  min-width: 0;
  background: transparent;
  border: none;
  padding: 0;
  font-size: 14px;
  color: var(--color-text-dark);
  text-align: center;
  font-family: var(--font-zh);
  line-height: 1.2;
  align-self: flex-end;
  margin-bottom: 5px;
}

.form-field input::placeholder {
  color: rgba(37, 42, 54, 0.35);
  font-family: var(--font-zh);
  font-size: 13px;
}

.form-field input:focus {
  outline: none;
}

/* Strip browser autofill's forced white/yellow background.
   The 9999s transition delays the autofill fill paint indefinitely,
   keeping the input transparent; text-fill-color locks the dark text. */
.form-field input:-webkit-autofill,
.form-field input:-webkit-autofill:hover,
.form-field input:-webkit-autofill:focus,
.form-field input:-webkit-autofill:active {
  -webkit-text-fill-color: var(--color-text-dark);
  caret-color: var(--color-text-dark);
  transition: background-color 9999s ease-in-out 0s;
}

/* ========================================
   SECTION 4: ARTISTS LIST
   ======================================== */
.artists-content {
  display: flex;
  align-items: flex-start;
  /* item 10: center the list in the content area — see .join-content note. */
  justify-content: center;
  padding: 55px calc(var(--page-padding-left) + var(--content-right-reserve)) 55px var(--page-padding-left);
  min-height: 100vh;
}

/* Placeholder mode (no artists yet): reuse the PIECES centered "coming soon"
   design. Added as a modifier so the artist-list styles above are preserved
   for when the real artist cards come back — just drop the .is-placeholder
   class and restore the card markup in index.html. */
.artists-content.is-placeholder {
  align-items: center;
  padding: 60px calc(var(--page-padding-left) + var(--content-right-reserve)) 40px var(--page-padding-left);
}

.artists-list {
  display: flex;
  flex-direction: column;
  gap: 30px;
  width: 800px;
  max-width: 100%;
}

.artist-card {
  background: var(--color-card);
  color: var(--color-text-dark);
  display: flex;
  align-items: center;
  gap: 45px;
  padding: 30px 40px 30px 30px;
  cursor: pointer;
  transition: transform 0.3s, box-shadow 0.3s;
  height: 240px;
}

.artist-card:hover {
  transform: translateX(8px);
  box-shadow: -8px 0 30px rgba(249, 56, 34, 0.3);
}

.artist-photo {
  width: 140px;
  height: 140px;
  flex-shrink: 0;
  overflow: hidden;
}

.artist-photo img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.artist-info {
  flex: 1;
}

.artist-name {
  font-family: var(--font-en);
  font-weight: 700;
  font-size: 26px;
  letter-spacing: 4px;
}

.artist-name-zh {
  font-family: var(--font-zh);
  font-size: 15px;
  margin-top: 3px;
}

.artist-tags {
  font-style: italic;
  font-size: 15px;
  margin-top: 18px;
  color: rgba(37, 42, 54, 0.7);   /* 紅卡片上的深色字 --color-text-dark 帶 alpha */
}

.artist-tags-zh {
  font-family: var(--font-zh);
  font-size: 13px;
  margin-top: 3px;
  color: rgba(37, 42, 54, 0.7);
}

/* ========================================
   SECTION 5: ARTIST DETAIL (standalone page)
   ======================================== */
.artist-detail-content {
  display: flex;
  align-items: flex-start;
  justify-content: flex-start;
  padding: 55px 320px 55px var(--page-padding-left);
  position: relative;
  z-index: 2;
}

.detail-card {
  background: var(--color-card);
  color: var(--color-text-dark);
  width: 800px;
  max-width: 100%;
  padding: 40px 50px 35px;
}

.detail-top {
  display: flex;
  gap: 30px;
  margin-bottom: 15px;
}

.detail-photo {
  width: 160px;
  height: 190px;
  flex-shrink: 0;
  overflow: hidden;
}

.detail-photo img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.detail-header {
  flex: 1;
}

.detail-name {
  font-family: var(--font-en);
  font-weight: 700;
  font-size: 28px;
  letter-spacing: 3px;
}

.detail-name-zh {
  font-size: 15px;
  margin-top: 4px;
}

.detail-tags {
  font-style: italic;
  font-size: 14px;
  color: rgba(37, 42, 54, 0.7);
}

.detail-tags-zh {
  font-size: 12px;
  color: rgba(37, 42, 54, 0.7);
}

.detail-bio {
  margin-top: 10px;
}

.detail-bio p {
  font-size: 14px;
  line-height: 1.65;
}

.detail-bio br {
  display: block;
  margin-top: 10px;
}

.detail-bio .bio-label {
  font-size: 14px;
  color: rgba(37, 42, 54, 0.7);
}

/* ========================================
   SECTION 6: CONTACT
   ======================================== */
.contact-content {
  display: flex;
  align-items: stretch;
  justify-content: center;
  /* Same centering as .join-content: content box midpoint = (100vw − reserve)/2,
     the line the sticky titles and JOIN/ARTISTS content sit on. */
  /* 上方 90px / 底部 110px：與 JOIN 保持間距，同時整塊內容略靠上、
     頁尾留白充足。 */
  padding: 90px calc(var(--page-padding-left) + var(--content-right-reserve)) 110px var(--page-padding-left);
  /* 底部再切掉整頁的 1/5：100vh → 80vh（下限 900px 同比例 → 720px）。
     內容是從上往下排（.contact-subscribe 已改成 margin-top:0，不再靠
     auto margin 撐到底），所以縮高度只是把下方多餘留白吃掉。 */
  min-height: max(80vh, 720px);
}

/* .scroll-section 的 min-height:100vh 也要一起降，否則 section 仍撐滿整屏，
   底部留白照樣存在。 */
#contact.scroll-section {
  min-height: 80vh;
}

.contact-info {
  text-align: center;
  max-width: 900px;
  width: 100%;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: flex-start;
}

.contact-info > .contact-icons-row,
.contact-info > .contact-item {
  width: 100%;
  flex: 0 0 auto;
}

.contact-info > .contact-subscribe {
  /* 面板改成「跟著上方內容往下排」而非釘在底部（原本 margin-top:auto 會把面板
     推到底，一旦頂到圖標列就再也上不去，加多少 margin-bottom 都沒用）。
     現在 email→圖標→面板 整組貼齊上方，位置由下面的 margin-top 直接控制。 */
  margin-top: 0;
  margin-bottom: 0;
}

.contact-item {
  margin-bottom: 60px;
}

.contact-item h3 {
  font-family: var(--font-en);
  font-weight: 700;
  font-size: 26px;
  letter-spacing: 5px;
  margin-bottom: 10px;
}

.contact-item p {
  font-size: 16px;
  letter-spacing: 2px;
}

/* E-mail is a clickable mailto link on desktop (hover underline);
   mobile disables the tap so it stays plain text (see media query below). */
.email-link {
  color: inherit;
  text-decoration: none;
  cursor: pointer;
}
@media (min-width: 1025px) {
  .email-link:hover { text-decoration: underline; }
}

/* App icon row - social logos (shown on desktop + mobile, replaces QR codes) */
.contact-icons-row {
  display: flex;
  justify-content: center;
  gap: 28px;
  /* 圖標列往上：縮小與上方 E-MAIL 的間距 */
  margin-top: 0;
  /* Guaranteed gap before the CTA below — when CTA expands it grows upward
     and would otherwise crowd this row. */
  margin-bottom: 80px;
}

.contact-icons-row img {
  width: 64px;
  height: 64px;
}

/* Icon links keep the flex layout tight (no inline-gap / underline) */
.contact-icons-row a {
  display: inline-flex;
  line-height: 0;
}

/* ─── Subscribe panel (KEEP IN TOUCH WITH US) ─── */
.contact-subscribe {
  position: relative;
  margin-left: auto;
  margin-right: auto;
  margin-bottom: 0;
  width: 100%;
  max-width: 600px;
  background: #ff3a1f;
  color: #fff;
  padding: 60px 40px;
  cursor: pointer;
  transition: padding 0.45s ease;
  user-select: none;
}

/* 面板收合時整塊是「點擊展開」按鈕，故上面設 user-select:none；但底下真正的
   文字與輸入框要能反白／選取，這裡重新開放（單擊展開不受影響，選字需拖曳）。 */
.subscribe-title,
.subscribe-sub,
.subscribe-hint,
.subscribe-input {
  user-select: text;
  -webkit-user-select: text;
}

.contact-subscribe.is-open .click-icon {
  opacity: 0;
  transform: scale(0.9);
}

.click-icon {
  position: absolute;
  width: 86px;
  height: auto;
  pointer-events: none;
  opacity: 1;
  transition: opacity 0.35s ease, transform 0.35s ease;
  filter: drop-shadow(0 0 18px rgba(0,0,0,0.55));
  animation: click-flicker 2.4s ease-in-out infinite;
}

@keyframes click-flicker {
  0%, 100% { opacity: 1; transform: translateY(0); }
  35%       { opacity: 0.45; transform: translateY(-2px); }
  55%       { opacity: 1;    transform: translateY(0); }
  75%       { opacity: 0.6;  transform: translateY(1px); }
}

/* Small-range wander for the subscribe submit button — keeps it lively. */
@keyframes subscribe-btn-drift {
  0%   { transform: translate(0, 0); }
  20%  { transform: translate(2px, -2px); }
  45%  { transform: translate(-2px, 1px); }
  70%  { transform: translate(1px, 2px); }
  100% { transform: translate(0, 0); }
}

.contact-subscribe.is-open .click-icon { animation: none; }

/* 5 click! icons matching original layout: TL inside, TR outside-above, R outside-mid, BL inside, B-center outside */
.click-icon-1 { top: 22px;     left: 16%;  animation-delay: -0.2s; }
.click-icon-2 { top: -42px;    right: 20%; animation-delay: -0.9s; }
.click-icon-3 { top: 52%;      right: -48px; animation-delay: -1.5s; }
.click-icon-4 { bottom: 28px;  left: 4%;   animation-delay: -2.0s; }
.click-icon-5 { bottom: -42px; left: 44%;  animation-delay: -0.6s; }

.subscribe-inner {
  text-align: center;
}

.subscribe-title {
  display: block;
  font-family: var(--font-en);
  font-weight: 700;
  font-size: 22px;
  letter-spacing: 0.06em;
  line-height: 26pt;
  margin-bottom: 10px;
  color: var(--color-text-dark);
}

.subscribe-sub {
  font-family: var(--font-zh);
  font-size: 14px;
  font-weight: 700;
  letter-spacing: 2px;
  margin-bottom: 0;
  color: var(--color-text-dark);
}

.subscribe-form {
  max-height: 0;
  overflow: hidden;
  opacity: 0;
  transition: max-height 0.45s ease, opacity 0.35s ease, margin-top 0.45s ease;
  margin-top: 0;
}

.contact-subscribe.is-open .subscribe-form {
  max-height: 400px;
  opacity: 1;
  margin-top: 22px;
}

/* When expanded, trim the panel's bottom padding so it doesn't leave a big gap
   below the revealed form. */
.contact-subscribe.is-open {
  padding-bottom: 32px;
}

.subscribe-input {
  width: 100%;
  background: transparent;
  border: none;
  border-bottom: 1px solid #2d333a;
  padding: 8px 4px;
  color: var(--color-text-dark);
  font-family: var(--font-zh);
  font-size: 14px;
  letter-spacing: 2px;
  text-align: center;
  outline: none;
}

.subscribe-input::placeholder {
  color: rgba(37,42,54,0.65);
  font-family: var(--font-zh);
  letter-spacing: 2px;
}

/* Strip autofill background on the subscribe field too (see .form-field note) */
.subscribe-input:-webkit-autofill,
.subscribe-input:-webkit-autofill:hover,
.subscribe-input:-webkit-autofill:focus,
.subscribe-input:-webkit-autofill:active {
  -webkit-text-fill-color: var(--color-text-dark);
  caret-color: var(--color-text-dark);
  transition: background-color 9999s ease-in-out 0s;
}

.subscribe-hint {
  margin-top: 14px;
  font-family: var(--font-zh);
  font-size: 13px;
  font-weight: 700;
  font-style: italic;
  letter-spacing: 2px;
  color: var(--color-text-dark);
}

/* ========================================
   COLLAB (placeholder)
   ======================================== */
.collab-content {
  display: flex;
  align-items: center;
  justify-content: center;
  /* Same centering as .join-content — see .contact-content note. */
  padding: 60px calc(var(--page-padding-left) + var(--content-right-reserve)) 40px var(--page-padding-left);
  min-height: 100vh;
}

.collab-placeholder,
.artists-placeholder {
  text-align: center;
}

.collab-placeholder h2,
.artists-placeholder h2 {
  font-family: var(--font-en);
  font-weight: 700;
  font-size: 48px;
  letter-spacing: 8px;
  text-indent: 8px;   /* 補償尾端 letter-spacing，置中不偏左 */
}

.collab-placeholder .zh,
.artists-placeholder .zh {
  font-size: 16px;
  font-weight: 700;
  margin-top: 8px;
}

.collab-placeholder .coming-soon,
.artists-placeholder .coming-soon {
  font-size: 14px;
  margin-top: 30px;
  color: rgba(249, 56, 34, 0.5);
  font-style: italic;
}

/* ── PIECES 蛋糕游標（桌機）──
   動畫 GIF 無法透過 CSS cursor:url() 播放（瀏覽器只會顯示第一格），
   因此改用 JS 讓這顆元素跟隨指標，並把 #collab 內的原生游標隱藏。 */
#cake-cursor {
  position: fixed;
  top: 0;
  left: 0;
  width: 72px;
  height: 72px;
  background: url('../images/cake-cursor.webp?v=3') center / contain no-repeat;
  pointer-events: none;
  z-index: 99999;
  opacity: 0;
  transition: opacity 0.12s ease;   /* 平滑距離驅動的淡入淡出（見 setupSectionCursor edgeOpacity） */
  will-change: transform;
}

#cake-cursor.cake-cursor-visible {
  opacity: 1;
}

body.cake-active #collab,
body.cake-active #collab * {
  cursor: none !important;
}

/* ── ARTISTS「Gathering」游標（桌機）── 與 PIECES 蛋糕游標同一套機制。 */
#gathering-cursor {
  position: fixed;
  top: 0;
  left: 0;
  width: 72px;
  height: 72px;
  background: url('../images/gathering-cursor.webp?v=1') center / contain no-repeat;
  pointer-events: none;
  z-index: 99999;
  opacity: 0;
  transition: opacity 0.12s ease;   /* 平滑距離驅動的淡入淡出（見 setupSectionCursor edgeOpacity） */
  will-change: transform;
}

#gathering-cursor.gathering-cursor-visible {
  opacity: 1;
}

body.gathering-active #artists,
body.gathering-active #artists * {
  cursor: none !important;
}

/* ========================================
   MOBILE SECTION TITLES (hidden on desktop)
   ======================================== */
.mobile-section-title {
  display: none;
}

/* ========================================
   STICKY SECTION BAR (hidden on desktop)
   ======================================== */
#sticky-section-bar {
  display: none;
}

/* ========================================
   NARROW DESKTOP (1025px - 1200px)
   ======================================== */
@media (max-width: 1200px) and (min-width: 1025px) {
  #main-nav {
    gap: 20px;
  }
}

/* ========================================
   MOBILE / TABLET RESPONSIVE (< 1024px)
   Covers phones and tablets — the right-side nav becomes a fullscreen
   overlay menu and panels stack vertically (no horizontal pin-scroll).
   ======================================== */
@media (max-width: 1024px) {
  /* ─── BACKGROUND VIDEO ─── */
  /* Video background - rotate 90deg for portrait mobile */
  #bg-video {
    width: 100vh;
    height: 100vw;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%) rotate(90deg) scale(1.12);
  }

  /* ─── NAVIGATION (fullscreen overlay menu) ─── */
  /* Navigation - hidden by default, toggled via mobile-top-logo */
  #main-nav {
    right: 0;
    top: 0;
    width: 100%;
    height: 100%;
    background: rgba(45, 51, 58, 0.95);
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 15px;
    text-align: center;
    opacity: 0;
    visibility: hidden;
    transition: opacity 0.3s ease, visibility 0.3s ease;
    z-index: 150;
    max-height: none;
    overflow-y: visible;
  }

  #main-nav.open {
    opacity: 1;
    visibility: visible;
  }

  #main-nav.open .nav-item {
    opacity: 0.6;
  }

  #main-nav.open .nav-item.active {
    opacity: 1;
  }

  .nav-en {
    font-size: 22px;
    letter-spacing: 4px;
  }

  .nav-zh {
    font-size: 12px;
    letter-spacing: 2px;
    margin-top: 4px;
  }

  /* Hide back button on mobile (scroll sections don't have them anyway) */
  .back-btn {
    display: none;
  }

  /* ─── BARCODE LOGO / MOBILE TOP LOGO / RED GLOW ─── */
  /* Barcode logo - bottom center */
  #barcode-logo {
    bottom: 28px;
    right: 50%;
    transform: translateX(50%);
    width: 90px;
  }

  /* 上下 logo 原本各有一條 100vw 的 rgba(45,51,58,0.8) 漸層蒙板（::before），
     已移除。改成「捲到畫面上下緣的內容自己變透明」，透出背景影片。

     遮罩掛在各個內容區塊上，不是掛在 #scroll-container —— 容器高兩萬多 px，
     瀏覽器會把這麼大的遮罩降級成「整片均勻淡化」（實測整頁剩約 15%），
     只有元素尺度正常時才會照漸層停點正確渲染。

     四個停點是「視窗上下帶」換算到元素自身座標的結果，由 js/main.js 的
     updateEdgeFade() 每幀寫入。預設值讓 JS 還沒跑時維持完全不透明。
     用 mask 而非 opacity：與既有的 --text-opacity / --icon-opacity /
     team-wiggle 等動畫相乘，不會互相覆蓋。 */
  .edge-fade {
    -webkit-mask-image: linear-gradient(to bottom,
      transparent var(--ef-a, -9999px), #000 var(--ef-b, -9999px),
      #000 var(--ef-c, 99999px), transparent var(--ef-d, 99999px));
    mask-image: linear-gradient(to bottom,
      transparent var(--ef-a, -9999px), #000 var(--ef-b, -9999px),
      #000 var(--ef-c, 99999px), transparent var(--ef-d, 99999px));
  }
  /* Mobile top logo - W O T M text at top */
  #mobile-top-logo {
    display: block;
    position: fixed;
    top: 35px;
    left: 50%;
    transform: translateX(-50%);
    width: 200px;
    z-index: 100;
    cursor: pointer;
  }

  #mobile-top-logo img {
    width: 100%;
    height: auto;
  }

  /* Red glow — raise above the top/bottom logo scrims so the red edge isn't
     masked. The logos are z-index:100 fixed elements, so their ::before
     gradient scrims paint on the "100" layer; lift the glow above that, but
     keep it below the mobile menu overlay (150) and the toast (10000). */
  #red-glow {
    width: 30px;
    z-index: 120;
  }

  /* ─── SCROLL SECTIONS (shared) ─── */
  /* All scroll sections: top padding for fixed mobile-top-logo */
  .scroll-section .page-content {
    padding-top: 100px;
  }

  /* ─── HOME ─── */
  /* HOME - credits visible on mobile too */
  .home-content {
    padding: 0;
    padding-left: 25px;
    padding-top: 0;
    height: 100vh;
  }

  .credits-wrapper {
    max-width: 280px;
  }

  .credits-scroll h3 {
    font-size: 14px;
  }

  .credits-scroll .zh {
    font-size: 12px;
    margin-bottom: 12px;
  }

  .credits-scroll .statement {
    font-size: 14px;
  }

  .home-subtitle {
    font-size: 13px;
  }

  .home-subtitle-zh {
    font-size: 12px;
  }

  .home-tagline {
    font-size: 13px;
  }

  .home-tagline-zh {
    font-size: 12px;
  }

  /* ─── ABOUT (large block: layout, panels, graphics, text overrides) ─── */
  /* ABOUT — mobile: stack graphic composition (scaled to fit) above text.
     Side padding on .about-content matches the rest of the mobile site (25px). */
  .about-content {
    padding: 0 25px;
  }

  .about-panel {
    padding: 50px 0;
    min-height: 100vh;
    display: flex;
    flex-direction: column;
    align-items: stretch;
    justify-content: center;
    gap: 30px;
    overflow: hidden;
  }

  /* For graphic-based panels: keep aspect-ratio composition.
     Width is capped by THREE constraints:
       100%               — fit viewport width
       460px              — don't balloon at narrow breakpoint (calibration size)
       calc(28vh * 1.407) — don't exceed viewport-height budget; mobile graphics
                           use negative-top offsets (e.g. -92%) that scale with
                           inner_width, so when viewport is short they would extend
                           above/below the panel and get clipped. 28vh × aspect
                           keeps total image span (~2.75 × inner_width) within
                           the 100vh − 100px-padding budget on any viewport. */
  .panel-stage .panel-inner,
  .panel-collab-intro .panel-inner,
  .panel-integrate .panel-inner,
  .panel-believe .panel-inner,
  .panel-part-1 .panel-inner,
  .panel-part-2 .panel-inner,
  .panel-part-3 .panel-inner,
  .panel-structure-a .panel-inner,
  .panel-structure-b .panel-inner,
  .panel-structure-c .panel-inner {
    width: min(100%, 460px, calc(28vh * 3000 / 2133));
    margin: 0 auto;
    aspect-ratio: 3000 / 2133;
    min-height: 0;
    transform: none;
    flex-shrink: 0;
  }

  /* ============ Mobile graphic/text position overrides ============
     Desktop rules above are preserved; these only apply < 1024px. */

  /* Panel 2 — STAGE (mobile composition) */
  .panel-stage .g-a01 { left: 26.55%; top: -29.85%; width: 32.66%; }
  .panel-stage .g-a02 { left: 35.04%; top: -40.51%; width: 29.93%; }
  .panel-stage .g-a03 { left: 40.79%; top: -29.85%; width: 32.66%; }
  .panel-stage .g-a04 { left: 19.20%; top: 69.52%;  width: 61.61%; }

  /* Panel 3 — COLLAB (mobile: rotated + repositioned) */
  .panel-collab-intro .g-b01 { left: 5.34%;  top: 14.15%;   width: 79.64%; transform: scaleX(-1) rotate(90deg); }
  .panel-collab-intro .g-b02 { left: 2.41%;  top: -42.27%;  width: 93.90%; transform: rotate(90deg); }
  .panel-collab-intro .g-b03 { left: 17.88%; top: -93.87%;  width: 67.89%; }

  /* Panel 4 — INTEGRATE (mobile)
     c01.top = c04.top% − c01.height/H
             = −51.95% − (0.2438 × 529/915) / (2133/3000)
             = −71.78%   (keeps semicircle flat-bottom flush to c04 top)
     c02.top = c04.top% = −51.95%   (下半圓平邊貼齊正方形頂邊) */
  .panel-integrate .g-c01 { left: 47.18%; top: -71.78%;  width: 24.38%; }
  .panel-integrate .g-c02 { left: 28.01%; top: -51.95%;  width: 54.36%; }
  .panel-integrate .g-c04 {
    left: 21.23%; top: -51.95%; width: 57.55%;
    content: url('../images/about/s_mobile_c_04.webp');
  }
  .panel-integrate .g-c05 { left: 45.93%; top: 156.80%; width: 36.43%; }
  /* Short viewports (iPhone SE 375×667 portrait, or any phone landscape
     where height ≤ 700): inner box shrinks proportionally but text content
     stays roughly the same height, so text + g-c05 collide and g-c05 also
     gets clipped at panel bottom. Sacrifice the decorative g-c05. */
  @media (max-height: 700px) {
    .panel-integrate .g-c05,
    .panel-believe .g-c05 {
      display: none;
    }
  }

  /* Panel 5 — BELIEVE (mobile — shares c01/c02/c04 with Panel 4, distinct c05) */
  .panel-believe .g-c01 { left: 47.18%; top: -71.78%;  width: 24.38%; }
  .panel-believe .g-c02 { left: 28.01%; top: -51.95%;  width: 54.36%; }
  .panel-believe .g-c04 {
    left: 21.23%; top: -51.95%; width: 57.55%;
    content: url('../images/about/s_mobile_c_04.webp');
  }
  .panel-believe .g-c05 { left: 14.43%; top: 150.69%; width: 36.43%; }

  /* Panels 7-9 — PART I/II/III (mobile: dedicated portrait artwork + big overflow positions) */
  .panel-part-1 .g-d01 {
    left: -32.12%; top: -112.06%; width: 162.27%;
    content: url('../images/about/s_mobile_d_02.webp');
  }
  .panel-part-2 .g-d02 {
    left: -25.67%; top: -94.62%;  width: 151.33%;
    content: url('../images/about/s_mobile_d_03.webp');
  }
  .panel-part-3 .g-d03 {
    left: -24.79%; top: -92.94%;  width: 149.58%;
    content: url('../images/about/s_mobile_d_05.webp');
  }

  /* Panel 2 text — mobile (full-width centered band overlaying triangles) */
  .panel-stage .panel-text {
    left: 0 !important;
    top: 42% !important;
    width: 100% !important;
    transform: none !important;
  }

  /* Panel 3 text — mobile */
  .panel-collab-intro .panel-text {
    left: 0 !important;
    top: 40.64% !important;
    width: 100% !important;
  }

  /* Panels 4 & 5 text — mobile */
  .panel-integrate .panel-text,
  .panel-believe .panel-text {
    left: 0 !important;
    top: 17.88% !important;
    width: 100% !important;
  }

  /* Graphics render at full opacity on mobile (same as desktop) */
  .panel-inner img {
    opacity: 1;
  }

  /* Text-only panels (Mission, Journey, Structure Intro): keep panel-inner visible so
     the nested panel-text renders — just drop the aspect-ratio so it collapses to content height */
  .panel-mission .panel-inner,
  .panel-journey-intro .panel-inner,
  .panel-structure-intro .panel-inner {
    aspect-ratio: auto;
    min-height: 0;
    flex: 1;
    display: flex;
    align-items: center;
    justify-content: center;
  }

  /* Panel 10 on mobile — give it 200vh so the centered title gets a full
     viewport-height of scroll on its own before the stack enters and the
     title pins. Without this it would be only 100vh, and the stack
     (Panels 11-13) starts entering immediately, never letting the centered
     title get a dedicated page. */
  .panel-structure-intro {
    min-height: 200vh !important;
  }

  /* Mobile text: only set text-align / padding / z-index / max-width. DO NOT
     force-reset left/top/width/transform — those come from each panel's own
     desktop rule (which the user tunes via the editor on a mobile-sized
     viewport, so the values ARE the mobile values). */
  .panel-mission .panel-text,
  .panel-journey-intro .panel-text,
  .panel-structure-intro .panel-text,
  .panel-stage .panel-text,
  .panel-collab-intro .panel-text,
  .panel-integrate .panel-text,
  .panel-believe .panel-text,
  .panel-part-1 .panel-text,
  .panel-part-2 .panel-text,
  .panel-part-3 .panel-text,
  .panel-structure-a .panel-text,
  .panel-structure-b .panel-text,
  .panel-structure-c .panel-text {
    max-width: 100%;
    text-align: center;
    padding: 0;
    box-sizing: border-box;
    z-index: 10;
  }

  /* Panels 1 / 6 / 10 (Mission / Journey / Structure Intro) — desktop uses
     calc(100vw - 260px) which makes no sense on mobile (no right-side nav).
     Re-center for mobile. */
  .panel-mission .panel-text,
  .panel-journey-intro .panel-text,
  .panel-structure-intro .panel-text {
    left: 50% !important;
    top: 50% !important;
    width: 90% !important;
    transform: translate(-50%, -50%) !important;
  }

  /* Panels 7/8/9 — desktop text values (left:17.07%; top:33%; width:42.49%)
     are relative to panel-inner's short aspect-ratio box, so they render stuck
     in the top-third on mobile. Center absolutely within panel-inner instead
     (graphic is background, text is overlay). */
  .panel-part-1 .panel-text,
  .panel-part-2 .panel-text,
  .panel-part-3 .panel-text {
    position: absolute !important;
    left: 50% !important;
    top: 50% !important;
    width: 90% !important;
    transform: translate(-50%, -50%) !important;
  }

  /* Panels 11/12/13 (Structure A/B/C) — body text centered, shared title
     above renders once via .structure-stack-title (no per-panel title). */
  .panel-structure-a .panel-text,
  .panel-structure-b .panel-text,
  .panel-structure-c .panel-text {
    position: absolute !important;
    left: 50% !important;
    top: 55% !important;
    width: 90% !important;
    transform: translate(-50%, -50%) !important;
  }
  /* Panels 11/12 icons now SHARE the desktop rules — same --st-base sizing,
     same per-icon spin + artwork-centre fix, same top:60vh anchor. The only
     value that must stay responsive is horizontal centring: desktop reserves
     260px on the right for the fixed nav; mobile's nav is a full-screen overlay,
     so centre on the full viewport instead. (Panel 13 c01/c02 below still keep
     their own mobile composite positioning.) */
  /* Mobile keeps the ORIGINAL viewport-fixed cross-fade: the cards stack
     vertically here (the pin wrappers are `display: contents`), so there is no
     horizontal track to travel with. Desktop switched these to `absolute`. */
  .panel-structure-a .panel-inner img,
  .panel-structure-b .panel-inner img,
  .panel-structure-c .panel-inner img {
    position: fixed !important;
  }
  .panel-structure-a .panel-inner img,
  .panel-structure-b .panel-inner img {
    left: 50vw !important;
  }

  /* Panel 13 c01 / c02 — same fixed-fade treatment as desktop, but converted
     from the MOBILE composite positions (c01 34.96%/-37.06%/81.86%,
     c02 -40.73%/20.33%/91.42%) against the mobile inner-box formula
     (min(100% , 460px, 28vh×aspect), centered at 50vw/50vh). */
  .panel-structure-c .panel-inner img {
    /* × 0.85 等比縮小：c01/c02 的 left/top/width 全部由 --st-cw / --st-ch 推導，
       且是以 (50vw, 50vh) 為原點的偏移，所以只縮這一個變數＝整組構圖對中心
       等比縮放，兩顆圖形的相對位置與比例不變。 */
    --st-cw: calc(min(100vw - 50px, 460px, calc(28vh * 3000 / 2133)) * 0.72);
    --st-ch: calc(var(--st-cw) * 2133 / 3000);
    /* 整組水平位移：c01/c02 共用，兩顆一起右移，相對構圖不變。
       綁 --st-cw 而非固定 px，縮放倍率改動時位移量會跟著等比。 */
    --st-c-dx: calc(var(--st-cw) * 0.16);
    opacity: var(--icon-opacity, 0);
  }
  .panel-structure-c .g-st-c01 {
    left: calc(50vw - 0.1504 * var(--st-cw) + var(--st-c-dx)) !important;
    top:  calc(50vh - 0.8706 * var(--st-ch)) !important;
    width: calc(0.8186 * var(--st-cw)) !important;
  }
  .panel-structure-c .g-st-c02 {
    left: calc(50vw - 0.9073 * var(--st-cw) + var(--st-c-dx)) !important;
    top:  calc(50vh - 0.2967 * var(--st-ch)) !important;
    width: calc(0.9142 * var(--st-cw)) !important;
  }

  .panel-inner .about-heading .h-en { font-size: 22px; letter-spacing: 2px; text-indent: 2px; }
  .panel-inner .about-heading .h-zh { font-size: 13px; letter-spacing: 4px; text-indent: 4px; }
  .panel-inner .about-subheading .h-en,
  .panel-inner .structure-subheading .h-en { font-size: 18px; }
  .panel-inner .about-subheading .h-zh,
  .panel-inner .structure-subheading .h-zh { font-size: 12px; }
  .panel-inner .about-body .line-en { font-size: 15px; margin-top: 12px; }
  .panel-inner .about-body .line-zh { font-size: 12px; }
  .panel-inner .journey-list .j-en { font-size: 15px; }
  .panel-inner .journey-list .j-zh { font-size: 12px; }
  /* Morphing structure title — smaller scale on mobile */
  .structure-title-element .about-heading .h-en { font-size: 18px; letter-spacing: 2px; text-indent: 2px; }
  .structure-title-element .about-heading .h-zh { font-size: 12px; letter-spacing: 3px; text-indent: 3px; }

  .about-heading .h-en {
    font-size: 22px;
    letter-spacing: 2px;
    text-indent: 2px;
  }

  .about-heading .h-zh {
    font-size: 13px;
    letter-spacing: 4px;
    text-indent: 4px;
  }

  .about-subheading .h-en {
    font-size: 18px;
  }

  .about-body .line-en {
    font-size: 15px;
  }

  .about-body .line-zh {
    font-size: 12px;
  }

  .about-content > .about-inner {
    padding: 40px 25px 60px 25px;
    /* Don't clip here: this box is inset by .about-content's + its own 25px
       padding, so clipping it would cut the portraits ~50px in from the screen
       edge (the leftmost got sliced). Let the portraits bleed to the true screen
       edge instead — body's overflow-x:hidden still blocks any sideways scroll. */
    overflow-x: visible;
  }

  .about-content > .about-inner > .about-trust,
  .about-content > .about-inner > .about-team,
  .about-content > .about-inner > .about-faq {
    max-width: 100%;
  }

  .about-section-title {
    font-size: 20px;
    letter-spacing: 3px;
    margin-bottom: 30px;
  }

  /* Mobile: keep the centered → pinned titles but scale the type down. No
     right-nav strip on mobile, so center on the full viewport; pin below the
     mobile top-logo bar (~90px), mirroring the STRUCTURE title. */
  .pin-title-intro {
    min-height: 130vh;   /* > viewport so the centered title also holds on mobile before pinning */
  }
  .pin-title-element { left: 50%; }
  .pin-title-element.is-centered,
  .pin-title-element.is-hidden.was-centered { left: 50%; }
  .pin-title-element.is-pinned,
  .pin-title-element.is-hidden.was-pinned { top: 90px; left: 50%; }
  /* Match the STRUCTURE title's smaller mobile scale. */
  .pin-title-element .about-heading .h-en { font-size: 18px; letter-spacing: 2px; text-indent: 2px; }
  .pin-title-element .about-heading .h-zh { font-size: 12px; letter-spacing: 3px; text-indent: 3px; }

  .about-trust {
    padding: 40px 0;
  }

  .trust-cards {
    grid-template-columns: 1fr;
    gap: 18px;
  }

  .trust-card {
    padding: 28px 22px;
  }

  .trust-card h3 {
    font-size: 16px;
  }

  .about-team {
    padding: 40px 0 60px;
  }

  /* Mobile: portraits removed entirely. */
  .team-members { display: none; }

  /* Video replaces the portraits, flowing in normal flow right BELOW the text
     (no absolute positioning → no large empty gap). Matched to the container
     (content-column) width so it lines up with the text; square source shown
     via a 1:1 box. */
  .about-team-bg {
    display: block;
    width: 100%;
    aspect-ratio: 1 / 1;
    height: auto;
    margin-top: 28px;
    object-fit: cover;
  }

  .about-team-text .line-en { font-size: 14px; }
  .about-team-text .line-zh { font-size: 12px; }

  .about-faq {
    padding: 40px 0 20px;
  }

  .faq-question {
    font-size: 14px;
    line-height: 21px;
    padding: 10px 25px 10px 0;
    min-height: 58px;
  }

  .faq-answer p {
    font-size: 13px;
  }

  /* 手機版取消 keep-all（桌機保留）。窄欄只放得下約 20 個字，keep-all 會把
     「兩個標點之間的整個子句」當成不可切開的單位，塞不下就整團擠到下一行，
     前一行只剩 22–50% 的孤兒短行（實測「沒問題的！」自己佔一行 = 65/290px）。
     改回中文逐字斷行，行行才填得滿；WOTM / JOIN 這類英文單字不受影響。 */
  .faq-answer .faq-a-zh {
    word-break: normal;
  }

  /* 題目（.faq-q-zh）刻意「不」改：它是粗體標題、只有兩行，keep-all 讓它斷在
     逗號／問號上（「除了協助商品化，/ 你們還會提供什麼幫助？」）語意完整；
     改成逐字斷行反而會留下「格？」這種兩字孤兒尾行，套 text-wrap: balance
     去救則會斷在詞中間（「如何分 / 潤？」）—— 兩者都比現況差。 */

  /* ─── JOIN ─── */
  /* JOIN - full width card */
  .join-content {
    padding: 100px 35px 100px 35px;
    align-items: flex-start;
    min-height: auto;
  }

  .join-card {
    width: 100%;
    padding: 30px 25px;
  }

  /* 25/25 → 26/27：手機版底線的垂直節距 43(標籤) + 26 + 27 = 96，是 4 的倍數
     （原本 93 是奇數）。節距不是 4 的倍數時，在 125%/150%/175% 系統縮放下
     相鄰兩條線會落在不同的實體像素相位 —— 一條實心、下一條被攤成兩列半調，
     看起來就是粗細不一。比照桌機 .form-field 的 104 節距做法。 */
  .form-row {
    gap: 10px;
    padding-bottom: 26px;
    margin-bottom: 27px;
  }

  /* 底線起點改用固定 left（比照桌機的 left: 245px），不再用固定寬度靠右：
     1) 線更長（390 寬時 120 → 152），2) 每列起點一致對齊，
     3) 窄機（320/360）也不會因為寬度固定而往左壓到標籤上。
     118 = 標籤欄 108 + gap 10，剛好讓過最長的 "Introduction"（102）。 */
  .form-row::after {
    left: 118px;
    right: 0;
    width: auto;
    top: 43px;
  }

  .form-photo-placeholder {
    display: none;
  }

  .form-row .form-field {
    padding-bottom: 0;
    margin-bottom: 0;
  }

  .form-field {
    align-items: flex-start;
    /* 與 .form-row 同一組節距（43 + 26 + 27 = 96），見上方註解。 */
    padding-bottom: 26px;
    margin-bottom: 27px;
    gap: 10px;
  }

  .join-card > .form-field::after {
    left: 118px;
    right: 0;
    width: auto;
    top: 43px;
  }

  .join-card > .form-field {
    margin-left: 0;
  }

  /* 標籤改固定欄寬（最長的 "Introduction" 是 102px），輸入框才能跟底線一樣
     從 118px 起、一路吃到欄位右緣，各列起點也才對得齊。 */
  .form-field label {
    width: 108px;
    flex-shrink: 0;
    min-width: 0;
  }

  .field-en {
    font-size: 16px;
    letter-spacing: 2px;
  }

  .field-zh {
    font-size: 11px;
    white-space: nowrap;
  }

  .form-field input {
    font-size: 12px;
    flex: 1;
    width: auto;
    min-width: 0;
    margin-left: 0;
  }

  /* ─── ARTISTS ─── */
  /* ARTISTS - centered cards */
  .artists-content {
    padding: 100px 25px 100px 25px;
    align-items: flex-start;
    justify-content: flex-start;
    min-height: auto;
  }

  .artists-list {
    gap: 25px;
    width: 100%;
    max-width: 100%;
    margin: 0;
  }

  .artist-card {
    gap: 20px;
    padding: 20px;
    height: auto;
  }

  .artist-photo {
    width: 110px;
    height: 110px;
  }

  .artist-name {
    font-size: 20px;
    letter-spacing: 3px;
  }

  .artist-name-zh {
    font-size: 13px;
  }

  .artist-tags {
    font-size: 13px;
    margin-top: 12px;
  }

  .artist-tags-zh {
    font-size: 11px;
  }

  /* ARTIST DETAIL - full width card */
  .artist-detail-content {
    padding: 100px 25px 100px 25px;
    height: auto;
    align-items: flex-start;
  }

  .detail-card {
    width: 100%;
    padding: 30px 25px 30px 20px;
  }

  .detail-top {
    flex-direction: row;
    gap: 20px;
    margin-bottom: 15px;
  }

  .detail-photo {
    width: 150px;
    height: 180px;
  }

  .detail-name {
    font-size: 26px;
  }

  .detail-tags {
    font-size: 14px;
  }

  .detail-tags-zh {
    font-size: 13px;
  }

  .detail-bio p {
    font-size: 14px;
    line-height: 1.7;
  }

  /* ─── CONTACT ─── */
  /* CONTACT - vertical layout */
  .contact-content {
    /* 依內容自然高度，不再撐滿 100vh；底部留白只需避開固定的條碼 logo。 */
    padding: 0 20px 150px 20px;
    min-height: auto;
  }

  #contact.scroll-section {
    min-height: auto;
  }

  .contact-info {
    max-width: 100%;
  }

  .contact-info > .contact-icons-row {
    margin-top: 30px;
  }

  .contact-info > .contact-subscribe {
    /* 與桌面版一致：紅色面板直接排在 app 圖示列下方，展開時表單向下長。 */
    margin-top: 0;
    margin-bottom: 70px;
    transition: padding 0.45s ease;
  }

  .contact-item {
    margin-bottom: 40px;
  }

  .contact-item h3 {
    font-size: 22px;
    letter-spacing: 4px;
  }

  .contact-item p {
    font-size: 13px;
  }

  /* Email click is desktop-only — on mobile it stays plain, non-tappable text. */
  .email-link {
    pointer-events: none;
    cursor: default;
  }

  /* Mobile keeps the 4 app icons tighter than desktop */
  .contact-icons-row {
    display: flex;
    justify-content: center;
    gap: 18px;
    margin-top: 0;
    margin-bottom: 30px;
  }

  .contact-icons-row img {
    width: 58px;
    height: 58px;
  }

  .contact-subscribe {
    padding: 36px 24px;
    /* Cap at 600px (same as desktop) so the red box doesn't stretch too wide on
       tablet-ish ratios (e.g. iPad Mini). Phones are narrower than 600, so
       width:100% still fills them edge-to-edge. */
    max-width: 600px;
  }

  .click-icon { width: 56px; }
  .click-icon-1 { top: -14px;    right: 12%; left: auto; }
  .click-icon-2 { top: 24%;      left: -22px; right: auto; }
  .click-icon-3 { top: 44%;      right: -22px; }
  .click-icon-4 { bottom: 22px;  left: 4%; }
  .click-icon-5 { bottom: -22px; left: 38%; }

  .subscribe-title { font-size: 18px; letter-spacing: 0.06em; line-height: 22pt; }
  .subscribe-sub  { font-size: 12px; letter-spacing: 1.5px; }
  .subscribe-hint { font-size: 11px; letter-spacing: 1.5px; }


  /* ─── COLLAB / PIECES ─── */
  /* COLLAB - center content vertically on mobile */
  #collab {
    height: 100vh;
    min-height: 100vh;
  }

  .scroll-section .collab-content,
  .scroll-section .artists-content.is-placeholder {
    padding: 0 20px;
    height: 100%;
    min-height: 100vh;
  }

  /* Override the list-mode mobile alignment (flex-start) so the placeholder
     stays centered like PIECES. */
  .scroll-section .artists-content.is-placeholder {
    align-items: center;
    justify-content: center;
  }

  .collab-placeholder h2,
  .artists-placeholder h2 {
    font-size: 28px;
    letter-spacing: 5px;
    text-indent: 5px;
  }

  /* ─── MOBILE SECTION TITLES & STICKY BAR ─── */
  /* Mobile section titles */
  .mobile-section-title {
    display: block;
    position: absolute;
    top: 100px;
    left: 0;
    right: 0;
    text-align: center;
    z-index: 10;
  }

  .mobile-section-title .title-en {
    display: block;
    font-family: var(--font-en);
    font-weight: 700;
    font-size: 22px;
    letter-spacing: 0.09em;
    color: var(--color-primary);
  }

  .mobile-section-title .title-zh {
    display: block;
    font-family: 'GlowSansTC Condensed', var(--font-zh);
    font-weight: 700;
    font-size: 12px;
    letter-spacing: 0.1em;
    color: var(--color-primary);
    margin-top: 4px;
  }

  /* Add extra top padding for sections with titles.
     Artist LIST mode has a .mobile-section-title and needs the offset;
     placeholder mode (.is-placeholder) centers instead, so exclude it. */
  .artists-content:not(.is-placeholder),
  .join-content {
    padding-top: 180px !important;
  }

  /* About has no mobile section title — only clear the fixed mobile header */
  .about-content {
    padding-top: 100px !important;
  }

  /* Sticky section bar */
  #sticky-section-bar {
    display: flex;
    align-items: flex-end;
    justify-content: center;
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    height: 30px;
    padding-bottom: 3px;
    background: var(--color-primary);
    z-index: 1000;
    transition: transform 0.25s ease;
    cursor: pointer;
  }

  #sticky-section-bar.sticky-bar-hidden {
    transform: translateY(-100%);
  }

  #sticky-section-bar.sticky-bar-visible {
    transform: translateY(0);
  }

  #sticky-bar-text {
    font-family: var(--font-en);
    font-weight: 700;
    font-size: 16px;
    color: #000;
    letter-spacing: 0.09em;
  }
}

/* ========================================
   TABLET ADJUSTMENTS (769px - 1024px)
   These widths share the mobile layout above (overlay nav, vertical
   stack), but a few phone-tuned rules need bumping up for tablet
   screen real estate.
   ======================================== */
@media (min-width: 769px) and (max-width: 1024px) {
  /* The bg-video rotation in the mobile block is for portrait phones —
     un-rotate it here so landscape/portrait tablets show the video in
     its native orientation. Scale 1.5 (was 1.12) — tablet aspect ratios
     reveal black gaps top/bottom at the smaller scale. */
  #bg-video {
    width: 100%;
    height: 100%;
    top: 0;
    left: 0;
    transform: scale(1.5);
  }
  /* Home credits column — phone's 280px feels tiny on a tablet. */
  .credits-wrapper {
    max-width: 480px;
  }
  /* Top logo — bigger so it doesn't get lost. */
  #mobile-top-logo {
    width: 280px;
  }
  /* About panel graphics — allow them to grow past the phone 460px cap. */
  .panel-stage .panel-inner,
  .panel-collab-intro .panel-inner,
  .panel-integrate .panel-inner,
  .panel-believe .panel-inner,
  .panel-part-1 .panel-inner,
  .panel-part-2 .panel-inner,
  .panel-part-3 .panel-inner,
  .panel-structure-a .panel-inner,
  .panel-structure-b .panel-inner,
  .panel-structure-c .panel-inner {
    width: min(100%, 640px, calc(36vh * 3000 / 2133));
  }
  /* Panel 13 fixed icons follow the tablet inner-box formula above. */
  .panel-structure-c .panel-inner img {
    --st-cw: min(100vw - 50px, 640px, calc(36vh * 3000 / 2133));
  }
  /* Tablet (e.g. iPad Pro 11" 834×1194 portrait): the 36vh box budget makes
     the inner box tall enough that g-c05 (top ~150%) lands at ~104% of
     viewport height and gets clipped at the panel bottom. The max-height:700px
     hide doesn't fire here (1194 > 700), so the cube would show clipped.
     Sacrifice the decorative g-c05, same as on short phones. */
  .panel-integrate .g-c05,
  .panel-believe .g-c05 {
    display: none;
  }
}

/* Landscape phones — also skip the bg-video rotation (the rotation is
   for portrait orientation only). */
@media (max-width: 768px) and (orientation: landscape) {
  #bg-video {
    width: 100%;
    height: 100%;
    top: 0;
    left: 0;
    transform: scale(1.5);
  }
}

/* ===== Form status + submit (JOIN + Subscribe) ===== */
.form-status {
  /* Was min-height:1.5em + margin:0.75em (≈46px reserved even when empty),
     which pushed the JOIN button down and padded the subscribe panel bottom.
     Collapse when empty; it still grows to show a message (minor shift on error). */
  min-height: 0;
  margin: 0.3em 0;
  font-family: var(--font-zh);
  font-size: 0.9em;
  letter-spacing: 0.05em;
  color: var(--color-primary);
}
.form-status.is-submitting { opacity: 0.7; }
.form-status.is-success { opacity: 1; }
.form-status.is-error {
  font-weight: 700;
  letter-spacing: 0.08em;
}
/* Subscribe panel is on light bg → use site dark color instead of brand red */
.subscribe-form .form-status {
  color: var(--color-text-dark);
}

.form-submit {
  display: inline-block;
  margin-top: 0.8em;
  padding: 0.7em 2em;
  background: var(--color-primary);
  color: var(--color-text-dark);
  border: none;
  border-radius: 999px;
  font-family: var(--font-zh);
  font-weight: 700;
  font-size: 0.95em;
  letter-spacing: 0.12em;
  cursor: pointer;
  transition: opacity 0.2s ease;
}
.form-submit:hover { opacity: 0.85; }
.form-submit:disabled { opacity: 0.4; cursor: wait; }
/* Subscribe submit inverted: dark on light panel */
.subscribe-form .form-submit {
  background: var(--color-bg);
  color: var(--color-primary);
}

/* ── JOIN submit: outlined text button → fills dark on hover (per design spec) ── */
.join-card .form-submit.join-submit {
  display: block;
  width: 650px;            /* design: 650px within the 800px panel */
  max-width: 100%;
  height: 60px;            /* design: 60px tall */
  margin: 1px auto 0;      /* nudged right up; panel's trimmed bottom padding hugs it */
  padding: 0;
  background: transparent;
  color: var(--color-text-dark);
  border: 2px solid var(--color-bg);
  border-radius: 0;
  font-family: var(--font-en);
  font-style: italic;
  font-weight: 700;
  font-size: 24px;
  letter-spacing: 0.1em;
  cursor: pointer;
  transition: background 0.2s ease, color 0.2s ease;
}
.join-card .form-submit.join-submit:hover {
  background: var(--color-bg);
  color: var(--color-primary);
  opacity: 1;
}
.join-card .form-submit.join-submit:disabled {
  opacity: 0.4;
  cursor: wait;
}

/* ── Image-based submit button (JOIN + subscribe) ── */
.form-submit.btn-image,
.subscribe-form .form-submit.btn-image {
  background: none;
  border: none;
  border-radius: 0;
  padding: 0;
  line-height: 0;
  /* Same idle flicker/pulse as the "click!" icons. */
  animation: click-flicker 2.4s ease-in-out infinite;
}
.form-submit.btn-image img {
  display: block;
  width: auto;
  height: 78px;        /* glow padding included; visible pill ~half this */
}
/* Pause the flicker and sit solid while hovered — feels ready to click. */
.form-submit.btn-image:hover { animation-play-state: paused; opacity: 1; }
.form-submit.btn-image:disabled { opacity: 0.4; cursor: wait; animation: none; }

/* ── Subscribe: input (underline) + image button on one row ── */
/* 1fr | input | 1fr keeps the underline dead-centre regardless of the button,
   while the button sits in the right column just past the underline. */
.subscribe-row {
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
}
.subscribe-row .subscribe-input {
  grid-column: 2;
  width: 220px;        /* narrower underline, stays centred */
  justify-self: center;
}
.subscribe-form .form-submit.subscribe-submit.btn-image {
  grid-column: 3;
  justify-self: start;
  margin: 0 0 0 8px;   /* just right of the underline */
  /* Keep the idle flicker (opacity) and add a small-range drift (transform).
     Drift is listed last so it owns transform; flicker still owns opacity. */
  animation: click-flicker 2.4s ease-in-out infinite,
             subscribe-btn-drift 5s ease-in-out infinite;
}
.subscribe-form .form-submit.subscribe-submit.btn-image img {
  height: 60px;
}

.join-card input[aria-invalid="true"],
.subscribe-form input[aria-invalid="true"] {
  border-color: var(--color-primary) !important;
  box-shadow: 0 0 0 1px var(--color-primary);
}

.cf-turnstile { margin-top: 0.5em; }

/* ===== Toast banner (top, full width) ===== */
#wotm-toast-container {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: 10000;
  display: flex;
  flex-direction: column;
  pointer-events: none;
}
.wotm-toast {
  display: flex;
  align-items: center;
  gap: 16px;
  width: 100%;
  padding: 14px clamp(20px, 5vw, 56px);
  background: var(--color-bg);
  color: var(--color-primary);
  font-family: 'GlowSansTC Condensed', var(--font-zh);
  font-size: 16px;
  letter-spacing: 0.06em;
  border-bottom: 2px solid var(--color-primary);
  box-shadow: 0 6px 20px rgba(0, 0, 0, 0.25);
  transform: translateY(-100%);
  transition: transform 0.35s ease;
  pointer-events: auto;
  box-sizing: border-box;
}
.wotm-toast.is-visible { transform: translateY(0); }
.wotm-toast.is-leaving { transform: translateY(-100%); }
.wotm-toast--success { border-bottom-color: var(--color-primary); }
.wotm-toast--error {
  border-bottom-width: 3px;
  font-weight: 700;
  letter-spacing: 0.08em;
}
.wotm-toast__icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 26px;
  height: 26px;
  border: 1.5px solid var(--color-primary);
  border-radius: 50%;
  font-size: 14px;
  font-weight: 700;
  flex-shrink: 0;
  color: var(--color-primary);
}
.wotm-toast--error .wotm-toast__icon { border-width: 2px; }
.wotm-toast__text { flex: 1; }
.wotm-toast__close {
  background: transparent;
  border: none;
  color: var(--color-primary);
  font-size: 22px;
  line-height: 1;
  padding: 0 4px;
  cursor: pointer;
  flex-shrink: 0;
  opacity: 0.7;
  transition: opacity 0.2s ease;
}
.wotm-toast__close:hover { opacity: 1; }
@media (max-width: 1024px) {
  .wotm-toast { font-size: 14px; padding: 12px 16px; gap: 10px; }
  .wotm-toast__icon { width: 22px; height: 22px; font-size: 12px; }
  .wotm-toast__close { font-size: 20px; }

  /* JOIN submit (mobile): MUST live here — after the desktop
     .join-card .form-submit.join-submit rule above — or that later rule wins
     by source order (same specificity, media queries don't add any). */
  .join-card .form-submit.join-submit {
    height: 46px;
    font-size: 18px;
    margin-top: 18px;
  }

  /* Subscribe (mobile): underline stays centred, button overlaid ON its right
     end. MUST live here — after the desktop .subscribe-row grid rules above —
     or those later rules would override it. Position via top/left/margin (NOT
     transform) so the click-flicker animation doesn't fight the placement. */
  .subscribe-row {
    position: relative;
    display: flex;
    justify-content: center;
    align-items: center;
  }
  .subscribe-row .subscribe-input {
    width: 190px;
    /* 防碰撞：按鈕(48px 高 ≈ 105px 寬)疊在列的右端，輸入框右側空位 =
       (列寬 − 190px)/2；不夠 105px 時，右 padding 自動補足差額，
       讓文字區永遠避開按鈕（border-box：底線寬度 190px 不變）。 */
    padding-right: max(4px, calc(105px - (100% - 190px) / 2));
  }
  .subscribe-form .form-submit.subscribe-submit.btn-image {
    position: absolute;
    top: 50%;
    left: auto;
    right: 0;                 /* hug the content's right edge — collision-proof:
                                 it can't exceed .subscribe-row, and the panel's
                                 24px padding + the image's own glow keep the
                                 visible button clear of the red box border. */
    margin: -24px 0 0 0;      /* −½ button height: centre it on the line */
  }
  .subscribe-form .form-submit.subscribe-submit.btn-image img { height: 48px; }
}

/* ===== Admin table styles ===== */
.admin-body {
  margin: 0;
  background: #0b0b0b;
  color: #fff;
  font-family: sans-serif;
  min-height: 100vh;
}
.admin-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 1em 2em;
  border-bottom: 1px solid #222;
  position: sticky;
  top: 0;
  background: rgba(11, 11, 11, 0.95);
  backdrop-filter: blur(6px);
  z-index: 10;
}
.admin-header h1 { margin: 0; font-size: 1.1em; letter-spacing: 0.1em; }
.admin-meta { display: flex; align-items: center; gap: 1em; }
.admin-count { color: rgba(255, 255, 255, 0.6); font-size: 0.9em; }
.admin-logout {
  padding: 0.45em 1em;
  background: transparent;
  color: #fff;
  border: 1px solid #444;
  border-radius: 999px;
  cursor: pointer;
  font-size: 0.85em;
}
.admin-logout:hover { background: #1f1f1f; }
.admin-main { padding: 1.5em 2em; }
.admin-section { margin-bottom: 2.5em; }
.admin-section-title {
  font-size: 1em;
  font-weight: 600;
  letter-spacing: 0.08em;
  margin: 0 0 0.8em;
  padding-bottom: 0.5em;
  border-bottom: 1px solid #222;
  display: flex;
  align-items: baseline;
  gap: 0.8em;
}
.admin-section-title .admin-count { font-weight: 400; font-size: 0.85em; }
.admin-empty {
  padding: 3em 1em;
  text-align: center;
  color: rgba(255, 255, 255, 0.5);
}
.admin-error {
  padding: 1em 2em;
  color: #f6a4a4;
}
.admin-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.88em;
}
.admin-table thead th {
  position: sticky;
  top: 64px;
  background: #111;
  text-align: left;
  padding: 0.7em 0.8em;
  font-weight: 600;
  color: rgba(255, 255, 255, 0.8);
  border-bottom: 1px solid #2a2a2a;
}
.admin-table tbody td {
  padding: 0.7em 0.8em;
  border-bottom: 1px solid #1d1d1d;
  vertical-align: top;
}
.admin-table tbody tr:hover { background: #131313; }
.admin-table .col-time { white-space: nowrap; color: rgba(255, 255, 255, 0.65); font-variant-numeric: tabular-nums; }
.admin-table .col-text { max-width: 22em; }
.admin-table .col-link a { color: #9bb6ff; text-decoration: none; word-break: break-all; }
.admin-table .col-link a:hover { text-decoration: underline; }
.admin-status-select {
  background: #1a1a1a;
  color: #fff;
  border: 1px solid #333;
  border-radius: 6px;
  padding: 0.35em 0.6em;
  font-size: 0.9em;
}
.admin-status-select:disabled { opacity: 0.5; cursor: wait; }

/* ========================================
   ADMIN — 使用者行為儀表板 (/admin/analytics.html)
   /admin/* 的 CSP 是 style-src 'self'，所以這裡不能有 inline style；
   長條的寬度由 js/admin-analytics.js 透過 CSSOM 設定。
   ======================================== */
.admin-nav { display: flex; gap: 1.2em; font-size: 0.85em; }
.admin-nav a {
  color: rgba(255, 255, 255, 0.55);
  text-decoration: none;
  padding-bottom: 0.2em;
  border-bottom: 1px solid transparent;
}
.admin-nav a:hover { color: #fff; }
.admin-nav a.is-current { color: #fff; border-bottom-color: var(--color-primary); }

.admin-range { display: flex; align-items: center; gap: 0.5em; font-size: 0.85em; color: rgba(255, 255, 255, 0.6); }
.admin-columns { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 2em; }
.admin-privacy-note {
  margin: 3em 0 1em;
  padding-top: 1.2em;
  border-top: 1px solid #1d1d1d;
  color: rgba(255, 255, 255, 0.4);
  font-size: 0.8em;
  line-height: 1.7;
}
.admin-table .col-num { text-align: right; font-variant-numeric: tabular-nums; white-space: nowrap; }

/* ── 總覽數字卡 ── */
.stat-grid { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 1em; }
.stat-card { padding: 1.2em 1.3em; background: #111; border: 1px solid #1f1f1f; border-radius: 6px; }
.stat-value {
  font-size: 2.1em;
  font-weight: 600;
  line-height: 1.1;
  font-variant-numeric: tabular-nums;
  color: var(--color-primary);
}
.stat-label { margin-top: 0.35em; font-size: 0.9em; color: rgba(255, 255, 255, 0.85); }
.stat-hint { margin: 0.5em 0 0; font-size: 0.75em; line-height: 1.5; color: rgba(255, 255, 255, 0.4); }

/* ── 每日長條圖 ── */
.daily-chart {
  display: flex;
  align-items: flex-end;
  gap: 3px;
  overflow-x: auto;
  padding-bottom: 0.5em;
}
.day-slot { flex: 1 0 22px; display: flex; flex-direction: column; align-items: center; gap: 0.3em; }
.day-bar { width: 100%; height: 140px; display: flex; align-items: flex-end; }
.day-column { width: 100%; min-height: 2px; background: var(--color-primary); border-radius: 2px 2px 0 0; }
.day-slot:hover .day-column { background: #ff6a56; }
.day-count { font-size: 0.7em; color: rgba(255, 255, 255, 0.65); font-variant-numeric: tabular-nums; }
.day-label { font-size: 0.65em; color: rgba(255, 255, 255, 0.35); white-space: nowrap; }

/* ── 水平長條清單 ── */
.bar-list { display: flex; flex-direction: column; gap: 0.55em; }
.bar-row { display: grid; grid-template-columns: 9em 1fr auto; align-items: center; gap: 0.9em; font-size: 0.85em; }
.bar-label { color: rgba(255, 255, 255, 0.85); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.bar-track { height: 10px; background: #1b1b1b; border-radius: 999px; overflow: hidden; }
.bar-fill { height: 100%; min-width: 2px; background: var(--color-primary); border-radius: 999px; }
.bar-value { color: rgba(255, 255, 255, 0.6); font-variant-numeric: tabular-nums; white-space: nowrap; }

@media (max-width: 900px) {
  .stat-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .admin-columns { grid-template-columns: 1fr; gap: 0; }
  .admin-header { flex-wrap: wrap; gap: 0.8em; }
  .bar-row { grid-template-columns: 7em 1fr auto; }
}
