/* ==========================================================================
   ThreadSpot 脆隱之心 — 前端樣式
   設計語言：莫蘭迪色系（低飽和灰調）、深墨色文字、楷體標題 × 襯線數字
   字型：LXGW WenKai TC（標題／品牌）、Noto Sans TC（內文）、Fraunces（數字）
   ========================================================================== */

:root {
  /* --- 莫蘭迪色票 --- */
  --bg: #ECE7DF;            /* 燕麥米底 */
  --surface: #F7F4EE;       /* 暖白卡片 */
  --surface-2: #E5DED3;     /* 深一階的米灰 */
  --line: #D8D0C4;          /* 分隔線 */

  --ink: #3B3733;           /* 深墨棕（主要文字） */
  --ink-soft: #6E675F;      /* 次要文字 */
  --ink-faint: #948C82;     /* 提示文字 */

  --sage: #82B0A2;          /* 湖水綠（安全／推薦，取自 logo 左半） */
  --sage-deep: #4E7A6C;
  --sage-mist: #DCE7E2;

  --rose: #C1A39B;          /* 灰粉 */
  --rose-mist: #EADFDB;

  --brick: #D97F6C;         /* 珊瑚紅（警示／踩雷，取自 logo 右半） */
  --brick-deep: #A2543F;
  --brick-mist: #F3DDD6;

  --blue: #93A5B7;          /* 霧藍（Google 側） */
  --blue-deep: #5E7286;
  --blue-mist: #DDE3E9;

  --gold: #C2A878;          /* 霧金（星星） */

  /* --- 字型 --- */
  --font-display: "LXGW WenKai TC", "Noto Serif TC", serif;
  --font-body: "Noto Sans TC", "PingFang TC", "Microsoft JhengHei", sans-serif;
  --font-numeral: "Fraunces", Georgia, serif;

  --radius: 18px;
  --radius-sm: 12px;
  --shadow: 0 2px 10px rgba(59, 55, 51, 0.07), 0 10px 32px rgba(59, 55, 51, 0.06);
}

* { box-sizing: border-box; margin: 0; padding: 0; }

html { -webkit-text-size-adjust: 100%; }

body {
  background:
    radial-gradient(1200px 500px at 85% -10%, rgba(147, 160, 140, 0.16), transparent 60%),
    radial-gradient(900px 420px at -10% 20%, rgba(193, 163, 155, 0.14), transparent 55%),
    var(--bg);
  color: var(--ink);
  font-family: var(--font-body);
  line-height: 1.65;
  min-height: 100dvh;
}

.page {
  max-width: 640px;
  margin: 0 auto;
  padding: clamp(16px, 4vw, 32px);
  padding-bottom: 48px;
}

.hidden { display: none !important; }
/* ⚠ 必要的防線（2026-07-29 踩到）：瀏覽器對 `[hidden]` 的預設是 UA 樣式的
   `display: none`，**任何作者端的 display 規則都會蓋過它**。桌機版把
   `.map-shell` 設成 `display: flex` 之後，切到清單視圖時地圖的 hidden 就失效了
   （地圖照樣佔著 750px，清單被推到畫面外）。這條讓 hidden 屬性永遠說了算。 */
[hidden] { display: none !important; }

/* ==========================================================================
   頁首
   ========================================================================== */
/* 頁首刻意收斂（2026-07-29 使用者拍板「以地圖為主」）：品牌是招牌不是主角，
   每多一列頁首，手機上的地圖就少一列。原本 logo 68px＋大標＋標語共佔 139px。 */
.masthead { padding: 2px 4px 12px; }

.brand { display: flex; align-items: center; gap: 12px; }

.brand-logo {
  width: 46px;
  height: 46px;
  border-radius: 14px;
  background: #FFFFFF;
  border: 1px solid var(--line);
  box-shadow: var(--shadow);
  object-fit: cover;
  /* logo 本體是正方形構圖（上圖下字），縮小時聚焦上半的刺蝟圓徽 */
  object-position: center top;
}

.brand-en {
  font-family: var(--font-numeral);
  font-size: 13px;
  font-weight: 600;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--ink-faint);
}

.brand-zh {
  font-family: var(--font-display);
  font-size: clamp(23px, 5.5vw, 27px);
  font-weight: 400;
  letter-spacing: 0.12em;
  color: var(--ink);
}

.tagline {
  margin-top: 8px;
  font-family: var(--font-display);
  font-size: 14.5px;
  color: var(--ink-soft);
  letter-spacing: 0.05em;
}
.tagline em {
  font-style: normal;
  color: var(--brick-deep);
  border-bottom: 2px solid var(--rose);
  padding-bottom: 1px;
}

/* ==========================================================================
   分頁
   ========================================================================== */
/* 分頁列（.tabs/.tab）已於 2026-07-29 隨「兩分頁合併成單一畫面」移除，
   樣式一併刪除——空著會被誤認為還有第二個分頁。視圖切換改用 .view-switch。 */

/* ==========================================================================
   卡片與輸入
   ========================================================================== */
.card {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  padding: 20px;
  margin-bottom: 18px;
}

.field-label {
  display: block;
  font-family: var(--font-display);
  font-size: 18px;
  letter-spacing: 0.08em;
  margin-bottom: 12px;
}

input[type="url"], input[type="text"], .city-select {
  flex: 1;
  width: 100%;
  border: 1.5px solid var(--line);
  border-radius: var(--radius-sm);
  background: #FDFCFA;
  color: var(--ink);
  font-family: var(--font-body);
  font-size: 15px;
  padding: 12px 14px;
  outline: none;
  transition: border-color 0.2s, box-shadow 0.2s;
}
input:focus, .city-select:focus {
  border-color: var(--sage);
  box-shadow: 0 0 0 3px rgba(147, 160, 140, 0.22);
}
input::placeholder { color: var(--ink-faint); }

.btn {
  border: none;
  border-radius: var(--radius-sm);
  font-family: var(--font-body);
  font-size: 15px;
  font-weight: 500;
  cursor: pointer;
  padding: 12px 18px;
  transition: transform 0.12s, filter 0.2s, background 0.2s;
}
.btn:active { transform: scale(0.97); }

.btn.primary {
  background: linear-gradient(160deg, var(--sage) 0%, var(--sage-deep) 130%);
  color: #FBFAF6;
  letter-spacing: 0.14em;
}
.btn.primary:hover { filter: brightness(1.06); }
.btn.primary:disabled { filter: grayscale(0.5) opacity(0.6); cursor: wait; }

.btn.block { display: block; width: 100%; font-size: 16px; padding: 14px; }

.btn.ghost {
  background: var(--surface-2);
  color: var(--ink-soft);
  font-size: 17px;
  padding: 10px 14px;
}
.btn.ghost:hover { background: var(--line); }

.btn.link {
  background: none;
  color: var(--blue-deep);
  text-decoration: underline;
  text-underline-offset: 3px;
  padding: 4px 6px;
  font-size: 13px;
}

.hint { font-size: 13px; color: var(--ink-faint); }

/* --- 快速類別 chips --- */
.chips { display: flex; flex-wrap: wrap; gap: 8px; margin: 4px 0 12px; }
.chip {
  border: 1.5px solid var(--line);
  background: #FDFCFA;
  color: var(--ink-soft);
  border-radius: 999px;
  padding: 7px 15px;
  font-size: 14px;
  font-family: var(--font-body);
  cursor: pointer;
  transition: all 0.2s;
}
.chip:hover { border-color: var(--sage); color: var(--sage-deep); }
.chip.is-active {
  background: var(--sage-mist);
  border-color: var(--sage);
  color: var(--sage-deep);
  font-weight: 500;
}

/* 店卡上的鄰近捷運站一行字 */
.reco-mrt {
  font-size: 13px;
  color: var(--sage-deep);
  margin-top: 4px;
}

/* 捷運路線色點（buildMrtLine）：轉乘站有多條線就連著畫幾個點 */
.mrt-line-dot {
  display: inline-block;
  width: 7px;
  height: 7px;
  border-radius: 50%;
  margin-right: 3px;
  vertical-align: 1px;
}
.mrt-line-dot + .mrt-line-dot { margin-left: -1px; }

/* ==========================================================================
   錯誤卡片
   ========================================================================== */
.error-card {
  background: var(--brick-mist);
  border-color: var(--rose);
  color: var(--brick-deep);
  font-size: 14.5px;
}
.error-card .error-title {
  font-family: var(--font-display);
  font-size: 17px;
  margin-bottom: 6px;
  letter-spacing: 0.06em;
}

/* 好評菜色徽章（脆友點名稱讚的品項；脆評卡片共用） */
.dish-chip {
  display: inline-block;
  padding: 5px 12px;
  border-radius: 999px;
  background: var(--surface);
  border: 1px solid var(--sage);
  color: var(--ink);
  font-size: 13.2px;
  line-height: 1.5;
}

/* ==========================================================================
   脆評卡片（地圖 modal 與脆友尋味共用）
   ========================================================================== */

/* 清單視圖（2026-07-29 起與地圖同一畫面）：狀態列＋精簡排行列（點列開店卡 modal）。
   `.trending-intro`／`.trending-sorts`／`.trending-chips` 已隨分頁合併刪除——
   排序改用地圖那一列 `.map-sorts`、分類改用「篩選」抽屜裡的 `.map-chips`，兩個視圖共用。
   保留下來的是「列」本身，由 map.js 的 exploreRenderList 驅動、資料來自 /map-data。 */
.list-shell { margin-top: 4px; }
.list-status { margin: 0 2px 12px; }
.list-more {
  width: 100%;
  margin-top: 10px;
  padding: 12px 16px;
  border: 1px dashed var(--line);
  border-radius: var(--radius-sm);
  background: var(--surface);
  color: var(--ink-soft);
  font-family: inherit;
  font-size: 14px;
  cursor: pointer;
  transition: border-color 0.15s, background 0.15s, color 0.15s;
}
.list-more:hover { border-color: var(--sage-deep); background: var(--sage-mist); color: var(--sage-deep); }

/* 排行列上的徽章：一眼看出「為什麼這家值得看」 */
.trending-badges { display: flex; flex-wrap: wrap; gap: 5px; margin-top: 3px; }
.tbadge {
  font-size: 10.5px;
  line-height: 1.6;
  padding: 1px 7px;
  border-radius: 999px;
  border: 1px solid var(--line);
  color: var(--ink-faint);
  white-space: nowrap;
}
.tbadge.is-gem { border-color: var(--sage); background: var(--sage-mist); color: var(--sage-deep); }
.tbadge.is-quiet { border-color: var(--line); }
.tbadge.is-talk { border-color: var(--brick); color: var(--brick-deep); }
.trending-status { margin: 4px 2px 14px; }

.trending-list { display: flex; flex-direction: column; gap: 8px; }
.trending-row {
  display: flex;
  align-items: center;
  gap: 12px;
  width: 100%;
  padding: 14px 16px;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  background: var(--surface);
  cursor: pointer;
  text-align: left;
  transition: border-color 0.15s, background 0.15s, transform 0.12s;
}
.trending-row:hover { border-color: var(--sage); background: var(--sage-mist); }
.trending-row:active { transform: scale(0.99); }
.trending-rank {
  flex: 0 0 auto;
  width: 26px;
  font-family: var(--font-numeral);
  font-size: 18px;
  font-weight: 600;
  color: var(--ink-faint);
  text-align: center;
}
/* 前三名名次強調（第一名珊瑚紅、二三名湖水綠） */
.trending-row:nth-child(1) .trending-rank { color: var(--brick-deep); }
.trending-row:nth-child(2) .trending-rank,
.trending-row:nth-child(3) .trending-rank { color: var(--sage-deep); }
.trending-main { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.trending-name-row { display: flex; align-items: baseline; gap: 8px; min-width: 0; }
.trending-name {
  font-family: var(--font-display);
  font-size: 16px;
  letter-spacing: 0.02em;
  color: var(--ink);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.trending-gap {
  flex-shrink: 0;
  font-family: var(--font-numeral);
  font-size: 11.5px;
  font-weight: 600;
  color: var(--brick-deep);
  background: var(--brick-mist);
  border-radius: 999px;
  padding: 1px 8px;
  white-space: nowrap;
}
.trending-hl {
  font-size: 13px;
  color: var(--ink-soft);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.trending-meta {
  font-size: 12px;
  color: var(--ink-faint);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.trending-score {
  flex: 0 0 auto;
  display: flex;
  flex-direction: column;
  align-items: center;
  min-width: 46px;
}
.trending-score-num {
  font-family: var(--font-numeral);
  font-size: 20px;
  font-weight: 700;
  color: var(--sage-deep);
  line-height: 1.1;
}
.trending-score-num.is-na { color: var(--ink-faint); font-size: 16px; }
.trending-score-label { font-size: 10.5px; color: var(--ink-faint); letter-spacing: 0.05em; }

.reco-card {
  display: block;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  padding: 16px 18px;
  transition: transform 0.15s, box-shadow 0.2s;
}
.reco-card:hover {
  transform: translateY(-2px);
  box-shadow: 0 4px 14px rgba(59, 55, 51, 0.1), 0 14px 40px rgba(59, 55, 51, 0.08);
}

.reco-top {
  display: flex;
  align-items: baseline;
  gap: 8px;
}
.reco-rank {
  flex-shrink: 0;
  font-family: var(--font-numeral);
  font-size: 13px;
  font-weight: 600;
  color: var(--ink-faint);
  min-width: 14px;
}
.reco-name {
  font-family: var(--font-display);
  font-size: 18.5px;
  letter-spacing: 0.04em;
  line-height: 1.4;
  flex: 1;
}
/* 落差標籤：Google 高分但脆上不是這麼回事——避雷針的核心價值 */
.reco-gap {
  flex-shrink: 0;
  font-family: var(--font-numeral);
  font-size: 12.5px;
  font-weight: 600;
  color: var(--brick-deep);
  background: var(--brick-mist);
  border-radius: 999px;
  padding: 2px 10px;
  white-space: nowrap;
}
.reco-loc {
  font-size: 12.5px;
  color: var(--ink-faint);
  margin-top: 3px;
}
.reco-stats {
  font-size: 12px;
  color: var(--ink-faint);
  margin-top: 8px;
}
.reco-warn {
  font-size: 12px;
  color: var(--brick-deep);
  margin-top: 4px;
}
/* 連鎖分店的來源範圍說明（含品牌整體評價）：中性語氣，不是警告 */
.reco-note {
  margin-top: 6px;
  padding: 6px 9px;
  border-left: 2px solid var(--line);
  font-size: 11.5px;
  line-height: 1.6;
  color: var(--ink-faint);
}

/* 店卡免責警語（2026-07-25）：內容是 AI 從脆友貼文彙整的，警語要跟著內容走。
   刻意低調（細字、淡色、上方細線分隔）——要看得到，但不搶走店卡本身的資訊。 */
.reco-disclaimer {
  margin-top: 14px;
  padding-top: 10px;
  border-top: 1px dashed var(--line);
  font-size: 11px;
  line-height: 1.65;
  color: var(--ink-faint);
  letter-spacing: 0.02em;
}

/* 好評菜色徽章 */
.reco-dishes {
  margin-top: 11px;
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}

/* 樣本出處（2026-08-05）：放在卡片尾端、免責警語之前。
   視覺權重刻意壓到最低——它是「佐證」不是「內容」，搶了主體的注意力就本末倒置。 */
.reco-sources { margin-top: 14px; padding-top: 12px; border-top: 1px dashed var(--line); }
.reco-sources-label { margin: 0 0 7px; font-size: 12.5px; color: var(--ink-soft); }
.reco-source-links { display: flex; flex-wrap: wrap; gap: 6px; }
.source-link {
  display: inline-block;
  max-width: 100%;
  padding: 3px 9px;
  border: 1px solid var(--line);
  border-radius: 999px;
  font-size: 12.5px;
  color: var(--ink-soft);
  text-decoration: none;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.source-link:hover, .source-link:focus-visible {
  border-color: var(--teal, #82B0A2);
  color: var(--ink);
}
/* 「N 則心得」與「無脆評」是**狀態字，不是分數**，所以不能用星等那種強調色。

   ⚠ 特異性要跟得上：分色規則是 `.mini-row.threads .mini-score`（3 個 class）
   且寫在本檔後段，光靠 `.mini-score.few`（2 個）會被壓過去——實測字色仍是
   rgb(162,84,63) 的磚紅。這也是既有 `.na` 一直沒生效的原因：「無脆評」被畫成
   強調紅，視覺上反而像個分數，正好與「不確定就別假裝有分數」相反。 */
.mini-row.threads .mini-score.few,
.mini-row.threads .mini-score.na,
.mini-row.google .mini-score.na {
  color: var(--ink-soft);
  font-family: var(--font-body);
  font-size: 13px;
  font-weight: 500;
  letter-spacing: 0;
}

/* 「這個分數怎麼來的？」——長得像連結的按鈕（用 button 才有鍵盤與 a11y 語意） */
.method-link {
  display: inline;
  margin-left: 4px;
  padding: 0;
  border: none;
  background: none;
  font: inherit;
  color: var(--teal, #82B0A2);
  text-decoration: underline;
  text-underline-offset: 2px;
  cursor: pointer;
}
.method-link:hover, .method-link:focus-visible { color: var(--ink); }

/* 方法論說明（走店卡同一個 modal，見 app.js showMethodology） */
.method-doc { padding-bottom: 4px; }
.method-title { margin: 0 0 4px; font-size: 18px; }
.method-h {
  margin: 18px 0 6px;
  font-size: 14px;
  color: var(--ink);
  border-left: 3px solid var(--teal, #82B0A2);
  padding-left: 8px;
}
.method-p {
  margin: 0 0 8px;
  font-size: 13.5px;
  line-height: 1.75;
  color: var(--ink-soft);
}

/* 「＋還有 N 篇」：與出處 chip 同尺寸好排在同一列，但用虛線邊框區分
   ——它是展開控制項，不是可以點去看的第 7 篇貼文。 */
.source-more {
  padding: 3px 9px;
  border: 1px dashed var(--line);
  border-radius: 999px;
  background: none;
  font: inherit;
  font-size: 12.5px;
  color: var(--ink-soft);
  cursor: pointer;
}
.source-more:hover, .source-more:focus-visible {
  border-color: var(--teal, #82B0A2);
  color: var(--ink);
}

/* ==========================================================================
   骨架屏（2026-08-05）：店卡的四個欄位是點開才向 /place-details 拿的，
   在它們回來之前先站好位置，否則內容長出來會把下面一路往下推（使用者回報的
   「閃爍感」）。尺寸與行數見 app.js 的 SKELETON_* 常數與那段實測說明。
   ========================================================================== */
.sk-lines { display: flex; flex-direction: column; gap: 7px; margin-top: 6px; }
.sk-line,
.sk-chip {
  display: block;
  border-radius: 6px;
  /* 兩層：底色 ＋ 一道掃過去的高光。用 background-position 動畫（合成器友善），
     不要動 width/left 那類會觸發 layout 的屬性——這張卡正在做 fade-in。 */
  background-color: var(--surface-2);
  background-image: linear-gradient(
    90deg,
    rgba(255, 253, 248, 0) 0%,
    rgba(255, 253, 248, 0.62) 50%,
    rgba(255, 253, 248, 0) 100%
  );
  background-size: 220% 100%;
  background-repeat: no-repeat;
  animation: sk-shimmer 1.35s ease-in-out infinite;
}
/* 行高刻意對齊 .reco-points li 與 .reco-summary 的實際行高，
   骨架才會跟真內容一樣高（差一點就是差一點的位移） */
.sk-line { height: 15px; }
.sk-chip { height: 27px; border: 0; }      /* 與 .dish-chip 的外框高度一致 */

@keyframes sk-shimmer {
  from { background-position: 140% 0; }
  to   { background-position: -40% 0; }
}

/* 骨架的標題（「推薦點」「一句話總評」）壓淡一點：那幾個字是真的，
   但整個區塊還沒有內容，不該和已經載好的區塊搶注意力 */
.reco-block.is-skeleton .reco-block-label,
.reco-summary-block.is-skeleton .reco-summary-label { opacity: 0.55; }

@media (prefers-reduced-motion: reduce) {
  .sk-line, .sk-chip { animation: none; background-image: none; }
}

/* 情境標籤（有插座／店狗／不限時…）。刻意比好評菜色**低一階**：
   菜色是「這家店好在哪」，標籤是「這家店適合什麼場合」——後者是輔助條件，
   搶了主體的視覺重量會讓店卡失焦。用虛線框與中性色，和實心框的菜色 chip 分開。 */
.reco-amenities {
  margin-top: 10px;
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}
.amenity-chip {
  display: inline-block;
  padding: 3px 10px;
  border-radius: 999px;
  border: 1px dashed var(--line);
  background: transparent;
  color: var(--ink-soft);
  font-size: 12.2px;
  line-height: 1.5;
}

/* 踩雷點／推薦點：完整列出，不截斷（2026-07-21） */
.reco-block { margin-top: 12px; }
.reco-block-label {
  font-size: 12px;
  letter-spacing: 0.05em;
  margin-bottom: 3px;
}
.reco-block.is-pain .reco-block-label { color: var(--brick-deep); }
.reco-block.is-good .reco-block-label { color: var(--sage-deep); }
.reco-points {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 3px;
}
.reco-points li {
  font-size: 13.5px;
  line-height: 1.6;
  color: var(--ink);
  padding-left: 12px;
  position: relative;
}
.reco-points li::before {
  content: "·";
  position: absolute;
  left: 2px;
  color: var(--ink-faint);
}
.reco-more {
  margin-top: 4px;
  padding: 0;
  border: none;
  background: none;
  font-size: 12.5px;
  color: var(--sage-deep);
  cursor: pointer;
}
.reco-more:hover { text-decoration: underline; }

/* 迷你雙評分條 */
.mini-duel { margin-top: 12px; display: flex; flex-direction: column; gap: 7px; }
.mini-row { display: grid; grid-template-columns: 64px 1fr 44px; align-items: center; gap: 10px; }
.mini-label { font-size: 11.5px; letter-spacing: 0.08em; color: var(--ink-faint); }
.mini-track {
  height: 8px;
  background: var(--surface-2);
  border-radius: 999px;
  overflow: hidden;
}
.mini-fill { height: 100%; border-radius: 999px; transition: width 0.7s ease; }
.mini-row.google .mini-fill { background: var(--blue); }
.mini-row.threads .mini-fill { background: var(--brick); }
.mini-score {
  font-family: var(--font-numeral);
  font-weight: 600;
  font-size: 14.5px;
  text-align: right;
}
.mini-row.google .mini-score { color: var(--blue-deep); }
.mini-row.threads .mini-score { color: var(--brick-deep); }
.mini-row .na { color: var(--ink-faint); font-size: 12px; font-family: var(--font-body); }
.mini-row .pending {
  color: var(--brick-deep);
  font-size: 12px;
  font-family: var(--font-body);
  animation: pendingPulse 1.4s ease-in-out infinite;
}
@keyframes pendingPulse {
  0%, 100% { opacity: 1; }
  50% { opacity: 0.35; }
}

/* 一句話總評是卡片裡最長的一段：預設收三行，超過才給「看完整」；
   其餘內容（踩雷點/推薦點/菜色）一律完整顯示 */
.reco-summary-block {
  margin-top: 13px;
  padding-top: 12px;
  border-top: 1px solid var(--line);
}
.reco-summary-label {
  font-size: 12px;
  letter-spacing: 0.05em;
  color: var(--ink-faint);
  margin-bottom: 4px;
}
.reco-summary {
  font-size: 13.2px;
  line-height: 1.75;
  color: var(--ink-soft);
}
.reco-summary.is-clamped {
  display: -webkit-box;
  -webkit-line-clamp: 3;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

.reco-foot {
  margin-top: 12px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
}
.reco-tag { font-size: 11.5px; color: var(--ink-faint); }
.reco-nav {
  font-size: 13px;
  color: var(--blue-deep);
  text-decoration: none;
  font-weight: 500;
  border: 1.5px solid var(--blue-mist);
  border-radius: 999px;
  padding: 5px 14px;
  transition: background 0.2s;
}
.reco-nav:hover { background: var(--blue-mist); }

/* ==========================================================================
   頁尾
   ========================================================================== */
.foot {
  margin-top: 40px;
  text-align: center;
  font-size: 12.5px;
  color: var(--ink-faint);
}
.foot-note { letter-spacing: 0.03em; }
/* 完整版免責聲明：比一般頁尾字更小、左右收窄成一段易讀的文字塊 */
.foot-disclaimer {
  margin: 12px auto 0;
  max-width: 44em;
  padding: 12px 14px;
  border: 1px solid var(--line);
  border-radius: 10px;
  background: var(--surface-2, transparent);
  font-size: 11.5px;
  line-height: 1.8;
  text-align: left;
}
.foot-disclaimer strong { color: var(--ink); }
.foot-disclaimer em { font-style: normal; color: var(--sage-deep); }

/* 申訴管道：緊接在免責聲明下方。刻意比免責聲明再小一階、但把 email 標成
   可點的重點色——它是「發現有誤怎麼辦」的答案，要找得到但不搶版面。 */
.foot-contact {
  margin: 8px auto 0;
  max-width: 44em;
  font-size: 11.5px;
  line-height: 1.7;
}
.foot-contact a {
  color: var(--sage-deep);
  text-decoration: underline;
  text-underline-offset: 2px;
}
.foot-contact a:hover { color: var(--brick); }

/* ==========================================================================
   進場動畫
   ========================================================================== */
@keyframes rise {
  from { opacity: 0; transform: translateY(10px); }
  to   { opacity: 1; transform: translateY(0); }
}
.reco-card, .error-card { animation: rise 0.35s ease both; }
.reco-card:nth-child(2) { animation-delay: 0.05s; }
.reco-card:nth-child(3) { animation-delay: 0.1s; }
.reco-card:nth-child(4) { animation-delay: 0.15s; }
.reco-card:nth-child(5) { animation-delay: 0.2s; }

/* ==========================================================================
   RWD：平板與桌機
   手機（<720px）維持原單欄；平板加寬；桌機改為「品牌側欄＋內容」雙欄
   ========================================================================== */

/* --- 平板（720px 以上）：加寬單欄、頁首橫向呼吸感 --- */
@media (min-width: 720px) {
  .page { max-width: 900px; }
  .brand-logo { width: 52px; height: 52px; }
  .tagline { font-size: 15.5px; }
}

/* --- 桌機（1024px 以上）：地圖優先版面（2026-07-29 使用者拍板重構）---
   舊版是「340px 品牌側欄 ＋ 內容」，光 logo 就佔 320×320px、標語與分頁再吃掉一截，
   地圖被擠成約 738×560。使用者定調「地圖是核心顯示項目」⇒
     ① 品牌收成頂部細長 bar（logo 46px）
     ② 控制項（搜尋／排序／篩選／狀態）移到左側欄——用 CSS 重排既有 DOM，不動 HTML
     ③ 地圖吃滿剩下的寬與整個視窗高度
   ⚠ 這裡只重排 #panel-explore 的子元素；modal 在 body 層不受影響。 */
@media (min-width: 1024px) {
  .page {
    max-width: 1600px;
    padding: 20px clamp(20px, 3vw, 40px) 28px;
  }

  .masthead {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 24px;
    padding: 0 2px 14px;
  }
  .brand { flex-direction: row; align-items: center; }
  /* ⚠ 舊版桌機把 .brand-text 無障礙隱藏，因為 320px 的 logo 本身就含中英文字標。
     縮到 46px 後那個字標完全看不清 ⇒ 必須把文字標還原，否則桌機沒有站名。 */
  .brand-text {
    position: static;
    width: auto;
    height: auto;
    overflow: visible;
    clip: auto;
    white-space: normal;
  }
  .brand-zh { font-size: 26px; }
  .tagline { margin: 0; font-size: 16px; text-align: right; }

  /* 左控制欄 ＋ 右地圖 */
  #panel-explore {
    display: grid;
    grid-template-columns: 330px minmax(0, 1fr);
    column-gap: 24px;
    align-items: start;
  }
  /* ⚠ sticky 元素比視窗高就等於沒有 sticky（會被卡住跟著捲走）——
     篩選抽屜展開時有 15 個分類 chips，必須封頂並讓它自己捲。 */
  .map-controls {
    grid-column: 1;
    position: sticky;
    top: 20px;
    margin-bottom: 0;
    max-height: calc(100dvh - 40px);
    overflow-y: auto;
  }
  .map-shell, .list-shell, #mapError { grid-column: 2; }
  /* 清單列是「左店名右分數」的橫向排版，拉到 1200px 寬會中間空一大片 */
  .list-shell { max-width: 900px; }

  /* 地圖吃滿視窗高度：直排 flex，圖例固定在下、地圖撐滿剩餘。
     機制與 .is-fullscreen 同一套（那套已在正式站驗證過）。
     ⚠ 圖例要設 max-height＋overflow：分類全選時它有 15 個項目，
     不封頂會把地圖壓扁。 */
  .map-shell:not(.is-fullscreen) {
    display: flex;
    flex-direction: column;
    height: calc(100dvh - 150px);
    min-height: 520px;
  }
  .map-shell:not(.is-fullscreen) .map-viewport {
    height: auto;
    flex: 1 1 auto;
    min-height: 0;
  }
  /* 圖例封頂用固定值不用百分比：分類全選時它有 15 個項目，
     在較窄的桌機（1024px）會換到 4-5 行、吃掉 137px 地圖高度。
     約 3 行就夠，多的自己捲。 */
  .map-shell:not(.is-fullscreen) .map-legend {
    flex: 0 0 auto;
    max-height: 104px;
    overflow-y: auto;
  }

  .foot { margin-top: 24px; text-align: left; }
  .card { padding: 22px 24px; }
}

/* --- 超寬桌機（1440px 以上）：控制欄略寬，其餘全給地圖 --- */
@media (min-width: 1440px) {
  #panel-explore { grid-template-columns: 360px minmax(0, 1fr); column-gap: 28px; }
}

/* ==========================================================================
   畫面三：地圖找店（2026-07-24 v4 版面重構）
   整寬地圖（無並排常駐清單）＋置中 modal（點圓點才出清單/店卡）
   ========================================================================== */

/* 搜店名 */
.map-search-wrap { position: relative; margin-bottom: 12px; }
.map-search {
  width: 100%;
  padding: 11px 14px;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  background: var(--surface);
  color: var(--ink);
  font-size: 15px;
  font-family: var(--font-body);
}
.map-search:focus { outline: none; border-color: var(--sage); }
.map-search-drop {
  position: absolute;
  top: calc(100% + 6px);
  left: 0;
  right: 0;
  z-index: 30;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  box-shadow: var(--shadow);
  /* ⚠ 必須封頂＋內捲：改成兩行列之後，8 筆＋入口列實測 535px＝手機視窗的 66%，
     等於把整張地圖蓋掉。50vh 讓使用者永遠看得到下面的地圖在變。 */
  max-height: min(50vh, 420px);
  overflow-x: hidden;
  overflow-y: auto;
  overscroll-behavior: contain;
}
/* 🔴 兩行版面（2026-08-01 使用者回報「根本看不到哪家店」）。
   舊版是單行 flex：店名 `flex:1`（＝flex-basis 0，只能分**剩下**的空間），而說明欄
   沒設 flex（＝flex-basis auto，先取滿內容寬度）⇒ 長片段一來就把空間吃光，
   實測**店名欄寬變成 0px**，畫面上完全看不到是哪一家店。
   現在第一行固定「店名＋星等」，輔助資訊一律降到第二行，店名永遠拿得到寬度。 */
.map-search-row {
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: 3px;
  width: 100%;
  padding: 10px 14px;
  border: none;
  background: transparent;
  cursor: pointer;
  text-align: left;
  font-size: 14.5px;
  color: var(--ink);
}
.map-search-row:hover { background: var(--sage-mist); }
.msr-main { display: flex; align-items: baseline; gap: 8px; min-width: 0; }
/* flex-basis 用 auto（不是 0）＋ min-width:0 允許收縮：店名先拿到自己的內容寬度，
   真的放不下才截斷，而不是被同一行的其他元素擠成零。 */
.map-search-name {
  flex: 1 1 auto;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.map-search-score { flex: 0 0 auto; color: var(--ink-soft); font-size: 13px; }
.msr-meta {
  display: flex;
  align-items: baseline;
  gap: 8px;
  min-width: 0;
  font-size: 12.2px;
  color: var(--ink-faint);
}
/* 「靠近哪裡」：固定寬度不收縮，它是最短也最有用的一段。
   ⚠ 「近 」前綴綁在這個 class 上 ⇒ 只有真的是捷運站才可以用它
   （沒有站而退回顯示分類時請用 .msr-cat，否則會變成「近 咖啡廳」）。 */
.msr-mrt { flex: 0 0 auto; }
.msr-mrt::before { content: "近 "; }
.msr-cat { flex: 0 0 auto; }
/* 命中片段：可收縮、超出截斷，絕不可以反過來擠壓店名 */
.msr-why {
  flex: 1 1 auto;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  color: var(--sage-deep);
  font-style: italic;
}
.map-search-cat { color: var(--ink-faint); font-size: 12.5px; }

/* 「🗺 在地圖上顯示這 N 家」＝這個搜尋框的**主要動作**，永遠是第一列。
   ⚠ 2026-08-01 使用者回報「很少人知道按 Enter 才有這效果」——鍵盤捷徑不是
   大眾會發現的東西。所以這一列要做得像一個**按鈕**（底色＋粗體＋副標說明它會
   做什麼），而不是像另一筆搜尋結果。 */
.map-search-apply {
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  padding: 11px 14px;
  border: none;
  border-bottom: 1px solid var(--line);
  background: var(--sage-mist);
  color: var(--sage-deep);
  font-size: 14px;
  text-align: left;
  cursor: pointer;
  position: sticky;      /* 捲動下拉時主要動作不該滑走 */
  top: 0;
  z-index: 1;
}
.map-search-apply:hover,
.map-search-apply.is-hl { background: var(--sage); color: #fff; }
.msa-icon { flex: 0 0 auto; font-size: 15px; }
.msa-text { display: flex; flex-direction: column; gap: 1px; min-width: 0; }
.msa-text strong { font-weight: 600; }
.msa-sub { font-size: 11.8px; opacity: 0.8; }

/* 鍵盤上下鍵選到的那一列 */
.map-search-row.is-hl { background: var(--sage-mist); }

/* 生效中的搜尋條件 */
.map-search-active { margin-top: 8px; }
.search-active-chip {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 5px 10px 5px 12px;
  border-radius: 999px;
  border: 1px solid var(--sage);
  background: var(--sage-mist);
  color: var(--sage-deep);
  font-size: 13px;
  cursor: pointer;
}
.search-active-chip:hover { background: var(--sage); color: #fff; }
.sac-x { font-size: 11px; opacity: 0.8; }

/* 情境快捷 chips：比分類 chips 低一階（分類是「看哪一類」，情境是「要什麼條件」） */
.chips.is-amenity { margin-bottom: 2px; }
.chip.amenity-quick {
  border-style: dashed;
  font-size: 12.8px;
}
.chip.amenity-quick.is-active {
  border-style: solid;
  background: var(--sage);
  border-color: var(--sage);
  color: #fff;
}
.map-filter-hint { margin: 2px 0 0; font-size: 12px; color: var(--ink-faint); line-height: 1.6; }
.map-search-empty { padding: 12px 14px; font-size: 13.5px; color: var(--ink-soft); margin: 0; }

/* 伺服器補搜到、但地圖上沒有的店（未勾分類／還在分析佇列）。淡一階＋一條分隔線，
   讓「這些是另一種東西」看得出來，但仍然點得下去（2026-08-01）。 */
.map-search-row.is-extra { opacity: 0.78; }
.map-search-row.is-extra:first-of-type { border-top: 1px solid var(--line-soft, rgba(0, 0, 0, 0.08)); }
.map-search-row.is-extra .map-search-name { font-weight: 400; }

/* 篩選收合面板：分類 chips＋快速篩選收進抽屜，地圖才是主角（2026-07-25） */
/* 排名切換（2026-07-29）：原本 4 欄（口碑／寶藏／熱議／不排名），
   一路收斂到 **2 欄：熱議／不排名**（見 index.html 的註解）。 */
.map-sorts {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 6px;
  margin: 8px 0;
}
/* ⚠ 高度要斤斤計較：375×812 手機上，控制列每高 1px 地圖就少 1px。
   實測這排原本 54px＋20px margin＝吃掉可見地圖的 24%（383→309px），
   壓到 45px 左右。副標不能砍——「寶藏」兩個字本身看不懂，
   而第一次打開的人正是這個功能要服務的對象。 */
.map-sort {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 1px;
  padding: 6px 2px;
  border: 1px solid var(--line);
  border-radius: 12px;
  background: var(--surface);
  color: var(--ink-soft);
  font-family: inherit;
  font-size: 13px;
  font-weight: 500;
  line-height: 1.3;
  cursor: pointer;
  transition: border-color 0.16s ease, background 0.16s ease, color 0.16s ease;
}
.map-sort .ms-sub {
  font-size: 9.5px;
  font-weight: 400;
  color: var(--ink-faint);
  letter-spacing: 0.01em;
  white-space: nowrap;
}
.map-sort:hover { border-color: var(--sage); }
.map-sort.is-on {
  border-color: var(--sage-deep);
  background: var(--sage-mist);
  color: var(--sage-deep);
}
.map-sort.is-on .ms-sub { color: var(--sage-deep); }
/* 清單模式沒有「不排名」（清單的存在理由就是排序），而拿掉它之後只剩「熱議」
   一顆——一個永遠選中、沒有其他選項的分頁鈕是純噪音，所以整列藏起來
   （手機上還省下 45px 給清單）。排序方式改由 #listStatus 的
   「依『熱議』排序，共 N 家」講出來。 */
.map-sorts.is-list-view { display: none; }

.map-toolbar { display: flex; gap: 8px; align-items: center; }

/* 地圖／清單切換：塞在「篩選」同一行，不佔額外高度（手機上高度就是地圖） */
.view-switch {
  display: flex;
  flex: 0 0 auto;
  gap: 2px;
  padding: 3px;
  background: var(--surface-2);
  border-radius: 999px;
}
.view-btn {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 7px 12px;
  border: none;
  border-radius: 999px;
  background: transparent;
  color: var(--ink-soft);
  font-family: inherit;
  font-size: 13.5px;
  cursor: pointer;
  transition: background 0.18s, color 0.18s, box-shadow 0.18s;
}
.view-btn.is-on {
  background: var(--surface);
  color: var(--ink);
  box-shadow: var(--shadow);
}
/* 窄螢幕只留圖示——375px 下「篩選」那顆按鈕要留夠寬度顯示分類摘要 */
@media (max-width: 419px) {
  .view-btn .vb-label { display: none; }
  .view-btn { padding: 7px 10px; }
}
.map-filter-toggle {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  flex: 1;
  min-width: 0;
  padding: 10px 16px;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: var(--surface);
  color: var(--ink);
  font-family: var(--font-body);
  font-size: 14px;
  cursor: pointer;
  transition: border-color 0.2s, background 0.2s;
}
.map-filter-toggle:hover { border-color: var(--sage); }
.map-filter-toggle.is-open { border-color: var(--sage); background: var(--sage-mist); }
.mft-icon { font-size: 13px; color: var(--ink-soft); }
.mft-label { font-weight: 500; letter-spacing: 0.08em; flex-shrink: 0; }
.mft-summary {
  flex: 1;
  min-width: 0;
  color: var(--ink-faint);
  font-size: 12.5px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.mft-caret { flex-shrink: 0; color: var(--ink-faint); font-size: 11px; transition: transform 0.24s; }
.map-filter-toggle.is-open .mft-caret { transform: rotate(180deg); }

.map-filter-panel { margin: 12px 0 2px; }
.map-filter-panel.is-open { animation: filterReveal 0.24s ease; }
@keyframes filterReveal { from { opacity: 0; transform: translateY(-6px); } }
.map-filter-heading {
  font-size: 12.5px;
  color: var(--ink-faint);
  letter-spacing: 0.06em;
  margin: 4px 0 8px;
}
.map-filter-panel .chips { margin: 0 0 14px; }

/* 快速篩選 toggle */
.map-filters { display: flex; flex-wrap: wrap; gap: 8px; margin: 2px 0 10px; }
.map-filter {
  padding: 7px 14px;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: var(--surface);
  color: var(--ink-soft);
  font-size: 13.5px;
  cursor: pointer;
  transition: background 0.2s, color 0.2s, border-color 0.2s;
}
.map-filter:hover { border-color: var(--sage); color: var(--sage-deep); }
.map-filter.is-on {
  background: var(--sage-deep);
  border-color: var(--sage-deep);
  color: #FFFDF8;
}

/* chips 的功能鈕（全部/清空） */
.map-chip-tool { border-style: dashed; color: var(--ink-faint); }
.map-chip-tool:hover { color: var(--sage-deep); }

.map-status { margin: 2px 0 0; font-size: 13px; color: var(--ink-soft); }

/* --- 地圖視窗（整寬） --- */
.map-shell { padding: 0; overflow: hidden; }
.map-viewport {
  position: relative;
  height: 64vh;
  min-height: 400px;
  background:
    radial-gradient(circle at 30% 20%, rgba(130, 176, 162, 0.06), transparent 55%),
    var(--surface);
  /* 容器也擋：雙指張開時有一根手指可能落在 svg 之外、但仍在這個框內
     （縮放鈕、「這一帶 N 家」都是它的絕對定位子元素），那一根若被瀏覽器
     當成頁面縮放的起點，整個網頁就會被放大。iOS Safari 的 gesture 事件
     另外由 map.js 攔（CSS 管不到那一套）。 */
  touch-action: none;
}
#mapSvg {
  display: block;
  width: 100%;
  height: 100%;
  touch-action: none;
  cursor: grab;
  user-select: none;
  -webkit-user-select: none;
}
#mapSvg:active { cursor: grabbing; }

/* 捷運骨架（字級＝螢幕 px；counter-scale 群組已抵銷 zoom 與容器寬） */
.mrt-line-halo { opacity: 0.9; }
.mrt-line { opacity: 0.85; }
.mrt-label {
  font-family: var(--font-body);
  font-size: 11px;
  fill: var(--ink-soft);
  paint-order: stroke;
  stroke: var(--surface);
  stroke-width: 3px;
  stroke-linejoin: round;
  pointer-events: none;
  display: none;
}
.mrt-label.is-major { fill: var(--ink); font-weight: 700; font-size: 12.5px; }
.mrt-label.is-l0 { display: block; }
#mapSvg.lod1 .mrt-label.is-l1 { display: block; }
#mapSvg.lod2 .mrt-label.is-l2 { display: block; }

/* 店點與聚合圓 */
.shop-dot, .shop-cluster { cursor: pointer; }
.shop-dot .shop-body,
.shop-cluster .cluster-body {
  transform-box: fill-box;
  transform-origin: center;
  transition: transform 0.16s ease;
}
.shop-dot:hover .shop-body { transform: scale(1.25); }
.shop-cluster:hover .cluster-body { transform: scale(1.1); }
.shop-dot.is-active .shop-body { stroke: var(--ink); stroke-width: 2.6; }
.shop-dot.is-closed { opacity: 0.72; }
.shop-cluster text { font-family: var(--font-numeral, var(--font-body)); pointer-events: none; }
.shop-trap-ring { animation: trap-pulse 1.8s ease-in-out infinite; }
@keyframes trap-pulse { 0%, 100% { opacity: 0.95; } 50% { opacity: 0.35; } }

/* 縮放按鈕（右下角直排） */
.map-zoom-btns {
  position: absolute;
  right: 12px;
  bottom: 14px;
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.map-zoom-btn {
  width: 40px;
  height: 40px;
  border-radius: 12px;
  border: 1px solid var(--line);
  background: var(--surface);
  box-shadow: var(--shadow);
  color: var(--ink);
  font-size: 18px;
  line-height: 1;
  cursor: pointer;
  display: flex;              /* 置中內容：文字（＋－⌂）靠 text-align、SVG（全螢幕）是 block 不吃 text-align，
                                  故改 flex 一律置中，否則全螢幕圖示會偏左看起來歪掉（2026-07-25） */
  align-items: center;
  justify-content: center;
}
.map-zoom-btn:hover { border-color: var(--sage); color: var(--sage-deep); }
.map-zoom-btn svg { display: block; }
/* 全螢幕鈕按下狀態（沉浸中）：湖水綠實心，一眼看出「再點退出」 */
.map-zoom-btn.is-on {
  background: var(--sage-deep);
  border-color: var(--sage-deep);
  color: #FFFDF8;
}

/* 全螢幕地圖：CSS 全視窗（跨平台穩健，iPhone Safari 不支援元素 Fullscreen API）。
   尺寸變化由既有 ResizeObserver 重算 aspect/counter-scale。 */
.map-shell.is-fullscreen {
  position: fixed;
  inset: 0;
  z-index: 55;
  margin: 0;
  border-radius: 0;
  max-width: none;
  height: 100dvh;
  display: flex;
  flex-direction: column;
}
.map-shell.is-fullscreen .map-viewport {
  height: auto;
  flex: 1 1 auto;
  min-height: 0;
}
.map-shell.is-fullscreen .map-legend { flex: 0 0 auto; }
body.map-fullscreen-active { overflow: hidden; }

/* 「這一帶 N 家」浮動鈕（開全區清單 modal） */
.map-area-btn {
  position: absolute;
  left: 12px;
  bottom: 14px;
  padding: 9px 16px;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: var(--surface);
  box-shadow: var(--shadow);
  color: var(--ink);
  font-size: 13.5px;
  font-family: var(--font-body);
  cursor: pointer;
  transition: border-color 0.2s;
}
.map-area-btn:hover { border-color: var(--sage); color: var(--sage-deep); }

/* hover tooltip（滑鼠限定） */
.map-tooltip {
  position: absolute;
  transform: translate(-50%, -100%);
  z-index: 6;
  max-width: 250px;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 12px;
  box-shadow: var(--shadow);
  padding: 10px 13px;
  pointer-events: none;
}
.map-tooltip p { margin: 0; }
.map-tip-name { font-size: 14px; font-weight: 700; color: var(--ink); }
.map-tip-scores { font-size: 12.5px; color: var(--ink-soft); margin-top: 2px; }
.map-tip-row { font-size: 12.5px; color: var(--ink-soft); margin-top: 2px; }
.map-tip-warn { font-size: 12.5px; color: var(--brick); margin-top: 3px; }
.map-tip-closed { font-size: 12.5px; color: var(--brick); font-weight: 700; margin-top: 2px; }
.map-tip-hint { font-size: 11.5px; color: var(--ink-faint); margin-top: 5px; }

/* 圖例 */
.map-legend {
  display: flex;
  flex-wrap: wrap;
  gap: 8px 16px;
  padding: 12px 16px;
  border-top: 1px solid var(--line);
  font-size: 12.5px;
  color: var(--ink-soft);
}
.map-legend:empty { display: none; }
.legend-item { display: inline-flex; align-items: center; gap: 6px; }
/* （2026-08-05 移除 .legend-item.is-lod：店點 LOD 已整個拿掉，圖例不再有
   「🔍 放大再看 N 家」那一項。理由見 map.js 檔頭。） */
.legend-dot {
  width: 11px; height: 11px; border-radius: 50%;
  border: 1.5px solid var(--surface);
  box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.08);
}
.legend-ring { width: 11px; height: 11px; border-radius: 50%; border: 2px dashed var(--brick); }
.legend-cluster {
  display: inline-flex; align-items: center; justify-content: center;
  width: 17px; height: 17px; border-radius: 50%;
  background: var(--sage-deep); color: #FFFDF8; font-size: 10px; font-weight: 700;
}
/* 名次圖例：珊瑚紅對應地圖上前 3 名的標記 */
.legend-item.is-rank, .legend-item.is-mixed { cursor: help; }
.legend-item.is-rank { font-weight: 600; color: var(--ink); }
.legend-rank {
  display: inline-flex; align-items: center; justify-content: center;
  width: 18px; height: 18px; border-radius: 50%;
  background: var(--brick-deep); color: #FFFDF8; font-size: 10.5px; font-weight: 700;
  box-shadow: 0 1px 3px rgba(43, 40, 36, 0.28);
}

/* 名次標記要「浮」在其他圓點之上——投影是它與聚合圓最直接的層級差異。
   ⚠ 只能用 filter，不能用 transform：counter-scale 走的是 attribute transform，
   在同一個 g 上加 CSS transform 會整個蓋掉它（既有鐵則）。 */
.shop-dot.is-ranked { filter: drop-shadow(0 2px 3px rgba(43, 40, 36, 0.35)); }
/* 標記被錯開時的連接線＋真實座標的小圓點：沒有它，錯開就變成謊報位置 */
.shop-rank-leader {
  stroke: var(--ink, #3B3733);
  stroke-width: 1.4;
  stroke-dasharray: 2.5 2;
  opacity: 0.75;
}
.shop-rank-anchor { opacity: 0.85; }

/* 前 3 名的店名：白色描邊墊底才讀得到（地圖底下可能是捷運線或別的圓點）。
   ⚠ paint-order + stroke 是 SVG 文字加外框的正規做法，與捷運站名同一套。 */
.shop-rank-label {
  font-family: var(--font-body);
  fill: var(--ink);
  paint-order: stroke;
  stroke: #FFFDF8;
  stroke-width: 3.5px;
  stroke-linejoin: round;
  pointer-events: none;
}

/* ==========================================================================
   置中 modal（點圓點→清單/店卡；淡入縮放，不從底部長出來）
   ========================================================================== */
.map-modal-backdrop {
  position: fixed;
  inset: 0;
  background: rgba(43, 40, 36, 0.38);
  z-index: 60;
  opacity: 0;
  transition: opacity 0.22s ease;
}
.map-modal-backdrop.is-open { opacity: 1; }
.map-modal {
  position: fixed;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -48%) scale(0.96);
  opacity: 0;
  z-index: 61;
  width: min(560px, calc(100% - 28px));
  max-height: min(82vh, 760px);
  display: flex;
  flex-direction: column;
  background: var(--bg);
  border-radius: 20px;
  box-shadow: 0 20px 60px rgba(43, 40, 36, 0.28);
  overflow: hidden;
  transition: opacity 0.22s ease, transform 0.22s cubic-bezier(0.34, 1.3, 0.64, 1);
}
.map-modal.is-open { opacity: 1; transform: translate(-50%, -50%) scale(1); }
@media (prefers-reduced-motion: reduce) {
  .map-modal, .map-modal-backdrop { transition: none; }
}

.map-modal-head {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 12px 14px;
  border-bottom: 1px solid var(--line);
  flex: 0 0 auto;
}
.map-modal-title {
  flex: 1;
  font-family: var(--font-display);
  font-size: 16px;
  letter-spacing: 0.04em;
  color: var(--ink);
  text-align: center;
}
.map-modal-back, .map-modal-close {
  flex: 0 0 auto;
  border: 1px solid var(--line);
  background: var(--surface);
  color: var(--ink-soft);
  border-radius: 999px;
  cursor: pointer;
  font-size: 13px;
}
.map-modal-back { padding: 5px 13px; }
.map-modal-close { width: 32px; height: 32px; font-size: 14px; }
.map-modal-back:hover, .map-modal-close:hover { border-color: var(--sage); color: var(--sage-deep); }

/* 分享是這個 modal 唯一的「主動作」（它是傳播鏈的起點，見 map.js 的 MAP_SHARE_PARAM），
   所以給強調色的淡底，比返回／關閉更容易被看到；尺寸仍與它們一致，不搶內容焦點。 */
.map-modal-share {
  flex: 0 0 auto;
  padding: 5px 13px;
  border: 1px solid var(--sage);
  background: var(--sage-mist);
  color: var(--sage-deep);
  border-radius: 999px;
  cursor: pointer;
  font-size: 13px;
  white-space: nowrap;   /* 文字換成「已複製連結」時不要換行把頭部撐高 */
}
.map-modal-share:hover { background: var(--sage); color: #fff; }

.map-modal-body {
  overflow-y: auto;
  /* bug e：modal 內滑到頂/底不連動背景（scroll chaining）→ 配合 body 鎖捲動雙保險 */
  overscroll-behavior: contain;
  padding: 14px 16px calc(16px + env(safe-area-inset-bottom));
  -webkit-overflow-scrolling: touch;
  scrollbar-width: thin;
  scrollbar-color: var(--line) transparent;
}

/* bug e：開 modal 時鎖背景捲動——position:fixed 保住捲動位置（iOS Safari 唯一可靠作法），
   JS 記錄/還原 scrollY（top 由 JS 設）。 */
body.modal-scroll-lock {
  position: fixed;
  left: 0;
  right: 0;
  width: 100%;
  overflow: hidden;
}
.map-modal-body::-webkit-scrollbar { width: 8px; }
.map-modal-body::-webkit-scrollbar-track { background: transparent; }
.map-modal-body::-webkit-scrollbar-thumb {
  background: var(--line);
  border-radius: 999px;
  border: 2px solid var(--bg);
}
.map-modal-body .reco-card { margin-bottom: 0; }

/* modal 內店卡頂部脈絡列：分類「中性」文字（不用顏色）＋今日營業 */
.map-sheet-context { display: flex; align-items: center; gap: 10px; margin: 0 0 12px; flex-wrap: wrap; }
.map-cat-tag {
  display: inline-block;
  padding: 3px 12px;
  border-radius: 999px;
  background: var(--surface-2);
  color: var(--ink-soft);
  font-size: 13px;
  letter-spacing: 0.04em;
}
.map-today { font-size: 13px; color: var(--ink-soft); }
.map-today.is-closed { color: var(--brick); font-weight: 700; }

/* modal 內清單（點圓點→該群/全區清單；不用分類顏色） */
.map-list { display: flex; flex-direction: column; gap: 8px; }
/* 聚合圓超過 MAP_MODAL_LIST_MAX 家時的說明（2026-08-05）：講出被截掉多少、
   並指出兩條走得通的路，否則使用者會以為圓上的數字是錯的 */
.map-list-more {
  margin: 12px 2px 2px;
  font-size: 13px;
  line-height: 1.6;
  color: var(--ink-soft);
}
.map-list-row {
  display: flex;
  align-items: center;
  gap: 12px;
  width: 100%;
  padding: 12px 14px;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  background: var(--surface);
  cursor: pointer;
  text-align: left;
  transition: border-color 0.15s, background 0.15s;
}
.map-list-row:hover { border-color: var(--sage); background: var(--sage-mist); }
.map-list-row.is-active { border-color: var(--sage-deep); background: var(--sage-mist); }
.map-row-info { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.map-row-name {
  font-size: 15px; color: var(--ink); font-weight: 500;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.map-row-sub {
  font-size: 12px; color: var(--ink-faint);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.map-row-scores { flex: 0 0 auto; display: flex; flex-direction: column; align-items: flex-end; gap: 1px; }
.map-row-threads { font-family: var(--font-numeral); font-size: 16px; font-weight: 700; color: var(--sage-deep); }
.map-row-threads.is-na { color: var(--ink-faint); font-size: 13px; font-family: var(--font-body); }
.map-row-google { font-size: 12px; color: var(--ink-soft); }
.map-row-gap { color: var(--brick); font-weight: 700; }
.map-list-empty { margin: 8px 4px; font-size: 13.5px; color: var(--ink-soft); }

/* 進場動畫：捷運線/站/店淡入＋店 pop（reduced-motion 全關）。
   ⚠ 線條「不」用 stroke-dasharray 描繪——CSS dasharray:1 被當 1px（不吃 pathLength）
   配 non-scaling-stroke 會讓線永久變 1px 點狀虛線＝斷線。改純透明度淡入，保證實線。 */
@keyframes fade-in-kf { from { opacity: 0; } }
.line-fade { animation: fade-in-kf 0.7s ease backwards; }
.station-enter { animation: fade-in-kf 0.5s ease backwards; }
.shop-enter { animation: fade-in-kf 0.28s ease backwards; }
.shop-enter circle { animation: shop-pop-kf 0.38s cubic-bezier(0.34, 1.56, 0.64, 1) backwards; animation-delay: inherit; }
@keyframes shop-pop-kf { from { transform: scale(0.2); } }
@media (prefers-reduced-motion: reduce) {
  .line-fade, .station-enter, .shop-enter, .shop-enter circle { animation: none; }
}

/* 窄手機：分頁字級微縮，地圖略降 */
@media (max-width: 380px) {
  .tab { font-size: 15px; letter-spacing: 0.04em; }
  .tab .tab-icon { margin-right: 3px; }
  .map-viewport { height: 60vh; min-height: 340px; }
}

/* 桌機：地圖更高（整寬，無側欄競爭空間） */
@media (min-width: 1024px) {
  .map-viewport { height: 70vh; }
}
