/* 深色為主，貼近 Steam 的視覺語言。零依賴、零框架。 */

:root {
  --bg: #12141a;
  --bg-soft: #1a1d26;
  --bg-card: #21252f;
  --line: #2d323d;
  --fg: #e6e9ef;
  --dim: #8b93a3;
  --accent: #66c0f4;
  --good: #6ec96e;
  --mixed: #d2a24c;
  --no: #e05b5b;
  --radius: 12px;
  /* 左上角站名列（.site-head）吃掉的高度：padding 16 ＋ 按鈕 37。
     卡片高度的每一條公式都要扣掉它——不扣的話手機版的四顆操作鍵會被頂到摺線下面，
     而「四顆鍵要在第一屏全部看得到」是這個版面的硬性條件。
     改站名列的高度就改這一個數字，不要去動下面那幾條 calc。 */
  --chrome: 53px;
}

* { box-sizing: border-box; }

body {
  margin: 0;
  background: var(--bg);
  color: var(--fg);
  font: 16px/1.6 "Noto Sans TC", "Microsoft JhengHei", system-ui, sans-serif;
  -webkit-font-smoothing: antialiased;
}

/* 1400 是為了種子牆——寬螢幕要排得下 5 欄。滑卡畫面另外壓回 1180，
   那個版面（卡片＋側欄）是照那個寬度調的，拉寬只會讓卡片變得又寬又空。 */
/* 站名／回首頁。跟 #app 同一個寬度與左右留白，這樣它會對齊每個畫面的左邊界。 */
.site-head { max-width: 1400px; margin: 0 auto; padding: 16px 20px 0; }
.btn-home {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  background: none;
  border: 0;
  padding: 4px 0;
  color: var(--fg);
  font-size: 17px;
  font-weight: 700;
  letter-spacing: .2px;
  cursor: pointer;
}
.btn-home:hover { color: var(--accent); }
.btn-home .home-mark { color: #e85a74; font-size: 18px; }
.btn-home:hover .home-mark { transform: scale(1.12); }
.home-mark { display: inline-block; transition: transform .15s; }

#app { max-width: 1400px; margin: 0 auto; padding: 12px 20px 64px; }
.loading, .fatal { color: var(--dim); padding: 40px 0; }
.fatal p { margin: 0 0 16px; }

/* 出處聲明。要看得到但不搶戲——它在種子牆最底下，而那面牆本來就長。 */
.site-footer {
  max-width: 1400px;
  margin: 0 auto;
  padding: 20px 20px 32px;
  color: var(--dim);
  font-size: 12px;
  line-height: 1.7;
  border-top: 1px solid var(--line);
}
.site-footer a { color: var(--dim); }
.site-footer a:hover { color: var(--accent); }
/* 隱私說明推到出處聲明後面、用分隔線隔開。它跟 Steam 那條連結是兩件事：
   一條是條款要求的出處標示，一條是本站自己的揭露，並排會讓人以為都是 Valve 的。 */
.footer-link {
  margin-left: 12px;
  padding-left: 12px;
  border-left: 1px solid var(--line);
  white-space: nowrap;
}
.fatal code { background: var(--bg-card); padding: 2px 6px; border-radius: 4px; }

/* ---------------------------------------------------------- 通用 */

h1 { font-size: 28px; margin: 0 0 8px; letter-spacing: .01em; }
h1 .sub { display: block; font-size: 16px; font-weight: 400; color: var(--dim); margin-top: 4px; }
.lead { color: var(--dim); max-width: 62ch; margin: 0 0 20px; }
.lead b { color: var(--fg); }
.dim { color: var(--dim); }
/* 「符號 ＋ 它的說明」不可拆。中文沒有詞間空白，換行點可以落在任何字之間，於是
   「◯ 有興趣」很容易被切成行尾一個 ◯、下一行才接「有興趣」——那個孤字看起來像亂碼。 */
.nb { white-space: nowrap; }
.intro { margin-bottom: 20px; }

.tag {
  display: inline-block;
  background: var(--bg-soft);
  border: 1px solid var(--line);
  color: var(--dim);
  font-size: 12px;
  padding: 2px 8px;
  border-radius: 999px;
  margin: 0 4px 4px 0;
}
.tag.strong { color: var(--accent); border-color: #35506b; background: #17222e; }

.review.good { color: var(--good); }
.review.mixed { color: var(--mixed); }
/* 契合度：跟「好評率」都是百分比，要明顯區分開，不然玩家會看混 */
.match {
  color: var(--accent);
  border: 1px solid #35506b;
  background: #17222e;
  border-radius: 4px;
  padding: 0 5px;
  font-weight: 600;
}
.price { color: var(--fg); font-variant-numeric: tabular-nums; }

/* 「支援繁體中文」只做顯示，刻意不影響推薦排序——語言不該埋掉好遊戲。 */
.badge-tc {
  font-size: 11px;
  line-height: 1.5;
  padding: 0 6px;
  border-radius: 4px;
  background: #17222e;
  border: 1px solid #35506b;
  color: var(--accent);
  white-space: nowrap;
}

button { font: inherit; cursor: pointer; }

/* ---------------------------------------------------------- 種子牆 */

/* 一排一個標籤群。標題要看得出是分隔，但不能搶戲——玩家要看的是封面，
   不是標題；標題太重會讓人先挑排再挑遊戲。 */
.seed-section { margin-bottom: 26px; }
.seed-section-title {
  font-size: 15px;
  font-weight: 600;
  color: var(--dim);
  margin: 0 0 10px;
  padding-bottom: 6px;
  border-bottom: 1px solid var(--line);
  letter-spacing: .02em;
}

.seed-grid {
  display: grid;
  /* auto-fill + minmax 讓欄數跟著視窗寬度自己長：1024 排 4 欄、1280 排 5 欄、
     1400 以上也是 5 欄（#app 的上限）。
     230 是「還能塞進 5 欄」與「圖不能太小」的折衷——圖改用 header（460×215）之後
     這個寬度仍然清楚，換成 231×87 的 capsule 就會糊。 */
  grid-template-columns: repeat(auto-fill, minmax(230px, 1fr));
  gap: 16px;
}

.seed {
  position: relative;
  /* 這兩行是必要的：.seed 是 .seed-cell 的子元素而不是 grid item，沒有寬度約束的話
     長標題（「魔法門之英雄無敵：上古紀元 Heroes of Might and Magic: Olden Era」）
     會把按鈕撐寬並蓋掉隔壁的格子。 */
  display: block;
  width: 100%;
  padding: 0;
  border: 2px solid var(--line);
  border-radius: var(--radius);
  background: var(--bg-card);
  overflow: hidden;
  text-align: left;
  transition: border-color .15s, transform .15s;
}
.seed:hover { border-color: #46536b; transform: translateY(-2px); }
/* header 的原生比例是 460×215 */
.seed img { width: 100%; aspect-ratio: 460 / 215; object-fit: cover; display: block; }
/* 遊戲名疊在封面下緣，不另外佔一列。
   單獨一列的話每格要多 48px，11 排 × 2 列 = 整面牆多出一千多 px；這面牆本來就長，
   那是最划算的一刀。漸層要夠深，長標題壓在亮色封面上才讀得到。 */
.seed-name {
  position: absolute;
  left: 0; right: 0; bottom: 0;
  padding: 14px 10px 6px;
  font-size: 13px;
  font-weight: 600;
  color: #fff;
  text-shadow: 0 1px 3px rgba(0, 0, 0, .9);
  background: linear-gradient(to top, rgba(6, 10, 15, .95) 40%, transparent);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
/* 選起來的記號是膠囊狀的「✓ 玩過」，不是單獨一個勾（v0.8.11）。理由寫在
   screens.js 的 cell()：一個抽象的勾沒有語意，而這裡是「以為在選下一款要玩的」那批
   玩家點下第一款封面時，唯一會再看到一次的說明。
   寬度要隨字長，所以是 inline-flex 而不是原本固定 24px 的 grid；transform-origin
   靠右上角，放大動畫才不會從格子邊緣往外撐。 */
.seed-check {
  position: absolute;
  top: 8px; right: 8px;
  height: 24px;
  padding: 0 9px;
  border-radius: 999px;
  background: var(--accent);
  color: #0b1218;
  font-size: 12px;
  font-weight: 700;
  display: inline-flex;
  align-items: center;
  gap: 4px;
  white-space: nowrap;
  opacity: 0;
  transform: scale(.6);
  transform-origin: 100% 0;
  transition: opacity .15s, transform .15s;
}
.seed.on { border-color: var(--accent); }
.seed.on .seed-check { opacity: 1; transform: scale(1); }

/* 「你上次選過這款」的小點。跟 .seed-check 同一個角落，選起來時被勾勾接手——
   兩個同時亮著只會讓人分不清哪個是現在選的、哪個是以前選的。
   外圈那道陰影是墊底用的：封面圖片的顏色什麼都有，沒有它點會在亮圖上消失。 */
.seed-mark {
  position: absolute;
  top: 13px; right: 13px;
  width: 10px; height: 10px;
  border-radius: 50%;
  background: var(--accent);
  box-shadow: 0 0 0 3px rgba(8, 14, 20, .75);
}
.seed.on .seed-mark { display: none; }

.seed-hint {
  display: flex;
  align-items: center;
  gap: 8px;
  margin: -12px 0 20px;
  color: var(--dim);
  font-size: 13px;
}
/* 說明文字裡的那顆點沒有封面墊在底下，所以不需要外圈陰影，也不必絕對定位 */
.seed-mark-inline { position: static; box-shadow: none; flex: none; }

/* 格子本身是選取用的按鈕，Steam 連結疊在左上角（右上角被勾選圖示佔了）。
   min-width: 0 讓 grid item 能被壓縮到欄寬，不然長標題會撐爆整列。 */
.seed-cell { position: relative; min-width: 0; }
.seed-link {
  position: absolute;
  top: 6px; left: 6px;
  width: 24px; height: 24px;
  border-radius: 6px;
  background: rgba(8, 14, 20, .82);
  border: 1px solid var(--line);
  color: var(--dim);
  font-size: 13px;
  text-decoration: none;
  display: grid;
  place-items: center;
  opacity: 0;
  transition: opacity .15s, color .15s, border-color .15s;
}
.seed-cell:hover .seed-link { opacity: 1; }
.seed-link:hover { color: var(--accent); border-color: var(--accent); }
/* 觸控裝置沒有 hover，連結一律顯示 */
@media (hover: none) {
  .seed-link { opacity: 1; }
}

/* 六十款的牆很長，開始按鈕固定在畫面底部，不必滾到最下面才能開始 */
.seed-footer {
  position: sticky;
  bottom: 0;
  margin: 8px -20px -64px;
  padding: 14px 20px;
  background: linear-gradient(to top, var(--bg) 55%, transparent);
  display: flex;
  justify-content: flex-end;
}

/* 兩組開關同一列：成人向、語言。窄螢幕自己折行。 */
.filters {
  display: flex;
  align-items: center;
  gap: 10px 24px;
  flex-wrap: wrap;
  margin-bottom: 16px;
}
/* 狀態按鈕，不是勾選框：開著的時候必須一眼看得出來。關掉時是低調的框線鈕，
   開著時是紅底實心鈕——顏色本身就是「現在有成人內容在畫面上」的提示。 */
.adult-toggle {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 8px 14px;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: var(--bg-soft);
  color: var(--dim);
  font-weight: 600;
  cursor: pointer;
  transition: background .15s, border-color .15s, color .15s;
}
.adult-toggle:hover { border-color: var(--dim); color: var(--fg); }
.adult-toggle .shield { font-size: 15px; line-height: 1; }
.adult-toggle.on {
  background: #b3323f;
  border-color: #c94756;
  color: #fff;
}
.adult-toggle.on:hover { background: #c33a48; color: #fff; }

/* 語言篩選。刻意跟成人向開關長得一樣——它們都是「這面牆要放什麼」的開關。 */
.lang-filter { display: inline-flex; align-items: center; gap: 12px; }
.lang-filter label {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  color: var(--fg);
  cursor: pointer;
}
.lang-filter input { width: 18px; height: 18px; accent-color: var(--accent); }
/* 簡中徽章用暖色跟繁中分開，一眼看得出這款只有簡中 */
.badge-sc { background: #2a2318; border-color: #5b4a2a; color: var(--mixed); }

.btn-start {
  background: var(--accent);
  color: #08131c;
  border: 0;
  border-radius: 8px;
  padding: 12px 22px;
  font-weight: 700;
}
.btn-start:hover { background: #7fcdf8; }
.btn-start .count { font-weight: 400; opacity: .75; }

/* ---------------------------------------------------------- 歡迎頁 */

/* 每次進站的第一個畫面。成人內容的詢問併在這一頁最後一步，舊的 .gate-backdrop
   彈窗（蓋在種子牆上的那個）連同 renderAgeGate 一起移除了，只留 .gate-actions ——
   那兩顆按鈕的主次原則沒變：「不要顯示」是預設值，不能被藏起來。

   **窄一點是刻意的**：#app 為了種子牆放到 1400，但這一頁是要讀的，
   行長超過 70ch 就開始難讀。 */
.welcome-screen { max-width: 1000px; margin: 0 auto; }
.welcome-hero { padding: 20px 0 4px; }
.welcome-hero h1 { font-size: 32px; }
.welcome-hero .lead { font-size: 17px; max-width: 56ch; margin-bottom: 0; }

/* 三步驟。桌機橫排三欄——每次進站都要看到這一頁，掃得完比講得細重要。 */
.steps {
  list-style: none;
  margin: 26px 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 18px;
}
.step {
  background: var(--bg-soft);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 16px;
}
/* 示意圖襯一層更深的底，才看得出那是一塊「畫面」而不是頁面本身的一部分。
   **寬度要封頂**：欄寬 321px 時圖會長到 160px 高，三張並排就把下面的「開始」
   整個推到摺線外——而這一頁每次進站都要按一次那顆。封在 220px（圖高 132）。 */
.step-art {
  background: var(--bg);
  border: 1px solid var(--line);
  border-radius: 8px;
  padding: 10px;
  max-width: 220px;
  margin: 0 auto;
}
.step-art svg { display: block; width: 100%; height: auto; }
.step-text h2 {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 17px;
  margin: 14px 0 6px;
}
.step-no {
  flex: none;
  width: 22px; height: 22px;
  border-radius: 50%;
  background: var(--accent);
  color: #08131c;
  font-size: 13px;
  font-weight: 700;
  display: grid;
  place-items: center;
}
.step-text p { margin: 0; color: var(--dim); font-size: 14px; line-height: 1.75; }
.step-text b { color: var(--fg); font-weight: 600; }

/* 示意圖的配色。**要跟真實畫面對得上**——示意圖跟實物長得不一樣的話，
   它就只是裝飾，不如不要放。 */
.wf-plate rect { fill: var(--bg-card); }
.wf-plate-on rect { fill: var(--bg-card); stroke: var(--accent); stroke-width: 2; }
.wf-shade rect { fill: #2b3240; }
.wf-line rect { fill: var(--line); }
.wf-pill rect { fill: var(--accent); }
.wf-pill-text text { fill: #08131c; font-size: 7px; font-weight: 700; text-anchor: middle; }
/* 操作鍵平常是中性底（真實畫面上要 hover 才變綠／紅），但示意圖只有一格靜態畫面，
   得靠顏色一眼分出這是兩個相反的動作，所以字先上色、底維持中性。 */
.wf-btn-no rect, .wf-btn-yes rect { fill: var(--bg-soft); stroke: var(--line); }
.wf-btn-text text { font-size: 10px; font-weight: 700; text-anchor: middle; }
.wf-btn-text text:first-child { fill: var(--no); }
.wf-btn-text text:last-child { fill: var(--good); }
.wf-btn-small rect { fill: var(--bg-soft); stroke: var(--line); }
.wf-badge rect { fill: #1b4b6b; }
.wf-badge-text text { fill: var(--accent); font-size: 8px; font-weight: 700; text-anchor: middle; }

/* 最後一步：開始 ＋ 成人向。兩種狀態（還沒選過＝問句，選過了＝狀態開關）共用這個框。 */
.welcome-go {
  background: var(--bg-soft);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 20px;
}
.welcome-gate h2 { font-size: 19px; margin: 0 0 8px; }
.welcome-gate .lead { margin-bottom: 16px; }
/* 兩顆按鈕分得出主次，但「不要顯示」不能藏起來——它是預設值 */
.gate-actions { display: flex; gap: 10px; flex-wrap: wrap; }
.welcome-actions { display: flex; align-items: center; gap: 14px; flex-wrap: wrap; }
.btn-go { font-size: 17px; padding: 14px 36px; }
.welcome-screen button:disabled { opacity: .55; cursor: default; }

/* 矮視窗（1366×768 的筆電扣掉瀏覽器介面只剩約 660）。這一頁的垂直預算跟滑卡畫面
   一樣是量死的：goTop 一旦超過可視高度，玩家連「下面還有一塊要按的東西」都看不到，
   而他每次進站都得按那一顆。這裡只收留白與字級，不動結構。 */
@media (min-width: 861px) and (max-height: 820px) {
  .welcome-hero { padding: 12px 0 0; }
  .welcome-hero h1 { font-size: 27px; }
  .welcome-hero .lead { font-size: 15.5px; }
  .steps { margin: 18px 0; gap: 14px; }
  .step { padding: 13px; }
  .step-art { padding: 8px; max-width: 200px; }
  .step-text h2 { margin: 10px 0 5px; font-size: 16px; }
  .step-text p { font-size: 13px; line-height: 1.65; }
  .welcome-go { padding: 16px; }
}

/* 再矮一級（1366×768 實測可視高度 660）。上面那一級收完主按鈕仍然差 8px 進不了
   第一屏——**要的是整顆按鈕看得到**，露出上半截等於還是要捲。只收留白，不動字級。 */
@media (min-width: 861px) and (max-height: 700px) {
  .steps { margin: 16px 0 14px; }
  .welcome-gate .lead { margin-bottom: 12px; }
  .welcome-go { padding: 14px 16px; }
}

/* 窄螢幕：三欄直排會變成一條很長的頁，而這一頁每次進站都要看一次。
   改成「小圖在左、字在右」，三步驟仍然在一兩屏之內掃得完。 */
@media (max-width: 860px) {
  .welcome-hero h1 { font-size: 26px; }
  .welcome-hero .lead { font-size: 16px; }
  .steps { grid-template-columns: 1fr; gap: 12px; }
  .step {
    display: grid;
    grid-template-columns: 104px 1fr;
    gap: 14px;
    align-items: start;
    padding: 14px;
  }
  .step-art { padding: 7px; }
  .step-text h2 { margin: 0 0 6px; font-size: 16px; }
  .step-text p { font-size: 13.5px; }
  .btn-go { width: 100%; }
}

/* ---------------------------------------------------------- 滑卡畫面 */

.swipe-screen {
  /* 單欄直向堆疊：進度列 → 卡片 → 操作按鈕 → 口味 → 推薦清單。
     舊版是雙欄（卡片 756px ＋ 側欄 400px），卡片被壓在左欄裡，主圖只剩 278px 高。
     改單欄之後整個寬度都給卡片，主圖與簡介都看得清楚。
     #app 放寬到 1400 是給種子牆用的；這裡壓回 880——再寬只會讓卡片變得又寬又空，
     而且主圖為了維持固定高度會被裁得更扁。
     欄寬還要跟著可用高度收：矮視窗上卡片會被壓到 min-height，這時仍然攤成 880px 寬
     的話，主圖會變成 878×166 的長條（實測 660px 高的視窗）。乘 1.6 讓主圖的寬高比
     大致停在 2.7:1 以內。 */
  max-width: min(880px, calc((100vh - 226px - var(--chrome)) * 1.6));
  margin: 0 auto;
  display: flex;
  flex-direction: column;
  gap: 24px;
}

/* ---- 寬螢幕：把熱門評論放到卡片右邊 ----
   **卡片一個 px 都不讓**。往右借的是本來就空著的地方：#app 上限 1400，而卡片欄只用
   880，1440 的視窗上左右各空著約 240px。這正是它跟當年被否決的雙欄版的差別——
   那個版本是把卡片壓進 756px 的左欄裡，主圖只剩 278px 高。

   **那條「欄寬跟著可用高度收」的限制要留在卡片欄上**（.card-host，不是 .swipe-screen）。
   搬錯地方的話矮視窗上卡片會攤成 880px 寬、主圖變成 878×166 的長條——那是 v0.6.0
   踩過的坑。所以這裡放寬的是外層的 max-width，內層的卡片欄限制原封不動。 */
@media (min-width: 1260px) {
  .swipe-screen { max-width: 1220px; }
  .swipe-main {
    display: flex;
    align-items: flex-start;
    justify-content: center;
    gap: 20px;
  }
  .swipe-main .card-host {
    flex: 1 1 auto;
    min-width: 0;
    max-width: min(880px, calc((100vh - 226px - var(--chrome)) * 1.6));
  }
  /* 高度跟卡片一模一樣，內部自己捲——視覺上就是跟卡片上下對齊的一欄 */
  .swipe-main .reviews-panel {
    flex: 0 0 320px;
    height: min(880px, calc(100vh - 110px - var(--chrome)));
    min-height: 520px;
  }
}
.topbar {
  display: flex;
  align-items: center;
  gap: 14px;
}
.progress-text { color: var(--dim); font-size: 14px; white-space: nowrap; }
.progress-track {
  flex: 1;
  height: 6px;
  background: var(--bg-card);
  border-radius: 999px;
  overflow: hidden;
}
.progress-fill { display: block; height: 100%; background: var(--accent); transition: width .25s; }
.btn-flat {
  background: transparent;
  border: 1px solid var(--line);
  color: var(--dim);
  border-radius: 8px;
  padding: 6px 14px;
}
.btn-flat:hover { color: var(--fg); border-color: #46536b; }

/* 卡片高度與卡片內容無關。不固定的話，有截圖／沒截圖、描述長／短會讓卡片高度差
   一百多 px，下方的 O/X 按鈕就跟著上下跳——答到第五題就會按錯。
   跟著視窗高度算而不是寫死一個常數：要保證的是「不隨卡片內容變」，而視窗高度在
   一輪之中不會變。寫死常數只會讓大螢幕浪費空間、小筆電塞不下操作列。
   110 是上下要留給 #app 留白、進度列與 gap 的量。桌機的操作列在卡片**裡面**
   （標題右邊），所以不必再扣 130px 的按鈕區；窄螢幕在下面的 media query 加回去。 */
.card {
  position: relative;   /* badge-explore 的定位基準 */
  height: min(880px, calc(100vh - 110px - var(--chrome)));
  min-height: 520px;
  display: flex;
  flex-direction: column;
  background: var(--bg-card);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  overflow: hidden;
  user-select: none;
  transition: transform .18s ease-out, opacity .18s;
}
.card.fly-right { transform: translateX(140%) rotate(14deg); opacity: 0; }
.card.fly-left { transform: translateX(-140%) rotate(-14deg); opacity: 0; }
/* 「忽略」往上飛、「已擁有」往下沉：方向要跟 O/X 明顯不同，
   玩家才會意識到那是四種不同的回答 */
.card.fly-up { transform: translateY(-120%) scale(.92); opacity: 0; }
.card.fly-down { transform: translateY(120%) scale(.92); opacity: 0; }

.card-media { position: relative; background: #0d1015; flex: 0 0 auto; }
/* 16:9 是截圖的原生比例（600×338）。這份基底規則是給完成畫面的卡片用的。
   max-height 不能拿掉：img 帶著 height="338" 的屬性，那會蓋掉 aspect-ratio
   （寬高都指定時 aspect-ratio 不生效），拿掉上限的話完成畫面的主圖會從 278 變成
   338px——那個畫面這次不該動。 */
.card-hero {
  width: 100%;
  display: block;
  aspect-ratio: 16 / 9;
  max-height: 278px;
  object-fit: cover;
  background: #0d1015;
}

/* 滑卡的卡片反過來：先把文字區排掉，主圖吃掉剩下的所有空間。
   舊版是給主圖一個 278px 的硬上限、讓簡介去搶剩下的，結果不管螢幕多大主圖都只有
   278px。改成這樣之後 1080p 約 300px、1440p 約 460px，而卡片總高仍然固定。 */
/* flex-basis 一定要是 0 而不是 auto：auto 的話主圖會把自己的內容高度算進基準，
   於是空間不夠時主圖與文字區「按比例」一起縮，文字區被壓掉幾十 px，卡片底部的
   Steam 連結就被 overflow 裁掉。basis 0 ＋ grow 1 的意思才是「把剩下的全給我」。 */
.card > .card-media { flex: 1 1 0; min-height: 150px; overflow: hidden; }
.card .card-hero { height: 100%; max-height: none; aspect-ratio: auto; }

/* 縮圖列給一個寬度上限。單欄之後卡片有 880px 寬，讓 4 張縮圖平分等於每張 213px、
   整條佔掉 130px 高——那是從主圖身上扣的。縮圖只是用來換主圖，不必看得那麼清楚。
   完成畫面的卡片寬 430px，每張只有 105px，本來就吃不到這個上限。 */
.shot-strip {
  flex: 0 0 auto;
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 168px));
  gap: 4px;
  padding: 4px;
  background: #0d1015;
}
.shot {
  padding: 0;
  border: 2px solid transparent;
  border-radius: 4px;
  overflow: hidden;
  background: none;
  line-height: 0;
  transition: border-color .15s, opacity .15s;
  opacity: .6;
}
.shot img { width: 100%; aspect-ratio: 16 / 9; object-fit: cover; display: block; }
.shot:hover { opacity: 1; }
.shot.on { border-color: var(--accent); opacity: 1; }

/* 大寫英文在 12px 沒有 letter-spacing 會擠成一團 */
.badge-explore {
  position: absolute;
  top: 10px; left: 10px;
  background: #17222e;
  border: 1px solid #35506b;
  color: var(--accent);
  font-size: 12px;
  font-weight: 600;
  letter-spacing: .12em;
  padding: 3px 10px;
  border-radius: 999px;
}

.card-body {
  padding: 16px 18px;
  flex: 1 1 auto;
  min-height: 0;
  overflow: hidden;
  display: flex;
  flex-direction: column;
}
/* 滑卡的卡片：文字區**固定高度**，剩下的全給主圖（見上面 .card > .card-media）。
   固定而不是隨內容，是因為操作鍵現在在標題列裡：body 高度一變，標題連同按鈕就
   跟著上下跳，答到第五題就會按錯。內容長短的差異由簡介吸收（它自己會捲）。
   窄螢幕的操作列在卡片外，那裡改回隨內容。 */
/* 280 是照最壞情況算的：標題折到三、四行（「Shadow Tactics: 愛子的抉擇」這種）時，
   標題＋meta＋標籤＋連結就吃掉 258px。給少了會把最底下的 Steam 連結裁掉。 */
.card > .card-body { flex: 0 0 280px; }
.card-title {
  font-size: 21px;
  margin: 0 0 8px;
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
}

/* 標題列：左邊遊戲名，右邊是四顆操作鍵（桌機才會被塞進來，見 main.js 的 drawSwipe）。
   align-items: flex-start 是關鍵——標題折成兩行時按鈕不能跟著往下移。 */
.card-head {
  display: flex;
  align-items: flex-start;
  gap: 16px;
  flex: 0 0 auto;
}
.card-head .card-title { flex: 1 1 auto; min-width: 0; margin: 0 0 8px; }
/* 操作列進到卡片裡就變成一橫排五顆，順序是
   **沒興趣 → 忽略 → 上一步 → 已擁有 → 有興趣**：
   兩個主要動作分站兩端、三個出口收在中間，跟卡片外那兩排的分組是兩回事。
   這個順序**跨越了 DOM 上的兩個 .action-row**，所以用 `display: contents` 把兩層
   row 從盒模型裡拿掉，五顆按鈕直接變成 .swipe-actions 的 flex item，再各給 order。
   （flex 的 order 只在同一個 flex 容器裡有效，不 contents 的話兩排怎麼排都拆不開；
   改 card.js 的 DOM 則會連帶把窄螢幕那兩排也拆了。）
   **五顆等寬**：每顆 flex: 1 1 0 ＋ 統一 gap。舊版第一排 flex 1.4、第二排 1，於是
   第二排三顆擠在 41% 裡，「忽略」「已擁有」被壓到兩個字直排——那是跑版不是層次。
   主次改由配色分（✕／◯ 字亮，另外三顆暗一階，見 .btn-skip / .btn-owned / .btn-undo）。
   窄螢幕（按鈕在卡片外）完全不吃這一段，仍然是上下兩排。 */
.card-head .swipe-actions {
  flex: 0 0 auto;
  width: 58%;
  max-width: 560px;
  flex-direction: row;
  gap: 8px;
  margin-top: 0;
}
.card-head .action-row { display: contents; }
/* 「上一步」在卡片外是刻意窄一半的（flex: 0 0 auto !important），進到標題列裡要跟著
   等寬，所以這裡得用同樣的 !important 解掉。 */
.card-head .swipe-actions button {
  flex: 1 1 0 !important;
  padding: 11px 4px;
  font-size: 15px;
  white-space: nowrap;
}
.card-head .btn-x { order: 1; }
.card-head .btn-skip { order: 2; }
.card-head .btn-undo { order: 3; }
.card-head .btn-owned { order: 4; }
.card-head .btn-o { order: 5; }
/* flex: 0 0 auto 不能少：文字區是固定高度的 flex 容器，meta 沒關掉 shrink 的話空間
   一緊就被壓成 0——實測 390×664 上「好評率／評論數／年份／價格」整排看不見。 */
.card-meta {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  font-size: 14px;
  margin-bottom: 12px;
  flex: 0 0 auto;
}
/* 語言徽章跟遊戲標籤放同一排（DOM 順序見 card.js，徽章固定第一個）。
   改 flex 是為了讓兩種高度不同的膠囊垂直置中；.tag 自己的 margin 換成 gap。 */
.card-tags {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 6px 4px;
  margin-bottom: 12px;
  flex: 0 0 auto;
}
.card-tags .tag { margin: 0; }
/* 徽章原本是塞在標題裡的小字，進到標籤排要跟標籤等高，不然那一排看起來會塌一角。
   只改這裡不動 .badge-tc 本體——推薦清單（results.js）那份仍然是小字版。 */
.card-tags .badge-tc { font-size: 12px; line-height: 1.5; padding: 2px 8px; border-radius: 999px; }
/* 簡介自己可以捲。原本用 -webkit-line-clamp 截到三行，長簡介就被切掉看不完；
   改成獨立的捲動區域後，卡片總高仍固定（按鈕不跳），但內容讀得完。
   min-height 是必要的：完成畫面以外的地方，簡介被其他元素擠成 0 高度就整段消失。 */
.card-desc {
  color: var(--dim);
  font-size: 14px;
  line-height: 1.55;
  margin: 0 0 12px;
  flex: 1 1 auto;
  min-height: 4.6em;
  overflow-y: auto;
  padding-right: 6px;
  scrollbar-width: thin;
  scrollbar-color: var(--line) transparent;
  /* 內容超出時給一點視覺提示，不然看不出還能往下捲 */
  mask-image: linear-gradient(to bottom, #000 calc(100% - 14px), transparent);
}
/* 滑卡的卡片：簡介吃掉文字區裡剩下的空間（文字區本身是固定高的），超過就自己捲。
   min-height 是保險，標題折兩行＋標籤折兩排時簡介才不會被壓成 0。 */
.card .card-desc { flex: 1 1 auto; min-height: 1.6em; }

/* 連結固定在卡片**左下角**，每張卡同一個位置——文字區是固定高度的，margin-top: auto
   把它推到最底下，所以標題折幾行、標籤幾排都不影響它的 Y 座標。 */
.card-link {
  color: var(--accent);
  text-decoration: none;
  font-size: 14px;
  flex: 0 0 auto;
  margin-top: auto;
  align-self: flex-start;
}
.card-link:hover { text-decoration: underline; }

/* 操作列在卡片外面。按鈕位置跟著卡片內容長短上下跳的話，滑到第五張就會按錯。 */
/* 三顆按鈕一列、提示另起一行。高度固定且與卡片內容無關——按鈕上下跳動的話
   滑到第五張就會按錯。 */
.swipe-actions {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin-top: 14px;
}
.action-row { display: flex; align-items: stretch; gap: 12px; }
.action-row button {
  flex: 1;
  border: 1px solid var(--line);
  background: var(--bg-soft);
  color: var(--fg);
  border-radius: 8px;
  padding: 14px;
  font-weight: 600;
  transition: background .15s, border-color .15s, color .15s;
}
/* 第二排是兩個特殊出口，用同一種按鈕樣式但配色低一階——
   看得出是按鈕，又不會跟主要動作搶注意力。
   **選擇器一定要帶 `.action-row`**：`.action-row button` 是 (0,1,1)，只寫 `.btn-skip`
   是 (0,1,0)，權重輸掉。v0.9.4 之前就是只寫類別，實測五顆的 color 全是 --fg——
   「主次由配色分」那條規則從寫下來的那天起就沒有生效過。 */
.action-row .btn-skip,
.action-row .btn-owned { color: var(--dim); }
/* **五顆回答鍵的 hover 一定要關在 `hover: hover` 裡**：觸控裝置沒有真正的 hover，
   點下去之後那個狀態會黏在按鈕上不放（sticky hover）。這個畫面每投一票就整個重畫，
   新按鈕生在同一個位置、手指也還停在那裡，於是**下一張卡一進來就有一顆是亮的**——
   看起來像系統已經幫你選好了，那是這個介面最不該給的暗示。
   按下去的回饋由卡片的飛出動畫承擔，不必再補 :active。 */
@media (hover: hover) {
  .btn-o:hover { background: #17301c; border-color: var(--good); color: var(--good); }
  .btn-x:hover { background: #2e1717; border-color: var(--no); color: var(--no); }
  .btn-skip:hover { background: var(--bg-card); border-color: var(--dim); color: var(--fg); }
  .btn-owned:hover { background: #17222e; border-color: var(--accent); color: var(--accent); }
}
/* 「上一步」是修正用的出口，不是第五種回答：窄一半、顏色再低一階、沒票可退時 disabled。
   給它 flex: 0 0 auto 而不是跟著 flex: 1，這樣「忽略」「已擁有」的寬度不會因為多了
   一顆而縮水——那兩顆的可點面積是量過的。 */
.btn-undo { flex: 0 0 auto !important; padding-left: 12px; padding-right: 12px; }
/* 同上，要帶 .action-row 才蓋得過 `.action-row button` 的 --fg。它比另外兩顆再暗一階。 */
.action-row .btn-undo { color: #6b7688; }
/* 同上：關在 hover: hover 裡，不然觸控點過之後它會一直亮著 */
@media (hover: hover) {
  .btn-undo:hover:not(:disabled) { background: var(--bg-card); border-color: var(--dim); color: var(--fg); }
}
.btn-undo:disabled { opacity: .38; cursor: default; }

/* ---------------------------------------------------------- 熱門評論 */

.reviews-panel {
  display: flex;
  flex-direction: column;
  min-width: 0;
  background: var(--bg-card);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  overflow: hidden;
}
/* **這條不能拿掉**：reviews.js 的分頁是用 `reviewsEl.hidden = true` 切的，但上面那條
   `display: flex` 會蓋掉瀏覽器預設的 `[hidden] { display: none }`（作者樣式一律贏 UA
   樣式，跟權重無關）。少了這條，窄螢幕切到「簡介」時評論面板照樣佔著 25.6px——
   實測簡介因此只剩 22.4px＝一行，補上之後是 46.6px。 */
.reviews-panel[hidden] { display: none; }
.rv-bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  padding: 12px 14px;
  border-bottom: 1px solid var(--line);
  flex: 0 0 auto;
}
.rv-title { font-size: 15px; margin: 0; }
.rv-langs { display: flex; gap: 4px; }
.rv-lang {
  border: 1px solid var(--line);
  background: transparent;
  color: var(--dim);
  border-radius: 999px;
  padding: 3px 12px;
  font-size: 13px;
  cursor: pointer;
}
.rv-lang.on { border-color: var(--accent); color: var(--accent); }
.rv-body { flex: 1 1 auto; overflow-y: auto; padding: 10px 14px 14px; }
.rv-note { color: var(--dim); font-size: 13px; margin: 6px 0; }
.rv-list { list-style: none; margin: 0; padding: 0; }
.rv {
  border: 1px solid var(--line);
  border-radius: 8px;
  padding: 10px 12px;
  margin-bottom: 10px;
  background: rgba(0, 0, 0, .18);
}
.rv-head { display: flex; align-items: baseline; justify-content: space-between; gap: 8px; }
.rv-up { color: var(--good); font-size: 13px; font-weight: 600; }
.rv-down { color: var(--no); font-size: 13px; font-weight: 600; }
.rv-hrs { color: var(--dim); font-size: 12px; white-space: nowrap; }
.rv-text {
  margin: 6px 0 0;
  font-size: 13px;
  line-height: 1.65;
  color: #c3ccd8;
  overflow-wrap: anywhere;
}
.rv-more { color: var(--accent); margin-left: 4px; }
.rv-votes { display: block; margin-top: 6px; color: var(--dim); font-size: 12px; }

/* 窄螢幕：卡片文字區裡的「簡介／熱門評論」分頁。
   分頁列只多 28px，而且吃的是簡介的空間——文字區本身固定高度，所以卡片總高、
   Steam 連結的 Y 座標、四顆操作鍵的位置都不受影響。 */
.card-tabs {
  display: flex;
  gap: 4px;
  margin-bottom: 8px;
  flex: 0 0 auto;
}
.card-tab {
  border: 0;
  border-bottom: 2px solid transparent;
  background: none;
  color: var(--dim);
  font-size: 13px;
  font-weight: 600;
  padding: 2px 8px 4px;
}
.card-tab.on { color: var(--fg); border-bottom-color: var(--accent); }

/* 分頁裡的評論：沒有自己的外框（外框是卡片給的），但要跟簡介一樣自己可捲。 */
.reviews-compact {
  background: none;
  border: 0;
  border-radius: 0;
  overflow: hidden;
  flex: 1 1 auto;
  min-height: 1.6em;
  margin-bottom: 12px;
}
.reviews-compact .rv-bar { padding: 0 0 8px; border-bottom: 0; }
.reviews-compact .rv-title { font-size: 13px; color: var(--dim); }
.reviews-compact .rv-body { padding: 0 6px 0 0; }
.reviews-compact .rv { padding: 8px 10px; margin-bottom: 8px; }

/* ---------------------------------------------------------- 評論彈窗（手機） */

/* 手機（≤860px）的評論是彈窗，不是卡片裡的分頁——那個文字區只有兩百多 px，兩個分頁
   一起分不到 30px，而評論是 3 則 × 200 字。**電腦版的兩種擺法都不受這一段影響。**
   從底部升起而不是置中：拇指構得到的是下半屏，而 ✕ 放在面板自己的標題列上。 */
.rv-modal {
  position: fixed;
  inset: 0;
  z-index: 60;
  display: flex;
  align-items: flex-end;
  background: rgba(4, 7, 11, .74);
}
/* **不能省**，理由跟 .reviews-panel[hidden] 那條一模一樣：上面那行 display: flex 會
   蓋掉瀏覽器預設的 [hidden] { display: none }，少了這條彈窗會永遠開著。 */
.rv-modal[hidden] { display: none; }
.rv-modal .reviews-panel {
  width: 100%;
  max-height: 86svh;
  border-radius: var(--radius) var(--radius) 0 0;
  border-bottom: 0;
}
.rv-modal .rv-body { padding: 12px 14px 20px; }
.rv-close {
  flex: 0 0 auto;
  background: none;
  border: 1px solid var(--line);
  color: var(--dim);
  border-radius: 999px;
  width: 30px;
  height: 30px;
  line-height: 1;
  font-size: 14px;
  cursor: pointer;
}
.rv-close:hover { color: var(--fg); border-color: var(--dim); }

/* 卡片底部那一列：「在 Steam 上查看」靠左，「熱門評論」靠右。只有手機會有這一列
   （`attachReviewsModal` 建的），它比單獨一條連結只高 4px，而換掉的分頁列是 36px。 */
.card-foot {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  margin-top: auto;
  flex: 0 0 auto;
}
.card-foot .card-link { margin-top: 0; }
.btn-rv-open {
  flex: 0 0 auto;
  background: var(--bg-soft);
  border: 1px solid var(--line);
  color: var(--dim);
  border-radius: 999px;
  padding: 4px 12px;
  font-size: 13px;
  font-weight: 600;
}

/* ---------------------------------------------------------- 推薦清單 */

.taste { margin-bottom: 16px; font-size: 13px; }
.taste .dim { margin-right: 6px; }

.results-title { font-size: 16px; margin: 0 0 6px; }
.results-note { color: var(--dim); font-size: 13px; margin: 0 0 12px; }
.results-note.warn { color: var(--mixed); }
.results-empty { color: var(--dim); }

/* 這一列刻意套 Steam 商店的視覺語言（方形角、藍底契合度、綠底價格、文字評價）。
   **只有這一列**——其餘畫面維持本站原本的樣子，完成畫面的 .done-card 也不套。 */
.result-list { list-style: none; margin: 0; padding: 0; }
.result-row {
  display: grid;
  grid-template-columns: 22px 92px minmax(0, 1fr);
  gap: 10px;
  align-items: center;
  padding: 8px 10px;
  margin-bottom: 3px;
  background: rgba(0, 0, 0, .2);
  border-radius: 2px;
}
.rank { color: var(--dim); font-size: 13px; font-variant-numeric: tabular-nums; }
.result-row .rank { color: #4f8fba; }
.result-thumb { width: 92px; aspect-ratio: 231 / 87; object-fit: cover; border-radius: 2px; }
.result-main { min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.result-name {
  color: #c7d5e0;
  text-decoration: none;
  font-size: 14px;
  font-weight: 600;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.result-name:hover { color: #fff; }
.result-meta { display: flex; gap: 10px; font-size: 12px; align-items: center; }
/* 好評率改用 Steam 自己的文字評價（「極度好評」），比一個裸的百分比好懂。
   資料集本來就有 reviewDesc，不必重抓。 */
.result-review { color: #66c0f4; }
.result-row .match {
  background: rgba(103, 193, 245, .2);
  color: #67c1f5;
  border: 0;
  border-radius: 2px;
  padding: 0 6px;
  font-weight: 400;
}
.result-row .price {
  background: #4c6b22;
  color: #beee11;
  border-radius: 2px;
  padding: 0 6px;
}
.why { color: var(--accent); font-size: 12px; }
/* 「因為你喜歡 <某款遊戲>」比標籤層級的解釋好懂，所以給它更亮的顏色 */
.why-game { color: var(--fg); font-size: 12px; }
.why-game b { color: var(--accent); font-weight: 600; }

/* ---------------------------------------------------------- 完成畫面 */

/* 每款都用跟 O/X 卡片一樣的排版（大主圖＋截圖縮圖列＋完整資訊）。
   這是收尾畫面，玩家要在這裡決定買哪款，小縮圖什麼都看不清。 */
.done-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(430px, 1fr));
  gap: 16px;
  /* **每張卡各自算高，不要拉齊整列**。grid 預設 stretch，於是展開一張的「熱門評論」
     會把同一列的鄰居一起撐高（實測 751 → 1108，多出來的全是空白）。 */
  align-items: start;
}
.done-card {
  position: relative;
  display: flex;
  flex-direction: column;
  background: var(--bg-card);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  overflow: hidden;
  transition: border-color .15s;
}
.done-card:hover { border-color: #46536b; }
/* 完成畫面的卡片高度不必固定——這裡沒有 O/X 按鈕要對齊，簡介也就不需要截斷 */
.done-card .card-desc {
  mask-image: none;
  overflow: visible;
  flex: 0 0 auto;
}
/* 完成畫面的評論：預設收起。一頁 12 張大卡，每張再攤開三則評論會長到沒人捲得完；
   收起來也讓那 12 個請求只在玩家真的想看時才發（見 screens.js 的 toggle 監聽）。 */
.done-rv { margin: 0 0 10px; }
.done-rv > summary {
  cursor: pointer;
  color: var(--dim);
  font-size: 13px;
  font-weight: 600;
  list-style: none;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 4px 10px;
  border: 1px solid var(--line);
  border-radius: 999px;
}
.done-rv > summary::-webkit-details-marker { display: none; }
.done-rv > summary::before { content: '▸'; font-size: 11px; }
.done-rv[open] > summary::before { content: '▾'; }
.done-rv > summary:hover { color: var(--fg); border-color: var(--dim); }
.done-rv .reviews-panel { margin-top: 10px; }
/* 這裡不必固定高度（完成畫面的卡片本來就是內容多高就多高），但太長會把一整列的
   grid 撐開，所以給評論區一個上限、超過自己捲。 */
.done-rv .rv-body { max-height: 320px; overflow-y: auto; }

.done-card .rank {
  position: absolute;
  top: 10px; left: 10px;
  z-index: 2;
  min-width: 28px;
  height: 28px;
  padding: 0 8px;
  border-radius: 999px;
  background: rgba(8, 14, 20, .85);
  border: 1px solid var(--line);
  color: var(--fg);
  font-size: 14px;
  font-weight: 700;
  display: grid;
  place-items: center;
}
.done-why { display: flex; flex-direction: column; gap: 3px; margin-bottom: 12px; }

/* 「再答 10 題」「重新開始」上下各放一份——清單至少 12 張大卡，只放在最底下的話
   每次都得捲過整份清單才按得到。 */
.done-actions { display: flex; gap: 12px; flex-wrap: wrap; align-items: center; }
/* 「複製連結」靠右，跟「再答 10 題／重新開始」分開——見 screens.js 的註解。
   窄螢幕換行時 margin-left: auto 會失效（它自己一行），那時改成靠右對齊。 */
.done-actions .btn-share { margin-left: auto; }
@media (max-width: 520px) {
  .done-actions { justify-content: flex-end; }
  .done-actions .btn-more, .done-actions .btn-restart { margin-right: auto; }
}
/* about-data.html 用的純文字排版。這是站上唯一一個「讀」的頁面。 */
.prose { max-width: 68ch; }
.prose h1 { margin-bottom: 8px; }
.prose h2 { margin: 28px 0 8px; font-size: 17px; }
.prose p { color: var(--dim); line-height: 1.75; margin: 0 0 12px; }
.prose p b, .prose li b { color: var(--fg); }
.prose ul { color: var(--dim); line-height: 1.75; margin: 0 0 12px; padding-left: 20px; }
.prose li { margin-bottom: 4px; }
.prose a { color: var(--accent); }

.done-actions-top { margin-top: 16px; }

/* 「忘掉我的口味」：找得到，但不會誤觸。跟上面那排按鈕刻意長得不一樣——
   它是罕見而且不可逆的動作，做成按鈕的樣子只會變成第四個等權選項。 */
.forget-row {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: 4px 10px;
  margin: 0;
  font-size: 13px;
}
.btn-forget {
  padding: 0;
  border: 0;
  background: none;
  color: var(--dim);
  font-size: 13px;
  text-decoration: underline;
  text-underline-offset: 3px;
  cursor: pointer;
}
.btn-forget:hover { color: var(--no); }

.done-footer {
  margin-top: 24px;
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: 16px;
}
/* 「再看 N 款」是清單的延伸，不是離開這個畫面的動作，所以樣式要跟上面兩顆分得開：
   整排寬、虛線框、字暗一階。 */
.btn-page {
  background: transparent;
  border: 1px dashed var(--line);
  color: var(--dim);
  border-radius: 8px;
  padding: 14px;
}
.btn-page:hover:not(:disabled) { color: var(--fg); border-color: #46536b; border-style: solid; }
/* 沒有下一頁時留在原地變成不可按的「沒有更多了」，不要整顆消失 */
.btn-page:disabled { opacity: .45; cursor: default; }
.btn-more {
  background: var(--accent);
  color: #08131c;
  border: 0;
  border-radius: 8px;
  padding: 12px 20px;
  font-weight: 700;
}
.btn-more:hover { background: #7fcdf8; }
.btn-restart, .btn-share {
  background: transparent;
  border: 1px solid var(--line);
  color: var(--dim);
  border-radius: 8px;
  padding: 12px 20px;
}
.btn-restart:hover, .btn-share:hover { color: var(--fg); border-color: #46536b; }
/* clipboard 被擋時的退路：把網址擺出來讓人自己複製 */
.share-fallback {
  flex: 1 1 260px;
  min-width: 0;
  background: var(--bg-soft);
  border: 1px solid var(--accent);
  color: var(--fg);
  border-radius: 8px;
  padding: 12px;
  font: inherit;
  font-size: 13px;
}

/* ---------------------------------------------------------- 窄螢幕 */

/* 矮視窗（1366×768 的筆電最常見，可視高度只剩 660 左右）：卡片被壓到 min-height，
   縮圖列與簡介多佔的每一 px 都是從主圖身上扣的。縮圖只是拿來換主圖，這時候先讓它。
   完成畫面的卡片寬 443px、縮圖本來就只有 105px，吃不到這個上限。 */
@media (max-height: 760px) {
  .shot-strip { grid-template-columns: repeat(4, minmax(0, 110px)); }
  .card > .card-body { flex-basis: 248px; }
}

/* 桌機版面現在也是單欄，所以這裡不必再改排版方向，只調尺寸。 */
@media (max-width: 860px) {
  h1 { font-size: 23px; }
  #app { padding: 16px 14px 48px; }
  /* 站名列與進度列併成一行（v0.9.2）。進度列自己佔一行是 40 ＋ 24(gap)
     ＝ 64px，而站名右邊本來就是空的。節點由 main.js 的 drawSwipe 搬進來、swap 清掉
     ——站名列在 #app 外面，CSS 搬不動它。
     `--chrome` 跟著重新定義成 43（padding 10 ＋ 那一行 32.8，實測）：卡片高度的每一條
     calc 都吃這個變數，改了這裡就不必動下面那幾條。**那一行的高度是站名決定的**
     （36.8 → 32.8，比進度列的 32.4 高），所以改站名的字級或內距就要重量這個數字。 */
  :root { --chrome: 43px; }
  .site-head { display: flex; align-items: center; gap: 12px; padding: 10px 14px 0; }
  .site-head .btn-home { flex: 0 0 auto; font-size: 15px; padding: 2px 0; }
  .site-head .home-mark { font-size: 16px; }
  /* min-width: 0 不能省：進度條那格是 flex: 1，沒有它的話最小內容寬會把整列撐爆，
     「看目前推薦」就被推出畫面右邊。 */
  .site-head .topbar { flex: 1 1 auto; min-width: 0; gap: 8px; }
  .site-head .progress-text { font-size: 12px; }
  .site-head .btn-flat { padding: 5px 10px; font-size: 13px; }
  /* 窄螢幕的操作列在卡片外面（四顆並排每顆只剩約 80px，塞不下）。
     卡片高度要把操作列的位置一起算進來：16(留白)+24(gap)+83(操作列)+8(餘裕) ＝ 131，
     四顆鍵才進得了第一屏。**v0.9.2 從 210 降到 131**：進度列併進了站名列（−64）、
     操作列壓小（−12）。這個常數與 `--chrome` 是同一筆預算的兩半，改任何一邊都要
     重量「操作列底部 vs 摺線」那個數字。
     **一定要用 svh 不是 vh**：iOS Safari 的 100vh 是「工具列收起」時的大值
     （iPhone 13 是 844，實際看得到的只有 664），照 vh 算出來的卡片會把第二排按鈕
     整排頂到摺線下面。上面那行 vh 是給不支援 svh 的舊瀏覽器的退路。 */
  .card {
    height: min(880px, calc(100vh - 147px - var(--chrome)));
    height: min(880px, calc(100svh - 131px - var(--chrome)));
    min-height: 300px;
  }
  .swipe-screen { max-width: min(880px, calc((100svh - 141px - var(--chrome)) * 1.6)); }
  /* **手機的文字區改成「內容多高就多高，剩下的全給主圖」**（v0.9.5，目標是讓主圖
     再大一點）。前兩版都是固定高度，病在同一個地方：把空間先切給文字，用不完就爛在
     那裡。實測 390×664 上文字區拿了 315px 但常見的簡介只有三行（約 66px），於是
     **主圖被壓到 120px 的下限、簡介下面掛著一百多 px 的空白**——兩個抱怨其實是同一件事。
     現在反過來：`flex: 0 1 auto` 讓文字區照內容算，`max-height` 只封住上限（超過就由
     簡介自己捲，它本來就會捲），主圖是 `flex: 1 1 0` 把剩下的全吃掉。實測同一輪裡
     主圖在 120～200px 之間隨簡介長短浮動，短簡介那幾張大得很明顯。
     **「Steam 連結／熱門評論的 Y 座標固定」這條沒有被犧牲**（量過才敢寫）：文字區是
     卡片這個 column flex 的最後一個小孩，而會伸縮的是它上面的主圖，所以文字區高度雖然
     每張不同，**它的底邊永遠貼著卡片底邊**——實測連續五張底列 Y 都是 505。四顆回答鍵
     更不受影響（它們在卡片外，卡片總高固定）。桌機與中間寬度維持固定高度，不吃這一段。
     上限 300 是拿主圖換來的：`100svh − 394` 在 390×664 得 270，主圖因此保底 165px
     （上一版是 120px 的下限，也就是常常貼著地板）。簡介超過約四行半才需要捲，而它本來
     就會捲、也有漸層提示。**想再放大主圖就再調小 394 那個數字**，代價是簡介更早開始捲。
     第一行 240px 是不支援 svh 的舊瀏覽器的退路。 */
  .card > .card-media { min-height: 120px; }
  .card > .card-body {
    flex: 0 1 auto;
    max-height: 240px;
    max-height: clamp(190px, calc(100svh - 394px), 300px);
    padding: 12px 14px;
  }
  /* 文字區改吃內容之後，簡介也要跟著改成「內容多高就多高」。留著 flex: 1 1 auto 的話
     它會把文字區撐到 max-height，等於固定高度那版換個地方犯。 */
  .card .card-desc { flex: 0 1 auto; padding-bottom: 12px; }
  .card .card-title { font-size: 18px; }
  /* 標題最多兩行：第三行會把簡介擠成一行，而 240px 是照兩行算的 */
  .card .card-title {
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
  }
  /* meta 收成一行：好評率／評論數／年份／價格四項在 354px 寬剛好排得下，
     類型（「動作／獨立製作」）在窄螢幕讓掉——標籤那排已經講了同樣的事。 */
  .card .card-meta { font-size: 13px; gap: 8px; margin-bottom: 10px; flex-wrap: nowrap; overflow: hidden; }
  .card .meta-genres { display: none; }
  /* 標籤只留一排（兩排會多吃 24px，那是從主圖身上扣的），但**放不下要能推得動**。
     舊版是 overflow: hidden，於是第五、六個標籤被切掉一半又推不走——看得到卻讀不到
     是最糟的一種，寧可整個不顯示。捲軸藏起來：那一排本來就只有 22px 高，捲軸會佔掉
     三分之一，而末端被切一半的標籤本身就是「還有更多」的提示。 */
  .card .card-tags {
    flex-wrap: nowrap;
    overflow-x: auto;
    overflow-y: hidden;
    margin-bottom: 10px;
    scrollbar-width: none;
    -webkit-overflow-scrolling: touch;
    overscroll-behavior-x: contain;
  }
  .card .card-tags::-webkit-scrollbar { display: none; }
  .card .card-tags > * { flex: 0 0 auto; }
  .card .card-desc { min-height: 1.6em; }
  .shot-strip { grid-template-columns: repeat(4, minmax(0, 84px)); padding: 3px; gap: 3px; }
  /* 操作列壓縮，四顆鍵才進得了第一屏。
     實測 iPhone 13（390×664）改之前按鈕頂端落在 y=614：第一排只露出一小截，
     「忽略」「已擁有」整排在摺線下面。改完是 79→533 卡片、557→652 操作列，
     四顆全在摺線內還剩十幾 px 餘裕（留給 iOS 字體比開發環境高一點的情況）。
     **試過 position: sticky; bottom: 0 但沒有用**：sticky 只能把「自然位置在視窗
     下方」的元素往上拉，不能把已經在視窗內的元素釘住往下推——實測捲到 300px 時
     按鈕照樣跟著跑掉。要真正釘住只能用 position: fixed，但那會永久吃掉 115px 的
     閱讀高度（推薦清單就在下面），不划算。 */
  /* v0.9.2 再壓一階：整列 95 → 78px，省下的 17px 全部進了卡片。
     第一排的 padding 是這裡的下限——再小就低於 44px 的觸控目標，而 ✕／◯ 是這個
     介面按最多次的兩顆。第二排本來就矮一階，跟著等比收。 */
  .swipe-actions { gap: 5px; margin-top: 0; }
  .action-row { gap: 10px; }
  .action-row button { padding: 9px 10px; font-size: 15px; }
  /* 第二排是兩個特殊出口，窄螢幕再壓一階——主次要分得出來 */
  .action-row:last-child button { padding: 6px 8px; font-size: 13px; }
  /* 第二排三顆等寬（v0.9.5）。「上一步」在桌機仍然刻意窄一半，但手機上
     三顆並排時寬度參差看起來就是跑版；主次改由配色承擔（它比另外兩顆再暗一階）。
     權重要蓋過 `.btn-undo` 自己的 `flex: 0 0 auto !important`，所以這裡也得 !important。 */
  .action-row .btn-undo { flex: 1 1 0 !important; padding-left: 10px; padding-right: 10px; }
  .seed-footer { margin: 8px -14px -48px; padding: 12px 14px; }
  /* 窄螢幕至少兩欄。一欄的話 11 排 × 10 款直向堆疊要捲 27 個畫面（實測 390px 寬），
     那面牆沒人會看完。兩欄的封面是 175×82，配上疊在上面的遊戲名仍然認得出來。 */
  .seed-grid { grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); }
  .seed-name { font-size: 12px; padding: 12px 8px 5px; }
  .done-grid { grid-template-columns: minmax(0, 1fr); }
}

/* 更矮的手機（iPhone SE 的 375×553 那一類，低於基準機種 iPhone 13 但還是別讓它
   壞掉）：卡片高度已經低於「主圖下限 ＋ 縮圖列 ＋ 240px 文字區」的總和，文字區底部
   （Steam 連結）會被卡片的 overflow: hidden 直接裁掉。實測 553 時裁掉 100px。
   這時先讓掉縮圖列與兩行簡介——縮圖只是拿來換主圖的，是這張卡上最不重要的東西。
   一定要排在上面那個 max-width 區塊之後，選擇器權重一樣時後面的才蓋得掉前面的。 */
@media (max-width: 860px) and (max-height: 620px) {
  .shot-strip { display: none; }
  .card > .card-media { min-height: 100px; }
  /* 同一條倒推，只是這裡沒有縮圖列要扣（上面剛把它收掉），主圖下限也降到 100。
     跟上面那塊一樣是 `max-height` 而不是 `flex-basis`——寫 basis 等於把 v0.9.5 那個
     「內容多高就多高、剩下的全給主圖」的行為在矮螢幕上關掉。實測 375×553 主圖 120px。 */
  .card > .card-body {
    max-height: 206px;
    max-height: clamp(190px, calc(100svh - 294px), 300px);
  }
  .card .card-desc { min-height: 1.6em; }
}
