@charset "UTF-8";
/* ==========================================================================
   3B — Deux encres sur papier
   Système visuel des Sommeliers Cavistes. Voir DESIGN.md à la racine.

   FICHIER GÉNÉRÉ — ne pas éditer directement.
   Les sources vivent dans assets/css/parts/, un fichier par composant.
   Régénérer avec : node themes/les3b/build/construire-css.mjs

   Cette feuille reste volontairement hors couche de cascade. Le thème acheté
   est importé en couche `vendor` par theme.css : ses règles perdent donc
   d'office. Les modules, eux, publient hors couche ; y ranger cette feuille
   lui ferait perdre ses arbitrages face à eux.
   ========================================================================== */

/* ===== 00-fondations.css ================================================= */

/* ==========================================================================
   3B — Deux encres sur papier
   Système visuel des Sommeliers Cavistes. Voir DESIGN.md à la racine.

   FICHIER GÉNÉRÉ — ne pas éditer directement.
   Les sources vivent dans assets/css/parts/, un fichier par composant.
   Régénérer avec : node themes/les3b/build/construire-css.mjs

   Cette feuille reste volontairement hors couche de cascade. Le thème acheté
   est importé en couche `vendor` par theme.css : ses règles perdent donc
   d'office. Les modules, eux, publient hors couche ; y ranger cette feuille
   lui ferait perdre ses arbitrages face à eux.
   ========================================================================== */
/* ===== 00-fondations.css ================================================= */
/* ==========================================================================
   3B — Deux encres sur papier
   Système visuel des Sommeliers Cavistes. Voir DESIGN.md à la racine.

   Cette feuille reste volontairement hors couche de cascade. Le thème acheté
   (theme.css, custom.css, owl.carousel.css) est, lui, importé en couche
   `vendor` par themes/les3b/assets/css/theme.css : ses règles perdent donc
   d'office, aussi spécifiques soient-elles.

   Les modules (pm_advancedtopmenu, ps_searchbar, wishlist…) publient en
   revanche leurs styles hors couche, et une règle hors couche l'emporte sur
   toute règle en couche. Y placer 3b.css reviendrait donc à lui faire perdre
   tous ses arbitrages face aux modules — d'où ce choix. Face à eux, 3b.css
   garde deux atouts : il est chargé en dernier, et la spécificité s'applique
   normalement.
   ========================================================================== */
/* ==========================================================================
   3B — Deux encres sur papier
   Système visuel des Sommeliers Cavistes. Voir DESIGN.md à la racine.

   Chargé après custom.css (priorité 1100, cf. config/theme.yml).
   Ne jamais éditer theme.css : il est écrasé à chaque mise à jour du thème.
   ========================================================================== */
/* --------------------------------------------------------------------------
   1. Police — Archivo variable, auto-hébergée
   Un seul fichier par sous-ensemble remplace les 5 familles Google Fonts
   chargées jusqu'ici en requête tierce bloquante.
   -------------------------------------------------------------------------- */
@font-face {
  font-family: "Archivo 3B";
  src: url("../fonts/archivo-latin.woff2") format("woff2-variations"),
       url("../fonts/archivo-latin.woff2") format("woff2");
  font-weight: 100 900;
  font-stretch: 62% 125%;
  font-style: normal;
  font-display: swap;
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6,
                 U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F,
                 U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: "Archivo 3B";
  src: url("../fonts/archivo-latin-ext.woff2") format("woff2-variations"),
       url("../fonts/archivo-latin-ext.woff2") format("woff2");
  font-weight: 100 900;
  font-stretch: 62% 125%;
  font-style: normal;
  font-display: swap;
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7,
                 U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF,
                 U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0,
                 U+2113, U+2C60-2C7F, U+A720-A7FF;
}

/* --------------------------------------------------------------------------
   2. Jetons
   -------------------------------------------------------------------------- */
:root {
  /* Encres — neutres teintés vers la teinte de marque (H 90), jamais de gris pur */
  --b3-encre:        oklch(0.19 0.012 90);
  --b3-encre-douce:  oklch(0.45 0.014 90);
  --b3-jaune:        oklch(0.8624 0.1745 90);
  --b3-jaune-fonce:  oklch(0.78 0.163 88);

  /* Papiers */
  --b3-papier:       oklch(0.975 0.008 90);
  --b3-papier-2:     oklch(0.94 0.011 90);

  /* Traits */
  --b3-trait:        oklch(0.85 0.010 90);
  --b3-trait-fort:   oklch(0.58 0.014 90);

  /* Sémantique — usage strict et rare */
  --b3-alerte:       oklch(0.48 0.17 27);
  --b3-succes:       oklch(0.50 0.10 150);

  /* Typographie */
  --b3-font: "Archivo 3B", "Archivo", -apple-system, BlinkMacSystemFont, "Segoe UI", system-ui, sans-serif;

  /* Espacement — base 4 */
  --b3-space-3xs: 4px;
  --b3-space-2xs: 8px;
  --b3-space-xs:  12px;
  --b3-space-sm:  16px;
  --b3-space-md:  24px;
  --b3-space-lg:  32px;
  --b3-space-xl:  48px;
  --b3-space-2xl: 64px;
  --b3-space-3xl: 96px;

  /* Arrondis — écho à l'épaule d'une bouteille et au tampon du logo */
  --b3-radius-sm: 10px;
  --b3-radius: 18px;
  --b3-radius-lg: 28px;
  --b3-radius-pill: 999px;

  /* Mouvement — ease-out-quart, sans rebond */
  --b3-ease: cubic-bezier(0.165, 0.84, 0.44, 1);
  --b3-dur-fast: 180ms;
  --b3-dur-base: 260ms;
  --b3-dur-slow: 320ms;
}

/* --------------------------------------------------------------------------
   3. Base
   -------------------------------------------------------------------------- */
/* `100vw` compte la largeur de la barre de défilement : les aplats qui sortent
   du conteneur dépassaient donc d'une quinzaine de pixels et provoquaient un
   défilement horizontal parasite, très pénalisant au doigt.
   `clip` plutôt que `hidden` : il ne crée pas de conteneur de défilement et
   laisse donc `position: sticky` fonctionner dans les descendants.

   Note : les panneaux du méga-menu (`.adtm_sub`, module pm_advancedtopmenu)
   débordent aussi, structurellement, jusqu'à 290 px en tablette. C'est un
   défaut du thème antérieur à cette refonte, à traiter avec le chantier
   responsive du sprint. */
html {
  overflow-x: clip;
}

body,
body.lang-fr {
  overflow-x: clip;
  font-family: var(--b3-font);
  font-optical-sizing: auto;
  font-kerning: normal;
  background-color: var(--b3-papier);
  color: var(--b3-encre);
  -webkit-font-smoothing: antialiased;
}

body h1, body h2, body h3, body h4, body h5, body h6,
body .h1, body .h2, body .h3, body .h4, body .h5, body .h6,
body .title, body .main-title, body .column_wrap_title,
body input, body select, body textarea, body button, body .btn {
  font-family: var(--b3-font);
}

body h1, body h2, body h3,
body .h1, body .h2, body .h3 {
  text-wrap: balance;
  color: var(--b3-encre);
}

/* Focus visible, jamais supprimé. */
body a:focus-visible,
body button:focus-visible,
body input:focus-visible,
body select:focus-visible,
body textarea:focus-visible,
body [tabindex]:focus-visible {
  outline: 3px solid var(--b3-encre);
  outline-offset: 2px;
}

/* Le thème centre le contenu des vignettes à plusieurs endroits et avec des
   sélecteurs plus spécifiques. Un alignement unique posé sur la carte entière
   évite d'en poursuivre chaque variante. */
body .b3-card,
body .b3-card * {
  text-align: left;
}

/* --------------------------------------------------------------------------
   9. Nettoyage du thème acheté
   Le rouge #b23c4a n'appartient pas à la marque. Il ne subsiste que comme
   couleur d'alerte, sur les messages d'erreur.
   -------------------------------------------------------------------------- */
body a {
  color: var(--b3-encre);
}

body a:hover,
body a:focus {
  color: var(--b3-encre);
}

body .main-title,
body .featured-products .h2,
body .product-accessories .h2 {
  font-weight: 800;
  font-stretch: 78%;
  font-size: clamp(1.5rem, 3vw, 2.25rem);
  line-height: 1.05;
  letter-spacing: -0.015em;
  text-transform: uppercase;
  color: var(--b3-encre);
}

/* Les séparateurs décoratifs en losange du thème sortent. */
body .main-title .subtitle-part,
body .title .subtitle-part {
  display: none;
}

/* --------------------------------------------------------------------------
   10. Mouvement réduit
   -------------------------------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
*,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
}


/* ===== 01-signature.css ================================================== */

@charset "UTF-8";
/* ==========================================================================
   Gestes de marque

   Les cinq signatures définies par DESIGN.md : la trame imprimée des aplats
   d'encre, le surligneur, le décalage de repérage, le tampon circulaire et le
   filet double. Ils n'appartiennent à aucun composant — n'importe quelle
   section peut les porter — d'où ce fichier à part, chargé avant les
   composants qui s'en servent.
   ========================================================================== */

/* ===== 09-divers.css ===================================================== */
/* --------------------------------------------------------------------------
   4. Gestes signature
   Cinq gestes empruntés à l'affiche sérigraphiée. Sans eux, le système
   retombe dans le brutalisme générique.
   -------------------------------------------------------------------------- */
/* 4.1 — La trame. Un aplat noir devient de l'encre, pas un rectangle CSS. */
.b3-trame {
  position: relative;
  isolation: isolate;
}

.b3-trame::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  background-image: radial-gradient(var(--b3-papier) 0.5px, transparent 0.5px);
  background-size: 4px 4px;
  opacity: 0.07;
}

/* 4.2 — Le surligneur. Le geste de marque le plus reconnaissable du site,
   aujourd'hui figé dans des images : ici c'est du texte, donc sélectionnable,
   traduisible et indexable. */
.b3-marker {
  display: inline-block;
  padding: 0.08em 0.38em;
  background-color: var(--b3-jaune);
  color: var(--b3-encre);
  transform: rotate(-1.5deg);
}

/* 4.3 — Le décalage de repérage, comme une impression mal calée.
   Réservé aux titres de section, jamais deux fois sur le même écran. */
.b3-offset {
  text-shadow: 4px 4px 0 var(--b3-jaune);
}

/* 4.4 — Le tampon, hérité du logo circulaire. */
.b3-stamp {
  display: grid;
  place-items: center;
  aspect-ratio: 1;
  min-width: 46px;
  padding: var(--b3-space-2xs);
  border-radius: 50%;
  background-color: var(--b3-jaune);
  color: var(--b3-encre);
  font-size: 0.625rem;
  font-weight: 700;
  line-height: 1.05;
  text-align: center;
  text-transform: uppercase;
  letter-spacing: 0.04em;
}

/* 4.5 — Le filet double. Remplace les losanges décoratifs du thème acheté. */
.b3-rule {
  position: relative;
  height: 4px;
  border: 0;
  background-color: var(--b3-encre);
  margin: var(--b3-space-lg) 0;
}

.b3-rule::before {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  top: -7px;
  height: 1px;
  background-color: var(--b3-encre);
}


/* ===== 01-typographie.css ================================================ */

/* ===== 01-typographie.css ================================================ */
/* Un titre de page vide ne doit pas réserver d'espace. Le <h1> reste dans le
   balisage — le retirer conditionnellement en Smarty vide la variable et
   supprime le titre de toutes les pages — mais son en-tête se replie. */
.page-header:has(h1:empty),
.page-header h1:empty {
  display: none;
}


/* ===== 02-boutons.css ==================================================== */

/* ===== 02-boutons.css ==================================================== */
/* --------------------------------------------------------------------------
   5. Boutons
   -------------------------------------------------------------------------- */
body .btn-primary,
body .btn.btn-primary,
body button.btn-primary {
  min-height: 44px;
  padding: var(--b3-space-xs) var(--b3-space-md);
  border: 0;
  border-radius: var(--b3-radius-pill);
  background-color: var(--b3-jaune);
  color: var(--b3-encre);
  font-weight: 700;
  font-size: 0.875rem;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  box-shadow: none;
  transition: background-color var(--b3-dur-fast) var(--b3-ease);
}

body .btn-primary:hover,
body .btn-primary:focus,
body .btn.btn-primary:hover {
  background-color: var(--b3-jaune-fonce);
  color: var(--b3-encre);
  box-shadow: none;
}

body .btn-secondary,
body .btn.btn-secondary {
  min-height: 44px;
  border: 2px solid var(--b3-encre);
  border-radius: var(--b3-radius-pill);
  background-color: transparent;
  color: var(--b3-encre);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  box-shadow: none;
}

/* 9bis.2 — Boutons de composition. */
.b3-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 48px;
  padding: var(--b3-space-xs) var(--b3-space-lg);
  border: 2px solid var(--b3-encre);
  border-radius: var(--b3-radius-pill);
  font-size: 0.8125rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  text-decoration: none;
  transition: background-color var(--b3-dur-fast) var(--b3-ease),
              color var(--b3-dur-fast) var(--b3-ease);
}

.b3-btn--ink {
  background-color: var(--b3-encre);
  color: var(--b3-papier);
}

.b3-btn--ink:hover,
.b3-btn--ink:focus {
  background-color: transparent;
  color: var(--b3-encre);
}

.b3-btn--ghost {
  background-color: transparent;
  color: var(--b3-encre);
}

.b3-btn--ghost:hover,
.b3-btn--ghost:focus {
  background-color: var(--b3-encre);
  color: var(--b3-papier);
}

.b3-panel__form .b3-btn {
  margin-top: var(--b3-space-sm);
}

/* Cases à cocher dessinées : celles du navigateur étaient minuscules et
   grises, difficiles à viser au doigt. */
#search_filters .custom-checkbox input[type="checkbox"],
#search_filters input[type="checkbox"] {
  appearance: none;
  flex: 0 0 20px;
  width: 20px;
  height: 20px;
  margin: 0;
  border: 2px solid var(--b3-trait-fort);
  border-radius: 6px;
  background-color: var(--b3-papier);
  cursor: pointer;
}

#search_filters input[type="checkbox"]:checked {
  border-color: var(--b3-encre);
  background-color: var(--b3-encre);
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-width='3.4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m5 12 5 5 9-9'/%3E%3C/svg%3E");
  background-size: 14px;
  background-position: center;
  background-repeat: no-repeat;
}

#search_filters input[type="checkbox"]:focus-visible {
  outline: 3px solid var(--b3-encre);
  outline-offset: 2px;
}

@media (max-width: 767px) {
.b3-hero__actions .b3-btn {
    flex: 1 1 100%;
  }
}


/* --------------------------------------------------------------------------
   Bouton occupé

   L'ajout au panier enchaîne deux requêtes séquentielles : sur un serveur
   distant, l'attente se voit. Le bouton la signale au lieu de rester inerte,
   ce qui laissait croire que le clic n'avait pas porté — et conduisait à
   cliquer deux fois.

   Le libellé ne change pas : le remplacer ferait sauter la largeur du bouton
   et déplacerait ce qui l'entoure. Seuls l'opacité et un trait tournant
   l'indiquent, et les clics sont neutralisés le temps de la requête.
   -------------------------------------------------------------------------- */

.b3-occupe {
  position: relative;
  pointer-events: none;
  color: transparent !important;
}

.b3-occupe::after {
  content: "";
  position: absolute;
  top: 50%;
  left: 50%;
  width: 1.15em;
  height: 1.15em;
  margin: -0.575em 0 0 -0.575em;
  border: 2px solid color-mix(in oklab, var(--b3-encre) 28%, transparent);
  border-top-color: var(--b3-encre);
  border-radius: 50%;
  animation: b3-rotation 620ms linear infinite;
}

@keyframes b3-rotation {
  to { transform: rotate(360deg); }
}

/* Mouvement réduit : le trait ne tourne plus, mais l'état reste signalé par
   l'assombrissement et par `aria-busy`. */
@media (prefers-reduced-motion: reduce) {
  .b3-occupe::after {
    animation: none;
    border-top-color: color-mix(in oklab, var(--b3-encre) 55%, transparent);
  }
}

/* Bouton papier : fond blanc cassé, texte encre. Sur l'aplat jaune du hero, le
   bouton fantôme n'était qu'un contour — deux boutons de poids très inégaux
   côte à côte, alors qu'ils mènent tous deux à un catalogue. Le papier lui
   rend sa surface sans lui donner le poids de l'encre. */
.b3-btn--papier {
  background-color: var(--b3-papier);
  border: 2px solid var(--b3-encre);
  color: var(--b3-encre);
}

.b3-btn--papier:hover,
.b3-btn--papier:focus-visible {
  background-color: var(--b3-encre);
  color: var(--b3-papier);
}


/* ===== 03-entete.css ===================================================== */

/* ===== 03-entete.css ===================================================== */
/* --------------------------------------------------------------------------
   6. Bandeau d'annonce
   Le rouge #d0121a vient d'un style inline posé dans la configuration du
   module otheaderrightblock : impossible à surcharger sans !important.
   À nettoyer côté back-office quand le module sera repris.
   -------------------------------------------------------------------------- */
#header .header-right,
#header #header-right-text {
  margin: 0;
}

#header #header-right-text p {
  margin: 0;
}

#header #header-right-text,
#header #header-right-text span[style],
#header #header-right-text strong span[style] {
  background-color: transparent !important;
  color: var(--b3-papier) !important;
  font-weight: 700;
  font-size: 0.75rem;
  text-transform: uppercase;
  letter-spacing: 0.14em;
}

/* Le drapeau, posé à côté du texte plutôt que dedans (voir le gabarit
   surchargé du module — un émoji ne survit pas à la colonne back-office). */
.b3-header-annonce {
  display: inline-flex;
  align-items: center;
  gap: 0.5em;
}

.b3-header-annonce .b3-drapeau {
  width: 18px;
  height: 18px;
  flex: none;
}

/* 9bis.0 — En-tête
   Le thème posait `#header { position: absolute }` : l'en-tête flottait
   au-dessus d'un bandeau photo plein écran. Sur l'accueil, il rejoint l'aplat
   jaune du hero et forme un seul bloc de couleur, de bord à bord. */
#header {
  position: static;
  background-color: var(--b3-jaune);
}

#header .header-top,
#header .header-nav {
  background-color: transparent;
  border: 0;
  box-shadow: none;
}

/* Le thème enfermait l'en-tête dans une boîte blanche centrée, plus étroite
   que la page. L'aplat doit filer sur toute la largeur. */
#header .header-top > .container {
  max-width: 1320px;
  width: 100%;
  background-color: transparent;
  box-shadow: none;
}

/* Le logo était en médaillon débordant sur le bandeau photo. */
#header #_desktop_logo {
  position: static;
  margin: 0;
  padding: 0;
}

#header #_desktop_logo .logo {
  width: auto;
  max-height: 76px;
  border-radius: 50%;
}

/* Ligne principale : logo, recherche, puis les accès compte / favoris / panier.
   Le menu des rayons passe dessous. */
#header .header-top .col-md-12 {
  display: flex;
  flex-direction: column;
  gap: var(--b3-space-xs);
}

#header .header-top .col-md-12 > .row {
  display: flex;
  flex-wrap: nowrap;
  align-items: center;
  gap: var(--b3-space-sm);
  order: 1;
  margin: 0;
  width: 100%;
}

#header .header-top .col-md-12 > #_desktop_top_menu {
  order: 2;
  width: 100%;
  max-width: none;
  padding: 0;
}

#header .header-top .col-md-12 > .row > #_desktop_logo {
  flex: 0 0 auto;
  width: auto;
  max-width: none;
}

/* La recherche prend la place centrale : c'est le premier geste d'un client
   qui sait ce qu'il veut. */
/* La largeur de la recherche est fixée par la grille (voir 9duodecies).
   L'ancienne règle flex, plus spécifique, la ramenait à 264 px. */
#header .header-top .col-md-12 > .row > #search_widget {
  float: none;
}

#header .header-top .col-md-12 > .row > #_desktop_user_info {
  order: 3;
  flex: 0 0 auto;
}

#header .header-top .col-md-12 > .row > #_desktop_wishlist {
  order: 3;
  flex: 0 0 auto;
}

#header .header-top .col-md-12 > .row > #_desktop_user_info {
  order: 4;
}

#header .header-top .col-md-12 > .row > #_desktop_cart {
  order: 5;
  flex: 0 0 auto;
}

#header .b3-wishlist-link a {
  display: inline-flex;
  align-items: center;
  gap: var(--b3-space-2xs);
  min-height: 48px;
  padding: 0 var(--b3-space-sm);
  border-radius: 999px;
  background-color: var(--b3-papier);
  color: var(--b3-encre);
  font-size: 0.8125rem;
  font-weight: 600;
  text-decoration: none;
}

#header .b3-wishlist-link .material-icons {
  font-size: 20px;
}

/* 9bis.0b — Champ de recherche : pilule blanche, contour encre.
   C'est la seule forme arrondie du système, avec le tampon : elle marque un
   champ de saisie, pas une décoration. */
#header #search_widget form {
  position: relative;
  display: flex;
  align-items: center;
  width: 100%;
  background-color: var(--b3-papier);
  border: 2px solid var(--b3-encre);
  border-radius: 999px;
  overflow: hidden;
}

/* Le thème repliait la recherche : le champ était en `position: absolute` et
   `opacity: 0`, révélé au clic sur la loupe. Un champ masqué derrière une icône
   coûte un clic à chaque recherche et se voit mal au doigt. Il est déplié. */
#header #search_widget input[type="text"],
#header #search_widget .ui-autocomplete-input {
  position: static;
  flex: 1 1 auto;
  width: 100%;
  min-height: 48px;
  padding: 0 var(--b3-space-sm) 0 var(--b3-space-md);
  border: 0;
  background: transparent;
  color: var(--b3-encre);
  font-family: var(--b3-font);
  font-size: 0.9375rem;
  opacity: 1;
  visibility: visible;
}

#header #search_widget input::placeholder {
  color: var(--b3-encre-douce);
  opacity: 1;
}

#header #search_widget button[type="submit"],
#header #search_widget form button {
  position: static;
  flex: 0 0 auto;
  display: grid;
  place-items: center;
  width: 48px;
  height: 48px;
  margin: 0;
  padding: 0;
  border: 0;
  border-radius: 0;
  background: transparent;
  color: var(--b3-encre);
  opacity: 1;
}

#header #search_widget button .material-icons {
  display: block;
  font-size: 22px;
  text-indent: 0;
  color: var(--b3-encre);
}

/* 9bis.0c — Accès compte, favoris et panier : pastilles papier sur l'aplat.

   Le thème empile ces contenus dans des blocs successifs (icône d'un côté,
   libellé de l'autre) : les trois pastilles n'avaient ni la même hauteur ni
   le même alignement interne. Un gabarit unique les remet d'aplomb :
   hauteur fixe, contenu centré sur une ligne. */
#header #_desktop_user_info .user-info,
#header #_desktop_cart .blockcart,
#header .b3-wishlist-link a {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--b3-space-2xs);
  height: 46px;
  padding: 0 var(--b3-space-md);
  border-radius: var(--b3-radius-pill);
  background-color: var(--b3-papier);
  color: var(--b3-encre);
  white-space: nowrap;
}

/* Les conteneurs internes du thème cessent de créer des lignes : leurs
   enfants rejoignent directement la pastille. */
#header #_desktop_user_info .user-icon,
#header #_desktop_cart .blockcart .header,
#header #_desktop_cart .blockcart .cart-desc {
  display: contents;
}

#header #_desktop_user_info .user-info a,
#header #_desktop_cart .blockcart a,
#header .b3-wishlist-link a {
  display: inline-flex;
  align-items: center;
  gap: var(--b3-space-2xs);
  color: var(--b3-encre);
  font-size: 0.8125rem;
  font-weight: 700;
  line-height: 1;
  text-decoration: none;
  float: none;
}

#header #_desktop_user_info .user-info .hidden-sm-down {
  display: inline;
}

/* Le total et le nombre d'articles n'ont pas leur place dans le bouton :
   ils sont repris dans le panneau panier. */
#header #_desktop_cart .shopping-cart-text,
#header #_desktop_cart .ajax_block_cart_total {
  display: none;
}

/* 9bis.0d — Menu des rayons, sur sa propre ligne, sous la recherche.
   Le thème le sortait du flux (`position: absolute; top: 6px`) pour le caler
   sur la même ligne que le logo. */
#header #_desktop_top_menu #adtm_menu {
  position: static;
  top: auto;
  width: 100%;
}

#header #_desktop_top_menu {
  padding-left: 0;
  padding-right: 0;
}

/* La barre du menu portait un dégradé blanc en `background-image` — invisible
   dans `background-color`, d'où la bande claire posée sur l'aplat jaune. */
#header #adtm_menu,
#header #adtm_menu_inner,
#header #menu {
  background-color: transparent;
  background-image: none;
  border: 0;
  box-shadow: none;
}

#header #menu {
  display: flex;
  flex-wrap: wrap;
  gap: var(--b3-space-md);
  padding: 0;
  margin: 0;
}

#header #menu > li.li-niveau1,
#header #menu > li.li-niveau1 > a.a-niveau1,
#header #menu > li.li-niveau1 > a.a-niveau1 > span {
  background: transparent;
  background-image: none;
  border: 0;
  box-shadow: none;
}

/* Le span porte l'essentiel de la métrique du module : sans cette remise à
   plat, la pastille conserve 56 px de haut et 40 px de rembourrage. */
#header #menu > li.li-niveau1 > a.a-niveau1 > span,
#header #menu > li.li-niveau1 > a.a-niveau1 .advtm_menu_span {
  display: inline;
  min-height: 0;
  height: auto;
  padding: 0;
  line-height: inherit;
}

/* Le thème superposait une loupe en image de fond à l'icône du bouton. */
#header #search_widget button[type="submit"]::before,
#header #search_widget button[type="submit"]::after,
#header #search_widget form button::before,
#header #search_widget form button::after {
  display: none;
  content: none;
}

#header #search_widget button {
  background-image: none;
}

/* Rayons en pastilles papier : sur l'aplat jaune, un simple texte se lisait
   mal et rien ne signalait la zone cliquable. */
/* Le module de menu impose sa propre métrique, et c'est elle qui faisait des
   pastilles démesurées :

     #adtm_menu .li-niveau1 a.a-niveau1               { min-height:56px; line-height:56px }
     #adtm_menu .li-niveau1 a.a-niveau1 .advtm_menu_span { min-height:56px; line-height:56px }
     .li-niveau1 a span                               { padding:0 20px }

   Borner la hauteur du lien ne suffisait pas : le <span> intérieur gardait ses
   56 px de hauteur et d'interligne, et gonflait la pastille de l'intérieur
   pendant que le pictogramme passait à la ligne. Le lien *et* son span sont
   donc remis à plat ici. Les sélecteurs portent deux identifiants contre un
   seul au module : ils l'emportent sans `!important`. */
#header #menu > li.li-niveau1 > a.a-niveau1 {
  display: inline-flex;
  align-items: center;
  line-height: 1;
  min-height: 40px;
  padding: 0 var(--b3-space-md);
  border-radius: var(--b3-radius-pill);
  background-color: var(--b3-papier);
  color: var(--b3-encre);
  font-weight: 800;
  font-size: 0.8125rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  text-decoration: none;
  transition: background-color var(--b3-dur-fast) var(--b3-ease),
              color var(--b3-dur-fast) var(--b3-ease);
}

#header #menu > li.li-niveau1 > a.a-niveau1:hover,
#header #menu > li.li-niveau1 > a.a-niveau1:focus {
  background-color: var(--b3-encre);
  color: var(--b3-papier);
  text-decoration: none;
}

#header #menu {
  justify-content: center;
  gap: var(--b3-space-2xs);
  padding: var(--b3-space-2xs) 0 var(--b3-space-sm);
}

/* --------------------------------------------------------------------------
   9ter. Correctifs responsive — audit mobile / tablette
   Relevé sur la page d'accueil à 390, 768 et 1024 px.
   -------------------------------------------------------------------------- */
/* 9ter.1 — Double menu.
   Le menu desktop et le bouton de menu mobile s'affichaient tous les deux
   sous 768 px : deux navigations concurrentes à l'écran, et un `ul#menu` plus
   large que le viewport. Un seul menu à la fois. */
@media (max-width: 991px) {
#header .header-top .col-md-12 > #_desktop_top_menu,
  #header #_desktop_top_menu {
    display: none;
  }
}

@media (min-width: 992px) {
#header .hidden-md-up.mobile,
  #header #menu-icon {
    display: none;
  }
}

/* 9ter.4 — En-tête mobile.
   Logo, recherche et accès ne tiennent pas sur une ligne sous 768 px. */
@media (max-width: 767px) {
#header .header-top .col-md-12 > .row {
    flex-wrap: wrap;
    gap: var(--b3-space-2xs);
    row-gap: var(--b3-space-xs);
  }

#header .header-top .col-md-12 > .row > #search_widget {
    order: 5;
    flex: 1 1 100%;
    max-width: none;
  }

#header .b3-wishlist-link a span,
  #header #_desktop_user_info .user-info .hidden-sm-down {
    /* Les libellés passent en accessible-only : les pastilles se réduisent à
       leur icône, la barre reste lisible sur un écran étroit. */
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border: 0;
  }

#header #_desktop_user_info .user-info,
  #header #_desktop_cart .blockcart,
  #header .b3-wishlist-link a {
    justify-content: center;
    min-width: 48px;
    padding: 0 var(--b3-space-xs);
  }

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

/* 9q.3 — En-tête mobile décentré.
   Les marges négatives de la rangée Bootstrap se combinaient au padding du
   conteneur : 30 px de retrait à gauche contre 4 px à droite. */
@media (max-width: 767px) {
#header .header-top > .container,
  #header .header-nav > .container {
    padding-left: var(--b3-space-xs);
    padding-right: var(--b3-space-xs);
  }

#header .header-top .col-md-12 > .row {
    margin-left: 0;
    margin-right: 0;
  }

#header .header-top .col-md-12,
  #header .header-top .container > .row {
    padding-left: 0;
    padding-right: 0;
    margin-left: 0;
    margin-right: 0;
  }
}

/* 9q.4 — Le logo disparaissait de l'en-tête sous 768 px (`hidden-sm-down`),
   ne laissant qu'un menu burger sans identité de marque. */
@media (max-width: 767px) {
/* `.hidden-sm-down` de Bootstrap pose `display: none !important` :
     seul un `!important` peut le rebattre. */
#header #_desktop_logo.hidden-sm-down {
    display: block !important;
    flex: 0 0 auto;
    order: 2;
    width: auto;
    padding: 0;
  }

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

/* Le décalage résiduel venait des marges négatives des rangées Bootstrap
     imbriquées, qui se cumulaient sur la gauche. */
#header .header-top .container .row,
  #header .header-nav .container .row {
    margin-left: 0;
    margin-right: 0;
  }

/* Plutôt que de traquer chaque padding de colonne Bootstrap imbriquée, les
     rangées de l'en-tête sont recadrées sur la largeur utile. */
#header .header-top .col-md-12 > .row,
  #header .header-top .col-md-12 > .hidden-md-up.mobile,
  #header .header-top .container > .row {
    box-sizing: border-box;
    width: 100%;
    max-width: 100%;
    margin: 0;
    padding: 0 var(--b3-space-xs);
  }

#header .header-top .container,
  #header .header-top .container > .row,
  #header .header-top .col-md-12 {
    box-sizing: border-box;
    width: 100%;
    max-width: 100%;
    margin-left: 0;
    margin-right: 0;
    padding-left: 0;
    padding-right: 0;
  }
}

/* --------------------------------------------------------------------------
   9sexies. En-tête — reprise du logo, de la recherche et des accès
   -------------------------------------------------------------------------- */
/* 9s.1 — Le tampon rond.
   Le fichier fait 500 × 246 : appliquer `border-radius: 50%` à ce rectangle
   donnait une ellipse. L'image est recadrée sur le carré de gauche, celui qui
   contient le tampon, et l'arrondi supprime le liseré blanc résiduel. */
#header .b3-logo {
  display: inline-flex;
  align-items: center;
  gap: var(--b3-space-2xs);
  text-decoration: none;
}

/* Le gabarit sert désormais `assets/img/tampon-3b.png`, carré et détouré. Les
   trois rattrapages qui vivaient ici — agrandissement de 1,23, `clip-path:
   circle(40.65%)` et cadrage à gauche — compensaient un fichier rectangulaire
   de 500 × 246 dont le cachet n'occupait que le carré de gauche. Accordés au
   pixel, ils rognaient le pourtour dès que la taille changeait. Ils sont
   retirés : l'image est ronde, il n'y a plus rien à découper.

   `max-height` reste indispensable : le thème en impose une sur les images
   d'en-tête, et sans elle la hauteur retombait à 58 px pour une largeur de 82,
   ce qui redonnait une ellipse. */
#header .b3-logo .logo,
#header #_desktop_logo .logo,
#header #_mobile_logo .logo {
  width: 82px;
  height: 82px;
  min-width: 82px;
  max-height: none;
  aspect-ratio: 1;
  object-fit: contain;
  border-radius: 50%;
}

/* Signature de marque, en texte : deux lignes serrées à droite du tampon. */
.b3-logo__wordmark {
  display: flex;
  flex-direction: column;
  color: var(--b3-encre);
  font-size: 0.6875rem;
  font-weight: 800;
  line-height: 1.15;
  text-transform: uppercase;
  letter-spacing: 0.06em;
}

@media (max-width: 991px) {
.b3-logo__wordmark {
    display: none;
  }
}

/* 9s.2 — Champ de recherche : plus de cerclage noir épais, un simple trait,
   et la loupe alignée dans un bouton à sa mesure. */
#header #search_widget form {
  border: 1px solid var(--b3-trait-fort);
  border-radius: var(--b3-radius-pill);
  padding-right: 6px;
  background-color: var(--b3-papier);
  transition: border-color var(--b3-dur-fast) var(--b3-ease);
}

#header #search_widget form:focus-within {
  border-color: var(--b3-encre);
}

#header #search_widget button[type="submit"],
#header #search_widget form button {
  width: 40px;
  height: 40px;
  border-radius: 50%;
  background-color: var(--b3-jaune);
  color: var(--b3-encre);
  transition: background-color var(--b3-dur-fast) var(--b3-ease);
}

#header #search_widget form button:hover {
  background-color: var(--b3-jaune-fonce);
}

#header #search_widget button .material-icons {
  font-size: 20px;
  line-height: 1;
}

/* 9s.3 — Accès compte, favoris, panier : même gabarit, contour discret,
   libellé lisible. Ils formaient trois blocs de traitements différents. */
#header #_desktop_user_info .user-info,
#header #_desktop_cart .blockcart,
#header .b3-wishlist-link a {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  min-height: 44px;
  padding: 0 var(--b3-space-xs);
  border: 1px solid var(--b3-trait-fort);
  border-radius: var(--b3-radius-pill);
  background-color: var(--b3-papier);
  color: var(--b3-encre);
  font-size: 0.8125rem;
  font-weight: 600;
  text-decoration: none;
  transition: border-color var(--b3-dur-fast) var(--b3-ease),
              background-color var(--b3-dur-fast) var(--b3-ease);
}

#header #_desktop_user_info .user-info:hover,
#header #_desktop_cart .blockcart:hover,
#header .b3-wishlist-link a:hover {
  border-color: var(--b3-encre);
  background-color: var(--b3-jaune);
}

/* Le compteur du panier devient une pastille encre, lisible sur le papier. */
#header #_desktop_cart .cart-products-count {
  display: inline-grid;
  place-items: center;
  min-width: 22px;
  height: 22px;
  padding: 0 5px;
  border-radius: var(--b3-radius-pill);
  background-color: var(--b3-encre);
  color: var(--b3-papier);
  font-size: 0.6875rem;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
}

/* 9s.4 — Menus déroulants du méga-menu : texte encre appuyé, panneau lisible. */
#header .adtm_sub,
#header .adtm_sub_wrap,
#header li.li-niveau1 .adtm_sub {
  /* Trait d'encre plutôt que gris : le panneau tombe sur l'aplat jaune du
     hero, où un filet clair disparaît. */
  border: 1.5px solid var(--b3-encre);
  border-radius: var(--b3-radius);
  background-color: var(--b3-papier);
  box-shadow: 0 16px 36px oklch(0.19 0.012 90 / 0.18);
  padding: var(--b3-space-sm);
}

#header .adtm_sub a,
#header .adtm_sub .advtm_menu_span,
#header .adtm_sub li a,
#header ul.adtm_column_wrap li a {
  display: flex;
  align-items: center;
  gap: 0.5em;
  padding: 8px var(--b3-space-2xs);
  border-radius: var(--b3-radius-sm);
  color: var(--b3-encre);
  font-size: 0.9375rem;
  font-weight: 800;
  line-height: 1.25;
  text-transform: none;
  letter-spacing: -0.005em;
  transition: background-color var(--b3-dur-fast) var(--b3-ease),
              padding-left var(--b3-dur-fast) var(--b3-ease);
}

/* Le repère est posé par 3b.js, qui tient la même table que les facettes : un
   panneau de quarante liens en colonnes se parcourt d'abord par la forme. */
#header .adtm_sub a[data-b3-picto]::before {
  content: attr(data-b3-picto);
  flex: none;
  width: 1.15em;
  font-size: 1.0625rem;
  line-height: 1;
  text-align: center;
}

/* Les entrées sans repère s'alignent quand même sur la colonne de texte :
   sans cette gouttière, deux listes voisines partaient de deux axes. */
#header .adtm_sub a:not([data-b3-picto])::before {
  content: "";
  flex: none;
  width: 1.15em;
}

#header .adtm_sub a:hover,
#header .adtm_sub li a:hover,
#header ul.adtm_column_wrap li a:hover {
  background-color: var(--b3-jaune);
  color: var(--b3-encre);
  text-decoration: none;
  /* Le décalage dit « ce lien-ci », là où l'aplat seul se confond avec le
     survol d'à côté quand la souris file dans la colonne. */
  padding-left: var(--b3-space-xs);
}

/* Le module appelle « titre de colonne » aussi bien un vrai en-tête qu'une
   entrée seule : dans le panneau « Vins », les sept rayons sont chacun le
   titre d'une colonne vide. Traités en en-têtes, ils s'affichaient en sept
   lignes soulignées d'un filet, sans rien à commander.

   Le titre n'est donc un en-tête que si sa colonne porte une liste. Sinon,
   c'est une entrée comme les autres. */
#header .adtm_sub .columnWrapTitle,
#header .adtm_sub .column_wrap_title {
  display: block;
  margin: 0;
  padding: 0;
  border: 0;
}

/* Le thème acheté cible ces liens par un sélecteur plus spécifique que
   `.adtm_sub a` et les ramenait à la graisse normale. La règle est répétée
   ici, à la spécificité qu'il faut pour la tenir. */
#header .adtm_sub .adtm_column .column_wrap_title a {
  display: flex;
  align-items: center;
  gap: 0.5em;
  padding: 8px var(--b3-space-2xs);
  border-radius: var(--b3-radius-sm);
  font-size: 0.9375rem;
  font-weight: 800;
  line-height: 1.25;
  letter-spacing: -0.005em;
  color: var(--b3-encre);
}

#header .adtm_sub .adtm_column:has(ul) .column_wrap_title {
  margin: 0 0 var(--b3-space-2xs);
  padding: 0 var(--b3-space-2xs) var(--b3-space-3xs);
  border-bottom: 1.5px solid var(--b3-encre);
  color: var(--b3-encre);
  font-size: 0.6875rem;
  font-weight: 800;
  text-transform: uppercase;
  letter-spacing: 0.12em;
}

#header .adtm_sub .adtm_column:has(ul) .column_wrap_title a,
#header .adtm_sub .adtm_column:has(ul) .column_wrap_title a:hover {
  display: block;
  padding: 0;
  background: none;
  font-size: inherit;
  font-weight: inherit;
  letter-spacing: inherit;
  text-transform: inherit;
}

#header .adtm_sub .adtm_column:has(ul) .column_wrap_title a::before {
  content: none;
}

/* Les colonnes respirent : le module les colle par un tableau sans gouttière. */
#header .adtm_sub .adtm_column {
  padding: 0 var(--b3-space-2xs);
  min-width: 11rem;
}

/* Le panneau n'a pas à border la fenêtre : une largeur minimale évite la
   colonne unique de cent pixels quand le rayon ne porte que trois entrées. */
#header .adtm_sub {
  min-width: 15rem;
}

/* 9s.5 — Barre mobile.
   Le thème positionnait ses éléments en flottants (`float-xs-left`,
   `float-xs-right`) : le logo tombait sous les icônes et les accès n'avaient
   aucun traitement. Rangée unique — menu, logo, accès. */
@media (max-width: 991px) {
/* Le thème déplace le contenu des blocs desktop vers leurs équivalents
     mobiles au chargement : les conteneurs d'origine restent dans le flux,
     vides, et décalaient la rangée. Seule la recherche est conservée.
     Sélecteurs par identifiant : le balisage rendu par le hook displayTop
     déplace ces blocs dans un conteneur intermédiaire. */
#header #_desktop_logo,
  #header #_desktop_cart,
  #header #_desktop_user_info,
  #header #_desktop_wishlist {
    display: none !important;
  }

#header .header-top .col-md-12 > .row > #search_widget {
    flex: 1 1 100%;
    max-width: none;
    margin: 0;
  }

/* La barre mobile vit dans `.header-nav`, pas dans `.header-top`.
     Le thème donne à cette bande une hauteur de 20 px, calibrée pour un
     sélecteur de langue : la barre de navigation, haute de 83 px, en
     débordait et venait recouvrir la recherche placée juste en dessous.
     La bande reprend une hauteur libre. */
/* La bande de navigation est plafonnée par le thème :
     `#header .header-nav { max-height: 20px }` (theme.css), une hauteur
     calibrée pour un simple sélecteur de langue. La barre mobile, haute de
     83 px, en débordait et recouvrait la recherche placée juste dessous.

     C'est `max-height` qui verrouillait la bande, pas `height` : tant qu'il
     restait, tout réglage de hauteur était sans effet. Le flottant est
     également retiré, pour que la bande reprenne sa place dans le flux. */
#header .header-nav {
    display: flow-root;
    float: none;
    max-height: none;
  }

#header .header-nav,
  #header .header-nav > .container,
  #header .header-nav > .container > .row {
    box-sizing: border-box;
    width: 100%;
    max-width: 100%;
    height: auto;
    max-height: none;
    min-height: 0;
    margin: 0;
    padding: 0;
    overflow: visible;
  }

#header .header-nav > .container > .row {
    display: block;
  }

#header .hidden-md-up.mobile {
    display: flex !important;
    align-items: center;
    gap: var(--b3-space-2xs);
    box-sizing: border-box;
    width: 100%;
    margin: 0;
    padding: var(--b3-space-2xs) var(--b3-space-xs);
  }

#header .hidden-md-up.mobile > div {
    float: none !important;
    margin: 0;
  }

#header #menu-icon {
    order: 1;
    display: grid;
    place-items: center;
    width: 44px;
    height: 44px;
    border-radius: var(--b3-radius-pill);
    cursor: pointer;
  }

#header #menu-icon .material-icons {
    font-size: 26px;
    color: var(--b3-encre);
  }

#header #_mobile_logo {
    order: 2;
    flex: 1 1 auto;
    min-width: 0;
  }

#header #_mobile_logo .logo {
    width: 58px;
    height: 58px;
    /* Le `min-width` de la règle générale vaut 82 px : sans ce rappel, il
       maintenait la largeur à 82 pour 58 de haut, et le tampon redevenait une
       ellipse sur mobile. */
    min-width: 58px;
    aspect-ratio: 1;
    object-fit: cover;
    object-position: left center;
    border-radius: 50%;
  }

#header #_mobile_user_info {
    order: 3;
  }

#header #_mobile_cart {
    order: 4;
  }

/* Même gabarit que sur grand écran : pastille papier, contour discret. */
#header #_mobile_user_info .user-info,
  #header #_mobile_cart .blockcart {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 4px;
    min-width: 44px;
    min-height: 44px;
    padding: 0 var(--b3-space-2xs);
    border: 1px solid var(--b3-trait-fort);
    border-radius: var(--b3-radius-pill);
    background-color: var(--b3-papier);
    color: var(--b3-encre);
  }

#header #_mobile_user_info .user-icon,
  #header #_mobile_cart .blockcart a {
    padding: 0;
    color: var(--b3-encre);
  }

/* Les libellés ne tiennent pas : l'icône porte l'action, le texte reste
     disponible pour les technologies d'assistance. */
#header #_mobile_user_info .user-info .hidden-sm-down {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
  }
}

/* --------------------------------------------------------------------------
   9nonies. Barre mobile — bouton menu, recherche, compteur
   Uniquement de l'habillage : le balisage des modules d'en-tête n'est pas
   touché, le thème y clone lui-même le bloc panier vers son équivalent
   mobile et toute réécriture y produisait des doublons.
   -------------------------------------------------------------------------- */
@media (max-width: 991px) {
/* Bouton menu : pastille encre, icône papier.
     `flex: 0 0 46px` est indispensable — dans la rangée en flex, le bouton se
     laissait comprimer et le cercle devenait un ovale. */
#header #menu-icon {
    flex: 0 0 46px;
    width: 46px;
    height: 46px;
    min-width: 46px;
    border-radius: 50%;
    background-color: var(--b3-encre);
    cursor: pointer;
  }

/* Le thème colore cette icône via `#header .header-nav #menu-icon
     .material-icons` : deux identifiants et deux classes, soit une
     spécificité supérieure à la nôtre. On reprend le même chemin. */
/* Le glyphe Material porte un `line-height` de texte qui le posait bas
     dans la pastille. */
#header .header-nav #menu-icon .material-icons,
  #header #menu-icon .material-icons {
    display: block;
    color: var(--b3-papier);
    font-size: 24px;
    line-height: 1;
    height: 24px;
    width: 24px;
    text-align: center;
  }

/* La bande qui porte la recherche restait blanche : `custom.css` pose
     `#header .header-top { background: #fff }` sous 767 px. L'aplat doit
     courir sans rupture du haut de l'en-tête jusqu'au hero. */
#header,
  #header .header-top,
  #header .header-nav,
  #header .header-top > .container,
  #header .header-nav > .container {
    background-color: var(--b3-jaune);
  }

/* Le champ reprend l'aplat, avec un contour encre pour rester lisible. */
#header #search_widget form {
    background-color: var(--b3-papier);
    border-color: var(--b3-encre);
  }

#header #search_widget input[type="text"],
  #header #search_widget .ui-autocomplete-input {
    background: transparent;
    color: var(--b3-encre);
  }

#header #search_widget input::placeholder {
    color: var(--b3-encre-douce);
    opacity: 1;
  }

#header #search_widget form button {
    background-color: var(--b3-jaune);
    color: var(--b3-encre);
  }

#header #search_widget button .material-icons {
    color: var(--b3-encre);
  }
}

/* Loupe centrée dans sa pastille : le thème lui laissait un `line-height` et
   un `text-indent` hérités du texte, qui la posaient en bas à droite. */
#header #search_widget form button {
  display: grid;
  place-items: center;
  padding: 0;
  line-height: 0;
  text-indent: 0;
}

#header #search_widget button .material-icons {
  display: block;
  margin: 0;
  padding: 0;
  line-height: 1;
  text-indent: 0;
}

/* `.cart-desc` regroupe le compteur et trois libellés. La masquer en bloc,
   en position absolue, en faisait le référentiel du compteur : celui-ci se
   calait sur une boîte de 1 px posée sous le bouton, et formait une seconde
   pastille claire à côté de la première — c'est le « double panier ».
   `display: contents` supprime la boîte sans supprimer les enfants : le
   compteur se cale de nouveau sur `.blockcart`, et seuls les libellés sont
   masqués. */
#header #_desktop_cart .cart-desc,
#header #_mobile_cart .cart-desc {
  display: contents;
}

#header #_desktop_cart .cart-desc > *:not(.cart-products-count),
#header #_mobile_cart .cart-desc > *:not(.cart-products-count) {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
}

/* Compteur d'articles en pastille sur l'angle de l'icône, plutôt qu'à la
   suite du libellé. */
#header #_mobile_cart .blockcart,
#header #_desktop_cart .blockcart {
  position: relative;
  overflow: visible;
}

/* Compteur : pastille papier cerclée d'encre, chiffre encre. En encre plein,
   il se confondait avec le tracé du panier juste derrière. */
#header #_mobile_cart .cart-products-count,
#header #_desktop_cart .cart-products-count {
  position: absolute;
  /* Calé sur l'angle du bouton, en léger débord : à 26 px il faisait plus de
     la moitié d'une pastille de 44 et se lisait comme un second bouton. */
  top: -6px;
  right: -6px;
  z-index: 2;
  display: grid;
  place-items: center;
  min-width: 22px;
  height: 22px;
  padding: 0 5px;
  border: 2px solid var(--b3-encre);
  border-radius: var(--b3-radius-pill);
  /* Jaune porteur, chiffre encre : 12:1, et le compteur cesse de se
     confondre avec la pastille papier du bouton qu'il surplombe. */
  background-color: var(--b3-jaune);
  color: var(--b3-encre);
  font-size: 0.75rem;
  font-weight: 800;
  font-variant-numeric: tabular-nums;
  line-height: 1;
}

/* --------------------------------------------------------------------------
   9duodecies. En-tête en grille nommée
   Le thème compose son en-tête avec des rangées et colonnes Bootstrap
   imbriquées, des flottants et des largeurs en pourcentage. Chaque correctif
   ponctuel en déplaçait un autre : rangée décalée de 30 px, barre mobile
   recouvrant la recherche, bandeau plafonné à 20 px de haut.
   Une grille explicite remplace cet empilement : les zones sont nommées, donc
   leur position ne dépend plus de l'ordre du balisage ni des marges héritées.
   -------------------------------------------------------------------------- */
/* Desktop : logo | recherche | accès, sur une ligne, plus le menu dessous. */
@media (min-width: 992px) {
#header .header-top .col-md-12 {
    display: grid;
    /* Une piste par élément : favoris, compte et panier partageaient la même
       zone et se superposaient. */
    grid-template-columns: auto minmax(0, 1fr) auto auto auto;
    grid-template-areas:
      "logo recherche favoris compte panier"
      "menu menu      menu    menu   menu"
      "pros pros      pros    pros   pros";
    align-items: center;
    column-gap: clamp(var(--b3-space-2xs), 1.4vw, var(--b3-space-sm));
    row-gap: var(--b3-space-2xs);
  }

/* Le bandeau « Accès pros » (ps_mainmenu) et le méga-menu des rayons
     partagent le même identifiant `_desktop_top_menu` — l'un dans
     `.row.main-menu`, l'autre en `.adtm_menu_container`. Faute de zone, le
     premier était placé automatiquement dans la première colonne : ses 951 px
     y dimensionnaient la piste `logo`, qui passait de 224 à 921 px et
     réduisait la recherche à 25 px. Celle-ci débordait alors de sa piste et
     recouvrait le bloc compte — la superposition constatée en haut de page. */
/* Pas de combinateur enfant ici : `.row.main-menu` est imbriqué dans un
     `.row` mis en `display: contents`. Il participe donc bien à la grille,
     mais n'est pas un enfant direct au sens des sélecteurs. */
/* Bandeau « Accès pros » : la barre des rayons porte déjà une entrée « PRO »
   qui mène à la même catégorie. Deux chemins vers la même page, l'un en
   pastille et l'autre en bandeau, se font concurrence sans rien ajouter.
   Masqué ; la ligne de grille reste disponible si l'entrée doit revenir. */
#header .header-top .col-md-12 .row.main-menu {
    display: none;
    grid-area: pros;
    width: 100%;
    float: none;
  }

/* Vestiges de la mise en page en flottants : sans hauteur ni contenu, ils
     n'occupaient de cellule que pour brouiller le calcul des pistes. */
#header .header-top .col-md-12 > .clear,
  #header .header-top .col-md-12 > div:not([id]):not([class]) {
    display: none;
  }

/* Le bouton panier tirait sa largeur de la sprite du thème, désormais
     masquée : il ne mesurait plus que 26 px, et son compteur débordait de
     part et d'autre. Même gabarit que le bloc compte. */
#header #_desktop_cart .blockcart {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 46px;
    min-height: 46px;
  }

/* La rangée intermédiaire du thème disparaît : ses enfants rejoignent
     directement la grille. */
#header .header-top .col-md-12 > .row {
    display: contents;
  }

#header #_desktop_logo        { grid-area: logo; }

#header #_desktop_wishlist    { grid-area: favoris; }

#header #_desktop_user_info   { grid-area: compte; }

#header #_desktop_cart        { grid-area: panier; }

#header #_desktop_top_menu    { grid-area: menu; }

/* La recherche occupe toute la piste centrale, sans plafond étroit : elle
     est l'entrée principale du catalogue. */
#header #search_widget {
    grid-area: recherche;
    justify-self: stretch;
    width: 100%;
    max-width: none;
    margin: 0;
  }
}

/* Mobile et tablette : une seule colonne, deux rangées.
   `grid-template-areas` rend l'ordre visuel indépendant du balisage — le logo
   arrive en quatrième position dans le HTML et se place pourtant au centre. */
@media (max-width: 991px) {
#header .header-nav > .container > .row {
    display: block;
  }

#header .hidden-md-up.mobile {
    display: grid !important;
    grid-template-columns: auto minmax(0, 1fr) auto auto;
    grid-template-areas: "logo menu compte panier";
    align-items: center;
    gap: var(--b3-space-2xs);
    box-sizing: border-box;
    width: 100%;
    padding: var(--b3-space-2xs) var(--b3-space-xs);
  }

#header #menu-icon         { grid-area: menu; }

#header #_mobile_logo      { grid-area: logo; justify-self: center; }

#header #_mobile_user_info { grid-area: compte; }

#header #_mobile_cart      { grid-area: panier; }

/* La rangée du haut ne porte plus que la recherche, en pleine largeur. */
#header .header-top .col-md-12 > .row {
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    box-sizing: border-box;
    width: 100%;
    margin: 0;
    padding: 0 var(--b3-space-xs);
  }

#header .header-top .col-md-12 > .row > #search_widget {
    width: 100%;
    max-width: none;
    margin: 0;
  }
}

/* --------------------------------------------------------------------------
   9quaterdecies. Icônes d'en-tête — tracés SVG
   Les glyphes Material du thème datent et s'alignent mal (métriques de
   police, pas d'icône). On les remplace par des tracés vectoriels posés en
   masque, sans toucher au balisage des modules : le thème y clone lui-même
   le bloc panier vers son équivalent mobile.
   -------------------------------------------------------------------------- */
/* Le thème ne dessine pas ses icônes d'en-tête avec une police, mais avec une
   sprite PNG posée en fond de pseudo-élément :

     .blockcart .header::before { background: url(assets/img/sprite.png) -28px -26px; width:30px; height:35px }
     .user-info .user-icon::before { background: url(assets/img/sprite.png) -27px -127px }

   D'où le panier vu en double : masquer le <i> porteur du glyphe ne touchait
   pas ce pseudo-élément, et la sprite du thème continuait de peindre un panier
   à côté du tracé vectoriel. Sur l'icône de compte, la sprite transparaissait
   sous le masque, au lieu de s'ajouter.

   `background-image: none` est donc indispensable partout où un masque est
   posé : le masque découpe la peinture de fond, il ne la remplace pas. */
#header #_desktop_user_info .user-icon::before,
#header #_mobile_user_info .user-icon::before,
#header #_desktop_cart .shopping-cart::before,
#header #_mobile_cart .shopping-cart::before,
#header .b3-wishlist-link .material-icons::before {
  content: "";
  display: block;
  width: 23px;
  height: 23px;
  background-image: none;
  background-color: currentColor;
  -webkit-mask-repeat: no-repeat;
  mask-repeat: no-repeat;
  -webkit-mask-position: center;
  mask-position: center;
  -webkit-mask-size: contain;
  mask-size: contain;
}

/* Le glyphe d'origine est neutralisé : seul le tracé reste. */
#header #_desktop_cart .shopping-cart,
#header #_mobile_cart .shopping-cart,
#header .b3-wishlist-link .material-icons {
  display: block;
  width: 23px;
  height: 23px;
  font-size: 0;
  line-height: 0;
  overflow: hidden;
}

#header #_desktop_user_info .user-icon::before,
#header #_mobile_user_info .user-icon::before {
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.7' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='8.5' r='3.5'/%3E%3Cpath d='M4.5 20a7.5 7.5 0 0 1 15 0'/%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.7' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='8.5' r='3.5'/%3E%3Cpath d='M4.5 20a7.5 7.5 0 0 1 15 0'/%3E%3C/svg%3E");
}

#header #_desktop_cart .shopping-cart::before,
#header #_mobile_cart .shopping-cart::before {
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.7' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6 8h12l-1 12H7L6 8Z'/%3E%3Cpath d='M9 8V6a3 3 0 0 1 6 0v2'/%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.7' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6 8h12l-1 12H7L6 8Z'/%3E%3Cpath d='M9 8V6a3 3 0 0 1 6 0v2'/%3E%3C/svg%3E");
}

#header .b3-wishlist-link .material-icons::before {
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.7' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M12 20s-7-4.4-7-9.2A4 4 0 0 1 12 8a4 4 0 0 1 7 2.8C19 15.6 12 20 12 20Z'/%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.7' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M12 20s-7-4.4-7-9.2A4 4 0 0 1 12 8a4 4 0 0 1 7 2.8C19 15.6 12 20 12 20Z'/%3E%3C/svg%3E");
}

/* --------------------------------------------------------------------------
   9quindecies. En-tête — reprise finale
   Correctifs issus d'un relevé des styles calculés, et non d'une estimation.
   -------------------------------------------------------------------------- */
/* 9q.1 — Filets gris entre les accès.
   Le thème les dessine en `::before` sur chaque bloc (`content: ""` plus une
   bordure). Ils séparaient une barre d'icônes qui n'existe plus. */
#header #_desktop_user_info::before,
#header #_desktop_user_info::after,
#header #_desktop_cart::before,
#header #_desktop_cart::after,
#header #_mobile_user_info::before,
#header #_mobile_cart::before,
#header .b3-wishlist-link::before,
#header .b3-wishlist-link::after {
  content: none !important;
  display: none !important;
  border: 0 !important;
}

/* 9q.2 — Double panier.
   Le glyphe Material est une ligature textuelle. Le neutraliser tout en
   dessinant par-dessus laissait les deux visibles selon le rendu de la
   police. Le porteur du glyphe est donc entièrement masqué, et le tracé
   vectoriel est posé sur le lien lui-même. */
/* Un seul panier. Le thème rend le glyphe à plusieurs endroits selon la page
   (aperçu, version mobile clonée) : tout porteur de glyphe est masqué, le
   tracé vectoriel est posé une fois sur le lien. */
#header .shopping-cart,
#header .material-icons.shopping-cart,
#header #_desktop_cart i,
#header #_mobile_cart i,
#header #_desktop_user_info .user-icon > .material-icons,
#header #_mobile_user_info .user-icon > .material-icons {
  display: none !important;
}

/* Seule la sprite du thème dessinait encore un second panier, sur le
   conteneur `.header` intercalé entre `.blockcart` et le lien. Le tracé
   vectoriel étant porté par le lien juste en dessous, ce pseudo-élément n'a
   plus d'objet. */
#header #_desktop_cart .blockcart .header::before,
#header #_mobile_cart .blockcart .header::before {
  content: none;
  display: none;
}

/* Le tracé est porté par `.blockcart`, pas par le lien : le thème n'émet
   celui-ci que lorsque le panier contient un article, et la pastille restait
   vide sur un panier vide. */
#header #_desktop_cart .blockcart::before,
#header #_mobile_cart .blockcart::before {
  content: "";
  display: block;
  flex: 0 0 23px;
  width: 23px;
  height: 23px;
  background-color: currentColor;
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.7' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6 8h12l-1 12H7L6 8Z'/%3E%3Cpath d='M9 8V6a3 3 0 0 1 6 0v2'/%3E%3C/svg%3E") center / contain no-repeat;
  mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.7' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6 8h12l-1 12H7L6 8Z'/%3E%3Cpath d='M9 8V6a3 3 0 0 1 6 0v2'/%3E%3C/svg%3E") center / contain no-repeat;
}

/* 9q.2b — Alignement des trois accès.
   « Favoris » porte sa pastille sur le lien, les deux autres sur un bloc
   intermédiaire : les conteneurs n'avaient pas la même hauteur et le premier
   flottait dix pixels plus haut. On les recale sur la grille. */
@media (min-width: 992px) {
/* Les trois blocs sont placés sur la même rangée de grille et centrés
     dessus. `align-self` seul ne suffisait pas : les conteneurs gardaient des
     hauteurs différentes selon ce qu'ils enveloppent, et « Favoris » flottait
     dix pixels plus haut que ses voisins. */
#header .header-top .col-md-12 > .row > #_desktop_wishlist,
  #header .header-top .col-md-12 > .row > #_desktop_user_info,
  #header .header-top .col-md-12 > .row > #_desktop_cart,
  #header #_desktop_wishlist,
  #header #_desktop_user_info,
  #header #_desktop_cart {
    display: flex;
    align-items: center;
    align-self: center;
    justify-content: center;
    height: 46px;
    min-height: 46px;
    max-height: 46px;
    margin: 0;
    padding: 0;
    line-height: 1;
  }
}

/* 9q.3 — Logo de l'en-tête, un peu plus présent.
   Il était mesuré à 0 : le thème lui applique `max-width` sur la colonne
   parente, ce qui écrasait l'image une fois la grille en place. */
#header #_desktop_logo,
#header .b3-logo {
  max-width: none;
  overflow: visible;
}

/* La taille du tampon est fixée plus haut, avec son ratio : la redéfinir ici
   sans `aspect-ratio` réintroduisait l'ellipse. */
/* 9q.4 — Menu des rayons sur une seule ligne.
   Les pastilles occupaient trois rangées : elles se resserrent et leur
   libellé suit la place disponible. */
#header #menu,
#header #menu {
  flex-wrap: nowrap;
  justify-content: center;
  gap: var(--b3-space-3xs);
  overflow: visible;
}

#header #menu > li.li-niveau1 > a.a-niveau1 {
  gap: 6px;
  padding: 0 clamp(var(--b3-space-2xs), 1vw, var(--b3-space-md));
  font-size: clamp(0.6875rem, 0.85vw, 0.8125rem);
  font-weight: 800;
  white-space: nowrap;
}

/* Un pictogramme par rayon, posé en CSS : les libellés viennent de la base et
   du module de menu, on ne les réécrit pas pour autant. Purement décoratif,
   d'où `aria-hidden` implicite : un pseudo-élément n'est pas restitué comme
   contenu par les lecteurs d'écran. */
#header #menu > li.li-niveau1 > a.a-niveau1::before,
#header #menu > li.li-niveau1 > a.a-niveau1::before {
  /* Le pictogramme est l'accroche de la pastille : il se lit avant le mot,
     donc nettement au-dessus du corps du libellé. */
  font-size: 1.45em;
  line-height: 1;
}

/* Les classes numérotées du module varient selon l'ordre des catégories :
   on se cale sur la position visible, plus stable ici. */
#header #menu > li.li-niveau1:nth-of-type(2) > a::before { content: "🍷"; }

#header #menu > li.li-niveau1:nth-of-type(3) > a::before { content: "🥃"; }

#header #menu > li.li-niveau1:nth-of-type(4) > a::before { content: "🍺"; }

#header #menu > li.li-niveau1:nth-of-type(5) > a::before { content: "🎁"; }

#header #menu > li.li-niveau1:nth-of-type(6) > a::before { content: "🏢"; }

#header #menu > li.li-niveau1:nth-of-type(7) > a::before { content: "📍"; }

/* 9q.5 — Bandeau d'annonce : aplat encre, texte papier.
   Il reprenait le jaune de l'en-tête et s'y fondait. Le texte ne vit pas dans
   `.header-banner`, qui est vide, mais dans `#header-right-text`, à
   l'intérieur de la bande de navigation. C'est donc cette bande qui porte
   l'aplat, sur toute la largeur. */
#header .header-nav {
  background-color: var(--b3-encre);
}

#header .header-nav > .container > .row > .hidden-sm-down {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 46px;
  padding: var(--b3-space-2xs) var(--b3-space-sm);
  text-align: center;
}

#header #header-right-text,
#header .header-right {
  background-color: transparent;
}

/* Le premier élément du méga-menu est un libellé « Menu » ajouté par le
   module : il occupe une pastille sans mener nulle part. */
#header #menu > li.li-niveau1:first-child,
#header #menu > li.li-niveau1:first-child {
  display: none;
}

#header #header-right-text span[style],
#header #header-right-text strong span[style],
#header #header-right-text p {
  background-color: transparent !important;
  color: var(--b3-papier) !important;
}

/* --------------------------------------------------------------------------
   9septdecies. Suggestions de recherche
   -------------------------------------------------------------------------- */
.ui-autocomplete.searchbar-autocomplete,
#header .ui-autocomplete {
  z-index: 800;
  max-height: min(60vh, 460px);
  padding: var(--b3-space-2xs);
  border: 1px solid var(--b3-trait);
  border-radius: var(--b3-radius);
  background-color: var(--b3-papier);
  box-shadow: 0 18px 40px oklch(0.19 0.012 90 / 0.16);
  overflow-y: auto;
  list-style: none;
}

@media (max-width: 767px) {
.ui-autocomplete.searchbar-autocomplete,
  #header .ui-autocomplete {
    left: var(--b3-space-xs) !important;
    right: var(--b3-space-xs) !important;
    width: auto !important;
  }
}

main > header#header { order: -3; }

/* --------------------------------------------------------------------------
   9terdecies. Pages de catalogue — même aplat que l'accueil
   L'en-tête restait blanc hors de la page d'accueil : la marque disparaissait
   dès qu'on entrait dans le catalogue.
   -------------------------------------------------------------------------- */
/* L'aplat de marque vaut sur tout le site. Il était énuméré page par page,
   si bien que la fiche produit, le panier, le compte et les pages CMS
   gardaient un en-tête transparent : l'identité disparaissait dès qu'on
   quittait l'accueil ou une liste. */
#header {
  position: static;
  background-color: var(--b3-jaune);
}

/* Le thème peint ce conteneur en blanc : sur les pages de catalogue, une
   bande claire coupait l'aplat jaune en deux. */
#header .header-top,
#header .header-top > .container,
#header .header-top > .container > .row,
#header .header-top .col-md-12 {
  background-color: transparent;
  border: 0;
  box-shadow: none;
}

#header #menu > li.li-niveau1 > a.a-niveau1 {
  display: inline-flex;
  align-items: center;
  min-height: 40px;
  padding: 0 var(--b3-space-md);
  border-radius: var(--b3-radius-pill);
  background-color: var(--b3-papier);
  color: var(--b3-encre);
  font-weight: 800;
  font-size: 0.8125rem;
  text-transform: uppercase;
  text-decoration: none;
}

#header #adtm_menu,
#header #adtm_menu_inner,
#header #menu {
  background-color: transparent;
  background-image: none;
  border: 0;
  box-shadow: none;
}

#header #search_widget form {
  background-color: var(--b3-papier);
}


/* --------------------------------------------------------------------------
   Rayons — refonte

   Ce qui rendait la barre disgracieuse tenait d'abord à la typographie, pas à
   la forme : le module laissait le lien en « Roboto Condensed » et son <span>
   intérieur en « Times New Roman ». Trois familles cohabitaient donc dans un
   en-tête censé n'en porter qu'une, et les libellés changeaient de dessin d'une
   pastille à l'autre.

   La barre reprend la police du site, un rythme régulier, et l'inversion
   encre/jaune au survol — le même geste que la pastille de marque du hero.
   -------------------------------------------------------------------------- */

#header #menu > li.li-niveau1 > a.a-niveau1,
#header #menu > li.li-niveau1 > a.a-niveau1 > span,
#header #menu > li.li-niveau1 > a.a-niveau1 .advtm_menu_span {
  font-family: var(--b3-font);
  font-style: normal;
}

#header #menu > li.li-niveau1 > a.a-niveau1 {
  /* Largeur de fonte resserrée : les libellés de rayon sont des étiquettes de
     signalétique, pas du texte courant. */
  font-stretch: 88%;
  font-weight: 800;
  letter-spacing: 0.04em;
  border: 1.5px solid transparent;
  transition:
    background-color var(--b3-dur-fast) var(--b3-ease),
    color var(--b3-dur-fast) var(--b3-ease),
    border-color var(--b3-dur-fast) var(--b3-ease);
}

/* Le pictogramme se pose sur une pastille jaune : il cesse de flotter contre le
   mot, et rappelle l'encre de marque sur chaque rayon. */
#header #menu > li.li-niveau1 > a.a-niveau1::before {
  display: grid;
  place-items: center;
  width: 1.9em;
  height: 1.9em;
  margin-left: -0.35em;
  border-radius: 50%;
  background-color: var(--b3-jaune);
  font-size: 0.92em;
}

#header #menu > li.li-niveau1 > a.a-niveau1:hover,
#header #menu > li.li-niveau1 > a.a-niveau1:focus-visible {
  background-color: var(--b3-encre);
  border-color: var(--b3-encre);
  color: var(--b3-jaune);
}

/* Sur l'encre, la pastille du pictogramme s'efface : deux jaunes superposés
   feraient tache. */
#header #menu > li.li-niveau1 > a.a-niveau1:hover::before,
#header #menu > li.li-niveau1 > a.a-niveau1:focus-visible::before {
  background-color: transparent;
}

/* Le rayon ouvert reste en encre : la barre indique où l'on se trouve. */
#header #menu > li.li-niveau1.sfHover > a.a-niveau1 {
  background-color: var(--b3-encre);
  border-color: var(--b3-encre);
  color: var(--b3-jaune);
}


/* --------------------------------------------------------------------------
   Rayons — reprise du gabarit

   Le pictogramme flottait au-dessus du libellé au lieu de partager sa ligne.
   La cause n'était pas l'alignement mais la disposition : le module impose

     #adtm_menu ul#menu li.li-niveau1 a.a-niveau1 { display: block; float: left }

   soit deux identifiants, deux classes et **trois** éléments. Les règles
   précédentes n'en comptaient que deux et perdaient l'arbitrage : le lien
   restait en bloc, où `align-items` n'a aucun effet, et le <span> intérieur —
   lui aussi en bloc — passait à la ligne. D'où onze pixels d'écart entre le
   centre de la pastille et celui du libellé.

   Le sélecteur reprend donc celui du module et lui ajoute `#header`.
   -------------------------------------------------------------------------- */

#header #adtm_menu ul#menu li.li-niveau1 a.a-niveau1 {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.5em;
  float: none;
  min-height: 42px;
  /* Six rayons plus l'accès pros doivent tenir sur une ligne : le rembourrage
     et le corps suivent la largeur disponible plutôt que de forcer un retour. */
  padding: 0 clamp(var(--b3-space-2xs), 0.9vw, var(--b3-space-sm));
  /* Contour franc plutôt qu'ombre : la pastille se détache de l'aplat jaune
     par le trait, comme tout le reste du système.

     `!important` est ici le seul recours : le module écrit une règle par
     entrée de menu, `li.advtm_menu_1 a.a-niveau1 { border-width: 0 !important }`,
     générée depuis sa configuration en back-office. Aucune spécificité ne
     l'emporte sur un `!important`, et ces règles ne sont pas modifiables sans
     toucher au module. */
  border: 2px solid var(--b3-encre) !important;
  border-radius: var(--b3-radius-pill);
  background-color: var(--b3-papier);
  font-size: clamp(0.75rem, 0.88vw, 0.875rem);
  font-weight: 800;
  font-stretch: 86%;
  letter-spacing: 0.02em;
  line-height: 1;
  color: var(--b3-encre);
}

/* Le libellé partage la ligne du pictogramme : en bloc, il la quittait. */
#header #adtm_menu ul#menu li.li-niveau1 a.a-niveau1 > span,
#header #adtm_menu ul#menu li.li-niveau1 a.a-niveau1 .advtm_menu_span {
  display: inline;
  min-height: 0;
  height: auto;
  padding: 0;
  line-height: 1;
  font-weight: 800;
}

/* Pictogramme franchement plus grand, sur son disque jaune. `flex: none`
   l'empêche de se laisser comprimer par le libellé. */
#header #adtm_menu ul#menu li.li-niveau1 a.a-niveau1::before {
  flex: none;
  display: grid;
  place-items: center;
  width: 1.7em;
  height: 1.7em;
  margin-left: -0.15em;
  border-radius: 50%;
  background-color: var(--b3-jaune);
  font-size: 1.2em;
  line-height: 1;
}

#header #adtm_menu ul#menu li.li-niveau1 a.a-niveau1:hover,
#header #adtm_menu ul#menu li.li-niveau1 a.a-niveau1:focus-visible,
#header #adtm_menu ul#menu li.li-niveau1.sfHover a.a-niveau1 {
  background-color: var(--b3-encre);
  color: var(--b3-jaune);
}

#header #adtm_menu ul#menu li.li-niveau1 a.a-niveau1:hover::before,
#header #adtm_menu ul#menu li.li-niveau1 a.a-niveau1:focus-visible::before,
#header #adtm_menu ul#menu li.li-niveau1.sfHover a.a-niveau1::before {
  background-color: var(--b3-papier);
}

/* --------------------------------------------------------------------------
   « Accès pros » — même gabarit que les rayons

   L'entrée s'affichait en texte nu sous la barre, sans rien qui la désigne
   comme cliquable. Elle prend la pastille des rayons : c'est un accès de même
   nature, il doit s'énoncer de la même façon.
   -------------------------------------------------------------------------- */

#header #adtm_menu ul#menu {
  flex-wrap: nowrap;
}

#header .row.main-menu {
  display: flex;
  justify-content: center;
  padding: 0 0 var(--b3-space-2xs);
}

#header .row.main-menu ul,
#header .row.main-menu .menu {
  display: flex;
  justify-content: center;
  gap: var(--b3-space-2xs);
  margin: 0;
  padding: 0;
  list-style: none;
  width: auto;
  float: none;
}

#header .row.main-menu a {
  display: inline-flex;
  align-items: center;
  gap: 0.5em;
  min-height: 38px;
  padding: 0 var(--b3-space-xs);
  border: 2px solid var(--b3-encre);
  border-radius: var(--b3-radius-pill);
  background-color: var(--b3-papier);
  font-size: clamp(0.6875rem, 0.8vw, 0.8125rem);
  font-weight: 800;
  font-stretch: 86%;
  letter-spacing: 0.02em;
  line-height: 1;
  text-transform: uppercase;
  text-decoration: none;
  color: var(--b3-encre);
  transition:
    background-color var(--b3-dur-fast) var(--b3-ease),
    color var(--b3-dur-fast) var(--b3-ease);
}

#header .row.main-menu a::before {
  content: "🏛";
  flex: none;
  display: grid;
  place-items: center;
  width: 1.75em;
  height: 1.75em;
  border-radius: 50%;
  background-color: var(--b3-jaune);
  font-size: 1.05em;
  line-height: 1;
}

#header .row.main-menu a:hover,
#header .row.main-menu a:focus-visible {
  background-color: var(--b3-encre);
  color: var(--b3-jaune);
}

#header .row.main-menu a:hover::before,
#header .row.main-menu a:focus-visible::before {
  background-color: var(--b3-papier);
}


/* --------------------------------------------------------------------------
   Tampon de l'en-tête, signature et bandeau

   Le tampon paraissait rogné : l'agrandissement qui cadre le cachet sur le
   fichier — un rectangle de 500 × 246 dont le tampon n'occupe que
   [25 → 225] — débordait de la boîte de l'image, et le pourtour du cachet,
   celui qui porte le texte circulaire, se retrouvait coupé. L'enveloppe rogne
   désormais à sa place, et le facteur est ramené juste sous le rapport exact
   (246/200 ≈ 1.23) pour laisser respirer le liseré.
   -------------------------------------------------------------------------- */

#header #_desktop_logo .b3-logo__tampon,
#header #_mobile_logo .b3-logo__tampon,
#header .b3-logo .b3-logo__tampon {
  flex: none;
  display: block;
  width: 96px;
  aspect-ratio: 1;
  overflow: hidden;
  border-radius: 50%;
  /* Cerne d'encre. Le tampon est jaune sur un en-tête jaune : sans trait, son
     bord se dissout dans l'aplat et le cachet flotte. Le cerne est porté par
     une ombre plutôt qu'une bordure — une bordure aurait mangé la boîte et
     réduit le cachet d'autant. */
  box-shadow: 0 0 0 2px var(--b3-encre);
}

/* Deux identifiants, comme la règle de taille historique posée sur `.logo` :
   c'est l'enveloppe qui porte désormais les dimensions, l'image ne fait plus
   que la remplir. */
/* Le fichier servi est carré et détouré : ni agrandissement, ni cadrage à
   gauche. Les deux réglages qui vivaient ici visaient l'ancien rectangle de
   500 × 246 et rognaient le pourtour du cachet — celui qui porte le texte
   circulaire — dès qu'ils s'appliquaient à une image déjà ronde. */
#header #_desktop_logo .b3-logo__tampon .logo,
#header #_mobile_logo .b3-logo__tampon .logo,
#header .b3-logo .b3-logo__tampon .logo {
  display: block;
  width: 100%;
  height: 100%;
  min-width: 0;
  max-height: none;
  object-fit: contain;
  object-position: center;
  border-radius: 0;
  transform: none;
}

/* La signature gagne en corps et descend d'un cran : alignée sur le centre du
   tampon, elle paraissait flotter au-dessus de la ligne de base du cachet. */
#header .b3-logo__wordmark {
  align-self: center;
  margin-top: 0.6em;
  font-size: 0.8125rem;
  line-height: 1.2;
  letter-spacing: 0.05em;
}

/* Bandeau d'annonce : vingt pixels de haut ne laissaient pas respirer un texte
   en capitales espacées, qui touchait les deux bords. */
#header .header-nav {
  min-height: 38px;
  padding-top: var(--b3-space-3xs);
  padding-bottom: var(--b3-space-3xs);
}

#header .header-nav > .container > .row > .hidden-sm-down {
  min-height: 34px;
}


/* Le module pousse son conteneur de menu de 150 px vers la droite, réglage
   hérité de sa mise en page d'origine où le logo occupait cette bande. La
   grille de l'en-tête place désormais le menu elle-même : cette marge ne fait
   plus que le sortir du conteneur, de 59 px sur un écran de 1440. */
#header #adtm_menu {
  width: 100%;
  margin-left: 0;
  padding-left: 0;
}


/* Le menu des rayons se centrait à l'intérieur de lui-même, non dans la page :
   15 px de marge à gauche contre 423 à droite. La largeur fautive n'était pas
   celle de la liste — qui suit son parent — mais celle de `#adtm_menu_inner`,
   fixée à 850 px dans un conteneur de 1258. */
#header #adtm_menu #adtm_menu_inner {
  /* `!important` comme pour les bordures des pastilles : cette largeur est
     générée depuis la configuration du module en back-office, avec une
     priorité qu'aucune spécificité ne renverse. */
  width: 100% !important;
}

#header #adtm_menu ul#menu {
  width: 100%;
  justify-content: center;
}


/* --------------------------------------------------------------------------
   Barre mobile — le tampon avant le menu

   Le tampon ouvre la barre, à gauche du bouton de menu : c'est le repère de
   marque, il vient avant l'outil. Il occupait 207 px de large sur 117 de haut,
   soit un tiers d'un écran de téléphone pour un logo : ramené au format du
   tampon, il laisse la place aux trois commandes.
   -------------------------------------------------------------------------- */

@media (max-width: 991px) {
  #header .hidden-md-up.mobile {
    grid-template-columns: auto 46px minmax(0, 1fr) auto auto;
    grid-template-areas: "logo menu . compte panier";
    align-items: center;
  }

  #header #_mobile_logo {
    grid-area: logo;
    justify-self: start;
    width: auto;
    max-width: none;
    margin: 0;
    text-align: left;
  }

  #header #_mobile_logo .b3-logo {
    gap: 0;
  }

  /* La signature ne tient pas à côté du tampon sur un écran de 390 px : le
     tampon la porte déjà, gravée en cercle. */
  #header #_mobile_logo .b3-logo__wordmark {
    display: none;
  }

  #header #_mobile_logo .b3-logo__tampon {
    width: 52px;
  }
}


/* ===== 04-carte.css ====================================================== */

/* ===== 04-carte.css ====================================================== */
/* --------------------------------------------------------------------------
   7. Vignette produit
   Composant unique, partagé par les grilles de catégorie et tous les
   carrousels du thème. Voir le gabarit pour le détail des défauts corrigés.
   -------------------------------------------------------------------------- */
/* Le thème dimensionnait les vignettes en colonnes flottantes :
   `#products .grid .product-miniature { width: 33.333% }` plus un
   `padding: 0 15px` de gouttière. Dans une grille CSS, ce pourcentage se
   recalcule sur la colonne et écrase la vignette à un tiers de sa place. */
#products .grid .product-miniature,
#products .product-miniature,
.featured-products .product-miniature,
.product-accessories .product-miniature,
.homepage-products .product-miniature,
#special-products .product-miniature {
  width: 100%;
  padding: 0;
  float: none;
}

.b3-card {
  container-type: inline-size;
  container-name: carte;
  display: flex;
  flex-direction: column;
  height: 100%;
  border: 1px solid var(--b3-trait);
  border-radius: var(--b3-radius);
  background-color: var(--b3-papier);
  overflow: hidden;
  transition: border-color var(--b3-dur-fast) var(--b3-ease),
              transform var(--b3-dur-base) var(--b3-ease);
}

.b3-card:hover,
.b3-card:focus-within {
  border-color: var(--b3-encre);
  transform: translateY(-3px);
}


/* 7.1 — Le visuel. Cadre à proportion constante : les bouteilles sont
   photographiées à des échelles différentes, une hauteur fixe les aligne. */
.b3-card__media {
  position: relative;
  background-color: var(--b3-papier-2);
}

.b3-card__thumb {
  display: block;
  aspect-ratio: 4 / 5;
}

#products .b3-card__thumb img,
.featured-products .b3-card__thumb img,
.homepage-products .b3-card__thumb img,
.product-accessories .b3-card__thumb img,
.b3-card__thumb img {
  width: 100%;
  height: 100%;
  max-width: 100%;
  margin: 0;
  padding: var(--b3-space-sm);
  object-fit: contain;
  mix-blend-mode: multiply;
  transition: transform var(--b3-dur-base) var(--b3-ease);
}


/* La loupe est pilotée en JS (origine suivant le pointeur, appui maintenu au
   doigt) : le survol seul ne doit pas concurrencer son agrandissement. */
.b3-card__thumb {
  overflow: hidden;
  cursor: zoom-in;
  touch-action: manipulation;
}

.b3-card__total {
  margin: var(--b3-space-2xs) 0 0;
  padding-top: var(--b3-space-2xs);
  border-top: 1px dashed var(--b3-trait);
  color: var(--b3-encre);
  font-size: 0.8125rem;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
}


/* 7.2 — Drapeaux. */
.b3-card__flags {
  position: absolute;
  top: var(--b3-space-2xs);
  left: var(--b3-space-2xs);
  display: flex;
  flex-direction: column;
  /* Par défaut, un conteneur flex en colonne étire ses enfants bloc sur
     toute sa largeur (`align-items: stretch`, valeur initiale). Chaque
     étiquette — « Rupture de stock » compris — en épousait ainsi la
     largeur maximale autorisée par `max-width` plus bas, quand son texte
     tenait sur une ligne bien plus courte : le bandeau plein s'étirait sans
     raison. */
  align-items: flex-start;
  gap: 4px;
  margin: 0;
  padding: 0;
  list-style: none;
}

.b3-card__flag {
  align-self: flex-start;
  padding: 4px 10px;
  border-radius: var(--b3-radius-pill);
  background-color: var(--b3-encre);
  color: var(--b3-papier);
  font-size: 0.625rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.08em;
}

.b3-card__flag--on-sale,
.b3-card__flag--discount {
  background-color: var(--b3-jaune);
  color: var(--b3-encre);
}


/* Le module de favoris place son bouton dans la zone visuelle. */
.b3-card__media .wishlist-button-add,
.b3-card__media .js-wishlist-button {
  top: var(--b3-space-2xs);
  right: var(--b3-space-2xs);
}



/* 7.3 — Le texte. */
/* Le thème centrait le bloc texte des vignettes d'accueil et de catégorie.
   La carte 3B s'aligne à gauche : l'œil descend une colonne unique,
   étiquette puis nom puis prix. */
#products .b3-card__body,
.featured-products .b3-card__body,
.homepage-products .b3-card__body,
.product-accessories .b3-card__body,
.b3-card .b3-card__body {
  display: flex;
  flex-direction: column;
  flex: 1 1 auto;
  gap: 2px;
  padding: var(--b3-space-sm);
  text-align: left;
}

.b3-card__origin {
  margin: 0 0 2px;
  color: var(--b3-encre-douce);
  font-size: 0.6875rem;
  font-weight: 600;
  line-height: 1.3;
  text-transform: uppercase;
  letter-spacing: 0.14em;
}

.b3-card__title,
h2.b3-card__title {
  margin: 0;
  font-size: 0.9375rem;
  font-weight: 700;
  font-stretch: 92%;
  line-height: 1.3;
  letter-spacing: -0.005em;
  text-transform: none;
  text-align: left;
}


/* Le thème centre le lien du titre et lui réimpose son `display` avec des
   sélecteurs plus spécifiques que la classe seule : d'où la reprise par
   `#products` / `.featured-products` / `.homepage-products`. */
#products .b3-card .b3-card__title a,
.featured-products .b3-card .b3-card__title a,
.homepage-products .b3-card .b3-card__title a,
.product-accessories .b3-card .b3-card__title a,
.b3-card .b3-card__title a {
  display: -webkit-box;
  -webkit-line-clamp: 2;
  line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
  color: var(--b3-encre);
  text-align: left;
  text-decoration: none;
  /* Pas de césure automatique : un nom d'appellation coupé en deux
     (« CHAM-PAGNE ») se lit mal et fait amateur. */
  hyphens: manual;
  overflow-wrap: break-word;
}

.b3-card__title a:hover,
.b3-card__title a:focus {
  text-decoration: underline;
  text-underline-offset: 3px;
}

.b3-card__meta {
  margin: 0;
  color: var(--b3-encre-douce);
  font-size: 0.8125rem;
  line-height: 1.4;
}


/* 7.4 — Pied de carte : prix, quantité, panier. `margin-top: auto` cale la
   ligne d'achat en bas quelle que soit la longueur du nom, pour que les
   prix s'alignent d'une carte à l'autre.

   `min-width: 0` sur les deux groupes : sans lui, un enfant de flex refuse de
   passer sous sa largeur de contenu et déborde du cadre au lieu de se
   replier — c'est ce qui rognait le bouton panier. */
.b3-card__footer {
  display: flex;
  flex-wrap: wrap;
  min-width: 0;
  align-items: center;
  justify-content: space-between;
  gap: var(--b3-space-2xs);
  margin-top: auto;
  padding-top: var(--b3-space-xs);
}

.b3-card__price {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: 6px;
  text-align: left;
}

.b3-card__price .price {
  color: var(--b3-encre);
  font-size: 1.125rem;
  font-weight: 800;
  font-variant-numeric: tabular-nums;
  letter-spacing: -0.01em;
}


/* Le surligneur n'apparaît que sur une promotion réelle : une vignette
   ordinaire reste encre sur papier, sans jaune. C'est le garde-fou contre la
   dérive vers le registre discount. */
.b3-card.b3-on-sale .b3-card__price .price {
  padding: 0.08em 0.38em;
  border-radius: var(--b3-radius-sm);
  background-color: var(--b3-jaune);
}

.b3-card__price .regular-price {
  color: var(--b3-encre-douce);
  font-size: 0.875rem;
  font-weight: 400;
  font-variant-numeric: tabular-nums;
  text-decoration: line-through;
}

.b3-card__price .discount-percentage,
.b3-card__price .discount-amount {
  padding: 2px 8px;
  border-radius: var(--b3-radius-pill);
  background-color: var(--b3-encre);
  color: var(--b3-papier);
  font-size: 0.6875rem;
  font-weight: 700;
}



/* 7.5 — Quantité et panier, dans le flux : atteignables au doigt comme au
   clavier. Le thème ne les révélait qu'au survol. */
/* La quantité précède immédiatement le bouton d'ajout, tous deux calés à
   droite du pied de carte : on règle, puis on valide, dans le sens de lecture
   et sans que le regard traverse la carte entre les deux gestes.

   L'écart entre eux est volontairement plus court que la gouttière courante —
   ils forment une seule commande, pas deux contrôles voisins. */
.b3-card__cart {
  display: flex;
  align-items: center;
  flex-wrap: nowrap;
  justify-content: flex-end;
  gap: var(--b3-space-3xs);
  min-width: 0;
  max-width: 100%;
}

.b3-card__cart .b3-qty { order: 1; }

.b3-card__cart .b3-card__add { order: 2; }


/* Le pied garde le prix à gauche et la commande à droite : sur une carte
   large, empiler les deux laissait une bande vide au milieu. */
.b3-card__footer {
  align-items: flex-end;
}



/* Pas d'`overflow: hidden` ici : sur une carte étroite, le champ s'étirait et
   le bouton « + » se retrouvait rogné au lieu de simplement se resserrer. */
/* Sélecteur de quantité : réglette encre, chiffre papier, commandes en
   pastilles claires. Pas d'`overflow: hidden` — sur une carte étroite, le
   champ s'étirait et le bouton « + » se retrouvait rogné. */
.b3-qty {
  display: flex;
  align-items: center;
  gap: 4px;
  flex: 0 0 auto;
  padding: 4px;
  border: 0;
  border-radius: var(--b3-radius-pill);
  background-color: var(--b3-encre);
}


/* `flex: 0 0 28px` et `aspect-ratio` sont nécessaires : le thème applique un
   rembourrage à tous ses boutons, ce qui étirait ces pastilles en ovales. */
.b3-qty__step {
  display: grid;
  place-items: center;
  flex: 0 0 28px;
  width: 28px;
  min-width: 28px;
  height: 28px;
  aspect-ratio: 1;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background-color: var(--b3-papier);
  color: var(--b3-encre);
  font-size: 0.9375rem;
  font-weight: 800;
  line-height: 1;
  cursor: pointer;
  transition: background-color var(--b3-dur-fast) var(--b3-ease);
}

.b3-qty__step:hover,
.b3-qty__step:focus-visible {
  background-color: var(--b3-jaune);
}

.b3-qty__input {
  flex: 0 0 30px;
  width: 30px;
  min-width: 30px;
  height: 28px;
  padding: 0;
  border: 0;
  background: transparent;
  color: var(--b3-papier);
  font-family: var(--b3-font);
  font-size: 0.875rem;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  text-align: center;
  -moz-appearance: textfield;
}

.b3-qty__input::-webkit-outer-spin-button,
.b3-qty__input::-webkit-inner-spin-button {
  -webkit-appearance: none;
  margin: 0;
}


/* Ajout au panier : pastille jaune, tracé encre.
   Le tracé était en papier, à 1,53:1 sur le jaune 3B — sous le 3:1 exigé pour
   un élément graphique porteur de sens, et difficile à distinguer en plein
   soleil sur un téléphone. En encre, le même panier atteint 12:1 et le bouton
   garde sa présence : c'est l'aplat jaune qui le signale, pas le tracé. */
.b3-card__add {
  display: grid;
  place-items: center;
  width: 50px;
  height: 50px;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background-color: var(--b3-jaune);
  color: var(--b3-encre);
  cursor: pointer;
  transition: background-color var(--b3-dur-fast) var(--b3-ease);
}

.b3-card__add .material-icons {
  color: var(--b3-encre);
}

.b3-card__add:hover,
.b3-card__add:focus {
  background-color: var(--b3-jaune-fonce);
}

.b3-card__add .material-icons {
  font-size: 20px;
}

.b3-card__oos {
  margin: 0;
  padding: 6px 12px;
  border: 1px solid var(--b3-trait-fort);
  border-radius: var(--b3-radius-pill);
  color: var(--b3-encre-douce);
  font-size: 0.6875rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.08em;
}


/* Vignettes à l'intérieur d'un carrousel.

   Le gabarit du module groupait ses produits deux par deux dans des
   `div.owl-item` écrits en dur. Owl encapsule ensuite chaque diapositive dans
   ses propres `.owl-item`, qu'il dimensionne en style en ligne : les deux
   niveaux portaient la même classe, et le conteneur interne, sans largeur
   propre, écrasait les cartes à deux pixels. La surcharge du gabarit dans le
   thème nomme ce groupe `.b3-slide`. */
.owl-carousel .b3-slide {
  display: flex;
  flex-direction: column;
  width: 100%;
}

.owl-carousel .b3-slide > ul,
.owl-carousel .product-item > ul {
  display: flex;
  flex-direction: column;
  gap: var(--b3-space-md);
  width: 100%;
  margin: 0;
  padding: 0;
  list-style: none;
}

.owl-carousel .b3-slide li {
  list-style: none;
  width: 100%;
}


/* La gouttière est portée par la diapositive, pas par la carte : une marge sur
   la carte s'ajoutait à la largeur calculée par Owl et faisait déborder la
   rangée. Le `border-box` garantit que le retrait reste à l'intérieur. */
.owl-carousel .owl-item {
  box-sizing: border-box;
  padding: 0 var(--b3-space-2xs);
}

.owl-carousel .owl-item .b3-card {
  box-sizing: border-box;
  width: 100%;
  max-width: 100%;
  margin: 0;
}

.owl-carousel .owl-stage-outer {
  overflow: hidden;
}


/* Owl calcule la largeur des diapositives au chargement : sans cette réserve,
   la section se replie à zéro le temps de l'initialisation. */
.homepage-products .owl-carousel:not(.owl-loaded) {
  min-height: 420px;
}

.b3-picks .owl-nav,
.featured-products .owl-nav {
  display: block;
}


/* Le thème habille ses flèches avec des sélecteurs plus spécifiques, ancrés
   sur l'identifiant du carrousel : on reprend le même chemin. */
#featuredproducts-carousel .owl-nav .owl-prev,
#featuredproducts-carousel .owl-nav .owl-next,
.b3-picks .owl-nav button,
.b3-picks .owl-nav .owl-prev,
.b3-picks .owl-nav .owl-next,
.featured-products .owl-nav button,
.homepage-products .owl-nav button {
  position: absolute;
  top: 50%;
  z-index: 3;
  display: grid;
  place-items: center;
  width: 56px;
  height: 56px;
  margin: 0;
  padding: 0;
  /* Pas de cerclage : sur l'aplat jaune, un liseré papier dessinait un cercle
     de plus autour du bouton. */
  border: 0;
  /* Le thème dessine ses flèches avec une sprite posée en image de fond —
     `sprite.png` à -428px -896px, un bouton rond gris. Une couleur de fond ne
     remplace pas une image de fond : les deux se superposaient, et le disque
     gris de la sprite apparaissait à l'intérieur du disque d'encre. C'est le
     « double bouton » — un seul élément, deux fonds empilés. */
  background-image: none;
  border-radius: 50%;
  background-color: var(--b3-encre);
  color: var(--b3-jaune);
  transform: translateY(-50%);
  transition: background-color var(--b3-dur-fast) var(--b3-ease);
}

#featuredproducts-carousel .owl-nav .owl-prev,
.b3-picks .owl-nav .owl-prev { left: calc(var(--b3-space-lg) * -1); right: auto; }

#featuredproducts-carousel .owl-nav .owl-next,
.b3-picks .owl-nav .owl-next { right: calc(var(--b3-space-lg) * -1); left: auto; }

.b3-picks .owl-nav button:hover {
  background-color: var(--b3-encre-douce);
}


/* Le module fournit des div vides comme libellés : la flèche est dessinée
   ici, en jaune sur l'encre. */
#featuredproducts-carousel .owl-nav .prev-arrow,
#featuredproducts-carousel .owl-nav .next-arrow,
.b3-picks .owl-nav .prev-arrow,
.b3-picks .owl-nav .next-arrow {
  width: 22px;
  height: 22px;
  background-color: currentColor;
  -webkit-mask: var(--b3-arrow) center / contain no-repeat;
  mask: var(--b3-arrow) center / contain no-repeat;
}

#featuredproducts-carousel .owl-nav .prev-arrow,
.b3-picks .owl-nav .prev-arrow {
  --b3-arrow: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M15 5l-7 7 7 7'/%3E%3C/svg%3E");
}

#featuredproducts-carousel .owl-nav .next-arrow,
.b3-picks .owl-nav .next-arrow {
  --b3-arrow: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M9 5l7 7-7 7'/%3E%3C/svg%3E");
}


/* Sous 1200 px, la place manque de part et d'autre : seuls les points
   subsistent. */
@media (max-width: 1199px) {
.b3-picks .owl-nav,
  .featured-products .owl-nav {
    display: none;
  }
}

.b3-picks .owl-dots,
.featured-products .owl-dots,
.homepage-products .owl-dots {
  display: flex;
  justify-content: center;
  gap: var(--b3-space-2xs);
  margin-top: var(--b3-space-md);
}

.b3-picks .owl-dot,
.featured-products .owl-dot,
.homepage-products .owl-dot {
  width: 10px;
  height: 10px;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background-color: oklch(0.19 0.012 90 / 0.28);
  transition: background-color var(--b3-dur-fast) var(--b3-ease),
              transform var(--b3-dur-fast) var(--b3-ease);
}


/* La cible tactile fait 44 px sans que le point grossisse. */
.b3-picks .owl-dot::before,
.featured-products .owl-dot::before,
.homepage-products .owl-dot::before {
  content: "";
  position: absolute;
  inset: -17px;
}

.b3-picks .owl-dot,
.featured-products .owl-dot,
.homepage-products .owl-dot {
  position: relative;
}

.b3-picks .owl-dot.active,
.featured-products .owl-dot.active,
.homepage-products .owl-dot.active {
  background-color: var(--b3-encre);
  transform: scale(1.25);
}



/* 9ter.2 — Cibles tactiles.
   L'audit relevait jusqu'à 99 éléments sous 40 px de haut. Le minimum
   retenu est 44 px, conformément à PRODUCT.md. */
/* Les commandes de quantité gardent leur forme ronde : la cible tactile de
   44 px est obtenue par une zone étendue en pseudo-élément, et non en
   étirant la pastille — une hauteur imposée ici la rendait ovale. */
.b3-qty__step {
  position: relative;
}

.b3-qty__step::after {
  content: "";
  position: absolute;
  inset: -8px;
}


/* Hauteur homogène d'une carte à l'autre.
   Le titre occupe une ou deux lignes selon le produit, et la ligne
   caractéristiques manque parfois : les cartes allaient de 409 à 463 px, ce
   qui donnait une rangée en dents de scie. On réserve la place plutôt que de
   contraindre le carrousel, dont Owl calcule lui-même la géométrie. */
.b3-card__title {
  min-height: 2.6em;
}

.b3-card__meta {
  min-height: 1.4em;
}


/* L'étiquette de région tient sur une ligne : « Languedoc - Roussillon »
   passait à deux et décalait toute la carte vers le bas. */
.b3-card__origin {
  min-height: 1.3em;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}


/* Sur l'aplat jaune, les cartes prennent le papier : elles doivent se détacher
   du fond, pas s'y fondre. */
.b3-picks .b3-card {
  background-color: var(--b3-papier);
  border-color: transparent;
}


/* 9q.6 — Sélecteur de quantité : chiffre réellement centré.
   Le thème aligne les champs numériques à gauche et leur pose un
   rembourrage ; la piste paraissait décalée. */
.b3-card .b3-qty__input,
.b3-card input.b3-qty__input {
  padding: 0;
  text-align: center;
  text-indent: 0;
  box-sizing: border-box;
}


/* Filtre actif : le carrousel cède la place à une grille. Owl positionne sa
   piste par transformation et fixe la largeur de chaque diapositive ; il faut
   défaire les deux pour que la grille reprenne la main. */
.b3-owl-off .owl-stage-outer,
.b3-owl-off .owl-stage {
  width: auto !important;
  transform: none !important;
  transition: none !important;
}

.b3-owl-off .owl-stage {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(230px, 1fr));
  gap: var(--b3-space-md);
}

/* Chaque diapositive porte deux produits. Tant que `.owl-item` restait une
   cellule de la grille, filtrer sur une couleur y laissait un produit visible
   et un masqué — donc une demi-cellule vide, et des trous dans la rangée.

   `display: contents` fait disparaître la cellule : ce sont les `li` qui
   deviennent les éléments de grille, et un `li` masqué ne prend plus de
   place. */
.b3-owl-off .owl-item {
  display: contents;
}

.b3-owl-off .owl-item.cloned,
.b3-owl-off .owl-nav,
.b3-owl-off .owl-dots {
  display: none;
}

/* Filet de sécurité : l'attribut `hidden` vaut `display: none` par la feuille
   du navigateur, que n'importe quelle règle d'auteur portant `display`
   emporte. Sur une grille, un élément ainsi ressuscité laisse un trou. */
.b3-owl-off [hidden],
.b3-bestsellers [hidden] {
  display: none !important;
}

/* Deux colonnes jusqu'à 767 px, et non 479. `auto-fit` avec un minimum de
   230 px ne tenait qu'une seule colonne sur un téléphone de 430 points : les
   vignettes se retrouvaient seules, à gauche, dans un écran vide. Le seuil
   suit celui du reste du responsive. */
@media (max-width: 767px) {
  .b3-owl-off .owl-stage {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: var(--b3-space-sm) var(--b3-space-xs);
  }
}

@media (max-width: 479px) {
.b3-card__body {
    padding: var(--b3-space-xs);
  }
}



/* --------------------------------------------------------------------------
   Métrique des étiquettes de la vignette — valeurs arrêtées ici, une fois.

   Ces deux lignes tiraient leur taille d'un sélecteur groupé écrit pour
   l'accueil (`.b3-entry__kicker, .b3-card__origin, .b3-partner span…`), qui
   traversait trois composants à la fois. Leur rendu dépendait donc de la
   position relative de ce groupe dans le fichier, c'est-à-dire du hasard de
   l'ordre des correctifs : la vignette gagnait ou perdait deux pixels et demi
   selon l'endroit où la règle avait atterri.

   La carte fixe désormais sa propre métrique de référence. Le plancher de 12 px
   est respecté : en dessous, une capitale espacée cesse d'être lisible sur un
   téléphone.

   La requête de conteneur `carte (max-width: 340px)` reste seule habilitée à
   descendre sous ce plancher, parce qu'elle sait, elle, que la vignette est
   étroite. Elle était jusqu'ici placée avant ces règles et donc toujours
   écrasée : le compactage annoncé ne s'appliquait nulle part, et la vignette
   gardait deux pixels et demi de trop.
   -------------------------------------------------------------------------- */
.b3-card__origin {
  font-size: 0.75rem;
  min-height: 1.3em;
}

.b3-card__meta {
  font-size: 0.75rem;
  min-height: 1.4em;
}








/* ----- repris de 09-divers ----- */

.b3-owl-off .b3-slide,
.b3-owl-off .b3-slide > ul {
  display: contents;
}


/* ==========================================================================
   Mise en favori

   Le module pose un bouton blanc portant une ligature Material
   (`favorite_border`) sur l'angle de la vignette : invisible sur un visuel
   clair, et rien n'indique l'état une fois le produit ajouté.

   Le rose est ici le seul écart assumé à la palette. Il ne désigne pas un
   produit ni une action marchande — c'est un repère personnel, qui doit se
   distinguer du jaune de la marque sans le concurrencer. Le cœur passe au
   jaune une fois retenu : deux états, deux couleurs, plus un changement de
   forme (contour puis plein) pour que l'information ne tienne pas à la seule
   teinte.
   ========================================================================== */

.b3-card .wishlist-button-add,
.product-miniature .wishlist-button-add {
  display: grid;
  place-items: center;
  width: 42px;
  height: 42px;
  border: 0;
  border-radius: 50%;
  background-color: oklch(0.63 0.19 12);
  box-shadow: none;
  cursor: pointer;
  transition:
    background-color var(--b3-dur-fast) var(--b3-ease),
    transform var(--b3-dur-fast) var(--b3-ease);
}

.b3-card .wishlist-button-add:hover,
.product-miniature .wishlist-button-add:hover {
  background-color: oklch(0.57 0.20 12);
  transform: scale(1.06);
}

.b3-card .wishlist-button-add:focus-visible,
.product-miniature .wishlist-button-add:focus-visible {
  outline: 3px solid var(--b3-encre);
  outline-offset: 2px;
}

/* La ligature du module est remplacée par un tracé : une police d'icônes ne
   se charge pas toujours, et son rendu varie d'un système à l'autre. */
.b3-card .wishlist-button-add i,
.product-miniature .wishlist-button-add i {
  font-size: 0;
  line-height: 0;
  color: transparent;
}

.b3-card .wishlist-button-add::before,
.product-miniature .wishlist-button-add::before {
  content: "";
  display: block;
  width: 21px;
  height: 21px;
  background-color: var(--b3-papier);
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2.1' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M12 20.5s-7.3-4.6-7.3-9.6A4.2 4.2 0 0 1 12 8a4.2 4.2 0 0 1 7.3 2.9c0 5-7.3 9.6-7.3 9.6Z'/%3E%3C/svg%3E") center / contain no-repeat;
  mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2.1' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M12 20.5s-7.3-4.6-7.3-9.6A4.2 4.2 0 0 1 12 8a4.2 4.2 0 0 1 7.3 2.9c0 5-7.3 9.6-7.3 9.6Z'/%3E%3C/svg%3E") center / contain no-repeat;
  transition: background-color var(--b3-dur-fast) var(--b3-ease);
}

/* Produit retenu : le cœur se remplit et passe au jaune. La classe est posée
   par le module ; `aria-pressed` couvre le cas où il l'exprime autrement. */
.b3-card .wishlist-button-add.active::before,
.b3-card .wishlist-button-add[aria-pressed="true"]::before,
.product-miniature .wishlist-button-add.active::before,
.product-miniature .wishlist-button-add[aria-pressed="true"]::before {
  background-color: var(--b3-jaune);
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='%23000'%3E%3Cpath d='M12 20.5s-7.3-4.6-7.3-9.6A4.2 4.2 0 0 1 12 8a4.2 4.2 0 0 1 7.3 2.9c0 5-7.3 9.6-7.3 9.6Z'/%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='%23000'%3E%3Cpath d='M12 20.5s-7.3-4.6-7.3-9.6A4.2 4.2 0 0 1 12 8a4.2 4.2 0 0 1 7.3 2.9c0 5-7.3 9.6-7.3 9.6Z'/%3E%3C/svg%3E");
}

/* Le battement ne dure que le temps du geste : il confirme le clic, il ne
   décore pas. Classe posée puis retirée par 3b.js. */
.b3-card .wishlist-button-add.b3-bat::before,
.product-miniature .wishlist-button-add.b3-bat::before {
  animation: b3-battement 420ms var(--b3-ease);
}

@keyframes b3-battement {
  0%   { transform: scale(1); }
  35%  { transform: scale(1.35); }
  60%  { transform: scale(0.94); }
  100% { transform: scale(1); }
}

@media (prefers-reduced-motion: reduce) {
  .b3-card .wishlist-button-add.b3-bat::before,
  .product-miniature .wishlist-button-add.b3-bat::before {
    animation: none;
  }

  .b3-card .wishlist-button-add:hover,
  .product-miniature .wishlist-button-add:hover {
    transform: none;
  }
}


/* --------------------------------------------------------------------------
   Position des flèches du carrousel

   Sorties du conteneur, elles étaient tranchées net par un `overflow` parent :
   il n'en restait qu'un demi-disque contre le bord. Elles rentrent dans la
   zone défilante, où elles se détachent par leur cerclage papier sans
   dépendre de ce que fait le conteneur.

   Le carrousel des témoignages a lui aussi ses flèches, dans un bloc masqué :
   nulles en taille mais présentes dans le document, elles apparaissaient dans
   tout relevé comme un second jeu.
   -------------------------------------------------------------------------- */

#featuredproducts-carousel .owl-nav .owl-prev,
.b3-picks .owl-nav .owl-prev,
.homepage-products .owl-nav .owl-prev {
  left: 10px;
}

#featuredproducts-carousel .owl-nav .owl-next,
.b3-picks .owl-nav .owl-next,
.homepage-products .owl-nav .owl-next {
  right: 10px;
}

#testimonial-slider .owl-nav,
#testimonial-slider .owl-prev,
#testimonial-slider .owl-next,
.testimonial-outer .owl-nav {
  display: none;
}


/* --------------------------------------------------------------------------
   Rupture de stock

   L'indisponibilité se lisait comme une mention parmi d'autres, en encre
   douce. C'est pourtant l'information qui décide : inutile de comparer un prix
   qu'on ne peut pas payer. Elle prend la couleur d'alerte — le seul emploi que
   DESIGN.md laisse au rouge — doublée du mot, jamais la couleur seule.
   -------------------------------------------------------------------------- */

.b3-card__oos {
  display: inline-flex;
  align-items: center;
  gap: 0.4em;
  margin: 0;
  padding: 0.35em 0.75em;
  border-radius: var(--b3-radius-pill);
  background-color: var(--b3-alerte);
  font-size: 0.75rem;
  font-weight: 800;
  letter-spacing: 0.06em;
  line-height: 1.2;
  text-transform: uppercase;
  color: var(--b3-papier);
}

.b3-card__oos::before {
  content: "";
  flex: none;
  width: 0.95em;
  height: 0.95em;
  background-color: currentColor;
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2.4' stroke-linecap='round'%3E%3Ccircle cx='12' cy='12' r='9'/%3E%3Cpath d='M6 6l12 12'/%3E%3C/svg%3E") center / contain no-repeat;
  mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2.4' stroke-linecap='round'%3E%3Ccircle cx='12' cy='12' r='9'/%3E%3Cpath d='M6 6l12 12'/%3E%3C/svg%3E") center / contain no-repeat;
}


/* Les flèches redescendent entre les deux rangées.

   Une passe antérieure les avait remontées à 27 % — « à hauteur de visuel »,
   disait le commentaire. C'était une erreur d'appréciation : à cette hauteur
   elles se posent *sur* la première rangée de vignettes, masquent une
   bouteille de chaque côté, et l'on clique sur la flèche en croyant ouvrir la
   fiche. Entre les deux rangées, elles ne recouvrent rien. */
#featuredproducts-carousel .owl-nav .owl-prev,
#featuredproducts-carousel .owl-nav .owl-next,
.b3-picks .owl-nav .owl-prev,
.b3-picks .owl-nav .owl-next,
.homepage-products .owl-nav button {
  top: 50%;
}


/* --------------------------------------------------------------------------
   La grille ne se rétractait pas sur le contenu

   Le carrousel vit dans `.homepage-products.products.row` — une rangée
   Bootstrap, donc un conteneur en `display: flex`. Owl posait jusqu'ici une
   largeur explicite sur sa piste, ce qui masquait le problème ; dès que la
   piste passe en grille, `.owl-carousel` redevient un élément flexible sans
   base, et un élément flexible sans base se réduit à la largeur de son
   contenu.

   D'où deux colonnes de quatre-vingts points serrées à gauche d'un écran de
   quatre cents : la grille était juste, c'est son conteneur qui se rétractait.

   La rangée redevient un bloc. Owl s'accommode d'un parent en bloc — il mesure
   la largeur disponible, ce qui est précisément ce qu'on veut ici.
   -------------------------------------------------------------------------- */

/* L'ID l'emporte sur `.products.row:not(:has(.owl-carousel))` de
   06-catalogue.css — même compte de classes, chargé après. Owl désactivé sur
   « Notre catalogue » (voir outils/desactiver-owl-catalogue.php) a fait
   disparaître son `.owl-carousel` du DOM, ce qui a rendu cette rangée
   éligible à la règle catalogue par erreur : `display: grid` sur le
   conteneur ne laissait que deux pistes (la grille et ses points de
   pagination), chacune écrasée à une fraction de la largeur réelle. */
#featured-products.b3-picks .homepage-products,
#featured-products.b3-picks .products.row {
  display: block;
  margin-inline: 0;
}

/* La grille de repli elle-même reste en flottement Bootstrap (`.item`,
   `col-lg-3`…), qui ne connaît pas de hauteur de ligne commune : une seule
   carte au nom plus long qu'à l'ordinaire (donc plus haute) empêche les
   colonnes suivantes de « clear » avant elle, laissant les autres cartes de
   sa ligne loin en dessous et un vide béant sous les colonnes plus courtes.
   Grille CSS native : chaque ligne s'aligne sur sa propre carte la plus
   haute, sans effet de bord sur les lignes voisines. Les classes `col-*`
   posent encore un `float` et un `padding` hérités de Bootstrap qu'il faut
   neutraliser pour laisser la grille seule décider de la largeur. */
#featured-products #featuredproducts-grid.products-grid {
  display: grid;
  grid-template-columns: repeat(1, 1fr);
  gap: var(--b3-space-md);
}

#featured-products #featuredproducts-grid.products-grid > .item {
  float: none;
  width: auto;
  padding-left: 0;
  padding-right: 0;
}

@media (min-width: 768px) {
  #featured-products #featuredproducts-grid.products-grid {
    grid-template-columns: repeat(2, 1fr);
  }
}

@media (min-width: 992px) {
  #featured-products #featuredproducts-grid.products-grid {
    grid-template-columns: repeat(3, 1fr);
  }
}

@media (min-width: 1200px) {
  #featured-products #featuredproducts-grid.products-grid {
    grid-template-columns: repeat(4, 1fr);
  }
}

.b3-picks .owl-carousel,
.b3-picks .b3-ventes-grille,
.b3-picks .b3-rayon-grille {
  width: 100%;
}


/* --------------------------------------------------------------------------
   La rupture de stock, dite une seule fois

   La vignette l'annonçait deux fois : une étiquette d'encre en haut à gauche,
   et un bandeau rouge dans le pied à la place du bouton d'ajout. Deux formes,
   deux couleurs, un seul message — et le pied s'en trouvait déséquilibré, le
   bandeau rouge occupant la largeur d'une ligne d'achat.

   On garde la position de l'étiquette — le coin haut gauche, où l'œil arrive —
   et la couleur du bandeau, qui dit l'indisponibilité sans qu'on ait à lire.
   -------------------------------------------------------------------------- */

.b3-card__flag--out_of_stock {
  background-color: var(--b3-rouge, #a92321);
  color: var(--b3-papier);
  font-weight: 800;
}

/* Le bandeau du pied disparaît : l'étiquette suffit, et le pied retrouve sa
   ligne d'achat. */
.b3-card__oos {
  display: none;
}

/* Coffret cadeau non commandable en ligne : aucune étiquette en haut de
   vignette n'annonce ce cas (à la différence de la rupture de stock), donc
   ce texte reste affiché — sans lui, le bouton « Appeler pour commander »
   apparaît sans qu'on sache pourquoi. */
.b3-card__coffret {
  display: block;
  margin: 0 0 0.35em;
  color: var(--b3-encre-douce);
  font-size: 0.6875rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.06em;
}


/* --------------------------------------------------------------------------
   Les flèches du carrousel, hors des vignettes

   Elles étaient posées en absolu à mi-hauteur du carrousel, c'est-à-dire sur
   la première rangée de cartes : elles masquaient une bouteille à gauche et
   une à droite, et l'on cliquait sur la flèche en croyant ouvrir la fiche.

   Chaque diapositive portant deux produits l'un sous l'autre, le milieu du
   carrousel tombe entre les deux rangées. Les flèches y restent, mais sortent
   de la largeur des cartes : elles se placent dans la marge, au-delà du bord.
   -------------------------------------------------------------------------- */

/* `-28px` supposait une marge de page assez large pour loger la flèche à côté
   du conteneur. Mesuré à 1280px de large — une largeur d'ordinateur portable
   très courante — cette marge ne fait que 24px : la flèche gauche se
   retrouvait à `-4px`, la droite à `1284px`, et `overflow-x: clip` sur
   `<body>` (00-fondations.css) les tranchait net. Posées sur le fond plutôt
   que dans une marge dont la largeur n'est pas garantie, elles restent
   toujours entières, quelle que soit la largeur d'écran. */
@media (min-width: 1200px) {
  #featuredproducts-carousel .owl-nav .owl-prev,
  .b3-picks .owl-nav .owl-prev,
  .featured-products .owl-nav .owl-prev {
    left: 4px;
  }

  #featuredproducts-carousel .owl-nav .owl-next,
  .b3-picks .owl-nav .owl-next,
  .featured-products .owl-nav .owl-next {
    right: 4px;
  }
}

/* En deçà, la marge n'existe plus : les flèches restent au bord, mais à cheval
   plutôt que par-dessus — la moitié de leur disque déborde du carrousel. */
@media (min-width: 768px) and (max-width: 1199px) {
  #featuredproducts-carousel .owl-nav .owl-prev,
  .b3-picks .owl-nav .owl-prev {
    left: -16px;
  }

  #featuredproducts-carousel .owl-nav .owl-next,
  .b3-picks .owl-nav .owl-next {
    right: -16px;
  }
}

/* Le carrousel cesse de rogner ce qui dépasse, sans quoi les flèches sorties
   dans la marge seraient coupées. */
.b3-picks .owl-carousel,
.featured-products .owl-carousel,
.b3-picks .owl-stage-outer {
  overflow: visible;
}


/* --------------------------------------------------------------------------
   Les flèches se calent sur le carrousel, non sur leur conteneur

   Mesuré : le carrousel fait 984 px de haut, et les flèches se posaient à
   265 px — soit la moitié de `.owl-nav`, que le thème positionne, et non la
   moitié du carrousel. Elles tombaient donc au milieu de la première rangée
   de cartes, celle qu'elles masquaient.

   `.owl-nav` redevient un conteneur sans position : le bloc de référence des
   flèches devient `.owl-carousel`, et `top: 50%` tombe entre les deux
   rangées, là où chaque diapositive sépare ses deux produits.
   -------------------------------------------------------------------------- */

.b3-picks .owl-carousel,
.featured-products .owl-carousel,
#featuredproducts-carousel {
  position: relative;
}

.b3-picks .owl-nav,
.featured-products .owl-nav,
#featuredproducts-carousel .owl-nav {
  position: static;
  margin: 0;
  padding: 0;
  height: 0;
}

/* Rien ne rogne les flèches sorties dans la marge, sur toute la chaîne. */
.b3-picks,
.b3-picks .featured-products,
.b3-picks .products.row,
.b3-picks .homepage-products {
  overflow: visible;
}

/* Sous 1200 px la marge manque : les flèches reviennent au bord intérieur,
   posées sur le fond et non sur une carte — la rangée du bas commence plus
   bas que le milieu, elles n'y masquent rien. */
@media (max-width: 1199px) {
  #featuredproducts-carousel .owl-nav .owl-prev,
  .b3-picks .owl-nav .owl-prev {
    left: 4px;
  }

  #featuredproducts-carousel .owl-nav .owl-next,
  .b3-picks .owl-nav .owl-next {
    right: 4px;
  }
}

/* Sur téléphone, le carrousel est une grille : les flèches n'ont plus d'objet. */
@media (max-width: 767px) {
  .b3-picks .owl-nav {
    display: none;
  }
}


/* --------------------------------------------------------------------------
   « J'en ai besoin ! » — l'issue quand la bouteille manque

   Une rupture de stock est le seul endroit du catalogue où le visiteur n'a
   rien à faire. Il voit le vin, il le veut, et la page lui répond non. Or la
   cave en a souvent en réserve, ou peut le commander : un appel règle la
   question en trente secondes.

   Le bouton prend le rouge de l'étiquette de rupture — même sujet, même
   couleur — mais en tracé plutôt qu'en aplat : c'est une proposition, pas une
   alerte de plus.
   -------------------------------------------------------------------------- */

.b3-card__besoin {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.5em;
  width: 100%;
  min-height: 40px;
  margin-top: var(--b3-space-3xs);
  padding: 0 var(--b3-space-sm);
  border: 2px solid var(--b3-rouge, #a92321);
  border-radius: var(--b3-radius-pill);
  background-color: transparent;
  color: var(--b3-rouge, #a92321);
  font-size: 0.75rem;
  font-weight: 800;
  letter-spacing: 0.03em;
  text-decoration: none;
  transition: background-color var(--b3-dur-fast) var(--b3-ease),
              color var(--b3-dur-fast) var(--b3-ease);
}

.b3-card__besoin:hover,
.b3-card__besoin:focus-visible {
  background-color: var(--b3-rouge, #a92321);
  color: var(--b3-papier);
}

/* Le combiné, dessiné en masque : une police d'icônes pour une seule forme ne
   se justifie pas. */
.b3-card__besoin-picto {
  flex: none;
  width: 15px;
  height: 15px;
  background-color: currentColor;
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M22 16.9v3a2 2 0 0 1-2.2 2 19.8 19.8 0 0 1-8.6-3.1 19.5 19.5 0 0 1-6-6A19.8 19.8 0 0 1 2.1 4.2 2 2 0 0 1 4.1 2h3a2 2 0 0 1 2 1.7c.1 1 .4 1.9.7 2.8a2 2 0 0 1-.5 2.1L8.1 9.9a16 16 0 0 0 6 6l1.3-1.3a2 2 0 0 1 2.1-.4c.9.3 1.8.6 2.8.7a2 2 0 0 1 1.7 2z'/%3E%3C/svg%3E") center / contain no-repeat;
  mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M22 16.9v3a2 2 0 0 1-2.2 2 19.8 19.8 0 0 1-8.6-3.1 19.5 19.5 0 0 1-6-6A19.8 19.8 0 0 1 2.1 4.2 2 2 0 0 1 4.1 2h3a2 2 0 0 1 2 1.7c.1 1 .4 1.9.7 2.8a2 2 0 0 1-.5 2.1L8.1 9.9a16 16 0 0 0 6 6l1.3-1.3a2 2 0 0 1 2.1-.4c.9.3 1.8.6 2.8.7a2 2 0 0 1 1.7 2z'/%3E%3C/svg%3E") center / contain no-repeat;
}


/* ===== 05-accueil.css ==================================================== */

/* ===== 05-accueil.css ==================================================== */
.b3-section {
  max-width: 1320px;
  margin: 0 auto;
  padding: var(--b3-space-2xl) var(--b3-space-md);
}

.b3-section__title {
  margin: 0 0 var(--b3-space-lg);
  font-size: clamp(1.75rem, 3.5vw, 2.5rem);
  font-weight: 800;
  font-stretch: 75%;
  line-height: 1.05;
  letter-spacing: -0.015em;
  text-transform: uppercase;
  color: var(--b3-encre);
}


/* Le hero enchaîne directement sur l'en-tête : pas de couture entre les deux. */
.b3-hero {
  margin-top: 0;
}

.b3-hero__inner {
  padding-top: clamp(var(--b3-space-2xs), 1.4vw, var(--b3-space-md));
}


/* 9bis.1 — Hero. Le seul aplat de couleur pleine du site.

   Le contenu de la page vit dans un `.container` centré à 1300px. Les aplats
   doivent filer de bord à bord : une affiche n'a pas de marge. D'où la sortie
   de conteneur, qui compense la gouttière quelle que soit sa largeur. */
.b3-hero,
.b3-reassure,
.b3-figures {
  width: 100vw;
  max-width: 100vw;
  margin-left: calc(50% - 50vw);
  margin-right: calc(50% - 50vw);
}

.b3-hero {
  background-color: var(--b3-jaune);
  color: var(--b3-encre);
}

/* Fond mobile portrait uniquement : le visuel hero (colonne de droite) se
   masque déjà sous 575px (voir plus bas), la section devient un aplat jaune
   nu. La photo, posée en fond et floutée, lui redonne une texture sans
   concurrencer le texte — qui garde ses propres fonds pleins (pastille,
   encart noir) pour rester lisible par-dessus. Jamais en paysage : une image
   verticale y serait coupée aux deux tiers. */
@media (max-width: 575px) and (orientation: portrait) {
  .b3-hero {
    position: relative;
    isolation: isolate;
    /* La section ne dépassait pas la hauteur de son contenu (titre, promesse,
       boutons) : le fond photo s'arrêtait donc au milieu de l'écran, et le
       jaune nu reprenait en dessous jusqu'au prochain bloc. `100dvh` — la
       hauteur réellement visible, barre d'adresse mobile déduite — fait
       tenir la photo sur tout l'écran, quelle que soit la longueur du texte.
       `100vh` reste en secours pour les moteurs sans `dvh`. */
    min-height: 100vh;
    min-height: 100dvh;
  }

  /* Retour au jaune uni : l'aplat de `.b3-hero` (posé plus haut dans ce
     fichier) suffit, aucun fond photo ici. La transparence d'en-tête posée
     ici visait justement à laisser cette photo remonter sous le logo et les
     icônes — sans elle, rendre l'en-tête transparent ne sert plus qu'à
     laisser voir le papier derrière lui (l'en-tête est `position: static`,
     donc jamais superposé au jaune du hero qui commence après lui dans le
     flux) : un bandeau clair au-dessus d'un aplat jaune qui ne l'atteint
     plus. `#header` retrouve son jaune plein par défaut (03-entete.css),
     continu avec celui du hero — rien à réécrire ici. */
}

/* Même traitement en portrait tablette (iPad, 576 → 1024) : la maquette
   desktop y affichait encore la bande de bouteille recadrée (voir la règle
   `.b3-hero__visuel img` ci-dessous) au-dessus d'un aplat jaune nu, une mise
   en page pensée pour un écran large plaquée sur un format vertical. Jamais
   en paysage — une tablette à l'horizontale a la largeur pour la vraie
   grille desktop. */
@media (min-width: 576px) and (max-width: 1024px) and (orientation: portrait) {
  .b3-hero {
    position: relative;
    isolation: isolate;
    min-height: 100vh;
    min-height: 100dvh;
  }

  .b3-hero::before {
    content: "";
    position: absolute;
    inset: 0;
    z-index: -1;
    background-image: url("../img/hero-mobile-fond.jpg");
    background-image: image-set(
      url("../img/hero-mobile-fond.webp") type("image/webp"),
      url("../img/hero-mobile-fond.jpg") type("image/jpeg")
    );
    background-size: cover;
    background-position: center;
    filter: blur(1px);
  }

  .b3-hero__visuel {
    display: none;
  }

  /* La grille à deux colonnes (voir `.b3-hero__inner` plus bas) ne se
     replie qu'à 767px : sans ce repli, la colonne visuelle masquée
     laissait un vide de 1.55fr à côté du texte. */
  .b3-hero__inner {
    grid-template-columns: 1fr;
    gap: var(--b3-space-lg);
  }

  .b3-hero__mark {
    order: -1;
  }
}

.b3-hero__inner {
  display: grid;
  /* 1.35fr -> 1.55fr : la colonne visuelle gagne un peu de largeur sur la
     colonne de texte, qui garde largement de quoi respirer à 1320px. */
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.55fr);
  align-items: center;
  gap: var(--b3-space-xl);
  max-width: 1320px;
  margin: 0 auto;
  padding: clamp(var(--b3-space-xl), 6vw, var(--b3-space-3xl)) var(--b3-space-md);
}


/* Pastille de marque, en tête du hero. Le libellé demandé était en jaune sur
   blanc : à 1.53:1, PRODUCT.md l'interdit sans exception. L'aplat est donc
   inversé — encre pleine, texte jaune, 12:1 — ce qui garde le jaune éclatant,
   respecte le contraste, et reprend le geste du tampon circulaire du logo. */
/* Pastille de marque. Papier plutôt qu'encre : posée sur l'aplat jaune, elle
   se lit comme une étiquette collée sur l'affiche, et laisse l'encre au titre,
   qui la suit immédiatement. Deux pleins d'encre l'un sous l'autre se
   disputaient l'attention.

   Elle est aussi plus petite et remonte : c'est une mention d'origine, pas une
   accroche. Le titre reste le premier objet du regard. */
.b3-hero__kicker {
  display: inline-flex;
  align-items: center;
  gap: 0.5em;
  margin: 0 0 var(--b3-space-sm);
  padding: 0.5em 1em;
  border-radius: var(--b3-radius-pill);
  background-color: var(--b3-papier);
  font-size: 0.6875rem;
  font-weight: 800;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  color: var(--b3-encre);
}


/* Le millésime se détache par un point, pas par une bordure : la pastille doit
   rester une forme pleine. */
.b3-hero__kicker b {
  position: relative;
  padding-left: 0.8em;
  font-weight: 800;
  /* Le millésime passe en encre adoucie : sur papier, l'ancien blanc était
     invisible et le jaune du point plafonnait à 1,53:1. */
  color: var(--b3-encre-douce);
}

.b3-hero__kicker b::before {
  content: "";
  position: absolute;
  left: 0;
  top: 50%;
  width: 4px;
  height: 4px;
  border-radius: 50%;
  background-color: var(--b3-encre);
  transform: translateY(-50%);
}

.b3-hero__title {
  margin: 0 0 var(--b3-space-md);
  font-size: clamp(2.5rem, 6.5vw, 5rem);
  font-weight: 900;
  font-stretch: 70%;
  line-height: 0.92;
  letter-spacing: -0.03em;
  color: var(--b3-encre);
  text-wrap: balance;
}

/* Le chapô prend la pastille papier : sur l'aplat jaune, un paragraphe en
   encre nue se lisait comme une légende du titre. Encadré, il devient une
   promesse à part entière — les quatre chiffres qu'il porte (900 références,
   trois villes) sont les seuls faits du hero. */
/* La phrase passe sur fond d'encre. Le jaune demandé sur les mots importants
   plafonne à 1,53:1 sur papier — PRODUCT.md l'y interdit sans exception. Sur
   l'encre il atteint 12:1, et le blanc du reste de la phrase, 15:1. C'est le
   fond qui change, pas la règle. */
.b3-hero__lead {
  display: inline-block;
  max-width: 46ch;
  margin: 0 0 var(--b3-space-lg);
  padding: var(--b3-space-sm) var(--b3-space-md);
  border-radius: var(--b3-radius);
  background-color: var(--b3-encre);
  font-size: clamp(1rem, 1.4vw, 1.1875rem);
  font-weight: 700;
  line-height: 1.55;
  color: var(--b3-papier);
}

/* Les segments de preuve — le nombre de références, les trois villes. Ce sont
   les seuls faits vérifiables de la phrase ; le reste est de la syntaxe. */
.b3-hero__lead b {
  font-weight: 800;
  color: var(--b3-jaune);
}

.b3-hero__actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--b3-space-xs);
}

.b3-hero__mark img {
  display: block;
  width: clamp(150px, 17vw, 240px);
  height: auto;
  border-radius: 50%;
}


/* 9bis.3 — Réassurance. */
.b3-reassure {
  background-color: var(--b3-encre);
  color: var(--b3-papier);
}

.b3-reassure__list {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: var(--b3-space-md);
  max-width: 1320px;
  margin: 0 auto;
  padding: var(--b3-space-md);
  list-style: none;
}

.b3-reassure__list li {
  display: flex;
  align-items: center;
  gap: var(--b3-space-xs);
}

.b3-reassure__icon {
  display: grid;
  place-items: center;
  flex: 0 0 42px;
  width: 42px;
  height: 42px;
  border-radius: 50%;
  background-color: oklch(0.975 0.008 90 / 0.12);
  color: var(--b3-jaune);
}

.b3-reassure__text {
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 0;
}


/* Sous 768 px, les quatre promesses défilent horizontalement plutôt que de
   s'empiler sur quatre rangées. L'animation s'interrompt au survol, au focus
   et si le visiteur a demandé moins de mouvement. */
@media (max-width: 767px) {
.b3-reassure {
    overflow: hidden;
  }

.b3-reassure__list {
    display: flex;
    flex-wrap: nowrap;
    width: max-content;
    gap: var(--b3-space-xl);
    animation: b3-marquee 26s linear infinite;
  }

.b3-reassure__list li {
    flex: 0 0 auto;
  }

.b3-reassure:hover .b3-reassure__list,
  .b3-reassure:focus-within .b3-reassure__list {
    animation-play-state: paused;
  }
}

@media (prefers-reduced-motion: reduce) {
.b3-reassure__list {
    animation: none;
  }
}

.b3-reassure__list strong {
  font-size: 0.8125rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  color: var(--b3-jaune);
}

.b3-reassure__list span {
  font-size: 0.875rem;
  line-height: 1.4;
  color: var(--b3-papier);
}


/* 9bis.4 — Trois entrées. Volontairement de tailles inégales : trois pavés
   identiques, c'est la grille de cartes que DESIGN.md proscrit. */
/* Trois entrées de tailles inégales. La majeure tient toute la hauteur du
   bloc et emporte la décision ; les deux autres se partagent la colonne de
   droite. Trois colonnes égales donnaient un triptyque sans hiérarchie, où
   rien ne disait par où commencer. */
.b3-entries {
  display: grid;
  grid-template-columns: 1.15fr 1fr;
  grid-template-rows: repeat(2, minmax(0, 1fr));
  grid-template-areas:
    "majeure haute"
    "majeure basse";
  gap: var(--b3-space-sm);
  min-height: 30rem;
}

.b3-entry--majeure { grid-area: majeure; }
.b3-entry--haute   { grid-area: haute; }
.b3-entry--basse   { grid-area: basse; }

/* La majeure a la place de respirer : son titre prend le corps d'un titre de
   section, pas celui d'une étiquette de carte. */
.b3-entry--majeure .b3-entry__title {
  font-size: clamp(1.75rem, 2.6vw, 2.5rem);
  line-height: 1.05;
}

/* 22ch tenaient quand la carte n'avait qu'un aplat pour fond. Avec un titre au
   corps d'un titre de section, la même mesure cassait « Les raretés à
   découvrir » en quatre lignes d'un mot. La largeur suit désormais la carte,
   et seule la ligne de titre reste bornée. */
.b3-entry--majeure .b3-entry__body {
  max-width: none;
}

.b3-entry--majeure .b3-entry__title {
  max-width: 14ch;
}

.b3-entry {
  position: relative;
  display: flex;
  flex-direction: column;
  min-height: 300px;
  border-radius: var(--b3-radius);
  overflow: hidden;
  text-decoration: none;
  transition: transform var(--b3-dur-base) var(--b3-ease);
}


/* Zone visuelle dédiée, en haut : les bouteilles ne passent jamais sous le
   texte. Elles sont décoratives — le sens est porté par le titre — d'où
   `alt=""` et `aria-hidden` dans le gabarit. */
.b3-entry__media {
  display: flex;
  align-items: flex-end;
  justify-content: center;
  gap: var(--b3-space-2xs);
  flex: 1 1 auto;
  min-height: 150px;
  margin: var(--b3-space-sm) var(--b3-space-sm) 0;
  padding: var(--b3-space-sm) var(--b3-space-sm) 0;
  border-radius: var(--b3-radius-sm);
  /* Les photos produit sont détourées sur fond blanc : posées telles quelles
     sur l'aplat encre, elles y découpaient des rectangles clairs. Une plaque
     papier unifie les trois entrées, quelle que soit leur couleur de fond. */
  background-color: var(--b3-papier);
  overflow: hidden;
}

.b3-entry__media img {
  display: block;
  width: auto;
  height: 100%;
  max-height: 158px;
  object-fit: contain;
  mix-blend-mode: multiply;
}

.b3-entry__body {
  display: flex;
  flex-direction: column;
  gap: var(--b3-space-2xs);
  flex: 0 0 auto;
  padding: var(--b3-space-md);
}

.b3-entry--ink {
  background-color: var(--b3-encre);
  color: var(--b3-papier);
}

.b3-entry--paper {
  background-color: var(--b3-papier-2);
  color: var(--b3-encre);
}

.b3-entry--yellow {
  background-color: var(--b3-jaune);
  color: var(--b3-encre);
}

.b3-entry__kicker {
  font-size: 0.6875rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.14em;
}

.b3-entry--ink .b3-entry__kicker {
  color: var(--b3-jaune);
}

.b3-entry__title {
  font-size: clamp(1.375rem, 2vw, 1.75rem);
  font-weight: 800;
  font-stretch: 80%;
  line-height: 1.1;
  letter-spacing: -0.015em;
  color: inherit;
}


/* Appel à l'action en pilule pleine : un lien souligné se lisait mal sur les
   aplats et n'indiquait pas de zone cliquable. */
.b3-entry__cta {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  align-self: flex-start;
  min-height: 42px;
  margin-top: var(--b3-space-2xs);
  padding: 0 var(--b3-space-md);
  border-radius: var(--b3-radius-pill);
  background-color: var(--b3-encre);
  color: var(--b3-papier);
  font-size: 0.75rem;
  font-weight: 800;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  text-decoration: none;
  transition: background-color var(--b3-dur-fast) var(--b3-ease),
              color var(--b3-dur-fast) var(--b3-ease);
}


/* Sur l'aplat encre, le bouton s'inverse pour rester lisible. */
.b3-entry--ink .b3-entry__cta {
  background-color: var(--b3-jaune);
  color: var(--b3-encre);
}

.b3-entry:hover .b3-entry__cta,
.b3-entry:focus .b3-entry__cta {
  background-color: var(--b3-jaune);
  color: var(--b3-encre);
}

.b3-entry--ink:hover .b3-entry__cta,
.b3-entry--ink:focus .b3-entry__cta {
  background-color: var(--b3-papier);
  color: var(--b3-encre);
}


/* Le survol ne doit jamais faire disparaître le texte de la carte : le
   `translateY` du conteneur suffit comme retour visuel. */
.b3-entry:hover .b3-entry__body,
.b3-entry:focus .b3-entry__body,
.b3-entry:hover .b3-entry__title,
.b3-entry:hover .b3-entry__kicker {
  opacity: 1;
  visibility: visible;
  color: inherit;
}

.b3-entry--ink:hover .b3-entry__title,
.b3-entry--ink .b3-entry__title {
  color: var(--b3-papier);
}

.b3-entry--paper .b3-entry__title,
.b3-entry--yellow .b3-entry__title {
  color: var(--b3-encre);
}


/* Emoji des rayons : décoratif, il ne remplace jamais le nom. */




/* 9bis.5 — Rayons. */
/* Les huit rayons tiennent sur une seule ligne : la largeur des pistes se
   contracte avec la place disponible plutôt que de renvoyer un rayon isolé
   à la ligne suivante. */
.b3-shelves__grid {
  display: grid;
  grid-template-columns: repeat(8, minmax(0, 1fr));
  gap: var(--b3-space-2xs);
}

.b3-shelves__grid .b3-shelf span:not(.b3-shelf__emoji) {
  font-size: clamp(0.6875rem, 0.9vw, 1rem);
  padding: var(--b3-space-2xs) var(--b3-space-2xs) var(--b3-space-xs);
  hyphens: auto;
}




/* Une bouteille du rayon, dans sa propre zone au-dessus du libellé. */


.b3-shelf:hover .b3-shelf__shot,
.b3-shelf:focus .b3-shelf__shot {
  transform: translateY(-5px);
}

.b3-shelf span {
  display: block;
  margin-top: auto;
  padding: var(--b3-space-sm);
  font-size: 1rem;
  font-weight: 700;
  font-stretch: 85%;
  line-height: 1.15;
  text-transform: uppercase;
  letter-spacing: 0.02em;
}

.b3-shelf:hover,
.b3-shelf:focus {
  background-color: var(--b3-jaune);
  color: var(--b3-encre);
}

.b3-shelf--rare {
  background-color: var(--b3-jaune);
  color: var(--b3-encre);
}

.b3-shelf--rare:hover,
.b3-shelf--rare:focus {
  background-color: var(--b3-encre);
  color: var(--b3-papier);
}


/* 9bis.5b — Nos partenaires. */
.b3-partners__lead {
  max-width: 60ch;
  margin: calc(var(--b3-space-lg) * -1) 0 var(--b3-space-lg);
  color: var(--b3-encre-douce);
  font-size: 1.0625rem;
  line-height: 1.6;
}

.b3-partners__grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: var(--b3-space-sm);
  margin: 0;
  padding: 0;
  list-style: none;
}

.b3-partner {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--b3-space-xs);
  height: 100%;
  padding: var(--b3-space-md);
  border: 1px solid var(--b3-trait);
  border-radius: var(--b3-radius);
  background-color: var(--b3-papier);
  color: var(--b3-encre);
  text-decoration: none;
  transition: border-color var(--b3-dur-fast) var(--b3-ease),
              transform var(--b3-dur-base) var(--b3-ease);
}

.b3-partner:hover,
.b3-partner:focus {
  border-color: var(--b3-encre);
  transform: translateY(-3px);
}


/* Médaillon rond, à l'image du tampon 3B. Les logos sont fournis en JPEG sur
   fond blanc : le disque les recadre proprement au lieu de laisser un carré
   clair posé sur le papier. */
.b3-partner img {
  width: 148px;
  height: 148px;
  max-width: 100%;
  padding: var(--b3-space-xs);
  border: 1px solid var(--b3-trait);
  border-radius: 50%;
  object-fit: contain;
  background-color: var(--b3-papier);
  transition: transform var(--b3-dur-base) var(--b3-ease);
}

.b3-partner:hover img,
.b3-partner:focus img {
  transform: scale(1.04);
}

.b3-partner__external {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  color: var(--b3-encre-douce);
  font-size: 0.75rem;
  font-weight: 600;
  text-transform: none;
  letter-spacing: 0;
}

.b3-partner span {
  font-size: 0.8125rem;
  font-weight: 700;
  text-align: center;
  text-transform: uppercase;
  letter-spacing: 0.08em;
}


/* La carte de la maison, à part de la grille des partenaires. Le médaillon
   grossit — c'est elle qui brasse, pas une marque parmi d'autres — et la
   vidéo occupe l'autre moitié plutôt qu'une photo figée. L'aplat jaune
   reprend le fond du plan de la vidéo elle-même : les deux se raccordent au
   lieu de juxtaposer deux couleurs de fond différentes. */
/* Flex, pas grid : deux colonnes en `fr` s'écartaient l'une de l'autre sur
   toute la largeur de la carte, la vidéo finissait centrée loin du logo au
   lieu d'être posée à côté. En flex, chacun garde la largeur de son contenu
   et les deux se tiennent comme un seul bloc, centré dans la carte. */
.b3-partner-maison {
  display: flex;
  align-items: center;
  justify-content: center;
  flex-wrap: wrap;
  gap: var(--b3-space-md);
  margin-bottom: var(--b3-space-md);
  padding: var(--b3-space-md);
  border: 0;
  border-radius: var(--b3-radius);
  background-color: var(--b3-jaune);
  text-decoration: none;
  color: var(--b3-encre);
  transition: transform var(--b3-dur-fast) var(--b3-ease);
}

.b3-partner-maison:hover,
.b3-partner-maison:focus {
  transform: translateY(-3px);
}

.b3-partner-maison__logo {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--b3-space-sm);
}

.b3-partner-maison__logo img {
  width: 220px;
  height: 220px;
  max-width: 100%;
  padding: var(--b3-space-sm);
  border: 1px solid var(--b3-trait);
  border-radius: 50%;
  object-fit: contain;
  background-color: var(--b3-papier);
  transition: transform var(--b3-dur-base) var(--b3-ease);
}

.b3-partner-maison:hover .b3-partner-maison__logo img,
.b3-partner-maison:focus .b3-partner-maison__logo img {
  transform: scale(1.04);
}

.b3-partner-maison__logo span {
  font-size: 0.9375rem;
  font-weight: 800;
  text-align: center;
  text-transform: uppercase;
  letter-spacing: 0.08em;
}

.b3-partner-maison__video {
  display: block;
  flex: 0 0 auto;
  width: min(360px, 100%);
  border-radius: var(--b3-radius-sm);
  overflow: hidden;
  aspect-ratio: 9 / 14;
  max-height: 560px;
}

.b3-partner-maison__video video {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

@media (max-width: 767px) {
  .b3-partner-maison {
    grid-template-columns: 1fr;
    gap: var(--b3-space-sm);
    justify-items: center;
    text-align: center;
  }

  .b3-partner-maison__logo img {
    width: 148px;
    height: 148px;
  }

  .b3-partner-maison__video {
    max-height: 440px;
    width: 100%;
  }
}


/* 9bis.6 — Repères chiffrés. */
/* La bande passait sur `papier-2`, à deux points de luminance du fond de page :
   elle ne se lisait pas comme une bande, et aucun réglage typographique n'y
   changeait rien tant que le cadre restait invisible.

   Elle prend l'encre. La page gagne son rythme — jaune, encre, papier, jaune,
   papier, encre — et les chiffres, en jaune sur encre, deviennent l'objet le
   plus contrasté de la section. C'est ce qu'on veut retenir. */
.b3-figures {
  background-color: var(--b3-encre);
  color: var(--b3-papier);
}

.b3-figures__inner {
  display: grid;
  /* Quatre colonnes fixes tant qu'elles tiennent : `auto-fit` en donnait
     trois puis une, et un chiffre isolé sur sa ligne perd son rang dans la
     série. La série se lit comme un tout ou pas du tout. */
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 0;
  max-width: 1320px;
  margin: 0 auto;
  padding: var(--b3-space-xl) var(--b3-space-md);
}

/* Un filet vertical sépare les repères, plutôt qu'une gouttière : quatre
   blocs flottants sur un aplat se lisaient comme quatre fragments. Le filet
   en fait une série — c'est ce que dit un tableau de chiffres. */
.b3-figure {
  display: flex;
  flex-direction: column;
  gap: var(--b3-space-3xs);
  padding: 0 var(--b3-space-md);
}

.b3-figure + .b3-figure {
  border-left: 1.5px solid color-mix(in oklab, var(--b3-encre) 16%, transparent);
}

.b3-figure:first-child {
  padding-left: 0;
}

.b3-figure:last-child {
  padding-right: 0;
}

.b3-figure__value {
  font-size: clamp(3rem, 5vw, 4.5rem);
  font-weight: 900;
  font-stretch: 70%;
  line-height: 1;
  letter-spacing: -0.03em;
  font-variant-numeric: tabular-nums;
  color: var(--b3-encre);
}

.b3-figure__plus {
  font-size: 0.6em;
  vertical-align: super;
}

/* L'étiquette passe sous le chiffre sans capitales espacées : « CAVES EN
   BRETAGNE » en petites capitales suivies de « Vitré · Fougères · Dinard » en
   bas de casse donnait trois registres typographiques pour trois lignes. Elle
   prend le corps d'une légende appuyée, en bas de casse. */
.b3-figure__label {
  font-size: 1.0625rem;
  font-weight: 800;
  font-stretch: 88%;
  text-transform: none;
  letter-spacing: -0.005em;
  line-height: 1.2;
  color: var(--b3-encre);
}

.b3-figure__detail {
  font-size: 0.9375rem;
  line-height: 1.45;
  color: var(--b3-encre-douce);
}

/* Le chiffre respire : c'est lui qu'on retient, l'étiquette ne fait que le
   nommer. */
.b3-figure__value {
  margin-bottom: var(--b3-space-3xs);
}

/* Sous 900 px, deux colonnes plutôt que quatre écrasées ; le filet suit. */
@media (max-width: 900px) {
  .b3-figures__inner {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    row-gap: var(--b3-space-lg);
  }

  .b3-figure {
    padding-inline: var(--b3-space-sm);
  }

  .b3-figure:nth-child(odd) {
    padding-left: 0;
    border-left: 0;
  }
}

@media (max-width: 479px) {
  .b3-figures__inner {
    grid-template-columns: 1fr;
  }

  .b3-figure {
    padding-inline: 0;
    border-left: 0;
  }

  .b3-figure + .b3-figure {
    padding-top: var(--b3-space-md);
    border-left: 0;
    border-top: 1.5px solid color-mix(in oklab, var(--b3-encre) 16%, transparent);
  }
}

@media (max-width: 767px) {
.b3-hero__inner {
    grid-template-columns: 1fr;
    gap: var(--b3-space-lg);
  }

.b3-hero__mark {
    order: -1;
  }
}

@media (max-width: 767px) {
.b3-section {
    padding: var(--b3-space-xl) var(--b3-space-sm);
  }

.b3-entries {
    grid-template-columns: 1fr;
  }

.b3-entry {
    min-height: 180px;
  }

.b3-shelves__grid {
    grid-template-columns: repeat(4, minmax(0, 1fr));
  }

.b3-shelf {
    min-height: 110px;
  }

.b3-shelf__shot {
    display: none;
  }
}


/* 9ter.3 — Texte minuscule.
   Les étiquettes descendaient à 11 px. Plancher à 12 px : en dessous, une
   capitale espacée devient illisible sur un écran de téléphone. */
.b3-entry__kicker,
.b3-card__origin,
.b3-card__flag,
.b3-partner span,
.b3-reassure__list strong {
  font-size: 0.75rem;
}



/* --------------------------------------------------------------------------
   9quinquies. Correctifs d'audit — typographie et lisibilité
   Relevés par une passe automatisée sur la version mobile.
   -------------------------------------------------------------------------- */
/* 9q.1 — Capitales et interlettrage réservés aux étiquettes.
   Le vocabulaire d'étiquetage de cave (capitales espacées) s'était étendu à des
   phrases entières : « Dans nos quatre caves bretonnes », « Emballage renforcé,
   casse assurée ». En capitales espacées, une phrase se déchiffre au lieu de se
   lire. Les capitales restent sur les libellés courts, jamais sur une phrase. */
.b3-reassure__list span,
.b3-figure__detail,
.b3-partners__lead,
.b3-hero__lead,
.b3-card__meta,
.b3-entry__title,
.b3-card__title,
.b3-card__title a {
  text-transform: none;
  letter-spacing: normal;
}


/* « Voir le site » est une phrase, pas une étiquette. */
.b3-partner__external {
  text-transform: none;
  letter-spacing: normal;
}






/* ----- repris de 09-divers ----- */
/* --------------------------------------------------------------------------
   9bis. Page d'accueil
   -------------------------------------------------------------------------- */
/* Pas d'`overflow-x: hidden` ici : il rognerait les aplats qui sortent
   volontairement du conteneur (hero, réassurance, repères chiffrés). */
.page-home {
  overflow: visible;
}


/* 9bis.7 — Adaptations, pilotées par la place disponible.

   Les sections d'accueil réagissent à la largeur de leur conteneur, pas à
   celle de l'écran : la même section reste juste en pleine largeur comme
   dans une colonne étroite, sans qu'aucun point de rupture ne soit à
   maintenir en double. */
.page-home {
  container-type: inline-size;
  container-name: page;
}







/* --------------------------------------------------------------------------
   9septies. « La sélection des cavistes » — aplat jaune
   -------------------------------------------------------------------------- */
/* La sortie de conteneur (`50% - 50vw`) suppose un parent centré. Les modules
   d'accueil sont enveloppés dans `.display-hometop`, qui porte ses propres
   marges de rangée : l'aplat s'en trouvait décalé de 15 px vers la droite. */
.display-hometop,
.display-homebottom {
  margin: 0;
  padding: 0;
}


/* Le thème cible cette section par son identifiant : une règle de classe seule
   se faisait écraser et la sortie de conteneur restait sans effet. */
section#featured-products.b3-picks,
.b3-picks {
  width: 100vw;
  max-width: 100vw;
  margin-left: calc(50% - 50vw);
  margin-right: calc(50% - 50vw);
  padding: var(--b3-space-xl) 0;
  background-color: var(--b3-jaune);
}






/* ----- repris de 09-divers ----- */
/* Reliquat sans composant identifié. */
/* Le bouton d'ajout garde le même habillage partout : c'est la même action,
   elle doit se reconnaître d'une section à l'autre. */
@media (max-width: 767px) {
.b3-picks {
    padding: var(--b3-space-lg) 0;
  }
}

@keyframes b3-marquee {
  from { transform: translateX(0); }
  to   { transform: translateX(-50%); }
}


/* Repli pour les navigateurs sans container queries : la règle ci-dessus
   reste inerte, celle-ci prend le relais. */
@supports not (container-type: inline-size) {
  @media (max-width: 1024px) {
    .b3-entries {
      grid-template-columns: 1fr 1fr;
    }

    .b3-entry--ink {
      grid-column: 1 / -1;
      min-height: 200px;
    }
  }
}


/* ----- repris de 09-divers ----- */

/* --------------------------------------------------------------------------
   9octodecies. Pages intérieures — bandeau de services
   Le module de réassurance (displayTopColumn) empile ses quatre blocs sur
   437 px de haut, avant le contenu : sur une fiche produit consultée au
   téléphone, la bouteille n'apparaissait qu'après un défilement complet.
   Il devient une bande compacte, et passe sous le contenu.
   -------------------------------------------------------------------------- */
.display-topcolumn {
  order: 2;
  margin-top: var(--b3-space-xl);
  padding: var(--b3-space-md) 0;
  background-color: var(--b3-papier-2);
}

.display-topcolumn .shipping-inner,
.display-topcolumn .row {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
  gap: var(--b3-space-md);
  max-width: 1320px;
  margin: 0 auto;
  padding: 0 var(--b3-space-md);
}

.display-topcolumn .shipping-inner > * {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
  text-align: center;
  font-size: 0.875rem;
}

/* Le module dimensionne ses pictogrammes en sprite : ils débordaient de la
   nouvelle bande. */
/* Les pictogrammes du bloc de réassurance, et eux seuls : cette limite de
   46 px s'appliquait à tout `.display-topcolumn`, donc aussi aux visuels du
   bandeau de diapositives — des images de 1903 px rabotées à 46. */
.display-topcolumn .shipping-inner img,
.display-topcolumn .shipping-inner i,
.display-topcolumn .otshippingblock img {
  max-width: 46px;
  height: auto;
}


/* Sous 768 px, les trois entrées s'empilent : la disposition en L n'a plus de
   sens sur une colonne, et la majeure garderait une hauteur inutile. */
@media (max-width: 767px) {
  .b3-entries {
    grid-template-columns: minmax(0, 1fr);
    grid-template-rows: none;
    grid-template-areas: none;
    min-height: 0;
  }

  .b3-entry--majeure,
  .b3-entry--haute,
  .b3-entry--basse {
    grid-area: auto;
  }
}


/* --------------------------------------------------------------------------
   Bloc de témoignages du thème

   Il sort tel quel de la démonstration d'Orthotheme : « Unjobeen mendago »,
   deux paragraphes de Lorem Ipsum et une image de bannière absente, dont le
   navigateur affiche l'alternative cassée. Quatre cent vingt-quatre pixels de
   faux contenu au milieu de la page d'accueil.

   Il est masqué ici plutôt que désinstallé : le module reste disponible si de
   vrais avis clients sont saisis un jour, et la boutique garde la main sur sa
   configuration.
   -------------------------------------------------------------------------- */

.testimonial_outer,
.ottestimonialblock,
[class*="testimonial_outer"] {
  display: none;
}


/* ==========================================================================
   Cartes de rayon — refonte

   Les vignettes portaient une photo du catalogue par-dessus l'aplat d'encre.
   Ces images sont détourées sur fond blanc : le rectangle clair se voyait plus
   que la bouteille, et la carte devenait illisible. Le pictogramme sur
   pastille tient le même rôle de repère, sans dépendre de la qualité du
   détourage — et la carte redevient un aplat franc, comme le reste du système.
   ========================================================================== */

.b3-shelf {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  justify-content: flex-end;
  gap: var(--b3-space-2xs);
  min-height: 10.5rem;
  padding: var(--b3-space-sm);
  border: 2px solid var(--b3-encre);
  border-radius: var(--b3-radius);
  overflow: hidden;
  background-color: var(--b3-encre);
  color: var(--b3-papier);
  text-decoration: none;
  transition:
    background-color var(--b3-dur-fast) var(--b3-ease),
    color var(--b3-dur-fast) var(--b3-ease),
    transform var(--b3-dur-fast) var(--b3-ease);
}

.b3-shelf:hover {
  transform: translateY(-3px);
  background-color: var(--b3-papier);
  color: var(--b3-encre);
}

.b3-shelf:focus-visible {
  outline: 3px solid var(--b3-encre);
  outline-offset: 3px;
}

/* Le pictogramme ouvre la carte, sur sa pastille jaune : même geste que dans
   la barre des rayons de l'en-tête, pour que le repère se reconnaisse d'un
   endroit à l'autre. */
.b3-shelf__emoji {
  display: grid;
  place-items: center;
  width: 2.6rem;
  height: 2.6rem;
  margin-bottom: auto;
  border-radius: 50%;
  background-color: var(--b3-jaune);
  font-size: 1.35rem;
  line-height: 1;
}

.b3-shelf__nom {
  font-size: 1rem;
  font-weight: 800;
  font-stretch: 88%;
  letter-spacing: 0.02em;
  line-height: 1.15;
  text-transform: uppercase;
  text-wrap: balance;
}

/* La flèche n'apparaît qu'au survol : sur huit cartes alignées, huit flèches
   permanentes ajoutent du bruit sans rien dire de plus. */
.b3-shelf__fleche {
  position: absolute;
  right: var(--b3-space-sm);
  bottom: var(--b3-space-sm);
  opacity: 0;
  font-size: 1.1rem;
  transform: translateX(-4px);
  transition:
    opacity var(--b3-dur-fast) var(--b3-ease),
    transform var(--b3-dur-fast) var(--b3-ease);
}

.b3-shelf:hover .b3-shelf__fleche,
.b3-shelf:focus-visible .b3-shelf__fleche {
  opacity: 1;
  transform: translateX(0);
}

/* Les raretés se distinguent par l'aplat jaune : c'est le rayon que la maison
   met en avant, il ne se signale pas par un simple libellé. */
.b3-shelf--rare {
  background-color: var(--b3-jaune);
  color: var(--b3-encre);
}

.b3-shelf--rare .b3-shelf__emoji {
  background-color: var(--b3-encre);
}

.b3-shelf--rare:hover {
  background-color: var(--b3-encre);
  color: var(--b3-jaune);
}

.b3-shelf--rare:hover .b3-shelf__emoji {
  background-color: var(--b3-jaune);
}

@media (prefers-reduced-motion: reduce) {
  .b3-shelf:hover {
    transform: none;
  }
}


/* --------------------------------------------------------------------------
   Filtres de « La sélection des cavistes »

   Deux critères : la couleur dit ce qu'on boit, la région d'où ça vient. Ce
   sont les deux questions du comptoir, et les deux caractéristiques
   renseignées sur la majorité du catalogue.

   Le pictogramme est posé par 3b.js, qui tient déjà la table des repères pour
   les facettes du catalogue : même vocabulaire, même signe, d'une section à
   l'autre.
   -------------------------------------------------------------------------- */

/* Le pictogramme portait la taille du texte, capitales de 12 px : un drapeau
   ou un verre y devenaient illisibles. Il est dimensionné à part, en unité
   absolue, et l'alignement vertical est repris à la main — un emoji ne se cale
   pas sur la ligne de base comme une lettre. */
.b3-filter[data-b3-picto]::before {
  content: attr(data-b3-picto);
  margin-right: 0.45em;
  font-size: 1.125rem;
  line-height: 1;
  vertical-align: -0.16em;
}

/* Un filet sépare les deux familles : sans lui, la barre se lit comme une
   liste unique où « Rouges » et « Loire » seraient de même nature. */
.b3-filters__separateur {
  flex: none;
  width: 1px;
  align-self: stretch;
  margin: 0 var(--b3-space-3xs);
  background-color: var(--b3-trait);
}

/* Sur un écran étroit, la barre défile plutôt que de s'empiler sur quatre
   rangées : le contenu filtré doit rester visible pendant qu'on choisit. */
@media (max-width: 767px) {
  .b3-filters {
    flex-wrap: nowrap;
    overflow-x: auto;
    scrollbar-width: none;
    -webkit-overflow-scrolling: touch;
  }

  .b3-filters::-webkit-scrollbar {
    display: none;
  }

  .b3-filter {
    flex: none;
  }
}


/* ==========================================================================
   Blocs de mise en avant de l'accueil

   Quatre modules tournaient en parallèle : « La sélection des cavistes »
   (otfeaturedproducts), « Produits populaires » (ps_featuredproducts),
   « Meilleures ventes » (ps_bestsellers) et un bloc de texte libre resté sur
   son contenu de démonstration.

   « Produits populaires » affiche les produits de la catégorie « Accueil »,
   choisis à la main en back-office : le titre annonce une popularité que rien
   ne mesure. Il fait par ailleurs doublon avec « La sélection des cavistes »,
   qui assume, elle, d'être un choix. « Meilleures ventes » est calculé sur les
   ventes réelles — c'est le seul des deux qui dise vrai.

   Ces blocs sont masqués à l'affichage. Le geste propre reste de les
   déshooker en back-office : ils continuent d'interroger la base pour un
   contenu que personne ne voit. À faire côté boutique, la configuration des
   modules n'appartenant pas au thème.
   ========================================================================== */

/* Bloc de texte libre : « Custom Text Block » et son Lorem Ipsum.

   Le nœud porte un **identifiant**, `<div id="custom-text">`, et non une
   classe : les sélecteurs `.custom-text` et `[class*="customtext"]` ne
   pouvaient pas l'atteindre, quelle que soit leur spécificité. */
#custom-text,
.custom-text,
.customtext_outer,
#customtext_block_home,
[class*="customtext"] {
  display: none;
}

/* --------------------------------------------------------------------------
   « Meilleures ventes » — aplat d'encre

   Le bloc factuel de la page : ce que les clients achètent réellement. Il
   prend l'aplat pour se détacher des deux sélections éditoriales qui
   l'entourent, et signaler qu'il relève d'un autre registre.
   -------------------------------------------------------------------------- */

.b3-bestsellers {
  position: relative;
  margin-block: var(--b3-space-xl);
  padding-block: var(--b3-space-lg);
  background-color: var(--b3-encre);
}

/* L'aplat saigne d'un bord à l'autre : une affiche n'a pas de marge. */
.b3-bestsellers::before {
  content: "";
  position: absolute;
  inset: 0 calc(50% - 50vw);
  z-index: -1;
  background-color: var(--b3-encre);
}

/* Le titre de section seulement. Viser `h2` en général attraperait aussi les
   titres de vignettes, qui passeraient en jaune sur fond papier — illisibles.
   `body h1, body h2…` du système impose l'encre : il faut au moins autant de
   spécificité pour la reprendre. */
body .b3-bestsellers > .products-section-title,
body .b3-bestsellers > .main-title,
body .b3-bestsellers > h1,
body .b3-bestsellers > h2 {
  color: var(--b3-jaune);
}

/* Sur l'encre, les vignettes gardent le papier : c'est le fond de section qui
   change, pas le composant. */
.b3-bestsellers .b3-card__title a,
.b3-bestsellers .b3-card__origin,
.b3-bestsellers .b3-card__meta {
  color: var(--b3-encre);
}


/* Le module ne distingue pas ses blocs : « Produits populaires » et
   « Meilleures ventes » portent la même classe `featured-products`. La classe
   `b3-bestsellers` est posée par 3b.js, sur le titre. */


/* --------------------------------------------------------------------------
   Repères chiffrés — aplat jaune

   Quatre caves, neuf cents références, trente ans, 4,8 sur 5. Ce sont les
   seuls chiffres vérifiables de la page : ils méritent l'aplat de marque
   plutôt que le fond de page, qui les laissait flotter entre deux sections
   sans qu'on sache s'ils appartenaient à l'une ou à l'autre.
   -------------------------------------------------------------------------- */

/* Cette règle vient après celle qui pose l'encre, et gagnait donc : la bande
   restait jaune, et le chiffre — passé au jaune pour se détacher de l'encre —
   devenait jaune sur jaune. Invisible. Les deux disent désormais la même
   chose. */
.b3-figures {
  position: relative;
  margin-block: var(--b3-space-xl);
  padding-block: var(--b3-space-lg);
  background-color: var(--b3-encre);
}

/* Le débord pleine largeur reprend la couleur de la section. Il était resté
   jaune quand la bande est passée à l'encre : recouvrant toute la surface, il
   annulait le changement de fond — et le chiffre, désormais jaune, devenait
   jaune sur jaune. Invisible. */
.b3-figures::before {
  content: "";
  position: absolute;
  inset: 0 calc(50% - 50vw);
  z-index: -1;
  background-color: var(--b3-encre);
}

/* Sur l'encre : le chiffre en jaune, l'étiquette en papier, le détail en
   papier adouci. Trois valeurs, trois rangs — le jaune est réservé au seul
   chiffre, sinon il cesse de désigner quoi que ce soit. */
.b3-figures .b3-figure__value,
.b3-figures .b3-figure__plus {
  color: var(--b3-jaune);
}

.b3-figures .b3-figure__label {
  color: var(--b3-papier);
}

/* Le détail était à 72 % de papier sur encre — 7:1, sous le confort de
   lecture d'un texte de neuf pixels. À 88 %, il atteint 11:1 et se lit sans
   effort. */
.b3-figures .b3-figure__detail {
  color: color-mix(in oklab, var(--b3-papier) 88%, transparent);
}

.b3-figures .b3-figure + .b3-figure {
  border-color: color-mix(in oklab, var(--b3-papier) 20%, transparent);
}

@media (max-width: 479px) {
  .b3-figures .b3-figure + .b3-figure {
    border-top-color: color-mix(in oklab, var(--b3-papier) 20%, transparent);
  }
}


/* --------------------------------------------------------------------------
   Bandeau de diapositives

   Trois visuels de la boutique — accueil, livraison, retrait — configurés en
   back-office et jamais rendus, le hook qui les porte n'étant pas appelé.

   Le bloc de réassurance du thème partage ce hook. Il répète la bande
   « Retrait gratuit / Expédition / Paiement sécurisé » écrite plus haut, et
   s'affichait en colonnes de cinquante-trois pixels : il reste masqué.
   -------------------------------------------------------------------------- */

.b3-bandeau {
  margin-block: var(--b3-space-lg);
}

.b3-bandeau .shipping-inner,
.b3-bandeau .otshippingblock {
  display: none;
}

/* Le visuel portait deux cadres concentriques : celui du conteneur du module,
   posé sur un aplat plus sombre que la page, et l'arrondi du carrousel à
   l'intérieur. Deux bordures pour une image, dont l'une n'est pas de la
   charte. Les fonds hérités sautent, il ne reste qu'un cadre. */
.b3-bandeau,
.b3-bandeau .homeslider-container,
.b3-bandeau .owl-stage-outer,
.b3-bandeau .owl-item,
.b3-bandeau .slide {
  background: none;
  border: 0;
  padding: 0;
}

/* Plein cadre, pas de cadre : le visuel occupe toute la largeur de l'écran,
   comme le hero — même sortie de conteneur (`100vw` compense la gouttière
   du `.b3-section` parent, `max-width:1320px` restait un liséré à gauche et
   à droite). Le filet d'encre et l'arrondi tenaient d'une lecture en carte ;
   ici le visuel n'est plus une carte parmi d'autres, il est l'écran. */
.b3-actus .b3-bandeau {
  width: 100vw;
  max-width: 100vw;
  margin-left: calc(50% - 50vw);
  margin-right: calc(50% - 50vw);
}

.b3-bandeau .owl-carousel,
.b3-bandeau [id*="slider"] {
  position: relative;
  border: 0;
  border-radius: 0;
  overflow: hidden;
}

/* Avant qu'Owl ait mesuré ses diapositives — ou si l'image n'a pas encore
   chargé —, rien ne réserve de hauteur : la bande retombe à celle de son
   contenu, quelques pixels. Mesuré en conditions réelles : 96px de haut au
   lieu de plusieurs centaines, la bande paraît minuscule et mal centrée.
   Le ratio des visuels du bandeau (1903×855) réserve la place à l'avance ;
   une fois chargé, la vraie hauteur du visuel prend le relais. */
.b3-bandeau .owl-carousel:not(.owl-loaded) {
  aspect-ratio: 1903 / 855;
}

.b3-bandeau img {
  display: block;
  width: 100%;
  height: auto;
}

/* Points de progression : disques cerclés d'encre, celui en cours en jaune
   plein. La forme change en même temps que la couleur — la position ne se
   signale jamais par la seule teinte. */
/* Les points se posent sur le visuel plutôt que sous lui : la bande blanche
   qu'ils occupaient ajoutait un troisième registre sous une image déjà
   encadrée. Une pilule de papier les rattache au visuel sans dépendre de sa
   couleur — les diapositives changent, le contraste doit tenir sur toutes. */
.b3-bandeau .owl-dots {
  position: absolute;
  left: 50%;
  bottom: var(--b3-space-sm);
  transform: translateX(-50%);
  z-index: 2;
  display: flex;
  justify-content: center;
  gap: var(--b3-space-2xs);
  margin: 0;
  padding: 7px 12px;
  border-radius: var(--b3-radius-pill);
  background-color: color-mix(in oklab, var(--b3-papier) 88%, transparent);
  backdrop-filter: blur(4px);
}

.b3-bandeau .owl-dot {
  width: 14px;
  height: 14px;
  padding: 0;
  border: 2px solid var(--b3-encre);
  border-radius: 50%;
  background-color: transparent;
  transition:
    background-color var(--b3-dur-fast) var(--b3-ease),
    transform var(--b3-dur-fast) var(--b3-ease);
}

.b3-bandeau .owl-dot:hover {
  background-color: color-mix(in oklab, var(--b3-jaune) 60%, transparent);
}

.b3-bandeau .owl-dot.active {
  background-color: var(--b3-jaune);
  transform: scale(1.25);
}

.b3-bandeau .owl-dot span {
  display: none;
}


/* Le bandeau défile tout seul et signale sa position par ses points : ses
   flèches n'ajoutent rien, et le thème les dessine avec la sprite — un disque
   gris posé en image de fond, qui se lisait comme un second bouton à
   l'intérieur du premier. */
.b3-bandeau .owl-nav,
.b3-bandeau .owl-prev,
.b3-bandeau .owl-next,
#homepage-carousel .owl-nav {
  display: none;
}


/* --------------------------------------------------------------------------
   Second bandeau — ps_imageslider

   Deux modules de diapositives tournent en parallèle : othomeslider, branché
   sur `displayTopColumn` et porteur des trois visuels de la boutique, et
   ps_imageslider sur `displayHome`, qui en affiche un de plus sous les
   meilleures ventes. Deux bandeaux promotionnels sur une même page se
   concurrencent : le second est masqué.

   Comme les autres blocs de démonstration, le geste propre reste de le
   déshooker en back-office.
   -------------------------------------------------------------------------- */

#carousel.carousel,
.wrapper-inner > #carousel {
  display: none;
}


/* --------------------------------------------------------------------------
   Nos partenaires — aplat sourd et cartes d'encre

   Les logos flottaient sur le fond de page, sans rien qui les rassemble. La
   section prend un aplat papier alterné, et chaque partenaire une carte
   d'encre : les logos, tous différents de forme et de couleur, y gagnent un
   cadre commun.
   -------------------------------------------------------------------------- */

.b3-partners {
  position: relative;
  margin-block: var(--b3-space-xl);
  padding-block: var(--b3-space-lg);
  background-color: var(--b3-papier-2);
}

.b3-partners::before {
  content: "";
  position: absolute;
  inset: 0 calc(50% - 50vw);
  z-index: -1;
  background-color: var(--b3-papier-2);
}

.b3-partners__grid > li,
.b3-partner {
  display: flex;
}

.b3-partners__grid a,
a.b3-partner {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--b3-space-2xs);
  width: 100%;
  padding: var(--b3-space-md) var(--b3-space-sm);
  border-radius: var(--b3-radius);
  background-color: var(--b3-encre);
  color: var(--b3-papier);
  text-decoration: none;
  transition: transform var(--b3-dur-fast) var(--b3-ease);
}

.b3-partners__grid a:hover,
a.b3-partner:hover {
  transform: translateY(-3px);
}

/* Le logo garde son disque : les visuels des partenaires sont hétérogènes,
   le cercle leur impose un gabarit commun. Fond papier pour que les logos
   sombres ne disparaissent pas dans l'encre de la carte. */
.b3-partners__grid img,
.b3-partner img {
  width: 84px;
  height: 84px;
  aspect-ratio: 1;
  object-fit: contain;
  padding: var(--b3-space-2xs);
  border-radius: 50%;
  background-color: var(--b3-papier);
}

.b3-partners__grid a span,
.b3-partner span {
  font-size: 0.875rem;
  font-weight: 700;
  text-align: center;
  color: var(--b3-papier);
}

.b3-partner__external {
  font-size: 0.75rem;
  font-weight: 600;
  color: var(--b3-jaune);
}

@media (prefers-reduced-motion: reduce) {
  .b3-partners__grid a:hover,
  a.b3-partner:hover {
    transform: none;
  }
}


/* --------------------------------------------------------------------------
   Entrées illustrées

   Une photographie occupe toute la carte, texte compris. Trois précautions
   la rendent lisible :

   1. Un voile d'encre, dégradé du bas vers le haut. Une opacité uniforme
      assombrirait la photo entière pour ne servir qu'au tiers bas ; le
      dégradé la laisse claire là où elle n'a rien à porter.
   2. Le texte passe en papier sur les trois cartes, y compris la jaune et la
      claire. Leur encre d'origine, posée sur une photographie, ne tient aucun
      rapport de contraste garanti — la photo change, le texte doit rester
      lisible.
   3. La couleur de fond reste posée sous l'image : elle sert de repli tant
      que la photographie n'est pas chargée, et évite le clignotement blanc.
   -------------------------------------------------------------------------- */

.b3-entry__fond {
  position: absolute;
  inset: 0;
  z-index: 0;
  display: block;
}

.b3-entry__fond img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform 600ms var(--b3-ease);
}

/* La photographie des raretés est un portrait très haut dans une carte
   presque carrée : le cadrage par défaut, centré, montrait surtout le mur du
   fond. Il descend sur les bouteilles, qui sont le sujet, et les pousse vers
   la droite plutôt que le centre. */
.b3-entry--majeure .b3-entry__fond img {
  object-position: 78% 74%;
}

/* Les coffrets et la sélection posent leur sujet à droite du cadre. */
.b3-entry--haute .b3-entry__fond img,
.b3-entry--basse .b3-entry__fond img {
  object-position: right center;
}

/* Le voile. `to top` plutôt qu'une teinte plate : le texte vit en bas. */
.b3-entry--photo::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 1;
  background-image: linear-gradient(
    to top,
    color-mix(in oklab, var(--b3-encre) 92%, transparent) 0%,
    color-mix(in oklab, var(--b3-encre) 72%, transparent) 34%,
    color-mix(in oklab, var(--b3-encre) 22%, transparent) 68%,
    transparent 100%
  );
}

/* Le texte repasse au-dessus du voile, et se cale en bas de carte. */
.b3-entry--photo .b3-entry__body {
  position: relative;
  z-index: 2;
  margin-top: auto;
}

.b3-entry--photo,
.b3-entry--photo .b3-entry__title,
.b3-entry--photo .b3-entry__body {
  color: var(--b3-papier);
}

/* Le sur-titre était en jaune sur les cartes claires, où il plafonne à
   1,53:1. Sur le voile d'encre il atteint 12:1 et redevient lisible. */
.b3-entry--photo .b3-entry__kicker {
  color: var(--b3-jaune);
}

.b3-entry--photo .b3-entry__cta {
  background-color: var(--b3-jaune);
  color: var(--b3-encre);
  border-color: var(--b3-jaune);
}

/* Le rapprochement se lit sur la photographie plutôt que sur la carte : c'est
   l'image qui avance, le cadre ne bouge pas. */
.b3-entry--photo:hover .b3-entry__fond img,
.b3-entry--photo:focus-visible .b3-entry__fond img {
  transform: scale(1.04);
}

@media (prefers-reduced-motion: reduce) {
  .b3-entry__fond img { transition: none; }
  .b3-entry--photo:hover .b3-entry__fond img { transform: none; }
}


/* --------------------------------------------------------------------------
   Visuel du hero

   La photographie est prise sur le jaune de la marque : son fond et l'aplat
   de la section se confondent, à condition de ne rien poser autour d'elle —
   ni cadre, ni ombre, ni arrondi, qui trahiraient la découpe.
   -------------------------------------------------------------------------- */

/* Le visuel s'aligne en bas plutôt qu'au centre : les bouteilles reposent sur
   un plateau, elles doivent porter sur la base du bloc, pas flotter au milieu.
   La marge du haut lui laisse dépasser la colonne de texte, la sortie basse le
   fait mordre sur la bande de réassurance — c'est le geste d'une affiche, pas
   d'une vignette rangée dans sa case. */
/* Le visuel repose sur la base du bloc sans en sortir : la sortie basse le
   faisait mordre sur la bande de réassurance, qui le tranchait net. */
.b3-hero__visuel {
  align-self: end;
  min-width: 0;
  margin-top: var(--b3-space-sm);
  margin-bottom: 0;
}

.b3-hero__visuel img {
  display: block;
  width: 100%;
  height: auto;
  /* Le sujet est au centre-droit du cadre ; sur les écrans étroits, la
     colonne se resserre et c'est lui qu'il faut garder. */
  object-fit: cover;
  object-position: center;
}

/* Le jaune de la photographie n'est pas exactement celui de la charte : la
   bordure du cliché se lisait comme un rectangle collé sur l'aplat.

   Quatre dégradés du jaune de marque vers la transparence, posés par-dessus,
   effacent les bords et rattrapent l'écart de teinte au passage. Un masque
   aurait rendu la photo transparente sur ses bords, ce qui laisse passer le
   jaune du fond — pas le même, précisément le problème qu'on veut résoudre.
   Ici c'est bien la couleur de la charte qui est peinte. */
.b3-hero__visuel {
  position: relative;
}

.b3-hero__visuel::after {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  background-image:
    linear-gradient(to right,  var(--b3-jaune) 0%, transparent 15%),
    linear-gradient(to left,   var(--b3-jaune) 0%, transparent 13%),
    linear-gradient(to top,    var(--b3-jaune) 0%, transparent 14%),
    linear-gradient(to bottom, var(--b3-jaune) 0%, transparent 11%);
}

/* Sous 992 px la grille repasse en une colonne. Le visuel y prendrait toute
   la largeur et repousserait les boutons hors de l'écran : il se limite à une
   bande, cadrée sur les bouteilles. */
@media (max-width: 991px) {
  .b3-hero__visuel img {
    max-height: 42vh;
    object-position: center 40%;
  }
}

/* Sur les très petits écrans, le hero doit tenir en un regard : titre,
   promesse, boutons. La photographie attendra le défilement. */
@media (max-width: 575px) {
  .b3-hero__visuel {
    display: none;
  }
}


/* --------------------------------------------------------------------------
   Survol des entrées illustrées

   `color: inherit` sur les descendants au survol les ramenait à la couleur de
   la carte — l'encre pour la claire et la jaune. Sur une photographie voilée
   d'encre, le texte passait donc du papier au noir : illisible, et sans
   raison. Les couleurs sont réaffirmées ici, après les règles de survol.
   -------------------------------------------------------------------------- */

.b3-entry--photo:hover .b3-entry__body,
.b3-entry--photo:focus .b3-entry__body,
.b3-entry--photo:focus-visible .b3-entry__body,
.b3-entry--photo:hover .b3-entry__title,
.b3-entry--photo:focus .b3-entry__title,
.b3-entry--photo:focus-visible .b3-entry__title {
  color: var(--b3-papier);
}

.b3-entry--photo:hover .b3-entry__kicker,
.b3-entry--photo:focus .b3-entry__kicker,
.b3-entry--photo:focus-visible .b3-entry__kicker {
  color: var(--b3-jaune);
}

.b3-entry--photo:hover .b3-entry__cta,
.b3-entry--photo:focus .b3-entry__cta,
.b3-entry--photo:focus-visible .b3-entry__cta {
  background-color: var(--b3-jaune);
  border-color: var(--b3-jaune);
  color: var(--b3-encre);
}


/* --------------------------------------------------------------------------
   Meilleures ventes — grille

   Huit vignettes tiennent sur deux rangées : une liste qu'on embrasse d'un
   regard n'a pas à défiler. La métrique est celle de « La sélection des
   cavistes » — même minimum de colonne, même gouttière — sans quoi la page
   servait deux tailles de carte à deux sections voisines.
   -------------------------------------------------------------------------- */

.b3-bestsellers__grille {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(230px, 1fr));
  gap: var(--b3-space-md);
  margin: 0;
  padding: 0;
  list-style: none;
}

@media (max-width: 479px) {
  .b3-bestsellers__grille {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: var(--b3-space-sm) var(--b3-space-xs);
  }
}

.b3-bestsellers__tout {
  margin: var(--b3-space-lg) 0 0;
  text-align: center;
}

/* Sur l'aplat d'encre, le bouton fantôme reprend le papier : son contour
   d'encre y était invisible. */
.b3-bestsellers .b3-btn--ghost {
  border-color: var(--b3-papier);
  color: var(--b3-papier);
}

.b3-bestsellers .b3-btn--ghost:hover {
  background-color: var(--b3-papier);
  color: var(--b3-encre);
}

/* Les filtres de la section gardent le fond papier : sur l'encre, une pastille
   transparente disparaît tout autant que sur le jaune. */
.b3-bestsellers .b3-filters__separateur {
  background-color: color-mix(in oklab, var(--b3-papier) 40%, transparent);
}

.b3-bestsellers .b3-filters__empty {
  color: var(--b3-papier);
}

/* --------------------------------------------------------------------------
   Nos actualités

   Le bandeau de diapositives n'avait pas de titre : il flottait entre deux
   sections sans qu'on sache ce qu'il annonçait.
   -------------------------------------------------------------------------- */

/* La section héritait de trois marges empilées : la sienne, celle de
   `.b3-bandeau`, et celle que le module pose sur son conteneur. Trois espaces
   pour un seul intervalle. Seule la section garde la sienne. */
.b3-actus {
  margin-block: var(--b3-space-lg);
}

.b3-actus .b3-bandeau,
.b3-actus .homeslider-container,
.b3-actus .display-topcolumn {
  margin-block: 0;
  padding-block: 0;
}

/* Le module pose `.homeslider-container` en `float: left` (othomeslider.css) —
   sans contenir ce flottant, le bandeau mesure une hauteur de 0 : le
   visuel reste visible (le flottant se peint où il est), mais la section qui
   le porte se referme dessus. Mesuré : 96px de haut annoncés pour un bandeau
   qui en occupe visuellement 169, et la section suivante qui commence par
   dessus le sien. `flow-root` contient le flottant sans rien recadrer, à la
   différence d'un `overflow: hidden` qui aurait pu couper les points de
   progression. */
.b3-actus .b3-bandeau {
  display: flow-root;
}

.b3-actus .b3-section__title {
  margin-bottom: var(--b3-space-sm);
}


/* --------------------------------------------------------------------------
   Quatrième entrée — format horizontal

   Elle occupe toute la largeur du bloc, sous les trois autres : c'est la seule
   qui parle d'une production propre à la maison, et le changement de format le
   dit avant que le texte ne l'explique.

   La zone média garde son rapport d'image dès maintenant, vide : quand la
   vidéo arrivera, elle prendra la place qui l'attend et rien ne bougera.
   -------------------------------------------------------------------------- */

.b3-entries {
  grid-template-areas:
    "majeure haute"
    "majeure basse"
    "large   large"
    "annonce annonce";
  grid-template-rows: minmax(0, 1fr) minmax(0, 1fr) auto auto;
}

/* La vidéo prend tout le fond de la carte : le texte se pose dessus, comme
   sur les trois autres entrées. Une colonne média séparée aurait fait de la
   vidéo une vignette ; en fond, elle fait décor. */
.b3-entry--large {
  grid-area: large;
  position: relative;
  display: grid;
  align-items: end;
  min-height: clamp(15rem, 26vw, 22rem);
}

.b3-entry__fond--video {
  position: absolute;
  inset: 0;
  z-index: 0;
  overflow: hidden;
  background-color: var(--b3-encre);
}

.b3-entry__video {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* Le voile d'encre de `.b3-entry--photo` ne s'applique pas ici : la carte
   n'est pas illustrée par une photographie mais par une vidéo, et le dégradé
   doit être plus franc — une image qui bouge tire l'œil davantage qu'une
   image fixe, et le texte doit tenir malgré elle. */
.b3-entry--large::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 1;
  background-image: linear-gradient(
    to top,
    color-mix(in oklab, var(--b3-encre) 94%, transparent) 0%,
    color-mix(in oklab, var(--b3-encre) 78%, transparent) 38%,
    color-mix(in oklab, var(--b3-encre) 34%, transparent) 72%,
    color-mix(in oklab, var(--b3-encre) 12%, transparent) 100%
  );
}

.b3-entry--large .b3-entry__body {
  position: relative;
  z-index: 2;
  justify-content: flex-end;
  gap: var(--b3-space-2xs);
  padding: var(--b3-space-lg);
}

.b3-entry--large .b3-entry__title {
  max-width: 18ch;
  font-size: clamp(1.375rem, 2.1vw, 1.875rem);
  line-height: 1.08;
}

.b3-entry__texte {
  max-width: 42ch;
  font-size: 0.9375rem;
  line-height: 1.5;
  color: color-mix(in oklab, var(--b3-papier) 78%, transparent);
}

@media (max-width: 767px) {
  .b3-entry--large {
    min-height: 17rem;
  }
}

/* Repli pour les navigateurs sans requête de conteneur : la grille à deux
   colonnes du bloc se réduit, la quatrième entrée garde sa pleine largeur. */
@supports not (container-type: inline-size) {
  @media (max-width: 1024px) {
    .b3-entries {
      grid-template-areas:
        "majeure majeure"
        "haute   basse"
        "large   large";
    }
  }
}


/* --------------------------------------------------------------------------
   Meilleures ventes — grille hors carrousel
   -------------------------------------------------------------------------- */

/* Même aplat encre que le pager de rayon (`.b3-rayon-pager`) : « Meilleures
   ventes » est un tri au même titre qu'un rayon, elle doit se lire comme un
   moment à part identique, pas comme une grille nue oubliée à côté. */
.b3-ventes-grille {
  display: grid;
  width: 100%;
  grid-template-columns: repeat(auto-fit, minmax(230px, 1fr));
  gap: var(--b3-space-md);
  margin: 0;
  padding: var(--b3-space-lg) var(--b3-space-md);
  border-radius: var(--b3-radius-lg);
  background-color: var(--b3-encre);
  list-style: none;
}

.b3-ventes-grille[hidden] {
  display: none;
}

@media (max-width: 479px) {
  .b3-ventes-grille {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: var(--b3-space-sm) var(--b3-space-xs);
  }
}


/* --------------------------------------------------------------------------
   Titre de section en pastille

   « Nos catégories » ouvre la moitié basse de la page : la pastille jaune le
   détache du flux de sections, comme la pastille du hero détache la mention
   d'origine.
   -------------------------------------------------------------------------- */

.b3-section__title--pastille {
  position: sticky;
  top: var(--b3-space-sm);
  z-index: 5;
  display: inline-block;
  margin-bottom: var(--b3-space-md);
  padding: var(--b3-space-2xs) var(--b3-space-md);
  border-radius: var(--b3-radius-pill);
  background-color: var(--b3-jaune);
  color: var(--b3-encre);
}

/* --------------------------------------------------------------------------
   Espacement des sections

   Les blancs venaient d'un cumul, pas d'une valeur : `.b3-section` porte sa
   marge, chaque section la sienne, et les modules ajoutent celle de leur
   conteneur. Trois marges pour un intervalle. Les sections voisines s'en
   remettent désormais à une seule, et les conteneurs de module sont remis à
   zéro là où ils s'empilent.
   -------------------------------------------------------------------------- */

.b3-shelves,
.b3-actus {
  margin-block: var(--b3-space-lg);
}

/* `.b3-section` pose 64px de remplissage vertical par défaut — pensé pour un
   titre et du texte. Cette section n'affiche ni l'un ni l'autre (le titre
   est `sr-only`) : son seul contenu est le bandeau plein cadre, qui a lui
   même son horizontal en pleine largeur par sortie de conteneur. Le
   remplissage vertical restait donc un bandeau blanc au-dessus et en dessous
   de l'image, sur une section censée être « pleine section ». */
.b3-actus {
  padding-block: 0;
}

/* Deux sections qui se suivent ne cumulent pas leurs marges : la seconde
   annule la sienne, l'intervalle reste celui de la première.

   `.b3-entries` est le voisin réel dans le gabarit actuel — `.b3-shelves`
   date d'une disposition antérieure et ne correspond plus à rien dans le
   DOM, d'où l'espace resté vide au-dessus du bandeau tant que cette règle
   ne portait que sur lui. Les deux sélecteurs restent posés : l'un couvre
   l'ordre d'aujourd'hui, l'autre une réorganisation qui le rétablirait. */
.b3-shelves + .b3-actus,
.b3-entries + .b3-actus {
  margin-top: 0;
}

.b3-actus + .b3-figures {
  margin-top: var(--b3-space-lg);
}

/* Le module pose ses propres marges sur trois niveaux de conteneur. */
.b3-actus .display-topcolumn,
.b3-actus .homeslider-container,
.b3-actus .owl-carousel,
.b3-actus .otshippingblock {
  margin-block: 0;
}

.b3-shelves .b3-shelves__grid {
  margin-bottom: 0;
}


/* --------------------------------------------------------------------------
   La barre de filtres, remise en ordre

   Elle était devenue une nappe de pilules sur deux rangées, où « Meilleures
   ventes », « Spiritueux », « Rouges » et « Loire » se suivaient sans qu'on
   voie qu'ils répondent à trois questions différentes : comment trier, quoi
   boire, d'où ça vient. Deux filets fins tentaient de le dire ; ils étaient
   perdus au milieu.

   Les trois familles gardent leur rangée. Chacune tient sur une ligne qui
   défile si elle déborde : mieux vaut faire glisser une rangée cohérente que
   d'en empiler quatre incohérentes.
   -------------------------------------------------------------------------- */

.b3-filters {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--b3-space-2xs);
  margin-bottom: var(--b3-space-md);
}

/* Le filet devient une rupture de ligne : il force la famille suivante à
   commencer sa propre rangée. Sur une grille souple, une largeur de 100 %
   suffit — inutile d'introduire un conteneur par famille dans le gabarit. */
.b3-filters__separateur {
  flex: 1 0 100%;
  width: auto;
  height: 0;
  align-self: auto;
  margin: var(--b3-space-3xs) 0 0;
  background-color: transparent;
}

/* Les pilules d'une même rangée partagent leur hauteur : sans cela, celles qui
   portent un emoji dépassaient les autres d'un ou deux pixels, et la rangée
   ondulait. */
.b3-filters .b3-filter {
  min-height: 40px;
  display: inline-flex;
  align-items: center;
}

/* Le tri est une décision différente d'un filtre de contenu : « Tout » et
   « Meilleures ventes » ouvrent la barre, détachés du reste. */
.b3-filters .b3-filter[data-b3-filter-type="*"],
.b3-filters .b3-filter--ventes {
  font-weight: 800;
}

@media (max-width: 767px) {
  /* Chaque famille défile pour elle-même. La règle plus haut mettait toute la
     barre sur une seule ligne : les onze boutons partaient loin à droite, et
     l'on ne voyait jamais les couleurs ni les pays sans faire défiler
     longuement. */
  /* Le repli en rangées vaut aussi sur téléphone. La règle plus haut mettait
     toute la barre sur une seule ligne défilante : les onze boutons partaient
     loin à droite, et l'on ne voyait jamais les couleurs ni les pays sans
     faire défiler longuement. Trois rangées courtes se lisent d'un coup. */
  .b3-filters {
    display: flex;
    flex-wrap: wrap;
    overflow-x: visible;
    gap: var(--b3-space-3xs);
  }

  .b3-filters .b3-filter {
    min-height: 36px;
    font-size: 0.75rem;
  }
}


/* L'intitulé de famille. Il ouvre sa rangée et n'est pas cliquable : c'est une
   étiquette, pas un filtre. Sans lui, « Spiritueux », « Rouges » et « France »
   se suivaient sans qu'on voie qu'ils répondent à trois questions. */
.b3-filters__intitule {
  flex: none;
  align-self: center;
  margin-right: var(--b3-space-3xs);
  font-size: 0.6875rem;
  font-weight: 800;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: color-mix(in oklab, var(--b3-encre) 62%, transparent);
  user-select: none;
}

/* Sur l'aplat jaune de la section, l'encre adoucie garde son contraste. */
.b3-picks .b3-filters__intitule {
  color: color-mix(in oklab, var(--b3-encre) 72%, transparent);
}


/* --------------------------------------------------------------------------
   « Nos partenaires » respire

   La bande était la plus basse de la page : quatre pavés d'encre serrés dans
   un rembourrage de section ordinaire, entre deux voisines qui prennent
   l'écran entier. Elle se lisait comme un pied de page avancé plutôt que comme
   une section.
   -------------------------------------------------------------------------- */

.b3-partners {
  padding-block: var(--b3-space-2xl);
}

@media (min-width: 992px) {
  .b3-partners {
    padding-block: clamp(var(--b3-space-2xl), 9vh, 7rem);
  }

  /* Les pavés gagnent en hauteur : un logo dans un cadre trop bas paraît
     posé de travers, quelle que soit sa taille. */
  .b3-partners__grid a,
  a.b3-partner {
    min-height: 11rem;
    padding-block: var(--b3-space-lg);
  }
}


/* --------------------------------------------------------------------------
   Le visuel de la hero

   Deux jaunes cohabitent, et il faut le dire : celui de la photographie est un
   ambre chaud, `#d89005` mesuré sur ses bords, quand celui de la marque est un
   jaune franc. Ils ne se raccorderont jamais tout à fait.

   Le détourage, qui a servi pour les canettes, ne s'applique pas ici : les
   coins hauts de l'image sont jaunes et les coins bas bruns — c'est une scène
   composée, avec un plan de pose sombre, et non un sujet sur fond uni. Un
   remplissage par diffusion n'y retirait que 0,5 % de la surface.

   La réponse tient en deux gestes. L'image touche les bords haut, droit et bas
   de la section : là où elle les touche, il n'y a pas de raccord à faire. Et
   son bord gauche, le seul qui rencontre l'aplat, s'estompe sur une bande
   étroite.

   Cette bande ne doit contenir que du fond. Une version antérieure y laissait
   les canettes de gauche, qui devenaient semi-transparentes : la même image se
   lisait deux fois, une fois pleine et une fois en fantôme par-dessus le
   texte. Ce n'était pas un doublon dans le document — vérifié, il n'y a qu'un
   `<picture>` et qu'un `<img>` — mais un sujet à demi effacé, ce qui se voit
   exactement pareil. L'image est donc recadrée pour qu'il y ait de l'aplat à
   cet endroit, et rien d'autre.
   -------------------------------------------------------------------------- */

/* L'image se cale en bas, à droite, et sort par la droite seulement.
   
   Étirée sur toute la hauteur du panneau avec `object-fit: cover`, elle était
   recadrée si fort qu'il ne restait que le milieu des bouteilles — cols et
   pieds coupés. Une composition de sept bouteilles ne supporte pas d'être
   rognée : c'est l'alignement de leurs silhouettes qui fait l'image. */
.b3-hero__visuel {
  position: relative;
  align-self: end;
  justify-self: end;
  /* Pas de débord jusqu'au bord de l'écran. Étalée sur toute la largeur
     restante, l'image devenait si grande que les bouteilles sortaient du
     cadre par le bas : une composition de sept silhouettes alignées ne
     supporte pas d'être agrandie au-delà de sa colonne. */
  margin-bottom: calc(var(--b3-space-lg) * -1);
  width: 100%;
  max-width: none;
  overflow: visible;
}

/* L'agrandissement et le masque portent sur `picture`, jamais sur l'`img`.
   
   `picture` enveloppe l'image : viser les deux appliquait la mise à l'échelle
   deux fois — 703 px devenaient 830, puis 979 — et composait le masque deux
   fois, ce qui dessinait un second contour au-dessus du premier. */
.b3-hero__visuel img {
  display: block;
  width: 100%;
  height: auto;
  object-fit: contain;
  transform: none;
  -webkit-mask-image: none;
  mask-image: none;
}

.b3-hero__visuel picture {
  display: block;
  width: 100%;
  height: auto;
  transform: none;
  -webkit-mask-image: linear-gradient(to right, transparent 0%, #000 18%);
  mask-image: linear-gradient(to right, transparent 0%, #000 18%);
}

@media (max-width: 900px) {
  /* Sur une colonne, l'image ne longe plus le texte : le fondu n'a plus de
     raccord à masquer, et la faire saigner la couperait. */
  .b3-hero__visuel {
    margin-inline: 0;
    margin-block: 0;
    width: 100%;
  }

  .b3-hero__visuel picture {
    -webkit-mask-image: none;
    mask-image: none;
  }

  .b3-hero__visuel img {
    height: auto;
    min-height: 0;
    object-fit: contain;
    border-radius: var(--b3-radius-lg);
  }
}


/* ==========================================================================
   Carte foire aux vins — trois états

   avant    : grisée, non cliquable, compte à rebours. Rien à vendre encore,
              la carte le montre plutôt que de mentir par un lien mort.
   active   : identique aux autres cartes annonce.
   terminee : reste cliquable (la sélection existe, à prix normal) mais un
              badge le dit sans détour.
   ========================================================================== */

.b3-entry__badge {
  position: absolute;
  z-index: 2;
  top: var(--b3-space-sm);
  left: var(--b3-space-sm);
  padding: 0.35em 0.9em;
  border-radius: var(--b3-radius-pill);
  background-color: var(--b3-jaune);
  color: var(--b3-encre);
  font-size: 0.6875rem;
  font-weight: 900;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.b3-entry__badge--fin {
  background-color: var(--b3-papier);
  color: var(--b3-encre-douce);
}

.b3-entry--foire-avant {
  cursor: default;
}

.b3-entry--foire-avant .b3-entry__fond img {
  filter: grayscale(0.85) brightness(0.72);
}

.b3-entry--foire-avant:hover .b3-entry__fond img,
.b3-entry--foire-avant:focus-visible .b3-entry__fond img {
  transform: none; /* pas de zoom au survol : rien à découvrir avant l'heure */
}

.b3-entry--foire-avant .b3-entry__cta {
  display: none;
}

.b3-entry__compte-a-rebours {
  display: inline-flex;
  align-items: baseline;
  gap: 0.35em;
  margin-top: var(--b3-space-2xs);
  font-size: 0.9375rem;
  font-weight: 800;
  font-variant-numeric: tabular-nums;
  color: var(--b3-papier);
}

@media (max-width: 575px) {
  .b3-entry__badge {
    top: var(--b3-space-2xs);
    left: var(--b3-space-2xs);
    font-size: 0.625rem;
  }
}

/* --------------------------------------------------------------------------
   Pagination réelle d'un rayon (Spiritueux, Coffrets, Bières, Raretés)

   Remplace, au clic sur un rayon, le premier écran préchargé par la vraie
   liste — voir B3RayonController et 3b.js, `chargerRayon()`. Grille dense en
   aplat encre (le rayon devient un moment à part, pas une simple suite du
   carrousel), points blancs pour la pagination : le fond sombre l'impose,
   c'est aussi la seule couleur qui reste lisible dessus sans jaune décoratif.
   -------------------------------------------------------------------------- */
/* `06-catalogue.css` borne `.featured-products .row` à `overflow: hidden`
   pour le carrousel Owl, qui déborde par construction pendant qu'il défile.
   Le pager n'a rien d'un carrousel : ses flèches doivent au contraire
   déborder jusqu'au jaune (voir `.b3-rayon-pager__fleche` plus bas), donc la
   ligne qui le porte retrouve son débordement normal — et elle seule, le
   carrousel garde le sien coupé. */
.featured-products .row:has(.b3-rayon-pager) {
  overflow: visible;
}

.b3-rayon-pager {
  position: relative;
  margin-top: var(--b3-space-md);
  padding: var(--b3-space-lg) var(--b3-space-md);
  border-radius: var(--b3-radius-lg);
  background-color: var(--b3-encre);
}

.b3-rayon-pager--charge {
  min-height: 240px;
}

.b3-rayon-pager--charge::after {
  content: "";
  position: absolute;
  top: var(--b3-space-md);
  right: var(--b3-space-md);
  width: 22px;
  height: 22px;
  border: 3px solid color-mix(in oklab, var(--b3-papier) 30%, transparent);
  border-top-color: var(--b3-jaune);
  border-radius: 50%;
  animation: b3-tourner 700ms linear infinite;
}

@keyframes b3-tourner {
  to { transform: rotate(360deg); }
}

@media (prefers-reduced-motion: reduce) {
  .b3-rayon-pager--charge::after {
    animation-duration: 1400ms;
  }
}

/* Le nombre porte l'info, pas le mot qui le suit : même logique que les
   chiffres repères du pied de page (`.b3-figure__value`), en plus compact —
   911 se lit d'un coup d'œil avant même de lire « références ». */
.b3-rayon-pager__compte {
  display: flex;
  align-items: baseline;
  gap: var(--b3-space-xs);
  margin: 0 0 var(--b3-space-md);
}

.b3-rayon-pager__compte-nombre {
  font-size: clamp(1.75rem, 3vw, 2.25rem);
  font-weight: 900;
  font-stretch: 70%;
  line-height: 1;
  letter-spacing: -0.02em;
  font-variant-numeric: tabular-nums;
  color: var(--b3-jaune);
}

.b3-rayon-pager__compte-label {
  font-size: 0.8125rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: color-mix(in oklab, var(--b3-papier) 70%, transparent);
}

.b3-rayon-pager__grille {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--b3-space-sm);
  transition: opacity 220ms var(--b3-ease), transform 220ms var(--b3-ease);
}

.b3-rayon-pager__grille--sortie {
  opacity: 0;
  transform: translateY(8px);
}

@media (prefers-reduced-motion: reduce) {
  .b3-rayon-pager__grille {
    transition-duration: 0.01ms;
  }
}

/* La vignette suppose une largeur de 100 % posée par son conteneur habituel
   (`#products`, `.featured-products`…) : celui-ci n'en fait pas partie. */
.b3-rayon-pager__grille .product-miniature {
  width: 100%;
  padding: 0;
  float: none;
}

.b3-rayon-pager__grille .b3-card {
  background-color: var(--b3-papier);
}

/* Sous 480px, la grille à deux colonnes tassait chaque carte au point de
   rogner le nom des vins : deux colonnes minuscules valent moins qu'une
   large. Un ruban qui swipe au doigt tient la promesse d'un « slider » —
   la grille verticale, elle, ne l'a jamais été. `scroll-snap` fait le
   travail nativement : pas de librairie, pas de JS pour le geste, le
   navigateur gère le doigt aussi bien qu'Owl gérait la souris.

   Repris tel quel après un aller-retour : le format en une colonne pleine
   largeur, essayé un temps pour matcher le reste du catalogue, a été
   écarté au profit de ce ruban — préférence confirmée. */
@media (max-width: 479px) {
  .b3-rayon-pager__grille {
    display: flex;
    grid-template-columns: none;
    overflow-x: auto;
    overscroll-behavior-x: contain;
    scroll-snap-type: x mandatory;
    -webkit-overflow-scrolling: touch;
    margin: 0 calc(var(--b3-space-md) * -1);
    padding: 0 var(--b3-space-md) var(--b3-space-2xs);
    scrollbar-width: none;
  }

  .b3-rayon-pager__grille::-webkit-scrollbar {
    display: none;
  }

  .b3-rayon-pager__grille .product-miniature {
    flex: 0 0 76%;
    width: 76%;
    scroll-snap-align: start;
  }
}

@media (min-width: 640px) {
  .b3-rayon-pager__grille {
    grid-template-columns: repeat(3, minmax(0, 1fr));
  }
}

@media (min-width: 992px) {
  .b3-rayon-pager__grille {
    grid-template-columns: repeat(4, minmax(0, 1fr));
  }
}

.b3-rayon-pager__dots {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: var(--b3-space-3xs);
  margin-top: var(--b3-space-lg);
}

.b3-rayon-pager__dot {
  flex: none;
  width: 10px;
  height: 10px;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background-color: color-mix(in oklab, var(--b3-papier) 35%, transparent);
  cursor: pointer;
  transition: background-color var(--b3-dur-fast) var(--b3-ease),
              transform var(--b3-dur-fast) var(--b3-ease);
}

.b3-rayon-pager__dot:hover,
.b3-rayon-pager__dot:focus-visible {
  background-color: color-mix(in oklab, var(--b3-papier) 65%, transparent);
}

.b3-rayon-pager__dot.is-active {
  background-color: var(--b3-papier);
  transform: scale(1.3);
}

.b3-rayon-pager__compteur-pages {
  font-size: 0.875rem;
  font-weight: 700;
  color: var(--b3-papier);
}

/* Flèches précédent/suivant : disque encre plein, chevron papier — le même
   contraste que le bouton primaire inversé, jamais la sprite grise du thème
   acheté.

   Posées entre les cartes et le bord de l'écran, sur le jaune plutôt que
   sur l'aplat du pager : au-delà de 768px, le conteneur laisse une marge
   jaune de part et d'autre du bloc noir, assez large pour y loger un
   disque de 44px sans jamais chevaucher une carte. En dessous, cette marge
   n'existe plus (le bloc touche déjà les bords) : les flèches rentrent
   dans le rang, à côté des points, comme avant. */
.b3-rayon-pager__nav {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--b3-space-sm);
}

.b3-rayon-pager__fleche {
  flex: none;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  padding: 0;
  border: 2px solid var(--b3-papier);
  border-radius: 50%;
  background-color: transparent;
  color: var(--b3-papier);
  cursor: pointer;
  transition: background-color var(--b3-dur-fast) var(--b3-ease),
              color var(--b3-dur-fast) var(--b3-ease),
              transform var(--b3-dur-fast) var(--b3-ease);
}

.b3-rayon-pager__fleche svg {
  width: 20px;
  height: 20px;
}

.b3-rayon-pager__fleche:hover:not(:disabled) {
  background-color: var(--b3-papier);
  color: var(--b3-encre);
  transform: translateY(-1px);
}

.b3-rayon-pager__fleche:focus-visible {
  outline: 3px solid var(--b3-jaune);
  outline-offset: 2px;
}

.b3-rayon-pager__fleche:disabled {
  opacity: 0.3;
  cursor: default;
}

@media (min-width: 768px) {
  .b3-rayon-pager__fleche {
    position: absolute;
    top: 50%;
    transform: translateY(-50%);
    border-color: var(--b3-encre);
    background-color: var(--b3-encre);
    color: var(--b3-papier);
    box-shadow: 0 2px 0 0 color-mix(in oklab, var(--b3-encre) 40%, transparent);
  }

  .b3-rayon-pager__fleche:hover:not(:disabled) {
    background-color: var(--b3-jaune);
    border-color: var(--b3-encre);
    color: var(--b3-encre);
    transform: translateY(-50%) translateY(-2px);
  }

  .b3-rayon-pager__fleche--prev {
    left: calc(var(--b3-space-xl) * -1);
  }

  .b3-rayon-pager__fleche--next {
    right: calc(var(--b3-space-xl) * -1);
  }
}

@media (min-width: 1100px) {
  .b3-rayon-pager__fleche--prev {
    left: calc(var(--b3-space-2xl) * -1);
  }

  .b3-rayon-pager__fleche--next {
    right: calc(var(--b3-space-2xl) * -1);
  }
}

.b3-rayon-pager__dots:empty {
  margin: 0;
}

/* --------------------------------------------------------------------------
   Recherche du catalogue — pilule sous les filtres

   Fond papier, pas jaune : le jaune signale, il ne décore pas un champ de
   saisie qui n'a rien à annoncer tant qu'on ne l'a pas rempli.
   -------------------------------------------------------------------------- */
.b3-recherche {
  position: relative;
  display: flex;
  align-items: center;
  max-width: 420px;
  margin: var(--b3-space-md) 0 var(--b3-space-lg);
}

.b3-recherche__icone {
  position: absolute;
  left: var(--b3-space-md);
  width: 18px;
  height: 18px;
  color: var(--b3-encre-douce, var(--b3-encre));
  pointer-events: none;
}

.b3-recherche__champ {
  width: 100%;
  height: 48px;
  padding: 0 var(--b3-space-md) 0 calc(var(--b3-space-md) * 2 + 18px);
  border: 2px solid var(--b3-trait-fort, var(--b3-encre));
  border-radius: 999px;
  background-color: var(--b3-papier);
  color: var(--b3-encre);
  font-family: var(--b3-font);
  font-size: 0.9375rem;
  transition: border-color var(--b3-dur-fast) var(--b3-ease);
}

.b3-recherche__champ::placeholder {
  color: color-mix(in oklab, var(--b3-encre) 45%, transparent);
}

.b3-recherche__champ:focus-visible {
  outline: 3px solid var(--b3-jaune);
  outline-offset: 2px;
  border-color: var(--b3-encre);
}

/* Chrome/Safari ajoutent leurs propres boutons d'annulation à
   `type="search"` : on les retire, la charte n'a pas de croix ronde grise. */
.b3-recherche__champ::-webkit-search-cancel-button {
  -webkit-appearance: none;
  appearance: none;
}

/* --------------------------------------------------------------------------
   Pagination de la grille de repli (accueil, section « Notre catalogue »,
   filtre « Tout »)

   Même principe que les points du panachage par rayon (voir plus haut),
   sur un aplat jaune plutôt qu'encre : les points restent en encre, l'actif
   passe en encre plein plutôt qu'en papier — sur ce fond-ci, un point blanc
   se serait fondu dans le jaune au lieu de s'en détacher.
   -------------------------------------------------------------------------- */
.b3-defaut-pager__dots {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: var(--b3-space-3xs);
  margin-top: var(--b3-space-lg);
}

.b3-defaut-pager__dot {
  flex: none;
  width: 10px;
  height: 10px;
  padding: 0;
  border: 1.5px solid var(--b3-encre);
  border-radius: 50%;
  background-color: transparent;
  cursor: pointer;
  transition: background-color var(--b3-dur-fast) var(--b3-ease),
              transform var(--b3-dur-fast) var(--b3-ease);
}

.b3-defaut-pager__dot:hover,
.b3-defaut-pager__dot:focus-visible {
  background-color: color-mix(in oklab, var(--b3-encre) 35%, transparent);
}

.b3-defaut-pager__dot.is-active {
  background-color: var(--b3-encre);
  transform: scale(1.3);
}

.b3-defaut-pager__dots[hidden] {
  display: none;
}


/* ===== 06-catalogue.css ================================================== */

/* ===== 06-catalogue.css ================================================== */
/* 7.6 — La grille, sans point de rupture.
   Les blocs de la page d'accueil (produits phares, nouveautés) ne sont pas des
   grilles mais des carrousels Owl : leur donner `display: grid` écrase le
   défilement et réduit chaque diapositive à quelques pixels. On les exclut. */
#products .products,
.products.row:not(:has(.owl-carousel)),
.product-accessories .products:not(:has(.owl-carousel)),
/* Les blocs de bas de fiche produit — « autres produits de la catégorie », «
   les clients ont aussi acheté » — sortent un `.products` sans classe `row` et
   sans carrousel. Aucun sélecteur ne les atteignait : leurs seize vignettes
   s'empilaient en une colonne de près de huit mille pixels. */
.featured-products .products:not(:has(.owl-carousel)){
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(230px, 1fr));
  gap: var(--b3-space-md);
  margin-left: 0;
  margin-right: 0;
}

/* Sur un téléphone, une colonne de 230 px minimum ne laisse passer qu'une
   vignette par ligne : la carte s'étire alors sur toute la largeur et le rayon
   défile interminablement. Deux colonnes tiennent dès 320 px de large, ce qui
   rapproche la vignette du format carré recherché et divise par deux la
   hauteur de la liste. */
@media (max-width: 639px) {
#products .products,
  .products.row:not(:has(.owl-carousel)),
  .product-accessories .products:not(:has(.owl-carousel)),
  .featured-products .products:not(:has(.owl-carousel)) {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: var(--b3-space-sm);
  }
}

.featured-products .homepage-products {
  padding: var(--b3-space-2xs) 0 var(--b3-space-md);
}

@media (max-width: 479px) {
#products .products,
  .products.row:not(:has(.owl-carousel)){
    grid-template-columns: repeat(2, 1fr);
    gap: var(--b3-space-sm) var(--b3-space-xs);
  }
}

/* Point de rupture tablette dédié — chantier v9, iPad portrait et paysage. */
@media (min-width: 768px) and (max-width: 1024px) {
#products .products,
  .products.row:not(:has(.owl-carousel)){
    grid-template-columns: repeat(3, 1fr);
    gap: var(--b3-space-md) var(--b3-space-sm);
  }
}

/* --------------------------------------------------------------------------
   Vue liste

   Le thème acheté reconstruisait chaque vignette en JavaScript pour ce mode
   (`custom.js`, `display('list')`), en relisant des classes que la refonte
   de la carte n'a pas gardées — d'où des vignettes vides, le mot
   « undefined » à la place de l'image (voir 3b.js, la bascule sans
   reconstruction qui remplace ce mécanisme). Ici, seule la disposition
   change : une colonne de rangées plutôt qu'une grille, la carte pivote de
   `column` à `row`. Le balisage ne bouge pas.
   -------------------------------------------------------------------------- */
#products .products.list {
  display: flex;
  flex-direction: column;
  gap: var(--b3-space-sm);
}

#products .products.list > .product-miniature {
  width: 100%;
}

#products .products.list .b3-card {
  flex-direction: row;
  height: auto;
}

#products .products.list .b3-card__media {
  flex: none;
  width: 30%;
  max-width: 220px;
}

#products .products.list .b3-card__thumb {
  aspect-ratio: 1;
  height: 100%;
}

#products .products.list .b3-card__body {
  flex: 1 1 auto;
  justify-content: center;
}

@media (max-width: 575px) {
  #products .products.list .b3-card {
    flex-direction: row;
  }

  #products .products.list .b3-card__media {
    width: 38%;
  }
}

/* Carrousel : flèches retirées au profit de points, plus discrets et
   utilisables au doigt. */
/* Les flèches reviennent, mais de part et d'autre du carrousel plutôt que
   posées sur les visuels : elles masquaient les bouteilles. */
.b3-picks .featured-products.container {
  position: relative;
}

/* 9ter.5 — Le carrousel déborde par construction (il défile) : on borne son
   débordement au conteneur plutôt qu'à la page. */
.homepage-products,
.featured-products .row {
  overflow: hidden;
}

.b3-picks .featured-products.container {
  max-width: 1320px;
  margin: 0 auto;
  padding: 0 var(--b3-space-md);
}

/* Les rangées Bootstrap du module portent des marges négatives de 15 px : la
   piste du carrousel démarrait à −14 px et débordait de 28 px au total. */
.b3-picks .featured-products.container > .row,
.b3-picks .homepage-products {
  margin-left: 0;
  margin-right: 0;
}

@media (max-width: 767px) {
.b3-picks .featured-products.container {
    padding: 0 var(--b3-space-sm);
  }
}

/* --------------------------------------------------------------------------
   9sexdecies. Filtre de la sélection
   -------------------------------------------------------------------------- */
.b3-filters {
  display: flex;
  flex-wrap: wrap;
  gap: var(--b3-space-2xs);
  margin: 0 0 var(--b3-space-md);
}

/* Fond papier plutôt que transparent : sur l'aplat jaune de « La sélection des
   cavistes », un fond transparent laissait passer le jaune et la pastille se
   lisait comme du jaune sur du jaune, cernée d'un trait. Le papier la détache
   de la bande et laisse l'encre au texte. */
.b3-filter {
  min-height: 40px;
  padding: 0 var(--b3-space-md);
  border: 2px solid var(--b3-encre);
  border-radius: var(--b3-radius-pill);
  background-color: var(--b3-papier);
  color: var(--b3-encre);
  font-family: var(--b3-font);
  font-size: 0.75rem;
  font-weight: 800;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  cursor: pointer;
  transition: background-color var(--b3-dur-fast) var(--b3-ease),
              color var(--b3-dur-fast) var(--b3-ease);
}

.b3-filter:hover {
  background-color: var(--b3-papier-2);
}

/* L'état retenu est porté par le fond plein, pas seulement par la couleur :
   `aria-pressed` le dit aussi aux technologies d'assistance. */
.b3-filter.is-active {
  background-color: var(--b3-encre);
  color: var(--b3-papier);
}

.b3-filters__empty {
  margin: 0 0 var(--b3-space-md);
  color: var(--b3-encre);
  font-size: 0.9375rem;
}

.b3-filters__empty[hidden] {
  display: none;
}

/* --------------------------------------------------------------------------
   9novodecies. Catalogue — navigation à facettes et barre de tri
   Le module gardait l'habillage du thème acheté : cases grises, libellés en
   gris clair sur blanc, aucune zone cliquable lisible.
   -------------------------------------------------------------------------- */
#left-column .block-categories,
#left-column .facet,
#search_filters,
#search_filters_wrapper {
  border: 1px solid var(--b3-trait);
  border-radius: var(--b3-radius);
  background-color: var(--b3-papier);
  padding: var(--b3-space-sm);
  margin-bottom: var(--b3-space-sm);
}

#search_filters .facet + .facet {
  margin-top: var(--b3-space-sm);
  padding-top: var(--b3-space-sm);
  border-top: 1px solid var(--b3-trait);
}

#search_filters .facet-title,
#left-column .block-categories .h6,
#left-column .text-uppercase {
  color: var(--b3-encre);
  font-size: 0.8125rem;
  font-weight: 800;
  text-transform: uppercase;
  letter-spacing: 0.1em;
}

/* Les libellés étaient en gris clair : sous le seuil AA sur fond papier. */
/* `:not(.ui-slider-handle)` : les deux poignées du curseur de prix sont des
   liens, posés dans la même liste de facette. Sans l'exclusion, elles
   héritaient de `display: flex` et de la hauteur tactile de 40 px — deux
   ellipses de quarante pixels de haut posées sur une barre de quatre. */
#search_filters .facet li a:not(.ui-slider-handle),
#search_filters .facet label,
#left-column .category-sub-menu a,
#left-column .block-categories a {
  display: flex;
  align-items: center;
  gap: var(--b3-space-2xs);
  min-height: 40px;
  color: var(--b3-encre);
  font-size: 0.9375rem;
  font-weight: 600;
  text-decoration: none;
}

#search_filters .facet li a:not(.ui-slider-handle):hover,
#left-column .block-categories a:hover {
  color: var(--b3-encre);
  text-decoration: underline;
  text-underline-offset: 3px;
}

/* Barre de tri et bascule grille / liste. */
#js-product-list-top,
.products-selection {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--b3-space-sm);
  padding: var(--b3-space-sm) 0;
  border-bottom: 1px solid var(--b3-trait);
  margin-bottom: var(--b3-space-md);
}

.products-selection .sort-by-row,
#js-product-list-top .col-md-6 {
  display: flex;
  align-items: center;
  gap: var(--b3-space-2xs);
}

.products-sort-order .select-title,
#js-product-list-top select {
  min-height: 44px;
  padding: 0 var(--b3-space-sm);
  border: 1px solid var(--b3-trait-fort);
  border-radius: var(--b3-radius-pill);
  background-color: var(--b3-papier);
  color: var(--b3-encre);
  font-family: var(--b3-font);
  font-size: 0.875rem;
  font-weight: 600;
}

/* Le thème acheté écrit `.sort-by`, `.products-sort-order` et
   `.total-products P` en gris clair (#999, ratio 2.8:1) : lisible sur
   l'ancien fond encre de cette page, plus du tout sur le papier revenu par
   défaut. Seule la version mobile avait été reprise ; le bureau restait sur
   le gris d'origine. */
.products-selection .sort-by,
.products-sort-order,
.products-selection .total-products,
.products-selection .total-products p,
#js-product-list-top .total-products {
  color: var(--b3-encre) !important;
}

/* « Filtrer » (déclencheur du panneau de facettes sur mobile, voir
   `#search_filter_toggler` — products-top.tpl du thème acheté) n'avait que
   le style générique `.btn.btn-secondary`, sans rapport avec « Pertinence »
   à côté. Même gabarit de pastille pour les deux : au doigt, ce sont deux
   commandes de même poids sur la même ligne, elles doivent se lire comme
   telles. Un pictogramme distinct par bouton — l'entonnoir pour filtrer, les
   flèches pour trier — plutôt qu'un mot seul à décrypter. */
#search_filter_toggler {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.4em;
  min-height: 44px;
  padding: 0 var(--b3-space-sm);
  border: 1px solid var(--b3-trait-fort);
  border-radius: var(--b3-radius-pill);
  background-color: var(--b3-papier);
  color: var(--b3-encre);
  font-family: var(--b3-font);
  font-size: 0.875rem;
  font-weight: 600;
  text-transform: none;
}

#search_filter_toggler:hover,
#search_filter_toggler:focus-visible {
  border-color: var(--b3-encre);
  background-color: var(--b3-papier-2);
}

.products-sort-order .select-title::before,
#search_filter_toggler::before {
  font-family: "Material Icons";
  font-size: 1.125rem;
  line-height: 1;
  speak: none;
  -webkit-font-smoothing: antialiased;
}

.products-sort-order .select-title {
  display: inline-flex;
  align-items: center;
  gap: 0.4em;
}

.products-sort-order .select-title::before {
  content: "\E164"; /* sort */
}

#search_filter_toggler::before {
  content: "\E152"; /* filter_list */
}


/* ----- repris de 09-divers ----- */

/* Reliquat sans composant identifié. */
/* --------------------------------------------------------------------------
   7bis. En-tête de page catégorie
   Un seul titre, à l'échelle « Affiche ». Le décalage de repérage s'y joue :
   une seule occurrence par écran.
   -------------------------------------------------------------------------- */
.b3-category-header {
  padding: 0;
  border: 0;
  border-radius: 0;
  background: transparent;
  box-shadow: none;
  margin-bottom: var(--b3-space-lg);
}

.b3-category-header .category-cover {
  margin-bottom: var(--b3-space-md);
}

.b3-category-header .category-cover img {
  display: block;
  width: 100%;
  height: auto;
}

.b3-category-header h1.h1 {
  margin: 0 0 var(--b3-space-sm);
  font-size: clamp(2.25rem, 5vw, 3.75rem);
  font-weight: 800;
  font-stretch: 68%;
  line-height: 0.95;
  letter-spacing: -0.02em;
  text-transform: uppercase;
  color: var(--b3-encre);
  text-shadow: 4px 4px 0 var(--b3-jaune);
}

.b3-category-header #category-description {
  max-width: 68ch;
  color: var(--b3-encre-douce);
  font-size: 1.0625rem;
  line-height: 1.65;
}

.b3-category-header #category-description p {
  margin-bottom: var(--b3-space-xs);
}

@media (max-width: 767px) {
.b3-category-header h1.h1 {
    text-shadow: 3px 3px 0 var(--b3-jaune);
  }
}

/* Filtres retenus, en pastilles retirables. */
#js-active-search-filters {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--b3-space-2xs);
  padding: var(--b3-space-sm) 0;
  border: 0;
}

#js-active-search-filters .filter-block {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  min-height: 36px;
  padding: 0 var(--b3-space-xs);
  border-radius: var(--b3-radius-pill);
  background-color: var(--b3-encre);
  color: var(--b3-papier);
  font-size: 0.75rem;
  font-weight: 700;
}

#js-active-search-filters .filter-block .close {
  color: var(--b3-jaune);
  opacity: 1;
  font-size: 1rem;
}

/* La bascule grille / liste : deux boutons carrés jaune et noir, sans
   libellé. Ils deviennent une paire lisible. */
#grid,
#list,
.display-grid,
.display-list {
  display: grid;
  place-items: center;
  width: 44px;
  height: 44px;
  border: 1px solid var(--b3-trait-fort);
  border-radius: var(--b3-radius-sm);
  background-color: var(--b3-papier);
  color: var(--b3-encre);
}

#grid.selected,
#list.selected,
.display-grid.selected,
.display-list.selected {
  border-color: var(--b3-encre);
  background-color: var(--b3-encre);
  color: var(--b3-papier);
}

/* En-tête de catégorie : l'image de couverture était rognée et le titre
   posé dessus. */
.b3-category-header .category-cover img {
  border-radius: var(--b3-radius);
  max-height: 220px;
  object-fit: cover;
}


/* ----- repris de 09-divers ----- */

@media (max-width: 991px) {
/* La colonne de filtres passe au-dessus des résultats, repliée. */
#left-column {
    order: -1;
  }

#search_filters,
  #search_filters_wrapper {
    margin-bottom: var(--b3-space-md);
  }
}


/* ==========================================================================
   Filtres du catalogue — refonte

   La colonne de facettes était restée au gabarit du thème : listes serrées,
   cases à cocher natives, compteurs collés aux libellés, aucun repère visuel.
   Sur un catalogue de 649 vins répartis en quatorze régions, c'est le premier
   outil de navigation du site — il mérite mieux qu'une liste.

   Chaque entrée reçoit un pictogramme posé par 3b.js : drapeau pour un pays,
   drapeau français pour une région française, verre ou bouteille pour une
   couleur, feuille pour un label. Il double le libellé écrit, jamais ne le
   remplace.
   ========================================================================== */

/* Un seul cadre par facette. Le bloc englobant portait le sien, et chaque
   facette le sien : trois rectangles arrondis emboîtés pour trois cases à
   cocher. Le titre « Filtrer par » reste, sans boîte autour. */
#search_filters,
#search_filters_wrapper,
#left-column #search_filters_wrapper {
  padding: 0;
  border: 0;
  border-radius: 0;
  background: transparent;
  box-shadow: none;
}

/* Un bloc de facette par carte papier : la colonne cesse d'être une liste
   continue où l'œil ne sait plus quel titre commande quelle option. */
#search_filters .facet {
  margin-bottom: var(--b3-space-sm);
  padding: var(--b3-space-sm);
  border: 1.5px solid var(--b3-trait);
  border-radius: var(--b3-radius);
  background-color: var(--b3-papier);
}

#search_filters .facet .facet-title,
#search_filters .facet .h6 {
  display: block;
  margin: 0 0 var(--b3-space-2xs);
  padding: 0;
  border: 0;
  font-size: 0.75rem;
  font-weight: 800;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--b3-encre);
}

#search_filters .facet ul {
  margin: 0;
  padding: 0;
  list-style: none;
}

#search_filters .facet li {
  margin: 0;
  padding: 0;
  border: 0;
}

/* Chaque option est une ligne entièrement cliquable, à hauteur tactile. */
#search_filters .facet-label,
#search_filters .facet li > a {
  display: flex;
  align-items: center;
  gap: var(--b3-space-2xs);
  min-height: 40px;
  margin: 0;
  padding: 0 var(--b3-space-2xs);
  border-radius: var(--b3-radius-sm);
  font-size: 0.875rem;
  /* 600 rendait toute la colonne aussi appuyée que ses titres : une liste
     d'options se lit, elle ne s'annonce pas. */
  font-weight: 500;
  line-height: 1.3;
  text-decoration: none;
  color: var(--b3-encre);
  cursor: pointer;
  transition: background-color var(--b3-dur-fast) var(--b3-ease);
}

/* Le lien occupe la place restante et garde le compteur à droite. */
#search_filters .facet li > a {
  flex: 1 1 auto;
  min-width: 0;
  padding-left: 0;
}

#search_filters .facet-label:hover,
#search_filters .facet li > a:hover {
  background-color: var(--b3-papier-2);
}

/* Le pictogramme est posé en attribut par le script : le CSS ne sait pas
   reconnaître « Espagne » dans un nœud de texte. */
/* La pastille grise autour du repère en faisait un troisième objet dans une
   ligne qui en portait déjà deux — la case et le libellé. Le repère se pose
   nu, à la taille d'une lettre capitale, juste avant le mot qu'il illustre. */
#search_filters [data-b3-picto]::before {
  content: attr(data-b3-picto);
  flex: none;
  margin-right: 0.15em;
  font-size: 1.0625rem;
  line-height: 1;
}

/* Le compteur se détache du libellé : collé à lui, il se lisait comme une
   partie du nom de la région. */
#search_filters .facet-label .magnitude,
#search_filters .facet li .magnitude {
  margin-left: auto;
  padding: 0 0.5em;
  border-radius: var(--b3-radius-pill);
  background-color: var(--b3-papier-2);
  font-size: 0.75rem;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  color: var(--b3-encre-douce);
}

/* La case reprend le trait du système plutôt que le contrôle natif, dont le
   dessin varie d'un système à l'autre. */
#search_filters .custom-checkbox input[type="checkbox"] + span,
#search_filters .custom-radio input[type="radio"] + span {
  flex: none;
  width: 20px;
  height: 20px;
  margin: 0;
  border: 2px solid var(--b3-trait-fort);
  border-radius: 6px;
  background-color: var(--b3-papier);
}

#search_filters .custom-checkbox input[type="checkbox"]:checked + span,
#search_filters .custom-radio input[type="radio"]:checked + span {
  border-color: var(--b3-encre);
  background-color: var(--b3-encre);
}

#search_filters .custom-checkbox input[type="checkbox"]:checked + span::after {
  content: "";
  display: block;
  width: 100%;
  height: 100%;
  background-color: var(--b3-jaune);
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='3.4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M4 12.5l5.2 5.2L20 7'/%3E%3C/svg%3E") center / 74% no-repeat;
  mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='3.4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M4 12.5l5.2 5.2L20 7'/%3E%3C/svg%3E") center / 74% no-repeat;
}

#search_filters .custom-checkbox input[type="checkbox"]:focus-visible + span,
#search_filters .custom-radio input[type="radio"]:focus-visible + span {
  outline: 3px solid var(--b3-encre);
  outline-offset: 2px;
}

/* Filtres actifs : ce qui est retiré d'un clic doit se voir comme tel. */
#js-active-search-filters {
  margin-bottom: var(--b3-space-sm);
  padding: var(--b3-space-2xs) 0 0;
  border: 0;
  background: transparent;
}

#js-active-search-filters .filter-block {
  display: inline-flex;
  align-items: center;
  gap: 0.4em;
  margin: 0 var(--b3-space-3xs) var(--b3-space-3xs) 0;
  padding: 0.35em 0.7em;
  border: 0;
  border-radius: var(--b3-radius-pill);
  background-color: var(--b3-encre);
  font-size: 0.8125rem;
  font-weight: 700;
  color: var(--b3-jaune);
}


/* --------------------------------------------------------------------------
   Filtres — reprise de la ligne

   Le libellé d'une option aligne quatre choses : un pictogramme, une case, le
   texte et son compteur. Sur une colonne de 218 px, les trois premiers en
   occupent 47 : c'est au texte de céder, et à lui seul.
   -------------------------------------------------------------------------- */

#search_filters .facet-label {
  display: flex;
  align-items: center;
  gap: var(--b3-space-2xs);
  width: 100%;
}

/* Pictogramme et case gardent leur taille ; seul le lien s'ajuste. */
#search_filters .facet-label::before,
#search_filters .facet-label .custom-checkbox {
  flex: none;
}

#search_filters .facet-label .custom-checkbox {
  display: grid;
  place-items: center;
  width: 20px;
  height: 20px;
  margin: 0;
}

#search_filters .facet-label > a,
#search_filters .facet-label .search-link {
  display: flex;
  align-items: center;
  gap: var(--b3-space-2xs);
  flex: 1 1 auto;
  min-width: 0;
  min-height: 0;
  padding: 0;
  font-size: 0.875rem;
  font-weight: 500;
  line-height: 1.25;
  color: var(--b3-encre);
}

/* Remise à zéro inverse : le repère vit désormais sur le lien, c'est
   l'étiquette qui ne doit plus le porter. Le script ne le pose plus là, mais
   une page servie depuis un cache ancien pourrait encore le faire. */
#search_filters .facet-label[data-b3-picto]::before {
  content: none;
}

#search_filters .facet-label .magnitude {
  flex: none;
  margin-left: auto;
}

/* La case cochée : le contour du thème laissait un « U » ouvert. */
#search_filters .custom-checkbox input[type="checkbox"] {
  position: absolute;
  width: 20px;
  height: 20px;
  margin: 0;
  opacity: 0;
  cursor: pointer;
}

#search_filters .custom-checkbox input[type="checkbox"] + span {
  display: grid;
  place-items: center;
  width: 20px;
  height: 20px;
  margin: 0;
  border: 2px solid var(--b3-trait-fort);
  border-radius: 6px;
  background-color: var(--b3-papier);
  pointer-events: none;
}


/* Un libellé long — « Languedoc - Roussillon », « Provence - Corse » — poussait
   son compteur hors de la colonne. Il se tronque proprement : le compteur est
   l'information qu'on lit en diagonale, il doit rester visible. */
#search_filters .facet-label > a,
#search_filters .facet-label .search-link {
  overflow: hidden;
}

#search_filters .facet-label .search-link {
  white-space: nowrap;
  text-overflow: ellipsis;
}

#search_filters .facet-label .magnitude {
  white-space: nowrap;
}


/* --------------------------------------------------------------------------
   Curseur de prix

   jQuery UI dessine ici deux poignées hautes de vingt-huit pixels sur une
   barre de six : à la capture, elles se lisaient comme deux traits verticaux
   posés au hasard sur un tuyau. La barre reprend le trait du système, et les
   poignées deviennent deux disques d'encre — la forme qu'on attend d'une
   chose qu'on tire.
   -------------------------------------------------------------------------- */

#search_filters .faceted-slider {
  padding: var(--b3-space-2xs) var(--b3-space-3xs) 0;
}

/* La fourchette chiffrée est l'information, pas la décoration : elle passe en
   encre. En gris clair sur papier, elle plafonnait sous le seuil AA. */
#search_filters .faceted-slider p,
#search_filters .faceted-slider label {
  margin: 0 0 var(--b3-space-2xs);
  font-size: 0.875rem;
  font-weight: 700;
  color: var(--b3-encre);
}

#search_filters .ui-slider-horizontal {
  height: 4px;
  margin: var(--b3-space-2xs) 0 var(--b3-space-md);
  border: 0;
  border-radius: var(--b3-radius-pill);
  background-color: var(--b3-trait);
}

#search_filters .ui-slider-horizontal .ui-slider-range {
  height: 4px;
  border-radius: var(--b3-radius-pill);
  background-color: var(--b3-encre);
}

#search_filters .ui-slider-horizontal .ui-slider-handle {
  top: 50%;
  width: 18px;
  height: 18px;
  margin-left: -9px;
  border: 2px solid var(--b3-encre);
  border-radius: 50%;
  background-color: var(--b3-papier);
  transform: translateY(-50%);
  cursor: grab;
  transition: transform var(--b3-dur-fast) var(--b3-ease);
}

#search_filters .ui-slider-horizontal .ui-slider-handle:hover,
#search_filters .ui-slider-horizontal .ui-slider-handle:focus-visible {
  transform: translateY(-50%) scale(1.12);
}

#search_filters .ui-slider-horizontal .ui-slider-handle:active {
  cursor: grabbing;
}

/* Le tri par ventes se distingue des filtres de contenu : « meilleures
   ventes » n'est ni une couleur ni une région, c'est un ordre. La pastille
   prend l'encre pleine, comme un état plutôt qu'un choix. */
/* Le tri par ventes se distingue des filtres de contenu : « meilleures
   ventes » n'est ni une couleur ni une région, c'est un ordre. Le rose est le
   même écart assumé à la palette que celui des boutons de mise en favori — il
   ne désigne pas une gamme, il désigne un geste. */
.b3-filter--ventes.is-active {
  background-color: #e8467c;
  border-color: var(--b3-papier);
  color: var(--b3-papier);
}

.b3-filter--ventes.is-active:hover {
  background-color: #d13a6d;
  border-color: var(--b3-papier);
  color: var(--b3-papier);
}

/* Une diapositive masquée reste dans la piste d'Owl, qui compte sa largeur :
   il faut la sortir du flux, pas seulement la rendre invisible. */
.b3-slide[hidden] {
  display: none !important;
}

/* --------------------------------------------------------------------------
   Blason de région

   Les logos officiels des interprofessions viticoles sont des marques
   déposées : les reproduire suppose une autorisation écrite, que la maison
   n'a pas. Un monogramme dans un disque les remplace — il se reconnaît d'un
   coup d'œil et n'engage personne.

   Il remplace surtout le drapeau tricolore, qui désignait aussi bien la
   Bourgogne que la Loire ou le Sud-Ouest : tous les filtres français
   portaient le même signe, donc aucun.
   -------------------------------------------------------------------------- */

.b3-filter[data-b3-blason]::before {
  content: attr(data-b3-blason);
  flex: none;
  display: inline-grid;
  place-items: center;
  width: 1.55em;
  height: 1.55em;
  margin-right: 0.5em;
  border-radius: 50%;
  background-color: var(--b3-encre);
  color: var(--b3-jaune);
  font-size: 0.625rem;
  font-weight: 800;
  letter-spacing: 0;
  line-height: 1;
  vertical-align: -0.35em;
}

/* Sur une pastille retenue, le disque s'inverse : le fond est déjà encre. */
.b3-filter.is-active[data-b3-blason]::before {
  background-color: var(--b3-jaune);
  color: var(--b3-encre);
}

/* --------------------------------------------------------------------------
   Rayons en liens

   Même forme que les filtres qui les suivent — ils répondent à la même
   question, « où est ce que je cherche ? » — mais la flèche dit qu'ils
   emmènent ailleurs plutôt que de trier sur place.
   -------------------------------------------------------------------------- */

.b3-rayons-liens {
  display: flex;
  flex-wrap: wrap;
  gap: var(--b3-space-2xs);
  margin: 0 0 var(--b3-space-sm);
}

.b3-rayon-lien {
  display: inline-flex;
  align-items: center;
  gap: 0.45em;
  min-height: 40px;
  padding: 0 var(--b3-space-md);
  border: 2px solid var(--b3-encre);
  border-radius: var(--b3-radius-pill);
  background-color: var(--b3-encre);
  font-family: var(--b3-font);
  font-size: 0.75rem;
  font-weight: 800;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  text-decoration: none;
  color: var(--b3-papier);
  transition: background-color var(--b3-dur-fast) var(--b3-ease),
              color var(--b3-dur-fast) var(--b3-ease);
}

.b3-rayon-lien:hover,
.b3-rayon-lien:focus-visible {
  background-color: var(--b3-papier);
  color: var(--b3-encre);
  text-decoration: none;
}

.b3-rayon-lien__emoji {
  font-size: 1.125rem;
  line-height: 1;
}

.b3-rayon-lien__fleche {
  font-size: 0.9375rem;
  line-height: 1;
  opacity: 0.7;
}


/* ==========================================================================
   La page de catalogue sur téléphone

   Relevé sur un iPhone : entre la barre de recherche et la première bouteille,
   huit cents pixels de page dont l'essentiel est du vide. Le titre, une barre
   de tri surdimensionnée, un compteur en gris pâle et trois filets séparateurs
   se succédaient sans qu'aucun ne porte d'information. Le visiteur qui arrive
   sur « Vins » veut voir des vins.
   ========================================================================== */

@media (max-width: 767px) {
  /* Le bandeau de catégorie. Trente-deux pixels de marge basse sous un titre
     de trente-quatre : la respiration valait le titre lui-même. */
  .block-category,
  .block-category.b3-category-header {
    margin-bottom: var(--b3-space-xs);
  }

  #js-product-list-header h1,
  .block-category h1 {
    margin-bottom: var(--b3-space-2xs);
    font-size: clamp(1.75rem, 8vw, 2.25rem);
  }

  /* La barre de tri : deux commandes qui occupaient cent trente pixels. Elles
     tiennent sur une rangée, à la hauteur d'une cible tactile. */
  .products-selection,
  #js-product-list-top {
    margin-bottom: var(--b3-space-xs) !important;
    padding-block: var(--b3-space-3xs) !important;
  }

  .products-selection .sort-by-row,
  .products-selection > div {
    display: flex;
    align-items: center;
    gap: var(--b3-space-2xs);
    margin-inline: 0;
  }

  /* Le tri et le bouton filtrer se partagent la largeur à égalité : l'un
     flottait plus large que l'autre, sans rapport avec ce que chacun pèse
     dans la décision. */
  .products-selection .sort-by-row > * {
    flex: 1 1 0;
  }

  .products-selection .btn,
  .products-selection .select-title,
  #js-product-list-top .btn {
    min-height: 44px;
    width: 100%;
    padding: 0 var(--b3-space-sm);
    font-size: 0.8125rem;
  }

  /* Le compteur devient une information et non une note de bas de page : il
     dit au visiteur l'ampleur de ce qu'il parcourt. */
  .products-selection .total-products,
  #js-product-list-top .total-products {
    display: block !important;
    margin: 0;
    padding: 0;
    font-size: 0.8125rem;
    font-weight: 700;
    color: var(--b3-encre);
  }

  /* Les filets séparateurs vides. Le thème en pose un par rangée de sa
     grille : trois traits pour deux informations. On n'en garde qu'un. */
  .products-selection + hr,
  .products-selection hr,
  #js-product-list-top + hr {
    display: none;
  }

  /* L'étiquette de rupture débordait de la vignette : posée en absolu avec un
     texte plein, elle sortait par la droite et passait sous le cœur. Elle se
     borne à la carte et cède le coin au bouton de favori. */
  .product-flags,
  .b3-card .product-flags {
    max-width: calc(100% - 56px);
  }

  .product-flag,
  .b3-card .product-flag {
    max-width: 100%;
    padding: 0.25em 0.6em;
    font-size: 0.625rem;
    line-height: 1.2;
    white-space: normal;
    overflow-wrap: anywhere;
  }

  /* Le bouton « rupture de stock » du pied de carte prenait deux lignes et
     débordait de la vignette. */
  .b3-card__footer .btn-danger,
  .b3-card__footer [disabled] {
    width: 100%;
    min-height: 38px;
    padding: 0 var(--b3-space-2xs);
    font-size: 0.6875rem;
    line-height: 1.15;
    white-space: normal;
  }
}


@media (max-width: 767px) {
  /* Le vide sous l'en-tête. Mesuré : le bas de l'en-tête tombe à 178 px et le
     titre de catégorie commence à 240. Les soixante-deux pixels manquants
     étaient le rembourrage haut de `section.wrapper`, hérité du thème, qui
     supposait un fil d'Ariane et un bandeau que cette page n'a plus. */
  section.wrapper,
  #wrapper {
    padding-top: var(--b3-space-sm);
  }

  /* Sauf sur l'accueil : la hero y est jaune et touche l'en-tête. Ce
     rembourrage laissait passer le papier de la page sur seize pixels — une
     bande claire entre deux aplats de la même couleur, exactement ce que la
     suppression des filets noirs devait faire disparaître. */
  .page-index section.wrapper,
  .page-index #wrapper {
    padding-top: 0;
  }

  /* Le compteur d'articles. Le thème le pose deux fois : une version masquée
     sous 768 px (`hidden-sm-down`) et une visible en gris pâle. C'est la
     seconde qu'on lit, et elle porte pourtant l'ampleur du rayon. */
  .products-selection p,
  #js-product-list-top p,
  .product-count,
  .showing {
    margin: 0;
    font-size: 0.8125rem;
    font-weight: 700;
    color: var(--b3-encre);
  }
}

/* --------------------------------------------------------------------------
   L'étiquette d'état, bornée à sa vignette

   Mesurée sur une carte de 340 px : l'étiquette commençait à 212 et courait
   sur 159, soit trente pixels au-delà du bord. « Rupture de stock » se lisait
   « Rupture de st ». Elle est posée en absolu, elle n'a donc aucune largeur de
   référence — il faut la lui donner.

   Le coin haut droit revient au bouton de favori : l'étiquette s'arrête avant.
   -------------------------------------------------------------------------- */
.b3-card__flags {
  right: auto;
  max-width: calc(100% - var(--b3-space-2xs) * 2 - 46px);
}

.b3-card__flag {
  max-width: 100%;
  white-space: normal;
  overflow-wrap: anywhere;
  line-height: 1.15;
  text-align: left;
}

@media (max-width: 767px) {
  .b3-card__flags {
    max-width: calc(100% - var(--b3-space-2xs) * 2 - 42px);
  }

  .b3-card__flag {
    padding: 3px 8px;
    font-size: 0.625rem;
  }
}

/* ==========================================================================
   Pages catalogue (catégorie, recherche) — retour au papier, bordures

   L'aplat encre (aplat de fond, breadcrumb, texte remonté au papier) est
   revenu sur ces deux pages après recette : trop de noir sur des pages
   qu'on parcourt longtemps (76 pages sur « Toutes nos références »)
   fatiguait l'œil, et cassait la continuité avec le reste du site, resté
   clair partout ailleurs. `body` retrouve son aplat papier par défaut
   (00-fondations.css) sans rien à réécrire ici.
   Le repère visuel qui séparait les cartes du fond noir devient une
   bordure — cartes et bloc de filtres se détachent maintenant du papier
   par un trait, pas par un contraste de fond. */
body.page-category .b3-card,
body.page-search .b3-card {
  border: 1px solid var(--b3-trait-fort);
}

body.page-category #search_filters_wrapper,
body.page-search #search_filters_wrapper {
  border: 1px solid var(--b3-trait-fort);
  border-radius: var(--b3-radius);
  padding: var(--b3-space-md);
}

/* Boutons et numéros de page : encre sur papier par défaut (hérité), la
   page courante se détache en aplat jaune plein — même geste que partout
   ailleurs sur le site pour signaler un état actif. Cible tactile 44px. */
body.page-category .pagination a,
body.page-category .pagination span,
body.page-search .pagination a,
body.page-search .pagination span {
  min-width: 44px;
  min-height: 44px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border: 1px solid var(--b3-trait-fort);
  border-radius: var(--b3-radius-pill);
  color: var(--b3-encre);
}

body.page-category .pagination a:hover,
body.page-category .pagination a:focus-visible,
body.page-search .pagination a:hover,
body.page-search .pagination a:focus-visible {
  border-color: var(--b3-encre);
  background-color: color-mix(in oklab, var(--b3-encre) 8%, transparent);
}

body.page-category .pagination .current span,
body.page-search .pagination .current span {
  border-color: var(--b3-jaune);
  background-color: var(--b3-jaune);
  color: var(--b3-encre);
  font-weight: 800;
}

/* Le curseur de prix (jQuery UI) vit dans la carte claire des filtres : rien
   à reprendre pour lui. Seule sa poignée, dessinée en jaune plein sur fond
   clair ailleurs dans ce fichier, garde un anneau d'encre pour se détacher —
   déjà le cas, non touché ici. */


/* ===== 07-panneaux.css =================================================== */

/* ===== 07-panneaux.css =================================================== */
/* --------------------------------------------------------------------------
   9quater. Actions flottantes — WhatsApp et retour en haut
   -------------------------------------------------------------------------- */
.b3-floating {
  position: fixed;
  right: var(--b3-space-sm);
  bottom: var(--b3-space-sm);
  z-index: 900;
  display: flex;
  flex-direction: column;
  gap: var(--b3-space-2xs);
}

.b3-floating__btn {
  display: grid;
  place-items: center;
  width: 52px;
  height: 52px;
  padding: 0;
  border: 0;
  border-radius: 50%;
  cursor: pointer;
  transition: transform var(--b3-dur-fast) var(--b3-ease),
              background-color var(--b3-dur-fast) var(--b3-ease);
}

.b3-floating__btn:hover {
  transform: translateY(-2px);
}

.b3-floating__btn[hidden] {
  display: none;
}

/* Vert officiel WhatsApp : c'est la couleur du service, pas celle de la
   marque — la reprendre en jaune rendrait le bouton méconnaissable. */
.b3-floating__btn--whatsapp {
  background-color: #25d366;
  color: #fff;
  text-decoration: none;
}

.b3-floating__btn--whatsapp:hover {
  background-color: #1da851;
  color: #fff;
}

/* Retour en haut : pastille jaune, flèche encre.
   La flèche était blanche, à 1,53:1 sur le jaune — sous le seuil de 3:1 exigé
   pour un élément graphique porteur de sens. En encre, elle atteint 12:1 et
   reste lisible en plein soleil. */
.b3-floating__btn--top {
  background-color: var(--b3-jaune);
  color: var(--b3-encre);
  border: 2px solid var(--b3-encre);
}

.b3-floating__btn--top:hover {
  background-color: var(--b3-jaune-fonce);
}

.b3-floating__btn--top svg {
  animation: b3-nudge-up 1.8s var(--b3-ease) infinite;
}

/* Bascule de langue : le drapeau occupe toute la pastille, cerclé d'encre
   comme les deux autres boutons. Le fond reste visible tant que le SVG ne
   couvre pas le cercle au pixel près. */
.b3-floating__btn--langue {
  padding: 0;
  overflow: hidden;
  background-color: var(--b3-papier);
  border: 2px solid var(--b3-encre);
  text-decoration: none;
}

.b3-floating__btn--langue:hover,
.b3-floating__btn--langue:focus-visible {
  text-decoration: none;
}

.b3-drapeau {
  display: block;
  width: 100%;
  height: 100%;
  border-radius: 50%;
  transition: transform var(--b3-dur-fast) var(--b3-ease);
}

.b3-floating__btn--langue:hover .b3-drapeau {
  transform: scale(1.06);
}

@media (max-width: 767px) {
.b3-floating {
    right: var(--b3-space-xs);
    bottom: var(--b3-space-xs);
  }

.b3-floating__btn {
    width: 48px;
    height: 48px;
  }
}

/* --------------------------------------------------------------------------
   9decies. Panneaux latéraux — menu, panier, connexion
   Éléments <dialog> natifs : empilement, touche Échap et confinement du focus
   sont pris en charge par le navigateur.
   -------------------------------------------------------------------------- */
.b3-panel {
  position: fixed;
  inset: 0;
  width: 100%;
  max-width: 100%;
  height: 100%;
  max-height: 100%;
  padding: 0;
  border: 0;
  background: transparent;
  overflow: hidden;
}

.b3-panel::backdrop {
  background-color: oklch(0.19 0.012 90 / 0.5);
  opacity: 0;
  transition: opacity var(--b3-dur-slow) var(--b3-ease);
}

.b3-panel[data-b3-open]::backdrop {
  opacity: 1;
}

.b3-panel__inner {
  position: absolute;
  top: 0;
  bottom: 0;
  display: flex;
  flex-direction: column;
  width: min(88vw, 400px);
  background-color: var(--b3-papier);
  transition: transform var(--b3-dur-slow) var(--b3-ease);
}

.b3-panel--left .b3-panel__inner {
  left: 0;
  border-radius: 0 var(--b3-radius-lg) var(--b3-radius-lg) 0;
  transform: translateX(-100%);
}

.b3-panel--right .b3-panel__inner {
  right: 0;
  border-radius: var(--b3-radius-lg) 0 0 var(--b3-radius-lg);
  transform: translateX(100%);
}

.b3-panel[data-b3-open] .b3-panel__inner {
  transform: translateX(0);
}

.b3-panel__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--b3-space-sm);
  padding: var(--b3-space-sm) var(--b3-space-md);
  background-color: var(--b3-jaune);
}

.b3-panel__title {
  font-size: 1rem;
  font-weight: 800;
  font-stretch: 85%;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--b3-encre);
}

.b3-panel__close {
  display: grid;
  place-items: center;
  width: 44px;
  height: 44px;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background-color: var(--b3-encre);
  color: var(--b3-papier);
  font-size: 1.5rem;
  line-height: 1;
  cursor: pointer;
}

.b3-panel__body {
  flex: 1 1 auto;
  padding: var(--b3-space-md);
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
}

.b3-panel__foot {
  flex: 0 0 auto;
  display: flex;
  gap: var(--b3-space-xs);
  padding: var(--b3-space-md);
  border-top: 1px solid var(--b3-trait);
}

.b3-panel__nav {
  margin: 0;
  padding: 0;
  list-style: none;
}

/* Le menu (panneau de gauche) reprend le filet gris générique du thème :
   des lignes plates, sans pictogramme, sans rien qui distingue un rayon
   d'un autre avant de lire le mot. Chaque rayon devient une carte — fond
   papier-2, coin arrondi de la charte — avec son pictogramme et un chevron
   de fin de ligne. Les autres panneaux (panier, compte, favoris) gardent le
   filet simple : ce ne sont pas des rayons à parcourir par la forme. */
#b3-panel-menu .b3-panel__nav li + li {
  margin-top: var(--b3-space-2xs);
}

#b3-panel-menu .b3-panel__nav a {
  display: flex;
  align-items: center;
  gap: 0.65em;
  min-height: 52px;
  padding: 0 var(--b3-space-sm);
  border-radius: var(--b3-radius);
  background-color: var(--b3-papier-2);
  color: var(--b3-encre);
  font-size: 1rem;
  font-weight: 800;
  letter-spacing: -0.005em;
  transition: background-color var(--b3-dur-fast) var(--b3-ease);
}

#b3-panel-menu .b3-panel__nav a:hover,
#b3-panel-menu .b3-panel__nav a:focus-visible,
#b3-panel-menu .b3-panel__nav a:active {
  background-color: var(--b3-jaune);
  color: var(--b3-encre);
  text-decoration: none;
}

#b3-panel-menu .b3-panel__pic {
  flex: none;
  width: 1.3em;
  font-size: 1.125rem;
  line-height: 1;
  text-align: center;
}

/* Chevron de fin de ligne : chaque entrée mène vers un rayon complet, le
   signe le dit avant le clic. */
#b3-panel-menu .b3-panel__nav a::after {
  content: "";
  flex: none;
  width: 0.5em;
  height: 0.5em;
  margin-left: auto;
  border-right: 2px solid currentColor;
  border-bottom: 2px solid currentColor;
  transform: rotate(-45deg);
}

.b3-panel__nav li + li {
  border-top: 1px solid var(--b3-trait);
}

.b3-panel__nav a {
  display: block;
  min-height: 44px;
  padding: var(--b3-space-xs) 0;
  color: var(--b3-encre);
  font-size: 1.0625rem;
  font-weight: 700;
  text-decoration: none;
}

.b3-panel__nav a:hover,
.b3-panel__nav a:focus {
  color: var(--b3-encre);
  text-decoration: underline;
  text-underline-offset: 4px;
}

.b3-panel__note,
.b3-panel__empty,
.b3-panel__hello {
  margin: var(--b3-space-md) 0 0;
  color: var(--b3-encre-douce);
  font-size: 0.9375rem;
  line-height: 1.5;
}

.b3-panel__cta {
  width: 100%;
}

.b3-panel__form {
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.b3-panel__form label {
  margin-top: var(--b3-space-2xs);
  font-size: 0.8125rem;
  font-weight: 700;
  color: var(--b3-encre);
}

.b3-panel__form input {
  min-height: 46px;
  padding: 0 var(--b3-space-sm);
  border: 1px solid var(--b3-trait-fort);
  border-radius: var(--b3-radius-sm);
  background-color: var(--b3-papier);
  color: var(--b3-encre);
  font-family: var(--b3-font);
  font-size: 1rem;
}

.b3-panel__form input:focus {
  border-color: var(--b3-encre);
  outline: 2px solid var(--b3-encre);
  outline-offset: 1px;
}

.b3-panel__aside {
  margin: var(--b3-space-xs) 0 0;
  font-size: 0.875rem;
}

.b3-panel__sep {
  display: flex;
  align-items: center;
  gap: var(--b3-space-xs);
  margin: var(--b3-space-md) 0;
  color: var(--b3-encre-douce);
  font-size: 0.8125rem;
}

.b3-panel__sep::before,
.b3-panel__sep::after {
  content: "";
  flex: 1 1 auto;
  height: 1px;
  background-color: var(--b3-trait);
}

@media (prefers-reduced-motion: reduce) {
.b3-panel__inner,
  .b3-panel::backdrop {
    transition: none;
  }

.b3-panel--left .b3-panel__inner,
  .b3-panel--right .b3-panel__inner {
    transform: translateX(0);
  }
}

.b3-suggest__item {
  list-style: none;
}

.b3-suggest {
  display: grid;
  grid-template-columns: 44px minmax(0, 1fr);
  align-items: center;
  gap: var(--b3-space-xs);
  min-height: 56px;
  padding: var(--b3-space-2xs);
  border-radius: var(--b3-radius-sm);
  color: var(--b3-encre);
  text-decoration: none;
}

/* jQuery UI applique sa propre classe d'état au survol et au clavier :
   les deux doivent se voir de la même façon. */
.ui-autocomplete .b3-suggest:hover,
.ui-autocomplete .ui-state-active .b3-suggest,
.ui-autocomplete .ui-menu-item-wrapper.ui-state-active,
.b3-suggest:focus {
  background-color: var(--b3-jaune);
  color: var(--b3-encre);
}

.b3-suggest__img {
  width: 44px;
  height: 44px;
  object-fit: contain;
  border-radius: var(--b3-radius-sm);
  background-color: var(--b3-papier-2);
  mix-blend-mode: multiply;
}

.b3-suggest__body {
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 0;
}

.b3-suggest__name {
  display: -webkit-box;
  -webkit-line-clamp: 2;
  line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
  font-size: 0.875rem;
  font-weight: 700;
  line-height: 1.25;
}

/* La portion saisie ressort sans changer la taille de la ligne. */
.b3-suggest__name mark {
  padding: 0 1px;
  background-color: transparent;
  color: inherit;
  font-weight: 900;
  text-decoration: underline;
  text-underline-offset: 2px;
}

.b3-suggest__price {
  color: var(--b3-encre-douce);
  font-size: 0.8125rem;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
}

.ui-autocomplete .b3-suggest:hover .b3-suggest__price,
.ui-autocomplete .ui-state-active .b3-suggest__price {
  color: var(--b3-encre);
}


/* --------------------------------------------------------------------------
   Invitation à se connecter — panneau des favoris

   Les favoris sont rattachés à un compte. Sans connexion, le panneau affichait
   un « Chargement… » qui n'aboutissait jamais : la requête part, le module
   répond une redirection, et le message reste. Il annonce désormais la
   condition et propose l'action, plutôt que de simuler une attente.
   -------------------------------------------------------------------------- */

.b3-panel__invite {
  display: flex;
  flex-direction: column;
  gap: var(--b3-space-2xs);
  padding: var(--b3-space-md) 0;
}

.b3-panel__invite-titre {
  margin: 0;
  font-size: 1.125rem;
  font-weight: 800;
  font-stretch: 90%;
  line-height: 1.2;
  color: var(--b3-encre);
}

.b3-panel__invite-texte {
  margin: 0;
  max-width: 34ch;
  font-size: 0.9375rem;
  line-height: 1.5;
  color: var(--b3-encre-douce);
}

/* Le second chemin — créer un compte — reste lisible sans concurrencer le
   bouton principal : un lien souligné, pas un second aplat. */
.b3-panel__lien {
  display: inline-block;
  margin-top: var(--b3-space-2xs);
  font-size: 0.9375rem;
  font-weight: 700;
  text-align: center;
  text-decoration: underline;
  text-underline-offset: 3px;
  color: var(--b3-encre);
}


/* ----- repris de 09-divers ----- */

@keyframes b3-nudge-up {
  0%, 55%, 100% { transform: translateY(2px); }
  25%           { transform: translateY(-3px); }
}


/* ----- repris de 09-divers ----- */

/* Le bouton injecté par jquery.ui.totop.js fait double emploi. */
#toTop,
#toTopHover {
  display: none !important;
}


/* ==========================================================================
   Confirmation d'ajout au panier

   Le moment où le client décide de continuer ou de commander. Le gabarit du
   module n'affichait qu'un titre et un nom : ni visuel, ni prix, ni total, ni
   action. Cette fenêtre porte donc les trois informations qui règlent la
   décision, et les deux chemins possibles.
   ========================================================================== */

#blockcart-modal.b3-cart-modal {
  position: fixed;
  inset: 0;
  z-index: 1200;
  display: grid;
  place-items: center;
  padding: var(--b3-space-sm);
  background-color: color-mix(in oklab, var(--b3-encre) 62%, transparent);
}

.b3-cart-modal__panneau {
  width: min(30rem, 100%);
  max-height: 90vh;
  overflow-y: auto;
  padding: var(--b3-space-md);
  border-radius: var(--b3-radius-lg);
  background-color: var(--b3-papier);
}

.b3-cart-modal__tete {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--b3-space-2xs);
  margin-bottom: var(--b3-space-md);
}

.b3-cart-modal__confirmation {
  display: flex;
  align-items: center;
  gap: 0.55em;
  margin: 0;
  font-size: 1.125rem;
  font-weight: 800;
  font-stretch: 90%;
  line-height: 1.2;
  color: var(--b3-encre);
}

/* La coche est dessinée, pas écrite : un caractère de police varie trop d'un
   système à l'autre pour porter une confirmation. */
.b3-cart-modal__coche {
  flex: none;
  display: grid;
  place-items: center;
  width: 1.8em;
  height: 1.8em;
  border-radius: 50%;
  background-color: var(--b3-jaune);
}

.b3-cart-modal__coche::before {
  content: "";
  width: 60%;
  height: 60%;
  background-color: var(--b3-encre);
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='3.2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M4 12.5l5.2 5.2L20 7'/%3E%3C/svg%3E") center / contain no-repeat;
  mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='3.2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M4 12.5l5.2 5.2L20 7'/%3E%3C/svg%3E") center / contain no-repeat;
}

.b3-cart-modal__fermer {
  flex: none;
  display: grid;
  place-items: center;
  width: 40px;
  height: 40px;
  border: 0;
  border-radius: 50%;
  background-color: transparent;
  font-size: 1.5rem;
  line-height: 1;
  color: var(--b3-encre);
  cursor: pointer;
}

.b3-cart-modal__fermer:hover {
  background-color: var(--b3-papier-2);
}

.b3-cart-modal__produit {
  display: grid;
  grid-template-columns: 88px minmax(0, 1fr);
  gap: var(--b3-space-sm);
  align-items: start;
  padding-bottom: var(--b3-space-sm);
}

.b3-cart-modal__visuel {
  width: 100%;
  height: auto;
  aspect-ratio: 3 / 4;
  object-fit: contain;
  border-radius: var(--b3-radius-sm);
  background-color: var(--b3-papier-2);
}

.b3-cart-modal__nom {
  margin: 0 0 0.25em;
  font-size: 1rem;
  font-weight: 700;
  line-height: 1.3;
  color: var(--b3-encre);
}

.b3-cart-modal__variante {
  margin: 0 0 0.4em;
  font-size: 0.8125rem;
  color: var(--b3-encre-douce);
}

.b3-cart-modal__ligne {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--b3-space-2xs);
  margin: 0;
}

.b3-cart-modal__qte {
  font-size: 0.875rem;
  color: var(--b3-encre-douce);
}

.b3-cart-modal__prix {
  font-size: 1.0625rem;
  font-weight: 800;
  font-variant-numeric: tabular-nums;
  color: var(--b3-encre);
}

.b3-cart-modal__recap {
  padding: var(--b3-space-sm) 0;
  border-top: 1.5px solid var(--b3-trait);
}

.b3-cart-modal__recap-ligne {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--b3-space-2xs);
  margin: 0 0 0.35em;
  font-size: 0.9375rem;
  color: var(--b3-encre-douce);
}

.b3-cart-modal__recap-ligne strong {
  font-variant-numeric: tabular-nums;
  color: var(--b3-encre);
}

.b3-cart-modal__recap-ligne--total {
  margin-top: 0.5em;
  padding-top: 0.5em;
  border-top: 1.5px solid var(--b3-trait);
  font-size: 1.0625rem;
  font-weight: 800;
  color: var(--b3-encre);
}

.b3-cart-modal__pied {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(11rem, 1fr));
  gap: var(--b3-space-2xs);
  padding-top: var(--b3-space-2xs);
}

.b3-cart-modal__pied .b3-btn {
  width: 100%;
  min-height: 48px;
  justify-content: center;
}

/* Sur un téléphone, la fenêtre se colle en bas : le pouce y atteint les deux
   actions sans traverser l'écran. */
@media (max-width: 575px) {
  #blockcart-modal.b3-cart-modal {
    place-items: end stretch;
    padding: 0;
  }

  .b3-cart-modal__panneau {
    width: 100%;
    max-height: 88vh;
    border-radius: var(--b3-radius-lg) var(--b3-radius-lg) 0 0;
  }
}


/* --------------------------------------------------------------------------
   Lignes du panneau panier
   -------------------------------------------------------------------------- */

.b3-cart-lignes {
  margin: 0;
  padding: 0;
  list-style: none;
}

.b3-cart-ligne {
  display: grid;
  grid-template-columns: 56px minmax(0, 1fr);
  gap: var(--b3-space-2xs);
  align-items: start;
  padding: var(--b3-space-2xs) 0;
  border-bottom: 1px solid var(--b3-trait);
}

.b3-cart-ligne__visuel {
  width: 100%;
  height: auto;
  aspect-ratio: 3 / 4;
  object-fit: contain;
  border-radius: var(--b3-radius-sm);
  background-color: var(--b3-papier-2);
}

.b3-cart-ligne__nom {
  display: block;
  font-size: 0.875rem;
  font-weight: 700;
  line-height: 1.3;
  color: var(--b3-encre);
  text-decoration: none;
}

.b3-cart-ligne__nom:hover {
  text-decoration: underline;
  text-underline-offset: 3px;
}

.b3-cart-ligne__variante {
  margin: 0.2em 0 0;
  font-size: 0.75rem;
  color: var(--b3-encre-douce);
}

.b3-cart-ligne__ligne {
  margin: 0.3em 0 0;
}

.b3-cart-ligne__qte {
  font-size: 0.875rem;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  color: var(--b3-encre);
}

.b3-cart-total {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--b3-space-2xs);
  margin: var(--b3-space-sm) 0 0;
  padding-top: var(--b3-space-sm);
  border-top: 2px solid var(--b3-encre);
  font-size: 1.0625rem;
  font-weight: 800;
  color: var(--b3-encre);
}

.b3-cart-total strong {
  font-variant-numeric: tabular-nums;
}


/* --------------------------------------------------------------------------
   Pilotage d'une ligne de panier

   Le panneau se contentait d'afficher : pour changer une quantité ou retirer
   une bouteille, il fallait ouvrir la page panier. Les liens de modification
   viennent du noyau — ils portent le jeton attendu par le contrôleur, qu'on ne
   saurait reconstruire ici — et provoquent un rechargement, comme sur la page
   panier native.
   -------------------------------------------------------------------------- */

.b3-cart-ligne__pilotage {
  display: flex;
  align-items: center;
  gap: var(--b3-space-2xs);
  margin-top: 0.4em;
}

.b3-cart-qte {
  display: inline-flex;
  align-items: center;
  flex: none;
  border: 1.5px solid var(--b3-encre);
  border-radius: var(--b3-radius-pill);
  overflow: hidden;
}

.b3-cart-qte__pas {
  display: grid;
  place-items: center;
  width: 30px;
  height: 30px;
  font-size: 1rem;
  font-weight: 800;
  line-height: 1;
  text-decoration: none;
  color: var(--b3-encre);
  transition: background-color var(--b3-dur-fast) var(--b3-ease);
}

.b3-cart-qte__pas:hover {
  background-color: var(--b3-encre);
  color: var(--b3-papier);
}

.b3-cart-qte__valeur {
  min-width: 26px;
  font-size: 0.875rem;
  font-weight: 800;
  font-variant-numeric: tabular-nums;
  text-align: center;
  color: var(--b3-encre);
}

.b3-cart-ligne__prix {
  font-size: 0.9375rem;
  font-weight: 800;
  font-variant-numeric: tabular-nums;
  color: var(--b3-encre);
}

/* Retirer est une action destructrice : elle reste discrète jusqu'au survol,
   où elle prend la couleur d'alerte. Elle ne doit pas se cliquer par mégarde
   en réglant une quantité juste à côté. */
/* Retirer est une action destructrice : elle s'annonce comme telle, en aplat
   d'alerte et par une corbeille — la croix pouvait se lire comme « fermer ».
   C'est le second des deux seuls emplois du rouge, avec les messages d'erreur. */
.b3-cart-ligne__retirer {
  display: grid;
  place-items: center;
  flex: none;
  width: 34px;
  height: 34px;
  margin-left: auto;
  border-radius: 50%;
  background-color: var(--b3-alerte);
  color: var(--b3-papier);
  transition:
    background-color var(--b3-dur-fast) var(--b3-ease),
    transform var(--b3-dur-fast) var(--b3-ease);
}

.b3-cart-ligne__retirer:hover {
  transform: scale(1.08);
}

.b3-cart-ligne__retirer::before {
  content: "";
  width: 15px;
  height: 15px;
  background-color: currentColor;
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M4 7h16M9 7V5h6v2M6 7l1 13h10l1-13'/%3E%3Cpath d='M10 11v6M14 11v6'/%3E%3C/svg%3E") center / contain no-repeat;
  mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M4 7h16M9 7V5h6v2M6 7l1 13h10l1-13'/%3E%3Cpath d='M10 11v6M14 11v6'/%3E%3C/svg%3E") center / contain no-repeat;
}

.b3-cart-ligne__retirer:hover {
  background-color: color-mix(in oklab, var(--b3-alerte) 82%, black);
}

/* La ligne s'efface avant que la page ne se recharge : sans cela, le clic
   reste sans effet visible pendant tout l'aller-retour serveur, et l'on
   doute d'avoir cliqué. */
.b3-cart-ligne.b3-part {
  overflow: hidden;
  animation: b3-retrait 320ms var(--b3-ease) forwards;
}

@keyframes b3-retrait {
  0%   { opacity: 1; transform: translateX(0); max-height: 160px; }
  40%  { opacity: 0; transform: translateX(28px); max-height: 160px; }
  100% { opacity: 0; transform: translateX(28px); max-height: 0; padding-block: 0; border-width: 0; }
}

@media (prefers-reduced-motion: reduce) {
  .b3-cart-ligne.b3-part {
    animation-duration: 1ms;
  }

  .b3-cart-ligne__retirer:hover {
    transform: none;
  }
}

/* Le visuel devient un bouton : cinquante-six pixels ne suffisent pas à
   vérifier qu'on a pris la bonne cuvée. */
.b3-cart-ligne__loupe {
  display: block;
  padding: 0;
  border: 0;
  border-radius: var(--b3-radius-sm);
  background: transparent;
  cursor: zoom-in;
}

.b3-cart-ligne__loupe:focus-visible {
  outline: 3px solid var(--b3-encre);
  outline-offset: 2px;
}

.b3-panel__foot .b3-panel__cta {
  flex: 1 1 auto;
  width: auto;
  justify-content: center;
}

/* « Commander » reprend `.b3-btn--ink` (encre pleine), le même traitement
   que partout où un bouton conclut une action — mais dans ce tiroir précis,
   posé sur fond clair juste après le panier, le jaune de la marque marque
   davantage la conclusion de l'achat que l'encre. */
#b3-panel-cart .b3-panel__foot .b3-panel__cta.b3-btn--ink {
  background-color: var(--b3-jaune);
  color: var(--b3-encre);
  font-weight: 800;
}

#b3-panel-cart .b3-panel__foot .b3-panel__cta.b3-btn--ink:hover,
#b3-panel-cart .b3-panel__foot .b3-panel__cta.b3-btn--ink:focus-visible {
  background-color: var(--b3-encre);
  color: var(--b3-papier);
}

/* --------------------------------------------------------------------------
   Visuel agrandi
   -------------------------------------------------------------------------- */

.b3-zoom {
  width: min(34rem, calc(100vw - 2rem));
  padding: var(--b3-space-sm);
  border: 0;
  border-radius: var(--b3-radius-lg);
  background-color: var(--b3-papier);
}

.b3-zoom::backdrop {
  background-color: color-mix(in oklab, var(--b3-encre) 74%, transparent);
}

.b3-zoom__image {
  display: block;
  width: 100%;
  height: auto;
  max-height: 74vh;
  object-fit: contain;
  border-radius: var(--b3-radius-sm);
  background-color: var(--b3-papier-2);
}

.b3-zoom__fermer {
  position: absolute;
  top: var(--b3-space-2xs);
  right: var(--b3-space-2xs);
  display: grid;
  place-items: center;
  width: 44px;
  height: 44px;
  border: 0;
  border-radius: 50%;
  background-color: var(--b3-papier);
  font-size: 1.6rem;
  line-height: 1;
  color: var(--b3-encre);
  cursor: pointer;
}

.b3-zoom__fermer:hover {
  background-color: var(--b3-encre);
  color: var(--b3-papier);
}


/* Sélecteur de langue du bandeau de tête (`ps_languageselector`, hook
   `displayNav1`). Deux commandes pour un même réglage se font concurrence, et
   celle du haut est la moins visible des deux : la pastille flottante suit le
   défilement, elle non. Masqué plutôt que débranché — le module reste en
   place pour le back-office. */
#header .language-selector-wrapper,
#header #_desktop_language_selector,
#header .language-selector {
  display: none;
}

/* --------------------------------------------------------------------------
   Invitation à créer un compte

   Ouverte au clic sur « favori » quand le visiteur n'est pas connecté. Le
   module envoyait sa requête, le serveur la refusait, et rien n'apparaissait :
   le geste restait sans réponse.

   C'est le moment où le visiteur manifeste une intention — il a repéré une
   bouteille. La fenêtre le dit et propose le compte, sans le forcer : le
   troisième bouton referme et laisse continuer.
   -------------------------------------------------------------------------- */

.b3-invite {
  width: min(94vw, 30rem);
  padding: 0;
  border: 1.5px solid var(--b3-encre);
  border-radius: var(--b3-radius-lg);
  background-color: var(--b3-papier);
  color: var(--b3-encre);
  box-shadow: 0 24px 60px oklch(0.19 0.012 90 / 0.28);
}

.b3-invite::backdrop {
  background-color: color-mix(in oklab, var(--b3-encre) 46%, transparent);
  backdrop-filter: blur(3px);
}

.b3-invite__corps {
  display: grid;
  justify-items: center;
  gap: var(--b3-space-sm);
  padding: var(--b3-space-xl) var(--b3-space-lg) var(--b3-space-lg);
  text-align: center;
}

/* Le cœur reprend le rose des vignettes : c'est le même geste, il doit porter
   le même signe. C'est le seul écart assumé à la palette. */
.b3-invite__coeur {
  display: grid;
  place-items: center;
  width: 58px;
  height: 58px;
  border-radius: 50%;
  background-color: #e8467c;
  color: var(--b3-papier);
}

.b3-invite__titre {
  margin: 0;
  font-size: clamp(1.25rem, 3.4vw, 1.625rem);
  font-weight: 800;
  font-stretch: 84%;
  letter-spacing: -0.01em;
  line-height: 1.1;
}

.b3-invite__texte {
  max-width: 34ch;
  margin: 0;
  font-size: 0.9375rem;
  line-height: 1.5;
  color: var(--b3-encre-douce);
}

.b3-invite__actions {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: var(--b3-space-2xs);
  width: 100%;
  margin-top: var(--b3-space-2xs);
}

/* La sortie n'est pas une croix perdue dans un angle : elle est nommée, et
   dit ce qu'elle fait. Un visiteur qui refuse doit pouvoir refuser vite. */
.b3-invite__fermer {
  margin-top: var(--b3-space-2xs);
  padding: var(--b3-space-3xs) var(--b3-space-2xs);
  border: 0;
  background: none;
  font-family: var(--b3-font);
  font-size: 0.8125rem;
  font-weight: 700;
  text-decoration: underline;
  text-underline-offset: 3px;
  color: var(--b3-encre-douce);
  cursor: pointer;
}

.b3-invite__fermer:hover {
  color: var(--b3-encre);
}

@media (max-width: 479px) {
  .b3-invite__actions .b3-btn {
    width: 100%;
  }
}

/* --------------------------------------------------------------------------
   Sélecteur de langue — quatre langues

   Le bouton garde sa place dans la colonne flottante ; la liste se déplie
   au-dessus, alignée sur son bord droit. Elle ne descend pas : elle est déjà
   au bas de l'écran.
   -------------------------------------------------------------------------- */

.b3-langues {
  position: relative;
  display: flex;
}

.b3-langues__liste {
  position: absolute;
  right: 0;
  bottom: calc(100% + var(--b3-space-2xs));
  z-index: 2;
  min-width: 12rem;
  margin: 0;
  padding: var(--b3-space-3xs);
  border: 1.5px solid var(--b3-encre);
  border-radius: var(--b3-radius);
  background-color: var(--b3-papier);
  box-shadow: 0 16px 36px oklch(0.19 0.012 90 / 0.22);
  list-style: none;
}

.b3-langues__liste[hidden] {
  display: none;
}

.b3-langues__lien {
  display: flex;
  align-items: center;
  gap: var(--b3-space-2xs);
  padding: var(--b3-space-3xs) var(--b3-space-2xs);
  border-radius: var(--b3-radius-sm);
  font-family: var(--b3-font);
  font-size: 0.875rem;
  font-weight: 800;
  text-decoration: none;
  color: var(--b3-encre);
  transition: background-color var(--b3-dur-fast) var(--b3-ease);
}

.b3-langues__lien:hover,
.b3-langues__lien:focus-visible {
  background-color: var(--b3-jaune);
  color: var(--b3-encre);
  text-decoration: none;
}

/* Dans la liste, le drapeau redevient une vignette : il accompagne un mot, il
   ne le remplace pas. */
.b3-langues__lien .b3-drapeau {
  flex: none;
  width: 22px;
  height: 22px;
  border: 1.5px solid var(--b3-encre);
}


/* --------------------------------------------------------------------------
   La fenêtre de confirmation, centrée partout

   Le module appelle `$('#blockcart-modal').modal('show')`. Bootstrap pose
   alors `display: block` en style en ligne, ce qui l'emporte sur toute règle
   d'auteur : notre grille centrée était défaite au moment précis où la
   fenêtre s'ouvrait, et le panneau retombait en haut à gauche.

   `!important` est ici le seul recours — il ne contredit pas une feuille de
   styles, il reprend un attribut posé par un script.
   -------------------------------------------------------------------------- */

#blockcart-modal.b3-cart-modal {
  display: grid !important;
  place-items: center !important;
  padding: var(--b3-space-sm);
}

/* Fermeture : le `!important` ci-dessus, posé pour tenir tête à Bootstrap à
   l'ouverture, tenait aussi tête à la fermeture — `style.display = 'none'`
   posé en JS perdait contre lui, la croix ne faisait plus rien. La classe
   ajoutée par `fermer()` (voir 3b.js) porte une sélectivité supérieure — un
   id, deux classes — pour regagner la priorité sans toucher à la règle
   d'ouverture, qui reste nécessaire face à Bootstrap. */
#blockcart-modal.b3-cart-modal.b3-cart-modal--fermee {
  display: none !important;
}

/* Le panneau ne se colle plus en bas sur téléphone. La proximité du pouce ne
   valait pas la confusion : une confirmation qui apparaît au centre se lit
   comme une réponse à l'action, une qui monte du bas se lit comme un tiroir. */
@media (max-width: 575px) {
  #blockcart-modal.b3-cart-modal {
    place-items: center !important;
    padding: var(--b3-space-sm);
  }

  .b3-cart-modal__panneau {
    width: min(30rem, 100%);
    max-height: 84vh;
    border-radius: var(--b3-radius-lg);
  }
}

/* « Voir mon panier » passe au jaune, texte encre : c'est le chemin que la
   maison propose, il doit se voir avant « continuer mes achats ». */
.b3-cart-modal__pied .b3-cart-modal__commander,
.b3-cart-modal__pied .b3-btn.b3-cart-modal__commander {
  background-color: var(--b3-jaune);
  border-color: var(--b3-jaune);
  color: var(--b3-encre);
  font-weight: 800;
}

.b3-cart-modal__pied .b3-cart-modal__commander:hover,
.b3-cart-modal__pied .b3-cart-modal__commander:focus-visible {
  background-color: color-mix(in oklab, var(--b3-jaune) 88%, var(--b3-encre));
  border-color: color-mix(in oklab, var(--b3-jaune) 88%, var(--b3-encre));
  color: var(--b3-encre);
}


/* --------------------------------------------------------------------------
   Les suggestions de recherche, sur téléphone

   La vignette faisait 44 px — la taille d'une icône, pas celle d'une bouteille
   qu'on reconnaît. Or c'est elle qui permet d'identifier un vin plus vite que
   son nom, surtout quand ce nom est un libellé de caisse en capitales.

   jQuery UI pose ses propres règles sur `.ui-menu-item` et sur les liens
   qu'il y place ; elles suffisent à défaire une grille d'auteur. D'où la
   spécificité renforcée ici, et non un `!important` de plus.
   -------------------------------------------------------------------------- */

.ui-autocomplete .b3-suggest__item .b3-suggest,
#header .ui-autocomplete .b3-suggest {
  display: grid;
  grid-template-columns: 64px minmax(0, 1fr);
  align-items: center;
  gap: var(--b3-space-sm);
  min-height: 72px;
  padding: var(--b3-space-2xs) var(--b3-space-xs);
  text-align: left;
}

.ui-autocomplete .b3-suggest .b3-suggest__img,
#header .ui-autocomplete .b3-suggest__img {
  width: 64px;
  height: 64px;
  object-fit: contain;
  padding: 4px;
}

.ui-autocomplete .b3-suggest .b3-suggest__body,
#header .ui-autocomplete .b3-suggest__body {
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 0;
}

/* Le libellé du catalogue est en capitales avec ses doubles apostrophes. On ne
   peut pas le réécrire depuis la feuille de styles, mais on peut cesser de
   l'aggraver : casse normale, deux lignes au plus, coupure propre. Le poids
   descend de 800 à 700 — des capitales en très gras se lisent comme un cri. */
.ui-autocomplete .b3-suggest .b3-suggest__name,
#header .ui-autocomplete .b3-suggest__name {
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
  font-size: 0.8125rem;
  font-weight: 700;
  letter-spacing: 0;
  line-height: 1.3;
  text-transform: none;
  word-break: normal;
  overflow-wrap: anywhere;
}

/* Le prix se détache : c'est la seconde information qu'on cherche. */
.ui-autocomplete .b3-suggest .b3-suggest__price,
#header .ui-autocomplete .b3-suggest__price {
  font-size: 0.9375rem;
  font-weight: 800;
  font-variant-numeric: tabular-nums;
  letter-spacing: 0;
  text-transform: none;
}

@media (max-width: 767px) {
  /* Le panneau descend jusqu'au bas de l'écran plutôt que de s'arrêter à
     60 % : sur un téléphone, une liste tronquée à trois résultats donne
     l'impression qu'il n'y en a pas d'autres. */
  .ui-autocomplete.searchbar-autocomplete,
  #header .ui-autocomplete {
    max-height: min(72vh, 560px);
  }

  .ui-autocomplete .b3-suggest__item + .b3-suggest__item {
    border-top: 1px solid var(--b3-trait);
  }
}


/* --------------------------------------------------------------------------
   La page panier

   « Continuer mes achats » y était un aplat rouge sang, hérité du thème : sur
   une page où le rouge ne sert nulle part ailleurs, il se lisait comme une
   alerte alors qu'il propose la sortie la plus banale. Il passe en bouton
   secondaire — cerné, sur papier — et laisse le jaune à « Commander », qui est
   la vraie décision.
   -------------------------------------------------------------------------- */

#js-checkout-summary ~ .cart-detailed-actions a,
.cart-grid-body a.continue,
.cart-grid-body .label-continue,
a.continue.btn {
  display: inline-flex;
  align-items: center;
  gap: 0.5em;
  min-height: 48px;
  padding: 0 var(--b3-space-lg);
  border: 2px solid var(--b3-encre);
  border-radius: var(--b3-radius-pill);
  background-color: transparent;
  color: var(--b3-encre);
  font-size: 0.875rem;
  font-weight: 800;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  text-decoration: none;
  transition: background-color var(--b3-dur-fast) var(--b3-ease),
              color var(--b3-dur-fast) var(--b3-ease);
}

a.continue.btn:hover,
.cart-grid-body a.continue:hover {
  background-color: var(--b3-encre);
  color: var(--b3-papier);
}

/* Les réglettes du panier : une seule, celle de la maison. Celle de TouchSpin
   est masquée par le script, mais une règle de repli évite qu'elle
   réapparaisse le temps d'un chargement. */
.cart-item .bootstrap-touchspin,
.cart-item .input-group-btn,
.cart-item input.js-cart-line-product-quantity {
  display: none !important;
}

.cart-item .b3-qty--panier {
  display: inline-flex !important;
}

/* La vignette du panier respire : elle était collée au bord de sa cellule. */
.cart-item .product-line-grid-left img,
.cart-item .product-image img {
  border-radius: var(--b3-radius-sm);
  background-color: var(--b3-papier-2);
}


/* ===== 08-pied.css ======================================================= */

/* ===== 08-pied.css ======================================================= */
/* --------------------------------------------------------------------------
   8. Pied de page
   Fond encre, titres en jaune (12.07:1, conforme AA), liens en papier.
   -------------------------------------------------------------------------- */
#footer .footer-container,
.page-footer #footer {
  background-color: var(--b3-encre);
  color: var(--b3-papier);
}

#footer .column_wrap_title,
#footer .footer-container .h3,
#footer .footer-container h3 {
  color: var(--b3-jaune);
  font-size: 0.875rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.14em;
}

#footer .footer-container a,
#footer .footer-container li a {
  color: var(--b3-papier);
  text-decoration: none;
}

#footer .footer-container a:hover,
#footer .footer-container a:focus {
  color: var(--b3-jaune);
  text-decoration: underline;
  text-underline-offset: 3px;
}

/* La mention sanitaire est une obligation légale : elle se lit. */
#footer .b3-legal,
#footer .footer-container .b3-legal {
  color: var(--b3-papier);
  font-size: 0.8125rem;
}

#footer .footer-container a,
#footer .footer-container li a {
  display: inline-block;
  padding: 9px 0;
}

/* 9q.2 — Contraste du pied de page.
   Le thème posait un gris moyen sur l'aplat encre : les coordonnées de la
   maison et la mention sanitaire passaient sous le seuil AA. */
#footer,
#footer .footer-container,
#footer .footer-container p,
#footer .footer-container span,
#footer .footer-container li,
#footer .footer-container address,
#footer .footer-container strong {
  color: var(--b3-papier);
}

#footer .footer-container .text-muted,
#footer .footer-container small {
  /* 6,9:1 sur l'encre : lisible tout en restant secondaire. */
  color: oklch(0.82 0.010 90);
}

/* --------------------------------------------------------------------------
   9octies. Pied de page — reprise mobile
   -------------------------------------------------------------------------- */
/* Le tampon débordait de son cadre et se retrouvait tronqué. */
#footer .footer-container img,
#footer img.logo {
  width: 84px;
  height: 84px;
  max-width: 84px;
  aspect-ratio: 1;
  object-fit: cover;
  object-position: left center;
  border-radius: 50%;
}

@media (max-width: 767px) {
/* Les coordonnées héritaient d'une taille de titre : trois mots par ligne. */
#footer .footer-container,
  #footer .footer-container p,
  #footer .footer-container span,
  #footer .footer-container strong {
    font-size: 0.9375rem;
    line-height: 1.5;
    letter-spacing: normal;
  }

#footer .footer-container .column_wrap_title,
  #footer .footer-container .h3 {
    font-size: 0.8125rem;
  }
}

main > footer#footer { order: 3; }


/* --------------------------------------------------------------------------
   Tampon en double dans le pied de page

   Le même identifiant, `#footerbottomleft2-text`, est rendu deux fois : une
   fois dans `.footerbottomleft-outer`, une fois dans
   `.footerbottom-text-inner`. Deux blocs différents servent le même contenu,
   d'où deux tampons superposés dans la colonne de gauche.

   Le second est masqué. Un identifiant dupliqué reste un défaut de gabarit
   côté module : à corriger en back-office si les deux blocs y sont
   configurés séparément.
   -------------------------------------------------------------------------- */

.footerbottom-text-inner #footerbottomleft2-text {
  display: none;
}

/* --------------------------------------------------------------------------
   Moyens de paiement acceptés

   Ils répondent à la question qu'on se pose avant de remplir un panier, pas
   après. Les marques sont posées sur des cartes de papier : les logos des
   réseaux sont dessinés pour du blanc, et perdent leur lisibilité sur l'encre
   du pied de page.
   -------------------------------------------------------------------------- */

.b3-contact {
  width: 100%;
  text-align: center;
}

.b3-contact__titre {
  margin: 0 0 var(--b3-space-sm);
  font-size: 0.6875rem;
  font-weight: 800;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--b3-jaune);
}

.b3-contact__liste {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: var(--b3-space-sm);
  margin: 0;
  padding: 0;
  list-style: none;
}

.b3-contact__liste a {
  color: var(--b3-papier);
  font-size: 0.9375rem;
  font-weight: 700;
  text-decoration: none;
}

.b3-contact__liste a:hover,
.b3-contact__liste a:focus-visible {
  color: var(--b3-jaune);
  text-decoration: underline;
  text-underline-offset: 3px;
}

.b3-paiements {
  width: 100%;
  margin-top: var(--b3-space-lg);
  padding-top: var(--b3-space-md);
  border-top: 1px solid color-mix(in oklab, var(--b3-papier) 22%, transparent);
  text-align: center;
}

.b3-paiements__titre {
  margin: 0 0 var(--b3-space-sm);
  font-size: 0.6875rem;
  font-weight: 800;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--b3-jaune);
}

.b3-paiements__liste {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: var(--b3-space-2xs);
  margin: 0;
  padding: 0;
  list-style: none;
}

.b3-paiement {
  display: flex;
  align-items: center;
  gap: 0.45em;
  margin: 0;
}

.b3-paiement svg {
  display: block;
  border-radius: 4px;
}

/* Virement et chèque n'ont pas de marque : un pictogramme et le mot suffisent,
   sur une pastille qui les met au même rang que les cartes. */
.b3-paiement--texte {
  min-height: 32px;
  padding: 0 var(--b3-space-2xs);
  border: 1px solid color-mix(in oklab, var(--b3-papier) 30%, transparent);
  border-radius: 4px;
  font-size: 0.75rem;
  font-weight: 700;
  color: var(--b3-papier);
}

.b3-paiements__mention {
  max-width: 60ch;
  margin: var(--b3-space-sm) auto 0;
  font-size: 0.75rem;
  line-height: 1.45;
  color: color-mix(in oklab, var(--b3-papier) 68%, transparent);
}

/* --------------------------------------------------------------------------
   Langues servies

   Quatre langues, c'est un argument qu'aucun caviste breton ne peut opposer.
   La mention est en clair — les moteurs génératifs lisent le texte visible
   autant que le balisage — et chaque langue est un lien : elle sert le
   lecteur avant de servir le moteur, sinon elle n'est qu'un mot-clé déguisé.
   -------------------------------------------------------------------------- */

.b3-langues-pied {
  width: 100%;
  margin-top: var(--b3-space-md);
  padding-top: var(--b3-space-md);
  border-top: 1px solid color-mix(in oklab, var(--b3-papier) 18%, transparent);
  text-align: center;
}

.b3-langues-pied__titre {
  margin: 0 0 var(--b3-space-2xs);
  font-size: 0.6875rem;
  font-weight: 800;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--b3-jaune);
}

.b3-langues-pied__liste {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: var(--b3-space-2xs);
  margin: 0;
  padding: 0;
  list-style: none;
}

/* Sans contour : le cadre gris cerclait un drapeau plus petit que lui, et deux
   cercles concentriques de tailles différentes se lisent comme un défaut de
   gabarit. Le drapeau se suffit, le mot le nomme. */
.b3-langues-pied__liste a {
  display: inline-flex;
  align-items: center;
  gap: 0.5em;
  min-height: 36px;
  padding: 0 var(--b3-space-2xs);
  border: 0;
  border-radius: var(--b3-radius-pill);
  font-size: 0.875rem;
  font-weight: 700;
  text-decoration: none;
  color: var(--b3-papier);
  transition: background-color var(--b3-dur-fast) var(--b3-ease),
              color var(--b3-dur-fast) var(--b3-ease);
}

.b3-langues-pied__liste a:hover {
  background-color: var(--b3-jaune);
  color: var(--b3-encre);
  text-decoration: none;
}

/* Le drapeau double de taille et redevient vraiment rond : `border-radius`
   seul ne suffit pas quand le SVG porte déjà son propre découpage — c'est le
   `clipPath` qui donne le cercle, et il faut que la boîte soit carrée pour
   qu'il en soit un. */
.b3-langues-pied__liste .b3-drapeau {
  flex: none;
  width: 28px;
  height: 28px;
  aspect-ratio: 1;
  border-radius: 50%;
  box-shadow: 0 0 0 1.5px color-mix(in oklab, var(--b3-papier) 30%, transparent);
}


/* --------------------------------------------------------------------------
   Corrections de pied de page

   Deux défauts que la capture rend évidents : un vide de deux cents pixels
   entre les colonnes de liens et le premier filet, et des pastilles de langue
   devenues des cercles.
   -------------------------------------------------------------------------- */

/* Le vide vient du thème acheté : ses colonnes portent une hauteur minimale
   calculée pour cinq entrées, alors que la plus longue en compte quatre. */
#footer .footer-container .links,
#footer .block_newsletter + div,
#footer .footer-container > .container > .row {
  min-height: 0;
}

#footer .footer-container {
  padding-bottom: var(--b3-space-md);
}

/* La pastille de langue passait en deux lignes — drapeau au-dessus, mot en
   dessous — et l'arrondi en pilule d'une boîte aussi haute que large donne un
   cercle, dans lequel le mot débordait. La ligne ne se coupe plus. */
.b3-langues-pied__liste a {
  flex-wrap: nowrap;
  white-space: nowrap;
}

.b3-langues-pied__liste span {
  display: inline-block;
}

/* Les deux filets consécutifs — celui du thème, celui des moyens de paiement —
   se lisaient comme une erreur de gabarit. Un seul suffit. */
.b3-paiements {
  margin-top: var(--b3-space-sm);
  padding-top: var(--b3-space-md);
}

/* Mention IA : discrète (petite, sous la mention sanitaire) mais jamais
   illisible — même logique que la mention sanitaire elle-même dans
   DESIGN.md, du texte papier plein, pas du gris effacé sur l'encre. */
.b3-mention-ia {
  margin: var(--b3-space-3xs) 0 0;
  font-size: 0.75rem;
  color: color-mix(in oklab, var(--b3-papier) 70%, transparent);
}


/* ===== 10-comptes.css ==================================================== */

/* ==========================================================================
   Pages de compte — connexion, inscription, identité, adresses, mot de passe

   Ces écrans étaient restés au gabarit du thème : champs sans contour ni
   arrondi, libellés en colonne de gauche façon formulaire administratif,
   bouton « Afficher » en gris #999 hors charte, et titre de page en graisse
   400 alors que l'échelle réserve cette graisse au texte courant.

   Le formulaire passe en colonne unique. Un label au-dessus de son champ se
   lit sans balayer la ligne, tient sur un téléphone sans reflow, et raccourcit
   la distance entre l'intitulé et la saisie — c'est la disposition la plus
   sûre pour un tunnel de compte.
   ========================================================================== */

body.page-authentication #content,
body.page-registration #content,
body.page-password #content,
body.page-identity #content,
body.page-addresses #content,
body.page-address #content {
  max-width: 34rem;
  margin-inline: auto;
  padding: var(--b3-space-lg) var(--b3-space-md) var(--b3-space-xl);
  background-color: var(--b3-papier);
  border-radius: var(--b3-radius-lg);
}

/* Titre de page : l'échelle réserve la graisse 400 au texte courant. */
body.page-authentication .page-header h1,
body.page-registration .page-header h1,
body.page-password .page-header h1,
body.page-identity .page-header h1,
body.page-addresses .page-header h1,
body.page-address .page-header h1 {
  max-width: 34rem;
  margin-inline: auto;
  font-size: clamp(1.75rem, 3.5vw, 2.5rem);
  font-weight: 800;
  font-stretch: 75%;
  line-height: 1.05;
  letter-spacing: -0.015em;
  color: var(--b3-encre);
  text-wrap: balance;
}

/* --------------------------------------------------------------------------
   Le formulaire en colonne unique. Les classes de grille du thème
   (`col-md-3`, `col-md-6`) sont neutralisées plutôt que retirées du gabarit :
   ces écrans sont rendus par le noyau, pas par un template du thème.
   -------------------------------------------------------------------------- */

body.page-authentication .form-group.row,
body.page-registration .form-group.row,
body.page-password .form-group.row,
body.page-identity .form-group.row,
body.page-address .form-group.row {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: var(--b3-space-3xs);
  margin: 0 0 var(--b3-space-sm);
}

body.page-authentication .form-group.row > [class*="col-md"],
body.page-registration .form-group.row > [class*="col-md"],
body.page-password .form-group.row > [class*="col-md"],
body.page-identity .form-group.row > [class*="col-md"],
body.page-address .form-group.row > [class*="col-md"] {
  width: 100%;
  max-width: none;
  flex: none;
  padding: 0;
}

body.page-authentication .form-control-label,
body.page-registration .form-control-label,
body.page-password .form-control-label,
body.page-identity .form-control-label,
body.page-address .form-control-label {
  justify-content: flex-start;
  padding: 0;
  font-size: 0.8125rem;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  text-align: left;
  color: var(--b3-encre);
}

/* Commentaire d'aide : il occupait une colonne de 226 px à droite du champ,
   où il n'était jamais lu. Il passe sous le champ, à sa vraie place. */
body.page-authentication .form-control-comment,
body.page-registration .form-control-comment,
body.page-password .form-control-comment,
body.page-identity .form-control-comment,
body.page-address .form-control-comment {
  padding: 0;
  font-size: 0.8125rem;
  line-height: 1.4;
  color: var(--b3-encre-douce);
}

/* --------------------------------------------------------------------------
   Champs
   -------------------------------------------------------------------------- */

body.page-authentication .form-control,
body.page-registration .form-control,
body.page-password .form-control,
body.page-identity .form-control,
body.page-address .form-control,
body.page-authentication select.form-control,
body.page-registration select.form-control {
  width: 100%;
  min-height: 48px;
  padding: 0 var(--b3-space-sm);
  border: 1.5px solid var(--b3-trait-fort);
  border-radius: var(--b3-radius-sm);
  background-color: var(--b3-papier);
  box-shadow: none;
  font-family: var(--b3-font);
  font-size: 1rem;
  color: var(--b3-encre);
  transition: border-color var(--b3-dur-fast) var(--b3-ease);
}

body.page-authentication .form-control:hover,
body.page-registration .form-control:hover,
body.page-identity .form-control:hover {
  border-color: var(--b3-encre);
}

/* Le focus ne se signale jamais par la seule couleur : un contour franc, qui
   ne dépend ni de la teinte ni du contraste du champ. */
body.page-authentication .form-control:focus,
body.page-registration .form-control:focus,
body.page-password .form-control:focus,
body.page-identity .form-control:focus,
body.page-address .form-control:focus {
  border-color: var(--b3-encre);
  outline: 3px solid var(--b3-encre);
  outline-offset: 2px;
}

/* Le groupe mot de passe : le champ et son bouton forment une seule pièce. */
body.page-authentication .input-group,
body.page-registration .input-group,
body.page-password .input-group {
  display: flex;
  align-items: stretch;
  gap: var(--b3-space-3xs);
}

body.page-authentication .input-group .form-control,
body.page-registration .input-group .form-control,
body.page-password .input-group .form-control {
  flex: 1 1 auto;
  min-width: 0;
}

/* « Afficher » : gris #999 sur blanc, soit 2.8:1 — sous le seuil. Il devient
   un bouton secondaire de la charte. */
body.page-authentication .input-group-btn > .btn,
body.page-registration .input-group-btn > .btn,
body.page-password .input-group-btn > .btn {
  min-height: 48px;
  padding: 0 var(--b3-space-sm);
  border: 1.5px solid var(--b3-encre);
  border-radius: var(--b3-radius-sm);
  background-color: transparent;
  box-shadow: none;
  font-size: 0.8125rem;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--b3-encre);
}

body.page-authentication .input-group-btn > .btn:hover,
body.page-registration .input-group-btn > .btn:hover,
body.page-password .input-group-btn > .btn:hover {
  background-color: var(--b3-encre);
  color: var(--b3-papier);
}

/* --------------------------------------------------------------------------
   Pied de formulaire et liens
   -------------------------------------------------------------------------- */

body.page-authentication .form-footer,
body.page-registration .form-footer,
body.page-password .form-footer,
body.page-identity .form-footer {
  margin-top: var(--b3-space-md);
  padding: 0;
  text-align: left;
}

body.page-authentication .form-footer .btn-primary,
body.page-registration .form-footer .btn-primary,
body.page-password .form-footer .btn-primary,
body.page-identity .form-footer .btn-primary {
  width: 100%;
  min-height: 52px;
  border: 0;
  border-radius: var(--b3-radius-pill);
  background-color: var(--b3-jaune);
  font-size: 0.9375rem;
  font-weight: 800;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--b3-encre);
}

body.page-authentication .form-footer .btn-primary:hover,
body.page-registration .form-footer .btn-primary:hover {
  background-color: var(--b3-jaune-fonce);
}

body.page-authentication .forgot-password,
body.page-registration .forgot-password {
  margin: var(--b3-space-2xs) 0 0;
  padding: 0;
  font-size: 0.9375rem;
}

body.page-authentication .forgot-password a,
body.page-registration .forgot-password a,
body.page-authentication .no-account a {
  color: var(--b3-encre);
  font-weight: 700;
  text-decoration: underline;
  text-underline-offset: 3px;
}

/* Bascule connexion / création de compte : c'est le second chemin de la page,
   il mérite d'être visible sans concurrencer le bouton principal. */
body.page-authentication .no-account,
body.page-registration .no-account {
  margin-top: var(--b3-space-md);
  padding-top: var(--b3-space-md);
  border-top: 1px solid var(--b3-trait);
  font-size: 0.9375rem;
}


/* --------------------------------------------------------------------------
   Pleine largeur sur les écrans de compte

   Ces pages héritaient de `layout-left-column` : une colonne de 325 px y
   répétait l'arborescence des rayons, à côté d'un formulaire de connexion. Le
   catalogue n'a rien à faire dans un tunnel de compte — il n'y a rien à
   parcourir à ce moment-là, et la colonne repousse le formulaire hors de l'axe
   de lecture. Le réglage est fait ici plutôt que dans theme.yml pour ne pas
   réappliquer la configuration complète du thème pour deux gabarits.
   -------------------------------------------------------------------------- */

body.page-authentication #left-column,
body.page-registration #left-column,
body.page-password #left-column,
body.page-identity #left-column,
body.page-addresses #left-column,
body.page-address #left-column {
  display: none;
}

body.page-authentication #content-wrapper,
body.page-registration #content-wrapper,
body.page-password #content-wrapper,
body.page-identity #content-wrapper,
body.page-addresses #content-wrapper,
body.page-address #content-wrapper {
  width: 100%;
  max-width: none;
  flex: 1 1 100%;
  padding: 0;
}


/* ===== 11-fil-ariane.css ================================================= */

/* ==========================================================================
   Fil d'Ariane et en-tête de page intérieure

   Le thème coiffait chaque page intérieure d'un bandeau photo de 245 px — un
   cliché de bouchons en gros plan, servi en image de fond. Il ne dit rien du
   contenu de la page, repousse le titre sous la ligne de flottaison, et
   contredit le parti pris du système : deux encres sur papier, aucune
   photographie décorative.

   L'aplat papier le remplace. Le fil d'Ariane, lui, reste : c'est la seule
   information réellement portée par ce bandeau.
   ========================================================================== */

.breadcumb_outer {
  min-height: 0;
  padding: var(--b3-space-sm) 0;
  background-image: none;
  background-color: var(--b3-papier-2);
}

.breadcumb_outer .breadcrumb,
.breadcumb_outer nav {
  padding: 0;
  background: transparent;
}

.breadcumb_outer a,
.breadcumb_outer span {
  font-size: 0.8125rem;
  font-weight: 600;
  letter-spacing: 0.04em;
  color: var(--b3-encre);
}

.breadcumb_outer a {
  text-decoration: underline;
  text-underline-offset: 3px;
}

/* La position courante ne se clique pas : elle se distingue par la graisse,
   jamais par la seule couleur. */
.breadcumb_outer li:last-child span,
.breadcumb_outer li[aria-current] span {
  font-weight: 800;
  text-decoration: none;
}


/* ===== 12-pages.css ====================================================== */

/* ==========================================================================
   Pages intérieures — traitement commun

   Panier, contact, magasins, pages CMS : ces écrans n'avaient jamais été
   repris. Ils gardaient le titre de page en graisse 400, des champs sans
   contour, et par endroits le rouge du thème acheté — que DESIGN.md range
   parmi les interdits, le rouge n'appartenant pas à la marque.
   ========================================================================== */

/* --------------------------------------------------------------------------
   Titre de page. L'échelle réserve la graisse 400 au texte courant : un titre
   de page à 22 px en graisse normale ne se distinguait pas d'un paragraphe.
   -------------------------------------------------------------------------- */

/* Le panier ne coiffe pas son titre d'un `.page-header` : il le pose dans
   `.cart-container > .card-block`. Le sélecteur doit couvrir les deux, sans
   quoi la page garde un titre en graisse normale. */
body.page-cart .page-header h1,
body.page-cart .cart-container h1,
body.page-cart #content h1,
body.page-contact .page-header h1,
body.page-stores .page-header h1,
body.page-cms .page-header h1,
body.page-sitemap .page-header h1,
body.page-order-confirmation .page-header h1,
body.page-my-account .page-header h1,
body.page-history .page-header h1,
body.page-order-detail .page-header h1 {
  font-size: clamp(1.75rem, 3.5vw, 2.5rem);
  font-weight: 800;
  font-stretch: 75%;
  line-height: 1.05;
  letter-spacing: -0.015em;
  color: var(--b3-encre);
  text-wrap: balance;
}

/* La demande de facture reste rare : un simple renvoi au contact, pas un
   champ dans le tunnel. Posé juste sous le titre, avant même le rappel
   d'email, au moment où la question se pose le plus naturellement. */
body.page-order-confirmation .b3-confirmation-facture {
  margin: var(--b3-space-2xs) 0 var(--b3-space-md);
  color: var(--b3-encre-douce);
  font-size: 0.9375rem;
}

/* --------------------------------------------------------------------------
   Le catalogue reste dans les pages de catalogue

   La colonne de rayons de 325 px s'affichait jusque dans le panier, la page
   contact et la page magasins. Sur ces écrans, il n'y a rien à parcourir : la
   colonne ne fait que rétrécir le contenu utile. Elle est conservée là où elle
   sert, c'est-à-dire sur les listes de produits.
   -------------------------------------------------------------------------- */

body.page-cart #left-column,
body.page-contact #left-column,
body.page-stores #left-column,
body.page-sitemap #left-column {
  display: none;
}

body.page-cart #content-wrapper,
body.page-contact #content-wrapper,
body.page-stores #content-wrapper,
body.page-sitemap #content-wrapper {
  width: 100%;
  max-width: none;
  flex: 1 1 100%;
  padding: 0;
}

/* --------------------------------------------------------------------------
   Champs de formulaire, hors écrans de compte (traités en 10-comptes.css)
   -------------------------------------------------------------------------- */

body.page-contact .form-control,
body.page-cart .form-control,
body.page-contact select.form-control,
body.page-contact textarea.form-control {
  min-height: 48px;
  padding: var(--b3-space-2xs) var(--b3-space-sm);
  border: 1.5px solid var(--b3-trait-fort);
  border-radius: var(--b3-radius-sm);
  background-color: var(--b3-papier);
  box-shadow: none;
  font-family: var(--b3-font);
  font-size: 1rem;
  color: var(--b3-encre);
}

body.page-contact textarea.form-control {
  min-height: 9rem;
  line-height: 1.5;
}

body.page-contact .form-control:focus,
body.page-cart .form-control:focus {
  border-color: var(--b3-encre);
  outline: 3px solid var(--b3-encre);
  outline-offset: 2px;
}

body.page-contact .form-control-label {
  font-size: 0.8125rem;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--b3-encre);
}

/* --------------------------------------------------------------------------
   Reste du rouge du thème

   `#b23c4a` subsistait sur le bouton de choix de fichier de la page contact.
   Il n'appartient pas à la marque : DESIGN.md ne lui laisse qu'un emploi, les
   messages d'erreur, sous le jeton `--b3-alerte`. Partout ailleurs, il sort.
   -------------------------------------------------------------------------- */

body.page-contact .custom-file,
body.page-contact input[type="file"] + label,
body.page-contact .btn-file,
body.page-contact label.btn {
  border: 1.5px solid var(--b3-encre);
  border-radius: var(--b3-radius-sm);
  background-color: transparent;
  background-image: none;
  font-size: 0.8125rem;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--b3-encre);
}

body.page-contact .custom-file:hover,
body.page-contact label.btn:hover {
  background-color: var(--b3-encre);
  color: var(--b3-papier);
}

/* --------------------------------------------------------------------------
   Boutons d'action des pages intérieures
   -------------------------------------------------------------------------- */

body.page-cart .btn-primary,
body.page-contact .btn-primary,
body.page-stores .btn-primary,
body.page-my-account .btn-primary {
  min-height: 48px;
  padding: 0 var(--b3-space-md);
  border: 0;
  border-radius: var(--b3-radius-pill);
  background-color: var(--b3-jaune);
  font-size: 0.9375rem;
  font-weight: 800;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--b3-encre);
}

body.page-cart .btn-primary:hover,
body.page-contact .btn-primary:hover,
body.page-stores .btn-primary:hover {
  background-color: var(--b3-jaune-fonce);
}

/* Le bouton secondaire garde le contour, jamais un aplat concurrent : deux
   aplats côte à côte annulent la hiérarchie entre l'action et son repli. */
body.page-cart .btn-secondary,
body.page-contact .btn-secondary,
body.page-my-account .btn-secondary {
  min-height: 48px;
  border: 1.5px solid var(--b3-encre);
  border-radius: var(--b3-radius-pill);
  background-color: transparent;
  font-weight: 700;
  color: var(--b3-encre);
}


/* ----- repris de 09-divers ----- */

/* Le contenu passe avant le bandeau de services : on inverse leur ordre
   sans toucher au balisage. */
main > section#wrapper {
  order: 1;
}

main {
  display: flex;
  flex-direction: column;
}

main > .breadcumb_outer { order: -1; }

/* 9octodecies.b — Cibles tactiles des pages intérieures.
   Le relevé sur la fiche produit comptait 68 éléments sous 40 px : les liens
   du fil d'Ariane, des onglets et du bloc de services. */
@media (max-width: 991px) {
.breadcumb_outer a,
  .display-topcolumn a,
  #product .tabs .nav-link,
  .product-tabs .nav-link {
    display: inline-flex;
    align-items: center;
    min-height: 40px;
  }
}


/* ==========================================================================
   Panier — récapitulatif et validation

   Le récapitulatif portait ses libellés en #999 sur blanc, soit 2.8:1 : sous
   le seuil AA, et illisible sur un écran mal orienté. C'est pourtant le bloc
   qu'on relit avant de payer.

   Le bouton de validation, lui, était en `inline-block` avec un interligne de
   18 px dans une boîte de 48 : le texte se calait en haut au lieu de se
   centrer.
   ========================================================================== */

body.page-cart .cart-summary-line {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--b3-space-2xs);
  padding: var(--b3-space-2xs) 0;
  font-size: 1rem;
}

body.page-cart .cart-summary-line .label,
body.page-cart .cart-summary-line .label a {
  font-size: 1rem;
  font-weight: 600;
  color: var(--b3-encre-douce);
}

body.page-cart .cart-summary-line .value {
  font-size: 1.0625rem;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  color: var(--b3-encre);
}

/* La livraison offerte est un argument : elle se lit, elle ne se devine pas. */
body.page-cart .cart-summary-line.cart-summary-subtotals-container .value,
body.page-cart .cart-summary-line .value:not(:empty) {
  white-space: nowrap;
}

/* Le total ferme le bloc : filet au-dessus, corps supérieur, encre pleine. */
body.page-cart .cart-summary-line.cart-total,
body.page-cart .cart-total {
  margin-top: var(--b3-space-2xs);
  padding-top: var(--b3-space-sm);
  border-top: 2px solid var(--b3-encre);
}

body.page-cart .cart-summary-line.cart-total .label,
body.page-cart .cart-total .label {
  font-size: 1.0625rem;
  font-weight: 800;
  color: var(--b3-encre);
}

body.page-cart .cart-summary-line.cart-total .value,
body.page-cart .cart-total .value {
  font-size: 1.375rem;
  font-weight: 800;
  color: var(--b3-encre);
}

/* Toute la colonne de droite tient dans un bloc papier : elle flottait sur le
   fond sans rien qui la désigne comme le récapitulatif. */
body.page-cart .cart-summary,
body.page-cart .cart-detailed-totals {
  padding: var(--b3-space-md);
  border: 1.5px solid var(--b3-trait);
  border-radius: var(--b3-radius);
  background-color: var(--b3-papier);
}

/* --------------------------------------------------------------------------
   Validation
   -------------------------------------------------------------------------- */

body.page-cart .checkout a,
body.page-cart .checkout .btn,
body.page-cart .cart-detailed-actions .btn-primary {
  /* `inline-flex` plutôt qu'`inline-block` : c'est le centrage vertical qui
     manquait, l'interligne ne remplissant pas la hauteur du bouton. */
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  min-height: 54px;
  padding: 0 var(--b3-space-md);
  border: 0;
  border-radius: var(--b3-radius-pill);
  background-color: var(--b3-jaune);
  font-size: 1rem;
  font-weight: 800;
  letter-spacing: 0.05em;
  line-height: 1;
  text-align: center;
  text-transform: uppercase;
  text-decoration: none;
  color: var(--b3-encre);
}

body.page-cart .checkout a:hover,
body.page-cart .cart-detailed-actions .btn-primary:hover {
  background-color: var(--b3-jaune-fonce);
}


/* --------------------------------------------------------------------------
   Bandeau de réassurance hors de l'accueil

   Le module de réassurance (otshippingblock) se rend aussi dans le panier et
   le tunnel, où il n'a pas sa place : on ne rassure plus quelqu'un qui a déjà
   choisi, on l'aide à conclure. Il s'y affichait de surcroît en colonnes de
   cinquante-trois pixels, où « Frais de port » s'empilait mot par mot.

   Il reste sur l'accueil, où il précède la décision d'achat.
   -------------------------------------------------------------------------- */

body.page-cart .shipping-inner,
body.page-cart .display-topcolumn,
body.page-order .shipping-inner,
body.page-order .display-topcolumn {
  display: none;
}


/* --------------------------------------------------------------------------
   Sélecteur de quantité du panier

   Les pas mesuraient 22 × 21 px. Ils fonctionnent — le plugin répond bien au
   clic — mais à cette taille on les manque, et l'on croit qu'ils sont cassés.
   PRODUCT.md fixe le minimum tactile à 44 px : c'est exactement le cas qu'il
   vise.
   -------------------------------------------------------------------------- */

body.page-cart .bootstrap-touchspin,
body.page-order .bootstrap-touchspin {
  display: inline-flex;
  align-items: stretch;
  width: auto;
  border: 1.5px solid var(--b3-encre);
  border-radius: var(--b3-radius-sm);
  overflow: hidden;
}

body.page-cart .bootstrap-touchspin .js-cart-line-product-quantity,
body.page-cart .bootstrap-touchspin input.form-control {
  order: 2;
  width: 3.25rem;
  min-height: 44px;
  padding: 0;
  border: 0;
  border-radius: 0;
  background-color: var(--b3-papier);
  font-family: var(--b3-font);
  font-size: 1rem;
  font-weight: 700;
  text-align: center;
  color: var(--b3-encre);
}

/* Les deux pas encadrent le champ plutôt que de s'empiler à sa droite :
   empilés, chacun n'avait que la moitié de la hauteur disponible. */
body.page-cart .bootstrap-touchspin .btn-touchspin,
body.page-order .bootstrap-touchspin .btn-touchspin {
  display: grid;
  place-items: center;
  flex: none;
  width: 44px;
  min-height: 44px;
  padding: 0;
  border: 0;
  border-radius: 0;
  background-color: var(--b3-papier-2);
  color: var(--b3-encre);
  cursor: pointer;
  transition: background-color var(--b3-dur-fast) var(--b3-ease);
}

body.page-cart .bootstrap-touchspin .js-decrease-product-quantity { order: 1; }
body.page-cart .bootstrap-touchspin .js-increase-product-quantity { order: 3; }

body.page-cart .bootstrap-touchspin .btn-touchspin:hover,
body.page-order .bootstrap-touchspin .btn-touchspin:hover {
  background-color: var(--b3-encre);
  color: var(--b3-papier);
}

/* Le glyphe du thème est remplacé par un signe lisible : la ligature Material
   ne se charge pas toujours, et une flèche minuscule ne dit pas « plus ». */
body.page-cart .bootstrap-touchspin .btn-touchspin i,
body.page-order .bootstrap-touchspin .btn-touchspin i {
  font-size: 0;
  line-height: 0;
}

body.page-cart .js-increase-product-quantity::after,
body.page-order .js-increase-product-quantity::after {
  content: "+";
  font-size: 1.25rem;
  font-weight: 700;
  line-height: 1;
}

body.page-cart .js-decrease-product-quantity::after,
body.page-order .js-decrease-product-quantity::after {
  content: "−";
  font-size: 1.25rem;
  font-weight: 700;
  line-height: 1;
}

/* --------------------------------------------------------------------------
   Page panier — reprise de la ligne produit

   Trois défauts tenaient à des règles du thème acheté :
   le pas de quantité se pliait en carré — « + » au-dessus de « − », la valeur
   à côté — ; la corbeille n'était qu'un glyphe posé sans surface ; et le
   bouton « Continuer mes achats » portait le rouge #b23c4a, que la charte
   proscrit sans exception.
   -------------------------------------------------------------------------- */

/* Le pas revient sur une ligne : moins, valeur, plus. C'est l'ordre d'un
   réglage, et c'est celui du panneau latéral — le même geste doit se
   présenter de la même façon d'un écran à l'autre. */
body.page-cart .product-line-grid-body .bootstrap-touchspin,
body.page-cart .bootstrap-touchspin {
  display: flex;
  flex-direction: row;
  align-items: stretch;
  width: max-content;
  min-width: 0;
  border: 1.5px solid var(--b3-encre);
  border-radius: var(--b3-radius-pill);
  overflow: hidden;
}

body.page-cart .bootstrap-touchspin .input-group-btn-vertical {
  display: contents;
}

body.page-cart .bootstrap-touchspin input.js-cart-line-product-quantity {
  order: 2;
  width: 3rem;
  min-height: 44px;
  padding: 0;
  border: 0;
  border-radius: 0;
  background-color: var(--b3-papier);
  font-family: var(--b3-font);
  font-size: 1rem;
  font-weight: 800;
  text-align: center;
  color: var(--b3-encre);
}

/* --------------------------------------------------------------------------
   La corbeille

   Un glyphe de vingt pixels sans boîte : la cible tenait dans la lettre.
   Rouge plein en permanence désormais, pas seulement au survol — la seule
   action irréversible de la page s'annonce d'emblée, pas seulement au
   moment où le doigt la touche déjà (le survol n'existe pas au tactile).
   -------------------------------------------------------------------------- */

body.page-cart .cart-line-product-actions,
body.page-cart .product-line-actions {
  display: flex;
  align-items: center;
  justify-content: flex-end;
}

/* Le thème acheté porte sa propre règle à trois classes
   (`.product-line-grid-right .cart-line-product-actions .remove-from-cart`,
   theme.css) : plus spécifique que la nôtre, elle regagnait `display` et
   `color`, cassant le carré fixe en pastille ovale (largeur reprise au
   contenu de l'icône, hauteur seule restant à 44px). `!important` sur les
   propriétés de boîte règle le rapport de force sans épuiser la chaîne de
   sélecteurs. */
body.page-cart .cart-line-product-actions a.remove-from-cart,
body.page-cart .product-line-actions a.remove-from-cart {
  display: grid !important;
  place-items: center;
  width: 44px !important;
  height: 44px !important;
  flex: none;
  border-radius: 50%;
  background-color: var(--b3-alerte);
  color: var(--b3-papier) !important;
  text-decoration: none;
  transition: background-color var(--b3-dur-fast) var(--b3-ease),
              transform var(--b3-dur-fast) var(--b3-ease);
}

body.page-cart a.remove-from-cart:hover,
body.page-cart a.remove-from-cart:focus-visible {
  background-color: color-mix(in oklab, var(--b3-alerte) 85%, black);
  transform: scale(1.06);
}

body.page-cart a.remove-from-cart i {
  float: none;
  font-size: 20px;
  line-height: 1;
  color: var(--b3-papier);
}

/* --------------------------------------------------------------------------
   Code promo

   Le thème acheté ne posait rien ici : un lien texte nu, un champ sans
   bordure visible, un bouton d'ajout qui se confondait avec le fond. Un
   cadre léger sépare le bloc du reste du récapitulatif, le lien d'ouverture
   se lit comme une invite (poids, chevron), le champ reprend la pilule de
   la recherche du site plutôt que le champ Bootstrap par défaut.
   -------------------------------------------------------------------------- */

body.page-cart .block-promo {
  margin-top: var(--b3-space-md);
  padding: var(--b3-space-md);
  border: 1px solid var(--b3-trait-fort);
  border-radius: var(--b3-radius);
}


/* `.block-promo .promo-code-button` (thème acheté) porte `padding-left:1.25rem;
   margin-bottom:1.25rem; display:inline-block` — même poids que la nôtre,
   égalité tranchée par l'ordre des sources en faveur du thème acheté. */
body.page-cart .promo-code-button {
  display: inline-flex !important;
  align-items: center;
  gap: var(--b3-space-3xs);
  padding-left: 0 !important;
  margin-bottom: 0 !important;
  font-size: 0.9375rem;
  font-weight: 700;
  color: var(--b3-encre);
  text-decoration: none;
  white-space: nowrap;
}

body.page-cart .promo-code-button::after {
  content: "";
  width: 8px;
  height: 8px;
  border-right: 2px solid currentColor;
  border-bottom: 2px solid currentColor;
  transform: rotate(45deg);
  transition: transform var(--b3-dur-fast) var(--b3-ease);
}

body.page-cart .promo-code-button[aria-expanded="true"]::after {
  transform: rotate(-135deg);
}

body.page-cart .promo-code-button:hover {
  text-decoration: underline;
}

/* Le thème acheté porte `.block-promo .promo-code{padding:1.6rem;background:#ebebeb}` :
   même poids de sélecteur (deux classes) que le nôtre, la source la plus
   tardive gagnant l'égalité — ici le thème acheté. Repris en totalité. */
body.page-cart .promo-code {
  margin-top: var(--b3-space-sm);
  padding: 0 !important;
  background: transparent !important;
}

body.page-cart .promo-code form {
  display: flex !important;
  gap: var(--b3-space-xs);
}

/* Même conflit qu'au-dessus : `.block-promo .promo-input` (thème acheté)
   posait `width:60%; height:2.5rem` — deux classes, gagnant l'égalité par
   l'ordre des sources. Le champ se lisait alors comme un rond plutôt qu'un
   champ de saisie, `flex: 1 1 auto` ne pouvant pas agrandir une largeur
   déjà figée en pourcentage par une règle de même poids. `!important` sur
   les dimensions plutôt que sur tout le bloc. */
body.page-cart .promo-input {
  flex: 1 1 auto;
  width: auto !important;
  min-height: 44px;
  height: 44px !important;
  padding: 0 var(--b3-space-md);
  border: 2px solid var(--b3-trait-fort);
  border-radius: var(--b3-radius-pill);
  background-color: var(--b3-papier);
  font-family: var(--b3-font);
  font-size: 0.9375rem;
  color: var(--b3-encre);
  text-indent: 0;
  transition: border-color var(--b3-dur-fast) var(--b3-ease);
}

body.page-cart .promo-input:focus-visible {
  outline: none;
  border-color: var(--b3-encre);
}

body.page-cart .promo-code .alert-danger {
  margin-top: var(--b3-space-xs);
  padding: var(--b3-space-xs) var(--b3-space-sm);
  border: 1px solid var(--b3-alerte);
  border-radius: var(--b3-radius-sm);
  background-color: color-mix(in oklab, var(--b3-alerte) 8%, var(--b3-papier));
  color: var(--b3-alerte);
  font-size: 0.875rem;
}

/* Un code déjà appliqué : ligne posée comme les autres du récapitulatif,
   la croix de suppression reprend le geste de la corbeille du panier. */
body.page-cart .promo-name.card-block {
  margin: 0 0 var(--b3-space-sm);
  padding: 0;
  list-style: none;
}

body.page-cart .promo-name .cart-summary-line {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--b3-space-xs);
  padding: var(--b3-space-2xs) 0;
  font-weight: 700;
  color: var(--b3-encre);
}

body.page-cart .promo-name .cart-summary-line a[data-link-action="remove-voucher"] {
  display: grid;
  place-items: center;
  width: 28px;
  height: 28px;
  border-radius: 50%;
  background-color: var(--b3-alerte);
  color: var(--b3-papier);
  text-decoration: none;
}

body.page-cart .promo-name .cart-summary-line a[data-link-action="remove-voucher"] i {
  font-size: 16px;
  color: var(--b3-papier);
}

body.page-cart .promo-name .float-xs-right {
  font-weight: 800;
  color: var(--b3-succes);
}

/* --------------------------------------------------------------------------
   Le pas de quantité chevauchait le prix, au téléphone

   Le thème case les deux dans une grille Bootstrap étroite — `col-xs-6` pour
   le pas, `col-xs-2` pour le prix, sur un total qui ne fait déjà que la
   moitié de la ligne. Le pas, habillé en pilule de largeur naturelle
   (`width: max-content`, plus haut dans ce fichier), déborde de sa colonne et
   recouvre le prix : mesuré, « 21,20 € » se lisait « 2 +,20 € », le bouton
   « + » posé par-dessus le premier chiffre.

   Les deux reprennent chacun toute la largeur, l'un sous l'autre : plus de
   colonnes étroites à se disputer. */
@media (max-width: 767px) {
  body.page-cart .product-line-grid-right .row,
  body.page-order .product-line-grid-right .row {
    display: flex;
    flex-direction: column;
    align-items: stretch;
    gap: var(--b3-space-2xs);
  }

  body.page-cart .product-line-grid-right [class*="col-"],
  body.page-order .product-line-grid-right [class*="col-"] {
    width: 100%;
    max-width: 100%;
    flex: none;
  }

  body.page-cart .product-line-grid-right .qty,
  body.page-order .product-line-grid-right .qty {
    display: flex;
  }

  body.page-cart .product-line-grid-right .price,
  body.page-order .product-line-grid-right .price {
    text-align: left;
  }
}

/* L'effacement précède la navigation : le clic doit se voir avant le
   rechargement, sinon on clique deux fois. */
body.page-cart .cart-item.b3-part {
  opacity: 0;
  transform: translateX(-14px);
  transition: opacity 240ms var(--b3-ease), transform 240ms var(--b3-ease);
}

@media (prefers-reduced-motion: reduce) {
  body.page-cart .cart-item.b3-part {
    transition: none;
  }
}

/* --------------------------------------------------------------------------
   Actions de bas de panier

   Le rouge du thème acheté n'appartient pas à la marque : la charte le
   réserve aux erreurs, et « continuer mes achats » n'en est pas une.

   Le bouton porte l'aplat encre en permanence, pas seulement au survol —
   « bouton sur fond noir » de DESIGN.md (texte jaune ou papier sur encre) :
   un geste secondaire, mais affirmé, pas une pilule fantôme qui se devine
   au doigt sur mobile où le survol n'existe pas.
   -------------------------------------------------------------------------- */

body.page-cart .b3-continuer-achats {
  display: inline-flex;
  align-items: center;
  gap: var(--b3-space-2xs);
  min-height: 48px;
  padding: 0 var(--b3-space-md);
  border: 1.5px solid var(--b3-encre);
  border-radius: var(--b3-radius-pill);
  background-color: var(--b3-encre);
  background-image: none;
  font-family: var(--b3-font);
  font-size: 0.875rem;
  font-weight: 800;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  text-decoration: none;
  color: var(--b3-papier);
  transition: background-color var(--b3-dur-fast) var(--b3-ease),
              transform var(--b3-dur-fast) var(--b3-ease);
}

body.page-cart .b3-continuer-achats:hover {
  background-color: color-mix(in oklab, var(--b3-encre) 85%, white);
  transform: translateY(-1px);
}

body.page-cart .b3-continuer-achats i {
  color: var(--b3-papier);
}

/* Le bloc de réassurance du thème sort une cadenas orange sur fond papier :
   ni la couleur ni le poids visuel n'appartiennent à la page. */
body.page-cart .block-reassurance img,
body.page-cart .block-reassurance i {
  filter: grayscale(1) contrast(0.9);
  opacity: 0.75;
}


/* ===== 13-splash.css ===================================================== */

/* ==========================================================================
   Écran d'ouverture

   Des bulles claires qui montent sur l'aplat jaune, puis le tampon 3B, puis
   l'accueil. Le geste emprunte à l'effervescence plutôt qu'au chargement : il
   n'y a rien à attendre, la page est déjà là dessous.

   Seuls `opacity` et `transform` sont animés — jamais une propriété de mise en
   page. Chaque bulle est isolée sur sa propre couche de composition, ce qui
   permet à douze d'entre elles de monter sans repeindre l'aplat à chaque
   image.
   ========================================================================== */

.b3-splash {
  position: fixed;
  inset: 0;
  z-index: 9999;
  display: grid;
  place-items: center;
  overflow: hidden;
  background-color: var(--b3-jaune);
  /* La sortie est un simple fondu : l'écran s'efface, il ne s'échappe pas. */
  transition: opacity 520ms var(--b3-ease), visibility 520ms var(--b3-ease);
}

.b3-splash[hidden] {
  display: none;
}

/* Classe posée par le script au moment de retirer l'écran. `visibility` est
   nécessaire en plus de l'opacité : un élément transparent resterait cliquable
   et continuerait d'intercepter le premier geste du visiteur. */
.b3-splash--sortie {
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
}

/* --------------------------------------------------------------------------
   Les bulles
   -------------------------------------------------------------------------- */

.b3-splash__bulles {
  position: absolute;
  inset: 0;
  pointer-events: none;
}

.b3-splash__bulle {
  position: absolute;
  /* Toutes partent sous l'écran : la remontée commence hors champ, aucune
     bulle n'apparaît par surgissement au milieu de l'aplat. */
  bottom: -12vh;

  /* Répartition sur toute la largeur : le pas de 2,5 % couvre les 40 rangs. */
  left: calc(var(--i) * 2.5% - 1%);

  /* Calibre de base. Les trois classes de taille sont posées plus bas par
     `nth-child`, et non par un modulo en `calc()` : `round()` n'existe que
     dans les navigateurs récents, et une fonction non reconnue invalide toute
     la déclaration — les bulles se retrouveraient alors sans largeur. */
  width: calc(0.4rem + var(--i) * 0.03rem);

  aspect-ratio: 1;
  border-radius: 50%;
  background-color: color-mix(in oklab, var(--b3-papier) 88%, transparent);
  /* Le reflet du haut suffit à faire lire une bulle plutôt qu'un disque. */
  box-shadow: inset 0 -0.12em 0.2em color-mix(in oklab, var(--b3-encre) 8%, transparent),
              inset 0 0.14em 0.16em color-mix(in oklab, #fff 85%, transparent);
  opacity: 0;
  will-change: transform, opacity;

  /* Les grosses montent moins vite que les fines : c'est l'inverse de la
     physique, mais c'est ce que l'œil attend d'une image de champagne, où les
     traînées fines filent et les grosses paressent. */
  animation: b3-monte calc(3200ms + var(--i) * 145ms) linear infinite;
  animation-delay: calc(var(--i) * -170ms);
}

/* Trois calibres et trois dérives, en alternance. Des bulles toutes égales se
   lisent comme des points ; il faut du gros et du fin pour que l'œil y voie du
   gaz. Le décalage horizontal change de sens d'un rang à l'autre, sinon toute
   la nappe part du même côté et l'écran semble pencher. */
.b3-splash__bulle:nth-child(5n) {
  width: calc(1.15rem + var(--i) * 0.02rem);
  animation-duration: calc(4800ms + var(--i) * 70ms);
}

.b3-splash__bulle:nth-child(5n + 1) {
  width: calc(0.24rem + var(--i) * 0.008rem);
  animation-duration: calc(2500ms + var(--i) * 45ms);
}

.b3-splash__bulle:nth-child(5n + 2) {
  width: calc(0.62rem + var(--i) * 0.014rem);
  animation-duration: calc(3400ms + var(--i) * 55ms);
}

.b3-splash__bulle:nth-child(5n + 3) {
  width: calc(0.4rem + var(--i) * 0.01rem);
  animation-duration: calc(3000ms + var(--i) * 50ms);
}

.b3-splash__bulle:nth-child(4n) {
  margin-left: 1.6%;
}

.b3-splash__bulle:nth-child(4n + 2) {
  margin-left: -1.8%;
}

/* Une bulle de champagne ne monte pas droit : elle dérive. Le décalage
   horizontal change de sens d'un rang à l'autre, sinon toute la nappe part du
   même côté et l'écran semble pencher. */
@keyframes b3-monte {
  0%   { transform: translate3d(0, 0, 0) scale(0.55); opacity: 0; }
  8%   { opacity: 0.95; }
  50%  { transform: translate3d(1.6vw, -62vh, 0) scale(1); }
  82%  { opacity: 0.7; }
  100% { transform: translate3d(-1.1vw, -125vh, 0) scale(1.05); opacity: 0; }
}

/* --------------------------------------------------------------------------
   Le tampon
   -------------------------------------------------------------------------- */

.b3-splash__marque {
  position: relative;
  z-index: 1;
  display: grid;
  place-items: center;
}

/* L'enveloppe porte le cercle blanc et rogne : l'image, agrandie pour cadrer
   le tampon, doit être découpée par un conteneur de taille fixe, sans quoi
   elle déborde et le cercle cesse d'être concentrique. */
.b3-splash__tampon {
  display: block;
  /* Le tampon est le sujet de l'écran : il occupe la moitié de la largeur sur
     un téléphone, et plafonne à 17rem pour ne pas devenir une affiche sur un
     grand écran. */
  width: clamp(10rem, 34vw, 17rem);
  aspect-ratio: 1;
  overflow: hidden;
  border-radius: 50%;
  /* Deux cernes concentriques : le papier détache le cachet de l'aplat jaune,
     l'encre lui rend le trait d'un vrai tampon. */
  box-shadow: 0 0 0 7px var(--b3-papier),
              0 0 0 10px var(--b3-encre);
  opacity: 0;
  animation: b3-tampon 1100ms var(--b3-ease) 260ms forwards;
}

/* Le fichier étant carré et détouré, `contain` suffit : le cachet touche le
   bord du disque sans être agrandi, donc sans perdre son pourtour. C'est ce
   que faisaient l'ancien `cover`, son cadrage à gauche et son facteur 1,23 —
   trois réglages accordés à un fichier rectangulaire qui n'a plus cours. */
.b3-splash__logo {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: contain;
}

/* Le tampon se pose : il arrive légèrement trop grand et se stabilise, comme
   un cachet qu'on appuie. Pas de rebond — la charte l'exclut. */
@keyframes b3-tampon {
  0%   { opacity: 0; transform: scale(1.16); }
  55%  { opacity: 1; }
  100% { opacity: 1; transform: scale(1); }
}

/* Signature sous le tampon, en encre pleine. Elle arrive après lui : le regard
   se pose sur la marque, puis lit. */
.b3-splash__signature {
  margin: var(--b3-space-lg) 0 0;
  /* Le tampon ayant grandi, la signature suivait mal : à 1,5 rem elle
     ressemblait à une légende sous une affiche. */
  font-size: clamp(1.5rem, 4.6vw, 2.5rem);
  font-weight: 800;
  font-stretch: 84%;
  letter-spacing: -0.005em;
  line-height: 1.02;
  text-align: center;
  color: var(--b3-encre);
  opacity: 0;
  animation: b3-signature 900ms var(--b3-ease) 900ms forwards;
}

/* La coupure est composée, pas subie : chaque ligne est son propre bloc. */
.b3-splash__signature span {
  display: block;
}

@keyframes b3-signature {
  0%   { opacity: 0; transform: translate3d(0, 10px, 0); }
  100% { opacity: 1; transform: translate3d(0, 0, 0); }
}

/* Le tampon se pose : il arrive légèrement trop grand et se stabilise, comme
   un cachet qu'on appuie. Pas de rebond — la charte l'exclut. */
/* --------------------------------------------------------------------------
   Adaptations
   -------------------------------------------------------------------------- */

/* Sur un écran étroit, les bulles se resserrent et ralentissent : leur
   trajectoire est plus courte, elles paraîtraient sinon précipitées. */
@media (max-width: 767px) {
  .b3-splash__bulle {
    width: calc(0.45rem + var(--i) * 0.12rem);
    animation-duration: calc(3000ms + var(--i) * 210ms);
  }
}

/* Écran bas et large — un téléphone couché, une tablette : la course verticale
   se raccourcit, les bulles doivent traverser plus vite pour rester lisibles. */
@media (max-height: 520px) {
  .b3-splash__bulle {
    animation-duration: calc(2000ms + var(--i) * 140ms);
  }
  .b3-splash__tampon {
    width: clamp(8rem, 30vh, 12rem);
  }
}

/* Mouvement réduit : l'écran ne s'anime plus du tout. Il reste affiché le
   temps que le script le retire, sans bulles ni mise à l'échelle. */
@media (prefers-reduced-motion: reduce) {
  .b3-splash__bulles {
    display: none;
  }

  .b3-splash__tampon,
  .b3-splash__signature {
    opacity: 1;
    transform: none;
    animation: none;
  }

  .b3-splash {
    transition-duration: 1ms;
  }
}


/* --------------------------------------------------------------------------
   Mention sanitaire

   Elle se lit sans être criée : capitales fines, encre adoucie, au pied de
   l'écran. Sur l'aplat jaune, l'encre à 78 % tient encore 8:1.
   -------------------------------------------------------------------------- */

/* Le centrage passe par `inset-inline: 0` et une marge automatique, pas par
   `left: 50%` et une translation. L'écran est une grille en `place-items:
   center`, et cet alignement s'applique aussi aux enfants positionnés : la
   boîte était déjà centrée, la translation la décalait ensuite d'une
   demi-largeur vers la droite. */
.b3-splash__prevention {
  position: absolute;
  inset-inline: 0;
  bottom: clamp(var(--b3-space-md), 4vh, var(--b3-space-xl));
  z-index: 2;
  width: min(92%, 46rem);
  margin-inline: auto;
  font-size: clamp(0.8125rem, 2vw, 1.0625rem);
  font-weight: 800;
  letter-spacing: 0.04em;
  line-height: 1.35;
  text-align: center;
  text-transform: uppercase;
  color: var(--b3-encre);
  opacity: 0;
  animation: b3-signature 900ms var(--b3-ease) 1200ms forwards;
}

@media (prefers-reduced-motion: reduce) {
  .b3-splash__prevention {
    opacity: 1;
    animation: none;
  }
}


/* ===== 14-produit.css ==================================================== */

@charset "UTF-8";
/* ==========================================================================
   Fiche produit

   L'écran le plus important du site après la vignette, et le moins repris : le
   titre du vin s'affichait en 22 px graisse 400 — celle du texte courant —, le
   visuel occupait 813 px de haut, soit la totalité de l'écran, et le prix se
   perdait dans le bloc d'informations.

   La page est remise dans l'ordre de lecture d'un caviste : ce que c'est, d'où
   ça vient, combien, comment l'avoir.
   ========================================================================== */

/* --------------------------------------------------------------------------
   Deux colonnes, avec un visuel borné

   Le visuel n'a pas besoin de la hauteur d'un écran : au-delà, il repousse le
   prix et le bouton d'achat sous la ligne de flottaison. Il garde le rapport
   3:4 des bouteilles et s'arrête à une hauteur qui laisse voir l'essentiel.
   -------------------------------------------------------------------------- */

/* --------------------------------------------------------------------------
   Badge « Foire aux vins »

   Posé au-dessus du titre : c'est la première chose qui doit se voir sur un
   vin de la sélection pendant la foire, avant même son nom. Fond jaune plein
   — la couleur de la marque, pas une couleur d'alerte — parce qu'un badge
   promotionnel n'est pas un avertissement.
   -------------------------------------------------------------------------- */
body.page-product .b3-badge-foire {
  display: inline-flex;
  align-items: center;
  gap: 0.4em;
  margin: 0 0 var(--b3-space-xs);
  padding: 0.4em 0.9em;
  border-radius: var(--b3-radius-pill);
  background-color: var(--b3-jaune);
  color: var(--b3-encre);
  font-size: 0.75rem;
  font-weight: 800;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  text-decoration: none;
}

body.page-product .b3-badge-foire::before {
  content: "";
  width: 14px;
  height: 14px;
  background-color: currentColor;
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M20.59 13.41 11 3.83A2 2 0 0 0 9.59 3.24H4a1 1 0 0 0-1 1v5.59a2 2 0 0 0 .59 1.41l9.58 9.59a2 2 0 0 0 2.83 0l4.59-4.6a2 2 0 0 0 0-2.82Z'/%3E%3Ccircle cx='7.5' cy='7.5' r='1.2' fill='%23000' stroke='none'/%3E%3C/svg%3E") center / contain no-repeat;
  mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M20.59 13.41 11 3.83A2 2 0 0 0 9.59 3.24H4a1 1 0 0 0-1 1v5.59a2 2 0 0 0 .59 1.41l9.58 9.59a2 2 0 0 0 2.83 0l4.59-4.6a2 2 0 0 0 0-2.82Z'/%3E%3Ccircle cx='7.5' cy='7.5' r='1.2' fill='%23000' stroke='none'/%3E%3C/svg%3E") center / contain no-repeat;
}

body.page-product #content .product-cover,
body.page-product #product-images-large {
  max-width: 100%;
  margin: 0;
}

body.page-product #content .product-cover img,
body.page-product #product-images-large img {
  width: 100%;
  height: auto;
  max-height: 62vh;
  object-fit: contain;
  border-radius: var(--b3-radius);
  background-color: var(--b3-papier-2);
}

/* --------------------------------------------------------------------------
   Titre et prix
   -------------------------------------------------------------------------- */

body.page-product h1,
body.page-product .product-information h1,
body.page-product .page-header h1 {
  margin: 0 0 var(--b3-space-2xs);
  font-size: clamp(1.75rem, 3.4vw, 2.75rem);
  font-weight: 800;
  font-stretch: 74%;
  line-height: 1.02;
  letter-spacing: -0.02em;
  color: var(--b3-encre);
  text-wrap: balance;
}

/* Le prix est l'information que l'on vient chercher : il prend le corps qui le
   dit, et se pose sur l'aplat de marque plutôt que de flotter dans le texte. */
body.page-product .product-prices .current-price,
body.page-product .product-price {
  display: inline-flex;
  align-items: baseline;
  gap: 0.3em;
  padding: 0.25em 0.55em;
  border-radius: var(--b3-radius-sm);
  background-color: var(--b3-jaune);
  font-size: clamp(1.375rem, 2.2vw, 1.75rem);
  font-weight: 800;
  font-variant-numeric: tabular-nums;
  line-height: 1.1;
  color: var(--b3-encre);
}

body.page-product .product-prices {
  margin: 0 0 var(--b3-space-sm);
  padding: 0;
  border: 0;
}

/* Le prix barré reste lisible : en gris clair, il devenait indéchiffrable. */
body.page-product .product-prices .regular-price {
  margin-left: 0.4em;
  font-size: 1rem;
  font-weight: 600;
  text-decoration: line-through;
  color: var(--b3-encre-douce);
}

/* --------------------------------------------------------------------------
   Achat
   -------------------------------------------------------------------------- */

body.page-product .product-actions .product-add-to-cart {
  margin: 0 0 var(--b3-space-sm);
  padding: var(--b3-space-sm) 0 0;
  border-top: 1.5px solid var(--b3-trait);
}

body.page-product .product-quantity {
  display: flex;
  align-items: center;
  gap: var(--b3-space-2xs);
}

/* Le thème compose ce contrôle en `display: table`, avec les deux flèches
   empilées dans un groupe qui se retrouvait écrasé à un pixel de large : le
   champ et ses commandes se chevauchaient. Il repasse en flex, et les flèches
   reçoivent une largeur. */
body.page-product .product-quantity .qty {
  width: auto;
  flex: none;
}

body.page-product .product-quantity .input-group.bootstrap-touchspin {
  display: flex;
  align-items: stretch;
  /* `max-content` est nécessaire : le thème pose une largeur sur ce groupe,
     qui le rabattait à 56 px pour un contenu de 110 — le champ débordait de
     son propre cadre. */
  width: max-content;
  min-width: max-content;
  border: 1.5px solid var(--b3-encre);
  border-radius: var(--b3-radius-sm);
  overflow: hidden;
}

body.page-product .product-quantity .input-group-btn-vertical {
  display: flex;
  flex: none;
  flex-direction: column;
  width: 38px;
  border-left: 1.5px solid var(--b3-encre);
}

body.page-product .product-quantity .input-group-btn-vertical > .btn {
  flex: 1 1 0;
  display: grid;
  place-items: center;
  width: 100%;
  min-width: 0;
  padding: 0;
  border: 0;
  border-radius: 0;
  background-color: var(--b3-papier);
  color: var(--b3-encre);
  cursor: pointer;
}

body.page-product .product-quantity .input-group-btn-vertical > .btn:first-child {
  border-bottom: 1.5px solid var(--b3-trait);
}

body.page-product .product-quantity .input-group-btn-vertical > .btn:hover {
  background-color: var(--b3-encre);
  color: var(--b3-papier);
}

/* Le champ ne porte plus le contour : c'est le groupe qui l'assure, sans quoi
   deux traits se superposaient au milieu du contrôle.

   `.qty` est l'enveloppe, pas la saisie : lui donner la largeur du champ
   l'enfermait dans 72 px alors que le contrôle en mesure 113 avec ses deux
   flèches. Le débordement passait sous le bouton « Ajouter au panier », qui
   commence 37 px plus tôt. La largeur ne s'applique donc qu'à la saisie. */
body.page-product .product-quantity input.form-control,
body.page-product .product-quantity input#quantity_wanted {
  min-height: 52px;
  width: 4.5rem;
  padding: 0 var(--b3-space-2xs);
  border: 0;
  border-radius: 0;
  background-color: var(--b3-papier);
  font-family: var(--b3-font);
  font-size: 1.0625rem;
  font-weight: 700;
  text-align: center;
  color: var(--b3-encre);
}

body.page-product .btn.add-to-cart,
body.page-product button.add-to-cart {
  flex: 1 1 auto;
  min-height: 52px;
  padding: 0 var(--b3-space-md);
  border: 0;
  border-radius: var(--b3-radius-pill);
  background-color: var(--b3-jaune);
  font-size: 1rem;
  font-weight: 800;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--b3-encre);
  transition: background-color var(--b3-dur-fast) var(--b3-ease);
}

body.page-product .btn.add-to-cart:hover:not([disabled]),
body.page-product button.add-to-cart:hover:not([disabled]) {
  background-color: var(--b3-jaune-fonce);
}

/* Rupture de stock : le bouton doit le dire, pas seulement s'éteindre. */
body.page-product .btn.add-to-cart[disabled],
body.page-product button.add-to-cart[disabled] {
  background-color: var(--b3-papier-2);
  color: var(--b3-encre-douce);
  cursor: not-allowed;
}

/* --------------------------------------------------------------------------
   Caractéristiques et onglets
   -------------------------------------------------------------------------- */

body.page-product .tabs {
  margin-top: var(--b3-space-lg);
  padding: var(--b3-space-md);
  border: 1.5px solid var(--b3-trait);
  border-radius: var(--b3-radius);
  background-color: var(--b3-papier);
  box-shadow: none;
}

body.page-product .tabs .nav-tabs {
  gap: var(--b3-space-2xs);
  margin-bottom: var(--b3-space-md);
  border: 0;
  border-bottom: 1.5px solid var(--b3-trait);
}

body.page-product .tabs .nav-tabs .nav-link {
  padding: var(--b3-space-2xs) var(--b3-space-sm);
  border: 0;
  border-radius: var(--b3-radius-sm) var(--b3-radius-sm) 0 0;
  font-size: 0.875rem;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--b3-encre-douce);
}

/* L'onglet courant est marqué par l'aplat et la graisse, pas par la seule
   couleur du libellé. */
body.page-product .tabs .nav-tabs .nav-link.active {
  background-color: var(--b3-encre);
  font-weight: 800;
  color: var(--b3-jaune);
}

/* Les caractéristiques sont le cœur documentaire de la fiche : appellation,
   cépage, contenance. En tableau nu, elles se lisaient comme un export. */
body.page-product .product-features .data-sheet {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: var(--b3-space-2xs);
  margin: 0;
  padding: 0;
}

body.page-product .product-features .data-sheet dt,
body.page-product .product-features .data-sheet dd {
  margin: 0;
  padding: var(--b3-space-2xs) var(--b3-space-xs);
  background-color: var(--b3-papier-2);
}

body.page-product .product-features .data-sheet dt {
  border-radius: var(--b3-radius-sm) var(--b3-radius-sm) 0 0;
  font-size: 0.75rem;
  font-weight: 800;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--b3-encre-douce);
}

body.page-product .product-features .data-sheet dd {
  margin-bottom: var(--b3-space-2xs);
  border-radius: 0 0 var(--b3-radius-sm) var(--b3-radius-sm);
  font-size: 1rem;
  font-weight: 700;
  color: var(--b3-encre);
}

/* --------------------------------------------------------------------------
   Adaptations
   -------------------------------------------------------------------------- */

@media (max-width: 991px) {
  /* Une colonne : le visuel d'abord, puis le nom, le prix, l'achat. */
  body.page-product #content .product-cover img,
  body.page-product #product-images-large img {
    max-height: 46vh;
  }

  body.page-product .product-quantity {
    flex-wrap: wrap;
  }

  body.page-product .btn.add-to-cart,
  body.page-product button.add-to-cart {
    flex: 1 1 100%;
  }
}


/* ==========================================================================
   Fiche produit — reprise des états et des contrastes
   ========================================================================== */

/* --------------------------------------------------------------------------
   Drapeaux

   La rupture de stock sortait en vert — la couleur de la confirmation, sur
   l'information qui dit précisément qu'on ne peut pas acheter. Elle prend
   l'alerte, seul emploi que la charte laisse au rouge avec les erreurs.
   -------------------------------------------------------------------------- */

body.page-product .product-flags li,
body.page-product .product-flag {
  display: inline-flex;
  align-items: center;
  gap: 0.4em;
  padding: 0.4em 0.8em;
  border-radius: var(--b3-radius-pill);
  background-color: var(--b3-encre);
  font-size: 0.75rem;
  font-weight: 800;
  letter-spacing: 0.05em;
  line-height: 1.2;
  text-transform: uppercase;
  color: var(--b3-papier);
}

body.page-product .product-flag.out_of_stock,
body.page-product .product-flags .out_of_stock {
  background-color: var(--b3-alerte);
  color: var(--b3-papier);
}

/* Les drapeaux positifs — nouveauté, promotion — gardent le jaune de la
   maison, sur encre. */
body.page-product .product-flag.new,
body.page-product .product-flag.on-sale,
body.page-product .product-flag.discount {
  background-color: var(--b3-jaune);
  color: var(--b3-encre);
}

/* --------------------------------------------------------------------------
   Contrastes

   Le thème sort ses textes secondaires en #999 sur blanc, soit 2.8:1 : la
   mention de taxe, la description courte et le libellé de quantité étaient
   sous le seuil AA. Le jeton `--b3-encre-douce` tient 6.95:1.
   -------------------------------------------------------------------------- */

body.page-product .product-information,
body.page-product .product-description-short,
body.page-product .product-description-short p,
body.page-product .tax-shipping-delivery-label,
body.page-product .product-quantity .control-label,
body.page-product label {
  color: var(--b3-encre-douce);
}

body.page-product .product-description-short,
body.page-product .product-description-short p {
  font-size: 1rem;
  line-height: 1.6;
  color: var(--b3-encre);
}

body.page-product .product-quantity .control-label {
  display: block;
  margin-bottom: var(--b3-space-3xs);
  font-size: 0.8125rem;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--b3-encre);
}

/* --------------------------------------------------------------------------
   Rupture : l'achat s'efface

   Un bouton grisé posé à côté d'un sélecteur de quantité actif laisse croire
   que la commande reste possible. Quand le produit est indisponible, la ligne
   d'achat cède la place au message.
   -------------------------------------------------------------------------- */

body.page-product .product-quantity {
  align-items: flex-end;
  gap: var(--b3-space-xs);
}

body.page-product #product-availability {
  display: inline-flex;
  align-items: center;
  gap: 0.45em;
  font-size: 0.9375rem;
  font-weight: 700;
  color: var(--b3-alerte);
}

/* --------------------------------------------------------------------------
   Partage

   Trois icônes de réseaux sociaux sur six cent dix-neuf pixels, dans la
   colonne d'achat, entre le bouton et les garanties. Personne ne partage une
   bouteille sur Pinterest depuis une fiche produit ; la place sert mieux au
   reste. Retiré de l'affichage — le module reste installé.
   -------------------------------------------------------------------------- */

body.page-product .social-sharing {
  display: none;
}

/* « Paiement sécurisé » (module blockreassurance, renommé depuis « Garanties
   sécurité » — voir outils/renommer-garanties.php).

   Le vrai marquage n'a ni `#block-reassurance` ni `<li>` : c'est
   `.blockreassurance_product > div > .item-product` (icône) + `.block-title`
   (texte), en dehors de toute liste — vérifié sur le HTML rendu, pas deviné
   depuis un gabarit. Le sélecteur précédent ne touchait donc jamais cet
   élément ; l'icône gardait sa couleur d'origine (le rouge/orange du SVG
   source) et le texte restait nu, sans le bandeau prévu.

   L'icône source est masquée : un cadenas plat ne dit pas grand-chose, et sa
   couleur ne se pilotait pas proprement en `filter` sur un `<img>` (déjà
   raté une fois). Un bouclier coché, en masque CSS comme le cœur des
   favoris, donne une couleur exacte — vert, la connotation universelle du
   « sécurisé » — sans dépendre du SVG livré par le module. */
body.page-product .blockreassurance_product {
  margin-top: var(--b3-space-sm);
}

/* Le module pose un second `<div class="clearfix">` vide, frère de celui
   qui porte l'icône et le texte : `:not()` l'exclut, sinon il reprenait la
   même bordure et affichait un cadre vide sous le bandeau. */
body.page-product .blockreassurance_product > div:not(.clearfix) {
  display: flex;
  align-items: center;
  gap: var(--b3-space-xs);
  padding: var(--b3-space-xs) var(--b3-space-sm);
  border: 1px solid var(--b3-trait-fort);
  border-radius: var(--b3-radius);
}

body.page-product .blockreassurance_product .item-product {
  display: block;
  flex: none;
  width: 22px;
  height: 22px;
}

/* Le module remplace le `<img class="svg invisible">` par un `<svg>` inline
   une fois chargé (même mécanique que les icônes de `#block-reassurance`
   ailleurs sur cette fiche) : masquer seulement `img` laissait ce second
   élément, non ciblé, apparaître sous le pictogramme — d'où le cadenas
   orange resté visible sous le bouclier vert lors de la recette. */
body.page-product .blockreassurance_product .item-product img,
body.page-product .blockreassurance_product .item-product svg {
  display: none;
}

body.page-product .blockreassurance_product .item-product::before {
  content: "";
  display: block;
  width: 22px;
  height: 22px;
  background-color: oklch(0.6 0.14 152);
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M12 3l7 3v6c0 4.5-3 7.5-7 9-4-1.5-7-4.5-7-9V6l7-3Z'/%3E%3Cpath d='m9 12 2 2 4-4'/%3E%3C/svg%3E") center / contain no-repeat;
  mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M12 3l7 3v6c0 4.5-3 7.5-7 9-4-1.5-7-4.5-7-9V6l7-3Z'/%3E%3Cpath d='m9 12 2 2 4-4'/%3E%3C/svg%3E") center / contain no-repeat;
}

body.page-product .blockreassurance_product .block-title {
  margin: 0;
  font-size: 0.875rem;
  font-weight: 700;
  color: var(--b3-encre) !important;
}

/* Coffret cadeau : même bouton « appeler » que la rupture de stock sur les
   cartes, agrandi à l'échelle de la fiche produit plutôt que d'une
   vignette. */
body.page-product .b3-card__coffret {
  margin-bottom: var(--b3-space-xs);
  font-size: 0.9375rem;
}

body.page-product .b3-card__besoin--fiche {
  min-height: 44px;
  font-size: 0.875rem;
}

/* Le bouton favori se pose maintenant sur le visuel — voir
   catalog/_partials/product-cover-thumbnails.tpl — même rond plein qu'une
   vignette de catalogue (04-carte.css, `.b3-card .wishlist-button-add`),
   repris ici pour le même geste au même endroit visuel : en haut à droite
   d'une image produit, où qu'elle se trouve sur le site. `.product-cover`
   porte déjà `position: relative` (thème acheté, pour son loupe de zoom). */
body.page-product .b3-produit-favori--visuel {
  position: absolute;
  top: var(--b3-space-2xs);
  right: var(--b3-space-2xs);
  z-index: 4;
}

body.page-product .b3-produit-favori--visuel .wishlist-button-add {
  position: static;
  display: grid !important;
  place-items: center;
  width: 42px !important;
  height: 42px !important;
  min-width: 0 !important;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background-color: oklch(0.63 0.19 12);
  color: transparent;
  box-shadow: none;
  cursor: pointer;
  transition: background-color var(--b3-dur-fast) var(--b3-ease),
              transform var(--b3-dur-fast) var(--b3-ease);
}

body.page-product .b3-produit-favori--visuel .wishlist-button-add:hover {
  background-color: oklch(0.57 0.20 12);
  transform: scale(1.06);
}

body.page-product .b3-produit-favori--visuel .wishlist-button-add::after {
  content: none;
}

/* La ligature du module (`favorite`/`favorite_border`) est remplacée par un
   tracé, comme sur les vignettes : une police d'icônes ne se charge pas
   toujours, et son rendu varie d'un système à l'autre. */
body.page-product .b3-produit-favori--visuel .wishlist-button-add i {
  font-size: 0;
  line-height: 0;
  color: transparent;
}

body.page-product .b3-produit-favori--visuel .wishlist-button-add svg,
body.page-product .b3-produit-favori--visuel .wishlist-button-add::before {
  content: "";
  display: block;
  width: 21px;
  height: 21px;
  background-color: var(--b3-papier);
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2.1' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M12 20.5s-7.3-4.6-7.3-9.6A4.2 4.2 0 0 1 12 8a4.2 4.2 0 0 1 7.3 2.9c0 5-7.3 9.6-7.3 9.6Z'/%3E%3C/svg%3E") center / contain no-repeat;
  mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2.1' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M12 20.5s-7.3-4.6-7.3-9.6A4.2 4.2 0 0 1 12 8a4.2 4.2 0 0 1 7.3 2.9c0 5-7.3 9.6-7.3 9.6Z'/%3E%3C/svg%3E") center / contain no-repeat;
}


/* --------------------------------------------------------------------------
   Contenu éditorial de la fiche

   La description et les caractéristiques sont saisies en back-office, souvent
   collées depuis un traitement de texte : elles arrivent avec leurs propres
   classes (`MsoNormal`) et parfois leurs styles. Le gris #999 qui en résulte
   tombe à 2.8:1 — sous le seuil AA, sur le texte qui décrit ce qu'on achète.

   La couleur est reprise sur l'ensemble du contenu produit. `!important` est
   nécessaire là où le style est inline, ce que la spécificité ne renverse pas.
   -------------------------------------------------------------------------- */

/* L'identifiant de la description porte l'identifiant du produit —
   `product-description-short-881` — et change donc à chaque fiche : on vise
   le préfixe. */
body.page-product [id^="product-description-short"] p,
body.page-product [id^="product-description-short"] span,
body.page-product .product-description p,
body.page-product .product-description span,
body.page-product .product-description div,
body.page-product .MsoNormal,
body.page-product .MsoNormal span,
body.page-product .product-add-to-cart .control-label,
body.page-product .product-quantity .control-label,
body.page-product .tabs .tab-content p,
body.page-product .tabs .tab-content span {
  color: var(--b3-encre) !important;
}

/* Les mentions accessoires — taxe, unité — restent en encre douce, qui tient
   6.95:1 : elles doivent se lire sans concurrencer le texte principal. */
body.page-product .tax-shipping-delivery-label,
body.page-product .product-unit-price {
  color: var(--b3-encre-douce) !important;
}

/* La description longue arrive souvent collée depuis un traitement de
   texte, exactement comme le cas Word détaillé plus haut : chaque
   paragraphe porte ses propres styles en ligne — `text-align:justify`,
   `line-height:normal`, une taille en points, une police, une couleur.
   Un style en ligne bat n'importe quelle règle externe, `!important` ou
   pas, sur sa propre déclaration ; il faut donc le viser explicitement.

   Le résultat sans ce nettoyage : un texte justifié sur une colonne de
   217px au téléphone, les mots espacés en escalier pour remplir la ligne —
   la justification est faite pour une colonne large, elle défigure une
   colonne étroite. Et un interligne, une police, une taille qui changent
   d'une fiche à l'autre selon qui a collé le texte et depuis quel logiciel. */
body.page-product .product-description,
body.page-product .product-description p,
body.page-product .product-description span {
  text-align: left !important;
  font-family: var(--b3-font) !important;
}

body.page-product .product-description {
  font-size: 1rem;
  line-height: 1.7;
  color: var(--b3-encre);
}

body.page-product .product-description p,
body.page-product .product-description span {
  font-size: inherit !important;
  line-height: inherit !important;
}

body.page-product .product-description p {
  margin: 0 0 var(--b3-space-sm) !important;
}

body.page-product .product-description p:last-child {
  margin-bottom: 0 !important;
}

/* Deux paragraphes composent chaque fiche (voir descriptions-fav.php et
   fiches-catalogue.php) : le fait — appellation, cépage, méthode — puis la
   maison. Le premier gagne un peu de poids, assez pour guider l'œil sans
   se lire comme un titre. */
body.page-product .product-description p:first-child {
  font-weight: 600;
}

@media (min-width: 992px) {
  body.page-product .product-description {
    max-width: 68ch;
  }
}

@media (max-width: 575px) {
  body.page-product .product-description {
    font-size: 1.0625rem;
    line-height: 1.65;
  }
}


/* --------------------------------------------------------------------------
   Rupture de stock : la commande disparaît

   Un bouton grisé posé à côté d'un sélecteur de quantité actif laisse croire
   que la commande reste possible, et invite à cliquer pour rien. Quand le
   produit est indisponible, la ligne d'achat cède la place au message : c'est
   lui l'information utile.

   Le formulaire reste dans le document — PrestaShop le réactive sans recharger
   dès qu'une déclinaison disponible est choisie — mais il n'occupe plus de
   place tant que le produit ne peut pas être acheté.
   -------------------------------------------------------------------------- */

body.page-product .product-quantity:has(.add-to-cart[disabled]) .qty,
body.page-product .product-quantity:has(.add-to-cart[disabled]) .add {
  display: none;
}

body.page-product .product-quantity:has(.add-to-cart[disabled]) #product-availability {
  margin: 0;
  padding: var(--b3-space-2xs) var(--b3-space-sm);
  border-radius: var(--b3-radius-sm);
  background-color: color-mix(in oklab, var(--b3-alerte) 12%, transparent);
  font-size: 1rem;
}

/* Repli pour les navigateurs sans `:has()` : le bouton reste, mais il annonce
   son état plutôt que de se contenter d'un gris. */
@supports not selector(:has(*)) {
  body.page-product .add-to-cart[disabled] {
    background-color: var(--b3-papier-2);
    color: var(--b3-encre-douce);
  }
}


/* ===== 15-responsive.css ================================================= */

@charset "UTF-8";
/* ==========================================================================
   Ajustements transversaux — tablette et cibles tactiles

   La tablette (768 → 1024 px) était la plage la moins vérifiée : trop large
   pour déclencher les règles mobiles, trop étroite pour la mise en page
   desktop. C'est aussi celle où les défauts structurels se voient le mieux.
   ========================================================================== */

/* --------------------------------------------------------------------------
   Le débordement de 30 px

   Les conteneurs cumulaient `width: 100%` et `margin: 0 15px` : deux réglages
   qui s'additionnent au lieu de se compléter. Mesuré sur un écran de 834 px,
   le conteneur allait de 15 à 849 — trente pixels de trop, sur toutes les
   pages. Le défaut existe à toute largeur inférieure au maximum de contenu,
   simplement il ne se voyait pas sur un grand écran, où la largeur est bornée
   bien avant les bords.

   Le centrage se fait par `margin-inline: auto`, et le retrait latéral par le
   rembourrage, qui reste dans la boîte grâce à `border-box`.
   -------------------------------------------------------------------------- */

.container,
.container-fluid {
  width: 100%;
  margin-inline: auto;
  padding-inline: var(--b3-space-sm);
  box-sizing: border-box;
}

/* Un conteneur imbriqué dans un autre ne doit pas ajouter son propre retrait
   au retrait déjà appliqué : il déborderait d'autant. */
.container .container,
.container-fluid .container {
  padding-inline: 0;
  max-width: 100%;
}

/* Les rangées Bootstrap compensent le rembourrage des colonnes par des marges
   négatives. Sans colonnes à compenser — c'est le cas partout où la mise en
   page est passée en grille — elles ne font plus que déborder. */
.container > .row,
.container-fluid > .row {
  margin-inline: 0;
}

/* --------------------------------------------------------------------------
   Cibles tactiles

   PRODUCT.md fixe le minimum à 44 × 44. Sur tablette, plusieurs commandes
   restaient sous ce seuil : les pas du sélecteur de quantité à 26 px, la
   pagination à 36, les liens de pied de page à 38. Une tablette se tient au
   doigt : la règle vaut là autant que sur un téléphone.
   -------------------------------------------------------------------------- */

@media (min-width: 768px) and (max-width: 1024px) {
  /* Le pas de quantité garde son dessin rond mais gagne la surface tactile,
     posée en pseudo-élément pour ne pas déformer la pastille. */
  .b3-qty__step {
    position: relative;
  }

  .b3-qty__step::after {
    content: "";
    position: absolute;
    top: 50%;
    left: 50%;
    width: 44px;
    height: 44px;
    transform: translate(-50%, -50%);
  }

  .pagination a,
  .pagination .page-list a,
  .pagination li > a {
    min-width: 44px;
    min-height: 44px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
  }

  #footer a,
  .footer-container a {
    display: inline-flex;
    align-items: center;
    min-height: 44px;
  }

  /* Les liens de bas de formulaire — mot de passe oublié, création de compte —
     ne faisaient que la hauteur de leur texte. */
  .forgot-password a,
  .no-account a {
    display: inline-flex;
    align-items: center;
    min-height: 44px;
  }
}

/* --------------------------------------------------------------------------
   Mise en page tablette

   Deux colonnes de vignettes tiennent mal entre 768 et 1024 : trop larges,
   elles étirent l'image ; trois donnent la densité d'un rayon sans rendre les
   étiquettes illisibles.
   -------------------------------------------------------------------------- */

@media (min-width: 768px) and (max-width: 1024px) {
  #products .products,
  .products.row:not(:has(.owl-carousel)),
  .product-accessories .products:not(:has(.owl-carousel)),
  .featured-products .products:not(:has(.owl-carousel)) {
    grid-template-columns: repeat(3, minmax(0, 1fr));
  }

  /* La colonne de filtres passe au-dessus des résultats : à cette largeur,
     elle amputait la grille d'un tiers pour rester illisible. */
  body.page-category #left-column,
  body.page-search #left-column {
    width: 100%;
    max-width: none;
    flex: 1 1 100%;
  }

  body.page-category #content-wrapper,
  body.page-search #content-wrapper {
    width: 100%;
    max-width: none;
    flex: 1 1 100%;
  }

  /* Les facettes se rangent en bandeau plutôt qu'en colonne. */
  #search_filters {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(230px, 1fr));
    gap: var(--b3-space-2xs);
  }

  #search_filters .facet {
    margin-bottom: 0;
  }

  /* Fiche produit : le visuel et les informations gardent deux colonnes, mais
     le visuel cesse de prendre la moitié de la hauteur d'écran. */
  body.page-product #content .product-cover img,
  body.page-product #product-images-large img {
    max-height: 44vh;
  }
}


/* --------------------------------------------------------------------------
   Reliquats relevés en tablette
   -------------------------------------------------------------------------- */

@media (min-width: 768px) and (max-width: 1024px) {
  /* La case de facette mesure 20 px, mais c'est le libellé qui porte le clic :
     c'est donc lui qui doit atteindre le seuil tactile. */
  #search_filters .facet-label,
  #search_filters .facet li > a {
    min-height: 44px;
  }

  /* Les poignées du curseur de prix se manipulent au doigt : deux carrés de
     seize pixels ne s'attrapent pas. */
  /* jQuery UI pose ses propres dimensions avec un sélecteur à deux classes :
     il faut au moins autant pour les reprendre. */
  #search_filters .ui-slider .ui-slider-handle.ui-state-default,
  .ui-slider .ui-slider-handle.ui-state-default {
    width: 28px;
    height: 28px;
    top: 50%;
    margin-top: -14px;
    margin-left: -14px;
    border: 2px solid var(--b3-encre);
    border-radius: 50%;
    background: var(--b3-jaune);
  }
}

/* Un élément de grille ne rétrécit pas en dessous de son contenu tant qu'on ne
   le lui dit pas : le compteur d'une facette sortait de l'écran, poussé par un
   libellé de région trop long. */
#search_filters .facet,
#search_filters .facet-label,
#search_filters .facet li > a {
  min-width: 0;
}

/* Le compteur, poussé à droite par sa marge automatique, sortait de sa facette.
   `overflow: hidden` sur l'étiquette le tranchait au lieu de le replacer : on
   lisait « Coffrets Bières ( ». C'est le libellé qui doit céder, pas le
   chiffre — il passe donc à la ligne dans la place qui lui reste, tandis que
   le compteur garde sa largeur. */
#search_filters .facet li > a {
  flex-wrap: nowrap;
  white-space: normal;
}

#search_filters .facet-label {
  flex-wrap: nowrap;
  overflow: visible;
}

#search_filters .magnitude {
  flex: none;
  margin-left: auto;
}

/* Le bandeau de réassurance reprenait les marges négatives d'une rangée
   Bootstrap sans colonnes à compenser : trente pixels de débordement. */
.display-topcolumn .shipping-inner,
.display-topcolumn .row {
  margin-inline: 0;
  max-width: 100%;
}


/* Les blocs CMS de bas de page reprennent la grille Bootstrap sans son
   conteneur : leurs rangées appliquent des marges négatives que rien ne
   compense, soit quatre pixels de débordement à droite. Sans conséquence
   visible — aucun défilement horizontal — mais autant ne pas laisser traîner
   une largeur fausse.

   La marge droite valait ici -20 px, ce qui étend la boîte d'autant vers la
   droite. Le sélecteur reste borné à ces blocs : un `.row { margin: 0 }`
   général casserait les grilles Bootstrap encore en service ailleurs. */
.subbannerbottomcms-outer,
.subbannerbottomcms-inner {
  max-width: 100%;
  overflow-x: clip;
}

.subbannerbottomcms-outer .container,
.subbannerbottomcms-outer .row,
.subbannerbottomcms-outer .banner-desc {
  max-width: 100%;
  margin-inline: 0;
  padding-inline: 0;
}

/* ==========================================================================
   Reprise mobile — en-tête, filtres, entrées, catalogue

   Corrections posées sur des causes identifiées dans la feuille, non sur des
   mesures : je n'ai pas d'appareil pour vérifier. À reprendre après une
   recette réelle sur iPhone.
   ========================================================================== */

@media (max-width: 991px) {
  /* Le tampon est visé sans passer par son conteneur : `#_mobile_logo` est
     rendu vide, et c'est le script du thème qui y déplace le logo du bureau
     après coup. Une règle attachée à l'un des deux ne s'applique donc que la
     moitié du temps, selon que le script a tourné ou non. */
  #header .b3-logo__tampon {
    width: 56px;
    height: 56px;
    min-width: 56px;
  }

  #header .b3-logo__tampon .logo {
    width: 100%;
    height: 100%;
  }

  #header #_mobile_logo,
  #header .b3-logo {
    display: flex;
    align-items: center;
    align-self: center;
    margin: 0;
  }

  /* La loupe est posée en absolu dans le champ. Sa règle de bureau la place à
     droite d'un champ large ; sur un champ pleine largeur, elle se retrouvait
     décalée du bord. */
  #header #search_widget form button[type="submit"],
  #header #search_widget form .search-icon {
    position: absolute;
    right: 6px;
    top: 50%;
    transform: translateY(-50%);
    margin: 0;
  }

  #header #search_widget form {
    position: relative;
  }
}

@media (max-width: 767px) {
  /* Les liens de rayon — « Vins », « Notre brasserie » — restent sur une ligne
     défilante : ils sont deux, ils tiennent.

     La barre de filtres, elle, n'y est plus. Avec onze boutons, la ligne unique
     partait si loin à droite qu'on ne voyait jamais les couleurs ni les pays :
     il fallait deviner qu'ils existaient pour aller les chercher. Elle se replie
     désormais en trois rangées, une par famille — voir 05-accueil.css. */
  .b3-rayons-liens {
    flex-wrap: nowrap;
    overflow-x: auto;
    scrollbar-width: none;
    -webkit-overflow-scrolling: touch;
    padding-bottom: var(--b3-space-3xs);
  }

  .b3-rayons-liens::-webkit-scrollbar {
    display: none;
  }

  /* La barre de filtres qui suit propose déjà « Vins » — pas de doublon
     sur un écran qui n'a pas la place d'en montrer deux. */
  .b3-rayon-lien--vins {
    display: none;
  }

  .b3-filter,
  .b3-rayon-lien {
    flex: none;
    min-height: 36px;
    padding: 0 var(--b3-space-sm);
    font-size: 0.6875rem;
  }

  /* Les filtres de région n'ont pas leur place sur un écran de téléphone :
     neuf pastilles de plus dans une barre déjà pleine, pour un tri qu'on fait
     mieux depuis la page de catégorie et ses facettes. */
  /* Les anciens filtres de région restent masqués s'il en subsiste ; les
     filtres de pays, eux, ont leur place — c'est la question qu'on pose. Le
     séparateur redevient une rupture de ligne, il ne se masque plus. */
  .b3-filter[data-b3-filter-type="region"] {
    display: none;
  }

  /* Les entrées éditoriales : une colonne, chacune à sa hauteur. La grille
     nommée gardait ses deux colonnes et rognait la carte « Coffrets », dont
     le texte se retrouvait hors cadre. */
  .b3-entries {
    grid-template-columns: 1fr;
    grid-template-areas:
      "majeure"
      "haute"
      "basse"
      "large"
      "annonce";
    grid-template-rows: none;
    min-height: 0;
  }

  .b3-entry {
    min-height: 15rem;
  }

  .b3-entry--majeure {
    min-height: 20rem;
  }

  .b3-entry--majeure .b3-entry__title {
    max-width: none;
    font-size: clamp(1.5rem, 6vw, 2rem);
  }

  /* Catalogue : deux vignettes par ligne, gouttière serrée. Le thème en
     imposait une par ligne sur toute la largeur, ce qui donnait des cartes de
     quatre cents pixels de haut pour une bouteille. */
  #js-product-list .products,
  .products.row {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: var(--b3-space-xs);
    margin-inline: 0;
  }

  #js-product-list .products > *,
  .products.row > * {
    width: auto;
    max-width: none;
    padding: 0;
    margin: 0;
  }
}

/* ==========================================================================
   Reprise mobile — deuxième passe, sur captures réelles
   ========================================================================== */

@media (max-width: 991px) {
  /* Le tampon : l'enveloppe portait sa taille, l'image non. Le cercle d'encre
     s'affichait donc en grand avec un cachet minuscule au centre. Les deux
     sont désormais dimensionnés ensemble, et l'image remplit son cadre. */
  #header .b3-logo__tampon,
  #header #_mobile_logo .b3-logo__tampon,
  #header #_desktop_logo .b3-logo__tampon {
    flex: none;
    width: 48px;
    height: 48px;
    min-width: 48px;
    max-width: 48px;
  }

  /* L'image gardait sa taille intrinsèque au lieu de remplir l'enveloppe : on
     voyait un cercle d'encre de cinquante pixels avec un cachet de cinq au
     milieu. Le thème pose des `!important` sur ces images — il en faut autant
     pour les reprendre. */
  #header .b3-logo__tampon img,
  #header .b3-logo__tampon .logo,
  #header #_mobile_logo img,
  #header .b3-logo img {
    display: block !important;
    width: 48px !important;
    height: 48px !important;
    min-width: 48px !important;
    max-width: 48px !important;
    max-height: 48px !important;
    object-fit: contain !important;
    transform: none !important;
  }

  /* L'interface remonte. `padding-block` sur `.header-top` faisait disparaître
     tout l'en-tête : le thème y compose sa rangée en grille, dont la hauteur
     dépend de ce rembourrage. Seule la marge haute est reprise, et par une
     propriété qui ne participe pas à la hauteur de la grille. */
  #header .header-nav {
    padding-top: var(--b3-space-3xs);
    padding-bottom: var(--b3-space-3xs);
  }

  #header #search_widget {
    margin-top: 0;
  }

  #header #search_widget form input[type="text"],
  #header #search_widget form input[type="search"] {
    min-height: 44px;
    font-size: 16px; /* en dessous, iOS agrandit la page à la mise au point */
  }

  .b3-hero.b3-panneau {
    min-height: 0;
  }
}

@media (max-width: 767px) {
  /* Vignette produit à deux colonnes : chaque carte fait environ 200 px.
     Les commandes gardaient leur taille de bureau et y devenaient énormes. */
  .b3-card .wishlist-button-add,
  .b3-card .b3-card__favori {
    width: 32px;
    height: 32px;
    top: var(--b3-space-3xs);
    right: var(--b3-space-3xs);
  }

  .b3-card .wishlist-button-add svg,
  .b3-card .wishlist-button-add i {
    width: 16px;
    height: 16px;
    font-size: 16px;
  }

  /* Le titre se coupait au milieu d'un mot : « COLLIN ES… ». La césure est
     rendue aux règles de la langue, et la troncature compte des lignes plutôt
     que des caractères. */
  .b3-card__title,
  .b3-card__title a {
    word-break: normal;
    overflow-wrap: break-word;
    hyphens: auto;
    font-size: 0.8125rem;
    line-height: 1.2;
  }

  /* Le pas de quantité débordait de la carte, moins et valeur hors cadre. */
  .b3-card__footer {
    flex-wrap: nowrap;
    gap: var(--b3-space-3xs);
    min-width: 0;
  }

  /* Le pied de carte est traité en fin de 99-conteneurs.css, après les
     requêtes de conteneur : le bouton d'ajout vit dans un formulaire, et il
     fallait rendre ce formulaire souple pour qu'il cesse d'être rogné. Les
     règles qui figuraient ici visaient les bons éléments mais posaient des
     propriétés `flex` sur des enfants dont le parent n'était pas un conteneur
     flexible — elles n'ont jamais rien produit. */

  .b3-card__price {
    font-size: 0.9375rem;
  }
}

/* --------------------------------------------------------------------------
   Nos actualités — le visuel prend la place

   Le bandeau vivait dans un cadre à la largeur de contenu, avec une marge de
   chaque côté : sur un téléphone, il restait une bande de deux cents pixels
   au milieu d'un écran vide. Il sort du conteneur et occupe la largeur.
   -------------------------------------------------------------------------- */

.b3-actus .b3-bandeau .owl-carousel,
.b3-actus .b3-bandeau [id*="slider"] {
  border-radius: var(--b3-radius-lg);
}

.b3-actus .b3-bandeau img {
  width: 100%;
  height: auto;
  object-fit: cover;
}

@media (max-width: 767px) {
  .b3-actus {
    margin-inline: calc(50% - 50vw);
    width: 100vw;
    max-width: 100vw;
  }

  .b3-actus .b3-section__title {
    padding-inline: var(--b3-space-sm);
  }

  .b3-actus .b3-bandeau .owl-carousel,
  .b3-actus .b3-bandeau [id*="slider"] {
    border-radius: 0;
    border-inline: 0;
  }

  /* Le visuel est un panoramique de 1600 × 719 : sur un écran étroit, il se
     réduit à une bande. Il est recadré en portrait pour occuper la hauteur
     qu'une annonce mérite. */
  .b3-actus .b3-bandeau img {
    aspect-ratio: 4 / 3;
    object-fit: cover;
  }
}


/* --------------------------------------------------------------------------
   Nos actualités — le visuel occupe le panneau

   Audit du vide. Trois contraintes se cumulaient :

     1. `.b3-section` borne la largeur à 1320 px et ajoute deux marges
        latérales ;
     2. `.b3-bandeau img` est en `height: auto` — la hauteur découle donc de
        cette largeur bornée, et pas d'autre chose ;
     3. la section est un panneau en `min-height: 100svh`, centré.

   Sur un écran de 1440 × 900, cela donnait une image de 1272 × 572 au milieu
   d'un panneau de 900 : plus de trois cents pixels de vide, répartis de part
   et d'autre. Le conteneur était bien le coupable, comme supposé.

   Le bandeau sort donc du conteneur à toutes les tailles, et l'image reçoit
   une hauteur explicite au lieu de la déduire de sa largeur. Le recadrage se
   fait en `cover` : les visuels sont des panoramiques de 1600 × 719, un
   redimensionnement les aurait déformés.
   -------------------------------------------------------------------------- */

@media (min-width: 768px) {
  .b3-actus {
    max-width: none;
    margin-inline: calc(50% - 50vw);
    width: 100vw;
    padding-inline: 0;
  }

  /* Le titre, lui, reste dans la mesure du texte : une ligne de titre au ras
     du bord de l'écran ne se lit pas comme un titre de section. */
  .b3-actus .b3-section__title {
    max-width: 1320px;
    margin-inline: auto;
    padding-inline: var(--b3-space-md);
  }

  /* Le cadre perd son arrondi et ses filets latéraux : au bord de l'écran,
     un angle arrondi n'a plus rien à arrondir. */
  .b3-actus .b3-bandeau .owl-carousel,
  .b3-actus .b3-bandeau [id*="slider"] {
    border-radius: 0;
    border-inline: 0;
  }

  /* Le visuel occupe la section, pas une bande au milieu.
     58svh laissait un tiers de panneau vide au-dessus et au-dessous. La
     hauteur se déduit désormais du panneau lui-même : tout l'écran, moins la
     place du titre et des marges. C'est ce qui donne l'immersion — une image
     qui s'arrête à mi-hauteur se lit comme une illustration, une image qui
     tient l'écran se lit comme une scène. */
  .b3-actus .b3-bandeau img {
    width: 100%;
    height: clamp(26rem, calc(100svh - 13rem), 56rem);
    object-fit: cover;
    object-position: center;
  }

  /* Owl fixe la hauteur de sa piste sur celle de la première diapositive
     mesurée. Sans cette reprise, la piste gardait la hauteur d'avant. */
  .b3-actus .b3-bandeau .owl-stage-outer,
  .b3-actus .b3-bandeau .owl-item,
  .b3-actus .b3-bandeau .slide,
  .b3-actus .b3-bandeau .slide > a {
    height: auto;
  }
}

/* Sur téléphone, la section était déjà en pleine largeur ; seule la hauteur
   du visuel manquait. Le portrait 4/3 posé à la passe précédente tenait sur
   un écran étroit, il devient une hauteur franche. */
@media (max-width: 767px) {
  .b3-actus .b3-bandeau img {
    aspect-ratio: auto;
    height: clamp(22rem, calc(100svh - 11rem), 40rem);
    object-fit: cover;
  }
}


/* --------------------------------------------------------------------------
   L'en-tête sur téléphone — trois corrections

   1. LE TAMPON ÉCRASÉ PAR SON REMBOURRAGE

   Le cachet apparaissait comme un point de quatre pixels au centre d'un cercle
   vide. Ni la taille de l'image ni le fichier n'étaient en cause : mesurée,
   l'image occupait bien ses 48 px, et le PNG porte son cachet sur 90 % de sa
   surface. C'est le thème qui pose `padding: 10px 24px 22px 20px` sur ses
   logos. Dans une case de 48 px en `border-box`, il ne restait que quatre
   pixels de large pour peindre.

   Mes `!important` précédents fixaient la largeur et la hauteur — jamais le
   rembourrage. D'où trois passes sans effet.

   2. LES BARRES NOIRES

   `.header-nav` porte un fond encre et un rembourrage vertical de 4 px que
   j'avais ajouté pour remonter l'interface. Le conteneur jaune à l'intérieur
   ne couvrant que sa propre hauteur, l'encre débordait de part et d'autre :
   deux filets noirs, en haut et en bas. Le fond passe au jaune.

   3. L'INTERFACE REMONTE

   La barre de recherche descendait trop bas. Les espaces de la rangée
   supérieure se resserrent.
   -------------------------------------------------------------------------- */

@media (max-width: 991px) {
  /* Le rembourrage d'abord : c'est lui qui écrasait le cachet. */
  #header .b3-logo__tampon img,
  #header .b3-logo__tampon .logo,
  #header #_mobile_logo img,
  #header #_mobile_logo .logo,
  #header .b3-logo img {
    padding: 0 !important;
    margin: 0 !important;
    box-sizing: border-box !important;
  }

  /* Le tampon grandit : à 48 px il se lisait mal une fois le cachet rétabli.
     56 px reste sous la hauteur de la rangée. */
  #header .b3-logo__tampon,
  #header #_mobile_logo .b3-logo__tampon,
  #header #_desktop_logo .b3-logo__tampon {
    width: 56px !important;
    height: 56px !important;
    min-width: 56px !important;
    max-width: 56px !important;
    display: grid !important;
    place-items: center !important;
  }

  #header .b3-logo__tampon img,
  #header .b3-logo__tampon .logo,
  #header #_mobile_logo img,
  #header .b3-logo img {
    width: 56px !important;
    height: 56px !important;
    min-width: 56px !important;
    max-width: 56px !important;
    max-height: 56px !important;
  }

  /* Plus de filet noir : la rangée est jaune de bord à bord. */
  #header .header-nav {
    padding-top: 0;
    padding-bottom: 0;
    background-color: var(--b3-jaune);
    border: 0;
  }

  /* L'interface remonte d'un cran. */
  #header .header-top {
    padding-top: var(--b3-space-3xs);
    padding-bottom: var(--b3-space-3xs);
  }

  #header .header-top .container,
  #header .header-top .row {
    margin-block: 0;
  }
}


/* --------------------------------------------------------------------------
   La barre de filtres, compacte

   Sur téléphone, les huit couleurs et les quatre rayons occupaient huit
   rangées : la moitié d'un écran avant la première bouteille. Deux erreurs
   successives de ma part — d'abord une ligne unique qui partait trop loin à
   droite, puis un repli qui empilait tout.

   La bonne réponse tient dans la structure, pas dans la taille : chaque
   famille a son rail, et chaque rail défile pour lui-même. On voit toujours
   les trois familles, on ne fait glisser que celle qui déborde.
   -------------------------------------------------------------------------- */

.b3-filters__groupe {
  display: flex;
  align-items: center;
  gap: var(--b3-space-2xs);
  width: 100%;
  min-width: 0;
}

.b3-filters__rail {
  display: flex;
  align-items: center;
  gap: var(--b3-space-2xs);
  min-width: 0;
  flex: 1 1 auto;
}

@media (max-width: 767px) {
  .b3-filters {
    display: flex;
    flex-direction: column;
    align-items: stretch;
    gap: var(--b3-space-3xs);
  }

  .b3-filters__groupe {
    gap: var(--b3-space-3xs);
  }

  /* Le rail défile ; l'intitulé reste en place à sa gauche, comme une clé de
     lecture. */
  .b3-filters__rail {
    flex-wrap: nowrap;
    overflow-x: auto;
    scrollbar-width: none;
    -webkit-overflow-scrolling: touch;
    padding-block: 2px;
    scroll-padding-inline-start: var(--b3-space-3xs);
  }

  .b3-filters__rail::-webkit-scrollbar {
    display: none;
  }

  .b3-filters__intitule {
    flex: 0 0 auto;
    width: 4.4rem;
    margin-right: 0;
    font-size: 0.625rem;
    letter-spacing: 0.06em;
    line-height: 1.1;
  }

  /* Les pastilles se resserrent : c'est le rembourrage qui les rendait
     énormes, pas le texte. */
  .b3-filters .b3-filter {
    flex: 0 0 auto;
    min-height: 34px;
    padding: 0 var(--b3-space-xs);
    font-size: 0.6875rem;
    letter-spacing: 0.02em;
    white-space: nowrap;
  }

  .b3-filters .b3-filter[data-b3-picto]::before {
    margin-right: 0.3em;
    font-size: 0.9375rem;
  }

  /* Le séparateur n'a plus de rôle : les groupes s'en chargent. */
  .b3-filters__separateur {
    display: none;
  }
}


/* --------------------------------------------------------------------------
   Points de finition — recherche, badge, entrée « raretés »
   -------------------------------------------------------------------------- */

/* La loupe dans sa pastille jaune.

   Le thème pose un `text-indent` et un rembourrage sur ses boutons de
   formulaire ; le glyphe se retrouvait décalé de quelques pixels dans un
   cercle par ailleurs bien centré. Le bouton redevient une grille dont le seul
   enfant est centré, et le glyphe perd tout ce qui le déplace. */
#header #search_widget button[type="submit"],
#header #search_widget form button {
  display: grid !important;
  place-items: center !important;
  place-content: center !important;
  text-indent: 0 !important;
  line-height: 1 !important;
}

#header #search_widget button .material-icons,
#header #search_widget button i,
#header #search_widget button svg {
  display: block;
  margin: 0 auto;
  text-indent: 0;
  line-height: 1;
  transform: none;
}

@media (min-width: 768px) and (max-width: 1200px) {
  /* Sur tablette, l'entrée « Les raretés à découvrir » occupait toute la
     largeur du bloc en gardant une hauteur de carte : une bande très étirée où
     la photographie ne se lit plus. Elle se rapproche du carré — le format qui
     rend une nature morte de bouteilles lisible. */
  .b3-entry--majeure {
    min-height: clamp(26rem, 46vw, 38rem);
  }

  .b3-entry--majeure .b3-entry__fond img {
    object-position: center 62%;
  }
}

@media (max-width: 767px) {
  /* L'interface remonte encore d'un cran : la barre de recherche flottait à
     mi-hauteur du premier écran, loin du pouce et loin du logo. */
  #header .header-top {
    padding-top: 0;
    padding-bottom: var(--b3-space-3xs);
  }

  #header #search_widget,
  #header .header-top .row {
    margin-top: 0;
  }

  .b3-hero.b3-panneau .b3-hero__inner {
    padding-block: var(--b3-space-sm);
  }

  /* Le badge : plus haut, et sa police en gras plein. À 800 sur onze pixels
     espacés, il se lisait comme une légende ; c'est une signature. */
  .b3-hero__kicker {
    margin-top: 0;
    margin-bottom: var(--b3-space-xs);
    padding: 0.55em 1.1em;
    font-size: 0.75rem;
    font-weight: 900;
    letter-spacing: 0.06em;
  }

  .b3-hero__kicker b {
    font-weight: 900;
  }
}


/* ==========================================================================
   Les pages intérieures
   ========================================================================== */

/* Le bandeau de diapositives ne vit plus que sur l'accueil.

   Il était masqué ici par une règle d'affichage, ce qui le retirait de la vue
   mais laissait ses six visuels se télécharger. `othomeslider` implémentant
   `WidgetInterface`, il a pu être débranché de `displayTopColumn` — voir
   index.tpl, qui l'appelle désormais par son widget. La règle CSS n'a plus
   d'objet et disparaît avec le problème. */

/* --------------------------------------------------------------------------
   Le pied de page sur téléphone

   Mesuré : le bloc d'identité — raison sociale, téléphone, adresse — tenait
   dans quatre-vingt-dix pixels de large. Les mots s'y coupaient un par ligne
   pendant que les deux tiers droits restaient vides. Le conteneur du thème
   répartit ses colonnes en flex sans point de rupture : `col-md-3` ne
   s'applique qu'au-delà de 768 px, mais la répartition flex, elle, vaut
   partout.
   -------------------------------------------------------------------------- */

@media (max-width: 767px) {
  #footer .footerbottomleft-outer,
  #footer .footer-container .row,
  #footer .wrapper.footer-cms {
    display: block;
    width: 100%;
    max-width: 100%;
    float: none;
  }

  #footer [class*="col-md-"],
  #footer [class*="col-sm-"] {
    width: 100%;
    max-width: 100%;
    flex: 0 0 100%;
  }

  #footer .bottomcms_img,
  #footer .bottomcms_img span,
  #footer .bottomcms_img strong {
    display: inline;
    width: auto;
    font-size: 0.9375rem;
    line-height: 1.5;
    word-break: normal;
    overflow-wrap: normal;
  }

  #footer .bottomcms_img {
    display: block;
    margin-top: var(--b3-space-2xs);
  }
}

/* --------------------------------------------------------------------------
   « Nos actualités » — le vide au-dessus du titre

   Le panneau centre son contenu sur toute la hauteur de l'écran. Avec un
   visuel qui occupe désormais presque tout le panneau, le reste du vide se
   reportait au-dessus du titre. Le contenu se cale en haut : le titre suit
   la section précédente, l'image suit le titre, et il ne reste rien à
   répartir.
   -------------------------------------------------------------------------- */

.b3-actus.b3-panneau {
  justify-content: flex-start;
  padding-top: var(--b3-space-md);
}

.b3-actus .b3-section__title {
  margin-bottom: var(--b3-space-sm);
}


/* --------------------------------------------------------------------------
   Ajustements de la passe du 27 août
   -------------------------------------------------------------------------- */

/* La réglette de quantité du panier, posée par le script en remplacement du
   champ du noyau. Elle reprend la forme de celle des vignettes ; seule la
   valeur change de nature — un texte, plus un champ de saisie. */
.b3-qty--panier .b3-qty__valeur {
  display: grid;
  place-items: center;
  min-width: 2.2rem;
  font-variant-numeric: tabular-nums;
}

.b3-qty--attente {
  opacity: 0.55;
  pointer-events: none;
}

.b3-qty__step[disabled] {
  opacity: 0.4;
  cursor: default;
}

/* Le titre masqué à l'œil, conservé pour les lecteurs d'écran. */
.b3-section__title.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* Le bandeau enchaîne directement : sans titre, la marge haute n'a plus de
   raison d'être. */
.b3-actus.b3-panneau {
  padding-top: 0;
  min-height: 0;
}

@media (max-width: 767px) {
  /* Le visuel était rogné sur les côtés : un panoramique de 1600 × 719 recadré
     en `cover` sur une hauteur imposée perd la moitié de sa largeur, et le
     texte incrusté dans l'image se retrouve coupé au milieu d'un mot.

     `contain` montre l'image entière. La bande de papier qui reste au-dessus
     et au-dessous vaut mieux qu'une annonce illisible — d'autant que ces
     visuels portent leur texte à l'intérieur. */
  .b3-actus .b3-bandeau img {
    height: auto;
    max-height: 60svh;
    aspect-ratio: auto;
    object-fit: contain;
    background-color: var(--b3-papier);
  }
}

/* Les pavés de partenaires deviennent carrés. Un logo dans un cadre allongé
   flotte ; dans un carré, il se pose. */
.b3-partners__grid a,
a.b3-partner {
  aspect-ratio: 1;
  min-height: 0;
}

@media (min-width: 992px) {
  .b3-partners__grid a,
  a.b3-partner {
    aspect-ratio: 1;
    min-height: 0;
  }
}

@media (max-width: 767px) {
  /* La hero remonte : entre la barre de recherche et le badge, il restait
     deux cent cinquante pixels de jaune vide. Le panneau cesse de centrer son
     contenu — sur un téléphone, centrer verticalement un bloc plus court que
     l'écran ne fait que le repousser vers le bas. */
  .b3-hero.b3-panneau {
    justify-content: flex-start;
    min-height: 0;
  }

  .b3-hero.b3-panneau .b3-hero__inner {
    padding-top: var(--b3-space-2xs);
    padding-bottom: var(--b3-space-lg);
  }
}


/* --------------------------------------------------------------------------
   Les filtres de rayon, sur téléphone

   Un rail horizontal supposait qu'on devine qu'il défile. Avec quatre rayons
   seulement, la question ne se pose plus : ils tiennent empilés, chacun sur sa
   ligne, où l'on voit d'un coup tout ce qui est proposé.
   -------------------------------------------------------------------------- */

@media (max-width: 767px) {
  .b3-filters,
  .b3-filters__groupe {
    display: flex;
    flex-direction: column;
    align-items: stretch;
    gap: var(--b3-space-3xs);
  }

  .b3-filters__rail {
    display: flex;
    flex-direction: column;
    align-items: stretch;
    gap: var(--b3-space-3xs);
    overflow: visible;
  }

  .b3-filters__intitule {
    width: auto;
    margin-bottom: var(--b3-space-3xs);
  }

  /* Chaque rayon prend la largeur : la cible est franche, et le pictogramme
     reste calé à gauche plutôt que de flotter au centre d'un bouton étroit. */
  .b3-filters .b3-filter {
    justify-content: flex-start;
    width: 100%;
    min-height: 46px;
    padding: 0 var(--b3-space-md);
    font-size: 0.8125rem;
  }

  .b3-filters .b3-filter[data-b3-picto]::before {
    margin-right: 0.6em;
    font-size: 1.125rem;
  }
}

/* --------------------------------------------------------------------------
   Les rayons, sur téléphone : repliés derrière « Tout »

   Quatre boutons de plus sous « Tout » et « Meilleures ventes » ouvraient la
   liste sur six lignes d'emblée, avant même de savoir ce qu'on cherche.
   Repliés par défaut, ils s'ouvrent au clic sur « Tout » — un bouton dédié,
   `.b3-filters--rayons-ouvert`, posé par 3b.js : s'en remettre à l'état actif
   du filtre ne marchait pas, « Tout » étant déjà actif au chargement, sans
   qu'aucun clic n'ait eu lieu.

   Sur grand écran, rien de tout ça : la place ne manque pas, les rayons
   restent en permanence dans la barre (comportement par défaut, aucune règle
   nécessaire ici). */
@media (max-width: 767px) {
  .b3-filters__groupe--rayons {
    display: none;
  }

  .b3-filters--rayons-ouvert .b3-filters__groupe--rayons {
    display: flex;
  }
}


/* --------------------------------------------------------------------------
   Le bandeau de services en pied de page

   « Frais de port », « Nos vendeurs » et leurs voisins répétaient ce que le
   pied de page dit déjà, sur une bande de quatre cents pixels que le visiteur
   traversait sans la lire. Retirée.
   -------------------------------------------------------------------------- */

.display-topcolumn .otshippingblock,
.display-topcolumn .shipping-inner,
#footer .otshippingblock,
.otfooterbottomblock .shipping-inner {
  display: none;
}

/* --------------------------------------------------------------------------
   Rupture de stock : un seul badge, pas deux

   La vignette porte déjà la mention en haut à gauche (`.b3-card__flags`,
   voir 04-carte.css). Le paragraphe « Rupture de stock » sous le bouton
   répétait la même information une seconde fois — sur une carte étroite au
   téléphone, la redite se voit plus qu'ailleurs. Le lien « J'en ai besoin ! »
   suffit seul en dessous du badge. Desktop non touché : la carte y a la
   place pour la répétition sans que ça se voie comme un doublon. */
@media (max-width: 767px) {
  .b3-card__oos {
    display: none;
  }
}


/* ===== 16-conseils.css =================================================== */

@charset "UTF-8";
/* ==========================================================================
   Conseils & accords

   Le conseil du comptoir, transposé en ligne. C'est exactement ce que l'audit
   reprochait au site : un catalogue qui montre des bouteilles sans dire
   pourquoi les choisir.

   Trois cartes en aplat d'encre, chacune ouvrant son article en place. Le
   contenu est déjà dans la page : lisible sans script, indexable, et affiché
   sans attente.
   ========================================================================== */

.b3-conseils__grille {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--b3-space-sm);
  margin: 0;
  padding: 0;
  list-style: none;
}

.b3-conseil {
  display: flex;
}

/* La carte entière est le bouton : une cible de la taille du bloc vaut mieux
   qu'un lien de deux mots en bas à gauche. */
.b3-conseil__ouvrir {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--b3-space-2xs);
  width: 100%;
  min-height: 15rem;
  padding: var(--b3-space-md);
  border: 0;
  border-radius: var(--b3-radius);
  background-color: var(--b3-encre);
  font-family: var(--b3-font);
  text-align: left;
  cursor: pointer;
  transition: transform var(--b3-dur-fast) var(--b3-ease);
}

.b3-conseil__ouvrir:hover {
  transform: translateY(-3px);
}

.b3-conseil__ouvrir:focus-visible {
  outline: 3px solid var(--b3-encre);
  outline-offset: 3px;
}

/* L'étiquette annonce le registre — accord, guide, actualité — avant le titre.
   Jaune sur encre : 12:1. */
.b3-conseil__etiquette {
  display: inline-block;
  padding: 0.35em 0.7em;
  border-radius: var(--b3-radius-pill);
  background-color: var(--b3-jaune);
  font-size: 0.6875rem;
  font-weight: 800;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--b3-encre);
}

.b3-conseil__titre {
  font-size: clamp(1.125rem, 1.6vw, 1.375rem);
  font-weight: 800;
  font-stretch: 88%;
  line-height: 1.15;
  color: var(--b3-papier);
  text-wrap: balance;
}

.b3-conseil__chapo {
  max-width: 34ch;
  font-size: 0.9375rem;
  line-height: 1.45;
  color: color-mix(in oklab, var(--b3-papier) 76%, transparent);
}

/* Le libellé de lecture ferme la carte, poussé en bas : la carte garde une
   base commune quelle que soit la longueur du chapô. */
.b3-conseil__lire {
  display: inline-flex;
  align-items: center;
  gap: 0.45em;
  margin-top: auto;
  padding-top: var(--b3-space-2xs);
  font-size: 0.9375rem;
  font-weight: 700;
  color: var(--b3-jaune);
  text-decoration: underline;
  text-underline-offset: 4px;
}

.b3-conseil__ouvrir:hover .b3-conseil__lire span {
  transform: translateX(3px);
}

.b3-conseil__lire span {
  transition: transform var(--b3-dur-fast) var(--b3-ease);
}

/* --------------------------------------------------------------------------
   L'article
   -------------------------------------------------------------------------- */

.b3-article {
  width: min(46rem, calc(100vw - 2rem));
  max-height: 88vh;
  padding: 0;
  border: 0;
  border-radius: var(--b3-radius-lg);
  background-color: var(--b3-papier);
  color: var(--b3-encre);
}

.b3-article::backdrop {
  background-color: color-mix(in oklab, var(--b3-encre) 68%, transparent);
}

.b3-article__inner {
  padding: var(--b3-space-lg);
}

.b3-article__tete {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--b3-space-sm);
  margin-bottom: var(--b3-space-sm);
}

.b3-article__etiquette {
  display: inline-block;
  margin: 0;
  padding: 0.35em 0.7em;
  border-radius: var(--b3-radius-pill);
  background-color: var(--b3-jaune);
  font-size: 0.6875rem;
  font-weight: 800;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--b3-encre);
}

.b3-article__fermer {
  flex: none;
  display: grid;
  place-items: center;
  width: 44px;
  height: 44px;
  border: 0;
  border-radius: 50%;
  background-color: transparent;
  font-size: 1.6rem;
  line-height: 1;
  color: var(--b3-encre);
  cursor: pointer;
}

.b3-article__fermer:hover {
  background-color: var(--b3-papier-2);
}

.b3-article__titre {
  margin: 0 0 var(--b3-space-md);
  font-size: clamp(1.5rem, 3vw, 2.125rem);
  font-weight: 800;
  font-stretch: 80%;
  line-height: 1.08;
  letter-spacing: -0.015em;
  text-wrap: balance;
}

/* Le corps de texte est borné à la longueur de ligne lisible fixée par
   DESIGN.md : au-delà, l'œil perd la ligne suivante. */
.b3-article__corps {
  max-width: 62ch;
  font-size: 1.0625rem;
  line-height: 1.65;
}

/* La couleur est posée explicitement : sans elle, les paragraphes héritaient
   d'un gris du thème et se lisaient plus pâles que les listes voisines, alors
   qu'ils portent le même propos. */
.b3-article__corps p,
.b3-article__corps li {
  margin: 0 0 var(--b3-space-sm);
  color: var(--b3-encre);
}

.b3-article__corps ul,
.b3-article__corps ol {
  margin: 0 0 var(--b3-space-sm);
  padding-left: 1.4em;
}

.b3-article__corps li {
  margin-bottom: var(--b3-space-2xs);
}

.b3-article__corps li::marker {
  font-weight: 800;
  color: var(--b3-encre-douce);
}

.b3-article__corps strong {
  font-weight: 800;
}

.b3-article__pied {
  display: flex;
  flex-wrap: wrap;
  gap: var(--b3-space-2xs);
  margin-top: var(--b3-space-md);
  padding-top: var(--b3-space-md);
  border-top: 1.5px solid var(--b3-trait);
}

/* --------------------------------------------------------------------------
   Adaptations
   -------------------------------------------------------------------------- */

@media (max-width: 991px) {
  .b3-conseils__grille {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

@media (max-width: 639px) {
  /* Neuf cartes empilées font neuf écrans de défilement avant la suite de la
     page : personne ne descend jusqu'au bout. Elles deviennent un rail
     horizontal — le geste de balayage rend visible qu'il y en a d'autres, ce
     qu'une pile ne dit jamais.

     `scroll-snap` cale chaque carte au bord gauche : on s'arrête sur une
     carte, jamais entre deux. */
  .b3-conseils__grille {
    display: grid;
    grid-auto-flow: column;
    grid-auto-columns: 78%;
    grid-template-columns: none;
    gap: var(--b3-space-sm);
    overflow-x: auto;
    scroll-snap-type: x mandatory;
    scroll-padding-inline: var(--b3-space-sm);
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;

    /* Le rail va d'un bord à l'autre de l'écran, mais son contenu reste
       aligné sur la marge du texte : une carte qui commence au ras du bord
       se lit comme un défaut de mise en page. */
    margin-inline: calc(50% - 50vw);
    padding-inline: var(--b3-space-sm);
    width: 100vw;
    max-width: 100vw;
  }

  .b3-conseils__grille::-webkit-scrollbar {
    display: none;
  }

  .b3-conseil {
    scroll-snap-align: start;
  }

  .b3-conseil__ouvrir {
    min-height: 0;
  }

  /* Sur un téléphone, l'article prend l'écran : une fenêtre centrée y perd
     plus de place en marges qu'elle n'en donne au texte. */
  .b3-article {
    width: 100vw;
    max-width: 100vw;
    max-height: 100dvh;
    height: 100dvh;
    margin: 0;
    border-radius: 0;
  }

  .b3-article__inner {
    padding: var(--b3-space-md);
  }
}

/* La mention de langue n'apparaît que là où le corps de l'article n'est pas
   dans la langue de la page — l'espagnol et l'italien reçoivent la version
   anglaise. Le dire vaut mieux que le masquer, ou que de le faire passer pour
   une traduction. */
.b3-article__mention {
  margin: 0 0 var(--b3-space-sm);
  font-size: 0.75rem;
  font-weight: 800;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--b3-jaune);
}


/* --------------------------------------------------------------------------
   Neuf sujets plutôt que trois

   Le sprint v9 ajoute six articles. À trois cartes, une rangée suffisait ; à
   neuf, la grille de trois colonnes donne trois rangées régulières sur un
   écran de bureau — la disposition la plus lisible pour un jeu de sujets de
   même nature.
   -------------------------------------------------------------------------- */

@media (min-width: 992px) {
  .b3-conseils__grille {
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: var(--b3-space-md);
  }
}

/* Les tableaux de données des nouveaux articles — températures, prix. Ils
   portent l'essentiel de ce qui rend ces pages citables : un moteur reprend un
   tableau, il ne reprend pas une opinion. */
.b3-article__tableau {
  width: 100%;
  border-collapse: collapse;
  margin: var(--b3-space-sm) 0;
  font-size: 0.9375rem;
}

.b3-article__tableau th {
  text-align: left;
  padding: 0.4em 0.6em;
  border-bottom: 2px solid var(--b3-encre);
  font-size: 0.75rem;
  font-weight: 800;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}

.b3-article__tableau td {
  padding: 0.45em 0.6em;
  border-bottom: 1px solid var(--b3-trait);
}

.b3-article__tableau tr:last-child td {
  border-bottom: 0;
}

/* La colonne de droite porte des valeurs : elles s'alignent et se comparent. */
.b3-article__tableau td:last-child {
  font-variant-numeric: tabular-nums;
  font-weight: 700;
  white-space: nowrap;
}


/* ===== 17-brasserie.css ================================================== */

/* ==========================================================================
   La brasserie — une bière par écran

   Chaque bière tient la hauteur de l'écran sur son propre aplat. Le défilement
   cale d'une section à l'autre : on s'arrête sur une bière, jamais entre deux.

   L'aplat vient du style — bleu pour une IPA, sombre pour un stout, cuivré
   pour une ambrée. Les deux teintes arrivent en variables posées sur la
   section : `--biere-fond` et `--biere-encre`, calculées côté serveur. Toute
   la feuille s'y adosse, ce qui évite une règle par bière.
   ========================================================================== */

.b3-brasserie {
  scroll-snap-type: y proximity;
}

/* --------------------------------------------------------------------------
   L'ouverture et la clôture
   -------------------------------------------------------------------------- */

.b3-brasserie__intro,
.b3-brasserie__fin {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--b3-space-sm);
  min-height: 72svh;
  padding: var(--b3-space-2xl) var(--b3-space-md);
  scroll-snap-align: start;
  text-align: center;
  background-color: var(--b3-jaune);
  color: var(--b3-encre);
}

.b3-brasserie__fin {
  background-color: var(--b3-encre);
  color: var(--b3-papier);
}

.b3-brasserie__sur {
  margin: 0;
  font-size: 0.8125rem;
  font-weight: 800;
  letter-spacing: 0.16em;
  text-transform: uppercase;
}

.b3-brasserie__fin .b3-brasserie__sur {
  color: var(--b3-jaune);
}

.b3-brasserie__titre {
  margin: 0;
  max-width: 18ch;
  font-size: clamp(2.5rem, 8vw, 5.5rem);
  font-weight: 800;
  font-stretch: 78%;
  letter-spacing: -0.02em;
  line-height: 0.98;
}

.b3-brasserie__chapo {
  margin: 0;
  max-width: 34ch;
  font-size: clamp(1rem, 2vw, 1.25rem);
  font-weight: 500;
}

/* Une invitation à descendre, qui respire. Sans elle, un premier écran plein
   se lit comme une page entière et l'on ne cherche pas la suite. */
.b3-brasserie__guide {
  margin: var(--b3-space-lg) 0 0;
  font-size: 0.75rem;
  font-weight: 800;
  letter-spacing: 0.12em;
  text-transform: uppercase;
}

.b3-brasserie__guide::after {
  content: "↓";
  display: block;
  margin-top: 0.4em;
  font-size: 1.5rem;
  animation: b3-descendre 2.2s var(--b3-ease) infinite;
}

@keyframes b3-descendre {
  0%, 100% { transform: translateY(0); opacity: 0.5; }
  50%      { transform: translateY(6px); opacity: 1; }
}

@media (prefers-reduced-motion: reduce) {
  .b3-brasserie__guide::after { animation: none; }
}

/* --------------------------------------------------------------------------
   Une bière
   -------------------------------------------------------------------------- */

.b3-biere {
  position: relative;
  display: grid;
  place-items: center;
  min-height: 100svh;
  padding: var(--b3-space-xl) var(--b3-space-md);
  scroll-snap-align: start;
  background-color: var(--biere-fond, var(--b3-jaune));
  color: var(--biere-encre, var(--b3-encre));
}

/* Le rang passe à gauche : la pastille de prix occupe désormais le coin droit,
   et les deux s'y superposaient. */
.b3-biere__rang {
  position: absolute;
  top: var(--b3-space-md);
  left: var(--b3-space-lg);
  margin: 0;
  font-size: clamp(1.5rem, 3vw, 2.25rem);
  font-weight: 900;
  font-variant-numeric: tabular-nums;
  opacity: 0.42;
}

.b3-biere__rang span {
  font-size: 0.5em;
  font-weight: 700;
}

.b3-biere__inner {
  display: grid;
  grid-template-columns: minmax(0, 0.92fr) minmax(0, 1.08fr);
  grid-template-areas:
    "visuel fiche"
    "visuel achat";
  align-items: center;
  gap: var(--b3-space-lg) var(--b3-space-xl);
  width: min(100%, 1180px);
}

/* --------------------------------------------------------------------------
   La canette
   -------------------------------------------------------------------------- */

/* Pas de cadre autour de la canette.

   Elle en portait un — panneau clair, coin arrondi, ombre portée — qui
   dupliquait celui du texte : deux boîtes de même facture de part et d'autre
   de l'écran, et la photographie ramenée au rang d'illustration encadrée. La
   canette se pose directement sur l'aplat, comme sur la maquette.

   L'ombre reste, portée par l'image elle-même : elle décolle la canette du
   fond sans lui dessiner de limite. */
.b3-biere__visuel {
  grid-area: visuel;
  display: grid;
  place-items: center;
  margin: 0;
  padding: 0;
  background: none;
}



/* Le détourage automatique (`outils/detourer-bieres.py`, fond transparent par
   diffusion depuis les bords) donnait des contours grossiers sur certaines
   canettes — signalé en prod le 11 septembre 2026. On revient à la photo
   d'origine, complète, avec son propre fond d'studio neutre : posée dans un
   conteneur carré à coins arrondis plutôt que détourée, elle n'a plus de bord
   à rater. Le carré prend l'aplat de la section en cadre plutôt qu'en fond
   direct — la couleur reste « logique » (celle de la canette) sans que la
   photo n'ait besoin d'un fond transparent pour s'y fondre. */
.b3-biere__visuel img,
.b3-biere__visuel picture {
  display: block;
  width: 100%;
  height: auto;
  max-height: 68svh;
  max-width: 560px;
  aspect-ratio: 1;
  object-fit: cover;
  border-radius: var(--b3-radius-lg, 1.5rem);
  overflow: hidden;
}

/* L'ombre se pose sous le cadre carré, pas sous une forme détourée. */
.b3-biere__visuel {
  filter: drop-shadow(0 20px 30px oklch(0 0 0 / 0.28));
}

/* --------------------------------------------------------------------------
   Le récit
   -------------------------------------------------------------------------- */

.b3-biere__fiche {
  grid-area: fiche;
  padding: var(--b3-space-lg) var(--b3-space-lg) var(--b3-space-md);
  border-radius: var(--b3-radius-lg);
  background-color: color-mix(in oklab, #fff 92%, var(--biere-fond, #fff));
  color: var(--b3-encre);
}

.b3-biere__nom {
  margin: 0 0 var(--b3-space-2xs);
  font-size: clamp(1.75rem, 3.4vw, 2.75rem);
  font-weight: 800;
  font-stretch: 84%;
  letter-spacing: -0.015em;
  line-height: 1.02;
}

/* Le style en pastille, dans la teinte de la bière : c'est le seul endroit où
   la couleur de fond revient sur le panneau clair, et elle y fait le lien. */
.b3-biere__style {
  display: inline-block;
  margin: 0 0 var(--b3-space-sm);
  padding: 0.35em 0.9em;
  border-radius: var(--b3-radius-pill);
  background-color: var(--biere-fond, var(--b3-jaune));
  color: var(--biere-encre, var(--b3-encre));
  font-size: clamp(0.9375rem, 1.6vw, 1.125rem);
  font-weight: 800;
}

/* Le texte en encre pleine, non en gris.

   Il héritait d'une teinte adoucie, héritée des chapôs de carte : sur un
   panneau clair qui ne porte que lui, ce gris se lisait comme une note
   secondaire alors que c'est le seul récit de la page.

   Les mots que la brasserie met en avant passent en gras. C'est le balisage
   du texte qui le décide, pas la feuille de styles — elle se contente de lui
   donner un poids et l'encre. */
.b3-biere__texte {
  font-size: clamp(0.9375rem, 1.45vw, 1.125rem);
  line-height: 1.58;
  color: var(--b3-encre);
}

.b3-biere__texte strong,
.b3-biere__texte b {
  font-weight: 800;
  color: var(--b3-encre);
}

.b3-biere__texte p {
  margin: 0 0 0.7em;
}

.b3-biere__texte p:last-child {
  margin-bottom: 0;
}

/* Les trois repères de brassage, séparés par un filet dans la teinte. */
.b3-biere__reperes {
  display: flex;
  align-items: center;
  gap: var(--b3-space-md);
  margin: var(--b3-space-md) 0 0;
  padding: var(--b3-space-sm) 0 0;
  border-top: 1px solid color-mix(in oklab, var(--b3-encre) 12%, transparent);
  list-style: none;
}

.b3-biere__reperes li {
  position: relative;
  font-size: 1.75rem;
  line-height: 1;
}

.b3-biere__reperes li + li::before {
  content: "";
  position: absolute;
  left: calc(var(--b3-space-md) / -2);
  top: 10%;
  bottom: 10%;
  width: 2px;
  background-color: var(--biere-fond, var(--b3-jaune));
}

/* --------------------------------------------------------------------------
   L'achat
   -------------------------------------------------------------------------- */

.b3-biere__achat {
  grid-area: achat;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--b3-space-sm);
}

.b3-biere__prix {
  margin: 0;
  font-size: clamp(1.5rem, 2.6vw, 2rem);
  font-weight: 900;
  font-variant-numeric: tabular-nums;
}

.b3-biere__form {
  display: flex;
  align-items: center;
  gap: var(--b3-space-sm);
  margin: 0;
}

.b3-biere__ajouter {
  display: inline-flex;
  align-items: center;
  gap: 0.6em;
  min-height: 56px;
  padding: 0 var(--b3-space-lg);
  border: 0;
  border-radius: var(--b3-radius-pill);
  background-color: var(--b3-encre);
  color: var(--b3-papier);
  font-family: inherit;
  font-size: 1.0625rem;
  font-weight: 800;
  cursor: pointer;
  transition: transform var(--b3-dur-fast) var(--b3-ease);
}

.b3-biere__ajouter:hover {
  transform: translateY(-2px);
}

@media (prefers-reduced-motion: reduce) {
  .b3-biere__ajouter:hover { transform: none; }
}

.b3-biere__panier {
  width: 22px;
  height: 22px;
  background-color: currentColor;
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='9' cy='21' r='1'/%3E%3Ccircle cx='20' cy='21' r='1'/%3E%3Cpath d='M1 1h4l2.7 13.4a2 2 0 0 0 2 1.6h9.7a2 2 0 0 0 2-1.6L23 6H6'/%3E%3C/svg%3E") center / contain no-repeat;
  mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='9' cy='21' r='1'/%3E%3Ccircle cx='20' cy='21' r='1'/%3E%3Cpath d='M1 1h4l2.7 13.4a2 2 0 0 0 2 1.6h9.7a2 2 0 0 0 2-1.6L23 6H6'/%3E%3C/svg%3E") center / contain no-repeat;
}

/* Sur un aplat sombre, l'encre du bouton se confondrait avec le fond. */
.b3-biere[style*="#2b2320"] .b3-biere__ajouter {
  background-color: var(--b3-papier);
  color: var(--b3-encre);
}

/* --------------------------------------------------------------------------
   Adaptations
   -------------------------------------------------------------------------- */

@media (max-width: 900px) {
  .b3-biere {
    /* Le plein écran cède : une canette, un texte et un achat empilés ne
       tiennent pas dans une hauteur de téléphone sans que tout rétrécisse. */
    min-height: 0;
    padding-block: var(--b3-space-2xl);
    scroll-snap-align: none;
  }

  .b3-biere__inner {
    grid-template-columns: minmax(0, 1fr);
    grid-template-areas:
      "visuel"
      "fiche"
      "achat";
    gap: var(--b3-space-md);
  }

  .b3-biere__visuel {
    padding: var(--b3-space-md);
  }

  .b3-biere__visuel img {
    max-height: 42svh;
  }

  .b3-biere__rang {
    top: var(--b3-space-sm);
    left: var(--b3-space-md);
  }

  .b3-biere__achat {
    justify-content: space-between;
  }

  .b3-brasserie {
    scroll-snap-type: none;
  }
}

@media (max-width: 480px) {
  .b3-biere__form {
    flex: 1 1 100%;
    justify-content: space-between;
  }

  .b3-biere__ajouter {
    flex: 1 1 auto;
    justify-content: center;
  }
}


/* --------------------------------------------------------------------------
   Pleine largeur

   Mesuré : le contenu de la page vit dans un `div.left-column.col-sm-8` large
   de 951 px sur un écran de 1440, avec un conteneur borné à 1300 au-dessus.
   Ce n'était donc pas un débord à provoquer mais une colonne à libérer — ma
   première tentative sortait la brasserie par marge négative et la décalait
   de cent cinquante pixels à gauche tout en laissant la bande de papier à
   droite : deux défauts pour une seule cause mal nommée.

   `:has()` permet de ne toucher ces conteneurs que sur cette page. Il est
   pris en charge par Safari depuis 15.4, vérifié sur le moteur de rendu.
   -------------------------------------------------------------------------- */

.b3-brasserie {
  width: 100%;
  max-width: none;
  margin-inline: 0;
}

#wrapper .container:has(.b3-brasserie),
#wrapper .wrapper-inner:has(.b3-brasserie),
#wrapper .left-column:has(.b3-brasserie),
#wrapper #content-wrapper:has(.b3-brasserie) {
  width: 100%;
  max-width: none;
  flex: 0 0 100%;
  margin-inline: 0;
  padding-inline: 0;
}

section.wrapper:has(.b3-brasserie) {
  padding-block: 0;
}

/* Le fil d'Ariane et le titre de catégorie n'ont pas leur place ici : la page
   porte son propre titre, et le fil doublonne avec le menu. */
#wrapper:has(.b3-brasserie) .breadcumb_outer,
#wrapper:has(.b3-brasserie) #js-product-list-header,
#wrapper:has(.b3-brasserie) .block-category,
body:has(.b3-brasserie) .breadcumb_outer {
  display: none;
}

/* Le prix reprend l'encre de la bière : il flottait en gris hérité. */
.b3-biere__prix {
  color: var(--biere-encre, var(--b3-encre));
}


/* --------------------------------------------------------------------------
   La réglette à la hauteur du bouton

   Les deux commandes se suivent sur la même ligne : une réglette de 44 px à
   côté d'un bouton de 56 donne une ligne bancale, où l'œil lit deux registres
   là où il n'y a qu'un geste.
   -------------------------------------------------------------------------- */

.b3-biere .b3-qty {
  height: 56px;
  padding: 5px;
}

.b3-biere .b3-qty__step {
  flex: 0 0 46px;
  width: 46px;
  min-width: 46px;
  height: 46px;
  font-size: 1.125rem;
}

.b3-biere .b3-qty__input {
  flex: 0 0 42px;
  width: 42px;
  min-width: 42px;
  height: 46px;
  font-size: 1rem;
}

/* --------------------------------------------------------------------------
   Le passage d'une bière à l'autre

   Chaque section colle en haut de l'écran pendant que la suivante remonte
   par-dessus. On ne défile plus « à travers » une liste : on tourne les pages
   d'un catalogue, une couleur chassant l'autre.

   Le procédé repose sur `position: sticky` et un empilement décroissant. Rien
   n'est animé en JavaScript : le navigateur compose, et cela reste fluide sur
   un téléphone d'entrée de gamme là où un écouteur de défilement ne le serait
   pas.
   -------------------------------------------------------------------------- */

@media (min-width: 901px) and (prefers-reduced-motion: no-preference) {
  .b3-brasserie {
    /* Le calage cède la place à l'empilement : les deux se disputent le
       contrôle du défilement et produisent des à-coups. */
    scroll-snap-type: none;
  }

  .b3-biere {
    position: sticky;
    top: 0;
    /* Chaque section couvre la précédente : sans fond opaque déclaré, on
       verrait les deux à la fois. L'aplat est déjà là, on le rappelle. */
    background-color: var(--biere-fond, var(--b3-jaune));
  }

  /* Pas d'animation d'entrée liée au défilement.

     Une première version faisait apparaître le contenu au fil du défilement,
     par `animation-timeline: view()`. Deux réglages successifs n'ont pas suffi
     à la rendre fiable : sur les premières sections, déjà visibles au
     chargement, elle laissait un aplat délavé et un texte fantôme — l'élément
     n'ayant aucune progression à parcourir restait à un état intermédiaire.

     L'empilement seul produit déjà l'effet demandé : une couleur chasse
     l'autre. Ajouter une seconde mise en scène par-dessus n'apportait rien
     qu'un risque d'affichage incomplet, et c'est ce risque qui s'est réalisé. */

  /* La dernière ne colle pas : elle doit libérer le pied de page. */
  .b3-biere:last-of-type {
    position: relative;
  }
}

/* Mouvement réduit : l'empilement disparaît, la page redevient une suite de
   sections. Rien ne se perd — seule la mise en scène s'efface. */
@media (prefers-reduced-motion: reduce) {
  .b3-biere {
    position: relative;
  }
}


/* --------------------------------------------------------------------------
   Le prix en pastille

   Il vivait sous la fiche, à côté de la réglette, où il se lisait après tout
   le reste. C'est pourtant la seconde information qu'on cherche, juste après
   le nom : elle monte au coin du panneau.
   -------------------------------------------------------------------------- */

.b3-biere__badge {
  position: absolute;
  top: var(--b3-space-lg);
  right: var(--b3-space-lg);
  z-index: 2;
  display: inline-flex;
  /* Colonne, pas ligne : le multiplicateur s'empile sous le prix plutôt que
     d'élargir la pastille. Ancrée par `right`, une pastille qui s'élargit
     grandit vers la GAUCHE — donc vers le titre, posé juste à côté sans
     marge de sécurité prévue pour ce cas. Constaté en prod le 11 septembre
     2026 : à partir de « × 9 », la pastille chevauchait un titre court
     comme « Back to Berlin Pils ». Empiler en hauteur laisse le titre
     tranquille quelle que soit la longueur du nombre. */
  flex-direction: column;
  align-items: center;
  gap: 0.1em;
  margin: 0;
  padding: 0.5em 1em;
  border-radius: var(--b3-radius-lg, 1.2em);
  background-color: var(--b3-encre);
  color: var(--b3-papier);
  font-size: clamp(1.125rem, 2vw, 1.5rem);
  font-weight: 900;
  font-variant-numeric: tabular-nums;
  box-shadow: 0 10px 24px oklch(0 0 0 / 0.22);
}

/* Le multiplicateur, quand la quantité dépasse l'unité. Sans lui, le prix
   change et l'on doute d'avoir compris ce qu'il recouvre. Sur sa propre
   ligne : voir la note ci-dessus sur `.b3-biere__badge`. */
.b3-biere__badge[data-b3-quantite]:not([data-b3-quantite=""])::after {
  content: "× " attr(data-b3-quantite);
  display: block;
  font-size: 0.62em;
  font-weight: 700;
  line-height: 1;
  text-align: center;
  opacity: 0.72;
}

/* Sur un aplat sombre, la pastille d'encre disparaîtrait. */
.b3-biere[style*="#2b2320"] .b3-biere__badge {
  background-color: var(--b3-papier);
  color: var(--b3-encre);
}

@media (max-width: 900px) {
  .b3-biere__badge {
    top: var(--b3-space-sm);
    right: var(--b3-space-md);
    font-size: 1.125rem;
  }
}


/* --------------------------------------------------------------------------
   Le film d'ouverture

   La même séquence que la carte d'accueil : des canettes au ralenti. Elle
   occupe tout le fond de l'ouverture, le texte se posant dessus.

   Un voile d'encre sépare les deux. Sans lui, un titre clair sur une image
   claire devient illisible dès que le plan change — et sur un film, le plan
   change toujours.
   -------------------------------------------------------------------------- */

.b3-brasserie__intro {
  position: relative;
  overflow: hidden;
  min-height: 82svh;
  color: var(--b3-papier);
  background-color: var(--b3-encre);
}

.b3-brasserie__film {
  position: absolute;
  inset: 0;
  z-index: 0;
  display: block;
}

.b3-brasserie__film video {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.b3-brasserie__film::after {
  content: "";
  position: absolute;
  inset: 0;
  background-image: linear-gradient(
    to bottom,
    color-mix(in oklab, var(--b3-encre) 58%, transparent) 0%,
    color-mix(in oklab, var(--b3-encre) 38%, transparent) 45%,
    color-mix(in oklab, var(--b3-encre) 72%, transparent) 100%
  );
}

/* Le texte passe devant le film. */
.b3-brasserie__intro > *:not(.b3-brasserie__film) {
  position: relative;
  z-index: 1;
}

/* Les couleurs sont déclarées ici et non héritées. Le titre reprenait l'encre
   de la règle générale des ouvertures — encre sur un fond devenu sombre, donc
   invisible. Un texte posé sur un film ne doit jamais dépendre d'un héritage :
   le fond change à chaque plan, la couleur doit être décidée. */
.b3-brasserie__intro .b3-brasserie__sur {
  color: var(--b3-jaune);
}

.b3-brasserie__intro .b3-brasserie__titre,
.b3-brasserie__intro .b3-brasserie__chapo,
.b3-brasserie__intro .b3-brasserie__guide {
  color: var(--b3-papier);
  text-shadow: 0 2px 24px oklch(0 0 0 / 0.55);
}


/* --------------------------------------------------------------------------
   Reprises de la passe du 27 août — soir
   -------------------------------------------------------------------------- */

/* L'empilement descend à 768 px. Il ne valait qu'au-delà de 901, si bien qu'un
   iPad en portrait — 820 points — n'en voyait rien. Le seuil n'a pas de raison
   d'être celui-là : l'effet demande de la hauteur, pas de la largeur, et une
   tablette en a autant qu'un écran de bureau. */
@media (min-width: 768px) and (prefers-reduced-motion: no-preference) {
  .b3-biere {
    position: sticky;
    top: 0;
    background-color: var(--biere-fond, var(--b3-jaune));
  }

  .b3-biere:last-of-type {
    position: relative;
  }

  .b3-brasserie {
    scroll-snap-type: none;
  }
}

/* La bande blanche entre l'en-tête et l'ouverture : le gabarit de catégorie
   pose un rembourrage haut sur son conteneur, qui laissait passer le papier de
   la page entre deux aplats sombres. */
section.wrapper:has(.b3-brasserie) {
  padding-top: 0;
  margin-top: 0;
}

body:has(.b3-brasserie) .breadcumb_outer,
body:has(.b3-brasserie) #content-wrapper {
  padding-top: 0;
  margin-top: 0;
}

/* Le titre en papier plein, le chapô en gras. Sur un film, un chapô en graisse
   normale se perd dès que le plan s'éclaircit. */
.b3-brasserie__intro .b3-brasserie__titre {
  color: var(--b3-papier);
}

.b3-brasserie__intro .b3-brasserie__chapo {
  color: var(--b3-papier);
  font-weight: 800;
  font-size: clamp(1.0625rem, 2.1vw, 1.375rem);
}


/* Le bouton pendant l'appel : il se retire sans disparaître, pour qu'on voie
   qu'il a été pressé sans que la mise en page bouge. */
.b3-biere__ajouter--attente {
  opacity: 0.62;
  cursor: progress;
}

.b3-biere__ajouter[disabled] {
  pointer-events: none;
}

/* La fenêtre de confirmation arrive en douceur plutôt qu'en surgissant. */
#blockcart-modal.b3-cart-modal .b3-cart-modal__panneau {
  animation: b3-modal-entree 260ms var(--b3-ease) both;
}

@keyframes b3-modal-entree {
  from { opacity: 0; transform: translate3d(0, 14px, 0) scale(0.985); }
  to   { opacity: 1; transform: none; }
}

@media (prefers-reduced-motion: reduce) {
  #blockcart-modal.b3-cart-modal .b3-cart-modal__panneau {
    animation: none;
  }
}


/* --------------------------------------------------------------------------
   Reprises du 28 août
   -------------------------------------------------------------------------- */

/* La pastille de prix rejoint la fiche. Posée au coin de l'écran, elle
   flottait loin du produit ; ici elle se lit avec le nom et le style, là où la
   décision se prend. */
.b3-biere__fiche {
  position: relative;
}

.b3-biere__badge {
  position: absolute;
  top: var(--b3-space-lg);
  right: var(--b3-space-lg);
  z-index: 2;
}

/* La canette gagne en présence : c'est le sujet de l'écran, elle n'a pas à
   partager la largeur à parts égales avec le texte.
   
   Cette règle est bornée au-delà de 900 px. Posée sans condition, elle passait
   après le repli mobile qui met tout sur une colonne et le défaisait : le
   téléphone se retrouvait avec deux colonnes de cent soixante pixels, une
   canette minuscule et un texte à trois mots par ligne. */
@media (min-width: 901px) {
  .b3-biere__inner {
    grid-template-columns: minmax(0, 1.05fr) minmax(0, 0.95fr);
  }

  .b3-biere__visuel img,
  .b3-biere__visuel picture {
    max-height: 78svh;
  }

  /* Le nom cède la place à la pastille de prix. */
  .b3-biere__nom {
    padding-right: 6.5rem;
  }
}

@media (max-width: 900px) {
  .b3-biere__visuel img,
  .b3-biere__visuel picture {
    max-height: 52svh;
  }

  .b3-biere__badge {
    top: var(--b3-space-md);
    right: var(--b3-space-md);
  }
}




/* ==========================================================================
   La brasserie sur téléphone

   Une colonne, une canette qui occupe la largeur, un texte qui respire. Les
   réglages de bureau — deux colonnes, réserve pour la pastille, hauteur en
   svh — n'ont rien à y faire et sont désormais bornés au-delà de 900 px.
   ========================================================================== */

@media (max-width: 900px) {
  .b3-biere {
    padding: var(--b3-space-xl) var(--b3-space-sm);
  }

  .b3-biere__inner {
    grid-template-columns: minmax(0, 1fr);
    grid-template-areas:
      "visuel"
      "fiche"
      "achat";
    gap: var(--b3-space-md);
    width: 100%;
  }

  /* La canette prend la largeur. Elle se retrouvait à cent soixante pixels
     dans une demi-colonne : sur une page dont c'est le seul sujet, c'est la
     dernière chose à rétrécir. */
  .b3-biere__visuel {
    width: 100%;
  }

  .b3-biere__visuel img,
  .b3-biere__visuel picture {
    width: 100%;
    max-height: 46svh;
    object-fit: contain;
  }

  .b3-biere__fiche {
    padding: var(--b3-space-md);
  }

  /* La pastille sort du flux du titre plutôt que de se poser dessus : sur une
     fiche étroite, elle recouvrait les premiers mots du nom. */
  .b3-biere__badge {
    position: static;
    display: inline-flex;
    margin-bottom: var(--b3-space-2xs);
    font-size: 1.0625rem;
  }

  .b3-biere__nom {
    padding-right: 0;
    font-size: clamp(1.5rem, 6.5vw, 2rem);
  }

  .b3-biere__texte {
    font-size: 0.9375rem;
    line-height: 1.5;
  }

  .b3-biere__reperes {
    gap: var(--b3-space-sm);
    margin-top: var(--b3-space-sm);
  }

  .b3-biere__reperes li {
    font-size: 1.375rem;
  }

  /* L'achat : le prix a rejoint la fiche, il ne reste que la commande. */
  .b3-biere__achat {
    justify-content: stretch;
  }

  .b3-biere__form {
    flex: 1 1 100%;
    justify-content: space-between;
    gap: var(--b3-space-xs);
  }

  .b3-biere .b3-qty {
    height: 50px;
    flex: 0 0 auto;
  }

  .b3-biere .b3-qty__step {
    flex: 0 0 40px;
    width: 40px;
    min-width: 40px;
    height: 40px;
  }

  .b3-biere .b3-qty__input {
    flex: 0 0 36px;
    width: 36px;
    min-width: 36px;
    height: 40px;
  }

  .b3-biere__ajouter {
    flex: 1 1 auto;
    justify-content: center;
    min-height: 50px;
    padding: 0 var(--b3-space-md);
    font-size: 1rem;
  }

  /* L'ouverture se resserre : le film y occupait un écran entier avant que la
     première bière n'apparaisse. */
  .b3-brasserie__intro {
    min-height: 62svh;
    padding: var(--b3-space-xl) var(--b3-space-sm);
  }

  .b3-brasserie__fin {
    min-height: 0;
    padding: var(--b3-space-2xl) var(--b3-space-sm);
  }
}

@media (max-width: 480px) {
  .b3-biere__visuel img,
  .b3-biere__visuel picture {
    max-height: 38svh;
  }
}


/* ===== 17-tunnel.css ===================================================== */

@charset "UTF-8";
/* ==========================================================================
   Tunnel de commande

   Quatre étapes : informations, adresses, livraison, paiement. C'est le
   parcours où l'on saisit une adresse et un moyen de paiement, et c'était le
   dernier resté au gabarit du thème — avec ses libellés de champs en #999 sur
   blanc, soit 2.8:1. Sous le seuil AA, sur l'écran où une faute de frappe
   coûte une livraison.

   Rien n'est réécrit du fonctionnement : les étapes, leur validation et leur
   enchaînement restent ceux du noyau, qui portent aussi les mentions
   obligatoires liées à la vente d'alcool.
   ========================================================================== */

body.page-order #content-wrapper,
body.page-checkout #content-wrapper {
  max-width: 62rem;
  margin-inline: auto;
}

/* --------------------------------------------------------------------------
   Les étapes

   Chaque étape est une carte : on doit voir d'un coup d'œil où l'on en est,
   ce qui est fait, ce qui reste. Le numéro est traité comme un jeton, pas
   comme un préfixe de texte.
   -------------------------------------------------------------------------- */

body.page-order .checkout-step {
  margin-bottom: var(--b3-space-sm);
  padding: 0;
  border: 1.5px solid var(--b3-trait);
  border-radius: var(--b3-radius);
  background-color: var(--b3-papier);
  box-shadow: none;
}

body.page-order .checkout-step .step-title {
  display: flex;
  align-items: center;
  gap: var(--b3-space-2xs);
  margin: 0;
  padding: var(--b3-space-sm) var(--b3-space-md);
  font-size: 1.125rem;
  font-weight: 800;
  font-stretch: 90%;
  letter-spacing: 0.01em;
  color: var(--b3-encre);
  cursor: pointer;
}

body.page-order .checkout-step .step-number {
  display: grid;
  place-items: center;
  flex: none;
  width: 2rem;
  height: 2rem;
  border-radius: 50%;
  background-color: var(--b3-papier-2);
  font-size: 0.9375rem;
  font-weight: 800;
  color: var(--b3-encre);
}

/* L'étape courante prend l'encre : c'est le seul repère qui dit où l'on se
   trouve dans un tunnel où tout le reste est replié. */
body.page-order .checkout-step.-current {
  border-color: var(--b3-encre);
  border-width: 2px;
}

body.page-order .checkout-step.-current .step-number {
  background-color: var(--b3-jaune);
}

/* Étape franchie : la coche double le trait, l'information ne tient pas à la
   seule couleur. */
body.page-order .checkout-step.-complete .step-number {
  background-color: var(--b3-encre);
  color: transparent;
  position: relative;
}

body.page-order .checkout-step.-complete .step-number::after {
  content: "";
  position: absolute;
  inset: 22%;
  background-color: var(--b3-jaune);
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='3.4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M4 12.5l5.2 5.2L20 7'/%3E%3C/svg%3E") center / contain no-repeat;
  mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='3.4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M4 12.5l5.2 5.2L20 7'/%3E%3C/svg%3E") center / contain no-repeat;
}

body.page-order .checkout-step .content {
  padding: 0 var(--b3-space-md) var(--b3-space-md);
}

/* --------------------------------------------------------------------------
   Formulaires

   Le point qui rendait le tunnel désagréable : des libellés à 2.8:1 sur des
   champs sans contour.
   -------------------------------------------------------------------------- */

body.page-order .form-control-label,
body.page-order label,
body.page-order .radio-label,
body.page-order .form-control-comment {
  font-size: 0.9375rem;
  font-weight: 600;
  color: var(--b3-encre);
}

body.page-order .form-control-label {
  margin-bottom: var(--b3-space-3xs);
  font-size: 0.8125rem;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}

body.page-order .form-control-comment {
  color: var(--b3-encre-douce);
}

body.page-order .form-control,
body.page-order select.form-control,
body.page-order textarea.form-control {
  min-height: 48px;
  padding: var(--b3-space-2xs) var(--b3-space-sm);
  border: 1.5px solid var(--b3-trait-fort);
  border-radius: var(--b3-radius-sm);
  background-color: var(--b3-papier);
  box-shadow: none;
  font-family: var(--b3-font);
  font-size: 1rem;
  color: var(--b3-encre);
}

body.page-order .form-control:focus {
  border-color: var(--b3-encre);
  outline: 3px solid var(--b3-encre);
  outline-offset: 2px;
}

/* Champ en erreur : le trait et le message, jamais la couleur seule. */
body.page-order .has-error .form-control,
body.page-order .form-control.is-invalid {
  border-color: var(--b3-alerte);
  border-width: 2px;
}

body.page-order .has-error .help-block,
body.page-order .js-invalid-feedback-browser {
  font-size: 0.875rem;
  font-weight: 700;
  color: var(--b3-alerte);
}

/* --------------------------------------------------------------------------
   Choix de livraison et de paiement

   Chaque option est une ligne cliquable entière, pas un bouton radio de 13 px
   suivi d'un libellé.
   -------------------------------------------------------------------------- */

body.page-order .delivery-option,
body.page-order .payment-option {
  display: flex;
  align-items: center;
  gap: var(--b3-space-2xs);
  margin: 0 0 var(--b3-space-2xs);
  padding: var(--b3-space-sm);
  border: 1.5px solid var(--b3-trait);
  border-radius: var(--b3-radius-sm);
  background-color: var(--b3-papier);
  cursor: pointer;
  transition: border-color var(--b3-dur-fast) var(--b3-ease);
}

body.page-order .delivery-option:hover,
body.page-order .payment-option:hover {
  border-color: var(--b3-encre);
}

/* L'option retenue se distingue par un trait franc et un fond alterné : deux
   signaux plutôt qu'un point coloré de six pixels. */
body.page-order .delivery-option:has(input:checked),
body.page-order .payment-option:has(input:checked) {
  border-color: var(--b3-encre);
  border-width: 2px;
  background-color: var(--b3-papier-2);
}

body.page-order .delivery-option label,
body.page-order .payment-option label {
  cursor: pointer;
}

body.page-order .carrier-name,
body.page-order .payment-option label {
  font-weight: 700;
  color: var(--b3-encre);
}

body.page-order .carrier-delay,
body.page-order .carrier-price {
  font-size: 0.9375rem;
  color: var(--b3-encre-douce);
}

body.page-order .carrier-price {
  margin-left: auto;
  font-weight: 800;
  font-variant-numeric: tabular-nums;
  color: var(--b3-encre);
}

/* --------------------------------------------------------------------------
   Actions
   -------------------------------------------------------------------------- */

body.page-order .continue,
body.page-order .btn-primary,
body.page-order button[type="submit"].btn-primary {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 52px;
  padding: 0 var(--b3-space-lg);
  border: 0;
  border-radius: var(--b3-radius-pill);
  background-color: var(--b3-jaune);
  font-size: 1rem;
  font-weight: 800;
  letter-spacing: 0.05em;
  line-height: 1;
  text-transform: uppercase;
  color: var(--b3-encre);
}

body.page-order .continue:hover,
body.page-order .btn-primary:hover {
  background-color: var(--b3-jaune-fonce);
}

/* --------------------------------------------------------------------------
   Récapitulatif
   -------------------------------------------------------------------------- */

body.page-order .cart-summary,
body.page-order #js-checkout-summary {
  padding: var(--b3-space-md);
  border: 1.5px solid var(--b3-trait);
  border-radius: var(--b3-radius);
  background-color: var(--b3-papier);
}

body.page-order .cart-summary-line {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--b3-space-2xs);
  padding: var(--b3-space-3xs) 0;
}

body.page-order .cart-summary-line .label {
  font-size: 0.9375rem;
  color: var(--b3-encre-douce);
}

body.page-order .cart-summary-line .value {
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  color: var(--b3-encre);
}

body.page-order .cart-total {
  margin-top: var(--b3-space-2xs);
  padding-top: var(--b3-space-sm);
  border-top: 2px solid var(--b3-encre);
}

body.page-order .cart-total .label,
body.page-order .cart-total .value {
  font-size: 1.125rem;
  font-weight: 800;
  color: var(--b3-encre);
}

/* --------------------------------------------------------------------------
   Adaptations
   -------------------------------------------------------------------------- */

@media (max-width: 991px) {
  /* Le récapitulatif passe au-dessus des étapes : sur une colonne, relégué en
     bas, il ne se voit qu'après avoir tout rempli. */
  body.page-order #checkout-cart-summary {
    order: -1;
    margin-bottom: var(--b3-space-sm);
  }

  body.page-order .checkout-step .step-title,
  body.page-order .checkout-step .content {
    padding-inline: var(--b3-space-sm);
  }

  body.page-order .continue,
  body.page-order .btn-primary {
    width: 100%;
  }
}

@media (max-width: 767px) {
  body.page-order .delivery-option,
  body.page-order .payment-option {
    flex-wrap: wrap;
  }

  body.page-order .carrier-price {
    margin-left: 0;
    width: 100%;
  }
}


/* --------------------------------------------------------------------------
   Cases à cocher du tunnel

   Elles sortaient en contrôle natif de treize pixels, collé à son libellé —
   sur l'écran où l'on accepte les conditions générales, c'est-à-dire là où la
   case a une valeur juridique. Cible tactile portée au seuil, libellé détaché,
   et coche jaune sur encre pour que l'état se voie sans ambiguïté.
   -------------------------------------------------------------------------- */

body.page-order .custom-checkbox,
body.page-order .checkbox-field {
  display: flex;
  align-items: flex-start;
  gap: var(--b3-space-2xs);
  margin-bottom: var(--b3-space-2xs);
}

body.page-order .custom-checkbox input[type="checkbox"] {
  position: absolute;
  opacity: 0;
  width: 24px;
  height: 24px;
  margin: 0;
  cursor: pointer;
}

body.page-order .custom-checkbox input[type="checkbox"] + span {
  flex: none;
  display: grid;
  place-items: center;
  width: 24px;
  height: 24px;
  margin: 0;
  border: 2px solid var(--b3-trait-fort);
  border-radius: 6px;
  background-color: var(--b3-papier);
  cursor: pointer;
  transition: border-color var(--b3-dur-fast) var(--b3-ease);
}

body.page-order .custom-checkbox:hover input[type="checkbox"] + span {
  border-color: var(--b3-encre);
}

body.page-order .custom-checkbox input[type="checkbox"]:checked + span {
  border-color: var(--b3-encre);
  background-color: var(--b3-encre);
}

body.page-order .custom-checkbox input[type="checkbox"]:checked + span::after {
  content: "";
  width: 68%;
  height: 68%;
  background-color: var(--b3-jaune);
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='3.4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M4 12.5l5.2 5.2L20 7'/%3E%3C/svg%3E") center / contain no-repeat;
  mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='3.4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M4 12.5l5.2 5.2L20 7'/%3E%3C/svg%3E") center / contain no-repeat;
}

body.page-order .custom-checkbox input[type="checkbox"]:focus-visible + span {
  outline: 3px solid var(--b3-encre);
  outline-offset: 2px;
}

/* Le libellé occupe la place restante et reste cliquable sur toute sa
   longueur : une case seule fait vingt-quatre pixels de cible, la ligne
   entière en fait plusieurs centaines. */
body.page-order .custom-checkbox label,
body.page-order .custom-checkbox > span:not(:first-of-type) {
  flex: 1 1 auto;
  font-size: 0.9375rem;
  line-height: 1.45;
  color: var(--b3-encre);
  cursor: pointer;
}

/* Les mentions légales et d'aide restent lisibles : en italique gris clair,
   la loi Informatique et Libertés se déchiffrait au lieu de se lire. */
body.page-order .custom-checkbox em,
body.page-order .form-control-comment,
body.page-order .checkbox-field em {
  display: block;
  margin-top: 0.3em;
  font-size: 0.875rem;
  font-style: normal;
  line-height: 1.45;
  color: var(--b3-encre-douce);
}


/* --------------------------------------------------------------------------
   En-tête du tunnel

   Le gabarit du noyau sert un en-tête allégé — logo seul, sans navigation ni
   recherche. Le thème enfant y substitue l'en-tête complet (voir
   templates/checkout/checkout.tpl), mais la recherche restait masquée par une
   règle du thème acheté propre à ce parcours.

   À signaler : réduire la navigation pendant le paiement est une pratique
   établie, qui limite les sorties et donc les abandons. Le choix inverse a été
   demandé par la boutique ; il se mesure sur le taux d'abandon en production.
   -------------------------------------------------------------------------- */

body.page-order #header #search_widget {
  display: block;
}


/* ===== 18-newsletter.css ================================================= */

@charset "UTF-8";
/* ==========================================================================
   Newsletter

   Le module sortait son gabarit de démonstration : un titre générique, un
   paragraphe de Lorem Ipsum latin, un champ souligné d'un simple trait et un
   bouton chevauché par une icône d'enveloppe rouge — le rouge du thème acheté,
   que la charte proscrit.

   La section prend l'aplat jaune : c'est une prise de parole de la maison, au
   même titre que le hero. Le formulaire s'y détache en papier.
   ========================================================================== */

.block_newsletter,
#footer .block_newsletter {
  position: relative;
  margin: 0;
  padding: var(--b3-space-lg) 0;
  border: 0;
  background-color: var(--b3-jaune);
}

/* L'aplat file d'un bord à l'autre, comme les autres sections pleines. */
.block_newsletter::before {
  content: "";
  position: absolute;
  inset: 0 calc(50% - 50vw);
  z-index: 0;
  background-color: var(--b3-jaune);
}

.block_newsletter > * {
  position: relative;
  z-index: 1;
}

.block_newsletter h3,
.block_newsletter .h3,
.block_newsletter .title {
  margin: 0 0 var(--b3-space-2xs);
  font-size: clamp(1.5rem, 2.6vw, 2rem);
  font-weight: 800;
  font-stretch: 82%;
  letter-spacing: -0.01em;
  line-height: 1.1;
  text-align: left;
  text-transform: none;
  color: var(--b3-encre);
}

/* Le texte de démonstration est remplacé par une phrase utile, posée en CSS :
   le contenu du module se règle en back-office, et rien ne garantit qu'il y
   soit corrigé avant la mise en ligne. */
.block_newsletter p:not(.newsletter-legal):not([class*="alert"]),
.block_newsletter .nwsletter-subtitle {
  margin: 0 0 var(--b3-space-sm);
  font-size: 1rem;
  line-height: 1.5;
  color: var(--b3-encre);
}

.block_newsletter [data-b3-remplace] {
  font-size: 0;
}

.block_newsletter [data-b3-remplace]::after {
  content: "Les nouveautés de la cave, les arrivages rares et les conseils de saison. Un envoi par mois, pas davantage.";
  display: block;
  max-width: 52ch;
  font-size: 1rem;
  line-height: 1.5;
  color: var(--b3-encre);
}

/* --------------------------------------------------------------------------
   Le formulaire

   Champ et bouton dans une même pièce, alignés sur la même hauteur : le
   bouton flottait par-dessus le champ, décalé vers le haut, et l'icône
   d'enveloppe le traversait.
   -------------------------------------------------------------------------- */

.block_newsletter form {
  max-width: 40rem;
  margin: 0;
}

/* Le module compose ce formulaire en deux colonnes Bootstrap, avec le bouton
   sorti du flux en `position: absolute` par-dessus le champ, et la mention
   légale dans la colonne voisine. D'où le bouton qui chevauchait la saisie et
   la mention rejetée sur le côté.

   Tout revient dans le flux, en une seule colonne. */
.block_newsletter form > .row {
  display: block;
  width: 100%;
  margin: 0;
}

.block_newsletter form > .row > [class*="col-"] {
  width: 100%;
  max-width: none;
  flex: none;
  padding: 0;
}

.block_newsletter .input-wrapper {
  display: flex;
  align-items: stretch;
  gap: var(--b3-space-2xs);
  width: 100%;
}

/* Le bouton rejoint la ligne du champ : il en était sorti pour être posé
   par-dessus. */
.block_newsletter .btn.btn-primary,
.block_newsletter input[type="submit"].btn {
  position: static;
  float: none;
}

/* La ligne de saisie regroupe le champ et le bouton, quel que soit l'endroit
   où le module a placé ce dernier. */
.block_newsletter form > .row > [class*="col-"]:first-child {
  display: flex;
  align-items: stretch;
  flex-wrap: wrap;
  gap: var(--b3-space-2xs);
  max-width: 34rem;
}

.block_newsletter .input-wrapper {
  flex: 1 1 16rem;
}

.block_newsletter input[type="email"],
.block_newsletter input[type="text"] {
  flex: 1 1 auto;
  min-width: 0;
  min-height: 54px;
  padding: 0 var(--b3-space-sm);
  border: 2px solid var(--b3-encre);
  border-radius: var(--b3-radius-pill);
  background-color: var(--b3-papier);
  box-shadow: none;
  font-family: var(--b3-font);
  font-size: 1rem;
  color: var(--b3-encre);
}

.block_newsletter input[type="email"]::placeholder {
  color: var(--b3-encre-douce);
}

.block_newsletter input[type="email"]:focus {
  outline: 3px solid var(--b3-encre);
  outline-offset: 2px;
}

.block_newsletter input[type="submit"],
.block_newsletter button[type="submit"],
.block_newsletter .btn {
  flex: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 54px;
  padding: 0 var(--b3-space-md);
  border: 0;
  border-radius: var(--b3-radius-pill);
  background-color: var(--b3-encre);
  background-image: none;
  font-size: 0.9375rem;
  font-weight: 800;
  letter-spacing: 0.05em;
  line-height: 1;
  text-transform: uppercase;
  color: var(--b3-jaune);
  cursor: pointer;
  transition: background-color var(--b3-dur-fast) var(--b3-ease);
}

.block_newsletter input[type="submit"]:hover,
.block_newsletter button[type="submit"]:hover {
  background-color: color-mix(in oklab, var(--b3-encre) 82%, white);
}

/* L'icône d'enveloppe du thème traversait le bouton, en rouge hérité. Le
   libellé suffit. */
.block_newsletter .material-icons,
.block_newsletter i,
.block_newsletter form::before,
.block_newsletter form::after {
  display: none;
}

/* La mention de désinscription est une obligation légale : elle se lit. */
.block_newsletter .newsletter-legal,
.block_newsletter em,
.block_newsletter small {
  display: block;
  max-width: 52ch;
  margin-top: var(--b3-space-2xs);
  font-size: 0.8125rem;
  font-style: normal;
  line-height: 1.45;
  color: color-mix(in oklab, var(--b3-encre) 78%, transparent);
}

@media (max-width: 575px) {
  .block_newsletter .input-wrapper,
  .block_newsletter form > div {
    flex-wrap: wrap;
  }

  .block_newsletter input[type="submit"],
  .block_newsletter button[type="submit"] {
    width: 100%;
  }
}


/* --------------------------------------------------------------------------
   Alignement de la section

   Trois alignements se contredisaient : titre centré, texte à gauche,
   formulaire au centre. Le regard n'avait pas d'axe. Tout se cale à gauche,
   dans une colonne unique — c'est la lecture naturelle d'un bloc de texte
   suivi d'un champ, et cela rejoint l'axe du reste de la page.
   -------------------------------------------------------------------------- */

.block_newsletter,
#footer .block_newsletter {
  text-align: left;
}

.block_newsletter .container,
.block_newsletter > .row,
.block_newsletter .row > [class*="col-"] {
  text-align: left;
}

.block_newsletter h3,
.block_newsletter .h3,
.block_newsletter .title,
.block_newsletter .nwsletter-subtitle,
.block_newsletter [data-b3-remplace]::after,
.block_newsletter p {
  text-align: left;
  margin-inline: 0;
}

/* Le bloc entier suit la largeur de contenu du site : centré dans la page,
   aligné à gauche à l'intérieur. */
.block_newsletter > .container,
.block_newsletter .wrapper-inner {
  max-width: 1320px;
  margin-inline: auto;
  padding-inline: var(--b3-space-sm);
}

/* Le titre passe en composition de section, comme les autres blocs de la
   page : il sortait en capitales espacées, seul de son espèce. */
.block_newsletter h3,
.block_newsletter .h3,
.block_newsletter .title {
  font-stretch: 82%;
  letter-spacing: -0.01em;
  text-transform: none;
}


/* Le module centre son formulaire par une marge latérale fixe — `margin:
   0 379px` sur `.newsletter_inner` — calculée pour une autre largeur de
   contenu. C'est elle qui décalait le formulaire de 380 px par rapport au
   texte, et elle ne suit aucun redimensionnement. */
.block_newsletter .newsletter_inner,
.block_newsletter .news-box,
.block_newsletter form {
  margin-inline: 0;
  text-align: left;
}


/* Le titre du module porte sa propre classe — `.nwsletter-maintitle`, ni un
   `h3` ni un `.title` — et restait donc centré pendant que le texte et le
   formulaire se calaient à gauche. */
.block_newsletter .newstitle-inner,
.block_newsletter .nwsletter-maintitle,
.block_newsletter .text-title {
  text-align: left;
}

.block_newsletter .nwsletter-maintitle {
  margin: 0 0 var(--b3-space-2xs);
  font-size: clamp(1.5rem, 2.6vw, 2rem);
  font-weight: 800;
  font-stretch: 82%;
  letter-spacing: -0.01em;
  line-height: 1.1;
  /* Le module écrit son titre en minuscules ; la capitale initiale se pose
     ici plutôt qu'en back-office, où rien ne garantit la correction. */
  text-transform: capitalize;
  color: var(--b3-encre);
}

/* --------------------------------------------------------------------------
   Composition de la bande

   Le module empile titre, texte puis formulaire dans une colonne de 510 px,
   au bord gauche d'un aplat qui fait toute la largeur : la moitié droite
   restait vide. Sur grand écran, le discours passe à gauche et le formulaire
   à droite, sur le même axe vertical.
   -------------------------------------------------------------------------- */

@media (min-width: 992px) {
  .block_newsletter ul {
    margin: 0;
    padding: 0;
    list-style: none;
  }

  .block_newsletter ul > li {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(20rem, 32rem);
    gap: var(--b3-space-lg);
    align-items: center;
  }

  .block_newsletter ul > li > .text-title,
  .block_newsletter ul > li > .news-box {
    width: auto;
    max-width: none;
    padding: 0;
  }

  .block_newsletter .newsletter_inner,
  .block_newsletter form,
  .block_newsletter form > .row > [class*="col-"]:first-child {
    max-width: none;
  }
}

/* Le texte de remplacement est injecté en CSS : il lui faut donc sa variante
   par langue, sans quoi la version anglaise sert une phrase française. */
html[lang^="en"] .block_newsletter [data-b3-remplace]::after {
  content: "New arrivals, rare bottles and seasonal advice. One email a month, no more.";
}


/* ===== 18-quota.css ====================================================== */

/* ==========================================================================
   Le quota de raretés

   La fenêtre reprend la forme de celle du panier — même papier, même arrondi,
   même fermeture — mais son ton est différent : elle n'annonce pas une erreur,
   elle explique une règle de la maison. D'où le jaune plutôt que le rouge, et
   un compte posé à plat plutôt qu'un avertissement.
   ========================================================================== */

.b3-quota {
  position: fixed;
  inset: 0;
  z-index: 1250;
  display: grid;
  place-items: center;
  padding: var(--b3-space-sm);
  background-color: color-mix(in oklab, var(--b3-encre) 66%, transparent);
}

.b3-quota[hidden] {
  display: none;
}

.b3-quota__panneau {
  width: min(34rem, 100%);
  max-height: 88vh;
  overflow-y: auto;
  padding: var(--b3-space-lg);
  border-radius: var(--b3-radius-lg);
  background-color: var(--b3-papier);
  animation: b3-quota-entree 280ms var(--b3-ease) both;
}

@keyframes b3-quota-entree {
  from { opacity: 0; transform: translate3d(0, 16px, 0) scale(0.985); }
  to   { opacity: 1; transform: none; }
}

@media (prefers-reduced-motion: reduce) {
  .b3-quota__panneau { animation: none; }
}

.b3-quota__tete {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--b3-space-2xs);
}

.b3-quota__sur {
  margin: 0;
  padding: 0.35em 0.9em;
  border-radius: var(--b3-radius-pill);
  background-color: var(--b3-jaune);
  color: var(--b3-encre);
  font-size: 0.6875rem;
  font-weight: 900;
  letter-spacing: 0.1em;
  text-transform: uppercase;
}

.b3-quota__fermer {
  flex: none;
  display: grid;
  place-items: center;
  width: 40px;
  height: 40px;
  border: 0;
  border-radius: 50%;
  background-color: transparent;
  font-size: 1.5rem;
  line-height: 1;
  color: var(--b3-encre);
  cursor: pointer;
}

.b3-quota__fermer:hover {
  background-color: var(--b3-papier-2);
}

.b3-quota__titre {
  margin: var(--b3-space-sm) 0 var(--b3-space-2xs);
  font-size: clamp(1.375rem, 3vw, 1.75rem);
  font-weight: 800;
  font-stretch: 86%;
  line-height: 1.1;
  color: var(--b3-encre);
}

.b3-quota__texte {
  margin: 0 0 var(--b3-space-md);
  font-size: 0.9375rem;
  line-height: 1.55;
  color: var(--b3-encre-douce);
}

/* Un bloc par règle déclenchée — le quota annuel et celui de la foire
   peuvent se déclencher ensemble, chacun garde son titre propre plutôt que
   de forcer un intitulé commun qui mentirait sur l'un des deux. */
.b3-quota__bloc + .b3-quota__bloc {
  margin-top: var(--b3-space-md);
  padding-top: var(--b3-space-md);
  border-top: 1.5px solid var(--b3-trait);
}

.b3-quota__bloc-titre {
  margin: 0 0 var(--b3-space-2xs);
  font-size: 1.0625rem;
  font-weight: 800;
  color: var(--b3-encre);
}

/* Le compte. Une règle qu'on ne peut pas vérifier soi-même se subit ; celle-ci
   se lit, ligne par ligne. */
.b3-quota__compte {
  margin: 0 0 var(--b3-space-sm);
  padding: 0;
  list-style: none;
  border-top: 1.5px solid var(--b3-trait);
}

.b3-quota__compte li {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--b3-space-sm);
  padding: 0.6em 0;
  border-bottom: 1px solid var(--b3-trait);
  font-size: 0.9375rem;
}

.b3-quota__compte strong {
  font-size: 1.125rem;
  font-weight: 900;
  font-variant-numeric: tabular-nums;
}

.b3-quota__compte--total {
  border-bottom: 0;
  color: var(--b3-encre);
  font-weight: 700;
}

.b3-quota__reste {
  margin: 0 0 var(--b3-space-md);
  padding: var(--b3-space-2xs) var(--b3-space-sm);
  border-radius: var(--b3-radius-sm);
  background-color: var(--b3-papier-2);
  font-size: 0.9375rem;
  font-weight: 700;
}

.b3-quota__reste strong {
  font-variant-numeric: tabular-nums;
}

.b3-quota__pied {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(11rem, 1fr));
  gap: var(--b3-space-2xs);
}

.b3-quota__pied .b3-btn {
  width: 100%;
  min-height: 48px;
  justify-content: center;
}

@media (max-width: 575px) {
  .b3-quota__panneau {
    padding: var(--b3-space-md);
  }
}


/* ===== 19-avis.css ======================================================= */

@charset "UTF-8";
/* ==========================================================================
   Avis clients — module productcomments

   Le module posait son bloc en fin de fiche sans aucun rattachement au reste
   de la page : une bulle de dialogue, « Commentaires (0) », puis un aplat
   blanc portant une phrase morte au centre. Aucune invitation, aucun chemin.

   Le bloc reprend la composition des autres sections : un titre, un compteur
   en second rang, puis les avis en lignes séparées d'un filet. Pas de cartes —
   un avis est un paragraphe signé, pas une vignette.
   ========================================================================== */

body.page-product #product-comments-list-header,
body.page-product #product-comments-list,
body.page-product #product-comments-list-footer,
body.page-product #empty-product-comment {
  max-width: none;
  margin-inline: 0;
}

body.page-product #product-comments-list-header {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: var(--b3-space-xs) var(--b3-space-md);
  margin-top: var(--b3-space-2xl);
  padding-bottom: var(--b3-space-sm);
  border-bottom: 1.5px solid var(--b3-encre);
  background: none;
}

body.page-product .b3-avis__titre {
  margin: 0;
  font-size: clamp(1.375rem, 2.2vw, 1.75rem);
  font-weight: 800;
  font-stretch: 82%;
  letter-spacing: -0.01em;
  line-height: 1.1;
  color: var(--b3-encre);
}

/* Le compteur passe derrière le titre : il informe, il n'annonce pas. */
body.page-product #product-comments-list-header .comments-nb {
  margin: 0;
  padding: 0;
  border: 0;
  font-size: 0.9375rem;
  font-weight: 600;
  color: var(--b3-encre-douce);
}

/* L'icône de bulle du thème doublait le titre sans rien dire de plus. */
body.page-product #product-comments-list-header .material-icons {
  display: none;
}

body.page-product #product-comments-list-header .comments-note {
  display: flex;
  align-items: center;
  gap: var(--b3-space-2xs);
  margin-left: auto;
  font-size: 0.875rem;
  color: var(--b3-encre-douce);
}

/* --------------------------------------------------------------------------
   Aucun avis

   L'état vide est le cas le plus fréquent du catalogue : 911 références,
   aucun avis publié. Il mérite donc autant de soin qu'une liste remplie.
   -------------------------------------------------------------------------- */

body.page-product #empty-product-comment,
body.page-product .b3-avis-vide {
  display: grid;
  /* `start` sur toute la grille rabattait aussi les paragraphes à la largeur
     de leur ligne la plus courte. Seul le bouton se cale à gauche. */
  justify-items: stretch;
  gap: var(--b3-space-sm);
  max-width: 46rem;
  margin: 0;
  padding: var(--b3-space-lg) 0 0;
  border: 0;
  background: none;
  text-align: left;
}

body.page-product .b3-avis-vide__phrase {
  margin: 0;
  font-size: 1.0625rem;
  line-height: 1.5;
  color: var(--b3-encre);
}

body.page-product .b3-avis-vide .btn-comment,
body.page-product .b3-avis-vide__lien {
  justify-self: start;
}

body.page-product .b3-avis-vide__mention {
  max-width: 52ch;
  margin: 0;
  font-size: 0.875rem;
  line-height: 1.5;
  color: var(--b3-encre-douce);
}

/* --------------------------------------------------------------------------
   Les boutons du module

   `.btn-comment` héritait du rouge du thème acheté, que la charte proscrit.
   -------------------------------------------------------------------------- */

body.page-product .btn-comment,
body.page-product .btn-comment-big,
body.page-product .btn-comment-huge,
.product-comment-modal .btn-comment,
.product-comment-modal .btn-comment-big,
.product-comment-modal .btn-comment-huge {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--b3-space-2xs);
  min-height: 48px;
  padding: 0 var(--b3-space-md);
  border: 1.5px solid var(--b3-encre);
  border-radius: var(--b3-radius-pill);
  background-color: var(--b3-encre);
  background-image: none;
  font-family: var(--b3-font);
  font-size: 0.9375rem;
  font-weight: 800;
  letter-spacing: 0.02em;
  line-height: 1;
  text-decoration: none;
  text-transform: none;
  color: var(--b3-jaune);
  cursor: pointer;
  transition: background-color var(--b3-dur-fast) var(--b3-ease),
              color var(--b3-dur-fast) var(--b3-ease);
}

body.page-product .btn-comment:hover,
.product-comment-modal .btn-comment:hover {
  background-color: var(--b3-jaune);
  color: var(--b3-encre);
}

body.page-product .btn-comment-inverse,
.product-comment-modal .btn-comment-inverse {
  background-color: transparent;
  color: var(--b3-encre);
}

body.page-product .btn-comment-inverse:hover,
.product-comment-modal .btn-comment-inverse:hover {
  background-color: var(--b3-encre);
  color: var(--b3-papier);
}

/* --------------------------------------------------------------------------
   Les avis publiés
   -------------------------------------------------------------------------- */

body.page-product #product-comments-list .product-comment-list-item {
  margin: 0;
  padding: var(--b3-space-lg) 0;
  border: 0;
  border-bottom: 1px solid var(--b3-trait);
  background: none;
}

body.page-product #product-comments-list .comment-author {
  font-weight: 700;
  color: var(--b3-encre);
}

body.page-product #product-comments-list .comment-date {
  font-size: 0.8125rem;
  color: var(--b3-encre-douce);
}

body.page-product #product-comments-list .comment-content .h4 {
  margin: 0 0 var(--b3-space-2xs);
  font-size: 1.0625rem;
  font-weight: 800;
  color: var(--b3-encre);
}

body.page-product #product-comments-list .comment-content p {
  max-width: 70ch;
  margin: 0;
  line-height: 1.6;
  color: var(--b3-encre);
}

/* Les commandes d'appréciation étaient en gris clair sur blanc — 2,8:1, sous
   le seuil AA. */
body.page-product #product-comments-list .comment-buttons a {
  color: var(--b3-encre-douce);
  cursor: pointer;
}

body.page-product #product-comments-list .comment-buttons a:hover {
  color: var(--b3-encre);
}

body.page-product #product-comments-list-footer {
  padding-top: var(--b3-space-md);
}

/* --------------------------------------------------------------------------
   La fenêtre de dépôt
   -------------------------------------------------------------------------- */

.product-comment-modal .modal-content {
  border: 1.5px solid var(--b3-encre);
  border-radius: var(--b3-radius);
  background-color: var(--b3-papier);
}

.product-comment-modal .modal-header {
  align-items: center;
  border-bottom: 1.5px solid var(--b3-trait);
  background: none;
}

.product-comment-modal .modal-header .h2 {
  margin: 0;
  font-size: 1.25rem;
  font-weight: 800;
  font-stretch: 82%;
  color: var(--b3-encre);
}

.product-comment-modal .form-label {
  display: block;
  margin: var(--b3-space-sm) 0 var(--b3-space-3xs);
  font-size: 0.875rem;
  font-weight: 700;
  color: var(--b3-encre);
}

.product-comment-modal input[type="text"],
.product-comment-modal textarea {
  width: 100%;
  min-height: 48px;
  padding: var(--b3-space-2xs) var(--b3-space-sm);
  border: 1.5px solid var(--b3-trait-fort);
  border-radius: var(--b3-radius-sm);
  background-color: var(--b3-papier);
  font-family: var(--b3-font);
  font-size: 1rem;
  color: var(--b3-encre);
}

.product-comment-modal textarea {
  min-height: 8rem;
  line-height: 1.5;
  resize: vertical;
}

.product-comment-modal input[type="text"]:focus,
.product-comment-modal textarea:focus {
  outline: 3px solid var(--b3-encre);
  outline-offset: 2px;
}

.product-comment-modal .post-comment-buttons {
  display: flex;
  justify-content: flex-end;
  gap: var(--b3-space-2xs);
}

.product-comment-modal .required {
  color: var(--b3-encre-douce);
}


/* ===== 20-scroll.css ===================================================== */

@charset "UTF-8";
/* ==========================================================================
   Sections plein écran et entrées au défilement

   Chaque section occupe la hauteur de la fenêtre et son contenu se centre :
   la page se parcourt écran par écran plutôt qu'en flux continu.

   `svh` et non `vh` : sur un téléphone, `vh` compte la fenêtre barre d'adresse
   masquée, si bien qu'une section « pleine hauteur » déborde tant que la barre
   est visible — et le premier geste de défilement fait sauter la mise en page.
   `svh` prend la plus petite hauteur, celle qui vaut toujours.

   `min-height` et non `height` : une section dont le contenu dépasse doit
   pouvoir grandir. Une grille de vingt-quatre vignettes ne tient pas dans un
   écran, et la rogner serait pire que de la laisser filer.
   ========================================================================== */

.b3-panneau {
  min-height: 100svh;
}

/* Le centrage vertical ne s'applique qu'aux sections qui ne portent pas déjà
   leur propre mise en page. `.b3-entries` est une grille nommée — trois zones,
   deux colonnes — et lui imposer `display: flex` détruisait la grille : les
   trois entrées se dépliaient en bandes pleine largeur.

   La règle vise donc ce qu'elle doit viser, plutôt que tout ce qui porte la
   classe. */
.b3-panneau:not(.b3-entries) {
  display: flex;
  flex-direction: column;
  justify-content: center;
}

/* La grille des entrées se centre par sa propre mécanique : ses rangées
   occupent la hauteur disponible. */
.b3-entries.b3-panneau {
  align-content: center;
}

/* Repli pour les navigateurs sans `svh` — Safari 15 et antérieurs. */
@supports not (height: 100svh) {
  .b3-panneau {
    min-height: 100vh;
  }
}

/* Le hero porte déjà une respiration calculée pour une section libre. Dans un
   panneau de hauteur fixe, elle s'ajoute à la hauteur imposée et pousse les
   boutons hors de l'écran : c'est le panneau qui donne l'espace désormais. */
.b3-hero.b3-panneau .b3-hero__inner {
  padding-block: var(--b3-space-lg);
}

/* Le hero retire la hauteur de l'en-tête : sans quoi il pousse sa propre
   moitié basse hors de l'écran, et les boutons se retrouvent sous la ligne de
   flottaison alors qu'ils sont l'objet de la section. */
.b3-hero.b3-panneau {
  min-height: calc(100svh - var(--b3-entete-hauteur, 0px));
}

/* Sous 900 px de large, la contrainte tombe : sur un téléphone, un écran par
   section transforme une page de dix sections en dix mille pixels de
   défilement, et le contenu y est déjà à l'étroit. */
@media (max-width: 900px) {
  .b3-panneau {
    min-height: 0;
  }
}

/* --------------------------------------------------------------------------
   Entrées au défilement

   L'élément monte de vingt pixels en apparaissant. Vingt, pas soixante : une
   entrée qu'on remarque est une entrée ratée — elle doit accompagner le
   regard, pas le détourner.

   L'état de départ n'est posé que si le script a pris la main
   (`html.b3-anim`). Sans JavaScript, rien n'est masqué : une page qui ne
   révèle son contenu qu'au défilement est une page vide pour un moteur qui
   n'exécute rien.
   -------------------------------------------------------------------------- */

.b3-anim [data-b3-anim] {
  opacity: 0;
  transform: translate3d(0, 20px, 0);
  transition:
    opacity 620ms var(--b3-ease),
    transform 620ms var(--b3-ease);
  transition-delay: var(--b3-anim-retard, 0ms);
  will-change: opacity, transform;
}

.b3-anim [data-b3-anim].b3-vu {
  opacity: 1;
  transform: none;
}

/* Une fois entré, l'élément rend sa couche de composition : garder
   `will-change` sur trente éléments coûte de la mémoire vidéo pour rien. */
.b3-anim [data-b3-anim].b3-vu {
  will-change: auto;
}

/* --------------------------------------------------------------------------
   Titres adhérents

   Le titre d'une section reste en haut de l'écran tant que sa section défile :
   on sait toujours ce qu'on regarde. Il ne colle qu'au-dessus de 900 px, là
   où la place ne manque pas — sur un téléphone, un titre collé mange le tiers
   de l'écran utile.
   -------------------------------------------------------------------------- */

@media (min-width: 901px) {
  .b3-panneau > .b3-section__title,
  .b3-panneau .main-title {
    position: sticky;
    top: var(--b3-space-sm);
    z-index: 3;

    /* Un titre adhérent sans fond laisse le contenu défiler à travers lui :
       sur « Conseils & accords », le titre se superposait à l'étiquette de la
       première carte, et les deux devenaient illisibles. Le fond reprend celui
       de la section, avec un débord latéral pour que rien ne passe sur les
       côtés. */
    background-color: inherit;
    padding-block: var(--b3-space-2xs);
    margin-inline: calc(var(--b3-space-2xs) * -1);
    padding-inline: var(--b3-space-2xs);
  }

  /* Le fond ne se pose que sur les sections qui portent un titre adhérent, et
     jamais sur la section elle-même.

     La version précédente peignait `.b3-panneau` en papier avec une liste
     d'exceptions : la hero n'y figurait pas, et son aplat jaune est devenu
     blanc. Énumérer les exceptions était la mauvaise approche — il suffisait
     de ne rien peindre du tout et de donner son fond au seul titre. */
  .b3-panneau > .b3-section__title {
    background-color: var(--b3-papier);
  }

  /* Les sections à fond propre donnent le leur à leur titre. */
  .b3-picks > .b3-section__title,
  .b3-entries > .b3-section__title {
    background-color: var(--b3-jaune);
  }

  .b3-figures > .b3-section__title {
    background-color: var(--b3-encre);
  }

}

@media (prefers-reduced-motion: reduce) {
  .b3-anim [data-b3-anim] {
    opacity: 1;
    transform: none;
    transition: none;
  }

  .b3-panneau > .b3-section__title,
  .b3-panneau .main-title {
    position: static;
  }
}

/* --------------------------------------------------------------------------
   Entrée « annonce »

   Une carte de texte seul, centrée, sur toute la largeur du bloc. Elle n'a ni
   visuel ni catégorie propre : c'est un rendez-vous qu'on annonce, et le texte
   y suffit.
   -------------------------------------------------------------------------- */

/* L'annonce prend une photographie en fond, comme les autres entrées. Elle
   garde son jaune dessous : c'est le repli tant que l'image n'est pas
   chargée, et il évite le clignotement blanc. */
.b3-entry--annonce {
  grid-area: annonce;
  min-height: clamp(13rem, 22vw, 18rem);
  background-color: var(--b3-jaune);
  color: var(--b3-papier);
}

/* Sur photographie, le texte repasse en papier et le sur-titre en jaune : sur
   l'aplat, ils étaient en encre. */
.b3-entry--annonce.b3-entry--photo .b3-entry__title,
.b3-entry--annonce.b3-entry--photo .b3-entry__texte {
  color: var(--b3-papier);
}

.b3-entry--annonce.b3-entry--photo .b3-entry__kicker {
  color: var(--b3-jaune);
  opacity: 1;
}

.b3-entry--annonce.b3-entry--photo .b3-entry__cta {
  background-color: var(--b3-jaune);
  border-color: var(--b3-jaune);
  color: var(--b3-encre);
}

.b3-entry--annonce .b3-entry__body {
  align-items: center;
  gap: var(--b3-space-2xs);
  padding: var(--b3-space-xl) var(--b3-space-lg);
  text-align: center;
}

.b3-entry--annonce .b3-entry__title {
  max-width: 22ch;
  font-size: clamp(1.5rem, 3vw, 2.25rem);
  line-height: 1.05;
}

.b3-entry--annonce .b3-entry__texte {
  max-width: 48ch;
}




/* --------------------------------------------------------------------------
   Le bento sur tablette

   Entre 768 et 1200 px, la disposition en L ne tient plus : la majeure occupe
   deux rangées d'une grille dont la hauteur est imposée par le panneau, et
   les cinq cartes se retrouvent étirées bien au-delà de ce que leurs
   photographies supportent.

   Sur cette plage, la majeure passe en pleine largeur — c'est elle qui porte
   la décision, elle mérite la bande haute — et les deux autres se partagent
   la rangée suivante. Le panneau relâche sa contrainte de hauteur : cinq
   cartes ne tiennent pas dans un écran de tablette, et vouloir les y faire
   entrer ne produit que des vides.
   -------------------------------------------------------------------------- */

@media (min-width: 768px) and (max-width: 1200px) {
  .b3-entries.b3-panneau {
    min-height: 0;
    align-content: start;
  }

  .b3-entries {
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    grid-template-rows: auto;
    grid-template-areas:
      "majeure majeure"
      "haute   basse"
      "large   large"
      "annonce annonce";
  }

  .b3-entry--majeure {
    min-height: clamp(20rem, 34vw, 26rem);
  }

  /* Le titre de la majeure était borné à 14ch pour tenir dans une colonne
     étroite. En pleine largeur, cette borne le casse sans raison. */
  .b3-entry--majeure .b3-entry__title {
    max-width: none;
  }

  .b3-entry--haute,
  .b3-entry--basse {
    min-height: clamp(15rem, 26vw, 20rem);
  }
}

/* Le repli pour les navigateurs sans requête de conteneur oubliait l'annonce :
   privée de sa zone nommée, la carte « Foire aux vins » était placée
   automatiquement, sur une seule colonne, à côté d'un vide. Il oubliait aussi
   que `.b3-entry--ink` désigne deux cartes — la majeure et la brasserie — et
   leur imposait à toutes deux une pleine largeur qui contredisait leur zone. */
@supports not (container-type: inline-size) {
  @media (max-width: 1024px) {
    .b3-entries {
      grid-template-areas:
        "majeure majeure"
        "haute   basse"
        "large   large"
        "annonce annonce";
    }

    .b3-entry--majeure {
      grid-column: 1 / -1;
    }

    .b3-entry--large.b3-entry--ink {
      grid-column: large;
    }
  }
}

/* --------------------------------------------------------------------------
   Les deux cartes pleine largeur respirent

   « Notre brasserie » porte un film, « Foire aux vins » une photographie : à
   14 rem de haut, l'un comme l'autre se réduisaient à une bande où l'image ne
   se lit plus. Elles montent d'un tiers, et suivent la largeur de l'écran
   plutôt qu'un plancher fixe.
   -------------------------------------------------------------------------- */

.b3-entry--large {
  min-height: clamp(18rem, 26vw, 26rem);
}

.b3-entry--annonce {
  min-height: clamp(17rem, 24vw, 24rem);
}

/* --------------------------------------------------------------------------
   Le cerne jaune

   Les cinq entrées portent le filet de la maison. Il est posé en `box-shadow`
   plutôt qu'en `border` : une bordure entrerait dans le calcul de la boîte et
   décalerait les photographies d'un pixel à chaque carte, `inset` reste au
   contact du rayon d'angle sans rien déplacer.
   -------------------------------------------------------------------------- */

.b3-entries .b3-entry {
  border-radius: var(--b3-radius-lg);
  box-shadow: inset 0 0 0 3px var(--b3-jaune);
}

/* Le cerne se renforce au survol, il ne change pas de nature. */
.b3-entries .b3-entry:hover,
.b3-entries .b3-entry:focus-visible {
  box-shadow: inset 0 0 0 4px var(--b3-jaune);
}

/* La carte « Coffrets » est déjà jaune : un cerne jaune sur un fond jaune ne
   se voit pas. Elle prend l'encre, qui joue le même rôle. */
.b3-entries .b3-entry--yellow {
  box-shadow: inset 0 0 0 3px var(--b3-encre);
}

.b3-entries .b3-entry--yellow:hover,
.b3-entries .b3-entry--yellow:focus-visible {
  box-shadow: inset 0 0 0 4px var(--b3-encre);
}

/* Safari ne rogne pas toujours un descendant transformé dans un conteneur à
   la fois `overflow: hidden` et `border-radius` : la photographie débordait
   sous la carte, en une bande visible dans l'intervalle de la grille. Le
   masque force le rognage sans changer le rendu ailleurs. */
.b3-entries .b3-entry {
  -webkit-mask-image: -webkit-radial-gradient(#fff, #000);
  mask-image: radial-gradient(#fff, #000);
}


/* ===== 99-conteneurs.css ================================================= */

@charset "UTF-8";
/* ==========================================================================
   Requêtes de conteneur

   Une requête de conteneur surcharge les règles de son composant : elle doit
   donc être lue après elles. Tant qu'elles vivaient dispersées dans les
   fichiers, leur effet dépendait de la position de leur fichier dans l'ordre
   d'assemblage — la vignette gagnait ou perdait un pixel et demi selon
   l'endroit où le bloc avait atterri, et le compactage annoncé pour les
   vignettes étroites ne s'appliquait pas.

   Elles sont donc rassemblées ici, en fin de chaîne. La règle se vérifie d'un
   coup d'œil : aucune `@container` ailleurs que dans ce fichier.
   ========================================================================== */

/* ----- repris de 09-divers ----- */
/* Sous 260 px de carte, prix et achat s'empilent plutôt que de se serrer :
   sur un écran de téléphone en deux colonnes, la ligne d'achat débordait et le
   bouton panier se retrouvait coupé par le bord arrondi de la carte.
   La requête porte le nom du conteneur : sans lui, elle pouvait se rattacher
   à la page plutôt qu'à la carte. */
@container carte (max-width: 340px) {
  /* Carte étroite : format plus carré et plus compact.
     Le visuel en 4/5 rendait la carte très haute — deux colonnes de bouteilles
     occupaient presque tout l'écran. Le cadre passe au carré, le texte se
     resserre, et la ligne d'achat s'empile pour que le bouton panier ne soit
     plus rogné par le bord arrondi. */
  .b3-card__thumb {
    aspect-ratio: 1;
  }

  .b3-card__thumb img {
    padding: var(--b3-space-2xs);
  }

  /* Même niveau de spécificité que les règles de section, sans quoi le
     rembourrage large de la carte large l'emporte. */
  #products .b3-card .b3-card__body,
  .featured-products .b3-card .b3-card__body,
  .homepage-products .b3-card .b3-card__body,
  .product-accessories .b3-card .b3-card__body,
  .b3-card .b3-card__body {
    gap: 0;
    padding: var(--b3-space-2xs) var(--b3-space-xs) var(--b3-space-xs);
  }

  /* La ligne d'achat tient sur une seule rangée à cette largeur : l'empiler
     ajoutait une soixantaine de pixels de hauteur pour rien. */
  .b3-card__footer {
    flex-direction: row;
    align-items: center;
    justify-content: space-between;
  }

  .b3-card__cart {
    width: auto;
  }

  .b3-card__origin {
    font-size: 0.6875rem;
    letter-spacing: 0.08em;
  }

  /* Interlignes et réserves resserrés : c'est le bloc texte, pas le visuel,
     qui donnait à la carte sa hauteur de 412 px pour 163 de large. */
  .b3-card__title {
    font-size: 0.8125rem;
    line-height: 1.25;
    /* Pas de `min-height` ici : la réserve de deux lignes est fixée une seule
       fois, dans 04-carte.css. La valeur qui figurait à cet endroit était
       écrasée et n'a jamais rien produit. */
  }

  .b3-card__origin,
  .b3-card__meta {
    min-height: 0;
    line-height: 1.3;
  }

  .b3-card__meta {
    font-size: 0.75rem;
  }

  .b3-card__price .price {
    font-size: 1rem;
  }

  .b3-card__footer {
    flex-direction: column;
    align-items: stretch;
    gap: var(--b3-space-2xs);
    padding-top: var(--b3-space-2xs);
  }

  .b3-card__cart {
    /* La commande reste groupée à droite, même sur une vignette étroite : la
       quantité et le bouton d'ajout forment un seul geste. Les écarter aux
       deux bords rallongeait le trajet entre le réglage et la validation. */
    justify-content: flex-end;
    width: 100%;
  }

  /* Contrôles resserrés plutôt qu'étirés : la rangée doit tenir entière. */
  .b3-qty {
    padding: 3px;
    gap: 2px;
  }

  /* Largeur et hauteur ensemble : n'ajuster que l'une des deux redonnait un
     ovale. `flex-basis` compte aussi, sinon la piste garde l'ancienne mesure. */
  .b3-qty__step {
    flex: 0 0 26px;
    width: 26px;
    min-width: 26px;
    height: 26px;
    font-size: 0.875rem;
  }

  .b3-qty__input {
    width: 24px;
    height: 26px;
    font-size: 0.8125rem;
  }

  .b3-card__add {
    flex: 0 0 auto;
    width: 42px;
    height: 42px;
  }

  .b3-card__add .material-icons {
    font-size: 20px;
  }
}

@container page (max-width: 1024px) {
  .b3-entries {
    grid-template-columns: 1fr 1fr;
  }

  .b3-entry--ink {
    grid-column: 1 / -1;
    min-height: 200px;
  }
}

@container page (max-width: 720px) {
  .b3-entries {
    grid-template-columns: minmax(0, 1fr);
  }

  .b3-entry {
    min-height: 200px;
  }

  .b3-shelves__grid {
    grid-template-columns: repeat(4, minmax(0, 1fr));
  }

  .b3-figures__inner {
    grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
    gap: var(--b3-space-md);
  }

  .b3-partners__grid {
    grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  }
}


/* --------------------------------------------------------------------------
   Le bouton d'ajout au panier, sur téléphone

   Le pied de carte n'a que deux enfants : le prix, et un `<form
   class="b3-card__cart">` qui porte la réglette de quantité et le bouton. Mes
   règles précédentes visaient `.b3-card__footer .b3-qty` et
   `.b3-card__footer .b3-card__add` — la sélection était juste, mais les
   propriétés `flex` posées dessus n'avaient aucun effet : leur parent est le
   formulaire, pas le pied. La réglette gardait sa largeur, le bouton était
   poussé au-delà du bord et rogné par l'`overflow` de la carte.

   Le formulaire devient donc lui-même une rangée souple. `flex-wrap: wrap` est
   le filet : quelle que soit la largeur restante, le bouton passe à la ligne
   plutôt que de sortir du cadre. C'est ce qui manquait.

   Ce bloc est en fin de fichier, et ce fichier est le dernier assemblé : à
   spécificité égale, c'est l'ordre qui tranche, et les requêtes de conteneur
   plus haut ne l'emportent plus.
   -------------------------------------------------------------------------- */

@media (max-width: 767px) {
  .b3-card .b3-card__footer {
    display: flex;
    flex-direction: row;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--b3-space-3xs);
  }

  /* Le prix prend la première ligne entière ; la commande suit dessous. Sur
     une vignette de cent quatre-vingts points, les trois ne tiennent pas
     côte à côte. */
  .b3-card .b3-card__footer > .b3-card__price {
    flex: 1 1 100%;
    margin: 0;
  }

  .b3-card .b3-card__cart {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: flex-end;
    gap: var(--b3-space-3xs);
    width: 100%;
    margin: 0;
  }

  /* La réglette garde sa largeur naturelle et pousse le bouton à droite. */
  .b3-card .b3-card__cart .b3-qty {
    flex: 0 0 auto;
    margin-right: auto;
    transform: none;
  }

  /* Quarante-deux pixels : au-dessus de la cible tactile de quarante, et
     assez petit pour tenir à côté d'une réglette de cent. */
  .b3-card .b3-card__cart .b3-card__add {
    flex: 0 0 42px;
    display: grid;
    place-items: center;
    width: 42px;
    height: 42px;
    min-width: 42px;
  }
}


/* --------------------------------------------------------------------------
   La carte « Les raretés à découvrir », sur tablette

   La règle plus haut dans ce fichier pose `min-height: 200px` sur
   `.b3-entry--ink` sous 1024 px de conteneur. Or `--ink` désigne deux cartes :
   la brasserie, qui est une bande horizontale et s'en accommode, et la
   majeure, qui porte une nature morte de bouteilles. À 200 px de haut sur
   toute la largeur du bloc, la photographie était rognée en un bandeau où les
   bouteilles se retrouvaient coupées au col.

   Ce fichier étant le dernier assemblé, une règle placée ici tranche. La
   majeure retrouve une hauteur proportionnée : encore horizontale — c'est son
   format — mais assez haute pour que le sujet tienne dans le cadre.
   -------------------------------------------------------------------------- */

@container page (max-width: 1024px) {
  .b3-entries .b3-entry--majeure {
    min-height: clamp(20rem, 40cqw, 30rem);
  }

  /* Le cadrage remonte : le sujet est au milieu des bouteilles, pas au sol. */
  .b3-entries .b3-entry--majeure .b3-entry__fond img {
    object-position: center 55%;
  }
}

/* Repli sans requête de conteneur. */
@supports not (container-type: inline-size) {
  @media (min-width: 768px) and (max-width: 1024px) {
    .b3-entries .b3-entry--majeure {
      min-height: clamp(20rem, 40vw, 30rem);
    }
  }
}

/* --------------------------------------------------------------------------
   Les rails de filtre, aussi sur tablette

   Le repli en rails ne valait que sous 768 px : sur un iPad, la barre
   retombait dans son ancien empilement. La largeur d'un rail n'a rien à voir
   avec le type d'appareil — c'est le nombre de pastilles qui déborde, et il
   est le même partout.
   -------------------------------------------------------------------------- */

@media (min-width: 768px) and (max-width: 1200px) {
  .b3-filters {
    display: flex;
    flex-direction: column;
    align-items: stretch;
    gap: var(--b3-space-2xs);
  }

  .b3-filters__rail {
    flex-wrap: nowrap;
    overflow-x: auto;
    scrollbar-width: none;
    -webkit-overflow-scrolling: touch;
    padding-block: 2px;
  }

  .b3-filters__rail::-webkit-scrollbar {
    display: none;
  }

  .b3-filters .b3-filter {
    flex: 0 0 auto;
    white-space: nowrap;
  }

  .b3-filters__separateur {
    display: none;
  }
}

/* L'intitulé de famille sur l'aplat jaune : papier plein plutôt qu'encre
   adoucie. À 62 % d'encre sur du jaune, il se lisait comme une mention légale ;
   c'est une clé de lecture, elle doit se voir. */
.b3-picks .b3-filters__intitule,
.b3-entries .b3-filters__intitule {
  font-size: 0.8125rem;
  font-weight: 900;
  letter-spacing: 0.08em;
  color: var(--b3-papier);
  -webkit-text-stroke: 0.4px var(--b3-encre);
  paint-order: stroke fill;
}

@media (max-width: 767px) {
  .b3-picks .b3-filters__intitule,
  .b3-entries .b3-filters__intitule {
    width: 4.8rem;
    font-size: 0.6875rem;
  }
}
