/* ==========================================================================
   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; }
/* Ouverture par la CLASSE (tap tactile + clavier) : vaut sur tous les supports. */
.shops-card-actions.is-open .shops-card-actions__menu { opacity:1; visibility:visible; transform:translateY(0); pointer-events:auto; }
.shops-card-actions.is-open .shops-card-toggle { background:#111; color:#fff; }
/* Survol / focus SOURIS uniquement : sur tactile, le focus qui persiste après le
 * tap empêchait la fermeture au 2e tap (:focus-within gardait le menu ouvert). */
@media (hover:hover) and (pointer:fine) {
  .shops-card-actions:hover .shops-card-actions__menu,
  .shops-card-actions:focus-within .shops-card-actions__menu { opacity:1; visibility:visible; transform:translateY(0); pointer-events:auto; }
  .shops-card-actions:hover .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. */
/* L'écart entre deux GROUPES (Couleur / Taille) était le même qu'entre deux
   valeurs d'un même groupe : les rangées se lisaient comme une seule liste.
   Un demi-cran de plus suffit à les séparer sans allonger la carte. */
.product__axes  { display: flex; flex-direction: column; gap: .5rem; 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 {
    /* 24 px : même raison que la pastille de taille ci-dessous — en dessous, on
       passe sous la cible minimale de WCAG 2.2 AA et c'est pénible au pouce. */
    width: 24px; height: 24px; padding: 0;
    background: var(--sw, #ccc);
    border: 1px solid rgba(0, 0, 0, .2);
    box-shadow: inset 0 0 0 2px #fff;
    /* Ronde : elle se distingue ainsi au premier coup d'œil des pastilles de
       TAILLE, qui restent rectangulaires. Deux formes, deux natures de choix —
       on ne confond plus une couleur avec une taille en balayant la carte.
       Le liseré blanc intérieur et l'anneau de sélection suivent le rayon. */
    border-radius: 50%;
    cursor: pointer; position: relative;
    transition: transform .12s, outline-color .12s;
}
.product__swatch:hover  { transform: scale(1.12); }

/* SÉLECTION D'UNE COULEUR — un anneau EXTÉRIEUR, pas une bordure.
   L'état actif ne se distinguait que par une bordure de 1 px passant de noir 20 %
   à noir plein : sur une pastille sombre elle se confondait avec la pastille
   elle-même, et on ne voyait plus quelle couleur était retenue. La pastille de
   TAILLE, elle, s'inverse en noir sur blanc — d'où un déséquilibre de lisibilité
   entre les deux axes du même sélecteur.
   L'anneau est posé HORS de la pastille (`outline` + `offset`) : il se détache
   donc du fond de la carte, quelle que soit la couleur du produit — blanc sur
   blanc compris. */
.product__swatch.active {
    border-color: rgba(0, 0, 0, .45);
    outline: 2px solid var(--btn-2-bg, var(--color-1, #111));
    outline-offset: 2px;
}
/* Le focus clavier reste distinct de la sélection : pointillé, pour ne pas
   laisser croire qu'un déplacement au clavier a déjà choisi la couleur. */
.product__swatch:focus-visible {
    outline: 2px dashed var(--btn-2-bg, var(--color-1, #111));
    outline-offset: 3px;
}

/* 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 {
    /* Rentré de 1 px depuis que la pastille est ronde : débordant, le trait
       laissait dépasser deux pointes hors du cercle. */
    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 --------------------------------------- */
/* Le cadre de la vignette vaut AVEC et SANS photo : même carré, donc des
   cartes de même hauteur et une colonne alignée. Le sélecteur ne vise plus
   `img` seul, sinon le repli (une <div>) n'aurait aucune dimension. */
.shops-cart-cross-sell-item .shops-cart-cross-sell-img {
    display: block; width: 100%; aspect-ratio: 1; object-fit: cover;
}
/* Cadre vide : EXACTEMENT le visuel des lignes du panier (même fond, même
   liseré, même pictogramme). Les deux cohabitent dans le même volet — deux
   gris différents à 20 cm l'un de l'autre se voient tout de suite. Le motif
   est repris tel quel de la règle `.shops-cart-item ... ::before`. */
.shops-cart-cross-sell-img--placeholder,
.shops-cart-cs-slide-img--placeholder {
    border: 1px solid rgba(0, 0, 0, .06);
    border-radius: .375rem;
    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;
}
/* Conservé : une boutique dont le gabarit pose encore un <img> nu. */
.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: .1rem 0; }
.shops-cart-cs-slide-img { width: 46px; height: 46px; 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; }
/* Carrousel horizontal : 1 produit par vue (hauteur = 1 produit). Le slider JS
   (_initCrossSellSlider) pilote scrollLeft/offsetWidth → il FAUT une rangée
   horizontale à défilement par accroche, pas une colonne (qui empilait les 4
   produits et rendait flèches/points inopérants). */
.shops-cart-cross-sell-mobile-list {
    display: flex; flex-direction: row; gap: .5rem;
    overflow-x: auto; scroll-snap-type: x mandatory;
    -webkit-overflow-scrolling: touch; scrollbar-width: none;
}
.shops-cart-cross-sell-mobile-list::-webkit-scrollbar { display: none; }
/* Réserve à gauche/droite pour que les flèches ne recouvrent NI l'image NI le
   bouton (elles vivent dans ces gouttières). box-sizing conservé → la diapo
   fait toujours 100 % de large. */
.shops-cart-cross-sell-mobile-item {
    flex: 0 0 100%; min-width: 100%; scroll-snap-align: start;
    box-sizing: border-box; padding: 0 26px;
}
.shops-cart-cross-sell-mobile-title { font-weight: 600; color: var(--aw-muted, #6b7280); }
.shops-cart-cross-sell-dots { display: flex; justify-content: center; gap: .35rem; margin-top: .25rem; }
.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;
    box-shadow: none;
    transition: border-color .15s, background-color .15s;
}
/* Ni ombre ni soulevement au survol : ils recouvraient le liseré supérieur.
   On garde seulement un discret changement de bordure/fond comme repère. */
.shops-shortcut:hover {
    border-color: #d3d7de;
    background: #fafbfc;
    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.
   Pas de bleed : la 1re tuile s'aligne à gauche sur les cartes et la barre
   d'outils. Avec le bleed (marge négative + padding), le scroll-snap calait la
   1re tuile au bord de l'écran (padding avalé) → décalée vs les autres blocs. */
@media (max-width: 767.98px) {
    .shops-shortcuts {
        flex-wrap: nowrap;
        overflow-x: auto;
        -webkit-overflow-scrolling: touch;
        scroll-snap-type: x proximity;
        margin-inline: 0;
        padding: 0 0 .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; }
/* SÉLECTION D'UNE PASTILLE DE FACETTE — la classe ET la case cochée.
   L'anneau n'était accroché qu'à `.active`, posée par le JavaScript. Or le
   TIROIR de filtres, lui, ne pose jamais cette classe : sa case à cocher est
   `visually-hidden` dans le label, et il s'en remettait à une règle qui ne
   redéfinissait que `outline-color` — sans style ni épaisseur d'outline, donc
   sans rien dessiner. Cocher une couleur dans le volet ne produisait AUCUN
   changement visible : on ne savait pas ce qu'on avait sélectionné.
   `:has(input:checked)` rejoint donc `.active` sur la même déclaration, et les
   deux chemins donnent le même anneau. */
.shops-color-swatch.active,
.shops-img-swatch.active,
.shops-icon-swatch.active,
.shops-svg-swatch.active,
.shops-color-swatch:has(input:checked),
.shops-img-swatch:has(input:checked),
.shops-icon-swatch:has(input:checked),
.shops-svg-swatch:has(input:checked) {
    border-color: var(--btn-2-bg, #111);
    box-shadow: 0 0 0 2px var(--btn-2-bg, #111);
}
/* Parcours clavier : la case est masquée, c'est donc le LABEL qui doit montrer
   le focus — sinon on navigue à l'aveugle dans le tiroir. Pointillé, pour ne pas
   se confondre avec la sélection. */
.shops-color-swatch:has(input:focus-visible),
.shops-img-swatch:has(input:focus-visible),
.shops-icon-swatch:has(input:focus-visible),
.shops-svg-swatch:has(input:focus-visible) {
    outline: 2px dashed var(--btn-2-bg, #111);
    outline-offset: 2px;
}
/* Valeur sans produit (product_count = 0) : barrée en diagonale. */
/* VALEUR SANS PRODUIT — la barre existait, mais pour la seule pastille COULEUR.
   Une icône ou une vignette à zéro était strictement identique à une vivante.
   Les quatre types partagent `position: relative`, la barre s'y pose telle
   quelle. L'opacité double le signal : sur une vignette photo, un trait rouge
   seul se perd dans l'image. */
.shops-swatch--vide {
    opacity: .5;
    cursor: not-allowed;
}
.shops-color-swatch .swatch-strike,
.shops-img-swatch .swatch-strike,
.shops-icon-swatch .swatch-strike,
.shops-svg-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;
    /* Ronde, comme la pastille de couleur des cartes : le même produit ne doit
       pas changer de vocabulaire visuel entre la grille et sa fiche. */
    border-radius: 50%;
    transition: border-color .12s, box-shadow .12s;
}
/* La vignette d'une déclinaison ILLUSTRÉE reste rectangulaire : un cercle y
   rognerait la photo du produit, qui est justement ce qu'on donne à voir. */
.shops-attr-swatch--img { background: #fff; border-radius: 6px; }
.shops-attr-swatch--img img { width: 100%; height: 100%; object-fit: cover; display: block; }
.shops-attr-swatch:hover { border-color: #111; }
/* SÉLECTION VISIBLE — un anneau EXTÉRIEUR, pas une bordure d'1 px.
   L'état actif ne se distinguait que par la bordure passant de gris clair à
   noir : sur une pastille foncée elle se confondait avec la pastille, et on
   ne savait plus quelle couleur on avait retenue. C'est le défaut déjà
   corrigé sur les cartes du catalogue et dans le volet de filtres ; la FICHE
   l'avait gardé. Trois écrans, une seule façon de montrer un choix. */
.shops-attr-swatch.active {
    border-color: var(--btn-2-bg, var(--color-1, #111));
    box-shadow: 0 0 0 2px var(--btn-2-bg, var(--color-1, #111));
}
/* Le focus clavier reste distinct de la sélection : pointillé. */
.shops-attr-swatch:focus-visible {
    outline: 2px dashed var(--btn-2-bg, var(--color-1, #111));
    outline-offset: 3px;
}
.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}

/* Bandeau de vignettes = carrousel (awcarousel), plus une rangée qui se replie.
   La vignette prend toute la largeur de son slide et reste carrée : c'est le
   carrousel qui décide combien il en tient, pas un `width:72px` en dur. */
.shops-thumbs{overflow:hidden}
.shops-thumbs .shops-product-gallery__thumb{display:block;width:100%;aspect-ratio:1;background:none}
.shops-thumbs .shops-product-gallery__thumb img{width:100%;height:100%;object-fit:cover;display:block}
.shops-thumbs-nav{position:absolute;top:50%;transform:translateY(-50%);z-index:3;width:28px;height:28px;border:0;border-radius:50%;
  background:rgba(255,255,255,.92);color:#111;box-shadow:0 1px 5px rgba(0,0,0,.18);display:flex;align-items:center;justify-content:center;cursor:pointer;font-size:.75rem;transition:background .15s}
.shops-thumbs-nav:hover{background:#fff}
.shops-thumbs-nav--prev{left:4px}
.shops-thumbs-nav--next{right:4px}
/* 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; }
/* Sélecteur date + créneaux : côte à côte quand la colonne est large, empilé
   dès qu'elle se resserre. Piloté par la LARGEUR DE LA COLONNE (requête de
   conteneur), pas celle de l'écran : sur tablette la fiche reste en 2 colonnes,
   donc la colonne d'achat est étroite alors que l'écran est large — le calendrier
   fixe (280px) y écrasait la liste des séances (texte tronqué, scroll horizontal). */
.product-ticket, .product-activity { container-type: inline-size; }
@container (max-width: 560px) {
    .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; }
}
/* Repli pour les navigateurs sans requêtes de conteneur : au moins le téléphone. */
@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,
.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 ». */
/* 420 px = largeur de confort dans une colonne de contenu LARGE (fiche native,
   pleine page) : au-delà, « Dès 5 » et son prix se retrouvent aux deux bouts
   d'un mètre de vide. Dans le BLOC DE VENTE, la contrainte s'inverse — le bloc
   fait ~500 px et le tableau s'arrêtait 80 px avant son bord, sous un en-tête
   qui, lui, allait jusqu'au bout : deux blocs sans rapport l'un au-dessus de
   l'autre. Il y prend donc toute la largeur (voir plus bas). */
.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; }
/* Déstockage : orange « liquidation », distinct de la promo (rose) et de la rupture (gris). */
.shops-badge--destock { background: #ea580c; color: #fff; }
/* État physique : occasion (ambre) / reconditionné (vert), pour distinguer d'un coup d'œil. */
.shops-badge--condition { color: #fff; }
.shops-badge--cond-2 { background: #b45309; } /* Occasion */
.shops-badge--cond-3 { background: #0f766e; } /* Reconditionné */

/* -- 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:flex;align-items:center;gap:.7rem;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;
}
/* ----- Haut du volet : de l'air, pas du vide ------------------------------
   Entre le bandeau « livraison gratuite » et le premier article s'accumulaient
   quatre espacements décidés séparément : la marge sous la barre de progression,
   la réserve du rail des paliers, le `pb-1` du bandeau, puis le `p-3` du
   conteneur d'articles. Mis bout à bout, une quarantaine de pixels perdus tout
   en haut, là où le client doit voir ses articles. On resserre — sans y toucher
   ailleurs : les marges LATÉRALES et le bas du conteneur restent inchangés. */
#shops-cartOffcanvas .shops-cart-shippings-status { padding-bottom: 0 !important; }
#shops-cartOffcanvas .shops-cart-shippings-status .progress { margin-bottom: .25rem !important; }
#shops-cartOffcanvas #cart-root-offcanvas { padding-top: .5rem !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}

/* ===================== Questions & Réponses produit ===================== */
.shops-detail-qa .shops-qa__counters{gap:.75rem}
.shops-qa__stat{display:flex;flex-direction:column;align-items:center;min-width:64px;padding:.4rem .6rem;border:1px solid rgba(0,0,0,.1);border-radius:8px}
.shops-qa__stat b{font-size:1.15rem;line-height:1}
.shops-qa__stat small{color:#6b7280;font-size:.7rem;text-transform:uppercase;letter-spacing:.02em}
.shops-qa__item{padding:1rem 0;border-bottom:1px solid rgba(0,0,0,.08)}
.shops-qa__meta{display:flex;gap:.6rem;align-items:baseline;font-size:.85rem;margin-bottom:.15rem}
.shops-qa__author{font-weight:600}
.shops-qa__date{color:#9ca3af;font-size:.8rem}
.shops-qa__qtext{margin:.15rem 0 .5rem;font-weight:500}
.shops-qa__vote{display:flex;align-items:center;flex-wrap:wrap;gap:.5rem;margin:.25rem 0 .5rem}
.shops-qa__vote-lbl{font-size:.82rem;color:#6b7280}
.shops-qa__vote-btn{border:1px solid rgba(0,0,0,.2);background:#fff;border-radius:6px;padding:.15rem .6rem;font-size:.82rem;cursor:pointer;line-height:1.4}
.shops-qa__vote-btn.is-on{background:var(--color-1,#16a34a);color:#fff;border-color:transparent}
.shops-qa__answers{margin-top:.5rem;padding:.6rem .8rem;background:#f6f7f9;border-radius:8px}
.shops-qa__answers-h{font-weight:700;font-size:.9rem;margin-bottom:.4rem}
.shops-qa__answer + .shops-qa__answer{margin-top:.5rem;padding-top:.5rem;border-top:1px dashed rgba(0,0,0,.1)}
.shops-qa__atext{margin:.1rem 0 0}
.shops-qa__empty{padding:.5rem 0}
.shops-qa__form textarea{max-width:640px}

/* ===== Mode LISTE du catalogue DESSINÉ ================================
   La bascule grille/liste (app.js) pose `.module-cards--list` sur la rangée
   `.aw-repeat-row`. La règle générique `.aw-repeat-row .module-card:not(...)
   :not(...)` force `flex-direction:column` avec une spécificité (0,4,0) qui
   ÉCRASAIT le passage en ligne du thème → carte pleine largeur, image en haut
   et grand vide à droite. On rebat ici (spécificité (0,5,0)), scopé aux cartes
   boutique, et on fait remplir le corps. Horizontale à TOUTES les largeurs
   (mobile inclus) ; réglage mobile dédié plus bas. ==================================== */
@media (min-width:0px){
  .module-cards--list.aw-repeat-row .module-card.shops-card:not(.module-card--horizontal){
    flex-direction:row;
    align-items:stretch;
  }
  .module-cards--list.aw-repeat-row .module-card.shops-card:not(.module-card--horizontal) > .module-card__media{
    flex:0 0 34%;
    max-width:240px;
    align-self:stretch;
  }
  .module-cards--list.aw-repeat-row .module-card.shops-card:not(.module-card--horizontal) > .module-card__media .module-card__img{
    height:100%;
    object-fit:cover;
  }
  .module-cards--list.aw-repeat-row .module-card.shops-card:not(.module-card--horizontal) > .module-card__body{
    flex:1 1 auto;
    display:flex;
    flex-direction:column;
    justify-content:center;
    padding-left:1.25rem;
  }
  /* La zone d'achat ne s'étire pas sur toute la largeur en mode liste. */
  .module-cards--list.aw-repeat-row .module-card.shops-card:not(.module-card--horizontal) .aw-composant--buy_block{
    max-width:360px;
  }
}
/* Mobile (<576px) : carte liste horizontale resserrée — image un peu plus large
   en proportion, corps collé, marge d'image supprimée pour gagner de la place. */
@media (max-width:575.98px){
  .module-cards--list.aw-repeat-row .module-card.shops-card:not(.module-card--horizontal) > .module-card__media{
    flex:0 0 40%;
    max-width:150px;
  }
  .module-cards--list.aw-repeat-row .module-card.shops-card:not(.module-card--horizontal) > .module-card__body{
    padding:.6rem;
    /* Contenu calé EN HAUT (et non centré) : les cartes peu remplies n'ont plus
       un grand vide vertical au-dessus/en dessous du contenu. */
    justify-content:flex-start;
  }
  /* Écart vertical entre cartes liste resserré (le gy-4 de la grille est trop
     grand pour une liste sur mobile). */
  .module-cards--list.aw-repeat-row{ --bs-gutter-y:.75rem; }
}
/* Description courte (extrait) masquée par défaut sur mobile → cartes plus
   compactes (grille comme liste). Réaffichable au besoin via le builder. */
@media (max-width:575.98px){
  .shops-index .aw-composant--excerpt{ display:none; }
  /* Corps de carte plus compact sur mobile (grille) : moins de padding perdu.
     !important car une règle de base plus bas (.shops-card .module-card__body{padding:1rem})
     a la même spécificité et gagnerait par ordre de source. */
  .shops-card .module-card__body{ padding:.6rem !important; }
}

/* CTA de carte en grille étroite (2 col mobile) : le libellé long
   ("Choisir un créneau", "Voir l'abonnement"…) s'enroule DANS le bouton au
   lieu de déborder. Le thème force white-space:nowrap sur .btn → !important. */
@media (max-width:575.98px){
  .shops-index .js-view-product,
  .shops-index .js-add-to-cart{ white-space:normal !important; line-height:1.15; min-width:0; }
  /* Zone « quantité + Ajouter » : le stepper est resserré pour que le bouton
     panier garde assez de large — sinon l'icône dépasse du bouton (cf. capture). */
  .shops-index .js-buy-zone .input-group{ max-width:92px !important; }
  .shops-index .js-buy-zone .input-group .form-control{ min-width:0; padding-left:2px; padding-right:2px; }
  .shops-index .js-buy-zone .input-group .btn{ padding-left:6px; padding-right:6px; }
  .shops-index .js-add-to-cart{ min-width:40px; }
  /* Bouton panier : même hauteur que le stepper (le thème le rend + court car
     sans bordure et line-height réduit) → on l'étire et on centre l'icône. */
  .shops-index .js-buy-zone .js-add-to-cart{ align-self:stretch; display:inline-flex; align-items:center; justify-content:center; }
  /* Cartes 2 colonnes étroites : on réduit les pastilles rondes (favoris / liste /
     « 3 points », l'avatar vendeur) et le badge d'avis, trop gros sinon. */
  .shops-index .shops-card-action{ width:28px !important; height:28px !important; font-size:12px !important; }
  .shops-index .shops-seller__avatar{ width:28px !important; height:28px !important; font-size:11px !important; }
  .shops-index .shops-seller__verified{ width:12px !important; height:12px !important; font-size:8px !important; }
  .shops-index .shops-card__rating-row{ font-size:.6rem !important; padding:1.5px 6px !important; gap:3px !important; }
  .shops-index .shops-rating{ gap:.5px !important; }
  .shops-index .shops-rating i{ font-size:8px !important; }
  /* Badges (« Nouveau », promo…) et titre produit compactés sur petites cartes. */
  .shops-index .shops-badge{ font-size:10px !important; padding:2px 6px !important; line-height:1.3 !important; }
  .shops-index .shops-card__title,
  .shops-index .module-card__title{ font-size:.95rem !important; line-height:1.25 !important; }
}

/* Bloc VENDEUR compact sur CARTE (chip) — ≠ .shops-seller--card (bloc plein fiche). */
.shops-seller--chip{display:inline-flex;align-items:center;gap:.5rem;text-decoration:none;margin:.15rem 0 .35rem}
.shops-seller__avatar{width:34px;height:34px;border-radius:50%;object-fit:cover;flex:0 0 auto}
.shops-seller__avatar--ini{display:inline-flex;align-items:center;justify-content:center;background:var(--btn-2-bg,#143F6F);color:#fff;font-weight:700;font-size:.8rem;letter-spacing:.02em}
.shops-seller--chip .shops-seller__chipbody{display:flex;flex-direction:column;line-height:1.15;min-width:0}
.shops-seller--chip .shops-seller__by{font-size:.68rem;text-transform:uppercase;letter-spacing:.04em;color:var(--aw-muted,#8a94a6)}
.shops-seller--chip .shops-seller__name{font-weight:700;color:var(--aw-text,#1a1a1a);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.shops-seller--chip:hover .shops-seller__name{color:var(--color-1,#d85575)}

/* Toggle buy_block : masquer les groupes d'attributs (déclinaisons) sur la carte. */
.shops-buy-block--no-axes .product__axes{display:none}

/* Vendeur en OVERLAY bas-gauche de l'image de carte (pastille blanche, cf. capture). */
.shops-card__media{position:relative}
.shops-card__media .aw-composant--seller.shops-card__seller-ov{position:absolute;left:.55rem;bottom:.55rem;z-index:5;margin:0;max-width:calc(100% - 1.1rem)}
.shops-card__seller-ov .shops-seller--chip{background:rgba(255,255,255,.96);border-radius:999px;padding:.2rem .6rem .2rem .25rem;box-shadow:0 2px 8px rgba(0,0,0,.18);margin:0}
.shops-card__seller-ov .shops-seller__avatar{width:28px;height:28px}
.shops-card__seller-ov .shops-seller__avatar--ini{font-size:.68rem}

/* ==========================================================================
   FICHE — bloc de vente et bas de page posés en COLONNE ÉTROITE (gabarit 6-6)

   Les partiels de la fiche native sont découpés pour la pleine largeur : les
   avis en 4/8 (statistiques à gauche, liste à droite). Dans une demi-colonne,
   cette grille écrase l'histogramme contre la liste.

   On interroge donc la largeur du BLOC, pas celle de l'écran : `@container`.
   La fiche native (bloc large) garde son 4/8 ; posé dans un `col-6`, le même
   bloc empile statistiques PUIS liste, chacune sur toute sa largeur.
   ========================================================================== */
.shops-detail-reviews { container-type: inline-size; }

@container (max-width: 700px) {
    .shops-detail-reviews > .row > [class*="col-md-"] { flex: 0 0 100%; max-width: 100%; }
    /* Statistiques en bandeau : la note et l'histogramme se lisent côte à côte
       sur toute la largeur, au lieu d'une colonne maigre. */
    .shops-detail-reviews .product-rating { display: flex; align-items: baseline; gap: .75rem; margin-bottom: .6rem; }
    .shops-detail-reviews .reviews-histogram { max-width: 32rem; }
}

/* Repli pour les navigateurs sans requêtes de conteneur : à partir de deux
   colonnes (≥ 992 px), la fiche dessinée met les avis dans une demi-largeur —
   on y empile aussi. Sans @supports, ce repli s'appliquerait AUSSI à la fiche
   native pleine largeur, qui n'en a pas besoin. */
@supports not (container-type: inline-size) {
    @media (min-width: 992px) {
        .col-lg-6 .shops-detail-reviews > .row > [class*="col-md-"] { flex: 0 0 100%; max-width: 100%; }
    }
}

/* ==========================================================================
   BLOC DE VENTE — hiérarchie et respiration

   Le bloc empilait tout au même rythme (`gap: 1rem`) : référence, prix, pastille
   de stock, quantité, bouton, paliers, mentions. Chaque élément pesait autant
   que le prix, et le regard n'avait aucun point d'entrée. On resserre ce qui va
   ensemble et on aère ce qui se lit séparément.
   ========================================================================== */
.shops-sale-block { gap: .85rem; }

/* En-tête : référence à gauche, disponibilité à droite, sur une seule ligne. */
.shops-sale-block__head { display: flex; align-items: center; justify-content: space-between; gap: .75rem; }
.shops-sale-block__head .shops-sale-block__stock { flex: 0 0 auto; }
.shops-sale-block__head .shops-sale-block__stock > * { margin: 0; }

/* Prix : le point d'entrée du bloc. Ce qui le qualifie (HT, économie,
   éco-participation) se colle dessous, sans l'écart d'un élément autonome. */
.shops-sale-block .shops-detail__prices { margin-bottom: 0; }
.shops-sale-block__secondary,
.shops-sale-block__eco { margin-top: -.5rem; }
.shops-sale-block__eco { font-size: .85rem; color: var(--aw-muted, #667085); }
.shops-sale-block__eco i { color: #16a34a; }

/* Paliers dégressifs : une grille lisible plutôt qu'un tableau quadrillé.
   Les bordures internes disparaissent, seules les lignes horizontales restent. */

/* TOUTE LA LARGEUR DU BLOC. Le plafond de 420 px, utile en pleine page, tassait
   ici le tableau à 80 px du bord droit alors que l'en-tête « Tarifs dégressifs
   … Selon la quantité » allait, lui, jusqu'au bout. */
.shops-sale-block__tiers .shops-tiers-table { max-width: none; width: 100%; }
.shops-sale-block__tiers .shops-tiers { margin: 0; font-size: .875rem; }
.shops-sale-block__tiers .shops-tiers th,
.shops-sale-block__tiers .shops-tiers td { border: 0; border-bottom: 1px solid rgba(0, 0, 0, .06); padding: .45rem .25rem; }
.shops-sale-block__tiers .shops-tiers thead th { background: none; text-transform: uppercase; font-size: .72rem; letter-spacing: .04em; color: var(--aw-muted, #667085); border-bottom-width: 2px; }
.shops-sale-block__tiers .shops-tiers tbody tr:last-child th,
.shops-sale-block__tiers .shops-tiers tbody tr:last-child td { border-bottom: 0; }

/* « Signaler ce produit » : utile, mais ce n'est pas une action de vente. Il ne
   doit pas peser autant que le bouton juste au-dessus. */
.shops-sale-block .js-report-product,
.shops-sale-block a[href*="signaler"] { font-size: .8rem; opacity: .65; }
.shops-sale-block .js-report-product:hover { opacity: 1; }

/* ==========================================================================
   BAS DE FICHE — AVIS et QUESTIONS/RÉPONSES

   Les deux blocs disaient la même chose de deux façons : titres de poids
   différents, séparateurs différents, encadrés de réponse sans parenté. Côte à
   côte dans une grille 6-6, l'écart se voyait. On leur donne la MÊME grammaire
   — un titre, un filet, un encadré de réponse à liseré — en s'appuyant sur les
   jetons de la charte (`--aw-*`, `--color-1`) plutôt que sur des couleurs en
   dur, pour qu'un changement de thème les emporte tous les deux.
   ========================================================================== */

/* Titres : même graisse, même échelle des deux côtés. */
.shops-detail-reviews > h2,
.shops-detail-qa h2 {
    font-size: 1.05rem; font-weight: 700; letter-spacing: -.01em;
    color: var(--aw-text, #111827);
}

/* ── Note globale ─────────────────────────────────────────────────────── */
.shops-detail-reviews .product-rating { align-items: baseline; }
.shops-detail-reviews .rating-info { font-size: .85rem; }

/* Histogramme : barres pleine hauteur, arrondies, comptage en colonne fixe —
   l'œil suit une ligne, au lieu de sauter d'un fin trait gris à un chiffre
   perdu à droite. */
.shops-detail-reviews .reviews-histogram > div { padding: .1rem 0; }
.shops-detail-reviews .reviews-histogram .progress {
    height: .55rem; border-radius: 999px;
    background: var(--aw-bg-soft, #f1f3f5);
}
.shops-detail-reviews .reviews-histogram .progress-bar { border-radius: 999px; }
.shops-detail-reviews .reviews-histogram > div > span:first-child { min-width: 1.9rem; }
.shops-detail-reviews .reviews-histogram > div > span:last-child {
    min-width: 1.5rem; text-align: right; font-variant-numeric: tabular-nums;
}

/* ── Un avis ──────────────────────────────────────────────────────────── */
.shops-detail-reviews .review-item {
    border-bottom: 1px solid var(--aw-border, #eceef2);
    padding-bottom: 1.1rem; margin-bottom: 1.1rem;
}
.shops-detail-reviews .review-item:last-child { border-bottom: 0; margin-bottom: 0; }
/* Le TITRE de l'avis est ce qu'on lit en diagonale : il passe devant le nom. */
.shops-detail-reviews .review-item .fw-bold { font-size: 1rem; line-height: 1.35; }
.shops-detail-reviews .review-item .fw-semibold { font-size: .85rem; color: var(--aw-muted, #4b5563); font-weight: 600; }
.shops-detail-reviews .review-item .badge { font-weight: 500; font-size: .7rem; }

/* Réponse du vendeur : liseré à la couleur du thème + retrait. Un encadré gris
   sans marque se confondait avec l'avis lui-même. */
.shops-detail-reviews .review-reply {
    border-left: 3px solid var(--color-1, #0d6efd);
    background: var(--aw-bg-soft, #f6f7f9) !important;
    border-radius: 0 8px 8px 0; padding: .6rem .8rem !important;
    margin-left: .25rem;
}
.shops-detail-reviews .review-reply .fw-semibold { color: var(--color-1, #0d6efd); }

/* ── Questions & réponses ─────────────────────────────────────────────── */
.shops-detail-qa .shops-qa__stat {
    border-color: var(--aw-border, rgba(0,0,0,.1));
    background: var(--aw-card, #fff);
}
.shops-detail-qa .shops-qa__stat b { font-variant-numeric: tabular-nums; }
.shops-detail-qa .shops-qa__item {
    border-bottom: 1px solid var(--aw-border, #eceef2);
    padding: 1.1rem 0;
}
.shops-detail-qa .shops-qa__item:last-child { border-bottom: 0; }
.shops-detail-qa .shops-qa__qtext { font-size: 1rem; font-weight: 600; line-height: 1.35; }
.shops-detail-qa .shops-qa__author { font-size: .85rem; color: var(--aw-muted, #4b5563); }

/* Même grammaire que la réponse du vendeur, côté avis : liseré + retrait. */
.shops-detail-qa .shops-qa__answers {
    border-left: 3px solid var(--color-1, #0d6efd);
    background: var(--aw-bg-soft, #f6f7f9);
    border-radius: 0 8px 8px 0; margin-left: .25rem;
}
.shops-detail-qa .shops-qa__answers-h { color: var(--color-1, #0d6efd); font-size: .82rem; text-transform: uppercase; letter-spacing: .03em; }
.shops-detail-qa .shops-qa__vote-btn {
    border-color: var(--aw-border, rgba(0,0,0,.18));
    border-radius: 999px; padding: .1rem .7rem;
}
.shops-detail-qa .shops-qa__vote-btn:hover { background: var(--aw-hover, #f1f5fb); }

/* Note chiffrée à côté des étoiles, au-dessus du titre : les deux jetons sont
   des blocs distincts dans le gabarit, on les remet sur une seule ligne. */
.shops-detail__rating { display: inline-flex; align-items: center; vertical-align: middle; }
.shops-detail__rating-text {
    display: inline-block; vertical-align: middle;
    margin-left: .45rem; font-size: .85rem; color: var(--aw-muted, #667085);
}
.shops-detail__rating-text:empty { display: none; }

/* Même chose sur la CARTE : étoiles et note chiffrée sur une ligne. La note est
   plus discrète qu'en fiche — sur une carte, c'est le prix qui doit gagner. */
.module-card__body > .aw-composant--rating { display: inline-flex; align-items: center; vertical-align: middle; }
.shops-card__rating-text {
    display: inline-block; vertical-align: middle;
    margin-left: .35rem; font-size: .78rem; color: var(--aw-muted, #667085);
}
.shops-card__rating-text:empty { display: none; }

/* Étoiles + note chiffrée réunies sur une ligne dans la carte. Le corps de carte
   étant une COLONNE flex, un simple `inline-flex` sur le composant reste sans
   effet : ses enfants directs sont des items, ils s'empilent. D'où ce conteneur. */
.shops-card__rating-row { display: flex; align-items: center; gap: .35rem; flex-wrap: wrap; }
.shops-card__rating-row > .aw-composant--rating { display: inline-flex; align-items: center; }
.shops-card__rating-row:has(> .shops-card__rating-text:empty) > .shops-card__rating-text { display: none; }

/* Étoiles au-dessus du titre et sur la carte : un cran plus discrètes. À la
   taille par défaut (.9rem) elles pesaient autant que le titre juste dessous,
   alors qu'elles ne font que le qualifier. */
.shops-detail__rating .shops-rating,
.shops-card__rating-row .shops-rating { font-size: .78rem; gap: .08rem; }

/* ==========================================================================
   DISPONIBILITÉ PAR DÉPÔT

   C'étaient deux lignes nues sous pointillés, posées à la suite du bloc de
   vente sans rien qui les rattache : ni cadre, ni repère, et un « 4989 en
   stock » de même poids que le nom du dépôt. On en fait un bloc à part entière,
   avec le même cadre et le même rayon que le bloc de vente, et une pastille de
   quantité qui CHANGE DE COULEUR selon l'état — plein, bas, épuisé.
   ========================================================================== */
.shops-depots {
    margin: 0; padding: .35rem .15rem;
    border: 1px solid var(--aw-border, #e6e8ee); border-radius: 12px;
    background: var(--aw-card, #fff);
    font-size: .875rem;
    gap: 0;
}
.shops-depot {
    align-items: center; padding: .5rem .85rem;
    border-bottom: 1px solid var(--aw-border, #f1f3f5);
}
.shops-depot:last-child { border-bottom: 0; }
.shops-depot__name {
    display: inline-flex; align-items: center; gap: .5rem;
    min-width: 0; color: var(--aw-text, #111827);
}
.shops-depot__name i { color: var(--aw-muted, #9aa3af); width: 1rem; text-align: center; }

/* Quantité en pastille : lisible d'un coup d'œil, et son état se lit à la
   couleur sans avoir à comparer les chiffres entre eux. */
.shops-depot__qty {
    font-size: .8rem; font-weight: 600; white-space: nowrap;
    padding: .12rem .55rem; border-radius: 999px;
    background: color-mix(in srgb, #16a34a 10%, transparent); color: #15803d;
    font-variant-numeric: tabular-nums;
}
.shops-depot.is-low  .shops-depot__name i { color: #b45309; }
.shops-depot.is-low  .shops-depot__qty {
    background: color-mix(in srgb, #f59e0b 16%, transparent); color: #92400e;
}
.shops-depot.is-out { opacity: 1; }
.shops-depot.is-out .shops-depot__name,
.shops-depot.is-out .shops-depot__name i { color: var(--aw-muted, #9aa3af); }
.shops-depot.is-out .shops-depot__qty {
    background: var(--aw-bg-soft, #f1f3f5); color: var(--aw-muted, #6b7280);
}

/* ==========================================================================
   MONTÉE EN GAMME — bandeau « passez au format supérieur »

   Il n'avait AUCUNE règle : seulement des utilitaires Bootstrap, donc un
   alignement à plat, sans cadre ni fond, posé entre l'accroche et le bloc de
   vente comme une phrase égarée. C'est pourtant une proposition commerciale :
   elle doit se distinguer du corps de page sans crier plus fort que le prix.
   Teinte et liseré tirés de la couleur du thème, cadre et rayon du bloc de vente.
   ========================================================================== */
.shops-upsell-banner {
    border: 1px solid color-mix(in srgb, var(--color-1, #0d6efd) 22%, transparent);
    background: color-mix(in srgb, var(--color-1, #0d6efd) 5%, var(--aw-card, #fff));
    border-radius: 12px;
    transition: background .15s, border-color .15s;
}
.shops-upsell-banner:hover {
    background: color-mix(in srgb, var(--color-1, #0d6efd) 9%, var(--aw-card, #fff));
    border-color: color-mix(in srgb, var(--color-1, #0d6efd) 38%, transparent);
}
.shops-upsell-banner__img {
    width: 48px; height: 48px; flex: 0 0 48px;
    border-radius: 10px; object-fit: cover;
    border: 1px solid color-mix(in srgb, var(--color-1, #0d6efd) 18%, transparent);
}
.shops-upsell-banner__img i { font-size: 1.15rem; }
/* L'accroche est la promesse : elle passe devant le nom du produit visé. */
.shops-upsell-banner__lead {
    font-weight: 600; line-height: 1.3;
    color: var(--aw-text, #111827);
}
.shops-upsell-banner .text-truncate { margin-top: .1rem; }
.shops-upsell-banner strong { color: var(--color-1, #0d6efd); }
/* Le chevron avance au survol : il annonce qu'on change de page. */
.shops-upsell-banner > i:last-child { transition: transform .15s; }
.shops-upsell-banner:hover > i:last-child { transform: translateX(3px); }

/* ==========================================================================
   EN-TÊTE DE FICHE — catégorie, note, titre, accroche

   `product.js` injecte les deux actions (favori, liste cadeau) DANS le <h1> :
   elles se retrouvaient collées au dernier mot du titre, avec deux styles
   différents (gris pour l'une, bleu pour l'autre) et des cadres rectangulaires
   qui pesaient autant que le titre lui-même. On en fait deux pastilles
   discrètes, alignées au titre et rejetées en fin de ligne.
   ========================================================================== */
.shops-detail-title,
.shops-detail__title {
    display: flex; flex-wrap: wrap; align-items: center; gap: .55rem;
    line-height: 1.15; margin-bottom: .35rem;
}
.shops-detail-title > .shops-detail__actions,
.shops-detail__title > .shops-detail__actions {
    flex: 0 0 100%;              /* force sa propre ligne, SOUS le titre */
    display: flex; align-items: center; gap: .55rem;
    margin-top: .15rem;
}
.shops-detail__actions > button,
.shops-detail-title > button,
.shops-detail__title > button {
    flex: 0 0 auto;
    width: 2.1rem; height: 2.1rem; padding: 0;
    margin: 0 !important;                 /* annule le ms-2 posé par product.js */
    display: inline-flex; align-items: center; justify-content: center;
    border-radius: 999px; font-size: .8rem;
    border-color: var(--aw-border, #e6e8ee);
    color: var(--aw-muted, #667085);
    background: var(--aw-card, #fff);
    transition: color .15s, border-color .15s, background .15s;
}
.shops-detail__actions > button:hover,
.shops-detail-title > button:hover,
.shops-detail-title > button.is-on,
.shops-detail__title > button:hover,
.shops-detail__title > button.is-on {
    color: var(--color-1, #0d6efd);
    border-color: color-mix(in srgb, var(--color-1, #0d6efd) 45%, transparent);
    background: color-mix(in srgb, var(--color-1, #0d6efd) 8%, var(--aw-card, #fff));
}

/* Catégorie : une surtitre, pas une ligne de texte perdue au-dessus des étoiles. */
.shops-detail__category {
    text-transform: uppercase; letter-spacing: .06em;
    font-size: .72rem; font-weight: 600;
    color: var(--aw-muted, #8a93a5);
}

/* Accroche : c'est la phrase qu'on lit après le titre — elle mérite mieux qu'un
   gris de note de bas de page, et une largeur de lecture confortable. */
.shops-detail__excerpt {
    font-size: .95rem; line-height: 1.5; max-width: 60ch;
    color: var(--aw-muted, #4b5563);
    margin-bottom: .9rem;
}

/* Signalement : même pastille que les deux autres actions, mais il ne doit pas
   s'allumer à la couleur du thème comme un favori — ce n'est pas une adhésion. */
.shops-detail__actions > button.js-report-product:hover,
.shops-detail-title > button.js-report-product:hover,
.shops-detail__title > button.js-report-product:hover {
    color: #b42318;
    border-color: color-mix(in srgb, #b42318 45%, transparent);
    background: color-mix(in srgb, #b42318 7%, var(--aw-card, #fff));
}
/* Le signalement passe en DERNIER : l'ordre d'injection le plaçait entre le
   favori et la liste cadeau, une action négative coincée entre deux envies. */
.shops-detail__actions > .js-report-product,
.shops-detail-title > .js-report-product,
.shops-detail__title > .js-report-product { order: 2; }

/* --- Compteur de quantite (fiche produit) --------------------------------
   Le champ est borne a 999 : il doit pouvoir afficher TROIS chiffres. Bootstrap
   pose `width:1%; min-width:0` sur un `.form-control` place dans un
   `.input-group` : coince entre deux boutons de 46 px, le champ tombait a 38 px
   et rognait deja « 20 ». On dimensionne le champ, le groupe s'ajuste. */
.shops-qty-group { width: auto; flex: 0 0 auto; }
.shops-qty-group > .shops-detail-qty-input {
    flex: 0 0 auto;
    width: 3.75rem;
    min-width: 3.75rem;
    padding-left: .35rem;
    padding-right: .35rem;
}

/* buy_block : nom du groupe d'attribut (Couleur/Taille…) masquable — défaut masqué. */
.shops-buy-block--no-labels .product__axis-label{display:none}

/* --- Bloc VENDEUR de la fiche produit (.shops-seller--card) ---------------
   Il se resumait a un avatar et un nom : rien qui aide a faire confiance. Il
   porte desormais l'identite (logo, nom, certification), la note, la ville et
   la presentation de la boutique, en deux etages : identite en haut, texte et
   lien en bas. Les regles de base restent plus haut (section 2290+) ; on ne
   fait ici que la mise en page du bloc enrichi. */
.shops-seller--card {
    display: block;
    padding: .9rem 1rem;
    border-radius: 14px;
    transition: border-color .15s ease, box-shadow .15s ease;
}
.shops-seller--card:hover {
    border-color: var(--btn-2-bg, #143F6F);
    box-shadow: 0 4px 14px rgba(20, 63, 111, .07);
}
.shops-seller__head { display: flex; align-items: center; gap: .8rem; }
.shops-seller__head .shops-seller__logo { width: 48px; height: 48px; }
.shops-seller__ident { flex: 1 1 auto; min-width: 0; }
.shops-seller__ident .shops-seller__by {
    display: block;
    color: var(--aw-muted, #8a94a6);
    line-height: 1.2;
}
.shops-seller__line {
    display: flex;
    align-items: center;
    gap: .35rem;
    font-size: 1.02rem;
    line-height: 1.25;
}

/* Certification : meme pastille que la vitrine vendeurs et la carte produit. */
.shops-seller__certified { color: #16a34a; font-size: .92em; }

/* Note et ville sur une ligne, separees par un point median discret. */
.shops-seller__meta { margin-top: .25rem; gap: .5rem; }
.shops-seller__meta > * + *::before {
    content: "·";
    margin-right: .5rem;
    color: var(--aw-border, #d7dbe4);
}

.shops-seller__body { margin-top: .7rem; }
/* Presentation : deux lignes au plus, le reste est sur la vitrine du vendeur. */
.shops-seller__bio {
    margin: 0;
    font-size: .875rem;
    line-height: 1.5;
    color: var(--aw-muted, #667085);
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
}
.shops-seller__visit {
    display: inline-flex;
    align-items: center;
    gap: .35rem;
    margin-top: .5rem;
    font-size: .84rem;
    font-weight: 600;
    text-decoration: none;
    color: var(--btn-2-bg, #143F6F);
}
.shops-seller__visit i { transition: transform .15s ease; }
.shops-seller__visit:hover { text-decoration: underline; }
.shops-seller__visit:hover i { transform: translateX(3px); }

/* Sous 400 px, le logo mange la ligne du nom : on le reduit. */
@media (max-width: 400px) {
    .shops-seller__head .shops-seller__logo { width: 40px; height: 40px; }
    .shops-seller__line { font-size: .95rem; }
}

/* Repli sans logo : initiales du vendeur, comme sur le chip des cartes. */
.shops-seller__logo--ini {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    background: var(--btn-2-bg, #143F6F);
    color: #fff;
    font-weight: 700;
    font-size: .95rem;
    letter-spacing: .02em;
}

/* Vendeur en PASTILLE (dot) bas-DROITE de l'image de carte, façon bouton « ⋮ ». */
.shops-card__media .aw-composant--seller.shops-card__seller-ov{left:auto;right:.5rem;bottom:.5rem;top:auto;max-width:none}
.shops-seller--dot{display:inline-flex;line-height:0;text-decoration:none}
.shops-seller--dot .shops-seller__avatar{width:38px;height:38px;border-radius:50%;border:2px solid #fff;box-shadow:0 2px 8px rgba(0,0,0,.22)}
.shops-seller--dot .shops-seller__avatar--ini{font-size:.8rem}

/* --- Blocs MARQUE et FOURNISSEUR de la fiche -----------------------------
   Deux noms nus l'un sous l'autre ne disaient pas ce qu'ils etaient. Chaque
   bloc porte desormais son intitule, et un cadre leger le rattache visuellement
   au bloc vendeur juste au-dessus, au lieu de flotter dans la colonne. */
.shops-brand-block {
    border: 1px solid var(--aw-border, #e6e8ee);
    border-radius: 12px;
    padding: .65rem .85rem;
    background: var(--aw-card, #fff);
}
.shops-brand-block__logo--ph {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 38px;
    height: 38px;
    flex: 0 0 auto;
    border-radius: 9px;
    background: var(--aw-hover, #f1f5fb);
    color: var(--btn-2-bg, #143F6F);
    font-size: .95rem;
}
.shops-brand-block__body { display: flex; flex-direction: column; min-width: 0; }
.shops-brand-block__label {
    font-size: .68rem;
    text-transform: uppercase;
    letter-spacing: .04em;
    color: var(--aw-muted, #8a94a6);
}
.shops-brand-block__name { font-weight: 700; color: var(--aw-text, #1a1a1a); }
.shops-brand-block__link { color: inherit; }
.shops-brand-block__link i { font-size: .72em; opacity: .6; }

/* Sur une CARTE, le bloc marque reste une simple mention : ni cadre, ni
   intitule, ni pastille — la carte doit rester dense. */
.shops-card__brand .shops-brand-block {
    border: 0;
    padding: 0;
    background: none;
    margin: .15rem 0;
}
.shops-card__brand .shops-brand-block__label,
.shops-card__brand .shops-brand-block__logo--ph { display: none; }
.shops-card__brand .shops-brand-block__name { font-weight: 600; font-size: .82rem; }

/* Padding du corps de carte (module Shops). */
.shops-card .module-card__body{padding:1rem}

/* Overlay HAUT-GAUCHE de la carte : note (étoiles + score) puis badges empilés. */
.shops-card__overlay-tl{position:absolute;top:.5rem;left:.5rem;z-index:4;display:flex;flex-direction:column;gap:.35rem;align-items:flex-start;max-width:calc(100% - 4rem);pointer-events:none}
.shops-card__overlay-tl > *{pointer-events:auto}
.shops-card__overlay-tl .shops-card__rating-row{background:rgba(255,255,255,.94);border-radius:999px;padding:.15rem .55rem;box-shadow:0 1px 5px rgba(0,0,0,.14);margin:0;flex-wrap:nowrap;gap:.28rem}
/* Une seule ligne dans la pastille : étoiles un cran plus petites, le nombre
   d'avis collé (pas de retour à la ligne, marge gauche annulée). */
.shops-card__overlay-tl .shops-card__rating-row .shops-rating{font-size:.72rem;gap:.06rem}
.shops-card__overlay-tl .shops-card__rating-text{margin-left:0;white-space:nowrap;font-size:.72rem}
.shops-card__overlay-tl .shops-card__rating-row:has(> .shops-card__rating-text:empty):has(> .aw-composant--rating:empty){display:none}
.shops-card__badges-ov{display:flex;flex-direction:row;flex-wrap:wrap;gap:.3rem;align-items:center}
/* La pastille de CATALOGUE se lit À CÔTÉ des pastilles d'état, pas en dessous :
   « Nouveau » puis « SOLDES » sur la même ligne. La superposition que l'empilement
   en colonne évitait reste impossible — c'est un enroulement (wrap + gap), pas une
   rangée rigide. La note (étoiles) n'est pas une pastille mais un bloc : elle garde
   sa ligne entière, sinon les chiffres se retrouvent collés aux badges. */
.shops-card__overlay-tl{flex-direction:row;flex-wrap:wrap;align-items:center}
.shops-card__overlay-tl > .aw-composant--rating_block,
.shops-card__overlay-tl > .shops-card__rating-row{flex:0 0 100%}
/* …mais la pilule elle-même garde sa largeur de contenu : occuper toute la ligne
   la transformait en bandeau blanc en travers du visuel. */
.shops-card__overlay-tl > .aw-composant--rating_block > .shops-card__rating-row,
.shops-card__overlay-tl > .shops-card__rating-row{width:fit-content}
.shops-card__badges-ov .aw-composant:empty{display:none}

/* Score « X sur 5 » masqué (PC + mobile) : on garde les étoiles + le nombre d.avis. */
.shops-card .shops-card__rating-score{display:none}

/* Pastille vendeur : badge de vérification (✓ vert) posé sur l'avatar. */
.shops-seller--dot{position:relative}
.shops-seller__verified{position:absolute;right:-3px;bottom:-3px;color:#16a34a;background:#fff;border-radius:50%;line-height:1;font-size:.74rem;box-shadow:0 0 0 1.5px #fff}

/* Raccourci « Produits similaires » (pastille sous le titre) : la barre de
   navigation est collante, une cible amenee pile en haut du viewport passe
   dessous. On reserve sa hauteur. */
.aw-composant--shop_related,
.aw-composant--frequently_bought,
.shops-related { scroll-margin-top: 96px; }

/* ==========================================================================
   RETRAIT EN MAGASIN À PROXIMITÉ — composant fiche {store_pickup}
   Promesse commerciale rendue uniquement si un dépôt « point de retrait » a
   réellement le stock du produit. Même cadre / rayon que le bloc de vente.
   ========================================================================== */
.shops-pickup {
    border: 1px solid var(--aw-border, #e6e8ee); border-radius: 12px;
    background: var(--aw-card, #fff); padding: .6rem .85rem; margin: 0;
    font-size: .875rem;
}
.shops-pickup:empty { display: none; }
.shops-pickup__head {
    display: flex; align-items: center; gap: .5rem;
    font-weight: 600; color: var(--aw-text, #111827); margin-bottom: .4rem;
}
.shops-pickup__head i { color: var(--color-1, #d85575); }
.shops-pickup__list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: .3rem; }
.shops-pickup__item { display: flex; align-items: center; gap: .5rem; }
.shops-pickup__dot {
    flex: 0 0 auto; width: .55rem; height: .55rem; border-radius: 999px;
    background: #16a34a; box-shadow: 0 0 0 3px color-mix(in srgb, #16a34a 18%, transparent);
}
.shops-pickup__txt { color: var(--aw-text, #111827); }
.shops-pickup__txt strong { font-weight: 600; }
.shops-pickup__free {
    margin-left: auto; font-size: .8rem; color: var(--aw-muted, #6b7280);
    text-transform: lowercase;
}

/* ==========================================================================
   PRIX DE LA LIVRAISON — composant fiche {shipping_cost}
   « À partir de X € » (plus petite tranche transporteur) + rappel du franco.
   ========================================================================== */
.shops-shipcost {
    border: 1px solid var(--aw-border, #e6e8ee); border-radius: 12px;
    background: var(--aw-card, #fff); padding: .6rem .85rem; margin: 0;
    font-size: .875rem;
}
.shops-shipcost:empty { display: none; }
.shops-shipcost__head {
    display: flex; align-items: center; gap: .5rem;
    font-weight: 600; color: var(--aw-text, #111827); margin-bottom: .4rem;
}
.shops-shipcost__head i { color: var(--color-1, #d85575); }
.shops-shipcost__line { display: flex; align-items: baseline; justify-content: space-between; gap: 1rem; }
.shops-shipcost__label { color: var(--aw-muted, #6b7280); }
.shops-shipcost__price { font-weight: 700; color: var(--aw-text, #111827); font-variant-numeric: tabular-nums; }
.shops-shipcost__line--free { justify-content: flex-start; gap: .4rem; color: #15803d; margin-top: .2rem; }
.shops-shipcost__note { font-size: .78rem; color: var(--aw-muted, #9aa3af); margin-top: .35rem; }

/* --- Composants GROUPES de carte -----------------------------------------
   `rating_block` (etoiles + avis) et `flags` (promo / nouveau / rupture)
   reunissent des jetons qu'il fallait poser un a un puis envelopper a la main.
   Le composant portant lui-meme l'enveloppe, il doit se comporter comme elle :
   dans un corps de carte, qui est une COLONNE flex, un `inline-flex` sur le
   composant serait blockifie et ses enfants s'empileraient. */
.aw-composant--rating_block,
.aw-composant--flags { display: block; }

/* Pastilles d'etat : alignees, jamais empilees, et sans hauteur quand elles
   sont toutes masquees (`promo_badge` et `badge_stock` sont TOUJOURS emis avec
   `d-none`, pour que le changement de declinaison puisse les reveler). */
.shops-card__flags { display: flex; align-items: center; gap: .3rem; flex-wrap: wrap; }
.shops-card__flags:empty { display: none; }

/* Dans la pastille superposee au media, les etats restent groupes. */
.shops-card__overlay-tl .shops-card__flags,
.shops-card__overlay-tr .shops-card__flags { gap: .25rem; }

/* --- Fiche produit : la description sous l'image (grand ecran) -------------
   La rangee du haut porte trois cellules, dans l'ordre du DOM : image, achat,
   description. C'est l'ordre qu'on veut sur mobile — on voit le produit, son
   prix, puis on lit.

   Sur grand ecran, une grille reprend la main : la colonne d'achat occupe les
   deux rangees, la description se glisse SOUS L'IMAGE. En flex, la troisieme
   cellule serait partie a la ligne suivante, donc sous la PLUS HAUTE des deux
   premieres — le bloc d'achat — et le vide a gauche serait reste. */
@media (min-width: 992px) {
    .shops-hero-row {
        display: grid;
        /* `minmax(0, 1fr)` et NON `1fr` : une piste `1fr` garde un minimum
           implicite `auto`, donc elle s'élargit si son contenu l'exige. Le
           carrousel de la galerie a une largeur minimale considérable — ses
           diapositives sont côte à côte, `overflow:hidden` ne réduit pas le
           min-content — et gonflait la colonne image à 917 px sur 1320, soit
           69 %, en écrasant la colonne d'achat à 379 px. Le même gabarit
           paraissait donc avoir deux mises en page selon la galerie du produit :
           un visuel carré tenait dans sa moitié, un carrousel garni non.
           Avec un minimum de 0, les deux pistes valent exactement la moitié et
           c'est au contenu de se contraindre. */
        grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
        /* PREMIERE RANGEE A LA TAILLE DE L'IMAGE, la seconde prend le reste.
           Sans ces pistes explicites, la colonne d'achat — qui enjambe les deux
           rangees — repartissait sa hauteur excedentaire entre elles : la
           rangee de l'image gagnait ~150 px de vide, et la description se
           decrochait de la photo sans raison visible. En `max-content`, la
           rangee 1 ne depend plus que de son propre contenu.

           La seconde piste est en `1fr` et non `auto` : un element qui enjambe
           une piste FLEXIBLE est ignore au dimensionnement des pistes
           intrinseques (CSS Grid, §12.5). En `auto`, les deux pistes restaient
           intrinseques et le bloc d achat les gonflait quand meme. */
        grid-template-rows: max-content 1fr;
        column-gap: var(--bs-gutter-x, 1.5rem);
        row-gap: 0;
        align-items: start;
    }
    .shops-hero-row > .shops-hero-media { grid-column: 1; grid-row: 1; }
    .shops-hero-row > .shops-hero-buy   { grid-column: 2; grid-row: 1 / span 2; }
    .shops-hero-row > .shops-hero-desc  { grid-column: 1; grid-row: 2; }
    /* En grille, les gouttieres Bootstrap des cellules feraient doublon avec
       column-gap : on les neutralise, la grille s'en charge. */
    .shops-hero-row > [class*="col-"] {
        width: auto;
        max-width: none;
        flex: none;
        padding-left: 0;
        padding-right: 0;
    }
    /* Aucune marge ajoutee ici : la cellule de l image porte deja sa gouttiere
       (1,5 rem). En ajouter une seconde doublait l ecart sous la photo. */
    .shops-hero-row > .shops-hero-desc { padding-top: 0; }
}

/* ==========================================================================
   FIDÉLITÉ — composant fiche {loyalty}
   Points gagnés à l'achat de ce produit + invite à se connecter si déconnecté.
   ========================================================================== */
.shops-loyalty {
    border: 1px solid color-mix(in srgb, var(--color-1, #d85575) 22%, transparent);
    background: color-mix(in srgb, var(--color-1, #d85575) 6%, transparent);
    border-radius: 12px; padding: .6rem .85rem; margin: 0; font-size: .875rem;
}
.shops-loyalty:empty { display: none; }
.shops-loyalty__earn { display: flex; align-items: baseline; gap: .5rem; flex-wrap: wrap; color: var(--aw-text, #111827); }
.shops-loyalty__earn i { color: var(--color-1, #d85575); }
.shops-loyalty__earn strong, .shops-loyalty__earn { font-weight: 500; }
.shops-loyalty__value { color: var(--aw-muted, #6b7280); font-size: .82rem; }
.shops-loyalty__prompt { margin-top: .35rem; font-size: .8rem; color: var(--aw-muted, #6b7280); }
.shops-loyalty__login { font-weight: 600; color: var(--color-1, #d85575); text-decoration: underline; }
.shops-loyalty__login:hover { text-decoration: none; }

/* Note de la fiche cliquable → défile vers les avis (product.js initRatingScroll). */
.shops-rating--link { cursor: pointer; }
.shops-rating--link:hover { text-decoration: underline; text-underline-offset: 2px; }
.shops-rating--link:focus-visible { outline: 2px solid var(--color-1, #d85575); outline-offset: 2px; border-radius: 4px; }

/* --- Colonne de gauche de la fiche : sections + caracteristiques ----------
   La description et les caracteristiques se suivent desormais sous l'image.
   Sans rythme ni cadre, six titres et un tableau gris s'y alignaient a plat. */

/* Sections de description : titre discret mais tenu par un filet d'accent, et
   une largeur de ligne lisible (au-dela de ~70 caracteres, l'oeil se perd). */
.shops-hero-desc .shops-detail__section { padding: 0 !important; margin: 0 0 1.35rem; }
.shops-hero-desc .shops-detail__section:last-of-type { margin-bottom: 1.75rem; }
.shops-hero-desc .shops-detail__section h2,
.shops-hero-desc .shops-detail__section h3,
.shops-hero-desc .shops-detail__section h4 {
    position: relative;
    margin: 0 0 .5rem;
    padding-left: .7rem;
    font-size: 1.05rem;
    font-weight: 700;
    line-height: 1.3;
    color: var(--aw-text, #1a1a1a);
}
.shops-hero-desc .shops-detail__section h2::before,
.shops-hero-desc .shops-detail__section h3::before,
.shops-hero-desc .shops-detail__section h4::before {
    content: "";
    position: absolute;
    left: 0;
    top: .18em;
    bottom: .18em;
    width: 3px;
    border-radius: 2px;
    background: var(--color-1, #d85575);
}
.shops-hero-desc .shops-detail__section p {
    margin: 0 0 .5rem;
    max-width: 62ch;
    line-height: 1.6;
    color: var(--aw-muted, #4b5563);
}
.shops-hero-desc .shops-detail__section p:last-child { margin-bottom: 0; }

/* Caracteristiques : une carte, des lignes alternees, l'intitule en retrait et
   la valeur en avant. Le tableau nu se confondait avec la description. */
.shops-hero-desc .shops-attrs {
    margin: 0;
    /* Colonne des intitules un peu plus large : dans une demi-colonne,
       `max-content` la serrait et « Compatible lave-vaisselle » passait sur
       trois lignes en face d une valeur d un mot. */
    grid-template-columns: minmax(150px, 40%) 1fr;
    border: 1px solid var(--aw-border, #e6e8ee);
    border-radius: 12px;
    background: var(--aw-card, #fff);
    overflow: hidden;
    gap: 0;
}
.shops-hero-desc .shops-attrs dt,
.shops-hero-desc .shops-attrs dd {
    padding: .6rem .9rem;
    border-top: 1px solid var(--aw-border, #eceef2);
    align-self: stretch;
}
.shops-hero-desc .shops-attrs dt {
    font-size: .78rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: .03em;
    color: var(--aw-muted, #8a94a6);
    background: color-mix(in srgb, var(--aw-border, #e6e8ee) 22%, transparent);
}
.shops-hero-desc .shops-attrs dd { font-weight: 600; color: var(--aw-text, #1a1a1a); }

/* Une URL de fiche technique ne se lit pas : on la nomme, et on la borne. */
.shops-hero-desc .shops-attrs dd a {
    display: inline-block;
    max-width: 100%;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    vertical-align: bottom;
    color: var(--btn-2-bg, #143F6F);
}

@media (max-width: 575.98px) {
    .shops-hero-desc .shops-attrs { grid-template-columns: 1fr; }
    .shops-hero-desc .shops-attrs dt { border-top: 1px solid var(--aw-border, #eceef2); }
    .shops-hero-desc .shops-attrs dd { border-top: 0; padding-top: 0; }
}

/* Fidelite dans le bloc de vente : collee au bouton, sans cadre redondant —
   le bloc en porte deja un. */
.shops-sale-block__loyalty { margin-top: .6rem; }
.shops-sale-block__loyalty .shops-loyalty { margin: 0; }

/* Lien vers la page du programme de fidelite, a la suite des points gagnes. */
.shops-loyalty__more {
    display: inline-flex;
    align-items: center;
    gap: .25rem;
    margin-left: .35rem;
    font-weight: 600;
    white-space: nowrap;
    text-decoration: none;
    color: var(--color-1, #d85575);
}
.shops-loyalty__more:hover { text-decoration: underline; }
.shops-loyalty__more i { font-size: .78em; transition: transform .15s ease; }
.shops-loyalty__more:hover i { transform: translateX(2px); }

/* Sélecteur multipanier (pastille dropdown) : nom tronqué pour ne pas déborder,
   et sur mobile on masque le total + on serre le nom → ne colle plus au ✕. */
.cart-switch .dropdown-toggle { max-width: 100%; display: inline-flex; align-items: center; }
.cart-switch__name {
    display: inline-block; max-width: 140px; overflow: hidden;
    text-overflow: ellipsis; white-space: nowrap; vertical-align: bottom;
}
.cart-switch__meta { white-space: nowrap; margin-left: .2rem; }
@media (max-width: 575.98px) {
    #cart-switch-oc .dropdown-toggle { max-width: 46vw; }
    #cart-switch-oc .cart-switch__name { max-width: 92px; }
    #cart-switch-oc .cart-switch__total { display: none; }
}

/* --- Bandeau de reassurance sur petit ecran -------------------------------
   Les trois arguments tiennent sur UNE ligne, y compris a 360 px : empiles,
   ils poussaient le reste de la page de deux ecrans pour dire trois choses
   courtes. On reduit l'icone et le libelle plutot que le nombre de colonnes. */
@media (max-width: 575.98px) {
    .shops-reassurance > .col { padding-left: .35rem; padding-right: .35rem; }
    .shops-reassurance i { font-size: 21px !important; margin-bottom: 4px !important; }
    .shops-reassurance .fw-semibold {
        font-size: .69rem;
        line-height: 1.25;
        /* Une cesure propre plutot qu'un mot qui deborde de sa colonne. */
        overflow-wrap: anywhere;
        hyphens: auto;
    }
}

/* ==========================================================================
   PAGE LIVRAISON — transporteurs, zones, tranches (catalogue/livraison)
   Tout y est deduit du parametrage : la mise en page doit donc rester lisible
   avec un seul transporteur a tarif unique comme avec huit barèmes.
   ========================================================================== */
.shops-shipping__country { margin: 1.25rem 0 0; }

.shops-shipping__list { display: grid; gap: 1rem; }
.shops-shipping__carrier {
    border: 1px solid var(--aw-border, #e6e8ee);
    border-radius: 14px;
    background: var(--aw-card, #fff);
    padding: 1.1rem 1.25rem;
}
.shops-shipping__head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 1rem;
    flex-wrap: wrap;
}
.shops-shipping__ident { display: flex; align-items: center; gap: .85rem; min-width: 0; }
.shops-shipping__logo { width: 46px; height: 46px; object-fit: contain; flex: 0 0 auto; }
.shops-shipping__logo--ph {
    display: inline-flex; align-items: center; justify-content: center;
    border-radius: 11px;
    background: var(--aw-hover, #f1f5fb);
    color: var(--btn-2-bg, #143F6F);
    font-size: 1.15rem;
}
.shops-shipping__name { font-weight: 700; font-size: 1.05rem; line-height: 1.25; }
.shops-shipping__meta {
    display: flex; flex-wrap: wrap; gap: .25rem .9rem;
    margin-top: .2rem; font-size: .84rem; color: var(--aw-muted, #667085);
}
.shops-shipping__franco {
    flex: 0 0 auto;
    padding: .4rem .75rem;
    border-radius: 999px;
    background: color-mix(in srgb, #16a34a 10%, transparent);
    color: #15803d;
    font-size: .85rem;
}
.shops-shipping__temps { display: flex; gap: .4rem; flex-wrap: wrap; margin-top: .7rem; }
.shops-shipping__temp {
    display: inline-flex; align-items: center; gap: .3rem;
    padding: .2rem .6rem; border-radius: 999px;
    background: var(--aw-hover, #f1f5fb);
    font-size: .78rem; color: var(--aw-muted, #4b5563);
}

.shops-shipping__grid { margin-top: .9rem; }
.shops-shipping__gridhead {
    font-size: .72rem; font-weight: 700; text-transform: uppercase; letter-spacing: .04em;
    color: var(--aw-muted, #8a94a6); margin-bottom: .35rem;
}
.shops-shipping__table { width: 100%; border-collapse: collapse; font-size: .9rem; }
.shops-shipping__table th,
.shops-shipping__table td { padding: .5rem .25rem; border-top: 1px solid var(--aw-border, #eceef2); }
.shops-shipping__table tr:first-child th,
.shops-shipping__table tr:first-child td { border-top: 0; }
.shops-shipping__table th { font-weight: 500; color: var(--aw-muted, #4b5563); text-align: left; }
.shops-shipping__table td { text-align: right; font-weight: 700; white-space: nowrap; }
.shops-shipping__offert { color: #15803d; }
.shops-shipping__free { margin: .8rem 0 0; color: #15803d; font-weight: 600; }

/* Zones : repliees par defaut, sauf celle du pays affiche. */
.shops-shipping__zones { display: grid; gap: .5rem; }
.shops-shipping__zone {
    border: 1px solid var(--aw-border, #e6e8ee);
    border-radius: 12px;
    background: var(--aw-card, #fff);
}
.shops-shipping__zone > summary {
    display: flex; align-items: center; gap: .5rem;
    padding: .75rem 1rem; cursor: pointer; font-weight: 600; list-style: none;
}
.shops-shipping__zone > summary::-webkit-details-marker { display: none; }
.shops-shipping__zone > summary::before {
    content: "+"; width: 1em; color: var(--color-1, #d85575); font-weight: 700;
}
.shops-shipping__zone[open] > summary::before { content: "\2212"; }
.shops-shipping__count { margin-left: auto; font-weight: 400; font-size: .82rem; color: var(--aw-muted, #8a94a6); }
.shops-shipping__countries {
    display: flex; flex-wrap: wrap; gap: .3rem;
    padding: 0 1rem 1rem;
}
.shops-shipping__country-link {
    padding: .2rem .6rem; border-radius: 999px;
    border: 1px solid var(--aw-border, #e6e8ee);
    font-size: .82rem; text-decoration: none; color: var(--aw-muted, #4b5563);
}
.shops-shipping__country-link:hover { border-color: var(--btn-2-bg, #143F6F); color: var(--btn-2-bg, #143F6F); }
.shops-shipping__country-link.is-on {
    background: var(--btn-2-bg, #143F6F); border-color: var(--btn-2-bg, #143F6F); color: #fff;
}

@media (max-width: 575.98px) {
    .shops-shipping__head { align-items: flex-start; }
    .shops-shipping__franco { width: 100%; text-align: center; }
}


/* ── Pastille de CATALOGUE ─────────────────────────────────────────────────
   Portée par le catalogue auquel le produit appartient (« Soldes d'été »),
   jamais saisie sur le produit. Elle se pose avec les pastilles d'état
   (« −20 % », « Nouveau ») : un marqueur de plus au même endroit se lit d'un
   coup d'œil, éparpillé aux quatre coins il ne se lit plus.
   Les couleurs viennent du réglage et arrivent en `style` inline : on ne fixe
   ici que le repli, pour rester lisible quand aucune couleur n'est choisie. */
/* Pastille de catalogue : c'est un LIEN vers la page de l'opération. Le
   soulignement du thème la déformerait, et la pile de pastilles est en
   `pointer-events:none` (pour ne pas voler le clic du lien qui couvre l'image) —
   il faut donc rendre le clic à celle-ci, et à elle seule. */
.shops-badge--catalogue { background: var(--color-1, #d85575); color: #fff; }
a.shops-badge--catalogue { text-decoration: none; pointer-events: auto; }
a.shops-badge--catalogue:hover,
a.shops-badge--catalogue:focus-visible { filter: brightness(1.12); text-decoration: none; }

/* « Tout effacer » : une puce, mais un LIEN — on la distingue des valeurs
   cochées (fond neutre, pas de fond « actif ») pour qu'on ne la prenne pas
   pour un filtre de plus. */
.shops-facets-chip--reset {
    text-decoration: none;
    color: var(--bs-secondary-color, #6c757d);
    border-style: dashed;
}
.shops-facets-chip--reset:hover { color: var(--btn-2-bg, #111); }

/* ═══ TABLEAUX DE DONNÉES PRODUIT ═══════════════════════════════════════════
   Rendu du composant « Tableaux de données » (nutritionnel, caractéristiques).
   Deux présentations pour la même donnée : `table` (deux colonnes, avec sa
   légende) et `list` (paires libellé/valeur). Les couleurs viennent des
   variables du thème — un tableau doit se fondre dans la charte, pas imposer
   la sienne. */
.shops-datatable-block { margin: 1.75rem 0; }
.shops-datatable-block:empty { display: none; }

.shops-datatable__title {
    font-size: .78rem;
    font-weight: 700;
    letter-spacing: .08em;
    text-transform: uppercase;
    margin: 0 0 .7rem;
    color: var(--body-color, #1b2130);
}

table.shops-datatable {
    width: 100%;
    border-collapse: collapse;
    font-size: .92rem;
}
table.shops-datatable caption {
    caption-side: top;
    text-align: left;
    padding: .55rem .85rem;
    font-weight: 600;
    font-size: .85rem;
    background: var(--bs-tertiary-bg, #f4f6f9);
    color: var(--body-color, #1b2130);
    border-radius: 6px 6px 0 0;
}
table.shops-datatable th,
table.shops-datatable td {
    padding: .65rem .85rem;
    border-bottom: 1px solid var(--bs-border-color, #eceef2);
}
table.shops-datatable th {
    text-align: left;
    font-weight: 400;
    color: var(--body-color, #3d4756);
}
table.shops-datatable td {
    text-align: right;
    white-space: nowrap;
    width: 34%;
}
/* Une ligne sur deux : la lecture d'un tableau de sept lignes chiffrées
   décroche sans ce repère. */
table.shops-datatable tbody tr:nth-child(even) { background: var(--bs-tertiary-bg, #fafbfc); }
/* « dont sucres » se lit sous « Glucides » : le retrait le dit visuellement,
   `scope="row"` le dit aux lecteurs d'écran. */
table.shops-datatable tr.is-sub th { padding-left: 1.9rem; opacity: .85; }

ul.shops-datatable--list {
    list-style: none;
    margin: 0;
    padding: 0;
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
    gap: .65rem 1.4rem;
}
.shops-datatable__item { display: flex; flex-direction: column; gap: .12rem; font-size: .92rem; }
.shops-datatable__label { font-size: .8rem; opacity: .7; }
.shops-datatable__value { font-weight: 600; }

@media (max-width: 575.98px) {
    table.shops-datatable { font-size: .86rem; }
    table.shops-datatable th,
    table.shops-datatable td { padding: .55rem .6rem; }
    table.shops-datatable tr.is-sub th { padding-left: 1.3rem; }
}

/* ─────────────────────────────────────────────────────────────────────────
   Panneau de RÉSERVATION (composant gabarit `booking`) — durée · créneau · récap.
   Accent = --bs-primary (bordeaux). N'habille QUE l'enveloppe : le bloc d'achat
   qu'il contient garde ses propres styles natifs.
   ───────────────────────────────────────────────────────────────────────── */
.shops-booking-panel { --shops-accent: var(--bs-primary, #7a1f3d); }
.shops-bp__section { margin-bottom: 1rem; }
.shops-bp__label {
    font-size: .72rem; font-weight: 700; letter-spacing: .08em; text-transform: uppercase;
    color: #8a7681; margin-bottom: .5rem;
}
.shops-bp__durs { display: grid; grid-template-columns: repeat(4, 1fr); gap: .5rem; }
.shops-bp__dur {
    display: flex; flex-direction: column; align-items: center; gap: .1rem;
    border: 1px solid #e3d9d4; background: #fff; border-radius: 10px;
    padding: .55rem .2rem; cursor: pointer; line-height: 1.15; transition: border-color .12s, background .12s;
}
.shops-bp__dur:hover { border-color: #c9b6bd; }
.shops-bp__dur.is-active {
    border-color: var(--shops-accent); background: color-mix(in srgb, var(--shops-accent) 8%, #fff);
    color: var(--shops-accent);
}
.shops-bp__dur-h { font-size: .92rem; font-weight: 600; }
.shops-bp__dur-p { font-size: .72rem; color: #8a7681; }
.shops-bp__dur.is-active .shops-bp__dur-p { color: var(--shops-accent); }
.shops-bp__hint { font-size: .76rem; color: #8a7681; margin: .5rem 0 0; }
.shops-bp__fees {
    margin-top: .9rem; padding-top: .8rem; border-top: 1px solid #eee5e0;
    display: flex; flex-direction: column; gap: .3rem;
}
@media (max-width: 575px) {
    .shops-bp__durs { grid-template-columns: repeat(2, 1fr); }
}

/* ─────────────────────────────────────────────────────────────────────────
   Galerie MOSAÏQUE (composant `gallery_mosaic`) — 1 grande + 2×2, façon séjour.
   ───────────────────────────────────────────────────────────────────────── */
.shops-mosaic {
    display: grid; grid-template-columns: repeat(4, 1fr); grid-template-rows: 1fr 1fr;
    gap: 8px; aspect-ratio: 2 / 1; border-radius: 16px; overflow: hidden;
}
.shops-mosaic__tile {
    padding: 0; border: 0; margin: 0; cursor: pointer; overflow: hidden;
    position: relative; background: #f1f3f5; min-height: 0;
}
.shops-mosaic__tile img { transition: transform .35s ease; }
.shops-mosaic__tile:hover img { transform: scale(1.04); }
.shops-mosaic__tile--big { grid-column: 1 / 3; grid-row: 1 / 3; }
.shops-mosaic__more {
    position: absolute; inset: 0; display: flex; align-items: center; justify-content: center;
    gap: .5rem; background: rgba(20, 16, 18, .44); color: #fff; font-weight: 600; font-size: .9rem;
}
/* 5+ images : la mosaïque pleine. Moins d'images : la grande occupe tout. */
.shops-mosaic[data-count="1"] { grid-template-columns: 1fr; grid-template-rows: 1fr; aspect-ratio: 16 / 10; }
.shops-mosaic[data-count="1"] .shops-mosaic__tile--big { grid-column: 1; grid-row: 1; }
@media (max-width: 767px) {
    .shops-mosaic { grid-template-columns: 1fr 1fr; aspect-ratio: 1 / 1; }
    .shops-mosaic__tile--big { grid-column: 1 / 3; grid-row: 1; aspect-ratio: 16 / 10; }
}
/* Visionneuse */
.shops-lightbox {
    position: fixed; inset: 0; z-index: 3000; background: rgba(12, 9, 11, .92);
    display: flex; align-items: center; justify-content: center; flex-direction: column;
}
.shops-lightbox__img { max-width: 92vw; max-height: 82vh; object-fit: contain; border-radius: 8px; }
.shops-lightbox__close, .shops-lightbox__nav {
    position: absolute; background: rgba(255, 255, 255, .12); color: #fff; border: 0;
    width: 46px; height: 46px; border-radius: 999px; cursor: pointer; font-size: 20px;
    display: flex; align-items: center; justify-content: center;
}
.shops-lightbox__close { top: 20px; right: 20px; }
.shops-lightbox__nav--prev { left: 20px; top: 50%; transform: translateY(-50%); }
.shops-lightbox__nav--next { right: 20px; top: 50%; transform: translateY(-50%); }
.shops-lightbox__count { color: rgba(255, 255, 255, .8); font-size: .85rem; margin-top: 14px; }

/* Occupation fixe du panneau de réservation (loveroom : « Pour 2 personnes »). */
.shops-bp__occ {
    display: inline-flex; align-items: center; gap: .4rem; margin-bottom: .9rem;
    font-size: .9rem; font-weight: 600; color: #5b6570;
    background: #f5ece8; border-radius: 999px; padding: .35rem .8rem;
}
.shops-bp__occ svg { color: var(--shops-accent, #7a1f3d); }

/* Sélecteur de créneau du panneau (mode horaire). */
.shops-bp__creneau { margin-top: .9rem; }
.shops-bp__date { max-width: 220px; margin-bottom: .7rem; }
.shops-bp__slots { display: flex; flex-wrap: wrap; gap: .5rem; }
.shops-bp__slots-hint { font-size: .82rem; color: #8a7681; margin: .2rem 0; }
.shops-bp__slot {
    display: flex; flex-direction: column; align-items: flex-start; gap: .05rem;
    border: 1.5px solid #e3d9d4; background: #fff; border-radius: 10px;
    padding: .5rem .8rem; cursor: pointer; line-height: 1.2; font-family: inherit;
}
.shops-bp__slot b { font-size: .9rem; }
.shops-bp__slot span { font-size: .74rem; color: #8a7681; }
.shops-bp__slot:hover { border-color: #c9b6bd; }
.shops-bp__slot.is-sel { border-color: var(--shops-accent, #7a1f3d); background: color-mix(in srgb, var(--shops-accent, #7a1f3d) 8%, #fff); color: var(--shops-accent, #7a1f3d); }
.shops-bp__slot.is-sel span { color: var(--shops-accent, #7a1f3d); }
.shops-bp__slot.is-off { opacity: .45; cursor: not-allowed; text-decoration: line-through; }

/* ─────────────────────────────────────────────────────────────────────────
   Composants FICHE HÉBERGEMENT : localisation, infos pratiques, à proximité.
   ───────────────────────────────────────────────────────────────────────── */
.shops-loc, .shops-practical, .shops-nearby { margin-top: 1.6rem; }
.shops-loc__title, .shops-practical__title, .shops-nearby__title {
    font-size: 1.15rem; font-weight: 650; margin: 0 0 .7rem; color: #24303a;
}
.shops-loc__addr { color: #5b6570; font-size: .95rem; margin: 0 0 .7rem; }
.shops-loc__addr i { color: var(--bs-primary, #7a1f3d); margin-right: .3rem; }
.shops-loc__map { height: 340px; border-radius: 14px; overflow: hidden; border: 1px solid #e6e9ed; background: #e9edf0; }
.shops-loc__fallback { display: flex; height: 100%; align-items: center; justify-content: center; color: #7a828c; }
.shops-practical__table { width: 100%; border-collapse: collapse; }
.shops-practical__table th, .shops-practical__table td {
    text-align: left; padding: .6rem .2rem; border-bottom: 1px solid #eef1f4; font-size: .95rem; vertical-align: top;
}
.shops-practical__table th { color: #7a828c; font-weight: 600; width: 42%; }
.shops-practical__table td { color: #24303a; }

/* Équipements : valeurs + « Tous les équipements » (aperçu essentiels). */
.shops-amenity__val { font-weight: 600; color: #24303a; }
.shops-amenities__more { margin-top: .7rem; }
.shops-amenities__more > summary {
    cursor: pointer; font-weight: 600; color: var(--bs-primary, #7a1f3d); list-style: none;
    display: inline-flex; align-items: center; gap: .45rem; padding: .5rem .9rem;
    border: 1px solid #e6e9ed; border-radius: 10px; user-select: none;
}
.shops-amenities__more > summary::-webkit-details-marker { display: none; }
.shops-amenities__more > summary::after { content: "＋"; font-weight: 700; }
.shops-amenities__more[open] > summary::after { content: "－"; }
.shops-amenities__morebody { margin-top: .9rem; }
.shops-amenities__h--rule { margin: 1rem 0 .5rem; }
