@charset "UTF-8";
/* ============================================
   v4 改版提案：疊加在原本 main.css / stall-card.css 之上的新規則
   這個檔案是全新獨立檔案，main.css 等原始檔案完全沒有被動過。
   下面每一段都寫了「改了什麼、為什麼」，方便對照。

   這次對話討論才發現的真bug：伺服器回應.css檔案時，Content-Type
   只有「text/css」，沒有帶charset=utf-8（本機python http.server、
   正式站zhuben.digital都一樣，不是本機測試環境特有的問題）。瀏覽器
   抓不到明確的編碼宣告時，用什麼編碼解析這個外部CSS檔案，不同瀏覽器
   的猜測/回退規則可能不一致——實測發現，同一段含有中文註解的規則，
   用<link>從外部載入時，註解後面緊接的兩行CSS宣告（display/
   animation）會被靜默吃掉，但把完全相同的文字內容用JS直接寫進
   inline <style>就沒事（inline <style>本來就跟著HTML文件本身的
   編碼走，不受這個問題影響）。加上這行@charset，明確告訴瀏覽器
   這個檔案本身就是UTF-8編碼，不用再靠HTTP標頭或用猜的，兩種載入
   方式的結果才會一致。這一行必須是檔案最前面、前面不能有任何字元
   （含空白/註解），不然規則會被瀏覽器忽略，等於沒加 */

/* ---------- 1. 地圖標記可點擊熱區放大
   問題：.map-marker 視覺上只有 8px，手指很難精準點到；
   但它本身有 overflow:hidden（用來做「展開顯示編號」的動畫），
   沒辦法直接用 ::after 撐大熱區（會被裁掉），
   所以改用 js/tap-target-boost.js 另外生成一層透明的熱區元素，
   位置跟著原本的小點同步，點擊會轉發給原本的 marker。
   這裡只負責熱區本身的樣式。 ---------- */
.tap-boost-hit {
  position: absolute;
  width: 30px;
  height: 30px;
  margin-left: -15px;
  margin-top: -15px;
  z-index: 6; /* 原本 marker 預設 z-index:5，選中/輪播是 8~10，這裡卡在中間，不擋到放大狀態 */
  cursor: pointer;
}

/* ---------- 2. 點按回饋（App 感的關鍵：按下去要有反應）
   原本按鈕/卡片點下去完全沒有任何回饋，改成輕微縮放，
   純 CSS transition，不影響任何既有版面或邏輯 ---------- */
.top-btn,
.legend-btn,
.lang-switch-btn,
.category-tag,
.stall-row,
.modal-close,
.hot-card,
.v4-cat-chip {
  transition: transform 0.12s ease, background 0.15s ease, border-color 0.15s ease;
}
.top-btn:active,
.legend-btn:active,
.lang-switch-btn:active,
.category-tag:active,
.stall-row:active,
.modal-close:active,
.v4-cat-chip:active {
  transform: scale(0.93);
}

/* ---------- 3. 抽屜收合狀態改成一顆浮動膠囊按鈕
   原本收合時是滿版寬度的長條，貼齊螢幕左右邊，容易被當成固定資訊列
   而不是可以互動的按鈕。改成收合時只顯示一顆置中、不貼邊的膠囊按鈕
   「📋 攤位列表・273 攤 ⌃」，展開後才變回原本滿版的清單面板。
   拖曳手勢／點擊展開完全沿用 drawer.js 既有邏輯（還是同一個
   #drawer-handle 元素，只是收合時樣式變成膠囊），沒有新增任何 JS。 ---------- */
.drawer {
  /* 收合時 .drawer 本身背景改透明，膠囊自己另外畫背景；
     露出高度也縮小到剛好放得下膠囊即可（原本 92px） */
  background: transparent;
  box-shadow: none;
  transform: translateY(calc(100% - 62px));
}
.drawer.expanded {
  /* 展開後要變回原本實心的滿版面板 */
  background: var(--nm-paper);
  box-shadow: 0 -8px 30px rgba(0, 0, 0, 0.35);
  /* main.css 原本是 translateY(28%)，等於永遠有「自己高度的28%」
     （螢幕高度16.8%）卡在螢幕下緣以下，.stall-list 捲到底也捲不到
     那塊區域，剛好卡住清單最後幾攤，導致捲不出來。改成0讓整個
     抽屜盒子完整露出螢幕，不會有捲不到的死角 */
  transform: translateY(0);
}
/* 收合狀態的提示文字（"往上滑查看全部攤位"）在膠囊改版後已經沒有
   存在意義——膠囊本身的⌃箭頭跟攤位數字就是提示了，展開狀態下更
   沒必要顯示（已經在看完整清單了，不用再提示往上滑）。這裡兩種
   狀態都明確隱藏，取代 js/drawer.js 原本用行內樣式手動切換的寫法
   （那段行內樣式是改版前的舊邏輯，沒清乾淨，見 drawer.js 的修改） */
.drawer.expanded .drawer-hint {
  display: none;
}
/* 收合時 .drawer 雖然背景透明，但元素還在、還是滿版寬度，
   不擋掉的話會蓋住底下地圖兩側，變成點不到的死角；
   展開時要恢復成正常可互動 */
.drawer:not(.expanded) {
  pointer-events: none;
}
.drawer:not(.expanded) .drawer-handle-area {
  pointer-events: auto;
}

.drawer-handle-area {
  /* 展開時維持原本滿版樣式，收合時另外用 :not(.expanded) 蓋成膠囊 */
  transition: none;
}
.drawer:not(.expanded) .drawer-handle-area {
  /* 這次對話討論：全新方向，不再是置中懸浮的膠囊（兩側會漏出黑色
     死區，量測過實際佔了整條橫幅41%的寬度、完全點不到）。改成
     滿版橫幅，貼齊螢幕左右邊緣，整條都可以點/拖曳，完全方正（不用
     圓角、不用滿版框線），跟上面地圖框那種「整片圓角+滿版邊框」的
     語言明確做出區隔。文字置中顯示，右側數字後面接一個會動的箭頭
     當作唯一的「可以展開」提示（原本還試過置中拉把短條、文字改左右
     撐開，都被使用者反應更怪異，最後定案是這個最單純的版本）。
     這次對話討論才發現的真bug：padding改小之後，這個把手實際高度
     只剩52.5px，但style/main.css .drawer收合時固定露出62px高
     （translateY(calc(100% - 62px))）——把手比露出的視窗矮了將近
     10px，底下真正的攤位清單內容（尤其選中中的那攤，紅色反白）
     就從縫隙裡冒出來，被實測抓到。padding往上調，確保把手至少跟
     62px一樣高，才不會漏餡 */
  width: 100%;
  max-width: none;
  margin: 0;
  padding: 21px 20px 22px;
  background: linear-gradient(180deg, #f8f0dc 0%, var(--nm-paper) 100%);
  border: none;
  /* 這次對話討論：完全拿掉邊框之後，使用者反應看起來像一片空白
     招牌。加回一條滿版的金色上緣細線——這是「收邊/框線」的語言，
     跟中間置中文字＋右側箭頭那個「這裡可以點」的提示語言是分開的
     兩件事，不會像之前拿掉的置中拉把那樣，變成第二個互相打架的
     提示 */
  border-top: 2px solid var(--nm-gold);
  border-radius: 0;
  box-shadow: 0 -6px 18px rgba(0, 0, 0, 0.35);
}
/* 這次對話討論：原本這裡還有一條置中的金色拉把短條，跟下面靠左/
   靠右撐開的文字排版兜不起來（拉把置中、文字卻左右分開，兩個提示
   各自獨立、對不上），使用者反應很怪異。拿掉拉把，只留右側本來就
   會動的箭頭當唯一的「可以展開」提示，避免兩個不相關的視覺線索
   同時存在 */
.drawer:not(.expanded) .drawer-title-row h2 {
  color: var(--nm-ink);
}
.drawer:not(.expanded) .drawer-count {
  color: var(--nm-lantern-deep);
}
.drawer:not(.expanded) .handle-chevron,
.drawer:not(.expanded) .drawer-hint {
  display: none; /* 膠囊狀態不需要展開箭頭跟提示文字，title列自己的⌃就是按鈕了 */
}
.drawer:not(.expanded) .drawer-title-row {
  gap: 10px;
  white-space: nowrap;
  /* 這次對話討論：試過space-between（標題貼左、數字貼右），使用者
     反應比置中更怪異。改回置中——文字當一整組置中顯示，不強行撐開
     去用滿橫幅寬度 */
  justify-content: center;
}
.drawer:not(.expanded) .drawer-title-row::after {
  /* 這次對話討論：箭頭原本掛在.drawer-count後面，緊貼著數字文字，
     使用者反應要獨立分開，不要黏在文字旁邊。改掛回.drawer-title-row
     （整排的最後一個項目），這樣它會是title列自己獨立的一個
     flex項目，靠row本身的gap（10px）自然跟文字分開，不是緊貼著。
     同時把原本的「⌃」文字符號，先換成用邊框畫出來的空心粗箭頭，後來
     使用者選了實心三角形這個方向——改用CSS經典的「零寬高+透明左右
     邊框+實色下邊框」畫三角形技巧，不用邊框線條勾勒外框，整塊都是
     實色，視覺上比空心箭頭更飽滿扎實 */
  content: "";
  display: inline-block;
  width: 0;
  height: 0;
  border-left: 6px solid transparent;
  border-right: 6px solid transparent;
  border-bottom: 9px solid var(--nm-lantern);
  position: relative;
  margin-bottom: 3px;
  /* 箭頭上下移動，暗示「往上滑」這個實際的展開手勢，不是純裝飾動畫。
     這次對話討論：先試過彈力球式的多段快速彈跳(1.4s+過衝
     cubic-bezier)，使用者反應太突兀。改回單純的上下來回，但拉長
     到2.4秒一個來回、用ease-in-out(沒有過衝)，動作放慢放柔，
     維持「有在動、看起來可以點」的效果就好，不追求Q彈手感 */
  animation: drawer-chevron-bounce 2.4s ease-in-out infinite;
}
@keyframes drawer-chevron-bounce {
  0%, 100% { top: 0; }
  50% { top: -5px; }
}
@media (prefers-reduced-motion: reduce) {
  .drawer:not(.expanded) .drawer-title-row::after {
    animation: none;
  }
}
/* 原本這裡是不分手機/桌機的 .stall-list，桌機版清單容器
   (#stall-list-desktop) 剛好也共用同一個 class，這條背景色因此被
   誤套到桌機版，變成一塊硬直角的乳白色矩形，貼在已經是圓角深色的
   側欄裡很突兀（實測發現的問題，見這次對話討論）。改成只 scope 在
   手機抽屜 .drawer 裡面，不影響桌機版 */
.drawer .stall-list {
  /* 展開時清單本身要有實心底色，膠囊狀態下清單被摺在畫面外，看不到，不影響 */
  background: var(--nm-paper);
}

/* ---------- 4. 手機版常駐分類列（新增的 DOM，樣式寫在這裡）
   原本 7 個分類都要點開搜尋彈窗才看得到；遊客通常不知道攤位名字，
   用「類型」找比打字找直覺，所以搬一份出來直接放在地圖上方常駐顯示。
   用的是既有的 .category-tag class，選中狀態、篩選邏輯全部沿用
   search-filter.js 原本的全域 querySelectorAll(".category-tag")，
   沒有新增或修改任何 JS 篩選邏輯。 ---------- */
.v4-persistent-cats {
  position: fixed;
  top: 93px; /* 緊接在雙排頂部列（93px）下面 */
  left: 0; right: 0;
  z-index: 45;
  display: flex;
  gap: 8px;
  overflow-x: auto;
  padding: 10px 14px;
  background: linear-gradient(to bottom, rgba(23,19,15,0.95), rgba(23,19,15,0.75));
}
.v4-cat-chip {
  flex-shrink: 0;
  width: auto !important; /* 蓋掉 .category-tag 原本固定 92px 寬，改成依文字自動寬，橫向排更多顆不會太擠 */
  padding: 0 16px;
  background: rgba(255, 255, 255, 0.06);
  border: 1px solid rgba(232, 178, 60, 0.3);
  color: var(--nm-paper);
  border-radius: 20px;
  font-size: 12.5px;
  white-space: nowrap;
}
/* ---------- 5. 攤位卡片打開時的進場動畫
   原本 .backdrop.show 是直接 display:flex 瞬間出現，加一個輕微的
   由下往上滑入＋淡入，感覀更像原生 App 的彈出方式。
   只加動畫，沒有改 stall-card.js 的顯示/隱藏邏輯。 ---------- */
@keyframes v4-card-in {
  from { transform: translateY(16px) scale(0.98); opacity: 0; }
  to { transform: translateY(0) scale(1); opacity: 1; }
}
.backdrop.show .card {
  animation: v4-card-in 0.22s cubic-bezier(0.22, 1, 0.36, 1);
}

/* ---------- 7. 地圖外框：讓地圖看起來像被裝框收納好的展示物，
   不是隨手貼一張圖上去。套用三種效果：
   ① 金色細框＋圓角＋內距（相框感）
   ② 陰影（懸浮感）
   ③ 底部展覽標示牌（強化「這是被介紹、被收藏的東西」）
   （原本還有四角裝飾角標，你說看起來像引號、不要，已拿掉）
   手機版／桌機版的 .map-stage 都套用同一份樣式。 ---------- */
.v4-map-frame {
  position: relative;
  width: 100%;
  height: 100%;
  box-sizing: border-box;
  padding: 16px;
  padding-top: 46px; /* 多留一點頂部空間放展覽標示牌，不用讓它疊到地圖內容，
                        也讓標示牌跟底下地圖之間有呼吸感，不要貼太緊 */
  /* 原本用 --nm-night 幾乎跟頁面背景 --nm-night-deep 融在一起，反差太小，
     改用帶一點金棕色調的深色，確保跟外面背景一眼就能分辨出「這是一塊獨立的框」 */
  background: #2a2013;
  border: 3px solid var(--nm-gold);
  border-radius: 20px;
  box-shadow: 0 12px 36px rgba(0, 0, 0, 0.6), 0 0 0 5px rgba(232, 178, 60, 0.12);
}
/* .map-stage 本身完全不加 padding／border，維持跟原本一樣的 100%/100%，
   避免 map-markers.js 算座標時的基準點（marker-layer 的 inset:0）
   跟圖片實際顯示位置對不上，這是這版最容易踩到的坑 */
.v4-map-frame .map-stage img {
  border-radius: 12px;
}

/* 標示牌刻意放在 padding 範圍「以內」（不懸空掛在邊框外），
   因為 .map-area / .map-area-desktop 本身都有 overflow:hidden，
   掛在外面會被切掉，索性讓它像嵌在畫框裡的說明牌。
   原本放在底部，手機版會被收合的抽屜膠囊蓋住，改放頂部就不會疊到
   地圖內容、也不會被抽屜擋住，手機桌機共用同一個位置不用分開處理 */
.v4-map-plate {
  /* 原本是<span>，改成<h2>（見index.html，這次對話討論：跟「Stall
     List」用真正的<h2>一樣，讓這個標牌在語意上也是一個標題，
     螢幕閱讀器/SEO讀得到，不只是裝飾性文字）。<h2>預設會有自己的
     margin，這裡歸零，不然position:absolute定位會跟著跑掉 */
  margin: 0;
  position: absolute;
  top: 14px;
  left: 50%;
  transform: translateX(-50%);
  background: rgba(23, 19, 15, 0.85);
  border: 1px solid rgba(232, 178, 60, 0.4);
  border-radius: 20px;
  padding: 4px 16px;
  /* 原本用Noto Serif TC襯線字體，這次對話討論改用網站預設的無襯線
     字體（跟其他大部分UI文字一致），筆畫比襯線字體圓潤，也跟主標題
     的襯線字體區隔開來，不會搶走主標題的字體特色 */
  font-family: "Work Sans", "PingFang TC", "Microsoft JhengHei", sans-serif;
  font-weight: 700;
  /* 原本11.5px比「Stall List」標牌的12.5px小一號，沒有明顯理由，
     統一成一樣的字級（這次對話討論） */
  font-size: 12.5px;
  color: var(--nm-paper);
  white-space: nowrap;
  z-index: 7;
}
/* 原本套用了跟頂部logo同一種金黃漸層+光暈，但這次對話討論發現偏暗、
   跟主標題撞色，反而稀釋主標題的獨特感。改回單純白色，漸層效果
   只留給主標題專屬 */
.v4-map-plate-text {
  color: var(--nm-paper);
}

/* ---------- 8. 桌機版簡介區塊底下重複的版權宣告
   intro.js 的 buildBodyHtml() 本身就會在簡介內容裡塞一份工作室名稱＋版權
   （.intro-contact），renderFooter() 又另外在真正的頁尾 #desktop-footer
   塞一次版權，桌機版兩個地方都會顯示，變成重複兩次。
   這是正式網站 intro.js 本來就有的重複，這裡沒有動 intro.js，
   只用 CSS 把「桌機簡介區塊裡」那份藏起來，保留頁尾那份（本來就在網頁最下面）。
   手機版沒有這個問題（手機版本來就是刻意把版權併入簡介彈窗，不能動），
   所以只 scope 在 #desktop-intro-text 裡，不影響 #intro-body-mobile。 ---------- */
#desktop-intro-text .intro-contact {
  display: none;
}

/* ---------- 9. 收藏攤位：地圖放大+變色 + 清單標色
   由 js/favorites-highlight.js 控制加減 class，這裡只放樣式。
   （原本還做了旗子圖示，密集聚在一起時旗子會互相重疊變亂，已拿掉） ---------- */

/* 收藏的地圖標記：固定放大＋數字常駐顯示，顏色改成深藍紫色，
   跟一般紅色點／選中的金色都不會搞混，同時風格上還算搭 */
.map-marker.v4-favorited {
  width: 20px;
  height: 20px;
  margin-left: -10px;
  margin-top: -10px;
  font-size: 10px;
  background: #5b4b9e;
  border-width: 2px;
  border-color: #fff;
  box-shadow: 0 1px 5px rgba(0, 0, 0, 0.5), 0 0 0 2px rgba(91, 75, 158, 0.4);
  z-index: 7;
}
/* 收藏的標記同時被選中/hover 時，蓋回原本更大的狀態樣式跟金色。
   這裡要注意：main.css 的 .map-marker.selected 也是兩個 class，
   跟 .v4-favorited 優先權打平時，後載入的 v4-enhancements.css 會贏，
   如果這裡不特別寫 background，選中狀態會被我這邊的紫色蓋掉、
   變不回金色，所以顏色也要在這個三個 class 疊加的規則裡明寫一次 */
.map-marker.v4-favorited.selected {
  width: 26px;
  height: 26px;
  margin-left: -13px;
  margin-top: -13px;
  font-size: 11px;
  background: var(--nm-gold);
}
.map-marker.v4-favorited.hover-preview {
  width: 26px;
  height: 26px;
  margin-left: -13px;
  margin-top: -13px;
  font-size: 11px;
  background: var(--nm-lantern-deep);
}

/* 清單裡收藏攤位標色：金色細邊框（四邊）＋淺金底，跟一般白底攤位
   區隔開。原本只在左邊加一條3px粗邊框，其他三邊維持原本細邊框，
   一邊重一邊輕看起來不對稱又偏暗沉，改成四邊統一用金色細邊框，
   整張卡片像被溫柔標示起來，而不是單邊被劃一刀（實測發現的問題，
   見這次對話討論） */
.stall-row.v4-favorited-row {
  /* 原本用半透明 rgba 疊在淺色側欄背景上，顯示成淡淡的暖金色卡片；
     但側欄背景改成深棕色之後，同樣的半透明色會透出底下深色一起
     混色，變成混濁的深橄欖棕，卡片裡固定深色的文字（設計給白色
     卡片用的）疊在這種意外變深的背景上幾乎看不清楚（實測發現的
     問題，見這次對話討論）。改用不透明的實色，不管側欄背景深淺
     都不會被影響，維持跟其他白色攤位卡片一樣清楚 */
  background: #fbf3e0;
  border: 1px solid var(--nm-gold);
}

/* ---------- 10. 攤位清單標題列：篩選中提示
   原本「共 273 攤」文字不管有沒有篩選分類都不會變（js/stalls-list.js
   的 bug，已經修掉），現在數字會跟著篩選結果變動；這裡另外用顏色
   強化「現在是篩選狀態」，避免使用者以為 273 就是全部攤位。
   .drawer-count / .desktop-stall-count 本身是在淺色紙感背景上
   （.drawer / 桌機側欄都是 --nm-paper），所以用偏深的燈籠紅而不是
   金色，金色在淺底上對比太弱看不清楚。 ---------- */
.count-filtered {
  color: var(--nm-lantern-deep) !important;
  font-weight: 700;
}

/* ---------- 11. 攤位卡片「看地圖位置」按鈕：呼吸燈提示
   點按鈕後 js/map-markers.js 的 locateStall() 會直接對標記加
   .selected（放大+金色，樣式沿用既有選中狀態）+ .locating（這裡的
   呼吸動畫，光暈強弱平滑循環，不是快閃），幫使用者在密集的地圖上
   找到剛剛按鈕指定的那個點。呼吸會持續，直到使用者做了下一個
   「真正選中」的動作（點別的標籤/列表項目）才停止，清除邏輯統一
   寫在 map-markers.js 的 updateSelectedState 裡。 ---------- */
@keyframes v5-locate-breathe {
  0%, 100% {
    box-shadow: 0 0 0 5px rgba(232, 178, 60, 0.3), 0 0 14px 2px #ffd97a;
    transform: scale(1);
  }
  50% {
    box-shadow: 0 0 0 10px rgba(232, 178, 60, 0.12), 0 0 28px 8px #ffd97a;
    /* 圓圈本體也跟著光暈一起小幅呼吸，幅度刻意抓小（1.08），不是
       誇張的放大縮小，避免看起來像在跳動而不是「呼吸」 */
    transform: scale(1.08);
  }
}
.map-marker.locating {
  animation: v5-locate-breathe 1.25s ease-in-out infinite;
}

/* ---------- 12. 手機版頭部重新設計
   1. logo 維持獨立一列，底下加一行副標題（攤位數＋建議時間）
   2. 原本 4 顆等重按鈕（搜尋/資訊/語言/收藏）→ 搜尋做成真正的
      長條搜尋列 + ★收藏 常駐，ℹ️資訊、中/EN語言收進「⋯」彈窗
   3. 分類列加右側漸層提示 + 每個分類帶數量（js/mobile-header.js 算的）
   4. 因為頭部總高度變了，.v4-persistent-cats / .map-area 的
      固定定位數值要跟著調整（原本寫死 93px，這裡蓋掉） ---------- */
.v5-header-titleblock {
  width: 100%;
  display: flex;
  flex-direction: column;
  gap: 3px;
  min-width: 0;
}
.v5-header-titleblock .top-bar-logo {
  width: auto;
  max-width: 100%;
}
.v5-subtitle-row {
  display: flex;
  align-items: center;
  gap: 8px;
  min-width: 0;
  /* 原本補30px縮排是為了對齊logo文字的起始位置（見上面.top-bar-logo
     的討論），但logo後來改成整組置中（這次對話討論），30px不再對齊
     任何東西、變成沒有意義的縮排。拿掉，改回貼齊頭部本身的左邊界，
     至少有個明確的參考點 */
}
.v5-header-subtitle {
  margin: 0;
  min-width: 0;
  font-family: "Work Sans", sans-serif;
  font-size: 11.5px;
  color: var(--nm-paper-dim);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  max-width: 100%;
}

.v5-toolbar {
  width: 100%;
  display: flex;
  align-items: center;
  gap: 8px;
}
/* 原本是一顆長得像輸入框的按鈕（點了跳彈窗），現在是真正的 <input>，
   直接在原地輸入，樣式盡量維持跟改版前一樣的外觀 */
.v5-search-wrap {
  flex: 1 1 auto;
  min-width: 0;
  display: flex;
  align-items: center;
  gap: 8px;
  height: 40px;
  padding: 0 14px;
  background: rgba(255, 255, 255, 0.06);
  border: 1px solid rgba(232, 178, 60, 0.3);
  border-radius: 20px;
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.3);
}
.v5-search-icon {
  font-size: 14px;
  flex-shrink: 0;
}
.v5-search-input {
  min-width: 0;
  flex: 1 1 auto;
  background: none;
  border: none;
  outline: none;
  font-family: "Work Sans", sans-serif;
  font-size: 13px;
  color: var(--nm-paper);
}
.v5-search-input::placeholder {
  color: #a89877;
}
/* display:flex 是 class selector，優先權會蓋掉瀏覽器預設的
   [hidden]{display:none}——這個坑在搜尋面板、入口標記浮動標籤
   都踩過，這次先主動補上，不要又測到才發現 */
.v5-active-filter-tag[hidden] {
  display: none;
}
/* 目前套用的分類篩選標籤，顯示在搜尋列的圖示跟輸入框之間，
   不管分類是從哪裡選的都會同步反映在這裡（見 js/mobile-search.js） */
.v5-active-filter-tag {
  flex-shrink: 0;
  display: flex;
  align-items: center;
  gap: 4px;
  padding: 3px 8px;
  background: var(--nm-gold);
  border: none;
  border-radius: 12px;
  color: var(--nm-ink);
  font-family: "Work Sans", sans-serif;
  font-size: 11.5px;
  font-weight: 600;
  cursor: pointer;
}
.v5-toolbar .top-btn {
  flex-shrink: 0;
}

/* main.css 的 .mobile-only{display:block} 是無條件套用的，優先權會蓋掉
   瀏覽器預設的 [hidden]{display:none}（同樣的坑之前在入口標記的浮動
   標籤踩過一次），這裡加回來，不然面板會不管 hidden 屬性直接顯示 */
.v5-search-panel[hidden] {
  display: none;
}
/* 搜尋面板：輸入框 focus 時蓋在分類列跟地圖上面，不是跳出來的彈窗。
   開關邏輯在 js/mobile-search.js，這裡只管樣式 */
.v5-search-panel {
  position: fixed;
  top: 112px; /* 跟 .map-area／.v5-persistent-cats-wrap 用同一個數值，見第12段說明 */
  left: 0; right: 0; bottom: 0;
  z-index: 48; /* 蓋過分類列(45)跟地圖，但不用跟頂部列(50)搶，兩者垂直位置本來就不重疊 */
  background: var(--nm-night);
  /* overflow-y/padding 移到 .v5-search-panel-content（第17段），
     面板本身現在是上下兩段的flex容器（內容可捲動＋底部固定關閉鈕） */
}
.v5-search-hints-label {
  margin: 0 0 10px;
  font-family: "Work Sans", sans-serif;
  font-size: 12px;
  color: var(--nm-paper-dim);
}
.v5-search-hint-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}
.v5-hint-chip {
  width: auto !important; /* 蓋掉 .category-tag 原本固定 92px 寬 */
  padding: 8px 14px;
  background: rgba(255, 255, 255, 0.06);
  border: 1px solid rgba(232, 178, 60, 0.3);
  color: var(--nm-paper);
  border-radius: 20px;
  font-size: 13px;
}

.v5-more-wrap {
  position: relative;
  flex-shrink: 0;
}
.v5-more-trigger[aria-expanded="true"] {
  background: var(--nm-gold);
  color: var(--nm-ink);
  border-color: var(--nm-gold);
}
.v5-more-popover {
  position: absolute;
  top: calc(100% + 8px);
  right: 0;
  z-index: 90;
  width: 200px;
  background: var(--nm-night);
  border: 1px solid rgba(232, 178, 60, 0.35);
  border-radius: 14px;
  box-shadow: 0 10px 30px rgba(0, 0, 0, 0.5);
  padding: 8px;
  animation: v4-popover-in 0.16s ease; /* 沿用桌機版彈窗既有的進場動畫，不重寫 */
}
.v5-more-item {
  width: 100%;
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 10px 8px;
  background: transparent;
  border: none;
  border-radius: 8px;
  color: var(--nm-paper);
  font-family: "Work Sans", sans-serif;
  font-size: 13px;
  text-align: left;
  cursor: pointer;
}
.v5-more-item:active {
  background: rgba(232, 178, 60, 0.12);
}
.v5-more-lang-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 8px 8px 2px;
  margin-top: 2px;
  border-top: 1px dashed rgba(232, 178, 60, 0.2);
}
.v5-more-lang-label {
  font-size: 13px;
  color: var(--nm-paper);
}

/* .v4-persistent-cats 本身有 overflow-x:auto，絕對定位的漸層如果
   直接掛在它自己身上會跟著內容一起被捲動裁切，所以外面再包一層
   不捲動的 wrap，把原本 .v4-persistent-cats 的 position:fixed
   定位責任轉移到 wrap 身上，漸層掛在 wrap 上才能保持
   「不管捲到哪都貼在右邊」。 */
.v5-persistent-cats-wrap {
  position: fixed;
  left: 0; right: 0;
  z-index: 45;
}
.v5-persistent-cats-wrap .v4-persistent-cats {
  position: relative;
  top: auto; left: auto; right: auto;
}
.v5-persistent-cats-wrap::after {
  content: "";
  position: absolute;
  top: 0; right: 0; bottom: 0;
  width: 34px;
  pointer-events: none;
  background: linear-gradient(to right, rgba(23, 19, 15, 0), rgba(23, 19, 15, 0.92));
}
.v5-cat-count {
  margin-left: 5px;
  opacity: 0.72;
  font-family: "JetBrains Mono", monospace;
  font-size: 10.5px;
}

/* 頭部總高度變了，地圖起始位置要跟著調整；實際數值用瀏覽器量測
   .top-bar 渲染後的高度核對過（這次對話討論：手機版logo改成中英文
   堆疊兩行、字放大，頭部從111.5px長高到127px，這裡跟著同步調整，
   不是用手算的） */
.v5-persistent-cats-wrap {
  top: 127px;
}
/* 手機版常駐分類列已經收合成地圖下方的按鈕（不佔頭部下方的橫向空間了，
   見 index.html #mobile-cat-trigger），地圖起始點回到緊貼頭部下方即可，
   不用再額外讓出56px高度 */
/* 這次對話討論新增精選推薦提示條（原本38px高，後來為了符合44px
   觸控目標建議值調高）後，地圖起始點要跟著往下加這個高度，不然
   提示條會蓋住地圖頂端——地圖是position:fixed+寫死的top值，不會
   像一般排版那樣自動被新元素往下推開，提示條的高度要手動同步反映
   在這裡（127+44=171），這個171實際渲染後有用瀏覽器量測校對過 */
.mobile-highlight-ticker {
  top: 127px;
}
.map-area {
  top: 171px;
}

/* ---------- 13. 入口標記：讓現場遊客點擊確認自己的位置
   跟攤位標記（.map-marker，紅色小圓點）刻意用完全不同的視覺語言，
   一眼就能分辨「這是入口，不是攤位」。固定顯示，不受分類篩選/
   輪播影響（見 js/entrance-markers.js 的獨立設計說明）。 ---------- */
.entrance-marker-layer {
  position: absolute;
  inset: 0;
}
.entrance-marker {
  position: absolute;
  width: 26px;
  height: 26px;
  margin-left: -13px;
  margin-top: -13px;
  border-radius: 50%;
  /* 渾圓有光澤的立體按鈕感：放射狀漸層模擬左上反光，
     內陰影疊加做出「拋光圓珠」的深度，不是純色平面色塊 */
  background: radial-gradient(circle at 32% 28%, #82aeea 0%, #3f6fc0 45%, #1e4278 100%);
  border: 1.5px solid rgba(255, 255, 255, 0.9);
  box-shadow:
    inset 0 2px 3px rgba(255, 255, 255, 0.55),
    inset 0 -3px 4px rgba(0, 0, 0, 0.3),
    0 2px 6px rgba(0, 0, 0, 0.4);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 13px;
  cursor: pointer;
  z-index: 6; /* 攤位一般狀態 z-index:5，入口常駐顯示要在上面一點，
                 但選中/呼吸中的攤位(z-index 8~10)還是要蓋過入口 */
  transition: transform 0.15s ease, box-shadow 0.15s ease;
}
.entrance-marker:active {
  transform: scale(0.92);
}
/* 桌機限定的hover效果：純CSS、不觸發JS、不會叫出名稱/照片標籤
   （那是點擊才會有的獨立行為），滑鼠移開立刻恢復，不用像點擊那樣
   維持5秒。手機是觸控裝置沒有真正的hover狀態，只在桌機生效 */
@media (min-width: 769px) {
  .entrance-marker:hover {
    transform: scale(1.15);
    box-shadow:
      inset 0 2px 3px rgba(255, 255, 255, 0.55),
      inset 0 -3px 4px rgba(0, 0, 0, 0.3),
      0 2px 6px rgba(0, 0, 0, 0.4),
      0 0 10px 4px rgba(47, 95, 168, 0.5);
  }
}

/* 點擊後的呼吸燈：跟攤位「看地圖位置」共用同一種節奏感（1.25s
   ease-in-out 循環），但顏色改成藍色系，跟入口本身的藍色呼應，
   也跟攤位的金色呼吸燈區隔開，不會搞混兩種不同的「被強調」狀態。
   box-shadow 要把原本立體按鈕的 inset 陰影也一起帶著循環，
   不然閃爍的時候會蓋掉光澤感、變回平面 */
@keyframes v6-entrance-breathe {
  0%, 100% {
    box-shadow:
      inset 0 2px 3px rgba(255, 255, 255, 0.55),
      inset 0 -3px 4px rgba(0, 0, 0, 0.3),
      0 0 0 5px rgba(47, 95, 168, 0.35), 0 2px 6px rgba(0, 0, 0, 0.4);
  }
  50% {
    box-shadow:
      inset 0 2px 3px rgba(255, 255, 255, 0.55),
      inset 0 -3px 4px rgba(0, 0, 0, 0.3),
      0 0 0 10px rgba(47, 95, 168, 0.15), 0 0 20px 6px rgba(47, 95, 168, 0.5);
  }
}
.entrance-marker.active {
  width: 30px;
  height: 30px;
  margin-left: -15px;
  margin-top: -15px;
  font-size: 15px;
  z-index: 9;
  animation: v6-entrance-breathe 1.25s ease-in-out infinite;
}

/* ---------- 13b. 廁所標記：跟入口標記共用同一套「常駐玻璃圓珠」互動
   語言（點擊放大+呼吸燈+浮動名稱/照片標籤，見js/restroom-markers.js），
   但顏色換成青綠色系（不是入口的藍、也不是攤位的紅/金），而且圖示
   直接常駐顯示（🚻），不用像入口一樣點了才知道是什麼——廁所屬於
   「重要提醒」等級的地標，希望使用者掃過地圖就能一眼找到，不用先
   點擊才發現。 ---------- */
.restroom-marker-layer {
  position: absolute;
  inset: 0;
}
.restroom-marker {
  position: absolute;
  width: 26px;
  height: 26px;
  margin-left: -13px;
  margin-top: -13px;
  border-radius: 50%;
  background: radial-gradient(circle at 32% 28%, #6fdbc4 0%, #1f9a80 45%, #0d5c4a 100%);
  border: 1.5px solid rgba(255, 255, 255, 0.9);
  box-shadow:
    inset 0 2px 3px rgba(255, 255, 255, 0.55),
    inset 0 -3px 4px rgba(0, 0, 0, 0.3),
    0 2px 6px rgba(0, 0, 0, 0.4);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 13px;
  cursor: pointer;
  z-index: 6;
  transition: transform 0.15s ease, box-shadow 0.15s ease;
}
.restroom-marker:active {
  transform: scale(0.92);
}
/* 桌機限定的hover效果，跟入口標記同一套邏輯，只是光暈顏色換成
   廁所自己的青綠色，跟標記本身顏色一致 */
@media (min-width: 769px) {
  .restroom-marker:hover {
    transform: scale(1.15);
    box-shadow:
      inset 0 2px 3px rgba(255, 255, 255, 0.55),
      inset 0 -3px 4px rgba(0, 0, 0, 0.3),
      0 2px 6px rgba(0, 0, 0, 0.4),
      0 0 10px 4px rgba(31, 154, 128, 0.5);
  }
}
@keyframes v6-restroom-breathe {
  0%, 100% {
    box-shadow:
      inset 0 2px 3px rgba(255, 255, 255, 0.55),
      inset 0 -3px 4px rgba(0, 0, 0, 0.3),
      0 0 0 5px rgba(31, 154, 128, 0.35), 0 2px 6px rgba(0, 0, 0, 0.4);
  }
  50% {
    box-shadow:
      inset 0 2px 3px rgba(255, 255, 255, 0.55),
      inset 0 -3px 4px rgba(0, 0, 0, 0.3),
      0 0 0 10px rgba(31, 154, 128, 0.15), 0 0 20px 6px rgba(31, 154, 128, 0.5);
  }
}
.restroom-marker.active {
  width: 30px;
  height: 30px;
  margin-left: -15px;
  margin-top: -15px;
  font-size: 15px;
  z-index: 9;
  animation: v6-restroom-breathe 1.25s ease-in-out infinite;
}

/* 浮動標籤：固定位置（不跟著入口點位跑），理由是入口可能落在地圖
   邊角，錨定在點位上容易被外框裁切，尤其手機版空間更窄。固定貼在
   地圖框頂端，跟底部的 .v4-map-plate 標示牌各自佔用上下不同位置，
   不會互相打架 */
/* .entrance-label 的 display:flex 是 class selector，優先權會蓋掉
   瀏覽器預設的 [hidden]{display:none} 規則（同樣是屬性選擇器，但
   使用者樣式表優先權本來就贏過瀏覽器預設樣式表），沒有這條的話
   標籤在還沒點擊入口、hidden屬性明明是true的情況下也會被強制顯示 */
.entrance-label[hidden] {
  display: none;
}
.entrance-label {
  position: absolute;
  /* 手機版 .v5-persistent-cats-wrap 是懸浮在地圖頂端的分類列（見第12段），
     貼在地圖框最上面會被那排分類 chips 蓋住，所以往下讓開它的高度
     （約56px）+ 一點緩衝。桌機版沒有這個懸浮分類列，貼近頂端沒問題，
     但用同一個數值兩邊都測試過視覺上OK，不用另外切版本 */
  top: 64px;
  left: 50%;
  /* 動畫預設 animation-fill-mode 是 none，動畫跑完後 transform 會
     回到「沒有動畫時」的樣子，也就是這行的值，不是 keyframe 最後一格
     的值——這行拿掉的話，動畫結束當下標籤會瞬間失去置中位移，
     整個滑到畫面右邊出框，之前少寫這行就是這個bug */
  transform: translateX(-50%);
  z-index: 20;
  display: flex;
  align-items: center;
  gap: 8px;
  max-width: calc(100% - 32px);
  padding: 6px 14px 6px 6px;
  background: rgba(23, 19, 15, 0.9);
  /* 邊框顏色跟隨標記本身的顏色（入口=藍，廁所另外在.restroom-label
     覆寫成青綠），讓彈窗一眼看得出是哪種標記跳出來的 */
  border: 1px solid rgba(47, 95, 168, 0.5);
  border-radius: 14px;
  box-shadow: 0 6px 20px rgba(0, 0, 0, 0.4);
  animation: v6-entrance-label-in 0.35s cubic-bezier(0.22, 1, 0.36, 1);
}
.restroom-label {
  border-color: rgba(31, 154, 128, 0.5);
}
.restroom-label .entrance-label-photo-fallback {
  background: #1f9a80;
}
/* 淡出關閉：js/entrance-markers.js 會先加這個 class，等動畫跑完
   （250ms）才真的把 hidden 屬性設回去，不是直接消失 */
.entrance-label.closing {
  animation: v6-entrance-label-out 0.25s ease forwards;
}
/* 兩個 keyframes 都要包含 translateX(-50%)（用來維持水平置中），
   不能只留在 base rule 裡——動畫播放期間 transform 是完全被
   keyframe 接管的，base rule 的 transform 不會生效，漏寫的話
   動畫播放中標籤會偏移、動畫結束才「跳」回置中，很突兀 */
@keyframes v6-entrance-label-in {
  from {
    opacity: 0;
    transform: translateX(-50%) translateY(-14px) scale(0.85);
  }
  to {
    opacity: 1;
    transform: translateX(-50%) translateY(0) scale(1);
  }
}
@keyframes v6-entrance-label-out {
  from {
    opacity: 1;
    transform: translateX(-50%) translateY(0) scale(1);
  }
  to {
    opacity: 0;
    transform: translateX(-50%) translateY(-10px) scale(0.9);
  }
}
/* 照片用長方形（不是圓形），高度是原本的2.5倍（34px→85px），
   寬度同比例放大（56px→140px），維持同樣的長寬比。
   大小先跟實際照片會用的尺寸一致，之後真的照片放進去不會因為
   容器尺寸變動造成版面跳動。
   選擇器故意寫成「.entrance-label .entrance-label-photo」而不是單純
   「.entrance-label-photo」——因為main.css有一條更早的規則
   ".map-area-desktop img{width:100%;height:100%}"，範圍太寬，
   這個標籤的縮圖剛好也在.map-area-desktop底下會被誤套用，撐成跟
   地圖一樣大。兩個class疊加的優先權才蓋得過那條規則（單一class蓋不過
   「一個class+一個標籤」的組合，實測踩過這個坑，入口跟廁所標籤
   都受影響，這裡在源頭修正，兩邊會一起正確） */
.entrance-label .entrance-label-photo {
  width: 140px;
  height: 85px;
  border-radius: 8px;
  /* 細金框呼應地圖外框本身「裝框展示」的質感，讓照片像被好好收在
     畫框裡，不是隨手貼一張圖上去 */
  border: 2px solid var(--nm-gold);
  object-fit: cover;
  flex-shrink: 0;
}
.entrance-label-photo-fallback {
  display: none;
  width: 140px;
  height: 85px;
  border-radius: 8px;
  border: 2px solid var(--nm-gold);
  background: #2f5fa8;
  color: #fff;
  font-size: 32px;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  box-sizing: border-box;
}
/* 照片載入失敗時（js/entrance-markers.js 偵測 img error 加上這個
   class）：藏起破圖的 img，改顯示門型圖示佔位，邏輯跟攤位卡片照片
   容錯處理一致 */
.entrance-label.no-photo .entrance-label-photo {
  display: none;
}
.entrance-label.no-photo .entrance-label-photo-fallback {
  display: flex;
}
.entrance-label-name {
  font-family: "Noto Serif TC", serif;
  font-size: 13px;
  font-weight: 700;
  color: var(--nm-paper);
  white-space: nowrap;
}

/* ---------- 14. 桌機版攤位清單：滑鼠移入被截斷的名稱時跑馬燈展示完整文字
   只作用在 #stall-list-desktop（js/list-marquee.js 有寫清楚範圍），
   不影響手機版清單、收藏彈窗清單、搜尋結果——那些沿用同一個
   .stall-row/.name-zh/.name-en class，但不會被這裡的邏輯選到。
   讚數徽章（.row-like-count）是同一行裡的獨立 flex 元素，不在
   捲動的文字容器內，滑鼠移入時文字捲動也不會牽動到它。

   結構是「外層固定窗口＋內層文字滑動」兩層，不能只用一個元素
   兼職裁切+位移（那樣裁切邊界會跟著文字一起移動，永遠露不出
   新內容，之前踩過這個坑）：
     .name-line-wrap（js/stalls-list.js 新增的包裝 div）
       負責 overflow:hidden，寬度固定＝數字編號跟讚數之間的可視空間，
       不管文字滑到哪裡，這層的裁切邊界永遠不動
     .name-zh / .name-en（實際文字）
       平常維持原本 main.css 的自我裁切+刪節號（外觀不變）；
       hover 觸發 .marquee-active 時關掉自我裁切，改用完整內容寬度
       渲染，交給外層 wrap 裁切，同時套用 transform 位移

   跑馬燈效果是「從可視窗口右側外面完全看不到的地方進場，往左
   持續移動、完整經過窗口，移出左側外面完全看不到後，瞬間重置回
   右側外面再開始下一輪」——重置的瞬間文字是完全不可見的，所以
   視覺上是無縫循環，不會看到跳動。 ---------- */
.name-line-wrap {
  overflow: hidden;
  min-width: 0;
  max-width: 100%;
}
#stall-list-desktop .stall-row .name-line-wrap {
  width: 100%; /* 桌機版 .info 是 flex-direction:column + align-items:flex-start，
                  子元素預設不會自動撐滿寬度，這裡強制撐滿，窗口寬度才會穩定 */
}

@keyframes v6-name-marquee {
  from { transform: translateX(var(--marquee-start, 0px)); }
  to { transform: translateX(var(--marquee-end, 0px)); }
}
/* 用跟 main.css 裡 #stall-list-desktop .stall-row .name-zh／.name-en
   相同前綴的選擇器（ID+多層class），優先權才蓋得過去，只加
   .marquee-active 這種單純疊 class 的寫法優先權不夠，會被原本的
   max-width:100%／overflow:hidden 蓋掉，之前踩過這個坑 */
#stall-list-desktop .stall-row .name-zh.marquee-active,
#stall-list-desktop .stall-row .name-en.marquee-active {
  max-width: none;
  overflow: visible;
  text-overflow: clip;
  animation-name: v6-name-marquee;
  animation-timing-function: linear;
  animation-iteration-count: infinite;
  /* animation-duration／--marquee-start／--marquee-end 由
     js/list-marquee.js 依每行實際文字寬度各自用 inline style 設定 */
}

/* ---------- 15. 分類標籤：滑鼠游標 + 點擊Q彈回饋
   <button> 元素預設游標是箭頭，不是手掌，跟其他可點擊元素（例如
   <a>連結）不一致，桌機版滑鼠移到分類標籤上沒有「這個可以點」的
   提示，這裡統一補上 cursor:pointer（手機觸控裝置不受影響，
   加了也無害）。 ---------- */
.category-tag {
  cursor: pointer;
}

/* 點擊回饋：放大跳動一下再彈回，跟卡片「按讚」按鈕共用同一種節奏感，
   由 js/tag-bounce.js 用事件代理統一觸發，涵蓋分類標籤、收藏按鈕、
   語言切換按鈕（不用個別接線）。class 名稱不再綁 .category-tag 前綴，
   因為現在套用範圍不只分類標籤了 */
@keyframes v6-tag-bounce {
  0% { transform: scale(1); }
  35% { transform: scale(1.12); }
  60% { transform: scale(0.96); }
  80% { transform: scale(1.04); }
  100% { transform: scale(1); }
}
.tag-bouncing {
  animation: v6-tag-bounce 0.35s ease;
}

/* ---------- 16. 圖例「？」按鈕：改成實心金色，跟深色背景區隔更明顯
   原本深色底+細金框+暗金色問號，跟頁面背景融在一起不夠顯眼。
   金色在這個網站本來就是「強調/選中」的代表色（選中的地圖標記、
   收藏狀態都是實心金色），這裡沿用同一套語言，不用發明新顏色 ---------- */
/* 桌機版「？」按鈕的位置背景跟深色外框顏色太接近，單純深色框對比不夠
   （用瀏覽器算出來的樣式確認過，CSS確實有套用，只是視覺上疊在一起
   看不出來，不是規則沒生效）。改成三層疊出對比：金色底 + 一圈亮色
   細框（跟底色/外框都有反差）+ 最外層黑框，不管落在深色或淺色
   背景上都看得清楚，不是賭深色框跟背景剛好不撞色 */
.legend-btn {
  background: var(--nm-gold);
  border: 2.5px solid var(--nm-night-deep);
  box-shadow: 0 0 0 2px var(--nm-paper), 0 2px 8px rgba(0, 0, 0, 0.4);
  color: var(--nm-ink);
}
/* 桌機限定hover：跟地圖上入口/廁所標記同一套語言（放大+對應色系光暈），
   「?」按鈕本身也是地圖角落的一顆圖示，視覺上統一處理 */
@media (min-width: 769px) {
  .legend-btn:hover {
    transform: scale(1.12);
    box-shadow: 0 0 0 2px var(--nm-paper), 0 2px 8px rgba(0, 0, 0, 0.4),
      0 0 10px 4px rgba(232, 178, 60, 0.5);
  }
}

/* ---------- 17. 手機版搜尋面板：底部固定一顆「關閉搜尋」按鈕
   原本只能靠「點面板以外的地方」關閉，不夠直覺，尤其面板幾乎佔滿
   整個畫面時使用者不一定知道要點哪裡。這裡讓面板變成上下兩段：
   上面是可以捲動的內容（提示/結果），下面固定貼著一顆關閉按鈕，
   結果再多也不會把按鈕往下推到看不見。 ---------- */
.v5-search-panel {
  display: flex;
  flex-direction: column;
}
.v5-search-panel-content {
  flex: 1;
  overflow-y: auto;
  padding: 16px;
}
.v5-search-close-btn {
  flex-shrink: 0;
  padding: 14px;
  background: rgba(255, 255, 255, 0.06);
  border: none;
  border-top: 1px solid rgba(232, 178, 60, 0.3);
  color: var(--nm-paper);
  font-family: "Work Sans", sans-serif;
  font-size: 14px;
  font-weight: 600;
  cursor: pointer;
}
.v5-search-close-btn:active {
  background: rgba(232, 178, 60, 0.15);
}

/* ---------- 18. 聯絡我們（攤販/熱心遊客留言）
   桌機版：footer裡的觸發按鈕（js/contact.js 動態補插入，因為 footer本身
   是 intro.js renderFooter() 動態渲染的），點了開 #contact-modal
   （獨立小彈窗，.contact-sheet 蓋掉預設 480px 寬度，做得比較精簡）。
   手機版：ℹ️簡介彈窗最下面補一顆同款觸發按鈕，點了不疊新彈窗，
   是同一個彈窗內容切換（#intro-main-view-mobile ↔
   #intro-contact-view-mobile 用 [hidden] 切換，瀏覽器預設
   [hidden]{display:none} 就夠用，這兩個是全新id沒有其他規則搶優先權，
   不用像其他地方一樣額外補[hidden]覆寫）。 ---------- */
.contact-trigger-btn {
  border: 1px solid rgba(232, 178, 60, 0.4);
  border-radius: 20px;
  background: var(--nm-paper-dim);
  color: var(--nm-ink);
  font-family: "Work Sans", sans-serif;
  font-size: 12.5px;
  font-weight: 600;
  cursor: pointer;
}
.contact-trigger-desktop {
  display: block;
  margin: 14px auto 0;
  padding: 8px 18px;
}
.contact-trigger-desktop:hover {
  background: #dbcba1;
}
.contact-trigger-mobile {
  display: block;
  width: 100%;
  margin-top: 16px;
  padding: 10px 14px;
}

.contact-back-btn {
  /* 這顆按鈕放在 .intro-body 外面，吃不到它的20px留白（.intro-sheet
     本身是padding:0），原本沒補padding會直接貼齊最左邊，跟右上角
     有12px留白的✕關閉鈕不對稱，這裡補上跟其他內容一致的留白 */
  display: block;
  border: none;
  background: none;
  padding: 16px 20px 4px;
  color: var(--nm-ink-soft);
  font-family: "Work Sans", sans-serif;
  font-size: 12.5px;
  font-weight: 600;
  cursor: pointer;
}

/* 手機版切換視圖跟桌機版獨立彈窗共用同一份表單樣式（js/contact.js
   buildFormHtml() 產出的內容注入到兩個不同容器裡） */
.contact-hint {
  font-size: 12px;
  line-height: 1.6;
  color: var(--nm-ink-soft);
  margin: 0 0 14px;
}
.contact-field-label {
  display: block;
  font-size: 12px;
  font-weight: 600;
  color: var(--nm-ink);
  margin-bottom: 12px;
}
/* .contact-field-label{display:block} 是 class selector，優先權會蓋掉
   瀏覽器預設的 [hidden]{display:none}（這個坑在搜尋面板、入口標記浮動
   標籤、v5-active-filter-tag 都踩過，這裡先主動補上） */
.contact-field-label[hidden] {
  display: none;
}
.contact-message-input,
.contact-info-input {
  display: block;
  width: 100%;
  margin-top: 6px;
  padding: 10px 12px;
  border: 1px solid var(--nm-paper-dim);
  border-radius: 10px;
  background: #fff;
  color: var(--nm-ink);
  font-family: "Work Sans", sans-serif;
  font-size: 13px;
  box-sizing: border-box;
  resize: vertical;
}
.contact-message-input:focus,
.contact-info-input:focus {
  outline: none;
  border-color: var(--nm-gold);
}
.contact-submit-btn {
  width: 100%;
  padding: 12px;
  border: none;
  border-radius: 10px;
  background: var(--nm-gold);
  color: var(--nm-ink);
  font-family: "Work Sans", sans-serif;
  font-size: 14px;
  font-weight: 700;
  cursor: pointer;
}
.contact-submit-btn:hover {
  background: #f0c368;
}
.contact-submitted-msg {
  margin: 0;
  padding: 14px;
  border-radius: 10px;
  background: rgba(232, 178, 60, 0.15);
  color: var(--nm-ink);
  font-size: 13px;
  font-weight: 600;
  text-align: center;
}

/* 桌機版聯絡彈窗：原本蓋掉預設480px做成360px精簡版，但後來加了QR code
   區塊要跟表單左右並排，360px塞不下兩欄，所以放寬到560px——比原本
   480px的預設彈窗還寬，但因為版面規劃得比較緊湊，實際看起來還是比
   收藏/圖例那種通用彈窗更「量身訂做」，不會顯得鬆散 */
.contact-sheet {
  max-width: 560px;
}

/* 表單欄位 + QR code區塊：手機版（單欄，寬度較窄）預設上下排，
   桌機版（.contact-sheet裡）改成左右並排中間一條分隔線
   （見 js/contact.js buildFormHtml()，兩邊容器共用同一份HTML，
   只靠外層容器id切換排列方向，不用維護兩份標記） */
.contact-layout {
  display: flex;
  flex-direction: column;
  gap: 16px;
}
#contact-form-desktop .contact-layout {
  flex-direction: row;
  align-items: stretch;
}
.contact-fields {
  min-width: 0;
}
#contact-form-desktop .contact-fields {
  flex: 1 1 auto;
}
.contact-qr-divider {
  border-top: 1px dashed var(--nm-paper-dim);
}
#contact-form-desktop .contact-qr-divider {
  border-top: none;
  border-left: 1px dashed var(--nm-paper-dim);
  width: 0;
}
.contact-qr-panel {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 10px;
  text-align: center;
}
#contact-form-desktop .contact-qr-panel {
  flex: 0 0 140px;
}
/* 桌機版：LINE加好友QR code圖片（assets/images/contact-line-qr.png），
   固定120×120正方形，跟原本佔位框尺寸一致 */
.contact-qr-image {
  display: block;
  width: 120px;
  height: 120px;
  object-fit: contain;
  border: 1px solid var(--nm-paper-dim);
  border-radius: 10px;
  background: #fff;
  padding: 6px;
  box-sizing: border-box;
}
.contact-qr-caption {
  margin: 0;
  font-size: 11.5px;
  color: var(--nm-ink-soft);
  line-height: 1.5;
}

/* honeypot欄位：真人看不到、Tab不到、螢幕閱讀器也跳過（aria-hidden），
   但機器人看DOM讀得到、常會自動填掉，見 js/contact.js 表單裡的說明。
   故意不用 display:none——部分比較聰明的機器人會跳過偵測到的
   display:none欄位，這裡改用標準的「視覺隱藏但仍在文件內」寫法
   （clip+1px+負margin），不會像 left:-9999px 那樣在彈窗裡撐出一塊
   可以被捲動出來的空白區域 */
.contact-hp-field {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

/* 手機版：QR code顯示在使用者自己手上這支手機的螢幕上，沒辦法拿同一支
   手機掃自己，所以用一顆直連加好友短網址的按鈕取代QR code圖片（見
   js/contact.js buildQrOrButtonHtml()）。用LINE官方品牌綠色，
   一眼就能看出是「LINE相關」的操作，跟金色系的其他按鈕做出區隔 */
.contact-line-add-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 10px 20px;
  border-radius: 20px;
  background: #06c755;
  color: #fff;
  font-family: "Work Sans", sans-serif;
  font-size: 13px;
  font-weight: 700;
  text-decoration: none;
  white-space: nowrap;
}
.contact-line-add-btn:hover {
  background: #05b34c;
}

/* ---------- 19. 攤位清單：號碼徽章染分類色
   卡片本身維持原本白底樣式不變，只把每一列最前面的號碼徽章
   （.num）染成該攤位分類的顏色，餘光掃過去就能分辨鹹食/甜點/
   飲料...不用逐行讀文字。顏色只是視覺輔助，篩選邏輯完全沒動，
   沿用 js/stalls-list.js 本來就有寫的 row.dataset.category ---------- */
.stall-row[data-category="savory"]      .num { background: #e0562f; color: #fff; }
.stall-row[data-category="dessert"]     .num { background: #d9527e; color: #fff; }
.stall-row[data-category="drink"]       .num { background: #3f6fc0; color: #fff; }
.stall-row[data-category="clothing"]    .num { background: #8a5fc2; color: #fff; }
.stall-row[data-category="accessories"] .num { background: #2f9e7a; color: #fff; }
.stall-row[data-category="toys_games"]  .num { background: #4f9e4f; color: #fff; }
.stall-row[data-category="other"]       .num { background: #9c8a6a; color: #fff; }

/* 搜尋結果列表（js/search-filter.js renderResultRow()）右側的分類色塊，
   原本固定用 --nm-paper-dim 底、--nm-ink-soft 文字，跟 .num 徽章一樣
   套上分類色。這裡底色是飽和度較高的顏色，原本偏中間調的文字色
   （--nm-ink-soft）在深色系（accessories/toys_games）對比會不夠，
   統一改白字，7個分類色都測過白字對比足夠，不用再逐色微調 */
.stall-row[data-category="savory"]      .search-category-tag { background: #e0562f; color: #fff; }
.stall-row[data-category="dessert"]     .search-category-tag { background: #d9527e; color: #fff; }
.stall-row[data-category="drink"]       .search-category-tag { background: #3f6fc0; color: #fff; }
.stall-row[data-category="clothing"]    .search-category-tag { background: #8a5fc2; color: #fff; }
.stall-row[data-category="accessories"] .search-category-tag { background: #2f9e7a; color: #fff; }
.stall-row[data-category="toys_games"]  .search-category-tag { background: #4f9e4f; color: #fff; }
.stall-row[data-category="other"]       .search-category-tag { background: #9c8a6a; color: #fff; }

/* 選中狀態的金色徽章優先權要蓋過分類色，不然選到哪一列看不出來 */
.stall-row.selected .num { background: var(--nm-gold); color: var(--nm-ink); }

/* ---------- 20. 桌機版 footer：獨立成一個區塊 + 聯絡我們/版權順序對調
   原本 .desktop-footer 沒有自己的底色，直接透在頁面底色上，跟上面
   地圖區塊的深色視覺融在一起，滑到最下面看不出「這裡才是頁尾」。
   改法：.desktop-footer 本身變成一條全寬色帶（自己的底色＋頂部
   細金線切割），裡面再用 .footer-inner 沿用原本 max-width 置中的
   內距設定（見 js/intro.js buildFooterHtml() 的 wrapper）。
   另外「聯絡我們」按鈕原本用 insertAdjacentHTML beforeend 插在
   版權宣告後面，改成 afterbegin 插到前面（見 js/contact.js
   renderTriggers()）——操作性內容排在上面，法律聲明放最下面，
   比較符合一般頁尾的閱讀順序 ---------- */
.desktop-footer {
  max-width: none;
  width: 100%;
  padding: 0;
  background: var(--nm-night);
  border-top: 2px solid rgba(232, 178, 60, 0.45);
  box-shadow: inset 0 8px 12px -8px rgba(0, 0, 0, 0.6);
}
/* footer 改成單行式：地址、更新日期、Contact Us按鈕、版權宣告
   全部排在同一條基準線上，用細直線（.footer-sep）隔開每一段。
   不會再有「兩欄/三欄高度不一樣、對不齊」的問題，因為所有東西
   本來就在同一行，只有寬度不夠時才會自動換行（flex-wrap）。
   整行用 justify-content:center 置中，不特別去頂 footer 左右邊緣，
   兩側留白是自然產生的，不用額外處理 */
.footer-inner {
  max-width: 1440px;
  margin: 0 auto;
  padding: 16px 32px;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 14px;
  flex-wrap: wrap;
}
.footer-seg {
  font-size: 12px;
  color: var(--nm-paper-dim);
  white-space: nowrap;
}
.footer-updated,
.footer-copyright {
  font-size: 11px;
  color: #7a6d55;
}
.footer-sep {
  width: 1px;
  height: 12px;
  background: rgba(232, 178, 60, 0.3);
  flex-shrink: 0;
}
.footer-col-center {
  display: inline-flex;
  align-items: center;
}
.contact-trigger-desktop {
  margin: 0;
  padding: 6px 16px;
}

/* 「聯絡我們」按鈕加上過渡動畫，滑過去有輕微浮起感，
   跟清單列/地圖標記的hover語彙一致，不是單純顏色瞬間切換 */
.contact-trigger-btn {
  transition: background 0.2s ease, transform 0.15s ease, box-shadow 0.2s ease;
}
@media (min-width: 769px) {
  .contact-trigger-desktop:hover {
    transform: translateY(-1px);
    box-shadow: 0 4px 10px rgba(0, 0, 0, 0.3);
  }
}

/* ---------- 21. 攤位列表標題列：計數改成小晶片 + 桌機版固定在頂部
   「共 277 攤」原本是純文字，改成跟 .num 徽章/分類標籤同語彙的
   小圓角色塊，比較有存在感。桌機版側欄本身就是可捲動的容器
   （.desktop-sidebar），把標題列改成 position:sticky 貼在頂部，
   往下捲清單時還是看得到攤位總數，不用捲回最上面才知道。
   用「負margin展開＋補padding」是sticky+有padding的容器常見寫法：
   父層 .desktop-sidebar 本身有16px padding，sticky的top若直接設0，
   會停在padding邊界下方，還留一截縫；改成 top:-16px 並用負margin
   把標題列撐滿容器寬度，自己重新補一份padding，才會真正貼齊頂部。
   下面用一條淡金線＋往下暈開的陰影做分隔，捲動時内容從陰影下方
   滑過去，比死板的一條硬線自然 ---------- */
.desktop-stall-count,
.drawer-count {
  background: var(--nm-paper-dim);
  border-radius: 10px;
  padding: 3px 9px;
}
@media (min-width: 769px) {
  /* 標題改成跟地圖標示牌（.v4-map-plate）同一套視覺語言：飄浮置中的
     深色小圓角標牌，不是貫穿滿版寬度、底下切一條分隔線的工具列。
     金邊+相框感的外框現在兩塊統一了，但滿版工具列 vs 飄浮小標牌
     這種標題呈現方式的反差比外框本身更搶眼，所以這裡直接比照地圖
     標示牌的樣式做（實測發現的問題，見這次對話討論）。
     position:sticky 保留，捲動清單時標題還是會固定在頂端 */
  .desktop-sidebar-title-row {
    display: flex;
    justify-content: center;
    position: sticky;
    top: 8px;
    z-index: 2;
    margin: 0 0 12px;
  }
  .desktop-sidebar-title {
    background: rgba(23, 19, 15, 0.85);
    border: 1px solid rgba(232, 178, 60, 0.4);
    border-radius: 20px;
    padding: 5px 18px;
    font-size: 12.5px;
    color: var(--nm-paper);
    white-space: nowrap;
  }
}

/* ---------- 22. 分類標籤：加上對應分類色的色線 + hover 光暈
   跟清單裡 .num 徽章共用同一組分類色（見上面第19段），讓使用者能把
   「這顆分類按鈕」跟「清單裡那個顏色的攤位」聯想在一起。
   色線放在底部（不是頂部），不內縮，直接用 border-bottom 整條貼齊
   按鈕寬度——放頂部時跟著圓角往上翹會有「戴帽子」的違和感，放底部
   走同樣的弧度反而比較像一般 tab/pill 常見的「底線指示條」，不用
   刻意內縮處理。
   選中狀態(.active)背景會變金色，但色線刻意不跟著消失或變色──
   選中/未選中是互動狀態，色線是分類身份，兩者分開表達（.active
   原本用 border-color 蓋掉四邊框線，這裡的 border-bottom 規則
   宣告在後面，優先權打平後贏過它，兩種狀態都看得到色線）。
   Hover 用該分類顏色的淺光暈＋一點上浮位移，增加立體感回饋，
   跟入口/廁所地圖標記、Contact Us 按鈕現在的 hover 語彙一致，
   只在桌機生效（觸控裝置沒有hover，套了也沒意義） ---------- */
.category-tag[data-category="savory"]      { border-bottom: 3px solid #e0562f; }
.category-tag[data-category="dessert"]     { border-bottom: 3px solid #d9527e; }
.category-tag[data-category="drink"]       { border-bottom: 3px solid #3f6fc0; }
.category-tag[data-category="clothing"]    { border-bottom: 3px solid #8a5fc2; }
.category-tag[data-category="accessories"] { border-bottom: 3px solid #2f9e7a; }
.category-tag[data-category="toys_games"]  { border-bottom: 3px solid #4f9e4f; }
.category-tag[data-category="other"]       { border-bottom: 3px solid #9c8a6a; }

@media (min-width: 769px) {
  .category-tag {
    transition: transform 0.12s ease, background 0.15s ease, border-color 0.15s ease, box-shadow 0.2s ease;
  }
  .category-tag[data-category="savory"]:hover      { transform: translateY(-1px); box-shadow: 0 0 10px 2px rgba(224, 86, 47, 0.3); }
  .category-tag[data-category="dessert"]:hover     { transform: translateY(-1px); box-shadow: 0 0 10px 2px rgba(217, 82, 126, 0.3); }
  .category-tag[data-category="drink"]:hover       { transform: translateY(-1px); box-shadow: 0 0 10px 2px rgba(63, 111, 192, 0.3); }
  .category-tag[data-category="clothing"]:hover    { transform: translateY(-1px); box-shadow: 0 0 10px 2px rgba(138, 95, 194, 0.3); }
  .category-tag[data-category="accessories"]:hover { transform: translateY(-1px); box-shadow: 0 0 10px 2px rgba(47, 158, 122, 0.3); }
  .category-tag[data-category="toys_games"]:hover  { transform: translateY(-1px); box-shadow: 0 0 10px 2px rgba(79, 158, 79, 0.3); }
  .category-tag[data-category="other"]:hover       { transform: translateY(-1px); box-shadow: 0 0 10px 2px rgba(156, 138, 106, 0.3); }
}

/* ---------- 23. 桌機版搜尋框補上放大鏡icon
   手機版搜尋列本來就有 .v5-search-icon，桌機版之前沒有。
   桌機版的視覺結構跟手機版不同：手機是「外層膠囊wrap自己有底色/邊框，
   icon跟input都是裡面單純的flex子項」；桌機是「input自己就有底色/
   邊框」，所以icon不能用flex排列（會被擠到input外面變成兩個獨立方塊），
   改成絕對定位疊在input左側內部，input自己加左邊距讓文字不會被icon
   蓋到 ---------- */
.desktop-search-wrap .desktop-search-icon {
  position: absolute;
  left: 12px;
  top: 50%;
  transform: translateY(-50%);
  font-size: 12.5px;
  pointer-events: none;
}
@media (min-width: 769px) {
  .desktop-search-input {
    padding-left: 34px;
  }
}

/* ---------- 24. SEO：畫面上看不到、但搜尋引擎/螢幕閱讀器讀得到的文字
   標準的視覺隱藏寫法（不是display:none，那樣screen reader也會跳過）。
   目前用在手機版/桌機版的 <h1>（見index.html），畫面上只顯示短版的
   「🏮 樂華夜市」（版面考量，H1本來就是logo位置，不適合放長句），
   但補上一段藏起來的完整描述，讓H1本身也有關鍵字，不用犧牲UI ---------- */
.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

/* ---------- 25. 地圖標記：分類篩選時直接隱藏（不是淡化）+ 符合的染色
   原本 .dimmed 是 opacity:0.25 讓不符合的標記變淡，改成直接隱藏，
   class名稱沿用沒改，只有這裡的CSS效果變了（見 js/map-markers.js
   updateFilterState() 的說明）。符合篩選的標記則額外加 .filter-match
   class，跟清單/分類標籤共用同一組分類色（見上面第19、22段），沒有
   篩選時（.filter-match不會被加上）維持原本統一的燈籠紅，不受影響 ---------- */
.map-marker.dimmed {
  display: none;
}
.map-marker.filter-match[data-category="savory"]      { background: #e0562f; }
.map-marker.filter-match[data-category="dessert"]     { background: #d9527e; }
.map-marker.filter-match[data-category="drink"]       { background: #3f6fc0; }
.map-marker.filter-match[data-category="clothing"]    { background: #8a5fc2; }
.map-marker.filter-match[data-category="accessories"] { background: #2f9e7a; }
.map-marker.filter-match[data-category="toys_games"]  { background: #4f9e4f; }
.map-marker.filter-match[data-category="other"]       { background: #9c8a6a; }

/* 選中/收藏是「當下更重要的狀態」，優先權要蓋過分類色，邏輯比照
   上面第9段 .v4-favorited.selected 已經在處理的三態疊加規則 */
.map-marker.filter-match.selected {
  background: var(--nm-gold);
}
.map-marker.filter-match.v4-favorited {
  background: #5b4b9e;
}
.map-marker.filter-match.v4-favorited.selected {
  background: var(--nm-gold);
}

/* ---------- 26. 手機版攤位標籤：固定顯示在地圖頂端置中
   原本手機版選中攤位時，標籤跟著該攤的亮點座標浮動，每次位置都不
   一樣。改成跟入口/廁所標籤（.entrance-label）同一個固定位置——
   數值直接照抄 .entrance-label 的 top:64px/left:50%，兩者視覺對齊。
   只在 .mobile-only 的地圖標記層生效，桌機版hover/選中標籤完全不動，
   還是原本跟著亮點走的動態定位（見 js/map-markers.js
   showLocateLabelsFor() 的 fixedPosition 判斷） ---------- */
.map-marker-hover-label.fixed-top {
  top: 64px;
  left: 50%;
  transform: translateX(-50%);
}

/* ---------- 27. 「顯示我的位置」：手機限定的即時定位開關+懸浮箭頭標記
   見 js/my-location.js。箭頭浮動+陰影呼吸的動畫效果，是先在對話裡
   做SVG demo定案樣式之後才搬進來的，色系跟形狀直接照那次的版本。
   区塊切換時用 transition 平滑滑過去，不是瞬間跳到新位置。 ---------- */
.my-location-layer {
  position: absolute;
  inset: 0;
  pointer-events: none;
  z-index: 20;
}
.my-location-marker {
  position: absolute;
  transform: translate(-50%, -100%);
  display: flex;
  flex-direction: column;
  align-items: center;
  transition: left 0.6s ease-in-out, top 0.6s ease-in-out;
}
/* .my-location-marker 的 display:flex 權重蓋過瀏覽器預設的
   [hidden]{display:none}，導致關閉功能時設定 marker.hidden=true
   沒有實際生效、箭頭還留在畫面上（實測發現的真bug）。這裡補上
   對應的 [hidden] 選擇器，權重比基本規則高，才會真的隱藏 */
.my-location-marker[hidden] {
  display: none;
}
@keyframes myLocationFloat {
  0%, 100% { transform: translateY(0); }
  50% { transform: translateY(-8px); }
}
@keyframes myLocationShadowBreathe {
  0%, 100% { transform: scaleX(1); opacity: 0.35; }
  50% { transform: scaleX(0.6); opacity: 0.15; }
}
.my-location-arrow {
  animation: myLocationFloat 2.6s ease-in-out infinite;
}
.my-location-shadow {
  width: 16px;
  height: 5px;
  border-radius: 50%;
  background: var(--nm-ink);
  animation: myLocationShadowBreathe 2.6s ease-in-out infinite;
  margin-top: 2px;
}

.my-location-status {
  position: absolute;
  left: 50%;
  top: 16px;
  transform: translateX(-50%);
  max-width: calc(100% - 32px);
  padding: 8px 16px;
  border-radius: 20px;
  background: rgba(23, 19, 15, 0.9);
  border: 1px solid rgba(232, 178, 60, 0.4);
  color: var(--nm-gold);
  font-size: 12.5px;
  font-weight: 600;
  text-align: center;
  z-index: 25;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.my-location-btn {
  position: absolute;
  left: 16px;
  bottom: 16px; /* 原本因為 .v4-map-frame 會延伸進收合抽屜的把手範圍，
    這裡要墊高到100px避開；現在 #map-area 本身已經在把手上方留了92px
    空間（見第28段），.v4-map-frame 不會再延伸進把手範圍，簡單貼齊
    邊角即可，不用再墊高 */
  padding: 8px 14px;
  border-radius: 20px;
  background: var(--nm-night);
  border: 1px solid rgba(232, 178, 60, 0.4);
  color: var(--nm-gold);
  font-size: 12.5px;
  font-weight: 700;
  cursor: pointer;
  z-index: 45;
}
/* .mobile-only 的 display:block 優先權會蓋掉 [hidden] 屬性（跟這次
   對話前面 .my-location-marker 踩過的同一種真bug），暫時下架這顆
   按鈕時（見 index.html 的 hidden 屬性）要補這條才會真的藏起來 */
.my-location-btn[hidden] {
  display: none;
}
.my-location-btn.active {
  background: var(--nm-lantern);
  border-color: var(--nm-lantern-deep);
  color: #fff;
}
/* 抽屜展開時道理跟 .legend-btn 一樣，地圖看不到了這顆按鈕也跟著藏起來。
   搬進 .v4-map-frame 底下之後不再是 #drawer 的親兄弟，同層選擇器選不到，
   改用 body 上的 class（見 js/drawer.js） */
body.drawer-expanded #btn-my-location {
  display: none;
}

/* ---------- 28. 手機版地圖下方攤位瀏覽列：分類篩選收合成按鈕、
   新增左右切換+開卡片+附近攤位，取代原本蓋在地圖上的常駐分類列跟
   攤位選中時蓋在地圖上的標籤（入口/公廁的蓋在地圖上標籤不受影響，
   兩者刻意分開，見 js/stall-browser.js） ---------- */
#map-area {
  display: flex;
  flex-direction: column;
  /* 抽屜收合時會固定貼在畫面最下方露出把手（見style/main.css
     .drawer的translateY計算），#map-area原本bottom:0會讓這裡的
     瀏覽列整個蓋在把手底下、被蓋住點不到（實測發現的真bug，跟之前
     「顯示我的位置」按鈕撞到收合抽屜是同一類問題）。空出跟把手一樣
     高的距離，瀏覽列才會完整露在把手上方。
     這次對話討論才發現：這裡原本寫92px，是抽屜還沒改成膠囊造型之前
     的舊把手高度；抽屜後來（本檔案第53行附近）已經把收合露出高度
     從92px縮小成62px，這裡卻沒有跟著同步改，等於地圖底部平白多留了
     30px用不到的空間，加上精選推薦提示條佔掉的44px，手機版地圖看
     起來明顯變矮。跟62px對齊，把這30px還給地圖 */
  bottom: 62px;
}
#map-area .v4-map-frame {
  flex: 1 1 auto;
  min-height: 0;
  /* padding-top 恢復用共用的base rule（46px，見本檔案第10段），標示牌
     復原了要留這個空間，不然會蓋到地圖內容 */
  /* 這次對話討論：原本地圖框跟下面的瀏覽列是兩個各自獨立畫邊框+圓角
     的框，中間留了間距，堆疊起來看像兩張分開的卡片，使用者反應整體
     看起來破碎、不像一個整體介面。改成地圖框只留上緣圓角、拿掉底部
     邊框，直接跟下面瀏覽列的頂部接在一起，兩者合併成一個框、內部用
     一條細分隔線區分「地圖」跟「控制列」兩個區塊，不是兩個框疊著。
     這次對話討論：原本3px邊框使用者覺得太粗，改細一點——只調整
     手機版（這裡scope在#map-area底下），桌機版的.v4-map-frame
     維持原本3px不動 */
  border-width: 1.5px;
  border-bottom: none;
  border-radius: 20px 20px 0 0;
}

/* 整組瀏覽列跟上面的地圖框（.v4-map-frame）合併成同一個框——這次
   對話討論才改的，原本瀏覽列自己也有一整圈金色圓角外框，跟地圖框
   中間留了margin-top的間距，兩個框疊在一起像分開的卡片。拿掉自己的
   上緣圓角跟間距，直接接在地圖框下面，共用同一個外側邊框，只在
   接縫處留一條較細的分隔線（border-top用更細更淡的金色，不是完整
   3px粗框），視覺上才會讀成「一個框、兩個區塊」 */
.stall-browse-bar {
  flex: 0 0 auto;
  display: flex;
  align-items: stretch;
  gap: 10px;
  margin: 0 0 10px;
  padding: 12px;
  background: #2a2013;
  /* 邊框粗細跟上面合併的地圖框（#map-area .v4-map-frame）同步改細，
     兩者共用一個外框，粗細要一致 */
  border: 1.5px solid var(--nm-gold);
  border-top: 1px solid rgba(232, 178, 60, 0.35);
  border-radius: 0 0 20px 20px;
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.5), 0 0 0 4px rgba(232, 178, 60, 0.1);
}
.stall-browse-center {
  flex: 1 1 auto;
  min-width: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 10px;
}
.stall-browse-name {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  width: 100%;
  max-width: 100%;
  /* 固定寬度=中間欄可用的全部寬度，不再跟著名稱長短縮放——短名稱
     卡片小小一個、長名稱幾乎滿版，寬度不一使卡片看起來不夠工整
     （使用者反饋希望統一），改成固定滿寬，不同攤位間卡片大小
     一致。徽章+文字在卡片裡置中，不是靠左（使用者反饋） */
  /* 方案A：名稱這排原本直接浮在瀏覽列的深棕底色上，跟旁邊有實色/
     光澤感的按鈕比起來太平、不夠明顯（實機測試反饋）。這裡給它
     自己一塊底色+邊框，讓它從背景「浮」出來，變成一張自己的小卡片，
     不是純文字貼在背景上。
     淺底深字（反色強調）：原本用深底金字，跟網站其他地方（標題/
     按鈕文字）視覺語言太像，切換攤位時不夠有感（實機測試反饋）。
     整個介面都是深色系，唯獨這張卡片用相反的淺色調，反差夠大，
     切換攤位時比較容易被注意到。顏色沿用網站既有的另一組配色
     （攤位清單展開時的紙感底 + 深墨字），不是新配色 */
  background: var(--nm-paper);
  border: 2px solid var(--nm-gold);
  border-radius: 12px;
  padding: 6px 14px;
  /* 「請選擇攤位」這句提示文字是直接寫進這一層（沒有攤位可選時，
     js/stall-browser.js 的 updateNameText() 不會經過下面
     .stall-browse-name-text 那個 span），這裡要補上跟
     .stall-browse-name-text 一樣的深墨色，不然沒設顏色的話會吃到
     瀏覽器預設黑色（剛好也接近，但不是特意設定的，明確寫出來才保險）*/
  color: var(--nm-ink);
  /* 固定保留兩行高度，不管名稱實際是一行還是兩行，避免外框跟著
     名稱長短「呼吸」忽高忽低（實機測試反饋的真bug），順便讓名稱
     跟底下按鈕列之間永遠有固定的呼吸空間。放在這一層（橫向容器）
     而不是文字本身，搭配 align-items:center 讓一行/兩行名稱都能
     在固定高度中垂直置中，不會卡在最上面留一塊空白（實機測試
     反饋的另一個真bug）。
     原本用 2.6em，但這裡的 font-size 是繼承來的16px（不是文字
     本身的13.5px），算出來的高度沒把後來加的 padding:6px 14px
     算進去，兩行文字時內容+padding會超過這個高度，又變回「一行
     兩行不一樣高」（實機測試反饋抓到的真bug，加背景卡片時漏算）。
     改用量測過的實際px值，直接把padding也算進去，不再用容易算錯
     的em推算 */
  min-height: 52px;
}
/* 名稱過長（英文版常見）改成最多兩行完整顯示，不再用單行刪節號
   截斷看不到全名——原本 white-space:nowrap + ellipsis 會把長名稱
   直接藏起來（實機測試反饋的真bug），改用 line-clamp 兩行顯示 */
.stall-browse-name-text {
  font-size: 13.5px;
  font-weight: 700;
  color: var(--nm-ink);
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
  overflow: hidden;
  min-width: 0;
  line-height: 1.3;
}
/* 編號徽章：跟清單/地圖標記同一套分類色，白色描邊+陰影確保跟旁邊
   紅色/青綠色按鈕放在一起時還是看得清楚，不會糊在一起（實測反饋
   要注意的細節） */
.stall-browse-num {
  flex-shrink: 0;
  min-width: 26px;
  height: 26px;
  padding: 0 6px;
  border-radius: 8px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-family: "JetBrains Mono", monospace;
  font-size: 12.5px;
  font-weight: 700;
  color: #fff;
  border: 2px solid rgba(255, 255, 255, 0.85);
  box-shadow: 0 2px 6px rgba(0, 0, 0, 0.45);
}
.stall-browse-num[data-category="savory"] { background: #e0562f; }
.stall-browse-num[data-category="dessert"] { background: #d9527e; }
.stall-browse-num[data-category="drink"] { background: #3f6fc0; }
.stall-browse-num[data-category="clothing"] { background: #8a5fc2; }
.stall-browse-num[data-category="accessories"] { background: #2f9e7a; }
.stall-browse-num[data-category="toys_games"] { background: #4f9e4f; }
.stall-browse-num[data-category="other"] { background: #9c8a6a; }
.stall-browse-controls {
  display: flex;
  align-items: center;
  gap: 12px;
  justify-content: center;
}
/* 圓潤+光澤感：漸層模擬球面光源反射（上亮下暗）+ 內縮的高光/陰影
   營造凸起厚度，按下去時陰影往內縮、位移1px模擬「真的被按下去」 */
.stall-browse-arrow {
  flex: 0 0 auto;
  width: 44px;
  height: 44px;
  border-radius: 14px;
  border: none;
  background: linear-gradient(180deg, #f3cf7a 0%, #e8b23c 45%, #c68a28 100%);
  box-shadow: inset 0 1px 2px rgba(255, 255, 255, 0.65), inset 0 -3px 4px rgba(0, 0, 0, 0.25),
    0 3px 8px rgba(0, 0, 0, 0.4);
  color: #4a2f0f;
  font-size: 16px;
  cursor: pointer;
  /* 放開時要平滑「彈」回原本樣子，不是瞬間切回去（實機測試反饋：
     按下去沒有回彈動畫），transition放在base rule上，press跟release
     兩個方向才都有過渡效果 */
  transition: transform 0.15s ease, box-shadow 0.15s ease, filter 0.15s ease;
}
.stall-browse-arrow:active {
  box-shadow: inset 0 2px 5px rgba(0, 0, 0, 0.35);
  transform: translateY(1px);
  /* 按下去整體變暗一階，跟陰影凹陷疊加，回饋更明顯（實機測試反饋：
     按下去沒有顏色變化）——用 filter:brightness 統一調暗，不用為
     每顆按鈕的漸層另外寫一組按下去專用的深色版本 */
  filter: brightness(0.85);
}
/* 篩選完剩0筆結果時按了沒反應，跟查看詳情停用同一種處理 */
.stall-browse-arrow:disabled {
  opacity: 0.45;
  filter: grayscale(0.4);
  cursor: not-allowed;
  box-shadow: none;
}
.stall-browse-open {
  /* 圓形，比左右箭頭(44px)稍微大一點點，不要差太多避免整排比例跑掉。
     固定寬高不再讓文字撐開寬度——原本是可以縮放的長橢圓形，英文版
     「View details」字比較長會撐寬，改固定圓形之後靠line-height換行
     容納，不會影響左右箭頭的間距版面 */
  flex: 0 0 auto;
  width: 58px;
  height: 58px;
  min-height: 0;
  padding: 4px;
  border-radius: 50%;
  border: none;
  background: linear-gradient(180deg, #ec6b4a 0%, var(--nm-lantern) 50%, #a8301c 100%);
  box-shadow: inset 0 1px 2px rgba(255, 255, 255, 0.5), inset 0 -3px 4px rgba(0, 0, 0, 0.25),
    0 4px 10px rgba(0, 0, 0, 0.45);
  color: #fff;
  font-size: 11px;
  font-weight: 700;
  line-height: 1.2;
  text-align: center;
  cursor: pointer;
  white-space: normal;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: transform 0.15s ease, box-shadow 0.15s ease, filter 0.15s ease;
}
.stall-browse-open:active {
  box-shadow: inset 0 2px 5px rgba(0, 0, 0, 0.35);
  transform: translateY(1px);
  filter: brightness(0.85);
}
/* 還沒選攤位時查看詳情按鈕點了沒反應（實測反饋的真bug），
   停用並調暗，避免看起來能按、按下去卻沒有任何回饋 */
.stall-browse-open:disabled {
  opacity: 0.45;
  filter: grayscale(0.4);
  cursor: not-allowed;
  box-shadow: none;
}
.stall-browse-side {
  flex: 0 0 auto;
  display: flex;
  flex-direction: column;
  gap: 10px;
  justify-content: center;
  padding-left: 12px;
  border-left: 1px solid rgba(232, 178, 60, 0.3);
}
/* 顏色沿用公廁標記本來就有的青綠色玻璃感（.restroom-marker），不是
   新配色，跟站內既有語言一致，同時跟主要動作的紅/金區隔開，這兩顆
   屬於次要的工具性按鈕 */
.map-side-btn {
  position: relative;
  width: 96px;
  min-height: 40px;
  padding: 9px 12px;
  border-radius: 16px;
  border: none;
  background: linear-gradient(180deg, #3fae95 0%, #1f9a80 50%, #0d5c4a 100%);
  box-shadow: inset 0 1px 1px rgba(255, 255, 255, 0.35), inset 0 -2px 3px rgba(0, 0, 0, 0.3),
    0 2px 6px rgba(0, 0, 0, 0.35);
  color: #fff;
  font-size: 11px;
  font-weight: 700;
  text-align: center;
  cursor: pointer;
  white-space: nowrap;
  transition: transform 0.15s ease, box-shadow 0.15s ease, filter 0.15s ease;
}
.map-side-btn:active {
  box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.4);
  transform: translateY(1px);
  filter: brightness(0.85);
}
.map-side-btn.active {
  background: linear-gradient(180deg, #6fdbc4 0%, #2fb89b 50%, #157a63 100%);
}
/* 篩選分類按鈕上的已選數量提示：改成疊在右上角的小圓點徽章，不是
   接在文字後面——原本用「篩選分類 (1)」文字拼接的做法，文字變長會
   撐大按鈕本身的寬度，而 .stall-browse-side 是 flex:0 0 auto 跟中間
   名稱區搶版面空間，篩選開關時整排版面會跟著抖動（實機測試反饋的
   真bug）。改用 position:absolute 疊加後，按鈕固定 96px 寬永遠不變，
   數字徽章完全不佔版面空間 */
/* 尺寸/圓角/陰影刻意跟 .stall-browse-num（攤位編號徽章）拉近，兩顆
   都是「貼右上角的小徽章」，原本一個全圓形18px、一個圓角方形26px，
   放在一起看質感差太多（實測反饋）；顏色/邊框顏色維持不同——這顆
   是「篩選了幾個」的通知性數字，跟攤位分類身份不是同一種資訊，
   不用做成完全一樣，只拉近份量感 */
.map-side-btn-count {
  position: absolute;
  top: -7px;
  right: -7px;
  min-width: 22px;
  height: 22px;
  padding: 0 5px;
  border-radius: 7px;
  background: var(--nm-gold);
  border: 2px solid #2a2013;
  box-shadow: 0 2px 6px rgba(0, 0, 0, 0.45);
  display: none;
  align-items: center;
  justify-content: center;
  font-family: "JetBrains Mono", monospace;
  font-size: 11px;
  font-weight: 700;
  line-height: 1;
  color: #2a2013;
}

/* 分類/附近攤位彈出清單：直式排列，傳送門模式（搬到body、
   position:fixed，動態算座標），理由：#map-area
   本身 overflow:hidden，卡在容器裡的話彈出清單會被裁切 */
.mobile-cat-popover,
.stall-nearby-popover {
  position: fixed;
  display: flex;
  flex-direction: column;
  gap: 6px;
  background: #2a2013;
  border: 1px solid rgba(232, 178, 60, 0.4);
  border-radius: 12px;
  padding: 10px;
  box-shadow: 0 12px 30px rgba(0, 0, 0, 0.5);
  z-index: 60;
  min-width: 170px;
}
.mobile-cat-popover[hidden],
.stall-nearby-popover[hidden] {
  display: none;
}
.mobile-cat-popover .category-tag {
  /* .category-tag 這個class本來是給水平排列的分類標籤用的，帶了寫死的
     width:92px/height:36px/overflow:hidden 等尺寸限制（見
     style/main.css），這裡沒有全部蓋掉的話，長一點的分類名稱會被裁掉
     或留白，跟附近攤位清單那邊視覺不一致（實測反饋的真bug），這裡
     全部強制覆寫，不留給舊規則插手的空間 */
  display: block;
  width: 100%;
  height: auto;
  overflow: visible;
  white-space: normal;
  text-align: left;
  justify-content: flex-start;
  line-height: 1.3;
  padding: 9px 12px;
  border-radius: 8px;
  /* 底邊故意不用 border 簡寫設，簡寫會連 border-bottom 一起蓋掉，
     這樣 .category-tag[data-category="X"] 那組分類色底線規則就完全
     顯示不出來——手機這份清單原本七個分類選中後全部變同一個顏色
     就是這樣來的（實測反饋抓到的真bug），桌機版彈出卡片沒這個問題
     是因為沒有整個蓋掉。這裡改成只設三邊，底邊留給分類色規則生效 */
  border-top: 1px solid rgba(232, 178, 60, 0.25);
  border-right: 1px solid rgba(232, 178, 60, 0.25);
  border-left: 1px solid rgba(232, 178, 60, 0.25);
  background: var(--nm-night);
  color: var(--nm-paper);
  font-size: 13px;
}
/* 選中狀態改回跟桌機版彈出卡片一致的統一金色（不是分類色）——
   站內既有慣例本來就是「選中=統一金色」，分類色只用在底線標示
   身份，兩者是不同的視覺管道，同時存在；之前這裡改成統一紅色
   又用 border-color 簡寫蓋掉底線分類色，是這次改版自己造成的
   不一致，改回跟桌機版同一套 */
.mobile-cat-popover .category-tag.active {
  background: var(--nm-gold);
  color: var(--nm-ink);
}
/* 清除篩選：跟上面7個分類選項用邊框/底色區隔開，一看就知道是
   「動作」不是另一個分類選項；沒有篩選在生效時整顆隱藏（見
   js/stall-browser.js updateCatCount()），不會顯示一個沒東西可清的
   按鈕 */
.mobile-cat-clear {
  display: block;
  width: 100%;
  margin-top: 4px;
  padding: 8px 12px;
  border-radius: 8px;
  border: 1px solid rgba(232, 178, 60, 0.4);
  background: transparent;
  color: var(--nm-gold);
  font-size: 12.5px;
  font-weight: 700;
  text-align: center;
  cursor: pointer;
  transition: background 0.15s ease;
}
.mobile-cat-clear:active {
  background: rgba(232, 178, 60, 0.12);
}

/* 方案C（貼右上角徽章）實測看起來太突兀，改成方案A：徽章固定在
   左邊一欄、名稱獨立一欄自己換行——跟瀏覽列「編號+名稱」
   （.stall-browse-name）同一種排版手法，換行時每一行都會對齊在
   名稱欄自己的左邊界，不會貼到整個項目最左邊去（實測反饋抓到的
   排版真bug，見 js/stall-browser.js renderNearbyList()） */
.nearby-stall-item {
  display: flex;
  align-items: flex-start;
  gap: 8px;
  width: 100%;
  text-align: left;
  padding: 9px 12px;
  border-radius: 8px;
  border: 1px solid rgba(232, 178, 60, 0.25);
  background: var(--nm-night);
  color: var(--nm-paper);
  font-size: 13px;
  cursor: pointer;
}
/* 編號沿用 .stall-browse-num 同一套分類色徽章（見js/stall-browser.js
   renderNearbyList()），跟瀏覽列的編號視覺一致，順便讓使用者掃這份
   清單時能快速看出每攤大概是什麼分類，不用逐一點開卡片 */
.nearby-stall-item .num {
  margin-top: 1px; /* 跟名稱文字第一行的視覺基準線對齊 */
}
.nearby-stall-name {
  flex: 1 1 auto;
  min-width: 0;
}

/* ---------- 29. 最上層按返回鍵離開網站的輕量提示（見
   js/back-button-stack.js）：不用彈窗+確定/取消，改用一個2秒後
   自動消失的短暫提示條，2秒內沒有再按第二次就當作沒事，比彈窗
   輕巧、也不會有iOS滑動返回手勢銜接不順的問題 ---------- */
.exit-toast {
  position: fixed;
  left: 50%;
  /* 收合的攤位清單抽屜把手固定佔螢幕最下面92px（見style/main.css
   .drawer 的 translateY(calc(100% - 92px))），這裡疊在32px的話會
   蓋到把手上面，往上挪開 */
  bottom: 108px;
  transform: translateX(-50%) translateY(0);
  z-index: 200;
  padding: 10px 20px;
  border-radius: 999px;
  background: #2a2013;
  border: 1px solid rgba(232, 178, 60, 0.4);
  color: var(--nm-paper);
  font-size: 13px;
  font-weight: 600;
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.5);
  white-space: nowrap;
  pointer-events: none;
  opacity: 0;
  transition: opacity 0.2s ease, transform 0.2s ease;
}
.exit-toast.show {
  opacity: 1;
}
.exit-toast[hidden] {
  display: none;
}

/* ---------- 30. 桌機版夜市簡介：改成收合式資訊條
   原本是常駐展開的一整塊，佔掉不少第一屏空間；改成一條可點擊收合的
   長條，預設收起，點開才展開完整內容。
   這條後來被併進 .desktop-unified-shell 整合外框（見第34段），
   不再是獨立一張卡片，改成外框裡的其中一段，跟頂部列/分類列共用
   同一圈外框，中間用 border-bottom 當分隔線 ---------- */
.desktop-intro-collapse {
  position: relative;
}
/* 資訊／FAQ雙分頁列（這次對話討論）：原本是單一按鈕佔滿整條，改成
   左右各半、各自獨立開關的兩個按鈕，靠flex平分寬度 */
.desktop-intro-collapse-tabs {
  display: flex;
}
.desktop-intro-collapse-tabs .desktop-intro-collapse-bar {
  flex: 1 1 50%;
  width: auto;
}
.desktop-intro-collapse-tabs .desktop-intro-collapse-bar:first-child {
  border-right: 1px solid rgba(232, 178, 60, 0.25);
}
/* 目前顯示中的那一半，底色加深區隔於未選中的另一半（這次對話討論） */
.desktop-intro-collapse-bar[aria-expanded="true"] {
  background: rgba(232, 178, 60, 0.28);
}
.desktop-intro-collapse-bar {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  padding: 13px 28px;
  /* 原本底色只有3%的白色tint，跟下面.desktop-filter-row同樣是
     transparent，兩條列都只是透出外框本身的深色底，看起來像同一塊、
     分不出這條其實是可以點的（實測發現的問題，這次對話討論）。
     改成明顯的暖金色調，讓這條列讀起來像自己獨立的一塊表面，跟
     下面維持透明的分類列拉開區隔。內陰影維持模擬上緣反光/下緣深度，
     都是靜態值，不會有動畫重繪的效能問題 */
  background: rgba(232, 178, 60, 0.12);
  border: none;
  border-bottom: 1px solid rgba(232, 178, 60, 0.25);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.06), inset 0 -1px 0 rgba(0, 0, 0, 0.25);
  color: var(--nm-paper);
  /* 這次對話討論：字放大加粗+加寬字距，加重這條列的視覺份量，
   跟底下實色的分類標籤/攤位數徽章比起來更有存在感 */
  font-size: 16px;
  font-weight: 800;
  letter-spacing: 0.04em;
  cursor: pointer;
  transition: background 0.15s ease;
  overflow: hidden;
}
.desktop-intro-collapse-bar:hover {
  /* 底色基準墊高之後，hover也要跟著加深，不然兩個狀態的差異會變得
     不明顯（這次對話討論） */
  background: rgba(232, 178, 60, 0.2);
}
/* 資訊符號（這次對話討論）：跟地圖上的P/?按鈕同一套圓形徽章語言
   （深色底+金色細框+金色文字），做小一點放在文字前面，填滿這條列
   偏空的視覺份量，不算額外文字內容 */
/* 原本套用了跟頂部logo同一種金黃漸層，但這次對話討論發現漸層偏暗、
   跟主標題的特殊感撞色，反而稀釋掉主標題的獨特性。改回單純的白色，
   保持清晰易讀，把漸層效果留給主標題專屬，這裡跟地圖告示牌
   （.v4-map-plate-text）都不再套用 */
.desktop-intro-collapse-label {
  color: var(--nm-paper);
}
.desktop-intro-collapse-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 24px;
  height: 24px;
  margin-right: 9px;
  border-radius: 50%;
  /* 文字放大加粗之後，原本細框+淡底的徽章比例上顯得偏弱（這次對話
     討論）。改成實心金底+深色字，跟旁邊分類標籤的實色份量搭起來，
     尺寸也跟著放大一點 */
  background: var(--nm-gold);
  border: none;
  color: var(--nm-ink);
  font-size: 15px;
  font-style: normal;
  font-weight: 900;
  flex-shrink: 0;
}
.desktop-intro-collapse-chevron {
  /* 原本absolute+right:20px是釘死在整條列最右側，但文字是置中在
     列正中間，兩者中間空了300多px，箭頭看起來跟文字脫節、像浮在
     角落（實測發現的問題，這次對話討論）。改成跟著icon/文字一起走
     正常排版順序，三個元素會一起被父層置中，箭頭自然貼在文字後面 */
  display: inline-block;
  margin-left: 10px;
  flex-shrink: 0;
  /* 原本是純文字符號「▾」，放大後邊緣不夠銳利、不同字體渲染會有
     落差（這次對話討論）。改用CSS純色三角形，線條乾淨、任何尺寸
     都清楚，顏色改用金色跟左邊資訊符號的金色徽章呼應，讓文字兩側
     有一致的重點色 */
  width: 0;
  height: 0;
  border-left: 6px solid transparent;
  border-right: 6px solid transparent;
  border-top: 9px solid var(--nm-gold);
  transition: transform 0.25s ease;
}
.desktop-intro-collapse-bar[aria-expanded="true"] .desktop-intro-collapse-chevron {
  transform: rotate(180deg);
}

/* 收合狀態的兩個提示效果（示範過的效果1+3，這次對話討論）：
   ① 邊框呼吸光暈，借用地圖「顯示我的位置」的呼吸動畫邏輯（見第27段
      v5-locate-breathe），頻率放慢、光暈更輕，暗示「這裡可以點開」
   ② 箭頭輕微上下跳動，像常見的「往下滑」提示動作
   兩個效果都只在收合狀態生效（用 :not([aria-expanded="true"]) 限定），
   展開之後就停掉，不會一直閃。
   ①原本直接動畫box-shadow/border-color本身，這兩個屬性瀏覽器沒辦法
   交給顯示卡處理，動畫時每一幀都要在CPU重新重繪（box-shadow還有
   模糊運算，成本更高），無限循環一直跑，會跟滑動時本來就要做的
   重繪工作搶資源，造成滑動卡頓（實測發現的問題，見這次對話討論）。
   改成疊一個獨立偽元素，box-shadow/border維持靜態值不變，animation
   只動它的opacity——這種動畫可以完全交給顯示卡合成，不用重繪 */
.desktop-intro-collapse-bar::after {
  content: "";
  position: absolute;
  inset: -1px;
  border: 1px solid rgba(232, 178, 60, 0.6);
  box-shadow: 0 0 14px 2px rgba(232, 178, 60, 0.35);
  opacity: 0;
  pointer-events: none;
}
@keyframes v5-intro-bar-breathe {
  0%, 100% { opacity: 0; }
  50% { opacity: 1; }
}
/* 呼吸光暈先關掉（這次對話討論），只留箭頭跳動。保留上面的
   ::after跟@keyframes定義，之後要重新打開只要把animation這行加
   回來即可，不用重寫 */
.desktop-intro-collapse-bar:not([aria-expanded="true"])::after {
  /* animation: v5-intro-bar-breathe 2.6s ease-in-out infinite; */
  will-change: opacity;
}
@keyframes v5-intro-chevron-bounce {
  0%, 100% { transform: translateY(0); }
  50% { transform: translateY(3px); }
}
.desktop-intro-collapse-bar:not([aria-expanded="true"]) .desktop-intro-collapse-chevron {
  /* 排除卡頓原因時關掉過，確認是呼吸光暈（動box-shadow）造成的，
     跟這裡動transform的箭頭跳動是不同性質，可以放心重新打開
     （這次對話討論） */
  animation: v5-intro-chevron-bounce 1.4s ease-in-out infinite;
}

/* 光澤掃過效果（這次對話討論）：一道很淡的暖金色高光斜向掃過整條列，
   隔幾秒掃一次，平常是靜止的。用 ::before（::after已經被上面的呼吸
   光暈用掉）疊一條窄長的漸層色塊，只動 transform（GPU合成，安全），
   .desktop-intro-collapse-bar 本身加了 overflow:hidden 讓這條色塊
   在列的範圍內才看得到，掃到範圍外會被裁掉 */
.desktop-intro-collapse-bar::before {
  content: "";
  position: absolute;
  top: 0;
  left: -120px;
  width: 120px;
  height: 100%;
  background: linear-gradient(100deg, transparent, rgba(255, 224, 130, 0.22), transparent);
  pointer-events: none;
}
@keyframes v5-intro-bar-shimmer {
  /* 前20%(約1秒)靜止在畫面外左側，20%~55%(約1.75秒)掃過去，
     剩下的時間停在畫面外右側，直到下一輪循環（迴圈重置那一刻
     色塊本來就在看不到的範圍外，不會有跳動感） */
  0%, 20% { transform: translateX(0); }
  55%, 100% { transform: translateX(1500px); }
}
.desktop-intro-collapse-bar:not([aria-expanded="true"])::before {
  /* 這次對話討論關掉：拆成兩個按鈕之後，收合狀態下兩邊會同時各自
     播放一次，動畫數量翻倍，使用者反映有卡頓感。保留::before跟
     @keyframes定義，之後要重新打開只要把animation這行加回來即可 */
  /* animation: v5-intro-bar-shimmer 5s ease-in-out infinite; */
}
@media (prefers-reduced-motion: reduce) {
  .desktop-intro-collapse-bar:not([aria-expanded="true"])::after,
  .desktop-intro-collapse-bar:not([aria-expanded="true"])::before,
  .desktop-intro-collapse-bar:not([aria-expanded="true"]) .desktop-intro-collapse-chevron {
    animation: none;
  }
}
/* 展開的內容用 max-height 動畫（而不是 grid-template-rows 0fr→1fr）：
   這個元素是絕對定位蓋在下面版面上面的，實測 grid-template-rows 的
   fr 單位在絕對定位容器上無法正確算出內容高度（一直是0），只有
   max-height 過渡在這裡有效 */
.desktop-intro-panel-wrap {
  position: absolute;
  top: 100%;
  /* 原本是28px/32px是對齊收合條外面那層wrapper自己的padding，
     現在那層wrapper併進整合外框後不再自己留padding（見上面
     .desktop-intro-collapse），這裡改成0，讓展開的卡片跟收合條
     一樣頂到列的左右邊界 */
  left: 0;
  right: 0;
  z-index: 40;
  max-height: 0;
  overflow-y: hidden;
  transition: max-height 0.38s ease;
  background: var(--nm-night);
  border: 1px solid rgba(232, 178, 60, 0.25);
  border-top: none;
  border-radius: 14px;
  border-top-left-radius: 0;
  border-top-right-radius: 0;
  box-shadow: 0 20px 40px rgba(0, 0, 0, 0.45);
  pointer-events: none;
}
.desktop-intro-panel-wrap.is-open {
  max-height: 70vh;
  overflow-y: auto;
  pointer-events: auto;
}
/* 分頁內容切換淡入效果（這次對話討論）：wrap本身已經有max-height
   展開動畫，這裡另外加一層淡入，讓「資訊/FAQ互相切換」這個動作
   也有轉場感，不是內容瞬間跳換。用animation而不是transition，
   這樣移除[hidden]屬性重新顯示時animation會自動重新觸發 */
@keyframes v5-intro-panel-fadein {
  from { opacity: 0; }
  to { opacity: 1; }
}
.desktop-intro-panel-wrap .desktop-intro:not([hidden]),
.desktop-intro-panel-wrap .desktop-faq-panel:not([hidden]) {
  animation: v5-intro-panel-fadein 0.2s ease;
}
@media (prefers-reduced-motion: reduce) {
  .desktop-intro-panel-wrap .desktop-intro:not([hidden]),
  .desktop-intro-panel-wrap .desktop-faq-panel:not([hidden]) {
    animation: none;
  }
}
/* 修正：main.css的.desktop-intro有display:flex，屬於作者樣式表，
   優先權蓋過瀏覽器內建的[hidden]{display:none}預設規則（實測發現
   的問題，這次對話討論），導致點FAQ分頁時資訊面板沒有真的被隱藏、
   兩塊內容同時疊在一起顯示。這裡用[hidden]選擇器提高優先權，讓
   hidden屬性能真的蓋過display:flex */
.desktop-intro[hidden],
.desktop-faq-panel[hidden] {
  display: none;
}
/* FAQ內容：兩欄排版（這次對話討論——8題答案都只有兩句話，篇幅短，
   兩欄比單欄從上排到下更能利用桌機版寬度，也不需要手風琴收合，
   見js/data/market-info.js的faq陣列註解說明原因） */
.desktop-faq-panel {
  padding: 20px;
}
.desktop-faq-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 22px 36px;
}
.desktop-faq-question {
  margin: 0 0 6px;
  color: var(--nm-gold);
  font-size: 15px;
  font-weight: 700;
}
.desktop-faq-answer {
  margin: 0;
  color: var(--nm-paper);
  font-size: 13.5px;
  line-height: 1.65;
}
.desktop-faq-more {
  display: block;
  margin-top: 16px;
  color: var(--nm-paper);
  font-size: 13px;
  font-weight: 700;
  text-decoration: none;
  text-align: right;
}
.desktop-faq-more:hover {
  text-decoration: underline;
}
.desktop-intro-collapse .desktop-intro {
  max-width: none;
  margin: 0;
  padding: 20px;
  /* 這次對話討論：置中會讓照片頂端跟「樂華夜市」標題對不齊，看起來
     像浮在中間、跟文字沒有對應關係。既然照片高度已經加高到360px
     跟文字欄位很接近了（見.desktop-intro-photo），落差不大，改回
     flex-start讓照片跟標題頂部對齊最自然，剩下一點點高度差留在
     底部也不明顯 */
  align-items: flex-start;
}

/* ---------- 31. 攤位清單跟地圖：併進整合外框（見第34段），
   不再各自獨立一張卡片。側欄原本自己一圈金框+陰影+20px圓角，
   現在拿掉，改成只用 border-right 當跟地圖之間的分隔線；圓角只
   保留在整個外框最外圈（外框的 overflow:hidden 會自動把側欄左下角
   跟地圖右下角裁成外框本身的圓角形狀，不用個別再設） ---------- */
.desktop-body {
  /* main.css原本這裡自己有 max-width:1440px + margin:0 auto 32px +
     padding:0 32px，是它自己獨立置中的寫法。併進外框後這些都要
     蓋掉，不然會變成外框裡面又有一層自己置中的窄框，兩層寬度
     算法疊在一起，側欄+地圖不會頂到外框的左右邊界 */
  max-width: none;
  margin: 0;
  padding: 0;
  gap: 0;
}
.desktop-sidebar {
  /* 攤位清單改回獨立一塊（這次對話討論）：之前試過跟地圖無縫貼在
     一起時，乳白色跟深色色差太硬、變成「一半亮一半暗被硬切開」的
     生硬感。清單本質上是要長時間閱讀文字的內容，跟資訊條/分類列/
     地圖這種「瀏覽操作介面」性質不同，值得獨立出來、拿回自己的
     乳白色配色，不用跟右邊硬統一成同一個深色系。跟右邊整合外框
     之間用.desktop-two-col-wrap的gap留一點間距當緩衝，不會硬碰硬 */
  background: var(--nm-paper);
  /* 邊框比照.v4-map-frame同一套語言（金邊+陰影+20px圓角），跟右邊
     整合外框風格統一，只是維持分開的兩塊 */
  border: 3px solid var(--nm-gold);
  border-radius: 20px;
  box-shadow: 0 12px 36px rgba(0, 0, 0, 0.6), 0 0 0 5px rgba(232, 178, 60, 0.12);
  /* 側欄現在是.desktop-two-col-wrap的flex子項，靠align-items預設值
     stretch自動長到跟右邊外框一樣高。但align-items:stretch算「這排
     應該多高」時，是先量每個子項「不受限時自然想要多高」，側欄
     overflow-y:auto但沒有明確高度上限，自然高度就是282攤全部展開
     的完整高度（實測：16000多px），這個數字反而變成整排的高度，
     右邊外框也被拖著等高長高，min-height:0沒辦法解決這個「量測」
     階段的問題（實測發現的問題，見這次對話討論）。改用max-height
     直接把側欄自己的高度硬性上限鎖住。這裡的calc(70vh+113px)只是
     JS算出精確值之前的初始概算值（避免JS還沒跑完那一瞬間側欄先
     炸開16000px的閃爍），實際精準對齊改由js/main.js的
     syncSidebarHeight()直接量測右邊外框當下的真實高度、寫成inline
     style蓋過這裡，不同瀏覽器/視窗尺寸下的微小落差不會再發生
     （這次對話討論） */
  max-height: calc(70vh + 113px);
}
/* 攤位卡片左右留白加大（這次對話討論）：只調整清單容器自己的左右
   padding，卡片本身的寬度/比例完全不動，卡片只是因為可用寬度變窄
   而跟著自然內縮，不是把卡片壓扁變形。只 scope 在桌機版清單
   （#stall-list-desktop），不影響手機版共用的 .stall-list 基礎樣式 */
#stall-list-desktop {
  padding-left: 20px;
  padding-right: 20px;
}

/* ---------- 32. 分類篩選：從側欄彈出卡片改成常駐一整排，
   跟攤位統計並列，蓋在清單+地圖上面。篩選邏輯完全交給
   search-filter.js 既有的全域邏輯（wireCategoryTags()/
   syncTagButtonStates() 本來就是抓所有 .category-tag，不管在DOM
   哪裡），這裡只負責排版跟外觀。色線沿用第22段已經有的
   .category-tag[data-category="X"] 全域規則，不用重複定義 ---------- */
.desktop-filter-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  /* 併進整合外框後（見第34段），這排不用再自己算「外層wrapper寬度
     減64px」對齊寬度了——外框本身已經是唯一一層負責寬度限制+置中
     的容器，這裡直接吃滿外框的寬度即可，不用另外設 max-width/
     margin。左右內距改成跟其他列一致的28px */
  padding: 4px 28px;
  background: transparent;
  border: none;
  border-bottom: 1px solid rgba(232, 178, 60, 0.25);
  /* 固定死高度，不管分類按鈕選中/未選中、統計徽章文字變長變短
     （「共 X 攤」↔「已篩選・X 攤」中英文長度都不一樣），這排的高度
     都不會被撐開往下擴張，版面不會跳動（實測發現的問題，
     見這次對話討論）。原本57px，後來發現滑鼠hover分類按鈕時的
     位移+發光效果會被裁掉（下面.desktop-cat-chips的說明），這裡
     多留一點高度給裁切用的內距 */
  height: 66px;
}
.desktop-cat-chips {
  display: flex;
  gap: 8px;
  /* 原本 wrap，當統計徽章文字變長（例如切成「已篩選」狀態）擠壓到
     可用寬度，分類按鈕可能被迫換到第二行，讓上面固定高度裝不下、
     視覺上看起來像整排往下擴張。改成不換行＋允許自己橫向捲動，
     寬度不夠時是「捲動」而不是「往下長高」（實測發現的問題，
     見這次對話討論） */
  flex-wrap: nowrap;
  overflow-x: auto;
  scrollbar-width: none;
  /* 這次對話討論：捲動列本身沒有任何提示，標籤卡在邊緣被硬生生
     切一半，看起來像壞掉而不是「可以捲動看更多」（實測發現的問題）。
     兩側邊緣加漸層淡出，暗示還有內容在捲動範圍外，是常見的橫向
     捲動UI手法。不特別判斷「捲到底時該不該淡出」（那需要另外寫
     scroll事件監聽），固定套用在兩側，內容真的塞得下、不需要捲動
     時，淡出的也只是邊緣本來就留白的地方，不會不好看 */
  mask-image: linear-gradient(to right, transparent 0, black 20px, black calc(100% - 20px), transparent 100%);
  -webkit-mask-image: linear-gradient(to right, transparent 0, black 20px, black calc(100% - 20px), transparent 100%);
  /* 副作用：overflow-x設非visible值時，CSS規範會強制overflow-y也
     跟著變成auto（不能只讓水平捲動、垂直保持visible），導致hover
     時分類按鈕的 translateY(-1px) 位移＋發光box-shadow一路被這個
     容器自己的邊界裁掉，滑鼠移上去反而看起來被「遮住」。這裡直接
     加垂直內距，讓發光效果有空間可以在容器邊界內完整顯示，不用
     真的伸出容器外面（實測發現的問題，見這次對話討論） */
  padding: 13px 4px;
}
.desktop-cat-chips::-webkit-scrollbar {
  display: none;
}
.desktop-cat-chips .category-tag {
  width: auto;
  height: auto;
  /* 這次對話討論：漏掉這兩行保護，篩選中「Filtered・121 stalls」
     文字比平常「282 stalls」長，把這排可用寬度擠壓，標籤按鈕沒有
     東西擋著就被壓縮、文字被迫換行變兩行（實測發現的問題）。加上
     不換行+不壓縮，遇到空間不夠時交給.desktop-cat-chips本來就有的
     overflow-x:auto處理（變成可以左右滑動），而不是硬壓扁文字 */
  white-space: nowrap;
  flex-shrink: 0;
  padding: 7px 14px 6px;
  /* 原本0.05太淡，未選中的按鈕不容易一眼看出膠囊形狀跟邊界，
     提高到0.09；再加內陰影模擬上緣反光/下緣深度（靜態值，跟收合條
     按鈕感用同一招，不會有動畫重繪的效能問題），讓按鈕有實體厚度感
     （這次對話討論） */
  background: rgba(255, 255, 255, 0.09);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.08), inset 0 -1px 0 rgba(0, 0, 0, 0.2);
  /* 只設上/左/右三邊，刻意不碰 border-bottom：底線的顏色跟寬度要
     留給第22段的 .category-tag[data-category="X"]（border-bottom:
     3px solid 分類色）去決定。原本這裡用 border 簡寫一次設四邊，
     等於把底線也蓋成統一的淡金色，害每個分類自己的顏色線消失
     （實測發現的問題，見這次對話討論） */
  border-top: 1px solid rgba(232, 178, 60, 0.25);
  border-left: 1px solid rgba(232, 178, 60, 0.25);
  border-right: 1px solid rgba(232, 178, 60, 0.25);
  border-radius: 999px;
  color: var(--nm-paper);
  font-size: 12.5px;
  font-weight: 600;
  transition: transform 0.12s ease, box-shadow 0.2s ease, background 0.15s ease;
}
.desktop-cat-chips .category-tag:hover {
  background: rgba(232, 178, 60, 0.12);
}
.desktop-cat-chips .category-tag.active {
  background: var(--nm-gold);
  color: var(--nm-ink);
  border-color: var(--nm-gold);
  /* 選中狀態改用「壓下去」的內陰影方向（陰影在上、不是反光在上），
     跟未選中的「浮起來」立體感方向相反，視覺上多一層「這顆被按下去
     了」的提示，不只是單純換色 */
  box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.25);
}
/* 分類數量原本是第12段 .v5-cat-count 的通用樣式（10.5px+72%透明度），
   跟旁邊分類文字擠在一起、又小又淡不容易看清楚。這裡只針對桌機
   常駐分類列加強對比，不動 .v5-cat-count 本身，避免影響手機版
   （見這次對話討論，之前也特別交代過不要影響手機版） */
.desktop-cat-chips .category-tag .v5-cat-count {
  opacity: 1;
  font-weight: 700;
  color: var(--nm-gold);
}
.desktop-cat-chips .category-tag.active .v5-cat-count {
  color: var(--nm-ink);
}
.desktop-filter-row .desktop-stall-count {
  flex-shrink: 0;
  /* 原本淡背景+暗淡文字+沒邊框，是「次要資訊」等級的配色，跟旁邊
     金色底線的分類按鈕比起來份量差很多，不顯眼（這次對話討論）。
     改成白底黑字（不分篩選中/未篩選，兩種狀態都一樣），跟深色系
     的分類按鈕拉開最大反差，最顯眼的配色組合，不用等到篩選中
     才特別標示 */
  background: #fff;
  border: 1px solid var(--nm-gold);
  color: var(--nm-ink);
  /* 原本用JetBrains Mono等寬字體——這是給程式碼/數字對齊用的字體，
     拿來排「Filtered」「stalls」這種一般英文單字，字母造型比較生硬，
     不像旁邊分類按鈕用的網站預設字體（Work Sans）那樣好讀，這才是
     使用者反應「文字本身看不清楚」的真正原因（實測發現的問題，
     見這次對話討論）。改用跟分類按鈕一樣的預設字體，數字部分
     （.desktop-stall-count-num）不用等寬字體也能單靠字級/粗細/
     顏色做出重點數字的效果 */
  font-family: "Work Sans", "PingFang TC", "Microsoft JhengHei", sans-serif;
  font-size: 13px;
  font-weight: 700;
  padding: 5px 12px;
  border-radius: 999px;
  white-space: nowrap;
}
/* 數字獨立包了span（見js/stalls-list.js），比旁邊「共／攤」這種
   說明文字再大一級、換成金色，做出「這是重點統計數字」的層次感 */
.desktop-stall-count-num {
  font-size: 15px;
  font-weight: 700;
  color: var(--nm-gold);
}
/* 篩選中/未篩選現在共用同一套白底黑字+金色數字的樣式（見上面），
   不需要另外針對 .count-filtered 寫覆蓋規則了。但第10段全站通用的
   .count-filtered 本身有 !important 蓋文字顏色，這裡明確蓋回來，
   確保篩選中不會被那條規則搶走顏色 */
.desktop-filter-row .desktop-stall-count.count-filtered {
  color: var(--nm-ink) !important;
}

/* ---------- 33. 右上角「★ 收藏」按鈕：呼應清單裡收藏攤位的金色語言
   不整塊填金色背景（會讓人誤以為是「目前在收藏檢視模式」的啟用
   狀態，但這顆按鈕其實只是入口），只加強邊框跟星星圖示兩處 ---------- */
#btn-favorites-desktop {
  border-color: var(--nm-gold);
}
.top-btn-fav-star {
  color: var(--nm-gold);
}

/* ---------- 34. 整合外框：頂部列／資訊條／分類列／清單+地圖
   原本這四塊各自獨立一張卡片（各自完整一圈邊框+四角都圓角），中間
   留白會透出頁面更深的底色，看起來像分開的個體而不是一個整體。
   改成只有 .desktop-unified-shell 這個最外層有一圈完整邊框+圓角，
   裡面每一段只用 border-bottom 當分隔線，段落之間不留白，直接貼齊
   （這次對話討論的整合外框範本） ---------- */
/* 左右兩塊的外層容器（這次對話討論）：左邊攤位清單、右邊整合外框
   （資訊條+分類列+地圖），取代原本.desktop-unified-shell自己算寬度
   置中的做法——寬度算法現在由這一層負責，跟第32段分類列同一個公式
   width:calc(100%-64px)搭配max-width，不管視窗多寬都會跟頁面其他
   元素對齊。align-items用預設值stretch，讓左邊清單自動長到跟右邊
   整合外框一樣高，不用手動算高度 */
/* .desktop-two-col-wrap 本身也有 .desktop-only（見index.html），跟
   main.css的 .desktop-only{display:none} 是同樣0,0,1,0優先權，單純
   看誰後載入──這條規則在enhancements.css，會贏過main.css先定義的
   .desktop-only，導致手機版寬度下這裡的display:flex蓋掉隱藏規則，
   整組桌機版側欄+地圖被撐開跑到手機畫面上（實測發現的真bug，這次
   對話討論）。包進跟main.css同一個中斷點的media query，只在桌機
   寬度才生效，不會再跟隱藏規則打架 */
@media (min-width: 769px) {
  .desktop-two-col-wrap {
    display: flex;
    gap: 16px;
    width: calc(100% - 64px);
    max-width: 1376px;
    margin: 24px auto;
  }
  /* 這次對話討論新增的精選推薦提示條，跟.desktop-two-col-wrap同樣
     道理：本身有.desktop-only，display規則要包進同一個中斷點，
     不然會重蹈上面說明的那個真bug（手機寬度下被撐開跑出來） */
  .desktop-highlight-ticker {
    display: flex;
    align-items: center;
    gap: 14px;
    /* 這次對話討論：原本跟.desktop-two-col-wrap同寬(max-width:1376px)，
       但這條只是輕量預告、內容量遠不如下面的地圖/列表主內容區，
       同樣滿版寬度比例上顯得過大。改用clamp()抓「畫面寬度的55%，
       但不小於520px、不大於820px」——用比例而不是單一固定px，
       小螢幕（769px附近）跟大螢幕（2000px+）都不會走鐘：小螢幕會
       被520px下限撐住不會太窄擠不下文字，大螢幕會被820px上限收住
       不會又變回太寬太空 */
    width: clamp(520px, 55%, 820px);
    height: 44px;
    margin: 24px auto;
    padding: 0 20px;
    /* 這次對話討論修正：原本border-radius只做上面兩角、border-bottom
       整個拿掉，那種寫法是「假設下面會緊貼著資訊/地圖那個外框、無縫
       接起來」才合理的做法。但實際量測發現兩者中間其實有24px的
       margin間距，不是緊貼——邊框下緣沒收口，看起來像沒做完、被
       裁掉一半的框。改成四角都是圓角+完整邊框，變成一個獨立完整
       的區塊，才符合它跟下面本來就有間距、是分開兩塊的事實。
       同時把底色從0.1提高到0.2——原本跟下面資訊列的0.12太接近，
       兩者幾乎分不出視覺層次，「精選推薦」看起來不夠突出、不像
       重點區塊，這裡一起加深讓它更明顯跳出來 */
    border-radius: 14px;
    /* 這次對話討論：查了Airbnb「Guest favorite」徽章的實際做法後改變
       思路——容器本身走中性深色，「重要」的訊號集中在小巧的徽章
       (.desktop-highlight-label)上，不是整個容器都染色。中間試過把
       底色調亮（跟頁面背景疊加後的亮度確實可以贏過FAQ面板），但
       使用者認為黑色底跟頁面整體深色調性比較搭、亮色底看起來偏灰、
       跟整體風格不一致——改回黑色底，「重要」這件事完全交給徽章本身
       的飽和橘色去扛，不再要求容器本身的亮度也要贏過其他面板。
       邊框保留加強後的0.3，幫忙定義範圍就好 */
    background: rgba(0, 0, 0, 0.22);
    border: 1px solid rgba(255, 255, 255, 0.3);
    box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.05), 0 2px 6px rgba(0, 0, 0, 0.25), 0 8px 20px rgba(0, 0, 0, 0.22);
  }
}
.desktop-highlight-label {
  /* 這次對話討論：改成比照.desktop-intro-collapse-icon（資訊/FAQ
     圓形徽章）同一套「實心重點色底+深色文字」的高對比邏輯，只是這裡
     做成藥丸形文字徽章，不是圓形單一符號。徽章本身扛下所有的顏色/
     份量，容器（見上面.desktop-highlight-ticker）保持中性 */
  /* 這次對話討論：徽章跟攤位名稱/描述之間的間距要比name跟tag之間
     的間距更大一點，讓「名稱+描述」讀起來像自己的一組，徽章是獨立
     的分類標籤，不是這組的一部分——父層.desktop-highlight-item的
     gap只負責name/tag之間的間距，這裡額外加margin-right把徽章
     推遠一點 */
  margin-right: 8px;
  flex-shrink: 0;
  display: inline-flex;
  align-items: center;
  padding: 4px 10px;
  border-radius: 12px;
  background: #de7734;
  color: var(--nm-ink);
  font-size: 12.5px;
  font-weight: 700;
}
/* 這次對話討論：三個chip並排雖然填滿了空間，但使用者反應「太多攤位
   會失去焦點」——改回一次只顯示一家，但輪替方式從原本的淡入淡出+
   6px小幅位移，改成「由上往下移動切換」：新項目從上方(-100%)滑入
   定位，同時舊項目往下滑出(+100%)，兩者同一個方向、有真正的移動感，
   不是原地淡入淡出。文字也改成置中（不是像之前那樣靠左），單一項目
   置中比較不會讓左右留白顯得像沒排好，反而像刻意的設計 */
.desktop-highlight-content {
  position: relative;
  flex: 1;
  min-width: 0;
  height: 100%;
  overflow: hidden;
}
.desktop-highlight-item {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  text-decoration: none;
  white-space: nowrap;
  overflow: hidden;
  transform: translateY(-100%);
  opacity: 0;
  transition: transform 0.4s ease, opacity 0.4s ease;
}
.desktop-highlight-item.active {
  transform: translateY(0);
  opacity: 1;
}
.desktop-highlight-item.leaving {
  transform: translateY(100%);
  opacity: 0;
}
/* 這次對話討論：系統開啟「減少動態效果」時，改用純淡入淡出取代
   由上往下滑動——有些使用者（例如前庭功能敏感）會在系統層級關掉
   這類位移動畫，這裡三個狀態的transform都設成none，剩下opacity還在
   變化，效果就變成單純淡入淡出，不會有位移 */
@media (prefers-reduced-motion: reduce) {
  .desktop-highlight-item,
  .desktop-highlight-item.active,
  .desktop-highlight-item.leaving {
    transform: none;
    transition: opacity 0.3s ease;
  }
}
.desktop-highlight-item:focus-visible {
  outline: 2px solid var(--nm-paper);
  outline-offset: -2px;
}
.desktop-highlight-item .name {
  /* 這次對話討論：原本改成跟前面「🔥 精選推薦」標籤同一個金色，
     結果兩段文字連在一起看不出哪裡是固定標籤、哪裡是真正在變動的
     攤位名稱。比照.desktop-intro-collapse-label（FAQ分頁文字）的
     配色邏輯：金色留給裝飾性標籤/圖示，實際內容文字用亮度更高的
     --nm-paper，兩者才有顏色區隔，米白對比也比金色更搶眼。字體改用
     Noto Serif TC——這是網站既有慣例專門留給「名稱/標題」類文字用的
     襯線字體（.top-bar-logo-zh、.modal-title、.intro-name、
     .legend-item-title都是），攤位名稱本質上就是一個名稱，套用同一套
     慣例會更有份量，不是另外挑一個突兀的新字體 */
  /* 這次對話討論才發現：跟手機版同一個問題（見style/main.css
     .mobile-highlight-item .name的說明）——原本flex-shrink:0假設
     .tag縮到0還是擠得下，但真的遇到又長又沒縮寫的英文攤位名稱時
     （例如"Authentic Lehua Chuan Ji Spicy Stinky Tofu"），光是
     徽章+name兩個就超過容器寬度，.tag縮到0也不夠，name本身會被
     父層.desktop-highlight-item的overflow:hidden硬裁切、沒有省略號
     提示。補上跟.tag同一套min-width:0+ellipsis當安全網——正常情況下
     這裡幾乎不會觸發（.tag還有伸縮空間會先被壓縮），只在.tag已經
     縮到0、名稱本身還是太長的極端情況才會用到 */
  flex-shrink: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  color: var(--nm-paper);
  font-family: "Noto Serif TC", serif;
  font-size: 16px;
  font-weight: 800;
  /* 這次對話討論：hover效果只做在.name這個文字本身，不能做在外層
     <a>身上——外層本來就有由上往下滑動用的transform，兩個transform
     疊在一起會互相蓋掉、破壞輪播動畫 */
  display: inline-block;
  transition: transform 0.15s ease, color 0.15s ease;
}
.desktop-highlight-item.active:hover .name {
  transform: translateY(-2px) scale(1.05);
  color: #de7734;
}
.desktop-highlight-item .tag {
  /* min-width:0是必要的（這次對話討論才發現漏掉，跟手機版同一個
     問題，見style/main.css .mobile-highlight-item .tag的說明） */
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  color: var(--nm-paper-dim);
  font-size: 13px;
}
.desktop-highlight-more {
  /* 這次對話討論：文字顏色從金色改成跟FAQ分頁一致的
     --nm-paper（見.desktop-intro-collapse-label），金色留給裝飾性的
     徽章/標籤用，實際可讀文字統一用亮度更高、對比更好的paper色 */
  flex-shrink: 0;
  padding-left: 14px;
  /* 這次對話討論：容器改走中性色路線後，分隔線也跟著改回中性的
     白色半透明，不再用重點色——重點色現在只保留給徽章 */
  border-left: 1px solid rgba(255, 255, 255, 0.15);
  color: var(--nm-paper);
  font-size: 12.5px;
  font-weight: 700;
  text-decoration: none;
  white-space: nowrap;
}
.desktop-highlight-more:hover {
  text-decoration: underline;
}
.desktop-unified-shell {
  flex: 1;
  min-width: 0;
  background: #2a2013;
  /* 原本是實心不透明金色，這是全頁面最大、最搶眼的金色元素，但它
     純粹是「這是一張卡片」的框線，不代表任何互動/選中狀態。調淡成
     半透明，跟真正代表互動/選中的金色（分類按鈕選中、收藏星星、
     收藏攤位邊框，這些維持不透明）拉開區隔（這次對話討論） */
  border: 2px solid rgba(232, 178, 60, 0.45);
  border-radius: 20px;
  box-shadow: 0 12px 36px rgba(0, 0, 0, 0.6), 0 0 0 5px rgba(232, 178, 60, 0.12);
  /* 不能用 overflow:hidden 讓內部方正邊角自動裁成圓角——資訊條展開時
     的卡片（.desktop-intro-panel-wrap）是 position:absolute，內容
     高度可以長到70vh，如果外框自己是overflow:hidden，只要展開卡片
     超出外框當下的高度，就會被外框直接裁掉看不到（實測會發生的問題）。
     改成手動只在最下面（側欄/地圖）加圓角，最上面（資訊條）本身
     background是transparent，不用額外設圓角就能讓外框自己的圓角
     透出來（見下面.desktop-intro-collapse-bar）。
     頂部列（logo/搜尋/語言/收藏）後來決定不併進這個外框——它是
     全站通用的導覽列，跟「瀏覽夜市攤位」這個功能模組是不同層級，
     維持原本獨立一條的樣子（這次對話討論） */
}

/* 地圖框併進外框，拿掉自己原本的金邊+陰影+20px圓角，只留放展覽
   標示牌用的內距（padding-top:46px，見第7段），背景改透明讓外框
   本身的底色透出來，跟側欄那邊看起來是同一塊底色。
   .map-area-desktop 本身另外還有自己一層14px圓角+更深的背景色
   （var(--nm-night-deep)，main.css原本設計給地圖自己獨立一塊時用
   的），也要一併拿掉，不然地圖那塊會比側欄暗一截、四個角也會有
   自己獨立的小圓角，跟外框最外圈的20px圓角不一致 */
.desktop-unified-shell .map-area-desktop {
  /* 原本這個高度寫在.desktop-body（清單+地圖那一列的外層wrapper），
     現在側欄搬出去變成獨立一塊，.desktop-body整個拿掉了，高度改
     直接寫在地圖自己身上——地圖上面現在多了資訊條+分類列兩段，
     這個70vh維持跟原本.desktop-body一樣的值，所以整個右側外框的
     總高度（資訊條+分類列+70vh地圖）跟這次改動之前是一樣的，不會
     變得比之前更高（這次對話討論） */
  height: 70vh;
  min-height: 480px;
  /* .map-area-desktop 本身有 overflow:hidden（main.css），會把裡面的
     地圖圖片裁成這裡設定的圓角形狀。因為外框拿掉了overflow:hidden
     （避免裁到資訊條展開卡片，見上面.desktop-unified-shell的說明），
     這裡改成手動只在左下角、右下角（外框最後一排的兩個角）加圓角，
     不然圖片會是方正的直角，在外框本身圓弧的角落露出一小塊方形
     缺角。左下角現在也要加了，因為側欄搬出去之後地圖變成外框裡
     唯一一塊，兩個下方角落都是外框的角 */
  border-radius: 0;
  border-bottom-left-radius: 18px;
  border-bottom-right-radius: 18px;
  background: transparent;
  /* 側欄維持原本280px不動（攤位卡片要保持精緻緊湊，不能為了減少
     文字截斷把側欄加寬，見這次對話討論）。改成只限制地圖本身的
     寬度上限，避免螢幕越寬、地圖佔比越誇張；用margin:auto讓地圖
     在剩餘空間裡置中，不會整塊貼左邊、右邊留一大塊突兀的空白 */
  max-width: 900px;
  margin: 0 auto;
}
.desktop-unified-shell .map-area-desktop .v4-map-frame {
  background: transparent;
  border: none;
  border-radius: 0;
  box-shadow: none;
  /* 原本46px是給標示牌留的空間，跟地圖圖片頂端只隔了約4px，太貼近
     （這次對話討論）。只加桌機版這裡的padding-top，手機版維持46px
     不變 */
  padding-top: 56px;
}
.desktop-unified-shell .map-area-desktop .v4-map-frame .map-stage img {
  border-radius: 0;
}

/* ---------- 35. 兩個實測發現的問題（這次對話討論）：
   ① 收藏按鈕沒有hover效果——原來.top-btn這個class本來就沒有寫
      :hover規則，不是這次改動造成的，這裡補上
   ② 搜尋框focus時是瀏覽器預設的藍色外框，跟整體金色系不搭，
      換成金色系的focus樣式（不是直接拿掉outline，用box-shadow
      當替代的可視化焦點提示，維持無障礙可及性） ---------- */
#btn-favorites-desktop:hover {
  background: rgba(232, 178, 60, 0.12);
}
.desktop-search-input:focus {
  outline: none;
  border-color: var(--nm-gold);
  box-shadow: 0 0 0 3px rgba(232, 178, 60, 0.25);
}

/* 展開面板的說明文字/提醒清單原本沒設max-width，外框變寬之後這兩段
   多行文字會跟著撐滿整個文字欄寬（將近900-1000px），一行字數太多
   不好讀。只限制這兩段多行文字，地址/交通這些單行短文字不受影響
   （這次對話討論） */
.desktop-intro-text .intro-desc,
.desktop-intro-text .intro-tips {
  max-width: 580px;
}

/* ---------- 36. 桌機版頂部標題：中文一行、英文一行堆疊顯示
   （這次對話討論，只針對桌機版，手機版.top-bar-logo維持原本單行寫法
   不受影響）。原本中英文擠在同一行，這裡拆成「大圖示＋堆疊兩行文字」
   的品牌識別標誌排法：中文大字在上，英文變成較輕的副標題在下。
   頂部列高度要跟著加高才放得下兩行 ---------- */
/* .desktop-top-bar 也有 .desktop-only，跟上面 .desktop-two-col-wrap
   同一種bug：這裡的display:grid是後載入的同優先權規則，會贏過
   main.css的.desktop-only{display:none}，導致手機版寬度下桌機頂部列
   也被撐出來（跟側欄+地圖一起，是同一個bug造成的，實測發現，這次
   對話討論）。同樣包進桌機中斷點才生效 */
@media (min-width: 769px) {
.desktop-top-bar {
  height: 76px;
  /* 原本是flex+space-between，實測發現搜尋框flex:1長到max-width上限
     後，多出來的空間沒有平均分配在左右兩個間距，全部堆到搜尋框右邊
     那一格，導致搜尋框看起來偏左、沒有真正置中（實測發現的問題，
     見這次對話討論）。改成grid三欄式（logo欄／搜尋框欄／按鈕欄），
     左右兩欄用同樣的1fr，不管logo或按鈕群實際寬度多少，中間的搜尋框
     永遠精準置中，不會再受flex-grow疊加max-width的難預期交互影響 */
  display: grid;
  grid-template-columns: 1fr 640px 1fr;
  column-gap: 24px;
}
}
.desktop-logo {
  justify-self: start;
}
.desktop-search-wrap {
  justify-self: center;
  width: 100%;
  max-width: none;
}
.desktop-actions {
  justify-self: end;
}
.desktop-logo {
  display: flex;
  align-items: center;
  gap: 12px;
  white-space: normal;
}
.desktop-logo-icon {
  /* 這次對話討論：頂部列76px高度本身不動（不改版面結構），logo垂直
     置中還有不少空間可以長，字放大一點即可 */
  font-size: 38px;
  line-height: 1;
  flex-shrink: 0;
}
.desktop-logo-text {
  display: flex;
  flex-direction: column;
  /* 這次對話討論：中文置中對齊到英文的寬度中間，英文不動。英文本來
     就是較寬的那行，align-items:center置中時英文本身沒有多餘空間
     可以動，只有比較短的中文會視覺上置中過去 */
  align-items: center;
  line-height: 1.25;
}
/* 桌機版標題下方細金線（這次對話討論，跟手機版同一個效果）。上面
   .desktop-logo-text改成align-items:center之後（中文置中對齊英文），
   這條底線如果不特別處理也會跟著被置中壓縮成0寬（沒設width，靠
   stretch撐滿的做法失效），這裡用align-self:stretch蓋掉父層的
   center，維持滿版寬、跟英文那行同寬同一個起點 */
.desktop-logo-text::after {
  content: "";
  display: block;
  align-self: stretch;
  height: 2px;
  margin-top: 4px;
  background: linear-gradient(90deg, var(--nm-gold), transparent);
}
.desktop-logo-zh {
  font-family: "Noto Serif TC", serif;
  font-weight: 900;
  font-size: 25px;
  /* 這次對話討論，跟手機版同一個效果：金黃漸層文字+暖色光暈，
     呼應夜市燈籠的暖色調 */
  color: var(--nm-paper);
  background: linear-gradient(180deg, var(--nm-gold) 0%, var(--nm-lantern) 100%);
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
  text-shadow: 0 0 12px rgba(232, 178, 60, 0.45);
}
.desktop-logo-en {
  font-family: "Work Sans", "PingFang TC", "Microsoft JhengHei", sans-serif;
  font-weight: 400;
  font-size: 15px;
  color: var(--nm-paper-dim);
  /* 襯線中文大標題底下搭配一行拉開字距的英文小字，是常見的精品感
     排版手法，比緊貼在一起的英文更講究（這次對話討論） */
  letter-spacing: 0.04em;
}

/* 搜尋框邊框原本濃度（0.3）跟收合條按鈕、分類按鈕差不多，但搜尋框
   角色比較像背景工具，不是主要互動重點，在深色底上顯得有點搶眼。
   邊框調淡、圓角加大一點，讓它更融入背景、更柔和（這次對話討論） */
.desktop-search-input {
  border-color: rgba(232, 178, 60, 0.15);
  border-radius: 11px;
}

/* 攤位卡片邊框加深（這次對話討論）：原本border用var(--nm-paper-dim)
   淡褐色，跟側欄背景var(--nm-paper)乳白色太接近，兩色幾乎融在一起，
   卡片邊界看起來偏軟。換成var(--nm-ink-soft)這種明顯更深的褐色，
   讓每張卡片的輪廓在乳白色背景上更清楚分明。只scope在桌機版清單，
   不影響手機版抽屜清單 */
#stall-list-desktop .stall-row {
  border-color: var(--nm-ink-soft);
}
