/* ==========================================================================
   COMPOSANTS PARTAGÉS — port des sections 3.1 à 3.4 et 8 du design V4, et
   des primitives des pages boutique (sections 20 à 23 du design).
   Chargée sur toutes les pages que le thème rend en entier (inc/assets.php) :
   accueil, boutique et fiche produit, puis compte, panier, commande.

   Sections 0 à 5 : ce que l'accueil et la boutique partagent (jetons
   locaux, section et en-tête de section, variantes de boutons, carte,
   pilule, carte produit et grille, menu déroulant). Sections 6 à 11 : les
   primitives du design pour les pages WooCommerce (fil d'Ariane, stock,
   nombre, case et interrupteur, quantité, notices). Section 12 : points de
   rupture des règles partagées.

   Mêmes règles que header.css : aucune couleur, ombre, rayon, police ni
   espacement en dur ; jetons :root de style.css, jetons locaux --cp-*
   ci-dessous pour les dimensions que le design écrit en dur (comme --hd-*
   pour l'en-tête, --ft-* pour le pied, --ac-* pour l'accueil, --fi-* pour
   la fiche).
   ========================================================================== */

/* --------------------------------------------------------------------------
   0. JETONS LOCAUX DES COMPOSANTS
   -------------------------------------------------------------------------- */
:root {
    --cp-btn-ghost-h:    36px;   /* bouton fantôme « View all »            */
    --cp-btn-icon:       40px;   /* bouton rond « Show next products »     */
    --cp-pill-h:         22px;   /* pilule de qualité ou d'étiquette        */
    --cp-lift:            2px;   /* soulèvement d'une carte au survol       */
    --cp-line:            1px;   /* bordures                                */
    --cp-line-thick:      2px;   /* marge fine, trait de la coche           */

    /* Hero */
    --cp-select-h:       48px;   /* champ du sélecteur                      */
    --cp-menu-max-h:    264px;   /* hauteur maximale du menu déroulant      */
    --z-dd:               20;    /* menu déroulant au-dessus du sélecteur   */

    /* Cartes produit (maquette du 20 septembre) */
    --cp-badge-out:      11px;   /* débord du badge de stock sur l'image    */
    --cp-qty-h-sm:       36px;   /* compteur de quantité de la carte        */
    --cp-qty-btn-sm:     32px;   /* ses boutons − et +                      */
    --cp-btn-h-sm:       36px;   /* bouton d'ajout, ou de connexion         */
    --cp-loading-opacity: .6;    /* bouton d'ajout pendant la requête AJAX  */
    --z-badge:             2;    /* badge de stock au-dessus de l'image     */

    /* Primitives des pages boutique */
    --cp-check-row-h:   36px;   /* ligne d'une case à cocher des filtres      */
    --cp-check-box:     18px;   /* la case dessinée                            */
    --cp-check-line:   1.5px;   /* sa bordure                                  */
    --cp-switch-w:      36px;   /* piste de l'interrupteur                     */
    --cp-switch-h:      20px;
    --cp-switch-knob:   16px;
    --cp-switch-pad:     2px;
    --cp-switch-row-h:  44px;   /* ligne de l'interrupteur (zone tactile)      */
    --cp-qty-h:         40px;   /* compteur de quantité                        */
    --cp-qty-btn:       36px;   /* ses boutons − et +                          */
    --cp-qty-input:     48px;   /* son champ                                   */
    --cp-notice-gap:    12px;
    --cp-field-h:       48px;   /* champ de formulaire                         */
    --cp-focus-ring:     3px;   /* halo de focus des champs                    */
    --cp-peek:          36px;   /* œil « afficher le mot de passe »            */
    --cp-peek-right:     6px;   /* sa distance au bord du champ                */
    --cp-peek-icon:     16px;   /* son tracé                                   */
    --cp-field-peek-pad: 48px;  /* place laissée à l'œil dans le champ         */
    --cp-meter-h:        3px;   /* jauge de force du mot de passe              */
    --cp-meter-gap:      4px;   /* espace entre ses segments                   */
    --cp-meter-top:      2px;   /* sa distance au champ                        */
    --cp-notice-nudge:   1px;   /* icône de la note, alignée sur la 1re ligne  */
    --cp-copy-h:        28px;   /* bouton « Copy » (SKU, numéro de commande)   */
    --cp-stock-count-gap:  4px; /* badge de stock : avant le nombre de pièces  */
    --cp-stock-count-opacity: .85;   /* … et sa transparence                  */
}

/* --------------------------------------------------------------------------
   1. SECTION ET EN-TÊTE DE SECTION (design 3.4)
   -------------------------------------------------------------------------- */

/* --section-y vaut 56 px, et 40 px sous 1100 px : le point de rupture
   du design est déjà porté par le jeton. */
.section {
    padding: var(--section-y) 0;
}

.section--bench {
    background: var(--bench);
}

.section-head {
    display: flex;
    align-items: flex-end;
    justify-content: space-between;
    gap: var(--sp-16);
    flex-wrap: wrap;
    margin-bottom: var(--sp-24);
}

.section-head h2 {
    font-size: var(--fs-24);
    font-weight: var(--fw-medium);
    letter-spacing: var(--ls-h2);
}

.section-head p {
    margin-top: var(--sp-4);
    font-size: var(--fs-14);
    color: var(--grey);
}

.section-head__actions {
    display: flex;
    align-items: center;
    gap: var(--sp-8);
}
/* --------------------------------------------------------------------------
   2. VARIANTES DE BOUTONS (design 3.1) — la base .btn est dans header.css
   -------------------------------------------------------------------------- */
.btn--pill {
    border-radius: var(--pill);
}

.btn--ghost {
    height: var(--cp-btn-ghost-h);
    padding: 0 var(--sp-14);
    border: var(--cp-line) solid var(--line-strong);
    border-radius: var(--pill);
    background: var(--paper);
    font-size: var(--fs-13);
    color: var(--ink);
}

.btn--ghost:hover {
    border-color: var(--slate);
    color: var(--ink);
}

.btn--icon {
    width: var(--cp-btn-icon);
    height: var(--cp-btn-icon);
    padding: 0;
    border-radius: var(--pill);
}
/* --------------------------------------------------------------------------
   3. CARTE, la surface de base du système (design 3.2)
   -------------------------------------------------------------------------- */
.card {
    background: var(--paper);
    border: var(--cp-line) solid var(--line);
    border-radius: var(--radius);
    box-shadow: var(--shadow);
    transition: transform var(--ease), box-shadow var(--ease);
}

.card--hover:hover {
    transform: translateY(calc(-1 * var(--cp-lift)));
    box-shadow: var(--shadow-lift);
}

/* Retour tactile à la pression. */
.card--hover:active {
    transform: scale(.98);
    box-shadow: var(--shadow);
}
/* --------------------------------------------------------------------------
   4. PILULE PASTEL : grades de qualité, étiquettes d'article (design 3.3)
   -------------------------------------------------------------------------- */
.pill {
    display: inline-flex;
    align-items: center;
    align-self: flex-start;
    height: var(--cp-pill-h);
    padding: 0 var(--sp-8);
    border-radius: var(--pill);
    font-size: var(--fs-11);
    font-weight: var(--fw-medium);
    letter-spacing: var(--ls-pill);
    white-space: nowrap;
}

.pill--slate  { background: var(--pastel-slate-bg);  color: var(--pastel-slate-ink); }
.pill--green  { background: var(--pastel-green-bg);  color: var(--pastel-green-ink); }
.pill--orange { background: var(--pastel-orange-bg); color: var(--pastel-orange-ink); }
.pill--amber  { background: var(--pastel-amber-bg);  color: var(--pastel-amber-ink); }
.pill--grey   { background: var(--pastel-grey-bg);   color: var(--pastel-grey-ink); }

/* Variante en capitales : pilule de qualité des cartes produit. */
.pill--upper {
    text-transform: uppercase;
}

/* --------------------------------------------------------------------------
   5a. CARTE PRODUIT ET GRILLE (design 8, maquette du 20 septembre 2026) —
   template-parts/product-card.php, partagée par les grilles de l'accueil
   et le carrousel des produits liés de la fiche (fiche.css section 6).

   Le bloc s'appelle « product-card », pas « product » comme dans la
   maquette : WooCommerce pose lui-même la classe « product » sur le
   conteneur de la fiche produit (wc_product_class, woocommerce/
   content-single-product.php) et sur les éléments de ses boucles. Un
   sélecteur descendant écrit pour la carte, par exemple
   « .product .quantity », atteignait alors le compteur de quantité du
   bloc d'achat de la fiche. Le nom reprend celui du gabarit qui rend la
   carte, comme « price-card » (accueil.css). La classe « product » de
   WooCommerce reste posée : elle est un point d'accroche public pour ses
   scripts et ses extensions ; on cesse seulement de la styler.
   -------------------------------------------------------------------------- */

/* Grille de cartes, partagée par l'accueil, les archives et les ventes
   croisées du panier. Seul l'écart entre les cartes est ici : le nombre de
   colonnes dépend de la largeur que laisse la page, donc chaque feuille de
   page pose --grid-cols et le redescend à ses points de rupture — cinq
   colonnes sur l'accueil (accueil.css section 10), quatre sur une archive,
   où la barre de filtres prend 260 px (boutique.css section 5). La valeur
   de repli sert à une page qui afficherait la grille sans le dire. */
.product-grid {
    display: grid;
    grid-template-columns: repeat(var(--grid-cols, 4), minmax(0, 1fr));
    gap: var(--sp-16);
}

.product-card {
    display: flex;
    flex-direction: column;
    gap: var(--sp-10);
    padding: var(--sp-16);
    min-width: 0;
}

/* Image : carré bordé, le badge de stock à cheval sur son coin, dans la
   marge de la carte. Le lien est ignoré des lecteurs d'écran (le titre
   porte déjà le lien) : l'état de stock leur est redit dans le corps. */
.product-card__media {
    position: relative;
    display: flex;
    align-items: center;
    justify-content: center;
    aspect-ratio: 1 / 1;
    background: var(--bench);
    border: var(--cp-line) solid var(--line);
    border-radius: var(--radius-sm);
}

.product-card__media .ph {
    width: 100%;
    height: 100%;
    background: var(--placeholder);
    border-radius: inherit;
}

.product-card__media img {
    width: 100%;
    height: 100%;
    object-fit: contain;
    border-radius: inherit;
}

/* Derrière une vraie photo, le fond passe au blanc : les photos fournisseur
   sont sur fond blanc, et une photo qui ne remplit pas le carré ne laisse
   alors aucune bande visible. Exception documentée à la maquette (fond
   gris partout). */
.product-card__media:has(> img) {
    background: var(--paper);
}

.product-card__media .stock {
    position: absolute;
    top: calc(-1 * var(--cp-badge-out));
    left: calc(-1 * var(--cp-badge-out));
    z-index: var(--z-badge);
    box-shadow: var(--shadow-badge);
}

/* Titre sur trois lignes, hauteur réservée : le pied des cartes d'une
   ligne s'aligne, titre court ou long. */
.product-card__body h3 {
    font-size: var(--fs-13);
    font-weight: var(--fw-medium);
    line-height: var(--lh-card);
    display: -webkit-box;
    -webkit-line-clamp: 3;
    -webkit-box-orient: vertical;
    overflow: hidden;
    min-height: calc(3 * var(--lh-card) * 1em);
    text-wrap: pretty;
}

.product-card__body h3 a {
    color: var(--ink);
}

.product-card__body h3 a:hover {
    color: var(--action);
    text-decoration: none;
}

/* SKU : la maquette l'écrit dans chaque carte et le masque (« cards: no
   SKU »). Le balisage reste pour que la même carte serve une liste qui le
   montrerait ; ce n'est ni un prix ni une donnée réservée, la règle
   « jamais display:none » de CLAUDE.md §6 ne s'applique pas. */
.product-card__sku {
    display: none;
}

/* Ligne prix et pilule, compte autorisé seulement. Un visiteur n'a pas de
   ligne de prix : sa pilule est dans .product-card__guest. */
.product-card__meta {
    display: flex;
    align-items: center;
    justify-content: space-between;
    flex-wrap: wrap;
    gap: var(--sp-6) var(--sp-8);
    min-width: 0;
}

.product-card__meta .pill {
    flex: none;
}

/* Prix WooCommerce : pile système, chiffres tabulaires (la chasse fixe ne
   sert plus qu'aux références, décision du 21 septembre 2026) ; la mention
   TVA dessous, en petites capitales. */
.product-card__price {
    display: flex;
    flex-direction: column;
    white-space: nowrap;
    font-size: var(--fs-15);
    font-weight: var(--fw-medium);
    line-height: var(--lh-page-title);
    color: var(--ink);
    font-variant-numeric: tabular-nums;
}

.product-card__price del {
    color: var(--grey);
    font-weight: var(--fw-normal);
}

.product-card__price ins {
    text-decoration: none;
}

.product-card__price small {
    font-family: var(--sans);
    font-size: var(--fs-10);
    font-weight: var(--fw-normal);
    letter-spacing: var(--ls-pill);
    text-transform: uppercase;
    color: var(--grey);
}

/* Bloc d'achat, au bas de la carte d'un compte autorisé : le compteur de
   quantité puis le bouton d'ajout. Le pied d'une carte visiteur est un
   bloc distinct, .product-card__guest, plus bas. */
.product-card__buy {
    display: flex;
    flex-direction: column;
    gap: var(--sp-8);
    margin: auto 0 0;
    padding: var(--sp-10) 0 0;
    border: 0;
    border-top: var(--cp-line) solid var(--line);
}

/* Le fieldset désactive tous ses contrôles d'un coup (produit en rupture). */
.product-card__fields {
    display: flex;
    flex-direction: column;
    gap: var(--sp-8);
    margin: 0;
    padding: 0;
    border: 0;
    min-width: 0;
}

/* Le compteur natif (section 10), à la géométrie de la carte : pleine
   largeur, angles droits, boutons plus étroits, survol gris clair. */
.product-card .quantity {
    display: grid;
    grid-template-columns: var(--cp-qty-btn-sm) minmax(0, 1fr) var(--cp-qty-btn-sm);
    width: 100%;
    height: var(--cp-qty-h-sm);
    border-radius: var(--radius-sm);
}

.product-card .quantite__bouton,
.product-card .quantite__bouton:hover,
.product-card .quantite__bouton:focus {
    width: auto;
}

.product-card .quantite__bouton:hover {
    background: var(--bench);
}

.product-card .quantite__bouton:disabled,
.product-card .quantite__bouton:disabled:hover {
    color: var(--grey);
    cursor: default;
}

.product-card .quantity .qty,
.product-card .quantity .qty:focus {
    width: auto;
    border-left: var(--cp-line) solid var(--line);
    border-right: var(--cp-line) solid var(--line);
    font-size: var(--fs-13);
}

.product-card .quantity .qty:disabled {
    color: var(--grey);
}

/* Sans JavaScript, les boutons − et + sont masqués (section 10) : le champ
   prend toute la ligne au lieu de la première colonne de 32 px. */
html:not(.js) .product-card .quantity {
    grid-template-columns: minmax(0, 1fr);
}

.product-card__add {
    width: 100%;
    height: var(--cp-btn-h-sm);
    padding: 0 var(--sp-12);
    font-size: var(--fs-13);
}

.product-card__add:disabled,
.product-card__add:disabled:hover {
    background: var(--line-strong);
    color: var(--grey);
    cursor: default;
    transform: none;
}

/* Ajout AJAX en cours (classe posée par WooCommerce, sans style depuis que
   sa feuille est retirée) : le bouton s'estompe le temps de la requête ;
   « added » ne change rien, la pastille du panier de l'en-tête suffit. */
.product-card__add.loading {
    opacity: var(--cp-loading-opacity);
    cursor: progress;
}

/* Le lien « View cart » que le script add-to-cart.js de WooCommerce insère
   après le bouton : pas de place dans un bloc à hauteur fixe, et le panier
   est à portée dans l'en-tête, dont le compteur suit par les mêmes
   fragments AJAX. Ce n'est pas un prix : la règle « jamais display:none »
   ne s'applique pas. */
.product-card__buy .added_to_cart {
    display: none;
}

/* Pied de la carte, visiteur et compte en attente : la pilule de qualité à
   gauche, le bouton vers Mon compte, son indice. Le prix n'a plus de place
   réservée : la maquette du 20 septembre 2026 accepte une carte visiteur
   plus courte qu'une carte de compte, les deux états ne coexistant jamais
   sur une page. */
.product-card__guest {
    display: flex;
    flex-direction: column;
    gap: var(--sp-6);
    margin: auto 0 0;
    padding: var(--sp-10) 0 0;
    border-top: var(--cp-line) solid var(--line);
}

.product-card__guest .pill {
    align-self: flex-start;
}

/* Bouton plein, gris clair, qui verdit au survol : ce n'est pas un .btn du
   design, il a ses propres couleurs. */
.product-card__cta {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: var(--sp-6);
    width: 100%;
    height: var(--cp-btn-h-sm);
    padding: 0 var(--sp-12);
    border-radius: var(--radius-sm);
    background: var(--chrome);
    color: var(--ink);
    font-size: var(--fs-13);
    font-weight: var(--fw-medium);
    transition: background var(--ease), color var(--ease), transform var(--ease-press);
}

.product-card__cta:hover {
    background: var(--pastel-green-bg);
    color: var(--action);
    text-decoration: none;
}

.product-card__cta:active {
    transform: scale(.95);
}

/* Variante ambre de la maquette, pour une rupture vue par un visiteur
   (« Notify me »). Le thème ne l'emploie pas : WooCommerce n'a pas
   d'alerte de réassort native et en construire une est une décision en
   attente (voir template-parts/product-card.php). La règle reste ici pour
   que la variante soit prête le jour où l'alerte existera. */
.product-card__cta--notify {
    color: var(--pastel-amber-ink);
}

.product-card__cta--notify:hover {
    background: var(--pastel-amber-bg);
    color: var(--pastel-amber-ink);
}

.product-card__hint {
    font-size: var(--fs-11);
    color: var(--grey);
    text-align: center;
}

/* --------------------------------------------------------------------------
   5b. MENU DÉROULANT (design 20.5) — autour d'un <select> natif
   -------------------------------------------------------------------------- */
/* Menu déroulant du design, construit par assets/js/menu-deroulant.js
   autour d'un <select> natif (sélecteur du hero, tri de la boutique). */
.dd {
    position: relative;
    min-width: 0;
}

.dd__toggle {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--sp-10);
    width: 100%;
    height: var(--cp-select-h);
    padding: 0 var(--sp-14);
    font-family: inherit;
    font-size: var(--fs-15);
    color: var(--grey);
    text-align: left;
    background: var(--paper);
    border: var(--cp-line) solid var(--line-strong);
    border-radius: var(--radius-sm);
    cursor: pointer;
    transition: border-color var(--ease);
}

/* Survol et focus : le CSS inline de GeneratePress impose à tout <button>
   un fond gris foncé et un texte blanc (button:hover, button:focus,
   spécificité 0,1,1, supérieure à .dd__toggle). Fond et couleur du repos
   sont donc redits ici, à 0,2,0. Part avec generate-style. */
.dd__toggle:hover {
    border-color: var(--slate);
    background: var(--paper);
    color: var(--grey);
}

.dd__toggle:focus,
.dd__toggle:focus-visible {
    outline: none;
    box-shadow: none;
    border-color: var(--slate);
    background: var(--paper);
    color: var(--grey);
}

.dd__toggle[data-filled="true"],
.dd__toggle[data-filled="true"]:hover,
.dd__toggle[data-filled="true"]:focus {
    color: var(--ink);
}

.dd__value {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.dd__caret {
    flex: none;
    transition: transform var(--ease);
}

.dd.is-open .dd__toggle {
    border-color: var(--slate);
}

.dd.is-open .dd__caret {
    transform: rotate(180deg);
}

/* Le panneau : arrondi, ombre douce, défilement propre. */
.dd__menu {
    position: absolute;
    left: 0;
    right: 0;
    top: calc(100% + var(--sp-6));
    z-index: var(--z-dd);
    max-height: var(--cp-menu-max-h);
    overflow-y: auto;
    padding: var(--sp-6);
    margin: 0;
    list-style: none;
    background: var(--paper);
    border: var(--cp-line) solid var(--line);
    border-radius: var(--radius);
    box-shadow: var(--shadow-menu);
    display: none;
}

.dd.is-open .dd__menu {
    display: block;
}

.dd__option {
    padding: var(--sp-10) var(--sp-12);
    border-radius: var(--radius-sm);
    font-size: var(--fs-14);
    color: var(--ink);
    cursor: pointer;
    transition: background var(--ease);
}

/* Survol gris clair, jamais le bleu natif. */
.dd__option:hover,
.dd__option.is-active {
    background: var(--option-hover);
}

.dd__option[aria-selected="true"] {
    font-weight: var(--fw-medium);
}

.dd__empty {
    padding: var(--sp-10) var(--sp-12);
    font-size: var(--fs-13);
    color: var(--grey);
}

/* --------------------------------------------------------------------------
   6. FIL D'ARIANE (design 20.1) — WooCommerce, filtré dans inc/boutique.php
   -------------------------------------------------------------------------- */
.crumbs {
    padding: var(--sp-16) 0 0;
    font-size: var(--fs-12);
    color: var(--grey);
}

.crumbs ol {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--sp-6);
    margin: 0;
    padding: 0;
    list-style: none;
}

.crumbs a {
    color: var(--grey);
}

.crumbs a:hover {
    color: var(--ink);
    text-decoration: none;
}

.crumbs li + li::before {
    content: "/";
    margin-right: var(--sp-6);
    color: var(--line-strong);
}

.crumbs [aria-current] {
    color: var(--ink);
}

/* --------------------------------------------------------------------------
   7. BADGE DE STOCK (maquette produit du 20 septembre 2026, généralisé à
   toutes les pages) : pilule pastel, même géométrie que la pilule de
   qualité, sans point ; encre et fond par état. Les couleurs d'état ne sont
   utilisées qu'ici et sur le point des cartes de l'accueil. Le nombre de
   pièces, quand le compte le voit, suit dans un <small> sur la même ligne
   (gmparts_badge_stock, inc/boutique.php). Police système : un état n'est
   pas une référence, la mono reste aux SKU et aux codes.
   -------------------------------------------------------------------------- */
.stock {
    display: inline-flex;
    align-items: center;
    align-self: flex-start;
    height: var(--cp-pill-h);
    padding: 0 var(--sp-8);
    border-radius: var(--pill);
    font-size: var(--fs-11);
    font-weight: var(--fw-medium);
    letter-spacing: var(--ls-pill);
    white-space: nowrap;
}

.stock--ok  { background: var(--stock-ok-bg);  color: var(--stock-ok); }
.stock--low { background: var(--stock-low-bg); color: var(--stock-low); }
.stock--out { background: var(--stock-out-bg); color: var(--stock-out); }

.stock small {
    margin-left: var(--cp-stock-count-gap);
    font-size: var(--fs-11);
    font-weight: var(--fw-normal);
    opacity: var(--cp-stock-count-opacity);
}

/* --------------------------------------------------------------------------
   8. NOMBRE (design 23.1) : prix et totaux en pile système, chiffres
   tabulaires. Les chiffres tabulaires viennent de font-feature-settings
   sur <body> (style.css) ; font-variant-numeric le redit ici pour les
   navigateurs qui n'héritent pas de la première dans un tableau.
   -------------------------------------------------------------------------- */
.num {
    font-size: var(--fs-14);
    text-align: right;
    white-space: nowrap;
    font-variant-numeric: tabular-nums;
}

.num--total {
    font-weight: var(--fw-medium);
    font-size: var(--fs-15);
}

.num small {
    display: block;
    font-family: var(--sans);
    font-size: var(--fs-11);
    color: var(--grey);
    font-weight: var(--fw-normal);
}

.num s {
    color: var(--grey);
    font-size: var(--fs-12);
    margin-right: var(--sp-4);
}

/* --------------------------------------------------------------------------
   9. CASE À COCHER ET INTERRUPTEUR (design 20.3, 22.1)
   La case native reste dans la page, invisible : c'est elle qui est cochée,
   envoyée et lue par le clavier ; .check__box la dessine.
   -------------------------------------------------------------------------- */
.check {
    position: relative;
    display: flex;
    align-items: center;
    gap: var(--sp-10);
    min-height: var(--cp-check-row-h);
    padding: 0 var(--sp-4);
    border-radius: var(--radius-sm);
    font-size: var(--fs-14);
    cursor: pointer;
    transition: background var(--ease);
}

.check:hover {
    background: var(--chrome);
}

.check input,
.switch input {
    position: absolute;
    opacity: 0;
    width: 0;
    height: 0;
}

.check__box {
    width: var(--cp-check-box);
    height: var(--cp-check-box);
    flex: none;
    border: var(--cp-check-line) solid var(--line-strong);
    border-radius: var(--radius-xs);
    color: var(--paper);
    display: flex;
    align-items: center;
    justify-content: center;
    transition: border-color var(--ease), background var(--ease);
}

.check__box svg {
    opacity: 0;
    transition: opacity var(--ease);
}

.check input:checked + .check__box {
    background: var(--action);
    border-color: var(--action);
}

.check input:checked + .check__box svg {
    opacity: 1;
}

.check input:focus-visible + .check__box {
    outline: 2px solid var(--action);
    outline-offset: 2px;
}

.check__count {
    margin-left: auto;
    font-size: var(--fs-12);
    color: var(--grey);
}

.check--disabled {
    opacity: .45;
    pointer-events: none;
}

/* Interrupteur : même piste que l'interrupteur TVA de l'en-tête. */
.switch {
    position: relative;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--sp-12);
    min-height: var(--cp-switch-row-h);
    padding: 0 var(--sp-4);
    font-size: var(--fs-14);
    font-weight: var(--fw-medium);
    cursor: pointer;
}

.switch__track {
    width: var(--cp-switch-w);
    height: var(--cp-switch-h);
    flex: none;
    border-radius: var(--pill);
    background: var(--line-strong);
    padding: var(--cp-switch-pad);
    display: flex;
    justify-content: flex-start;
    transition: background var(--ease);
}

.switch__knob {
    width: var(--cp-switch-knob);
    height: var(--cp-switch-knob);
    border-radius: var(--pill);
    background: var(--paper);
    transition: transform var(--ease);
}

.switch input:checked + .switch__track {
    background: var(--action);
}

.switch input:checked + .switch__track .switch__knob {
    transform: translateX(var(--cp-switch-knob));
}

.switch input:focus-visible + .switch__track {
    outline: 2px solid var(--action);
    outline-offset: 2px;
}

/* --------------------------------------------------------------------------
   10. QUANTITÉ (design 23.2) : le champ natif de WooCommerce, ses boutons
   − et + ajoutés par inc/boutique.php, animés par assets/js/quantite.js.
   GeneratePress habille input[type=number] (0,1,1) et son focus (0,2,1) :
   les sélecteurs ci-dessous sont plus lourds pour reprendre la main.
   -------------------------------------------------------------------------- */
.quantity {
    display: inline-flex;
    align-items: stretch;
    height: var(--cp-qty-h);
    border: var(--cp-line) solid var(--line-strong);
    border-radius: var(--pill);
    background: var(--paper);
    overflow: hidden;
    transition: border-color var(--ease);
}

.quantity:focus-within {
    border-color: var(--action);
}

/* Sans JavaScript, − et + seraient inertes : seul le champ reste. */
html:not(.js) .quantite__bouton {
    display: none;
}

.quantite__bouton,
.quantite__bouton:hover,
.quantite__bouton:focus {
    width: var(--cp-qty-btn);
    padding: 0;
    border: 0;
    background: transparent;
    color: var(--ink);
    font-size: var(--fs-16);   /* les glyphes − et + des maquettes (.qty__btn) */
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    transition: background var(--ease), transform var(--ease-press);
}

.quantite__bouton:hover {
    background: var(--chrome);
}

.quantite__bouton:active {
    transform: scale(.9);
}

.quantite__bouton:disabled,
.quantite__bouton:disabled:hover {
    color: var(--line-strong);
    cursor: not-allowed;
    background: transparent;
}

.quantity .qty,
.quantity .qty:focus {
    width: var(--cp-qty-input);
    height: auto;
    min-height: 0;
    margin: 0;
    padding: 0;
    border: 0;
    border-radius: 0;
    outline: none;
    box-shadow: none;
    text-align: center;
    font-size: var(--fs-14);
    font-weight: var(--fw-medium);
    color: var(--ink);
    background: transparent;
    appearance: textfield;
    -moz-appearance: textfield;
}

/* Le champ n'a pas de bordure à lui : l'anneau de focus du clavier est
   ramené à l'intérieur pour rester visible dans le compteur (la maquette
   fait de même sur .qty__input). outline:none ci-dessus ne concerne que
   :focus, posé pour reprendre la main sur GeneratePress. */
.quantity .qty:focus-visible {
    outline: var(--cp-line-thick) solid var(--action);
    outline-offset: calc(-1 * var(--cp-line-thick));
}

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

/* --------------------------------------------------------------------------
   11. NOTICES WOOCOMMERCE (design 22.2) : balisage natif, habillage du
   design. Info en ardoise, succès en vert, erreur en orange pastel.
   -------------------------------------------------------------------------- */
.woocommerce-notices-wrapper:empty {
    display: none;
}

.woocommerce-info,
.woocommerce-message,
.woocommerce-error {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--sp-8) var(--cp-notice-gap);
    margin: 0 0 var(--sp-16);
    padding: var(--sp-14) var(--sp-16);
    border-radius: var(--radius-sm);
    background: var(--pastel-slate-bg);
    color: var(--pastel-slate-ink);
    font-size: var(--fs-13);
    line-height: var(--lh-lede);
    list-style: none;
}

.woocommerce-message {
    background: var(--pastel-green-bg);
    color: var(--pastel-green-ink);
}

.woocommerce-error {
    background: var(--pastel-orange-bg);
    color: var(--pastel-orange-ink);
}

.woocommerce-error li {
    margin: 0;
}

.woocommerce-info a,
.woocommerce-message a,
.woocommerce-error a {
    color: inherit;
    text-decoration: underline;
}

/* Le bouton d'une notice (« View cart » après un ajout) : bouton fantôme. */
.woocommerce-info .button,
.woocommerce-message .button,
.woocommerce-error .button {
    order: 2;
    margin-left: auto;
    display: inline-flex;
    align-items: center;
    height: var(--cp-btn-ghost-h);
    padding: 0 var(--sp-14);
    border: var(--cp-line) solid currentColor;
    border-radius: var(--pill);
    background: transparent;
    color: inherit;
    font-size: var(--fs-13);
    font-weight: var(--fw-medium);
    text-decoration: none;
}

/* --------------------------------------------------------------------------
   12. FORMULAIRES (design 22.1) : étiquette au-dessus du champ, jamais un
   simple placeholder ; halo de focus visible à la souris comme au clavier.
   Deux familles de sélecteurs : ceux du design (.form, .field) dans les
   gabarits du thème, et ceux de WooCommerce (.form-row, .input-text) dans
   ses formulaires non surchargés (mot de passe perdu, adresses, commande).
   L'œil « afficher le mot de passe » et la jauge de force sont ceux que
   WooCommerce injecte lui-même (woocommerce.js, password-strength-meter.js) :
   habillés ici, jamais réécrits.
   -------------------------------------------------------------------------- */
.form,
.woocommerce-ResetPassword {
    display: flex;
    flex-direction: column;
    gap: var(--sp-16);
    margin: 0;
}

.form__row {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: var(--sp-16);
}

.field,
.form-row {
    display: flex;
    flex-direction: column;
    gap: var(--sp-6);
    min-width: 0;
    margin: 0;
    padding: 0;
}

.field label,
.form-row label {
    margin: 0;
    font-size: var(--fs-13);
    font-weight: var(--fw-medium);
    color: var(--ink);
}

.field__wrap,
.password-input {
    position: relative;
    display: flex;
    align-items: center;
    flex-wrap: wrap;
}

.password-input {
    flex: 1 1 100%;
    min-width: 0;
}

/* GeneratePress habille les champs (input[type=text], 0,1,1) : deux classes
   ici pour reprendre la main. */
.field .input-text,
.form-row .input-text {
    width: 100%;
    height: var(--cp-field-h);
    margin: 0;
    padding: 0 var(--sp-14);
    border: var(--cp-line) solid var(--line-strong);
    border-radius: var(--radius-xs);
    background: var(--paper);
    font-size: var(--fs-15);
    line-height: var(--lh-body);
    color: var(--ink);
    outline: none;
    box-shadow: none;
    transition: border-color var(--ease), box-shadow var(--ease);
}

.field .input-text::placeholder,
.form-row .input-text::placeholder {
    color: var(--field-placeholder);
}

.field .input-text:hover,
.form-row .input-text:hover {
    border-color: var(--slate);
}

.field .input-text:focus,
.form-row .input-text:focus {
    border-color: var(--action);
    box-shadow: 0 0 0 var(--cp-focus-ring) var(--focus-halo);
}

.password-input .input-text {
    padding-right: var(--cp-field-peek-pad);
}

/* Listes déroulantes natives (pays, état) : le champ, flèche du navigateur. */
.field select,
.form-row select {
    width: 100%;
    height: var(--cp-field-h);
    margin: 0;
    padding: 0 var(--sp-14);
    border: var(--cp-line) solid var(--line-strong);
    border-radius: var(--radius-xs);
    background: var(--paper);
    font-size: var(--fs-15);
    color: var(--ink);
    outline: none;
}

.form-row select:focus {
    border-color: var(--action);
    box-shadow: 0 0 0 var(--cp-focus-ring) var(--focus-halo);
}

/* Zone de texte native (note de commande) : le champ, en plus haut. */
.form-row textarea,
.form-row textarea:focus {
    width: 100%;
    min-height: calc(2 * var(--cp-field-h));
    margin: 0;
    padding: var(--sp-12) var(--sp-14);
    border: var(--cp-line) solid var(--line-strong);
    border-radius: var(--radius-xs);
    background: var(--paper);
    font-size: var(--fs-15);
    line-height: var(--lh-body);
    color: var(--ink);
    outline: none;
    box-shadow: none;
    resize: vertical;
}

.form-row textarea:focus {
    border-color: var(--action);
    box-shadow: 0 0 0 var(--cp-focus-ring) var(--focus-halo);
}

/* Enveloppe et mentions que WooCommerce écrit autour de ses champs. */
.form-row .woocommerce-input-wrapper {
    display: block;
}

.form-row label .optional {
    font-weight: var(--fw-normal);
    color: var(--grey);
}

.form-row label .required {
    border: 0;
    color: var(--stock-out);
    text-decoration: none;
}

/* Formulaires natifs à deux colonnes : les lignes que WooCommerce marque
   « first » et « last » côte à côte, le reste en pleine largeur ; une
   colonne sous 520 px (§14). */
.woocommerce-EditAccountForm,
.woocommerce-address-fields__field-wrapper,
.woocommerce-billing-fields__field-wrapper,
.woocommerce-shipping-fields__field-wrapper,
.woocommerce-additional-fields__field-wrapper {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: var(--sp-16);
}

.woocommerce-EditAccountForm > *,
.woocommerce-address-fields__field-wrapper > *,
.woocommerce-billing-fields__field-wrapper > *,
.woocommerce-shipping-fields__field-wrapper > *,
.woocommerce-additional-fields__field-wrapper > * {
    grid-column: 1 / -1;
}

.woocommerce-EditAccountForm > .form-row-first,
.woocommerce-address-fields__field-wrapper > .form-row-first,
.woocommerce-billing-fields__field-wrapper > .form-row-first,
.woocommerce-shipping-fields__field-wrapper > .form-row-first {
    grid-column: 1;
}

.woocommerce-EditAccountForm > .form-row-last,
.woocommerce-address-fields__field-wrapper > .form-row-last,
.woocommerce-billing-fields__field-wrapper > .form-row-last,
.woocommerce-shipping-fields__field-wrapper > .form-row-last {
    grid-column: 2;
}

/* Le même <select> une fois enrichi par selectWoo (WooCommerce, pays et
   état, adresses et commande) : la boîte de select2 prend la forme du champ. */
.form-row .select2-container .select2-selection--single {
    height: var(--cp-field-h);
    border: var(--cp-line) solid var(--line-strong);
    border-radius: var(--radius-xs);
    background: var(--paper);
}

.form-row .select2-container .select2-selection--single .select2-selection__rendered {
    height: 100%;
    padding: 0 var(--touch) 0 var(--sp-14);
    line-height: calc(var(--cp-field-h) - 2 * var(--cp-line));
    font-size: var(--fs-15);
    color: var(--ink);
}

.form-row .select2-container .select2-selection--single .select2-selection__arrow {
    height: 100%;
    right: var(--sp-8);
}

.form-row .select2-container--open .select2-selection--single,
.form-row .select2-container--focus .select2-selection--single {
    border-color: var(--action);
    box-shadow: 0 0 0 var(--cp-focus-ring) var(--focus-halo);
}

.field__hint,
.form-row .description,
.woocommerce-password-hint {
    display: block;
    margin: 0;
    font-size: var(--fs-12);
    color: var(--grey);
}

/* Œil injecté par WooCommerce dans .password-input : rond, dans le champ.
   Le tracé est celui de assets/icons/eye.svg, en masque : le bouton naît
   vide, côté navigateur, hors de portée du PHP. */
.password-input .show-password-input,
.password-input .show-password-input:hover,
.password-input .show-password-input:focus {
    position: absolute;
    top: calc((var(--cp-field-h) - var(--cp-peek)) / 2);
    right: var(--cp-peek-right);
    width: var(--cp-peek);
    height: var(--cp-peek);
    padding: 0;
    border: 0;
    border-radius: var(--pill);
    background: transparent;
    color: var(--grey);
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    transition: color var(--ease), transform var(--ease-press);
}

.password-input .show-password-input::before {
    content: "";
    width: var(--cp-peek-icon);
    height: var(--cp-peek-icon);
    background: currentColor;
    -webkit-mask: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'><path d='M2.5 12s3.5-6.5 9.5-6.5S21.5 12 21.5 12s-3.5 6.5-9.5 6.5S2.5 12 2.5 12z'/><circle cx='12' cy='12' r='2.8'/></svg>") center / contain no-repeat;
    mask: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'><path d='M2.5 12s3.5-6.5 9.5-6.5S21.5 12 21.5 12s-3.5 6.5-9.5 6.5S2.5 12 2.5 12z'/><circle cx='12' cy='12' r='2.8'/></svg>") center / contain no-repeat;
}

.password-input .show-password-input:hover,
.password-input .show-password-input.display-password {
    color: var(--ink);
}

.password-input .show-password-input:active {
    transform: scale(.95);
}

/* Jauge de force de WooCommerce : les quatre segments du design, puis son
   texte. Le masque (couleur quelconque, opaque) découpe les trois espaces. */
.woocommerce-password-strength {
    flex: 1 1 100%;
    margin: 0;
    padding: 0;
    font-size: var(--fs-12);
    color: var(--grey);
    text-align: left;
}

.woocommerce-password-strength::before {
    content: "";
    display: block;
    height: var(--cp-meter-h);
    margin: var(--cp-meter-top) 0 var(--sp-6);
    background-image: linear-gradient(var(--cp-meter-color, transparent), var(--cp-meter-color, transparent)), linear-gradient(var(--line), var(--line));
    background-size: var(--cp-meter-fill, 0%) 100%, 100% 100%;
    background-repeat: no-repeat;
    -webkit-mask: repeating-linear-gradient(90deg, #000 0 calc(25% - var(--cp-meter-gap)), transparent calc(25% - var(--cp-meter-gap)) 25%) 0 0 / calc(100% + var(--cp-meter-gap)) 100% no-repeat;
    mask: repeating-linear-gradient(90deg, #000 0 calc(25% - var(--cp-meter-gap)), transparent calc(25% - var(--cp-meter-gap)) 25%) 0 0 / calc(100% + var(--cp-meter-gap)) 100% no-repeat;
}

.woocommerce-password-strength.short {
    --cp-meter-fill: 25%;
    --cp-meter-color: var(--stock-out);
}

.woocommerce-password-strength.bad {
    --cp-meter-fill: 50%;
    --cp-meter-color: var(--stock-low);
}

.woocommerce-password-strength.good {
    --cp-meter-fill: 75%;
    --cp-meter-color: var(--action);
}

.woocommerce-password-strength.strong {
    --cp-meter-fill: 100%;
    --cp-meter-color: var(--action);
}

.form__between {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--sp-12);
    flex-wrap: wrap;
    font-size: var(--fs-13);
}

.form__between a {
    font-size: var(--fs-13);
}

/* La case à cocher des filtres (§8), en version formulaire : une ligne de
   texte, sans hauteur de rangée ni fond au survol. */
.form .check {
    position: static;
    align-items: flex-start;
    min-height: 0;
    padding: 0;
    border-radius: 0;
    font-size: var(--fs-13);
    line-height: var(--lh-body);
}

.form .check:hover {
    background: transparent;
}

.form .check__box {
    margin-top: var(--cp-notice-nudge);
}

.form .btn {
    width: 100%;
    height: var(--cp-field-h);
    font-size: var(--fs-15);
}

.form__foot {
    margin: 0;
    font-size: var(--fs-13);
    color: var(--grey);
    text-align: center;
}

/* Texte de confidentialité de WooCommerce (inscription) : le ton de l'aide. */
.woocommerce-privacy-policy-text,
.woocommerce-privacy-policy-text p {
    margin: 0;
    font-size: var(--fs-12);
    color: var(--grey);
}

/* Formulaires natifs de mot de passe perdu : phrase d'intro, bouton du design. */
.woocommerce-ResetPassword > p:first-child {
    margin: 0;
    font-size: var(--fs-14);
    line-height: var(--lh-lede);
    color: var(--grey);
}

.woocommerce-ResetPassword .clear,
.woocommerce-ResetPassword .required {
    display: none;   /* tout est requis : pas d'astérisque, comme le design */
}

.woocommerce-ResetPassword .button,
.woocommerce-ResetPassword .button:focus {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 100%;
    height: var(--cp-field-h);
    padding: 0 var(--sp-20);
    border: 0;
    border-radius: var(--radius-sm);
    background: var(--action);
    color: var(--paper);
    font-size: var(--fs-15);
    font-weight: var(--fw-medium);
    cursor: pointer;
    transition: background var(--ease), transform var(--ease-press);
}

.woocommerce-ResetPassword .button:hover {
    background: var(--action-lift);
    color: var(--paper);
}

.woocommerce-ResetPassword .button:active {
    transform: scale(.95);
}

/* --------------------------------------------------------------------------
   13. NOTE (design 22.2) : encart gris à icône pour une information de
   procédure (comptes vérifiés à la main). Autre chose que les notices
   WooCommerce du §11, qui répondent à une action.
   -------------------------------------------------------------------------- */
.notice {
    display: flex;
    gap: var(--sp-12);
    padding: var(--sp-14) var(--sp-16);
    border-radius: var(--radius-sm);
    background: var(--pastel-slate-bg);
    color: var(--pastel-slate-ink);
    font-size: var(--fs-13);
    line-height: var(--lh-lede);
}

.notice > svg {
    flex: none;
    margin-top: var(--cp-notice-nudge);
}

.notice strong {
    font-weight: var(--fw-medium);
    color: var(--ink);
}

.notice ol {
    margin: var(--sp-6) 0 1em;
    padding-left: var(--sp-16);
    list-style: decimal;
    color: var(--grey);
}

/* --------------------------------------------------------------------------
   13b. BOUTON « COPY » (design 21, 25) : pilule discrète qui copie un texte
   (copier.js) ; masquée sans JavaScript.
   -------------------------------------------------------------------------- */
.copy-btn,
.copy-btn:hover,
.copy-btn:focus {
    display: inline-flex;
    align-items: center;
    gap: var(--sp-6);
    height: var(--cp-copy-h);
    padding: 0 var(--sp-10);
    border: var(--cp-line) solid var(--line-strong);
    border-radius: var(--pill);
    background: var(--paper);
    color: var(--grey);
    font-size: var(--fs-12);
    cursor: pointer;
    transition: border-color var(--ease), color var(--ease), transform var(--ease-press);
}

.copy-btn:hover {
    border-color: var(--slate);
    color: var(--ink);
}

.copy-btn:active {
    transform: scale(.95);
}

/* Sans JavaScript, le bouton serait inerte : le SKU reste sélectionnable. */
html:not(.js) .copy-btn {
    display: none;
}

.copy-btn.is-done,
.copy-btn.is-done:hover {
    border-color: var(--action);
    color: var(--action);
}

/* --------------------------------------------------------------------------
   14. POINTS DE RUPTURE DES RÈGLES PARTAGÉES
   -------------------------------------------------------------------------- */

/* Sous 768 px : en-tête de section aligné en haut ; compteur et boutons de
   la carte à la zone tactile minimale (CLAUDE.md §11, 44 px : choix du
   thème, la maquette garde 36 px). Le nombre de colonnes de la grille n'est
   pas ici : il appartient à la page (accueil.css, boutique.css). */
@media (max-width: 768px) {

    .section-head {
        align-items: flex-start;
    }

    .product-card .quantity {
        grid-template-columns: var(--touch) minmax(0, 1fr) var(--touch);
        height: var(--touch);
    }

    .product-card__add,
    .product-card__cta {
        height: var(--touch);
    }
}

/* Sous 520 px : formulaires sur une colonne. */
@media (max-width: 520px) {

    .form__row,
    .woocommerce-EditAccountForm,
    .woocommerce-address-fields__field-wrapper,
    .woocommerce-billing-fields__field-wrapper,
    .woocommerce-shipping-fields__field-wrapper,
    .woocommerce-additional-fields__field-wrapper {
        grid-template-columns: 1fr;
    }

    .woocommerce-EditAccountForm > .form-row-first,
    .woocommerce-EditAccountForm > .form-row-last,
    .woocommerce-address-fields__field-wrapper > .form-row-first,
    .woocommerce-address-fields__field-wrapper > .form-row-last,
    .woocommerce-billing-fields__field-wrapper > .form-row-first,
    .woocommerce-billing-fields__field-wrapper > .form-row-last,
    .woocommerce-shipping-fields__field-wrapper > .form-row-first,
    .woocommerce-shipping-fields__field-wrapper > .form-row-last {
        grid-column: 1 / -1;
    }
}
