/* ==========================================================================
   Shops — feuille de style front (chargée sur tout le site).
   Minimal : ne fait que ce que Bootstrap ne couvre pas déjà.

   Conventions de nommage (surcharge thème facile) :
     .shops-index-* / .shops-index …    listing catalogue + recherche
     .shops-detail-*                    fiche produit
     .shops-cart-*                      panier (page + offcanvas + cross-sell)
     .shops-checkout-*                  tunnel de commande
     .shops-checkout-confirmation …     page de fin d'achat (après paiement)

   Source : modules/Shops/Assets/css/shops.css
   → copier dans public/modules/shops/css/shops.css après modification.
   ========================================================================== */


/* Badge compteur panier (icône nav) : fond noir, texte blanc. */
.shops-cart-badge { background: #000; color: #fff; }

/* Détails datés (créneau/dates/heures/lieu) dans le résumé du checkout. */
.shops-checkout-summary-meta { font-size: .78rem; color: #6b7177; line-height: 1.35; margin-top: .1rem; }

/* Bon cadeau prestation : page « Utiliser mon bon » (saisie code + choix date). */
.shops-voucher-redeem { max-width: 720px; }
.shops-voucher-thumb { width: 72px; height: 72px; object-fit: cover; border-radius: 8px; }

/* Compte à rebours « occupation du créneau » (hébergement/activité/billet) :
   bannière ambre en haut du panier / du checkout, rouge une fois expiré. */
/* `align-items: flex-start` + icône non rétractable : sur mobile la phrase passe
   sur deux lignes et l'horloge se retrouvait centrée à cheval entre les deux.
   Le rayon suit la charte. */
.shops-cart-hold-timer {
    margin: 0 0 .75rem; padding: .55rem .75rem;
    font-size: .85rem; line-height: 1.35;
    background: #fff7ed; color: #9a3412; border: 1px solid #fed7aa;
    border-radius: var(--card-radius, 8px);
}
.shops-hold-timer__row { display: flex; align-items: baseline; gap: .5rem; }
.shops-hold-timer__text { flex: 1 1 auto; }
.shops-cart-hold-timer strong { font-variant-numeric: tabular-nums; white-space: nowrap; }
/* « En savoir plus » : lien discret, hérite de la couleur du bandeau. */
.shops-hold-timer__more {
    flex: 0 0 auto; background: none; border: 0; padding: 0;
    font: inherit; font-size: .8rem; font-weight: 600;
    color: inherit; text-decoration: underline; text-underline-offset: 2px;
    cursor: pointer; white-space: nowrap;
}
.shops-hold-timer__more:hover, .shops-hold-timer__more:focus-visible { opacity: .75; }
/* Explication dépliable : rattachée au bandeau par un filet, texte un cran plus petit. */
.shops-hold-timer__help {
    margin-top: .5rem; padding-top: .5rem; border-top: 1px solid #fed7aa;
    font-size: .82rem;
}
.shops-hold-timer__help p { line-height: 1.45; }
.shops-cart-hold-timer.is-expired { background: #fef2f2; color: #b91c1c; border-color: #fecaca; }
.shops-cart-hold-timer.is-expired .shops-hold-timer__help { border-top-color: #fecaca; }

/* Veille de disponibilité du tunnel : ce qui vient de devenir indisponible
   pendant que le client remplit. Même grammaire visuelle que le compte à rebours
   expiré — c'est la même mauvaise nouvelle, dite plus tôt. */
.shops-checkout-availability {
    margin: 0 0 .75rem; padding: .6rem .8rem;
    font-size: .85rem; line-height: 1.35;
    background: #fef2f2; color: #b91c1c; border: 1px solid #fecaca;
    border-radius: var(--card-radius, 8px);
}
.shops-checkout-availability ul { list-style: disc; }
.shops-checkout-availability li + li { margin-top: .35rem; }
.shops-checkout-availability .js-indispo-remove { color: inherit; text-decoration: underline; }
.shops-checkout-availability-swap { display: flex; flex-wrap: wrap; align-items: center; gap: .35rem; }
/* `text-transform: none` : la charte met les boutons en majuscules, ce qui
   convient à « VALIDER » mais pas à un NOM DE PRODUIT — « MUG CÉRAMIQUE
   ARTISANAL » se lit mal et n'est plus le titre du catalogue. */
.shops-checkout-availability-swap .btn {
    --bs-btn-padding-y: .15rem; --bs-btn-padding-x: .5rem; --bs-btn-font-size: .78rem;
    background: var(--ck-surface, #fff); border-color: var(--ck-line, #d5d7da);
    color: var(--ck-text, #333);
    text-transform: none; letter-spacing: normal; font-weight: 500;
}
.shops-checkout-availability-swap .btn:hover { background: var(--ck-hover, #f7f8fa); }

/* ==========================================================================
   1. SHOPS-INDEX — listing catalogue / recherche
   ========================================================================== */

/* Le partial AJAX _products.php réinjecte sa propre .row dans #shops-products :
   on garde ce conteneur en bloc simple pour éviter toute .row imbriquée
   (qui rétrécirait la grille au contenu minimal). */
#shops-products { display: block; }
#shops-products.is-loading { opacity: .5; pointer-events: none; transition: opacity .15s; }

/* Pastille « N filtres actifs » du panneau. Elle était en `bg-primary`, c'est-à-dire
   le bleu PAR DÉFAUT de Bootstrap (#0d6efd) — une couleur qui n'existe nulle part
   dans la charte du site. On reprend le bouton secondaire du thème, avec repli sur
   le bleu d'origine si aucun jeton n'est défini. */
.shops-badge-charte {
    background: var(--btn-2-bg, var(--color-2, #0d6efd));
    color: var(--btn-2-color, #fff);
}

/* --- Squelette de chargement de la grille --------------------------------- */
/* Pendant une recherche, la grille était seulement estompée : on continuait à
   lire les résultats PRÉCÉDENTS en plus pâle, sans savoir s'ils correspondaient
   à ce qu'on venait de taper. Les squelettes disent « ce n'est plus le
   résultat ». Ils reprennent les classes réelles de la carte, donc les mêmes
   hauteurs et les mêmes points de rupture — aucune dimension n'est recopiée. */
#shops-products.is-skeleton { opacity: 1; }              /* pas d'estompe par-dessus */
.shops-skeleton { box-shadow: none; transform: none; width: 100%; }
.shops-skeleton .product-image { position: relative; }

.shops-skeleton .sk {
    display: block;
    background: var(--aw-border, #e6e8ee);
    border-radius: 6px;
    /* Le dégradé qui balaie : deux fois la largeur du bloc, décalé en boucle. */
    background-image: linear-gradient(90deg,
        rgba(255,255,255,0) 0%, rgba(255,255,255,.65) 50%, rgba(255,255,255,0) 100%);
    background-size: 200% 100%;
    background-repeat: no-repeat;
    animation: shops-sk-balayage 1.2s ease-in-out infinite;
}
.shops-skeleton .sk-img   { width: 100%; aspect-ratio: 1 / 1; border-radius: 0; }
.shops-skeleton .sk-line  { height: .7rem; margin: 0 0 .5rem; }
.shops-skeleton .sk-brand { width: 45%; height: .55rem; }
.shops-skeleton .sk-title { width: 100%; }
.shops-skeleton .sk-title--court { width: 65%; }
.shops-skeleton .sk-chips { display: flex; gap: .35rem; margin: .2rem 0 .9rem; }
.shops-skeleton .sk-chip  { width: 3.6rem; height: 1.1rem; border-radius: 999px; }
.shops-skeleton .sk-price { width: 40%; height: 1rem; margin-bottom: .6rem; }
.shops-skeleton .sk-btn   { height: 2.1rem; border-radius: .375rem; }

@keyframes shops-sk-balayage {
    from { background-position: 200% 0; }
    to   { background-position: -200% 0; }
}

/* Un balayage continu peut déclencher malaises et migraines : on garde les blocs,
   on retire le mouvement. */
@media (prefers-reduced-motion: reduce) {
    .shops-skeleton .sk { animation: none; background-image: none; }
}

/* --- Carte produit ------------------------------------------------------- */
.shops-index .product { transition: box-shadow .2s, transform .2s; }
.shops-index .product:hover {
    box-shadow: var(--card-shadow-hover, 0 .5rem 1.25rem rgba(0, 0, 0, .1)) !important;
    transform: translateY(-3px);
}
.shops-index .product-image img { transition: transform .3s, opacity .2s; }
.shops-index .product:hover .product-image img { transform: scale(1.04); }

/* --- Carte produit : actions rapides (⋮) / partage / wishlist -------------
   GLOBAL (non scopé .shops-index) : la carte _product_card est réutilisée
   partout — catalogue, cross-sell fiche, widget [shops]. Déplacé ici depuis
   le <style> inline de catalog/index.php pour un rendu identique partout. */
.product-image { position: relative; }
/* Badge VENDEUR (marketplace) — bas-gauche de l'image, cliquable au-dessus du
   stretched-link du titre (z-index > 2). */
.product__vendor-badge {
    z-index: 6; max-width: calc(100% - 1rem);
    display: inline-flex; align-items: center; gap: .45rem;
    padding: .28rem .6rem .28rem .3rem; border-radius: 99px;
    background: rgba(255, 255, 255, .92); color: #1a1c20; text-decoration: none;
    line-height: 1.15;
    -webkit-backdrop-filter: saturate(1.2) blur(6px); backdrop-filter: saturate(1.2) blur(6px);
    border: 1px solid rgba(0, 0, 0, .06);
    box-shadow: 0 4px 14px rgba(0, 0, 0, .16);
    transition: box-shadow .15s ease, transform .15s ease;
}
.product__vendor-avatar {
    flex: 0 0 auto; width: 1.7rem; height: 1.7rem; border-radius: 50%;
    display: inline-flex; align-items: center; justify-content: center;
    background: var(--shops-accent, #7a1f3d); color: #fff;
    font-size: .68rem; font-weight: 700; letter-spacing: .02em;
}
.product__vendor-meta { display: inline-flex; flex-direction: column; min-width: 0; }
.product__vendor-label {
    font-size: .58rem; font-weight: 600; text-transform: uppercase; letter-spacing: .04em;
    color: #8a8f98; line-height: 1;
}
.product__vendor-label i { font-size: .9em; }
.product__vendor-name {
    font-size: .76rem; font-weight: 700; line-height: 1.2;
    max-width: 12ch; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.product__vendor-badge:hover { box-shadow: 0 6px 18px rgba(0, 0, 0, .22); transform: translateY(-1px); }
.product__vendor-badge:hover .product__vendor-name { color: var(--shops-accent, #7a1f3d); }
.shops-card-actions { position:absolute; top:8px; right:8px; z-index:6; display:flex; flex-direction:column; align-items:flex-end; gap:6px; }
.shops-card-action { width:34px; height:34px; padding:0; border-radius:50%; border:0; background:rgba(255,255,255,.92); color:#333; display:flex; align-items:center; justify-content:center; cursor:pointer; box-shadow:0 2px 6px rgba(0,0,0,.15); transition:transform .12s, background .12s, color .12s; font-size:.9rem; line-height:1; }
.shops-card-action:hover { transform:scale(1.08); background:#fff; }
.shops-card-action.is-active { background: var(--color-1, #d85575); color:#fff; }
.shops-card-action:disabled { opacity:.6; cursor:default; }
/*
 * Le menu est replié derrière le bouton « ⋮ » ; il se déplie vers le bas au
 * survol / focus / clic.
 *
 * DEUX COLONNES, et non plus une pile. Le visuel de carte mesure 188 px de haut
 * et porte `overflow:hidden` : empilés, le bouton « ⋮ » plus quatre actions
 * dépassaient de 12 px et la dernière — le partage — était coupée. Mesuré.
 * En grille, quatre actions tiennent sur deux rangées (74 px) et six y
 * tiendraient encore : le menu ne dépend plus du nombre d'actions ni de la
 * hauteur du visuel, qui suit le format d'image du site.
 */
.shops-card-actions__menu { display:grid; grid-template-columns:repeat(2, auto); justify-items:end; gap:6px; margin-top:6px; opacity:0; visibility:hidden; transform:translateY(-8px); pointer-events:none; transition:opacity .18s ease, transform .18s ease, visibility .18s; }
.shops-card-actions:hover .shops-card-actions__menu,
.shops-card-actions:focus-within .shops-card-actions__menu,
.shops-card-actions.is-open .shops-card-actions__menu { opacity:1; visibility:visible; transform:translateY(0); pointer-events:auto; }
.shops-card-actions:hover .shops-card-toggle,
.shops-card-actions.is-open .shops-card-toggle { background:#111; color:#fff; }
.shops-card-share { position:relative; }
.shops-share-menu { position:absolute; top:0; right:calc(100% + 8px); display:flex; gap:4px; background:#fff; border-radius:10px; box-shadow:0 6px 20px rgba(0,0,0,.18); padding:6px; }
.shops-share-menu[hidden] { display:none; }
.shops-share-menu a, .shops-share-menu button { width:32px; height:32px; border-radius:50%; border:0; background:#f3f4f6; color:#333; display:flex; align-items:center; justify-content:center; text-decoration:none; cursor:pointer; font-size:.85rem; }
.shops-share-menu a:hover, .shops-share-menu button:hover { background:#e5e7eb; }
/* Modale « liste d'envie » (indépendante de Bootstrap) */
.shops-gl-modal { position:fixed; inset:0; z-index:2000; background:rgba(15,23,42,.5); display:flex; align-items:center; justify-content:center; padding:16px; }
.shops-gl-modal__box { background:#fff; border-radius:14px; width:min(420px,100%); max-height:85vh; overflow:auto; box-shadow:0 20px 60px rgba(0,0,0,.3); }
.shops-gl-modal__head { display:flex; align-items:center; justify-content:space-between; padding:14px 18px; border-bottom:1px solid #eef0f4; font-weight:600; }
.shops-gl-modal__close { border:0; background:transparent; font-size:1.5rem; line-height:1; color:#94a3b8; cursor:pointer; }
.shops-gl-modal__close:hover { color:#334155; }
.shops-gl-modal__body { padding:16px 18px; }
.shops-gl-list { display:flex; flex-direction:column; gap:6px; }
.shops-gl-item { display:flex; align-items:center; justify-content:space-between; gap:10px; width:100%; text-align:left; padding:10px 12px; border:1px solid #e5e7eb; border-radius:10px; background:#fff; cursor:pointer; font-size:.9rem; transition:background .12s,border-color .12s; }
.shops-gl-item:hover { background:#f8fafc; border-color:#c7d2fe; }
.shops-gl-item:disabled { opacity:.6; cursor:default; }

/* Titre : 2 lignes max, sans mots coupés lettre par lettre */
.shops-index .card-title { line-height: 1.3; }
.shops-index .card-title a {
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
    overflow-wrap: anywhere;
}

/* --- Prix ---------------------------------------------------------------- */
.shops-index .js-product-price { font-size: 1.05rem; }
.shops-index .price_old { font-size: .85em; }

/* --- Zone d'achat -------------------------------------------------------- */
/* Le bouton « Ajouter » reste sur une ligne et ne déborde pas de la carte. */
.shops-index .add-to-cart-modern { flex-wrap: nowrap; }
.shops-index .add-to-cart-modern .js-add-to-cart { white-space: nowrap; min-width: 0; }
.shops-index .js-qty-input,
.shops-detail .js-qty-input { -moz-appearance: textfield; }
.shops-index .js-qty-input::-webkit-inner-spin-button,
.shops-index .js-qty-input::-webkit-outer-spin-button,
.shops-detail .js-qty-input::-webkit-inner-spin-button,
.shops-detail .js-qty-input::-webkit-outer-spin-button { -webkit-appearance: none; margin: 0; }

/* Produit non achetable : « Voir le produit » (+ cloche « Me prévenir » à gauche). */
.shops-index .js-view-zone { flex-wrap: nowrap; }
.shops-index .js-view-zone .js-stock-message { flex-shrink: 0; }
.shops-index .js-view-zone .js-view-product { white-space: nowrap; min-width: 0; }

/* Zones d'achat mutuellement exclusives : l'attribut `hidden` (posé côté serveur
   selon showBuy, et par catalog.js applyVariant) doit l'emporter sur le
   `display:flex !important` de Bootstrap (.d-flex), sinon les DEUX zones
   s'affichent (quantité+Ajouter ET « Voir le produit »). */
/* Zones d'achat mutuellement exclusives (buy vs view/cloche) : l'attribut hidden
   DOIT l'emporter sur .d-flex (Bootstrap, display:flex!important). NON scopé à
   .shops-index pour valoir aussi dans l'embed « Vendre ailleurs » et l'aperçu
   admin — là, aucun catalog.js ne corrige l'affichage, donc une carte en rupture
   montrerait à tort qté+panier. .js-*[hidden] (0,2,0) bat .d-flex (0,1,0). */
.js-buy-zone[hidden],
.js-view-zone[hidden],
.js-stock-message[hidden] { display: none !important; }

/* --- Badges (promo / rupture / nouveau) ---------------------------------- */
.shops-index .product-image .badge { font-size: .68rem; font-weight: 600; }
/* Ruban « Promo -x% » haut-gauche : pilule orange (façon maquette produit variable). */
.shops-index .product-image .js-promo-badge {
    background: var(--color-1, #d85575) !important;
    color: #fff;
    border-radius: 1rem;
    padding: .2rem .6rem;
}

/* --- Vignettes de variantes (produit variable) --------------------------- */
/* Rangée de « boîtes » sélectionnables en overlay sur le bas de l'image ;
   la vignette active passe en blanc + bordure sombre, un badge promo par
   variante (rouge) signale les variantes en réduction. */
.shops-index .product__variants {
    position: absolute;
    left: 0; right: 0; bottom: .5rem;
    display: flex; flex-wrap: wrap; justify-content: center; gap: .4rem;
    padding: 0 .5rem;
    z-index: 3;
}
.shops-index .product__variant {
    position: relative;
    display: flex; flex-direction: column; align-items: center; gap: .1rem;
    min-width: 60px; max-width: 90px;
    padding: .35rem .4rem;
    background: rgba(255, 255, 255, .82);
    -webkit-backdrop-filter: blur(3px); backdrop-filter: blur(3px);
    border: 1px solid transparent;
    border-radius: .65rem;
    color: #333; font-size: .68rem; line-height: 1.15; cursor: pointer;
    transition: background .15s, border-color .15s, box-shadow .15s;
}
.shops-index .product__variant:hover { background: #fff; }
.shops-index .product__variant.active {
    background: #fff;
    border-color: #111;
    box-shadow: 0 .25rem .6rem rgba(0, 0, 0, .18);
}
.shops-index .product__variant-icon  { font-size: 1rem; }
.shops-index .product__variant-label {
    font-weight: 500; white-space: nowrap;
    max-width: 78px; overflow: hidden; text-overflow: ellipsis;
}
.shops-index .product__variant-promo {
    position: absolute; top: -.4rem; right: -.3rem;
    background: var(--color-1, #d85575); color: #fff;
    font-size: .6rem; font-weight: 700; line-height: 1.3;
    padding: .02rem .3rem; border-radius: .55rem;
    box-shadow: 0 1px 3px rgba(0, 0, 0, .25);
}

/* --- Sélecteur de déclinaisons à AXES (Couleur = pastilles hex, Taille = pills)
   Rendu dans le CORPS de la carte (non scopé .shops-index → marche aussi sur les
   cartes de recherche / produits liés). */
/* position/z-index : les chips passent AU-DESSUS du .stretched-link du titre
   (sinon le clic sur une valeur — ex. « XL » — atterrit sur le lien fiche et
   redirige au lieu de sélectionner la variante). Même parade que .js-buy-zone. */
.product__axes  { display: flex; flex-direction: column; gap: .35rem; position: relative; z-index: 2; }
.product__axis  { display: flex; align-items: center; gap: .5rem; flex-wrap: wrap; }
.product__axis-label {
    font-size: .66rem; font-weight: 600; color: #6b7280;
    text-transform: uppercase; letter-spacing: .02em; min-width: 3.4em;
}
.product__axis-values { display: flex; flex-wrap: wrap; gap: .3rem; }

/* Caractéristiques produit (groupes à valeur UNIQUE : torréfaction, type, intensité…)
   → lecture seule, PAS des axes sélectionnables. Libellé gris + valeur en chip discret. */
.product__specs { display: flex; flex-direction: column; gap: .2rem; }
.product__spec  { display: flex; align-items: center; gap: .5rem; }
.product__spec-label {
    font-size: .66rem; font-weight: 600; color: #6b7280;
    text-transform: uppercase; letter-spacing: .02em; min-width: 3.4em;
}
.product__spec-value {
    font-size: .72rem; color: #374151; background: #f3f4f6;
    border: 1px solid #e5e7eb; border-radius: 4px; padding: .1rem .4rem;
}

/* Pastille couleur (liseré blanc intérieur → visible même sur fond clair) */
.product__swatch {
    width: 20px; height: 20px; padding: 0;
    background: var(--sw, #ccc);
    border: 1px solid rgba(0, 0, 0, .2);
    box-shadow: inset 0 0 0 2px #fff;
    cursor: pointer; position: relative;
    transition: transform .12s, box-shadow .12s;
}
.product__swatch:hover  { transform: scale(1.12); }
.product__swatch.active { border: 1px solid #000; }

/* Pill texte (Taille…) */
/* La hauteur faisait 21 px : sous les 24 px minimum de WCAG 2.2 AA (« Target
   Size »), et pénible au pouce. Flex pour centrer le libellé sans gonfler la
   police — l'aspect change à peine, la cible gagne 3 px. */
.product__pill {
    min-width: 30px; min-height: 24px; padding: .16rem .45rem;
    display: inline-flex; align-items: center; justify-content: center;
    font-size: .72rem; font-weight: 600; line-height: 1.2;
    background: #fff; color: #333;
    border: 1px solid #d7dbe0; border-radius: .4rem;
    cursor: pointer; transition: border-color .12s, background .12s, color .12s;
}
.product__pill:hover  { border-color: #111; }
.product__pill.active { background: #111; color: #fff; border-color: #111; }

/* Valeur indisponible avec la sélection courante (reste cliquable → ré-aligne) */
.product__swatch.is-unavailable { opacity: .3; }
.product__swatch.is-unavailable::after {
    content: ''; position: absolute; left: -1px; right: -1px; top: 50%;
    height: 1px; background: #888; transform: rotate(-45deg);
}
.product__pill.is-unavailable { opacity: .45; text-decoration: line-through; }

/* --- Stickers produit (badges promotionnels posés par coin, façon « Nouveau ») */
.shops-index .product__sticker {
    background: #212529; color: #fff;
    font-size: .68rem; font-weight: 600;
    padding: .3rem .5rem; border-radius: .35rem;
    box-shadow: 0 1px 3px rgba(0, 0, 0, .2);
}
.shops-index .product__sticker-img {
    max-width: 66px; height: auto;
    filter: drop-shadow(0 1px 2px rgba(0, 0, 0, .25));
}

/* --- Barre d'outils catalogue : Filtrer + recherche + tri + stock ---------
   Une seule ligne. La recherche est un <form> statique ; #shops-filters (peuplé
   par catalog.js) et son #filters-form passent en `display:contents` pour que
   leurs enfants (Filtrer, tri, stock, clear, pills) deviennent des items flex
   directs de .shops-toolbar → alignement sur la même ligne, ordre via `order`.
   Les pills de filtres actifs occupent toute la largeur et passent en dessous. */
.shops-toolbar #shops-filters,
.shops-toolbar #filters-form { display: contents; }

/* Filtrer collé à GAUCHE ; recherche + tri + stock groupés à DROITE grâce au
   margin-left:auto sur le 1er item de droite (la recherche). Recherche compacte
   (pas de flex-grow) → ne mange pas la place. */
.shops-toolbar__filter        { order: 1; white-space: nowrap; }
/* Pastille « nombre de filtres actifs » : chiffre centré et lisible. */
.shops-toolbar__filter-badge {
    display: inline-flex; align-items: center; justify-content: center;
    min-width: 1.25rem; height: 1.25rem; padding: 0 .35rem;
    font-size: .72rem; font-weight: 700; line-height: 1;
}

/* --- Sélecteur de variantes (offcanvas « Choisissez votre format ») -------- */
.shops-variant-picker { max-width: 380px; width: 92vw; }
.shops-variant-picker-row {
    display: flex; align-items: center; gap: .85rem; width: 100%;
    text-align: left; padding: .85rem 1.1rem;
    border: 0; border-bottom: 1px solid #eee; background: #fff;
    cursor: pointer; transition: background .12s;
}
.shops-variant-picker-row:hover { background: #f7f8fa; }
.shops-variant-picker-row.active {
    background: rgba(var(--bs-primary-rgb, 13, 110, 253), .08);
    box-shadow: inset 3px 0 0 var(--bs-primary, #0d6efd);
}
.shops-variant-picker-row.is-unavailable { opacity: .5; cursor: not-allowed; }
.shops-variant-picker-thumb {
    flex-shrink: 0; width: 52px; height: 52px; border-radius: 8px;
    border: 1px solid #e3e4e6; background: #f3f4f6;
    display: flex; align-items: center; justify-content: center;
    color: #adb1b6; overflow: hidden;
}
.shops-variant-picker-thumb img { width: 100%; height: 100%; object-fit: cover; }
.shops-variant-picker-info { flex: 1 1 auto; min-width: 0; }
.shops-variant-picker-label { display: block; font-weight: 500; font-size: .9rem; color: #1a1a1a; }
.shops-variant-picker-price { display: block; margin-top: .15rem; font-size: .85rem; }
.shops-variant-picker-unavail { margin-left: auto; font-size: .75rem; color: #9aa0a6; white-space: nowrap; }
/* Pied de page : quantité + bouton « Ajouter au panier » explicite. */
.shops-variant-picker-footer {
    border-top: 1px solid #e6e7e9; padding: 1rem 1.1rem;
    display: flex; flex-direction: column; gap: .75rem; background: #fff;
}
.shops-variant-picker-qty { display: flex; align-items: center; justify-content: space-between; }
.shops-variant-picker-qty-label { font-weight: 500; font-size: .9rem; }
.shops-variant-picker-stepper { display: inline-flex; align-items: center; border: 1px solid #d5d7da; border-radius: 8px; overflow: hidden; }
.shops-variant-picker-step { width: 2.25rem; height: 2.25rem; border: 0; background: #fff; font-size: 1.1rem; line-height: 1; cursor: pointer; color: #333; }
.shops-variant-picker-step:hover { background: #f2f3f5; }
.shops-variant-picker-qtyinput {
    width: 3rem; height: 2.25rem; text-align: center;
    border: 0; border-left: 1px solid #e6e7e9; border-right: 1px solid #e6e7e9;
    -moz-appearance: textfield;
}
.shops-variant-picker-qtyinput::-webkit-inner-spin-button,
.shops-variant-picker-qtyinput::-webkit-outer-spin-button { -webkit-appearance: none; margin: 0; }
/* Skin (fond, texte, bordure, rayon, survol) géré par .btn-1 ; ici, layout seul. */
.shops-variant-picker-add {
    display: flex; align-items: center; justify-content: center;
    width: 100%; padding: .8rem 1rem; font-weight: 600; font-size: 1rem;
}
.shops-variant-picker-add--oos, .shops-variant-picker-add:disabled { background: #adb5bd; cursor: not-allowed; }
.shops-variant-picker-add-price { font-weight: 700; }
.shops-variant-picker-add-price:not(:empty)::before { content: "·"; margin: 0 .4rem; opacity: .65; }
.shops-toolbar__count         { order: 2; white-space: nowrap; }  /* juste après « Filtrer » (full ET sidebar) */
.shops-toolbar__search { order: 3; margin-left: auto; flex: 0 1 auto; width: 260px; max-width: 42vw; }
.shops-toolbar__promo  { order: 4; white-space: nowrap; }  /* En promo, à gauche de En stock */
.shops-toolbar__stock  { order: 5; white-space: nowrap; }  /* En stock */
.shops-toolbar__sort   { order: 6; }                       /* Meilleures ventes, à droite de En stock */
/* Barre catalogue DESSINÉE (composant catalogbar) : ses boutons portent des classes
   .shops-catbar__* qui n'héritaient PAS des `order` ci-dessus → la recherche partait
   tout à droite et le compteur au milieu. On réaligne sur la barre native : Filtrer,
   compteur, recherche (poussée à droite via son margin-left:auto), promo, stock, tri.
   Le compteur (.shops-toolbar__count) et la recherche (.shops-toolbar__search) héritent
   déjà de leurs order 2 et 3. Promo et stock partagent .shops-catbar__toggle → même
   order, l'ordre DOM (promo avant stock) est conservé. */
.shops-catbar .shops-catbar__filter { order: 1; }
.shops-catbar .shops-catbar__toggle { order: 4; }
.shops-catbar .shops-catbar__sort   { order: 6; }
/* « Effacer tout » n'est plus un item de la barre : il vit dans la ligne des
   critères sélectionnés (.shops-toolbar__pills), aligné à droite via ms-auto. */
/* Mobile : la recherche reprend toute la largeur, plus de poussée à droite. */
@media (max-width: 575.98px) {
    .shops-toolbar__search { width: 100%; max-width: none; margin-left: 0; }
}
/* Pills : sur leur propre ligne, pleine largeur (flex-wrap du conteneur). */
.shops-toolbar__pills  { order: 9; flex: 1 1 100%; margin-top: .25rem; }
.shops-toolbar__pills:empty,
.shops-toolbar__pills[style*="display:none"] { display: none !important; }


/* --- Outils de filtrage remontés dans le tiroir (mobile, < 768 px) ---------
   catalog.js DÉPLACE ici (sans dupliquer) la recherche, le tri et les puces
   promo/stock/conservation : sous 768 px, la barre d'outils les empilait sur
   trois rangs au-dessus de la grille. Dans le tiroir, ces commandes deviennent
   différées comme les autres filtres (elles s'appliquent au clic sur « Voir les
   résultats ») — comportement de inOffcanvas(), voulu ici.
   `:empty` : sur grand écran les commandes repartent dans la barre et la zone
   ne doit laisser aucun trait résiduel. */
.shops-oc-tools {
    display: flex; flex-wrap: wrap; align-items: center; gap: .6rem;
    padding-bottom: .9rem; margin-bottom: .9rem;
    border-bottom: 1px solid var(--bs-border-color, #dee2e6);
}
.shops-oc-tools:empty { display: none; }

/* Dans le tiroir, ces commandes ne sont plus des items de .shops-toolbar : leurs
   `order` et largeurs de barre n'ont plus cours. */
.shops-oc-tools .shops-toolbar__search,
.shops-oc-tools .shops-toolbar__sort { flex: 1 1 100%; width: 100%; max-width: none; margin-left: 0; }
.shops-oc-tools .shops-toolbar__sort .form-select { width: 100% !important; }

/* Puces promo / stock / conservation : une seule rangée, elles se partagent la
   largeur pour rester atteignables au pouce. */
.shops-oc-tools .shops-toolbar__promo,
.shops-oc-tools .shops-toolbar__stock { flex: 1 1 8rem; }
.shops-oc-tools .shops-toolbar__temp { flex: 1 1 100%; display: flex; }
.shops-oc-tools .shops-toolbar__temp .btn { flex: 1 1 auto; }

/* --- Tiroir « Filtrer » du catalogue DESSINÉ ------------------------------
   Contenu chargé à la première ouverture (catalog.js → initFacetsDrawer) et fait
   de LIENS, pas de cases : la page dessinée n'embarque pas le moteur de facettes
   du catalogue natif. D'où une liste, à débarrasser de ses puces. */
.shops-catbar__drawer { width: 320px; max-width: 88vw; }
.shops-catbar__filter { white-space: nowrap; }

.shops-facets__group + .shops-facets__group { margin-top: 1.1rem; }
.shops-facets__title {
    font-size: .74rem; font-weight: 700; letter-spacing: .04em; text-transform: uppercase;
    color: var(--bs-secondary-color, #6c757d); margin-bottom: .4rem;
}
.shops-facets__list { list-style: none; margin: 0; padding: 0; }

/* Ligne de valeur : le libellé prend la place, le compte reste à droite. */
.shops-facets__item {
    display: flex; align-items: center; gap: .5rem;
    padding: .3rem .25rem; border-radius: 6px;
    color: inherit; text-decoration: none; font-size: .9rem;
}
a.shops-facets__item:hover { background: rgba(0, 0, 0, .04); }
.shops-facets__item > span:nth-child(2) { flex: 1 1 auto; min-width: 0; }
.shops-facets__count { color: var(--bs-secondary-color, #6c757d); font-size: .8rem; font-variant-numeric: tabular-nums; }

/* Case dessinée en CSS : pas d'input à piloter, mais l'état doit se lire d'un
   coup d'œil comme sur le panneau natif. */
.shops-facets__mark {
    flex: 0 0 auto; width: 1rem; height: 1rem; border-radius: 4px;
    border: 1px solid var(--bs-border-color, #ced4da); background: #fff;
    position: relative;
}
.shops-facets__item.is-on { font-weight: 600; }
.shops-facets__item.is-on .shops-facets__mark {
    background: var(--color-1, var(--bs-primary, #0d6efd));
    border-color: var(--color-1, var(--bs-primary, #0d6efd));
}
.shops-facets__item.is-on .shops-facets__mark::after {
    content: ''; position: absolute; left: .3rem; top: .11rem;
    width: .28rem; height: .58rem; border: solid #fff;
    border-width: 0 2px 2px 0; transform: rotate(45deg);
}

/* Valeur sans résultat : montrée, pas masquée — sinon la liste change de forme à
   chaque clic et on ne retrouve plus ce qu'on cherchait. */
.shops-facets__item.is-empty { color: var(--bs-secondary-color, #6c757d); opacity: .55; cursor: default; }

/* --- Outils en tête du volet « Filtrer » (catalogue dessiné) --------------
   Recherche, « En promo », « En stock » et tri entrent dans le MÊME formulaire
   que les facettes : « Voir les résultats » applique tout d'un coup. Les puces
   sont des <label> portant une case masquée — aucun JavaScript à câbler. */
.shops-facets-tools {
    display: flex; flex-direction: column; gap: .55rem;
    padding-bottom: .9rem; margin-bottom: .9rem;
    border-bottom: 1px solid var(--bs-border-color, #dee2e6);
}
.shops-facets-tools__chips { display: flex; flex-wrap: wrap; gap: .5rem; }

.shops-facets-chip {
    flex: 1 1 8rem; display: inline-flex; align-items: center; justify-content: center; gap: .35rem;
    padding: .3rem .6rem; border: 1px solid var(--bs-border-color, #ced4da); border-radius: 999px;
    font-size: .8rem; line-height: 1.4; cursor: pointer; user-select: none;
    background: #fff; color: inherit;
}
.shops-facets-chip input { position: absolute; opacity: 0; width: 0; height: 0; }
.shops-facets-chip:hover { background: rgba(0, 0, 0, .04); }
/* L'état vient de la CASE elle-même : cocher/décocher se voit sans rechargement,
   là où une classe posée au rendu serveur serait restée figée jusqu'à la validation. */
.shops-facets-chip:has(input:checked) {
    background: var(--color-1, var(--bs-primary, #0d6efd));
    border-color: var(--color-1, var(--bs-primary, #0d6efd));
    color: #fff;
}
.shops-facets-chip input:focus-visible + i { outline: 2px solid currentColor; outline-offset: 2px; }

/* Bouton de validation : collé en bas du volet, toujours atteignable. */
.shops-facets-form__apply {
    position: sticky; bottom: 0; z-index: 2;
    padding: .9rem 0 .2rem; margin-top: 1rem;
    background: var(--bs-body-bg, #fff);
    border-top: 1px solid var(--bs-border-color, #dee2e6);
}

/* Sous 768 px, la barre ne redouble plus ce que le volet porte déjà : recherche,
   puces et tri s'y empilaient sur trois rangs au-dessus de la grille. Le bouton
   « Filtrer » et le compteur restent. */
@media (max-width: 767.98px) {
    .shops-catbar .shops-toolbar__search,
    .shops-catbar .shops-catbar__toggle,
    .shops-catbar .shops-catbar__sort { display: none; }
}

/* --- Sidebar catégories : accordéon (parents repliables) ------------------ */
.shops-categories .shops-cat-toggle {
    border: 0; background: none; box-shadow: none;
    font-size: inherit; text-align: left;
}
.shops-categories .shops-cat-toggle:focus { box-shadow: none; }
.shops-categories .shops-cat-toggle:hover,
.shops-categories .list-group-item > a:hover,
.shops-categories .collapse a:hover { background: rgba(0, 0, 0, .035); }
.shops-categories .shops-cat-chevron {
    font-size: .78em; color: #888; transition: transform .2s ease;
}
/* Replié : le chevron pointe vers la droite (rotation), déplié : vers le bas. */
.shops-categories .shops-cat-toggle.collapsed .shops-cat-chevron { transform: rotate(-90deg); }


/* ==========================================================================
   2. SHOPS-DETAIL — fiche produit
   Points d'ancrage surchargeables par le thème :
     .shops-detail-title  .shops-detail-price  .shops-detail-price-old
     .shops-detail-stock-badge  .shops-detail-qty  .shops-detail-qty-input
     .shops-detail-option  .shops-detail-add-btn  .shops-detail-feedback
     .shops-detail-gallery  .shops-detail-description
     .shops-detail-reviews  .shops-detail-related
   Le rendu s'appuie sur Bootstrap ; le thème surcharge ces classes au besoin.
   ========================================================================== */

.shops-detail-feedback:empty { display: none; }


/* ==========================================================================
   3. SHOPS-CART — panier (page, offcanvas, cross-sell, paliers livraison)
   ========================================================================== */

/* --- Sélecteur multipanier (page panier) ---------------------------------
   Le résumé de commande est en `sticky-lg-top` → z-index Bootstrap 1020. Sans
   élévation, le menu déroulant « Panier N » (z-index 1000) s'ouvrait DERRIÈRE
   le résumé. On lève tout le dropdown au-dessus du sticky à l'ouverture. */
#cart-switch { position: relative; }
#cart-switch.show { z-index: 1031; }
#cart-switch .dropdown-menu { z-index: 1031; }

/* Sélecteur de panier (multipanier) — pilule compacte, cohérente dans
   l'offcanvas (près de la croix) comme sur /cart. */
.cart-switch > .dropdown-toggle {
    border-radius: 2rem; font-weight: 600; font-size: .8rem;
    padding: .3rem .8rem; white-space: nowrap;
    display: inline-flex; align-items: center; gap: .4rem;
}
#cart-switch-oc { margin-right: .25rem; }               /* respire à côté de la croix */
/* Item actif du multipanier : surbrillance NEUTRE (plus de bleu). Le JS pose
   aussi `text-white` sur les enfants (héritage de l'ancien fond bleu) → on force
   une couleur lisible sur fond clair. */
.cart-switch .dropdown-item.active,
.cart-switch .dropdown-item:active { background: #f1f5f9; color: #1e293b; }
.cart-switch .dropdown-item.active small { color: #64748b; }
.cart-switch .dropdown-item.active .text-white { color: #1e293b !important; }

/* --- Panneaux front AU-DESSUS de la bulle chatbot ------------------------------
   Le widget chatbot (.awcb, style.css du thème) est en z-index 99998 : sans
   élévation, la bulle recouvre l'offcanvas panier ouvert (cf. capture). On lève
   les panneaux Bootstrap du front au-dessus, en conservant l'ordre backdrop <
   panneau. Chargé front-wide → s'applique à tous les offcanvas/modales du site. */
.offcanvas-backdrop { z-index: 99999; }
.offcanvas          { z-index: 100000; }
.modal-backdrop     { z-index: 100001; }
.modal              { z-index: 100002; }
.shops-gl-modal     { z-index: 100002; }

/* --- Layout offcanvas (colonne cross-sell + panier) ----------------------- */
.shops-cart-layout { display: flex; height: 100%; }
.shops-cart-layout.no-cross-sell .shops-cart-cross-sell { display: none !important; }
.shops-cart-layout.with-cross-sell { flex-direction: row; }
.shops-cart-cross-sell { width: 160px; min-width: 140px; overflow-y: auto; flex-shrink: 0; }
.shops-cart-main { flex: 1; min-width: 0; display: flex; flex-direction: column; height: 100%; }

/* --- Cross-sell : vignettes desktop --------------------------------------- */
.shops-cart-cross-sell-item img { width: 100%; aspect-ratio: 1; object-fit: cover; }

/* --- Cross-sell : slides (mobile + desktop) ------------------------------- */
.shops-cart-cs-slide-inner { display: flex; align-items: center; gap: .5rem; padding: .25rem 0; }
.shops-cart-cs-slide-img { width: 56px; height: 56px; object-fit: cover; border-radius: .25rem; flex-shrink: 0; }
.shops-cart-cs-slide-img--placeholder { background: #f0f0f0; }
.shops-cart-cs-slide-body { flex: 1; min-width: 0; font-size: .8rem; }
.shops-cart-cs-slide-title a {
    color: inherit; text-decoration: none; font-weight: 600;
    display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}
.shops-cart-cs-slide-price { color: #666; margin-top: .15rem; }
.shops-cart-cs-slide-btn { font-size: .75rem; padding: .2rem .5rem; white-space: nowrap; }

/* --- Cross-sell : slider mobile ------------------------------------------- */
.shops-cart-cross-sell-slider { position: relative; }
.shops-cart-cross-sell-mobile-list { display: flex; flex-direction: column; gap: .25rem; }
.shops-cart-cross-sell-dots { display: flex; justify-content: center; gap: .35rem; margin-top: .4rem; }
.shops-cart-cross-sell-dot {
    width: 7px; height: 7px; border-radius: 50%;
    border: none; background: #ccc; padding: 0; cursor: pointer;
}
.shops-cart-cross-sell-dot.is-active { background: var(--bs-primary, #0d6efd); }

@media (max-width: 768px) {
    .shops-cart-layout.with-cross-sell { flex-direction: column; }
    .shops-cart-cross-sell { display: none !important; }
}

/* --- Barre de progression livraison gratuite ------------------------------ */
/* Styles déplacés depuis les attributs style="" des vues (offcanvas + /cart). */
.shops-cart-shippings-status .progress { height: 5px; }
.shops-cart-shippings-status .progress-bar { width: 0; transition: width .4s ease; }
/* Le rail des paliers : hauteur suffisante pour dot + transporteur + montant. */
.shops-cart-shipping-steps-wrapper { position: relative; height: 40px; }
.shops-cart-shippings-status .shops-cart-shipping-steps { position: absolute; inset: 0; }
.shops-cart-shippings-status .shops-cart-shipping-step {
    position: absolute; transform: translateX(-50%); text-align: center; top: -3px;
    display: flex; flex-direction: column; align-items: center; gap: 1px; line-height: 1.1;
}
/* EXTRÉMITÉS : le premier jalon (0 %) et le dernier (100 %) ne peuvent pas être
   centrés sur leur point sans sortir du panneau. On les aligne vers l'intérieur —
   le libellé du dernier transporteur était tronqué à droite. */
.shops-cart-shippings-status .shops-cart-shipping-step:first-child {
    transform: translateX(0);
    align-items: flex-start;
    text-align: left;
}
.shops-cart-shippings-status .shops-cart-shipping-step:last-child {
    transform: translateX(-100%);
    align-items: flex-end;
    text-align: right;
}
/* Le point reste sur SA position exacte, sinon la pastille se décale du jalon. */
.shops-cart-shippings-status .shops-cart-shipping-step:first-child .dot { margin-left: -5px; }
.shops-cart-shippings-status .shops-cart-shipping-step:last-child  .dot { margin-right: -5px; }
.shops-cart-shippings-status .shops-cart-shipping-step .dot {
    width: 10px; height: 10px; border-radius: 50%;
    background: #dee2e6; border: 2px solid #fff; box-shadow: 0 0 0 1px #dee2e6;
}
.shops-cart-shippings-status .shops-cart-shipping-step.is-active .dot {
    background: var(--bs-success, #198754); box-shadow: 0 0 0 1px var(--bs-success, #198754);
}
.shops-cart-shippings-status .shops-cart-shipping-step.is-next .dot {
    background: var(--bs-warning, #ffc107); box-shadow: 0 0 0 1px var(--bs-warning, #ffc107);
}
/* Transporteur : icône + nom, sous le point. */
.shops-cart-shippings-status .shops-cart-shipping-step .carrier {
    display: inline-flex; align-items: center; gap: 3px;
    font-size: .62rem; color: #555; max-width: 90px;
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.shops-cart-shippings-status .shops-cart-shipping-step .carrier i { font-size: .7rem; color: var(--bs-primary, #4972C1); }
.shops-cart-shippings-status .shops-cart-shipping-step .carrier-name { overflow: hidden; text-overflow: ellipsis; }
.shops-cart-shippings-status .shops-cart-shipping-step.is-active .carrier i { color: var(--bs-success, #198754); }
.shops-cart-shippings-status .shops-cart-shipping-step .amount { font-size: .6rem; color: #888; white-space: nowrap; }
.shops-cart-shippings-status .shops-cart-shipping-step.is-active .amount { color: var(--bs-success, #198754); font-weight: 600; }


/* ==========================================================================
   4. SHOPS-CHECKOUT — tunnel de commande (présentation façon Shopify)
   Deux colonnes : formulaire (blanc) à gauche, récap (gris qui file jusqu'au
   bord droit) à droite ; champs à label flottant ; blocs plats bordés.
   ========================================================================== */

/* Fond blanc ; overflow-x: clip empêche le scroll dû au bandeau gris 100vw
   SANS casser la position:sticky du récap (clip n'ouvre pas de scroll container). */
.shops-checkout-page { background: var(--card-bg, #fff); overflow-x: clip; }
.shops-checkout { max-width: 1000px; }

/* GRANDS ÉCRANS — le bandeau du récapitulatif file jusqu'au bord droit du
   viewport (c'est voulu, il ancre la colonne). Mais avec un contenu plafonné à
   1000 px, il restait au-delà de 1400 px une DALLE GRISE de 700 px pour 376 px
   de contenu dedans : le tunnel se lisait décentré, posé contre un vide. On
   laisse donc respirer le contenu à mesure que l'écran grandit — sans jamais
   partir à pleine largeur, un formulaire de paiement trop large se lit mal. */
@media (min-width: 1400px) { .shops-checkout { max-width: 1140px; } }
@media (min-width: 1700px) { .shops-checkout { max-width: 1260px; } }

/* CHARTE DU TUNNEL — alias LOCAUX (jamais en :root : la configuration du thème
   doit rester la source de vérité). Le tunnel peignait tout en dur : bleu
   Bootstrap pour le focus et les options actives, gris arbitraires pour les
   bords. Il ne ressemblait donc à aucune boutique en particulier. Chaque alias
   consomme le jeton de la charte et garde l'ancienne valeur en repli, pour que
   rien ne change sur un thème qui ne déclare pas le jeton.

   Le PANIER est dans la liste : son bloc code promo emprunte désormais les
   mêmes composants que le tunnel (`.shops-checkout-promo`, l'encart « code
   appliqué », la pastille de message). Sans les jetons, ces composants
   retombaient sur leurs valeurs de repli — le même bloc suivait la charte au
   tunnel et l'ignorait au panier, à un clic d'écart. */
.shops-checkout-page,
.shops-cart {
    --ck-accent:      var(--form-focus-color, var(--color-4, #0d6efd));
    --ck-surface:     var(--card-bg, #fff);
    --ck-text:        var(--card-text, #1a1a1a);
    --ck-line:        var(--card-border, #e2e3e5);
    --ck-field-line:  var(--form-border-color, #b9bcc0);
    --ck-field-bg:    var(--form-bg, #fff);
    --ck-field-text:  var(--form-color, #212529);
    --ck-radius:      var(--form-radius, 8px);
    --ck-card-radius: var(--card-radius, 10px);
    --ck-muted:       #6b7177;
    /* Fond du bandeau récapitulatif : une teinte à peine posée sur la surface,
       dérivée du texte de la charte → suit un thème sombre comme un thème clair. */
    --ck-band:        color-mix(in srgb, var(--ck-text) 4%, var(--ck-surface));
    --ck-hover:       color-mix(in srgb, var(--ck-text) 5%, var(--ck-surface));
    --ck-accent-soft: color-mix(in srgb, var(--ck-accent) 8%, var(--ck-surface));
    /* Vert « c'est acquis » (remise appliquée, code accepté) : une couleur de
       SENS, pas de marque — elle ne suit donc pas la palette. Son pendant
       ambre dit « ça n'a pas pris, corrigez » sans la dureté du rouge d'erreur
       système : un code promo refusé n'est pas une panne. */
    --ck-ok:          #2f6f3a;
    --ck-warn:        #8a5a00;
}
.shops-checkout-grid { display: flex; flex-direction: column; }

@media (min-width: 992px) {
    .shops-checkout-grid {
        display: grid;
        grid-template-columns: minmax(0, 1fr) minmax(0, 27rem);
        /* stretch (défaut) : l'aside s'étire sur TOUTE la hauteur de la ligne,
           sinon son bandeau gris ::before (top:0;bottom:0) s'arrête à la fin du
           récapitulatif alors que le formulaire continue en dessous. Le contenu
           reste en haut via le sticky de .shops-checkout-summary-inner. */
    }
    /* La grille descend au moins jusqu'au bas de l'écran : le bandeau du récap
       (::before, top:0/bottom:0) suit, au lieu de s'arrêter à la fin du
       formulaire et de laisser une arête au milieu de la page. */
    .shops-checkout-grid { min-height: calc(100vh - 14rem); }
    .shops-checkout-main  { padding: 2.5rem 3.5rem 3rem 0; }
    .shops-checkout-aside { position: relative; padding: 2.5rem 0 3rem 3.5rem; }
    /* Bandeau gris qui déborde jusqu'au bord droit du viewport. */
    .shops-checkout-aside::before {
        content: ""; position: absolute; top: 0; bottom: 0; left: 0;
        width: 100vw; background: var(--ck-band, #f7f8fa); border-left: 1px solid var(--ck-line, #e6e7e9); z-index: 0;
    }
    .shops-checkout-aside > * { position: relative; z-index: 1; }
    .shops-checkout-summary-inner { position: sticky; top: 2rem; }
}

/* ── Sections du formulaire ─────────────────────────────────────────────── */
/* Un peu d'air ENTRE les sections (Contact / Livraison / Mode de livraison /
   Paiement) et moins DANS chacune : le tunnel se lisait comme un seul bloc de
   champs, sans hiérarchie. On ne rallonge quasiment pas la page — le gain vient
   du regroupement, pas de l'espacement. */
.shops-checkout-section { margin-bottom: 1.9rem; }
.shops-checkout-section-head {
    display: flex; align-items: baseline; justify-content: space-between;
    gap: .75rem; margin-bottom: .65rem;
}
.shops-checkout-section-title { font-size: 1.0625rem; font-weight: 600; margin: 0; color: var(--ck-text, #1a1a1a); letter-spacing: -.01em; }

/* ÉTAPES NUMÉROTÉES — « Contact », « Livraison », « Mode de livraison » et
   « Paiement » avaient exactement la même taille, la même graisse et la même
   couleur que « Adresse de facturation » ou « Message pour la commande » : rien
   ne disait où l'on en était, ni ce qui restait à faire. La pastille chiffrée
   distingue les quatre étapes du tunnel des blocs secondaires.

   Le compteur vit en CSS, pas dans le HTML : une section MASQUÉE (« Mode de
   livraison » disparaît pour un panier sans rien à expédier) est en display:none,
   et les compteurs CSS sautent ces éléments — la numérotation se referme
   d'elle-même au lieu d'afficher « 1, 2, 4 ». Un numéro écrit en dur aurait
   demandé au serveur de savoir à l'avance ce que le panier contient. */
.shops-checkout-main { counter-reset: ck-etape; }
.shops-checkout-section-title[data-etape] {
    display: flex;
    align-items: center;
    gap: .55rem;
    counter-increment: ck-etape;
}
.shops-checkout-section-title[data-etape]::before {
    content: counter(ck-etape);
    flex: 0 0 auto;
    width: 1.55rem; height: 1.55rem;
    display: inline-flex; align-items: center; justify-content: center;
    border-radius: 50%;
    background: var(--ck-accent-soft, #eef2f7);
    color: var(--ck-accent, #0d6efd);
    border: 1px solid color-mix(in srgb, var(--ck-accent, #0d6efd) 22%, transparent);
    font-size: .8rem; font-weight: 700; line-height: 1;
    font-variant-numeric: tabular-nums;
}
.shops-checkout-section-link { font-size: .875rem; text-decoration: none; }
.shops-checkout-section-hint { font-size: .78rem; color: var(--ck-muted, #6b7177); }
.shops-checkout-note { font-size: .8rem; color: var(--ck-muted, #6b7177); margin-top: .35rem; }

/* ── Champs (labels flottants) ──────────────────────────────────────────── */
.shops-checkout-field { margin-bottom: .5rem; }
.shops-checkout .form-control,
.shops-checkout .form-select { border: 1px solid var(--ck-field-line, #b9bcc0); border-radius: var(--ck-radius, 8px); background: var(--ck-field-bg, #fff); color: var(--ck-field-text, #212529); }
/* Anneau de focus VISIBLE (RGAA 10.7) et à la couleur de la boutique : l'ancien
   liseré de 1 px en bleu Bootstrap se voyait à peine et jurait avec la charte. */
.shops-checkout .form-control:focus,
.shops-checkout .form-select:focus {
    border-color: var(--ck-accent, #0d6efd);
    box-shadow: 0 0 0 3px color-mix(in srgb, var(--ck-accent, #0d6efd) 18%, transparent);
    outline: none;
}
.shops-checkout .form-floating > label { color: var(--ck-muted, #6b7177); }
.shops-checkout-label { font-size: .8rem; color: var(--ck-muted, #6b7177); margin-bottom: .25rem; }
.shops-checkout-textarea { min-height: 5rem; }

/* Champs à label flottant COMPACTS (48px, façon Shopify) : remplace la hauteur
   Bootstrap par défaut (~58px) et recale le label + le padding en conséquence. */
.shops-checkout .form-floating > .form-control,
.shops-checkout .form-floating > .form-select {
    height: 48px;
    min-height: 48px;
    line-height: 1.2;
}
.shops-checkout .form-floating > .form-control { padding: 1rem .75rem .25rem; }
.shops-checkout .form-floating > .form-select  { padding-top: 1.15rem; padding-bottom: .25rem; }
.shops-checkout .form-floating > label { padding: .85rem .75rem; }
.shops-checkout .form-floating > .form-control:focus,
.shops-checkout .form-floating > .form-control:not(:placeholder-shown) {
    padding-top: 1.25rem;
    padding-bottom: .2rem;
}
.shops-checkout .form-floating > .form-control:focus ~ label,
.shops-checkout .form-floating > .form-control:not(:placeholder-shown) ~ label,
.shops-checkout .form-floating > .form-select ~ label {
    transform: scale(.8) translateY(-.5rem) translateX(.15rem);
}
/* ── Suggestions d'adresse (BAN / Google Places) ─────────────────────────────
   Le JS produisait bien `.checkout-ac-list` / `.checkout-ac-item`, mais AUCUNE
   feuille de style ne les décrivait : la liste sortait en `position: static`,
   sans fond ni bordure — elle POUSSAIT le formulaire vers le bas au lieu de le
   survoler, rien n'indiquait la ligne survolée, et le curseur restait une
   flèche. On la pose donc en calque au-dessus du champ. */
.shops-checkout .checkout-ac-list {
    position: absolute;
    top: calc(100% + 4px);
    left: 0;
    right: 0;
    z-index: 1050;                       /* au-dessus des sections suivantes */
    max-height: 16rem;
    overflow-y: auto;
    padding: .25rem;
    background: var(--ck-surface, #fff);
    border: 1px solid var(--ck-line, #e2e3e5);
    border-radius: var(--ck-radius, 8px);
    box-shadow: 0 8px 24px rgba(0, 0, 0, .12);
}
.shops-checkout .checkout-ac-item {
    padding: .5rem .65rem;
    border-radius: calc(var(--ck-radius, 8px) - 3px);
    font-size: .875rem;
    line-height: 1.35;
    color: var(--ck-text, #1a1a1a);
    cursor: pointer;
}
.shops-checkout .checkout-ac-item:hover,
.shops-checkout .checkout-ac-item.is-active {
    background: var(--ck-accent-soft, #eef4ff);
    color: var(--ck-text, #1a1a1a);
}
/* Navigation au clavier (RGAA) : la ligne courante reste visible même sans
   souris, et le contraste ne dépend pas de la seule couleur de fond. */
.shops-checkout .checkout-ac-item.is-active {
    box-shadow: inset 2px 0 0 var(--ck-accent, #0d6efd);
}
@media (prefers-reduced-motion: no-preference) {
    .shops-checkout .checkout-ac-item { transition: background-color .12s ease; }
}
/* Suggestions GOOGLE PLACES (repli quand la BAN ne trouve rien). Google injecte
   son propre `.pac-container` DANS <body>, avec un z-index de 1000 : sous le
   récapitulatif collant du tunnel, la liste passait dessous. On la remonte et on
   l'aligne sur le rayon du reste du formulaire. */
.pac-container {
    z-index: 1060 !important;
    border-radius: var(--form-radius, 8px);
    box-shadow: 0 8px 24px rgba(0, 0, 0, .12);
    font-family: inherit;
}
/* Champs sans label flottant (téléphone) alignés sur la même hauteur. */
.shops-checkout-field > .form-control[type="tel"] { height: 48px; }

/* Widget téléphone (awtel) intégré au style du checkout : pleine largeur, 48px,
   et UN SEUL bloc drapeau + saisie. Le bord est porté par le CONTENEUR et retiré
   des enfants → AUCUNE barre verticale entre le préfixe et le numéro. Pas de
   overflow:hidden (le menu pays déborde en dessous et ne doit pas être rogné). */
.shops-checkout .awtel {
    max-width: none;
    font-size: 1rem;
    border: 1px solid var(--ck-field-line, #b9bcc0);
    border-radius: var(--ck-radius, 8px);
}
.shops-checkout .awtel-flag-btn,
.shops-checkout .awtel-original-input {
    height: 46px;            /* 46 + 2px de bord conteneur = 48px */
    border: none;
    padding: 0 .75rem;
}
.shops-checkout .awtel-flag-btn { border-radius: 8px 0 0 8px; }
.shops-checkout .awtel-original-input { border-radius: 0 8px 8px 0; font-size: 1rem; }
.shops-checkout .awtel-original-input:focus { box-shadow: none; }
/* États portés par le conteneur (le vert « valide » n'apparaît plus ; rouge si erreur). */
.shops-checkout .awtel:focus-within { border-color: var(--ck-accent, #0d6efd); box-shadow: 0 0 0 3px color-mix(in srgb, var(--ck-accent, #0d6efd) 18%, transparent); }
.shops-checkout .awtel.awtel-invalid { border-color: #e23d3d; }
.shops-checkout-check { font-size: .9rem; }

/* Code promo déplacé près du bouton de paiement (petit écran) : il arrive juste
   après le champ « Message pour la commande » et s'y collait, les deux se lisant
   comme un seul bloc de saisie. Un filet et de l'air l'en détachent — c'est une
   autre intention, au moment de conclure. */
#promo-slot-mobile > #promo-zone {
    margin-top: 1.4rem;
    padding-top: 1.2rem;
    border-top: 1px solid var(--ck-line, #e6e7e9);
}
#promo-slot-mobile > #promo-zone > .shops-checkout-promo:first-child { margin-top: 0 !important; }

/* ── Page « Paiement interrompu » ───────────────────────────────────────────
   Elle flottait au milieu d'un fond gris : un titre, un paragraphe et trois
   boutons de même poids qui retombaient à la ligne n'importe comment. On la
   pose sur une carte, et on hiérarchise — une seule action met en avant la
   reprise du paiement, les deux autres passent en liens. */
.shops-cancel { padding: 3rem 1rem 4rem; }
.shops-cancel__card {
    max-width: 34rem;
    margin: 0 auto;
    padding: 2.25rem 1.75rem 2rem;
    text-align: center;
    background: var(--ck-surface, #fff);
    border: 1px solid var(--ck-line, #e6e7e9);
    border-radius: calc(var(--ck-card-radius, 10px) + 4px);
    box-shadow: 0 18px 40px -32px rgba(0, 0, 0, .45);
}
/* Rond plein plutôt qu'une croix nue : l'interruption n'est pas une faute du
   client, le ton reste neutre — et le pictogramme dit « on reprend », pas « échec ». */
.shops-cancel__icon {
    width: 3.75rem; height: 3.75rem;
    margin: 0 auto 1.1rem;
    display: flex; align-items: center; justify-content: center;
    border-radius: 50%;
    background: var(--ck-accent-soft, #eef2f7);
    color: var(--ck-accent, #0d6efd);
    font-size: 1.5rem;
}
.shops-cancel__title { font-size: 1.5rem; font-weight: 650; margin: 0 0 .6rem; letter-spacing: -.01em; }
.shops-cancel__lead  { color: var(--ck-muted, #6b7177); line-height: 1.55; margin: 0 0 1.35rem; }
.shops-cancel__lead strong { color: var(--ck-text, #1a1a1a); }
.shops-cancel__kept {
    display: inline-flex; align-items: center; gap: .5rem;
    margin-bottom: 1.35rem; padding: .5rem .85rem;
    border-radius: 999px;
    background: var(--ck-band, #f7f8fa);
    font-size: .875rem;
}
.shops-cancel__actions { display: grid; gap: .9rem; }
.shops-cancel__main { width: 100%; padding: .85rem 1rem; font-weight: 600; }
.shops-cancel__secondary {
    display: flex; flex-wrap: wrap; align-items: center; justify-content: center; gap: .5rem;
    font-size: .9rem;
}
.shops-cancel__secondary a { color: var(--ck-muted, #6b7177); text-decoration: none; }
.shops-cancel__secondary a:hover { color: var(--ck-text, #1a1a1a); text-decoration: underline; }
.shops-cancel__secondary span { color: var(--ck-line, #d5d7da); }
.shops-cancel__help {
    margin: 1.5rem 0 0; padding-top: 1.1rem;
    border-top: 1px solid var(--ck-line, #eceded);
    font-size: .82rem; color: var(--ck-muted, #6b7177); line-height: 1.5;
}

/* ── Groupes d'options (livraison, paiement, facturation) ───────────────── */
.shops-checkout-options,
.shops-checkout-option-group {
    border: 1px solid var(--ck-line, #d5d7da);
    border-radius: var(--ck-card-radius, 10px);
    overflow: hidden;
    background: var(--ck-surface, #fff);
}
.shops-checkout-loading { padding: 1rem; text-align: center; color: var(--ck-muted, #6b7177); font-size: .85rem; }

/* ATTENTE — « Saisissez votre adresse complète pour voir les modes de
   livraison » s'affichait dans un cadre plein, identique à celui des vraies
   options : on croyait lire un choix grisé, pas une information. Trait
   discontinu et fond transparent : la place est réservée, rien n'est encore
   proposé. */
.shops-checkout-options.is-empty {
    border-style: dashed;
    border-color: var(--ck-line, #d5d7da);
    background: transparent;
}
.shops-checkout-options.is-empty > p { margin: 0; padding: .35rem .75rem; }
.shops-checkout-option,
.shops-checkout-shipping-option,
.shops-checkout-payment-option {
    display: flex; align-items: center; gap: .75rem;
    padding: .8rem .9rem !important; margin: 0 !important;
    border: 0 !important; border-radius: 0 !important;
    border-bottom: 1px solid var(--ck-line, #e2e3e5) !important;
    cursor: pointer; background: var(--ck-surface, #fff);
    transition: background .12s ease;
}
.shops-checkout-options > label:last-child,
.shops-checkout-option-group > label:last-child { border-bottom: 0 !important; }
.shops-checkout-option:hover,
.shops-checkout-shipping-option:hover,
.shops-checkout-payment-option:hover { background: var(--ck-hover, #f7f8fa); }
.shops-checkout-option.active,
.shops-checkout-shipping-option.active,
.shops-checkout-payment-option.active {
    background: var(--ck-accent-soft, rgba(13, 110, 253, .06));
    box-shadow: inset 3px 0 0 var(--ck-accent, #0d6efd);
}
/* Radio à la couleur de la boutique + cible un peu plus grande. */
.shops-checkout-option input[type="radio"],
.shops-checkout-shipping-option input[type="radio"],
.shops-checkout-payment-option input[type="radio"] {
    flex-shrink: 0; margin: 0; width: 1.1rem; height: 1.1rem; accent-color: var(--ck-accent, #0d6efd);
}
/* Icône transporteur : gabarit constant → les libellés s'alignent proprement. */
.shops-checkout-shipping-option > i,
.shops-checkout-payment-option > i { width: 1.4rem; text-align: center; font-size: 1.05rem; flex-shrink: 0; }
.shops-checkout-option-label { flex: 1 1 auto; min-width: 0; }
.shops-checkout-option-price { font-weight: 600; white-space: nowrap; }
.shops-checkout-carrier-logo { max-width: 46px; max-height: 30px; object-fit: contain; flex-shrink: 0; }
/* Bloc texte d'une option livraison : nom (compact) + 2e ligne discrète (délai /
   dépôt de retrait). Le nom n'est plus « gros et gras » — juste posé. */
.shops-checkout-ship-info { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: .08rem; line-height: 1.3; }
.shops-checkout-ship-name { font-size: .9rem; font-weight: 600; color: var(--ck-text, #1a1a1a); }
.shops-checkout-ship-name .badge { font-size: .66rem; font-weight: 600; vertical-align: middle; margin-left: .15rem; }
.shops-checkout-ship-sub { font-size: .78rem; color: var(--ck-muted, #6b7177); }
.shops-checkout-ship-price { flex: 0 0 auto; margin-left: auto; align-self: center; font-weight: 600; font-size: .9rem; white-space: nowrap; }
/* Pied « Voir les N autres options » : bandeau plein-largeur, à la couleur de la
   boutique, séparé des options par leur trait — flush sous la dernière. */
.shops-checkout-shipping-toggle {
    display: flex !important; align-items: center; justify-content: center; gap: .4rem;
    width: 100%; padding: .65rem !important; margin: 0 !important;
    border: 0 !important; border-radius: 0 !important;
    color: var(--ck-accent, #0d6efd) !important; font-weight: 600; font-size: .82rem;
    background: var(--ck-band, #f7f8fa);
}
.shops-checkout-shipping-toggle:hover { background: var(--ck-hover, #f7f8fa); }

/* Commande multi-vendeurs : un « colis » par vendeur = une carte distincte
   (bandeau d'en-tête + liste des transporteurs de ce vendeur). */
.shops-checkout-shipping-group {
    border: 1px solid var(--ck-line, #e2e3e5);
    border-radius: 12px;
    overflow: hidden;
    margin-bottom: .85rem;
    background: var(--ck-surface, #fff);
    box-shadow: 0 1px 2px rgba(16, 24, 40, .04);
}
.shops-checkout-shipping-group__head {
    display: flex; align-items: center; gap: .6rem;
    padding: .6rem .85rem;
    background: var(--ck-band, #f7f8fa);
    border-bottom: 1px solid var(--ck-line, #e2e3e5);
}
/* Icône du colis en pastille (cadre net, comme une étiquette d'expédition). */
.shops-checkout-shipping-group__icon {
    flex: 0 0 auto; display: inline-flex; align-items: center; justify-content: center;
    width: 1.9rem; height: 1.9rem; border-radius: 8px;
    background: var(--ck-surface, #fff); border: 1px solid var(--ck-line, #e2e3e5);
    color: var(--ck-muted, #6b7177); font-size: .9rem;
}
.shops-checkout-shipping-group__name {
    font-weight: 600; font-size: .9rem; color: var(--ck-text, #1a1a1a);
    min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
/* Méta « N articles · sous-total » en pilule discrète, calée à droite. */
.shops-checkout-shipping-group__meta {
    margin-left: auto; flex: 0 0 auto;
    font-size: .76rem; color: var(--ck-muted, #6b7177);
    background: var(--ck-surface, #fff); border: 1px solid var(--ck-line, #e2e3e5);
    border-radius: 999px; padding: .12rem .55rem; white-space: nowrap;
}
.shops-checkout-shipping-group .shops-checkout-shipping-option:last-child { border-bottom: 0 !important; }
/* Aucun transporteur pour ce vendeur : c'est un BLOQUANT (colis inexpédiable) →
   encart d'alerte ambré, pas un texte gris qu'on survole. */
.shops-checkout-shipping-group__empty {
    display: flex; align-items: center; gap: .5rem;
    padding: .7rem .85rem; font-size: .82rem;
    color: #92400e; background: #fff7ed;
}
.shops-checkout-shipping-group__empty i { color: #d97706; flex: 0 0 auto; }
/* Mobile : nom du vendeur en entier (la pilule méta passe sous le nom, indentée
   sous l'icône) plutôt que « Colis de Ma Boutiq… » tronqué. */
@media (max-width: 480px) {
    .shops-checkout-shipping-group__head { flex-wrap: wrap; row-gap: .3rem; }
    .shops-checkout-shipping-group__name { white-space: normal; overflow: visible; }
    .shops-checkout-shipping-group__meta { flex-basis: 100%; margin-left: 2.5rem; }
}
/* Point relais du colis d'un vendeur (relais choisi / bouton « choisir »). */
.shops-checkout-vendor-pickup:not(:empty) {
    padding: .55rem .85rem;
    border-top: 1px dashed var(--ck-line, #e2e3e5);
    background: var(--ck-surface, #fff);
}
.shops-checkout-pickup-chosen { font-size: .85rem; }

/* Points relais (garde une carte bordée distincte) */
.shops-checkout-pickup-option { cursor: pointer; transition: border-color .15s; }
.shops-checkout-pickup-option.active {
    border-color: var(--ck-accent, #0d6efd) !important;
    background: var(--ck-accent-soft, rgba(13, 110, 253, .06));
}

/* Affichage COMPACT du sélecteur de points relais : carte plus courte, liste
   déroulante limitée, cartes moins hautes — évite un widget démesuré quand il
   y a beaucoup de relais. (!important : surcharge la hauteur inline + .p-3.) */
#pickup-map { height: 190px !important; margin-bottom: .5rem !important; }
.pickup-points-list { max-height: 300px; overflow-y: auto; padding-right: .25rem; }
.shops-checkout-pickup-option {
    padding: .5rem .7rem !important;
    margin-bottom: .375rem !important;
    gap: .6rem !important;
    line-height: 1.3;
}
.shops-checkout-pickup-option strong { font-size: .85rem; }
.shops-checkout-pickup-option small  { font-size: .76rem; }
/* Bandeau « points de démonstration » : le conteneur passe en flex sur grand
   écran (carte | liste). Sans largeur pleine, le bandeau devenait une TROISIÈME
   colonne et écrasait la liste des relais à quelques pixels. */
.shops-checkout-pickup-demo { flex: 1 1 100%; }
/* Desktop : carte + liste côte à côte → beaucoup moins de hauteur. */
@media (min-width: 992px) {
    #pickup-widget { display: flex; flex-wrap: wrap; gap: 1rem; align-items: flex-start; }
    #pickup-widget #pickup-map { flex: 0 0 52%; height: 300px !important; margin-bottom: 0 !important; }
    #pickup-widget .pickup-points-list { flex: 1 1 48%; max-height: 300px; }
}

/* ── Correctifs d'accessibilité et de cohérence du tunnel ───────────────────
   Quatre points relevés en audit, tous vérifiés au navigateur.

   1. FOCUS DU BOUTON DE PAIEMENT. `.shops-checkout-pay-btn` pose `border: 0`,
      ce qui annule aussi l'anneau que Bootstrap dérive de la bordure : au
      clavier, le bouton le plus important de la page ne changeait pas d'un
      pixel quand il recevait le focus.
   2. CONTRASTES sous 4,5:1 (mesurés) : la pastille « Click & Collect » (3,49)
      et — sur le fond teinté de l'option SÉLECTIONNÉE — le délai « 2 à 4 jours »
      (4,45) et la mention « Gratuit » (4,08). C'est l'état actif qui fait passer
      sous le seuil. (L'indicatif « +33 », 3,17, se corrigeait chez awtel : son
      jeton de gris atone servait aussi ailleurs.)
   3. RADIOS DE FACTURATION en bleu Bootstrap quand celles de la livraison et
      du paiement sont à la couleur de la boutique. La classe est retirée dans
      la vue ; ce filet couvre les balisages qui la porteraient encore.
   4. IDENTITÉ SUR TÉLÉPHONE ÉTROIT : civilité + prénom + nom tiennent sur une
      seule ligne, soit 93 px par champ à 320 px de large. */

.shops-checkout-pay-btn:focus-visible,
.shops-checkout-estimate-btn:focus-visible {
    outline: 3px solid var(--ck-text, #111827);
    outline-offset: 2px;
}

.shops-checkout .badge.bg-success-subtle.text-success { color: #0f5132 !important; }
.shops-checkout .text-success { color: #146c43 !important; }
.shops-checkout-ship-sub { color: #5f656b; }

/* Les radios du tunnel parlent d'une seule voix, quelle que soit la section. */
.shops-checkout .shops-checkout-option input[type="radio"].form-check-input:checked {
    background-color: transparent;
    border-color: currentColor;
}

@media (max-width: 399.98px) {
    .shops-checkout-civility { flex: 0 0 100%; max-width: 100%; }
    .shops-checkout-identity { flex: 0 0 50%;  max-width: 50%; }
}

/* L'aide de section passe sous le titre dès que la ligne devient trop courte :
   collée au H2, « Toutes les transactions sont sécurisées » se lisait mal. */
.shops-checkout-section-head { flex-wrap: wrap; }
@media (max-width: 575.98px) {
    .shops-checkout-section-hint { flex: 1 0 100%; margin-top: .15rem; }
}

/* ── Conditions d'un code promo, énoncées une par une ───────────────────────
   Partagé par le panier et le tunnel. Trois états :
     .is-ok   remplie          .is-ko   manquante        .is-wait  en attente
   La couleur ne porte JAMAIS l'information seule — chaque ligne a son icône
   (coche, croix, cercle pointillé) et son intitulé lu par les lecteurs d'écran
   (« Condition remplie : … »). Un fond trop appuyé ferait de cette liste le
   sujet du bloc : elle reste discrète, c'est une explication, pas une alarme. */
/* Le bloc est POSÉ sur un fond propre : sans lui, la liste flottait entre le
   message d'erreur et les totaux, et l'œil ne savait plus si « aucun article
   concerné » commentait le code ou la ligne « Sous-total » juste dessous. */
.shops-promo-conditions {
    margin: .55rem 0 0;
    padding: .5rem .6rem;
    border-radius: .45rem;
    background: rgba(0, 0, 0, .025);
    font-size: .82rem;
    line-height: 1.4;
}
.shops-promo-conditions__head {
    margin: 0 0 .3rem; font-weight: 600; font-size: .78rem;
    text-transform: uppercase; letter-spacing: .03em; color: var(--ck-muted, #6b7177);
}
.shops-promo-conditions__list { list-style: none; margin: 0; padding: 0; }
.shops-promo-cond {
    display: flex;
    align-items: flex-start;
    gap: .45rem;
    padding: .22rem 0;
}
.shops-promo-cond + .shops-promo-cond { border-top: 1px solid rgba(0, 0, 0, .05); }
.shops-promo-cond > i { flex: 0 0 auto; margin-top: .15rem; font-size: .9em; }
.shops-promo-cond__txt { min-width: 0; }
.shops-promo-cond__label { display: block; }
/* Le détail sous son intitulé, en retrait de ton : c'est une précision, pas une
   seconde condition. */
.shops-promo-cond__detail {
    display: block;
    margin-top: .1rem;
    font-size: .95em;
    opacity: .75;
}

.shops-promo-cond.is-ok   { color: #146c43; }
.shops-promo-cond.is-ko   { color: #b02a37; }
.shops-promo-cond.is-wait { color: #5f656b; }

/* Page de confirmation, petit écran : le récapitulatif des articles se plafonne
   pour ne pas repousser l'offre après-vente hors de portée. Au-delà du plafond il
   défile ; en dessous, la règle est sans effet. */
@media (max-width: 991.98px) {
    .shops-confirm-items { max-height: 22rem; overflow-y: auto; }
}

/* Pastille de l'en-tête de confirmation quand la commande n'est PAS réglée :
   la coche verte annoncerait une transaction aboutie. */
.confirmation-check--attente { color: #b8860b; background: #fff7e6; }

/* Bandeau de l'offre après-vente : une pastille Bootstrap est en `nowrap`, et
   cette phrase-là est longue — sur un téléphone elle sortait du cadre et se
   faisait couper (« … pour vous re »). Elle passe à la ligne et reste dans la
   largeur disponible. */
.shops-upsell .badge {
    white-space: normal;
    max-width: 100%;
    line-height: 1.35;
    text-wrap: balance;
}

/* Compte à rebours de l'offre après-vente : lisible sans crier, chiffres à
   chasse fixe pour que la ligne ne tressaute pas à chaque seconde. */
.shops-upsell-chrono { font-size: .85rem; color: #b02a37; }
.shops-upsell-chrono strong { font-variant-numeric: tabular-nums; }


/* ── Actions (Payer maintenant) ─────────────────────────────────────────── */
.shops-checkout-actions { margin-top: 1.5rem; }

/* Total à payer, au contact du bouton (mobile/tablette). Discret : il rappelle
   le montant, il ne concurrence pas le bouton. */
.shops-checkout-paytotal {
    display: flex; align-items: baseline; justify-content: space-between;
    gap: .75rem; margin-bottom: .6rem;
}
.shops-checkout-paytotal__label {
    font-size: .875rem; color: var(--ck-muted, #6b7280);
}
.shops-checkout-paytotal__value {
    font-size: 1.15rem; font-weight: 700; white-space: nowrap;
}

/* MOBILE ET TABLETTE — le bouton de paiement reste à portée de pouce.
   Il vivait tout en bas d'un formulaire de plus de deux écrans : après avoir
   rempli son adresse, le client devait dérouler jusqu'au bout pour trouver
   comment payer. `sticky` plutôt qu'un second bouton fixe : un seul bouton dans
   la page, donc un seul état à tenir (libellé, désactivation pendant l'envoi) et
   rien à dupliquer. Il se cale au bas de l'écran pendant la saisie, puis reprend
   sa place naturelle quand on atteint la fin du formulaire.
   Au-delà de 992 px, la colonne tient dans la hauteur : on n'y touche pas. */
@media (max-width: 991.98px) {
    .shops-checkout-actions {
        position: sticky;
        bottom: 0;
        z-index: 5;
        margin-left: -.75rem; margin-right: -.75rem;
        padding: .75rem .75rem calc(.75rem + env(safe-area-inset-bottom, 0px));
        background: var(--ck-surface, #fff);
        border-top: 1px solid var(--ck-line, #e6e7e9);
        box-shadow: 0 -6px 16px -12px rgba(0, 0, 0, .35);
    }
    /* « Retour au panier » quitte la barre collante : dans une zone où le pouce
       vise le paiement, un lien qui vide l'écran n'a rien à faire à 8 px du
       bouton. Il reste accessible en haut de page. */
    .shops-checkout-actions .shops-checkout-back { display: none; }
}
.shops-checkout-pay-btn {
    width: 100%; padding: .95rem 1rem; font-size: 1.05rem; font-weight: 600;
    color: var(--btn-1-color, #fff);
    background: var(--btn-1-bg, var(--color-1, #0d6efd));
    border: 0; border-radius: var(--btn-1-radius, 8px);
}
.shops-checkout-pay-btn-label { color: var(--btn-1-color, #fff); }
.shops-checkout-pay-btn:hover,
.shops-checkout-pay-btn:focus {
    background: var(--btn-1-bg-hover, color-mix(in srgb, var(--btn-1-bg, var(--color-1, #0d6efd)) 85%, #000));
    color: var(--btn-1-color, #fff);
}
.shops-checkout-pay-btn:disabled { opacity: .6; }
.shops-checkout-estimate-btn {
    width: 100%; padding: .6rem 1rem; margin-top: .6rem;
    border: 1px solid var(--ck-line, #d5d7da); border-radius: var(--ck-radius, 8px);
    background: var(--ck-surface, #fff); color: var(--ck-text, #333);
}
.shops-checkout-estimate-btn:hover { background: var(--ck-hover, #f7f8fa); }
.shops-checkout-back { display: inline-block; margin-top: 1rem; font-size: .875rem; color: var(--ck-muted, #6b7177); text-decoration: none; }
.shops-checkout-back:hover { color: var(--ck-accent, #0d6efd); }

/* ── Récapitulatif (colonne droite) ─────────────────────────────────────── */
.shops-checkout-summary-products { margin-bottom: 1.25rem; }
.shops-checkout-summary-item { display: flex; align-items: center; gap: .85rem; padding: .6rem 0; }
.shops-checkout-summary-thumb {
    position: relative; flex-shrink: 0;
    width: 3.25rem; height: 3.25rem; border-radius: 8px;
    border: 1px solid var(--ck-line, #d9dadd); background: var(--ck-surface, #fff);
    display: flex; align-items: center; justify-content: center; color: var(--ck-muted, #adb1b6);
}
.shops-checkout-summary-thumb img { width: 100%; height: 100%; object-fit: cover; border-radius: 8px; }
.shops-checkout-summary-badge {
    position: absolute; top: -.5rem; right: -.5rem;
    min-width: 1.25rem; height: 1.25rem; padding: 0 .3rem;
    background: var(--ck-text, #6b7177); color: var(--ck-surface, #fff); border-radius: 999px;
    font-size: .72rem; font-weight: 600;
    display: flex; align-items: center; justify-content: center;
}
.shops-checkout-summary-info { flex: 1 1 auto; min-width: 0; }
/* Titre + total de ligne sur UNE ligne : le total partage ainsi le même bord droit
   que le prix de base et les options en dessous (une seule colonne de montants). */
.shops-checkout-summary-headline { display: flex; align-items: baseline; gap: .5rem; }
.shops-checkout-summary-title { flex: 1 1 auto; min-width: 0; font-size: .875rem; font-weight: 600; color: var(--ck-text, #1a1a1a); }
.shops-checkout-summary-variant { font-size: .8rem; color: var(--ck-muted, #6b7177); }
/* Options (extras) de la ligne : chaque option en ligne sous le produit, prix
   aligné à droite sans retour à la ligne, libellé qui wrap au mot. */
.shops-checkout-summary-options { margin-top: .1rem; }
.shops-checkout-summary-opt { display: flex; align-items: baseline; gap: .5rem; font-size: .78rem; color: var(--ck-muted, #6b7177); line-height: 1.35; }
.shops-checkout-summary-opt .opt-label { flex: 1 1 auto; min-width: 0; overflow-wrap: anywhere; }
.shops-checkout-summary-opt .opt-price { flex: 0 0 auto; margin-left: auto; white-space: nowrap; color: var(--ck-text, #495057); }
.shops-checkout-summary-opt i { opacity: .5; }
.shops-checkout-summary-price { flex: 0 0 auto; font-size: .875rem; font-weight: 600; white-space: nowrap; text-align: right; }

/* Code promo — `min-width: 0` : sans lui, la largeur intrinsèque du placeholder
   (« Code de réduction ou carte cadeau ») empêchait le champ de se rétrécir dans
   la colonne, et le texte se retrouvait coupé en plein mot. */
.shops-checkout-promo { display: flex; gap: .5rem; margin-bottom: .75rem; }
.shops-checkout-promo .form-control { flex: 1 1 auto; min-width: 0; }
.shops-checkout-promo-btn {
    flex-shrink: 0; border: 1px solid var(--ck-field-line, #babfc3); border-radius: var(--ck-radius, 8px);
    background: var(--ck-hover, #eef0f2); color: var(--ck-text, #333); padding: 0 1.1rem; font-weight: 500;
}
.shops-checkout-promo-btn:hover { background: color-mix(in srgb, var(--ck-text, #333) 10%, var(--ck-surface, #fff)); }
.shops-checkout-promo-applied {
    display: flex; align-items: center; gap: .35rem;
    background: color-mix(in srgb, var(--ck-ok, #2f6f3a) 8%, var(--ck-surface, #fff));
    border: 1px solid color-mix(in srgb, var(--ck-ok, #2f6f3a) 25%, var(--ck-surface, #fff));
    border-radius: var(--ck-radius, 8px);
    padding: .5rem .75rem; font-size: .85rem; color: var(--ck-ok, #2f6f3a); margin-bottom: .75rem;
}
.shops-checkout-promo-applied .btn-close { font-size: .55rem; }

/* Message sous le champ promo. Un refus s'affichait en texte rouge nu sous un
   encart de succès en pastille verte : deux langages visuels pour deux issues
   du MÊME geste. La pastille ambre répond maintenant à la verte, au même
   endroit et au même gabarit — seule la couleur change de sens. Vide, elle ne
   doit rien peindre du tout, d'où le `:empty`. */
.shops-promo-msg {
    display: flex; align-items: center; gap: .35rem;
    border-radius: var(--ck-radius, 8px);
    padding: .5rem .75rem; font-size: .85rem;
    margin-top: .5rem; margin-bottom: .75rem;
}
.shops-promo-msg:empty { display: none; }
.shops-promo-msg > i { flex: 0 0 auto; }
.shops-promo-msg--warn {
    background: color-mix(in srgb, var(--ck-warn, #8a5a00) 10%, var(--ck-surface, #fff));
    border: 1px solid color-mix(in srgb, var(--ck-warn, #8a5a00) 28%, var(--ck-surface, #fff));
    color: var(--ck-warn, #8a5a00);
}
.shops-promo-msg--ok {
    background: color-mix(in srgb, var(--ck-ok, #2f6f3a) 8%, var(--ck-surface, #fff));
    border: 1px solid color-mix(in srgb, var(--ck-ok, #2f6f3a) 25%, var(--ck-surface, #fff));
    color: var(--ck-ok, #2f6f3a);
}

/* Totaux */
.shops-checkout-totals { border-top: 1px solid var(--ck-line, #e6e7e9); padding-top: 1rem; }
.shops-checkout-total-row {
    display: flex; justify-content: space-between; align-items: baseline;
    font-size: .9rem; color: var(--ck-text, #333); margin-bottom: .6rem;
}
.shops-checkout-total-discount { color: var(--ck-ok, #2f6f3a); }
.shops-checkout-total-grand { font-size: 1rem; font-weight: 700; color: var(--ck-text, #1a1a1a); margin-top: .6rem; margin-bottom: .1rem; padding-top: .6rem; border-top: 1px solid var(--ck-line, #e6e7e9); }
.shops-checkout-total-grand-value { display: flex; align-items: baseline; gap: .4rem; }
.shops-checkout-total-currency { font-size: .72rem; font-weight: 500; color: var(--ck-muted, #6b7177); }
.shops-checkout-total-grand-value #summary-total { font-size: 1.4rem; }
.shops-checkout-total-tax { font-size: .78rem; color: var(--ck-muted, #6b7177); }
/* Total du récap : bandeau d'accent marque (unité avec le panier et le tiroir).
   Le texte reste sombre pour le contraste ; seul le fond porte la couleur. */
.shops-checkout-grand-total {
    background: color-mix(in srgb, var(--btn-1-bg, var(--color-1, #F8B11F)) 9%,  var(--ck-surface, #fff));
    border:  1px solid color-mix(in srgb, var(--btn-1-bg, var(--color-1, #F8B11F)) 30%, var(--ck-surface, #fff));
    border-radius: 10px;
    padding: .55rem .7rem;
}

/* Incitation anniversaire (dans la section Contact) : DISCRÈTE — un fond à peine
   posé et le trait fin de la charte, pas un bandeau coloré. Seule l'icône garde
   une nuance neutre. Rattachée au compte, elle ne doit pas crier plus fort que
   les champs autour. */
.shops-checkout-birthday {
    background: var(--ck-band, #f7f8fa);
    border: 1px solid var(--ck-line, #e2e3e5);
    border-radius: var(--ck-radius, 8px);
    padding: .7rem .8rem;
}
.shops-checkout-birthday__text { font-size: .85rem; color: var(--ck-text, #1a1a1a); line-height: 1.4; }
.shops-checkout-birthday__text .fa-cake-candles { color: var(--ck-muted, #6b7177); }
.shops-checkout-birthday__form { display: flex; flex-wrap: wrap; align-items: center; gap: .5rem; }
.shops-checkout-birthday__form .form-control { width: auto; }

/* PAIEMENT EXPRESS : boutons des fournisseurs connectés + séparateur « ou ». */
.shops-checkout-express { margin-bottom: 1.25rem; }
.shops-checkout-express__label { text-align: center; font-size: .8rem; color: var(--ck-muted, #6b7177); margin: 0 0 .5rem; }
.shops-checkout-express__buttons { display: flex; flex-wrap: wrap; gap: .6rem; }
.shops-checkout-express__btn {
    flex: 1 1 auto; min-width: 8rem; height: 2.85rem;
    display: inline-flex; align-items: center; justify-content: center; gap: .4rem;
    border: 0; border-radius: var(--ck-radius, 8px); cursor: pointer;
    font-weight: 700; font-size: 1rem; transition: filter .15s ease;
}
.shops-checkout-express__btn:hover:not(:disabled) { filter: brightness(.96); }
.shops-checkout-express__btn:disabled { opacity: .6; cursor: default; }
.shops-checkout-express__btn:focus-visible { outline: 2px solid var(--ck-accent, #0d6efd); outline-offset: 2px; }
/* PayPal : jaune de marque, texte foncé, le « Pal » ne se colorie pas (icône FA). */
.shops-checkout-express__btn--paypal { background: #ffc439; color: #003087; }
.shops-checkout-express__btn--paypal .fa-paypal { font-size: 1.25rem; }
/* Wallet Apple/Google Pay : noir, texte blanc (convention des boutons wallet). */
.shops-checkout-express__btn--wallet { background: #000; color: #fff; }
.shops-checkout-express__btn--wallet .fa-apple-pay { font-size: 1.5rem; }
/* Séparateur « ou » : un trait de part et d'autre. */
.shops-checkout-express__sep { display: flex; align-items: center; gap: .75rem; margin-top: 1.1rem; color: var(--ck-muted, #6b7177); font-size: .8rem; text-transform: uppercase; letter-spacing: .04em; }
.shops-checkout-express__sep::before, .shops-checkout-express__sep::after { content: ""; flex: 1 1 auto; height: 1px; background: var(--ck-line, #e2e3e5); }

/* ── Récap repliable (mobile) : au-dessus du formulaire, façon Shopify ──── */
.shops-checkout-summary-bar { display: none; }
@media (max-width: 991.98px) {
    .shops-checkout-aside {
        order: -1;
        background: var(--ck-band, #f7f8fa);
        border-top: 1px solid var(--ck-line, #e6e7e9); border-bottom: 1px solid var(--ck-line, #e6e7e9);
        margin: 0 calc(-1 * var(--bs-gutter-x, 1.5rem) / 2);
        padding: 0 calc(var(--bs-gutter-x, 1.5rem) / 2);
    }
    .shops-checkout-summary-bar {
        display: flex; align-items: center; justify-content: space-between;
        padding: 1rem .25rem; cursor: pointer; font-size: .95rem;
        color: var(--ck-accent, #0d6efd);
    }
    .shops-checkout-summary-bar-total { font-weight: 700; color: var(--ck-text, #1a1a1a); }
    .shops-checkout-summary-bar-caret { transition: transform .2s; margin-left: .35rem; font-size: .8rem; }
    .shops-checkout-summary-body { display: none; padding-bottom: 1.25rem; }
    .shops-checkout-summary-toggle:checked ~ .shops-checkout-summary-body { display: block; }
    .shops-checkout-summary-toggle:checked ~ .shops-checkout-summary-bar .shops-checkout-summary-bar-caret { transform: rotate(180deg); }
    .shops-checkout-main { padding: 1.5rem 0; }
}

/* -- Raccourcis mis en avant (tuiles sous le fil d'Ariane) ----------------- */
.shops-shortcuts {
    display: flex;
    flex-wrap: nowrap;            /* tous les raccourcis sur UNE seule ligne */
    gap: .75rem;
    overflow-x: auto;            /* défilement horizontal quand ça déborde (desktop compris) */
    padding-bottom: .25rem;     /* l'ombre au survol des tuiles n'est pas rognée */
    scroll-snap-type: x proximity;
    /* Barre de défilement MASQUÉE : le défilement reste possible (molette, swipe,
       clavier) et les deux flèches le pilotent sur pointeur fin. Firefox. */
    scrollbar-width: none;
    -ms-overflow-style: none;   /* Edge ancien / IE */
}
/* WebKit : `display:none` suffit — fixer une hauteur laisserait la gouttière. */
.shops-shortcuts::-webkit-scrollbar { display: none; }
.shops-shortcuts-scroller { position: relative; }
.shops-shortcuts-nav {
    position: absolute; top: 50%; transform: translateY(-50%);
    z-index: 3; width: 36px; height: 36px; border-radius: 50%;
    border: 1px solid rgba(0,0,0,.1); background: #fff; color: #1a1a2e;
    box-shadow: 0 2px 10px rgba(0,0,0,.18); cursor: pointer;
    display: flex; align-items: center; justify-content: center;
    font-size: .95rem; transition: background .15s, box-shadow .15s;
}
.shops-shortcuts-nav:hover { background: #f3f5fb; box-shadow: 0 3px 14px rgba(0,0,0,.24); }
.shops-shortcuts-nav--prev { left: -2px; }
.shops-shortcuts-nav--next { right: -2px; }
.shops-shortcuts-nav[hidden] { display: none; }
@media (hover: none) and (pointer: coarse) { .shops-shortcuts-nav { display: none !important; } }
.shops-shortcut { scroll-snap-align: start; }
.shops-shortcut {
    display: flex;
    align-items: center;
    gap: .75rem;
    min-width: 200px;
    flex: 0 0 auto;              /* ne rétrécit pas → déborde et déclenche le défilement */
    padding: .6rem .9rem .6rem .6rem;
    background: #fff;
    border: 1px solid #e6e8ec;
    border-radius: 12px;
    text-decoration: none;
    color: #1f2430;
    transition: box-shadow .15s, transform .15s, border-color .15s;
}
.shops-shortcut:hover {
    border-color: #d3d7de;
    box-shadow: 0 6px 18px rgba(20, 30, 60, .08);
    transform: translateY(-2px);
    color: #1f2430;
}
.shops-shortcut__media {
    flex-shrink: 0;
    width: 48px;
    height: 48px;
    border-radius: 8px;
    background: #f4f6f9;
    display: flex;
    align-items: center;
    justify-content: center;
    overflow: hidden;
    color: #8a93a2;
    font-size: 1.15rem;
}
.shops-shortcut__media img {
    width: 100%;
    height: 100%;
    object-fit: cover;
}
.shops-shortcut__label {
    font-weight: 600;
    font-size: .92rem;
    line-height: 1.25;
}
/* Titre optionnel (raccourcis AUTOMATIQUES : « Explorer » / « Affiner votre recherche ») */
.shops-shortcuts__title {
    font-size: .78rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: .05em;
    color: #8a93a2;
}
/* Injecté juste sous la barre de recherche : au plus près d'elle. */
.shops-shortcuts-inject { margin-top: .25rem; }
/* Thème sombre : les tuiles étaient en couleurs claires codées en dur. */
:root[data-theme="dark"] .shops-shortcut {
    background: #1b1e24;
    border-color: #2c3036;
    color: #e6e8ec;
}
:root[data-theme="dark"] .shops-shortcut:hover { border-color: #3a3f47; color: #fff; }
:root[data-theme="dark"] .shops-shortcut__media { background: #24272e; color: #aab2c0; }

/* Mobile : défilement horizontal (X) au lieu du retour à la ligne.
   Bleed jusqu'aux bords du conteneur (body a overflow-x:hidden → pas de scroll page). */
@media (max-width: 767.98px) {
    .shops-shortcuts {
        flex-wrap: nowrap;
        overflow-x: auto;
        -webkit-overflow-scrolling: touch;
        scroll-snap-type: x proximity;
        margin-inline: -.75rem;
        padding: 0 .75rem .2rem;       /* padding-bottom : l'ombre au survol n'est pas rognée */
    }
    /* Ces trois règles REDONNAIENT la barre sous 768 px, là où la règle générale
       vient de la masquer : une même bande se serait affichée différemment selon
       la largeur de l'écran. Le swipe reste le geste naturel sur tactile. */
    .shops-shortcuts::-webkit-scrollbar { display: none; }
    .shops-shortcut {
        flex: 0 0 auto;                /* ne rétrécit pas → provoque le scroll + laisse « déborder » la tuile suivante */
        scroll-snap-align: start;
    }
}

/* ==========================================================================
   Filtres à swatches (types couleur / image / icône / svg de l'attribut).
   Ces classes n'existaient pas tant que filter_type était figé sur checkbox.
   ========================================================================== */
.shops-color-swatch,
.shops-img-swatch,
.shops-icon-swatch,
.shops-svg-swatch {
    position: relative;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 34px;
    height: 34px;
    border: 1px solid #d0d5dd;
    cursor: pointer;
    overflow: hidden;
    transition: border-color .12s, box-shadow .12s;
}
.shops-color-swatch .swatch-inner {
    display: block;
    width: 100%;
    height: 100%;
}
.shops-icon-swatch i { font-size: 16px; color: #333; }
.shops-img-swatch img,
.shops-svg-swatch span { display: block; }
.shops-color-swatch:hover,
.shops-img-swatch:hover,
.shops-icon-swatch:hover,
.shops-svg-swatch:hover { border-color: #111; }
.shops-color-swatch.active,
.shops-img-swatch.active,
.shops-icon-swatch.active,
.shops-svg-swatch.active {
    border-color: #111;
    box-shadow: 0 0 0 2px #111;
}
/* Valeur sans produit (product_count = 0) : barrée en diagonale. */
.shops-color-swatch .swatch-strike {
    position: absolute;
    inset: 0;
    pointer-events: none;
    background: linear-gradient(to top right, transparent calc(50% - 1px), #e11d48 50%, transparent calc(50% + 1px));
}

/* Sélecteur de variantes de la FICHE : pastille couleur / image (shops-js-attr-btn). */
.shops-attr-swatch {
    width: 34px;
    height: 34px;
    padding: 0;
    border: 1px solid #d0d5dd;
    background: var(--sw, #eee);
    cursor: pointer;
    overflow: hidden;
    transition: border-color .12s, box-shadow .12s;
}
.shops-attr-swatch--img { background: #fff; }
.shops-attr-swatch--img img { width: 100%; height: 100%; object-fit: cover; display: block; }
.shops-attr-swatch:hover { border-color: #111; }
.shops-attr-swatch.active { border-color: #111; }
.shops-attr-swatch.is-unavailable { opacity: .35; }

/* Catalogue : léger fondu au 1er chargement — la grille (SSR) n'apparaît qu'une
   fois facettes + produits injectés, en fondu, plutôt qu'un « flash » de swap.
   opacity:0 (et non visibility) → la mise en page reste en flux, pas de saut. */
#shops-products { transition: opacity .25s ease; }
/*
 * Grille masquée le temps du PREMIER chargement d'une URL filtrée (le SSR ne
 * reflète pas les filtres AJAX) — SAUF quand le squelette est posé.
 *
 * `.is-skeleton { opacity: 1 }` est déclaré plus haut dans ce fichier : à
 * spécificité égale (un id + une classe), c'est la règle la PLUS BASSE qui
 * l'emporte, donc celle-ci gagnait et le squelette était construit puis rendu
 * invisible. Symptôme : on arrivait sur une page filtrée — typiquement depuis
 * la recherche en langage courant, qui redirige vers le catalogue — et on
 * n'avait qu'un vide, jamais le squelette, jusqu'à l'arrivée des produits.
 */
#shops-products.is-catalog-initial:not(.is-skeleton) { opacity: 0; }

/* ==========================================================================
   FICHE PRODUIT — galerie, carte, sélecteurs (déplacé du <style> inline de
   Views/front/catalog/detail.php).
   ========================================================================== */
.shops-product-gallery__thumb { cursor: pointer; opacity: .7; transition: opacity .15s, border-color .15s; border: 2px solid #dee2e6 !important; background: none; }
.shops-product-gallery__thumb.active, .shops-product-gallery__thumb:hover { opacity: 1; border-color: var(--bs-primary) !important; }
.shops-product-gallery__main--zoom img { cursor: zoom-out; transform: scale(1.4); transition: transform .3s; }
.shops-product-gallery__main img { transition: transform .3s; }
.shops-product-card { transition: box-shadow .2s, transform .15s; }
.shops-product-card:hover { box-shadow: 0 8px 24px rgba(0, 0, 0, .1) !important; transform: translateY(-2px); }
.shops-js-attr-btn.active { color: #fff; }
/* Option indisponible AVEC la sélection courante : grisée mais CLIQUABLE (façon
   Shopify) — le clic bascule dessus et libère les autres groupes. Seul :disabled
   (valeur sans aucune variante) est mort. (Ex-<style> inline de catalog/detail.php.) */
.shops-js-attr-btn.is-unavailable { opacity: .4; text-decoration: line-through; }
.shops-js-attr-btn:disabled { pointer-events: none; }
.shops-js-giftcard-preset.active, .shops-js-donation-preset.active { background: var(--bs-primary); border-color: var(--bs-primary); color: #fff; }

/* Galerie fiche produit : flèches de navigation + vignettes (ex-<style> inline de
   Views/front/catalog/detail.php). */
.shops-gallery-nav{position:absolute;top:50%;transform:translateY(-50%);z-index:3;width:38px;height:38px;border:0;border-radius:50%;
  background:rgba(255,255,255,.9);color:#111;box-shadow:0 1px 6px rgba(0,0,0,.15);display:flex;align-items:center;justify-content:center;cursor:pointer;transition:background .15s}
.shops-gallery-nav:hover{background:#fff}
.shops-gallery-nav--prev{left:10px}
.shops-gallery-nav--next{right:10px}
.shops-js-product-thumbs .shops-product-gallery__thumb{opacity:.6;transition:opacity .15s,border-color .15s;cursor:pointer}
.shops-js-product-thumbs .shops-product-gallery__thumb.active{opacity:1;border-color:var(--btn-1-bg,#2c7a6e)!important;border-width:2px}

/* Sélecteur de créneau « Calendly » (billets + activités + enfants de pack) —
   ex-<style> inline de catalog/detail.php. */
.act-picker { display:flex; gap:1rem; border:1px solid #e5e8ee; border-radius:12px; padding:1rem; }
.act-cal { flex:0 0 280px; max-width:280px; }
.act-cal__head { display:flex; align-items:center; justify-content:space-between; margin-bottom:.5rem; }
.act-cal__title { font-weight:600; text-transform:capitalize; font-size:.95rem; }
.act-cal__nav { border:none; background:#f2f4f8; border-radius:8px; width:30px; height:30px; cursor:pointer; }
.act-cal__nav:disabled { opacity:.35; cursor:default; }
.act-cal__grid { display:grid; grid-template-columns:repeat(7,1fr); gap:3px; }
.act-cal__dow { text-align:center; font-size:.7rem; color:#8a93a3; text-transform:uppercase; padding:.15rem 0; }
.act-cal__day { aspect-ratio:1; border:none; background:transparent; border-radius:50%;
                font-size:.85rem; color:#c2c8d2; display:flex; align-items:center; justify-content:center; }
.act-cal__day.av { background:#eef2ff; color:var(--bs-primary,#4972C1); font-weight:600; cursor:pointer; }
.act-cal__day.av:hover { background:var(--bs-primary,#4972C1); color:#fff; }
.act-cal__day.sel { background:var(--bs-primary,#4972C1); color:#fff; font-weight:700; }
.act-slots { flex:1 1 auto; min-width:0; border-left:1px solid #eef1f6; padding-left:1rem; }
.act-slots__date { font-weight:600; font-size:.9rem; margin-bottom:.6rem; text-transform:capitalize; }
.act-slots__list { display:flex; flex-direction:column; gap:.45rem; max-height:300px; overflow-y:auto; }
.act-slot { display:flex; justify-content:space-between; align-items:center; width:100%;
            border:1.5px solid var(--bs-primary,#4972C1); background:#fff; color:var(--bs-primary,#4972C1);
            border-radius:8px; padding:.5rem .8rem; font-weight:600; cursor:pointer; transition:background .12s; }
.act-slot:hover { background:#eef2ff; }
.act-slot.active { background:var(--bs-primary,#4972C1); color:#fff; }
.act-slot small { font-weight:400; font-size:.72rem; opacity:.75; }
.act-slot:disabled { border-color:#d4d9e2; color:#a5adba; background:#f7f8fa; cursor:not-allowed; }
@media (max-width: 575.98px) {
    .act-picker { flex-direction:column; }
    .act-cal { flex-basis:auto; max-width:none; }
    .act-slots { border-left:none; padding-left:0; border-top:1px solid #eef1f6; padding-top:.75rem; }
}

/* ── FAQ produit (accordéon natif <details>) ───────────────────────────── */
.shops-faq { display:flex; flex-direction:column; gap:.6rem; max-width:820px; }
.shops-faq__item { border:1px solid #e6e9f0; border-radius:10px; background:#fff; overflow:hidden; }
.shops-faq__q { list-style:none; cursor:pointer; padding:.85rem 1.1rem; font-weight:600;
                display:flex; align-items:center; justify-content:space-between; gap:1rem; }
.shops-faq__q::-webkit-details-marker { display:none; }
.shops-faq__q::after { content:"\f078"; font-family:"Font Awesome 6 Pro","Font Awesome 6 Free","FontAwesome";
                       font-weight:900; font-size:.75rem; color:#9aa2b1; transition:transform .18s; }
.shops-faq__item[open] .shops-faq__q::after { transform:rotate(180deg); }
.shops-faq__item[open] .shops-faq__q { border-bottom:1px solid #eef1f6; }
.shops-faq__q:hover { background:#f7f8fa; }
.shops-faq__a { padding:.85rem 1.1rem; color:#4a5262; font-size:.95rem; line-height:1.55; }

/* ==========================================================================
   SHOPS-MAP — vue carte marketplace (domaines géolocalisés)
   Leaflet + markercluster. Accent = primary du thème (bordeaux awroom…).
   ========================================================================== */
.shops-map-page { --shops-accent: var(--bs-primary, #7a1f3d); }
.shops-map__grid {
    display: grid; grid-template-columns: 1fr minmax(480px, 700px);
    min-height: calc(100vh - 70px);
}
.shops-map__mapcol { position: relative; }
.shops-map__map {
    position: sticky; top: 0; height: calc(100vh - 70px); width: 100%;
    background: #e9edf0; z-index: 0;
}
.shops-map__panel {
    display: flex; flex-direction: column; gap: .9rem;
    padding: 1rem 1.1rem 2rem; background: #fff; border-left: 1px solid #e6e9ed;
}
.shops-map__filters { display: flex; flex-wrap: wrap; gap: .6rem; align-items: end; }
.shops-map__field { flex: 1 1 46%; min-width: 140px; display: flex; flex-direction: column; gap: .2rem; }
.shops-map__field label {
    font-size: .68rem; letter-spacing: .06em; text-transform: uppercase; color: #7a828c; font-weight: 600;
}
.shops-map__search {
    flex: 1 1 100%; background: var(--shops-accent); color: #fff; font-weight: 600;
    border: 0; border-radius: 8px; padding: .6rem 1rem;
}
.shops-map__search:hover { filter: brightness(.94); color: #fff; }
.shops-map__count { font-size: .95rem; color: #384049; padding: .2rem 0; border-bottom: 1px solid #eef1f4; }
.shops-map__count b { color: var(--shops-accent); font-size: 1.15rem; }
.shops-map__count span { color: #7a828c; }
.shops-map__results { display: grid; grid-template-columns: 1fr 1fr 1fr; gap: .6rem; align-items: start; }
.shops-map__empty { grid-column: 1 / -1; }
.shops-map__empty { color: #7a828c; padding: 1.2rem 0; }
.shops-map__all { align-self: flex-start; margin-top: .4rem; font-weight: 600; color: var(--shops-accent); text-decoration: none; }
.shops-map__all:hover { text-decoration: underline; }

/* Carte produit (panneau droit) — VERTICALE sur PC (grille 3 colonnes) */
.shops-map__card {
    display: flex; flex-direction: column; gap: .5rem; padding: .55rem;
    border: 1px solid #e6e9ed; border-radius: 10px; height: 100%;
    text-decoration: none; color: inherit; background: #fff; transition: border-color .15s, box-shadow .15s, transform .12s;
}
.shops-map__card:hover, .shops-map__card.is-hover {
    border-color: var(--shops-accent); box-shadow: 0 6px 18px rgba(0,0,0,.09); transform: translateY(-1px);
}
.shops-map__thumb {
    flex: none; width: 100%; height: 120px; border-radius: 8px; overflow: hidden;
    background: #f1f3f5; display: flex; align-items: center; justify-content: center;
}
.shops-map__thumb img { width: 100%; height: 100%; object-fit: cover; }
.shops-map__ph { font-size: 1.6rem; font-weight: 700; color: #b6bec7; }
.shops-map__info { min-width: 0; display: flex; flex-direction: column; gap: .12rem; }
.shops-map__name { font-weight: 650; line-height: 1.2; }
.shops-map__meta { font-size: .82rem; color: #7a828c; }
.shops-map__count-badge {
    align-self: flex-start; font-size: .72rem; font-weight: 600; color: var(--shops-accent);
    background: color-mix(in srgb, var(--shops-accent) 10%, #fff); border-radius: 99px; padding: .1rem .5rem; margin-top: .1rem;
}
.shops-map__price { font-size: .85rem; color: #384049; margin-top: auto; }
.shops-map__price b { color: var(--shops-accent); }

/* Marqueur (pastille bordeaux avec compteur) */
.shops-pin span {
    position: relative; display: flex; align-items: center; justify-content: center;
    width: 32px; height: 32px; border-radius: 50%;
    background: var(--bs-primary, #7a1f3d); color: #fff; font-weight: 700; font-size: 13px;
    border: 2px solid #fff; box-shadow: 0 2px 5px rgba(0,0,0,.3); font-variant-numeric: tabular-nums;
}
.shops-pin span::after {
    content: ''; position: absolute; bottom: -5px; left: 50%;
    width: 10px; height: 10px; background: var(--bs-primary, #7a1f3d);
    border-right: 2px solid #fff; border-bottom: 2px solid #fff;
    transform: translateX(-50%) rotate(45deg); z-index: -1;
}
.shops-pin.is-active span { transform: scale(1.18); box-shadow: 0 4px 12px rgba(0,0,0,.4); z-index: 2; }
.shops-cluster {
    display: flex; align-items: center; justify-content: center;
    width: 38px; height: 38px; border-radius: 50%;
    background: var(--bs-primary, #7a1f3d); color: #fff; font-weight: 700; font-size: 14px;
    border: 3px solid rgba(255,255,255,.85); box-shadow: 0 2px 8px rgba(0,0,0,.35); font-variant-numeric: tabular-nums;
}
/* Popup */
.shops-pop { min-width: 150px; }
.shops-pop__name { font-weight: 700; margin-bottom: .1rem; }
.shops-pop__meta { font-size: .82rem; color: #7a828c; }
.shops-pop__count { font-size: .8rem; color: var(--bs-primary, #7a1f3d); font-weight: 600; margin: .25rem 0; }
.shops-pop__link { font-weight: 600; color: var(--bs-primary, #7a1f3d); text-decoration: none; }

@media (max-width: 991px) {
    .shops-map__grid { grid-template-columns: 1fr; }
    .shops-map__map { position: relative; height: 46vh; }
    .shops-map__panel { border-left: 0; border-top: 1px solid #e6e9ed; }
    /* Mobile : retour à UNE colonne, carte horizontale (miniature à gauche). */
    .shops-map__results { grid-template-columns: 1fr; }
    .shops-map__card { flex-direction: row; gap: .75rem; }
    .shops-map__thumb { width: 84px; height: 84px; }
}

/* ==========================================================================
   SHOPS-VENDOR — vitrine vendeur marketplace (/catalogue/vendor/{id})
   ========================================================================== */
.shops-vendor-page { --shops-accent: var(--bs-primary, #7a1f3d); }
.shops-vendor__header { position: relative; margin-bottom: .5rem; }
.shops-vendor__banner {
    height: 200px; background-size: cover; background-position: center;
    background-color: #e9edf0;
    background-image: linear-gradient(120deg, color-mix(in srgb, var(--shops-accent) 85%, #000) 0%, var(--shops-accent) 100%);
    border-radius: 0 0 14px 14px;
}
.shops-vendor__id { display: flex; align-items: flex-end; gap: 1.1rem; margin-top: -46px; position: relative; }
.shops-vendor__logo {
    flex: none; width: 104px; height: 104px; border-radius: 18px; overflow: hidden;
    background: #fff; border: 4px solid #fff; box-shadow: 0 6px 20px rgba(0,0,0,.15);
    display: flex; align-items: center; justify-content: center;
}
.shops-vendor__logo img { width: 100%; height: 100%; object-fit: cover; }
/* ── Squelette de grille (application de filtres, gros catalogue) ──────────────
   Affiché par catalog.js pendant le rechargement pour éviter l'impression de gel. */
.shops-skel-card { border: 1px solid var(--bs-border-color, #e6e8ec); border-radius: .6rem; padding: .7rem; height: 100%; }
.shops-skel { background: linear-gradient(90deg, #eceef1 25%, #f6f7f9 37%, #eceef1 63%); background-size: 400% 100%; animation: shops-skel 1.2s ease-in-out infinite; border-radius: .3rem; }
.shops-skel-img { aspect-ratio: 1 / 1; min-height: 160px; margin-bottom: .6rem; }
.shops-skel-line { height: .7rem; margin: .45rem 0; }
.shops-skel-btn { height: 2.1rem; margin-top: .7rem; border-radius: .4rem; }
@keyframes shops-skel { 0% { background-position: 100% 0; } 100% { background-position: 0 0; } }
@media (prefers-reduced-motion: reduce) { .shops-skel { animation: none; } }
/* Variante sombre : uniquement en thème sombre EXPLICITE, ou en préférence système
   sombre SANS choix « clair » — sinon le squelette virait au gris foncé sur une page
   claire (le sélecteur nu :not([data-theme="light"]) s'appliquait par défaut). */
:root[data-theme="dark"] .shops-skel { background: linear-gradient(90deg, #23262b 25%, #2c3036 37%, #23262b 63%); background-size: 400% 100%; }
@media (prefers-color-scheme: dark) {
    :root:not([data-theme="light"]) .shops-skel { background: linear-gradient(90deg, #23262b 25%, #2c3036 37%, #23262b 63%); background-size: 400% 100%; }
}

.shops-vendor__logo span { font-size: 2.4rem; font-weight: 700; color: var(--shops-accent); }
.shops-vendor__title { padding-bottom: .35rem; min-width: 0; }
.shops-vendor__title h1 { margin: 0 0 .2rem; font-size: clamp(1.4rem, 3vw, 2rem); line-height: 1.15; }
.shops-vendor__meta { display: flex; flex-wrap: wrap; gap: .3rem 1.1rem; color: #6b7480; font-size: .9rem; }
.shops-vendor__meta a { color: inherit; text-decoration: none; }
.shops-vendor__meta a:hover { color: var(--shops-accent); }
.shops-vendor__about { max-width: 760px; }
.shops-vendor__desc { color: #3a424c; line-height: 1.6; }

@media (max-width: 575px) {
    .shops-vendor__id { flex-direction: column; align-items: flex-start; gap: .5rem; margin-top: -54px; }
    .shops-vendor__banner { height: 150px; }
}

/* Vitrine vendeur — en-tête SANS bannière (pas de bloc coloré) + dropdown fil d'Ariane */
.shops-vendor__header--flat { margin-bottom: 0; }
.shops-vendor__header--flat .shops-vendor__id { margin-top: 0; padding-top: 1.5rem; align-items: center; }
.shops-vendor__header--flat .shops-vendor__logo { box-shadow: 0 4px 14px rgba(0,0,0,.1); }
.shops-vendor__crumb .dropdown-toggle { color: var(--bs-breadcrumb-item-active-color, #6c757d); cursor: pointer; }
.shops-vendor__crumb .dropdown-toggle:hover { color: var(--shops-accent); }
.shops-vendor__crumb-menu { max-height: 340px; overflow-y: auto; }


/* ==========================================================================
   5. SHOPS-CHECKOUT-CONFIRMATION — page de fin d'achat (après paiement)
   En-tête « Merci » avec pastille check animée, cartes plates arrondies,
   carte parrainage, bloc upsell. Reprend les styles jadis inline dans la vue
   Views/front/checkout/confirmation.php.
   ========================================================================== */

/* Pastille de validation (ex-<style> inline de la vue). */
.confirmation-icon { display: flex; justify-content: center; }
.confirmation-check {
    width: 90px; height: 90px; border-radius: 50%;
    background: #d1e7dd; color: #198754;
    display: flex; align-items: center; justify-content: center;
    font-size: 3rem;
    animation: shops-confirm-pop .4s cubic-bezier(.22, 1.5, .46, 1) both;
}
@keyframes shops-confirm-pop {
    from { transform: scale(.3); opacity: 0; }
    to   { transform: scale(1);  opacity: 1; }
}
@media (prefers-reduced-motion: reduce) {
    .confirmation-check { animation: none; }
}

/* Cartes de la page : plates, arrondies, ombre douce, en-tête discret. */
.shops-checkout-confirmation .card { border-radius: 14px; border: 1px solid #e6e7e9; }
.shops-checkout-confirmation .card-header { border-bottom: 1px solid #eef0f2; padding: .85rem 1rem; }
.shops-checkout-confirmation .list-group-item { border-color: #eef0f2; }
.shops-checkout-confirmation .card-footer { background: #fbfcfd; }

/* Carte de parrainage. */
.shops-referral-card { border-radius: 14px; }
.shops-referral-card #referral-code { letter-spacing: .04em; }

/* Bloc upsell — mise en avant de l'offre exclusive (survol des cartes). */
.shops-upsell-item .card { transition: transform .12s, box-shadow .12s; }
.shops-upsell-item .card:hover { transform: translateY(-3px); box-shadow: 0 .5rem 1.2rem rgba(0, 0, 0, .12) !important; }

/* Carte de position de livraison (Leaflet) : coins bas arrondis cohérents. */
.shops-checkout-confirmation #delivery-map { border-radius: 0 0 14px 14px; }

/* ---------------------------------------------------------------------------
   Modale « Produits similaires » (ouverte depuis les actions d'une carte).
   Calquée sur .shops-gl-modal (liste d'envie) — même voile, même en-tête, même
   fermeture — mais BOÎTE PLUS LARGE : elle affiche une grille de cartes, pas un
   formulaire. Un second motif visuel n'aurait rien apporté.
   --------------------------------------------------------------------------- */
.shops-sim-modal { position:fixed; inset:0; z-index:100002; background:rgba(15,23,42,.5); display:flex; align-items:center; justify-content:center; padding:16px; }
.shops-sim-modal__box { background:#fff; border-radius:14px; width:min(960px,100%); max-height:88vh; display:flex; flex-direction:column; box-shadow:0 20px 60px rgba(0,0,0,.3); }
.shops-sim-modal__head { display:flex; align-items:center; justify-content:space-between; padding:14px 18px; border-bottom:1px solid #eef0f4; font-weight:600; flex:0 0 auto; }
.shops-sim-modal__close { border:0; background:transparent; font-size:1.5rem; line-height:1; color:#94a3b8; cursor:pointer; }
.shops-sim-modal__close:hover { color:#334155; }
/* Seul le CORPS défile : l'en-tête et sa fermeture restent atteignables même
   avec beaucoup de produits. */
.shops-sim-modal__body { padding:16px 18px; overflow:auto; flex:1 1 auto; }
/* Cartes COMPACTES dans la modale « Produits similaires » : la carte native rend une
   image plein format (aspect-ratio 1/1, en inline-style), soit ≈400px de haut — chaque
   carte dépassait 690px et une seule tenait à l'écran. On borne la hauteur d'image et
   on resserre le corps pour densifier la grille (plusieurs produits visibles d'un coup).
   `!important` : l'aspect-ratio est posé en style INLINE sur .card-img-top. */
.shops-sim-modal__body .product-image,
.shops-sim-modal__body .card-img-top { height:170px !important; aspect-ratio:auto !important; }
.shops-sim-modal__body .card-img-top { object-fit:cover; }
.shops-sim-modal__body .card-body { padding:.6rem .75rem; }
.shops-sim-modal__body .card-title { font-size:.9rem; }
.shops-sim-modal__body .product__specs,
.shops-sim-modal__body .product__axes { margin-bottom:.35rem !important; }

/* -- Alternatives sous l'alerte de stock ------------------------------
   Trois produits achetables tout de suite, proposés sous le formulaire
   « prévenez-moi ». Volontairement discret : le formulaire reste
   l'action principale, la liste n'est qu'une sortie de secours. */
.shops-sa-alt { border-top: 1px solid var(--aw-border, #e5e7eb); padding: .85rem 1rem 1rem; }
.shops-sa-alt__head { font-size: .78rem; font-weight: 600; text-transform: uppercase; letter-spacing: .04em; color: var(--aw-muted, #6b7280); margin-bottom: .5rem; }
.shops-sa-alt__list li + li { margin-top: .35rem; }
.shops-sa-alt__item { display: flex; align-items: center; gap: .7rem; padding: .4rem; border-radius: 8px; text-decoration: none; color: inherit; transition: background-color .15s ease; }
.shops-sa-alt__item:hover,
.shops-sa-alt__item:focus-visible { background: var(--aw-bg-soft, #f6f7f9); }
.shops-sa-alt__item img,
.shops-sa-alt__ph { width: 48px; height: 48px; flex: 0 0 48px; border-radius: 6px; object-fit: cover; }
.shops-sa-alt__ph { display: flex; align-items: center; justify-content: center; background: var(--aw-bg-soft, #f1f3f5); color: var(--aw-muted, #9ca3af); }
.shops-sa-alt__txt { display: flex; flex-direction: column; min-width: 0; flex: 1 1 auto; }
.shops-sa-alt__title { font-size: .875rem; line-height: 1.25; overflow: hidden; text-overflow: ellipsis; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; }
.shops-sa-alt__price { font-size: .82rem; font-weight: 700; margin-top: .1rem; }
.shops-sa-alt__chev { font-size: .75rem; color: var(--aw-muted, #9ca3af); flex: 0 0 auto; }

/* =====================================================================
   GABARITS DE MODULE — boutique
   ---------------------------------------------------------------------
   Habillage des composants propres à la boutique rendus par
   ShopsTemplateRegistrar dans un gabarit dessiné au page-builder
   (prix, pastille promo, disponibilité, note, déclinaisons, livraison).

   Portée : uniquement des classes `shops-*` neuves. Aucune règle
   existante n'est modifiée, et rien ici ne peut atteindre une carte
   d'actualité — la famille Blogs ne produit aucune de ces classes.
   ===================================================================== */

/* -- Carte produit ---------------------------------------------------- */
.shops-card .shops-card__brand { margin: 0 0 .15rem; font-size: .8rem; text-transform: uppercase; letter-spacing: .04em; color: var(--aw-muted, #6b7280); }
.shops-card .shops-card__title-link { text-decoration: none; color: inherit; }
.shops-card .shops-card__title-link:hover .module-card__title { text-decoration: underline; }
.shops-card__media { position: relative; }
.shops-card__prices { display: flex; align-items: baseline; gap: .5rem; flex-wrap: wrap; margin: .35rem 0 .5rem; }
.shops-card__price { font-size: 1.15rem; font-weight: 700; color: var(--aw-text, #111827); }
.shops-card__price-old { font-size: .95rem; color: var(--aw-muted, #9ca3af); text-decoration: line-through; }
/* Prix barré vide : sans ceci le `gap` laisserait un blanc à droite du prix. */
.shops-card__price-old:empty { display: none; }
/* Prix en DOUBLE sur la carte dessinée : le bloc d'achat (buy_block) affiche déjà le
   prix, VIVANT (il suit la déclinaison choisie via catalog.js). Quand le gabarit
   embarque aussi ce bloc, on masque le prix STATIQUE de la carte — on n'en garde
   qu'un, et c'est celui qui se met à jour. Ne s'applique QUE si un buy_block existe :
   une carte purement vitrine (sans achat) garde son prix. */
.shops-card:has(.aw-composant--buy_block) .shops-card__prices,
.module-card:has(.aw-composant--buy_block) .shops-card__prices { display: none; }
/* Ligne de statut stock (« En stock » / « Épuisé ») redondante SUR LA CARTE : le
   badge « Rupture » signale déjà l'indisponibilité, et le bloc d'achat (panier / « Voir
   le produit ») porte le reste. Masquée sur les cartes du catalogue ; la fiche produit
   (hors .module-card / .shops-card) garde son indicateur de stock. */
.module-card .aw-composant--stock,
.shops-card .aw-composant--stock { display: none; }
.shops-card--min .module-card__body { padding: .75rem 1rem 1rem; }

/* Pastilles du média (promo, nouveauté, rupture) : ancrées sur le MÉDIA, jamais
   sur la carte entière — une carte horizontale a son média à gauche, les pastilles
   doivent suivre.

   Elles sont empilées par un conteneur en colonne plutôt que superposées à la même
   coordonnée : un produit neuf ET en promo affichait sinon deux pastilles l'une
   sur l'autre. Chacune reste un composant à part, donc désactivable seule ; le
   conteneur n'existe que pour les ranger. */
.shops-card__media { position: relative; }
.shops-card__badges {
    position: absolute; top: .6rem; left: .6rem; z-index: 2;
    display: flex; flex-direction: column; align-items: flex-start; gap: .3rem;
    pointer-events: none; /* ne vole pas le clic du lien qui couvre l'image */
}
.shops-card__badges .aw-composant { padding: 0; }
/* Un composant vide (hors promo, produit ancien, produit en stock) ne doit pas
   creuser un intervalle dans la pile. */
.shops-card__badges .aw-composant:empty { display: none; }

/* Repli : pastille promo posée SEULE dans le média (gabarit d'avant la pile). */
.shops-card__media > .aw-composant--promo_badge { position: absolute; top: .6rem; left: .6rem; z-index: 2; padding: 0; }

.shops-badge { display: inline-block; padding: .2rem .5rem; border-radius: 6px; font-size: .78rem; font-weight: 700; line-height: 1.3; }
.shops-badge--promo { background: var(--color-1, #d85575); color: #fff; }

/* -- Disponibilité ---------------------------------------------------- */
/* La couleur ne porte JAMAIS l'information seule (RGAA 3.1) : le texte du
   composant dit « En stock » / « Bientôt épuisé » / « Épuisé ». */
.shops-stock { display: inline-flex; align-items: center; gap: .35rem; font-size: .85rem; font-weight: 600; }
.shops-stock::before { content: ""; width: .5rem; height: .5rem; border-radius: 50%; background: currentColor; flex: 0 0 auto; }
.shops-stock--in  { color: #15803d; }
.shops-stock--low { color: #b45309; }
.shops-stock--out { color: #b91c1c; }

/* -- Note ------------------------------------------------------------- */
/* Les étoiles sont décoratives : la valeur chiffrée est portée par
   l'aria-label du conteneur (cf. ShopsTemplateRegistrar::starsHtml). */
.shops-rating { display: inline-flex; align-items: center; gap: .1rem; color: #f59e0b; font-size: .9rem; }

/* -- Fiche produit ---------------------------------------------------- */
.shops-detail__brand { margin: 0 0 .25rem; font-size: .85rem; text-transform: uppercase; letter-spacing: .04em; color: var(--aw-muted, #6b7280); }
.shops-detail__title { margin: 0 0 .5rem; }
.shops-detail__ref { margin: 0 0 .75rem; font-size: .85rem; color: var(--aw-muted, #6b7280); }
.shops-detail__ref:empty { display: none; }
.shops-detail__prices { display: flex; align-items: baseline; gap: .75rem; flex-wrap: wrap; margin: .75rem 0; }
.shops-detail__price { font-size: 1.75rem; font-weight: 700; }
.shops-detail__price-old { font-size: 1.1rem; color: var(--aw-muted, #9ca3af); text-decoration: line-through; }
.shops-detail__price-old:empty { display: none; }
.shops-detail__img { border-radius: 12px; }

/* Galerie : grille de vignettes, adaptative sans point de rupture. */
.shops-gallery { list-style: none; margin: .75rem 0 0; padding: 0; display: grid; grid-template-columns: repeat(auto-fill, minmax(90px, 1fr)); gap: .5rem; }
.shops-gallery img { width: 100%; aspect-ratio: 1/1; object-fit: cover; border-radius: 8px; display: block; }
/* Produit sans image : placeholder sobre à ratio carré, teinte charte (--color-1). */
.shops-gallery--empty { display: flex; align-items: center; justify-content: center; width: 100%; aspect-ratio: 1 / 1; margin: 0; padding: 0; background: #f5f6f8; border: 1px solid #e6e8ec; border-radius: 14px; color: var(--color-1, #d85575); }
.shops-gallery--empty i { font-size: clamp(2.5rem, 7vw, 3.75rem); opacity: .3; line-height: 1; }

/* Déclinaisons : une ligne par variante (référence à gauche, prix à droite).
   Liste sans puces — la puce native doublait le cadre de chaque ligne. */
.shops-variants { list-style: none; margin: .75rem 0; padding: 0; display: flex; flex-direction: column; gap: .4rem; }
.shops-variant { display: flex; justify-content: space-between; align-items: baseline; gap: 1rem; padding: .5rem .75rem; border: 1px solid var(--aw-border, rgba(0,0,0,.12)); border-radius: 8px; }
/* Variante épuisée : l'atténuation ne dit rien à qui ne perçoit pas la couleur —
   la disponibilité reste énoncée en toutes lettres par le composant Stock. */
.shops-variant.is-out { opacity: .55; }
.shops-variant__ref { color: var(--aw-muted, #6b7280); font-size: .85rem; }
.shops-variant__ref:empty { display: none; }
.shops-variant__price { font-weight: 600; white-space: nowrap; margin-left: auto; }

/* Caractéristiques : deux colonnes libellé / valeur qui s'empilent en mobile. */
.shops-attrs { display: grid; grid-template-columns: minmax(120px, max-content) 1fr; gap: .35rem 1rem; margin: 1rem 0 0; }
.shops-attrs dt { font-weight: 600; color: var(--aw-muted, #4b5563); margin: 0; }
.shops-attrs dd { margin: 0; }
@media (max-width: 575.98px) {
    .shops-attrs { grid-template-columns: 1fr; gap: .1rem .5rem; }
    .shops-attrs dd { margin-bottom: .5rem; }
}

/* Blocs de la fiche produit (gabarit page-builder) : cartes homogènes, avec titre
   + icône, masquées automatiquement quand le composant qu'elles portent est vide
   (le moteur laisse un .aw-composant vide) → jamais de carte « fantôme ». */
.shops-tpl-block { border: 1px solid var(--aw-border, #e6e8ee); border-radius: 14px; padding: 1rem 1.25rem; margin: 0 0 1rem; background: var(--aw-card, #fff); }
.shops-tpl-block__h { font-weight: 600; font-size: 1rem; margin: 0 0 .65rem; display: flex; align-items: center; gap: .5rem; }
.shops-tpl-block__h i { color: var(--btn-2-bg, #143F6F); width: 1.1rem; text-align: center; }
.shops-tpl-block > .aw-composant { margin: 0; }
.shops-tpl-block:has(> .aw-composant:empty) { display: none; }
.shops-tpl-block:has(> .shops-detail__content:empty) { display: none; }
/* Le contenu est un jeton TRANSPARENT : le moteur garde son TextElement, si bien
   qu'un produit sans description laisse un `<div class="shops-detail__content">`
   vide — pas une enveloppe `:empty`, d'où la règle ci-dessus qui le vise
   nommément. Depuis que `{content}` est posé en COMPOSANT (interrupteur
   « Composant actif »), ce div n'est plus enfant DIRECT du bloc : l'enveloppe
   s'intercale, et la carte « Description » réapparaissait vide. */
.shops-tpl-block:has(> .aw-composant > .shops-detail__content:empty) { display: none; }
/* Carte fantôme des avis : le bloc « Avis clients » enveloppe une `<section
   d-none>` que product.js révèle SEULEMENT s'il y a des avis. La section existe
   donc toujours — ni `:empty`, ni vide au sens des règles ci-dessus — et sans
   avis il restait un cadre bordé de 34 px contenant du vide. On masque le bloc
   tant que son unique enfant est caché ; product.js retirant `d-none`, `:has`
   réévalue et la carte réapparaît d'elle-même dès le premier avis. */
.shops-tpl-block:has(> .aw-composant > .d-none:only-child) { display: none; }
.shops-tpl-block--plain { border: 0; padding: 0; background: none; }
/* Le sélecteur de déclinaisons hérite du bloc → plus de marge propre en double. */
.shops-tpl-block .product-variants { margin: 0; }

/* ── Bloc d'ACHAT tout-en-un (sale_block) : même cadre de carte que les autres
      blocs, en gardant tout son contenu (réf, note, prix, dispo, déclinaisons,
      achat, offrir, tarifs, caution/taxe/poids). ── */
.shops-sale-block { display: flex; flex-direction: column; gap: 1rem; border: 1px solid var(--aw-border, #e6e8ee); border-radius: 12px; padding: 1.15rem 1.35rem; margin: 0 0 1rem; background: var(--aw-card, #fff); }
.shops-sale-block > * { margin-top: 0; margin-bottom: 0; }
.shops-sale-block__ref { letter-spacing: .01em; }
.shops-sale-block__mentions { display: flex; flex-direction: column; gap: .4rem; margin-top: .35rem; padding-top: .85rem; border-top: 1px solid rgba(0, 0, 0, .07); font-size: .9rem; color: var(--aw-muted, #667085); }

/* ── Équipements & règles d'hébergement (composant {amenities}) ── */
.shops-amenities { display: flex; flex-direction: column; gap: 1rem; }
.shops-amenities__grp { display: flex; flex-direction: column; gap: .5rem; }
.shops-amenities__h { font-weight: 600; font-size: 1rem; margin: 0; }
.shops-amenities-grid { display: flex; flex-wrap: wrap; gap: .5rem .9rem; }
.shops-amenity { display: inline-flex; align-items: center; gap: .45rem; font-size: .9rem; color: #3f4652; }
.shops-amenity i { color: var(--btn-2-bg, #143F6F); width: 1.1rem; text-align: center; }
.shops-amenity--rule i { color: #b45309; }
.shops-amenities__note { margin: .25rem 0 0; font-size: .85rem; color: #667085; font-style: italic; }
/* Placeholder muet dans un bloc (éditeur only) : le titre est déjà au-dessus. */
.aw-comp-ph--muted { color: var(--aw-muted, #98a2b3); font-style: italic; font-size: .85rem; }

/* ── Carte SANS mon titre : le composant affiche déjà le sien (tarifs, avis, vidéo). */
.shops-tpl-block--self .shops-tiers caption { caption-side: top; text-align: left; font-weight: 600; font-size: 1rem; margin: 0 0 .65rem; }
.shops-tpl-block--self > .aw-composant > *:first-child,
.shops-tpl-block--self h2 { margin-top: 0; }

/* ── Notes d'achat (sous le bouton) & méta de pied : lignes discrètes, pas de carte. */
.shops-detail__notes { display: flex; flex-direction: column; gap: .4rem; margin-top: 1rem; }
.shops-detail__notes > .aw-composant { color: var(--aw-muted, #667085); font-size: .9rem; }
.shops-detail__meta { display: flex; flex-wrap: wrap; gap: .3rem 1.75rem; margin-top: 1.25rem; padding-top: 1rem; border-top: 1px solid var(--aw-border, #e6e8ee); }
.shops-detail__meta > .aw-composant { color: var(--aw-muted, #667085); font-size: .85rem; }
.shops-detail__notes > .aw-composant:empty,
.shops-detail__meta  > .aw-composant:empty { display: none; }
.shops-detail__notes i, .shops-detail__meta i { color: var(--btn-2-bg, #143F6F); width: 1.05rem; text-align: center; margin-right: .35rem; }

/* ── Aperçu réaliste dans l'ÉDITEUR (remplacé par le vrai contenu sur le front). */
.aw-comp-ph--preview { color: inherit; font-style: normal; font-weight: 400; }
.aw-comp-ph--preview .shops-stars { color: #f5a524; letter-spacing: 1px; }
.aw-comp-ph--preview .shops-chip { display: inline-block; background: #eef1f6; color: #334155; border-radius: 999px; padding: .12rem .55rem; font-size: .75rem; }
.aw-comp-ph--preview .shops-crumb { color: #667085; font-size: .85rem; }
.aw-comp-ph--preview .shops-crumb span { margin: 0 .3rem; color: #c2c8d2; }
.aw-comp-ph--preview .shops-video-ph { aspect-ratio: 16/9; background: #1e293b; border-radius: 10px; display: flex; align-items: center; justify-content: center; }
.aw-comp-ph--preview .shops-video-ph i { color: #fff; font-size: 2rem; opacity: .85; }
.aw-comp-ph--preview .shops-reviews-ph b { color: #111; }

/* ── Tarifs dégressifs interactifs (fiche native + gabarit) : lignes cliquables,
   surbrillance du palier appliqué selon la quantité, colonne « Économie ». */
.product-tiers .shops-tiers-table { max-width: 420px; }
.product-tiers .js-tier-row { cursor: pointer; transition: background .12s ease; }
.product-tiers .js-tier-row:hover { background: var(--aw-hover, #f1f5fb); }
.product-tiers .js-tier-row.table-active { background: rgba(20, 63, 111, .10); box-shadow: inset 3px 0 0 var(--btn-2-bg, #143F6F); }
.product-tiers .js-tier-row:focus-visible { outline: 2px solid var(--btn-2-bg, #143F6F); outline-offset: -2px; }
/* Bouton « Offrir en bon cadeau » : espace au-dessus (bouton panier) ET en
   dessous, pour ne pas coller au bloc « Tarifs dégressifs » qui le suit. */
.shops-detail__gift { margin: .6rem 0 1.25rem; }
.shops-detail__gift > .aw-composant:empty { display: none; }
/* Si le bouton cadeau est absent (produit sans bon cadeau), pas de trou. */
.shops-detail__gift:has(> .aw-composant:empty) { margin: 0; }

/* Récapitulatif ligne : montant total + remise globale, au-dessus du bouton. */
.shops-line-summary { border-top: 1px solid var(--aw-border, #e6e8ee); padding-top: .6rem; }
.shops-line-summary__total { font-size: 1.15rem; }

/* Livraison. */
.shops-delivery { display: flex; flex-direction: column; gap: .3rem; margin-top: .75rem; font-size: .9rem; color: var(--aw-muted, #4b5563); }

/* -- Vendeur (marketplace) -------------------------------------------- */
.shops-seller { display: inline-flex; align-items: center; gap: .5rem; font-size: .9rem; color: var(--aw-muted, #4b5563); }
.shops-seller__logo { border-radius: 50%; object-fit: cover; flex: 0 0 auto; }
/* Carte vendeur enrichie (logo + nom cliquable + note + ville). */
.shops-seller--card { display: flex; align-items: center; gap: .75rem; border: 1px solid var(--aw-border, #e6e8ee); border-radius: 12px; padding: .6rem .8rem; background: var(--aw-card, #fff); }
.shops-seller--card .shops-seller__logo { width: 44px; height: 44px; }
.shops-seller__logo--ph { display: inline-flex; align-items: center; justify-content: center; background: var(--aw-hover, #f1f5fb); color: var(--btn-2-bg, #143F6F); font-size: 1.1rem; }
.shops-seller__body { flex: 1 1 auto; min-width: 0; }
.shops-seller__top { font-size: .95rem; color: var(--aw-muted, #667085); }
.shops-seller__by { font-size: .78rem; text-transform: uppercase; letter-spacing: .03em; }
.shops-seller__name { font-weight: 700; color: var(--aw-text, #1a1a1a); text-decoration: none; }
.shops-seller__name:hover { color: var(--color-1, #d85575); text-decoration: underline; }
.shops-seller__meta { display: flex; align-items: center; gap: .75rem; margin-top: .2rem; font-size: .82rem; color: var(--aw-muted, #667085); flex-wrap: wrap; }
.shops-seller__rating { display: inline-flex; align-items: center; gap: .3rem; }
.shops-seller__rating .shops-stars, .shops-seller__rating .shops-rating,
.shops-seller__rating .shops-rating i, .shops-seller__rating i { color: #f5a524; font-size: .8rem; }
.shops-seller__note { font-weight: 700; color: var(--aw-text, #1a1a1a); }
.shops-seller__city { display: inline-flex; align-items: center; gap: .25rem; }
.shops-seller__go { flex: 0 0 auto; width: 34px; height: 34px; display: inline-flex; align-items: center; justify-content: center; border-radius: 50%; background: var(--aw-hover, #f1f5fb); color: var(--btn-2-bg, #143F6F); text-decoration: none; transition: background .12s; }
.shops-seller__go:hover { background: var(--btn-2-bg, #143F6F); color: #fff; }

/* -- Disponibilité par dépôt ------------------------------------------ */
.shops-depots { list-style: none; margin: .5rem 0; padding: 0; display: flex; flex-direction: column; gap: .25rem; font-size: .9rem; }
.shops-depot { display: flex; justify-content: space-between; gap: 1rem; padding: .3rem 0; border-bottom: 1px dashed var(--aw-border, rgba(0,0,0,.1)); }
.shops-depot:last-child { border-bottom: 0; }
.shops-depot__qty { white-space: nowrap; font-weight: 600; }
/* Dépôt vide : l'atténuation accompagne le texte « Épuisé », elle ne le remplace pas. */
.shops-depot.is-out { opacity: .6; }

/* -- Tarifs dégressifs ------------------------------------------------- */
.shops-tiers { width: 100%; margin: .75rem 0; border-collapse: collapse; font-size: .9rem; }
.shops-tiers caption { text-align: left; font-weight: 600; padding-bottom: .35rem; color: var(--aw-text, #111827); }
.shops-tiers th, .shops-tiers td { padding: .35rem .5rem; border: 1px solid var(--aw-border, rgba(0,0,0,.12)); text-align: left; }
.shops-tiers thead th { background: var(--aw-surface, #f8fafc); font-weight: 600; }
.shops-tiers tbody th { font-weight: 500; }

/* -- Mentions d'une ligne (caution, poids, fournisseur, annulation…) --- */
.shops-mention { margin: .25rem 0; font-size: .9rem; color: var(--aw-muted, #4b5563); display: flex; align-items: baseline; gap: .4rem; }
.shops-mention--cancel { font-style: italic; }

/* -- Stickers et badges ------------------------------------------------ */
.shops-stickers { display: inline-flex; gap: .35rem; align-items: center; }
.shops-stickers img { max-width: 64px; max-height: 64px; object-fit: contain; filter: drop-shadow(0 1px 3px rgba(0,0,0,.3)); }
.shops-badge--new { background: var(--btn-2-bg, #143F6F); color: #fff; }
/* Rupture : gris neutre. Le rouge est déjà pris par la promotion, et une rupture
   n'est pas une alerte — c'est un état. */
.shops-badge--oos { background: #6b7280; color: #fff; }

/* -- Température ------------------------------------------------------- */
/* Rien pour « sec » : seuls le frais et le surgelé sont une information utile. */
.shops-temp { display: inline-flex; align-items: center; gap: .3rem; padding: .15rem .5rem; border-radius: 6px; font-size: .8rem; font-weight: 600; }
.shops-temp--fresh  { background: #e0f2fe; color: #075985; }
.shops-temp--frozen { background: #dbeafe; color: #1e3a8a; }

/* -- Documents --------------------------------------------------------- */
.shops-files { list-style: none; margin: .5rem 0 0; padding: 0; display: flex; flex-direction: column; gap: .3rem; }
.shops-files a { text-decoration: none; }
.shops-files a:hover, .shops-files a:focus-visible { text-decoration: underline; }
.shops-file__meta { color: var(--aw-muted, #6b7280); font-size: .85em; }

/* -- Champs personnalisés (réutilise la grille des caractéristiques) ---- */
.shops-fields { margin-top: .75rem; }

/* Bloc marque / fournisseur (logo + nom) — jetons {brand_block} / {supplier_block}. */
.shops-brand-block{display:inline-flex;align-items:center;gap:.6rem;margin:.5rem 0;line-height:1.2;}
.shops-brand-block__logo{max-height:46px;max-width:130px;width:auto;height:auto;object-fit:contain;}
.shops-brand-block__name{font-weight:600;}
.shops-brand-block__link{display:inline-flex;align-items:center;gap:.6rem;color:inherit;text-decoration:none;}
.shops-brand-block__link:hover{text-decoration:underline;}

/* ==========================================================================
   PAGE PANIER (/catalogue/cart) — habillage
   --------------------------------------------------------------------------
   PORTÉE. Tout est sous `.page-cart`, jamais sur `.shops-cart-*` nu : le tiroir
   latéral (#shops-cartOffcanvas) partage le même gabarit de ligne, rendu par la
   MÊME fonction `_renderProduct()` de cart.js. Une règle non scopée le
   repeindrait au passage, dans un cadre deux fois plus étroit.

   AUCUN CROCHET TOUCHÉ. Les sélecteurs réutilisent ce que cart.js écrit déjà
   (`.shops-cart-item`, `.shops-cart-qty`, `data-remove`, `data-option-remove`…) :
   rien n'est ajouté ni renommé côté script.

   POURQUOI DES `!important`. Les utilitaires Bootstrap 5 (`bg-light`, `p-2`,
   `mb-2`, `border`, `rounded-3`, `text-danger`, `opacity-75`…) sont eux-mêmes
   déclarés `!important` : la spécificité seule ne les bat pas. Chaque
   `!important` ci-dessous vise EXACTEMENT une propriété posée par un utilitaire,
   et rien d'autre. Les tailles fixées en style inline par le script (la vignette
   de 72 px) sont laissées telles quelles — le placeholder s'aligne sur elles.
   ========================================================================== */

/* -- Ligne article : carte blanche au lieu du pavé gris ------------------- */
.page-cart .shops-cart-item {
    background: #fff !important;                    /* .bg-light */
    border-color: rgba(0, 0, 0, .08) !important;    /* .border */
    border-radius: 14px !important;                 /* .rounded-3 */
    margin-bottom: .75rem !important;               /* .mb-2 */
    overflow: hidden;
    transition: box-shadow .18s ease, border-color .18s ease;
}
.page-cart .shops-cart-item:hover {
    border-color: rgba(0, 0, 0, .14) !important;
    box-shadow: 0 2px 10px rgba(16, 24, 40, .06);
}

/* Ligne « comprise dans un pack » ou offerte : mise en retrait par le fond et le
   trait, plus par l'opacité globale — celle-ci délavait aussi le prix. */
.page-cart .shops-cart-item--pack-child {
    opacity: 1 !important;                          /* .opacity-75 */
    background: #fbfbfd !important;
    border-style: dashed !important;
}

/* Corps de la ligne : de l'air. `p-2` (8 px) collait le texte au bord. */
.page-cart .shops-cart-item > div:first-child {
    padding: 1rem !important;                       /* .p-2 */
    gap: 1rem !important;                           /* .gap-3 */
}

/* -- Vignette ------------------------------------------------------------ */
.page-cart .shops-cart-item-image img {
    border: 1px solid rgba(0, 0, 0, .06);
}

/* Produit SANS visuel : on réserve la même colonne, sinon les lignes avec et
   sans image ne s'alignent pas et le titre saute d'un cran vers la gauche.
   Dimensions et marge calées sur celles que le script pose sur la vraie
   vignette (72 px, `.ms-2`, `.rounded`). Le `:has()` ne cible que les lignes
   dépourvues de vignette ; là où il n'est pas supporté, la règle entière est
   ignorée et on retrouve l'affichage d'avant. */
.page-cart .shops-cart-item > div:first-child:not(:has(.shops-cart-item-image))::before {
    content: "";
    flex: 0 0 auto;
    width: 72px;
    height: 72px;
    margin-left: .5rem;
    border-radius: .375rem;
    border: 1px solid rgba(0, 0, 0, .06);
    background: #f4f5f9 url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23aab2c0' stroke-width='1.4' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='3' y='3' width='18' height='18' rx='2'/%3E%3Ccircle cx='8.5' cy='8.5' r='1.5'/%3E%3Cpath d='M21 15l-5-5L5 21'/%3E%3C/svg%3E") center / 26px no-repeat;
}

/* -- Titre --------------------------------------------------------------- */
.page-cart .shops-cart-item-title {
    font-size: 1rem;
    line-height: 1.35;
}
.page-cart .shops-cart-item-title a:hover,
.page-cart .shops-cart-item-title a:focus-visible {
    text-decoration: underline;
}

/* -- Prix ---------------------------------------------------------------- */
/* Le prix payé porte l'accent, le prix barré passe en gris. C'était l'inverse :
   l'ancien prix, en rouge, attirait l'œil AVANT le montant réellement dû. */
.page-cart .shops-cart-item-price {
    font-size: 1.1rem;
    line-height: 1.3;
}
.page-cart .shops-cart-item-price-old {
    color: #9aa3b2 !important;                      /* .text-danger */
}

/* -- Sélecteur de quantité : trois contrôles → un seul bloc -------------- */
.page-cart .shops-cart-qty {
    gap: 0 !important;                              /* .gap-1 */
    width: fit-content;                             /* sinon .d-flex l'étire */
    border: 1px solid rgba(0, 0, 0, .12);
    border-radius: 999px;
    overflow: hidden;
    background: #fff;
}
.page-cart .shops-cart-qty .btn {
    border: 0;
    border-radius: 0;
    background: transparent;
    color: #4b5563;
    width: 2.1rem;
    height: 2.1rem;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-size: 1rem;
    line-height: 1;
    padding: 0;
}
.page-cart .shops-cart-qty .btn:hover:not(:disabled),
.page-cart .shops-cart-qty .btn:focus-visible:not(:disabled) {
    background: rgba(0, 0, 0, .06);
    color: #111827;
}
.page-cart .shops-cart-qty .btn:disabled {
    opacity: .3;
}
.page-cart .shops-cart-qty .form-control {
    border: 0;
    border-radius: 0;
    background: transparent;
    box-shadow: none;
    height: 2.1rem;
    padding: 0;
    font-weight: 600;
}
/* Les flèches natives du <input type="number"> doublaient les boutons − / +. */
.page-cart .shops-cart-qty .form-control::-webkit-outer-spin-button,
.page-cart .shops-cart-qty .form-control::-webkit-inner-spin-button {
    -webkit-appearance: none;
    margin: 0;
}
.page-cart .shops-cart-qty .form-control[type="number"] {
    -moz-appearance: textfield;
    appearance: textfield;
}

/* -- Suppression : cible de 32 px au lieu d'une icône de 12 -------------- */
.page-cart .shops-cart-item [data-remove] {
    width: 2rem;
    height: 2rem;
    border-radius: 50%;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    color: #9aa3b2 !important;                      /* .text-danger */
    transition: background-color .15s ease, color .15s ease;
}
.page-cart .shops-cart-item [data-remove]:hover,
.page-cart .shops-cart-item [data-remove]:focus-visible {
    background: #fee2e2;
    color: #dc2626 !important;
}

/* -- Options et champs personnalisés : encart rattaché à l'article ------- */
/* Ces blocs étaient des bandeaux gris pleine largeur, visuellement détachés : la
   ventilation « Prix de base / Éco-participation / Garantie » se lisait comme un
   article de plus. Fond légèrement teinté = sous-partie de la ligne au-dessus. */
.page-cart .shops-cart-options,
.page-cart .shops-cart-custom-fields {
    background: #fafbfc;
    border-top-color: rgba(0, 0, 0, .06) !important;    /* .border-top */
    padding: .5rem 1rem .7rem !important;               /* .px-2 .pt-1 .pb-2 */
}
.page-cart .shops-cart-options [data-option-remove] {
    color: #9aa3b2 !important;                      /* .text-danger */
}
.page-cart .shops-cart-options [data-option-remove]:hover {
    color: #dc2626 !important;
}

/* -- Colonne de droite --------------------------------------------------- */
/* Le bloc code promo reprend le dessin de la carte récapitulative : ils se
   suivent, ils ne peuvent pas porter deux habillages différents. */
.page-cart #coupon-section {
    background: #fff !important;                    /* .bg-light */
    border: 1px solid rgba(0, 0, 0, .08);
    border-radius: 14px !important;                 /* .rounded */
    padding: 1rem 1.25rem !important;               /* .p-3 */
}
.page-cart #coupon-section .form-control,
.page-cart #coupon-section .btn {
    height: 2.35rem;
}

.page-cart .card {
    border-radius: 14px;
}
.page-cart .shops-cart-summary,
.page-cart .card-header,
.page-cart .card-footer {
    padding-left: 1.25rem;
    padding-right: 1.25rem;
}
.page-cart .card-header {
    font-size: 1rem;
    padding-top: 1rem;
    padding-bottom: 1rem;
    border-bottom: 1px solid rgba(0, 0, 0, .06);
}
.page-cart .shops-cart-summary hr {
    margin: .9rem 0;
    opacity: .12;
}
.page-cart .shops-cart-summary-line {
    align-items: baseline;
}
.page-cart .card-footer .btn-lg {
    padding-top: .75rem;
    padding-bottom: .75rem;
    font-weight: 600;
}

/* -- Panier vide --------------------------------------------------------- */
.page-cart .shops-cart-empty {
    background: #fff;
    border: 1px dashed rgba(0, 0, 0, .12);
    border-radius: 16px;
}
.page-cart .shops-cart-empty .fa-cart-shopping {
    opacity: .35;
}

/* -- Couche de marque : un peu de vie, sans casser la lisibilité ---------- */
/* Alias LOCAUX (jamais en :root) dérivés de la charte : la couleur d'accent
   suit le bouton principal de la boutique (btn-1 / color-1). Le texte des
   montants NE prend PAS l'accent (un orange clair échoue au contraste) : la
   couleur ne sert qu'aux fonds tènus et aux détails décoratifs. */
.page-cart {
    --cart-accent:      var(--btn-1-bg, var(--color-1, #F8B11F));
    --cart-accent-soft: color-mix(in srgb, var(--cart-accent) 9%,  var(--card-bg, #fff));
    --cart-accent-line: color-mix(in srgb, var(--cart-accent) 32%, var(--card-bg, #fff));
}
/* Icône du titre de page : touche de couleur de la boutique. */
.page-cart h1 .fa-cart-shopping { color: var(--cart-accent) !important; }
/* Survol de carte : le bord se teinte à la couleur de la boutique + ombre douce. */
.page-cart .shops-cart-item:hover {
    border-color: var(--cart-accent-line) !important;
    box-shadow: 0 4px 16px color-mix(in srgb, var(--cart-accent) 14%, transparent);
}
/* Ligne TOTAL : bandeau teinté qui la détache du reste du récap. Le montant
   reste sombre (contraste), le bandeau apporte la couleur. */
.page-cart .shops-cart-summary .shops-cart-summary-line.fw-bold {
    background: var(--cart-accent-soft);
    border: 1px solid var(--cart-accent-line);
    border-radius: 10px;
    padding: .65rem .8rem;
    margin-top: .2rem;
}
.page-cart .shops-cart-summary hr { margin-bottom: .5rem; }
/* Entête du récap : liseré d'accent discret sous le titre. */
.page-cart .shops-cart-summary-header-accent { color: var(--cart-accent); }

/* -- Téléphone ----------------------------------------------------------- */
/* La vignette garde ses 72 px (posés en style inline par le script) ; seul le
   rembourrage se resserre, sinon le titre n'a plus de place à côté. */
@media (max-width: 575.98px) {
    .page-cart .shops-cart-item > div:first-child {
        padding: .75rem !important;
        gap: .75rem !important;
    }
    .page-cart .shops-cart-item-price {
        font-size: 1rem;
    }
}

/* ==========================================================================
   TIROIR PANIER (#shops-cartOffcanvas) — MÊME langage visuel que la page,
   calibré pour le cadre plus étroit du tiroir. Bloc SÉPARÉ à dessein (cf. la
   portée du bloc page ci-dessus) : paddings plus serrés, vignette conservée.
   ========================================================================== */
/* --- Tiroir panier : largeur ------------------------------------------------
   720 px sur grand écran, PLEIN ÉCRAN sous 992 px. Entre les deux, il couvrait
   94 % d'une tablette de 768 px : ni panneau latéral, ni plein écran — le
   fragment de page laissé derrière ne servait à rien.
   La valeur vivait en style EN LIGNE sur le div (vue _offcanvas.php), ce qui
   gagnait sur toute feuille et interdisait le moindre point de rupture. */
#shops-cartOffcanvas { width: min(720px, 100vw); max-width: 100vw; }
@media (max-width: 991.98px) {
    #shops-cartOffcanvas { width: 100vw; }
}

/* --- Tiroir panier : en-tête et paliers de livraison sur petit écran ------- */
@media (max-width: 575.98px) {
    /* Le titre passait sur deux lignes, comprimé par la pastille multipanier.
       On rend la pastille compressible et on tronque SON libellé, plutôt que de
       casser le titre du volet. */
    #shops-cartOffcanvas .offcanvas-title { font-size: 1.05rem; white-space: nowrap; }
    #shops-cartOffcanvas .cart-switch { min-width: 0; }
    /* La PAGE panier souffre du même serrage : son h1 passe sur deux lignes,
       comprimé par la même pastille multipanier. Même remède. */
    .page-cart h1 { font-size: 1.35rem; white-space: nowrap; }
    .page-cart #cart-switch { min-width: 0; }
    .page-cart #cart-switch .dropdown-toggle,
    #shops-cartOffcanvas .cart-switch .dropdown-toggle {
        max-width: 42vw; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
    }

    /* Les jalons débordaient de 5 px et le dernier libellé était rogné. Chacun
       est borné au tiers de la piste et peut passer sur deux lignes — on donne
       au conteneur la hauteur correspondante. */
    .shops-cart-shippings-status .shops-cart-shipping-step {
        max-width: 33%; font-size: .62rem;
    }
    .shops-cart-shippings-status .shops-cart-shipping-step > * {
        white-space: normal; overflow-wrap: anywhere;
    }
    .shops-cart-shipping-steps-wrapper { height: 52px; }

    /* Les 5 px de débordement venaient des marges NÉGATIVES qui recalent la
       pastille des jalons extrêmes sur leur position exacte (-5px de part et
       d'autre). Sur 351 px de piste, les rendre à zéro décale le point de 1,4 %
       — invisible — et rend le dernier libellé entièrement lisible.
       Au-dessus de 576 px la piste est assez large : la règle d'origine tient. */
    .shops-cart-shippings-status .shops-cart-shipping-step:first-child .dot { margin-left: 0; }
    .shops-cart-shippings-status .shops-cart-shipping-step:last-child  .dot { margin-right: 0; }
}

#shops-cartOffcanvas {
    --cart-accent:      var(--btn-1-bg, var(--color-1, #F8B11F));
    --cart-accent-soft: color-mix(in srgb, var(--cart-accent) 9%,  #fff);
    --cart-accent-line: color-mix(in srgb, var(--cart-accent) 32%, #fff);
}
#shops-cartOffcanvas .offcanvas-title .fa-cart-shopping { color: var(--cart-accent); }

/* Ligne article : carte blanche au lieu du pavé gris Bootstrap. */
#shops-cartOffcanvas .shops-cart-item {
    background: #fff !important;
    border-color: rgba(0, 0, 0, .08) !important;
    border-radius: 12px !important;
    margin-bottom: .6rem !important;
    overflow: hidden;
    transition: box-shadow .18s ease, border-color .18s ease;
}
#shops-cartOffcanvas .shops-cart-item:hover {
    border-color: var(--cart-accent-line) !important;
    box-shadow: 0 3px 12px color-mix(in srgb, var(--cart-accent) 12%, transparent);
}
#shops-cartOffcanvas .shops-cart-item--pack-child {
    opacity: 1 !important; background: #fbfbfd !important; border-style: dashed !important;
}
#shops-cartOffcanvas .shops-cart-item > div:first-child { padding: .8rem !important; gap: .8rem !important; }
#shops-cartOffcanvas .shops-cart-item-image img { border: 1px solid rgba(0, 0, 0, .06); }
/* Article sans visuel : même colonne réservée (aligne titres avec/sans image). */
#shops-cartOffcanvas .shops-cart-item > div:first-child:not(:has(.shops-cart-item-image))::before {
    content: ""; flex: 0 0 auto; width: 72px; height: 72px; margin-left: .5rem;
    border-radius: .375rem; border: 1px solid rgba(0, 0, 0, .06);
    background: #f4f5f9 url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23aab2c0' stroke-width='1.4' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='3' y='3' width='18' height='18' rx='2'/%3E%3Ccircle cx='8.5' cy='8.5' r='1.5'/%3E%3Cpath d='M21 15l-5-5L5 21'/%3E%3C/svg%3E") center / 26px no-repeat;
}
#shops-cartOffcanvas .shops-cart-item-title { font-size: .95rem; line-height: 1.35; }
#shops-cartOffcanvas .shops-cart-item-title a:hover,
#shops-cartOffcanvas .shops-cart-item-title a:focus-visible { text-decoration: underline; }
#shops-cartOffcanvas .shops-cart-item-price { font-size: 1.05rem; line-height: 1.3; }
#shops-cartOffcanvas .shops-cart-item-price-old { color: #9aa3b2 !important; }

/* Stepper de quantité : trois contrôles → une pilule. */
#shops-cartOffcanvas .shops-cart-qty {
    gap: 0 !important; width: fit-content; border: 1px solid rgba(0, 0, 0, .12);
    border-radius: 999px; overflow: hidden; background: #fff;
}
#shops-cartOffcanvas .shops-cart-qty .btn {
    border: 0; border-radius: 0; background: transparent; color: #4b5563;
    width: 2rem; height: 2rem; display: inline-flex; align-items: center; justify-content: center;
    font-size: 1rem; line-height: 1; padding: 0;
}
#shops-cartOffcanvas .shops-cart-qty .btn:hover:not(:disabled),
#shops-cartOffcanvas .shops-cart-qty .btn:focus-visible:not(:disabled) { background: rgba(0, 0, 0, .06); color: #111827; }
#shops-cartOffcanvas .shops-cart-qty .btn:disabled { opacity: .3; }
#shops-cartOffcanvas .shops-cart-qty .form-control {
    border: 0; border-radius: 0; background: transparent; box-shadow: none;
    height: 2rem; padding: 0; font-weight: 600; width: 46px !important;
}
#shops-cartOffcanvas .shops-cart-qty .form-control::-webkit-outer-spin-button,
#shops-cartOffcanvas .shops-cart-qty .form-control::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }
#shops-cartOffcanvas .shops-cart-qty .form-control[type="number"] { -moz-appearance: textfield; appearance: textfield; }

/* Suppression : cible de 32 px. */
#shops-cartOffcanvas .shops-cart-item [data-remove] {
    width: 2rem; height: 2rem; border-radius: 50%; display: inline-flex; align-items: center; justify-content: center;
    color: #9aa3b2 !important; transition: background-color .15s ease, color .15s ease;
}
#shops-cartOffcanvas .shops-cart-item [data-remove]:hover,
#shops-cartOffcanvas .shops-cart-item [data-remove]:focus-visible { background: #fee2e2; color: #dc2626 !important; }

/* Options / champs perso : encart rattaché à l'article. */
#shops-cartOffcanvas .shops-cart-options,
#shops-cartOffcanvas .shops-cart-custom-fields {
    background: #fafbfc; border-top-color: rgba(0, 0, 0, .06) !important; padding: .5rem .8rem .6rem !important;
}
#shops-cartOffcanvas .shops-cart-options [data-option-remove] { color: #9aa3b2 !important; }
#shops-cartOffcanvas .shops-cart-options [data-option-remove]:hover { color: #dc2626 !important; }

/* Pied du tiroir : total en bandeau d'accent (texte sombre = contraste). */
#shops-cartOffcanvas .shops-cart-summary .fw-bold {
    background: var(--cart-accent-soft); border: 1px solid var(--cart-accent-line);
    border-radius: 10px; padding: .6rem .75rem;
}

/* =========================================================================
   FICHE PRODUIT — couverture, rythme et blocs secondaires
   ========================================================================= */

/* -- Bandeau de couverture --------------------------------------------------
   Première image du produit, sortie de la galerie : un visuel d'ambiance ne se
   parcourt pas comme les photos du produit. Rendu pleine largeur, hauteur
   BORNÉE — un portrait en 3:4 occuperait sinon deux écrans avant le prix. */
/* Même convention que la cover d'une CATÉGORIE (`.aw-composant--cover` du thème) :
   bannière pleine largeur. Le FORMAT vient du réglage du module
   (Boutique › Paramètres › Ratio de l'image de couverture), posé en variable par
   le composant — comme la famille Blogs. Réglage absent → ratio naturel de
   l'image, borné en hauteur pour qu'un portrait ne remplisse pas deux écrans. */
.shops-cover { margin: 0 0 1.5rem; padding: 0; line-height: 0; }
.shops-cover img {
    display: block;
    width: 100%;
    height: auto;
    max-height: 70vh;
    object-fit: cover;
    object-position: center;
}
.shops-cover[style*="--shops-cover-ratio"] img {
    aspect-ratio: var(--shops-cover-ratio);
    height: 100%;          /* sans quoi `height:auto` l'emporte sur le ratio */
    max-height: none;
}
@media (max-width: 575.98px) { .shops-cover img { max-height: 55vh; } }
/* Produit sans couverture : le composant ne rend rien, on retire aussi la marge. */
.shops-cover:empty { display: none; }

/* -- Stickers : image OU libellé ------------------------------------------
   Un sticker peut n'avoir qu'un nom (« Exclu web ») : il devient une pastille
   texte, aux couleurs de la charte, plutôt que de disparaître. */
.shops-stickers { display: inline-flex; align-items: center; gap: .4rem; flex-wrap: wrap; }
.shops-stickers img { height: 34px; width: auto; display: block; }
/* Aspect DISTINCT du badge promo (`.shops-badge--promo`, fond --color-1 plein) :
   un sticker est une étiquette choisie par le marchand, le badge est une remise
   CALCULÉE sur les prix. Les afficher à l'identique laissait croire à deux
   remises contradictoires — « -30% » (sticker) à côté de « -17% » (réel). */
.shops-sticker--text {
    display: inline-block;
    padding: .18rem .55rem;
    border-radius: 6px;
    font-size: .75rem;
    font-weight: 600;
    line-height: 1.45;
    letter-spacing: .01em;
    color: var(--aw-text, #1f2937);
    background: transparent;
    border: 1px solid var(--aw-border, #d7dae0);
}


/* -- Badges du commerçant -------------------------------------------------
   Réglés dans Catalogue › Badges (libellé, couleurs, arrondi, icône). Les
   couleurs arrivent en `style` inline : la feuille ne pose donc QUE la mise
   en forme, jamais les teintes — sinon le réglage d'administration n'aurait
   plus aucun effet. Repli discret si le commerçant n'a rien choisi. */
.shops-badges { display: inline-flex; align-items: center; gap: .35rem; flex-wrap: wrap; }
.shops-badge--custom {
    display: inline-flex;
    align-items: center;
    padding: .18rem .55rem;
    font-size: .75rem;
    font-weight: 600;
    line-height: 1.45;
    letter-spacing: .01em;
    background: var(--aw-surface-2, #f3f4f6);
    color: var(--aw-text, #1f2937);
    white-space: nowrap;
}
/* -- Colonne d'achat : un rythme, pas une pile ----------------------------
   Les composants arrivent les uns sous les autres sans hiérarchie ; on donne
   au prix l'espace qui le distingue, et on rapproche ce qui va ensemble. */
.shops-detail__prices { margin: .5rem 0 .25rem; }
.shops-detail__price { font-size: clamp(1.6rem, 1.2rem + 1.4vw, 2.1rem); line-height: 1.1; letter-spacing: -.01em; }
.aw-composant--price_ht,
.aw-composant--saving { font-size: .85rem; }
.aw-composant--saving { color: #15803d; font-weight: 600; }
.aw-composant--price_ht { color: var(--aw-muted, #6b7280); }

/* -- Caractéristiques : lignes alternées, plus lisibles en liste longue --- */
.shops-attrs { gap: 0; }
.shops-attrs dt,
.shops-attrs dd { padding: .45rem .25rem; border-top: 1px solid var(--aw-border, #eceef2); }
.shops-attrs dt:first-of-type,
.shops-attrs dd:first-of-type { border-top: 0; }

/* -- Documents ------------------------------------------------------------- */
.shops-files { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: .4rem; }
.shops-files a { display: flex; align-items: center; gap: .5rem; text-decoration: none; }

/* -- Tarifs dégressifs : le palier conseillé doit se voir ----------------- */
.shops-tiers table { width: 100%; margin: 0; }
.shops-tiers .is-best { background: color-mix(in srgb, var(--color-1, #d85575) 8%, transparent); font-weight: 600; }

/* -- Galerie sous la couverture ------------------------------------------
   Son format vient du réglage du module (Boutique › Paramètres › Ratio des
   images produit), posé en style inline par le composant. On ne le force donc
   PLUS ici : la règle qui suivait imposait 4/5 puis 1/1 et écrasait le choix du
   marchand. */

/* ------------------------------------------------------------------ *
 * Composants ATTRIBUTS (fiche + carte) — visuels d'affichage & format.
 * Classes shops-av* : visuel NON interactif (distinct du pavé cliquable
 * .shops-attr-swatch du sélecteur de déclinaisons).
 * ------------------------------------------------------------------ */
.shops-av { display: inline-flex; align-items: center; justify-content: center; vertical-align: middle; }
.shops-av--color { width: 16px; height: 16px; border-radius: 4px; border: 1px solid rgba(0,0,0,.15); background: var(--sw, #eee); }
.shops-av--img { width: 20px; height: 20px; border-radius: 4px; object-fit: cover; }
.shops-av--icon { font-size: 1rem; line-height: 1; color: inherit; }
.shops-av--svg { width: 18px; height: 18px; }
.shops-av--svg svg { width: 100%; height: 100%; display: block; }
.shops-attrs dd .shops-av { margin-right: .2rem; }
.shops-attr-val { }

/* Format TABLEAU du composant Attributs (fiche). */
.shops-attrs-table { width: 100%; border-collapse: collapse; margin: 1rem 0 0; }
.shops-attrs-table th, .shops-attrs-table td { text-align: left; padding: .45rem .5rem; border-top: 1px solid var(--aw-border, #eceef2); vertical-align: top; }
.shops-attrs-table tr:first-child th, .shops-attrs-table tr:first-child td { border-top: 0; }
.shops-attrs-table th { font-weight: 600; color: var(--aw-muted, #4b5563); white-space: nowrap; }

/* Attributs statiques de CARTE : disposition en ligne (chips) / sans nom de groupe. */
.shops-static-attrs--inline { display: flex; flex-wrap: wrap; gap: .35rem .6rem; }
.shops-static-attrs--inline .product__spec { display: inline-flex; gap: .3rem; }
.shops-static-attrs--no-labels .product__spec-label { display: none; }

/* -- Cartes de catalogue à HAUTEUR ÉGALE ---------------------------------- */
/*
 * Les colonnes Bootstrap s'étiraient déjà à la même hauteur (mesuré : 480 px
 * partout) ; c'est la CARTE qui ne remplissait pas la sienne — 479, 457, 405,
 * 376… selon qu'elle porte des étoiles, trois ou quatre lignes d'attributs, un
 * bouton « Ajouter » ou « Voir le produit ». D'où des cartes de hauteurs
 * différentes sur une même rangée.
 *
 * La carte prend donc toute la hauteur de sa colonne, et son corps devient une
 * colonne flex : le bloc d'achat est poussé en bas (`margin-top:auto`), si bien
 * que les boutons s'alignent d'une carte à l'autre au lieu de flotter là où le
 * texte s'arrête.
 *
 * Hors grille (carrousel, widget, embarqué), le parent n'a pas de hauteur
 * définie : `height:100%` y retombe sur `auto` — rien ne change.
 */
.shops-card,
.module-card {
    height: 100%;
    display: flex;
    flex-direction: column;
}
/* Le visuel garde sa taille : sans cela, une carte plus courte que sa colonne
   verrait son image s'étirer, et une carte plus longue l'écraserait. */
.shops-card > .module-card__media,
.module-card > .module-card__media { flex: 0 0 auto; }

.shops-card > .module-card__body,
.module-card > .module-card__body {
    flex: 1 1 auto;
    display: flex;
    flex-direction: column;
}
/* Zone d'achat (quantité + panier, ou « Voir le produit ») collée en bas. */
.module-card__body > .aw-composant--buy_block { margin-top: auto; }


/* ── Leviers conversion / panier moyen (composants fiche) ───────────────── */
.aw-composant--franco_bar,.aw-composant--stock_urgency{display:block}
.shops-franco-hint{display:flex;align-items:center;gap:.5rem;background:#eef7f0;border:1px solid #cfe8d6;color:#1b6b3a;border-radius:8px;padding:.6rem .9rem;font-size:.95rem;margin:.75rem 0}
.shops-franco-hint i{color:#2c7a6e;font-size:1.1rem}
.shops-urgency-wrap{display:flex;flex-wrap:wrap;gap:.5rem;margin:.75rem 0}
.shops-urgency{display:inline-flex;align-items:center;gap:.4rem;border-radius:999px;padding:.35rem .8rem;font-size:.9rem;font-weight:600;line-height:1.2}
.shops-urgency--stock{background:#fff3e6;color:#b3541e;border:1px solid #f4d3b0}
.shops-urgency--promo{background:#fdeaef;color:#b01e46;border:1px solid #f4c2cf}
.shops-comp-related,.shops-comp-fbt{margin-top:2rem;padding-top:1.25rem;border-top:1px solid #eee}
.shops-comp-related h2,.shops-comp-fbt h2{font-weight:700}
