
* { margin: 0; padding: 0; box-sizing: border-box; }
:root {
  --primary: #B8825C;
  --primary-dark: #9A6A47;
  --primary-soft: #C8946E;   /* 主色浅一档，用于渐变浅端与文档内引用 */
  --primary-light: #F8F0E8;
  --primary-lighter: #FDFAF6;
  --danger: #D96B5A;
  --danger-dark: #C25A4A;
  --success: #7BAE7B;
  --warning: #D9A85C;
  --bg: #F8F4F0;
  --bg-outer: #EFE8E1;   /* 桌面端内容区两侧的底色（手机端撑满，看不到） */
  --card: #fff;
  --text: #4A3B32;
  --text-2: #7A6B62;
  --text-3: #A89B92;
  --border: #EBE2DA;
  --shadow-sm: 0 1px 4px rgba(140,110,80,0.06);
  --shadow-md: 0 2px 12px rgba(140,110,80,0.08);
  --shadow-lg: 0 4px 20px rgba(140,110,80,0.12);
  --radius: 10px;
  --radius-lg: 14px;
  --transition: cubic-bezier(0.4, 0, 0.2, 1);
  --transition-bounce: cubic-bezier(0.34, 1.56, 0.64, 1);
  --grad-primary: linear-gradient(135deg, #C8946E, #B8825C);
  --grad-seller: linear-gradient(135deg, #4A3B32, #3D3027);
  --grad-cart: linear-gradient(135deg, #D9A85C, #C8946E);
  --grad-buy: linear-gradient(135deg, #D96B5A, #C75A4A);

  /* ---------- 吸顶层级偏移（2026-09-12 新增，见 js/api.js 里的 StickyTop） ----------
     ⚠️ 背景：.navbar 自己就是 position:sticky; top:0; z-index:100。
     任何「第二个」吸顶条如果也写 top:0，会**被 navbar 直接盖住**——
     往下滑时搜索栏、分类栏整条钻进 navbar 底下，用户就看不到了。
     2026-09-12 Marco 反馈「任意界面往下滑搜索栏会被隐藏」就是这个原因。

     所以：所有次级吸顶条必须写 top: var(--navbar-h)，而不是 top: 0。
     --navbar-h 由 JS 实测 .navbar 高度后写入（含卖家模式徽章导致的高度变化）。
     默认 0px 保证「没有 navbar 的页面」不会多留空档。 */
  --navbar-h: 0px;
  --batch-h: 0px;
}

/* ==================== 全局动画 ==================== */
@keyframes fadeInUp {
  from { opacity: 0; transform: translateY(20px); }
  to { opacity: 1; transform: translateY(0); }
}
@keyframes fadeIn {
  from { opacity: 0; }
  to { opacity: 1; }
}
/* 底部固定栏专用入场动画（2026-09-11 新增）
   ⚠️ 为什么不能直接用 fadeInUp：.bottom-bar / .cart-footer 是
   `position:fixed; left:50%; transform:translateX(-50%)` 居中的，
   而 **CSS 动画会完全接管 transform** —— 动画期间 translateX(-50%) 直接失效，
   整条栏会以 left:50% 渲染，也就是**先偏右半个屏**（390 宽屏上偏右 195px），
   动画结束才「啪」地弹回中间。全站扫描时抓到 checkout 的 .bottom-bar
   在该状态下 getBoundingClientRect().right = 585（= 195 + 390）就是这个原因。

   修法：把居中位移写进关键帧，让动画期间也保持居中。
   ⚠️ 以后凡是「靠 transform 定位」的元素，入场动画都不能用带 translate 的关键帧，
      要么用 fadeIn，要么像这里一样把定位一并写进关键帧。 */
@keyframes bottomBarIn {
  from { opacity: 0; transform: translateX(-50%) translateY(14px); }
  to   { opacity: 1; transform: translateX(-50%) translateY(0); }
}
@keyframes slideInLeft {
  from { opacity: 0; transform: translateX(-30px); }
  to { opacity: 1; transform: translateX(0); }
}
@keyframes slideInRight {
  from { opacity: 0; transform: translateX(30px); }
  to { opacity: 1; transform: translateX(0); }
}
@keyframes scaleIn {
  from { opacity: 0; transform: scale(0.9); }
  to { opacity: 1; transform: scale(1); }
}
@keyframes shimmer {
  0% { background-position: -200% 0; }
  100% { background-position: 200% 0; }
}
@keyframes pulse {
  0%, 100% { transform: scale(1); }
  50% { transform: scale(1.05); }
}
@keyframes ripple {
  to { transform: scale(4); opacity: 0; }
}
@keyframes spin {
  to { transform: rotate(360deg); }
}
@keyframes bounceIn {
  0% { opacity: 0; transform: scale(0.3); }
  50% { opacity: 1; transform: scale(1.05); }
  70% { transform: scale(0.95); }
  100% { transform: scale(1); }
}
@keyframes toastSlide {
  from { opacity: 0; transform: translate(-50%, -60%) scale(0.9); }
  to { opacity: 1; transform: translate(-50%, -50%) scale(1); }
}
@keyframes shake {
  0%, 100% { transform: translateX(0); }
  25% { transform: translateX(-6px); }
  75% { transform: translateX(6px); }
}
@keyframes glowPulse {
  0%, 100% { box-shadow: 0 0 5px rgba(184,130,92,0.3); }
  50% { box-shadow: 0 0 20px rgba(184,130,92,0.6); }
}

body {
  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
  background: var(--bg);
  color: var(--text);
  max-width: 480px;
  margin: 0 auto;
  min-height: 100vh;
  position: relative;
  -webkit-tap-highlight-color: transparent;
  -webkit-font-smoothing: antialiased;
}
a { text-decoration: none; color: inherit; }
img { display: block; max-width: 100%; }

/* 页面入场动画
   ⚠️⚠️ 铁律：加在 <body> 上的入场动画**绝对不能带 transform**。
   原因：元素的 transform 只要不是 none，它就会成为后代 position:fixed 元素的
   「包含块」。body 一旦中招，body 里所有固定定位元素（底部标签栏 .tabbar、
   详情页操作栏 .bottom-bar、购物车结算条 .cart-footer）就不再相对视口定位，
   而是相对整个文档定位 —— 页面一长，它们直接跑到文档最底部，用户完全看不见。

   2026-09-11 实际踩到：给详情页加底部导航栏后整条标签栏消失，
   查了半天才发现是这行 `fadeInUp ... both` 把 transform: translateY(0)
   永久留在了 body 上（fill-mode: both 会一直保留最后一帧）。

   所以这里只做透明度淡入。需要「上浮」观感的地方，把动画加在内容容器上
   （.detail-page / .cart-page / .checkout-page 等）——它们是固定栏的兄弟节点，
   不会影响固定定位。 */
.page-enter {
  animation: fadeIn 0.4s var(--transition) both;
}

/* ==================== 骨架屏 ==================== */
.skeleton {
  background: linear-gradient(90deg, #F0EBE5 25%, #E5DDD4 50%, #F0EBE5 75%);
  background-size: 200% 100%;
  animation: shimmer 1.5s infinite;
  border-radius: 6px;
}
.skeleton-card {
  background: #fff;
  border-radius: var(--radius);
  overflow: hidden;
  box-shadow: var(--shadow-sm);
}
.skeleton-card .s-img { width: 100%; aspect-ratio: 1; }
.skeleton-card .s-lines { padding: 8px 10px; }
.skeleton-card .s-line { height: 12px; margin-bottom: 6px; border-radius: 4px; }

/* ==================== 加载动画 ==================== */
.loading-spinner {
  width: 36px; height: 36px;
  border: 3px solid var(--border);
  border-top-color: var(--primary);
  border-radius: 50%;
  animation: spin 0.8s linear infinite;
  margin: 20px auto;
}
.loading-overlay {
  position: fixed;
  inset: 0;
  background: rgba(255,255,255,0.7);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 9998;
  animation: fadeIn 0.2s;
}
.loading-overlay .loading-spinner { width: 40px; height: 40px; }

/* ==================== 顶部导航 ==================== */
.navbar {
  background: var(--grad-primary);
  color: #fff;
  padding: 12px 16px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 8px 0;
  position: sticky;
  top: 0;
  z-index: 100;
  box-shadow: 0 2px 8px rgba(140,110,80,0.2);
  transition: box-shadow 0.3s;
}
.navbar h1 { font-size: 18px; font-weight: 600; display: flex; align-items: baseline; gap: 6px; flex-wrap: wrap; }
.navbar h1 .brand-sub { font-size: 12px; font-weight: 400; opacity: 0.85; letter-spacing: 0.5px; }
.navbar .nav-right { display: flex; gap: 12px; align-items: center; }
.navbar a { color: #fff; font-size: 14px; transition: opacity 0.2s; display: flex; align-items: center; gap: 3px; }
.navbar a:active { opacity: 0.7; }
.navbar .nav-icon { width: 18px; height: 18px; flex-shrink: 0; }
.navbar .nav-text { font-size: 12px; }
.navbar .nav-icon-btn { padding: 4px; border-radius: 8px; transition: background 0.2s; }
.navbar .nav-icon-btn:active { background: rgba(255,255,255,0.15); }

/* ==================== 顶栏改版 · 紧凑 + 搜索入口（2026-09-18）====================
   Marco 要求：
     ① 固定栏占屏太多 → 顶栏瘦下来；原先「顶栏 + 独立搜索栏」两行合并成一行。
     ② 左边 logo + 店铺名，「你的专属百货」放店名下方（双行）；右边是搜索框。
     ③ 搜索框平时只是个入口，点一下弹出搜索页，输入框放大回正常大小。
     ④ 一键回顶：双击顶栏 / 下滑浮出向上箭头。
   ⚠️ 全部挂在 .navbar-compact 这个修饰类下 —— 全站 19 个页面共用 .navbar，
      直接在 .navbar 上改 flex-wrap:nowrap 会把 my.html / detail.html 等挤坏。
   高度实测：改版前 48px（顶栏）+ 56px（搜索行）= 104px；改版后 44px，省 60px。 */
.navbar.navbar-compact {
  padding: 7px 12px;
  flex-wrap: nowrap;
  gap: 0 10px;
  /* 双击回顶的手势区：禁止系统双击缩放误触、禁止选中文字 */
  -webkit-tap-highlight-color: transparent;
  touch-action: manipulation;
  user-select: none;
  -webkit-user-select: none;
}
.navbar-compact h1.nav-brand {
  display: flex;
  align-items: center;
  gap: 7px;
  flex-wrap: nowrap;
  flex: 1 1 auto;
  min-width: 0;
  font-size: 15.5px;
  font-weight: 700;
  line-height: 1.16;
}
.nav-brand .brand-logo {
  width: 26px; height: 26px;
  border-radius: 7px;
  flex: 0 0 auto;
  box-shadow: 0 1px 3px rgba(74,59,50,.18);
}
.nav-brand .brand-text {
  display: flex; flex-direction: column;
  min-width: 0;               /* 关键：不加这行，省略号在 flex 里不生效、会把搜索框挤出去 */
}
.nav-brand .brand-line { display: flex; align-items: center; gap: 5px; min-width: 0; }
.nav-brand .brand-name {
  font-size: 15.5px; font-weight: 700; letter-spacing: .5px;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.nav-brand .brand-sub {
  font-size: 10.5px; font-weight: 400; opacity: .85;
  letter-spacing: .3px;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
/* 卖家徽章收进店名旁边的小胶囊，不再另起一行把顶栏撑高 */
.navbar-compact .seller-badge {
  font-size: 10px; padding: 1px 6px; border-radius: 8px;
  flex: 0 0 auto; line-height: 1.5;
}
/* 右侧搜索入口（看起来像搜索框，实际是按钮 —— 点开才弹真的搜索页） */
.navbar-compact .nav-search {
  flex: 0 1 auto;
  width: min(44vw, 156px);
  min-width: 96px;
  display: flex; align-items: center; gap: 5px;
  background: rgba(255,255,255,.93);
  border: none;
  border-radius: 999px;
  padding: 7px 11px;
  cursor: pointer;
  transition: background .2s, transform .15s var(--transition);
  -webkit-tap-highlight-color: transparent;
  text-align: left;
}
.navbar-compact .nav-search:active { transform: scale(.96); background: #fff; }
.navbar-compact .nav-search .icon-svg { width: 14px; height: 14px; flex: 0 0 auto; color: var(--primary); }
.navbar-compact .nav-search .nav-search-ph {
  font-size: 12px; color: var(--text-3);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
/* 当前正在按关键词筛的时候，入口显示的就是那个关键词 —— 加深一点，别像占位符 */
.navbar-compact .nav-search.has-kw .nav-search-ph { color: var(--primary); font-weight: 600; }
.navbar-compact .nav-search.has-kw { background: #fff; }

/* ==================== 搜索页（顶栏搜索入口点开的浮层）====================
   Marco 要求：不用的时候只是一行小入口，用的时候输入框放大到正常大小。
   做成全屏浮层而不是新开页面 —— 关掉后筛选条件、已加载的商品、滚动位置都还在。 */
.search-overlay {
  position: fixed;
  inset: 0;
  z-index: 200;              /* 高于 .navbar(100) 与底部标签栏(120)，低于模态框 */
  background: var(--bg);
  display: flex;
  flex-direction: column;
  animation: searchOverlayIn .22s var(--transition) both;
}
.search-overlay[hidden] { display: none; }
@keyframes searchOverlayIn {
  from { opacity: 0; transform: translateY(-10px); }
  to   { opacity: 1; transform: none; }
}
.search-overlay-bar {
  display: flex; align-items: center; gap: 10px;
  padding: 10px 12px;
  padding-top: calc(10px + env(safe-area-inset-top, 0px));
  background: var(--grad-primary);
  box-shadow: 0 2px 10px rgba(140,110,80,.18);
}
.search-overlay-field {
  flex: 1;
  display: flex; align-items: center; gap: 8px;
  min-width: 0;
  background: #fff;
  border-radius: 999px;
  padding: 9px 13px;
  box-shadow: 0 2px 8px rgba(74,59,50,.10);
}
.search-overlay-field .icon-svg { width: 16px; height: 16px; flex: 0 0 auto; color: var(--primary); }
.search-overlay-field input {
  flex: 1; min-width: 0;
  border: none; outline: none; background: transparent;
  font-size: 15px; color: var(--text);   /* 放大回正常字号，不再是顶栏里的 12px */
  padding: 0;
}
.search-overlay-field input::placeholder { color: var(--text-3); font-size: 13.5px; }
/* type=search 在 Chrome/Safari 上会自带一个原生 ✕，和我们自己的清空按钮叠成两个 —— 干掉它 */
.search-overlay-field input::-webkit-search-cancel-button,
.search-overlay-field input::-webkit-search-decoration,
.search-overlay-field input::-webkit-search-results-button { -webkit-appearance: none; display: none; }
.search-overlay-clear {
  flex: 0 0 auto;
  width: 20px; height: 20px; border-radius: 50%;
  border: none; background: var(--border); color: var(--text-2);
  display: none; align-items: center; justify-content: center;
  cursor: pointer; padding: 0;
}
.search-overlay-clear .icon-svg { width: 11px; height: 11px; }
.search-overlay-field.has-value .search-overlay-clear { display: flex; }
.search-overlay-cancel {
  flex: 0 0 auto;
  background: none; border: none;
  color: #fff; font-size: 14.5px; font-weight: 500;
  padding: 6px 2px; cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}
.search-overlay-cancel:active { opacity: .65; }
/* 「搜索」按钮只在输入框有内容时才出现 —— 没输入时它按了也没用，
   白白占掉窄屏上宝贵的横向空间（旁边一直有「取消」兜底）。 */
.search-overlay-submit {
  flex: 0 0 auto;
  border: none; border-radius: 999px;
  background: #fff; color: var(--primary);
  font-size: 13.5px; font-weight: 600;
  padding: 7px 15px; cursor: pointer;
  display: none;
  animation: fadeIn .18s;
  -webkit-tap-highlight-color: transparent;
}
.search-overlay-field.has-value + .search-overlay-submit { display: block; }
.search-overlay-submit:active { transform: scale(.96); opacity: .85; }
.search-overlay-body {
  flex: 1; overflow-y: auto;
  padding: 16px;
  -webkit-overflow-scrolling: touch;
}
.search-sec-hd {
  display: flex; align-items: center; justify-content: space-between;
  font-size: 13px; color: var(--text-2); margin-bottom: 11px;
}
.search-sec-hd .clr { font-size: 12.5px; color: var(--text-3); cursor: pointer; }
.search-sec-hd .clr:active { color: var(--primary); }
.search-chips { display: flex; flex-wrap: wrap; gap: 9px; }
.search-chip {
  background: #fff;
  border: 1px solid var(--border);
  border-radius: 999px;
  padding: 7px 14px;
  font-size: 13px; color: var(--text-2);
  cursor: pointer;
  max-width: 100%;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  transition: background .2s, color .2s, border-color .2s;
  animation: fadeInUp .3s var(--transition) both;
}
.search-chip:active { background: var(--primary-light); color: var(--primary); border-color: var(--primary); }
/* 热门分类的标签：和「搜索历史」区分开，用主色浅底 */
.search-chip.search-cat {
  background: var(--primary-lighter);
  border-color: var(--primary-light);
  color: var(--primary-dark);
  font-weight: 500;
}
.search-chip.search-cat:active { background: var(--primary-light); color: var(--primary); }
.search-sec-hd.gap { margin-top: 22px; }
.search-tip { font-size: 13px; color: var(--text-3); line-height: 2; }
.search-tip b { color: var(--text-2); font-weight: 600; }

/* ==================== 一键回顶（下滑浮出的箭头）====================
   z-index 110：低于底部标签栏(120)，高于正文；bottom 让开标签栏，不互相压住。

   ⚠️⚠️ 2026-09-18 事故修正：让开标签栏的判据**必须用 body.has-tabbar 这个类**，
   绝不能用 JS 去猜、更绝不能去覆盖 --tabbar-h。
   事故经过：原先 nav-tools.js 的 syncTabbarVar() 在解析期查
   `script[src*="tabbar.js"]`，查不到就把 --tabbar-h 写成 0px —— 而它**只写不还原**。
   于是只要某页 nav-tools.js 排在 tabbar.js 之前（index.html / products.html 就是），
   解析期必然查不到 → 写成 0px → 之后 load 时虽然查到了，却只是 return，
   **0px 被永久闩住**。
   后果：`.tabbar` 高度变成 calc(0px + safe-area) ≈ 1px（只剩上边框），
   白底只画 1 条线 → 整条栏「看起来透明」，5 个图标溢出到视口外、文字标签全消失。

   现在改为纯 CSS：**没有 .has-tabbar 的页面箭头直接贴底，有标签栏的页面让开 56px**。
   .has-tabbar 由 tabbar.js 权威添加，CSS 自动响应 → 与脚本加载顺序完全无关，
   这类「谁先加载」的 bug 从根上不可能再发生。

   2026-09-18 扩到全站时新增 --totop-lift：有些页面底部还有一条固定操作栏
   （详情页 .bottom-bar、购物车 .cart-footer、客服页 .chat-input-bar），
   它们的 z-index 是 100 < 110，不加会让箭头**压在「加入购物车」按钮上**。
   该变量由 nav-tools.js 在运行时实测那条栏的高度写入（见 syncBottomBars），
   页面自己不用配。没有底部栏的页面它就是 0，等于没这回事。 */
.to-top {
  position: fixed;
  right: 14px;
  bottom: calc(env(safe-area-inset-bottom, 0px) + var(--totop-lift, 0px) + 16px);
  width: 44px; height: 44px;
  border-radius: 50%;
  border: 1px solid var(--border);
  background: rgba(255,255,255,.96);
  box-shadow: 0 4px 16px rgba(140,110,80,.22);
  color: var(--primary);
  display: flex; align-items: center; justify-content: center;
  z-index: 110;
  cursor: pointer;
  padding: 0;
  opacity: 0; visibility: hidden;
  transform: translateY(12px) scale(.88);
  transition: opacity .22s, transform .26s var(--transition-bounce), visibility .22s;
  -webkit-tap-highlight-color: transparent;
}
.to-top.show { opacity: 1; visibility: visible; transform: none; }
.to-top:active { transform: scale(.9); }
.to-top .icon-svg { width: 21px; height: 21px; }

/* 有底部标签栏的页面：箭头再让开标签栏那 56px（.has-tabbar 由 tabbar.js 加） */
body.has-tabbar .to-top {
  bottom: calc(var(--tabbar-h, 56px) + env(safe-area-inset-bottom, 0px) + var(--totop-lift, 0px) + 16px);
}

/* 顶栏手势的轻提示条（双击回顶后用一次，确认手势生效）
   同样按 body.has-tabbar 让开标签栏，判据与 .to-top 一致（见上方事故说明） */
.nav-toast {
  position: fixed;
  left: 50%;
  bottom: calc(env(safe-area-inset-bottom, 0px) + var(--totop-lift, 0px) + 74px);
  transform: translateX(-50%) translateY(10px);
  background: rgba(60,45,36,.93);
  color: #fff;
  font-size: 12.5px;
  padding: 8px 16px;
  border-radius: 999px;
  white-space: nowrap;
  z-index: 130;
  pointer-events: none;
  opacity: 0;
  transition: opacity .2s, transform .26s var(--transition);
}
body.has-tabbar .nav-toast {
  bottom: calc(var(--tabbar-h, 56px) + env(safe-area-inset-bottom, 0px) + var(--totop-lift, 0px) + 74px);
}
.nav-toast.show { opacity: 1; transform: translateX(-50%) translateY(0); }

/* 搜索中的结果提示（普通流，不吸顶）—— 搜索入口进顶栏后，
   用户需要一处「我现在搜的是什么 + 怎么退出搜索」的落点。 */
.search-result-bar {
  display: flex; align-items: center; gap: 8px;
  margin: 8px 12px 0;
  padding: 8px 12px;
  background: #fff;
  border: 1px solid var(--border);
  border-radius: 8px;
  font-size: 12.5px;
  line-height: 1.6;
  color: var(--text-2);
  animation: fadeInUp .25s var(--transition) both;
}
.search-result-bar #searchResultText { min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.search-result-bar .kw { color: var(--primary); font-weight: 600; }
.search-result-bar .clr {
  margin-left: auto; flex: 0 0 auto;
  border: 1px solid var(--border);
  background: var(--bg);
  color: var(--text-2);
  border-radius: 999px;
  font-size: 12px;
  padding: 3px 11px;
  cursor: pointer;
  transition: background .2s, color .2s, border-color .2s;
}
.search-result-bar .clr:active { background: var(--primary-light); color: var(--primary); border-color: var(--primary); }

/* ==================== 搜索栏 ==================== */
/* ==================== 吸顶工具栏（2026-09-12） ====================
   Marco 要求：商品列表页往下滑时，搜索栏 / 分类栏 / 筛选栏要一直固定在顶部，
   否则想搜东西得先滑回最上面，很麻烦。
   ⚠️ 必须给背景色 —— 否则滚动时下面的商品会从工具栏背后透出来。
   z-index 取 60：低于底部标签栏和模态框，高于商品卡片。 */
.sticky-toolbar {
  position: sticky;
  top: var(--navbar-h, 0px);   /* ⚠️ 不能写 0 —— 会被 .navbar 盖住，见 :root 注释 */
  z-index: 60;
  background: var(--bg);
  box-shadow: 0 2px 8px rgba(74,59,50,0.06);
}

.search-bar {
  background: #fff;
  padding: 10px 16px;
  display: flex;
  gap: 8px;
  animation: fadeIn 0.3s;
}
.search-bar input {
  flex: 1;
  border: 1px solid var(--border);
  border-radius: 20px;
  padding: 8px 16px;
  font-size: 14px;
  outline: none;
  transition: all 0.3s var(--transition);
}
.search-bar input:focus {
  border-color: var(--primary);
  box-shadow: 0 0 0 3px var(--primary-light);
}
.search-bar button {
  background: var(--primary);
  color: #fff;
  border: none;
  border-radius: 20px;
  padding: 0 16px;
  font-size: 14px;
  cursor: pointer;
  transition: all 0.2s var(--transition);
  position: relative;
  overflow: hidden;
}
.search-bar button:active { transform: scale(0.95); }

/* ==================== 分类标签 ====================
   2026-09-18：纵向内边距 10→7px。吸顶区里的每一行都是「滚不掉」的，
   减掉 3px 就是实打实多给商品 3px。 */
.category-tabs {
  display: flex;
  gap: 8px;
  padding: 7px 16px 6px;
  overflow-x: auto;
  background: #fff;
  border-bottom: 1px solid var(--border);
  scrollbar-width: none;
  position: relative;
}
.category-tabs::-webkit-scrollbar { display: none; }
.category-tabs .tab {
  white-space: nowrap;
  padding: 6px 14px;
  border-radius: 16px;
  font-size: 13px;
  background: var(--bg);
  color: var(--text-2);
  cursor: pointer;
  transition: background 0.2s, color 0.2s, opacity 0.2s;
  flex-shrink: 0;
  transform: none !important;
  position: relative;
}
/* 大分类激活态：保留原样式 */
.category-tabs .tab.active {
  background: var(--primary);
  color: #fff;
  box-shadow: 0 2px 8px rgba(184,130,92,0.35);
  font-weight: 600;
}
/* 大分类激活时，下方附加"展开子分类"的光晕（关联动画的一部分） */
.category-tabs .tab.active.expanded::after {
  content: '';
  position: absolute;
  left: -6px; right: -6px; bottom: -6px;
  height: 3px;
  background: linear-gradient(90deg, transparent 0%, var(--primary) 50%, transparent 100%);
  border-radius: 3px;
  animation: expandBar 0.45s var(--transition) both;
}
@keyframes expandBar {
  0%   { transform: scaleX(0); opacity: 0; }
  100% { transform: scaleX(1); opacity: 1; }
}
.category-tabs .tab:active {
  background: var(--border);
  opacity: 0.85;
}

/* ==================== 二级子分类（与一级同款 chip + 关联动画） ==================== */
.sub-category-wrap {
  background: #fff;
  overflow: hidden;
  max-height: 0;
  opacity: 0;
  transition: max-height 0.4s var(--transition), opacity 0.3s ease, padding 0.3s ease;
  padding: 0 16px;
}
.sub-category-wrap.show {
  max-height: 200px;
  opacity: 1;
  padding: 8px 16px 12px;
  border-bottom: 1px solid var(--border);
  background: linear-gradient(180deg, #FCF7F1 0%, #fff 100%);
}
.sub-category-tabs {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  align-items: center;
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: 18px;
  padding: 10px 12px;
  box-shadow: var(--shadow-sm);
  /* 关联动画：从上方滑下+淡入 */
  transform: translateY(-6px);
  opacity: 0;
  transition: transform 0.4s var(--transition), opacity 0.4s ease, box-shadow 0.3s ease;
}
.sub-category-wrap.show .sub-category-tabs {
  transform: translateY(0);
  opacity: 1;
}
/* 子分类 chip：与大分类完全同款（圆角矩形+边框） */
.sub-category-tabs .tab {
  white-space: nowrap;
  padding: 6px 14px;
  border-radius: 16px;
  font-size: 13px;
  background: var(--bg);
  color: var(--text-2);
  cursor: pointer;
  transition: background 0.2s, color 0.2s, opacity 0.2s, transform 0.2s;
  flex-shrink: 0;
  transform: none !important;
  border: 1px solid transparent;
  /* 错时入场动画 */
  opacity: 0;
  transform: translateY(4px);
}
.sub-category-wrap.show .sub-category-tabs .tab {
  animation: chipIn 0.35s var(--transition) both;
}
@keyframes chipIn {
  0%   { opacity: 0; transform: translateY(6px) scale(0.9); }
  60%  { opacity: 1; transform: translateY(0) scale(1.04); }
  100% { opacity: 1; transform: translateY(0) scale(1); }
}
.sub-category-tabs .tab.active {
  background: var(--primary);
  color: #fff;
  border-color: var(--primary);
  box-shadow: 0 2px 6px rgba(184,130,92,0.3);
  font-weight: 600;
}
.sub-category-tabs .tab:not(.active):hover {
  background: #fff;
  border-color: var(--primary);
  color: var(--primary);
}
.sub-category-tabs .tab:active {
  transform: scale(0.95) !important;
}
.sub-category-tabs .tab.manage-tab {
  background: transparent;
  color: var(--primary);
  border: 1px dashed var(--primary);
  margin-left: auto;
  opacity: 0.7;
}
.sub-category-tabs .tab.manage-tab:hover { opacity: 1; }

/* ==================== 公告栏 ==================== */
.notice-bar {
  background: #FFF8EE;
  border-bottom: 1px solid #F0DDB8;
  padding: 8px 16px;
  font-size: 13px;
  color: #9A7A4A;
  display: flex;
  align-items: center;
  gap: 6px;
  animation: fadeIn 0.4s;
}
.notice-bar .icon { animation: pulse 2s ease-in-out infinite; }

/* ==================== 商品列表 ==================== */
.product-list {
  padding: 10px;
  display: grid;
  /* minmax(0,1fr) 而不是裸 1fr：裸 1fr = minmax(auto,1fr)，下限取内容的 min-content，
     长商品名/大金额会把列顶宽、撑爆容器（页面能往右滑）。
     这里本来靠 .product-card{overflow:hidden} 侥幸没事，但别再依赖那个巧合。 */
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 10px;
}
.product-card {
  background: var(--card);
  border-radius: var(--radius);
  overflow: hidden;
  box-shadow: var(--shadow-sm);
  cursor: pointer;
  transition: all 0.3s var(--transition);
  animation: scaleIn 0.4s var(--transition) both;
}
.product-card:active {
  transform: scale(0.97);
  box-shadow: var(--shadow-md);
}
.product-card .img-box {
  width: 100%;
  aspect-ratio: 1;
  background: var(--bg);
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
  position: relative;
}
.product-card .img-box img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform 0.4s var(--transition);
}
.product-card:active .img-box img { transform: scale(1.08); }
.product-card .img-box .placeholder {
  font-size: 40px;
  transition: transform 0.3s;
}
.product-card:active .placeholder { transform: scale(1.1); }
.product-card .info {
  padding: 8px 10px;
}
.product-card .name {
  font-size: 13px;
  line-height: 1.4;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
  margin-bottom: 6px;
}
.product-card .spec {
  font-size: 11px;
  color: var(--text-3);
  margin-bottom: 4px;
}
.product-card .price {
  color: var(--danger);
  font-size: 16px;
  font-weight: 700;
}
.product-card .price .unit { font-size: 11px; font-weight: 400; }
/* 会员价标注（标价=批发价，会员价另标） */
.member-tag {
  display: block;
  margin-top: 2px;
  font-size: 11px;
  font-weight: 500;
  color: var(--primary);
  letter-spacing: 0.2px;
}

/* 秒杀价标注（2026-09-20）：规格商品选中了参与秒杀的规格时，
   主价格显示秒杀价，原来挂「会员价」的位置改挂这个标签，避免两个价并存造成误解 */
.tag-flash {
  display: inline-block;
  margin-top: 3px;
  padding: 1px 6px;
  font-size: 10.5px;
  font-weight: 600;
  line-height: 1.5;
  color: #fff;
  background: var(--danger);
  border-radius: 3px;
  letter-spacing: 0.3px;
}

/* P1-1: 库存状态徽章 */
.product-card .img-box .stock-out,
.product-card .img-box .stock-low {
  position: absolute;
  top: 6px;
  right: 6px;
  font-size: 11px;
  padding: 2px 6px;
  border-radius: 8px;
  font-weight: 600;
  color: #fff;
  z-index: 1;
}
.product-card .img-box .stock-out { background: rgba(0,0,0,0.65); }
.product-card .img-box .stock-low { background: rgba(250,173,20,0.9); }
.product-card.out-of-stock .img-box img { filter: grayscale(1) opacity(0.6); }
.product-card.out-of-stock .img-box .placeholder { opacity: 0.4; }

/* 商品卡片入场延迟 */
.product-card:nth-child(1) { animation-delay: 0.02s; }
.product-card:nth-child(2) { animation-delay: 0.06s; }
.product-card:nth-child(3) { animation-delay: 0.10s; }
.product-card:nth-child(4) { animation-delay: 0.14s; }
.product-card:nth-child(5) { animation-delay: 0.18s; }
.product-card:nth-child(6) { animation-delay: 0.22s; }
.product-card:nth-child(7) { animation-delay: 0.26s; }
.product-card:nth-child(8) { animation-delay: 0.30s; }
.product-card:nth-child(9) { animation-delay: 0.34s; }
.product-card:nth-child(10) { animation-delay: 0.38s; }

/* ==================== 加载更多 ==================== */
.load-more {
  text-align: center;
  padding: 16px;
  color: var(--text-3);
  font-size: 13px;
}
.load-more.loading { position: relative; }

/* ==================== 猜你喜欢（详情页推荐区，2026-09-11 重做） ====================
   改版原因（Marco 反馈）：原实现写成一行内联样式 grid-template-columns:repeat(3,1fr)，
   1fr 的实际含义是 minmax(auto,1fr)，而 auto 最小值取「内容的 min-content」。
   卡片里的商品名当时用了 white-space:nowrap —— min-content 就等于整行文字宽度，
   列被文字硬撑到 232/211/134px，整个网格 593px 塞进 342px 的容器里，
   于是页面能往右滑 227px。

   同时图片用了 img.cat-ph 的 height:100%，在网格项里会被解析成「整个行高」，
   图片吃掉卡片全部高度，下面的名称/价格被挤出卡片外，压到下一行的图片上
   —— 就是用户看到的「图片跟文字有干涉」。

    现在的三条防线（缺一不可）：
   ① 固定 2 列，且下限写死为 0（minmax(0,1fr)）—— 这是首页商品列表的同款排法。
      为什么不写 repeat(2,1fr)：1fr 的隐含下限是 auto（= 内容的 min-content），
      内容一宽列就跟着宽、整个网格就能撑爆容器；写死 0 下限后列宽只由容器决定。
      为什么不写 auto-fill minmax(150px,1fr)：320px 窄屏上会算成 1 列（272px 一张卡），很丑。
      为什么是 2 列不是 3 列：本店商品名普遍 12~22 个汉字，3 列每张卡只有 108px、
      名字只能看到 8 个字；2 列有 167px，名字基本能完整显示。
   ② 卡片 min-width:0 + 名称 overflow:hidden，内容再长也只能在轨道内截断
   ③ 图片放进固定 1:1 的 .rec-img 盒子里，图片只负责 cover，
      高度由盒子决定，不再反过来影响卡片高度
   ⚠️ 不要改回 repeat(3,1fr) 或 1fr 1fr，也不要把 nowrap 加回来。 */
.rec-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 10px 8px;
  min-width: 0;
}
.rec-card {
  min-width: 0;          /* 关键：否则网格项会被内容顶宽 */
  overflow: hidden;
  cursor: pointer;
  transition: transform 0.2s var(--transition);
}
.rec-card:active { transform: scale(0.96); }
.rec-img {
  width: 100%;
  aspect-ratio: 1;
  border-radius: 8px;
  overflow: hidden;
  background: var(--bg);
}
.rec-img img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}
.rec-name {
  font-size: 12px;
  line-height: 1.35;
  color: var(--text);
  margin-top: 5px;
  /* 两行截断，不再用 nowrap（nowrap 会把网格列顶宽） */
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
  word-break: break-all;
  /* 固定占满两行：否则短名字的卡片价格会比其他卡片高一截，整行看着不齐 */
  min-height: calc(1.35em * 2);
}
.rec-price {
  font-size: 14px;
  font-weight: 700;
  color: var(--danger);
  margin-top: 3px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.rec-price .unit { font-size: 11px; font-weight: 400; color: var(--text-3); }
/* 推荐卡片里的会员价标注（复用全局 .member-tag，只压小一号） */
.rec-card .member-tag {
  margin-top: 1px;
  font-size: 10.5px;
  line-height: 1.3;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* ==================== 商品详情 ==================== */
.detail-page { animation: fadeInUp 0.4s var(--transition) both; }
.detail-page .img-main {
  width: 100%;
  aspect-ratio: 1;
  background: var(--bg);
  display: flex;
  align-items: center;
  justify-content: center;
  animation: fadeIn 0.5s;
  position: relative;      /* 轮播的计数/指示点要绝对定位在这一层 */
  overflow: hidden;
}
.detail-page .img-main img { width: 100%; height: 100%; object-fit: cover; }
.detail-page .img-main .placeholder { font-size: 80px; animation: bounceIn 0.6s; }

/* ---------- 商品图册轮播（2026-09-16 新增：一个商品多张图） ----------
   Marco 要求「每个商品可上传多张图片，商品展示页轮播」。
   做法是横向 scroll-snap —— 手机上原生跟手，不用引任何轮播库；
   指示器只在多图时才有（JS 加 .is-gallery），单图完全退化成原来的样子。 */
.detail-page .img-swiper {
  display: flex;
  width: 100%;
  height: 100%;
  overflow-x: auto;
  overflow-y: hidden;
  scroll-snap-type: x mandatory;
  -webkit-overflow-scrolling: touch;
  overscroll-behavior-x: contain;
  scrollbar-width: none;
}
.detail-page .img-swiper::-webkit-scrollbar { display: none; }
.detail-page .img-slide {
  flex: 0 0 100%;
  width: 100%;
  height: 100%;
  scroll-snap-align: start;
  scroll-snap-stop: always;
}
.detail-page .img-slide img { width: 100%; height: 100%; object-fit: cover; display: block; }

/* 右下角计数（1/5） */
.detail-page .img-counter {
  position: absolute;
  right: 12px;
  bottom: 12px;
  padding: 3px 10px;
  border-radius: 20px;
  background: rgba(74,59,50,0.42);
  color: #fff;
  font-size: 12px;
  line-height: 1.5;
  letter-spacing: 0.5px;
  backdrop-filter: blur(4px);
  -webkit-backdrop-filter: blur(4px);
  pointer-events: none;
}
/* 底部居中指示点：当前点拉长成小胶囊 */
.detail-page .img-dots {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 15px;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
}
.detail-page .img-dots i {
  display: block;
  width: 6px;
  height: 6px;
  border-radius: 3px;
  background: rgba(255,255,255,0.62);
  box-shadow: 0 0 3px rgba(74,59,50,0.35);
  transition: width 0.25s var(--transition), background 0.25s var(--transition);
}
.detail-page .img-dots i.on { width: 16px; background: #fff; }

/* ---------- 全屏看图（点详情页主图触发） ---------- */
.img-viewer {
  position: fixed;
  top: 0; right: 0; bottom: 0; left: 0;
  z-index: 9998;
  background: #000;
  animation: fadeIn 0.22s var(--transition);
}
.img-viewer-track {
  display: flex;
  width: 100%;
  height: 100%;
  overflow-x: auto;
  overflow-y: hidden;
  scroll-snap-type: x mandatory;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: none;
}
.img-viewer-track::-webkit-scrollbar { display: none; }
.img-viewer-slide {
  flex: 0 0 100%;
  width: 100%;
  height: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  scroll-snap-align: start;
}
.img-viewer-slide img { max-width: 100%; max-height: 100%; object-fit: contain; }
.img-viewer-counter {
  position: absolute;
  left: 50%;
  bottom: 28px;
  transform: translateX(-50%);
  padding: 4px 14px;
  border-radius: 20px;
  background: rgba(255,255,255,0.16);
  color: #fff;
  font-size: 13px;
  letter-spacing: 1px;
  pointer-events: none;
}
.img-viewer-close {
  position: absolute;
  right: 14px;
  top: 14px;
  width: 34px;
  height: 34px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(255,255,255,0.16);
  color: #fff;
  cursor: pointer;
  transition: background 0.2s;
}
.img-viewer-close svg { width: 17px; height: 17px; }
.img-viewer-close:active { background: rgba(255,255,255,0.34); }

.detail-page .price-box {
  background: #fff;
  padding: 16px;
  animation: fadeInUp 0.4s 0.1s both;
}
.detail-page .price-box .price {
  color: var(--danger);
  font-size: 28px;
  font-weight: 700;
}
.detail-page .price-box .price .symbol { font-size: 16px; }
/* 主价格上方的小标签（2026-09-12：主价格由「零售价」改为「批发价」）。
   没有这个标签，顾客看到一个数字也不知道是哪一档价。 */
.detail-page .price-box .price-label {
  font-size: 12px;
  color: var(--text-3);
  margin-bottom: 2px;
  letter-spacing: 0.5px;
}
.detail-page .info-box {
  background: #fff;
  padding: 16px;
  margin-top: 10px;
  animation: fadeInUp 0.4s 0.2s both;
}
.detail-page .info-box h2 {
  font-size: 17px;
  line-height: 1.5;
  margin-bottom: 10px;
}
.detail-page .info-box .row {
  display: flex;
  justify-content: space-between;
  padding: 6px 0;
  font-size: 14px;
  border-bottom: 1px solid var(--border);
}
.detail-page .info-box .row .label { color: var(--text-3); }

/* ==================== 底部操作栏 ==================== */
.bottom-bar {
  position: fixed;
  bottom: 0;
  left: 50%;
  transform: translateX(-50%);
  width: 100%;
  max-width: 480px;
  background: #fff;
  border-top: 1px solid var(--border);
  display: flex;
  padding: 8px 12px;
  gap: 8px;
  z-index: 100;
  /* 用带居中的关键帧，不要换回 fadeInUp（动画会吃掉 translateX(-50%)，整条栏会先偏右半个屏） */
  animation: bottomBarIn 0.32s var(--transition) both;
  box-shadow: 0 -2px 10px rgba(0,0,0,0.05);
}
.bottom-bar .btn-cart,
.bottom-bar .btn-buy {
  flex: 1;
  border: none;
  border-radius: 22px;
  padding: 12px 0;
  font-size: 15px;
  font-weight: 600;
  cursor: pointer;
  transition: all 0.2s var(--transition);
  position: relative;
  overflow: hidden;
}
.bottom-bar .btn-cart {
  background: var(--grad-cart);
  color: #fff;
  box-shadow: 0 2px 8px rgba(217,168,92,0.3);
}
.bottom-bar .btn-buy {
  background: var(--grad-buy);
  color: #fff;
  box-shadow: 0 2px 8px rgba(217,107,90,0.3);
}
.bottom-bar .btn-cart:active,
.bottom-bar .btn-buy:active {
  transform: scale(0.96);
  box-shadow: 0 1px 4px rgba(0,0,0,0.2);
}

/* 涟漪效果 */
.ripple {
  position: absolute;
  border-radius: 50%;
  background: rgba(255,255,255,0.5);
  transform: scale(0);
  animation: ripple 0.6s ease-out;
  pointer-events: none;
}

/* ==================== 购物车（2026-09-12 淘宝风格改版） ====================
   改动前：一列「勾选框 + 小图 + 名称 + 价格 + 步进器」，信息密度低、很像半成品。
   改动后：店铺行 + 卡片式商品行（规格/会员价/标签）+ 失效分区 + 为你推荐 + 底部结算栏。
   保持不变的锚点：.cart-footer 仍用 bottomBarIn（靠 transform 居中，动画不能吃掉它）、
   #checkAll 与 .cart-del 仍存在、item.qty <= 1 仍禁用「-」。
   ⚠️ 新增样式一律不用裸 1fr（用 minmax(0,1fr)），也不给全宽块加 scale>1 动画 —— 会横向溢出。 */
.cart-page { animation: fadeInUp 0.4s var(--transition) both; padding-bottom: 10px; }

/* 导航栏里的「编辑 / 完成」 */
.nav-back-link { color: #fff; font-size: 14px; display: flex; align-items: center; gap: 3px; }
.nav-back-link:active { opacity: 0.7; }
.nav-edit-btn {
  border: 1px solid rgba(255,255,255,0.55);
  background: rgba(255,255,255,0.14);
  color: #fff;
  font-size: 13px;
  font-family: inherit;
  padding: 4px 13px;
  border-radius: 14px;
  cursor: pointer;
  transition: background 0.2s var(--transition), transform 0.2s var(--transition);
}
.nav-edit-btn:active { background: rgba(255,255,255,0.3); transform: scale(0.94); }

/* ---- 店铺行 ---- */
.tb-shop {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 11px 14px;
  background: #fff;
  border-bottom: 1px solid var(--border);
  animation: fadeInUp 0.3s var(--transition) both;
}
.tb-shop-name { display: flex; align-items: center; gap: 5px; font-size: 14px; flex: 1; min-width: 0; }
.tb-shop-name b { font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.tb-shop-tag {
  flex-shrink: 0;
  font-size: 11px;
  color: var(--primary);
  background: var(--primary-light);
  border-radius: 4px;
  padding: 2px 7px;
}

/* ---- 通用勾选框（淘宝用暖红，比主题棕更醒目）---- */
.tb-checkbox { display: flex; align-items: center; justify-content: center; flex-shrink: 0; padding: 2px; }
.tb-checkbox input {
  width: 19px; height: 19px; margin: 0;
  cursor: pointer;
  accent-color: var(--danger);
}
.tb-checkbox input:disabled { opacity: 0.3; cursor: not-allowed; }

/* ---- 商品卡 ---- */
.tb-item {
  position: relative;
  overflow: hidden;
  background: #fff;
  border-bottom: 1px solid var(--border);
  animation: fadeInUp 0.3s var(--transition) both;
}
/* 左滑露出的删除层（在卡片主体下层） */
.tb-item-del {
  position: absolute;
  top: 0; right: 0; bottom: 0;
  width: 76px;
  border: none;
  background: var(--danger);
  color: #fff;
  font-size: 14px;
  font-family: inherit;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
}
/* 卡片主体：白底盖住删除层，左滑时位移露出 */
.tb-item-main {
  position: relative;
  z-index: 1;
  background: #fff;
  display: flex;
  align-items: flex-start;
  gap: 10px;
  padding: 12px 14px;
  transition: transform 0.25s var(--transition);
}
.tb-thumb {
  width: 76px; height: 76px;
  flex-shrink: 0;
  border-radius: 8px;
  background: var(--bg);
  overflow: hidden;
  display: flex; align-items: center; justify-content: center;
}
.tb-thumb img { width: 100%; height: 100%; object-fit: cover; }

.tb-detail { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 4px; }
.tb-name {
  font-size: 14px;
  line-height: 1.35;
  color: var(--text);
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.tb-spec {
  font-size: 12px;
  color: var(--text-3);
  background: var(--bg);
  border-radius: 4px;
  padding: 2px 6px;
  align-self: flex-start;
  max-width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.tb-badges { display: flex; flex-wrap: wrap; gap: 4px; }
.tb-badge { font-size: 11px; padding: 1px 6px; border-radius: 3px; line-height: 1.5; }
.tb-badge-flash { color: var(--danger); background: #FBF0EE; }
.tb-badge-gray { color: var(--text-3); background: var(--bg); }
.tb-badge-warn { color: #A9761B; background: #FDF6E3; }

.tb-bottom {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 8px;
  margin-top: 2px;
}
.tb-price { display: flex; flex-direction: column; gap: 1px; min-width: 0; }
.tb-now { color: var(--danger); font-size: 17px; font-weight: 700; line-height: 1.15; }
.tb-now-gray { color: var(--text-3); font-weight: 500; font-size: 15px; }
.tb-mp { font-size: 11px; color: var(--primary); }

/* 步进器 */
.tb-step {
  display: flex;
  align-items: center;
  flex-shrink: 0;
  border: 1px solid var(--border);
  border-radius: 6px;
  overflow: hidden;
}
.tb-step button {
  width: 28px; height: 26px;
  border: none; background: #fff;
  font-size: 15px; line-height: 1;
  color: var(--text);
  cursor: pointer;
  font-family: inherit;
}
.tb-step button:active { background: var(--primary-light); }
.tb-step button:disabled { opacity: 0.3; cursor: not-allowed; }
.tb-step span { min-width: 30px; text-align: center; font-size: 13px; }

/* ---- 失效商品分区 ---- */
.tb-item.is-invalid .tb-item-main { opacity: 0.62; }
.tb-invalid-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 11px 14px 7px;
  font-size: 13px;
  color: var(--text-2);
  background: var(--bg);
  border-bottom: 1px solid var(--border);
}
.tb-invalid-title { display: flex; align-items: center; gap: 5px; }
.tb-invalid-title em { font-style: normal; color: var(--text-3); font-size: 12px; }
.tb-invalid-clear {
  border: 1px solid var(--border);
  background: #fff;
  color: var(--text-2);
  font-size: 12px;
  padding: 3px 10px;
  border-radius: 12px;
  cursor: pointer;
  font-family: inherit;
}
.tb-invalid-clear:active { background: var(--primary-light); }

/* ---- 为你推荐 ---- */
.tb-rec { margin-top: 12px; background: #fff; padding: 12px 0 10px; border-top: 1px solid var(--border); }
.tb-rec-head { display: flex; align-items: center; gap: 5px; font-size: 14px; font-weight: 600; padding: 0 14px 10px; }
.tb-rec-grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 8px;
  padding: 0 14px;
}
.tb-rec-card { display: block; text-decoration: none; color: inherit; }
.tb-rec-card:active { opacity: 0.75; }
.tb-rec-thumb {
  width: 100%;
  aspect-ratio: 1 / 1;
  border-radius: 8px;
  background: var(--bg);
  overflow: hidden;
  display: flex; align-items: center; justify-content: center;
}
.tb-rec-thumb img { width: 100%; height: 100%; object-fit: cover; }
.tb-rec-name {
  font-size: 12px;
  line-height: 1.35;
  margin-top: 6px;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.tb-rec-price { color: var(--danger); font-size: 13px; font-weight: 600; margin-top: 2px; }

/* ---- 底部结算栏 ---- */
.cart-footer {
  position: fixed;
  bottom: 0;
  left: 50%;
  transform: translateX(-50%);
  width: 100%;
  max-width: 480px;
  background: #fff;
  border-top: 1px solid var(--border);
  padding: 10px 14px;
  display: flex;
  align-items: center;
  gap: 10px;
  /* 同上：不能用 fadeInUp，必须用把 translateX(-50%) 写进去的关键帧 */
  animation: bottomBarIn 0.32s var(--transition) both;
  box-shadow: 0 -2px 10px rgba(0,0,0,0.05);
}
.cf-all { display: flex; align-items: center; gap: 6px; font-size: 14px; cursor: pointer; flex-shrink: 0; }
.cf-all input { width: 19px; height: 19px; margin: 0; accent-color: var(--danger); cursor: pointer; }
.cf-right { flex: 1; min-width: 0; display: flex; align-items: center; justify-content: flex-end; gap: 10px; }
.cf-amount { min-width: 0; text-align: right; }
.cf-total { font-size: 13px; color: var(--text-2); }
.cf-total .price { color: var(--danger); font-weight: 700; font-size: 18px; }
.cf-sub { font-size: 11px; color: var(--text-3); margin-top: 1px; }
.cf-sub-good { color: var(--primary); }
.cart-footer .checkout-btn {
  background: var(--grad-buy);
  color: #fff;
  border: none;
  border-radius: 22px;
  padding: 10px 24px;
  font-size: 15px;
  font-weight: 600;
  font-family: inherit;
  cursor: pointer;
  flex-shrink: 0;
  transition: all 0.2s var(--transition);
  box-shadow: 0 2px 8px rgba(217,107,90,0.3);
}
.cart-footer .checkout-btn:active { transform: scale(0.96); }
.cart-footer .checkout-btn:disabled { opacity: 0.5; box-shadow: none; cursor: not-allowed; }
.cart-footer .cf-danger { background: var(--danger); }
.cf-sec-btn {
  border: 1px solid var(--border);
  background: #fff;
  color: var(--text);
  font-size: 14px;
  padding: 9px 16px;
  border-radius: 22px;
  font-family: inherit;
  cursor: pointer;
  flex-shrink: 0;
}
.cf-sec-btn:active { background: var(--primary-light); }

/* ==================== 下单页 ==================== */
.checkout-page { animation: fadeInUp 0.4s var(--transition) both; }
.checkout-page .section {
  background: #fff;
  margin: 10px;
  border-radius: var(--radius);
  padding: 14px;
  box-shadow: var(--shadow-sm);
  animation: fadeInUp 0.4s var(--transition) both;
}
.checkout-page .section:nth-child(2) { animation-delay: 0.1s; }
.checkout-page .section:nth-child(3) { animation-delay: 0.2s; }
.checkout-page .section h3 {
  font-size: 15px;
  margin-bottom: 10px;
  padding-bottom: 8px;
  border-bottom: 1px solid var(--border);
}
.checkout-page .form-row {
  display: flex;
  align-items: center;
  padding: 8px 0;
}
.checkout-page .form-row label {
  width: 80px;
  font-size: 14px;
  color: var(--text-2);
}
.checkout-page .form-row input {
  flex: 1;
  border: none;
  border-bottom: 1px solid var(--border);
  padding: 6px 0;
  font-size: 14px;
  outline: none;
  transition: border-color 0.3s;
}
.checkout-page .form-row input:focus { border-bottom-color: var(--primary); }
.checkout-page .order-item {
  display: flex;
  gap: 8px;
  padding: 8px 0;
  border-bottom: 1px solid var(--border);
}
.checkout-page .order-item:last-child { border: none; }
.checkout-page .order-item .name { flex: 1; font-size: 13px; }
.checkout-page .order-item .qty { font-size: 13px; color: var(--text-3); }
.checkout-page .order-item .price { color: var(--danger); font-size: 13px; }

.pay-methods { display: flex; gap: 10px; }
.pay-method {
  flex: 1;
  border: 2px solid var(--border);
  border-radius: var(--radius);
  padding: 10px;
  text-align: center;
  cursor: pointer;
  font-size: 13px;
  transition: all 0.3s var(--transition-bounce);
}
.pay-method.active {
  border-color: var(--primary);
  background: var(--primary-light);
  color: var(--primary);
  transform: scale(1.03);
}
.pay-method:active { transform: scale(0.97); }

/* ==================== 订单列表 ==================== */
.order-card {
  background: #fff;
  margin: 8px 10px;
  border-radius: var(--radius);
  padding: 12px;
  box-shadow: var(--shadow-sm);
  animation: slideInRight 0.3s var(--transition) both;
}
.order-card .header {
  display: flex;
  justify-content: space-between;
  font-size: 13px;
  color: var(--text-3);
  margin-bottom: 8px;
  padding-bottom: 8px;
  border-bottom: 1px solid var(--border);
}
.order-card .status-tag {
  padding: 2px 8px;
  border-radius: 4px;
  font-size: 12px;
}
.status-pending { background: #FFF8EE; color: var(--warning); }
.status-paid { background: #F8F0E8; color: var(--primary); }
.status-shipped { background: #F0F6F0; color: var(--success); }
.status-completed { background: #F5F2EF; color: #A89B92; }
.status-cancelled { background: #FBF0EE; color: var(--danger); }

/* ==================== 登录页 ==================== */
.login-page {
  background: linear-gradient(180deg, var(--primary-light) 0%, var(--bg) 40%);
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  align-items: center;
  padding-top: 80px;
}
.login-page .logo {
  font-size: 28px;
  font-weight: 700;
  color: var(--primary);
  margin-bottom: 6px;
  animation: bounceIn 0.6s var(--transition-bounce);
  text-align: center;
}
.login-page .logo-sub {
  font-size: 12px;
  color: var(--text-3);
  letter-spacing: 2px;
  margin-bottom: 28px;
  animation: fadeIn 0.6s 0.2s both;
}
.login-page .form-box {
  width: 85%;
  max-width: 360px;
  animation: scaleIn 0.5s 0.1s both;
}
.login-page .form-box input {
  width: 100%;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 12px 14px;
  font-size: 15px;
  margin-bottom: 12px;
  outline: none;
  transition: all 0.3s var(--transition);
  background: #fff;
}
.login-page .form-box input:focus {
  border-color: var(--primary);
  box-shadow: 0 0 0 3px var(--primary-light);
}
.login-page .form-box button {
  width: 100%;
  background: var(--grad-primary);
  color: #fff;
  border: none;
  border-radius: var(--radius);
  padding: 13px;
  font-size: 16px;
  font-weight: 600;
  cursor: pointer;
  transition: all 0.3s var(--transition);
  box-shadow: 0 3px 12px rgba(184,130,92,0.3);
}
.login-page .form-box button:active {
  transform: scale(0.97);
  box-shadow: 0 1px 6px rgba(184,130,92,0.2);
}
.login-page .toggle-text {
  text-align: center;
  margin-top: 16px;
  font-size: 14px;
  color: var(--text-2);
  animation: fadeIn 0.5s 0.3s both;
}
.login-page .toggle-text a { color: var(--primary); font-weight: 500; }
.login-page .seller-tip {
  margin-top: 30px;
  padding: 12px 16px;
  background: rgba(255,255,255,0.8);
  border-radius: var(--radius);
  font-size: 13px;
  color: var(--text-2);
  text-align: center;
  width: 85%;
  max-width: 360px;
  animation: fadeIn 0.5s 0.4s both;
  border: 1px solid var(--border);
}

/* 微信登录按钮 */
.wechat-login-btn {
  width: 100%;
  background: #07c160 !important;
  border: none;
  border-radius: var(--radius);
  padding: 13px;
  font-size: 15px;
  font-weight: 600;
  color: #fff;
  cursor: pointer;
  transition: all 0.3s var(--transition);
  margin-top: 12px;
  box-shadow: 0 3px 10px rgba(7,193,96,0.25);
}
.wechat-login-btn:active { transform: scale(0.97); }
.divider {
  display: flex;
  align-items: center;
  margin: 20px 0;
  animation: fadeIn 0.3s both;
}
.divider::before, .divider::after {
  content: '';
  flex: 1;
  height: 1px;
  background: var(--border);
}
.divider span {
  padding: 0 16px;
  font-size: 12px;
  color: var(--text-3);
}

/* ==================== 卖家端通用 ==================== */
.seller-page { background: var(--bg); min-height: 100vh; }
.seller-navbar {
  background: var(--grad-seller);
  color: #fff;
  padding: 14px 16px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  position: sticky; top: 0; z-index: 100;
  box-shadow: 0 2px 10px rgba(74,59,50,0.2);
}
.seller-navbar h1 { font-size: 16px; }
.seller-navbar a { color: #fff; font-size: 13px; transition: opacity 0.2s; }
.seller-navbar a:active { opacity: 0.7; }

/* 注：.stat-grid / .stat-card 目前全站没有页面在用（疑似死 CSS，2026-09-11 核实）。
   一并按 minmax(0,1fr) 加固，避免以后有人重新启用时踩到「数字顶宽」的坑。 */
.stat-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 10px;
  padding: 12px;
}
.stat-card {
  min-width: 0;
  overflow: hidden;
  background: #fff;
  border-radius: var(--radius-lg);
  padding: 16px;
  text-align: center;
  box-shadow: var(--shadow-sm);
  transition: all 0.3s var(--transition);
  animation: scaleIn 0.4s var(--transition) both;
}
.stat-card:nth-child(1) { animation-delay: 0.05s; }
.stat-card:nth-child(2) { animation-delay: 0.10s; }
.stat-card:nth-child(3) { animation-delay: 0.15s; }
.stat-card:nth-child(4) { animation-delay: 0.20s; }
.stat-card:active { transform: scale(0.97); }
.stat-card .num { font-size: 26px; font-weight: 700; }
.stat-card .label { font-size: 13px; color: var(--text-3); margin-top: 4px; }
.stat-card .num.blue { color: var(--primary); }
.stat-card .num.green { color: var(--success); }
.stat-card .num.orange { color: var(--warning); }
.stat-card .num.red { color: var(--danger); }

.seller-table {
  width: 100%;
  background: #fff;
  margin: 8px 0;
}
.seller-table th, .seller-table td {
  padding: 8px 6px;
  text-align: left;
  font-size: 12px;
  border-bottom: 1px solid var(--border);
}
.seller-table th { background: var(--bg); font-weight: 600; }

/* ==================== 按钮 ==================== */
.btn {
  display: inline-block;
  padding: 6px 12px;
  border-radius: 6px;
  font-size: 13px;
  border: none;
  cursor: pointer;
  transition: all 0.2s var(--transition);
  position: relative;
  overflow: hidden;
}
.btn:active { transform: scale(0.96); }
.btn-primary { background: var(--primary); color: #fff; }
.btn-primary:active { background: var(--primary-dark); }
.btn-danger { background: var(--danger); color: #fff; }
.btn-success { background: var(--success); color: #fff; }
.btn-warning { background: var(--warning); color: #fff; }
.btn-outline { background: #fff; border: 1px solid var(--border); color: var(--text-2); }
.btn-outline:active { background: var(--bg); }
.btn-sm { padding: 4px 8px; font-size: 12px; }
.btn-lg { padding: 13px; font-size: 16px; width: 100%; border-radius: var(--radius); font-weight: 600; }

/* ==================== 表单 ==================== */
.form-group { margin-bottom: 14px; }
.form-group label { display: block; font-size: 14px; color: var(--text-2); margin-bottom: 4px; }
.form-group input, .form-group select, .form-group textarea {
  width: 100%;
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 10px 12px;
  font-size: 14px;
  outline: none;
  transition: all 0.3s var(--transition);
  background: #fff;
}
.form-group input:focus, .form-group select:focus, .form-group textarea:focus {
  border-color: var(--primary);
  box-shadow: 0 0 0 3px var(--primary-light);
}
.form-actions { padding: 16px; }
.form-actions button { width: 100%; }

/* 设置区块 */
.settings-section {
  background: #fff;
  margin: 10px;
  border-radius: var(--radius-lg);
  padding: 16px;
  box-shadow: var(--shadow-sm);
  animation: fadeInUp 0.4s var(--transition) both;
}
.settings-section h3 {
  font-size: 15px;
  margin-bottom: 14px;
  display: flex;
  align-items: center;
  gap: 6px;
}

/* 微信绑定状态 */
.wechat-bound {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 12px;
  background: #F0F6F0;
  border-radius: 10px;
  border: 1px solid #D4E8D4;
}
.wechat-bound .wx-avatar {
  width: 40px; height: 40px;
  border-radius: 50%;
  background: #07c160;
  color: #fff;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 18px;
}
.wechat-bound .wx-info { flex: 1; }
.wechat-bound .wx-info .name { font-size: 14px; font-weight: 500; }
.wechat-bound .wx-info .status { font-size: 12px; color: #07c160; }

.wechat-unbound {
  text-align: center;
  padding: 16px;
  color: var(--text-3);
  font-size: 13px;
}

/* 模态框 */
.modal-overlay {
  position: fixed;
  inset: 0;
  background: rgba(0,0,0,0.5);
  z-index: 9990;
  display: flex;
  align-items: center;
  justify-content: center;
  animation: fadeIn 0.2s;
}
.modal-box {
  background: #fff;
  border-radius: var(--radius-lg);
  width: 90%;
  max-width: 340px;
  padding: 24px 20px;
  animation: bounceIn 0.4s var(--transition-bounce);
}
.modal-box h3 { text-align: center; font-size: 17px; margin-bottom: 16px; }
.modal-box .modal-actions {
  display: flex;
  gap: 10px;
  margin-top: 20px;
}
.modal-box .modal-actions button {
  flex: 1;
  padding: 11px;
  border: none;
  border-radius: 8px;
  font-size: 15px;
  cursor: pointer;
  transition: all 0.2s var(--transition);
  font-family: inherit; /* button 默认不继承字体，不写会掉到系统 UI 字体 */
}
.modal-box .modal-actions .btn-cancel {
  background: var(--bg);
  color: var(--text-2);
}
.modal-box .modal-actions .btn-cancel:active { background: var(--border); }
.modal-box .modal-actions .btn-confirm {
  background: var(--primary);
  color: #fff;
}
.modal-box .modal-actions .btn-confirm:active { background: var(--primary-dark); }
/* 危险操作（删除类）确认按钮 */
.modal-box .modal-actions .btn-danger {
  background: var(--danger);
  color: #fff;
}
.modal-box .modal-actions .btn-danger:active { background: var(--danger-dark); }

/* ==================== 站内确认/输入弹层（js/dialog.js，替代原生 confirm/prompt） ==================== */
.app-dlg .app-dlg-msg {
  font-size: 14px;
  color: var(--text-2);
  line-height: 1.7;
  white-space: pre-wrap;   /* 保留消息里的换行（原来 confirm 靠 \n 换行） */
  word-break: break-word;
  text-align: center;
}
.app-dlg .app-dlg-input {
  width: 100%;
  box-sizing: border-box;
  margin-top: 14px;
  padding: 11px 12px;
  border: 1px solid var(--border);
  border-radius: 9px;
  font-size: 15px;
  font-family: inherit;
  background: var(--primary-lighter);
  color: var(--text);
}
.app-dlg .app-dlg-input:focus {
  outline: none;
  border-color: var(--primary);
  background: #fff;
}
.app-dlg textarea.app-dlg-input {
  min-height: 84px;
  resize: vertical;
  line-height: 1.6;
}

/* ==================== Toast ==================== */
.toast {
  position: fixed;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  background: rgba(0,0,0,0.8);
  color: #fff;
  padding: 12px 24px;
  border-radius: 10px;
  font-size: 14px;
  z-index: 9999;
  pointer-events: none;
  opacity: 0;
  transition: opacity 0.3s, transform 0.3s var(--transition-bounce);
  max-width: 80%;
  text-align: center;
}
.toast.show {
  opacity: 1;
  animation: toastSlide 0.4s var(--transition-bounce);
}

/* ==================== 空状态 ==================== */
.empty {
  text-align: center;
  padding: 60px 20px;
  color: var(--text-3);
  animation: fadeIn 0.5s;
}
/* ⚠️ 为什么必须 width:fit-content（2026-09-11 血泪）：
   .icon 是 <div>（块元素），默认撑满整行。空状态页面常写 .empty{padding:40px 0}，
   横向 padding 为 0 → .icon 宽 = 视口宽（320px）。此时再挂 pulse（scale 到 1.05）
   → 放大成 336px 并居中，左右各溢出 8px，而且 2s 无限循环，页面**一直**能往右滑。
   让它收缩到内容宽度（48px 图标）后，scale(1.05) 只有 50px，怎么放都不会溢出。
   实测：修前 div.icon right=328.46（视口 320），修后不再越界。 */
.empty .icon {
  font-size: 50px;
  width: fit-content;          /* 不能是撑满整行的块元素 */
  margin: 0 auto 10px;         /* 居中 + 保住原来的下间距 */
  animation: pulse 2s ease-in-out infinite;
}
.empty .text { font-size: 14px; }

/* ==================== 排序栏 ==================== */
.sort-bar {
  display: flex;
  gap: 12px;
  padding: 6px 16px;
  background: #fff;
  border-bottom: 1px solid var(--border);
  font-size: 12.5px;   /* 2026-09-18：13→12.5px，配合顶栏瘦身一起给商品腾地方 */
}
.sort-bar .sort-item { color: var(--text-2); cursor: pointer; transition: all 0.2s; }
.sort-bar .sort-item.active { color: var(--primary); font-weight: 600; }
.sort-bar .sort-item:active { opacity: 0.6; }

/* ==================== 列表项 ==================== */
.list-item {
  background: #fff;
  padding: 12px 16px;
  display: flex;
  align-items: center;
  gap: 10px;
  border-bottom: 1px solid var(--border);
  cursor: pointer;
  transition: background 0.2s;
  animation: fadeInUp 0.3s var(--transition) both;
}
.list-item:active { background: var(--bg); }
.list-item .icon { font-size: 20px; }
.list-item .text { flex: 1; font-size: 14px; }
.list-item .arrow { color: var(--text-3); font-size: 14px; }

/* ==================== 标签 ==================== */
.badge {
  display: inline-block;
  padding: 2px 8px;
  border-radius: 10px;
  font-size: 11px;
  font-weight: 500;
}
.badge-green { background: #F0F6F0; color: var(--success); }
.badge-blue { background: var(--primary-light); color: var(--primary); }
.badge-gray { background: #F5F2EF; color: var(--text-3); }

/* ==================== 摇晃错误提示 ==================== */
.shake { animation: shake 0.4s; }

/* ==================== 页面切换淡入 ==================== */
.fade-transition {
  animation: fadeIn 0.3s var(--transition);
}

/* ==================== 输入框聚焦动画 ==================== */
input:focus, select:focus, textarea:focus {
  transition: all 0.3s var(--transition);
}

/* ==================== 滚动平滑 ==================== */
/* body 限宽 480px 居中；html 必须也给个底色，否则桌面浏览器两侧露出纯白，
   中间一条米色，像没铺满 */
html { scroll-behavior: smooth; background: var(--bg-outer); }

/* ==================== 卖家编辑按钮 ==================== */
.product-card .seller-edit-btn {
  display: block;
  width: 100%;
  border: none;
  border-top: 1px solid var(--border);
  background: var(--primary-light);
  color: var(--primary);
  font-size: 12px;
  font-weight: 600;
  padding: 7px 0;
  cursor: pointer;
  transition: all 0.2s var(--transition);
  position: relative;
  overflow: hidden;
}
.product-card .seller-edit-btn:active {
  background: var(--primary-light);
  transform: scale(0.97);
}

/* ==================== 商品编辑模态框 ==================== */
.edit-modal-box {
  background: #fff;
  border-radius: 14px;
  width: 94%;
  max-width: 420px;
  margin: 20px auto;
  box-shadow: 0 8px 40px rgba(0,0,0,0.2);
  animation: bounceIn 0.35s var(--transition-bounce);
  overflow: hidden;
}
.edit-modal-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 14px 18px;
  background: var(--grad-primary);
  color: #fff;
}
.edit-modal-header h3 { font-size: 16px; font-weight: 600; }
.edit-modal-close {
  font-size: 18px;
  cursor: pointer;
  opacity: 0.8;
  transition: opacity 0.2s;
  padding: 4px 8px;
}
.edit-modal-close:active { opacity: 1; }

.edit-modal-body {
  padding: 16px 18px;
  max-height: 60vh;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
}

/* 商品图册（2026-09-16 由单图改为多图）
   替代原来的 .edit-img-preview（100×100 单张预览）。
   9 张图按 3 列排布，每格自带「封面」角标、删除和左右移位。 */
.edit-img-section { margin-bottom: 16px; }
.edit-img-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  font-size: 14px;
  font-weight: 600;
  color: var(--text-2);
  margin: 0 0 10px;
  padding-top: 12px;
  border-top: 1px solid var(--border);
}
.edit-img-head svg { margin-right: 4px; }
.edit-img-count {
  font-size: 12px;
  font-weight: 500;
  color: var(--text-3);
  background: var(--bg);
  padding: 2px 8px;
  border-radius: 20px;
}
.edit-img-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(82px, 1fr));
  gap: 8px;
}
.edit-img-cell {
  position: relative;
  aspect-ratio: 1;
  border-radius: var(--radius);
  overflow: hidden;
  background: var(--bg);
  border: 1px solid var(--border);
  cursor: pointer;
  transition: box-shadow 0.2s var(--transition), transform 0.15s var(--transition);
}
.edit-img-cell:active { transform: scale(0.97); }
.edit-img-cell img { width: 100%; height: 100%; object-fit: cover; display: block; }
/* 封面格：主色描边，一眼能认出来 */
.edit-img-cell.is-cover {
  border-color: var(--primary);
  box-shadow: 0 0 0 2px var(--primary-light);
}
.edit-img-badge {
  position: absolute;
  left: 0;
  top: 0;
  z-index: 2;
  font-size: 10px;
  line-height: 1;
  padding: 4px 6px;
  color: #fff;
  background: var(--primary);
  border-bottom-right-radius: 8px;
  letter-spacing: 0.5px;
}
.edit-img-badge.is-no {
  background: rgba(74,59,50,0.5);
  min-width: 17px;
  text-align: center;
  padding: 4px 0;
  font-weight: 600;
}
.edit-img-del {
  position: absolute;
  right: 3px;
  top: 3px;
  z-index: 2;
  width: 20px;
  height: 20px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(74,59,50,0.5);
  color: #fff;
  transition: background 0.2s;
}
.edit-img-del svg { width: 11px; height: 11px; }
.edit-img-del:active { background: var(--danger); }
.edit-img-tools {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 2;
  display: flex;
  justify-content: space-between;
  padding: 10px 4px 3px;
  background: linear-gradient(to top, rgba(74,59,50,0.6), rgba(74,59,50,0));
}
.edit-img-tools span {
  width: 20px;
  height: 20px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  color: #fff;
  background: rgba(255,255,255,0.22);
  transition: background 0.2s, opacity 0.2s;
}
.edit-img-tools span svg { width: 12px; height: 12px; }
.edit-img-tools span:active { background: var(--primary); }
.edit-img-tools span.is-off { opacity: 0; pointer-events: none; }
.edit-img-cell.is-add {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 3px;
  border-style: dashed;
  border-color: var(--primary);
  background: var(--primary-lighter);
  color: var(--primary);
}
.edit-img-plus { font-size: 22px; line-height: 1; font-weight: 300; }
.edit-img-add-text { font-size: 11px; }
.edit-img-cell.is-loading {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 5px;
  cursor: default;
  border-style: dashed;
}
.edit-img-loading-tip { font-size: 10px; color: var(--text-3); }
.edit-img-tip { font-size: 12px; color: var(--text-3); margin-top: 8px; text-align: center; }

/* 图册上传失败提示（2026-09-22 新增）
   原来失败只有一句 2 秒的 toast，用户注意力在系统文件框上，看不到 →
   表现为「选了图没反应」。这里做成常驻的一块，逐张说明原因。 */
.edit-img-err {
  margin-top: 10px;
  padding: 10px 12px;
  background: #FDF3F0;
  border: 1px solid #F0C9BE;
  border-left: 3px solid var(--danger, #D9534F);
  border-radius: 6px;
  font-size: 12.5px;
  line-height: 1.65;
  color: #8A3A2E;
}
.edit-img-err-title { font-weight: 600; margin-bottom: 4px; }
.edit-img-err ul { margin: 0; padding-left: 18px; }
.edit-img-err li { word-break: break-all; }
.edit-img-err-more { margin-top: 2px; color: #A9604F; }

/* 拖拽进图册区域时的高亮 */
.edit-img-grid.is-drag {
  outline: 2px dashed var(--primary);
  outline-offset: 3px;
  background: rgba(184, 130, 92, 0.06);
  border-radius: 8px;
}


/* 分区标题 */
.edit-section-title {
  font-size: 14px;
  font-weight: 600;
  color: var(--text-2);
  margin: 16px 0 10px;
  padding-top: 12px;
  border-top: 1px solid var(--border);
  display: flex;
  align-items: center;
  gap: 6px;
}
.edit-price-tag {
  font-size: 11px;
  font-weight: 400;
  color: var(--text-3);
  background: var(--bg);
  padding: 2px 8px;
  border-radius: 8px;
}

/* 表单字段 */
.edit-field { margin-bottom: 12px; }
.edit-field label {
  display: block;
  font-size: 13px;
  color: var(--text-2);
  margin-bottom: 4px;
}
.edit-field input, .edit-field select {
  width: 100%;
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 9px 12px;
  font-size: 14px;
  outline: none;
  transition: all 0.3s var(--transition);
  background: #fff;
}
.edit-field input:focus, .edit-field select:focus {
  border-color: var(--primary);
  box-shadow: 0 0 0 3px var(--primary-light);
}

/* 双列布局 */
.edit-field-row {
  display: flex;
  gap: 10px;
}
.edit-field-row .edit-field { flex: 1; }

/* 价格网格 */
.edit-price-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 10px;
}
.edit-price-item {
  margin-bottom: 0;
}
.edit-price-item label {
  display: block;
  font-size: 12px;
  color: var(--text-2);
  margin-bottom: 4px;
}
.edit-price-item input {
  width: 100%;
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 8px 10px;
  font-size: 14px;
  outline: none;
  transition: all 0.3s var(--transition);
}
.edit-price-item input:focus {
  border-color: var(--primary);
  box-shadow: 0 0 0 3px var(--primary-light);
}
.edit-price-item.highlight input {
  border-color: var(--danger);
  background: #FBF0EE;
}
.edit-price-item.highlight input:focus {
  box-shadow: 0 0 0 3px rgba(255,77,79,0.1);
}
.edit-buyer-tag {
  font-size: 12px;
  color: var(--danger);
  margin-left: 2px;
}

/* 底部操作按钮 */
.edit-modal-footer {
  display: flex;
  gap: 10px;
  padding: 12px 18px;
  border-top: 1px solid var(--border);
  background: var(--bg);
}
.edit-modal-footer button {
  flex: 1;
  border: none;
  border-radius: 10px;
  padding: 11px;
  font-size: 15px;
  font-weight: 600;
  cursor: pointer;
  transition: all 0.2s var(--transition);
  position: relative;
  overflow: hidden;
}
.edit-btn-cancel {
  background: var(--bg);
  color: var(--text-2);
}
.edit-btn-cancel:active { background: var(--border); transform: scale(0.97); }
.edit-btn-save {
  background: var(--grad-primary);
  color: #fff;
  box-shadow: 0 2px 8px rgba(184,130,92,0.3);
}
.edit-btn-save:active { transform: scale(0.97); }
.edit-btn-save:disabled { opacity: 0.6; }

/* ==================== SVG 图标系统 ==================== */
.icon-svg { display: inline-block; vertical-align: middle; width: 18px; height: 18px; flex-shrink: 0; }
.icon-svg path, .icon-svg circle, .icon-svg rect, .icon-svg line, .icon-svg polyline {
  stroke-linecap: round; stroke-linejoin: round;
}

/* 登录页装饰圆 */
.login-deco {
  position: fixed;
  top: -60px;
  right: -60px;
  width: 200px;
  height: 200px;
  border-radius: 50%;
  background: var(--primary-light);
  opacity: 0.5;
  z-index: 0;
  pointer-events: none;
}
.login-deco-2 {
  position: fixed;
  bottom: -80px;
  left: -40px;
  width: 180px;
  height: 180px;
  border-radius: 50%;
  background: var(--primary-lighter);
  opacity: 0.6;
  z-index: 0;
  pointer-events: none;
}
.login-page .logo, .login-page .logo-sub, .login-page .form-box, .login-page .seller-tip {
  position: relative;
  z-index: 1;
}

/* ==================== 首页底部合规信息 ==================== */
.site-footer {
  padding: 20px 16px 78px;
  text-align: center;
  color: var(--text-3);
  font-size: 12px;
  line-height: 1.9;
  background: var(--bg);
}
.site-footer .footer-links a { color: var(--text-2); margin: 0 6px; text-decoration: none; }
.site-footer .footer-links .dot { opacity: .5; }
.site-footer .footer-license { margin-top: 3px; }

/* 分类占位图（无商品图时按分类显示） */
img.cat-ph { object-fit: cover; width: 100%; height: 100%; background: var(--primary-lighter); }

/* 导航栏图标按钮组（图标 + 文字标签） */
.navbar .nav-actions { display: flex; gap: 2px; align-items: center; flex-wrap: wrap; justify-content: flex-end; margin-left: auto; }
.navbar .nav-action-btn { display: flex; flex-direction: column; align-items: center; gap: 2px; padding: 3px 5px; border-radius: 8px; transition: background 0.2s; position: relative; }
.navbar .nav-action-btn:active { background: rgba(255,255,255,0.15); }
.navbar .nav-action-btn .icon-svg { width: 18px; height: 18px; display: block; margin: 0 auto; }
.navbar .nav-action-btn .nav-label { font-size: 12px; opacity: 0.95; white-space: nowrap; line-height: 1.2; }
.navbar .nav-action-btn .nav-badge {
  position: absolute;
  top: 0;
  right: 2px;
  background: var(--danger);
  color: #fff;
  border-radius: 10px;
  font-size: 9px;
  padding: 0 4px;
  min-width: 14px;
  height: 14px;
  line-height: 14px;
  text-align: center;
  font-weight: 600;
}

/* 搜索栏图标 */
.search-bar .search-icon-btn {
  background: var(--grad-primary);
  color: #fff;
  border: none;
  border-radius: 20px;
  padding: 0 16px;
  font-size: 14px;
  cursor: pointer;
  transition: all 0.2s var(--transition);
  position: relative;
  overflow: hidden;
  display: flex;
  align-items: center;
  gap: 4px;
}

/* 底部栏图标按钮 */
.bottom-bar .btn-cart, .bottom-bar .btn-buy {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 5px;
}
.bottom-bar .btn-cart .icon-svg, .bottom-bar .btn-buy .icon-svg { width: 18px; height: 18px; }

/* ==================== 底部标签栏（2026-09-11 改版） ====================
   背景：原先首页顶栏塞了 8 个入口（秒杀/优惠券/收藏/通知/会员/客服/订单/登录），
   手机上放不下折成两行，且入口文字只有 10px。根因是"没有『我的』页面"，
   订单/收藏/优惠券/会员/客服无处安放，只好全摊在顶栏。
   改法：顶栏只留店铺名；新建 /my.html 承载个人中心；底部标签栏承载 4 个主入口。
   详见《体验走查报告.html》问题 1。 */
:root {
  --tabbar-h: 56px;
}
.tabbar {
  position: fixed;
  bottom: 0;
  left: 50%;
  transform: translateX(-50%);
  width: 100%;
  max-width: 480px;
  height: calc(var(--tabbar-h) + env(safe-area-inset-bottom, 0px));
  padding-bottom: env(safe-area-inset-bottom, 0px);
  background: rgba(255, 255, 255, 0.97);
  -webkit-backdrop-filter: saturate(180%) blur(12px);
  backdrop-filter: saturate(180%) blur(12px);
  border-top: 1px solid var(--border);
  display: flex;
  z-index: 120;
  box-shadow: 0 -2px 12px rgba(140, 110, 80, 0.08);
}
.tabbar-item {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 3px;
  color: var(--text-3);
  text-decoration: none;
  font-size: 12px; /* 原顶栏入口是 10px，手机上要眯眼才看得清 */
  line-height: 1.2;
  position: relative;
  transition: color 0.18s var(--transition);
  -webkit-tap-highlight-color: transparent;
}
.tabbar-item .icon-svg {
  width: 22px;
  height: 22px;
  transition: transform 0.18s var(--transition-bounce);
}
.tabbar-item.active {
  color: var(--primary);
  font-weight: 600;
}
.tabbar-item.active .icon-svg {
  stroke-width: 2.1;
  transform: translateY(-1px);
}
.tabbar-item:active .icon-svg {
  transform: scale(0.88);
}
.tabbar-badge {
  position: absolute;
  top: 5px;
  left: 50%;
  margin-left: 5px;
  background: var(--danger);
  color: #fff;
  border: 1.5px solid #fff;
  border-radius: 10px;
  font-size: 11px;
  font-weight: 600;
  padding: 0 4px;
  min-width: 15px;
  height: 15px;
  line-height: 15px;
  text-align: center;
  box-sizing: content-box;
}
/* 有标签栏的页面，正文底部要留出空间，否则最后一行商品被压住 */
body.has-tabbar {
  padding-bottom: calc(var(--tabbar-h) + env(safe-area-inset-bottom, 0px) + 4px);
}
/* 购物车页的「合计 + 去结算」条需要架在标签栏之上（淘宝/拼多多的做法） */
body.has-tabbar .cart-footer {
  bottom: calc(var(--tabbar-h) + env(safe-area-inset-bottom, 0px));
}
/* 购物车列表：给上面那条「合计 + 去结算」留出空间，否则最后一件商品被盖住 */
body.has-tabbar #cartList {
  padding-bottom: 76px;
}
body.has-tabbar .site-footer {
  margin-bottom: 8px;
}

/* ==================== 「我的」页面 ==================== */
.me-card {
  margin: 12px;
  padding: 18px 16px;
  border-radius: var(--radius-lg);
  background: var(--grad-primary);
  color: #fff;
  display: flex;
  align-items: center;
  gap: 14px;
  box-shadow: 0 6px 20px rgba(184, 130, 92, 0.28);
  animation: fadeInUp 0.35s var(--transition);
}
.me-avatar {
  width: 54px;
  height: 54px;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.22);
  border: 2px solid rgba(255, 255, 255, 0.5);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 22px;
  font-weight: 600;
  flex-shrink: 0;
  overflow: hidden;
}
.me-avatar img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.me-info {
  flex: 1;
  min-width: 0;
}
.me-info .me-name {
  font-size: 17px;
  font-weight: 600;
  display: flex;
  align-items: center;
  gap: 6px;
  flex-wrap: wrap;
}
.me-info .me-sub {
  font-size: 12.5px;
  opacity: 0.9;
  margin-top: 4px;
  word-break: break-all;
}
.me-badge {
  font-size: 11px;
  font-weight: 600;
  padding: 2px 7px;
  border-radius: 9px;
  background: rgba(255, 255, 255, 0.24);
  border: 1px solid rgba(255, 255, 255, 0.42);
}
.me-arrow {
  font-size: 13px;
  opacity: 0.85;
  flex-shrink: 0;
}

.me-panel {
  margin: 12px;
  background: var(--card);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-sm);
  overflow: hidden;
  animation: fadeInUp 0.35s var(--transition);
}
.me-panel-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 14px 16px 10px;
}
.me-panel-head h3 {
  font-size: 15px;
  font-weight: 600;
  color: var(--text);
}
.me-panel-head a {
  font-size: 12.5px;
  color: var(--text-3);
  text-decoration: none;
  display: flex;
  align-items: center;
  gap: 2px;
}
.me-panel-head a:active {
  color: var(--primary);
}

/* 订单四宫格 */
.me-order-grid {
  display: flex;
  padding: 0 4px 14px;
}
.me-order-grid a {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 5px;
  padding: 6px 0;
  text-decoration: none;
  color: var(--text-2);
  font-size: 12.5px;
  position: relative;
  transition: transform 0.18s var(--transition);
}
.me-order-grid a .icon-svg {
  width: 24px;
  height: 24px;
  color: var(--primary);
}
.me-order-grid a:active {
  transform: scale(0.93);
}
.me-order-grid .me-count {
  position: absolute;
  top: 0;
  left: 50%;
  margin-left: 4px;
  background: var(--danger);
  color: #fff;
  border: 1.5px solid #fff;
  border-radius: 10px;
  font-size: 11px;
  font-weight: 600;
  padding: 0 4px;
  min-width: 15px;
  height: 15px;
  line-height: 15px;
  text-align: center;
  box-sizing: content-box;
}

/* 我的服务九宫格 */
.me-grid {
  display: grid;
  /* 4 列 × minmax(0,1fr)：标签是固定 4 个汉字，本来放得下，
     但一旦以后改成长标签，裸 1fr 会把整列顶宽 → 页面能往右滑。 */
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 4px 0;
  padding: 0 4px 16px;
}
.me-grid a {
  min-width: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
  padding: 10px 2px;
  text-decoration: none;
  color: var(--text-2);
  font-size: 12.5px;
  position: relative;
  transition: transform 0.18s var(--transition);
}
.me-grid a .icon-svg {
  width: 24px;
  height: 24px;
  color: var(--primary);
}
.me-grid a:active {
  transform: scale(0.93);
}
.me-grid .me-count {
  position: absolute;
  top: 4px;
  left: 50%;
  margin-left: 2px;
  background: var(--danger);
  color: #fff;
  border: 1.5px solid #fff;
  border-radius: 10px;
  font-size: 11px;
  font-weight: 600;
  padding: 0 4px;
  min-width: 15px;
  height: 15px;
  line-height: 15px;
  text-align: center;
  box-sizing: content-box;
}
.me-grid a.me-wide {
  grid-column: span 4;
  flex-direction: row;
  justify-content: space-between;
  padding: 14px 16px;
  font-size: 14px;
  border-top: 1px solid var(--border);
}
.me-grid a.me-wide .me-wide-left {
  display: flex;
  align-items: center;
  gap: 10px;
  color: var(--text);
}

/* 卖家专区 */
.me-seller {
  background: var(--grad-seller);
  color: #E8C896;
}
.me-seller .me-grid a,
.me-seller .me-panel-head h3 {
  color: #E8C896;
}
.me-seller .me-grid a .icon-svg {
  color: #E8C896;
}
/* 卖家专区里 .me-wide-left 的文字：上面那条 .me-grid a.me-wide .me-wide-left
   用了 var(--text)（深色），在深色卖家底上几乎看不见。
   这里补一条更高优先级的规则把颜色掰回来。（2026-09-11 实际踩到） */
.me-seller .me-grid a.me-wide .me-wide-left {
  color: #E8C896;
}
.me-seller .me-panel-head {
  border-bottom: 1px solid rgba(232, 200, 150, 0.18);
}

/* 退出登录 */
.me-logout {
  margin: 12px;
  padding: 14px;
  text-align: center;
  background: var(--card);
  border-radius: var(--radius-lg);
  color: var(--danger);
  font-size: 15px;
  font-weight: 600;
  box-shadow: var(--shadow-sm);
  cursor: pointer;
  transition: background 0.2s;
}
.me-logout:active {
  background: var(--primary-lighter);
}

/* ================================================================
   商品规格选择弹窗（2026-09-20，配套 js/variant-picker.js）
   ----------------------------------------------------------------
   同款不同规格合并成一个商品后，加购 / 立即购买时弹出这个底部抽屉。
   z-index 取 9995：要盖住吸顶栏(100)与批量操作条(200)，
   但低于 toast(9999)，否则选完规格看不到提示。
   ================================================================ */
.vp-overlay {
  position: fixed;
  inset: 0;
  z-index: 9995;
}
.vp-mask {
  position: absolute;
  inset: 0;
  background: rgba(45, 35, 28, 0);
  transition: background 0.24s var(--transition);
}
.vp-in .vp-mask { background: rgba(45, 35, 28, 0.45); }

.vp-panel {
  position: absolute;
  left: 0; right: 0; bottom: 0;
  max-width: 560px;
  margin: 0 auto;
  background: var(--card);
  border-radius: 18px 18px 0 0;
  box-shadow: 0 -6px 30px rgba(74, 59, 50, 0.18);
  display: flex;
  flex-direction: column;
  max-height: 82vh;
  transform: translateY(101%);
  transition: transform 0.28s var(--transition);
  padding-bottom: env(safe-area-inset-bottom, 0px);
}
.vp-in .vp-panel { transform: translateY(0); }
.vp-leave .vp-panel { transform: translateY(101%); }
.vp-leave .vp-mask { background: rgba(45, 35, 28, 0); }

.vp-close {
  position: absolute;
  top: 8px; right: 10px;
  width: 32px; height: 32px;
  border: none; background: transparent;
  font-size: 26px; line-height: 1;
  color: var(--text-3);
  cursor: pointer;
  border-radius: 50%;
}
.vp-close:active { background: var(--primary-light); }

/* ---------- 头部：图片 + 价格 + 库存 + 已选 ---------- */
.vp-head {
  display: flex;
  gap: 12px;
  padding: 16px 44px 12px 16px;
  border-bottom: 1px solid var(--border);
}
.vp-thumb-box {
  width: 88px; height: 88px;
  flex: 0 0 88px;
  border-radius: var(--radius);
  overflow: hidden;
  background: var(--primary-lighter);
  display: flex; align-items: center; justify-content: center;
  /* 2026-09-24：小图可点开看大图（Marco 反馈「预览图点不开」） */
  position: relative;
  cursor: zoom-in;
  -webkit-tap-highlight-color: transparent;
}
.vp-thumb { width: 100%; height: 100%; object-fit: cover; }
/* 右下角放大镜角标：提示买家这张图可以点开 */
.vp-thumb-zoom {
  position: absolute;
  right: 3px; bottom: 3px;
  width: 19px; height: 19px;
  border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  background: rgba(0, 0, 0, 0.42);
  color: #fff;
  pointer-events: none;
}
.vp-thumb-zoom svg { width: 12px; height: 12px; display: block; }
.vp-thumb-box:active .vp-thumb-zoom { background: rgba(0, 0, 0, 0.6); }
.vp-info { flex: 1; min-width: 0; display: flex; flex-direction: column; justify-content: center; gap: 4px; }
.vp-price {
  font-size: 20px; font-weight: 700;
  color: var(--danger);
  line-height: 1.2;
}
.vp-price i { font-style: normal; font-size: 14px; color: var(--text-3); margin: 0 2px; }
.vp-mp {
  margin-left: 8px;
  font-size: 11px; font-weight: 500;
  color: var(--primary-dark);
  background: var(--primary-light);
  border-radius: 4px;
  padding: 1px 5px;
  vertical-align: 2px;
}
.vp-stock { font-size: 12px; color: var(--text-3); }
.vp-sel {
  font-size: 13px; color: var(--text-2);
  line-height: 1.4;
  /* 型号名可能很长（如「78*16mm-A618C1」），最多两行 */
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}

/* ---------- 规格区 ---------- */
.vp-body {
  flex: 1;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  padding: 14px 16px 6px;
}
.vp-dim { margin-bottom: 16px; }
.vp-dim-name {
  font-size: 13px;
  color: var(--text-2);
  margin-bottom: 8px;
  font-weight: 500;
}
.vp-opts {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}
.vp-opt {
  font-family: inherit;
  font-size: 13px;
  line-height: 1.2;
  padding: 8px 12px;
  min-height: 34px;
  border: 1px solid var(--border);
  border-radius: 17px;
  background: var(--bg);
  color: var(--text);
  cursor: pointer;
  transition: all 0.16s var(--transition);
  max-width: 100%;
  word-break: break-all;
  text-align: left;
}
.vp-opt:active { transform: scale(0.96); }
.vp-opt.is-on {
  background: var(--primary-light);
  border-color: var(--primary);
  color: var(--primary-dark);
  font-weight: 600;
}
/* 缺货 / 当前组合下选不中：划一道线，但仍然可点（点了好提示「请换一个」） */
.vp-opt.is-off {
  color: var(--text-3);
  background: var(--bg-outer);
  border-style: dashed;
  text-decoration: line-through;
}
.vp-opt.is-on.is-off {
  border-color: var(--danger);
  color: var(--danger);
}
@keyframes vpShake {
  0%, 100% { transform: translateX(0); }
  20% { transform: translateX(-6px); }
  40% { transform: translateX(5px); }
  60% { transform: translateX(-3px); }
  80% { transform: translateX(2px); }
}
.vp-shake { animation: vpShake 0.45s; }

/* ---------- 底部：数量 + 按钮 ---------- */
.vp-foot {
  border-top: 1px solid var(--border);
  padding: 10px 16px calc(12px + env(safe-area-inset-bottom, 0px));
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.vp-qty {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 13px;
  color: var(--text-2);
}
.vp-qty > span { margin-right: auto; }
.vp-qty-btn {
  width: 32px; height: 32px;
  border: 1px solid var(--border);
  background: var(--bg);
  border-radius: 8px;
  font-size: 18px; line-height: 1;
  color: var(--text);
  cursor: pointer;
  font-family: inherit;
}
.vp-qty-btn:active { background: var(--primary-light); }
.vp-qty-input {
  width: 54px; height: 32px;
  text-align: center;
  border: 1px solid var(--border);
  border-radius: 8px;
  background: var(--card);
  font-family: inherit;
  font-size: 14px;
  color: var(--text);
}
.vp-actions { display: flex; gap: 10px; }
.vp-btn {
  flex: 1;
  height: 46px;
  border: none;
  border-radius: 23px;
  font-family: inherit;
  font-size: 15px;
  font-weight: 600;
  color: #fff;
  cursor: pointer;
  transition: opacity 0.16s, transform 0.16s;
}
.vp-btn:active { transform: scale(0.98); }
.vp-btn[disabled] { opacity: 0.45; }
.vp-btn-cart { background: var(--grad-cart); }
.vp-btn-buy { background: var(--grad-buy); }
.vp-btn-primary { background: var(--grad-primary); }
.vp-btn.is-disabled { opacity: 0.45; }

/* 桌面端：底部抽屉变成居中的卡片，别贴着屏幕底边 */
@media (min-width: 561px) {
  .vp-panel {
    bottom: 50%;
    transform: translateY(calc(50% + 40px));
    border-radius: 18px;
    max-height: 76vh;
  }
  .vp-in .vp-panel { transform: translateY(50%); }
  .vp-leave .vp-panel { transform: translateY(calc(50% + 40px)); }
}

/* ================================================================
   商品卡片上的「N 个规格」角标 + 价格区间
   ================================================================ */
.spec-badge {
  display: inline-block;
  font-size: 11px;
  line-height: 1.5;
  color: var(--primary-dark);
  background: var(--primary-light);
  border-radius: 4px;
  padding: 0 5px;
  margin-left: 4px;
  vertical-align: 1px;
  font-weight: 500;
}
.price .price-range i {
  font-style: normal;
  font-size: 12px;
  color: var(--text-3);
  margin: 0 1px;
}

/* ================================================================
   卖家端商品规格编辑器（js/variant-editor.js，2026-09-20）
   与买家端的规格选择抽屉（variant-picker.js）配对使用
   ================================================================ */
.ve-wrap { background: #fff; margin-bottom: 10px; padding: 14px 16px; }
.ve-head { display: flex; align-items: center; justify-content: space-between; gap: 10px; flex-wrap: wrap; }
.ve-switch { display: inline-flex; align-items: center; gap: 8px; font-size: 14px; font-weight: 600; color: var(--text-1); cursor: pointer; }
.ve-switch input { width: 18px; height: 18px; accent-color: var(--primary); }
.ve-head-tip { font-size: 11.5px; color: var(--text-3); }
.ve-body { margin-top: 14px; }

.ve-section-title {
  display: flex; align-items: center; justify-content: space-between; gap: 8px;
  font-size: 13px; font-weight: 600; color: var(--text-2);
  padding: 8px 0 6px; border-top: 1px solid var(--border);
}
.ve-section-title:first-child { border-top: none; padding-top: 0; }
.ve-section-title em { font-style: normal; font-size: 11.5px; font-weight: 500; color: var(--text-3); }

/* ---- 维度 ---- */
.ve-dim { border: 1px solid var(--border); border-radius: 10px; padding: 10px; margin-bottom: 8px; background: var(--bg); }
.ve-dim-head { display: flex; align-items: center; gap: 8px; }
.ve-dim-name {
  flex: 1; min-width: 0; border: 1px solid var(--border); border-radius: 6px;
  padding: 8px 10px; font-size: 13px; outline: none; background: #fff; color: var(--text-1);
}
.ve-dim-name:focus { border-color: var(--primary); }
.ve-dim-del {
  flex-shrink: 0; width: 30px; height: 30px; border: none; border-radius: 6px;
  background: #FBEAE8; color: var(--danger); cursor: pointer;
  display: inline-flex; align-items: center; justify-content: center;
}
.ve-dim-del .icon-svg { width: 13px; height: 13px; }

.ve-vals { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 8px; }
.ve-val {
  display: inline-flex; align-items: center; gap: 5px;
  background: var(--primary-light); color: var(--primary-dark);
  border-radius: 14px; padding: 4px 6px 4px 10px; font-size: 12.5px; font-weight: 500;
}
.ve-val i { display: inline-flex; cursor: pointer; opacity: 0.6; }
.ve-val i .icon-svg { width: 11px; height: 11px; }
.ve-val-add { flex: 1 1 140px; min-width: 120px; }
.ve-val-add input {
  width: 100%; border: 1px dashed var(--border); border-radius: 14px;
  padding: 6px 10px; font-size: 12.5px; outline: none; background: transparent; color: var(--text-1);
}
.ve-val-add input:focus { border-color: var(--primary); border-style: solid; }

.ve-add-dim {
  width: 100%; margin-top: 4px; padding: 10px; border: 1px dashed var(--border);
  border-radius: 10px; background: #fff; color: var(--primary);
  font-size: 13px; font-weight: 600; cursor: pointer;
  display: inline-flex; align-items: center; justify-content: center; gap: 6px;
}
.ve-add-dim .icon-svg { width: 14px; height: 14px; }

/* ---- 批量填 ---- */
.ve-fill {
  display: flex; align-items: center; gap: 6px; flex-wrap: wrap;
  background: #FDF6E7; border-radius: 8px; padding: 8px 10px; margin-bottom: 10px;
}
.ve-fill-label { font-size: 12px; color: var(--text-2); font-weight: 600; }
.ve-fill input {
  width: 84px; border: 1px solid var(--border); border-radius: 6px;
  padding: 6px 8px; font-size: 12.5px; outline: none; background: #fff; color: var(--text-1);
}
.ve-fill button {
  border: none; border-radius: 6px; background: var(--primary); color: #fff;
  font-size: 12.5px; font-weight: 600; padding: 7px 12px; cursor: pointer;
}

/* ---- 批量配图 ---- */
.ve-batch {
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
  margin-bottom: 6px;
}
.ve-batch-btn {
  display: inline-flex; align-items: center; gap: 6px;
  border: 1px solid var(--primary); border-radius: 8px; background: #fff;
  color: var(--primary); font-size: 12.5px; font-weight: 600;
  padding: 8px 12px; cursor: pointer;
}
.ve-batch-btn .icon-svg { width: 15px; height: 15px; }
.ve-batch-clear {
  border: none; background: transparent; color: var(--text-3);
  font-size: 12.5px; padding: 8px 4px; cursor: pointer;
}
.ve-batch-status { font-size: 12px; font-weight: 600; color: var(--primary); }
.ve-batch-hint { font-size: 11.5px; color: var(--text-3); line-height: 1.6; margin-bottom: 10px; }

/* ---- 规格行 ---- */
.ve-rows { display: flex; flex-direction: column; gap: 8px; }
.ve-row { border: 1px solid var(--border); border-radius: 10px; padding: 10px; background: #fff; }
.ve-row-head { display: flex; align-items: center; justify-content: space-between; gap: 8px; margin-bottom: 8px; }
.ve-row-spec { font-size: 13px; font-weight: 600; color: var(--text-1); }
.ve-row-del {
  flex-shrink: 0; width: 26px; height: 26px; border: none; border-radius: 6px;
  background: #F2F2F2; color: var(--text-3); cursor: pointer;
  display: inline-flex; align-items: center; justify-content: center;
}
.ve-row-del .icon-svg { width: 12px; height: 12px; }
.ve-row-body { display: flex; gap: 10px; align-items: flex-start; }

.ve-thumb {
  flex-shrink: 0; position: relative; width: 62px; height: 62px; padding: 0;
  border: 1px dashed var(--border); border-radius: 8px; background: var(--bg);
  cursor: pointer; overflow: hidden;
  display: inline-flex; align-items: center; justify-content: center;
}
.ve-thumb.has-img { border-style: solid; }
.ve-thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }
.ve-thumb-ph { color: var(--text-3); opacity: 0.5; display: inline-flex; }
.ve-thumb-ph .icon-svg { width: 20px; height: 20px; }
.ve-thumb-tip {
  position: absolute; left: 0; right: 0; bottom: 0;
  font-size: 10px; color: #fff; background: rgba(0,0,0,0.45);
  text-align: center; padding: 1px 0;
}

.ve-fields { flex: 1; min-width: 0; display: grid; grid-template-columns: 1fr 1fr; gap: 6px 8px; }
.ve-f { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.ve-f span { font-size: 11px; color: var(--text-3); }
.ve-f input {
  width: 100%; min-width: 0; border: 1px solid var(--border); border-radius: 6px;
  padding: 7px 8px; font-size: 13px; outline: none; background: #fff; color: var(--text-1);
}
.ve-f input:focus { border-color: var(--primary); }

.ve-note { font-size: 11.5px; color: var(--text-3); line-height: 1.7; margin-top: 10px; }
.ve-empty {
  font-size: 12.5px; color: var(--text-3); background: var(--bg);
  border-radius: 8px; padding: 12px; text-align: center; line-height: 1.7;
}

@media (min-width: 768px) {
  .ve-fields { grid-template-columns: repeat(4, 1fr); }
}

/* ============================================================================
   桌面端适配（2026-10-21 新增）
   ----------------------------------------------------------------------------
   背景：Marco 反馈「电脑上打开是手机版界面，不适配」——实测 1440px 屏幕下
        body 被限死 480px，两侧各空 480px，商品还是 2 列、底部还是手机标签栏。
   策略：**只在这一条媒体查询里做覆盖**，移动端（<1024px）一行都不受影响。
   遵守 CSS 铁律：
     · 网格一律 minmax(0,1fr)，不用裸 1fr（铁律 2）
     · .bottom-bar / .cart-footer 的关键帧里写死了 translateX(-50%)，
       这里只改宽度，绝不动它们的 transform / left（铁律 4）
     · 不用 body{overflow-x:hidden} 糊溢出（铁律 5 附注）
   ============================================================================ */
@media (min-width: 1024px) {
  /* 1. 内容区：480px → 1200px */
  body { max-width: 1200px; }

  /* 2. 商品栅格：2 列 → 4 列（首页新品区与商品列表页共用 .product-list） */
  .product-list { grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 14px; }
  .rec-grid     { grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 14px; }

  /* 3. 底部标签栏 → 顶部横向导航
        .tabbar 没有 animation，所以可以安全地把 transform 清成 none（铁律 4 只在有 animation 时才危险） */
  .tabbar {
    top: 0;
    bottom: auto;
    left: 0;
    transform: none;
    max-width: none;
    height: 56px;
    padding-bottom: 0;
    border-top: 0;
    border-bottom: 1px solid var(--border);
    box-shadow: 0 2px 12px rgba(140, 110, 80, 0.08);
    justify-content: center;
    gap: 2px;
  }
  .tabbar-item {
    flex: 0 0 auto;
    flex-direction: row;
    gap: 8px;
    padding: 0 24px;
    font-size: 14px;
  }
  .tabbar-item .icon-svg { width: 20px; height: 20px; }

  /* 标签栏挪到顶部后，让位方向从「底部 56px」改成「顶部 56px」 */
  body.has-tabbar { padding-top: 56px; padding-bottom: 0; }

  /* 4. 底部固定操作栏（详情页加购条 / 购物车结算条）跟着放宽 */
  .bottom-bar, .cart-footer { max-width: 1200px; }
}

