/*
 * Pont de variables CSS — identité K KLEMERLAIN sur le plugin aod-cod-form
 * (Story 1.3, architecture.md Décision 1). Redéclare les tokens --sh-* / --ac-*
 * lus par le plugin, SANS modifier une seule ligne de plugins-dev/.
 *
 * Deux ancrages différents, chacun choisi pour la raison qui suit :
 * - --ac-* (aod-cart.css) sont déclarées sur :root dans le plugin -> un bloc
 *   html:root (spécificité 0-1-1) suffit à les redéclarer, quel que soit
 *   l'ordre d'impression réel des feuilles de style.
 * - --sh-* (aod-cod-form.css) sont déclarées DIRECTEMENT sur .aod-cod
 *   (spécificité 0-1-0), jamais sur :root (vérifié ligne 3 du fichier plugin).
 *   Une valeur posée directement sur un élément gagne toujours sur une valeur
 *   héritée d'un ancêtre, quelle que soit la spécificité de la règle qui a
 *   posé cette valeur héritée : un simple html:root { --sh-accent: ... }
 *   n'atteint donc JAMAIS le formulaire réel (bug trouvé en revue de code de
 *   cette story, corrigé ici). Correctif : cibler .aod-cod avec une
 *   spécificité strictement supérieure à celle du plugin (0-1-0), soit
 *   html:root .aod-cod (0-2-1) — gagne quel que soit l'ordre d'impression,
 *   sans dépendre d'un !important.
 */

:root {
	/* Tokens de marque K KLEMERLAIN (DESIGN.md) — source unique, référencée
	   ci-dessous par les deux ponts pour éviter toute couleur dupliquée.
	   Retour owner (2026-09-02) : « change toutes les couleurs bleues
	   existantes par #162950 » (exemples cités : barre d'annonce, boutons
	   Commander) — remplace l'ancien bleu/teal #146E7D. `-hover`/`-wash`
	   RESTENT en `color-mix()` dérivé de ce token (pas de littéral figé) :
	   les deux suivent automatiquement la nouvelle base, comme ils suivaient
	   déjà l'ancienne. Toujours assez sombre pour le texte blanc dessus
	   (contraste AA — plus sombre que l'ancien #146E7D, donc jamais un
	   recul de contraste). */
	--bb-brand-teal-dark: #162950;
	--bb-brand-teal-dark-hover: color-mix(in srgb, var(--bb-brand-teal-dark) 90%, #000);
	--bb-brand-teal-wash: color-mix(in srgb, var(--bb-brand-teal-dark) 8%, #FFFFFF);
	--bb-feedback-error: #C4453F;
	--bb-ink-navy: #16264A;
	--bb-border-hairline: #ECECEC;
	--bb-rounded-sm: 6px;
	--bb-rounded-md: 12px;
	--bb-rounded-lg: 20px;
	--bb-header-logo-max-height: 40px;

	/* Story 4.1 — tokens DESIGN.md restants, introduits à l'occasion de
	   l'habillage Accueil (premier composant à en avoir réellement besoin).
	   --bb-brand-teal : DÉCORATIF UNIQUEMENT (soulignement de nav, icônes) —
	   jamais texte, jamais fond de bouton, jamais anneau de focus.
	   ⚠️ Alignée sur --bb-brand-teal-dark (2026-09-02, même retour owner
	   « toutes les couleurs bleues ») : c'était la seule teinte bleu/teal du
	   thème encore distincte de #162950. La mise en garde AA d'origine
	   (« la teal claire échoue le contraste en texte ») ne s'applique PLUS
	   littéralement à cette valeur assombrie — gardée par prudence : ce
	   token reste un usage décoratif, jamais du texte pleine taille. */
	--bb-brand-teal: var(--bb-brand-teal-dark);
	--bb-ink-slate: #98A1AF;
	/* Retour owner (2026-09-02) : « change le marron partout sur le site par
	   #162950 » — alias sur --bb-brand-teal-dark (déjà cette valeur, même
	   patron que --bb-brand-teal ci-dessus), plutôt qu'un littéral dupliqué.
	   ⚠️ Tous les textes/icônes posés sur ce fond ont été audités et corrigés
	   en conséquence (institutionnel, boutons de rail au survol, badge de
	   réassurance, lien du pied de page) : plusieurs étaient en
	   --bb-ink-navy/--bb-brand-teal-dark, illisibles (contraste ~1:1) sur un
	   fond DEVENU la même couleur — jamais un simple changement de jeton
	   seul, cf. les commentaires sur chaque site corrigé. */
	--bb-surface-cream: var(--bb-brand-teal-dark);
	--bb-surface-white: #FFFFFF;
	/* ⚠️ Distinct de --bb-border-hairline (#ECECEC) ci-dessus, qui correspond
	   en réalité à ce que DESIGN.md nomme `border-hairline-white`. Celui-ci
	   est la bordure crème (#E7DFD3, sections éditoriales) — les deux valeurs
	   ne sont PAS interchangeables, DESIGN.md les distingue explicitement.
	   Ne jamais renommer --bb-border-hairline existant : romprait la Story 3.x. */
	--bb-border-hairline-cream: #E7DFD3;
	--bb-rounded-full: 9999px;
	/* Échelle d'espacement DESIGN.md (jamais introduite jusqu'ici — la Story 3.1
	   a délibérément laissé un `gap: 20px` littéral, cf. commentaire plus bas,
	   en attendant l'occasion naturelle de la poser : cette story). */
	--bb-space-1: 4px;
	--bb-space-2: 8px;
	--bb-space-3: 12px;
	--bb-space-4: 16px;
	--bb-space-5: 24px;
	--bb-space-6: 32px;
	--bb-space-7: 48px;
	--bb-space-8: 64px;
	--bb-gutter-mobile: 16px;
	--bb-gutter-desktop: 32px;
	/* Typographie — Montserrat partout (retour owner, 2026-09-02 : « change
	   toutes les polices restantes vers Montserrat »), Poppins/Inter retirés
	   (plus aucun usage une fois --bb-font-display/--bb-font-body redirigés
	   ci-dessous — @font-face et fichiers .woff2 correspondants supprimés).
	   'Cairo' reste en repli pour l'arabe dans TOUS les tokens (Montserrat
	   n'a pas de glyphes arabes, TEMPLATE.md §5 : le RTL doit rester
	   fonctionnel) — un seul token source, les autres n'en sont que des
	   alias pour garder leur nom d'usage (display/body/topbar) sans dupliquer
	   la liste de polices trois fois. Fichiers auto-hébergés en @font-face
	   plus bas, aucun CDN (TEMPLATE.md). */
	--bb-font-montserrat: 'Montserrat', 'Cairo', sans-serif;
	--bb-font-display: var(--bb-font-montserrat);
	--bb-font-body: var(--bb-font-montserrat);
	--bb-font-topbar: var(--bb-font-montserrat);

	/* Story 4.2 — accents par produit (DESIGN.md colors.accent-*), jamais
	   repris en :root jusqu'ici (Story 4.1 n'en avait pas besoin). Utilisés
	   UNIQUEMENT comme bordure/point décoratif du badge-catégorie, jamais
	   comme couleur de texte (cf. .bb-badge-category ci-dessous — jusqu'à
	   1,65:1 pour accent-ginger, sous le seuil AA). */
	--bb-accent-ginger: #C7D22E;
	--bb-accent-fortifiant: #E14F63;
	--bb-accent-oignon: #7C63C4;
	--bb-accent-keratine: #35B873;
	--bb-accent-masque: #B8A6DA;
}

/* ── Marge extérieure du site (0,5 cm de chaque côté, 0,2 cm en mobile) ────
   `margin-inline` (logique, donc correcte en RTL sans règle miroir) sur
   `body` : s'applique à TOUT le site (header, contenu, footer), une seule
   fois, au niveau le plus haut possible. Bat `body{margin:0}` (Astra,
   main.min.css) à spécificité égale (0-0-1) grâce à l'ordre d'impression —
   `bbio-theme` est enqueue avec `astra-theme-css` en dépendance
   (functions.php), donc toujours imprimée après.
   Aucun effet sur `.bb-hero` (héro plein cadre, plus bas dans ce fichier) :
   son patron `width:100vw; margin-inline:calc(50% - 50vw)` s'annule
   algébriquement contre N'IMPORTE QUELLE marge/padding posée par SES
   ANCÊTRES, `body` compris — c'est le même raisonnement, déjà vérifié en
   pratique, qui le faisait déjà sortir du padding de `.aod-home` et du
   conteneur Astra. Rien à faire de plus pour que le héro continue de
   toucher les deux bords réels de la fenêtre.

   Retour owner (2026-09-06) : « en mobile, marge extérieure de 0,2 cm sur
   tout le site » — 0,5 cm mangeait trop de largeur utile sur petit écran.
   Même seuil que le reste du fichier (max-width:767.98px, EXPERIENCE.md/
   `.aod-home` grille de produits juste plus bas). `.aod-home` reprend cette
   même valeur en padding-inline (voir plus bas) : les deux DOIVENT rester
   synchronisés, sinon la grille "Nos produits"/"Nos catégories" ne
   s'aligne plus avec le reste de la page sous 768px. */
body {
	margin-inline: 0.5cm;
}

@media ( max-width: 767.98px ) {
	body {
		margin-inline: 0.2cm;
	}
}

/* Retour owner (2026-09-02) : « change toutes les polices restantes vers
   Montserrat ». Mesuré, pas supposé (audit Playwright : tous les éléments
   texte visibles des 3 pages publiques dont la police calculée n'était ni
   Montserrat ni Cairo) : au-delà des tokens --bb-font-* déjà posés sur des
   sélecteurs précis, une bonne partie du texte restant (prix WooCommerce,
   switcher FR/العربية, liens de fil d'ariane, "Lire la suite", options du
   tri Boutique…) n'hérite d'AUCUN de ces tokens — il retombe sur la police
   système de base d'Astra : `body,button,input,select,textarea{font-family:
   -apple-system,…}` (main.min.css). Même sélecteur ICI, à l'identique
   (spécificité 0-0-5 des deux côtés) : `bbio-theme` étant enqueue APRÈS
   `astra-theme-css` (functions.php), cette règle gagne à spécificité égale
   sans `!important` — même patron que la marge de `body` ci-dessus.
   `button`/`input`/`select`/`textarea` répétés à dessein : un `<button>` ou
   un `<select>` n'hérite PAS du `font-family` de `body` par défaut (feuille
   de style utilisateur du navigateur) — c'est exactement pourquoi Astra les
   liste explicitement, et pourquoi les retirer ici laisserait formulaires et
   listes déroulantes dans la police système. */
body,
button,
input,
select,
textarea {
	font-family: var(--bb-font-montserrat);
}

/*
 * Polices auto-hébergées (DESIGN.md Typography + TEMPLATE.md : pas de CDN de
 * polices en production). `arabic`+`latin` pour Cairo (variable,
 * `font-weight: 200 1000` — une seule déclaration par sous-ensemble sert
 * tous les poids utilisés).
 *
 * Montserrat — TOUTE la typographie latine du site (retour owner,
 * 2026-09-02 : « change toutes les polices restantes vers Montserrat »),
 * Poppins ET Inter retirés (plus aucun token n'y renvoie depuis le bloc
 * `:root` ci-dessus — @font-face ET fichiers .woff2 supprimés avec eux,
 * poppins-latin-{600,700}.woff2 et inter-var.woff2). 4 poids auto-hébergés
 * — ceux réellement utilisés par ce fichier (400/500/600/700, vérifié par
 * un passage sur chaque `font-weight` combiné à --bb-font-display/-body/
 * -topbar/-montserrat), pas la plage variable complète.
 */
@font-face {
	font-family: 'Cairo';
	font-style: normal;
	font-weight: 200 1000;
	font-display: swap;
	src: url('../fonts/cairo-var-arabic.woff2') format('woff2');
	unicode-range: U+0600-06FF, U+0750-077F, U+0870-088E, U+0890-0891, U+0897-08E1, U+08E3-08FF, U+200C-200E, U+2010-2011, U+204F, U+2E41, U+FB50-FDFF, U+FE70-FE74, U+FE76-FEFC;
}
@font-face {
	font-family: 'Cairo';
	font-style: normal;
	font-weight: 200 1000;
	font-display: swap;
	src: url('../fonts/cairo-var-latin.woff2') format('woff2');
	unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+20AC, U+2122;
}
@font-face {
	font-family: 'Montserrat';
	font-style: normal;
	font-weight: 400;
	font-display: swap;
	src: url('../fonts/montserrat-latin-400.woff2') format('woff2');
}
@font-face {
	font-family: 'Montserrat';
	font-style: normal;
	font-weight: 500;
	font-display: swap;
	src: url('../fonts/montserrat-latin-500.woff2') format('woff2');
}
@font-face {
	font-family: 'Montserrat';
	font-style: normal;
	font-weight: 600;
	font-display: swap;
	src: url('../fonts/montserrat-latin-600.woff2') format('woff2');
}
@font-face {
	font-family: 'Montserrat';
	font-style: normal;
	font-weight: 700;
	font-display: swap;
	src: url('../fonts/montserrat-latin-700.woff2') format('woff2');
}

/* --ac-* (aod-cart.css, panier COD) : déclarées sur :root dans le plugin. */
html:root {
	--ac-accent: var(--bb-brand-teal-dark);
	--ac-accent-dark: var(--bb-brand-teal-dark-hover);
	--ac-danger: var(--bb-feedback-error);
	--ac-ink: var(--bb-ink-navy);
	--ac-line: var(--bb-border-hairline);
	--ac-surface: #FFFFFF;
	--ac-r-md: var(--bb-rounded-md);
	--ac-r-sm: var(--bb-rounded-sm);
	/* Coins du panneau panier COD lui-même — pas de pendant --sh-* (le
	   formulaire n'a pas de bloc flottant équivalent). */
	--ac-r-lg: var(--bb-rounded-lg);
	/* Fond des états sélectionnés (ligne panier) : dérivé du nouvel accent. */
	--ac-accent-wash: var(--bb-brand-teal-wash);
}

/* --sh-* (aod-cod-form.css, formulaire COD) : déclarées sur .aod-cod, pas sur
   :root -> doivent être redéclarées sur .aod-cod lui-même pour battre la
   déclaration du plugin (voir en-tête de fichier).
   `font-family` (2026-09-02, retour owner « toutes les polices ») : PAS une
   variable --sh-*, le plugin la pose en dur sur `.aod-cod` lui-même
   (aod-cod-form.css : `-apple-system, …, Arial, sans-serif`) — même
   correctif que les --sh-* ci-dessous, même sélecteur, à la fois pour battre
   la spécificité ET l'ordre d'impression (aod-cod-form.css charge APRÈS
   theme.css sur la page produit/Contact, cf. Dev Notes de
   `.aod-contact__form.aod-cod` plus bas dans ce fichier). Hérite jusqu'aux
   labels/boutons du formulaire (`font-family` se transmet normalement, sauf
   aux contrôles de formulaire — mais le plugin les laisse hériter
   explicitement, vérifié : aucun `font-family` propre sur `.aod-cod__submit`
   dans aod-cod-form.css). */
html:root .aod-cod {
	--sh-accent: var(--bb-brand-teal-dark);
	--sh-accent-dark: var(--bb-brand-teal-dark-hover);
	--sh-error: var(--bb-feedback-error);
	--sh-text: var(--bb-ink-navy);
	--sh-line: var(--bb-border-hairline);
	--sh-bg: #FFFFFF;
	--sh-radius: var(--bb-rounded-md);
	--sh-radius-sm: var(--bb-rounded-sm);
	/* Fond des états sélectionnés (option choisie) : dérivé du nouvel accent,
	   pas de l'ancien vert Shopify. --sh-green (réassurance/confirmation)
	   volontairement non touchée — hors périmètre de cette story. */
	--sh-accent-wash: var(--bb-brand-teal-wash);
	font-family: var(--bb-font-montserrat);
}

/*
 * Logo K KLEMERLAIN (Story 2.2) — hauteur maximale imposée par DESIGN.md
 * (header.logo-max-height: 40px). Astra ne pilote qu'une LARGEUR via son
 * réglage Personnalisateur (ast-header-responsive-logo-width) ; la hauteur
 * suit ensuite le ratio naturel du fichier. Le logo fourni (1080x231px,
 * ratio ~4.68:1) est plus « plat » que le ratio par défaut d'Astra (3:1) :
 * fixer uniquement une largeur serait fragile à chaque changement de ce
 * réglage. max-height + width:auto est robuste quel que soit ce réglage.
 * Sélecteur vérifié contre le HTML réellement servi (curl), pas supposé :
 * <span class="site-logo-img"><a class="custom-logo-link">
 *   <img class="custom-logo" ...></a></span>
 *
 * ⚠️ Cette règle a une spécificité (0-2-1) supérieure aux règles de largeur
 * qu'Astra génère dynamiquement depuis son propre réglage Personnalisateur
 * « Largeur du logo » (0-1-2 aux 3 points de rupture, vérifié dans
 * astra/inc/class-astra-dynamic-css.php:647,3786,3885) : ce contrôle natif
 * devient donc SILENCIEUSEMENT INERTE pour ce logo, quelle que soit la
 * valeur que le gérant y saisirait. C'est un choix assumé, pas un oubli —
 * la contrainte de hauteur de DESIGN.md est incompatible par construction
 * avec une largeur libre sur un logo à ratio fixe (~4.68:1, différent du
 * 3:1 par défaut d'Astra). Trouvé en revue de code (2026-08-31).
 */
.custom-logo-link img.custom-logo {
	max-height: var(--bb-header-logo-max-height);
	width: auto;
}

/*
 * Barre d'annonce (Accueil/Boutique/Contact, includes/home-announcement-bar.php)
 * — au-dessus de la topbar, messages qui défilent. Permanente, sans bouton de
 * fermeture — retrait demandé par l'owner (2026-09-02) : un premier essai
 * portait une croix de fermeture, jugée superflue une fois la barre rendue
 * non-intrusive (un seul message à la fois, hauteur fixe).
 *
 * ⚠️ PAS « naturellement plein cadre » comme l'affirmait un commentaire
 * précédent — corrigé sur retour owner (2026-09-02), mesuré (pas supposé) :
 * si la barre échappe bien à tout conteneur Astra (hook `astra_header_before`,
 * hors `.aod-home`), elle reste display DANS `<body>`, qui porte
 * `margin-inline: 0.5cm` (tout en haut de ce fichier) — un filet blanc de
 * 0,5 cm restait donc visible de chaque côté. Même patron que `.bb-hero`/
 * `.aod-home` plus bas dans ce fichier pour en sortir : `width:100vw` +
 * `margin-inline:calc(50% - 50vw)`, qui s'annule algébriquement contre
 * N'IMPORTE QUELLE marge/padding posée par ses ancêtres, `body` compris.
 */
.bb-announce {
	width: 100vw;
	margin-inline: calc( 50% - 50vw );
	background: var(--bb-brand-teal-dark);
	color: var(--bb-surface-white);
	padding-inline: var(--bb-space-5);
}

/* Défilement VERTICAL du message actif (translation de la liste, pas un
   fondu) — demande explicite de l'owner : « les messages qui se défilent »,
   un simple fondu ne se lisait pas comme un défilement. `.bb-announce__list`
   translatée par JS d'une hauteur de message à la fois ; le viewport
   `overflow:hidden` ne laisse voir que la ligne active. Sans JS, la liste
   reste à sa position d'origine (translateY(0)) : le premier message reste
   affiché en continu, jamais de bandeau vide — dégradation obligatoire,
   même principe que le reste du thème. */
.bb-announce__viewport {
	position: relative;
	height: 2.75rem;
	overflow: hidden;
}

.bb-announce__list {
	margin: 0;
	padding: 0;
	list-style: none;
	transition: transform 0.5s ease;
}

.bb-announce__item {
	height: 2.75rem;
	display: flex;
	align-items: center;
	justify-content: center;
	text-align: center;
	font-family: var(--bb-font-body);
	font-size: 0.85rem;
	font-weight: 500;
	line-height: 1.3;
	padding-inline: var(--bb-space-2);
}

@media ( prefers-reduced-motion: reduce ) {
	.bb-announce__list {
		transition: none;
	}
}

@media ( max-width: 600px ) {
	.bb-announce {
		padding-inline: var(--bb-space-3);
	}

	/* Deux lignes possibles sur mobile étroit — les messages sont plus
	   longs que la largeur disponible à cette taille de police. Les DEUX
	   valeurs doivent rester synchronisées : `.bb-announce__item` est
	   désormais en flux normal (plus en `position:absolute`), sa hauteur
	   RÉELLE doit correspondre à celle du viewport pour que la translation
	   JS (mesurée sur `items[0]`, cf. theme.js) tombe juste. */
	.bb-announce__viewport {
		height: 3.4rem;
	}

	.bb-announce__item {
		height: 3.4rem;
		font-size: 0.78rem;
	}
}

/*
 * Bandeau de confiance DANS la topbar (includes/header-trust-badge.php) —
 * icône végane + « Testés et validés dermatologiquement », en #162950
 * (= --bb-brand-teal-dark, TOUJOURS ce token, jamais un littéral dupliqué —
 * retour owner 2026-09-02 : « change toutes les couleurs bleues par
 * #162950 »). Distinct de `.bb-announce` ci-dessus (AU-DESSUS de la topbar,
 * plusieurs messages qui défilent) : injecté via `astra_masthead_top`,
 * DIRECTEMENT enfant de `<header id="masthead">`.
 *
 * Retour owner (2026-09-05) : « fusionné dans la ligne logo/menu, au milieu ».
 * En dessous de 1200px, la ligne reste une ligne normale, empilée au-dessus de
 * `#ast-desktop-header`/`#ast-mobile-header` (flux normal, comme avant) —
 * MESURÉ (pas supposé) : entre le point de rupture mobile d'Astra (921px —
 * vérifié dans le HTML réellement servi :
 * `@media (min-width:922px){#ast-mobile-header{display:none}}`) et 1200px, la
 * ligne logo/nav est bien affichée en desktop mais l'espace libre entre le
 * logo et « Accueil » est trop étroit pour la phrase entière — chevauchement
 * réel constaté à 1024px avant ce seuil. À partir de 1200px (espace mesuré
 * largement suffisant), le bandeau passe en position absolue centrée sur
 * `#masthead` : il rejoint alors VISUELLEMENT la même ligne que le logo/menu,
 * sans lui ajouter de hauteur (l'absolu le retire du flux). `pointer-events:none` :
 * ligne purement décorative (aucun lien dedans), pour ne jamais intercepter un
 * clic sur le logo/menu si l'espace venait à se resserrer malgré tout (zoom
 * navigateur, futur changement de logo/menu…).
 */
.bb-header-trust {
	display: flex;
	align-items: center;
	justify-content: center;
	gap: var(--bb-space-2);
	padding-block: 0.5rem;
	padding-inline: var(--bb-space-3);
	font-family: var(--bb-font-topbar);
	font-size: 0.75rem;
	font-weight: 600;
	letter-spacing: 0.03em;
	color: var(--bb-brand-teal-dark);
	text-align: center;
}

.bb-header-trust__icon {
	display: inline-flex;
	flex-shrink: 0;
	color: var(--bb-brand-teal-dark);
}

/* Retour owner (2026-09-06) : « ce logo (l'icône végane) doit être grand,
   que les visiteurs le voient très bien » — 1rem (16px) se perdait à côté
   du logo/menu. Tailles reprises à CHAQUE point de rupture ci-dessous
   (1.6rem ici, puis 2rem/2.25rem plus bas) plutôt qu'un seul saut : sans ça
   le badge redeviendrait proportionnellement minuscule dès le premier
   palier (600px), comme avant ce correctif.
   ⚠️ Plafond volontaire à 1200px : `--bb-header-logo-max-height` (:root,
   40px) borne déjà la hauteur de toute la ligne logo/menu — un icône plus
   grand qu'elle risquerait de dépasser de la topbar une fois le badge
   superposé en `position:absolute` (cf. Dev Notes de `.bb-header-trust`
   plus haut). 2.25rem (36px) reste sous ce plafond. */
.bb-header-trust__icon svg {
	width: 1.6rem;
	height: 1.6rem;
	display: block;
}

/* Retour owner (2026-09-05) : « que ça clignote en vert pour attirer
   l'attention ». Un vrai on/off (`visibility`/`opacity:0`) est à la fois plus
   agressif ET un risque d'accessibilité (clignotement rapide) — un fondu de
   COULEUR (texte + icône, `currentColor` oblige à cibler les deux sélecteurs)
   entre le bleu de marque et un vert, assez lent (1,8 s, `ease-in-out`), lit
   comme une pulsation qui attire l'œil sans jamais disparaître ni déclencher
   de seuil photosensible (bien en dessous de 3 flashs/seconde). Vert choisi
   proche de celui déjà connu sur ce thème (pastille active du switcher
   FR/العربية, `#16a34a`, cf. plus bas dans ce fichier) plutôt qu'une teinte
   inventée. Coupé sous `prefers-reduced-motion`, même patron que
   `.bb-announce__list` plus haut. */
.bb-header-trust,
.bb-header-trust__icon {
	animation: bb-header-trust-pulse 1.8s ease-in-out infinite;
}

@keyframes bb-header-trust-pulse {
	0%, 100% {
		color: var(--bb-brand-teal-dark);
	}
	50% {
		color: #16A34A;
	}
}

@media ( prefers-reduced-motion: reduce ) {
	.bb-header-trust,
	.bb-header-trust__icon {
		animation: none;
	}
}

@media ( min-width: 600px ) and ( max-width: 1199px ) {
	.bb-header-trust {
		gap: var(--bb-space-3);
		font-size: 0.85rem;
	}

	.bb-header-trust__icon svg {
		width: 2rem;
		height: 2rem;
	}
}

/* Même point de rupture qu'Astra pour la ligne logo/nav complète (desktop) —
   cf. Dev Notes ci-dessus. `.site-header` = `#masthead` (l'attribut `id` ET la
   classe sont posés sur le même élément, vérifié dans le HTML réellement
   servi), donc `position:relative` ici suffit à ancrer l'overlay sans toucher
   à un seul sélecteur du thème parent Astra.
   `z-index: 20` (pas 1) — vérifié via le protocole DevTools (CDP) directement,
   pas supposé : à 1, l'élément a un `getBoundingClientRect()`/`getComputedStyle()`
   entièrement correct (position, taille, couleurs, opacité, aucun clip/overflow
   parent) mais ne PEINT PAS — `elementFromPoint()` sur son propre centre saute
   par-dessus lui. Un `z-index` local plus élevé (testé : 2 encore invisible,
   10 déjà visible) le fait apparaître, sans rien changer d'autre. `.site-header`
   étant déjà son propre contexte d'empilement (z-index:99, posé par Astra), ce
   z-index reste purement LOCAL à l'intérieur de la topbar — aucun risque de
   passer au-dessus d'un élément hors du header. */
@media ( min-width: 1200px ) {
	.site-header {
		position: relative;
	}

	.bb-header-trust {
		position: absolute;
		inset: 0;
		margin: auto;
		width: fit-content;
		height: fit-content;
		padding-block: 0;
		padding-inline: 0;
		gap: var(--bb-space-3);
		font-size: 0.88rem;
		pointer-events: none;
		z-index: 20;
		white-space: nowrap;
	}

	.bb-header-trust__icon svg {
		width: 2.25rem;
		height: 2.25rem;
	}
}

/* 🔴 « VEGAN 100% » (2026-09-08) a allongé la phrase de 11 caractères — mesuré
   au pixel (Playwright, viewport réel) : à 1200px la boîte centrée (496px de
   large à 0,88rem) chevauchait « Accueil » de 38 px, et l'écart restait sous
   3 px jusqu'à 1330px (889 px de large à 1280 pour un espace de 890-967 —
   visuellement collé, même sans chevauchement mesurable). Réduire ICI, sur
   cette seule tranche, plutôt que sur tout `min-width:1200px` : au-delà rien
   ne clochait, et un badge plus petit qu'il ne pourrait l'être desservirait
   le retour owner du 2026-09-06 (« ce logo doit être grand »). */
@media ( min-width: 1200px ) and ( max-width: 1339.98px ) {
	.bb-header-trust {
		gap: var(--bb-space-2);
		font-size: 0.72rem;
	}

	.bb-header-trust__icon svg {
		width: 1.75rem;
		height: 1.75rem;
	}
}

/*
 * En-tête — logo seul (sans le nom du site) + habillage aux couleurs/police
 * de marque (retour owner, 2026-09-01).
 *
 * ⚠️ Le nom du site ("BELLISSIMA BIO", ou tout autre saisi par un futur
 * client dans Réglages > Général / le Personnalisateur) N'EST PAS supprimé
 * en dur : `.site-title` reste la donnée réelle, seul son affichage est
 * masqué ICI en CSS — TEMPLATE.md §1, rien de spécifique à un client codé
 * en dur, et un futur clone qui voudrait le réafficher (ex. logo absent)
 * n'a qu'à retirer cette seule règle.
 * Corrige AUSSI un bug mobile préexistant, indépendant de la demande :
 * sans cette règle, `.site-title` (26px, `display:block`, aucune largeur
 * contrainte) s'enroulait caractère par caractère sur une colonne verticale
 * sous ~400px de large — mesuré, Chromium headless réel, avant correctif.
 */
.site-header .ast-site-title-wrap {
	display: none;
}

.site-header {
	background: var(--bb-surface-white);
	border-bottom: 1px solid var(--bb-border-hairline);
}

/* Liens de nav en police de marque (--bb-font-topbar, cf. commentaire
   ci-dessous pour son historique — Montserrat depuis le 2026-09-02), pas la
   police système par défaut d'Astra : cohérence avec les titres/boutons du
   reste du site. `.menu-link` : classe posée par
   `AOD_COD_Pages::translate_menu_labels()` sur les 3 entrées du menu
   (vérifiée dans le HTML réellement servi), stable contrairement à un
   sélecteur qui viserait l'ID généré du menu.
   `color` en `!important` : sans lui, la couleur de base d'Astra
   (`.ast-builder-menu-1 .menu-item > .menu-link`, injectée en `<style>`
   inline par le Customizer) l'emporte MALGRÉ une spécificité inférieure sur
   le papier (0-3-0 contre 0-4-0 ici, avec le préfixe `.site-header`) — même
   phénomène déjà rencontré et documenté plus bas pour
   `.ast-on-card-button:focus-visible` (CSS dynamique Astra imprévisible face
   à la spécificité déclarée). Mesuré en isolant chaque règle CSSOM
   (`deleteRule` un par un, transition de 0,2s d'Astra laissée se stabiliser
   avant lecture), pas supposé. */
/* Retour owner (2026-09-02) : « change la police de la topbar vers
   Montserrat » — remplace --bb-font-display (Poppins/Cairo) par le token
   dédié --bb-font-topbar ci-dessus, avec le detail demandé : graisse ~400,
   taille ~12-13px, bleu/gris foncé (déjà --bb-ink-navy, ne change pas) et
   lettres espacées (`letter-spacing`, absent jusqu'ici). */
.site-header .main-header-menu .menu-link {
	font-family: var(--bb-font-topbar);
	font-weight: 400;
	font-size: 13px;
	letter-spacing: 0.04em;
	color: var(--bb-ink-navy) !important;
	/* Support du soulignement décoratif ci-dessous (page courante/survol),
	   posé sur le lien plutôt que le <li> pour suivre exactement sa largeur
	   de texte. */
	position: relative;
	padding-block-end: var(--bb-space-1);
}

.main-header-menu .menu-link::after {
	content: '';
	position: absolute;
	inset-inline-start: 0;
	inset-block-end: -1px;
	width: 100%;
	height: 2px;
	background: var(--bb-brand-teal);
	transform: scaleX( 0 );
	transform-origin: center;
	transition: transform 0.15s ease;
}

/* Même piège que la règle de base ci-dessus, sur :hover/:focus/page courante
   cette fois : `.ast-builder-menu-1 .menu-link:hover` (Astra, 0-3-0)
   l'emportait sur notre 0-4-0 malgré la spécificité — `!important`
   nécessaire, mesuré de la même façon (isolement de règle CSSOM, transition
   0,2s stabilisée avant lecture). */
.site-header .main-header-menu .menu-link:hover,
.site-header .main-header-menu .menu-link:focus,
.site-header .main-header-menu .menu-item.current-menu-item > .menu-link {
	color: var(--bb-brand-teal-dark) !important;
}

.main-header-menu .menu-link:hover::after,
.main-header-menu .menu-link:focus::after,
.main-header-menu .menu-item.current-menu-item > .menu-link::after {
	transform: scaleX( 1 );
}

/* Switcher FR/العربية (plugin aod-cod-form, jamais modifié dans
   plugins-dev/ — TEMPLATE.md §0) : sa pastille active est verte par défaut
   (`#16a34a`, style générique du plugin), qui jurait à côté du bleu Astra
   d'origine ET du teal de marque posé ci-dessus. Recolorée ICI, en CSS
   seul, sans toucher au fichier du plugin. `!important` nécessaire :
   `class-aod-cod-lang.php` pose déjà `!important` sur `.aod-lang__btn.is-active`,
   seule une spécificité au moins égale + `!important` peut la battre. */
.aod-lang__btn.is-active {
	background: var(--bb-brand-teal-dark) !important;
}

/* Retour owner (2026-09-01) : le héro doit toucher directement la topbar
   (« la hauteur de cette section s'étend jusqu'à la topbar »), sans l'espace
   qu'Astra pose par défaut au-dessus de la zone de contenu. Mesuré (pas
   supposé) : la source réelle de ce blanc est
   `.ast-plain-container.ast-no-sidebar #primary{margin-top:60px}` (réglage
   global Astra « Espacement du contenu »), PAS un padding du héro lui-même.
   Neutralisé UNIQUEMENT sur l'Accueil (`body.home`, classe posée par
   WordPress sur la page statique définie comme page d'accueil) : les 2
   autres pages publiques (Boutique/Contact) gardent cet espacement, jamais
   demandé de le retirer là. `!important` nécessaire : la règle Astra
   ci-dessus a 2 classes + 1 ID (1-2-0) contre 1 ID + 1 classe + 1 type
   (1-1-1) ici — spécificité réellement supérieure, pas le phénomène
   habituel de CSS dynamique qui l'emporte malgré une spécificité inférieure
   sur le papier (documenté plus haut pour la nav). */
body.home #primary {
	margin-top: 0 !important;
}

/*
 * Fiche produit — structure 2 colonnes (Story 3.1, architecture.md Décision 4).
 * Galerie à gauche, colonne résumé (titre/prix/formulaire COD, rendue par
 * woocommerce_single_product_summary — jamais touchée ici) à droite en desktop ;
 * empilé en mobile. Point de rupture 768px repris des seuils déjà standards
 * d'Astra (tablette/desktop), DESIGN.md n'imposant aucune valeur pour ce
 * composant précis — cf. Dev Notes de la story.
 *
 * Portée volontairement minimale : uniquement la structure. Le style complet
 * (badges, argumentaire, ingrédients, barre collante du mockup
 * mockups/fiche-produit.html) est hors périmètre de cette story.
 */
.bb-product-layout {
	display: block;
}

/*
 * Neutralise le float/width hérité de la mise en page WooCommerce/Astra sur
 * .images et .summary.entry-summary — trouvé lors d'une vérification visuelle
 * réelle (Chrome headless) après la première version de cette règle : Astra
 * fixe .images{float:left;width:48%} et .summary{float:right;width:48%}
 * SANS AUCUNE dépendance de largeur d'écran (vérifié dans
 * astra/inc/.../compatibility/woocommerce/woocommerce-layout-grid.min.css,
 * media="all", et confirmé que le fichier gated en max-width:921px ne les
 * réinitialise jamais). Sans ce correctif, ces 48% s'appliquaient À
 * L'INTÉRIEUR de nos propres colonnes (déjà à ~50% chacune), écrasant
 * galerie et formulaire à ~24% de la largeur totale — sur desktop ET mobile,
 * puisque ces règles Astra ne sont jamais conditionnées par un point de
 * rupture.
 *
 * ⚠️ Un premier correctif ici (chaîne de classes seule, 0-5-1) s'est révélé
 * INSUFFISANT — vérifié visuellement (toujours écrasé après déploiement) :
 * la véritable règle Astra comporte 4 variantes séparées par virgule, dont
 * DEUX qualifiées par `#content` (un ID — `.woocommerce #content div.product
 * div.images`, spécificité 1-3-2). Ce thème a bien un `<div id="content"
 * class="site-content">` ancêtre (vérifié dans le HTML réellement servi) :
 * cette variante s'applique donc, et aucune chaîne de classes ne peut
 * jamais la battre. D'où `#content` repris ici — spécificité 1-5-1, bat
 * 1-3-2 sans `!important`.
 *
 * ⚠️ Repli volontaire ci-dessous : les 2 autres variantes d'Astra (sans
 * `#content`, ex. `.woocommerce div.product div.images{float:left;width:48%}`,
 * spécificité 0-3-2) s'appliqueraient si un futur gabarit de CE clone — ou
 * d'un futur clone de ce template sur un thème sans `#content` (Elementor
 * Theme-Builder, canvas, ou un autre thème classique de TEMPLATE.md §4 —
 * GeneratePress/Neve/Blocksy/Kadence — qui ne partage pas nécessairement
 * cette structure Astra) — rend `.bb-product-gallery`/`.summary.entry-summary`
 * sans ancêtre `#content`. Le repli reprend la même chaîne sans `#content`
 * (0-5-1) : bat la variante non-`#content` d'Astra (0-3-2) sans dépendre de
 * son existence. Trouvé en revue de code, 2026-08-31.
 */
.woocommerce #content div.product .bb-product-layout .bb-product-gallery,
.woocommerce #content div.product .bb-product-layout .bb-product-gallery .images,
.woocommerce #content div.product .bb-product-layout .summary.entry-summary,
.woocommerce div.product .bb-product-layout .bb-product-gallery,
.woocommerce div.product .bb-product-layout .bb-product-gallery .images,
.woocommerce div.product .bb-product-layout .summary.entry-summary {
	float: none;
	width: 100%;
}

/*
 * Galerie produit — miniatures verticales en desktop (Story 3.2, AC #1).
 * CSS SEUL, aucun override `woocommerce/single-product/*.php`.
 *
 * Fait vérifié par lecture du CSS Astra réellement servi ET par un dump DOM
 * post-JS (Chromium headless, produit réel) : flexslider (`initFlexslider`,
 * WooCommerce core) ne verticalise jamais lui-même les miniatures — il génère
 * un élément SÉPARÉ, `<ol class="flex-control-nav flex-control-thumbs">`,
 * SIBLING de `.flex-viewport` (pas un enfant), tous deux enfants directs de
 * `.woocommerce-product-gallery`. Astra pose sur ces miniatures un simple
 * `float:left;width:25%` (`.flex-control-thumbs li`, CSS classique, AUCUN
 * positionnement JS/transform). Le slide-track horizontal réel
 * (`.flex-viewport` > `.woocommerce-product-gallery__wrapper`, positionné par
 * `translate3d` à l'exécution) n'est JAMAIS ciblé ci-dessous — verticaliser
 * les miniatures ne touche donc jamais le mécanisme de swipe/drag du slider,
 * vérifié empiriquement (navigateur réel) après déploiement.
 *
 * ⚠️ Spécificité — piège identique à la Story 3.1, revérifié EMPIRIQUEMENT
 * (pas juste par `grep`) après un premier déploiement qui semblait échouer :
 * une capture d'écran a montré les miniatures écrasées à ~7px de large, hors
 * de la colonne galerie. Cause trouvée via `CSS.getMatchedStylesForNode`
 * (Chrome DevTools Protocol, `playwright-core` + Chromium headless local) :
 * la RÉELLE règle Astra qui gagnait n'était PAS celle isolée par un premier
 * `grep .flex-control-thumbs` (`.woocommerce-product-gallery--columns-4
 * .flex-control-thumbs li`, 0-2-1) mais une variante plus qualifiée présente
 * dans le même fichier compilé, jamais vue au premier passage :
 * `.woocommerce-js div.product div.woocommerce-product-gallery--columns-4
 * .flex-control-thumbs li` (0-4-3 — 3 sélecteurs de TYPE, `div`+`div`+`li`,
 * pas 2 : compte recorrigé en revue de code, la story affirmait à tort 0-4-2
 * — n'invalide pas le correctif, l'ID `#content` gagne quel que soit le
 * compte exact — et `woocommerce-js`, classe posée sur `<body>` par le JS
 * natif de WooCommerce). Un simple `grep` sur un motif ISOLÉ
 * (`.flex-control-thumbs`) peut donc rater une variante plus longue du même
 * sélecteur si elle n'apparaît que préfixée ailleurs dans le fichier — la
 * leçon de la Story 3.1 (« vérifier la cascade réellement servie, pas une
 * estimation ») s'étend ici à : *vérifier via l'inspecteur de correspondance
 * de règles, pas seulement `grep`, quand un premier correctif semble échouer
 * malgré une spécificité en apparence suffisante*. D'où `#content` repris ici
 * comme en Story 3.1 : un ID bat n'importe quelle chaîne de classes, quel que
 * soit son nombre réel — plus besoin de compter les classes d'Astra pour
 * être sûr de gagner. Et, comme en Story 3.1 (cf. bloc float/width plus
 * haut), un repli sans `#content` accompagne chaque règle `#content`-qualifiée
 * ci-dessous : même raison de généricité (TEMPLATE.md §4, thème futur sans
 * `#content`). Trouvé en revue de code, 2026-08-31.
 *
 * `order` (pas `row-reverse`) : place les miniatures au DÉBUT de l'axe
 * flex — gauche en FR (LTR), droite en AR (RTL), automatiquement, sans
 * sélecteur `[dir=rtl]` (même principe que le grid 2 colonnes de la
 * Story 3.1, vérifié par capture d'écran FR et AR).
 */
@media ( min-width: 768px ) {
	.bb-product-layout {
		display: grid;
		grid-template-columns: 1fr 1fr;
		/* Littéral volontaire, pas var(--bb-rounded-lg) : un jeton de RAYON DE
		   BORDURE ne doit pas piloter un ESPACEMENT — même valeur par choix
		   visuel, mais les deux concepts doivent pouvoir diverger sans se
		   coupler. Aucun jeton d'espacement n'existe encore dans DESIGN.md
		   pour ce composant (cf. Dev Notes de la story) ; ne pas en créer un
		   pour un seul usage. Trouvé en revue de code, 2026-08-31. */
		gap: 20px;
		align-items: start;
	}

	/*
	 * Panier COD (plugin aod-cod-form) — vue « panier validé » : la galerie
	 * disparaît (`body.aod-cart-checkout .woocommerce-product-gallery`, cf.
	 * aod-cart.css du plugin, générique) mais la grille 2 colonnes CI-DESSUS
	 * réservait quand même sa piste `1fr` — un cadre vide de 50 % de large à
	 * côté du formulaire. `body.aod-cart-checkout` est la classe GÉNÉRIQUE
	 * posée par le plugin (`applyProductMode()`) ; `.bb-product-layout` est
	 * SPÉCIFIQUE à ce thème enfant — d'où cette règle ICI et pas dans le
	 * plugin (règle 1 du gabarit : rien de spécifique à un client dans le
	 * code générique). Une seule piste : `.summary.entry-summary` (seul
	 * enfant visible) prend alors toute la largeur.
	 */
	body.aod-cart-checkout .bb-product-layout {
		grid-template-columns: 1fr;
	}
	body.aod-cart-checkout .bb-product-gallery {
		display: none;
	}

	.bb-product-gallery .woocommerce-product-gallery.images {
		display: flex;
		align-items: flex-start;
		gap: 12px;
	}

	.bb-product-gallery .woocommerce-product-gallery.images .flex-viewport {
		order: 2;
		flex: 1 1 auto;
		min-width: 0; /* évite qu'un slide large ne pousse la colonne hors du flex */
	}

	/* Produit à IMAGE UNIQUE (pas de galerie) : flexslider ne s'active qu'à
	   partir de 2 images (WooCommerce core, `initFlexslider`) — `.flex-viewport`
	   n'est alors jamais créé, et `.woocommerce-product-gallery__wrapper`
	   devient enfant DIRECT de `.images` au lieu d'être nesté dedans. Sans
	   cette règle, ce cas n'a aucune largeur flex explicite. Trouvé en revue
	   de code, 2026-08-31. */
	.bb-product-gallery .woocommerce-product-gallery.images > .woocommerce-product-gallery__wrapper {
		flex: 1 1 auto;
		min-width: 0;
	}

	.bb-product-gallery .woocommerce-product-gallery--columns-4 .flex-control-thumbs,
	.bb-product-gallery .flex-control-thumbs {
		order: 1;
		display: flex;
		flex-direction: column;
		/* 76px choisi pour loger confortablement une miniature carrée (mesuré
		   à 76×76px lors de la vérification CSS.getMatchedStylesForNode
		   post-correctif) ; aucun jeton dédié dans DESIGN.md pour ce
		   composant — même logique que le `gap: 20px` ci-dessus (littéral
		   assumé plutôt qu'un jeton créé pour un seul usage). Trouvé en
		   revue de code, 2026-08-31. */
		flex: 0 0 76px;
		gap: 8px;
		max-height: 600px;
		overflow-y: auto;
	}

	/* `overflow-y:auto` ci-dessus est battu par la RÉELLE règle Astra
	   `overflow:hidden` sur ce même élément (0-4-3, cf. docblock ci-dessus) :
	   au-delà d'environ 7 miniatures, les suivantes deviennent invisibles et
	   inatteignables sans qu'aucune scrollbar ne soit jamais servie. `#content`
	   (+ repli sans `#content`, même raison de généricité que pour le `li`
	   ci-dessous) gagne quel que soit le compte exact de classes d'Astra.
	   Trouvé en revue de code, 2026-08-31. */
	.woocommerce #content div.product .bb-product-gallery .flex-control-thumbs,
	.woocommerce #content div.product .bb-product-gallery .woocommerce-product-gallery--columns-4 .flex-control-thumbs,
	.woocommerce div.product .bb-product-gallery .flex-control-thumbs,
	.woocommerce div.product .bb-product-gallery .woocommerce-product-gallery--columns-4 .flex-control-thumbs {
		overflow-y: auto;
	}

	.woocommerce #content div.product .bb-product-gallery .flex-control-thumbs li,
	.woocommerce #content div.product .bb-product-gallery .woocommerce-product-gallery--columns-4 .flex-control-thumbs li,
	.woocommerce div.product .bb-product-gallery .flex-control-thumbs li,
	.woocommerce div.product .bb-product-gallery .woocommerce-product-gallery--columns-4 .flex-control-thumbs li {
		width: 100%;
		float: none;
		margin: 0;
	}

	/* Déclencheur zoom PhotoSwipe (`.woocommerce-product-gallery__trigger`,
	   premier enfant de `.images`, positionné par Astra en `right:.5em`
	   PHYSIQUE — pas logique). En LTR, la galerie principale (`order:2`) est
	   visuellement à droite : `right:.5em` tombe dessus, correct. En RTL,
	   l'ordre flex logique place la galerie principale visuellement à
	   GAUCHE (cf. docblock ci-dessus) — `right:.5em` reste physique et
	   atterrit alors sur le rail de miniatures. Vérifié contre le CSS Astra
	   réel et `single-product.js`. Corrigé en repositionnant le déclencheur
	   à gauche uniquement en RTL, plutôt qu'avec une propriété logique CSS
	   (`inset-inline-end` suivrait le SENS D'ÉCRITURE, pas notre propre
	   inversion `order` — les deux coïncident ici mais ce n'est pas garanti
	   pour un futur ajustement de la galerie). Trouvé en revue de code,
	   2026-08-31. */
	html[dir="rtl"] .woocommerce #content div.product .bb-product-gallery .woocommerce-product-gallery__trigger,
	html[dir="rtl"] .woocommerce div.product .bb-product-gallery .woocommerce-product-gallery__trigger {
		right: auto;
		left: .5em;
	}
}

/* Bandeau de badges (includes/product-badges.php, retour owner 2026-09-02) —
   rendu à l'intérieur du panneau Description (.bb-product-description__body
   ci-dessous, includes/product-description-panel.php), lui-même dans la
   colonne .summary entre le résumé/prix et le formulaire COD. Grille
   auto-fill : le nombre d'items varie par produit (4 à 8 selon la fiche,
   cf. Dev Notes de bbio_product_badge_sets()), jamais une largeur de
   colonne fixe codée en dur. */
.bb-product-badges {
	display: grid;
	grid-template-columns: repeat( auto-fill, minmax( 72px, 1fr ) );
	gap: var(--bb-space-4) var(--bb-space-2);
	margin-block: var(--bb-space-5);
	padding-block: var(--bb-space-4);
	border-block: 1px solid color-mix( in srgb, var(--bb-ink-navy) 12%, transparent );
}

.bb-product-badges__item {
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: var(--bb-space-2);
	text-align: center;
	min-width: 0; /* laisse le libellé se réduire à la largeur de sa colonne de grille (sinon un mot long comme « DERMATOLOGIQUEMENT » déborde par-dessus la colonne voisine). */
}

.bb-product-badges__icon {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 44px;
	height: 44px;
	object-fit: contain; /* sans effet tant qu'aucun badge de type "img" n'est utilisé (Halal retiré, cf. product-badges.php) — gardé pour un futur badge de ce type */
	/* Les 9 icônes "svg" tiennent leur trait de cette couleur (`stroke="currentColor"`
	   posé dans chaque fichier assets/icons/badges/*.svg) — même jeton que le
	   libellé juste en dessous, contraste déjà couvert par la porte `contraste`
	   (TEMPLATE.md, tests/run.sh). */
	color: var(--bb-ink-navy);
}

.bb-product-badges__icon svg {
	width: 100%;
	height: 100%;
	display: block;
}

.bb-product-badges__label {
	max-width: 100%;
	overflow-wrap: break-word; /* coupe les mots longs plutôt que de déborder sur le badge voisin, cf. .bb-product-badges__item ci-dessus */
	font-size: 10.5px;
	line-height: 1.25;
	font-weight: 600;
	letter-spacing: 0.02em;
	color: var(--bb-ink-navy);
	text-transform: uppercase;
}

/*
 * Panneau « Description » de la fiche produit (includes/product-description-panel.php,
 * retour owner 2026-09-05 : « lire la description avant de remplir le
 * formulaire »), dans la colonne .summary entre le résumé/prix et le
 * formulaire COD. Remplace l'ancien onglet Description pleine largeur —
 * même contenu (badges + texte), un seul emplacement.
 *
 * `<details>`/`<summary>` natifs, ouverts par défaut (choix owner) :
 * `list-style:none` + masquage du triangle natif (deux pseudo-éléments
 * différents, Chrome/Firefox vs. Safari) au profit d'un chevron SVG inline
 * qui pivote sur LUI-MÊME via [open] — jamais sur `__toggle` en entier, qui
 * contient aussi le libellé (une rotation posée sur un conteneur plus grand
 * que son contenu réel déborde de son propre axe, leçon déjà rencontrée
 * côté /gestion — ROADMAP-AMELIORATIONS.md §9, dette D32).
 */
.bb-product-description {
	margin-block-end: var(--bb-space-5);
	border: 1px solid var(--bb-border-hairline);
	border-radius: var(--bb-rounded-md);
	background: var(--bb-surface-white);
}

.bb-product-description__toggle {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: var(--bb-space-3);
	padding: var(--bb-space-4) var(--bb-space-5);
	font-family: var(--bb-font-display);
	font-size: 1.05rem;
	font-weight: 700;
	color: var(--bb-ink-navy);
	cursor: pointer;
	list-style: none;
	user-select: none;
}

/* Triangle de disclosure natif — Chrome/Firefox (pseudo-élément) et Safari
   (::marker) utilisent deux mécanismes distincts ; les deux doivent être
   masqués pour que seul le chevron SVG ci-dessous reste visible. */
.bb-product-description__toggle::-webkit-details-marker {
	display: none;
}

.bb-product-description__toggle::marker {
	content: '';
}

.bb-product-description__toggle:focus-visible {
	outline: 2px solid var(--bb-brand-teal-dark);
	outline-offset: 2px;
}

.bb-product-description__chevron {
	flex-shrink: 0;
	width: 1rem;
	height: 1rem;
	color: var(--bb-ink-navy);
	transition: transform 0.2s ease;
}

.bb-product-description[open] > .bb-product-description__toggle .bb-product-description__chevron {
	transform: rotate(180deg);
}

@media ( prefers-reduced-motion: reduce ) {
	.bb-product-description__chevron {
		transition: none;
	}
}

.bb-product-description__body {
	padding: 0 var(--bb-space-5) var(--bb-space-5);
}

/* Le bandeau de badges n'a plus besoin de son propre espacement supérieur
   ici : `__body` porte déjà le padding du panneau. */
.bb-product-description__body .bb-product-badges {
	margin-block-start: 0;
}

/*
 * Section « Avis » de la fiche produit — retour owner (2026-09-05) :
 * « styliser et harmoniser », puis (2026-09-06) : rendu jugé trop imposant
 * (taille de police) et pas assez « premium ». Rendu par WooCommerce core
 * (`single-product-reviews.php`, `single-product/review*.php` — jamais
 * copiés dans ce thème, CSS seul ci-dessous) : liste d'avis nue + formulaire
 * natif, sans une seule classe de composant, héritant jusqu'ici des seuls
 * styles Astra génériques. Désormais le SEUL contenu de
 * `woocommerce_after_single_product_summary` (l'onglet Description a été
 * retiré par includes/product-description-panel.php) : pas de nav d'onglets
 * à habiller, juste le titre + la liste + le formulaire.
 *
 * Refonte 2026-09-06 : mise en page à deux colonnes sur bureau (avis à
 * gauche, formulaire « Ajouter un avis » à droite — patron courant des
 * fiches produit premium), cartes reprenant le langage visuel de
 * `.bb-review-card` (Accueil, plus bas dans ce fichier) pour harmoniser les
 * deux endroits où des avis s'affichent, et plusieurs tailles de police
 * resserrées (titre 1.4rem → 1.05rem, texte d'avis explicitement 0.95rem,
 * mention RGPD du formulaire descendue à 0.82rem — jusqu'ici sans
 * `font-size` propre, elle héritait donc de la taille de base et pesait
 * visuellement autant qu'un champ obligatoire).
 *
 * `.star-rating`/`.stars` (notation existante et widget de notation du
 * formulaire) restent le rendu WooCommerce core tel quel (glyphes dorés,
 * déjà cohérents avec la convention universelle des avis en ligne) — non
 * repris ici, uniquement l'agencement autour (marges, alignement).
 */
/* Nav d'onglets Astra (`ul.tabs.wc-tabs`, un seul `<li class="reviews_tab">`
   depuis le retrait de l'onglet Description) : masquée quand elle ne
   contient plus qu'UN item — un sélecteur à un seul onglet, avec son
   soulignement "actif" flottant au-dessus du vrai titre `.woocommerce-Reviews-title`
   juste en dessous, ferait doublon (« Avis (0) » affiché deux fois). Le
   panneau reste visible sans elle : c'est le seul/premier panneau, affiché
   par défaut par le CSS core WooCommerce (`:first-of-type`) que JS soit
   actif ou non — masquer la nav ne cache jamais son contenu. `:has()` borne
   la règle au cas à un seul onglet : un futur onglet supplémentaire (ex.
   attributs produit) restituerait la nav automatiquement. */
.woocommerce-tabs.wc-tabs-wrapper ul.tabs.wc-tabs:has( li:only-child ) {
	display: none;
}

/* `#reviews` ET `.woocommerce-Reviews` : même élément (id + classe sur la
   même balise, single-product-reviews.php). Grille mobile-first à une
   colonne (empilée : avis puis formulaire, l'ordre du DOM) ; passe à deux
   colonnes ci-dessous à partir de 768px — même point de rupture que
   le reste du fichier (cf. `.bb-review-card`, plus bas). Les colonnes CSS
   Grid suivent nativement `direction` : rien à faire pour le RTL (même
   raisonnement que `.bb-institutional`/`.bb-reviews-rail` ailleurs dans ce
   fichier), le formulaire passe simplement à gauche. */
.woocommerce-Reviews {
	display: grid;
	grid-template-columns: 1fr;
	align-items: start;
	gap: var(--bb-space-6);
	margin-block-start: var(--bb-space-7);
	padding-block-start: var(--bb-space-6);
	border-top: 1px solid var(--bb-border-hairline);
}

@media ( min-width: 768px ) {
	.woocommerce-Reviews {
		grid-template-columns: minmax( 0, 1.2fr ) minmax( 0, 1fr );
		gap: var(--bb-space-7);
	}
}

/* Reliquat de clearfix (`div.clear` en fin de template core) : inutile en
   grille — le laisser occuperait sa propre cellule (3ᵉ enfant direct) et
   ajouterait un `gap` de trop en bas de colonne. */
.woocommerce-Reviews > .clear {
	display: none;
}

/* `!important` nécessaire et vérifié : Astra masque ce titre par design
   (`.woocommerce-js #reviews .woocommerce-Reviews-title{display:none}`,
   woocommerce-grid.min.css) — il compte normalement sur le libellé de la
   nav d'onglets juste au-dessus (« Avis (0) ») pour tenir lieu de titre.
   Cette nav est justement celle qu'on masque ci-dessus (un seul onglet) :
   sans ce `!important`, la section n'affiche alors PLUS AUCUN titre (vérifié
   par capture d'écran — trouvé APRÈS un premier passage qui masquait la nav
   sans réactiver ce titre). Spécificité Astra : `.woocommerce-js` + `#reviews`
   + `.woocommerce-Reviews-title` (1-2-0) — largement au-dessus d'une simple
   classe, `!important` plus direct qu'une chaîne de sélecteurs à égaler.
   Taille resserrée (1.4rem → 1.05rem, retour owner 2026-09-06 : « police
   trop grande ») — reste un titre de section, pas un titre de page. */
.woocommerce-Reviews-title {
	display: block !important;
	font-family: var(--bb-font-display);
	font-size: 1.05rem;
	font-weight: 700;
	color: var(--bb-ink-navy);
	margin: 0 0 var(--bb-space-5);
}

.woocommerce-noreviews {
	margin: 0;
	padding: var(--bb-space-5);
	background: var(--bb-surface-white);
	border: 1px solid var(--bb-border-hairline-cream);
	border-radius: var(--bb-rounded-lg);
	color: var(--bb-ink-slate);
	font-size: 0.95rem;
}

.commentlist {
	list-style: none;
	display: flex;
	flex-direction: column;
	gap: var(--bb-space-4);
	margin: 0;
	padding: 0;
}

/* `.comment_container` (pas `li.comment`) : le `<li>` lui-même ne porte
   aucune classe stylable (`comment_class()` core WordPress, pas
   `product-badges.php`) — c'est son enfant direct, posé par
   single-product/review.php, qui délimite la carte. Même patron que
   `.bb-review-card` (Accueil) : fond blanc, bordure crème, coin large,
   ombre portée navy légère — pour que les deux endroits où un avis
   s'affiche se ressemblent. */
.commentlist .comment_container {
	display: flex;
	gap: var(--bb-space-4);
	padding: var(--bb-space-5);
	background: var(--bb-surface-white);
	border: 1px solid var(--bb-border-hairline-cream);
	border-radius: var(--bb-rounded-lg);
	box-shadow: 0 2px 10px rgba( 22, 38, 74, 0.06 );
}

.commentlist .comment_container img.avatar {
	width: 48px;
	height: 48px;
	border-radius: var(--bb-rounded-full);
	border: 2px solid var(--bb-brand-teal-wash);
	flex-shrink: 0;
}

.commentlist .comment-text {
	display: flex;
	flex-direction: column;
	flex: 1 1 auto;
	min-width: 0;
}

.commentlist .star-rating {
	margin: 0 0 var(--bb-space-2);
}

.commentlist p.meta {
	margin: 0 0 var(--bb-space-2);
	font-size: 0.8rem;
	color: var(--bb-ink-slate);
}

.commentlist .woocommerce-review__author {
	color: var(--bb-ink-navy);
	font-weight: 700;
}

.commentlist .description p {
	margin: 0;
	font-size: 0.95rem;
	line-height: 1.6;
	color: var(--bb-ink-navy);
}

.commentlist .description p:last-child {
	margin-block-end: 0;
}

/* Formulaire « Laisser un avis » — même carte visuelle que les avis
   ci-dessus et que les autres panneaux de la fiche produit
   (.bb-product-description). Classes du formulaire natif
   WordPress/WooCommerce (`#commentform`, jamais `.aod-cod` — ce N'EST PAS
   le formulaire de commande du plugin, aucune classe ni jeton `--sh-*` de
   plugins-dev/ partagé ici). */
#review_form_wrapper {
	padding: var(--bb-space-6) var(--bb-space-5);
	background: var(--bb-surface-white);
	border: 1px solid var(--bb-border-hairline-cream);
	border-radius: var(--bb-rounded-lg);
	box-shadow: 0 2px 10px rgba( 22, 38, 74, 0.06 );
}

.comment-reply-title {
	display: block;
	font-family: var(--bb-font-display);
	font-size: 1rem;
	font-weight: 700;
	color: var(--bb-ink-navy);
	margin-block-end: var(--bb-space-4);
}

#commentform p {
	margin: 0 0 var(--bb-space-4);
}

#commentform label {
	display: block;
	margin-block-end: var(--bb-space-2);
	font-weight: 600;
	font-size: 0.9rem;
	color: var(--bb-ink-navy);
}

#commentform .required {
	color: var(--bb-feedback-error);
}

#commentform input[type="text"],
#commentform input[type="email"],
#commentform textarea,
#commentform select {
	width: 100%;
	max-width: 100%;
	padding: var(--bb-space-3);
	border: 1px solid var(--bb-border-hairline);
	border-radius: var(--bb-rounded-sm);
	background: var(--bb-surface-white);
	color: var(--bb-ink-navy);
	font-size: 0.95rem;
	transition: border-color 0.15s ease, box-shadow 0.15s ease;
}

#commentform input[type="text"]:focus,
#commentform input[type="email"]:focus,
#commentform textarea:focus,
#commentform select:focus {
	outline: none;
	border-color: var(--bb-brand-teal-dark);
	box-shadow: 0 0 0 2px var(--bb-brand-teal-wash);
}

#commentform textarea {
	resize: vertical;
	min-height: 120px;
}

/* `.comment-form-rating` (le `<p>` posé par WooCommerce autour du
   `<select>`/widget d'étoiles) : uniquement une marge propre — la taille et
   la couleur des étoiles restent le rendu core, cf. commentaire en tête de
   section. */
.comment-form-rating {
	margin: 0 0 var(--bb-space-4);
}

.comment-form-rating .stars {
	margin: 0;
}

/* Mention RGPD (case à cocher « Enregistrer mon nom… ») — jusqu'ici sans
   `font-size` propre : elle héritait donc de la taille de base et pesait,
   à l'œil, autant qu'un champ obligatoire du formulaire. Rendue plus
   discrète (police réduite, gris slate), conformément à sa nature de
   mention secondaire. */
#commentform .comment-form-cookies-consent {
	display: flex;
	align-items: flex-start;
	gap: var(--bb-space-2);
	margin: 0 0 var(--bb-space-4);
}

#commentform .comment-form-cookies-consent input[type="checkbox"] {
	margin-block-start: 0.2em;
	flex-shrink: 0;
}

#commentform .comment-form-cookies-consent label {
	margin: 0;
	font-weight: 400;
	font-size: 0.82rem;
	color: var(--bb-ink-slate);
}

#commentform .form-submit {
	margin: 0;
}

#commentform .form-submit input#submit {
	display: inline-flex;
	width: 100%;
	align-items: center;
	justify-content: center;
	background: var(--bb-brand-teal-dark);
	color: var(--bb-surface-white);
	border: none;
	border-radius: var(--bb-rounded-full);
	padding: var(--bb-space-3) var(--bb-space-6);
	font-family: var(--bb-font-body);
	font-weight: 600;
	font-size: 0.95rem;
	cursor: pointer;
	transition: background-color 0.15s ease, transform 0.15s ease, box-shadow 0.15s ease;
}

@media ( min-width: 640px ) {
	#commentform .form-submit input#submit {
		width: auto;
	}
}

#commentform .form-submit input#submit:hover {
	background: var(--bb-brand-teal-dark-hover);
	transform: translateY( -1px );
	box-shadow: 0 4px 14px rgba( 22, 38, 74, 0.18 );
}

#commentform .form-submit input#submit:active {
	transform: translateY( 0 );
}

#commentform .form-submit input#submit:focus-visible {
	outline: 2px solid var(--bb-brand-teal-dark);
	outline-offset: 2px;
}

@media ( prefers-reduced-motion: reduce ) {
	#commentform .form-submit input#submit {
		transition: none;
	}
}

/*
 * ═══════════════════════════════════════════════════════════════════════
 * Accueil — habillage du shortcode [aod_home] (Story 4.1, AC #1/#2/#3).
 * ═══════════════════════════════════════════════════════════════════════
 *
 * Portée : uniquement la structure `.aod-home` fournie par le plugin
 * (jamais modifiée ici, cf. Décision 6 architecture.md) + le markup
 * WooCommerce natif qu'elle contient ([product_categories]/[products]) +
 * la section institutionnelle injectée par includes/home-institutional.php.
 *
 * Grille produit/catégories : Astra pose déjà `display:grid` en 2/3/4
 * colonnes responsive nativement sur `ul.products` (vérifié empiriquement,
 * Task 1, `getComputedStyle` réel), mais à SES propres seuils (900px → 3
 * col, 1440px → 4 col), générés dynamiquement par le Customizer Astra
 * (`Astra_Dynamic_CSS`, pas dans les fichiers CSS statiques du thème parent)
 * — pas ceux d'EXPERIENCE.md Responsive & Platform (768px / 1280px).
 * Revue de code (2026-09-01) : écart confirmé entre 768-900px et
 * 1280-1440px. Corrigé ci-dessous par un override explicite aux seuils
 * exacts de la spec, plutôt que de dupliquer toute la grille — `!important`
 * nécessaire car la spécificité/l'ordre de la CSS générée par le Customizer
 * Astra n'est pas garanti par le child theme.
 *
 * Toutes les propriétés directionnelles ci-dessous sont LOGIQUES
 * (`margin-inline`, `padding-inline`, `text-align:center`) — aucune valeur
 * `left`/`right` codée en dur, conformément à l'Accessibility Floor
 * d'EXPERIENCE.md : le RTL (arabe) doit se refléter automatiquement.
 */

/* Plein cadre + marge de 0,5 cm contrôlée (même patron que `.bb-hero`,
   ci-dessous) — remplace l'ancien `padding-inline` (gutter mobile/desktop),
   qui s'ajoutait au-dessus du padding du conteneur Astra ET de sa largeur
   maximale centrée (`--ast-normal-container-width`, ~1600px) : sur un grand
   écran, "Nos catégories"/"Nos produits" se retrouvaient avec une marge
   BEAUCOUP plus large que les 0,5 cm de `body` (constaté à l'écran — cette
   section n'était donc pas alignée avec le héro/l'en-tête, qui eux touchent
   déjà les vrais bords). Sortir entièrement du conteneur Astra puis reposer
   un padding de 0,5 cm ici donne une marge identique, à toute largeur
   d'écran, à celle du reste de la page.
   0,2 cm sous 768px : doit rester identique à la marge mobile de `body`
   ci-dessus (même retour owner 2026-09-06), sans quoi cette section se
   désaligne du héro/de l'en-tête en dessous de ce seuil. */
.aod-home {
	width: 100vw;
	margin-inline: calc( 50% - 50vw );
	padding-inline: 0.5cm;
}

@media ( max-width: 767.98px ) {
	.aod-home {
		padding-inline: 0.2cm;
	}
}

/* Seuils de grille EXPERIENCE.md (< 768px → 2 colonnes, 768px → 3, 1280px
   → 4), forcés indépendamment des seuils réels du Customizer Astra.
   Mesuré en revue de code (2026-09-01), Chromium headless réel, balayage fin
   500→768px : le commentaire précédent (et les Dev Notes de la story)
   annonçaient un seuil natif à 900px, mais le VRAI seuil natif Astra vers 3
   colonnes se situe entre 500 et 600px — jamais vérifié à cette granularité
   pendant l'implémentation (seulement 390/900/1440px testés, trois points qui
   entourent le seuil réel sans jamais le traverser). Sans la règle
   `max-width:767.98px` ci-dessous, la grille afficherait déjà 3 colonnes dès
   ~600px de large, en pleine zone "mobile" d'EXPERIENCE.md. `!important` :
   seul moyen fiable de battre une CSS générée dynamiquement par le
   Customizer Astra dont la spécificité/l'ordre de sortie n'est pas sous le
   contrôle du child theme. Revérifié après correctif (balayage 390 à 1600px,
   Chromium headless réel) : 2 colonnes jusqu'à 767px, 3 de 768 à 1279px,
   4 à partir de 1280px — conforme à EXPERIENCE.md sur toute la plage. */
@media ( max-width: 767.98px ) {
	.aod-home .aod-home__section ul.products.columns-3,
	.aod-home .aod-home__section ul.products.columns-4 {
		grid-template-columns: repeat( 2, 1fr ) !important;
	}
}

@media ( min-width: 768px ) and ( max-width: 1279.98px ) {
	.aod-home .aod-home__section ul.products.columns-3,
	.aod-home .aod-home__section ul.products.columns-4 {
		grid-template-columns: repeat( 3, 1fr ) !important;
	}
}

@media ( min-width: 1280px ) {
	.aod-home .aod-home__section ul.products.columns-3,
	.aod-home .aod-home__section ul.products.columns-4 {
		grid-template-columns: repeat( 4, 1fr ) !important;
	}
}

/* ── Héro carrousel (habillage Accueil, remplace le héro texte-seul du
   plugin — includes/home-hero.php) ──────────────────────────────────────
   Plein cadre : sort de `.aod-home` (padding-inline) ET de tout conteneur
   Astra en amont via le patron `calc(50% - 50vw)` — casse n'importe quel
   conteneur centré peu importe la profondeur d'imbrication, sans dépendre
   d'un sélecteur qui viserait cet ancêtre par son nom. `overflow-x:hidden`
   sur `body` (déjà posé par Astra lui-même, main.min.css — pas besoin de le
   répéter ici) absorbe le débordement gauche de ce patron. */
.bb-hero {
	position: relative;
	width: 100vw;
	margin-inline: calc( 50% - 50vw );
}

.bb-hero__track {
	position: relative;
	overflow: hidden;
	/* `width: 100%` explicite — indispensable dès que `aspect-ratio` ET
	   `max-height` sont TOUS LES DEUX posés (≥1280px ci-dessous) : passé un
	   certain viewport, la hauteur plafonne à `max-height` et le navigateur
	   déduit alors la LARGEUR de cette hauteur plafonnée via le ratio, au
	   lieu de remplir son conteneur — mesuré : 1493 px de piste (640×21/9)
	   dans une section pourtant large de 1920 px, laissant 427 px de vide à
	   droite (la piste, en flux normal, reste calée à gauche). Sans ce
	   `width: 100%`, le bug ne se voit qu'au-delà d'un viewport large et
	   spécifique (~1493 px ici) — invisible sur les écrans plus étroits, ce
	   qui a fait croire à tort à un souci de barre de défilement lors d'une
	   première investigation. */
	width: 100%;
	aspect-ratio: 4 / 5;
	max-height: 560px;
}

@media ( min-width: 768px ) {
	.bb-hero__track {
		aspect-ratio: 16 / 9;
	}
}

@media ( min-width: 1280px ) {
	.bb-hero__track {
		aspect-ratio: 21 / 9;
		max-height: 640px;
	}
}

.bb-hero__slide {
	position: absolute;
	inset: 0;
	opacity: 0;
	pointer-events: none;
	transition: opacity 0.6s ease;
}

.bb-hero__slide.is-active {
	opacity: 1;
	pointer-events: auto;
}

.bb-hero__img {
	position: absolute;
	inset: 0;
	width: 100%;
	height: 100%;
	object-fit: cover;
}

.bb-hero__scrim {
	position: absolute;
	inset: 0;
	/* rgba de --bb-ink-navy (#16264A = 22,38,74) — littéral assumé, rgba()
	   ne peut pas composer une var() couleur + un alpha variable ici. */
	background: linear-gradient( to top, rgba( 22, 38, 74, 0.78 ) 0%, rgba( 22, 38, 74, 0.32 ) 45%, rgba( 22, 38, 74, 0 ) 72% );
}

.bb-hero__content {
	position: absolute;
	inset-inline-start: 0;
	inset-block-end: 0;
	max-width: 30rem;
	padding: var(--bb-space-6) var(--bb-space-5);
	text-align: start;
}

.bb-hero__slogan {
	font-family: var(--bb-font-display);
	font-weight: 700;
	font-size: clamp( 1.375rem, 4vw, 2rem );
	line-height: 1.2;
	color: var(--bb-surface-white);
	margin: 0 0 var(--bb-space-2);
}

.bb-hero__text {
	font-family: var(--bb-font-body);
	font-weight: 400;
	font-size: 0.95rem;
	line-height: 1.6;
	color: rgba( 255, 255, 255, 0.92 );
	margin: 0 0 var(--bb-space-4);
}

.bb-hero .bb-hero__cta.aod-home__btn.button {
	/* Réutilise le bouton primaire de marque (couleurs/hover/focus déjà
	   définis plus haut dans ce fichier) — aucune redéfinition ici. */
	display: inline-flex;
}

.bb-hero__nav {
	position: absolute;
	inset-block-start: 50%;
	transform: translateY( -50% );
	/* 44px : même cible tactile que le reste de /gestion (Phase 46.6). */
	width: 44px;
	height: 44px;
	/* `padding:0` indispensable : le `button{padding:.6em 1em .4em}` /
	   `padding:15px 30px` globaux d'Astra (main.min.css) dépassent à eux seuls
	   44px de large — avec `border-box`, ça FORCE la boîte à s'élargir pour
	   loger ce padding (62px mesuré), donc un OVALE au lieu d'un cercle avec
	   `border-radius:9999px`. Trouvé en vérifiant le même bouton du carrousel
	   d'avis (bb-reviews-rail__btn, plus bas) — même bug, ici passé inaperçu
	   jusqu'ici faute d'avoir mesuré la boîte au pixel. */
	padding: 0;
	border: none;
	border-radius: var(--bb-rounded-full);
	background: rgba( 255, 255, 255, 0.85 );
	color: var(--bb-ink-navy);
	display: flex;
	align-items: center;
	justify-content: center;
	cursor: pointer;
	z-index: 2;
}

.bb-hero__nav--prev {
	inset-inline-start: var(--bb-space-3);
}

.bb-hero__nav--next {
	inset-inline-end: var(--bb-space-3);
}

/* `color` répété ici et sur `:focus` ci-dessous — pas un oubli de
   factorisation : Astra pose globalement `button:hover, button:focus {
   color:#fff }` (main.min.css, spécificité 0-1-1, élément + pseudo-classe).
   `.bb-hero__nav:hover`/`:focus` (0-2-0, classe + pseudo-classe) l'emporte
   déjà sans `!important` — mais UNIQUEMENT si `color` est déclaré ici : sans
   ça, rien dans ce fichier ne dispute la propriété `color` sur ces états, et
   la règle Astra s'applique alors seule. Sans ce correctif, le chevron ‹ ›
   (texte hérité de `.bb-hero__nav`) devient blanc sur fond blanc — donc
   invisible — dès le survol OU le focus (`:focus`, pas seulement
   `:focus-visible` : Astra cible `:focus` tout court, qui matche aussi un
   simple clic souris). Trouvé en vérifiant réellement l'état post-clic
   (Playwright + Chromium, `getComputedStyle`), pas supposé. */
.bb-hero__nav:hover {
	background: var(--bb-surface-white);
	color: var(--bb-ink-navy);
}

.bb-hero__nav:focus {
	color: var(--bb-ink-navy);
}

.bb-hero__nav:focus-visible {
	outline: 2px solid var(--bb-surface-white);
	outline-offset: 2px;
}

/* Chevrons ‹ / › (glyphes Unicode dans le markup, includes/home-hero.php) —
   aucune police d'icônes chargée pour ce seul usage. Chaque bouton porte son
   propre glyphe (‹ pour précédent, › pour suivant) : en RTL, un simple
   `scaleX(-1)` sur les DEUX suffit à les faire pointer dans le sens de
   lecture inverse — leurs libellés aria (« Image précédente »/« Image
   suivante ») restent corrects quel que soit le sens, seul le tracé change. */
.bb-hero__nav-icon {
	font-size: 1.5rem;
	line-height: 1;
	font-weight: 700;
}

html[dir="rtl"] .bb-hero__nav-icon {
	display: inline-block;
	transform: scaleX( -1 );
}

@media ( prefers-reduced-motion: reduce ) {
	.bb-hero__slide {
		transition: none;
	}
}

/* Bouton primaire (héro + fin de section produits) — DESIGN.md
   `button-primary` : teal foncé, jamais la teal claire (contraste). Astra ne
   pose qu'une seule règle `.button` peu qualifiée sur ce contexte (page
   classique, pas de `.woocommerce-page` sur ce gabarit — vérifié dans le
   HTML réellement servi, `body` n'a pas cette classe ici) : `.aod-home
   .aod-home__btn.button` (0-3-0) l'emporte sans ambiguïté, pas besoin de
   `#content`. */
.aod-home .aod-home__btn.button {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	background: var(--bb-brand-teal-dark);
	color: var(--bb-surface-white);
	border: none;
	border-radius: var(--bb-rounded-md);
	padding: var(--bb-space-3) var(--bb-space-5);
	font-family: var(--bb-font-body);
	font-weight: 600;
	text-decoration: none;
}

.aod-home .aod-home__btn.button:hover {
	background: var(--bb-brand-teal-dark-hover);
	color: var(--bb-surface-white);
}

.aod-home .aod-home__btn.button:focus-visible {
	outline: 2px solid var(--bb-brand-teal-dark);
	outline-offset: 2px;
}

/* ── Titres de section ("Nos catégories" / "Nos produits" / institutionnel,
   même classe réutilisée par includes/home-institutional.php) ──────────── */

.aod-home__h2 {
	font-family: var(--bb-font-display);
	font-weight: 700;
	font-size: 1.5rem;
	line-height: 1.25;
	color: var(--bb-ink-navy);
	text-align: center;
	margin: 0 0 var(--bb-space-5);
}

/* Retour owner (2026-09-02) : traitement Montserrat dédié aux 2 titres
   "vedette" de l'Accueil (catégories → "DE QUOI DEVEZ-VOUS PRENDRE SOIN ?",
   produits → "VOS FAVORIS") — classe AJOUTÉE en second sur le `<h2>`, PAS
   une redéfinition de `.aod-home__h2` : cette dernière est aussi utilisée
   par la page Contact ("Nous contacter", class-aod-cod-contact.php:123) et
   par la section institutionnelle, qui ne doivent pas hériter de ce
   traitement. Injectée par includes/home-categories.php (str_replace sur le
   `<h2>` rendu en entier, même patron que le reste de ce fichier). Taille en
   `clamp()` (28px → 32px) : ~31-33px demandé est une cible desktop, un
   littéral figé aurait débordé/tassé le texte sur mobile étroit (le rail de
   catégories mesure déjà ce risque ailleurs dans ce fichier). */
.bb-home-heading--display {
	font-family: var(--bb-font-montserrat);
	font-weight: 600;
	font-size: clamp( 1.75rem, 5vw, 2rem );
	text-transform: uppercase;
	letter-spacing: 0.04em;
}

.aod-home__section {
	padding-block: var(--bb-space-7);
}

/* ── Rail de catégories (habillage Accueil, remplace la grille figée du
   shortcode [product_categories] — includes/home-categories.php) ────────
   Cartes plein cadre (photo + libellé en surimpression) + défilement
   horizontal NATIF (overflow-x:auto sur `.bb-cat-rail__viewport`) : la
   navigation JS (theme.js) avance par élément via `Element.scrollIntoView()`
   plutôt que par lecture/écriture de `scrollLeft` — dont le signe diverge
   encore entre moteurs en RTL — donc juste en RTL par construction. Sans JS,
   le défilement tactile/trackpad natif reste utilisable (règle 4,
   TEMPLATE.md : rien ne doit dépendre du JS pour rester utilisable). */

.bb-cat-rail__viewport {
	overflow-x: auto;
	overflow-y: hidden;
	scroll-snap-type: x proximity;
	scrollbar-width: none;
	-ms-overflow-style: none;
}

.bb-cat-rail__viewport::-webkit-scrollbar {
	display: none;
}

/* `!important` : bat la mise en grille posée plus haut sur ce même sélecteur
   `ul.products.columns-3` (grid-template-columns, ligne ~459) — cette carte
   n'a plus besoin de colonnes, elle passe en ligne défilable.

   Retour owner (2026-09-06) : « les catégories doivent être centrées » —
   avec peu de catégories (le catalogue de ce clone n'en a que 3 non vides),
   les cartes ne remplissaient pas le rail et restaient collées au bord de
   départ (`justify-content` initial = `flex-start`), un vide visible de
   l'autre côté. `safe center` plutôt qu'un simple `center` : sur un rail
   DÉFILABLE (`overflow-x:auto` ci-dessus), un `center` nu masquerait le
   début du contenu dès qu'il déborde — certains moteurs ne laissent alors
   remonter la position de scroll qu'à la moitié du dépassement, rendant les
   premières cartes inatteignables même en glissant à fond. `safe` retombe
   sur l'alignement de départ (comportement actuel, inchangé) SEULEMENT si
   le contenu déborde réellement — jamais de carte perdue. Navigateur trop
   ancien pour comprendre `safe` : toute la déclaration est invalide et
   ignorée, `justify-content` retombe sur son défaut (`normal`, identique à
   `flex-start`) — donc strictement le rendu d'avant, jamais une régression. */
.bb-cat-rail__viewport ul.products {
	display: flex !important;
	flex-wrap: nowrap !important;
	justify-content: safe center;
	gap: var(--bb-space-4);
	margin: 0 !important;
	padding-block-end: var(--bb-space-1);
}

/* `width` en `!important` : bat `.woocommerce ul.products li.product{width:100%}`
   (spécificité 0-3-2, plus élevée que ce sélecteur ici) posé par la
   compatibilité grille WooCommerce d'Astra
   (astra/assets/css/minified/compatibility/woocommerce/woocommerce-layout-grid.min.css)
   — vérifié via les règles CSS réellement appliquées (Playwright,
   `document.styleSheets`), pas supposé : sans ce `!important`, chaque carte
   occupait 100% du rail au lieu de sa largeur clampée, changement invisible
   en `display:flex` seul (aucun signal d'erreur, juste 1 carte pleine
   largeur au lieu de 3 côte à côte). */
.bb-cat-rail__viewport li.product-category {
	position: relative;
	flex: 0 0 auto;
	width: clamp( 220px, 34vw, 300px ) !important;
	aspect-ratio: 1 / 1;
	border-radius: var(--bb-rounded-lg);
	overflow: hidden;
	scroll-snap-align: start;
	background: var(--bb-surface-cream);
}

.bb-cat-rail__viewport li.product-category a {
	display: block;
	position: relative;
	width: 100%;
	height: 100%;
}

.bb-cat-rail__viewport li.product-category img {
	position: absolute;
	inset: 0;
	width: 100%;
	height: 100%;
	object-fit: cover;
	object-position: center;
}

/* Scrim dégradé (mêmes teintes que .bb-hero__scrim, --bb-ink-navy en rgba)
   pour garantir le contraste du libellé blanc quelle que soit la photo. */
.bb-cat-rail__viewport li.product-category a::after {
	content: '';
	position: absolute;
	inset: 0;
	background: linear-gradient( to top, rgba( 22, 38, 74, 0.85 ) 0%, rgba( 22, 38, 74, 0.18 ) 48%, rgba( 22, 38, 74, 0 ) 72% );
}

/* `background`/`font-size` en `!important` : bat la compatibilité grille
   WooCommerce d'Astra sur ce même élément — `.woocommerce-page ul.products
   li.product .woocommerce-loop-category__title` (astra/.../woocommerce-grid.min.css)
   a une spécificité (0-4-2) plus élevée que ce sélecteur ici (0-4-0), à la
   fois pour `background-color:rgba(255,255,255,.88)` (cadre clair autour du
   titre) ET `font-size:.9em` (titre trop petit malgré la valeur posée ici).
   Vérifié via les règles CSS réellement appliquées, pas supposé — même
   méthode que le correctif de largeur des cartes plus haut. */
.aod-home .aod-home__section .bb-cat-rail__viewport .woocommerce-loop-category__title {
	position: absolute;
	inset-inline: 0 !important;
	inset-block-end: 0;
	z-index: 1;
	margin: 0;
	padding: var(--bb-space-4);
	background: none !important;
	font-family: var(--bb-font-display);
	font-weight: 700;
	font-size: clamp( 1.15rem, 1.5vw + 0.8rem, 1.5rem ) !important;
	line-height: 1.2 !important;
	color: var(--bb-surface-white);
	text-align: start;
}

/* Compteur "N produits" retiré de l'affichage (carte plein cadre premium,
   dans l'esprit de la page de référence) — l'information reste secondaire
   par rapport au nom + lien de la catégorie, qui restent pleinement
   accessibles. `!important` : bat le `display:block` posé par la même
   compatibilité grille WooCommerce d'Astra que le `width` ci-dessus. */
.bb-cat-rail__viewport mark.count {
	display: none !important;
}

/* `[hidden]` d'abord : sans ce garde, la règle `display:flex` ci-dessous
   (sélecteur de classe, donc plus prioritaire que l'attribut `[hidden]` de
   la feuille UA) annulerait l'attribut `hidden` posé par défaut côté serveur
   (includes/home-categories.php) et par theme.js quand le rail ne déborde
   pas — les boutons resteraient visibles en permanence, y compris quand rien
   ne déborde. Constaté à l'écran (Playwright), pas supposé. */
.bb-cat-rail__nav[hidden] {
	display: none;
}

.bb-cat-rail__nav {
	display: flex;
	justify-content: center;
	gap: var(--bb-space-3);
	margin-block-start: var(--bb-space-5);
}

.bb-cat-rail__btn {
	width: 44px;
	height: 44px;
	/* `padding:0` : sans lui, le padding global d'Astra sur `button` élargit
	   la boîte à 62px (cf. commentaire équivalent sur .bb-hero__nav) et
	   `border-radius:9999px` dessine un ovale au lieu d'un cercle. */
	padding: 0;
	border: 1px solid var(--bb-border-hairline);
	border-radius: var(--bb-rounded-full);
	background: var(--bb-surface-white);
	color: var(--bb-ink-navy);
	display: flex;
	align-items: center;
	justify-content: center;
	cursor: pointer;
}

/* Même collision Astra `button:hover,button:focus{color:#fff}` que
   `.bb-hero__nav` (cf. son commentaire, ligne ~613) — même correctif. */
.bb-cat-rail__btn:hover:not( :disabled ) {
	background: var(--bb-surface-cream);
	/* Blanc, pas --bb-ink-navy : ce fond vaut désormais #162950 (retour
	   owner, 2026-09-02) — la même icône en navy y devenait illisible. */
	color: var(--bb-surface-white);
}

.bb-cat-rail__btn:focus {
	color: var(--bb-ink-navy);
}

.bb-cat-rail__btn:focus-visible {
	outline: 2px solid var(--bb-brand-teal-dark);
	outline-offset: 2px;
}

.bb-cat-rail__btn:disabled {
	opacity: 0.35;
	cursor: default;
}

.bb-cat-rail__btn-icon {
	font-size: 1.5rem;
	line-height: 1;
	font-weight: 700;
}

html[dir="rtl"] .bb-cat-rail__btn-icon {
	display: inline-block;
	transform: scaleX( -1 );
}

@media ( prefers-reduced-motion: reduce ) {
	.bb-cat-rail__viewport {
		scroll-behavior: auto;
	}
}

/* ── Produits — carte Astra déjà riche (image, catégorie, titre, prix,
   bouton), habillée aux couleurs de marque sans toucher sa structure ───── */

/* Pas de `overflow: hidden` ici (contrairement à la carte catégorie
   ci-dessus) — retiré en revue de code (2026-09-01) : cette carte porte le
   bouton d'ajout rapide en surimpression du panier COD togglable
   (`.ast-on-card-button`, Phase 35-36) ; un `overflow:hidden` sur ce
   conteneur le masquerait si le gérant active la fonctionnalité un jour
   (contrainte explicite des Dev Notes de la story). */
/* Retour owner (2026-09-05) : « fais disparaître la bordure des cartes
   produit de l'Accueil ». `border: none` explicite (pas juste l'absence de
   déclaration) : sans lui, la carte retombe sur le `1px solid #ECECEC` par
   défaut d'Astra (`.ast-article-single`, vérifié dans le HTML réellement
   servi) — la même valeur que l'ancien `border` ci-dessous, d'où l'absence
   de changement visuel si on s'était contenté de retirer la ligne. Scopé
   `.aod-home` : ne touche pas la grille Boutique, non demandée ici. */
.aod-home .aod-home__section ul.products.columns-4 li.product {
	background: var(--bb-surface-white);
	border: none;
	border-radius: var(--bb-rounded-md);
}

/* `.ast-woo-product-category` : sur ce gabarit (page classique, pas
   `.woocommerce-page`), seule la variante Astra la moins qualifiée
   s'applique (0-1-0, vérifié dans le HTML réellement servi et dans le CSS
   Astra) — `.aod-home .ast-woo-product-category` (0-2-0) l'emporte sans
   ambiguïté. Traité en étiquette "eyebrow" (DESIGN.md Typography), PAS en
   badge-category à accent-par-produit : aucune donnée d'accent par produit
   n'existe dans ce clone (architecture.md Décision 5, « rien de nouveau à
   modéliser ») — un badge-category complet nécessiterait une nouvelle
   méta-donnée, hors périmètre de cette story d'habillage CSS seul. */
.aod-home .ast-woo-product-category {
	/* --bb-font-display (Poppins/Cairo) + 0.8rem — corrigé en revue de code
	   (2026-09-01) : la valeur précédente (--bb-font-body, 0.75rem) ne
	   correspondait pas à l'entrée "eyebrow" de DESIGN.md Typography malgré
	   le commentaire ci-dessus qui la revendiquait. */
	font-family: var(--bb-font-display);
	font-weight: 600;
	font-size: 0.8rem;
	letter-spacing: 0.08em;
	text-transform: uppercase;
	/* --bb-ink-navy, pas --bb-ink-slate — contraste AA (--bb-ink-slate échoue
	   ~2,6:1 sur blanc/crème, sous les seuils AA à toute taille). */
	color: var(--bb-ink-navy);
	opacity: 1;
}

/* PAS scopé `.aod-home` — même bug que le bouton "Commander" plus haut dans
   ce fichier (`.ast-on-card-button`/`.astra-shop-summary-wrap .button`) :
   `.aod-home` n'existe QUE sur l'Accueil, jamais sur l'archive Boutique
   (`body.woocommerce-page`). Trouvé en auditant les polices calculées des 3
   pages publiques (2026-09-02, retour owner « toutes les polices ») — sur
   Boutique, ce titre retombait sur le stack système de `body`. */
.woocommerce-loop-product__title {
	font-family: var(--bb-font-body);
	font-weight: 600;
	font-size: 1rem;
	color: var(--bb-ink-navy);
}

/* Filet CSS — CHECKLIST-THEME-CHILD.md C1 (inversion bidi du symbole DZD).
   Le filtre `wc_price` (includes/woocommerce-currency.php) force déjà
   `dir="ltr"` sur le `<bdi>` généré par WooCommerce ; cette règle est un
   filet pour tout prix qui échapperait à ce filtre (ex. rendu JS/AJAX d'un
   plugin tiers) — sans elle, `dir="auto"` retomberait sur le sens du 1er
   caractère fort et pourrait réinverser nombre/symbole. */
.woocommerce-Price-amount,
.woocommerce-Price-amount bdi {
	direction: ltr;
	unicode-bidi: isolate;
}

.aod-home .astra-shop-summary-wrap .price {
	color: var(--bb-ink-navy);
	font-weight: 700;
}

/* Les deux boutons "Commander" de la carte (surimpression au survol +
   pied de carte, tous deux déjà fournis par Astra) partagent le même
   traitement de couleur de marque — aucune restructuration de la carte.

   ⚠️ PAS scopé `.aod-home` — corrigé sur retour owner (2026-09-02) : « sur
   Boutique, le bouton Commander n'est pas encore appliqué ». Mesuré (pas
   supposé) : `.aod-home` n'existe QUE sur l'Accueil (wrapper du shortcode
   [aod_home], shop-hooks.php n'en pose aucun) — sur l'archive Boutique
   (`body.woocommerce-page`, PAS `.aod-home`), ces règles ne matchaient donc
   jamais, et le bouton restait au bleu Astra par défaut (`rgb(4,107,210)`,
   l'accent global du Customizer), 148px de large, `border-radius:4px`.
   `ul.products li.product` porte la carte sur les DEUX gabarits (Boutique
   ET grille [products] de l'Accueil) — même patron déjà utilisé plus bas
   dans ce fichier pour la rupture de stock. */
ul.products li.product .ast-on-card-button,
ul.products li.product .astra-shop-summary-wrap .button.add_to_cart_button {
	background: var(--bb-brand-teal-dark);
	color: var(--bb-surface-white);
}

/* Retour owner (2026-09-01) : « au survol d'un produit, un carré bleu
   s'affiche derrière l'icône » — `.ast-on-card-button` (le lien "Commander"
   en surimpression, coin haut-droit de la carte) est un carré 32×32 SANS
   rayon (mesuré : `border-radius:0`), pendant que le glyphe rond qu'Astra
   affiche dedans (`.ahfb-svg-iconset`, cercle blanc) est plus petit — les
   coins du carré teal dépassaient donc visiblement derrière le rond blanc.
   Le bouton pied-de-carte (`.button.add_to_cart_button`, ci-dessus) n'est
   PAS concerné : lui est un rectangle plein assumé, jamais rond. */
ul.products li.product .ast-on-card-button {
	border-radius: 50%;
	/* `aspect-ratio` seul ne suffit pas ici : la hauteur réelle du bloc
	   (mesurée 32,9px, contre 32px de large posés par Astra) vient du
	   `line-height` HÉRITÉ (26,4px = corps de texte × 1,65, `main.min.css`)
	   qui pousse le contenu au-delà de la largeur — `aspect-ratio` ne fait
	   que suggérer une taille, il ne force pas le contenu à tenir dedans.
	   `line-height: 1` retire cette inflation à la source ; `aspect-ratio`
	   reste en filet de sécurité si le contenu venait à changer. */
	line-height: 1;
	aspect-ratio: 1;
}

/* Retour owner (2026-09-02) : « le bouton Commander n'est pas centré et il
   est très petit » — mesuré (pas supposé) : Astra le rend `inline-block`,
   largeur au contenu (148px sur une carte de 293px de large), donc collé au
   bord gauche du pied de carte (le conteneur `.astra-shop-summary-wrap`
   hérite d'un `text-align:left`). `width:100%` + `justify-content:center`
   l'étend et centre son libellé ; même famille de rayon que le bouton
   primaire de marque (`--bb-rounded-md`, `.aod-home__btn.button` plus haut
   dans ce fichier) pour rester harmonisé plutôt que le `4px` par défaut
   d'Astra. */
ul.products li.product .astra-shop-summary-wrap .button.add_to_cart_button {
	display: flex;
	align-items: center;
	justify-content: center;
	width: 100%;
	text-align: center;
	border-radius: var(--bb-rounded-md);
	padding: var(--bb-space-3) var(--bb-space-4);
	font-family: var(--bb-font-body);
	font-weight: 600;
	font-size: 0.95rem;
}

ul.products li.product .astra-shop-summary-wrap .button.add_to_cart_button:hover {
	background: var(--bb-brand-teal-dark-hover);
}

/* Anneau de focus manquant, ajouté en revue de code (2026-09-01) — seul le
   bouton héros en avait un jusqu'ici (EXPERIENCE.md Accessibility Floor :
   « Focus clavier visible sur tous les éléments interactifs »), même
   traitement que .aod-home__btn.button. `!important` nécessaire et vérifié :
   sans lui, une règle générée dynamiquement par le Customizer Astra
   (`.woocommerce .astra-shop-summary-wrap a:focus-visible{outline-style:
   dotted;outline-color:inherit;...}`, injectée en `<style>` inline, hors des
   fichiers CSS statiques du thème parent) l'emportait malgré une spécificité
   CSS inférieure sur le papier (0,3,1 contre 0,5,0 ici) — mesuré réellement
   (Chromium headless, `getComputedStyle` + inspection de
   `document.styleSheets`), pas supposé. */
ul.products li.product .ast-on-card-button:focus-visible,
ul.products li.product .astra-shop-summary-wrap .button.add_to_cart_button:focus-visible {
	outline: 2px solid var(--bb-brand-teal-dark) !important;
	outline-offset: 2px !important;
}

/* ── Section institutionnelle BELLISSIMA BIO (Story 4.1, AC #3 ; refonte deux
   colonnes + texte repliable, demande owner 2026-09-01 ; pleine largeur +
   photo entière, demande owner 2026-09-01 suite) ────────────────────────────
   Grille `auto`/`1fr` implicite via deux enfants directs (média puis corps)
   plutôt que flex + ordre manuel : les colonnes CSS Grid suivent `direction`
   nativement, donc l'image et le texte échangent déjà de côté en RTL sans
   règle miroir — même raisonnement que `.bb-reviews-rail` plus haut.

   ⚠️ PAS de `max-width` propre à cette section (contrairement à un essai
   précédent à 72rem, plus étroit que ses sœurs) : `.aod-home` (plus haut
   dans ce fichier) sort déjà tout l'Accueil du conteneur Astra et repose une
   marge de 0,5 cm identique partout — cette section doit occuper exactement
   la même largeur que "Nos produits"/"Nos avis" juste au-dessus, pas une
   largeur en plus réduite et centrée. */

.bb-institutional {
	display: grid;
	grid-template-columns: minmax( 0, 5fr ) minmax( 0, 7fr );
	align-items: stretch;
	/* Seul espaceur entre l'image et le texte : `.bb-institutional__body` n'a
	   pas de padding côté image (`padding-inline-start` resté à 0, cf.
	   plus bas) pour ne pas le doubler avec ce `gap`. En mobile empilé, ce
	   même `gap` sépare aussi verticalement l'image du texte. */
	gap: var(--bb-space-6);
	background: var(--bb-surface-cream);
	border-radius: var(--bb-rounded-lg);
	overflow: hidden; /* Coins de l'image alignés sur le rayon de la carte. */
}

.bb-institutional__media {
	position: relative;
	min-height: 320px;
}

.bb-institutional__media-img {
	position: absolute;
	inset: 0;
	width: 100%;
	height: 100%;
	/* `contain`, pas `cover` : la photo doit s'afficher EN ENTIER (demande
	   owner explicite), jamais rognée pour remplir la boîte. Les bandes
	   restantes se fondent dans `--bb-surface-cream` (fond de la section,
	   pas de couleur propre au média), donc invisibles à l'œil — pas un
	   "letterboxing" gris qui trahirait un cadrage raté. */
	object-fit: contain;
	object-position: center;
}

.bb-institutional__body {
	display: flex;
	flex-direction: column;
	justify-content: center;
	padding-block: var(--bb-space-7);
	padding-inline-end: var(--bb-space-6);
}

.bb-institutional__title {
	/* `.aod-home__h2` centre par défaut (titres "Nos catégories"/"Nos
	   produits") — ici le titre s'aligne avec le texte de sa colonne. */
	text-align: start;
	/* Fond de la carte passé à #162950 (retour owner, 2026-09-02) : le navy
	   hérité de `.aod-home__h2` (--bb-ink-navy) y devenait illisible
	   (contraste mesuré ~1:1) — blanc, comme le reste du texte de cette
	   carte ci-dessous. */
	color: var(--bb-surface-white);
}

.bb-institutional__text {
	font-family: var(--bb-font-body);
	font-weight: 400;
	font-size: 1rem;
	line-height: 1.6;
	/* Blanc, pas --bb-ink-navy : même raison que .bb-institutional__title
	   ci-dessus (fond #162950, contraste mesuré 14,3:1 en blanc contre
	   ~1:1 en navy). */
	color: var(--bb-surface-white);
	margin: 0 0 var(--bb-space-4);
}

.bb-institutional__sig {
	font-family: var(--bb-font-display);
	font-weight: 600;
	font-size: 0.9rem;
	letter-spacing: 0.04em;
	/* Blanc, pas --bb-brand-teal-dark : cette variable VAUT désormais la
	   couleur du fond (#162950, retour owner 2026-09-02) — texte et fond
	   identiques, invisible. */
	color: var(--bb-surface-white);
	margin: var(--bb-space-5) 0 0;
}

/* Replié : hauteur fixe + dégradé de sortie vers la couleur de fond de la
   carte (`--bb-surface-cream`), pour suggérer qu'il reste du texte sans
   couper une ligne à moitié. Posé UNIQUEMENT par theme.js, et seulement s'il
   mesure un texte qui dépasse réellement cette hauteur (jamais par défaut en
   CSS pur : dégradation obligatoire, cf. commentaire PHP au-dessus du bouton
   dans home-institutional.php — sans JS, le texte reste entier). */
.bb-institutional__text-wrap.is-collapsed {
	max-height: 170px;
	overflow: hidden;
	position: relative;
}

.bb-institutional__text-wrap.is-collapsed::after {
	content: '';
	position: absolute;
	inset-inline: 0;
	inset-block-end: 0;
	height: 48px;
	/* rgba(22,41,80,…) = #162950 (--bb-surface-cream, retour owner 2026-09-02) :
	   littéral, pas var(), pour porter la transparence du dégradé — mis à
	   jour depuis l'ancien crème (242,234,224) pour rester fondu dans le
	   NOUVEAU fond de la carte. */
	background: linear-gradient( to bottom, rgba( 22, 41, 80, 0 ) 0%, rgba( 22, 41, 80, 1 ) 85% );
	pointer-events: none;
}

.bb-institutional__toggle {
	align-self: flex-start;
	margin-block-start: var(--bb-space-4);
	padding: 0;
	border: none;
	background: none;
	font-family: var(--bb-font-display);
	font-weight: 600;
	font-size: 0.9rem;
	/* Blanc, pas --bb-brand-teal-dark : même raison que .bb-institutional__sig
	   plus haut (variable désormais identique à la couleur du fond). */
	color: var(--bb-surface-white);
	text-decoration: underline;
	cursor: pointer;
}

/* `background: none` répété ICI, pas seulement dans l'état de base : Astra
   (main.min.css) pose `button:hover, button:focus { background-color:
   var(--ast-global-color-1) — bleu ; color: #fff; }` sur l'élément NU
   `button`. Sa spécificité (1 type + 1 pseudo-classe) bat notre état de base
   `.bb-institutional__toggle` (1 classe seule) sur le DÉPARTAGE — la couleur
   de texte s'en sort (notre `:hover` fait 1 classe + 1 pseudo-classe, donc
   la bat), mais le fond bleu d'Astra passait, rendant le libellé illisible
   dessus (retour owner, 2026-09-01). Trouvé en comparant les règles CSS
   correspondantes réellement appliquées (`document.styleSheets`), pas
   supposé. */
.bb-institutional__toggle:hover,
.bb-institutional__toggle:focus {
	background: none;
	/* Blanc légèrement atténué (pas --bb-brand-teal-dark-hover, qui reste un
	   dérivé sombre du fond — invisible dessus) : assez distinct du blanc
	   plein de l'état de base pour rester un vrai retour au survol. */
	color: rgba( 255, 255, 255, 0.75 );
}

.bb-institutional__toggle:focus-visible {
	/* Blanc, pas --bb-brand-teal-dark : cet anneau se dessine SUR le fond
	   #162950 de la carte (retour owner, 2026-09-02) — même couleur que lui
	   serait un anneau de focus invisible, le pire endroit pour ça. */
	outline: 2px solid var(--bb-surface-white);
	outline-offset: 2px;
}

@media ( max-width: 800px ) {
	/* Sous ce point de rupture, deux colonnes de 5fr/7fr n'ont plus la place
	   d'exister sans écraser la photo à quelques dizaines de pixels — empilé,
	   média d'abord (même ordre visuel qu'en LTR, cohérent en RTL car c'est
	   l'ordre SOURCE qui devient l'ordre d'empilement, plus de colonnes à
	   mirorer). */
	.bb-institutional {
		grid-template-columns: 1fr;
	}

	.bb-institutional__media {
		min-height: 240px;
	}

	.bb-institutional__body {
		padding-inline: var(--bb-space-5);
		padding-block-start: var(--bb-space-6);
	}
}

/* ── « Découvrez toute la routine » (sous VOS FAVORIS, includes/home-brand-showcase.php) ──
   Une ligne divisée en deux : UN visuel de gamme à gauche (retour owner,
   2026-09-02 : un seul des deux visuels fournis, pas les deux), un panneau
   qui fait défiler (translation verticale, JS theme.js) les 5 fiches
   produits à droite — UN SEUL item visible à la fois, même patron que
   `.bb-announce` plus haut dans ce fichier (mesuré, pas un fondu : cf. sa
   Dev Note). Item unique plutôt que plusieurs visibles à la fois : évite
   l'espace vide en fin de boucle qu'un panneau multi-items aurait exigé de
   gérer (dernier des 5 items, viewport dimensionné pour 3 → 2 lignes
   vides) — même choix, pour la même raison, que `.bb-announce`.

   Items agrandis trois fois sur retour owner (2026-09-02) : 10rem/96px
   (« qu'on puisse bien voir le produit »), puis « qu'il occupe la moitié de
   cette section ». ⚠️ Un premier essai posait `.viewport{height:50%}` en CSS
   pur : dépendance CIRCULAIRE avec la grille `.row{align-items:stretch}`
   (le pourcentage, indéfini tant que la ligne n'a pas de hauteur arrêtée,
   retombe à `auto` pendant le calcul intrinsèque — dont le résultat sert
   justement à arrêter cette hauteur), mesurée (Playwright) à ~2000px de haut
   sur TOUTES les largeurs testées, un chiffre sans rapport avec le visuel.
   Corrigé en calculant cette moitié en JS (theme.js), à partir de la
   hauteur RÉELLE et déjà stable du visuel de gamme — posée en style inline
   par mesure, jamais par pourcentage CSS. Cf. Dev Note de l'IIFE dédiée. */
.bb-brand-showcase__row {
	display: grid;
	grid-template-columns: minmax( 0, 6fr ) minmax( 0, 6fr );
	align-items: stretch;
	gap: var(--bb-space-6);
}

.bb-brand-showcase__media {
	display: block;
}

.bb-brand-showcase__media-img {
	width: 100%;
	height: auto;
	border-radius: var(--bb-rounded-lg);
	object-fit: cover;
}

.bb-brand-showcase__scroll {
	display: flex;
	align-items: center;
	/* Retour owner (2026-09-02) : fond blanc, plus le fond crème d'origine
	   (--bb-surface-cream, aussi utilisé par la carte institutionnelle). */
	background: var(--bb-surface-white);
	border-radius: var(--bb-rounded-lg);
	padding-inline: var(--bb-space-6);
	/* `min-width:0` : c'est un item de la grille `.row` — sans lui, sa largeur
	   MINIMALE par défaut ("auto") vaut le min-content de tout son contenu,
	   vignette fixe (150px) comprise, et il refuse de rétrécir sous cette
	   largeur — débordement mesuré (Playwright, 390px) : 394,5px de large,
	   413px de bord droit, texte du produit tronqué hors écran. */
	min-width: 0;
}

.bb-brand-showcase__viewport {
	/* Hauteur de repli SANS JS uniquement — JS (theme.js) la remplace toujours
	   par la moitié RÉELLE, mesurée, du visuel de gamme (cf. Dev Note plus
	   haut). Dégradation obligatoire : sans JS, le 1ᵉʳ produit reste affiché
	   en entier à cette hauteur, jamais un panneau tronqué à 0. */
	position: relative;
	width: 100%;
	height: 14rem;
	overflow: hidden;
}

.bb-brand-showcase__list {
	margin: 0;
	padding: 0;
	list-style: none;
	transition: transform 0.5s ease;
}

@media ( prefers-reduced-motion: reduce ) {
	.bb-brand-showcase__list {
		transition: none;
	}
}

.bb-brand-showcase__item {
	/* Hauteur de repli SANS JS uniquement, alignée sur celle de `.viewport`
	   ci-dessus (un `%` ne se résoudrait pas mieux ici : même parent `.list`
	   en flux, hauteur auto circulaire) — JS pose toujours la vraie hauteur
	   mesurée en style inline, qui prime sur cette règle. */
	height: 14rem;
	display: flex;
	align-items: center;
}

.bb-brand-showcase__item-link {
	display: flex;
	align-items: center;
	gap: var(--bb-space-5);
	width: 100%;
	/* `height:100%` : requis pour que `.item-img{height:100%}` ait une base
	   DÉFINIE à résoudre. `.item` (parent) a bien une hauteur définie, posée
	   en JS — mais `align-items:center` sur `.item` NE L'ÉTIRE PAS pour
	   autant à ses enfants directs (`.item-link` n'en hérite pas). Sans cette
	   ligne, la hauteur de l'image retombait à `auto`, qui — combiné à
	   `aspect-ratio:1` sans base définie — se rabattait sur la taille
	   intrinsèque du fichier (attributs `width`/`height` HTML, 600×600) :
	   mesuré (Playwright, 1440px) une image à 601px de large, texte réduit à
	   0px, débordant toute la carte. */
	height: 100%;
	/* !important mesuré, pas décoratif : cette section vit dans `.entry-content`
	   (sortie de [aod_home]), où Astra pose `.ast-single-post .entry-content a
	   { text-decoration: underline }` (main.min.css) — spécificité 0-2-1, qui
	   bat cette règle (0-1-0) même déclarée après elle. Même patron déjà établi
	   ailleurs dans ce fichier face à une anomalie de spécificité Astra. */
	text-decoration: none !important;
}

.bb-brand-showcase__item-img {
	/* Retour owner (2026-09-02, 3 demandes le même jour) : la PHOTO du
	   produit doit occuper la moitié de la section, PUIS « encore plus
	   grande verticalement, le produit n'est pas montré en entier ».
	   ⚠️ Un essai à `flex-basis:50%` (largeur fixe) + `height:100%` +
	   `object-fit:contain` calait la photo — CARRÉE en source (1254×1254,
	   `contain` ne rogne jamais) — sur la PLUS PETITE des deux dimensions de
	   sa case : ici la hauteur (case plus large que haute), laissant des
	   bandes vides des deux côtés et un flacon perçu comme petit malgré ses
	   50% de largeur alloués. Passé en `aspect-ratio:1` + `width:auto` +
	   `height:100%` : le carré suit maintenant SA hauteur disponible sans
	   perdre de place, donc grandit RÉELLEMENT quand l'item grandit
	   verticalement (`HEIGHT_RATIO`, theme.js) — plus besoin de lui réserver
	   une largeur fixe, `.item-text` (ci-dessous, `flex:1 1 auto`) absorbe
	   ce qui reste. `object-fit:contain` conservé : le flacon entier reste
	   visible, jamais rogné en haut/bas — les bandes résiduelles (le carré
	   source n'est pas rempli à 100% par le flacon) se fondent dans
	   `background`, posé à la même couleur que le fond de la carte. */
	flex: 0 0 auto;
	aspect-ratio: 1;
	width: auto;
	height: 100%;
	/* `max-width` : sous 800px, la grille de la section repasse à 1 seule
	   colonne (plus bas dans ce fichier) — la largeur disponible pour TOUTE
	   la carte devient alors celle de l'écran, plutôt que la moitié d'une
	   grille 2 colonnes. Sans ce plafond, un carré qui suit fidèlement sa
	   hauteur (déjà généreuse, `HEIGHT_RATIO`, theme.js) pouvait manger
	   quasi toute la largeur de la carte sur mobile — mesuré (Playwright,
	   390px) : 200px de carré pour seulement 44px restants au texte. Au-delà
	   de ce plafond, `object-fit:contain` continue de montrer le flacon
	   ENTIER (jamais rogné), simplement plus petit que sa hauteur dispo. */
	max-width: 55%;
	border-radius: var(--bb-rounded-md);
	object-fit: contain;
	background: var(--bb-surface-white);
}

.bb-brand-showcase__item-text {
	display: flex;
	flex-direction: column;
	justify-content: center;
	gap: var(--bb-space-2);
	flex: 1 1 auto;
	min-width: 0;
}

.bb-brand-showcase__item-name {
	font-family: var(--bb-font-display);
	font-weight: 700;
	font-size: clamp( 1rem, 3.6vw, 1.4rem );
	line-height: 1.3;
	color: var(--bb-ink-navy);
}

.bb-brand-showcase__item-blurb {
	font-family: var(--bb-font-body);
	font-size: clamp( 0.85rem, 2.8vw, 1.05rem );
	line-height: 1.45;
	color: var(--bb-ink-slate);
	/* Hauteur d'item posée en JS (theme.js, égale à celle du viewport — la
	   cascade CSS seule ne peut pas la résoudre, cf. Dev Note sur
	   `.bb-brand-showcase__item`) : un texte qui déborderait sur un item
	   précis désynchroniserait le défilement des suivants. Clampé à 4 lignes
	   plutôt que raccourci en amont, pour ne jamais couper un mot au milieu. */
	display: -webkit-box;
	-webkit-line-clamp: 4;
	-webkit-box-orient: vertical;
	overflow: hidden;
	text-overflow: ellipsis;
}

@media ( max-width: 800px ) {
	.bb-brand-showcase__row {
		grid-template-columns: 1fr;
	}
}

/* `.item-img` est déjà plafonnée à 55% de la largeur de la carte (règle de
   base ci-dessus) — mais à 390px cette part suffit à réduire la colonne de
   texte à ~97px, sous laquelle « Shampooing » (le mot le plus long des 5
   noms de produits) casse en plein milieu (mesuré, Playwright). Resserré à
   45% sous 480px : encore nettement plus grand que la vignette d'avant
   cette story (150px fixe), juste assez pour laisser le mot entier passer
   à la ligne suivante. */
@media ( max-width: 480px ) {
	.bb-brand-showcase__item-img {
		max-width: 45%;
	}
}

/* ── Témoignages ("Voici ce que disent nos clients !", includes/home-reviews.php) ──
   Carrousel de cartes plein format (3 par page sur bureau, 2 en tablette, 1
   en mobile), défilement AUTO + deux flèches latérales pour parcourir sans
   attendre (JS, theme.js) ; sans JS, `.bb-reviews-rail__viewport` reste
   défilable au doigt/trackpad via son `overflow-x:auto` natif — jamais la
   seule façon d'atteindre un avis.

   Grille `auto 1fr auto`, pas flex + `position:absolute` : les colonnes CSS
   Grid suivent `direction` nativement, donc les deux boutons échangent déjà
   de côté en RTL sans règle miroir — seul le glyphe du chevron a besoin d'un
   `scaleX(-1)` explicite (même raisonnement déjà appliqué au rail de
   catégories ci-dessus, qui lui reste en `flex` car ses boutons sont
   centrés ENSEMBLE sous la ligne, pas de part et d'autre).

   ⚠️ Largeur de carte EXACTE par `calc()`, pas élastique en `vw` (corrigé sur
   demande explicite de l'owner, 2026-09-01 : « il affichera toujours 3
   avis », jamais 2 pleines + un bout de 3ᵉ qui dépasse). `calc()` retire les
   (N-1) espacements internes de `.bb-reviews-rail__list` puis divise par N :
   N cartes remplissent alors EXACTEMENT 100% du viewport, à n'importe quelle
   largeur d'écran — plus aucun aperçu partiel d'une carte suivante. */

/* `text-transform`/`letter-spacing` retirés d'ici (2026-09-02) : portés par
   `.bb-home-heading--display` désormais posée sur ce même `<h2>`
   (includes/home-reviews.php) — les garder ICI AUSSI aurait fait gagner
   cette règle sur `letter-spacing` (même spécificité 0-1-0, mais définie
   PLUS BAS dans ce fichier que `.bb-home-heading--display`, donc prioritaire
   à égalité) et affiché 0.03em au lieu des 0.04em demandés par l'owner. */

.bb-reviews-rail {
	display: grid;
	grid-template-columns: auto 1fr auto;
	align-items: center;
	gap: var(--bb-space-3);
}

.bb-reviews-rail__viewport {
	overflow-x: auto;
	overflow-y: hidden;
	scroll-snap-type: x proximity;
	scrollbar-width: none;
	-ms-overflow-style: none;
}

.bb-reviews-rail__viewport::-webkit-scrollbar {
	display: none;
}

.bb-reviews-rail__list {
	display: flex;
	flex-wrap: nowrap;
	gap: var(--bb-space-5);
	margin: 0;
	padding: var(--bb-space-1) 0;
	list-style: none;
}

.bb-review-card {
	display: flex;
	flex-direction: column;
	flex: 0 0 auto;
	/* 1 carte par page par défaut (mobile-first) — élargi ci-dessous en
	   tablette/bureau. Cf. note de calc() en tête de ce bloc. */
	width: 100%;
	scroll-snap-align: start;
	background: var(--bb-surface-white);
	border: 1px solid var(--bb-border-hairline-cream);
	border-radius: var(--bb-rounded-lg);
	padding: var(--bb-space-5);
	/* rgba de --bb-ink-navy (#16264A = 22,38,74) — même convention littérale
	   assumée qu'ailleurs dans ce fichier (cf. scrim du héro). */
	box-shadow: 0 2px 10px rgba( 22, 38, 74, 0.06 );
}

.bb-review-card__stars {
	font-size: 1rem;
	letter-spacing: 0.15em;
	margin: 0 0 var(--bb-space-3);
}

/* #162950 sur TOUTES les étoiles (retour owner, 2026-09-02), pleines ET
   vides — avant : pleines en #162950, vides en --bb-border-hairline (gris
   clair). La distinction pleine/vide reste lisible par la FORME du glyphe
   (★ plein vs ☆ contour, cf. bbio_review_stars_markup() dans
   home-reviews.php), pas seulement par la couleur — deux propriétés
   fusionnées en une seule règle, `.is-filled` n'a donc plus de raison
   d'exister séparément. */
.bb-review-card__star {
	color: var(--bb-brand-teal-dark);
}

.bb-review-card__quote {
	flex: 1;
	font-family: var(--bb-font-body);
	font-style: italic;
	font-size: 0.95rem;
	line-height: 1.6;
	color: var(--bb-ink-navy);
	margin: 0 0 var(--bb-space-4);
}

.bb-review-card__author {
	font-family: var(--bb-font-body);
	font-size: 0.8rem;
	font-weight: 600;
	color: var(--bb-ink-slate);
	margin: 0 0 var(--bb-space-4);
}

.bb-review-card__product {
	display: flex;
	align-items: center;
	gap: var(--bb-space-3);
	margin-block-start: auto;
	padding-block-start: var(--bb-space-4);
	border-block-start: 1px solid var(--bb-border-hairline-cream);
	text-decoration: none;
}

.bb-review-card__product-img {
	width: 56px;
	height: 56px;
	object-fit: cover;
	border-radius: var(--bb-rounded-md);
	flex-shrink: 0;
}

.bb-review-card__product-name {
	font-family: var(--bb-font-display);
	font-weight: 600;
	font-size: 0.85rem;
	line-height: 1.3;
	color: var(--bb-ink-navy);
}

.bb-review-card__product:hover .bb-review-card__product-name,
.bb-review-card__product:focus .bb-review-card__product-name {
	color: var(--bb-brand-teal-dark);
	text-decoration: underline;
}

.bb-reviews-rail__btn {
	width: 44px;
	height: 44px;
	flex-shrink: 0;
	/* `padding:0` : Astra pose `padding:15px 30px` (ou `.6em 1em .4em`) sur
	   `button` globalement — mesuré : sans cette ligne, la boîte s'élargit à
	   62×44px (le padding seul dépasse 44px, même avec `border-box`), et
	   `border-radius:9999px` dessine un ovale au lieu d'un cercle. */
	padding: 0;
	border: 1px solid var(--bb-border-hairline);
	border-radius: var(--bb-rounded-full);
	background: var(--bb-surface-white);
	color: var(--bb-ink-navy);
	display: flex;
	align-items: center;
	justify-content: center;
	cursor: pointer;
}

.bb-reviews-rail__btn:hover {
	background: var(--bb-surface-cream);
	/* Blanc, pas --bb-ink-navy : même raison que .bb-cat-rail__btn:hover
	   ci-dessus (fond devenu #162950, retour owner 2026-09-02). */
	color: var(--bb-surface-white);
}

.bb-reviews-rail__btn:focus {
	color: var(--bb-ink-navy);
}

.bb-reviews-rail__btn:focus-visible {
	outline: 2px solid var(--bb-brand-teal-dark);
	outline-offset: 2px;
}

.bb-reviews-rail__btn-icon {
	font-size: 1.5rem;
	line-height: 1;
	font-weight: 700;
}

html[dir="rtl"] .bb-reviews-rail__btn-icon {
	display: inline-block;
	transform: scaleX( -1 );
}

/* Mêmes points de rupture que la grille produits ci-dessus (768px/1280px) —
   même convention dans tout ce fichier. 2 cartes en tablette, 3 en bureau. */
@media ( min-width: 768px ) {
	.bb-review-card {
		width: calc( ( 100% - var(--bb-space-5) ) / 2 );
	}
}

@media ( min-width: 1280px ) {
	.bb-review-card {
		width: calc( ( 100% - 2 * var(--bb-space-5) ) / 3 );
	}
}

@media ( prefers-reduced-motion: reduce ) {
	.bb-reviews-rail__viewport {
		scroll-behavior: auto;
	}
}

/* ── Vidéo(s) client·e·s ("Ils utilisent déjà nos produits",
   includes/home-video-testimonials.php) ─────────────────────────────────
   Carte(s) au format portrait (9:16, source des vidéos), centrée(s), même
   habillage (fond, bordure, ombre) que `.bb-review-card` juste au-dessus
   pour rester dans la même famille visuelle. `preload="none"` posé côté PHP :
   seule la vignette (poster) pèse au chargement, la vidéo elle-même
   n'est récupérée qu'au clic play (mobile-first, TEMPLATE.md §1). */
.bb-video-testimonials__grid {
	display: flex;
	flex-wrap: wrap;
	justify-content: center;
	gap: var(--bb-space-5);
}

.bb-video-testimonials__card {
	width: 100%;
	max-width: 320px;
	background: var(--bb-surface-white);
	border: 1px solid var(--bb-border-hairline-cream);
	border-radius: var(--bb-rounded-lg);
	padding: var(--bb-space-3);
	box-shadow: 0 2px 10px rgba( 22, 38, 74, 0.06 );
}

.bb-video-testimonials__player {
	display: block;
	width: 100%;
	height: auto;
	aspect-ratio: 9 / 16;
	border-radius: var(--bb-rounded-md);
	background: var(--bb-ink-navy);
}

/* Capture d'écran (carte « image », home-video-testimonials.php) — PAS de
   `aspect-ratio` forcé comme `.player` ci-dessus : son ratio source
   (941×1672, ~9:16 quasi pile) n'en a de toute façon pas besoin, et le
   contenu utile (le texte du témoignage) va jusqu'aux bords — un recadrage
   forcé risquerait d'en couper un morceau. Ratio intrinsèque affiché tel
   quel, seule sa largeur est contrainte par `.bb-video-testimonials__card`. */
.bb-video-testimonials__image {
	display: block;
	width: 100%;
	height: auto;
	border-radius: var(--bb-rounded-md);
}

/* Bouton qui enrobe l'image (retour owner 2026-09-06 : « au clic, elle
   s'agrandit ») — `<button>` natif, reset des styles `button` par défaut
   d'Astra (padding 15px/30px, fond/bordure) pour que seule l'image reste
   visible. `cursor:zoom-in` : seul indice visuel que l'image est
   cliquable, la carte ne change pas d'aspect au survol (contrairement aux
   boutons ronds du reste du fichier — ici l'image EST le bouton). */
.bb-video-testimonials__zoom {
	display: block;
	width: 100%;
	padding: 0;
	border: none;
	background: none;
	cursor: zoom-in;
}

.bb-video-testimonials__zoom:focus-visible {
	outline: 2px solid var(--bb-brand-teal-dark);
	outline-offset: 2px;
	border-radius: var(--bb-rounded-md);
}

/* Lightbox (assets/js/theme.js) — UNE SEULE instance créée par le script et
   ajoutée en fin de `<body>`, réutilisée pour n'importe quel déclencheur
   `[data-bb-lightbox-trigger]` présent sur la page (aujourd'hui la seule
   capture d'écran de cette section, potentiellement d'autres cartes image
   à l'avenir). `position:fixed` + `z-index:1000` : au-dessus du header
   sticky d'Astra (`.site-header`/`#masthead`, son propre contexte
   d'empilement plafonne à `z-index:99` — cf. commentaire de
   `.bb-header-trust` plus haut dans ce fichier) et de tout le reste de la
   page, quel que soit l'endroit du DOM d'où elle est ouverte.
   `[hidden]` posé en classe ET attribut (même patron que `.bb-cat-rail__nav`
   plus haut) : un sélecteur `.bb-lightbox[hidden]` (spécificité 0-2-0) bat
   `.bb-lightbox{display:flex}` (0-1-0) — sans lui, la règle de classe
   annulerait l'attribut `hidden` posé par JS et la lightbox resterait
   affichée en permanence, vide, par-dessus toute la page. */
.bb-lightbox[hidden] {
	display: none;
}

.bb-lightbox {
	position: fixed;
	inset: 0;
	z-index: 1000;
	display: flex;
	align-items: center;
	justify-content: center;
	padding: var(--bb-space-5);
	background: rgba( 22, 38, 74, 0.85 );
}

.bb-lightbox__img {
	display: block;
	max-width: min( 90vw, 480px );
	max-height: 90vh;
	width: auto;
	height: auto;
	border-radius: var(--bb-rounded-md);
	box-shadow: 0 10px 40px rgba( 0, 0, 0, 0.35 );
}

/* Même famille visuelle que `.bb-cat-rail__btn`/`.bb-reviews-rail__btn`
   (cercle blanc 44px, bascule vers `--bb-surface-cream` — qui VAUT le navy
   de marque #162950, retour owner 2026-09-02 — au survol). */
.bb-lightbox__close {
	position: absolute;
	top: var(--bb-space-4);
	inset-inline-end: var(--bb-space-4);
	width: 44px;
	height: 44px;
	padding: 0;
	border: none;
	border-radius: var(--bb-rounded-full);
	background: var(--bb-surface-white);
	color: var(--bb-ink-navy);
	display: flex;
	align-items: center;
	justify-content: center;
	font-size: 1.1rem;
	cursor: pointer;
}

.bb-lightbox__close:hover {
	background: var(--bb-surface-cream);
	color: var(--bb-surface-white);
}

.bb-lightbox__close:focus-visible {
	outline: 2px solid var(--bb-surface-white);
	outline-offset: 2px;
}

/* ── Réassurance (3 promesses COD) ───────────────────────────────────────── */

/* Retour owner (2026-09-02) : le fond gris (`rgba(128,128,128,0.07)`, posé
   par le plugin — `aod-cod-pages.css`, JAMAIS modifié) jurait avec le reste
   de l'Accueil, entièrement blanc/crème jusqu'ici — neutralisé en blanc
   explicite. Section aussi « collée » à l'institutionnelle juste au-dessus
   (mesuré : 0px d'écart, bord à bord) — son `padding-block` interne ne crée
   de l'air qu'À L'INTÉRIEUR de la zone teintée, pas AVANT elle ; `margin-
   block-start` ajoute l'espace manquant entre les deux sections. */
.aod-home__reassure {
	display: grid;
	grid-template-columns: 1fr;
	gap: var(--bb-space-5);
	padding-block: var(--bb-space-7);
	margin-block-start: var(--bb-space-7);
	background: var(--bb-surface-white);
	border-radius: 0;
	text-align: center;
}

@media ( min-width: 768px ) {
	.aod-home__reassure {
		grid-template-columns: repeat( 3, 1fr );
	}
}

.aod-home__promise {
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: var(--bb-space-2);
}

.aod-home__promise h3 {
	font-family: var(--bb-font-display);
	font-weight: 700;
	font-size: 1rem;
	color: var(--bb-ink-navy);
	margin: 0;
}

.aod-home__promise p {
	font-family: var(--bb-font-body);
	font-weight: 400;
	font-size: 0.9rem;
	/* --bb-ink-navy, pas --bb-ink-slate — contraste AA (--bb-ink-slate échoue
	   ~2,6:1 sur blanc/crème, sous les seuils AA à toute taille). */
	color: var(--bb-ink-navy);
	margin: 0;
	max-width: 22rem;
}

/* Icône de réassurance en badge circulaire (DESIGN.md `badge-trust` :
   fond crème, texte navy) — cercle repris des pictogrammes de packaging.
   Contient désormais un SVG Phosphor (includes/home-reassure-icons.php,
   remplace les émojis du plugin) plutôt qu'un glyphe texte — `font-size`
   conservé, sans effet sur le SVG mais inoffensif si un émoji réapparaissait
   un jour (fichier introuvable, dégradation silencieuse de l'injection). */
.aod-home__ico {
	display: flex;
	align-items: center;
	justify-content: center;
	width: 56px;
	height: 56px;
	border-radius: var(--bb-rounded-full);
	background: var(--bb-surface-cream);
	font-size: 1.5rem;
	/* `currentColor` du SVG (`fill="currentColor"` posé dans le fichier
	   source Phosphor) hérite de cette couleur. Blanc, pas --bb-brand-teal :
	   ce jeton VAUT désormais la couleur du fond (#162950, retour owner
	   2026-09-02) — icône et fond identiques, invisible. */
	color: var(--bb-surface-white);
}

.aod-home__ico svg {
	width: 28px;
	height: 28px;
}

/* ── Scroll-reveal (Story 4.1, AC #2 — JS dans assets/js/theme.js) ──────
   État `.bb-reveal` = visible par défaut (SANS JS, contenu déjà visible,
   cf. Dev Notes : piège de la Story 3.1/3.2 sur un état initial invisible
   qui dépend d'un script pouvant ne jamais s'exécuter). Le JS ajoute
   `.bb-reveal--hidden` UNIQUEMENT s'il s'exécute réellement ET si
   `prefers-reduced-motion` n'est pas actif, puis retire cette classe à
   l'entrée dans le viewport — jamais l'inverse. */
.bb-reveal--hidden {
	opacity: 0;
	transform: translateY( 16px );
}

.bb-reveal--visible {
	opacity: 1;
	transform: none;
	transition: opacity 0.5s ease-out, transform 0.5s ease-out;
}

@media ( prefers-reduced-motion: reduce ) {
	.bb-reveal--hidden {
		opacity: 1;
		transform: none;
	}
	.bb-reveal--visible {
		transition: none;
	}
}

/* ── Boutique — puces de catégorie (Story 4.2, AC #1) ────────────────────
   Patron repris de mockups/boutique.html (.filters/.chip/.chip.active),
   mécanisme changé (architecture.md Décision 3 : liens réels, pas de JS) —
   [aria-current="page"] remplace aria-pressed en sélecteur CSS, le rendu
   visuel de l'état actif reste identique au mock. */
.bb-shop-chips {
	display: flex;
	gap: var(--bb-space-2);
	padding-block: var(--bb-space-4);
	overflow-x: auto;
}

.bb-chip {
	flex: none;
	padding: var(--bb-space-2) var(--bb-space-4);
	border-radius: var(--bb-rounded-full);
	border: 1px solid var(--bb-border-hairline);
	font-family: var(--bb-font-body);
	font-size: 0.78rem;
	font-weight: 600;
	color: var(--bb-ink-navy);
	background: var(--bb-surface-white);
	white-space: nowrap;
	text-decoration: none;
}

.bb-chip[aria-current="page"] {
	border-color: var(--bb-brand-teal-dark);
	color: var(--bb-brand-teal-dark);
	background: var(--bb-brand-teal-wash);
}

.bb-chip:focus-visible {
	outline: 2px solid var(--bb-brand-teal-dark);
	outline-offset: 2px;
}

/* ── Boutique — badge-catégorie à accent-produit (Story 4.2, AC #2) ──────
   S'applique partout où `astra_woo_shop_category_after` tire (Boutique,
   archives de catégorie ET grille [products] de l'Accueil, cf. shop-hooks.php)
   — effet de bord voulu (DESIGN.md : un seul badge par carte). Masque donc
   `.ast-woo-product-category` (Story 4.1) sur ces mêmes cartes pour ne
   jamais empiler les deux étiquettes.
   `!important` nécessaire et vérifié (pas par réflexe, cf. Dev Notes/Previous
   Story Intelligence) : Astra pose déjà `.woocommerce-js ul.products
   li.product .ast-woo-product-category, .woocommerce-page ul.products
   li.product .ast-woo-product-category { display:block }` dans son propre
   CSS statique (woocommerce-grid.min.css), spécificité (0,4,2) — supérieure
   à celle atteignable ici sans dupliquer sa liste de sélecteurs pour DEUX
   gabarits différents (archive Boutique = `.woocommerce-page`, Accueil =
   ni l'un ni l'autre côté serveur). `.woocommerce-js` est ajoutée par le
   cœur WooCommerce en JS sur TOUTES les pages (page-title.js), donc la
   règle Astra s'applique aussi sur l'Accueil dès que le JS s'exécute —
   confirmé par inspection réelle de `document.styleSheets` (Chromium
   headless, 2026-09-01), pas supposé. */
.ast-woo-product-category:has(+ .bb-badge-category) {
	display: none !important;
}

.bb-badge-category {
	display: inline-flex;
	align-items: center;
	gap: 5px;
	background: var(--bb-surface-white);
	color: var(--bb-ink-navy);
	font-family: var(--bb-font-body);
	font-size: 0.7rem;
	font-weight: 700;
	/* Logique (pas left/right physiques) — corrigé en revue de code
	   (2026-09-01) : `padding: 3px var(--bb-space-2) 3px 6px` (physique)
	   ne se retournait pas en RTL, vérifié réellement sur
	   /boutique/?aod_lang=ar (getBoundingClientRect) — le point décoratif,
	   déplacé à droite par le retournement du flex row, héritait du
	   padding-right (8px, prévu pour le côté texte) au lieu du 6px prévu
	   pour son côté. `padding-inline` (début/fin) suit le sens d'écriture
	   automatiquement. */
	padding-block: 3px;
	padding-inline: 6px var(--bb-space-2);
	border-radius: var(--bb-rounded-full);
	border: 1px solid var(--accent);
	margin-block-end: var(--bb-space-2);
}

.bb-badge-category__dot {
	display: inline-block;
	width: 8px;
	height: 8px;
	border-radius: var(--bb-rounded-full);
	background: var(--accent);
}

.bb-badge-category--ginger { --accent: var(--bb-accent-ginger); }
.bb-badge-category--fortifiant { --accent: var(--bb-accent-fortifiant); }
.bb-badge-category--oignon { --accent: var(--bb-accent-oignon); }
.bb-badge-category--keratine { --accent: var(--bb-accent-keratine); }
.bb-badge-category--masque { --accent: var(--bb-accent-masque); }

/* ── Boutique — rupture de stock (Story 4.2, AC #3) — CSS seul, WooCommerce
   et Astra gèrent déjà la donnée/le comportement (cf. Dev Notes). Portée
   `ul.products` : Boutique, archives de catégorie ET grille de l'Accueil. */
ul.products li.product.outofstock .astra-shop-thumbnail-wrap img {
	filter: grayscale( 0.6 ) opacity( 0.55 );
}

/* `:not(.ast-onsale-card)` — corrigé en revue de code (2026-09-01) : en
   style de boutique « moderne » (`astra_is_shop_page_modern_style()`,
   actif sur ce clone, vérifié via `wp eval`), le ruban de promotion
   partage la classe `.ast-on-card-button` (`class-astra-woocommerce.php:309`
   — `'ast-on-card-button ast-onsale-card'`). Sans cette exclusion, un
   produit à la fois en rupture de stock ET en promotion perdrait aussi son
   ruban de promotion. */
ul.products li.product.outofstock .ast-on-card-button:not(.ast-onsale-card) {
	display: none;
}

/* Astra pose déjà (woocommerce-grid.min.css) `.woocommerce-js ul.products
   li.product .ast-shop-product-out-of-stock, .woocommerce-page ul.products
   li.product .ast-shop-product-out-of-stock { position:absolute; left:1em;
   right:1em; bottom:1em; background-color:rgba(255,255,255,.88);
   text-transform:uppercase; font-weight:700; ... }` — spécificité (0,4,2),
   supérieure à un simple `ul.products li.product .ast-shop-product-out-of-stock`
   (0,3,2) ici, ET `.woocommerce-js` est ajoutée par le cœur WooCommerce en JS
   sur TOUTES les pages (donc présente même sur l'Accueil une fois le JS
   exécuté). Deux bugs trouvés et vérifiés réellement (Chromium headless,
   `getBoundingClientRect`/`document.styleSheets`, 2026-09-01), pas supposés :
   (1) sans réinitialiser `right`/`bottom`, poser seulement
   `inset-block-start`/`inset-inline-start` fait COEXISTER mon `top` avec le
   `bottom:1em` d'Astra → un élément absolu avec top ET bottom non-auto et
   hauteur auto s'ÉTIRE pour remplir l'espace entre les deux (idem largeur
   avec `left`/`right` d'Astra) : le badge couvrait TOUTE l'image en blanc
   translucide au lieu d'une pastille ; (2) `background`/`color` perdaient
   aussi face à la spécificité (0,4,2) d'Astra. `!important` sur l'ensemble de
   la règle, nécessaire et vérifié — pas par réflexe. */
ul.products li.product .ast-shop-product-out-of-stock {
	position: absolute !important;
	inset-block-start: var(--bb-space-2) !important;
	inset-inline-start: var(--bb-space-2) !important;
	inset-block-end: auto !important;
	inset-inline-end: auto !important;
	background: var(--bb-ink-navy) !important;
	color: var(--bb-surface-white) !important;
	font-family: var(--bb-font-body) !important;
	font-size: 0.65rem !important;
	font-weight: 700 !important;
	padding: 3px var(--bb-space-2) !important;
	border-radius: var(--bb-rounded-full) !important;
	text-transform: none !important;
}

ul.products li.product.outofstock .astra-shop-thumbnail-wrap {
	position: relative;
}

/* ── Contact (Story 4.3) — mise en page/RTL déjà fournies par
   plugins-dev/aod-cod-form/assets/css/aod-cod-pages.css (grille 2 colonnes,
   propriétés logiques, `.aod-home__h2` déjà stylé sans scope pour le titre) ;
   ici, seulement la typographie/couleur qui manque encore. */
.aod-contact__intro {
	font-family: var(--bb-font-body);
	color: var(--bb-ink-navy);
}

.aod-contact__list {
	color: var(--bb-ink-navy);
}

.aod-contact__list a {
	color: var(--bb-brand-teal-dark);
	text-decoration: none;
}

.aod-contact__list a:hover {
	color: var(--bb-brand-teal-dark-hover);
	text-decoration: underline;
}

.aod-contact__list a:focus-visible {
	outline: 2px solid var(--bb-brand-teal-dark);
	outline-offset: 2px;
}

/* Corrigé (2026-09-01) : le formulaire (`.aod-cod`) rendait très étroit
   (~291px au lieu de 640px) sur desktop, comme replié en colonne mobile —
   signalé par l'owner, vérifié réellement (Chromium headless,
   `getBoundingClientRect` avant/après un correctif test). Cause :
   `plugins-dev/aod-cod-form/assets/css/aod-cod-form.css` pose
   `.aod-cod { margin: 24px auto }` puis, à partir de 922px,
   `margin-inline: 0 auto` — pensé pour centrer/ancrer le formulaire dans le
   flux normal de la fiche produit (Story 3.1/3.2), où un bloc en `width:auto`
   remplit déjà son conteneur par défaut. Réutilisé tel quel dans la grille
   CSS de `.aod-contact` (`aod-cod-pages.css`), la marge `auto` sur l'axe
   inline empêche l'étirement normal d'un élément de grille et le fait
   RÉTRÉCIR à la taille de son contenu au lieu de remplir sa colonne.
   `margin-inline: 0` neutralise cette marge auto UNIQUEMENT sur le
   formulaire de Contact (`.aod-contact__form`, jamais `.aod-cod` seul — la
   fiche produit n'est pas touchée) ; `max-width: 640px` du plugin continue de
   s'appliquer normalement, l'étirement de grille prend le relais.
   Sélecteur composé `.aod-contact__form.aod-cod` (0,2,0), pas
   `.aod-contact__form` seul (0,1,0) : `aod-cod-form.css` (qui pose la marge
   fautive) est enqueue APRÈS `theme.css` sur cette page (`bbio-theme-css`
   avant `aod-cod-form-css`, vérifié dans le HTML réellement servi) — à
   spécificité égale, la feuille chargée en dernier gagne, donc ma règle
   perdait silencieusement sans cette spécificité supplémentaire. */
.aod-contact__form.aod-cod {
	margin-inline: 0;
}

/* ── Pied de page (includes/site-footer.php) — logo/tagline + navigation +
   bandeau de copyright, demande owner explicite (2026-09-02 : « il manque un
   footer stylé harmonisé ») ──────────────────────────────────────────────
   Fond BLANC pour la zone haute — pas une couleur de marque (teal/navy) :
   le logo (wp-content/uploads/…/12_Logo.jpeg) est un JPEG à fond blanc
   OPAQUE, pas un PNG transparent (vérifié : Read sur le fichier réel) — sur
   tout fond non blanc, son cadre rectangulaire serait visible. Le bandeau du
   bas (copyright), lui, n'a pas cette contrainte : légère teinte crème pour
   distinguer les deux zones sans dupliquer un fond de section déjà utilisé
   pleine largeur ailleurs (institutionnelle, réassurance). */
.bb-footer {
	margin-block-start: var(--bb-space-7);
	border-block-start: 1px solid var(--bb-border-hairline-cream);
	background: var(--bb-surface-white);
}

/* 3 colonnes (marque / navigation / coordonnées) — retour owner (2026-09-02) :
   « le footer doit contenir tout ce que la page Contact contient ». `start`
   sur l'axe bloc (pas `center`) : les 3 colonnes n'ont pas la même hauteur
   (la 3ᵉ porte jusqu'à 4 lignes), un centrage vertical les désalignerait en
   haut de section. */
.bb-footer__top {
	display: grid;
	grid-template-columns: 1.2fr 1fr 1.3fr;
	align-items: start;
	gap: var(--bb-space-6);
	padding-block: var(--bb-space-7);
}

.bb-footer__brand {
	display: flex;
	flex-direction: column;
	gap: var(--bb-space-1);
}

.bb-footer__sitename {
	font-family: var(--bb-font-display);
	font-weight: 700;
	font-size: 1.1rem;
	color: var(--bb-ink-navy);
}

.bb-footer__tagline {
	margin: 0;
	font-family: var(--bb-font-body);
	font-size: 0.82rem;
	color: var(--bb-ink-slate);
}

/* Instagram/TikTok (retour owner 2026-09-06, includes/site-footer.php) —
   même famille de bouton rond que `.bb-cat-rail__btn`/`.bb-lightbox__close`
   plus haut dans ce fichier (cercle 40px, bascule vers `--bb-surface-cream`
   — qui VAUT le navy de marque #162950 — au survol), pour rester dans la
   même famille visuelle plutôt qu'inventer un style de bouton de plus. */
.bb-footer__social {
	display: flex;
	gap: var(--bb-space-3);
	margin-block-start: var(--bb-space-2);
}

.bb-footer__social-link {
	display: flex;
	align-items: center;
	justify-content: center;
	width: 40px;
	height: 40px;
	flex-shrink: 0;
	border: 1px solid var(--bb-border-hairline);
	border-radius: var(--bb-rounded-full);
	color: var(--bb-ink-navy);
}

.bb-footer__social-link svg {
	width: 1.15rem;
	height: 1.15rem;
	display: block;
}

.bb-footer__social-link:hover {
	background: var(--bb-surface-cream);
	color: var(--bb-surface-white);
}

/* `:focus` séparé de `:hover` (pas groupé) : même patron défensif que
   `.bb-cat-rail__btn`/`.bb-reviews-rail__btn` plus haut dans ce fichier —
   un focus au clavier ne doit reprendre le fond/la couleur du survol QUE
   si le navigateur juge l'indication visible nécessaire (`:focus-visible`
   ci-dessous s'en charge, séparément) ; un simple `:focus` (ex. clic
   souris) reste sur les couleurs normales. */
.bb-footer__social-link:focus {
	color: var(--bb-ink-navy);
}

.bb-footer__social-link:focus-visible {
	outline: 2px solid var(--bb-brand-teal-dark);
	outline-offset: 2px;
}

/* Retour owner (2026-09-02) : « applique la police et la couleur du texte
   comme pour "Boutique en ligne" (.bb-footer__tagline) » — étendu aux titres
   de colonne, aux liens de navigation ET aux coordonnées : même
   `--bb-font-body`/`--bb-ink-slate` que le slogan, seuls `font-weight`/
   `font-size` restent propres à chaque élément (pas demandés). */
.bb-footer__heading {
	margin: 0 0 var(--bb-space-3);
	font-family: var(--bb-font-body);
	font-weight: 700;
	font-size: 0.9rem;
	/* Retour owner (2026-09-02) : #162950 sur "Navigation"/"Coordonnées" — les
	   deux titres de colonne partagent cette même classe, --bb-ink-slate
	   d'origine (harmonisation précédente) laissé aux liens/coordonnées
	   eux-mêmes, inchangés. */
	color: var(--bb-brand-teal-dark);
}

.bb-footer__links,
.bb-footer__contact {
	display: flex;
	flex-direction: column;
	align-items: flex-start;
	gap: var(--bb-space-2);
	margin: 0;
	padding: 0;
	list-style: none;
}

.bb-footer__links a {
	font-family: var(--bb-font-body);
	font-weight: 600;
	font-size: 0.9rem;
	color: var(--bb-ink-slate);
	text-decoration: none;
}

.bb-footer__links a:hover,
.bb-footer__links a:focus {
	color: var(--bb-brand-teal-dark);
}

.bb-footer__links a:focus-visible {
	outline: 2px solid var(--bb-brand-teal-dark);
	outline-offset: 2px;
}

/* Coordonnées (téléphone, adresse, e-mail, lien carte) — mêmes données que
   `.aod-contact__list` de la page Contact (includes/contact-details.php),
   habillage propre au footer (classe distincte : `.aod-contact__ico` porte
   déjà un style posé par `aod-cod-pages.css`, pas question d'en hériter ici
   par accident). */
.bb-footer__contact li {
	display: flex;
	align-items: flex-start;
	gap: var(--bb-space-2);
}

/* Retour owner (2026-09-06) : « les icônes des informations de Coordonnées
   doivent être des icônes Phosphor » — remplace les émojis natifs
   (📞/📍/✉️/🗺️, colorés et non stylables) par les SVG `currentColor` de
   assets/icons/footer/ (includes/site-footer.php). `margin-block-start` :
   les émojis se casaient naturellement sur la ligne de texte via leur
   propre métrique de police ; un SVG n'a pas cette métrique et flottait
   trop haut par rapport à la première ligne du texte à côté (mesuré à
   l'œil contre `line-height:1.5` du texte voisin) — ce petit décalage
   recale visuellement l'icône sur cette première ligne. */
.bb-footer__ico {
	display: flex;
	flex-shrink: 0;
	width: 1.1rem;
	height: 1.1rem;
	margin-block-start: 0.15rem;
	color: var(--bb-ink-slate);
}

.bb-footer__ico svg {
	width: 100%;
	height: 100%;
	display: block;
}

.bb-footer__contact a,
.bb-footer__contact span:not(.bb-footer__ico) {
	font-family: var(--bb-font-body);
	font-size: 0.88rem;
	line-height: 1.5;
	color: var(--bb-ink-slate);
}

.bb-footer__contact a {
	text-decoration: none;
}

.bb-footer__contact a:hover,
.bb-footer__contact a:focus {
	color: var(--bb-brand-teal-dark);
}

.bb-footer__contact a:focus-visible {
	outline: 2px solid var(--bb-brand-teal-dark);
	outline-offset: 2px;
}

/* Retour owner (2026-09-02) : pleine largeur, sans marge de chaque côté.
   `.bb-footer` (parent) est déjà hors du conteneur Astra (hooké sur
   `astra_footer_before`, direct enfant de `.hfeed.site`) — mais reste
   BORNÉ par `margin-inline: 0.5cm` posé sur `body` (tout en haut de ce
   fichier), qui laisse un filet de 0,5 cm de chaque côté (mesuré,
   Playwright : 18,9px). Même patron que `.bb-announce` plus haut dans ce
   fichier pour s'en sortir : `width:100vw` + `margin-inline:calc(50% - 50vw)`,
   qui s'annule algébriquement contre N'IMPORTE QUELLE marge posée par ses
   ancêtres, `body` compris — une simple `margin-inline` négative n'aurait
   marché qu'à CETTE valeur précise de marge, pas si elle changeait ailleurs. */
.bb-footer__bottom {
	width: 100vw;
	margin-inline: calc( 50% - 50vw );
	border-block-start: 1px solid var(--bb-border-hairline-cream);
	background: var(--bb-surface-cream);
	padding-block: var(--bb-space-4);
	padding-inline: var(--bb-space-5);
}

.bb-footer__credit {
	margin: 0;
	text-align: center;
	font-family: var(--bb-font-body);
	font-size: 0.8rem;
	/* --bb-ink-slate reste lisible sur le nouveau fond #162950 (retour owner,
	   2026-09-02) : contraste mesuré 5,49:1, au-dessus du seuil AA (4,5:1)
	   pour du texte normal — pas de changement nécessaire ici. */
	color: var(--bb-ink-slate);
}

.bb-footer__credit a {
	/* Blanc, pas --bb-brand-teal-dark : ce jeton VAUT désormais la couleur du
	   fond (#162950) — lien et fond identiques, totalement invisible. */
	color: var(--bb-surface-white);
	font-weight: 600;
	text-decoration: none;
}

.bb-footer__credit a:hover,
.bb-footer__credit a:focus {
	text-decoration: underline;
}

.bb-footer__credit a:focus-visible {
	/* Blanc, même raison que ci-dessus : un anneau de la couleur du fond est
	   un anneau invisible. */
	outline: 2px solid var(--bb-surface-white);
	outline-offset: 2px;
}

@media ( max-width: 700px ) {
	.bb-footer__top {
		grid-template-columns: 1fr;
		text-align: center;
	}

	.bb-footer__brand {
		align-items: center;
	}

	.bb-footer__links,
	.bb-footer__contact {
		align-items: center;
	}

	.bb-footer__contact li {
		justify-content: center;
	}
}

/* Pied de page PAR DÉFAUT d'Astra (une simple ligne « Copyright © {année}
   BELLISSIMA BIO | Propulsé par Thème WordPress Astra », sans habillage) —
   masqué, remplacé par .bb-footer ci-dessus (includes/site-footer.php,
   injecté juste avant via le hook `astra_footer_before`). Un seul footer
   rendu, jamais les deux empilés.
   `!important` nécessaire et vérifié (pas par réflexe, CDP
   `CSS.getMatchedStylesForNode`) : Astra pose
   `.site-below-footer-wrap[data-section="section-below-footer-builder"]
   {display:grid}` (spécificité 0-2-0, un attribut ET une classe) — supérieure
   à `.site-below-footer-wrap` seul (0-1-0) ici, quel que soit l'ordre
   d'impression des feuilles. */
.site-below-footer-wrap {
	display: none !important;
}
