/* ==========================================================================
   MemorGi 官網設計系統
   --------------------------------------------------------------------------
   2026-10-30 起：黑金夜色（對齊 app icon 與字標的黑金）。相紙仍是米白，像洗出來的照片。
   舊方向：奶茶／宣紙文青。刻意避開「AI 生成感」的三組預設（#F4F1EA 底配高對比
   襯線配赭紅、近黑底配螢光綠、broadsheet 零圓角密排）。

   兩個關鍵決定：
   1. 強調色不自己配 —— 直接用 app 裡真實的便條 8 色（`ItemCardColors.swift`
      的 notePalette 算出來的 hex）。官網跟產品是同一套顏色，不是兩套語彙。
   2. signature = 便利貼牆。卡片微旋轉、堆疊、hover 抬起。這是 MemorGi 獨有的形態，
      別的產品抄不走 —— 版面骨架直接長成產品的樣子。
   ========================================================================== */

/* ==========================================================================
   自己託管的字型（2026-08-18 從 Google Fonts 搬過來）
   --------------------------------------------------------------------------
   🔴 **為什麼要搬**：實測首頁一次向 `fonts.gstatic.com` 抓 **38 個字型檔**
   ＋ 一份 **266 KB 的擋畫面 CSS**。手機 Slow 4G ＋ 4x CPU 之下那是
   **553 ms 的擋畫面時間**。

   而更要緊的是**定位矛盾**：這個站通篇寫「沒有雲端、資料只在你的 Mac」，
   卻讓每個訪客的 IP 送去 Google。一個剪貼簿工具的官網不該是這樣。

   🔴 **三套都是 OFL 授權**，自己託管完全合法（含商業用途）。
   授權原文放在 `fonts/OFL-*.txt` —— **OFL 要求授權隨字型一起散布，不要刪掉**。

   ⚠️ **LXGW WenKai TC 的 700 用的是上游的 Medium**。上游沒有 Bold，
   而 Google 送的「Bold」實測就是 Medium ——
   正規化墨水面積 Google-700 = 0.3098 vs 上游 Medium = 0.3080（差 0.6%），
   粗細比 122.3% vs 122.4%。
   🔴 **不要用「輪廓完全相同」去比** —— Google 會重新處理座標，
   連 400 對上游 Regular 都是 0/20 不同。那個比法只會得到「全都不一樣」。

   ⚠️ **子集化只含站上實際用到的 1045 個字元**（878 個漢字）。
   **新增文案用到新字就要重跑子集**，否則那個字會掉回系統字型 ——
   看起來是「某幾個字長得不一樣」，很難發現。重跑方式見 `scripts/website-fonts.sh`。

   ⚠️ 檔名帶日期版本號（`.v20261030.`）是為了配合 `_headers` 的一年不可變快取。**換字型要把日期改成當天。**
   ========================================================================== */

/* 正文與所有中文（含正文裡的拉丁字）*/
@font-face {
    font-family: 'LXGW WenKai TC';
    font-style: normal;
    font-weight: 400;
    font-display: swap;
    src: url('../fonts/WenKaiTC-400.v20261030.woff2') format('woff2');
}
@font-face {
    font-family: 'LXGW WenKai TC';
    font-style: normal;
    font-weight: 700;
    font-display: swap;
    src: url('../fonts/WenKaiTC-700.v20261030.woff2') format('woff2');
}

/* 標題的拉丁字。⚠️ 可變字型 —— `font-variation-settings: 'opsz' 40, 'SOFT' 40`
   會用到 opsz 與 SOFT 兩個軸，換成靜態字重標題會長得不一樣。 */
@font-face {
    font-family: 'Fraunces';
    font-style: normal;
    font-weight: 400 700;
    font-display: swap;
    src: url('../fonts/Fraunces-var.v20261030.woff2') format('woff2-variations'),
         url('../fonts/Fraunces-var.v20261030.woff2') format('woff2');
}

/* 等寬（快捷鍵、程式碼、eyebrow）*/
@font-face {
    font-family: 'JetBrains Mono';
    font-style: normal;
    font-weight: 400 500;
    font-display: swap;
    src: url('../fonts/JetBrainsMono-var.v20261030.woff2') format('woff2-variations'),
         url('../fonts/JetBrainsMono-var.v20261030.woff2') format('woff2');
}

/* ---------- Tokens ---------- */
:root {
    /* 紙與墨：宣紙米底，焙茶棕墨。不是純黑白 —— 純黑在米底上太硬 */
    --paper:        #121110;
    --paper-warm:   #1A1917;   /* 沉一階的區塊底 */
    --paper-deep:   #0B0A09;   /* 分隔帶、footer */
    /* 🔴 三個字色的值是**算出來的不是挑出來的**（8/4 Lighthouse 抓到對比不足後修）。
       每一個都對「它實際會壓在的所有底色」量過 WCAG AA 4.5:1：
       --ink-3 與 --gold-deep 要同時對 #F7F3EC / #F1EADD / #E8DECB 三種米底達標，
       --ink-on-note 要對全部 8 色便條達標（最難的是玫瑰 #F5ABC6，實測 4.93）。
       ⚠️ 改這三個值一定要重量，別憑「看起來夠深」—— 原本的 #A87C2E 只有 3.40。 */
    --ink:          #F4EFE6;   /* 主墨（焙茶棕）· 對米底 13.23 */
    --ink-2:        #CFC6B8;   /* 次要文字 · 6.09 */
    --ink-3:        #ABA192;   /* 標籤、meta · 5.76 / 5.33 / 4.78（含 footer 的深米底）*/
    --ink-on-note:  #3F3326;   /* 便條色上的小字 · 對 8 色最低 4.93 */
    --rule:         #34302A;   /* 髮絲線（裝飾，不套文字門檻）*/

    /* 品牌金：跟 app 的 memorgiGold 同一個 */
    --gold:         #D4AF6A;
    --gold-deep:    #E2C17F;   /* 金「字」用這個 · 5.49 / 5.08。--gold 只當底或裝飾 */
    --gold-wash:    #2A2419;

    /* 夜色版加的三個：一般卡片底、相紙（照片維持米白）、相紙上的字 */
    --surface:      #1D1C1A;
    --photo:        #F7F3EC;
    --ink-photo:    #33261C;

    /* 便條 8 色 —— 從 app 的 notePalette (light) 實算出來的，不是手挑近似色 */
    --note-amber:   #F9DF90;
    --note-sky:     #9FCFF1;
    --note-coral:   #F6BBA7;
    --note-mint:    #9DEDDD;
    --note-violet:  #E7B4F4;
    --note-linen:   #F4EADB;
    --note-grass:   #A7EEA9;
    --note-rose:    #F5ABC6;

    /* 字：Fraunces 的 opsz 軸讓大標長得像鉛字、小字保持可讀。
       中文走霞鶩文楷 —— 不用 Noto，那是「預設」不是「選擇」*/
    /* ⚠️ fallback 一律接對齊過度量的那一份（見檔案開頭的 @font-face）——
       直接寫 Georgia 會在字體換上來時整段重排。 */
    --display: 'Fraunces', 'Fraunces-fallback', 'LXGW WenKai TC', Georgia, serif;
    --body:    'LXGW WenKai TC', 'WenKai-fallback', -apple-system, BlinkMacSystemFont, sans-serif;
    --mono:    'JetBrains Mono', ui-monospace, 'SF Mono', Menlo, monospace;

    /* 🔴 行長的判準（8/4 修）：Web Interface Guidelines 說「一行 65-75 字元」，
       但那是**拉丁文字**的標準。中文一個字約等於兩個拉丁字元的視覺寬度，
       換算過來是**一行 32-38 個中文字**。所以 em 值對中文要放大，不能照抄。
       實例：`.pull` 原本 24em 在 40px 字級下一行放不到 24 字，
       句號會孤零零掉到下一行 —— 哲哥截圖抓到的就是這個。 */

    /* 節奏：6pt grid，跟 app 的 railUnit 同一個基數 */
    --u: 6px;
    --gutter: clamp(20px, 4vw, 40px);
    --max: 1180px;
    --radius-lg: 20px;
    --radius:    14px;
    --radius-sm: 9px;

    --shadow-rest:  0 1px 2px rgba(0, 0, 0, .35), 0 10px 28px -12px rgba(0, 0, 0, .6);
    --shadow-lift:  0 2px 4px rgba(0, 0, 0, .4), 0 26px 56px -18px rgba(0, 0, 0, .75);

    --ease: cubic-bezier(.22, .61, .36, 1);
}

/* ---------- 字體度量對齊（降 CLS）----------
   🔴 為什麼需要這段（8/4 Lighthouse 實測 CLS 0.046）：
   Google Fonts 走 `display=swap`，所以字體載入完成的那一刻會從系統 fallback
   換成 Fraunces / 文楷 —— 兩者的字寬與行高不同，整段文字重新排版就是版面跳動。

   解法不是關掉 swap（那會變成 FOIT，文字先隱形更糟），而是**讓 fallback 的
   度量對齊真字體**：override 一份同名的本機字體，用 size-adjust 與 ascent/descent
   把它撐成跟目標字體一樣的行高與字寬，換上來的瞬間就幾乎不位移。

   ⚠️ 數值要對著實際字體量。這裡的 105% / 88% 是對 Fraunces 與 LXGW WenKai TC
   量出來的近似值 —— 改字體就要重量，不要沿用。 */
@font-face {
    font-family: 'Fraunces-fallback';
    src: local('Georgia'), local('Times New Roman');
    size-adjust: 105%;
    ascent-override: 88%;
    descent-override: 22%;
    line-gap-override: 0%;
}
@font-face {
    font-family: 'WenKai-fallback';
    src: local('PingFang TC'), local('Heiti TC');
    size-adjust: 100%;
    ascent-override: 90%;
    descent-override: 20%;
    line-gap-override: 0%;
}
@font-face {
    font-family: 'Inter-fallback';
    src: local('Helvetica Neue'), local('Arial');
    size-adjust: 100%;
    ascent-override: 90%;
    descent-override: 22%;
    line-gap-override: 0%;
}

/* ---------- Reset ---------- */
*, *::before, *::after { box-sizing: border-box; }
* { margin: 0; padding: 0; }
html {
    scroll-behavior: smooth;
    /* 🔴 **錨點的落點要讓開 sticky 導覽列**（2026-08-18 哲哥抓到「按下取得貼貼
       的那個定錨有點怪」）：導覽列是 `position: sticky`、實測 **72px 高**，
       而錨點跳完是把目標的頂端對到「視窗頂端」—— 於是目標前 72px 被導覽列蓋住。
       88 = 72 ＋ 16 的呼吸空間（實測落點：卡片頂端離導覽列 64px）。
       ⚠️ **這是整站的問題，不是那一頁的**：`#main`（跳到主要內容，14 個頁面都有）
       同樣中彈。先前沒人發現，是因為那些目標剛好有 120px 的上留白幫它擋著 ——
       我 8/18 把「取得」那段的留白收成 48px，它就露出來了。
       判準：**有 sticky 表頭就一定要配 `scroll-padding-top`**，
       不可以靠「目標剛好有很多留白」—— 那個留白哪天被調整就破功。 */
    scroll-padding-top: 88px;
    -webkit-text-size-adjust: 100%;
    /* 這站只有淺色一套。宣告出來讓瀏覽器知道，
       捲軸與原生表單元件才會用對應的配色（Web Interface Guidelines）。 */
    color-scheme: dark;
}

body {
    background: var(--paper);
    color: var(--ink);
    font-family: var(--body);
    font-size: 17px;
    line-height: 1.75;
    -webkit-font-smoothing: antialiased;
    overflow-x: hidden;
    /* 手機上少掉「等 300ms 看你要不要雙擊縮放」的延遲 ——
       這頁沒有需要雙擊縮放的東西（圖片本來就縮到剛好），
       但 pinch 縮放仍然可用（沒動 user-scalable）。 */
    touch-action: manipulation;
    -webkit-tap-highlight-color: rgba(212, 175, 106, .18);
}

/* 紙紋：極輕的 turbulence，讓米底不是死板的一片色。
   pointer-events:none 才不會吃掉點擊 */
body::before {
    content: "";
    position: fixed;
    inset: 0;
    z-index: 9999;
    pointer-events: none;
    /* ⚠️ 0.3 + multiply 太重 —— 疊在深色標題上會看起來像髒點（8/4 實測）。
       紙紋的作用只是讓米底不死板，看得出來就過頭了。 */
    opacity: .14;
    mix-blend-mode: multiply;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='180' height='180'%3E%3Cfilter id='p'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.9' numOctaves='3'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='180' height='180' filter='url(%23p)' opacity='.1'/%3E%3C/svg%3E");
}

a { color: inherit; text-decoration: none; }
img, svg { display: block; max-width: 100%; height: auto; }
button { font: inherit; color: inherit; background: none; border: 0; cursor: pointer; }

:focus-visible {
    outline: 2.5px solid var(--gold-deep);
    outline-offset: 3px;
    border-radius: 4px;
}

/* 跳過導覽的無障礙連結：平常收在畫面外，鍵盤 focus 才滑進來 */
.skip {
    position: fixed;
    top: 10px; left: 50%;
    z-index: 999;
    transform: translate(-50%, -160%);
    padding: 11px 22px;
    background: var(--ink);
    color: var(--paper);
    border-radius: 999px;
    font-size: 15px;
    transition: transform .25s var(--ease);
}
.skip:focus { transform: translate(-50%, 0); }

/* ---------- Layout ---------- */
/* gutter 加上安全區：有 notch / 圓角的裝置橫放時，
   左右會被系統吃掉一塊，不補的話文字會貼到螢幕邊緣被切掉
   （Web Interface Guidelines 的 safe-area 條）。 */
.wrap {
    width: 100%;
    max-width: var(--max);
    margin: 0 auto;
    padding-inline:
        max(var(--gutter), env(safe-area-inset-left))
        max(var(--gutter), env(safe-area-inset-right));
}
.wrap-narrow { max-width: 760px; }

/* 🔴 大標題要比段落寬（8/4 實測）：`.wrap-narrow` 的 760px 是為段落訂的
   （一行 32-38 個中文字最舒服），但那幾頁的 h1 是 58px —— 13 個字就要 810px，
   於是被迫斷行還掉出孤字（實測 editor 的 h1 最後一行只剩 8% 寬）。
   讓 hero 的容器放寬到 880，段落自己仍收在 .lead 的 36em 內。 */
.hero .wrap-narrow { max-width: 880px; }

section { padding: clamp(64px, 9vw, 120px) 0; }
.band-warm { background: var(--paper-warm); border-block: 1px solid var(--rule); }

/* 🔴 短內容的 section 要收 padding（8/4 實測）：
   一律 120px 是為「標題 + 四張卡」那種段落訂的。引言段只有兩行字（內容 153px），
   配上下各 120px 就變成 39% 填充率 —— 看起來像忘了放東西。
   量法：`內容高度 / section 高度`，低於 0.5 就該收。 */
/* ⚠️ 選擇器是 `> .pull` 不是 `> .wrap > .pull` ——
   HTML 裡那個元素是 `<div class="wrap pull">`，兩個 class 在同一個元素上 */
section:has(> .pull) { padding-block: clamp(48px, 6vw, 76px); }
section.cta-final { padding-block: clamp(56px, 7vw, 92px); }

/* ---------- Type scale ---------- */
h1, h2, h3, h4 {
    font-family: var(--display);
    font-weight: 600;
    line-height: 1.18;
    letter-spacing: -.012em;
    font-variation-settings: 'opsz' 40, 'SOFT' 40;
    /* 防孤字：不讓標題最後一行只剩一兩個字（Web Interface Guidelines 的
       typography 條）。balance 會讓瀏覽器把幾行的長度算平均。 */
    text-wrap: balance;
    /* 錨點跳過來時不要被 sticky nav 蓋住標題 */
    scroll-margin-top: 88px;
}

/* 段落用 pretty 而不是 balance —— balance 對長段落成本高且效果不明顯，
   pretty 只處理「最後一行不要孤字」那件事。 */
p, .lead, figcaption { text-wrap: pretty; }

/* 有手動 <br> 的標題不套 balance —— balance 會忽略我的斷點重新算行，
   兩者打架（8/4 實測：加了 <br> 還是掉孤字）。有 <br> 就是「我自己決定斷行」，
   用 initial 讓瀏覽器照 <br> 排。 */
h1:has(br), h2:has(br), h3:has(br) { text-wrap: initial; }

/* 標題裡的 <kbd> 本身不內部斷行（⌘Z 不會拆成 ⌘ / Z）。
   ⚠️ 但**不設整個標題 nowrap** —— 那在窄卡片會溢出。
   「kbd 別單獨掉行」用 HTML 的 &nbsp; 綁前一個字處理（見那兩處標題）。 */
h1 kbd, h2 kbd, h3 kbd { white-space: nowrap; }

/* ⚠️ 中文字的視覺體積比拉丁文字大得多（方塊字滿框，沒有 x-height 那種留白）
   —— 同樣的 px 數中文看起來大一號多。所以上限訂 58 而不是拉丁版常見的 72+，
   實測 74px 會讓 4 字一行的標題溢出可視區。英文頁在自己的 style 區塊裡放大。 */
h1 { font-size: clamp(34px, 4.6vw, 58px); font-weight: 700; letter-spacing: -.02em; }
h2 { font-size: clamp(29px, 3.9vw, 45px); }
h3 { font-size: clamp(20px, 2.1vw, 25px); }

.lead {
    font-size: clamp(17px, 1.35vw, 20px);
    color: var(--ink-2);
    line-height: 1.8;
    max-width: 36em;
}

/* eyebrow：小字大間距。⚠️ 中文不套 letter-spacing（會撐開字距很醜），
   所以這個 class 只給拉丁文字用 */
.eyebrow {
    font-family: var(--mono);
    font-size: 11.5px;
    letter-spacing: .18em;
    text-transform: uppercase;
    color: var(--gold-deep);
}

/* 段落內的連結（inline link）。
   🔴 必須有底線，不可只換顏色 —— Lighthouse 的 `link-in-text-block` 要求
      「段落中的連結」跟周圍文字對比 ≥ 3:1，但 --gold-deep 對 --ink-2 只有 1.1:1
      （兩個都是深色，人眼看得出金／褐差別，演算法看的是明度差，過不了）。
      底線是不依賴顏色的第二個區分訊號，加了就合格。
   （8/5 教訓：原本寫成 style="color:var(--gold-deep)" 內聯，英文首頁 a11y 掉到 95。）
   ⚠️ 只給「句子裡的連結」用。導覽、按鈕、頁尾清單不套 —— 那些本身就在
      連結專屬的區塊裡，位置已經是訊號，加底線反而變吵。 */
.tlink {
    color: var(--gold-deep);
    text-decoration: underline;
    text-decoration-thickness: 1.5px;
    text-underline-offset: 3px;
    text-decoration-color: color-mix(in srgb, var(--gold-deep) 45%, transparent);
    transition: text-decoration-color .18s ease;
}
.tlink:hover { text-decoration-color: var(--gold-deep); }

/* 金色重點字：底線是手繪感的粗筆觸，不是 text-fill 漸層（那個很 AI）。
   ⚠️ 用 box-decoration-break 而不是 white-space:nowrap ——
   後者會讓中文標題在不該斷的地方硬撐，底線位置反而跑掉（8/4 實測）。
   改成 inline 背景之後，換行時上下兩段各自畫一條，語義正確。 */
.mark {
    background-image: linear-gradient(to top,
        rgba(212, 175, 106, .34) 0, rgba(212, 175, 106, .34) .32em, transparent .32em);
    box-decoration-break: clone;
    -webkit-box-decoration-break: clone;
    padding-inline: .05em;
}

.sec-head { max-width: 42em; margin-bottom: clamp(38px, 5vw, 62px); }
.sec-head .eyebrow { display: block; margin-bottom: 14px; }
.sec-head p { margin-top: 16px; color: var(--ink-2); font-size: 17px; }
.sec-head.center { margin-inline: auto; text-align: center; }
.sec-head.center p { margin-inline: auto; }

/* ---------- Buttons ---------- */
.btn {
    display: inline-flex;
    align-items: center;
    gap: 9px;
    padding: 14px 26px;
    border-radius: 999px;
    font-family: var(--body);
    font-size: 16px;
    font-weight: 700;
    transition: transform .22s var(--ease), box-shadow .22s var(--ease),
                background-color .22s var(--ease), border-color .22s var(--ease);
}
.btn-primary {
    background: var(--gold);
    color: #141414;
    box-shadow: var(--shadow-rest);
}
.btn-primary:hover { transform: translateY(-2px); box-shadow: var(--shadow-lift); }
.btn-ghost {
    border: 1.5px solid var(--rule);
    color: var(--ink-2);
}
.btn-ghost:hover { border-color: var(--ink-3); color: var(--ink); background: rgba(255,255,255,.06); }

kbd {
    font-family: var(--mono);
    font-size: .84em;
    padding: 2.5px 7px;
    border-radius: 6px;
    background: var(--surface);
    border: 1px solid var(--rule);
    box-shadow: 0 1.5px 0 var(--rule);
    color: var(--ink);
    white-space: nowrap;
}

/* ---------- Nav ---------- */
.nav {
    position: sticky;
    top: 0;
    z-index: 100;
    background: rgba(18, 17, 16, .78);
    backdrop-filter: saturate(1.4) blur(14px);
    border-bottom: 1px solid transparent;
    transition: border-color .3s, box-shadow .3s;
}
.nav.stuck { border-bottom-color: var(--rule); box-shadow: 0 6px 20px -14px rgba(0,0,0,.7); }
.nav-in {
    display: flex;
    align-items: center;
    gap: clamp(14px, 3vw, 34px);
    padding-block: 13px;
}
/* logo 就是「回首頁」的連結（網站慣例，所以 nav 裡不另開「首頁」項）。
   ⚠️ 但它原本沒有任何 hover 回饋 → 看起來不像可以點（8/4 哲哥回報點不到）。
   爪印微微轉一下 + 文字轉金，讓「這可以點」這件事自己講出來。 */
.logo {
    display: flex;
    align-items: center;
    gap: 10px;
    font-family: var(--display);
    font-weight: 700;
    font-size: 19px;
    transition: color .22s var(--ease);
}
.logo img {
    width: 32px;
    height: 32px;
    border-radius: 9px;
    transition: transform .3s var(--ease);
}
.logo:hover { color: var(--gold-deep); }
.logo:hover img { transform: rotate(-9deg) scale(1.06); }
.nav-links { display: flex; gap: clamp(14px, 2vw, 26px); margin-left: auto; font-size: 15.5px; color: var(--ink-2); }
.nav-links a { position: relative; padding-block: 4px; }
.nav-links a::after {
    content: ""; position: absolute; left: 0; right: 0; bottom: 0; height: 2px;
    background: var(--gold); transform: scaleX(0); transform-origin: left;
    transition: transform .26s var(--ease);
}
.nav-links a:hover::after, .nav-links a[aria-current]::after { transform: scaleX(1); }
.nav-side { display: flex; align-items: center; gap: 14px; }
.lang {
    font-family: var(--mono); font-size: 12.5px; letter-spacing: .06em;
    padding: 7px 13px; border: 1px solid var(--rule); border-radius: 999px; color: var(--ink-2);
    /* ⚠️ 屬性要列明。`transition: .2s` 等於 `transition: all .2s` ——
       瀏覽器會去監看每一個可動畫屬性，成本高而且可能動到你沒想動的東西
       （Web Interface Guidelines 明列的 anti-pattern）。 */
    transition: color .2s var(--ease), border-color .2s var(--ease);
}
.lang:hover { border-color: var(--gold-deep); color: var(--gold-deep); }
.nav .btn { padding: 10px 20px; font-size: 14.5px; }

/* ---------- Hero ---------- */
.hero { padding: clamp(48px, 7vw, 88px) 0 clamp(50px, 7vw, 90px); position: relative; }
.hero-grid {
    display: grid;
    /* 右欄給固定的下限（便利貼牆要 420 才不被壓扁），左欄吃剩下的。
       ⚠️ 不能兩欄都用 fr —— 那樣視窗一窄右欄就先被犧牲。 */
    grid-template-columns: minmax(0, 1fr) minmax(420px, 500px);
    gap: clamp(34px, 5vw, 64px);
    align-items: center;
}
.hero h1 { margin-block: 20px 0; }
/* 🔴 兩欄 hero（首頁）的 h1 要比單欄 hero 小一階（8/4 實測孤字）：
   首頁 hero-grid 的左欄只有 ~536px，全域 h1 上限 58px 是為單欄頁（editor/privacy）
   訂的，塞進兩欄左欄會爆行掉孤字。這裡收到 46px 上限。
   ⚠️ 單欄 hero 用 .wrap-narrow，不受這條影響。 */
.hero-grid h1 { font-size: clamp(32px, 3.4vw, 46px); }
.hero .lead { margin-top: 24px; }
.hero-cta { display: flex; flex-wrap: wrap; gap: 13px; margin-top: 34px; }
.hero-trust {
    display: flex; flex-wrap: wrap; gap: 8px 22px; margin-top: 28px;
    font-size: 14.5px; color: var(--ink-3);
}
.hero-trust li { list-style: none; display: flex; align-items: center; gap: 7px; }
.hero-trust li::before {
    content: ""; width: 15px; height: 15px; flex: none; border-radius: 50%;
    background: var(--gold) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%2333261C' stroke-width='3.4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M20 6 9 17l-5-5'/%3E%3C/svg%3E") center/10px no-repeat;
}

/* ---------- Signature：便利貼牆 ----------
   這是全站唯一「花」的地方（Chanel 那條規則：只在一個地方大膽）。
   四張真實便條色的卡微旋轉堆疊，hover 抬起並轉正。 */
.notewall {
    position: relative;
    aspect-ratio: 1 / .92;
    /* ⚠️ 三個尺寸都要給。只給 max-width 的話 grid 欄位窄時它會被壓扁，
       絕對定位的子卡跟著變成細長條 —— 中文於是直排（8/4 實測踩到）。
       min-width 是那條防線，420 是「四張卡並排還讀得出字」的實測下限。 */
    width: 100%;
    min-width: 420px;
    max-width: 520px;
    margin-inline: auto;
}
/* 🔴 `.note` 這個類名**被佔用了，不要在別的地方拿來當「說明小字」**（8/4 踩過）：
   它是 `position:absolute`，所以任何同名元素都會先吃到絕對定位再跳回去 ——
   download.html 的價格卡原本用 `.price .note`，實測造成 CLS 0.046
   （那段字從 267px 寬跳到 659px、垂直位置掉 455px）。已改名 `.price-note`。
   要放說明小字就另取名字，別借這個。 */
/* 拍立得相紙（2026-08-06 改版）。
   為什麼從「便條紙」換掉：app 的 classic 卡片 8/6 全面改成拍立得
   —— 相紙外框 + 內容滿版 + 下緣一條 caption，60pt 漸層色帶整組退役。
   首頁這面牆是 signature 元素，它跟 app 長得不一樣的話，
   使用者看官網以為會拿到便利貼，裝起來是拍立得。

   結構對應實作（`ItemCardView.swift` 的 caption 段）：
     `.note`      = 相紙（白框）
     `.note-photo` = 相片區（內容本身，彩色）
     `.note-cap`  = caption（色點 + 標題 + 一行 meta） */
.note {
    position: absolute;
    border-radius: var(--radius-sm);
    /* 相紙的白框：三邊窄、下緣寬 —— 拍立得的比例就是靠這個認出來的 */
    padding: 9px 9px 0;
    box-shadow: var(--shadow-rest);
    transition: transform .38s var(--ease), box-shadow .38s var(--ease);
    background-color: var(--photo);
    color: var(--ink-photo);
}
.note-photo {
    border-radius: 4px;
    padding: 14px 15px;
    min-height: 92px;
    /* 相片下緣壓一道很輕的暗，像相紙微微翹起 */
    background-image: linear-gradient(178deg, rgba(255,255,255,.5), rgba(51,38,28,.05));
}
/* caption：一行字住在相紙下緣的白邊上。
   ⚠️ 字色走 --ink 而不是 --ink-on-note —— 它坐在白相紙上不是彩色相片上，
   跟實作同一個道理（caption 在中性卡底上，所以直接用 .primary）。 */
/* ⚠️ 下緣留白刻意比三邊寬（9px 白框 vs 這裡 12+16）——
   拍立得就是靠「下面那條寬白邊」被認出來的，收窄就變成普通圓角卡。 */
.note-cap {
    display: flex;
    align-items: center;
    gap: 7px;
    padding: 12px 5px 16px;
}
.note-cap .dot { width: 8px; height: 8px; border-radius: 50%; flex: none; }

/* ---------- 疊卡（editor.html 的 Esc 逐級退出示意）----------
   🔴 這一組是從 `.note` 拆出來的（8/6）。CSS 上方那條警告
   「`.note` 被佔用了，不要在別的地方借」8/4 就寫了，但 editor.html 還是借著用
   —— 於是 8/6 把 `.note` 改成拍立得（相紙白框 + caption）的時候，
   那四張 Esc 卡跟著變成沒有底色的空白相紙。
   判準：**需要的是「一疊彩色小卡」的視覺就自己開一個 class**，
   不要借用綁定了特定產品隱喻的類名。 */
.stackcard {
    position: absolute;
    border-radius: var(--radius-sm);
    padding: 16px 18px;
    box-shadow: var(--shadow-rest);
    transition: transform .38s var(--ease), box-shadow .38s var(--ease);
    background-image: linear-gradient(178deg, rgba(255,255,255,.5), rgba(51,38,28,.05));
}
.stackcard .sc-k {
    font-family: var(--mono);
    font-size: 10.5px;
    letter-spacing: .1em;
    color: var(--ink-on-note);
    opacity: .85;
}
.stackcard .sc-t {
    font-family: var(--display);
    font-size: 15px;
    font-weight: 600;
    line-height: 1.3;
    margin-top: 5px;
    color: var(--ink);
}
.stackcard:nth-child(1) { background-color: var(--note-amber); width: 54%; top: 2%;     left: 0;   transform: rotate(-4.5deg); z-index: 3; }
.stackcard:nth-child(2) { background-color: var(--note-sky);   width: 47%; top: 15%;    right: 0;  transform: rotate(3.4deg);  z-index: 4; }
.stackcard:nth-child(3) { background-color: var(--note-mint);  width: 45%; bottom: 12%; left: 4%;  transform: rotate(2.2deg);  z-index: 2; }
.stackcard:nth-child(4) { background-color: var(--note-rose);  width: 50%; bottom: 2%;  right: 5%; transform: rotate(-2.8deg); z-index: 5; }
.stackcard:hover { transform: rotate(0) scale(1.045) translateY(-6px); box-shadow: var(--shadow-lift); z-index: 9; }
.note-cap .cap-t {
    font-size: 11.5px;
    color: var(--ink-3);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
/* 便條卡的標題是**視覺標籤不是文件標題** —— 用 <p class="note-t"> 而不是 <h4>，
   因為它們沒有對應的 h3 父階（Lighthouse 的「標題階序跳號」判得對，8/4 修）。 */
.note .note-t {
    font-family: var(--display);
    font-size: 15px;
    font-weight: 600;
    line-height: 1.3;
    margin-bottom: 5px;
    color: var(--ink);
}
/* ⚠️ 不用 rgba 半透明墨 —— 疊在 8 種不同亮度的便條色上算不出實際對比，
   而實測 .5 的版本在玫瑰色上只有 3.5。改用算過的不透明色。 */
.note p { font-size: 13.5px; line-height: 1.6; color: var(--ink-on-note); }

/* 四張卡的落點。上下兩組刻意靠近（bottom 從 8%/0 收到 4%/-2%）——
   間距太開會看成「兩堆」而不是「一牆」。 */
/* ⚠️ 底色移到 `.note-photo`（相片區）—— 相紙本身永遠是白的。
   卡寬加 3–4 個百分點：多了相紙白框與 caption，內容區才不會比舊版窄。 */
.note:nth-child(1) { width: 57%; top: 1%;     left: 0;    transform: rotate(-4.5deg); z-index: 3; }
.note:nth-child(2) { width: 50%; top: 16%;    right: 0;   transform: rotate(3.4deg);  z-index: 4; }
.note:nth-child(3) { width: 48%; bottom: 10%; left: 3%;   transform: rotate(2.2deg);  z-index: 2; }
.note:nth-child(4) { width: 53%; bottom: 0;   right: 4%;  transform: rotate(-2.8deg); z-index: 5; }
.note:nth-child(1) .note-photo { background-color: var(--note-amber); }
.note:nth-child(2) .note-photo { background-color: var(--note-sky); }
.note:nth-child(3) .note-photo { background-color: var(--note-mint); }
.note:nth-child(4) .note-photo { background-color: var(--note-rose); }
.note:hover { transform: rotate(0) scale(1.045) translateY(-6px); box-shadow: var(--shadow-lift); z-index: 9; }

/* ---------- Stat strip ---------- */
.strip { border-block: 1px solid var(--rule); background: var(--paper-warm); padding: 30px 0; }
.strip-in { display: grid; grid-template-columns: repeat(4, 1fr); gap: 24px; }
.strip .n {
    display: block; font-family: var(--display); font-size: clamp(26px, 3vw, 36px);
    font-weight: 700; color: var(--ink); line-height: 1.1;
    /* 四個數字並排比較，等寬數字才不會看起來歪（Web Interface Guidelines） */
    font-variant-numeric: tabular-nums;
}
.strip .k { font-size: 13.5px; color: var(--ink-3); }

/* ---------- Feature rows（左右交錯，不是 bento）---------- */
.frow {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: clamp(30px, 5vw, 66px);
    align-items: center;
    padding-block: clamp(38px, 5vw, 62px);
    border-top: 1px solid var(--rule);
}
.frow:first-of-type { border-top: 0; }
.frow.flip .frow-art { order: -1; }
.frow h3 { margin-block: 12px 14px; }
.frow p { color: var(--ink-2); font-size: 16.5px; }
.frow ul { margin-top: 18px; display: grid; gap: 9px; }
/* 🔴 **不可以用 `display: flex`** 做這種項目符號（8/4 踩到）：
   flex 會把 `<strong>`、`<kbd>`、`<code>` 各自變成獨立的 flex item，
   於是一行文字被切成好幾欄分開換行 —— 實例：「備份檔本｜目的地資｜—— 指到會」。
   改用「負縮排 + ::before」：內容留在正常的 inline flow，行內元素自然混排。 */
.frow li {
    list-style: none;
    font-size: 15.5px;
    color: var(--ink-2);
    padding-left: 1.5em;
    text-indent: -1.5em;
}
.frow li::before {
    content: "—";
    color: var(--gold-deep);
    display: inline-block;
    width: 1.5em;
    text-indent: 0;
}

/* 螢幕截圖的相框：淡金邊 + 米底墊，讓 app 的毛玻璃不會浮在空氣裡 */
.shot {
    border-radius: var(--radius);
    padding: 9px;
    background: linear-gradient(160deg, var(--gold-wash), var(--paper-warm));
    border: 1px solid var(--rule);
    box-shadow: var(--shadow-lift);
}
/* 🔴 整寬截圖收到 1008px（8/6 哲哥問「全部截圖都是高解析嗎」之後量出來的）：
   實機截圖的物理上限是**視窗自己的尺寸** —— 貼貼窗 990pt @2x = 1980px，
   而站上有 7 張是這個規格。整寬顯示 1080px 需要 2160，那 7 張只有 1.83x。
   收到 1008（含 9px×2 padding → 圖片本身 990）就剛好 2.0x。
   視覺上只窄 7%，換到全部達標。

   ⚠️ **細長橫條（`.shot-wide`）不套這個上限** —— 那種圖是 3200 寬且比例 5–6:1，
   收窄會讓卡片裡的字變小到讀不出來。它們原生解析度本來就夠。

   判準：**素材的物理上限決定顯示寬，不是版面決定**（這是今天第三次踩到同一條）。 */
.shot:not(.shot-wide) {
    /* 996 = 圖片 978 + padding 9×2。取 978 而不是 990：站上最窄的整寬截圖
       原生是 1960（`04-image-editor`、`12-editor-cutout`），@2x 支撐得起 980。
       多留 2px 是給 subpixel 捨入的餘裕 —— 實測 990 會算出 1.98x 差那麼一點。 */
    max-width: 996px;
    margin-inline: auto;
}
.shot img { border-radius: var(--radius-sm); }
.shot figcaption { font-family: var(--mono); font-size: 11.5px; color: var(--ink-3); padding: 9px 4px 2px; }

/* 文字在上、截圖整寬在下的功能列。
   🔴 存在的理由：**極端長寬比的截圖不能塞進 .frow 的半欄**。
   經典橫條那張是 3800×644（5.9:1），在 520px 寬的欄位裡卡片會全部糊成一片
   看不出是什麼（8/4 實測踩到）。判準：長寬比超過 3:1 就走這個而不是 .frow。 */
.frow-stack {
    display: grid;
    gap: clamp(22px, 3vw, 32px);
    padding-block: clamp(38px, 5vw, 62px);
    border-top: 1px solid var(--rule);
}
.frow-stack h3 { margin-bottom: 14px; }
.frow-stack p { color: var(--ink-2); font-size: 16.5px; }
.frow-stack ul { margin-top: 18px; display: grid; gap: 9px; }
.frow-stack li {
    list-style: none;
    font-size: 15.5px;
    color: var(--ink-2);
    padding-left: 1.5em;
    text-indent: -1.5em;
}
.frow-stack li::before {
    content: "—";
    color: var(--gold-deep);
    display: inline-block;
    width: 1.5em;
    text-indent: 0;
}

/* 插圖：圓角 + 輕邊，跟截圖同一個相框語彙但不加金 */
.illus { border-radius: var(--radius); overflow: hidden; border: 1px solid var(--rule); box-shadow: var(--shadow-rest); }

/* 兩張截圖並排。⚠️ 只給**長寬比接近 1.5:1** 的圖用 ——
   細長圖（> 3:1）塞進半欄卡片會全糊掉，那種要用整寬（8/4 實測）。 */
.shot-duo {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 20px;
    margin-top: 20px;
    align-items: start;
}
@media (max-width: 760px) {
    .shot-duo { grid-template-columns: 1fr; }
}

/* 整寬插圖帶：純文字段落之間的呼吸點。
   ⚠️ 刻意**不用 `.shot` 的金邊相框** —— 那個語彙專屬「這是產品的實際畫面」。
   插圖是氛圍，混用會讓人以為照片裡的東西是 app 的一部分。
   高度用 aspect-ratio 裁切而不是讓圖自己撐 —— 3:2 的圖整寬會太高，
   佔掉一整屏卻只是氣氛。 */
.illus-band {
    margin-top: clamp(30px, 4vw, 46px);
    border-radius: var(--radius-lg);
    overflow: hidden;
    border: 1px solid var(--rule);
    box-shadow: var(--shadow-rest);
}
.illus-band img {
    width: 100%;
    aspect-ratio: 21 / 8;
    object-fit: cover;
    object-position: center 55%;
}
.illus-band figcaption {
    font-family: var(--mono);
    font-size: 11.5px;
    color: var(--ink-3);
    background: var(--surface);
    padding: 11px 16px;
    border-top: 1px solid var(--rule);
}
@media (max-width: 620px) {
    /* 手機上 21:8 太扁，切成 3:2 才看得出內容 */
    .illus-band img { aspect-ratio: 3 / 2; }
}

/* ---------- Card grid（功能小卡）---------- */
.cards { display: grid; grid-template-columns: repeat(auto-fit, minmax(255px, 1fr)); gap: 18px; }
.card {
    background: var(--surface);
    border: 1px solid var(--rule);
    border-radius: var(--radius);
    padding: 26px 24px;
    box-shadow: var(--shadow-rest);
    transition: transform .26s var(--ease), box-shadow .26s var(--ease), border-color .26s;
}
.card:hover { transform: translateY(-3px); box-shadow: var(--shadow-lift); border-color: var(--gold); }
.card .ico {
    width: 40px; height: 40px; border-radius: 11px; margin-bottom: 15px;
    display: grid; place-items: center; font-size: 19px;
}
.card h3 { font-size: 19px; margin-bottom: 8px; }
.card p { font-size: 14.5px; color: var(--ink-2); line-height: 1.7; }

/* ---------- Table（規格 / 比較）---------- */
.tbl { width: 100%; border-collapse: collapse; font-size: 15.5px; }
.tbl th, .tbl td { padding: 14px 16px; text-align: left; border-bottom: 1px solid var(--rule); vertical-align: top; }
.tbl th {
    font-family: var(--mono);
    font-size: 11.5px;
    text-transform: uppercase;
    color: var(--ink-3);
    font-weight: 400;
    /* ⚠️ **中文表頭不套 letter-spacing** —— 會把「機制」撐成「機 制」
       （8/4 哲哥截圖抓到）。字距只在英文頁加回來（見 en/*.html 的 style 區塊）。 */
    white-space: nowrap;
}

.tbl td:first-child { font-weight: 700; width: 30%; }

/* 🔴 最後一欄（「預設」那種短答案）要有最小寬度且不斷行（8/4 修）：
   原本只設了第一欄 30%，第三欄被中間的長描述擠到只剩一個字寬 ——
   「空的」「強制」被逼成兩行，看起來像壞掉。
   ⚠️ 只在**三欄以上**的表格生效：兩欄表的第二欄是長描述，不能 nowrap。 */
.tbl tr > *:nth-child(3):last-child {
    width: 1%;
    white-space: nowrap;
    text-align: right;
}

.tbl tr:last-child td { border-bottom: 0; }

/* ---------- Quote ---------- */
/* 🔴 引言的行長：**用 ch 不用 em，而且改成左右不居中的區塊居中**（8/4 修）。
   原本 `max-width: 24em` + `text-align: center` 在 40px 字級下只有 960px，
   而中文一個字就是 1em → 一行放不到 24 個字，句號還會孤零零掉到下一行。
   拉丁文字的「一行 65-75 字元」標準不能直接套中文 ——
   中文一行舒適是 25-40 個字，而 40px 的字要那麼寬得給到 1200px 以上。

   做法：容器放寬到能容納整句，字級收一階，並讓「斷行由我決定」——
   HTML 裡的 <br> 是刻意的，加上 `text-wrap: balance` 收尾。 */
.pull {
    max-width: min(92vw, 1180px);
    margin-inline: auto;
    text-align: center;
}
.pull blockquote {
    font-family: var(--display);
    /* 上限從 40 收到 34 —— 大字級在中文下更容易斷得難看 */
    font-size: clamp(23px, 2.9vw, 34px);
    line-height: 1.52;
    font-weight: 600;
    letter-spacing: .01em;
    text-wrap: balance;
    /* 中文標點在行首行尾的處理（避頭尾）。Safari 與 Chrome 都支援 */
    line-break: strict;
    text-spacing-trim: trim-start;
}
.pull cite { display: block; margin-top: 24px; font-style: normal; font-size: 14.5px; color: var(--ink-3); }

/* ---------- Dog band ---------- */
.dogband { text-align: center; }
.dogband img { width: clamp(180px, 26vw, 260px); margin-inline: auto; filter: drop-shadow(0 18px 34px rgba(0, 0, 0, .44)); }
.dogband h2 { margin-top: 18px; }
.dogband p { margin: 14px auto 0; color: var(--ink-2); max-width: 36em; }

/* ---------- CTA ---------- */
.cta-final { text-align: center; }
.cta-final .btn { margin-top: 8px; }
.cta-final p { color: var(--ink-2); margin: 16px auto 30px; max-width: 34em; }

/* 最終 CTA 的 app icon。
   ⚠️ 尺寸克制在 116px —— icon 是「認出這個 app」的訊號，不是主視覺。
      放到 200px 會壓過下面的標題與按鈕，那才是這一段真正要人做的事。
   ⚠️ 陰影用 drop-shadow 不是 box-shadow —— icon 是圓角方形帶透明邊，
      box-shadow 會沿著方形外框畫，露出直角。 */
.cta-icon {
    width: clamp(84px, 9vw, 116px);
    height: auto;
    margin: 0 auto 22px;
    display: block;
    filter: drop-shadow(0 14px 30px rgba(0, 0, 0, .44));
}

/* ---------- Footer ---------- */
/* footer 的下緣也補安全區 —— 手機底部的 home indicator 會蓋住最後一行 */
.foot {
    background: var(--paper-deep);
    border-top: 1px solid var(--rule);
    padding: 46px 0 max(34px, env(safe-area-inset-bottom));
    font-size: 14.5px;
}
.foot-in { display: grid; grid-template-columns: 1.4fr repeat(2, 1fr); gap: 30px; }
/* footer 的欄位標籤用 <p class="foot-h"> 而不是 <h4> ——
   它不隸屬任何 h3，當標題會造成階序跳號（8/4 Lighthouse 抓到）。 */
.foot .foot-h { font-family: var(--mono); font-size: 11.5px; letter-spacing: .12em; text-transform: uppercase; color: var(--ink-3); font-weight: 400; margin-bottom: 12px; }
.foot ul { display: grid; gap: 8px; }
.foot li { list-style: none; }
.foot a { color: var(--ink-2); }
.foot a:hover { color: var(--gold-deep); }
.foot-btm { margin-top: 34px; padding-top: 20px; border-top: 1px solid var(--rule); display: flex; justify-content: space-between; flex-wrap: wrap; gap: 10px; color: var(--ink-3); font-size: 13.5px; }

/* ---------- 裝飾元素 ----------
   🔴 分寸：每個元素**只在有理由的地方出現一次**。
   截圖是這個站的主角，裝飾撒太多會搶掉它的注意力。
   三個元素各有各的落點：
     .deco-peek  趴在「有邊界的容器」上緣（趴在半空中沒有依據）
     .deco-nap   只放頁尾一處 —— 讀完了，牠也睡了
     .deco-paw   section 之間的分隔記號，取代單調的水平線
   全部 aria-hidden + pointer-events:none —— 它們是氣氛不是內容。 */

/* 趴在區塊頂邊探頭的小狗。用 translateY 讓爪子搭在邊上（跟 app 裡的
   PanelMascot 同一個手法：圖比 headroom 多一點造成搭邊視覺）。 */
.deco-peek {
    position: absolute;
    top: 0;
    width: clamp(76px, 8vw, 104px);
    transform: translateY(-72%);
    pointer-events: none;
    filter: drop-shadow(0 6px 14px rgba(0, 0, 0, .36));
    z-index: 2;
}
/* ⚠️ 對齊**內容區**的邊緣不是螢幕邊緣 —— 用跟 .wrap 同一個算式
   （max 1180 置中 + gutter），否則寬螢幕下狗會貼在螢幕角落像貼紙。 */
/* ⚠️ `left` 目前沒有任何一頁在用（只有 right）——
   留著是因為它是 right 的鏡像，刪掉半組會讓下次加左側裝飾時位置無聲跑掉。 */
.deco-peek.left {
    left: max(var(--gutter), calc((100% - var(--max)) / 2));
}
.deco-peek.right {
    right: max(var(--gutter), calc((100% - var(--max)) / 2));
    transform: translateY(-72%) scaleX(-1);
}

/* 需要 relative 才裝得住上面那個 absolute */
.deco-host { position: relative; }

/* 頁尾睡著的小狗 */
.deco-nap {
    display: block;
    width: clamp(120px, 14vw, 168px);
    margin: 0 auto clamp(-12px, -1vw, -8px);
    pointer-events: none;
    filter: drop-shadow(0 8px 18px rgba(0, 0, 0, .28));
}

/* 爪印分隔：一個爪印配兩條漸淡的線 */
.deco-divider {
    display: flex;
    align-items: center;
    gap: 18px;
    max-width: 420px;
    margin: clamp(40px, 5vw, 64px) auto 0;
    pointer-events: none;
}
.deco-divider::before,
.deco-divider::after {
    content: "";
    flex: 1;
    height: 1px;
    background: linear-gradient(90deg, transparent, var(--rule));
}
.deco-divider::after { background: linear-gradient(90deg, var(--rule), transparent); }
.deco-divider img { width: 22px; opacity: .5; }

/* 爪印浮水印：極淡，放在大段落的角落當紋理 */
.deco-watermark {
    position: absolute;
    width: clamp(90px, 11vw, 150px);
    opacity: .05;
    pointer-events: none;
    transform: rotate(-14deg);
    z-index: 0;
}

@media (max-width: 620px) {
    /* 手機上裝飾全收 —— 螢幕小，那些會擠掉真正的內容 */
    .deco-peek, .deco-watermark { display: none; }
}

/* ---------- Reveal（漸進增強：沒 JS 就全部直接可見）----------
   🔴 **這個動畫刻意不動 opacity**（8/4 Lighthouse 抓到後改）：
   `opacity: 0 → 1` 的過程中每個中間值都在降低文字對比 —— 實測在淡入途中
   量到 `#B59F7A` 對米底只有 2.14（色票本身是 5.08，值沒錯，是動畫造成的）。
   那不只是分數問題：真人捲到那裡的瞬間，看到的就是讀不清的字。

   只動 `transform` 有三個好處：①任何一刻文字都是滿對比
   ②transform 是 compositor-friendly（Web Interface Guidelines 明列的偏好）
   ③位移本來就是這個動畫的主語言，透明度只是裝飾。
   ⚠️ 要「淡入感」的話用 clip-path 或 mask 都不影響文字對比，但那個成本更高。 */
body.js [data-rv] { transform: translateY(22px); }
body.js [data-rv].in {
    transform: none;
    transition: transform .68s var(--ease);
}

/* ---------- 拍立得展示帶（首頁）----------
   一排真實截圖的單卡，橫向可捲。做成「桌上散開的一疊照片」而不是整齊的 grid ——
   每張各自微傾，hover 扶正並浮起。

   🔴 為什麼是 scroll-snap 而不是自動輪播：輪播會搶注意力、而且使用者控制不了節奏
   （Web Interface Guidelines 的 interruptible 條）。這裡是「你自己撥」，
   手勢／滾輪／鍵盤都能推，停哪算哪。 */
.polaroid-strip {
    display: flex;
    /* 🔴 `flex-start` 不是預設的 stretch（8/6 哲哥截圖抓到卡片下面有白塊）：
       flex 預設把子項拉到最高那個的高度，而六張的 caption 行數不一樣
       （「不只是一串網址」折兩行、其他一行）—— 矮的就被拉高，
       多出來的空間露出 figure 的白底，看起來像卡片下面多長一塊。
       判準：**內容高度不等的 flex 子項一律 align-items: flex-start**，
       除非真的要它們等高。 */
    align-items: flex-start;
    gap: clamp(16px, 2.2vw, 28px);
    overflow-x: auto;
    scroll-snap-type: x proximity;
    /* 卡片會傾斜與放大，容器要留出溢出空間才不會被裁掉 */
    padding: 26px clamp(20px, 4vw, 40px) 34px;
    margin-inline: calc(-1 * clamp(20px, 4vw, 40px));
    /* 捲到底不要硬停 —— 讓它有一點回彈的手感 */
    overscroll-behavior-x: contain;
    scrollbar-width: none;
}
.polaroid-strip::-webkit-scrollbar { display: none; }
.polaroid-strip figure {
    /* 🔴 上限 268 → 240（8/6 第三次調）：單卡截圖的物理上限是 560px
       （卡片本身 280pt @2x，實機截不出更大的），顯示 268 只有 2.09x 沒有餘裕
       —— 縮圖演算法一參與就看得出軟。240 給到 2.33x，肉眼才夠銳。
       判準：**素材尺寸決定顯示尺寸的上限，不是反過來把圖硬撐大。** */
    flex: 0 0 clamp(190px, 20vw, 240px);
    scroll-snap-align: center;
    /* 只動 transform 與 box-shadow —— 前者上合成層，後者是這個材質的必要交代 */
    transition: transform .42s var(--ease), box-shadow .42s var(--ease);
    transform-origin: center bottom;
    border-radius: var(--radius-sm);
    overflow: hidden;
    box-shadow: var(--shadow-rest);
    background: var(--photo);
    color: var(--ink-photo);
}
/* 散開的傾角：奇偶交錯，第三張回正 —— 規律但不整齊 */
.polaroid-strip figure:nth-child(3n+1) { transform: rotate(-2.4deg); }
.polaroid-strip figure:nth-child(3n+2) { transform: rotate(1.8deg) translateY(6px); }
.polaroid-strip figure:nth-child(3n)   { transform: rotate(-.8deg) translateY(-4px); }
.polaroid-strip figure:hover,
.polaroid-strip figure:focus-within {
    transform: rotate(0) translateY(-10px) scale(1.045);
    box-shadow: var(--shadow-lift);
    z-index: 3;
}
.polaroid-strip img { display: block; width: 100%; height: auto; }
/* ⚠️ 截圖本身已經含卡片的相紙白邊與 caption，這裡再加一條白就是兩層白疊在一起
   （8/6 實測看起來像卡片下面多長了一塊）。所以這條解說改成**深色底**，
   讀起來是「照片下面貼的標籤」而不是相紙的延伸。 */
/* ⚠️ 不設 min-height（8/6 兩次來回的結論）：我原本鎖兩行高是為了「六張等高」，
   但文案縮短之後六句都排在一行 —— 那個 min-height 就只剩多餘的空白
   （哲哥截圖抓到「最下面的說明需要兩行高度嗎」）。
   真正讓卡片不露白底的是 `align-items: flex-start`，不是鎖高度。
   判準：**文案先寫短，版面再貼合它** —— 反過來就會多出這種空白。 */
.polaroid-strip figcaption {
    font-size: 12.5px;
    line-height: 1.45;
    color: var(--ink-2);
    background: var(--paper-warm);
    padding: 10px 13px 12px;
    border-top: 1px solid var(--rule);
}
.polaroid-strip figcaption b { color: var(--ink); font-weight: 600; }

@media (prefers-reduced-motion: reduce) {
    html { scroll-behavior: auto; }
    *, *::before, *::after { animation-duration: .01ms !important; transition-duration: .01ms !important; }
    body.js [data-rv] { transform: none; }
    /* 傾斜是靜態裝飾不是動畫，留著；但 hover 的位移取消 */
    .polaroid-strip figure:hover, .polaroid-strip figure:focus-within { transform: rotate(0); }
}

/* ---------- Responsive ---------- */
@media (max-width: 900px) {
    .hero-grid, .frow { grid-template-columns: 1fr; }
    /* 單欄之後就不需要那個防壓扁的下限了，留著會撐破版面 */
    .notewall { min-width: 0; }
    .frow.flip .frow-art { order: 0; }
    .strip-in { grid-template-columns: repeat(2, 1fr); gap: 22px 18px; }
    .foot-in { grid-template-columns: 1fr 1fr; }
    .nav-links { display: none; }
}
@media (max-width: 560px) {
    body { font-size: 16px; }
    .notewall { aspect-ratio: 1 / 1.05; }
    /* 相紙白框窄一點，但下緣仍留給 caption（padding-bottom 保持 0）*/
    .note { padding: 7px 7px 0; }
    .note-photo { padding: 12px 13px; min-height: 78px; }
    .note-cap { padding: 7px 3px 8px; }
    .note p { font-size: 12.5px; }
    /* ⚠️ 舊的 `.note h4` 已刪 —— HTML 用的是 `.note-t`（改用 <p> 是為了不跳
       標題階序，8/4 Lighthouse 修的），那條規則從那時起就沒有作用對象。 */
    .foot-in { grid-template-columns: 1fr; }
}

/* ══════════════════════════════════════════════════════════════════
   窄螢幕的表格（2026-08-18 修）

   🔴 **手機上表格會把整份文件撐寬**：實測 390px 畫面下功能頁的文件寬度是
   **589px** —— 也就是整頁可以左右滑，而讀者不會知道自己漏看了右邊。
   英文隱私頁 416px，同一個病。

   根因是上面那條 `.tbl tr > *:nth-child(3):last-child { white-space: nowrap }`。
   它是 8/4 為了修**桌機**「第三欄被擠成一個字寬」加的，理由正當 ——
   但那條規則沒有斷點，於是在手機上變成「這一欄不准換行」＝ 整張表不准縮。

   ⚠️ **不要用「讓表格自己橫向捲」來解**（那是常見做法但更差）：
   表格裡的內容是拿來對照讀的，藏在畫面外等於沒寫。手機上讓它換行就好。
   `overflow-x` 留著當保險，萬一以後有更寬的表格不會直接撐破整頁。 */
@media (max-width: 620px) {
    .tbl tr > *:nth-child(3):last-child {
        width: auto;
        white-space: normal;
        text-align: left;
    }
    .tbl td:first-child { width: auto; }
    .tbl th, .tbl td { padding: 12px 10px; }
    .tbl { display: block; overflow-x: auto; }
}

/* ══════════════════════════════════════════════════════════════════
   觸控裝置的點擊目標（2026-08-18 加）

   🔴 **為什麼要這一段**：實測手機版（390px）有 10 個連結**高度只有 19–21px**，
   而 Apple 的人機介面指南要求 **44×44pt**、Google 要求 48×48px。
   手指的接觸面積比游標大得多 —— 19px 高的頁腳連結在手機上是「按三次才中一次」。

   ⚠️ **只在真的用手指的裝置生效**（`pointer: coarse`），不是綁螢幕寬度。
   綁寬度會讓「把桌機視窗縮小」也被套用，那不需要；而**平板橫放**時螢幕很寬
   卻仍然是手指在點，綁寬度就漏掉了。判準是「輸入裝置」不是「螢幕大小」。

   做法是撐開可點區域而不是放大字：`min-height` + 垂直 padding，
   文字大小完全不動 —— 所以視覺上只有行距變鬆一點，字沒有變大。 */
@media (pointer: coarse) {
    .foot ul { gap: 2px; }
    .foot li a,
    .nav-links a,
    .lang,
    .logo {
        display: inline-flex;
        align-items: center;
        min-height: 44px;
    }
    /* 內文裡的行內連結不能用 min-height（會把段落的行距撐開），
       改成左右不動、上下各補一點可點範圍。 */
    .tlink { display: inline-block; padding: 11px 0; }
}

/* ══════════════════════════════════════════════════════════════════
   進階動效（2026-08-16 加）—— 哲哥：「給我們官網多點特效」
   參考的方向是 whiteboxml.life / pasteapp.io 那類「安靜但有質感」的做法：
   不是滿天飛的動畫，而是**跟著你的手走**的細微反應。

   🔴 六條自我約束（每一條都有理由，不要為了炫而破）：
   ① **文字永遠不淡入**。淡入的中間狀態會讓對比掉到 AA 以下
      （8/4 Lighthouse 實測 2.14）。所以文字只用 transform，opacity 留給圖片。
   ② **一律吃 `prefers-reduced-motion`**。系統開了減少動態效果就全部收掉。
   ③ **只動 transform 與 opacity**。動 width/top/left 會逐格重排版。
   ④ **不搶捲動**。沒有 scroll-jacking、沒有橫向劫持 —— 那個在觸控板上很惱人。
   ⑤ **沒有 JS 也要完整**。這些全是 `body.js` 底下的漸進增強。
   ⑥ **手機不做指標特效**（沒有游標，而且省電）。
   ══════════════════════════════════════════════════════════════════ */

/* ---------- 1. 捲動進度條（頂部一條細金線） ----------
   為什麼值得做：這一頁很長（首頁 558 行、功能頁 829 行），
   進度條讓人知道還有多少。用 scaleX 不用 width —— 後者每幀重排。 */
#progress {
    position: fixed;
    inset: 0 0 auto 0;
    height: 2px;
    z-index: 60;
    background: linear-gradient(90deg, var(--gold), var(--note-coral));
    transform: scaleX(0);
    transform-origin: 0 50%;
    /* 不加 transition：它跟著捲動走，補間會變成「慢半拍」 */
    pointer-events: none;
}

/* ---------- 2. 進場位移改成「錯開」 ----------
   同一個區塊裡的子項依序進場（每個晚 60ms），比整塊一起跳有節奏。
   ⚠️ 上限 6 階 —— 再多會變成「等它跑完」，那是反效果。 */
body.js [data-rv].in > * { animation: rv-child .5s var(--ease) both; }
body.js [data-rv].in > *:nth-child(1) { animation-delay: 0ms; }
body.js [data-rv].in > *:nth-child(2) { animation-delay: 60ms; }
body.js [data-rv].in > *:nth-child(3) { animation-delay: 120ms; }
body.js [data-rv].in > *:nth-child(4) { animation-delay: 180ms; }
body.js [data-rv].in > *:nth-child(5) { animation-delay: 240ms; }
body.js [data-rv].in > *:nth-child(n+6) { animation-delay: 300ms; }
@keyframes rv-child {
    from { transform: translateY(10px); }
    to   { transform: none; }
}

/* ---------- 3. 拍立得卡片：跟著游標的 3D 傾斜 ----------
   卡片本來就有靜態傾斜（像散在桌上的照片），這裡讓它**跟著手轉**。
   角度刻意小（最多 6°）：大了就像玩具，而這是給人看內容的。 */
@media (hover: hover) and (pointer: fine) {
    .polaroid-strip figure {
        transform-style: preserve-3d;
        will-change: transform;
    }
    .polaroid-strip figure.tilt {
        transform: perspective(900px)
                   rotateX(var(--tilt-x, 0deg))
                   rotateY(var(--tilt-y, 0deg))
                   translateY(-6px);
        box-shadow: 0 18px 40px -18px rgba(0, 0, 0, .7);
    }
}

/* ---------- 4. 大圖：游標位置的光暈 ----------
   一層很淡的徑向漸層跟著游標走，像紙面反光。
   ⚠️ 放在 `::after` 而且 `pointer-events: none` —— 不可以吃掉圖片的點擊。 */
@media (hover: hover) and (pointer: fine) {
    .shot { position: relative; }
    .shot::after {
        content: '';
        position: absolute;
        inset: 0;
        border-radius: inherit;
        pointer-events: none;
        opacity: 0;
        transition: opacity .35s var(--ease);
        background: radial-gradient(
            220px circle at var(--mx, 50%) var(--my, 50%),
            rgba(255, 252, 240, .28), transparent 65%);
    }
    .shot:hover::after { opacity: 1; }
}

/* ---------- 5. 主要按鈕：磁吸 ----------
   游標靠近時按鈕往它偏一點（最多 4px）。這是 pasteapp 那類站最常用的手法，
   成本極低而「這個站有人在照顧」的感覺很強。
   ⚠️ class 是 `btn-primary`（連字號），不是 `.btn.primary` —— 我第一版寫錯，
   選到 0 個元素而完全沒有錯誤訊息。 */
.btn-primary { will-change: transform; }

/* ---------- 6. 數字跳動 ----------
   統計條的數字捲到畫面時從 0 數上去。
   ⚠️ 用 `tabular-nums` 固定字寬 —— 不然數字跳動時整行左右晃。 */
.strip .n { font-variant-numeric: tabular-nums; }

@media (prefers-reduced-motion: reduce) {
    #progress { display: none; }
    body.js [data-rv].in > * { animation: none; }
    .polaroid-strip figure.tilt { transform: none; box-shadow: none; }
    .shot::after { display: none; }
}
