/*
 * Règles de mise en page du thème Toutdebons.
 * Consomme les variables définies dans tokens.css (chargé avant ce fichier).
 * Breakpoint unique déduit des frames Figma réellement fournies : smartphone
 * 390px / desktop 1920px, point de bascule à 767px (voir tokens.css).
 */

/* MOD-IA 2026-09-02 : reset, conteneur, lien d'évitement, focus visible et
   .screen-reader-text déplacés tel quels vers assets/css/ui/00-base.css
   (aucune valeur changée) dans le cadre du découpage CSS de la charte
   graphique — voir page-charte.php et la règle de routage qui y est décrite. */

/* MOD-IA 2026-09-02 : .btn (+ variantes, .btn__icon, état désactivé) et
   .tdb-badge déplacés tel quels vers assets/css/ui/01-boutons.css (aucune
   valeur changée), même découpage. */

/* ==========================================================================
   En-tête (header.php) — reproduit "header menu secondaire" (539:3602) et
   "menu principal" (121:725) en desktop, "phone menu OK" (2181:3957) et
   "SP - menu site" (435:1952) en mobile.
   ========================================================================== */
.site-header {
    position: relative;
    z-index: 40;
}

.site-header__utility {
    background: var( --color-ink );
    border-radius: 0 0 10px 10px;
}

.site-header__utility-inner {
    display: flex;
    align-items: center;
    justify-content: space-between;
    /* MOD-IA 2026-09-22 : HD2 — le padding vertical de la barre noire passe de
       16px a 20px, valeur relevee dans Figma (voir
       docs/feedback_20260921/00-RELEVE-FIGMA.md §1), ce qui porte la hauteur de
       la barre de 50px a 58px comme dans la maquette.
       ANCIEN CODE : padding-block: var( --space-md ); */
    padding-block: 20px;
}

.site-header__utility-list,
.site-header__utility-links {
    display: flex;
    align-items: center;
    gap: var( --space-2xl );
}

.site-header__utility-list li,
.site-header__utility-links li {
    display: flex;
    align-items: center;
    gap: var( --space-xs );
    color: #fff;
    font-size: 11px;
    font-weight: var( --weight-medium );
    letter-spacing: var( --tracking-tight );
    white-space: nowrap;
}

.site-header__utility-links {
    gap: var( --space-xl );
}

/* Survol "Comment ça marche" / "A propos" (nodes I539:3602;539:3322/3323) :
   le texte blanc passe en orange (réaction ON_HOVER du prototype Figma). */
.site-header__utility-links a {
    transition: color var( --duration-tdb ) var( --ease-tdb );
}

.site-header__utility-links a:hover {
    color: var( --color-primary );
}

/* MOD-IA 2026-09-23 : page d'accueil uniquement (`body.home`) — la barre
   noire n'est plus pleine largeur : fond et arrondi passent sur la boîte
   intérieure, bornée à 1440px avec le padding latéral de 30px du symbole
   Figma « header menu secondaire » (539:3601, relevé §1 HD2). Sous 768px la
   barre est masquée (règle ci-dessous). */
body.home .site-header__utility {
    background: transparent;
    border-radius: 0;
}

body.home .site-header__utility-inner {
    max-width: calc( var( --container-max ) - 2 * var( --space-lg ) );
    padding-inline: 30px;
    background: var( --color-ink );
    border-radius: 0 0 10px 10px;
}

@media ( max-width: 767px ) {
    .site-header__utility {
        display: none; /* Absente des frames Figma "SP" — utilitaire desktop uniquement. */
    }
}

.site-header__main {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var( --space-lg );
    /* MOD-IA 2026-09-21 : G3 — le retrait BAS passe à 0. La maquette pose 50px
       de blanc entre le bas du menu principal et le contenu (menu 108 → 155,
       contenu à 205 sur 1:10, 121:748, 247:1713 — voir
       docs/feedback_20260921/00-RELEVE-FIGMA.md §1), et ce blanc est désormais
       posé une seule fois par `.site-main` (ui/00-base.css). Garder 16px ici
       les ajouterait aux 50px et donnerait 66px.
       Le retrait HAUT reste à 16px : c'est HD2 qui le portera à 50px, et il
       devra écrire `padding-block: 50px 0` — jamais `padding-block: 50px`,
       sous peine de recréer le cumul.
       Le mobile n'est pas concerné : la requête média ci-dessous repose
       `padding-block: 12px` des deux côtés, et le filet `border-bottom` marque
       la limite de l'en-tête, sous laquelle viennent les 25px.
       ANCIEN CODE : padding-block: var( --space-md ); */
    /* MOD-IA 2026-09-22 : HD2 — le retrait HAUT passe de 16px a 50px : la
       maquette pose 50px de blanc entre le bas de la barre noire et le menu
       principal (relevé §1). Écrit en `50px 0` et jamais `50px`, pour ne pas
       recréer le cumul avec les 50px posés par `.site-main`.
       ANCIEN CODE : padding-block: var( --space-md ) 0; */
    padding-block: 50px 50px;
}

.site-header__logo-img--mobile {
    display: none;
}

@media ( max-width: 767px ) {
    .site-header__logo-img--desktop {
        display: none;
    }
    .site-header__logo-img--mobile {
        display: block;
    }
    .site-header__main {
        padding-block: 12px;
        /* MOD-IA 2026-09-01 : filet fin sous l'en-tête mobile, présent dans
           toutes les frames « SP - » (435:1510, 450:1982…) et jusqu'ici absent
           du thème — reste du chore A-4. */
        border-bottom: 1px solid var( --color-border );
    }
}

.site-header__nav {
    flex: 1 0 auto;
    display: flex;
    justify-content: flex-end;
}

.site-header__menu {
    display: flex;
    align-items: center;
    gap: var( --space-sm );
}

.site-header__menu a,
.site-header__menu > li:not(:has(a)) {
    display: flex;
    align-items: center;
    height: 46px;
    padding: 0 var( --space-lg );
    border-radius: var( --radius-sm );
    background: var( --color-surface-muted );
    font-size: var( --text-button-size );
    font-weight: var( --weight-medium );
    letter-spacing: var( --tracking-tight );
    white-space: nowrap;
    transition: background-color var( --duration-tdb ) var( --ease-tdb );
}

/* Survol des pastilles du menu principal (nodes I121:725;120:587/588/589) :
   fond gris → fond orange plein (réaction ON_HOVER du prototype Figma). */
.site-header__menu a:hover {
    background: var( --color-primary );
}

.site-header__actions {
    display: flex;
    align-items: center;
    gap: var( --space-md );
    /* MOD-IA 2026-09-29 : MD12 — reste calé à droite quand il est seul dans
       .site-header__main (mode intégré : logo et navigation retirés), sans
       quoi « space-between » le pousserait à gauche. Sans effet sinon. */
    margin-left: auto;
}

/* "BTN shop" (composant 52:267, variantes "neutre" 52:266 / "survol" 52:268).
   Relevé Figma :
     - fond      #F7F7F7 → #FC9728
     - rayon     10px    → 100px (le carré devient un rond)
     - glyphe    #000000 dans les deux états (il ne s'inverse pas)
     - bulles    couleur du fond ; le groupe passe du centre (23,5 ; 23,5) au
                 coin haut-gauche (4,7 ; −0,3) en pivotant de 10,2°
     - pastille  #FC9728 → #FFFFFF
   Le bouton ne rogne pas son contenu (clipsContent = false), les bulles
   sortent donc volontairement de sa surface. */
.site-header__cart {
    position: relative;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 47px;
    height: 47px;
    border-radius: 10px;
    background: var( --color-surface-muted );
    transition:
        background-color var( --duration-spring ) var( --ease-spring ),
        border-radius    var( --duration-spring ) var( --ease-spring );
}

.site-header__cart:hover {
    background: var( --color-primary );
    border-radius: 50%;
}

.site-header__cart-icon {
    display: flex;
    position: relative;
    z-index: 1;
}

.site-header__cart-bubbles {
    position: absolute;
    left: 16px;
    top: 16px;
    width: 15px;
    height: 15px;
    z-index: 2;
    transition: transform var( --duration-spring ) var( --ease-spring );
}

.site-header__cart:hover .site-header__cart-bubbles {
    /* centre du groupe : (23,5 ; 23,5) → (4,7 ; −0,3), rotation Figma +10,2° */
    transform: translate( -18.8px, -23.8px ) rotate( -10.2deg );
}

.site-header__cart-bubble {
    position: absolute;
    border-radius: 50%;
    background: var( --color-surface-muted );
    transition: background-color var( --duration-spring ) var( --ease-spring );
}

.site-header__cart:hover .site-header__cart-bubble {
    background: var( --color-primary );
}

.site-header__cart-bubble--a { left: 0;    top: 9px; width: 4px; height: 4px; } /* Ellipse 5 */
.site-header__cart-bubble--b { left: 11px; top: 0;   width: 4px; height: 4px; } /* Ellipse 7 */
.site-header__cart-bubble--c { left: 7px;  top: 7px; width: 8px; height: 8px; } /* Ellipse 6 */

/* Pastille du panier ("Group 1") : centre (44 ; 3) dans la boîte de 47 px,
   soit un débord de 7 px en haut et à droite. Elle s'inverse au survol. */
.site-header__cart-count {
    position: absolute;
    top: -7px;
    right: -7px;
    z-index: 3;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 20px;
    height: 20px;
    border-radius: 50%;
    background: var( --color-primary );
    color: #000;
    font-size: 10px;
    font-weight: var( --weight-medium );
    transition: background-color var( --duration-spring ) var( --ease-spring );
}

.site-header__cart:hover .site-header__cart-count {
    background: #fff;
}

/* "SP - menu site" (435:1952) : même style que le bouton panier voisin —
   carré arrondi gris clair, barres sombres — pas un carré orange plein. */
.site-header__burger {
    display: none;
    flex-direction: column;
    justify-content: center;
    align-items: center;
    gap: 4px;
    width: 37px;
    height: 37px;
    border-radius: 8px;
    background: var( --color-surface-muted );
    padding: 8px;
}

.site-header__burger span {
    display: block;
    width: 18px;
    height: 2px;
    background: var( --color-ink );
    border-radius: 1px;
}

/* MOD-IA 2026-09-07 : bouton « Mon compte » de la barre d'actions du header
   (voir header.php). Reprend le bouton « Compte » de la production, seul accès
   au back-office pour un commerçant. Aucune frame Figma ne le dessine : on ne
   crée donc pas de style propre, on pose le composant .btn--primary de la
   charte et on se contente de le contraindre à la hauteur de la barre — 37 px,
   celle du panier et du burger — au lieu des 44 px de .btn--small. */
.site-header__account {
    height: 37px;
    padding: 0 var( --space-sm );
}

@media ( max-width: 767px ) {
    .site-header {
        border-bottom: 1px solid var( --color-border );
    }
    .site-header__nav {
        display: none; /* Remplacé par le menu hors-canevas mobile. */
    }
    /* Le menu hors-canevas porte déjà l'entrée « Mon compte » : inutile de
       doubler le lien dans une barre où la place manque. */
    .site-header__account {
        display: none;
    }
    .site-header__burger {
        display: flex;
    }
    .site-header__cart {
        width: 37px;
        height: 42px;
        background: none;
    }
    .site-header__cart-icon {
        display: flex;
        align-items: center;
        justify-content: center;
        width: 37px;
        height: 37px;
        border-radius: 8px;
        background: var( --color-surface-muted );
    }

    /* MOD-IA 2026-09-02 : le survol "carré gris → rond orange" du panier
       desktop (ligne 169 et suivantes) restait actif en mobile — repéré en
       vérifiant les appelants lors du découpage CSS de la charte graphique.
       Sur tactile un ":hover" peut rester "collé" après un tap (Safari iOS
       notamment) : le panier affichait alors un cercle orange débordant de
       la boîte 37×42, par-dessus l'icône grise ci-dessus. Le panier mobile
       n'a pas d'état de survol dans la maquette (450:1982) — on le neutralise. */
    .site-header__cart:hover {
        background: none;
        border-radius: 0;
    }
    .site-header__cart:hover .site-header__cart-bubbles {
        transform: none;
    }
    .site-header__cart:hover .site-header__cart-bubble {
        background: var( --color-surface-muted ); /* couleur de repos, pas celle du survol */
    }
    .site-header__cart:hover .site-header__cart-count {
        background: var( --color-primary ); /* couleur de repos, pas celle du survol (blanc) */
    }

    /* MOD-IA 2026-09-22 : MN2 — « affichage du nombre d'articles dans le panier
       caché sur le picto dans le header » (mobile).

       Défaut repéré à la lecture : la pastille est positionnée par rapport à
       `.site-header__cart`, et son débord de 7px a été relevé sur la boîte
       DESKTOP de 47×47, où elle mord le coin du carré gris. En mobile, ce
       n'est plus `.site-header__cart` qui est visible — il passe à 37×42 et
       perd son fond — mais `.site-header__cart-icon`, le carré gris de 37×37
       centré à l'intérieur. La pastille se retrouvait donc ~9,5px AU-DESSUS du
       carré visible au lieu d'en mordre le coin, poussée dans les 12px de
       retrait de l'en-tête mobile.

       On recale son décalage vertical sur le carré réellement visible :
       (42 − 37) / 2 = 2,5px de décalage, moins les 7px de débord voulus.
       `overflow: visible` est réaffirmé sur les deux boîtes : si un `overflow`
       venait à être posé sur l'une d'elles, il emporterait la pastille — c'est
       l'une des trois causes possibles listées dans la story MN2, et celle
       contre laquelle le commentaire d'origine du bouton met déjà en garde
       (« le bouton ne rogne pas son contenu »).

       ⚠ La cause exacte reste à CONFIRMER EN NAVIGATEUR, panier non vide, en
       390×844 : la story MN2 est marquée [DIAG] et trois causes restaient
       possibles. Ce correctif traite celle qui se démontre à la lecture du
       code ; les deux autres (rognage par un ancêtre, recouvrement par le
       burger) demandent l'inspecteur. */
    .site-header__cart,
    .site-header__cart-icon {
        overflow: visible;
    }

    .site-header__cart-count {
        top: -4.5px;
    }
}

/* ---------- Menu mobile hors-canevas ---------- */
.mobile-menu {
    position: fixed;
    inset: 0;
    z-index: 100;
    background: var( --color-ink );
    overflow-y: auto;
}

.mobile-menu[hidden] {
    display: none;
}

.mobile-menu__panel {
    padding: 20px 15px 40px;
    display: flex;
    flex-direction: column;
    gap: var( --space-2xl );
    min-height: 100%;
}

.mobile-menu__top {
    display: flex;
    align-items: center;
    justify-content: space-between;
}

.mobile-menu__close {
    width: 34px;
    height: 34px;
    border-radius: 8px;
    background: var( --color-primary );
    display: flex;
    align-items: center;
    justify-content: center;
}

.mobile-menu__nav {
    display: flex;
    flex-direction: column;
}

/* MOD-IA 2026-09-01 : le filet passe SOUS chaque entrée, et le pas monte à 63px.
   Relevé sur « SP - menu site » (435:1952) : les libellés sont à y=133, 196,
   259, 322, 385, 448 — un pas de 63 — et chaque entrée, « A propos » comprise,
   est suivie d'un filet. Le thème posait le filet AU-DESSUS, sans rien après la
   dernière entrée, et avec un pas de 54 : les filets paraissaient collés au
   texte au lieu de partager l'interligne. */
/* ANCIEN CODE :
.mobile-menu__nav li {
    padding-top: var( --space-lg );
    border-top: 1px solid rgba(255,255,255,.15);
}
.mobile-menu__nav li:first-child {
    border-top: none;
}
*/
.mobile-menu__nav li {
    padding-block: 19px 18px;
    border-bottom: 1px solid rgba(255,255,255,.15);
}

.mobile-menu__nav li:first-child {
    padding-top: 0;
}

.mobile-menu__nav a {
    color: #fff;
    font-size: 18px;
    font-weight: var( --weight-medium );
}

.mobile-menu__bottom {
    display: flex;
    flex-direction: column;
    /* MOD-IA 2026-09-01 : sans align-items, l'étirement par défaut d'une
       colonne flex donnait un « Accès prestataire » bord à bord. La maquette
       (435:1952) le pose en 164x44, calé à gauche. */
    align-items: flex-start;
    gap: var( --space-xl );
    margin-top: auto;
}

/* La liste des liens légaux, elle, occupe bien toute la largeur. */
.mobile-menu__bottom .mobile-menu__legal {
    align-self: stretch;
}

.mobile-menu__legal li {
    padding-block: 6px;
}

.mobile-menu__legal a {
    color: var( --color-surface-muted );
    font-size: 12px;
    /* MOD-IA 2026-09-01 : pas de 32px dans la maquette (12 de padding + 20
       d'interligne), contre 38 rendus faute d'interligne explicite. */
    line-height: 20px;
}

/* ==========================================================================
   Pied de page (footer.php) — reproduit l'instance Figma "Footer"
   (539:7142 desktop / 2039:3411 mobile).
   ========================================================================== */
.site-footer__top {
    background: var( --color-ink );
}

/* MOD-IA 2026-09-08 : les deux bandeaux du pied de page sont ramenés à 1440 de
   large — vérification de parité desktop du 08.09.2026.

   Le gabarit leur donne la classe `container` (footer.php lignes 33 et 126),
   dont la largeur maximale est de 1488 : 1440 de contenu PLUS ses deux marges
   de 24. Mais ces bandeaux redeclarent leur propre `padding` (122 puis 20/122),
   ce qui écrase celui du conteneur : la boîte colorée occupait donc les 1488
   entiers, là où l'instance « Footer » (539:7142) la donne à 1440, alignée sur
   la bande de contenu du reste du site.

   Le pied de page dépassait ainsi de 24px de chaque côté la grille de la page
   au-dessus de lui — visible sur ses coins arrondis, décalés vers l'extérieur.
   Les colonnes, elles, avaient les bonnes largeurs (220 / 222 / 234 / 217) : ce
   sont leurs écarts qui absorbaient les 48px en trop, à 117 au lieu de 101.

   La largeur maximale est écrite en `calc()` à partir des mêmes variables que
   `.container`, pour qu'un changement de l'une suive dans l'autre. */
.site-footer__top-inner {
    max-width: calc( var( --container-max ) - 2 * var( --space-lg ) );
    background: var( --color-ink );
    border-radius: 10px 10px 0 0;
    padding: 60px 122px;
    display: flex;
    flex-direction: column;
    gap: var( --space-xl );
}

.site-footer__brand-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var( --space-lg );
}

.site-footer__prestataire-desktop {
    margin-inline-start: auto;
}

.site-footer__social-mobile {
    display: none;
}

.site-footer__divider {
    border: none;
    border-top: 1px solid rgba(255,255,255,.2);
    margin: 0;
}

.site-footer__columns {
    display: flex;
    justify-content: space-between;
    gap: var( --space-xl );
    flex-wrap: wrap;
}

.site-footer__col {
    display: flex;
    flex-direction: column;
    gap: var( --space-lg );
    color: #fff;
}

.site-footer__col-title {
    color: var( --color-primary );
    font-size: var( --text-kicker-size );
    font-weight: var( --weight-semibold );
    margin: 0;
}

.site-footer__col--suivre {
    width: 220px;
}

.site-footer__social-icons {
    display: flex;
    gap: 10px;
    margin-top: var( --space-md );
}

.site-footer__social-icons a,
.site-footer__social-mobile a {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 26px;
    height: 26px;
    border-radius: 5px;
    background: #fff;
}

/* MOD-IA 2026-09-21 : H4 — normalisation optique des pictogrammes sociaux.

   Les trois glyphes ne sont PAS carrés dans la maquette (Footer, « Group 23 »
   539:6724) : Facebook 8,25 × 15,45 (nœud 539:6736), LinkedIn 15,07 × 15,04
   (539:6731), X 14,88 × 13,55 (539:6727) — la tuile blanche, elle, fait bien
   26,18 de côté pour les trois.

   Les SVG sont exportés à ces dimensions exactes ET portent
   preserveAspectRatio="none" : le `width="15"` écrit en dur sur Facebook
   (footer.php) l'étirait donc de 1,8× en largeur. C'est tout le « logo FB trop
   grand » du retour client — la boîte n'y est pour rien.

   `object-fit: contain` + largeur libre remettent chaque glyphe à son propre
   ratio, quelle que soit la valeur des attributs — et protègent d'avance
   l'icône Instagram qui remplacera X (H5). */
.site-footer__social-icons a img,
.site-footer__social-mobile a img {
    width: auto;
    object-fit: contain;
}

.site-footer__legal-links {
    display: flex;
    flex-direction: column;
    gap: 4px;
    font-size: 14px;
    font-weight: var( --weight-medium );
}

.site-footer__col--envoi {
    width: 222px;
}

.site-footer__feature {
    display: flex;
    gap: var( --space-sm );
    font-size: 14px;
    font-weight: var( --weight-light );
}

.site-footer__feature strong {
    display: block;
    font-weight: var( --weight-medium );
    margin-bottom: 2px;
}

.site-footer__feature-icon {
    flex-shrink: 0;
    width: 28px;
    height: 28px;
    border-radius: 5px;
    background: var( --color-primary );
    display: flex;
    align-items: center;
    justify-content: center;
}

.site-footer__col--paiement {
    width: 234px;
}

.site-footer__payment-icons {
    display: flex;
    gap: var( --space-md );
    flex-wrap: wrap;
}

.site-footer__payment-badge {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 79px;
    height: 40px;
    border-radius: 5px;
    background: #fff;
    padding: 8px;
}

.site-footer__payment-badge--dark {
    background: #020202;
}

.site-footer__col--contact {
    width: 217px;
}

.site-footer__contact {
    font-size: 14px;
    font-weight: var( --weight-light );
    line-height: 1.57;
    margin: 0;
}

.site-footer__bottom {
    background: var( --color-primary );
}

/* "soutien + ©" (I539:7142;539:6782) : bandeau orange de 76,6 px, padding
   20/122 — le même retrait latéral que le bloc sombre au-dessus, pour que
   "Soutenu par" s'aligne sur le logo et la colonne "Suivez-nous". */
/* MOD-IA 2026-09-08 : même remise à 1440 que le bandeau sombre au-dessus —
   voir le commentaire complet là-bas. « soutien + © » fait 1440x76,6 dans
   l'instance Figma. */
.site-footer__bottom-inner {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var( --space-xl );
    max-width: calc( var( --container-max ) - 2 * var( --space-lg ) );
    padding: 20px 122px;
    flex-wrap: wrap;
}

/* MOD-IA 2026-09-23 : page d'accueil uniquement (`body.home`), desktop — les
   deux bandeaux du pied de page ne débordent plus en pleine largeur : le fond
   (noir puis orange) passe des bandeaux extérieurs aux boîtes intérieures de
   1440px, comme l'instance Figma « Footer » (539:7142, 1440 de large, 240px de
   blanc de chaque côté en 1920). Le mobile garde ses bandeaux pleine largeur
   (frames « SP » de 390). */
@media ( min-width: 768px ) {
    body.home .site-footer__top,
    body.home .site-footer__bottom {
        background: transparent;
    }
    body.home .site-footer__bottom-inner {
        background: var( --color-primary );
    }
}

.site-footer__partners {
    display: flex;
    align-items: center;
    gap: 42px; /* gap de l'auto-layout "Frame 56" */
}

/* Boîtes relevées une à une sur les nœuds Figma : les trois logos n'ont ni la
   même hauteur ni le même rapport, les dimensionner à hauteur égale (ce qui
   était fait auparavant) les rend tous faux. */
.site-footer__partner {
    display: block;
    flex: none;
    object-fit: cover;
}

/* MOD-IA 2026-09-22 : F1 — les logos sont desormais des liens. Le <a> qui les
   enveloppe est mis en flex et sans interlignage pour ne pas introduire
   l'espace parasite qu'un element en ligne laisse sous une image. */
.site-footer__partner-link {
    display: flex;
    flex: none;
    line-height: 0;
}

.site-footer__partner--valezy    { width: 79px;    height: 29.9px; } /* Rectangle 27 */
.site-footer__partner--passeport { width: 104.9px; height: 36.6px; } /* Rectangle 26 */
.site-footer__partner--tnt       { width: 121px;   height: 19.3px; } /* Rectangle 28 */

.site-footer__partners-label {
    font-size: 10px;
    font-weight: var( --weight-light );
    color: var( --color-ink );
}

.site-footer__copyright {
    font-size: 10px;
    font-weight: var( --weight-light );
    color: var( --color-ink );
    margin: 0;
}

@media ( max-width: 767px ) {
    .site-footer__top-inner {
        padding: 20px 15px 40px;
        gap: var( --space-lg );
    }
    .site-footer__logo {
        width: 117px;
        height: auto;
    }
    .site-footer__prestataire-desktop {
        display: none;
    }
    .site-footer__social-mobile {
        display: flex;
        gap: 10px;
    }
    /* Les icônes sociales vivent déjà dans la barre du haut (.site-footer__
       social-mobile) : le bloc "Suivez-nous" desktop (titre + icônes +
       liens légaux) n'a plus sa place en mobile, la maquette ne le montre pas
       du tout (A-2/A-3). */
    .site-footer__col--suivre {
        display: none;
    }
    /* MOD-IA 2026-09-01 : ce ne sont pas les SECTIONS qui se mettent sur deux
       colonnes, mais le CONTENU de chacune.
       Relevé au bas de « SP - page détail commerçant » (2068:6474) : « Envoi »
       occupe toute la largeur, avec Print@home et Coffret cadeau côte à côte
       en dessous ; puis « Nous contacter » occupe toute la largeur, avec
       e-mail/téléphone et adresse côte à côte ; puis « Mode de paiement ».
       La règle précédente plaçait « Envoi » et « Nous contacter » côte à côte
       comme deux colonnes de premier niveau, chacune empilée à l'intérieur —
       l'inverse de la maquette. Moitié restante du chore A-3. */
    /* ANCIEN CODE :
    .site-footer__columns { display: grid; grid-template-columns: 1fr 1fr; gap: var( --space-lg ); }
    .site-footer__col--envoi   { order: 1; width: auto; }
    .site-footer__col--contact { order: 2; width: auto; }
    .site-footer__col--paiement{ order: 3; grid-column: 1 / -1; width: auto; }
    */
    .site-footer__columns {
        display: flex;
        flex-direction: column;
        gap: var( --space-xl );
    }
    .site-footer__col--envoi,
    .site-footer__col--contact {
        display: grid;
        grid-template-columns: 1fr 1fr;
        column-gap: var( --space-lg );
        row-gap: var( --space-md );
        width: auto;
    }
    .site-footer__col--envoi .site-footer__col-title,
    .site-footer__col--contact .site-footer__col-title {
        grid-column: 1 / -1;
    }
    .site-footer__col--envoi   { order: 1; }
    .site-footer__col--contact { order: 2; }
    .site-footer__col--paiement {
        order: 3;
        width: auto;
    }
    /* MOD-IA 2026-09-08 : les pictos du pied de page sont RÉTABLIS en mobile —
       vérification de parité du 08.09.2026.

       Ils étaient masqués au motif que la capture de « phone footer » ne les
       montrait pas. Le composant lui-même dit l'inverse : dans l'instance
       2039:3649 (pied de page de la frame « SP - page bons commercant »), les
       colonnes « print » et « coffret » contiennent chacune un cadre « picto »
       de 28x28 en tête, le texte venant 40px plus bas.

       La différence avec le desktop n'est donc pas la présence du picto mais sa
       POSITION : au-dessus du texte en mobile, à côté en desktop.

       ANCIEN CODE :
       .site-footer__col--envoi .site-footer__feature-icon {
           display: none;
       } */
    .site-footer__feature {
        flex-direction: column;
        gap: 12px;
    }
    /* Le retrait de 122px n'existe qu'en desktop : il doit être remis à la
       marge mobile, sinon la rangée de logos déborde de l'écran. */
    .site-footer__bottom-inner {
        padding: 15px;
        align-items: flex-start;
    }
    .site-footer__partners {
        flex-wrap: wrap;
        gap: var( --space-md );
    }
    /* Logos réduits proportionnellement (mêmes rapports qu'en desktop) pour
       tenir sur une largeur de 390px. */
    .site-footer__partner--valezy    { width: 63px;   height: 23.9px; }
    .site-footer__partner--passeport { width: 83.9px; height: 29.3px; }
    .site-footer__partner--tnt       { width: 96.8px; height: 15.4px; }
}

/* ==========================================================================
   Page d'accueil (front-page.php)
   ========================================================================== */

/* ---------- Héros ---------- */
/* MOD-IA 2026-09-21 : H1 — la boîte photo s'aligne sur les blocs du dessous.

   Le héros vivait HORS .container : `margin: 0 24px` lui donnait la largeur du
   viewport moins 48px, sans plafond, alors que tout le reste de la page est
   borné à --container-max (1488) moins les 24px de padding, soit 1440 — la
   largeur du conteneur de la maquette (frame homepage 1:10, « elements »).
   Sous 1536px les deux coïncidaient ; en 1920, écran du client, la photo
   débordait franchement des cartes « étapes ».

   On reproduit donc le calcul de .container : même largeur utile, mêmes
   gouttières de 24px sous le plafond.
   ANCIEN CODE :
   margin: 0 var(--space-lg); */
.hero {
    position: relative;
    /* width: calc( 100% - var( --space-lg ) * 2 );
    max-width: calc( var( --container-max ) - var( --space-lg ) * 2 );
    margin-inline: auto; */
    margin: 0 var(--space-lg);
    border-radius: 20px;
    overflow: hidden;
}

/* MOD-IA 2026-09-23 : page d'accueil uniquement (`body.home`) — le héros est
   ramené à 1440px de large, centré, comme la frame Figma « banner image text
   et bloc » (2010:3415, 1440 dans « elements » 6153:6554). Même calcul que
   .container : pleine largeur moins 24px de chaque côté sous le plafond.
   La sauvegarde pleine largeur (page-accueil-pleine-largeur.php) n'a pas la
   classe `home` et garde la règle ci-dessus. */
body.home .hero {
    width: calc( 100% - var( --space-lg ) * 2 );
    max-width: calc( var( --container-max ) - var( --space-lg ) * 2 );
    margin-inline: auto;
}

.hero__media {
    position: absolute;
    inset: 0;
    z-index: 0;
}

.hero__media::after {
    content: "";
    position: absolute;
    inset: 0;
    background: linear-gradient( -57deg, rgba(255,255,255,.3) 12%, rgba(0,0,0,.3) 87% );
    mix-blend-mode: multiply;
}

.hero__media img:not(.hero__motif) {
    width: 100%;
    height: 100%;
    object-fit: cover;
}

.hero__motif {
    position: absolute;
    top: 0;
    right: 0;
    height: 65%;
    width: auto;
    /* Le calque "Intersect" (2010:3415) est un dégradé orange plein exporté
       tel quel de Figma ; son rendu Figma reste un orange vif et net même si
       le calque porte "mix-blend-mode: darken" côté design. Reproduire ce
       blend-mode au sens CSS contre une photo de montagne aussi claire donne
       une teinte olive terne au lieu de l'orange attendu — on affiche donc le
       motif sans blend-mode pour matcher le rendu visuel réel du design. */
    mix-blend-mode: normal;
}

.hero__inner {
    position: relative;
    z-index: 1;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var( --space-xl );
    padding-block: 110px;
    min-height: 684px;
}

.hero__accroche {
    display: flex;
    flex-direction: column;
    gap: var( --space-xl );
    max-width: 720px;
}

.hero__pill {
    display: inline-flex;
    align-items: center;
    gap: var( --space-sm );
    align-self: flex-start;
    height: 48px;
    padding: 0 var( --space-md ) 0 10px;
    border-radius: var( --radius-sm );
    background: rgba(33,33,33,.2);
    border: 1px solid #fff;
    color: #fff;
    font-size: 15px;
    font-weight: var( --weight-medium );
}

.hero__pill-icon {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 28px;
    height: 28px;
    border-radius: 6px;
    background: var( --color-primary );
}

.hero__title {
    color: #fff;
    font-size: var( --text-hero-size );
    line-height: var( --text-hero-lh );
}

/* MOD-IA 2026-09-24 : « Achetons et offrons » ne doit jamais se couper. */
.hero__title-ligne {
    white-space: nowrap;
}

.hero__card {
    position: relative;
    flex-shrink: 0;
    width: 393px;
    max-width: 100%;
    background: rgba(255,255,255,.85);
    border-radius: 20px;
    padding: var( --space-2xl );
    display: flex;
    flex-direction: column;
    gap: var( --space-lg );
}

.hero__dots {
    display: flex;
    align-items: center;
    gap: 8px;
}

.hero__dot {
    width: 12px;
    height: 12px;
    border-radius: 100px;
    background: #d9d9d9;
    padding: 0;
    transition: background-color var( --duration-tdb ) var( --ease-tdb ), width var( --duration-tdb ) var( --ease-tdb );
}

.hero__dot.is-active {
    width: 33px;
    background: var( --color-primary );
}

.hero__dot:hover:not( .is-active ) {
    background: #bdbdbd;
}

/* MOD-IA 2026-09-30 : slides de la carte du héros (template-parts/home/
   hero-slider.php). Toutes les slides occupent la même cellule de grille :
   la carte prend la hauteur de la plus haute et ne « saute » pas au
   changement. Seule la slide active est visible, avec un fondu. */
.hero__slides {
    display: grid;
}

.hero__slide {
    grid-area: 1 / 1;
    display: flex;
    flex-direction: column;
    gap: var( --space-lg );
    opacity: 0;
    visibility: hidden;
    transition: opacity var( --duration-tdb ) var( --ease-tdb ), visibility 0s linear var( --duration-tdb );
}

.hero__slide.is-active {
    opacity: 1;
    visibility: visible;
    transition: opacity var( --duration-tdb ) var( --ease-tdb ), visibility 0s;
}

.hero__card-title {
    color: var( --color-primary );
    font-size: var( --text-h1-size );
    line-height: var( --text-h1-lh );
}

.hero__card-text {
    font-size: var( --text-body-size );
    line-height: var( --text-body-lh );
    margin: 0;
}

@media ( max-width: 767px ) {
    /* MOD-IA 2026-09-21 : H1 — même mécanique qu'en desktop, avec la gouttière
       mobile de 15px du .container.
       ANCIEN CODE :
       margin: 0 15px; */
    .hero {
        width: calc( 100% - 30px );
        margin-inline: auto;
        border-radius: 12px;
    }
    .hero__inner {
        flex-direction: column;
        align-items: stretch;
        padding-block: var( --space-xl ) var( --space-lg );
        min-height: 0;
    }
    .hero__title {
        font-size: var( --text-hero-size-mobile );
        line-height: var( --text-hero-lh-mobile );
    }
    /* MOD-IA 2026-09-01 : l'arabesque est dimensionnée en LARGEUR, pas en
       hauteur. Le SVG « Intersect » fait 636.9 x 501 (ratio 1.27) : une hauteur
       de 65% d'un héros mobile d'environ 765px lui donnait 632px de large dans
       un héros de 360 — ancrée à droite, elle débordait de 270px sur la gauche
       et recouvrait tout le bloc, alors que la maquette la garde dans la moitié
       DROITE. Mesuré sur 435:1510 : la bande occupe x=211→317 entre y=120 et
       y=240, et son bord d'attaque coupe le haut du héros à ~54% de la largeur,
       ce qui correspond à une largeur de motif d'environ 60%. */
    /* ANCIEN CODE (hérité du desktop) : height: 65%; width: auto; */
    .hero__motif {
        width: 60%;
        height: auto;
    }
    .hero__card {
        width: auto;
        padding: var( --space-lg );
    }
    /* MOD-IA 2026-09-01 : le CTA du héros garde sa largeur naturelle (244x44
       dans la maquette mobile) au lieu d'être étiré par le align-items:stretch
       implicite de la colonne flex .hero__card. */
    /* MOD-IA 2026-09-21 : G2 — devenu redondant, `width: fit-content` sur .btn
       (ui/01-boutons.css) traite désormais le cas partout, desktop compris —
       c'est précisément ce que demandait H2, la règle n'existant qu'en mobile.
       ANCIEN CODE :
    .hero__card > .btn {
        align-self: flex-start;
    }
    */
    /* MOD-IA 2026-09-01 : le premier paragraphe est en gras dans la maquette
       (« Quoi de mieux que d'offrir un cadeau… »), le second en graisse
       normale — c'est ce contraste qui hiérarchise le bloc. */
    .hero__card-text:first-of-type {
        font-weight: var( --weight-semibold );
    }
}

/* ==========================================================================
   3 étapes — "box étapes" (6147:6872)

   Chaque carte reprend une instance de composant à deux variantes reliées par
   une réaction ON_HOVER / Smart Animate. Toutes les valeurs ci-dessous sont
   relevées sur les nœuds Figma (centre, taille, rotation absolue, remplissage)
   pour la carte de référence de 463 × 350 px.

   Les décorations sont exprimées en `cqw` — 1cqw = 1 % de la largeur de la
   carte — pour que le collage garde exactement les proportions de la maquette
   quelle que soit la largeur réelle de la colonne. La "scène" décorative est
   ancrée en bas de la carte (comme dans Figma, où le texte est calé en haut et
   les tuiles en bas), ce qui la rend insensible à une hauteur de carte
   supérieure au ratio de la maquette.
   ========================================================================== */
.steps {
    padding-block: var( --space-3xl );
}

.steps__title {
    color: var( --color-primary );
    font-size: var( --text-h1-home-size );
    line-height: var( --text-h1-home-lh );
    margin-bottom: 40px; /* gap de l'auto-layout "box étapes" */
}

.steps__grid {
    display: grid;
    grid-template-columns: repeat( 3, 1fr );
    gap: var( --space-lg ); /* 24px — gap de l'auto-layout "etapes" (6147:6871) */
}

/* MOD-IA 2026-09-02 : .step-card, .step-tile et .step-coin (collage des 3 étapes) déplacé tel quel vers
   assets/css/ui/03-cartes.css (aucune valeur changée) — famille « Cartes »
   de la charte graphique. */

@media ( max-width: 767px ) {
    .steps {
        padding-block: var( --space-xl );
    }
    .steps__title {
        font-size: var( --text-h2-size-mobile );
        line-height: var( --text-h2-lh-mobile );
        margin-bottom: var( --space-lg );
    }
    /* MOD-IA 2026-09-01 : carrousel horizontal au lieu d'une pile verticale.
       "box etapes phone" (6023:8745) aligne 3 cartes de 265x246 espacées de
       15px sur une rangée de 825px de large, donc bien au-delà des 390px de
       la frame : les deux cartes suivantes dépassent volontairement pour
       signaler le défilement. La pile verticale doublait la hauteur de la page
       d'accueil (7170px rendus contre 3328px en maquette).
       Le débord latéral (margin/padding négatifs) laisse la carte suivante
       filer jusqu'au bord de l'écran, comme dans la maquette, au lieu d'être
       coupée par le padding du .container.
       Même motif que .tdb-prestation-grid (fiche commerçant). */
    /* ANCIEN CODE :
    .steps__grid {
        grid-template-columns: 1fr;
    }
    */
    .steps__grid {
        display: flex;
        grid-template-columns: none;
        gap: 15px;
        overflow-x: auto;
        scroll-snap-type: x mandatory;
        scrollbar-width: none;
        margin-inline: -15px;
        padding-inline: 15px;
        /* MOD-IA 2026-09-22 : MN1 — « l'alignement des blocs slider trop a
           gauche, pas d'espace blanc ». Le `padding-inline: 15px` etait bien
           la, mais l'accrochage `scroll-snap` ne le voyait pas : faute de
           `scroll-padding`, le snapport est le bord de la boite de padding et
           la premiere carte se recalait au ras de l'ecran a chaque arret,
           mangeant les 15px. Le `scroll-padding-inline` decale le snapport de
           la meme marge, si bien que la carte s'arrete sur l'axe du titre de
           section au-dessus. */
        scroll-padding-inline: 15px;
    }
    .steps__grid::-webkit-scrollbar {
        display: none;
    }
    /* MOD-IA 2026-09-02 : les règles mobiles de .step-card sont déplacées
       telles quelles vers assets/css/ui/03-cartes.css ; celles de
       .steps / .steps__grid, qui sont de la mise en page, restent ici. */
}

/* ---------- Blocs "Nos promotions" / saisonnier ---------- */
.promo-block {
    padding-block: var( --space-xl );
}

.promo-block__title {
    color: var( --color-primary );
    font-size: var( --text-h1-home-size );
    line-height: var( --text-h1-home-lh );
    margin-bottom: var( --space-2xl );
}

.promo-block__grid {
    display: grid;
    grid-template-columns: repeat( 4, 1fr );
    gap: var( --space-lg );
}

.promo-block__cta {
    display: flex;
    justify-content: flex-end;
    margin-top: var( --space-lg );
}

.promo-block__empty {
    color: var( --color-text-muted );
    font-style: italic;
}

@media ( max-width: 767px ) {
    /* MOD-IA 2026-09-01 : carrousel horizontal au lieu d'une pile verticale.
       "vignette promo" (2033:3541) aligne les cartes "phone box commercant +
       promo" de 265px de large aux abscisses 0 / 281 / 567, soit un écart de
       16px, sur une rangée qui déborde largement les 390px de la frame.
       Concerne "Nos promotions" comme "Pour la fête des mères". */
    /* ANCIEN CODE :
    .promo-block__grid {
        grid-template-columns: 1fr;
    }
    */
    .promo-block__grid {
        display: flex;
        grid-template-columns: none;
        gap: 16px;
        overflow-x: auto;
        scroll-snap-type: x mandatory;
        scrollbar-width: none;
        margin-inline: -15px;
        padding-inline: 15px;
        /* MOD-IA 2026-09-22 : MN1 — « l'alignement des blocs slider trop a
           gauche, pas d'espace blanc ». Le `padding-inline: 15px` etait bien
           la, mais l'accrochage `scroll-snap` ne le voyait pas : faute de
           `scroll-padding`, le snapport est le bord de la boite de padding et
           la premiere carte se recalait au ras de l'ecran a chaque arret,
           mangeant les 15px. Le `scroll-padding-inline` decale le snapport de
           la meme marge, si bien que la carte s'arrete sur l'axe du titre de
           section au-dessus. */
        scroll-padding-inline: 15px;
    }
    .promo-block__grid::-webkit-scrollbar {
        display: none;
    }
    .promo-block__grid > * {
        flex: 0 0 265px;
        scroll-snap-align: start;
    }
    .promo-block__title {
        font-size: var( --text-h2-size-mobile );
        line-height: var( --text-h2-lh-mobile );
        margin-bottom: var( --space-lg );
    }
    /* MOD-IA 2026-09-01 : le CTA garde sa largeur naturelle et reste aligné à
       GAUCHE. La maquette mobile pose « phone BTN mascot orange > noir » en
       244x44 à x=15 dans un conteneur de 390 — pas un bouton bord à bord.
       ANCIEN CODE :
       .promo-block__cta { justify-content: stretch; }
       .promo-block__cta .btn { width: 100%; } */
    .promo-block__cta {
        justify-content: flex-start;
    }
}

/* MOD-IA 2026-09-02 : .tdb-card-commercant (photo, badge, logo, texte, flèche) déplacé tel quel vers
   assets/css/ui/03-cartes.css (aucune valeur changée) — famille « Cartes »
   de la charte graphique. */

/* ---------- Bandeau CTA "Vous êtes commerçant ?" ---------- */
.cta-rejoindre {
    position: relative;
    border-radius: 20px;
    overflow: hidden;
    /* MOD-IA 2026-09-21 : G3 — la marge BASSE disparaît : l'espace avant le
       footer (80px, relevé sur les quatre frames desktop) est désormais posé
       une seule fois par `.site-main` (ui/00-base.css). La garder ici
       l'ajouterait aux 80px et donnerait 112px sur la page d'accueil.
       ANCIEN CODE :
       margin-block: var( --space-xl ); */
    margin-block: var( --space-xl ) 0;
    min-height: 625px;
    display: flex;
    align-items: center;
}

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

/* MOD-IA 2026-09-21 : H6 — note de relevé. Le voile de la maquette est bien
   présent ici (dégradé -54,185°, blancs 11,709 % → noirs 86,935 %, en
   `multiply` par-dessus la photo, nœud 539:4541). Seul `.cta-rejoindre::before`
   le rend réellement : `.cta-rejoindre__bg` est un <img>, un élément remplacé,
   qui n'a jamais de ::after. Le sélecteur est conservé tel quel — il est sans
   effet, pas nuisible — mais il ne faut pas compter dessus. */
.cta-rejoindre__bg::after,
.cta-rejoindre::before {
    content: "";
    position: absolute;
    inset: 0;
    background: linear-gradient( -54deg, rgba(255,255,255,.3) 12%, rgba(0,0,0,.3) 87% );
    mix-blend-mode: multiply;
    z-index: 1;
}

/* MOD-IA 2026-09-21 : H6 — l'arc est ancré EN BAS, plus par le haut.

   Relevé sur « image fond + cercle » 539:4540 : le nœud « Intersect »
   (539:4543) occupe x 644,2 → 1440 et y 236 → 625 dans un bloc de 1440 × 625,
   soit right: 0 / width: 55,26 % / height: 62,24 % — et surtout bottom: 0 :
   dans la maquette, l'arc est l'INTERSECTION d'une ellipse et du bloc, il est
   donc découpé par le bord inférieur.

   Les valeurs `top: 38%` et `width: 55%` tombaient juste à 0,25 % près, mais
   avec une hauteur laissée en auto, tout écart de hauteur du bloc rendu par
   rapport aux 625px de la maquette décollait l'arc du bas. C'est ce que voit
   le client (« placement pas ok »). En l'ancrant en bas, le bas de l'arc reste
   collé au bord quelle que soit la hauteur réelle du bandeau.

   Le blend-mode, lui, est bien celui de la maquette : contrairement au motif
   du héros (voir plus haut), « Intersect » est déclaré en hard-light dans
   Figma — il ne faut PAS le neutraliser ici.
   ANCIEN CODE :
   top: 38%;
   width: 55%; */
.cta-rejoindre__motif {
    position: absolute;
    right: 0;
    bottom: 0;
    width: 55.26%;
    z-index: 1;
    /* mix-blend-mode: hard-light; */
}

.cta-rejoindre__inner {
    position: relative;
    z-index: 2;
    width: 100%;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var( --space-xl );
    padding: 68px 80px;
}

/* Le bloc texte fait 574px dans Figma, mais "Google Sans Flex" y est remplacé
   par "Plus Jakarta Sans", sensiblement plus large : à 574px, "Rejoignez-nous."
   passait à la ligne et le titre s'affichait sur 4 lignes au lieu de 3. La
   largeur est donc portée à 660px pour retrouver le découpage de la maquette. */
.cta-rejoindre__accroche {
    display: flex;
    flex-direction: column;
    gap: var( --space-xl );
    max-width: 660px;
}

/* "bouton rejoindre" (I539:4647;539:4536) — instance du composant
   "BTN bouton orange > blanc" (100:862). Variantes relevées :
     neutre  : fond #FC9728, libellé #000000
     survol  : fond #FFFFFF, libellé #000000 (inchangé)
   Rayon 10px, padding 14/20, gap 8, libellé 14px Medium / interligne 18px.
   Ressort raide propre à ce bouton (raideur 1600 / amortissement 60), soit
   ~0,256 s — quatre fois plus vif que les autres survols de la page. */
.btn--orange-blanc {
    /* MOD-IA 2026-09-21 : G2 — `width: fit-content` sur .btn rend l'align-self
       inutile, le bouton épouse son libellé (189px) de lui-même.
       ANCIEN CODE :
       align-self: flex-start; */
    padding: 0 20px;
    border-radius: 10px;
    background: var( --color-primary );
    color: #000;
    transition: background-color var( --duration-spring-snap ) var( --ease-spring );
}

.btn--orange-blanc:hover {
    background: #fff;
    color: #000;
}

.cta-rejoindre__title {
    color: #fff;
    font-size: var( --text-hero-size );
    line-height: var( --text-hero-lh );
}

.cta-rejoindre__card {
    flex-shrink: 0;
    width: 421px;
    max-width: 100%;
    background: rgba(255,255,255,.9);
    border-radius: 20px;
    padding: var( --space-2xl );
}

.cta-rejoindre__card h3 {
    color: var( --color-primary );
    font-size: var( --text-h1-size );
    line-height: var( --text-h1-lh );
    margin-bottom: var( --space-lg );
}

.cta-rejoindre__card p {
    font-size: var( --text-body-size );
    line-height: var( --text-body-lh );
}

@media ( max-width: 767px ) {
    /* MOD-IA 2026-09-21 : G3 — même raison qu'en desktop, l'espace avant le
       footer (40px en mobile) vient de `.site-main`.
       ANCIEN CODE :
       margin-block: var( --space-lg ); */
    .cta-rejoindre {
        min-height: 0;
        margin-block: var( --space-lg ) 0;
    }
    .cta-rejoindre__inner {
        flex-direction: column;
        align-items: stretch;
        padding: var( --space-xl ) 15px;
    }
    .cta-rejoindre__title {
        font-size: var( --text-hero-size-mobile );
        line-height: var( --text-hero-lh-mobile );
    }
    .cta-rejoindre__card {
        width: auto;
        padding: var( --space-lg );
    }
}

/* ==========================================================================
   Annuaire des commerçants (archive-commercant.php)
   ========================================================================== */
.tdb-banner-bons-valeur {
    display: flex;
    align-items: center;
    justify-content: flex-end;
    gap: 60px;
    background: var( --color-ink );
    border-radius: 20px;
    padding: var( --space-2xl );
    margin-block: var( --space-xl );
}

.tdb-banner-bons-valeur__accroche {
    display: flex;
    /* MOD-IA 2026-09-08 : `min-width: 0` lève la largeur minimale implicite d'un
       élément flex (`auto` = min-content). Sans elle, laisser l'image rétrécir
       ne suffisait pas : le texte reprenait à son compte le minimum du bandeau. */
    min-width: 0;
    flex-direction: column;
    /* MOD-IA 2026-09-01 : même correctif que .mobile-menu__bottom — le bouton
       « J'opte pour un bon valeur » était étiré par le align-items:stretch
       implicite. Maquette (450:1982) : 216x40, aligné à gauche. */
    align-items: flex-start;
    gap: var( --space-md );
    max-width: 444px;
    color: #fff;
}

/* Les paragraphes de l'accroche gardent la pleine largeur du bandeau. */
.tdb-banner-bons-valeur__accroche h2,
.tdb-banner-bons-valeur__accroche p {
    align-self: stretch;
}

.tdb-banner-bons-valeur__accroche h2 {
    color: var( --color-primary );
    font-size: var( --text-h1-size );
    line-height: var( --text-h1-lh );
}

.tdb-banner-bons-valeur__accroche p {
    font-size: var( --text-kicker-size );
    font-weight: var( --weight-semibold );
    margin: 0;
}

.tdb-banner-bons-valeur__image {
    position: relative;
    /* MOD-IA 2026-09-08 : l'image peut désormais RÉTRÉCIR — c'est elle qui
       imposait au bandeau une largeur minimale de 791px (48 + 227 de texte + 60
       de gouttière + 408 d'image + 48), au-delà des 720px disponibles sur une
       tablette en portrait. Elle garde ses 408px comme largeur de départ, donc
       son rendu de 1024px vers le haut ; en dessous elle se réduit, et son
       image de fond — déjà en `position: absolute` recadrée — suit sans se
       déformer. Sous 768px la question ne se pose pas : le bandeau passe en
       colonne et l'image est masquée, absente de la maquette mobile.
       ANCIEN CODE : flex-shrink: 0; */
    flex-shrink: 1;
    width: 408px;
    max-width: 100%;
    height: 243px;
    border-radius: 10px;
    overflow: hidden;
    display: flex;
    align-items: center;
    justify-content: center;
}

.tdb-banner-bons-valeur__image img:first-child {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: cover;
}

.tdb-banner-bons-valeur__smile {
    position: relative;
    width: 150px;
    height: auto;
}

@media ( max-width: 767px ) {
    .tdb-banner-bons-valeur {
        flex-direction: column-reverse;
        gap: var( --space-lg );
        /* MOD-IA 2026-09-08 : 20px haut/bas et 15px gauche/droite, valeurs du
           nœud 450:3608 (le cadre de texte y est à x=15, y=20 dans un bandeau
           de 197 de haut). --space-lg posait 24 partout.
           ANCIEN CODE : padding: var( --space-lg ); */
        padding: 20px 15px;
    }
    .tdb-banner-bons-valeur__image {
        display: none; /* absente de la maquette mobile (450:1982) */
    }

    /* MOD-IA 2026-09-08 : échelle typographique MOBILE du bandeau, absente
       jusqu'ici — vérification de parité du 08.09.2026.

       Le bandeau gardait les tailles du desktop à toutes les largeurs et
       mesurait 242px de haut au lieu des 197 de la maquette (450:3608). Les
       hauteurs relevées nœud par nœud :
         titre    28 (thème : 38, en 32px/38)
         écart    15 (thème : 16)
         texte    60 sur 3 lignes, soit 20 par ligne (thème : 78, en 16px/26)
         écart    14 (thème : 16)
         bouton   216x40 (thème : 227x46)
       Les tailles ci-dessous reproduisent ces hauteurs. */
    .tdb-banner-bons-valeur__accroche {
        gap: 15px;
    }

    .tdb-banner-bons-valeur__accroche h2 {
        font-size: 24px;
        line-height: 28px;
    }

    .tdb-banner-bons-valeur__accroche p {
        font-size: 14px;
        line-height: 20px;
    }

    /* 40px de haut : c'est aussi la hauteur du bouton panier voisin et celle
       des champs de la maquette mobile en général. */
    .tdb-banner-bons-valeur__accroche .btn {
        height: 40px;
    }
}

.tdb-annuaire {
    display: grid;
    /* MOD-IA 2026-09-08 : `minmax( 0, 1fr )` au lieu de `1fr` — débordement
       horizontal repéré le 08.09.2026 entre 768px et 1023px.

       `1fr` vaut en réalité `minmax( auto, 1fr )`, et ce minimum `auto` est la
       largeur min-content du contenu de la colonne. Le bandeau « En panne
       d'idées ? » ne descendant pas sous 791px (voir plus bas), la colonne
       s'étirait à 791 dans un conteneur de 720 et toute la page défilait
       latéralement. `minmax( 0, 1fr )` autorise la colonne à se réduire ; à
       1440 le rendu est identique, la colonne y valant de toute façon 1074.
       ANCIEN CODE : grid-template-columns: 300px 1fr; */
    grid-template-columns: 300px minmax( 0, 1fr );
    gap: 66px; /* sidebar 300 + gouttière 66 + colonne cartes 1074 = 1440 (127:1247 / 2443:3642) */
    padding-block: var( --space-xl ) var( --space-3xl );
    align-items: start;
}

/* "vignettes" (539:7951) : 3 colonnes de 342px espacées de 25px, rangées de
   403px de haut espacées de 25px elles aussi. */
.tdb-annuaire__grid {
    display: grid;
    grid-template-columns: repeat( 3, 1fr );
    gap: 25px;
}

@media ( max-width: 1023px ) {
    .tdb-annuaire {
        /* MOD-IA 2026-09-08 : `minmax( 0, 1fr )`, même raison qu'en desktop. */
        /* ANCIEN CODE : grid-template-columns: 1fr; */
        grid-template-columns: minmax( 0, 1fr );
        /* MOD-IA 2026-09-01 : les 66px sont la GOUTTIÈRE HORIZONTALE du desktop
           (sidebar 300 + 66 + cartes 1074 = 1440). En une seule colonne, ce même
           gap devient un écart VERTICAL et creusait ~95px entre le bouton
           « Afficher sur la carte » et le bandeau.
           Valeur relevée sur 450:1982 : le bloc de filtres finit à y=271, le
           bandeau démarre à 296, les vignettes à 518 alors que le bandeau finit
           à 493 — soit 25px partout, le rythme mobile du reste du site. */
        gap: 25px;
    }
    .tdb-annuaire__grid {
        grid-template-columns: repeat( 2, 1fr );
    }
}

@media ( max-width: 767px ) {
    .tdb-annuaire__grid {
        grid-template-columns: 1fr;
        /* MOD-IA 2026-09-01 : écart de 15px entre cartes. Relevé sur « vignette
           produits » (450:3018) : 4 cartes de 363x283 aux ordonnées 0 / 298 /
           596 / 894, soit un pas de 298 pour une hauteur de 283. */
        gap: 15px;
    }
    /* MOD-IA 2026-09-02 : les règles mobiles de .tdb-card-commercant
       (photo, secteur, lieu, nom) sont déplacées telles quelles vers
       assets/css/ui/03-cartes.css, dans un @media de même condition. */
}

/* ---------- Sidebar de filtres ---------- */
/* "bloc menu préférence" (547:3487) : tous les blocs de la sidebar sont
   espacés de 10px (boutons à y=0/56/112, prix à 168, Afficher à 294…). */
.tdb-filtres {
    display: flex;
    flex-direction: column;
    gap: 10px;
    position: sticky;
    top: var( --space-lg );
}

/* "Frame 368" (539:7943) : le libellé fait 22px de haut, le filet (Line 3)
   est posé 20px plus bas, et le bloc de filtres démarre 40px après le filet. */
.tdb-filtres__title {
    font-size: var( --text-h3-size );
    line-height: var( --text-h3-lh );
    font-weight: var( --weight-semibold );
    color: var( --color-primary );
    text-transform: none;
    letter-spacing: var( --tracking-tight );
    /* 28px + les 12px de gap du conteneur flex = les 40px du design. */
    margin: 0 0 28px;
    padding-bottom: 20px;
    border-bottom: 1px solid var( --color-ink );
}

/* "Filtres complémentaires" (mobile uniquement) : replie Gamme de prix +
   Afficher, dépliés par défaut en desktop (127:1247 n'a que 3 selects visibles
   + le bloc prix/afficher toujours ouvert ; le mobile ajoute un 4e contrôle
   qui les masque tant qu'on ne clique pas dessus). */
.tdb-filtres__complementaires-toggle {
    display: none;
}

.tdb-filtres__complementaires {
    display: flex;
    flex-direction: column;
    gap: var( --space-md );
}

/* MOD-IA 2026-09-30 : panneau des menus déroulants de la sidebar agrandi
   (retour client) — les 280px de ui/02-formulaires.css ne montraient qu'une
   partie des options et forçaient à défiler pour retrouver les cases cochées.
   Limité à la hauteur de l'écran pour ne jamais sortir de la fenêtre ; le
   panneau du widget bon valeur garde les 280px d'origine. */
.tdb-filtres .tdb-dropdown__panel {
    max-height: min( 70vh, 640px );
}

/* MOD-IA 2026-09-30 : lien « Réinitialiser les filtres » (filtres.php),
   affiché seulement quand un filtre est actif. */
.tdb-filtres__reset {
    align-self: flex-start;
    font-size: var( --text-button-size );
    font-weight: var( --weight-medium );
    color: var( --color-ink );
    text-decoration: underline;
    text-underline-offset: 3px;
}

.tdb-filtres__reset:hover,
.tdb-filtres__reset:focus-visible {
    color: var( --color-primary );
}

/* MOD-IA 2026-09-02 : .tdb-dropdown (déclencheur, panneau, variante à filet) déplacé tel quel vers
   assets/css/ui/02-formulaires.css (aucune valeur changée) — famille « Formulaires »
   de la charte graphique. */

/* "TDB bouton defilement gris fleche" (322:3341) — neutre : fond #F7F7F7,
   46px, padding latéral 20px, rayon 10px. Survol/ouvert : fond orange plein
   (#FC9728), le libellé et la flèche restent noirs. */
.tdb-filtres__select {
    appearance: none;
    height: 46px;
    padding: 0 20px;
    border: none;
    border-radius: var( --radius-sm );
    background-color: var( --color-surface-muted );
    background-image: url( '../images/filters/chevron-down.svg' );
    background-repeat: no-repeat;
    background-position: right 20px center;
    background-size: 12px auto;
    font-family: var( --font-body );
    font-size: var( --text-button-size );
    line-height: var( --text-button-lh );
    font-weight: var( --weight-medium );
    letter-spacing: var( --tracking-tight );
    color: var( --color-ink );
    cursor: pointer;
    text-align: left;
    transition: background-color var( --duration-tdb ) var( --ease-tdb );
}

.tdb-filtres__select:hover,
.tdb-filtres__select:focus-visible {
    background-color: var( --color-primary );
}

/* Blocs "gamme prix" (547:3499) et "détail/Afficher" (547:3509) : padding
   20px, 12px entre le titre et les lignes (cases à 34px de pas : 22 + 12). */
.tdb-filtres__block {
    background: var( --color-surface-muted );
    border-radius: var( --radius-sm );
    padding: 20px;
    display: flex;
    flex-direction: column;
    gap: 12px;
}

.tdb-filtres__block-title {
    font-size: var( --text-button-size );
    font-weight: var( --weight-medium );
    margin: 0;
}

.tdb-filtres__price-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    font-size: var( --text-button-size );
    font-weight: var( --weight-medium );
}

.tdb-filtres__price-row--muted {
    font-size: 10px;
    font-weight: var( --weight-light );
    color: var( --color-text-muted );
}

/* MOD-IA 2026-09-02 : .tdb-range (curseur de gamme de prix) déplacé tel quel vers
   assets/css/ui/02-formulaires.css (aucune valeur changée) — famille « Formulaires »
   de la charte graphique. */

/* MOD-IA 2026-09-02 : .tdb-checkbox (case, coche, focus) déplacé tel quel vers
   assets/css/ui/02-formulaires.css (aucune valeur changée) — famille « Formulaires »
   de la charte graphique. */

/* MOD-IA 2026-09-22 : MN4 — même précaution que pour `.tdb-bons-valeur__map`
   ci-dessus : cette mini-carte porte elle aussi un conteneur Leaflet dont les
   panneaux (z-index 400 à 1000) remonteraient au contexte racine sans
   `isolation: isolate`. Elle est masquée en mobile, mais reste au-dessus de
   toute surimpression en desktop. */
.tdb-filtres__carte {
    isolation: isolate;
}

.tdb-filtres__carte {
    display: flex;
    flex-direction: column;
    gap: var( --space-sm );
}

.tdb-filtres__map-preview {
    display: block;
    height: 196px;
    border-radius: var( --radius-sm );
    overflow: hidden;
}

.tdb-filtres__map-preview img {
    width: 100%;
    height: 100%;
    object-fit: cover;
}

/* "Voir sur la carte" (127:1218) : bouton à largeur automatique, aligné à
   gauche — le parent flex column l'étirait par défaut sur toute la sidebar. */
/* MOD-IA 2026-09-21 : G2 — rustine devenue redondante. `width: fit-content`
   sur .btn (ui/01-boutons.css) empêche désormais tout étirement par une
   colonne flex, ici comme ailleurs : le bouton garde sa largeur naturelle
   sans règle de rattrapage. La pleine largeur MOBILE, elle, reste voulue —
   elle passe maintenant par la classe explicite .btn--pleine-largeur-mobile
   posée sur les deux boutons de template-parts/commercant/filtres.php.
   ANCIEN CODE :
.tdb-filtres__carte .btn {
    align-self: flex-start;
}
*/

.tdb-filtres__map-label--mobile {
    display: none;
}

@media ( max-width: 767px ) {
    /* La vignette de carte de la sidebar n'existe pas en mobile (450:1982) —
       seul le bouton "Afficher sur la carte" subsiste. */
    .tdb-filtres__map-preview {
        display: none;
    }
    /* MOD-IA 2026-09-01 : pas de filet sous « Faites votre sélection » en
       mobile. Le filet vient du chore B-3, relevé sur la sidebar DESKTOP
       (539:7943) ; la frame mobile (450:1982) enchaîne directement le titre
       (y=107) et le premier select (y=163). */
    /* ANCIEN CODE (hérité du desktop) : padding-bottom 20px + border-bottom. */
    .tdb-filtres__title {
        padding-bottom: 0;
        border-bottom: none;
        /* Le libellé fait 22px et le bloc de filtres démarre 25px plus bas
           (450:2362 à y=0, « phone filtres bons » à y=47) ; les 8px de gap du
           conteneur flex s'ajoutent à cette marge. */
        margin-bottom: 17px;
    }
    /* MOD-IA 2026-09-01 : rythme des selects resserré. Relevé sur 450:1982 :
       selects à y=163 / 208 / 253 / 298, soit un PAS DE 45px pour une hauteur
       de 37 — donc 8px d'écart, contre 10px + hauteur 40 dans le thème. */
    .tdb-filtres {
        gap: 8px;
    }
    .tdb-filtres__select,
    .tdb-dropdown__trigger {
        height: 37px;
    }
    /* MOD-IA 2026-09-21 : G2 — la pleine largeur mobile est CONSERVÉE, mais
       elle est désormais demandée par le gabarit (classe
       .btn--pleine-largeur-mobile, définie dans ui/01-boutons.css) au lieu
       d'être imposée depuis la feuille de style de la page. Un bouton large
       devient ainsi un choix lisible dans le HTML, au lieu de dépendre de
       l'étirement de son parent.
       ANCIEN CODE :
    .tdb-filtres__carte .btn {
        align-self: stretch;
        width: 100%;
    }
    */
    .tdb-filtres__map-label--desktop {
        display: none;
    }
    .tdb-filtres__map-label--mobile {
        display: inline;
    }
    .tdb-filtres__complementaires-toggle {
        display: flex;
    }
    .tdb-filtres__complementaires.is-collapsed {
        display: none;
    }
}

/* MOD-IA 2026-09-02 : .tdb-pagination déplacé tel quel vers
   assets/css/ui/04-navigation.css (aucune valeur changée) — famille « Navigation »
   de la charte graphique. */

/* MOD-IA 2026-09-02 : le @media mobile de .tdb-pagination déplacé tel quel vers
   assets/css/ui/04-navigation.css (aucune valeur changée) — famille « Navigation »
   de la charte graphique. */
/* ==========================================================================
   Page détail commerçant (single-commercant.php)
   ========================================================================== */

/* Contenu limité à 952px et centré (6153:6614) : 1440 − 2 × 244 de retrait.
   .container ajoute 24px de padding de chaque côté, le max-width doit donc
   valoir 952 + 48 pour que la boîte de contenu retombe sur 952px pile. */
.tdb-commercant-page {
    max-width: calc( 952px + 2 * var( --space-lg ) );
}

@media ( max-width: 1023px ) {
    .tdb-commercant-page {
        max-width: var( --container-max );
    }
}

/* "détail commercant" (4018:5819) : le bloc texte + logo fait 117px, suivi
   d'un filet (Line 5) puis de 40px avant la galerie. */
.tdb-commercant-header {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: var( --space-lg );
    padding-block: var( --space-xl ) 20px;
    border-bottom: 1px solid var( --color-border );
    margin-bottom: 40px;
}

.tdb-commercant-header h1 {
    font-size: 2.5rem;
    line-height: 1.2;
    margin-bottom: var( --space-sm );
}

/* "Frame 376" (547:3971) : ligne secteur/public en orange (20px de haut),
   ligne de lieu en gris 5px plus bas (22px de haut). */
.tdb-commercant-header__meta {
    color: var( --color-text-muted );
    font-size: var( --text-card-place-size );
    line-height: var( --text-card-place-lh );
    letter-spacing: var( --tracking-tight );
    margin: 0;
}

.tdb-commercant-header__secteur {
    color: var( --color-primary );
    font-weight: var( --weight-semibold );
}

.tdb-commercant-header__logo {
    flex-shrink: 0;
    width: 117px;
    height: 117px;
    border-radius: 10px;
    overflow: hidden;
    border: 1px solid var( --color-border );
}

.tdb-commercant-header__logo img {
    width: 100%;
    height: 100%;
    object-fit: contain;
}

/* Galerie carrousel (170:3861) : une grande image visible, deux flèches
   orange en bas à droite — pas une mosaïque de vignettes (voir C-2). */
.tdb-commercant-gallery {
    position: relative;
    margin-bottom: 0; /* l'écart à la section suivante est porté par .tdb-commercant-section (80px) */
}

.tdb-commercant-gallery__track {
    display: flex;
    overflow: hidden;
    border-radius: 10px;
    scroll-snap-type: x mandatory;
}

.tdb-commercant-gallery__slide {
    flex: 0 0 100%;
    width: 100%;
    height: 511px; /* "galerie" (4018:5404) : 952 × 511 */
    object-fit: cover;
    scroll-snap-align: start;
}

/* MOD-IA 2026-09-02 : .tdb-carousel-nav déplacé tel quel vers
   assets/css/ui/04-navigation.css (aucune valeur changée) — famille « Navigation »
   de la charte graphique. */

.tdb-commercant-gallery .tdb-carousel-nav {
    position: absolute;
    right: var( --space-lg );
    bottom: var( --space-lg );
}

/* MOD-IA 2026-09-02 : .tdb-carousel-nav__btn (repos, survol, désactivé) déplacé tel quel vers
   assets/css/ui/04-navigation.css (aucune valeur changée) — famille « Navigation »
   de la charte graphique. */

/* Valeurs relevées sur "SP - page détail commerçant" (2181:4038) : le
   rythme mobile est de 25px entre sections et 20px entre un titre et son
   contenu (contre 80/40 en desktop), et le logo reste À GAUCHE du texte
   (Frame 529 : logo 74px en x=0, texte en x=94) — pas au-dessus. */

/* Rythme relevé sur "detail commercant" (6153:6614) : 80px entre deux
   sections, 40px entre le titre d'une section et son contenu. Le design ne
   pose AUCUN filet entre les sections — le seul trait de la page est celui
   sous l'en-tête du commerçant (Line 5, 191:1890). */
.tdb-commercant-section {
    padding-block: 0;
    margin-top: 80px;
    border-top: none;
}

/* Titres de section (4018:5425) : orange #FC9728, 32px SemiBold, 38px de
   hauteur de ligne — pas du noir. */
.tdb-commercant-section h2 {
    color: var( --color-primary );
    font-size: var( --text-h1-size );
    line-height: var( --text-h1-lh );
    font-weight: var( --weight-semibold );
    letter-spacing: var( --tracking-tight );
    margin: 0 0 40px; /* titre 38px de haut, contenu 40px plus bas */
}

/* Bloc titre + sous-titre de "acheter un bon" (4018:5814) : le sous-titre
   suit le titre à 10px (48 − 38), et le contenu démarre 40px après le bloc. */
.tdb-commercant-section__head h2 {
    margin-bottom: 10px;
}

.tdb-commercant-section__head p {
    color: var( --color-text-muted );
    font-size: var( --text-caption-size );
    line-height: var( --text-caption-lh );
    letter-spacing: var( --tracking-tight );
    margin: 0 0 40px;
}

.tdb-commercant-section__head--carousel {
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin-bottom: 40px;
}

.tdb-commercant-section__head--carousel h2 {
    margin-bottom: 0;
}

/* "détail bon" (4018:5791) : les lignes sont espacées de 10px (promo 90px
   de haut, lignes simples 76px — obtenues par le padding de 15px). */
.tdb-bon-rows {
    display: flex;
    flex-direction: column;
    gap: 10px;
}

.tdb-bon-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var( --space-lg );
    background: var( --color-surface-muted );
    border-radius: var( --radius-sm );
    padding: 15px;
}

/* MOD-IA 2026-09-08 : le fond d'une ligne de bon EN PROMOTION est le même gris
   box que celui d'une ligne ordinaire — seul le filet orange la distingue.
   Vérification de parité du 08.09.2026.

   Le commentaire d'origine citait pourtant le bon nœud : 4018:5695 rendu depuis
   le fichier donne #F7F7F7 à l'intérieur et #FC9728 sur son contour — pas de
   crème. Même relevé par échantillonnage de pixels sur les deux lignes en
   promotion de la frame mobile « SP - page détail commerçant » (2181:4038) :
   (247, 247, 247) dans la ligne, orange sur le filet.

   L'écart valait pour TOUTES les largeurs, la règle n'étant pas dans un
   @media : une ligne en promotion s'affichait crème sur la fiche commerçant,
   en mobile comme en desktop.

   ANCIEN CODE :
   background: #FDF3E3; — fond crème (4018:5695) */
.tdb-bon-row.is-promo {
    background: var( --color-surface-muted );
    /* MOD-IA 2026-09-08 : filet tracé À L'INTÉRIEUR de la ligne, en ombre portée
       interne plutôt qu'en `border`.

       Dans Figma le contour d'un cadre est tracé vers l'intérieur : la ligne en
       promotion mesure 90 filet compris. Une `border` CSS, elle, s'AJOUTE à la
       boîte quand la hauteur est automatique : la ligne faisait 92, et les
       lignes en promotion étaient donc 2px plus hautes que les autres alors que
       la maquette les veut alignées sur la même trame.

       `inset` ne change rien à l'apparence du filet et le retire du calcul de
       hauteur comme de largeur.

       ANCIEN CODE : border: 1px solid var( --color-primary ); */
    box-shadow: inset 0 0 0 1px var( --color-primary );
}

/* MOD-IA 2026-09-08 : écart badge → prix ramené à 10px — vérification de parité
   desktop du 08.09.2026. Dans 4018:5695, le cadre du prix commence à y=38 pour
   un bloc de badges de 28 de haut, soit 10 et non les 12 de --space-sm.
   ANCIEN CODE : margin-bottom: var( --space-sm ); */
.tdb-bon-row__promo {
    display: flex;
    align-items: center;
    gap: var( --space-sm );
    margin-bottom: 10px;
}

/* MOD-IA 2026-09-08 : hauteur de ligne posée à 18px sur les deux pastilles —
   vérification de parité desktop du 08.09.2026.

   Les instances « box promotion commerce » de 4018:5695 font 28 de haut. Sans
   `line-height`, la pastille héritait de celle du corps de texte (22,75px pour
   14px de police) et mesurait 5 + 22,75 + 5 = 33. 18px la ramène à 28, le
   padding de 5 étant conservé. La mesure du fond noir sur le rendu 1:1 du nœud
   confirme : la pastille occupe les lignes y=15 à y=42, soit 28 pixels. */
.tdb-bon-row__promo-percent {
    background: var( --color-ink );
    color: #fff;
    font-size: var( --text-button-size );
    line-height: 18px;
    font-weight: var( --weight-medium );
    padding: 5px 12px;
    border-radius: 5px;
}

.tdb-bon-row__promo-date {
    background: var( --color-primary );
    font-size: var( --text-button-size );
    line-height: 18px;
    font-weight: var( --weight-medium );
    padding: 5px 12px;
    border-radius: 5px;
}

/* MOD-IA 2026-09-08 : la ligne de prix tient sur 22px — même vérification.

   Le cadre « Frame 608 » de 4018:5695 fait 22 de haut. Le paragraphe héritait
   ici de la hauteur de ligne du corps de texte (26px) ; combinée à la police de
   22px du montant, elle produisait une boîte de 36. La ligne entraînait toute
   la rangée avec elle : 113px de haut au lieu des 90 annoncés par le
   commentaire de .tdb-bon-rows plus haut.

   Les tailles de police, elles, étaient JUSTES et ne bougent pas : la hauteur
   des capitales de « CHF 80.– » mesurée sur le rendu 1:1 du nœud est de 16px,
   ce qui correspond bien à une police de 22px.

   ANCIEN CODE :
   .tdb-bon-row__price { margin: 0; } */
.tdb-bon-row__price {
    margin: 0;
    line-height: 22px;
    /* MOD-IA 2026-09-08 : le montant et sa mention entre parenthèses sont posés
       sur la MÊME LIGNE DE BASE, au lieu d'être deux boîtes en ligne dans un
       paragraphe.

       `line-height: 22px` seul ne suffisait pas : deux textes de corps
       différents (22px et 12px) partageant une ligne produisent une boîte de
       ligne dont la hauteur est l'union des deux, calée sur leurs lignes de
       base respectives — 27px ici, là où la maquette en demande 22. En passant
       le paragraphe en `flex` à alignement `baseline`, sa hauteur redevient
       celle du plus haut de ses enfants, soit 22.

       `flex-wrap` est conservé pour que la mention puisse passer à la ligne sur
       les très petits écrans, comme aujourd'hui. */
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: 0 6px;
}

.tdb-bon-row__price-main {
    color: var( --color-primary );
    font-size: 22px;
    font-weight: var( --weight-semibold );
}

.tdb-bon-row__price-note {
    color: var( --color-text-muted );
    font-size: var( --text-caption-size );
    /* MOD-IA 2026-09-08 : l'écart est porté par le `gap` du parent passé en flex
       (voir ci-dessus) ; la marge ferait doublon.
       ANCIEN CODE : margin-left: 6px; */

    /* MOD-IA 2026-09-08 : hauteur de ligne resserrée sur le texte.
       Héritant des 22px du parent, cette mention se retrouvait dans une boîte de
       22 pour une police de 12, donc 5px de blanc au-dessus et en dessous. Une
       fois sa ligne de base alignée sur celle du montant, ces 5px du bas
       dépassaient sous le montant et rendaient la ligne à 27px au lieu de 22. */
    line-height: 1;
}

.tdb-bon-row__form {
    display: flex;
    align-items: center;
    gap: var( --space-sm );
    flex-shrink: 0;
}

/* MOD-IA 2026-09-02 : .tdb-qty (compteur de quantité et champ de montant) déplacé tel quel vers
   assets/css/ui/02-formulaires.css (aucune valeur changée) — famille « Formulaires »
   de la charte graphique. */

.tdb-bon-row__cart-btn {
    flex-shrink: 0;
    width: 47px;
    height: 47px;
    border-radius: var( --radius-sm );
    background: var( --color-ink );
    display: flex;
    align-items: center;
    justify-content: center;
}

@media ( max-width: 767px ) {
    /* MOD-IA 2026-09-01 : la ligne de bon reste sur UNE seule rangée en mobile.
       Le passage en colonne empilait prix puis quantité + panier, ce qui
       donnait une ligne de 3 niveaux. Relevé sur « bon 1 » (6023:9414) : la
       rangée fait 360x60, retrait de 10px, le prix à gauche et le bloc
       quantité + panier calé à droite (x=223, largeur 117). La variante promo
       (« bon promo 1 », 6023:9398) fait 92 de haut : les pastilles occupent
       une première ligne (10/10, 200x25), le prix et le formulaire restant
       ensemble sur la seconde.
       ANCIEN CODE :
       .tdb-bon-row { flex-direction: column; align-items: stretch; }
       .tdb-bon-row__form { justify-content: space-between; } */
    /* La ligne passe en GRILLE, et .tdb-bon-row__info en display:contents.
       Les pastilles de promo sont imbriquées DANS __info (structure correcte en
       desktop, où elles se placent au-dessus du prix dans une colonne de 282px).
       En mobile cette imbrication posait problème : la pastille de date élargit
       __info à 338px, si bien que __info + le formulaire (117) dépassaient les
       340 disponibles et que le panier tombait sur une TROISIÈME ligne.
       En neutralisant __info, les pastilles et le prix deviennent des enfants
       directs de la grille : les pastilles occupent toute la largeur (ligne 1),
       le prix et le formulaire se partagent la ligne 2 — exactement la structure
       de « bon promo 1 » (6023:9398), où Frame 828 et Frame 831 sont frères. */
    .tdb-bon-row {
        display: grid;
        grid-template-columns: 1fr auto;
        align-items: center;
        gap: 7px 10px;
        padding: 10px;
    }
    .tdb-bon-row__info {
        display: contents;
    }
    .tdb-bon-row__promo {
        grid-column: 1 / -1;
        gap: 5px;
        margin-bottom: 0;
    }
    /* « phone box promotion » (6023:9369 / 6023:9370) : pastilles de 25px de
       haut, la première de 50 de large et la seconde de 145. Avec l'interligne
       hérité du desktop elles montaient à 35 et la rangée à 102 au lieu de 92. */
    .tdb-bon-row__promo-percent,
    .tdb-bon-row__promo-date {
        font-size: 12px;
        line-height: 15px;
        padding: 5px 10px;
    }
    .tdb-bon-row__price {
        grid-column: 1;
        min-width: 0;
    }
    .tdb-bon-row__form {
        grid-column: 2;
        gap: 5px;
    }
    .tdb-qty {
        width: 72px;
        height: 40px;
    }
    .tdb-bon-row__cart-btn {
        width: 40px;
        height: 40px;
    }
    /* « Frame 829 » (6023:9390) : bloc de prix de 105x35 — le montant occupe
       23px de haut, la mention de valeur faciale seulement 7. C'est ce qui
       permet à la ligne 2 de tenir dans les 40px du formulaire, et donc à la
       rangée promo de faire 92px et non 111. */
    .tdb-bon-row__price-main {
        font-size: 18px;
        line-height: 23px;
    }
    /* Repli sous le prix, comme dans la maquette, plutôt qu'à sa suite : la
       ligne « (Valeur du bon 100.–) » est un second niveau de texte. */
    .tdb-bon-row__price-note {
        display: block;
        margin-left: 0;
        font-size: 10px;
        line-height: 12px;
    }
}

/* Carrousel (C-3) : 2 cartes visibles à la fois en desktop, scroll horizontal
   piloté par les flèches de .tdb-commercant-section__head--carousel plutôt
   qu'une grille figée. */
/* "Frame 703" (4018:5816) : deux cartes de ~462px espacées de 25px. */
.tdb-prestation-grid {
    display: flex;
    gap: 25px;
    overflow-x: auto;
    scroll-snap-type: x mandatory;
    scrollbar-width: none;
}

.tdb-prestation-grid::-webkit-scrollbar {
    display: none;
}

/* MOD-IA 2026-09-02 : .tdb-prestation-card (largeur dans la piste) déplacé tel quel vers
   assets/css/ui/03-cartes.css (aucune valeur changée) — famille « Cartes »
   de la charte graphique. */

@media ( max-width: 767px ) {
    /* MOD-IA 2026-09-02 : la règle mobile de .tdb-prestation-card est
       déplacée telle quelle vers assets/css/ui/03-cartes.css ; la règle
       de .tdb-prestation-grid, qui est de la mise en page, reste ici. */
    .tdb-prestation-grid {
        gap: 15px;
        /* MOD-IA 2026-09-22 : MN1 — meme piste defilante que les blocs promo
           et etapes de la page d'accueil, et meme correctif : la marge de 15px
           est rendue au debut et a la fin de la piste, et l'accrochage
           `scroll-snap` la respecte. Sans cela la premiere carte de
           « Acheter une prestation » demarre collee au bord de l'ecran. */
        margin-inline: -15px;
        padding-inline: 15px;
        scroll-padding-inline: 15px;
    }
}

/* MOD-IA 2026-09-02 : .tdb-prestation-card (fond, photo, prix, stock) déplacé tel quel vers
   assets/css/ui/03-cartes.css (aucune valeur changée) — famille « Cartes »
   de la charte graphique. */

.tdb-commercant-bio {
    max-width: 952px;
    line-height: 1.6;
}

/* "carte" de "qui sommes-nous" (2325:3359) : 952 × 385, 80px sous le texte. */
.tdb-commercant-map {
    height: 385px;
    border-radius: var( --radius-sm );
    overflow: hidden;
    margin-top: 80px;
    background: var( --color-surface-muted );
}

/* Même fond de carte désaturé que la carte plein écran et la mini-carte
   "Bons valeur" (D-3/E-1), pour rester cohérent avec le reste du site. */
.tdb-commercant-map .leaflet-tile-pane {
    filter: grayscale( 1 ) contrast( .9 ) brightness( 1.05 );
}

.tdb-commercant-map .leaflet-control-zoom {
    display: none;
}

.tdb-commercant-map .leaflet-control-attribution {
    font-size: 10px;
    background: rgba( 255, 255, 255, .7 );
}

/* ---------- Accordéon FAQ (générique, réutilisé partout) ---------- */
/* "FAQ" (423:1754) : le titre fait 38px de haut et l'accordéon démarre 40px
   plus bas ; le bloc lui-même n'ajoute pas de padding vertical propre (son
   écart au bloc précédent est porté par ce dernier). */
.tdb-faq {
    padding-block: 0;
    margin-top: 80px; /* même rythme de 80px que les autres sections */
}

/* "Des questions?" (247:1725 / 191:1404) : même style de titre H1 orange
   que les autres titres de section. */
.tdb-faq__title {
    color: var( --color-primary );
    font-size: var( --text-h1-size );
    line-height: var( --text-h1-lh );
    font-weight: var( --weight-semibold );
    letter-spacing: var( --tracking-tight );
    margin: 0 0 40px;
}

@media ( max-width: 767px ) {
    /* MOD-IA 2026-09-01 : en mobile la galerie passe AVANT l'en-tête. Les deux
       maquettes divergent sur ce point : en desktop (4018:5820) le bloc
       "détail commercant" est à y=0 et la galerie à y=177 ; en mobile
       (2181:4038) la galerie est à y=0 (h=200) et le bloc "detail" à y=240.
       Le DOM garde donc l'ordre desktop et seul le mobile réordonne, d'où le
       flex + order plutôt qu'un échange dans le gabarit. */
    .tdb-commercant-page {
        display: flex;
        flex-direction: column;
    }
    .tdb-commercant-gallery {
        order: -1;
        margin-bottom: 40px; /* 240 - 200 = 40px entre la galerie et le bloc détail */
    }
    .tdb-commercant-header {
        flex-direction: row;
        align-items: flex-start;
        /* MOD-IA 2026-09-01 : en mobile le logo est COLLÉ au texte (74px puis
           20px de gouttière, 2181:4038), alors qu'en desktop le logo est
           repoussé à droite du bloc. Le space-between hérité de la règle de
           base creusait un vide entre les deux et poussait le titre contre le
           bord droit de l'écran. */
        justify-content: flex-start;
        gap: 20px;
        padding-block: 0 15px;
        margin-bottom: 25px;
    }
    /* MOD-IA 2026-09-01 : sans min-width:0, le titre ne peut pas se replier
       dans la ligne flex et « Le Centre Chamoson » débordait à droite de
       l'écran. */
    .tdb-commercant-header__text {
        min-width: 0;
    }
    .tdb-commercant-header__logo {
        order: -1;
        width: 74px;
        height: 74px;
        flex-shrink: 0;
    }
    .tdb-commercant-header h1 {
        font-size: 20px;
        line-height: 25px;
    }
    .tdb-commercant-gallery__slide {
        height: 200px; /* "galerie" (2055:4610) : 360 × 200 */
    }
    .tdb-commercant-section {
        margin-top: 25px;
    }
    .tdb-commercant-section h2 {
        font-size: var( --text-h2-size-mobile );
        line-height: var( --text-h2-lh-mobile );
        margin-bottom: 20px;
    }
    .tdb-commercant-section__head h2 {
        margin-bottom: 10px;
    }
    .tdb-commercant-section__head p {
        margin-bottom: 20px;
    }
    .tdb-commercant-map {
        height: 236px; /* "carte" (2333:3449) : 360 × 236 */
        margin-top: 25px;
    }
    .tdb-faq {
        margin-top: 25px;
    }
    .tdb-faq__title {
        font-size: var( --text-h2-size-mobile );
        line-height: var( --text-h2-lh-mobile );
        margin-bottom: 24px;
    }
    /* Les lignes de bon passent de 90/76px à 92/60px, écart identique de 10px. */
    .tdb-bon-row {
        padding: 10px;
    }
}

/* MOD-IA 2026-09-02 : .tdb-accordion (item, déclencheur, chevron, panneau) déplacé tel quel vers
   assets/css/ui/04-navigation.css (aucune valeur changée) — famille « Navigation »
   de la charte graphique. */

/* ==========================================================================
   Carte de recherche (page-carte.php)
   ========================================================================== */
/* Page plein écran (D-2) : ni en-tête ni pied de page (get_header/
   get_footer('minimal')), la carte occupe tout le viewport. */
.tdb-carte-page {
    position: relative;
    width: 100vw;
    height: 100vh;
}

/* isolation: le conteneur Leaflet est en z-index:auto, ses panneaux internes
   (z-index 400) remontent donc dans le contexte d'empilement du parent et
   recouvrent le panneau de filtres (z-index 20). On force la carte à créer
   son propre contexte pour que ses z-index restent chez elle. */
.tdb-carte-page__map {
    width: 100%;
    height: 100%;
    isolation: isolate;
}

/* Panneau de filtres flottant (547:3835) : 360×635, rayon ~20px, ombre
   portée, en surimpression sur la carte plutôt que dans le flux — D-1. */
/* "menu préférences" (547:3835) : 360×635, posé à x=210 / y=200 — soit, sur
   un canvas de 1920, la gouttière gauche du conteneur du site. */
.tdb-carte-page__panel {
    position: absolute;
    top: 200px;
    left: max( var( --space-lg ), calc( ( 100vw - var( --container-max ) ) / 2 ) );
    z-index: 20;
    width: 360px;
    max-height: calc( 100vh - 200px - var( --space-xl ) );
    overflow-y: auto;
    background: #fff;
    border-radius: var( --radius-card );
    padding: var( --space-lg ) 30px;
    box-shadow: var( --shadow-popover );
}

.tdb-carte-page__panel .tdb-filtres {
    position: static;
}

/* Bouton de fermeture (6201:7902) : mobile uniquement, la maquette desktop
   n'en a pas (le retour se fait via "Retour à ma sélection" du panneau). */
.tdb-carte-page__close {
    display: none;
}

.tdb-map-popup a {
    color: var( --color-primary );
    font-weight: var( --weight-medium );
}

/* Masque le contrôle de zoom Leaflet (+/−), absent de la maquette ; garde
   l'attribution OpenStreetMap (obligation légale) mais en discret (D-4). */
.tdb-carte-page .leaflet-control-zoom {
    display: none;
}

.tdb-carte-page .leaflet-control-attribution {
    font-size: 10px;
    background: rgba( 255, 255, 255, .7 );
}

/* Fond de carte désaturé (D-3) : les tuiles OSM restent en couleur à la
   source (pas de tuiles grises auto-hébergées dans ce projet), on les
   désature en CSS pour retrouver le rendu "plan gris" de la maquette. */
.tdb-carte-page .leaflet-tile-pane {
    filter: grayscale( 1 ) contrast( .9 ) brightness( 1.05 );
}

/* Marqueurs et grappes personnalisés (D-4) : carré arrondi orange, voir
   assets/js/map.js (tdbMarkerDivIcon / tdbClusterDivIcon). */
.tdb-map-marker {
    width: 34px;
    height: 34px;
    border-radius: 8px;
    background: var( --color-primary );
    display: flex;
    align-items: center;
    justify-content: center;
    box-shadow: 0 2px 6px rgba( 0, 0, 0, .25 );
}

.tdb-map-marker img {
    width: 18px;
    height: 15px;
}

/*
 * MOD-IA 2026-09-22 : BC1 — variante « logo du commerçant » du marqueur.
 *
 * Le logo remplit toute la pastille : plus de fond orange ni de retrait, le
 * carré arrondi et l'ombre portée sont conservés pour que la silhouette du
 * marqueur reste celle de la maquette (170:3554). Les logos n'ayant pas tous
 * le même format, `object-fit: cover` recadre au centre plutôt que de
 * déformer.
 */
.tdb-map-marker--logo {
    background: #fff;
    overflow: hidden;
    padding: 0;
}

.tdb-map-marker__logo {
    width: 34px;
    height: 34px;
    object-fit: cover;
    display: block;
}

.tdb-map-cluster {
    width: 34px;
    height: 34px;
    border-radius: 8px;
    background: var( --color-primary );
    color: #000;
    font-size: var( --text-button-size );
    font-weight: var( --weight-semibold );
    display: flex;
    align-items: center;
    justify-content: center;
    box-shadow: 0 2px 6px rgba( 0, 0, 0, .25 );
}

/* Mini-carte "Bons valeur" (4044:5499) : pastilles noires numérotées par
   région, une pastille orange pour la région active (E-1). */
.tdb-map-region {
    width: 34px;
    height: 34px;
    border-radius: 8px;
    background: var( --color-ink-strong );
    color: #fff;
    font-size: var( --text-button-size );
    font-weight: var( --weight-semibold );
    display: flex;
    align-items: center;
    justify-content: center;
    box-shadow: 0 2px 6px rgba( 0, 0, 0, .25 );
}

.tdb-map-region.is-active {
    background: var( --color-primary );
    color: #000;
}

@media ( max-width: 767px ) {
    /* La frame mobile (6201:7902) ne montre aucun filtre, juste la carte et
       une croix de fermeture — voir D-5. */
    .tdb-carte-page__panel {
        display: none;
    }
    .tdb-carte-page__close {
        display: flex;
        align-items: center;
        justify-content: center;
        position: absolute;
        top: var( --space-md );
        right: var( --space-md );
        z-index: 20;
        width: 34px;
        height: 34px;
        /* MOD-IA 2026-09-01 : carré arrondi sombre au lieu du rond blanc — la
           maquette (6201:7902) pose un carré sombre à croix blanche. Sur fond
           blanc, la croix (trait blanc) était invisible : on ne voyait qu'une
           pastille vide en haut à droite de la carte. */
        /* ANCIEN CODE :
        border-radius: 50%;
        background: #fff;
        */
        border-radius: var( --radius-sm );
        background: var( --color-ink );
        box-shadow: var( --shadow-popover );
    }
}

/* ==========================================================================
   Page "Bons valeur" (page-bons-valeur.php)
   ========================================================================== */
/* Colonnes relevées sur "detail bon valeur + box acheter" (6153:6620) :
   colonne gauche 829px, gouttière 148px, colonne droite 463px = 1440. */
.tdb-bons-valeur {
    display: grid;
    grid-template-columns: 829fr 463fr;
    gap: 148px;
    padding-block: var( --space-xl ) var( --space-3xl );
    align-items: start;
}

.tdb-bons-valeur__map {
    width: 100%;
    height: 489px;
    border-radius: var( --radius-card );
    overflow: hidden;
    margin-bottom: 73px; /* la carte finit à y=489, le descriptif démarre à 562 */
    /* MOD-IA 2026-09-22 : MN4 — la carte restait affichée PAR-DESSUS le menu
       hors-canevas mobile (`.mobile-menu`, z-index 100). Les panneaux internes
       de Leaflet portent des z-index de 400 à 1000 ; ce conteneur étant en
       z-index auto, et aucun ancêtre ne créant de contexte d'empilement (en
       mobile, `.tdb-bons-valeur` et `__content` passent même en
       `display: contents`), ces panneaux remontaient jusqu'au contexte racine
       et passaient donc devant le menu.
       `isolation: isolate` crée le contexte d'empilement qui manquait : les
       z-index de Leaflet y restent confinés. C'est exactement le correctif
       déjà posé sur `.tdb-carte-page__map` (voir plus haut dans ce fichier),
       qui n'avait jamais été reporté ici. */
    isolation: isolate;
}

/* Fond de carte désaturé (4044:5499), même traitement que la carte plein
   écran (D-3/E-1) ; zoom masqué, cette mini-carte n'est pas interactive au
   même niveau que la page-carte. */
.tdb-bons-valeur__map .leaflet-tile-pane {
    filter: grayscale( 1 ) contrast( .9 ) brightness( 1.05 );
}

.tdb-bons-valeur__map .leaflet-control-zoom {
    display: none;
}

.tdb-bons-valeur__map .leaflet-control-attribution {
    font-size: 10px;
    background: rgba( 255, 255, 255, .7 );
}

/* Espacements relevés sur "carte + txt + faq" (6023:7568) : la carte finit à
   y=489, le titre "Les bons valeur" commence à y=562 (73px), le corps de
   texte à y=640 (40px après le titre de 38px de haut). */
.tdb-bons-valeur__descriptif h1 {
    color: var( --color-primary );
    font-size: var( --text-h1-size );
    line-height: var( --text-h1-lh );
    letter-spacing: var( --tracking-tight );
    margin: 0 0 40px;
}

.tdb-bons-valeur__descriptif {
    line-height: var( --text-body-lh );
    margin-bottom: 80px; /* Descriptif finit à 1004, la FAQ démarre à 1084. */
}

.tdb-bons-valeur__sidebar {
    position: sticky;
    top: var( --space-lg );
}

@media ( max-width: 1023px ) {
    .tdb-bons-valeur {
        grid-template-columns: 1fr;
    }
}

@media ( max-width: 767px ) {
    /* MOD-IA 2026-09-01 : hauteur relevée sur "carte" (6174:8132) — 360x236,
       et non 320. */
    /* ANCIEN CODE : height: 320px; */
    .tdb-bons-valeur__map {
        height: 236px;
        margin-bottom: 0; /* le rythme est porté par le gap du conteneur */
    }

    /* MOD-IA 2026-09-01 : en mobile le bloc d'achat remonte ENTRE la carte et
       le descriptif. Relevé sur 2181:4059 : carte y=0 (h=236), "box acheter
       bon valeur" y=261, "qui sommes-nous" y=553, FAQ y=1266 — soit 25px
       entre chaque section. Le thème le rendait en dernier, après la FAQ,
       parce qu'il vit dans <aside class="__sidebar"> (colonne de droite en
       desktop, 829/463) et que la grille se contentait de passer à 1 colonne.
       On neutralise les deux conteneurs avec display:contents pour que les
       quatre blocs deviennent frères du <main> et puissent être réordonnés. */
    .tdb-bons-valeur-page {
        display: flex;
        flex-direction: column;
        gap: 25px;
        /* MOD-IA 2026-09-21 : G3 — le rythme vertical part d'ici. C'était la
           dernière exception de gabarit en mobile : 24px / 32px, valeurs
           d'avant le relevé. Le relevé Figma (00-RELEVE-FIGMA.md §1, frames
           435:1510 et 450:1982) mesure 25px après l'en-tête et 40px avant le
           pied de page, et c'est `.site-main` qui les porte désormais pour
           tous les gabarits (ui/00-base.css). La règle l'emportait : même
           spécificité que `.site-main` (0-1-0), mais style.css est chargé
           APRÈS ui/00-base.css.
           Le reste de la règle (flex + gap 25px) est le réordonnancement des
           sections, sans rapport avec G3 : on n'y touche pas.
           ANCIEN CODE :
           padding-block: var( --space-lg ) var( --space-xl ); */
    }
    .tdb-bons-valeur-page .tdb-bons-valeur,
    .tdb-bons-valeur-page .tdb-bons-valeur__content {
        display: contents;
    }
    .tdb-bons-valeur-page .tdb-bons-valeur__map { order: 1; }
    .tdb-bons-valeur-page .tdb-bons-valeur__sidebar { order: 2; position: static; }
    .tdb-bons-valeur-page .tdb-bons-valeur__descriptif { order: 3; margin-bottom: 0; }
    .tdb-bons-valeur-page .tdb-faq { order: 4; }

    /* "phone/titre H1 homepage" : 24/30, contre 32/38 en desktop. */
    .tdb-bons-valeur__descriptif h1 {
        font-size: var( --text-h1-home-size-mobile );
        line-height: var( --text-h1-home-lh-mobile );
        margin-bottom: 20px;
    }
}

/* "bloc acheter un bon valeur région" (547:5431) : DEUX boîtes distinctes
   (cartouche titre + box détail), séparées de 10px, chacune arrondie sur ses
   4 coins — pas un seul bloc avec un en-tête collé. */
.tdb-widget-bon-generique {
    display: flex;
    flex-direction: column;
    gap: 10px;
}

.tdb-widget-bon-generique__title {
    background: var( --color-ink );
    color: #fff;
    font-size: var( --text-h3-size );
    line-height: var( --text-h3-lh );
    font-weight: var( --weight-semibold );
    letter-spacing: var( --tracking-tight );
    padding: 15px;
    border-radius: 10px;
}

.tdb-widget-bon-generique__body {
    background: var( --color-surface-muted );
    padding: 15px;
    border-radius: 10px;
    display: flex;
    flex-direction: column;
    align-items: flex-end; /* le bouton panier est aligné à droite (items-end) */
    gap: 20px;
}

/* "Choisir ma région" est un menu déroulant à cases (variante --filet),
   pas un <select> : son style vit dans le bloc .tdb-dropdown plus haut. */
.tdb-widget-bon-generique__body .tdb-dropdown {
    width: 100%;
}

.tdb-widget-bon-generique__row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    width: 100%;
    font-size: var( --text-button-size );
    font-weight: var( --weight-light );
    letter-spacing: var( --tracking-tight );
}

/* Ordre du design : champ "Montant" (149px) PUIS quantité (70px). */
.tdb-widget-bon-generique__inputs {
    display: flex;
    gap: 10px;
}

.tdb-widget-bon-generique__inputs .tdb-qty {
    height: 46px;
    border: 1px solid var( --color-text-muted );
    border-radius: 10px;
}

.tdb-widget-bon-generique__inputs .tdb-qty--montant {
    width: 149px;
}

.tdb-widget-bon-generique__inputs .tdb-qty--quantite {
    width: 70px;
}

/* Filet orange (Line 8), pas un gris neutre. */
.tdb-widget-bon-generique__divider {
    width: 100%;
    height: 1px;
    border: none;
    background: var( --color-primary );
    margin: 0;
}

.tdb-widget-bon-generique__note {
    width: 100%;
    color: var( --color-text-muted );
    font-size: var( --text-caption-size );
    line-height: var( --text-caption-lh );
    letter-spacing: var( --tracking-tight );
    margin: 0;
}

.tdb-widget-bon-generique__body .tdb-bon-row__cart-btn {
    border-radius: 10px;
}

.tdb-widget-bon-generique__empty {
    color: var( --color-text-muted );
    font-style: italic;
    margin: 0;
}

/* MOD-IA 2026-09-08 : version MOBILE du bloc « Acheter un bon valeur », qui
   n'existait pas — vérification de parité du 08.09.2026.

   Le gabarit rendait la structure DESKTOP (547:5431) à toutes les largeurs. Or
   la maquette mobile (2055:4612, dans « SP - page bon valeur » 2181:4059) est
   différente sur trois points, relevés nœud par nœud :

     |                     | desktop 547:5431      | mobile 2055:4612        |
     | cartouche de titre  | 52 de haut            | 44                      |
     | libellé « Montant » | présent (x=0, w=165)  | ABSENT                  |
     | bouton panier       | 43x46, SOUS la note   | 40x40, EN BOUT DE LIGNE |
     | ligne des champs    | 46 de haut            | 40                      |
     | montant / quantité  | 149 / 70              | 172 / 100               |

   Le bloc mesurait donc 350px de haut au lieu de 267 : le bouton panier
   occupait une ligne à lui seul, tout en bas, séparé des champs qu'il valide
   par le filet orange ET par le paragraphe de conditions.

   Rien n'est touché dans le gabarit : l'ordre du balisage reste celui du
   desktop (déroulant, ligne des champs, filet, note, bouton) et c'est une
   grille qui replace le bouton sur la ligne des champs. Un lecteur d'écran
   suit toujours l'ordre du document, identique aux deux largeurs. */
@media ( max-width: 767px ) {
    .tdb-widget-bon-generique__title {
        /* 44 de haut : 15px de padding de part et d'autre d'une ligne de 14. */
        padding-block: 11px;
    }

    /* La colonne de droite fait la largeur du bouton panier de la maquette. */
    .tdb-widget-bon-generique__body {
        display: grid;
        grid-template-columns: 1fr 40px;
        align-items: center;
        gap: 10px 9px;
    }

    .tdb-widget-bon-generique__body .tdb-dropdown {
        grid-column: 1 / -1;
        grid-row: 1;
    }

    .tdb-widget-bon-generique__row {
        grid-column: 1;
        grid-row: 2;
    }

    /* Le libellé « Montant » n'existe pas dans la maquette mobile : les deux
       champs y portent déjà leur unité (« .– » et « x »). Masqué plutôt que
       retiré du gabarit — il reste lu par les lecteurs d'écran via le
       `aria-label` de chaque champ, et le desktop le garde. */
    .tdb-widget-bon-generique__row > span {
        display: none;
    }

    /* Les deux champs occupent alors toute la ligne, dans le rapport de la
       maquette (172 / 100 pour 281 disponibles). */
    .tdb-widget-bon-generique__inputs {
        width: 100%;
        gap: 9px;
    }

    .tdb-widget-bon-generique__inputs .tdb-qty {
        height: 40px;
    }

    .tdb-widget-bon-generique__inputs .tdb-qty--montant {
        flex: 1 1 auto;
        width: auto;
    }

    .tdb-widget-bon-generique__inputs .tdb-qty--quantite {
        flex: 0 0 100px;
        width: 100px;
    }

    .tdb-widget-bon-generique__divider {
        grid-column: 1 / -1;
        grid-row: 3;
    }

    .tdb-widget-bon-generique__note {
        grid-column: 1 / -1;
        grid-row: 4;
    }

    /* Le bouton remonte sur la ligne des champs, à leur droite (40x40). */
    .tdb-widget-bon-generique__body .tdb-bon-row__cart-btn {
        grid-column: 2;
        grid-row: 2;
        width: 40px;
        height: 40px;
        padding: 0;
    }

    /* Le bloc « aucun produit configuré » n'a qu'un enfant : il reprend toute
       la largeur, sinon il se serrerait dans la colonne de gauche. */
    .tdb-widget-bon-generique__empty {
        grid-column: 1 / -1;
    }
}

/* ==========================================================================
   WooCommerce natif (panier, checkout, mon compte, produit) — les gabarits
   métier sur-mesure (single-commercant.php, page-bons-valeur.php) ont leurs
   propres styles ci-dessus ; ce qui suit habille les écrans WooCommerce
   standards que le thème ne recompose pas lui-même.
   ========================================================================== */
.woocommerce a.button,
.woocommerce button.button,
.woocommerce input.button,
.woocommerce #respond input#submit {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    height: 46px;
    padding: 0 var( --space-lg );
    border-radius: var( --radius-sm );
    background: var( --color-primary );
    color: #000;
    font-family: var( --font-heading );
    font-size: var( --text-button-size );
    font-weight: var( --weight-medium );
    border: none;
}

.woocommerce a.button:hover,
.woocommerce button.button:hover,
.woocommerce input.button:hover {
    background: var( --color-primary-hover );
    color: #000;
}

.woocommerce a.button.alt,
.woocommerce button.button.alt,
.woocommerce input.button.alt {
    background: var( --color-ink );
    color: #fff;
}

.woocommerce table.shop_table {
    border: none;
    border-radius: var( --radius-sm );
    overflow: hidden;
}

.woocommerce table.shop_table th {
    background: var( --color-surface-muted );
    font-weight: var( --weight-semibold );
}

.woocommerce table.shop_table td,
.woocommerce table.shop_table th {
    border: 1px solid var( --color-border );
}

.woocommerce .woocommerce-message,
.woocommerce .woocommerce-info,
.woocommerce .woocommerce-noticed {
    border-top-color: var( --color-primary );
    background: var( --color-surface-muted );
}

.woocommerce .woocommerce-message::before,
.woocommerce .woocommerce-info::before {
    color: var( --color-primary );
}

.woocommerce .woocommerce-error {
    border-top-color: var( --color-status-expired );
}

.woocommerce .quantity .qty {
    height: 46px;
    border-radius: var( --radius-sm );
    border: 1px solid var( --color-text-muted );
    text-align: center;
}

.woocommerce ul.products li.product .price,
.woocommerce div.product p.price,
.woocommerce div.product span.price {
    color: var( --color-primary );
    font-weight: var( --weight-semibold );
}

.woocommerce-checkout .form-row input.input-text,
.woocommerce-checkout .form-row select {
    height: 46px;
    border-radius: var( --radius-sm );
    border: 1px solid var( --color-text-muted );
    padding-inline: var( --space-md );
}

.woocommerce-checkout #payment {
    background: var( --color-surface-muted );
    border-radius: var( --radius-sm );
}

.woocommerce-checkout #payment div.payment_box {
    background: #fff;
}

.woocommerce-MyAccount-navigation ul {
    display: flex;
    flex-direction: column;
    gap: 4px;
}

.woocommerce-MyAccount-navigation li a {
    display: block;
    padding: var( --space-sm ) var( --space-md );
    border-radius: var( --radius-sm );
    background: var( --color-ink );
    color: #fff;
    font-size: var( --text-button-size );
}

.woocommerce-MyAccount-navigation li.is-active a {
    background: var( --color-primary );
    color: #000;
}

/* ==========================================================================
   MOD-IA 2026-09-28 : section NOUVELLE — Fiche produit (/product/…,
   woocommerce.php + tdb_fiche_produit_crochets() dans inc/woocommerce.php).

   Aucune frame Figma pour cette vue : mise en page DÉRIVÉE de la charte —
   image à gauche au rayon 20 sur fond noir (comme les cartes prestation),
   fiche d'achat à droite dans une boîte gris box au rayon 20, badge de type
   repris du panier, prix orange, champs à filet gris de 46px (hauteur des
   champs du checkout), bouton noir « alt » déjà défini plus haut.

   Les sélecteurs commencent par `.woocommerce .tdb-produit-page` : les
   feuilles de WooCommerce (woocommerce-layout.css, woocommerce.css) sont
   chargées APRÈS le thème et posent leurs flottants en 0-2-2 / 0-3-2 ; il faut
   les dépasser en spécificité, pas seulement en ordre.
   ========================================================================== */
.woocommerce .tdb-produit-page div.product {
    display: grid;
    grid-template-columns: minmax( 0, 1fr ) minmax( 0, 1fr );
    gap: var( --space-2xl );
    align-items: start;
    padding-top: var( --space-xl );
}

/* Clearfix éventuel de WooCommerce : dans une grille, ses pseudo-éléments
   deviendraient des cellules vides. */
.woocommerce .tdb-produit-page div.product::before,
.woocommerce .tdb-produit-page div.product::after {
    content: none;
}

.woocommerce .tdb-produit-page div.product div.images,
.woocommerce .tdb-produit-page div.product div.summary {
    float: none;
    width: auto;
    margin: 0;
}

/* Pastille « Promo ! » native retirée : le prix barré et le pourcentage de
   la fiche portent déjà l'information. */
.woocommerce .tdb-produit-page div.product span.onsale {
    display: none;
}

/* ---------- Image ---------- */
.woocommerce .tdb-produit-page div.product div.images {
    border-radius: var( --radius-card );
    overflow: hidden;
    background: var( --color-ink );
}

.woocommerce .tdb-produit-page div.product div.images img {
    width: 100%;
    aspect-ratio: 4 / 3;
    object-fit: cover;
    border-radius: 0;
}

.woocommerce .tdb-produit-page div.product div.images .woocommerce-product-gallery__wrapper {
    margin: 0;
}

/* ---------- Fiche d'achat ---------- */
.woocommerce .tdb-produit-page div.product div.summary {
    display: flex;
    flex-direction: column;
    gap: var( --space-md );
    padding: var( --space-xl );
    background: var( --color-surface-muted );
    border-radius: var( --radius-card );
}

.woocommerce .tdb-produit-page div.product div.summary > * {
    margin: 0;
}

.tdb-produit__entete {
    display: flex;
    align-items: center;
    justify-content: space-between;
    flex-wrap: wrap;
    gap: var( --space-sm );
}

.tdb-produit__retour {
    color: var( --color-text-muted );
    font-size: var( --text-card-desc-size );
    text-decoration: none;
    transition: color var( --duration-tdb-snap ) var( --ease-tdb );
}

.tdb-produit__retour:hover,
.tdb-produit__retour:focus-visible {
    color: var( --color-primary );
}

.woocommerce .tdb-produit-page div.product .product_title {
    font-size: var( --text-h1-size );
    line-height: var( --text-h1-lh );
    font-weight: var( --weight-semibold );
    letter-spacing: var( --tracking-tight );
}

.woocommerce .tdb-produit-page div.product p.price {
    display: flex;
    align-items: baseline;
    flex-wrap: wrap;
    gap: var( --space-sm );
    color: var( --color-primary );
    font-size: 1.75rem;
    line-height: 1.2;
    font-weight: var( --weight-semibold );
}

.woocommerce .tdb-produit-page div.product p.price del {
    order: 2;
    color: var( --color-text-muted );
    font-size: var( --text-body-size );
    font-weight: var( --weight-regular );
    opacity: 1;
}

.woocommerce .tdb-produit-page div.product p.price ins {
    text-decoration: none;
}

.tdb-produit__remise {
    order: 3;
    align-self: center;
    padding: 5px 12px;
    border-radius: var( --radius-badge );
    background: var( --color-ink );
    color: #fff;
    font-size: var( --text-button-size );
    font-weight: var( --weight-medium );
}

.woocommerce .tdb-produit-page .woocommerce-product-details__short-description {
    font-size: var( --text-card-desc-size );
    line-height: var( --text-card-desc-lh );
    color: var( --color-ink );
}

.woocommerce .tdb-produit-page .woocommerce-product-details__short-description > :last-child {
    margin-bottom: 0;
}

.woocommerce .tdb-produit-page div.product .stock {
    color: var( --color-text-muted );
    font-size: var( --text-caption-size );
}

/* ---------- Formulaire d'achat (form.cart + champs PassVal) ----------
   PassVal insère ses champs (choix du commerçant, montant du bon variable,
   canton) dans des <div> sans classe, AVANT le compteur et le bouton : ils
   prennent toute la largeur, compteur et bouton se partagent la dernière
   ligne. */
.woocommerce .tdb-produit-page div.product form.cart {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-end;
    gap: var( --space-md );
    margin: var( --space-xs ) 0 0;
    padding-top: var( --space-lg );
    border-top: 1px solid var( --color-border );
}

.woocommerce .tdb-produit-page div.product form.cart::before,
.woocommerce .tdb-produit-page div.product form.cart::after {
    content: none;
}

.woocommerce .tdb-produit-page div.product form.cart > div:not( .tdb-produit__qty ),
.woocommerce .tdb-produit-page div.product form.cart > p {
    flex: 1 0 100%;
    margin: 0;
}

/* Bloc d'erreur vide de PassVal : sans contenu, il ne doit pas créer un
   écart de plus dans la pile. */
.woocommerce .tdb-produit-page div.product form.cart > #error-variable-area:empty {
    display: none;
}

.woocommerce .tdb-produit-page form.cart label {
    display: block;
    margin-bottom: 7px;
    font-size: 13px;
    font-weight: var( --weight-medium );
    line-height: 1.4;
    color: var( --color-text );
}

.woocommerce .tdb-produit-page form.cart select,
.woocommerce .tdb-produit-page form.cart input[type="number"]:not( .qty ),
.woocommerce .tdb-produit-page form.cart input[type="text"] {
    width: 100%;
    height: 46px;
    padding-inline: var( --space-md );
    border: 1px solid var( --color-text-muted );
    border-radius: var( --radius-sm );
    background-color: var( --color-surface );
    font-family: var( --font-body );
    font-size: var( --text-body-size );
    color: var( --color-text );
    transition: border-color var( --duration-tdb-snap ) var( --ease-tdb );
}

/* Flèche du <select> : chevron de la charte à la place de la flèche native,
   dont le rendu varie d'un navigateur à l'autre. */
.woocommerce .tdb-produit-page form.cart select {
    appearance: none;
    -webkit-appearance: none;
    padding-right: 44px;
    background-image: url( "data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'%3E%3Cpath d='M1 1.5l5 5 5-5' fill='none' stroke='%23212121' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E" );
    background-repeat: no-repeat;
    background-position: right var( --space-md ) center;
    cursor: pointer;
}

.woocommerce .tdb-produit-page form.cart select:hover,
.woocommerce .tdb-produit-page form.cart input[type="number"]:not( .qty ):hover,
.woocommerce .tdb-produit-page form.cart input[type="text"]:hover {
    border-color: var( --color-text );
}

.woocommerce .tdb-produit-page form.cart select:focus,
.woocommerce .tdb-produit-page form.cart input[type="number"]:not( .qty ):focus,
.woocommerce .tdb-produit-page form.cart input[type="text"]:focus {
    border-color: var( --color-primary );
    outline: 0;
}

/* Fourchette « Entre X et Y CHF » du bon variable (p#text-value-range). */
.woocommerce .tdb-produit-page #text-value-range {
    margin: 6px 0 0;
    font-size: var( --text-caption-size );
    line-height: var( --text-caption-lh );
    color: var( --color-text-muted );
}

/* Message d'erreur du bon variable : PassVal le pose en style EN LIGNE
   (fond rouge plein, texte blanc, largeur 50 %) — d'où les !important, seul
   moyen de passer devant un attribut style. Rendu aligné sur l'état erreur
   des champs de la charte (ui/02-formulaires.css). */
.woocommerce .tdb-produit-page #error-variable {
    width: auto !important;
    margin: 0 !important;
    padding: var( --space-sm ) var( --space-md ) !important;
    border: 1px solid var( --color-status-expired-line ) !important;
    border-radius: var( --radius-sm );
    background: var( --color-status-expired-surface ) !important;
    color: var( --color-status-expired-text ) !important;
    font-size: var( --text-card-desc-size );
    font-weight: var( --weight-medium ) !important;
    text-align: left !important;
}

/* Compteur : même boîte que celui du panier, portée à 46px pour s'aligner
   sur le bouton. */
.woocommerce .tdb-produit-page div.product form.cart .tdb-produit__qty .quantity {
    float: none;
    height: 46px;
    margin: 0;
}

/* Produit vendu à l'unité : WooCommerce ne rend qu'un champ caché, les
   boutons −/+ n'auraient rien à piloter. */
.woocommerce .tdb-produit-page .tdb-produit__qty:has( input[type="hidden"] ) {
    display: none;
}

.woocommerce .tdb-produit-page div.product form.cart .single_add_to_cart_button {
    float: none;
    flex: 1 1 200px;
    height: 46px;
    margin: 0;
}

/* ---------- Description longue ---------- */
.tdb-produit__description {
    grid-column: 1 / -1;
    padding-top: var( --space-xl );
    border-top: 1px solid var( --color-border );
    font-size: var( --text-body-size );
    line-height: var( --text-body-lh );
}

.tdb-produit__description h2 {
    margin: 0 0 var( --space-md );
    font-size: var( --text-h2-size );
    line-height: var( --text-h2-lh );
}

/* ---------- Mobile ---------- */
@media ( max-width: 767px ) {
    .woocommerce .tdb-produit-page div.product {
        grid-template-columns: minmax( 0, 1fr );
        gap: var( --space-lg );
        padding-top: 0;
    }

    .woocommerce .tdb-produit-page div.product div.summary {
        padding: var( --space-lg );
    }

    .woocommerce .tdb-produit-page div.product .product_title {
        font-size: var( --text-h1-home-size-mobile );
        line-height: var( --text-h1-home-lh-mobile );
    }
}

/* ==========================================================================
   MOD-IA 2026-09-03 : section NOUVELLE — Panier (woocommerce/cart/cart.php,
   cart-totals.php, cart-empty.php, cart-item-data.php,
   proceed-to-checkout-button.php). Refonte en cartes proposée en maquette et
   validée par le client, même langage visuel que .tdb-bon-row /
   .tdb-prestation-card ci-dessus (rayon de carte, ombre, badges de type,
   prix en orange).
   ========================================================================== */
/* MOD-IA 2026-09-04 : fond gris box de la page panier. La maquette validée
   pose des cartes BLANCHES sur un fond gris ; la page réelle héritait du fond
   blanc du site (body, assets/css/ui/00-base.css), où les cartes du panier
   n'avaient plus aucune limite visible — leur ombre très douce ne suffit pas à
   les détacher du blanc. C'est l'écart qui rendait la page « pas tout à fait
   comme la maquette ». Portée limitée à la page panier par la classe de corps
   de WooCommerce. La barre principale de l'en-tête est repassée en blanc :
   elle n'a pas de fond à elle et serait devenue grise avec le corps. */
body.woocommerce-cart {
    background: var( --color-surface-muted );
}

/* Le fond est posé sur .site-header et non sur .site-header__main : cette
   dernière est un .container (largeur plafonnée, centrée), le blanc n'aurait
   couvert que le milieu de la barre et laissé deux bandes grises sur les
   côtés. .site-header, elle, occupe toute la largeur — et sa barre de
   services garde son fond noir, qu'elle porte elle-même. */
body.woocommerce-cart .site-header {
    background: var( --color-surface );
}

/* Respiration verticale de la page panier (aucune règle générique n'en donne
   aux gabarits de page : .site-main n'est pas stylé). */
/* MOD-IA 2026-09-21 : G3 — cette exception n'a plus lieu d'être : `.site-main`
   porte désormais le rythme pour tous les gabarits (ui/00-base.css), aux
   valeurs relevées dans Figma. La laisser ajouterait 32px + 64px aux 50px +
   80px communs.
   ANCIEN CODE :
.tdb-panier-page {
    padding-block: var( --space-xl ) var( --space-3xl );
}
*/

/* MOD-IA 2026-09-04 : titre et compteur sur une seule ligne, comme dans la
   maquette (page-panier.php). */
.tdb-panier-entete {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    flex-wrap: wrap;
    gap: var( --space-md );
    margin-bottom: var( --space-lg );
    padding-top: var(--space-lg);
}

.tdb-panier-entete .entry-title {
    font-size: var( --text-h1-size );
    line-height: var( --text-h1-lh );
}

/* MOD-IA 2026-09-04 : la marge basse n'a plus lieu d'être quand le compteur
   est dans l'en-tête (c'est .tdb-panier-entete qui la porte) ; elle reste sur
   le repli affiché par woocommerce/cart/cart.php hors page panier.
   ANCIEN CODE :
   .tdb-panier-compte { margin: 0 0 var( --space-md ); … } */
.tdb-panier-compte {
    margin: 0 0 var( --space-md );
    color: var( --color-text-muted );
    font-size: var( --text-card-desc-size );
}

.tdb-panier-entete .tdb-panier-compte {
    margin: 0;
}

.tdb-panier-grid {
    display: grid;
    grid-template-columns: 1fr 360px;
    gap: var( --space-xl );
    align-items: start;
}

.tdb-panier-liste {
    display: flex;
    flex-direction: column;
    gap: var( --space-md );
}

.tdb-panier-item {
    display: grid;
    grid-template-columns: auto 1fr auto;
    gap: var( --space-lg );
    align-items: start;
    padding: var( --space-lg );
    background: var( --color-surface );
    border-radius: var( --radius-card );
    box-shadow: var( --shadow-card );
}

.tdb-panier-item__badge {
    font-family: var( --font-heading );
    font-size: .7rem;
    font-weight: var( --weight-semibold );
    letter-spacing: .02em;
    text-transform: uppercase;
    color: #fff;
    padding: 5px 10px;
    border-radius: var( --radius-badge );
    white-space: nowrap;
}

.tdb-panier-item__badge--commercant { background: var( --color-ink ); }
.tdb-panier-item__badge--generique  { background: var( --color-primary ); color: #000; }
.tdb-panier-item__badge--prestation { background: #6c5ce7; }
.tdb-panier-item__badge--libre      { background: var( --color-status-inactive ); }

.tdb-panier-item__main {
    min-width: 0;
}

.tdb-panier-item__titre {
    margin: 0 0 var( --space-xs );
    font-family: var( --font-heading );
    font-weight: var( --weight-semibold );
    font-size: var( --text-h3-size );
    line-height: var( --text-h3-lh );
}

.tdb-panier-item__titre a {
    color: inherit;
    text-decoration: none;
}

.tdb-panier-item__meta {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-wrap: wrap;
    gap: var( --space-sm ) var( --space-lg );
    font-size: var( --text-card-desc-size );
    color: var( --color-text-muted );
}

.tdb-panier-item__meta b {
    color: var( --color-text );
    font-weight: var( --weight-medium );
}

.tdb-panier-item__side {
    display: flex;
    flex-direction: column;
    align-items: flex-end;
    gap: var( --space-sm );
}

/* Compteur de quantité du panier — mêmes valeurs que .tdb-qty
   (assets/css/ui/02-formulaires.css), avec les boutons +/- ajoutés par
   tdb_cart_quantity_stepper_avant()/_apres() (inc/woocommerce.php). */
.tdb-panier-qty .quantity {
    display: flex;
    align-items: center;
    /* MOD-IA 2026-09-04 : largeur sur le contenu — sans elle, la boîte
       s'étirait sur toute la colonne d'actions dès que celle-ci passait en
       ligne (moins de 600 px). */
    width: max-content;
    height: 40px;
    margin: 0;
    border: 1px solid var( --color-text-muted );
    border-radius: var( --radius-sm );
    background: #fff;
    overflow: hidden;
}

/*
 * MOD-IA 2026-09-04 : le champ est désormais visé par
 * `.tdb-panier-qty .quantity input.qty` (0,3,1) et non plus par
 * `.tdb-panier-qty .qty` (0,2,0), qui perdait contre DEUX règles à trois
 * classes — d'où un compteur qui ne ressemblait pas à la maquette :
 *   - `.woocommerce .quantity .qty` plus haut dans CE fichier (champ de
 *     quantité de la fiche produit) redonnait au champ sa PROPRE bordure,
 *     son rayon de 10 et une hauteur de 46 px : un second cadre arrondi,
 *     plus haut que la boîte de 40 px qui le contient, coincé entre les
 *     boutons − et + ;
 *   - `.woocommerce .quantity .qty { width: 3.631em }` de woocommerce.css,
 *     chargé APRÈS le thème, l'élargissait à ~58 px au lieu de 34.
 * Les valeurs ci-dessous sont celles de la maquette validée ; les
 * `border: 0` / `box-shadow: none` / `padding: 0` neutralisent explicitement
 * ce que ces deux règles posaient.
 * ANCIEN CODE :
 * .tdb-panier-qty .qty {
 *     width: 34px;
 *     border: 0;
 *     text-align: center;
 *     font-family: var( --font-body );
 *     font-size: .9rem;
 *     font-variant-numeric: tabular-nums;
 *     background: transparent;
 * }
 */
.tdb-panier-qty .quantity input.qty {
    width: 34px;
    height: auto;
    margin: 0;
    padding: 0;
    border: 0;
    border-radius: 0;
    box-shadow: none;
    text-align: center;
    font-family: var( --font-body );
    font-size: .9rem;
    font-variant-numeric: tabular-nums;
    background: transparent;
    color: var( --color-text );
    /* Flèches natives du champ nombre retirées : les boutons − / + les
       remplacent, le navigateur en affichait un SECOND jeu à l'intérieur du
       champ (Chrome les révèle au survol), absent de la maquette. Limité au
       panier : le compteur .tdb-qty du reste du site n'a pas encore ses
       boutons et a besoin des flèches natives pour rester utilisable. */
    -moz-appearance: textfield;
    appearance: textfield;
}

.tdb-panier-qty .quantity input.qty::-webkit-outer-spin-button,
.tdb-panier-qty .quantity input.qty::-webkit-inner-spin-button {
    -webkit-appearance: none;
    margin: 0;
}

/* Le contour orange de focus se poserait à l'intérieur de la boîte, sur un
   champ sans bordure : c'est la boîte entière qui le prend (règle suivante). */
.tdb-panier-qty .quantity input.qty:focus,
.tdb-panier-qty .quantity input.qty:focus-visible {
    outline: 0;
}

.tdb-panier-qty .quantity:focus-within {
    outline: 2px solid var( --color-primary );
    outline-offset: 2px;
}

.tdb-panier-qty__btn {
    /* MOD-IA 2026-09-04 : flex-none — les deux boutons se laissaient comprimer
       par le champ quand la ligne devenait étroite. */
    flex: none;
    width: 32px;
    height: 100%;
    border: 0;
    padding: 0;
    background: transparent;
    font-size: 1rem;
    line-height: 1;
    color: var( --color-text );
    display: flex;
    align-items: center;
    justify-content: center;
    transition: background-color var( --duration-tdb ) var( --ease-tdb );
}

.tdb-panier-qty__btn:hover {
    background: var( --color-surface-muted );
}

.tdb-panier-item__prix {
    text-align: right;
}

.tdb-panier-item__prix-unite {
    display: block;
    font-size: var( --text-caption-size );
    color: var( --color-text-muted );
}

.tdb-panier-item__sous-total {
    font-family: var( --font-heading );
    font-weight: var( --weight-semibold );
    color: var( --color-primary );
    font-size: var( --text-h4-size );
    font-variant-numeric: tabular-nums;
}

.tdb-panier-item__retirer {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    padding: 2px;
    border-radius: 6px;
    color: var( --color-text-muted );
    font-size: var( --text-caption-size );
    text-decoration: none;
    transition: color .15s ease, background-color .15s ease;
}

.tdb-panier-item__retirer svg {
    width: 14px;
    height: 14px;
}

.tdb-panier-item__retirer:hover {
    color: var( --color-status-expired-text );
    background: #fdeceb;
}

.tdb-panier-actions {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var( --space-md );
    padding: var( --space-md );
    background: var( --color-surface );
    border-radius: var( --radius-card );
    box-shadow: var( --shadow-card );
}

.tdb-panier-coupon {
    display: flex;
    gap: var( --space-xs );
    flex: 1 1 260px;
}

.tdb-panier-coupon__champ {
    flex: 1 1 auto;
    height: 46px;
    border-radius: var( --radius-sm );
    border: 1px solid var( --color-text-muted );
    padding-inline: var( --space-md );
    font-family: var( --font-body );
}

.tdb-panier-recap-carte {
    background: var( --color-surface );
    border-radius: var( --radius-card );
    box-shadow: var( --shadow-card );
    padding: var( --space-lg );
    position: sticky;
    top: var( --space-lg );
}

.tdb-panier-recap-carte h2 {
    margin: 0 0 var( --space-md );
    font-family: var( --font-heading );
    font-size: var( --text-h3-size );
    line-height: var( --text-h3-lh );
    font-weight: var( --weight-semibold );
}

.tdb-panier-recap-ligne {
    display: flex;
    justify-content: space-between;
    gap: var( --space-md );
    padding-block: var( --space-xs );
    font-size: var( --text-card-desc-size );
}

.tdb-panier-recap-ligne--remise {
    color: var( --color-status-expired-text );
}

.tdb-panier-recap-separateur {
    border: 0;
    border-top: 1px solid var( --color-border );
    margin: var( --space-sm ) 0;
}

.tdb-panier-recap-total {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    margin-block: var( --space-sm ) var( --space-lg );
}

.tdb-panier-recap-total__label {
    font-family: var( --font-heading );
    font-weight: var( --weight-semibold );
}

.tdb-panier-recap-total__valeur {
    font-family: var( --font-heading );
    font-weight: var( --weight-semibold );
    font-size: var( --text-h2-size );
    color: var( --color-primary );
    font-variant-numeric: tabular-nums;
}

.tdb-panier-recap-checkout__btn {
    width: 100%;
}

/* MOD-IA 2026-09-04 : lien « Continuer mes achats » et encart de réassurance
   du récapitulatif (woocommerce/cart/cart-totals.php), tous deux repris de la
   maquette validée. Le lien reprend le rôle du bouton fantôme de la maquette
   (texte gris souligné, pleine largeur, sans fond) : la variante .btn--ghost
   du thème a un fond gris et une hauteur de bouton, qui l'auraient mis au même
   niveau visuel que « Passer la commande ». */
.tdb-panier-continuer {
    display: block;
    margin-top: var( --space-sm );
    text-align: center;
    color: var( --color-text-muted );
    font-size: var( --text-button-size );
    line-height: var( --text-button-lh );
    text-decoration: underline;
    transition: color var( --duration-tdb ) var( --ease-tdb );
}

.tdb-panier-continuer:hover,
.tdb-panier-continuer:focus-visible {
    color: var( --color-text );
}

.tdb-panier-recap-note {
    display: flex;
    gap: 6px;
    margin: var( --space-md ) 0 0;
    padding: var( --space-sm );
    border-radius: var( --radius-sm );
    background: var( --color-surface-muted );
    color: var( --color-text-muted );
    font-size: var( --text-caption-size );
    line-height: var( --text-caption-lh );
}

.tdb-panier-recap-note__icone {
    flex-shrink: 0;
}

@media ( max-width: 900px ) {
    .tdb-panier-grid {
        grid-template-columns: 1fr;
    }
    .tdb-panier-recap-carte {
        position: static;
    }
}

@media ( max-width: 600px ) {
    .tdb-panier-item {
        grid-template-columns: 1fr;
        gap: var( --space-sm );
    }
    .tdb-panier-item__side {
        flex-direction: row;
        align-items: center;
        justify-content: space-between;
        width: 100%;
    }
}

/* ==========================================================================
   Back-office commerçant (page-connexion.php, page-tableau-de-bord.php,
   page-mon-compte.php)
   ========================================================================== */
.tdb-connexion {
    display: flex;
    align-items: center;
    justify-content: center;
    min-height: 100vh;
    background: var( --color-primary ); /* fond orange plein de la maquette (F-1) */
    padding-block: var( --space-3xl );
}

/* Fond blanc manquant (préexistant, invisible tant que le fond de page était
   blanc aussi) : sans lui, le formulaire flotte directement sur le fond
   orange plein (F-1) et le logo — dont la moitié droite est du même orange —
   y devient illisible, indiscernable du fond. */
.tdb-connexion__box {
    width: 465px;
    max-width: 100%;
    background: var( --color-surface );
    border-radius: 20px;
    overflow: hidden;
    box-shadow: var( --shadow-popover );
}

/* "box identifiant" (2015:3957) : padding 60px/40px, 60px entre le logo et
   le groupe de champs, 23px entre deux champs, 10px entre libellé et champ. */
.tdb-connexion__form {
    display: flex;
    flex-direction: column;
    gap: 23px;
}

/* :not(.tdb-checkbox) — cette règle ne doit s'appliquer qu'aux labels de
   champ texte ; sans cette exclusion elle écrasait .tdb-checkbox (I-6) et
   centrait/empilait les cases "Type de bons vendu" au lieu de les aligner à
   gauche sur une ligne. */
.tdb-connexion__form > label,
.tdb-compte-form label:not( .tdb-checkbox ) {
    display: flex;
    flex-direction: column;
    gap: 10px;
    font-size: var( --text-card-desc-size ); /* 14px Light (2015:3965) */
    line-height: var( --text-card-desc-lh );
    letter-spacing: var( --tracking-tight );
    font-weight: var( --weight-light );
}

/* MOD-IA 2026-09-02 : la règle ci-dessus a été écrite pour l'ANCIEN balisage de
   « Mon compte » — <label><span>libellé</span><input></label> — où le libellé
   et le champ étaient tous deux enfants du <label>, d'où le flex en colonne.

   Depuis le passage de cette page à tdb_ui( 'champ' ), le <label> ne contient
   plus que son texte et l'astérisque : le flex en colonne faisait donc tomber
   l'astérisque SOUS le libellé, avec 10px d'écart, et le 14px Light écrasait le
   13px Medium du composant.

   La règle de gabarit (0-2-1) l'emportait sur .tdb-champ label (0-1-1) : c'est
   exactement le « on ne descend jamais dans un composant » que la charte
   interdit. On lui retire donc les labels du composant, ici plutôt que par un
   :not() à sélecteur complexe — même spécificité, mais placée après, et
   compatible partout.

   Les labels hors composant (formulaires ACF, générer/valider un bon) gardent
   la règle d'origine : elle n'est pas supprimée, seulement bornée. */
.tdb-compte-form .tdb-champ label {
    display: block;
    gap: 0;
    font-size: 13px;
    line-height: 1.4;
    font-weight: var( --weight-medium );
}

.tdb-connexion__logo {
    margin: 60px 40px 0; /* padding vertical de 60px de la boîte blanche */
}

/* MOD-IA 2026-09-01 : le retrait de 40px ne doit viser QUE les libellés de
   champ ("Identifiant ou e-mail", "Mot de passe"), qui sont posés directement
   dans la boîte blanche sans retrait propre. Le sélecteur attrapait aussi le
   <label> de « Se souvenir de moi », qui vit dans .tdb-connexion__footer —
   lequel porte déjà un padding de 40px : la case se retrouvait décalée de
   80px au total et n'était plus alignée sur le bouton « Me connecter »
   (mesuré : bouton à x=56, case à x=96). Même famille de défaut que I-6, où
   un sélecteur `label` trop large écrasait .tdb-checkbox. */
/* ANCIEN CODE :
.tdb-connexion__form label {
    padding-inline: 40px;
}
*/
.tdb-connexion__form label:not( .tdb-checkbox ) {
    padding-inline: 40px;
}

.tdb-connexion__form input[type="text"],
.tdb-connexion__form input[type="password"],
.tdb-compte-form input[type="text"],
.tdb-compte-form input[type="password"],
.tdb-compte-form input[type="email"],
.tdb-compte-form input[type="number"],
.tdb-compte-form input[type="date"],
.tdb-compte-form textarea {
    height: 60px;
    border: 1px solid var( --color-text-muted );
    border-radius: var( --radius-sm );
    padding-inline: var( --space-md );
    font-family: var( --font-body );
}

.tdb-compte-form textarea {
    height: auto;
    padding-block: var( --space-sm );
}

/* MOD-IA 2026-09-08 : les listes déroulantes reçoivent enfin l'habillage des
   autres champs.

   La règle ci-dessus énumère les types d'<input> et le <textarea>, mais pas le
   <select> : aucune règle du thème ne visait `.tdb-compte-form select`. Tant
   que les seuls formulaires du back-office étaient ceux du thème, cela ne se
   voyait guère. Les écrans repris de PassVal (« Génération de bons »,
   « Validation d'un bon ») sont eux construits autour de listes déroulantes —
   type de bon, prestation — qui seraient restées au style natif du navigateur
   au milieu de champs de 60px à filet arrondi.

   La flèche est dessinée en SVG inline (data:) plutôt que chargée depuis
   assets/ : la CSS du thème est servie telle quelle, sans réécriture d'URL
   relative, et un fichier de plus pour un chevron de 10px n'apporterait rien. */
/* MOD-IA 2026-09-08 : les listes déroulantes des formulaires ACF du compte
   reçoivent le même habillage.

   Les écrans « Mon compte » servis par PassVal (fiche commerçant, modèle PDF,
   option bons valeurs) sont des acf_form() : leurs champs texte étaient déjà
   habillés par le thème, mais leurs <select> gardaient la flèche et la hauteur
   natives du navigateur — visible sur « Modèle PDF » à côté d'un champ de 60px
   à filet arrondi. On étend donc la règle ci-dessous à `.acf-field select`,
   plutôt que d'écrire un second bloc qui dériverait du premier. */
.tdb-compte-form select,
.tdb-bo__content .acf-field select {
    height: 60px;
    border: 1px solid var( --color-text-muted );
    border-radius: var( --radius-sm );
    padding-inline: var( --space-md );
    padding-right: calc( var( --space-md ) + 20px );
    font-family: var( --font-body );
    background-color: #fff;
    background-image: url( "data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8' fill='none'%3E%3Cpath d='M1 1.5 6 6.5l5-5' stroke='%23000' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E" );
    background-repeat: no-repeat;
    background-position: right var( --space-md ) center;
    appearance: none;
    -webkit-appearance: none;
}

/* MOD-IA 2026-09-08 : rangée de champs côte à côte.

   `.tdb-compte-form__row` était déjà employée par
   template-parts/backoffice/actions-bons.php sans qu'AUCUNE règle ne la
   définisse : ses champs s'empilaient donc au lieu de se ranger sur une ligne.
   Les écrans repris de PassVal s'appuient sur la même classe. Comme
   `.tdb-compte-form__grid`, elle repasse sur une colonne en mobile. */
.tdb-compte-form__row {
    display: flex;
    flex-wrap: wrap;
    gap: var( --space-md );
}

.tdb-compte-form__row > * {
    flex: 1 1 200px;
    min-width: 0;
}

@media ( max-width: 767px ) {
    .tdb-compte-form__row {
        flex-direction: column;
        /* MOD-IA 2026-09-22 : MC2 — « gros espaces entre les champs type de
           bons et nombre dans la génération de bons ».

           Le `gap: 16px` de la règle de base est un écart HORIZONTAL entre
           deux colonnes : parfaitement dosé en desktop. En passant la rangée
           en colonne, le mobile transformait ce même écart en écart VERTICAL,
           qui venait s'ajouter aux marges propres des libellés et des champs
           de 60px. Le défaut n'était pas propre à cet écran : il touchait
           TOUTES les rangées `.tdb-compte-form__row` en mobile.

           On dissocie donc les deux axes : l'écart horizontal reste celui du
           desktop, l'écart vertical descend à 8px, cohérent avec le rythme des
           autres champs empilés du formulaire.
           ANCIEN CODE : (gap: var( --space-md ) hérité de la règle de base) */
        row-gap: var( --space-xs );
        column-gap: var( --space-md );
    }

    /* MOD-IA 2026-09-22 : MC2 — le `flex: 1 1 200px` n'a plus de sens en
       colonne : la largeur y est de toute façon de 100 %, et la base de 200px
       n'y sert qu'à introduire une hauteur minimale parasite. */
    .tdb-compte-form__row > * {
        flex: 0 0 auto;
    }
}

/* MOD-IA 2026-09-08 : un bouton d'envoi ne prend pas toute la largeur du
   formulaire.

   `.tdb-compte-form` empile ses enfants en colonne, qui s'étirent donc par
   défaut sur toute la largeur. Tant que les formulaires faisaient 322px (voir
   la largeur imposée par PassVal, corrigée dans son global-account.css), cela
   ne se remarquait pas ; à pleine largeur, le bouton « Générer » devenait une
   barre orange de plus de 1000px.

   La règle ne vise QUE les <input type="submit"> portant .btn — c'est-à-dire
   les formulaires repris de PassVal. Les <button> rendus par tdb_ui( 'bouton' )
   dans les gabarits du thème gardent le comportement qu'ils avaient. */
/* MOD-IA 2026-09-21 : G2 — rustine devenue redondante, même raison que pour
   .tdb-filtres__carte .btn : `width: fit-content` sur .btn (ui/01-boutons.css)
   borne la largeur de tous les boutons, <input type="submit"> compris.
   ANCIEN CODE :
.tdb-compte-form input[type="submit"].btn {
    align-self: flex-start;
}
*/

/* MOD-IA 2026-09-08 : écran « Valider un bon » de PassVal.

   Le bloc de résultat est produit par PassvalBlocResultatBon()
   (wp-content/plugins/passval/valezy_gutenberg_blocks/custom_gutenberg_blocks.php),
   qui remplace la quinzaine de recopies à la main de `.messageContainer`. Les
   règles vivent ici, dans le thème, et non dans l'extension : c'est le thème
   qui porte la charte, et PassVal reste lisible sans elle.

   Deux états seulement — refusé et utilisable — là où l'ancien balisage
   distinguait quatre classes (.notExist, .notActivate, .alreadyUse, .canUse)
   pour deux apparences réelles. */
/* MOD-IA 2026-09-08 : le bloc est CENTRÉ, et son verdict passe au premier plan
   — demande client du 08.09.2026 (« je n'aime pas comment le texte pour la
   validation est mis, centre les éléments dedans »).

   Ce qu'il était : une grille de deux colonnes — une pastille de 34px à gauche,
   un pavé de texte aligné à gauche à droite — où le motif du refus (« CE BON
   N'EST PAS ACTIVÉ ! ») était rendu à la même échelle que le numéro qu'il
   commente, sur la deuxième ligne d'une liste. Rien ne se détachait : au
   comptoir, il fallait LIRE le bloc pour savoir si le bon passait.

   Ce qu'il est : une colonne centrée — pastille, verdict en grand, puis le
   numéro et le montant côte à côte en dessous. Le verdict se lit d'un mètre,
   les détails restent à portée d'œil.

   ANCIEN CODE :
   .tdb-validation-resultat {
       display: grid;
       grid-template-columns: auto 1fr;
       align-items: start;
       gap: var( --space-md );
       padding: var( --space-lg );
       border: 1px solid #ECECEC;
       border-radius: 20px;
       background: #fff;
       text-align: left;
   } */
.tdb-validation-resultat {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: var( --space-md );
    padding: var( --space-xl ) var( --space-lg );
    border: 1px solid var( --color-border );
    border-radius: 20px;
    background: #fff;
    text-align: center;
}

/* MOD-IA 2026-09-08 : la couleur de l'état ne tient plus à la seule pastille.
   Le panneau entier prend un fond et un filet teintés : c'est ce qui se voit
   en premier, avant même d'avoir lu quoi que ce soit. */
.tdb-validation-resultat--succes {
    background: var( --color-status-validated-surface );
    border-color: var( --color-status-validated-line );
}

.tdb-validation-resultat--erreur {
    background: var( --color-status-expired-surface );
    border-color: var( --color-status-expired-line );
}

/* MOD-IA 2026-09-08 : pastille refaite — demande client du 08.09.2026 (« la
   pastille verte et rouge n'est pas assez visible »).

   Trois causes à cela, toutes corrigées ici :
     1. la TAILLE : 34px de diamètre, la même qu'un rang du fil d'étapes, pour
        l'élément qui porte le verdict. Elle passe à 64px ;
     2. la COULEUR : --color-status-validated (#99D7A3) et
        --color-status-expired (#FD6060) sont les pastels des badges, prévus
        pour un texte NOIR. Sous du blanc ils tombent à 1,7:1 et 2,6:1 — le
        glyphe s'y effaçait. On prend leurs tons foncés (5,2:1 et 5,6:1) ;
     3. le HALO : un anneau de la teinte pastel détache la pastille du fond
        teinté du panneau, qui sinon la mangeait.
   Le contenu, lui, n'est plus un caractère de texte mais un pictogramme tracé
   (voir PassvalIconeResultatBon() dans l'extension).

   ANCIEN CODE :
   .tdb-validation-resultat__pastille {
       display: inline-flex;
       align-items: center;
       justify-content: center;
       width: 34px;
       height: 34px;
       border-radius: 50%;
       font-weight: var( --weight-medium );
       color: #fff;
   }
   .tdb-validation-resultat--erreur .tdb-validation-resultat__pastille {
       background: var( --color-status-expired, #D64545 );
   }
   .tdb-validation-resultat--succes .tdb-validation-resultat__pastille {
       background: var( --color-status-validated, #3F9142 );
   } */
.tdb-validation-resultat__pastille {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex: 0 0 auto;
    width: 64px;
    height: 64px;
    border-radius: 50%;
    color: #fff;
}

.tdb-validation-resultat__pastille svg {
    width: 32px;
    height: 32px;
}

/* Les deux halos reprennent --color-status-expired / --color-status-validated
   en transparence. Écrits en rgba() plutôt qu'en color-mix() : la webview de
   l'aperçu mobile (WPMobile.App) ne la connaît pas partout, et un halo qui
   disparaît vaut mieux qu'une pastille sans fond. */
.tdb-validation-resultat--erreur .tdb-validation-resultat__pastille {
    background: var( --color-status-expired-strong );
    box-shadow: 0 0 0 8px rgba( 253, 96, 96, .28 );
}

.tdb-validation-resultat--succes .tdb-validation-resultat__pastille {
    background: var( --color-status-validated-strong );
    box-shadow: 0 0 0 8px rgba( 153, 215, 163, .45 );
}

/* MOD-IA 2026-09-08 : le verdict, en titre. Il vient de l'extension
   (clé `titre` de PassvalControlerBon()), qui l'a sorti de la liste des
   lignes où il passait inaperçu. */
.tdb-validation-resultat__titre {
    margin: 0;
    font-family: var( --font-heading );
    font-size: 20px;
    line-height: 1.25;
    font-weight: var( --weight-semibold );
    letter-spacing: var( --tracking-tight );
    text-wrap: balance;
}

.tdb-validation-resultat--succes .tdb-validation-resultat__titre {
    color: var( --color-status-validated-strong );
}

.tdb-validation-resultat--erreur .tdb-validation-resultat__titre {
    color: var( --color-status-expired-strong );
}

/* MOD-IA 2026-09-08 : les lignes ne s'empilent plus, elles se rangent côte à
   côte au centre — deux couples courts (numéro, montant), qui se lisent mieux
   sur une ligne qu'en tableau à filets.
   ANCIEN CODE :
   .tdb-validation-resultat__lignes {
       margin: 0;
       display: flex;
       flex-direction: column;
       gap: var( --space-sm );
   } */
.tdb-validation-resultat__lignes {
    margin: 0;
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: var( --space-sm ) var( --space-xl );
}

/* MOD-IA 2026-09-08 : libellé AU-DESSUS de sa valeur, tous deux centrés, au
   lieu du couple libellé-à-gauche / valeur-à-droite séparé par un filet.
   ANCIEN CODE :
   .tdb-validation-resultat__ligne {
       display: flex;
       flex-wrap: wrap;
       justify-content: space-between;
       gap: var( --space-sm );
       padding-bottom: var( --space-sm );
       border-bottom: 1px solid #ECECEC;
   }
   .tdb-validation-resultat__ligne:last-child {
       padding-bottom: 0;
       border-bottom: 0;
   } */
.tdb-validation-resultat__ligne {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 2px;
}

.tdb-validation-resultat__ligne dt {
    font-size: var( --text-caption-size );
    font-weight: var( --weight-light );
    color: var( --color-text-muted );
}

/* La valeur est ce qu'on relit pour vérifier : chasse fixe et lettres
   espacées, comme dans le champ de saisie du numéro. */
.tdb-validation-resultat__ligne dd {
    margin: 0;
    font-family: var( --font-heading );
    font-size: 18px;
    font-weight: var( --weight-medium );
    letter-spacing: .04em;
    font-variant-numeric: tabular-nums;
    color: var( --color-text );
}

/* MOD-IA 2026-09-29 : ligne pleine largeur (la prestation) — elle passe seule
   sous le numéro du bon ; un titre long s'y replie sur plusieurs lignes,
   centré, au lieu d'être serré à côté du numéro. */
.tdb-validation-resultat__ligne--pleine {
    flex-basis: 100%;
    min-width: 0;
}

.tdb-validation-resultat__ligne--pleine dd {
    letter-spacing: normal;
    text-align: center;
    text-wrap: balance;
    overflow-wrap: anywhere;
}

/* MOD-IA 2026-09-08 : plus de `grid-column` — le bloc n'est plus une grille. */
.tdb-validation-resultat__note {
    margin: 0;
    font-size: var( --text-caption-size );
    font-style: italic;
    color: var( --color-text-muted );
}

/* MOD-IA 2026-09-08 : actions centrées sous un panneau centré. */
.tdb-validation-actions {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    align-items: center;
    gap: var( --space-sm );
    margin-top: var( --space-md );
}

/* MOD-IA 2026-09-08 : neutralisation de `#useBon` (PassVal,
   valezy_gutenberg_blocks/css/validate.css lignes 161-165), repérée à l'écran
   le 08.09.2026 en jouant la validation de TDB025001.

   Cette feuille pose sur le bouton d'encaissement :
       #useBon { margin-top: 16px; border-radius: 3px; }
   Un sélecteur d'ID l'emporte sur toutes les classes du thème : le bouton
   principal descendait donc de 16px sous son voisin « Vérifier un autre bon »
   — deux boutons côte à côte et désaxés — et gardait un rayon de 3px là où la
   charte en veut 10.

   On neutralise ici plutôt que d'éditer validate.css : c'est le thème qui porte
   la charte, et PassVal doit rester utilisable sans lui (avec sa feuille seule,
   les 16px gardent leur sens : le bouton y était seul sous un bloc de texte).
   `.tdb-validation-actions #useBon` pèse (0,1,1,0) et suffit à passer devant
   (0,1,0,0) : aucun !important nécessaire. */
.tdb-validation-actions #useBon {
    margin-top: 0;
    border-radius: var( --radius-sm );
}

/* MOD-IA 2026-09-08 : le champ « Montant à utiliser » d'une carte décomptable
   est le seul élément à saisir de ce panneau : il se centre avec lui. */
.tdb-validation-montant {
    margin-top: var( --space-md );
    margin-inline: auto;
    max-width: 260px;
    text-align: center;
}

/* `.warning` est la classe d'origine de PassVal : on la garde dans le sélecteur
   pour que les branches non reprises gardent une apparence cohérente. */
.tdb-validation-avertissement,
.tdb-validation-resultat + .warning {
    margin-top: var( --space-md );
    font-size: var( --text-card-desc-size );
    color: var( --color-text-muted );
}

/* MOD-IA 2026-09-08 : le repli mobile de la grille n'a plus d'objet — le bloc
   est une colonne centrée à toutes les largeurs. Seules la pastille et le
   verdict se resserrent, pour ne pas manger l'écran.
   ANCIEN CODE :
   @media ( max-width: 767px ) {
       .tdb-validation-resultat {
           grid-template-columns: 1fr;
       }
       .tdb-validation-resultat__note {
           grid-column: 1;
       }
   } */
@media ( max-width: 767px ) {
    .tdb-validation-resultat {
        padding: var( --space-lg ) var( --space-md );
    }

    .tdb-validation-resultat__pastille {
        width: 56px;
        height: 56px;
    }

    .tdb-validation-resultat__pastille svg {
        width: 28px;
        height: 28px;
    }

    .tdb-validation-resultat__titre {
        font-size: 18px;
    }
}

/* MOD-IA 2026-09-08 : remontée de 8px supprimée et hauteur de ligne posée —
   vérification de parité desktop du 08.09.2026.

   Dans « Box connection » (2015:4000), « Mot de passe perdu? » est à y=230 du
   groupe de champs, soit 23px sous le champ mot de passe qui finit à 207 — le
   même écart qu'entre les deux champs. La colonne applique déjà ce `gap: 23px` ;
   la marge négative le ramenait à 15 et décalait le lien de 8px vers le haut.

   Le lien fait par ailleurs 18 de haut dans la maquette, contre 20 ici faute de
   `line-height` déclarée.

   ANCIEN CODE : margin: -8px 40px 0 0; */
.tdb-connexion__perdu {
    align-self: flex-end;
    margin: 0 40px 0 0;
    color: var( --color-text-muted );
    font-size: var( --text-caption-size );
    line-height: 18px;
    /* MOD-IA 2026-09-01 : souligné dans la maquette (6174:8145), sans
       décoration dans le thème. C'est le seul lien de la boîte : le
       soulignement est ce qui le donne à lire comme tel. */
    text-decoration: underline;
    text-underline-offset: 2px;
}

/* "footer" (2015:3951) : padding 20px haut / 30px bas / 40px côtés. */
/* MOD-IA 2026-09-08 : 34px d'écart supplémentaire au-dessus de la barre sombre
   — vérification de parité desktop du 08.09.2026.

   La partie blanche de la boîte (« box identifiant », 2015:3957) fait 465 de
   haut pour un groupe de champs qui finit à 408 : il reste donc 57 avant la
   barre sombre. La colonne n'apportait que son `gap` de 23, et la boîte
   mesurait 520 au lieu des 561 de la maquette. 23 + 34 = 57.

   La barre elle-même était déjà juste : 96 de haut, padding 20/40/30. */
.tdb-connexion__footer {
    margin-top: 34px;
    background: var( --color-ink );
    display: flex;
    align-items: center;
    justify-content: space-between;
    flex-wrap: nowrap;
    gap: var( --space-sm );
    padding: 20px 40px 30px;
}

/* "BTN mascot orange > blanc" (2015:3956) : 46px de haut, padding
   6px à gauche / 15px à droite, gap 10px, badge d'icône blanc de 34px
   au rayon 6px. */
.tdb-connexion__footer .btn {
    height: 46px;
    padding: 6px 15px 6px 6px;
    gap: 10px;
    font-size: var( --text-button-size );
}

.tdb-connexion__footer .btn__icon {
    width: 34px;
    height: 34px;
    border-radius: 6px;
}

/* MOD-IA 2026-09-02 : .tdb-checkbox--light déplacé tel quel vers
   assets/css/ui/02-formulaires.css (aucune valeur changée) — famille « Formulaires »
   de la charte graphique. */

/* La case blanche à filet orange de la boîte de connexion (2015:3954) est
   déjà couverte par la règle générique .tdb-checkbox input[type=checkbox]. */

@media ( max-width: 767px ) {
    /* Mobile (6174:8145) : le bouton "Me connecter" passe au-dessus de la
       case "Se souvenir de moi", les deux empilés et alignés à gauche —
       ordre inverse du desktop (F-2). */
    /* MOD-IA 2026-09-01 : géométrie relevée sur « phone BO box connection »
       (2068:6325) : la boîte fait 341 de large, posée à x=24 — donc 24px de
       marge de chaque côté, et non les 15 de --space-md. Le thème rendait une
       boîte de 362 collée aux bords. */
    /* ANCIEN CODE : padding-inline: var( --space-md ); */
    .tdb-connexion {
        padding-inline: 24px;
    }
    /* Le logo occupait 248px de large contre ~168 dans la maquette, ce qui
       gonflait la hauteur de la boîte (538 rendus contre 451). */
    .tdb-connexion__logo {
        margin: 40px 24px 0;
    }
    .tdb-connexion__logo img {
        width: 168px;
        height: auto;
    }
    .tdb-connexion__footer {
        flex-direction: column;
        align-items: flex-start;
        gap: var( --space-md );
    }
    .tdb-connexion__footer .btn {
        order: 1;
    }
    .tdb-connexion__footer .tdb-checkbox--light {
        order: 2;
        white-space: normal;
    }
}


/* --------------------------------------------------------------------------
   MOD-IA 2026-09-02 : formulaires Theme My Login (connexion, inscription,
   mot de passe perdu / réinitialisation).

   Le balisage n'est plus écrit par le gabarit mais produit par l'extension :
   au lieu de `.tdb-connexion__form > label`, on reçoit une suite de
   `.tml-field-wrap` contenant `label.tml-label` + le contrôle. Les règles
   ci-dessous transposent la géométrie de « box identifiant » (2015:3957) sur
   ce balisage, à valeurs identiques (padding 60/40, 23px entre deux champs,
   10px entre libellé et champ) — c'est un changement de sélecteurs, pas de
   design.
   -------------------------------------------------------------------------- */

/* Le gabarit pose désormais un second enfant sous la boîte (le lien
   « Créer mon compte »). Sans direction de colonne, le flex centrait les deux
   côte à côte. */
.tdb-connexion {
    flex-direction: column;
}

/* Conteneur que TML enroule autour des alertes et du formulaire. Il remplace
   `.tdb-connexion__form` comme boîte de flux verticale : le logo, lui, reste
   posé par le gabarit au-dessus de ce conteneur. */
.tdb-connexion .tml {
    display: flex;
    flex-direction: column;
    gap: 23px;
    margin-top: 60px; /* 60px entre le logo et le premier champ (2015:3957) */
}

.tdb-connexion .tml form {
    display: flex;
    flex-direction: column;
    gap: 23px;
}

/* Un champ = libellé au-dessus du contrôle, retrait de 40px comme les libellés
   du formulaire maison. Les enveloppes de la barre noire (case à cocher,
   bouton) portent leur propre retrait via .tdb-connexion__footer : on les
   exclut ici, faute de quoi elles cumuleraient 80px — même famille de défaut
   que le sélecteur `label` trop large corrigé au-dessus. */
.tdb-connexion .tml-field-wrap {
    display: flex;
    flex-direction: column;
    gap: 10px;
    padding-inline: 40px;
    /* La feuille de TML (chargée avant celle du thème) pose 1em de marge basse
       sur chaque champ : cumulée au gap de 23px de la colonne, elle étirait la
       boîte bien au-delà des 451px de la maquette. */
    margin-bottom: 0;
}

/* Les deux enveloppes de la barre noire ne suivent PAS le gabarit « libellé
   au-dessus du contrôle » : la case à cocher reste sur une ligne (le sélecteur
   .tdb-connexion .tml-field-wrap ci-dessus l'emporte sur .tdb-checkbox, plus
   faible, et l'empilerait), et le bouton n'a pas à s'étirer. */
.tdb-connexion__footer .tml-field-wrap {
    flex-direction: row;
    align-items: center;
    padding-inline: 0;
}

/* `:has()` — TML cible la case à cocher par `.tml .tml-field-wrap:has(.tml-checkbox)`,
   à trois classes : sans le même poids, son gap de .5em l'emporterait sur les
   11px de la maquette (127:1523). */
.tdb-connexion .tdb-connexion__footer .tml-rememberme-wrap {
    gap: 11px;
}

/* « Se souvenir de moi » : légende blanche de 12px de la maquette (2015:3954),
   et non les 14px Light des libellés de champ. */
.tdb-connexion__footer .tml-label {
    color: #fff;
    font-size: var( --text-caption-size );
    line-height: var( --text-caption-lh );
    font-weight: var( --weight-regular );
}

.tdb-connexion .tml-label {
    margin: 0; /* TML pose .5em au-dessus et au-dessous du libellé */
    font-size: var( --text-card-desc-size ); /* 14px Light (2015:3965) */
    line-height: var( --text-card-desc-lh );
    letter-spacing: var( --tracking-tight );
    font-weight: var( --weight-light );
}

.tdb-connexion .tml input[type="text"],
.tdb-connexion .tml input[type="email"],
.tdb-connexion .tml input[type="password"],
.tdb-connexion .tml input[type="tel"],
.tdb-connexion .tml input[type="number"] {
    width: 100%;
    height: 60px;
    border: 1px solid var( --color-text-muted );
    border-radius: var( --radius-sm );
    padding-inline: var( --space-md );
    font-family: var( --font-body );
}

/* TML pose le champ mot de passe et son bouton « afficher » dans un même
   .tml-pwd ; sans position relative, le bouton (absolu) irait se caler sur la
   boîte blanche entière. */
.tdb-connexion .tml-pwd {
    position: relative;
    display: flex;
    align-items: center;
}

.tdb-connexion .tml-toggle-pwd {
    position: absolute;
    right: 8px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 40px;
    height: 40px;
    border: 0;
    background: none;
    color: var( --color-text-muted );
    cursor: pointer;
}

/* Indicateur de robustesse du mot de passe (inscription) : c'est du mobilier
   d'administration WordPress, ramené à la typographie des légendes du thème. */
.tdb-connexion #pass-strength-result,
.tdb-connexion .indicator-hint {
    margin: 0;
    font-size: var( --text-caption-size );
    line-height: var( --text-caption-lh );
    color: var( --color-text-muted );
}

.tdb-connexion #pass-strength-result {
    padding: 6px var( --space-sm );
    border-radius: var( --radius-sm );
    background: var( --color-surface-muted );
}

.tdb-connexion #pass-strength-result.short,
.tdb-connexion #pass-strength-result.bad {
    background: var( --color-status-expired );
    color: #fff;
}

.tdb-connexion #pass-strength-result.good {
    background: var( --color-status-pending );
}

.tdb-connexion #pass-strength-result.strong {
    background: var( --color-status-validated );
}

.tdb-connexion .tml-description {
    margin: 0;
    font-size: var( --text-caption-size );
    line-height: var( --text-caption-lh );
    /* TML met ses descriptions en italique ; le thème n'utilise l'italique
       nulle part ailleurs. */
    font-style: normal;
    color: var( --color-text-muted );
}

/* Le lien « Mot de passe perdu? » est rendu comme un champ : son enveloppe ne
   doit pas ajouter le retrait de 40px une seconde fois (le lien porte déjà sa
   propre marge dans .tdb-connexion__perdu). */
.tdb-connexion .tml-tdb_liens-wrap {
    padding-inline: 0;
}

/* Alertes de TML (identifiant inconnu, e-mail déjà utilisé, mot de passe
   envoyé…) : mêmes codes que .tdb-notice, en retrait de 40px pour s'aligner
   sur les champs. Le conteneur .tml-alerts est toujours présent, même vide :
   il n'a donc ni marge ni fond propre. */
.tdb-connexion .tml-alerts {
    padding-inline: 40px;
}

.tdb-connexion .tml-alerts:empty {
    display: none;
}

.tdb-connexion .tml-errors,
.tdb-connexion .tml-messages {
    list-style: none;
    margin: 0;
    padding: var( --space-md );
    border-radius: var( --radius-sm );
    border-left: 4px solid var( --color-status-validated );
    background: var( --color-surface-muted );
    font-size: var( --text-card-desc-size );
    line-height: var( --text-card-desc-lh );
}

.tdb-connexion .tml-errors {
    border-left-color: var( --color-status-expired );
}

/* Erreur attachée à un champ précis (mot de passe non confirmé, par exemple). */
.tdb-connexion .tml-field-wrap .tml-error {
    font-size: var( --text-caption-size );
    line-height: var( --text-caption-lh );
    color: var( --color-status-expired );
}

/* La barre noire reçoit maintenant, selon l'écran, un lien de retour à gauche
   plutôt que la case « Se souvenir de moi ». */
.tdb-connexion__retour {
    color: #fff;
    font-size: var( --text-caption-size );
    line-height: var( --text-caption-lh );
    text-decoration: underline;
    text-underline-offset: 2px;
}

/* Le bouton d'envoi est un <button> produit par TML : il porte déjà .btn
   .btn--primary (posé dans inc/tml.php), il ne manque que la réinitialisation
   des styles natifs de bouton. */
.tdb-connexion .tml-submit-wrap .btn {
    border: 0;
    cursor: pointer;
}

/* Entrée vers l'inscription, sous la boîte, sur le fond orange plein. */
.tdb-connexion__inscription {
    margin: var( --space-lg ) 0 0;
    color: #000;
    font-size: var( --text-card-desc-size );
    line-height: var( --text-card-desc-lh );
    text-align: center;
}

.tdb-connexion__inscription a {
    font-weight: var( --weight-semibold );
    text-decoration: underline;
    text-underline-offset: 2px;
}

/* ---------- Inscription commerçant ----------
   Même boîte que la connexion, mais le formulaire enchaîne une vingtaine de
   champs ACF : la largeur de 465px de « box identifiant » y devient une
   colonne interminable. On l'élargit et on passe les champs ACF sur deux
   colonnes au-delà du mobile. */
.tdb-inscription__box {
    width: 760px;
}

.tdb-inscription__titre {
    margin: 0;
    font-size: var( --text-h2-size );
    line-height: var( --text-h2-lh );
    letter-spacing: var( --tracking-tight );
}

/*
 * MOD-IA 2026-09-22 : I1 — en-tête de la page d'inscription (titre + chapeau).
 *
 * Classes DISTINCTES de .tdb-inscription__titre, qui sert déjà au « Votre
 * compte » injecté dans le formulaire par inc/tml.php:260 : ce dernier vit
 * dans le <form> et reçoit son retrait de `.tdb-inscription .tml form > h2`.
 * L'en-tête, lui, est posé directement dans la boîte blanche et doit porter le
 * retrait de 40px comme le logo (.tdb-connexion__logo).
 */
.tdb-inscription__entete-titre {
    margin: var( --space-md ) 40px 0;
    font-size: var( --text-h2-size );
    line-height: var( --text-h2-lh );
    letter-spacing: var( --tracking-tight );
}

.tdb-inscription__entete-chapeau {
    margin: var( --space-xs ) 40px 0;
    color: var( --color-text-muted );
}

/* Titres des groupes ACF (« Coordonnées de l'entreprise », « Coordonnées de la
   personne de contact ») : ACF les sort en <h2> nus. */
.tdb-inscription .tml form > h2 {
    margin: var( --space-md ) 40px 0;
    font-size: var( --text-h2-size );
    line-height: var( --text-h2-lh );
    letter-spacing: var( --tracking-tight );
}

.tdb-inscription .acf-fields {
    display: grid;
    grid-template-columns: repeat( 2, minmax( 0, 1fr ) );
    gap: 23px;
    padding-inline: 40px;
    border: 0;
}

/* ACF positionne ses champs en absolu/flottant dans wp-admin ; en front il
   suffit de neutraliser ses largeurs pour que la grille reprenne la main. */
.tdb-inscription .acf-fields > .acf-field {
    width: auto;
    min-width: 0;
    padding: 0;
    border: 0;
}

/* Un champ long (présentation de l'entreprise, adresse) prend toute la
   largeur : sur deux colonnes il se retrouverait à ~330px, illisible pour un
   texte de plusieurs lignes. */
.tdb-inscription .acf-fields > .acf-field-textarea,
.tdb-inscription .acf-fields > .acf-field-wysiwyg,
.tdb-inscription .acf-fields > .acf-field-image,
.tdb-inscription .acf-fields > .acf-field-file {
    grid-column: 1 / -1;
}

.tdb-inscription .acf-field .acf-label label {
    font-size: var( --text-card-desc-size );
    line-height: var( --text-card-desc-lh );
    letter-spacing: var( --tracking-tight );
    font-weight: var( --weight-light );
}

.tdb-inscription .acf-field .acf-label {
    margin-bottom: 10px;
}

.tdb-inscription .acf-field .acf-label p.description {
    font-size: var( --text-caption-size );
    line-height: var( --text-caption-lh );
    color: var( --color-text-muted );
}

.tdb-inscription .acf-field input[type="text"],
.tdb-inscription .acf-field input[type="email"],
.tdb-inscription .acf-field input[type="url"],
.tdb-inscription .acf-field input[type="tel"],
.tdb-inscription .acf-field input[type="number"],
.tdb-inscription .acf-field input[type="password"],
.tdb-inscription .acf-field select,
.tdb-inscription .acf-field textarea {
    width: 100%;
    height: 60px;
    border: 1px solid var( --color-text-muted );
    border-radius: var( --radius-sm );
    padding-inline: var( --space-md );
    font-family: var( --font-body );
    font-size: var( --text-card-desc-size );
}

.tdb-inscription .acf-field textarea {
    height: auto;
    min-height: 120px;
    padding-block: var( --space-sm );
}

/* Select2, employé par ACF pour les listes (canton, secteurs) : sa hauteur par
   défaut (28px) casserait l'alignement avec les champs texte de 60px. */
.tdb-inscription .acf-field .select2-container .select2-selection--single {
    height: 60px;
    border: 1px solid var( --color-text-muted );
    border-radius: var( --radius-sm );
}

.tdb-inscription .acf-field .select2-container .select2-selection--single .select2-selection__rendered {
    line-height: 58px;
    padding-inline: var( --space-md );
}

.tdb-inscription .acf-field .select2-container .select2-selection--single .select2-selection__arrow {
    height: 58px;
}

@media ( max-width: 900px ) {
    .tdb-inscription .acf-fields {
        grid-template-columns: minmax( 0, 1fr );
    }
}

@media ( max-width: 767px ) {
    /* Mêmes retraits que la boîte de connexion en mobile (2068:6325) : 24px
       de marge de page, 24px de retrait interne. */
    .tdb-connexion .tml {
        margin-top: 40px;
    }

    .tdb-connexion .tml-field-wrap,
    .tdb-connexion .tml-alerts,
    .tdb-inscription .acf-fields,
    .tdb-inscription .tml form > h2 {
        padding-inline: 24px;
    }

    .tdb-inscription .tml form > h2 {
        margin-inline: 24px;
        padding-inline: 0;
    }

    .tdb-connexion__footer .tml-field-wrap {
        padding-inline: 0;
    }

    .tdb-connexion__perdu {
        margin-right: 24px;
    }

    /* MOD-IA 2026-09-08 : métriques MOBILES de la boîte de connexion — elles
       n'existaient pas, et l'écran rendait les valeurs desktop à toute largeur.
       Vérification faite le 08.09.2026, une fois la session fermée : tant qu'un
       compte était connecté, /connexion/ redirigeait vers « Mon compte » et la
       page n'avait jamais pu être observée.

       Relevé sur « phone BO box connection » (2068:6325, dans la frame
       « SP - connection » 6174:8145) :

         |                     | desktop 2015:4000 | mobile 2068:6325 |
         | boîte               | 465x561           | 341x451          |
         | logo                | 246x40            | 169x27,5         |
         | libellé de champ    | 22                | 15               |
         | champ               | 60                | 45               |
         | écart entre champs  | 23                | 20               |
         | barre du bas        | 96                | 128              |
         | ordre dans la barre | case puis bouton  | BOUTON puis case |

       La boîte mesurait donc 559 de haut au lieu de 451. */
    .tdb-connexion__logo {
        width: 169px;
        height: auto;
        /* 30px du haut de la boîte, contre 60 en desktop. */
        margin-top: 30px;
    }

    .tdb-connexion .tml,
    .tdb-connexion .tml form {
        gap: 20px;
    }

    .tdb-connexion .tml-label {
        font-size: 12px;
        line-height: 15px;
    }

    /* Les mêmes sélecteurs que la règle desktop plus haut, et pas
       `.tdb-connexion .tml-field` : `.tml-field` est posée sur l'`input`
       lui-même, et un sélecteur d'attribut pèse plus lourd qu'une simple
       classe — la surcharge était ignorée et le champ restait à 60. */
    .tdb-connexion .tml input[type="text"],
    .tdb-connexion .tml input[type="email"],
    .tdb-connexion .tml input[type="password"],
    .tdb-connexion .tml input[type="tel"],
    .tdb-connexion .tml input[type="number"] {
        height: 45px;
    }

    /* Dans la maquette mobile, le bouton passe AU-DESSUS de la case à cocher,
       l'inverse du desktop. La barre gagne 32px (128 contre 96) et son padding
       passe à 25. */
    .tdb-connexion__footer {
        margin-top: 8px;
        gap: 20px;
        padding: 25px;
    }

    .tdb-connexion__footer > .tml-field-wrap:first-child {
        order: 2;
    }

    /* Bouton de 40 et ligne « Se souvenir de moi » de 18, contre 46 et 22 en
       desktop (« phone BTN mascot orange > blanc » 142x40 dans 2068:6325). */
    .tdb-connexion__footer .btn {
        height: 40px;
    }

    .tdb-connexion__footer .tml-rememberme-wrap {
        line-height: 18px;
    }

    /* Le lien de retour de la barre noire suit l'empilement du bouton et de la
       case « Se souvenir de moi » (F-2). */
    .tdb-connexion__footer .tdb-connexion__retour {
        order: 2;
    }
}

/* MOD-IA 2026-09-02 : .tdb-notice et .tdb-notice--error déplacé tel quel vers
   assets/css/ui/05-retours.css (aucune valeur changée) — famille « Retours et données »
   de la charte graphique. */

/* ---------- Structure commune BO ---------- */
/* "BO header" (2001:3588) : 1440 × 127, collé en haut de page, SEULS les
   deux coins du bas arrondis (10px) — padding 50px en haut, 30px ailleurs. */
.tdb-bo-header {
    background: var( --color-ink );
    border-radius: 0 0 10px 10px;
    margin-top: 0;
    padding: 50px 30px 30px;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var( --space-lg );
    flex-wrap: wrap;
}

/* "mascot + bienvenue" (2001:3548) : écart de 20px entre la pastille et le
   texte, lui-même en colonne avec 5px entre le sur-titre et le titre. */
.tdb-bo-header__welcome {
    display: flex;
    align-items: center;
    gap: 20px;
    color: inherit;
    text-decoration: none;
}

.tdb-bo-header__welcome > div {
    display: flex;
    flex-direction: column;
    gap: 5px;
}

.tdb-bo-header__mascot {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 43px;
    height: 43px;
    border-radius: 9px;
    background: var( --color-primary );
    flex-shrink: 0;
}

/* MOD-IA 2026-09-08 : hauteurs de ligne posées sur les deux lignes du bandeau
   d'accueil — vérification de parité desktop du 08.09.2026.

   Dans « BO header » (6214:6057), le bloc « mascot + bienvenue » fait 43 de
   haut : « Tableau de bord » occupe 13, « Bienvenue à ... » 25, avec 5 d'écart.
   Sans `line-height` déclarée, les deux héritaient de celle du corps de texte
   (1,625) et mesuraient 16 et 33, soit 54 au lieu de 43.

   Ce bloc devenait alors plus haut que la rangée de boutons (47) et c'est LUI
   qui donnait sa hauteur au bandeau : 50 + 54 + 30 = 134, là où la maquette en
   demande 127 (50 + 47 + 30). Le bandeau étant collé en haut de page, ces 7px
   décalaient tout le back-office vers le bas.

   Les tailles de police sont conformes et ne bougent pas. */
.tdb-bo-header__eyebrow {
    color: #fff;
    font-size: 10px;
    line-height: 13px;
    letter-spacing: var( --tracking-tight );
    margin: 0; /* l'écart de 5px est porté par le gap du conteneur */
}

.tdb-bo-header__title {
    color: #fff;
    font-size: 20px;
    line-height: 25px;
    font-weight: var( --weight-medium );
    margin: 0;
}

.tdb-bo-header__title span {
    color: var( --color-primary );
}

.tdb-bo-header__actions {
    display: flex;
    align-items: center;
    gap: 10px; /* écart des boutons d'en-tête (2001:3556) */
    flex-wrap: wrap;
}

.tdb-bo-header__btn {
    background: #fff;
    padding: 14px 20px;
    border-radius: var( --radius-sm );
    font-size: 12px;
    font-weight: var( --weight-medium );
    white-space: nowrap;
}

.tdb-bo-header__logout {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 47px;
    height: 47px;
    border-radius: var( --radius-sm );
    background: var( --color-primary );
}

.tdb-bo-header__mobile-btn {
    display: none;
}

@media ( max-width: 767px ) {
    /* G-8 : barre compacte, les 4 actions passent dans le menu hors-canevas
       (SP - menu BO, H-1), remplacées par 2 boutons icône blancs. */
    .tdb-bo-header {
        /* MOD-IA 2026-09-22 : MC1 — « alignement / retour a la ligne de
           Bienvenue - Le Centre Chamoson pour avoir le menu et le picto scan
           comme sur figma ».

           Le releve §6 (composant « phone BO header » 2055:5045) donne :
           390 x 84, padding 20 vertical / 15 horizontal, align-items
           flex-start, justify-content space-between, titre borne a 258px,
           deux boutons de 34 avec 10px de gouttiere. Arithmetique :
           390 − 2x15 = 360 ; boutons 78 ; titre 258 -> 24px de respiration.

           Trois ecarts corriges ici :
           - `flex-wrap: wrap` de la regle de base : un titre long faisait
             passer les boutons a la ligne suivante, ou hors cadre. Les deux
             boutons doivent rester sur la rangee du titre ;
           - `align-items: center` : la maquette aligne en HAUT, ce qui compte
             des lors que le titre passe sur deux lignes ;
           - `gap: var( --space-lg )` (24px) : la maquette pose 10px.
           ANCIEN CODE : padding: var( --space-md ); */
        padding: 20px 15px;
        flex-wrap: nowrap;
        align-items: flex-start;
        gap: 10px;
        border-radius: 0px;
    }

    .container:has(.tdb-bo-header){
        padding: 0px;
    }

    /* MOD-IA 2026-09-22 : MC1 — c'est toujours le TITRE qui cede, jamais les
       boutons.

       `min-width: 0` est indispensable : sans lui, un enfant flex refuse de
       passer sous la largeur de son contenu, et « Bienvenue Le Centre
       Chamoson » poussait les deux boutons hors du cadre. Il faut le poser sur
       le lien ET sur le bloc texte imbrique, la contrainte ne se propageant pas
       toute seule.

       Le releve a tranche la question ouverte de la story : RETOUR A LA LIGNE,
       pas troncature — le titre y est borne a 258px avec un interlignage de 20,
       et aucune ellipse n'apparait dans la maquette. On ne pose donc pas
       `text-overflow: ellipsis`.

       Les boutons portent deja `flex-shrink: 0` (voir plus bas). */
    .tdb-bo-header__welcome {
        flex: 1 1 auto;
        min-width: 0;
        align-items: flex-start;
    }

    .tdb-bo-header__welcome > div {
        min-width: 0;
    }

    /* Un nom d'etablissement d'un seul tenant, plus large que la colonne, doit
       pouvoir se couper plutot que deborder. */
    .tdb-bo-header__title {
        overflow-wrap: anywhere;
    }

    .tdb-bo-header__actions,
    .tdb-bo-header__logout {
        display: none;
    }
    /* MOD-IA 2026-09-21 : la mascotte disparaît en mobile — relevé du lot 0,
       demande client du 21.09.2026.

       Le bandeau mobile de la maquette (« phone BO header » 2055:5045) ne porte
       AUCUNE pastille mascotte : 390 × 84, et à gauche uniquement le sur-titre
       et le titre « Bienvenue <nom> », en colonne. Les 43px de la pastille plus
       les 20px de gouttière mangeaient 63px des 360px utiles, au détriment du
       titre — ce qui alimentait le débordement décrit en MC1.

       Le lien vers le tableau de bord reste porté par le bloc texte : seule la
       vignette disparaît, pas le chemin de retour. En desktop, la mascotte est
       bien dans la maquette (« BO header ») et ne bouge pas. */
    .tdb-bo-header__mascot {
        display: none;
    }
    .tdb-bo-header__mobile-btn {
        display: flex;
        /* MOD-IA 2026-09-01 : direction "column" + gap, comme .site-header__burger.
           En "row" (valeur par défaut), les trois barres du burger se plaçaient
           CÔTE À CÔTE au lieu de s'empiler : le bouton n'affichait qu'un seul
           tiret de 48px, rogné par les 37px du carré. Le margin-top du
           span + span était sans effet en direction row. */
        flex-direction: column;
        gap: 3px;
        align-items: center;
        justify-content: center;
        width: 37px;
        height: 37px;
        border-radius: 8px;
        background: #fff;
        color: var( --color-ink );
        text-decoration: none;
        border: none;
        flex-shrink: 0;
    }
    .tdb-bo-header__mobile-btn span {
        display: block;
        width: 16px;
        height: 2px;
        background: var( --color-ink );
        border-radius: 1px;
    }
    /* ANCIEN CODE : l'écart entre barres passait par une marge, inopérante en row.
    .tdb-bo-header__mobile-btn span + span {
        margin-top: 3px;
    }
    */
}

/* "menu + tableau de bord" (6011:6508) : menu 319px, gouttière 47px, colonne
   de contenu 1074px ; le bloc démarre 50px sous l'en-tête BO (127px de haut). */
.tdb-bo__layout {
    display: grid;
    /* MOD-IA 2026-09-08 : le garde-fou `minmax( 0, 1fr )` remonte de la requête
       média à la RÈGLE DE BASE — débordement repéré le 08.09.2026 sur
       « Tableau de bord » à 1024px.

       Il avait été posé le 01.09 dans `@media ( max-width: 1023px )`
       uniquement. La bande 1024-1440px restait donc sur `1fr`, c'est-à-dire
       `minmax( auto, 1fr )` : la colonne s'étirait à la largeur min-content de
       son contenu (808px pour 665 disponibles à 1024) et la page défilait
       latéralement. C'est précisément la plage des portables de 13 pouces.
       ANCIEN CODE : grid-template-columns: 319px 1fr; */
    grid-template-columns: 319px minmax( 0, 1fr );
    gap: 47px;
    padding-block: 50px var( --space-3xl );
    align-items: start;
}

@media ( max-width: 1023px ) {
    /* MOD-IA 2026-09-01 : minmax(0,1fr) et non 1fr. `1fr` vaut
       `minmax(auto, 1fr)` : la piste ne peut pas descendre sous le min-content
       de son contenu. Un seul élément large (ici le tableau de listing des
       bons, 559px) suffisait donc à étirer toute la colonne du back-office
       au-delà de la fenêtre. minmax(0,…) autorise la piste à rétrécir. */
    /* ANCIEN CODE : grid-template-columns: 1fr; */
    .tdb-bo__layout {
        grid-template-columns: minmax( 0, 1fr );
    }
}

/* MOD-IA 2026-09-01 : le menu latéral du back-office n'existe pas dans les
   frames mobiles (473:7459, 6174:8500, 482:3258, 6201:6650) — la navigation y
   passe entièrement par le panneau hors-canevas "SP - menu BO" (473:7936),
   ouvert par le burger de l'en-tête BO. Il était rendu en pleine page, avec
   des pastilles de 539px qui sortaient de l'écran. */
@media ( max-width: 767px ) {
    .tdb-bo__layout .tdb-bo-sidebar,
    .tdb-bo__layout .woocommerce-MyAccount-navigation {
        display: none;
    }
    /* MOD-IA 2026-09-01 : le masquage du bouton « Retour » a été déplacé plus
       bas, dans la règle dédiée à ce bouton (recherche « tdb-retour-compte »).
       Posé ici, il ne l'emportait pas : `.tdb-retour-compte` (0-1-0) perdait
       contre `.tdb-bo-endpoint .button.button-primary` (0-3-0), qui rétablit
       l'affichage. Le bouton était de toute façon déjà masqué en desktop — le
       défaut ne se voyait qu'en mobile. */
    /* MOD-IA 2026-09-01 : le retrait haut de 50px était calibré pour le desktop,
       où il sépare la barre BO du menu latéral. Le menu latéral masqué (règle
       ci-dessus), il ne restait qu'un grand vide blanc entre l'en-tête et le
       titre de page. Les frames mobiles posent 23px (en-tête jusqu'à ~86,
       contenu à 109). */
    .tdb-bo__layout {
        padding-block: 23px var( --space-xl );
    }
}

.tdb-bo-sidebar {
    display: flex;
    flex-direction: column;
    gap: 10px;
    background: var( --color-surface-muted );
    border-radius: var( --radius-sm );
    padding: 10px;
    position: sticky;
    top: var( --space-lg );
}

/* Pastille du menu latéral BO : libellé centré, chevron collé à droite
   (2010:3618). En flex, sinon l'icône du repli "Mon commerce" retombe sous
   le texte au lieu de s'aligner à droite. */
.tdb-bo-sidebar__link {
    position: relative;
    display: flex;
    align-items: center;
    /* MOD-IA 2026-09-22 : MD5 — les titres de groupe (« Mon commerce »,
       « Mes bons », « Mes achats », « Administration ») etaient centres
       au-dessus de sous-entrees alignees a gauche, avec le « + » flottant a
       droite : d'ou le desalignement signale par le client. Ils passent a
       gauche, sur le meme axe que leurs sous-entrees.
       Le padding droit monte a 44px (20px de retrait + 24px pour le « + »
       absolu place a `right: 20px`), afin qu'un libelle long ne passe jamais
       sous l'indicateur.
       ANCIEN CODE :
       justify-content: center;
       text-align: center;
       padding: 14px 20px; */
    justify-content: flex-start;
    background: var( --color-ink );
    color: #fff;
    text-align: left;
    padding: 14px 44px 14px 20px;
    border-radius: var( --radius-sm );
    font-size: var( --text-button-size );
    font-weight: var( --weight-medium );
    letter-spacing: var( --tracking-tight );
    cursor: pointer;
    border: none;
    width: 100%;
}

.tdb-bo-sidebar__chevron {
    position: absolute;
    right: 20px;
    top: 50%;
    transform: translateY( -50% );
    filter: brightness( 0 ) invert( 1 ); /* chevron blanc sur la pastille noire */
}

/*
 * MOD-IA 2026-09-22 : MD4 — la rotation est RÉTABLIE. Le glyphe est redevenu un
 * chevron (navigation.php), qui lui n'est pas symétrique : pivoté de 180° il
 * pointe bien vers le haut une fois le groupe ouvert.
 *
 * ANCIEN CODE :
 * .tdb-bo-sidebar__group[open] .tdb-bo-sidebar__chevron {
 *     transform: translateY( -50% );
 * }
 */
.tdb-bo-sidebar__group[open] .tdb-bo-sidebar__chevron {
    transform: translateY( -50% ) rotate( 180deg );
}

.tdb-bo-sidebar__group summary {
    list-style: none; /* la mise en page vient de .tdb-bo-sidebar__link */
}

.tdb-bo-sidebar__group summary::-webkit-details-marker {
    display: none;
}

.tdb-bo-sidebar__chevron {
    transition: transform var( --duration-tdb ) var( --ease-tdb );
}

.tdb-bo-sidebar__submenu {
    margin-top: 8px;
    display: flex;
    flex-direction: column;
    gap: 4px;
}

.tdb-bo-sidebar__submenu a {
    display: block;
    padding: var( --space-sm ) var( --space-md );
    font-size: var( --text-caption-size );
}

/* ---------- Menu hors-canevas du back-office mobile (H-1) ---------- */
.tdb-bo-mobile-menu {
    position: fixed;
    inset: 0;
    z-index: 100;
    background: #fff;
    overflow-y: auto;
}

.tdb-bo-mobile-menu[hidden] {
    display: none;
}

.tdb-bo-mobile-menu__top {
    background: var( --color-ink );
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 20px 15px;
}

.tdb-bo-mobile-menu__close {
    width: 34px;
    height: 34px;
    border-radius: 8px;
    background: #fff;
    display: flex;
    align-items: center;
    justify-content: center;
    border: none;
}

.tdb-bo-mobile-menu__nav {
    display: flex;
    flex-direction: column;
    gap: var( --space-sm );
    padding: var( --space-lg ) 15px;
    border-bottom: 1px solid var( --color-border );
}

/* MOD-IA 2026-09-01 : dans le menu hors-canevas, les pastilles sont alignées à
   GAUCHE (473:7936), contrairement au menu latéral desktop (2010:3618) où le
   libellé est centré. .tdb-bo-sidebar__link étant partagé par les deux, on
   surcharge ici plutôt que de dupliquer le composant. */
.tdb-bo-mobile-menu__nav .tdb-bo-sidebar__link {
    justify-content: flex-start;
    text-align: left;
}

.tdb-bo-mobile-menu__actions {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: var( --space-sm );
    padding: var( --space-lg ) 15px;
}

.tdb-bo-mobile-menu__btn {
    display: flex;
    align-items: center;
    justify-content: center;
    text-align: center;
    /* MOD-IA 2026-09-01 : hauteur fixée à 40px comme dans « SP - menu BO »
       (473:7936) ; le padding seul donnait 53px. */
    height: 40px;
    padding: 0 var( --space-md );
    border-radius: var( --radius-sm );
    border: 1px solid var( --color-primary );
    color: var( --color-ink );
    font-size: var( --text-button-size );
    font-weight: var( --weight-medium );
    background: none;
}

/* ---------- Statistiques / donut ---------- */
/* "infographie" (6011:6499) : donut 432×433, résumé 625×433, écart 17px ;
   le bloc "activités" démarre 60px plus bas. */
.tdb-bo-stats {
    display: grid;
    /* MOD-IA 2026-09-08 : même remontée du garde-fou que sur .tdb-bo__layout
       ci-dessus — le résumé à droite du donut était étiré par son propre
       contenu entre 1024 et 1440px.
       ANCIEN CODE : grid-template-columns: 432px 1fr; */
    grid-template-columns: 432px minmax( 0, 1fr );
    gap: 17px;
    margin-bottom: 60px;
}

/* MOD-IA 2026-09-08 : le donut et le résumé s'empilent désormais jusqu'à
   1221px, et non plus jusqu'à 1023 — débordement repéré le 08.09.2026 sur
   « Tableau de bord » à 1024px.

   Le calcul de la place disponible pour la colonne de contenu du back-office :
       largeur de fenêtre − 48 (marges du conteneur) − 319 (menu) − 47 (gouttière)
   Les deux blocs côte à côte en réclament 432 (donut) + 17 (écart) + 359
   (largeur minimale du résumé, mesurée) = 808. Il faut donc 808 + 414 = 1222px
   de fenêtre. En dessous, ils ne tenaient pas : à 1024 la colonne ne fait que
   610, et le résumé sortait de l'écran.

   `minmax( 0, 1fr )` seul ne suffisait pas ici : il empêche la COLONNE de
   s'étirer, mais le résumé débordait alors de sa propre colonne devenue trop
   étroite (161px). Il fallait changer de mise en page, pas seulement borner
   la piste.

   ANCIEN CODE : @media ( max-width: 1023px ) */
@media ( max-width: 1221px ) {
    /* MOD-IA 2026-09-01 : même garde-fou que sur .tdb-bo__layout — voir le
       commentaire là-bas. Sans minmax(0,…), le donut et le résumé étaient
       étirés à 559px et sortaient de l'écran en mobile. */
    /* ANCIEN CODE : grid-template-columns: 1fr; */
    .tdb-bo-stats {
        grid-template-columns: minmax( 0, 1fr );
    }
}

.tdb-bo-donut {
    min-height: 433px; /* "infographie" (2443:3847) : 432 × 433 */
    background: var( --color-surface-muted );
    border-radius: var( --radius-card );
    display: flex;
    align-items: center;
    justify-content: center;
    padding: var( --space-2xl );
}

.tdb-bo-donut__ring {
    position: relative;
    width: 234px;
    height: 234px;
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
}

/* Bulles de pourcentage posées sur l'anneau (10%/18%/38%/48% du design
   2443:3838, G-3) : positionnées au milieu de leur arc via une rotation +
   translation le long du rayon, puis contre-tournées pour rester lisibles. */
.tdb-bo-donut__bubble {
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate( -50%, -50% ) rotate( var( --tdb-angle ) ) translateY( -117px ) rotate( calc( -1 * var( --tdb-angle ) ) );
    background: #fff;
    color: var( --color-ink );
    font-size: 11px;
    font-weight: var( --weight-semibold );
    padding: 3px 9px;
    border-radius: var( --radius-pill );
    box-shadow: var( --shadow-card );
    white-space: nowrap;
}

.tdb-bo-donut__hole {
    width: 154px;
    height: 154px;
    border-radius: 50%;
    background: var( --color-surface-muted );
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    text-align: center;
}

.tdb-bo-donut__hole strong {
    font-size: 20px;
    font-weight: var( --weight-semibold );
    display: block;
}

.tdb-bo-donut__hole span {
    font-size: var( --text-h3-size );
    font-weight: var( --weight-semibold );
    color: var( --color-ink );
}

.tdb-bo-summary {
    min-height: 433px; /* "resume infographie" (2443:3864) : 625 × 433 */
    background: var( --color-surface-muted );
    border-radius: var( --radius-card );
    padding: var( --space-2xl );
}

.tdb-bo-summary__intro {
    font-size: var( --text-h3-size );
    margin-bottom: var( --space-lg );
}

.tdb-bo-summary__intro strong{
    text-wrap: nowrap;
}

/* Rangée gris clair arrondie + carré de couleur (G-4), pas une pastille
   ronde sur fond transparent. */
/* MOD-IA 2026-09-08 : hauteur et écart des lignes du résumé repris de la
   maquette — vérification de parité desktop du 08.09.2026.

   Dans « resume infographie » (2443:3864), les quatre lignes font 51 de haut et
   sont espacées de 10 : le bloc en occupe 233. Ici elles faisaient 58 (padding
   de 12 autour d'une pastille de 34) espacées de 12, soit 268.

   Conséquence : le résumé dépassait la hauteur du donut voisin et la rangée
   « infographie » mesurait 447 au lieu des 433 de la maquette — le donut a bien
   une hauteur minimale de 433, mais c'est le plus haut des deux qui gagne.

   `min-height` plutôt qu'un padding de 8,5px : la pastille de compte fait 34,
   et 8 + 34 + 8 donne 50. La hauteur minimale ramène la ligne à 51 sans
   décentrer son contenu.

   ANCIEN CODE :
   padding: var( --space-sm ) var( --space-md );
   .tdb-bo-summary__row + .tdb-bo-summary__row { margin-top: var( --space-sm ); } */
.tdb-bo-summary__row {
    display: flex;
    align-items: center;
    gap: var( --space-md );
    min-height: 51px;
    background: #fff;
    border-radius: var( --radius-sm );
    padding: 8px var( --space-md );
}

.tdb-bo-summary__row + .tdb-bo-summary__row {
    margin-top: 10px;
}

.tdb-bo-summary__count {
    flex-shrink: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 34px;
    height: 34px;
    border-radius: 8px;
    background: var( --badge-color, var( --color-surface-muted ) );
    font-weight: var( --weight-semibold );
}

.tdb-bo-summary__label {
    flex: 1;
    /* MOD-IA 2026-09-01 : « Bons à valider » et « Bons non activés » se
       repliaient sur deux lignes en mobile, ce qui déformait la rangée. La
       maquette (473:7459) les tient sur une seule. */
    white-space: nowrap;
}

/* MOD-IA 2026-09-22 : MD1 — le montant du resume passait a la ligne.
   `.tdb-bo-summary__value` n'avait aucune regle : dans la rangee flex, le
   compteur ne se comprime pas (flex-shrink: 0) et le libelle ne se coupe pas
   (white-space: nowrap), le montant etait donc le seul element ajustable et
   cassait sur l'espace fine de « CHF 2 100.– » des que la colonne se resserrait
   (surtout entre 1221px et ~1400px, juste au-dessus du point de rupture de la
   grille `.tdb-bo-activites`).
   C'est desormais le LIBELLE qui cede, pas le montant : un libelle tronque
   reste comprehensible, un montant coupe ne l'est pas. */
.tdb-bo-summary__value {
    flex-shrink: 0;
    white-space: nowrap;
    margin-left: auto;
}

/* MOD-IA 2026-09-22 : MD1 — corollaire de la regle ci-dessus : le libelle
   devient la variable d'ajustement et doit pouvoir passer sous sa largeur de
   contenu (min-width: 0), en tronquant proprement. */
.tdb-bo-summary__label {
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
}

.tdb-bo-summary__label--mobile {
    display: none;
}

@media ( max-width: 767px ) {
    .tdb-bo-summary__label--desktop {
        display: none;
    }
    .tdb-bo-summary__label--mobile {
        display: inline;
    }
}

/* ---------- Activités / vignettes / listing ---------- */
/* "titre + filtre" (6011:6486) : 40px de haut, contenu 40px plus bas. */
.tdb-bo-activites__head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin-bottom: 40px;
}

/* "Suivi de mes bons" (I-11) : titre + filet orange, comme "Mon compte" /
   "Mes bons" — contrairement à "Dernières activités" (tableau de bord) qui
   reste dans le style de titre par défaut. */
.tdb-bo-activites__head--titled h2 {
    color: var( --color-primary );
    padding-bottom: var( --space-md );
    border-bottom: 1px solid var( --color-primary );
    /* MOD-IA 2026-09-08 : le titre peut de nouveau RÉTRÉCIR (`1 1` au lieu de
       `1 0`) — débordement horizontal repéré à 320px le 08.09.2026 sur
       « Suivi de mes bons ».

       Avec `flex-shrink: 0`, le titre gardait la largeur de son texte quoi
       qu'il arrive et poussait la bascule vue liste / vue vignettes hors du
       conteneur : la page défilait de 6px sur le côté (326 pour 320 de
       viewport). Le `flex-grow: 1` est conservé — c'est lui qui étend le filet
       orange sous le titre jusqu'à la bascule. `min-width: 0` lève la largeur
       minimale implicite d'un élément flex, sans laquelle `flex-shrink` reste
       sans effet sur un texte long.

       320px n'est pas un cas d'école : c'est la largeur d'un iPhone SE.

       ANCIEN CODE : flex: 1 0 auto; */
    flex: 1 1 auto;
    min-width: 0;
}

.tdb-view-toggle {
    display: inline-flex;
    gap: 6px;
    background: var( --color-surface-muted );
    border-radius: var( --radius-sm );
    padding: 4px;
    flex-shrink: 0;
}

/* MOD-IA 2026-09-22 : MD13 + MD17 — la bascule Vignettes / Listing n'est plus
   l'enfant droit d'un en-tête flex (`.tdb-bo-activites__head`) mais un bloc
   autonome pose sous « Les chiffres en un clin d'œil »
   (template-parts/backoffice/suivi-bons-entete.php). Elle a donc besoin de son
   propre alignement — a droite, comme dans la maquette — et de son propre
   espacement vis-a-vis du bloc de chiffres au-dessus et de la barre de filtres
   en dessous. */
.tdb-suivi-vue {
    display: flex;
    justify-content: flex-end;
    margin: 0 0 20px;
}

/* "BTN noir > orange" (2443:4080) : 168×46, aligné à droite, 40px sous les
   vignettes. */
.tdb-bo-activites__cta {
    display: flex;
    justify-content: flex-end;
    margin-top: 40px;
}

/* Barre de filtres "Suivi de mes bons" (I-10) : Type / Canal / Statut /
   Filtrer + Rechercher. */
.tdb-bons-filtres {
    display: flex;
    flex-wrap: wrap;
    gap: var( --space-sm );
    margin-bottom: var( --space-lg );
}

.tdb-bons-filtres .tdb-filtres__select {
    width: auto;
    flex: 1 1 160px;
}

.tdb-bons-filtres__search {
    position: relative;
    flex: 2 1 220px;
    display: flex;
    align-items: center;
}

.tdb-bons-filtres__search input {
    width: 100%;
    height: 46px;
    border: none;
    border-radius: var( --radius-sm );
    background: var( --color-surface-muted );
    padding: 0 44px 0 var( --space-lg );
    font-family: var( --font-body );
    font-size: var( --text-button-size );
}

.tdb-bons-filtres__search-btn {
    position: absolute;
    right: var( --space-md );
    top: 50%;
    transform: translateY( -50% );
    display: flex;
    color: var( --color-text-muted );
    background: none;
    border: none;
    padding: 0;
    cursor: pointer;
}

.tdb-view-toggle button {
    display: flex;
    align-items: center;
    gap: 6px;
    padding: 8px 16px;
    border-radius: 6px;
    font-size: var( --text-caption-size );
    font-weight: var( --weight-medium );
    color: var( --color-text-muted );
    /* MOD-IA 2026-09-08 : la bascule n'avait AUCUNE transition — le passage de
       « Vignettes » à « Listing » se faisait par un saut sec, alors que la
       pastille active change de fond, de couleur et d'ombre. Mêmes jetons que
       les pilules de filtre (.tdb-suivi-pill). */
    transition:
        background-color var( --duration-tdb-snap ) var( --ease-tdb ),
        color var( --duration-tdb-snap ) var( --ease-tdb ),
        box-shadow var( --duration-tdb-snap ) var( --ease-tdb );
}

/* MOD-IA 2026-09-08 : état de survol, jusqu'ici inexistant. Rien n'indiquait
   que ces deux libellés étaient cliquables tant qu'on n'avait pas cliqué. Le
   survol rapproche simplement le libellé de sa couleur active, sans lui donner
   le fond blanc réservé à la vue courante. */
.tdb-view-toggle button:hover,
.tdb-view-toggle button:focus-visible {
    color: var( --color-ink );
}

.tdb-view-toggle button.is-active {
    background: #fff;
    color: var( --color-ink );
    box-shadow: var( --shadow-card );
}

@media ( max-width: 767px ) {
    /* Boutons icône seule, ordre "Listing" puis "Vignettes", alignés à
       droite (G-5/I-11 — 473:7459). */
    .tdb-view-toggle__label {
        display: none;
    }
    .tdb-view-toggle button[data-view="listing"] {
        order: 1;
    }
    .tdb-view-toggle button[data-view="vignettes"] {
        order: 2;
    }
}

/* MOD-IA 2026-09-22 : la vue « Listing » n'est plus un tableau.

   « listes » (6169:7227 pour le tableau de bord, 6174:7333 pour le suivi) est
   une PILE de cartouches « BO listing bon » (6002:6423) de 64px de haut,
   espacées de 10px — ni en-tête, ni filets, ni colonnes. Le conteneur devient
   donc une colonne flex, toujours masquée tant que la vue Vignettes est
   active. Voir bons-toggle.php et ligne-bon.php.

   ANCIEN CODE :
   .tdb-bons-vue__listing {
       display: none;
       width: 100%;
       border-collapse: collapse;
   }
*/
.tdb-bons-vue__listing {
    display: none;
    flex-direction: column;
    gap: 10px;
    width: 100%;
}

/* "vignettes" (6002:6062) : cartes de 342×184, écart horizontal 24px,
   écart vertical 21px. */
.tdb-bons-vue__vignettes {
    display: grid;
    grid-template-columns: repeat( 3, 1fr );
    gap: 21px 24px;
}

.tdb-bons-vue[data-current-view="listing"] .tdb-bons-vue__vignettes {
    display: none;
}

/* MOD-IA 2026-09-22 : pile de cartouches, donc `flex` et non plus `table`.
   ANCIEN CODE :
   .tdb-bons-vue[data-current-view="listing"] .tdb-bons-vue__listing {
       display: table;
   }
*/
.tdb-bons-vue[data-current-view="listing"] .tdb-bons-vue__listing {
    display: flex;
}

/* MOD-IA 2026-09-22 : plus aucune cellule de tableau dans cette vue — la
   maquette n'en montre pas. Règle conservée en commentaire.
   ANCIEN CODE :
.tdb-bons-vue__listing th,
.tdb-bons-vue__listing td {
    text-align: left;
    padding: var( --space-sm ) var( --space-md );
    border-bottom: 1px solid var( --color-border );
    font-size: var( --text-caption-size );
}
*/

@media ( max-width: 1023px ) {
    .tdb-bons-vue__vignettes {
        grid-template-columns: repeat( 2, 1fr );
    }
}

@media ( max-width: 767px ) {
    .tdb-bons-vue__vignettes {
        grid-template-columns: 1fr;
    }
    /* MOD-IA 2026-09-01 : le tableau de listing n'est rendu défilable QUE dans
       la vue "listing". L'ancienne règle posait display:block sans condition :
       elle écrasait le display:none de la règle de base (même spécificité,
       règle plus tardive), le tableau restait donc affiché en permanence
       PAR-DESSUS les vignettes, et son min-content de 559px remontait la
       chaîne des grilles jusqu'à faire déborder toute la page BO en mobile
       (fenêtre de 390px). Voir aussi les garde-fous minmax(0,1fr) posés sur
       .tdb-bo__layout et .tdb-bo-stats. */
    /* ANCIEN CODE :
    .tdb-bons-vue__listing {
        display: block;
        overflow-x: auto;
    }
    */
    /* MOD-IA 2026-09-22 : plus rien à faire défiler — la cartouche mobile
       (« listing bon BO phone » 6048:12063) se replie sur deux lignes dans les
       360px de la colonne, il n'y a plus de largeur minimale de tableau à
       absorber. La pile flex de la règle de base suffit.
       ANCIEN CODE :
    .tdb-bons-vue[data-current-view="listing"] .tdb-bons-vue__listing {
        display: block;
        overflow-x: auto;
        max-width: 100%;
    }
    */
}

.tdb-vignette-bon {
    background: var( --color-surface-muted );
    border-radius: var( --radius-sm );
}

/* MOD-IA 2026-09-08 : la marge basse de l'accordéon est neutralisée DANS la
   grille de vignettes — vérification de parité desktop du 08.09.2026.

   La vignette réemploie le composant accordéon pour son dépliage, et héritait
   donc de `.tdb-accordion__item { margin-bottom: var( --space-sm ) }`
   (assets/css/ui/04-navigation.css). Dans une grille, cette marge s'AJOUTE au
   `row-gap` : les rangées étaient séparées de 33px (21 + 12) là où la maquette
   en demande 21 (« vignettes » 6002:6062 : rangées de 184 posées à y=0 et
   y=205). La grille montrait d'ailleurs des rangées de 196px pour des vignettes
   de 184.

   La portée s'arrête à cette grille : partout ailleurs, un item d'accordéon
   garde sa marge, qui l'y sépare correctement du suivant. */
.tdb-bons-vue__vignettes .tdb-accordion__item {
    margin-bottom: 0;
}

/* "Propriété 1=ferme" (6002:5414) : 321×184, padding 20px/15px, les trois
   rangées (type+code+jour / valeur / statut+canal+déplier) espacées de 15px. */
/* MOD-AI 2026-09-09 : le résumé est désormais un conteneur passif ; conserver l'étirement qui aligne ses trois rangées à gauche. */
/* ANCIEN CODE (commentaire) : align-items: stretch est explicite : la vignette est un <button>, et la
   feuille de style du navigateur y impose align-items:center, ce qui
   recentrait les trois rangées au lieu de les aligner à gauche. */
.tdb-vignette-bon__summary {
    width: 100%;
    padding: 20px 15px;
    display: flex;
    flex-direction: column;
    align-items: stretch;
    gap: 15px;
    text-align: left;
}

.tdb-vignette-bon__row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var( --space-sm );
}

/* MOD-AI 2026-09-09 : règle historique conservée comme garde-fou visuel, même si le déclencheur est maintenant limité au bouton +/−. */
/* MOD-IA 2026-09-02 : la vignette OUVERTE virait au fond orange. Effet de bord
   du réemploi de l'accordéon : le résumé porte .tdb-accordion__trigger, et la
   règle « .tdb-accordion__item.is-open .tdb-accordion__trigger { background:
   var(--color-primary) } » (voir plus haut) s'y appliquait aussi. Vérifié sur
   la maquette : le composant « BO vignette bon » (6002:5413) a bien deux
   variantes, « Propriété 1=ferme » (6002:5414, 321x184) et « Propriété
   1=ouvert » (6002:5412, 321x364) — et l'ouverte garde EXACTEMENT le même fond
   gris box que la fermée. Seuls le bouton +/− et le bloc de détail changent.
   Le fond orange reste le bon comportement pour la FAQ, qui n'est pas touchée
   ici : on ne neutralise la règle que pour la vignette. Même spécificité que
   la règle de l'accordéon (3 classes), mais posée plus loin dans le fichier —
   c'est l'ordre qui tranche, pas un !important. */
.tdb-vignette-bon.is-open .tdb-vignette-bon__summary {
    background: var( --color-surface-muted );
}

/* MOD-IA 2026-09-02 : bouton de dépliage « BTN BO fiche bon » (6002:5430) —
   deux glyphes superposés en fondu croisé, « + » replié et « − » déplié. Voir
   l'explication complète dans template-parts/backoffice/vignette-bon.php :
   l'ancien montage (une seule image tournée de 180°) laissait un « + » dans
   les deux états, un « + » étant symétrique par rotation. */
.tdb-vignette-bon__toggle {
    position: relative;
    display: inline-flex;
    flex: 0 0 auto;
    width: 34px;
    height: 34px;
    /* MOD-AI 2026-09-09 : le pictogramme +/− est désormais un bouton ; neutraliser les styles génériques d'accordéon sans agrandir sa zone cliquable au reste de la carte. */
    padding: 0;
    border: 0;
    background: transparent;
    cursor: pointer;
}

/* MOD-AI 2026-09-09 : conserver le fond transparent du bouton dédié lorsque la vignette est ouverte, malgré la règle générique des accordéons. */
.tdb-accordion__item.is-open .tdb-vignette-bon__toggle {
    background: transparent;
}

.tdb-vignette-bon__toggle-icon {
    position: absolute;
    inset: 0;
    width: 34px;
    height: 34px;
    transition: opacity var( --duration-tdb-snap ) var( --ease-tdb );
}

.tdb-vignette-bon__toggle-icon--moins {
    opacity: 0;
}

.tdb-vignette-bon.is-open .tdb-vignette-bon__toggle-icon--plus {
    opacity: 0;
}

.tdb-vignette-bon.is-open .tdb-vignette-bon__toggle-icon--moins {
    opacity: 1;
}

/* MOD-IA 2026-09-08 : hauteur fixée à 34 — vérification de parité desktop du
   08.09.2026. Dans « vignette bon BO » (6002:5710) la pastille de type
   (« Box carte ») mesure 76x34, comme la pastille de statut voisine (.tdb-badge,
   déjà à 34) et le bouton de dépliage. Celle-ci montait à 38 : son padding de 8
   s'ajoutait à la hauteur de ligne héritée du corps de texte ET aux 2px de
   filet, alors que .tdb-badge n'a pas de filet.

   La hauteur est posée directement plutôt que déduite d'une hauteur de ligne :
   la pastille contient une icône de 18px à côté du texte, donc sa hauteur ne
   dépend pas seulement de la typographie. `box-sizing` est déjà global dans le
   thème : les 34px incluent le filet.
   ANCIEN CODE : padding: 8px; */
.tdb-vignette-bon__type {
    display: flex;
    align-items: center;
    gap: 8px;
    height: 34px;
    background: #fff;
    border: 1px solid var( --color-text-muted );
    border-radius: 5px;
    padding: 0 8px;
    font-size: var( --text-caption-size );
    font-weight: var( --weight-medium );
}

/*
 * MOD-IA 2026-09-22 : MD2 — le numéro du bon est devenu un <button> (il déplie
 * le détail). Le soulignement, qui le faisait passer pour un lien alors qu'il
 * était inerte, est désormais justifié ; il faut en revanche neutraliser
 * l'apparence native du bouton pour que le rendu soit inchangé.
 *
 * Même traitement pour la cellule équivalente de la vue Listing.
 */
.tdb-vignette-bon__code,
.tdb-ligne-bon__code {
    font-size: var( --text-caption-size );
    font-weight: var( --weight-medium );
    text-decoration: underline;
    padding: 0;
    border: 0;
    background: none;
    color: inherit;
    font-family: inherit;
    line-height: inherit;
    /* cursor: pointer; */
}

/* .tdb-vignette-bon__code:hover,
.tdb-ligne-bon__code:hover,
.tdb-vignette-bon__code:focus-visible,
.tdb-ligne-bon__code:focus-visible {
    color: var( --color-primary );
} */

.tdb-vignette-bon__jour {
    color: var( --color-text-muted );
    font-size: var( --text-caption-size );
}

/* MOD-IA 2026-09-08 : hauteurs de ligne posées sur le montant et sa
   dénomination — vérification de parité desktop du 08.09.2026.

   Dans « vignette bon BO » (6002:5710), le cadre « valeur + dénomination » fait
   46 de haut : le montant occupe 28 et la dénomination 18. Sans `line-height`
   déclarée, les deux héritaient de celle du corps de texte (1,625), ce qui
   donnait 39 pour le montant et 20 pour la dénomination, soit 59 au lieu de 46.
   La vignette entière en héritait : 206 de haut au lieu des 184 de la maquette.

   C'est le même défaut que sur la ligne de prix de la fiche commerçant : une
   hauteur de ligne pensée pour un paragraphe, appliquée à un chiffre d'affiche.
   Les tailles de police, elles, sont conformes et ne bougent pas. */
.tdb-vignette-bon__montant {
    font-size: 24px;
    line-height: 28px;
    font-weight: var( --weight-semibold );
    margin: 0;
}

.tdb-vignette-bon__label {
    font-size: var( --text-caption-size );
    line-height: 18px;
    margin: 0;
}

.tdb-vignette-bon__meta {
    display: flex;
    align-items: center;
    gap: 10px;
}

/* MOD-IA 2026-09-08 : même mise à 34 que la pastille de type ci-dessus — la
   maquette lui donne 97x34 (« box sur place » dans 6002:5710).
   ANCIEN CODE : padding: 8px; */
.tdb-vignette-bon__canal {
    display: flex;
    align-items: center;
    gap: 6px;
    height: 34px;
    border: 1px solid var( --color-text-muted );
    border-radius: 5px;
    padding: 0 8px;
    font-size: var( --text-caption-size );
    font-weight: var( --weight-medium );
}

/* La vignette est REPLIÉE par défaut sur le tableau de bord (variante
   "ferme", 184px de haut) : ce bloc ne doit devenir flex qu'une fois
   l'accordéon ouvert — sinon son "display:flex" écrase le "display:none"
   de .tdb-accordion__panel (même spécificité, règle plus tardive) et toutes
   les vignettes s'affichent dépliées. */
.tdb-vignette-bon__detail {
    padding: 0 15px 20px;
    gap: 5px;
    border-top: 1px solid var( --color-border );
    margin-top: 0;
}

.tdb-accordion__item.is-open .tdb-vignette-bon__detail {
    display: flex;
    flex-direction: column;
}

.tdb-vignette-bon__detail-row {
    display: flex;
    justify-content: space-between;
    font-size: var( --text-caption-size );
}

.tdb-vignette-bon__detail-row span:first-child {
    color: var( --color-text-muted );
}

/* --------------------------------------------------------------------------
   MOD-IA 2026-09-22 : cartouche de la vue Listing — « BO listing bon »
   (6002:6423), empilée par « listes » (6169:7227 / 6174:7333).

   Ces règles REMPLACENT celles de la ligne de tableau (détail logé dans un
   <tr> frère, cellule de commande, filets de cellule) : il n'y a plus de
   tableau du tout. Le panneau de détail est redevenu un simple DESCENDANT de
   l'item d'accordéon, exactement comme dans la vignette — la règle générique
   `.tdb-accordion__item.is-open .tdb-accordion__panel` (ui/04-navigation.css)
   l'ouvre donc sans sélecteur de fratrie.

   ANCIEN CODE :
   .tdb-ligne-bon__detail-row {
       display: none;
   }
   .tdb-ligne-bon.is-open + .tdb-ligne-bon__detail-row {
       display: table-row;
   }
   .tdb-ligne-bon.is-open + .tdb-ligne-bon__detail-row .tdb-accordion__panel {
       display: flex;
       flex-direction: column;
       gap: 5px;
       padding: var( --space-sm ) 0;
   }
   .tdb-ligne-bon__detail-cell {
       display: flex;
       justify-content: space-between;
       gap: var( --space-md );
       max-width: 480px;
       font-size: var( --text-caption-size );
   }
   .tdb-bons-vue__listing td.tdb-ligne-bon__commande {
       width: 1%;
       white-space: nowrap;
       text-align: right;
   }
   -------------------------------------------------------------------------- */

/* « Propriété 1=Variante2 » (6002:6424) : 1074×64, fond #F7F7F7, rayon 10,
   padding 15. La hauteur de 64 n'est PAS posée : elle découle du padding et
   des pastilles de 34 (15 + 34 + 15), ce qui laisse la cartouche grandir si un
   libellé passe à la ligne au lieu de le rogner. */
.tdb-ligne-bon {
    background: var( --color-surface-muted );
    border-radius: var( --radius-sm );
    padding: 15px;
    /* Neutralise la marge basse générique des items d'accordéon
       (ui/04-navigation.css) : l'écart de 10px de la maquette est déjà porté
       par le `gap` de la pile (.tdb-bons-vue__listing). */
    margin-bottom: 0;
}

.tdb-ligne-bon__resume {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
}

/* « type + statut + canal » (6002:6427) : trois pastilles espacées de 5. */
.tdb-ligne-bon__boxes {
    order: 1;
    display: flex;
    align-items: center;
    gap: 5px;
    flex: 0 0 auto;
}

/* Colonnes de la maquette : n° 100, montant 80, prestation 180, fin de
   validité 180 ; 12px entre les pastilles et le n°, puis 24px entre chaque
   colonne (6002:6426 / 6002:6431). Les écarts sont posés en `margin-left`
   plutôt qu'en `gap` parce qu'ils ne sont pas tous égaux. Les deux colonnes
   de texte long peuvent se réduire (`0 1`) : entre 768 et 1200px la colonne
   du back-office est plus étroite que les 1074 de la maquette, et mieux vaut
   un libellé abrégé qu'une ligne qui se casse en deux. */
.tdb-ligne-bon__code {
    order: 2;
    flex: 0 0 100px;
    margin-left: 12px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.tdb-ligne-bon__montant {
    order: 3;
    flex: 0 0 80px;
    margin-left: 24px;
    font-size: var( --text-h4-size );
    line-height: 20px;
    font-weight: var( --weight-semibold );
}

.tdb-ligne-bon__presta,
.tdb-ligne-bon__date {
    flex: 0 1 180px;
    min-width: 0;
    margin-left: 24px;
    font-size: var( --text-h5-size );
    line-height: 18px;
    font-weight: var( --weight-medium );
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.tdb-ligne-bon__presta {
    order: 4;
}

.tdb-ligne-bon__date {
    order: 5;
}

/* « n° » et « jour » vivent dans un conteneur commun pour la maquette mobile
   (voir ligne-bon.php). En desktop ce conteneur s'efface : `display: contents`
   rend ses deux enfants directement positionnables dans la ligne. */
.tdb-ligne-bon__reference {
    display: contents;
}

/* « jour + picto » (6002:6440) : poussés contre le bord droit, espacés de 15. */
.tdb-ligne-bon__jour {
    order: 6;
    margin-left: auto;
    min-width: 30px;
    text-align: right;
    color: var( --color-text-muted );
    font-size: var( --text-h5-size );
    line-height: 18px;
}

/* « detail » (6002:6418) : 25px sous la ligne, filet #212121, puis 20px avant
   trois colonnes de 220 réparties sur toute la largeur. */
.tdb-ligne-bon__detail {
    margin-top: 25px;
    padding: 20px 0 0;
    border-top: 1px solid var( --color-ink );
}

.tdb-accordion__item.is-open .tdb-ligne-bon__detail {
    display: grid;
    grid-template-columns: repeat( 3, 220px );
    justify-content: space-between;
    row-gap: 5px;
}

.tdb-ligne-bon__detail-cell {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var( --space-sm );
    font-size: var( --text-h5-size );
    line-height: 18px;
}

.tdb-ligne-bon__detail-cell span:first-child {
    color: var( --color-text-muted );
}

.tdb-ligne-bon__detail-cell span:last-child {
    text-align: right;
}

/* --------------------------------------------------------------------------
   MOD-IA 2026-09-22 : pastilles « Type / Statut / Canal » de la cartouche —
   « Box carte » (6002:5399), « picto à valider » (2479:4540) et « box sur
   place light » (6001:6211), relevées dans « Backoffice composants »
   (4051:5515). Balisage posé par tdb_bon_box_type() / _statut() / _canal()
   (inc/template-tags.php).
   -------------------------------------------------------------------------- */
.tdb-bon-box {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex: 0 0 auto;
    height: 34px;
    border-radius: var( --radius-badge );
    color: var( --color-ink-strong );
    font-size: var( --text-h5-size );
    line-height: 18px;
    font-weight: var( --weight-medium );
}

.tdb-bon-box__picto {
    display: flex;
    align-items: center;
    justify-content: center;
    flex: 0 0 34px;
    width: 34px;
    height: 34px;
}

.tdb-bon-box__picto img {
    display: block;
}

/* Type : boîte blanche à filet de 110 dans la ligne de listing (6002:6428) —
   carré de picto à gauche, libellé ensuite, 8px de réserve à droite. */
.tdb-bon-box--type {
    width: 110px;
    justify-content: flex-start;
    padding-right: 8px;
    background: #fff;
    border: 1px solid var( --color-text-muted );
}

.tdb-bon-box--type .tdb-bon-box__libelle {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* Statut : carré plein de la couleur du statut, pictogramme seul — le libellé
   n'est servi qu'aux lecteurs d'écran, la maquette n'en montre aucun. */
.tdb-bon-box--statut {
    width: 34px;
    background: var( --badge-color, var( --color-surface-muted ) );
}

/* Canal : carré blanc à filet, pictogramme seul. */
.tdb-bon-box--canal {
    width: 34px;
    background: #fff;
    border: 1px solid var( --color-text-muted );
}

/* Canal inconnu : repli en pastille TEXTE plutôt qu'un pictogramme faux
   (voir tdb_bon_box_canal(), inc/template-tags.php). */
.tdb-bon-box--canal-texte {
    width: auto;
    padding: 0 8px;
}

/* Le +/− reprend exactement le composant de la vignette (« BTN BO fiche bon »,
   6002:5430) : deux glyphes superposes croises en opacite, plutot qu'une
   rotation — un « + » est symetrique par rotation. */
.tdb-ligne-bon__toggle {
    position: relative;
    display: inline-flex;
    width: 34px;
    height: 34px;
    padding: 0;
    border: none;
    background: none;
    cursor: pointer;
    /* MOD-IA 2026-09-22 : place du bouton dans la cartouche — dernier item de
       la ligne, 15px après l'âge du bon (« jour + picto » 6002:6440). */
    order: 7;
    flex: 0 0 34px;
    margin-left: 15px;
}

/* MOD-IA 2026-09-22 : la cartouche ouverte garde son fond gris, comme la
   vignette. Sans cette règle, `.tdb-accordion__item.is-open
   .tdb-accordion__trigger` (ui/04-navigation.css, DEUX classes) repeint le
   bouton +/− en orange dès l'ouverture — c'est le même effet de bord que celui
   corrigé le 02.09.2026 sur .tdb-vignette-bon__summary. */
.tdb-accordion__item.is-open .tdb-ligne-bon__toggle {
    background: transparent;
}

.tdb-ligne-bon__toggle-icon {
    position: absolute;
    inset: 0;
    transition: opacity var( --duration-tdb-snap ) var( --ease-tdb );
}

.tdb-ligne-bon__toggle-icon--moins,
.tdb-ligne-bon.is-open .tdb-ligne-bon__toggle-icon--plus {
    opacity: 0;
}

.tdb-ligne-bon.is-open .tdb-ligne-bon__toggle-icon--moins {
    opacity: 1;
    background-color: #ffffff;
}

/* --------------------------------------------------------------------------
   MOD-IA 2026-09-22 : cartouche de listing en mobile — « listing bon BO
   phone » (6048:12063), 360×102, padding 20/15.

   La maquette téléphone replie la cartouche sur DEUX lignes (pastilles +
   montant + bouton, puis la prestation) et descend le n° du bon et son âge
   DANS le détail déplié, sur une même ligne sous le filet. C'est pour cela que
   ligne-bon.php les réunit dans `.tdb-ligne-bon__reference` : ici le conteneur
   redevient une vraie boîte, là où le desktop l'efface en `display: contents`.
   -------------------------------------------------------------------------- */
@media ( max-width: 767px ) {
    .tdb-ligne-bon {
        padding: 20px 15px;
    }

    /* 10px entre les deux lignes du résumé (6048:12066). */
    .tdb-ligne-bon__resume {
        row-gap: 10px;
    }

    .tdb-ligne-bon__montant {
        order: 2;
        flex: 0 0 auto;
        margin-left: 20px;
    }

    .tdb-ligne-bon__toggle {
        order: 3;
        margin-left: auto;
    }

    .tdb-ligne-bon__presta {
        order: 4;
        flex: 0 0 100%;
        margin-left: 0;
    }

    /* La cartouche repliée du téléphone ne montre PAS la fin de validité :
       elle est déjà dans le détail, à la ligne « Fin ». */
    .tdb-ligne-bon__date {
        display: none;
    }

    /* n° + âge : sous le filet du détail (6048:12024), sur une même ligne.
       L'écart de 21px de la maquette = les 10px de `row-gap` + ces 11px. */
    .tdb-ligne-bon__reference {
        order: 5;
        display: flex;
        align-items: center;
        justify-content: space-between;
        flex: 0 0 100%;
        margin-top: 11px;
        padding-top: 20px;
        border-top: 1px solid var( --color-ink );
    }

    .tdb-ligne-bon:not( .is-open ) .tdb-ligne-bon__reference {
        display: none;
    }

    .tdb-ligne-bon__code,
    .tdb-ligne-bon__jour {
        flex: 0 0 auto;
        margin-left: 0;
    }

    /* Le filet est porté par le bloc n° + âge : le détail le perd et se
       contente des 10px qui l'en séparent (6048:12025). */
    .tdb-ligne-bon__detail {
        margin-top: 10px;
        padding-top: 0;
        border-top: 0;
    }

    .tdb-accordion__item.is-open .tdb-ligne-bon__detail {
        grid-template-columns: 1fr;
    }
}

/* ---------- Formulaire "Mon compte" ---------- */

/* Titre de page (I-1) : orange + filet orange, seul niveau de titre orange
   de la page (I-2 — les titres de section restent noirs, voir plus bas). */
.tdb-compte-form__title {
    color: var( --color-primary );
    font-size: var( --text-h1-size );
    line-height: var( --text-h1-lh );
    margin: var( --space-xl ) 0 var( --space-lg );
    padding-bottom: var( --space-md );
    border-bottom: 1px solid var( --color-primary );
}

.tdb-compte-form {
    margin-bottom: var( --space-2xl );
}

.tdb-compte-form__cols {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: var( --space-2xl );
}

@media ( max-width: 767px ) {
    .tdb-compte-form__cols {
        grid-template-columns: 1fr;
    }
}

.tdb-compte-form__section {
    display: flex;
    flex-direction: column;
    gap: var( --space-md );
    margin-bottom: var( --space-lg );
}

/* I-2 : contrairement au titre de page, les titres de section (Informations,
   Changement de mot de passe, Coordonnées bancaires, Type de bons vendu,
   Autoriser le bon à valeur variable) restent noirs dans la maquette. */
.tdb-compte-form__section h2 {
    font-size: var( --text-h2-size );
    color: var( --color-ink );
}

/* "Mes bons" (comme "Mon compte" et "Suivi de mes bons") est un titre de
   niveau page, pas un sous-titre — orange, contrairement aux 5 sous-titres
   ci-dessus (I-2). */
.tdb-compte-form__section--majeure h2 {
    color: var( --color-primary );
}

.tdb-compte-form__section h3 {
    font-size: var( --text-h3-size );
    color: var( --color-ink );
    margin: 0;
}

.tdb-compte-form__grid {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: var( --space-md );
}

/* Adresse (large) + NPA + Localité sur une même ligne (I-5). */
.tdb-compte-form__grid--adresse {
    grid-template-columns: 2fr 1fr 1fr;
}

@media ( max-width: 767px ) {
    /* MOD-IA 2026-09-01 : la grille GÉNÉRIQUE repasse aussi sur une colonne.
       Seule la variante --adresse était traitée : les sections du formulaire
       (Informations, Changement de mot de passe, Coordonnées bancaires…)
       restaient donc côte à côte sur deux colonnes de 178px, et la colonne de
       droite sortait de l'écran — la moitié du formulaire était inatteignable.
       La maquette mobile (482:3258) empile des blocs pleine largeur de 360px.
       Le défaut existait déjà, mais restait invisible tant que la colonne du
       back-office débordait elle-même (voir BO-1). */
    .tdb-compte-form__grid {
        grid-template-columns: 1fr;
    }
    .tdb-compte-form__grid--adresse {
        grid-template-columns: 1fr;
    }
}

.tdb-compte-form__full {
    grid-column: 1 / -1;
}

.tdb-compte-form__divider {
    border: none;
    border-top: 1px solid var( --color-primary ); /* filets orange (I-8) */
    margin-block: var( --space-xl );
}

/* Astérisque orange des champs obligatoires + mention de fin de bloc (I-3). */
.tdb-compte-form__req {
    color: var( --color-primary );
}

.tdb-compte-form__requis {
    align-self: flex-end;
    color: var( --color-primary );
    font-size: var( --text-caption-size );
    margin: 0;
}

/* Indication grise à la suite du libellé (I-4), sur les deux champs de mot
   de passe plutôt qu'un seul. */
.tdb-compte-form__hint {
    color: var( --color-text-muted );
    font-weight: var( --weight-light );
}

/* Grille 2 colonnes (I-6) : 10/20/50 à gauche, 100/200/500 à droite, cases
   alignées à gauche sur une ligne — la vraie régression venait de la règle
   ".tdb-compte-form label" (voir plus haut, corrigée avec :not(.tdb-checkbox)). */
.tdb-compte-form__checkboxes {
    display: grid;
    grid-template-columns: 1fr 1fr;
    grid-template-rows: repeat( 3, auto );
    grid-auto-flow: column; /* remplit la 1re colonne avant la 2e (10/20/50 puis 100/200/500) */
    gap: var( --space-sm ) var( --space-xl );
}

@media ( max-width: 767px ) {
    .tdb-compte-form__checkboxes {
        grid-template-columns: 1fr;
        grid-auto-flow: row;
    }
}

/* Bouton pilule gris (I-9) plutôt que l'input[type=file] natif du
   navigateur — le vrai champ reste présent, en superposition transparente. */
.tdb-compte-form__upload-label {
    display: block; /* écrase ".tdb-compte-form label{display:flex;flex-direction:column}" :
                        ce label ne contient que du texte + un astérisque, pas de champ à empiler dessous. */
    font-size: var( --text-caption-size );
    color: var( --color-text-muted );
}

/* "Valeur minimum/maximum du bon" (I-7) : empilés mais chacun à demi-largeur,
   pas étirés sur toute la largeur de la section comme les autres champs. */
.tdb-compte-form__demi {
    display: flex;
    flex-direction: column;
    gap: var( --space-md );
    max-width: 50%;
}

@media ( max-width: 767px ) {
    .tdb-compte-form__demi {
        max-width: 100%;
    }
}

.tdb-compte-form__upload {
    position: relative;
    display: inline-flex;
    align-items: center;
    align-self: flex-start;
    background: var( --color-surface-muted );
    border-radius: var( --radius-sm );
    padding: 12px 20px;
    font-size: var( --text-button-size );
    font-weight: var( --weight-medium );
    cursor: pointer;
}

.tdb-compte-form__upload input[type="file"] {
    position: absolute;
    inset: 0;
    opacity: 0;
    cursor: pointer;
}

/* ---------- Grille de cartes générique (repli WordPress standard) ---------- */
.posts-grid {
    display: grid;
    gap: var( --space-lg );
    grid-template-columns: 1fr;
}

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

.card {
    border-radius: var( --radius-card );
    box-shadow: var( --shadow-card );
    overflow: hidden;
}

/* ---------- Confort visuel : respecte "réduire les animations" ---------- */
@media ( prefers-reduced-motion: reduce ) {
    .btn,
    .btn__icon,
    .btn__icon img,
    .btn--orange-blanc,
    .btn--mascot-orange-blanc,
    .site-header__menu a,
    .site-header__utility-links a,
    .site-header__cart,
    .site-header__cart-bubbles,
    .site-header__cart-bubble,
    .site-header__cart-count,
    .step-card,
    .step-card__label strong,
    .step-card__label > span,
    .step-tile,
    .step-coin,
    .tdb-card-commercant,
    .tdb-card-commercant__name,
    .tdb-card-commercant__place,
    .tdb-card-commercant__tags,
    .tdb-card-commercant__arrow-icon,
    /* MOD-IA 2026-09-02 : le fondu croisé du bouton +/− de la vignette suit la
       même règle que celui de la flèche de carte, juste au-dessus. */
    .tdb-vignette-bon__toggle-icon,
    .tdb-prestation-card,
    .tdb-prestation-card__title,
    .tdb-prestation-card__desc,
    .tdb-prestation-card__stock,
    .hero__dot,
    /* MOD-IA 2026-09-30 : pas de fondu entre les slides du héros. */
    .hero__slide {
        transition: none !important;
    }

    /* Les collages des cartes "étapes" et les bulles du panier restent dans
       leur état neutre : seuls les changements de couleur (sans mouvement)
       sont conservés. Les tuiles satellites continuent de s'effacer, ce qui
       est une variation d'opacité, pas un déplacement. */
    .site-header__cart:hover .site-header__cart-bubbles,
    .tdb-card-commercant:hover {
        transform: none !important;
    }

    .step-card:hover .step-tile--burger,
    .step-card:hover .step-tile--mascot {
        transform: translate(-50%,-50%) !important;
    }

    .step-card:hover .step-tile--print {
        z-index: 3;
        transform: translate(-50%,-50%) rotate( 15deg ) !important;
    }

    .step-card:hover .step-tile--mail {
        transform: translate(-50%,-50%) rotate( 15deg ) !important;
    }

    .step-card:hover .step-coin--50 {
        left: 47.84cqw;
        top: 49.741cqw;
        width: 29.093cqw;
        height: 29.071cqw;
        border-radius: 6.177cqw;
        font-size: 8.639cqw;
        transform: translate(-50%,-50%) rotate( -25.8deg ) !important;
    }
}


/* ---------------------------------------------------------------------------
   « Suivi de mes bons » : chiffres clés + filtres segmentés
   Contenu repris de la prod, habillage repris de la maquette : bloc blanc à
   rayon 20px et filet #ECECEC comme les autres panneaux du back-office,
   pastilles de statut aux couleurs de .tdb-badge, pilules de filtre reprenant
   la bascule liste/vignettes.
   --------------------------------------------------------------------------- */
.tdb-suivi-chiffres {
    padding: 24px;
    margin: 0 0 20px;
    background: #fff;
    border: 1px solid var( --color-border );
    border-radius: var( --radius-card );
}

.tdb-suivi-chiffres__titre {
    margin: 0 0 18px;
    font-size: 18px;
    font-weight: 700;
    color: var( --color-text );
}

.tdb-suivi-chiffres__grid {
    display: grid;
    grid-template-columns: repeat( 2, 1fr );
    gap: 24px;
}

.tdb-suivi-chiffres__total {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 12px;
    padding-bottom: 10px;
    border-bottom: 1px solid var( --color-border );
}

.tdb-suivi-chiffres__label {
    font-size: 15px;
    color: var( --color-text );
}

.tdb-suivi-chiffres__montant {
    font-size: 20px;
    font-weight: 700;
    color: var( --color-primary );
    font-variant-numeric: tabular-nums;
}

.tdb-suivi-chiffres__details {
    list-style: none;
    margin: 12px 0 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 8px;
}

.tdb-suivi-chiffres__details li {
    display: flex;
    align-items: center;
    gap: 10px;
    font-size: 14px;
    color: #7C7C7C;
}

.tdb-suivi-chiffres__puce {
    flex-shrink: 0;
    width: 10px;
    height: 10px;
    border-radius: 50%;
    background: var( --badge-color, var( --color-primary ) );
}

.tdb-suivi-chiffres__detail-label {
    flex: 1;
}

.tdb-suivi-chiffres__detail-valeur {
    font-variant-numeric: tabular-nums;
    color: var( --color-text );
}

.tdb-suivi-segments {
    display: grid;
    grid-template-columns: repeat( 2, 1fr );
    gap: 24px;
    padding: 24px;
    margin: 0 0 20px;
    background: #fff;
    border: 1px solid var( --color-border );
    border-radius: var( --radius-card );
}

.tdb-suivi-segments__titre {
    margin: 0 0 12px;
    font-size: 15px;
    font-weight: 700;
    color: var( --color-text );
}

.tdb-suivi-segments__pills {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
}

/* MOD-IA 2026-09-02 : .tdb-suivi-pill déplacé tel quel vers
   assets/css/ui/01-boutons.css (aucune valeur changée), même découpage que
   .btn et .tdb-badge — famille "Actions" de la charte graphique. */

.tdb-suivi-export {
    display: flex;
    margin: 0 0 20px;
}

@media ( max-width: 900px ) {
    .tdb-suivi-chiffres__grid,
    .tdb-suivi-segments {
        grid-template-columns: 1fr;
    }
}


/* ---------------------------------------------------------------------------
   Contenu des onglets du compte (.tdb-bo-endpoint)
   Le HTML de ces onglets est produit par PassVal (et par WooCommerce), avec ses
   propres classes : on ne le réécrit pas, on l'habille pour qu'il adopte le
   vocabulaire de la maquette — titres, tableaux, boutons et notices du
   back-office.
   --------------------------------------------------------------------------- */
.tdb-bo-endpoint > h2,
.tdb-bo-endpoint > h3 {
    margin: 0 0 16px;
    font-size: 22px;
    color: var( --color-text );
}

/* PassVal ouvre chaque onglet par un bouton « Retour » : on lui donne
   l'apparence d'un bouton secondaire du thème. */
/* MOD-IA 2026-09-08 : même garde-fou que sur les <input type="submit"> plus
   bas — un élément qui porte déjà `.btn` relève du composant du thème, pas de
   cet habillage de repli, qui l'emporterait sinon jusque dans son survol.
   ANCIEN CODE :
   .tdb-bo-endpoint .button.button-primary,
   .tdb-bo-endpoint a.button { */
/* MOD-IA 2026-09-08 : ces boutons adoptent l'état neutre ET le survol de
   .btn--primary — demande client du 08.09.2026 (« normalise les boutons dans la
   page mon-compte pour que les animations soient pareil »).

   Les onglets du compte empilaient QUATRE comportements différents pour une
   même action orange, selon la balise que PassVal avait choisie :
     - .button.button-primary / a.button  : orange → blanc à texte orange, .2s
     - .rounded-btn                       : idem, .2s
     - input[type=submit]                 : AUCUN survol
     - .btn--primary (composant du thème) : orange → noir à texte blanc, .4s
   Passer d'un onglet à l'autre changeait donc la réaction des boutons. C'est
   .btn--primary qui fait foi : c'est le composant de la charte, celui qu'on
   retrouve sur tout le reste du site. Les trois habillages de repli s'alignent
   dessus ici et plus bas, durée et courbe comprises.

   Le libellé passe aussi du blanc au noir, comme .btn--primary : du blanc sur
   l'orange #FC9728 ne donne que 2,2:1, contre 8,6:1 en noir.

   ANCIEN CODE :
   .tdb-bo-endpoint .button.button-primary:not( .btn ),
   .tdb-bo-endpoint a.button:not( .btn ) {
       ...
       color: #fff;
       ...
       transition:
           background-color var( --duration-tdb-snap ) var( --ease-tdb ),
           color var( --duration-tdb-snap ) var( --ease-tdb );
   } */
/* MOD-IA 2026-09-09 : les <button class="button"> et <input class="button"> de
   WooCommerce entrent enfin dans cet habillage.

   Le sélecteur ne connaissait que deux formes : `.button.button-primary`
   (celle que pose PassVal) et `a.button` (les liens de WooCommerce). Or les
   DEUX formulaires que le client signale envoient par un `<button>` nu :
   « Enregistrer les modifications » de /mon-compte/edit-account/ sort en
   `<button class="woocommerce-Button button">` (form-edit-account.php) et
   « Enregistrer l'adresse » de /mon-compte/edit-address/ en
   `<button class="button">` (form-edit-address.php). Aucun des deux ne porte
   `button-primary` et aucun n'est un `<a>` : ils tombaient donc hors de toute
   règle du thème, s'affichaient avec le bouton gris natif du navigateur et
   n'avaient AUCUNE réaction au survol — c'est l'« animation hover pas
   correcte » relevée le 09.09.2026.

   `appearance: none`, `cursor: pointer` et `font-family: inherit` viennent de
   la même nécessité que sur les <input type="submit"> plus bas : un contrôle de
   formulaire natif garde sinon la police d'interface du système, le curseur
   flèche et une partie de son propre dessin par-dessus les jetons de la
   charte. Les trois sont neutres pour les <a>, qui n'en ont pas besoin. */
.tdb-bo-endpoint .button.button-primary:not( .btn ),
.tdb-bo-endpoint a.button:not( .btn ),
.tdb-bo-endpoint button.button:not( .btn ),
.tdb-bo-endpoint input.button:not( .btn ) {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    height: 60px;
    padding-inline: var( --space-lg );
    appearance: none;
    -webkit-appearance: none;
    cursor: pointer;
    background: var( --color-primary );
    border: 1px solid var( --color-primary );
    border-radius: var( --radius-sm );
    color: #000;
    font-family: inherit;
    font-size: var( --text-card-desc-size );
    text-decoration: none;
    transition:
        background-color var( --duration-tdb ) var( --ease-tdb ),
        border-color var( --duration-tdb ) var( --ease-tdb ),
        color var( --duration-tdb ) var( --ease-tdb );
}

/* MOD-IA 2026-09-08 : `:not( .btn )` aussi sur le survol, pour que la paire
   état neutre / état de survol reste cohérente (voir la règle ci-dessus).
   ANCIEN CODE :
   .tdb-bo-endpoint .button.button-primary:hover,
   .tdb-bo-endpoint a.button:hover { */
/* MOD-IA 2026-09-08 : survol aligné sur .btn--primary — bascule sur le noir de
   la charte au lieu de s'inverser en blanc à texte orange. Le clavier obtient
   le même retour que la souris (:focus-visible), qui manquait.
   ANCIEN CODE :
   .tdb-bo-endpoint .button.button-primary:not( .btn ):hover,
   .tdb-bo-endpoint a.button:not( .btn ):hover {
       background: #fff;
       color: var( --color-primary );
   } */
/* MOD-IA 2026-09-08 : survol ORANGE -> BLANC — demande client du 08.09.2026
   (« que l'animation du hover soit orange->blanc au lieu de orange->noir »).

   Le filet reste orange (posé dans l'état neutre) : sans lui, un bouton blanc
   sur le fond blanc de l'onglet n'aurait plus de contour au survol. Durée,
   courbe et :focus-visible sont ceux de la normalisation du même jour : c'est
   la COULEUR d'arrivée qui change, pas le rythme.

   ANCIEN CODE (bascule sur le noir, alignée sur .btn--primary) :
   background: var( --color-ink-strong );
   border-color: var( --color-ink-strong );
   color: #fff; */
/* MOD-IA 2026-09-09 : le survol suit les deux formes ajoutées à l'état neutre
   ci-dessus (<button class="button">, <input class="button">). Un état neutre
   sans son survol aurait juste déplacé le défaut : bouton à la charte, mais
   toujours inerte sous la souris. */
.tdb-bo-endpoint .button.button-primary:not( .btn ):hover,
.tdb-bo-endpoint .button.button-primary:not( .btn ):focus-visible,
.tdb-bo-endpoint a.button:not( .btn ):hover,
.tdb-bo-endpoint a.button:not( .btn ):focus-visible,
.tdb-bo-endpoint button.button:not( .btn ):hover,
.tdb-bo-endpoint button.button:not( .btn ):focus-visible,
.tdb-bo-endpoint input.button:not( .btn ):hover,
.tdb-bo-endpoint input.button:not( .btn ):focus-visible {
    background: #fff;
    border-color: var( --color-primary );
    color: var( --color-primary );
}

/* Tableaux (listes de bons, de prestations, DataTables de PassVal). */
.tdb-bo-endpoint table {
    width: 100%;
    border-collapse: collapse;
    background: #fff;
    border: 1px solid var( --color-border );
    border-radius: var( --radius-card );
    overflow: hidden;
    font-size: 14px;
}

.tdb-bo-endpoint table th {
    padding: 14px 16px;
    background: #FAFAFA;
    border-bottom: 1px solid var( --color-border );
    text-align: left;
    font-weight: 700;
    color: var( --color-text );
}

.tdb-bo-endpoint table td {
    padding: 14px 16px;
    border-bottom: 1px solid var( --color-border );
    color: var( --color-text );
    font-variant-numeric: tabular-nums;
}

.tdb-bo-endpoint table tr:last-child td {
    border-bottom: 0;
}

/* Le tableau ne doit jamais élargir la page : il défile dans son conteneur. */
.tdb-bo-endpoint .dataTables_wrapper,
.tdb-bo-endpoint .tdb-table-scroll {
    overflow-x: auto;
}

/* Champs de formulaire hors ACF (PassVal en pose quelques-uns à la main). */
.tdb-bo-endpoint input[type="text"],
.tdb-bo-endpoint input[type="number"],
.tdb-bo-endpoint input[type="email"],
.tdb-bo-endpoint input[type="date"],
.tdb-bo-endpoint select,
.tdb-bo-endpoint textarea {
    height: 60px;
    padding-inline: var( --space-md );
    background: #fff;
    border: 1px solid var( --color-text-muted );
    border-radius: var( --radius-sm );
    font-family: var( --font-body );
    font-size: var( --text-card-desc-size );
    font-weight: var( --weight-light );
    color: var( --color-text );
}

/* MOD-IA 2026-09-10 : plancher de 120px pour toute zone de texte d'un onglet du
   compte — revue visuelle du 10.09.2026.

   Sans plancher, une zone de texte sans attribut `rows` retombait sur la
   hauteur naturelle d'UNE ligne : la « Remarque des bons (facultatif) » de
   « Génération de bons » faisait 62px, à côté de zones de 120px (prestations,
   bons QR autocollants) et de 140px (formulaires ACF). Elle se lisait comme un
   champ de saisie simple, pas comme une zone de texte.

   120px est la valeur déjà posée sur les formulaires de PassVal
   (#prestation-form, #add-bon-activable-form, plus bas) : c'est un plancher, pas
   une hauteur fixe — une zone à qui son attribut `rows` donne plus de place la
   garde (« Texte de présentation de votre entreprise », rows=8).
   ANCIEN CODE :
   .tdb-bo-endpoint textarea {
       height: auto;
       padding-block: var( --space-sm );
   } */
.tdb-bo-endpoint textarea {
    height: auto;
    min-height: 120px;
    padding-block: var( --space-sm );
}

/* MOD-IA 2026-09-08 : cette règle de repli ne touche PLUS les boutons qui
   portent déjà `.btn`, sinon elle éteint leur survol.

   Régression constatée à l'écran sur le bouton « Générer » de l'onglet
   « Génération de bons » (#generate-bons-btn, classe `btn btn--primary`) : il
   restait orange au survol, alors que .btn--primary bascule sur le noir.

   La cause est une question de spécificité, pas de valeur : le sélecteur
   `.tdb-bo-endpoint input[type="submit"]` pèse (0,2,1) — une classe PLUS un
   sélecteur d'attribut, qui compte comme une classe, PLUS un élément — quand
   `.btn--primary:hover` ne pèse que (0,2,0). L'habillage de repli l'emportait
   donc sur le composant, y compris dans son état de survol : le bouton avait
   son fond et sa hauteur (60px au lieu de 46), mais plus aucune réaction.

   `:not( .btn )` rend la règle à son rôle : habiller les <input type="submit">
   que PassVal pose SANS classe. Ceux qui portent le composant du thème sont
   désormais gouvernés par .btn / .btn--primary, avec leurs cinq états.

   ANCIEN CODE :
   .tdb-bo-endpoint input[type="submit"] { */
.tdb-bo-endpoint input[type="submit"]:not( .btn ) {
    height: 60px;
    padding-inline: var( --space-lg );
    background: var( --color-primary );
    border: 1px solid var( --color-primary );
    border-radius: var( --radius-sm );
    /* MOD-IA 2026-09-08 : libellé noir et transition, comme .btn--primary
       (normalisation des boutons de « Mon compte », demande du 08.09.2026).
       ANCIEN CODE :
       color: #fff;
       (aucune transition) */
    color: #000;
    font-family: inherit;
    /* MOD-IA 2026-09-10 : 15px -> 14px Medium, comme tous les autres boutons du
       compte — revue visuelle du 10.09.2026.

       15px ne correspond à aucun jeton de la charte : le libellé de bouton est
       en 14px Medium (--text-button-size / --weight-medium, composant .btn).
       Ce sélecteur est le plus spécifique de la page (0-3-1) : il l'emportait
       sur « .tdb-bo-endpoint .rounded-btn » et sur l'habillage des
       « .button », si bien que les DEUX boutons d'envoi rendus par PassVal en
       <input type="submit"> — « Ajouter » (Gestion des prestations) et
       « Activer ce bon » (Bons QR autocollants) — sortaient un cran plus gros
       et un cran plus maigre que le « Mise à jour » de l'onglet voisin.
       ANCIEN CODE :
       font-size: 15px;
       (aucune graisse déclarée, donc 400 hérité du navigateur) */
    font-size: var( --text-button-size );
    font-weight: var( --weight-medium );
    cursor: pointer;
    transition:
        background-color var( --duration-tdb ) var( --ease-tdb ),
        border-color var( --duration-tdb ) var( --ease-tdb ),
        color var( --duration-tdb ) var( --ease-tdb );
}

/* MOD-IA 2026-09-08 : survol AJOUTÉ — ces boutons d'envoi étaient les seuls de
   la page à ne donner aucun retour au passage de la souris, alors qu'ils
   portent l'action principale de plusieurs onglets (« Enregistrer » des
   formulaires ACF de la fiche commerçant et des coordonnées bancaires). Même
   bascule que .btn--primary. */
/* MOD-IA 2026-09-08 : survol ORANGE -> BLANC — demande client du 08.09.2026
   (« que l'animation du hover soit orange->blanc au lieu de orange->noir »).

   Le filet reste orange (posé dans l'état neutre) : sans lui, un bouton blanc
   sur le fond blanc de l'onglet n'aurait plus de contour au survol. Durée,
   courbe et :focus-visible sont ceux de la normalisation du même jour : c'est
   la COULEUR d'arrivée qui change, pas le rythme.

   ANCIEN CODE (bascule sur le noir, alignée sur .btn--primary) :
   background: var( --color-ink-strong );
   border-color: var( --color-ink-strong );
   color: #fff; */
.tdb-bo-endpoint input[type="submit"]:not( .btn ):hover,
.tdb-bo-endpoint input[type="submit"]:not( .btn ):focus-visible {
    background: #fff;
    border-color: var( --color-primary );
    color: var( --color-primary );
}

/* MOD-IA 2026-09-08 : un <input type="submit"> ne se dessine pas comme un
   <button>. Sans ces trois déclarations, `.btn` posé sur un input laissait le
   navigateur peindre le liseré et le fond gris de son bouton natif par-dessus
   les jetons de la charte, et le curseur restait la flèche par défaut. La
   règle est neutre pour les <button>, qui ne sont pas visés. */
.tdb-bo-endpoint input[type="submit"].btn,
.tdb-compte-form input[type="submit"].btn {
    border: 0;
    appearance: none;
    cursor: pointer;
}

/* MOD-IA 2026-09-08 : .btn--primary suit le même survol orange -> blanc, mais
   SEULEMENT dans les onglets du compte — demande client du 08.09.2026.

   Le composant de la charte est présent sur cette page (bouton « Générer » de
   « Génération de bons », envoi des formulaires ACF) à côté des habillages de
   repli ci-dessus. Sans cette règle, la page mélangerait de nouveau deux
   survols — exactement ce que la normalisation du matin avait supprimé.

   La portée s'arrête à .tdb-bo-endpoint, c'est-à-dire au contenu d'un onglet du
   compte : partout ailleurs .btn--primary garde le survol noir relevé dans le
   prototype Figma (réaction ON_HOVER du composant « BTN mascot orange > noir »),
   y compris sur l'écran « Valider un bon », qui vit dans .tdb-bo__content et
   non dans un onglet.

   Le filet orange est posé en `box-shadow: inset` et non en `border` : .btn n'a
   pas de bordure, et lui en ajouter une au survol décalerait le libellé d'un
   pixel au passage de la souris. */
/* MOD-IA 2026-09-09 : le filet orange s'anime AVEC le fond, au lieu d'apparaître
   d'un coup.

   La règle de survol ci-dessous dessine ce filet en `box-shadow`, mais la
   transition du composant (.btn, assets/css/ui/01-boutons.css) n'énumère que
   `background-color` et `color` : une propriété absente de cette liste change
   instantanément. Le fond du bouton fondait donc en .4s pendant que son contour
   claquait à 0s — deux vitesses dans un même survol, ce qui se lit comme un
   défaut d'animation. On étend la liste ICI, dans la portée de l'onglet, plutôt
   que sur .btn : le filet inset n'existe que dans cette règle, le composant
   général n'a rien à animer de plus. */
/* MOD-IA 2026-09-10 : hauteur alignée sur les autres boutons d'envoi du compte
   — revue visuelle du 10.09.2026.

   .btn fait 46px : c'est la hauteur du composant de la charte, juste sur tout
   le site public. Mais dans un onglet du compte, le bouton d'envoi fait 60px
   (règle « .tdb-bo-endpoint .button… » plus haut), comme les champs qu'il
   suit. Le seul .btn--primary d'un onglet est le bouton « Générer » de
   « Génération de bons » : il s'affichait 14px plus court que le « Mise à
   jour » des formulaires ACF et que les champs juste au-dessus de lui.

   La portée reste .tdb-bo-endpoint : ailleurs, .btn--primary garde ses 46px. */
.tdb-bo-endpoint .btn--primary {
    height: 60px;
    transition:
        background-color var( --duration-tdb ) var( --ease-tdb ),
        color var( --duration-tdb ) var( --ease-tdb ),
        box-shadow var( --duration-tdb ) var( --ease-tdb );
}

.tdb-bo-endpoint .btn--primary:hover,
.tdb-bo-endpoint .btn--primary:focus-visible {
    background: #fff;
    box-shadow: inset 0 0 0 1px var( --color-primary );
    color: var( --color-primary );
}

/* Le badge d'icône d'un bouton à mascotte s'inverse avec lui : sur fond blanc,
   c'est lui qui prend l'orange. */
.tdb-bo-endpoint .btn--primary:hover .btn__icon {
    background: var( --color-primary );
}

/* Notices WooCommerce dans le back-office. */
.tdb-bo-endpoint .woocommerce-message,
.tdb-bo-endpoint .woocommerce-error,
.tdb-bo-endpoint .woocommerce-info {
    padding: 14px 18px;
    margin: 0 0 20px;
    border-radius: var( --radius-sm );
    border: 1px solid var( --color-border );
    background: #fff;
    list-style: none;
}

/* MOD-IA 2026-09-09 : la puce en police WooCommerce est retirée — vérifié au
   navigateur le 09.09.2026 sur /mon-compte/orders/.

   WooCommerce pose son icône en ::before ABSOLU à left: 1.5em et réserve la
   place avec un padding gauche de 3.5em. La règle ci-dessus ramène ce padding à
   18px sans toucher au ::before : le glyphe se superposait donc aux deux
   premières lettres du message (« Confirmez votre adresse e-mail » barré d'un
   rond). Nos propres bandeaux (tdb_ui( 'notice' )) n'ont pas de puce : on
   supprime celle-ci plutôt que de rendre le padding à WooCommerce. */
.tdb-bo-endpoint .woocommerce-message::before,
.tdb-bo-endpoint .woocommerce-error::before,
.tdb-bo-endpoint .woocommerce-info::before {
    content: none;
}

/* MOD-IA 2026-09-09 : sur petit écran, le bouton du bandeau passe SOUS le
   texte. WooCommerce le fait flotter à droite ; à 390px, « Confirmez votre
   adresse e-mail pour vérifier les commandes passées » se retrouvait comprimé
   sur cinq lignes dans la colonne restante. */
@media ( max-width: 767px ) {
    .tdb-bo-endpoint .woocommerce-message,
    .tdb-bo-endpoint .woocommerce-error,
    .tdb-bo-endpoint .woocommerce-info {
        display: flex;
        flex-direction: column;
        align-items: flex-start;
        gap: var( --space-sm );
    }

    /* order: 2 — WooCommerce place le bouton AVANT le texte dans le balisage
       du bandeau « Confirmez votre adresse e-mail » (et après dans celui
       « Aucune commande »). Sans cette ligne, le bouton se retrouvait au-dessus
       du message dans un cas et en dessous dans l'autre. */
    .tdb-bo-endpoint .woocommerce-message .button,
    .tdb-bo-endpoint .woocommerce-error .button,
    .tdb-bo-endpoint .woocommerce-info .button {
        float: none;
        order: 2;
        margin: 0;
    }
}

/* ---------------------------------------------------------------------------
   MOD-IA 2026-09-09 : écrans clients de WooCommerce dans le back-office
   (Commandes, Adresses, Moyens de paiement) — demande client du 09.09.2026.

   Ces trois onglets n'avaient jamais été habillés : ils étaient retirés du menu
   du compte (woocommerce/myaccount/navigation.php), donc jamais affichés dans
   .tdb-bo-endpoint. Le gros de leur mise en forme est déjà là — tableaux,
   champs, boutons — il ne reste que ce que WooCommerce livre dans sa propre
   feuille pour un thème boutique : deux adresses posées en colonnes flottées.
   --------------------------------------------------------------------------- */

/* Les deux adresses (facturation, livraison) en grille plutôt qu'en flottants :
   la mise en colonnes de WooCommerce (.col2-set > .col-1 / .col-2) suppose une
   largeur de contenu qu'un onglet du back-office n'a pas. */
.tdb-bo-endpoint .woocommerce-Addresses {
    display: grid;
    grid-template-columns: repeat( 2, minmax( 0, 1fr ) );
    gap: var( --space-md );
    margin: 0;
}

/* MOD-IA 2026-09-09 : le clearfix de WooCommerce (.col2-set::before / ::after,
   `content: " "; display: table`) est neutralisé — vérifié au navigateur le
   09.09.2026 sur /mon-compte/edit-address/.

   Dans un conteneur en grille, ::before et ::after DEVIENNENT DES ÉLÉMENTS DE
   GRILLE. Les deux fausses cases occupaient donc la 1re et la 4e position :
   « Adresse de facturation » se retrouvait poussée dans la colonne de droite et
   « Adresse de livraison » seule sur une deuxième ligne, en escalier. Le
   clearfix n'a plus d'objet ici de toute façon, les adresses ne flottant plus. */
.tdb-bo-endpoint .woocommerce-Addresses::before,
.tdb-bo-endpoint .woocommerce-Addresses::after {
    content: none;
}

/* float: none est indispensable — sans lui les .col-1 / .col-2 restent flottés
   et sortent de la grille, l'une par-dessus l'autre. */
.tdb-bo-endpoint .woocommerce-Addresses .woocommerce-Address {
    float: none;
    width: auto;
    padding: var( --space-md );
    border: 1px solid var( --color-border );
    border-radius: var( --radius-sm );
    background: #fff;
}

/* MOD-IA 2026-09-10 : titre et lien empilés au lieu d'être côte à côte — revue
   visuelle du 10.09.2026.

   Sur une rangée, le titre et le lien « Ajouter … » se partageaient la largeur
   de la carte (~390px) : « Adresse de facturation » se cassait sur deux lignes
   et son lien aussi, pendant que « Adresse de livraison », plus court, tenait
   sur une seule. Les deux cartes de l'onglet, identiques par nature,
   n'affichaient donc pas leur en-tête à la même hauteur et la ligne suivante ne
   tombait pas au même endroit dans l'une et dans l'autre.

   Empilés, les deux en-têtes ont la même forme quelle que soit la longueur du
   libellé — c'est aussi ce que fait le reste du back-office, où le titre d'un
   bloc occupe sa propre ligne.
   ANCIEN CODE :
       align-items: baseline;
       justify-content: space-between; */
.tdb-bo-endpoint .woocommerce-Address-title {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: var( --space-2xs );
    margin: 0 0 12px;
}

/* MOD-IA 2026-09-10 : taille du titre d'une carte d'adresse — revue visuelle du
   10.09.2026.

   Ces deux <h2> (« Adresse de facturation », « Adresse de livraison ») vivent
   dans un <header class="woocommerce-Address-title"> : la règle
   « .tdb-bo-endpoint > h2 », qui ne vise que les enfants DIRECTS de l'onglet,
   ne les atteignait pas et ils retombaient sur le h2 global du site, 24px. Ils
   s'affichaient donc à la taille d'un titre de niveau page — la même que celle
   du titre orange qui ouvre désormais l'onglet — alors que ce sont des titres
   de section, comme « Formulaire de création d'une nouvelle prestation » ou
   « Bons QR autocollants », tous deux à 22px. Sur 24px, « Adresse de
   facturation » se cassait en plus sur deux lignes dans sa carte.
   ANCIEN CODE :
   .tdb-bo-endpoint .woocommerce-Address-title h2,
   .tdb-bo-endpoint .woocommerce-Address-title h3 {
       margin: 0;
   } */
.tdb-bo-endpoint .woocommerce-Address-title h2,
.tdb-bo-endpoint .woocommerce-Address-title h3 {
    margin: 0;
    font-size: 22px;
    color: var( --color-text );
}

.tdb-bo-endpoint .woocommerce-Address address {
    margin: 0;
    font-style: normal;
    line-height: 1.6;
    color: var( --color-text );
}

/* Une seule colonne dès que la place manque : c'est la même bascule que le
   reste du back-office (menu latéral masqué sous 767px). */
@media ( max-width: 767px ) {
    .tdb-bo-endpoint .woocommerce-Addresses {
        grid-template-columns: 1fr;
    }
}

/* Historique des commandes et liste des moyens de paiement : rien à poser sur
   les tableaux eux-mêmes — ils héritent de `.tdb-bo-endpoint table`, et sur
   petit écran c'est woocommerce-smallscreen.css qui les empile ligne par ligne.
   Leur donner ici un `display: block` pour les faire défiler casserait
   justement cet empilement (chaque thead/tbody formerait sa propre table). */

/* Le bouton « Ajouter un moyen de paiement » et la pagination des commandes
   sont posés juste après leur tableau, sans marge propre.

   MOD-IA 2026-09-09 : la pagination passe en flex — vérifié au navigateur le
   09.09.2026 sur l'écran « Commandes ». WooCommerce y pose « Précédent » et
   « Suivant » comme deux liens frères, sans conteneur ni marge : habillés en
   boutons du thème, ils se touchaient et leurs coins arrondis se chevauchaient.
   Le gap les sépare sans dépendre de l'espace blanc du balisage. */
.tdb-bo-endpoint .woocommerce-pagination {
    display: flex;
    flex-wrap: wrap;
    gap: var( --space-sm );
}

.tdb-bo-endpoint .woocommerce-pagination,
.tdb-bo-endpoint > .button {
    margin-top: var( --space-md );
}

/* MOD-IA 2026-09-09 : séparation entre deux commandes dans la vue empilée.

   Sous 768px, woocommerce-smallscreen.css transforme chaque ligne du tableau en
   bloc « libellé : valeur ». Les commandes s'enchaînent alors sans rien entre
   elles : vérifié au navigateur à 390px, on ne voit pas où finit la commande
   #1042 et où commence #1038. Le filet et l'écart rendent chaque commande
   lisible comme une carte. */
@media ( max-width: 768px ) {
    .tdb-bo-endpoint .shop_table_responsive tbody tr {
        display: block;
        margin-bottom: var( --space-md );
        border-bottom: 2px solid var( --color-border );
    }

    .tdb-bo-endpoint .shop_table_responsive tbody tr:last-child {
        margin-bottom: 0;
        border-bottom: 0;
    }
}

/* Entrée active du menu latéral. */
.tdb-bo-sidebar__submenu li.is-active > a {
    color: var( --color-primary );
    font-weight: 700;
}

/* ---------------------------------------------------------------------------
   Formulaires ACF du back-office (.tdb-acf-form ET onglets PassVal)
   Les champs viennent de PassVal (ACF) : lui seul décide du nom, du type et de
   la liste. Ici on ne fait que les habiller AVEC LES MÊMES VALEURS que les
   formulaires du thème (.tdb-compte-form, mesurées sur la maquette) — champ de
   60px, filet --color-text-muted, rayon --radius-sm, libellé 14px Light — pour
   qu'un formulaire ACF soit indistinguable d'un formulaire du thème.
   --------------------------------------------------------------------------- */
.tdb-acf-form .acf-fields > .acf-field,
.tdb-bo-endpoint .acf-fields > .acf-field {
    padding: 0;
    margin: 0 0 var( --space-md );
    border: 0;
}

.tdb-acf-form .acf-field .acf-label,
.tdb-bo-endpoint .acf-field .acf-label {
    margin: 0 0 10px;
}

.tdb-acf-form .acf-field .acf-label label,
.tdb-bo-endpoint .acf-field .acf-label label {
    display: block;
    margin: 0;
    font-family: var( --font-body );
    font-size: var( --text-card-desc-size );
    line-height: var( --text-card-desc-lh );
    letter-spacing: var( --tracking-tight );
    font-weight: var( --weight-light );
    color: var( --color-text );
}

/* ACF marque les champs requis par un <span class="acf-required">*</span> :
   même orange que l'astérisque des formulaires du thème. */
.tdb-acf-form .acf-required,
.tdb-bo-endpoint .acf-required {
    color: var( --color-primary );
}

.tdb-acf-form .acf-field .acf-label p.description,
.tdb-bo-endpoint .acf-field .acf-label p.description {
    margin: 4px 0 0;
    font-size: var( --text-card-desc-size );
    font-weight: var( --weight-light );
    color: var( --color-text-muted );
}

.tdb-acf-form .acf-input input[type="text"],
.tdb-bo-endpoint .acf-input input[type="text"],
.tdb-acf-form .acf-input input[type="email"],
.tdb-bo-endpoint .acf-input input[type="email"],
.tdb-acf-form .acf-input input[type="url"],
.tdb-bo-endpoint .acf-input input[type="url"],
.tdb-acf-form .acf-input input[type="number"],
.tdb-bo-endpoint .acf-input input[type="number"],
.tdb-acf-form .acf-input input[type="password"],
.tdb-bo-endpoint .acf-input input[type="password"],
.tdb-acf-form .acf-input input[type="date"],
.tdb-bo-endpoint .acf-input input[type="date"],
.tdb-acf-form .acf-input select,
.tdb-bo-endpoint .acf-input select,
.tdb-acf-form .acf-input textarea,
.tdb-bo-endpoint .acf-input textarea {
    width: 100%;
    height: 60px;
    padding-inline: var( --space-md );
    background: #fff;
    border: 1px solid var( --color-text-muted );
    border-radius: var( --radius-sm );
    font-family: var( --font-body );
    font-size: var( --text-card-desc-size );
    font-weight: var( --weight-light );
    color: var( --color-text );
    transition: border-color var( --duration-tdb-snap ) var( --ease-tdb );
}

/* MOD-IA 2026-09-10 : plancher ramené de 140px à 120px, le seul du compte —
   revue visuelle du 10.09.2026. Voir la règle « .tdb-bo-endpoint textarea »
   plus haut : trois planchers différents cohabitaient (aucun, 120, 140). Sans
   effet visible sur les deux zones de l'onglet « Entreprise - Détails », dont
   l'attribut `rows` (8 et 5) donne déjà 183px et 140px.
   ANCIEN CODE : min-height: 140px; */
.tdb-acf-form .acf-input textarea,
.tdb-bo-endpoint .acf-input textarea {
    height: auto;
    min-height: 120px;
    padding-block: var( --space-sm );
    resize: vertical;
}

.tdb-acf-form .acf-input input:focus,
.tdb-bo-endpoint .acf-input input:focus,
.tdb-acf-form .acf-input textarea:focus,
.tdb-bo-endpoint .acf-input textarea:focus,
.tdb-acf-form .acf-input select:focus,
.tdb-bo-endpoint .acf-input select:focus {
    outline: none;
    border-color: var( --color-primary );
}

/* MOD-IA 2026-09-01 : la liste de cases passe sur DEUX colonnes, comme la
   maquette (chore I-6 : 10 / 20 / 50 en colonne 1, 100 / 200 / 500 en colonne 2).
   Elle s'affichait sur une seule colonne, chaque case sur sa propre ligne.
   Repasse à une colonne en mobile, où la frame empile les blocs. */
.tdb-acf-form .acf-checkbox-list,
.tdb-bo-endpoint .acf-checkbox-list {
    display: grid;
    grid-template-columns: 1fr 1fr;
    /* Remplissage en COLONNES : la maquette veut 10 / 20 / 50 dans la première
       et 100 / 200 / 500 dans la seconde (I-6), pas un remplissage ligne par
       ligne qui donnerait 10 / 20 puis 50 / 100. */
    grid-template-rows: repeat( 3, auto );
    grid-auto-flow: column;
    column-gap: var( --space-xl );
}

/* ACF pose un clearfix (::before / ::after) sur .acf-bl. Dans une grille, ces
   pseudo-éléments deviennent de vrais ITEMS : le premier occupait la case 1 et
   décalait toute la liste d'un cran — « 10chf » se retrouvait seul en haut de
   la colonne de droite. */
.tdb-acf-form .acf-checkbox-list::before,
.tdb-bo-endpoint .acf-checkbox-list::before,
.tdb-acf-form .acf-checkbox-list::after,
.tdb-bo-endpoint .acf-checkbox-list::after {
    content: none;
}

@media ( max-width: 767px ) {
    .tdb-acf-form .acf-checkbox-list,
    .tdb-bo-endpoint .acf-checkbox-list {
        grid-template-columns: 1fr;
    }
}

/* MOD-IA 2026-09-01 : c'est le <label> qui porte la rangée, pas le <li>.
   ACF rend `<li><label><input> texte</label></li>` : le <li> n'a donc qu'UN
   seul enfant, et le display:flex + gap posé sur lui ne pouvait rien aligner.
   La case se retrouvait au-dessus de son libellé au lieu d'être à côté.
   Même structure pour le champ oui/non (`.acf-true-false > label`), dont le
   texte vit dans un <span class="message">. */
.tdb-acf-form .acf-checkbox-list li > label,
.tdb-bo-endpoint .acf-checkbox-list li > label,
.tdb-acf-form .acf-radio-list li > label,
.tdb-bo-endpoint .acf-radio-list li > label,
.tdb-acf-form .acf-true-false > label,
.tdb-bo-endpoint .acf-true-false > label {
    display: flex;
    align-items: center;
    gap: 10px;
    cursor: pointer;
    font-size: var( --text-card-desc-size );
    font-weight: var( --weight-light );
    color: var( --color-text );
}

/* Le gabarit d'ACF laisse des tabulations entre <input> et <span class="message">.
   Dans un conteneur flex, cette espace devient un ITEM anonyme à part entière :
   on payait sa largeur PLUS un second `gap`, d'où un écart d'environ 40px entre
   la case et son libellé. font-size:0 sur le conteneur annule cet item, la
   taille réelle étant rendue aux enfants. */
.tdb-acf-form .acf-true-false > label,
.tdb-bo-endpoint .acf-true-false > label {
    font-size: 0;
}

.tdb-acf-form .acf-true-false > label .message,
.tdb-bo-endpoint .acf-true-false > label .message {
    font-size: var( --text-card-desc-size );
    /* ACF centre ce libellé (text-align:center dans sa propre feuille). Comme
       le <span> s'étire sur toute la largeur restante — 513px pour un texte de
       384 —, le centrage le décalait de 64px vers la droite et creusait un vide
       après la case. Il doit être calé à gauche, collé à sa case. */
    text-align: left;
}

/* Cases à cocher / radios ACF : même pastille orange que .tdb-checkbox. */
.tdb-acf-form .acf-checkbox-list li,
.tdb-bo-endpoint .acf-checkbox-list li,
.tdb-acf-form .acf-radio-list li,
.tdb-bo-endpoint .acf-radio-list li {
    display: flex;
    align-items: center;
    gap: 10px;
    margin: 0 0 10px;
    font-size: var( --text-card-desc-size );
    font-weight: var( --weight-light );
    color: var( --color-text );
}

/* MOD-IA 2026-09-01 : le champ oui/non (.acf-true-false) reçoit la même case
   carrée à filet orange. Il affichait la case native bleue du navigateur,
   seule note discordante du formulaire une fois les toggles retirés. */
.tdb-acf-form .acf-checkbox-list input[type="checkbox"],
.tdb-bo-endpoint .acf-checkbox-list input[type="checkbox"],
.tdb-acf-form .acf-true-false input[type="checkbox"],
.tdb-bo-endpoint .acf-true-false input[type="checkbox"],
.tdb-acf-form .acf-radio-list input[type="radio"],
.tdb-bo-endpoint .acf-radio-list input[type="radio"] {
    appearance: none;
    -webkit-appearance: none;
    flex-shrink: 0;
    width: 16px;
    height: 16px;
    margin: 0;
    background: #fff;
    border: 1px solid var( --color-primary );
    border-radius: var( --radius-badge );
    cursor: pointer;
    display: grid;
    place-content: center;
}

.tdb-acf-form .acf-radio-list input[type="radio"],
.tdb-bo-endpoint .acf-radio-list input[type="radio"] {
    border-radius: 50%;
}

.tdb-acf-form .acf-checkbox-list input[type="checkbox"]::before,
.tdb-bo-endpoint .acf-checkbox-list input[type="checkbox"]::before,
.tdb-acf-form .acf-true-false input[type="checkbox"]::before,
.tdb-bo-endpoint .acf-true-false input[type="checkbox"]::before,
.tdb-acf-form .acf-radio-list input[type="radio"]::before,
.tdb-bo-endpoint .acf-radio-list input[type="radio"]::before {
    content: "";
    width: 8px;
    height: 8px;
    border-radius: 2px;
    background: var( --color-primary );
    transform: scale( 0 );
    transition: transform var( --duration-tdb-snap ) var( --ease-tdb );
}

.tdb-acf-form .acf-radio-list input[type="radio"]::before,
.tdb-bo-endpoint .acf-radio-list input[type="radio"]::before {
    border-radius: 50%;
}

.tdb-acf-form .acf-checkbox-list input[type="checkbox"]:checked::before,
.tdb-bo-endpoint .acf-checkbox-list input[type="checkbox"]:checked::before,
.tdb-acf-form .acf-true-false input[type="checkbox"]:checked::before,
.tdb-bo-endpoint .acf-true-false input[type="checkbox"]:checked::before,
.tdb-acf-form .acf-radio-list input[type="radio"]:checked::before,
.tdb-bo-endpoint .acf-radio-list input[type="radio"]:checked::before {
    transform: scale( 1 );
}

.tdb-acf-form .acf-true-false .acf-switch.-on,
.tdb-bo-endpoint .acf-true-false .acf-switch.-on {
    background: var( --color-primary );
    border-color: var( --color-primary );
}

.tdb-acf-form .acf-image-uploader,
.tdb-bo-endpoint .acf-image-uploader,
.tdb-acf-form .acf-input .acf-button,
.tdb-bo-endpoint .acf-input .acf-button {
    border-radius: var( --radius-sm );
}

.tdb-acf-form .acf-form-submit,
.tdb-bo-endpoint .acf-form-submit {
    margin-top: var( --space-lg );
}

/* ---------------------------------------------------------------------------
   MOD-IA 2026-09-09 : formulaires de compte de WooCommerce — « Détails du
   compte » (/mon-compte/edit-account/) et « Adresses » de facturation et de
   livraison (/mon-compte/edit-address/{billing,shipping}/).
   Demande client du 09.09.2026 : « que ça ressemble plus au visuel des
   formulaires ACF ».

   Ces deux écrans sont rendus par les gabarits de WooCommerce
   (myaccount/form-edit-account.php, myaccount/form-edit-address.php), que le
   thème NE surcharge PAS : leur balisage n'est donc pas le nôtre
   (`p.form-row` + `label` + `input.input-text`, là où ACF pose
   `div.acf-field` + `div.acf-label` + `div.acf-input`). Ils n'héritaient que de
   la règle de repli `.tdb-bo-endpoint input[type="text"]` — d'où des champs à
   la bonne hauteur mais sans largeur imposée, des libellés au style natif du
   navigateur, un astérisque de champ requis en rouge souligné, et les deux
   colonnes flottées de WooCommerce (`form-row-first` / `form-row-last`, 47% en
   float) au milieu d'une colonne de back-office qui n'a pas cette largeur.

   On les habille ICI avec exactement les mêmes valeurs que le bloc ACF
   ci-dessus — libellé 14px Light à 10px du champ, champ de 60px, filet
   --color-text-muted, rayon --radius-sm, filet orange au focus — plutôt que
   de recopier les gabarits de WooCommerce dans le thème : une surcharge de
   gabarit se périme à chaque mise à jour de l'extension, une feuille de style
   non.
   --------------------------------------------------------------------------- */

/* Titre « Adresse de facturation » / « Adresse de livraison ». Il vit DANS le
   <form> : `.tdb-bo-endpoint > h2` (enfant direct) ne l'atteignait pas, il
   sortait donc au style par défaut du navigateur. */
.tdb-bo-endpoint .woocommerce-EditAccountForm > h2,
.tdb-bo-endpoint form > h2,
.tdb-bo-endpoint form > h3 {
    margin: 0 0 16px;
    font-size: 22px;
    color: var( --color-text );
}

/* Une rangée = un champ, sur toute la largeur, comme un `.acf-field`.
   WooCommerce fait flotter `form-row-first` et `form-row-last` à 47% pour les
   mettre côte à côte : dans la colonne du back-office (665px à 1024px, moins
   encore quand le menu latéral est là), les deux moitiés se chevauchaient avec
   le champ pleine largeur qui suit. Le `.clear` que WooCommerce intercale pour
   rattraper ces flottants n'a plus d'objet une fois ceux-ci retirés. */
.tdb-bo-endpoint .woocommerce-EditAccountForm .form-row,
.tdb-bo-endpoint .woocommerce-address-fields .form-row {
    display: block;
    float: none;
    width: 100%;
    padding: 0;
    margin: 0 0 var( --space-md );
}

.tdb-bo-endpoint .woocommerce-EditAccountForm .clear,
.tdb-bo-endpoint .woocommerce-address-fields .clear {
    display: none;
}

/* Libellé : mêmes valeurs que `.acf-field .acf-label label`. */
.tdb-bo-endpoint .woocommerce-EditAccountForm .form-row > label,
.tdb-bo-endpoint .woocommerce-address-fields .form-row > label {
    display: block;
    margin: 0 0 10px;
    font-family: var( --font-body );
    font-size: var( --text-card-desc-size );
    line-height: var( --text-card-desc-lh );
    letter-spacing: var( --tracking-tight );
    font-weight: var( --weight-light );
    color: var( --color-text );
}

/* Champ requis : même astérisque orange que `.acf-required`. WooCommerce le
   pose tantôt en `<span class="required">` (compte), tantôt en
   `<abbr class="required" title="obligatoire">` (adresses) — que les
   navigateurs soulignent en pointillé et affichent en rouge. */
.tdb-bo-endpoint .woocommerce-EditAccountForm .required,
.tdb-bo-endpoint .woocommerce-address-fields .required {
    color: var( --color-primary );
    border: 0;
    text-decoration: none;
}

/* Texte d'explication sous un champ (« Ceci sera le nom affiché… ») : même
   traitement que `.acf-label p.description`. */
.tdb-bo-endpoint .woocommerce-EditAccountForm .form-row > span:not( .woocommerce-input-wrapper ),
.tdb-bo-endpoint .woocommerce-address-fields .form-row > span:not( .woocommerce-input-wrapper ) {
    display: block;
    margin: 4px 0 0;
    font-size: var( --text-card-desc-size );
    font-weight: var( --weight-light );
    font-style: normal;
    color: var( --color-text-muted );
}

/* Le gabarit des adresses enveloppe chaque champ dans un <span> ; en `inline`
   par défaut, il empêchait le champ de prendre la largeur de la rangée. */
.tdb-bo-endpoint .woocommerce-input-wrapper {
    display: block;
    width: 100%;
}

/* Champs. Le `width: 100%` est ce qui manquait le plus : sans lui, un
   <input> prend sa taille par défaut (~170px) et la rangée paraissait vide aux
   trois quarts. `password` et `tel` ne figuraient dans AUCUNE règle du thème —
   ce sont pourtant les trois champs de mot de passe du compte et le téléphone
   des adresses. */
.tdb-bo-endpoint .woocommerce-EditAccountForm input.input-text,
.tdb-bo-endpoint .woocommerce-EditAccountForm select,
.tdb-bo-endpoint .woocommerce-EditAccountForm textarea,
.tdb-bo-endpoint .woocommerce-address-fields input.input-text,
.tdb-bo-endpoint .woocommerce-address-fields select,
.tdb-bo-endpoint .woocommerce-address-fields textarea {
    width: 100%;
    height: 60px;
    padding-inline: var( --space-md );
    background: #fff;
    border: 1px solid var( --color-text-muted );
    border-radius: var( --radius-sm );
    font-family: var( --font-body );
    font-size: var( --text-card-desc-size );
    font-weight: var( --weight-light );
    color: var( --color-text );
    box-sizing: border-box;
    transition: border-color var( --duration-tdb-snap ) var( --ease-tdb );
}

.tdb-bo-endpoint .woocommerce-EditAccountForm textarea,
.tdb-bo-endpoint .woocommerce-address-fields textarea {
    height: auto;
    min-height: 140px;
    padding-block: var( --space-sm );
    resize: vertical;
}

.tdb-bo-endpoint .woocommerce-EditAccountForm input.input-text:focus,
.tdb-bo-endpoint .woocommerce-EditAccountForm select:focus,
.tdb-bo-endpoint .woocommerce-EditAccountForm textarea:focus,
.tdb-bo-endpoint .woocommerce-address-fields input.input-text:focus,
.tdb-bo-endpoint .woocommerce-address-fields select:focus,
.tdb-bo-endpoint .woocommerce-address-fields textarea:focus {
    outline: none;
    border-color: var( --color-primary );
}

/* « Changement de mot de passe » : WooCommerce le pose en <fieldset><legend>,
   dont le cadre gravé et le libellé incrusté du navigateur n'ont rien à voir
   avec le reste. Le <legend> devient un titre de section, comme le
   `.tdb-compte-form__section h2` de « Mon compte ». */
.tdb-bo-endpoint .woocommerce-EditAccountForm fieldset {
    padding: 0;
    margin: var( --space-lg ) 0 0;
    border: 0;
}

.tdb-bo-endpoint .woocommerce-EditAccountForm legend {
    display: block;
    width: 100%;
    padding: 0;
    margin: 0 0 16px;
    font-size: 18px;
    font-weight: var( --weight-medium );
    color: var( --color-text );
}

/* Pays et canton passent par Select2, qui remplace le <select> par sa propre
   structure : la règle ci-dessus ne l'atteint pas, le champ restait à la
   hauteur et au filet de Select2 au milieu de champs de 60px.
   La portée s'arrête à l'onglet : la liste déroulante de Select2 est, elle,
   greffée sur <body>, hors de cette portée — elle garde son apparence propre,
   qui ne jure pas avec la charte. */
.tdb-bo-endpoint .select2-container .select2-selection--single {
    height: 60px;
    background: #fff;
    border: 1px solid var( --color-text-muted );
    border-radius: var( --radius-sm );
}

.tdb-bo-endpoint .select2-container .select2-selection--single .select2-selection__rendered {
    padding-inline: var( --space-md );
    line-height: 58px;
    font-family: var( --font-body );
    font-size: var( --text-card-desc-size );
    font-weight: var( --weight-light );
    color: var( --color-text );
}

.tdb-bo-endpoint .select2-container .select2-selection--single .select2-selection__arrow {
    height: 58px;
    right: var( --space-sm );
}

/* Le bouton d'envoi est enveloppé dans un <p> nu : sans marge propre, il
   collait au dernier champ. Même écart que `.acf-form-submit`. */
.tdb-bo-endpoint .woocommerce-EditAccountForm > p:last-of-type,
.tdb-bo-endpoint .woocommerce-address-fields > p:last-of-type {
    margin: var( --space-lg ) 0 0;
}

/* ---------------------------------------------------------------------------
   Charpente du compte
   Le shortcode [woocommerce_my_account] enveloppe sa sortie dans
   <div class="woocommerce">. Sans rien, ce conteneur serait l'unique enfant de
   la grille .tdb-bo__layout et toute la page s'écraserait dans la colonne du
   menu. "display: contents" l'efface de la grille pour que le menu et le
   contenu en redeviennent les colonnes.
   Mais WooCommerce insère aussi ses propres éléments dans ce conteneur (bandeau
   de notices, et selon les extensions d'autres blocs) : en placement
   automatique, le premier d'entre eux prend la colonne du menu et décale tout
   d'une case — c'est ce qui mettait le menu en colonne 2 et le contenu à la
   ligne suivante. On place donc EXPLICITEMENT les deux éléments qui comptent,
   ce qui rend la mise en page indépendante de l'ordre et du nombre des
   éléments que WooCommerce ajoute.
   --------------------------------------------------------------------------- */
.tdb-bo__layout > .woocommerce {
    display: contents;
}

.tdb-bo__layout > .woocommerce > .woocommerce-MyAccount-navigation {
    grid-column: 1;
    grid-row: 2;
}

.tdb-bo__layout > .woocommerce > .woocommerce-MyAccount-content {
    grid-column: 2;
    grid-row: 2;
    min-width: 0; /* sans quoi un tableau large étire la colonne */
}

/* Notices (et tout autre bloc ajouté par WooCommerce) : pleine largeur au-dessus. */
.tdb-bo__layout > .woocommerce > .woocommerce-notices-wrapper {
    grid-column: 1 / -1;
    grid-row: 1;
}

@media ( max-width: 1023px ) {
    /* Une seule colonne : on rend la place au flux normal. */
    .tdb-bo__layout > .woocommerce > .woocommerce-MyAccount-navigation,
    .tdb-bo__layout > .woocommerce > .woocommerce-MyAccount-content,
    .tdb-bo__layout > .woocommerce > .woocommerce-notices-wrapper {
        grid-column: auto;
        grid-row: auto;
    }
}


/* ---------------------------------------------------------------------------
   Menu latéral du compte : largeur de colonne, sous-entrées à picto
   Le <nav> est un élément de grille : sans width:100% il se réduisait au plus
   large de ses libellés (96px au lieu des 319px de la colonne), ce qui écrasait
   les pastilles et donnait un menu en escalier.
   --------------------------------------------------------------------------- */
.tdb-bo-sidebar {
    width: 100%;
    box-sizing: border-box;
}

.tdb-bo-sidebar__group {
    width: 100%;
}

/* MOD-IA 2026-09-22 : MD5 — le libelle du groupe n'est plus centre mais
   aligne a gauche (voir la regle de base plus haut dans ce fichier) ; la
   pastille, elle, occupe toujours toute la largeur de la colonne.
   ANCIEN COMMENTAIRE : « Le libellé du groupe reste centré comme dans la
   maquette, mais la pastille occupe toute la largeur de la colonne. » */
.tdb-bo-sidebar__link {
    width: 100%;
    box-sizing: border-box;
}

/* MOD-IA 2026-09-10 : les pastilles de groupe du menu réagissent au survol —
   revue visuelle du 10.09.2026.

   « Mon commerce », « Mes bons », « Mes achats » et « Administration » sont des
   <summary> : on clique dessus pour déplier le groupe. Elles étaient les SEULES
   pastilles du menu à ne donner aucun retour au passage de la souris, et sans
   transition (0s), là où chaque sous-entrée passe du noir au blanc à libellé
   orange en .2s. Le menu réagissait donc sur ses entrées et restait inerte sur
   ses en-têtes, alors que les deux se cliquent.

   Valeurs et rythme repris à l'identique des sous-entrées ci-dessous — c'est le
   même geste, il se voit de la même façon. Le signe +/− suit, puisqu'il est
   tracé en currentColor. */
.tdb-bo-sidebar__group summary.tdb-bo-sidebar__link {
    cursor: pointer;
    transition:
        background-color var( --duration-tdb-snap ) var( --ease-tdb ),
        color var( --duration-tdb-snap ) var( --ease-tdb );
}

.tdb-bo-sidebar__group summary.tdb-bo-sidebar__link:hover,
.tdb-bo-sidebar__group summary.tdb-bo-sidebar__link:focus-visible {
    background: #fff;
    color: var( --color-primary );
}

/* Le signe +/− passe à l'orange AVEC le libellé. Il porte un `color: #fff` en
   dur (« sur la pastille sombre du groupe », plus bas) : sans cette règle il
   restait blanc sur le fond blanc du survol, et l'indicateur disparaissait au
   moment précis où l'on s'apprête à cliquer dessus. C'est le même traitement
   que le picto d'une sous-entrée, qui suit lui aussi la couleur du libellé. */
.tdb-bo-sidebar__group summary.tdb-bo-sidebar__link:hover .tdb-bo-sidebar__chevron,
.tdb-bo-sidebar__group summary.tdb-bo-sidebar__link:focus-visible .tdb-bo-sidebar__chevron {
    color: var( --color-primary );
}

.tdb-bo-sidebar__submenu {
    list-style: none;
    padding: 0;
}

.tdb-bo-sidebar__submenu li {
    margin: 0;
}

/* Sous-entrée : picto à gauche, libellé aligné à gauche — comme les pastilles
   de groupe depuis MD5. */
.tdb-bo-sidebar__submenu li > a {
    display: flex;
    align-items: center;
    gap: 12px;
    /* MOD-IA 2026-09-22 : MD5 — retrait interne porte de 16px a 20px pour que
       les sous-entrees partagent exactement l'axe gauche du titre de groupe,
       qui est lui aussi a 20px. Sans cela le desalignement signale par le
       client se deplacerait au lieu de disparaitre.
       ANCIEN CODE : padding: 12px 16px; */
    padding: 12px 20px;
    border-radius: var( --radius-sm );
    /* Fond ET couleur posés explicitement : les sous-entrées héritaient d'un
       fond sombre tout en gardant un texte sombre — donc noir sur noir. */
    background: var( --color-ink );
    color: #fff;
    text-decoration: none;
    font-size: var( --text-card-desc-size );
    line-height: 1.2;
    transition:
        background-color var( --duration-tdb-snap ) var( --ease-tdb ),
        color var( --duration-tdb-snap ) var( --ease-tdb );
}

/* Le picto suit la couleur du texte (stroke="currentColor"). */
.tdb-bo-sidebar__submenu li > a,
.tdb-bo-sidebar__submenu li > a .tdb-bo-sidebar__picto {
    color: #fff;
}

.tdb-bo-sidebar__submenu li > a:hover,
.tdb-bo-sidebar__submenu li > a:focus-visible,
.tdb-bo-sidebar__submenu li > a:hover .tdb-bo-sidebar__picto,
.tdb-bo-sidebar__submenu li > a:focus-visible .tdb-bo-sidebar__picto {
    color: var( --color-primary );
}

.tdb-bo-sidebar__submenu li > a:hover,
.tdb-bo-sidebar__submenu li > a:focus-visible {
    background: #fff;
}

.tdb-bo-sidebar__submenu li.is-active > a,
.tdb-bo-sidebar__submenu li.is-active > a .tdb-bo-sidebar__picto {
    background: #fff;
    color: var( --color-primary );
    font-weight: var( --weight-medium );
}

.tdb-bo-sidebar__picto {
    flex-shrink: 0;
    display: grid;
    place-content: center;
    width: 22px;
    height: 22px;
    color: currentColor;
}

.tdb-bo-sidebar__picto svg {
    width: 20px;
    height: 20px;
}

.tdb-bo-sidebar__texte {
    min-width: 0;
}


/* ---------------------------------------------------------------------------
   Neutralisation de la mise en page par défaut de WooCommerce
   La feuille de WooCommerce pose sur le compte une mise en page en flottés :
     .woocommerce-MyAccount-navigation { float: left;  width: 30%; }
     .woocommerce-MyAccount-content    { float: right; width: 68%; }
   Ces pourcentages s'appliquent À L'INTÉRIEUR de nos colonnes de grille : le
   menu ne faisait plus que 30% de 319px (96px, d'où les pastilles écrasées et
   les libellés qui débordaient) et le contenu 68% de 1074px (730px). Les
   flottés, eux, sont ignorés sur un élément de grille.
   Sélecteurs à trois classes pour l'emporter sur ceux de WooCommerce quel que
   soit l'ordre de chargement des feuilles.
   --------------------------------------------------------------------------- */
.tdb-bo__layout > .woocommerce > .woocommerce-MyAccount-navigation,
.tdb-bo__layout > .woocommerce > .woocommerce-MyAccount-content,
.tdb-bo__layout > .woocommerce-MyAccount-navigation,
.tdb-bo__layout > .woocommerce-MyAccount-content {
    float: none;
    width: 100%;
    box-sizing: border-box;
}

/* Le menu latéral rendu hors page « Mon compte » (tableau de bord, validation…)
   passe par le même gabarit : il ne doit pas hériter des 30% non plus. */
.tdb-bo__layout .tdb-bo-sidebar {
    float: none;
    width: 100%;
}

/* Un libellé long ne doit jamais déborder de la colonne. */
.tdb-bo-sidebar__submenu li > a {
    overflow-wrap: anywhere;
}


/* Entrées isolées du menu latéral (« Account details » en tête, « Contacter le
   support » en pied) : même pastille que les sous-entrées, sans le retrait ni
   la marge d'un groupe dépliant. */
.tdb-bo-sidebar__submenu--isolee {
    margin-top: 0;
}

.tdb-bo-sidebar__group + .tdb-bo-sidebar__submenu--isolee {
    margin-top: 10px;
}


/* ---------------------------------------------------------------------------
   Indicateur +/− des groupes du menu latéral
   Dessiné en SVG (navigation.php) : la barre verticale disparaît à l'ouverture,
   le « + » devient donc un « − ».
   --------------------------------------------------------------------------- */
.tdb-bo-sidebar__chevron {
    display: grid;
    place-content: center;
    width: 16px;
    height: 16px;
    color: #fff; /* sur la pastille sombre du groupe */
    filter: none; /* annule le filtre prévu pour l'ancienne image */
}

.tdb-bo-sidebar__chevron svg {
    width: 14px;
    height: 14px;
    overflow: visible;
}

/*
 * MOD-IA 2026-09-22 : MD4 — règles devenues sans objet : la barre verticale du
 * « + » n'existe plus dans le balisage (voir navigation.php). Conservées en
 * commentaire au cas où le « + » serait rétabli.
 *
 * ANCIEN CODE :
 * .tdb-bo-sidebar__chevron-vertical {
 *     transform-origin: center;
 *     transition:
 *         opacity var( --duration-tdb-snap ) var( --ease-tdb ),
 *         transform var( --duration-tdb-snap ) var( --ease-tdb );
 * }
 *
 * .tdb-bo-sidebar__group[open] .tdb-bo-sidebar__chevron-vertical {
 *     opacity: 0;
 *     transform: scaleY( 0 );
 * }
 */

/* ---------------------------------------------------------------------------
   Bouton « Retour » de PassVal
   add_return_to_account_btn() écrit en dur <a href="/compte">Retour</a> en tête
   de chaque onglet. Il fait doublon avec le menu latéral, et son lien pointe
   sur le slug de production (/compte) qui n'existe pas ici. On le masque plutôt
   que de modifier l'extension ; le sélecteur vise précisément ce lien, pas les
   autres boutons des onglets.
   --------------------------------------------------------------------------- */
/* MOD-IA 2026-09-01 : on vise désormais la CLASSE `tdb-retour-compte`, posée
   sur le lien par PassVal, plutôt que son seul href.
   Les sélecteurs d'attribut ci-dessous testent la FIN de l'URL. Or en mobile,
   l'aperçu WPMobile.App réécrit les liens en leur ajoutant une chaîne de
   requête (`…/mon-compte/?wpappninja_cache=friendly&wpappninja=true…`) : le
   `href$="/mon-compte/"` ne correspondait alors plus, et le bouton
   réapparaissait — masqué en desktop, visible en mobile.
   Les anciens sélecteurs sont CONSERVÉS : ils couvrent le lien tel qu'il est
   écrit dans les versions de PassVal qui n'ont pas encore la classe. */
a.button.button-primary.tdb-retour-compte,
.tdb-bo-endpoint a.button.button-primary.tdb-retour-compte,
.tdb-bo-endpoint a.button.button-primary[href="/compte"],
.tdb-bo-endpoint a.button.button-primary[href$="/compte/"],
.tdb-bo-endpoint a.button.button-primary[href$="/mon-compte/"] {
    display: none;
}


/* ---------------------------------------------------------------------------
   Onglets PassVal « Gestion des prestations » et « Bons QR autocollants »
   PassVal y écrit des formulaires bruts (libellés et champs à la suite, sans
   conteneur) : on leur donne la même grammaire que les formulaires du thème —
   bloc blanc à rayon 20px, libellé 14px Light au-dessus, champ de 60px à filet,
   bouton orange — sans toucher à son HTML.
   --------------------------------------------------------------------------- */
.tdb-bo-endpoint h3,
.tdb-bo-endpoint h5 {
    margin: 0 0 var( --space-md );
    color: var( --color-text );
}

.tdb-bo-endpoint h3 {
    font-size: 22px;
}

.tdb-bo-endpoint h5 {
    font-size: var( --text-card-desc-size );
    font-weight: var( --weight-light );
    color: var( --color-text-muted );
}

#prestation-form,
#add-bon-activable-form {
    display: flex;
    flex-direction: column;
    gap: 6px;
    max-width: 640px;
    padding: var( --space-lg );
    background: #fff;
    border: 1px solid var( --color-border );
    border-radius: var( --radius-card );
}

/* Les <div> de regroupement des bons activables deviennent des lignes. */
#add-bon-activable-form > div {
    display: flex;
    flex-direction: column;
    gap: 10px;
    margin-bottom: var( --space-sm );
}

#prestation-form label,
#add-bon-activable-form label {
    display: block;
    margin-top: var( --space-sm );
    font-size: var( --text-card-desc-size );
    line-height: var( --text-card-desc-lh );
    font-weight: var( --weight-light );
    color: var( --color-text );
}

/* Les mentions « (55 caractères max) » suivent le libellé, en gris. */
#prestation-form > span {
    margin-top: -4px;
    font-size: var( --text-caption-size );
    color: var( --color-text-muted );
}

#prestation-form input[type="text"],
#prestation-form input[type="number"],
#prestation-form input[type="date"],
#prestation-form textarea,
#add-bon-activable-form input[type="text"],
#add-bon-activable-form input[type="date"],
#add-bon-activable-form textarea {
    width: 100%;
    box-sizing: border-box;
}

#prestation-form textarea,
#add-bon-activable-form textarea {
    height: auto;
    min-height: 120px;
    padding-block: var( --space-sm );
    resize: vertical;
}

#prestation-form input[type="file"] {
    padding: var( --space-sm ) 0;
    font-size: var( --text-card-desc-size );
}

/* Case « Stock illimité » : même pastille orange que .tdb-checkbox. */
.prestation-stock-ilimite-container .toggle-label {
    display: flex;
    align-items: center;
    gap: 10px;
    margin-top: var( --space-sm );
}

.prestation-stock-ilimite-container input[type="checkbox"] {
    appearance: none;
    -webkit-appearance: none;
    flex-shrink: 0;
    width: 16px;
    height: 16px;
    margin: 0;
    background: #fff;
    border: 1px solid var( --color-primary );
    border-radius: var( --radius-badge );
    cursor: pointer;
    display: grid;
    place-content: center;
}

.prestation-stock-ilimite-container input[type="checkbox"]::before {
    content: "";
    width: 8px;
    height: 8px;
    border-radius: 2px;
    background: var( --color-primary );
    transform: scale( 0 );
    transition: transform var( --duration-tdb-snap ) var( --ease-tdb );
}

.prestation-stock-ilimite-container input[type="checkbox"]:checked::before {
    transform: scale( 1 );
}

/* Aperçu de l'image de la prestation. */
#image-prestation-info-group {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 10px;
    margin-top: var( --space-sm );
}

#image-prestation-preview {
    max-width: 200px;
    height: auto;
    border-radius: var( --radius-sm );
}

#image-prestation-preview[src=""] {
    display: none;
}

/* Boutons de ces formulaires (PassVal les marque .rounded-btn). */
/* MOD-IA 2026-09-08 : même alignement sur .btn--primary que les deux familles
   ci-dessus — libellé noir, bascule sur le noir au survol, durée --duration-tdb
   (normalisation des boutons de « Mon compte », demande du 08.09.2026).
   ANCIEN CODE :
   .tdb-bo-endpoint .rounded-btn {
       ...
       color: #fff;
       transition:
           background-color var( --duration-tdb-snap ) var( --ease-tdb ),
           color var( --duration-tdb-snap ) var( --ease-tdb );
   }
   .tdb-bo-endpoint .rounded-btn:hover {
       background: #fff;
       color: var( --color-primary );
   } */
.tdb-bo-endpoint .rounded-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    height: 60px;
    padding-inline: var( --space-lg );
    background: var( --color-primary );
    border: 1px solid var( --color-primary );
    border-radius: var( --radius-sm );
    color: #000;
    font-family: var( --font-body );
    font-size: var( --text-card-desc-size );
    cursor: pointer;
    transition:
        background-color var( --duration-tdb ) var( --ease-tdb ),
        border-color var( --duration-tdb ) var( --ease-tdb ),
        color var( --duration-tdb ) var( --ease-tdb );
}

/* MOD-IA 2026-09-08 : survol ORANGE -> BLANC — demande client du 08.09.2026
   (« que l'animation du hover soit orange->blanc au lieu de orange->noir »).

   Le filet reste orange (posé dans l'état neutre) : sans lui, un bouton blanc
   sur le fond blanc de l'onglet n'aurait plus de contour au survol. Durée,
   courbe et :focus-visible sont ceux de la normalisation du même jour : c'est
   la COULEUR d'arrivée qui change, pas le rythme.

   ANCIEN CODE (bascule sur le noir, alignée sur .btn--primary) :
   background: var( --color-ink-strong );
   border-color: var( --color-ink-strong );
   color: #fff; */
.tdb-bo-endpoint .rounded-btn:hover,
.tdb-bo-endpoint .rounded-btn:focus-visible {
    background: #fff;
    border-color: var( --color-primary );
    color: var( --color-primary );
}

/* « Supprimer image » est destructif : filet plutôt que aplat orange. */
/* MOD-IA 2026-09-10 : hauteur, filet et graisse alignés sur l'autre bouton
   blanc du même formulaire — revue visuelle du 10.09.2026.

   « Supprimer image » et « Annuler la modification » sont deux boutons
   secondaires blancs du formulaire de prestation, et ils ne se ressemblaient
   pas : 46px contre 60px, filet --color-border (#ECECEC, presque invisible)
   contre --color-text-muted (#7C7C7C), libellé Regular contre Medium. C'est
   « Annuler la modification » qui fait foi : son habillage est celui des
   boutons blancs de tout le back-office.

   Le survol rouge est CONSERVÉ tel quel (règle ci-dessous) : c'est un geste
   destructeur, et rien d'autre dans le compte ne porte cette teinte.
   ANCIEN CODE :
       height: 46px;
       border: 1px solid var( --color-border );
       (aucune graisse déclarée) */
#image-prestation-delete {
    display: inline-flex;
    align-items: center;
    height: 60px;
    padding-inline: var( --space-md );
    background: #fff;
    border: 1px solid var( --color-text-muted );
    border-radius: var( --radius-sm );
    color: var( --color-text );
    font-family: var( --font-body );
    font-size: var( --text-card-desc-size );
    font-weight: var( --weight-medium );
    cursor: pointer;
    /* MOD-IA 2026-09-08 : transition ajoutée en même temps que le survol
       ci-dessous.
       MOD-IA 2026-09-08 : durée portée à --duration-tdb, celle de tous les
       autres boutons de la page depuis la normalisation du 08.09.2026 — ce
       bouton était deux fois plus rapide que celui d'à côté.
       ANCIEN CODE : var( --duration-tdb-snap ) sur les trois propriétés. */
    transition:
        background-color var( --duration-tdb ) var( --ease-tdb ),
        border-color var( --duration-tdb ) var( --ease-tdb ),
        color var( --duration-tdb ) var( --ease-tdb );
}

/* MOD-IA 2026-09-08 : survol de « Supprimer image », absent jusqu'ici — seul
   bouton de l'onglet « Gestion des prestations » à ne donner aucun retour au
   passage de la souris. Le geste étant destructif, le survol vire au rouge de
   la charte (--color-status-expired, celui de la pastille « échu ») plutôt
   qu'à l'orange des actions ordinaires. */
#image-prestation-delete:hover,
#image-prestation-delete:focus-visible {
    border-color: var( --color-status-expired );
    color: var( --color-status-expired );
}

.form-bottom,
.active-carte-group {
    display: flex;
    align-items: center;
    gap: var( --space-md );
    margin-top: var( --space-lg );
}

/* Liste des prestations existantes. */
#prestations-list {
    display: grid;
    grid-template-columns: repeat( auto-fill, minmax( 260px, 1fr ) );
    gap: var( --space-md );
    margin-bottom: var( --space-xl );
}

#prestations-list:empty::after {
    content: "Aucune prestation pour le moment.";
    grid-column: 1 / -1;
    padding: var( --space-lg );
    background: #fff;
    border: 1px solid var( --color-border );
    border-radius: var( --radius-card );
    font-size: var( --text-card-desc-size );
    font-weight: var( --weight-light );
    color: var( --color-text-muted );
}

/* ---------------------------------------------------------------------------
   « Suivi des transactions » : filtres et tableau
   Même grammaire que « Suivi de mes bons » — panneaux blancs à rayon 20px et
   filet #ECECEC, chiffres alignés en tabulaire.
   --------------------------------------------------------------------------- */
.tdb-suivi-filtres {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-end;
    gap: var( --space-md );
    padding: var( --space-lg );
    margin: 0 0 var( --space-md );
    background: #fff;
    border: 1px solid var( --color-border );
    border-radius: var( --radius-card );
}

.tdb-suivi-filtres label {
    display: flex;
    flex-direction: column;
    gap: 10px;
    font-size: var( --text-card-desc-size );
    font-weight: var( --weight-light );
    color: var( --color-text );
}

.tdb-suivi-filtres select,
.tdb-suivi-filtres input[type="search"] {
    height: 60px;
    min-width: 220px;
    padding-inline: var( --space-md );
    background: #fff;
    border: 1px solid var( --color-text-muted );
    border-radius: var( --radius-sm );
    font-family: var( --font-body );
    font-size: var( --text-card-desc-size );
    color: var( --color-text );
}

/* MOD-AI 2026-09-09 : nouvelle grille de filtres du suivi des transactions, construite avec les mêmes panneaux, champs, rayons et couleurs que le back-office existant. */
.tdb-suivi-filtres--transactions {
    display: grid;
    grid-template-columns: repeat( 6, minmax( 0, 1fr ) );
    align-items: end;
    gap: var( --space-sm );
}

.tdb-suivi-filtres__entete {
    display: flex;
    grid-column: 1 / -1;
    align-items: flex-start;
    justify-content: space-between;
    gap: var( --space-md );
    margin-bottom: var( --space-xs );
}

.tdb-suivi-filtres__titre,
.tdb-suivi-filtres__aide {
    margin: 0;
}

.tdb-suivi-filtres__titre {
    font-family: var( --font-heading );
    font-size: 18px;
    font-weight: var( --weight-semibold );
    color: var( --color-text );
}

.tdb-suivi-filtres__aide {
    margin-top: 4px;
    font-size: var( --text-caption-size );
    line-height: var( --text-caption-lh );
    color: var( --color-text-muted );
}

.tdb-suivi-filtres__compteur {
    flex: 0 0 auto;
    padding: 5px var( --space-sm );
    border-radius: var( --radius-badge );
    background: color-mix( in srgb, var( --color-primary ) 18%, #fff );
    font-size: var( --text-caption-size );
    font-weight: var( --weight-medium );
    color: var( --color-ink );
}

.tdb-suivi-filtres--transactions .tdb-suivi-filtres__champ {
    min-width: 0;
}

.tdb-suivi-filtres--transactions .tdb-suivi-filtres__champ--recherche {
    grid-column: span 2;
}

.tdb-suivi-filtres--transactions select,
.tdb-suivi-filtres--transactions input[type="search"],
.tdb-suivi-filtres--transactions input[type="number"] {
    width: 100%;
    min-width: 0;
    height: 52px;
    box-sizing: border-box;
    padding-inline: var( --space-sm );
    background: #fff;
    border: 1px solid var( --color-border );
    border-radius: var( --radius-sm );
    font-family: var( --font-body );
    font-size: var( --text-card-desc-size );
    color: var( --color-text );
}

.tdb-suivi-filtres--transactions select:focus,
.tdb-suivi-filtres--transactions input:focus {
    border-color: var( --color-primary );
    outline: 2px solid color-mix( in srgb, var( --color-primary ) 28%, transparent );
    outline-offset: 1px;
}

.tdb-suivi-filtres__actions {
    display: flex;
    grid-column: 1 / -1;
    flex-wrap: wrap;
    align-items: center;
    gap: var( --space-sm );
    margin-top: var( --space-xs );
}

.tdb-suivi-filtres__actions .btn {
    min-height: 52px;
}

.tdb-suivi-filtres__reinitialiser {
    display: inline-flex;
    align-items: center;
    min-height: 52px;
    padding: 0 var( --space-md );
    border: 1px solid var( --color-border );
    border-radius: var( --radius-sm );
    background: #fff;
    font-family: var( --font-heading );
    font-weight: var( --weight-medium );
    color: var( --color-text );
    text-decoration: none;
}

.tdb-suivi-filtres__reinitialiser:hover,
.tdb-suivi-filtres__reinitialiser:focus-visible {
    border-color: var( --color-primary );
    color: var( --color-primary );
}

@media ( max-width: 1023px ) {
    .tdb-suivi-filtres--transactions {
        grid-template-columns: repeat( 2, minmax( 0, 1fr ) );
    }

    .tdb-suivi-filtres--transactions .tdb-suivi-filtres__champ--recherche {
        grid-column: 1 / -1;
    }
}

@media ( max-width: 599px ) {
    .tdb-suivi-filtres--transactions {
        grid-template-columns: minmax( 0, 1fr );
        padding: var( --space-md );
    }

    .tdb-suivi-filtres__entete {
        align-items: flex-start;
        flex-direction: column;
    }

    .tdb-suivi-filtres--transactions .tdb-suivi-filtres__champ--recherche {
        grid-column: auto;
    }

    /* MOD-IA 2026-09-21 : G2 — note, pas de changement. Autre pleine largeur
       VOULUE, conservée telle quelle : la règle couvre d'un seul tenant le
       conteneur, le bouton et le lien « Réinitialiser » (qui n'est pas un
       .btn), ce qu'une classe posée sur le seul bouton ne ferait pas. Sa
       spécificité passe devant `width: fit-content` de .btn, et le
       `justify-content: center` juste en dessous garde le contenu centré,
       comme .btn--pleine-largeur. */
    .tdb-suivi-filtres__actions,
    .tdb-suivi-filtres__actions .btn,
    .tdb-suivi-filtres__reinitialiser {
        width: 100%;
    }

    .tdb-suivi-filtres__actions .btn,
    .tdb-suivi-filtres__reinitialiser {
        justify-content: center;
    }
}

/* MOD-IA 2026-09-02 : .tdb-table et son enveloppe .tdb-table-scroll déplacé tel quel vers
   assets/css/ui/05-retours.css (aucune valeur changée) — famille « Retours et données »
   de la charte graphique. */


/* ---------------------------------------------------------------------------
   Onglet « Gestion des promotions »
   MOD-IA 2026-09-07 : bloc entièrement réécrit — l'écran est refait
   visuellement.

   Il ne s'agit plus de « neutraliser » PassVal : l'extension a été reprise le
   même jour (tdb_gestion_promotion(), passval.php) et ne pose plus aucun
   attribut style=, plus aucun bloc <style> injecté au milieu du HTML ; sa
   structure est désormais explicite — un en-tête, une section par famille de
   bons, un panneau blanc, une réduction générale, une bascule, une grille de
   cartes. Tous les !important de l'ancien bloc, qui n'existaient que pour
   l'emporter sur ces attributs style=, disparaissent donc.

   ANCIEN CODE (ancien bloc conservé pour mémoire) :

   #custom-acf-field-reduction-valeur,
   #custom-acf-field-reduction-prestation,
   .tdb-bo-endpoint input.reduction-select,
   .tdb-bo-endpoint input.fin-reduction-select,
   #date-fin-reduction-valeur,
   #date-fin-reduction-prestation {
       width: 100% !important;
       max-width: 220px !important;
       height: 60px !important;
       margin-left: 0 !important;
       padding: 0 var( --space-md ) !important;
       background: #fff !important;
       border: 1px solid var( --color-text-muted ) !important;
       border-radius: var( --radius-sm ) !important;
       font-family: var( --font-body ) !important;
       font-size: var( --text-card-desc-size ) !important;
       font-weight: var( --weight-light ) !important;
       color: var( --color-text ) !important;
       box-sizing: border-box !important;
   }
   .tdb-bo-endpoint .reduction-select-group-div,
   .tdb-bo-endpoint form.fake-form {
       display: flex !important;
       flex-direction: column !important;
       align-items: flex-start !important;
       gap: var( --space-sm ) !important;
       margin-left: 0 !important;
       width: 100% !important;
   }
   .tdb-bo-endpoint .prestation-container-reduc {
       margin-bottom: var( --space-lg ) !important;
       padding: var( --space-lg ) !important;
       background: #fff !important;
       border: 1px solid var( --color-border ) !important;
       border-radius: var( --radius-card ) !important;
   }
   .tdb-bo-endpoint .prestation-name {
       height: auto !important;
       margin: 0 0 var( --space-sm ) !important;
       font-size: 18px !important;
       color: var( --color-text ) !important;
   }
   .tdb-bo-endpoint .reduction-select-group-div span,
   .tdb-bo-endpoint form.fake-form span {
       margin-top: 0 !important;
       font-size: var( --text-card-desc-size ) !important;
       font-weight: var( --weight-light ) !important;
       color: var( --color-text ) !important;
   }
   .tdb-bo-endpoint form.fake-form p {
       width: 100% !important;
       margin: 0 !important;
   }
   --------------------------------------------------------------------------- */
.tdb-promo {
    display: flex;
    flex-direction: column;
    gap: var( --space-xl );
    max-width: 900px;
}

.tdb-promo__entete {
    display: flex;
    flex-direction: column;
    gap: var( --space-xs );
}

/* Le titre garde son identifiant (#gestion-reduction-h3) : PassVal y accroche
   le bandeau « Publication mise à jour ». */
.tdb-promo__entete h3 {
    margin: 0;
}

.tdb-promo__chapo {
    max-width: 62ch;
    margin: 0;
    font-size: var( --text-card-desc-size );
    line-height: var( --text-card-desc-lh );
    font-weight: var( --weight-light );
    color: var( --color-text-muted );
}

/* ---------- Une section par famille de bons ---------- */
.tdb-promo__section {
    display: flex;
    flex-direction: column;
    gap: var( --space-sm );
}

/* Intitulé de famille : petite capitale orange, comme les chapeaux de section
   du back-office. */
.tdb-promo__titre {
    margin: 0;
    font-family: var( --font-heading );
    font-size: var( --text-h5-size );
    line-height: var( --text-h5-lh );
    font-weight: var( --weight-semibold );
    letter-spacing: .08em;
    text-transform: uppercase;
    color: var( --color-primary );
}

.tdb-promo__panneau {
    display: flex;
    flex-direction: column;
    gap: var( --space-lg );
    padding: var( --space-lg );
    background: #fff;
    border: 1px solid var( --color-border );
    border-radius: var( --radius-card );
}

/* Réduction générale + date de fin : deux champs sur une ligne, séparés du
   reste du panneau par un filet. */
.tdb-promo__generale {
    display: flex;
    flex-wrap: wrap;
    gap: var( --space-md ) var( --space-lg );
    padding-bottom: var( --space-lg );
    border-bottom: 1px solid var( --color-border );
}

/* ---------- Champ : libellé au-dessus, saisie en dessous ---------- */
.tdb-promo__champ {
    display: flex;
    flex: 1 1 200px;
    flex-direction: column;
    gap: 10px;
    min-width: 0;
}

.tdb-promo__champ label {
    font-size: var( --text-card-desc-size );
    line-height: var( --text-card-desc-lh );
    font-weight: var( --weight-light );
    color: var( --color-text );
}

/* MOD-IA 2026-09-10 : hauteur ramenée de 52px à 60px — revue visuelle du
   10.09.2026. 60px est la hauteur du champ de la charte (.tdb-champ__input,
   assets/css/ui/02-formulaires.css) et celle de TOUS les autres champs du
   compte : formulaires ACF (fiche, coordonnées bancaires, option bons valeurs,
   modèle PDF), génération de bons, bons activables, prestations, détails du
   compte. Cet onglet était le seul à en poser deux autres — 52px ici et 46px
   dans les cartes ci-dessous —, ce qui se voyait d'un onglet à l'autre.
   ANCIEN CODE : height: 52px; */
.tdb-promo__champ input[type="number"],
.tdb-promo__champ input[type="date"] {
    width: 100%;
    max-width: 220px;
    height: 60px;
    padding: 0 var( --space-md );
    box-sizing: border-box;
    background: #fff;
    border: 1px solid var( --color-text-muted );
    border-radius: var( --radius-sm );
    font-family: var( --font-body );
    font-size: var( --text-card-desc-size );
    font-weight: var( --weight-light );
    color: var( --color-text );
}

.tdb-promo__champ input[type="number"]:focus,
.tdb-promo__champ input[type="date"]:focus {
    outline: none;
    border-color: var( --color-primary );
    box-shadow: 0 0 0 3px rgba( 252, 151, 40, .18 );
}

/* ---------- Bascule « réduction par montant / par prestation » ---------- */
/* Le balisage reste celui d'un champ ACF true_false (PassVal le produit ainsi,
   et son script lit la case par son identifiant) : seul l'habillage change. */
.tdb-promo__bascule {
    margin: 0;
}

.tdb-promo__bascule .acf-label,
.tdb-promo__bascule br {
    display: none;
}

.tdb-promo__switch {
    display: inline-flex;
    align-items: center;
    gap: var( --space-sm );
    margin: 0;
    cursor: pointer;
}

/* La case reste dans le flux (lecteurs d'écran, navigation clavier) mais
   invisible : c'est la piste qui la représente. */
.tdb-promo__switch input[type="checkbox"] {
    position: absolute;
    width: 1px;
    height: 1px;
    margin: -1px;
    padding: 0;
    overflow: hidden;
    clip: rect( 0 0 0 0 );
    white-space: nowrap;
    border: 0;
}

.tdb-promo__switch-piste {
    position: relative;
    flex-shrink: 0;
    width: 44px;
    height: 24px;
    background: #DEDEDE;
    border-radius: var( --radius-pill );
    transition: background-color var( --duration-tdb-snap ) var( --ease-tdb );
}

.tdb-promo__switch-piste::after {
    content: "";
    position: absolute;
    top: 3px;
    left: 3px;
    width: 18px;
    height: 18px;
    background: #fff;
    border-radius: 50%;
    box-shadow: 0 1px 3px rgba( 33, 33, 33, .3 );
    transition: transform var( --duration-tdb-snap ) var( --ease-tdb );
}

.tdb-promo__switch input[type="checkbox"]:checked + .tdb-promo__switch-piste {
    background: var( --color-primary );
}

.tdb-promo__switch input[type="checkbox"]:checked + .tdb-promo__switch-piste::after {
    transform: translateX( 20px );
}

.tdb-promo__switch input[type="checkbox"]:focus-visible + .tdb-promo__switch-piste {
    outline: 2px solid var( --color-primary );
    outline-offset: 2px;
}

.tdb-promo__switch-libelle {
    font-size: var( --text-card-desc-size );
    line-height: var( --text-card-desc-lh );
    color: var( --color-text );
}

/* ---------- Grilles de cartes (par montant, par prestation) ---------- */
/* Remplace le « justify-content: space-evenly » de PassVal et son découpage
   manuel en rangées de quatre : les cartes gardent la même largeur quel que
   soit leur nombre. */
.tdb-promo__grille {
    display: grid;
    grid-template-columns: repeat( auto-fill, minmax( 220px, 1fr ) );
    gap: var( --space-md );
}

.tdb-promo__carte {
    display: flex;
    flex-direction: column;
    gap: var( --space-sm );
    padding: var( --space-md );
    background: var( --color-surface-muted );
    border: 1px solid var( --color-border );
    border-radius: var( --radius-sm );
}

.tdb-promo__carte-titre {
    margin: 0;
    font-family: var( --font-heading );
    font-size: var( --text-h3-size );
    line-height: var( --text-h3-lh );
    font-weight: var( --weight-semibold );
    letter-spacing: var( --tracking-tight );
    color: var( --color-text );
}

.tdb-promo__carte-meta {
    margin: 0;
    font-size: var( --text-caption-size );
    line-height: var( --text-caption-lh );
    color: var( --color-text-muted );
}

.tdb-promo__carte-meta--alerte {
    color: var( --color-status-expired-text );
}

/* Prestation retirée de la vente : la carte reste réglable, mais s'efface. */
.tdb-promo__carte--inactive {
    border-style: dashed;
    opacity: .65;
}

/* Dans une carte, les deux champs sont l'un sous l'autre et prennent toute la
   largeur : la carte est déjà étroite. */
.tdb-promo__carte .tdb-promo__champ {
    flex: 0 0 auto;
}

/* MOD-IA 2026-09-10 : la carte ne rétrécit plus ses champs — revue visuelle du
   10.09.2026. Un champ de 46px dans la carte et de 52px juste au-dessus, dans
   la réduction générale du même écran, faisaient trois hauteurs de champ pour
   un seul onglet. Les deux reprennent les 60px de la charte : la carte grandit
   de 28px, ce que la grille absorbe.
   ANCIEN CODE :
   .tdb-promo__carte .tdb-promo__champ input[type="number"],
   .tdb-promo__carte .tdb-promo__champ input[type="date"] {
       max-width: none;
       height: 46px;
   } */
.tdb-promo__carte .tdb-promo__champ input[type="number"],
.tdb-promo__carte .tdb-promo__champ input[type="date"] {
    max-width: none;
}

/* MOD-IA 2026-09-08 : règle devenue sans objet — PassVal n'enveloppe plus les
   deux champs d'une prestation dans un .prestation-reduc-page-field-group, ils
   sont maintenant des enfants directs de la carte, comme dans l'encart d'un
   bon valeur (voir tdb_gestion_promotion(), passval.php). Conservée en
   commentaire au cas où une autre vue de l'extension produirait encore ce
   conteneur.
   ANCIEN CODE :
   .tdb-promo__carte .prestation-reduc-page-field-group {
       display: flex;
       flex-direction: column;
       gap: var( --space-sm );
   }
*/

.tdb-promo__vide {
    grid-column: 1 / -1;
    margin: 0;
    padding: var( --space-lg );
    background: var( --color-surface-muted );
    border-radius: var( --radius-sm );
    font-size: var( --text-card-desc-size );
    font-weight: var( --weight-light );
    color: var( --color-text-muted );
}

/* ---------- Bas de page de l'onglet ---------- */
.tdb-promo__note {
    margin: 0;
    font-size: var( --text-caption-size );
    line-height: var( --text-caption-lh );
    color: var( --color-text-muted );
}

.tdb-promo__actions {
    margin: 0;
}

/* MOD-IA 2026-09-08 : « Mise à jour » de l'onglet « Gestion des promotions »
   s'aligne lui aussi sur .btn--primary — c'était le dernier bouton de « Mon
   compte » à garder l'ancien survol inversé et la durée courte (normalisation
   du 08.09.2026).
   ANCIEN CODE :
   .tdb-bo-endpoint #update-bons-prestation-reduc {
       ...
       color: #fff;
       transition:
           background-color var( --duration-tdb-snap ) var( --ease-tdb ),
           color var( --duration-tdb-snap ) var( --ease-tdb );
   }
   .tdb-bo-endpoint #update-bons-prestation-reduc:hover {
       background: #fff;
       color: var( --color-primary );
   } */
/* MOD-IA 2026-09-10 : « Mise à jour » repris à la mesure des autres boutons du
   compte — revue visuelle du 10.09.2026. Il était le seul à 52px de haut et à
   32px de retrait latéral, quand les boutons d'envoi de tous les autres onglets
   (« Retour », « Mise à jour » des formulaires ACF, « Enregistrer les
   modifications ») font 60px et 24px.
   ANCIEN CODE :
       height: 52px;
       padding-inline: var( --space-xl ); */
.tdb-bo-endpoint #update-bons-prestation-reduc {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    height: 60px;
    padding-inline: var( --space-lg );
    background: var( --color-primary );
    border: 1px solid var( --color-primary );
    border-radius: var( --radius-sm );
    color: #000;
    font-family: var( --font-body );
    font-size: var( --text-card-desc-size );
    font-weight: var( --weight-medium );
    cursor: pointer;
    transition:
        background-color var( --duration-tdb ) var( --ease-tdb ),
        border-color var( --duration-tdb ) var( --ease-tdb ),
        color var( --duration-tdb ) var( --ease-tdb );
}

/* MOD-IA 2026-09-08 : survol ORANGE -> BLANC — demande client du 08.09.2026
   (« que l'animation du hover soit orange->blanc au lieu de orange->noir »).

   Le filet reste orange (posé dans l'état neutre) : sans lui, un bouton blanc
   sur le fond blanc de l'onglet n'aurait plus de contour au survol. Durée,
   courbe et :focus-visible sont ceux de la normalisation du même jour : c'est
   la COULEUR d'arrivée qui change, pas le rythme.

   ANCIEN CODE (bascule sur le noir, alignée sur .btn--primary) :
   background: var( --color-ink-strong );
   border-color: var( --color-ink-strong );
   color: #fff; */
.tdb-bo-endpoint #update-bons-prestation-reduc:hover,
.tdb-bo-endpoint #update-bons-prestation-reduc:focus-visible {
    background: #fff;
    border-color: var( --color-primary );
    color: var( --color-primary );
}

/* Retour d'enregistrement : PassVal écrit .form-result-good / .form-result-bad
   (aplat vert ou rouge de 300px de large, filet de 5px). On lui donne la
   grammaire du bandeau du thème (.tdb-notice) : fond gris box, filet de
   couleur à gauche, texte lisible. */
.tdb-bo-endpoint #result-form {
    width: auto;
    max-width: 520px;
    margin-top: var( --space-md );
    border-radius: var( --radius-sm );
}

.tdb-bo-endpoint #result-form.form-result-good,
.tdb-bo-endpoint #result-form.form-result-bad {
    padding: var( --space-md );
    background: var( --color-surface-muted );
    border: 1px solid var( --color-border );
    border-left: 4px solid var( --color-status-validated );
}

.tdb-bo-endpoint #result-form.form-result-bad {
    border-left-color: var( --color-status-expired );
}

.tdb-bo-endpoint #result-form p {
    margin: 0;
    text-align: left;
    font-size: var( --text-card-desc-size );
    color: var( --color-text );
}

/* Bandeau « Publication mise à jour » inséré par PassVal après le titre. */
#fake-acf-update-message {
    display: inline-block;
    padding: var( --space-xs ) var( --space-md );
    background: var( --color-surface-muted );
    border-left: 4px solid var( --color-status-validated );
    border-radius: var( --radius-sm );
    font-size: var( --text-card-desc-size );
    color: var( --color-text );
}

/* MOD-IA 2026-09-22 : MC3 — « dans les réductions : le champ de date est plus
   long que le bloc dessous ».

   La levée du `max-width: 220px` existait déjà, mais sous un point de bascule
   de 600px, alors que TOUT le reste du thème bascule à 767px (voir l'en-tête
   de ce fichier : breakpoint unique déduit des frames Figma). Entre 601px et
   767px, les blocs passaient donc en pleine largeur pendant que le champ de
   date restait bloqué à 220px — exactement le décalage décrit. Le point de
   bascule de ce bloc est aligné sur celui du thème.

   `max-width: 100%` plutôt que `none` : le champ s'aligne sur la largeur du
   bloc sans jamais pouvoir la dépasser, quelle que soit la largeur
   intrinsèque que le navigateur donne à son sélecteur de date natif — c'est la
   part du symptôme qu'un simple `width: 100%` ne couvre pas. `box-sizing:
   border-box` est déjà posé sur la règle de base.

   ANCIEN CODE : @media ( max-width: 600px ) { … max-width: none; … } */
@media ( max-width: 767px ) {
    .tdb-promo__generale {
        flex-direction: column;
    }
    .tdb-promo__champ{
        flex: 0 0 auto;
    }

    .tdb-promo__champ input[type="number"],
    .tdb-promo__champ input[type="date"] {
        max-width: 100% !important;
    }

    .tdb-promo__grille {
        grid-template-columns: 1fr;
    }
}


/* ---------------------------------------------------------------------------
   MOD-IA 2026-09-07 : cartes de l'onglet « Gestion des prestations »
   La liste #prestations-list est une grille depuis le 02.09.2026, mais ses
   cartes n'avaient aucun habillage : titre, prix et boutons se suivaient à nu
   sur le fond de page. On leur donne la même grammaire que les cartes de
   « Gestion des promotions », et on distingue une prestation retirée de la
   vente (bouton Désactiver / Activer, voir passval/api/toggle-prestation.php).
   --------------------------------------------------------------------------- */
.prestation-card {
    display: flex;
    flex-direction: column;
    gap: var( --space-2xs );
    padding: var( --space-md );
    background: #fff;
    border: 1px solid var( --color-border );
    border-radius: var( --radius-card );
}

.prestation-card--inactive {
    border-style: dashed;
    background: var( --color-surface-muted );
}

/* PassVal produit encore un <h2> et un <br> derrière : on annule leur poids. */
.prestation-card .prestation-name {
    margin: 0;
    font-family: var( --font-heading );
    font-size: var( --text-h3-size );
    line-height: var( --text-h3-lh );
    font-weight: var( --weight-semibold );
    letter-spacing: var( --tracking-tight );
    color: var( --color-text );
}

.prestation-card br {
    display: none;
}

.prestation-card p {
    margin: 0;
    font-size: var( --text-card-desc-size );
    line-height: var( --text-card-desc-lh );
    font-weight: var( --weight-light );
    color: var( --color-text-muted );
}

/* Pastille d'état, reprise des couleurs de statut des bons. */
.prestation-card .prestation-etat {
    align-self: flex-start;
    margin-bottom: var( --space-2xs );
    padding: 2px var( --space-xs );
    border-radius: var( --radius-badge );
    font-size: var( --text-caption-size );
    line-height: var( --text-caption-lh );
    font-weight: var( --weight-medium );
}

.prestation-card .prestation-etat--active {
    background: var( --color-status-validated );
    color: var( --color-ink );
}

.prestation-card .prestation-etat--inactive {
    background: var( --color-status-depleted );
    color: var( --color-ink );
}

.prestation-card .prestations-actions {
    display: flex;
    flex-wrap: wrap;
    gap: var( --space-xs );
    margin-top: var( --space-sm );
}

/* Les boutons de carte sont plus compacts que ceux des formulaires. */
.tdb-bo-endpoint .prestation-card .prestation-action-button.rounded-btn {
    height: 40px;
    padding-inline: var( --space-md );
}

/* « Désactiver » retire de la vente : filet plutôt qu'aplat orange, pour ne
   pas le confondre avec l'action principale « Modifier ». « Activer », lui,
   remet en vente : il garde l'aplat. */
.tdb-bo-endpoint .prestation-card .form-toggle {
    background: #fff;
    border: 1px solid var( --color-text-muted );
    color: var( --color-text );
}

/* MOD-IA 2026-09-08 : :focus-visible ajouté, pour que le clavier obtienne le
   même retour que la souris — c'est désormais la règle sur tous les boutons de
   la page (normalisation du 08.09.2026). Le noir du survol vient du même
   vocabulaire que .btn--primary. */
.tdb-bo-endpoint .prestation-card .form-toggle:hover,
.tdb-bo-endpoint .prestation-card .form-toggle:focus-visible {
    background: var( --color-ink-strong );
    border-color: var( --color-ink-strong );
    color: #fff;
}

/* MOD-IA 2026-09-08 : « Activer » est une action orange : elle suit donc
   .btn--primary comme les autres (libellé noir, bascule sur le noir), au lieu
   de s'inverser en blanc à texte orange.
   ANCIEN CODE :
   ...--reactiver {
       color: #fff;
   }
   ...--reactiver:hover {
       background: #fff;
       color: var( --color-primary );
   } */
.tdb-bo-endpoint .prestation-card .form-toggle.prestation-action-button--reactiver {
    background: var( --color-primary );
    border-color: var( --color-primary );
    color: #000;
}

/* MOD-IA 2026-09-08 : survol ORANGE -> BLANC — demande client du 08.09.2026
   (« que l'animation du hover soit orange->blanc au lieu de orange->noir »).

   Le filet reste orange (posé dans l'état neutre) : sans lui, un bouton blanc
   sur le fond blanc de l'onglet n'aurait plus de contour au survol. Durée,
   courbe et :focus-visible sont ceux de la normalisation du même jour : c'est
   la COULEUR d'arrivée qui change, pas le rythme.

   ANCIEN CODE (bascule sur le noir, alignée sur .btn--primary) :
   background: var( --color-ink-strong );
   border-color: var( --color-ink-strong );
   color: #fff; */
.tdb-bo-endpoint .prestation-card .form-toggle.prestation-action-button--reactiver:hover,
.tdb-bo-endpoint .prestation-card .form-toggle.prestation-action-button--reactiver:focus-visible {
    background: #fff;
    border-color: var( --color-primary );
    color: var( --color-primary );
}

/* « Annuler la modification » du formulaire de prestation : action secondaire. */
.tdb-bo-endpoint #cancel-prestation-btn {
    background: #fff;
    border: 1px solid var( --color-text-muted );
    color: var( --color-text );
}

/* MOD-IA 2026-09-08 : :focus-visible ajouté et noir aligné sur celui des
   autres survols de la page (normalisation du 08.09.2026). */
.tdb-bo-endpoint #cancel-prestation-btn:hover,
.tdb-bo-endpoint #cancel-prestation-btn:focus-visible {
    background: var( --color-ink-strong );
    border-color: var( --color-ink-strong );
    color: #fff;
}

/* MOD-IA 2026-09-07 : « .hide » doit l'emporter sur « .rounded-btn ».
   PassVal masque ses boutons en leur posant la classe .hide
   (global-account.css, display: none). Mais la règle du thème
   « .tdb-bo-endpoint .rounded-btn » est plus spécifique et remet
   display: inline-flex : le bouton « Annuler la modification », rendu masqué
   par défaut, se serait affiché en permanence. */
.tdb-bo-endpoint .rounded-btn.hide {
    display: none;
}

/* ---------------------------------------------------------------------------
   MOD-IA 2026-09-07 : neutralisation des restes de global-account.css
   La feuille de PassVal (global-account.css) est chargée sur toutes les pages
   du compte et contient encore les réglages de l'ancienne mise en page des
   promotions : retrait de 10px sur la bascule, largeur maximale de 200px sur
   les cartes de prestation, colonne centrée en mobile. Ils entrent en conflit
   avec la grille ci-dessus. Le « !important » n'est posé que là où la feuille
   de PassVal en pose un elle-même.
   --------------------------------------------------------------------------- */
#own-valeur-specific,
#own-prestation-specific {
    margin-left: 0;
}

/* MOD-IA 2026-09-10 : rayon des boutons et des champs ramené à 10px dans TOUS
   les onglets du compte — revue visuelle du 10.09.2026, tous rôles et tous
   onglets.

   global-account.css ouvre sur
     « .disabled, .acf-gallery-add, .woocommerce-Button, .rounded-btn
       { border-radius: 3px !important } »
   puis pose le même 3px sur « .button-rounded », « #charge-carte-btn » et
   « #image-prestation-delete ». Ce 3px est un reste de l'ancien habillage : le
   rayon du fichier Figma est 10px (--radius-sm), et c'est ce que portent déjà
   les champs, les panneaux et les boutons « Retour » / « Mise à jour » de tous
   les onglets bâtis sur ACF. Le compte affichait donc DEUX rayons selon la
   balise choisie par PassVal, souvent côte à côte sur le même écran :
     - « Enregistrer les modifications » (.woocommerce-Button, Détails du compte)
     - « Ajouter à la galerie » et le select « Actions de groupe » (.acf-gallery-add)
     - « Ajouter », « Activer ce bon », « Modifier », « Activer »,
       « Désactiver », « Annuler la modification » (.rounded-btn)
     - « Mise à jour » de Gestion des promotions (.button-rounded)
     - « Supprimer image » (#image-prestation-delete)
     - le bouton de charge de carte (#charge-carte-btn)

   Le « !important » n'est posé que parce que la feuille de PassVal en pose un
   elle-même sur les quatre premiers sélecteurs (règle de la section). La portée
   s'arrête à .tdb-bo-endpoint : hors du compte, ces classes ne sont pas les
   nôtres. */
.tdb-bo-endpoint .disabled,
.tdb-bo-endpoint .acf-gallery-add,
.tdb-bo-endpoint .woocommerce-Button,
.tdb-bo-endpoint .rounded-btn,
.tdb-bo-endpoint .button-rounded,
.tdb-bo-endpoint #charge-carte-btn,
.tdb-bo-endpoint #image-prestation-delete {
    border-radius: var( --radius-sm ) !important;
}

/* MOD-IA 2026-09-10 : taille et graisse du libellé des boutons de PassVal.

   « .rounded-btn » n'héritait d'aucune taille du thème : les boutons
   « Ajouter » (Gestion des prestations) et « Activer ce bon » (Bons QR
   autocollants) sortaient en 15px Regular, là où tous les autres boutons du
   compte — « Retour », « Mise à jour », « Enregistrer les modifications » —
   sont en 14px Medium (--text-card-desc-size / --weight-medium, valeur du
   composant .btn de la charte). Deux libellés de tailles différentes pour la
   même action, d'un onglet à l'autre. */
.tdb-bo-endpoint .rounded-btn,
.tdb-bo-endpoint .button-rounded {
    font-size: var( --text-card-desc-size );
    font-weight: var( --weight-medium );
}

/* MOD-IA 2026-09-10 : dans un onglet du compte, les actions s'alignent à gauche
   — revue visuelle du 10.09.2026 sur « Model PDF bons ».

   `.tdb-validation-actions` a été dessiné pour l'écran « Valider un bon », où
   les actions se centrent SOUS UN PANNEAU CENTRÉ (voir la règle d'origine plus
   haut). PassVal réemploie la même classe pour le bouton « Aperçu du PDF » de
   l'onglet « Model PDF bons » (tdb_model_pdf(), passval.php), qui est un écran
   aligné à gauche comme tous les onglets : le bouton s'y retrouvait poussé à
   464px du bord, seul au milieu de la colonne, juste sous un « Mise à jour »
   collé à gauche. Deux actions du même écran, deux alignements.

   La portée est l'onglet : l'écran de validation vit dans .tdb-bo__content et
   non dans .tdb-bo-endpoint, son centrage n'est donc pas touché. */
.tdb-bo-endpoint .tdb-validation-actions {
    justify-content: flex-start;
}

#own-valeur-specific .tdb-promo__switch,
#own-prestation-specific .tdb-promo__switch {
    margin: 0 !important;
    font-weight: var( --weight-regular );
}

.tdb-promo__carte.prestation-container-reduc {
    max-width: none;
    margin: 0;
}

#prestations-list-reduction.tdb-promo__grille {
    align-items: stretch;
}

/* MOD-IA 2026-09-08 : dernier écart entre les encarts « bons valeurs » et les
   encarts « prestations ».

   global-account.css pose, en dessous de 650px,
   « .prestation-container-reduc { margin-left: 0 !important; margin-top: 40px } ».
   Seules les cartes de prestation portent cette classe : en mobile, elles
   s'écartaient donc de 40px les unes des autres alors que celles des bons
   valeurs gardaient l'écart normal de la grille. Le !important d'origine oblige
   à en poser un ici. */
@media ( max-width: 650px ) {
    .tdb-promo__grille .prestation-container-reduc {
        margin-top: 0 !important;
        margin-left: 0 !important;
    }
}


/* ---------------------------------------------------------------------------
   MOD-IA 2026-09-08 : « Bons déjà générés », sous le formulaire de génération
   de bons du compte (onglet PassVal « Génération de bons »).

   Chaque bon était rendu par PassVal comme un pavé orange plein portant tout
   le texte (« PDF du bon (TDB123456 — Massage) »), empilé dans un conteneur
   figé à 25% de la largeur de l'écran, avec des styles écrits en ligne. Le
   numéro du bon — la seule chose qu'on vient y chercher — s'y noyait, et
   l'ensemble ne ressemblait à aucun autre écran du back-office.

   Le balisage produit par PassVal ne fait plus que nommer ses blocs (voir
   PassvalLienPdfBon(), api/commercant-generate-bons.php) ; la mise en forme est
   ici, avec les jetons de la charte : ligne blanche à filet, numéro de bon en
   avant, prestation / montant / date en légende, et un bouton « PDF » qui
   reprend .btn--ghost. Le survol bascule sur le noir de la charte, comme
   .tdb-carousel-nav__btn et .btn--dark.
   --------------------------------------------------------------------------- */
.tdb-bons-generes__titre {
    margin: var( --space-xl ) 0 var( --space-sm );
    font-family: var( --font-heading );
    font-size: var( --text-h5-size );
    line-height: var( --text-h5-lh );
    font-weight: var( --weight-semibold );
    letter-spacing: .08em;
    text-transform: uppercase;
    color: var( --color-primary );
}

.tdb-bons-generes {
    display: flex;
    flex-direction: column;
    gap: var( --space-xs );
    width: 100%;
    max-width: 560px;
}

/* La ligne entière est cliquable : c'est un lien, pas une carte contenant un
   bouton — le « PDF » de droite n'est qu'un repère visuel. */
.tdb-bons-generes__item {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var( --space-md );
    padding: var( --space-sm ) var( --space-md );
    background: #fff;
    border: 1px solid var( --color-border );
    border-radius: var( --radius-sm );
    color: var( --color-text );
    text-decoration: none;
    transition: background-color var( --duration-tdb ) var( --ease-tdb ), border-color var( --duration-tdb ) var( --ease-tdb ), color var( --duration-tdb ) var( --ease-tdb );
}

.tdb-bons-generes__item:hover,
.tdb-bons-generes__item:focus-visible {
    background: var( --color-ink-strong );
    border-color: var( --color-ink-strong );
    color: #fff;
}

.tdb-bons-generes__infos {
    display: flex;
    flex-direction: column;
    gap: 2px;
    min-width: 0;
}

.tdb-bons-generes__code {
    font-family: var( --font-heading );
    font-size: var( --text-card-desc-size );
    line-height: var( --text-card-desc-lh );
    font-weight: var( --weight-semibold );
    letter-spacing: var( --tracking-tight );
}

.tdb-bons-generes__meta {
    overflow: hidden;
    font-size: var( --text-caption-size );
    line-height: var( --text-caption-lh );
    font-weight: var( --weight-light );
    color: var( --color-text-muted );
    text-overflow: ellipsis;
    white-space: nowrap;
}

.tdb-bons-generes__item:hover .tdb-bons-generes__meta,
.tdb-bons-generes__item:focus-visible .tdb-bons-generes__meta {
    color: #fff;
}

/* Même pastille que .btn--ghost, en plus compact : c'est un repère dans une
   ligne, pas un bouton à part entière. */
.tdb-bons-generes__action {
    flex: 0 0 auto;
    padding: 6px var( --space-md );
    background: var( --color-surface-muted );
    border-radius: var( --radius-badge );
    font-family: var( --font-heading );
    font-size: var( --text-button-size-mobile );
    font-weight: var( --weight-medium );
    color: var( --color-ink );
}

.tdb-bons-generes__item:hover .tdb-bons-generes__action,
.tdb-bons-generes__item:focus-visible .tdb-bons-generes__action {
    background: var( --color-primary );
    color: #000;
}

/* MOD-AI 2026-09-09 : neutralisation du comportement visuel de lien sur la ligne complète, maintenant que seul le bouton PDF est interactif et que les informations doivent pouvoir être sélectionnées. */
.tdb-bons-generes__item:hover,
.tdb-bons-generes__item:focus-visible {
    background: var( --color-surface-muted );
    border-color: var( --color-border );
    color: var( --color-text );
}

.tdb-bons-generes__item:hover .tdb-bons-generes__meta,
.tdb-bons-generes__item:focus-visible .tdb-bons-generes__meta {
    color: var( --color-text-muted );
}

.tdb-bons-generes__item:hover .tdb-bons-generes__action,
.tdb-bons-generes__item:focus-visible .tdb-bons-generes__action {
    background: var( --color-surface-muted );
    color: var( --color-ink );
}

/* MOD-AI 2026-09-09 : le repère PDF devient le seul véritable bouton de la ligne, avec des états de survol et de clavier conformes à la charte. */
.tdb-bons-generes__action {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    text-decoration: none;
    cursor: pointer;
    user-select: none;
    transition: background-color var( --duration-tdb ) var( --ease-tdb ), color var( --duration-tdb ) var( --ease-tdb );
}

.tdb-bons-generes__item .tdb-bons-generes__action:hover,
.tdb-bons-generes__item .tdb-bons-generes__action:focus-visible {
    background: var( --color-ink-strong );
    color: #fff;
    outline: 2px solid var( --color-primary );
    outline-offset: 2px;
}

@media ( max-width: 767px ) {
    .tdb-bons-generes {
        max-width: none;
    }
}


/* ---------------------------------------------------------------------------
   MOD-IA 2026-09-08 : PROCESSUS DE VALIDATION D'UN BON — refonte visuelle et
   passage à un écran unique (demande client du 08.09.2026).

   Ce que remplace cet habillage : un champ de saisie posé pleine largeur sur la
   page publique, puis, APRÈS un changement de page, un panneau de résultat,
   puis un troisième aller-retour pour encaisser. Rien n'annonçait qu'il y avait
   trois temps, et les deux écrans ne se ressemblaient pas.

   Ici, l'écran est UN : un panneau blanc à rayon 20px et filet #ECECEC — le
   même vocabulaire que « Suivi de mes bons » — surmonté du fil des trois
   étapes, dans lequel la saisie cède la place au verdict puis à
   l'encaissement, sans que la page bouge. Les couleurs sont celles de la
   charte : orange pour l'étape en cours, noir anthracite pour les étapes
   franchies, gris box pour celles à venir.

   Le balisage vient de PassVal (PassvalFilEtapesValidation(),
   validation_bons_callback(), PassvalPanneauValidation() dans
   valezy_gutenberg_blocks/custom_gutenberg_blocks.php). Les règles vivent ici :
   c'est le thème qui porte la charte, et l'extension reste lisible sans elle.
   --------------------------------------------------------------------------- */
.tdb-validation {
    max-width: 680px;
    padding: var( --space-xl );
    background: #fff;
    border: 1px solid #ECECEC;
    border-radius: var( --radius-card );
}

/* Mention « En tant que validateur » : une précision de contexte, pas un titre. */
.tdb-validation__role {
    margin: 0 0 var( --space-md );
    font-size: var( --text-caption-size );
    font-weight: var( --weight-medium );
    letter-spacing: .08em;
    text-transform: uppercase;
    color: var( --color-primary );
}

/* ---------- Fil des trois étapes ---------- */
.tdb-validation__etapes {
    display: flex;
    align-items: flex-start;
    gap: var( --space-xs );
    margin: 0 0 var( --space-xl );
    padding: 0;
    list-style: none;
}

.tdb-validation__etape {
    position: relative;
    flex: 1 1 0;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 8px;
    text-align: center;
    font-size: var( --text-caption-size );
    line-height: 1.25;
    color: var( --color-text-muted );
    transition: color var( --duration-tdb ) var( --ease-tdb );
}

/* Le trait de liaison relie une étape à la précédente. Il est tracé par
   l'étape de droite, derrière sa pastille, pour rester aligné quelle que soit
   la largeur des libellés. */
.tdb-validation__etape + .tdb-validation__etape::before {
    content: "";
    position: absolute;
    top: 16px;
    right: 50%;
    left: -50%;
    height: 2px;
    background: var( --color-border );
    transition: background-color var( --duration-tdb ) var( --ease-tdb );
}

/* Seule une étape FRANCHIE colore le trait qui la suit. L'étape en cours ne le
   colorait pas non plus jusqu'à ce qu'on la franchisse : à l'ouverture de
   l'écran, le trait entre « Saisir » et « Vérifier » s'affichait déjà en orange
   et donnait l'étape 2 pour acquise. */
.tdb-validation__etape.is-done + .tdb-validation__etape::before {
    background: var( --color-primary );
}

.tdb-validation__etape-rang {
    position: relative;
    z-index: 1;
    display: grid;
    place-content: center;
    width: 34px;
    height: 34px;
    border-radius: 50%;
    background: var( --color-surface-muted );
    color: var( --color-text-muted );
    font-family: var( --font-heading );
    font-weight: var( --weight-semibold );
    transition:
        background-color var( --duration-tdb ) var( --ease-tdb ),
        color var( --duration-tdb ) var( --ease-tdb );
}

.tdb-validation__etape.is-active .tdb-validation__etape-rang {
    background: var( --color-primary );
    color: #000;
}

.tdb-validation__etape.is-done .tdb-validation__etape-rang {
    background: var( --color-ink );
    color: #fff;
}

.tdb-validation__etape.is-active,
.tdb-validation__etape.is-done {
    color: var( --color-ink );
    font-weight: var( --weight-medium );
}

/* ---------- Saisie du numéro ---------- */
.tdb-validation__label {
    display: block;
    margin-bottom: 10px;
    font-size: var( --text-caption-size );
    font-weight: var( --weight-light );
    color: var( --color-text );
}

/* Le champ et son bouton sur une seule ligne : c'est un geste unique. Sous
   560px la ligne se replie, le champ restant en premier. */
.tdb-validation__champ {
    display: flex;
    flex-wrap: wrap;
    gap: var( --space-sm );
}

.tdb-validation__input {
    flex: 1 1 220px;
    min-width: 0;
    height: 60px;
    padding-inline: var( --space-md );
    background: #fff;
    border: 1px solid var( --color-text-muted );
    border-radius: var( --radius-sm );
    font-family: var( --font-heading );
    font-size: 18px;
    font-weight: var( --weight-medium );
    /* Un numéro de bon se lit caractère par caractère au comptoir : l'écart
       entre les lettres et les chiffres à chasse fixe évitent de confondre
       0 et O. */
    letter-spacing: .08em;
    font-variant-numeric: tabular-nums;
    text-transform: uppercase;
    color: var( --color-text );
    transition: border-color var( --duration-tdb-snap ) var( --ease-tdb );
}

.tdb-validation__input::placeholder {
    font-weight: var( --weight-light );
    letter-spacing: normal;
    text-transform: none;
    color: var( --color-text-muted );
}

.tdb-validation__input:focus {
    outline: none;
    border-color: var( --color-primary );
}

.tdb-validation__verifier {
    flex: 0 0 auto;
    height: 60px;
    /* MOD-IA 2026-09-22 : libellé « Vérifier » centré. .btn aligne son contenu
       à gauche (justify-content: flex-start, ui/01-boutons.css) : invisible à
       sa largeur naturelle, mais dès que le bouton s'élargit (pleine largeur
       sous 768px, ou ligne repliée avec le bouton « Scanner »), le texte
       partait sur la gauche. */
    justify-content: center;
}

/* MOD-IA 2026-09-22 : bouton « Scanner » (app WPMobile.App seulement) qui
   ouvre la caméra pour lire le QR code du bon. Même hauteur que « Vérifier »,
   pictogramme et libellé côte à côte. */
.tdb-validation__scanner {
    flex: 0 0 auto;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var( --space-xs, 6px );
    height: 60px;
}

.tdb-validation__scanner-icone {
    flex: 0 0 auto;
}

.tdb-validation__aide {
    margin: var( --space-sm ) 0 0;
    font-size: var( --text-caption-size );
    font-weight: var( --weight-light );
    color: var( --color-text-muted );
}

/* ---------- Panneau de résultat ---------- */
.tdb-validation__panneau {
    margin-top: var( --space-lg );
}

/* Vide, il ne doit occuper aucune place : sans cette règle, sa marge creusait
   un blanc sous le formulaire avant toute vérification. */
.tdb-validation__panneau:empty {
    display: none;
    margin-top: 0;
}

/* MOD-IA 2026-09-08 : le panneau GARDE désormais son fond et son filet dans le
   cadre blanc de l'écran — demande client du 08.09.2026 sur la visibilité de
   l'état.

   La règle précédente les retirait pour ne pas faire « une boîte dans une
   boîte ». C'était juste tant que le panneau était blanc comme son cadre : il
   n'apportait alors qu'un second filet. Il est maintenant TEINTÉ selon l'état
   (vert pâle / rouge pâle), et c'est précisément cette surface colorée qui
   annonce le verdict avant la lecture. La retirer reviendrait à supprimer le
   signal qu'on cherche à rendre visible.

   ANCIEN CODE :
   .tdb-validation .tdb-validation-resultat {
       padding: 0;
       background: none;
       border: 0;
       border-radius: 0;
   } */
.tdb-validation .tdb-validation-resultat {
    padding: var( --space-lg );
    border-radius: var( --radius-sm );
}

/* Message renvoyé par useBon.php après encaissement : du HTML libre (numéro en
   gras, montant, solde restant), auquel on n'impose que la lecture.
   MOD-IA 2026-09-08 : centré et borné en largeur, comme le reste du panneau
   (`align-self: center` ne servait qu'à la grille qui n'existe plus). */
.tdb-validation-resultat__message {
    max-width: 46ch;
    margin-inline: auto;
    line-height: 1.5;
    color: var( --color-text );
}

.tdb-validation__code {
    margin: var( --space-xs ) 0 0;
    font-size: var( --text-caption-size );
    font-style: italic;
    color: var( --color-text-muted );
}

/* ---------- Attente ---------- */
/* `[hidden]` doit l'emporter sur le `display: flex` ci-dessous : une règle
   d'auteur bat la feuille du navigateur, et le bandeau d'attente restait donc
   affiché en permanence, spinner compris, alors qu'aucun appel n'était en
   cours. */
.tdb-validation__attente[hidden] {
    display: none;
}

.tdb-validation__attente {
    display: flex;
    align-items: center;
    gap: var( --space-sm );
    margin-top: var( --space-md );
    font-size: var( --text-caption-size );
    color: var( --color-text-muted );
}

.tdb-validation__spinner {
    width: 18px;
    height: 18px;
    border: 2px solid var( --color-border );
    border-top-color: var( --color-primary );
    border-radius: 50%;
    animation: tdb-validation-tourne .7s linear infinite;
}

@keyframes tdb-validation-tourne {
    to { transform: rotate( 360deg ); }
}

/* Pendant l'appel, l'écran s'estompe : le commerçant voit qu'il se passe
   quelque chose sans que le contenu disparaisse sous ses yeux. */
.tdb-validation.is-busy .tdb-validation__panneau,
.tdb-validation.is-busy .tdb-validation__saisie {
    opacity: .5;
    pointer-events: none;
    transition: opacity var( --duration-tdb-snap ) var( --ease-tdb );
}

/* Mouvement retiré pour qui le demande ; le retour visuel, lui, reste. */
@media ( prefers-reduced-motion: reduce ) {
    .tdb-validation__spinner {
        animation: none;
    }
}

@media ( max-width: 767px ) {
    .tdb-validation {
        padding: var( --space-lg ) var( --space-md );
    }

    /* Le fil garde ses trois pastilles mais perd ses libellés : à cette largeur
       ils se coupaient en trois lignes et poussaient le formulaire hors de
       l'écran. Le titre de la page dit déjà où l'on se trouve. */
    .tdb-validation__etape-libelle {
        display: none;
    }

    .tdb-validation__verifier {
        width: 100%;
    }

    /* MOD-IA 2026-09-22 : sur mobile, le bouton « Scanner » prend toute la
       largeur comme « Vérifier » : c'est le geste principal dans l'app. */
    .tdb-validation__scanner {
        width: 100%;
    }
}


/* ---------------------------------------------------------------------------
   MOD-IA 2026-09-08 : zones de liste rechargées en AJAX (« Suivi de mes bons »
   et « Suivi des transactions »).

   Le seul habillage nécessaire est celui de l'attente : pendant l'appel, la
   zone s'estompe et cesse de répondre au clic, pour qu'on ne déclenche pas deux
   filtres à la suite sur un contenu qui va être remplacé. Rien d'autre ne
   change : le contenu rendu est exactement celui de la page.
   --------------------------------------------------------------------------- */
.tdb-bo-liste.is-loading {
    opacity: .55;
    pointer-events: none;
    transition: opacity var( --duration-tdb-snap ) var( --ease-tdb );
}


/* ---------------------------------------------------------------------------
   MOD-IA 2026-09-08 : « Vos bons activables », sous le formulaire d'activation
   de l'onglet PassVal « Gestion des bons activables ».

   La liste n'avait aucun habillage : deux paragraphes bruts par bon, dans un
   conteneur figé à 30% de la largeur de l'écran, et aucun repère visuel entre
   un bon déjà activé et un bon encore vierge.

   Elle reprend ici le vocabulaire de « Bons déjà générés » (ligne blanche à
   filet, numéro en avant, légende dessous) et la pastille de statut du suivi
   (.tdb-badge). Le balisage est produit par ShowBonsActivablesValue()
   (wp-content/plugins/passval/passval.php).
   --------------------------------------------------------------------------- */
.tdb-activables {
    max-width: 560px;
    margin-top: var( --space-xl );
}

/* Le conteneur porte encore `.bon-activable-type-show`, que global-account.css
   de PassVal peut viser : on neutralise la largeur figée qu'il imposait. */
.tdb-bo-endpoint .tdb-activables .bon-activable-list-element,
.tdb-activables.bon-activable-type-show {
    width: auto;
}

.tdb-activables__entete {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: var( --space-md );
}

.tdb-activables__entete .tdb-bons-generes__titre {
    margin: 0 0 var( --space-sm );
}

.tdb-activables__resume {
    margin: 0 0 var( --space-sm );
    font-size: var( --text-caption-size );
    font-weight: var( --weight-light );
    color: var( --color-text-muted );
}

.tdb-activables__liste {
    display: flex;
    flex-direction: column;
    gap: var( --space-xs );
    margin: 0;
    padding: 0;
    list-style: none;
}

.tdb-activables__item {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var( --space-md );
    margin: 0;
    padding: var( --space-sm ) var( --space-md );
    background: #fff;
    border: 1px solid var( --color-border );
    border-radius: var( --radius-sm );
}

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

.tdb-activables__code {
    font-family: var( --font-heading );
    font-size: var( --text-card-desc-size );
    line-height: var( --text-card-desc-lh );
    font-weight: var( --weight-semibold );
    letter-spacing: var( --tracking-tight );
}

.tdb-activables__valeur {
    font-size: var( --text-caption-size );
    line-height: var( --text-caption-lh );
    font-weight: var( --weight-light );
    color: var( --color-text-muted );
    font-variant-numeric: tabular-nums;
}

@media ( max-width: 767px ) {
    .tdb-activables {
        max-width: none;
    }
}


/* ---------------------------------------------------------------------------
   MOD-IA 2026-09-08 : « Mes bons » — la liste des bons d'un CLIENT, onglet
   « vouchers » de PassVal (tdb_client_vouchers_list_endpoints()).

   Constaté à l'écran le 08.09.2026, après avoir donné des bons au compte de
   démonstration client.test : la page sortait en texte brut. Un <h2> et des
   <h3> aux tailles par défaut de WordPress, les bons empilés sans séparation ni
   fond, et le lien vers le PDF réduit au mot « PDF » posé sous chaque ligne —
   rien n'indiquait qu'il était cliquable, ni où finissait un bon et où
   commençait le suivant.

   L'habillage est le même que partout ailleurs dans le compte : ligne blanche à
   filet et rayon, information à gauche, action à droite (voir « Bons déjà
   générés » et « Vos bons activables »). Le balisage est celui de PassVal, on
   ne fait que l'habiller — l'extension reste lisible sans cette feuille.
   --------------------------------------------------------------------------- */
/* La taille (22px) vient deja de la regle « .tdb-bo-endpoint > h2 » plus haut,
   commune a tous les titres d'onglet : on ne fait qu'ajouter la fonte de titre
   et la graisse de la charte. */
/* MOD-IA 2026-09-10 : « Mes bons » est un titre de NIVEAU PAGE — revue visuelle
   du 10.09.2026.

   C'est le titre qui ouvre l'onglet des bons d'un client, au même rang que
   « Entreprise - Détails », « Génération de bons » ou « Gestion des
   promotions » chez un commerçant. Ceux-là sont orange et à 24px
   (.tdb-compte-form__section--majeure h2, posé par PassvalEnteteEcranCompte()) ;
   celui-ci restait noir et à 22px, la taille d'un SOUS-titre — le seul onglet à
   annoncer son écran dans une autre couleur que tous les autres.
   ANCIEN CODE :
       margin: 0 0 var( --space-xs );
       color: var( --color-text ); */
.tdb-bo-endpoint .voucher_title {
    margin: 0 0 var( --space-md );
    font-family: var( --font-heading );
    font-size: var( --text-h2-size );
    font-weight: var( --weight-semibold );
    letter-spacing: var( --tracking-tight );
    color: var( --color-primary );
}

/* Intertitre de famille (« chez un commerçant », « dans un canton ») : même
   traitement que « BONS DÉJÀ GÉNÉRÉS », qui joue le même rôle. */
.tdb-bo-endpoint .voucher_type {
    margin: var( --space-xl ) 0 var( --space-sm );
    font-family: var( --font-heading );
    font-size: var( --text-h5-size );
    line-height: var( --text-h5-lh );
    font-weight: var( --weight-semibold );
    letter-spacing: .08em;
    text-transform: uppercase;
    color: var( --color-primary );
}

.tdb-bo-endpoint .vouchers_list {
    display: flex;
    flex-direction: column;
    gap: var( --space-xs );
    max-width: 620px;
}

/* Un bon = une ligne : l'information à gauche, le lien vers le PDF à droite,
   comme dans « Bons déjà générés » et « Vos bons activables ». Le bloc du
   bouton est un ENFANT du bloc de bon (et non son frère) : c'est donc ce
   dernier qui porte la grille à deux colonnes. */
.tdb-bo-endpoint .vouchers_list_item {
    display: grid;
    grid-template-columns: minmax( 0, 1fr ) auto;
    align-items: center;
    gap: var( --space-md );
    padding: var( --space-sm ) var( --space-md );
    background: #fff;
    border: 1px solid var( --color-border );
    border-radius: var( --radius-sm );
}

.tdb-bo-endpoint .vouchers_list_item_button {
    text-align: right;
}

.tdb-bo-endpoint .vouchers_list_item_title {
    display: flex;
    flex-direction: column;
    gap: 2px;
    min-width: 0;
}

/* Première ligne : nom du commerçant en gras, montant, éventuel intitulé de
   prestation. Deuxième ligne : la description, souvent vide. */
.tdb-bo-endpoint .vouchers_list_item_title > span:first-child {
    font-size: var( --text-card-desc-size );
    line-height: var( --text-card-desc-lh );
    color: var( --color-text );
}

.tdb-bo-endpoint .vouchers_list_item_title > span:first-child b {
    font-family: var( --font-heading );
    font-weight: var( --weight-semibold );
}

.tdb-bo-endpoint .vouchers_list_item_title > span + span:empty {
    display: none;
}

.tdb-bo-endpoint .vouchers_list_item_title > span + span {
    font-size: var( --text-caption-size );
    line-height: var( --text-caption-lh );
    font-weight: var( --weight-light );
    color: var( --color-text-muted );
}

/* Le lien vers le PDF prend la pastille compacte de « Bons déjà générés ». */
.tdb-bo-endpoint .vouchers_list .show_vouchers {
    display: inline-flex;
    align-items: center;
    padding: 6px var( --space-md );
    background: var( --color-surface-muted );
    border-radius: var( --radius-badge );
    font-family: var( --font-heading );
    font-size: var( --text-button-size-mobile );
    font-weight: var( --weight-medium );
    color: var( --color-ink );
    text-decoration: none;
    transition:
        background-color var( --duration-tdb ) var( --ease-tdb ),
        color var( --duration-tdb ) var( --ease-tdb );
}

.tdb-bo-endpoint .vouchers_list .show_vouchers:hover,
.tdb-bo-endpoint .vouchers_list .show_vouchers:focus-visible {
    background: var( --color-primary );
    color: #000;
}

@media ( max-width: 767px ) {
    .tdb-bo-endpoint .vouchers_list {
        max-width: none;
    }
}


/* ---------------------------------------------------------------------------
   MOD-IA 2026-09-09 : écrans d'administration du back-office — « Gestion des
   remboursements » (page-gestion-remboursements.php) et « Export des ventes »
   (page-export-ventes.php). Demande client du 09.09.2026.

   Aucune frame Figma ne les couvre : ils reprennent le vocabulaire déjà posé
   par « Suivi des transactions » — panneau de chiffres clés en tête
   (.tdb-suivi-chiffres, réutilisé tel quel) puis tableau du composant
   tdb_ui( 'tableau' ). Il ne reste ici que la mise en page propre aux deux
   écrans.
   --------------------------------------------------------------------------- */

/* Barre d'action au-dessus du tableau des remboursements : bouton à gauche,
   message d'état à sa droite, et le message passe sous le bouton dès que la
   place manque plutôt que de le comprimer. */
.tdb-rmb__actions {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var( --space-md );
    margin: 0 0 var( --space-md );
}

.tdb-rmb__message {
    margin: 0;
    font-size: var( --text-card-desc-size );
    font-weight: var( --weight-light );
    color: var( --color-text-muted );
}

/* Un échec de génération n'est pas une information de plus : il dit que les
   virements n'ont PAS été produits. Il se distingue donc du gris d'attente. */
.tdb-rmb__message--erreur {
    /* --color-status-expired-strong et non --color-status-expired : le rouge
       vif des pastilles ne donne que 3,1:1 sur blanc, insuffisant pour du
       texte. Le jeton « strong » existe précisément pour ce cas (tokens.css). */
    color: var( --color-status-expired-strong );
    font-weight: var( --weight-medium );
}

.tdb-rmb__titre {
    margin: var( --space-xl ) 0 16px;
    font-size: 18px;
    font-weight: var( --weight-medium );
    color: var( --color-text );
}

.tdb-rmb__aide {
    margin: var( --space-sm ) 0 0;
    font-size: var( --text-caption-size );
    font-weight: var( --weight-light );
    color: var( --color-text-muted );
}

.tdb-rmb__aide code {
    padding: 2px 6px;
    background: var( --color-surface-muted );
    border-radius: var( --radius-badge );
    font-size: inherit;
}

/* MOD-AI 2026-09-09 : barre de filtres du tableau des remboursements, alignée sur les champs et espacements existants du back-office. */
.tdb-rmb-filtres {
    display: grid;
    grid-template-columns: minmax( 220px, 2fr ) repeat( 2, minmax( 150px, 1fr ) ) minmax( 120px, auto ) auto;
    align-items: end;
    gap: var( --space-sm );
    margin: var( --space-lg ) 0 var( --space-md );
}

/* MOD-AI 2026-09-09 : maintien du repli progressif en masquant les contrôles tant que le script ne les a pas initialisés. */
.tdb-rmb-filtres[hidden] {
    display: none;
}

.tdb-rmb-filtres__champ {
    display: flex;
    flex-direction: column;
    gap: 6px;
    min-width: 0;
    font-size: var( --text-caption-size );
    color: var( --color-text-muted );
}

.tdb-rmb-filtres__champ input,
.tdb-rmb-filtres__champ select {
    width: 100%;
    height: 46px;
    padding: 0 var( --space-sm );
    border: 1px solid var( --color-border );
    border-radius: var( --radius-sm );
    background: #fff;
    color: var( --color-text );
    font: inherit;
}

.tdb-rmb-filtres__champ input:focus,
.tdb-rmb-filtres__champ select:focus {
    border-color: var( --color-primary );
    outline: 2px solid color-mix( in srgb, var( --color-primary ) 28%, transparent );
    outline-offset: 1px;
}

.tdb-rmb-filtres__reinitialiser,
.tdb-rmb-pagination__bouton {
    min-height: 46px;
    padding: 0 var( --space-md );
    border: 1px solid var( --color-border );
    border-radius: var( --radius-sm );
    background: #fff;
    color: var( --color-text );
    font-family: var( --font-heading );
    font-weight: var( --weight-medium );
    cursor: pointer;
}

/* MOD-AI 2026-09-09 : intégration de la taille de page, de la réinitialisation et du compteur dans la barre de suivi des bons, avec les dimensions des contrôles de « Gestion des commerçants ». */
.tdb-bons-filtres .tdb-rmb-filtres__reinitialiser {
    min-height: 46px;
}

/* MOD-AI 2026-09-09 : le compteur occupe sa propre ligne dans la barre flexible des bons. */
.tdb-bons-filtres .tdb-rmb-filtres__resultats {
    flex: 1 0 100%;
}

/* MOD-AI 2026-09-09 : état visuel non interactif de la réinitialisation lorsqu'aucun filtre n'est actif. */
[data-tdb-liste-reset][aria-disabled="true"] {
    opacity: .5;
}

.tdb-rmb-filtres__reinitialiser:hover,
.tdb-rmb-filtres__reinitialiser:focus-visible,
.tdb-rmb-pagination__bouton:hover,
.tdb-rmb-pagination__bouton:focus-visible {
    border-color: var( --color-primary );
    color: var( --color-primary );
}

.tdb-rmb-filtres__resultats {
    grid-column: 1 / -1;
    margin: 0;
    font-size: var( --text-caption-size );
    color: var( --color-text-muted );
}

/* MOD-AI 2026-09-09 : boutons de tri intégrés aux en-têtes existants sans changer le fond, les bordures ou la typographie du tableau. */
.tdb-rmb-tri {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var( --space-xs );
    width: 100%;
    padding: 0;
    border: 0;
    background: transparent;
    color: inherit;
    font: inherit;
    text-align: left;
    cursor: pointer;
}

.tdb-rmb-tri::after {
    content: "↕";
    color: var( --color-text-muted );
    font-size: 12px;
}

.tdb-rmb__table-interactive th[aria-sort="ascending"] .tdb-rmb-tri::after {
    content: "↑";
    color: var( --color-primary );
}

.tdb-rmb__table-interactive th[aria-sort="descending"] .tdb-rmb-tri::after {
    content: "↓";
    color: var( --color-primary );
}

/* MOD-AI 2026-09-09 : mêmes flèches de tri actif sur les tableaux de suivi, enrichis après chaque réponse AJAX. */
.tdb-suivi__table-interactive th[aria-sort="ascending"] .tdb-rmb-tri::after {
    content: "↑";
    color: var( --color-primary );
}

.tdb-suivi__table-interactive th[aria-sort="descending"] .tdb-rmb-tri::after {
    content: "↓";
    color: var( --color-primary );
}

/* MOD-AI 2026-09-09 : pagination compacte sous le tableau, dans le même langage visuel que les contrôles du back-office. */
.tdb-rmb-pagination {
    display: flex;
    align-items: center;
    justify-content: flex-end;
    gap: var( --space-sm );
    margin-top: var( --space-md );
}

.tdb-rmb-pagination[hidden] {
    display: none;
}

.tdb-rmb-pagination__bouton:disabled {
    opacity: .45;
    cursor: not-allowed;
}

.tdb-rmb-pagination__etat {
    min-width: 110px;
    text-align: center;
    font-size: var( --text-caption-size );
    color: var( --color-text-muted );
}

/* MOD-AI 2026-09-09 : adaptation des filtres sur tablette et mobile sans provoquer de débordement horizontal. */
@media ( max-width: 1023px ) {
    .tdb-rmb-filtres {
        grid-template-columns: repeat( 2, minmax( 0, 1fr ) );
    }

    .tdb-rmb-filtres__champ--recherche {
        grid-column: 1 / -1;
    }
}

@media ( max-width: 599px ) {
    .tdb-rmb-filtres {
        grid-template-columns: 1fr;
    }

    .tdb-rmb-filtres__champ--recherche,
    .tdb-rmb-filtres__resultats {
        grid-column: auto;
    }

    .tdb-rmb-filtres__reinitialiser {
        width: 100%;
    }

    .tdb-rmb-pagination {
        justify-content: space-between;
    }
}

/* ---------------------------------------------------------------------------
   MOD-IA 2026-09-09 : « Gestion des commerçants »
   (page-gestion-des-commercants.php). Demande client du 09.09.2026.

   Troisième écran d'administration, et le seul à avoir DEUX vues : une liste et
   une fiche. La liste n'a besoin de rien — chiffres clés et tableau du composant,
   déjà habillés. Tout ce qui suit ne sert donc qu'à la fiche.
   --------------------------------------------------------------------------- */

/* Barre d'actions de la fiche : retour à gauche, exports à sa suite, et les
   boutons passent à la ligne plutôt que de se comprimer quand la place manque. */
/* MOD-AI 2026-09-09 : adaptation de la grille de filtres partagée au nombre de contrôles propre à la liste des commerçants. */
.tdb-cmc-filtres {
    /* MOD-AI 2026-09-09 : adaptation de la grille de filtres partagée au nombre de contrôles propre à la liste des commerçants. */
    grid-template-columns: minmax( 240px, 2fr ) minmax( 190px, 1fr ) minmax( 120px, auto ) auto;
}

/* MOD-AI 2026-09-09 : reprise des indicateurs de tri du tableau existant pour les colonnes interactives de la liste des commerçants. */
.tdb-cmc__table-interactive th[aria-sort="ascending"] .tdb-rmb-tri::after {
    content: "↑";
    color: var( --color-primary );
}

.tdb-cmc__table-interactive th[aria-sort="descending"] .tdb-rmb-tri::after {
    content: "↓";
    color: var( --color-primary );
}

/* MOD-AI 2026-09-09 : rétablissement explicite des deux puis une colonne après la règle bureau propre aux filtres des commerçants. */
@media ( max-width: 1023px ) {
    .tdb-cmc-filtres {
        grid-template-columns: repeat( 2, minmax( 0, 1fr ) );
    }
}

@media ( max-width: 599px ) {
    .tdb-cmc-filtres {
        grid-template-columns: minmax( 0, 1fr );
    }
}

/* MOD-AI 2026-09-09 : maintien du commentaire historique au contact de la barre d'actions après l'insertion des styles de la liste. */
/* Barre d'actions de la fiche : retour à gauche, exports à sa suite, et les
   boutons passent à la ligne plutôt que de se comprimer quand la place manque. */
.tdb-cmc__actions {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var( --space-sm );
    margin: 0 0 var( --space-lg );
}

.tdb-cmc__bloc {
    margin-top: var( --space-xl );
}

/* Le badge de vérification vit DANS le titre : d'où l'alignement en ligne et
   l'écart, sans quoi il se collerait au texte ou décalerait la ligne de base. */
.tdb-cmc__titre {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var( --space-sm );
    margin: 0 0 16px;
    font-size: 18px;
    font-weight: var( --weight-medium );
    color: var( --color-text );
}

/* Le badge « À vérifier » est parfois un lien vers la pièce justificative : il
   garde l'aspect du badge, sans le soulignement ni le bleu du navigateur. */
.tdb-badge--lien {
    text-decoration: none;
    color: var( --color-ink );
}

.tdb-badge--lien:hover,
.tdb-badge--lien:focus-visible {
    text-decoration: underline;
}

/* Coordonnées : deux colonnes sur ordinateur, une seule dès que la place
   manque. Le <dl> est volontaire — ce sont des couples libellé/valeur, et non
   un tableau : il n'y a pas de colonne à comparer d'une ligne à l'autre. */
.tdb-cmc__infos {
    display: grid;
    grid-template-columns: repeat( 2, minmax( 0, 1fr ) );
    gap: var( --space-md );
    margin: 0;
    padding: var( --space-md );
    background: #fff;
    border: 1px solid var( --color-border );
    border-radius: var( --radius-card );
}

@media ( max-width: 767px ) {
    .tdb-cmc__infos {
        grid-template-columns: minmax( 0, 1fr );
    }
}

.tdb-cmc__info dt {
    margin: 0 0 4px;
    font-size: var( --text-caption-size );
    font-weight: var( --weight-medium );
    color: var( --color-text-muted );
}

.tdb-cmc__info dd {
    margin: 0;
    font-size: var( --text-card-desc-size );
    font-weight: var( --weight-light );
    color: var( --color-text );
    /* Un IBAN n'a pas d'espace où revenir à la ligne : sans cela il élargit la
       grille et déborde de la colonne en mobile. */
    overflow-wrap: anywhere;
}

.tdb-cmc__vide {
    color: var( --color-text-muted );
    font-style: italic;
}

.tdb-cmc__aide {
    margin: 0 0 var( --space-sm );
    font-size: var( --text-card-desc-size );
    font-weight: var( --weight-light );
    color: var( --color-text-muted );
}

/* Le formulaire d'export porte .tdb-compte-form : ses <select> et ses <input>
   héritent donc déjà de l'habillage des formulaires du thème (champ de 60px,
   filet, chevron SVG des listes déroulantes). Il ne reste que le libellé, que
   `.tdb-compte-form label:not(.tdb-checkbox)` empile en flex — on ne fait ici
   que régler l'écart et la largeur des colonnes. */
.tdb-export-ventes__champ {
    flex: 1 1 240px;
    min-width: 0;
}

.tdb-export-ventes__envoi {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var( --space-md );
    margin: var( --space-lg ) 0 0;
}

/* La classe `hidden` que bascule le script de PassVal
   (scripts/scripts-add.js:31 et :74) n'était définie NULLE PART — ni dans le
   thème, ni dans l'extension. Le message « Export en cours… » restait donc
   affiché en permanence, avant comme après l'export. On la définit dans la
   portée du formulaire plutôt que globalement : `hidden` est un nom trop
   courant pour en faire une règle de site. */
.tdb-export-ventes .hidden {
    display: none;
}

/* ==========================================================================
   MOD-IA 2026-09-22 : MD9 — unification des menus déroulants.
   Couvre aussi la sous-remarque de MD5 (« menu déroulant en noir au lieu de
   gris ») et MN3 (« alignement des filtres pas propre » en mobile).

   Le retour client est « se rapprocher un peu plus de ce qui a été proposé par
   MOJO (Figma) ». Le thème ne comptait pas UN déroulant mais DEUX composants
   et QUATRE habillages de <select> selon l'écran — c'est cette dispersion que
   le client ressentait :

     1. `.tdb-filtres__select`                  gris #F7F7F7, 46px, chevron image
     2. `.tdb-compte-form select` / `.acf-field select`  blanc + filet, 60px
     3. `.tdb-bo-endpoint select`               blanc + filet, 60px, appearance
                                                NATIVE (flèche du navigateur)
     4. `.tdb-bo-endpoint .acf-input select`    blanc + filet, 60px, 100 %

   La flèche changeait donc d'un onglet à l'autre, et la hauteur d'un écran à
   l'autre. Ce bloc ramène les quatre îlots sur la géométrie relevée dans
   Figma — voir docs/feedback_20260921/00-RELEVE-FIGMA.md §4 :

       300 × 46 · rayon 10 · padding-inline 20 · Medium 14/18 · chevron 12×8

   Les valeurs des îlots d'origine ne sont PAS effacées : elles restent en
   place plus haut dans ce fichier, ce bloc les surcharge en fin de feuille.
   L'ancienne hauteur commune était 60px ; la maquette pose 46px.

   ⚠ POINT À VALIDER AVEC LE CLIENT : les <input> et <textarea> des mêmes
   formulaires restent, eux, à 60px — leur hauteur n'est pas du périmètre de
   MD9. Dans une rangée `.tdb-compte-form__row` mêlant un champ texte et une
   liste déroulante, les deux n'ont donc plus la même hauteur. Le relevé Figma
   de CK3 (§1 du relevé) donne 46px pour les champs COMME pour les déroulants :
   la suite cohérente est de descendre aussi les champs à 46px, mais c'est un
   changement large qui touche tous les formulaires du site et qui doit être
   validé visuellement avant d'être fait.

   Ce qui n'est PAS changé, volontairement : la variante NOIRE relevée dans
   Figma (« BO bouton defilement fleche noir > orange », #212121 / texte blanc)
   n'existe dans la maquette que pour les déroulants de FILTRE du back-office.
   Les champs de formulaire du compte restent sur la variante « filet »
   (blanc + 1px #7C7C7C), et les filtres du front sur la variante grise
   (#F7F7F7 sans filet) — c'est précisément ce que demande MD5.
   ========================================================================== */

/* Chevron commun — même tracé, même taille, même position que celui de
   `.tdb-dropdown__arrow` (template-parts/ui/dropdown.php), pour que les deux
   composants soient indiscernables : l'utilisateur ignore qu'il y a deux
   implémentations, il voit une flèche qui change de place. */
.tdb-filtres__select,
.tdb-compte-form select,
.tdb-bo__content .acf-field select,
.tdb-bo-endpoint select,
.tdb-acf-form .acf-input select,
.tdb-bo-endpoint .acf-input select {
    height: 46px;
    padding-inline: 20px;
    padding-right: 44px; /* 20px de retrait + 12px de chevron + 12px de respiration */
    border-radius: var( --radius-sm );
    font-family: var( --font-body );
    font-size: var( --text-button-size );
    line-height: var( --text-button-lh );
    font-weight: var( --weight-medium );
    letter-spacing: var( --tracking-tight );
    background-image: url( "data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8' fill='none'%3E%3Cpath d='M1 1.5 6 6.5l5-5' stroke='%23000' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E" );
    background-repeat: no-repeat;
    background-position: right 20px center;
    background-size: 12px 8px;
    appearance: none;
    -webkit-appearance: none;
    cursor: pointer;
}

/* Variante « filet » (322:3421) — formulaires du compte et du back-office. */
.tdb-compte-form select,
.tdb-bo__content .acf-field select,
.tdb-bo-endpoint select,
.tdb-acf-form .acf-input select,
.tdb-bo-endpoint .acf-input select {
    background-color: #fff;
    border: 1px solid var( --color-text-muted );
}

/* `.tdb-bo-endpoint select` n'avait AUCUNE largeur déclarée : il retombait sur
   la largeur native du navigateur (~150-200px) à côté de champs ACF étirés à
   100 %. C'est l'îlot qui faisait exception ; il cesse de l'être. */
.tdb-bo-endpoint select {
    width: 100%;
}

/* Variante « grise » (322:3341) — filtres du front ET barre de filtres du
   back-office : fond #F7F7F7, aucun filet, orange plein au survol comme à
   l'ouverture, exactement comme `.tdb-dropdown__trigger`. */
.tdb-filtres__select {
    background-color: var( --color-surface-muted );
    border: none;
}

/* ---------- MN3 : alignement des filtres en mobile ---------- */
/* Les trois filtres de taxonomie sont des `.tdb-dropdown` maison, le bouton
   « Filtres complémentaires » un `<select>` : seule leur HAUTEUR était
   harmonisée en mobile, ni le retrait du libellé ni la flèche ne l'étaient.
   Une fois la géométrie unifiée ci-dessus, il reste à ramener la flèche du
   `<select>` dans la piste plus courte du mobile (37px de haut). */
@media ( max-width: 767px ) {
    .tdb-filtres__select,
    .tdb-dropdown__trigger {
        /* La hauteur mobile de 37px est relevée sur 450:1982 (selects à
           y=163 / 208 / 253 / 298, soit un pas de 45 pour une hauteur de 37).
           Elle est REPOSÉE ici : la règle d'origine vit plus haut dans le
           fichier, et le `height: 46px` du bloc d'unification ci-dessus, plus
           tardif à spécificité égale, l'emporterait sinon. */
        height: 37px;
        padding-inline: 15px;
    }
    .tdb-filtres__select {
        padding-right: 39px; /* 15 + 12 + 12, comme en desktop mais sur 15px */
        background-position: right 15px center;
    }
    .tdb-dropdown__arrow {
        margin-left: var( --space-xs );
    }
}

/* ==========================================================================
   MOD-IA 2026-09-22 : MD10 — largeurs des champs de texte du back-office
   (onglets « Détails » et « Coordonnées bancaires » de /mon-compte/).

   Deux familles de champs cohabitent dans ces écrans, avec des largeurs qui
   n'avaient de rapport ni entre elles ni avec la donnée saisie :

     - champs ACF            `width: 100%`, AUCUN `max-width` → un NPA de
                             quatre chiffres occupait toute la colonne ;
     - champs PassVal hors ACF   aucune déclaration de largeur du tout → largeur
                             native du navigateur (~150-200px).

   Côte à côte, l'un s'étirait pendant que l'autre restait étroit. On pose donc
   l'échelle sémantique définie dans tokens.css (--champ-court / -moyen /
   -long), en `max-width` : le champ reste fluide sous son plafond, et tout
   repasse en pleine largeur en mobile.

   Ciblage : les champs ACF n'acceptent pas de classe posée depuis le thème
   (le balisage vient d'acf_form()), on s'appuie donc sur `data-key`, qui est
   l'identifiant STABLE d'un champ ACF, et sur le type d'<input> quand il suffit
   à trancher.

   Travail entièrement CSS : aucune modification de `passval` n'est nécessaire.
   ========================================================================== */

/* Plafond général : au-delà, un champ de texte cesse d'être lisible et ne fait
   que remplir la colonne. */
.tdb-bo-endpoint .acf-input input[type="text"],
.tdb-bo-endpoint .acf-input input[type="email"],
.tdb-bo-endpoint .acf-input input[type="url"],
.tdb-bo-endpoint .acf-input input[type="password"],
.tdb-bo-endpoint input[type="text"],
.tdb-bo-endpoint input[type="email"] {
    max-width: var( --champ-long );
}

/* Court : NPA de la fiche commerçant (field_5fb227f8eb6e2) et tout champ
   numérique — un nombre n'a jamais besoin d'une colonne entière. */
.tdb-bo-endpoint .acf-field[data-key="field_5fb227f8eb6e2"] .acf-input input,
.tdb-bo-endpoint .acf-input input[type="number"],
.tdb-bo-endpoint input[type="number"] {
    max-width: var( --champ-court );
}

/* Moyen : localité (field_5fb22805eb6e3), canton (field_5fb29afe92816),
   téléphone, et les dates — dont le sélecteur natif a sa propre largeur
   intrinsèque. */
.tdb-bo-endpoint .acf-field[data-key="field_5fb22805eb6e3"] .acf-input input,
.tdb-bo-endpoint .acf-field[data-key="field_5fb29afe92816"] .acf-input input,
.tdb-bo-endpoint .acf-field[data-key="field_5fb29afe92816"] .acf-input select,
.tdb-bo-endpoint .acf-input input[type="tel"],
.tdb-bo-endpoint .acf-input input[type="date"],
.tdb-bo-endpoint input[type="date"],
.tdb-bo-endpoint select {
    max-width: var( --champ-moyen );
}

/* Les zones de texte libre gardent toute la largeur : elles n'ont pas de
   longueur attendue. */
.tdb-bo-endpoint .acf-input textarea,
.tdb-bo-endpoint textarea {
    max-width: none;
}

/* La ligne NPA / Localité / Canton est fabriquée APRÈS coup par le JavaScript
   de PassVal (passval.php, « hack à la MacGyver » du 14.10.2025) : il déplace
   les trois `.acf-field` dans un <span id="my-account-npa-localiter-line">.
   Ce conteneur n'avait AUCUNE règle — les trois champs s'empilaient donc au
   lieu de tenir sur une rangée, ce que la vérification de MD10 demande
   explicitement de contrôler. C'est lui qui a le dernier mot sur la mise en
   page : la règle doit viser ce conteneur, pas les champs d'origine. */
#my-account-npa-localiter-line {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-end;
    gap: var( --space-md );
}

#my-account-npa-localiter-line > .acf-field {
    flex: 0 1 auto;
    margin-bottom: 0;
}

@media ( max-width: 767px ) {
    /* En mobile, aucune largeur sémantique ne tient : tout repasse en pleine
       largeur, y compris la ligne NPA / Localité / Canton, qui s'empile. */
    .tdb-bo-endpoint .acf-input input,
    .tdb-bo-endpoint .acf-input select,
    .tdb-bo-endpoint .acf-input textarea,
    .tdb-bo-endpoint input,
    .tdb-bo-endpoint select,
    .tdb-bo-endpoint textarea {
        max-width: 100%;
    }

    #my-account-npa-localiter-line {
        flex-direction: column;
        align-items: stretch;
    }
}

/* ==========================================================================
   MOD-IA 2026-09-22 : CK2 + CK3 — page de commande (/commande/, ex /checkout/).

   CK2 : « possibilité de mettre les infos sur deux colonnes ? »
   CK3 : « mettre à jour visuellement pour correspondre à la charte graphique »

   Constat : la commande était la page la moins habillée du site. Tout le CSS
   que le thème lui consacrait tenait en 16 lignes (hauteur de champ 46px, fond
   de `#payment`, fond de `.payment_box`) — voir plus haut dans ce fichier,
   règles conservées. Il n'existait AUCUNE règle pour `.col2-set`, pour
   `.woocommerce-checkout-review-order`, pour les libellés ni pour
   `#order_review_heading`. La page avait simplement été oubliée lors de
   l'habillage, ce qui allait de pair avec l'absence de surcharge de gabarit.

   AUCUNE FRAME DE COMMANDE N'EXISTE DANS LE FICHIER FIGMA — inventaire complet
   des 40 frames de premier niveau, docs/feedback_20260921/00-RELEVE-FIGMA.md
   §7. La mise en page est donc DÉRIVÉE de la charte, sur le modèle de la page
   panier (`page-panier.php`, `.tdb-panier-page`), et doit être VALIDÉE
   VISUELLEMENT par le client — elle n'est pas relevée.

   Vocabulaire repris tel quel de la charte (relevé §1, §2 et §4) :
   champs et déroulants 46px, rayon 10, padding-inline 20, filet 1px #7C7C7C
   sur fond blanc ; blocs blancs rayon 20 et filet #ECECEC ; titres Semibold
   32/38 (H1) et 24/28 (H2) ; libellés Medium 14/18.
   ========================================================================== */

/* ---------- CK2 : structure en deux colonnes ---------- */
/* MOD-IA 2026-09-24 : CK2 révisé — retour client : « Votre commande » repasse
   SOUS « Détails de facturation » (une seule colonne de page) ; ce sont les
   CHAMPS de facturation qui passent sur deux colonnes (voir plus bas,
   « CK2 révisé : champs de facturation sur deux colonnes »).
   ANCIEN CODE :
.tdb-checkout__grid {
    display: grid;
    grid-template-columns: minmax( 0, 1fr ) 432px;
    gap: var( --space-xl );
    align-items: start;
}
*/
.tdb-checkout__grid {
    display: grid;
    grid-template-columns: minmax( 0, 1fr );
    gap: var( --space-lg );
}

/* Le récapitulatif suit le défilement : sur une commande à plusieurs bons, la
   colonne de gauche est bien plus haute que la droite. Même valeur de `top`
   que les autres colonnes collantes du thème (`.tdb-filtres`). */
/* MOD-IA 2026-09-24 : plus de colonne de droite, donc plus de récapitulatif
   collant — il suit simplement les coordonnées.
   ANCIEN CODE :
.tdb-checkout__col--recap {
    position: sticky;
    top: var( --space-lg );
}
*/

/* ---------- CK2 révisé : champs de facturation sur deux colonnes ----------
   MOD-IA 2026-09-24 : les rangées de WooCommerce (`form-row-first` /
   `form-row-last` flottées à 47 %, `form-row-wide` pleine largeur) sont
   remplacées par une grille à deux colonnes. Groupes, dans l'ordre du DOM
   (priorités : voir `tdb_checkout_ordre_champs_facturation()` dans
   inc/woocommerce.php) :
     1. identité  — E-mail | Téléphone, Prénom | Nom ;
     2. adresse   — Pays (pleine largeur, ouvre le groupe par un filet),
                    Rue | Complément, NPA | Localité, Canton.
   Sous 640px, une seule colonne. */
.tdb-checkout .woocommerce-billing-fields__field-wrapper {
    display: grid;
    grid-template-columns: repeat( 2, minmax( 0, 1fr ) );
    column-gap: var( --space-md );
}

.tdb-checkout .woocommerce-billing-fields__field-wrapper .form-row {
    float: none;
    width: auto;
    min-width: 0;
    /* `.woocommerce form .form-row` (plus spécifique que `.tdb-checkout
       .form-row`) remettait 3px de retrait : les libellés d'une même rangée
       étaient décalés de 3px par rapport au Pays. */
    padding: 0;
}

/* Le Pays ouvre le groupe « adresse » : pleine largeur, séparé du groupe
   « identité » par le filet des cartes. */
.tdb-checkout #billing_country_field {
    grid-column: 1 / -1;
    margin-top: var( --space-sm );
    padding-top: var( --space-lg );
    border-top: 1px solid var( --color-border );
}

/* Le libellé du Complément d'adresse est masqué par WooCommerce
   (`screen-reader-text`) : à côté du champ Rue, qui a le sien, les deux champs
   ne seraient plus alignés. On le rend visible. */
/* `!important` : la feuille de WooCommerce impose le masquage de
   `.screen-reader-text` en `!important`. */
.tdb-checkout #billing_address_2_field label.screen-reader-text {
    position: static !important;
    width: auto !important;
    height: auto !important;
    margin: 0 0 10px !important;
    clip: auto !important;
    clip-path: none !important;
    overflow: visible !important;
    word-wrap: normal !important;
}

/* Pays et Canton sont rendus par Select2 (39px natifs) : même hauteur, filet
   et rayon que les champs texte voisins, sur le modèle de la règle
   `.tdb-bo-endpoint .select2-container` (valeurs de la commande : 46px). */
.tdb-checkout .select2-container .select2-selection--single {
    height: 46px;
    background: #fff;
    border: 1px solid var( --color-text-muted );
    border-radius: var( --radius-sm );
}

.tdb-checkout .select2-container .select2-selection--single .select2-selection__rendered {
    /* padding-block : WooCommerce en pose 7px, qui décalait le texte vers le bas. */
    padding: 0 20px;
    line-height: 44px;
    font-family: var( --font-body );
    font-size: var( --text-card-desc-size );
    color: var( --color-text );
}

.tdb-checkout .select2-container .select2-selection--single .select2-selection__arrow {
    height: 44px;
    right: var( --space-sm );
}

/* Le `.clear` intercalé par WooCommerce après les rangées flottées deviendrait
   une cellule vide de la grille. */
.tdb-checkout .woocommerce-billing-fields__field-wrapper .clear {
    display: none;
}

/* MOD-IA 2026-09-24 : « Informations complémentaires » vit DANS `.col-2`, qui
   est déjà une carte : les deux recevaient le cadre (carte dans la carte). Le
   bloc intérieur perd le sien. */
.tdb-checkout .col2-set .col-2 .woocommerce-additional-fields {
    padding: 0;
    background: none;
    border: none;
    border-radius: 0;
}

/* Même retrait de 3px de WooCommerce sur les notes de commande : le champ
   n'était pas aligné sur le titre de sa carte. */
.tdb-checkout .woocommerce-additional-fields__field-wrapper .form-row {
    padding: 0;
}

@media ( max-width: 639px ) {
    .tdb-checkout .woocommerce-billing-fields__field-wrapper {
        grid-template-columns: minmax( 0, 1fr );
    }

    /* MOD-IA 2026-09-24 : en mobile, trois retraits s'emboîtaient autour du
       bouton « Commander » (carte, cartouche `#payment`, rangée de WooCommerce)
       et ne laissaient qu'une colonne de texte d'environ 180px. On les
       resserre. */
    .tdb-checkout .col2-set .col-1,
    .tdb-checkout .col2-set .col-2,
    .tdb-checkout #order_review {
        padding: var( --space-md );
    }

    .tdb-checkout #payment {
        padding: var( --space-sm );
    }

    .tdb-checkout #payment div.form-row {
        padding: var( --space-sm ) 0 0;
    }
}

/* MOD-IA 2026-09-28 : la variante bureau sur trois colonnes (adresse en
   grille de 6 pistes, ≥ 1024px) est retirée à la demande du client : la
   grille reste sur deux colonnes à toutes les largeurs ≥ 640px. */

/* Les deux blocs natifs `.col-1` (facturation) et `.col-2` (livraison) ne sont
   plus des colonnes de page : ils s'empilent dans la colonne de gauche. La
   règle neutralise les FLOTTANTS que WooCommerce leur pose. */
.tdb-checkout .col2-set {
    display: flex;
    flex-direction: column;
    gap: var( --space-lg );
}

.tdb-checkout .col2-set .col-1,
.tdb-checkout .col2-set .col-2 {
    float: none;
    width: 100%;
}

/* ---------- CK3 : surfaces de la charte ---------- */
/* Bloc blanc rayon 20 + filet #ECECEC : la grammaire des cartes du compte et
   du panier. Chaque groupe de la commande en reçoit un, pour que la page cesse
   d'être une suite de champs posés sur le fond de page. */
.tdb-checkout .col2-set .col-1,
.tdb-checkout .col2-set .col-2,
.tdb-checkout .woocommerce-additional-fields,
.tdb-checkout #order_review {
    background: #fff;
    border: 1px solid var( --color-border );
    border-radius: var( --radius-card );
    padding: var( --space-lg );
}

/* `#payment` vit DANS `#order_review` : deux cartouches imbriquées feraient un
   cadre dans un cadre. Il garde donc le fond gris de la charte, sans filet.
   Les deux règles d'origine (fond gris, `.payment_box` blanche) restent en
   place plus haut dans le fichier ; on ne fait qu'y ajouter le retrait et le
   rayon de la charte. */
.tdb-checkout #payment {
    background: var( --color-surface-muted );
    border: none;
    border-radius: var( --radius-sm );
    padding: var( --space-md ) 20px;
}

.tdb-checkout #payment div.payment_box {
    background: #fff;
    border-radius: var( --radius-sm );
}

/* Titres de section — H2 de la charte (Semibold 24/28). WooCommerce en rend
   plusieurs en <h3> non stylés (« Détails de facturation », « Informations
   complémentaires »). */
.tdb-checkout__titre,
.tdb-checkout .col2-set h3,
.tdb-checkout .woocommerce-additional-fields h3 {
    margin: 0 0 var( --space-lg );
    font-size: var( --text-h2-size );
    line-height: var( --text-h2-lh );
    font-weight: var( --weight-semibold );
    letter-spacing: var( --tracking-tight );
    color: var( --color-ink );
}

/* Libellés — Medium 14/18, comme partout ailleurs dans les formulaires. */
.tdb-checkout .form-row label {
    display: block;
    margin-bottom: 10px;
    font-size: var( --text-button-size );
    line-height: var( --text-button-lh );
    font-weight: var( --weight-medium );
    letter-spacing: var( --tracking-tight );
    color: var( --color-text );
}

.tdb-checkout .form-row {
    margin-bottom: var( --space-md );
    padding: 0;
}

/* Champs : la règle générique `.woocommerce-checkout .form-row input.input-text`
   posait déjà 46px et le filet, mais ne couvrait ni les zones de texte ni le
   retrait de 20px de la charte, et laissait le déroulant Pays au style natif. */
.tdb-checkout .form-row input.input-text,
.tdb-checkout .form-row textarea,
.tdb-checkout .form-row select {
    width: 100%;
    height: 46px;
    box-sizing: border-box;
    padding-inline: 20px;
    background: #fff;
    border: 1px solid var( --color-text-muted );
    border-radius: var( --radius-sm );
    font-family: var( --font-body );
    font-size: var( --text-card-desc-size );
    color: var( --color-text );
}

.tdb-checkout .form-row textarea {
    height: auto;
    min-height: 120px;
    padding-block: var( --space-sm );
    resize: vertical;
}

.tdb-checkout .form-row input.input-text:focus,
.tdb-checkout .form-row textarea:focus,
.tdb-checkout .form-row select:focus {
    outline: none;
    border-color: var( --color-primary );
}

/* Champ en erreur : le rouge de la charte plutôt que celui de WooCommerce. */
.tdb-checkout .woocommerce-invalid input.input-text,
.tdb-checkout .woocommerce-invalid select {
    border-color: var( --color-status-expired-strong );
}

/* Tableau récapitulatif : mêmes filets discrets que le panier, pas les
   bordures pleines du tableau natif de WooCommerce. */
.tdb-checkout .woocommerce-checkout-review-order-table {
    width: 100%;
    border-collapse: collapse;
    font-size: var( --text-card-desc-size );
}

.tdb-checkout .woocommerce-checkout-review-order-table th,
.tdb-checkout .woocommerce-checkout-review-order-table td {
    padding: var( --space-sm ) 0;
    border-bottom: 1px solid var( --color-border );
    text-align: left;
}

.tdb-checkout .woocommerce-checkout-review-order-table th:last-child,
.tdb-checkout .woocommerce-checkout-review-order-table td:last-child {
    text-align: right;
}

.tdb-checkout .woocommerce-checkout-review-order-table .order-total {
    font-weight: var( --weight-semibold );
}

/* MOD-IA 2026-09-24 : les trois règles ci-dessus perdaient face à
   `.woocommerce table.shop_table …` (WooCommerce + règles génériques du thème,
   plus spécifiques) : le récapitulatif gardait l'en-tête gris, les filets
   verticaux et le cadre du tableau natif. Même intention, portée par
   `#order_review` pour l'emporter. `nowrap` sur la colonne des montants :
   « Sous-total » passait sur deux lignes en mobile. */
.tdb-checkout #order_review table.shop_table {
    margin: 0 0 var( --space-lg );
    border: none;
    border-radius: 0;
    border-collapse: collapse;
}

.tdb-checkout #order_review table.shop_table th,
.tdb-checkout #order_review table.shop_table td {
    padding: var( --space-sm ) 0;
    background: none;
    border: none;
    border-bottom: 1px solid var( --color-border );
}

.tdb-checkout #order_review table.shop_table th:last-child,
.tdb-checkout #order_review table.shop_table td:last-child {
    padding-left: var( --space-md );
    white-space: nowrap;
}

.tdb-checkout #order_review table.shop_table .order-total th,
.tdb-checkout #order_review table.shop_table .order-total td {
    border-bottom: none;
    font-size: var( --text-body-size );
}

/* Bouton « Commander » : variante primaire de la charte. Il ne peut pas
   recevoir le sourire des boutons du thème — c'est un <button> rendu par
   WooCommerce, pas par tdb_ui( 'bouton' ) —, mais il en prend la surface, le
   rayon et le comportement de survol. */
.tdb-checkout #place_order {
    width: 100%;
    min-height: 46px;
    padding-inline: var( --space-lg );
    background: var( --color-primary );
    color: var( --color-ink );
    border: none;
    border-radius: var( --radius-pill );
    font-family: var( --font-body );
    font-size: var( --text-button-size );
    font-weight: var( --weight-medium );
    letter-spacing: var( --tracking-tight );
    cursor: pointer;
    transition: background-color var( --duration-tdb ) var( --ease-tdb );
}

.tdb-checkout #place_order:hover,
.tdb-checkout #place_order:focus-visible {
    background: var( --color-ink );
    color: #fff;
}

/* Coupon : le bandeau natif est un encadré en pointillés hérité du thème
   Storefront. Il reprend la cartouche grise des messages de la charte. */
.woocommerce-checkout .woocommerce-form-coupon-toggle .woocommerce-info,
.woocommerce-checkout form.checkout_coupon {
    background: var( --color-surface-muted );
    border: none;
    border-radius: var( --radius-sm );
    /* padding: var( --space-md ) 20px; */
}

@media ( max-width: 1023px ) {
    /* Sous la largeur d'un écran de bureau, la colonne de droite n'a plus la
       place de ses 432px : la page passe sur une seule colonne, coordonnées
       puis récapitulatif — l'ordre logique du parcours. */
    /* MOD-IA 2026-09-24 : la page est désormais sur une colonne à toutes les
       largeurs (CK2 révisé) — règles devenues sans objet.
       ANCIEN CODE :
    .tdb-checkout__grid {
        grid-template-columns: minmax( 0, 1fr );
    }

    .tdb-checkout__col--recap {
        position: static;
    }
    */
}


/* ---------------------------------------------------------------------------
   MOD-IA 2026-09-22 : PA2 — champs cadeau des formulaires d'achat
   (template-parts/commercant/champs-cadeau.php).

   Repliés par défaut dans un <details> : les trois champs sont facultatifs et
   ne doivent pas alourdir un parcours qui tient en deux gestes. Largeur 100 %
   du formulaire, pas de largeur fixe — le partiel sert aussi bien dans la
   ligne de bon d'une fiche commerçant que dans le widget étroit de
   /bons-valeur/.
--------------------------------------------------------------------------- */
.tdb-champs-cadeau {
    width: 100%;
    margin: var( --space-xs ) 0;
}

.tdb-champs-cadeau__resume {
    cursor: pointer;
    font-size: var( --text-caption-size );
    color: var( --color-text-muted );
    list-style: none;
}

.tdb-champs-cadeau__resume::-webkit-details-marker {
    display: none;
}

.tdb-champs-cadeau__resume::before {
    content: '+ ';
    font-weight: var( --weight-medium );
}

.tdb-champs-cadeau[open] .tdb-champs-cadeau__resume::before {
    content: '− ';
}

.tdb-champs-cadeau__resume:hover,
.tdb-champs-cadeau__resume:focus-visible {
    color: var( --color-primary );
}

.tdb-champs-cadeau__corps {
    display: flex;
    flex-direction: column;
    gap: var( --space-xs );
    margin-top: var( --space-xs );
}

.tdb-champs-cadeau__champ {
    display: flex;
    flex-direction: column;
    gap: 4px;
    margin: 0;
}

.tdb-champs-cadeau__champ label {
    font-size: var( --text-caption-size );
    color: var( --color-text-muted );
}

.tdb-champs-cadeau__champ input,
.tdb-champs-cadeau__champ textarea {
    width: 100%;
    box-sizing: border-box;
    font-family: inherit;
    font-size: var( --text-caption-size );
}

.tdb-champs-cadeau__champ textarea {
    resize: vertical;
}

.tdb-champs-cadeau__aide {
    font-size: var( --text-caption-size );
    color: var( --color-text-muted );
}


/* ---------------------------------------------------------------------------
   MOD-IA 2026-09-22 : PA2 (révision) — dédicaces du panier
   (template-parts/panier/dedicaces.php).

   Le bloc .tdb-champs-cadeau ci-dessus n'est plus utilisé (gabarit neutralisé) :
   il est conservé comme référence, la saisie ayant déménagé du formulaire
   d'achat vers la ligne de panier, avec un jeu de champs PAR BON.

   Le <summary> est habillé en bouton : c'est le « bouton dans le panier »
   demandé par le client, mais sans JavaScript — le repli natif de <details>
   suffit, et le panier doit rester utilisable si main.js ne se charge pas.
--------------------------------------------------------------------------- */
.tdb-dedicaces {
    margin-top: var( --space-sm );
}

.tdb-dedicaces__bouton {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    cursor: pointer;
    padding: 6px 12px;
    border: 1px solid var( --color-text-muted );
    border-radius: var( --radius-sm );
    background: #fff;
    font-family: var( --font-body );
    font-size: var( --text-caption-size );
    color: var( --color-text );
    list-style: none;
}

/* Triangle natif du <summary> retiré (Chrome/Safari d'un côté, Firefox de
   l'autre) : il déplaçait le texte hors du bouton. */
.tdb-dedicaces__bouton::-webkit-details-marker {
    display: none;
}

.tdb-dedicaces__bouton::before {
    content: 'B';
    font-weight: var( --weight-semibold );
    line-height: 1;
}

.tdb-dedicaces[open] .tdb-dedicaces__bouton::before {
    content: '2';
}

.tdb-dedicaces__bouton:hover,
.tdb-dedicaces__bouton:focus-visible {
    border-color: var( --color-primary );
    color: var( --color-primary );
}

.tdb-dedicaces__corps {
    display: flex;
    flex-direction: column;
    gap: var( --space-sm );
    margin-top: var( --space-sm );
    max-width: 420px;
}

.tdb-dedicaces__intro {
    margin: 0;
    font-size: var( --text-caption-size );
    color: var( --color-text-muted );
}

/* Un <fieldset> par bon de la ligne : c'est ce qui rend visible le « 1 bon =
   une dédicace » quand la quantité dépasse 1. */
.tdb-dedicaces__bon {
    display: flex;
    flex-direction: column;
    gap: var( --space-xs );
    margin: 0;
    padding: var( --space-sm );
    border: 1px solid var( --color-border, rgba( 0, 0, 0, .12 ) );
    border-radius: var( --radius-sm );
}

.tdb-dedicaces__legende {
    padding: 0 6px;
    font-family: var( --font-heading );
    font-size: var( --text-caption-size );
    font-weight: var( --weight-semibold );
    color: var( --color-text-muted );
    text-transform: uppercase;
    letter-spacing: .02em;
}

.tdb-dedicaces__champ {
    display: flex;
    flex-direction: column;
    gap: 4px;
    margin: 0;
}

.tdb-dedicaces__champ label {
    font-size: var( --text-caption-size );
    color: var( --color-text-muted );
}

.tdb-dedicaces__champ input,
.tdb-dedicaces__champ textarea {
    width: 100%;
    box-sizing: border-box;
    font-family: inherit;
    font-size: var( --text-caption-size );
}

.tdb-dedicaces__champ textarea {
    resize: vertical;
}

.tdb-dedicaces__aide {
    font-size: var( --text-caption-size );
    color: var( --color-text-muted );
}

.tdb-dedicaces__enregistrer {
    align-self: flex-start;
}


/* ---------------------------------------------------------------------------
   MOD-IA 2026-09-22 : CL4 — barre de tri et de filtres de « Mes bons ».

   L'écran est rendu par PassVal (tdb_client_vouchers_list_endpoints(),
   passval.php) ; seule sa mise en forme vit ici, comme le reste des écrans
   client du plugin.
--------------------------------------------------------------------------- */
.tdb-vouchers-filtres {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var( --space-xs );
    margin: 0 0 var( --space-md );
}

.tdb-vouchers-filtres label {
    font-size: var( --text-caption-size );
    color: var( --color-text-muted );
}

.tdb-vouchers-filtres select {
    font-family: inherit;
    font-size: var( --text-caption-size );
}

.tdb-vouchers-filtres__compte {
    margin-left: auto;
    font-size: var( --text-caption-size );
    color: var( --color-text-muted );
}

@media ( max-width: 767px ) {
    .tdb-vouchers-filtres__compte {
        margin-left: 0;
        width: 100%;
    }
}

/* ==========================================================================
   MOD-IA 2026-09-22 : page « FAQ » (page-faq.php)
   ========================================================================== */
/* Le titre de page (H1 orange + filet) vient de .tdb-compte-form__title, comme
   sur « Contacter le support ». Les rubriques reprennent le bloc .tdb-faq,
   mais leur titre passe en H2 noir : un seul titre orange par page (I-2). */
.tdb-faq-page .tdb-faq {
    margin-top: var( --space-2xl );
}

.tdb-faq-page .tdb-compte-form__title + .tdb-faq {
    margin-top: 0;
}

.tdb-faq-page .tdb-faq__title {
    color: var( --color-text );
    font-size: var( --text-h2-size );
    line-height: var( --text-h2-lh );
    margin-bottom: var( --space-md );
}

.tdb-faq-page__intro {
    margin-bottom: var( --space-md );
}

/* Réponses : paragraphes et listes issus de l'éditeur, sans marge parasite
   en fin de panneau. */
.tdb-faq-page .tdb-accordion__panel > :first-child {
    margin-top: 0;
}

.tdb-faq-page .tdb-accordion__panel > :last-child {
    margin-bottom: 0;
}

.tdb-faq-page .tdb-accordion__panel p,
.tdb-faq-page .tdb-accordion__panel ol,
.tdb-faq-page .tdb-accordion__panel ul {
    margin: 0 0 var( --space-sm );
}

.tdb-faq-page .tdb-accordion__panel ol,
.tdb-faq-page .tdb-accordion__panel ul {
    padding-left: 1.5em;
}

.tdb-faq-page .tdb-accordion__panel ol {
    list-style: decimal;
}

.tdb-faq-page .tdb-accordion__panel ul {
    list-style: disc;
}

.tdb-faq-page .tdb-accordion__panel a {
    text-decoration: underline;
}

@media ( max-width: 767px ) {
    .tdb-faq-page .tdb-faq {
        margin-top: var( --space-xl );
    }
    .tdb-faq-page .tdb-faq__title {
        font-size: var( --text-h2-size-mobile );
        line-height: var( --text-h2-lh-mobile );
    }
}

/* ==========================================================================
   MOD-IA 2026-09-22 : MD9 (suite) — panneau OUVERT des menus déroulants de
   la barre de filtres du back-office (« Suivi de mes bons »,
   template-parts/backoffice/bons-filtres.php).

   Jusqu'ici, seul le bouton fermé suivait la maquette : à l'ouverture, le
   navigateur affichait sa propre liste système (fond gris, surlignage bleu,
   aucune icône), sans rapport avec les panneaux « BO menu déroulant » de
   Figma, relevés en lecture seule le 22.09.2026 :

       Type    6023:6217     Canal   6023:6348
       Statut  6023:6446     Filtrer 6023:6216

   Géométrie commune : panneau blanc, filet 1px #7C7C7C, rayon 10, padding 20,
   300 de large ; lignes Regular 14/35, letter-spacing -0.14px, texte noir ;
   dans Type / Canal / Statut, chaque ligne = boîte picto 34×34 (rayon 5)
   + 5px + libellé, 5px entre deux lignes.

   Changement PUREMENT VISUEL : ni le balisage, ni les valeurs, ni le
   JavaScript ne bougent. On s'appuie sur les <select> personnalisables
   (`appearance: base-select` + `::picker(select)`), que Chrome et Edge
   prennent en charge depuis la version 135. Firefox et Safari ignorent le
   bloc `@supports` et gardent leur liste système, sans régression.

   Les pictos sont les SVG exportés de Figma déjà présents dans
   assets/images/icons/ (ceux des pastilles du listing, cf.
   tdb_bon_picto_type() et tdb_bon_box_statut() dans inc/template-tags.php),
   posés sur l'option par sa `value` — d'où l'absence de toute modification
   PHP. Seule exception : le picto « Tout afficher », qui dans Figma n'est pas
   un vecteur exporté mais quatre carrés 7×7 (filet 1,5 noir, rayon 1, pas de
   11 — nœud I6023:6223;6079:6463) ; il est reproduit à l'identique en SVG
   inline.

   ⚠ NON FIXÉ PAR LA MAQUETTE (hypothèses, à valider visuellement) :
     - aucun état survol / option sélectionnée n'est dessiné dans les
       panneaux : on pose un fond #F7F7F7 (--color-surface-muted) au survol
       et au focus clavier, et le libellé en Medium pour l'option en cours ;
     - l'écart entre le bouton et le panneau (6px) et l'ombre reprennent ceux
       du panneau front `.tdb-dropdown__panel` (ui/02-formulaires.css) ;
     - le déroulant « par page » n'a pas de panneau dans Figma : il reprend le
       panneau texte seul de « Filtrer ».
   Les LIBELLÉS ne changent pas (la première option reste « Type », « Canal »…
   là où la maquette écrit « Tout afficher ») : ce serait une modification du
   contenu, hors du périmètre « visuel uniquement ».
   ========================================================================== */

@supports ( appearance: base-select ) {

    .tdb-bons-filtres .tdb-filtres__select,
    .tdb-bons-filtres .tdb-filtres__select::picker( select ) {
        appearance: base-select;
    }

    /* Bouton fermé : inchangé. Le mode base-select ajoute sa propre flèche
       (::picker-icon) ; le chevron du thème (background-image du bloc MD9)
       reste le seul affiché. */
    .tdb-bons-filtres .tdb-filtres__select {
        display: flex;
        align-items: center;
    }

    .tdb-bons-filtres .tdb-filtres__select::picker-icon {
        display: none;
    }

    /* Ouvert = orange plein, comme au survol (relevé §4 : « Ouvert et survol »
       identiques dans les trois variantes de bouton). */
    .tdb-bons-filtres .tdb-filtres__select:open {
        background-color: var( --color-primary );
    }

    /* Panneau — 6023:6217 & co. */
    .tdb-bons-filtres .tdb-filtres__select::picker( select ) {
        box-sizing: border-box;
        min-width: 300px;
        max-height: 320px;
        margin-block: 6px;
        padding: 20px;
        overflow-y: auto;
        background: #fff;
        border: 1px solid var( --color-text-muted );
        border-radius: var( --radius-sm );
        box-shadow: var( --shadow-popover );
    }

    /* Ligne texte seule (panneau « Filtrer » 6023:6216) : Regular 14/35. */
    .tdb-bons-filtres .tdb-filtres__select option {
        display: flex;
        align-items: center;
        gap: 5px;
        min-height: 35px;
        padding: 0 8px;
        border-radius: var( --radius-badge );
        font-family: var( --font-body );
        font-size: 14px;
        line-height: 35px;
        font-weight: var( --weight-regular );
        letter-spacing: -0.14px;
        color: #000;
        background: transparent;
        cursor: pointer;
    }

    /* La coche que le navigateur ajoute devant l'option choisie n'existe pas
       dans la maquette. */
    .tdb-bons-filtres .tdb-filtres__select option::checkmark {
        display: none;
    }

    .tdb-bons-filtres .tdb-filtres__select option:hover,
    .tdb-bons-filtres .tdb-filtres__select option:focus-visible {
        background-color: var( --color-surface-muted );
        outline: none;
    }

    .tdb-bons-filtres .tdb-filtres__select option:checked {
        font-weight: var( --weight-medium );
    }

    /* Panneaux à pictos (Type, Canal, Statut) : ligne de 34, 5px entre deux
       lignes ; le padding de gauche tombe à 0, c'est la boîte picto qui porte
       le retrait, comme dans Figma. */
    #tdb-bons-filtre-type option,
    #tdb-bons-filtre-canal option,
    #tdb-bons-filtre-statut option {
        min-height: 34px;
        padding: 0 8px 0 0;
    }

    #tdb-bons-filtre-type option + option,
    #tdb-bons-filtre-canal option + option,
    #tdb-bons-filtre-statut option + option {
        margin-top: 5px;
    }

    /* Boîte picto 34×34, rayon 5, picto centré à sa taille Figma. */
    #tdb-bons-filtre-type option::before,
    #tdb-bons-filtre-canal option::before,
    #tdb-bons-filtre-statut option::before {
        content: "";
        flex: 0 0 34px;
        height: 34px;
        border-radius: var( --radius-badge );
        background-repeat: no-repeat;
        background-position: center;
        /* « Tout afficher » : 4 carrés 7×7, filet 1,5, rayon 1, pas de 11. */
        background-image: url( "data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='18' height='18' viewBox='0 0 18 18' fill='none' stroke='%23000' stroke-width='1.5'%3E%3Crect x='.75' y='.75' width='5.5' height='5.5' rx='.5'/%3E%3Crect x='11.75' y='.75' width='5.5' height='5.5' rx='.5'/%3E%3Crect x='.75' y='11.75' width='5.5' height='5.5' rx='.5'/%3E%3Crect x='11.75' y='11.75' width='5.5' height='5.5' rx='.5'/%3E%3C/svg%3E" );
        background-size: 18px 18px;
    }

    /* Type — 6023:6217 */
    #tdb-bons-filtre-type option[value="bon_valeur"]::before {
        background-image: url( '../images/icons/picto-type-bon-valeur.svg' );
        background-size: 18px 19px;
    }
    #tdb-bons-filtre-type option[value="prestation"]::before {
        background-image: url( '../images/icons/picto-type-prestation.svg' );
        background-size: 16px 20px;
    }
    /* MOD-IA 2026-09-28 : le filtre « Bon activable » reprend le picto QR. */
    #tdb-bons-filtre-type option[value="carte_qr"]::before,
    #tdb-bons-filtre-type option[value="bon_activable"]::before {
        background-image: url( '../images/icons/picto-type-carte-qr.svg' );
        background-size: 17px 17px;
    }
    #tdb-bons-filtre-type option[value="carte"]::before {
        background-image: url( '../images/icons/picto-type-carte.svg' );
        background-size: 18px 13px;
    }

    /* Canal — 6023:6348 (valeurs = libellés, cf. $canaux dans bons-filtres.php) */
    #tdb-bons-filtre-canal option[value="Achat en ligne"]::before {
        background-image: url( '../images/icons/picto-canal-achat-en-ligne.svg' );
        background-size: 14px 20px;
    }
    #tdb-bons-filtre-canal option[value="Sur place"]::before {
        background-image: url( '../images/icons/picto-sur-place.svg' );
        background-size: 18px 22px;
    }
    #tdb-bons-filtre-canal option[value="Généré"]::before {
        background-image: url( '../images/icons/picto-canal-genere.svg' );
        background-size: 18px 18px;
    }
    #tdb-bons-filtre-canal option[value="Activé"]::before {
        background-image: url( '../images/icons/picto-canal-active.svg' );
        background-size: 21px 12px;
    }

    /* Statut — 6023:6446 : pictos de 20×20. */
    #tdb-bons-filtre-statut option[value="a_valider"]::before {
        background-image: url( '../images/icons/picto-statut-a-valider.svg' );
        background-size: 20px 20px;
    }
    #tdb-bons-filtre-statut option[value="valide"]::before {
        background-image: url( '../images/icons/picto-statut-valide.svg' );
        background-size: 20px 20px;
    }
    #tdb-bons-filtre-statut option[value="non_active"]::before {
        background-image: url( '../images/icons/picto-statut-non-active.svg' );
        background-size: 20px 20px;
    }
    #tdb-bons-filtre-statut option[value="epuise"]::before {
        background-image: url( '../images/icons/picto-statut-epuise.svg' );
        background-size: 20px 20px;
    }
    #tdb-bons-filtre-statut option[value="echu"]::before {
        background-image: url( '../images/icons/picto-statut-echu.svg' );
        background-size: 20px 20px;
    }
}

/* ==========================================================================
   MOD-IA 2026-09-22 : menu latéral du back-office — états FERMÉ et OUVERT
   ramenés sur le composant Figma « BO menu lateral », relevé en lecture seule
   le 22.09.2026 :

       fermé  2010:3618   (instance 2162:3948 de « Page BO - mon compte »
                           352:2549)
       ouvert 2010:3616
       mobile « SP - menu BO » 473:7936

   Balisage inchangé (woocommerce/myaccount/navigation.php, partagé par le menu
   desktop et le menu hors-canevas mobile) : seule l'apparence bouge.

   Ce que dit la maquette, et qui différait du thème :

     FERMÉ   pastilles #212121, texte blanc Medium 14/18 (-0.14px), hauteur 46,
             rayon 10, retrait 20, 15px entre deux pastilles ; AUCUN picto.
             Survol = orange plein, texte noir (« noir > orange ») — le thème
             passait en blanc à texte orange.
     OUVERT  le titre du groupe passe en ORANGE plein, texte et chevron NOIRS,
             chevron vers le haut. Les sous-entrées ne sont PLUS des pastilles
             noires à picto : ce sont des lignes de texte noir Regular 14/30,
             retrait 20, posées sur le fond gris du menu, chacune soulignée
             d'un filet 1px #D0D0D0 (5px au-dessus du texte, 10px dessous).

   Les règles d'origine ne sont pas effacées : elles restent plus haut dans ce
   fichier, ce bloc les surcharge.

   ⚠ NON DESSINÉ DANS LA MAQUETTE (hypothèses, à valider visuellement) :
     - survol d'une sous-entrée : libellé orange, sans fond ;
     - sous-entrée de la page en cours : libellé orange en Medium (la maquette
       ne montre aucun état « actif » dans le menu ouvert) ;
     - le niveau intermédiaire de la maquette (« Gérer mon profil en ligne »,
       « Gérer mes ventes directes », pastilles blanches) n'existe pas dans
       le menu du thème, qui n'a qu'un niveau de groupes : il n'est pas
       reproduit, ce serait une modification de structure, pas de style.
   ========================================================================== */

/* 15px entre deux pastilles (gap du composant 2010:3618). */
.tdb-bo-sidebar,
.tdb-bo-sidebar .tdb-bo-sidebar__submenu--isolee {
    gap: 15px;
}

/* La marge ajoutée plus haut (`+ .tdb-bo-sidebar__submenu--isolee`) s'ajoutait
   au gap : l'écart doit rester 15px partout. */
.tdb-bo-sidebar .tdb-bo-sidebar__group + .tdb-bo-sidebar__submenu--isolee {
    margin-top: 0;
}

/* ---------- Pastilles : titres de groupe ET entrées isolées ---------- */
.tdb-bo-sidebar .tdb-bo-sidebar__group > summary.tdb-bo-sidebar__link,
.tdb-bo-sidebar .tdb-bo-sidebar__submenu--isolee li > a,
.tdb-bo-sidebar .tdb-bo-sidebar__submenu--isolee li.is-active > a {
    display: flex;
    align-items: center;
    min-height: 46px;
    padding-block: 0;
    border-radius: var( --radius-sm );
    background: var( --color-ink );
    color: #fff;
    font-size: var( --text-button-size );
    line-height: 18px;
    font-weight: var( --weight-medium );
    letter-spacing: -0.14px;
}

/* Entrées isolées : retrait 20 à gauche comme les titres de groupe. Sur la
   page en cours, « Mon compte » reste noir dans la maquette (352:2549). */
.tdb-bo-sidebar .tdb-bo-sidebar__submenu--isolee li > a {
    padding-inline: 20px;
}

/* Aucun picto dans le menu de la maquette, ni fermé ni ouvert. */
.tdb-bo-sidebar .tdb-bo-sidebar__picto {
    display: none;
}

/* Survol : orange plein, texte et chevron noirs. */
.tdb-bo-sidebar .tdb-bo-sidebar__group > summary.tdb-bo-sidebar__link:hover,
.tdb-bo-sidebar .tdb-bo-sidebar__group > summary.tdb-bo-sidebar__link:focus-visible,
.tdb-bo-sidebar .tdb-bo-sidebar__submenu--isolee li > a:hover,
.tdb-bo-sidebar .tdb-bo-sidebar__submenu--isolee li > a:focus-visible {
    background: var( --color-primary );
    color: #000;
}

/* ---------- Groupe OUVERT (2010:3616) ---------- */
.tdb-bo-sidebar .tdb-bo-sidebar__group[open] > summary.tdb-bo-sidebar__link {
    background: var( --color-primary );
    color: #000;
}

/* Le chevron est tracé en currentColor : il suit le texte, blanc sur la
   pastille noire, noir sur l'orange (survol ou groupe ouvert). */
.tdb-bo-sidebar .tdb-bo-sidebar__group > summary.tdb-bo-sidebar__link:hover .tdb-bo-sidebar__chevron,
.tdb-bo-sidebar .tdb-bo-sidebar__group > summary.tdb-bo-sidebar__link:focus-visible .tdb-bo-sidebar__chevron,
.tdb-bo-sidebar .tdb-bo-sidebar__group[open] > summary.tdb-bo-sidebar__link .tdb-bo-sidebar__chevron {
    color: #000;
}

/* Liste des sous-entrées : 5px au-dessus et au-dessous (2010:3568), lignes
   jointives — le rythme vient du retrait et du filet de chaque ligne. */
.tdb-bo-sidebar .tdb-bo-sidebar__group > .tdb-bo-sidebar__submenu {
    margin-top: 0;
    padding-block: 5px;
    gap: 0;
}

/* Sous-entrée : texte noir Regular 14/30, retrait 20, filet #D0D0D0 dessous
   (2010:3518 : 5px au-dessus du texte, 10px entre le texte et le filet). */
.tdb-bo-sidebar .tdb-bo-sidebar__group > .tdb-bo-sidebar__submenu li > a,
.tdb-bo-sidebar .tdb-bo-sidebar__group > .tdb-bo-sidebar__submenu li.is-active > a {
    display: block;
    padding: 5px 20px 10px;
    border-radius: 0;
    border-bottom: 1px solid #D0D0D0;
    background: transparent;
    color: #000;
    font-size: var( --text-button-size );
    line-height: 30px;
    font-weight: var( --weight-regular );
    letter-spacing: -0.14px;
}

.tdb-bo-sidebar .tdb-bo-sidebar__group > .tdb-bo-sidebar__submenu li > a:hover,
.tdb-bo-sidebar .tdb-bo-sidebar__group > .tdb-bo-sidebar__submenu li > a:focus-visible {
    background: transparent;
    color: var( --color-primary );
}

.tdb-bo-sidebar .tdb-bo-sidebar__group > .tdb-bo-sidebar__submenu li.is-active > a {
    color: var( --color-primary );
    font-weight: var( --weight-medium );
}

/* ---------- Menu hors-canevas mobile (473:7936) ---------- */
/* Même composant, gabarit téléphone : pastilles de 44 (et non 46), rayon 8,
   texte Medium 12/18 (-0.12px), 5px entre deux pastilles. */
.tdb-bo-mobile-menu__nav .tdb-bo-sidebar,
.tdb-bo-mobile-menu__nav .tdb-bo-sidebar .tdb-bo-sidebar__submenu--isolee {
    gap: 5px;
}

.tdb-bo-mobile-menu__nav .tdb-bo-sidebar .tdb-bo-sidebar__group > summary.tdb-bo-sidebar__link,
.tdb-bo-mobile-menu__nav .tdb-bo-sidebar .tdb-bo-sidebar__submenu--isolee li > a,
.tdb-bo-mobile-menu__nav .tdb-bo-sidebar .tdb-bo-sidebar__submenu--isolee li.is-active > a {
    min-height: 44px;
    border-radius: 8px;
    font-size: 12px;
    letter-spacing: -0.12px;
}

/* MOD-IA 2026-09-22 : menu hors-canevas mobile — ce qui ENTOURE les pastilles,
   ramené sur « SP - menu BO » (473:7936). Les pastilles avaient bien changé,
   mais le panneau gardait l'ancien habillage, d'où l'impression que le mobile
   n'avait pas bougé :

     - le cadre gris (#F7F7F7, padding 10) du menu latéral desktop était repris
       tel quel ; la maquette mobile pose les pastilles directement sur le fond
       blanc, sur 360 de large (15px de marge) ;
     - le filet de séparation courait sur toute la largeur de l'écran en
       #ECECEC ; la maquette le pose sur les 360 du menu, en #7C7C7C, avec 25px
       au-dessus et au-dessous ;
     - l'écart sous le bandeau noir est de 40px (et non --space-lg) ;
     - les boutons d'action étaient blancs à filet orange, texte centré en 14 ;
       la maquette les veut ORANGE PLEIN, rayon 8, texte noir Medium 12/18
       aligné à gauche avec un retrait de 20, 10px entre deux boutons.

   Les règles d'origine (plus haut, « Menu hors-canevas du back-office mobile »)
   ne sont pas effacées : ce bloc les surcharge. */
.tdb-bo-mobile-menu__nav {
    padding: 40px 15px 25px;
    border-bottom: 0;
}

.tdb-bo-mobile-menu__nav .tdb-bo-sidebar {
    position: static;
    padding: 0;
    background: transparent;
    border-radius: 0;
}

.tdb-bo-mobile-menu__actions {
    gap: 10px;
    margin-inline: 15px;
    padding: 25px 0;
    border-top: 1px solid var( --color-text-muted );
}

.tdb-bo-mobile-menu__btn {
    justify-content: flex-start;
    text-align: left;
    padding: 0 20px;
    border: 0;
    border-radius: 8px;
    background: var( --color-primary );
    color: #000;
    font-size: 12px;
    line-height: 18px;
    font-weight: var( --weight-medium );
    letter-spacing: -0.12px;
    cursor: pointer;
}

/* MOD-IA 2026-09-28 : détail des commandes côté client (inc/commandes-client.php).
   Colonne « Bons » de la liste des commandes, bloc « Vos bons » et fiches de
   contact des commerçants sous le tableau d'une commande. Les tableaux
   héritent déjà de `.tdb-bo-endpoint table` ; seuls les compléments sont ici. */
.tdb-commande-resume {
    margin: 0;
    padding: 0;
    list-style: none;
}

.tdb-commande-resume li + li {
    margin-top: 4px;
}

.tdb-commande-resume__qte {
    color: var( --color-text-muted );
}

.tdb-commande-resume__produit,
.tdb-commande-bons__note {
    display: block;
    color: var( --color-text-muted );
    font-size: 12px;
    line-height: 18px;
}

.tdb-commande-bons,
.tdb-commande-commercants {
    margin-top: var( --space-xl );
}

/* MOD-IA 2026-09-28 : même taille que les titres WooCommerce de la page
   (« Détails de la commande », « Adresse de facturation » : 24px). */
.tdb-commande-bons__titre {
    margin: 0 0 var( --space-xs );
    font-size: 24px;
}

.tdb-commande-bons__code {
    font-variant-numeric: tabular-nums;
    letter-spacing: 0.02em;
}

.tdb-commande-bons__vide {
    padding: var( --space-md );
    background: #FAFAFA;
    border: 1px solid var( --color-border );
    border-radius: var( --radius-sm );
}

.tdb-commande-commercants__grille {
    display: grid;
    grid-template-columns: repeat( auto-fill, minmax( 240px, 1fr ) );
    gap: var( --space-md );
}

.tdb-commande-commercant {
    padding: var( --space-md ) var( --space-lg );
    background: #fff;
    border: 1px solid var( --color-border );
    border-radius: var( --radius-card );
    font-size: 14px;
    overflow-wrap: anywhere;
}

.tdb-commande-commercant__nom {
    margin: 0 0 var( --space-xs );
    font-size: 16px;
}

.tdb-commande-commercant__adresse {
    margin: 0 0 var( --space-xs );
}

.tdb-commande-commercant__contacts {
    margin: 0 0 var( --space-sm );
    padding: 0;
    list-style: none;
}

.tdb-commande-commercant__contacts a,
.tdb-commande-commercant__fiche {
    color: var( --color-primary );
    text-decoration: none;
}

.tdb-commande-commercant__contacts a:hover,
.tdb-commande-commercant__fiche:hover {
    text-decoration: underline;
}

.tdb-commande-commercant__fiche {
    font-weight: 700;
}

/* MOD-IA 2026-09-28 : alignement des tableaux de commande côté client
   (retour client du 28.09.2026 : « faire un meilleur alignement »).

   PassVal charge sur toutes les pages gestion_bons.css, qui pose
   `td { text-align: center; }` sans portée. Les en-têtes, eux, sont alignés à
   gauche par `:is( .tdb-bo-endpoint, .woocommerce-order ) table th` : chaque valeur flottait au milieu
   de sa colonne, loin de son titre, et les métas de ligne (« Pour », « De la
   part de », « Message ») avaient leur libellé à gauche et leur valeur au
   centre. On réaligne à gauche, montants à droite, cellules centrées
   verticalement. Portée limitée aux tableaux de commande pour ne pas toucher
   les listes de PassVal.

   MOD-IA 2026-09-28 : étendu à la page de confirmation de commande
   (/checkout/order-received/, conteneur .woocommerce-order de
   checkout/thankyou.php) — même tableau, même défaut d'alignement. */
:is( .tdb-bo-endpoint, .woocommerce-order ) .woocommerce-orders-table th,
:is( .tdb-bo-endpoint, .woocommerce-order ) .woocommerce-orders-table td,
:is( .tdb-bo-endpoint, .woocommerce-order ) .woocommerce-table--order-details th,
:is( .tdb-bo-endpoint, .woocommerce-order ) .woocommerce-table--order-details td,
:is( .tdb-bo-endpoint, .woocommerce-order ) .tdb-commande-bons__table td {
    text-align: left;
    vertical-align: middle;
}

/* Numéro de commande : WooCommerce le rend en <th> de ligne, qui héritait du
   fond gris des en-têtes de colonne. */
:is( .tdb-bo-endpoint, .woocommerce-order ) .woocommerce-orders-table tbody th {
    background: #fff;
    border-bottom: 1px solid var( --color-border );
    white-space: nowrap;
}

:is( .tdb-bo-endpoint, .woocommerce-order ) .woocommerce-orders-table tbody tr:last-child th {
    border-bottom: 0;
}

/* Montants et bouton d'action alignés à droite, titres compris. */
:is( .tdb-bo-endpoint, .woocommerce-order ) .woocommerce-orders-table .woocommerce-orders-table__header-order-total,
:is( .tdb-bo-endpoint, .woocommerce-order ) .woocommerce-orders-table .woocommerce-orders-table__cell-order-total,
:is( .tdb-bo-endpoint, .woocommerce-order ) .woocommerce-orders-table .woocommerce-orders-table__header-order-actions,
:is( .tdb-bo-endpoint, .woocommerce-order ) .woocommerce-orders-table .woocommerce-orders-table__cell-order-actions,
:is( .tdb-bo-endpoint, .woocommerce-order ) .woocommerce-table--order-details .product-total,
:is( .tdb-bo-endpoint, .woocommerce-order ) .woocommerce-table--order-details tfoot td {
    text-align: right;
}

:is( .tdb-bo-endpoint, .woocommerce-order ) .woocommerce-orders-table__cell-order-date,
:is( .tdb-bo-endpoint, .woocommerce-order ) .woocommerce-orders-table__cell-order-total {
    white-space: nowrap;
}

/* Métas d'une ligne de commande : libellé et valeur sur la même ligne. */
:is( .tdb-bo-endpoint, .woocommerce-order ) .wc-item-meta {
    margin: var( --space-2xs ) 0 0;
    padding: 0;
    list-style: none;
    font-size: 13px;
    color: var( --color-text-muted );
}

:is( .tdb-bo-endpoint, .woocommerce-order ) .wc-item-meta li {
    display: flex;
    gap: var( --space-2xs );
    text-align: left;
}

:is( .tdb-bo-endpoint, .woocommerce-order ) .wc-item-meta li strong {
    flex: none;
    color: var( --color-text );
}

:is( .tdb-bo-endpoint, .woocommerce-order ) .wc-item-meta li p {
    margin: 0;
    text-align: left;
}

/* Tableau « Vos bons » : bouton PDF à droite. */
:is( .tdb-bo-endpoint, .woocommerce-order ) .tdb-commande-bons__table td:last-child {
    text-align: right;
}

/* Vue empilée (< 768px) : WooCommerce pose `libellé : valeur` avec
   text-align:right sur la cellule ; la règle gauche ci-dessus ne doit pas
   s'y appliquer. */
@media ( max-width: 768px ) {
    :is( .tdb-bo-endpoint, .woocommerce-order ) .shop_table_responsive tbody td,
    :is( .tdb-bo-endpoint, .woocommerce-order ) .shop_table_responsive tbody th {
        text-align: right !important;
    }
}

/* ==========================================================================
   MOD-IA 2026-09-29 : page « À propos » (page-a-propos*.php,
   template-parts/a-propos/). Trois modèles partagent les mêmes sections :
   .tdb-apropos--editorial (défaut), --bandeau et --epure. Le titre de page
   (H1 orange + filet) vient de .tdb-compte-form__title, comme FAQ et Contact.
   ========================================================================== */
.tdb-apropos-section {
    margin-top: var( --space-3xl );
}

.tdb-apropos-section__titre {
    font-size: var( --text-h2-size );
    line-height: var( --text-h2-lh );
    margin: 0 0 var( --space-lg );
}

/* Accroche : les passages en gras de l'éditeur passent en orange. */
.tdb-apropos__accroche {
    font-size: var( --text-h1-size );
    line-height: var( --text-h1-lh );
    font-weight: var( --weight-medium );
    margin: 0 0 var( --space-lg );
}

.tdb-apropos__accroche strong,
.tdb-apropos-partage__titre strong {
    color: var( --color-primary );
    font-weight: var( --weight-semibold );
}

.tdb-apropos__texte p {
    margin: 0 0 var( --space-md );
}

.tdb-apropos__texte > :last-child {
    margin-bottom: 0;
}

.tdb-apropos__texte a {
    color: var( --color-text );
    text-decoration: underline;
    text-decoration-color: var( --color-primary );
    text-underline-offset: 3px;
}

/* ---------- Introduction ---------- */
.tdb-apropos-intro--editorial {
    display: grid;
    grid-template-columns: minmax( 0, 1fr ) minmax( 0, 1fr );
    gap: var( --space-3xl );
    align-items: center;
}

.tdb-apropos-mosaique {
    display: grid;
    grid-template-columns: repeat( 3, 1fr );
    gap: var( --space-sm );
    padding-bottom: var( --space-lg );
}

.tdb-apropos-mosaique img {
    width: 100%;
    aspect-ratio: 1;
    object-fit: cover;
    border-radius: var( --radius-card );
}

/* Décalage vertical de la colonne du milieu : casse la grille trop sage. */
.tdb-apropos-mosaique img:nth-child( 3n + 2 ) {
    transform: translateY( var( --space-lg ) );
}

/* ---------- Valeurs ---------- */
.tdb-apropos-valeurs__liste {
    list-style: none;
    margin: 0;
    padding: 0;
    display: grid;
    grid-template-columns: repeat( 3, minmax( 0, 1fr ) );
    gap: var( --space-lg );
}

.tdb-apropos-valeurs__item {
    background: var( --color-surface-muted );
    border-radius: var( --radius-card );
    padding: var( --space-xl );
}

.tdb-apropos-valeurs__numero {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 40px;
    height: 40px;
    border-radius: var( --radius-sm );
    background: var( --color-primary );
    color: var( --color-ink );
    font-weight: var( --weight-semibold );
    margin-bottom: var( --space-lg );
}

.tdb-apropos-valeurs__titre {
    font-size: var( --text-h3-size );
    line-height: var( --text-h3-lh );
    margin: 0 0 var( --space-xs );
}

.tdb-apropos-valeurs__texte {
    margin: 0;
    color: var( --color-text-muted );
}

/* ---------- Chiffres ---------- */
.tdb-apropos-chiffres__liste {
    display: grid;
    grid-template-columns: repeat( auto-fit, minmax( 180px, 1fr ) );
    gap: var( --space-lg );
    margin: 0;
}

.tdb-apropos-chiffres__valeur {
    font-size: var( --text-hero-size );
    line-height: var( --text-hero-lh );
    font-weight: var( --weight-semibold );
    letter-spacing: var( --tracking-tight );
}

.tdb-apropos-chiffres__suffixe {
    color: var( --color-primary );
}

.tdb-apropos-chiffres__libelle {
    margin: var( --space-xs ) 0 0;
}

/* Éditorial : bandeau sombre pleine largeur. */
.tdb-apropos-chiffres--editorial {
    background: var( --color-ink );
    color: #fff;
    padding-block: var( --space-3xl );
}

.tdb-apropos-chiffres--editorial .tdb-apropos-section__titre {
    color: #fff;
}

.tdb-apropos-chiffres--editorial .tdb-apropos-chiffres__valeur {
    color: var( --color-primary );
}

.tdb-apropos-chiffres--editorial .tdb-apropos-chiffres__libelle {
    color: rgba( 255, 255, 255, .75 );
}

/* Bandeau photo : cartes grises. */
.tdb-apropos-chiffres--bandeau .tdb-apropos-chiffres__item {
    background: var( --color-surface-muted );
    border-radius: var( --radius-card );
    padding: var( --space-xl );
}

/* Épuré : chiffres en ligne séparés par un filet orange. */
.tdb-apropos-chiffres--epure .tdb-apropos-chiffres__item {
    border-left: 2px solid var( --color-primary );
    padding-left: var( --space-md );
}

.tdb-apropos-chiffres--epure .tdb-apropos-chiffres__valeur {
    font-size: var( --text-h1-home-size );
    line-height: var( --text-h1-home-lh );
}

.tdb-apropos-chiffres--epure .tdb-apropos-chiffres__libelle {
    color: var( --color-text-muted );
}

/* ---------- Questions ---------- */
.tdb-apropos-questions__grille {
    display: grid;
    grid-template-columns: repeat( 2, minmax( 0, 1fr ) );
    gap: var( --space-lg );
}

.tdb-apropos-questions__carte {
    display: flex;
    flex-direction: column;
    gap: var( --space-lg );
    border: 1px solid var( --color-border );
    border-radius: var( --radius-card );
    padding: var( --space-2xl );
}

.tdb-apropos-questions__carte .tdb-apropos__texte {
    flex: 1;
}

.tdb-apropos-questions__titre {
    font-size: var( --text-h2-size );
    line-height: var( --text-h2-lh );
    margin: 0;
}

.tdb-apropos-questions--epure .tdb-accordion__panel > :last-child {
    margin-bottom: 0;
}

/* ---------- Galerie ---------- */
.tdb-apropos-galerie {
    display: grid;
    grid-template-columns: repeat( auto-fill, minmax( 160px, 1fr ) );
    gap: var( --space-sm );
}

.tdb-apropos-galerie img {
    width: 100%;
    aspect-ratio: 1;
    object-fit: cover;
    border-radius: var( --radius-sm );
}

/* Épuré : une seule bande défilante, pas un mur de photos. */
.tdb-apropos-galerie--epure {
    display: flex;
    overflow-x: auto;
    scroll-snap-type: x mandatory;
    margin-top: var( --space-2xl );
}

.tdb-apropos-galerie--epure img {
    flex: 0 0 140px;
    scroll-snap-align: start;
}

/* ---------- Partage ---------- */
.tdb-apropos-partage {
    text-align: center;
    background: var( --color-surface-muted );
    border-radius: var( --radius-card );
    padding: var( --space-2xl ) var( --space-lg );
}

.tdb-apropos-partage__titre {
    font-size: var( --text-h2-size );
    line-height: var( --text-h2-lh );
    font-weight: var( --weight-medium );
    margin: 0 0 var( --space-lg );
}

.tdb-apropos-partage__liens {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: var( --space-sm );
}

.tdb-apropos-partage__lien {
    display: inline-flex;
    align-items: center;
    gap: var( --space-xs );
    height: 46px;
    padding: 0 var( --space-lg );
    border-radius: var( --radius-sm );
    background: var( --color-surface );
    border: 1px solid var( --color-border );
    color: var( --color-text );
    font-size: var( --text-button-size );
    font-weight: var( --weight-medium );
    text-decoration: none;
    transition: border-color var( --duration-tdb ) var( --ease-tdb );
}

.tdb-apropos-partage__lien:hover,
.tdb-apropos-partage__lien:focus-visible {
    border-color: var( --color-primary );
}

/* Les pictos sociaux sont blancs (pied de page sombre) : on les fonce ici. */
.tdb-apropos-partage__lien img {
    filter: brightness( 0 );
}

/* ---------- Modèle « Bandeau photo » ---------- */
.tdb-apropos-bandeau {
    position: relative;
    min-height: 560px;
    display: flex;
    align-items: flex-end;
    padding-block: var( --space-3xl );
    background: var( --color-ink );
    overflow: hidden;
}

.tdb-apropos-bandeau__photo {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: cover;
}

.tdb-apropos-bandeau::after {
    content: "";
    position: absolute;
    inset: 0;
    background: linear-gradient( 180deg, rgba( 33, 33, 33, 0 ) 30%, rgba( 33, 33, 33, .6 ) 100% );
}

.tdb-apropos-bandeau__inner {
    position: relative;
    z-index: 1;
    width: 100%;
}

.tdb-apropos-bandeau__carte {
    max-width: 640px;
    background: rgba( 255, 255, 255, .9 );
    border-radius: var( --radius-card );
    padding: var( --space-2xl );
}

/* La pastille du héros est prévue pour un fond sombre : version claire ici. */
.tdb-apropos-bandeau .hero__pill {
    background: var( --color-surface );
    border-color: var( --color-border );
    color: var( --color-text );
    margin-bottom: var( --space-lg );
}

/* ---------- Modèle « Épuré » ---------- */
.tdb-apropos__colonne {
    max-width: calc( 760px + 48px );
}

.tdb-apropos--epure .tdb-apropos-valeurs__liste {
    grid-template-columns: 1fr;
    gap: 0;
}

.tdb-apropos--epure .tdb-apropos-valeurs__item {
    display: grid;
    grid-template-columns: 40px 1fr;
    column-gap: var( --space-md );
    background: none;
    border-radius: 0;
    padding: var( --space-lg ) 0;
    border-top: 1px solid var( --color-border );
}

.tdb-apropos--epure .tdb-apropos-valeurs__numero {
    grid-row: span 2;
    margin: 0;
}

/* ---------- Tablette / mobile ---------- */
@media ( max-width: 959px ) {
    .tdb-apropos-intro--editorial {
        grid-template-columns: 1fr;
        gap: var( --space-2xl );
    }

    .tdb-apropos-valeurs__liste,
    .tdb-apropos-questions__grille {
        grid-template-columns: 1fr;
    }
}

@media ( max-width: 767px ) {
    .tdb-apropos-section {
        margin-top: var( --space-2xl );
    }

    .tdb-apropos__accroche {
        font-size: var( --text-h1-home-size-mobile );
        line-height: var( --text-h1-home-lh-mobile );
    }

    .tdb-apropos-section__titre,
    .tdb-apropos-questions__titre,
    .tdb-apropos-partage__titre {
        font-size: var( --text-h2-size-mobile );
        line-height: var( --text-h2-lh-mobile );
    }

    .tdb-apropos-chiffres__valeur {
        font-size: var( --text-hero-size-mobile );
        line-height: var( --text-hero-lh-mobile );
    }

    .tdb-apropos-chiffres--editorial {
        padding-block: var( --space-2xl );
    }

    .tdb-apropos-questions__carte,
    .tdb-apropos-bandeau__carte {
        padding: var( --space-lg );
    }

    .tdb-apropos-bandeau {
        min-height: 480px;
        padding-block: var( --space-lg );
    }

    /* Le bandeau colle à l'en-tête : on retire l'espace haut mobile de .site-main. */
    .site-main.tdb-apropos--bandeau {
        padding-top: 0;
    }

    .tdb-apropos-mosaique img:nth-child( 3n + 2 ) {
        transform: none;
    }
}

/* ==========================================================================
   MOD-IA 2026-09-29 : page « Contacter le support » (page-contact.php).
   Aucune règle ne visait .tdb-contact : le formulaire Contact Form 7 sortait
   brut (champs natifs étroits, bouton gris) et les coordonnées s'empilaient
   dessous. Mise en page en deux colonnes — formulaire dans une carte grise,
   coordonnées + mini-carte à droite — et champs CF7 habillés avec les mêmes
   valeurs que .tdb-champ / .tdb-compte-form (60px, filet gris info, rayon 10).
   ========================================================================== */
.tdb-contact {
    display: grid;
    grid-template-columns: minmax( 0, 1fr ) minmax( 0, 420px );
    gap: var( --space-2xl );
    align-items: start;
}

.tdb-contact__form {
    background: var( --color-surface-muted );
    border-radius: var( --radius-card );
    padding: var( --space-2xl );
}

.tdb-contact__form > :first-child {
    margin-top: 0;
}

.tdb-contact__form > :last-child {
    margin-bottom: 0;
}

/* Champs CF7 : <p><label>Libellé<br><span class="wpcf7-form-control-wrap">…</span></label></p>.
   Le dernier enfant du <form> est la zone de réponse (masquée au repos) :
   c'est donc le dernier <p>, celui du bouton, qui perd sa marge. */
.tdb-contact__form .wpcf7-form p {
    margin: 0 0 var( --space-lg );
}

.tdb-contact__form .wpcf7-form p:last-of-type {
    margin-bottom: 0;
}

.tdb-contact__form .wpcf7-form label {
    display: flex;
    flex-direction: column;
    gap: 10px;
    font-size: var( --text-card-desc-size );
    line-height: var( --text-card-desc-lh );
    letter-spacing: var( --tracking-tight );
    font-weight: var( --weight-medium );
    color: var( --color-text );
}

.tdb-contact__form .wpcf7-form label br {
    display: none;
}

.tdb-contact__form .wpcf7-form-control-wrap {
    display: block;
}

.tdb-contact__form .wpcf7-form input:is( [type="text"], [type="email"], [type="tel"], [type="url"], [type="number"], [type="date"] ),
.tdb-contact__form .wpcf7-form select,
.tdb-contact__form .wpcf7-form textarea {
    display: block;
    width: 100%;
    height: 60px;
    border: 1px solid var( --color-text-muted );
    border-radius: var( --radius-sm );
    padding-inline: var( --space-md );
    font-family: var( --font-body );
    font-size: var( --text-body-size );
    font-weight: var( --weight-regular );
    color: var( --color-text );
    background: var( --color-surface );
    transition: border-color var( --duration-tdb-snap ) var( --ease-tdb );
}

.tdb-contact__form .wpcf7-form textarea {
    height: 180px;
    padding-block: var( --space-sm );
    line-height: var( --text-body-lh );
    resize: vertical;
}

.tdb-contact__form .wpcf7-form :is( input, select, textarea ):hover {
    border-color: var( --color-text );
}

.tdb-contact__form .wpcf7-form :is( input, select, textarea ):focus {
    border-color: var( --color-primary );
    outline: none;
}

.tdb-contact__form .wpcf7-form :is( input, select, textarea ):focus-visible {
    outline: 2px solid var( --color-primary );
    outline-offset: 1px;
}

/* Bouton d'envoi : mêmes valeurs que .btn.btn--primary (ui/01-boutons.css) —
   CF7 génère son <input type="submit"> sans nos classes. */
.tdb-contact__form .wpcf7-form input[type="submit"] {
    height: 46px;
    padding: 0 var( --space-lg );
    border: 0;
    border-radius: var( --radius-sm );
    background: var( --color-primary );
    color: #000;
    font-family: var( --font-heading );
    font-size: var( --text-button-size );
    line-height: var( --text-button-lh );
    font-weight: var( --weight-medium );
    letter-spacing: var( --tracking-tight );
    cursor: pointer;
    appearance: none;
    transition: background-color var( --duration-tdb ) var( --ease-tdb ), color var( --duration-tdb ) var( --ease-tdb );
}

.tdb-contact__form .wpcf7-form input[type="submit"]:hover {
    background: var( --color-ink-strong );
    color: #fff;
}

.tdb-contact__form .wpcf7-form input[type="submit"]:disabled {
    opacity: .6;
    cursor: wait;
}

/* Erreurs et message de retour de CF7. */
.tdb-contact__form .wpcf7-form .wpcf7-not-valid {
    border-color: var( --color-status-expired-strong );
}

.tdb-contact__form .wpcf7-not-valid-tip {
    margin-top: 6px;
    font-size: 13px;
    color: var( --color-status-expired-text );
}

.tdb-contact__form .wpcf7 form .wpcf7-response-output {
    margin: var( --space-lg ) 0 0;
    padding: var( --space-sm ) var( --space-md );
    border: 1px solid var( --color-border );
    border-radius: var( --radius-sm );
    background: var( --color-surface );
    font-size: var( --text-card-desc-size );
    line-height: var( --text-card-desc-lh );
}

.tdb-contact__form .wpcf7 form.sent .wpcf7-response-output {
    border-color: var( --color-status-validated-line );
    background: var( --color-status-validated-surface );
    color: var( --color-status-validated-strong );
}

.tdb-contact__form .wpcf7 form:is( .invalid, .unaccepted, .payment-required, .failed, .aborted, .spam ) .wpcf7-response-output {
    border-color: var( --color-status-expired-line );
    background: var( --color-status-expired-surface );
    color: var( --color-status-expired-text );
}

/* Coordonnées. */
.tdb-contact__infos {
    border: 1px solid var( --color-border );
    border-radius: var( --radius-card );
    padding: var( --space-xl );
}

.tdb-contact__infos h2 {
    font-size: var( --text-h2-size );
    line-height: var( --text-h2-lh );
    margin: 0 0 var( --space-md );
}

.tdb-contact__infos p {
    margin: 0 0 var( --space-xs );
}

.tdb-contact__infos .tdb-contact__adresse {
    margin-bottom: var( --space-md );
}

.tdb-contact__infos a {
    color: var( --color-text );
    font-weight: var( --weight-medium );
    text-decoration: none;
    transition: color var( --duration-tdb-snap ) var( --ease-tdb );
}

.tdb-contact__infos a:hover {
    color: var( --color-primary );
}

/* Mini-carte : même traitement que .tdb-commercant-map (fiche commerçant). */
.tdb-contact__carte {
    height: 260px;
    margin-top: var( --space-lg );
    border-radius: var( --radius-sm );
    overflow: hidden;
    background: var( --color-surface-muted );
}

.tdb-contact__carte .leaflet-tile-pane {
    filter: grayscale( 1 ) contrast( .9 ) brightness( 1.05 );
}

.tdb-contact__carte .leaflet-control-attribution {
    font-size: 10px;
    background: rgba( 255, 255, 255, .7 );
}

@media ( max-width: 991px ) {
    .tdb-contact {
        grid-template-columns: minmax( 0, 1fr );
        gap: var( --space-lg );
    }
}

@media ( max-width: 767px ) {
    .tdb-contact__form,
    .tdb-contact__infos {
        padding: var( --space-lg );
    }
}
