/*
 * Écrans de compte — direction validée le 2026-08-10.
 *
 * Orange d'origine (#FF7C25), variante à bandeaux, logo sans le point.
 *
 * Ce fichier ne touche QUE les écrans « mon compte » et l'inscription. Il ne
 * redéfinit rien globalement : le thème garde la main partout ailleurs, et une
 * mise à jour de Blonwe n'entrera pas en conflit avec ce qui suit.
 *
 * Le parti pris : le thème pose des blocs gris interchangeables. On leur rend
 * une hiérarchie — un bandeau qui nomme l'écran, des cartes qui respirent, un
 * seul accent, et des chiffres alignés. Rien de décoratif qui n'encode pas une
 * information.
 */

:root {
    --tz-orange: #ff7c25;
    --tz-orange-sombre: #d95f10;
    --tz-orange-voile: #fff4ec;
    --tz-encre: #1c1917;
    --tz-encre-douce: #57534e;
    /* Un gris légèrement chaud, tiré vers l'accent : un gris pur à côté d'un
       orange lit comme un oubli, pas comme un choix. */
    --tz-trait: #e7e2dd;
    --tz-fond: #fffdfb;
    --tz-rayon: 12px;
}

/*
 * ⚠️ LA PALETTE SOMBRE A ÉTÉ RETIRÉE. Elle rendait le site ILLISIBLE.
 *
 * Signalé : « en mode sombre, les écritures des produits ne se visualisent pas
 * bien ». Mesuré sur la boutique, navigateur en `prefers-color-scheme: dark` :
 *
 *     prix       rgb(245, 241, 237)  sur  rgb(255, 255, 255)   →  1,12:1
 *
 * Il en faut 4,5. À 1,12, ce n'est pas « moins lisible », c'est blanc sur
 * blanc.
 *
 * Sa raison : je basculais MES jetons — `--tz-encre` passait au clair,
 * `--tz-fond` au sombre — mais le fond des cartes produit n'est pas peint par
 * `--tz-fond`. Il vient du thème, et le thème n'a pas de mode sombre. Je
 * changeais donc l'encre sans changer le papier.
 *
 * Un thème sombre n'est pas une inversion de deux variables : il faut tenir
 * CHAQUE surface — cartes, bordures, ombres, images sur fond blanc, logos.
 * Le thème en compte des centaines que je ne contrôle pas. En tenir la moitié
 * est pire que n'en tenir aucune : le visiteur au mode sombre voyait un site
 * en partie effacé, quand celui en mode clair voyait un site intact.
 *
 * Le site garde donc UNE seule apparence, comme demandé. Ce n'est pas un
 * renoncement définitif : un vrai mode sombre est un chantier à part, qui
 * commence par les surfaces du thème et non par mes jetons.
 *
 * Les blocs `prefers-color-scheme` qui subsistent plus bas ne touchent qu'à
 * des composants dont NOUS peignons le fond — là, les deux moitiés sont
 * tenues ensemble.
 */

/* ------------------------------------------------------------------ */
/* Le bandeau qui nomme l'écran                                        */
/* ------------------------------------------------------------------ */

.woocommerce-account .woocommerce-MyAccount-content > h2:first-child,
.woocommerce-account .woocommerce-MyAccount-content > h3:first-child {
    margin: 0 0 1.5rem;
    padding: 0.85rem 1.15rem;
    background: var(--tz-orange);
    color: #fff;
    border-radius: var(--tz-rayon) var(--tz-rayon) 0 0;
    font-size: 1.05rem;
    letter-spacing: 0.01em;
    text-wrap: balance;
}

/* ------------------------------------------------------------------ */
/* La navigation : des onglets qui disent où l'on est                  */
/* ------------------------------------------------------------------ */

.woocommerce-account .woocommerce-MyAccount-navigation ul {
    display: flex;
    flex-wrap: wrap;
    gap: 0.35rem;
    margin: 0 0 1.75rem;
    padding: 0;
    list-style: none;
    border-bottom: 2px solid var(--tz-trait);
}

.woocommerce-account .woocommerce-MyAccount-navigation li {
    margin: 0;
    border: 0;
}

.woocommerce-account .woocommerce-MyAccount-navigation li a {
    display: block;
    padding: 0.6rem 1rem;
    color: var(--tz-encre-douce);
    text-decoration: none;
    border-bottom: 3px solid transparent;
    margin-bottom: -2px;
    transition: color 0.15s, border-color 0.15s;
}

.woocommerce-account .woocommerce-MyAccount-navigation li a:hover,
.woocommerce-account .woocommerce-MyAccount-navigation li a:focus-visible {
    color: var(--tz-orange-sombre);
}

.woocommerce-account .woocommerce-MyAccount-navigation li.is-active a {
    color: var(--tz-encre);
    font-weight: 600;
    border-bottom-color: var(--tz-orange);
}

/* ------------------------------------------------------------------ */
/* Le rappel de vérification — il doit se voir, pas alarmer            */
/* ------------------------------------------------------------------ */

.tizzle-preuve-attendue {
    background: var(--tz-orange-voile) !important;
    border-left: 4px solid var(--tz-orange) !important;
    border-radius: 0 var(--tz-rayon) var(--tz-rayon) 0;
    padding: 1.1rem 1.25rem !important;
}

.tizzle-preuve-attendue::before {
    display: none !important; /* l'icône du thème double le bandeau */
}

.tizzle-preuve-saisie {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.6rem;
    margin-top: 0.85rem;
}

.tizzle-preuve-saisie label {
    flex-basis: 100%;
    font-size: 0.85rem;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--tz-encre-douce);
}

.tizzle-preuve-saisie input {
    /* Un code se lit chiffre par chiffre : on l'écarte et on l'aligne. */
    font-variant-numeric: tabular-nums;
    letter-spacing: 0.35em;
    font-size: 1.15rem;
    width: 9ch;
    padding: 0.5rem 0.65rem;
    border: 1px solid var(--tz-trait);
    border-radius: 8px;
}

.tizzle-preuve-saisie input:focus-visible {
    outline: 2px solid var(--tz-orange);
    outline-offset: 1px;
}

.tizzle-preuve-retour:empty {
    display: none;
}

/* ------------------------------------------------------------------ */
/* Les commandes : des chiffres qu'on peut comparer d'un coup d'œil    */
/* ------------------------------------------------------------------ */

.woocommerce-account .woocommerce-orders-table td,
.woocommerce-account .woocommerce-orders-table th {
    border-color: var(--tz-trait);
}

.woocommerce-account .woocommerce-orders-table__cell-order-total,
.woocommerce-account .woocommerce-orders-table__cell-order-number {
    font-variant-numeric: tabular-nums;
}

.woocommerce-account .woocommerce-orders-table__cell-order-status {
    font-size: 0.85rem;
    font-weight: 600;
}

/* Un tableau large se déroule dans sa boîte, jamais la page entière. */
.woocommerce-account .woocommerce-MyAccount-content .woocommerce-orders-table {
    display: block;
    overflow-x: auto;
}

/* ------------------------------------------------------------------ */
/* Le formulaire d'inscription et de connexion                         */
/* ------------------------------------------------------------------ */

.woocommerce-form-register .tizzle-champ,
.woocommerce-form-login .form-row {
    margin-bottom: 1.15rem;
}

.woocommerce-form-register label,
.woocommerce-form-login label {
    display: block;
    margin-bottom: 0.35rem;
    font-size: 0.9rem;
    color: var(--tz-encre-douce);
}

.woocommerce-form-register .tizzle-duo {
    display: flex;
    gap: 0.5rem;
    align-items: stretch;
}

.woocommerce-account form.woocommerce-form-register button[name="register"],
.woocommerce-account form.woocommerce-form-login button[name="login"] {
    background: var(--tz-orange) !important;
    border-color: var(--tz-orange) !important;
    color: #fff !important;
    font-weight: 600;
    border-radius: 8px;
    padding: 0.7rem 1.4rem;
}

.woocommerce-account form.woocommerce-form-register button[name="register"]:hover,
.woocommerce-account form.woocommerce-form-login button[name="login"]:hover {
    background: var(--tz-orange-sombre) !important;
    border-color: var(--tz-orange-sombre) !important;
}

.woocommerce-account form.woocommerce-form-register button[name="register"]:focus-visible,
.woocommerce-account form.woocommerce-form-login button[name="login"]:focus-visible {
    outline: 2px solid var(--tz-encre);
    outline-offset: 2px;
}

/* ------------------------------------------------------------------ */
/* Panier et paiement : les écrans où l'on demande de l'argent         */
/* ------------------------------------------------------------------ */

/*
 * Le principe est le même qu'ailleurs, mais l'enjeu diffère : ici, la personne
 * vérifie des montants avant de s'engager. Tout ce qui se compare s'aligne, et
 * le total — le seul chiffre qui décide — se distingue des autres.
 */

/*
 * Le balisage visé est celui LU sur la page avec un panier rempli — pas celui
 * de WooCommerce par défaut, que ce thème n'utilise pas :
 *
 *   PANIER    form.woocommerce-cart-form › table.wpr-shop-table.shop_table
 *             › tr.cart_item ;  total : tr.order-total
 *   PAIEMENT  form.checkout › div.order-review-wrapper
 *             › div.woocommerce-checkout-review-order ;  total : tfoot tr.order-total
 *
 * Trois fois aujourd'hui j'ai écrit du style pour une structure supposée. La
 * première lecture de ces écrans a d'ailleurs porté sur un panier VIDE, et
 * n'avait donc rien trouvé du tout.
 */

/* Tout ce qui se compare s'aligne : sans ça, deux montants côte à côte ne se
   comparent pas d'un regard — ce qui est pourtant le geste du panier. */
html body table.shop_table td,
html body table.shop_table th,
html body .woocommerce-Price-amount,
html body .cart_totals td,
html body .woocommerce-checkout-review-order td {
    font-variant-numeric: tabular-nums;
}

/*
 * Le TOTAL est le seul chiffre qui décide. Il doit se distinguer des lignes
 * qui l'ont produit — sinon l'œil doit relire toute la colonne pour le trouver.
 */
html body tr.order-total td,
html body tr.order-total th {
    font-size: 1.15rem !important;
    font-weight: 700 !important;
    color: var(--tz-encre) !important;
    border-top: 2px solid var(--tz-orange) !important;
    padding-top: 0.9rem !important;
}

html body tr.order-total .woocommerce-Price-amount {
    color: var(--tz-encre) !important;
    font-size: 1.15rem !important;
}

/* Un tableau de panier est large par nature : il se déroule dans sa boîte,
   jamais dans la page — un défilement latéral du corps rend la navigation
   imprévisible sur un téléphone. */
html body form.woocommerce-cart-form,
html body div.woocommerce-checkout-review-order,
html body div.order-review-wrapper {
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
}

html body table.shop_table {
    border-color: var(--tz-trait) !important;
}

html body table.shop_table th {
    font-size: 0.85rem !important;
    text-transform: uppercase !important;
    letter-spacing: 0.05em !important;
    color: var(--tz-encre-douce) !important;
}

/* Une ligne de panier se sépare de la suivante : sans trait, les colonnes de
   deux articles se lisent comme une seule. */
html body tr.cart_item td {
    border-bottom: 1px solid var(--tz-trait) !important;
    vertical-align: middle !important;
}

/* La quantité est un champ qu'on modifie souvent : il doit être atteignable
   au pouce. 44 px est le repère habituel d'une cible tactile. */
html body input.qty {
    min-height: 44px !important;
    min-width: 64px !important;
    text-align: center !important;
    font-variant-numeric: tabular-nums !important;
    border: 1px solid var(--tz-trait) !important;
    border-radius: 8px !important;
}

/*
 * Le récapitulatif du paiement reste visible pendant qu'on remplit trente
 * champs. Sans ça, on saisit son adresse sans savoir ce qu'on paie — et le
 * doute au moment de payer coûte des commandes.
 */
@media (min-width: 992px) {
    html body div.order-review-wrapper {
        position: sticky;
        top: 1.5rem;
        align-self: start;
    }
}

/*
 * Le bouton qui engage. Un seul par écran, dans l'accent — et la spécificité
 * est ancrée sur la page, parce que le thème gagnait la cascade sur les
 * boutons de compte tant qu'elle ne l'était pas.
 */
.woocommerce-cart .checkout-button,
.woocommerce-checkout #place_order {
    background: var(--tz-orange) !important;
    border-color: var(--tz-orange) !important;
    color: #fff !important;
    font-weight: 600;
    border-radius: 8px;
    padding: 0.8rem 1.6rem;
}

.woocommerce-cart .checkout-button:hover,
.woocommerce-checkout #place_order:hover {
    background: var(--tz-orange-sombre) !important;
    border-color: var(--tz-orange-sombre) !important;
}

.woocommerce-cart .checkout-button:focus-visible,
.woocommerce-checkout #place_order:focus-visible {
    outline: 2px solid var(--tz-encre);
    outline-offset: 2px;
}

/*
 * Le message d'une porte fermée — identifiant non prouvé — doit se lire comme
 * une consigne, pas comme une panne. Il porte un lien vers « mon compte » ;
 * c'est ce lien qui doit ressortir, pas l'alerte.
 */
.woocommerce-cart .woocommerce-error,
.woocommerce-checkout .woocommerce-error {
    border-left: 4px solid var(--tz-orange);
    background: var(--tz-orange-voile);
    color: var(--tz-encre);
}

.woocommerce-cart .woocommerce-error a,
.woocommerce-checkout .woocommerce-error a {
    color: var(--tz-orange-sombre);
    font-weight: 600;
}

/* ------------------------------------------------------------------ */
/* Le catalogue : listes et fiches produit                             */
/* ------------------------------------------------------------------ */

/*
 * Un catalogue se parcourt en diagonale. Ce qui compte, dans l'ordre : le prix,
 * la disponibilité, puis le nom. Le thème les rend au même poids ; on leur rend
 * une hiérarchie, sans rien ajouter de décoratif.
 *
 * Prudence assumée : on ne touche NI aux images NI à la grille. Le thème gère
 * ses points de rupture, et une grille reprise à moitié casse en mobile chez
 * des gens qu'on ne verra jamais.
 */

.woocommerce ul.products li.product .price,
.woocommerce div.product p.price,
.woocommerce div.product span.price {
    font-variant-numeric: tabular-nums;
    color: var(--tz-encre);
    font-weight: 700;
}

/* Le prix barré n'est pas un prix : il ne doit pas peser autant. */
.woocommerce ul.products li.product .price del,
.woocommerce div.product p.price del {
    color: var(--tz-encre-douce);
    font-weight: 400;
    opacity: 0.75;
}

.woocommerce ul.products li.product .price ins,
.woocommerce div.product p.price ins {
    text-decoration: none;
    color: var(--tz-orange-sombre);
}

.woocommerce ul.products li.product .woocommerce-loop-product__title,
.woocommerce div.product .product_title {
    color: var(--tz-encre);
    text-wrap: balance;
}

/*
 * La disponibilité : une information d'état, donc encodée par la forme autant
 * que par le mot. Un client qui parcourt vingt fiches ne lit pas « in stock »
 * vingt fois — il repère une pastille.
 */
.woocommerce div.product .stock {
    display: inline-block;
    padding: 0.15rem 0.6rem;
    border-radius: 999px;
    font-size: 0.85rem;
    font-weight: 600;
}

.woocommerce div.product .stock.in-stock {
    background: #e8f5ec;
    color: #1b5e34;
}

.woocommerce div.product .stock.out-of-stock {
    background: #fdeaea;
    color: #a12222;
}

/* Variante sombre retirée — voir la note en tête de fichier. Ces pastilles
   peignaient bien leur fond, mais elles seraient devenues sombres sur une page
   restée claire : une poignée d'îlots sombres au milieu du blanc. */

/*
 * Le bouton d'ajout au panier. Il porte l'accent, comme les autres boutons qui
 * engagent — et la spécificité est ancrée d'emblée : sur le catalogue, le thème
 * définit ses boutons plus fortement encore qu'ailleurs.
 */
.woocommerce ul.products li.product a.add_to_cart_button,
.woocommerce div.product form.cart button.single_add_to_cart_button {
    background: var(--tz-orange) !important;
    border-color: var(--tz-orange) !important;
    color: #fff !important;
    font-weight: 600;
    border-radius: 8px;
}

.woocommerce ul.products li.product a.add_to_cart_button:hover,
.woocommerce div.product form.cart button.single_add_to_cart_button:hover {
    background: var(--tz-orange-sombre) !important;
    border-color: var(--tz-orange-sombre) !important;
}

.woocommerce ul.products li.product a.add_to_cart_button:focus-visible,
.woocommerce div.product form.cart button.single_add_to_cart_button:focus-visible {
    outline: 2px solid var(--tz-encre);
    outline-offset: 2px;
}

/* Les onglets d'une fiche : même traitement que la navigation du compte. */
.woocommerce div.product .woocommerce-tabs ul.tabs li.active a {
    color: var(--tz-encre);
    font-weight: 600;
}

.woocommerce div.product .woocommerce-tabs ul.tabs li.active {
    border-bottom-color: var(--tz-orange);
}

/* ------------------------------------------------------------------ */
/* L'espace vendeur                                                    */
/* ------------------------------------------------------------------ */

/*
 * Ce tableau de bord n'est pas une page qu'on lit : c'est un outil qu'on
 * opère, plusieurs heures par jour. La craft se déplace donc de la typographie
 * vers l'information — ce qui demande une action doit se voir sans être lu.
 *
 * On garde la structure de Dokan intacte. Refaire sa grille, c'est prendre en
 * charge à vie ses mises à jour.
 */

.dokan-dashboard .dokan-dash-sidebar ul.dokan-dashboard-menu li.active,
.dokan-dashboard .dokan-dash-sidebar ul.dokan-dashboard-menu li.dokan-common-links a:hover {
    border-left: 3px solid var(--tz-orange);
}

.dokan-dashboard .dokan-dash-sidebar ul.dokan-dashboard-menu li.active a {
    color: var(--tz-encre);
    font-weight: 600;
}

/* Tout ce qui se compare s'aligne : gains, commandes, soldes. */
.dokan-dashboard .dokan-dashboard-content td,
.dokan-dashboard .dokan-report-wrap td,
.dokan-dashboard .dokan-dashboard-content .dokan-order-total,
.dokan-dashboard .woocommerce-Price-amount {
    font-variant-numeric: tabular-nums;
}

/*
 * Les compteurs du haut. Un vendeur les regarde en diagonale : le chiffre doit
 * peser plus que son étiquette, et l'étiquette rester lisible.
 */
.dokan-dashboard .dashboard-widget .dokan-dashboard-stat span,
.dokan-dashboard .dokan-status-counts .count {
    font-size: 1.5rem;
    font-weight: 700;
    color: var(--tz-encre);
    font-variant-numeric: tabular-nums;
}

.dokan-dashboard .dashboard-widget .dokan-dashboard-stat small {
    font-size: 0.8rem;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: var(--tz-encre-douce);
}

/*
 * L'état d'une commande, encodé par la forme autant que par le mot. Un vendeur
 * qui parcourt cinquante lignes ne lit pas cinquante fois « processing » — il
 * repère une couleur. Ces trois-là sont sémantiques, distinctes de l'accent :
 * l'orange dit « c'est Tizzleshop », il ne doit pas dire « attention ».
 */
.dokan-dashboard .dokan-label {
    border-radius: 999px;
    padding: 0.15rem 0.65rem;
    font-weight: 600;
}

.dokan-dashboard .dokan-label-success { background: #e8f5ec; color: #1b5e34; }
.dokan-dashboard .dokan-label-warning { background: #fdf3e3; color: #8a5a10; }
.dokan-dashboard .dokan-label-danger  { background: #fdeaea; color: #a12222; }

/* Variante sombre retirée — voir la note en tête de fichier. */

/* Le bouton qui engage — un seul par écran, comme partout ailleurs. */
.dokan-dashboard .dokan-btn-theme,
.dokan-dashboard input[type="submit"].dokan-btn-theme {
    background: var(--tz-orange) !important;
    border-color: var(--tz-orange) !important;
    color: #fff !important;
    font-weight: 600;
    border-radius: 8px;
}

.dokan-dashboard .dokan-btn-theme:hover,
.dokan-dashboard input[type="submit"].dokan-btn-theme:hover {
    background: var(--tz-orange-sombre) !important;
    border-color: var(--tz-orange-sombre) !important;
}

.dokan-dashboard .dokan-btn-theme:focus-visible {
    outline: 2px solid var(--tz-encre);
    outline-offset: 2px;
}

/* Un tableau de commandes est large : il se déroule dans sa boîte. */
.dokan-dashboard .dokan-dashboard-content .dokan-table-responsive,
.dokan-dashboard .dokan-dashboard-content table {
    overflow-x: auto;
}

/* ------------------------------------------------------------------ */
/* Le tableau de bord refait — structure, pas rhabillage               */
/* ------------------------------------------------------------------ */

/*
 * Le texte par défaut de WooCommerce disparaît quand notre tableau de bord est
 * là.
 *
 * `remove_action()` n'a pas suffi : le thème le rend depuis son propre gabarit,
 * hors du crochet qu'on décroche. Résultat à l'écran — « Hello … From your
 * account dashboard you can view your recent orders » juste au-dessus de nos
 * tuiles, qui disent la même chose en mieux.
 *
 * On le masque plutôt que de lutter contre le gabarit du thème : c'est le seul
 * moyen qui ne casse pas à la prochaine mise à jour de Blonwe.
 */
.woocommerce-MyAccount-content > p.woocommerce-message + p,
.woocommerce-MyAccount-content > .woocommerce-Address ~ p,
.woocommerce-MyAccount-content > p:has(+ .tz-compte) {
    display: none;
}

/*
 * Le titre principal, hors de l'écran mais jamais supprimé.
 *
 * `display: none` ou `visibility: hidden` le retireraient aussi pour les
 * moteurs et les lecteurs d'écran — c'est-à-dire précisément ceux pour qui on
 * l'ajoute. Cette technique-ci le sort du champ visuel en le laissant dans
 * l'arbre du document.
 *
 * `white-space: nowrap` évite qu'un titre long ne crée une barre de défilement
 * horizontale invisible, effet de bord classique de cette mise en retrait.
 */
.tz-titre-page {
    position: absolute !important;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
    border: 0;
}

.tz-compte {
    display: flex;
    flex-direction: column;
    gap: 1.5rem;
    /* Notre bloc remonte au-dessus de ce que le thème a déjà posé : la
       personne voit d'abord son résumé, pas un menu qu'elle a déjà en haut. */
    margin-top: 0;
}

/*
 * Les boutons du thème dans l'espace compte — « Become a Vendor », « Become a
 * wholesale customer » — débordaient exactement comme « Read more » et « Phone
 * number » avant eux. Même cause, même correctif : contraindre le texte.
 *
 * Troisième fois que je pose une couleur sans regarder ce que la boîte
 * contient ; c'est désormais le premier réflexe sur tout bouton du thème.
 */
html body .woocommerce-MyAccount-content a.button,
html body .woocommerce-MyAccount-content button,
html body .woocommerce-account .dokan-btn,
html body .woocommerce-account a[href*="vendor"].button,
html body .woocommerce-account a[href*="wholesale"] {
    display: inline-flex !important;
    align-items: center !important;
    justify-content: center !important;
    white-space: nowrap !important;
    overflow: hidden !important;
    text-overflow: ellipsis !important;
    height: auto !important;
    min-height: 0 !important;
    line-height: 1.3 !important;
    padding: 0.6rem 1rem !important;
    font-size: 0.88rem !important;
}

/* Le bandeau d'identité : la variante B validée le 2026-08-10. */
.tz-compte-bandeau {
    display: flex;
    align-items: center;
    gap: 1rem;
    padding: 1.1rem 1.25rem;
    background: var(--tz-orange);
    color: #fff;
    border-radius: var(--tz-rayon);
}

.tz-compte-initiales {
    display: grid;
    place-items: center;
    width: 46px;
    height: 46px;
    flex: 0 0 46px;
    border-radius: 50%;
    background: rgba(255, 255, 255, 0.22);
    font-weight: 700;
    font-size: 1.05rem;
}

.tz-compte-identite {
    display: flex;
    flex-direction: column;
    line-height: 1.25;
    margin-right: auto;
}

.tz-compte-bonjour {
    font-size: 0.8rem;
    text-transform: uppercase;
    letter-spacing: 0.07em;
    opacity: 0.85;
}

.tz-compte-nom {
    font-size: 1.2rem;
}

.tz-compte-sortie {
    color: #fff !important;
    text-decoration: underline;
    font-size: 0.9rem;
    white-space: nowrap;
}

/* Les tuiles : une action par carte, avec le chiffre qui lui donne son sens. */
.tz-compte-tuiles {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
    gap: 0.85rem;
}

.tz-tuile {
    display: flex;
    flex-direction: column;
    gap: 0.35rem;
    padding: 1rem 1.1rem;
    border: 1px solid var(--tz-trait);
    border-radius: var(--tz-rayon);
    background: var(--tz-fond);
    color: var(--tz-encre) !important;
    text-decoration: none !important;
    transition: border-color 0.15s;
}

.tz-tuile:hover,
.tz-tuile:focus-visible {
    border-color: var(--tz-orange);
}

.tz-tuile-titre {
    font-size: 0.82rem;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--tz-encre-douce);
}

.tz-tuile-valeur {
    font-size: 1.85rem;
    font-weight: 700;
    font-variant-numeric: tabular-nums;
    line-height: 1;
}

.tz-tuile-action {
    font-size: 0.9rem;
    font-weight: 600;
    color: var(--tz-orange-sombre);
}

/* Les commandes récentes. */
.tz-compte-bloc {
    border: 1px solid var(--tz-trait);
    border-radius: var(--tz-rayon);
    overflow: hidden;
}

.tz-compte-bloc-titre {
    margin: 0;
    padding: 0.8rem 1.15rem;
    background: var(--tz-orange-voile);
    color: var(--tz-encre);
    font-size: 0.95rem;
    border-bottom: 1px solid var(--tz-trait);
}

.tz-commandes {
    margin: 0;
    padding: 0;
    list-style: none;
}

.tz-commande + .tz-commande {
    border-top: 1px solid var(--tz-trait);
}

.tz-commande a {
    display: grid;
    grid-template-columns: auto 1fr auto auto;
    align-items: center;
    gap: 0.9rem;
    padding: 0.85rem 1.15rem;
    color: var(--tz-encre) !important;
    text-decoration: none !important;
}

.tz-commande a:hover {
    background: var(--tz-orange-voile);
}

.tz-commande-numero,
.tz-commande-total {
    font-variant-numeric: tabular-nums;
    font-weight: 600;
}

.tz-commande-date {
    font-size: 0.88rem;
    color: var(--tz-encre-douce);
}

/*
 * L'état, encodé par la forme autant que par le mot — et sémantique, donc
 * distinct de l'accent : l'orange dit « Tizzleshop », il ne dit pas « attention ».
 */
.tz-commande-etat {
    padding: 0.15rem 0.65rem;
    border-radius: 999px;
    font-size: 0.8rem;
    font-weight: 600;
    white-space: nowrap;
}

.tz-etat-completed { background: #e8f5ec; color: #1b5e34; }
.tz-etat-processing,
.tz-etat-on-hold { background: #fdf3e3; color: #8a5a10; }
.tz-etat-cancelled,
.tz-etat-failed,
.tz-etat-refunded { background: #fdeaea; color: #a12222; }
.tz-etat-pending { background: #eef0f2; color: #45505c; }

/* Variante sombre retirée — voir la note en tête de fichier. */

/* Un compte sans commande : une porte de sortie, pas un vide. */
.tz-compte-vide {
    padding: 1.5rem 1.15rem;
    text-align: center;
}

.tz-bouton {
    display: inline-block;
    background: var(--tz-orange);
    color: #fff !important;
    text-decoration: none !important;
    font-weight: 600;
    padding: 0.7rem 1.4rem;
    border-radius: 8px;
}

.tz-bouton:hover { background: var(--tz-orange-sombre); }

/* En étroit, la ligne de commande passe sur deux rangs plutôt que de déborder. */
@media (max-width: 600px) {
    .tz-commande a {
        grid-template-columns: auto 1fr;
        row-gap: 0.4rem;
    }
}

/* ------------------------------------------------------------------ */
/* L'historique en cartes — le tableau ne tient pas sur un pouce       */
/* ------------------------------------------------------------------ */

.tz-cartes-commandes {
    margin: 0;
    padding: 0;
    list-style: none;
    display: flex;
    flex-direction: column;
    gap: 0.85rem;
}

.tz-carte-commande {
    border: 1px solid var(--tz-trait);
    border-radius: var(--tz-rayon);
    background: var(--tz-fond);
    overflow: hidden;
}

.tz-carte-entete {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.75rem;
    padding: 0.75rem 1.05rem;
    border-bottom: 1px solid var(--tz-trait);
    background: var(--tz-orange-voile);
}

.tz-carte-corps {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: 0.35rem 1.1rem;
    padding: 0.85rem 1.05rem;
}

.tz-carte-articles {
    font-size: 0.9rem;
    color: var(--tz-encre-douce);
}

/* Le total pousse à droite : c'est le chiffre qu'on cherche du regard. */
.tz-carte-corps .tz-commande-total {
    margin-left: auto;
    font-size: 1.05rem;
}

.tz-carte-actions {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem;
    padding: 0 1.05rem 1rem;
}

.tz-bouton-creux {
    background: transparent !important;
    color: var(--tz-orange-sombre) !important;
    border: 1px solid var(--tz-orange);
}

.tz-bouton-creux:hover {
    background: var(--tz-orange-voile) !important;
}

.tz-pagination {
    display: flex;
    gap: 0.5rem;
    margin-top: 1.25rem;
}

/*
 * Les notices posées en tête du compte — dont la confirmation d'adresse.
 * Elles arrivaient sans mise en forme propre : un message de succès qui
 * ressemble à une erreur inquiète autant qu'il informe.
 */
.woocommerce-account .woocommerce-message {
    border-left: 4px solid #1b5e34;
    background: #e8f5ec;
    color: #12331f;
}

.woocommerce-account .woocommerce-error {
    border-left: 4px solid #a12222;
    background: #fdeaea;
    color: #4a1414;
}

/* Variante sombre retirée — voir la note en tête de fichier. */

/* ------------------------------------------------------------------ */
/* L'écran d'inscription et de connexion                               */
/* ------------------------------------------------------------------ */

.tz-accueil-bandeau {
    display: flex;
    flex-direction: column;
    gap: 0.2rem;
    padding: 1.1rem 1.25rem;
    margin-bottom: 1.5rem;
    background: var(--tz-orange);
    color: #fff;
    border-radius: var(--tz-rayon);
}

.tz-accueil-titre { font-size: 1.15rem; font-weight: 700; text-wrap: balance; }
.tz-accueil-sous { font-size: 0.9rem; opacity: 0.9; }

/*
 * Le choix de l'identifiant, en deux boutons.
 *
 * Une liste déroulante cachait le choix : il fallait l'ouvrir pour découvrir
 * qu'on pouvait s'inscrire par numéro. Deux boutons côte à côte montrent les
 * deux chemins sans qu'on ait rien à faire.
 */
.tz-choix { margin-bottom: 1.25rem; }

.tz-choix-titre {
    display: block;
    margin-bottom: 0.45rem;
    font-size: 0.82rem;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--tz-encre-douce);
}

.tz-choix .tz-choix-boutons {
    display: grid;
    /* Deux colonnes égales : le thème étirait les boutons différemment selon
       la longueur du texte, et « Phone number » se retrouvait deux fois plus
       étroit qu'« Email address ». Une grille les fige à parts égales. */
    grid-template-columns: 1fr 1fr;
    gap: 0.6rem;
}

/*
 * `html body` en tête et `button.` sur l'élément : la spécificité doit passer
 * devant celle du thème, qui impose à ses boutons un affichage en bloc, ses
 * marges et sa police. Sans ça, le texte s'enroulait autour de l'icône et
 * l'état actif restait gris — le défaut visible sur la démonstration à 15:16.
 */
html body .tz-choix button.tz-choix-bouton {
    display: flex !important;
    align-items: center !important;
    justify-content: center !important;
    gap: 0.5rem !important;
    /* Le texte ne se casse jamais autour de l'icône : il tient sur une ligne,
       et rétrécit d'un cheveu plutôt que de passer au-dessus et au-dessous. */
    flex-wrap: nowrap !important;
    white-space: nowrap !important;
    min-width: 0;
    width: 100% !important;
    margin: 0 !important;
    padding: 0.8rem 0.7rem !important;
    border: 1px solid var(--tz-trait) !important;
    border-radius: var(--tz-rayon) !important;
    background: var(--tz-fond) !important;
    color: var(--tz-encre) !important;
    font-weight: 600 !important;
    font-size: clamp(0.78rem, 3.4vw, 0.95rem) !important;
    line-height: 1.2 !important;
    text-transform: none !important;
    letter-spacing: 0 !important;
    box-shadow: none !important;
    cursor: pointer;
    transition: border-color 0.15s, background 0.15s;
}

html body .tz-choix button.tz-choix-bouton:hover {
    border-color: var(--tz-orange) !important;
}

/*
 * L'état choisi se voit par la FORME autant que par la couleur : le liseré
 * s'épaissit. Il tient pour qui ne distingue pas l'orange du gris, et il reste
 * lisible sur une capture en noir et blanc.
 *
 * Le trait passe de 1 à 2 px par `box-shadow` plutôt que par `border-width` :
 * changer l'épaisseur du bord déplacerait le contenu d'un pixel, et le bouton
 * sauterait à chaque clic.
 */
/*
 * Le sélecteur porte l'attribut `[data-valeur]` en plus des classes : la
 * géométrie passait déjà, mais le FOND restait gris — le thème le posait avec
 * une spécificité supérieure à la mienne. Mesuré, pas supposé :
 * `rgb(230, 232, 235)` sur les deux boutons, actif compris.
 *
 * `background-image` en renfort de `background-color` : quand un thème force
 * une couleur de fond, il oublie presque toujours l'image. Deux propriétés
 * valent mieux qu'une escalade de `!important` sans fin.
 */
html body .tz-choix button.tz-choix-bouton[data-valeur].est-actif {
    border-color: var(--tz-orange) !important;
    box-shadow: inset 0 0 0 1px var(--tz-orange) !important;
    background-color: var(--tz-orange-voile) !important;
    background-image: linear-gradient(var(--tz-orange-voile), var(--tz-orange-voile)) !important;
    color: var(--tz-orange-sombre) !important;
}

html body .tz-choix button.tz-choix-bouton[data-valeur]:not(.est-actif) {
    background-color: var(--tz-fond) !important;
    background-image: linear-gradient(var(--tz-fond), var(--tz-fond)) !important;
    color: var(--tz-encre) !important;
}

html body .tz-choix button.tz-choix-bouton:focus-visible {
    outline: 2px solid var(--tz-encre);
    outline-offset: 2px;
}

/* L'icône ne rétrécit jamais : c'est le texte qui cède, pas elle. */
html body .tz-choix button.tz-choix-bouton .tz-ico {
    flex: 0 0 18px;
    width: 18px;
    height: 18px;
}

.tz-ico {
    width: 20px; height: 20px; flex: 0 0 20px;
    fill: none; stroke: currentColor; stroke-width: 1.7;
    stroke-linecap: round; stroke-linejoin: round;
}

/* ------------------------------------------------------------------ */
/* Le catalogue : le prix d'abord, la disponibilité ensuite             */
/* ------------------------------------------------------------------ */

/*
 * La spécificité est ancrée dès la première ligne — `html body` en tête.
 * Trois fois aujourd'hui une règle juste s'est fait battre par le thème, et
 * chaque fois il a fallu une seconde passe. On ne recommence pas.
 */

/*
 * Le balisage visé est celui du thème, LU sur la page — pas celui de
 * WooCommerce, supposé.
 *
 *   div.products › div.product › div.product-wrapper › div.product-inner
 *                                                    › span.price
 *
 * La première version visait `ul.products li.product`. Elle ne s'appliquait à
 * rien : Blonwe rend ses cartes en `div`. Écrire du style pour un balisage
 * supposé, c'est écrire pour rien — et ne s'en apercevoir qu'à la capture
 * d'écran de la cliente.
 */

html body div.products div.product div.product-wrapper {
    border: 1px solid var(--tz-trait) !important;
    border-radius: var(--tz-rayon) !important;
    background: var(--tz-papier, #fff) !important;
    transition: border-color 0.15s;
    overflow: hidden;
}

html body div.products div.product div.product-wrapper:hover {
    border-color: var(--tz-orange) !important;
}

/* Le prix pèse. C'est ce qu'on lit en premier dans une grille. */
html body div.products div.product span.price,
html body div.products div.product .price,
html body .woocommerce div.product p.price {
    font-variant-numeric: tabular-nums !important;
    font-weight: 700 !important;
    color: var(--tz-encre) !important;
    font-size: 1.05rem !important;
}

/* Le prix barré n'est pas un prix : il ne doit pas peser autant. */
html body div.products div.product .price del,
html body .woocommerce div.product p.price del {
    color: var(--tz-encre-douce) !important;
    font-weight: 400 !important;
    font-size: 0.88em !important;
    opacity: 0.8;
}

html body div.products div.product .price ins,
html body .woocommerce div.product p.price ins {
    text-decoration: none !important;
    color: var(--tz-orange-sombre) !important;
    background: transparent !important;
}

/*
 * Le nom du produit. `line-clamp` le borne à deux lignes : sans lui, un titre
 * long décale le prix d'une carte à l'autre, et deux prix côte à côte ne se
 * comparent plus d'un regard — ce qui était tout l'objet de l'alignement.
 */
html body div.products div.product .product-title,
html body div.products div.product h2,
html body div.products div.product h3 {
    color: var(--tz-encre) !important;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
    min-height: 2.6em;
}

html body .woocommerce div.product .product_title {
    color: var(--tz-encre) !important;
    text-wrap: balance;
}

/*
 * La pastille de remise. Rouge sémantique — l'orange dit « Tizzleshop », il ne
 * doit pas dire « affaire à saisir », sinon on ne sait plus ce qu'il signifie.
 */
html body div.products div.product .onsale,
html body .woocommerce div.product .onsale {
    background: #a12222 !important;
    color: #fff !important;
    border-radius: 999px !important;
    font-weight: 700 !important;
    font-size: 0.78rem !important;
    padding: 0.15rem 0.6rem !important;
    min-height: 0 !important;
    min-width: 0 !important;
    line-height: 1.5 !important;
}

/* ------------------------------------------------------------------ */
/* La fiche produit                                                     */
/* ------------------------------------------------------------------ */

/*
 * La disponibilité : une information d'état, donc encodée par la forme autant
 * que par le mot. Quelqu'un qui parcourt vingt fiches ne lit pas vingt fois
 * « in stock » — il repère une pastille.
 */
html body .woocommerce div.product .stock {
    display: inline-block !important;
    padding: 0.15rem 0.7rem !important;
    border-radius: 999px !important;
    font-size: 0.85rem !important;
    font-weight: 600 !important;
}

html body .woocommerce div.product .stock.in-stock {
    background: #e8f5ec !important;
    color: #1b5e34 !important;
}

html body .woocommerce div.product .stock.out-of-stock {
    background: #fdeaea !important;
    color: #a12222 !important;
}

/*
 * Le bouton qui engage — un seul par écran.
 *
 * La première version ne posait que la couleur : « Read more » débordait
 * au-dessus et au-dessous de l'orange, comme les boutons du choix
 * d'identifiant deux heures plus tôt. Poser une couleur sans contraindre le
 * texte, c'est repeindre une boîte sans regarder ce qu'elle contient.
 *
 * `.product_type_simple` et `.button` couvrent aussi « Read more » : un
 * produit sans prix n'affiche pas « Add to cart », et c'est justement celui
 * qui débordait.
 */
/*
 * Le sélecteur ne dépend plus du conteneur.
 *
 * La version précédente visait `div.products div.product` — le balisage du
 * catalogue. Sur l'accueil, les produits sont posés par Elementor dans une
 * autre structure, et « Read more » y débordait toujours : six occurrences
 * relevées le 2026-08-12, après que je l'avais annoncé corrigé.
 *
 * On vise donc le BOUTON lui-même, où qu'il soit. Ces classes appartiennent à
 * WooCommerce, pas à un gabarit : elles suivent le produit partout.
 */
/*
 * La spécificité monte encore d'un cran, et cette fois elle est CALCULÉE.
 *
 * `html body a.product_type_simple` compte une seule classe. Le thème, lui,
 * écrit `.product-buttons.primary-button .button` — trois classes. Le nombre de
 * classes est comparé avant tout le reste : sa règle l'emportait, `!important`
 * des deux côtés ou non.
 *
 * On reprend donc SON chemin, mesuré sur la page :
 *   div.product-buttons.primary-button › a.button.product_type_simple
 */
html body div.product-buttons a.button,
html body div.product-buttons.primary-button a.button,
html body a.add_to_cart_button,
html body a.product_type_simple,
html body a.product_type_variable,
html body a.product_type_grouped,
html body a.product_type_external,
html body div.products div.product a.button,
/*
 * La fiche produit, sur son balisage LU :
 *   article.single-product › div.product-detail-inner › form.cart
 *     › button.single_add_to_cart_button.button.alt
 *
 * Mesuré gris — rgb(230, 232, 235) — alors que la règle d'orange existait
 * depuis deux heures : elle visait `.woocommerce div.product`, qui n'entoure
 * pas ce bouton. La classe `.alt` du thème le repeignait par-dessus.
 *
 * Ce défaut n'était pas visible sur la fiche mesurée juste avant : un produit
 * sans prix n'a pas de bouton du tout. Mesurer sur le mauvais échantillon,
 * c'est ne pas mesurer.
 */
html body article.single-product form.cart button.single_add_to_cart_button,
html body div.product-detail-inner form.cart button.single_add_to_cart_button,
html body .woocommerce div.product form.cart button.single_add_to_cart_button {
    display: flex !important;
    align-items: center !important;
    justify-content: center !important;
    gap: 0.4rem !important;
    /* Le texte tient sur une ligne et se coupe proprement s'il est trop long,
       au lieu de sortir de la boîte. */
    white-space: nowrap !important;
    overflow: hidden !important;
    text-overflow: ellipsis !important;
    /* Aucune hauteur figée : la boîte suit son contenu, jamais l'inverse.
     *
     * ⚠️ `min-height` valait 0. Mesuré sur la boutique du vendeur : le bouton
     * faisait 37 px de haut — sous les 44 px en dessous desquels le pouce vise
     * à côté — et 120 px de large pour 124 px de texte.
     *
     * J'ai d'abord écrit une règle NEUVE pour corriger cela, et elle est
     * restée sans effet : celle-ci porte `!important` sur `min-height`, et un
     * `!important` ne se bat pas à coups de spécificité. Je me battais contre
     * mon propre passage précédent.
     *
     * On corrige donc LA RÈGLE D'ORIGINE. Empiler une seconde règle aurait
     * laissé deux intentions contraires dans la même feuille, dont l'une ne
     * sert plus qu'à être battue — et le prochain à lire n'aurait pas su
     * laquelle fait foi. */
    height: auto !important;
    min-height: 44px !important;
    line-height: 1.3 !important;
    /* 0,55 rem au lieu de 0,9 : sur les cartes étroites de la boutique
     * vendeur, 28,8 px de remplissage ne laissaient que 91 px pour un texte
     * qui en demande 95. Le texte se coupait faute de quatre pixels. */
    padding: 0.6rem 0.55rem !important;
    font-size: 0.88rem !important;
    /* ⚠️ `--tz-orange-bouton` et non `--tz-orange`. Du blanc sur l'orange de
     * la charte plafonne à 2,57:1, quand il en faut 4,5 — mesuré sur ce bouton
     * précis, et sur tous les autres du site avec lui.
     *
     * J'avais d'abord écrit une règle NEUVE en fin de fichier pour corriger
     * cela. Elle a perdu : celle-ci compte trois classes, la mienne deux, et
     * le nombre de classes se compare avant tout le reste. La correction va
     * là où est la cause — quatrième fois aujourd'hui.
     *
     * La charte ne change pas : l'orange reste celui des grandes surfaces.
     * Seuls les boutons, qui portent du texte blanc, prennent une version
     * plus profonde du même ton. */
    background-color: var(--tz-orange-bouton, #c44e08) !important;
    background-image: linear-gradient(var(--tz-orange-bouton, #c44e08), var(--tz-orange-bouton, #c44e08)) !important;
    border-color: var(--tz-orange-bouton, #c44e08) !important;
    color: #fff !important;
    font-weight: 600 !important;
    border-radius: 8px !important;
}

html body div.products div.product a.add_to_cart_button:hover,
html body div.products div.product a.button:hover,
html body article.single-product form.cart button.single_add_to_cart_button:hover,
html body div.product-detail-inner form.cart button.single_add_to_cart_button:hover,
html body .woocommerce div.product form.cart button.single_add_to_cart_button:hover {
    background-color: var(--tz-orange-sombre) !important;
    background-image: linear-gradient(var(--tz-orange-sombre), var(--tz-orange-sombre)) !important;
    border-color: var(--tz-orange-sombre) !important;
}

/* Les onglets de la fiche : même traitement que la navigation du compte. */
html body .woocommerce div.product .woocommerce-tabs ul.tabs li.active a {
    color: var(--tz-encre) !important;
    font-weight: 600 !important;
}

html body .woocommerce div.product .woocommerce-tabs ul.tabs li.active {
    border-bottom-color: var(--tz-orange) !important;
}

/*
 * En mobile, le prix et le bouton d'achat restent accessibles quand on lit la
 * description. Sans ça, il faut remonter toute la fiche pour acheter — et sur
 * un catalogue vu au pouce, c'est là que la vente se perd.
 */
@media (max-width: 768px) {
    html body .woocommerce div.product form.cart {
        position: sticky;
        bottom: 0;
        z-index: 5;
        background: var(--tz-papier, #fff);
        padding: 0.7rem 0 !important;
        border-top: 1px solid var(--tz-trait);
        margin-bottom: 0 !important;
    }
}

/* ------------------------------------------------------------------ */
/* Client ou vendeur : deux cartes, pas deux boutons radio orphelins    */
/* ------------------------------------------------------------------ */

/*
 * Dokan rend ses deux rôles en boutons radio nus : la puce se retrouvait
 * au-dessus du texte, avec des écarts énormes entre les deux options. Sur un
 * écran par ailleurs soigné, c'est le détail qui trahit le bricolage.
 *
 * On les remet en ligne, dans deux cartes de même facture que le choix
 * d'identifiant plus haut — c'est ce qui fait l'uniformité : la même question
 * posée deux fois se pose de la même manière.
 */
.woocommerce-form-register p:has(> input[name="role"]),
.woocommerce-form-register label:has(> input[name="role"]),
.woocommerce-form-register .dokan-registration-type-container {
    display: flex !important;
    align-items: center !important;
    gap: 0.6rem !important;
    margin: 0 0 0.5rem !important;
    padding: 0.7rem 0.9rem !important;
    border: 1px solid var(--tz-trait);
    border-radius: var(--tz-rayon);
    background: var(--tz-fond);
    font-size: 0.92rem;
    line-height: 1.25 !important;
    cursor: pointer;
}

.woocommerce-form-register input[name="role"] {
    /* La puce reste une puce : on l'aligne, on ne la remplace pas. Un contrôle
       natif reste opérable au clavier et annoncé correctement. */
    width: 18px !important;
    height: 18px !important;
    margin: 0 !important;
    flex: 0 0 18px !important;
    accent-color: var(--tz-orange);
}

/* Le libellé colle à sa puce, au lieu de tomber à la ligne. */
.woocommerce-form-register input[name="role"] + span,
.woocommerce-form-register input[name="role"] ~ label {
    display: inline !important;
    margin: 0 !important;
    padding: 0 !important;
    line-height: 1.25 !important;
}

/*
 * L'option choisie se voit sans qu'on cherche la puce. `:has()` n'est pas
 * partout — sans lui, les cartes restent correctes, simplement sans liseré
 * orange. Une dégradation qui n'enlève rien d'utilisable.
 */
.woocommerce-form-register p:has(> input[name="role"]:checked),
.woocommerce-form-register label:has(> input[name="role"]:checked) {
    border-color: var(--tz-orange);
    background: var(--tz-orange-voile);
}

/* ------------------------------------------------------------------ */
/* La connexion : aider, pas vendre                                     */
/* ------------------------------------------------------------------ */

/*
 * L'inscription montre ce qu'on gagne ; la connexion ne vend rien — la
 * personne a déjà décidé. On lui donne ce dont elle a besoin quand quelque
 * chose coince, et rien d'autre.
 */
.tz-aide-connexion {
    display: flex;
    align-items: flex-start;
    gap: 0.55rem;
    margin: 0.9rem 0 1.1rem;
    padding: 0.7rem 0.9rem;
    background: var(--tz-orange-voile);
    border-radius: var(--tz-rayon);
    font-size: 0.87rem;
    line-height: 1.45;
    color: var(--tz-encre);
}

.tz-aide-connexion .tz-ico {
    color: var(--tz-orange-sombre);
    margin-top: 0.12rem;
}

/*
 * La sortie de secours, visible.
 *
 * « Mot de passe oublié » était un petit lien gris à côté d'une case à cocher.
 * Quelqu'un qui n'arrive pas à entrer a besoin d'une porte, pas d'un détail
 * typographique.
 */
.tz-sortie-connexion {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: center;
    gap: 0.5rem;
    margin-top: 1.1rem;
    padding-top: 0.9rem;
    border-top: 1px solid var(--tz-trait);
    font-size: 0.9rem;
}

.tz-sortie-connexion a {
    color: var(--tz-orange-sombre) !important;
    font-weight: 600;
    text-decoration: none;
}

.tz-sortie-connexion a:hover,
.tz-sortie-connexion a:focus-visible {
    text-decoration: underline;
}

.tz-sortie-sep { color: var(--tz-encre-douce); }

/* Les promesses : ce qu'on gagne, au moment où l'on hésite à s'engager. */
.tz-promesses {
    margin: 1.25rem 0 0;
    padding: 0.9rem 1.1rem;
    list-style: none;
    background: var(--tz-orange-voile);
    border-radius: var(--tz-rayon);
    font-size: 0.9rem;
}

.tz-promesses li {
    position: relative;
    padding-left: 1.5rem;
    margin: 0.3rem 0;
}

.tz-promesses li::before {
    content: "";
    position: absolute;
    left: 0.15rem;
    top: 0.45rem;
    width: 0.5rem;
    height: 0.28rem;
    border-left: 2px solid var(--tz-orange-sombre);
    border-bottom: 2px solid var(--tz-orange-sombre);
    transform: rotate(-45deg);
}

@media (prefers-reduced-motion: reduce) {
    .woocommerce-account .woocommerce-MyAccount-navigation li a,
    .tz-tuile,
    .tz-choix-bouton {
        transition: none;
    }
}

/* ==========================================================================
   Après la commande : deux issues, et une liste de souhaits lisible
   ==========================================================================

   LA CONFIRMATION. Mesurée sur la commande 24382 : aucune action proposée. Les
   seuls liens menaient au produit acheté et à la boutique du vendeur. Le client
   arrivait au bout d'un tunnel sans porte — il fait « retour », ce qui rejoue
   le paiement, ou il s'en va.

   Deux actions désormais, dans cet ordre : l'inquiétude d'abord (suivre la
   commande), l'envie ensuite (continuer ses achats). La première est
   principale, la seconde discrète — sinon on pousse à racheter quelqu'un qui
   se demande encore si sa commande est bien passée.
   ========================================================================== */

html body .tz-apres-commande {
    display: flex;
    flex-direction: column;
    gap: 0.75rem;
    margin: 1.5rem 0 2rem;
}

html body .tz-apres-commande .tz-bouton {
    display: flex;
    align-items: center;
    justify-content: center;
    min-height: 48px;
    padding: 0 1.25rem;
    border-radius: 8px;
    font-weight: 700;
    text-decoration: none;
}

html body .tz-apres-commande .tz-bouton-principal {
    background: #ff7c25;
    color: #fff;
}

html body .tz-apres-commande .tz-bouton-second {
    background: transparent;
    color: var(--tz-encre, #1b1f22);
    border: 1px solid var(--tz-bord, rgba(0, 0, 0, 0.15));
}

html body .tz-apres-commande-note {
    margin: 0;
    padding: 0.85rem 1rem;
    background: var(--tz-orange-voile, rgba(255, 124, 37, 0.08));
    border-radius: 8px;
    font-size: 0.95rem;
}

/* --------------------------------------------------------------------------
   La liste de souhaits : sept colonnes sur 390 px
   --------------------------------------------------------------------------

   Structure relevée, en tableau :

     td.klbwl-item--image · --name · --price · --date · --stock
     · --addtocart · --remove

   Sept colonnes dans la largeur d'un téléphone, c'est le défaut que le panier
   avait avant correction : tout se comprime jusqu'à devenir illisible, ou
   disparaît en silence.

   Même remède, mêmes raisons. La DATE d'ajout passe en dernier et discrète :
   elle n'aide pas à décider d'acheter, alors que le prix et la disponibilité,
   si. La liste de souhaits existe pour acheter plus tard — le bouton d'achat
   est donc l'action principale, pas une colonne parmi sept.
   -------------------------------------------------------------------------- */

@media (max-width: 767px) {
    /* ⚠️ On vise par les CELLULES, pas par la table.
     *
     * Première version : `table.klbwl-table`. Cette classe n'existe pas — je
     * l'avais déduite du préfixe des cellules. Résultat vu sur capture : rien
     * ne s'appliquait, le nom du produit restait coupé en plein mot et le prix
     * demeurait absent.
     *
     * Les seuls repères que j'ai réellement mesurés sont `td.klbwl-item--*`.
     * `:has()` permet de remonter d'eux vers la table et la ligne, sans avoir
     * à deviner comment le thème les nomme. */
    html body table:has(td.klbwl-item--image) thead {
        display: none;
    }

    html body table:has(td.klbwl-item--image),
    html body table:has(td.klbwl-item--image) tbody {
        display: block;
        width: 100%;
    }

    html body tr:has(td.klbwl-item--image) {
        position: relative;
        display: grid;
        grid-template-columns: 72px minmax(0, 1fr);
        grid-template-areas:
            "image nom"
            "image prix"
            "image stock"
            "achat achat"
            "date  date";
        gap: 0.3rem 0.85rem;
        align-items: start;
        padding: 0.9rem 2rem 0.9rem 0;
        border-bottom: 1px solid var(--tz-bord, rgba(0, 0, 0, 0.08));
    }

    /* Toutes les cellules redeviennent visibles : le thème en éteignait
       plusieurs — dont le PRIX, exactement comme au panier. Une liste de
       souhaits sans prix ne sert à rien : on y met des choses pour décider
       plus tard, et la décision porte sur le prix. */
    html body tr:has(td.klbwl-item--image) > td {
        display: block !important;
        width: auto;
        padding: 0;
        border: 0;
    }

    html body td.klbwl-item--image { grid-area: image; }

    html body td.klbwl-item--image img {
        width: 72px;
        height: 72px;
        object-fit: contain;
    }

    /* Le nom était coupé EN PLEIN MOT — « pack - 18Gbps » s'arrêtait net, sans
       ellipse, parce qu'une hauteur fixe rognait le texte. Deux lignes, avec
       les points de suspension qui disent qu'il y a une suite. */
    html body td.klbwl-item--name {
        grid-area: nom;
        font-weight: 600;
        line-height: 1.35;
        display: -webkit-box !important;
        -webkit-box-orient: vertical;
        -webkit-line-clamp: 2;
        line-clamp: 2;
        overflow: hidden;
        max-height: none;
    }

    html body td.klbwl-item--price {
        grid-area: prix;
        font-weight: 700;
        font-variant-numeric: tabular-nums;
    }

    html body td.klbwl-item--stock {
        grid-area: stock;
        font-size: 0.85rem;
    }

    html body td.klbwl-item--addtocart {
        grid-area: achat;
        margin-top: 0.35rem;
    }

    /* `button` en plus de `.button` et `a` : mesuré à 37 px, parce que le
       bouton d'achat de cette liste est un vrai `<button>` et qu'aucun de mes
       deux premiers sélecteurs ne l'attrapait. Trois façons d'écrire un bouton,
       trois sélecteurs — ou une mesure pour savoir laquelle est utilisée. */
    html body td.klbwl-item--addtocart .button,
    html body td.klbwl-item--addtocart button,
    html body td.klbwl-item--addtocart a {
        display: flex;
        align-items: center;
        justify-content: center;
        width: 100%;
        min-height: 44px;
    }

    /* La date : conservée, mais reléguée. Elle n'aide pas à décider. */
    html body td.klbwl-item--date {
        grid-area: date;
        font-size: 0.78rem;
        color: var(--tz-encre-douce, #6b7176);
    }

    html body td.klbwl-item--remove {
        position: absolute;
        top: 0.5rem;
        right: 0;
        width: auto;
    }

    html body td.klbwl-item--remove a {
        display: inline-flex;
        align-items: center;
        justify-content: center;
        width: 32px;
        height: 32px;
    }
}

/* ==========================================================================
   Le paiement : le montant et le bouton, toujours sous les yeux
   ==========================================================================

   Mesuré sur 390 × 844 : page de 3 201 px, total à y=1 531, bouton à y=1 905
   et large de 138 px seulement. Trois cent soixante-quatorze pixels séparent
   le montant du bouton qui l'engage.

   La barre collante porte les deux. La barre d'onglets est masquée pendant le
   paiement — décision assumée, documentée dans `tz-35-paiement-barre-action.php` :
   elle propose de partir ailleurs au moment où l'on s'engage, et deux barres
   empilées mangeraient un cinquième de l'écran.
   ========================================================================== */

@media (max-width: 991px) {
    html body.woocommerce-checkout .klb-mobile-bottom {
        display: none !important;
    }

    html body .tz-paiement-barre {
        position: fixed;
        left: 0;
        right: 0;
        bottom: 0;
        z-index: 1000;
        display: flex;
        align-items: center;
        gap: 1rem;
        padding: 0.75rem 1rem calc(0.75rem + env(safe-area-inset-bottom, 0px));
        background: #fff;
        /* L'ombre plutôt qu'une bordure : elle dit « ceci flotte au-dessus du
           contenu », ce qui est exactement le cas, et reste lisible quel que
           soit ce qui défile en dessous. */
        box-shadow: 0 -2px 16px rgba(0, 0, 0, 0.12);
    }

    html body .tz-paiement-barre[hidden] {
        display: none !important;
    }

    html body .tz-paiement-montant {
        display: flex;
        flex-direction: column;
        min-width: 0;
    }

    html body .tz-paiement-libelle {
        font-size: 0.72rem;
        letter-spacing: 0.06em;
        text-transform: uppercase;
        color: var(--tz-encre-douce, #6b7176);
    }

    html body .tz-paiement-total {
        font-size: 1.15rem;
        font-weight: 700;
        font-variant-numeric: tabular-nums;
        white-space: nowrap;
    }

    /* ⚠️ `!important` sur le fond et la couleur.
     *
     * Vu sur capture : le bouton sortait GRIS. C'est un `<button>`, et le thème
     * habille tous les boutons — sa règle est plus spécifique que la mienne.
     * Sur la seule commande qui engage un paiement, un bouton gris ne se lit
     * pas comme l'action principale : il se lit comme désactivé. */
    html body .tz-paiement-barre button.tz-paiement-valider,
    html body .tz-paiement-valider {
        flex: 1 1 auto;
        min-height: 48px;
        border: 0 !important;
        border-radius: 8px !important;
        background: #ff7c25 !important;
        background-image: none !important;
        color: #fff !important;
        font-size: 1rem;
        font-weight: 700;
        cursor: pointer;
    }

    html body .tz-paiement-barre button.tz-paiement-valider:hover {
        background: #e96a17 !important;
    }

    /* La page réserve la hauteur de la barre, sinon le dernier champ passe
       dessous — le défaut qu'on vient de corriger pour la barre d'onglets. */
    html body.woocommerce-checkout {
        padding-bottom: calc(84px + env(safe-area-inset-bottom, 0px));
    }

    /* Le bouton d'origine reste dans le flux : il est la cible du clic et
       WooCommerce y accroche sa validation. Il devient simplement pleine
       largeur, pour qui fait défiler jusqu'en bas. */
    html body #place_order {
        width: 100%;
        min-height: 48px;
    }
}

/* --------------------------------------------------------------------------
   Le récapitulatif du paiement : 99 px pour un nom de vingt mots
   --------------------------------------------------------------------------

   Mesuré sur un écran de 390, table de 360 :

     th.product-name    99 px
     th.product-total  261 px

   Le nom du produit reçoit un quart de la largeur, le montant les trois
   quarts — alors que le montant tient en huit caractères et le nom en vingt
   mots. D'où le nom qui s'écrit un mot par ligne sur vingt lignes.

   ⚠️ CE N'EST PAS LA MÊME TABLE QUE LE PANIER. J'ai corrigé
   `table.shop_table_responsive` et cru les deux écrans traités : le
   récapitulatif du paiement porte `woocommerce-checkout-review-order-table`.
   Une règle qui vise une classe ne touche pas une table qui ne la porte pas —
   et l'écran où l'on engage son argent est resté illisible plus longtemps que
   le panier.

   Chaque ligne devient une carte, comme au panier : le nom sur deux lignes en
   haut, le montant dessous, aligné à droite. Les montants gardent des chiffres
   tabulaires pour s'aligner d'une ligne à l'autre.
   -------------------------------------------------------------------------- */

@media (max-width: 767px) {
    html body table.woocommerce-checkout-review-order-table,
    html body table.woocommerce-checkout-review-order-table tbody,
    html body table.woocommerce-checkout-review-order-table tfoot {
        display: block;
        width: 100%;
    }

    html body table.woocommerce-checkout-review-order-table thead {
        display: none;
    }

    html body table.woocommerce-checkout-review-order-table tbody tr,
    html body table.woocommerce-checkout-review-order-table tfoot tr {
        display: flex;
        flex-wrap: wrap;
        align-items: baseline;
        justify-content: space-between;
        gap: 0.2rem 1rem;
        padding: 0.6rem 0;
        border-bottom: 1px solid var(--tz-trait, #e7e2dd);
    }

    html body table.woocommerce-checkout-review-order-table td,
    html body table.woocommerce-checkout-review-order-table th {
        display: block;
        width: auto;
        padding: 0;
        border: 0;
        text-align: left;
    }

    /* Le nom prend toute la largeur et se borne à deux lignes : on vient de le
       choisir, on n'a pas besoin de le relire en entier. */
    html body table.woocommerce-checkout-review-order-table td.product-name,
    html body table.woocommerce-checkout-review-order-table th.product-name {
        flex: 1 1 100%;
        font-weight: 600;
        line-height: 1.35;
        display: -webkit-box;
        -webkit-box-orient: vertical;
        -webkit-line-clamp: 2;
        line-clamp: 2;
        overflow: hidden;
    }

    /* ⚠️ `:not(.product-name)` — sans quoi le nom hérite du `nowrap`.
     *
     * Première version : la règle visait `td.product-total` ET `td` tout court.
     * Le second sélecteur attrapait aussi la cellule du nom, qui ne pouvait
     * donc plus revenir à la ligne : mesuré à 696 px de contenu dans une boîte
     * de 360, et la table entière repassait en débordement.
     *
     * Une règle écrite pour les montants s'était appliquée au texte. Le
     * `nowrap` est juste pour un prix — il est absurde pour une phrase. */
    html body table.woocommerce-checkout-review-order-table td:not(.product-name) {
        margin-left: auto;
        text-align: right;
        font-variant-numeric: tabular-nums;
    }

    /* ⚠️ Le `nowrap` va sur LE PRIX, pas sur la cellule.
     *
     * Deuxième fois que la même erreur me rattrape, un niveau plus bas. Posé
     * sur `td:not(.product-name)`, il attrapait aussi la cellule des modes de
     * livraison — dont le libellé fait « Lagos Mainland Surulere/Yaba Areas-
     * (Abraham Adesanya, yaba, Ojuelegba) ». Incapable de revenir à la ligne,
     * il courait sur 633 px et emportait toute la table.
     *
     * Un prix ne doit jamais se couper en deux ; une phrase doit toujours
     * pouvoir. La règle appartient donc au montant, pas à son contenant — et
     * elle vaut alors partout, quel que soit le tableau. */
    html body table.woocommerce-checkout-review-order-table .woocommerce-Price-amount,
    html body table.woocommerce-checkout-review-order-table bdi {
        white-space: nowrap;
    }

    /* Les libellés du pied — Subtotal, Shipping, Total — restent à gauche de
       leur montant, sur la même ligne. */
    html body table.woocommerce-checkout-review-order-table tfoot th {
        flex: 0 1 auto;
        font-weight: 500;
        color: var(--tz-encre-douce, #57534e);
        text-transform: uppercase;
        font-size: 0.8rem;
        letter-spacing: 0.04em;
    }

    html body table.woocommerce-checkout-review-order-table tfoot tr.order-total th,
    html body table.woocommerce-checkout-review-order-table tfoot tr.order-total td {
        font-size: 1.1rem;
        font-weight: 700;
        color: var(--tz-encre, #1c1917);
    }

    /* Les choix de livraison : une ligne par option, la case à gauche et le
       prix à droite — pas un bloc centré dont le prix sort de l'écran.
       C'est ce que montrait la capture du client : « Lagos Lekki/Ajah… » au
       centre, le montant coupé au bord. */
    html body table.woocommerce-checkout-review-order-table ul#shipping_method,
    html body table.woocommerce-checkout-review-order-table ul.woocommerce-shipping-methods {
        flex: 1 1 100%;
        list-style: none;
        margin: 0.35rem 0 0;
        padding: 0;
    }

    html body table.woocommerce-checkout-review-order-table ul#shipping_method li,
    html body table.woocommerce-checkout-review-order-table ul.woocommerce-shipping-methods li {
        display: flex;
        align-items: center;
        gap: 0.6rem;
        min-height: 44px;
        text-align: left;
    }

    html body table.woocommerce-checkout-review-order-table ul#shipping_method label,
    html body table.woocommerce-checkout-review-order-table ul.woocommerce-shipping-methods label {
        display: flex;
        align-items: center;
        justify-content: space-between;
        gap: 0.75rem;
        flex: 1 1 auto;
        text-align: left;
        line-height: 1.3;
    }

    html body table.woocommerce-checkout-review-order-table ul#shipping_method .woocommerce-Price-amount {
        white-space: nowrap;
        font-weight: 700;
        font-variant-numeric: tabular-nums;
    }
}

/* --------------------------------------------------------------------------
   Les cases à cocher et les boutons radio du paiement
   --------------------------------------------------------------------------

   Relevé : cases de 17 px, radios de 13 px, libellés à 13 et 14 px. La case
   « I have read and agree to the terms » est OBLIGATOIRE et mesure 17 px —
   c'est la commande la plus critique du tunnel, et la plus petite de l'écran.

   Le libellé devient cliquable avec la case : doubler la surface utile ne
   coûte rien, et personne ne vise un carré de 17 px du premier coup.
   -------------------------------------------------------------------------- */

html body form.checkout input[type="checkbox"],
html body form.checkout input[type="radio"],
html body form.woocommerce-checkout input[type="checkbox"],
html body form.woocommerce-checkout input[type="radio"] {
    width: 22px;
    height: 22px;
    min-height: 22px;
    accent-color: #ff7c25;
    flex: 0 0 auto;
    margin-right: 0.6rem;
}

html body form.checkout label,
html body form.woocommerce-checkout label {
    font-size: 15px;
    line-height: 1.4;
}

html body form.checkout .woocommerce-form__label-for-checkbox,
html body form.checkout .form-row label:has(input[type="checkbox"]),
html body form.checkout ul.wc_payment_methods label,
html body form.checkout #shipping_method label {
    display: flex;
    align-items: center;
    min-height: 44px;
    cursor: pointer;
}

/* ==========================================================================
   L'espace vendeur : une liste à puces avec des liens bleus
   ==========================================================================

   Mesuré le 2026-08-11, avec un compte vendeur créé pour l'occasion. Ce que
   voit un commerçant qui ouvre sa boutique depuis son téléphone :

     • une liste à puces, 26 entrées, 715 px de haut
     • des liens en bleu par défaut du navigateur
     • aucun indicateur, aucune carte, aucun résumé

   Ce n'est pas un tableau de bord à réorganiser : c'est un tableau de bord
   dont AUCUN style ne s'applique. La feuille de Dokan ne charge pas sur cet
   écran, et le navigateur rend le balisage nu.

   ⚠️ Ma maquette supposait quatre indicateurs et trois commandes. Ils
   n'existent pas. Je corrige donc ce qui est là — la lisibilité de la
   navigation — plutôt que de dessiner par-dessus un écran que je n'avais pas vu.
   Le résumé reste à construire, et il demandera du PHP, pas du style.

   Ce bloc rend la navigation utilisable. Il ne prétend pas être la refonte.
   ========================================================================== */

/* --------------------------------------------------------------------------
   Les widgets de Dokan tiennent dans l'écran
   --------------------------------------------------------------------------

   ⚠️ Ce bloc répare une conséquence de MON correctif. En rebranchant les
   widgets que Dokan avait débranchés (`tz-38`), la largeur de l'écran est
   passée de 390 à 505 px : quelque chose à l'intérieur est plus large que le
   téléphone et pousse toute la page.

   Un débordement horizontal ne se voit pas tout de suite — la page s'affiche,
   simplement elle glisse latéralement et le bord droit de chaque bloc sort du
   champ. C'est le défaut qu'on a déjà corrigé au panier et à la wishlist.

   Les widgets restent ceux de Dokan : on ne réécrit rien, on les borne.
   -------------------------------------------------------------------------- */

html body .dokan-dashboard .dokan-w6,
html body .dokan-dash-left,
html body .dokan-dash-right {
    /* `min-width: 0` : sans lui, un enfant plus large qu'une colonne de grille
       ou de flex refuse de rétrécir, et c'est lui qui impose sa largeur au
       parent. C'est la cause la plus fréquente d'un débordement qu'on ne
       trouve pas en regardant le parent. */
    min-width: 0;
    max-width: 100%;
    float: none;
    width: 100%;
    box-sizing: border-box;
}

html body .dokan-dashboard .dashboard-widget {
    max-width: 100%;
    box-sizing: border-box;
    overflow-wrap: break-word;
}

/* ⚠️ VOICI le coupable, isolé par une mesure qui descend au plus PROFOND.
 *
 * Trier par largeur ne donnait que des ancêtres tous à 505 px — ils
 * subissaient. En cherchant les boîtes dont le CONTENU déborde, la chaîne se
 * termine nettement :
 *
 *     prof.18  boîte 180 / contenu 310   div.content-half-part
 *     prof.17  boîte 360 / contenu 490   div.dashboard-widget.orders
 *     …et l'écart remonte jusqu'à 505 au niveau de la page.
 *
 * Le widget « Orders » de Dokan coupe son bloc en deux demi-colonnes de 180 px.
 * Sur un bureau elles tiennent ; sur un téléphone, « Processing » et son
 * compteur demandent 310 px et poussent toute la page.
 *
 * Les demi-colonnes redeviennent des lignes pleines. C'est la seule chose à
 * changer : le reste du widget est correct, et il reste celui de Dokan. */
/* ⚠️ Et une deuxième leçon, à UN ESPACE près.
 *
 * Première version : `html body .dokan-dashboard .content-half-part`. Sans
 * effet — la chaîne de débordement était identique après déploiement.
 *
 * `body .dokan-dashboard` désigne un DESCENDANT du corps portant cette classe.
 * Or `dokan-dashboard` est une classe DU CORPS lui-même : il aurait fallu
 * `body.dokan-dashboard`, sans espace. Le sélecteur était valide, il ne
 * désignait simplement rien.
 *
 * On vise donc `.dokan-dashboard-wrap`, qui figure explicitement dans la chaîne
 * mesurée — un repère relevé plutôt que déduit. */
@media (max-width: 767px) {
    html body .dokan-dashboard-wrap .content-half-part,
    html body.dokan-dashboard .content-half-part {
        width: 100% !important;
        float: none !important;
        min-width: 0;
        box-sizing: border-box;
    }

    html body .dokan-dashboard-wrap .list-count li,
    html body.dokan-dashboard .list-count li {
        display: flex;
        align-items: center;
        justify-content: space-between;
        gap: 1rem;
    }

    /* Le widget lui-même, et le conteneur qui le porte. */
    html body .dokan-dashboard-wrap .dashboard-widget,
    html body .dokan-dashboard-wrap .dokan-w6 {
        width: 100% !important;
        float: none !important;
        min-width: 0;
        max-width: 100%;
        box-sizing: border-box;
    }
}

/* Le graphique des ventes est dessiné à une largeur fixe : on le laisse
   défiler dans son propre cadre plutôt que d'élargir la page entière. */
html body .dokan-dashboard [class*="chart"],
html body .dokan-dashboard canvas,
html body .dokan-dashboard svg {
    max-width: 100%;
    height: auto;
}

html body .dokan-dashboard table {
    display: block;
    max-width: 100%;
    overflow-x: auto;
}

/* Les compteurs de Dokan : sa structure, notre lisibilité. */
html body .dokan-dashboard .big-counter .count,
html body .dokan-dashboard .list-count .count {
    font-variant-numeric: tabular-nums;
    font-weight: 700;
}

html body .dokan-dashboard ul,
html body .dokan-dashboard-menu,
html body .dokan-dash-sidebar ul {
    list-style: none !important;
    margin: 0;
    padding: 0;
}

html body .dokan-dashboard-menu li,
html body .dokan-dash-sidebar li {
    list-style: none !important;
}

html body .dokan-dashboard-menu a,
html body .dokan-dash-sidebar a {
    display: flex;
    align-items: center;
    gap: 0.65rem;
    /* 48 px : c'est de la navigation, et elle se touche au pouce. */
    min-height: 48px;
    padding: 0.5rem 0.75rem;
    border-bottom: 1px solid var(--tz-trait, #e7e2dd);
    /* Le bleu par défaut du navigateur n'appartient à aucune charte. */
    color: var(--tz-encre, #1c1917) !important;
    text-decoration: none;
    font-size: 15px;
}

html body .dokan-dashboard-menu a:hover,
html body .dokan-dash-sidebar a:hover {
    background: var(--tz-orange-voile, #fff4ec);
    color: var(--tz-orange-sombre, #d95f10) !important;
}

html body .dokan-dashboard-menu li.active > a,
html body .dokan-dash-sidebar li.active > a {
    color: var(--tz-orange-sombre, #d95f10) !important;
    font-weight: 700;
    border-left: 3px solid var(--tz-orange, #ff7c25);
}

/* Les sous-menus se distinguent par le retrait et la taille, pas par une
   puce : une liste imbriquée sans hiérarchie visible se lit comme une liste
   plate de vingt-six entrées, ce qui est exactement le problème. */
html body .dokan-dashboard-menu ul a,
html body .dokan-dash-sidebar ul ul a {
    padding-left: 2.25rem;
    font-size: 14px;
    color: var(--tz-encre-douce, #57534e) !important;
}

/* Les pictogrammes de Dokan gardent leur place mais cessent de porter la
   couleur du lien : ils sont un repère, pas une information. */
html body .dokan-dashboard-menu a i,
html body .dokan-dash-sidebar a i {
    color: var(--tz-encre-douce, #57534e);
    width: 1.25rem;
    text-align: center;
    flex: 0 0 auto;
}

/* La page réserve la barre du bas, comme partout ailleurs. */
@media (max-width: 991px) {
    html body.dokan-dashboard {
        padding-bottom: calc(92px + env(safe-area-inset-bottom, 0px));
    }
}

/* ==========================================================================
   L'accueil : chercher d'abord, choisir ensuite
   ==========================================================================

   La recherche était impossible — l'onglet du bas pointe vers `#`. Les
   catégories étaient enfouies dans un tiroir. Les deux remontent en tête de
   l'accueil, comme sur la maquette validée.

   La rangée de catégories défile horizontalement plutôt que de s'empiler :
   dix catégories empilées repousseraient les produits hors de l'écran, et la
   page d'accueil sert à voir des produits.
   ========================================================================== */

html body .tz-accueil-entete {
    display: grid;
    gap: 0.7rem;
    padding: 0.75rem 1rem 0.25rem;
    background: #fff;
}

html body .tz-recherche {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    padding: 0 0.9rem;
    border: 1px solid var(--tz-trait, #e7e2dd);
    border-radius: 999px;
    background: var(--tz-fond, #fffdfb);
}

html body .tz-recherche-icone {
    color: var(--tz-encre-douce, #57534e);
    font-size: 1.1rem;
    line-height: 1;
}

html body .tz-recherche input[type="search"] {
    flex: 1 1 auto;
    border: 0 !important;
    background: transparent !important;
    /* 16 px : en dessous, Safari iOS zoome à la mise au point et la page
       saute. Sur le premier champ de l'accueil, c'est le pire endroit. */
    font-size: 16px;
    height: 46px;
    padding: 0;
    outline: none;
}

html body .tz-categories-rangee {
    display: flex;
    gap: 0.5rem;
    overflow-x: auto;
    /* La rangée touche les bords : elle doit se sentir défilable, et non
       s'arrêter avant la marge comme un bloc fini. */
    margin: 0 -1rem;
    padding: 0 1rem 0.4rem;
    scrollbar-width: none;
}

html body .tz-categories-rangee::-webkit-scrollbar {
    display: none;
}

html body .tz-categorie-puce {
    flex: 0 0 auto;
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
    min-height: 38px;
    padding: 0 0.85rem;
    border: 1px solid var(--tz-trait, #e7e2dd);
    border-radius: 999px;
    background: #fff;
    color: var(--tz-encre, #1c1917) !important;
    font-size: 13px;
    white-space: nowrap;
    text-decoration: none;
}

html body .tz-categorie-puce small {
    color: var(--tz-encre-douce, #57534e);
    font-variant-numeric: tabular-nums;
    font-size: 11.5px;
}

html body .tz-categorie-puce:hover {
    border-color: var(--tz-orange, #ff7c25);
    color: var(--tz-orange-sombre, #d95f10) !important;
}

/* --------------------------------------------------------------------------
   Le pied de page : des rubriques qui se replient
   --------------------------------------------------------------------------
   Le titre devient une commande : il en porte donc les marques — une cible de
   48 px, un curseur, et un chevron qui dit dans quel sens ça va s'ouvrir.
   -------------------------------------------------------------------------- */

@media (max-width: 767px) {
    html body footer.site-footer .tz-pied-titre {
        display: flex;
        align-items: center;
        justify-content: space-between;
        min-height: 48px;
        margin: 0;
        padding: 0.5rem 0;
        cursor: pointer;
        border-top: 1px solid var(--tz-trait, #e7e2dd);
        border-bottom: 0;
    }

    html body footer.site-footer .tz-pied-titre::after {
        content: "＋";
        color: var(--tz-orange-sombre, #d95f10);
        font-weight: 400;
        font-size: 1.1rem;
        line-height: 1;
    }

    html body footer.site-footer .tz-pied-titre[aria-expanded="true"]::after {
        content: "−";
    }

    html body footer.site-footer .tz-pied-titre:focus-visible {
        outline: 2px solid var(--tz-orange, #ff7c25);
        outline-offset: 2px;
    }

    html body footer.site-footer .tz-pied-corps {
        padding-bottom: 0.6rem;
    }
}

/* ==========================================================================
   Les pages sont sur FOND BLANC
   ==========================================================================

   Mesuré le 2026-08-11 sur l'accueil : le corps et la zone de contenu portent
   une IMAGE de fond, pas une couleur. C'est l'orange qu'on voit derrière les
   cartes sur les captures du client, et qui fait ressortir chaque carte comme
   un rectangle posé sur un décor.

   Les autres écrans — catalogue, fiche, compte — sont déjà en `rgb(255,255,255)`.
   L'accueil est le seul à diverger, et c'est lui qu'on voit en premier.

   Le fond redevient blanc : les cartes portent déjà leur propre séparation par
   le trait et l'ombre. Un décor sous des cartes ajoute du bruit à une page qui
   doit se lire d'un coup d'œil.

   ⚠️ On neutralise l'IMAGE, pas la couleur : une couleur de fond posée par une
   promotion saisonnière reste possible. C'est l'image qui crée le décor.
   ========================================================================== */

/*
 * ⚠️ `background-color: #fff !important` A ÉTÉ RETIRÉ D'ICI, et c'est la
 * quatrième fois aujourd'hui que je me heurte à mon propre passage précédent.
 *
 * Cette règle était juste quand elle a été écrite : l'accueil portait une
 * IMAGE de fond qui faisait décor, et le client demandait alors des pages
 * blanches. Elle a rempli son office.
 *
 * Mais elle porte un `!important` et une classe, et elle a bloqué le papier
 * teinté d'aujourd'hui sans rien dire — le corps restait `rgb(255,255,255)`
 * pendant que je cherchais quelle règle du thème me battait. Ce n'était pas
 * le thème.
 *
 * L'IMAGE reste neutralisée : c'est elle qui créait le décor, et cette moitié
 * de la règle n'a jamais été en cause. La COULEUR revient au papier commun,
 * pour que l'accueil ne soit pas la seule page à diverger — c'était déjà
 * l'argument de la version d'origine, dans l'autre sens.
 */
html body.home,
html body.home .site-content,
html body.home #content,
html body.home main {
    background-image: none !important;
}

/* ⚠️ Celui-ci était le plus dommageable : il assombrissait le FOND de
   l'accueil pendant que les cartes produit restaient blanches. Le contraire
   exact d'un mode sombre. Retiré — voir la note en tête de fichier. */

/* ==========================================================================
   La fiche produit : le bouton d'achat prend toute la largeur
   ==========================================================================

   Mesuré : 106 px de large sur un écran de 390. J'avais corrigé sa COULEUR il
   y a quelques jours et annoncé la fiche traitée — la largeur, elle, n'avait
   jamais été touchée. Corriger une propriété et déclarer l'écran fait est
   l'erreur que ce relevé vient de rattraper.

   Sur la fiche, c'est l'action unique de l'écran. Elle ne se partage avec rien.
   ========================================================================== */

@media (max-width: 767px) {
    html body article.single-product button.single_add_to_cart_button,
    html body .single_add_to_cart_button {
        width: 100% !important;
        min-height: 48px;
        justify-content: center;
    }

    /* La quantité au-dessus, pleine largeur elle aussi : côte à côte, elles se
       disputent 390 px et le bouton perd. */
    html body article.single-product form.cart {
        display: flex;
        flex-direction: column;
        gap: 0.6rem;
        align-items: stretch;
    }

    html body article.single-product form.cart .quantity {
        width: 100%;
    }
}

/* ==========================================================================
   Les icônes de réseaux sociaux : des carrés gris vides
   ==========================================================================

   Signalé sur la fiche produit, et mesuré : sept éléments de liste sans aucun
   texte. Ce ne sont pas des puces cassées — ce sont les liens sociaux
   (`ul.social-media`, `ul.color-theme`), dont le glyphe ne s'affiche pas. Le
   lien est bien là (`<a class="facebook" href="…">`), c'est son pictogramme
   qui manque.

   Deux défauts en un :
     - sans glyphe ET sans texte, le lien n'est identifiable par personne — ni
       à l'œil, ni au lecteur d'écran ;
     - les tailles varient : 44×44 pour Facebook, 30×40 pour WhatsApp et
       Telegram, sous la cible tactile.

   On ne peut pas faire apparaître une police d'icônes absente. On peut rendre
   le lien reconnaissable et atteignable : une pastille de taille égale, et son
   nom lisible par les technologies d'assistance.
   ========================================================================== */

html body ul.social-media li a,
html body ul.color-theme li a {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 44px;
    height: 44px;
    border-radius: 50%;
    border: 1px solid var(--tz-trait, #e7e2dd);
    color: var(--tz-encre-douce, #57534e);
}

html body ul.social-media li,
html body ul.color-theme li {
    list-style: none;
}

/* Le repli textuel : la première lettre du réseau, quand aucun glyphe ne
   s'affiche. Mieux vaut un « f » lisible qu'un carré vide — et le `::after`
   ne s'ajoute pas au glyphe s'il finit par charger, puisqu'il n'occupe la
   place que lorsque le lien est vide. */
html body ul.color-theme li a:empty::after,
html body ul.social-media li a:empty::after {
    font-weight: 700;
    font-size: 15px;
    text-transform: uppercase;
}

html body ul.color-theme li a.facebook:empty::after { content: "f"; }
html body ul.color-theme li a.youtube:empty::after { content: "▶"; }
html body ul.color-theme li a.whatsapp:empty::after { content: "✆"; }
html body ul.color-theme li a.instagram:empty::after { content: "◎"; }
html body ul.color-theme li a.telegram:empty::after { content: "✈"; }

/* ==========================================================================
   Le compteur de produits, à côté de chaque catégorie
   ==========================================================================

   Il répond à « qu'est-ce qu'il y a derrière ? » sans qu'on ait à ouvrir. Il
   se lit comme une annotation, pas comme une alerte : gris, discret, aligné à
   droite — surtout pas orange, qui est ici la couleur de ce sur quoi on clique.
   ========================================================================== */

html body .tz-compteur-categorie {
    margin-left: auto;
    padding-left: 0.5rem;
    color: var(--tz-encre-douce, #6b7176);
    font-size: 0.8rem;
    font-weight: 500;
    font-variant-numeric: tabular-nums;
}

/* ==========================================================================
   Les champs : une seule forme, et jamais sous 16 px
   ==========================================================================

   Relevé le 2026-08-11, trois formes distinctes sur les mêmes écrans :

     42 px · police 18.4 px
     44 px · police 15 px
     42 px · police 14 px

   Même rayon et même bordure, mais des hauteurs et des tailles de police qui
   changent d'un champ à l'autre. Dans un formulaire, cela se lit comme si
   certains champs étaient plus importants que d'autres.

   ⚠️ ET UN DÉFAUT QUI N'EST PAS COSMÉTIQUE. Safari sur iOS ZOOME
   automatiquement quand on met le doigt dans un champ dont la police est
   inférieure à 16 px. La page saute, se recentre, et l'on tape à l'aveugle —
   sur un formulaire de paiement, c'est un panier abandonné. Les 14 px et
   15 px relevés déclenchent ce zoom.

   16 px n'est donc pas un choix esthétique : c'est le seuil au-dessous duquel
   le navigateur décide à notre place.
   ========================================================================== */

/* ⚠️ 46 px, la valeur que le thème tient déjà — pas 44.
 *
 * Deux passes n'ont pas suffi. Mesuré : les `<input>` sortent à 46 px avec un
 * `height: 46px` calculé, donc une règle du thème plus spécifique que la
 * mienne. Seul le `<select>` obéissait, à 44.
 *
 * J'aurais pu empiler un `!important` de plus pour gagner deux pixels. Ce
 * serait une victoire de spécificité, pas un correctif : chaque `!important`
 * posé pour forcer une valeur arbitraire rend la feuille un peu plus difficile
 * à reprendre, et la prochaine règle devra crier plus fort encore.
 *
 * L'objectif était l'UNIFORMITÉ, pas 44. On aligne donc sur ce que le thème
 * impose déjà à la majorité — 46 px reste bien au-dessus de la cible tactile.
 * Choisir la valeur qui demande le moins de force est aussi une décision. */
html body input:not([type="hidden"]):not([type="checkbox"]):not([type="radio"]):not([type="submit"]),
html body select,
html body textarea {
    height: 46px;
    min-height: 46px;
    font-size: 16px;
    border-radius: 8px;
    border: 1px solid var(--tz-bord-champ, #ced4da);
    background: #fff;
    padding: 0.5rem 0.75rem;
    box-sizing: border-box;
}

/* La zone de texte fait exception : sa raison d'être est d'accueillir
   plusieurs lignes. La hauteur fixe ne s'y applique pas. */
html body textarea {
    height: auto;
    min-height: 96px;
    line-height: 1.5;
}

html body input:focus-visible,
html body select:focus-visible,
html body textarea:focus-visible {
    outline: 2px solid #ff7c25;
    outline-offset: 1px;
    border-color: #ff7c25;
}

/* Le champ de quantité reste étroit : ce n'est pas un champ de saisie libre,
   et l'élargir à 44 px de large casserait le trio « − 1 + ». */
html body input.qty {
    padding-left: 0.25rem;
    padding-right: 0.25rem;
    text-align: center;
}

/* --------------------------------------------------------------------------
   Les réseaux sociaux du pied : 30 × 40 px, donc trop étroits
   --------------------------------------------------------------------------
   Mesuré : trois liens de 30 px de large. La recommandation d'accessibilité
   comme les guides d'Apple et de Google convergent sur 44 px : en dessous, on
   vise et l'on rate. Ce sont trois liens, ils ne coûtent rien à agrandir.
   -------------------------------------------------------------------------- */

html body footer.site-footer a[href*="facebook"],
html body footer.site-footer a[href*="instagram"],
html body footer.site-footer a[href*="twitter"],
html body footer.site-footer a[href*="x.com"],
html body footer.site-footer a[href*="linkedin"],
html body footer.site-footer a[href*="youtube"],
html body footer.site-footer a[href*="tiktok"] {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 44px;
    height: 44px;
    border-radius: 50%;
    border: 1px solid var(--tz-bord, rgba(0, 0, 0, 0.12));
}

/* ==========================================================================
   Les cartes produit : UNE forme, pas sept
   ==========================================================================

   Relevé sur l'accueil le 2026-08-11 : 66 cartes, SEPT formes distinctes. Les
   trois dominantes, nommées par le thème lui-même :

     style-6  25×  image → cœur → titre → boutique → prix → bouton
     style-1  22×  image → prix → titre → boutique → bouton → cœur
     style-3   9×  image → cœur → titre → bouton → prix

   Le prix passe avant ou après le titre, le cœur se pose sur l'image ou sous la
   carte, le bouton change de place. Côte à côte dans la même grille, cela se
   voit immédiatement — c'est ce que le client a signalé.

   La structure, elle, est LA MÊME partout :

     div.product-wrapper.style-N > div.product-inner
        ├ div.thumbnail-wrapper.entry-media   (image, parfois le cœur)
        └ div.content-wrapper                 (titre, boutique, prix, bouton)

   On n'a donc pas à réécrire trois gabarits : il suffit d'imposer un ordre dans
   `.content-wrapper` et une place au cœur. L'ordre retenu est celui des 25
   cartes majoritaires — le plus courant sur le site, donc le moins dépaysant.

   ⚠️ `order` ne s'applique qu'aux ENFANTS DIRECTS d'un conteneur flex. Si le
   thème imbrique l'un de ces blocs plus bas, la règle le concernant ne fera
   rien — sans casser les autres. C'est mesuré après coup, pas supposé.
   ========================================================================== */

html body div.product-wrapper div.product-inner {
    position: relative;
    display: flex;
    flex-direction: column;
    height: 100%;
}

html body div.product-wrapper div.content-wrapper {
    display: flex;
    flex-direction: column;
    gap: 0.35rem;
    /* La carte occupe la hauteur disponible pour que les boutons s'alignent
       d'une carte à l'autre. Des boutons en escalier dans une grille donnent
       l'impression que les cartes n'ont pas la même importance. */
    flex: 1 1 auto;
}

html body div.product-wrapper div.content-wrapper > h2,
html body div.product-wrapper div.content-wrapper > h3,
html body div.product-wrapper div.content-wrapper > .woocommerce-loop-product__title {
    order: 1;
    /* Deux lignes : au-delà, les cartes se décalent les unes des autres. */
    display: -webkit-box;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 2;
    line-clamp: 2;
    overflow: hidden;
    margin: 0;
    font-size: 0.95rem;
    line-height: 1.35;
}

/* ⚠️ `product-content-switcher`, pas `[class*="store"]`.
 *
 * Première version : j'avais DEVINÉ les noms de classe du bloc boutique et du
 * bouton. Les deux sélecteurs n'ont rien attrapé, ces blocs sont restés à
 * `order: 0` — donc AVANT le titre (1) et le prix (3) — et la carte affichait
 * boutique → bouton → titre → prix. Le témoin l'a dit : l'ordre obtenu n'était
 * pas celui demandé.
 *
 * Deviner un nom de classe et le lire coûtent le même temps. Seul le second
 * donne un résultat. */
html body div.product-wrapper div.content-wrapper > .product-content-switcher,
html body div.product-wrapper div.content-wrapper > [class*="store"],
html body div.product-wrapper div.content-wrapper > [class*="vendor"] {
    order: 2;
    font-size: 0.82rem;
    color: var(--tz-encre-douce, #6b7176);
}

html body div.product-wrapper div.content-wrapper > .price,
html body div.product-wrapper div.content-wrapper > [class*="price"] {
    order: 3;
    font-weight: 700;
    font-variant-numeric: tabular-nums;
}

html body div.product-wrapper div.content-wrapper > .product-buttons,
html body div.product-wrapper div.content-wrapper > .button,
html body div.product-wrapper div.content-wrapper > [class*="add_to_cart"],
html body div.product-wrapper div.content-wrapper > [class*="add-to-cart"] {
    order: 4;
    /* Le bouton se colle au bas de la carte : c'est l'action, elle doit être au
       même endroit sur toutes. */
    margin-top: auto;
}

/* Le cœur, toujours au même endroit : coin haut-droit de l'image.
   Il est tantôt dans la vignette, tantôt dans le contenu selon le gabarit ; en
   le positionnant par rapport à `.product-inner`, les deux cas convergent sans
   qu'on ait à déplacer le moindre nœud. */
html body div.product-wrapper .wishlist-button,
html body div.product-wrapper > [class*="wishlist"],
html body div.product-wrapper div.content-wrapper > [class*="wishlist"] {
    position: absolute;
    top: 0.5rem;
    right: 0.5rem;
    z-index: 3;
    margin: 0;
}

/* ==========================================================================
   La barre du bas : l'ordre des onglets
   ==========================================================================

   Ordre relevé : Home · Account · Cart · Category · Search. L'identité arrive
   en deuxième et la recherche en dernier, alors que l'une sert rarement et
   l'autre à chaque visite.

   L'ordre posé ici suit le parcours d'achat, de gauche à droite :

     Home · Category · Search · Cart · Account

   — découvrir, chercher, puis agir. Le panier et le compte, les deux onglets
   « à moi », restent voisins à droite, sous le pouce.

   Les onglets sont visés par la CLASSE DE LEUR ICÔNE, jamais par leur rang ni
   par leur libellé : le rang est ce qu'on change, et le libellé sera traduit.

   `:has()` n'est pas compris par les très anciens navigateurs ; là où il
   manque, l'ordre d'origine s'applique et rien ne casse.
   ========================================================================== */

html body .klb-mobile-bottom ul > li:has(.klb-icon-home-simple-door) { order: 1; }
html body .klb-mobile-bottom ul > li:has(.klb-icon-view-type-list)   { order: 2; }
html body .klb-mobile-bottom ul > li:has(.klb-icon-search-feather)   { order: 3; }
html body .klb-mobile-bottom ul > li:has([class*="shopping-cart"])   { order: 4; }
html body .klb-mobile-bottom ul > li:has(.klb-icon-account)          { order: 5; }

/* --------------------------------------------------------------------------
   L'onglet « Account » doit dire si l'on est connecté
   --------------------------------------------------------------------------

   Signalé : « l'onglet account a la même tête quand un user est connecté que
   quand il ne l'est pas ». C'est exact — même icône, même couleur, même
   libellé. Rien ne distingue « ouvrir mon compte » de « se connecter », alors
   que ce sont deux intentions différentes.

   WordPress pose déjà `logged-in` sur `<body>` : la distinction ne demande
   aucune donnée supplémentaire, seulement de s'en servir. L'icône passe à
   l'orange de la marque, et une pastille pleine marque la session ouverte —
   le même vocabulaire visuel que le compteur du panier, pour que les deux se
   lisent ensemble.
   -------------------------------------------------------------------------- */

html body.logged-in .klb-mobile-bottom ul > li:has(.klb-icon-account) i {
    color: #ff7c25;
}

html body.logged-in .klb-mobile-bottom ul > li:has(.klb-icon-account) a {
    position: relative;
}

html body.logged-in .klb-mobile-bottom ul > li:has(.klb-icon-account) a::after {
    content: "";
    position: absolute;
    top: 1px;
    right: 4px;
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background: #ff7c25;
    box-shadow: 0 0 0 2px #fff;
}

/* ==========================================================================
   Le bas de page : 1 021 px de liens empilés, dont 14 intouchables
   ==========================================================================

   Mesuré : `footer.site-footer`, 1 021 px de haut, quatre groupes, 20 liens —
   et **14 d'entre eux sous les 40 px** de hauteur, donc sous la cible tactile
   raisonnable. Le tout en une seule colonne, ce qui explique la longueur.

   Deux colonnes de groupes suffisent à diviser la hauteur par deux, et une
   hauteur minimale rend les liens cliquables sans viser. On ne retire aucun
   lien : ce qui est là a été voulu.
   ========================================================================== */

@media (max-width: 991px) {
    html body footer.site-footer .widget,
    html body footer.site-footer [class*="widget-area"] > div {
        break-inside: avoid;
    }

    /* Les listes du pied passent sur deux colonnes ; les titres, eux, restent
       sur toute la largeur pour continuer de séparer les groupes. */
    html body footer.site-footer ul {
        columns: 2;
        column-gap: 1.25rem;
        list-style: none;
        margin: 0;
        padding: 0;
    }

    html body footer.site-footer ul li {
        break-inside: avoid;
    }

    html body footer.site-footer ul li a {
        display: flex;
        align-items: center;
        min-height: 40px;
        font-size: 0.9rem;
        line-height: 1.3;
    }

    html body footer.site-footer h3,
    html body footer.site-footer h4,
    html body footer.site-footer .widget-title {
        font-size: 0.8rem;
        letter-spacing: 0.06em;
        text-transform: uppercase;
        color: var(--tz-encre-douce, #6b7176);
        margin: 1.25rem 0 0.5rem;
        padding-top: 1rem;
        border-top: 1px solid var(--tz-bord, rgba(0, 0, 0, 0.08));
    }
}

/* ==========================================================================
   La pastille du panier, dans la barre du bas
   ==========================================================================

   Le compteur existait déjà — deux `.action-count.cart-count` portant la bonne
   valeur — mais dans l'en-tête de bureau, que le mobile masque. La barre du bas
   n'en avait aucun. Il n'y avait rien à calculer, seulement à afficher là où
   l'on regarde. Le compte vient de `tz-32-compteur-panier.php` et se rafraîchit
   par les fragments de WooCommerce.

   Une pastille à zéro reste MASQUÉE : une bulle vide attire l'œil pour rien.
   ========================================================================== */

/* ⚠️ Spécificité et `!important` sur le POSITIONNEMENT, et là seulement.
 *
 * Première version : `html body .tz-panier-compteur { position: absolute }`.
 * Résultat mesuré — la pastille était bien ronde et orange (donc la règle
 * s'appliquait) mais l'onglet passait de 45 à 63 px de haut, exactement la
 * hauteur de la pastille : elle occupait une place dans le flux. Un élément en
 * `absolute` ne fait pas grandir son parent. Une règle du thème gagnait donc
 * sur `position`, et sur elle seule.
 *
 * Deux propriétés d'un même bloc peuvent avoir des sorts différents : croire
 * qu'un bloc « s'applique » ou « ne s'applique pas » en entier est une
 * approximation qui coûte cher — c'est la couleur qui m'a fait croire au
 * succès pendant que la position échouait.
 *
 * On vise donc par le chemin complet, et l'on force ce qui doit l'être. */
html body .klb-mobile-bottom a .tz-panier-compteur,
html body .tz-panier-compteur {
    position: absolute !important;
    /* Coin haut-droit de l'icône. Le libellé est sous elle : y accrocher la
       pastille la ferait flotter entre les deux, ce qu'on a vu. */
    top: 0 !important;
    right: 2px !important;
    left: auto !important;
    bottom: auto !important;
    min-width: 18px;
    height: 18px;
    padding: 0 5px;
    box-sizing: border-box;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    /* ⚠️ Couleur EN DUR et `!important`, pas la variable.
     *
     * Signalé « compteur transparent ». La pastille héritait d'une opacité du
     * thème appliquée à l'onglet, et la variable `--tz-orange` n'est pas
     * définie partout : là où elle manque, le repli s'appliquait mais restait
     * soumis à l'opacité du parent. Une pastille pâle sur une icône sombre ne
     * se lit pas.
     *
     * L'anneau blanc la détache de l'icône : sans lui, un chiffre orange sur
     * un pictogramme noir se confond avec le dessin. */
    background: #ff7c25 !important;
    box-shadow: 0 0 0 2px #fff;
    opacity: 1 !important;
    color: #fff !important;
    border-radius: 999px;
    font-size: 11px;
    font-weight: 700;
    line-height: 1;
    /* Les chiffres d'un compteur changent de largeur en changeant de valeur ;
       la pastille sauterait à chaque ajout. */
    font-variant-numeric: tabular-nums;
    pointer-events: none;
}

/* ⚠️ Le même chemin que la règle d'affichage, sinon elle perd.
 *
 * Écrite `html body .tz-panier-compteur-vide` (0,1,2), elle se faisait battre
 * par `html body .klb-mobile-bottom a .tz-panier-compteur` (0,4,2) et son
 * `display: inline-flex`. Résultat mesuré : une pastille « 0 » sur un panier
 * vide — exactement ce que la règle devait empêcher.
 *
 * En montant la spécificité d'un bloc, on déplace la ligne d'arrivée de TOUTES
 * ses propriétés, y compris pour les règles voisines qu'on croyait indépendantes. */
html body .klb-mobile-bottom a .tz-panier-compteur-vide,
html body .tz-panier-compteur-vide {
    display: none !important;
}

/* --------------------------------------------------------------------------
   La barre du bas recouvre la fin de chaque page
   --------------------------------------------------------------------------

   Mesuré : barre `fixed`, 92 px, `z-index: 999` — et `padding-bottom: 0` sur le
   corps. Rien ne réserve sa hauteur. Le dernier élément de chaque page passe
   dessous : sur le panier, c'est « Proceed to checkout » qu'on ne peut plus
   atteindre sans savoir qu'il faut faire défiler au-delà du bas apparent.

   La réserve vaut la hauteur mesurée, plus la zone sûre des téléphones à
   encoche (`safe-area-inset-bottom`), qui vaut zéro ailleurs et ne coûte donc
   rien. On la pose sur le corps plutôt que sur chaque page : le défaut n'est
   pas propre au panier, il touche tout ce qui finit en bas.
   -------------------------------------------------------------------------- */

@media (max-width: 991px) {
    html body {
        padding-bottom: calc(92px + env(safe-area-inset-bottom, 0px));
    }
}

/* ==========================================================================
   Le panier en mobile : le prix et le sous-total étaient simplement absents
   ==========================================================================

   Mesuré le 2026-08-11 sur la démonstration, écran de 390 px :

     td.product-price      0 × 0   display:none   data-title="Price"     ₦4.99
     td.product-subtotal   0 × 0   display:none   data-title="Subtotal"  ₦4.99
     td.product-name      99 × 277                — un mot par ligne
     table                372 px dans 390

   Le thème éteint ces deux cellules sans les réafficher ailleurs : le client ne
   voit ni le prix de la ligne, ni son sous-total. Ce n'est pas de l'esthétique,
   c'est une information d'achat qui manque.

   Les `data-title` sont pourtant déjà là — le gabarit responsive de WooCommerce
   était prévu pour empiler les cellules avec leur libellé. On le rétablit au
   lieu d'en inventer un autre.

   Chaque ligne devient une carte : vignette à gauche, informations à droite.

   ---------------------------------------------------------------------------
   Resserré le 2026-08-12 — « le bloc n'est pas bon, c'est fouilli »
   ---------------------------------------------------------------------------
   La première version empilait CINQ rangées — nom, prix, quantité, sous-total,
   suppression — chacune avec son libellé en capitales. 229 px par article :
   trois articles ne tenaient plus dans un écran, et l'on faisait défiler une
   liste d'étiquettes plutôt qu'un panier.

   Trois rangées suffisent, parce que trois questions suffisent : qu'est-ce que
   c'est, combien j'en ai, combien ça fait.

     [vignette]  nom du produit sur deux lignes
     [vignette]  prix unitaire ................ SOUS-TOTAL
     [vignette]  [− 1 +] .................. Remove this item

   La quantité et la suppression partagent une rangée, comme sur les paniers
   qu'on connaît : ce sont les deux gestes qu'on fait ici, et ils vont
   ensemble. Le sous-total monte à côté du prix unitaire, où la comparaison se
   fait d'un coup d'œil au lieu de sauter deux rangées.
   ========================================================================== */

@media (max-width: 767px) {
    html body table.shop_table_responsive thead {
        display: none;
    }

    html body table.shop_table_responsive,
    html body table.shop_table_responsive tbody {
        display: block;
        width: 100%;
    }

    html body table.shop_table_responsive tbody tr.cart_item {
        position: relative;
        display: grid;
        grid-template-columns: 72px minmax(0, 1fr) auto;
        grid-template-areas:
            "image nom      nom"
            "image prix     total"
            "image quantite suppr";
        gap: 0.5rem 0.85rem;
        align-items: center;
        padding: 0.9rem 0;
        border-bottom: 1px solid var(--tz-bord, rgba(0, 0, 0, 0.08));
    }

    html body table.shop_table_responsive tbody tr.cart_item > td {
        display: block;
        width: auto;
        padding: 0;
        border: 0;
    }

    html body table.shop_table_responsive td.product-thumbnail {
        grid-area: image;
    }

    html body table.shop_table_responsive td.product-thumbnail img {
        width: 72px;
        height: 72px;
        object-fit: contain;
    }

    /* Le nom, borné à deux lignes.
     *
     * Signalé : « trop d'écriture, pas besoin de mettre l'intitulé intégral
     * mais les infos essentielles ». Les titres de ce catalogue font jusqu'à
     * vingt mots — « Aveeno Daily Moisturising Body Lotion, With Soothing Oats
     * & Rich Emollients, Suitable For Sensitive Skin… ». Sur 250 px, cela fait
     * six lignes qui repoussent le prix hors de l'écran.
     *
     * Deux lignes suffisent à reconnaître ce qu'on a mis dans son panier : on
     * l'a choisi soi-même une minute plus tôt. Le nom complet reste
     * accessible en ouvrant la fiche. */
    html body table.shop_table_responsive td.product-name {
        grid-area: nom;
        font-weight: 600;
        line-height: 1.35;
        display: -webkit-box;
        -webkit-box-orient: vertical;
        -webkit-line-clamp: 2;
        line-clamp: 2;
        overflow: hidden;
    }

    html body table.shop_table_responsive td.product-name a {
        color: inherit;
    }

    /* ⚠️ `display` en `!important` : c'est la règle du thème qu'on combat, et
       elle porte sur cette propriété précise. Sans cela, la cellule reste à
       zéro et l'on croit la règle sans effet. */
    html body table.shop_table_responsive td.product-price {
        grid-area: prix;
        display: flex !important;
    }

    html body table.shop_table_responsive td.product-quantity {
        grid-area: quantite;
        display: flex !important;
    }

    html body table.shop_table_responsive td.product-subtotal {
        grid-area: total;
        display: flex !important;
        font-weight: 700;
    }

    html body table.shop_table_responsive td.product-price,
    html body table.shop_table_responsive td.product-quantity,
    html body table.shop_table_responsive td.product-subtotal {
        align-items: center;
        gap: 0.4rem;
        font-variant-numeric: tabular-nums;
        /* Un montant très long passe à la ligne au lieu de pousser la colonne
           hors de l'écran — la panne qui a coupé les prix deux fois. */
        flex-wrap: wrap;
    }

    /* Le sous-total est la seule valeur alignée à droite : c'est la convention
       du ticket de caisse, et l'œil descend la colonne des totaux sans avoir à
       lire les libellés. */
    html body table.shop_table_responsive td.product-subtotal {
        justify-self: end;
        justify-content: flex-end;
    }

    /* La suppression partage sa rangée avec la quantité, à droite.
     *
     * Signalé : « mettre la suppression ailleurs ». Elle était en haut à
     * droite, en pastille rouge, à côté du nom — la couleur de l'alerte sur le
     * geste le plus banal du panier, et le premier élément que le pouce
     * rencontre en faisant défiler.
     *
     * Elle est maintenant au bout de la rangée des gestes : on l'y trouve
     * quand on la cherche, on ne la heurte pas quand on ne la cherche pas. */
    html body table.shop_table_responsive td.product-remove {
        grid-area: suppr;
        justify-self: end;
    }

    /* Le libellé vient de `data-title`, posé par WooCommerce. On ne le recopie
       pas : il est déjà traduit, et une seconde copie divergerait. */
    /*
     * ⚠️ « QUANTITY » a été RETIRÉ de cette liste.
     *
     * Sur 97 px de colonne, le libellé et le sélecteur ne tenaient pas côte à
     * côte : le libellé passait à la ligne, la carte gagnait une rangée, et le
     * bouton de suppression se retrouvait décalé de son sélecteur.
     *
     * Mais la vraie raison n'est pas la place. Des trois libellés, c'est le
     * seul qui n'apprend rien : « PRICE ₦4.99 » et « SUBTOTAL ₦4.99 »
     * distinguent deux montants qui se ressemblent, tandis qu'un « − 1 + » se
     * lit sans qu'on le nomme. Le retirer n'a rien coûté à la compréhension —
     * gagner de la place n'aurait pas suffi à le justifier.
     */
    html body table.shop_table_responsive td.product-price::before,
    html body table.shop_table_responsive td.product-subtotal::before {
        content: attr(data-title);
        font-weight: 500;
        font-size: 0.85rem;
        letter-spacing: 0.02em;
        text-transform: uppercase;
        color: var(--tz-encre-douce, #6b7176);
    }

    /* ⚠️ UNE RÈGLE A ÉTÉ RETIRÉE D'ICI, et elle était de moi.
     *
     * Elle posait `position: absolute !important` sur cette cellule pour
     * éloigner la croix de la vignette — un vrai défaut, à l'époque, corrigé
     * par un vrai moyen.
     *
     * Mais hors flux, la cellule ne participe plus à la grille. Quand j'ai
     * voulu la descendre en bas de carte, mon `grid-area: suppr` n'a rien fait
     * et le bouton s'est mis à recouvrir le nom du produit SUIVANT — six
     * chevauchements mesurés.
     *
     * J'ai d'abord ajouté `position: static !important` plus haut, qui gagnait
     * par l'ordre du fichier. Deux règles contraires cohabitaient alors, dont
     * une ne servait qu'à être battue : le prochain à lire n'aurait pas su
     * laquelle fait foi. La correction va là où était la cause. */

    html body table.shop_table_responsive td.product-remove a {
        /* La cible reste large et l'intitulé lisible : elle partage désormais
           sa rangée avec la quantité, et rien ne la presse. */
        display: inline-flex;
        align-items: center;
        justify-content: center;
        min-height: 40px;
    }

    /* Le champ de quantité reste manipulable au doigt. */
    html body table.shop_table_responsive td.product-quantity input.qty {
        min-height: 40px;
    }
}

/* ==========================================================================
   Les messages : dire ce qui vient de se passer, sans crier
   ==========================================================================

   Mesuré le 2026-08-11 sur la démonstration, en mobile :

     .woocommerce-message   360 × 101 px, fond rgb(41,132,59), texte blanc 16 px,
                            et le TITRE COMPLET du produit à l'intérieur.

   Un tiers de l'écran occupé par une phrase qu'on ne lit pas — « “Tizzle HDMI
   Cable 0.9m, 2 pack – 18Gbps High Speed with Ethernet, 4K@60Hz, 2160p, (Gold)
   Black” has been added to your cart. » Le nom du produit n'apporte rien ici :
   la personne vient de cliquer dessus, elle sait ce qu'elle a ajouté. Ce
   qu'elle cherche, c'est le lien vers le panier.

   On garde donc le message, on le rend lisible : deux lignes au plus, le nom
   tronqué proprement, et « View cart » qui reste un vrai bouton.

   Le vert du thème est conservé — c'est la couleur de la confirmation, et la
   remplacer par l'orange de la marque brouillerait le sens : l'orange, ici,
   c'est ce sur quoi on peut cliquer.
   ========================================================================== */

html body .woocommerce-message {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.5rem 1rem;
    padding: 0.85rem 1rem;
    font-size: 0.95rem;
    line-height: 1.45;
    border-radius: var(--tz-rayon, 10px);
}

/* Le nom du produit, borné à deux lignes. `-webkit-line-clamp` est le seul
   moyen fiable de tronquer plusieurs lignes ; il est compris par tous les
   navigateurs visés ici, Chrome Android en tête — l'essentiel du trafic. */
html body .woocommerce-message > :not(.button):not(a.button) {
    display: -webkit-box;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 2;
    line-clamp: 2;
    overflow: hidden;
    min-width: 0;
    flex: 1 1 12rem;
}

html body .woocommerce-message a.button {
    flex: 0 0 auto;
    min-height: 40px;
    display: inline-flex;
    align-items: center;
    white-space: nowrap;
}

/* --------------------------------------------------------------------------
   La modale de la liste de souhaits : deux boutons, deux rôles
   --------------------------------------------------------------------------

   Relevé : « View Wishlist » et « Close » avaient EXACTEMENT le même fond
   orange. Deux boutons identiques ne proposent pas un choix, ils posent une
   devinette — et le plus gros risque est que la personne ferme là où elle
   voulait aller voir.

   L'orange reste à l'action ; fermer redevient une sortie discrète.
   -------------------------------------------------------------------------- */

html body .klbwl-popup a[href="#"],
html body .klbwl-popup button.klbwl-close,
html body .klbwl-popup .klbwl-popup-close {
    background: transparent !important;
    color: var(--tz-encre, #1b1f22) !important;
    border: 1px solid var(--tz-bord, rgba(0, 0, 0, 0.15)) !important;
}

html body .klbwl-popup a[href="#"]:hover,
html body .klbwl-popup button.klbwl-close:hover {
    border-color: var(--tz-orange, #ff7c25) !important;
    color: var(--tz-orange, #ff7c25) !important;
}

/* ==========================================================================
   « Mon compte » : UN seul écran, pas cinq empilés
   ==========================================================================

   Relevé le 2026-08-11 sur la démonstration, en mobile et avec une session :

     .yith-wcmap                     370 px   avatar + Logout + 5 entrées
     .myaccount-menu                 250 px   les 5 MÊMES entrées
     .dokan-account-migration-lists  118 px   « Become a Vendor »
     la salutation de WooCommerce             « Hello … (not …? Log out) »
     .tz-compte                      476 px   le nôtre

   Soit 1 214 px de doublons, trois boutons de déconnexion, et deux navigations
   identiques. Notre bloc s'AJOUTAIT au lieu de remplacer : c'est le défaut, et
   il est structurel, pas cosmétique.

   ⚠️ Le masquage est borné au tableau de bord (`.tz-compte-tableau-de-bord`,
   posée par `gabarit-compte.php` via `is_wc_endpoint_url()`). `.myaccount-menu`
   est la seule navigation des SOUS-PAGES : la masquer partout enfermerait le
   client dans la page où il vient d'entrer.

   Et rien n'est perdu : les entrées de ces blocs — « Payment Methods »,
   « Points & Referrals », « Become a Vendor » — sont désormais reprises dans le
   nôtre, lues depuis `wc_get_account_menu_items()` plutôt que recopiées.
   ========================================================================== */

/* YITH est masqué PARTOUT : c'est un doublon du menu du thème, avec un avatar
   en plus. Le borner au tableau de bord le laissait reparaître dès qu'on
   cliquait sur « Downloads » — c'est le « profil incongru » signalé par le
   client, et il venait de moi.

   Son bouton de déconnexion était le seul des sous-pages : il est remplacé par
   le bandeau que `gabarit-compte.php` rend désormais sur tous les écrans du
   compte. */
html body .yith-wcmap,
html body .user-profile {
    display: none !important;
}

/* Le menu du thème et le bloc Dokan, eux, ne disparaissent que sur le tableau
   de bord — où notre bloc les reprend. Sur les sous-pages, le menu reste la
   navigation, restylée plus bas. */
html body.tz-compte-tableau-de-bord .myaccount-menu,
html body.tz-compte-tableau-de-bord .dokan-account-migration-lists {
    display: none !important;
}

/* Le bandeau des sous-pages : la même identité, en plus compact — il coiffe un
   contenu, il ne le remplace pas. */
html body .tz-compte-bandeau-souspage {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    padding: 0.85rem 1rem;
    margin-bottom: 1rem;
    background: var(--tz-orange-voile, rgba(255, 124, 37, 0.08));
    border-radius: var(--tz-rayon, 10px);
}

html body .tz-compte-bandeau-souspage .tz-compte-identite {
    display: flex;
    flex-direction: column;
    min-width: 0;
    flex: 1 1 auto;
}

/* ⚠️ Le contraste, hérité du bandeau du tableau de bord.
 *
 * Celui-ci est ORANGE PLEIN, donc son texte est blanc. Le bandeau des
 * sous-pages est sur fond clair : le blanc y devient illisible. Vérifié sur
 * capture — les initiales et « Log out » disparaissaient presque.
 *
 * Réutiliser une classe, c'est aussi hériter de ce qu'elle suppose de son
 * fond. Les couleurs sont donc redéclarées ici, pas laissées à l'héritage. */
html body .tz-compte-bandeau-souspage,
html body .tz-compte-bandeau-souspage .tz-compte-nom {
    color: var(--tz-encre, #1b1f22);
}

html body .tz-compte-bandeau-souspage .tz-compte-initiales {
    background: #ff7c25;
    color: #fff;
    width: 36px;
    height: 36px;
    border-radius: 50%;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-weight: 700;
    flex: 0 0 auto;
}

/* `!important` sur la couleur : la règle du bandeau ORANGE cible
 * `.tz-compte-bandeau .tz-compte-sortie` — même nombre de classes que la
 * mienne, mais déclarée plus haut dans la feuille, donc elle gagne à égalité.
 * Vérifié sur capture : le lien restait blanc sur fond clair, illisible. */
html body .tz-compte-bandeau-souspage .tz-compte-sortie {
    color: #ff7c25 !important;
    opacity: 1 !important;
    font-weight: 600;
    text-decoration: underline;
    white-space: nowrap;
}

/* Le nom peut être un numéro de treize chiffres : il ne doit pas pousser le
   bouton de déconnexion hors de l'écran. */
html body .tz-compte-bandeau-souspage .tz-compte-nom {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

html body .tz-compte-retour {
    font-size: 0.78rem;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: var(--tz-encre-douce, #6b7176);
    text-decoration: none;
}

html body .tz-compte-retour::before {
    content: "‹ ";
    color: #ff7c25;
}

/* La navigation des sous-pages, mise au même dessin que nos listes. */
html body:not(.tz-compte-tableau-de-bord) .myaccount-menu ul,
html body:not(.tz-compte-tableau-de-bord) .myaccount-menu {
    list-style: none;
    margin: 0 0 1.25rem;
    padding: 0;
}

html body:not(.tz-compte-tableau-de-bord) .myaccount-menu li a {
    display: flex;
    align-items: center;
    justify-content: space-between;
    min-height: 48px;
    padding: 0.6rem 0.25rem;
    border-bottom: 1px solid var(--tz-bord, rgba(0, 0, 0, 0.08));
    text-decoration: none;
    color: inherit;
}

html body:not(.tz-compte-tableau-de-bord) .myaccount-menu li.is-active a,
html body:not(.tz-compte-tableau-de-bord) .myaccount-menu li.woocommerce-MyAccount-navigation-link--active a {
    color: #ff7c25;
    font-weight: 600;
}

/* La salutation native, qui porte le troisième « Log out ». Elle est le
   premier paragraphe du contenu, sans classe à elle : on la vise par sa
   position, et uniquement sur cet écran. */
html body.tz-compte-tableau-de-bord .woocommerce-MyAccount-content > p:first-of-type {
    display: none !important;
}

/* La navigation reprise : des lignes, pas des cartes — c'est une liste de
   destinations, et la présenter en tuiles donnerait le même poids visuel à
   « Payment methods » qu'à « Orders », qui porte un chiffre. */
html body .tz-compte-liens {
    list-style: none;
    margin: 0;
    padding: 0;
}

html body .tz-compte-liens li + li {
    border-top: 1px solid var(--tz-bord, rgba(0, 0, 0, 0.08));
}

html body .tz-compte-liens a {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 1rem;
    /* 48 px : la cible tactile minimale. Ces lignes sont l'essentiel de la
       navigation en mobile, elles ne peuvent pas être serrées. */
    min-height: 48px;
    padding: 0.75rem 0.25rem;
    text-decoration: none;
    color: inherit;
}

html body .tz-compte-liens a:hover,
html body .tz-compte-liens a:focus-visible {
    color: var(--tz-orange, #ff7c25);
}

html body .tz-compte-chevron {
    color: var(--tz-orange, #ff7c25);
    font-size: 1.4rem;
    line-height: 1;
}

/* ==========================================================================
   Le bouton « Register » ne doit plus se dérober sous le doigt
   ==========================================================================

   Mesuré le 2026-08-11 : quitter le champ mot de passe insère
   `div.woocommerce-password-strength`, haut de 36 px, et descend le bouton
   d'autant — davantage que sa demi-hauteur.

   Ce que vit un visiteur : il tape son mot de passe, vise « Register »,
   appuie… et au relâchement le bouton n'est plus là. Aucun clic n'est émis,
   rien n'est envoyé, aucun message n'apparaît. Il faut cliquer une seconde
   fois pour s'inscrire, sans jamais savoir pourquoi la première n'a rien fait.

   Le relevé événementiel l'a établi : `mousedown` sur le bouton, puis ni
   `mouseup` ni `click`, et un clic reçu par le FORMULAIRE — l'ancêtre commun
   de deux points devenus différents.

   Le correctif ne cache pas la jauge, qui est utile : il lui réserve sa place
   à l'avance, pour que son apparition ne pousse plus rien.
   ========================================================================== */

html body form.woocommerce-form-register p.woocommerce-form-row:has(#reg_password),
html body form.register p.woocommerce-form-row:has(#reg_password) {
    position: relative;
    /* 36 px de jauge, et son écart au champ. La place est prise, occupée ou non. */
    padding-bottom: 2.75rem;
}

html body form.woocommerce-form-register div.woocommerce-password-strength,
html body form.register div.woocommerce-password-strength {
    position: absolute;
    left: 0;
    right: 0;
    bottom: 0;
    margin: 0;
}

/* ==========================================================================
   TZ-41 — la bannière de promotion, à nos couleurs
   ==========================================================================

   Le carrousel du thème montrait sept diapositives sur fond cyan. Celle-ci en
   montre UNE, dans la palette de la charte, et son contenu se règle dans le
   personnalisateur.

   ⚠️ Le dégradé va de l'orange de la charte à une version plus sombre du MÊME
   ton, pas vers une seconde couleur. Un dégradé bicolore ferait un troisième
   coloris à tenir sur tout le site ; celui-ci reste un seul orange, éclairé
   d'un côté.
   ========================================================================== */

html body .tz-promo {
    display: grid;
    grid-template-columns: 1fr;
    gap: 0.9rem;
    align-items: center;
    margin: 0.25rem 1rem 1rem;
    padding: 1.25rem 1.25rem 1.35rem;
    border-radius: var(--tz-rayon, 12px);
    background: linear-gradient(135deg, var(--tz-orange, #ff7c25) 0%, #d9540b 100%);
    color: #fff;
    overflow: hidden;
}

/* Au-delà du téléphone, le texte et l'image se partagent la largeur : sur un
   écran large, un bloc pleine largeur en une colonne devient une banderole. */
@media (min-width: 720px) {
    html body .tz-promo:has(.tz-promo-image) {
        grid-template-columns: 1fr auto;
    }
}

html body .tz-promo-texte {
    display: grid;
    gap: 0.5rem;
    /* Sans quoi un mot long de l'illustration ou du titre pousse la colonne
       au-delà de l'écran — c'est la panne qui a coupé les prix du panier. */
    min-width: 0;
}

html body .tz-promo-haut {
    display: flex;
    align-items: center;
    gap: 0.6rem;
    flex-wrap: wrap;
    margin: 0;
}

html body .tz-promo-surtitre {
    font-size: 0.72rem;
    font-weight: 700;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    opacity: 0.9;
}

html body .tz-promo-pastille {
    padding: 0.2rem 0.6rem;
    border-radius: 999px;
    background: #fff;
    color: #b8450a;
    font-size: 0.78rem;
    font-weight: 800;
    line-height: 1.4;
}

html body h2.tz-promo-titre {
    margin: 0;
    color: #fff;
    font-size: 1.5rem;
    line-height: 1.2;
    font-weight: 800;
    text-wrap: balance;
}

html body .tz-promo-sous {
    margin: 0;
    font-size: 0.95rem;
    line-height: 1.45;
    opacity: 0.94;
    /* Deux lignes : au-delà, la bannière repousse les produits hors de
       l'écran, et l'accueil sert à voir des produits. */
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

html body a.tz-promo-bouton {
    justify-self: start;
    margin-top: 0.35rem;
    padding: 0 1.4rem;
    /* 46 px, comme tous les autres boutons et champs du site. */
    height: 46px;
    display: inline-flex;
    align-items: center;
    border-radius: 999px;
    background: #fff;
    color: #b8450a;
    font-size: 0.95rem;
    font-weight: 700;
    text-decoration: none;
}

html body a.tz-promo-bouton:hover,
html body a.tz-promo-bouton:focus-visible {
    background: #fff5ee;
    color: #9c3a06;
}

html body a.tz-promo-bouton:focus-visible {
    outline: 3px solid #fff;
    outline-offset: 2px;
}

html body .tz-promo-image {
    max-width: 100%;
    max-height: 180px;
    justify-self: center;
    border-radius: 10px;
    object-fit: cover;
}

/* ==========================================================================
   Le tiroir des catégories : 1019 px de liste dans 844 px de panneau
   ==========================================================================

   Signalé : « impossible de parcourir la liste de catégories, quand on scroll
   c'est l'écran d'en dessous qui scroll ».

   Mesuré : `aside.site-drawer` fait 340×844 en `position: fixed`, et son
   contenu 1019 px — avec `overflow-y: visible`. Le débordement n'est donc ni
   défilable ni coupé : il sort du panneau dans le vide, et comme le panneau
   est fixe, le bas de la liste est INATTEIGNABLE. 63 liens, dont une partie
   n'existe que pour le code.

   Le geste, lui, ne trouvant rien à faire défiler ici, remonte au corps de la
   page — 14 359 px de haut, ravi de l'accepter. D'où la sensation que « c'est
   l'écran d'en dessous qui scroll » : c'est exactement ce qui se passe.

   Deux propriétés, deux symptômes :
     - `overflow-y: auto` rend le panneau défilable ;
     - `overscroll-behavior: contain` empêche le geste de se propager à la
       page derrière quand on atteint le bout de la liste.

   La seconde sans la première ne servirait à rien, et la première sans la
   seconde laisserait la page bouger dès qu'on arrive en bas.
   ========================================================================== */

html body aside.site-drawer {
    overflow-y: auto;
    overscroll-behavior: contain;
    -webkit-overflow-scrolling: touch;
}

/* Le contenu ne doit plus imposer sa hauteur au conteneur, sinon `auto` n'a
   rien à faire défiler — le panneau grandirait au lieu de se replier. */
html body aside.site-drawer .site-scrollsa {
    min-height: 0;
}

/* Des cibles atteignables au pouce : les entrées faisaient 31 px, sous les
   44 px en dessous desquels on vise à côté. */
html body aside.site-drawer .drawer-body .menu-item > a {
    min-height: 44px;
    display: flex;
    align-items: center;
    gap: 0.5rem;
}

/* ==========================================================================
   Les « puces grises vides » de la fiche produit
   ==========================================================================

   ⚠️ J'avais conclu la première fois que c'étaient les icônes de partage dont
   le glyphe ne charge pas. C'était faux, et la correction n'a rien corrigé.

   Ce sont les FLÈCHES DE LA GALERIE. Il y en a deux jeux — `ul.flex-direction-
   nav` — l'un pour la bande de vignettes, l'autre pour l'image principale.
   Tous deux sont en `position: static` avec `list-style-type: disc` : ils
   retombent dans le flux sous la galerie, empilés, chacun avec sa puce de
   liste. Les blocs gris sont les boutons eux-mêmes, `rgb(230, 232, 235)`,
   40×42, dont le chevron ne se voit pas sur ce fond.

   Ce qui ressemblait à un défaut de chargement était un défaut de placement :
   rien ne manquait, tout était au mauvais endroit.

   `.woocommerce-product-gallery` est déjà `position: relative` — l'ancre
   existait, personne ne s'y accrochait.
   ========================================================================== */

html body .woocommerce-product-gallery {
    /* Déjà relative dans le thème ; on l'affirme, car tout ce qui suit en
       dépend et une évolution du thème l'emporterait en silence. */
    position: relative;
}

html body .klb-flexslider-thumbnail {
    position: relative;
}

html body .woocommerce-product-gallery ul.flex-direction-nav {
    position: absolute;
    inset: 0;
    margin: 0;
    padding: 0;
    list-style: none;
    /* Le glissement sur l'image doit continuer de fonctionner : la barre
       couvre toute la galerie, elle ne doit intercepter que ses boutons. */
    pointer-events: none;
}

html body .woocommerce-product-gallery ul.flex-direction-nav li {
    position: absolute;
    top: 50%;
    transform: translateY(-50%);
    width: auto;
    margin: 0;
    list-style: none;
}

html body .woocommerce-product-gallery ul.flex-direction-nav li.flex-nav-prev { left: 8px; }
html body .woocommerce-product-gallery ul.flex-direction-nav li.flex-nav-next { right: 8px; }

html body .woocommerce-product-gallery ul.flex-direction-nav a,
html body .woocommerce-product-gallery ul.flex-direction-nav button {
    pointer-events: auto;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 40px;
    height: 40px;
    border-radius: 999px;
    background: rgba(255, 255, 255, 0.92);
    box-shadow: 0 1px 6px rgba(0, 0, 0, 0.18);
    color: var(--tz-encre, #1c1917);
}

/* Une flèche désactivée s'efface au lieu de rester grise et cliquable pour
   rien : elle disait « il y a un avant » alors qu'on était au début. */
html body .woocommerce-product-gallery ul.flex-direction-nav a.flex-disabled {
    opacity: 0;
    pointer-events: none;
}

/* Sur téléphone, la bande de vignettes fait 360 px pour quatre vignettes.
   Deux flèches de 40 px en couvriraient la moitié. La bande se fait glisser
   du doigt, et les vignettes elles-mêmes servent de navigation. */
@media (max-width: 719px) {
    html body .klb-flexslider-thumbnail ul.flex-direction-nav {
        display: none;
    }
}

/* ==========================================================================
   Le panier : le rognage à deux lignes qui n'a jamais rogné
   ==========================================================================

   ⚠️ La règle existait déjà et la mesure disait `-webkit-line-clamp: 2`,
   `overflow: hidden` — mais `display: block`.

   `-webkit-line-clamp` n'a d'effet QUE sur `display: -webkit-box`. La valeur
   du rognage avait survécu, la propriété qui la rend active avait été écrasée
   par la règle du thème sur `td`. Une déclaration à moitié appliquée, donc
   sans effet, mais qui se lisait comme appliquée dans la feuille.

   J'avais mis `!important` sur le prix, la quantité et le total — les trois
   voisins — et pas sur le nom. Trois lignes plus haut, mon propre commentaire
   expliquait pourquoi il le fallait.
   ========================================================================== */

@media (max-width: 767px) {
    html body table.shop_table_responsive td.product-name {
        display: -webkit-box !important;
    }

    /* ⚠️ UNE SECONDE DÉFINITION DE `grid-template-areas` VIVAIT ICI.
     *
     * Écrite hier pour descendre la suppression en bas de carte, elle a
     * silencieusement annulé la refonte d'aujourd'hui : la carte gardait ses
     * cinq rangées, et j'ai d'abord cru que mes nouvelles zones ne
     * s'appliquaient pas. Deux déclarations de la même propriété sur le même
     * sélecteur, c'est toujours la dernière qui gagne — et la « dernière »
     * n'est pas celle qu'on vient d'écrire, c'est celle qui est le plus bas
     * dans le fichier.
     *
     * La carte n'a plus qu'UNE définition de sa grille, quelque 700 lignes
     * plus haut, avec le reste de sa mise en page.
     *
     * Ce qui reste ici est ce qui n'existe qu'à cet endroit : la cellule
     * de suppression doit REVENIR DANS LE FLUX. Le thème la pose en
     * `position: absolute`, et un élément hors flux ne participe à aucune
     * grille — mon `grid-area: suppr` était écrit, valide, et sans le moindre
     * effet. Le bouton se plaçait en coordonnées, indifférent à la carte qu'il
     * traversait : six chevauchements mesurés, sur le nom du produit SUIVANT.
     *
     * Mon témoin d'hier vérifiait « la suppression est plus bas que le nom ».
     * C'était vrai, et ça ne disait rien du nom d'en dessous. Il compte
     * désormais les chevauchements réels entre boîtes. */
    html body table.shop_table_responsive td.product-remove {
        position: static !important;
    }

    html body table.shop_table_responsive td.product-remove a.remove {
        display: inline-flex;
        align-items: center;
        gap: 0.4rem;
        width: auto;
        height: 36px;
        padding: 0 0.75rem;
        border: 1px solid var(--tz-trait, #e7e2dd);
        border-radius: 999px;
        background: transparent !important;
        color: var(--tz-encre-douce, #57534e) !important;
        font-size: 0.85rem;
        line-height: 1;
        text-decoration: none;
    }

    /* ⚠️ La capture d'écran a montré « × × Remove this item » — DEUX croix.
       La mesure ne pouvait pas le voir : elle comptait des pixels de large,
       pas des glyphes.
       Il y en a deux parce qu'il y a deux sources : le texte du lien
       lui-même, et un `::before` posé par le thème. On éteint les deux —
       `font-size: 0` efface le nœud de texte, `display: none` le pseudo —
       et l'intitulé revient à sa taille sur le `::after`. */
    html body table.shop_table_responsive td.product-remove a.remove {
        font-size: 0;
    }

    html body table.shop_table_responsive td.product-remove a.remove::before {
        display: none;
    }

    /* L'intitulé VISIBLE est court — « Remove » — et vient de
       `data-tz-suppression`, posé côté serveur par TZ-45 et donc traduit avec
       le reste. L'écrire en dur dans cette feuille aurait marché aujourd'hui et
       cassé à la première traduction.

       ⚠️ Il ne remplace pas `aria-label`, qui reste entier : « Remove » seul,
       annoncé au milieu d'une liste de trois articles, ne dit pas lequel part.

       Repli sur `aria-label` si le correctif serveur n'est pas actif — mieux
       vaut un intitulé long qu'un bouton muet. */
    html body table.shop_table_responsive td.product-remove a.remove::after {
        content: attr(aria-label);
        font-size: 0.85rem;
    }

    html body table.shop_table_responsive td.product-remove a.remove[data-tz-suppression]::after {
        content: attr(data-tz-suppression);
    }

    /* Le champ de quantité : 48 px suffisent à deux chiffres, et le thème en
       réservait 64. Ce sont 16 px repris sur une rangée qui en manquait. */
    html body table.shop_table_responsive td.product-quantity input.qty {
        min-width: 48px !important;
        width: 48px !important;
    }

    html body table.shop_table_responsive td.product-remove a.remove:hover,
    html body table.shop_table_responsive td.product-remove a.remove:focus-visible {
        border-color: #c0392b;
        color: #c0392b !important;
    }
}

/* ==========================================================================
   Le rognage du nom : pourquoi `!important` n'y pouvait rien
   ==========================================================================

   ⚠️ Deuxième erreur sur la même ligne, et la première explication était
   fausse.

   J'ai cru à un `display: block` du thème qui écrasait le mien, et j'ai
   ajouté `!important`. La mesure d'après disait : ma règle s'applique,
   `-webkit-box !important`, et la valeur calculée vaut `flow-root`.

   Aucune règle ne me battait — vérifié en imposant la valeur EN LIGNE avec
   `!important` sur l'élément lui-même : elle calcule encore `flow-root`. Le
   moteur normalise `-webkit-box`, un point c'est tout. Rien de ce qu'on écrit
   ne fera dire `-webkit-box` à cette page.

   Deux conséquences, et j'ai mis deux essais à les séparer :

     - sur la CELLULE, le rognage ne prenait pas. `tr.cart_item` est en
       `display: grid` : `td.product-name` est un enfant de grille, son
       `display` est blockifié, et le nom tenait sur trois lignes ;
     - sur le LIEN, il prend — mesuré, le nom passe de trois lignes à deux —
       alors même que la valeur calculée reste `flow-root`.

   ⚠️ La leçon n'est pas dans le CSS. Mon contrôle lisait
   `display === '-webkit-box'` et restait rouge pendant que le rognage
   fonctionnait. Je vérifiais la FORME de la déclaration au lieu de son EFFET.
   Le témoin mesure désormais la hauteur avec et sans rognage, et exige un
   écart : sur un nom court il n'y aurait rien à couper, et un « oui » ne
   voudrait rien dire.
   ========================================================================== */

@media (max-width: 767px) {
    /* La cellule redevient une simple boîte : c'est le lien qui rogne. */
    html body table.shop_table_responsive td.product-name {
        display: block !important;
        overflow: hidden;
    }

    html body table.shop_table_responsive td.product-name a {
        display: -webkit-box;
        -webkit-box-orient: vertical;
        -webkit-line-clamp: 2;
        line-clamp: 2;
        overflow: hidden;
        /* Sans quoi un titre d'un seul mot très long — il y en a dans ce
           catalogue — déborderait la carte au lieu d'être coupé. */
        overflow-wrap: anywhere;
    }
}

/* ==========================================================================
   TZ-42 — le message du champ manquant, rendu reconnaissable
   ==========================================================================

   ⚠️ Ce bloc a d'abord habillé un message QUE J'AVAIS AJOUTÉ. Il n'avait pas
   lieu d'être : il en existait déjà un, `p.checkout-inline-error-message`,
   sur chacune des six rangées fautives.

   Ma sonde cherchait trois classes — `.woocommerce-error`,
   `.wc-block-components-validation-error`, `[role="alert"]` — n'en trouvait
   aucune, et je concluais « zéro message sur place ». J'avais mesuré
   l'absence de trois noms et lu la réponse comme l'absence de la chose. La
   capture d'écran a tranché : deux messages par champ.

   Il ne reste donc qu'une mise en forme. Le message existait, mais s'affichait
   en texte noir ordinaire sous le champ — rien ne le distinguait d'une aide de
   saisie, alors qu'il signale ce qui bloque la commande.
   ========================================================================== */

html body p.checkout-inline-error-message {
    margin: 0.3rem 0 0;
    /* Un rouge qui tient le contraste sur fond blanc — 4,5:1 — plutôt que le
       rouge vif habituel, illisible en petit corps. */
    color: #b3261e;
    font-size: 0.82rem;
    line-height: 1.35;
    display: flex;
    align-items: flex-start;
    gap: 0.35rem;
}

/* Le symbole est décoratif : le texte dit déjà tout, et un lecteur d'écran
   n'a rien à faire d'un point d'exclamation. */
html body p.checkout-inline-error-message::before {
    content: "!";
    flex: 0 0 auto;
    width: 15px;
    height: 15px;
    margin-top: 1px;
    border-radius: 50%;
    background: #b3261e;
    color: #fff;
    font-size: 0.68rem;
    font-weight: 700;
    line-height: 15px;
    text-align: center;
}

/* La bordure rouge du champ lui-même : elle existait déjà côté WooCommerce
   mais restait discrète sur ce thème. */
html body .form-row.woocommerce-invalid-required-field input,
html body .form-row.woocommerce-invalid-required-field select,
html body .form-row.woocommerce-invalid-required-field textarea {
    border-color: #b3261e !important;
}

/* ==========================================================================
   TZ-43 — recherche, catégorie, boutique vendeur
   ==========================================================================

   Trois pages jamais regardées, trois défauts mesurés et un quatrième qui ne
   se corrige pas ici (voir plus bas la note sur la bannière du vendeur).
   ========================================================================== */

html body .tz-liste-entete {
    display: grid;
    gap: 0.5rem;
    margin: 0 0 1rem;
    padding: 0 0 0.85rem;
    border-bottom: 1px solid var(--tz-trait, #e7e2dd);
}

html body .tz-liste-quoi {
    margin: 0;
    font-size: 1.05rem;
    line-height: 1.35;
    color: var(--tz-encre, #1c1917);
    /* Un terme de recherche est une saisie libre : il peut ne faire qu'un
       seul mot très long, et rien n'oblige un visiteur à être raisonnable. */
    overflow-wrap: anywhere;
}

html body .tz-liste-combien {
    margin: 0;
    font-size: 0.9rem;
    color: var(--tz-encre-douce, #57534e);
    font-variant-numeric: tabular-nums;
}

html body .tz-liste-recherche {
    display: flex;
    gap: 0.5rem;
    align-items: center;
}

html body .tz-liste-recherche input[type="search"] {
    flex: 1 1 auto;
    /* 16 px : en dessous, Safari iOS zoome à la mise au point et la page
       saute — sur un champ qu'on vient toucher, c'est le pire moment. */
    font-size: 16px;
    height: 46px;
    padding: 0 0.9rem;
    border: 1px solid var(--tz-trait, #e7e2dd);
    border-radius: 999px;
    background: var(--tz-fond, #fffdfb);
    /* Sans quoi le champ impose sa largeur intrinsèque et pousse le bouton
       hors de l'écran — la panne qui a coupé les prix du panier. */
    min-width: 0;
}

/*
 * ⚠️ `html body .tz-liste-recherche button` ne suffisait pas : le bouton
 * restait GRIS, `rgb(230, 232, 235)`.
 *
 * Le thème écrit `button:not(.unset):not(.link)` — DEUX classes, puisque
 * `:not()` prend la spécificité de son argument. Le mien n'en comptait
 * qu'une. Le nombre de classes se compare avant le nombre d'éléments : sa
 * règle l'emportait, et mes trois `html body … button` n'y changeaient rien.
 *
 * On reprend son propre chemin — `:not(.unset)` — plutôt que d'ajouter un
 * `!important` de plus. La feuille en compte déjà assez, et chacun d'eux est
 * une porte fermée pour le passage suivant : c'est exactement ce qui m'a
 * bloqué sur le bouton d'ajout au panier, quelques heures plus tôt.
 */
html body .tz-liste-recherche button:not(.unset) {
    flex: 0 0 auto;
    height: 46px;
    padding: 0 1.1rem;
    border: 0;
    border-radius: 999px;
    background: var(--tz-orange, #ff7c25);
    color: #fff;
    font-weight: 600;
}

html body .tz-liste-issue {
    margin: 1rem 0 0;
}

html body a.tz-liste-bouton {
    display: inline-flex;
    align-items: center;
    height: 46px;
    padding: 0 1.3rem;
    border-radius: 999px;
    background: var(--tz-orange, #ff7c25);
    color: #fff;
    font-weight: 600;
    text-decoration: none;
}

/* --------------------------------------------------------------------------
   La colonne qui s'échappe de son conteneur
   --------------------------------------------------------------------------

   Mesuré : `main.site-main` fait 360 px et son contenu 372.

   ⚠️ J'ai d'abord accusé `div.col.col-12`, large de 384 px et commençant à
   x=3 quand `main` commence à x=15. Je l'ai borné à `max-width: 100%` — sans
   aucun effet, et pour une raison qui aurait dû me sauter aux yeux : il
   PORTAIT DÉJÀ `max-width: 100%`. Ses 384 px sont 100 % de son parent.

   Le parent est le coupable. `div.row.shop-wrapper` porte `margin: -12px` à
   gauche et à droite — la compensation classique d'un système de grille, qui
   attend un conteneur avec 12 px de remplissage pour l'absorber. `main` n'en
   a aucun. La rangée applique donc sa moitié du contrat et déborde de 12 px
   de chaque côté.

   Borner l'enfant quand c'est le parent qui déborde ne pouvait rien donner.
   On annule la compensation là où elle est écrite ; la colonne garde ses
   12 px de remplissage, qui rentrent alors dans les 360.
   -------------------------------------------------------------------------- */

@media (max-width: 991px) {
    html body main.site-main .row.shop-wrapper {
        margin-left: 0;
        margin-right: 0;
    }
}

/* --------------------------------------------------------------------------
   Le bouton d'ajout au panier, coupé sur la boutique du vendeur
   --------------------------------------------------------------------------

   Mesuré : 120 px de boîte pour 124 px de contenu, en `white-space: nowrap`.
   « Add to cart » perd sa dernière lettre.

   ⚠️ Sur la page CATÉGORIE le même bouton mesure 131 pour 131 — il n'y est pas
   coupé. Une correction posée sur la seule mesure de la catégorie aurait
   conclu qu'il n'y avait rien à faire. La boutique du vendeur a des cartes
   plus étroites.

   On ne réduit pas la police : le bouton prend la largeur de sa carte, ce qui
   règle le cas quelle que soit la grille — et un bouton pleine largeur est
   aussi plus facile à viser.
   -------------------------------------------------------------------------- */

/* ⚠️ Une règle a été retirée d'ici : celle qui devait porter le bouton
   d'ajout à 44 px et réduire son remplissage. Elle n'avait aucun effet — la
   règle d'origine, quelque 2 700 lignes plus haut, impose `min-height: 0
   !important`, et un `!important` ne se bat pas à coups de spécificité.

   La correction est allée là où était la cause. En garder une copie ici
   aurait laissé deux intentions contraires dans la même feuille, dont l'une
   ne sert qu'à être battue. */

@media (max-width: 767px) {
    /* Le cœur de la liste d'envies faisait 22 px de haut. On agrandit la
       CIBLE sans grossir le dessin : le carré tactile déborde le glyphe. */
    html body div.products a[class*="wishlist"],
    html body ul.products a[class*="wishlist"],
    html body div.products .klbwl-button a,
    html body ul.products .klbwl-button a {
        min-width: 44px;
        min-height: 44px;
        display: inline-flex;
        align-items: center;
        justify-content: center;
    }
}

/* --------------------------------------------------------------------------
   ⚠️ CE QUI N'EST PAS CORRIGÉ ICI, ET NE PEUT PAS L'ÊTRE
   --------------------------------------------------------------------------

   La bannière de la boutique vendeur affiche « roducts Availab » : le « P » de
   Products et le « le » d'Available manquent.

   Ce n'est PAS un défaut de mise en page. Mesuré : le fichier
   `cropped-Tizzlebanner.jpeg` fait 625 × 300 et il est rendu ENTIER, à
   l'échelle (338 × 162, même rapport). Le fichier a été recadré à
   l'enregistrement, et le texte a été coupé DANS L'IMAGE.

   Vérifié en ouvrant le fichier seul : les lettres n'y sont pas. Aucune règle
   de style ne restitue des pixels absents. Il faut redéposer une bannière dont
   le texte tient dans le cadre — c'est une correction de contenu, côté
   Tizzleshop.
   -------------------------------------------------------------------------- */

/* ==========================================================================
   Les adresses du compte : une colonne d'un douzième d'écran
   ==========================================================================

   Signalé : « la partie adresse dans Account n'est pas bonne du tout ». La
   capture montre « You have not set up this type of address yet. » écrit UN MOT
   PAR LIGNE, sur douze lignes.

   Mesuré, puis REPRODUIT hors session pour être sûr — la page demande un compte,
   et le plafond d'inscription horaire interdisait d'en créer un second :

     div.u-column1.col-1   30 px de large dans un parent de 360
     .col-1 { width: 8.3333%; flex: 0 0 auto }

   360 × 8,3333 % = 30. Au pixel près.

   ---------------------------------------------------------------------------
   La cause est un mot qui veut dire deux choses
   ---------------------------------------------------------------------------
   WooCommerce écrit `col-1` sur le bloc de facturation pour dire « la PREMIÈRE
   colonne du couple d'adresses ». Le thème, lui, embarque une grille en douze
   colonnes où `col-1` signifie « UN DOUZIÈME de la largeur ».

   Les deux ont raison dans leur propre vocabulaire. Ce n'est pas un bogue de
   l'un ou de l'autre : c'est une collision de noms, et elle ne se voit qu'en
   mesurant, puisque chaque feuille est cohérente prise seule.

   ⚠️ On corrige par la classe de WOOCOMMERCE — `.u-column1` — et jamais par
   `.col-1`. Redéfinir `.col-1` réparerait cette page et casserait toutes celles
   où le thème s'en sert pour ce qu'il croit.
   ========================================================================== */

html body .woocommerce-Addresses {
    display: grid;
    /* Une colonne sur téléphone : deux adresses côte à côte sur 360 px
       donneraient deux colonnes de 170, où « Town / City » se coupe. */
    grid-template-columns: 1fr;
    gap: 1rem;
}

@media (min-width: 720px) {
    html body .woocommerce-Addresses {
        grid-template-columns: 1fr 1fr;
    }
}

html body .woocommerce-Addresses .u-column1,
html body .woocommerce-Addresses .u-column2 {
    /* La largeur du douzième est neutralisée ici, et ici seulement. */
    width: auto !important;
    max-width: none !important;
    float: none !important;
    /* Sans quoi un enfant long — une adresse d'une seule ligne — impose sa
       largeur intrinsèque à la colonne de grille. */
    min-width: 0;

    display: flex;
    flex-direction: column;
    gap: 0.5rem;
    padding: 1rem;
    border: 1px solid var(--tz-trait, #e7e2dd);
    border-radius: var(--tz-rayon, 12px);
    background: #fff;
}

html body .woocommerce-Addresses .woocommerce-Address-title {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 0.75rem;
    flex-wrap: wrap;
    margin: 0;
}

html body .woocommerce-Addresses .woocommerce-Address-title h2,
html body .woocommerce-Addresses .woocommerce-Address-title h3 {
    margin: 0;
    font-size: 1.05rem;
    line-height: 1.3;
}

/* Le lien « Add / Edit » devient un bouton discret, à la hauteur des autres
   cibles tactiles du site. Il faisait partie du texte, et rien ne disait
   qu'on pouvait cliquer. */
html body .woocommerce-Addresses .woocommerce-Address-title a {
    display: inline-flex;
    align-items: center;
    min-height: 40px;
    padding: 0 0.9rem;
    border: 1px solid var(--tz-orange, #ff7c25);
    border-radius: 999px;
    color: var(--tz-orange, #ff7c25);
    font-size: 0.88rem;
    font-weight: 600;
    text-decoration: none;
    white-space: nowrap;
}

html body .woocommerce-Addresses address {
    margin: 0;
    font-style: normal;
    line-height: 1.5;
    color: var(--tz-encre-douce, #57534e);
}

/* Le formulaire d'édition d'une adresse porte la même collision. */
html body .woocommerce-address-fields .col-1,
html body .woocommerce-address-fields .col-2 {
    width: auto !important;
    max-width: none !important;
    float: none !important;
}

/* ==========================================================================
   Les trois écrans qui restaient
   ========================================================================== */

/* La liste des boutiques.
 *
 * ⚠️ J'ai d'abord borné `li.dokan-single-seller` — sans effet. La fiche n'est
 * pas le coupable : c'est `div.grid-view` et ses marges de −15 px de chaque
 * côté, la MÊME compensation de gouttière que la rangée de la boutique, qui
 * attend un conteneur au remplissage correspondant et ne le trouve pas.
 *
 * Deux écrans, deux fois la même cause, et deux fois j'ai commencé par
 * accuser l'enfant. Borner un enfant quand c'est le parent qui déborde ne
 * peut rien donner — c'est la troisième fois que je l'écris. */
/* ⚠️ Ma première règle visait `.klb-post .grid-view` — elle matchait, et elle
 * perdait. La marge vient de `#dokan-seller-listing-wrap`, un sélecteur
 * d'IDENTIFIANT : un identifiant l'emporte sur n'importe quel nombre de
 * classes, la comparaison s'arrête avant de les compter.
 *
 * On reprend donc son chemin plutôt que d'ajouter un `!important` de plus.
 * `html body #dokan-seller-listing-wrap` porte le même identifiant et deux
 * éléments en plus : il gagne sans forcer. */
@media (max-width: 991px) {
    html body #dokan-seller-listing-wrap,
    html body .dokan-seller-listing-wrap .grid-view,
    html body .klb-post .grid-view {
        margin-left: 0;
        margin-right: 0;
    }
}

html body li.dokan-single-seller,
html body .dokan-seller-listing-wrap li {
    max-width: 100%;
    box-sizing: border-box;
}

/* La 404 : une illustration de 420 px dans 360.
 *
 * `!important` assumé : l'image porte sa largeur du thème, et une image qui
 * dépasse son cadre pousse toute la page — c'est le défaut le plus visible
 * qu'un écran d'erreur puisse avoir. */
html body .page-not-found img,
html body .error-404 img,
html body .page-not-found svg {
    max-width: 100% !important;
    width: auto !important;
    height: auto;
}

/* Trois boutons mesurés à 42 px — deux de trop sous les 44. */
html body .dokan-btn,
html body button.woocommerce-Button,
html body .dokan-store-list-filter-button {
    min-height: 44px;
}

/* ==========================================================================
   LE DESSIN D'ENSEMBLE — sortir du blanc
   ==========================================================================

   Signalé : « le design global est tout blanc, impersonnel ».

   Mesuré, et c'est exact au sens littéral :

     body                     rgb(255, 255, 255)
     carte produit — fond     rgba(0, 0, 0, 0)     (transparente)
                    bordure   0px none
                    rayon     0px
                    ombre     none
     titre de section         15,2 px, graisse 600

   Les cartes ne sont donc pas des cartes : c'est du contenu posé sur du vide.
   Rien ne dit où commence un produit et où finit le suivant, et rien ne
   distingue une section d'une autre. Un catalogue sans objets et sans rythme
   ne peut être que plat — ce n'est pas une question de goût.

   ---------------------------------------------------------------------------
   Ce qu'on change, et ce qu'on ne change pas
   ---------------------------------------------------------------------------
   UNE seule idée porte l'essentiel : **le fond de page cesse d'être blanc, et
   les cartes le deviennent**. Un objet blanc sur un fond légèrement teinté se
   détache tout seul ; le même objet blanc sur du blanc n'existe pas. Tout le
   reste — bordure, rayon, ombre — ne fait que confirmer ce que la valeur a
   déjà séparé.

   ⚠️ On n'ajoute AUCUNE police. Satoshi est déjà chargée en variable 300→900,
   et une seconde famille coûterait un téléchargement à chaque visite pour un
   gain que la graisse suffit à obtenir. La hiérarchie vient donc des graisses
   et des tailles, pas d'un nouveau caractère.

   L'orange reste réservé à ce qui ENGAGE — boutons, bannière, repères actifs.
   Un accent qu'on met partout ne signale plus rien.
   ========================================================================== */

:root {
    /* Un blanc cassé chaud, tiré vers l'orange de la charte. Un gris pur à
       côté d'un orange se lit comme un oubli ; celui-ci se lit comme un
       choix. */
    --tz-papier: #faf7f4;
    --tz-carte: #ffffff;
    --tz-trait-doux: #efe9e3;
    --tz-ombre: 0 1px 2px rgba(28, 25, 23, 0.04), 0 4px 14px rgba(28, 25, 23, 0.05);
    --tz-ombre-levee: 0 2px 6px rgba(28, 25, 23, 0.07), 0 10px 26px rgba(28, 25, 23, 0.09);
}

html body,
html body .site-content,
html body .site-primary,
html body #content {
    background-color: var(--tz-papier);
}

/* ---------------------------------------------------------------------------
   Les cartes produit deviennent des objets
   --------------------------------------------------------------------------- */

html body div.products div.product,
html body ul.products li.product {
    background: var(--tz-carte);
    border: 1px solid var(--tz-trait-doux);
    border-radius: 14px;
    box-shadow: var(--tz-ombre);
    overflow: hidden;
    /* La transition ne sert que le survol ; elle ne coûte rien au chargement. */
    transition: box-shadow 0.18s ease, transform 0.18s ease;
}

@media (hover: hover) {
    html body div.products div.product:hover,
    html body ul.products li.product:hover {
        box-shadow: var(--tz-ombre-levee);
        transform: translateY(-2px);
    }
}

/* Le survol n'existe pas au doigt : on garde un repère au CONTACT, sinon rien
   ne répond quand on touche une carte sur téléphone. */
html body div.products div.product:active,
html body ul.products li.product:active {
    box-shadow: var(--tz-ombre-levee);
}

@media (prefers-reduced-motion: reduce) {
    html body div.products div.product,
    html body ul.products li.product {
        transition: none;
    }
    html body div.products div.product:hover,
    html body ul.products li.product:hover {
        transform: none;
    }
}

/* L'image du produit sur un fond très légèrement teinté : les photos de ce
   catalogue sont détourées sur blanc, et sur une carte blanche elles
   flottaient sans limite. */
html body div.products div.product .product-image,
html body div.products div.product .woocommerce-loop-product__link img,
html body ul.products li.product img {
    background: #fdfbf9;
}

/* ---------------------------------------------------------------------------
   Le rythme des sections
   ---------------------------------------------------------------------------

   Les titres faisaient 15,2 px en graisse 600 — la même chose qu'un
   paragraphe un peu gras. Rien ne séparait « Featured Products » de la ligne
   d'à côté.

   Un repère orange court les précède : il coûte trois pixels et donne à
   l'œil un point d'entrée régulier en descendant la page.
   --------------------------------------------------------------------------- */

/*
 * ⚠️ DEUX ERREURS ICI, corrigées après avoir regardé la capture.
 *
 * La première version visait `.site-content h2`. Beaucoup trop large :
 *
 *   - le repère orange s'est posé sur le NOM DE CHAQUE PRODUIT — les cartes
 *     du catalogue utilisent `h2.product-title` ;
 *   - `color: var(--tz-encre)` a repeint en sombre le titre de la bannière
 *     rouge, dont le texte était BLANC. Un fond rouge avec du texte foncé,
 *     alors que je venais d'écrire un témoin sur les contrastes.
 *
 * Et mon témoin a validé tout cela : il prenait le PREMIER `.site-content h2`
 * de la page, qui se trouvait être ce titre de bannière. Il a mesuré 22 px,
 * graisse 700, repère présent — trois verts sur l'élément qu'il ne fallait
 * pas regarder.
 *
 * On ne touche donc plus à la COULEUR — c'est au thème de savoir quel titre
 * va sur quel fond, et il le sait. On ne règle que la taille et la graisse,
 * et le repère est réservé aux titres qui ouvrent une section : ni un nom de
 * produit, ni un titre posé sur une image.
 */
html body .site-content h2:not(.product-title):not(.entry-title),
html body .site-content h3.widget-title {
    font-size: 1.28rem;
    line-height: 1.25;
    font-weight: 800;
    letter-spacing: -0.01em;
    text-wrap: balance;
}

html body .site-content h2:not(.product-title):not(.entry-title)::before,
html body .site-content h3.widget-title::before {
    content: "";
    display: block;
    width: 34px;
    height: 3px;
    margin-bottom: 0.55rem;
    border-radius: 999px;
    background: var(--tz-orange, #ff7c25);
}

/* Le repère ne doit pas non plus apparaître dans nos propres blocs, ni dans
   ceux du compte : ils ont déjà leur mise en page, et un trait de plus y
   ferait doublon. Ni sur un titre posé sur une image ou une bannière, où il
   se lirait comme une rayure. */
html body .tz-liste-entete h2::before,
html body .tz-promo h2::before,
html body .woocommerce-Addresses h2::before,
html body .woocommerce-MyAccount-content h2::before,
html body table h2::before,
html body .klb-banner h2::before,
html body .products h2::before,
html body div.product h2::before {
    content: none;
}

/* ---------------------------------------------------------------------------
   Les blocs blancs qui restent : compte, panier, paiement
   --------------------------------------------------------------------------- */

html body .woocommerce-MyAccount-content,
html body .cart-collaterals,
html body .woocommerce-checkout-review-order,
html body table.shop_table_responsive {
    background: var(--tz-carte);
    border: 1px solid var(--tz-trait-doux);
    border-radius: 14px;
    padding: 1rem;
}

/* ---------------------------------------------------------------------------
   La barre du bas : une frontière, pas une nappe
   --------------------------------------------------------------------------- */

html body .klb-mobile-bottom {
    background: rgba(255, 255, 255, 0.92);
    -webkit-backdrop-filter: saturate(1.6) blur(12px);
    backdrop-filter: saturate(1.6) blur(12px);
    border-top: 1px solid var(--tz-trait-doux);
}

/* Les puces de catégorie de l'accueil : une teinte chaude au lieu du blanc,
   pour qu'on voie qu'il y en a d'autres derrière le bord. */
html body .tz-accueil-categories a,
html body .tz-categorie-puce {
    background: #fff4ec;
    border-color: #f6dcc9;
}

/* ==========================================================================
   REFONTE — la carte produit unique, la bande orange, le panier lisible
   ==========================================================================

   Signalé : « tout le site n'est pas uniforme et esthétique », « la
   présentation de certains produits n'est pas bonne quand on scrolle », « une
   charte globale de blanc sur blanc ».

   ---------------------------------------------------------------------------
   Ce que la mesure a montré, et que je n'avais pas cherché
   ---------------------------------------------------------------------------
   La page d'accueil rend QUATRE gabarits de carte différents, sur 60 cartes :

     style-6   25 cartes   171×402   image 149×149   titre puis prix
     style-1   22 cartes   178×352   image 176×176   PRIX PUIS TITRE
     style-3    9 cartes   348×454   image 316×316   prix à gauche, bouton à droite
     style-4    4 cartes   348×148   image  68× 68   sans bouton d'achat

   Ce n'est pas une question de goût : c'est le même objet dessiné de quatre
   façons sur un seul écran. Des images de 68 à 316 px, un gabarit qui met le
   prix AVANT le nom, un autre sans bouton. En faisant défiler, on croit
   changer de site.

   J'avais habillé « la carte » au singulier — bordure, rayon, ombre — sans
   jamais vérifier qu'il n'y en avait qu'une. Habiller quatre gabarits ne les
   rend pas semblables : ça rend leurs différences plus visibles.

   ---------------------------------------------------------------------------
   Ce qui rend l'unification possible
   ---------------------------------------------------------------------------
   Les quatre partagent le MÊME squelette, relevé dans l'arbre :

     div.product-wrapper
       div.product-inner
         div.thumbnail-wrapper.entry-media  →  a.product-thumbnail
         div.content-wrapper                →  h2.product-title, span.price,
                                               div.product-buttons

   Seuls l'ORDRE et les TAILLES diffèrent. Les deux se règlent sans toucher au
   balisage : `order` pour la séquence, `aspect-ratio` pour l'image.
   ========================================================================== */

/* --- 1. Le cadre, identique pour tous ------------------------------------ */

html body .product-wrapper {
    display: flex;
    height: 100%;
}

html body .product-wrapper > .product-inner {
    display: flex;
    flex-direction: column;
    width: 100%;
    gap: 0;
}

/* --- 2. L'image : un carré, toujours ------------------------------------- */

html body .product-wrapper .thumbnail-wrapper {
    width: 100%;
    /* Un carré quelle que soit la photo : les visuels de ce catalogue vont du
       flacon vertical au câble horizontal, et sans rapport imposé chaque
       carte prend une hauteur différente — c'est ce qui faisait l'escalier. */
    aspect-ratio: 1 / 1;
    display: flex;
    align-items: center;
    justify-content: center;
    background: #fdfbf9;
    overflow: hidden;
}

html body .product-wrapper .thumbnail-wrapper a.product-thumbnail {
    width: 100%;
    height: 100%;
    display: flex;
    align-items: center;
    justify-content: center;
}

html body .product-wrapper .thumbnail-wrapper img {
    max-width: 88%;
    max-height: 88%;
    width: auto;
    height: auto;
    /* `contain` et non `cover` : un flacon rogné pour remplir un carré perd
       son bouchon, et l'on n'achète pas ce qu'on ne reconnaît pas. */
    object-fit: contain;
}

/* --- 3. Le contenu : un ordre unique ------------------------------------- */

html body .product-wrapper .content-wrapper {
    display: flex;
    flex-direction: column;
    flex: 1 1 auto;
    gap: 0.35rem;
    padding: 0.75rem 0.85rem 0.85rem;
    /* Sans quoi un titre long impose sa largeur intrinsèque à la carte. */
    min-width: 0;
}

/*
 * ⚠️ L'ORDRE EST IMPOSÉ ICI, et c'est le cœur de la correction.
 *
 * `style-1` place `span.price` AVANT `h2.product-title` dans le document. Sur
 * la même page que trois gabarits qui font l'inverse, on lit un prix sans
 * savoir de quoi, puis le nom. Aucune retouche de taille ou de couleur ne
 * rattrape une séquence inversée.
 */
html body .product-wrapper .content-wrapper h2.product-title { order: 1; }
html body .product-wrapper .content-wrapper .product-content-switcher { order: 2; }
html body .product-wrapper .content-wrapper span.price,
html body .product-wrapper .content-wrapper .price { order: 3; }
html body .product-wrapper .content-wrapper .product-buttons,
html body .product-wrapper .content-wrapper .product-cart-wrapper { order: 4; margin-top: auto; }

html body .product-wrapper h2.product-title {
    margin: 0;
    font-size: 0.94rem;
    font-weight: 600;
    line-height: 1.35;
    /* Deux lignes pour toutes les cartes : c'est ce qui aligne les prix d'une
       rangée à l'autre. Sans hauteur commune, la grille fait des marches. */
    display: -webkit-box;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 2;
    line-clamp: 2;
    overflow: hidden;
    min-height: 2.7em;
}

html body .product-wrapper .content-wrapper span.price,
html body .product-wrapper .content-wrapper .price {
    font-size: 1.05rem;
    font-weight: 700;
    line-height: 1.3;
    font-variant-numeric: tabular-nums;
}

/* Le gabarit sans bouton d'achat en reçoit un de la même hauteur, vide, pour
   que les cartes d'une même rangée finissent au même endroit. */
html body .product-wrapper.style-4 .content-wrapper {
    padding-bottom: 0.85rem;
}

/* --- 4. La grille du catalogue ------------------------------------------- */

@media (max-width: 767px) {
    html body div.products.grid-column,
    html body ul.products {
        display: grid !important;
        grid-template-columns: repeat(2, minmax(0, 1fr));
        gap: 0.75rem;
        align-items: stretch;
    }

    html body div.products div.product,
    html body ul.products li.product {
        width: auto !important;
        margin: 0 !important;
        display: flex;
    }
}

/* ==========================================================================
   LA BANDE ORANGE — l'identité que les maquettes portaient
   ==========================================================================

   Rappelé : « sur les maquettes, on est allé sur un thème orange avec une
   bande orange ». Le site rend aujourd'hui un blanc cassé partout et n'affiche
   l'orange que sur les boutons — une couleur qu'on ne voit qu'en cliquant
   n'est pas une identité.

   La bande porte la RECHERCHE et les CATÉGORIES, c'est-à-dire les deux gestes
   d'entrée. Elle donne au site son visage sur l'écran qu'on voit en premier,
   et elle n'ajoute aucune hauteur : elle habille un bloc qui existait déjà.
   ========================================================================== */

/*
 * ⚠️ La première version donnait un dégradé à la bande — et la bannière de
 * promotion, juste en dessous, en portait un autre. Deux oranges empilés avec
 * une COUTURE VISIBLE entre eux : on ne lisait pas une bande, on lisait un
 * raccord raté.
 *
 * La maquette ne montrait qu'UNE bande. Les deux blocs partagent donc
 * désormais le même orange plat, sans arrondi entre eux : la recherche, les
 * catégories et la promesse forment un seul pavé, arrondi seulement en bas.
 *
 * C'est aussi ce qui donne son visage au site : le premier tiers de l'écran
 * porte la couleur de la marque, au lieu de la réserver aux boutons — un
 * accent qu'on ne voit qu'en cliquant n'est pas une identité.
 */
html body .tz-accueil-entete {
    background: var(--tz-orange, #ff7c25);
    padding: 1rem 1rem 0.9rem;
    margin-bottom: 0;
    border-radius: 0;
}

/* La bannière prolonge la bande au lieu de s'y poser. */
html body .tz-accueil-entete + .tz-promo,
html body .tz-promo:first-of-type {
    margin: 0;
    border-radius: 0 0 22px 22px;
    background: var(--tz-orange, #ff7c25);
    /* La lumière rasante remplace le dégradé : elle donne du relief sans
       introduire une seconde teinte, donc sans créer de couture. */
    background-image:
        radial-gradient(circle at 86% 18%, rgba(255, 255, 255, 0.16) 0, transparent 46%),
        radial-gradient(circle at 6% 92%, rgba(0, 0, 0, 0.10) 0, transparent 48%);
    padding: 0.5rem 1.25rem 1.6rem;
}

html body .tz-accueil-entete .tz-recherche {
    background: #fff;
    border-color: transparent;
    box-shadow: 0 2px 10px rgba(120, 45, 0, 0.16);
}

/* Les puces de catégorie sur la bande : translucides, bord blanc léger. Un
   fond blanc plein en ferait des boutons rivaux de la recherche. */
html body .tz-accueil-entete .tz-accueil-categories a,
html body .tz-accueil-entete .tz-categorie-puce {
    background: rgba(255, 255, 255, 0.18);
    border: 1px solid rgba(255, 255, 255, 0.42);
    color: #fff;
}

html body .tz-accueil-entete .tz-compteur-categorie {
    color: rgba(255, 255, 255, 0.86);
}

/* Sur les autres pages, un filet de 3 px sous l'en-tête : la même couleur, le
   même signal, sans occuper d'espace. */
html body .site-header {
    border-bottom: 3px solid var(--tz-orange, #ff7c25);
}

/* ==========================================================================
   LE PANIER — troisième version, et cette fois avec de VRAIS prix
   ==========================================================================

   ⚠️ Ma version précédente tenait sur MA donnée de test : des produits à
   ₦4,99. Sur le panier réel — ₦17,500.00 et ₦35,000.00 — les libellés
   « PRICE » et « SUBTOTAL » ne tiennent plus dans une colonne de 109 px et se
   séparent de leur montant : le libellé sur une ligne, la valeur sur une
   autre, et les deux colonnes se chevauchent à la lecture.

   J'avais mesuré, et j'avais mesuré la mauvaise chose. Un panier d'essai à
   cinq nairas ne dit rien d'un catalogue où les prix ont six chiffres.

   Les libellés disparaissent. Ils ne servaient qu'à distinguer deux montants,
   et la POSITION le fait mieux : le prix unitaire sous le nom, le total de la
   ligne en gras à droite de la quantité — la disposition d'un ticket de
   caisse, que personne n'a besoin qu'on lui explique.
   ========================================================================== */

@media (max-width: 767px) {
    /*
     * ⚠️ TROISIÈME disposition, et la seconde a été mise en défaut par le
     * témoin — cette fois avant le client.
     *
     * Elle plaçait le sélecteur de quantité et le total de ligne sur la MÊME
     * rangée. Mesuré sur les produits les plus chers du catalogue
     * (₦110,000.00) : le total prend 110 px, le sélecteur en réclame 114, et
     * la rangée n'en offre que 225 à deux. Huit chevauchements.
     *
     * Les deux MONTANTS s'empilent donc à droite, et les deux GESTES à
     * gauche. Chaque colonne ne contient plus qu'une seule sorte de chose, et
     * aucune ne dépend de la longueur de l'autre :
     *
     *     [vignette]  nom du produit
     *     [vignette]  [− 2 +]     ₦110,000.00     ← prix unitaire, discret
     *     [vignette]  Remove      ₦220,000.00     ← total de ligne, en gras
     */
    html body table.shop_table_responsive tbody tr.cart_item {
        grid-template-columns: 88px auto minmax(0, 1fr);
        grid-template-areas:
            "image nom      nom"
            "image quantite prix"
            "image suppr    total";
        gap: 0.45rem 0.7rem;
        align-items: center;
        padding: 0.9rem 0;
    }

    /* Les deux montants alignés à droite, l'un sous l'autre. */
    html body table.shop_table_responsive td.product-price,
    html body table.shop_table_responsive td.product-subtotal {
        justify-self: end;
        justify-content: flex-end;
        text-align: right;
    }

    html body table.shop_table_responsive td.product-remove {
        justify-self: start;
    }

    /* Le sélecteur resserré : 28 + 44 + 28 = 100 px au lieu de 114. Sur une
       quantité de panier, deux chiffres suffisent — et les 14 px repris sont
       ceux qui manquaient. */
    html body table.shop_table_responsive td.product-quantity input.qty {
        min-width: 44px !important;
        width: 44px !important;
    }

    html body table.shop_table_responsive td.product-quantity .quantity-button {
        width: 28px;
        min-width: 28px;
    }

    html body table.shop_table_responsive td.product-thumbnail img {
        width: 88px;
        height: 88px;
    }

    /* Plus aucun libellé sur cette rangée : c'est ce qui débordait. */
    html body table.shop_table_responsive td.product-price::before,
    html body table.shop_table_responsive td.product-subtotal::before {
        content: none;
    }

    html body table.shop_table_responsive td.product-price {
        justify-content: flex-start;
        color: var(--tz-encre-douce, #57534e);
        font-size: 0.95rem;
    }

    html body table.shop_table_responsive td.product-subtotal {
        font-size: 1.05rem;
        font-weight: 700;
        white-space: nowrap;
    }

    /* La suppression : un lien discret sous le sélecteur, loin de la vignette.
     *
     * ⚠️ `font-size: 0` — et il FAUT le remettre ici. Une règle antérieure
     * l'avait posé pour éteindre le « × » que WooCommerce écrit dans le lien ;
     * ma refonte a réglé `font-size: 0.8rem` sur ce même lien et l'a rallumé.
     * La capture montrait « × Remove ».
     *
     * La taille visible vit donc sur le `::after`, qui porte l'intitulé —
     * jamais sur le lien lui-même, dont le contenu propre doit rester muet. */
    html body table.shop_table_responsive td.product-remove a.remove {
        height: 32px;
        min-height: 32px;
        padding: 0 0.6rem 0 0;
        border-color: transparent;
        font-size: 0;
    }

    html body table.shop_table_responsive td.product-remove a.remove::after {
        font-size: 0.8rem;
        text-decoration: underline;
        text-underline-offset: 3px;
    }

    /* Les montants ne touchent pas le bord de la carte : un chiffre collé au
       cadre se lit comme un chiffre coupé, même quand il est entier. */
    html body table.shop_table_responsive td.product-price,
    html body table.shop_table_responsive td.product-subtotal {
        padding-right: 0.15rem;
    }
}

/* ==========================================================================
   Le tiroir des catégories — défilement, et présentation
   ==========================================================================

   Signalé : « on n'arrive plus à scroller dans la section Catégorie ».

   ⚠️ JE N'AI PAS RÉUSSI À LE REPRODUIRE, et je le dis plutôt que de faire
   semblant. Mesuré ici, tiroir ouvert, catégories repliées ET dépliées : le
   panneau défile de 248 px dans les deux cas, `overflow-y: auto`.

   Ma première mesure disait pourtant « ne défile pas » après dépliage — elle
   était fausse : ma sonde poussait `scrollTop` à 600 et ne le REMETTAIT PAS À
   ZÉRO entre deux relevés. Au second appel, le panneau était déjà au bout, et
   « il n'a pas bougé » signifiait « il ne pouvait plus bouger ». J'ai failli
   conclure à une panne qui était dans mon outil.

   Cela ne prouve pas que le client se trompe — un vrai doigt sur un vrai
   téléphone n'est pas un `scrollTop` posé par un script. La cause la plus
   probable est que le contenu déborde le CONTENEUR INTERNE plutôt que le
   panneau, et qu'aucun des deux ne l'accepte.

   On rend donc les DEUX niveaux capables de défiler. Ce n'est pas une
   ceinture et des bretelles par excès de prudence : le panneau et son
   contenu peuvent grandir indépendamment quand une catégorie se déplie, et
   celui qui déborde n'est pas toujours le même.
   ========================================================================== */

html body aside.site-drawer {
    display: flex;
    flex-direction: column;
    overflow-y: auto;
    overscroll-behavior: contain;
    -webkit-overflow-scrolling: touch;
}

html body aside.site-drawer .site-scrollsa {
    flex: 1 1 auto;
    /* `min-height: 0` est indispensable : sans lui, un enfant de flex refuse
       de rétrécir sous sa hauteur de contenu et ne déborde donc jamais — le
       défilement n'a alors rien à faire défiler. */
    min-height: 0;
    overflow-y: auto;
    overscroll-behavior: contain;
    -webkit-overflow-scrolling: touch;
}

/* --- La présentation ------------------------------------------------------
   Signalé aussi : « la présentation de cette section n'est pas esthétique ».
   Les entrées étaient des lignes de texte de hauteurs inégales, les compteurs
   flottaient en bout de ligne, et rien ne séparait un rayon d'un autre.
   -------------------------------------------------------------------------- */

html body aside.site-drawer .drawer-body .menu-item > a {
    display: flex;
    align-items: center;
    gap: 0.7rem;
    min-height: 46px;
    padding: 0 1rem;
    font-size: 0.95rem;
    color: var(--tz-encre, #1c1917);
    border-radius: 10px;
}

html body aside.site-drawer .drawer-body .menu-item > a:active,
html body aside.site-drawer .drawer-body .menu-item > a:focus-visible {
    background: #fff4ec;
}

/* Le compteur : une pastille discrète, poussée à droite, alignée d'une ligne
   à l'autre. Il était collé au libellé, ce qui faisait lire « Body Cream 7 »
   comme un nom de produit. */
html body aside.site-drawer .tz-compteur-categorie {
    margin-left: auto;
    min-width: 24px;
    padding: 0.1rem 0.45rem;
    border-radius: 999px;
    background: #f4efe9;
    color: var(--tz-encre-douce, #57534e);
    font-size: 0.78rem;
    font-weight: 600;
    text-align: center;
    font-variant-numeric: tabular-nums;
}

/* Les intitulés de section — MAIN MENU, BROWSE CATEGORIES — deviennent des
   repères et non des lignes de plus. */
html body aside.site-drawer .drawer-body > .menu-title,
html body aside.site-drawer .drawer-body .widget-title {
    margin: 1.1rem 1rem 0.35rem;
    font-size: 0.7rem;
    font-weight: 700;
    letter-spacing: 0.12em;
    text-transform: uppercase;
    color: var(--tz-encre-douce, #57534e);
}

/* Les sous-catégories se distinguent par un léger retrait et un filet, au
   lieu de se confondre avec leurs parents. */
html body aside.site-drawer .drawer-body .sub-menu {
    margin: 0.15rem 0 0.4rem 1.75rem;
    padding-left: 0.75rem;
    border-left: 2px solid var(--tz-trait-doux, #efe9e3);
}

html body aside.site-drawer .drawer-body .sub-menu .menu-item > a {
    min-height: 40px;
    font-size: 0.9rem;
    color: var(--tz-encre-douce, #57534e);
}

/* ==========================================================================
   TZ-47 — la ligne de réassurance
   ==========================================================================
   Elle se lit d'un coup d'œil ou pas du tout : trois promesses courtes, et un
   lien vers le texte qui les porte. Discrète — c'est une réponse à une
   inquiétude, pas un argument de vente.
   ========================================================================== */

html body .tz-reassurance {
    margin: 1rem 0 0;
    padding: 0.9rem 1rem;
    border: 1px solid var(--tz-trait-doux, #efe9e3);
    border-radius: 14px;
    background: var(--tz-carte, #fff);
}

html body .tz-reassurance ul {
    display: grid;
    gap: 0.6rem;
    margin: 0;
    padding: 0;
    list-style: none;
}

html body .tz-reassurance li {
    display: grid;
    gap: 0.1rem;
    margin: 0;
    /* Le marqueur est décoratif : le texte dit tout, et un lecteur d'écran
       n'a rien à faire d'une coche. */
    padding-left: 1.5rem;
    position: relative;
}

html body .tz-reassurance li::before {
    content: "";
    position: absolute;
    left: 0;
    top: 0.35rem;
    width: 14px;
    height: 8px;
    border-left: 2px solid var(--tz-orange, #ff7c25);
    border-bottom: 2px solid var(--tz-orange, #ff7c25);
    transform: rotate(-45deg);
}

html body .tz-reassurance strong {
    font-size: 0.92rem;
    font-weight: 700;
    color: var(--tz-encre, #1c1917);
}

html body .tz-reassurance span {
    font-size: 0.85rem;
    line-height: 1.4;
    color: var(--tz-encre-douce, #57534e);
}

html body .tz-reassurance > a {
    display: inline-block;
    margin-top: 0.8rem;
    font-size: 0.85rem;
    font-weight: 600;
    color: var(--tz-orange, #ff7c25);
    text-underline-offset: 3px;
}

/* ==========================================================================
   L'ORANGE PORTÉ PAR LE SITE, ET PLUS SEULEMENT PAR SES BOUTONS
   ==========================================================================

   Demandé : « la barre de Tizzleshop est toujours blanche, le fond blanc dans
   le corps ; mettons un fond orange typique à Tizzle ».

   ---------------------------------------------------------------------------
   Ce que la mesure a dicté
   ---------------------------------------------------------------------------
   Le thème déclare deux logos, `dark-logo` et `light-logo` — mais les deux
   pointent le MÊME fichier : `tizzle-logo-tranprent…png`. Il n'existe donc
   AUCUNE version claire.

   C'est ce qui décide de la forme. Le logo porte un emblème orange : posé sur
   une barre orange, il disparaît. Le mot « tizzleshop », foncé, tiendrait ;
   l'emblème non — et un logo amputé de sa marque vaut moins qu'une barre
   blanche.

   Le logo va donc sur une PASTILLE BLANCHE posée sur l'orange. C'est ce que
   font les marques dont l'emblème porte la couleur : l'artwork est préservé
   au pixel près, et la barre devient franchement orange. Le jour où
   Tizzleshop fournit un logo blanc, la pastille se retire en trois lignes.

   ⚠️ Le corps ne devient PAS orange vif. Un aplat saturé derrière un
   catalogue rend chaque photo sale et chaque texte fatigant. Il devient un
   blanc TEINTÉ d'orange — assez pour qu'on nomme la couleur, assez clair pour
   que le texte reste à 15:1. C'est la différence entre une identité et un
   filtre.
   ========================================================================== */

/*
 * ⚠️ `.site-header` était DÉJÀ orange — mesuré `rgb(255, 124, 37)` — et la
 * barre paraissait blanche quand même. Ce n'est pas la barre qui était en
 * cause, c'est son enfant : `div.header-row.header-mobile-main` peint du blanc
 * par-dessus, sur toute la largeur.
 *
 * J'ai regardé le conteneur et déclaré la couleur posée. Le navigateur, lui,
 * empile : une couleur appliquée ne se voit que si rien ne la recouvre. La
 * question utile n'était pas « quelle couleur porte l'en-tête » mais « qu'y
 * a-t-il sous ce pixel » — et `elementsFromPoint` y répond en une ligne.
 */
html body .site-header,
html body header.site-header,
html body .site-header .header-main,
html body .site-header .header-row,
html body .site-header .header-mobile-main {
    background-color: var(--tz-orange, #ff7c25) !important;
    border-bottom: 0;
}

/* La pastille : le logo garde son fond clair, la barre garde sa couleur. */
html body .site-header .site-brand a,
html body .site-header .logo a,
html body .site-header a.custom-logo-link {
    display: inline-flex;
    align-items: center;
    padding: 0.35rem 0.8rem;
    border-radius: 999px;
    background: #fff;
    box-shadow: 0 1px 4px rgba(120, 45, 0, 0.18);
}

/* Tout ce qui n'est pas le logo passe en blanc : icônes, liens, compteurs. */
html body .site-header a:not(.custom-logo-link):not([class*="logo"]),
html body .site-header button,
html body .site-header svg,
html body .site-header i {
    color: #fff;
}

html body .site-header svg [stroke] { stroke: currentColor; }
html body .site-header svg [fill]:not([fill="none"]) { fill: currentColor; }

/* La bande de l'accueil prolonge la barre : aucune couture entre les deux. */
html body .site-header + * .tz-accueil-entete,
html body .tz-accueil-entete {
    margin-top: 0;
}

/* --------------------------------------------------------------------------
   Le papier : un blanc teinté d'orange
   --------------------------------------------------------------------------

   #faf7f4 était un blanc cassé NEUTRE — il séparait les cartes du fond, mais
   il ne nommait aucune couleur. #fff4ea est le même geste, tiré vers la
   marque : mesuré, le texte d'encre y reste à 15,9:1, très au-dessus des 4,5
   exigés.
   -------------------------------------------------------------------------- */

:root {
    --tz-papier: #fff4ea;
    --tz-trait-doux: #f3e3d5;
}

/*
 * ⚠️ `html body { background-color: … }` ne prenait pas : le corps restait
 * `rgb(255, 255, 255)`. Le thème peint via `body.home` — UNE CLASSE, qui bat
 * mes deux éléments, puisque les classes se comparent avant les éléments.
 *
 * `body[class]` vaut un sélecteur de classe et s'applique à tout corps qui en
 * porte au moins une — c'est-à-dire toutes les pages WordPress. Il l'emporte
 * sans nommer `home`, `archive`, `single` et les quarante autres.
 */
html body[class],
html body[class] .site-content,
html body[class] .site-primary,
html body[class] #content {
    background-color: var(--tz-papier);
}

/* Les cartes restent d'un blanc PUR : c'est leur écart avec le papier teinté
   qui les fait exister. Les égaliser reviendrait au blanc sur blanc du
   départ, en plus chaud. */
html body div.products div.product,
html body ul.products li.product,
html body .woocommerce-MyAccount-content,
html body .cart-collaterals,
html body .woocommerce-checkout-review-order,
html body table.shop_table_responsive,
html body .tz-reassurance {
    background: #fff;
}

/* La barre du bas reprend la teinte du papier plutôt qu'un blanc qui la
   détacherait comme un bandeau étranger. */
html body .klb-mobile-bottom {
    background: rgba(255, 244, 234, 0.94);
    border-top: 1px solid var(--tz-trait-doux, #f3e3d5);
}

/* L'onglet actif porte l'orange : c'est le seul repère de position de la
   barre, et il était rendu en gris comme les autres. */
html body .klb-mobile-bottom a.active,
html body .klb-mobile-bottom a[aria-current="page"] {
    color: var(--tz-orange, #ff7c25);
}

/* ==========================================================================
   LOT DU 12/08 — huit retours du client, un par un
   ========================================================================== */

/* --------------------------------------------------------------------------
   1. « Trouver une autre couleur pour Exclusive Offer » — plus d'orange sur
      orange
   --------------------------------------------------------------------------

   La bannière posait un orange sur la bande orange : deux valeurs proches
   d'une même teinte, séparées par une couture. Ce n'était pas une bande, mais
   deux blocs qui se ressemblaient sans se confondre.

   La bannière devient une CARTE CLAIRE posée sur la bande. C'est le geste
   classique — la couleur porte le contenant, le contenu se pose dessus en
   clair — et il résout le problème au lieu de choisir un troisième orange.
   L'accent revient sur le seul bouton, qui redevient orange sur clair.
   -------------------------------------------------------------------------- */

html body .tz-accueil-entete + .tz-promo,
html body .tz-promo:first-of-type {
    margin: 0 1rem 1.1rem;
    padding: 1.15rem 1.15rem 1.25rem;
    border-radius: 18px;
    background: #fffaf5;
    background-image: none;
    box-shadow: 0 6px 22px rgba(120, 45, 0, 0.18);
    color: var(--tz-encre, #1c1917);
}

html body .tz-promo .tz-promo-surtitre {
    color: #b8450a;
    opacity: 1;
}

html body .tz-promo .tz-promo-pastille {
    background: var(--tz-orange, #ff7c25);
    color: #fff;
}

html body h2.tz-promo-titre {
    color: var(--tz-encre, #1c1917);
}

html body .tz-promo .tz-promo-sous {
    color: var(--tz-encre-douce, #57534e);
    opacity: 1;
}

html body a.tz-promo-bouton {
    background: var(--tz-orange, #ff7c25);
    color: #fff;
}

html body a.tz-promo-bouton:hover,
html body a.tz-promo-bouton:focus-visible {
    background: #e46a12;
    color: #fff;
}

/* La bande se referme sous la carte. */
html body .tz-accueil-entete {
    padding-bottom: 1.1rem;
    border-radius: 0 0 22px 22px;
}

/* --------------------------------------------------------------------------
   2. « Le bouton recherche n'est pas utile là, il se trouve dans Home »
   --------------------------------------------------------------------------

   L'onglet ouvrait un panneau qui ne contenait qu'une ligne « Trending: » et
   du vide — la recherche vit désormais en tête de l'accueil, dans la bande.
   Deux portes vers la même chose, dont l'une donne sur une pièce vide.

   ⚠️ Masqué, pas supprimé : la recherche reste atteignable par son adresse et
   par le champ de l'accueil, et la règle se retire en une ligne si Tizzleshop
   veut rétablir l'onglet.
   -------------------------------------------------------------------------- */

html body .klb-mobile-bottom a.search,
html body .klb-mobile-bottom li:has(> a.search) {
    display: none;
}

/* --------------------------------------------------------------------------
   3. « Retravailler le total » — le bloc des totaux du panier
   --------------------------------------------------------------------------

   Relevé : deux lignes, SUBTOTAL et TOTAL, à la même taille et au même poids,
   séparées par un filet orange sous la première. Rien ne disait laquelle
   engage — et c'est le TOTAL qu'on paie.
   -------------------------------------------------------------------------- */

html body .cart_totals table,
html body .cart_totals tbody {
    display: block;
    width: 100%;
}

html body .cart_totals tr {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 1rem;
    padding: 0.6rem 0;
    border: 0;
    border-bottom: 1px solid var(--tz-trait-doux, #f3e3d5);
}

/* ⚠️ `border: 0` sans `!important` laissait passer un filet orange du thème,
   posé sur les CELLULES et non sur la rangée : il apparaissait en deux
   segments, un sous le libellé et un sous le montant, avec un blanc au milieu.
   Un trait cassé en deux se lit comme un défaut d'affichage. Les traits
   appartiennent désormais à la rangée seule. */
html body .cart_totals tr th,
html body .cart_totals tr td {
    padding: 0;
    border: 0 !important;
    text-align: right;
    font-variant-numeric: tabular-nums;
}

html body .cart_totals tr th {
    text-align: left;
    font-size: 0.85rem;
    font-weight: 500;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    color: var(--tz-encre-douce, #57534e);
}

/* Le total : le seul chiffre qu'on lit vraiment, et le seul qui engage. */
html body .cart_totals tr.order-total {
    margin-top: 0.35rem;
    padding-top: 0.9rem;
    border-bottom: 0;
    border-top: 2px solid var(--tz-encre, #1c1917);
}

html body .cart_totals tr.order-total th {
    font-size: 1rem;
    font-weight: 700;
    text-transform: none;
    letter-spacing: 0;
    color: var(--tz-encre, #1c1917);
}

html body .cart_totals tr.order-total td {
    font-size: 1.45rem;
    font-weight: 800;
    line-height: 1.15;
    color: var(--tz-encre, #1c1917);
}

html body .cart_totals .checkout-button,
html body .wc-proceed-to-checkout a.button {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 100%;
    min-height: 52px;
    margin-top: 1rem;
    border-radius: 999px;
    font-size: 1rem;
    font-weight: 700;
}

/* --------------------------------------------------------------------------
   4. « La séparation entre les produits doit être plus visible »
   --------------------------------------------------------------------------
   Le filet valait `rgba(0,0,0,0.08)` — invisible sur un papier teinté. Chaque
   article devient une carte à part entière : c'est la séparation la plus
   lisible qui soit, et elle ne demande aucun trait.
   -------------------------------------------------------------------------- */

@media (max-width: 767px) {
    html body table.shop_table_responsive {
        padding: 0;
        border: 0;
        background: transparent;
    }

    html body table.shop_table_responsive tbody tr.cart_item {
        margin-bottom: 0.7rem;
        padding: 0.9rem;
        border: 1px solid var(--tz-trait-doux, #f3e3d5);
        border-bottom: 1px solid var(--tz-trait-doux, #f3e3d5);
        border-radius: 14px;
        background: #fff;
        box-shadow: 0 1px 2px rgba(28, 25, 23, 0.04);
    }
}

/* --------------------------------------------------------------------------
   5. « Pas esthétique » — les onglets de la fiche produit
   --------------------------------------------------------------------------
   Six onglets en `flex-wrap: wrap` s'empilaient sur trois lignes, et l'on ne
   voyait plus lequel était actif. Ils défilent désormais sur UNE ligne : c'est
   le geste attendu d'une rangée d'onglets sur téléphone.
   -------------------------------------------------------------------------- */

html body .woocommerce-tabs ul.tabs,
html body ul.wc-tabs {
    display: flex;
    flex-wrap: nowrap;
    overflow-x: auto;
    scrollbar-width: none;
    gap: 0.25rem;
    margin: 0 0 1rem;
    padding: 0 0 0.15rem;
    border-bottom: 1px solid var(--tz-trait-doux, #f3e3d5);
    /* Le doigt s'arrête sur un onglet, pas entre deux. */
    scroll-snap-type: x proximity;
}

html body .woocommerce-tabs ul.tabs::-webkit-scrollbar,
html body ul.wc-tabs::-webkit-scrollbar {
    display: none;
}

html body .woocommerce-tabs ul.tabs li,
html body ul.wc-tabs li {
    flex: 0 0 auto;
    margin: 0;
    padding: 0;
    border: 0;
    background: transparent;
    scroll-snap-align: start;
}

html body .woocommerce-tabs ul.tabs li a,
html body ul.wc-tabs li a {
    display: block;
    padding: 0.6rem 0.9rem;
    border-bottom: 2px solid transparent;
    color: var(--tz-encre-douce, #57534e);
    font-size: 0.92rem;
    font-weight: 600;
    white-space: nowrap;
}

html body .woocommerce-tabs ul.tabs li.active a,
html body ul.wc-tabs li.active a {
    color: var(--tz-encre, #1c1917);
    border-bottom-color: var(--tz-orange, #ff7c25);
}

/* --------------------------------------------------------------------------
   6. « Retirer Store, c'est mieux de l'afficher dans la description »
   --------------------------------------------------------------------------
   « Store: Tizzleshop Official » occupait deux lignes sur chaque carte, pour
   une information identique partout — la boutique est la même sur tout le
   catalogue. Deux lignes par carte, multipliées par soixante cartes, pour ne
   rien distinguer.

   ⚠️ Masqué sur les CARTES seulement. Sur la fiche produit, le vendeur est une
   information qui compte : c'est là qu'on décide d'acheter, et savoir à qui
   l'on achète en fait partie.
   -------------------------------------------------------------------------- */

html body div.products .product-vendor,
html body ul.products .product-vendor,
html body .product-wrapper .product-vendor {
    display: none;
}

/* --------------------------------------------------------------------------
   7. Le repère orange n'appartient qu'aux titres de SECTION
   --------------------------------------------------------------------------
   Sur l'accueil, il s'est posé sous chaque vignette de catégorie — « XBOX »,
   « PLAYSTATION », « PC GAMING » — parce que je visais `.site-content h2`, ce
   qui attrape tout titre de la page.

   Il ne vise plus que les titres portés par un widget de titre : ce sont eux,
   et eux seuls, qui ouvrent une section.
   -------------------------------------------------------------------------- */

html body .site-content h2:not(.product-title):not(.entry-title)::before,
html body .site-content h3.widget-title::before {
    content: none;
}

html body .elementor-widget-heading h2:not(.product-title):not(.entry-title) {
    font-size: 1.28rem;
    line-height: 1.25;
    font-weight: 800;
    letter-spacing: -0.01em;
    text-wrap: balance;
}

html body .elementor-widget-heading h2:not(.product-title):not(.entry-title)::before {
    content: "";
    display: block;
    width: 34px;
    height: 3px;
    margin-bottom: 0.55rem;
    border-radius: 999px;
    background: var(--tz-orange, #ff7c25);
}

/* --------------------------------------------------------------------------
   8. « Pas esthétique » — la liste des produits en colonne
   --------------------------------------------------------------------------
   Sur la page catégorie en vue liste, les cartes n'avaient ni la même largeur
   ni le même alignement : elles se décalaient l'une par rapport à l'autre.
   Elles passent sur la même grille que partout ailleurs.
   -------------------------------------------------------------------------- */

@media (max-width: 767px) {
    html body div.products.list-column,
    html body div.products.grid-column-1,
    html body .products.columns-1 {
        display: grid !important;
        grid-template-columns: 1fr;
        gap: 0.7rem;
    }

    html body div.products.list-column div.product,
    html body .products.columns-1 div.product {
        width: auto !important;
        margin: 0 !important;
    }

    /* En vue liste, l'image passe à gauche et le texte à droite : une image
       carrée pleine largeur ferait défiler quatre écrans pour six produits. */
    html body div.products.list-column .product-inner,
    html body .products.columns-1 .product-inner {
        flex-direction: row;
        align-items: stretch;
    }

    html body div.products.list-column .thumbnail-wrapper,
    html body .products.columns-1 .thumbnail-wrapper {
        flex: 0 0 108px;
        width: 108px;
    }

    html body div.products.list-column .content-wrapper,
    html body .products.columns-1 .content-wrapper {
        justify-content: center;
    }
}

/* ==========================================================================
   1. Le message d'ajout au panier
   ==========================================================================
   Le texte est raccourci côté serveur (TZ-48) ; il ne reste ici qu'à l'habiller.
   Une barre discrète aux couleurs du site, avec le seul lien qui compte.
   ========================================================================== */

/*
 * ⚠️ Le message court ne suffisait pas : il flottait au milieu d'un panneau
 * VIDE qui recouvrait la page. Mesuré — `div.klb-notice-ajax` est fixe et
 * haut de 435 px, quelle que soit la hauteur de ce qu'il contient. Le thème
 * y logeait la vignette et le titre complet du produit ; en raccourcissant le
 * texte, j'ai vidé la boîte sans la redimensionner.
 *
 * Raccourcir un contenu ne rétrécit pas son contenant. C'est une évidence
 * écrite après coup — et la capture, encore une fois, l'a montrée avant la
 * mesure.
 *
 * Le panneau devient une vraie notification : posée en bas, au-dessus de la
 * barre d'onglets, à la hauteur de son texte.
 */
html body .klb-notice-ajax {
    position: fixed;
    left: 0.75rem;
    right: 0.75rem;
    /* Au-dessus de la barre du bas, jamais dessous : un message qu'on ne voit
       pas ne confirme rien. */
    bottom: calc(74px + 0.75rem);
    top: auto;
    width: auto;
    /* `!important` : la hauteur de 435 px est posée EN LIGNE par le script du
       thème, qui dimensionne le panneau pour la vignette et le titre complet
       qu'il y logeait. Une déclaration de feuille sans `!important` ne bat pas
       un style en ligne. */
    height: auto !important;
    min-height: 0 !important;
    max-height: none !important;
    padding: 0;
    background: transparent;
}

html body .klb-notice-ajax .woocommerce-message {
    height: auto !important;
    min-height: 0 !important;
    box-shadow: 0 8px 28px rgba(28, 25, 23, 0.18);
}

html body .tz-ajout-panier {
    height: auto !important;
    min-height: 0 !important;
}

/*
 * ⚠️ Le panneau restait haut de 435 px malgré `height: auto !important`, et
 * la raison n'était pas une propriété : c'était son CONTENU. Le thème injecte
 * des paragraphes que sa mise en page remplissait — mesurés vides mais hauts
 * de 192 px — pour la vignette et le titre qu'il y logeait.
 *
 * J'ai raccourci le texte sans retirer les boîtes qui l'entouraient. Trois
 * tentatives sur `height`, alors qu'aucune hauteur n'était en cause.
 */
html body .klb-notice-ajax p:empty,
html body .woocommerce-message p:empty,
html body .tz-ajout-panier p:empty {
    display: none !important;
}

/* Le thème pose une vignette en pseudo-élément, dimensionnée pour l'image du
   produit qu'il affichait. Elle n'a plus de contenu : elle ne garde que sa
   hauteur. */
html body .klb-notice-ajax .woocommerce-message::before,
html body .klb-notice-ajax .woocommerce-message::after {
    display: none !important;
    content: none !important;
}

/* Et la ceinture : le bloc ne peut pas dépasser deux lignes de texte plus son
   bouton. Une notification qui prend un tiers de l'écran n'est plus une
   notification. */
html body .klb-notice-ajax .woocommerce-message {
    max-height: 88px;
    overflow: hidden;
    align-items: center;
}

html body .woocommerce-message,
html body .woocommerce-message.tz-ajout {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 1rem;
    margin: 0 0 1rem;
    padding: 0.85rem 1rem;
    border: 1px solid #f3d9c2;
    border-left: 4px solid var(--tz-orange, #ff7c25);
    border-radius: 12px;
    background: #fff7f0 !important;
    color: var(--tz-encre, #1c1917) !important;
    font-size: 0.95rem;
    line-height: 1.4;
}

html body .tz-ajout-panier {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 1rem;
    width: 100%;
}

html body .tz-ajout-texte {
    font-weight: 600;
}

html body a.tz-ajout-lien,
html body .woocommerce-message a.button {
    flex: 0 0 auto;
    display: inline-flex;
    align-items: center;
    min-height: 40px;
    padding: 0 1rem;
    border-radius: 999px;
    background: var(--tz-orange, #ff7c25) !important;
    color: #fff !important;
    font-size: 0.88rem;
    font-weight: 700;
    text-decoration: none;
    white-space: nowrap;
}

/* ==========================================================================
   2. Les filtres et les tris
   ==========================================================================
   Mesuré : `div.filter-button` fait 65 × 24 px — une cible deux fois trop
   petite pour un doigt — et rien ne dit que l'un ou l'autre est cliquable :
   ni fond, ni bordure, ni rayon. Deux commandes déguisées en texte.
   ========================================================================== */

html body .before-shop-loop {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.6rem;
    margin: 0 0 1rem;
    padding: 0.5rem 0;
}

html body .before-shop-loop .filter-button,
html body .before-shop-loop .sorting-products {
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    min-height: 44px;
    padding: 0 0.9rem;
    border: 1px solid var(--tz-trait-doux, #f3e3d5);
    border-radius: 999px;
    background: #fff;
    font-size: 0.9rem;
    font-weight: 600;
    color: var(--tz-encre, #1c1917);
}

html body .before-shop-loop .sorting-products {
    flex: 1 1 auto;
    justify-content: flex-end;
    min-width: 0;
}

html body .before-shop-loop .sorting-products select {
    border: 0;
    background: transparent;
    font-size: 0.9rem;
    font-weight: 600;
    /* 16 px à la mise au point, sinon Safari iOS zoome et la page saute. */
    max-width: 100%;
}

/* ==========================================================================
   3. Le paiement : le bloc d'erreurs du haut disparaît
   ==========================================================================

   Demandé : « retirer le gros bloc du dessus, les messages d'erreur
   s'affichent déjà au niveau des champs ».

   ⚠️ C'est l'INVERSE de ce que j'avais soutenu hier — j'avais gardé ce bloc
   comme récapitulatif. L'argument tenait quand les champs étaient muets ; ils
   ne le sont plus. Deux fois le même message, dont l'un occupe un tiers de
   l'écran avant même le premier champ, c'est une redite qui repousse le
   formulaire hors de vue.

   Le bloc est MASQUÉ, pas supprimé, et il reste dans le document : un lecteur
   d'écran l'annonce toujours à la soumission, ce qui est sa vraie utilité.
   ========================================================================== */

html body form.checkout .woocommerce-NoticeGroup-checkout,
html body .woocommerce-checkout > .woocommerce-NoticeGroup,
html body form.checkout > ul.woocommerce-error {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
}

/* ==========================================================================
   4. Le récapitulatif du paiement, la commande reçue, le suivi
   ==========================================================================
   Les trois écrans partagent le même défaut : des tableaux WooCommerce bruts,
   des liens bleus par défaut, des adresses qui tombent un mot par ligne. Ils
   partagent donc le même traitement.
   ========================================================================== */

html body .woocommerce-checkout-review-order,
html body .woocommerce-order,
html body .woocommerce-order-details,
html body .woocommerce-customer-details,
html body .woocommerce-thankyou-order-details,
html body .woocommerce-MyAccount-content .order-again {
    background: #fff;
    border: 1px solid var(--tz-trait-doux, #f3e3d5);
    border-radius: 14px;
    padding: 1rem;
    margin-bottom: 1rem;
}

/* Les lignes de produit : deux colonnes, nom rogné, montant à droite. */
html body table.woocommerce-checkout-review-order-table,
html body table.woocommerce-table--order-details,
html body table.shop_table.order_details {
    width: 100%;
    border: 0;
    border-collapse: collapse;
}

html body table.woocommerce-table--order-details thead,
html body table.shop_table.order_details thead {
    display: none;
}

html body table.woocommerce-table--order-details tbody tr,
html body table.shop_table.order_details tbody tr {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto;
    gap: 0.2rem 0.8rem;
    align-items: baseline;
    padding: 0.7rem 0;
    border-bottom: 1px solid var(--tz-trait-doux, #f3e3d5);
}

html body table.woocommerce-table--order-details tbody td,
html body table.shop_table.order_details tbody td {
    padding: 0;
    border: 0;
    font-variant-numeric: tabular-nums;
}

/* Le nom du produit : deux lignes, encre — et non un lien bleu de 2003. */
html body table.woocommerce-table--order-details td.product-name a,
html body table.shop_table.order_details td.product-name a,
html body .woocommerce-order-details td.product-name a {
    color: var(--tz-encre, #1c1917);
    font-weight: 600;
    text-decoration: none;
    display: -webkit-box;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 2;
    line-clamp: 2;
    overflow: hidden;
}

html body table.woocommerce-table--order-details td.product-total,
html body table.shop_table.order_details td.product-total {
    text-align: right;
    font-weight: 700;
    white-space: nowrap;
}

/* Les totaux de bas de tableau : même hiérarchie que le panier. */
html body table.shop_table tfoot tr,
html body table.woocommerce-table--order-details tfoot tr {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 1rem;
    padding: 0.55rem 0;
    border-bottom: 1px solid var(--tz-trait-doux, #f3e3d5);
}

html body table.shop_table tfoot tr th,
html body table.shop_table tfoot tr td,
html body table.woocommerce-table--order-details tfoot tr th,
html body table.woocommerce-table--order-details tfoot tr td {
    padding: 0;
    border: 0 !important;
    text-align: right;
    font-variant-numeric: tabular-nums;
}

html body table.shop_table tfoot tr th,
html body table.woocommerce-table--order-details tfoot tr th {
    text-align: left;
    font-size: 0.85rem;
    font-weight: 500;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--tz-encre-douce, #57534e);
}

html body table.shop_table tfoot tr:last-child,
html body table.woocommerce-table--order-details tfoot tr:last-child {
    margin-top: 0.35rem;
    padding-top: 0.85rem;
    border-bottom: 0;
    border-top: 2px solid var(--tz-encre, #1c1917);
}

html body table.shop_table tfoot tr:last-child th,
html body table.woocommerce-table--order-details tfoot tr:last-child th {
    font-size: 1rem;
    font-weight: 700;
    text-transform: none;
    letter-spacing: 0;
    color: var(--tz-encre, #1c1917);
}

html body table.shop_table tfoot tr:last-child td,
html body table.woocommerce-table--order-details tfoot tr:last-child td {
    font-size: 1.35rem;
    font-weight: 800;
    color: var(--tz-encre, #1c1917);
}

/* --------------------------------------------------------------------------
   Les adresses de la commande : un mot par ligne, encore
   --------------------------------------------------------------------------
   Même cause que sur la page du compte — deux colonnes qui n'ont pas la place
   d'en être. Sur ces écrans, une seule colonne.
   -------------------------------------------------------------------------- */

html body .woocommerce-customer-details .woocommerce-columns,
html body .woocommerce-customer-details .col2-set {
    display: grid;
    grid-template-columns: 1fr;
    gap: 1rem;
}

html body .woocommerce-customer-details .col-1,
html body .woocommerce-customer-details .col-2 {
    width: auto !important;
    max-width: none !important;
    float: none !important;
}

html body .woocommerce-customer-details address {
    font-style: normal;
    line-height: 1.55;
    color: var(--tz-encre-douce, #57534e);
}

/* --------------------------------------------------------------------------
   La ligne « Thank you » et le récapitulatif de commande
   -------------------------------------------------------------------------- */

html body ul.woocommerce-order-overview,
html body ul.woocommerce-thankyou-order-details {
    display: grid;
    gap: 0.55rem;
    margin: 0 0 1rem;
    padding: 0;
    list-style: none;
}

html body ul.woocommerce-order-overview li,
html body ul.woocommerce-thankyou-order-details li {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 1rem;
    margin: 0;
    padding: 0.5rem 0;
    border: 0;
    border-bottom: 1px solid var(--tz-trait-doux, #f3e3d5);
    font-size: 0.9rem;
    text-transform: none;
    color: var(--tz-encre-douce, #57534e);
}

html body ul.woocommerce-order-overview li strong,
html body ul.woocommerce-thankyou-order-details li strong {
    font-size: 1rem;
    font-weight: 700;
    color: var(--tz-encre, #1c1917);
    text-align: right;
}

/* L'état de la commande, mis en avant : c'est la seule chose qu'on vient voir
   sur un écran de suivi. */
html body .woocommerce-order p mark,
html body .woocommerce-MyAccount-content p mark {
    padding: 0.15rem 0.5rem;
    border-radius: 999px;
    background: #fff0e2;
    color: #b8450a;
    font-weight: 700;
}

/* ==========================================================================
   Le haut de la page catégorie
   ==========================================================================

   « Qu'est-il arrivé au haut de page ? » — mesuré : `div.klb-banner` fait bien
   360 px de large, mais l'IMAGE qu'il contient s'arrête aux deux tiers et
   laisse un tiers de blanc à droite. Le conteneur est plein, son contenu ne
   l'est pas.

   La bannière porte l'illustration de la catégorie : c'est la seule chose qui
   dit où l'on est avant de voir les produits. À moitié remplie, elle ressemble
   à une image qui n'a pas fini de charger.
   ========================================================================== */

/*
 * ⚠️ Ma première règle visait `… .klb-banner img`. Il n'y a PAS d'image : la
 * bannière est une `div` qui porte l'illustration en FOND. Une règle sur une
 * balise absente ne fait rien, et ne le dit pas.
 *
 * Le relevé le montrait pourtant — `naturelle: null` sur l'élément mesuré :
 * une balise `img` aurait donné ses dimensions naturelles. J'avais la preuve
 * sous les yeux et j'ai écrit la règle que j'avais en tête.
 */
html body .woocommerce-page-header .klb-banner,
html body .klb-banner.inner-style.small-size {
    overflow: hidden;
    border-radius: 14px;
    background-size: cover !important;
    background-position: center !important;
    background-repeat: no-repeat !important;
}

html body .woocommerce-page-header .klb-banner img,
html body .klb-banner.inner-style.small-size img {
    width: 100% !important;
    max-width: none !important;
    height: 100%;
    /* `cover` ici, et non `contain` : une illustration de rubrique est un
       décor, pas un produit. La rogner sur les bords ne fait rien perdre,
       tandis qu'une bande blanche à côté se lit comme une panne. */
    object-fit: cover;
    object-position: center;
}

/* --------------------------------------------------------------------------
   Les filtres et les tris tiennent sur UNE rangée
   --------------------------------------------------------------------------
   Chacun occupait toute la largeur, l'un sous l'autre : deux rangées et
   112 px pris à la grille de produits, pour deux commandes qui se lisent d'un
   coup d'œil côte à côte.
   -------------------------------------------------------------------------- */

html body .before-shop-loop {
    flex-wrap: nowrap;
    align-items: stretch;
}

html body .before-shop-loop .filter-button {
    flex: 0 0 auto;
}

html body .before-shop-loop .sorting-products {
    flex: 1 1 auto;
    min-width: 0;
    overflow: hidden;
}

html body .before-shop-loop .sorting-products select,
html body .before-shop-loop .sorting-products .orderby {
    max-width: 100%;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* ==========================================================================
   Les moyens de paiement
   ==========================================================================

   ⚠️ Relevé au paiement : UN SEUL moyen est actif — « Direct bank transfer »,
   sur 134 px de haut. Ni Visa, ni Mastercard, ni Paystack : ils ne sont pas
   installés, et aucune règle de style ne peut les faire apparaître.

   Ce qui suit habille donc la LISTE, quel que soit ce qu'elle contiendra
   demain. Le jour où Paystack est branché, il prend sa place dans le même
   dessin, sans une ligne de plus.
   ========================================================================== */

html body ul.wc_payment_methods {
    display: grid;
    gap: 0.6rem;
    margin: 0 0 1rem;
    padding: 0;
    list-style: none;
}

html body ul.wc_payment_methods > li {
    margin: 0;
    padding: 0;
    border: 1px solid var(--tz-trait-doux, #f3e3d5);
    border-radius: 14px;
    background: #fff;
    overflow: hidden;
}

html body ul.wc_payment_methods > li:has(input:checked) {
    border-color: var(--tz-orange, #ff7c25);
    box-shadow: 0 0 0 1px var(--tz-orange, #ff7c25);
}

html body ul.wc_payment_methods > li > label {
    display: flex;
    align-items: center;
    gap: 0.7rem;
    /* 56 px : la ligne entière est la cible, pas le seul bouton radio de
       18 px qu'il fallait viser jusqu'ici. */
    min-height: 56px;
    margin: 0;
    padding: 0.6rem 0.9rem;
    font-size: 0.98rem;
    font-weight: 600;
    color: var(--tz-encre, #1c1917);
    cursor: pointer;
}

html body ul.wc_payment_methods > li > input[type="radio"] {
    margin: 0 0 0 0.9rem;
    width: 20px;
    height: 20px;
    accent-color: var(--tz-orange, #ff7c25);
}

/* Les logos que les passerelles fournissent : alignés, jamais étirés. */
html body ul.wc_payment_methods > li > label img {
    max-height: 24px;
    width: auto;
    margin-left: auto;
}

/* Le pavé d'explication d'un moyen de paiement — un virement demande un RIB,
   et ce bloc en portait 134 px sans respiration. */
html body ul.wc_payment_methods .payment_box {
    margin: 0;
    padding: 0.85rem 0.9rem;
    border-top: 1px solid var(--tz-trait-doux, #f3e3d5);
    border-radius: 0;
    background: #fffaf5;
    font-size: 0.88rem;
    line-height: 1.5;
    color: var(--tz-encre-douce, #57534e);
}

html body ul.wc_payment_methods .payment_box::before {
    display: none;
}

/* ==========================================================================
   La fiche produit : trop de texte d'un bloc
   ==========================================================================
   Signalé deux fois. La description tombe d'un seul tenant, sur quinze lignes
   et plus, sans que rien ne dise où elle s'arrête. On la borne, avec un
   dépliage — le texte reste entier, il cesse seulement d'occuper l'écran
   avant qu'on ait choisi de le lire.
   ========================================================================== */

html body .woocommerce-Tabs-panel--description,
html body #tab-description {
    position: relative;
    max-height: 16.5em;
    overflow: hidden;
}

html body .woocommerce-Tabs-panel--description.tz-deplie,
html body #tab-description.tz-deplie {
    max-height: none;
}

/* Le voile qui annonce qu'il y a une suite : sans lui, un texte coupé net se
   lit comme un texte tronqué par erreur. */
html body .woocommerce-Tabs-panel--description:not(.tz-deplie)::after,
html body #tab-description:not(.tz-deplie)::after {
    content: "";
    position: absolute;
    left: 0;
    right: 0;
    bottom: 0;
    height: 4.5em;
    background: linear-gradient(to bottom, rgba(255, 244, 234, 0), #fff4ea 88%);
    pointer-events: none;
}

html body .tz-lire-plus {
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
    min-height: 44px;
    margin-top: 0.5rem;
    padding: 0 1rem;
    border: 1px solid var(--tz-orange, #ff7c25);
    border-radius: 999px;
    background: transparent;
    color: var(--tz-orange, #ff7c25);
    font-size: 0.9rem;
    font-weight: 700;
    cursor: pointer;
}

/* ==========================================================================
   Le texte posé SUR l'image du produit
   ==========================================================================
   « 4 people favorite this product » s'écrivait par-dessus la photo, en noir
   sur un flacon sombre. Un compteur d'envies n'a pas à couvrir ce qu'on
   regarde : il descend sous l'image, en mention.
   ========================================================================== */

html body .product-wrapper [class*="favorite"],
html body .product-wrapper [class*="wishlist-count"],
html body .thumbnail-wrapper [class*="favorite"] {
    position: static !important;
    display: block;
    margin: 0.35rem 0 0;
    padding: 0;
    background: transparent !important;
    color: var(--tz-encre-douce, #57534e) !important;
    font-size: 0.78rem !important;
    font-weight: 500 !important;
    line-height: 1.35;
    text-align: left;
    text-shadow: none;
}

/* ==========================================================================
   LE CONTRASTE DES BOUTONS — le défaut le plus grave de la journée
   ==========================================================================

   Signalé : « bouton continuer shopping complètement illisible, non visible ».
   Mesuré, en reproduisant les deux boutons hors commande :

     Continue shopping   blanc sur crème   1,08:1
     Track my order      blanc sur orange  2,57:1

   Le premier est invisible — le client a raison au sens littéral. Mais la
   mesure a montré plus que ce qu'il signalait : le bouton PRINCIPAL est lui
   aussi sous le seuil. Du blanc sur `#ff7c25` ne fait jamais mieux que 2,57,
   et il en faut 4,5. Tous les boutons du site sont concernés — « Add to
   cart », « Place order », « Proceed to checkout ».

   ---------------------------------------------------------------------------
   La correction, et ce qu'elle préserve
   ---------------------------------------------------------------------------
   L'orange de la charte ne bouge PAS. Il reste celui des grandes surfaces —
   bande, bannière, repères — où il ne porte pas de texte blanc.

   Les BOUTONS reçoivent une version plus profonde du même ton. C'est le même
   orange, poussé jusqu'à ce que le blanc devienne lisible : la marque est
   intacte, et le texte se lit. Un accent qu'on ne peut pas lire n'est pas un
   accent, c'est une tache.
   ========================================================================== */

:root {
    /* Mesuré : blanc sur #c44e08 → 4,6:1. Au-dessus des 4,5 exigés, et le
       plus clair qui y parvienne — donc le plus proche de la charte. */
    --tz-orange-bouton: #c44e08;
    --tz-orange-bouton-actif: #a94106;
}

html body a.tz-promo-bouton,
html body .tz-apres-commande .tz-bouton-principal,
html body div.products a.add_to_cart_button,
html body ul.products a.add_to_cart_button,
html body div.products a.button.product_type_simple,
html body ul.products a.button.product_type_simple,
html body a.add_to_cart_button,
html body a.product_type_simple,
html body .cart_totals .checkout-button,
html body .wc-proceed-to-checkout a.button,
html body #place_order,
html body .tz-barre-paiement button,
html body a.tz-liste-bouton,
html body .tz-liste-recherche button:not(.unset),
html body .dokan-btn-theme,
html body article.single-product form.cart button.single_add_to_cart_button {
    background-color: var(--tz-orange-bouton) !important;
    background-image: linear-gradient(var(--tz-orange-bouton), var(--tz-orange-bouton)) !important;
    border-color: var(--tz-orange-bouton) !important;
    color: #fff !important;
}

html body a.tz-promo-bouton:hover,
html body div.products a.add_to_cart_button:hover,
html body .cart_totals .checkout-button:hover,
html body #place_order:hover {
    background-color: var(--tz-orange-bouton-actif) !important;
    background-image: linear-gradient(var(--tz-orange-bouton-actif), var(--tz-orange-bouton-actif)) !important;
    border-color: var(--tz-orange-bouton-actif) !important;
}

/* Le bouton secondaire : de l'encre sur du clair, bordé d'orange. Il était
   blanc sur crème — une commande qu'on ne pouvait pas voir. */
html body .tz-apres-commande .tz-bouton-second {
    background: #fff !important;
    color: var(--tz-orange-bouton) !important;
    border: 1px solid var(--tz-orange-bouton) !important;
    font-weight: 700;
}

/* ==========================================================================
   La page de commande reçue : le total caché, les blocs disparates
   ==========================================================================

   « Tout le bloc total non visible avec moyen de paiement trop gros » — le
   récapitulatif se termine sous la barre d'onglets, et « PAYMENT METHOD »
   passe sur deux lignes en poussant sa valeur hors de vue.

   « Ce n'est pas uniforme du tout » — trois blocs se suivent avec trois
   traitements : un tableau bordé, une liste à puces, un second tableau. Ils
   reçoivent le même cadre.
   ========================================================================== */

/* La barre d'onglets fait 74 px : sans cette réserve, la dernière ligne de
   chaque page finit dessous. Le total d'une commande est la pire chose à
   cacher. */
html body.woocommerce-order-received .site-content,
html body.woocommerce-checkout .site-content,
html body.woocommerce-cart .site-content {
    padding-bottom: 96px;
}

html body .woocommerce-order .woocommerce-order-overview,
html body .woocommerce-order .woocommerce-bacs-bank-details,
html body .woocommerce-order .woocommerce-order-details,
html body .woocommerce-order .woocommerce-customer-details {
    margin: 0 0 1rem;
    padding: 1rem;
    border: 1px solid var(--tz-trait-doux, #f3e3d5);
    border-radius: 14px;
    background: #fff;
}

/* Les libellés en majuscules coupaient sur deux lignes et repoussaient leur
   valeur. Ils passent en casse normale, sur une seule ligne. */
html body .woocommerce-order th,
html body .woocommerce-order .woocommerce-order-overview li,
html body table.shop_table.order_details tfoot th {
    text-transform: none !important;
    letter-spacing: 0 !important;
    white-space: normal;
}

html body .woocommerce-bacs-bank-details h2,
html body .woocommerce-order-details h2,
html body .woocommerce-customer-details h2,
html body .woocommerce-column__title {
    margin: 0 0 0.7rem;
    font-size: 1.05rem;
    font-weight: 800;
}

html body .woocommerce-bacs-bank-details ul,
html body ul.wc-bacs-bank-details {
    display: grid;
    gap: 0.45rem;
    margin: 0;
    padding: 0;
    list-style: none;
}

html body .woocommerce-bacs-bank-details li,
html body ul.wc-bacs-bank-details li {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 1rem;
    margin: 0;
    padding: 0.45rem 0;
    border-bottom: 1px solid var(--tz-trait-doux, #f3e3d5);
    font-size: 0.92rem;
    color: var(--tz-encre-douce, #57534e);
}

html body .woocommerce-bacs-bank-details li strong,
html body ul.wc-bacs-bank-details li strong {
    color: var(--tz-encre, #1c1917);
    font-weight: 700;
    text-align: right;
}

/* Les deux boutons de fin : pleine largeur, l'un sous l'autre, à la même
   hauteur que partout ailleurs. */
html body .tz-apres-commande {
    display: grid;
    gap: 0.6rem;
    margin-top: 1rem;
}

html body .tz-apres-commande .tz-bouton {
    display: flex;
    align-items: center;
    justify-content: center;
    min-height: 52px;
    border-radius: 999px;
    font-size: 1rem;
    font-weight: 700;
    text-decoration: none;
}

/* ==========================================================================
   La mention descendue de la vignette (TZ-50)
   ========================================================================== */

html body .tz-mention-vignette {
    position: static !important;
    display: block;
    margin: 0.3rem 0 0;
    padding: 0;
    background: transparent !important;
    color: var(--tz-encre-douce, #57534e) !important;
    font-size: 0.78rem !important;
    font-weight: 500 !important;
    line-height: 1.35;
    text-align: left;
    text-shadow: none !important;
    inset: auto !important;
    transform: none !important;
}

/* ==========================================================================
   TZ-51 — les offres qui défilent
   ==========================================================================
   Le défilement au doigt est natif : `scroll-snap` fait ce que des
   bibliothèques de carrousel font en quarante kilo-octets.
   ========================================================================== */

html body .tz-promo-carrousel {
    display: block;
    padding: 1.15rem 0 0.9rem;
}

html body .tz-promo-piste {
    display: flex;
    gap: 0;
    overflow-x: auto;
    scroll-snap-type: x mandatory;
    scrollbar-width: none;
    -webkit-overflow-scrolling: touch;
    /* Sans quoi la barre de défilement du navigateur mange 12 px sous la
       dernière ligne de chaque offre. */
    scrollbar-color: transparent transparent;
}

html body .tz-promo-piste::-webkit-scrollbar {
    display: none;
}

html body .tz-promo-diapo {
    flex: 0 0 100%;
    scroll-snap-align: start;
    display: grid;
    gap: 0.5rem;
    padding: 0 1.15rem;
    /* `min-width: 0` : sans lui, un titre long impose sa largeur et la
       diapositive cesse d'occuper exactement un écran — le calage saute. */
    min-width: 0;
}

html body .tz-promo-pastilles {
    display: flex;
    justify-content: center;
    gap: 0.45rem;
    margin-top: 0.9rem;
}

html body .tz-promo-point {
    width: 8px;
    height: 8px;
    padding: 0;
    border: 0;
    border-radius: 999px;
    background: rgba(28, 25, 23, 0.22);
    cursor: pointer;
    transition: width 0.2s ease, background 0.2s ease;
}

html body .tz-promo-point.est-active {
    width: 22px;
    background: var(--tz-orange-bouton, #c44e08);
}

/* La cible tactile fait 8 px de large à l'œil et 32 px au doigt : le point
   reste discret sans devenir impossible à viser. */
html body .tz-promo-point::before {
    content: "";
    position: absolute;
    width: 32px;
    height: 32px;
    margin: -12px;
}

html body .tz-promo-pastilles {
    position: relative;
}

@media (prefers-reduced-motion: reduce) {
    html body .tz-promo-piste {
        scroll-behavior: auto;
    }
    html body .tz-promo-point {
        transition: none;
    }
}

/* ==========================================================================
   Les deux cercles blancs de la galerie
   ==========================================================================

   Signalé : « ces deux cercles blancs ne sont pas esthétiques ». Mesuré : le
   bouton fait bien 40 × 40 avec son fond blanc, mais le SVG qu'il contient
   mesure 0 × 0. Ce ne sont pas des flèches mal dessinées — ce sont des
   flèches ABSENTES, et il ne reste que le cercle.

   J'avais réparé leur PLACEMENT sans jamais vérifier que le contenu se
   voyait : le témoin comptait les barres restées dans le flux, pas les
   chevrons.
   ========================================================================== */

html body .woocommerce-product-gallery ul.flex-direction-nav svg {
    width: 18px !important;
    height: 18px !important;
    /* Le tracé du thème est en `currentColor` : il suit la couleur du bouton,
       il fallait seulement lui donner une taille. */
    stroke: currentColor;
    fill: none;
    flex: 0 0 auto;
}

/* ⚠️ Le lien ET le bouton qu'il contient portaient tous deux le cercle : un
   cercle DANS un cercle, d'où l'impression d'épaisseur. Seul le bouton le
   garde. */
html body .woocommerce-product-gallery ul.flex-direction-nav a {
    background: transparent !important;
    box-shadow: none !important;
    width: auto;
    height: auto;
    padding: 0;
}

html body .woocommerce-product-gallery ul.flex-direction-nav button {
    width: 38px;
    height: 38px;
    border: 0;
    border-radius: 999px;
    background: rgba(255, 255, 255, 0.94);
    box-shadow: 0 2px 10px rgba(28, 25, 23, 0.22);
    color: var(--tz-encre, #1c1917);
}

/* ==========================================================================
   La vignette du panier : de la place perdue
   ==========================================================================
   Signalé : « l'image du produit est toute petite par rapport à la place
   restante ». Mesuré : la cellule fait 88 × 89, l'image 46 × 88 — elle est
   bornée par la HAUTEUR, et sa largeur suit son format. La colonne s'élargit
   donc, et l'image avec elle.
   ========================================================================== */

@media (max-width: 767px) {
    html body table.shop_table_responsive tbody tr.cart_item {
        grid-template-columns: 104px auto minmax(0, 1fr);
    }

    html body table.shop_table_responsive td.product-thumbnail img {
        width: 104px;
        height: 104px;
        object-fit: contain;
    }
}

/* ==========================================================================
   La barre du bas ne doit jamais disparaître
   ==========================================================================

   ⚠️ JE N'AI PAS REPRODUIT le défaut, et je le dis. Mesuré en bas de page :
   `position: fixed`, haut 770, hauteur 74, `visibility: visible`, opacité 1 —
   la barre reste en place.

   Elle est verrouillée par précaution, pas par diagnostic. Si le thème la
   masque par un script au contact du pied de page, ces règles l'en
   empêcheront ; si la cause est ailleurs — hauteur de fenêtre changeante sur
   un vrai téléphone — elles ne feront rien, et il faudra chercher encore.
   ========================================================================== */

html body .klb-mobile-bottom {
    position: fixed !important;
    left: 0;
    right: 0;
    bottom: 0;
    z-index: 9990;
    visibility: visible !important;
    opacity: 1 !important;
    transform: none !important;
}

/* ==========================================================================
   Le sélecteur de quantité : le « 1 » n'était pas entre les deux boutons
   ==========================================================================

   Mesuré sur la fiche produit : conteneur de 360 px, moins à x=1, champ à
   x=33, plus à x=327. Les deux boutons sont posés en ABSOLU aux extrémités,
   et le champ, lui, reste dans le flux — il se colle donc au moins, laissant
   230 px de vide avant le plus.

   Le conteneur n'a pas à faire toute la largeur : un sélecteur de quantité se
   dessine à la taille de ce qu'il contient. Borné à 132 px, les deux boutons
   se rapprochent et le chiffre se retrouve au milieu, sans toucher à leur
   positionnement.
   ========================================================================== */

html body form.cart .quantity,
html body .single-product .quantity {
    position: relative;
    width: 132px;
    max-width: 132px;
    display: inline-flex;
    align-items: center;
}

html body form.cart .quantity input.qty,
html body .single-product .quantity input.qty {
    width: 100%;
    /* La place des deux boutons absolus, laissée libre de part et d'autre. */
    padding: 0 34px;
    text-align: center;
    font-variant-numeric: tabular-nums;
}

/* ==========================================================================
   Le doublon « Add to wishlist »
   ==========================================================================

   Mesuré : DEUX boutons sur la fiche —

     a.klbwl-btn                       y=1248   greffon du thème
     button.tsgr-add-to-wishlist-btn   y=1537   le nôtre (registre de cadeaux)

   Ils ne font pas la même chose. Celui du thème range dans une liste privée ;
   le nôtre alimente le registre de cadeaux, qu'on peut partager et sur lequel
   un tiers peut acheter. C'est celui-là que Tizzleshop a demandé.

   ⚠️ On masque celui du THÈME, pas le nôtre. L'inverse aurait été plus simple
   — il est mieux placé — mais aurait supprimé la fonction au profit de
   l'emplacement.
   ========================================================================== */

html body .single-product .wishlist-button a.klbwl-btn,
html body .single-product div.wishlist-button {
    display: none !important;
}

/* Le nôtre remonte à côté des boutons d'achat, et prend leur allure. */
html body .single-product .tsgr-add-to-wishlist-btn {
    display: inline-flex;
    align-items: center;
    gap: 0.45rem;
    width: 100%;
    min-height: 48px;
    justify-content: center;
    margin: 0.5rem 0 0;
    padding: 0 1rem;
    border: 1px solid var(--tz-orange-bouton, #c44e08);
    border-radius: 999px;
    background: #fff;
    color: var(--tz-orange-bouton, #c44e08);
    font-size: 0.95rem;
    font-weight: 700;
}

/* ==========================================================================
   « X people favorited this product » sort des CARTES
   ==========================================================================

   Demandé : « ce n'est pas bon que ces infos soient sur les produits, les
   retirer et mettre dans la description ». Sur la fiche, la mention garde son
   sens — elle accompagne le bouton de liste d'envies, à l'endroit où l'on
   décide. Sur une carte de catalogue, elle vole la place du nom et du prix.
   ========================================================================== */

html body div.products [class*="favorit"],
html body ul.products [class*="favorit"],
html body .product-wrapper [class*="favorit"],
html body .tz-mention-vignette {
    display: none !important;
}

/* ==========================================================================
   Le point orange décalé du bouton radio
   ==========================================================================
   Ma règle posait `margin-left: 0.9rem` sur l'entrée. Elle n'est pas DANS le
   libellé mais à côté : la marge la décalait au lieu de l'aligner. On la
   place par la grille, comme le reste.
   ========================================================================== */

html body ul.wc_payment_methods > li {
    display: grid;
    grid-template-columns: auto minmax(0, 1fr);
    align-items: center;
}

html body ul.wc_payment_methods > li > input[type="radio"] {
    grid-column: 1;
    margin: 0 0 0 0.9rem;
    width: 20px;
    height: 20px;
    accent-color: var(--tz-orange-bouton, #c44e08);
}

html body ul.wc_payment_methods > li > label {
    grid-column: 2;
    padding-left: 0.6rem;
}

/* Le pavé d'explication passe sous les deux colonnes. */
html body ul.wc_payment_methods .payment_box {
    grid-column: 1 / -1;
}

/* ==========================================================================
   Les champs de modification du compte
   ==========================================================================
   Signalé : « uniformiser les champs ». Les champs de mot de passe portent un
   bouton d'œil gris qui les raccourcit, les autres non — trois hauteurs
   différentes sur un même formulaire.
   ========================================================================== */

html body form.woocommerce-EditAccountForm .woocommerce-form-row {
    margin-bottom: 0.9rem;
}

html body form.woocommerce-EditAccountForm input[type="text"],
html body form.woocommerce-EditAccountForm input[type="email"],
html body form.woocommerce-EditAccountForm input[type="password"],
html body form.woocommerce-EditAccountForm input[type="tel"] {
    width: 100%;
    height: 48px;
    padding: 0 0.9rem;
    border: 1px solid var(--tz-trait-doux, #f3e3d5);
    border-radius: 10px;
    background: #fff;
    /* 16 px : en dessous, Safari iOS zoome à la mise au point. */
    font-size: 16px;
    box-sizing: border-box;
}

/* Le champ de mot de passe et son œil forment un seul bloc, de la même
   hauteur que les autres — l'œil dedans, pas à côté. */
html body form.woocommerce-EditAccountForm .password-input,
html body form.woocommerce-EditAccountForm .woocommerce-password-input {
    position: relative;
    display: block;
    width: 100%;
}

html body form.woocommerce-EditAccountForm .password-input input {
    padding-right: 52px;
}

html body form.woocommerce-EditAccountForm .show-password-input {
    position: absolute;
    top: 50%;
    right: 0.5rem;
    transform: translateY(-50%);
    width: 38px;
    height: 38px;
    display: flex;
    align-items: center;
    justify-content: center;
    border: 0;
    border-radius: 8px;
    background: transparent;
    color: var(--tz-encre-douce, #57534e);
}

/* ==========================================================================
   Le tiroir : des repères de taille égale
   ==========================================================================
   Signalé : « My wishlist, my account non uniforme ». Les pictogrammes de ces
   deux entrées viennent du menu et diffèrent des autres — un camion et un
   canapé au milieu d'icônes de rayons.

   ⚠️ On ne peut pas corriger le CHOIX du pictogramme depuis une feuille de
   style : il est enregistré dans le menu, et c'est à Tizzleshop de le changer
   dans l'éditeur. Ce qu'on peut faire, c'est leur donner la même boîte et la
   même teinte que les autres, pour que la colonne reste alignée.
   ========================================================================== */

html body aside.site-drawer .menu-item > a > i,
html body aside.site-drawer .menu-item > a > img,
html body aside.site-drawer .menu-item > a > svg {
    flex: 0 0 22px;
    width: 22px;
    height: 22px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-size: 18px;
    color: var(--tz-encre-douce, #57534e);
}

/* ==========================================================================
   La bannière de consentement aux notifications
   ==========================================================================
   Elle se pose au-dessus de la barre d'onglets, jamais dessous : une demande
   qu'on ne voit pas ne se refuse ni ne s'accepte — elle se subit.
   ========================================================================== */

html body .tz-push-invite {
    position: fixed;
    left: 0.75rem;
    right: 0.75rem;
    bottom: calc(74px + 0.75rem);
    z-index: 9995;
    display: grid;
    gap: 0.75rem;
    padding: 1rem;
    border: 1px solid var(--tz-trait-doux, #f3e3d5);
    border-radius: 16px;
    background: #fff;
    box-shadow: 0 10px 32px rgba(28, 25, 23, 0.2);
}

html body .tz-push-invite[hidden] {
    display: none;
}

html body .tz-push-texte {
    display: grid;
    gap: 0.2rem;
    margin: 0;
}

html body .tz-push-texte strong {
    font-size: 0.98rem;
    font-weight: 700;
    color: var(--tz-encre, #1c1917);
}

html body .tz-push-texte span {
    font-size: 0.87rem;
    line-height: 1.4;
    color: var(--tz-encre-douce, #57534e);
}

html body .tz-push-actions {
    display: flex;
    gap: 0.5rem;
    justify-content: flex-end;
}

html body .tz-push-invite button {
    min-height: 44px;
    padding: 0 1.1rem;
    border-radius: 999px;
    font-size: 0.9rem;
    font-weight: 700;
    cursor: pointer;
}

/* Le refus est aussi lisible que l'accord : un « non » qu'on doit chercher
   est un « oui » arraché. */
html body .tz-push-non {
    border: 1px solid var(--tz-trait-doux, #f3e3d5);
    background: #fff;
    color: var(--tz-encre-douce, #57534e);
}

html body .tz-push-oui {
    border: 1px solid var(--tz-orange-bouton, #c44e08);
    background: var(--tz-orange-bouton, #c44e08);
    color: #fff;
}

/* ==========================================================================
   « Prévenez-moi quand c'est revenu »
   ==========================================================================
   Sur un produit épuisé, c'est la seule action possible. Elle prend donc la
   place et l'allure d'un bouton d'achat — sans en prendre la couleur pleine,
   qui promettrait un achat immédiat.
   ========================================================================== */

html body .tz-stock-bouton {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 0.45rem;
    width: 100%;
    min-height: 52px;
    margin: 0.6rem 0 0;
    padding: 0 1.1rem;
    border: 1px solid var(--tz-orange-bouton, #c44e08);
    border-radius: 999px;
    background: #fff;
    color: var(--tz-orange-bouton, #c44e08);
    font-size: 0.98rem;
    font-weight: 700;
    cursor: pointer;
}

html body .tz-stock-bouton::before {
    content: "";
    width: 16px;
    height: 16px;
    flex: 0 0 auto;
    border: 2px solid currentColor;
    border-radius: 50% 50% 0 0 / 60% 60% 0 0;
    border-bottom: 0;
}

/* Une fois inscrit : plus de bordure d'appel, plus de curseur de main. La
   demande est prise, et rien ne doit inviter à la reprendre. */
html body .tz-stock-bouton.est-inscrit,
html body .tz-stock-bouton[disabled] {
    border-color: var(--tz-trait-doux, #f3e3d5);
    background: #fffaf5;
    color: var(--tz-encre-douce, #57534e);
    cursor: default;
}

html body .tz-stock-invite {
    margin: 0.6rem 0 0;
    font-size: 0.92rem;
}

html body .tz-stock-invite a {
    color: var(--tz-orange-bouton, #c44e08);
    font-weight: 700;
    text-underline-offset: 3px;
}


/* =========================================================================
   UNIFORMITÉ — deux styles de bouton, et deux seulement
   =========================================================================

   La campagne d'uniformité a relevé TROIS styles pour la même intention :

     · orange plein `#c44e08` sur la boutique ;
     · orange en contour sur l'écran des adresses ;
     · gris `#e6e8eb` sur « Save address », « Return to shop », « Clear All »,
       et — le pire — sur notre propre bouton « Turn on » des notifications.

   Le gris ne veut rien dire. Il ne dit ni « c'est l'action principale » ni
   « c'est l'action secondaire » : il dit seulement que personne n'a choisi.
   Sur « Save address », l'action la plus importante de l'écran était la plus
   discrète.

   On retient donc DEUX styles, et l'on s'y tient :

     · PRINCIPAL — orange plein, texte blanc. Une seule fois par écran ;
     · SECONDAIRE — fond papier, contour orange. Autant de fois qu'il faut.

   ⚠️ La spécificité, encore. Le gris vient d'une règle du thème qui compte
   deux classes ; `html body` plus l'élément plus deux classes passe devant.
   `!important` là où le thème en pose lui-même — se battre à la spécificité
   contre un `!important` ne marche pas, et j'ai déjà perdu ce combat.
   ========================================================================= */

html body a.button.wc-backward,
html body button.button.tz-push-oui,
html body .tz-push-actions button.tz-push-oui,
/* ⚠️ « Save address » est resté gris au premier passage : je visais
 * `form.woocommerce-address-fields`, et le formulaire ne porte pas cette
 * classe — son bouton n'a même pas de parent classé. Je visais une structure
 * supposée, pour la quatrième fois.
 *
 * On vise donc le CONTENEUR du compte, qui lui existe bel et bien, et l'on
 * couvre d'un coup les enregistrements d'adresse et de profil. */
html body .woocommerce-MyAccount-content button.button,
html body .woocommerce-MyAccount-content input.button[type="submit"],
html body form.woocommerce-address-fields button.button,
html body form.edit-account button.button,
html body .woocommerce-EditAccountForm button.button {
    background-color: var(--tz-orange-bouton, #c44e08) !important;
    background-image: none !important;
    border: 1px solid var(--tz-orange-bouton, #c44e08) !important;
    color: #fff !important;
    font-weight: 600 !important;
    border-radius: 999px !important;
    min-height: 44px !important;
    padding: 0.7rem 1.4rem !important;
}

html body button.button.empty-cart-button,
html body .cart .actions button.button.remove-all,
html body button.tz-push-non,
html body .tz-push-actions button.tz-push-non {
    background-color: transparent !important;
    background-image: none !important;
    border: 1px solid var(--tz-orange-bouton, #c44e08) !important;
    color: var(--tz-orange-bouton, #c44e08) !important;
    font-weight: 600 !important;
    border-radius: 999px !important;
    min-height: 44px !important;
    padding: 0.7rem 1.4rem !important;
}

/* -------------------------------------------------------------------------
   « Place order » — l'orange clair était resté
   -------------------------------------------------------------------------
   Mesuré `rgb(255, 124, 37)` : du blanc dessus ne fait que 2,57:1, quand il en
   faut 4,5. Ce bouton-là avait échappé au passage sur le contraste — et c'est
   celui qui prend l'argent.
   ------------------------------------------------------------------------- */

html body #place_order.button.alt,
html body .form-row.place-order button.button.alt,
html body .tz-paiement-barre button.tz-paiement-valider {
    background-color: var(--tz-orange-bouton, #c44e08) !important;
    background-image: none !important;
    border-color: var(--tz-orange-bouton, #c44e08) !important;
    color: #fff !important;
}

/* -------------------------------------------------------------------------
   Deux boutons « Place order » sur le même écran
   -------------------------------------------------------------------------
   Le nôtre, dans la barre collée en bas, ET celui de WooCommerce plus haut
   dans le formulaire. Les deux visibles, les deux actifs. Le visiteur ne sait
   pas lequel fait foi ; et celui qui appuie sur le premier trouvé peut penser
   avoir commandé deux fois.

   C'est notre barre qui a créé le doublon : elle a été ajoutée sans masquer
   l'original.

   ⚠️ On ne masque le bouton d'origine QUE si notre barre est réellement à
   l'écran. `:has()` le vérifie. Le masquer sans condition serait catastrophique
   le jour où notre barre ne s'affiche pas : plus aucun moyen de commander.
   Notre bouton, lui, continue de cliquer l'original — un bouton masqué reste
   cliquable par programme.

   ⚠️⚠️ ET C'EST EXACTEMENT CE QUI EST ARRIVÉ, PAR UN AUTRE CHEMIN.

   Cette règle masquait `.form-row.place-order` — la LIGNE entière. Or cette
   ligne ne contient pas que le bouton : elle contient aussi
   `.woocommerce-terms-and-conditions-wrapper`, c'est-à-dire **la case
   « j'accepte les conditions »**.

   Mesuré sur la démonstration :

       input#terms                                  → 0 × 0
       div.woocommerce-terms-and-conditions-wrapper → 0 × 0
       div.form-row.place-order                     → display: none  ← ici
       div#payment                                  → 326 px, bien rendu

   Personne ne pouvait donc cocher. Et comme le serveur, lui, exige toujours
   cette case, TOUTE commande était refusée par « Please read and accept the
   terms and conditions » — un message désignant une case que nous avions
   nous-mêmes rendue invisible. Blocage total du paiement, et le plus sournois
   qui soit : chaque pièce prise séparément a l'air de fonctionner.

   On ne masque donc plus que le BOUTON, jamais la ligne qui le porte. Écrire
   « je masque le doublon » et masquer son conteneur, ce n'est pas la même
   chose — un conteneur héberge ce que d'autres y ont mis.
   ------------------------------------------------------------------------- */

html body:has(.tz-paiement-barre:not([hidden])) .form-row.place-order #place_order,
html body:has(.tz-paiement-barre:not([hidden])) .form-row.place-order > button.button.alt {
    display: none !important;
}

/* La case des conditions, elle, doit rester visible et atteignable — c'est le
   seul endroit où le client peut accepter. */
html body .form-row.place-order .woocommerce-terms-and-conditions-wrapper {
    display: block !important;
}

/* -------------------------------------------------------------------------
   Le pied de page était d'une autre couleur que la page
   -------------------------------------------------------------------------
   Le corps est en papier chaud `#fff4ea` ; le pied virait au gris bleuté, puis
   au blanc franc sur la bande de copyright. Trois fonds sur un même écran,
   qu'aucune intention ne sépare — juste des blocs venus de trois endroits.
   ------------------------------------------------------------------------- */

html body footer.site-footer,
html body footer.site-footer > *,
html body footer.site-footer .elementor-section,
html body footer.site-footer .elementor-container,
html body footer.site-footer .footer-bottom,
html body footer.site-footer .footer-main {
    background-color: transparent !important;
    background-image: none !important;
}

html body footer.site-footer {
    background-color: var(--tz-papier, #fff4ea) !important;
}

/* =========================================================================
   L'EN-TÊTE DU COMPTE — un seul traitement, pas deux
   =========================================================================

   Mesuré : `div.tz-compte-bandeau-tableau` est orange `rgb(255,124,37)`,
   `div.tz-compte-bandeau-souspage` est papier `rgb(255,244,236)`. Même
   composant, même information (avatar, nom, déconnexion), deux apparences —
   selon qu'on est sur le tableau de bord ou sur une sous-page.

   Et le bandeau orange se pose JUSTE SOUS la barre orange du site : orange sur
   orange, la chose expressément écartée pour la page d'accueil. Le même défaut
   s'était réinstallé ici, où personne ne l'avait cherché.

   On retient le traitement papier — celui des sous-pages : il laisse la barre
   orange être le seul aplat de la zone, et le nom du client se lit en encre
   foncée plutôt qu'en blanc sur un fond clair.
   ========================================================================= */

html body .tz-compte-bandeau,
html body .tz-compte-bandeau.tz-compte-bandeau-tableau,
html body .tz-compte-bandeau.tz-compte-bandeau-souspage {
    background-color: var(--tz-papier, #fff4ea) !important;
    background-image: none !important;
    color: var(--tz-encre, #1b1f22) !important;
    border-radius: 0 !important;
    padding: 0.9rem 1rem !important;
}

html body .tz-compte-bandeau.tz-compte-bandeau-tableau * ,
html body .tz-compte-bandeau.tz-compte-bandeau-souspage * {
    color: inherit !important;
}

/* L'action de sortie garde sa couleur d'action, sur les deux écrans. */
html body .tz-compte-bandeau a[href*="customer-logout"],
html body .tz-compte-bandeau .tz-deconnexion {
    color: var(--tz-orange-bouton, #c44e08) !important;
    text-decoration: underline !important;
    text-underline-offset: 3px;
}

/* -------------------------------------------------------------------------
   « Welcome to Tizzleshop » — le même orange sur orange, à la connexion
   ------------------------------------------------------------------------- */

html body .tz-accueil-bandeau {
    background-color: transparent !important;
    background-image: none !important;
    color: var(--tz-encre, #1b1f22) !important;
    padding: 1rem 1rem 0.25rem !important;
}

html body .tz-accueil-bandeau * {
    color: inherit !important;
}

/* -------------------------------------------------------------------------
   Le bouton « Log in » était resté à l'orange clair
   -------------------------------------------------------------------------
   Mesuré `rgb(255, 124, 37)` : du blanc dessus ne fait que 2,57:1. Le passage
   sur le contraste avait couvert la boutique et le paiement, pas la porte
   d'entrée — l'écran que TOUT LE MONDE voit en premier.
   ------------------------------------------------------------------------- */

/* ⚠️ TROIS CLASSES, PAS UNE.
 *
 * Ma première règle visait `button.woocommerce-form-login__submit` — une
 * classe — et elle a perdu : le thème porte `!important` lui aussi, et sa
 * feuille est chargée APRÈS la nôtre. À `!important` égal et spécificité
 * égale, c'est l'ordre qui tranche, et l'ordre ne nous appartient pas.
 *
 * On énumère donc les trois classes que le bouton porte réellement
 * (`woocommerce-button button woocommerce-form-login__submit`), relevées sur
 * la page plutôt que devinées. Cinquième fois que la spécificité décide à ma
 * place sur ce projet. */
html body button.woocommerce-button.button.woocommerce-form-login__submit,
html body button.woocommerce-button.button.woocommerce-form-register__submit,
html body form.woocommerce-form-login button.woocommerce-button.button,
html body form.woocommerce-form-register button.woocommerce-button.button,
html body button.woocommerce-form-login__submit,
html body .woocommerce-form-login button.button,
html body .woocommerce-form-register button.button,
html body button.woocommerce-form-register__submit {
    background-color: var(--tz-orange-bouton, #c44e08) !important;
    background-image: none !important;
    border-color: var(--tz-orange-bouton, #c44e08) !important;
    color: #fff !important;
}

/* =========================================================================
   LA POPUP « INSTALL TIZZLESHOP » NE RECOUVRE PLUS UN FORMULAIRE
   =========================================================================

   Mesurée : modale, 844 px de haut, elle intercepte le clic sur « Log in » et
   ne se retire pas d'elle-même — relevée présente à chaque instant pendant
   soixante secondes. Elle vient d'une extension tierce
   (`custom-pwa-plugin`), pas de nous.

   On ne la supprime pas : proposer l'installation est légitime, et c'est un
   choix du client. On l'empêche seulement de s'ouvrir là où elle empêche
   d'agir — connexion, panier, paiement, compte. Elle reste sur les pages de
   lecture, où interrompre ne coûte rien.

   ⚠️ Elle n'était jamais apparue à nos campagnes : le Chromium de Playwright
   ne gère pas l'évènement d'installation. Un vrai Chrome la montre.
   ========================================================================= */

html body.woocommerce-account #custom-pwa-install-popup,
html body.woocommerce-cart #custom-pwa-install-popup,
html body.woocommerce-checkout #custom-pwa-install-popup,
html body.woocommerce-account .custom-pwa-popup,
html body.woocommerce-cart .custom-pwa-popup,
html body.woocommerce-checkout .custom-pwa-popup {
    display: none !important;
}

/* =========================================================================
   LA BANNIÈRE DE NOTIFICATION NE RECOUVRE PLUS LE TOTAL
   =========================================================================

   Mesurée : `position: fixed; bottom: 86px; z-index: 9995`, 136 px de haut.
   Elle flotte au-dessus du contenu — et sur le panier, elle masquait le total
   et le bouton de commande, c'est-à-dire précisément ce qu'on regarde à ce
   moment-là.

   Une bannière fixe doit RÉSERVER sa place, pas se poser dessus. La classe est
   ajoutée par TZ-53 au moment où la bannière se montre : sans elle, on
   réserverait la place d'une bannière absente sur toutes les pages.
   ========================================================================= */

html body.tz-push-invite-visible {
    padding-bottom: 240px !important;
}

/* =========================================================================
   LES BOUTONS DU REGISTRE DE CADEAUX
   =========================================================================

   Mesuré sur « + Create New » : rgb(255, 153, 0) — un ambre qui
   n'appartient à aucune de nos deux familles. Le registre est une extension
   tierce : elle habille ses boutons avec sa propre palette, et l ecran des
   listes d envies detonne des qu on y arrive depuis le compte.

   On les ramene aux DEUX styles retenus pour tout le site : orange plein pour
   l action principale, contour orange pour le reste. Aucune regle nouvelle,
   les memes valeurs qu ailleurs.

   ⚠️ Le mot-clé !important est nécessaire : le registre pose ses couleurs en
   dur sur ses classes, et la leçon a été payée six fois sur ce projet.

   ⚠️ Ce bloc a été ajouté par un heredoc via le shell, et les accents graves
   de ce commentaire ont été interprétés — deux fragments avaient disparu. Ma
   propre règle dit d'écrire les fichiers avec l'outil d'édition, jamais par
   heredoc. Relire ce qu'on vient d'écrire a rattrapé la faute ; ne pas relire
   l'aurait laissée passer, dans un commentaire que personne ne vérifie.
   ========================================================================= */

/* ⚠️ TROIS JETONS DE NIVEAU CLASSE, PAS DEUX.
 *
 * Première tentative : `html body .tsgr-btn.tsgr-btn-yellow` — deux classes,
 * comme la règle du registre. À égalité de classes ET de `!important`, c'est
 * l'ORDRE DE CHARGEMENT qui tranche, et la feuille du registre passe après la
 * nôtre. Le rayon et la hauteur avaient pris ; le fond, non — le signe qu'on
 * était à égalité et qu'on perdait au départage.
 *
 * Le sélecteur d'attribut `[type="button"]` compte comme une classe. Trois
 * contre deux : on passe devant quel que soit l'ordre. Septième fois que la
 * spécificité décide à ma place sur ce projet. */
html body button.tsgr-btn.tsgr-btn-yellow[type="button"],
html body button.tsgr-btn-yellow[type="button"],
html body button.tsgr-btn-yellow,
html body .tsgr-btn.tsgr-btn-yellow,
html body button.tsgr-btn-primary,
html body .tsgr-sheet button.tsgr-btn-yellow {
    background-color: var(--tz-orange-bouton, #c44e08) !important;
    background-image: none !important;
    border: 1px solid var(--tz-orange-bouton, #c44e08) !important;
    color: #fff !important;
    font-weight: 600 !important;
    border-radius: 999px !important;
    min-height: 44px !important;
}

html body button.tsgr-btn-secondary:not(.tz-coeur-grille) {
    background-color: transparent !important;
    background-image: none !important;
    border: 1px solid var(--tz-orange-bouton, #c44e08) !important;
    color: var(--tz-orange-bouton, #c44e08) !important;
    font-weight: 600 !important;
    border-radius: 999px !important;
    min-height: 44px !important;
}
