/*
Theme Name: Petlib
Description: Thème enfant de GeneratePress pour le site Petlib.
Author: Petlib
Template: generatepress
Version: 1.0.0
Requires PHP: 7.4
License: GNU General Public License v2 or later
License URI: http://www.gnu.org/licenses/gpl-2.0.html
Text Domain: petlib
*/

/* Les personnalisations CSS du site viennent ici. */

:root {
    /* Couleurs générales du site */
    --bs-primary: #F8F4EE;
    --bs-secondary: #f4f4f4;

    /* Univers Chat */
    /* Le secondaire porte le texte du menu d'univers, posé sur le primaire très
       clair : #5c765a n'y donnait que 3,87:1. Foncé à #4d6b4b, qui atteint
       4,61:1 sur ce fond et 5,96:1 en blanc sur fond plein. */
    --petlib-chat-primary: #e1e4d1;
    --petlib-chat-secondary: #4d6b4b;
    --petlib-chat-tertiary: #8EA18B;

    /* Univers Chien */
    --petlib-chien-primary: #d1d8e0;
    --petlib-chien-secondary: #1f486e;
    --petlib-chien-tertiary: #5B7EA1;

    /* Univers NAC
       Le secondaire sert de fond au texte blanc (bouton de filtres, pastille du
       menu) : #d56918 n'y donnait que 3,58:1, sous le seuil WCAG AA de 4,5:1.
       Assombri à #b8560f, qui monte à 4,80:1 tout en restant franchement orange. */
    --petlib-nac-primary: #fce4cc;
    --petlib-nac-secondary: #b8560f;
    --petlib-nac-tertiary: #E79A59;

    /* Versions pour fond sombre — quatrième valeur de chaque maison.
       Les secondaires sont calibrés pour du texte sur fond clair : posés sur le
       #1f1f1f du pied de page, ils tombent à 1,73:1 pour le chien, 2,76:1 pour le
       chat et 3,43:1 pour le NAC, tous sous le plancher de 4,5:1.
       Ces trois-là sont les mêmes couleurs — teinte et saturation conservées à
       l'identique — dont on n'a fait monter que la luminosité, jusqu'à 5,5:1 sur
       ce fond : une marge au-dessus du seuil, parce qu'ils servent à du texte de
       0,8125rem en capitales.
       Mesurés sur #1f1f1f : chien 5,52:1, chat 5,51:1, nac 5,52:1.
       À n'employer que sur fond sombre : sur le crème du site ils retombent
       autour de 2,7:1. */
    --petlib-chien-inverse: #5e9ad2;
    --petlib-chat-inverse: #789f76;
    --petlib-nac-inverse: #ec731a;

    /* Texte secondaire — mentions, métadonnées, fil d'Ariane.
       Réchauffé plutôt que neutre : un gris pur posé sur le crème du site sonne
       comme une salissure, alors qu'un gris tiré de la même famille chromatique
       s'y intègre. Il remplace les #666 et #5a5a5a dispersés dans la feuille.
       5,45:1 sur le crème, 5,73:1 sur le blanc des cartes. */
    --petlib-encre-douce: #6b625a;

    /* Polices — chargées par petlib_enqueue_fonts() */
    --petlib-font-titre: 'Nunito Sans', sans-serif;
    --petlib-font-texte: 'Inter', sans-serif;

    --bs-font-sans-serif: var(--petlib-font-texte);
}

/*    TYPOGRAPHIE     */

/* GeneratePress pose sa pile système sur « body, button, input, select,
   textarea » (main.css) : on reprend la même liste, sinon les champs de
   formulaire garderaient la police système. */
body,
button,
input,
select,
textarea {
    font-family: var(--petlib-font-texte);
}

/* GeneratePress met h1-h6 en « font-family: inherit » : sans cette règle, les
   titres hériteraient d'Inter via le body. */
h1,
h2,
h3,
h4,
h5,
h6 {
    font-family: var(--petlib-font-titre);
    font-weight: 800;
}

/*    LARGEUR DU SITE     */

/* GeneratePress plafonne .grid-container à 1200px dans son main.min.css, sans
   qu'aucun réglage du Customizer n'intervienne. On surcharge ici, la feuille du
   thème enfant étant chargée après celle du parent.
   Portée volontairement globale : l'en-tête, le contenu et le pied de page
   partagent ce conteneur, les élargir séparément les désalignerait. */
.grid-container {
    max-width: 1400px;
}

/*    FOND DU SITE     */

/* Détache le header du crème du body, qui le prolongeait visuellement. */
.site-header {
    border-bottom: 1px solid #ECE6DD;
    box-shadow: 0 2px 8px rgba(0, 0, 0, .04);
}

/* Remplace le gris de GeneratePress (#f7f8f9) par le crème de la marque.
   Portée volontairement globale : à restreindre aux fiches produit avec
   « .single-product body » si le rendu ne convient pas ailleurs. */
body {
    background-color: var(--bs-primary);
}

.text-chat {
    color: var(--petlib-chat-secondary);
}

.text-chien {
    color: var(--petlib-chien-secondary);
}

.text-nac {
    color: var(--petlib-nac-secondary);
}

/*    LIENS ET TEXTE SECONDAIRE     */

/* Le thème n'avait jamais défini de couleur de lien : les liens de contenu
   héritaient du #1e73be de GeneratePress, un bleu qui n'appartient à aucune
   des trois palettes du site et qui ne passait le seuil AA sur le crème que
   d'un centième (4,51:1). Ils prennent désormais la couleur de l'univers
   courant — 8,67:1 sur le crème pour le chien — avec le repli graphite hors
   univers, comme l'anneau de focus.

   Le soulignement est conservé et seulement décalé : la couleur seule ne doit
   pas être ce qui distingue un lien du paragraphe qui l'entoure.

   La liste vise les zones de contenu rédactionnel. Les liens qui sont déjà des
   composants — boutons, cartes — portent leur propre habillage à une
   spécificité supérieure. « :not(nav a) » écarte le fil d'Ariane, qui vit lui
   aussi dans .entry-content mais relève de la navigation utilitaire, pas de la
   prose. */
.entry-content a:not(.btn):not(.button):not(nav a),
.petlib-bloc-texte a,
.petlib-editorial-univers-final a,
.petlib-faq-reponse a,
.woocommerce-Tabs-panel a {
    color: var(--petlib-univers-color, #1f1f1f);
    text-underline-offset: .18em;
}

/* Le fil d'Ariane sortait en #767676 sur le crème, soit 4,15:1 — sous le seuil
   AA, et sur des liens. La couleur vient de WooCommerce, jamais du thème :
   elle n'avait donc jamais été mesurée.
   « body.woocommerce » porte la spécificité à (0,2,1), juste au-dessus du
   « .woocommerce:where(…) .woocommerce-breadcrumb » du plugin, qui pèse (0,2,0).
   Il reste volontairement monochrome : une piste de navigation utilitaire n'a
   pas à concurrencer en couleur les actions réelles de la page. */
body.woocommerce .woocommerce-breadcrumb,
body.woocommerce .woocommerce-breadcrumb a {
    color: var(--petlib-encre-douce);
}

/*    FOCUS CLAVIER (global)     */

/* Le thème n'avait aucun anneau de focus. Ses quinze règles « :focus » se
   contentaient de rejouer le survol — un changement de couleur ou de
   luminosité — et quatre endroits supprimaient le contour natif du navigateur.
   Un visiteur au clavier ne pouvait donc pas savoir où il se trouvait.

   Une seule règle globale le rétablit, à la couleur de l'univers courant. Le
   repli graphite couvre le panier, la commande et l'espace client, qui n'ont
   pas d'univers — même idiome de repli que .petlib-bouton-filtres plus bas.

   « outline » plutôt que « box-shadow » : le thème pose déjà des ombres sur
   les cartes et les blocs flottants, un anneau en box-shadow devrait les
   redéclarer à chaque fois pour ne pas les écraser. Le contour vit sur un
   canal séparé, épouse le border-radius de l'élément, et survit au mode
   contraste élevé de Windows, qui efface les ombres.

   « :focus-visible » plutôt que « :focus » : le clic souris ne fait pas
   apparaître l'anneau, seule la navigation au clavier le déclenche. */
a:focus-visible,
button:focus-visible,
input:focus-visible,
select:focus-visible,
textarea:focus-visible,
summary:focus-visible,
[tabindex]:focus-visible {
    outline: 2px solid var(--petlib-univers-color, #1f1f1f);
    outline-offset: 2px;
}

/* Bootstrap pose « outline: 0 » sur « .btn:focus-visible » et « .accordion-button:focus »,
   WooCommerce fait de même sur ses boutons : ces sélecteurs pèsent (0,2,0), au-dessus
   du sélecteur de type ci-dessus qui ne pèse que (0,1,1). On les rejoint à
   égalité — la feuille enfant étant chargée après, elle l'emporte. Sans cette
   règle, le CTA du hero, les boutons d'achat et l'accordéon de la fiche
   produit restaient sans anneau.
   La liste ne retient que les classes Bootstrap réellement présentes dans le
   thème : .btn, .accordion-button et .btn-close. */
.btn:focus-visible,
.button:focus-visible,
.accordion-button:focus-visible,
.btn-close:focus-visible,
button.single_add_to_cart_button:focus-visible {
    outline: 2px solid var(--petlib-univers-color, #1f1f1f);
    outline-offset: 2px;
}

/* Les cartes produit et les cadres d'image rognent ce qui dépasse
   (overflow: hidden) : un anneau posé à 2px à l'extérieur du lien y serait
   coupé. On le rentre à l'intérieur pour ces cas-là. */
body.petlib-categorie ul.products li.product a:focus-visible,
.petlib-produit .related ul.products li.product a:focus-visible,
.petlib-categories-univers-carte a:focus-visible {
    outline-offset: -2px;
}

/*    BARRE DE PROMOTION     */

/* On cible .bi-star-fill et non toutes les icônes de la barre : seule l'étoile
   passe en doré, le camion et la bulle gardent la couleur du texte. La règle
   couvre les deux occurrences du markup, la rangée desktop et le carrousel
   mobile. */
.petlib-promo-bar .bi-star-fill {
    color: #f5b301;
}

/* Bulle blanche sur un fond quasi blanc : sans contour elle disparaît. Le
   glyphe étant du texte, on le cerne avec text-stroke plutôt qu'avec une
   bordure, qui encadrerait la boîte et non le dessin. */
.petlib-promo-bar .bi-chat-dots-fill {
    color: #fff;
    -webkit-text-stroke: 1px #000;
    paint-order: stroke fill;
}

/* Vert de l'univers Chat, repris ici comme vert de marque : il évite
   d'introduire une quatrième couleur hors palette, et se lit comme un « c'est
   offert ». */
.petlib-promo-bar .bi-truck-front-fill {
    color: var(--petlib-chat-secondary);
}

/*    MENU     */

.menu-image > a::before {
    content: "";
    display: inline-block;
    width: 24px;
    height: 24px;
    background-size: contain;
    background-repeat: no-repeat;
    margin-right: 8px;
    vertical-align: middle;
}

.menu-compte > a::before,
.menu-panier > a::before {
    font-family: dashicons;
    display: inline-block;
    font-size: 20px;
    margin-right: 8px;
    vertical-align: middle;
}

/* Chemins relatifs à style.css, et non racine-absolus : le sous-dossier
   d'installation diffère d'un environnement à l'autre, un /petlib/ en dur
   renverrait un 404 en production.

   Variantes 100×100 et non les originaux : ces icônes sont affichées en 24px,
   et les fichiers d'origine font 300×300 pour 60 à 79 Ko pièce — 207 Ko à eux
   trois, plus que toutes les autres images de la page réunies. Le 100×100
   couvre encore un écran à 4× de densité, pour 24 Ko au total. Les variantes
   sont générées par WordPress, il n'y a aucun fichier à produire. */
.menu-chien > a::before {
    background-image: url('../../uploads/2026/07/chien-menu-100x100.png');
}

.menu-chat > a::before {
    background-image: url('../../uploads/2026/07/chat-menu-100x100.png');
}

.menu-nac > a::before {
    background-image: url('../../uploads/2026/07/nac-menu-100x100.png');
}

.menu-compte > a::before {
    content: "\f110";
}

.menu-panier > a::before {
    content: "\f174";
}

/* Pastille du nombre d'articles, posée sur l'icône du panier.
   Le repère de positionnement est le <li> : la pastille est un frère du lien,
   le walker de WordPress ne permettant pas d'insérer proprement à l'intérieur.
   pointer-events désactivé pour qu'elle n'intercepte pas le clic du lien
   qu'elle recouvre. */
.menu-panier {
    position: relative;
}

.menu-panier .petlib-panier-compteur {
    pointer-events: none;
}

/* Calage sur le coin haut-droit de l'icône : le lien a 20px de padding gauche
   et le glyphe fait 20px, son bord droit est donc à 40px du <li>. On y retire
   quelques pixels pour que la pastille chevauche l'icône. */
.menu-panier .petlib-panier-pastille {
    position: absolute;
    top: 50%;
    left: 31px;
    transform: translateY(-19px);

    display: flex;
    align-items: center;
    justify-content: center;

    min-width: 18px;
    height: 18px;
    padding: 0 5px;

    background-color: #C0392B;
    border: 2px solid #fff;
    border-radius: 999px;
    color: #fff;
    font-size: 0.6875rem;
    font-weight: 700;
    line-height: 1;
}

.menu-chat a {
    color: var(--petlib-chat-secondary) !important;
    font-weight: bold;
}

.menu-chien a {
    color: var(--petlib-chien-secondary) !important;
    font-weight: bold;
}

.menu-nac a {
    color: var(--petlib-nac-secondary) !important;
    font-weight: bold;
}

/* L'entrée de l'univers déjà consulté disparaît du menu de l'en-tête : la barre
   d'univers juste en dessous indique où l'on est, et les deux univers restants
   gagnent la place ainsi libérée. La classe vient de
   petlib_marque_univers_courant() (functions.php).
   Le seuil est celui du menu de GeneratePress (max-width: 768px), et non les
   768px de Bootstrap employés ailleurs : à 768px exactement le menu est encore
   replié derrière le bouton hamburger, où l'entrée reste le chemin le plus
   court vers la racine de l'univers. */
@media (min-width: 769px) {
    .main-navigation .petlib-univers-en-cours {
        display: none;
    }
}

.menu-recherche {
    display: flex;
    align-items: center;
    padding: 0 10px;

}

.menu-recherche > a {
    background: none !important;
    cursor: default;
}

.petlib-search-trigger {
    display: flex;
    align-items: center;
    justify-content: center;

    width: 36px;
    height: 36px;
    padding: 0;

    color: #111;
    background: transparent;
    border: 0;
    cursor: pointer;
}

.petlib-search-trigger svg {
    width: 24px;
    height: 24px;

    fill: none;
    stroke: currentColor;
    stroke-width: 1.8;
    stroke-linecap: round;
}

.petlib-search-trigger:hover {
    color: var(--petlib-chien-secondary);
}

#petlib-search-modal .petlib-search {
    width: 100%;
}

.petlib-search {
    display: flex;
    align-items: center;
    width: 160px;
    height: 40px;
    padding: 0 10px 0 19px;

    background-color: var(--bs-secondary);
    border: 1px solid #e4e4e4;
    border-radius: 999px;
}

.petlib-search input[type="search"] {
    flex: 1;
    min-width: 0;
    height: 100%;
    padding: 0;

    color: #222;
    font-size: 16px;

    background: transparent;
    border: 0;
    box-shadow: none;
}

/* Le champ visible, c'est la pastille : l'input à l'intérieur est
   volontairement sans bordure ni fond. L'anneau de focus se pose donc sur le
   conteneur, et on le retire de l'input pour ne pas en dessiner deux. */
.petlib-search:focus-within {
    outline: 2px solid var(--petlib-univers-color, #1f1f1f);
    outline-offset: 2px;
}

.petlib-search input[type="search"]:focus-visible {
    outline: none;
}

/* #999 ne donnait que 2,6:1 sur le gris du champ. L'encre douce monte à 5,4:1. */
.petlib-search input[type="search"]::placeholder {
    color: var(--petlib-encre-douce);
}

.petlib-search button {
    display: flex;
    align-items: center;
    justify-content: center;

    flex: 0 0 36px;
    width: 36px;
    height: 36px;
    padding: 0;

    color: #111;
    background: transparent;
    border: 0;
    cursor: pointer;
}

.petlib-search button svg {
    width: 27px;
    height: 27px;

    fill: none;
    stroke: currentColor;
    stroke-width: 1.8;
    stroke-linecap: round;
}

.petlib-search button:hover {
    color: var(--petlib-chien-secondary);
}

/*    MENU D'UNIVERS (sous l'en-tete)     */

/* La classe .petlib-univers-<slug> posée sur la barre alimente les deux
   variables : la couleur suit donc l'univers sans règle par univers.
   La couleur de texte est portée par la barre, pas par les liens, pour que
   currentColor serve aussi aux traits de séparation. */
/* Le dégradé entier passe par une variable, et non ses arrêts un par un : un
   univers peut ainsi avoir son propre nombre d'arrêts.
   La valeur par défaut est dérivée de la couleur principale de l'univers, très
   éclaircie en haut et pleine en bas, pour que chat et nac aient un dégradé
   comparable tant qu'ils n'ont pas leurs valeurs propres. */
.petlib-menu-univers {
    --petlib-menu-fond: linear-gradient(
        180deg,
        color-mix(in srgb, var(--petlib-univers-primary-color) 45%, #fff) 0%,
        color-mix(in srgb, var(--petlib-univers-primary-color) 75%, #fff) 55%,
        var(--petlib-univers-primary-color) 100%
    );

    background-image: var(--petlib-menu-fond);
    color: var(--petlib-univers-color);
    border-bottom: 1px solid var(--petlib-univers-color);
}

/* Valeurs choisies à la main pour l'univers chien. */
.petlib-menu-univers.petlib-univers-chien {
    --petlib-menu-fond: linear-gradient(180deg, #EAF2FB 0%, #DCE8F6 55%, #D2E0F0 100%);
}

/* « space-evenly » répartit tout l'espace libre entre les entrées et de part et
   d'autre de la liste. Il retombe de lui-même sur « safe center » quand la
   place manque, ce qui préserve le défilement mobile : le début de la liste
   reste atteignable.
   La gouttière ne sert donc que de minimum ; l'essentiel de la respiration en
   desktop vient de la répartition, et en mobile du padding des liens. */
.petlib-menu-univers-liste {
    display: flex;
    flex-wrap: wrap;
    justify-content: space-evenly;
    gap: 8px 16px;

    margin: 0;
    padding: 10px 0;

    list-style: none;
}

/* « block » et non « inline » : sans cela le fond arrondi du survol se
   limiterait à la hauteur du texte.
   Un peu d'interlettrage : en capitales et à cette taille, le texte est
   sensiblement plus lisible espacé. */
.petlib-menu-univers-liste a {
    display: block;
    padding: 6px 16px;

    border-radius: 999px;
    color: inherit;
    font-size: 0.8125rem;
    font-weight: 700;
    letter-spacing: .04em;
    text-decoration: none;
    text-transform: uppercase;
    transition: background-color .2s ease, color .2s ease;
}

/* L'entrée de la catégorie consultée porte la même pastille que le survol.
   Les classes « ancestor » couvrent les catégories filles : l'une vient de la
   hiérarchie du menu, « current-product_cat-ancestor » de celle des termes,
   quand la sous-catégorie visitée n'est pas elle-même dans le menu.
   « petlib-menu-univers-actif » est posée par petlib_marque_categorie_produit()
   (functions.php) : sur une fiche produit, WordPress ne marque aucune entrée. */
.petlib-menu-univers-liste a:hover,
.petlib-menu-univers-liste a:focus-visible,
.petlib-menu-univers-liste .current-menu-item > a,
.petlib-menu-univers-liste .current-menu-parent > a,
.petlib-menu-univers-liste .current-menu-ancestor > a,
.petlib-menu-univers-liste .current-product_cat-ancestor > a,
.petlib-menu-univers-liste .petlib-menu-univers-actif > a {
    background-color: var(--petlib-univers-color);
    color: #fff;
    text-decoration: none;
}

/* Barre défilante plutôt qu'un retour à la ligne en mobile : les entrées
   restent sur une seule ligne, comme une navigation secondaire. */
@media (max-width: 767px) {
    .petlib-menu-univers-liste {
        flex-wrap: nowrap;
        overflow-x: auto;
        scrollbar-width: thin;
    }

    .petlib-menu-univers-liste li {
        flex-shrink: 0;
    }
}

/*    HOME - UNIVERS     */

.petlib-univers {
    position: relative;
}

/* Le décor déborde volontairement du conteneur pour toucher les bords de
   l'écran. « 100vw » compte la barre de défilement, que la zone visible n'a pas :
   le décor dépassait donc de 4px de chaque côté et ouvrait une barre horizontale
   sur toute la page. Le débordement est coupé sur le body — voir la règle
   « overflow-x: clip » en fin de feuille — plutôt que corrigé ici : c'est le
   comportement voulu du décor, c'est la page qui doit le contenir. */
.petlib-univers::before {
    content: "";
    position: absolute;
    top: 0;
    left: 50%;
    z-index: -1;

    width: 100vw;
    height: 100%;

    background-image: url('../../uploads/2026/07/bg-univers-animaux.jpg');
    background-repeat: no-repeat;
    background-position: top center;
    background-size: cover;
    transform: translateX(-50%);
}

.petlib-univers-header {
    margin-bottom: 32px;
}

/* Titre d'ouverture du site : c'est la plus grosse typographie de tout Petlib,
   et elle doit le rester — les titres d'encart des pages d'univers montent au
   même moment, la hiérarchie ne tiendrait plus si celui-ci ne prenait pas
   l'avance. line-height resserré : à cette taille l'interligne par défaut
   ouvrait un blanc entre les deux lignes du titre en mobile. */
.petlib-univers-title {
    margin-bottom: 8px;
    font-size: 2.75rem;
    font-weight: bold;
    line-height: 1.1;
}

.petlib-univers-tagline {
    margin-bottom: 0;
    color: var(--petlib-encre-douce);
    font-size: 1.1rem;
}

.petlib-univers-slick .slick-slide {
    height: auto;
}

.petlib-univers-slick .slick-track {
    display: flex;
    align-items: stretch;
}

.petlib-univers-slide {
    height: 100%;
    padding: 0 12px;
}

.petlib-univers-slick .slick-prev,
.petlib-univers-slick .slick-next {
    z-index: 1;

    width: 36px;
    height: 36px;

    background-color: rgba(0, 0, 0, .6);
    border-radius: 50%;
}

.petlib-univers-slick .slick-prev:hover,
.petlib-univers-slick .slick-next:hover {
    background-color: rgba(0, 0, 0, .8);
}

.petlib-univers-slick .slick-prev::before,
.petlib-univers-slick .slick-next::before {
    color: #fff;
}

.petlib-univers-slick .slick-prev {
    left: 8px;
}

.petlib-univers-slick .slick-next {
    right: 8px;
}

.petlib-univers-chat {
    --petlib-univers-color: var(--petlib-chat-secondary);
    --petlib-univers-primary-color: var(--petlib-chat-primary);
}

.petlib-univers-chien {
    --petlib-univers-color: var(--petlib-chien-secondary);
    --petlib-univers-primary-color: var(--petlib-chien-primary);
}

.petlib-univers-nac {
    --petlib-univers-color: var(--petlib-nac-secondary);
    --petlib-univers-primary-color: var(--petlib-nac-primary);
}

.petlib-univers-card {
    max-width: 400px;
    margin-left: auto;
    margin-right: auto;
    padding: 24px;

    background-color: var(--petlib-univers-primary-color);
    border-radius: 16px;
}

.petlib-univers-card-image img {
    width: 100%;
    aspect-ratio: 1 / 1;

    object-fit: cover;
    border-radius: 12px;
}

/* L'image est ancrée en bas de son cadre (80% de la hauteur), en fond perdu */
.petlib-univers-card--bleed {
    margin-top: 0;

    padding: 0;
    overflow: hidden;
}

.petlib-univers-card--bleed .petlib-univers-card-image,
.petlib-univers-card--bleed .petlib-univers-card-content {
    margin-top: 0;
}

.petlib-univers-card--bleed .petlib-univers-card-image {
    position: relative;

    flex: 0 0 41.6667%;
    max-width: 41.6667%;

    padding: 0;
}

.petlib-univers-card--bleed .petlib-univers-card-content {
    flex: 0 0 58.3333%;
    max-width: 58.3333%;
}

.petlib-univers-card--bleed .petlib-univers-image-frame {
    position: absolute;
    bottom: 0;
    left: 0;
    width: 100%;
    height: 80%;
}

.petlib-univers-card--bleed .petlib-univers-image-frame img {
    display: block;
    width: 100%;
    height: 100%;

    aspect-ratio: auto;
    object-fit: cover;
    border-radius: 0;
}

.petlib-univers-card--bleed .petlib-univers-card-content {
    padding: 20px;
}

.petlib-univers-card-content {
    display: flex;
    flex-direction: column;
    gap: 12px;
}

/* Tailles calées sur Nunito Sans 800 / Inter : ces polices sont plus larges que
   l'ancienne pile système, et aux tailles précédentes (1.75rem / 0.95rem) le
   titre « Univers Chien » passait sur deux lignes. La carte s'allongeait, et
   comme le cadre image fait 80% de sa hauteur pour une largeur fixe, l'image
   se retrouvait rognée sur les côtés.

   C'est la contrainte qui borne ce titre : il a été remonté de 1.3/1.4rem à
   1.45/1.6rem, mesuré sur une ligne aux deux largeurs, et 1.75rem reste la
   limite haute connue. Toute augmentation se vérifie sur la carte, pas dans
   l'absolu. */
.petlib-univers-card-content h2 {
    color: var(--petlib-univers-color);
    font-size: 1.45rem;
    line-height: 1.2;
}

@media (min-width: 768px) {
    .petlib-univers-title {
        font-size: 3.5rem;
    }

    .petlib-univers-card-content h2 {
        font-size: 1.6rem;
    }
}

.petlib-univers-separator {
    display: block;
    width: 60px;
    height: 4px;

    background-color: var(--petlib-univers-color);
    border-radius: 999px;
}

.petlib-univers-text {
    margin: 0;
    font-size: 0.875rem;
}

/* Le bouton d'univers : l'action de découverte, partout où elle apparaît — les
   cartes de la home, le hero d'univers, la sortie des encarts.

   Le rembourrage et la taille appartiennent à cette classe et non à une classe
   de contexte. Ils vivaient sur .petlib-hero-univers-cta, si bien que tout
   bouton d'univers posé ailleurs retombait sur le « .375rem .75rem » de
   Bootstrap : 36px de haut, sous les 44px d'une cible tactile confortable, et
   à côté des 12px/24px que le référentiel décrit pour ce composant.

   La transition est déclarée ici, et non au survol, pour valoir aussi au retour.
   Elle remplace celle de Bootstrap, qui ne couvre pas border-radius. */
.petlib-univers-cta {
    align-self: flex-start;

    padding: 12px 24px;

    color: #fff;
    background-color: var(--petlib-univers-color);
    border: 0;
    font-size: 1rem;
    font-weight: 700;
    transition: background-color .2s ease, border-radius .2s ease;
}

/* Survol commun aux cartes de la home et au hero des pages d'univers : les coins
   s'adoucissent et le fond se fonce d'un cran.
   La couleur est assombrie par color-mix plutôt que fixée univers par univers,
   comme le dégradé de la barre d'univers plus haut : un quatrième univers suivra
   sans règle supplémentaire. Assombrir ne fait que gagner du contraste avec le
   texte blanc, aucun des trois ne redescend sous le seuil AA.
   « color » est redéclaré parce que Bootstrap cible « .btn:hover », plus
   spécifique que la classe seule : sans ça le bouton perdait son fond au survol
   et son texte repassait en gris. */
.petlib-univers-cta:hover {
    color: #fff;
    background-color: color-mix(in srgb, var(--petlib-univers-color) 85%, #000);
    border-radius: 20px;
}

/*    PAGE D'UNIVERS - HERO     */

/* Encart d'ouverture des pages d'univers. Photo et texte se superposent par
   position absolue plutôt que par background-image : l'image reste une balise
   <img>, donc garde le srcset que wp_get_attachment_image() lui a posé. */
.petlib-hero-univers {
    position: relative;
    display: flex;
    align-items: center;

    min-height: 420px;
    padding: 24px;
    overflow: hidden;

    border-radius: 16px;
}

/* La photo est cadrée large — le chien à droite, le mur nu à gauche. En mobile
   le recadrage mange les bords : on garde le centre, seul cadrage où le chien
   reste entier et où il subsiste du mur derrière le texte.

   Sélecteur doublé : GeneratePress impose « height: auto » à toute image des
   pages WooCommerce (.woocommerce img), qui l'emporte sur une classe seule et
   rendait la photo à sa hauteur naturelle au lieu de remplir l'encart. */
.petlib-hero-univers .petlib-hero-univers-image {
    position: absolute;
    inset: 0;
    z-index: 0;

    width: 100%;
    height: 100%;

    object-fit: cover;
    object-position: center;
}

/* Voile : dégradé de la crème du site (--bs-primary), qui se trouve être la
   couleur du mur au fond de la photo. Il garantit le contraste du texte quel
   que soit le recadrage, et se fond dans le mur en desktop. La couleur est
   écrite en rgba faute de pouvoir mettre une variable hexadécimale dans un
   dégradé. */
.petlib-hero-univers::after {
    content: "";
    position: absolute;
    inset: 0;
    z-index: 1;

    background-image: linear-gradient(to right,
        rgba(248, 244, 238, .97) 0%,
        rgba(248, 244, 238, .94) 55%,
        rgba(248, 244, 238, .88) 75%,
        rgba(248, 244, 238, .45) 90%,
        rgba(248, 244, 238, 0) 100%);
}

/* Largeur volontairement inférieure à celle de l'encart : le chien occupe le
   tiers droit de la photo, une ligne pleine largeur viendrait le recouvrir. */
.petlib-hero-univers-contenu {
    position: relative;
    z-index: 2;

    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 14px;

    max-width: 280px;
}

.petlib-hero-univers-titre {
    margin: 0;
    color: var(--petlib-univers-color);
    font-size: 2.25rem;
    line-height: 1.15;
}

.petlib-hero-univers-accroche {
    max-width: 22em;
    margin: 0;
    font-size: 1.0625rem;
    line-height: 1.45;
}

/* .petlib-hero-univers-cta ne porte plus aucune règle : son rembourrage et sa
   taille sont remontés sur .petlib-univers-cta, dont ils décrivent le
   composant. La classe reste dans le balisage comme point d'accroche. */

.petlib-hero-univers-mention {
    margin: 0;
    color: var(--petlib-encre-douce);
    font-size: 0.8125rem;
    line-height: 1.4;
}

@media (min-width: 768px) {
    .petlib-hero-univers {
        min-height: 480px;
        padding: 48px;
    }

    /* En desktop la photo n'est presque plus recadrée : le mur nu occupe déjà
       toute la gauche, le voile n'a plus qu'à l'uniformiser. */
    .petlib-hero-univers::after {
        background-image: linear-gradient(to right,
            rgba(248, 244, 238, .90) 0%,
            rgba(248, 244, 238, .70) 35%,
            rgba(248, 244, 238, 0) 65%);
    }

    .petlib-hero-univers-contenu {
        max-width: 520px;
    }

    .petlib-hero-univers-titre {
        font-size: 3.5rem;
    }

    .petlib-hero-univers-accroche {
        font-size: 1.1875rem;
    }
}

/*    PAGE D'UNIVERS - CATEGORIES     */

/* L'écart avec l'encart suivant n'est pas déclaré ici : le rythme vertical de
   la page d'univers est réglé en un seul endroit, plus bas. */

/* Les trois titres d'encart — catégories, produits, valeurs — partagent la même
   échelle : 1.75rem en mobile, 2.25rem au-delà. Ils ne sont pas fondus dans une
   règle commune pour autant, chaque encart restant autonome, mais toute retouche
   de l'un se reporte sur les deux autres. */
.petlib-categories-univers-titre {
    margin-bottom: 16px;
    color: var(--petlib-univers-color);
    font-size: 1.75rem;
    line-height: 1.2;
}

/* État avant que Slick ne prenne la main, et repli si le JavaScript ne tourne
   pas : les cartes défilent horizontalement plutôt que de s'empiler en grille.
   Le padding bas réserve la place de la barre de défilement. */
.petlib-categories-univers-liste {
    display: flex;
    gap: 12px;
    overflow-x: auto;
    scroll-snap-type: x proximity;

    margin: 0;
    padding: 0 0 8px;

    scrollbar-width: thin;
}

.petlib-categories-univers-carte {
    flex: 0 0 auto;
    width: 150px;
    scroll-snap-align: start;
}

/* Carrousel monté (categories-slick-init.js, mobile uniquement) : Slick pose sa
   propre piste, le défilement natif et la largeur fixe des cartes n'ont plus
   lieu d'être — Slick calcule lui-même la largeur pour en montrer deux. */
.petlib-categories-univers-liste.slick-initialized {
    display: block;
    overflow: visible;

    /* Compense le padding des cartes ci-dessous, pour que la première et la
       dernière restent alignées sur les bords de l'encart. */
    margin: 0 -6px;
    padding-bottom: 0;
}

/* Slick ne gère aucun espacement entre les slides : la gouttière vient du
   padding des cartes, comme sur le carrousel de la home. */
.petlib-categories-univers-liste.slick-initialized .petlib-categories-univers-carte {
    padding: 0 6px;
}

/* slick-theme.css sort la pagination du flux (position: absolute; bottom: -25px),
   où elle chevaucherait l'encart suivant. On la remet dans le flux. */
.petlib-categories-univers-liste .slick-dots {
    position: static;
    margin-top: 12px;
}

.petlib-categories-univers-liste .slick-dots li button::before {
    color: var(--petlib-univers-color);
}

.petlib-categories-univers-carte a {
    display: block;
    color: inherit;
    text-decoration: none;
}

/* Le cadre porte le fond et les coins : il reste carré même quand aucune image
   n'a pu être trouvée, plutôt que de laisser la carte s'effondrer.
   Il est aussi le repère du nom, posé par-dessus en bas — d'où le position. */
.petlib-categories-univers-image {
    position: relative;
    aspect-ratio: 1 / 1;
    overflow: hidden;

    background-color: var(--petlib-univers-primary-color);
    border-radius: 12px;
}

/* GeneratePress impose « height: auto » à toute image des pages WooCommerce via
   « .woocommerce img ». Ce sélecteur est à égalité de spécificité et l'emporte
   par l'ordre de chargement, la feuille enfant venant après celle du parent. */
.petlib-categories-univers-image img {
    display: block;
    width: 100%;
    height: 100%;

    object-fit: cover;
    transition: transform .3s ease;
}

/* Le nom est posé sur la photo, centré en bas. Le dégradé n'est pas décoratif :
   les vignettes viennent des produits, on ne maîtrise ni leur cadrage ni leur
   luminosité, et du blanc sur une photo claire deviendrait illisible. Il est
   tiré de l'encre du thème plutôt que d'un noir pur, et s'éteint avant le haut
   du cadre pour ne pas assombrir l'image entière.
   Le padding haut est large : c'est lui qui donne au dégradé la place de
   s'établir sous le texte.
   La marge est remise à zéro parce que le nom est un h3 : GeneratePress pose
   20px sous tout titre, et sur un élément calé en « bottom: 0 » cette marge
   décollerait le bandeau du bas du cadre. */
.petlib-categories-univers-nom {
    position: absolute;
    right: 0;
    bottom: 0;
    left: 0;

    display: block;
    margin: 0;
    padding: 32px 10px 12px;

    background: linear-gradient(
            to top,
            rgba(17, 17, 17, .88) 0%,
            rgba(17, 17, 17, .72) 60%,
            rgba(17, 17, 17, 0) 100%
    );
    color: #fff;
    font-family: var(--petlib-font-titre);
    font-size: 1rem;
    font-weight: 800;
    line-height: 1.25;
    text-align: center;
}

@media (hover: hover) {
    .petlib-categories-univers-carte a:hover img {
        transform: scale(1.06);
    }
}

@media (prefers-reduced-motion: reduce) {
    .petlib-categories-univers-image img {
        transition: none;
    }

    .petlib-categories-univers-carte a:hover img {
        transform: none;
    }
}

/* À partir de la tablette, trois catégories par ligne. Un nombre fixe et non un
   auto-fill : les vignettes portent maintenant leur nom en surimpression, et il
   leur faut une largeur franche pour rester lisibles — un remplissage
   automatique les aurait réduites à 180px sur un grand écran. */
@media (min-width: 768px) {
    .petlib-categories-univers-titre {
        margin-bottom: 24px;
        font-size: 2.25rem;
    }

    .petlib-categories-univers-liste {
        display: grid;
        grid-template-columns: repeat(3, 1fr);
        gap: 24px;

        overflow-x: visible;
        padding-bottom: 0;
    }

    .petlib-categories-univers-carte {
        width: auto;
    }
}

/*    PAGE D'UNIVERS - RYTHME VERTICAL     */

/* L'écart entre deux encarts est réglé ici et nulle part ailleurs : la page en
   comptera huit, et huit marges à tenir d'accord se seraient désaccordées à la
   première retouche. Chaque encart ne déclare donc que son contenu.
   48px en mobile, 64px au-delà : au-dessus des 32px qui séparent deux blocs
   ordinaires du site, parce que ces encarts sont des sections pleine largeur —
   à 32px ils se touchaient plus qu'ils ne se suivaient. */
.petlib-univers-racine main > section {
    margin-bottom: 48px;
}

.petlib-univers-racine main > section:last-child {
    margin-bottom: 0;
}

@media (min-width: 768px) {
    .petlib-univers-racine main > section {
        margin-bottom: 64px;
    }
}

/*    PAGE D'UNIVERS - PRODUITS     */

/* La grille elle-même n'est pas déclarée ici : elle vient de
   « body.petlib-categorie ul.products », le système de cartes déjà écrit pour
   les archives de sous-catégorie. Cet encart ne pose que son titre. */
.petlib-produits-univers-titre {
    margin-bottom: 16px;
    color: var(--petlib-univers-color);
    font-size: 1.75rem;
    line-height: 1.2;
}

/* Le bouton ferme l'encart, centré sous la grille. Le <p> porte l'alignement
   plutôt que le lien lui-même : centrer un élément de type bloc demanderait des
   marges automatiques et une largeur, là où le texte se centre tout seul. */
.petlib-produits-univers-suite {
    margin: 24px 0 0;
    text-align: center;
}

@media (min-width: 768px) {
    .petlib-produits-univers-titre {
        font-size: 2.25rem;
    }

    .petlib-produits-univers-suite {
        margin-top: 32px;
    }
}

/*    PAGE D'UNIVERS - VALEURS     */

/* Mobile : tout s'empile — l'image, le propos, les trois repères. Aucune
   déclaration de grille ici, l'ordre du balisage suffit.

   Le fondu est un masque posé sur l'image, et non un voile en dégradé posé
   par-dessus comme le fait le hero : le masque efface la photo elle-même, si
   bien qu'elle se dissout dans ce qu'il y a derrière, quelle que soit la
   couleur — il n'y a pas de crème à resynchroniser le jour où le fond de la
   page change. Le préfixe -webkit- reste nécessaire pour Safari.

   À cette largeur la jonction est horizontale : c'est le bord bas de la photo
   qui s'efface, dans le titre qui la suit. Hauteur fixe et cadrage en cover
   plutôt que la hauteur naturelle : le fondu mange le dernier tiers, une image
   entière n'en montrerait qu'un bout inutilement haut.

   Sélecteur doublé : GeneratePress impose « height: auto » à toute image des
   pages WooCommerce (.woocommerce img), qui pèse autant qu'une classe suivie
   d'un type et l'emporterait selon l'ordre de chargement des feuilles. */
.petlib-valeurs-univers .petlib-valeurs-univers-image img {
    display: block;
    width: 100%;
    height: 260px;

    object-fit: cover;
    object-position: center;

    -webkit-mask-image: linear-gradient(to bottom, #000 65%, transparent 100%);
    mask-image: linear-gradient(to bottom, #000 65%, transparent 100%);

    border-radius: 12px;
}

/* Surtitre : il reste à l'encre douce et non à la couleur d'univers, que porte
   déjà le titre juste dessous — deux lignes colorées l'une sur l'autre feraient
   du titre un doublon plus gros. Les majuscules et l'interlettrage sont ceux du
   menu d'univers, seul autre libellé capitalisé du site.

   Marge haute réduite : le fondu a déjà ouvert une bonne centaine de pixels
   au-dessus du bloc de texte. Les 24px d'avant, quand la photo s'arrêtait net,
   feraient ici un trou. */
.petlib-valeurs-univers-surtitre {
    margin: 8px 0 6px;

    color: var(--petlib-encre-douce);
    font-family: var(--petlib-font-titre);
    font-size: 0.8125rem;
    font-weight: 700;
    letter-spacing: .08em;
    text-transform: uppercase;
}

.petlib-valeurs-univers-titre {
    margin: 0 0 12px;
    color: var(--petlib-univers-color);
    font-size: 1.75rem;
    line-height: 1.2;
}

.petlib-valeurs-univers-texte {
    margin-bottom: 24px;
    line-height: 1.6;
}

.petlib-valeurs-univers-liste {
    display: grid;
    gap: 20px;

    margin: 0;
    padding: 0;

    list-style: none;
}

/* Chaque repère est une grille de deux colonnes : l'icône tient la première sur
   les deux lignes, le titre et le texte se suivent dans la seconde. Un flex
   aurait demandé un conteneur de plus autour du texte. */
.petlib-valeur {
    display: grid;
    grid-template-columns: auto 1fr;
    column-gap: 14px;
    row-gap: 2px;
}

/* L'icône est le seul endroit coloré du repère : le titre reste à l'encre, un
   bloc de trois titres en couleur d'univers ferait concurrence au titre de
   l'encart juste au-dessus.

   Elle est posée dans une pastille ronde, teinte très claire de la couleur
   d'univers obtenue par color-mix plutôt qu'écrite en dur : un univers n'a
   toujours que ses deux couleurs à déclarer, la pastille en découle.

   Le fond est mélangé au blanc et non au crème de la page : la pastille se
   détache ainsi du fond quel que soit l'endroit où l'encart est posé.

   Dimension fixe et flex: none, sinon la grille rendrait la pastille ovale dès
   que le texte du repère est plus haut qu'elle. align-self: start la cale sur
   le titre du repère et non au milieu du bloc, dont la hauteur varie avec le
   nombre de lignes. */
.petlib-valeur-icone {
    grid-row: 1 / 3;
    align-self: start;

    display: inline-flex;
    flex: none;
    align-items: center;
    justify-content: center;

    width: 38px;
    height: 38px;

    background-color: color-mix(in srgb, var(--petlib-univers-color) 12%, #fff);
    border-radius: 50%;
    color: var(--petlib-univers-color);
    font-size: 1.125rem;
    line-height: 1;
}

.petlib-valeur-titre {
    font-family: var(--petlib-font-titre);
    font-size: 1rem;
    font-weight: 800;
}

.petlib-valeur-texte {
    color: var(--petlib-encre-douce);
    line-height: 1.5;
}

/* À partir de la tablette : le propos à gauche, la photo à droite, à parts
   égales. Les deux colonnes se touchent — gap nul, align-items: stretch — parce
   que le fondu a besoin d'une jonction à couvrir : un espace entre elles, ou une
   photo laissée à sa hauteur naturelle, redonnerait deux blocs posés côte à
   côte, exactement ce que le fondu efface. */
@media (min-width: 768px) {
    .petlib-valeurs-univers {
        display: grid;
        grid-template-columns: 1fr 1fr;
        gap: 0;
        align-items: stretch;
    }

    /* Placement par la grille et non par « order » ni par l'ordre du balisage :
       celui-ci doit garder l'image en premier, elle ouvre l'encart en mobile. */
    .petlib-valeurs-univers-contenu {
        grid-column: 1;
        grid-row: 1;

        padding-right: 16px;
    }

    /* Conteneur en position relative et photo en absolu, comme le hero : la
       colonne est étirée par la grille mais n'a pas de hauteur propre à
       laquelle un « height: 100% » pourrait se rapporter. Le min-height la lui
       donne quand c'est la photo, et non le texte, qui commande la rangée. */
    .petlib-valeurs-univers-image {
        position: relative;
        grid-column: 2;
        grid-row: 1;

        min-height: 340px;
    }

    /* La jonction est verticale à cette largeur : c'est le bord gauche de la
       photo qui s'efface. Le cadrage retient la droite de l'image, où se tient
       le chien — le mur nu, à gauche, est justement ce que le fondu dissout. */
    .petlib-valeurs-univers .petlib-valeurs-univers-image img {
        position: absolute;
        inset: 0;

        height: 100%;
        object-position: right center;

        -webkit-mask-image: linear-gradient(to right, transparent 0, #000 45%);
        mask-image: linear-gradient(to right, transparent 0, #000 45%);
    }

    /* C'est le surtitre qui ouvre la colonne à cette largeur : la marge haute
       de repli, héritée du mobile où la photo le précède, n'a plus lieu d'être. */
    .petlib-valeurs-univers-surtitre {
        margin-top: 0;
    }

    .petlib-valeurs-univers-titre {
        font-size: 2.25rem;
    }
}

/*    PAGE D'UNIVERS - BESOINS     */

.petlib-besoins-univers-titre {
    margin-bottom: 16px;
    color: var(--petlib-univers-color);
    font-size: 1.75rem;
    line-height: 1.2;
}

/* État avant que Slick ne prenne la main, et repli si le JavaScript ne tourne
   pas : les cartes défilent horizontalement plutôt que de s'empiler. Même
   dispositif que le carrousel des catégories. */
.petlib-besoins-univers-liste {
    display: flex;
    gap: 12px;
    overflow-x: auto;
    scroll-snap-type: x proximity;

    margin: 0;
    padding: 0 0 8px;

    scrollbar-width: thin;
}

/* La diapositive et la carte sont deux éléments distincts : Slick pose sa largeur
   sur la première, la gouttière doit donc vivre à l'intérieur de cette largeur —
   en marge, les cartes déborderaient de la piste. Le fond, le trait et les coins
   appartiennent à la seconde, sinon la gouttière serait blanche. */
.petlib-besoin {
    flex: 0 0 86%;
    scroll-snap-align: start;
}

/* Carte du référentiel : blanc sur le crème, trait crème 1px, rayon de contenant,
   pose de carte à 4%. En colonne et en pleine hauteur pour qu'en desktop les
   trois cartes s'alignent malgré des listes de rayons inégales — celle des repas
   n'en compte qu'un, celle des promenades quatre.
   overflow: hidden — le visuel épouse les coins de la carte au lieu de les
   déborder. */
.petlib-besoin-carte {
    display: flex;
    flex-direction: column;
    height: 100%;

    background-color: #fff;
    border: 1px solid #ECE6DD;
    border-radius: 12px;
    box-shadow: 0 2px 8px rgba(0, 0, 0, .04);
    overflow: hidden;
}

/* Le cadre garde son format même sans image — la couleur claire de l'univers
   tient alors la place, plutôt que de laisser la carte s'effondrer. Il est aussi
   le repère du texte posé par-dessus, d'où le position. */
.petlib-besoin-visuel {
    position: relative;
    aspect-ratio: 4 / 3;
    overflow: hidden;

    background-color: var(--petlib-univers-primary-color);
}

/* Sélecteur à égalité de spécificité avec le « height: auto » que GeneratePress
   impose à toute image des pages WooCommerce ; il l'emporte par l'ordre de
   chargement, la feuille enfant venant après celle du parent. */
.petlib-besoin-visuel img {
    display: block;
    width: 100%;
    height: 100%;

    object-fit: cover;
}

/* Titre et accroche sur la photo. Le dégradé n'est pas décoratif : les visuels
   viennent des produits tant que les photos définitives n'existent pas, on ne
   maîtrise ni leur cadrage ni leur luminosité, et du blanc sur une photo claire
   deviendrait illisible. Même voile que les vignettes de catégorie, tiré de
   l'encre du thème et éteint avant le haut du cadre. */
.petlib-besoin-texte {
    position: absolute;
    right: 0;
    bottom: 0;
    left: 0;

    padding: 44px 16px 16px;

    background-image: linear-gradient(
            to top,
            rgba(17, 17, 17, .88) 0%,
            rgba(17, 17, 17, .72) 55%,
            rgba(17, 17, 17, 0) 100%
    );
    color: #fff;
}

/* Graisse déclarée : Nunito Sans n'est chargée qu'en 800 et GeneratePress pose
   une graisse plus légère sur les h3 — le navigateur la synthétiserait. */
.petlib-besoin-titre {
    margin: 0 0 4px;
    color: #fff;
    font-size: 1.25rem;
    font-weight: 800;
    line-height: 1.25;
}

.petlib-besoin-accroche {
    margin: 0;
    font-size: 0.8125rem;
    line-height: 1.4;
}

.petlib-besoin-rayons {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;

    margin: 0;
    padding: 16px;

    list-style: none;
}

/* Pastille : le ton clair de l'univers en fond, sa couleur en texte — 6,6:1 pour
   le bleu du chien, au-dessus du plancher de 4,5:1. Au survol, l'aplat plein et
   le texte blanc, exactement le basculement de l'entrée active du menu d'univers.
   Pas de soulignement, contrairement aux liens de contenu : une pastille est un
   objet de navigation, sa forme dit déjà qu'elle se clique. */
.petlib-besoin-rayon {
    display: block;
    padding: 6px 14px;

    background-color: var(--petlib-univers-primary-color);
    border-radius: 999px;
    color: var(--petlib-univers-color);
    font-size: 0.8125rem;
    font-weight: 700;
    text-decoration: none;
    transition: background-color .2s ease, color .2s ease;
}

.petlib-besoin-rayon:hover,
.petlib-besoin-rayon:focus-visible {
    background-color: var(--petlib-univers-color);
    color: #fff;
}

@media (prefers-reduced-motion: reduce) {
    .petlib-besoin-rayon {
        transition: none;
    }
}

/* Carrousel monté (besoins-slick-init.js, mobile uniquement) : Slick pose sa
   propre piste, le défilement natif et la largeur des diapositives n'ont plus
   lieu d'être. */
.petlib-besoins-univers-liste.slick-initialized {
    display: block;
    overflow: visible;

    /* Compense le padding des diapositives, pour que la première et la dernière
       restent alignées sur les bords de l'encart. */
    margin: 0 -6px;
    padding-bottom: 0;
}

/* flex: none — la piste de Slick est un conteneur flex (voir plus bas) et la base
   de 86% du défilement natif y survivrait : elle se calculerait alors sur la
   piste entière, soit trois fois la largeur de l'écran. C'est la largeur posée en
   ligne par Slick sur chaque diapositive qui doit gagner. */
.petlib-besoins-univers-liste.slick-initialized .petlib-besoin {
    flex: none;
    padding: 0 6px;
}

/* slick-theme.css sort la pagination du flux (position: absolute; bottom: -25px),
   où elle chevaucherait l'encart suivant. On la remet dans le flux. */
.petlib-besoins-univers-liste .slick-dots {
    position: static;
    margin-top: 12px;
}

.petlib-besoins-univers-liste .slick-dots li button::before {
    color: var(--petlib-univers-color);
}

/* Slick met les diapositives en float : sans hauteur commune, la carte ne peut
   pas s'étirer et le « height: 100% » ci-dessus n'aurait rien à quoi se
   rapporter. */
.petlib-besoins-univers-liste .slick-track {
    display: flex;
    align-items: stretch;
}

.petlib-besoins-univers-liste .slick-slide {
    height: auto;
}

@media (min-width: 768px) {
    .petlib-besoins-univers-titre {
        margin-bottom: 24px;
        font-size: 2.25rem;
    }

    /* Le carrousel est démonté à cette largeur : la grille reprend la main. */
    .petlib-besoins-univers-liste {
        display: grid;
        grid-template-columns: repeat(3, 1fr);
        gap: 24px;
        overflow: visible;

        padding-bottom: 0;
    }

    .petlib-besoin {
        flex: none;
    }
}

/*    PAGE D'UNIVERS - ENGAGEMENTS     */

.petlib-engagements-univers-titre {
    margin-bottom: 16px;
    color: var(--petlib-univers-color);
    font-size: 1.75rem;
    line-height: 1.2;
}

/* Le composant de réassurance pose sa marge haute et son filet de séparation :
   ils servent quand il ferme une fiche produit, pas sous un titre d'encart, où
   ils ouvriraient un trait entre le titre et ses vignettes. Le rythme vertical de
   la page est déjà tenu par la marge commune des sections. */
.petlib-engagements-univers .petlib-reassurance {
    margin-top: 0;
    padding-top: 0;
    border-top: 0;
}

@media (min-width: 768px) {
    .petlib-engagements-univers-titre {
        margin-bottom: 24px;
        font-size: 2.25rem;
    }
}

@media (min-width: 992px) {
    .petlib-engagements-univers .petlib-reassurance {
        padding-top: 0;
    }
}

/*    PAGE D'UNIVERS - INCONTOURNABLES ET NOUVEAUTES     */

/* Les deux encarts partagent leur grille de cartes — elle vient de
   « body.petlib-categorie ul.products » — et leur badge. Ils ne déclarent ici que
   leur titre. */
.petlib-incontournables-univers-titre,
.petlib-nouveautes-univers-titre {
    margin-bottom: 16px;
    color: var(--petlib-univers-color);
    font-size: 1.75rem;
    line-height: 1.2;
}

/* Badge posé sur la vignette. Le lien de la carte est le seul élément positionné
   de la carte — il l'est déjà pour l'image de survol — et la vignette en est le
   premier enfant : s'y caler revient à se caler sur elle.

   z-index parce que cette image de survol est elle aussi en absolu et passerait
   devant le badge sans lui.

   Style Label du référentiel : Inter 700, 0,8125rem, capitales, interlettrage
   0,04em — à cette taille, des capitales sans interlettrage se referment. Les
   capitales viennent du CSS et non du balisage, pour les lecteurs d'écran.

   Blanc sur la couleur d'univers, soit 9,5:1 pour le bleu du chien, très au-delà
   du plancher de 4,5:1 que le thème tient. Pastille et non coin de commande :
   le badge n'est pas une commande, il ne se clique pas.

   Un seul composant pour « Sélection » et « Nouveau » : les deux encarts sont à
   plusieurs écrans l'un de l'autre, c'est le mot qui les distingue. Deux
   traitements colorés auraient introduit une teinte de plus sans rien dire de
   plus. */
.petlib-badge-carte {
    position: absolute;
    top: 8px;
    left: 8px;
    z-index: 1;

    padding: 4px 10px;

    background-color: var(--petlib-univers-color);
    border-radius: 999px;
    color: #fff;
    font-size: 0.8125rem;
    font-weight: 700;
    letter-spacing: .04em;
    line-height: 1.3;
    text-transform: uppercase;
    white-space: nowrap;
}

@media (min-width: 768px) {
    .petlib-incontournables-univers-titre,
    .petlib-nouveautes-univers-titre {
        font-size: 2.25rem;
    }
}

/*    PAGE D'UNIVERS - VISAGE LISTE     */

/* Les rayons au-dessus de la liste. La pastille elle-même est celle du bloc
   éditorial, déclarée plus bas : ici seulement la disposition et le rythme.
   Le nav est titré par aria-label plutôt que par un intitulé visible : la ligne
   de pastilles se comprend d'un regard, un « Rayons » au-dessus n'aurait informé
   que les outils qui ne la voient pas. */
.petlib-rayons-univers {
    margin: 24px 0;
}

.petlib-rayons-univers-liste {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;

    margin: 0;
    padding: 0;

    list-style: none;
}

@media (min-width: 768px) {
    .petlib-rayons-univers {
        margin: 32px 0 24px;
    }

    .petlib-rayons-univers-liste {
        gap: 12px;
    }
}

/*    PAGE D'UNIVERS - BLOC EDITORIAL     */

/* Du texte, pas une carte : ni fond blanc, ni bordure, ni ombre. L'encart se lit
   sur le crème de la page comme le reste ; c'est la photo qui lui donne son poids.
   Titre aux mêmes valeurs que les six autres titres d'encart — ils ouvrent tous le
   même niveau, ils ont la même voix. */
.petlib-editorial-univers-titre {
    margin: 0 0 16px;
    color: var(--petlib-univers-color);
    font-size: 1.75rem;
    line-height: 1.2;
}

/* L'accroche porte le propos, elle est donc au-dessus du texte courant sans
   monter jusqu'au titre : c'est la valeur d'accroche du référentiel.
   Sa marge basse est la plus courte de l'encart — plus courte que celle qui la
   sépare du titre : les pastilles ne sont pas un bloc de plus dans une liste
   régulière, elles concluent l'accroche. C'est la proximité qui le dit, aucun
   libellé n'a à l'annoncer. */
.petlib-editorial-univers-intro {
    margin: 0 0 12px;
    font-size: 1.0625rem;
    line-height: 1.6;
}

/* Le dernier paragraphe ne pousse pas l'écart entre deux encarts : celui-ci est
   déclaré une seule fois sur « .petlib-univers-racine main > section ». */
.petlib-editorial-univers-final {
    margin: 0;
    line-height: 1.6;
}

/* Les rayons en pastilles plutôt qu'en liens dans le texte : le maillage reste
   entier mais se lit comme une entrée de rayon, pas comme du remplissage. */
.petlib-editorial-univers-rayons {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;

    /* 12px au-dessus, 32px en dessous : le groupe accroche + pastilles se ferme
       ici, et le dernier paragraphe repart. */
    margin: 0 0 32px;
    padding: 0;

    list-style: none;
}

/* Aplat clair de l'univers et texte à sa couleur, comme la carte de catégorie :
   6,6:1 pour le bleu du chien sur sa brume, au-delà du plancher de 4,5:1 que le
   thème tient. Au survol la pastille se remplit — blanc sur la couleur pleine,
   9,5:1 — et c'est le seul mouvement de l'encart.
   Pastille et non coin de commande : ces liens explorent, ils n'achètent pas.
   inline-flex et min-height plutôt qu'un rembourrage vertical : quatre cibles
   côte à côte en mobile méritent les 44px d'une cible tactile confortable, que
   les 6px du menu d'univers n'atteignent pas. */
.petlib-rayon-pastille {
    display: inline-flex;
    align-items: center;
    min-height: 44px;
    padding: 0 20px;

    background-color: var(--petlib-univers-primary-color);
    border-radius: 999px;
    color: var(--petlib-univers-color);
    font-size: 0.8125rem;
    font-weight: 700;
    letter-spacing: .04em;
    line-height: 1.3;
    text-decoration: none;
    text-transform: uppercase;

    transition: background-color .2s ease, color .2s ease;
}

.petlib-rayon-pastille:hover,
.petlib-rayon-pastille:focus {
    background-color: var(--petlib-univers-color);
    color: #fff;
}

@media (prefers-reduced-motion: reduce) {
    .petlib-rayon-pastille {
        transition: none;
    }
}

/* En mobile la photo s'intercale entre les pastilles et le dernier paragraphe, et
   c'est l'ordre du balisage qui la place : aucune règle ici.
   24px de rayon, au-delà des 12px d'un contenant ordinaire et des 16px du hero :
   c'est le seul objet purement visuel de la page, sans contenu à border, et la
   rondeur y prolonge le langage des cartes sans les copier. Vérifié sur la hauteur
   réelle — 240px en mobile, 480px et plus en desktop — bien loin de l'écrêtage à
   la moitié de la hauteur. */
.petlib-editorial-univers-image {
    margin: 0 0 24px;
    overflow: hidden;

    border-radius: 24px;
}

/* GeneratePress impose « height: auto » à toute image des pages WooCommerce via
   « .woocommerce img ». Ce sélecteur est à égalité de spécificité et l'emporte
   par l'ordre de chargement, la feuille enfant venant après celle du parent. */
.petlib-editorial-univers .petlib-editorial-univers-image img {
    display: block;
    width: 100%;
    height: 240px;

    object-fit: cover;
}

@media (min-width: 768px) {
    /* 60 % de contenu, 40 % d'image. Placement par la grille et non par « order »
       ni par l'ordre du balisage : celui-ci doit garder la photo entre les
       pastilles et le dernier paragraphe, c'est sa place en mobile.

       Six rangées pour quatre éléments : les quatre du milieu sont en « auto »,
       la première et la dernière sont des rangées vides en « 1fr ». La photo
       enjambe les six et réclame sa propre hauteur, que ces deux rangées souples
       absorbent à parts égales — le texte se retrouve centré en face d'elle,
       plutôt que tassé en haut avec un vide sous le dernier paragraphe. Sans ces
       rangées, la grille répartirait l'excédent sur les quatre rangées de contenu
       et écarterait le titre de son accroche. */
    .petlib-editorial-univers {
        display: grid;
        grid-template-columns: 3fr 2fr;
        grid-template-rows: 1fr auto auto auto auto 1fr;
        column-gap: 40px;
    }

    .petlib-editorial-univers-titre {
        grid-column: 1;
        grid-row: 2;

        font-size: 2.25rem;
    }

    .petlib-editorial-univers-intro {
        grid-column: 1;
        grid-row: 3;

        font-size: 1.1875rem;
    }

    .petlib-editorial-univers-rayons {
        grid-column: 1;
        grid-row: 4;

        gap: 12px;
        margin-bottom: 0;
    }

    /* Le pendant desktop du 12/32 du mobile : la marge basse des pastilles est
       neutralisée — en grille elle s'ajouterait à ce rembourrage au lieu de s'y
       fondre — et c'est lui seul qui ouvre l'espace après le groupe. */
    .petlib-editorial-univers-final {
        grid-column: 1;
        grid-row: 5;

        padding-top: 32px;
    }

    /* Au plus large la colonne atteint 70 % de 1400px, soit près de 120
       caractères par ligne — bien au-delà de ce qu'un œil suit sans se perdre en
       fin de ligne. Le texte est donc plafonné, et la colonne garde sa part de la
       grille : l'espace gagné revient à la gouttière, qui sépare d'autant mieux le
       texte de la photo. Le plafond ne mord qu'à partir de 1230px environ ; en
       dessous le texte remplit sa colonne.
       46rem mesuré à 84 caractères sur le paragraphe courant et 63 sur
       l'accroche, plus large que la fourchette classique de 45 à 75 : c'est un
       arbitrage assumé pour un paragraphe de clôture de quatre lignes.
       En rem et non en em : les deux paragraphes n'ont pas la même taille de
       police, et une mesure relative à la leur les aurait terminés à des largeurs
       différentes — le bord droit du bloc se serait mis à onduler. */
    .petlib-editorial-univers-intro,
    .petlib-editorial-univers-final {
        max-width: 46rem;
    }

    /* Carrée, et c'est elle qui donne sa hauteur à la colonne : le texte est trop
       court pour la commander sans l'étirer. « align-self: start » l'empêche de se
       déformer si le texte venait à la dépasser. */
    .petlib-editorial-univers-image {
        grid-column: 2;
        grid-row: 1 / -1;
        align-self: start;
        aspect-ratio: 1 / 1;

        margin: 0;
    }

    .petlib-editorial-univers .petlib-editorial-univers-image img {
        height: 100%;
    }
}

/* Troisième palier du thème, et le seul de cet encart : la photo est carrée et
   ne fait donc que 30 % de la largeur en hauteur aussi. À 70/30 dès 768px elle
   tombait à 207px — une vignette à côté d'un titre, plus une illustration. Le
   60/40 lui garde 265px minimum jusqu'à 1100px, largeur à partir de laquelle
   30 % valent enfin plus de 300px et la colonne de texte peut s'élargir sans
   l'écraser.

   1100 et non 992, le palier que le thème emploie déjà pour la quatrième colonne
   des grilles : à 992px, 30 % ne donnent encore que 278px, soit le défaut qu'on
   cherche justement à corriger. */
@media (min-width: 1100px) {
    .petlib-editorial-univers {
        grid-template-columns: 7fr 3fr;
    }
}

/*    PAGE D'UNIVERS - FAQ     */

/* L'accordéon est celui de la fiche produit et arrive tel quel. Son titre, lui,
   n'arrive pas : toute la mise en forme de « petlib-faq » est scopée
   « .petlib-produit », si bien qu'ici le titre retombait sur le noir et la taille
   par défaut de GeneratePress, au milieu de six titres d'encart bleus. On lui
   redonne les valeurs des autres — c'est le même niveau, c'est la même voix. */
.petlib-faq-univers .petlib-faq-titre {
    margin: 0 0 16px;
    color: var(--petlib-univers-color);
    font-size: 1.75rem;
    line-height: 1.2;
}

@media (min-width: 768px) {
    .petlib-faq-univers .petlib-faq-titre {
        margin-bottom: 24px;
        font-size: 2.25rem;
    }
}

/*    FICHE PRODUIT - UNIVERS     */

/* Seules règles propres à un univers de toute la fiche produit : elles ne font
   qu'alimenter deux variables. Toute la mise en forme qui suit est scopée à
   .petlib-produit et lit ces variables, si bien qu'un univers n'a rien d'autre
   à déclarer que ses deux couleurs. */
.petlib-produit-chat {
    --petlib-univers-color: var(--petlib-chat-secondary);
    --petlib-univers-primary-color: var(--petlib-chat-primary);
}

.petlib-produit-chien {
    --petlib-univers-color: var(--petlib-chien-secondary);
    --petlib-univers-primary-color: var(--petlib-chien-primary);
}

.petlib-produit-nac {
    --petlib-univers-color: var(--petlib-nac-secondary);
    --petlib-univers-primary-color: var(--petlib-nac-primary);
}

.petlib-produit .product_title {
    color: var(--petlib-univers-color);
}

/* Prix en noir, comme celui des variations plus bas : le montant se lit d'abord,
   la couleur d'univers reste au titre.
   Spécificité (0,4,1) pour passer devant woocommerce.css, dont le
   « .woocommerce:where(…) div.product p.price » pèse (0,3,2) — le :where() ne
   comptant pas — et impose sinon son olive #958e09. */
.petlib-produit .product .summary p.price {
    color: #000;
}

/* Mobile first : GeneratePress impose h1 { font-size: 42px } sans jamais le
   réduire en mobile, ce qui fait un titre produit sur 3 ou 4 lignes. On part
   donc de la taille mobile, agrandie à partir de la tablette (breakpoint md
   de Bootstrap, 768px). */
.petlib-produit .product_title {
    margin-bottom: 12px;
    font-size: 1.5rem;
    line-height: 1.25;
}

@media (min-width: 768px) {
    .petlib-produit .product_title {
        margin-bottom: 20px;
        font-size: 2rem;
    }
}

/*    FICHE PRODUIT CHIEN - MISE EN PAGE     */

/* WooCommerce met la galerie en float:left et le résumé en float:right, et
   comptait sur le « clear: both » du bloc d'onglets pour les contenir. Ces
   onglets étant retirés au profit de l'accordéon, plus rien ne les clôt :
   div.product retombait à 0 de hauteur et le fond blanc de .inside-article
   disparaissait, laissant voir le gris du body.
   flow-root crée un contexte de formatage de bloc, donc contient les flottants
   sans rogner quoi que ce soit — contrairement à overflow: hidden.
   « div.product » partout dans ce bloc : les cartes des produits similaires
   sont des li.product et reprennent le design de la catégorie, elles ne doivent
   rien recevoir de la mise en page de la fiche. */
.petlib-produit div.product {
    display: flow-root;
}

@media (min-width: 768px) {
    /* Colonnes en flex plutôt qu'en float : position: sticky ne s'applique pas
       de façon fiable à un élément flottant.
       align-items: flex-start est indispensable — en « stretch » (le défaut),
       la galerie prendrait toute la hauteur de la ligne et n'aurait plus aucune
       course pour glisser.
       Le flex contient ses enfants, il remplace donc aussi le flow-root
       ci-dessus, posé à l'origine pour éviter l'effondrement du conteneur. */
    .petlib-produit div.product {
        display: flex;
        flex-wrap: wrap;
        align-items: flex-start;
        justify-content: space-between;
    }

    /* Filet de sécurité : woocommerce_after_single_product_summary se déclenche
       à l'intérieur de div.product. Tout bloc qu'une extension y accrocherait
       deviendrait une troisième colonne et écraserait les deux autres — c'est
       ce qui est arrivé aux produits similaires. Ces enfants-là passent donc
       sur une ligne entière plutôt que de voler de la largeur.
       « div.product » et non « .product » : les cartes des produits similaires
       sont des li.product, elles aussi en flex depuis qu'elles reprennent le
       design de la catégorie. Sans cette précision, leur bouton héritait d'un
       flex-basis: 100% qui, dans une colonne, lui donnait la hauteur de la
       carte entière. */
    .petlib-produit div.product > :not(.woocommerce-product-gallery):not(.summary) {
        flex-basis: 100%;
    }

    /* Les float de WooCommerce sur ces deux colonnes ne sont pas neutralisés :
       la spec veut qu'ils soient ignorés sur un élément flex, et c'est bien ce
       qu'on observe ici.
       Sélecteur allongé à dessein : woocommerce.css pose la position via
       « .woocommerce div.product div.images », de spécificité (0,3,2). On monte
       à (0,4,2) en réutilisant .images, que WooCommerce met lui-même sur ce
       bloc — sans ça, le sticky ne s'applique pas.
       La galerie accompagne le défilement puis se libère en bas de la colonne
       droite, la course étant bornée par la hauteur du conteneur flex. */
    .petlib-produit div.product > div.images.woocommerce-product-gallery {
        position: sticky;
        top: 20px;
    }
}

/*    FICHE PRODUIT CHIEN - ENCART GARANTIE     */

.petlib-produit .petlib-encart-garantie {
    display: block;

    margin: 0 0 12px;
    padding: 5px 12px;

    color: var(--petlib-univers-color);
    font-size: 0.8125rem;
    font-style: italic;
    line-height: 1.3;
    text-align: center;

    background-color: #fff;
    border-radius: 6px;
}

@media (min-width: 768px) {
    .petlib-produit .petlib-encart-garantie {
        font-size: 0.875rem;
    }
}

/*    FICHE PRODUIT CHIEN - BULLET POINTS     */

/* Rendu en pastilles alignées, pas en liste à puces : le <ul> ne sert plus
   qu'à porter le sens (une liste de caractéristiques), toute l'apparence de
   liste est retirée. */
.petlib-produit .petlib-produit-bullets {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;

    margin: 0 0 20px;
    padding: 0;

    list-style: none;
}

.petlib-produit .petlib-produit-bullets li {
    display: flex;
    align-items: center;
    gap: 6px;

    padding: 6px 14px;

    color: #fff;
    font-size: 0.875rem;
    line-height: 1.3;

    background-color: var(--petlib-univers-color);
    border-radius: 999px;
}

.petlib-produit .petlib-produit-bullets .bi {
    font-size: 1.05em;
    line-height: 1;
}

/* Animation réservée aux appareils à vrai survol : sur tactile, :hover reste
   « collé » après un appui et la pastille resterait soulevée. */
@media (hover: hover) {
    .petlib-produit .petlib-produit-bullets li,
    .petlib-produit .petlib-produit-bullets .bi {
        transition: transform .2s ease, box-shadow .2s ease;
    }

    .petlib-produit .petlib-produit-bullets li:hover {
        transform: translateY(-2px);
        box-shadow: 0 4px 10px rgba(0, 0, 0, .18);
    }

    .petlib-produit .petlib-produit-bullets li:hover .bi {
        transform: scale(1.15);
    }
}

@media (prefers-reduced-motion: reduce) {
    .petlib-produit .petlib-produit-bullets li,
    .petlib-produit .petlib-produit-bullets .bi {
        transition: none;
    }

    .petlib-produit .petlib-produit-bullets li:hover,
    .petlib-produit .petlib-produit-bullets li:hover .bi {
        transform: none;
    }
}

@media (min-width: 768px) {
    .petlib-produit .petlib-produit-bullets li {
        font-size: 0.75rem;
    }
}

/*    CONTENEUR GENERATEPRESS - PRODUIT ET CATEGORIE     */

/* Ces deux blocs sont des ancêtres du contenu : impossible de les cibler depuis
   .petlib-produit ni depuis le template de catégorie. On passe donc par des
   classes de body — « single-product » posée par WordPress, « petlib-categorie »
   par petlib_body_class_categorie().
   Les racines d'univers gardent le fond blanc et la marge d'origine, d'où le
   :not() : elles portent « petlib-categorie » depuis que leur encart produits
   existe, mais uniquement pour hériter de la grille de cartes — pas de ce
   traitement de conteneur, qui appartient aux sous-catégories. */
.single-product .inside-article,
.petlib-categorie:not(.petlib-univers-racine) .inside-article,
.woocommerce-cart .inside-article,
.woocommerce-checkout .inside-article,
.woocommerce-account .inside-article {
    background-color: transparent;
}

.single-product .entry-content,
.petlib-categorie:not(.petlib-univers-racine) .entry-content,
.woocommerce-cart .entry-content,
.woocommerce-checkout .entry-content,
.woocommerce-account .entry-content {
    margin-top: 0;
}

/*    PANIER     */

/* Le panier est rendu par le shortcode [woocommerce_cart], donc par les
   templates PHP de WooCommerce : tout ce qui suit s'applique à un balisage
   stable, contrairement aux classes du bloc React. */

/* Tableau et totaux deviennent deux cartes, comme partout ailleurs sur le site.
   Le fond crème de la page les détache, ce que le fond blanc d'origine de
   .inside-article empêchait. */
.woocommerce-cart .woocommerce-cart-form,
.woocommerce-cart .cart-collaterals .cart_totals {
    padding: 20px;

    background-color: #fff;
    border: 1px solid #ECE6DD;
    border-radius: 12px;
    box-shadow: 0 2px 8px rgba(0, 0, 0, .04);
}

.woocommerce-cart .shop_table,
.woocommerce-cart .shop_table td,
.woocommerce-cart .shop_table th {
    border: 0;
}

.woocommerce-cart .shop_table thead th {
    padding-bottom: 12px;

    border-bottom: 1px solid #ECE6DD;
    font-size: 0.8125rem;
    letter-spacing: .03em;
    text-transform: uppercase;
}

.woocommerce-cart .shop_table .cart_item td {
    padding: 16px 12px;
    border-bottom: 1px solid #F2EDE5;
}

.woocommerce-cart .shop_table .product-thumbnail img {
    width: 72px;
    border-radius: 8px;
}

.woocommerce-cart .shop_table .product-name > a {
    font-weight: 700;
}

/* Variantes sous le titre. WooCommerce les sort en <dl> : on remet le terme et
   sa valeur sur une même ligne, le rendu par défaut les empilant. */
.woocommerce-cart .shop_table .product-name dl.variation {
    display: flex;
    flex-wrap: wrap;
    gap: 2px 6px;

    margin: 6px 0 0;

    color: var(--petlib-encre-douce);
    font-size: 0.8125rem;
}

.woocommerce-cart .shop_table .product-name dl.variation dt,
.woocommerce-cart .shop_table .product-name dl.variation dd {
    margin: 0;
    padding: 0;
    font-weight: 400;
}

/* WooCommerce enveloppe chaque valeur dans un <p> qui casserait la ligne. */
.woocommerce-cart .shop_table .product-name dl.variation dd p {
    margin: 0;
}

/* Séparateur entre deux variantes, sauf avant la première. */
.woocommerce-cart .shop_table .product-name dl.variation dt:not(:first-of-type)::before {
    content: "·";
    margin-right: 6px;
    color: #bbb;
}

.woocommerce-cart .cart_totals h2 {
    margin-bottom: 16px;
    font-size: 1.125rem;
}

/* « TTC » est une mention, pas une partie du montant : allégée pour que le
   chiffre reste ce qu'on lit en premier. */
.petlib-mention-ttc {
    color: var(--petlib-encre-douce);
    font-size: 0.8125rem;
    font-weight: 400;
}

/* Bouton de commande : mêmes valeurs que l'ajout au panier de la fiche produit
   — dégradé sombre, texte blanc, bordure noire — pour que l'action principale
   du site ait toujours la même apparence.
   L'animation élastique n'est pas reprise : elle sert à attirer l'œil sur une
   fiche produit, là où le bouton est déjà l'évidence de la page. */
.woocommerce-cart .wc-proceed-to-checkout a.checkout-button {
    display: block;
    padding: 14px 20px;

    background: linear-gradient(
            135deg,
            #404040 0%,
            #2D2D2D 45%,
            #1F1F1F 100%
    );
    border: 1px solid #000;
    border-radius: 8px;
    color: #FFF;
    font-size: 1rem;
    font-weight: 700;
    text-align: center;
}

.woocommerce-cart .wc-proceed-to-checkout a.checkout-button:hover {
    color: #FFF;
    filter: brightness(.96);
}

/* « Mettre à jour le panier » est une action secondaire : elle ne doit pas
   rivaliser visuellement avec la validation de commande. */
.woocommerce-cart .shop_table button[name="update_cart"] {
    background-color: transparent;
    border: 1px solid #d9d9d9;
    border-radius: 8px;
    color: #111;
    font-size: 0.875rem;
    font-weight: 400;
}

.woocommerce-cart .shop_table button[name="update_cart"]:hover:not(:disabled) {
    background-color: #fff;
    border-color: #111;
    color: #111;
}

/* Les moyens de paiement sont centrés sous le bouton, et le bandeau de
   réassurance occupe toute la largeur sous les deux colonnes. */
.woocommerce-cart .cart_totals .petlib-moyens-paiement {
    justify-content: center;
    margin-top: 16px;
}

.woocommerce-cart .petlib-reassurance {
    clear: both;
}

/*    MON COMPTE     */

/* Deux colonnes : navigation à gauche, contenu à droite. WooCommerce les sort
   en flottants ; la grille évite d'avoir à les clore. */
@media (min-width: 768px) {
    /* :has() est indispensable ici : le même conteneur .woocommerce sert au
       tableau de bord et au formulaire de connexion. Sans cette condition, la
       grille s'appliquait aussi à la page de connexion et renvoyait son titre
       dans la colonne de navigation. */
    .woocommerce-account .woocommerce:has(.woocommerce-MyAccount-navigation) {
        display: grid;
        grid-template-columns: 240px 1fr;
        gap: 24px;
        align-items: start;
    }

    /* Placement explicite plutôt que le placement automatique : celui-ci
       renvoyait la navigation en seconde colonne et sur une autre ligne, les
       flottants de woocommerce.css interférant avec l'ordre de placement. */
    .woocommerce-account .woocommerce-MyAccount-navigation {
        grid-column: 1;
        grid-row: 1;
    }

    .woocommerce-account .woocommerce-MyAccount-content {
        grid-column: 2;
        grid-row: 1;
    }
}

.woocommerce-account .woocommerce-MyAccount-navigation,
.woocommerce-account .woocommerce-MyAccount-content {
    float: none;
    width: auto;

    background-color: #fff;
    border: 1px solid #ECE6DD;
    border-radius: 12px;
    box-shadow: 0 2px 8px rgba(0, 0, 0, .04);
}

.woocommerce-account .woocommerce-MyAccount-navigation {
    padding: 8px;
}

.woocommerce-account .woocommerce-MyAccount-content {
    padding: 24px;
}

/* La navigation était une liste à puces : elle devient une pile de lignes
   cliquables sur toute la largeur, plus facile à viser. */
.woocommerce-account .woocommerce-MyAccount-navigation ul {
    margin: 0;
    padding: 0;
    list-style: none;
}

.woocommerce-account .woocommerce-MyAccount-navigation li a {
    display: block;
    padding: 10px 12px;

    border-radius: 8px;
    color: #111;
    font-size: 0.9375rem;
    text-decoration: none;
}

.woocommerce-account .woocommerce-MyAccount-navigation li a:hover {
    background-color: #F8F4EE;
}

.woocommerce-account .woocommerce-MyAccount-navigation li.is-active a {
    background-color: #4A4340;
    color: #fff;
    font-weight: 700;
}

/* « Se déconnecter » est une sortie, pas une rubrique : elle est détachée du
   reste par un filet et allégée. */
.woocommerce-account .woocommerce-MyAccount-navigation li--customer-logout {
    margin-top: 8px;
    padding-top: 8px;
    border-top: 1px solid #F2EDE5;
}

.woocommerce-account .woocommerce-MyAccount-navigation li--customer-logout a {
    color: var(--petlib-encre-douce);
}

/* Les formulaires eux-mêmes deviennent les cartes, et non leurs colonnes :
   l'inscription étant désactivée, WooCommerce n'émet pas le conteneur
   #customer_login. Cibler les formulaires fonctionne dans les deux cas.
   WooCommerce leur pose déjà une bordure grise et un rayon de 5px, qu'on
   remplace ici par ceux du site. */
.woocommerce-account form.woocommerce-form-login,
.woocommerce-account form.woocommerce-form-register {
    max-width: 520px;
    margin: 0;
    padding: 24px;

    background-color: #fff;
    border: 1px solid #ECE6DD;
    border-radius: 12px;
    box-shadow: 0 2px 8px rgba(0, 0, 0, .04);
}

.woocommerce-account #customer_login h2,
.woocommerce-account .woocommerce > h2 {
    margin-bottom: 16px;
    font-size: 1.25rem;
}

.woocommerce-account .woocommerce-form-login input.input-text,
.woocommerce-account .woocommerce-form-register input.input-text,
.woocommerce-account .woocommerce-EditAccountForm input.input-text,
.woocommerce-account .woocommerce-address-fields input.input-text {
    width: 100%;
    padding: 10px 14px;

    background-color: #fff;
    border: 1px solid #d9d9d9;
    border-radius: 8px;
    font-size: 0.9375rem;
}

.woocommerce-account .form-row label {
    display: block;
    margin-bottom: 6px;
    font-size: 0.8125rem;
    font-weight: 700;
}

/* Boutons d'action : même dégradé sombre que l'ajout au panier et la commande. */
.woocommerce-account .woocommerce-form-login button.woocommerce-form-login__submit,
.woocommerce-account .woocommerce-form-register button.woocommerce-form-register__submit,
.woocommerce-account .woocommerce-EditAccountForm button.woocommerce-Button,
.woocommerce-account .woocommerce-address-fields button.button {
    padding: 12px 22px;

    background: linear-gradient(
            135deg,
            #404040 0%,
            #2D2D2D 45%,
            #1F1F1F 100%
    );
    border: 1px solid #000;
    border-radius: 8px;
    color: #FFF;
    font-size: 0.9375rem;
    font-weight: 700;
}

.woocommerce-account .woocommerce-form-login button:hover,
.woocommerce-account .woocommerce-form-register button:hover,
.woocommerce-account .woocommerce-EditAccountForm button:hover,
.woocommerce-account .woocommerce-address-fields button:hover {
    color: #FFF;
    filter: brightness(.96);
}

/*    COMMANDE     */

/* Coordonnées, récapitulatif et paiement deviennent des cartes, comme le panier
   et le reste du site. */
.woocommerce-checkout #customer_details .col-1,
.woocommerce-checkout #customer_details .col-2,
.woocommerce-checkout #order_review {
    padding: 20px;

    background-color: #fff;
    border: 1px solid #ECE6DD;
    border-radius: 12px;
    box-shadow: 0 2px 8px rgba(0, 0, 0, .04);
}

.woocommerce-checkout #customer_details h3,
.woocommerce-checkout #order_review_heading {
    margin-bottom: 16px;
    font-size: 1.125rem;
}

.woocommerce-checkout #order_review_heading {
    margin-top: 32px;
}

/* Champs de formulaire : bordure et rayon du site, plutôt que le rendu natif du
   navigateur qui varie d'un poste à l'autre. */
.woocommerce-checkout .woocommerce-input-wrapper input.input-text,
.woocommerce-checkout .woocommerce-input-wrapper textarea,
.woocommerce-checkout .select2-container .select2-selection--single {
    padding: 10px 14px;

    background-color: #fff;
    border: 1px solid #d9d9d9;
    border-radius: 8px;
    font-size: 0.9375rem;
}

/* La bordure qui fonce reste comme indice secondaire ; l'anneau de focus
   global s'en charge pour le clavier. Le « outline: none » qui était ici
   annulait le seul repère dont disposait un visiteur qui remplit ce
   formulaire sans souris. */
.woocommerce-checkout .woocommerce-input-wrapper input.input-text:focus,
.woocommerce-checkout .woocommerce-input-wrapper textarea:focus {
    border-color: #111;
}

.woocommerce-checkout .form-row label {
    display: block;
    margin-bottom: 6px;
    font-size: 0.8125rem;
    font-weight: 700;
}

/* Tableau du récapitulatif : mêmes règles que le panier, sans ses bordures. */
.woocommerce-checkout #order_review .shop_table,
.woocommerce-checkout #order_review .shop_table td,
.woocommerce-checkout #order_review .shop_table th {
    border: 0;
}

.woocommerce-checkout #order_review .shop_table tbody td,
.woocommerce-checkout #order_review .shop_table tfoot td,
.woocommerce-checkout #order_review .shop_table tfoot th {
    padding: 12px 8px;
    border-bottom: 1px solid #F2EDE5;
}

.woocommerce-checkout #order_review .shop_table .order-total td,
.woocommerce-checkout #order_review .shop_table .order-total th {
    border-bottom: 0;
    font-size: 1.0625rem;
}

/* Les variantes du récapitulatif reprennent le traitement du panier. */
.woocommerce-checkout #order_review .shop_table dl.variation {
    display: flex;
    flex-wrap: wrap;
    gap: 2px 6px;

    margin: 6px 0 0;

    color: var(--petlib-encre-douce);
    font-size: 0.8125rem;
}

.woocommerce-checkout #order_review .shop_table dl.variation dt,
.woocommerce-checkout #order_review .shop_table dl.variation dd {
    margin: 0;
    padding: 0;
    font-weight: 400;
}

.woocommerce-checkout #order_review .shop_table dl.variation dd p {
    margin: 0;
}

.woocommerce-checkout #payment {
    background-color: transparent;
    border-radius: 0;
}

.woocommerce-checkout #payment ul.payment_methods {
    padding: 0;
    border-bottom: 1px solid #F2EDE5;
}

/* Bouton de commande : mêmes valeurs que l'ajout au panier et que la validation
   du panier — l'action principale garde la même apparence de bout en bout. */
.woocommerce-checkout #payment #place_order {
    display: block;
    width: 100%;
    padding: 14px 20px;

    background: linear-gradient(
            135deg,
            #404040 0%,
            #2D2D2D 45%,
            #1F1F1F 100%
    );
    border: 1px solid #000;
    border-radius: 8px;
    color: #FFF;
    font-size: 1rem;
    font-weight: 700;
}

.woocommerce-checkout #payment #place_order:hover {
    color: #FFF;
    filter: brightness(.96);
}

/* Code promo : le champ tombait à 80px, trop court pour lire ce qu'on y saisit.
   Le bouton reprend le style secondaire de « Mettre à jour le panier ». */
.woocommerce-cart .coupon {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
}

.woocommerce-cart .coupon #coupon_code {
    width: auto;
    min-width: 180px;
    padding: 9px 14px;

    background-color: #fff;
    border: 1px solid #d9d9d9;
    border-radius: 8px;
    font-size: 0.875rem;
}

.woocommerce-cart .coupon button[name="apply_coupon"] {
    padding: 9px 16px;

    background-color: transparent;
    border: 1px solid #d9d9d9;
    border-radius: 8px;
    color: #111;
    font-size: 0.875rem;
    font-weight: 400;
}

.woocommerce-cart .coupon button[name="apply_coupon"]:hover {
    background-color: #fff;
    border-color: #111;
    color: #111;
}

/* La croix de suppression est un « × » typographique de 25px, sans zone de clic
   confortable. On la ramène à un bouton rond discret, atteignable au doigt. */
.woocommerce-cart .product-remove a.remove {
    display: flex;
    align-items: center;
    justify-content: center;

    width: 28px;
    height: 28px;

    background-color: #F2EDE5;
    border-radius: 50%;
    color: var(--petlib-encre-douce);
    font-size: 1.125rem;
    line-height: 1;
}

.woocommerce-cart .product-remove a.remove:hover {
    background-color: #111;
    color: #fff;
}

/*    CATEGORIE - BARRE D'OUTILS     */

/* Bouton de filtres, compteur et tri sur une ligne. Le tri est poussé à droite
   par la marge automatique, ce qui tient quel que soit le nombre d'éléments. */
.petlib-outils {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 12px 16px;

    margin-bottom: 16px;
}

.petlib-bouton-filtres {
    display: flex;
    align-items: center;
    gap: 8px;

    padding: 9px 16px;

    background-color: var(--petlib-univers-color, #111);
    border: 0;
    border-radius: 8px;
    color: #fff;
    font-size: 0.875rem;
    font-weight: 700;
}

/* GeneratePress colore tous les boutons au survol et au focus : sans cette
   neutralisation, le bouton perdrait la couleur de son univers. */
.petlib-bouton-filtres:hover,
.petlib-bouton-filtres:focus {
    background-color: var(--petlib-univers-color, #111);
    color: #fff;
    opacity: .9;
}

/* Le chevron suit l'état du collapse, que Bootstrap reflète dans la classe.
   Ce glyphe pointe vers le bas tel quel — vérifié dans le navigateur, les
   codepoints de Bootstrap Icons ayant bougé d'une version à l'autre. C'est donc
   l'état ouvert qui le retourne, pas l'état fermé. */
.petlib-bouton-filtres::after {
    content: "\f229";
    font-family: bootstrap-icons;
    font-size: .75em;
    line-height: 1;
    transition: transform .2s ease;
}

.petlib-bouton-filtres:not(.collapsed)::after {
    transform: rotate(180deg);
}

.petlib-bouton-filtres-compte {
    display: inline-flex;
    align-items: center;
    justify-content: center;

    min-width: 20px;
    height: 20px;
    padding: 0 6px;

    background-color: #fff;
    border-radius: 999px;
    color: var(--petlib-univers-color, #111);
    font-size: 0.75rem;
}

/* WooCommerce sort le compteur dans un <p> avec ses propres marges. */
.petlib-outils-compteur .woocommerce-result-count {
    margin: 0;
    color: var(--petlib-encre-douce);
    font-size: 0.875rem;
}

.petlib-outils-tri {
    margin-left: auto;
}

.petlib-outils-tri .woocommerce-ordering {
    margin: 0;
}

/* Le select natif est remplacé visuellement : apparence neutralisée, puis
   chevron dessiné en fond. Le padding droit lui réserve sa place. */
.petlib-outils-tri select.orderby {
    padding: 9px 38px 9px 14px;

    appearance: none;
    -webkit-appearance: none;
    background-color: #fff;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23111111'%3E%3Cpath d='M8 11.5 2.5 6h11z'/%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: right 14px center;
    background-size: 11px;
    border: 1px solid #ECE6DD;
    border-radius: 8px;
    box-shadow: 0 2px 8px rgba(0, 0, 0, .04);
    color: #111;
    font-size: 0.875rem;
}

.petlib-outils-tri select.orderby:focus {
    border-color: var(--petlib-univers-color, #111);
}

/*    CATEGORIE - FILTRES PAR ATTRIBUT     */

/* Les liens portent les paramètres « filter_* » natifs de WooCommerce : cette
   barre n'est qu'une interface, aucun moteur de filtrage n'est réimplémenté.
   Habillage accordé aux options de variation de la fiche produit, sans réutiliser
   leurs classes — celles-ci sont scopées à .petlib-produit et pilotées par un JS
   qui n'a pas lieu d'être ici. */
.petlib-filtres {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 12px 28px;

    margin-bottom: 24px;
    padding: 16px;

    box-shadow: 0 2px 8px rgba(0, 0, 0, .04);

    background-color: #fff;
    border: 1px solid #ECE6DD;
    border-radius: 12px;
}

.petlib-filtre {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 8px;
}

.petlib-filtre-libelle {
    font-size: 0.8125rem;
    font-weight: 700;
}

.petlib-filtre-options {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;

    margin: 0;
    padding: 0;

    list-style: none;
}

.petlib-filtre-options a {
    display: flex;
    align-items: center;

    color: inherit;
    text-decoration: none;
    transition: border-color .2s ease, background-color .2s ease;
}

/* Taille : cadres alignés, le terme actif prenant une bordure noire et un fond
   léger — même parti que sur la fiche produit. */
.petlib-filtre--taille .petlib-filtre-options a {
    padding: 5px 12px;

    background-color: var(--bs-primary);
    border: 1px solid #d9d9d9;
    border-radius: 6px;
    font-size: 0.8125rem;
}

.petlib-filtre--taille .petlib-filtre-options a:hover {
    border-color: #111;
}

.petlib-filtre--taille .petlib-filtre-options a.is-active {
    background-color: #ebebeb;
    border-color: #111;
    font-weight: 700;
}

/* Couleur : la pastille est le lien lui-même, l'anneau signale la sélection. */
.petlib-filtre-pastille {
    display: block;
    width: 24px;
    height: 24px;

    border: 1px solid rgba(0, 0, 0, .15);
    border-radius: 50%;
}

.petlib-filtre--couleur .petlib-filtre-options a {
    padding: 2px;
    border: 2px solid transparent;
    border-radius: 50%;
}

.petlib-filtre--couleur .petlib-filtre-options a:hover {
    border-color: #bbb;
}

.petlib-filtre--couleur .petlib-filtre-options a.is-active {
    border-color: var(--petlib-univers-color, #111);
}

.petlib-filtres-reset {
    display: flex;
    align-items: center;
    gap: 6px;

    margin-left: auto;

    color: var(--petlib-encre-douce);
    font-size: 0.8125rem;
    text-decoration: none;
}

.petlib-filtres-reset:hover {
    color: #111;
}

/*    CARTES PRODUIT - CATEGORIE ET PRODUITS SIMILAIRES     */

/* Grille plutôt que les flottants de WooCommerce : les cartes prennent alors
   toutes la hauteur de leur ligne, ce qui suffit à aligner les boutons.
   Mobile first — deux colonnes, puis trois et quatre.
   « body » dans le sélecteur porte la spécificité à (0,3,1), au-dessus du
   « .woocommerce ul.products li.product » de woocommerce.css : l'emporter ne
   dépend donc pas de l'ordre de chargement des feuilles.

   Le second sélecteur applique la même carte aux produits similaires de la
   fiche produit, seule autre liste .products du thème. « .related » n'y est pas
   décoratif : il porte la spécificité au-dessus de woocommerce.css, comme
   « body » le fait côté catégorie. */
body.petlib-categorie ul.products,
.petlib-produit .related ul.products {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    gap: 16px;

    margin: 0;
    padding: 0;
}

body.petlib-categorie ul.products::before,
body.petlib-categorie ul.products::after,
.petlib-produit .related ul.products::before,
.petlib-produit .related ul.products::after {
    display: none;
}

/* Les marges et la largeur en pourcentage de WooCommerce sont neutralisées :
   la grille s'en charge, les conserver décalerait les colonnes.

   « .woocommerce » ne sert qu'à la spécificité, et c'est ici qu'elle se joue :
   sous 769px, woocommerce-smallscreen.css impose
   « .woocommerce ul.products[class*="columns-"] li.product { width: 48% } »,
   soit (0,4,2) — au-dessus des (0,3,3) et (0,4,2) que ces deux sélecteurs
   pesaient. Ce pourcentage se calcule sur la cellule de grille et non sur la
   liste : chaque carte retombait à 48% de sa colonne — 66px de large sur un
   écran de 390px, image comprise et titre coupé mot à mot — avec les 2.992em
   de marge basse de WooCommerce en prime. La classe est posée sur le body par
   WooCommerce lui-même sur toutes ses pages, dont les archives de catégorie :
   elle est acquise partout où ces cartes existent. */
body.woocommerce.petlib-categorie ul.products li.product,
body.woocommerce .petlib-produit .related ul.products li.product,
/* L'accueil affiche les mêmes cartes mais n'est pas une page WooCommerce : la
   classe « woocommerce » n'y est pas posée, et l'habillage des cartes tombait.
   « petlib-accueil » la remplace au même poids de spécificité, (0,4,3). */
body.petlib-accueil.petlib-categorie ul.products li.product {
    display: flex;
    flex-direction: column;
    float: none;
    width: auto;
    margin: 0;

    background-color: #fff;
    border: 1px solid #ECE6DD;
    border-radius: 12px;
    box-shadow: 0 2px 8px rgba(0, 0, 0, .04);
    overflow: hidden;
    transition: box-shadow .2s ease, transform .2s ease;
}

body.petlib-categorie ul.products li.product:hover,
.petlib-produit .related ul.products li.product:hover {
    box-shadow: 0 6px 16px rgba(0, 0, 0, .08);
    transform: translateY(-2px);
}

/* Le lien enveloppe l'image, le titre et le prix. En colonne avec flex: 1, il
   occupe toute la hauteur restante et pousse le bouton en bas de carte.
   « position: relative » sert de repère à l'image de survol, posée en absolu
   plus bas : la vignette étant le premier élément de cette colonne, se caler
   sur le lien revient à se caler sur elle. */
body.petlib-categorie ul.products li.product a.woocommerce-loop-product__link,
.petlib-produit .related ul.products li.product a.woocommerce-loop-product__link {
    display: flex;
    flex: 1;
    flex-direction: column;
    position: relative;
}

body.petlib-categorie ul.products li.product img,
.petlib-produit .related ul.products li.product img {
    width: 100%;
    margin: 0;
    aspect-ratio: 1;
    object-fit: cover;
}

/* Seconde image de la galerie, superposée à la vignette et révélée au survol
   de la carte (voir petlib_image_survol_carte()).
   Elle est sortie du flux : sans cela elle s'empilerait sous la vignette et
   allongerait la carte. Les dimensions viennent de la règle « img » ci-dessus,
   seul le placement est repris ici.
   Spécificité (0,4,4) pour passer devant cette même règle, en (0,3,4). */
body.petlib-categorie ul.products li.product img.petlib-image-survol,
.petlib-produit .related ul.products li.product img.petlib-image-survol {
    position: absolute;
    top: 0;
    left: 0;

    opacity: 0;
    transition: opacity .3s ease;
}

body.petlib-categorie ul.products li.product:hover img.petlib-image-survol,
.petlib-produit .related ul.products li.product:hover img.petlib-image-survol {
    opacity: 1;
}

/* Au clavier comme au survol : sans cela l'effet serait réservé à la souris. */
body.petlib-categorie ul.products li.product a:focus-visible img.petlib-image-survol,
.petlib-produit .related ul.products li.product a:focus-visible img.petlib-image-survol {
    opacity: 1;
}

/* Un mouvement d'image reste une animation : on la coupe pour qui la refuse,
   la seconde image ne portant aucune information indispensable. */
@media (prefers-reduced-motion: reduce) {
    body.petlib-categorie ul.products li.product img.petlib-image-survol,
    .petlib-produit .related ul.products li.product img.petlib-image-survol {
        transition: none;
    }
}

/* Le titre est le seul élément extensible : c'est lui qui absorbe la différence
   de hauteur entre cartes, le prix restant collé au bouton. */
body.petlib-categorie ul.products li.product .woocommerce-loop-product__title,
.petlib-produit .related ul.products li.product .woocommerce-loop-product__title {
    flex: 1;
    padding: 12px 12px 4px;

    color: var(--petlib-univers-color, inherit);
    font-size: 0.875rem;
    line-height: 1.35;
}

body.petlib-categorie ul.products li.product .price,
.petlib-produit .related ul.products li.product .price {
    display: block;
    padding: 0 12px 12px;

    color: var(--petlib-univers-color, inherit);
    font-size: 0.9375rem;
    font-weight: 700;
}

/* « À partir de » est une mention, pas le prix : sans cet allègement les deux
   se disputent l'attention et le montant ne ressort plus. */
.petlib-prix-mention {
    color: var(--petlib-encre-douce);
    font-size: 0.8125rem;
    font-weight: 400;
}

/* Même apparence que l'ajout au panier de la fiche produit — dégradé sombre,
   texte blanc, bordure noire — pour que l'action principale du site se
   reconnaisse partout : fiche, carte et validation de commande.
   Comme pour le bouton de commande, ce sont l'habillage et le rayon du site qui
   sont repris, pas les dimensions : le 17px de la fiche dépasserait le titre de
   la carte, et son rayon de 3px n'est qu'un reliquat de GeneratePress.
   L'animation élastique n'est pas reprise non plus : elle sert à attirer l'œil
   sur une fiche, une grille entière qui pulse serait intenable. */
body.petlib-categorie ul.products li.product a.button,
.petlib-produit .related ul.products li.product a.button {
    display: block;
    margin: 0 12px 12px;
    padding: 10px 12px;

    background: linear-gradient(
            135deg,
            #404040 0%,
            #2D2D2D 45%,
            #1F1F1F 100%
    );
    border: 1px solid #000;
    border-radius: 8px;
    color: #FFF;
    font-size: 0.875rem;
    font-weight: 700;
    text-align: center;
    transition: filter .2s ease;
}

/* Le dégradé est une image de fond : elle couvrirait tout background-color posé
   ici. On assombrit donc par la luminosité, comme le bouton de la fiche — même
   bouton, même survol. */
body.petlib-categorie ul.products li.product a.button:hover,
.petlib-produit .related ul.products li.product a.button:hover {
    color: #FFF;
    filter: brightness(.75);
}

/* Le bandeau de réassurance, désormais juste au-dessus, n'espace que son propre
   dessus (margin: 32px 0 0) : sans cette marge le titre « Produits similaires »
   lui reste collé. Même valeur, pour un rythme constant entre les blocs. */
.petlib-produit .related {
    margin-top: 32px;
}

@media (min-width: 768px) {
    body.petlib-categorie ul.products,
    .petlib-produit .related ul.products {
        grid-template-columns: repeat(3, 1fr);
        gap: 20px;
    }

    body.petlib-categorie ul.products li.product .woocommerce-loop-product__title,
    .petlib-produit .related ul.products li.product .woocommerce-loop-product__title {
        font-size: 0.9375rem;
    }
}

@media (min-width: 992px) {
    body.petlib-categorie ul.products,
    .petlib-produit .related ul.products {
        grid-template-columns: repeat(4, 1fr);
        gap: 24px;
    }
}

/*    FICHE PRODUIT - AVIS     */

/* Premier bloc pleine largeur sous les deux colonnes. Le filet et les marges
   sont ceux du bandeau de réassurance : ces blocs se suivent, autant qu'ils se
   séparent de la même façon. */
.petlib-produit .petlib-avis {
    margin-top: 32px;
    padding-top: 24px;
    border-top: 1px solid rgba(0, 0, 0, .1);
}

/* L'encart : même recette de carte que les cartes produit — blanc, bordure
   crème, rayon de 12px. Sur la fiche, .inside-article est transparent et laisse
   voir le fond du site : c'est ce blanc qui détache le bloc.
   Largeur plafonnée et centré : sur toute la largeur du contenu, les lignes
   d'un avis deviendraient illisibles et le bloc écraserait le reste de la page.
   Le filet, lui, reste pleine largeur : c'est lui qui clôt les deux colonnes.
   En dessous de ce plafond la carte occupe naturellement toute la place, il n'y
   a donc rien à prévoir pour le mobile. */
.petlib-produit .woocommerce-Reviews {
    max-width: 720px;
    margin-right: auto;
    margin-left: auto;
    padding: 20px;

    background-color: #fff;
    border: 1px solid #ECE6DD;
    border-radius: 12px;
}

/* GeneratePress sort les h2 à 35px : à l'échelle d'un encart, c'est un titre de
   page posé dans une carte. */
.petlib-produit .woocommerce-Reviews-title {
    margin: 0 0 16px;

    color: var(--petlib-univers-color);
    font-size: 1.25rem;
    line-height: 1.3;
}

.petlib-produit .woocommerce-noreviews {
    margin: 0;
    color: var(--petlib-encre-douce);
    font-size: 0.9375rem;
}

/*    FICHE PRODUIT - AVIS : LISTE     */

/* Tous les sélecteurs de ce bloc passent par « #reviews #comments », et sont
   préfixés de « body ». Ce n'est pas une coquetterie : woocommerce.css habille
   la liste avec des sélecteurs à DEUX identifiants, du type
   « .woocommerce #reviews #comments ol.commentlist li .comment-text ». Aucune
   quantité de classes ne passe devant deux id — il faut les reprendre, et
   « body » fournit l'élément d'écart qui départage sans !important. */
.petlib-produit .woocommerce-Reviews .commentlist {
    margin: 0;
    padding: 0;
    list-style: none;
}

/* Un filet entre deux avis plutôt qu'un cadre autour de chacun : dans une carte
   qui a déjà sa bordure, encadrer chaque avis ferait boîte dans la boîte. */
body .petlib-produit #reviews #comments ol.commentlist li.review {
    margin: 0;
    padding: 16px 0;
    border-top: 1px solid #F2EDE5;
}

body .petlib-produit #reviews #comments ol.commentlist li.review:first-child {
    padding-top: 0;
    border-top: 0;
}

/* WooCommerce sort la vignette en position: absolue et décale le texte de 50px
   pour lui faire de la place. On repasse en flex : les deux colonnes se placent
   d'elles-mêmes, quelle que soit la taille de la vignette. */
body .petlib-produit #reviews #comments ol.commentlist li .comment_container {
    display: flex;
    align-items: flex-start;
    gap: 12px;

    padding: 0;

    background: none;
    border: 0;
    border-radius: 0;
}

body .petlib-produit #reviews #comments ol.commentlist li img.avatar {
    position: static;

    width: 40px;
    height: 40px;
    margin: 0;
    padding: 0;

    background: none;
    border: 0;
    border-radius: 50%;
    flex-shrink: 0;
}

/* min-width: 0 indispensable : sans lui, un élément flex refuse de descendre
   sous la largeur de son contenu et un avis d'un seul tenant déborderait. */
body .petlib-produit #reviews #comments ol.commentlist li .comment-text {
    flex: 1;
    min-width: 0;
    margin: 0;
    padding: 0;

    border: 0;
    border-radius: 0;
}

body .petlib-produit #reviews #comments ol.commentlist li .comment-text p.meta {
    margin: 0 0 6px;
    color: var(--petlib-encre-douce);
    font-size: 0.8125rem;
}

/* L'auteur porte l'information, la mention « client confirmé » et la date
   l'accompagnent : seul le premier passe en gras et en noir. */
body .petlib-produit #reviews #comments ol.commentlist li .comment-text p.meta strong {
    color: #111;
    font-size: 0.9375rem;
}

body .petlib-produit #reviews #comments ol.commentlist li .comment-text .description {
    font-size: 0.9375rem;
    line-height: 1.55;
}

body .petlib-produit #reviews #comments ol.commentlist li .comment-text .description p:last-child {
    margin-bottom: 0;
}

/*    FICHE PRODUIT - AVIS : FORMULAIRE     */

/* Séparé de ce qui précède par le même filet que les avis entre eux — qu'il
   s'agisse de la liste ou, quand elle est vide, du « il n'y a pas encore
   d'avis » : dans les deux cas le filet marque le passage à l'écriture. */
.petlib-produit .woocommerce-Reviews #review_form_wrapper {
    margin-top: 20px;
    padding-top: 20px;
    border-top: 1px solid #F2EDE5;
}

.petlib-produit .woocommerce-Reviews #reply-title {
    display: block;
    margin: 0 0 12px;

    font-size: 1rem;
    font-weight: 700;
}

.petlib-produit .woocommerce-Reviews .comment-form label {
    display: block;
    margin-bottom: 6px;
    font-size: 0.8125rem;
    font-weight: 700;
}

/* Mêmes valeurs que les champs de la commande, pour ne pas dépendre du rendu
   natif du navigateur, qui varie d'un poste à l'autre. */
.petlib-produit .woocommerce-Reviews .comment-form textarea {
    width: 100%;
    padding: 10px 14px;

    background-color: #fff;
    border: 1px solid #d9d9d9;
    border-radius: 8px;
    font-size: 0.9375rem;
}

.petlib-produit .woocommerce-Reviews .comment-form textarea:focus {
    border-color: #111;
}

/* Les étoiles de notation reprennent le doré de l'étoile de la barre de
   promotion : c'est déjà la couleur « avis » du site. */
.petlib-produit .woocommerce-Reviews .stars a {
    color: #f5b301;
}

.petlib-produit .woocommerce-Reviews .comment-form-rating {
    margin-bottom: 16px;
}

/* Action secondaire de la page — le bouton principal reste l'ajout au panier :
   couleur d'univers plutôt que le dégradé sombre, qui lui est réservé.
   Même raison qu'au-dessus pour le sélecteur : woocommerce.css colore ce bouton
   via « .woocommerce #respond input#submit », donc deux identifiants. */
body .petlib-produit #respond input#submit {
    padding: 10px 20px;

    background-color: var(--petlib-univers-color);
    border: 0;
    border-radius: 8px;
    color: #FFF;
    font-size: 0.875rem;
    font-weight: 700;
}

body .petlib-produit #respond input#submit:hover,
body .petlib-produit #respond input#submit:focus {
    background-color: var(--petlib-univers-color);
    color: #FFF;
    filter: brightness(1.15);
}

/*    FICHE PRODUIT - FAQ     */

/* Mobile first : le propos puis les questions, empilés. Les deux colonnes
   n'arrivent qu'à partir de la tablette, comme les blocs éditoriaux.
   La colonne des questions est la plus large : une question tient sur une
   ligne, un paragraphe d'introduction se lit mieux étroit. */
.petlib-produit .petlib-faq {
    display: grid;
    grid-template-columns: 1fr;
    gap: 24px;

    margin-top: 32px;
    padding-top: 24px;

    border-top: 1px solid rgba(0, 0, 0, .1);
}

@media (min-width: 768px) {
    .petlib-produit .petlib-faq {
        grid-template-columns: minmax(0, 1fr) minmax(0, 1.4fr);
        align-items: start;
        gap: 40px;
    }

    /* La colonne de gauche accompagne le défilement des questions : sur une FAQ
       longue, le rappel du service client reste sous les yeux. La course est
       bornée par la hauteur de la grille. */
    .petlib-produit .petlib-faq-intro {
        position: sticky;
        top: 20px;
    }
}

.petlib-produit .petlib-faq-titre {
    margin: 0 0 12px;

    color: var(--petlib-univers-color);
    font-size: 1.5rem;
    line-height: 1.2;
}

.petlib-produit .petlib-faq-texte {
    margin: 0 0 16px;
    font-size: 0.9375rem;
    line-height: 1.55;
}

/* Le rappel du service client est une aparté, pas la suite du texte : fond
   blanc et cadre fin le détachent sans en faire une carte de plus.
   Cadre complet de 1px et non plus filet latéral de 3px : l'accordéon FAQ
   juste en dessous est bordé de la même façon, deux langages de bordure dans
   une même section se voyaient. */
.petlib-produit .petlib-faq-aide {
    margin: 0;
    padding: 14px 16px;

    background-color: #fff;
    border: 1px solid var(--petlib-univers-color);
    border-radius: 12px;
    color: #555;
    font-size: 0.875rem;
    line-height: 1.5;
}

.petlib-produit .petlib-faq-aide strong {
    display: block;
    margin-bottom: 4px;
    color: #111;
}

/* L'accordéon reprend l'habillage de celui de la fiche — même chevron, mêmes
   filets, même couleur d'univers. Ne restent ici que les écarts : les questions
   n'ont pas d'icône, et la marge haute de 24px n'a pas lieu d'être, la grille
   pose déjà l'espacement. */
.petlib-produit .petlib-faq-accordeon {
    margin-top: 0;
}

/** guide des tailles accordeon **/


/* Base carte : classes communes avec guide-tailles-collier-lumineux.html */
.size-guide {
    max-width: 480px;
    background: #ffffff;
    border: 1px solid #e5e3dc;
    border-radius: 12px;
    font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Arial, sans-serif;
    box-sizing: border-box;
    overflow: hidden;
}
.size-guide * {
    box-sizing: border-box;
}
.size-guide .note {
    font-size: 12px;
    color: #8a8880;
}

/* Bannière (spécifique harnais) */
.size-guide-banner {
    background: #1b2a4a;
    color: #ffffff;
    padding: 24px 24px 20px;
}
.size-guide-banner h2 {
    margin: 0 0 6px;
    font-size: 22px;
    font-weight: 700;
    letter-spacing: 0.5px;
}
.size-guide-banner p {
    margin: 0;
    font-size: 13px;
    color: #c7cee0;
}

/* Tableau */
.size-guide-table {
    width: 100%;
    border-collapse: collapse;
}
.size-guide-table th {
    background: #1b2a4a;
    color: #ffffff;
    font-size: 11px;
    text-transform: uppercase;
    letter-spacing: 0.5px;
    padding: 12px 8px;
    text-align: center;
    font-weight: 600;
}
.size-guide-table td {
    padding: 14px 8px;
    text-align: center;
    font-size: 14px;
    color: #1a1a18;
    border-top: 1px solid #e5e3dc;
}
.size-guide-table tr:nth-child(even) td {
    background: #f7f6f2;
}
.size-badge {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 34px;
    height: 34px;
    border-radius: 50%;
    background: #1b2a4a;
    color: #ffffff;
    font-size: 13px;
    font-weight: 700;
}

/* Pied de carte : conseil */
.size-guide-footer {
    display: flex;
    align-items: center;
    gap: 10px;
    background: #1b2a4a;
    color: #ffffff;
    padding: 14px 20px;
    font-size: 13px;
}
.size-guide-footer svg {
    flex-shrink: 0;
}


/*    FICHE PRODUIT - APPARITION DES BLOCS AU DEFILEMENT     */

/* L'image monte en fondu quand elle entre à l'écran, une fois par visite.
   L'état de départ est scopé à « .petlib-apparition », classe que le script
   pose lui-même sur <html> : sans lui, la règle ne s'applique pas et les images
   restent visibles. C'est ce qui évite le pire des cas — du contenu resté
   invisible parce qu'un script n'a pas tourné.
   La classe .is-visible, elle, est posée sur chaque image par l'observateur. */
.petlib-apparition .petlib-produit .petlib-bloc-image {
    opacity: 0;
    transform: translateY(24px);
    transition: opacity .6s ease, transform .6s ease;
}

.petlib-apparition .petlib-produit .petlib-bloc-image.is-visible {
    opacity: 1;
    transform: none;
}

/* Le contenu reste accessible, seule l'animation disparaît. */
@media (prefers-reduced-motion: reduce) {
    .petlib-apparition .petlib-produit .petlib-bloc-image {
        opacity: 1;
        transform: none;
        transition: none;
    }
}

/*    FICHE PRODUIT CHIEN - BLOCS EDITORIAUX     */

/* Mobile first : image puis texte, empilés. Les deux colonnes n'arrivent qu'à
   partir de la tablette.
   L'espacement entre blocs vient de cette marge et non d'un gap sur le
   conteneur : les deux se seraient additionnés. Le conteneur reste donc en flux
   normal, où les marges verticales de deux blocs voisins fusionnent — l'écart
   entre blocs vaut donc 50px, pas 100. */
.petlib-bloc {
    display: grid;
    grid-template-columns: 1fr;
    align-items: center;
    gap: 24px;

    margin: 50px 0 50px 0;
}

.petlib-bloc-image img,
.petlib-bloc-image-vide {
    display: block;
    width: 100%;
    aspect-ratio: 4 / 3;

    object-fit: cover;
    border-radius: 12px;
}

/* Cadre d'attente tant que le fichier n'est pas déposé : la mise en page reste
   lisible, sans image cassée. */
.petlib-bloc-image-vide {
    background-color: var(--bs-secondary);
}

.petlib-bloc-titre {
    margin-bottom: 12px;
    font-size: 1.375rem;
    line-height: 1.25;
}

.petlib-bloc-texte {
    margin-bottom: 0;
    font-size: 0.9375rem;
    line-height: 1.6;
}

/* Le texte vient d'un champ WYSIWYG : il arrive avec ses propres paragraphes,
   dont la marge basse s'ajouterait à celle du bloc. */
.petlib-bloc-texte > :last-child {
    margin-bottom: 0;
}

@media (min-width: 768px) {
    .petlib-bloc {
        grid-template-columns: 1fr 1fr;
        gap: 48px;
    }

    /* Inversion par « order » et non par un changement de colonnes : l'ordre du
       DOM reste image puis texte, ce qui garde la lecture cohérente en mobile
       et pour les lecteurs d'écran. */
    .petlib-bloc--inverse .petlib-bloc-image {
        order: 2;
    }

    .petlib-bloc-titre {
        font-size: 1.625rem;
    }

    .petlib-bloc-texte {
        font-size: 1rem;
    }
}

/*    BANDEAU DE REASSURANCE (composant reutilisable)     */

/* Volontairement non scopé à un univers : ce bandeau est appelé par
   petlib_reassurance() et doit pouvoir servir n'importe où. */
.petlib-reassurance {
    margin-top: 32px;
    padding-top: 24px;
    border-top: 1px solid rgba(0, 0, 0, .1);
}

/* Deux vignettes par ligne en mobile, quatre à partir de 992px. Le display est
   déclaré ici et non plus par une classe utilitaire de Bootstrap : la grille est
   désormais le seul rendu du composant, le carrousel qui tenait le mobile a été
   retiré. */
/* minmax(0, 1fr) et non 1fr : une piste 1fr garde un plancher à la largeur de son
   contenu, et un mot long comme « accompagnements » élargissait sa colonne — 120
   contre 151px dans la colonne étroite d'une fiche produit. Le 0 supprime ce
   plancher et rend les deux moitiés vraiment égales. */
.petlib-reassurance-grille {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 16px;

    margin: 0;
    padding: 0;

    list-style: none;
}

/* Empilement centré : icône, puis titre, puis texte. align-items règle ici le
   centrage horizontal, l'axe principal étant devenu vertical.
   Bordure et ombre reprennent celles de l'en-tête du site plutôt que des
   valeurs propres : les deux éléments se répondent ainsi visuellement. */
.petlib-reassurance-item {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 12px;

    margin: 0;
    padding: 24px 16px;

    background-color: #fff;
    border: 1px solid #ECE6DD;
    border-radius: 12px;
    box-shadow: 0 2px 8px rgba(0, 0, 0, .04);
    line-height: 1.35;
    text-align: center;
}

/* Même traitement que les bullet points de la fiche : la carte se soulève et
   son ombre se creuse, l'icône grossit légèrement. Réservé aux appareils à vrai
   survol — sur tactile, :hover reste « collé » après un appui et la carte
   resterait soulevée.
   Le sélecteur porte sur .petlib-reassurance-item et non sur un li : c'est la
   vignette qui est le composant, pas son rôle dans la liste. */
@media (hover: hover) {
    .petlib-reassurance-item,
    .petlib-reassurance-icone {
        transition: transform .2s ease, box-shadow .2s ease;
    }

    .petlib-reassurance-item:hover {
        transform: translateY(-3px);
        box-shadow: 0 6px 16px rgba(0, 0, 0, .08);
    }

    .petlib-reassurance-item:hover .petlib-reassurance-icone {
        transform: scale(1.12);
    }
}

@media (prefers-reduced-motion: reduce) {
    .petlib-reassurance-item,
    .petlib-reassurance-icone {
        transition: none;
    }

    .petlib-reassurance-item:hover,
    .petlib-reassurance-item:hover .petlib-reassurance-icone {
        transform: none;
    }
}

/* min-width: 0 indispensable : un élément flex vaut min-width: auto par défaut,
   il refuse donc de descendre sous la largeur de son contenu et le texte
   déborde au lieu de se renvoyer à la ligne. */
.petlib-reassurance-contenu {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 2px;
    min-width: 0;
}

.petlib-reassurance-titre {
    font-size: 0.875rem;
    font-weight: 700;
}

/* break-word : la vignette ne fait que 120px de large dans la colonne d'une fiche
   produit en mobile, et « accompagnements » y déborderait de sa carte. */
.petlib-reassurance-texte {
    color: var(--petlib-encre-douce);
    font-size: 0.8125rem;
    overflow-wrap: break-word;
}

/* Le cercle est dimensionné en em : sa taille suit donc le font-size posé
   ici, et l'icône reste toujours proportionnée à son fond.
   Cercle dans la couleur soutenue de l'univers, glyphe dans sa teinte claire :
   l'inverse laisserait un rond pâle peu visible sur la carte blanche. */
.petlib-reassurance-icone {
    display: flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;

    width: 1.6em;
    height: 1.6em;
    font-size: 2rem;

    /* Repli sur un brun sombre plutôt que currentColor : hors univers — le
       panier, par exemple — currentColor donnait des cercles quasi noirs, très
       durs sur le crème. Le blanc du glyphe y reste à 9,7:1. */
    background-color: var(--petlib-univers-color, #4A4340);
    border-radius: 50%;
}

/* font-size hérité du cercle, sinon la valeur ci-dessus resterait sans effet.
   Repli clair : hors d'un univers la variable n'est pas définie, et le glyphe
   se confondrait sinon avec le fond soutenu du cercle. */
.petlib-reassurance-icone .bi {
    color: var(--petlib-univers-primary-color, #fff);
    font-size: inherit;
    line-height: 1;
}

/* 992px : le seuil auquel ce bandeau passe de deux à quatre colonnes, donc son
   propre point de bascule desktop. Quatre vignettes plus tôt donneraient des
   titres de trois lignes — « Retours gratuits sous 30 jours » est le plus long
   des quatre et c'est lui qui commande. */
@media (min-width: 992px) {
    .petlib-reassurance {
        padding-top: 75px;
    }

    .petlib-reassurance-grille {
        grid-template-columns: repeat(4, 1fr);
        gap: 24px;
    }

    /* Le cercle reprend sa pleine taille : en mobile il partage la largeur avec
       une seconde vignette, ici il a la place. */
    .petlib-reassurance-icone {
        font-size: 2.5rem;
    }
}

/*    FICHE PRODUIT - REPERES DE REASSURANCE SOUS L'ACHAT     */

/* Trois colonnes égales, icône au-dessus du libellé, posées sur une bande
   blanche. Le filet qui les séparait de ce qui précède n'a plus lieu d'être :
   la bande se détache d'elle-même du fond de la page, et l'accordéon qui suit
   ouvre déjà sur le sien.
   Le rayon de 12px est celui de toutes les surfaces blanches du site — carte
   produit, carte d'avis, bandeau de réassurance. */
.petlib-produit .petlib-reassurance-achat {
    display: flex;
    gap: 12px;

    margin: 20px 0 0;
    padding: 16px 12px;

    background-color: #fff;
    border-radius: 12px;
    list-style: none;
}

/* min-width: 0 : un élément flex vaut min-width: auto par défaut et refuse de
   descendre sous la largeur de son mot le plus long, ce qui déséquilibrerait
   les trois colonnes.
   position: relative pour ancrer la barre de séparation ci-dessous. */
.petlib-produit .petlib-reassurance-achat li {
    display: flex;
    flex: 1;
    min-width: 0;
    flex-direction: column;
    align-items: center;
    gap: 6px;
    position: relative;

    color: #555;
    font-size: 0.75rem;
    line-height: 1.3;
    text-align: center;
}

/* Une barre verticale entre deux repères, jamais avant le premier — d'où le
   sélecteur de voisinage plutôt qu'un border-left sur tous.
   Elle est volontairement plus courte que le repère et centrée en hauteur : une
   barre pleine hauteur découperait la bande en trois cases.
   Posée au milieu du gap de 12px, donc à -6px du bord de l'élément. */
.petlib-produit .petlib-reassurance-achat li + li::before {
    content: "";
    position: absolute;
    top: 50%;
    left: -6px;
    transform: translateY(-50%);

    width: 1px;
    height: 32px;

    background-color: var(--petlib-univers-color);
}

/* Aucune couleur déclarée : les emoji portent la leur, c'est tout l'intérêt.
   La police du site n'a pas de glyphe pour eux, le navigateur bascule seul sur
   la police emoji du système. */
.petlib-produit .petlib-reassurance-achat-emoji {
    font-size: 1.375rem;
    line-height: 1;
}

/*    FICHE PRODUIT - ACCORDEON     */

/* Accordéon Bootstrap : le comportement vient du bundle déjà chargé par
   petlib_enqueue_bootstrap(), on ne fait qu'habiller.

   Chaque panneau est une carte blanche posée sur le crème du site, séparée de
   la suivante par 8px. Auparavant les panneaux partageaient des filets pleine
   largeur en couleur d'univers : ces lignes traversaient la colonne de part en
   part et pesaient visuellement plus lourd que les titres qu'elles séparaient.
   La couleur d'univers ne sert plus qu'à trois endroits — le titre, la
   pastille du chevron, et la bordure du panneau ouvert.

   Le chevron ouvert reprend celui de l'état fermé : Bootstrap le repasse sinon
   dans un bleu à lui à l'ouverture. C'est le SVG d'origine de Bootstrap, en
   stroke et non en fill, simplement redéclaré ici pour maîtriser sa teinte. Sa
   rotation est déjà gérée par la feuille du framework. */
.petlib-accordeon {
    margin-top: 24px;

    /* Une seule teinte commande tout l'accordéon. C'est la couleur de l'univers
       partout où il y en a un, et le graphite ailleurs : l'accueil est le couloir
       et n'a pas de maison. Sans ce repli, « color-mix » recevrait une variable
       vide, la déclaration serait invalide, et l'accordéon retomberait sur le
       bleu de Bootstrap. */
    --petlib-accordeon-couleur: var(--petlib-univers-color, #2d2d2d);

    /* Deux teintes dérivées, calculées plutôt que saisies : elles suivent
       d'elles-mêmes le chien, le chat et les NAC. À ces taux, le bleu du soir
       donne un gris-bleu à peine perceptible — c'est l'intention, la couleur
       reste un signal, pas un aplat. */
    --petlib-accordeon-pastille: color-mix(in srgb, var(--petlib-accordeon-couleur) 10%, #fff);
    --petlib-accordeon-entete: color-mix(in srgb, var(--petlib-accordeon-couleur) 5%, #fff);

    --bs-accordion-btn-focus-box-shadow: none;
    /* Fond transparent : c'est .accordion-item qui porte le blanc de la carte,
       le bouton se contente de le laisser voir. */
    --bs-accordion-btn-bg: transparent;
    --bs-accordion-active-bg: transparent;
    /* Trait crème au repos, comme toute carte du thème — la règle du trait
       crème veut qu'une bordure ne soit jamais un gris neutre. La couleur
       d'univers est réservée au panneau ouvert. */
    --bs-accordion-border-color: #ece6dd;
    --bs-accordion-active-color: var(--petlib-accordeon-couleur);
    /* Titres en couleur d'univers, ouverts comme fermés. Les règles de survol
       et de focus reprennent cette variable, elles suivent donc d'office. */
    --bs-accordion-btn-color: var(--petlib-accordeon-couleur);
    --bs-accordion-btn-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='%23212529' stroke-linecap='round' stroke-linejoin='round'%3e%3cpath d='m2 5 6 6 6-6'/%3e%3c/svg%3e");
    --bs-accordion-btn-active-icon: var(--bs-accordion-btn-icon);
}

/* La carte. Bootstrap ne borde que le bas de chaque élément et supprime le
   haut de tous sauf le premier : on rétablit les quatre côtés, puis on écarte
   les cartes de 8px. */
.petlib-accordeon .accordion-item {
    margin-bottom: 8px;

    background-color: #fff;
    border: 1px solid var(--bs-accordion-border-color);
    border-radius: 12px;
    transition: border-color .25s ease;
}

.petlib-accordeon .accordion-item:last-child {
    margin-bottom: 0;
}

/* Panneau ouvert : la bordure de la carte prend la couleur d'univers. C'est le
   seul marqueur d'état sur la carte entière — pas d'ombre, pas d'aplat.
   :has() est nécessaire parce que Bootstrap ne pose aucune classe sur
   .accordion-item ; seul .accordion-collapse reçoit « show ». */
.petlib-accordeon .accordion-item:has(.accordion-collapse.show) {
    border-color: var(--petlib-accordeon-couleur);
}

/* Le chevron est une pastille de 34px : assez grande pour se lire comme un
   bouton rond, assez petite pour ne pas concurrencer le titre. Le chevron lui-
   même reste à 15px, le reste est du vide qui laisse la forme respirer.
   La carte étant désormais blanche, le fond de repos ne peut plus être blanc :
   il prend la teinte pâle d'univers, seul moyen de voir la pastille. */
.petlib-accordeon .accordion-button::after {
    flex-shrink: 0;
    width: 34px;
    height: 34px;

    background-color: var(--petlib-accordeon-pastille);
    background-position: center;
    background-size: 15px;
    border-radius: 50%;

    transition: background-color .25s ease, transform .25s ease-in-out;
}

/* GeneratePress colore TOUS les <button> au survol et au focus, via son CSS
   dynamique inline :
       button:hover, …, button:focus, … { color:#fff; background-color:#3f4047 }
   Sans neutralisation, la ligne entière vire au gris foncé et le titre au
   blanc — et le focus faisant partie du sélecteur, ça persistait après un clic.
   On remet donc explicitement les deux propriétés à leur valeur de repos. */
.petlib-accordeon .accordion-button:hover,
.petlib-accordeon .accordion-button:focus {
    color: var(--bs-accordion-btn-color);
    background-color: transparent;
}

/* Panneau ouvert : on rend au titre sa couleur d'univers, que la règle
   ci-dessus vient d'écraser, et on garde la teinte de l'en-tête — sans ce
   rappel, survoler un panneau ouvert le décolorait. */
.petlib-accordeon .accordion-button:not(.collapsed),
.petlib-accordeon .accordion-button:not(.collapsed):hover,
.petlib-accordeon .accordion-button:not(.collapsed):focus {
    background-color: var(--petlib-accordeon-entete);
    color: var(--bs-accordion-active-color);
}

/* Filet de séparation entre l'en-tête et le contenu, à l'intérieur de la
   carte. Il reste crème même quand la carte est bordée d'univers : deux traits
   colorés dans un si petit bloc feraient cage. */
.petlib-accordeon .accordion-collapse.show {
    border-top: 1px solid #ece6dd;
}

/* Le rembourrage du corps est posé sur .accordion-body sans condition, et non
   sur « .show .accordion-body » : Bootstrap ne pose « show » qu'à la fin de son
   animation, le corps se dépliait donc sans marge latérale puis la prenait
   d'un coup. Le texte partait collé au bord gauche et sautait de 16px à
   l'arrivée. */

/* Pastille en couleur d'univers dans deux cas : au survol, et tant que le
   panneau est ouvert. Le chevron passe en blanc, illisible sinon sur ce fond
   sombre. Le sélecteur bat le « :not(.collapsed)::after » de Bootstrap, qui
   remettrait sinon son icône bleue. */
.petlib-accordeon .accordion-button:hover::after,
.petlib-accordeon .accordion-button:not(.collapsed)::after {
    background-color: var(--petlib-accordeon-couleur, #2d2d2d);
    background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='%23fff' stroke-linecap='round' stroke-linejoin='round'%3e%3cpath d='m2 5 6 6 6-6'/%3e%3c/svg%3e");
}

/* gap plutôt qu'une marge sur l'icône : .accordion-button est déjà un flex
   chez Bootstrap, et le chevron étant poussé par « margin-left: auto », le gap
   ne décolle que l'icône du titre.

   Le rayon suit celui de la carte, sinon la teinte de l'en-tête ouvert
   déborderait en angle droit sur les coins arrondis. En bas il s'annule dès
   que le panneau s'ouvre : le bouton n'est plus la dernière chose de la carte.

   700 et non 600 : seules les graisses 400 et 700 d'Inter sont chargées, et
   demander une graisse absente fait synthétiser un faux gras par le
   navigateur. */
.petlib-accordeon .accordion-button {
    gap: 8px;
    padding: 14px 16px;

    border-radius: 12px;
    font-size: 1rem;
    font-weight: 700;
    transition: background-color .25s ease;
}

.petlib-accordeon .accordion-button:not(.collapsed) {
    border-radius: 12px 12px 0 0;
}

.petlib-accordeon .accordion-button .bi {
    flex-shrink: 0;
    font-size: 1.1em;
    line-height: 1;
}

/* 1rem plutôt que les 14px d'avant : c'est le corps de texte documenté du
   thème, et ces panneaux portent l'information qui décide de l'achat — tailles,
   matières, entretien, délais. L'interligne à 1,6 est le haut de la fourchette
   du système, justifié par la largeur étroite de la colonne. */
.petlib-accordeon .accordion-body {
    padding: 16px;
    font-size: 1rem;
    line-height: 1.6;
}

.petlib-accordeon .accordion-body p {
    margin-bottom: 12px;
}

.petlib-accordeon .accordion-body p:last-child {
    margin-bottom: 0;
}

/* Listes des panneaux (délais de livraison, conditions de retour, puces saisies
   dans la description). La puce noire du navigateur est remplacée par une
   pastille en couleur d'univers, posée en ::before — le retrait est alors géré
   au pixel plutôt que laissé au calcul de list-style. */
/* La marge est écrite en raccourci pour annuler explicitement le
   « margin: 0 0 1.5em 3em » de GeneratePress (assets/css/style.css:305) : une
   déclaration margin-bottom seule laissait vivre ses 3em de retrait à gauche,
   soit 48px pris sur une colonne déjà étroite. */
.petlib-accordeon .accordion-body ul {
    margin: 0 0 1em;
    padding-left: 0;
    list-style: none;
}

.petlib-accordeon .accordion-body ul li {
    position: relative;
    padding-left: 10px;
}

/* Une pastille et non une coche : le même CSS habille la liste « Livraison et
   expédition », où une coche devant un délai de préparation affirmerait
   quelque chose de faux. Les panneaux n'ont aucune classe distinctive — ils
   sont numérotés par index et leur ordre varie d'un produit à l'autre — donc
   pas de traitement par panneau possible.
   top en em : la pastille suit la première ligne même si l'élément en compte
   plusieurs. */
.petlib-accordeon .accordion-body ul li::before {
    content: "";
    position: absolute;
    top: .62em;
    left: 0;

    width: 6px;
    height: 6px;

    background-color: var(--petlib-accordeon-couleur, #2d2d2d);
    border-radius: 50%;
}

/* Les listes numérotées gardent leurs chiffres : le rang y porte du sens. Même
   raccourci de marge que les <ul> ci-dessus, pour la même raison — seul le
   retrait interne diffère, les chiffres demandant plus de place qu'un point. */
.petlib-accordeon .accordion-body ol {
    margin: 0 0 1em;
    padding-left: 1.25em;
}

.petlib-accordeon .accordion-body li + li {
    margin-top: 8px;
}

.petlib-accordeon .accordion-body > :last-child {
    margin-bottom: 0;
}

/* Intertitres saisis dans la description du produit. Ils reprennent la couleur
   de l'univers, comme le titre de la fiche : c'est le seul repère de marque
   dans un panneau par ailleurs en texte courant.
   Taille en px et non en rem : la valeur est voulue absolue, indépendante du
   corps de référence du thème parent. */
.petlib-accordeon .accordion-body h3 {
    margin-bottom: 5px;
    color: var(--petlib-accordeon-couleur, #2d2d2d);
    font-size: 20px;
}

/* Aucune media query : les cartes se comportent de la même façon de 320px au
   plafond du conteneur, et les tailles retenues sont déjà celles du corps de
   texte documenté. Le seuil de 768px n'aurait rien à y changer.

   Les trois transitions posées plus haut — bordure de carte, teinte d'en-tête,
   pastille et rotation du chevron — sont neutralisées ici, comme partout
   ailleurs dans le thème. */
@media (prefers-reduced-motion: reduce) {
    .petlib-accordeon .accordion-item,
    .petlib-accordeon .accordion-button,
    .petlib-accordeon .accordion-button::after {
        transition: none;
    }
}

/*    FICHE PRODUIT CHIEN - QUANTITE, PRIX ET PANIER     */

/* Ordre voulu : prix, mention de taxes, libellé de quantité, sélecteur de
   quantité, bouton. WooCommerce sort le prix dans .single_variation et la
   quantité + le bouton dans .woocommerce-variation-add-to-cart, deux
   conteneurs frères : la grille permet de tout replacer librement. */
.petlib-produit .single_variation_wrap {
    display: grid;
    grid-template-columns: auto minmax(0, 1fr);
    align-items: center;
    row-gap: 8px;
    column-gap: 12px;
}

/* Ce conteneur ne sert qu'à grouper : on l'efface pour que la quantité et le
   bouton deviennent directement des éléments de la grille. Sans risque ici,
   WooCommerce ne lui applique que des classes (enabled / disabled) et jamais
   de display inline — contrairement à .single_variation, qu'on laisse donc
   intact. */
.petlib-produit .woocommerce-variation-add-to-cart {
    display: contents;
}

.petlib-produit .single_variation_wrap .single_variation      { grid-row: 1; grid-column: 1 / -1; }
.petlib-produit .single_variation_wrap .petlib-mention-taxes  { grid-row: 2; grid-column: 1 / -1; }

/* Libellé et champ de quantité sur la même ligne. */
.petlib-produit .single_variation_wrap .petlib-label-quantite { grid-row: 3; grid-column: 1; }

.petlib-produit .single_variation_wrap .quantity {
    grid-row: 3;
    grid-column: 2;
    justify-self: start;
}

.petlib-produit .single_variation_wrap .woocommerce-variation-add-to-cart button.single_add_to_cart_button {
    grid-row: 4;
    grid-column: 1 / -1;
    margin-top: 4px;
}

/* Même bloc d'achat sur un produit simple, où WooCommerce pose tout directement
   dans le formulaire : ni .single_variation_wrap ni conteneur intermédiaire à
   aplatir, la grille est donc portée par form.cart lui-même.
   « :not(.variations_form) » est indispensable : sur un produit à variations,
   ce même formulaire contient aussi le tableau des attributs, et en faire une
   grille désorganiserait tout le bloc.
   Une ligne de moins que la grille des variations : le prix d'un produit simple
   n'est pas retiré du résumé (il n'y a pas de fourchette à masquer), il reste
   donc au-dessus du formulaire — au même endroit à l'écran. */
.petlib-produit form.cart:not(.variations_form) {
    display: grid;
    grid-template-columns: auto minmax(0, 1fr);
    align-items: center;
    row-gap: 8px;
    column-gap: 12px;
}

.petlib-produit form.cart:not(.variations_form) .petlib-mention-taxes  { grid-row: 1; grid-column: 1 / -1; }

/* Libellé et champ de quantité sur la même ligne. */
.petlib-produit form.cart:not(.variations_form) .petlib-label-quantite { grid-row: 2; grid-column: 1; }

.petlib-produit form.cart:not(.variations_form) .quantity {
    grid-row: 2;
    grid-column: 2;
    justify-self: start;
}

.petlib-produit form.cart:not(.variations_form) button.single_add_to_cart_button {
    grid-row: 3;
    grid-column: 1 / -1;
    margin-top: 4px;
}

.petlib-produit form.cart:not(.variations_form) .petlib-moyens-paiement {
    grid-row: 4;
    grid-column: 1 / -1;
}

/* Habillage du composant lui-même, volontairement non scopé : petlib_moyens_paiement()
   est appelée aussi bien sur la fiche produit que dans le panier. Scopées à
   .petlib-produit, ces règles laissaient les logos à leur taille naturelle
   partout ailleurs — un PayPal de plusieurs centaines de pixels. */
.petlib-moyens-paiement {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: 8px;

    margin: 0;
    padding: 0;

    list-style: none;
}

.petlib-moyens-paiement li {
    display: flex;
    align-items: center;
    min-height: 28px;
}

/* Repli quand le fichier du logo n'est pas encore déposé. */
.petlib-moyens-paiement .petlib-moyen--texte {
    padding: 4px 10px;

    color: #555;
    font-size: 0.75rem;
    line-height: 1.2;

    background-color: #fff;
    border: 1px solid rgba(0, 0, 0, .2);
    border-radius: 4px;
}

/* Les logos dessinent déjà leur propre cadre de carte : les encadrer une
   seconde fois ferait une boîte dans une boîte.
   Hauteur imposée, largeur libre — les logos n'ont pas tous le même format. */
.petlib-moyens-paiement img {
    display: block;
    width: auto;
    height: 40px;
}

/* Seul le placement dans la grille du bloc panier reste propre à la fiche. */
.petlib-produit .single_variation_wrap .petlib-moyens-paiement {
    grid-row: 5;
    grid-column: 1 / -1;
}

/* Le bouton doit rester identique sur les trois univers ET quel que soit le
   type de produit : aucune variable d'univers ici, contrairement au reste de la
   fiche.
   Le sélecteur passe par form.cart, commun aux deux gabarits : le produit à
   variations range son bouton dans .single_variation_wrap, le produit simple le
   pose directement dans le formulaire. Il faut aussi battre le
   « .woocommerce button.button.alt » de woocommerce.css (0,3,1), qui sans ça
   impose son violet par défaut — « form.cart button » monte à (0,3,2) et
   l'emporte sans !important. */
.petlib-produit form.cart button.single_add_to_cart_button {
    color: #FFF;
    background: linear-gradient(
            135deg,
            #404040 0%,
            #2D2D2D 45%,
            #1F1F1F 100%
    );
    border: 1px solid #000;
    animation: petlib-elastique 3s ease-in-out infinite;
    transition: filter .2s ease;
}

/* Étirement élastique : le bouton s'allonge, dépasse sa position d'équilibre,
   puis oscille en s'amortissant jusqu'au repos — un ressort, pas un simple
   zoom. Chaque étirement horizontal s'accompagne d'un écrasement vertical
   (et inversement), c'est ce qui donne la sensation de matière.
   Le mouvement tient dans les 40 premiers pour-cent du cycle, le reste est un
   temps mort sans lequel l'effet deviendrait nerveux. */
@keyframes petlib-elastique {
    0%   { transform: scale(1, 1); }
    8%   { transform: scale(1.04, .94); }
    16%  { transform: scale(.98, 1.04); }
    24%  { transform: scale(1.02, .98); }
    32%  { transform: scale(.995, 1.01); }
    40%  { transform: scale(1, 1); }
    100% { transform: scale(1, 1); }
}

@media (prefers-reduced-motion: reduce) {
    .petlib-produit form.cart button.single_add_to_cart_button {
        animation: none;
    }
}

/* Le survol posait « color: #000 » en comptant sur un background-color clair
   pour prendre le dessus — sauf que le dégradé ci-dessus est une image de fond,
   qui recouvre toute couleur de fond : le libellé virait au noir sur du noir.
   On garde donc le texte blanc et on assombrit le dégradé.
   La luminosité plutôt qu'un second dégradé : background-image ne s'interpole
   pas, un changement de dégradé sauterait d'un état à l'autre là où le filtre
   se transitionne. */
.petlib-produit form.cart button.single_add_to_cart_button:hover {
    color: #FFF;
    filter: brightness(.75);
}

/* Prix en noir. Spécificité (0,4,1) pour passer devant la règle de
   woocommerce.css « .woocommerce div.product span.price », en (0,3,2). */
.petlib-produit .single_variation .woocommerce-variation-price span.price {
    color: #000;
}

/* Suffixe purement visuel : le prix est généré en JS par WooCommerce à partir
   des données de variation, on ne peut pas l'y insérer proprement en PHP. */
.petlib-produit .woocommerce-variation-price .price::after {
    content: " TTC";
}

.petlib-produit .petlib-mention-taxes {
    margin: 0;
    color: var(--petlib-encre-douce);
    font-size: 0.75rem;
    line-height: 1.4;
}

.petlib-produit .petlib-label-quantite {
    margin: 8px 0 0;
    font-size: 0.875rem;
    font-weight: 700;
}

.petlib-produit .petlib-quantite-panier {
    color: var(--petlib-encre-douce);
    font-weight: 400;
}

/*    FICHE PRODUIT CHIEN - OPTIONS DE VARIATION     */

/* Le <select> reste dans le DOM, simplement masqué : c'est lui qui pilote le
   moteur de variations de WooCommerce, les options ne font que le régler.
   !important assumé : woocommerce.css impose display: inline-block via
   « .woocommerce div.product form.cart .variations select », de spécificité
   (0,4,3) — l'égaler demanderait un sélecteur bien plus fragile que ça. */
.petlib-produit .petlib-choix-variation > select {
    display: none !important;
}

.petlib-produit .petlib-options-variation {
    display: flex;
    flex-wrap: wrap;
    gap: 10px;

    margin: 0;
    padding: 0;

    list-style: none;
}

.petlib-produit .petlib-option {
    cursor: pointer;
}

.petlib-produit .petlib-option.is-indisponible {
    opacity: .3;
    cursor: not-allowed;
}

/* Couleur : pastille ronde, cible tactile confortable en mobile puis
   resserrée à la souris. */
.petlib-produit .petlib-option--couleur {
    width: 36px;
    height: 36px;
    padding: 0;

    background-color: transparent;
    border: 1px solid rgba(0, 0, 0, .2);
    border-radius: 50%;
}

.petlib-produit .petlib-option--couleur.is-active {
    box-shadow: 0 0 0 2px #fff, 0 0 0 4px var(--petlib-univers-color);
}

/* Repli quand le slug du terme n'est pas une couleur connue. */
.petlib-produit .petlib-option--texte {
    width: auto;
    height: auto;
    padding: 6px 12px;

    font-size: 0.875rem;
    border-radius: 999px;
}

/* Taille : cadres alignés à la suite. La bordure noire de l'état actif est
   épaissie par un box-shadow interne plutôt qu'en changeant border-width,
   pour ne pas décaler les cadres voisins. */
.petlib-produit .petlib-option--taille {
    padding: 10px 16px;

    color: inherit;
    font-size: 0.75rem;
    line-height: 1.2;

    background-color: #fff;
    border: 1px solid rgba(0, 0, 0, .25);
    border-radius: 6px;
}

.petlib-produit .petlib-option--taille.is-active {
    background-color: var(--bs-secondary);
    border-color: #000;
    box-shadow: inset 0 0 0 1px #000;
}

@media (min-width: 768px) {
    .petlib-produit .petlib-option--couleur {
        width: 32px;
        height: 32px;
    }

    .petlib-produit .petlib-option--taille {
        padding: 8px 14px;
    }
}

/*    FICHE PRODUIT CHIEN - GALERIE     */

/* Mobile first : FlexSlider assure déjà le défilement tactile de la galerie,
   qui sert de carrousel en mobile. Les flèches (activées côté PHP par
   petlib_galerie_produit_fleches()) ne servent qu'à partir de la tablette. */
.petlib-produit .flex-direction-nav {
    display: none;
}

/* Bande de vignettes sur une seule ligne, défilante horizontalement.
   WooCommerce les dispose en float à 25% de large, ce qui les fait passer à la
   ligne dès la cinquième : on repasse en flex sans retour à la ligne, et le
   surplus devient du défilement. assets/js/galerie-produit.js y amène la
   vignette active à chaque changement d'image. */
.petlib-produit .flex-control-thumbs {
    display: flex;
    flex-wrap: nowrap;
    gap: 8px;

    margin: 12px 0 0;
    padding: 0;

    /* !important assumé : woocommerce.css impose « overflow: hidden » via
       « .woocommerce div.product div.images .flex-control-thumbs », de
       spécificité (0,4,2). L'égaler demanderait un sélecteur bien plus fragile.
       Seul l'axe X est surchargé : overflow-y hérite du hidden de WooCommerce,
       ce qui évite une barre de défilement verticale parasite. */
    overflow-x: auto !important;
    overscroll-behavior-x: contain;
    scrollbar-width: thin;
}

.petlib-produit .flex-control-thumbs li {
    flex: 0 0 64px;
    float: none; /* annule le float à 25% de WooCommerce */
    width: 64px;
    margin: 0;
}

/* aspect-ratio + cover : les vignettes restent carrées quel que soit le format
   du fichier source, sans déformation (WooCommerce laisse object-fit: fill). */
.petlib-produit .flex-control-thumbs img {
    display: block;
    width: 100%;
    height: auto;
    aspect-ratio: 1;

    object-fit: cover;
    border-radius: 4px;
    cursor: pointer;
}

.petlib-produit .flex-control-thumbs img.flex-active {
    outline: 2px solid var(--petlib-univers-color);
    outline-offset: -2px;
}

@media (min-width: 768px) {
    .petlib-produit .flex-control-thumbs li {
        flex-basis: 76px;
        width: 76px;
    }
}

@media (min-width: 768px) {
    /* Image et flèches sont empilées sur la même cellule de grille : les
       flèches épousent donc la hauteur de l'image quel que soit son format,
       et les miniatures restent en dessous. */
    .petlib-produit .woocommerce-product-gallery {
        display: grid;
    }

    .petlib-produit .flex-viewport,
    .petlib-produit .flex-direction-nav {
        grid-row: 1;
        grid-column: 1;
    }

    .petlib-produit .flex-control-thumbs {
        grid-row: 2;
        grid-column: 1;
    }

    /* position + z-index indispensables : la galerie contient deux éléments
       positionnés qui passeraient sinon par-dessus des flèches restées en
       "static" — .flex-viewport (position: relative posée par FlexSlider), qui
       les masque, et le calque .zoomImg de jQuery Zoom (transparent mais
       cliquable), qui leur vole le clic dès que la souris entre dans la
       galerie. On reste sous le 99 du bouton de zoom. */
    .petlib-produit .flex-direction-nav {
        position: relative;
        z-index: 2;

        display: flex;
        align-items: center;
        justify-content: space-between;

        margin: 0;
        padding: 0 12px;

        list-style: none;
        pointer-events: none; /* seuls les liens captent le clic, pas l'image */
    }

    .petlib-produit .flex-direction-nav a {
        display: flex;
        align-items: center;
        justify-content: center;

        width: 40px;
        height: 40px;

        color: #fff;
        font-size: 0; /* masque le libellé "Previous"/"Next" de FlexSlider */
        background-color: var(--petlib-univers-color);
        border-radius: 50%;
        pointer-events: auto;
    }

    /* Chevrons Bootstrap Icons, police déjà chargée par petlib_enqueue_bootstrap(). */
    .petlib-produit .flex-direction-nav a::before {
        font-family: bootstrap-icons;
        font-size: 1.25rem;
        line-height: 1;
    }

    .petlib-produit .flex-direction-nav .flex-prev::before {
        content: "\f284";
    }

    .petlib-produit .flex-direction-nav .flex-next::before {
        content: "\f285";
    }

    .petlib-produit .flex-direction-nav a:hover {
        opacity: .85;
    }

    /* animationLoop est à false : FlexSlider grise la flèche en bout de galerie. */
    .petlib-produit .flex-direction-nav .flex-disabled {
        opacity: .3;
        cursor: default;
    }
}

/*    FICHE PRODUIT - BLOC D'ACHAT FLOTTANT     */

/* Sorti sur wp_footer, ce bloc est un enfant direct de <body> : il échappe donc
   aux conteneurs de la fiche — dont la colonne de galerie en position: sticky —
   mais aussi à .petlib-produit, qui porte les variables d'univers. D'où le noir
   du bouton, identique sur les trois univers, comme celui du panier.

   Mobile : barre pleine largeur collée en bas de l'écran. L'image et le bouton
   de repli n'y ont pas leur place, ils sont réservés au sticker qui prend le
   relais à partir de la tablette. */
.petlib-achat-flottant {
    position: fixed;
    right: 0;
    bottom: 0;
    left: 0;
    z-index: 900;

    padding: 10px 16px;

    background-color: #fff;
    box-shadow: 0 -2px 12px rgba(0, 0, 0, .12);
}

/* Le display posé plus bas (flex, dès 768px) l'emporterait sur le
   « display: none » que la feuille du navigateur applique à [hidden]. */
.petlib-achat-flottant[hidden] {
    display: none;
}

/* Réservés à la tablette et au-delà : la largeur d'un téléphone ne permet pas
   d'aligner une vignette, un nom, un prix et deux boutons sur une ligne. En
   mobile il ne reste donc que le bouton, sur toute la largeur. */
.petlib-achat-flottant__image,
.petlib-achat-flottant__infos,
.petlib-achat-flottant__fermer {
    display: none;
}

/* Mêmes valeurs que l'ajout au panier de la fiche et que la validation de
   commande : l'action principale du site garde partout la même apparence.
   L'animation élastique n'est pas reprise — un bloc qui surgit au défilement
   attire déjà l'œil. */
.petlib-achat-flottant__bouton {
    display: block;
    width: 100%;
    padding: 14px 20px;
    transition: filter .2s ease;

    background: linear-gradient(
            135deg,
            #404040 0%,
            #2D2D2D 45%,
            #1F1F1F 100%
    );
    border: 1px solid #000;
    border-radius: 8px;
    color: #FFF;
    font-size: 1rem;
    font-weight: 700;
    text-align: center;
    cursor: pointer;
}

/* GeneratePress colore tous les <button> au survol et au focus : sans cette
   règle, le bouton virerait à son bleu. Le dégradé étant une image de fond, il
   couvrirait de toute façon le background-color — on joue donc sur la
   luminosité, comme le bouton de commande. */
.petlib-achat-flottant__bouton:hover,
.petlib-achat-flottant__bouton:focus {
    color: #FFF;
    filter: brightness(.75);
}

/* Un élément fixe recouvre ce qui reçoit le focus au clavier — WCAG 2.2 AA
   « Focus Not Obscured ». On réserve donc la hauteur de la barre au défilement
   automatique vers un élément focalisé ou une ancre. La règle est portée par
   :has() parce que scroll-padding n'agit que sur l'élément qui défile, <html>,
   alors que la classe d'état est posée sur <body> par achat-flottant.js. */
html:has(body.petlib-achat-flottant-visible) {
    scroll-padding-bottom: 104px;
}

/* À partir de la tablette : la barre garde toute la largeur de l'écran, mais
   son contenu est ramené à la largeur du site et centré. Sans ce conteneur,
   la vignette et le bouton se colleraient chacun à un bord opposé, à plus d'un
   mètre l'un de l'autre sur un écran large. */
@media (min-width: 768px) {
    .petlib-achat-flottant {
        padding: 12px 16px;
    }

    .petlib-achat-flottant__contenu {
        display: flex;
        align-items: center;
        gap: 16px;

        /* Même plafond que .grid-container, pour que la barre s'aligne sur le
           reste du site plutôt que sur le hasard de sa propre largeur. */
        max-width: 1400px;
        margin: 0 auto;
    }

    .petlib-achat-flottant__image {
        display: block;
        flex-shrink: 0;

        width: 64px;
        height: 64px;

        border-radius: 8px;
        object-fit: cover;
    }

    /* min-width: 0 : un enfant flex refuse par défaut de descendre sous la
       largeur de son propre texte, et l'ellipsis du titre ne se déclencherait
       jamais. */
    .petlib-achat-flottant__infos {
        display: flex;
        flex: 1 1 auto;
        flex-direction: column;
        gap: 2px;
        min-width: 0;
    }

    /* Le nom tient sur une ligne. Un retour à la ligne ferait varier la hauteur
       de la barre d'un produit à l'autre, alors que c'est cette hauteur que le
       scroll-padding ci-dessus et le décalage du retour-en-haut réservent. */
    .petlib-achat-flottant__titre {
        overflow: hidden;

        font-weight: 700;
        text-overflow: ellipsis;
        white-space: nowrap;
    }

    /* Pas de taille déclarée : le prix reste au corps de texte, et c'est la
       graisse qui sépare le nom du prix plutôt qu'un écart de taille. */

    /* Le prix barré des promotions : WooCommerce le sort en <del>, suivi du
       prix courant en <ins>. Sans cette règle, le <ins> serait souligné. */
    .petlib-achat-flottant__prix del {
        margin-right: 6px;
        opacity: .6;
    }

    .petlib-achat-flottant__prix ins {
        background-color: transparent;
        font-weight: 700;
        text-decoration: none;
    }

    /* Le bouton reprend sa largeur naturelle : le « width: 100% » du rendu
       mobile l'étirerait sur toute la barre. */
    .petlib-achat-flottant__bouton {
        flex-shrink: 0;
        width: auto;
        padding: 12px 28px;
    }

    /* 32px de côté : au-dessus des 24px CSS exigés par WCAG 2.2 AA pour une
       cible de pointage. La couleur d'univers vient de la classe
       .petlib-univers-<slug> posée sur le body — sortie sur wp_footer, la barre
       est hors de .petlib-produit et n'hériterait de rien sans elle. Le repli
       couvre les pages sans univers, où la variable n'existe pas. */
    .petlib-achat-flottant__fermer {
        display: flex;
        flex-shrink: 0;
        align-items: center;
        justify-content: center;

        width: 32px;
        height: 32px;
        padding: 0;

        background-color: transparent;
        border: 0;
        border-radius: 50%;
        color: var(--petlib-univers-color, #1F1F1F);
        line-height: 1;
        cursor: pointer;
    }

    .petlib-achat-flottant__fermer:hover,
    .petlib-achat-flottant__fermer:focus {
        background-color: var(--petlib-univers-color, #1F1F1F);
        color: #FFF;
    }
}

/*    RETOUR EN HAUT     */

/* Le bouton lui-même vient de GeneratePress : le balisage, le script de
   défilement et le seuil d'apparition sont les siens, petlib_activer_retour_haut()
   ne fait qu'activer le réglage.

   Son habillage est en revanche entièrement repris ici, y compris ce que le
   parent produirait lui-même (position, dimensions, état masqué). GeneratePress
   met son CSS dynamique en cache et ne le régénère qu'au changement de version
   du thème : activer le réglage par un filtre ne suffit donc pas à faire
   apparaître ses règles, et le bouton restait en position: static. Tout écrire
   ici rend le résultat indépendant de l'état de ce cache — et le jour où il est
   régénéré, ses règles ont une spécificité plus faible, sans conflit.

   L'état masqué reprend le parti du parent : opacité 0,1 et translation hors
   écran plutôt que visibility, qui provoque un double appui sur iOS.
   Sélecteur en (0,1,2) : les couleurs du parent viennent de
   « a.generate-back-to-top », l'égaler dépendrait de l'ordre des feuilles. */
body a.generate-back-to-top {
    position: fixed;
    right: auto;
    bottom: 30px;
    left: 30px;
    z-index: 899;

    width: 40px;

    background-color: var(--petlib-univers-color, #1F1F1F);
    border-radius: 50%;
    color: #FFF;
    font-size: 20px;
    line-height: 40px;
    text-align: center;

    opacity: .1;
    transform: translateY(1000px);
    transition: opacity 300ms ease-in-out;
}

/* Classe posée par le script du parent au-delà de 300px de défilement. */
body a.generate-back-to-top.generate-back-to-top__show {
    opacity: 1;
    transform: translateY(0);
}

body a.generate-back-to-top:hover,
body a.generate-back-to-top:focus {
    background-color: var(--petlib-univers-color, #1F1F1F);
    color: #FFF;
    filter: brightness(1.15);
}

/* Pas de bouton en mobile : le bas de l'écran y est déjà pris — barre d'achat
   sur les fiches produit, barre d'outils du navigateur — et la remontée s'y fait
   au geste. Masqué plutôt que retiré du balisage, que GeneratePress pose sur
   generate_after_footer avec son script : « display: none » le sort du rendu
   comme de l'ordre de tabulation, sans rien à décrocher côté PHP. */
@media (max-width: 767px) {
    body a.generate-back-to-top {
        display: none;
    }
}

/* La barre d'achat occupe toute la largeur du bas de l'écran : le bouton passe
   au-dessus tant qu'elle est affichée. La classe est posée par
   achat-flottant.js, seul à connaître cet état.
   Une seule valeur depuis que le bouton est masqué en mobile : la seule hauteur
   de barre à franchir est celle du grand écran, vignette de 64px comprise. */
body.petlib-achat-flottant-visible a.generate-back-to-top {
    bottom: 104px;
}


/*    PIED DE PAGE - REASSURANCE     */

/* Sur le crème de la page et non sur le sombre du pied : c'est la rupture de
   fond qui sépare les deux, aucun filet n'est nécessaire. */
.petlib-reassurance-pied {
    padding: 32px 0;
    background-color: var(--petlib-papier-creme, #f8f4ee);
}

.petlib-reassurance-pied-liste {
    display: grid;
    grid-template-columns: 1fr;
    gap: 20px;

    margin: 0;
    padding: 0;

    list-style: none;
}

.petlib-reassurance-pied-item {
    display: flex;
    align-items: center;
    gap: 12px;
}

/* Icône en trait, à peine plus grande que le texte : ces quatre repères ferment
   la page, ils n'accompagnent pas une décision d'achat comme ceux de la fiche
   produit. Le trait suffit, l'aplat serait de trop.

   Neutre et non « var(--petlib-univers-color) » : cette bande ferme toutes les
   pages du site, elle appartient aux trois maisons comme le pied de page qui la
   suit. Prendre la couleur de l'univers courant la faisait changer d'une page à
   l'autre et disparaître sur l'accueil, qui n'a volontairement pas d'univers.
   C'est aussi la couleur du fond du pied, juste en dessous : les icônes lui
   répondent. */
.petlib-reassurance-pied-item .bi {
    flex: none;
    color: #1f1f1f;
    font-size: 1.375rem;
    line-height: 1;
}

.petlib-reassurance-pied-contenu {
    display: flex;
    flex-direction: column;
}

.petlib-reassurance-pied-contenu strong {
    font-family: var(--petlib-font-titre);
    font-size: 0.9375rem;
    line-height: 1.3;
}

.petlib-reassurance-pied-contenu span {
    color: var(--petlib-encre-douce);
    font-size: 0.8125rem;
    line-height: 1.4;
}

@media (min-width: 768px) {
    .petlib-reassurance-pied {
        padding: 40px 0;
    }

    /* Deux colonnes d'abord. À quatre dès 768px chaque repère tombait à 170px, et
       « Des produits sélectionnés avec soin » s'y repliait sur trois lignes sous
       un titre d'une seule — la bande cessait d'être une ligne de repères pour
       devenir quatre paragraphes. */
    .petlib-reassurance-pied-liste {
        grid-template-columns: repeat(2, 1fr);
        gap: 20px 24px;
    }
}

/* Quatre de front seulement quand chaque repère dispose d'environ 245px, largeur
   à laquelle son sous-titre tient enfin sur une ligne. Même palier que les
   colonnes du pied et que le bloc éditorial des pages d'univers. */
@media (min-width: 1100px) {
    .petlib-reassurance-pied-liste {
        grid-template-columns: repeat(4, 1fr);
        gap: 24px;
    }
}

/*    PIED DE PAGE - FOND ET COLONNES     */

/* Tout le pied passe au sombre. Les couleurs sont posées ici et nulle part
   ailleurs : les descendants héritent, et une seule ligne suffirait à changer
   l'ensemble. */
.site-info {
    padding: 40px 0 24px;
    background-color: #1f1f1f;
    color: #d0d0d0;
}

/* GeneratePress met ce conteneur en « flex; align-items: center » pour ranger sa
   barre de crédits sur une ligne. Nos trois blocs — newsletter, colonnes, barre
   du bas — y devenaient donc trois colonnes voisines, chacune écrasée au tiers
   de la largeur. Ils s'empilent, ils ne se juxtaposent pas : le retour au bloc
   est la seule règle nécessaire, chacun gère sa propre disposition interne. */
.site-info .inside-site-info {
    display: block;
}

/* GeneratePress centre le texte de son pied, ce qui convient à une seule ligne
   de crédits mais pas à quatre colonnes de liens : centrées, leurs bords ne
   s'alignent sur rien et l'œil ne trouve plus le début des lignes. */
.site-info {
    text-align: left;
}

.site-info a {
    color: #d8d8d8;
    text-decoration: none;
}

.site-info a:hover,
.site-info a:focus {
    color: #fff;
    text-decoration: underline;
}

/*    PIED DE PAGE - NEWSLETTER     */

/* Bande pleine largeur en tête du pied, séparée des colonnes par un filet : un
   champ coincé dans une cinquième colonne ne se serait pas vu. */
.petlib-newsletter {
    display: flex;
    flex-direction: column;
    gap: 16px;

    padding-bottom: 32px;
    margin-bottom: 32px;

    border-bottom: 1px solid #3a3a3a;
}

.petlib-newsletter-titre {
    margin: 0 0 6px;
    color: #fff;
    font-size: 1.25rem;
    line-height: 1.25;
}

.petlib-newsletter-accroche {
    margin: 0;
    color: #d0d0d0;
    font-size: 0.9375rem;
    line-height: 1.5;
}

.petlib-newsletter-form {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
}

/* Le champ prend la place restante et ne descend jamais sous 200px : en dessous
   une adresse saisie n'est plus relisible. */
.petlib-newsletter-champ {
    flex: 1 1 200px;
    min-width: 0;
    padding: 12px 16px;

    background-color: #2d2d2d;
    border: 1px solid #3a3a3a;
    border-radius: 8px;
    color: #fff;
    font-family: var(--petlib-font-texte);
    font-size: 1rem;
}

.petlib-newsletter-champ::placeholder {
    color: #9a9a9a;
}

.petlib-newsletter-champ:focus {
    border-color: #d0d0d0;
    outline: 2px solid transparent;
    outline-offset: 2px;
}

/* Coins de commande (8px) : c'est un bouton, pas un contenant. Blanc sur sombre
   plutôt que la couleur d'un univers — le pied appartient aux trois. */
.petlib-newsletter-bouton {
    flex: none;
    padding: 12px 24px;

    background-color: #fff;
    border: 0;
    border-radius: 8px;
    color: #1f1f1f;
    font-family: var(--petlib-font-texte);
    font-size: 1rem;
    font-weight: 700;

    cursor: pointer;
    transition: background-color .2s ease;
}

.petlib-newsletter-bouton:hover,
.petlib-newsletter-bouton:focus {
    background-color: #d0d0d0;
}

@media (prefers-reduced-motion: reduce) {
    .petlib-newsletter-bouton {
        transition: none;
    }
}

@media (min-width: 768px) {
    .petlib-newsletter {
        flex-direction: row;
        align-items: center;
        justify-content: space-between;
        gap: 40px;
    }

    .petlib-newsletter-titre {
        font-size: 1.5rem;
    }

    .petlib-newsletter-form {
        flex: 0 1 440px;
        flex-wrap: nowrap;
    }
}

/*    PIED DE PAGE - LES QUATRE COLONNES     */

.petlib-pied-colonnes {
    display: grid;
    grid-template-columns: 1fr;
    gap: 32px;
}

.petlib-pied-titre {
    margin: 0 0 16px;
    color: #fff;
    font-size: 1rem;
    line-height: 1.25;
}

.petlib-pied-liste {
    display: flex;
    flex-direction: column;
    gap: 10px;

    margin: 0;
    padding: 0;

    list-style: none;
    font-size: 0.9375rem;
    line-height: 1.5;
}

/* max-width plutôt qu'une largeur seule : en deux colonnes le conteneur descend
   sous 180px, et le logo en débordait. */
.petlib-pied-logo {
    display: block;
    width: 180px;
    max-width: 100%;
    height: auto;
    margin-bottom: 16px;
}

.petlib-pied-presentation {
    margin: 0 0 16px;
    font-size: 0.9375rem;
    line-height: 1.6;
}

/* Les trois portes, chacune sa lumière. Pastilles et non liens nus : sur un fond
   sombre, un mot coloré seul se lit mal, un aplat le détache. */
.petlib-pied-univers {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;

    margin: 0;
    padding: 0;

    list-style: none;
}

.petlib-pied-univers-lien {
    display: inline-block;
    padding: 6px 16px;

    border-radius: 999px;
    font-size: 0.8125rem;
    font-weight: 700;
    letter-spacing: .04em;
    text-transform: uppercase;
}

/* Les versions pour fond sombre, pas les secondaires : sur le #1f1f1f du pied,
   ceux-ci descendent jusqu'à 1,73:1 pour le chien.
   Sélecteur doublé : « .site-info a » plus haut est en (0,1,1) et l'emporterait
   sur une classe seule, laissant les trois liens au gris commun du pied. */
.site-info a.petlib-pied-univers-chien {
    color: var(--petlib-chien-inverse);
}

.site-info a.petlib-pied-univers-chat {
    color: var(--petlib-chat-inverse);
}

.site-info a.petlib-pied-univers-nac {
    color: var(--petlib-nac-inverse);
}

.petlib-pied-coordonnees {
    gap: 8px;
}

/* Deux colonnes d'abord, quatre seulement à partir de 1100px : à quatre dès
   768px chacune tombait à 121px, largeur à laquelle « Condition générale de
   vente » se replie sur quatre lignes. Même palier que le bloc éditorial de la
   page d'univers. */
@media (min-width: 768px) {
    .petlib-pied-colonnes {
        grid-template-columns: repeat(2, 1fr);
        gap: 32px 40px;
    }
}

@media (min-width: 1100px) {
    .petlib-pied-colonnes {
        grid-template-columns: 1.4fr 1fr 1fr 1.2fr;
        gap: 40px;
    }
}

/*    PIED DE PAGE - BARRE DU BAS     */

.petlib-pied-bas {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 16px;

    padding-top: 24px;
    margin-top: 32px;

    border-top: 1px solid #3a3a3a;
    font-size: 0.8125rem;
}

/* Le composant des moyens de paiement pose ses propres marges, utiles au panier
   et à la fiche produit, superflues sur une barre déjà espacée. */
.petlib-pied-bas .petlib-moyens-paiement {
    margin: 0;
}

@media (min-width: 768px) {
    .petlib-pied-bas {
        flex-direction: row;
        align-items: center;
        justify-content: space-between;
    }
}

/*    PAGE D'UNIVERS - TITRE DE REPLI     */

/* Sert tant qu'un univers n'a pas de hero. Mêmes valeurs que le titre du hero,
   sans sa photo ni son voile : c'est le même niveau de discours, pas le même
   composant. Il disparaît de lui-même le jour où le hero est renseigné. */
.petlib-titre-univers-texte {
    margin: 0;
    color: var(--petlib-univers-color);
    font-size: 2rem;
    line-height: 1.15;
}

@media (min-width: 768px) {
    .petlib-titre-univers-texte {
        font-size: 2.75rem;
    }
}

/*    ACCUEIL - ENCART DE SELECTION     */

.petlib-selection-accueil {
    padding: 8px 0 40px;
}

/* Pas de couleur d'univers ici : l'accueil est le couloir qui mène aux trois
   maisons, il n'en porte aucune — c'est la Règle d'une Seule Maison. Le titre
   prend donc l'encre du site. */
.petlib-selection-accueil-titre {
    margin: 0 0 16px;
    color: var(--petlib-encre, #111);
    font-size: 1.75rem;
    line-height: 1.2;
    text-align: center;
}

/* Deux colonnes en mobile, quatre dès la tablette. La grille commune passe par
   trois colonnes entre 768 et 992px : avec exactement quatre produits, ça
   laissait une carte orpheline sur la seconde ligne. */
body.petlib-accueil .petlib-selection-accueil ul.products {
    grid-template-columns: repeat(2, 1fr);
}

/* Titre et prix des cartes prennent « --petlib-univers-color » avec « inherit »
   en repli. Sur l'accueil, qui n'a pas de couleur d'univers, ce repli les faisait
   hériter du lien qui les enveloppe — donc du bleu par défaut du navigateur. On
   pose l'encre du site, comme le veut le couloir.
   Scopé au body et non à un encart : l'accueil porte deux grilles de produits,
   les coups de cœur et les nouveautés, et toute grille qu'il portera demain
   aura le même besoin. */
body.petlib-accueil ul.products li.product .woocommerce-loop-product__title,
body.petlib-accueil ul.products li.product .price {
    color: var(--petlib-encre, #111);
}

body.petlib-accueil ul.products li.product a {
    text-decoration: none;
}

@media (min-width: 768px) {
    .petlib-selection-accueil {
        padding: 16px 0 56px;
    }

    .petlib-selection-accueil-titre {
        margin-bottom: 24px;
        font-size: 2.25rem;
    }

    body.petlib-accueil .petlib-selection-accueil ul.products {
        grid-template-columns: repeat(4, 1fr);
    }
}

/*    ACCUEIL - ENCART BIEN-ETRE     */

.petlib-bienetre-accueil {
    padding: 8px 0 40px;
}

.petlib-bienetre-accueil-titre {
    margin: 0 0 20px;
    color: var(--petlib-encre, #111);
    font-size: 1.75rem;
    line-height: 1.2;
    text-align: center;
}

/* Le cadre porte le rayon et masque le débordement : c'est lui qui recadre,
   l'image se contente de le remplir.
   position: relative pour que la bulle s'y cale. */
/* C'est le cadre qui porte le rapport d'image, pas la photo — même motif que les
   cartes de catégorie. Laissée à son dimensionnement intrinsèque, l'image sortait
   à 1376x1500 au lieu de 1376x589 : un « height: 100% » sur un remplacé dont le
   parent n'a pas de hauteur définie ne se résout pas de façon fiable. Un rapport
   posé sur le cadre lève toute ambiguïté, et réserve la place avant le
   chargement.
   4/3 en mobile : l'original fait 2,33 de rapport, soit 150px de haut sur un
   écran de 390px — la bulle y aurait couvert toute l'image. */
.petlib-bienetre-accueil-visuel {
    position: relative;
    aspect-ratio: 4 / 3;
    margin: 0;
    overflow: hidden;

    border-radius: 16px;
}

/* GeneratePress impose « height: auto » à toute image des pages WooCommerce ;
   ce sélecteur est à égalité de spécificité et l'emporte par l'ordre de
   chargement, la feuille enfant venant après celle du parent. L'image ne fait
   que remplir le cadre, qui décide seul de la forme. */
.petlib-bienetre-accueil .petlib-bienetre-accueil-visuel img {
    display: block;
    width: 100%;
    height: 100%;

    object-fit: cover;
    object-position: center;
}

/* La bulle. Blanc cassé du site, légèrement translucide pour que la photo
   respire dessous sans jamais gêner la lecture ; coins très arrondis ; ombre au
   seuil du perceptible. Aucune bordure : le trait noir de la BD est justement
   ce qu'on ne veut pas. */
.petlib-bulle {
    position: absolute;
    top: 12px;
    right: 12px;
    z-index: 1;

    /* 70 % : en dessous, le message passe sur trois lignes alors qu'il en demande
       deux. C'est cette contrainte, et non l'encombrement, qui fixe la largeur en
       mobile — la bulle y couvre déjà moins d'un cinquième du cadre. */
    max-width: 70%;
    padding: 11px 14px;

    /* 85 % d'opacité et non 92 : la scène transparaît davantage, la bulle s'y
       pose au lieu de flotter au-dessus. L'encre reste pleine — c'est le fond
       qui s'intègre, pas le texte, qui doit rester lisible sur une photo dont on
       ne maîtrise ni le cadrage ni la luminosité.
       L'ombre passe de 16px à 10px et de 12 % à 7 % : elle ne fait plus que
       décoller la bulle, elle ne la souligne plus. */
    background-color: rgba(248, 244, 238, .85);
    border-radius: 18px;
    box-shadow: 0 2px 10px rgba(0, 0, 0, .07);
    color: var(--petlib-encre, #111);
    font-family: var(--petlib-font-titre);
    /* 0,875rem plutôt que 0,9375 : le message tient alors en deux lignes dès
       360px, largeur des petits Android. Réduire le texte coûte moins que
       d'élargir la bulle, qui mangerait la photo au moment où elle est déjà la
       plus petite. */
    font-size: 0.875rem;
    font-weight: 800;
    line-height: 1.35;
}

/* La pointe : un carré tourné, coin adouci, posé sous le bord bas gauche de la
   bulle et dirigé vers la scène. Un triangle en « border » aurait donné une
   pointe à angles vifs, en contradiction avec des coins à 20px. Il reprend le
   fond de la bulle, translucidité comprise, donc la jonction ne se voit pas. */
.petlib-bulle::after {
    content: "";
    position: absolute;
    bottom: -5px;
    left: 22px;

    width: 16px;
    height: 16px;

    background-color: rgba(248, 244, 238, .85);
    border-radius: 0 0 4px 0;
    transform: rotate(45deg);
}

@media (min-width: 768px) {
    .petlib-bienetre-accueil {
        padding: 16px 0 56px;
    }

    .petlib-bienetre-accueil-titre {
        margin-bottom: 28px;
        font-size: 2.25rem;
    }

    /* Le cadrage d'origine reprend ses droits : la largeur est là pour lui.
       1916/821 sont les dimensions réelles du fichier — le cadre épouse la photo
       et ne rogne plus rien. */
    .petlib-bienetre-accueil-visuel {
        aspect-ratio: 1916 / 821;
        border-radius: 24px;
    }

    /* Environ 12 % de moins qu'avant, sur la largeur comme sur le corps du texte :
       à 320px et 1,0625rem, la bulle pesait presque autant que la scène. */
    .petlib-bulle {
        top: 28px;
        right: 28px;

        max-width: 280px;
        padding: 14px 18px;

        border-radius: 20px;
        font-size: 0.9375rem;
    }
}

/*    ACCUEIL - REASSURANCE     */

.petlib-reassurance-accueil {
    padding-bottom: 40px;
}

@media (min-width: 768px) {
    .petlib-reassurance-accueil {
        padding-bottom: 56px;
    }
}

/*    ACCUEIL - TITRE DE LA REASSURANCE     */

/* Le composant pose sa marge haute et son filet de séparation, utiles quand il
   ferme une fiche produit. Sous un titre d'encart ils ouvriraient un trait entre
   le titre et ses vignettes : ils sont neutralisés, et c'est la section qui
   porte l'espacement. Même parti que l'encart des engagements d'un univers. */
.petlib-reassurance-accueil .petlib-reassurance {
    margin-top: 0;
    padding-top: 0;
    border-top: 0;
}

.petlib-reassurance-accueil-titre {
    margin: 0 0 20px;
    color: var(--petlib-encre, #111);
    font-size: 1.75rem;
    line-height: 1.2;
    text-align: center;
}

/*    ACCUEIL - CARROUSEL DES NOUVEAUTES     */

.petlib-nouveautes-accueil {
    padding-bottom: 40px;
}

.petlib-nouveautes-accueil-titre {
    margin: 0 0 20px;
    color: var(--petlib-encre, #111);
    font-size: 1.75rem;
    line-height: 1.2;
    text-align: center;
}

/* La liste de produits est une grille CSS partout ailleurs ; ici c'est Slick qui
   pose la mise en page, et une grille l'en empêcherait. Le display est donc
   rendu au bloc, et les gouttières passent des « gap » de la grille à un
   rembourrage sur chaque vignette — Slick calcule des largeurs, pas des
   gouttières. */
body.petlib-accueil .petlib-nouveautes-accueil ul.products {
    display: block;
    gap: 0;
}

body.petlib-accueil .petlib-nouveautes-accueil ul.products li.product {
    height: auto;
    margin: 0 8px;
}

/* Slick étire ses vignettes à la hauteur de la piste : sans cette hauteur
   pleine, une carte au titre court flotterait au-dessus du vide au lieu de
   caler son bouton en bas comme les autres. */
body.petlib-accueil .petlib-nouveautes-accueil .slick-track {
    display: flex;
    align-items: stretch;
}

body.petlib-accueil .petlib-nouveautes-accueil .slick-slide {
    height: auto;
}

/* La pagination reprend celle des autres carrousels du thème. */
.petlib-nouveautes-accueil .slick-dots {
    position: static;
    margin-top: 16px;
}

@media (min-width: 768px) {
    .petlib-reassurance-accueil-titre,
    .petlib-nouveautes-accueil-titre {
        margin-bottom: 28px;
        font-size: 2.25rem;
    }

    .petlib-nouveautes-accueil {
        padding-bottom: 56px;
    }

    body.petlib-accueil .petlib-nouveautes-accueil ul.products li.product {
        margin: 0 12px;
    }
}

/*    ACCUEIL - FLECHES DU CARROUSEL DES NOUVEAUTES     */

/* Posées à l'intérieur de la piste et non à l'extérieur : le conteneur ne garde
   que 12px de marge à 768px, des flèches débordantes auraient créé un
   défilement horizontal. Elles chevauchent donc la première et la dernière
   vignette, ce qu'un fond blanc franc rend lisible.
   Calées à 34 % de la hauteur, soit au milieu de la bande d'image : à 50 % elles
   seraient tombées sur le titre et le prix. */
.petlib-carrousel-fleche {
    position: absolute;
    top: 34%;
    z-index: 2;

    display: flex;
    align-items: center;
    justify-content: center;
    width: 40px;
    height: 40px;
    padding: 0;

    background-color: #fff;
    border: 1px solid var(--petlib-trait-creme, #ece6dd);
    border-radius: 50%;
    box-shadow: 0 2px 8px rgba(0, 0, 0, .12);
    color: var(--petlib-encre, #111);
    font-size: 1.125rem;
    line-height: 1;

    cursor: pointer;
    transition: background-color .2s ease, box-shadow .2s ease;
}

.petlib-carrousel-fleche:hover,
.petlib-carrousel-fleche:focus-visible {
    background-color: var(--petlib-papier-creme, #f8f4ee);
    box-shadow: 0 6px 16px rgba(0, 0, 0, .16);
}

.petlib-carrousel-fleche--prec {
    left: 4px;
}

.petlib-carrousel-fleche--suiv {
    right: 4px;
}

/* Slick masque ses flèches en leur posant « display: none » quand un bloc
   responsive les désactive ; la nôtre est en flex, il faut le lui redire. */
.petlib-carrousel-fleche.slick-hidden {
    display: none;
}

@media (prefers-reduced-motion: reduce) {
    .petlib-carrousel-fleche {
        transition: none;
    }
}

/*    DEBORDEMENT HORIZONTAL     */

/* Les décors pleine largeur du thème sont dimensionnés en « 100vw », unité qui
   compte la barre de défilement alors que la zone visible ne l'a pas : ils
   dépassent donc de quelques pixels et ouvrent une barre horizontale sur toute
   la page. C'est le cas du fond du carrousel des univers en accueil.

   « clip » et non « hidden » : les deux coupent le débordement, mais « hidden »
   fait du body un conteneur de défilement et casserait toute « position: sticky »
   descendante — la colonne d'introduction de la FAQ des fiches produit en est
   une. « clip » coupe sans créer ce conteneur.

   Posé sur « html » et non sur « body » : la règle de propagation du débordement
   ne remonte au document que si les deux axes du body sont concernés, et un
   « overflow-x » posé sur le seul body laissait la barre horizontale intacte —
   mesuré. Sur html, le débordement tombe à zéro et l'axe vertical passe en
   « auto », donc la barre de défilement de la page reste. */
html {
    overflow-x: clip;
}

/*    ACCUEIL - JONCTION AVEC L'EN-TETE     */

/* GeneratePress pose 20px de marge haute sur « .site-main », utiles quand la page
   ouvre sur du texte. L'accueil ouvre sur un décor pleine largeur : cette marge y
   laissait une bande de fond entre l'en-tête et le carrousel des univers. */
body.petlib-accueil .site-main {
    margin-top: 0;
}

/*    ACCUEIL - FAQ     */

/* Toute la mise en page de « petlib-faq » vient de la fiche produit, où elle
   tient sur deux colonnes. Sur l'accueil elle se déploie sur toute la largeur :
   seuls le titre et l'espacement sont à déclarer, l'accordéon arrive du
   composant commun. */
.petlib-faq-accueil {
    padding-bottom: 48px;
}

.petlib-faq-accueil .petlib-faq-titre {
    margin: 0 0 20px;
    color: var(--petlib-encre, #111);
    font-size: 1.75rem;
    line-height: 1.2;
    text-align: center;
}

@media (min-width: 768px) {
    .petlib-faq-accueil {
        padding-bottom: 64px;
    }

    .petlib-faq-accueil .petlib-faq-titre {
        margin-bottom: 28px;
        font-size: 2.25rem;
    }
}

/*    SUIVI DE COMMANDE     */

/* Le formulaire vient du shortcode [woocommerce_order_tracking], rendu tel quel
   par WooCommerce : rien n'est surchargé côté template, seul l'habillage est
   repris ici. La largeur est plafonnée parce que deux champs et un bouton posés
   sur 1376px se perdent — la mesure de lecture vaut aussi pour un formulaire. */
.woocommerce form.track_order {
    max-width: 44rem;
}

.woocommerce form.track_order > p:first-of-type {
    margin-bottom: 24px;
    line-height: 1.6;
}

/* Les deux champs côte à côte au-dessus du seuil, empilés en dessous. WooCommerce
   les flotte par « form-row-first » et « form-row-last » ; une grille reprend la
   main et évite le « clear » qui suit. */
.woocommerce form.track_order .form-row {
    float: none;
    width: auto;
    margin: 0 0 16px;
    padding: 0;
}

.woocommerce form.track_order .clear {
    display: none;
}

.woocommerce form.track_order label {
    display: block;
    margin-bottom: 6px;

    font-family: var(--petlib-font-titre);
    font-size: 0.9375rem;
    font-weight: 800;
}

/* Même champ que celui de la newsletter et des filtres : coins de commande,
   trait crème, fond blanc. */
.woocommerce form.track_order .input-text {
    width: 100%;
    padding: 12px 16px;

    background-color: #fff;
    border: 1px solid var(--petlib-trait-creme, #ece6dd);
    border-radius: 8px;
    color: var(--petlib-encre, #111);
    font-family: var(--petlib-font-texte);
    font-size: 1rem;
}

.woocommerce form.track_order .input-text:focus {
    border-color: var(--petlib-encre-douce, #6b625a);
    outline: 2px solid transparent;
    outline-offset: 2px;
}

.woocommerce form.track_order .input-text::placeholder {
    color: var(--petlib-encre-douce, #6b625a);
}

/* Bouton de commerce : le dégradé graphite et le liseré noir de l'ajout au
   panier. Suivre une commande est une action de commerce, pas de découverte —
   c'est la séparation posée par le référentiel. */
.woocommerce form.track_order button.button {
    display: inline-block;
    margin-top: 8px;
    padding: 12px 28px;

    background: linear-gradient(135deg, #404040 0%, #2d2d2d 45%, #1f1f1f 100%);
    border: 1px solid #000;
    border-radius: 8px;
    color: #fff;
    font-family: var(--petlib-font-texte);
    font-size: 1rem;
    font-weight: 700;

    cursor: pointer;
    transition: filter .2s ease;
}

.woocommerce form.track_order button.button:hover,
.woocommerce form.track_order button.button:focus-visible {
    filter: brightness(.75);
}

@media (prefers-reduced-motion: reduce) {
    .woocommerce form.track_order button.button {
        transition: none;
    }
}

@media (min-width: 768px) {
    /* Les deux champs partagent la ligne. Le bouton reprend la largeur pleine
       en dessous : il ferme le formulaire, il n'est pas un troisième champ. */
    .woocommerce form.track_order {
        display: grid;
        grid-template-columns: 1fr 1fr;
        column-gap: 20px;
    }

    .woocommerce form.track_order > p:first-of-type,
    .woocommerce form.track_order .form-row:last-of-type {
        grid-column: 1 / -1;
    }
}

/*    FORMULAIRE DE CONTACT (Contact Form 7)     */

/* Le formulaire est monté en administration, dans Contact Form 7 : le thème n'en
   décrit que l'habillage. Les sélecteurs portent sur « .wpcf7 » et sur les types
   de champs plutôt que sur des classes propres au formulaire, pour qu'un champ
   ajouté en administration soit habillé sans toucher au CSS. */
.wpcf7 .petlib-cf7-champ {
    margin: 0 0 18px;
}

.wpcf7 .petlib-cf7-champ label {
    display: block;
    margin-bottom: 6px;

    font-family: var(--petlib-font-titre);
    font-size: 0.9375rem;
    font-weight: 800;
}

/* « facultatif » se lit comme une mention, pas comme une partie du libellé. */
.wpcf7 .petlib-cf7-facultatif {
    color: var(--petlib-encre-douce, #6b625a);
    font-family: var(--petlib-font-texte);
    font-size: 0.8125rem;
    font-weight: 400;
    text-transform: lowercase;
}

/* Mêmes champs que le suivi de commande, la newsletter et les filtres : un seul
   dessin de champ dans tout le site. */
.wpcf7 input[type="text"],
.wpcf7 input[type="email"],
.wpcf7 input[type="tel"],
.wpcf7 input[type="url"],
.wpcf7 input[type="number"],
.wpcf7 input[type="date"],
.wpcf7 select,
.wpcf7 textarea {
    width: 100%;
    padding: 12px 16px;

    background-color: #fff;
    border: 1px solid var(--petlib-trait-creme, #ece6dd);
    border-radius: 8px;
    color: var(--petlib-encre, #111);
    font-family: var(--petlib-font-texte);
    font-size: 1rem;
    line-height: 1.5;
}

.wpcf7 textarea {
    min-height: 160px;
    resize: vertical;
}

.wpcf7 input:focus,
.wpcf7 select:focus,
.wpcf7 textarea:focus {
    border-color: var(--petlib-encre-douce, #6b625a);
    outline: 2px solid transparent;
    outline-offset: 2px;
}

/* Champ en erreur : la bordure suffit à le désigner, le message se place en
   dessous. Rouge et non couleur d'univers — une erreur n'appartient à aucune
   maison. */
.wpcf7 .wpcf7-not-valid {
    border-color: #b3261e;
}

.wpcf7 .wpcf7-not-valid-tip {
    display: block;
    margin-top: 6px;

    color: #b3261e;
    font-size: 0.875rem;
}

/* Bouton de commerce : envoyer un message au service client relève de l'achat,
   pas de la découverte. Même dessin que « Suivre » et « Ajouter au panier ». */
.wpcf7 .wpcf7-submit {
    display: inline-block;
    padding: 12px 28px;

    background: linear-gradient(135deg, #404040 0%, #2d2d2d 45%, #1f1f1f 100%);
    border: 1px solid #000;
    border-radius: 8px;
    color: #fff;
    font-family: var(--petlib-font-texte);
    font-size: 1rem;
    font-weight: 700;

    cursor: pointer;
    transition: filter .2s ease;
}

.wpcf7 .wpcf7-submit:hover,
.wpcf7 .wpcf7-submit:focus-visible {
    filter: brightness(.75);
}

.wpcf7 .petlib-cf7-envoi {
    margin: 24px 0 0;
}

/* Bandeau de réponse. Contact Form 7 le borde d'un trait de 2px aux couleurs
   crues du plugin ; on le repasse au langage du thème — carte, coin de
   contenant, trait crème, et une seule couleur pour dire l'état. */
.wpcf7 form .wpcf7-response-output {
    margin: 20px 0 0;
    padding: 14px 18px;

    background-color: #fff;
    border: 1px solid var(--petlib-trait-creme, #ece6dd);
    border-left-width: 4px;
    border-radius: 12px;
    font-size: 0.9375rem;
    line-height: 1.5;
}

.wpcf7 form.sent .wpcf7-response-output {
    border-left-color: #2e7d32;
}

.wpcf7 form.invalid .wpcf7-response-output,
.wpcf7 form.unaccepted .wpcf7-response-output,
.wpcf7 form.failed .wpcf7-response-output,
.wpcf7 form.aborted .wpcf7-response-output,
.wpcf7 form.spam .wpcf7-response-output {
    border-left-color: #b3261e;
}

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

/*    PAGES DE CONTENU - MENTIONS ET POLITIQUES     */

/* Une page de texte long sur toute la largeur du conteneur donne des lignes de
   150 caractères : l'œil perd le début de la ligne suivante. Le texte est donc
   plafonné à une mesure lisible.

   « :not(:has(.wp-block-columns)) » épargne les pages bâties en colonnes — la
   page Contact en est une : son formulaire et ses coordonnées se partagent déjà
   la largeur, les plafonner une seconde fois les écraserait. */
body.page .entry-content:not(:has(.wp-block-columns)) {
    max-width: 46rem;
}

/* Encadré d'avertissement. Carte à part, filet ambré sur le bord gauche : il ne
   se lit pas comme du contenu contractuel mais comme une note de chantier, et
   il disparaîtra avec elle. */
.petlib-avertissement {
    padding: 16px 20px;
    margin-bottom: 32px;

    background-color: #fff;
    border: 1px solid var(--petlib-trait-creme, #ece6dd);
    border-left: 4px solid var(--petlib-nac-secondary, #b8560f);
    border-radius: 12px;
    font-size: 0.9375rem;
    line-height: 1.6;
}

/* Sommaire. Sur douze articles, il évite de faire défiler la page pour trouver
   la médiation ou l'hébergeur. */
.petlib-sommaire {
    padding: 20px 24px;
    margin-bottom: 40px;

    background-color: #fff;
    border: 1px solid var(--petlib-trait-creme, #ece6dd);
    border-radius: 12px;
}

/* WordPress glisse un « inner-container » dans tout bloc de groupe et lui pose
   40px de rembourrage : il s'ajoutait aux 24px de la carte, décalant le sommaire
   de 65px de son bord. La carte porte le rembourrage, l'enveloppe interne n'en a
   pas besoin. */
.petlib-sommaire .wp-block-group__inner-container {
    padding: 0;
}

.petlib-sommaire h2 {
    margin: 0 0 12px;
    font-size: 1rem;
    letter-spacing: .04em;
    text-transform: uppercase;
}

.petlib-sommaire ul {
    display: grid;
    grid-template-columns: 1fr;
    gap: 6px 24px;

    margin: 0;
    padding: 0;

    list-style: none;
}

.petlib-sommaire a {
    display: flex;
    gap: 10px;

    color: var(--petlib-encre, #111);
    font-size: 0.9375rem;
    line-height: 1.4;
    text-decoration: none;
}

.petlib-sommaire a:hover,
.petlib-sommaire a:focus-visible {
    text-decoration: underline;
}

/* Le numéro tient une colonne fixe : les intitulés s'alignent tous sur la même
   verticale, quel que soit le nombre de caractères du chiffre romain. */
.petlib-sommaire-numero {
    flex: none;
    width: 2.5em;

    color: var(--petlib-encre-douce, #6b625a);
    font-variant-numeric: tabular-nums;
}

/* Titre d'article : le numéro à côté de l'intitulé, en couleur atténuée. Il se
   lit comme un repère et non comme le début de la phrase — « VIII. Liens
   hypertextes » se lisait d'un bloc.
   Alignement sur la ligne de base, pour que le numéro, plus petit, pose sur la
   même ligne que le titre au lieu de flotter au-dessus. */
h2.petlib-article {
    display: flex;
    flex-direction: row;
    align-items: baseline;
    gap: 12px;

    padding-top: 28px;
    margin-top: 40px;

    border-top: 1px solid var(--petlib-trait-creme, #ece6dd);
}

/* Largeur fixe : les douze intitulés commencent alors sur la même verticale,
   que le chiffre romain fasse une lettre ou quatre. Sans elle, « I » et « VIII »
   décaleraient leur titre de trois caractères. */
.petlib-article-numero {
    flex: none;
    /* En em et non en rem : la réserve suit la taille du numéro. « VIII » est le
       plus large des chiffres romains jusqu'à XII et mesure 1,63 fois son corps ;
       1,8em le contient avec de la marge, et continuera de le contenir si le
       corps change. En rem, toute retouche de la taille désalignait les titres. */
    min-width: 1.8em;

    color: var(--petlib-encre-douce, #6b625a);
    font-size: 2rem;
    line-height: 1.2;
}

.petlib-article-titre {
    font-size: 1.5rem;
    line-height: 1.2;
}

/* Le premier article suit le sommaire : son filet ferait doublon avec la bordure
   de la carte juste au-dessus. */
h2.petlib-article:first-of-type {
    padding-top: 0;
    margin-top: 0;
    border-top: 0;
}

/* Une ancre cliquée doit dégager le titre du bord de l'écran. */
h2.petlib-article {
    scroll-margin-top: 24px;
}

body.page .entry-content li {
    margin-bottom: 6px;
}

@media (min-width: 768px) {
    .petlib-sommaire ul {
        grid-template-columns: 1fr 1fr;
    }

    .petlib-article-titre {
        font-size: 1.75rem;
    }
}
