/**
 * CUBX Theme — theme.css
 * Phase 1 : Variables DS H2J + layout pleine largeur
 * FIX v1.0.5 : --h2j-bg-card ajoutée, .cubx-homepage-fw pour full-width
 *
 * @author    H2J Ecosystem <info@2klove.fr>
 * @copyright 2024-2026 H2J sas RCS 978391720
 */

/* ═══════════════════════════════════════════════════════════
   1. VARIABLES CSS
   — --h2j-*  : Design System (BO + FO, consommées par tous les modules)
   — --cubx-* : Front-office CUBX (surchargées par H2JEcosystem Phase 2)
   ═══════════════════════════════════════════════════════════ */
:root {
  /* Couleurs DS — H2JEcosystem surcharge ces valeurs via <style> dans displayHeader */
  --h2j-primary:        #7c3aed;
  --h2j-primary-dark:   #6d28d9;
  --h2j-secondary:      #8b5cf6;
  --h2j-accent:         #f43f5e;
  --h2j-sidebar-bg:     #1a1f2c;
  --h2j-sidebar-text:   #ffffff;
  --h2j-bg:             #ffffff;
  --h2j-bg-light:       #f8f7ff;
  --h2j-bg-card:        #ffffff;
  --h2j-border:         #e5e7eb;
  --h2j-text:           #1a1f2c;
  --h2j-text-light:     #6b7280;
  --h2j-success:        #10b981;
  --h2j-warning:        #f59e0b;
  --h2j-error:          #ef4444;
  --h2j-info:           #3b82f6;
  --h2j-font:           'Inter', system-ui, -apple-system, sans-serif;
  --h2j-radius:         6px;

  /* Variables CUBX front-office
     Phase 1 : valeurs neutres
     Phase 2 : H2JEcosystem injecte les valeurs BO dans displayHeader */
  --cubx-accent:             var(--h2j-primary);
  --cubx-accent-2:           var(--h2j-primary-dark);
  --cubx-overlay-color:      transparent;
  --cubx-overlay-opacity:    0;
  --cubx-blend-mode:         normal;
  --cubx-grayscale:          0%;
  --cubx-font-primary:       var(--h2j-font);
  --cubx-radius:             var(--h2j-radius);
  --cubx-sidebar-w:          280px;
  --cubx-gallery-enabled:    0;
  --cubx-sticky-bg:          #ffffff;
  --cubx-sticky-border:      1px solid var(--h2j-border);
  --cubx-sticky-z:           900;

  /* v2.14.1 — Font sizes pilotées par H2JEcosystem (BO > Thème CUBX > Typography).
     Fallbacks 16px / 32px si h2jecosystem absent ou non configuré.
     Valeurs clampées server-side : base 12-24, heading 18-72. */
  --cubx-font-size-base:     16px;
  --cubx-font-size-heading:  32px;

  /* v2.21.0 — Form input design tokens (shared).
     Source unique de vérité pour la cohérence visuelle des champs de saisie
     dans tous les modules H2J (h2jforms, h2jphone, h2jdatepicker, h2jsecurity...).
     Tous les composants form lisent ces tokens via fallback :
        height: var(--cubx-input-height, 44px);
        padding: var(--cubx-input-padding-y, 10px) var(--cubx-input-padding-x, 14px);
        border: var(--cubx-input-border, 1px solid var(--h2j-border, #e5e7eb));
        font-size: var(--cubx-input-font-size, 15px);
     Override depuis h2jforms BO > Appearance prévu en Étape 3 (BO slider). */
  --cubx-input-height:         44px;
  --cubx-input-padding-y:      10px;
  --cubx-input-padding-x:      14px;
  --cubx-input-border-width:   1px;
  --cubx-input-border-color:   var(--h2j-border, #e5e7eb);
  --cubx-input-border:         var(--cubx-input-border-width) solid var(--cubx-input-border-color);
  --cubx-input-font-size:      15px;
  --cubx-input-bg:             var(--h2j-bg-card, #fff);
  --cubx-input-color:          var(--h2j-text, #1a1f2c);
  --cubx-input-placeholder:    var(--h2j-text-light, #6b7280);
  --cubx-input-focus-ring:     rgba(244, 63, 94, 0.12);
}

/* ═══════════════════════════════════════════════════════════
   2. BASE
   ═══════════════════════════════════════════════════════════ */

/* v2.5.80 — Utilitaires Bootstrap manquants en mode standalone CUBX.
   Avant v2.5.63, ces classes étaient chargées via Classic theme.css (Bootstrap 4).
   Depuis use_parent_assets:false, Bootstrap n'est plus chargé → les templates
   PS natifs (product.tpl, cart.tpl, etc.) qui utilisent .hidden, .sr-only, etc.
   se retrouvent avec ces classes inactives.

   On redéfinit ici le strict minimum nécessaire :
     - .hidden : utilisé sur input.product-refresh (form ATC), product-cover, etc.
     - .sr-only : utilisé dans nos swatches couleur + variants pour accessibilité
     - .invisible : pendant générique BS

   Pas besoin de tout Bootstrap, juste ces 3 utilitaires d'affichage. */
.hidden {
  display: none !important;
}

.invisible {
  visibility: hidden !important;
}

.sr-only {
  position: absolute !important;
  width: 1px !important;
  height: 1px !important;
  padding: 0 !important;
  margin: -1px !important;
  overflow: hidden !important;
  clip: rect(0, 0, 0, 0) !important;
  white-space: nowrap !important;
  border: 0 !important;
}

*, *::before, *::after {
  box-sizing: border-box;
}

html {
  /* v2.14.1 — Consomme --cubx-font-size-base pilotée par BO Thème CUBX > Typography.
     Fallback 16px. Attention : cette valeur définit le rem racine utilisé partout
     dans le thème (Bootstrap, body, formulaires…). Modifier cette var répercute
     l'agrandissement/réduction sur toute la typographie relative. */
  font-size: var(--cubx-font-size-base, 16px);
  -webkit-text-size-adjust: 100%;
}

body {
  font-family: var(--cubx-font-primary);
  font-size: 1rem;
  font-weight: 400;
  line-height: 1.5;
  color: var(--h2j-text);
  background-color: var(--h2j-bg);
  margin: 0;
}

a {
  color: var(--cubx-accent);
  text-decoration: none;
}

a:hover {
  color: var(--cubx-accent-2);
  text-decoration: underline;
}

img {
  max-width: 100%;
  height: auto;
}

/* v2.14.1 — Heading size scale pilotée par H2JEcosystem BO > Thème CUBX > Typography.
   h1 = --cubx-font-size-heading (absolu) ; h2..h4 = ratios descendants.
   Ces règles globales sont override par les règles plus spécifiques déjà en place
   (ex: .block-category h1.h1 avec clamp() pour le header catégorie responsive).
   C'est voulu : la SPEC permet de personnaliser ponctuellement un H1 spécifique
   tout en gardant un scale cohérent pour le reste du site. */
h1, .h1 {
  font-size: var(--cubx-font-size-heading, 32px);
  line-height: 1.15;
}
h2, .h2 {
  font-size: calc(var(--cubx-font-size-heading, 32px) * 0.75);
  line-height: 1.2;
}
h3, .h3 {
  font-size: calc(var(--cubx-font-size-heading, 32px) * 0.625);
  line-height: 1.25;
}
h4, .h4 {
  font-size: calc(var(--cubx-font-size-heading, 32px) * 0.5);
  line-height: 1.3;
}

/* ═══════════════════════════════════════════════════════════
   3. LAYOUT — Phase 1 pleine largeur
   Phase 2 ajoutera : #main-sidebar + #left_container
   ═══════════════════════════════════════════════════════════ */
#main {
  min-height: 100vh;
  display: flex;
  flex-direction: column;
}

#wrapper {
  flex: 1;
}

.container {
  max-width: 1280px;
  margin-left: auto;
  margin-right: auto;
  padding-left: 15px;
  padding-right: 15px;
}

#content-wrapper {
  padding: 20px 0;
}

/* ═══════════════════════════════════════════════════════════
   4. HEADER
   ═══════════════════════════════════════════════════════════ */
#header {
  background-color: var(--h2j-bg);
  box-shadow: 0 1px 4px rgba(0,0,0,0.08);
  position: sticky;
  top: 0;
  z-index: 800;
}

/* Barre nav supérieure (currency, langue, compte) */
.header-nav {
  background-color: var(--h2j-sidebar-bg);
  color: var(--h2j-sidebar-text);
  padding: 6px 0;
  font-size: 13px;
  overflow: visible;
  position: relative;
  z-index: 100;
}

.header-nav .container {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: 12px;
  flex-wrap: nowrap;
}

.header-nav a,
.header-nav button,
.header-nav .expand-more {
  color: var(--h2j-sidebar-text);
  background: none;
  border: none;
  cursor: pointer;
  font-size: 13px;
  padding: 0;
  text-decoration: none;
}

.header-nav a:hover {
  color: rgba(255,255,255,0.75);
  text-decoration: none;
}

/* Language & currency selectors — fix overflow and stacking */
.header-nav .language-selector,
.header-nav .currency-selector {
  position: relative;
}

.header-nav .language-selector .dropdown-menu,
.header-nav .currency-selector .dropdown-menu {
  right: 0;
  left: auto;
  min-width: 120px;
  z-index: 200;
}

/* Barre principale (logo + recherche + compte + panier) */
.header-top {
  padding: 12px 0;
  border-bottom: 1px solid var(--h2j-border);
}

.header-top .container {
  display: flex;
  align-items: center;
  gap: 20px;
}

/* Logo */
.header-logo {
  flex-shrink: 0;
}

#header .logo {
  display: block;
  max-height: 60px;
  width: auto;
}

/* Recherche — occupe l'espace central */
.header-search {
  flex: 1;
  max-width: 520px;
}

.header-search .search-widget {
  width: 100%;
}

.header-search .search-widget form {
  display: flex;
  align-items: center;
  position: relative;
}

.header-search .search-widget input[type="text"] {
  width: 100%;
  padding: 10px 40px 10px 14px;
  border: 1px solid var(--h2j-border);
  border-radius: var(--cubx-radius);
  font-size: 14px;
  color: var(--h2j-text);
  background: var(--h2j-bg);
  transition: border-color 0.2s;
}

.header-search .search-widget input[type="text"]:focus {
  border-color: var(--cubx-accent);
  outline: none;
  box-shadow: 0 0 0 3px rgba(124,58,237,0.1);
}

.header-search .search-widget button[type="submit"] {
  position: absolute;
  right: 4px;
  top: 50%;
  transform: translateY(-50%);
  background: none;
  border: none;
  color: var(--h2j-text-light);
  cursor: pointer;
  padding: 6px;
}

/* Bloc droite : compte + panier en ligne */
.header-right {
  display: flex;
  align-items: center;
  gap: 16px;
  flex-shrink: 0;
}

/* ps_customersignin — compact inline */
.header-right .user-info {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 13px;
  white-space: nowrap;
}

.header-right .user-info a {
  color: var(--h2j-text);
  text-decoration: none;
  display: flex;
  align-items: center;
  gap: 4px;
}

.header-right .user-info a:hover {
  color: var(--cubx-accent);
}

/* ps_shoppingcart — compact inline */
.header-right .blockcart {
  display: flex;
  align-items: center;
  white-space: nowrap;
}

.header-right .blockcart a {
  display: flex;
  align-items: center;
  gap: 6px;
  color: var(--h2j-text);
  text-decoration: none;
  font-size: 14px;
  font-weight: 600;
}

.header-right .blockcart a:hover {
  color: var(--cubx-accent);
}

/* Barre menu navigation */
.header-bottom {
  background: var(--h2j-bg);
  border-bottom: 1px solid var(--h2j-border);
  position: relative;   /* v1.4.12 : ancre pour le dropdown full-width (span 100vw) */
}

.header-bottom .container {
  display: flex;
  align-items: center;
}

/* ─── Bouton hamburger mobile (v1.4.14) ───────────────
   Injecté dans header.tpl dans .header-top .container, caché par défaut,
   révélé dans le @media (max-width: 768px) plus bas (section 16).
   L'animation vers croix se déclenche via .is-active (ajoutée par cubx-core.js). */
.cubx-menu-toggle {
  display: none;
  flex-direction: column;
  justify-content: center;
  gap: 5px;
  width: 40px;
  height: 40px;
  padding: 8px;
  background: none;
  border: 1px solid var(--h2j-border);
  border-radius: var(--cubx-radius);
  cursor: pointer;
  flex-shrink: 0;
  transition: background-color 0.2s, border-color 0.2s;
}
.cubx-menu-toggle:hover {
  background-color: var(--h2j-bg-light);
  border-color: var(--cubx-accent);
}
.cubx-menu-toggle:focus-visible {
  outline: 2px solid var(--cubx-accent);
  outline-offset: 2px;
}
.cubx-menu-toggle__bar {
  display: block;
  width: 22px;
  height: 2px;
  background: var(--h2j-text);
  border-radius: 2px;
  transform-origin: center;
  transition: transform 0.25s ease, opacity 0.2s ease;
}
.cubx-menu-toggle.is-active .cubx-menu-toggle__bar:nth-child(1) {
  transform: translateY(7px) rotate(45deg);
}
.cubx-menu-toggle.is-active .cubx-menu-toggle__bar:nth-child(2) {
  opacity: 0;
}
.cubx-menu-toggle.is-active .cubx-menu-toggle__bar:nth-child(3) {
  transform: translateY(-7px) rotate(-45deg);
}

/* ═══════════════════════════════════════════════════════════
   5. MENU (ps_mainmenu)
   ═══════════════════════════════════════════════════════════ */
/* v1.4.12 — Menu top (niveau 0).
   Cible explicitement [data-depth="0"] pour ne pas matcher les ul imbriqués
   qui ont aussi la classe .top-menu (ps_mainmenu les nomme toutes pareil).

   v1.4.12 : l'ancrage du dropdown est déporté sur .header-bottom (voir section 4)
   qui fait 100% du viewport — le dropdown peut donc s'étendre sur toute la largeur
   de l'écran. Le <ul> lui-même reste en position static (pas d'ancre). */
.top-menu[data-depth="0"] {
  display: flex;
  list-style: none;
  margin: 0;
  padding: 0;
  gap: 4px;
}

.top-menu[data-depth="0"] > li {
  position: static;    /* v1.4.11 : PAS relative, laisser .sub-menu s'ancrer sur .header-bottom */
  list-style: none;
}

.top-menu[data-depth="0"] > li > a,
.top-menu a[data-depth="0"] {
  display: block;
  padding: 8px 14px;
  color: var(--h2j-text);
  font-weight: 600;
  font-size: 14px;
  border-radius: var(--cubx-radius);
  transition: color 0.2s, background-color 0.2s;
  white-space: nowrap;
  text-decoration: none;
}

.top-menu[data-depth="0"] > li:hover > a,
.top-menu[data-depth="0"] > li > a:hover,
.top-menu a[data-depth="0"]:hover {
  color: var(--cubx-accent);
  background-color: var(--h2j-bg-light);
  text-decoration: none;
}

/* ════════════════════════════════════════════════════════════
   MEGA MENU DROPDOWN — Layout colonnes verticales (v1.4.4)
   Inspiration : theme Universal Chic, Concorde, Passage du Désir.

   Pattern :
   • Hover sur un item top (ex "Lovetoys") → ouvre un dropdown
   • Le dropdown affiche les enfants niveau 1 (ex "Godemichets", "Godes ceinture") en COLONNES
   • Chaque colonne = titre niveau 1 + ses enfants niveau 2 empilés VERTICALEMENT en dessous
   • Tout est visible d'un coup quand le dropdown est ouvert (pas de flyout cascade)

   Structure HTML attendue (ps_mainmenu) :
   <li.has-sub> "Lovetoys"                           ← niveau 0 (top)
     <ul.top-menu.sub-menu>                          ← dropdown niveau 1
       <li.has-sub> "Godemichets"                    ← colonne 1
         <ul.top-menu.sub-menu>                      ← enfants niveau 2 (empilés vertical)
           <li> "Godes classiques"
           <li> "Godes réalistes"
         </ul>
       </li>
       <li.has-sub> "Godes ceinture"                 ← colonne 2
         <ul.top-menu.sub-menu> ... </ul>
       </li>
     </ul>
   </li>
   ════════════════════════════════════════════════════════════ */

/* ════════════════════════════════════════════════════════════
   MEGA MENU DROPDOWN — v1.4.9 Structure réelle ps_mainmenu

   VRAIE structure HTML (vérifiée sur 2klove.fr) :

     <ul class="top-menu" data-depth="0">
       <li class="category">
         <a class="dropdown-item" data-depth="0">Lovetoys</a>
         <div class="popover sub-menu js-sub-menu collapse">
           <ul class="top-menu" data-depth="1">
             <li class="category">
               <a class="dropdown-item dropdown-submenu" data-depth="1">Godemichets</a>
               <div class="collapse">
                 <ul class="top-menu" data-depth="2">
                   <li><a data-depth="2">Godes classiques</a></li>
                 </ul>
               </div>
             </li>
           </ul>
         </div>
       </li>
     </ul>

   Points clés :
   • Le sub-menu est un <div class="popover sub-menu js-sub-menu collapse">, PAS un <ul>
   • Les <ul> imbriqués ont la classe .top-menu (pas .sub-menu)
   • Différenciés via attribut data-depth (0, 1, 2, 3...)
   • Bootstrap .collapse a display:none par défaut — on force à afficher
   • .dropdown-item.dropdown-submenu = items avec enfants niveau 2+
   ════════════════════════════════════════════════════════════ */

/* ── Chevron indicateur sur les items top qui ont un sub-menu ── */
.top-menu[data-depth="0"] > li:has(.sub-menu) > a::after {
  content: '▾';
  margin-left: 6px;
  font-size: 10px;
  opacity: 0.6;
}

/* ── Dropdown wrapper (le <div class="popover sub-menu js-sub-menu collapse">) ── */
/* Bootstrap .collapse = display:none par défaut. On override via display:none explicite
   puis on force display:flex au hover avec !important pour battre Bootstrap.

   v1.4.12 : Positionnement absolute par rapport à .header-bottom (position:relative,
   voir section 4), qui fait 100% du viewport. Le dropdown s'étend donc sur toute la
   largeur de l'écran, permettant d'afficher 6+ colonnes sans débordement latéral.
   Le padding utilise des valeurs viewport-based pour respecter les marges visuelles. */
.top-menu[data-depth="0"] > li > .sub-menu {
  position: absolute;
  top: 100%;
  left: 0;
  right: 0;
  display: none;
  min-width: 100%;
  max-width: none;
  padding: 20px max(20px, 5vw);   /* padding responsive : 5vw sur les côtés */
  margin: 0;
  background: var(--h2j-bg);
  border: 1px solid var(--h2j-border);
  border-top: 2px solid var(--cubx-accent);
  border-radius: 0 0 var(--cubx-radius) var(--cubx-radius);
  box-shadow: 0 6px 20px rgba(0, 0, 0, 0.12);
  z-index: 1000;
  /* Reset des styles Bootstrap .popover qui peuvent interférer */
  font-family: inherit;
  font-size: inherit;
  line-height: inherit;
  text-align: left;
  white-space: normal;
}

/* Révélation au hover — force display:flex via !important pour battre Bootstrap .collapse */
.top-menu[data-depth="0"] > li:hover > .sub-menu {
  display: flex !important;
  flex-direction: row;
  flex-wrap: nowrap;
  align-items: flex-start;
  gap: 24px;
}

/* v1.4.11 : plus besoin de la règle nth-last-child pour les 2 derniers items :
   le dropdown occupe toute la largeur du menu, donc pas de problème de débordement
   à droite pour les items de fin. */

/* ── Niveau 1 : ul.top-menu[data-depth="1"] enfant direct du .sub-menu ── */
/* ps_mainmenu génère un SEUL ul.top-menu[data-depth="1"] enfant du .sub-menu.
   On le transforme en conteneur flex pour que ses enfants <li> deviennent
   les colonnes du mega menu.

   v1.4.12 : justify-content: flex-start + flex-wrap: wrap pour que les colonnes
   restent compactes à gauche (pas étirées) et se replient si trop nombreuses.
   column-gap réduit pour plus de densité. */
.top-menu[data-depth="0"] > li > .sub-menu > .top-menu[data-depth="1"] {
  display: flex;
  flex-direction: row;
  flex-wrap: wrap;
  justify-content: flex-start;
  align-items: flex-start;
  column-gap: 32px;
  row-gap: 20px;
  list-style: none;
  margin: 0;
  padding: 0;
  width: 100%;
}

/* Colonnes du mega menu (items niveau 1) */
.top-menu[data-depth="1"] > li {
  position: static;
  list-style: none;
  margin: 0;
  padding: 0;
  min-width: 160px;
  max-width: 220px;    /* v1.4.12 : borne max pour empêcher l'étirement excessif */
  flex: 0 1 auto;      /* v1.4.12 : peut shrink si besoin, pas de grow */
}

/* Titre de colonne (le <a> niveau 1) — style "header".
   v1.4.12 : font-size légèrement réduit (12px) pour plus de compacité. */
.top-menu[data-depth="1"] > li > a,
.top-menu a[data-depth="1"] {
  display: block;
  padding: 0 0 8px 0;
  margin-bottom: 6px;
  color: var(--cubx-accent);
  font-weight: 700;
  font-size: 12px;
  text-transform: uppercase;
  letter-spacing: 0.3px;
  border-bottom: 1px solid var(--h2j-border);
  white-space: nowrap;
  text-decoration: none;
  transition: color 0.2s;
  background: none;
}

.top-menu[data-depth="1"] > li > a:hover,
.top-menu a[data-depth="1"]:hover {
  color: var(--cubx-accent-2);
  text-decoration: none;
  background: none;
  padding-left: 0;
}

/* ── Niveau 2 : wrapper .collapse + ul.top-menu[data-depth="2"] ── */
/* Les items niveau 2 sont dans un <div class="collapse"> (Bootstrap) qui masque
   par défaut. On force ce div à s'afficher toujours dans le contexte du mega menu. */
.top-menu[data-depth="1"] > li > .collapse {
  display: block !important;
  height: auto !important;
  visibility: visible !important;
}

/* Le ul niveau 2 : colonne verticale sous le titre.
   v1.4.12 : gap réduit pour serrer visuellement les items (moins d'espace vertical). */
.top-menu[data-depth="1"] > li > .collapse > .top-menu[data-depth="2"] {
  display: flex;
  flex-direction: column;
  gap: 0;
  list-style: none;
  padding: 0;
  margin: 0;
  width: 100%;
}

.top-menu[data-depth="2"] > li {
  position: static;
  list-style: none;
  margin: 0;
  padding: 0;
  width: 100%;
}

/* Items niveau 2 — v1.4.12 : font 12px + padding compact + white-space normal
   pour autoriser le retour à la ligne sur les libellés longs ("Crèmes & sprays intimes (H/F)"). */
.top-menu[data-depth="2"] > li > a,
.top-menu a[data-depth="2"] {
  display: block;
  padding: 3px 0;
  color: var(--h2j-text);
  font-weight: 400;
  font-size: 12px;
  line-height: 1.35;
  text-decoration: none;
  white-space: normal;
  transition: color 0.2s, padding-left 0.15s;
  background: none;
}

.top-menu[data-depth="2"] > li > a:hover,
.top-menu a[data-depth="2"]:hover {
  color: var(--cubx-accent);
  padding-left: 6px;
  background: none;
  text-decoration: none;
}

/* ── Niveau 3+ (sous-sous-catégories, rares) ── */
.top-menu[data-depth="2"] > li > .collapse {
  display: block !important;
  height: auto !important;
  visibility: visible !important;
}

.top-menu[data-depth="2"] > li > .collapse > .top-menu[data-depth="3"] {
  display: flex;
  flex-direction: column;
  padding-left: 12px;
  margin-top: 2px;
  list-style: none;
}

.top-menu a[data-depth="3"],
.top-menu a[data-depth="4"] {
  display: block;
  padding: 3px 0;
  color: var(--h2j-text-light);
  font-size: 12px;
  text-decoration: none;
}

.top-menu a[data-depth="3"]:hover,
.top-menu a[data-depth="4"]:hover {
  color: var(--cubx-accent);
}

/* ── Reset des ul internes (safety) ── */
.top-menu ul {
  list-style: none;
  padding: 0;
  margin: 0;
}

/* ═══════════════════════════════════════════════════════════
   6. PANIER
   ═══════════════════════════════════════════════════════════ */
.blockcart .cart-products-count {
  background-color: var(--cubx-accent);
  color: #ffffff;
  border-radius: 50%;
  font-size: 11px;
  font-weight: 700;
  padding: 1px 5px;
  min-width: 18px;
  text-align: center;
}

.blockcart a {
  color: var(--h2j-text);
}

/* ═══════════════════════════════════════════════════════════
   7. BREADCRUMB
   ═══════════════════════════════════════════════════════════ */
/* ═══════════════════════════════════════════════════════════
   7b. BREADCRUMB — v1.6.0 (Sprint 1 Catégorie)
   =========================================================
   Le partial _partials/breadcrumb.tpl produit un <ol class="breadcrumb">
   avec des <li class="breadcrumb-item"> (Schema.org BreadcrumbList).

   Par défaut le <ol> garde la numérotation ordinale 1. 2. 3. → on reset
   à list-style:none et on met en flex inline avec séparateur "\">\"" violet
   entre items.

   Mobile (< 768px) : on masque les items intermédiaires et on garde
   uniquement le parent direct + la catégorie courante, pour gagner
   de la largeur d'écran.

   Toggle visibility via setting H2JCUBX_CAT_SHOW_BREADCRUMB : piloté par
   la classe .cubx-hide-breadcrumb posée sur <body> si la valeur est 0.
   (à connecter en Lot 7 — plug settings BO).
   ═══════════════════════════════════════════════════════════ */
.breadcrumb {
  list-style: none;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0;
  padding: 12px 0;
  margin: 0 0 16px;
  background: transparent;
  font-size: 13px;
  color: var(--h2j-text-light);
  line-height: 1.4;
}

.breadcrumb-item {
  display: inline-flex;
  align-items: center;
  white-space: nowrap;
  max-width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* Séparateur ">" violet entre les items — injecté via ::before sur les
   items à partir du 2e. Évite de polluer le HTML avec des spans dédiés. */
.breadcrumb-item + .breadcrumb-item::before {
  content: ">";
  color: var(--cubx-accent, var(--h2j-primary, #7c4dff));
  margin: 0 10px;
  font-weight: 400;
  opacity: 0.6;
  flex-shrink: 0;
}

/* Liens des items parents — gris, hover souligné en couleur accent */
.breadcrumb-item a {
  color: var(--h2j-text-light);
  text-decoration: none;
  transition: color 0.15s, text-decoration 0.15s;
}

.breadcrumb-item a:hover {
  color: var(--cubx-accent, var(--h2j-primary, #7c4dff));
  text-decoration: underline;
}

/* Dernier item (catégorie courante) — non cliquable, plus foncé, gras léger */
.breadcrumb-item.active {
  color: var(--h2j-text, #1a1a1a);
  font-weight: 500;
}

.breadcrumb-item.active span {
  color: inherit;
}

/* Mobile : on ne garde que le parent direct + catégorie courante.
   Les items intermédiaires (Accueil, catégorie parent, sous-catégorie...) sont masqués
   pour gagner de la largeur sur petit écran. Le séparateur ">" reste visible devant
   la catégorie courante pour rappeler la hiérarchie.

   v2.5.196 : aligne sur la nouvelle règle de theme-category.css — on garde TOUJOURS
   Accueil (1er item) en plus des 2 derniers. Avant ce fix, Accueil était masqué sur
   mobile alors qu'il avait été remis dans le DOM en v2.5.193 via _partials/breadcrumb.tpl.
   Note : ce fichier garde la duplication des règles breadcrumb avec theme-category.css
   en attendant le cleanup global (cf. note d'en-tête de theme-category.css). */
@media (max-width: 768px) {
  .breadcrumb-item:not(:first-child):not(:nth-last-child(-n+2)) {
    display: none;
  }
  .breadcrumb {
    font-size: 12px;
    padding: 8px 0;
    margin-bottom: 12px;
  }
  .breadcrumb-item + .breadcrumb-item::before {
    margin: 0 6px;
  }
}

/* Toggle visibility via class body (sera posée par le thème quand
   H2JCUBX_CAT_SHOW_BREADCRUMB = 0 — plug en Lot 7). */
.cubx-hide-breadcrumb .breadcrumb,
.cubx-hide-breadcrumb nav[aria-label="Breadcrumb"] {
  display: none !important;
}

/* ═══════════════════════════════════════════════════════════
   Wrapper breadcrumb — v1.6.2 (Sprint 1 Catégorie)
   =========================================================
   Le breadcrumb est injecté dans le content column par category.tpl pour
   éviter (a) le chevauchement par le menu burger fixed, (b) la superposition
   par la hero gallery sticky.

   POSITIONNEMENT : on réplique la logique de .block-category (H1 catégorie) :
   wrapper flex avec justify-content:center → le breadcrumb est centré
   horizontalement comme le H1. Le burger à gauche ne masque jamais les
   éléments centrés. Aucun padding-left custom nécessaire.
   ═══════════════════════════════════════════════════════════ */
.cubx-cat-breadcrumb-wrap {
  display: flex;
  justify-content: center;
  padding: 20px 20px 0;
  position: relative;
  z-index: 5;
}

@media (max-width: 768px) {
  .cubx-cat-breadcrumb-wrap {
    /* v2.5.196 : flex-start + padding-left:60px pour ne pas chevaucher le
       menu burger fixed qui occupe les ~50px de gauche du viewport.
       Aligne sur la règle de theme-category.css. */
    justify-content: flex-start;
    padding: 12px 12px 0 60px;
  }
}

/* Retire le margin-bottom du breadcrumb interne car l'espacement avec le H1
   est déjà géré par le padding-bottom du wrapper et le padding-top de .block-category. */
.cubx-cat-breadcrumb-wrap .breadcrumb {
  margin: 0;
  padding: 0;
}

/* ═══════════════════════════════════════════════════════════
   8. LISTING PRODUITS — v2.3.0 (Sprint Catégorie 3 vues stables)
   =========================================================
   ANCIENNES rules legacy de la grille produits Classic SUPPRIMÉES.
   Elles forçaient :
     - .products desktop = 4 cols (var --cubx-cat-grid-cols-desktop)
     - .products @992px  = 3 cols HARDCODÉ (sans variable)
     - .products @768px  = 2 cols (var --cubx-cat-grid-cols-mobile)

   Ces rules entraient en conflit avec :
     - Notre override #js-product-list .products (section v2.3.0 en bas)
     - Les rules .cubx-cat-grid.products / cubx-cat-grid--with-ads
     - Les rules density body[data-cubx-density]
     - Les rules variant toggle (3 grilles séparées sprint 2D)

   La nouvelle source de vérité UNIQUE est la section v2.3.0 placée en
   fin de fichier, qui cible #js-product-list .products avec !important
   et consomme les 3 vars --cubx-cat-grid-cols-{no-hero|with-hero|mobile}
   selon body.cubx-hero-active state.
   ═══════════════════════════════════════════════════════════ */

/* Neutralisation du wrapper Classic PS autour de notre .hb-product.
   Classic wrappe chaque miniature dans <article class="product-miniature">
   avec parfois un .card interne. On remet à zéro border/padding/shadow
   pour que seul le rendu .hb-product soit visible. */
.products article.product-miniature,
.products .product-miniature,
.products article.js-product-miniature {
  background: transparent;
  border: 0 !important;
  border-radius: 0 !important;
  padding: 0 !important;
  margin: 0 !important;
  box-shadow: none !important;
  overflow: visible;
  list-style: none;
}

.products article.product-miniature > .card,
.products .product-miniature > .card {
  border: 0 !important;
  border-radius: 0 !important;
  box-shadow: none !important;
  background: transparent;
  overflow: visible;
  padding: 0 !important;
  margin: 0 !important;
}

/* Les styles .product-miniature .card / .product-title / .price / .regular-price
   deviennent inutiles car la miniature CUBX utilise .hb-product__* (stylisable
   via h2jhomeblocks.css chargé via hookDisplayHeader). Conservés pour fallback
   au cas où un module tiers rendrait une miniature Classic brute. */

.product-miniature .card {
  border: 1px solid var(--h2j-border);
  border-radius: var(--cubx-radius);
  overflow: hidden;
  transition: box-shadow 0.2s;
  height: 100%;
}

.product-miniature .card:hover {
  box-shadow: 0 4px 20px rgba(0,0,0,0.1);
}

.product-miniature .product-title a {
  color: var(--h2j-text);
  font-weight: 600;
  font-size: 14px;
}

.product-miniature .price {
  color: var(--cubx-accent);
  font-weight: 700;
  font-size: 16px;
}

.product-miniature .regular-price {
  color: var(--h2j-text-light);
  text-decoration: line-through;
  font-size: 13px;
}

/* Badges */
.product-flag {
  border-radius: var(--cubx-radius);
  font-weight: 700;
  font-size: 11px;
  padding: 3px 8px;
  text-transform: uppercase;
}

.product-flag.new { background-color: var(--h2j-success); color: #fff; }
.product-flag.on-sale,
.product-flag.discount { background-color: var(--cubx-accent); color: #fff; }

/* ═══════════════════════════════════════════════════════════
   9. BOUTONS
   ═══════════════════════════════════════════════════════════ */
.btn-primary,
.btn.btn-primary,
.add-to-cart {
  background-color: var(--cubx-accent);
  border-color: var(--cubx-accent);
  border-radius: var(--cubx-radius);
  font-weight: 600;
  transition: background-color 0.2s, border-color 0.2s;
  color: #ffffff;
}

.btn-primary:hover,
.btn.btn-primary:hover,
.add-to-cart:hover {
  background-color: var(--cubx-accent-2);
  border-color: var(--cubx-accent-2);
  color: #ffffff;
}

.btn-secondary,
.btn.btn-secondary {
  border-radius: var(--cubx-radius);
}

/* ═══════════════════════════════════════════════════════════
   10. FICHE PRODUIT
   ═══════════════════════════════════════════════════════════ */
.product-information .product-name,
h1.h1 {
  color: var(--h2j-text);
  font-weight: 700;
}

.product-information .current-price .price,
.product-prices .price {
  color: var(--cubx-accent);
  font-weight: 700;
  font-size: 24px;
}

.product-information .regular-price {
  color: var(--h2j-text-light);
  text-decoration: line-through;
}

/* Manufacturer / brand logo */
.cubx-product-brand {
  margin-bottom: 16px;
}

.cubx-product-brand img {
  max-height: 48px;
  width: auto;
}

/* Reference */
.product-reference {
  font-size: 13px;
  color: var(--h2j-text-light);
  margin-bottom: 12px;
}

.product-reference .label {
  font-weight: 600;
  color: var(--h2j-text);
  margin-right: 4px;
}

/* Features / Data sheet */
.product-features .h6 {
  font-size: 16px;
  font-weight: 700;
  color: var(--h2j-text);
  margin-bottom: 12px;
  padding-bottom: 8px;
  border-bottom: 2px solid var(--cubx-accent);
}

.data-sheet {
  display: grid;
  grid-template-columns: minmax(140px, auto) 1fr;
  gap: 0;
  border: 1px solid var(--h2j-border);
  border-radius: var(--cubx-radius);
  overflow: hidden;
}

.data-sheet dt,
.data-sheet dd {
  padding: 10px 14px;
  margin: 0;
  font-size: 14px;
  border-bottom: 1px solid var(--h2j-border);
}

.data-sheet dt {
  font-weight: 600;
  color: var(--h2j-text);
  background: #f8fafc;
}

.data-sheet dd {
  color: var(--h2j-text-light);
}

.data-sheet dt:last-of-type,
.data-sheet dd:last-of-type {
  border-bottom: none;
}

/* Specific references */
.product-specific-references .h6 {
  font-size: 14px;
  font-weight: 600;
  color: var(--h2j-text);
  margin-top: 20px;
  margin-bottom: 10px;
}

@media (max-width: 576px) {
  .data-sheet {
    grid-template-columns: 1fr;
  }
  .data-sheet dt {
    border-bottom: none;
    padding-bottom: 2px;
  }
  .data-sheet dd {
    padding-top: 2px;
  }
}

/* ═══════════════════════════════════════════════════════════
   11. DROPDOWN (currency, langue, compte)
   ═══════════════════════════════════════════════════════════ */
.dropdown-menu {
  border: 1px solid var(--h2j-border);
  border-radius: var(--cubx-radius);
  box-shadow: 0 4px 16px rgba(0,0,0,0.1);
  background: var(--h2j-bg);
  font-size: 13px;
}

.dropdown-item:hover,
.dropdown-item:focus {
  background-color: var(--h2j-bg-light);
  color: var(--cubx-accent);
}

/* ===========================================================
   12. FOOTER - v1.4.28 : container neutre
   ===========================================================
   Le footer complet (colonnes de liens, newsletter, copyright,
   reseaux sociaux) est desormais gere par le module h2jhomeblocks
   via le bloc "footer_columns" (17 types de blocs configurables).

   Le theme fournit juste un container transparent sans decoration
   qui laisse place au rendu du module. Aucun background, aucun
   padding, aucune marge : c'est h2jhomeblocks qui decide.

   Pour restaurer le footer natif classic (ps_linklist, etc.), il
   suffit de revenir a la version 1.4.26 ou anterieure de CUBX.
   =========================================================== */
#footer,
.footer-container {
  background: transparent;
  color: inherit;
  padding: 0;
  margin: 0;
  border: none;
}

.footer-container .container,
.footer-container .container-fluid {
  padding: 0;
  margin: 0;
  max-width: none;
  width: 100%;
}

.footer-container .footer-middle {
  display: block;
  padding: 0;
  margin: 0;
  gap: 0;
  grid-template-columns: none;
}

/* Legacy .footer-bottom retire dans footer.tpl - regle conservee
   en defense au cas ou un autre module l'injecte encore */
.footer-container .footer-bottom {
  display: none;
}

/* ═══════════════════════════════════════════════════════════
   13. FORMULAIRES
   ═══════════════════════════════════════════════════════════ */
/* v2.5.211 — Section 13 FORMULAIRES extraite dans theme-forms.css.
   Les règles .form-control, .form-control:focus, .form-group, labels,
   checkboxes, validation states sont maintenant dans le fichier dédié
   theme-forms.css (priority 217). Cette séparation permet :
     - Maintenance plus facile des inputs (un seul fichier à toucher)
     - Overlay BO h2jforms Appearance qui surcharge proprement les tokens
     - Nettoyage progressif de theme-core.css (objectif < 2000 lignes)

   Les tokens --cubx-input-* restent définis dans :root section 1 de
   theme-core.css car ils sont des design tokens globaux (et lus aussi
   par h2jphone-front.css, h2j-datepicker.css, h2jforms-front.css). */

/* ═══════════════════════════════════════════════════════════
   14. NOTIFICATIONS / ALERTES
   ═══════════════════════════════════════════════════════════ */
.alert-success { border-left: 4px solid var(--h2j-success); }
.alert-danger   { border-left: 4px solid var(--h2j-error); }
.alert-warning  { border-left: 4px solid var(--h2j-warning); }
.alert-info     { border-left: 4px solid var(--h2j-info); }

/* ═══════════════════════════════════════════════════════════
   15. PAGINATION
   ═══════════════════════════════════════════════════════════ */
.pagination-nav {
  margin: 32px 0 40px;
  padding: 24px 20px 20px;
  border-top: 1px solid var(--h2j-border, #e5e7eb);
  border-bottom: 1px solid var(--h2j-border, #e5e7eb);
  text-align: center;
}

.pagination-nav .pagination,
nav .pagination {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  align-items: center;
  gap: 6px;
  list-style: none;
  margin: 0 0 10px;
  padding: 0;
}

.pagination-nav .page-item,
nav .pagination .page-item {
  margin: 0;
  padding: 0;
  list-style: none;
}

/* v1.6.6 — Bouton pagination carré 40px, border fin, esprit cube CUBX.
   !important sur border-radius pour défendre contre Bootstrap. */
.pagination-nav .page-link,
nav .pagination .page-link {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 40px;
  height: 40px;
  padding: 0 10px;
  background: transparent;
  border: 1px solid var(--h2j-border, #e5e7eb);
  border-radius: 0 !important;
  color: var(--h2j-text, #1a1f2c);
  font-size: 13px;
  font-weight: 600;
  letter-spacing: 0.5px;
  line-height: 1;
  text-decoration: none;
  transition: background-color 0.15s ease, border-color 0.15s ease, color 0.15s ease;
  cursor: pointer;
  user-select: none;
}

.pagination-nav .page-link:hover,
nav .pagination .page-link:hover,
.pagination-nav .page-link:focus-visible,
nav .pagination .page-link:focus-visible {
  background: var(--h2j-bg-light, #f8f7ff);
  border-color: var(--cubx-accent, var(--h2j-primary, #7c3aed));
  color: var(--cubx-accent, var(--h2j-primary, #7c3aed));
  text-decoration: none;
  outline: none;
}

/* Active : fond accent solide, non-cliquable. Override Bootstrap .active */
.pagination-nav .page-item.active .page-link,
nav .pagination .page-item.active .page-link,
.pagination-nav .page-item.current .page-link,
nav .pagination .page-item.current .page-link {
  background-color: var(--cubx-accent, var(--h2j-primary, #7c3aed));
  border-color: var(--cubx-accent, var(--h2j-primary, #7c3aed));
  color: #ffffff;
  cursor: default;
  pointer-events: none;
  font-weight: 700;
}

/* Prev/Next chevrons — légèrement plus larges */
.pagination-nav .page-item:first-child .page-link,
.pagination-nav .page-item:last-child .page-link,
nav .pagination .page-item:first-child .page-link,
nav .pagination .page-item:last-child .page-link {
  min-width: 44px;
  font-size: 16px;
  font-weight: 700;
}

/* Disabled state (prev sur page 1, next sur dernière page) */
.pagination-nav .page-item.disabled .page-link,
nav .pagination .page-item.disabled .page-link {
  opacity: 0.35;
  cursor: not-allowed;
  pointer-events: none;
}

/* Texte "Showing X-Y of Z" — discret sous la pagination */
.pagination-nav .text-muted,
.pagination-nav > p {
  font-size: 12px;
  color: var(--h2j-text-light, #6b7280);
  margin: 0;
  padding: 0;
  text-transform: uppercase;
  letter-spacing: 0.8px;
  font-weight: 500;
}

/* Mobile : boutons légèrement plus petits, gap serré */
@media (max-width: 560px) {
  .pagination-nav {
    margin: 24px 0 28px;
    padding: 16px 10px 12px;
  }
  .pagination-nav .page-link,
  nav .pagination .page-link {
    min-width: 36px;
    height: 36px;
    font-size: 12px;
    padding: 0 8px;
  }
  .pagination-nav .pagination,
  nav .pagination {
    gap: 4px;
  }
}

/* ═══════════════════════════════════════════════════════════
   16. MOBILE
   ═══════════════════════════════════════════════════════════ */
@media (max-width: 768px) {
  .header-nav .container {
    justify-content: space-between;
  }

  /* v1.4.14 — Révèle le bouton hamburger + cache .header-bottom par défaut.
     Le bouton toggle #cubx-mobile-menu (.header-bottom) via cubx-core.js. */
  .cubx-menu-toggle {
    display: flex;
    order: 0;
    margin-right: 4px;
  }

  .header-bottom {
    display: none;
  }

  .header-bottom.is-open {
    display: block;
    animation: cubxMenuSlideDown 0.25s ease-out;
    /* v1.4.16 — Scrollable container : le body est locké (cubx-menu-open),
       donc le scroll doit être interne au menu. max-height calculée pour
       laisser visible la barre header-top (~60px) + header-nav (~30px). */
    position: absolute;
    top: 100%;
    left: 0;
    right: 0;
    max-height: calc(100vh - 90px);
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
    background: var(--h2j-bg);
    box-shadow: 0 8px 24px rgba(0, 0, 0, 0.15);
    z-index: 999;
  }

  /* v1.4.16 — Items niveau 0 en mobile : padding généreux pour le touch,
     bordures pleines largeur, font plus lisible. */
  .header-bottom.is-open .top-menu[data-depth="0"] > li > a,
  .header-bottom.is-open .top-menu a[data-depth="0"] {
    padding: 16px 20px;
    font-size: 16px;
    border-radius: 0;
    display: flex;
    align-items: center;
    justify-content: space-between;
  }

  .header-bottom.is-open .top-menu[data-depth="0"] > li {
    border-bottom: 1px solid var(--h2j-border);
  }

  .header-bottom.is-open .top-menu[data-depth="0"] > li:last-child {
    border-bottom: none;
  }

  /* Items niveau 1 (dans les sub-menus ouverts) : indent + plus discret */
  .header-bottom.is-open .top-menu[data-depth="1"] > li > a,
  .header-bottom.is-open .top-menu a[data-depth="1"] {
    padding: 12px 20px 12px 36px;
    font-size: 14px;
    font-weight: 600;
    background: var(--h2j-bg-light);
  }

  /* Items niveau 2 : encore plus indentés, lighter */
  .header-bottom.is-open .top-menu[data-depth="2"] > li > a,
  .header-bottom.is-open .top-menu a[data-depth="2"] {
    padding: 10px 20px 10px 52px;
    font-size: 13px;
    font-weight: 400;
    color: var(--h2j-text-light);
  }

  /* v1.4.17 — Fix chevrons menu mobile.
     ps_mainmenu rend <span class="float-xs-right hidden-md-up">
        <span class="navbar-toggler collapse-icons" data-toggle="collapse">
          <i class="material-icons add">expand_more</i>
          <i class="material-icons remove">expand_less</i>
        </span>
     </span>
     Sans le CSS natif ps_mainmenu (caché par hidden-sm-down), les 2 icônes
     s'empilent et notre chevron ▾ ::after fait doublon. On reproduit le
     toggle Bootstrap et on repositionne tout proprement. */

  /* Neutraliser notre chevron ▾ ::after qui fait doublon avec collapse-icons */
  .header-bottom.is-open .top-menu[data-depth="0"] > li:has(.sub-menu) > a::after {
    content: none;
  }

  /* L'item top devient relatif pour ancrer le chevron en absolute */
  .header-bottom.is-open .top-menu[data-depth="0"] > li {
    position: relative;
  }

  /* Make room for the chevron à droite */
  .header-bottom.is-open .top-menu[data-depth="0"] > li > a,
  .header-bottom.is-open .top-menu[data-depth="0"] > li > a[data-depth="0"] {
    padding-right: 56px;
  }

  /* Repositionner le wrapper .float-xs-right en absolute à droite, centré */
  .header-bottom.is-open .float-xs-right {
    position: absolute;
    right: 12px;
    top: 14px;
    display: flex;
    align-items: center;
    margin: 0;
    padding: 0;
  }

  .header-bottom.is-open .collapse-icons {
    display: inline-flex;
    align-items: center;
    cursor: pointer;
    padding: 6px;
    background: none;
    border: none;
  }

  .header-bottom.is-open .collapse-icons .material-icons {
    font-size: 24px;
    color: var(--h2j-text);
    line-height: 1;
  }

  /* Réimplémentation du toggle add/remove (normalement fourni par ps_mainmenu).
     Défaut : on montre add (chevron bas), on cache remove (chevron haut). */
  .header-bottom.is-open .collapse-icons .remove {
    display: none;
  }
  .header-bottom.is-open .collapse-icons .add {
    display: inline-flex;
  }
  /* Quand le collapse est ouvert (Bootstrap retire .collapsed ou met aria-expanded) */
  .header-bottom.is-open .collapse-icons:not(.collapsed) .add,
  .header-bottom.is-open .collapse-icons[aria-expanded="true"] .add {
    display: none;
  }
  .header-bottom.is-open .collapse-icons:not(.collapsed) .remove,
  .header-bottom.is-open .collapse-icons[aria-expanded="true"] .remove {
    display: inline-flex;
  }

  /* v1.4.14 — Force l'affichage des wrappers ps_mainmenu qui sont masqués
     par le CSS natif du module sous 992px. Sans ça, .header-bottom s'ouvre
     mais son contenu reste invisible (display:none hérité de ps_mainmenu). */
  .header-bottom.is-open #_desktop_top_menu,
  .header-bottom.is-open .js-top-menu,
  .header-bottom.is-open .menu,
  .header-bottom.is-open > .container > div {
    display: block !important;
  }

  .header-bottom.is-open .top-menu[data-depth="0"] {
    display: flex !important;
  }

  /* v1.4.18 — Sub-menus collapsés par défaut, révélés par .show
     (toggle via cubx-core.js initMobileSubmenuToggle, vu que Bootstrap JS
     n'est pas chargé dans CUBX). Sans cette règle les sub-menus restent
     ouverts en permanence à cause des overrides .menu/.js-top-menu ci-dessus. */
  .header-bottom.is-open .popover.sub-menu,
  .header-bottom.is-open .js-sub-menu,
  .header-bottom.is-open .top-menu[data-depth="1"] > li > .collapse,
  .header-bottom.is-open .top-menu[data-depth="2"] > li > .collapse {
    display: none !important;
    height: auto !important;
    visibility: visible !important;
    /* Reset des styles desktop hover popover */
    position: static !important;
    box-shadow: none !important;
    border: none !important;
    border-top: 1px solid var(--h2j-border) !important;
    background: var(--h2j-bg-light) !important;
    padding: 0 !important;
    min-width: 0 !important;
    max-width: none !important;
    border-radius: 0 !important;
  }

  .header-bottom.is-open .popover.sub-menu.show,
  .header-bottom.is-open .js-sub-menu.show,
  .header-bottom.is-open .top-menu[data-depth="1"] > li > .collapse.show,
  .header-bottom.is-open .top-menu[data-depth="2"] > li > .collapse.show {
    display: block !important;
  }

  /* Sub-menus en stack vertical (override des règles desktop flex row) */
  .header-bottom.is-open .popover.sub-menu .top-menu[data-depth="1"],
  .header-bottom.is-open .js-sub-menu .top-menu[data-depth="1"] {
    display: flex !important;
    flex-direction: column !important;
    flex-wrap: nowrap !important;
    gap: 0 !important;
    column-gap: 0 !important;
    row-gap: 0 !important;
    width: 100% !important;
  }

  .header-bottom.is-open .top-menu[data-depth="1"] > li {
    width: 100% !important;
    min-width: 0 !important;
    max-width: none !important;
  }

  /* Reset titre niveau 1 desktop (transform uppercase, border-bottom, etc.)
     pour ressembler aux items niveau 0 */
  .header-bottom.is-open .top-menu[data-depth="1"] > li > a {
    text-transform: none !important;
    letter-spacing: 0 !important;
    border-bottom: none !important;
    margin-bottom: 0 !important;
    color: var(--h2j-text) !important;
  }

  .header-bottom.is-open .container {
    display: block;
    padding-top: 8px;
    padding-bottom: 8px;
  }

  @keyframes cubxMenuSlideDown {
    from { opacity: 0; transform: translateY(-8px); }
    to   { opacity: 1; transform: translateY(0);    }
  }

  /* Lock du scroll body quand menu ouvert (évite le double-scroll) */
  body.cubx-menu-open {
    overflow: hidden;
  }

  .header-top .container {
    flex-wrap: wrap;
  }

  .header-logo {
    order: 1;
  }

  .header-right {
    order: 2;
    margin-left: auto;
  }

  .header-search {
    order: 3;
    flex-basis: 100%;
    max-width: none;
    margin-top: 8px;
  }

  #header .logo {
    max-height: 44px;
  }

  /* v1.4.9 — Menu mobile : layout vertical + sub-menus via Bootstrap .collapse.
     Sur mobile, ps_mainmenu utilise le comportement Bootstrap natif (data-toggle="collapse")
     qui ajoute la classe .show au .collapse quand l'utilisateur tape sur un item.
     On laisse Bootstrap gérer l'ouverture/fermeture, on stylise juste les positions. */
  .header-bottom .top-menu[data-depth="0"] {
    flex-direction: column;
    gap: 0;
    width: 100%;
  }

  .header-bottom .top-menu[data-depth="0"] > li {
    width: 100%;
    border-bottom: 1px solid var(--h2j-border);
  }

  /* Sur mobile, les sub-menus passent en static (pas absolute) et se révèlent via Bootstrap */
  .header-bottom .top-menu[data-depth="0"] > li > .sub-menu {
    position: static;
    min-width: 0;
    max-width: none;
    box-shadow: none;
    border: none;
    border-top: 1px solid var(--h2j-border);
    border-radius: 0;
    padding: 0 0 0 16px;
    background: var(--h2j-bg-light);
  }

  /* Mobile : quand Bootstrap ajoute .show à un .collapse, on l'affiche en block vertical */
  .header-bottom .top-menu[data-depth="0"] > li > .sub-menu.show,
  .header-bottom .top-menu[data-depth="0"] > li > .sub-menu.in {
    display: block !important;
  }

  /* Mobile : le layout du niveau 1 passe en colonne simple (pas de mega menu) */
  .header-bottom .top-menu[data-depth="0"] > li > .sub-menu > .top-menu[data-depth="1"] {
    flex-direction: column;
    gap: 0;
  }

  .header-bottom .top-menu[data-depth="1"] > li {
    width: 100%;
    min-width: 0;
  }

  /* Mobile : les wrappers .collapse niveau 2 restent masqués par défaut, Bootstrap gère */
  .header-bottom .top-menu[data-depth="1"] > li > .collapse {
    display: none !important;
  }
  .header-bottom .top-menu[data-depth="1"] > li > .collapse.show,
  .header-bottom .top-menu[data-depth="1"] > li > .collapse.in {
    display: block !important;
    padding-left: 16px;
  }
}

/* ═══════════════════════════════════════════════════════════
   17. HOMEPAGE FULL-WIDTH (FIX v1.0.5 → v1.3.1)
   content_wrapper sans .container pour que les homeblocks
   (hero, ticker, grilles) occupent toute la largeur.

   v1.3.1 : Le parent Classic wrappe #content-wrapper dans
   <div class="container"><div class="row">…</div></div>.
   Ces deux wrappers imposent max-width:1280px + gutters Bootstrap,
   ce qui empêchait .cubx-homepage-fw de prendre toute la largeur.
   Fix : neutraliser container + row UNIQUEMENT sur body.page-index
   pour que la homepage occupe 100vw sans toucher aux autres pages.
   ═══════════════════════════════════════════════════════════ */
.cubx-homepage-fw {
  padding: 0;
  margin: 0;
  max-width: none;
}

/* v1.3.1 : libère la homepage de la contrainte .container + .row du parent Classic */
body.page-index #wrapper > .container {
  max-width: none;
  padding-left: 0;
  padding-right: 0;
  width: 100%;
}
body.page-index #wrapper > .container > .row {
  margin-left: 0;
  margin-right: 0;
}
body.page-index #content-wrapper.cubx-homepage-fw {
  padding-left: 0;
  padding-right: 0;
}

/* ===========================================================
   17b. CATEGORY PAGE HERO FULL-WIDTH FIX — v1.6.6 + v2.5.197 (extended)
   =========================================================
   Même logique que section 17 (homepage full-width) mais appliquée à la
   page catégorie quand une hero gallery est active. Sans ça :
     - .cubx-hero-panel : position:fixed + width:38% → 38% du VIEWPORT
     - .cubx-hero-content : margin-left:38% → 38% du PARENT (container
        Bootstrap limité à 1280px, donc 487px au lieu de 730px sur 1920px)
   Résultat : gap blanc visible entre la fin de la hero (bord droit du pan-
   neau fixé) et le début des blocs produits (début du content column
   décalé de 38% du container).

   Fix : neutraliser le container Bootstrap + row sur body#category quand
   une hero est active, comme on le fait déjà sur body.page-index. Les
   règles internes de la page cat (toolbar, breadcrumb, block-category,
   products grid) ont déjà leur propre padding donc rien ne casse.

   v2.5.197 — Extension aux pages listing spéciales (new-products,
   prices-drop, best-sales) qui rencontraient le même problème sur mobile :
   la hero gallery s'affichait avec des marges blanches latérales (héritées
   du .container Bootstrap 1280px + padding 15px) au lieu de prendre toute
   la largeur du viewport. Bug visuel reporté par David sur /nouveaux-produits
   en mobile (08/05 nuit). La section 24 générique avec body:has(.cubx-hero-active)
   neutralisait bien le container desktop, mais avait un override mobile (≤991px)
   qui restaurait .container 1280px + padding 15px — ce qui marche pour les pages
   où la hero passe en "sticky natural" mais pas pour les pages listing spéciales
   où le hero panel reste en mode static dans le flow.
   Fix v2.5.197 : appliquer la règle stricte sans override mobile (même approche
   que body#category) pour body.page-new-products, body.page-prices-drop,
   body.page-best-sales. Les autres pages avec hero (cms, contact, etc.)
   continuent à utiliser la règle section 24 générique qui passe en sticky
   mobile.

   v2.5.199 — Extension à body.page-cms (Sprint front V3) : même problème
   constaté sur les pages /content/X-slug. La règle générique section 24 ne
   suffisait pas car son override mobile @media(max-width:991px) restaurait
   .container 1280px + padding 15px, créant des marges blanches sur le hero
   gallery des CMS sur mobile (visible iPhone reporté par David).

   v2.5.207 — Extension aux pages customer/* (Sprint front V3 cont.) : même
   problème constaté sur le dashboard "Mon compte" et toutes les sub-pages
   (identity, addresses, address, history, order-detail, order-slip, discount).
   Capture iPhone reportée par David sur /fr/adresses (form "Mettre à jour
   votre adresse") montrait le hero gallery iDYLL avec marges blanches au
   lieu de full-width. Pattern identique à P-066 / v2.5.197 : la règle
   générique section 24 a un override mobile qui restaure .container 1280px,
   donc on étend la règle stricte (sans override mobile) à tous les
   controllers customer concernés. Body classes pages customer (vérifié
   page /fr/mon-compte) :
     body.page-my-account             → /mon-compte (dashboard)
     body.page-customer-account       → alias possible selon controller
     body.page-identity               → /identite (Information form)
     body.page-addresses              → /adresses (liste)
     body.page-address                → /adresse (form add/edit)
     body.page-history                → /historique-commandes
     body.page-order-slip             → /avoirs (Credit slips)
     body.page-discount               → /bons-reduction (vouchers)
     body.page-order-detail           → /commande?id_order=N (détail commande)

   v2.5.210 — Extension aux pages contact + stores + sitemap (Sprint front V3 cont.) :
   même problème constaté sur /fr/nous-contacter (page-contact),
   /fr/magasins (page-stores) et /fr/plan-site (page-sitemap) reporté par David.
   Pattern strictement identique aux pages customer/* — le hero gallery est
   actif (mode_auto) mais la règle s24 générique avec override mobile crée
   des marges blanches sur mobile. Body classes ajoutées :
     body.page-contact                → /nous-contacter (Contact PS)
     body.page-stores                 → /magasins (Stores PS)
     body.page-sitemap                → /plan-site (Sitemap PS natif)

   v2.5.212 — Extension aux 3 surfaces custom h2jforms (Sprint front V3 cont.) :
   même problème constaté sur /connexion-h2j, /inscription-h2j et /contact-h2j
   (LOT 13 à venir). Le hero gallery est actif (mode_auto), mais sans la
   whitelist ci-dessous, le widget Turnstile et les autres composants du form
   custom héritaient des marges blanches latérales sur mobile (héritées du
   .container Bootstrap 1280px + padding 15px de la règle s24 générique qui
   restaure le container sur mobile). Pattern strictement identique à P-066
   déjà appliqué sur customer/* + contact/stores/sitemap : règle stricte sans
   override mobile pour garantir le full-width sur tous les viewports.

   Body classes ajoutées — PrestaShop Classic 8.x génère pour les
   ModuleFrontController 2 patterns parallèles :
     body#module-h2jforms-register     → ID (sélecteur primaire)
     body.page-module-h2jforms-register → class (sélecteur secondaire)
     idem pour login + contact

   On utilise les 2 par défense en profondeur : si une version de PS ne pose
   qu'un des 2, l'autre est juste inerte (cost zero). Résout aussi le titre
   tronqué "eate an account" derrière le burger megamenu mobile signalé par
   David sur les captures session 13/05 (le breadcrumb natif PS qui s'affichait
   par-dessus est masqué par theme-cms.css section 3 également étendu en
   v2.5.212 aux 3 mêmes body classes).

   URLs ciblées (montées par h2jforms.php hookModuleRoutes) :
     /inscription-h2j → module=h2jforms&controller=register (LOT 12 ✅)
     /connexion-h2j   → module=h2jforms&controller=login    (LOT 11 ✅)
     /contact-h2j     → module=h2jforms&controller=contact  (LOT 13 ⏳)

   La 3e surface (contact-h2j) est ajoutée dès maintenant en avance — le
   controller n'existe pas encore mais la règle CSS sera juste inerte tant que
   le LOT 13 n'est pas livré (zero risque, façon naturelle de préparer
   l'ouverture progressive de la grille Native Forms Takeover).

   Sélecteur :has(.cubx-hero-active) cible la page UNIQUEMENT quand la
   gallery est active (setting BO H2JCUBX_HERO_*_ENABLED = 1). Sans hero,
   le container Bootstrap reste normal et la page garde son centrage.
   Support :has() : Chrome 105+, Safari 15.4+, Firefox 121+ (tous green 2024+).
   =========================================================== */
body#category:has(.cubx-hero-active) #wrapper > .container,
body.page-new-products:has(.cubx-hero-active) #wrapper > .container,
body.page-prices-drop:has(.cubx-hero-active) #wrapper > .container,
body.page-best-sales:has(.cubx-hero-active) #wrapper > .container,
body.page-cms:has(.cubx-hero-active) #wrapper > .container,
body.page-my-account:has(.cubx-hero-active) #wrapper > .container,
body.page-customer-account:has(.cubx-hero-active) #wrapper > .container,
body.page-identity:has(.cubx-hero-active) #wrapper > .container,
body.page-addresses:has(.cubx-hero-active) #wrapper > .container,
body.page-address:has(.cubx-hero-active) #wrapper > .container,
body.page-history:has(.cubx-hero-active) #wrapper > .container,
body.page-order-slip:has(.cubx-hero-active) #wrapper > .container,
body.page-discount:has(.cubx-hero-active) #wrapper > .container,
body.page-order-detail:has(.cubx-hero-active) #wrapper > .container,
body.page-contact:has(.cubx-hero-active) #wrapper > .container,
body.page-stores:has(.cubx-hero-active) #wrapper > .container,
body.page-sitemap:has(.cubx-hero-active) #wrapper > .container,
body#module-h2jforms-register:has(.cubx-hero-active) #wrapper > .container,
body.page-module-h2jforms-register:has(.cubx-hero-active) #wrapper > .container,
body#module-h2jforms-login:has(.cubx-hero-active) #wrapper > .container,
body.page-module-h2jforms-login:has(.cubx-hero-active) #wrapper > .container,
body#module-h2jforms-contact:has(.cubx-hero-active) #wrapper > .container,
body.page-module-h2jforms-contact:has(.cubx-hero-active) #wrapper > .container,
body#module-h2jecosystem-categories:has(.cubx-hero-active) #wrapper > .container,
body.page-module-h2jecosystem-categories:has(.cubx-hero-active) #wrapper > .container {
  max-width: none;
  padding-left: 0;
  padding-right: 0;
  width: 100%;
}
body#category:has(.cubx-hero-active) #wrapper > .container > .row,
body.page-new-products:has(.cubx-hero-active) #wrapper > .container > .row,
body.page-prices-drop:has(.cubx-hero-active) #wrapper > .container > .row,
body.page-best-sales:has(.cubx-hero-active) #wrapper > .container > .row,
body.page-cms:has(.cubx-hero-active) #wrapper > .container > .row,
body.page-my-account:has(.cubx-hero-active) #wrapper > .container > .row,
body.page-customer-account:has(.cubx-hero-active) #wrapper > .container > .row,
body.page-identity:has(.cubx-hero-active) #wrapper > .container > .row,
body.page-addresses:has(.cubx-hero-active) #wrapper > .container > .row,
body.page-address:has(.cubx-hero-active) #wrapper > .container > .row,
body.page-history:has(.cubx-hero-active) #wrapper > .container > .row,
body.page-order-slip:has(.cubx-hero-active) #wrapper > .container > .row,
body.page-discount:has(.cubx-hero-active) #wrapper > .container > .row,
body.page-order-detail:has(.cubx-hero-active) #wrapper > .container > .row,
body.page-contact:has(.cubx-hero-active) #wrapper > .container > .row,
body.page-stores:has(.cubx-hero-active) #wrapper > .container > .row,
body.page-sitemap:has(.cubx-hero-active) #wrapper > .container > .row,
body#module-h2jforms-register:has(.cubx-hero-active) #wrapper > .container > .row,
body.page-module-h2jforms-register:has(.cubx-hero-active) #wrapper > .container > .row,
body#module-h2jforms-login:has(.cubx-hero-active) #wrapper > .container > .row,
body.page-module-h2jforms-login:has(.cubx-hero-active) #wrapper > .container > .row,
body#module-h2jforms-contact:has(.cubx-hero-active) #wrapper > .container > .row,
body.page-module-h2jforms-contact:has(.cubx-hero-active) #wrapper > .container > .row,
body#module-h2jecosystem-categories:has(.cubx-hero-active) #wrapper > .container > .row,
body.page-module-h2jecosystem-categories:has(.cubx-hero-active) #wrapper > .container > .row {
  margin-left: 0;
  margin-right: 0;
}
body#category:has(.cubx-hero-active) #content-wrapper,
body.page-new-products:has(.cubx-hero-active) #content-wrapper,
body.page-prices-drop:has(.cubx-hero-active) #content-wrapper,
body.page-best-sales:has(.cubx-hero-active) #content-wrapper,
body.page-cms:has(.cubx-hero-active) #content-wrapper,
body.page-my-account:has(.cubx-hero-active) #content-wrapper,
body.page-customer-account:has(.cubx-hero-active) #content-wrapper,
body.page-identity:has(.cubx-hero-active) #content-wrapper,
body.page-addresses:has(.cubx-hero-active) #content-wrapper,
body.page-address:has(.cubx-hero-active) #content-wrapper,
body.page-history:has(.cubx-hero-active) #content-wrapper,
body.page-order-slip:has(.cubx-hero-active) #content-wrapper,
body.page-discount:has(.cubx-hero-active) #content-wrapper,
body.page-order-detail:has(.cubx-hero-active) #content-wrapper,
body.page-contact:has(.cubx-hero-active) #content-wrapper,
body.page-stores:has(.cubx-hero-active) #content-wrapper,
body.page-sitemap:has(.cubx-hero-active) #content-wrapper,
body#module-h2jforms-register:has(.cubx-hero-active) #content-wrapper,
body.page-module-h2jforms-register:has(.cubx-hero-active) #content-wrapper,
body#module-h2jforms-login:has(.cubx-hero-active) #content-wrapper,
body.page-module-h2jforms-login:has(.cubx-hero-active) #content-wrapper,
body#module-h2jforms-contact:has(.cubx-hero-active) #content-wrapper,
body.page-module-h2jforms-contact:has(.cubx-hero-active) #content-wrapper,
body#module-h2jecosystem-categories:has(.cubx-hero-active) #content-wrapper,
body.page-module-h2jecosystem-categories:has(.cubx-hero-active) #content-wrapper {
  padding-left: 0;
  padding-right: 0;
}

/* ═══════════════════════════════════════════════════════════
   18. HERO PANEL — colonne gauche fixe (v1.1.0)
   Reproduit le comportement 01GRID : image éditoriale fixe
   sur la gauche, contenu scrollable sur la droite.

   Variables pilotées par Homeblocks BO (injectées via getCssVars) :
     --cubx-hero-w          largeur du panel (défaut 38%)
     --cubx-hero-mobile-h   hauteur mobile (défaut 55vw)
     --cubx-hero-grayscale  désaturation (défaut 100%)
     --cubx-hero-blend      mix-blend-mode (défaut normal)
     --cubx-hero-overlay    couleur overlay (défaut transparent)
   ═══════════════════════════════════════════════════════════ */

/* Fallbacks — écrasés par getCssVars() via <style> dans <head> */
:root {
  --cubx-hero-w:         38%;
  --cubx-hero-mobile-h:  55vw;
  --cubx-hero-grayscale: 100%;
  --cubx-hero-blend:     normal;
  --cubx-hero-overlay:   transparent;
}

/* ── Layout wrapper : hero + contenu côte à côte ── */
/* v1.4.13 — Fix décalage vertical hero panel vs content :
   #content-wrapper a un padding: 20px 0 par défaut (section 3 LAYOUT).
   Le panel étant position:fixed l'ignore, mais le content (static) le respecte.
   Résultat : 20px d'écart entre le top du panel et celui du content.
   Fix : neutraliser le padding-top sur le wrapper en mode hero actif. */
.cubx-hero-layout {
  display: block;        /* stacking context — le panel est fixed */
  position: relative;
  min-height: 100vh;
  padding-top: 0 !important;
  padding-bottom: 0 !important;
}

/* Le content reprend le padding défaut pour respirer en bas, mais part de tout en haut */
.cubx-hero-content {
  padding-top: 0;
}

/* v1.4.6 — Mode natural : layout flex pour panel sticky + contenu côte à côte.
   Déclenché par la classe .cubx-hero-mode-natural (injectée par le template).
   Plus robuste que :has() qui avait un support navigateur variable. */
.cubx-hero-layout.cubx-hero-mode-natural {
  display: flex;
  align-items: flex-start;
}

/* ── Panneau hero (colonne gauche) ── */
.cubx-hero-panel {
  position: fixed;
  top: 0;
  left: 0;
  width: var(--cubx-hero-w);
  height: 100vh;
  z-index: 10;
  overflow: hidden;
  /* v1.4.0 — Transition pour l'animation de collapse (voir toggle ci-dessous).
     Transform utilisé pour la translation (GPU-acceleré, 60fps fluide). */
  transition: transform 0.4s cubic-bezier(0.4, 0, 0.2, 1);
  /* Empêche le panneau de couvrir le header sticky PS */
}

/* v1.4.1 — Mode natural : panel sticky à hauteur naturelle de l'image.
   Le panel colle en haut du viewport tant que le wrapper est visible,
   puis scrolle avec le contenu. La largeur reste pilotée par --cubx-hero-w. */
.cubx-hero-panel[data-height-mode="natural"] {
  position: sticky;
  top: 0;
  height: auto;            /* hauteur dictée par l'image */
  flex: 0 0 var(--cubx-hero-w);
  align-self: flex-start;  /* sticky a besoin d'un align top dans un flex */
  overflow: visible;
}

/* v1.4.3 — Mode auto : largeur panel calculée depuis le ratio de l'image.
   Formule : largeur = hauteur × ratio, clampé entre min et max vw.
   Le ratio est injecté via --cubx-hero-image-ratio (émis par H2JHomeBlocksConfig::getCssVars).
   Les bornes min/max sont pilotées par --cubx-hero-auto-min et --cubx-hero-auto-max (en vw).

   Avantages vs viewport mode :
   • Aucun crop : le panel a exactement le ratio de l'image
   • Aucun letterbox : pas de bandes vides
   • S'adapte à chaque image du pool random automatiquement
   • Fonctionne sur tous les formats (portrait, landscape, carré) */
.cubx-hero-panel[data-height-mode="auto"] {
  position: fixed;
  top: 0;
  left: 0;
  height: 100vh;
  width: clamp(
    var(--cubx-hero-auto-min, 15vw),
    calc(100vh * var(--cubx-hero-image-ratio, 0.67)),
    var(--cubx-hero-auto-max, 50vw)
  );
  overflow: hidden;
}

/* En mode auto, l'image peut utiliser object-fit:cover en toute sécurité
   parce que le ratio du panel = le ratio de l'image. Pas de crop effectif. */
.cubx-hero-panel[data-height-mode="auto"] .cubx-hero-panel__img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center center;
}

.cubx-hero-panel__link {
  display: block;
  width: 100%;
  height: 100%;
  cursor: pointer;
}

.cubx-hero-panel__figure {
  position: relative;
  width: 100%;
  height: 100%;
  margin: 0;
}

.cubx-hero-panel__img {
  width: 100%;
  height: 100%;
  /* v1.2.0 : object-fit + object-position pilotés par BO (H2JHB_HEROGAL_HOME_FIT/POS_X/POS_Y)
     via --cubx-hero-fit et --cubx-hero-pos émises par H2JHomeBlocksConfig::getCssVars().
     Fallbacks : cover + center center (compatible avec le comportement v1.1.x). */
  object-fit: var(--cubx-hero-fit, cover);
  object-position: var(--cubx-hero-pos, center center);
  display: block;
  /* Effets pilotés par variables */
  filter: grayscale(var(--cubx-hero-grayscale));
  mix-blend-mode: var(--cubx-hero-blend);
  transition: filter 0.4s ease;
}

/* v1.4.1 — Mode natural : l'image conserve son ratio naturel.
   width:100% + height:auto = la hauteur s'adapte à la largeur du panel. */
.cubx-hero-panel[data-height-mode="natural"] .cubx-hero-panel__img {
  width: 100%;
  height: auto;
  object-fit: unset;
}

/* Overlay ::after — couleur de teinte par-dessus l'image */
.cubx-hero-panel__overlay {
  position: absolute;
  inset: 0;
  background: var(--cubx-hero-overlay);
  pointer-events: none;
  transition: background 0.4s ease;
}

/* Hover : révèle la couleur */
.cubx-hero-panel:hover .cubx-hero-panel__img {
  filter: grayscale(0%);
}

.cubx-hero-panel:hover .cubx-hero-panel__overlay {
  background: transparent;
}

/* ── Contenu décalé à droite pour laisser la place au panel ── */
/* v1.4.6 — Fix : utilise les classes .cubx-hero-mode-{mode} injectées par le template
   au lieu de :has() (qui avait un problème de support). Plus fiable et plus simple.
   Quand la gallery est OFF, .cubx-hero-content n'existe pas du tout dans le DOM
   (cf. index.tpl qui bifurque sur {if enabled}), donc pas besoin de gérer ce cas. */
.cubx-hero-content {
  min-height: 100vh;
  transition: margin-left 0.4s cubic-bezier(0.4, 0, 0.2, 1);
  position: relative;
  z-index: 5;
}

/* Mode viewport (défaut) : margin-left = largeur BO fixe */
.cubx-hero-layout.cubx-hero-mode-viewport .cubx-hero-content {
  margin-left: var(--cubx-hero-w);
}

/* v1.4.6 — Mode natural : pas de margin-left, le content est flex-item next to panel sticky. */
.cubx-hero-layout.cubx-hero-mode-natural .cubx-hero-content {
  margin-left: 0;
  flex: 1 1 auto;
  min-width: 0;            /* laisse le flex item shrink correctement */
}

/* v1.4.6 — Mode auto : le content se décale de la même largeur clampée que le panel. */
.cubx-hero-layout.cubx-hero-mode-auto .cubx-hero-content {
  margin-left: clamp(
    var(--cubx-hero-auto-min, 15vw),
    calc(100vh * var(--cubx-hero-image-ratio, 0.67)),
    var(--cubx-hero-auto-max, 50vw)
  );
}

/* ════════════════════════════════════════════════════════
   v1.4.0 — HERO PANEL TOGGLE (collapse/expand button)
   Feature premium : l'utilisateur peut masquer/révéler le hero panel.
   État persisté dans localStorage via cubx-hero-toggle.js.

   Architecture :
     • Bouton flottant attaché au bord droit du panel (centré verticalement)
     • Icône flèche Material Icons qui change selon l'état
     • Au clic : attribut data-collapsed="true" → panel translate(-100%) + content margin 0
     • Le bouton reste visible grâce à son conteneur wrapper qui ne collapse pas
   ═══════════════════════════════════════════════════════ */

/* Bouton toggle — flottant, attaché au bord droit du panel.
   v1.4.1 : bouton plus discret (16px large au lieu de 32px).
   v1.4.5 : position par défaut 0 (hidden si pas de panel), override par mode via :has().
   Position absolue par rapport au panel lui-même, centré verticalement.
   z-index 11 pour passer au-dessus du contenu (.cubx-hero-content z-index 5). */
.cubx-hero-toggle {
  position: fixed;
  top: 50%;
  left: 0;                 /* v1.4.5 : fallback, override par les règles :has() ci-dessous */
  transform: translate(-50%, -50%);
  width: 16px;
  height: 48px;
  background: var(--cubx-accent);
  color: #ffffff;
  border: none;
  border-radius: 0 6px 6px 0;
  cursor: pointer;
  z-index: 11;
  display: none;           /* v1.4.5 : masqué par défaut, révélé uniquement si un panel existe */
  align-items: center;
  justify-content: center;
  box-shadow: 2px 0 6px rgba(0, 0, 0, 0.12);
  opacity: 0.7;
  /* Synchronisé avec le panel pour suivre son mouvement */
  transition: left 0.4s cubic-bezier(0.4, 0, 0.2, 1),
              background 0.2s ease,
              transform 0.2s ease,
              opacity 0.2s ease;
  padding: 0;
  outline: none;
}

/* v1.4.8 — Le toggle est visible uniquement sous un parent .cubx-hero-active.
   Sa position horizontale dépend de la classe mode :
   • viewport : left = --cubx-hero-w (largeur BO fixe)
   • auto     : left = clamp(...) (même formule que le panel)
   • natural  : left = --cubx-hero-w (comme viewport, le panel sticky a même largeur)

   IMPORTANT : le toggle est appendu à document.body par cubx-hero-toggle.js,
   donc il n'est PAS un descendant de .cubx-hero-layout. On utilise donc
   body.cubx-hero-mode-* (le JS ajoute cette classe au body au démarrage). */
body.cubx-hero-mode-viewport .cubx-hero-toggle {
  display: flex;
  left: var(--cubx-hero-w);
}

body.cubx-hero-mode-auto .cubx-hero-toggle {
  display: flex;
  left: clamp(
    var(--cubx-hero-auto-min, 15vw),
    calc(100vh * var(--cubx-hero-image-ratio, 0.67)),
    var(--cubx-hero-auto-max, 50vw)
  );
}

/* v1.4.8 — Mode natural : le toggle est affiché comme en viewport (left = largeur BO).
   Le panel sticky a la même largeur, donc le toggle est bien au bord droit du panel.
   Note : quand l'utilisateur scroll au-delà du layout, le toggle reste fixed visible
   (acceptable, l'utilisateur peut cliquer pour replier le panel à tout moment). */
body.cubx-hero-mode-natural .cubx-hero-toggle {
  display: flex;
  left: var(--cubx-hero-w);
}

.cubx-hero-toggle:hover {
  background: var(--cubx-accent-2);
  opacity: 1;
  transform: translate(-50%, -50%) scale(1.1);
}

.cubx-hero-toggle:focus-visible {
  outline: 2px solid var(--cubx-accent);
  outline-offset: 2px;
}

.cubx-hero-toggle .material-icons {
  font-size: 14px;
  transition: transform 0.3s ease;
}

/* v1.4.8 — ETAT COLLAPSED : approche body.cubx-hero-collapsed
   Le JS cubx-hero-toggle.js ajoute/retire la classe `cubx-hero-collapsed` sur <body>
   quand l'utilisateur clique le toggle. Cette classe est utilisée comme sélecteur
   CSS de haute spécificité pour override les règles de position mode-specific.

   Pourquoi cette approche :
   v1.4.7 utilisait `[data-collapsed="true"]` sur le toggle mais la spécificité CSS
   ne suffisait pas à battre les règles `body.cubx-hero-mode-*` pour `left` et
   `transform`. Avec body.cubx-hero-collapsed en combinaison avec body.cubx-hero-mode-*,
   on a une spécificité (0,3,1) qui bat proprement (0,2,1) + !important en secours. */

/* Panel collapsed : translate off-screen (inchangé depuis v1.4.0) */
body.cubx-hero-collapsed .cubx-hero-panel {
  transform: translateX(-100%);
  pointer-events: none;
}

/* v1.4.10 — Mode natural : en plus de translateX, on réduit le flex-basis à 0
   pour retirer le panel du flex flow, sinon il garde sa place et laisse un espace
   blanc à gauche. En viewport/auto le panel est position:fixed donc hors flow,
   ce problème ne se pose pas — seule la mode natural (flex item) est concernée. */
body.cubx-hero-collapsed.cubx-hero-mode-natural .cubx-hero-panel {
  flex: 0 0 0 !important;
  width: 0 !important;
  min-width: 0 !important;
  overflow: hidden !important;
  transition: flex-basis 0.4s cubic-bezier(0.4, 0, 0.2, 1),
              width 0.4s cubic-bezier(0.4, 0, 0.2, 1),
              transform 0.4s cubic-bezier(0.4, 0, 0.2, 1);
}

/* Content collapsed : pleine largeur (override les margins mode-specific) */
body.cubx-hero-collapsed.cubx-hero-mode-viewport .cubx-hero-content,
body.cubx-hero-collapsed.cubx-hero-mode-auto .cubx-hero-content,
body.cubx-hero-collapsed.cubx-hero-mode-natural .cubx-hero-content {
  margin-left: 0 !important;
}

/* Toggle collapsed : collé au bord gauche du viewport avec flèche inversée.
   La règle doit gagner sur les règles de position mode-specific qui ont la même
   spécificité de base. On utilise body.cubx-hero-collapsed + body.cubx-hero-mode-*
   combinés pour monter la spécificité à (0,3,1), + !important en ceinture-bretelles. */
body.cubx-hero-collapsed.cubx-hero-mode-viewport .cubx-hero-toggle,
body.cubx-hero-collapsed.cubx-hero-mode-auto .cubx-hero-toggle,
body.cubx-hero-collapsed.cubx-hero-mode-natural .cubx-hero-toggle {
  left: 0 !important;
  transform: translate(0, -50%) !important;
  border-radius: 0 8px 8px 0;
}

body.cubx-hero-collapsed .cubx-hero-toggle:hover {
  transform: translate(0, -50%) scale(1.1) !important;
  opacity: 1;
}

body.cubx-hero-collapsed .cubx-hero-toggle .material-icons {
  transform: rotate(180deg);
}

/* Légacy data-collapsed — gardé pour compatibilité mais surpassé par les règles body ci-dessus */
.cubx-hero-panel[data-collapsed="true"] {
  transform: translateX(-100%);
  pointer-events: none;
}

/* ── Quand hero actif : wrapper en position relative ── */
.cubx-hero-layout {
  position: relative;
}

/* ═══════════════════════════════════════════════════════════
   19. HERO PANEL — MOBILE
   Sur mobile : le panel n'est plus fixe, il apparaît
   en bloc statique en haut de page, hauteur configurable.
   ═══════════════════════════════════════════════════════════ */
@media (max-width: 991px) {
  /* v1.4.17 — Force TOUS les modes hero à se restacker en mobile : panel statique
     pleine largeur, peu importe le height_mode configuré dans le BO. Sans !important
     les règles [data-height-mode="auto"|"natural"] (spécificité 0,2,0) battent celles-ci.
     v1.4.25 — position: relative (pas static) pour que les enfants absolute du logo
     overlay (.cubx-header-logo / .cubx-logo-filter) restent ancrés DANS le panel
     plutôt que de se reporter au viewport, ce qui faisait que le bloc multiply
     couvrait toute la page et que le logo se retrouvait centré en milieu d'écran. */
  .cubx-hero-panel,
  .cubx-hero-panel[data-height-mode="viewport"],
  .cubx-hero-panel[data-height-mode="natural"],
  .cubx-hero-panel[data-height-mode="auto"] {
    position: relative !important;
    width: 100% !important;
    height: var(--cubx-hero-mobile-h) !important;
    flex: none !important;
    transform: none !important;
    overflow: hidden !important;
  }

  /* Layout wrapper : passe en block (mode natural était en flex) */
  .cubx-hero-layout,
  .cubx-hero-layout.cubx-hero-mode-viewport,
  .cubx-hero-layout.cubx-hero-mode-natural,
  .cubx-hero-layout.cubx-hero-mode-auto {
    display: block !important;
    min-height: auto !important;
  }

  /* Content : margin-left 0 dans tous les modes (override des règles
     desktop .cubx-hero-layout.cubx-hero-mode-* .cubx-hero-content qui ont 0,3,0) */
  .cubx-hero-content,
  .cubx-hero-layout.cubx-hero-mode-viewport .cubx-hero-content,
  .cubx-hero-layout.cubx-hero-mode-natural .cubx-hero-content,
  .cubx-hero-layout.cubx-hero-mode-auto .cubx-hero-content {
    margin-left: 0 !important;
    flex: none !important;
    width: 100% !important;
  }

  .cubx-hero-panel {
    position: relative;
    width: 100%;
    height: var(--cubx-hero-mobile-h);
    /* Réinitialise le fixed pour le layout mobile */
    transform: none !important;  /* v1.4.0 : désactive le collapse sur mobile */
  }

  .cubx-hero-content {
    margin-left: 0;
  }

  .cubx-hero-layout {
    min-height: auto;
  }

  /* Sur mobile, le hover ne s'applique pas (touch) —
     on montre l'image en couleur directement */
  .cubx-hero-panel .cubx-hero-panel__img {
    filter: grayscale(0%);
    transition: none;
    width: 100% !important;
    height: 100% !important;
    object-fit: cover !important;
  }

  .cubx-hero-panel .cubx-hero-panel__overlay {
    background: transparent;
  }

  /* v1.4.17 — Bouton toggle hero masqué sur mobile dans tous les modes
     (les règles body.cubx-hero-mode-* .cubx-hero-toggle ont 0,2,0). */
  body.cubx-hero-mode-viewport .cubx-hero-toggle,
  body.cubx-hero-mode-natural .cubx-hero-toggle,
  body.cubx-hero-mode-auto .cubx-hero-toggle,
  .cubx-hero-toggle {
    display: none !important;
  }
}

/* ═══════════════════════════════════════════════════════════
   20. CUSTOM — override client (vide Phase 1)
   ═══════════════════════════════════════════════════════════ */
/* @import 'custom.css'; */

/* H2J MEGAMENU INTEGRATION (cubx-theme v1.4.19, evol v2.5.107)
   When h2jecosystem injects the megamenu, the legacy CUBX header bars
   (nav-bar, top-bar) become redundant. We hide them.
   .header-bottom is NOT hidden because it's the Smarty block that receives
   {hook h='displayNavFullWidth'} — which is exactly where h2jecosystem injects
   the megamenu. Hiding .header-bottom would hide the burger + sidebar with it.
   Instead we neutralise .header-bottom visually (transparent, no layout).
   Class is added by h2jecosystem hookDisplayHeader on <html>.

   v2.5.107 — Restauration du masquage simple .header-top { display:none }.
   v2.5.106 avait tenté un masquage chirurgical pour préserver .header-right
   (qui contenait le cart-btn mode 'header'), mais cela créait un bandeau
   résiduel pleine largeur visible (David : "absolument ce que je veux éviter,
   avoir une barre sur toute la largeur"). Solution propre v2.5.107 : le
   cart-btn sort de .header-top et devient un corner fixed top-right indépendant
   (cf. theme-cart.css §1.A) en symétrie parfaite avec le burger megamenu
   top-left. .header-top reprend son masquage intégral d'origine. */
html.h2j-mm-active .header-nav,
html.h2j-mm-active .header-top {
  display: none !important;
}

html.h2j-mm-active .header-bottom {
  background: transparent !important;
  border: none !important;
  box-shadow: none !important;
  padding: 0 !important;
  margin: 0 !important;
  min-height: 0 !important;
  position: static !important;
  /* v1.4.21 — Force display:block to override the mobile @media 768px rule
     at section 16 (`.header-bottom { display: none }`) that otherwise hides
     the container and cascades to the burger + sidebar inside. */
  display: block !important;
  visibility: visible !important;
  max-height: none !important;
  overflow: visible !important;
}
html.h2j-mm-active .header-bottom > .container {
  padding: 0 !important;
  margin: 0 !important;
  max-width: none !important;
  display: block !important;
  min-height: 0 !important;
}

/* Collapse the #header wrapper so the hero touches the top of the viewport */
html.h2j-mm-active #header {
  background: transparent !important;
  box-shadow: none !important;
  position: static !important;
  min-height: 0 !important;
}

html.h2j-mm-active.h2j-mm-mode-sidebar #content-wrapper,
html.h2j-mm-active.h2j-mm-mode-sidebar .cubx-hero-layout {
  margin-top: 0 !important;
  padding-top: 0 !important;
}

/* ══════════════════════════════════════════════════════════════════════
   22. HERO LOGO OVERLAY  (v1.4.23)
   Reproduces the legacy 01grid logo + colored layer behavior inside the
   CUBX hero panel. Two sibling divs positioned absolute inside
   .cubx-hero-panel :
     • .cubx-header-logo  — flex-centered <img> logo, z-index 11
     • .cubx-logo-filter  — solid colored block behind the logo, blended
       via mix-blend-mode: multiply on the underlying hero image, z-index 10

   Positioning is driven by two modifier classes added on both sibling divs :
     • .cubx-logo-v-{top|center|bottom}
     • .cubx-logo-h-{left|center|right}

   Sizing is driven by a third modifier class :
     • .cubx-logo-size-{S|M|L|XL}
     (S = 30% / 25%, M = 45% / 33%, L = 75% / 60%, XL = 90% / 75%)

   v1.4.23 — Customizable overlay colour :
   The filter block colour is driven by --cubx-logo-overlay-color with
   fallback to --cubx-accent. h2jecosystem emits the variable inline in
   hookDisplayHeader when the user sets a custom colour in the BO.

   Settings come from h2jecosystem BO (Design System > Thème & Effets > Logo
   display per position > Navigation). The h2jecosystem module assigns the
   Smarty variable $cubx_logo_cfg in hookDisplayHeader with :
     {enabled, src, align_v, align_h, size, colored_layer}
   and hero-panel.tpl renders the two divs conditionally.
   ══════════════════════════════════════════════════════════════════════ */

/* ── Shared box model for both siblings ──
   They overlap exactly (same position + width + height) so the filter block
   sits perfectly under the logo. Base size = M (45% × 33%). */
.cubx-header-logo,
.cubx-logo-filter {
  position: absolute;
  top: 33.3333%;
  left: 27.5%;
  width: 45%;
  height: 33.3333%;
  pointer-events: none;
  box-sizing: border-box;
}

/* ── Logo image wrapper ──
   v1.4.23 — Padding reduced from 20px to 12px to let the logo breathe
   more inside its overlay box (users found the logo too small at L). */
.cubx-header-logo {
  z-index: 11;
  padding: 12px;
  display: flex;
  align-items: center;
  justify-content: center;
}

.cubx-header-logo__link {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  height: 100%;
  pointer-events: auto;
  text-decoration: none;
  transition: opacity 150ms ease-in-out;
}

.cubx-header-logo__link:hover,
.cubx-header-logo__link:focus {
  opacity: 0.85;
  text-decoration: none;
}

/* v1.4.24 — Fix logo scaling : use width/height 100% + object-fit contain
   so the image actually grows with the container. Previous rule used
   width:auto + max-width:100% which capped the image at its intrinsic
   natural dimensions, so S/M/L/XL only grew the box without scaling up
   the logo inside. object-fit:contain preserves the ratio (no crop,
   no stretch) while letting the image fill the available space. */
.cubx-header-logo img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: contain;
  object-position: center center;
}

/* ── Colored filter block (multiply by default) ──
   Sits one z-index below the logo, and uses mix-blend-mode to tint the
   hero image underneath with the configured overlay colour.
   v1.4.23 — Colour pilotable via --cubx-logo-overlay-color (set by the BO
   color picker in h2jecosystem). Falls back to --cubx-accent when unset. */
.cubx-logo-filter {
  z-index: 10;
  background-color: var(--cubx-logo-overlay-color, var(--cubx-accent));
  mix-blend-mode: multiply;
  opacity: 1;
}

/* Fallback for browsers without mix-blend-mode support — soft transparency
   so the logo is still readable over the image. */
@supports not (mix-blend-mode: multiply) {
  .cubx-logo-filter {
    opacity: 0.5;
  }
}

/* ── Size modifiers (override width + height) ──
   v1.4.23 — Dimensions bumped up across the board. Previous values were too
   timid compared to the reference idyll.fr rendering :
     S  :  25% / 25%  →  30% / 25%
     M  :  40% / 33%  →  45% / 33%
     L  :  60% / 50%  →  75% / 60%
     XL : (new)          90% / 75%   (new size for "really big" use cases) */
.cubx-header-logo.cubx-logo-size-S,
.cubx-logo-filter.cubx-logo-size-S {
  width: 30%;
  height: 25%;
}

.cubx-header-logo.cubx-logo-size-M,
.cubx-logo-filter.cubx-logo-size-M {
  width: 45%;
  height: 33.3333%;
}

.cubx-header-logo.cubx-logo-size-L,
.cubx-logo-filter.cubx-logo-size-L {
  width: 75%;
  height: 60%;
}

.cubx-header-logo.cubx-logo-size-XL,
.cubx-logo-filter.cubx-logo-size-XL {
  width: 90%;
  height: 75%;
}

/* ── Vertical alignment modifiers ──
   Default (.cubx-logo-v-center) = top at (100% - h) / 2 handled via
   calc below so the block stays vertically centered regardless of size. */
.cubx-header-logo.cubx-logo-v-center,
.cubx-logo-filter.cubx-logo-v-center {
  top: 50%;
  transform: translateY(-50%);
  bottom: auto;
}

.cubx-header-logo.cubx-logo-v-top,
.cubx-logo-filter.cubx-logo-v-top {
  top: 0;
  transform: none;
  bottom: auto;
}

.cubx-header-logo.cubx-logo-v-bottom,
.cubx-logo-filter.cubx-logo-v-bottom {
  top: auto;
  bottom: 0;
  transform: none;
}

/* ── Horizontal alignment modifiers ──
   margin-left = -width/2 for each size to center within the panel. */
.cubx-header-logo.cubx-logo-h-center,
.cubx-logo-filter.cubx-logo-h-center {
  left: 50%;
  right: auto;
  margin-left: -22.5%;     /* default for size M (width 45%) */
}
.cubx-header-logo.cubx-logo-h-center.cubx-logo-size-S,
.cubx-logo-filter.cubx-logo-h-center.cubx-logo-size-S {
  margin-left: -15%;       /* S width 30% */
}
.cubx-header-logo.cubx-logo-h-center.cubx-logo-size-L,
.cubx-logo-filter.cubx-logo-h-center.cubx-logo-size-L {
  margin-left: -37.5%;     /* L width 75% */
}
.cubx-header-logo.cubx-logo-h-center.cubx-logo-size-XL,
.cubx-logo-filter.cubx-logo-h-center.cubx-logo-size-XL {
  margin-left: -45%;       /* XL width 90% */
}

.cubx-header-logo.cubx-logo-h-left,
.cubx-logo-filter.cubx-logo-h-left {
  left: 0;
  right: auto;
  margin-left: 0;
}

.cubx-header-logo.cubx-logo-h-right,
.cubx-logo-filter.cubx-logo-h-right {
  left: auto;
  right: 0;
  margin-left: 0;
}

/* Combine V+H center: we need translate(-50%, -50%) instead of mixing
   translateY + negative margin-left (which conflict visually). */
.cubx-header-logo.cubx-logo-v-center.cubx-logo-h-center,
.cubx-logo-filter.cubx-logo-v-center.cubx-logo-h-center {
  top: 50%;
  left: 50%;
  margin-left: 0;
  transform: translate(-50%, -50%);
}

/* ── Mobile : hero panel becomes static and full-width (see section 19),
   so the absolute-positioned logo + filter must also adapt. We cap the
   vertical size and disable horizontal translation to keep things readable
   on touch devices. ── */
@media (max-width: 991px) {
  .cubx-header-logo,
  .cubx-logo-filter {
    top: 0 !important;
    left: 0 !important;
    right: 0 !important;
    bottom: auto !important;
    width: 100% !important;
    height: 100% !important;
    margin-left: 0 !important;
    transform: none !important;
  }
  .cubx-header-logo {
    padding: 16px;
  }
  .cubx-header-logo img {
    max-height: 70%;    /* leave breathing room above/below */
  }
}

/* ==========================================================================
   v1.5.0 — Category Ad Cells (consomme $cubx_cat_ads de h2jhomeblocks v3.23.0+)
   ========================================================================== */

:root {
    /* Ratio des cells ad — laissé libre par défaut : la cell prend la hauteur
       des miniatures produits voisines dans la même row CSS grid.
       Override possible par thematique (pinup portrait vs autopromo landscape). */
    --cubx-cat-ad-radius: 6px;
    --cubx-cat-ad-overlay-bg: rgba(0, 0, 0, 0.58);
    --cubx-cat-ad-overlay-color: #fff;
    --cubx-cat-ad-cta-bg: var(--cubx-accent, #7c4dff);
    --cubx-cat-ad-cta-color: #fff;
    --cubx-cat-ad-shadow-hover: 0 8px 22px rgba(0, 0, 0, 0.18);
}

.cubx-cat-grid--with-ads {
    /* v1.9.1 — Sprint 2D ads catégorie : placement explicite par grille.
       Le PHP émet 3 grilles (.cubx-cat-grid-variant--{no-hero,with-hero,mobile})
       avec items placés en (row, col) absolus. Pas d'auto-flow:dense — le
       placement vient des coords inline style="grid-column:X/span N; grid-row:Y/span M".
       Une seule grille est visible à la fois selon body classes / media queries
       (cf. règles plus bas "VARIANT TOGGLE"). */
    grid-auto-rows: 1fr;
}

/* v2.3.0 — RECUL : rules variant toggle supprimées.
   Le DOM ne génère plus de .cubx-cat-grid-variant--{no-hero|with-hero|mobile}
   (template v2.3.0 délègue à Classic, pas de 3 grilles séparées).
   Le toggle hero est géré directement par la section v2.3.0 en fin de fichier. */

.cubx-cat-ad-cell {
    position: relative;
    display: block;
    overflow: hidden;
    border-radius: var(--cubx-cat-ad-radius);
    background: var(--h2j-gray-100, #f5f5f5);
    /* Pas d'aspect-ratio fixé : la cell prend la hauteur de sa ligne grid,
       côté à côté des miniatures produits (image + titre + prix). L'image
       object-fit: cover absorbe la différence de ratio pinup portrait. */
    min-height: 100%;
    transition: transform 180ms ease, box-shadow 180ms ease;
    isolation: isolate;
}

.cubx-cat-ad-cell:hover {
    transform: translateY(-2px);
    box-shadow: var(--cubx-cat-ad-shadow-hover);
}

.cubx-cat-ad-cell__link {
    position: absolute;
    inset: 0;
    z-index: 2;
    display: block;
    color: inherit;
    text-decoration: none;
}

.cubx-cat-ad-cell__link:hover,
.cubx-cat-ad-cell__link:focus {
    text-decoration: none;
    color: inherit;
}

.cubx-cat-ad-cell__figure {
    position: absolute;
    inset: 0;
    margin: 0;
    z-index: 1;
    /* Image occupe la totalité de la cell (pas de padding parent) */
    display: flex;
    align-items: stretch;
    justify-content: stretch;
}

.cubx-cat-ad-cell__img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
}

.cubx-cat-ad-cell__overlay {
    position: absolute;
    inset: auto 0 0 0;
    padding: 12px 14px 14px;
    background: linear-gradient(to top, var(--cubx-cat-ad-overlay-bg) 0%, transparent 100%);
    color: var(--cubx-cat-ad-overlay-color);
    display: flex;
    flex-direction: column;
    gap: 4px;
    pointer-events: none;
}

.cubx-cat-ad-cell__title {
    font-size: clamp(14px, 1.6vw, 18px);
    font-weight: 700;
    line-height: 1.15;
    text-shadow: 0 1px 3px rgba(0, 0, 0, 0.35);
}

.cubx-cat-ad-cell__subtitle {
    font-size: clamp(11px, 1.2vw, 13px);
    line-height: 1.3;
    opacity: 0.95;
    text-shadow: 0 1px 2px rgba(0, 0, 0, 0.35);
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

.cubx-cat-ad-cell__cta {
    display: inline-block;
    align-self: flex-start;
    margin-top: 4px;
    padding: 4px 10px;
    font-size: 11px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.5px;
    background: var(--cubx-cat-ad-cta-bg);
    color: var(--cubx-cat-ad-cta-color);
    border-radius: 4px;
    pointer-events: none;
}

/* Type-specific accent */
.cubx-cat-ad-cell--pinup {
    /* Déco pure — pas de CTA visuel par défaut. */
}
.cubx-cat-ad-cell--autopromo {
    /* Campagne interne — accent border optionnelle */
    outline: 0 solid transparent;
}
.cubx-cat-ad-cell--sponsor::before {
    content: 'SPONSORISÉ';
    position: absolute;
    top: 8px;
    right: 8px;
    z-index: 3;
    padding: 2px 6px;
    font-size: 9px;
    font-weight: 700;
    letter-spacing: 0.4px;
    background: rgba(255, 255, 255, 0.92);
    color: #555;
    border-radius: 3px;
    pointer-events: none;
}

/* Visibility modifiers */
.cubx-cat-ad-cell--no-mobile {
    /* Caché sous 768px */
}
@media (max-width: 767.98px) {
    .cubx-cat-ad-cell--no-mobile {
        display: none !important;
    }
}
@media (min-width: 768px) {
    .cubx-cat-ad-cell--no-desktop {
        display: none !important;
    }
}

/* ==========================================================================
   v1.5.0 — Category grid : skin miniatures Classic sur le style .hb-product
   (cubes denses homepage). Override CSS pur, aucune modif de template
   PrestaShop Classic nécessaire. Aligné sur h2jhomeblocks.css v3.5.0.
   ========================================================================== */

/* ---- Grille dense, gap zéro (override de la section 8 .products) ----
   v1.7.3 — hero-aware + collapse-aware.
   
   La grille bascule entre 2 valeurs de colonnes selon 3 états :
   
   │ État                                  │ Classes body                          │ Colonnes                    │
   │ Pas de hero active                    │ (aucune)                             │ --cols-no-hero  (BO: 6)      │
   │ Hero active, dépliée                   │ cubx-hero-active                     │ --cols-with-hero (BO: 4)     │
   │ Hero active, repliée (toggle FO)      │ cubx-hero-active + cubx-hero-collapsed│ --cols-no-hero  (BO: 6)      │
   
   Ceci respecte le choix admin : quand l'utilisateur replie la hero sidebar
   via le bouton chevron en FO (géré par cubx-hero-toggle.js v1.4.6+), la grille
   passe automatiquement au mode "no-hero" configé en BO. Déplier la remet en
   "with-hero". Le choix est persisté en localStorage (cle cubx-hero-collapsed).
   
   Sélecteur `body:has(.cubx-hero-active):not(.cubx-hero-collapsed)` cible
   uniquement l'état hero active + dépliée. Les 2 autres états (no-hero tout
   court, ou hero repliée) retombent sur la règle par défaut --cols-no-hero.
   
   Supporte : Chrome 105+, Safari 15.4+, Firefox 121+. Fallback 6 cols sinon.
   Tablet 768-992px hardcodé à 3. Mobile < 768px consomme --cols-mobile. */
/* v2.3.0 — RECUL : rules .cubx-cat-grid.products et --with-ads supprimées.
   Le DOM ne génère plus la classe .cubx-cat-grid (template v2.3.0 délègue
   à Classic), ces rules étaient inertes mais créaient de la cascade parasite.
   La grille produits catégorie est pilotée UNIQUEMENT par la section v2.3.0
   en fin de fichier (#js-product-list .products avec !important). */

/* ==========================================================================
   v1.8.0 — Sprint 2b : Density switcher FO override
   
   Offset vs baseline BO selon data-cubx-density posé sur <body> par
   cubx-cat-density.js (compact = +1, normal = 0, airy = -1).
   
   Compose avec l'état hero (plain ou with-hero selon :has(.cubx-hero-active)
   et :not(.cubx-hero-collapsed)) via calc() sur la var utilisée à chaque état.
   
   Clamp min 1 : si l'user est en mode airy sur une grille déjà à 1 col
   (ex: mobile + with-hero = 2 − 1 = 1), on reste à 1. max() garantit ça.
   
   Cascade de spécificité ordonnée : les règles density[compact|airy]
   doivent battre les règles hero-active dans les 4 breakpoints. Un simple
   body[attr] ne battra pas body:has() car égale spécificité (10 + 10 = 20
   vs 1 + 10 = 11), donc on compose les sélecteurs.
   ========================================================================== */

/* v2.3.0 — RECUL : rules density supprimées.
   Le DOM ne pose plus body[data-cubx-density] (cubx-cat-density.js désactivé
   en v2.0.0). Ces rules étaient inertes mais créaient de la cascade parasite. */

/* ==========================================================================
   v1.8.0 — Sprint 2b : Density switcher — styling des 3 boutons toolbar
   
   Segment contrôle inspiré d'un radio group iOS : 3 boutons collés avec
   bordure unique, l'actif prend l'accent couleur CUBX (violet). Icons-only
   pour un look moderne et compact ; labels accessibles via aria-label.
   
   Calé sur les patterns visuels des boutons --filter et --sort existants
   (hauteur 40px, border-radius 6px, hover état). Placement : flex-end du
   toolbar, à droite après le dropdown Sort.
   ========================================================================== */
.cubx-cat-toolbar__density {
    display: inline-flex;
    align-items: stretch;
    gap: 0;
    margin-left: auto;
    border: 1px solid #e0e0e0;
    border-radius: 6px;
    overflow: hidden;
    background: #fff;
}

.cubx-cat-toolbar__density-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 40px;
    height: 40px;
    padding: 0;
    margin: 0;
    background: transparent;
    border: none;
    border-left: 1px solid #e0e0e0;
    color: #555;
    cursor: pointer;
    transition: background-color 0.15s ease, color 0.15s ease;
}

/* Premier bouton : pas de border-left (la bordure du wrapper suffit) */
.cubx-cat-toolbar__density-btn:first-child {
    border-left: none;
}

.cubx-cat-toolbar__density-btn:hover {
    background-color: #f5f5f5;
    color: #000;
}

.cubx-cat-toolbar__density-btn:focus-visible {
    outline: 2px solid var(--cubx-accent, #9b87f5);
    outline-offset: -2px;
    z-index: 1;
}

/* État actif : fond violet CUBX + iconône blanche */
.cubx-cat-toolbar__density-btn.is-current {
    background-color: var(--cubx-accent, #9b87f5);
    color: #fff;
}

.cubx-cat-toolbar__density-btn.is-current:hover {
    background-color: var(--cubx-accent-hover, #7c6bd6);
    color: #fff;
}

.cubx-cat-toolbar__density-btn svg {
    display: block;
    flex-shrink: 0;
}

/* Mobile : s'intègre en fin de toolbar, rétrécit légèrement */
@media (max-width: 576px) {
    .cubx-cat-toolbar__density-btn {
        width: 36px;
        height: 36px;
    }
    .cubx-cat-toolbar__density-btn svg {
        width: 16px;
        height: 16px;
    }
}

/* v1.8.1 — Mobile : on cache le switcher de densité en dessous de 768px.
   Sur une grille mobile à 2 colonnes par défaut, les offsets compact (+1=3)
   et airy (-1=1) ne sont pas pertinents : 3 cols = miniatures trop étroites,
   1 col = cartes géantes qui cassent le flow. Le client applique donc le
   baseline BO sans personnalisation possible. Toolbar plus aérée également.
   Le même raisonnement pourrait justifier d'étendre à 768px ou même tablet,
   mais on garde le choix actif sur desktop small + tablet pour l'instant. */
@media (max-width: 768px) {
    .cubx-cat-toolbar__density {
        display: none;
    }
}

/* ---- Cell miniature = cube carré, fond transparent, overflow hidden ---- */
.cubx-cat-grid .product-miniature,
.cubx-cat-grid--with-ads .product-miniature {
    position: relative;
    overflow: hidden;
    aspect-ratio: 1 / 1;
    margin: 0;
    padding: 0;
    background: transparent;
    border: none;
    border-radius: 0;
    list-style: none;
}

/* Neutralise les styles de .card Bootstrap qui englobent la miniature Classic */
.cubx-cat-grid .product-miniature .card,
.cubx-cat-grid .product-miniature .thumbnail-container,
.cubx-cat-grid--with-ads .product-miniature .card,
.cubx-cat-grid--with-ads .product-miniature .thumbnail-container {
    position: absolute;
    inset: 0;
    display: block;
    width: 100%;
    height: 100%;
    margin: 0;
    padding: 0;
    background: transparent;
    border: none;
    border-radius: 0;
    box-shadow: none;
    overflow: hidden;
}

.cubx-cat-grid .product-miniature .card:hover,
.cubx-cat-grid--with-ads .product-miniature .card:hover {
    box-shadow: none;
}

/* Image remplit le cube, grayscale au repos, couleur au hover */
.cubx-cat-grid .product-miniature .product-thumbnail,
.cubx-cat-grid .product-miniature .thumbnail-top,
.cubx-cat-grid--with-ads .product-miniature .product-thumbnail,
.cubx-cat-grid--with-ads .product-miniature .thumbnail-top {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    margin: 0;
    padding: 0;
}

.cubx-cat-grid .product-miniature img,
.cubx-cat-grid--with-ads .product-miniature img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
    filter: grayscale(var(--cubx-grayscale, 0%));
    transition: filter 0.3s ease;
}

.cubx-cat-grid .product-miniature:hover img,
.cubx-cat-grid--with-ads .product-miniature:hover img {
    filter: none;
}

/* Overlay couleur au repos (identique .hb-product::after) */
.cubx-cat-grid .product-miniature::after,
.cubx-cat-grid--with-ads .product-miniature::after {
    content: '';
    position: absolute;
    inset: 0;
    background: var(--cubx-overlay-color, transparent);
    mix-blend-mode: var(--cubx-blend-mode, normal);
    opacity: 0;
    pointer-events: none;
    transition: opacity 0.3s ease;
    z-index: 2;
}

/* v1.8.9 — Overlay visible uniquement sur items marqués .has-overlay
   (JS aléatoire via cubx-core.js initCatOverlay, identique pattern homeblocks).
   Avant v1.8.9 cette règle manquait → overlay jamais visible sur page cat. */
.cubx-cat-grid .product-miniature.has-overlay::after,
.cubx-cat-grid--with-ads .product-miniature.has-overlay::after {
    opacity: var(--cubx-overlay-opacity, 1);
}

.cubx-cat-grid .product-miniature:hover::after,
.cubx-cat-grid--with-ads .product-miniature:hover::after {
    opacity: 0 !important;
}

/* ---- Bande noire « flyover info » (titre + prix) qui remonte au hover ---- */
.cubx-cat-grid .product-miniature .product-description,
.cubx-cat-grid--with-ads .product-miniature .product-description {
    position: absolute;
    inset: auto 0 0 0;
    /* v1.2.0 — Consomme --cubx-info-band-bg émis par H2JHomeBlocksConfig::getCssVars()
       (ecosystem H2JCUBX_FX_GRADIENT_STYLE/TOP/BOTTOM/OPACITY).
       Fallback #000 si la var n'est pas émise (ex: homeblocks désactivé). */
    background: var(--cubx-info-band-bg, #000);
    color: #fff;
    padding: 8px 10px;
    margin: 0;
    transform: translateY(100%);
    transition: transform 0.3s ease;
    z-index: 15;
    pointer-events: none;
    text-align: center;
}

.cubx-cat-grid .product-miniature:hover .product-description,
.cubx-cat-grid--with-ads .product-miniature:hover .product-description {
    transform: translateY(0);
}

/* Titre produit dans la bande noire */
.cubx-cat-grid .product-miniature .product-title,
.cubx-cat-grid .product-miniature .product-title a,
.cubx-cat-grid--with-ads .product-miniature .product-title,
.cubx-cat-grid--with-ads .product-miniature .product-title a {
    font-size: var(--cubx-font-size-name, 10px);
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 1px;
    line-height: 1.3;
    margin: 0 0 4px;
    padding: 0;
    color: #fff;
    text-align: center;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
    text-overflow: ellipsis;
    max-height: 2.6em;
    text-decoration: none;
}

/* Prix dans la bande noire */
.cubx-cat-grid .product-miniature .product-price-and-shipping,
.cubx-cat-grid .product-miniature .price,
.cubx-cat-grid--with-ads .product-miniature .product-price-and-shipping,
.cubx-cat-grid--with-ads .product-miniature .price {
    font-size: var(--cubx-font-size-price, 16px);
    font-weight: 700;
    line-height: 1;
    text-align: center;
    color: #fff;
    margin: 0;
    display: block;
}

.cubx-cat-grid .product-miniature .regular-price,
.cubx-cat-grid--with-ads .product-miniature .regular-price {
    font-size: calc(var(--cubx-font-size-price, 16px) * 0.85);
    color: #fff;
    opacity: 0.7;
    text-decoration: line-through;
    margin-right: 6px;
    font-weight: 400;
}

/* ---- Badges top-left (flags PrestaShop : new, on-sale, pack, discount) ---- */
.cubx-cat-grid .product-miniature .product-flags,
.cubx-cat-grid--with-ads .product-miniature .product-flags {
    position: absolute;
    top: 6px;
    left: 6px;
    display: flex;
    flex-direction: column;
    gap: 3px;
    z-index: 10;
    pointer-events: none;
    margin: 0;
    padding: 0;
}

.cubx-cat-grid .product-miniature .product-flag,
.cubx-cat-grid--with-ads .product-miniature .product-flag {
    display: inline-flex;
    align-items: center;
    padding: 3px 6px;
    border-radius: 2px;
    font-size: 10px;
    font-weight: 700;
    text-transform: uppercase;
    color: #fff;
    letter-spacing: 0.3px;
    white-space: nowrap;
    min-height: 18px;
    line-height: 1;
    position: static;
}

.cubx-cat-grid .product-miniature .product-flag.new,
.cubx-cat-grid--with-ads .product-miniature .product-flag.new {
    background: var(--cubx-pill-positive, #1a7a42);
}

.cubx-cat-grid .product-miniature .product-flag.on-sale,
.cubx-cat-grid .product-miniature .product-flag.discount,
.cubx-cat-grid .product-miniature .product-flag.discount-amount,
.cubx-cat-grid .product-miniature .product-flag.discount-percentage,
.cubx-cat-grid--with-ads .product-miniature .product-flag.on-sale,
.cubx-cat-grid--with-ads .product-miniature .product-flag.discount,
.cubx-cat-grid--with-ads .product-miniature .product-flag.discount-amount,
.cubx-cat-grid--with-ads .product-miniature .product-flag.discount-percentage {
    background: var(--cubx-pill-negative, #b5201e);
}

.cubx-cat-grid .product-miniature .product-flag.pack,
.cubx-cat-grid--with-ads .product-miniature .product-flag.pack {
    background: var(--cubx-pill-attention, #a85d00);
}

.cubx-cat-grid .product-miniature .product-flag.out_of_stock,
.cubx-cat-grid--with-ads .product-miniature .product-flag.out_of_stock {
    background: var(--cubx-pill-neutral, #212121);
}

/* ---- Masque les éléments Classic qu'on ne veut pas dans les cubes ---- */
/* "Aperçu rapide" violet — déjà dans .product-description, masqué par défaut
   et révélé au hover avec la bande noire. On le cache dur puisqu'il n'a pas
   sa place dans le style "cube". */
.cubx-cat-grid .product-miniature .quick-view,
.cubx-cat-grid .product-miniature .highlighted-informations,
.cubx-cat-grid--with-ads .product-miniature .quick-view,
.cubx-cat-grid--with-ads .product-miniature .highlighted-informations {
    display: none !important;
}

/* Rupture de stock label Classic (.product-availability / .out-of-stock) */
.cubx-cat-grid .product-miniature .product-availability,
.cubx-cat-grid--with-ads .product-miniature .product-availability {
    display: none;
}

/* ---- Harmonisation ad-cells avec la grille dense (pas de radius, pas de gap) ---- */
/* v1.5.4 : pinups suivent le même pattern visuel que .hb-product :
     - filter grayscale au repos (via --cubx-grayscale)
     - full color au hover
     - pas d'aspect-ratio forcé : hérite de la ligne grid (comme les cubes produits)
     - pas de border-radius (grille dense sans gap)
     - overlay couleur optionnel identique aux .product-miniature */
.cubx-cat-grid--with-ads .cubx-cat-ad-cell {
    aspect-ratio: 1 / 1;
    border-radius: 0;
    min-height: auto;
    overflow: hidden;
}

.cubx-cat-grid--with-ads .cubx-cat-ad-cell:hover {
    transform: none;           /* override du translateY v1.5.0 */
    box-shadow: none;
}

/* Image pinup : grayscale au repos, couleur au hover (même logique que .hb-product img) */
.cubx-cat-grid--with-ads .cubx-cat-ad-cell__img {
    filter: grayscale(var(--cubx-grayscale, 0%));
    transition: filter 0.3s ease;
}

.cubx-cat-grid--with-ads .cubx-cat-ad-cell:hover .cubx-cat-ad-cell__img {
    filter: none;
}

/* Overlay couleur pour harmoniser avec les miniatures produits (optionnel via --cubx-overlay-*) */
.cubx-cat-grid--with-ads .cubx-cat-ad-cell__figure::after {
    content: '';
    position: absolute;
    inset: 0;
    background: var(--cubx-overlay-color, transparent);
    mix-blend-mode: var(--cubx-blend-mode, normal);
    opacity: 0;
    pointer-events: none;
    transition: opacity 0.3s ease;
    z-index: 2;
}

.cubx-cat-grid--with-ads .cubx-cat-ad-cell.has-overlay .cubx-cat-ad-cell__figure::after {
    opacity: var(--cubx-overlay-opacity, 1);
}

.cubx-cat-grid--with-ads .cubx-cat-ad-cell:hover .cubx-cat-ad-cell__figure::after {
    opacity: 0 !important;
}

/* ==========================================================================
   /v1.5.0 — fin du skin category grid
   ========================================================================== */


/* ==========================================================================
   v1.5.2 — Category page : header refait + miniatures polies
   Corrige le header brut Classic (H1 + thumbnail + count + dropdown de tri
   en vrac), masque le label RUPTURE DE STOCK qui dépasse des cubes,
   ajoute le bouton panier dans la bande noire flyover.
   Scope : body#category + .cubx-cat-grid + .product-miniature.
   ========================================================================== */

/* ---- Header catégorie (H1 + count + tri) --------------------------------- */

/* Wrapper du header Classic — dans PS 8.2, c'est un <section id="js-product-list-top">
   avec à l'intérieur : titre catégorie, image de couverture mini, description,
   count "Il y a N produits", barre de tri. On le transforme en un strip horizontal
   aéré et sobre aligné CUBX. */
body#category #js-product-list-top,
body#category .block-category,
body#category #js-product-list-header {
    background: transparent;
    padding: 0;
    margin: 0 0 20px 0;
    border: none;
    box-shadow: none;
}

/* Titre catégorie — grand, noir, gras, aligné à gauche, majuscules CUBX */
body#category .block-category h1,
body#category #category h1,
body#category .page-heading {
    font-size: clamp(24px, 3vw, 36px);
    font-weight: 800;
    text-transform: uppercase;
    letter-spacing: 1px;
    color: var(--h2j-text, #1a1f2c);
    margin: 0 0 16px 0;
    padding: 0;
    line-height: 1.1;
    text-align: left;
}

/* Thumbnail parasite de la catégorie (petite image 98×98 de couverture
   qui s'affiche sous le H1) — on la masque, la vraie image de couverture
   est déjà dans le hero sidebar gauche via $cubx_hero_cat. */
body#category .block-category #category-description img,
body#category .block-category .category-cover,
body#category .category-cover img,
body#category .category-thumbnail,
body#category #category-description > img:first-child {
    display: none !important;
}

/* Description catégorie — si présente, rendu propre ; sinon espace minimal */
body#category #category-description,
body#category .block-category .category-description {
    font-size: 14px;
    line-height: 1.5;
    color: var(--h2j-text-light, #6b7280);
    margin: 0 0 16px 0;
    max-width: 760px;
}

body#category #category-description:empty,
body#category .block-category .category-description:empty {
    display: none;
}

/* Barre de tri Classic (#products-section-title + .sort-by-row) — le "Trier par"
   brut avec un dropdown et les 5 options listées dessous en une ligne.
   On restructure en bandeau horizontal : [count à gauche] [tri à droite],
   cohérent avec un style e-commerce standard. */
body#category .products-sort-order,
body#category .sort-by-row,
body#category #js-product-list-top {
    display: flex;
    align-items: center;
    justify-content: space-between;
    flex-wrap: wrap;
    gap: 12px;
    padding: 12px 0;
    margin: 0 0 16px 0;
    border-top: 1px solid var(--h2j-border, #e5e7eb);
    border-bottom: 1px solid var(--h2j-border, #e5e7eb);
}

/* Count "Il y a N produits" / "Affichage 1-12 de N" */
body#category .total-products p,
body#category .total-products,
body#category #js-product-list-top .total-products,
body#category .pagination__count {
    font-size: 13px;
    color: var(--h2j-text-light, #6b7280);
    margin: 0;
    padding: 0;
    font-weight: 500;
}

/* Dropdown label "Trier par :" */
body#category .products-sort-order .sort-by,
body#category .sort-by-row .sort-by {
    font-size: 13px;
    font-weight: 600;
    color: var(--h2j-text, #1a1f2c);
    margin-right: 8px;
    text-transform: none;
    letter-spacing: 0;
}

/* Dropdown trigger PS ("Pertinence ▼") */
body#category .products-sort-order .select-title,
body#category .products-sort-order button.select-title,
body#category .sort-by-row button.select-title {
    border: 1px solid var(--h2j-border, #e5e7eb);
    border-radius: var(--cubx-radius, 6px);
    padding: 6px 28px 6px 12px;
    font-size: 13px;
    color: var(--h2j-text, #1a1f2c);
    background: var(--h2j-bg, #fff);
    min-width: 160px;
    cursor: pointer;
}

/* Liste des options brute qui s'affiche en ligne ("Pertinence Nom, A à Z...")
   — rendu par défaut Classic qui n'est pas un vrai <select> mais une
   <div class="dropdown-menu"> dépliable. Masquer le fallback à plat. */
body#category .products-sort-order .dropdown-menu,
body#category .sort-by-row .dropdown-menu {
    display: none;
    position: absolute;
    background: var(--h2j-bg, #fff);
    border: 1px solid var(--h2j-border, #e5e7eb);
    border-radius: var(--cubx-radius, 6px);
    box-shadow: 0 4px 12px rgba(0,0,0,0.08);
    padding: 4px 0;
    z-index: 100;
    min-width: 180px;
}

body#category .products-sort-order .dropdown-menu.show,
body#category .sort-by-row .dropdown-menu.show {
    display: block;
}

body#category .products-sort-order .dropdown-item,
body#category .sort-by-row .dropdown-item {
    display: block;
    padding: 8px 14px;
    font-size: 13px;
    color: var(--h2j-text, #1a1f2c);
    text-decoration: none;
    white-space: nowrap;
    transition: background 0.15s;
}

body#category .products-sort-order .dropdown-item:hover,
body#category .sort-by-row .dropdown-item:hover {
    background: var(--h2j-bg-light, #f8f7ff);
    color: var(--cubx-accent, var(--h2j-primary, #7c3aed));
}

/* Masque le "fallback text" brut (la ligne lavande Pertinence Nom A à Z...) —
   c'est un <select> natif rendu sans style qui apparaît à côté du dropdown
   stylé. Cible le .products-sort-order > select ou les #products-section-title. */
body#category .products-sort-order > select,
body#category #products-section-title {
    display: none !important;
}


/* ---- Miniatures : masquer RUPTURE DE STOCK banner (fix v1.5.2) ----------- */

/* Sur PS 8.2 Classic, la bannière "RUPTURE DE STOCK" peut apparaître à 3 endroits :
   1. .product-flag.out_of_stock dans .product-flags (mon premier essai, OK)
   2. .product-flag.product-available-later / .product-available (second type)
   3. .product-availability dans .product-description (déjà masqué via .product-description
      transform translateY 100%, mais parfois échappé)
   4. <li><span class="out-of-stock">...</span></li> en bloc frère de .product-miniature

   Les 4 sont maintenant masqués dans le scope de la grille catégorie CUBX. */

.cubx-cat-grid .product-flag.out_of_stock,
.cubx-cat-grid .product-flag.product-available-later,
.cubx-cat-grid .product-flag.product-unavailable,
.cubx-cat-grid--with-ads .product-flag.out_of_stock,
.cubx-cat-grid--with-ads .product-flag.product-available-later,
.cubx-cat-grid--with-ads .product-flag.product-unavailable,
.cubx-cat-grid .product-miniature .out-of-stock,
.cubx-cat-grid .product-miniature .product-availability,
.cubx-cat-grid--with-ads .product-miniature .out-of-stock,
.cubx-cat-grid--with-ads .product-miniature .product-availability {
    display: none !important;
}

/* Si l'élément RUPTURE est placé au-dessus de la card en élément frère
   (observé sur ta capture Baillonner) — contenu un .product-flag pleine largeur
   collé en haut de la miniature. Force-masquage : tout .product-flag hors
   de .product-flags (qui est le conteneur stylé top-left). */
.cubx-cat-grid .product-miniature > .product-flag,
.cubx-cat-grid--with-ads .product-miniature > .product-flag {
    display: none !important;
}


/* ---- Bouton panier hover sur miniature (fix v1.5.2) ---------------------- */

/* Placeholder visuel uniquement : le bouton "Ajouter au panier" de la miniature
   Classic est dans .product-description.action ou .highlighted-informations
   (les deux sont masqués). On ajoute un faux bouton via un pseudo-élément qui
   renvoie le clic sur le .product-miniature__link (le <a> qui wrappe tout).

   Esthétique : carré 28×28 blanc transparent bottom-right, apparait au hover
   avec animation translateY, identique à .hb-cart-btn homeblocks. */

.cubx-cat-grid .product-miniature::before,
.cubx-cat-grid--with-ads .product-miniature::before {
    content: '';
    position: absolute;
    inset: auto 6px 6px auto;
    width: 28px;
    height: 28px;
    background: rgba(255, 255, 255, 0.2);
    border-radius: 4px;
    opacity: 0;
    transform: translateY(100%);
    transition: opacity 0.3s ease, transform 0.3s ease;
    z-index: 25;
    pointer-events: none;
    /* Icône panier SVG 16×16 en blanc, injectée via background-image */
    background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='white' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><circle cx='9' cy='21' r='1'/><circle cx='20' cy='21' r='1'/><path d='M1 1h4l2.68 13.39a2 2 0 002 1.61h9.72a2 2 0 002-1.61L23 6H6'/></svg>");
    background-repeat: no-repeat;
    background-position: center;
    background-size: 16px 16px;
    background-color: rgba(255, 255, 255, 0.2);
}

.cubx-cat-grid .product-miniature:hover::before,
.cubx-cat-grid--with-ads .product-miniature:hover::before {
    opacity: 1;
    transform: translateY(0);
}


/* ---- Polish des badges product-flag (fix v1.5.2) ------------------------- */

/* Les badges new/discount existent déjà en v1.5.0, on raffine leur apparence :
   texte plus lisible, ombrage léger, gap plus serré. */
.cubx-cat-grid .product-miniature .product-flags,
.cubx-cat-grid--with-ads .product-miniature .product-flags {
    gap: 4px;
}

.cubx-cat-grid .product-miniature .product-flag,
.cubx-cat-grid--with-ads .product-miniature .product-flag {
    box-shadow: 0 1px 3px rgba(0, 0, 0, 0.15);
    font-size: 11px;
    padding: 4px 7px;
    letter-spacing: 0.4px;
}


/* ==========================================================================
   /v1.5.2 — fin des corrections category page
   ========================================================================== */


/* ==========================================================================
   v1.5.3 — Header catégorie CUBX : titre + description + barre d'outils
   Structure rendue par templates/catalog/listing/category.tpl :
     .cubx-cat-header    → H1 + description + toggle "En savoir plus"
     .cubx-cat-toolbar   → [Search] [Trier par]
   Masque le rendu Classic parasite (count, fallback select, bandeau tri natif).
   ========================================================================== */

/* ---- v1.5.4 : restyling du H1 + description natifs Classic -------------- */

/* STRUCTURE RÉELLE Classic 8.2 (confirmée via view-source) :
     #js-product-list-header
       └─ .block-category.card.card-block
            ├─ h1.h1                     ← titre catégorie
            └─ .block-category-inner
                 └─ #category-description ← description (img + texte)

   On ne masque PAS .block-category : on le restyle directement pour obtenir
   le look CUBX (titre centré gros uppercase + description centrée sobre +
   bouton "Read more" injecté au runtime par theme.js). */

body#category #js-product-list-header {
    margin: 0;
    padding: 0;
    background: transparent;
}

body#category .block-category {
    display: flex;
    flex-direction: column;
    align-items: center;
    padding: 24px 20px 20px;
    margin: 0 0 16px 0;
    background: transparent;
    border: none;
    box-shadow: none;
    border-radius: 0;
}

/* Titre H1 catégorie — style CUBX (centré, uppercase, gras, grand) */
body#category .block-category > h1,
body#category .block-category > .h1,
body#category .block-category h1.h1 {
    font-size: clamp(24px, 3vw, 38px);
    font-weight: 800;
    text-transform: uppercase;
    letter-spacing: 1.5px;
    color: var(--h2j-text, #1a1f2c);
    margin: 0 0 16px 0;
    padding: 0;
    line-height: 1.1;
    text-align: center;
    width: 100%;
}

/* Description catégorie — wrapper .block-category-inner */
body#category .block-category .block-category-inner {
    width: 100%;
    max-width: 760px;
    text-align: center;
}

/* Image miniature de la catégorie dans la description — on la masque :
   l'image de couverture est déjà dans la sidebar hero gauche. */
body#category .block-category-inner img,
body#category #category-description img:first-child,
body#category .category-cover img {
    display: none !important;
}

/* Description texte */
body#category #category-description,
body#category .block-category-inner #category-description {
    position: relative;
    font-size: 14px;
    line-height: 1.6;
    color: var(--h2j-text-light, #4a5260);
    margin: 0;
    padding: 0;
    text-align: center;
}

body#category #category-description > *:first-child { margin-top: 0; }
body#category #category-description > *:last-child  { margin-bottom: 0; }

/* Mode "replié" : injecté au runtime par theme.js avec data-cubx-cat-desc-long */
body#category #category-description[data-cubx-cat-desc-long]:not(.is-expanded) {
    display: -webkit-box;
    -webkit-line-clamp: 3;
    -webkit-box-orient: vertical;
    overflow: hidden;
    max-height: calc(1.6em * 3);
}

/* Mode "déplié" */
body#category #category-description[data-cubx-cat-desc-long].is-expanded {
    display: block;
    -webkit-line-clamp: unset;
    max-height: none;
    overflow: visible;
}

/* Bouton toggle "Read more" / "Show less" — injecté au runtime par theme.js */
body#category .cubx-cat-desc-toggle {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    margin: 10px 0 0 0;
    padding: 6px 14px;
    background: transparent;
    border: none;
    border-radius: var(--cubx-radius, 6px);
    font-size: 13px;
    font-weight: 600;
    color: var(--cubx-accent, var(--h2j-primary, #7c3aed));
    cursor: pointer;
    text-transform: uppercase;
    letter-spacing: 0.5px;
    transition: background 0.2s ease, color 0.2s ease;
}

body#category .cubx-cat-desc-toggle:hover,
body#category .cubx-cat-desc-toggle:focus-visible {
    background: var(--h2j-bg-light, #f8f7ff);
    color: var(--cubx-accent-2, var(--h2j-primary-dark, #6d28d9));
    outline: none;
}

body#category .cubx-cat-desc-toggle__icon {
    display: inline-block;
    transition: transform 0.25s ease;
    font-size: 10px;
}

body#category .cubx-cat-desc-toggle[aria-expanded="true"] .cubx-cat-desc-toggle__icon {
    transform: rotate(180deg);
}

/* Count ("Il y a N produits" / "Showing X of Y") — v1.8.11 : visible par défaut,
   masquable via le toggle BO Category Header > Show product count (classe
   html.cubx-cat-no-count). Avant v1.8.11 le count était inconditionnellement
   masqué ici, rendant le toggle BO inopérant.
   Style : petit label discret aligné à gauche dans la toolbar. */
body#category .total-products,
body#category #js-product-list-top .total-products,
body#category .pagination__count,
body#category .products-selection .total-products,
body#category .products-selection p.total {
    font-size: 12px;
    color: var(--h2j-text-light, #6b7280);
    text-transform: uppercase;
    letter-spacing: 0.5px;
    font-weight: 600;
    margin: 0;
    padding: 0;
}

/* Fallback inline list des options tri (Pertinence Nom, A à Z Nom, ...) */
body#category .products-sort-order .select-list,
body#category .products-sort-order > select,
body#category #products-section-title {
    display: none !important;
}

/* Ancien bandeau tri Classic — notre toolbar override le remplace proprement */
body#category .products-sort-order:not(.cubx-cat-toolbar),
body#category .sort-by-row:not(.cubx-cat-toolbar) {
    display: none !important;
}


/* ---- Barre d'outils : [Search] [Trier par] ------------------------------ */

.cubx-cat-toolbar {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 12px;
    flex-wrap: wrap;
    padding: 16px 20px;
    margin: 0 0 20px 0;
    border-top: 1px solid var(--h2j-border, #e5e7eb);
    border-bottom: 1px solid var(--h2j-border, #e5e7eb);
}

.cubx-cat-toolbar__btn {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    padding: 10px 18px;
    min-height: 40px;
    background: var(--h2j-bg, #fff);
    border: 1px solid var(--h2j-border, #e5e7eb);
    border-radius: var(--cubx-radius, 6px);
    font-size: 13px;
    font-weight: 600;
    color: var(--h2j-text, #1a1f2c);
    text-transform: uppercase;
    letter-spacing: 0.5px;
    cursor: pointer;
    transition: background 0.2s ease, border-color 0.2s ease, color 0.2s ease;
    white-space: nowrap;
}

.cubx-cat-toolbar__btn:hover,
.cubx-cat-toolbar__btn:focus-visible {
    background: var(--h2j-bg-light, #f8f7ff);
    border-color: var(--cubx-accent, var(--h2j-primary, #7c3aed));
    color: var(--cubx-accent, var(--h2j-primary, #7c3aed));
    outline: none;
}

.cubx-cat-toolbar__btn-icon {
    font-size: 16px;
    line-height: 1;
}

.cubx-cat-toolbar__btn-caret {
    font-size: 10px;
    opacity: 0.7;
    transition: transform 0.2s ease;
}

.cubx-cat-toolbar__btn--sort[aria-expanded="true"] .cubx-cat-toolbar__btn-caret {
    transform: rotate(180deg);
}

/* État visuel quand Search n'est pas encore câblé (pas de h2jsearch installé) :
   on rend le bouton légèrement moins éclatant pour signaler qu'il est inerte.
   Override facile par h2jsearch quand il se branchera via data-cubx-cat-search. */
.cubx-cat-toolbar__btn--search:not([data-cubx-cat-search-ready]),
.cubx-cat-toolbar__btn--filter:not([data-cubx-cat-search-ready]) {
    opacity: 0.7;
}

.cubx-cat-toolbar__btn--search:not([data-cubx-cat-search-ready]):hover,
.cubx-cat-toolbar__btn--filter:not([data-cubx-cat-search-ready]):hover {
    opacity: 1;
}

/* ---- Dropdown de tri ---------------------------------------------------- */

.cubx-cat-toolbar__sort {
    position: relative;
}

.cubx-cat-toolbar__sort-menu {
    position: absolute;
    top: calc(100% + 4px);
    right: 0;
    min-width: 220px;
    margin: 0;
    padding: 6px 0;
    list-style: none;
    background: var(--h2j-bg, #fff);
    border: 1px solid var(--h2j-border, #e5e7eb);
    border-radius: var(--cubx-radius, 6px);
    box-shadow: 0 6px 20px rgba(0, 0, 0, 0.12);
    z-index: 100;
    opacity: 0;
    visibility: hidden;
    transform: translateY(-4px);
    transition: opacity 0.18s ease, transform 0.18s ease, visibility 0.18s;
}

.cubx-cat-toolbar__sort.is-open .cubx-cat-toolbar__sort-menu {
    opacity: 1;
    visibility: visible;
    transform: translateY(0);
}

.cubx-cat-toolbar__sort-item {
    display: block;
    padding: 10px 16px;
    font-size: 13px;
    color: var(--h2j-text, #1a1f2c);
    text-decoration: none;
    white-space: nowrap;
    transition: background 0.15s ease, color 0.15s ease;
}

.cubx-cat-toolbar__sort-item:hover,
.cubx-cat-toolbar__sort-item:focus-visible {
    background: var(--h2j-bg-light, #f8f7ff);
    color: var(--cubx-accent, var(--h2j-primary, #7c3aed));
    text-decoration: none;
    outline: none;
}

.cubx-cat-toolbar__sort-item.is-current {
    background: var(--cubx-accent, var(--h2j-primary, #7c3aed));
    color: #fff;
    font-weight: 700;
}

.cubx-cat-toolbar__sort-item.is-current:hover,
.cubx-cat-toolbar__sort-item.is-current:focus-visible {
    background: var(--cubx-accent-2, var(--h2j-primary-dark, #6d28d9));
    color: #fff;
}

/* Mobile : le dropdown prend toute la largeur, centré */
@media (max-width: 560px) {
    .cubx-cat-toolbar {
        gap: 8px;
        padding: 12px 10px;
    }
    .cubx-cat-toolbar__btn {
        padding: 8px 14px;
        font-size: 12px;
    }
    .cubx-cat-toolbar__btn-label {
        font-size: 12px;
    }
    .cubx-cat-toolbar__sort-menu {
        right: 50%;
        transform: translateX(50%) translateY(-4px);
        min-width: min(280px, calc(100vw - 40px));
    }
    .cubx-cat-toolbar__sort.is-open .cubx-cat-toolbar__sort-menu {
        transform: translateX(50%) translateY(0);
    }
}


/* ==========================================================================
   /v1.5.3 — fin du header catégorie CUBX
   ========================================================================== */


/* ==========================================================================
   v1.2.0 — PRODUCT INFO DISPLAY TOGGLES (catégorie CUBX)
   ==========================================================================
   Les 3 toggles BO (Thème CUBX > Product info display : name / price /
   strikethrough) pilotent l'affichage des infos sous les miniatures dans la
   grille catégorie CUBX. CSS vars --cubx-show-* injectées par
   H2JHomeBlocksConfig::getCssVars() (ecosystem H2JCUBX_PROD_SHOW_*).

   Le 4e toggle (cart) n'est pas appliqué ici car la miniature catégorie Classic
   n'a pas de bouton cart natif — il est uniquement rendu dans les cards
   homeblocks (.hb-cart-btn) avec ses propres règles.

   Fallbacks : si les vars ne sont pas émises (homeblocks désactivé ou
   non installé), tout reste visible via le display d'origine.
   ========================================================================== */
.cubx-cat-grid .product-miniature .product-title,
.cubx-cat-grid--with-ads .product-miniature .product-title {
    display: var(--cubx-show-name, -webkit-box);
}
.cubx-cat-grid .product-miniature .product-price-and-shipping,
.cubx-cat-grid .product-miniature .price,
.cubx-cat-grid--with-ads .product-miniature .product-price-and-shipping,
.cubx-cat-grid--with-ads .product-miniature .price {
    display: var(--cubx-show-price, block);
}
.cubx-cat-grid .product-miniature .regular-price,
.cubx-cat-grid--with-ads .product-miniature .regular-price {
    display: var(--cubx-show-strikethrough, inline);
}

/* ═══════════════════════════════════════════════════════════
   23. MOBILE TAP-TO-REVEAL (v1.5.6) — pattern idyll.fr

   Le comportement tap-to-reveal est intégralement piloté par JS
   (cubxInitTapToReveal() dans theme.js) via style inline direct sur
   .hb-product__info / .hb-flex-item__info / .hb-cart-btn.

   Le CSS desktop :hover natif continue à fonctionner normalement sans
   override — sur desktop, le JS ne s'active pas (pas de touch detection).

   Seule la classe `body.cubx-touch-device` (ajoutée par le JS) et le
   feedback visuel sur les cubes révélés (outline accent) sont gérés
   en CSS ici.
   ══════════════════════════════════════════════════════════ */

/* Feedback visuel sur le cube révélé (1er tap effectué). Outline au
   lieu de border pour ne pas décaler la mise en page. */
body.cubx-touch-device [data-band-visible="true"] {
    outline: 2px solid var(--cubx-accent, #7c4dff);
    outline-offset: -2px;
}

/* ═══════════════════════════════════════════════════════════
   24. HERO ACTIVE — full-width container (v1.6.5)
   =========================================================
   Fix de l'espace parasite entre le panel hero (à gauche) et le
   content column (à droite) sur pages catégorie avec hero-gallery.

   CAUSE :
     Le panel hero est `position: fixed; left: 0; width: var(--cubx-hero-w);`
     (38% par défaut), donc ancré sur le VIEWPORT.
     Mais `.cubx-hero-content` a `margin-left: 38%` calculé par rapport à son
     PARENT .container Bootstrap (max-width: 1280px, centré auto).
     
     Sur un viewport > 1280px, le .container est plus étroit que le viewport,
     donc 38% du container ≠ 38% du viewport → décalage visible entre le bord
     droit du panel hero et le premier élément du content.
     
     Exemple concret viewport 1920px :
       • Panel hero : 0 → 38% × 1920 = 730px
       • Container : centré, 1280px large, donc x=(1920-1280)/2=320px à 1600px
       • Content margin-left = 38% × 1280 = 486px (relatif au container)
       • Donc content commence à 320 + 486 = 806px (viewport)
       • GAP = 806 - 730 = 76px entre fin panel et début content

   FIX :
     Neutraliser les contraintes .container (max-width + padding-left/right) et
     .row (margin gutters Bootstrap) dans le scope d'une page hero-active.
     Même traitement que `body.page-index` applique pour la homepage.

   SÉLECTEUR :
     body:has(.cubx-hero-active) — supporté sur tous navigateurs modernes
     (Chrome 105+, Safari 15.4+, Firefox 121+). Fallback : la hero panel reste
     fonctionnelle sans ce fix sur vieux navigateurs, juste avec un léger gap.
   ═══════════════════════════════════════════════════════════ */
body:has(.cubx-hero-active) #wrapper > .container {
    max-width: none;
    padding-left: 0;
    padding-right: 0;
    width: 100%;
}

body:has(.cubx-hero-active) #wrapper > .container > .row {
    margin-left: 0;
    margin-right: 0;
}

body:has(.cubx-hero-active) #content-wrapper {
    padding-left: 0;
    padding-right: 0;
}

/* Neutralise également le padding Bootstrap 4 .card.card-block que Classic PS 8.2
   applique au wrapper <section id="content" class="page-content card card-block">.
   Sans ce fix, le card-block ajoute ~20px de padding-left supplémentaire qui
   s'ajoute au gap. */
body:has(.cubx-hero-active) .cubx-hero-content .card.card-block,
body:has(.cubx-hero-active) .cubx-hero-content > #content.page-content,
body:has(.cubx-hero-active) .cubx-hero-content section.page-content {
    padding-left: 0;
    padding-right: 0;
    background: transparent;
    border: none;
    box-shadow: none;
}

/* Sur mobile (<992px), la hero passe en statique pleine largeur (cf section 19),
   donc ces règles ne doivent pas s'appliquer : on restaure le comportement natif
   Bootstrap pour que le content bénéficie de ses paddings normaux. */
@media (max-width: 991px) {
    body:has(.cubx-hero-active) #wrapper > .container {
        max-width: 1280px;
        padding-left: 15px;
        padding-right: 15px;
    }
    body:has(.cubx-hero-active) #wrapper > .container > .row {
        margin-left: -15px;
        margin-right: -15px;
    }
    body:has(.cubx-hero-active) #content-wrapper {
        padding-left: 15px;
        padding-right: 15px;
    }
}

/* ══════════════════════════════════════════════════════════
   25. CATEGORY HEADER TOGGLES — v1.8.9 (Sprint cat header)
   =========================================================
   Les 6 toggles BO (Thème CUBX > Category Page > Header + Toolbar) pilotent
   l'affichage des éléments suivants sur la page catégorie CUBX.

   Les classes html.cubx-cat-no-* sont ajoutées par h2jecosystem
   hookDisplayHeader (v2.14.10+) via un script inline sur <html> avant le
   DOMContentLoaded, évitant le flash d'élément visible.

   Clés consommées :
     H2JCUBX_CAT_SHOW_BREADCRUMB  → .cubx-cat-no-breadcrumb
     H2JCUBX_CAT_SHOW_TITLE       → .cubx-cat-no-title
     H2JCUBX_CAT_SHOW_DESCRIPTION → .cubx-cat-no-description
     H2JCUBX_CAT_SHOW_FILTER      → .cubx-cat-no-filter
     H2JCUBX_CAT_SHOW_SORT        → .cubx-cat-no-sort
     H2JCUBX_CAT_SHOW_COUNT       → .cubx-cat-no-count

   Description collapsible (H2JCUBX_CAT_DESC_COLLAPSIBLE + DESC_MAX_CHARS) est
   géré par JS dans cubx-core.js initCatDescCollapsible qui lit window.cubxCatDesc.
   ══════════════════════════════════════════════════════════ */

/* Breadcrumb : cache le wrapper injecté par cubx-theme + le nav Classic */
html.cubx-cat-no-breadcrumb .cubx-cat-breadcrumb-wrap,
html.cubx-cat-no-breadcrumb body#category .breadcrumb,
html.cubx-cat-no-breadcrumb body#category nav[aria-label="Breadcrumb"] {
    display: none !important;
}

/* Titre H1 catégorie */
html.cubx-cat-no-title body#category .block-category > h1,
html.cubx-cat-no-title body#category .block-category > .h1,
html.cubx-cat-no-title body#category .block-category h1.h1,
html.cubx-cat-no-title body#category .page-heading {
    display: none !important;
}

/* Description catégorie (+ inner wrapper + bouton toggle collapsible) */
html.cubx-cat-no-description body#category #category-description,
html.cubx-cat-no-description body#category .block-category-inner,
html.cubx-cat-no-description body#category .cubx-cat-desc-toggle {
    display: none !important;
}

/* Si ni titre ni description : cache aussi le bloc .block-category pour éviter le padding vide */
html.cubx-cat-no-title.cubx-cat-no-description body#category .block-category {
    display: none !important;
}

/* Toolbar : bouton Filter */
html.cubx-cat-no-filter .cubx-cat-toolbar__btn--filter {
    display: none !important;
}

/* Toolbar : dropdown Sort (bouton + menu) */
html.cubx-cat-no-sort .cubx-cat-toolbar__sort {
    display: none !important;
}

/* Count "Il y a N produits" / "Showing X of Y" — déjà masqué par défaut
   (cf section 23 body#category .total-products { display:none !important }),
   mais on garde la règle cat-no-count explicite pour la cohérence + futur
   unhide si on le réintroduit visuellement en non-default. */
html.cubx-cat-no-count body#category .total-products,
html.cubx-cat-no-count body#category #js-product-list-top .total-products,
html.cubx-cat-no-count body#category .pagination__count,
html.cubx-cat-no-count body#category .pagination-nav .text-muted,
html.cubx-cat-no-count body#category .pagination-nav > p {
    display: none !important;
}

/* Si toolbar devient vide (ni filter ni sort ni density sur mobile), on cache
   la toolbar entière pour éviter le padding + bordures haut/bas vides.
   Le switcher density est masqué sur mobile uniquement, donc sur desktop s'il
   reste visible la toolbar reste affichée même avec cat-no-filter + cat-no-sort. */
html.cubx-cat-no-filter.cubx-cat-no-sort .cubx-cat-toolbar:not(:has(.cubx-cat-toolbar__density:not([hidden]))) {
    display: none !important;
}

/* ════════════════════════════════════════════════════════
   26. CATEGORY ADS FORMATS — v1.8.13 (h2jhomeblocks v3.33.0)
   =========================================================
   Les ads peuvent prendre 4 formats de grille (champ BO) :
     - square  → 1×1 (cellule standard, équivalent miniature produit)
     - tall    → 1×2 (portrait, hauteur double — pinup pleine hauteur)
     - wide    → 2×1 (bannère horizontale — ex: offre combo)
     - hero    → 2×2 (hero promo, mis en avant maximal)

   Les classes .cubx-cat-ad-cell--fmt-{format} pilotent grid-column / grid-row.
   L'image conserve object-fit:cover (overflow caché), donc pas de crop
   disgracieux même si l'image source n'a pas le bon ratio.

   Responsive :
     - Desktop : formats appliqués tels quels
     - Tablet (768-992px) : wide/hero restent 2×X, mais comme la grille est
       en 3 colonnes, ça reste lisible
     - Mobile (< 768px) : tous les formats reviennent à 1×1 (square) car la
       grille 2 colonnes ne tolère pas un spread 2×X sans casser le layout

   IMPORTANT : l'algorithme de placement PHP (H2JHBAdMedia::placeRandom) ne
   connaît pas les formats — donc un wide/hero placé sur la dernière ligne
   peut déborder visuellement. Pour un comportement robuste, l'utilisateur
   BO peut limiter les formats non-carrés aux premières positions en ajustant
   le poids (weight élevé = placé en priorité).
   ════════════════════════════════════════════════════════ */

/* square = défaut, pas de span explicite (1×1) */
.cubx-cat-ad-cell--fmt-square {
    grid-column: span 1;
    grid-row:    span 1;
}

/* tall = 1×2 (1 colonne, 2 lignes — portrait hauteur double) */
.cubx-cat-ad-cell--fmt-tall {
    grid-column: span 1;
    grid-row:    span 2;
    aspect-ratio: auto;   /* override du 1/1 imposé aux cellules standards */
}

/* wide = 2×1 (2 colonnes, 1 ligne — bannère horizontale) */
.cubx-cat-ad-cell--fmt-wide {
    grid-column: span 2;
    grid-row:    span 1;
    aspect-ratio: auto;
}

/* hero = 2×2 (2 colonnes, 2 lignes — hero promo maximal) */
.cubx-cat-ad-cell--fmt-hero {
    grid-column: span 2;
    grid-row:    span 2;
    aspect-ratio: auto;
}

/* Image dans une cellule non-carrée : remplit entièrement la zone */
.cubx-cat-ad-cell--fmt-tall .cubx-cat-ad-cell__img,
.cubx-cat-ad-cell--fmt-wide .cubx-cat-ad-cell__img,
.cubx-cat-ad-cell--fmt-hero .cubx-cat-ad-cell__img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    object-position: center center;
}

/* Mobile : tous les formats redeviennent square pour que la grille 2 cols
   reste propre. Un hero 2×2 sur une grille 2 cols prendrait toute la ligne
   et la ligne suivante — mais ça casse le rythme visuel global. */
@media (max-width: 768px) {
    .cubx-cat-ad-cell--fmt-tall,
    .cubx-cat-ad-cell--fmt-wide,
    .cubx-cat-ad-cell--fmt-hero {
        grid-column: span 1;
        grid-row:    span 1;
        aspect-ratio: 1 / 1;
    }
}

/* ═══════════════════════════════════════════════════════════════════════
   v2.4.0 — GRILLE CATÉGORIE : DENSITY OFFSET FO + HERO AUTO -2
   ═══════════════════════════════════════════════════════════════════════

   Modèle :
     - cols_baseline (BO)        : valeur "Normal" choisie par l'admin
                                   (consomme --cubx-cat-grid-cols-no-hero)
     - density_offset (FO)       : offset client {-2, -1, 0, +1, +2}
                                   posé via --cubx-density-offset sur <html>
                                   par cubx-cat-density.js (localStorage)
     - hero_open offset (auto)   : -2 quand hero ouvert
     - mobile (auto)             : 2 cols figé, ignore tous les offsets

   Formule cols affichées (v2.4.1 — plancher 2) :
     cols = max(2, baseline + density_offset - (hero_open ? 2 : 0))

   Niveaux density (4 — v2.4.1 : retrait "Très aéré") :
     +2 = Ultra-dense
     +1 = Dense
      0 = Normal (défaut)
     -1 = Aéré

   Variables CSS :
     --cubx-cat-grid-cols-no-hero  (BO baseline, default 4)
     --cubx-density-offset         (FO, default 0)
     --cubx-cat-grid-cols-mobile   (BO, default 2 — figé sur mobile)
   ═══════════════════════════════════════════════════════════════════════ */

/* Default offset = 0 si jamais le JS n'a pas encore posé la variable */
:root {
    --cubx-density-offset: 0;
}

/* Vue 1 — Desktop sans hero / hero fermé
   cols = max(2, baseline + density_offset)
   v2.4.1 : plancher 2 cols partout pour garantir la lisibilité */
#js-product-list .products {
    display: grid !important;
    grid-template-columns: repeat(
        max(2, calc(var(--cubx-cat-grid-cols-no-hero, 4) + var(--cubx-density-offset, 0))),
        1fr
    ) !important;
    gap: 0 !important;
}

/* Vue 2 — Desktop avec hero ouvert
   cols = max(2, baseline + density_offset - 2)
   v2.4.1 : plancher 2 cols (clamp Aéré+hero à 2 au lieu de 1) */
body.cubx-hero-active:not(.cubx-hero-collapsed) #js-product-list .products {
    grid-template-columns: repeat(
        max(2, calc(var(--cubx-cat-grid-cols-no-hero, 4) + var(--cubx-density-offset, 0) - 2)),
        1fr
    ) !important;
}

/* Vue 3 — Mobile (<768px) : 2 cols figé, ignore offset et hero */
@media (max-width: 768px) {
    #js-product-list .products,
    body.cubx-hero-active:not(.cubx-hero-collapsed) #js-product-list .products {
        grid-template-columns: repeat(var(--cubx-cat-grid-cols-mobile, 2), 1fr) !important;
    }
}
