/* 🛒 前台共用樣式：首頁(index.html)＋商品詳情頁(product.html)共用。
   會員/結帳/購物車/查詢訂單這一整套互動元件兩個頁面都需要，抽出來避免兩份重複維護(2026-07-24)。*/
* { box-sizing: border-box; }

/* ⚠️(2026-08-08使用者回報的「頁首收合時畫面會左右晃一下」，已修正)
   ─────────────────────────────────────────────────────────────
   症狀：頁首展開時整排稍微偏左，收起來時又偏回右邊，一收一放畫面就晃一下。

   原因不在頁首本身，在「捲軸」：
     1. 收合頁首時，下面那條 JS 會把 body 的 padding-top 從約 180px 改成 16px；
     2. 文件總高度因此少了約 160px；
     3. 如果這一頁的內容原本只比視窗高一點點，捲軸就會在這個瞬間消失；
     4. 捲軸一消失，可視寬度多出約 15px；
     5. 站上所有置中容器(.page/.header-row/.top-bar-inner/.nav-bar-inner/.footer-inner
        還有 left:50% 的拉桿)都是 margin:0 auto 置中，於是通通往右位移約 7.5px。
     展開時整個過程反過來跑一次 → 就是她看到的左右晃動。

   修法：永遠替捲軸保留那條槽位，可視寬度就不會忽寬忽窄。
   ⚠️ 這一行必須下在 html(真正的捲動容器)上，寫在 body 上不會生效。
   手機不受影響也不會有副作用——行動瀏覽器是「覆蓋式捲軸」，本來就不佔寬度，
   規格也明訂覆蓋式捲軸會忽略 scrollbar-gutter。 */
html { scrollbar-gutter: stable; }
/* 舊版瀏覽器(Safari 18.2 以前)不認得 scrollbar-gutter，退回「捲軸永遠顯示」。
   效果一樣是寬度固定，只是內容短的時候會看到一條沒作用的捲軸。 */
@supports not (scrollbar-gutter: stable) {
  html { overflow-y: scroll; }
}

/* ⚠️(2026-07-26審查抓到的真bug，已修正)：body的padding-top/padding-bottom是JS(applyChromeLayout)
   在頁首/頁尾收合展開時同步改的inline style，用來幫忙讓出/收回頁首/頁尾佔用的空間。原本這裡沒有
   transition，inline style改變是「瞬間跳」；但#site-header/#site-footer本身是靠transform+.22s
   ease慢慢滑動——兩邊速度不同步，會有大約220ms的畫面撕裂(頁首還在滑動途中，內容已經瞬間跳到
   新位置，兩者互相重疊或露出破綻的空白)。加上同樣的.22s ease讓padding也跟著慢慢變化，兩邊才會
   視覺同步。 */
body { font-family: 'Segoe UI', sans-serif; background: #f4f1ea; color: #2b2620; margin: 0; padding: 0; transition: padding-top .22s ease, padding-bottom .22s ease; }
/* 置中容器：max-width+width:100%+margin:0 auto+左右padding+box-sizing:border-box(2026-07-24調整為1200px、
   padding直接寫在容器上，不再靠body的padding代勞——這樣body可以維持padding:0，跟頁首那幾條需要
   滿版背景的橫條之間不會有兩層padding疊加的問題) */
.page { max-width: 1200px; width: 100%; margin: 0 auto; padding-left: 16px; padding-right: 16px; }
h1 { color: #4a7a3d; text-align: center; margin-bottom: 4px; }
.sub { text-align: center; color: #8a7e6a; font-size: .85em; margin-bottom: 20px; }

/* 🔝🔻 頁首/頁尾懸浮固定＋拉桿收合(2026-07-26，使用者要求)：兩者都position:fixed蓋在最上層，
   下層內容捲動時不會被牽著一起動；各自的拉桿預設拉出(展開)狀態，使用者手動拉入才收合，
   且刻意不用localStorage記憶——每次重新整理網頁都要回到預設展開，這是使用者明確要求的行為。
   實際的顯示/隱藏尺寸量測、拉桿定位、跟#cart-bar的疊放協調，全部在shop-common.js的
   applyChromeLayout()處理(因為頁首內容手機/電腦寬度不同會換行，高度不是固定值，只能用JS量)。 */
#site-header {
  position: fixed; top: 0; left: 0; right: 0; z-index: 6;
  background: #f4f1ea; box-shadow: 0 2px 8px rgba(0,0,0,.08);
  transition: transform .22s ease;
}
#site-header.chrome-collapsed { transform: translateY(-100%); }
.top-bar { background: #efe9da; font-size: .78em; }
.top-bar-inner { max-width: 1200px; width: 100%; margin: 0 auto; padding: 4px 16px; display: flex; justify-content: flex-end; align-items: center; gap: 16px; flex-wrap: wrap; }
.top-bar-inner a { color: #6b6250; text-decoration: none; }
.top-bar-inner a:hover { color: #4a7a3d; }
/* 🔍「查詢我的訂單」放大突顯(2026-08-11 使用者要求「放大再放大」)。
   .top-bar 本身是 .78em(約 12.5px)，這裡用 1.8em 拉到約 22px，比旁邊的自訂連結大一倍多。
   ⚠️ 要調大小改這一個 font-size 就好，其他都是相對它算的。
   ⚠️ 這一列變高會把整個固定頁首撐高，但 applyChromeLayout() 是用 offsetHeight 動態量測的，
      內容區留白會自動跟著長，不用去改任何寫死的高度。 */
.top-bar-inner a.top-order-lookup {
  font-size: 1.8em; font-weight: 700; color: #4a7a3d;
  line-height: 1.25; padding: 2px 0; white-space: nowrap;
}
.top-bar-inner a.top-order-lookup:hover { color: #3d6633; text-decoration: underline; }
@media (max-width: 767px) {
  /* 手機版頂部空間寶貴，放大但不要大到把自訂連結擠到下一排 */
  .top-bar-inner a.top-order-lookup { font-size: 1.55em; }
}
.header-row { max-width: 1200px; width: 100%; margin: 0 auto; padding: 12px 16px; display: flex; align-items: center; gap: 16px; flex-wrap: wrap; }
.logo-link { font-size: 1.4em; font-weight: 700; color: #4a7a3d; text-decoration: none; white-space: nowrap; display: flex; align-items: center; gap: 10px; }
.logo-link img { height: 72px; width: auto; object-fit: contain; flex-shrink: 0; }
/* position:relative 是給搜尋建議下拉當定位基準的（2026-08-11）。
   ⚠️ #site-header 沒有 overflow:hidden，所以下拉可以正常超出頁首往下展開。 */
.search-wrap { flex: 1; min-width: 160px; position: relative; }
/* 🔧 返回維護（2026-08-11）：只在「從後台點過來」的分頁出現，客人看不到。
   ⚠️ 放右下角並把 bottom 拉到 78px —— 購物車列是固定在最底下的，
      貼著底邊會被它蓋住（她預覽商品時購物車通常是空的、看不出問題，
      但一旦購物車有東西就會撞在一起）。 */
#admin-return-bar {
  position: fixed; right: 12px; bottom: 78px; z-index: 30;
  display: flex; align-items: stretch; gap: 1px;
  border-radius: 8px; overflow: hidden;
  box-shadow: 0 3px 12px rgba(0,0,0,.25);
}
.admin-return-btn {
  background: #4a7a3d; color: #fff; text-decoration: none;
  padding: 9px 14px; font-size: .85em; font-weight: 700; white-space: nowrap;
}
.admin-return-btn:hover { background: #3d6633; color: #fff; }
.admin-return-x {
  background: #3d6633; color: #fff; border: none; cursor: pointer;
  padding: 0 10px; font-size: .9em; line-height: 1;
}
.admin-return-x:hover { background: #345629; }
@media (max-width: 767px) { #admin-return-bar { bottom: 84px; right: 8px; } }

/* 🔍 搜尋建議下拉：給「頁面上沒有商品格子可以就地篩」的頁面用（商品頁/店鋪頁/政策頁）。
   首頁不用這個——它直接篩自己的商品格子，一次看到整片結果，體驗更好。 */
.search-suggest {
  position: absolute; left: 0; right: 0; top: calc(100% + 6px); z-index: 20;
  background: #fff; border: 1px solid #e0dbd0; border-radius: 12px;
  box-shadow: 0 6px 22px rgba(0,0,0,.16);
  max-height: 60vh; overflow-y: auto; overscroll-behavior: contain;
}
.search-suggest a {
  display: flex; align-items: center; gap: 10px; padding: 8px 12px;
  text-decoration: none; color: #2b2620; border-bottom: 1px solid #f2efe8;
}
.search-suggest a:last-child { border-bottom: none; }
.search-suggest a:hover, .search-suggest a.active { background: #f2f6ef; }
.search-suggest img { width: 40px; height: 40px; object-fit: cover; border-radius: 6px; flex-shrink: 0; background: #eee; }
.search-suggest .ss-name {
  flex: 1; min-width: 0; font-size: .86em; line-height: 1.35;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}
.search-suggest .ss-price { font-size: .82em; color: #4a7a3d; font-weight: 700; white-space: nowrap; }
.search-suggest .ss-more { justify-content: center; color: #4a7a3d; font-size: .84em; font-weight: 600; }
.search-suggest .ss-empty { padding: 14px 12px; text-align: center; color: #8a7e6a; font-size: .85em; }
.search-box { width: 100%; padding: 10px 14px; border: 1px solid #ddd; border-radius: 20px; font-size: .95em; }
/* 🛒(2026-07-26使用者要求)：購物車圖示從「綠圓底+🛒emoji」換成自製圖片(cart_icon.png，已去外圍
   白邊、圖片本身自帶橘色圓角方形外框)——按鈕背景因此改透明、拿掉綠圓底，尺寸維持44px不變。 */
.cart-icon-btn { position: relative; background: none; width: 48px; height: 48px; display: flex; align-items: center; justify-content: center; flex-shrink: 0; padding: 0; } /* 44px使用者要求改48px試試，兩版共用(2026-07-26) */
.cart-icon-btn img { width: 100%; height: 100%; object-fit: contain; display: block; }
.cart-icon-count { position: absolute; top: -4px; right: -4px; background: #c2703a; color: #fff; border-radius: 10px; font-size: .62em; padding: 1px 5px; font-weight: 700; }
.nav-bar { background: #fff; border-top: 1px solid #eee; border-bottom: 1px solid #eee; }
.nav-bar-inner { max-width: 1200px; width: 100%; margin: 0 auto; padding: 8px 16px; display: flex; gap: 20px; flex-wrap: wrap; }
/* 🔠 商品類別字級(2026-08-11 使用者要求放大一些)：.88em → 1.08em（約 14px → 17px）。
   ⚠️ 手機版的 @media 區塊只覆寫了 padding、沒有覆寫 font-size，所以改這一行**兩版同時生效**，
      不要再去手機版那邊加第二個 font-size（加了就變成兩個數字要同步維護）。
   ⚠️ 這一列變高會把固定頁首撐高，但 applyChromeLayout() 是動態量測的，內容留白會自動跟著長。 */
.nav-link { color: #6b6250; text-decoration: none; font-size: 1.08em; padding: 4px 2px; border-bottom: 2px solid transparent; }
.nav-link.active { color: #4a7a3d; font-weight: 700; border-bottom-color: #4a7a3d; }
.nav-link:hover { color: #4a7a3d; }
/* 🏷️ 第二層分類籤條(2026-08-11)：完全沿用上面 .nav-bar/.nav-link 那一套，
   只做三個修飾——去掉上框線(跟第一層黏成一組，不要看起來像兩條不相干的橫條)、
   底色略淺、字級縮小。刻意不換配色：層級差用大小表達就夠了。 */
.sub-nav-bar { border-top: none; background: #fbfaf7; }
.sub-nav-bar .nav-bar-inner { padding-top: 5px; padding-bottom: 5px; gap: 16px; }
/* 子分類跟著主分類等比放大（.8→.96em），維持「比上一層小一點」的層級感。
   主分類放大到 1.08em 而子分類還停在 .8em 的話，兩層的大小差距會突兀到像兩個不相干的元件。 */
.sub-nav-bar .nav-link { font-size: .96em; cursor: pointer; }
/* 📏(2026-07-26使用者截圖要求，僅手機版)：分類標籤換行成兩排時上下太鬆——排與排之間的
   row-gap從20px縮到6px(左右間距維持20px不變)、整條導覽列的上下padding從8px縮到4px、
   每個標籤自身的上下padding從4px縮到2px。桌機版(≥768px)單排顯示、維持原間距不動。 */
@media (max-width: 767px) {
  .nav-bar-inner { row-gap: 6px; padding-top: 4px; padding-bottom: 4px; }
  .nav-link { padding-top: 2px; padding-bottom: 2px; }
  /* 🏷️ 手機版**兩層都橫向捲動、各佔一排**。
     第二層 2026-08-11 就改了；第一層 2026-08-13 跟上——分類從 7 個變 13 個之後，
     第一層在手機上會折成三四排，首屏被吃掉一大半。 */
  .nav-bar-inner { flex-wrap: nowrap; overflow-x: auto; row-gap: 0;
    -webkit-overflow-scrolling: touch; scrollbar-width: none; scroll-behavior: smooth; }
  .nav-bar-inner::-webkit-scrollbar { display: none; }
  .nav-link { white-space: nowrap; flex-shrink: 0; }

  /* 👉 捲動提示（純 CSS，不用監聽 scroll 事件）。
     原理是兩層背景疊在一起：
       · 上層＝「跟著內容捲動」(local) 的底色遮罩
       · 下層＝「固定在容器上」(scroll) 的陰影
     捲到最左邊時，左邊遮罩剛好蓋住左邊陰影 → 看不見；
     一往右捲，遮罩跟著內容跑掉，左邊陰影就露出來。右邊同理。
     於是「哪一邊還有東西」會自己顯示、捲到底自己消失。
     ⚠️ 遮罩顏色**必須跟該列底色一致**，所以兩層底色不同要分開寫。 */
  .nav-bar-inner {
    background:
      linear-gradient(90deg, #fff 40%, rgba(255,255,255,0)) 0 0 / 28px 100% no-repeat local,
      linear-gradient(90deg, rgba(255,255,255,0), #fff 60%) 100% 0 / 28px 100% no-repeat local,
      radial-gradient(farthest-side at 0 50%, rgba(0,0,0,.16), rgba(0,0,0,0)) 0 0 / 13px 100% no-repeat scroll,
      radial-gradient(farthest-side at 100% 50%, rgba(0,0,0,.16), rgba(0,0,0,0)) 100% 0 / 13px 100% no-repeat scroll;
  }
  .sub-nav-bar .nav-bar-inner {
    flex-wrap: nowrap; overflow-x: auto; row-gap: 0;
    background:
      linear-gradient(90deg, #fbfaf7 40%, rgba(251,250,247,0)) 0 0 / 28px 100% no-repeat local,
      linear-gradient(90deg, rgba(251,250,247,0), #fbfaf7 60%) 100% 0 / 28px 100% no-repeat local,
      radial-gradient(farthest-side at 0 50%, rgba(0,0,0,.16), rgba(0,0,0,0)) 0 0 / 13px 100% no-repeat scroll,
      radial-gradient(farthest-side at 100% 50%, rgba(0,0,0,.16), rgba(0,0,0,0)) 100% 0 / 13px 100% no-repeat scroll;
  }
  .sub-nav-bar .nav-bar-inner::-webkit-scrollbar { display: none; }
  .sub-nav-bar .nav-link { white-space: nowrap; flex-shrink: 0; }

}

/* 🖼️(2026-07-26最終版)：頁首「宜家工坊」文字兩版都已拿掉(先是電腦版畫圖要求、後手機版也跟進)，
   HTML裡只剩<img>的LOGO(72px，跟後台側欄一致；alt文字保留無障礙用途)；搜尋欄兩版統一跟
   LOGO/購物車同一排、flex:1自動填滿中間寬度(手機版原本「搜尋框獨佔第二排」的特例規則已移除)。
   .cart-icon-btn的margin-left:auto保留當備援：萬一螢幕窄到擠不下(<約360px)、搜尋框被flex-wrap
   擠去換行時，第一排剩LOGO+購物車，購物車依然靠右貼齊而不是緊貼LOGO。 */
@media (max-width: 480px) {
  .cart-icon-btn { margin-left: auto; }
}
button { border: none; border-radius: 8px; padding: 7px 14px; cursor: pointer; font-size: .9em; }
.btn-add { background: #4a7a3d; color: #fff; }
.btn-add:disabled { background: #ccc; }
.btn-ghost { background: #eee; color: #6b6250; }
.btn-ghost:disabled { background: #f5f5f5; color: #bbb; }
.btn-checkout:disabled { background: #ccc; cursor: not-allowed; }
/* position:sticky只有在頁面內容比視窗高、真的需要捲動時才會貼底；商品少、內容比視窗矮時
   (例如只有幾件商品)sticky完全不會生效，購物車列就停在內容結尾、跟畫面下緣之間留一大截空白
   (2026-07-24抓到這個問題)。改成position:fixed，不管內容多高都固定貼在視窗最下緣。
   ⚠️(2026-07-26)：bottom值改由JS的applyChromeLayout()動態控制——#site-footer上線後，
   購物車列要疊在頁尾「目前展開的那一截」上方、不能互相蓋住，寫死bottom:0不夠用了，這裡的
   bottom:0只當JS還沒執行完之前的預設值(fallback)。 */
#cart-bar { position: fixed; bottom: 0; left: 0; right: 0; background: #fff; border-top: 2px solid #4a7a3d; padding: 10px 16px; box-shadow: 0 -2px 8px rgba(0,0,0,.08); z-index: 5; transition: bottom .22s ease; }

/* 🔻 頁尾(2026-07-26新建)：跟頁首同一種懸浮收合機制，方向相反(往下滑收合)。沒有訊息也沒有
   連結時JS會把display設none，整個頁尾骨架不佔任何空間、拉桿也會一併隱藏(見applyChromeLayout)。 */
#site-footer {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 6;
  background: #efe9da; border-top: 1px solid #ddd6c4;
  box-shadow: 0 -2px 8px rgba(0,0,0,.08);
  padding: 10px 16px; font-size: .82em; color: #6b6250;
  transition: transform .22s ease;
}
#site-footer.chrome-collapsed { transform: translateY(100%); }
.footer-inner { max-width: 1200px; width: 100%; margin: 0 auto; display: flex; flex-direction: column; gap: 6px; align-items: center; text-align: center; }
/* 📐 版權宣告(2026-08-08起固定在頁尾最底下那一列)：三列由上而下是
   ①導流連結 ②政策法規 ③版權宣告，重要性遞減，所以字級與顏色也跟著遞減。
   版權是「網站的句點」——要在、但不該搶任何注意力。 */
.footer-message { white-space: pre-line; font-size: .8em; color: #a0958a; }
.footer-message:not(:first-child) { margin-top: 1px; }
.footer-links { display: flex; gap: 14px; flex-wrap: wrap; justify-content: center; }
.footer-links a { color: #6b6250; text-decoration: none; }
.footer-links a:hover { color: #4a7a3d; }
/* 📜 政策條文那一列(2026-08-08)：字級與顏色都比上面的自訂連結再收斂一階。
   服務條款這類東西要「找得到」但不該搶注意力，電商站的慣例就是壓在最底下一行。
   分隔線只在它上面真的有東西時才該出現，所以用 :not(:first-child) 擋掉
   「頁尾只有政策連結」那種情況——不然會憑空多一條線。 */
.footer-policies { font-size: .86em; gap: 10px; }
.footer-policies a { color: #8a7e6a; }
.footer-policies:not(:first-child) { margin-top: 2px; padding-top: 6px;
  border-top: 1px solid rgba(0,0,0,.06); align-self: stretch; }

/* 🖐️ 頁首/頁尾拉桿(2026-07-26)：刻意獨立於#site-header/#site-footer之外、不是它們的子元素——
   頁首/頁尾靠transform滑動收合，CSS規則是「有transform的祖先元素，會讓子孫元素的position:fixed
   變成相對於這個祖先定位、不是相對於整個畫面」，如果拉桿是子元素，頁首/頁尾收合滑走時拉桿會被
   一起藏起來、完全抓不回來。改成跟頁首/頁尾同層級的獨立fixed元素，top/bottom由JS動態算出來
   跟著頁首/頁尾目前的高度連動(見shop-common.js的applyChromeLayout())，不管收合或展開，拉桿
   永遠留在畫面上可以抓。 */
.chrome-drag-handle {
  position: fixed; left: 50%; transform: translateX(-50%);
  width: 52px; height: 16px; background: #2b2620;
  z-index: 7; cursor: grab; touch-action: none;
  display: flex; align-items: center; justify-content: center;
  transition: top .22s ease, bottom .22s ease;
}
.chrome-drag-handle::before { content: ''; width: 24px; height: 3px; background: rgba(255,255,255,.6); border-radius: 2px; }
#header-drag-handle { border-radius: 0 0 8px 8px; }
#footer-drag-handle { border-radius: 8px 8px 0 0; }
#cart-summary { display: flex; justify-content: space-between; align-items: center; max-width: 680px; margin: 0 auto; }
/* 🛒(2026-07-26使用者要求)：底部購物車列的🛒emoji也換成自製圖示，跟頁首/彈窗同一張圖 */
.cart-summary-label { display: flex; align-items: center; gap: 8px; }
.cart-summary-label img { height: 48px; width: auto; object-fit: contain; } /* 32px使用者要求改48px試試(2026-07-26) */
.btn-checkout { background: #c2703a; color: #fff; font-weight: 700; padding: 10px 20px; }
.modal { position: fixed; inset: 0; background: rgba(0,0,0,.4); display: flex; align-items: center; justify-content: center; z-index: 10; }
.sheet { background: #fff; border-radius: 14px; padding: 20px; max-width: 420px; width: 92%; max-height: 85vh; overflow: auto; font-size: 1.3em; }
.sheet-cart { max-width: 760px; }
.sheet h2 { margin-top: 0; }
/* 🛒(2026-07-26使用者要求)：購物車彈窗左上標題的🛒emoji也換成自製圖示，跟頁首按鈕同一張圖 */
.cart-modal-title { display: flex; align-items: center; gap: 8px; }
.cart-modal-title img { height: 48px; width: auto; object-fit: contain; } /* 30px使用者反應太小，2026-07-26放大到48px */
.sheet p { font-size: 1.08em; line-height: 1.5; }
.field { margin-bottom: 10px; }
.field label { display: block; font-size: .82em; color: #8a7e6a; margin-bottom: 3px; }
.field input, .field select, .field textarea { width: 100%; padding: 8px; border: 1px solid #ddd; border-radius: 6px; font-size: .95em; }
/* 📅 自訂日期時間選擇器(2026-07-25)：取代瀏覽器原生<input type="datetime-local">，因為原生的
   年曆彈出視窗是瀏覽器自己畫的、網頁完全無法在裡面加確定按鈕。用position:fixed置中的小面板，
   不受外層.sheet(overflow:auto)捲動位置影響，不管當下捲到哪裡，點開都一定完整看得到。 */
#transfer-time-display { cursor: pointer; background: #fff; }
.dt-picker-popup { position: fixed; top: 50%; left: 50%; transform: translate(-50%, -50%); z-index: 30; background: #fff; border-radius: 10px; box-shadow: 0 8px 28px rgba(0,0,0,.28); padding: 14px; width: 260px; max-width: 90vw; }
/* 🗨️ 站內聊聊(2026-07-26使用者要求)：浮動聊聊按鈕預設在右下角、z-index全站最高(不被頁尾/
   購物車列蓋住)、可自由拖曳(JS比照admin.html的☰按鈕同一套2D拖曳，輕點=開聊天面板、拖曳=移動、
   重新整理回到預設位不記憶)。聊天面板：手機版貼底的抽屜、桌機版右下角卡片。 */
/* (2026-07-26二版)：按鈕從「綠圓+🗨️emoji」換成四款每日輪換的去背圖(見shop-common.js的
   chatFabIconSrc())——容器改透明、寬度隨圖片比例(圓形款~52px寬、橫幅款~200-260px寬)，
   陰影用drop-shadow跟著去背輪廓走(box-shadow會畫出透明矩形外框的影子，不適用)。 */
#chat-fab { position: fixed; right: 12px; bottom: 12px; height: 52px; background: none; z-index: 40; display: flex; align-items: center; justify-content: center; padding: 0; border: none; touch-action: none; cursor: grab; filter: drop-shadow(0 2px 6px rgba(0,0,0,.35)); }
#chat-fab img { height: 100%; width: auto; object-fit: contain; display: block; pointer-events: none; }
#chat-fab-badge { position: absolute; top: -4px; right: -4px; background: #c2703a; color: #fff; border-radius: 10px; font-size: .55em; padding: 1px 6px; font-weight: 700; }
#chat-panel { position: fixed; z-index: 41; background: #fff; border: 1px solid #ddd6c4; box-shadow: 0 4px 24px rgba(0,0,0,.3); display: flex; flex-direction: column; overflow: hidden; }
@media (min-width: 481px) { #chat-panel { right: 16px; bottom: 16px; width: 340px; height: 480px; max-height: 80vh; border-radius: 12px; } }
@media (max-width: 480px) { #chat-panel { left: 0; right: 0; bottom: 0; height: 72vh; border-radius: 12px 12px 0 0; } }
#chat-panel-header { background: #4a7a3d; color: #fff; padding: 10px 12px; display: flex; justify-content: space-between; align-items: center; font-weight: 700; flex-shrink: 0; }
#chat-panel-header button { background: none; color: #fff; font-size: 1em; padding: 2px 6px; }
#chat-contact-row { display: flex; gap: 8px; padding: 8px 10px; border-bottom: 1px solid #eee; background: #faf8f2; flex-shrink: 0; }
#chat-contact-row input { flex: 1; min-width: 0; padding: 6px 8px; border: 1px solid #ddd; border-radius: 6px; font-size: .85em; }
#chat-verify-row { padding: 8px 10px; border-bottom: 1px solid #eee; background: #fff6e0; flex-shrink: 0; }
#chat-verify-row input { padding: 6px 8px; border: 1px solid #ddd; border-radius: 6px; font-size: .85em; }
#chat-verify-row button { background: #4a7a3d; color: #fff; font-size: .85em; padding: 6px 10px; flex-shrink: 0; }
#chat-verify-hint { font-size: .78em; color: #8a6d1a; margin-bottom: 6px; }
#chat-messages { flex: 1; overflow-y: auto; padding: 10px; background: #f4f1ea; }
.chat-empty { color: #8a7e6a; font-size: .82em; text-align: center; padding: 18px 8px; }
.chat-line { margin-bottom: 8px; display: flex; flex-direction: column; }
.chat-mine { align-items: flex-end; }
.chat-theirs { align-items: flex-start; }
.chat-bubble { max-width: 80%; padding: 8px 10px; border-radius: 10px; font-size: .9em; white-space: pre-wrap; word-break: break-word; }
.chat-mine .chat-bubble { background: #dcedc8; }
.chat-theirs .chat-bubble { background: #fff; border: 1px solid #eee; }
.chat-time { font-size: .68em; color: #8a7e6a; margin-top: 2px; }
#chat-input-row { display: flex; gap: 8px; padding: 8px; border-top: 1px solid #eee; background: #fff; flex-shrink: 0; }
#chat-input-row textarea { flex: 1; resize: none; border: 1px solid #ddd; border-radius: 8px; padding: 8px; font-size: .9em; font-family: inherit; }
#chat-input-row button { background: #4a7a3d; color: #fff; }
.dt-picker-cal-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 8px; font-weight: 700; }
.dt-picker-cal-header button { background: none; border: none; font-size: 1.3em; line-height: 1; cursor: pointer; color: #4a7a3d; padding: 2px 10px; }
.dt-picker-weekdays { display: grid; grid-template-columns: repeat(7, 1fr); text-align: center; font-size: .78em; color: #8a7e6a; margin-bottom: 4px; }
.dt-picker-grid { display: grid; grid-template-columns: repeat(7, 1fr); gap: 2px; }
.dt-picker-grid span { text-align: center; padding: 6px 0; border-radius: 6px; font-size: .88em; }
.dt-picker-day { cursor: pointer; }
.dt-picker-day:hover { background: #f0ede0; }
.dt-picker-day.selected { background: #4a7a3d; color: #fff; font-weight: 700; }
.dt-picker-time-row { display: flex; align-items: center; gap: 6px; margin-top: 10px; font-size: .9em; }
.dt-picker-time-row select { padding: 4px 6px; border: 1px solid #ddd; border-radius: 6px; width: auto; }
.dt-picker-quick { font-size: .8em; margin-top: 8px; }
.dt-picker-quick a { color: #4a7a3d; cursor: pointer; text-decoration: underline; margin-right: 14px; }
.dt-picker-actions { display: flex; justify-content: flex-end; gap: 8px; margin-top: 12px; }
.cart-line { padding: 10px 0; border-bottom: 1px solid #f0ede6; }
.cart-line:last-of-type { border-bottom: none; }
.cart-line-top { display: flex; align-items: center; gap: 8px; font-size: .9em; }
.cart-line-info { flex: 1; min-width: 0; font-weight: 600; }
.cart-line-price { color: #4a7a3d; font-weight: 700; white-space: nowrap; }
.cart-line-bottom { display: flex; align-items: flex-end; justify-content: space-between; margin-top: 8px; padding-left: 52px; }
.qty-control { display: flex; align-items: center; gap: 8px; }
.qty-btn { width: 26px; height: 26px; border-radius: 6px; background: #eee; }
.qty-btn:disabled { opacity: .35; cursor: not-allowed; }
.qty-num { min-width: 20px; text-align: center; font-weight: 700; }
.stock-hint { font-size: .75em; color: #8a7e6a; margin-top: 4px; }
/* 🚦 這一項已經超過供給上限：數字要跟著紅起來，客人才會把它跟上面的紅框對上 */
.stock-hint.over { color: #d94436; font-weight: 700; }
.remove-link { background: none; border: none; padding: 4px; font-size: .85em; color: #8a7e6a; cursor: pointer; }
.remove-link:hover { color: #a33; }
.quote-row { display: flex; justify-content: space-between; font-size: .88em; padding: 2px 0; }
.quote-row.total { font-weight: 700; font-size: 1.05em; border-top: 1px solid #eee; margin-top: 6px; padding-top: 6px; }
.free-ship-hint { font-size: 1em; line-height: 1.5; color: #c2703a; margin: 8px 0; }
/* 🔔 訂單編號提醒(2026-07-25)：跟admin.html既有的blink-reminder同一套「一閃一閃」動畫語言，
   顏色改用前台自己的品牌綠(#4a7a3d，跟h1/價格同色)，跟admin那邊用的#22c55e區隔開來，
   各自跟自己頁面的既有配色一致。 */
@keyframes blink-reminder { 0%, 100% { opacity: 1; } 50% { opacity: .25; } }
.order-id-reminder { color: #4a7a3d; font-weight: 700; font-size: .88em; margin: 10px 0; animation: blink-reminder 1.2s ease-in-out infinite; }

/* 🚦 購物車缺貨提示(2026-08-06 使用者要求)：警告框用跟訂單編號提醒同一套閃爍語言，
   出問題的那幾列再加一圈醒目紅框——警告文字裡的商品名稱很長，光看文字很難跟下面的清單對上，
   一定要在清單上直接標出來客人才知道要動哪一項。 */
.cart-alert-blink { animation: blink-reminder 1.2s ease-in-out infinite; }
.cart-line.out-of-stock { border: 2px solid #d94436; border-radius: 8px; padding: 8px; margin: 6px 0; background: #fff8f7; }
/* 紅框那一列自己有邊框了，就不要再疊原本的底線分隔線，看起來會像雙線 */
.cart-line.out-of-stock { border-bottom: 2px solid #d94436; }
.pay-option { border: 1px solid #ddd; border-radius: 8px; padding: 8px 10px; margin-bottom: 8px; cursor: pointer; }
.pay-option.selected { border-color: #4a7a3d; background: #f0f7ec; }
/* ✕ 關閉鈕（2026-08-10 改）。
   ⚠️ 原本只有 float:right，而 .sheet 是 max-height:85vh + overflow:auto 的捲動容器——
      內容一長，✕ 就跟著捲出畫面外。以前不明顯是因為「點背景也能關」還在，
      使用者總有退路；現在背景關閉拿掉了（她要求的：怕誤點把打到一半的回饋弄丟），
      ✕ 就成了唯一的出口，**絕對不能讓它捲不見**。
      sticky 讓它永遠貼在可視區的上緣；不透明底色 + 圓形是必要的，
      否則捲動時下面的文字會從按鈕後面透出來，糊成一團。
   （另外還有 Esc 可以關，見 shop-common.js 的鍵盤處理。） */
#close-modal { float: right; position: sticky; top: -6px; z-index: 3;
               background: #fff; border: 1px solid #ece5d8; border-radius: 50%;
               width: 34px; height: 34px; line-height: 1; padding: 0;
               font-size: 1.1em; color: #888; cursor: pointer;
               box-shadow: 0 1px 4px rgba(0,0,0,.12); }
#close-modal:hover { color: #333; background: #f6f3ec; }
.status-badge { display: inline-block; padding: 3px 10px; border-radius: 20px; font-size: .8em; }

/* ⭐ 商品回饋（2026-08-08）——只出現在「查詢我的訂單」查到自己那筆時。
   ⚠️ 這不是公開評價：商品頁/首頁/店鋪頁完全沒有對應的樣式與元素，是刻意的。 */
.rv-wrap { margin-top: 14px; padding-top: 12px; border-top: 1px dashed #e0d8c8; }
.rv-head { font-weight: 700; color: #4a7a3d; margin-bottom: 4px; }
.rv-note { font-size: .8em; color: #8a7e6a; line-height: 1.8; margin-bottom: 10px; }
.rv-item { background: #fbf9f4; border: 1px solid #ece5d8; border-radius: 8px;
           padding: 10px 12px; margin-bottom: 8px; }
.rv-name { font-size: .9em; font-weight: 600; color: #3a3228; margin-bottom: 6px;
           word-break: break-word; }
.rv-stars { font-size: 1.5em; line-height: 1; letter-spacing: 3px; margin-bottom: 6px; }
/* 未選是灰的、選到是橘的。cursor:pointer 讓人知道可以點 */
.rv-star { color: #ddd6c4; cursor: pointer; user-select: none; transition: color .1s; }
.rv-star.on { color: #e0a33f; }
.rv-star:hover { color: #e0a33f; }
.rv-text { width: 100%; padding: 8px 10px; border: 1px solid #e6ded0; border-radius: 8px;
           font-family: inherit; font-size: .88em; line-height: 1.7; resize: vertical; }
.rv-act { display: flex; align-items: center; gap: 10px; margin-top: 6px; flex-wrap: wrap; }
.rv-act button { padding: 6px 14px; font-size: .85em; }
.rv-msg { font-size: .8em; color: #8a7e6a; }
.rv-msg.ok { color: #4a7a3d; font-weight: 700; }
.rv-msg.bad { color: #c0392b; }

/* 💬 賣家回覆（2026-08-10）。做成「往內縮一層＋左側色條」，
   一眼就分得出上面是客人自己寫的、這一塊是賣家回的，不會看成同一段。 */
.rv-reply { margin: 8px 0 2px 12px; padding: 8px 12px; background: #f2f7ef;
            border-left: 3px solid #4a7a3d; border-radius: 0 8px 8px 0; }
.rv-reply-head { font-size: .8em; font-weight: 700; color: #4a7a3d; margin-bottom: 3px; }
.rv-reply-body { font-size: .88em; line-height: 1.8; color: #3a3228;
                 white-space: pre-wrap; word-break: break-word; }

/* 🌏 商品頁上的公開評價（2026-08-10，只有「開啟商品回饋曝光」時才會出現） */
.pr-wrap { margin-top: 22px; padding-top: 16px; border-top: 1px solid #ece5d8; }
.pr-head { display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap; margin-bottom: 10px; }
.pr-title { font-weight: 700; font-size: 1.05em; color: #3a3228; }
.pr-avg { color: #e0a33f; font-weight: 700; letter-spacing: 2px; }
.pr-count { font-size: .82em; color: #8a7e6a; }
.pr-item { background: #fbf9f4; border: 1px solid #ece5d8; border-radius: 8px;
           padding: 10px 12px; margin-bottom: 8px; }
.pr-row { display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap; }
.pr-stars { color: #e0a33f; letter-spacing: 2px; }
.pr-name { font-size: .84em; color: #6b6152; font-weight: 700; }
.pr-date { font-size: .78em; color: #a99a86; }
.pr-body { margin-top: 5px; font-size: .9em; line-height: 1.8; color: #3a3228;
           white-space: pre-wrap; word-break: break-word; }
.pr-empty { font-size: .85em; color: #8a7e6a; padding: 6px 0; }
