/* ================================================================
   Board Sea Technology — 內頁共用元件

   design-b 是單頁設計，所以這些內頁才需要的東西她沒做過：
   頁首區、麵包屑、表格、篩選列、分頁、chevron 步驟條、文章內文。
   本檔逐一補上，**全部從她既有的 token 推導，不發明任何數值**
   （DESIGN.md 硬約束 ⑥：缺 token 就停下來回報，不可就地發明）。

   由 _head.php 依 $page['css'] 載入，排在 01–05 之後。首頁不載。

   ── 沿用的硬約束（她的交接契約，內頁一樣要守）──
   ①  :root 以外禁止字面 hex / rgb() / hsl() / 非階梯 px
   ③  :focus-visible 一律 3px ring ＋ 2px 間距，禁裸 outline:none
   ④  觸控目標 ≥44px，相鄰間距 ≥8px
   ⑤  document.scrollWidth 不得超過 clientWidth
   ⑦  法律連結與聯絡管道無真實目的地時一律 EmptyState（非 <a>、無 href）
   ⑩  Marcellus 禁 faux bold
   一般 hover 位移預算 0px、禁 scale()；:active 一律 translateY(--motion-press-offset)
   ================================================================ */


/* ── 內頁頁首 ────────────────────────────────────────────────────
   每支內頁 <main> 的第一個區塊，由 component('page-hero') 產生。

   字級走 --type-role-page-title-*，那是 h1 階的 role 別名。
   首頁的 <h1>（HERO 標題）用的是 h2 階，內頁大標比它高一級——
   這是 DESIGN.md h1._unassigned 寫好的用途，不是新發明的字級。
   別名會自動跟著四斷點的 scale 覆寫走，所以本檔不需要任何 media query。 */
.page-hero {
  padding-block: var(--section-padding-block);
  background-color: var(--surface-page);
  border-block-end: var(--border-width-hairline) solid var(--border-hairline);
}

.page-hero__title {
  font-family: var(--type-role-page-title-family);
  font-size: var(--type-role-page-title-size);
  line-height: var(--type-role-page-title-line-height);
  letter-spacing: var(--type-role-page-title-letter-spacing);
  font-weight: var(--type-role-page-title-weight);
  /* ⑩ Marcellus 只有 400，禁止瀏覽器代為加粗 */
  font-synthesis: none;
  color: var(--text-primary);
  margin-block: var(--section-head-gap) 0;
  /* floor_guard 的第二層保險，照 .hero__title / .section-title 的既有寫法。
     ⚠️ 2026-08-21 補：套版時漏了這一行，實測 375px 下
     「GPU Infrastructure Services」「About Board Sea Technology」等長單字
     撐破 312px 的容器 → **整份文件出現水平捲軸**（/about/ 362>360、
     /services/ 419>360、infrastructure-strategy 419>360、deployment 384>360）。
     ⚠️ 這個缺陷在 Chrome headless 的 --window-size 下量不到：它最窄只到
     500 CSS px，而問題只在 <500px 出現。要量真手機寬度得把頁面放進
     同源 iframe（媒體查詢會對 iframe 的 viewport 求值）。 */
  /* floor_guard 的第二層保險，照 .hero__title / .section-title 的既有寫法。
     ⚠️ 2026-08-21 補：套版時漏了這一行，實測 375px 下「GPU Infrastructure Services」
     「About Board Sea Technology」等長單字撐破 312px 容器 → 整份文件出現水平捲軸。
     ⚠️ 但它**只保證不溢出，不保證好看**：實測會把字攔腰砍成「Infrastruct / ure」。
        試過加 hyphens: auto 讓它帶連字號 —— 無效，overflow-wrap: anywhere 會搶先
        在任意位置斷開；而且 66px 下光是「Infrastruc-」就有 340px，超過容器寬，
        **任何斷點都放不下**。真正的原因是字級，已在 01-tokens.css 處理。
        這一行留著當最後保險（遇到超長字仍然不會溢出）。 */
  overflow-wrap: anywhere;
}

/* eyebrow 直接沿用她的 .eyebrow，這裡只補與大標之間的節奏 */
.page-hero .eyebrow + .page-hero__title {
  margin-block-start: var(--section-head-gap);
}

.page-hero__lead {
  margin-block-start: var(--space-5);
}

/* lead 之後的第二段散文（2026-08-24，服務內頁的 overview 併進 hero）。
   ⚠️ 間距用 --space-4 比 lead 的 --space-5 小一階：lead 與 body 是同一個
      意義單位的兩段（總結句 ＋ 展開），彼此要比「標題 → lead」更靠近，
      否則讀起來又變回兩塊。 */
.page-hero__body {
  margin-block-start: var(--space-4);
}


/* ── 麵包屑 ──────────────────────────────────────────────────────
   由 component('breadcrumb') 產生，同時輸出 BreadcrumbList JSON-LD。

   ⚠️ 分隔線用 --text-secondary 不用 --decorative-only：後者對白只有 2.49:1，
      她明文禁止用於**任何文字**。分隔符雖然是裝飾用途，但它確實是會被渲染的字。
   ⚠️ 連結加 padding-block 是為了滿足 ④（觸控目標 ≥44px）。
      caption 行高 20–24px ＋ 上下各 12px ＝ 44–48px，視覺字級不變。 */
.crumbs {
  font-family: var(--type-role-breadcrumb-family);
  font-size: var(--type-role-breadcrumb-size);
  line-height: var(--type-role-breadcrumb-line-height);
  letter-spacing: var(--type-role-breadcrumb-letter-spacing);
  font-weight: var(--type-role-breadcrumb-weight);
  color: var(--text-secondary);
}

.crumbs__list {
  display: flex;
  flex-wrap: wrap;              /* ⑤ 窄寬度下換行，不產生水平捲動 */
  align-items: center;
  gap: 0 var(--space-2);        /* ④ 相鄰觸控目標間距 ≥8px */
  margin: 0;
  padding: 0;
  list-style: none;
}

.crumbs__item {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
}

.crumbs__item:not(:last-child)::after {
  content: "/";
  color: var(--text-secondary);
  /* 分隔符是排版符號不是內容，讀屏靠 <ol> 的語意就夠了 */
  speak: never;
}

.crumbs a {
  display: inline-flex;
  align-items: center;
  padding-block: var(--space-3);
  color: var(--text-link);
  text-decoration: none;
  transition: color var(--motion-duration-hover) var(--motion-easing-standard);
}

/* hover 位移預算 0px、禁 scale()：只換色與底線 */
@media (hover: hover) and (pointer: fine) {
  .crumbs a:hover {
    text-decoration: underline;
    text-underline-offset: var(--space-1);
  }
}

/* :active 一律走 --motion-press-offset，該 token 在 reduced-motion 下自動歸零，
   所以這裡不需要自己寫一份 media query */
.crumbs a:active {
  transform: translateY(var(--motion-press-offset));
}

/* ③ 焦點環：3px ring ＋ 2px 間距，全站同一套 */
.crumbs a:focus-visible {
  outline: var(--focus-ring-width) solid var(--focus-ring-on-light);
  outline-offset: var(--focus-ring-offset);
  border-radius: var(--radius-alias-control);
}

.crumbs [aria-current="page"] {
  color: var(--text-secondary);
}


/* ── CTA 帶 ──────────────────────────────────────────────────────
   視覺全部沿用既有元件（section--navy / eyebrow--on-inverse /
   section-title--on-inverse / prose--on-inverse / btn--on-inverse），
   這裡只補版面：置中、限寬、垂直節奏。 */
.cta-band__in {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  gap: var(--section-head-gap);
}

.cta-band__in .prose {
  /* 置中時 max-width 要吃 auto margin 才會真的置中 */
  margin-inline: auto;
}

.cta-band__in .btn {
  margin-block-start: var(--space-4);
}


/* ── chevron 步驟條（中央廚房準則 H-2）────────────────────────────

   ⚠️⚠️ **2026-08-24 起這一整段沒有消費端了**，daniel 指定四處全改成 .step-list
   （覆寫 H-2，見 CLAUDE.md 規則 6 與 includes/components/_step-list.php 檔頭）。
   **樣式保留不刪**，比照 .card-rail 的處理：實作完整，日後要用接得回去。

   ⚠️⚠️ 但接回去之前**必須先修底色** —— 下面那條「必須放在白底區塊上」的警告
   不是假設，是**已經發生過的事實**：四處全放在 section--subtle 上，
   .ck-flow-step 的 --surface-subtle 與區塊底色都是 #F3F3F3，實測四處
   secBg === stepBg。也就是說 chevron 從上線到移除為止**一天都沒有顯示過**，
   畫面上只有一排裸文字。修法二選一：把區塊改成 --surface-page，
   或把 .ck-flow-step 的底色改成 --surface-page（但那樣它就只在灰底區成立，
   元件會變成「必須知道自己被放在哪」——.phase 當初選的是後者並寫明了理由）。

   「任何流程／步驟一律用 chevron 步驟條」是公司準則，不是這個設計的選擇。
   移除前是 4 處，全在 service-detail.php（services.php 那一處已於 2026-08-21 移除）。

   ⚠️ 風格上要注意：她的設計語彙偏圓（所有控件 --radius-alias-control 是 999px），
      而 chevron 是硬角。這兩者本來就有張力——2026-08-14 daniel 就曾為了同樣的
      理由指定覆寫 H-2，把首頁的交付四階段改成「階段軌道」。這裡先照準則做，
      視覺上不合再由 daniel 裁決要不要比照辦理。

   ⚠️ overflow-x: auto 是必要的：步驟多的時候（事件響應有七階）不能讓整頁
      產生水平捲動（硬約束 ⑤），捲動要關在元件裡面。
   ⚠️ 箭頭深度取 --space-3（12px，在間距階梯上），不是隨手挑的數字。 */
/* ⚠️ chevron 只能靠底色分辨，**必須放在 --surface-page（白）的區塊上**。
   clip-path 會把 border 連同斜角一起裁掉，所以不能用邊線補救；
   放到 section--subtle 上就會同色疊同色而消失（實測踩過）。 */
.ck-flow-stepper {
  --ck-arrow: var(--space-3);
  display: flex;
  flex-wrap: nowrap;
  align-items: stretch;
  overflow-x: auto;
  overscroll-behavior-inline: contain;
  /* ④ 不能只靠滑動手勢（WCAG 2.5.1），並且允許垂直捲動穿透 */
  touch-action: pan-y pan-x;
  gap: var(--space-1);
  padding-block-end: var(--space-2);
}

.ck-flow-step {
  position: relative;
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  /* 左側留出箭頭咬合的空間 */
  padding: var(--space-3) var(--space-5) var(--space-3) calc(var(--space-5) + var(--ck-arrow));
  /* ④ 觸控目標 ≥44px：space-3 ×2 ＋ meta 行高 ≈ 44–48px */
  min-block-size: var(--space-8);
  background-color: var(--surface-subtle);
  color: var(--text-body);
  font-family: var(--type-role-meta-family);
  font-size: var(--type-role-meta-size);
  line-height: var(--type-role-meta-line-height);
  letter-spacing: var(--type-role-meta-letter-spacing);
  text-decoration: none;
  /* 兩端切成箭頭：右側凸出、左側凹入，並排時互相咬合 */
  clip-path: polygon(
    0 0,
    calc(100% - var(--ck-arrow)) 0,
    100% 50%,
    calc(100% - var(--ck-arrow)) 100%,
    0 100%,
    var(--ck-arrow) 50%
  );
  transition: background-color var(--motion-duration-hover) var(--motion-easing-standard);
}

/* 第一節左邊不咬合，切平 */
.ck-flow-step:first-child {
  padding-inline-start: var(--space-5);
  clip-path: polygon(
    0 0,
    calc(100% - var(--ck-arrow)) 0,
    100% 50%,
    calc(100% - var(--ck-arrow)) 100%,
    0 100%
  );
}

/* 最後一節右邊切平 */
.ck-flow-step:last-child {
  clip-path: polygon(
    0 0,
    100% 0,
    100% 100%,
    0 100%,
    var(--ck-arrow) 50%
  );
}

.ck-flow-step:first-child:last-child {
  clip-path: none;
}

.ck-flow-no {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-inline-size: var(--space-5);
  color: var(--text-eyebrow);
  font-weight: var(--font-weight-bold);
  font-variant-numeric: tabular-nums;
}

/* ⚠️ hover 只換文字色，**底色刻意不動**。
   她的語意層在淺底只有 --surface-page / --surface-subtle / --surface-inverse，
   subtle 與 inverse 之間沒有中間階，也就是**「淺底 hover 底色」這顆 token 不存在**。
   硬約束 ⑥ 說缺 token 要停下來回報、不可就地發明，所以這裡不自己調一個灰。
   已列入回報清單；補上 token 之後再把 background-color 加回來。 */
@media (hover: hover) and (pointer: fine) {
  .ck-flow-step:hover {
    color: var(--text-primary);
  }
}

.ck-flow-step:active {
  transform: translateY(var(--motion-press-offset));
}

/* ③ clip-path 會把 outline 一起裁掉，所以焦點改用內描邊 box-shadow，
   視覺結果與 3px ring ＋ 2px 間距等價 */
.ck-flow-step:focus-visible {
  outline: none;
  box-shadow: inset 0 0 0 var(--focus-ring-width) var(--focus-ring-on-light);
}


/* 表格後面的尾註多一階間距（2026-08-24）。
   ⚠️ 其餘尾註（接在 .panel-grid／.phase-grid 後面）維持 .section-note 的
      --space-5 不動 —— 那些是卡片，下緣本來就有留白。
      表格不一樣：最後一列有一條實線，**同樣 24px 從硬線起算比從文字基線
      起算看起來擠**，所以只有這個組合加到 --space-6。
   ⚠️ 不去改 .section-note 本身：它是共用詞彙，about 與首頁也在用，
      為了這一個情境改共用值會波及到不相干的地方。 */
.tbl-wrap + .section-note {
  margin-block-start: var(--space-6);
}


/* RMA 那句 scope 後面的細項清單（2026-08-24）。
   ⚠️ 間距刻意比 .section-note（--space-5）小一階：它是上面那句話的細項，
      不是新的一段。用一樣的間距會讓兩者讀起來各自獨立。
   ⚠️ 全站 <ul> 在 reset 裡是 margin:0 / padding:0 / list-style:none，
      所以項目符號與縮排都要自己給回來。 */
.rma-notes {
  margin-block-start: var(--space-3);
  padding-inline-start: var(--space-5);
  list-style: disc;
}

.rma-notes > li + li {
  margin-block-start: var(--space-2);
}


/* ══════════════════════════════════════════════════════════════════
   .scope-list — 服務內頁 Scope（2026-08-24 取代 .phase-grid 的 6 個白框）

   daniel：「編號拿掉改成 icon」＋「排版感覺有點無聊」。
   量出來的問題：每格約 400px 寬但文字只佔 230–350px，數字還自己佔一整行；
   4 或 6 個一模一樣的白框，邊線的視覺重量超過內容本身。

   改成圖左文右的兩欄清單、髮絲線分隔、不用框。

   ⚠️ .phase／.phase-grid **保留不刪** —— 同一頁的交付四階段、事件響應七階段、
      RMA 六階段、RCS 五步驟還在用它們。這裡只是 Scope 不再用。
   ⚠️ 兩欄之間有 column-gap，所以分隔線在中間會斷開一段。那是刻意的：
      它讀起來就是「兩欄清單」而不是一張表格。
   ⚠️ 每一項都有上緣線（含第一列），最上面那條剛好接在區塊標題下方，
      看起來像規格表的表頭線。最後一列下方**沒有**線 —— 收在 cta 之前不封口。
   ══════════════════════════════════════════════════════════════════ */
.scope-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-columns: 1fr;
}

@media (min-width: 768px) {
  .scope-list {
    grid-template-columns: repeat(2, 1fr);
    column-gap: var(--space-7);
  }
}

.scope-list__item {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: var(--space-4);
  align-items: start;
  padding-block: var(--space-5);
  border-block-start: var(--border-width-hairline) solid var(--border-hairline);
}

/* 圖示走 eyebrow 的藍 —— 原本那組編號就是這個顏色，換成圖示不改色彩語彙。
   ⚠️ 顏色下在這裡而不是 .licon：那支是共用原子，svg 吃 currentColor，
      顏色一律由消費端決定。 */
.scope-list__icon {
  display: flex;
  color: var(--text-eyebrow);
}


.scope-list__label {
  margin: 0;
  font-family: var(--type-role-paragraph-family);
  font-size: var(--type-role-paragraph-size);
  line-height: var(--type-role-paragraph-line-height);
  color: var(--text-body);
}


/* ══════════════════════════════════════════════════════════════════
   .step-list — 有先後的步驟／階段清單（2026-08-24，daniel 指定的「方案 B」）

   取代「chevron 步驟條 ＋ .phase-grid 說明卡」的上下兩排版型，四處共用
   （交付四階段／事件響應七階段／RMA 六階段／RCS 五步驟）。
   換掉的三個量測理由寫在 includes/components/_step-list.php 檔頭，這裡不重複。

   ⚠️ 版型刻意與同頁的 .scope-list 同一套語彙：左窄欄 ＋ 右內容、髮絲線分隔、
      不用框。差別只在左欄是**編號**不是圖示 —— 那正是「有先後」與「無先後」
      的分野，同一頁兩區才讀得出是兩種不同的東西。
   ⚠️ **單欄，不比照 .scope-list 分兩欄。** 兩欄 grid 是列優先填（1→2 一列、
      3→4 下一列），對一份有先後的清單來說每讀完一項就要橫跨一次版面。
      單欄由上往下讀，版型本身就是順序。
   ⚠️ 描述直接用共用的 .prose —— 行寬上限（--type-role-paragraph-max-width，
      36em ≈ 72 字元）由它帶進來，不在這裡另外寫一個 max-inline-size。
   ⚠️ 不需要自己給上緣間距：.section-head 帶著 --section-head-space-after。
   ══════════════════════════════════════════════════════════════════ */
/* ── 一區塊一張圖：左清單、右圖（2026-08-24，daniel 選的「選項 A」）──

   daniel：「往下捲動的時候雖然資訊清楚但感覺偏無聊」。
   量出來的背景：/services/managed-services/ 整頁 6228px 高、**全頁只有一張圖**，
   而清單的文字受 .prose 的 36em 上限，在 1440 只佔容器 1305px 的 41%，
   右邊 765px 全空 —— 而且該頁有**兩個清單連著**（七階段 ＋ RMA 六階段）。

   ⚠️ 欄寬用 --split-columns 不是自己編的值：那是全站 .split 圖文對開的同一顆
      token（583fr 577fr），而且 @media (max-width: 1023px) 已經覆寫成 1fr。
      也就是**單欄退化跟著站上其他圖文區一起走，這裡不必自己寫斷點**。
   ⚠️ align-items: start 不是 .split 的 center：清單高度是圖的兩倍，
      置中會讓圖浮在清單中間、上下都不對齊任何東西。
   ⚠️ 基底 .step-block **刻意沒有任何宣告**（連 display 都不給）：沒傳 media 時
      它就是一個普通 div，版面與加這層之前逐字相同。兩欄只掛在 --with-media 上。 */
.step-block--with-media {
  display: grid;
  grid-template-columns: 1fr;
  align-items: start;
  gap: var(--space-7);
}

/* ⚠️ 2026-08-24 二修（daniel：「有點大張，應該要再縮小一半左右」）：
   圖欄從 --split-columns 的 577fr（1440 量到 629px）改成固定
   --step-media-width（320px）≈ 對半，清單欄吃 minmax(0, 1fr)。
   ⚠️ 為什麼不是「維持 --split-columns，只把圖 max-inline-size 壓小」：
      那樣圖會停在右欄的左緣或右緣，兩者都會在文字結束（.prose 上限 540px）
      與圖之間留下 300px 以上的空白 —— 看起來像圖掉在半路。
      改欄寬則髮絲線跟著變寬、圖靠齊容器右緣，兩端都有東西收邊。
   ⚠️ 斷點 1024 與下方 sticky／order 的兩條規則**必須同一個值**：
      三者描述的是同一件事（兩欄 vs 單欄），拆開改就會出現
      「單欄了但圖還在 sticky」這種只在特定寬度才看得到的狀態。 */
@media (min-width: 1024px) {
  .step-block--with-media {
    grid-template-columns: minmax(0, 1fr) var(--step-media-width);
  }
}

/* ⚠️ sticky 的門檻與 --split-columns 的覆寫斷點對齊（1023/1024）：單欄時圖在
   清單上方，若還 sticky 會變成圖釘在頂端、清單從它底下捲過去。
   ⚠️ top 值沿用站上既有算式 calc(--header-height-compact + --space-6)
      —— header 捲動後會壓成 compact(64px)，這是本站清 header 的既定寫法。
   ⚠️ 為什麼非 sticky 不可：七階段那一塊約 820px 高、圖只有約 419px，
      靜態擺放的話捲過第 4 項之後右邊又是一片空白，等於沒解決原本的問題。 */
@media (min-width: 1024px) {
  .step-block--with-media .step-block__media {
    position: sticky;
    inset-block-start: calc(var(--header-height-compact) + var(--space-6));
  }
}

/* ⚠️ 單欄時圖排到清單**前面**（order: -1）。站上 .split 在 ≤1023 的既定行為就是
   「圖先文後」（見 01-tokens.css 的 --split-columns 覆寫註解），這裡跟著走。
   order 不影響無障礙樹的順序（讀屏仍是清單→圖），這對一張補充性的材質圖
   可以接受；若日後放的是「非看不可」的圖，要改成調 DOM 順序而不是 order。 */
@media (max-width: 1023px) {
  .step-block--with-media .step-block__media {
    order: -1;
  }
}
/* ⚠️ 單欄時**不要**再給 margin-block-end：格線的 row-gap 就是 --space-7(40px)，
   加了會變成 72px（實測 768 與 375 都量到 72）。欄距與列距同一個 gap 才有節奏。 */


.step-list {
  list-style: none;
  margin: 0;
  padding: 0;
}

.step-list__item {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: var(--space-4);
  /* ⚠️ baseline 不是 start：編號是 caption 級、標題是 h4 級，用 start 對齊
     會讓編號浮在標題上緣之上。baseline 讓兩者的基線對齊，看起來才是同一行。 */
  align-items: baseline;
  padding-block: var(--space-5);
  border-block-start: var(--border-width-hairline) solid var(--border-hairline);
}

/* 編號沿用原本 chevron 步驟條 .ck-flow-no 的處理（--text-eyebrow 藍、bold、
   等寬數字），不另外發明一套 —— 換版型不等於換色彩語彙。
   ⚠️ min-inline-size 取 --space-5（24px），與 .scope-list 的圖示欄
      （--licon-size 20px）幾乎等寬，同頁兩區的右欄起點才對得齊。
   ⚠️ tabular-nums 是必要的：沒有它 01 與 04 的寬度不同，一整欄編號會歪。 */
.step-list__no {
  min-inline-size: var(--space-5);
  color: var(--text-eyebrow);
  font-family: var(--type-role-meta-family);
  font-size: var(--type-role-meta-size);
  line-height: var(--type-role-meta-line-height);
  letter-spacing: var(--type-role-meta-letter-spacing);
  font-weight: var(--font-weight-bold);
  font-variant-numeric: tabular-nums;
}

.step-list__body {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}

/* 標題與右側小字同一行，放不下才折行。
   ⚠️ 小字**刻意不推到最右邊**（沒有 margin-inline-start: auto）：這一欄在
      1440 有 1200px 寬，推到底會離標題太遠而讀不出從屬關係。緊跟在標題後面
      讀起來就是「Detection — Identify and validate」。 */
.step-list__head {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: var(--space-2) var(--space-4);
}

/* 與 .svc-axis__title 同一組宣告 —— 都是「區塊標題底下一層」的小標。 */
.step-list__title {
  margin: 0;
  font-family: var(--type-role-card-title-family);
  font-size: var(--type-role-card-title-size);
  line-height: var(--type-role-card-title-line-height);
  letter-spacing: var(--type-role-card-title-letter-spacing);
  font-weight: var(--type-role-card-title-weight);
  font-synthesis: none;
  color: var(--text-primary);
  overflow-wrap: anywhere;
}

/* 與 .svc-axis__note 同一組宣告：Ongoing · 24×7 在 /services/ 就長這樣，
   兩處是**同一個欄位**（ongoing_note）的兩個露出點，視覺必須一致。 */
.step-list__meta {
  font-family: var(--type-role-meta-family);
  font-size: var(--type-role-meta-size);
  line-height: var(--type-role-meta-line-height);
  letter-spacing: var(--type-role-meta-letter-spacing);
  color: var(--text-secondary);
}


/* ── 階段格 ──────────────────────────────────────────────────────

   ⚠️ **2026-08-24 起 .phase / .phase-grid 沒有消費端了**（四處說明卡一併
      併進 .step-list）。**保留不刪**：① 同上，日後要用接得回去；
      ② `.phase` 與 04-components.css 的 `.panel` 是同一組外框規格、
      註明「改一邊要改兩邊」，而 **.panel 仍在用** —— 把 .phase 刪掉會讓那條
      對照關係斷掉，下一個改 .panel 的人就沒有東西可以對。

   ⚠️ 順帶記下移除的原因（量出來的，不是偏好）：.phase-grid 走 auto-fit
      (--card-row-scroll-width 380px)，實測 1855→4 欄、1680→3+1、
      **1440→3+1**、1024→2+2，而上方的步驟條永遠是一排 N 格。
      「上排第 i 格對應下排第 i 格」只在極寬視窗成立。
      （deploy.md #15 記的就是這個 auto-fit 孤兒，當時 daniel 說先不動。）

   步驟條下方的說明卡。auto-fit 讓欄數隨寬度變，不寫死欄數。
   ⚠️ minmax 的下限用 --card-min-inline-size（她 S5 卡片列已定義的 token），
      不另外發明一個寬度。 */
/* ⚠️ 欄寬下限用 --card-row-scroll-width：那是她 S5 服務卡的欄寬，
   四個斷點都有覆寫（380 / 320 / 280），語意上就是「一張卡多寬」。
   自己編一個 260px 會多出一個沒人維護的數字，也不會跟著斷點走。
   min(100%, …) 是為了守住硬約束 ⑤：容器比一欄還窄時不撐出水平捲動。 */
.phase-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, var(--card-row-scroll-width)), 1fr));
  gap: var(--space-5);
}

/* ⚠️ 白底 ＋ 髮絲邊，不是灰底。
   灰底（--surface-subtle）放在 section--subtle 上會同色疊同色**整個看不見**——
   實測踩過。改成白底之後：放白底區靠邊線讀得出來、放淺灰區靠白底讀得出來，
   兩種底都成立，元件不必知道自己被放在哪一種區塊上。 */
/* ⚠️ 2026-08-21：原本這裡是 `.phase, .panel` 群組選擇器，.panel 已搬到
   04-components.css（跨頁共用）。兩者外框規格必須一致 —— **改一邊要改兩邊**。 */
.phase {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  padding: var(--space-5);
  background-color: var(--surface-page);
  border: var(--border-width-hairline) solid var(--border-hairline);
  border-radius: var(--radius-alias-media);
}

.phase > p {
  margin: 0;
  font-family: var(--type-role-paragraph-family);
  font-size: var(--type-role-paragraph-size);
  line-height: var(--type-role-paragraph-line-height);
  color: var(--text-body);
}


/* ── 卡片格 ──────────────────────────────────────────────────────
   ⚠️⚠️ **這裡原本有第二份 `.card-grid`，2026-09-02 移除。**

   原註解是「首頁 S5 是橫向捲動的 .card-rail，內頁列表要的是格狀」——
   那是 2026-08-24 **之前**的事實。當天 daniel 把首頁 S5 由 rail 改成
   `.card-grid` 五欄（規則 6-1），`.card-grid` 這個名字就變成
   `includes/components/_lifecycle.php` 專有的了；全站 grep 只有那一支會產出它。
   於是這一條變成**沒有自己的消費端、卻會蓋掉別人**的規則：

     05-blocks.css  .card-grid  1fr → 2(768) → 3(1024) → 5(1200)   ← 元件要的
     這裡           .card-grid  auto-fit minmax(--card-row-scroll-width)

   兩者特異性相同（都是 0,1,0），而 `pages/inner.css` **載入在後**，所以在
   任何載 inner.css 的頁面上贏的是這一條。

   ⚠️ 在 2026-09-02 之前這件事**完全看不出來** —— `/services/` 那時只印
      `.svc-axis`，整站沒有一個載 inner.css 的頁面會渲染 `.card-grid`。
      CSP 改版把 Cloud 群（`.card-grid--4`）放進 `/services/` 才讓它現形：
      實測 1440 下該頁是 **3 欄（4 張卡排成 3+1 孤兒）**、1200 是 2 欄，
      而首頁同一個元件是 4 欄。而且 `sizes` 是照元件的欄寬算的，
      欄寬被這條改掉之後圖就挑錯階（1200 實測版位 517px 卻挑 480w）。

   ⚠️ **刪掉而不是比照 `.ck-flow-*` / `.card-rail` 留著**：那兩者留著是因為
      「實作完整、日後要接回去不必重寫」，而且它們**不會蓋到任何人**。
      這一條的問題是**名字撞了**，留著就得另外想辦法讓它不生效 ——
      保留一個會靜默覆寫共用元件的同名規則，本身就是那個坑。
      要恢復「內頁卡片自動排列」的話，另取一個名字（例如 .card-grid--auto）
      再加回來即可，那四行不值得為它承擔這個風險。 */


/* ── 篩選列 / 分頁 ───────────────────────────────────────────────
   兩者都是**控件**，所以直接用她的按鈕詞彙，不另做一套 pill：
     未選中 → .btn .btn--secondary（透明底＋髮絲邊）
     選中   → .btn .btn--primary  （深藍實心）
   這樣做的好處是零新 token、觸控目標自動達標
   （--btn-padding-block 是 12px，她標為「mobile 44px 觸控餘裕 0 的硬下限」），
   而且日後按鈕改版篩選列會跟著變。

   ⚠️ 未選中態沒有 hover 樣式，這是刻意的：她在 .btn--secondary 的註解寫著
      「狀態矩陣未列 hover/active/disabled 明確值，**本輪不發明**，
        需要態時回頭出規格」。同一堵牆，做法保持一致。 */
.filterbar {
  display: flex;
  flex-wrap: wrap;              /* ⑤ 窄寬度換行，不撐出水平捲動 */
  align-items: center;
  gap: var(--space-2);          /* ④ 相鄰觸控目標間距 ≥8px */
}

.filterbar + .filterbar {
  margin-block-start: var(--space-3);
}

/* 「N of M」的計數，屬於附屬資訊不是控件 */
.filterbar__count {
  margin-inline-start: auto;
  font-family: var(--type-role-meta-family);
  font-size: var(--type-role-meta-size);
  line-height: var(--type-role-meta-line-height);
  letter-spacing: var(--type-role-meta-letter-spacing);
  color: var(--text-secondary);
}

.pager {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: var(--space-2);
  margin-block-start: var(--space-8);
}


/* ── 新聞列表（內頁）────────────────────────────────────────────
   .news-row 本體完全沿用她首頁 S4 那套，這裡只補列表容器與空狀態。 */
.news-list--page {
  margin-block-start: var(--space-8);
}

/* ⑦ 沒有結果時是 EmptyState：不可做成連結、不可有 hover */
.news-empty {
  padding-block: var(--space-9);
  text-align: center;
  font-family: var(--type-role-paragraph-family);
  font-size: var(--type-role-paragraph-size);
  line-height: var(--type-role-paragraph-line-height);
  color: var(--text-secondary);
}

/* 案例的「客戶 · 地區 · 年份」，與摘要區隔開來（只有案例才有這一行） */
.news-row__excerpt--meta {
  color: var(--text-secondary);
}


/* ── 表格 ────────────────────────────────────────────────────────
   ⚠️ .tbl-wrap 的 overflow-x 是必要的：表格欄多的時候不能讓**整頁**
      產生水平捲動（硬約束 ⑤），捲動要關在容器裡面。
   ⚠️ 分隔線用 --border-hairline（純裝飾，1.22:1）；表頭底下那條是結構線，
      用 --border-functional（4.54:1，≥3:1 才能承載功能語意）。 */
/* ⚠️ 白卡是 2026-08-24 加的（daniel：「應該還可以多一些層次」）。
   原本表格是「底色上的裸文字＋髮絲線」，浮著沒有圖地關係。
   判準同 .phase 當初選白底髮絲邊的理由：**白底＋髮絲邊在白區靠邊線讀得出來、
   在灰區靠白底讀得出來**，元件不必知道自己被放在哪一種底色上。
   ⚠️ 只給 padding-block 不給 padding-inline：.tbl 的 th/td 本來就有 16px 內距，
      再加一層會把內容往中間擠；而且 overflow-x: auto 的容器加左右內距，
      捲到底時右側內距會消失（瀏覽器既有行為），不如不加。 */
.tbl-wrap {
  overflow-x: auto;
  overscroll-behavior-inline: contain;
  touch-action: pan-y pan-x;
  background-color: var(--surface-page);
  border: var(--border-width-hairline) solid var(--border-hairline);
  border-radius: var(--media-radius);
  padding-block: var(--space-3);
}

/* ⚠️ 重音區塊裡**不要白卡**：在照片上蓋一塊大白，重音就沒了。
   改成透明＋反白 —— 顏色不必寫在這裡，.section--feature 重定義的
   --text-* / --border-* 會直接把 .tbl 的既有宣告帶到深底版本。 */
.section--feature .tbl-wrap {
  background-color: transparent;
  border: 0;
  border-radius: 0;
  padding-block: 0;
}

.tbl {
  inline-size: 100%;
  border-collapse: collapse;
  font-family: var(--type-role-paragraph-family);
  font-size: var(--type-role-paragraph-size);
  line-height: var(--type-role-paragraph-line-height);
  color: var(--text-body);
}

.tbl th {
  text-align: start;
  padding: var(--space-3) var(--space-4);
  border-block-end: var(--border-width-hairline) solid var(--border-functional);
  font-family: var(--type-role-eyebrow-family);
  font-size: var(--type-role-eyebrow-size);
  line-height: var(--type-role-eyebrow-line-height);
  letter-spacing: var(--type-role-eyebrow-letter-spacing);
  font-weight: var(--type-role-eyebrow-weight);
  text-transform: var(--type-role-eyebrow-transform);
  color: var(--text-eyebrow);
  white-space: nowrap;
}

.tbl td {
  padding: var(--space-4);
  border-block-end: var(--border-width-hairline) solid var(--border-hairline);
  vertical-align: baseline;
}

.tbl tbody tr:last-child td {
  border-block-end: 0;
}

/* 數量欄：等寬數字，欄位才不會因為位數不同而跳動 */
.tbl .num {
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
  color: var(--text-primary);
}

/* 該列的主鍵欄位 */
.tbl .is-key {
  color: var(--text-primary);
}

/* ── 圖說 ────────────────────────────────────────────────────────
   .media 有 aspect-ratio ＋ overflow:hidden，圖說塞進去會被裁掉，
   所以外層包一個 .figure，.media 只負責圖框。 */
.figure {
  margin: 0;
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}

.figure__cap {
  font-family: var(--type-role-meta-family);
  font-size: var(--type-role-meta-size);
  line-height: var(--type-role-meta-line-height);
  letter-spacing: var(--type-role-meta-letter-spacing);
  color: var(--text-secondary);
}

.figure__plate {
  color: var(--text-eyebrow);
  font-weight: var(--font-weight-bold);
  margin-inline-end: var(--space-2);
}


/* ── 文章內文（news-detail）──────────────────────────────────────
   body_blocks 有五種型別：text / link / img-single / img-left / img-right / img-pair。
   前三種是單欄，left/right 是文繞圖，pair 是並排兩張。 */
.artmeta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2) var(--space-5);
  margin-block-end: var(--space-5);
}

/* 案例的規格列：Scale / Hardware / Region / Customer。
   用 <dl>，讓讀屏能把「欄位名 → 值」配成對。 */
.artspec {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, var(--card-row-scroll-width)), 1fr));
  gap: var(--space-4);
  margin-block: var(--space-6);
  padding-block: var(--space-5);
  border-block: var(--border-width-hairline) solid var(--border-hairline);
}

.artspec__row {
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
}

.artspec__row dd {
  margin: 0;
  font-family: var(--type-role-paragraph-family);
  font-size: var(--type-role-paragraph-size);
  line-height: var(--type-role-paragraph-line-height);
  color: var(--text-primary);
}

/* ══════════════════════════════════════════════════════════════════
   .artflow / .artrow — 新聞內頁的圖文交錯列（2026-08-26，daniel：
   「改成左文右圖…有些文章有兩張圖像是 APAC-first 就交錯排列
   （左文右圖 右文左圖）」）

   改版前是「首圖獨佔一整列（1305×870，比視窗還高）＋ 底下一疊文字」。
   現在每一列是「一組文字 ＋ 一張圖」，第一列圖在右，之後左右交錯。
   配對規則（圖當分隔符、首圖排在佇列第一個）寫在 news-detail.php 的
   $rows 那段，這裡只管版型。

   ⚠️ **`align-items: start` 不是 `.split` 的 `center`。** 一列裡文字通常比圖高
      （四段文字約 460px、圖 3:2 約 390px），置中會讓圖浮在文字中間、上下各留
      一段空白 —— 那正是規則 6-3 記過的 `.split` 問題。這裡是閱讀流，兩者
      都該從同一條上緣開始。
   ⚠️ **鏡射的 `order` 下在 `.artrow__media` 上，不是 `.media` 上。** 規則 6-3
      踩過：`component('figure')` 吐的是 `<div><figure><div class="media">`，
      `.media` 是孫節點，order 對格線無效。
   ⚠️ **≤1023 一律圖先文後**，與 `.split` 的既定規則一致（04-components.css
      的 `.split--media-end` 檔頭：「取消鏡射，與 S2 一致」）。行動版因此仍然是
      「圖 → 文字」，跟改版前的閱讀順序相同。
   ══════════════════════════════════════════════════════════════════ */
/* ⚠️ **整個文章欄置中,不是靠左推。**（2026-08-26 三修，daniel：「右邊空白好多」）
   上一版把每一列靠左包，留白就全積在右邊。實測三個真實文章頁（1440 寬）：
     Rest of World  內文 600px／左右留白 420·420（置中）
     ProPublica     內文 754px／左右留白 343·343（置中）
   **留白總量其實一樣多**（ProPublica 是 48% 的視窗寬），差別只在左右均分。
   ⚠️ artmeta／artspec 也一起包進來 —— 只置中內文的話，日期與規格列會與
      文字欄錯開一段，反而更明顯。整個文章欄是同一條軸。
   ⚠️ 寬度走 --article-wrap-max（＝ 文字欄 ＋ 欄間 ＋ 圖欄，**推導出來的**），
      改任一欄的寬度它自己跟上，不會有第二份會漂的數字。 */
.artwrap {
  max-inline-size: var(--article-wrap-max);
  margin-inline: auto;
}

.artflow {
  display: grid;
  gap: var(--space-9);
  margin-block-start: var(--space-7);
}

/* ⚠️ **用 flex 不用 grid,這是修「圖文距離不一致」的作法。**
   grid 的 `fr` 軌道會把多餘寬度分給欄位，而段落本身被 36em 鎖住 ——
   多出來的寬度就變成**文字與圖之間的空隙**（1830 實測 276px）。而鏡射列
   因為文字靠右，多餘寬度落在畫面外，所以看起來正常：**同一個版面在兩列
   給出兩種間距，只有寬視窗才看得出來。**
   flex 的 basis 是固定寬，`flex-grow` 都是 0，多餘寬度**留在整列的尾端**
   （外側邊界），不會跑到欄間 —— 欄間永遠等於 gap。
   ⚠️ 順帶解決了鏡射時欄寬要跟著換的問題：flex 每個項目自帶寬度，
      `order` 換位置不會換寬度。grid 版曾經因此讓兩列的圖一大一小。
   ⚠️ **不可以加 `flex-wrap: wrap`。** 直覺上它是「放不下就換行」的安全網，
      實際上 flex 在 wrap 模式下是**先換行再考慮壓縮** —— 1024 實測兩欄
      （540 + 40 + 460 = 1040 > 容器 889）直接換行堆疊，而 1024 在
      ≤1023 的斷點之上，等於多出一段沒人設計過的版面。
      不 wrap 就會照 flex-shrink 等比壓縮（1024 實測文字 458／圖 391），
      而且兩者都有 `min-inline-size: 0`，不會水平溢出。 */
.artrow {
  display: flex;
  align-items: flex-start;
  gap: var(--space-7);
}

/* 文字欄釘在墨水寬（36em）—— 不長大，所以欄間距恆等於 gap。 */
.artrow__text {
  flex: 1 1 var(--article-text-measure);
  max-inline-size: var(--article-text-measure);
  min-inline-size: 0;
}

.artrow__media {
  flex: 0 1 var(--article-media-max);
  max-inline-size: var(--article-media-max);
  min-inline-size: 0;
}

.artrow--media-start .artrow__media {
  order: -1;
}

@media (max-width: 1023px) {
  /* 單欄時取消鏡射、一律圖先文後（同 .split 的既定規則）。
     ⚠️ **要換 flex-direction,不能只把 flex-basis 設成 100%。** 沒有 wrap 的
        flex 容器裡，兩個 100% 的 basis 只會被等比壓成各 50% —— 768 實測
        文字 324／圖 324 並排，完全沒有堆疊。這是拿掉 wrap 之後才冒出來的，
        改版當下四斷點掃描一量就抓到。
     ⚠️ 換成 column 之後 `align-items` 管的是**水平**方向，base 的
        `flex-start` 會讓兩者縮到內容寬，所以要改成 stretch。 */
  .artrow {
    flex-direction: column;
    align-items: stretch;
  }

  /* 單欄時圖**填滿欄寬**，不再套 --article-media-max ——
     那顆是「旁欄配圖」的上限，單欄下會變成一張浮在左邊的小圖。 */
  .artrow__text,
  .artrow__media {
    flex-basis: auto;
    max-inline-size: 100%;
  }

  .artrow__media {
    order: -1;
  }
}

/* 內文段落走 paragraph 角色。
   ⚠️ 上限（36em）與文字欄的寬度**是同一顆 token** —— 兩者一致，欄裡才不會
      再出現一段誰也用不到的空白。 */
.artrow__text > p {
  font-family: var(--type-role-paragraph-family);
  /* ⚠️ 新聞內頁的內文比全站內文大一階（--article-body-size），理由與實測
     參照寫在 01-tokens.css 那顆 token。 */
  font-size: var(--article-body-size);
  line-height: var(--article-body-line-height);
  letter-spacing: var(--type-role-paragraph-letter-spacing);
  /* ⚠️ 上限走 --article-text-measure（明算 36 個字級寬），**不是 36em** ——
     em 是對元素自己的字級解析的，欄容器與段落的字級不同，36em 會算出兩個
     不同的數字，欄裡就又會出現一段空白。 */
  max-inline-size: var(--article-text-measure);
  color: var(--text-body);
  margin-block: 0 var(--space-5);
}

.artrow__text > p:last-child {
  margin-block-end: 0;
}

/* ── 首字放大（2026-08-26，daniel：「第一個字母放大一點」）──────────────
   只給**全篇第一段**（第一列的第一段），不是每一段 —— 首字放大的作用是
   標示「文章從這裡開始」，每段都放就變成裝飾。

   ⚠️ 走 `::first-letter` 不是另外包一個 `<span>`：包 span 等於把版面決定
      寫進資料（第二期後台編輯要自己記得包），而 `::first-letter` 是純樣式，
      文案怎麼改都自己跟上。
   ⚠️ 字體用 --font-family-heading（Marcellus 襯線），與 h1／h2 同一套 ——
      內文是無襯線的 Albert Sans，首字用襯線才讀得出是刻意的排版而不是
      「這個字不小心變大了」。
   ⚠️ `line-height: 1` 是必要的：不歸一的話首字會把**第一行的行高**撐開，
      整段的行距在第一行就斷掉。
   ⚠️ 不在 ≤768 停用 —— 首字放大不是動效也不是互動，窄螢幕一樣讀得到；
      但字級跟著縮一階，免得在 327px 的欄寬裡吃掉半行。 */
.artflow > .artrow:first-child .artrow__text > p:first-child::first-letter {
  float: inline-start;
  margin-inline-end: var(--space-3);
  margin-block-start: var(--space-1);
  font-family: var(--font-family-heading);
  font-size: var(--article-dropcap-size);
  line-height: 1;
  color: var(--text-primary);
}


.artfig {
  margin-block: var(--space-6);
}

/* 文繞圖：寬螢幕才浮動，窄螢幕維持單欄（⑤ 不製造水平溢出）。
   斷點沿用她 tablet 的分界 1023px。 */
@media (min-width: 1024px) {
  .artfig--left,
  .artfig--right {
    inline-size: 50%;
    max-inline-size: 50%;
  }

  .artfig--left {
    float: inline-start;
    margin-inline-end: var(--space-6);
  }

  .artfig--right {
    float: inline-end;
    margin-inline-start: var(--space-6);
  }
}

/* 浮動之後要收尾，否則後面的區塊會爬上來 */
.artbody::after {
  content: "";
  display: block;
  clear: both;
}

/* 並排兩張圖：窄螢幕自動疊成單欄 */
.artpair {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, var(--card-row-scroll-width)), 1fr));
  gap: var(--space-5);
  margin-block: var(--space-6);
}


/* 內文條列（服務內頁的重點清單） */
.prose-list {
  margin: 0;
  padding-inline-start: var(--space-5);
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  font-family: var(--type-role-paragraph-family);
  font-size: var(--type-role-paragraph-size);
  line-height: var(--type-role-paragraph-line-height);
  color: var(--text-body);
}

/* ══════════════════════════════════════════════════════════════════
   .svc-axis — /services/ 的五支服務（2021-08-21 建立，2026-08-24 拿掉軸線）

   ⚠️ **class 名字裡的「axis」已經名不符實**，但刻意不改名：它出現在
      _lifecycle.php、本檔、CLAUDE.md、.agent/spec.md 四處，改名的收益
      只是名字好看一點，代價是四處同步 ＋ 任何一處漏改就是靜默破版。

   ── 2026-08-24：軸線、節點、Handover 分界全部移除（daniel 裁示）──
   移除的東西：每格上方那段細線、五顆節點（實心＝會結束／空心環＝持續中）、
   交付分界標籤，以及為它們預留的 padding。

   為什麼移除：首頁 S5 同日改成五欄 grid 之後，這一頁剩下的差別只有
   一條很淡的線加五個點 —— 那條線在 1440 下細到幾乎看不見，實心與空心
   節點的差異在該尺寸也分辨不出來，Handover 標籤則浮在空中沒有上下文。
   資訊沒有消失：「持續中」由每格的 ongoing_note（Ongoing · 24×7）
   以文字承擔，那是本來就在的欄位。

   ⚠️ 連帶效應：軸線是 CLAUDE.md 規則 6「例外二」（覆寫中央廚房 H-2
      chevron 準則）的**唯一理由**。軸線一走，那條例外就沒有保護對象了 ——
      已同步更新，不要留著一條保護空氣的規則（同日清掉的 .rail 就是這種）。

   ⚠️ data/services.php 的 is_ongoing 仍在用（決定 ongoing_note 印不印），
      欄位不要當成孤兒清掉。
   ══════════════════════════════════════════════════════════════════ */
.svc-axis {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: var(--space-7) var(--space-5);
}

.svc-axis__stage {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--space-2);
}

/* 軸上的圖（2026-08-24）。首頁 S5 與這條軸共用同一組檔案與同一支元件
   （includes/components/_lifecycle.php），差別只有 srcset 的 sizes。

   ⚠️ 原本軸上不放圖，理由是「card_image 全是灰底佔位圖」——
      8/21 換圖之後那五張是真實場景照，理由失效。而且順序剛好就是這條軸：
      空機房 → 機櫃進場 → 光纖配線 → 監控室 → 工程師值機。

   ⚠️ 這裡**不必動 ::before/::after 一行**。軸線與節點是用負的 inset-block-start
      錨在 .svc-axis 的 padding 區（桌機）／padding-inline-start（直向）裡的，
      與格子內容的高度無關 —— 圖插在內容最前面，自然落在線的下方。

   ⚠️ 框本身（aspect-ratio／overflow／圓角）全部由 .media + .media--1x1 提供，
      這裡只管寬度。<figure> 的瀏覽器預設 margin 要清掉。 */
.svc-axis__media {
  margin: 0;
  inline-size: 100%;
  /* 直向時的上限，理由見 01-tokens.css 的 --svc-axis-media-max */
  max-inline-size: var(--svc-axis-media-max);
}

/* 文字欄。存在的理由是 768–1199 的圖左文右（見下方那個斷點）——
   有了這層包裝，那裡只要把格子改成兩欄 grid，不必去數格子裡有幾個子元素
   （proof 與 note 是選填的，各格數量本來就不一樣）。

   ⚠️ flex: 1 不能拿掉。桌機五格是等高的（grid 預設 stretch），
      .svc-axis__cta 的 margin-block-start:auto 要靠這一欄把剩餘高度吃滿，
      五顆按鈕才會對齊底部。
   ⚠️ align-self: stretch 也不能拿掉。父層 .svc-axis__stage 是
      align-items: flex-start（為的是 CTA 不要被拉成滿寬），
      這一欄若跟著 shrink-to-fit，裡面的段落會照 max-content 排、不換行。 */
.svc-axis__body {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  align-self: stretch;
  flex: 1;
  min-inline-size: 0;
  gap: var(--space-2);
}

.svc-axis__title {
  margin: 0;
  font-family: var(--type-role-card-title-family);
  font-size: var(--type-role-card-title-size);
  line-height: var(--type-role-card-title-line-height);
  letter-spacing: var(--type-role-card-title-letter-spacing);
  font-weight: var(--type-role-card-title-weight);
  font-synthesis: none;
  color: var(--text-primary);
  overflow-wrap: anywhere;
}

.svc-axis__line {
  margin: 0;
  font-family: var(--type-role-paragraph-family);
  font-size: var(--type-role-paragraph-size);
  line-height: var(--type-role-paragraph-line-height);
  color: var(--text-body);
}

/* 實績句。字級同 meta，但用 --text-primary 讓它比 stage_line 更「站得住」——
   它是事實不是描述。 */
.svc-axis__proof {
  margin: 0;
  font-family: var(--type-role-meta-family);
  font-size: var(--type-role-meta-size);
  line-height: var(--type-role-meta-line-height);
  letter-spacing: var(--type-role-meta-letter-spacing);
  color: var(--text-primary);
}

/* 持續中的標記。用她既有的 .tag 太重（那是分類 pill），這裡只要一行細字。 */
.svc-axis__note {
  font-family: var(--type-role-meta-family);
  font-size: var(--type-role-meta-size);
  line-height: var(--type-role-meta-line-height);
  letter-spacing: var(--type-role-meta-letter-spacing);
  color: var(--text-secondary);
}

/* 整格可點（2026-08-24，daniel：「點圖片應該也要可以進入詳細頁」）。

   ⚠️ 作法是 **stretched link**，不是把 <figure> 另外包一層 <a>。
      包一層的話同一格會有兩個指向同一個網址的連結 —— 讀屏會唸兩次、
      鍵盤要 Tab 兩次才過得去，而使用者得到的資訊一模一樣。
      stretched link 是本站既有手法（.card__cta::after 撐滿整張首頁卡片、
      .news-row__link 撐滿整列），這裡沿用同一個作法而不是發明第二種。

   ⚠️ 錨點是 .svc-axis__stage 的 position: relative（它本來就有，為了軸線與節點）。
      inset: 0 只蓋格子本身 —— 軸線、節點、Handover 標籤都是用負的 inset 錨在
      格子外面的 padding 區，不會被蓋到，也不需要為它們調 z-index。

   ⚠️ 代價（既有手法本來就有的）：覆蓋層會攔截文字選取。首頁卡片與 news 列
      已經接受這個取捨兩週了，這裡跟著一致，不另立一種行為。 */
.svc-axis__cta::after {
  content: '';
  position: absolute;
  inset: 0;
  z-index: 1;
}

/* 滑過整格時圖片微放大 —— 與首頁卡片同一顆 token、同一個過場時長。
   這是「這一格可以點」的視覺回饋；沒有它，指標變成 pointer 是唯一線索。
   ⚠️ 查詢條件是 `(hover: hover) and (pointer: fine)`，**與首頁 .card:hover
      逐字相同**（2026-08-24 對齊）。原本這裡只寫 (hover: hover)，少了
      pointer: fine —— 那會讓「有 hover 但指標不精確」的裝置（例如某些
      觸控筆電、電視瀏覽器）在首頁不放大、在這一頁放大。
      daniel 要求兩邊 hover 行為一致，媒體查詢也算在內。 */
.svc-axis__media .media__img {
  transition: transform var(--motion-duration-hover) var(--motion-easing-standard);
}

@media (hover: hover) and (pointer: fine) {
  .svc-axis__stage:hover .media__img {
    transform: scale(var(--media-scale-hover));
  }
}

/* 鍵盤焦點也要有同樣的回饋 —— 焦點落在 CTA 上，但可點範圍是整格，
   只讓按鈕出現 ring 而圖沒反應，會讓人看不出「按 Enter 會去哪」。 */
.svc-axis__stage:has(.svc-axis__cta:focus-visible) .media__img {
  transform: scale(var(--media-scale-hover));
}

/* ⚠️ margin-block-start:auto 而不是固定間距 —— 五格的內容高度不一樣
   （標題換行數不同、只有 ongoing 的格子多一行 note），
   固定間距會讓五顆按鈕高低參差。auto 把剩餘空間吃掉，五顆對齊底部。 */
.svc-axis__cta {
  margin-block-start: auto;
  padding-block-start: var(--space-2);
}

/* ── 桌機（≥1200）：橫向五格 ───────────────────────────────────
   ⚠️ 斷點是 **1200 不是 1024**，量出來的不是猜的：
      grid 的 `1fr` 欄**不會縮到比內容的 min-content 還窄**，而每格最寬的內容是
      CTA 按鈕（最長的「Explore deployment」約 197px）。
      五格 ＋ 四個 --space-5 間距 ＝ 5×197 + 4×24 ≈ **1081px** 是硬底線。
      再加 .container 左右內距與捲軸，1024 的視窗只有約 1009 可用 → 一定溢出。
      實測：在 1024 下 doc scrollW 1128 > clientW 1009。
   ⚠️ 那個溢出**只在 1024 這個邊界出現**，先前四斷點驗收（1440/1024/768/375）
      剛好踩中，才抓到。改斷點之前要重量，不要只改數字。 */
@media (min-width: 1200px) {
  /* 五欄橫排，圖跟著欄寬走（1440 視窗下約 240px），解除直向的寬度上限 */
  .svc-axis__media {
    max-inline-size: none;
  }

  .svc-axis {
    grid-template-columns: repeat(5, 1fr);
  }

  /* ── .svc-axis--3 —— Infrastructure 群三支（2026-09-02，CSP 改版）──────
     欄數由 includes/components/_lifecycle.php 依實際傳進來幾支產出修飾 class。
     **基底那條 repeat(5, 1fr) 刻意不動**：沒有對應修飾 class 的欄數會落回基底
     （比照 .card-rail／.ck-flow-* 的保留作法）。

     ⚠️ 不改成 auto-fit：那會讓欄寬由 minmax 決定，三支在 1920 會被拉成三條
        很寬的欄、而 1200 又擠成兩欄 + 孤兒。明確寫欄數，斷點行為才可預期。 */
  .svc-axis--3 {
    grid-template-columns: repeat(3, 1fr);
  }

  /* 節點列的高度：點本身 ＋ 上下留白。只有掛了旗標（真的畫線）才需要留。 */

  /* ⚠️ inset-inline-end 取負的 gap 值：grid 的欄間距（--space-5）不屬於任何一格，
     線只畫到格子右緣的話，五段線中間會出現四個缺口 —— 實測就是這樣斷成五截。
     每一格的線多畫一個 gap 的長度，接到下一格左緣才連得起來。 */
  /* 第一格左半段不畫（線從第一個節點開始） */
  /* 最後一格：會結束就在節點收口；持續中就往右淡出、不收口 */
  /* ⚠️ 漸層要用**硬停點**，不能寫成 0%→100%：
     那樣淡出會跨整格（桌機 ~265px、手機 ~250px），最後一格旁邊的線整段被沖淡，
     跟前面幾段明顯不同色 —— 實測就是這樣。
     改成「到倒數 --space-8 為止都是實色，最後那段才淡出」。 */
  /* ⚠️ inset-inline-end 是 **0 不是負值**。原本讓線往右超出容器 48px 想做出
     「跑出畫面」的感覺，但那 48px 會**讓整份文件產生水平捲軸**（實測 1128 > 1009）。
     收在容器邊緣、讓漸層在最後 --space-8 內淡到全透明，視覺上一樣是「溶掉」，
     但不會製造橫捲。 */
  /* 從標籤往下拉一條短刻度接到軸線，否則標籤看起來是浮在空中的 */
}

/* ── 平板（768–1199）：格子內改成圖左文右 ──────────────────────
   這個範圍每格有 600px 以上可用，圖若還是壓在文字上面，右側會空掉一大片
   （實測 1024：圖佔左側 23%，右邊約 650px 全白）。

   ⚠️ 下限是 768 不是更小。375 的內容欄只有 276px，扣掉 200px 的圖
      只剩不到 60px 給文字 —— 那個寬度只能上下堆。
   ⚠️ .svc-axis__handover 是 position:absolute，不會變成 grid item，
      所以改 grid 之後它的定位不受影響（父層本來就有 position:relative）。
   ⚠️ column-gap 要另外指定：.svc-axis__stage 的 gap 是 --space-2（給直向堆疊用的），
      套到欄間會太窄。 */
@media (min-width: 768px) and (max-width: 1199px) {
  .svc-axis__stage {
    display: grid;
    grid-template-columns: var(--svc-axis-media-max) 1fr;
    column-gap: var(--space-5);
    align-items: start;
  }

  /* ⚠️ 這一行是必要的，不是保險。.svc-axis__body 的基底規則帶 align-self: stretch
     （桌機五格等高時要靠它把 .svc-axis__cta 的 margin-block-start:auto 壓到底部），
     而 align-self 的優先序高於容器的 align-items: start —— 不覆寫的話文字欄會被
     拉到與圖同高（280px），按鈕就被 auto 推到離內文一大段的下方。
     這裡是單格橫排、沒有「五顆按鈕要對齊」的問題，按鈕跟著內文走才對。 */
  .svc-axis__body {
    align-self: start;
  }
}

/* ── 1199 以下：改直向，軸線走左緣 ─────────────────────────────
   五格橫排在這個寬度以下放不下（見上方斷點的說明）。
   直向反而更清楚：線由上往下，最後一段往下淡出。 */
@media (max-width: 1199px) {
  .svc-axis {
    grid-template-columns: 1fr;
    gap: var(--space-7);
  }

  /* 左緣軸線的讓位。同上，只有掛旗標才需要。 */

  /* 同桌機：inset-block-start 取負的 row gap，讓線跨過格與格之間的間距 */
  /* ⚠️ 漸層要用**硬停點**，不能寫成 0%→100%：
     那樣淡出會跨整格（桌機 ~265px、手機 ~250px），最後一格旁邊的線整段被沖淡，
     跟前面幾段明顯不同色 —— 實測就是這樣。
     改成「到倒數 --space-8 為止都是實色，最後那段才淡出」。 */
}

/* ── 區域格的營運狀態（2026-08-21）───────────────────────────────
   ⚠️ 這不只是裝飾。data/regions.php 的 is_operating 存在的理由是**對外數字禁灌水**：
      報價單 P4 明載美國是「擴展中」，五格長得一模一樣就等於宣稱五地都在營運。
      該檔檔頭寫的做法是「is_operating = false 的市場整欄降階（無綠燈、事實欄不用 accent）」，
      這裡是它第一次被真的實作 —— 欄位備好了兩週沒有任何 view 在讀。 */
.region__status {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
}

.region__status::before {
  content: '';
  inline-size: var(--space-2);
  block-size: var(--space-2);
  border-radius: var(--radius-max);
  background-color: var(--border-interactive);
}

/* 尚未營運：虛線框 ＋ 空心燈 ＋ 文字降階。用「未完成」的視覺語言，不是「失敗」。 */
.region--pending {
  border-style: dashed;
}

.region--pending .region__status::before {
  background-color: transparent;
  box-shadow: inset 0 0 0 var(--border-width-hairline) var(--border-functional);
}

.region--pending .panel__title,
.region--pending .prose {
  color: var(--text-secondary);
}

/* ── 區域清單（2026-08-25，daniel：「global footprint 那邊看可不可以用列表呈現」）──
   原本是 .panel-grid 五張卡。改成縱向清單，版型語彙**刻意與 .step-list 同一套**
   （左窄欄 ＋ 右內容、髮絲線分隔、不用框），差別只在左欄是**國碼**不是編號。

   ⚠️ 用 <ul> 不是 <ol>：五個市場**沒有先後**（同 .scope-list 的判準；
      有先後的 .step-list 才用 <ol>）。
   ⚠️ 四個欄位一個都沒少（code／type／description／status）—— 卡片版有的
      這裡都有，只是排列方式換了（CLAUDE.md 全域守則 2：禁刪，只能調樣式與順序）。
   ⚠️ **不重用 .panel 的外框**：這一區同日改成 .section--feature（照片＋遮罩），
      白卡會在照片上蓋一塊大白，判準同服務內頁的表格（規則 6-2 的 .tbl-wrap）。 */
.region-list {
  list-style: none;
  margin: 0;
  padding: 0;
}

.region-list__item {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  gap: var(--space-4);
  align-items: baseline;
  padding-block: var(--space-5);
  border-block-start: var(--border-width-hairline) solid var(--border-hairline);
}

/* 國碼。用 tabular-nums 與 .step-list__no 同一組設定，兩份清單的左欄才會等寬對齊。 */
.region-list__code {
  font-size: var(--type-scale-meta-size);
  font-weight: var(--font-weight-bold);
  font-variant-numeric: tabular-nums;
  color: var(--text-eyebrow);
  min-inline-size: var(--space-5);
}

.region-list__head {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: var(--space-2) var(--space-4);
}

.region-list__name {
  margin: 0;
  font-size: var(--type-scale-h5-size);
  line-height: var(--type-scale-h5-line-height);
  color: var(--text-primary);
}

.region-list__type {
  font-size: var(--type-scale-meta-size);
  color: var(--text-secondary);
}

.region-list__desc {
  margin-block: var(--space-2) 0;
}

.region-list__status {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  margin-block-start: var(--space-3);
  font-size: var(--type-scale-meta-size);
  color: var(--text-secondary);
}

/* 狀態燈。與卡片版 .region__status::before 同一顆 token，換版型不換語意。 */
.region-list__status::before {
  content: '';
  inline-size: var(--space-2);
  block-size: var(--space-2);
  border-radius: var(--radius-max);
  background-color: var(--border-interactive);
  flex-shrink: 0;
}

/* 尚未營運：空心燈。**用「未完成」的視覺語言不是「失敗」**（沿用卡片版的判準）。
   ⚠️ 卡片版是靠虛線外框表達，清單沒有框，所以這裡只剩燈與文字色兩個載體 ——
      燈不能再省，它是 is_operating 唯一還在露出的地方。 */
.region-list__item--pending .region-list__status::before {
  background-color: transparent;
  box-shadow: inset 0 0 0 var(--border-width-hairline) var(--border-functional);
}

.region-list__item--pending .region-list__name,
.region-list__item--pending .region-list__desc {
  color: var(--text-secondary);
}

/* /contact/ 的第四欄：狀態 ＋ 聯絡方式（2026-08-25 合併兩區時新增）。
   /about/ 沒有這一層（它的狀態直接是 .region-list__status），所以樣式寫成
   「有這個容器才生效」，兩頁共用同一支 .region-list 不必分岔。
   ⚠️ 客戶把 deploy.md #7 的地址／電話／email 交出來之前，下面的 __lines
      整段不會輸出（view 端 if），所以這一欄現在看起來只有狀態那一行。 */
.region-list__contact {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}

.region-list__lines {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
  font-size: var(--type-scale-meta-size);
  color: var(--text-secondary);
}

/* ── ≥1024：一列一行的橫向欄位（2026-08-25，daniel 選的「A」）────────
   上面那組是**基準（窄螢幕）**：名稱／描述／狀態三層堆疊。
   這一組把它們排回同一行。

   起因與量測：daniel「這個列表好像太長了…右半邊空間太多」。堆疊版實測
   每列 **153px** × 5 ＝ 765px（整段 1047px），而最長那行的墨水寬只有
   **307px**，清單寬 1305px —— **內容只佔 24%，右側空 938px**。
   兩個症狀是同一個成因：一行短字被拆成三層，所以高度是內容的三倍、
   寬度只用四分之一。排回同一行之後每列降到 **95px**、整段 757px（−28%），
   寬度利用約 76%。

   ⚠️ **不用兩欄**（當時的 B 案）：高度雖然也降到 740，但每一欄的內容仍然
      只佔那一欄的 47% —— 右邊的空白只是被切成兩塊小的；而且五是奇數，
      右下角必定留一格空（同 .grid-3 auto-fit 孤兒的病灶，deploy.md #15）。
   ⚠️ **斷點沿用 1024**，不另立新值 —— 與 .step-block--with-media 同一個。
      四欄在 1024 以下會擠爆，退回上面的堆疊版。
   ⚠️ **狀態欄在 /about/ 不能省**。`is_operating` 的降階在清單版只剩「空心燈 ＋
      文字色」兩個載體（卡片版的虛線外框已經沒了）。
      ⚠️ 2026-09-08 更正：`/contact/` 的狀態欄**已依客戶簡報 p8 移除**，所以那一頁
         只剩「文字色」那一半 —— 但同一份簡報把美國的 `type` 由 `Site` 改成
         `Expanding`，文字載體反而比一顆空心燈明確。/about/ 那一份未動。 */
@media (min-width: 1024px) {
  .region-list__item {
    padding-block: var(--space-4);
  }

  /* 三欄：名稱＋類型／描述／狀態。中間欄給最大權重（描述是最長的一欄），
     兩側用 minmax 給下限，避免窄容器時把名稱或狀態擠到折行。 */
  .region-list__body {
    display: grid;
    grid-template-columns: minmax(160px, 0.9fr) minmax(0, 1.6fr) minmax(150px, 0.8fr);
    gap: var(--space-5);
    align-items: baseline;
  }

  /* 名稱與類型改成上下兩行（橫排時並列會把中間欄推得太窄）。 */
  .region-list__head {
    display: block;
  }

  .region-list__name {
    display: inline;
  }

  .region-list__type {
    display: block;
    margin-block-start: var(--space-1);
  }

  /* 三欄各自對齊第一行基線，所以堆疊版用來拉開層次的上下邊距要歸零。 */
  .region-list__desc,
  .region-list__status {
    margin-block: 0;
  }

  /* /contact/ 的第三欄是 .region-list__contact（未來的聯絡方式），
     /about/ 是 .region-list__status 直接當第三欄 —— grid 只認**直接子元素**，
     所以兩者都會落在第三軌，不必替兩頁各寫一份格線。 */
  .region-list__contact {
    margin-block: 0;
  }

  /* 第三欄整個不存在時收成兩欄（2026-09-08）。
     ⚠️ 三欄格線的第三軌是 `minmax(150px, 0.8fr)` —— 沒有東西可放時它**不會塌縮**，
        而是在右側留下 150px 以上的空白，看起來像版面破洞。
     ⚠️ class 由 view 依「有沒有任何一筆有聯絡方式」決定，不是寫死 ——
        客戶交出 deploy.md #7 的地址／電話／email 之後，三欄自己會回來。 */
  .region-list--2col .region-list__body {
    grid-template-columns: minmax(160px, 0.9fr) minmax(0, 1.6fr);
  }
}

/* ── 大數字（2026-08-21）──────────────────────────────────────
   About 整頁原本沒有任何「大聲」的畫面：兩張表 ＋ 五個小面板 ＋ 一段文字。
   機隊組成是全站最有份量的事實，用 stat 的字級把它講出來。
   ⚠️ **不是重用 .stat**：她的 .stat 綁 --stat-value-fg（淺藍，為深藍底設計的，
      對 #00173E 13.55:1），放白底上對比不足。這裡用同一組字級 role token
      配 --text-primary，不動她的元件。 */
.count-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, var(--card-row-scroll-width)), 1fr));
  gap: var(--space-6) var(--space-5);
}

.count {
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
}

.count__value {
  margin: 0;
  font-family: var(--type-role-stat-number-family);
  font-size: var(--type-role-stat-number-size);
  line-height: var(--type-role-stat-number-line-height);
  letter-spacing: var(--type-role-stat-number-letter-spacing);
  font-weight: var(--type-role-stat-number-weight);
  font-feature-settings: var(--type-role-stat-number-font-feature-settings);
  font-synthesis: none;
  color: var(--text-primary);
}

.count__label {
  margin: 0;
  font-family: var(--type-role-card-title-family);
  font-size: var(--type-role-card-title-size);
  line-height: var(--type-role-card-title-line-height);
  letter-spacing: var(--type-role-card-title-letter-spacing);
  font-weight: var(--type-role-card-title-weight);
  font-synthesis: none;
  color: var(--text-primary);
}

.count__detail {
  margin: 0;
  font-family: var(--type-role-meta-family);
  font-size: var(--type-role-meta-size);
  line-height: var(--type-role-meta-line-height);
  letter-spacing: var(--type-role-meta-letter-spacing);
  color: var(--text-secondary);
}

/* ── 支援層級（2026-08-21）───────────────────────────────────────
   報價單 P3：「本地團隊分為**兩個層級**，**配備**專屬專案管理」。
   L1／L2 是層級，PM 不是第三層而是統一聯絡窗口 —— 原本的三列表格
   把這個差異壓平了。左邊兩層堆疊、右邊窗口另立一塊。
   ⚠️ 誰是窗口由 data 的 is_window 決定（見 data/service-details.php），
      版型不靠字串比對 'PM' 猜。 */
.tiers {
  display: grid;
  gap: var(--space-5);
}

.tiers__stack {
  display: flex;
  flex-direction: column;
  gap: var(--border-width-hairline);   /* 兩層之間只留一條髮絲縫，看起來是「疊」的 */
}

.tier {
  display: flex;
  align-items: baseline;
  gap: var(--space-5);
  padding: var(--space-5);
  background-color: var(--surface-page);
  border: var(--border-width-hairline) solid var(--border-hairline);
}

/* 疊起來的圓角：只有最上與最下有 */
.tier:first-child {
  border-start-start-radius: var(--radius-alias-media);
  border-start-end-radius: var(--radius-alias-media);
}

.tier:last-child {
  border-end-start-radius: var(--radius-alias-media);
  border-end-end-radius: var(--radius-alias-media);
}

.tier__no {
  flex: none;
  min-inline-size: var(--space-8);
  font-family: var(--type-role-meta-family);
  font-size: var(--type-role-meta-size);
  line-height: var(--type-role-meta-line-height);
  letter-spacing: var(--type-role-meta-letter-spacing);
  color: var(--text-link);
}

.tier__body {
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
}

/* 窗口那一塊直接用 .panel 的盒子，不加額外裝飾。
   ⚠️ 2026-08-21 曾在左緣加一條 4px 的 accent 邊想強調「這不是第三層」——
      daniel 回報很醜，已移除。區分本來就夠了：它在版面上是獨立的一塊、
      標籤是 PM 不是 L1/L2、而且說明白寫著 Single contact window。
      ⚠️ 這個移除**不隨設計實驗回退**（a548d97 的 revert 會把它帶回來，已再次移除）。 */

@media (min-width: 1024px) {
  .tiers {
    grid-template-columns: 2fr 1fr;
    align-items: start;
  }
}


/* ══════════════════════════════════════════════════════════════════
   .page-hero--with-media — 內頁 hero 的選填主圖（2026-08-24）

   daniel：服務內頁「看起來很空」。圖放 hero 而不是放 overview 旁邊，
   理由在 includes/components/_page-hero.php 的檔頭：overview 有四支只有
   181–230 字元，滿欄大圖配三行字會在右側留下一塊空洞（實測 636px 高的圖
   配 3 行字）；hero 的內容量則每頁一致。

   ⚠️ 沒傳 media 的頁面（about／news／contact）**完全不受影響** ——
      .page-hero__grid 這兩層 div 只在有圖時才吐，這裡的規則自然不匹配。
   ⚠️ 麵包屑在格線外面、跨滿寬，所以不在這段規則的管轄範圍。
   ══════════════════════════════════════════════════════════════════ */

/* 上限在所有斷點都生效：≤1023 是上下堆疊，不設限的話平板會出現一張
   700px 見方的圖把 hero 撐到快兩個螢幕高。 */
.page-hero__media {
  max-inline-size: var(--page-hero-media-max);
  margin-block-start: var(--space-6);
}

/* ⚠️ 斷點取 1024 而不是 1200：左欄放的是大標，--type-role-page-title-size
   在 ≤768 才降階，1024 時大標仍是全尺寸，兩欄各約 460px 放得下。
   （軸那條線用 1200 是因為它有五欄 CTA 按鈕的硬底線，兩者無關。） */
@media (min-width: 1024px) {
  .page-hero__grid {
    display: grid;
    grid-template-columns: 1fr var(--page-hero-media-max);
    gap: var(--space-7);
    align-items: center;
  }

  .page-hero__media {
    margin-block-start: 0;
  }
}




/* ═══════════════════════════════════════════════════════════════════════
   /contact/ 的 Email us（2026-09-14）

   客戶交出對外信箱之後新增。在此之前這一頁**沒有任何聯絡方式**
   （`.agent/deploy.md` #7 列為上線硬阻斷）。

   ⚠️ **只給 `.contact-direct__addr`，不給裸的 `.mailto`。** 同一支元件
      `component('mailto')` 也用在區域清單的各據點信箱上，那裡吃的是
      `.region-list__lines` 的 meta 字級 —— 把樣式下在 `.mailto` 上會把
      那一串一起放大。

   ⚠️ **顏色用 `--text-link-large` 不是 `--text-link`。** 那顆 token 的註解
      自己就寫著判準：`--text-link`(accent-600) 是「≤13px 藍字」，
      ≥18px 要走 `--text-link-large`(accent-500)。這裡是 24px。

   ⚠️ **`a` 是 JS 生出來的。** `assets/js/inner.js` 在 DOM ready 後把 span 的
      內容換成一顆 `<a>`，所以顏色下在 span 上、`a` 吃 `inherit` ——
      這樣**沒有 JS 時（畫面上是 `name [at] domain`）視覺完全一樣**，
      不會出現「有 JS 才看得出這是重點」的落差。

   ⚠️ `overflow-wrap: anywhere`：JS 組裝**之前**的字串比組裝後長
      （`contact [at] boardsea.com.tw` 比 `contact@boardsea.com.tw` 多 5 個字元），
      375 那一格是最窄的版位，不給它換行的機會就會水平溢出。
   ═══════════════════════════════════════════════════════════════════════ */
.contact-direct {
  margin-block-start: var(--space-5);
}

.contact-direct__addr {
  font-family: var(--type-scale-h4-family);
  font-size: var(--type-scale-h4-size);
  line-height: var(--type-scale-h4-line-height);
  letter-spacing: var(--type-scale-h4-letter-spacing);
  color: var(--text-link-large);
  overflow-wrap: anywhere;
}

.contact-direct__addr a {
  color: inherit;
  text-decoration: none;
  transition: color var(--motion-duration-hover) var(--motion-easing-standard);
}

/* hover 位移預算 0px、禁 scale()：只換色與底線（沿用 .crumbs a 的處置） */
@media (hover: hover) and (pointer: fine) {
  .contact-direct__addr a:hover {
    text-decoration: underline;
    text-underline-offset: var(--space-1);
  }
}

/* ⚠️ **刻意沒有 `:active` 的按壓位移**（站上其他連結都有）。那個效果吃
   `transform`，而 `transform` 對 inline 元素無效 —— 要生效就得把這顆 `a`
   改成 `inline-block`，那會讓它在 375 變成一個不能被拆行的整塊。
   換行能力比一次按壓回饋重要（這是全站唯一的聯絡入口）。 */
