/* ================================================================
   Board Sea Technology — 04-components.css
   S2–S6 與 footer 的共用元件（atom 層）。跨頁會重複用到的元件放這裡。

   ── 本檔是 styles.css（4,118 行）拆檔的第 4/5 段 ──
   拆檔只切不搬：五個檔案**依序串接回去逐位元組等於原檔**，層疊結果不變。
   由 includes/_head.php 依 01→05 的順序載入，**順序不可調換**。
   來源 banner 邊界見 git 歷史（2026-08-20 拆檔 commit）。
   ================================================================ */

/* ================================================================
   SHARED ATOM LAYER — Batch B1 (S2–S6 + Footer 模組化元件架構)
   單一真相源：/Users/dawa/博洋興業有限公司/site-b/DESIGN.md
   施工依據：/Users/dawa/博洋興業有限公司/site-b/docs/spec-s2-s6-components.md
   （uiux 2026-08-18 產出，§A 元件清冊／§A-2 逐元件詳規／§A-3 互動狀態矩陣）

   新增 14 個共用 atom（C1–C14）＋ 擴充既有 focus-visible 規則以涵蓋
   新元件。對應的新 token 已追加在檔案上方既有 :root 區塊尾端。

   本批範圍只到「共用 atom 層」，不含：
   - index.html（S2 的 DOM 組裝是下一批的事，本層純樣式定義）
   - 區塊層樣式：.split / .news / .news-row / .card-rail / .card /
     .stat-grid / .stat / .site-footer__* / .giant-wordmark
     （這 5 個是「區塊專屬」元件，各自組裝下面的 atom，屬 B2–B6 各批
     自己的命名空間，此處不越界；.card:hover .media__img 的 hover
     驅動同理留給 B4）
   - .nav-overlay__eyebrow 與 .eyebrow--label 的指紋合併（B6 的事）

   atom 層治理（DESIGN.md 交接契約 硬約束⑦）：C1–C14 只有本批（B1）
   可編輯；B2–B6 只能使用、不能改，發現缺口停下回報，不得自行分叉。

   前一個「Unit 1 of 2」／「Unit 2 of 2」標記（檔案上方）在本批之後
   已不是完整描述——本層是第三個邏輯區塊，但既有標記文字本身不動
   （非本批授權範圍），特此註記避免誤讀。
   ================================================================ */

/* ── 共用 focus-visible 擴充（新元件）——承 styles.css 上方 skip-link
   附近既有規則（.site-header/.nav-overlay 手列選擇器清單），該規則
   不會自動蓋到本批新增的 atom。這裡補一條共用規則涵蓋 C7/C8/C13 的
   可聚焦元素。深色區塊（.section--dark 黑 / .section--navy 深藍）內
   的 ring 色必須切到 --focus-ring-on-dark：on-light 的 accent.500
   對 navy 只有 1.7:1，等於沒有 ring（DESIGN.md 交接契約 硬約束③，
   驗收點 8）。.card / .news-row 的 :has(:focus-visible) 卡外緣 ring
   屬區塊層（B3/B4），不在本批範圍。 ── */
.btn:focus-visible,
.icon-btn:focus-visible,
.link-list 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);
}

.section--dark .btn:focus-visible,
.section--dark .icon-btn:focus-visible,
.section--dark .link-list a:focus-visible,
.section--navy .btn:focus-visible,
.section--navy .icon-btn:focus-visible,
.section--navy .link-list a:focus-visible {
  outline-color: var(--focus-ring-on-dark);
}


/* ── C1 `.section` — 區帶外殼（規格 §A-2 C1）。padding-block 由
   --section-padding-block 承擔四斷點值，.section 本身不得寫 media
   query（硬約束⑥：同一元件四斷點須引用同一 token 名）。 ── */
.section {
  padding-block: var(--section-padding-block);
  border-radius: var(--radius-alias-flush);
}

.section--dark {
  background-color: var(--surface-inverse-deep);
}

.section--subtle {
  background-color: var(--surface-subtle);
}

.section--page {
  background-color: var(--surface-page);
}

.section--navy {
  background-color: var(--surface-inverse);
}


/* ── C2 `.container`（規格 §A-2 C2，公式逐字轉錄）。這條公式讓「單一
   左緣」在五個區塊自動成立，驗收點 5（各區標題 left 相等，容差 0）
   靠它，不靠各區自己算 padding。 ── */
.container {
  width: min(100% - 2 * var(--inset-x), var(--container-max-width));
  margin-inline: auto;
}


/* ── C3 `.section-head`（規格 §A-2 C3）。結構：
   .section-head > .eyebrow + .section-title (+ .section-head__actions)。
   預設為 flex column，eyebrow/title 直接吃 --section-head-gap。
   --inline-actions（S5 專用）切成 row 佈局時，eyebrow+title 需要一個
   文字群組 wrapper（.section-head__text）才能在 row 佈局下繼續維持
   「兩者疊在一起」的視覺關係——DOM 巢狀深度屬「frontend 可自行決定」
   （交接契約 4「邊界」），下一批組裝 S5 DOM 時請照此 wrapper 結構。 ── */
.section-head {
  display: flex;
  flex-direction: column;
  gap: var(--section-head-gap);
  margin-block-end: var(--section-head-space-after);
}

.section-head__text {
  display: flex;
  flex-direction: column;
  gap: var(--section-head-gap);
}

.section-head__actions {
  display: flex;
  gap: var(--space-3);
  flex-shrink: 0;
}

.section-head--inline-actions {
  flex-direction: row;
  flex-wrap: wrap;
  justify-content: space-between;
  align-items: flex-end;
  gap: var(--space-4);
}

/* ≤1023：actions 移到 title 下方（長標題與控制項互擠時的既定行為，
   規格 §A-2 C3）。 */
@media (max-width: 1023px) {
  .section-head--inline-actions {
    flex-direction: column;
    align-items: flex-start;
  }
}


/* ── C4 `.eyebrow`（規格 §A-2 C4）。預設 transform:none 已由
   --type-role-eyebrow-transform 承擔，--label 變體覆寫為 uppercase +
   寬字距。--label 與既有 .nav-overlay__eyebrow 同指紋（見 D 段），
   合併是 B6 的事，本層不動 .nav-overlay__eyebrow。 ── */
.eyebrow {
  display: block;
  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);
}

.eyebrow--on-inverse {
  color: var(--text-eyebrow-on-inverse);
}

.eyebrow--label {
  text-transform: uppercase;
  letter-spacing: var(--letter-spacing-label-wide);
}


/* ── C5 `.section-title`（規格 §A-2 C5）。overflow-wrap:anywhere 是
   floor_guard 配套的第二層保險，.hero__title 已有此寫法，照抄。不得
   加 text-shadow——那是 hero 專屬（文字疊照片），S2–S6 標題不疊圖。 ── */
.section-title {
  font-family: var(--type-role-section-title-family);
  font-size: var(--type-role-section-title-size);
  line-height: var(--type-role-section-title-line-height);
  letter-spacing: var(--type-role-section-title-letter-spacing);
  font-weight: var(--type-role-section-title-weight);
  color: var(--text-primary);
  overflow-wrap: anywhere;
}

.section-title--on-inverse {
  color: var(--text-on-inverse);
}


/* ── C6 `.prose`（規格 §A-2 C6）。 ── */
.prose {
  font-family: var(--type-role-paragraph-family);
  font-size: var(--type-role-paragraph-size);
  line-height: var(--type-role-paragraph-line-height);
  letter-spacing: var(--type-role-paragraph-letter-spacing);
  font-weight: var(--type-role-paragraph-weight);
  max-width: var(--type-role-paragraph-max-width);
  color: var(--text-body);
}

/* 表面鎖定：--text-secondary-on-inverse 對白底僅 1.42:1，只准用在
   .section--dark / .section--navy 內；對 #00173E 實測 11.75:1、對
   #000000 實測 13.8:1（規格 §A-2 C6，驗收點 2）。 */
.prose--on-inverse {
  color: var(--text-secondary-on-inverse);
}


/* ── C7 `.btn` — 最重要的複用元件（規格 §A-2 C7／§A-3 狀態矩陣）。
   觸控地板逐斷點（caption 行高 + padding-block×2）：mobile 44 / tablet
   45 / base 46 / wide 48，四斷點全過 44；mobile 餘裕 0 →
   --btn-padding-block 是硬下限，不得再減。 ── */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--btn-gap);
  padding: var(--btn-padding-block) var(--btn-padding-inline);
  border: none;
  border-radius: var(--btn-radius);
  font-family: var(--type-role-button-label-family);
  font-size: var(--type-role-button-label-size);
  line-height: var(--type-role-button-label-line-height);
  letter-spacing: var(--type-role-button-label-letter-spacing);
  font-weight: var(--type-role-button-label-weight);
  text-decoration: none;
  white-space: nowrap;
  cursor: pointer;
  transition:
    background-color var(--motion-duration-hover) var(--motion-easing-standard),
    transform var(--motion-duration-press) var(--motion-easing-standard);
}

/* 2026-08-18 全站微動態規格 P9：加 transform transition，供 S5
   .btn--with-icon:hover 消費（見 S5 區塊該處規則）。 */
.btn__icon {
  width: var(--btn-icon-size);
  height: var(--btn-icon-size);
  flex-shrink: 0;
  transition: transform var(--motion-duration-hover) var(--motion-easing-standard);
}

/* --primary：S3「See the delivery model」、S5 卡片×5「Explore …」 */
.btn--primary {
  background-color: var(--btn-primary-bg);
  color: var(--btn-primary-fg);
}

@media (hover: hover) and (pointer: fine) {
  .btn--primary:hover {
    background-color: var(--btn-primary-bg-hover);
  }
}

/* 2026-08-18 全站微動態規格 P2：hardcode 1px 改 token，理由同
   .primary-nav__list a:active 註解。 */
.btn--primary:active {
  background-color: var(--btn-primary-bg-active);
  transform: translateY(var(--motion-press-offset));
}

.btn--primary:disabled,
.btn--primary[aria-disabled="true"] {
  background-color: var(--color-neutral-300);
  color: var(--color-neutral-600);
  cursor: not-allowed;
}

/* --on-inverse：S2「How we work」——深底上的白色實心膠囊＋深字，
   17.6:1。DESIGN.md 原本只有透明＋白框的 button_secondary.on_dark，
   本規格新增此變體（規格 §A-2 C7）。 */
.btn--on-inverse {
  background-color: var(--btn-on-inverse-bg);
  color: var(--btn-on-inverse-fg);
}

@media (hover: hover) and (pointer: fine) {
  .btn--on-inverse:hover {
    background-color: var(--btn-on-inverse-bg-hover);
  }
}

/* 2026-08-18 全站微動態規格 P2：hardcode 1px 改 token，理由同上。 */
.btn--on-inverse:active {
  background-color: var(--btn-on-inverse-bg-active);
  transform: translateY(var(--motion-press-offset));
}

.btn--on-inverse:disabled,
.btn--on-inverse[aria-disabled="true"] {
  opacity: 0.4;
}

/* --secondary：本輪 0 使用者，入庫備用（DESIGN.md button_secondary.on_light）。
   狀態矩陣未列 hover/active/disabled 明確值，本輪不發明，只建立
   default 外觀，需要態時回頭出規格。 */
.btn--secondary {
  background-color: transparent;
  color: var(--color-brand-900);
  border: var(--border-width-hairline) solid var(--color-brand-900);
}


/* ── C8 `.icon-btn`（規格 §A-2 C8／§A-3 狀態矩陣，S5 carousel 控制）。
   44×44 尺寸：A-5 未提供專屬 token，比照既有 .menu-toggle／
   .nav-overlay__close（同為方形控制按鈕 touch target，皆 raw literal
   px、非本批可編輯範圍）的既定寫法處理，非新發明數值，回報中已揭露。
   邊框用 --border-functional（4.54:1 ≥3:1），禁用 --decorative-only
   （2.49:1，僅裝飾用）。 ── */
.icon-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  border: var(--border-width-hairline) solid var(--border-functional);
  border-radius: var(--radius-alias-control);
  background-color: transparent;
  cursor: pointer;
  /* 2026-08-18 全站微動態規格：矩陣對 [aria-disabled] 的 opacity 變化標記
     hover(160ms) 時長，原本未過渡（瞬時切換）。加入 opacity 使其平滑，
     opacity 為全站唯二允許的合成器屬性之一，非新違規。 */
  transition:
    background-color var(--motion-duration-hover) var(--motion-easing-standard),
    opacity var(--motion-duration-hover) var(--motion-easing-standard),
    transform var(--motion-duration-press) var(--motion-easing-standard);
}

.icon-btn__icon {
  width: var(--btn-icon-size);
  height: var(--btn-icon-size);
}

@media (hover: hover) and (pointer: fine) {
  .icon-btn:hover {
    background-color: var(--color-neutral-200);
  }
}

/* 2026-08-18 全站微動態規格 P2：原僅色變，補上全站一致的按下位移
   （矩陣「press 120」欄要求），token 化避免 reduce 漏洞。 */
.icon-btn:active {
  background-color: var(--color-neutral-300);
  transform: translateY(var(--motion-press-offset));
}

/* disabled＝捲到最左/最右時對應方向鍵不可用。用 aria-disabled 而非
   disabled 屬性，保留焦點可達性以利螢幕閱讀器理解邊界；
   pointer-events:none 只擋滑鼠 hover/click，不擋鍵盤 Tab/focus。 */
.icon-btn[aria-disabled="true"] {
  opacity: 0.4;
  cursor: not-allowed;
  pointer-events: none;
}


/* ── C9 `.media` — 11 張圖共用同一個元件（規格 §A-2 C9）。
   error state：.media 自身帶 --media-fallback-bg 灰底，圖載入失敗時
   3:2 版位不塌陷（<img> 帶 width/height 防 CLS 由下一批 HTML 負責）。
   --3x2 是預設外觀（比例/圓角已在 .media 本身），HTML 上仍可掛
   .media--3x2 class 以求顯式，不需要獨立、內容相同的空規則。
   hover 不在本元件定義——由 .card:hover .media__img 從外層驅動
   （.card 是 B4 的區塊層範圍，不在本批）。 ── */
.media {
  position: relative;
  aspect-ratio: var(--media-ratio);
  overflow: hidden;
  border-radius: var(--media-radius);
  background-color: var(--media-fallback-bg);
}

.media--thumb {
  border-radius: var(--media-radius-sm);
}

/* D37（docs/spec-s5-redesign.md §1②#1/#2 + §9）：S5 卡片圖改正方形。
   --media-ratio 全站僅 :root 定義一次、零覆寫的既有先例（見上方 C9
   註解）在此首次被打破——1:1 與 3:2 是內容不同的兩個比例值，不是
   .media--3x2 那種「顯式但零規則、三斷點皆同值」的情形。圓角比照
   .media--thumb 既有寫法沿用 --media-radius-sm（= small 階，四斷點
   12/10/12/14 由 --radius-small primitive 各自 media block 覆寫自動
   響應，此處零新增 media query）。 */
.media--1x1 {
  --media-ratio: var(--card-media-aspect);
  border-radius: var(--media-radius-sm);
}

/* D38（docs/spec-s5-redesign.md §3 逃生口，逐字）：素材右下 40%×30%
   若實測平均 sRGB 不達門檻（≤0.38），可對 .media 加掛本 class 提高
   描邊可讀性。預設不掛——開不開由 quality 對真實素材的 V7/V8 量測
   結果決定，不由手感決定。 */
.media--ordinal-scrim::before {
  content: '';
  position: absolute;
  inset-inline-end: 0;
  inset-block-end: 0;
  width: 40%;
  height: 30%;
  background: var(--card-ordinal-scrim-gradient);
  pointer-events: none;
}

/* ⚠️ <picture> 必須自己撐滿 .media，否則 .media__img 的 height:100% 會吃到
   picture 的內容高度而不是 .media 的高度 —— 結果是圖片只佔上半、下面留一片灰。
   （02-base.css 的 reset 給 img/picture 一組 height:auto，picture 因此縮成內容高。）

   2026-08-20 實測踩過：為了補 webp 而把 <img> 包進 <picture> 之後，
   1:1 的服務卡變成 380x380 的框裡塞 380x253 的圖。她自己的註解也記過同一件事
   —— 03-header-hero.css 提到「原本『單一 picture』年代用的 display:contents 手法
   （讓 picture 不佔盒模型、img 直接吃 .hero__media 的高度）」。
   這裡用明確的 block + 100% 而不是 display:contents，行為比較好預測。
   ⚠️ hero 的 .hero__slide-media 是**多個 picture 疊放**、走 position:absolute，
      不適用本規則，所以選擇器限定 .media 底下。 */
.media > picture {
  display: block;
  width: 100%;
  height: 100%;
}

.media__img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}


/* ── C10 `.tag`（規格 §A-2 C10，S4×4）。非互動、無 5 態（DESIGN.md
   已裁決，交接契約 硬約束⑬）。不得做成 <a>。 ── */
.tag {
  display: inline-block;
  padding-block: var(--tag-padding-block);
  padding-inline: var(--tag-padding-inline);
  border-radius: var(--radius-alias-control);
  background-color: var(--tag-bg);
  color: var(--tag-fg);
  font-family: var(--type-role-tag-label-family);
  font-size: var(--type-role-tag-label-size);
  line-height: var(--type-role-tag-label-line-height);
  letter-spacing: var(--type-role-tag-label-letter-spacing);
  font-weight: var(--type-role-tag-label-weight);
  white-space: nowrap;
}


/* ── C11 `.badge`（規格 §A-2 C11，S6×4 `Fictional proposal`）。紅線
   #7 強制元件，必須可見（不得 opacity<1、不得只在 hover 顯示）。
   規格只定義了 --on-inverse 這一個變體（S6 navy 專用）；padding-block
   A-5 未給專屬 token，比照 C10 tag 的節奏直接複用既有 --space-1
   （非新發明值）。base .badge 本輪無淺底變體可用，不擅自發明。
   非互動、無 5 態。 ── */
.badge {
  display: inline-block;
  padding-block: var(--space-1);
  padding-inline: var(--badge-padding-inline);
  border-radius: var(--radius-alias-control);
  font-family: var(--type-role-button-label-family);
  font-size: var(--type-role-button-label-size);
  line-height: var(--type-role-button-label-line-height);
  letter-spacing: var(--type-role-button-label-letter-spacing);
  font-weight: var(--type-role-button-label-weight);
  white-space: nowrap;
}

.badge--on-inverse {
  background-color: var(--badge-bg);
  color: var(--badge-fg);
}


/* ── C12 `.rule`（hairline 分隔，規格 §A-2 C12）。--on-inverse 不可
   直接沿用淺底 --border-hairline（#E8E8E8 對 #00173E 是 14.57:1，
   那是一條白線不是分隔線）；--border-hairline-on-inverse 對 navy
   1.32:1／對黑 1.21:1，與淺底 1.22:1 同一個感知重量。非互動、無 5 態。
   --v（垂直）欄間分隔屬 S6 .stat-grid 的區塊層用法（B5），本層只給
   基礎方向樣式。 ── */
.rule {
  border: none;
  background-color: var(--border-hairline);
}

.rule--h {
  width: 100%;
  height: var(--border-width-hairline);
}

.rule--v {
  width: var(--border-width-hairline);
  align-self: stretch;
}

.rule--on-inverse {
  background-color: var(--border-hairline-on-inverse);
}


/* ── C13 `.link-list`（footer 兩欄，規格 §A-2 C13）。垂直節奏：
   --footer-column-gap-block(16) + item 行高 22 = 38px（figma-exact）。
   觸控：22 行高 + padding-block:12px = 46px≥44；為維持 38px 視覺節奏
   不變，用 margin-block:-4px 抵銷 padding 撐出的額外高度。這是規格登錄過
   的 intentional deviation（理由：footer 同質連結清單，Figma 38px 節奏為
   figma-exact；擴大節奏會破壞兩欄底緣對齊 D11），frontend 不得自行改
   節奏。字重/字級用 --type-role-button-label-*（caption/700），非
   tag-label（caption/400）——link-list item 字重是 700，用 tag-label 會
   少了粗體。無 disabled。

   2026-08-18 QA 修正（qaB a11y FAIL，5 筆寬度不足 44px）：上一版註解曾寫
   「可點區因此相鄰重疊 8px」，QA 實測推翻——相鄰命中區其實是相隔 8px、
   不是重疊，規格登錄的例外只涵蓋垂直節奏（above），從未涵蓋寬度軸。真正
   的缺口在 `.link-list a` 舊為 `inline-block`（shrink-to-fit 自己的文字
   寬度），沒有吃滿父層 `<li>`（flex column 預設 stretch，已是滿欄寬）的
   寬度——欄寬本身由同欄最長字串撐開（如 explore 欄的「Contact Us」），
   但較短的字（Home/About/News）只佔自己文字的窄寬，未達 44px 地板。改為
   `block`＋`width:100%` 讓每個連結吃滿欄寬，只動水平軸，不改
   padding-block/margin-block/gap 任何一個垂直度量，38px 節奏不受影響。 ── */
.link-list {
  display: flex;
  flex-direction: column;
  gap: var(--footer-column-gap-block);
  list-style: none;
}

/* 2026-08-18 全站微動態規格 P3：HTML 端已把 `u-underline-wipe` class 直接
   掛在 `.link-list a` 本身（grep index.html 核實），grep 確認此元素全站
   零既有 ::before/::after 使用，安全套用。position:relative 為底線
   ::before 建立 positioning context——與 .primary-nav__list a（同樣
   padding-block:var(--space-3) 且 position:relative + bottom:0 底線）
   既有手法一致，非新發明的定位策略。文字色矩陣標「→ --text-primary」，
   但本規則現況預設色本已是 --text-primary（非其餘狀態），核對後判定
   矩陣此欄為既定目標的重申、非需要變更的 delta，未新增色彩規則。 */
.link-list a {
  position: relative;
  display: block;
  width: 100%;
  padding-block: var(--space-3);
  margin-block: -4px;
  color: var(--text-primary);
  font-family: var(--type-role-button-label-family);
  font-size: var(--type-role-button-label-size);
  line-height: var(--type-role-button-label-line-height);
  letter-spacing: var(--type-role-button-label-letter-spacing);
  font-weight: var(--type-role-button-label-weight);
  text-decoration: none;
}

.link-list a.u-underline-wipe::before {
  content: '';
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: 2px;
  background-color: var(--border-interactive);
  transform: scaleX(0);
  transform-origin: left center;
  transition: transform var(--motion-duration-slide) var(--motion-easing-standard);
}

.link-list--explore a {
  text-transform: uppercase;
}

.link-list a.u-underline-wipe:focus-visible::before {
  transform: scaleX(1);
}

@media (hover: hover) and (pointer: fine) {
  .link-list a.u-underline-wipe:hover::before {
    transform: scaleX(1);
  }
}

/* 2026-08-18 全站微動態規格 P2：hardcode 1px 改 token，理由同
   .primary-nav__list a:active 註解。 */
.link-list a:active {
  transform: translateY(var(--motion-press-offset));
}


/* ── C14 `.empty-state`（規格 §A-2 C14）。三條硬約束（DESIGN.md D14）：
   不得是 <a>、不得有 href（含 #）、不得有 hover/pointer 樣式——本規則
   刻意不含任何互動選擇器或 cursor 宣告。純文字。 ── */
.empty-state {
  color: var(--text-secondary);
  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(--type-role-meta-weight);
}


/* ══════════════════════════════════════════════════════════════
   S2 BLOCK LAYER — 區塊層（規格 §B「S2 — 深色圖文區」；.split 命名空間，
   Unit 2 派工單硬約束⑨：只寫 .split，不寫 .news/.card/.stat/.site-footer__*）
   ══════════════════════════════════════════════════════════════ */

/* .split — S2/S3 共用的圖文雙欄骨架，本批只建 S2 用得到的部分。
   base/wide：grid-template-columns 吃 --split-columns（583px 577px，
   token 已在既有 tablet/mobile media block 覆寫為 1fr）；.split 本身
   不寫 media query（硬約束⑥：同一元件四斷點須引用同一 token 名，響應
   由 token 層承擔）。
   .split--media-end（S3「文左圖右」鏡射）不在本批範圍，未建——DOM 順序
   或 order 屬性的取捨屬「frontend 可自行決定」（交接契約 4「邊界」），
   不替負責 S3 的下一批預先拍板。
   .split--media-start：預設 DOM 順序（media 在前）本身就是「圖左文
   右」，不需要額外規則——同 C9 `.media--3x2` 的既定先例（B1 報告：
   「無視覺差異的顯式變體 class 允許零規則」，HTML 上仍掛 class 以求
   顯式）。 */
.split {
  display: grid;
  grid-template-columns: var(--split-columns);
  align-items: center;
  gap: var(--space-7);
}

.split > * {
  min-width: 0; /* 防 grid item（圖片／長文字）撐爆軌道寬度，CSS grid 常見陷阱 */
}

/* 右側文字直欄：eyebrow → title → prose → btn 單一 gap 節奏（規格 §B
   S2「文字直欄內部 gap: var(--prose-stack-gap)（24）」，非 C3
   .section-head 的兩層節奏——A-1 總表列 C3 用於「S2 S3 S4 S5 S6」但
   §B 逐區組裝對 S2 的操作性描述是扁平單一 gap 直欄、未出現
   .section-head，兩處有落差，本批以更具體的 §B 為準（同 B1 報告處理
   prose/code-block 落差的方法論），回報中已標出。 */
.split__content {
  display: flex;
  flex-direction: column;
  align-items: flex-start; /* 修正：flex column 預設 stretch 會把 inline-flex 的
     .btn 撐成整欄滿寬（真機實測抓到，577px/327px 滿版 pill 按鈕，非按鈕內容應有
     尺寸）。flex-start 讓 .btn 恢復 shrink-to-fit；p/h2 本身是 block 元素、有無
     stretch 皆滿寬，.prose 有 max-width 封頂，三者視覺不受影響。 */
  gap: var(--prose-stack-gap);
}


/* ══════════════════════════════════════════════════════════════
   S3 BLOCK LAYER — 區塊層（規格 §B「S3 — 淺灰圖文區（S2 鏡射）」；
   .split 命名空間，B2 派工單硬約束⑨：只寫 .split，不寫其他區塊）

   .split--media-end（S3「文左圖右」鏡射，B1 註解標為未建、DOM 順序或
   order 屬性取捨屬「frontend 可自行決定」——交接契約 4「邊界」）。

   本批採 DOM 順序反轉（.split__content 在前、.media 在後），與 S2 的
   DOM 順序（.media 在前）刻意相反：desktop 2 欄 grid 依 DOM 順序自動
   排成文左圖右，不需要任何 order 規則介入，與 .split--media-start
   零規則的既定先例（「無視覺差異的顯式變體 class 允許零規則」）同一
   精神——這裡差別只在於「零規則」的那個斷點從 desktop 換成
   tablet/mobile。

   ≤1023 收成單欄（--split-columns 已在既有 media query 覆寫為 1fr）
   時，若不介入，DOM 順序會讓文字先出現、圖片在後——與規格「≤1023
   取消鏡射、一律圖先文後」相反（單欄堆疊時鏡射不可感，只會讓 S2 與
   S3 圖文順序不一致）。故只在該斷點用 order:-1 把 .media 拉到最前，
   讓視覺順序回到與 S2 一致的圖先文後；.split__content 不需要對應
   宣告（預設 order:0 已經在 .media 之後）。 ── */
@media (max-width: 1023px) {
  .split--media-end .media {
    order: -1;
  }
}


/* ══════════════════════════════════════════════════════════════
   S4 BLOCK LAYER — 區塊層（規格 §B「S4 — News」；.news/.news-row 命名空間，
   B3 派工單硬約束⑩：只寫 .news/.news-row，不寫 .card/.stat/.site-footer__*）
   施工依據：docs/spec-s2-s6-components.md §B S4 段、§A-2 C9/C10/C12/C14、
   §A-3 互動狀態矩陣 .news-row 列、§A-4 內容韌性 .news-row 列

   互動實作說明：規格對 .news-row 的 focus-visible 態標「同上 :has()」
   （同 .card 手法），代表可聚焦元素是列內的一個後代連結、不是 .news-row
   本身。本批採 stretched-link 手法：.news-row__link 只包標題文字（可讀
   連結名稱＝完整標題，不需額外 aria-label），其 ::after 偽元素
   position:absolute + inset:0，相對 .news-row（position:relative）撐滿
   整列可點/可聚焦區——DOM 巢狀與連結範圍屬「frontend 可自行決定」（交接
   契約 4 邊界）。.news-row:has(.news-row__link:focus-visible) 在列外緣
   畫 ring；.news-row__link 本身的 outline:none 有明確替代（ring 轉移到
   父層），非違反硬約束③無替代裸關 outline。已知限制：:has() 不支援的
   瀏覽器會讓這個替代失效（規格本身在 .card 已預期用同一手法，非本批
   獨有風險，回報中已揭露）。 ══════════════════════════════════════════════════════════════ */

.news {
  display: grid;
  grid-template-columns: var(--news-columns);
  align-items: start;
  gap: var(--space-7);
}

.news > * {
  min-width: 0;
}

/* gap:0 是 figma-exact——列間分隔靠每列自己的 border-block-start，不靠
   flex gap（規格 §B S4：「列間 gap: 0 + 每列 border-block-start」）。 */
.news-list {
  display: flex;
  flex-direction: column;
}

.news-row {
  position: relative;
  display: grid;
  grid-template-columns: var(--news-thumb-width) 1fr auto;
  align-items: center;
  gap: var(--news-row-gap);
  min-height: var(--news-row-height); /* ≤768 已由既有 token 覆寫為 auto，本層不重寫 */
  padding-inline: var(--news-row-padding-inline); /* 2026-08-19 S4 news-row hover pass（R1）：
     plate 水平內距，≤768 由既有 token 覆寫為 space-4(16px)，見 media block */
  padding-block: var(--news-row-padding-block);
  border-block-start: var(--border-width-hairline) solid var(--border-hairline);
  /* 2026-08-18 全站微動態規格 P1：整列 bg 表面色變（矩陣「S4 .news-row
     hover」列，此前無此規則，全新新增）。
     2026-08-18 追加核對：寫成 base（非 :hover 覆寫）是否引入新的可見底色
     變化？已核對 index.html #s4 section class＝`section section--subtle`，
     `.section--subtle { background-color: var(--surface-subtle) }`——即 S4
     區塊本身底色就是 --surface-subtle（#F3F3F3），與這裡的 base 宣告同值，
     視覺上無變化，維持現況不撤銷。
     2026-08-19 更新（S4 hover pass R1）：下方「附帶觀察」段所述「hover 無
     第二色可切換」已被本次改動推翻——--news-row-bg-hover 引入 #FFFFFF 為
     真實第二色，段落保留僅供沿革查閱，現況請見 R3 hover 區塊。
     附帶觀察（非本項修正範圍，僅記錄）：因 base 與（不存在的）hover 態同色，
     矩陣要求的「hover 表面色變」目前沒有可見效果可言——base 已恆為
     --surface-subtle，沒有第二色可供 hover 再切換。是否需另訂 hover 專屬
     色階，屬新視覺決策，留待設計裁示，本批未動手。 */
  background-color: var(--news-row-bg);
  transition: transform var(--motion-duration-press) var(--motion-easing-standard);
  /* 2026-08-19 用戶當面裁決極簡化 hover（派工單「NEWS hover 極簡化」）：background-color
     變色／box-shadow ring／border-radius／border-color 四項裝飾 hover 效果與其 transition
     已刪除，只留 transform（:active 按壓位移）。用戶原話「news 的 Hover 這樣太 奇怪 圖片
     放大 箭頭 微動就好」——整列可點（本規則 position:relative 是 stretched-link 的
     containing block）與 .news-row__title 已移除的 position:relative 不受影響、原樣
     保留，未被本次改動觸碰。 */
}

/* .reveal-group.is-armed.is-revealed .reveal（styles.css:1003-1009）用 transition
   簡寫把 transition-property 整個重設為 opacity,transform，特異度 (0,4,0) 蓋過
   .news-row 的 (0,1,0)，且 is-armed/is-revealed 由 site.js 加上後永不移除。本規則
   特異度 (0,5,0)，不依賴原始碼順序的 tie-break（沿用 .card .card__cta:active
   既有先例，styles.css:3334）。
   已知殘留：transform 仍綁在 --motion-duration-enter(400ms)，故 :active 的 1px
   按下位移實跑 400ms 而非宣告的 120ms —— 這是既有狀態、非本次回歸；根治須把
   REVEAL 由 transition 改為 @keyframes + animation（hero-load-in 已有先例，
   styles.css:2173-2181），屬另案。2026-08-19 hover 極簡化：background-color／
   box-shadow／border-color／border-radius 四項已隨 base 規則一併移除，此處同步簡化。 */
.reveal-group.is-armed.is-revealed .news-row.reveal {
  transition:
    opacity   var(--motion-duration-enter) var(--motion-easing-standard),
    transform var(--motion-duration-enter) var(--motion-easing-standard);
}

.news-row > * {
  min-width: 0;
}

/* 2026-08-18 全站微動態規格 P2：hardcode 1px 改 token（本規則未列在矩陣
   8 處明細內，但與同批修正的其餘 :active 規則同一缺陷——字面 1px 繞過
   reduced-motion 安全網，一併修正，屬既有 pattern 的一致性維護）。 */
.news-row:active {
  transform: translateY(var(--motion-press-offset));
}

/* 2026-08-19 用戶當面裁決極簡化 hover：background-color／border-radius／box-shadow
   ring／相鄰列分隔線隱藏四項裝飾已移除，鍵盤 focus 指示改為只靠 outline（3px solid
   + 2px offset，全站標準值，單獨已是合規的清楚指示，不依賴額外背景/ring）。箭頭
   位移與圖片放大兩項與滑鼠 hover 保持同步（鍵盤與滑鼠拿到同一組視覺回饋，此原則
   延續自 R4 既有裁決，只是「同一組視覺」現已簡化）。 */
.news-row:has(.news-row__link:focus-visible) {
  outline: var(--focus-ring-width) solid var(--focus-ring-on-light);
  outline-offset: var(--focus-ring-offset);
}

.news-row:has(.news-row__link:focus-visible) .news-row__arrow svg {
  transform: translateX(var(--space-1));
}

.news-row:has(.news-row__link:focus-visible) .news-row__media .media__img {
  transform: scale(var(--media-scale-hover));
}

.news-row__meta {
  display: flex;
  align-items: center;
  gap: var(--space-3);
}

.news-row__date {
  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(--type-role-meta-weight);
  color: var(--text-secondary);
}

.news-row__content {
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: var(--space-2);
}

/* h4 階：規格只寫「標題（h4，clamp 1 行）」，未給獨立 type-role token；
   --type-role-card-title-* 本身就是 h4 尺度（見既有定義），復用既有角色
   token，不新發明（交接契約 硬約束②）。 */
/* 2026-08-18 全站微動態規格 P3（.u-underline-wipe 定義見 SHARED ATOM LAYER
   區塊）：HTML 端已把 `u-underline-wipe` class 掛在子層 `.news-row__link`
   上（grep index.html 核實），但該元素的 `::after` 已被下方 stretched-link
   佔用（`position:absolute; inset:0`，相對 `.news-row` 撐滿整列可點區）——
   若在 `.news-row__link` 本身建立 `position:relative`，會讓它自己的
   `::after` 的 containing block 從 `.news-row`（整列）縮小成自己的文字寬，
   破壞整列可點擊/可鍵盤觸達區（且 ≤768 grid-template-areas 重排後無法用
   固定 inset 補償，見任務報告）。改在父層 `.news-row__title`（純文字
   wrapper `<h4>`，grep 確認全站零既有 ::before/::after/position 使用）
   建立 positioning context 與底線本體，視覺結果相同（文字緊貼），不觸碰
   `.news-row__link` 的既有規則一個字。 */
.news-row__title {
  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);
  color: var(--text-primary);
  display: -webkit-box;
  -webkit-line-clamp: 1;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

.news-row__link {
  color: inherit;
  text-decoration: none;
}

/* stretched link：見本區塊頂部大註解 */
.news-row__link::after {
  content: '';
  position: absolute;
  inset: 0;
  z-index: 1;
}

.news-row__link:focus-visible {
  outline: none; /* 替代：ring 轉移到 .news-row:has() 規則，非無替代違約 */
}

.news-row__excerpt {
  font-family: var(--type-role-paragraph-family);
  font-size: var(--type-role-paragraph-size);
  line-height: var(--type-role-paragraph-line-height);
  letter-spacing: var(--type-role-paragraph-letter-spacing);
  font-weight: var(--type-role-paragraph-weight);
  color: var(--text-body);
  display: -webkit-box;
  -webkit-line-clamp: 1;
  -webkit-box-orient: vertical;
  overflow: hidden;
  max-width: var(--type-role-paragraph-max-width);
}

.news-row__arrow {
  display: inline-flex;
  color: var(--text-link);
}

.news-row__arrow svg {
  width: var(--news-arrow-size);
  height: var(--news-arrow-size);
  display: block;
  transition: transform var(--motion-duration-hover) var(--motion-easing-standard);
}

.news-row__media .media__img {
  transition: transform var(--motion-duration-hover) var(--motion-easing-standard); /*
     2026-08-19 用戶當面裁決極簡化 hover：新增圖片放大效果，.media 父層已有
     overflow:hidden（styles.css:2660 一帶），縮放不會溢出卡片邊界。 */
}

/* iOS Safari pitfalls #8：hover 專屬樣式收在 hover-capable 裝置內
   （沿用本檔既有慣例，見 .primary-nav__list a:hover 等處）。 */
@media (hover: hover) and (pointer: fine) {
  /* 2026-08-19 用戶當面裁決極簡化 hover（派工單「NEWS hover 極簡化」）：background-color
     變色／border-radius／box-shadow ring／相鄰列分隔線隱藏四項裝飾已移除。用戶原話
     「news 的 Hover 這樣太 奇怪 圖片放大 箭頭 微動就好」——只留圖片放大與箭頭位移兩項。 */
  .news-row:hover .news-row__media .media__img {
    transform: scale(var(--media-scale-hover));
  }

  .news-row:hover .news-row__arrow svg {
    transform: translateX(var(--space-1));
  }
}

/* ≤768：圖上文下，箭頭移到摘要行尾附近（規格 §B S4）。grid-template-areas
   把三個既有 grid item 重新排位，不靠改 DOM 順序、不靠改 --news-row-gap
   以外任何 token 引用（硬約束⑥）。 */
@media (max-width: 768px) {
  .news-row {
    grid-template-columns: 1fr auto;
    grid-template-areas:
      "media    media"
      "content  arrow";
  }

  .news-row__media {
    grid-area: media;
  }

  .news-row__content {
    grid-area: content;
  }

  .news-row__arrow {
    grid-area: arrow;
    align-self: end;
  }
}

