/* 电商动态积木的样式 —— 类目导航面板 / 品牌墙 / 类目商品分组。
 *
 * 由 website_sale 自己发（view/templates.xml 的 base_frontend_layout 补丁插 <link>），
 * 不塞进 website 的 snippets.css：那一份是 tools/build_snippet_css.py 从 Odoo 的片段
 * SCSS 编出来的**产物**，手改会在下一次重跑生成器时无声消失。
 *
 * 配色一律走主题变量（--o-color-* / --bs-*），只在没有对应变量的地方用中性灰。
 * 写死颜色的话，换主题时这几个积木会是全站唯一没跟着变的那几块。
 *
 * ⚠️ 前台与建站器画布共用这一份。画布是 srcdoc iframe，继承父页面 base URL，
 * 页面 <head> 里的 <link> 在画布里同样生效 —— 编辑态与访客态因此不会对不上
 * （同 website 的 grid.css 那条注释）。
 */

/* ══════════════════ 通用 ══════════════════ */

/* 建站器画布里的"这里将显示…"提示条。前台不会出现（填充器只在 Editor 时产出）。 */
.o_wsale_snippet_notice {
  border-style: dashed;
}

/* ══════════════════ 类目导航面板 ══════════════════ */

.o_wsale_catnav {
  display: flex;
  align-items: stretch;
  gap: 0;
  border: 1px solid var(--bs-border-color, #dee2e6);
  border-radius: .5rem;
  overflow: hidden;
  background: var(--bs-body-bg, #fff);
  /* 面板比左栏高时整体跟着长，不裁切；矮时左栏撑满（min-height 由内容定）。 */
  min-height: 20rem;
}

/* ── 左栏：一级类目 ── */
.o_wsale_catnav_aside {
  flex: 0 0 15rem;
  max-width: 15rem;
  background: var(--bs-secondary-bg, #f8f9fa);
  border-right: 1px solid var(--bs-border-color, #dee2e6);
  padding: .5rem 0;
  /* 类目多到装不下时**只让左栏自己滚**，不撑高整块积木。 */
  max-height: 34rem;
  overflow-y: auto;
}

.o_wsale_catnav_root_link {
  display: flex;
  align-items: center;
  gap: .5rem;
  padding: .5rem 1rem;
  color: inherit;
  text-decoration: none;
  font-size: .95rem;
  line-height: 1.4;
}

.o_wsale_catnav_root_name {
  flex: 1 1 auto;
  /* 类目名可以很长（"微控制器 / 逻辑器件"），两行封顶后省略，不推歪箭头。 */
  overflow: hidden;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
}

.o_wsale_catnav_chevron {
  flex: 0 0 auto;
  opacity: .35;
  transition: opacity .15s ease;
}

.o_wsale_catnav_root:hover .o_wsale_catnav_root_link,
.o_wsale_catnav_root.active .o_wsale_catnav_root_link {
  background: var(--bs-body-bg, #fff);
  color: var(--o-color-1, #714b67);
  font-weight: 600;
}

.o_wsale_catnav_root:hover .o_wsale_catnav_chevron,
.o_wsale_catnav_root.active .o_wsale_catnav_chevron {
  opacity: 1;
}

.o_wsale_catnav_icon {
  width: 1.25rem;
  height: 1.25rem;
  object-fit: contain;
  flex: 0 0 auto;
}

/* ── 右侧：二三级面板 ── */
.o_wsale_catnav_panels {
  flex: 1 1 auto;
  min-width: 0; /* 不给的话内部的长链接行会把 flex 容器撑破 */
  padding: 1.25rem 1.5rem;
}

/* 默认全部隐藏，显示哪一个由 .active 决定。
   ★ 用 display:none 而不是 visibility：面板叠在一起时后面那些仍会占位，
   积木会平白高出好几屏。 */
.o_wsale_catnav_panel {
  display: none;
}

.o_wsale_catnav_panel.active {
  display: block;
}

/* **无 JS 兜底**：脚本没跑时至少显示第一个面板，否则右边一大片空白，看着就是
   积木坏了 —— 而建站器画布**一定**会走到这一支：画布把 <script> 全剥掉
   （见 vertex editor 的说明）。JS 一跑就给容器打上 o_has_active，这条兜底随即让位。 */
.o_wsale_catnav_panels:not(.o_has_active) > .o_wsale_catnav_panel:first-child {
  display: block;
}

.o_wsale_catnav_panel_head {
  margin-bottom: 1rem;
}

.o_wsale_catnav_panel_title {
  font-size: 1.15rem;
  font-weight: 700;
  color: inherit;
  text-decoration: none;
  display: inline-flex;
  align-items: center;
  gap: .35rem;
}

.o_wsale_catnav_panel_title:hover {
  color: var(--o-color-1, #714b67);
}

.o_wsale_catnav_group {
  padding-bottom: .75rem;
  margin-bottom: .75rem;
  border-bottom: 1px solid var(--bs-border-color, #dee2e6);
}

.o_wsale_catnav_group:last-child {
  border-bottom: 0;
  margin-bottom: 0;
  padding-bottom: 0;
}

.o_wsale_catnav_group_title {
  display: inline-flex;
  align-items: center;
  gap: .35rem;
  font-weight: 600;
  color: inherit;
  text-decoration: none;
  margin-bottom: .5rem;
}

.o_wsale_catnav_group_title:hover {
  color: var(--o-color-1, #714b67);
}

.o_wsale_catnav_leaf {
  display: block;
  padding: .2rem 0;
  font-size: .9rem;
  color: var(--bs-secondary-color, #6c757d);
  text-decoration: none;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.o_wsale_catnav_leaf:hover {
  color: var(--o-color-1, #714b67);
}

/* 窄屏：左栏与面板堆叠，左栏变成横向滚动的标签条 */
@media (max-width: 767.98px) {
  .o_wsale_catnav {
    flex-direction: column;
    min-height: 0;
  }
  .o_wsale_catnav_aside {
    flex: 0 0 auto;
    max-width: none;
    max-height: none;
    display: flex;
    overflow-x: auto;
    overflow-y: hidden;
    border-right: 0;
    border-bottom: 1px solid var(--bs-border-color, #dee2e6);
    padding: 0;
  }
  .o_wsale_catnav_root {
    flex: 0 0 auto;
  }
  .o_wsale_catnav_root_link {
    white-space: nowrap;
    padding: .6rem .9rem;
  }
  .o_wsale_catnav_root_name {
    -webkit-line-clamp: 1;
  }
  .o_wsale_catnav_chevron {
    display: none;
  }
  .o_wsale_catnav_panels {
    padding: 1rem;
  }
}

/* ══════════════════ 品牌墙 ══════════════════ */

.o_wsale_brand_card {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: .5rem;
  height: 100%;
  padding: 1rem;
  border: 1px solid var(--bs-border-color, #dee2e6);
  border-radius: var(--o-card-radius, .5rem);
  background: var(--bs-body-bg, #fff);
  text-decoration: none;
  color: inherit;
}
/* 悬停 / 点选 / 灰度转彩色归 website 的 card_fx.css（品牌墙积木的「卡片」选项可单独选「灰度转彩色」） */

.o_wsale_brand_logo_wrap {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  height: 3.5rem;
}

.o_wsale_brand_logo {
  max-width: 100%;
  max-height: 100%;
  object-fit: contain;
}

/* 没传 logo 的品牌出名字 —— 破图框比没有 logo 糟得多，而"刚建好还没传图"
   是最常见的状态。 */
.o_wsale_brand_fallback {
  font-weight: 700;
  font-size: 1.05rem;
  text-align: center;
  /* 一个长单词（"IndustrialSupplies.com"）没有断点，不许断就整截被裁掉。 */
  overflow-wrap: anywhere;
  color: var(--bs-secondary-color, #6c757d);
  overflow: hidden;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
}

.o_wsale_brand_name {
  font-size: .85rem;
  text-align: center;
  color: var(--bs-secondary-color, #6c757d);
}

.o_wsale_brand_count {
  font-size: .75rem;
  color: var(--bs-secondary-color, #6c757d);
  opacity: .8;
}

/* ══════════════════ 类目商品分组 ══════════════════ */

.o_wsale_cat_group_head {
  border-bottom: 1px solid var(--bs-border-color, #dee2e6);
  padding-bottom: .5rem;
}

/* ══════════════════ 积木的「每行几列」══════════════════
 *
 * Go 的 colClass（internal/controller/grid_cols.go）给每一格下发 o_wsale_col-{断点-}N：
 * 设置值只在 ≥1200px 原样生效，窄下来按容器宽封顶（sm 3 / md 4 / lg 5），手机 2。
 * Bootstrap 的 col-* 是 12 栅格，5、7、8 列都表达不了（从前 5 列靠一条 o_wsale_col_5 特判，
 * 7、8 列静默落成 6 列），所以这里直接按 100%/N 给。
 * 选择器带 .row > ：与 Bootstrap 的 `.row > * { width: 100% }` 同权重时谁赢取决于样式表顺序。
 */
.row > .o_wsale_col-1 { flex: 0 0 auto; width: 100%; }
.row > .o_wsale_col-2 { flex: 0 0 auto; width: 50%; }
.row > .o_wsale_col-3 { flex: 0 0 auto; width: 33.333333%; }
.row > .o_wsale_col-4 { flex: 0 0 auto; width: 25%; }
.row > .o_wsale_col-5 { flex: 0 0 auto; width: 20%; }
.row > .o_wsale_col-6 { flex: 0 0 auto; width: 16.666667%; }
.row > .o_wsale_col-7 { flex: 0 0 auto; width: 14.285714%; }
.row > .o_wsale_col-8 { flex: 0 0 auto; width: 12.5%; }
@media (min-width: 576px) {
  .row > .o_wsale_col-sm-1 { flex: 0 0 auto; width: 100%; }
  .row > .o_wsale_col-sm-2 { flex: 0 0 auto; width: 50%; }
  .row > .o_wsale_col-sm-3 { flex: 0 0 auto; width: 33.333333%; }
  .row > .o_wsale_col-sm-4 { flex: 0 0 auto; width: 25%; }
  .row > .o_wsale_col-sm-5 { flex: 0 0 auto; width: 20%; }
  .row > .o_wsale_col-sm-6 { flex: 0 0 auto; width: 16.666667%; }
  .row > .o_wsale_col-sm-7 { flex: 0 0 auto; width: 14.285714%; }
  .row > .o_wsale_col-sm-8 { flex: 0 0 auto; width: 12.5%; }
}
@media (min-width: 768px) {
  .row > .o_wsale_col-md-1 { flex: 0 0 auto; width: 100%; }
  .row > .o_wsale_col-md-2 { flex: 0 0 auto; width: 50%; }
  .row > .o_wsale_col-md-3 { flex: 0 0 auto; width: 33.333333%; }
  .row > .o_wsale_col-md-4 { flex: 0 0 auto; width: 25%; }
  .row > .o_wsale_col-md-5 { flex: 0 0 auto; width: 20%; }
  .row > .o_wsale_col-md-6 { flex: 0 0 auto; width: 16.666667%; }
  .row > .o_wsale_col-md-7 { flex: 0 0 auto; width: 14.285714%; }
  .row > .o_wsale_col-md-8 { flex: 0 0 auto; width: 12.5%; }
}
@media (min-width: 992px) {
  .row > .o_wsale_col-lg-1 { flex: 0 0 auto; width: 100%; }
  .row > .o_wsale_col-lg-2 { flex: 0 0 auto; width: 50%; }
  .row > .o_wsale_col-lg-3 { flex: 0 0 auto; width: 33.333333%; }
  .row > .o_wsale_col-lg-4 { flex: 0 0 auto; width: 25%; }
  .row > .o_wsale_col-lg-5 { flex: 0 0 auto; width: 20%; }
  .row > .o_wsale_col-lg-6 { flex: 0 0 auto; width: 16.666667%; }
  .row > .o_wsale_col-lg-7 { flex: 0 0 auto; width: 14.285714%; }
  .row > .o_wsale_col-lg-8 { flex: 0 0 auto; width: 12.5%; }
}
@media (min-width: 1200px) {
  .row > .o_wsale_col-xl-1 { flex: 0 0 auto; width: 100%; }
  .row > .o_wsale_col-xl-2 { flex: 0 0 auto; width: 50%; }
  .row > .o_wsale_col-xl-3 { flex: 0 0 auto; width: 33.333333%; }
  .row > .o_wsale_col-xl-4 { flex: 0 0 auto; width: 25%; }
  .row > .o_wsale_col-xl-5 { flex: 0 0 auto; width: 20%; }
  .row > .o_wsale_col-xl-6 { flex: 0 0 auto; width: 16.666667%; }
  .row > .o_wsale_col-xl-7 { flex: 0 0 auto; width: 14.285714%; }
  .row > .o_wsale_col-xl-8 { flex: 0 0 auto; width: 12.5%; }
}

/* ══════════════════ 页头 mega menu 的三档版式 ══════════════════
 *
 * 分栏（默认，`.o_wsale_mega_cats`）不需要专属规则 —— 它就是一行 Bootstrap 栅格，
 * 面板由 website 的 header.css 撑成整页宽（`.o_mega_menu { width: 100% }`）。
 * 下面两档要动的正是那个前提。
 */

/* ── ① 悬浮（flyout）───────────────────────────────────────────
 * 图示形态（DigiKey / Mouser 那类目录站）：**挂在那颗菜单项下面**的一张窄卡片，
 * 鼠标停在哪个一级类目，哪一项的二/三级就从右边贴着浮出来。
 *
 * ★★★ 横竖两个方向的锚点**不在同一个盒子上**，这一条是整块最容易改坏的地方：
 *    - 竖直方向要贴**导航条底边**。用户 2026-08-23 报的"偏移了很多"就是这个：
 *      片段自带 `pt24 pb24`，而 theme.css 的间距 utility 是
 *      `calc(24px * var(--o-spacing-scale))`、本站 scale 1.35 —— 卡片悬在导航条
 *      下方 32.4px 的空中，中间一段透明。分栏档里那圈留白是面板的内边距（对的），
 *      悬浮档里它只是把卡片推下去。这一档清零。
 *    - 水平方向要贴**那颗菜单项**。第一版靠 `.container` 的内容边缘对齐，真栈量出来
 *      1600 视口下卡片 left=152、按钮 left=152，看着是齐的 —— **那纯属巧合**：这份
 *      菜单恰好是导航条第一项，换到第二项就整个错开，而版式一个字都没改。
 *
 *    两者冲突：给 li 加 `position:relative` 能对齐水平，但 `top:100%` 跟着变成
 *    "菜单项底边"，卡片就压进页头里去了（实测 1000 视口下菜单项换行，卡片顶边比
 *    导航条底边高 48px，直接盖住页头下半截）。
 *
 *    解法是 **`left: auto`**：绝对定位元素在 `left/right/width` 都是 auto 时，
 *    用的是它的**静态位置** —— 也就是"不定位的话它会在哪儿"，即那颗 li 的内容
 *    左边缘。而包含块仍是 `nav.navbar`（li 上挂着 position-static），所以
 *    `top: 100%` 量的还是导航条。一个属性同时拿到两个锚点，不用 JS。
 *    bootstrap 的 `.dropdown-menu[data-bs-popper]{top:100%;left:0}` 特异度 (0,2,0)
 *    正好打平，所以下面第二条选择器带上 `[data-bs-popper]` 压到 (0,3,0)。
 * ★ `pointer-events: none` 留着：`.o_mega_menu` 的盒子现在收缩到卡片大小了，但
 *    片段/容器的内边距一旦被谁改回来，那圈透明的边就会挡住下面的商品，而
 *    `data-bs-auto-close="outside"` 认为点在菜单**里面**、连关都不关 —— 表现是
 *    页面卡死。卡片自己收回 auto。
 * ★ 出视口（2026-10-27 修）：面板从卡片右边浮出、宽 46rem，而 CSS 只知道视口宽、不知道
 *    卡片在哪 —— 菜单项只要不在导航条最左边就顶出去，还撑出横向滚动条。现在由
 *    wsale_snippets.js 的 fitFlyout 量过之后写 --o-wsale-flyout-shift / --o-wsale-flyout-room，
 *    放不下时加 .o_wsale_mega_flyout_left 向左浮出（见本文件面板那一段）。没有脚本的地方
 *    （建站器画布）回落到原来的向右浮出。
 */
.o_mega_menu:has(.o_wsale_mega_flyout),
.o_mega_menu:has(.o_wsale_mega_flyout)[data-bs-popper] {
  /* width:auto 压 header.css 的 width:100%；两者都是 (0,2,0)，靠加载顺序 */
  width: auto;
  left: auto;                    /* ← 静态位置 = 那颗菜单项的左边缘 */
  /* 卡片顶出视口右边时往左挪回来（JS 量的，没量过就是 0）。挪的是**下拉框本身**：
     用 translate 挪里面的卡片只是看起来回来了，下拉框的盒子还在视口外，照样撑出横向滚动条。 */
  margin-left: var(--o-wsale-flyout-shift, 0px);
  background-color: transparent;
  border: 0;
  box-shadow: none;
  pointer-events: none;
}

/* 片段与容器的留白清零：卡片贴着导航条挂下来。间距 utility 带 !important，
   这里也得带（(0,2,0) + !important）。 */
.o_mega_menu:has(.o_wsale_mega_flyout) > .s_mega_menu_wsale_categories {
  padding-top: 0 !important;
  padding-bottom: 0 !important;
}
.o_mega_menu:has(.o_wsale_mega_flyout) .container,
.o_mega_menu:has(.o_wsale_mega_flyout) .container-fluid {
  width: auto;
  max-width: none;
  padding-left: 0;
  padding-right: 0;
}

/* 片段根节点的底色也要撤掉。website 的 header.css 里有一条
   `.o_mega_menu > .o_colored_level { background-color: var(--o-cc-bg) }`
   （它在补 theme.css 抹平 o_cc 底色的坑，见那边的注释），特异度 (0,2,0)；
   这里 (0,3,0) 压过它，不必 !important，也不影响另外两档。 */
.o_mega_menu:has(.o_wsale_mega_flyout) > .o_colored_level {
  background-color: transparent;
}

.o_wsale_mega_flyout {
  /* 浮出面板的定位面。列表宽度只此一处，面板的 left/width 都从它算 —— 两处各写
     一个数的话，改宽列表就会在中间裂出一条缝或者盖住第一列。 */
  --o-wsale-flyout-w: 17rem;
  position: relative;
  pointer-events: auto;
}

.o_wsale_mega_flyout_list {
  width: var(--o-wsale-flyout-w);
  max-width: 100%;
  padding: .5rem 0;
  background: var(--bs-body-bg, #fff);
  border: 1px solid var(--bs-border-color, #dee2e6);
  border-radius: var(--o-wsale-mega-radius, 0);
  box-shadow: 0 .5rem 1.5rem rgba(0, 0, 0, .14);
  /* 类目多到装不下时列表自己滚，不把页头撑掉半屏。 */
  max-height: min(70vh, 40rem);
  overflow-y: auto;
}

/* 浮出面板是 li 的**子节点**，定位却要相对整块 —— 所以 li 保持 static。
   给 li 设 relative 的话面板会贴着那一行，宽度也只剩一行的高度可用。 */
.o_wsale_mega_flyout_item {
  position: static;
}

.o_wsale_mega_flyout_link {
  display: flex;
  align-items: center;
  gap: .5rem;
  padding: .5rem 1rem;
  color: inherit;
  text-decoration: none;
  font-size: .95rem;
  line-height: 1.4;
}

.o_wsale_mega_flyout_name {
  flex: 1 1 auto;
  overflow: hidden;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
}

.o_wsale_mega_flyout_chevron {
  flex: 0 0 auto;
  opacity: .35;
  transition: opacity .15s ease;
}

.o_wsale_mega_flyout_item:hover > .o_wsale_mega_flyout_link,
.o_wsale_mega_flyout_item:focus-within > .o_wsale_mega_flyout_link {
  background: var(--bs-secondary-bg, #f8f9fa);
  color: var(--o-color-1, #714b67);
  font-weight: 600;
}

.o_wsale_mega_flyout_item:hover > .o_wsale_mega_flyout_link .o_wsale_mega_flyout_chevron {
  opacity: 1;
}

/* 「查看全部」压在最后一格，与类目行区分开（截断之后没有它，用户以为店里
   就这几个类目）。 */
.o_wsale_mega_flyout_more {
  margin-top: .25rem;
  padding-top: .25rem;
  border-top: 1px solid var(--bs-border-color, #dee2e6);
}

.o_wsale_mega_flyout_all {
  display: block;
  padding: .5rem 1rem;
  font-size: .9rem;
  font-weight: 600;
  color: var(--o-color-1, #714b67);
  text-decoration: none;
}

/* 浮出面板：贴着列表右边，**零间距**。留一条缝的话鼠标从列表移到面板的途中
   两边都不 hover，面板当场收起 —— 那条缝里没有任何东西能把 hover 接住，
   而面板本身是 li 的后代，只要一路都在 li 的盒子里 hover 就不会断。 */
.o_wsale_mega_flyout_panel {
  display: none;
  position: absolute;
  top: 0;
  left: var(--o-wsale-flyout-w);
  /* ★ 不能写 `calc(100% - ...)`：定位祖先是那颗菜单项（宽百来像素），算出来是负数，
     min() 取负、面板被夹成 0 宽 —— 表现是"停上去什么也没浮出来"。按视口算。 */
  /* --o-wsale-flyout-room：JS 量出来的「面板这一侧还剩多宽」；没量过回落到按视口估 */
  width: min(46rem, var(--o-wsale-flyout-room, calc(100vw - var(--o-wsale-flyout-w) - 4rem)));
  min-height: 100%;
  max-height: min(70vh, 40rem);
  overflow-y: auto;
  padding: 1.25rem 1.5rem;
  background: var(--bs-body-bg, #fff);
  border: 1px solid var(--bs-border-color, #dee2e6);
  border-left: 0;
  border-radius: 0 var(--o-wsale-mega-radius, 0) var(--o-wsale-mega-radius, 0) 0;
  box-shadow: 0 .5rem 1.5rem rgba(0, 0, 0, .14);
  z-index: 1;
}

.o_wsale_mega_flyout_item:hover > .o_wsale_mega_flyout_panel,
.o_wsale_mega_flyout_item:focus-within > .o_wsale_mega_flyout_panel {
  display: block;
}

/* 向左浮出：右边放不下、左边更宽时（JS 判）。面板贴着卡片**左**边，同样零间距 —— 面板仍是
   li 的后代，鼠标从列表横移过去 hover 不断。边框与圆角跟着换边。 */
.o_wsale_mega_flyout_left .o_wsale_mega_flyout_panel {
  left: auto;
  right: 100%;
  border-left: 1px solid var(--bs-border-color, #dee2e6);
  border-right: 0;
  border-radius: var(--o-wsale-mega-radius, 0) 0 0 var(--o-wsale-mega-radius, 0);
}

.o_wsale_mega_flyout_panel_head {
  margin-bottom: 1rem;
}

.o_wsale_mega_flyout_panel_title {
  display: inline-flex;
  align-items: center;
  gap: .35rem;
  font-size: 1.1rem;
  font-weight: 700;
  color: inherit;
  text-decoration: none;
}

.o_wsale_mega_flyout_panel_title:hover {
  color: var(--o-color-1, #714b67);
}

.o_wsale_mega_flyout_group_title {
  display: block;
  margin-bottom: .35rem;
  font-weight: 600;
  font-size: .95rem;
  color: inherit;
  text-decoration: none;
}

.o_wsale_mega_flyout_group_title:hover {
  color: var(--o-color-1, #714b67);
}

.o_wsale_mega_flyout_leaf {
  display: block;
  padding: .15rem 0;
  font-size: .875rem;
  color: var(--bs-secondary-color, #6c757d);
  text-decoration: none;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.o_wsale_mega_flyout_leaf:hover {
  color: var(--o-color-1, #714b67);
}

/* 窄屏与触屏：没有 hover 就没有"浮出"这回事 —— 展开成一份缩进的嵌套清单。
   ★ 这条同时兜住**手指**：`(hover: none)` 覆盖真正的触屏，而带触摸屏的笔记本
   仍按鼠标走（同 wsale_snippets.js 里 isTouchLike 的判据）。JS 一行都不用，
   建站器画布（<script> 被剥光）里因此也是对的。 */
@media (max-width: 991.98px), (hover: none) {
  .o_wsale_mega_flyout_list {
    width: 100%;
    max-height: none;
    overflow: visible;
    box-shadow: none;
  }
  .o_wsale_mega_flyout_panel {
    display: block;
    position: static;
    width: auto;
    max-height: none;
    overflow: visible;
    padding: 0 1rem .75rem 2rem;
    border: 0;
    border-radius: 0;
    box-shadow: none;
  }
  .o_wsale_mega_flyout_panel_head {
    display: none; /* 上面那行类目名就是标题，再来一遍是重复 */
  }
  .o_wsale_mega_flyout_chevron {
    transform: rotate(90deg);
    opacity: .5;
  }
}

/* 竖排导航（汉堡/侧栏）里同样按嵌套清单走：抽屉本来就窄，再浮一层出去会跑到
   屏幕外面。这里不能只靠上面那条宽度媒体查询 —— 侧栏版式在 ≥lg 也是竖排的。
   ★ 上面那组"锚到菜单项"的规则要在这里**逐条撤回**：它们与 header.css 的
     `.o_mega_menu_is_offcanvas .o_mega_menu` 特异度打平 (0,2,0)，而本文件加载在
     后面 —— 不撤的话抽屉里的面板会缩成卡片那么宽、且脱离随流排布。 */
.o_mega_menu_is_offcanvas .o_mega_menu:has(.o_wsale_mega_flyout) {
  position: static;
  width: 100%;
}

.o_mega_menu_is_offcanvas .o_wsale_mega_flyout_list {
  width: 100%;
  max-height: none;
  overflow: visible;
  box-shadow: none;
}

.o_mega_menu_is_offcanvas .o_wsale_mega_flyout_panel {
  display: block;
  position: static;
  width: auto;
  max-height: none;
  overflow: visible;
  padding: 0 1rem .75rem 2rem;
  border: 0;
  box-shadow: none;
}

/* ── 圆角：侧栏那个开关落在 section 上，看得见的却是卡片 ──────────
 * 「圆角」是通用开关（builtin_options 的 classOption('rounded')），它往**积木根节点**
 * 也就是 section 上加 bootstrap 的 rounded-* 类。可悬浮档里 section 是透明的舞台、
 * 图卡档里 section 只是底板 —— 圆的是卡片，卡片的 border-radius 写死在下面这几条
 * 规则里，于是"圆角：无"点了没反应，而类确实加上去了、两边代码看着都对。
 *
 * 把 section 上那组类换算成一个变量转发给卡片。**没有任何 rounded-* 类 = 没有圆角**
 * —— 只有这样"无"才真的是无（"无"这一档发出的是空字符串，也就是把类删掉，
 * 没法用"有没有类"以外的信号区分"没选过"和"选了无"）。想要圆角就在侧栏选一档。
 */
.s_mega_menu_wsale_categories            { --o-wsale-mega-radius: 0px; }   /* 带单位：图卡拿它进 max()，无单位的 0 在那里是数不是长度 */
.s_mega_menu_wsale_categories.rounded    { --o-wsale-mega-radius: var(--bs-border-radius, .375rem); }
.s_mega_menu_wsale_categories.rounded-1  { --o-wsale-mega-radius: var(--bs-border-radius-sm, .25rem); }
.s_mega_menu_wsale_categories.rounded-2  { --o-wsale-mega-radius: var(--bs-border-radius, .375rem); }
.s_mega_menu_wsale_categories.rounded-3  { --o-wsale-mega-radius: var(--bs-border-radius-lg, .5rem); }
.s_mega_menu_wsale_categories.rounded-4  { --o-wsale-mega-radius: var(--bs-border-radius-xl, 1rem); }
.s_mega_menu_wsale_categories.rounded-5  { --o-wsale-mega-radius: var(--bs-border-radius-xxl, 2rem); }
/* pill 在一张几百像素高的卡片上照抄 50rem 会削成橄榄球，夹到 1.5rem。 */
.s_mega_menu_wsale_categories.rounded-pill { --o-wsale-mega-radius: 1.5rem; }

/* ── ② 图卡（cards）────────────────────────────────────────────
 * 一级类目的图 + 名字铺成一排卡片。没传图的出名字，不出破图框（同品牌墙）。
 */
.o_wsale_mega_card {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: .5rem;
  height: 100%;
  padding: .75rem;
  border: 1px solid var(--bs-border-color, #dee2e6);
  /* 圆角取巨型菜单自己的「圆角」（上面那组 rounded-* 换算）与主题「类目卡片 ▸ 圆角」里大的那个：图卡也是类目卡片，
     主题那一项此前在这里不起作用（2026-10-24 用户报）。积木的「无」与「没选过」分不出来（见上），所以不能让积木整个盖过主题。 */
  border-radius: max(var(--o-wsale-mega-radius, 0px), var(--o-card-radius, 0px));
  background: var(--bs-body-bg, #fff);
  color: inherit;
  text-decoration: none;
}
/* 悬停、点击、叠层、名称位置、图片边框归 website 的 card_fx.css */

.o_wsale_mega_card_media {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  height: 5rem;
}

.o_wsale_mega_card_img {
  max-width: 100%;
  max-height: 100%;
  object-fit: contain;
}

/* 没传图时的占位图标。**不拿类目名顶替** —— 卡片下面那行本来就是名字，
   顶替的结果是同一个词上下印两遍（品牌墙那边名字是可关的，这里不是）。 */
.o_wsale_mega_card_ph {
  font-size: 2rem;
  color: var(--bs-border-color, #dee2e6);
}

.o_wsale_mega_card_name {
  font-size: .9rem;
  font-weight: 600;
  text-align: center;
  overflow: hidden;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
}

/* ══════════════════ 商品卡：字号跟着卡片宽度走 ══════════════════
 *
 * 每行商品数（/shop 的 shop_ppr、商品积木的 data-columns）调大之后，卡片窄到一半，
 * 名字、价格、按钮却还是一行三个时的字号 —— 名字折成四五行、价格挤成两行、
 * 「Add to Cart」溢出按钮。
 *
 * ★ 按**卡片自己的宽度**缩（容器查询），不按"每行几个"分档：同样是一行 4 个，
 *   有侧栏和没侧栏、1290 和 1600 的视口下卡片宽差出一倍；按 ppr 分档的话
 *   哪一档都只在一种布局下对。卡片宽到 ~300px 时与原来逐字相同（上限 1rem），
 *   窄到 ~160px 时降到 .75rem 封底。
 * ★ 只在 card-body 上定一个字号，里面一律 em 相对：说明（.small = .875em）、
 *   划线价与含税标注（<small>）跟着一起缩，不用逐个写。按钮例外：theme.css 直接写
 *   `.btn-sm { font-size: var(--o-btn-font-size-sm) }`（rem，主题页签可调），改
 *   Bootstrap 的 --bs-btn-font-size 毫无作用（第一版就是这么白写的，量出来按钮恒 14px）。
 *   这里取 min(主题值, .875em)：卡片够宽时就是主题值，窄了才跟着缩。
 * ★ 浏览器不认容器单位时整条 clamp 失效、落回原字号 —— 退化成改动前的样子，不会更坏。
 * ★ 只挂在**会变列数**的两种网格上（/shop 列表与搜索页预览、商品积木），不碰别处的 .oe_product。
 */
.o_wsale_products_grid .oe_product,
.o_wsale_snippet_grid .oe_product {
  container-type: inline-size;
}

.o_wsale_products_grid .oe_product .card-body,
.o_wsale_snippet_grid .oe_product .card-body {
  font-size: clamp(.75rem, .4rem + 3.2cqi, 1rem);
  padding: clamp(.5rem, 5.5cqi, 1rem);
}

/* 名字原是 h6（1rem）；随 card-body 走。 */
.o_wsale_products_grid .oe_product .card-title,
.o_wsale_snippet_grid .oe_product .card-title {
  font-size: 1em;
}

.o_wsale_products_grid .oe_product .card-body .btn-sm,
.o_wsale_snippet_grid .oe_product .card-body .btn-sm {
  font-size: min(var(--o-btn-font-size-sm, .875rem), .875em);
  padding-left: min(var(--o-btn-padding-x-sm, .5rem), max(.25rem, 3cqi));
  padding-right: min(var(--o-btn-padding-x-sm, .5rem), max(.25rem, 3cqi));
}

/* ══════════════════ 全部品牌总览（/shop/brands）══════════════════ */
/* 点字母跳到那一组：页头是 sticky 的，不留出这段，组标题正好被页头盖住。 */
/* 字母条也吸顶，还要再让出它的高度。页头（整个高度，不是此刻的下沿：往回跳时隐去的页头会重新出来）与字母条的高度
   由 shop_filters.js 量好写进变量；没有脚本时约等于 7.5rem。 */
.o_wsale_brand_group {
  scroll-margin-top: 7rem;
  scroll-margin-top: calc(var(--o-wsale-header-h, 4rem) + var(--o-wsale-letters-h, 3rem) + .5rem);
}
.o_wsale_brand_group_letter {
  flex: 0 0 2.5rem;
  padding-top: .75rem;
}
/* 总览上的卡片比品牌墙矮一截：多数品牌没有 logo，卡片里只有一行名字。 */
.o_wsale_brands_page .o_wsale_brand_card {
  padding: .75rem;
}
.o_wsale_brands_page .o_wsale_brand_logo_wrap {
  height: 2.5rem;
}
/* 字母条吸顶：滚到中间也能直接跳到别的字母。贴在吸顶页头的下沿（--o-wsale-fbar-top，与网店筛选条同一个变量，
   shop_filters.js 量页头；页头隐去时跟着上移），层级在页头（1020）下面。 */
.o_wsale_brand_letters {
  position: sticky;
  top: var(--o-wsale-fbar-top, 0px);
  z-index: 1010;
  padding: .5rem 0;
  background: var(--o-cc-bg, var(--o-body-bg, #ffffff));
  transition: box-shadow .2s;
}
.o_wsale_brand_letters.is-stuck {
  box-shadow: 0 8px 18px -14px rgba(0, 0, 0, .35);
}
.o_wsale_brand_letters .btn {
  min-width: 2.25rem;
}
/* 窄屏：27 个字母折成三四行，吸在顶上会占掉小半屏 —— 改成一行横滑。模板上是 Bootstrap 的 flex-wrap（!important），
   只能同样 !important 盖掉（改模板要升模块版本）。 */
@media (max-width: 767.98px) {
  .o_wsale_brand_letters.flex-wrap {
    flex-wrap: nowrap !important;
    overflow-x: auto;
    scrollbar-width: none;
    -webkit-overflow-scrolling: touch;
  }
  .o_wsale_brand_letters::-webkit-scrollbar { display: none; }
  .o_wsale_brand_letters .btn { flex: 0 0 auto; }
}

/* 品牌页页头的 logo（website_sale_site_templates.xml site_shop 的 o_wsale_brand_intro）：width/height 属性只用来占位防跳动，
   实际按 logo 自己的比例缩进 200×64 的框里——横长的字标与方形的徽标都不变形。 */
.o_wsale_brand_page_logo {
  display: block;
  width: auto;
  height: auto;
  max-width: min(200px, 100%);
  max-height: 64px;
  object-fit: contain;
}

/* 商品卡上的品牌标（shop_card_brand_logo）：压在商品图右下角的白底小签，不占正文高度（左上角是促销角标）。
   logo 是各家自己的宽高比：定高、限宽，横幅形的不会盖住半张图。 */
.o_wsale_card_brand {
  position: absolute;
  right: .5rem;
  bottom: .5rem;
  z-index: 2;
  display: inline-flex;
  align-items: center;
  max-width: calc(100% - 1rem);
  padding: .3rem .5rem;
  line-height: 1;
  background-color: rgba(255, 255, 255, .92);
  border-radius: .375rem;
  box-shadow: 0 1px 3px rgba(0, 0, 0, .15);
}
.o_wsale_card_brand_logo {
  display: block;
  width: auto;
  height: 27px;
  max-width: min(108px, 100%);
  object-fit: contain;
}
.o_wsale_card_brand_name {
  display: block;
  max-width: 10rem;
  overflow: hidden;
  font-size: .875rem;
  color: #495057;
  text-overflow: ellipsis;
  white-space: nowrap;
}
/* 便当 / 优站精选的名字与按钮压在图的下半部：签挪到右上角 */
.o_wsale_d_bento.oe_product .o_wsale_card_brand,
.o_wsale_d_showcase.oe_product .o_wsale_card_brand { top: .5rem; bottom: auto; }
/* Condensed 的图只有 3.5rem 宽，签放不下 */
.o_wsale_d_condensed.oe_product .o_wsale_card_brand { display: none; }

/* 商品详情页主图右下角的品牌标（product_page_brand_logo）：同卡片上的小签，大一号。 */
.o_wsale_product_brand {
  position: absolute;
  right: .75rem;
  bottom: .75rem;
  z-index: 2;
  display: inline-flex;
  align-items: center;
  max-width: calc(100% - 1.5rem);
  padding: .5rem .75rem;
  line-height: 1;
  background-color: rgba(255, 255, 255, .92);
  border-radius: .5rem;
  box-shadow: 0 1px 4px rgba(0, 0, 0, .15);
}
.o_wsale_product_brand_logo {
  display: block;
  width: auto;
  height: 42px;
  max-width: min(180px, 100%);
  object-fit: contain;
}
.o_wsale_product_brand_name {
  display: block;
  max-width: 14rem;
  overflow: hidden;
  font-size: 1rem;
  color: #495057;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* 品牌页介绍第一段之后收起的那几段：「展开阅读」是一行小字链接，不带浏览器默认的三角；展开后链接留在段落上面。 */
.o_wsale_brand_intro_more > summary {
  display: inline-block;
  color: var(--bs-link-color);
  cursor: pointer;
  list-style: none;
}
.o_wsale_brand_intro_more > summary::-webkit-details-marker {
  display: none;
}
.o_wsale_brand_intro_more[open] > summary .fa {
  transform: rotate(180deg);
}
.o_wsale_brand_intro_more[open] > summary {
  margin-bottom: .5rem;
}

/* ══════════════════ 商品卡设计（Products Design 的 11 套预设）══════════════════
 * Odoo 19 建站器那张下拉（网格一族 缩略图 / Chips / 卡片 / 表格 / 便当，列表一族 缩略图 / 卡片 /
 * 表格 / 优站精选 / Condensed / 大）。上游是 product_tile.scss 里一套 CSS 变量驱动的卡片，绑死在
 * 它自己的 products_item 结构上；本仓的卡片是 site_product_card / site_product_card_list，这里
 * 按上游各套的样子画（对着 website_sale/static/src/img/products_entries_design/*.svg 与那份 scss）。
 *
 * 分派：卡片根上的 o_wsale_d_<key>、网格容器上的 o_wsale_grid_d_<key>（Go 给，见 controller 的
 * shop_design.go）。缩略图 / 卡片 / 列表缩略图是 2.x 就有的三档，样子不动，这里没有它们的规则。
 * ★ 选择器一律带 .oe_product 凑够特异度：上面「卡片字号随卡宽」那组是 (0,3,0)，padding 写在那里。
 * ★ 图片上的 bg-light / object-fit-contain / p-3 是 Bootstrap 工具类（!important），要换掉只能也写 !important。
 */

/* 图贴着卡片边的那几套（缩略图 / 卡片 / 列表缩略图……）：图片层是方角、带底色，会压住卡片的圆角边框。
   只裁图片层，不给整张卡 overflow:hidden（那样正文溢出与颜色点的选中光环会一起被裁）。
   圆角 inherit 卡片自己的，各设计改过的圆角（表格 / Condensed 是 0）自动跟上；列表卡多隔一层 .row，让它也 inherit。
   Chips 的图内缩在卡里、自带圆角，不参与。 */
.card.oe_product:not(.o_wsale_d_chips) > .o_wsale_card_media {
  border-top-left-radius: inherit;
  border-top-right-radius: inherit;
  overflow: hidden;
}
.card.oe_product > .row { border-radius: inherit; }
.card.oe_product > .row > .o_wsale_card_media {
  border-top-left-radius: inherit;
  border-bottom-left-radius: inherit;
  overflow: hidden;
}

/* 网格卡左上角的角标（Sale / New!）：模板里它排在图片前面，而图片框也是定位元素、后来居上 ——
   角标从来都被商品图整个盖住（2026-10-24 量到：角标中心点 elementFromPoint 命中的是 <img>）。
   抬到图与卡片动效那层（card_fx.css 的 ::after，z-index 2）之上。 */
.oe_product > .badge.position-absolute { z-index: 3; }

/* 没有现成 ratio-* 的两种比例 */
.o_wsale_ratio_6x5 { --bs-aspect-ratio: 83.3333%; }
.o_wsale_ratio_2x3 { --bs-aspect-ratio: 150%; }

/* 表格那两套：没有间距、靠细线分格。/shop 的间距写在行内 style 上（--bs-gutter-*），
   自定义属性的 !important 照样盖过行内声明。 */
.o_wsale_grid_flush {
  --bs-gutter-x: 0px !important;
  --bs-gutter-y: 0px !important;
}
.o_wsale_grid_flush > *,
.o_wsale_grid_d_condensed > * {
  margin-bottom: 0 !important;
}
.o_wsale_grid_d_condensed { --bs-gutter-y: 0px !important; }

/* ── Chips：圆角描边卡，图内缩在卡里、自己带圆角；悬停浮起 ── */
.o_wsale_d_chips.oe_product {
  border-radius: var(--o-card-radius, 1rem);
  padding: .75rem;
}
.o_wsale_d_chips.oe_product .o_wsale_product_images {
  border-radius: .65rem;
  overflow: hidden;
}
.o_wsale_d_chips.oe_product .card-body { padding: .75rem 0 0; }

/* ── 表格：单元格之间一条细线，外框由容器补上边与左边 ── */
.o_wsale_grid_d_grid {
  border-top: 1px solid var(--bs-border-color, #dee2e6);
  border-left: 1px solid var(--bs-border-color, #dee2e6);
}
.o_wsale_d_grid.oe_product {
  border: 0;
  border-right: 1px solid var(--bs-border-color, #dee2e6);
  border-bottom: 1px solid var(--bs-border-color, #dee2e6);
  border-radius: 0;
  transition: background-color .2s ease;
}
.o_wsale_d_grid.oe_product:hover { background-color: rgba(0, 0, 0, .025); }
.o_wsale_d_grid.oe_product .o_wsale_product_images { border-radius: 0; }

/* ── 便当 / 优站精选：图铺满整张卡，名字、价格、按钮压在深色渐变上 ── */
.o_wsale_d_bento.oe_product,
.o_wsale_d_showcase.oe_product {
  border: 0;
  overflow: hidden;
  color: #fff;
  background-color: var(--o-cc5-bg, #212529);
}
.o_wsale_d_bento.oe_product { border-radius: var(--o-card-radius, .75rem); }
.o_wsale_d_showcase.oe_product { border-radius: 0; }
.o_wsale_d_bento.oe_product .o_wsale_product_images,
.o_wsale_d_showcase.oe_product .o_wsale_product_images {
  background-color: transparent !important;
}
.o_wsale_d_bento.oe_product .o_wsale_product_images img,
.o_wsale_d_showcase.oe_product .o_wsale_product_images img {
  object-fit: cover !important;
  padding: 0 !important;
}
.o_wsale_d_bento.oe_product .o_wsale_product_images::after,
.o_wsale_d_showcase.oe_product .o_wsale_product_images::after {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: linear-gradient(to top, rgba(0, 0, 0, .78) 0, rgba(0, 0, 0, .35) 45%, rgba(0, 0, 0, 0) 75%);
}
.o_wsale_d_showcase.oe_product .o_wsale_product_images::after {
  background: linear-gradient(90deg, rgba(0, 0, 0, .8) 0, rgba(0, 0, 0, .55) 38%, rgba(0, 0, 0, 0) 72%);
}
/* 正文压在图上：整块不吃指针，只有链接与按钮吃（否则点图片的大半面积点不进商品页） */
.o_wsale_d_bento.oe_product .card-body,
.o_wsale_d_showcase.oe_product .card-body {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  pointer-events: none;
  background: transparent;
}
.o_wsale_d_bento.oe_product .card-body :is(a, button, form, .o_wsale_cdots),
.o_wsale_d_showcase.oe_product .card-body :is(a, button, form, .o_wsale_cdots) { pointer-events: auto; }
.o_wsale_d_bento.oe_product .card-body :is(.card-title a, .text-muted, small),
.o_wsale_d_showcase.oe_product .card-body :is(.card-title a, .text-muted, small) { color: #fff !important; }
.o_wsale_d_bento.oe_product .card-body .text-muted,
.o_wsale_d_showcase.oe_product .card-body .text-muted { opacity: .8; }
/* 便当：描述悬停才出（上游 hover_show_description） */
.o_wsale_d_bento.oe_product .card-body > p {
  max-height: 0;
  overflow: hidden;
  margin: 0;
  opacity: 0;
  transition: max-height .35s ease, opacity .35s ease, margin .35s ease;
}
.o_wsale_d_bento.oe_product:hover .card-body > p,
.o_wsale_d_bento.oe_product:focus-within .card-body > p {
  max-height: 6em;
  margin-bottom: .5rem;
  opacity: 1;
}
.o_wsale_d_bento.oe_product .card-title { font-size: 1.15em; }
/* 优站精选：文字在左侧一栏，桌面 16:9 横幅；手机上图改方形、文字落到底部 */
.o_wsale_d_showcase.oe_product .card-body {
  top: 0;
  right: auto;
  width: min(45%, 34rem);
  justify-content: center;
  padding: clamp(1rem, 4cqi, 3rem);
}
.o_wsale_d_showcase.oe_product .card-title { font-size: clamp(1.1rem, 2.2cqi, 2rem); }
.o_wsale_d_showcase.oe_product .card-body .btn { width: auto !important; align-self: flex-start; }
.o_wsale_d_showcase.oe_product .card-body form { margin-top: .5rem !important; }
@media (max-width: 767.98px) {
  .o_wsale_d_showcase.oe_product .o_wsale_product_images { --bs-aspect-ratio: 100%; }
  .o_wsale_d_showcase.oe_product .o_wsale_product_images::after {
    background: linear-gradient(to top, rgba(0, 0, 0, .8) 0, rgba(0, 0, 0, .3) 50%, rgba(0, 0, 0, 0) 75%);
  }
  .o_wsale_d_showcase.oe_product .card-body { top: auto; right: 0; width: auto; }
}

/* ── 列表 · 卡片：描边圆角卡，图占满左栏整高并裁切 ── */
.o_wsale_d_list_cards.oe_product {
  border-radius: var(--o-card-radius, .75rem);
  overflow: hidden;
}
.o_wsale_d_list_cards.oe_product .o_wsale_product_images img {
  object-fit: cover !important;
  padding: 0 !important;
}
.o_wsale_d_list_cards.oe_product .card-body { padding: 1rem 1.25rem; }

/* ── 列表 · 表格：一行一格，上下细线；名字 / 描述 / 价格与按钮横着排 ── */
.o_wsale_grid_d_list_grid { border-top: 1px solid var(--bs-border-color, #dee2e6); }
.o_wsale_d_list_grid.oe_product {
  border: 0;
  border-bottom: 1px solid var(--bs-border-color, #dee2e6);
  border-radius: 0;
  background: transparent;
}
.o_wsale_d_list_grid.oe_product:hover { background-color: rgba(0, 0, 0, .025); }
.o_wsale_d_list_grid.oe_product .o_wsale_product_images { border-right: 1px solid var(--bs-border-color, #dee2e6); }
@media (min-width: 768px) {
  .o_wsale_d_list_grid.oe_product .card-body {
    flex-direction: row !important;
    flex-wrap: wrap;
    align-items: center;
    column-gap: 1.5rem;
  }
  .o_wsale_d_list_grid.oe_product .card-title { flex: 1 1 12rem; margin: 0 !important; }
  .o_wsale_d_list_grid.oe_product .card-body > p { flex: 2 1 16rem; margin: 0 !important; }
  .o_wsale_d_list_grid.oe_product .card-body > .d-flex { margin-top: 0 !important; flex: 0 0 auto; }
  /* 角标不占一格（横排时它会把名字挤到一边），压在这一格的左上角 */
  .o_wsale_d_list_grid.oe_product .card-body > .badge { position: absolute; top: .5rem; left: 1rem; }
}

/* ── Condensed：最紧凑的一行，小方图 + 名字 + 价格 + 按钮，不出描述与颜色点 ── */
.o_wsale_d_condensed.oe_product {
  border: 0;
  border-bottom: 1px solid var(--bs-border-color, #dee2e6);
  border-radius: 0;
  background: transparent;
}
.o_wsale_d_condensed.oe_product > .row > .col-auto { width: 3.5rem; padding: .35rem 0; }
.o_wsale_d_condensed.oe_product .o_wsale_product_images { border-radius: .35rem; overflow: hidden; height: auto !important; }
.o_wsale_d_condensed.oe_product .o_wsale_product_images img { padding: .15rem !important; }
.o_wsale_d_condensed.oe_product .card-body {
  flex-direction: row !important;
  align-items: center;
  gap: 1rem;
  padding: .35rem .75rem !important;
}
.o_wsale_d_condensed.oe_product .card-title { flex: 1 1 auto; margin: 0 !important; font-size: .95em; }
.o_wsale_d_condensed.oe_product .card-body > p,
.o_wsale_d_condensed.oe_product .card-body > .o_wsale_cdots,
.o_wsale_d_condensed.oe_product .card-body > .badge { display: none !important; }
.o_wsale_d_condensed.oe_product .card-body > .d-flex { margin-top: 0 !important; flex-wrap: nowrap !important; }
.o_wsale_d_condensed.oe_product .o_wsale_product_price { white-space: nowrap; }

/* ── 大：大图在左（约四成宽）、正文与描述在右，字号放大 ── */
.o_wsale_d_list_large.oe_product { border: 0; background: transparent; }
.o_wsale_d_list_large.oe_product .o_wsale_product_images { border-radius: .75rem; overflow: hidden; }
.o_wsale_d_list_large.oe_product .o_wsale_product_images img { object-fit: cover !important; padding: 0 !important; }
.o_wsale_d_list_large.oe_product .card-body { padding: 1rem 0 1rem 1.5rem; justify-content: center; }
.o_wsale_d_list_large.oe_product .card-title { font-size: 1.5em; margin-bottom: .5rem !important; }
.o_wsale_d_list_large.oe_product .card-body > p { font-size: 1em; flex-grow: 0 !important; }
.o_wsale_d_list_large.oe_product .card-body > .d-flex { margin-top: 1rem !important; justify-content: flex-start !important; }
@media (max-width: 767.98px) {
  .o_wsale_d_list_large.oe_product .card-body { padding: 1rem 0; }
}

/* ══════════════════ 商品轮播（s_wsale_products_carousel / data-layout=carousel）══════════════════
 * 一行横滑（scroll-snap），一屏几张由 --o-wsale-carousel-cols 给（Go 按「每行几个」算），手机上固定两张。
 * 两颗按钮翻一屏（wsale_snippets.js）；画布里脚本被剥，按钮不动但整行照样能横向滚，内容一张不少。 */
.o_wsale_carousel {
  --_cols: var(--o-wsale-carousel-cols, 4);
  --_gap: 1rem;
  position: relative;
}
.o_wsale_carousel_track {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: calc((100% - (var(--_cols) - 1) * var(--_gap)) / var(--_cols));
  gap: var(--_gap);
  overflow-x: auto;
  overscroll-behavior-x: contain;
  scroll-snap-type: x mandatory;
  scroll-behavior: smooth;
  scrollbar-width: none;
  padding-bottom: .25rem;
}
.o_wsale_carousel_track::-webkit-scrollbar { display: none; }
.o_wsale_carousel_item { scroll-snap-align: start; min-width: 0; }
.o_wsale_carousel_item .oe_product { container-type: inline-size; }
.o_wsale_carousel_item .oe_product .card-body {
  font-size: clamp(.75rem, .4rem + 3.2cqi, 1rem);
  padding: clamp(.5rem, 5.5cqi, 1rem);
}
.o_wsale_carousel_item .oe_product .card-title { font-size: 1em; }
@media (max-width: 767.98px) {
  .o_wsale_carousel { --_cols: 2; --_gap: .75rem; }
}
.o_wsale_carousel_btn {
  position: absolute;
  top: 40%;
  z-index: 2;
  width: 2.5rem;
  height: 2.5rem;
  border: 1px solid var(--bs-border-color, #dee2e6);
  border-radius: 50%;
  background: var(--bs-body-bg, #fff);
  color: var(--bs-body-color, #212529);
  box-shadow: 0 .25rem .75rem rgba(0, 0, 0, .12);
  transform: translateY(-50%);
  transition: opacity .2s ease;
}
.o_wsale_carousel_prev { left: -1.25rem; }
.o_wsale_carousel_next { right: -1.25rem; }
.o_wsale_carousel_btn[disabled] { opacity: 0; pointer-events: none; }
@media (max-width: 767.98px) {
  .o_wsale_carousel_prev { left: .25rem; }
  .o_wsale_carousel_next { right: .25rem; }
}

/* ══════════════════ 类目列表（s_wsale_category_list）══════════════════
 * 三种样子共用一份结构：卡片（封面 4:3 + 名字在下）、圆形（圆形封面 + 名字居中）、磁贴（小方图在左、名字与件数在右）。
 * 没有封面时出名字的第一个字。 */
.o_wsale_catlist_item {
  display: flex;
  flex-direction: column;
  height: 100%;
  color: inherit;
  text-decoration: none;
}
.o_wsale_catlist_item:hover { color: inherit; text-decoration: none; }
.o_wsale_catlist_media {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
  background: var(--o-cc2-bg, #f3f4f6);
}
.o_wsale_catlist_media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}
/* 悬停（放大封面等）归 website 的 card_fx.css */
.o_wsale_catlist_initial {
  font-size: 2rem;
  font-weight: 600;
  color: var(--o-color-1, #714b67);
  opacity: .6;
}
.o_wsale_catlist_text { display: flex; flex-direction: column; gap: .15rem; }
.o_wsale_catlist_name { font-weight: 600; line-height: 1.3; }
.o_wsale_catlist_count { font-size: .85em; opacity: .65; }

.o_wsale_catlist_cards .o_wsale_catlist_media { aspect-ratio: 4 / 3; border-radius: var(--o-card-radius, .75rem); }
.o_wsale_catlist_cards .o_wsale_catlist_text { padding: .65rem .15rem 0; }

.o_wsale_catlist_circles .o_wsale_catlist_item { align-items: center; text-align: center; }
.o_wsale_catlist_circles .o_wsale_catlist_media {
  width: min(100%, 9rem);
  aspect-ratio: 1;
  border-radius: 50%;
  box-shadow: 0 0 0 1px var(--bs-border-color, #dee2e6);
  transition: box-shadow .2s ease;
}
/* 悬停的光环 / 阴影归 website 的 card_fx.css（主题「类目卡片 ▸ 悬停」）：这里从前写死一圈主色，悬停选「无」也照样出 */
.o_wsale_catlist_circles .o_wsale_catlist_text { padding-top: .65rem; align-items: center; }

.o_wsale_catlist_tiles .o_wsale_catlist_item {
  flex-direction: row;
  align-items: center;
  gap: .75rem;
  padding: .6rem;
  border: 1px solid var(--bs-border-color, #dee2e6);
  border-radius: var(--o-card-radius, .6rem);
}
.o_wsale_catlist_tiles .o_wsale_catlist_media {
  flex: 0 0 3rem;
  width: 3rem;
  height: 3rem;
  border-radius: .45rem;
}
.o_wsale_catlist_tiles .o_wsale_catlist_initial { font-size: 1.25rem; }
.o_wsale_catlist_tiles .o_wsale_catlist_text { min-width: 0; }
.o_wsale_catlist_tiles .o_wsale_catlist_name {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* ══════════════════ 单品推介（s_wsale_product_spotlight）══════════════════ */
.o_wsale_spotlight_media {
  overflow: hidden;
  border-radius: 1rem;
  background: #fff;
  aspect-ratio: 1;
}
.o_wsale_spotlight_img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: contain;
  transition: transform .5s ease;
}
.o_wsale_spotlight_media:hover .o_wsale_spotlight_img { transform: scale(1.03); }
.o_wsale_spotlight_name { font-size: clamp(1.6rem, 1.1rem + 1.6vw, 2.5rem); }

/* ══════════════════ 商品滚动条（s_wsale_products_marquee / data-layout=marquee）══════════════════
 * 滚动本身是 website 的通用 .o_scroll_strip（snippets.css + website_runtime.js）；这里只定每张卡的宽度与卡片字号。 */
.o_wsale_marquee_item { width: var(--o-wsale-marquee-w, 15rem); align-self: stretch; }
.o_wsale_marquee_item .oe_product { height: 100%; container-type: inline-size; }
.o_wsale_marquee_item .oe_product .card-body { font-size: clamp(.75rem, .4rem + 3.2cqi, 1rem); padding: clamp(.5rem, 5.5cqi, 1rem); }
.o_wsale_marquee_item .oe_product .card-title { font-size: 1em; }
.o_wsale_marquee .o_scroll_strip_track { align-items: stretch; padding-block: .5rem; }
@media (max-width: 767.98px) { .o_wsale_marquee_item { width: 11rem; } }

/* ══════════════════ 加购提示（wsale_snippets.js 的 showCartToast）══════════════════
 * 加购改成异步之后页面不再刷新，没有这一句客户不知道点没点上。 */
#o_wsale_cart_toast {
  position: fixed; right: 1rem; bottom: 1rem; z-index: 1080;
  display: flex; align-items: center; gap: .75rem;
  max-width: calc(100vw - 2rem); padding: .65rem 1rem;
  border-radius: .5rem; background: #212529; color: #fff;
  box-shadow: 0 .5rem 1.5rem rgba(0, 0, 0, .2);
  font-size: .9rem; opacity: 0; transform: translateY(.5rem);
  pointer-events: none; transition: opacity .2s ease, transform .2s ease;
}
#o_wsale_cart_toast.o_show { opacity: 1; transform: none; pointer-events: auto; }
#o_wsale_cart_toast.o_wsale_cart_toast_warning { background: #842029; }
#o_wsale_cart_toast a { color: inherit; font-weight: 600; text-decoration: underline; white-space: nowrap; }
