/* 產品全景圖的樣式 —— index.html 與 en.html 共用。

   抽出來的原因跟 data.*.js 一樣：這 44 KB 原本在兩個頁面各存一份，規則
   完全相同、只有註解語言不同。改一次要記得改兩次，遲早會漏 —— 而漏掉的
   那次不會報錯，只會讓兩個語言版本長得不一樣。

   注意 url() 一律用絕對路徑（開頭的 /）。這個檔案位在 assets/portfolio/，
   相對路徑會以它自己的位置為基準，不是以頁面的位置 —— 背景圖就因此改過。
*/

/* ---- 自架字體 ----------------------------------------------------------
       可變字體，一個檔涵蓋 100..900 全部字重（所以 font-weight:500 也有真實字重，
       不是合成的）。子集只含本站實際出現過的字元，含 <script> 裡那些會被注入 modal 的。
       改文案後請重跑 build/tools/gen-fonts.py，否則新字會落到系統字體（不會變豆腐字）。 */
    @font-face {
      font-family: 'Noto Sans TC';
      font-style: normal;
      font-weight: 100 900;
      font-display: swap;
      src: url('/assets/fonts/noto-sans-tc-subset.woff2') format('woff2');
    }
    @font-face {
      font-family: 'Plus Jakarta Sans';
      font-style: normal;
      font-weight: 200 800;
      font-display: swap;
      src: url('/assets/fonts/plus-jakarta-sans-subset.woff2') format('woff2');
    }

    /* 設計系統變數 - 預設深色模式 (Sleek Space Dark) */
    :root {
      --bg: #060913;
      --surface: rgba(15, 23, 42, 0.72);
      --surface-hover: rgba(30, 41, 59, 0.88);
      --surface-1: rgba(30, 41, 59, 0.5);
      --text: #f3f4f6;
      --text-2: #9ca3af;
      --muted: #6b7280;
      --border: rgba(255, 255, 255, 0.08);
      --border-hover: rgba(255, 255, 255, 0.18);
      --border-strong: rgba(255, 255, 255, 0.25);
      
      /* 品牌層級配色 */
      --orange: #f97316;          /* 應用層 - 活力橘 */
      --bg-orange: rgba(249, 115, 22, 0.12);
      --border-orange: rgba(249, 115, 22, 0.35);
      --text-orange: #fdba74;
      --orange-glow: rgba(249, 115, 22, 0.25);

      --cyan: #06b6d4;            /* 營運層 - 湖水青 */
      --bg-cyan: rgba(6, 182, 212, 0.12);
      --border-cyan: rgba(6, 182, 212, 0.35);
      --text-cyan: #67e8f9;
      --cyan-glow: rgba(6, 182, 212, 0.25);

      --accent: #3b82f6;          /* 平台層 - 科技藍 */
      --bg-accent: rgba(59, 130, 246, 0.12);
      --border-accent: rgba(59, 130, 246, 0.35);
      --text-accent: #93c5fd;
      --accent-glow: rgba(59, 130, 246, 0.25);

      --success: #10b981;         /* 擷取層 - 安全綠 */
      --bg-success: rgba(16, 185, 129, 0.12);
      --border-success: rgba(16, 185, 129, 0.35);
      --text-success: #6ee7b7;
      --success-glow: rgba(16, 185, 129, 0.25);

      --business: #8b5cf6;        /* 商業層 - 活力紫 */
      --bg-business: rgba(139, 92, 246, 0.12);
      --border-business: rgba(139, 92, 246, 0.35);
      --text-business: #c4b5fd;
      --business-glow: rgba(139, 92, 246, 0.25);

      --shadow: 0 10px 30px -10px rgba(0, 0, 0, 0.5);
      --glass-blur: blur(16px);
      color-scheme: dark;
    }

    * {
      box-sizing: border-box;
    }

    /* Keyboard focus must stay visible. :focus-visible keeps the ring off for
       mouse/touch, so this costs the pointer experience nothing. */
    :focus-visible {
      outline: 2px solid var(--text-accent);
      outline-offset: 3px;
      border-radius: 4px;
    }
    .card:focus-visible {
      outline: 2px solid var(--text-accent);
      outline-offset: 4px;
    }

    body {
      margin: 0;
      background-color: var(--bg);
      color: var(--text);
      /* PingFang TC / JhengHei / Noto Sans CJK 是明確的中文備援：子集若缺字，
         會落到這些字體而不是 sans-serif 的預設，字形差異最小。 */
      font-family: "Plus Jakarta Sans", "Noto Sans TC", "PingFang TC",
                   "Microsoft JhengHei", "Noto Sans CJK TC", sans-serif;
      line-height: 1.6;
      -webkit-font-smoothing: antialiased;
      min-height: 100vh;
      display: flex;
      flex-direction: column;
      justify-content: space-between;
      overflow-x: hidden;
      position: relative;
    }

    /* 疊加遮罩以確保文字高對比度與質感 */
    /* The backdrop lives on a fixed pseudo-element instead of
       `background-attachment: fixed`, which causes bad scroll jank on iOS
       Safari. Image + dark scrim are stacked in one paint here. */
    body::before {
      content: '';
      position: fixed;
      inset: 0;
      z-index: -1;
      pointer-events: none;
      background-image:
        linear-gradient(rgba(6, 9, 19, 0.85), rgba(6, 9, 19, 0.85)),
        url('/images/bg.webp');
      background-size: cover;
      background-position: center;
      background-repeat: no-repeat;
    }

    .wrap {
      max-width: 860px;
      width: 100%;
      margin: 0 auto;
      padding: 40px 20px 60px;
      position: relative;
      z-index: 1;
    }

    /* 頂部 Header */
    .head {
      text-align: center;
      margin-bottom: 25px;
      position: relative;
    }

    /* 語言切換 */
    .lang-toggle {
      position: absolute;
      top: 0;
      right: 0;
      display: inline-flex;
      align-items: center;
      gap: 5px;
      font-size: 12.5px;
      font-weight: 600;
      color: var(--text-2);
      background: var(--surface-1);
      border: 1px solid var(--border);
      border-radius: 20px;
      padding: 6px 13px;
      text-decoration: none;
      letter-spacing: 0.04em;
      transition: all 0.25s ease;
      z-index: 5;
    }
    .lang-toggle:hover {
      color: var(--text);
      background: var(--surface-hover);
      border-color: var(--border-hover);
    }
    .lang-toggle i { font-size: 15px; }
    /* three languages (zh / en / ja): a group of links, the current one highlighted */
    nav.lang-toggle { gap: 2px; padding: 3px; }
    nav.lang-toggle:hover { background: var(--surface-1); border-color: var(--border); }
    nav.lang-toggle > i { color: var(--text-2); padding: 0 4px 0 8px; }
    nav.lang-toggle a { color: var(--text-2); text-decoration: none; border-radius: 16px; padding: 4px 10px; transition: all 0.25s ease; }
    nav.lang-toggle a:hover { color: var(--text); background: var(--surface-hover); }
    nav.lang-toggle a[aria-current] { color: var(--text); background: var(--surface-hover); pointer-events: none; }
    @media (max-width: 640px) {
      nav.lang-toggle { position: static; display: flex; width: max-content; margin: 0 0 12px auto; }
    }

    .head h1 {
      font-size: 26px;
      font-weight: 700;
      margin: 0;
      letter-spacing: 0.1em;
      background: linear-gradient(135deg, var(--text) 30%, var(--text-accent) 100%);
      -webkit-background-clip: text;
      -webkit-text-fill-color: transparent;
      display: inline-block;
    }

    .head p {
      font-size: 14px;
      color: var(--text-2);
      margin: 6px 0 0;
      font-weight: 400;
    }

    /* 銷售情境篩選器 (Scenario Filter) */
    .filter-section {
      background: rgba(15, 23, 42, 0.45);
      backdrop-filter: var(--glass-blur);
      -webkit-backdrop-filter: var(--glass-blur);
      border: 1px solid var(--border);
      border-radius: 20px;
      padding: 16px;
      margin-bottom: 35px;
      box-shadow: var(--shadow);
      display: flex;
      flex-direction: column;
      gap: 10px;
    }

    .filter-label {
      font-size: 12px;
      font-weight: 700;
      color: var(--text-accent);
      text-transform: uppercase;
      letter-spacing: 0.08em;
      display: flex;
      align-items: center;
      gap: 6px;
    }

    .filter-buttons {
      display: flex;
      flex-wrap: wrap;
      gap: 8px;
    }

    .filter-btn {
      background: var(--surface-1);
      border: 1px solid var(--border);
      color: var(--text-2);
      padding: 8px 14px;
      border-radius: 12px;
      font-size: 12.5px;
      font-weight: 600;
      cursor: pointer;
      display: inline-flex;
      align-items: center;
      gap: 6px;
      transition: all 0.25s cubic-bezier(0.4, 0, 0.2, 1);
    }

    .filter-btn:hover {
      background: var(--surface-hover);
      color: var(--text);
      border-color: var(--border-hover);
    }

    .filter-btn.active {
      background: linear-gradient(135deg, var(--accent) 0%, #1d4ed8 100%);
      color: #ffffff;
      border-color: var(--accent);
      box-shadow: 0 4px 12px rgba(59, 130, 246, 0.3);
    }

    .filter-btn[data-scenario="mobile"].active {
      background: linear-gradient(135deg, var(--success) 0%, #065f46 100%);
      box-shadow: 0 4px 12px rgba(16, 185, 129, 0.3);
    }
    .filter-btn[data-scenario="billing"].active {
      background: linear-gradient(135deg, var(--business) 0%, #5b21b6 100%);
      box-shadow: 0 4px 12px rgba(139, 92, 246, 0.3);
    }

    /* 分層佈局 */
    .layer-container {
      display: flex;
      flex-direction: column;
    }

    .layer {
      display: flex;
      align-items: stretch;
      gap: 16px;
      opacity: 0;
      transform: translateY(20px);
      animation: fadeInUp 0.6s cubic-bezier(0.16, 1, 0.3, 1) forwards;
      transition: opacity 0.4s cubic-bezier(0.4, 0, 0.2, 1);
    }

    /* 進場動畫延遲 */
    .layer:nth-child(9) { animation-delay: 0.1s; } /* 商業 */
    .layer:nth-child(7) { animation-delay: 0.2s; } /* 擷取 */
    .layer:nth-child(5) { animation-delay: 0.3s; } /* 平台 */
    .layer:nth-child(3) { animation-delay: 0.4s; } /* 營運 */
    .layer:nth-child(1) { animation-delay: 0.5s; } /* 應用 */

    @keyframes fadeInUp {
      to {
        opacity: 1;
        transform: translateY(0);
      }
    }

    /* 右側分層發光徽章標籤 (.lab) */
    .lab {
      width: 90px;
      flex: none;
      display: flex;
      flex-direction: column;
      align-items: center;
      justify-content: center;
      font-size: 12px;
      font-weight: 700;
      border-left: 2px dashed var(--border);
      padding-left: 14px;
      margin-left: 4px;
      letter-spacing: 0.05em;
      transition: opacity 0.4s, color 0.3s;
      gap: 4px;
    }

    .lab-badge {
      display: flex;
      flex-direction: column;
      align-items: center;
      gap: 5px;
      border-radius: 12px;
      padding: 10px 8px;
      width: 100%;
      text-align: center;
      transition: all 0.3s ease;
      font-weight: 700;
      font-size: 12px;
      border-width: 1px;
      border-style: solid;
    }

    .lab-badge i {
      font-size: 15px;
      transition: color 0.3s;
    }

    /* 側邊欄五層主題色適配 - 顏色分明化 */
    .lab-badge.badge-app {
      background: var(--bg-orange);
      border-color: var(--border-orange);
      color: var(--text-orange);
      box-shadow: 0 0 12px var(--orange-glow);
    }
    .lab-badge.badge-app i {
      color: var(--text-orange);
    }

    .lab-badge.badge-ops {
      background: var(--bg-cyan);
      border-color: var(--border-cyan);
      color: var(--text-cyan);
      box-shadow: 0 0 12px var(--cyan-glow);
    }
    .lab-badge.badge-ops i {
      color: var(--text-cyan);
    }

    .lab-badge.badge-plat {
      background: var(--bg-accent);
      border-color: var(--border-accent);
      color: var(--text-accent);
      box-shadow: 0 0 12px var(--accent-glow);
    }
    .lab-badge.badge-plat i {
      color: var(--text-accent);
    }

    .lab-badge.badge-success {
      background: var(--bg-success);
      border-color: var(--border-success);
      color: var(--text-success);
      box-shadow: 0 0 12px var(--success-glow);
    }
    .lab-badge.badge-success i {
      color: var(--text-success);
    }
    
    .lab-badge.badge-business {
      background: var(--bg-business);
      border-color: var(--border-business);
      color: var(--text-business);
      box-shadow: 0 0 12px var(--business-glow);
    }
    .lab-badge.badge-business i {
      color: var(--text-business);
    }

    .body {
      flex: 1;
      min-width: 0;
      display: flex;
      flex-direction: column;
      justify-content: center;
    }

    /* 連接線 */
    .up-flow {
      display: flex;
      justify-content: center;
      align-items: center;
      height: 28px;
      color: var(--muted);
      font-size: 14px;
      position: relative;
      transition: opacity 0.4s;
    }

    .up-flow::before {
      content: '';
      position: absolute;
      top: 0;
      bottom: 0;
      left: calc(50% - 49px);
      width: 1px;
      background: linear-gradient(180deg, var(--border) 0%, transparent 100%);
    }

    .up-flow i {
      animation: pulseUpDown 2s infinite ease-in-out;
      background: transparent;
      padding: 2px 0;
      z-index: 2;
      /* 箭頭原本用 --muted，在深底上幾乎看不見，整張圖因此讀不出方向。
         分層圖本身不指方向，讀者就不知道該由上往下還是由下往上讀 ——
         那才是「擷取放太下面」那種違和感的來源，不是順序本身。 */
      color: var(--text-cyan);
      opacity: .75;
    }

    @keyframes pulseUpDown {
      0%, 100% { transform: translateY(-2px); opacity: 0.4; }
      50% { transform: translateY(2px); opacity: 1; color: var(--accent); }
    }

    /* 卡片基本樣式 */
    .card {
      background: var(--surface);
      backdrop-filter: var(--glass-blur);
      -webkit-backdrop-filter: var(--glass-blur);
      border: 1px solid var(--border);
      border-radius: 16px;
      padding: 18px 20px;
      cursor: pointer;
      transition: all 0.4s cubic-bezier(0.25, 0.8, 0.25, 1);
      position: relative;
      overflow: hidden;
      box-shadow: var(--shadow);
    }

    .card::before {
      content: '';
      position: absolute;
      inset: 0;
      background: linear-gradient(135deg, rgba(255,255,255,0.05) 0%, transparent 100%);
      pointer-events: none;
    }

    /* 卡片被篩選時的狀態 */
    .card.dimmed {
      opacity: 0.25;
      pointer-events: none;
      transform: scale(0.97);
    }

    .card.highlighted {
      transform: scale(1.03);
      border-color: var(--border-hover);
      box-shadow: 0 15px 35px -5px rgba(0, 0, 0, 0.35);
    }

    /* 綠色呼吸燈點 */
    .pulse-dot {
      display: inline-block;
      width: 8px;
      height: 8px;
      background-color: #10b981;
      border-radius: 50%;
      box-shadow: 0 0 8px #10b981;
      animation: pulseGreen 1.8s infinite ease-in-out;
      margin-left: 6px;
      vertical-align: 2px;
    }

    @keyframes pulseGreen {
      0% { transform: scale(0.85); box-shadow: 0 0 0 0 rgba(16, 185, 129, 0.8); }
      70% { transform: scale(1.15); box-shadow: 0 0 0 6px rgba(16, 185, 129, 0); }
      100% { transform: scale(0.85); box-shadow: 0 0 0 0 rgba(16, 185, 129, 0); }
    }

    /* 紫色動態流光邊框 */
    .shimmer-border {
      position: relative;
      border: 1px solid transparent !important;
      background: linear-gradient(var(--surface), var(--surface)) padding-box,
                  linear-gradient(90deg, var(--business), #d8b4fe, var(--business), #c084fc, var(--business)) border-box !important;
      background-size: 200% auto;
      animation: shimmerEffect 4s linear infinite;
    }

    .card.shimmer-border:hover {
      animation: shimmerEffect 2s linear infinite;
    }

    @keyframes shimmerEffect {
      to { background-position: 200% center; }
    }

    /* 商業層卡片 */
    .band-business {
      border-color: var(--border-business);
    }
    .band-business:hover {
      border-color: var(--business);
      box-shadow: 0 15px 30px -10px var(--business-glow);
    }
    .card.highlighted.band-business {
      box-shadow: 0 0 25px var(--business-glow);
    }
    .band-business .bt {
      color: var(--text-business);
      display: flex;
      align-items: center;
      justify-content: center;
      gap: 10px;
    }
    .band-business .bt img {
      height: 26px;
      width: auto;
      filter: drop-shadow(0 0 14px rgba(139, 92, 246, 0.35));
    }
    .band-business .bt .title-text {
      font-size: 18px;
      font-weight: 700;
      letter-spacing: -0.01em;
    }

    /* 應用層卡片 */
    .band-app {
      border-color: var(--border-orange);
    }
    .band-app:hover {
      border-color: var(--orange);
      box-shadow: 0 15px 30px -10px var(--orange-glow);
    }
    .card.highlighted.band-app {
      border-color: var(--orange);
      box-shadow: 0 0 25px var(--orange-glow);
    }
    .band-app .bt {
      color: var(--text-orange);
      display: flex;
      align-items: center;
      justify-content: center;
      gap: 10px;
    }
    .band-app .bt img {
      height: 26px;
      width: auto;
      filter: drop-shadow(0 0 14px rgba(249, 115, 22, 0.35));
    }
    .band-app .bt .title-text {
      font-size: 18px;
      font-weight: 700;
      letter-spacing: -0.01em;
    }

    /* ══ XMap 為什麼是一條橫帶而不是一張卡 ═══════════════════
       XMap 疊在下方任一平台之上（CliO 兩版，或客戶既有的 NX / Milestone
       / 利凌），並不跟它們爭同一個位置。畫成置中的一張卡時，讀者會把它
       當成「平台層上面那一格產品」，於是必然要問「XMap 和 CliO Enterprise
       我該買哪個」。改成橫跨整排的帶、再用三條腿落在下方三格，這個誤會
       不必寫字就消失。
       底部的 ResellerHub 用同一套語彙：橫帶＝橫跨全部，卡片＝單一產品。 */
    .band-hub {
      border-color: var(--border-cyan);
    }
    .band-hub:hover {
      border-color: var(--cyan);
      box-shadow: 0 15px 30px -10px var(--cyan-glow);
    }
    .card.highlighted.band-hub {
      border-color: var(--cyan);
      box-shadow: 0 0 25px var(--cyan-glow);
    }
    .band-hub .bt {
      color: var(--text-cyan);
      display: flex;
      align-items: center;
      justify-content: center;
      gap: 10px;
    }
    .band-hub .bt img {
      height: 24px;
      width: auto;
      filter: drop-shadow(0 0 14px rgba(6, 182, 212, 0.35));
    }
    .band-hub .bt .title-text {
      font-size: 18px;
      font-weight: 700;
      letter-spacing: -0.01em;
    }
    /* 「疊加、不取代」是這張圖最需要講的一句話,給它自己的位置 */
    .hub-note {
      margin-top: 7px;
      text-align: center;
      font-size: 12px;
      color: var(--text-cyan);
      opacity: .82;
    }
    .hub-note b { font-weight: 700; }
    /* Xboard takes events, not video: its note is orange, and no video line runs up into it */
    .hub-note.app-note { color: var(--text-orange); }
    .up-flow.up-gap::before { display: none; }

    /* 三條腿:XMap 橫跨下面三欄,而不是接在某一欄上。
       這三條線是 C 排法的整個重點,所以畫得比一般連接線重。 */
    .hub-legs {
      display: grid;
      grid-template-columns: 1fr 1fr 1fr;
      gap: 12px;
      height: 30px;
      margin-right: 106px;   /* .lab 90px + .layer gap 16px */
    }
    .hub-legs span {
      justify-self: center;
      position: relative;
      width: 2px;
      height: 100%;
      background: linear-gradient(180deg, var(--cyan) 0%, rgba(6, 182, 212, 0.15) 100%);
      opacity: .85;
    }
    /* 落點的小圓,讓「蓋在這三個之上」有明確著地點 */
    .hub-legs span::after {
      content: '';
      position: absolute;
      left: 50%; bottom: -3px;
      width: 7px; height: 7px;
      margin-left: -3.5px;
      border-radius: 50%;
      background: var(--cyan);
      box-shadow: 0 0 10px var(--cyan-glow);
    }

    /* Xboard 是一個產品,不是一個橫跨層 —— 只有真正橫跨的
       XMap(頂蓋) 與 ResellerHub(底座) 才做成整排的帶。 */
    .layer .body > .band-app {
      max-width: 560px;
      margin: 0 auto;
      width: 100%;
    }

    /* ══ 影像從哪裡進到平台 ═════════════════════════════════
       兩條路,差別就是這張圖最該講清楚的一件事:

         第 1 欄  既有設備 → Smart Gateway → CliO 雲端
         第 2 欄  既有設備 ─────────────→ CliO Enterprise

       第 1 欄的線被 Gateway 卡片中斷,第 2 欄的線連續穿過中間那格 ——
       上雲需要 Gateway 橋接,地端不需要。這個對比不必寫字就讀得出來。
       第 3 欄(第三方平台)不畫線:NX / Milestone / 利凌自己就錄影,
       不靠我們的現場層。 */
    .flow-legs {
      display: grid;
      grid-template-columns: 1fr 1fr 1fr;
      gap: 12px;
      height: 22px;
    }
    .flow-legs span {
      justify-self: center;
      position: relative;
      width: 2px;
      height: 100%;
      background: linear-gradient(0deg, rgba(59, 130, 246, 0.12) 0%, var(--accent) 100%);
      opacity: .75;
    }
    .flow-legs span.none { background: none; }
    /* 小圓在頂端 —— 影像往上流,圓點標的是這一段的終點 */
    .flow-legs span:not(.none)::after {
      content: '';
      position: absolute;
      left: 50%; top: -3px;
      width: 6px; height: 6px;
      margin-left: -3px;
      border-radius: 50%;
      background: var(--accent);
      box-shadow: 0 0 9px var(--accent-glow);
    }

    /* tag 拉到卡片右上角，脫離標題行。
       它原本是 .nt 的 flex item，會跟產品名搶同一行的水平空間 —— 現場層的
       格子只有平台層 1/3 寬，"Smart Gateway" 就是這樣被擠成「Smart /
       Gateway」兩行的。絕對定位之後每張卡都放得下 tag，標題也不必讓位。 */
    .card > .tag,
    .card .nt > .tag,
    .card .bt > .tag {
      position: absolute;
      top: 15px;
      right: 16px;
      margin-left: 0;
      z-index: 2;
    }
    .site-row .node .nt span.title-text { white-space: nowrap; }

    /* 窄卡（平台層與現場層只有 1/3 寬）讓 tag 獨佔右上角，標題另起一行。
       量過：Smart Gateway 的 logo + 標題 + tag 需要 259px，格子只有 189px。
       縮字級、縮短 tag、縮 logo 全部加起來也補不上這 70px，而且會讓這張卡
       的字比隔壁小一號。把 tag 移出標題那一行才是真正的解 —— 代價是卡片高
       26px，三格等高所以整排一起長，視覺仍然整齊。
       橫帶（Xboard / XMap / ResellerHub）寬度綽綽有餘，維持原樣。 */
    .node .nt { padding-top: 26px; }

    /* 中間那格不放卡片,只讓線直接穿過去 */
    .pass { position: relative; }
    .pass::before {
      content: '';
      position: absolute;
      left: 50%; top: 0; bottom: 0;
      width: 2px;
      margin-left: -1px;
      background: var(--accent);
      opacity: .5;
    }
    /* 第三欄的留白會被當成「漏畫」,所以說明它為什麼是空的 */
    .no-need {
      display: flex;
      align-items: center;
      justify-content: center;
      text-align: center;
      font-size: 11px;
      line-height: 1.6;
      color: var(--muted);
      opacity: .65;
      padding: 0 10px;
    }

    .band-legacy {
      border: 1px dashed rgba(148, 163, 184, 0.34);
      border-radius: 14px;
      padding: 11px 18px;
      text-align: center;
      background: rgba(148, 163, 184, 0.035);
    }
    .legacy-t {
      font-size: 13px;
      font-weight: 700;
      color: #94a3b8;
      letter-spacing: 0.01em;
    }
    .legacy-s {
      margin-top: 4px;
      font-size: 11.5px;
      color: #7f8ea3;
    }
    .legacy-s b { color: #94a3b8; font-weight: 700; }

    /* 分層圖之外的兩個區塊 */
    .aside-block {
      margin-top: 34px;
      padding-top: 26px;
      border-top: 1px dashed var(--border);
    }
    .aside-head { margin-bottom: 14px; }
    .aside-kicker {
      display: inline-flex;
      align-items: center;
      gap: 6px;
      font-size: 11px;
      font-weight: 700;
      letter-spacing: 0.08em;
      color: var(--muted);
      text-transform: uppercase;
    }
    .aside-head h3 {
      margin: 5px 0 3px;
      font-size: 19px;
      font-weight: 700;
      letter-spacing: -0.01em;
    }
    .aside-head p {
      margin: 0;
      font-size: 12.5px;
      color: var(--muted);
    }
    .aside-flow {
      display: flex;
      align-items: center;
      gap: 14px;
    }
    .aside-flow > .card { flex: 1 1 auto; min-width: 0; }
    .aside-flow > i {
      color: var(--success);
      font-size: 18px;
      flex: none;
      opacity: .8;
    }
    .fstep {
      flex: 0 0 190px;
      border: 1px dashed rgba(148, 163, 184, 0.3);
      border-radius: 12px;
      padding: 13px 14px;
      font-size: 12px;
      line-height: 1.55;
      color: #94a3b8;
      text-align: center;
      background: rgba(148, 163, 184, 0.035);
    }

    .grid3 {
      display: grid;
      grid-template-columns: 1fr 1fr 1fr;
      gap: 12px;
    }

    /* 第三方 VMS:不是我們的產品,所以畫成虛線且不可點。
       它在圖上的作用是證明 XMap 疊得上去的不只有 CliO。 */
    .card.ghost {
      border-style: dashed;
      border-left-color: var(--muted);
      background: transparent;
      opacity: .6;
      cursor: default;
    }
    .card.ghost:hover {
      border-color: var(--border);
      box-shadow: none;
      transform: none;
    }
    .card.ghost .title-text { color: var(--muted); }
    .tag.tghost {
      background: rgba(148, 163, 184, 0.10);
      color: var(--muted);
      border-color: rgba(148, 163, 184, 0.22);
    }

    /* 一般節點樣式 */
    .node {
      border-left-width: 4px;
    }
    .node.fix {
      border-left-color: var(--accent);
    }
    .node.fix:hover {
      border-color: var(--accent);
      box-shadow: 0 12px 25px -10px var(--accent-glow);
    }
    .card.highlighted.node.fix {
      border-color: var(--accent);
      box-shadow: 0 0 22px var(--accent-glow);
    }
    .node.mob {
      border-left-color: var(--success);
    }
    .node.mob:hover {
      border-color: var(--success);
      box-shadow: 0 12px 25px -10px var(--success-glow);
    }
    .card.highlighted.node.mob {
      border-color: var(--success);
      box-shadow: 0 0 22px var(--success-glow);
    }

    .node .nt {
      font-size: 16px;
      font-weight: 700;
      display: flex;
      align-items: center;
      gap: 8px;
    }

    .node .nt span.title-text {
      font-size: 16px;
      font-weight: 700;
      letter-spacing: -0.01em;
    }

    .node .nt img {
      height: 22px;
      width: auto;
      filter: drop-shadow(0 0 8px rgba(255, 255, 255, 0.12));
      vertical-align: middle;
    }

    .node .nt i {
      font-size: 18px;
      color: var(--muted);
      transition: color 0.3s;
    }
    .node.fix:hover .nt i {
      color: var(--text-accent);
    }
    .node.mob:hover .nt i {
      color: var(--text-success);
    }

    /* 卡片副標題樣式 */
    .ns, .bs {
      font-size: 12.5px;
      color: var(--text-2);
      margin-top: 6px;
      line-height: 1.5;
      /* Each feature is one flex item, so a narrow screen wraps between
         features instead of splitting a phrase mid-way. */
      display: flex;
      flex-wrap: wrap;
      gap: 2px 14px;
    }

    .bs { justify-content: center; }

    .feat {
      display: inline-flex;
      align-items: baseline;
      gap: 4px;
    }

    .ns i, .bs i {
      font-size: 11.5px;
      color: var(--text-accent);
      opacity: 0.75;
      margin-right: 2px;
      vertical-align: -1px;
    }

    .card[data-k="xboard"] .bs i {
      color: var(--text-orange);
    }

    .card[data-k="xmap"] .ns i {
      color: var(--text-cyan);
    }

    .card[data-k="liveedge"] .ns i {
      color: var(--text-success);
    }

    .card[data-k="resellerhub"] .bs i {
      color: var(--text-business);
    }

    /* 網格版面 */
    .grid2 {
      display: grid;
      grid-template-columns: 1fr 1fr;
      gap: 12px;
    }

    /* 藥丸標籤 */
    .tag {
      font-size: 10px;
      padding: 2px 8px;
      border-radius: 20px;
      font-weight: 600;
      letter-spacing: 0.02em;
      flex: none;
    }
    .tapp {
      background: rgba(249, 115, 22, 0.10);
      color: var(--text-orange);
      border: 1px solid var(--border-orange);
    }
    .thub {
      background: rgba(6, 182, 212, 0.10);
      color: var(--text-cyan);
      border: 1px solid var(--border-cyan);
    }
    .tbiz {
      background: rgba(139, 92, 246, 0.12);
      color: var(--text-business);
      border: 1px solid var(--border-business);
    }
    /* 橫帶本身不是 .card,自己處理定位 */
    .band-legacy { position: relative; }
    .legacy-tag { position: absolute; top: 13px; right: 16px; }

    .tfix {
      background: var(--bg-accent);
      color: var(--text-accent);
      border: 1px solid var(--border-accent);
    }
    .tmob {
      background: var(--bg-success);
      color: var(--text-success);
      border: 1px solid var(--border-success);
    }

    /* 圖例與說明 */
    /* 補充材料入口（新增，不影響既有規則） */
    .more-link-section { margin-top: 26px; display: flex; flex-direction: column;
      align-items: center; gap: 10px; }
    .more-link {
      display: flex; align-items: center; gap: 12px;
      max-width: 560px; width: 100%;
      padding: 14px 18px; border-radius: 14px;
      background: var(--surface-1); border: 1px solid var(--border);
      color: var(--text-2); text-decoration: none; font-size: 12.5px; line-height: 1.6;
      transition: background .18s ease, border-color .18s ease, color .18s ease;
    }
    .more-link:hover { background: var(--surface-hover); border-color: var(--border-hover); color: var(--text); }
    .more-link b { display: block; color: var(--text); font-size: 13.5px; font-weight: 600; margin-bottom: 1px; }
    .more-link > span { flex: 1; min-width: 0; }
    .more-link > .ti:first-child { font-size: 20px; color: var(--text-accent); flex: none; }
    .more-link > .ti:last-child { font-size: 16px; flex: none; }

    /* 銷售速查入口。刻意放在頁首下面、而不是併進下方的 .more-link-section：
       經銷商到站第一件想知道的是「現場怎麼講」，補充材料是看完架構才會點的。 */
    .guide-banner {
      display: flex; align-items: center; gap: 14px;
      max-width: 720px; width: 100%;
      margin: 0 auto 22px;
      padding: 15px 20px; border-radius: 14px;
      background: linear-gradient(135deg, rgba(59, 130, 246, 0.16), rgba(139, 92, 246, 0.12));
      border: 1px solid var(--border-accent);
      color: var(--text-2); text-decoration: none; font-size: 12.5px; line-height: 1.6;
      transition: border-color .18s ease, transform .18s ease, box-shadow .18s ease;
    }
    .guide-banner:hover {
      border-color: var(--border-strong); color: var(--text);
      transform: translateY(-1px); box-shadow: 0 10px 26px -14px var(--accent-glow);
    }
    .guide-banner b { display: block; color: var(--text); font-size: 14.5px; font-weight: 700; margin-bottom: 2px; }
    .guide-banner > span { flex: 1; min-width: 0; }
    .guide-banner > .ti:first-child { font-size: 22px; color: var(--text-accent); flex: none; }
    .guide-banner > .ti:last-child { font-size: 16px; flex: none; }
    @media (max-width: 560px) {
      .guide-banner { padding: 14px 16px; gap: 11px; }
      .guide-banner > .ti:first-child { font-size: 20px; }
    }

    /* 3D 數位雙生入口：緊接在銷售速查下面（使用者 2026-10-13：這是好用的素材，不要藏在頁尾） */
    .guide-banner:has(+ .twin-banner) { margin-bottom: 10px; }
    .twin-banner { background: linear-gradient(135deg, rgba(255, 180, 84, 0.14), rgba(57, 208, 255, 0.10)); }
    .twin-banner > .ti:first-child { color: #ffb454; }
    .twin-thumbs { display: flex; gap: 6px; flex: none; }
    .twin-thumbs img { width: 78px; height: 44px; object-fit: cover; border-radius: 6px; border: 1px solid var(--border); }
    @media (max-width: 720px) { .twin-thumbs img:nth-child(n+2) { display: none; } }
    @media (max-width: 460px) { .twin-thumbs { display: none; } }

    .legend {
      display: flex;
      gap: 20px;
      justify-content: center;
      margin-top: 30px;
      font-size: 12px;
      color: var(--text-2);
      flex-wrap:wrap;
      opacity: 0;
      animation: fadeIn 0.8s ease forwards;
      animation-delay: 0.7s;
    }

    @keyframes fadeIn {
      to { opacity: 1; }
    }

    .legend-item {
      display: flex;
      align-items: center;
      gap: 6px;
    }

    .dot {
      display: inline-block;
      width: 10px;
      height: 10px;
      border-radius: 3px;
    }

    /* 彈出視窗 (Modal Overlay) */
    .overlay {
      position: fixed;
      inset: 0;
      background: rgba(4, 7, 13, 0.75);
      backdrop-filter: blur(10px);
      -webkit-backdrop-filter: blur(10px);
      display: flex;
      align-items: center;
      justify-content: center;
      padding: 20px;
      opacity: 0;
      pointer-events: none;
      transition: opacity 0.3s cubic-bezier(0.16, 1, 0.3, 1);
      z-index: 100;
    }

    .overlay.open {
      opacity: 1;
      pointer-events: auto;
    }

    .modal {
      background: rgba(13, 20, 38, 0.96);
      backdrop-filter: var(--glass-blur);
      -webkit-backdrop-filter: var(--glass-blur);
      border: 1px solid var(--border-strong);
      border-radius: 24px;
      max-width: 660px;
      width: 100%;
      padding: 26px;
      transform: scale(0.95) translateY(10px);
      transition: transform 0.3s cubic-bezier(0.34, 1.56, 0.64, 1);
      max-height: 88vh;
      overflow-y: auto;
      box-shadow: 0 30px 60px -12px rgba(0, 0, 0, 0.8);
    }

    .overlay.open .modal {
      transform: scale(1) translateY(0);
    }

    /* 情境大圖 Banner */
    .modal-banner {
      width: 100%;
      height: 200px;
      background-size: cover;
      background-position: center;
      border-radius: 16px;
      margin-bottom: 20px;
      border: 1px solid rgba(255, 255, 255, 0.1);
      box-shadow: inset 0 0 40px rgba(0,0,0,0.5);
      position: relative;
    }

    .modal-header {
      display: flex;
      justify-content: space-between;
      align-items: flex-start;
      gap: 16px;
      margin-bottom: 16px;
    }

    .modal-header img {
      filter: drop-shadow(0 0 10px rgba(255, 255, 255, 0.15));
    }

    .modal-title-group h2 {
      font-size: 22px;
      font-weight: 700;
      margin: 4px 0 0;
      letter-spacing: -0.01em;
      display: flex;
      align-items: center;
      gap: 8px;
    }

    .modal-title-group h2 i {
      color: var(--accent);
    }

    .pill-large {
      display: inline-block;
      font-size: 11px;
      padding: 4px 12px;
      border-radius: 20px;
      font-weight: 600;
      letter-spacing: 0.03em;
    }

    .xbtn {
      border: none;
      background: var(--surface-1);
      cursor: pointer;
      font-size: 18px;
      color: var(--text-2);
      width: 32px;
      height: 32px;
      border-radius: 50%;
      display: flex;
      align-items: center;
      justify-content: center;
      transition: all 0.2s ease;
      border: 1px solid var(--border);
    }

    .xbtn:hover {
      background: var(--surface-hover);
      color: var(--text);
      transform: rotate(90deg);
    }

    /* 痛點與解決方案分欄 */
    .pain-solution-grid {
      display: grid;
      grid-template-columns: 1fr 1fr;
      gap: 14px;
      margin-bottom: 16px;
    }

    .pain-box {
      background: rgba(239, 68, 68, 0.04);
      border: 1px solid rgba(239, 68, 68, 0.15);
      border-left: 4px solid #ef4444;
      padding: 12px 14px;
      border-radius: 12px;
    }
    
    .pain-box h3 {
      margin: 0 0 6px;
      color: #f87171;
      font-size: 13.5px;
      font-weight: 700;
      display: flex;
      align-items: center;
      gap: 6px;
    }

    .solution-box {
      background: rgba(59, 130, 246, 0.04);
      border: 1px solid rgba(59, 130, 246, 0.15);
      border-left: 4px solid var(--accent);
      padding: 12px 14px;
      border-radius: 12px;
    }

    .solution-box.mob-solution {
      background: rgba(16, 185, 129, 0.04);
      border-color: rgba(16, 185, 129, 0.15);
      border-left-color: var(--success);
    }

    .solution-box h3 {
      margin: 0 0 6px;
      color: var(--text-accent);
      font-size: 13.5px;
      font-weight: 700;
      display: flex;
      align-items: center;
      gap: 6px;
    }

    .solution-box.mob-solution h3 {
      color: var(--text-success);
    }

    .pain-solution-grid p {
      margin: 0;
      font-size: 12px;
      line-height: 1.55;
      color: var(--text-2);
    }

    /* 其他 Modal 元件 */
    .pos {
      font-size: 14px;
      color: var(--text);
      line-height: 1.55;
      background: var(--surface-1);
      padding: 12px 16px;
      border-radius: 12px;
      border-left: 3px solid var(--accent);
      margin-bottom: 16px;
    }
    
    .pos.mob-border {
      border-left-color: var(--success);
    }

    .origin {
      font-size: 12.5px;
      color: var(--text-2);
      line-height: 1.6;
      margin: -8px 0 16px;
      padding: 0 6px;
      font-style: italic;
    }

    .mlab {
      font-size: 11px;
      font-weight: 700;
      color: var(--muted);
      margin: 18px 0 8px;
      text-transform: uppercase;
      letter-spacing: 0.1em;
      display: flex;
      align-items: center;
      gap: 6px;
    }

    .mlab::after {
      content: '';
      flex: 1;
      height: 1px;
      background: var(--border);
    }

    /* 水平架構流 */
    .flow {
      display: flex;
      align-items: stretch;
      gap: 8px;
      margin-top: 10px;
    }

    .step {
      background: var(--surface-1);
      border: 1px solid var(--border);
      border-radius: 12px;
      padding: 10px 12px;
      flex: 1;
      min-width: 90px;
      display: flex;
      flex-direction: column;
      justify-content: center;
    }

    .steplab {
      font-size: 10px;
      font-weight: 700;
      color: var(--muted);
      margin-bottom: 4px;
      text-transform: uppercase;
      display: flex;
      align-items: center;
      gap: 4px;
    }

    .steplab i {
      font-size: 12px;
    }

    .stepv {
      font-size: 11.5px;
      color: var(--text);
      line-height: 1.4;
      font-weight: 500;
    }

    .arrow {
      display: flex;
      align-items: center;
      justify-content: center;
      color: var(--muted);
      font-size: 14px;
      flex: none;
      animation: pulseRight 1.5s infinite ease-in-out;
    }

    @keyframes pulseRight {
      0%, 100% { transform: translateX(0); opacity: 0.5; }
      50% { transform: translateX(3px); opacity: 1; }
    }

    /* 重點項目 */
    .hi {
      font-size: 13px;
      color: var(--text);
      line-height: 1.55;
      display: flex;
      gap: 8px;
      margin: 8px 0;
      align-items: flex-start;
    }

    .hi i {
      color: var(--accent);
      font-size: 15px;
      margin-top: 3px;
      flex: none;
    }
    
    .hi.mob-icon i {
      color: var(--success);
    }

    /* 案例區塊 */
    .casebox {
      background: var(--bg-accent);
      border-radius: 12px;
      padding: 12px 14px;
      font-size: 13px;
      line-height: 1.55;
      color: var(--text);
      margin-top: 8px;
      border: 1px dashed var(--border-accent);
      display: flex;
      gap: 8px;
      align-items: flex-start;
    }
    
    .casebox.mob-case {
      background: var(--bg-success);
      border-color: var(--border-success);
    }

    .casebox i {
      color: var(--accent);
      font-size: 17px;
      margin-top: 2px;
      flex: none;
    }
    
    .casebox.mob-case i {
      color: var(--success);
    }

    /* 備註區塊 */
    .notebox {
      font-size: 12px;
      color: var(--text-2);
      line-height: 1.55;
      border-left: 3px solid var(--border-strong);
      padding-left: 12px;
      margin-top: 8px;
      font-style: italic;
    }

    .notebox i {
      font-size: 13px;
      vertical-align: -1px;
    }

    /* 按鈕連結 */
    .lnk {
      display: inline-flex;
      align-items: center;
      justify-content: center;
      gap: 8px;
      font-size: 13.5px;
      font-weight: 600;
      color: #ffffff;
      background: linear-gradient(135deg, var(--accent) 0%, #1d4ed8 100%);
      margin-top: 18px;
      text-decoration: none;
      border-radius: 12px;
      padding: 10px 20px;
      width: 100%;
      transition: all 0.3s ease;
      box-shadow: 0 4px 12px rgba(59, 130, 246, 0.3);
    }

    .lnk:hover {
      transform: translateY(-2px);
      box-shadow: 0 6px 16px rgba(59, 130, 246, 0.4);
      filter: brightness(1.1);
    }

    .lnk i {
      font-size: 16px;
    }

    /* 型錄下載按鈕 */
    .dl-row {
      display: grid;
      grid-template-columns: 1fr 1fr;
      gap: 10px;
      margin-top: 10px;
    }
    .dl-btn {
      display: flex;
      align-items: center;
      gap: 10px;
      text-decoration: none;
      background: var(--surface-1);
      border: 1px solid var(--border);
      border-radius: 12px;
      padding: 11px 14px;
      color: var(--text);
      transition: all 0.25s ease;
    }
    .dl-btn:hover {
      background: var(--surface-hover);
      border-color: var(--border-accent);
      transform: translateY(-2px);
    }
    .dl-btn i {
      font-size: 24px;
      color: #ef4444;
      flex: none;
    }
    .dl-btn span {
      display: flex;
      flex-direction: column;
      line-height: 1.3;
      font-size: 13.5px;
      font-weight: 600;
    }
    .dl-btn small {
      font-size: 11px;
      font-weight: 400;
      color: var(--text-2);
    }
    @media (max-width: 640px) {
      .dl-row { grid-template-columns: 1fr; }
    }

    /* 延伸簡報清單 */
    .res-list {
      display: flex;
      flex-direction: column;
      gap: 8px;
      margin-top: 10px;
    }
    .res-item {
      display: flex;
      align-items: center;
      justify-content: space-between;
      gap: 12px;
      background: var(--surface-1);
      border: 1px solid var(--border);
      border-radius: 12px;
      padding: 11px 14px;
    }
    .res-name {
      display: flex;
      align-items: center;
      gap: 8px;
      font-size: 13.5px;
      font-weight: 600;
      color: var(--text);
    }
    .res-name i {
      font-size: 17px;
      color: var(--text-accent);
      flex: none;
    }
    .res-dl {
      display: flex;
      gap: 8px;
      flex: none;
    }
    .res-pill {
      display: inline-flex;
      align-items: center;
      gap: 5px;
      font-size: 11.5px;
      font-weight: 600;
      color: var(--text-accent);
      background: var(--bg-accent);
      border: 1px solid var(--border-accent);
      border-radius: 20px;
      padding: 5px 12px;
      text-decoration: none;
      transition: all 0.2s ease;
    }
    .res-pill:hover {
      background: var(--surface-hover);
      color: var(--text);
      border-color: var(--border-hover);
    }
    .res-pill i { font-size: 14px; }

    /* 架構總覽圖。這種圖的資訊密度在 660px 的 modal 裡讀不了，
       所以縮圖只是入口 —— 點下去用整個視窗看，並附 PDF 原檔。 */
    .mlab-hint {
      margin-left: 8px; font-weight: 400; font-size: 10px;
      color: var(--muted); letter-spacing: 0.04em; text-transform: none;
    }
    .archfig { margin: 0; }
    .archfig img {
      display: block; width: 100%; height: auto; border-radius: 12px;
      border: 1px solid var(--border); cursor: zoom-in;
      background: #0a0f1c; transition: border-color .2s ease;
    }
    .archfig img:hover { border-color: var(--border-accent); }
    .archfig figcaption { margin-top: 8px; text-align: right; }
    .archfig figcaption a {
      display: inline-flex; align-items: center; gap: 6px;
      font-size: 11.5px; font-weight: 600; color: var(--text-2);
      text-decoration: none; padding: 5px 11px; border-radius: 20px;
      background: var(--surface-1); border: 1px solid var(--border);
    }
    .archfig figcaption a:hover { color: var(--text); border-color: var(--border-hover); }
    .archfig figcaption i { font-size: 15px; color: #ef4444; }

    /* 產品影片 —— 點擊前完全不碰 YouTube。
       這個站自架字型與圖示就是為了不讓第三方拖慢首屏；直接放 iframe 會在
       每次開啟 modal 時載入 YouTube 的 JS 並種 cookie，即使使用者根本沒按
       播放。所以預設只有一張本地縮圖，按下去才換成 iframe（並用
       youtube-nocookie 網域）。播放鍵是純 CSS 三角形，不必為了一個圖示去
       重新產生自架的 Tabler 子集。 */
    .vembed {
      position: relative;
      display: block;
      width: 100%;
      padding: 0;
      border: 1px solid var(--border);
      border-radius: 14px;
      overflow: hidden;
      background: #000;
      cursor: pointer;
      transition: border-color .3s, box-shadow .3s;
    }
    .vembed:hover, .vembed:focus-visible {
      border-color: var(--border-accent);
      box-shadow: 0 12px 28px -14px var(--accent-glow);
    }
    .vembed img { width: 100%; height: auto; display: block; }
    .vplay {
      position: absolute;
      inset: 0;
      display: flex;
      align-items: center;
      justify-content: center;
      background: rgba(4, 8, 14, 0.26);
      transition: background .3s;
    }
    .vembed:hover .vplay { background: rgba(4, 8, 14, 0.12); }
    .vplay::before {
      content: '';
      width: 58px;
      height: 58px;
      border-radius: 50%;
      background: rgba(204, 31, 43, 0.92);
      box-shadow: 0 6px 24px rgba(0, 0, 0, 0.45);
      transition: transform .3s;
    }
    .vplay::after {
      content: '';
      position: absolute;
      width: 0; height: 0;
      margin-left: 6px;
      border-left: 19px solid #fff;
      border-top: 12px solid transparent;
      border-bottom: 12px solid transparent;
    }
    .vembed:hover .vplay::before { transform: scale(1.08); }
    .vframe {
      position: relative;
      width: 100%;
      aspect-ratio: 16 / 9;
      border: 1px solid var(--border);
      border-radius: 14px;
      overflow: hidden;
      background: #000;
    }
    .vframe iframe { position: absolute; inset: 0; width: 100%; height: 100%; border: 0; }
    /* 流程動畫的嵌入框：高度由嵌入頁回報（postMessage），先給一個接近的預設值。 */
    .vframe.aframe { aspect-ratio: auto; height: 620px; background: #0f1729; }
    .anim-page { display: inline-block; margin: 8px 0 4px; font-size: 12.5px; font-weight: 600;
      color: var(--text-accent); text-decoration: none; }
    .anim-page:hover { text-decoration: underline; }
    /* 3D 情境示範：連到 /twin-* 獨立頁，不嵌入（WebGL 在 modal 裡太重） */
    .twin-links { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px; }
    .twin-link {
      display: block; overflow: hidden; border: 1px solid var(--border); border-radius: 14px;
      background: var(--surface-1); color: var(--text-2); text-decoration: none; font-size: 12.5px;
      transition: border-color .3s, box-shadow .3s;
    }
    .twin-link:hover, .twin-link:focus-visible {
      border-color: var(--border-accent); box-shadow: 0 12px 28px -14px var(--accent-glow);
    }
    .twin-link img { width: 100%; height: auto; display: block; }
    .twin-link span { display: block; padding: 9px 12px 11px; line-height: 1.5; }
    .twin-link b { display: block; color: var(--text); font-size: 13.5px; font-weight: 600; }
    .twin-link b::after { content: ' →'; color: var(--text-accent); }
    @media (max-width: 560px) { .twin-links { grid-template-columns: 1fr; } }


    /* 放大檢視。獨立於產品 modal 之上 —— 關掉它要回到 modal，不是回到頁面。 */
    #zoom {
      position: fixed; inset: 0; z-index: 200; display: flex;
      align-items: center; justify-content: center; padding: 24px;
      background: rgba(3, 6, 12, .93); backdrop-filter: blur(6px);
      opacity: 0; pointer-events: none; transition: opacity .22s ease;
    }
    #zoom.open { opacity: 1; pointer-events: auto; }
    #zoom img {
      max-width: 100%; max-height: 100%; border-radius: 10px;
      border: 1px solid var(--border-strong);
    }
    #zoom .zoom-close {
      position: absolute; top: 20px; right: 20px; width: 40px; height: 40px;
      border-radius: 50%; border: 1px solid var(--border);
      background: var(--surface-1); color: var(--text-2);
      font-size: 20px; cursor: pointer; line-height: 1;
    }
    #zoom .zoom-close:hover { background: var(--surface-hover); color: var(--text); }

    @media (max-width: 480px) {
      .res-item { flex-direction: column; align-items: flex-start; gap: 8px; }
    }

    /* 頁尾 */
    .foot {
      margin-top: 40px;
      font-size: 12px;
      color: var(--muted);
      text-align: center;
      opacity: 0;
      animation: fadeIn 0.8s ease forwards;
      animation-delay: 0.8s;
      letter-spacing: 0.05em;
    }

    .sr-only {
      position: absolute;
      width: 1px;
      height: 1px;
      overflow: hidden;
      clip: rect(0 0 0 0);
    }

    /* 響應式調整 */
    @media (max-width: 640px) {
      .wrap {
        padding: 24px 14px 40px;
      }
      .grid2, .grid3 {
        grid-template-columns: 1fr;
        gap: 10px;
      }
      .aside-flow { flex-direction: column; align-items: stretch; }
      .aside-flow > i { transform: rotate(90deg); align-self: center; }
      .fstep { flex: none; }
      /* 單欄之後「對齊欄位」這件事不存在了，線會落在跟卡片無關的位置。
         它們表達的關係在既有設備橫帶的說明文字裡已經講完，直接收掉。 */
      .hub-legs,
      .flow-legs,
      .pass,
      .no-need { display: none; }
      .pain-solution-grid {
        grid-template-columns: 1fr;
        gap: 10px;
      }
      .flow {
        flex-direction: column;
        gap: 6px;
      }
      .arrow {
        transform: rotate(90deg);
        margin: 2px 0;
        animation: pulseDown 1.5s infinite ease-in-out;
      }
      .modal {
        padding: 20px;
      }
      .head h1 {
        font-size: 24px;
      }
      .lab {
        width: 76px;
        padding-left: 8px;
      }
      .lab-badge {
        padding: 8px 4px;
        font-size: 11px;
      }
    }

    @keyframes pulseDown {
      0%, 100% { transform: translateY(0) rotate(90deg); opacity: 0.5; }
      50% { transform: translateY(3px) rotate(90deg); opacity: 1; }
    }

    /* ============================================================
       Mobile layout + accessibility pass
       ============================================================ */

    @media (max-width: 640px) {
      /* The scenario filter used to wrap into six rows (~570px tall), pushing
         every product card below the fold on a 375px screen. One horizontally
         scrollable row keeps the products visible on first paint. */
      .filter-buttons {
        flex-wrap: nowrap;
        overflow-x: auto;
        scroll-snap-type: x proximity;
        -webkit-overflow-scrolling: touch;
        margin: 0 -16px;
        padding: 2px 16px;
        scrollbar-width: none;
      }
      .filter-buttons::-webkit-scrollbar { display: none; }
      .filter-btn {
        flex: none;
        scroll-snap-align: start;
        min-height: 44px;      /* touch target floor */
        padding: 10px 16px;
        font-size: 13px;
      }

      /* Layer badges move from a right-hand column (which ate ~180px of a
         375px screen) to a single chip above each layer. */
      .layer {
        flex-direction: column-reverse;   /* .lab is last in the DOM */
        align-items: stretch;
        gap: 8px;
      }
      .lab {
        width: auto;
        flex-direction: row;
        justify-content: flex-start;
        border-left: none;
        padding-left: 0;
        margin-left: 0;
      }
      .lab-badge {
        width: auto;
        flex-direction: row;
        align-items: center;
        gap: 6px;
        padding: 5px 12px;
        font-size: 11.5px;
      }
      .lab-badge i { font-size: 14px; }

      /* The -49px offset assumed the right-hand label column; centre it now. */
      .up-flow::before { left: 50%; }

      .lang-toggle { min-height: 44px; padding: 8px 14px; }
    }

    @media (prefers-reduced-motion: reduce) {
      *, *::before, *::after {
        animation-duration: 0.01ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: 0.01ms !important;
        scroll-behavior: auto !important;
      }
      /* These start at opacity:0 and rely on an animation to reveal them —
         pin them visible so reduced-motion never leaves blank content. */
      .layer, .foot { opacity: 1 !important; transform: none !important; }
    }

    /* ══ Flow net (assets/portfolio/flow-net.js) ═══════════════════════
       A light pulse climbs each connector, staggered by height, so the eye reads the
       diagram bottom-up the way video travels. Hover or a scenario keeps one path lit. */
    .fn-pk {
      position: absolute; left: 50%; bottom: -16px; width: 4px; height: 16px; margin-left: -2px;
      border-radius: 2px; pointer-events: none; opacity: 0;
      background: linear-gradient(0deg, transparent, var(--fn-c, #93c5fd));
      box-shadow: 0 0 8px var(--fn-c, #93c5fd);
      animation: fn-up 2.8s linear infinite; animation-delay: var(--d, 0s);
    }
    .up-flow .fn-pk { left: calc(50% - 49px); }    /* that line sits on the diagram body's centre */
    .hub-legs .fn-pk, .up-flow .fn-pk { --fn-c: #67e8f9; }
    @keyframes fn-up {
      0% { bottom: -16px; opacity: 0; }
      10% { opacity: 1; }
      34% { bottom: 100%; opacity: 0; }
      100% { bottom: 100%; opacity: 0; }
    }
    .fn-edge { transition: opacity .3s; }
    .layer-container.fn-focus .fn-edge.fn-off { opacity: .16; }
    .layer-container.fn-focus .fn-edge.fn-off .fn-pk { animation: none; opacity: 0; }
    .layer-container.fn-focus .fn-edge.fn-on { opacity: 1; filter: drop-shadow(0 0 4px rgba(147, 197, 253, .7)); }

    /* one sentence about the chosen scenario, under the filter buttons */
    .fn-cap {
      margin: 12px 0 0; padding: 8px 12px; border-left: 3px solid var(--accent);
      background: rgba(59, 130, 246, .08); border-radius: 0 8px 8px 0;
      font-size: 13px; line-height: 1.7; color: var(--text);
    }
    .fn-cap[hidden] { display: none; }

    /* dashed ONVIF link from the LiveEdge block up into the third-party card */
    .fn-onvif { position: absolute; z-index: 3; pointer-events: none; overflow: visible; }
    .fn-onvif path { fill: none; stroke: var(--success); stroke-width: 1.6; stroke-linecap: round; stroke-linejoin: round; }
    .fn-onvif path:first-child { stroke-dasharray: 5 6; opacity: .55; animation: fn-dash 1.2s linear infinite; }
    .fn-onvif text { fill: var(--success); font-size: 10.5px; font-weight: 700; letter-spacing: .06em; opacity: .8; }
    .fn-onvif.fn-on path:first-child { opacity: 1; stroke-width: 2; }
    .fn-onvif.fn-off { opacity: .2; }
    @keyframes fn-dash { to { stroke-dashoffset: -11; } }
    /* event link: Smart Gateway -> Xboard. Orange like the application layer, so it never reads as video */
    .fn-onvif.fn-event path { stroke: var(--orange); }
    .fn-onvif.fn-event text { fill: var(--text-orange); }

    /* small device icons: the customer's own gear at the bottom, the mobile devices on the left */
    .dev-ico { display: flex; justify-content: center; gap: 14px; margin-bottom: 6px; color: var(--muted); }
    .dev-ico svg { width: 22px; height: 22px; }
    .band-legacy .dev-ico { color: #9ca3af; }
    .fstep .dev-ico { gap: 10px; color: #6ee7b7; }

    @media (prefers-reduced-motion: reduce) {
      .fn-pk { display: none; }
      .fn-onvif path:first-child { animation: none; }
    }
