@charset "UTF-8";
/* ========================
  🎨 Design Tokens - Variables
======================== */
/* Theme semantic colors */
/* Libraries fixed colors：不隨 Theme 切換。 */
/* v1 migration aliases：案件檔案完成遷移前保留，不是新的正式命名。 */
/* Viewport breakpoints */
/* Font Family */
/* Content Spacing */
/*
  content-px：內容版心與瀏覽器邊界的預設距離
  content-py：承接內容之容器的上下留白
  Section 自身構圖需要的 padding 使用案件 Node override，不建立 section-py Token。
*/
/* Content Spacing - Mobile */
/* Content Spacing - Desktop */
/* Text Block Padding */
/* Layout Pattern */
/* 舊單值 alias；新 layout 應分別使用 X / Y。 */
/* Form Structure v1（DDWPS-FORM-CONTRACT-v1.md §4.2）
   Starter 泛用預設值，非任何特定案件設計稿；案件依自己的設計覆寫這些 Token，
   不需要新增第二套 Form class。*/
/* ========================
  🌐 Root Runtime Tokens
======================== */
:root {
  --design-width: 1920;
  --vw-base: calc(100vw / var(--design-width));
  --color-brand-primary: #6e8800;
  --color-brand-primary-hover: #444f13;
  --color-brand-secondary: #bea850;
  --color-brand-secondary-hover: #a68915;
  --color-brand-neutral: #888888;
  --color-brand-neutral-hover: #656565;
  --color-text-primary: #212529;
  --color-text-secondary: #495057;
  --color-text-muted: #6c757d;
  --color-background-primary: #ffffff;
  --color-background-secondary: #f8f9fa;
  --color-background-surface: #ffffff;
  --color-border-primary: #dee2e6;
  --color-border-secondary: #ced4da;
  --color-fixed-black: #000000;
  --color-fixed-white: #ffffff;
  /* migration aliases */
  --color-primary: var(--color-brand-primary);
  --color-primary-hover: var(--color-brand-primary-hover);
  --color-secondary: var(--color-brand-secondary);
  --color-secondary-hover: var(--color-brand-secondary-hover);
  --color-gray: var(--color-brand-neutral);
  --color-gray-hover: var(--color-brand-neutral-hover);
  /*
    🎯 Focus Ring Token
    案件只要覆寫 --focus-ring-color 就能換成案件主色；
    預設走 --color-brand-primary，任何情況下都不得改成 none。
  */
  --focus-ring-color: var(--color-brand-primary);
  --focus-ring-width: max(2px, calc(3 * var(--vw-base)));
  --focus-ring-offset: max(2px, calc(2 * var(--vw-base)));
  /*
    🔤 字型角色 Token
    預設值直接沿用共用 Sass Token（`_tokens.scss`），不另寫一份 fallback stack。
    案件只要覆寫 --font-zh-sans 等四個角色，Body、Footer 與所有 .page-* / .font-*
    就會一起跟隨——不需要再建立第二套 case-specific 字型變數。
  */
  --font-zh-sans: Noto Sans TC, PingFang TC, Microsoft JhengHei, sans-serif;
  --font-zh-serif: Noto Serif TC, PMingLiU, serif;
  --font-en-sans: Helvetica Neue, Arial, sans-serif;
  --font-en-serif: Playfair Display, Times New Roman, serif;
  /*
    Body 是全站唯一的 typography 基準，宣告點只有 `_typography.scss` 的 `body`。
    ⚠ font-size 必須維持 vw()：整個設計系統以 --vw-base 縮放，寫死 px 會讓
      Nav 與所有未指定字級的節點在其他視窗寬度下失準。
    ⚠ line-height 必須無單位：子節點字級不同，繼承絕對行高會算錯行距。
  */
  --font-body-family: var(--font-zh-sans);
  --font-body-size: calc(16 * var(--vw-base));
  --font-body-size-mobile: calc(14.4 * var(--vw-base));
  --font-body-line-height: 1.66;
  --font-body-letter-spacing: 0.04em;
  --font-body-weight: 400;
  --content-px: calc(25 * var(--vw-base));
  --content-py: calc(61 * var(--vw-base));
  --container-max-width: 100%;
  --txt-px: calc(33 * var(--vw-base));
  --txt-py: calc(33 * var(--vw-base));
  /* Layout Phase 3（2026-09-15 Gap 巢狀隔離）：Theme 預設值，只給 .layout-stack／
     .layout-split 當 fallback；案件不得直接覆寫這兩個 Token 去改變單一 Layout
     節點的間距——單一節點要覆寫的是 .layout-stack／.layout-split 自己 reset 出
     來的 --layout-gap-x/y（見 _layout.scss）。要整個 Section 範圍內的多個
     Layout 一起改預設值時，才在該範圍的 owner class 覆寫這兩個 Theme Token。 */
  --layout-default-gap-x: calc(32 * var(--vw-base));
  --layout-default-gap-y: calc(32 * var(--vw-base));
  --txt-title-gap: calc(20 * var(--vw-base));
  --txt-body-gap: calc(14 * var(--vw-base));
  /*
    📋 Form Structure v1 Token（DDWPS-FORM-CONTRACT-v1.md §4.2）
    --form-grid-gap-x/y 由 _forms.scss 分別轉接到 .contact-form__grid 與
    .contact-form__verify 兩個各自獨立的 .layout-grid，不在這裡直接控制排列。
  */
  --form-grid-gap-x: calc(16 * var(--vw-base));
  --form-grid-gap-y: calc(16 * var(--vw-base));
  --form-control-height: calc(44 * var(--vw-base));
  --form-control-padding-x: calc(14 * var(--vw-base));
  --form-control-padding-y: calc(10 * var(--vw-base));
  --form-control-font-size: calc(14.4 * var(--vw-base));
  --form-control-line-height: 1.5;
  --form-control-color: var(--color-text-primary);
  --form-control-placeholder-color: var(--color-text-muted);
  --form-control-background: var(--color-background-surface);
  --form-control-border-color: var(--color-border-secondary);
  --form-control-border-width: 1px;
  --form-control-radius: 0;
  /* --surface-translucent 消費這個 Token，不寫死案件顏色；色版來自
     $color-background-surface，透明度是 Starter 預設比例。 */
  --form-control-background-translucent: rgba(255, 255, 255, 0.6);
  --form-control-focus-color: var(--color-brand-primary);
  --form-control-focus-shadow: 0 0 calc(10 * var(--vw-base)) calc(3 * var(--vw-base)) rgba(110, 136, 0, .44);
  --form-label-color: var(--color-text-primary);
  --form-label-font-size: calc(12.8 * var(--vw-base));
  --form-label-gap: calc(6 * var(--vw-base));
  --form-helper-color: var(--color-text-muted);
  --form-error-color: #dc3545;
  --form-submit-height: calc(44 * var(--vw-base));
  --form-submit-color: var(--color-fixed-white);
  --form-submit-background: var(--color-brand-primary);
  --form-submit-radius: 0;
  /* v2 一般尺寸 Checkbox 專用；v2 invisible／v3 不適用這個縮放模型。 */
  --form-recaptcha-scale: 1;
}

@media (max-width: 991.98px) {
  :root {
    --design-width: 610;
  }
}
@media (min-width: 992px) {
  :root {
    --content-px: calc(160 * var(--vw-base));
    --content-py: calc(96 * var(--vw-base));
    --container-max-width: calc(1600 * var(--vw-base));
    --txt-px: calc(80 * var(--vw-base));
    --txt-py: calc(64 * var(--vw-base));
    --layout-default-gap-x: calc(120 * var(--vw-base));
    --layout-default-gap-y: calc(120 * var(--vw-base));
    --txt-title-gap: calc(32 * var(--vw-base));
    --txt-body-gap: calc(16 * var(--vw-base));
    --form-grid-gap-x: calc(24 * var(--vw-base));
    --form-grid-gap-y: calc(24 * var(--vw-base));
    --form-control-height: calc(52 * var(--vw-base));
    --form-control-padding-x: calc(16 * var(--vw-base));
    --form-control-padding-y: calc(12 * var(--vw-base));
    --form-control-font-size: calc(16 * var(--vw-base));
    --form-label-font-size: calc(14 * var(--vw-base));
    --form-label-gap: calc(8 * var(--vw-base));
    --form-submit-height: calc(52 * var(--vw-base));
  }
}
[data-color-mode=light] {
  --color-background-primary: #ffffff;
  --color-background-secondary: #f8f9fa;
  --color-background-surface: #ffffff;
  --color-text-primary: #212529;
  --color-text-secondary: #495057;
  --color-text-muted: #6c757d;
  --color-border-primary: #dee2e6;
  --color-border-secondary: #ced4da;
  --form-control-color: var(--color-text-primary);
  --form-label-color: var(--color-text-primary);
  --form-control-placeholder-color: var(--color-text-muted);
  --form-helper-color: var(--color-text-muted);
  --form-control-background: var(--color-background-surface);
  --form-control-border-color: var(--color-border-secondary);
  --form-control-background-translucent: rgba(255, 255, 255, 0.6);
  color: var(--color-text-primary);
}

[data-color-mode=dark] {
  --color-background-primary: #1a1d21;
  --color-background-secondary: #22262b;
  --color-background-surface: #2a2f35;
  --color-text-primary: #f8f9fa;
  --color-text-secondary: #ced4da;
  --color-text-muted: #adb5bd;
  --color-border-primary: #3d444b;
  --color-border-secondary: #7b848c;
  --form-control-color: var(--color-text-primary);
  --form-label-color: var(--color-text-primary);
  --form-control-placeholder-color: var(--color-text-muted);
  --form-helper-color: var(--color-text-muted);
  --form-control-background: var(--color-background-surface);
  --form-control-border-color: var(--color-border-secondary);
  --form-control-background-translucent: rgba(42, 47, 53, 0.6);
  color: var(--color-text-primary);
}

.page-wrap[data-color-mode] {
  background-color: var(--color-background-primary);
}

/* Responsive naming: family/property-breakpoint-value.
   Mobile is the base; only Desktop overrides are generated. */
/* 本地 UI 基礎層：只保留模板需要的能力，不依賴 Bootstrap 或 --bs-*。 */
html {
  line-height: 1.5;
  -webkit-text-size-adjust: 100%;
}

/*
  body 只負責 reset 與頁面底色／文字色（語意 Token）。
  ⚠ font-family / font-size 已移除：typography 的唯一權威來源是 `_typography.scss` 的 `body`。
    這裡原本的兩行與那裡同值重複，且因 @use 順序永遠被覆蓋，屬於死碼。
*/
body {
  margin: 0;
  color: var(--color-text-primary);
  background: var(--color-background-primary);
}

img, svg, video, canvas, iframe {
  display: block;
  max-width: 100%;
}

button, input, select, textarea {
  margin: 0;
  font: inherit;
}

table {
  width: 100%;
  border-collapse: collapse;
}

.container, .container-fluid {
  width: 100%;
  margin-inline: auto;
}

.container {
  max-width: var(--container-max-width);
}

.row {
  --grid-gap-x: calc(24 * var(--vw-base));
  --grid-gap-y: 0;
  display: flex;
  flex-wrap: wrap;
  margin-inline: calc(var(--grid-gap-x) / -2);
  margin-top: calc(var(--grid-gap-y) * -1);
}
.row > * {
  width: 100%;
  max-width: 100%;
  padding-inline: calc(var(--grid-gap-x) / 2);
  margin-top: var(--grid-gap-y);
}

.col-6 {
  width: 50%;
}

.col-12 {
  width: 100%;
}

.g-0, .gx-0 {
  --grid-gap-x: 0;
}

.g-2 {
  --grid-gap-x: calc(8 * var(--vw-base));
  --grid-gap-y: calc(8 * var(--vw-base));
}

.g-3 {
  --grid-gap-x: calc(16 * var(--vw-base));
  --grid-gap-y: calc(16 * var(--vw-base));
}

.g-4 {
  --grid-gap-x: calc(24 * var(--vw-base));
  --grid-gap-y: calc(24 * var(--vw-base));
}

.d-none {
  display: none !important;
}

.d-block {
  display: block !important;
}

.d-inline {
  display: inline !important;
}

.d-inline-block {
  display: inline-block !important;
}

.d-flex {
  display: flex !important;
}

.d-grid {
  display: grid !important;
}

@media (max-width: 991.98px) {
  .d-mobile-none {
    display: none !important;
  }
  .d-mobile-block {
    display: block !important;
  }
  .d-mobile-inline {
    display: inline !important;
  }
  .d-mobile-inline-block {
    display: inline-block !important;
  }
  .d-mobile-flex {
    display: flex !important;
  }
  .d-mobile-grid {
    display: grid !important;
  }
}
@media (min-width: 992px) {
  .d-desktop-none {
    display: none !important;
  }
  .d-desktop-block {
    display: block !important;
  }
  .d-desktop-inline {
    display: inline !important;
  }
  .d-desktop-inline-block {
    display: inline-block !important;
  }
  .d-desktop-flex {
    display: flex !important;
  }
  .d-desktop-grid {
    display: grid !important;
  }
}
.flex-wrap {
  flex-wrap: wrap !important;
}

.flex-column {
  flex-direction: column !important;
}

.flex-grow-1 {
  flex-grow: 1 !important;
}

.align-items-center {
  align-items: center !important;
}

.justify-content-center {
  justify-content: center !important;
}

.justify-content-between {
  justify-content: space-between !important;
}

.position-relative {
  position: relative !important;
}

.sticky-top {
  position: sticky !important;
  top: 0;
  z-index: 20;
}

.w-100 {
  width: 100% !important;
}

.h-100 {
  height: 100% !important;
}

.small, small {
  font-size: 0.875em;
}

.h4 {
  font-size: calc(24 * var(--vw-base));
}

.h5 {
  font-size: calc(20 * var(--vw-base));
}

.h6 {
  font-size: calc(16 * var(--vw-base));
}

.fw-bold {
  font-weight: 700 !important;
}

.fw-semibold {
  font-weight: 600 !important;
}

.text-start {
  text-align: start !important;
}

.text-center {
  text-align: center !important;
}

.text-end {
  text-align: end !important;
}

.text-decoration-none {
  text-decoration: none !important;
}

.lh-1 {
  line-height: 1 !important;
}

.text-primary {
  color: #6e8800 !important;
}

.text-secondary {
  color: #bea850 !important;
}

.text-muted {
  color: #6c757d !important;
}

.text-dark {
  color: #212529 !important;
}

.text-light {
  color: #f8f9fa !important;
}

.text-white {
  color: #fff !important;
}

.bg-primary {
  background-color: #6e8800 !important;
}

.bg-secondary {
  background-color: #bea850 !important;
}

.bg-light {
  background-color: #f8f9fa !important;
}

.bg-dark {
  background-color: #212529 !important;
}

.bg-white {
  background-color: #fff !important;
}

.m-0 {
  margin: 0 !important;
}

.mt-0 {
  margin-top: 0 !important;
}

.mb-0 {
  margin-bottom: 0 !important;
}

.ms-0 {
  margin-inline-start: 0 !important;
}

.me-0 {
  margin-inline-end: 0 !important;
}

.mx-0 {
  margin-inline: 0 !important;
}

.my-0 {
  margin-block: 0 !important;
}

.p-0 {
  padding: 0 !important;
}

.pt-0 {
  padding-top: 0 !important;
}

.pb-0 {
  padding-bottom: 0 !important;
}

.ps-0 {
  padding-inline-start: 0 !important;
}

.pe-0 {
  padding-inline-end: 0 !important;
}

.px-0 {
  padding-inline: 0 !important;
}

.py-0 {
  padding-block: 0 !important;
}

.gap-0 {
  gap: 0 !important;
}

.m-1 {
  margin: calc(4 * var(--vw-base)) !important;
}

.mt-1 {
  margin-top: calc(4 * var(--vw-base)) !important;
}

.mb-1 {
  margin-bottom: calc(4 * var(--vw-base)) !important;
}

.ms-1 {
  margin-inline-start: calc(4 * var(--vw-base)) !important;
}

.me-1 {
  margin-inline-end: calc(4 * var(--vw-base)) !important;
}

.mx-1 {
  margin-inline: calc(4 * var(--vw-base)) !important;
}

.my-1 {
  margin-block: calc(4 * var(--vw-base)) !important;
}

.p-1 {
  padding: calc(4 * var(--vw-base)) !important;
}

.pt-1 {
  padding-top: calc(4 * var(--vw-base)) !important;
}

.pb-1 {
  padding-bottom: calc(4 * var(--vw-base)) !important;
}

.ps-1 {
  padding-inline-start: calc(4 * var(--vw-base)) !important;
}

.pe-1 {
  padding-inline-end: calc(4 * var(--vw-base)) !important;
}

.px-1 {
  padding-inline: calc(4 * var(--vw-base)) !important;
}

.py-1 {
  padding-block: calc(4 * var(--vw-base)) !important;
}

.gap-1 {
  gap: calc(4 * var(--vw-base)) !important;
}

.m-2 {
  margin: calc(8 * var(--vw-base)) !important;
}

.mt-2 {
  margin-top: calc(8 * var(--vw-base)) !important;
}

.mb-2 {
  margin-bottom: calc(8 * var(--vw-base)) !important;
}

.ms-2 {
  margin-inline-start: calc(8 * var(--vw-base)) !important;
}

.me-2 {
  margin-inline-end: calc(8 * var(--vw-base)) !important;
}

.mx-2 {
  margin-inline: calc(8 * var(--vw-base)) !important;
}

.my-2 {
  margin-block: calc(8 * var(--vw-base)) !important;
}

.p-2 {
  padding: calc(8 * var(--vw-base)) !important;
}

.pt-2 {
  padding-top: calc(8 * var(--vw-base)) !important;
}

.pb-2 {
  padding-bottom: calc(8 * var(--vw-base)) !important;
}

.ps-2 {
  padding-inline-start: calc(8 * var(--vw-base)) !important;
}

.pe-2 {
  padding-inline-end: calc(8 * var(--vw-base)) !important;
}

.px-2 {
  padding-inline: calc(8 * var(--vw-base)) !important;
}

.py-2 {
  padding-block: calc(8 * var(--vw-base)) !important;
}

.gap-2 {
  gap: calc(8 * var(--vw-base)) !important;
}

.m-3 {
  margin: calc(16 * var(--vw-base)) !important;
}

.mt-3 {
  margin-top: calc(16 * var(--vw-base)) !important;
}

.mb-3 {
  margin-bottom: calc(16 * var(--vw-base)) !important;
}

.ms-3 {
  margin-inline-start: calc(16 * var(--vw-base)) !important;
}

.me-3 {
  margin-inline-end: calc(16 * var(--vw-base)) !important;
}

.mx-3 {
  margin-inline: calc(16 * var(--vw-base)) !important;
}

.my-3 {
  margin-block: calc(16 * var(--vw-base)) !important;
}

.p-3 {
  padding: calc(16 * var(--vw-base)) !important;
}

.pt-3 {
  padding-top: calc(16 * var(--vw-base)) !important;
}

.pb-3 {
  padding-bottom: calc(16 * var(--vw-base)) !important;
}

.ps-3 {
  padding-inline-start: calc(16 * var(--vw-base)) !important;
}

.pe-3 {
  padding-inline-end: calc(16 * var(--vw-base)) !important;
}

.px-3 {
  padding-inline: calc(16 * var(--vw-base)) !important;
}

.py-3 {
  padding-block: calc(16 * var(--vw-base)) !important;
}

.gap-3 {
  gap: calc(16 * var(--vw-base)) !important;
}

.m-4 {
  margin: calc(24 * var(--vw-base)) !important;
}

.mt-4 {
  margin-top: calc(24 * var(--vw-base)) !important;
}

.mb-4 {
  margin-bottom: calc(24 * var(--vw-base)) !important;
}

.ms-4 {
  margin-inline-start: calc(24 * var(--vw-base)) !important;
}

.me-4 {
  margin-inline-end: calc(24 * var(--vw-base)) !important;
}

.mx-4 {
  margin-inline: calc(24 * var(--vw-base)) !important;
}

.my-4 {
  margin-block: calc(24 * var(--vw-base)) !important;
}

.p-4 {
  padding: calc(24 * var(--vw-base)) !important;
}

.pt-4 {
  padding-top: calc(24 * var(--vw-base)) !important;
}

.pb-4 {
  padding-bottom: calc(24 * var(--vw-base)) !important;
}

.ps-4 {
  padding-inline-start: calc(24 * var(--vw-base)) !important;
}

.pe-4 {
  padding-inline-end: calc(24 * var(--vw-base)) !important;
}

.px-4 {
  padding-inline: calc(24 * var(--vw-base)) !important;
}

.py-4 {
  padding-block: calc(24 * var(--vw-base)) !important;
}

.gap-4 {
  gap: calc(24 * var(--vw-base)) !important;
}

.m-5 {
  margin: calc(48 * var(--vw-base)) !important;
}

.mt-5 {
  margin-top: calc(48 * var(--vw-base)) !important;
}

.mb-5 {
  margin-bottom: calc(48 * var(--vw-base)) !important;
}

.ms-5 {
  margin-inline-start: calc(48 * var(--vw-base)) !important;
}

.me-5 {
  margin-inline-end: calc(48 * var(--vw-base)) !important;
}

.mx-5 {
  margin-inline: calc(48 * var(--vw-base)) !important;
}

.my-5 {
  margin-block: calc(48 * var(--vw-base)) !important;
}

.p-5 {
  padding: calc(48 * var(--vw-base)) !important;
}

.pt-5 {
  padding-top: calc(48 * var(--vw-base)) !important;
}

.pb-5 {
  padding-bottom: calc(48 * var(--vw-base)) !important;
}

.ps-5 {
  padding-inline-start: calc(48 * var(--vw-base)) !important;
}

.pe-5 {
  padding-inline-end: calc(48 * var(--vw-base)) !important;
}

.px-5 {
  padding-inline: calc(48 * var(--vw-base)) !important;
}

.py-5 {
  padding-block: calc(48 * var(--vw-base)) !important;
}

.gap-5 {
  gap: calc(48 * var(--vw-base)) !important;
}

@media (min-width: 992px) {
  .px-desktop-0 {
    padding-inline: 0 !important;
  }
  .pt-desktop-0 {
    padding-top: 0 !important;
  }
  .px-desktop-1 {
    padding-inline: calc(4 * var(--vw-base)) !important;
  }
  .pt-desktop-1 {
    padding-top: calc(4 * var(--vw-base)) !important;
  }
  .px-desktop-2 {
    padding-inline: calc(8 * var(--vw-base)) !important;
  }
  .pt-desktop-2 {
    padding-top: calc(8 * var(--vw-base)) !important;
  }
  .px-desktop-3 {
    padding-inline: calc(16 * var(--vw-base)) !important;
  }
  .pt-desktop-3 {
    padding-top: calc(16 * var(--vw-base)) !important;
  }
  .px-desktop-4 {
    padding-inline: calc(24 * var(--vw-base)) !important;
  }
  .pt-desktop-4 {
    padding-top: calc(24 * var(--vw-base)) !important;
  }
  .px-desktop-5 {
    padding-inline: calc(48 * var(--vw-base)) !important;
  }
  .pt-desktop-5 {
    padding-top: calc(48 * var(--vw-base)) !important;
  }
  .text-desktop-start {
    text-align: start !important;
  }
  .text-desktop-center {
    text-align: center !important;
  }
  .text-desktop-end {
    text-align: end !important;
  }
}
/* 人工／Legacy 元件已有 Desktop 基礎值，只需覆蓋 Mobile 時使用。
   Core Exporter 應優先輸出 Mobile base + 必要的 text-desktop-*。 */
@media (max-width: 991.98px) {
  .text-mobile-start {
    text-align: start !important;
  }
  .text-mobile-center {
    text-align: center !important;
  }
  .text-mobile-end {
    text-align: end !important;
  }
}
.border {
  border: 1px solid #dee2e6 !important;
}

.border-top {
  border-top: 1px solid #dee2e6 !important;
}

.border-bottom {
  border-bottom: 1px solid #dee2e6 !important;
}

.border-start {
  border-inline-start: 1px solid #dee2e6 !important;
}

.border-top-0 {
  border-top: 0 !important;
}

.border-primary {
  border-color: #6e8800 !important;
}

.border-secondary {
  border-color: #bea850 !important;
}

.border-2 {
  border-width: calc(2 * var(--vw-base)) !important;
}

.border-3 {
  border-width: calc(3 * var(--vw-base)) !important;
}

.border-4 {
  border-width: calc(4 * var(--vw-base)) !important;
}

.rounded {
  border-radius: calc(6 * var(--vw-base)) !important;
}

.rounded-1 {
  border-radius: calc(4 * var(--vw-base)) !important;
}

.rounded-top {
  border-start-start-radius: calc(6 * var(--vw-base)) !important;
  border-start-end-radius: calc(6 * var(--vw-base)) !important;
}

.rounded-bottom {
  border-end-start-radius: calc(6 * var(--vw-base)) !important;
  border-end-end-radius: calc(6 * var(--vw-base)) !important;
}

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: calc(8 * var(--vw-base));
  padding: calc(12 * var(--vw-base)) calc(32 * var(--vw-base));
  border: 1px solid transparent;
  color: #212529;
  background: transparent;
  font-size: calc(16 * var(--vw-base));
  line-height: 1.5;
  text-align: center;
  cursor: pointer;
  transition: color 0.15s ease, background-color 0.15s ease, border-color 0.15s ease;
}

.btn-sm {
  padding: calc(6 * var(--vw-base)) calc(16 * var(--vw-base));
  font-size: calc(14 * var(--vw-base));
}

.btn-primary {
  color: #fff;
  background: #6e8800;
  border-color: #6e8800;
}

.btn-primary:hover {
  background: #444f13;
  border-color: #444f13;
}

.btn-secondary {
  color: #fff;
  background: #bea850;
  border-color: #bea850;
}

.btn-secondary:hover {
  background: #a68915;
  border-color: #a68915;
}

.btn-gray {
  color: #fff;
  background: #888888;
  border-color: #888888;
}

.btn-gray:hover {
  background: #656565;
  border-color: #656565;
}

.btn-outline-primary {
  color: #6e8800;
  border-color: #6e8800;
}

.btn-outline-primary:hover {
  color: #fff;
  background: #6e8800;
}

.btn-outline-secondary {
  color: #bea850;
  border-color: #bea850;
}

.btn-outline-secondary:hover {
  color: #fff;
  background: #bea850;
}

.btn-outline-light {
  color: #fff;
  border-color: #f8f9fa;
}

.btn-outline-light:hover {
  color: #212529;
  background: #f8f9fa;
}

.alert {
  padding: calc(16 * var(--vw-base)) calc(24 * var(--vw-base));
  border: 1px solid transparent;
  border-radius: calc(6 * var(--vw-base));
}

.alert-warning {
  color: #664d03;
  background: #fff3cd;
  border-color: #ffecb5;
}

.alert-info {
  color: #055160;
  background: #cff4fc;
  border-color: #b6effb;
}

.badge {
  display: inline-block;
  padding: calc(4 * var(--vw-base)) calc(8 * var(--vw-base));
  font-size: 0.75em;
  line-height: 1;
}

.card {
  background: #fff;
  border: 1px solid #dee2e6;
  border-radius: calc(8 * var(--vw-base));
}

.card-body {
  padding: calc(24 * var(--vw-base));
}

.form-control, .form-select {
  display: block;
  width: 100%;
  padding: calc(12 * var(--vw-base)) calc(16 * var(--vw-base));
  border: 1px solid #ced4da;
  border-radius: 0;
  color: #212529;
  background: rgba(255, 255, 255, 0.596);
  font-size: calc(16 * var(--vw-base));
}

.form-control:focus, .form-select:focus {
  border-color: #6e8800;
  box-shadow: 0 0 calc(10 * var(--vw-base)) calc(3 * var(--vw-base)) rgba(110, 136, 0, 0.44);
}

.form-check {
  display: block;
  min-height: calc(24 * var(--vw-base));
  padding-inline-start: calc(24 * var(--vw-base));
}

.form-check-input {
  float: inline-start;
  width: calc(16 * var(--vw-base));
  height: calc(16 * var(--vw-base));
  margin: calc(4 * var(--vw-base)) 0 0 calc(-24 * var(--vw-base));
}

.form-check-input:checked {
  accent-color: #6e8800;
}

.form-check-inline {
  display: inline-block;
  margin-inline-end: calc(16 * var(--vw-base));
}

.form-floating {
  position: relative;
}

.form-floating > label {
  position: absolute;
  inset: 0;
  padding: calc(12 * var(--vw-base)) calc(16 * var(--vw-base));
  pointer-events: none;
}

.table th, .table td {
  padding: calc(8 * var(--vw-base));
  border-bottom: 1px solid #dee2e6;
  vertical-align: top;
}

.table-sm th, .table-sm td {
  padding: calc(4 * var(--vw-base));
}

.table-bordered th, .table-bordered td {
  border: 1px solid #dee2e6;
}

.table-light th {
  background: #f8f9fa;
}

.table-responsive {
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
}

.align-middle {
  vertical-align: middle !important;
}

.visually-hidden {
  position: absolute !important;
  width: 1px !important;
  height: 1px !important;
  padding: 0 !important;
  margin: -1px !important;
  overflow: hidden !important;
  clip: rect(0, 0, 0, 0) !important;
  white-space: nowrap !important;
  border: 0 !important;
}

@media (max-width: 991.98px) {
  body {
    font-size: calc(14.4 * var(--vw-base));
  }
  .row {
    --grid-gap-x: calc(16 * var(--vw-base));
  }
  .btn {
    padding: calc(10 * var(--vw-base)) calc(24 * var(--vw-base));
    font-size: calc(14 * var(--vw-base));
  }
  .btn-sm {
    padding: calc(6 * var(--vw-base)) calc(14 * var(--vw-base));
    font-size: calc(12 * var(--vw-base));
  }
  .alert {
    padding: calc(12 * var(--vw-base)) calc(16 * var(--vw-base));
  }
  .card-body {
    padding: calc(16 * var(--vw-base));
  }
  .form-control, .form-select {
    padding: calc(10 * var(--vw-base)) calc(14 * var(--vw-base));
    font-size: calc(14 * var(--vw-base));
  }
}
/* =========================================
  📐 Spacing Layout System v2

  規則：
  - .container        = 置中內容最大寬度
  - .content-px       = 非 container 內容的左右安全距離
  - .content-py       = 承接內容之容器的上下留白
  - .content-pt/pb    = 承接內容之容器的單側上下留白
  - .content-ps       = 手機雙側安全距離；桌機左側對齊版心，右側可貼邊
  - .content-pe       = 手機雙側安全距離；桌機右側對齊版心，左側可貼邊
  - .txt-p*           = 文字區塊內距，用於圖文版型的圖文距離
  - *--mobile-0       = 手機歸零，桌機恢復

  手機滿版用法：
  <section>
    <img>
    <div class="content-px content-py">文字</div>
  </section>
========================================= */
/* ─── Content Width ──────────────────────────────────────── */
.container {
  width: var(--container-max-width, 100%);
  max-width: none;
  padding-inline: 0;
}

.content-px {
  padding-inline: var(--content-px);
}

.content-px--mobile-0 {
  padding-inline: 0;
}
@media (min-width: 992px) {
  .content-px--mobile-0 {
    padding-inline: var(--content-px);
  }
}

/* Mobile 套用內容安全邊界，Desktop 歸零。
   Desktop 的最終水平邊界必須由 container、layout 或其他明確 owner 提供；
   本 utility 不保證 Desktop 安全邊界。 */
.content-px--desktop-0 {
  padding-inline: var(--content-px);
}
@media (min-width: 992px) {
  .content-px--desktop-0 {
    padding-inline: 0;
  }
}

.content-ps {
  padding-inline: var(--content-px);
}
@media (min-width: 992px) {
  .content-ps {
    padding-inline-end: 0;
  }
}

.content-ps--mobile-0 {
  padding-inline-start: 0;
}
@media (min-width: 992px) {
  .content-ps--mobile-0 {
    padding-inline-start: var(--content-px);
    padding-inline-end: 0;
  }
}

.content-pe {
  padding-inline: var(--content-px);
}
@media (min-width: 992px) {
  .content-pe {
    padding-inline-start: 0;
  }
}

.content-pe--mobile-0 {
  padding-inline-end: 0;
}
@media (min-width: 992px) {
  .content-pe--mobile-0 {
    padding-inline-start: 0;
    padding-inline-end: var(--content-px);
  }
}

.content-py {
  padding-block: var(--content-py);
}

.content-pt {
  padding-block-start: var(--content-py);
}

.content-pb {
  padding-block-end: var(--content-py);
}

.py-mobile-0 {
  padding-block: 0;
}
@media (min-width: 992px) {
  .py-mobile-0 {
    padding-block: var(--content-py);
  }
}

.pt-mobile-0 {
  padding-block-start: 0;
}
@media (min-width: 992px) {
  .pt-mobile-0 {
    padding-block-start: var(--content-py);
  }
}

.pb-mobile-0 {
  padding-block-end: 0;
}
@media (min-width: 992px) {
  .pb-mobile-0 {
    padding-block-end: var(--content-py);
  }
}

/* ─── Text Block Padding ─────────────────────────────────── */
.txt-px {
  padding-inline: var(--txt-px);
}

.txt-py {
  padding-block: var(--txt-py);
}

.txt-ps {
  padding-inline-start: var(--txt-px);
}

.txt-pe {
  padding-inline-end: var(--txt-px);
}

.txt-pt {
  padding-block-start: var(--txt-py);
}

.txt-pb {
  padding-block-end: var(--txt-py);
}

@media (min-width: 992px) {
  .txt-desktop-ps {
    padding-inline-start: var(--txt-px);
  }
}

@media (min-width: 992px) {
  .txt-desktop-px {
    padding-inline: var(--txt-px);
  }
}

@media (min-width: 992px) {
  .txt-desktop-py {
    padding-block: var(--txt-py);
  }
}

@media (min-width: 992px) {
  .txt-desktop-pe {
    padding-inline-end: var(--txt-px);
  }
}

@media (min-width: 992px) {
  .txt-desktop-pt {
    padding-block-start: var(--txt-py);
  }
}

@media (min-width: 992px) {
  .txt-desktop-pb {
    padding-block-end: var(--txt-py);
  }
}

/* =========================================
  DDWPS Layout Language

  HTML class describes intent:
  - section-* = content meaning
  - layout-*  = layout pattern
  - layout modes = stack / split / grid / absolute
  - *-wrap    = content object boundary (.txt-wrap / .img-wrap /
                .video-wrap): case hook, width, position and the
                whole-object Motion target live here
  - txt-heading / txt-content = the two text groups INSIDE .txt-wrap
  No shared visual-reorder helper exists any more: `.layout-desktop-reverse`
  was removed on 2026-09-15 (Phase 1R). A case that really needs a
  Desktop-only reverse writes `order` in its own owner SCSS; forms, steps,
  Grid collections and other order-sensitive content never reorder.

  Numeric values stay in CSS variables. A case configures a
  Layout's own variables (--layout-split-columns,
  --layout-split-columns-desktop, --layout-split-align,
  --layout-gap-x/y, --layout-grid-*) through an explicit owner
  class (`#pageXX .pageXX-main-layout { ... }`), never through a
  descendant selector that ends in the shared class
  (`#pageXX .layout-split { ... }` also hits every nested
  Layout inside that Section). Layout Phase 1A, Unified Contract
  §6.5.4. Layout Phase 1N (2026-09-15) renamed the canonical classes
  (see internal/migration-2026-09-15-layout-1N/RENAME-MAP.md); no alias
  for the pre-1N names is kept.
  Layout Phase 3 (2026-09-15, Gap isolation): `--layout-gap-x/y` on
  `.layout-stack`/`.layout-split` is now an instance token, reset at
  class level from the Theme default `--layout-default-gap-x/y` (same
  pattern `.layout-grid` already uses for `--layout-grid-gap-x/y`, and
  `_forms.scss` already uses to relay `--form-grid-gap-x/y` into it). A
  case overrides `--layout-gap-x/y` on the owner class of one Layout
  node; overriding `--layout-default-gap-x/y` changes the Theme default
  for every Layout under that scope instead. Neither an outer Stack/
  Split's instance override nor the Theme default leaks into a nested
  Stack/Split any more — every `.layout-stack`/`.layout-split` resets
  its own `--layout-gap-x/y` back to the (possibly locally overridden)
  Theme default. The single-value `--layout-gap` alias had zero
  consumers and is removed, matching
  DDWPS-THEME-VARIABLE-CONTRACT-v1.md §5.2, which already excludes a
  single-value `layout-gap` from the v1 core semantic variables.
  Only Mobile base and Desktop overrides are supported.
  .layout-stack / .layout-split / .layout-grid are Grid-based:
  never combine them with a display utility (.d-flex,
  .d-desktop-flex, .row, .section-v-center …) on the same node —
  the utility's `display` would silently replace `display: grid`.
========================================= */
.layout-split {
  --layout-split-columns: minmax(0, 1fr);
  --layout-split-columns-desktop: minmax(0, 1fr) minmax(0, 1fr);
  --layout-split-align: center;
  --layout-gap-x: var(--layout-default-gap-x);
  --layout-gap-y: var(--layout-default-gap-y);
  display: grid;
  grid-template-columns: var(--layout-split-columns);
  align-items: var(--layout-split-align);
  column-gap: var(--layout-gap-x);
  row-gap: var(--layout-gap-y);
}
@media (min-width: 992px) {
  .layout-split {
    grid-template-columns: var(--layout-split-columns-desktop);
  }
}

.layout-absolute {
  position: relative;
}

.layout-stack {
  --layout-gap-x: var(--layout-default-gap-x);
  --layout-gap-y: var(--layout-default-gap-y);
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  column-gap: var(--layout-gap-x);
  row-gap: var(--layout-gap-y);
}

/* Grid v1（DDWPS Unified Contract §6.5.4）。
   `.layout-grid` is the canonical repeat/span Grid system; legacy `.layout-gallery`/
   `.layout-cards` are removed — zero consumers in Starter/Contract/Skill/
   fixtures at removal time (see Skill CASE-BRIEF-style disclosure in
   ddwps-case-layout's version notes for other cases still on the old classes,
   unaffected since each case holds its own copied _layout.scss). */
.layout-grid {
  --layout-grid-columns: 1;
  --layout-grid-gap-x: 0;
  --layout-grid-gap-y: 0;
  display: grid;
  grid-template-columns: repeat(var(--layout-grid-columns), minmax(0, 1fr));
  column-gap: var(--layout-grid-gap-x);
  row-gap: var(--layout-grid-gap-y);
}

.layout-grid--columns-1 {
  --layout-grid-columns: 1;
}

.layout-grid--columns-2 {
  --layout-grid-columns: 2;
}

.layout-grid--columns-3 {
  --layout-grid-columns: 3;
}

.layout-grid--columns-4 {
  --layout-grid-columns: 4;
}

.layout-grid--columns-5 {
  --layout-grid-columns: 5;
}

.layout-grid--columns-6 {
  --layout-grid-columns: 6;
}

.layout-grid--columns-7 {
  --layout-grid-columns: 7;
}

.layout-grid--columns-8 {
  --layout-grid-columns: 8;
}

.layout-grid--columns-9 {
  --layout-grid-columns: 9;
}

.layout-grid--columns-10 {
  --layout-grid-columns: 10;
}

.layout-grid--columns-11 {
  --layout-grid-columns: 11;
}

.layout-grid--columns-12 {
  --layout-grid-columns: 12;
}

@media (min-width: 992px) {
  .layout-grid--desktop-columns-1 {
    --layout-grid-columns: 1;
  }
  .layout-grid--desktop-columns-2 {
    --layout-grid-columns: 2;
  }
  .layout-grid--desktop-columns-3 {
    --layout-grid-columns: 3;
  }
  .layout-grid--desktop-columns-4 {
    --layout-grid-columns: 4;
  }
  .layout-grid--desktop-columns-5 {
    --layout-grid-columns: 5;
  }
  .layout-grid--desktop-columns-6 {
    --layout-grid-columns: 6;
  }
  .layout-grid--desktop-columns-7 {
    --layout-grid-columns: 7;
  }
  .layout-grid--desktop-columns-8 {
    --layout-grid-columns: 8;
  }
  .layout-grid--desktop-columns-9 {
    --layout-grid-columns: 9;
  }
  .layout-grid--desktop-columns-10 {
    --layout-grid-columns: 10;
  }
  .layout-grid--desktop-columns-11 {
    --layout-grid-columns: 11;
  }
  .layout-grid--desktop-columns-12 {
    --layout-grid-columns: 12;
  }
}
.layout-grid--tracks-12 {
  --layout-grid-columns: 12;
}

.layout-grid > .layout-span-1 {
  grid-column: span 1;
}

.layout-grid > .layout-span-2 {
  grid-column: span 2;
}

.layout-grid > .layout-span-3 {
  grid-column: span 3;
}

.layout-grid > .layout-span-4 {
  grid-column: span 4;
}

.layout-grid > .layout-span-5 {
  grid-column: span 5;
}

.layout-grid > .layout-span-6 {
  grid-column: span 6;
}

.layout-grid > .layout-span-7 {
  grid-column: span 7;
}

.layout-grid > .layout-span-8 {
  grid-column: span 8;
}

.layout-grid > .layout-span-9 {
  grid-column: span 9;
}

.layout-grid > .layout-span-10 {
  grid-column: span 10;
}

.layout-grid > .layout-span-11 {
  grid-column: span 11;
}

.layout-grid > .layout-span-12 {
  grid-column: span 12;
}

@media (min-width: 992px) {
  .layout-grid > .layout-span-desktop-1 {
    grid-column: span 1;
  }
  .layout-grid > .layout-span-desktop-2 {
    grid-column: span 2;
  }
  .layout-grid > .layout-span-desktop-3 {
    grid-column: span 3;
  }
  .layout-grid > .layout-span-desktop-4 {
    grid-column: span 4;
  }
  .layout-grid > .layout-span-desktop-5 {
    grid-column: span 5;
  }
  .layout-grid > .layout-span-desktop-6 {
    grid-column: span 6;
  }
  .layout-grid > .layout-span-desktop-7 {
    grid-column: span 7;
  }
  .layout-grid > .layout-span-desktop-8 {
    grid-column: span 8;
  }
  .layout-grid > .layout-span-desktop-9 {
    grid-column: span 9;
  }
  .layout-grid > .layout-span-desktop-10 {
    grid-column: span 10;
  }
  .layout-grid > .layout-span-desktop-11 {
    grid-column: span 11;
  }
  .layout-grid > .layout-span-desktop-12 {
    grid-column: span 12;
  }
}
/* Layout Phase 4（mobileFlatten，2026-09-23，Unified Contract §6.5.4）：
   `data-layout-flatten="mobile"` is a pure-CSS responsive setting on an
   EXISTING Layout family node (.layout-stack / .layout-split / .layout-grid),
   not a JS hook and not a fourth Layout family. Mobile: the wrapper's own box
   disappears (`display: contents`) and its direct children become direct
   participants of whatever Grid governs its own parent, exactly as if the
   wrapper were never there in the DOM — the DOM itself is untouched. Desktop:
   `display: grid` is restored and the wrapper's own Layout family class
   (tracks / gap / align) applies normally again.

   Only safe when the wrapper's own PARENT resolves to exactly one effective
   grid-flow column at the breakpoint where this attribute is active — Grid's
   row-major auto-placement algorithm only guarantees each flattened child its
   own row when there is nowhere else for the next item to go. A case author
   is responsible for that precondition (Mobile default column count on
   .layout-stack/.layout-split/.layout-grid already satisfies it; deliberately
   opting a parent into 2+ Mobile columns and flattening a child inside it is
   unsupported in this first version — see the Contract section for the full
   list of unsupported combinations, audited by
   scripts/audit_grid_structure.mjs and scripts/audit_layout_css.mjs).

   Compound selector (Layout family class + attribute selector), not "declare
   this rule after the Layout family blocks": both are single-selector
   (0,1,0), so the compound (0,2,0) always wins regardless of where in this
   file it is written — reordering this file later can never silently break
   Mobile Flatten. */
.layout-stack[data-layout-flatten=mobile],
.layout-split[data-layout-flatten=mobile],
.layout-grid[data-layout-flatten=mobile] {
  display: contents;
}
@media (min-width: 992px) {
  .layout-stack[data-layout-flatten=mobile],
  .layout-split[data-layout-flatten=mobile],
  .layout-grid[data-layout-flatten=mobile] {
    display: grid;
  }
}

.txt,
.media {
  min-width: 0;
}

/* Text object boundary（Unified Contract §4.5「文字物件」，2026-09-15 恢復為
   canonical）。`.txt-wrap` 是整個文字物件的最外層邊界，與 `.img-wrap`／
   `.video-wrap` 同層級：案件定位 hook、整體寬度、位置與整組 Motion 都掛在
   這裡；裡面只放 `.txt-heading`（標題群組）與／或 `.txt-content`（內文群組）。
   共用層只給寬度能力，不給字級、gap 或對齊。 */
.txt-wrap {
  width: 100%;
  max-width: var(--txt-max-width, none);
}

/* legacy-only：舊版 `.txt-wrap > .txt-title / .txt-body` 的子結構。只為既有
   案件相容保留，新輸出不得使用（改用 .txt-heading / .txt-content）。 */
.txt-title {
  margin: 0 0 var(--txt-title-gap);
}
.txt-title:last-child {
  margin-bottom: 0;
}

.txt-body {
  display: grid;
  gap: var(--txt-body-gap);
}
.txt-body p {
  margin: 0;
}

/* DDWPS Unified Contract §4.5/§4.5.2 canonical text groups — always direct
   children of `.txt-wrap`. Structure-only reset — no font-family/size/color/
   gap here. Typography is `.text-style-*` (see `_typography.scss`, landed
   2026-09-16 — apply it on the same node as the `__*` role class, e.g.
   `<h2 class="txt-heading__title text-style-heading-zh">`); case/Theme
   spacing owns the gap between children per §3.3. */
.txt-heading,
.txt-content {
  margin: 0;
}

.txt-heading__eyebrow,
.txt-heading__title,
.txt-heading__subtitle,
.txt-heading__description {
  margin: 0;
}

.media-slider,
.media-video,
.media-map {
  width: 100%;
}

/*
  🔠 Body：全站 typography 的**唯一**權威來源。
  值全部讀 --font-body-*（定義於 `_root.scss`），案件只覆寫 Token，
  不得在別處再宣告一次 body 的 font-family / font-size。
*/
body {
  font-family: var(--font-body-family);
  font-weight: var(--font-body-weight);
  font-size: var(--font-body-size);
  line-height: var(--font-body-line-height);
  letter-spacing: var(--font-body-letter-spacing);
}
@media (max-width: 991.98px) {
  body {
    font-size: var(--font-body-size-mobile);
  }
}

/* ========================
  🔤 Text Style（DDWPS-UNIFIED-WEBSITE-CONTRACT-v1.md §3.3、
  DDWPS-THEME-VARIABLE-CONTRACT-v1.md §6-7，2026-09-16 落地）

  這是文字外觀的唯一正式管道。舊版 .page-*／.slogan-wrap／
  .page-slogan-* 家族（2026-09-16 曾短暫降為 legacy-only）已於
  internal/migration-2026-09-16-typography-legacy-removal/ 這輪確認
  零消費端後整批移除，CSS 不存在、沒有 alias，新舊案件一律只用這裡的
  .text-style-*；完整移除清單見該資料夾的 MIGRATION-REPORT.md。每個
  .text-style-* 只管
  font-family／font-size／font-weight／line-height／letter-spacing／
  text-transform；顏色走 Color Variable，對齊／位置／外部間距走
  Layout 或 Node，一律不寫在這裡（Unified Contract §3.3.2「四種責任
  必須分離」）。

  Mobile 是 base、Desktop 用 min-width 覆寫 --text-font-size，與 Kit
  其餘 Token（--content-px、--layout-default-gap-x 等）的斷點方向一致。
  每個 Style 把自己的 metrics 攤成 --text-* 自訂屬性再消費，案件需要
  覆寫單一 metric（最常見是字級）時，直接在 owner class 覆寫對應的
  --text-* 屬性，不必整組重寫、也不必另建案件字級 class。

  下列數字是 Starter 起始值，逐字沿用舊 .page-* 的既有實作數值
  （2026-09-16 Typography 唯讀盤點的盤點結果），不是任何案件的設計稿
  量測結果；原本已有明確 line-height 的三個 Style（display-l-en／
  display-l-zh／heading-zh）維持原數值，其餘原本沒宣告 line-height、
  實際靠繼承拿到 body 1.66 的 Style，這裡把 1.66 明確攤平成自己的
  起始值（不再依賴繼承鏈），同樣需要案件依實際設計稿覆寫。
======================== */
.text-style-display-l-en {
  --text-font-family: var(--font-en-serif);
  --text-font-size: calc(45.3 * var(--vw-base));
  --text-font-weight: 300;
  --text-line-height: 1;
  --text-letter-spacing: normal;
  --text-transform: uppercase;
  font-family: var(--text-font-family);
  font-size: var(--text-font-size);
  font-weight: var(--text-font-weight);
  line-height: var(--text-line-height);
  letter-spacing: var(--text-letter-spacing);
  text-transform: var(--text-transform);
}
@media (min-width: 992px) {
  .text-style-display-l-en {
    --text-font-size: calc(72 * var(--vw-base));
  }
}

.text-style-display-l-zh {
  --text-font-family: var(--font-zh-serif);
  --text-font-size: calc(30.2 * var(--vw-base));
  --text-font-weight: 400;
  --text-line-height: 1.8;
  --text-letter-spacing: 0.3rem;
  --text-transform: none;
  font-family: var(--text-font-family);
  font-size: var(--text-font-size);
  font-weight: var(--text-font-weight);
  line-height: var(--text-line-height);
  letter-spacing: var(--text-letter-spacing);
  text-transform: var(--text-transform);
}
@media (min-width: 992px) {
  .text-style-display-l-zh {
    --text-font-size: calc(48 * var(--vw-base));
  }
}

.text-style-display-m-zh {
  --text-font-family: var(--font-zh-serif);
  --text-font-size: calc(23.2 * var(--vw-base));
  --text-font-weight: 400;
  --text-line-height: 1.66;
  --text-letter-spacing: normal;
  --text-transform: none;
  font-family: var(--text-font-family);
  font-size: var(--text-font-size);
  font-weight: var(--text-font-weight);
  line-height: var(--text-line-height);
  letter-spacing: var(--text-letter-spacing);
  text-transform: var(--text-transform);
}
@media (min-width: 992px) {
  .text-style-display-m-zh {
    --text-font-size: calc(38.4 * var(--vw-base));
  }
}

.text-style-display-s-zh {
  --text-font-family: var(--font-zh-sans);
  --text-font-size: calc(17.6 * var(--vw-base));
  --text-font-weight: 400;
  --text-line-height: 1.66;
  --text-letter-spacing: normal;
  --text-transform: none;
  font-family: var(--text-font-family);
  font-size: var(--text-font-size);
  font-weight: var(--text-font-weight);
  line-height: var(--text-line-height);
  letter-spacing: var(--text-letter-spacing);
  text-transform: var(--text-transform);
}
@media (min-width: 992px) {
  .text-style-display-s-zh {
    --text-font-size: calc(28.8 * var(--vw-base));
  }
}

.text-style-heading-zh {
  --text-font-family: var(--font-zh-serif);
  --text-font-size: calc(22.5 * var(--vw-base));
  --text-font-weight: 400;
  --text-line-height: 1.8;
  --text-letter-spacing: normal;
  --text-transform: none;
  font-family: var(--text-font-family);
  font-size: var(--text-font-size);
  font-weight: var(--text-font-weight);
  line-height: var(--text-line-height);
  letter-spacing: var(--text-letter-spacing);
  text-transform: var(--text-transform);
}
@media (min-width: 992px) {
  .text-style-heading-zh {
    --text-font-size: calc(32 * var(--vw-base));
  }
}

.text-style-subheading-zh {
  --text-font-family: var(--font-zh-serif);
  --text-font-size: calc(23.8 * var(--vw-base));
  --text-font-weight: 400;
  --text-line-height: 1.66;
  --text-letter-spacing: normal;
  --text-transform: none;
  font-family: var(--text-font-family);
  font-size: var(--text-font-size);
  font-weight: var(--text-font-weight);
  line-height: var(--text-line-height);
  letter-spacing: var(--text-letter-spacing);
  text-transform: var(--text-transform);
}
@media (min-width: 992px) {
  .text-style-subheading-zh {
    --text-font-size: calc(40 * var(--vw-base));
  }
}

.text-style-subheading-en {
  --text-font-family: var(--font-en-sans);
  --text-font-size: calc(19.3 * var(--vw-base));
  --text-font-weight: 400;
  --text-line-height: 1.66;
  --text-letter-spacing: normal;
  --text-transform: none;
  font-family: var(--text-font-family);
  font-size: var(--text-font-size);
  font-weight: var(--text-font-weight);
  line-height: var(--text-line-height);
  letter-spacing: var(--text-letter-spacing);
  text-transform: var(--text-transform);
}
@media (min-width: 992px) {
  .text-style-subheading-en {
    --text-font-size: calc(24 * var(--vw-base));
  }
}

.text-style-label-zh {
  --text-font-family: var(--font-zh-sans);
  --text-font-size: calc(10.8 * var(--vw-base));
  --text-font-weight: 400;
  --text-line-height: 1.66;
  --text-letter-spacing: normal;
  --text-transform: none;
  font-family: var(--text-font-family);
  font-size: var(--text-font-size);
  font-weight: var(--text-font-weight);
  line-height: var(--text-line-height);
  letter-spacing: var(--text-letter-spacing);
  text-transform: var(--text-transform);
}
@media (min-width: 992px) {
  .text-style-label-zh {
    --text-font-size: calc(12 * var(--vw-base));
  }
}

.text-style-caption-zh {
  --text-font-family: var(--font-zh-sans);
  --text-font-size: calc(10.8 * var(--vw-base));
  --text-font-weight: 400;
  --text-line-height: 1.66;
  --text-letter-spacing: normal;
  --text-transform: none;
  font-family: var(--text-font-family);
  font-size: var(--text-font-size);
  font-weight: var(--text-font-weight);
  line-height: var(--text-line-height);
  letter-spacing: var(--text-letter-spacing);
  text-transform: var(--text-transform);
}
@media (min-width: 992px) {
  .text-style-caption-zh {
    --text-font-size: calc(12 * var(--vw-base));
  }
}

.text-style-label-en {
  --text-font-family: var(--font-en-sans);
  --text-font-size: calc(10.8 * var(--vw-base));
  --text-font-weight: 400;
  --text-line-height: 1.66;
  --text-letter-spacing: 0.08em;
  --text-transform: uppercase;
  font-family: var(--text-font-family);
  font-size: var(--text-font-size);
  font-weight: var(--text-font-weight);
  line-height: var(--text-line-height);
  letter-spacing: var(--text-letter-spacing);
  text-transform: var(--text-transform);
}
@media (min-width: 992px) {
  .text-style-label-en {
    --text-font-size: calc(12 * var(--vw-base));
  }
}

.text-style-body-zh {
  --text-font-family: var(--font-zh-sans);
  --text-font-size: calc(14.4 * var(--vw-base));
  --text-font-weight: 400;
  --text-line-height: 1.66;
  --text-letter-spacing: 0.04em;
  --text-transform: none;
  font-family: var(--text-font-family);
  font-size: var(--text-font-size);
  font-weight: var(--text-font-weight);
  line-height: var(--text-line-height);
  letter-spacing: var(--text-letter-spacing);
  text-transform: var(--text-transform);
}
@media (min-width: 992px) {
  .text-style-body-zh {
    --text-font-size: calc(16 * var(--vw-base));
  }
}

/* ========================
  🚫 已移除（2026-09-16，見 internal/migration-2026-09-16-typography-legacy-removal/）
  .page-en-title／.page-en-title__gradient／.page-zh-title／
  .page-zh-title__gradient／.page-zh-subtitle／.page-en-subtitle／
  .page-zh-label／.page-en-label／.page-caption／.slogan-wrap／
  .page-slogan-heading1/2/3／.page-slogan-label 已整批移除，CSS 不存在、
  沒有 alias。唯讀盤點確認全 Kit（含 Guide、fixtures、Motion／JS）零消費
  端後才移除；既有外部案件不在此範圍，本輪未觸碰任何案件檔案。
  對照：字級一律改用上方的 .text-style-*；Slogan 容器改用
  .txt-heading.txt-heading--slogan。完整清單見該資料夾的
  MIGRATION-REPORT.md，舊名稱→新名稱歷史對照仍可查
  internal/migration-2026-09-16-typography-text-style/RENAME-MAP.md。
======================== */
/* ========================
  ✨ Text Decoration Utilities
======================== */
/* 文字左右對齊*/
.text-justify {
  text-align: justify;
  text-justify: inter-ideograph;
  word-break: normal;
  overflow-wrap: break-word;
}

@media (min-width: 992px) {
  .text-desktop-justify {
    text-align: justify !important;
    text-justify: inter-ideograph;
    word-break: normal;
    overflow-wrap: break-word;
  }
}

/* 最後一行對齊，搭配 .text-justify / .text-desktop-justify 使用 */
.text-last-start {
  text-align-last: start;
}

.text-last-center {
  text-align-last: center;
}

.text-last-end {
  text-align-last: end;
}

.text-last-justify {
  text-align-last: justify;
}

@media (min-width: 992px) {
  .text-last-desktop-start {
    text-align-last: start;
  }
}

@media (min-width: 992px) {
  .text-last-desktop-center {
    text-align-last: center;
  }
}

@media (min-width: 992px) {
  .text-last-desktop-end {
    text-align-last: end;
  }
}

@media (min-width: 992px) {
  .text-last-desktop-justify {
    text-align-last: justify;
  }
}

/* ========================
  🈶 Typography Feature Utilities（CJK 排版特性）
  只切換 OpenType feature，不含字型、字級、行高或對齊，
  因此不是 Text Style，也不是元件；屬於節點層的排版特性 utility。
  斷點差異一律寫在 class 名稱上：base 為 Mobile，Desktop 用 text-desktop-* 覆寫，
  不得把 media query 藏進沒有斷點名稱的 class。
======================== */
/* CJK 約物緊縮：等同 Illustrator 的「標點擠壓（約物半形）」 */
.text-cjk-compact {
  font-feature-settings: "halt";
}

/* Desktop 還原正常約物寬度 */
@media (min-width: 992px) {
  .text-desktop-cjk-normal {
    font-feature-settings: normal;
  }
}

/* ========================
  🔤 Font System
======================== */
.font-zh-sans {
  font-family: var(--font-zh-sans);
}

.font-zh-serif {
  font-family: var(--font-zh-serif);
}

.font-en-sans {
  font-family: var(--font-en-sans);
}

.font-en-serif {
  font-family: var(--font-en-serif);
}

/*
  已移除（2026-09-16，見 internal/migration-2026-09-16-typography-legacy-removal/）：
  原本這裡有一條只為 legacy .txt-title.text-center 結構搭配已刪除的
  .page-en-title／.page-zh-title／.page-zh-subtitle 服務的 Mobile 置中規則。
  .txt-title 本身早在 2026-09-15 就已是 legacy-only（canonical 是
  .txt-heading／.txt-content），三個目標 class 這輪也已整批移除，
  這條規則失去存在意義，一併清除，不留孤兒規則。
*/
/* ========================
  🎞 Plugins
======================== */
/* fancybox */
.fancybox-navigation {
  height: 100vh;
}

.img-lightbox {
  display: block;
  height: 100%;
  cursor: zoom-in;
}

/* swiper */
.swiper-button-next,
.swiper-button-prev {
  color: #6e8800;
}

.swiper-pagination-bullet-active {
  background: #6e8800;
}

.swiper-pagination-bullet {
  background: #fff;
}
.swiper-pagination-bullet-active {
  background: #6e8800;
}

/* DDWPS media carousel defaults.
   Third-party compatibility belongs in _vendors.scss; component appearance
   belongs here and may be overridden by a scoped #pageXX .media-slider rule. */
.media-slider {
  --swiper-navigation-color: #ffffff;
  --swiper-pagination-color: #808080;
  --swiper-pagination-bullet-inactive-color: #808080;
  --swiper-pagination-bullet-inactive-opacity: 0.45;
}
.media-slider .swiper-button-prev,
.media-slider .swiper-button-next {
  color: var(--swiper-navigation-color);
}
.media-slider .swiper-pagination-bullet {
  background: var(--swiper-pagination-bullet-inactive-color);
  opacity: var(--swiper-pagination-bullet-inactive-opacity);
}
.media-slider .swiper-pagination-bullet-active {
  background: var(--swiper-pagination-color);
  opacity: 1;
}

/* ==========================================================================
  Form Structure v1（DDWPS-FORM-CONTRACT-v1.md §4.2，2026-09-14 定案）

  .contact-form 是唯一 canonical 表單元件根 class。這裡只負責 Structure：
  HTML 語意、class、欄位排列、外觀模式。Provider（action／formId／欄位
  name）與 Runtime（驗證、送出狀態、Fancybox、reCAPTCHA 互動）是分開的責任，
  不在此檔案。欄位排列全部交給 Grid v1（`_layout.scss` 的 `.layout-grid`），
  這裡不用 margin 排欄位。

  所有規則 scope 在 `.contact-form` 之下，不改動 `_foundation.scss` 既有的
  裸 `.form-control`／`.form-select` 預設（那是給未套用 `.contact-form` 情境
  的泛用 fallback，兩者不互相競爭：`.contact-form` 內的 specificity 更高）。

  既有案件的 `.page05-form`／`.reserve-form` 等自創表單根維持相容，不因為
  這裡新增 `.contact-form` 就被取代或自動遷移。
========================================================================== */
.contact-form {
  display: block;
}

.contact-form__note {
  margin: 0 0 var(--form-grid-gap-y);
  color: var(--form-helper-color);
  font-size: var(--form-control-font-size);
}

/* Grid gap 必須分別轉接到這兩個各自獨立的 .layout-grid 實例——Grid v1 規定
   每個 .layout-grid 自己重新宣告 gap，不繼承外層，所以不能只設一次。 */
.contact-form__grid,
.contact-form__verify {
  --layout-grid-gap-x: var(--form-grid-gap-x);
  --layout-grid-gap-y: var(--form-grid-gap-y);
}

.contact-form__grid {
  margin-block-end: var(--form-grid-gap-y);
}

.contact-form__field {
  display: block;
}

.contact-form__label {
  display: block;
  margin-block-end: var(--form-label-gap);
  color: var(--form-label-color);
  font-size: var(--form-label-font-size);
}

.contact-form__required {
  color: var(--form-error-color);
}

.contact-form .form-control,
.contact-form .form-select {
  display: block;
  width: 100%;
  height: var(--form-control-height);
  padding-inline: var(--form-control-padding-x);
  padding-block: var(--form-control-padding-y);
  color: var(--form-control-color);
  background: var(--form-control-background);
  border-style: solid;
  border-color: var(--form-control-border-color);
  border-width: var(--form-control-border-width);
  border-radius: var(--form-control-radius);
  line-height: var(--form-control-line-height);
  font-size: var(--form-control-font-size);
}
@media (max-width: 991.98px) {
  .contact-form .form-control,
  .contact-form .form-select {
    font-size: max(16px, var(--form-control-font-size));
  }
}
.contact-form .form-control::placeholder,
.contact-form .form-select::placeholder {
  color: var(--form-control-placeholder-color);
}
.contact-form .form-control:focus,
.contact-form .form-select:focus {
  border-color: var(--form-control-focus-color);
  box-shadow: var(--form-control-focus-shadow);
}
.contact-form .form-control:focus-visible,
.contact-form .form-select:focus-visible {
  outline: none;
}
.contact-form .form-control.is-invalid,
.contact-form .form-select.is-invalid {
  border-color: var(--form-error-color);
}

.contact-form textarea.form-control {
  height: auto;
}

/* ==========================================================================
  Floating label（`.contact-form--floating`，§4.2.3）。

  真正的浮動行為，不是只把 label 疊在上面就結束，且不是所有控制項型別都用
  同一套切換邏輯——已逐型別實測（Chromium／Playwright；無法在本環境安裝
  WebKit／Firefox 交叉驗證，跨瀏覽器一致性見下方「固定浮起」分類理由）：

  - **一般型別（.form-floating--auto，靠 :placeholder-shown 判斷）**：
    `text`／`email`／`tel`／`<textarea>`。空值＋未 focus 時 label 疊在輸入區
    （視覺上像 placeholder）；focus 或已有值時 label 縮小上移，露出下方輸入
    內容、不遮住它。這要求 `placeholder` 是與 label 文字一致的真實值
    （canonical 範例本來就如此），不是用單一空白字元「騙」CSS。
  - **固定浮起型別（.form-floating--fixed，不判斷 :placeholder-shown，
    label 永遠在上緣小字狀態）**：
    - `<select>`：原生一定顯示某個 option，沒有真正「空」的視覺狀態。
    - `date`／`time`：原生格式提示與挑選 UI 不是 CSS `placeholder`，
      `:placeholder-shown` 不可靠，且固定不動的 label 才不會遮住原生內容。
    - `number`：Chromium 單一引擎測試下 `:placeholder-shown` 可正常切換
      （含鍵盤／原生 spinner 互動），但本環境無法交叉驗證 Safari／Firefox，
      number 輸入的原生 spinner 與 :placeholder-shown 搭配又是已知的跨瀏覽器
      不穩定點；依「不能穩定判斷就列為固定浮起」的原則保守處理，不採用一般
      切換邏輯。
  - **禁止使用 Floating 的型別**：`checkbox`／`radio`／`file`／`range`／
    `color`——這些型別的原生控制項本身就不是「文字內容」，硬套浮動 label
    語意不通；下面另外用選擇器讓誤用時視覺上明顯失效（label 不會浮起、貼著
    控制項），實際攔截交給 `audit_form_structure.mjs`。
========================================================================== */
.contact-form .form-floating {
  position: relative;
}
.contact-form .form-floating > .form-control,
.contact-form .form-floating > .form-select {
  height: auto;
  min-height: var(--form-control-height);
  padding-block-start: calc(var(--form-control-padding-y) * 1.8);
  padding-block-end: calc(var(--form-control-padding-y) * 0.6);
}
.contact-form .form-floating > label {
  position: absolute;
  inset-block-start: 0;
  inset-inline-start: 0;
  width: 100%;
  height: 100%;
  padding-inline: var(--form-control-padding-x);
  padding-block: var(--form-control-padding-y);
  overflow: hidden;
  color: var(--form-control-placeholder-color);
  font-size: var(--form-control-font-size);
  text-overflow: ellipsis;
  white-space: nowrap;
  pointer-events: none;
  transform-origin: 0 0;
  transition: transform 0.1s ease-in-out, color 0.1s ease-in-out, font-size 0.1s ease-in-out;
}
@media (max-width: 991.98px) {
  .contact-form .form-floating > label {
    font-size: max(16px, var(--form-control-font-size));
  }
}
.contact-form .form-floating > input[type=text]::placeholder {
  color: transparent;
}
.contact-form .form-floating > input[type=email]::placeholder {
  color: transparent;
}
.contact-form .form-floating > input[type=tel]::placeholder {
  color: transparent;
}
.contact-form .form-floating > textarea.form-control::placeholder {
  color: transparent;
}
.contact-form .form-floating > .form-select ~ label, .contact-form .form-floating > input[type=date] ~ label, .contact-form .form-floating > input[type=time] ~ label, .contact-form .form-floating > input[type=number] ~ label, .contact-form .form-floating > input[type=text]:focus ~ label, .contact-form .form-floating > input[type=text]:not(:placeholder-shown) ~ label, .contact-form .form-floating > input[type=email]:focus ~ label, .contact-form .form-floating > input[type=email]:not(:placeholder-shown) ~ label, .contact-form .form-floating > input[type=tel]:focus ~ label, .contact-form .form-floating > input[type=tel]:not(:placeholder-shown) ~ label,
.contact-form .form-floating > textarea.form-control:focus ~ label,
.contact-form .form-floating > textarea.form-control:not(:placeholder-shown) ~ label {
  color: var(--form-label-color);
  font-size: var(--form-label-font-size);
  transform: translateY(calc(-1 * (var(--form-control-padding-y) + var(--form-label-font-size) * 0.6)));
}
.contact-form .form-floating > input[type=checkbox] ~ label,
.contact-form .form-floating > input[type=radio] ~ label,
.contact-form .form-floating > input[type=file] ~ label,
.contact-form .form-floating > input[type=range] ~ label,
.contact-form .form-floating > input[type=color] ~ label {
  position: static;
  transform: none;
  pointer-events: auto;
}

.contact-form__helper {
  margin: var(--form-label-gap) 0 0;
  color: var(--form-helper-color);
  font-size: var(--form-label-font-size);
}

.contact-form__error {
  margin: var(--form-label-gap) 0 0;
  color: var(--form-error-color);
  font-size: var(--form-label-font-size);
}

.contact-form__group {
  margin: 0;
  padding: 0;
  border: 0;
}

.contact-form__legend {
  display: block;
  width: 100%;
  margin-block-end: var(--form-label-gap);
  padding: 0;
  color: var(--form-label-color);
  font-size: var(--form-label-font-size);
}

.contact-form__options {
  display: flex;
  flex-wrap: wrap;
  gap: var(--form-grid-gap-y) var(--form-grid-gap-x);
}

/* reCAPTCHA v2 一般尺寸 Checkbox 專用縮放結構（§4.2.8）。304×78 是 Google
   widget 在 scale:1 時的原生尺寸，不是所有驗證模式的固定值；v2 invisible／
   v3 沒有固定版面尺寸，不使用這個 class。 */
.contact-form__captcha-scale {
  width: calc(304px * var(--form-recaptcha-scale));
  height: calc(78px * var(--form-recaptcha-scale));
  overflow: hidden;
}
.contact-form__captcha-scale .g-recaptcha {
  transform: scale(var(--form-recaptcha-scale));
  transform-origin: 0 0;
}

.contact-form__consent {
  color: var(--form-label-color);
  font-size: var(--form-label-font-size);
}

.contact-form__consent-title,
.contact-form__disclaimer {
  margin: 0;
}

.contact-form__consent-list {
  margin: var(--form-label-gap) 0;
  padding-inline-start: 1.4em;
}

/* 政策觸發按鈕是 checkbox <label> 的手足元素，不巢狀在裡面（§4.2.9）。 */
.contact-form__agree {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  column-gap: var(--form-label-gap);
  row-gap: 0;
  margin-block-start: var(--form-grid-gap-y);
}

.contact-form__policy-trigger {
  padding: 0;
  border: 0;
  background: none;
  color: var(--form-control-focus-color);
  font: inherit;
  text-decoration: underline;
  cursor: pointer;
}

.contact-form__submit {
  display: block;
  width: 100%;
  height: var(--form-submit-height);
  margin-block-start: var(--form-grid-gap-y);
  border: 0;
  border-radius: var(--form-submit-radius);
  background: var(--form-submit-background);
  color: var(--form-submit-color);
  font-size: var(--form-control-font-size);
  cursor: pointer;
}

/* ==========================================================================
  外觀三軸（§4.2.6）：Label 模式／控制項邊框／控制項底色。
  三軸互相獨立，只切換 Token 或必要的結構差異；不新增第四個維度的 modifier，
  圓角、顏色、高度、padding、字級一律交給上面的 Form Token 控制。
  `--standard` 與 `--control-outline` 是隱性預設（沿用 Token 原值），不需要
  額外規則；`--floating` 靠 `.form-floating` 既有結構（`_foundation.scss`）
  搭配上面 `.contact-form .form-floating > label` 的 Token 化樣式。
========================================================================== */
.contact-form--control-underline .form-control,
.contact-form--control-underline .form-select {
  border-width: 0 0 var(--form-control-border-width) 0;
  border-radius: 0;
  background: transparent;
}

.contact-form--control-borderless .form-control,
.contact-form--control-borderless .form-select {
  border-width: 0;
}
.contact-form--control-borderless .form-control:focus-visible,
.contact-form--control-borderless .form-select:focus-visible {
  outline: var(--focus-ring-width) solid var(--focus-ring-color);
  outline-offset: var(--focus-ring-offset);
}

.contact-form--surface-filled {
  --form-control-background: var(--color-background-surface);
}

.contact-form--surface-translucent {
  --form-control-background: var(--form-control-background-translucent);
}

.contact-form--surface-transparent {
  --form-control-background: transparent;
}

/* ========================
  📐 Section
======================== */
/* Exporter 對所有 Section 輸出的穩定結構 class；
   不以 HTML tag 或 pageXX 流水號代替結構身分。 */
.section {
  width: 100%;
}

/* 2026-09-15 移除共用首屏／高度工具（.section-screen、.is-fullscreen、
   .section-v-center、.section-v-between）：沒有正式 canonical consumer。
   Section 的高度、aspect-ratio、垂直排列一律寫在案件 owner SCSS，例如
   #page01.section--hero { aspect-ratio: 16 / 9; display: grid; align-items: end; }。 */
/* ========================
  🖼 Image
======================== */
/*
  Canonical 結構（2026-09-13 起，見 DDWPS-IMAGE-CONTRACT-v1.md §3）：
  content-image／lightbox-image 一律固定用 <figure class="img-wrap
  pageXX-img-N">，不論有沒有圖說；圖說有無只決定是否輸出 <figcaption>，
  外層元素本身不隨圖說切換（不再有「無圖說用 <div>」的分支）。

  一般內容圖片（§3.1）：
  <figure class="img-wrap pageXX-img-N">
    <picture><img class="img-cover" src="xxx.jpg" alt="..." loading="lazy"></picture>
    <figcaption class="img-caption text-style-caption-zh">說明</figcaption>  <!-- 只在有真實圖說時輸出 -->
  </figure>

  內容圖片＋Fancybox（§3.2）：案件定位 hook（pageXX-img-N）掛在這層
  <figure>，不得掛在下面的 <a class="img-lightbox">——見該 class 的
  height:100% 陷阱說明（_vendors.scss）。
  <figure class="img-wrap pageXX-img-N">
    <a class="img-lightbox" href="xxx-full.jpg" data-fancybox="pageXX-img-N"
        data-caption="">
      <picture><img class="img-cover" src="xxx.jpg" alt="" loading="lazy"></picture>
    </a>
    <figcaption class="img-caption text-style-caption-zh">說明</figcaption>  <!-- 只在有真實圖說時輸出，data-caption 需與此同文字 -->
  </figure>

  純 CSS background 版本（<div class="img-ratio"><div class="img-bg">）
  屬 Image v1、僅供既有案件相容（見 Contract §17 Legacy），新案件一律用
  上面兩種 <img> 結構，不再生成 background-image 版本。
*/
.img-wrap {
  position: relative;
  margin: 0;
}
.img-wrap a {
  display: block;
}
.img-wrap .img-ratio {
  position: relative;
  width: 100%;
  aspect-ratio: var(--ratio, 10/7);
}
@media (max-width: 991.98px) {
  .img-wrap .img-ratio {
    aspect-ratio: var(--ratio-m, var(--ratio, 10/7));
  }
}
.img-wrap .img-ratio .img-bg {
  position: absolute;
  inset: 0;
  background-size: cover;
  background-repeat: no-repeat;
  background-position: center;
}
.img-wrap.img-gradient::after {
  content: "";
  position: absolute;
  bottom: 0;
  left: 0;
  width: 100%;
  aspect-ratio: 23/5;
  background: linear-gradient(123deg, rgba(0, 0, 0, 0) 32.84%, rgb(0, 0, 0) 100%);
  mask: linear-gradient(to bottom, transparent 0%, black 100%);
  -webkit-mask: linear-gradient(to bottom, transparent 0%, black 100%);
  pointer-events: none;
}
.img-wrap.img-gradient .img-caption {
  z-index: 2;
}

.img-cover {
  display: block;
  width: 100%;
  height: auto;
  object-fit: cover;
  object-position: center;
  aspect-ratio: var(--ratio, 3/2);
}
@media (max-width: 991.98px) {
  .img-cover {
    aspect-ratio: var(--ratio-m, var(--ratio, 3/2));
  }
}

.img-caption {
  position: absolute;
  right: 0;
  bottom: 0;
  color: #fff;
  width: 100%;
  text-align: right;
  padding: calc(3 * var(--vw-base));
  text-shadow: 0 0 calc(10 * var(--vw-base)) rgba(0, 0, 0, 0.678);
  font-size: calc(12 * var(--vw-base));
}
@media (max-width: 991.98px) {
  .img-caption {
    font-size: calc(10.8 * var(--vw-base));
  }
}

/* ========================
  🗺 google Map Embed
======================== */
/*
  高度開成 --map-embed-height，讓使用端可以覆寫（例如固定比例的內嵌地圖）。
  不得用 !important 硬鎖 width／height——那會逼使用端也用 !important 才蓋得掉。
*/
.map-embed {
  --map-embed-height: clamp(calc(300 * var(--vw-base)), 50vh, calc(700 * var(--vw-base)));
}
.map-embed iframe {
  display: block;
  width: 100%;
  height: var(--map-embed-height);
  border: 0;
}

/* ========================
  🎭 Stage（複合素材共同座標系，2026-09-15 Background／Stage 收斂）
======================== */
.stage-wrap {
  position: relative;
}

.stage-wrap__layer {
  position: absolute;
}

/* ========================
  🎬 Video Components
======================== */
.bg-video-wrap {
  position: absolute;
  inset: 0;
  overflow: hidden;
}
.bg-video-wrap > div {
  position: absolute;
  inset: 0;
}
.bg-video-wrap video {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.video-ctrl-overlay {
  position: absolute;
  inset: 0;
  z-index: 2;
  pointer-events: none;
}

.video-controls {
  position: absolute;
  bottom: 0;
  right: 0;
  display: flex;
  justify-content: flex-end;
  align-items: center;
  z-index: 9999;
  pointer-events: auto;
}

.btn-music {
  font-size: 2rem;
  color: #E0DFC6;
  cursor: pointer;
  background: none;
  border: none;
  padding: 1.5vw;
  line-height: 1;
}

.btn-sound {
  display: none;
}

.video-wrap {
  position: relative;
  width: 100%;
  margin: 0;
  font-size: 0;
}

.video-wrap__media {
  display: block;
  width: 100%;
  height: auto;
}

.video-wrap--audio .video-controls {
  width: 100%;
}

.youtube-embed iframe {
  width: 100%;
  height: auto;
  aspect-ratio: 1680/954;
  border: none;
}

.youtube-thumb {
  overflow: hidden;
  padding: 5% 10%;
}
.youtube-thumb a {
  display: block;
}
.youtube-thumb a .Img .img-ratio {
  aspect-ratio: var(--ratio, 16/9);
}
.youtube-thumb a i {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  color: #fff;
  font-size: 5rem;
  transition: all 0.5s;
}
.youtube-thumb a:hover i {
  font-size: 6rem;
  transition: all 0.5s;
}

/* ========================
  🧭 Fixed Nav Offset
======================== */
/*
  Site shell 變數：fixed nav 的高度與底部保留量。
  這裡提供元件預設值；案件若實測到不同高度，只覆蓋 --site-nav-height，
  不要另外複製 body.has-site-nav 規則。
*/
:root {
  /* Desktop：nav 固定於頂部，不佔用底部空間 */
  --site-nav-height: 0px;
  --site-nav-reserve: 0px;
}

@media (max-width: 991.98px) {
  :root {
    --site-nav-height: calc(74 * var(--vw-base));
    /* reserve = nav 實際高度 + 安全邊際。
       安全值屬功能防護，不得在窄螢幕隨 vw 縮到低於 3px。 */
    --site-nav-reserve: calc(var(--site-nav-height) + max(3px, calc(3 * var(--vw-base))));
  }
}
/*
  Exporter／模板有輸出 .site-nav 時，才在 <body> 加上 has-site-nav。
  這是明確的輸出狀態，不由 JavaScript 切換，也不使用 body:has()。
  env(safe-area-inset-bottom) 為裝置動態附加，不屬於設計稿數值。
*/
body.has-site-nav {
  padding-bottom: calc(var(--site-nav-reserve) + env(safe-area-inset-bottom));
}

/* 第一個正式 Nav variant：建案／個案銷售網站。
   .site-nav 只保留 component identity，不承擔特定產品外觀。 */
.site-nav--property-sales {
  padding: 0;
  width: 100%;
  position: fixed;
  z-index: 9999;
  top: 0;
  left: 0;
  background-color: rgba(252, 252, 252, 0.571);
  -webkit-backdrop-filter: saturate(180%) blur(calc(20 * var(--vw-base)));
  backdrop-filter: saturate(180%) blur(calc(20 * var(--vw-base)));
  color: #000;
  box-shadow: calc(1 * var(--vw-base)) calc(1 * var(--vw-base)) calc(3 * var(--vw-base)) rgba(0, 0, 0, 0.1);
  display: flex;
  justify-content: space-between;
  /* Nav 專用 icon box：四個 icon 一律使用同一個外框尺寸，
     視覺墨跡差異再由 --site-nav-icon-scale 做最小光學校正。
     校正值來自 Chrome 4x 截圖的實際墨跡量測（墨跡高度，單位為 4x 像素）：
       phone 100｜facebook 100｜location 73｜envelope 78
     以墨跡高度 80 為共同視覺目標，換算出各自的縮放值。
     transform 不影響 Layout 尺寸，四者的 box 仍完全相同。 */
  --site-nav-icon-size: 1.35em;
}
.site-nav--property-sales .icon-phone {
  --site-nav-icon-scale: 0.8;
}
.site-nav--property-sales .icon-facebook {
  --site-nav-icon-scale: 0.8;
}
.site-nav--property-sales .icon-location {
  --site-nav-icon-scale: 1.1;
}
.site-nav--property-sales .icon-envelope {
  --site-nav-icon-scale: 1.03;
}
.site-nav--property-sales .navbar-brand {
  padding-inline: 2%;
  display: flex;
  align-items: center;
}
.site-nav--property-sales .navbar-brand img {
  height: 2.7rem;
}
.site-nav--property-sales .navbar-Link {
  display: flex;
}
.site-nav--property-sales .navbar-Link .btn {
  flex: 1;
  /* 每一個項目內部改直向堆疊（icon / 標題 / 副標）；
     .site-nav 與 .navbar-Link 本身維持橫向排列 */
  flex-direction: column;
  /* 副標放大到 vw(24) 後，最寬的「GoogleMap」需 vw(134)；vw(160) 保留左右各約 13px 餘裕 */
  min-width: calc(160 * var(--vw-base));
  color: #333;
  padding: calc(12 * var(--vw-base)) calc(24 * var(--vw-base));
  text-align: center;
  border-left: 1px solid rgba(0, 0, 0, 0.1);
}
.site-nav--property-sales .navbar-Link .btn:hover, .site-nav--property-sales .navbar-Link .btn:active {
  border-color: transparent;
  border-left: 1px solid rgba(0, 0, 0, 0.1);
  background-color: rgba(255, 255, 255, 0.6666666667);
}
.site-nav--property-sales .navbar-Link .btn > i {
  /* Desktop 不顯示 icon；box 尺寸仍統一定義，Mobile 直接開啟顯示 */
  display: none;
  flex: 0 0 var(--site-nav-icon-size);
  width: var(--site-nav-icon-size);
  height: var(--site-nav-icon-size);
  /* transform 不影響 Layout 尺寸，只做視覺墨跡校正 */
  transform: scale(var(--site-nav-icon-scale, 1));
}
.site-nav--property-sales .navbar-Link .btn {
  /*
    主標（中文）：Desktop 文字層級，四個 action 共用同一套樣式，
    不為個別 action（電話／FB／Map／Booking）設定字級。
  */
}
.site-nav--property-sales .navbar-Link .btn b {
  display: block;
  font-size: calc(18 * var(--vw-base));
  line-height: 1.2;
  font-weight: normal;
}
.site-nav--property-sales .navbar-Link .btn {
  /*
    副標（電話號碼／英文名稱）：以真正的 Typography 建立層級，
    不用 transform 縮放文字（縮放會連同字重與 hinting 一起失真）。
    四個 action 共用同一組規則。
  */
}
.site-nav--property-sales .navbar-Link .btn span {
  display: block;
  font-size: calc(20 * var(--vw-base));
  line-height: 1.2;
  letter-spacing: 0.03em;
  transform: none;
  white-space: nowrap;
}
.site-nav--property-sales .navbar-Link .btn {
  /*
    缺值連結（例如尚未提供 FB／Google Map URL）：
    不輸出 href、加上 aria-disabled="true"，因此本身即不可 focus。
    只停用互動，不改變文字與 icon 顏色，維持與其他項目一致。
  */
}
.site-nav--property-sales .navbar-Link .btn.is-disabled {
  pointer-events: none;
  cursor: default;
}
.site-nav--property-sales {
  /* Sticky */
  opacity: 0;
  transform: translateY(calc(-10 * var(--vw-base)));
  transition: all 0.5s;
  pointer-events: none;
}
.site-nav--property-sales.Sticky {
  opacity: 1;
  transform: translateY(0);
  transition: all 0.5s;
  pointer-events: all;
}
@media (max-width: 991.98px) {
  .site-nav--property-sales {
    box-shadow: 0 calc(-6 * var(--vw-base)) calc(20 * var(--vw-base)) rgba(0, 0, 0, 0.1);
    bottom: 0;
    top: auto;
  }
  .site-nav--property-sales .navbar-brand {
    display: none;
  }
  .site-nav--property-sales .navbar-Link {
    width: 100%;
  }
  .site-nav--property-sales .navbar-Link .btn {
    min-width: auto;
    font-size: calc(14 * var(--vw-base));
    padding: calc(10 * var(--vw-base)) 0;
    padding-bottom: calc(20 * var(--vw-base));
  }
  .site-nav--property-sales .navbar-Link .btn > i {
    display: block;
  }
  .site-nav--property-sales .navbar-Link .btn {
    /* Desktop 文字層級不套用到 Mobile：主標回到繼承 .btn 的字級與行高 */
  }
  .site-nav--property-sales .navbar-Link .btn b {
    font-size: 1em;
    line-height: inherit;
    font-weight: normal;
  }
  .site-nav--property-sales .navbar-Link .btn span {
    display: none;
  }
}

/* ========================
  Site Footer variants
======================== */
/*
  Footer 的背景與文字色開成元件 Token。
  用 `background`（不是 `background-color`）讓 --site-footer-background
  同時接受純色與漸層；Footer 因此不再把 --color-brand-primary 當成固定背景責任，
  案件只要覆寫元件 Token 就能換底，不需要改品牌色，也不需要 !important。
*/
.site-footer--property-sales {
  --site-footer-background: var(--color-brand-primary);
  --site-footer-color: var(--color-fixed-white);
  --site-footer-font-family: var(--font-zh-serif);
  padding-block: calc(16 * var(--vw-base));
  background: var(--site-footer-background);
  color: var(--site-footer-color);
  text-align: center;
  font-family: var(--site-footer-font-family);
  font-size: calc(14 * var(--vw-base));
  line-height: 1.7142857143;
}

.site-footer__copyright {
  margin: 0;
}

.site-footer__credit-link {
  color: inherit;
  line-height: 1;
}

@media (max-width: 991.98px) {
  .site-footer--property-sales {
    padding-block: calc(20 * var(--vw-base));
    font-size: calc(18 * var(--vw-base));
    line-height: 1.6666666667;
  }
}
/* 隱私權政策 Fancybox inline content。隱藏掛在來源容器，不能掛在
   Fancybox 開啟時會搬移的 #privacy-policy 內容節點本身。 */
.site-policy-source {
  display: none;
}

.site-policy {
  width: 100%;
  max-width: 1000px;
  padding: 40px;
  background-color: var(--color-fixed-white);
  color: var(--color-text-primary);
  font-family: var(--font-zh-serif);
  font-size: 16px;
  line-height: 1.9;
  text-align: justify;
}

.site-policy__title {
  margin: 0 0 24px;
  font-size: 22px;
  line-height: 1.4;
  text-align: center;
  color: var(--color-brand-primary);
}

.site-policy__subtitle {
  margin: 28px 0 8px;
  font-size: 17px;
  line-height: 1.6;
  color: var(--color-brand-primary);
}

.site-policy p {
  margin: 0 0 12px;
}

.site-policy__list {
  margin: 0 0 12px;
  padding-inline-start: 1.6em;
  list-style: disc;
}

.site-policy__list li {
  margin-block-end: 4px;
}

.site-policy__actions {
  margin-block-start: 32px;
  text-align: center;
}

.site-policy__close {
  min-width: 160px;
  padding: 12px 32px;
  border: 0;
  background-color: var(--color-brand-secondary);
  font-family: var(--font-zh-serif);
  font-size: 16px;
  color: var(--color-fixed-white);
  cursor: pointer;
}

@media (max-width: 991.98px) {
  .site-policy {
    padding: 24px 20px;
    font-size: 15px;
  }
  .site-policy__title {
    font-size: 19px;
  }
  .site-policy__subtitle {
    font-size: 16px;
  }
  .site-policy__close {
    width: 100%;
    min-width: 0;
  }
}
body.is-loading {
  overflow: hidden;
}

.site-loader {
  position: fixed;
  inset: 0;
  z-index: 9999;
  display: flex;
  align-items: center;
  justify-content: center;
  isolation: isolate;
  background-color: #f6f1eb;
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
  transition: opacity 0.35s ease, visibility 0s linear 0.35s;
}

.site-loader.is-visible {
  opacity: 1;
  visibility: visible;
  pointer-events: auto;
  transition: opacity 0.35s ease, visibility 0s linear 0s;
}

.site-loader__logo {
  width: calc(240 * var(--vw-base));
  height: auto;
}

.site-loader__logo path {
  fill: transparent;
  stroke-dasharray: var(--len, 2000);
  stroke-dashoffset: var(--len, 2000);
  stroke-width: 1.2;
}

.site-loader__logo path.st0 {
  stroke: #4D4D4D;
  animation: logo-reveal-dark 2.4s ease-in-out forwards;
}

.site-loader__logo path.st1 {
  stroke: #C8C9CA;
  animation: logo-reveal-light 2.4s ease-in-out forwards;
}

@keyframes logo-reveal-dark {
  0% {
    stroke-dashoffset: var(--len, 2000);
    fill: transparent;
    opacity: 0;
  }
  5% {
    opacity: 1;
  }
  65% {
    stroke-dashoffset: 0;
    fill: transparent;
  }
  100% {
    stroke-dashoffset: 0;
    fill: #4D4D4D;
    opacity: 1;
  }
}
@keyframes logo-reveal-light {
  0% {
    stroke-dashoffset: var(--len, 2000);
    fill: transparent;
    opacity: 0;
  }
  5% {
    opacity: 1;
  }
  65% {
    stroke-dashoffset: 0;
    fill: transparent;
  }
  100% {
    stroke-dashoffset: 0;
    fill: #C8C9CA;
    opacity: 1;
  }
}
.site-loader__spinner {
  width: calc(70 * var(--vw-base));
  height: calc(70 * var(--vw-base));
  border: calc(1 * var(--vw-base)) solid rgba(110, 136, 0, 0.25);
  border-top-color: #6e8800;
  border-radius: 50%;
  animation: site-loader-spin 0.7s linear infinite;
  will-change: transform;
}

@keyframes site-loader-spin {
  to {
    transform: rotate(360deg);
  }
}
@media (prefers-reduced-motion: reduce) {
  .site-loader {
    transition: none;
  }
  .site-loader__logo path.st0 {
    animation: none;
    stroke-dashoffset: 0;
    fill: #4D4D4D;
    opacity: 1;
  }
  .site-loader__logo path.st1 {
    animation: none;
    stroke-dashoffset: 0;
    fill: #C8C9CA;
    opacity: 1;
  }
  .site-loader__spinner {
    animation: none;
    will-change: auto;
  }
}
.icon-phone,
.icon-facebook,
.icon-location,
.icon-envelope {
  display: inline-block;
  flex: 0 0 auto;
  width: 1em;
  height: 1em;
  background-color: currentColor;
  mask: var(--icon-mask) center/contain no-repeat;
  -webkit-mask: var(--icon-mask) center/contain no-repeat;
}

/* 單一來源：四個 nav icon 一律使用 --icon-mask 契約（1em box）。
   此處採用原本第二段定義的圖形，避免整併後 phone 圖形改變。 */
.icon-phone {
  --icon-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath fill='%23000' fill-rule='evenodd' d='M1.885.511a1.745 1.745 0 0 1 2.61.163L6.29 2.98c.329.423.445.974.315 1.494l-.547 2.19a.68.68 0 0 0 .178.643l2.457 2.457a.68.68 0 0 0 .644.178l2.189-.547a1.75 1.75 0 0 1 1.494.315l2.306 1.794c.829.645.905 1.87.163 2.611l-1.034 1.034c-.74.74-1.846 1.065-2.877.702a18.6 18.6 0 0 1-7.01-4.42a18.6 18.6 0 0 1-4.42-7.009c-.362-1.03-.037-2.137.703-2.877z'/%3E%3C/svg%3E");
}

.icon-facebook {
  --icon-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath fill='%23000' d='M16 8.049C16 3.603 12.418 0 8 0S0 3.603 0 8.049C0 12.067 2.925 15.397 6.75 16v-5.624H4.719V8.049H6.75V6.276c0-2.017 1.194-3.132 3.022-3.132.875 0 1.791.157 1.791.157v1.984h-1.009c-.994 0-1.304.621-1.304 1.258v1.506h2.219l-.355 2.327H9.25V16C13.075 15.397 16 12.067 16 8.049z'/%3E%3C/svg%3E");
}

.icon-location {
  --icon-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath fill='%23000' d='M12 6c0 2.05-2.17 5.23-4 7.44C6.17 11.23 4 8.05 4 6a4 4 0 1 1 8 0zm-4 2a2 2 0 1 0 0-4 2 2 0 0 0 0 4z'/%3E%3C/svg%3E");
}

.icon-envelope {
  --icon-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath fill='%23000' d='M0 4a2 2 0 0 1 2-2h12a2 2 0 0 1 2 2v8a2 2 0 0 1-2 2H2a2 2 0 0 1-2-2V4zm2-.5a.5.5 0 0 0-.5.5v.217l6.5 3.9 6.5-3.9V4a.5.5 0 0 0-.5-.5H2zm12.5 2.466-4.793 2.876L14.5 11.7V5.966zM14.293 13 8.97 9.806 8 10.388l-.97-.582L1.707 13h12.586zM1.5 11.7l4.793-2.858L1.5 5.966V11.7z'/%3E%3C/svg%3E");
}

.icon, .icon-aerial-swipe, .icon-cat {
  --icon-size: 1.35em;
  vertical-align: -0.22em;
  display: inline-block;
  width: var(--icon-size);
  height: var(--icon-size);
  flex: 0 0 auto;
}

.icon-filled {
  font-variation-settings: "FILL" 1, "wght" 400, "GRAD" 0, "opsz" 24;
}

.icon-cat {
  background-color: currentColor;
  -webkit-mask-image: var(--svg);
  mask-image: var(--svg);
  -webkit-mask-repeat: no-repeat;
  mask-repeat: no-repeat;
  -webkit-mask-size: 100% 100%;
  mask-size: 100% 100%;
  --svg: url("data:image/svg+xml;charset=utf-8;base64,PHN2ZyB4bWxucz0naHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmcnIHdpZHRoPScxZW0nIGhlaWdodD0nMWVtJyB2aWV3Qm94PScwIDAgMjQgMjQnPjxwYXRoIGQ9J00wIDBoMjR2MjRIMHonIGZpbGw9J25vbmUnIC8+PGcgZmlsbD0nbm9uZScgc3Ryb2tlPSdjdXJyZW50Q29sb3InIHN0cm9rZS13aWR0aD0nMS41Jz48cGF0aCBzdHJva2UtbGluZWNhcD0ncm91bmQnIGQ9J00xOS4xIDEwLjY2YzEuMTExIDEuMzE0Ljg4IDIuOTIyLjg4IDQuMzRjMCAzLjkwNi01LjI2NyA1LTcuOTggNXMtNy45OC0xLjA5NC03Ljk4LTVjMC0xLjQxOC0uMjMxLTMuMDI2Ljg4LTQuMzRtMTQuMiAwYy0uMTk1LS4yMy0uNDMtLjQ1LS43MTYtLjY2bS43MTUuNjZjLjcuNDAzLjg4LTEuMTA1Ljg4MS0xLjU5OFY3LjE4OEMxOS45OCA1LjU2MyAxOC44NjMgNSAxNy45MDUgNWMtLjk1NyAwLTIuODczIDEuNTYzLTMuNTExIDEuNTYzYy0uNzY2IDAtLjkxNC0uMTU3LTIuMzk0LS4xNTdzLTEuNjI4LjE1Ny0yLjM5NC4xNTdDOC45NjggNi41NjMgNy4wNTIgNSA2LjA5NSA1UzQuMDIgNS41NjMgNC4wMiA3LjE4OHYxLjg3NWMuMDAyLjQ5Mi4xOCAyIC44OCAxLjU5N20wIDBjLjE5NS0uMjMuNDMtLjQ1LjcxNi0uNjYnIC8+PHBhdGggZD0nTTEyLjgyNiAxNmMwIC4xNzMtLjM2MS4zMTMtLjgwNy4zMTNjLS40NDUgMC0uODA2LS4xNC0uODA2LS4zMTNzLjM2MS0uMzEyLjgwNi0uMzEycy44MDcuMTQuODA3LjMxMlptMi42NzQtMi40MDZjMCAuNDMxLS4yMTcuNzgxLS40ODQuNzgxcy0uNDg0LS4zNS0uNDg0LS43ODFzLjIxNy0uNzgxLjQ4NC0uNzgxcy40ODQuMzUuNDg0Ljc4Wm0tNiAwYzAgLjQzMS0uMjE3Ljc4MS0uNDg0Ljc4MXMtLjQ4NC0uMzUtLjQ4NC0uNzgxcy4yMTctLjc4MS40ODQtLjc4MXMuNDg0LjM1LjQ4NC43OFonIC8+PHBhdGggc3Ryb2tlLWxpbmVjYXA9J3JvdW5kJyBkPSdNMjIgMTUuNDY5Yy0uNDgzLS4zMTMtMi41OC0xLjA5NC0zLjM4Ny0xLjA5NG0xLjc3NCAzLjU5NGMtLjQ4NC0uMzEzLTEuNjEzLTEuMDk0LTIuNDItMS4wOTRNMiAxNS40NjljLjQ4NC0uMzEzIDIuNTgtMS4wOTQgMy4zODctMS4wOTRtLTEuNzc0IDMuNTk0Yy40ODQtLjMxMyAxLjYxMy0xLjA5NCAyLjQyLTEuMDk0JyAvPjwvZz48L3N2Zz4g");
}

.icon-aerial-swipe {
  background-color: currentColor;
  -webkit-mask-image: var(--svg);
  mask-image: var(--svg);
  -webkit-mask-repeat: no-repeat;
  mask-repeat: no-repeat;
  -webkit-mask-size: 100% 100%;
  mask-size: 100% 100%;
  --svg: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 -960 960 960'%3E%3Cpath fill='%23000' d='M880-680H680v-60h116q-66-58-147-89t-169-31q-88 0-169 31t-147 89h116v60H80v-200h60v81q72-59 159-90t181-31q94 0 181 31t159 90v-81h60v200ZM473-80q-24 0-46-9t-39-26L184-320l30-31q16-16 37.5-21.5t42.5.5l66 19v-327q0-17 11.5-28.5T400-720q17 0 28.5 11.5T440-680v280h40v-120q0-17 11.5-28.5T520-560q17 0 28.5 11.5T560-520v120h40v-80q0-17 11.5-28.5T640-480q17 0 28.5 11.5T680-480v80h40q0-17 11.5-28.5T760-440q17 0 28.5 11.5T800-400v160q0 66-47 113T640-80H473Z'/%3E%3C/svg%3E");
}

.icon-logo-utmost {
  --logo-height: 1em;
  display: inline-block;
  width: auto;
  height: var(--logo-height);
  aspect-ratio: 253/61.7;
  background-color: currentColor;
  -webkit-mask-image: url("../images/logo-utmost.svg");
  mask-image: url("../images/logo-utmost.svg");
  -webkit-mask-repeat: no-repeat;
  mask-repeat: no-repeat;
  -webkit-mask-size: contain;
  mask-size: contain;
  -webkit-mask-position: center;
  mask-position: center;
}

.aerial-bg {
  --aerial-bg: #2285de;
  background-color: var(--aerial-bg);
}

.aerial-anchor {
  position: absolute;
  transform: translateX(-50%);
  text-align: center;
  pointer-events: none;
  z-index: 3;
}
.aerial-anchor .aerial-anchor-label {
  display: inline-block;
  background: rgba(0, 0, 0, 0.55);
  color: #fff;
  font-size: 0.8rem;
  font-weight: bold;
  padding: calc(3 * var(--vw-base)) calc(10 * var(--vw-base));
  white-space: nowrap;
  letter-spacing: 0.05em;
  margin-bottom: calc(4 * var(--vw-base));
  backdrop-filter: blur(calc(4 * var(--vw-base)));
}
.aerial-anchor::before {
  content: "";
  display: block;
  width: calc(1 * var(--vw-base));
  height: calc(36 * var(--vw-base));
  background: linear-gradient(to bottom, rgba(255, 255, 255, 0.9), rgba(255, 255, 255, 0.1));
  margin: 0 auto;
}
.aerial-anchor::after {
  content: "";
  display: block;
  width: calc(8 * var(--vw-base));
  height: calc(8 * var(--vw-base));
  border-radius: 50%;
  background: #fff;
  box-shadow: 0 0 0 calc(3 * var(--vw-base)) rgba(255, 255, 255, 0.35), 0 0 calc(14 * var(--vw-base)) calc(4 * var(--vw-base)) rgba(255, 255, 255, 0.5);
  margin: calc(4 * var(--vw-base)) auto 0;
}

.aerial-map-wrap {
  position: relative;
  margin: 0;
  --aerial-h: 80vh;
  --aerial-min-h: 100vh;
  height: var(--aerial-h);
  min-height: var(--aerial-min-h);
  overflow: hidden;
}
.aerial-map-wrap.aerial-map-wrap--scrim::before {
  content: "";
  position: absolute;
  z-index: 1;
  width: 100%;
  padding-top: 20%;
  background: linear-gradient(to bottom, var(--aerial-bg) 0%, transparent 100%);
}
.aerial-map-wrap .aerial-txt-overlay {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  z-index: 2;
  pointer-events: none;
}
.aerial-map-wrap .aerial-txt-overlay > * {
  pointer-events: auto;
}
.aerial-map-wrap .aerial-txt-overlay .txt-wrap {
  text-align: center;
}
.aerial-map-wrap .aerial-txt-overlay .txt-wrap > small {
  display: block;
  letter-spacing: 0.3em;
  opacity: 0.75;
  margin-bottom: 0.5rem;
}
.aerial-map-wrap .aerial-map-scroll {
  position: absolute;
  inset: 0;
  overflow-x: auto;
  overflow-y: hidden;
  -webkit-overflow-scrolling: touch;
  cursor: auto;
  scrollbar-width: none;
}
.aerial-map-wrap .aerial-map-scroll::-webkit-scrollbar {
  display: none;
}
.aerial-map-wrap[data-pannable=true] .aerial-map-scroll {
  cursor: grab;
}
.aerial-map-wrap[data-pannable=true] .aerial-map-scroll:active {
  cursor: grabbing;
}
.aerial-map-wrap .aerial-map-inner {
  position: relative;
  display: inline-block;
  height: var(--aerial-h);
  min-height: var(--aerial-min-h);
}
.aerial-map-wrap .aerial-map-inner img {
  display: block;
  height: 100%;
  width: auto;
  max-width: none;
}
.aerial-map-wrap .aerial-hint {
  display: none;
  position: absolute;
  left: calc(10 * var(--vw-base));
  bottom: calc(10 * var(--vw-base));
  z-index: 5;
  animation: aerial-hint-flick 2s ease-in-out infinite alternate;
}
.aerial-map-wrap .aerial-hint--icon {
  left: 50%;
  bottom: 10vw;
  transform: translateX(-50%);
  animation: none;
}
.aerial-map-wrap[data-pannable=true] .aerial-hint {
  display: block;
}
.aerial-map-wrap[data-pannable=true] .aerial-hint--icon {
  display: flex;
}

.txt-wrap .aerial-hint--icon {
  position: relative;
  left: auto;
  bottom: auto;
  transform: none;
}

.aerial-hint {
  color: rgba(255, 255, 255, 0.85);
  font-size: 0.7rem;
  letter-spacing: 0.08em;
  text-shadow: 0 0 calc(8 * var(--vw-base)) rgba(0, 0, 0, 0.6);
  pointer-events: none;
}

.aerial-hint--icon {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: calc(4 * var(--vw-base));
  font-size: 1.5rem;
  letter-spacing: 0;
}
.aerial-hint--icon .icon {
  display: block;
  animation: aerial-hint-swipe 0.9s ease-in-out infinite alternate;
}
.aerial-hint--icon small {
  font-size: 0.6rem;
  letter-spacing: 0.1em;
}

@media (prefers-reduced-motion: reduce) {
  .aerial-hint,
  .aerial-hint .icon {
    animation: none;
  }
}
@keyframes aerial-hint-flick {
  0% {
    letter-spacing: 0.02em;
  }
  100% {
    letter-spacing: 0.16em;
  }
}
@keyframes aerial-hint-swipe {
  from {
    transform: translateX(-12px);
  }
  to {
    transform: translateX(calc(12 * var(--vw-base)));
  }
}
html.is-draft {
  --draft-line-width: calc(2 * var(--vw-base));
  --draft-grid-color: rgba(255, 193, 7, .28);
  --draft-grid-border: rgba(255, 193, 7, .85);
  --draft-content-padding-color: rgba(0, 132, 255, .18);
  --draft-content-padding-border: rgba(0, 132, 255, .75);
  --draft-txt-padding-color: rgba(255, 0, 180, .16);
  --draft-txt-padding-border: rgba(255, 0, 180, .75);
}
@media (min-width: 992px) {
  html.is-draft {
    --draft-line-width: calc(1 * var(--vw-base));
  }
}
html.is-draft body {
  position: relative;
}
html.is-draft body::after {
  content: "";
  background-size: 100%;
  background-repeat: no-repeat;
  background-position: 0% 21.5%;
  position: absolute;
  pointer-events: none;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  z-index: 9999;
  border: calc(2 * var(--vw-base)) solid blue;
  opacity: 0.2;
}
@media (min-width: 992px) {
  html.is-draft body::after {
    background-position: 0% 0%;
  }
}
html.is-draft body::before {
  content: "";
  position: fixed;
  inset: 0;
  z-index: 999;
  pointer-events: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 1200 32' preserveAspectRatio='none'%3E%3Cg font-family='Arial,sans-serif' font-size='18' font-weight='700' text-anchor='middle' dominant-baseline='middle' fill='red' stroke='white' stroke-width='4' paint-order='stroke'%3E%3Ctext x='50' y='16'%3E1%3C/text%3E%3Ctext x='150' y='16'%3E2%3C/text%3E%3Ctext x='250' y='16'%3E3%3C/text%3E%3Ctext x='350' y='16'%3E4%3C/text%3E%3Ctext x='450' y='16'%3E5%3C/text%3E%3Ctext x='550' y='16'%3E6%3C/text%3E%3Ctext x='650' y='16'%3E7%3C/text%3E%3Ctext x='750' y='16'%3E8%3C/text%3E%3Ctext x='850' y='16'%3E9%3C/text%3E%3Ctext x='950' y='16'%3E10%3C/text%3E%3Ctext x='1050' y='16'%3E11%3C/text%3E%3Ctext x='1150' y='16'%3E12%3C/text%3E%3C/g%3E%3C/svg%3E"), repeating-linear-gradient(90deg, transparent 0, transparent calc(8.3333333333% - var(--draft-line-width)), red calc(8.3333333333% - var(--draft-line-width)), red 8.3333333333%);
  background-repeat: no-repeat, repeat;
  background-size: 100% calc(32 * var(--vw-base)), auto;
  background-position: center, 0 0;
}
html.is-draft .container {
  border: var(--draft-line-width) solid rgb(0, 26, 255);
}
html.is-draft .container > .row {
  position: relative;
}
html.is-draft .container > .row::before {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  z-index: 999;
  border: var(--draft-line-width) solid rgb(0, 255, 51);
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 1200 32' preserveAspectRatio='none'%3E%3Cg font-family='Arial,sans-serif' font-size='18' font-weight='700' text-anchor='middle' dominant-baseline='middle' fill='rgb(0,255,51)' stroke='white' stroke-width='4' paint-order='stroke'%3E%3Ctext x='50' y='16'%3E1%3C/text%3E%3Ctext x='150' y='16'%3E2%3C/text%3E%3Ctext x='250' y='16'%3E3%3C/text%3E%3Ctext x='350' y='16'%3E4%3C/text%3E%3Ctext x='450' y='16'%3E5%3C/text%3E%3Ctext x='550' y='16'%3E6%3C/text%3E%3Ctext x='650' y='16'%3E7%3C/text%3E%3Ctext x='750' y='16'%3E8%3C/text%3E%3Ctext x='850' y='16'%3E9%3C/text%3E%3Ctext x='950' y='16'%3E10%3C/text%3E%3Ctext x='1050' y='16'%3E11%3C/text%3E%3Ctext x='1150' y='16'%3E12%3C/text%3E%3C/g%3E%3C/svg%3E"), linear-gradient(to right, rgba(123, 255, 0, 0.1) 0, rgba(123, 255, 0, 0.1) calc(100% - var(--draft-line-width)), rgb(0, 255, 51) calc(100% - var(--draft-line-width)), rgb(0, 255, 51) 100%);
  background-repeat: no-repeat, repeat;
  background-size: 100% calc(32 * var(--vw-base)), 8.3333333333% 100%;
  background-position: center, 0 0;
}
html.is-draft .container > .row::after {
  content: "";
  position: absolute;
  inset-block: calc(var(--grid-gap-y) / -2);
  inset-inline: 0;
  z-index: 998;
  pointer-events: none;
  border-block: 1px dashed var(--draft-grid-border);
}
html.is-draft .container > .row > [class^=col],
html.is-draft .container > .row > [class*=" col"] {
  position: relative;
  outline: 1px dashed var(--draft-grid-border);
  outline-offset: calc(var(--draft-line-width) * -1);
}
html.is-draft .container > .row > [class^=col]::before,
html.is-draft .container > .row > [class*=" col"]::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 998;
  pointer-events: none;
  background-image: linear-gradient(90deg, var(--draft-grid-color) 0, var(--draft-grid-color) calc(var(--grid-gap-x) / 2), transparent calc(var(--grid-gap-x) / 2), transparent calc(100% - var(--grid-gap-x) / 2), var(--draft-grid-color) calc(100% - var(--grid-gap-x) / 2), var(--draft-grid-color) 100%);
}
html.is-draft .content-px,
html.is-draft .content-ps,
html.is-draft .content-pe,
html.is-draft .content-px--mobile-0,
html.is-draft .content-px--desktop-0,
html.is-draft .content-ps--mobile-0,
html.is-draft .content-pe--mobile-0,
html.is-draft .txt-px,
html.is-draft .txt-py,
html.is-draft .txt-ps,
html.is-draft .txt-pe,
html.is-draft .txt-pt,
html.is-draft .txt-pb,
html.is-draft .txt-desktop-px,
html.is-draft .txt-desktop-py,
html.is-draft .txt-desktop-ps,
html.is-draft .txt-desktop-pe,
html.is-draft .txt-desktop-pt,
html.is-draft .txt-desktop-pb {
  --draft-content-ps: 0;
  --draft-content-pe: 0;
  --draft-txt-ps: 0;
  --draft-txt-pe: 0;
  --draft-txt-pt: 0;
  --draft-txt-pb: 0;
  outline-offset: calc(var(--draft-line-width) * -1);
}
html.is-draft .content-px,
html.is-draft .content-ps,
html.is-draft .content-pe,
html.is-draft .content-px--mobile-0,
html.is-draft .content-px--desktop-0,
html.is-draft .content-ps--mobile-0,
html.is-draft .content-pe--mobile-0 {
  outline: 1px dashed var(--draft-content-padding-border);
}
html.is-draft .txt-px,
html.is-draft .txt-py,
html.is-draft .txt-ps,
html.is-draft .txt-pe,
html.is-draft .txt-pt,
html.is-draft .txt-pb,
html.is-draft .txt-desktop-px,
html.is-draft .txt-desktop-py,
html.is-draft .txt-desktop-ps,
html.is-draft .txt-desktop-pe,
html.is-draft .txt-desktop-pt,
html.is-draft .txt-desktop-pb {
  outline: 1px dashed var(--draft-txt-padding-border);
}
html.is-draft .content-px {
  --draft-content-ps: var(--content-px);
  --draft-content-pe: var(--content-px);
}
html.is-draft .content-px--desktop-0 {
  --draft-content-ps: var(--content-px);
  --draft-content-pe: var(--content-px);
}
html.is-draft .content-ps {
  --draft-content-ps: var(--content-px);
  --draft-content-pe: var(--content-px);
}
html.is-draft .content-pe {
  --draft-content-ps: var(--content-px);
  --draft-content-pe: var(--content-px);
}
@media (min-width: 992px) {
  html.is-draft .content-px--desktop-0 {
    --draft-content-ps: 0;
    --draft-content-pe: 0;
  }
  html.is-draft .content-px--mobile-0 {
    --draft-content-ps: var(--content-px);
    --draft-content-pe: var(--content-px);
  }
  html.is-draft .content-ps--mobile-0 {
    --draft-content-ps: var(--content-px);
    --draft-content-pe: 0;
  }
  html.is-draft .content-pe--mobile-0 {
    --draft-content-ps: 0;
    --draft-content-pe: var(--content-px);
  }
  html.is-draft .content-ps {
    --draft-content-pe: 0;
  }
  html.is-draft .content-pe {
    --draft-content-ps: 0;
  }
  html.is-draft .ps-desktop-0 {
    --draft-content-ps: 0;
    --draft-txt-ps: 0;
  }
  html.is-draft .pe-desktop-0 {
    --draft-content-pe: 0;
    --draft-txt-pe: 0;
  }
  html.is-draft .pt-desktop-0 {
    --draft-txt-pt: 0;
  }
  html.is-draft .pb-desktop-0 {
    --draft-txt-pb: 0;
  }
}
html.is-draft .content-px,
html.is-draft .content-ps,
html.is-draft .content-pe,
html.is-draft .content-px--mobile-0,
html.is-draft .content-ps--mobile-0,
html.is-draft .content-pe--mobile-0 {
  box-shadow: inset var(--draft-content-ps) 0 0 var(--draft-content-padding-color), inset calc(var(--draft-content-pe) * -1) 0 0 var(--draft-content-padding-color);
}
html.is-draft .txt-px {
  --draft-txt-ps: var(--txt-px);
  --draft-txt-pe: var(--txt-px);
}
html.is-draft .txt-py {
  --draft-txt-pt: var(--txt-py);
  --draft-txt-pb: var(--txt-py);
}
html.is-draft .txt-ps {
  --draft-txt-ps: var(--txt-px);
}
html.is-draft .txt-pe {
  --draft-txt-pe: var(--txt-px);
}
html.is-draft .txt-pt {
  --draft-txt-pt: var(--txt-py);
}
html.is-draft .txt-pb {
  --draft-txt-pb: var(--txt-py);
}
@media (min-width: 992px) {
  html.is-draft .txt-desktop-px {
    --draft-txt-ps: var(--txt-px);
    --draft-txt-pe: var(--txt-px);
  }
  html.is-draft .txt-desktop-py {
    --draft-txt-pt: var(--txt-py);
    --draft-txt-pb: var(--txt-py);
  }
  html.is-draft .txt-desktop-ps {
    --draft-txt-ps: var(--txt-px);
  }
  html.is-draft .txt-desktop-pe {
    --draft-txt-pe: var(--txt-px);
  }
  html.is-draft .txt-desktop-pt {
    --draft-txt-pt: var(--txt-py);
  }
  html.is-draft .txt-desktop-pb {
    --draft-txt-pb: var(--txt-py);
  }
}
html.is-draft .txt-px,
html.is-draft .txt-py,
html.is-draft .txt-ps,
html.is-draft .txt-pe,
html.is-draft .txt-pt,
html.is-draft .txt-pb,
html.is-draft .txt-desktop-px,
html.is-draft .txt-desktop-py,
html.is-draft .txt-desktop-ps,
html.is-draft .txt-desktop-pe,
html.is-draft .txt-desktop-pt,
html.is-draft .txt-desktop-pb {
  box-shadow: inset var(--draft-txt-ps) 0 0 var(--draft-txt-padding-color), inset calc(var(--draft-txt-pe) * -1) 0 0 var(--draft-txt-padding-color), inset 0 var(--draft-txt-pt) 0 var(--draft-txt-padding-color), inset 0 calc(var(--draft-txt-pb) * -1) 0 var(--draft-txt-padding-color);
}

/* ========================
  🔧 Base
======================== */
*,
*::before,
*::after {
  position: relative;
  box-sizing: border-box;
}

html {
  overflow-x: clip;
  overflow-y: auto;
}

body {
  display: flex;
  flex-direction: column;
}

footer {
  margin-top: auto;
}

/* ========================
  🔗 Link / Button
======================== */
a,
.btn {
  text-decoration: none;
  border-radius: 0;
}
a:hover,
.btn:hover {
  text-decoration: none;
}

/*
  🎯 Focus Ring（鍵盤可及性）
  焦點框不得移除：鍵盤操作必須看得見目前焦點在哪裡。
  這裡只用 :focus-visible，因此滑鼠點擊不會出現焦點框，
  但 Tab、方向鍵與螢幕閱讀器操作一定看得見。
  顏色／粗細走 --focus-ring-* Token（定義於 _root.scss），案件只要覆寫 Token 即可換色，
  不需要在案件層用 !important 補洞。
*/
a:focus-visible,
button:focus-visible,
input:focus-visible,
select:focus-visible,
textarea:focus-visible,
summary:focus-visible,
[tabindex]:not([tabindex="-1"]):focus-visible {
  outline: var(--focus-ring-width) solid var(--focus-ring-color);
  outline-offset: var(--focus-ring-offset);
}
a,
button,
input,
select,
textarea,
summary,
[tabindex]:not([tabindex="-1"]) {
  /* 滑鼠／觸控點擊不強制呈現與鍵盤相同的焦點框 */
}
a:focus:not(:focus-visible),
button:focus:not(:focus-visible),
input:focus:not(:focus-visible),
select:focus:not(:focus-visible),
textarea:focus:not(:focus-visible),
summary:focus:not(:focus-visible),
[tabindex]:not([tabindex="-1"]):focus:not(:focus-visible) {
  outline: none;
}

a {
  color: #6e8800;
}

p {
  margin-bottom: 0;
}

/*# sourceMappingURL=main.css.map */
