/* ==========================================================================
 * 08-shop.css — BOUTIQUE WooCommerce en DA V8 gelée
 * --------------------------------------------------------------------------
 * Habille les surfaces WooCommerce (storefront /boutique/, fiche produit,
 * archive catégorie produit) dans la DA Nooktails V8 :
 *   anthracite #16161A · or mat #c9a878 (RARE) · serif (Fraunces/Newsreader).
 *
 * PÉRIMÈTRE : 100% tokens (00-tokens.css). Aucun golden touché.
 * Tout est scopé sous body.woocommerce / .woocommerce / archives produit /
 * single-product / tax-product_cat. Ne redéfinit AUCUN token.
 * Le HERO reste régi par pillar.css (propriétaire unique) — on ne fait que
 * styliser l'en-tête d'archive Kadence, pas la mécanique du hero.
 *
 * Anti-IA STRICT : 0 emoji, 0 picto déco, 0 numérotation, 0 gradient déco,
 * 0 pill, 0 carte arrondie. Photo éditoriale : radius 0, 0 ombre/bordure.
 * SEO avant UI : aucun signal masqué (H1, prix, titres, images préservés).
 * ========================================================================== */

/* --------------------------------------------------------------------------
 * 0. FONDATION — fond anthracite + typo sur toutes les surfaces boutique
 * ------------------------------------------------------------------------ */
body.woocommerce,
body.woocommerce-page,
body.post-type-archive-product,
body.tax-product_cat,
body.single-product {
  background: var(--nt-bg);
  color: var(--nt-text);
  font-family: var(--nt-font-body);
}

/* Neutralise le fond « carte claire » Kadence (.content-bg) sur les surfaces
 * boutique : on veut le fond anthracite, pas la boîte Kadence. Scopé. */
body.woocommerce .content-bg,
body.woocommerce-page .content-bg,
body.post-type-archive-product .content-bg,
body.tax-product_cat .content-bg,
body.single-product .content-bg {
  background: transparent;
  box-shadow: none;
}

/* Le conteneur contenu ne doit pas réintroduire une boîte claire. */
body.post-type-archive-product .content-container.site-container,
body.tax-product_cat .content-container.site-container,
body.single-product .content-container.site-container {
  background: transparent;
}

/* --------------------------------------------------------------------------
 * 1. EN-TÊTE D'ARCHIVE — titre serif + filet doré + sous-titre feutré
 *    (hero Kadence .entry-hero-container-inner : on habille, on ne casse pas)
 * ------------------------------------------------------------------------ */
body.post-type-archive-product .page-title.archive-title,
body.tax-product_cat .page-title.archive-title {
  font-family: var(--nt-font-heading);
  font-weight: var(--nt-weight-semibold);
  font-size: var(--nt-h1);
  line-height: var(--nt-lh-h1);
  color: var(--nt-text-strong);
  letter-spacing: var(--nt-tracking-heading);
}

/* Filet doré fin sous le titre d'archive — signature DA, discret. */
body.post-type-archive-product .page-title.archive-title::after,
body.tax-product_cat .page-title.archive-title::after {
  content: "";
  display: block;
  width: 64px;
  height: 2px;
  margin-top: var(--nt-space-sm);
  background: var(--nt-gold);
}

/* Description de terme / boutique = sous-titre feutré, corps serif. */
body.post-type-archive-product .term-description,
body.post-type-archive-product .archive-description,
body.tax-product_cat .term-description,
body.tax-product_cat .archive-description {
  font-family: var(--nt-font-body);
  font-size: var(--nt-fs-lead);
  color: var(--nt-text-muted);
  line-height: var(--nt-leading-normal);
  max-width: 62ch;
  margin-top: var(--nt-space-sm);
}

/* --------------------------------------------------------------------------
 * 2. BARRE D'OUTILS ARCHIVE — result-count + tri (ordering)
 * ------------------------------------------------------------------------ */
body.woocommerce .woocommerce-result-count,
body.woocommerce-page .woocommerce-result-count {
  font-family: var(--nt-font-ui);
  font-size: var(--nt-text-sm);
  color: var(--nt-text-muted);
  letter-spacing: .01em;
}

/* Select de tri : anthracite feutré, filet doré, pas de style natif criard. */
body.woocommerce .woocommerce-ordering select,
body.woocommerce-page .woocommerce-ordering select,
body.woocommerce select.orderby {
  font-family: var(--nt-font-ui);
  font-size: var(--nt-text-sm);
  color: var(--nt-text);
  background: var(--nt-surface-1);
  border: 1px solid var(--nt-line);
  border-radius: var(--nt-radius-sm);
  padding: 10px 14px;
  min-height: 44px;
  cursor: pointer;
  transition: border-color var(--nt-transition);
}
body.woocommerce .woocommerce-ordering select:hover,
body.woocommerce .woocommerce-ordering select:focus,
body.woocommerce select.orderby:focus {
  border-color: var(--nt-gold);
  outline: none;
}

/* --------------------------------------------------------------------------
 * 3. FEATURED PRODUCT — Nooktails Commerce Design System V3, composant 02
 * (28/07, reconstruction complète — remplace l'ancienne grille de cartes ul.products/
 * li.product : conteneur grid 3 colonnes, wrapper .woocommerce-loop-product__link, image
 * à 78% flottante, titre/prix dédiés. Purgé en bloc, remplacé par un composant unique —
 * cf. content-product.php côté enfant pour le nouveau markup. S'applique à l'archive
 * boutique, aux pages catégorie et aux produits liés/upsells (même template WooCommerce),
 * PAS au widget Blocks "Nouveau dans la boutique" du panier vide (markup différent,
 * .wc-block-grid__product, section dédiée plus bas dans ce fichier, inchangée). */
ul.products {
  display: flex;
  flex-direction: column;
  gap: clamp(5rem, 10vw, 8rem);   /* V3 par.9 : espace "section", hors-echelle des autres tokens --
    separe deux unites editoriales completes, pas deux lignes de texte. */
  margin: var(--nt-space-lg) 0 0;
  padding: 0;
  list-style: none;
}
.nk-featured-product {
  display: flex;
  align-items: center;
  gap: clamp(2.5rem, 6vw, 5rem);
  margin: 0;
  padding: 0;
  background: transparent;
  border: 0;
  border-radius: 0;
  box-shadow: none;
  width: auto;
  float: none;
  text-align: left;
}
.nk-featured-product--reverse {
  flex-direction: row-reverse;   /* V3 par.5 : alternance gauche/droite a chaque produit */
}
@media (max-width: 900px) {
  .nk-featured-product,
  .nk-featured-product--reverse {
    flex-direction: column;   /* V3 par.6 : alternance abandonnee sur mobile, image toujours au-dessus */
    align-items: stretch;
  }
}
.nk-featured-product__media {
  flex: 0 0 55%;
  max-width: 55%;
}
@media (max-width: 900px) {
  .nk-featured-product__media { flex: 1 1 auto; max-width: 100%; }
}
.nk-featured-product__media a {
  display: block;
  aspect-ratio: 4 / 5;
  background: var(--nt-surface-1);
  overflow: hidden;
}
.nk-featured-product__media img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: contain;
  padding: 8%;
  border-radius: 0;
  box-shadow: none;
  border: 0;
}
.nk-featured-product__body {
  flex: 1 1 auto;
  min-width: 0;
}
.nk-featured-product__kind {
  font-family: var(--nt-font-ui);
  font-size: var(--nt-text-xs);
  font-weight: 600;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--nt-text-muted);
  margin: 0 0 var(--nt-space-xs);
}
.nk-featured-product__title {
  font-family: var(--nt-font-heading);
  font-weight: var(--nt-weight-medium);
  font-size: clamp(1.5rem, 2.6vw, 2rem);   /* V3 par.18 : jamais tronque, l'espace le permet */
  line-height: var(--nt-leading-snug);
  color: var(--nt-text-strong);
  margin: 0 0 var(--nt-space-sm);
}
.nk-featured-product__title a {
  color: inherit;
  text-decoration: none;
}
.nk-featured-product__price {
  margin: 0 0 var(--nt-space-xs);
}
.nk-featured-product__price .price {
  font-family: var(--nt-font-ui);
  font-size: 1.5rem;
  font-weight: 700;   /* V3 par.7/par.6 : le prix redevient une information forte */
  color: var(--nt-text-strong);
  font-variant-numeric: tabular-nums;
  font-feature-settings: "tnum" 1;
}
.nk-featured-product__price .price del,
.nk-featured-product__price .price del .amount {
  color: var(--nt-text-faint);
  font-weight: var(--nt-weight-regular);
  opacity: .8;
}
.nk-featured-product__price .price ins {
  text-decoration: none;
}
.nk-featured-product__stock {
  font-family: var(--nt-font-ui);
  font-size: var(--nt-text-xs);
  color: var(--nt-text-muted);
  margin: 0 0 var(--nt-space-sm);
}
.nk-featured-product__reassurance {
  font-family: var(--nt-font-ui);
  font-size: var(--nt-text-xs);
  color: var(--nt-text-muted);
  margin: 0 0 var(--nt-space-md);
}
.nk-featured-product__actions {
  display: flex;
  align-items: center;
  gap: var(--nt-space-md);
  flex-wrap: wrap;
}
/* CTA primaire = bouton natif WooCommerce restyle fond encre plein (V3 par.8 - Composant CTA) :
   remplace le contrat filet-or utilise jusqu'ici pour TOUT bouton archive. Specificite
   (0,5,3) bat la regle native Kadence "bouton archive = texte nu" (0,5,2), meme technique
   que l'ancien contrat, 0 !important. */
body.woocommerce ul.products li.product .nk-featured-product__actions .add_to_cart_button:not(.kb-button) {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 44px;
  padding: 13px 26px;
  font-family: var(--nt-font-ui);
  font-size: var(--nt-text-sm);
  font-weight: 600;
  letter-spacing: .02em;
  line-height: 1.2;
  color: var(--nt-bg);
  background: var(--nt-text-strong);
  border: 1px solid var(--nt-text-strong);
  border-radius: 0;
  box-shadow: none;
  text-decoration: none;
  text-transform: none;
  cursor: pointer;
  transition: background var(--nt-transition), border-color var(--nt-transition);
}
body.woocommerce ul.products li.product .nk-featured-product__actions .add_to_cart_button:not(.kb-button):hover {
  background: var(--nt-gold-dark);
  border-color: var(--nt-gold-dark);
}
body.woocommerce ul.products li.product .nk-featured-product__actions .add_to_cart_button:not(.kb-button):focus-visible {
  outline: 2px solid var(--nt-text-strong);
  outline-offset: 2px;
}
.nk-featured-product__cta-secondary {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 44px;
  padding: 12px 25px;
  font-family: var(--nt-font-ui);
  font-size: var(--nt-text-sm);
  font-weight: var(--nt-weight-medium);
  color: var(--nt-gold);
  background: transparent;
  border: 1px solid var(--nt-gold);
  border-radius: 0;
  text-decoration: none;
  transition: background var(--nt-transition), color var(--nt-transition);
}
.nk-featured-product__cta-secondary:hover,
.nk-featured-product__cta-secondary:active {
  background: var(--nt-gold);
  color: var(--nt-bg);
}
/* Trouvé en validation Phase 1 (28/07) : aucun état focus clavier défini pour ce lien —
   n'a pas la classe .button donc n'hérite pas du contrat générique body.woocommerce a.button:
   focus-visible. Anneau neutre, cohérence avec le CTA primaire (V3 §15/§20 : l'or jamais au focus). */
.nk-featured-product__cta-secondary:focus-visible {
  outline: 2px solid var(--nt-text-strong);
  outline-offset: 2px;
}
/* Kadence "woo-archive-action-on-hover" — mécanisme natif de masquage/décalage au survol,
   neutralisé pour le widget WooCommerce Blocks ("Nouveau dans la boutique", panier vide) UNIQUEMENT.
   La branche `.product-action-wrap` (grille classique ul.products) a été retirée le 28/07
   (reconstruction V3) : vérifié en direct sur le HTML réel de /boutique/ ET /panier/, cette
   classe n'apparaît plus nulle part dans le DOM — le nouveau markup Featured Product
   (content-product.php) ne la génère jamais. Règle devenue morte, supprimée. La branche
   `.wc-block-grid__product-add-to-cart` reste nécessaire et active (confirmé présente sur
   /panier/, widget cross-sell inchangé). !important nécessaire : une règle générique ne peut
   pas répliquer la spécificité exacte de Kadence sans redevenir markup-spécifique. */
.woo-archive-action-on-hover .wc-block-grid__product-add-to-cart {
  position: static !important;
}
@media (hover: none) {
  .woo-archive-action-on-hover .wc-block-grid__product-add-to-cart {
    opacity: 1 !important;
  }
}

/* Bloc Gutenberg "Nouveautés produits" (`wc-block-grid__product-*`) : structure ENTIÈREMENT
   différente de `ul.products` classique (BEM propre aux blocks WooCommerce), utilisé dans le
   panier vide ("Nouveau dans la boutique") et potentiellement d'autres blocks Woo. Titre
   trouvé à 12px sans plafond de lignes → débordait et chevauchait l'image. Même famille de
   gotcha que les pages Blocks panier/commande (cf. [[nooktails-search-drawer-fix]]) : markup
   Blocks ≠ markup classique, jamais couvert par les règles `ul.products`. Repris le même
   traitement (taille dédiée + line-clamp 2) pour cohérence visuelle avec la grille classique. */
/* Le plugin WooCommerce cible `.wc-block-grid__product .wc-block-grid__product-title`
   (2 classes, spécificité 0,2,0) dans son propre CSS (`block-library`) — bat un sélecteur
   simple 1 classe. Repris le même chemin ancestral pour égaler/battre proprement, 0 !important. */
.wc-block-grid__product .wc-block-grid__product-title {
  font-family: var(--nt-font-heading);
  font-weight: var(--nt-weight-medium);
  font-size: clamp(.95rem, 1.3vw, 1.05rem);
  line-height: var(--nt-leading-tight);
  color: var(--nt-text-strong);
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
  overflow-wrap: normal;   /* 26/07 (signalé fondateur, "on voit rien écrit") : Kadence pose
    .entry-content{word-break:break-word} en global -> coupe "Marchepied" en "Marchep/ied" même
    quand le mot tiendrait très bien en entier. Restauré au comportement standard (coupure aux
    espaces uniquement), scopé à ce composant, la règle Kadence reste intacte ailleurs. */
  word-break: normal;
  /* 28/07 (finition premium, demande fondateur) : line-clamp:2 limite la hauteur MAX mais ne
     réserve rien pour un titre plus court (1 ligne) — prix/CTA se décaleraient vers le haut à la
     prochaine fiche courte. min-height en em (pas px) pour suivre le font-size fluide (clamp)
     ci-dessus : 2 lignes à line-height ~1.14 ≈ 2.3em, avec marge de sécurité. Grille verrouillée
     sur 2 lignes quel que soit le texte, sans dépendre du nombre de produits actuel. */
  min-height: 2.3em;
  margin-top: 4px;      /* un peu plus de respiration sous l'image (finition premium) */
  margin-bottom: 10px;  /* était 8px (défaut Kadence) */
}
.wc-block-grid__product .wc-block-grid__product-price {
  font-family: var(--nt-font-ui);
  font-size: var(--nt-text-sm);
  font-weight: var(--nt-weight-semibold);
  color: var(--nt-text-strong);
  margin-bottom: 16px; /* était 13.5px (défaut Kadence) — finition premium, plus de respiration avant le CTA */
}
/* Kadence "woo-archive-action-on-hover" tué À LA RACINE (23/07) : ce mécanisme réapparaissait
   sous 2 markups différents (grille classique `li.product`, bloc Gutenberg
   `.wc-block-grid__product`) et un fix scopé au markup + à la classe body devait être refait
   à chaque nouveau contexte trouvé — whack-a-mole. Remplacé par UNE règle qui cible la CLASSE
   elle-même, sans condition de markup/page : peu importe où Kadence pose cette classe
   (présent ou futur), le shift est neutralisé. !important nécessaire pour battre le style
   inline que Kadence applique parfois via JS au survol (exception documentée, scope
   strictement isolé à cette classe). */
.woo-archive-action-on-hover:hover .entry-content-wrap {
  transform: none !important;
}

/* --------------------------------------------------------------------------
 * 4. CTA / BOUTONS — feutré anthracite/or, ≥44px, pas de bleu/violet Woo
 * ------------------------------------------------------------------------ */
/* D019 (audit 27/07) — le bouton "Se connecter" (.woocommerce-form-login__submit, qui porte
   aussi .button) était happé par cette règle générique : même specificité de classes que la
   règle dédiée de components/woocommerce-myaccount.css, mais 2 éléments (body+button) contre
   1 (body) → cette règle-ci gagnait malgré son chargement plus tôt dans le head. Exclu ici
   plutôt que d'ajouter un !important côté myaccount.css. */
/* Signalé fondateur (capture mobile réelle, boutique) : ce bouton générique utilisait un filet
   --nt-line-strong (#C7BEA8) sur fond --nt-surface-1 (#EAE6DB), quasi invisible sur le fond
   --nt-bg (#F3F1EA) — même famille de tons, delta de contraste minime. Le CTA "Ajouter au panier"
   de la grille boutique passait donc pour du texte nu. Remplacé par LE contrat filet or déjà
   utilisé partout ailleurs sur le site (fiche produit .single_add_to_cart_button, boutons Mon
   compte woocommerce-myaccount.css) : transparent + filet or au repos (contraste --nt-gold
   vérifié 5.18:1 sur Plâtre), remplissage or seulement au survol/actif. Un seul contrat de
   bouton pour toute la partie Woo, pas une règle par écran. */
/* 27/07 (signalé fondateur, capture RÉELLE en navigation privée iPhone — bug persistant après le
   1er fix) : Kadence a son propre style "bouton archive = texte nu" activé par défaut, sur 2
   sélecteurs jumeaux — grille classique `.woocommerce ul.products:not(.woo-archive-btn-button)
   li:where(:not(.woo-archive-btn-button)) .button:not(.kb-button)` (spécificité 0,5,2) et widget
   Blocks (ex. "Nouveau dans la boutique") `.wc-block-grid__product:not(.woo-archive-btn-button)
   .wc-block-grid__product-add-to-cart .wp-block-button__link` (0,4,0) — qui forcent
   background:transparent / border:0 / color:inherit. L'ancien sélecteur `ul.products
   .button.add_to_cart_button` (0,3,1) perdait silencieusement contre Kadence. Corrigé À LA SOURCE
   par la spécificité du sélecteur (pas de !important) : `body.woocommerce ul.products li.product
   .button.add_to_cart_button:not(.kb-button)` monte à (0,6,3), qui bat Kadence sur les 2 axes de
   comparaison (classes puis éléments). Widget Blocks : nouvelle règle dédiée plus bas, même
   principe (ajout de `.ajax_add_to_cart`, classe réellement présente sur ce bouton, pour dépasser
   la spécificité Kadence de ce côté aussi). */
body.woocommerce a.button,
body.woocommerce button.button:not(.woocommerce-form-login__submit),
body.woocommerce input.button,
body.woocommerce #respond input#submit,
body.woocommerce-page a.button,
body.woocommerce-page button.button:not(.woocommerce-form-login__submit) {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 44px;   /* plancher tactile non négociable (doctrine "CTA ≥44px") */
  padding: 12px 22px;
  font-family: var(--nt-font-ui);
  font-size: var(--nt-text-sm);
  font-weight: var(--nt-weight-medium);
  letter-spacing: .02em;
  line-height: 1.2;
  color: var(--nt-gold);
  background: transparent;
  border: 1px solid var(--nt-gold);
  border-radius: 0;   /* DA : coins nets (fondateur 19/07) — était --nt-radius-sm 10px = legacy arrondi Woo */
  box-shadow: none;
  text-decoration: none;
  text-transform: none;
  cursor: pointer;
  transition: background var(--nt-transition), border-color var(--nt-transition), color var(--nt-transition);
}
body.woocommerce a.button:hover,
body.woocommerce button.button:hover:not(.woocommerce-form-login__submit) {
  background: var(--nt-gold);
  border-color: var(--nt-gold);
  color: var(--nt-bg);
}
body.woocommerce a.button:active,
body.woocommerce button.button:active:not(.woocommerce-form-login__submit) {
  background: var(--nt-gold-dark);
  border-color: var(--nt-gold-dark);
  color: var(--nt-bg);
}
/* focus clavier restauré (24/07) : le bouton WooCommerce le plus courant du site (grille boutique,
   fiches, comptes) n'avait AUCUN indicateur de focus — outline:none sans remplacement. */
body.woocommerce a.button:focus-visible,
body.woocommerce button.button:focus-visible:not(.woocommerce-form-login__submit) {
  background: var(--nt-gold);
  border-color: var(--nt-gold);
  color: var(--nt-bg);
  outline: 2px solid var(--nt-text-strong);
  outline-offset: 2px;
}

/* Widget WooCommerce Blocks (ex. "Nouveau dans la boutique" en panier vide) : markup DIFFÉRENT de
   la grille classique — `.wp-block-button__link.add_to_cart_button`, pas de classe `.button` du
   tout — donc la règle ci-dessus ne l'atteint jamais. Même contrat filet or ; spécificité (0,5,0)
   via l'ajout de `.ajax_add_to_cart` pour dépasser la règle Kadence jumelle (0,4,0), sans !important. */
.wc-block-grid__product .wc-block-grid__product-add-to-cart .wp-block-button__link.add_to_cart_button.ajax_add_to_cart {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 44px;   /* plancher tactile non négociable (doctrine "CTA ≥44px") */
  padding: 10px 18px;   /* 27/07 (signalé fondateur, "boutons trop gros") : 22px de padding
    horizontal lisait épais sur une grille à 2 produits (cartes larges). Resserré, min-height
    44px garde le plancher accessibilité identique au contrat golden (fiche produit, Mon Compte). */
  font-family: var(--nt-font-ui);
  font-size: var(--nt-text-sm);
  font-weight: var(--nt-weight-medium);
  letter-spacing: .02em;
  line-height: 1.2;
  color: var(--nt-gold);
  background: transparent;
  border: 1px solid var(--nt-gold);
  border-radius: 0;
  box-shadow: none;
  text-decoration: none;
  text-transform: none;
  cursor: pointer;
  transition: background var(--nt-transition), border-color var(--nt-transition), color var(--nt-transition);
}
.wc-block-grid__product .wc-block-grid__product-add-to-cart .wp-block-button__link.add_to_cart_button.ajax_add_to_cart:hover {
  background: var(--nt-gold);
  border-color: var(--nt-gold);
  color: var(--nt-bg);
}
.wc-block-grid__product .wc-block-grid__product-add-to-cart .wp-block-button__link.add_to_cart_button.ajax_add_to_cart:active {
  background: var(--nt-gold-dark);
  border-color: var(--nt-gold-dark);
  color: var(--nt-bg);
}
.wc-block-grid__product .wc-block-grid__product-add-to-cart .wp-block-button__link.add_to_cart_button.ajax_add_to_cart:focus-visible {
  outline: 2px solid var(--nt-text-strong);
  outline-offset: 2px;
}

/* P0 urgent v2 (28/07, capture iPhone réelle fondateur + diagnostic complet demandé) — cause
   exacte identifiée en remontant toute la chaîne DOM (pas une supposition) : le wrapper
   `.wc-block-grid__product-add-to-cart` porte nativement `padding:0 1rem` (Kadence,
   `.wc-block-grid__product.entry.loop-entry.content-bg.woo-archive-action-on-hover
   .wc-block-grid__product-add-to-cart`), soit 32px pris sur une carte mobile déjà étroite
   (~122px de contenu disponible dans `.product-details`) — il ne restait que ~58px pour le
   texte du bouton, d'où le rendu vertical caractère par caractère.
   v1 (min-width:112px) contournait le symptôme en débordant volontairement du wrapper de
   90px — corrigé à la source : padding retiré au niveau du wrapper (même sélecteur/spécificité
   que la règle Kadence pour le battre proprement), bouton en width:100% de ce wrapper
   maintenant pleine largeur. Aucun débordement, min-height 44px conservé (plancher tactile). */
@media (max-width: 560px) {
  .wc-block-grid__product.entry.loop-entry.content-bg.woo-archive-action-on-hover .wc-block-grid__product-add-to-cart {
    padding: 0;
  }
  .wc-block-grid__product .wc-block-grid__product-add-to-cart .wp-block-button__link.add_to_cart_button.ajax_add_to_cart {
    width: 100%;
    /* 28/07 (finition premium, point 2) : le conteneur (90px) est déjà à 100% d'espace utilisé —
       aucune largeur supplémentaire disponible sans rouvrir le padding de `.product-details`
       (partagé avec titre/prix, décision explicitement mise en pause). Gain sûr : padding
       horizontal resserré 10px→6px, 8px de texte en plus dans la même largeur extérieure. */
    padding: 7px 6px;
    font-size: 11px;
  }
}

/* P2 audit pré-lancement (28/07, signalé fondateur capture mobile réelle "REGARDE LES DEFAULT") :
   le lien "Voir le panier" qui apparaît sous le CTA après ajout (a.added_to_cart.wc-forward)
   n'avait jamais été stylé sur la grille archive — rendu en bleu souligné natif du navigateur.
   Un 2e bouton filet or complet (même contrat que le bandeau .woocommerce-message, cf plus bas)
   serait trop lourd empilé sous le CTA déjà bordé dans une carte étroite (mobile 2 colonnes) :
   simple lien texte or souligné, cohérent avec la couleur du site sans dupliquer le bouton. */
body.woocommerce ul.products li.product a.added_to_cart.wc-forward {
  margin-top: var(--nt-space-xs);
  font-family: var(--nt-font-ui);
  font-size: var(--nt-text-xs);
  font-weight: var(--nt-weight-medium);
  color: var(--nt-gold);
  text-decoration: underline;
  text-underline-offset: 2px;
}
body.woocommerce ul.products li.product a.added_to_cart.wc-forward:hover,
body.woocommerce ul.products li.product a.added_to_cart.wc-forward:focus-visible {
  color: var(--nt-gold-dark);
}

/* --------------------------------------------------------------------------
 * 5. FICHE PRODUIT (single-product)
 * ------------------------------------------------------------------------ */
/* Galerie : photo radius 0, pas d'ombre. */
body.single-product div.product .woocommerce-product-gallery {
  margin-bottom: var(--nt-space-md);
}
body.single-product .woocommerce-product-gallery__image img,
body.single-product .woocommerce-product-gallery img {
  border-radius: 0;
  box-shadow: none;
  border: 0;
}
/* Vignettes de galerie : filet fin, radius 0. */
body.single-product .flex-control-thumbs li img {
  border-radius: 0;
  border: 1px solid transparent;
  transition: border-color var(--nt-transition), opacity var(--nt-transition);
}
body.single-product .flex-control-thumbs li img:hover,
body.single-product .flex-control-thumbs li img.flex-active {
  border-color: var(--nt-gold);
  opacity: 1;
}
/* Loupe zoom galerie = icône or sobre, radius 0 (rapatrié du snippet WPCode #1763,
   19/07 : la règle vit dans le thème, plus en DB). !important = bat le core WooCommerce.
   26/07 (signalé fondateur, "couleur legacy") : la couleur était figée en dur dans le SVG
   (stroke='#c9a878', hex littéral) — un vrai hardcode déguisé, découplé du token si
   --nt-gold change un jour. Passé en masque (mask-image = juste la FORME) + background-color:
   var(--nt-gold) — l'icône suit maintenant vraiment le token, plus de couleur figée. */
body.single-product .woocommerce-product-gallery__trigger {
  background: transparent !important;
  box-shadow: none !important;
  border: 0 !important;
  border-radius: 0 !important;
  width: 34px !important;
  height: 34px !important;
  font-size: 0 !important;
  color: transparent !important;
  background-image: none !important;
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20width='24'%20height='24'%20viewBox='0%200%2024%2024'%20fill='none'%20stroke='%23000'%20stroke-width='2'%20stroke-linecap='round'%20stroke-linejoin='round'%3E%3Ccircle%20cx='11'%20cy='11'%20r='7'/%3E%3Cline%20x1='21'%20y1='21'%20x2='16.65'%20y2='16.65'/%3E%3C/svg%3E") !important;
  mask-image: url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20width='24'%20height='24'%20viewBox='0%200%2024%2024'%20fill='none'%20stroke='%23000'%20stroke-width='2'%20stroke-linecap='round'%20stroke-linejoin='round'%3E%3Ccircle%20cx='11'%20cy='11'%20r='7'/%3E%3Cline%20x1='21'%20y1='21'%20x2='16.65'%20y2='16.65'/%3E%3C/svg%3E") !important;
  -webkit-mask-repeat: no-repeat !important;
  mask-repeat: no-repeat !important;
  -webkit-mask-position: center !important;
  mask-position: center !important;
  -webkit-mask-size: 22px 22px !important;
  mask-size: 22px 22px !important;
  background-color: var(--nt-gold) !important;
  filter: drop-shadow(0 1px 2px rgba(0, 0, 0, .35));
  transition: opacity var(--nt-transition);
}
body.single-product .woocommerce-product-gallery__trigger::before,
body.single-product .woocommerce-product-gallery__trigger::after {
  content: none !important;
  background: none !important;
}
body.single-product .woocommerce-product-gallery__trigger:hover { opacity: .65 !important; }

/* D039 (audit 27/07) — prix + CTA hors du 1er écran mobile : la galerie carrée (1:1, pleine
   largeur) pousse titre/prix/bouton sous la ligne de flottaison. Déjà partiellement mitigé par
   la barre sticky add-to-cart (23/07) ; ici on réduit juste la hauteur initiale de la galerie
   SUR MOBILE UNIQUEMENT (le ratio desktop/tablette n'est pas touché). Crop doux (58vw de haut,
   pas un carré écrasé) via object-fit:cover — la photo reste lisible, le zoom PhotoSwipe/
   FlexSlider (déjà en place) permet de voir l'image complète au tap. */
@media (max-width: 767px) {
  body.single-product .woocommerce-product-gallery__image img {
    max-height: 58vw;
    object-fit: cover;
    object-position: center;
  }
}

/* D039 v2 (28/07, demande fondateur "faire remonter prix/stock/CTA/réassurance") : vérifié en
   direct (mesure DOM réelle à 375px) — la bande de vignettes (7 images × 65px, flex-wrap:wrap)
   retombe sur 2 lignes et pèse 130px, presque autant que l'image principale déjà réduite (215px).
   Seule l'image avait été traitée en 27/07 ; la bande de vignettes ne l'avait jamais été.
   Repassée en défilement horizontal 1 seule ligne (swipe tactile natif, scroll-snap pour un
   calage propre), vignettes resserrées à 48px (zone tactile encore confortable pour une nav
   secondaire, pas un CTA principal) — la ligne de vignettes tombe de 130px à ~56px. Gain net
   cumulé avec le fix image : ~150px de moins avant le prix/stock/CTA, sans rogner l'image plus
   agressivement que le 58vw déjà validé (doctrine "pas de coupe agressive").
   v2-bis : 1re version (`body.single-product .flex-control-thumbs`, 0,2,1) perdait silencieusement
   contre la règle native WooCommerce `.woocommerce div.product div.images .flex-control-thumbs`
   (0,4,2) — vérifié en direct sur le CSS agrégé Autoptimize réel, pas deviné. Le natif pose aussi
   `li:first-child`/`li:nth-child(9){width:65px}` (0,5,3) pour les vignettes de bord. Sélecteur
   aligné sur la même chaîne d'ancêtres exacte + classe `.flex-control-nav` déjà présente sur
   l'élément pour dépasser proprement les deux (0,6,4), 0 !important. */
@media (max-width: 767px) {
  body.single-product.woocommerce div.product div.images .flex-control-nav.flex-control-thumbs {
    flex-wrap: nowrap;
    overflow-x: auto;
    scroll-snap-type: x proximity;
    -webkit-overflow-scrolling: touch;
    padding-bottom: 2px; /* évite que la scrollbar tactile ne colle aux vignettes */
  }
  body.single-product.woocommerce div.product div.images .flex-control-nav.flex-control-thumbs li {
    flex: 0 0 auto;
    width: 48px;
    scroll-snap-align: start;
  }
  body.single-product.woocommerce div.product div.images .flex-control-nav.flex-control-thumbs li img {
    width: 48px;
    height: 48px;
  }
}

/* ====================================================================
   FICHE PRODUIT — composants de CONTENU (source unique, 0 style inline)
   Remplace les encadrés hardcodés en DB (#A8824A / monospace / radius / puces disc)
   des descriptions produit. Anti-IA : filet or COURT en ouverture, pas de boîte,
   pas de rail plein, pas de puce démultipliée. Cf. nooktails-anti-ai-design-tells.
   ==================================================================== */
/* Réponse clé (ex-boîte « question → réponse » en tête de fiche) */
.nk-note {
  position: relative;
  margin: 0 0 2.2rem;
  padding-top: 1.1rem;
}
.nk-note::before {
  content: "";
  position: absolute;
  top: 0;
  inset-inline-start: 0;
  inline-size: 2.4rem;
  block-size: 1px;
  background: var(--nt-gold);
}
.nk-note__q {
  margin: 0 0 .5rem;
  font-family: var(--nt-font-ui);
  font-size: .9rem;
  font-weight: 500;
  color: var(--nt-text-muted);
}
.nk-note__a {
  margin: 0;
  font-family: var(--nt-font-body);
  font-size: 1.05rem;
  line-height: 1.6;
  color: var(--nt-text-strong);
}
.nk-note__a strong { font-weight: 600; color: var(--nt-text-strong); }

/* Avis externes cités (Amazon) — sobre, filet or d'ouverture, pas de boîte */
.nk-reviews {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: 1rem;
  margin: 2rem 0 .4rem;
  padding-top: 1.1rem;
}
.nk-reviews::before {
  content: "";
  position: absolute;
  top: 0;
  inset-inline-start: 0;
  inline-size: 2.4rem;
  block-size: 1px;
  background: var(--nt-gold);
}
.nk-reviews__item {
  margin: 0;
  font-size: .98rem;
  line-height: 1.55;
  color: var(--nt-text-muted);
}
.nk-reviews__item strong { color: var(--nt-text-strong); font-weight: 600; }
.nk-reviews__badge {
  font-family: var(--nt-font-ui);
  font-size: .7rem;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--nt-text-faint);
}

/* Disclaimer / source externe — caption discrète */
.nk-disclaimer {
  margin: 0 0 .5rem;
  font-family: var(--nt-font-ui);
  font-size: .72rem;
  line-height: 1.5;
  color: var(--nt-text-faint);
}

/* Listes de contenu de la description : 1 filet fin sur le BLOC (pas de puce disc par item) */
body.single-product .woocommerce-Tabs-panel--description ul:not(.nk-seealso__list, .nt-litter-compat__list, .nt-receive-block__list, .nt-decision-aid__notice-list) {
  list-style: none;
  margin: 1.4rem 0;
  padding: 0 0 0 1.2rem;
  border-inline-start: 1px solid var(--nt-white-a08);
}
body.single-product .woocommerce-Tabs-panel--description ul:not(.nk-seealso__list, .nt-litter-compat__list, .nt-receive-block__list, .nt-decision-aid__notice-list) li {
  margin: 0 0 .5rem;
  padding: 0;
}
body.single-product .woocommerce-Tabs-panel--description ul:not(.nk-seealso__list, .nt-litter-compat__list, .nt-receive-block__list, .nt-decision-aid__notice-list) li::before { content: none; }

/* ====================================================================
   V2 BOUTIQUE (fondateur 19/07 · verdict designer) — conversion + luxe
   ==================================================================== */
/* V3 (19/07) : le CHEVAUCHEMENT résumé ↔ onglets/related venait du sticky V2 non borné
   (`div.product .summary{position:sticky}` : bloc conteneur = TOUT div.product, qui inclut
   onglets+related → le résumé restait collé par-dessus). Kadence rend la galerie hors des
   hooks WC standard → impossible de wrapper galerie+résumé proprement pour borner le sticky.
   FIX DÉFINITIF = PAS de sticky : layout Kadence 2-col natif (galerie | résumé), onglets +
   related pleine largeur dessous, 0 chevauchement. (Sticky borné = V3.1 si besoin.) */
/* Ancien mécanisme "CTA révélé au survol seulement" (opacity:0 par défaut sur
   a.add_to_cart_button) SUPPRIMÉ (28/07, reconstruction V3) — contraire à la doctrine V3 §8/§22 :
   "jamais un CTA primaire discret. Il peut être sobre, jamais timide." Le nouveau CTA
   (.nk-featured-product__actions .add_to_cart_button) est visible en permanence, sans
   dépendance au survol ni au device (hover/tactile). */

/* Résumé produit : titre serif, prix tabular. */
body.single-product .summary .product_title,
body.single-product h1.product_title.entry-title {
  font-family: var(--nt-font-heading);
  font-weight: var(--nt-weight-semibold);
  font-size: clamp(1.9rem, 3.4vw, 2.375rem);   /* V2 : 38px cap (le 44px rivalisait avec le H1 home) */
  line-height: var(--nt-lh-h1);
  color: var(--nt-text-strong);
  letter-spacing: var(--nt-tracking-heading);
  margin: 0 0 var(--nt-space-sm);
}
body.single-product .summary .price,
body.single-product .summary p.price {
  font-family: var(--nt-font-ui);
  font-size: var(--nt-fs-summary);
  font-weight: var(--nt-weight-semibold);
  color: var(--nt-text-strong);   /* V3-bis luxe : prix NEUTRE (le tarif ne s'affiche pas en or) */
  font-variant-numeric: tabular-nums;
  font-feature-settings: "tnum" 1;
  margin: 0 0 var(--nt-space-md);
}
body.single-product .summary .woocommerce-product-details__short-description {
  font-family: var(--nt-font-body);
  font-size: var(--nt-text-lg);
  color: var(--nt-text);
  line-height: var(--nt-leading-relaxed);
}

/* Disponibilité : feutré, pas de badge criard. */
body.single-product .stock.in-stock {
  font-family: var(--nt-font-ui);
  font-size: var(--nt-text-sm);
  color: var(--nt-text-muted);
}
body.single-product .stock.out-of-stock {
  color: var(--nt-alert);
}

/* Quantité + CTA principal. */
body.single-product form.cart {
  display: flex;
  flex-wrap: wrap;
  align-items: stretch;
  gap: var(--nt-gap-sm);
  margin: var(--nt-space-md) 0;
}
body.single-product .quantity input.qty {
  font-family: var(--nt-font-ui);
  font-variant-numeric: tabular-nums;
  min-height: 44px;
  width: 72px;
  text-align: center;
  color: var(--nt-text);
  background: var(--nt-surface-1);
  border: 1px solid var(--nt-line);
  border-radius: 0;   /* champ quantité : coins nets (était 10px) */
}
/* Stepper +/- (23/07, mandat exécution point 3) — progressive enhancement JS
   (js/nk-quantity-stepper.js) sur le VRAI champ .quantity input.qty ci-dessus : même hauteur/filet,
   0 logique panier dupliquée (le input garde son name="quantity", WooCommerce ne voit aucune
   différence). Le panier (WC Blocks) a déjà son propre stepper natif, non touché ici. */
body.single-product .quantity.nk-qty-stepper {
  display: inline-flex;
  align-items: stretch;
}
body.single-product .quantity.nk-qty-stepper input.qty {
  width: 56px;
  border-left: 0;
  border-right: 0;
  /* Flèches natives du navigateur retirées (23/07, bug signalé) : redondantes avec les
     boutons +/- custom, et trop serrées avec 2 chiffres dans une largeur réduite. */
  -moz-appearance: textfield;
  appearance: textfield;
}
body.single-product .quantity.nk-qty-stepper input.qty::-webkit-outer-spin-button,
body.single-product .quantity.nk-qty-stepper input.qty::-webkit-inner-spin-button {
  -webkit-appearance: none;
  margin: 0;
}
body.single-product .nk-qty-btn {
  min-width: 44px;
  min-height: 44px;
  background: transparent;
  color: var(--nt-text);
  border: 1px solid var(--nt-line);
  font-family: var(--nt-font-ui);
  font-size: var(--nt-text-base);
  line-height: 1;
  cursor: pointer;
  padding: 0;
  transition: background var(--nt-transition), color var(--nt-transition), border-color var(--nt-transition);
}
body.single-product .nk-qty-btn:hover {
  border-color: var(--nt-gold);
  color: var(--nt-gold);
}
body.single-product .nk-qty-btn:active {
  border-color: var(--nt-gold-dark);
  color: var(--nt-gold-dark);
  background: var(--nt-gold-soft);
}
/* focus = distinct du hover (outline, pas juste une couleur) — grammaire d'interaction unique, 24/07 */
body.single-product .nk-qty-btn:focus-visible {
  border-color: var(--nt-gold);
  color: var(--nt-gold);
  outline: 2px solid var(--nt-text-strong);
  outline-offset: 2px;
}
/* Phase 2 (28/07, Commerce Design System V3, composant 08 CTA) : le contrat "filet or" ci-dessous
   (V3-bis luxe, 19/07) est devenu incohérent avec le CTA primaire reconstruit sur l'archive
   (fond --nt-text-strong plein, cf. Featured Product) — trouvé en audit, corrigé pour "une seule
   source de vérité" (demande fondateur explicite). Le bouton "Ajouter au panier" de la fiche
   produit EST le CTA primaire au sens V3 (l'action d'achat directe) : même traitement que
   l'archive, pas un second contrat de bouton propre à cette page. */
body.single-product .single_add_to_cart_button.button.alt,
body.single-product button.single_add_to_cart_button {
  flex: 1 1 auto;
  min-height: 44px;
  padding: 12px 26px;
  font-family: var(--nt-font-ui);
  font-size: var(--nt-text-sm);
  font-weight: 600;
  text-transform: none;
  letter-spacing: .02em;
  color: var(--nt-bg);
  background: var(--nt-text-strong);
  border: 1px solid var(--nt-text-strong);
  border-radius: 0;
  box-shadow: none;
  outline: 0 !important;
  transition: background var(--nt-transition), border-color var(--nt-transition);
}
/* Anneau de focus natif du navigateur au clic (signalé : « cadre » qui apparaît au clic sur
   Ajouter au panier) — jamais neutralisé pour CE bouton précis, Kadence gère ça globalement
   via sa classe body `hide-focus-outline` mais son détecteur JS clavier/souris peut rater
   sur certains devices. Verrou dur explicite, même famille que [[nooktails-search-drawer-fix]]. */
body.single-product .single_add_to_cart_button.button.alt:focus,
body.single-product button.single_add_to_cart_button:focus {
  outline: 0 !important;
  box-shadow: none !important;
}
/* 24/07 : le verrou ci-dessus tuait AUSSI :focus-visible → le bouton "Ajouter au panier"
   (CTA le plus important du site) n'avait plus AUCUN indicateur de focus clavier. On restaure
   :focus-visible seul (ne se déclenche jamais au clic souris, contrairement à :focus) —
   grammaire d'interaction unique, encre neutre. Inchangé par le passage au fond plein (28/07) :
   l'anneau neutre reste correct quel que soit le fond du bouton. */
body.single-product .single_add_to_cart_button.button.alt:focus-visible,
body.single-product button.single_add_to_cart_button:focus-visible {
  outline: 2px solid var(--nt-text-strong) !important;
  outline-offset: 2px;
  box-shadow: none !important;
}
body.single-product .single_add_to_cart_button.button.alt:hover,
body.single-product button.single_add_to_cart_button:hover {
  background: var(--nt-gold-dark);
  border-color: var(--nt-gold-dark);
  color: var(--nt-bg);
}
body.single-product .single_add_to_cart_button.button.alt:active,
body.single-product button.single_add_to_cart_button:active {
  background: var(--nt-gold);
  border-color: var(--nt-gold);
  color: var(--nt-bg);
}
/* Liste de bénéfices (description courte) : PAS de puce disc (fondateur 19/07, anti-IA) →
   filet NEUTRE à gauche qui marque le bloc comme une unité + air entre items. 0 glyphe par item. */
body.single-product .woocommerce-product-details__short-description ul,
body.woocommerce div.product .woocommerce-product-details__short-description ul {
  list-style: none;
  margin: 1.1rem 0 0;
  padding: 0 0 0 1.1rem;
  display: grid;
  gap: .55rem;
  border-inline-start: 1px solid var(--nt-white-a08);
}
body.single-product .woocommerce-product-details__short-description li,
body.woocommerce div.product .woocommerce-product-details__short-description li {
  padding-inline-start: 0;
  color: var(--nt-text);
  line-height: 1.6;
}

/* Méta produit (catégories/tags) MASQUÉE À L'ÉCRAN (23/07, fondateur) : lisait comme un
   2e fil d'Ariane redondant avec le vrai breadcrumb Rank Math juste au-dessus de la page
   (Litière > Bacs à litière > [produit]). Conservée dans le DOM (liens `<a>` intacts,
   crawlables) → 0 perte SEO, juste retirée du rendu visuel. Doctrine "SEO avant UI" respectée :
   masquage, pas suppression. Même technique que `.nk-meta-seo` déjà utilisée ailleurs. */
body.single-product .product_meta {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}

/* Onglets (description / avis) : filet doré actif, serif, anthracite.
   Spécificité renforcée (.woocommerce + div.product ajoutés à la chaîne) : le thème
   parent Kadence pose SA propre règle .woocommerce div.product .woocommerce-tabs
   ul.tabs li (4 classes, boîte grise arrondie) qui battait notre ancienne version
   à 3 classes → tabs rendus en pilule grise par défaut au lieu du filet sobre.
   0 !important (doctrine) : on gagne à la spécificité, à la source. */
/* RYTHME ÉDITORIAL (24/07, composant Core .nt-chapter, cf. 02-components.css) : la fiche
   produit empilait fiche → onglets → produits liés sans respiration. Même recette que
   les genres gelés (06-cluster.css) — repère neutre, pas d'or (fiche produit = pas une
   transition "argent"). */
body.single-product.woocommerce div.product .woocommerce-tabs,
body.single-product .related.products,
body.single-product .upsells.products {
  margin-top: var(--nt-chapter-gap, clamp(2.5rem, 6vw, 4.5rem));
  position: relative;
}
body.single-product.woocommerce div.product .woocommerce-tabs::before,
body.single-product .related.products::before,
body.single-product .upsells.products::before {
  content: "";
  position: absolute;
  top: calc(-1 * var(--nt-chapter-mark-offset, clamp(1.25rem, 3vw, 2.25rem)));
  left: 50%;
  transform: translateX(-50%);
  width: var(--nt-chapter-mark-width, 32px);
  height: 1px;
  background: var(--nt-chapter-mark-color, var(--nt-line-strong));
}
body.single-product.woocommerce div.product .woocommerce-tabs {
  border: 0;
}
body.single-product.woocommerce div.product .woocommerce-tabs ul.tabs {
  border: 0;
  padding: 0;
  margin: 0 0 var(--nt-space-md);
  display: flex;
  flex-wrap: wrap;
  gap: var(--nt-space-md);
  border-bottom: 1px solid var(--nt-line);
}
body.single-product.woocommerce div.product .woocommerce-tabs ul.tabs::before {
  display: none;
}
body.single-product.woocommerce div.product .woocommerce-tabs ul.tabs li {
  background: transparent;
  border: 0;
  border-radius: 0;
  margin: 0;
  padding: 0;
}
body.single-product.woocommerce div.product .woocommerce-tabs ul.tabs li::before,
body.single-product.woocommerce div.product .woocommerce-tabs ul.tabs li::after {
  display: none;
}
body.single-product.woocommerce div.product .woocommerce-tabs ul.tabs li a {
  font-family: var(--nt-font-ui);
  font-size: var(--nt-text-sm);
  font-weight: var(--nt-weight-medium);
  letter-spacing: .04em;
  text-transform: uppercase;
  color: var(--nt-text-muted);
  padding: 0 0 var(--nt-space-sm);
  border-bottom: 2px solid transparent;
  transition: color var(--nt-transition), border-color var(--nt-transition);
}
body.single-product.woocommerce div.product .woocommerce-tabs ul.tabs li.active a,
body.single-product.woocommerce div.product .woocommerce-tabs ul.tabs li a:hover {
  color: var(--nt-text-strong);
  border-bottom-color: var(--nt-gold);
}
body.single-product.woocommerce div.product .woocommerce-tabs ul.tabs li.active {
  background: transparent;
}
/* Un seul onglet (produit sans caractéristiques additionnelles) : la nav à cliquer
   n'a aucune fonction, seul le panneau reste utile. */
body.single-product.woocommerce div.product .woocommerce-tabs ul.tabs:has(li:only-child) {
  display: none;
}
body.single-product .woocommerce-Tabs-panel {
  font-family: var(--nt-font-body);
  font-size: var(--nt-text-lg);
  color: var(--nt-text);
  line-height: var(--nt-leading-relaxed);
}
body.single-product .woocommerce-Tabs-panel h2 {
  font-family: var(--nt-font-heading);
  font-weight: var(--nt-weight-medium);
  font-size: var(--nt-h2);
  color: var(--nt-text-strong);
}

/* Titre section « produits liés / related ». */
body.single-product .related.products > h2,
body.single-product .upsells.products > h2 {
  font-family: var(--nt-font-heading);
  font-weight: var(--nt-weight-semibold);
  font-size: var(--nt-h2);
  color: var(--nt-text-strong);
  margin: var(--nt-space-xl) 0 var(--nt-space-md);
}

/* --------------------------------------------------------------------------
 * 6. NOTES / MESSAGES / BADGES Woo — désamorcer les couleurs criardes
 * ------------------------------------------------------------------------ */
/* Bandeau « ajouté au panier » & co. : PAS de boîte or arrondie (tell anti-DA).
   Traitement V8 sobre = fond surface, UN filet or FIN à gauche, coins nets (radius 0).
   Verrou dur (23/07, même famille que le drawer de recherche cf. [[nooktails-search-drawer-fix]]) :
   contour complet signalé de façon reproductible sur device réel malgré une source déjà
   correcte (confirmé filet-gauche-seul en test Chrome direct) — exception documentée
   !important, scope strictement isolé à ce bandeau. */
/* WooCommerce déplace le focus (a11y) vers .woocommerce-message après un ajout AJAX au
   panier (`$('.woocommerce-message').focus()` dans son propre JS core) — élément focusable
   jamais couvert par un reset outline avant ce round → anneau natif du navigateur autour de
   TOUT le bandeau au moment exact de l'ajout, distinct du fix bouton (round 8). */
body.woocommerce .woocommerce-message,
body.woocommerce .woocommerce-info,
body.woocommerce .woocommerce-notice {
  background: var(--nt-surface-1);
  color: var(--nt-text);
  border-top: 0 !important;
  border-right: 0 !important;
  border-bottom: 0 !important;
  border-inline-start: 1px solid var(--nt-gold) !important;
  border-radius: 0;
  box-shadow: none !important;
  outline: 0 !important;
  font-family: var(--nt-font-ui);
  font-size: var(--nt-text-sm);
}
body.woocommerce .woocommerce-message:focus,
body.woocommerce .woocommerce-info:focus,
body.woocommerce .woocommerce-notice:focus,
body.woocommerce .woocommerce-message:focus-visible,
body.woocommerce .woocommerce-info:focus-visible,
body.woocommerce .woocommerce-notice:focus-visible {
  outline: 0 !important;
  box-shadow: none !important;
}
body.woocommerce .woocommerce-message::before,
body.woocommerce .woocommerce-info::before {
  color: var(--nt-gold);
}
/* Bouton « Voir le panier » dans le bandeau = CTA filet or (transparent, rempli au hover), coins nets. */
body.woocommerce .woocommerce-message .button,
body.woocommerce .woocommerce-message a.wc-forward,
body.woocommerce .woocommerce-info .button {
  background: transparent;
  color: var(--nt-gold);
  border: 1px solid var(--nt-gold);
  border-radius: 0;
  box-shadow: none;
}
body.woocommerce .woocommerce-message .button:hover,
body.woocommerce .woocommerce-message a.wc-forward:hover,
body.woocommerce .woocommerce-info .button:hover {
  background: var(--nt-gold);
  color: var(--nt-bg);
}
body.woocommerce .woocommerce-error {
  background: var(--nt-surface-1);
  color: var(--nt-text);
  border: 0;
  border-inline-start: 1px solid var(--nt-alert);
  border-radius: 0;
  box-shadow: none;
}
/* Badge « promo » : filet doré discret, pas de rond ni gradient. */
body.woocommerce span.onsale {
  font-family: var(--nt-font-ui);
  font-size: var(--nt-text-xs);
  font-weight: var(--nt-weight-medium);
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--nt-bg);
  background: var(--nt-gold);
  border-radius: 0;
  box-shadow: none;
  min-height: auto;
  min-width: auto;
  line-height: 1;
  padding: 6px 10px;
}

/* Notes / étoiles : chiffres tabular. */
body.woocommerce .star-rating span::before {
  color: var(--nt-rating);
}
body.woocommerce .woocommerce-product-rating .count,
body.woocommerce .woocommerce-review-link {
  font-variant-numeric: tabular-nums;
  color: var(--nt-text-muted);
}

/* --------------------------------------------------------------------------
 * 7. RESPONSIVE — tablette + mobile (0 débordement horizontal)
 * ------------------------------------------------------------------------ */
@media (max-width: 768px) {
  body.single-product form.cart {
    gap: var(--nt-gap-sm);
  }
  body.single-product .single_add_to_cart_button.button.alt {
    flex: 1 1 auto;
  }
}

@media (max-width: 480px) {
  body.woocommerce .woocommerce-tabs ul.tabs {
    gap: var(--nt-space-sm);
  }
  body.single-product .woocommerce-tabs ul.tabs li a {
    font-size: var(--nt-text-xs);
  }
}

/* ====================================================================
   RÉASSURANCE sous le CTA (hook functions.php nooktails_reassurance_cta)
   Micro-ligne sobre, items séparés par filet or fin, 0 picto, radius 0.
   ==================================================================== */
.nk-reassurance{
  list-style:none; display:flex; flex-wrap:wrap; align-items:center;
  gap:.4rem 0; margin:1.15rem 0 0; padding:0;   /* column-gap:0 -> le séparateur ::after
    porte SEUL l'espacement horizontal (marges symétriques), plus le gap du conteneur en plus */
  font-family:var(--nt-font-ui); font-size:.8rem; letter-spacing:.01em;
  color:var(--nt-text-muted);
}
.nk-reassurance li{ position:relative; margin:0; padding:0; display:inline-flex; align-items:center; }
.nk-reassurance li::before{ content:none; }
.nk-reassurance li:not(:last-child)::after{
  /* --nt-line (#DED8C8) sur fond --nt-bg (#F3F1EA) = quasi invisible (signalé fondateur,
     fiche produit) -> --nt-text-faint (token prévu pour légendes/séparateurs). Espace ASYMÉTRIQUE
     corrigé (26/07, signalé fondateur) : le gap du conteneur (.85rem) ne s'appliquait qu'APRÈS le
     séparateur, pas avant -> plus d'air après le trait qu'avant. Le séparateur porte maintenant
     seul l'espacement, à égalité des deux côtés (margin-inline symétrique). */
  content:""; inline-size:1px; block-size:.85em; margin-inline:.5rem;
  background:var(--nt-text-faint);
}

/* ====================================================================
   DRAWER PANIER AJAX (25/07, mandat exécution tunnel, lot 1A.3)
   Markup = functions.php (nooktails_cart_drawer_markup), JS = nk-cart-drawer.js.
   z-index/overlay/easing ALIGNÉS sur les drawers Kadence (#mobile-drawer=99999,
   #search-drawer) mais valeurs reprises EN DUR ici — 0 dépendance technique à
   Kadence (cf mémoire nooktails-cart-tunnel-execution-p1). CTA = même contrat que
   .single_add_to_cart_button (28/07 : fond plein --nt-text-strong, V3, plus filet or —
   0 nouveau style de bouton, juste suivi de la mise à jour du contrat source).
   ==================================================================== */
.nt-cart-overlay{
  position:fixed; inset:0; z-index:100001;
  background:rgba(0,0,0,.4); opacity:0; visibility:hidden;
  transition:opacity .22s ease-in-out, visibility 0s .22s;
}
.nt-cart-overlay.is-open{ opacity:1; visibility:visible; transition:opacity .22s ease-in-out; }
.nt-cart-drawer{
  position:fixed; inset-block-start:0; inset-inline-end:0; z-index:100002;
  width:100%; max-width:24rem; max-block-size:100vh; max-block-size:100dvh; overflow-y:auto;
  background:var(--nt-bg); color:var(--nt-text);
  border-inline-start:1px solid var(--nt-line);
  box-shadow:0 0 2rem rgba(0,0,0,.15);
  display:flex; flex-direction:column; gap:.85rem;
  padding:1.4rem clamp(20px,4vw,28px);
  transform:translateX(100%);
  transition:transform .24s cubic-bezier(.77,.2,.05,1);
}
.nt-cart-drawer.is-open{ transform:translateX(0); }
.nt-cart-drawer__head{ display:flex; align-items:center; justify-content:space-between; gap:1rem; margin-block-end:-.2rem; }
.nt-cart-drawer__title{
  margin:0; font-family:var(--nt-font-heading); font-size:1.05rem; font-weight:600; color:var(--nt-text-strong);
}
.nt-cart-drawer__close{
  appearance:none; -webkit-appearance:none; background:transparent; border:0;
  inline-size:44px; block-size:44px; padding:0;
  display:inline-flex; align-items:center; justify-content:center;
  font-size:1.2rem; font-weight:200; line-height:1; color:var(--nt-text-muted); cursor:pointer;
  transition:color var(--nt-transition);
}
/* Kadence applique background/border-radius sur button:focus (spécificité 0,1,1) qui bat
   .nt-cart-drawer__close seul (0,1,0) — même famille que le verrou déjà posé sur
   .single_add_to_cart_button (cf mémoire nooktails-search-drawer-fix). Fix par spécificité
   (pseudo-classes explicites), pas de !important : le JS met le focus ici à chaque ouverture. */
.nt-cart-drawer__close:hover,
.nt-cart-drawer__close:focus,
.nt-cart-drawer__close:active{
  background:transparent; color:var(--nt-gold); box-shadow:none; border-radius:0;
}
.nt-cart-drawer__close:focus-visible{
  outline:1px solid var(--nt-gold); outline-offset:2px;
}
.nt-cart-summary{ display:flex; gap:1rem; align-items:flex-start; }
.nt-cart-summary__img{ inline-size:108px; block-size:108px; object-fit:cover; border:1px solid var(--nt-line); flex-shrink:0; }
.nt-cart-summary__info{ display:flex; flex-direction:column; gap:.25rem; }
.nt-cart-summary__name{
  margin:0; font-family:var(--nt-font-body); font-size:1.05rem; color:var(--nt-text-strong); line-height:1.4;
  display:-webkit-box; -webkit-line-clamp:2; -webkit-box-orient:vertical; overflow:hidden;
}
.nt-cart-summary__qty{ margin:0; font-family:var(--nt-font-ui); font-size:var(--nt-text-sm); color:var(--nt-text-muted); }
.nt-cart-summary__price{ margin:.15rem 0 0; font-family:var(--nt-font-ui); font-size:1rem; font-weight:600; color:var(--nt-text-strong); }
.nt-cart-summary__subtotal{
  display:flex; align-items:baseline; justify-content:space-between;
  margin:0; padding-block-start:1rem; border-block-start:1px solid var(--nt-line);
  font-family:var(--nt-font-ui); font-size:var(--nt-text-xs); letter-spacing:.03em; text-transform:uppercase; color:var(--nt-text-muted);
}
.nt-cart-summary__subtotal-amount{
  font-size:1.15rem; font-weight:600; letter-spacing:normal; text-transform:none; color:var(--nt-text-strong);
}
.nt-cart-drawer__reassure{
  margin:0; margin-block-start:-.25rem; font-family:var(--nt-font-ui); font-size:var(--nt-text-xs); color:var(--nt-text-muted);
}
.nt-cart-drawer__actions{ display:flex; flex-direction:column; gap:.4rem; margin-block-start:-.3rem; }
.nt-cart-drawer__cta{
  display:flex; align-items:center; justify-content:center; text-align:center;
  min-height:44px; padding:12px 26px;
  font-family:var(--nt-font-ui); font-size:var(--nt-text-sm); font-weight:600;
  text-transform:none; letter-spacing:.02em; text-decoration:none;
  border-radius:0; color:var(--nt-bg); background:var(--nt-text-strong); border:1px solid var(--nt-text-strong);
  transition:background var(--nt-transition), border-color var(--nt-transition);
}
.nt-cart-drawer__cta:hover{ background:var(--nt-gold-dark); border-color:var(--nt-gold-dark); }
.nt-cart-drawer__cta:focus-visible{ outline:2px solid var(--nt-text-strong); outline-offset:2px; }
/* Voir le panier = lien texte secondaire, jamais un 2e bouton (2 CTA de même poids = décision
   concurrente juste avant l'achat). min-height 44px = tap target seul, pas de fond/bordure. */
.nt-cart-drawer__secondary{
  display:flex; align-items:center; justify-content:center; text-align:center;
  min-height:44px; padding:4px; border:none; background:none;
  font-family:var(--nt-font-ui); font-size:var(--nt-text-xs); font-weight:400;
  text-transform:none; letter-spacing:.02em; text-decoration:underline; text-underline-offset:3px;
  color:var(--nt-text-muted); transition:color var(--nt-transition);
}
.nt-cart-drawer__secondary:hover{ color:var(--nt-text-strong); }
@media (max-width:560px){
  .nt-cart-drawer{ max-width:none; padding:1.1rem clamp(16px,5vw,22px); }
  .nt-cart-drawer__cta{ min-height:52px; }
}
@media (prefers-reduced-motion: reduce){
  .nt-cart-overlay{ transition:none; }
  .nt-cart-drawer{ transition:none; }
}

/* ====================================================================
   BOUTIQUE (archive) — entête harmonisé au hero éditorial du thème.
   H1 SEO préservé ("Boutique") ; traitement premium : filet or + Fraunces + air.
   ==================================================================== */
/* V3 : le H1 "Boutique" vit dans le HERO KADENCE (.entry-hero .product-archive-title),
   centré par le réglage GLOBAL Kadence des archives (classes title-*-align-inherit).
   → on n'entre pas en guerre de spécificité CSS (ça toucherait toutes les archives) :
   la baseline est CENTRÉE pour matcher le titre → hero cohérent, filet centré (bloc-1).
   Passage left-flush = 1 réglage Kadence Customizer (Archives › Titre › Alignement = Gauche),
   la voie SOURCE ; on basculera alors la baseline à gauche. */
.nk-shop-hero__baseline{
  margin:1rem auto clamp(1.8rem,4vw,2.6rem); max-inline-size:52ch; text-align:center;
  font-family:var(--nt-font-body); font-size:1.02rem; line-height:1.6;
  color:var(--nt-text-muted);
}
/* Hero WooCommerce (26/07, signalé fondateur) : .entry-header.product-archive-title a un
   min-height de 200px qui force TOUT le bloc hero (.hero-container/.entry-hero-container-inner)
   à 200px alors que le H1 ne fait que ~45px -> gros vide avant l'intro/la grille. Règle source
   introuvable dans les feuilles de style accessibles (probablement CSS dynamique Kadence
   Customizer non lisible via cssRules) ; confirmé EMPIRIQUEMENT (override direct de l'élément,
   le vide disparaît). Scopé à product-archive-title (classe déjà spécifique WooCommerce) : ne
   touche PAS le hero des archives de blog (.post-archive-title, cf 05-archives.css). */
.entry-header.product-archive-title{
  min-height:0;
}

/* ====================================================================
   BADGE « Sélection Nooktails » (hook) — sceau éditorial, PAS une pilule.
   Fiche produit uniquement (28/07, reconstruction V3) : l'archive utilise désormais
   .nk-featured-product__kind, rendu directement dans content-product.php, avec sa
   propre taille — l'override archive ci-dessous devenait mort, retiré.
   ==================================================================== */
.nk-selection-badge{
  display:inline-flex; align-items:center;
  font-family:var(--nt-font-ui); font-size:.62rem; font-weight:600;
  letter-spacing:.16em; text-transform:uppercase; color:var(--nt-text-faint);
  margin:0 0 .7rem; background:none; border:0; border-radius:0; padding:0;
}
.nk-selection-badge::before{ content:none; }

/* ====================================================================
   FICHE PRODUIT V2 — « Pourquoi on l'a choisi » (verdict) + « Compléter le coin »
   Registre = revue qui teste. Filet or court, 0 boîte/rail/puce.
   ==================================================================== */
/* V3-bis luxe : plus de filet or (l'air sépare). Label discret, corps sobre. */
.nk-verdict{ margin:2.4rem 0; }
.nk-verdict::before{ content:none; }
.nk-verdict__label{
  margin:0 0 .55rem; font-family:var(--nt-font-ui); font-size:.68rem; font-weight:600;
  letter-spacing:.16em; text-transform:uppercase; color:var(--nt-text-faint);
}
.nk-verdict__body{
  margin:0; font-family:var(--nt-font-body); font-size:1.05rem; line-height:1.65;
  color:var(--nt-text-strong);
}
/* ====================================================================
   V3 (19/07 · spec web designer) — déchrome + cohérence boutique
   ==================================================================== */
/* Ancienne grille dédiée "produits similaires"/upsells (grid-template-columns:repeat(3,1fr))
   RETIRÉE (28/07, reconstruction V3) : forçait un affichage en grille, entrant directement en
   contradiction avec le nouveau composant Featured Product (séquence verticale) désormais
   utilisé par ul.products partout, y compris ici — related/upsells héritent maintenant du
   même composant que l'archive. Un composant "Product Card" compact dédié aux zones related/
   upsell (V3 §c1) est identifié comme prochaine étape (Phase 2, fiche produit), pas encore
   construit dans cette passe. */

/* P3 — Amazon Pay (jaune) / Google Pay = iframes de marque NON restylables → hors fiche produit
   (restent au panier/checkout). Garde-fou si le réglage WooPayments repasse actif. SEO-neutre. */
body.single-product .wcpay-express-checkout-wrapper,
body.single-product .wc-block-components-express-payment--checkout{ display:none; }

/* ====================================================================
   V3-bis LUXE (19/07 · spec designer soustractif) — or démoté, chrome caché
   ==================================================================== */
/* product_meta minimal : catégorie en caption grise ; UGS + mur d'étiquettes MASQUÉS
   à l'écran mais CONSERVÉS dans le DOM (.nk-meta-seo) → SEO/schema intacts. */
.nk-meta{
  font-family:var(--nt-font-ui); font-size:.72rem; letter-spacing:.02em;
  color:var(--nt-text-faint); margin:1.6rem 0 0;
}
.nk-meta a{ color:var(--nt-text-faint); text-decoration:none; }
.nk-meta a:hover{ color:var(--nt-gold); }   /* or au HOVER seulement */
.nk-meta-seo{
  position:absolute; width:1px; height:1px; padding:0; margin:-1px;
  overflow:hidden; clip:rect(0 0 0 0); white-space:nowrap; border:0;
}

/* Fil d'Ariane (Rank Math) harmonisé sobre : gris faible, séparateur discret, or au hover only.
   24/07 : --nt-text-faint (2.42:1) rendait le fil d'Ariane quasi invisible au repos sur TOUTES
   les pages produit → --nt-text-muted (4.66:1, AA) — grammaire d'interaction unique. */
body.single-product .rank-math-breadcrumb,
body.woocommerce .rank-math-breadcrumb{
  font-family:var(--nt-font-ui); font-size:var(--nt-text-xs);
  color:var(--nt-text-muted); letter-spacing:.02em;
}
body.woocommerce .rank-math-breadcrumb a{
  color:var(--nt-text-muted); text-decoration:none; transition:color var(--nt-transition);
}
body.woocommerce .rank-math-breadcrumb a:hover{ color:var(--nt-gold); }
body.woocommerce .rank-math-breadcrumb a:active{ color:var(--nt-gold-dark); }
body.woocommerce .rank-math-breadcrumb a:focus-visible{ outline:2px solid var(--nt-text-strong); outline-offset:2px; }
body.woocommerce .rank-math-breadcrumb .separator{ opacity:.4; margin:0 .5rem; color:var(--nt-text-faint); }
body.woocommerce .rank-math-breadcrumb .last{ color:var(--nt-text-muted); }

/* ====================================================================
   PANIER / COMMANDE (WooCommerce Blocks) — habillage maison à la source
   Panier et commande tournent en Blocks Gutenberg, pas le template
   classique : 0 classe .woocommerce nue, markup .wc-block-*. Sans ce
   bloc, les boutons héritent du style bouton GLOBAL Kadence
   (button, .wp-block-button__link, .wp-element-button →
   background:var(--global-palette-btn-bg), qui vaut l'or du thème →
   aplat or + radius 3px) et les champs restent au blanc natif WooCommerce.
   Repris ici le contrat CTA filet or (cf. .single_add_to_cart_button
   plus haut) pour cohérence de marque. Spécificité 2 classes bat le
   sélecteur global Kadence sans !important.
   ==================================================================== */
/* Phase 3 (28/07, Commerce Design System V3, composant 08 CTA) : trouvé en audit — 3e occurrence
   du contrat filet-or pré-V3, incohérente avec le CTA archive/fiche produit/drawer déjà unifiés
   en fond --nt-text-strong plein. Ce sélecteur couvre panier ET checkout ensemble (même règle
   d'origine) : mis à jour pour les deux en une fois plutôt que de dupliquer la règle en deux
   copies qui se désynchroniseraient visuellement — contredirait justement le principe de source
   unique. Checkout reste hors périmètre fonctionnel de la Phase 3 (React/Blocks, risque à part,
   cf. Phase 4) ; seul CE style de bouton, déjà partagé, est concerné ici. */
body.woocommerce-cart .wc-block-cart__submit-button,
body.woocommerce-checkout .wc-block-components-checkout-place-order-button {
  background: var(--nt-text-strong);
  border: 1px solid var(--nt-text-strong);
  border-radius: 0;
  color: var(--nt-bg);
  font-family: var(--nt-font-ui);
  font-weight: 600;
  box-shadow: none;
  transition: background var(--nt-transition), border-color var(--nt-transition);
}
/* Taille — le contrat couleur ci-dessus n'écrase pas la taille par défaut WC Blocks
   (variante "contained" : 54px/18px, très au-dessus du contrat bouton du site
   44px/--nt-text-sm, cf. .single_add_to_cart_button). Signalé "énorme" 23/07. */
body.woocommerce-cart .wc-block-cart__submit-button,
body.woocommerce-checkout .wc-block-components-checkout-place-order-button {
  min-height: 44px;
  height: auto;
  padding: 12px 26px;
  font-size: var(--nt-text-sm);
}
body.woocommerce-cart .wc-block-cart__submit-button:hover,
body.woocommerce-checkout .wc-block-components-checkout-place-order-button:hover {
  background: var(--nt-gold-dark);
  border-color: var(--nt-gold-dark);
  color: var(--nt-bg);
}
body.woocommerce-cart .wc-block-cart__submit-button:active,
body.woocommerce-checkout .wc-block-components-checkout-place-order-button:active {
  background: var(--nt-gold);
  border-color: var(--nt-gold);
  color: var(--nt-bg);
}
body.woocommerce-cart .wc-block-cart__submit-button:focus-visible,
body.woocommerce-checkout .wc-block-components-checkout-place-order-button:focus-visible {
  outline: 2px solid var(--nt-text-strong);
  outline-offset: 2px;
}
/* Pictogramme "panier vide" (bonhomme triste natif WooCommerce Blocks) RETIRÉ (23/07) :
   `.wc-block-cart__empty-cart__title.with-empty-cart-icon::before` pose une icône via
   `mask-image` (SVG base64) + `background-color` — pas une image DOM, un pseudo-élément
   décoratif. Interdit strict doctrine anti-IA (0 emoji, 0 picto déco). Texte seul suffit. */
body.woocommerce-cart .wc-block-cart__empty-cart__title.with-empty-cart-icon::before {
  display: none;
}
/* Séparateur "•••" (bloc Gutenberg natif `is-style-dots`, pas Kadence) RETIRÉ (23/07) :
   3 points décoratifs sous "Panier vide" — interdit anti-IA. Converti en filet sobre,
   même contrat que `.nk-decision .nk-prose hr` (06-cluster.css) : ligne fine, pas de puce. */
body.woocommerce-cart .wp-block-woocommerce-empty-cart-block .wp-block-separator.is-style-dots {
  background: none;
  border: 0;
  border-top: 1px solid var(--nt-line);
  height: 0;
  max-width: 6rem;
  margin: var(--nt-space-lg) auto;
}
body.woocommerce-cart .wp-block-woocommerce-empty-cart-block .wp-block-separator.is-style-dots::before {
  content: none;
}

/* Cartes "Nouveau dans la boutique" (panier vide, bloc natif Gutenberg wp-block-product-new) —
   28/07, Lot Final CRO (fondateur, capture réelle DevTools 390px). Boutons/titres natifs
   WooCommerce quasi illisibles (bouton 7px/6px de padding, 11px de police ; titre 11,25px,
   0 line-clamp -> wrap sur 4 lignes dans une carte de 141px). Scope strict à ce bloc
   (.wp-block-woocommerce-empty-cart-block) : ne touche ni les cartes Featured Product de la
   boutique (déjà validées), ni aucun autre usage du bloc "Nouveau" ailleurs sur le site. */
/* Spécificité : une règle déjà existante plus haut dans ce même fichier (P0 cross-sell mobile,
   25/07) cible ce bouton via .wc-block-grid__product .wc-block-grid__product-add-to-cart
   .wp-block-button__link.add_to_cart_button.ajax_add_to_cart (5 classes, non scopée à une
   page précise — s'applique à tout widget Blocks "grille produits" du site). Notre règle
   reprend exactement la même chaîne de classes pour être certaine de gagner, préfixée par le
   scope empty-cart : aucune autre occurrence de ce widget sur le site n'est affectée. */
body.woocommerce-cart .wp-block-woocommerce-empty-cart-block .wc-block-grid__product .wc-block-grid__product-add-to-cart .wp-block-button__link.add_to_cart_button.ajax_add_to_cart {
  padding: 12px 16px;
  font-size: 15px;
}
body.woocommerce-cart .wp-block-woocommerce-empty-cart-block .wc-block-grid__product-title-link {
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
  overflow: hidden;
}

/* Paiement express — compact (28/07, Lot Final CRO, fondateur). Cible uniquement le wrapper
   <li> natif WooCommerce Blocks autour du bouton Apple/Google Pay (jamais l'iframe SDK à
   l'intérieur) et le séparateur "OU". Scope panier + checkout : les deux pages partagent
   les mêmes classes publiques Blocks.
   Spécificité : blocks-checkout.css (WooCommerce, chargé après notre thème) définit déjà
   .wc-block-components-express-payment--cart/--checkout .wc-block-components-express-payment__
   event-buttons > li (0,2,1) et .continue-rule--cart/--checkout (0,1,0) — nos sélecteurs
   génériques précédents étaient à égalité ou en dessous et perdaient sur l'ordre de source.
   On reprend les variantes --cart/--checkout exactes, préfixées body.woocommerce-*, pour
   gagner sans !important. */
body.woocommerce-cart .wc-block-components-express-payment--cart .wc-block-components-express-payment__event-buttons > li:not(:last-child),
body.woocommerce-checkout .wc-block-components-express-payment--checkout .wc-block-components-express-payment__event-buttons > li:not(:last-child) {
  padding-bottom: 8px;
}
body.woocommerce-cart .wc-block-components-express-payment-continue-rule--cart {
  margin: 16px 0;
}
body.woocommerce-checkout .wc-block-components-express-payment-continue-rule--checkout {
  margin: 16px 0;
}

/* input[type] : WooCommerce définit sa propre variante scopée .wc-block-components-form
   (specificité 0,3,1) plus précise qu'un simple ".wc-block-components-text-input input"
   (0,2,2) — on égale sa liste de types, préfixée body, pour gagner sans !important. */
body.woocommerce-checkout .wc-block-components-text-input input[type="email"],
body.woocommerce-checkout .wc-block-components-text-input input[type="number"],
body.woocommerce-checkout .wc-block-components-text-input input[type="password"],
body.woocommerce-checkout .wc-block-components-text-input input[type="tel"],
body.woocommerce-checkout .wc-block-components-text-input input[type="text"],
body.woocommerce-checkout .wc-block-components-text-input input[type="url"],
body.woocommerce-checkout .wc-block-components-text-input textarea {
  background: var(--nt-surface-1);
  border: 1px solid var(--nt-line);
  border-radius: 0;
  color: var(--nt-text);
}
body.woocommerce-checkout .wc-block-components-text-input input[type="email"]:focus,
body.woocommerce-checkout .wc-block-components-text-input input[type="number"]:focus,
body.woocommerce-checkout .wc-block-components-text-input input[type="password"]:focus,
body.woocommerce-checkout .wc-block-components-text-input input[type="tel"]:focus,
body.woocommerce-checkout .wc-block-components-text-input input[type="text"]:focus,
body.woocommerce-checkout .wc-block-components-text-input input[type="url"]:focus,
body.woocommerce-checkout .wc-block-components-text-input textarea:focus {
  border-color: var(--nt-gold);
  outline: none;
}

/* Lien "Politique de confidentialité" (CGV checkout) — jamais rethémé, tournait sur
   le lien Kadence brut (a{color:var(--global-palette-highlight)}, global.min.css),
   d'où l'or permanent au repos. Contrat repris : encre neutre au repos, or réservé
   au hover (même convention que .nt-guide/.nk-decision — l'or ne s'affiche jamais
   en continu, doctrine palette "or RARE"). */
body.woocommerce-checkout .wc-block-checkout__terms a {
  color: var(--nt-text-strong);
  text-decoration: underline;
  text-decoration-color: var(--nt-line);
  transition: color var(--nt-transition);
}
body.woocommerce-checkout .wc-block-checkout__terms a:hover {
  color: var(--nt-gold);
  text-decoration-color: var(--nt-gold);
}
body.woocommerce-checkout .wc-block-checkout__terms a:focus-visible {
  outline: 2px solid var(--nt-text-strong);
  outline-offset: 2px;
}

/* Bouton "Appliquer" (code promo, panier ET checkout) — jamais rethémé, tournait
   sur le reset bouton générique Kadence (aplat or plein, radius 3px, cf. mémoire
   nooktails-panier-checkout-premium-cleanup point 4, même famille de bug déjà
   corrigée sur le bouton "Commander" du mini-panier). Repris ici le contrat CTA
   filet or (cf. .wc-block-components-checkout-place-order-button plus haut).
   État désactivé (avant saisie d'un code) rendu explicitement sobre plutôt que
   l'aplat or plein qui donnait l'impression fausse d'un bouton actif. Hauteur
   alignée avec le champ juste à côté (44px, contrat site). */
body.woocommerce-cart .wc-block-components-totals-coupon__button,
body.woocommerce-checkout .wc-block-components-totals-coupon__button {
  background: transparent;
  border: 1px solid var(--nt-gold);
  border-radius: 0;
  color: var(--nt-gold);
  font-family: var(--nt-font-ui);
  font-weight: 500;
  box-shadow: none;
  min-height: 44px;
  height: auto;
  padding: 12px 26px;
  font-size: var(--nt-text-sm);
  transition: background var(--nt-transition), color var(--nt-transition), border-color var(--nt-transition);
}
body.woocommerce-cart .wc-block-components-totals-coupon__button:hover:not(:disabled),
body.woocommerce-checkout .wc-block-components-totals-coupon__button:hover:not(:disabled) {
  background: var(--nt-gold);
  border-color: var(--nt-gold);
  color: var(--nt-bg);
}
body.woocommerce-cart .wc-block-components-totals-coupon__button:disabled,
body.woocommerce-checkout .wc-block-components-totals-coupon__button:disabled {
  border-color: var(--nt-line);
  color: var(--nt-text-faint);
  cursor: not-allowed;
}
body.woocommerce-cart .wc-block-components-totals-coupon__button:focus-visible,
body.woocommerce-checkout .wc-block-components-totals-coupon__button:focus-visible {
  outline: 2px solid var(--nt-text-strong);
  outline-offset: 2px;
}
body.woocommerce-cart .wc-block-components-totals-coupon .wc-block-components-text-input input,
body.woocommerce-checkout .wc-block-components-totals-coupon .wc-block-components-text-input input {
  min-height: 44px;
}

/* ============================================================================
   CHECKOUT MOBILE — rythme vertical (25/07, mandat exécution tunnel, lot 1A.4)
   Vide de ~116px mesuré en direct entre le header et « Résumé de la commande »
   (412px réel) : pas 1 élément fautif, empilement de 4 paddings/marges de
   conteneurs imbriqués (thème → WooCommerce Blocks). Réduit uniquement sur
   cette page (body.woocommerce-checkout), aucun autre gabarit concerné.
   Aucun hook/JS/iframe touché — CSS de rythme seulement.
   ============================================================================ */
@media (max-width: 768px) {
  body.woocommerce-checkout .entry-content-wrap {
    padding-block-start: 8px;
  }
  body.woocommerce-checkout .wp-block-woocommerce-checkout {
    padding-block-start: 12px;
  }
  body.woocommerce-checkout .wc-block-components-checkout-order-summary__title {
    margin-block-start: 8px;
  }
}
/* Montant "819,90 €" qui déborde du cadre au clic sur "Résumé de la commande" (mobile réel
   412px) : le prix (white-space:nowrap, non négociable) porte flex-shrink:1 alors que sa
   propre valeur ne peut PAS rétrécir (texte non-wrappable) -> à espace insuffisant, il
   déborde du conteneur au lieu de wrapper. Fix = protéger le prix (flex-shrink:0, jamais
   compressé) et laisser le libellé (wrappable) absorber la contrainte de largeur. */
body.woocommerce-checkout .wc-block-components-checkout-order-summary__title-price {
  flex-shrink: 0;
}
body.woocommerce-checkout .wc-block-components-checkout-order-summary__title-text {
  min-width: 0;
}
/* Même bug, ligne d'article du résumé (pas l'en-tête) : le prix total de la ligne
   (white-space:normal, flex-shrink:1) se retrouve écrasé en colonne verticale de chiffres
   dès que la quantité fait grimper le montant (ex. "1 739,70 €" pour 6 unités, testé/
   simulé en direct : largeur réduite à 12px, hauteur multipliée par ~4). Même fix : prix
   protégé (nowrap + flex-shrink:0), le nom produit (déjà wrappable) absorbe la contrainte. */
body.woocommerce-checkout .wc-block-components-order-summary-item__total-price {
  flex-shrink: 0;
  white-space: nowrap;
}
body.woocommerce-checkout .wc-block-components-order-summary-item__description {
  min-width: 0;
}

/* ============================================================================
   CHECKOUT — header simplifié (25/07, lot 1A.5 — v2 À LA SOURCE)
   v1 masquait recherche/panier/hamburger en CSS display:none (rustine, gardait
   le markup complet en DOM). Remplacé par remove_action/add_action sur les
   hooks Kadence natifs (kadence_header_search, kadence_navigation_popup_toggle,
   kadence_header_cart, kadence_mobile_cart — functions.php, is_checkout()) :
   recherche/hamburger retirés à la source, panier REMPLACÉ par le lien
   « Retour au panier » exactement à sa position (0 positionnement CSS custom,
   hérite du layout flex/grid natif du header). Seul style restant ici =
   l'apparence du lien lui-même (le markup n'existe nulle part ailleurs).
   ============================================================================ */
.nt-checkout-back-link {
  font-family: var(--nt-font-ui);
  font-size: var(--nt-text-sm);
  color: var(--nt-text-muted);
  text-decoration: none;
  white-space: nowrap;
  transition: color var(--nt-transition);
}
.nt-checkout-back-link:hover {
  color: var(--nt-gold);
}

/* ============================================================================
   PANIER + CHECKOUT — doublon devise sur le Total (25/07, durci 25/07 audit P1)
   WooCommerce Blocks ajoute un nœud texte brut " EUR" après le montant sur la
   ligne Total UNIQUEMENT (composant TotalsFooterItem, absent de Sous-total/
   Livraison — structure différente confirmée en direct : Sous-total = span nu,
   Livraison = <strong>Gratuit</strong>, aucun des deux n'a ce texte). Même
   composant réutilisé sur /panier/ ET /commander/ (repéré d'abord sur checkout,
   confirmé ensuite présent aussi sur panier — "Total estimé 429,95 € EUR").
   Confirmé injecté CÔTÉ CLIENT (JS, hydratation React du bloc) : absent du HTML
   brut servi par le serveur (vérifié via curl avec session/cookies) — donc pas
   de filtre PHP à corriger à la source ici, contrairement aux emails.
   Un nœud texte brut n'est pas ciblable en CSS -> technique : `visibility:hidden`
   sur le conteneur + `visibility:visible` restauré sur le montant. PRÉFÉRÉ à
   `font-size:0` (utilisé initialement) : `font-size:0` rendait le texte
   invisible à l'écran MAIS il restait dans `innerText`/sélectionnable au clic
   (copier-coller du prix révélait encore "429,95 € EUR" — trouvé lors de
   l'audit P1 pré-lancement, 25/07). `visibility:hidden` corrige ça : plus dans
   `innerText`, plus sélectionnable. Comportement des lecteurs d'écran non
   garanti au-delà de ça (varie selon navigateur/AT, non testable dans cet
   environnement) — traiter comme une amélioration réelle mais pas une preuve
   d'accessibilité totale. Fix propre à la source (empêcher le JS d'injecter le
   texte) resterait préférable à moyen terme si le point d'accroche du script
   tiers est identifié un jour. */
body.woocommerce-cart .wc-block-components-totals-item__value:has(.wc-block-components-totals-footer-item-tax-value),
body.woocommerce-checkout .wc-block-components-totals-item__value:has(.wc-block-components-totals-footer-item-tax-value) {
  visibility: hidden;
}
body.woocommerce-cart .wc-block-components-totals-footer-item-tax-value,
body.woocommerce-checkout .wc-block-components-totals-footer-item-tax-value {
  visibility: visible;
}

/* Extrait produit tronqué en plein mot dans le panier/checkout (25/07, audit CRO P2).
   WooCommerce Blocks (React, Store API) tronque wc-block-components-product-metadata__description
   à un nombre de caractères FIXE, quel que soit le contenu ou la largeur d'écran — vérifié en
   testant un texte totalement différent et plus court : coupé au même endroit ("Litière automati…").
   Comportement du cœur WooCommerce Blocks, pas du thème — aucun fix PHP propre possible sans
   patcher le plugin. Le champ "Résumé" (short_description) de chaque produit n'apporte aucune
   information que la carte produit (nom, image, prix) ne donne déjà — masqué plutôt que laissé
   dans un état visuellement cassé. */
body.woocommerce-cart .wc-block-components-product-metadata__description,
body.woocommerce-checkout .wc-block-components-product-metadata__description {
  display: none;
}

/* Réassurance sous le CTA "Commander" (25/07, audit CRO P2 — refait 26/07 à la source).
   v1 générait le texte en CSS (::after{content:"..."}), fragile : un bug d'échappement \A
   a réellement cassé le texte en prod ("NPaiement"/"NRetours"), et un middot "·" dans une
   chaîne wrappe au hasard sur mobile (pas de contrôle de coupure). Remplacé par une vraie
   insertion DOM (js/nk-checkout-reassurance.js, Slot/Fill ExperimentalOrderMeta) qui rend
   EXACTEMENT le même markup <ul class="nk-reassurance"><li> que la fiche produit
   (nooktails_reassurance_cta, functions.php) : le wrap mobile est géré par flex-wrap, pas
   par du texte. Seul ajout ici = le centrage (la version produit est alignée à gauche). */
.nk-reassurance--checkout {
  justify-content: center;
  margin-block-start: 0.85rem;
}

/* ====================================================================
   PANIER — LARGEUR (28/07, Lot 3A, fondateur)
   --------------------------------------------------------------------
   Même racine que le "grand vide à droite" déjà corrigée sur la fiche produit
   (cf. plus haut dans ce fichier, .woocommerce-Tabs-panel--description:has(...)) :
   .entry-content{max-width:var(--nt-prose)} (65ch ≈ 589px) est une règle SITE-WIDE
   pensée pour la largeur de lecture des articles — elle capture aussi le conteneur
   du Cart Block sur /panier/, qui dispose pourtant de ~1242px réels (entry-content-wrap).
   Le Cart Block a sa propre grille interne 2 colonnes (zone produits / récapitulatif),
   actuellement display:block faute de largeur suffisante pour s'exprimer. Ce fix ne
   RECONSTRUIT rien : il libère le conteneur et laisse la mise en page native de
   WooCommerce Blocks s'activer d'elle-même. Scope strict body.woocommerce-cart —
   n'affecte aucune page éditoriale, ni le checkout, ni le compte client. */
body.woocommerce-cart .entry-content.single-content {
  max-width: var(--nt-container, 1160px);
}

/* Réassurance panier (28/07, Phase 3 V3, audit) — l'essai Slot/Fill DANS le Cart Block
   (.nk-reassurance--cart, scope 'woocommerce-cart') ne rendait jamais rien en pratique
   (limite documentée, nooktails_cart_reassurance_content, functions.php). Remplacé par ce
   même bloc rendu côté serveur (functions.php, insertion juste avant le marqueur
   wp-block-woocommerce-cart), donc déjà collé au panier dans le DOM.
   28/07 Lot 3A (fondateur, retour visuel post-audit) : le filet de séparation + la marge de
   34px + le padding de 22px le faisaient lire comme un bandeau de PAGE autonome plutôt que
   comme un élément rattaché à la décision d'achat. Retiré le filet, réduit marge/padding à
   des valeurs d'espacement interne (space-sm/space-2xs) plutôt que des valeurs de séparation
   de section, et baissé d'un cran la hiérarchie typo (text-xs + text-faint, au lieu du
   text-muted hérité de .nk-reassurance) — modifs scopées à CETTE variante uniquement, la
   base .nk-reassurance (fiche produit) et .nk-reassurance--checkout ne sont pas touchées. */
.nk-reassurance--cart-page {
  justify-content: center;
  max-width: var(--nt-container, 1160px);
  margin: 0 auto var(--nt-space-sm);
  padding: var(--nt-space-2xs) 0;
  font-size: var(--nt-text-xs);
  color: var(--nt-text-faint);
}

/* Même bug "EUR" dupliqué, page "Commande reçue" (25/07) — mais template CLASSIQUE
   WooCommerce (thankyou.php, pas WooCommerce Blocks), markup différent : pas de
   wc-block-*, texte "EUR" brut à côté de .woocommerce-Price-amount dans
   .woocommerce-order-overview__total ET la ligne Total du tableau détails (tfoot,
   avant-dernière ligne — "Moyen de paiement" toujours en dernier, ordre natif
   WooCommerce). Même durcissement `visibility` (25/07 audit P1) — voir commentaire
   ci-dessus, non re-confirmé en direct côté serveur/client pour cette page précise
   (pas de commande de test disponible au moment de l'audit) mais appliqué par
   cohérence/précaution, aucun risque de régression visuelle. */
body.woocommerce-order-received .woocommerce-order-overview__total.total strong {
  visibility: hidden;
}
body.woocommerce-order-received .woocommerce-order-overview__total.total strong .woocommerce-Price-amount {
  visibility: visible;
}
body.woocommerce-order-received table.woocommerce-table--order-details tfoot tr:nth-last-child(2) td {
  visibility: hidden;
}
body.woocommerce-order-received table.woocommerce-table--order-details tfoot tr:nth-last-child(2) td .woocommerce-Price-amount {
  visibility: visible;
}

/* ============================================================================
   DÉTAIL DE COMMANDE — order-received (confirmation) + view-order (Mon Compte)
   (28/07, signalé fondateur — capture mobile réelle). Les deux pages partagent
   le même template natif WooCommerce (order/order-details.php) et n'avaient
   JAMAIS reçu de style : rendu 100% défaut navigateur/Kadence (titres non
   stylés, tableau sans filet, adresses en texte brut). Titres repris à
   l'identique de woocommerce-myaccount.css (body.woocommerce-account
   .woocommerce > h2) pour rester cohérent avec le reste du compte. 100% tokens,
   0 hex. Puces de liste par défaut retirées (rondes = tell générique/IA,
   signalé fondateur) → marqueur tiret sobre --nt-text-faint, cohérent avec les
   filets hairline déjà utilisés ailleurs (pas d'or : réservé aux accents rares). */
body.woocommerce-order-received h2,
body.woocommerce-view-order h2 {
  font-family: var(--nt-font-heading);
  font-weight: var(--nt-weight-semibold);
  font-size: clamp(1.4rem, 2.6vw, 1.75rem);
  color: var(--nt-text-strong);
  margin: var(--nt-space-xl) 0 var(--nt-space-md);
}
body.woocommerce-order-received h3,
body.woocommerce-view-order h3 {
  font-family: var(--nt-font-heading);
  font-weight: var(--nt-weight-semibold);
  font-size: var(--nt-text-lg);
  color: var(--nt-text-strong);
  margin: 0 0 var(--nt-space-sm);
}
body.woocommerce-order-received table.woocommerce-table--order-details,
body.woocommerce-view-order table.woocommerce-table--order-details {
  width: 100%;
  border-collapse: collapse;
  font-family: var(--nt-font-body);
  font-size: var(--nt-text-sm);
  color: var(--nt-text);
  margin: 0 0 var(--nt-space-lg);
}
@media (max-width: 480px) {
  /* Filet de sécurité mobile (doctrine site) : un nom de produit long ("Furoomate
     PCT110 – Litière automatique autonettoyante...") peut forcer la colonne au-delà
     de 320px de large. Scroll horizontal isolé À la table, jamais à la page. */
  body.woocommerce-order-received table.woocommerce-table--order-details,
  body.woocommerce-view-order table.woocommerce-table--order-details {
    display: block;
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
  }
}
/* Cellules (29/07, polish qualité perçue, signalé fondateur sur capture) : padding
   remonté de --nt-space-sm (14px) à --nt-space-md (22px) pour plus de respiration —
   demande explicite "18-24px". Séparateur retiré entre les lignes PRODUIT
   (tbody) — gardé seulement entre groupes logiques (avant/après tfoot) — pour
   un effet "allégé" sans introduire un 2e ton de filet (le fondateur avait
   demandé un filet unique il y a 2 passes ; alléger = réduire où il apparaît,
   pas créer une variante plus claire). CSS uniquement, 0 changement de HTML. */
body.woocommerce-order-received table.woocommerce-table--order-details th,
body.woocommerce-order-received table.woocommerce-table--order-details td,
body.woocommerce-view-order table.woocommerce-table--order-details th,
body.woocommerce-view-order table.woocommerce-table--order-details td {
  padding: var(--nt-space-md);
  border-bottom: none;
  text-align: left;
}
body.woocommerce-order-received table.woocommerce-table--order-details thead th,
body.woocommerce-view-order table.woocommerce-table--order-details thead th {
  border-bottom: 1px solid var(--nt-line);
}
body.woocommerce-order-received table.woocommerce-table--order-details tbody tr,
body.woocommerce-view-order table.woocommerce-table--order-details tbody tr {
  border-bottom: 1px solid var(--nt-line);
}
body.woocommerce-order-received table.woocommerce-table--order-details th,
body.woocommerce-view-order table.woocommerce-table--order-details th {
  font-family: var(--nt-font-ui);
  font-size: var(--nt-text-xs);
  letter-spacing: .02em;
  text-transform: uppercase;
  color: var(--nt-text-faint);
  font-weight: 500;
}
/* Hiérarchie tfoot (29/07) : sous-total/livraison discrets (taille réduite,
   même famille --nt-text-muted déjà utilisée ailleurs pour du texte secondaire
   — pas une couleur nouvelle), total nettement plus présent. Le tri
   ligne-avant-dernière/dernière reprend la logique déjà en place plus haut
   dans ce fichier (masquage du doublon "Total" natif WooCommerce). */
body.woocommerce-order-received table.woocommerce-table--order-details tfoot td,
body.woocommerce-view-order table.woocommerce-table--order-details tfoot td {
  font-weight: 500;
  border-top: 1px solid var(--nt-line);
  border-bottom: none;
}
body.woocommerce-order-received table.woocommerce-table--order-details tfoot tr:not(:last-child) td,
body.woocommerce-view-order table.woocommerce-table--order-details tfoot tr:not(:last-child) td {
  font-size: var(--nt-text-sm);
  font-weight: 400;
  color: var(--nt-text-muted);
  border-top: none;
}
body.woocommerce-order-received table.woocommerce-table--order-details tfoot tr:last-child td,
body.woocommerce-view-order table.woocommerce-table--order-details tfoot tr:last-child td {
  font-size: var(--nt-text-lg);
  font-weight: var(--nt-weight-semibold);
  color: var(--nt-text-strong);
}
body.woocommerce-order-received .woocommerce-customer-details address,
body.woocommerce-view-order .woocommerce-customer-details address {
  font-family: var(--nt-font-body);
  font-size: var(--nt-text-sm);
  font-style: normal;
  line-height: 1.6;
  color: var(--nt-text-muted);
  background: var(--nt-surface-1);
  border: 1px solid var(--nt-line);
  border-radius: 0;
  padding: var(--nt-space-md);
}
body.woocommerce-order-received .nk-order-journey h3 {
  margin-top: 0;
  margin-bottom: var(--nt-space-2xs);
}
body.woocommerce-order-received .nk-order-journey ul {
  list-style: none;
  margin: 0;
  padding: 0;
  font-family: var(--nt-font-body);
  font-size: var(--nt-text-sm);
  color: var(--nt-text-muted);
  line-height: 1.7;
}
body.woocommerce-order-received .nk-order-journey li {
  position: relative;
  padding-left: 1.1em;
  margin-bottom: var(--nt-space-2xs);
}
body.woocommerce-order-received .nk-order-journey li::before {
  content: "–";
  position: absolute;
  left: 0;
  color: var(--nt-text-faint);
}

/* ============================================================================
   STICKY ADD TO CART — fiche produit (23/07)
   Réutilise les mêmes tokens que le bloc d'achat principal (titre, prix, CTA
   filet or, cf. body.single-product .summary .price / .single_add_to_cart_button
   plus haut dans ce fichier) : 0 divergence graphique, juste un contexte fixed
   distinct. Le bouton n'a AUCUNE logique panier propre — il proxy-clique le
   vrai bouton du formulaire form.cart (js/nk-sticky-atc.js). Visible seulement
   quand form.cart quitte le viewport (IntersectionObserver, 0 scroll listener).
   ============================================================================ */
.nk-sticky-atc {
  position: fixed;
  inset-inline: 0;
  bottom: 0;
  z-index: 60;
  background: var(--nt-surface-1);
  border-top: 1px solid var(--nt-line);
  transform: translateY(100%);
  opacity: 0;
  visibility: hidden;
  transition: transform .32s ease, opacity .32s ease, visibility 0s linear .32s;
}
.nk-sticky-atc.is-visible {
  transform: translateY(0);
  opacity: 1;
  visibility: visible;
  transition: transform .32s ease, opacity .32s ease, visibility 0s;
}
@media (prefers-reduced-motion: reduce) {
  .nk-sticky-atc { transition: opacity .01s linear, visibility 0s linear; }
}
.nk-sticky-atc__inner {
  max-width: 1100px;
  margin-inline: auto;
  padding: var(--nt-space-sm) clamp(20px, 4vw, 24px);
  padding-bottom: calc(var(--nt-space-sm) + env(safe-area-inset-bottom, 0px));
  display: flex;
  align-items: center;
  gap: var(--nt-space-sm);
}
.nk-sticky-atc__thumb {
  width: 44px;
  height: 44px;
  object-fit: cover;
  border-radius: 0;
  flex: none;
}
@media (max-width: 420px) {
  .nk-sticky-atc__thumb { display: none; }
}
.nk-sticky-atc__info {
  flex: 1 1 auto;
  min-width: 0;
}
.nk-sticky-atc__title {
  font-family: var(--nt-font-heading);
  font-size: var(--nt-text-sm);
  color: var(--nt-text-strong);
  margin: 0 0 2px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.nk-sticky-atc__price {
  font-family: var(--nt-font-ui);
  font-size: var(--nt-fs-summary);
  font-weight: var(--nt-weight-semibold);
  color: var(--nt-text-strong);
  font-variant-numeric: tabular-nums;
  font-feature-settings: "tnum" 1;
  margin: 0;
}
.nk-sticky-atc__cta {
  flex: none;
  min-height: 44px;
  padding: 12px 26px;
  font-family: var(--nt-font-ui);
  font-size: var(--nt-text-sm);
  font-weight: 500;
  letter-spacing: .02em;
  color: var(--nt-gold);
  background: transparent;
  border: 1px solid var(--nt-gold);
  border-radius: 0;
  cursor: pointer;
  transition: background var(--nt-transition), color var(--nt-transition), border-color var(--nt-transition);
}
.nk-sticky-atc__cta:hover {
  background: var(--nt-gold);
  color: var(--nt-bg);
}
.nk-sticky-atc__cta:active {
  background: var(--nt-gold-dark);
  border-color: var(--nt-gold-dark);
  color: var(--nt-bg);
}
/* focus = distinct du hover (outline, pas juste une couleur) — grammaire d'interaction unique, 24/07 */
.nk-sticky-atc__cta:focus-visible {
  background: var(--nt-gold);
  color: var(--nt-bg);
  outline: 2px solid var(--nt-text-strong);
  outline-offset: 2px;
}
.nk-sticky-atc__cta.is-added {
  background: var(--nt-gold);
  color: var(--nt-bg);
}

/* MON COMPTE — déplacé au niveau Core (25/07, retour fondateur "une seule source CSS, pas
   d'inline, template mon compte généralisable, le Core ne connaît pas Nooktails").
   Ce bloc ne contenait aucun couplage de marque (100% var(--nt-*), classes WooCommerce
   natives) — il vivait ici par erreur au niveau Project. Déplacé tel quel vers
   components/woocommerce-myaccount.css (Core, cf. docs/core-vs-project.md), enqueue
   séparé dans functions.php. Ne pas réintroduire ces règles ici. */
/* Lien "Continuer mes achats" — contenu de la page Panier (pas de composant custom,
   même contrat de lien que .nk-info a). */
body.woocommerce-cart .nk-cart-continue {
  margin: clamp(20px, 4vw, 32px) 0 24px;   /* respiration ajoutée sous le header (25/07) — était collé (margin-top:0) */
  font-family: var(--nt-font-ui);
  font-size: var(--nt-text-sm);
}
body.woocommerce-cart .nk-cart-continue a {
  color: var(--nt-text-muted);
  text-decoration: underline;
  text-decoration-color: var(--nt-gold);
  text-underline-offset: 3px;
  transition: color var(--nt-transition);
}
body.woocommerce-cart .nk-cart-continue a:hover {
  color: var(--nt-gold);
}

/* D013 (audit 27/07) — la barre "Valider la commande" du panier (WooCommerce Blocks natif,
   .wc-block-cart__submit-container--sticky, position:fixed/bottom:0/z-index:9999 posée par
   WooCommerce lui-même dès @media(max-width:782px), mesurée 79,6px de haut) recouvre les
   contrôles quantité/suppression du dernier article. On ne touche pas la règle WooCommerce
   (source tierce) : on libère l'espace côté conteneur d'articles avec un padding-bottom
   scopé au même breakpoint, à la source (pas de !important). */
@media (max-width: 782px) {
  body.woocommerce-cart .wc-block-cart-items {
    padding-bottom: 96px;
  }
}

/* Astérisque champ obligatoire — rouge vif #FF0000 hors palette (défaut Kadence non
   surchargé jusqu'ici, vérifié en direct sur .required : color:rgb(255,0,0)). Repris avec
   le token alerte déjà utilisé pour les statuts de commande (--nt-alert). Portée globale
   (.required apparaît sur les formulaires Mon compte/adresses, pas seulement panier). */
.woocommerce .form-row .required,
.woocommerce-page .form-row .required,
.woocommerce .required,
.woocommerce-page .required {
  color: var(--nt-alert);
}

/* 28/07 (audit P2) : message de validation du checkout WooCommerce Blocks (ex. email
   invalide) en rouge natif #cc1818 — hors palette, aucune règle ne le ciblait jusqu'ici
   (seul l'astérisque .required était couvert, pas ce composant React distinct). */
.wc-block-components-validation-error,
.wc-block-components-validation-error p,
.wc-block-components-text-input.has-error .wc-block-components-text-input__label,
.wc-block-components-text-input.has-error input {
  color: var(--nt-alert-text);
}
.wc-block-components-text-input.has-error input {
  border-color: var(--nt-alert-text);
}

/* 28/07 (audit P3) : bordures pointillées grises du tableau "Caractéristiques"
   (--global-gray-400, natif Kadence, jamais remappé) — hors palette chaude du site. */
body.single-product table.shop_attributes,
body.single-product table.shop_attributes th,
body.single-product table.shop_attributes td {
  border-color: var(--nt-line);
}

/* Vidéo produit (shortcode [nt_product_video], 26/07) — pleine largeur du résumé
   produit, ratio natif préservé (pas de crop forcé), juste sous la galerie. */
body.single-product .nt-product-video {
  margin: 0 0 1.5em;
}
body.single-product .nt-product-video video {
  display: block;
  width: 100%;
  aspect-ratio: 16 / 9;
  height: auto;
  object-fit: cover;
  background: var(--nt-surface-3);
}

/* 26/07 (mandat CRO fondateur) — vidéo + aide à la décision, 60/40 desktop, empilé mobile.
   Remplace la vidéo seule qui laissait un grand vide à droite. Contenu produit-spécifique
   généré par le shortcode [nt_product_video] côté PHP (functions.php), scopé Furoomate 4825. */
body.single-product .nt-video-decision-row {
  display: flex;
  align-items: flex-start;
  gap: clamp(1.5rem, 3vw, 2.5rem);
  margin: 0 0 1.5em;
}
body.single-product .nt-video-decision-row .nt-product-video {
  flex: 0 0 60%;
  min-width: 0;
  margin: 0;
}
body.single-product .nt-decision-aid {
  flex: 0 0 40%;
  min-width: 0;
}
@media (max-width: 767px) {
  body.single-product .nt-video-decision-row {
    flex-direction: column;
  }
  body.single-product .nt-video-decision-row .nt-product-video,
  body.single-product .nt-decision-aid {
    flex-basis: auto;
    width: 100%;
  }
}
.nt-decision-aid__lead {
  margin: 0 0 1.1rem;
  font-family: var(--nt-font-heading);
  font-size: clamp(1.05rem, 1.8vw, 1.2rem);
  font-weight: var(--nt-weight-medium);
  line-height: var(--nt-leading-snug);
  color: var(--nt-text-strong);
}
.nt-decision-aid__point {
  margin: 0 0 1rem;
}
.nt-decision-aid__point-title {
  margin: 0 0 .25rem;
  font-family: var(--nt-font-ui);
  font-size: .68rem;
  font-weight: var(--nt-weight-semibold);
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--nt-text-faint);
}
.nt-decision-aid__point p:not(.nt-decision-aid__point-title) {
  margin: 0;
  font-family: var(--nt-font-body);
  font-size: .92rem;
  line-height: var(--nt-leading-normal);
  color: var(--nt-text);
}
.nt-decision-aid__notice {
  margin: 1.4rem 0 0;
  padding-inline-start: 1rem;
  border-inline-start: 1px solid var(--nt-white-a08);
}
.nt-decision-aid__notice-title {
  margin: 0 0 .55rem;
  font-family: var(--nt-font-ui);
  font-size: .68rem;
  font-weight: var(--nt-weight-semibold);
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--nt-text-faint);
}
.nt-decision-aid__notice ul {
  list-style: none;
  margin: 0;
  padding: 0;
  border-inline-start: none;
}
.nt-decision-aid__notice li {
  margin: 0 0 .4rem;
  padding: 0;
  font-family: var(--nt-font-body);
  font-size: .88rem;
  color: var(--nt-text-muted);
}
.nt-decision-aid__notice li:last-child {
  margin-bottom: 0;
}

/* Fiche produit — modules visuels alternés (27/07, lot anti-répétition Furoomate).
   Image + texte court, alterne à droite/gauche en desktop via modificateur explicite
   (pas de nth-of-type : le contenu WooCommerce mélange d'autres éléments autour).
   Mobile : toujours image → titre → texte, jamais 2 colonnes (ordre DOM déjà correct,
   la modif ne fait que neutraliser l'inversion desktop). */
body.single-product .nt-visual-module {
  display: flex;
  align-items: center;
  gap: clamp(1.5rem, 4vw, 3rem);
  margin-block: var(--nt-space-xl);
}
body.single-product .nt-visual-module--reverse {
  flex-direction: row-reverse;
}
body.single-product .nt-visual-module__media {
  flex: 0 0 44%;
  min-width: 0;
}
body.single-product .nt-visual-module__media img {
  display: block;
  width: 100%;
  height: auto;
  border-radius: var(--nt-radius-sm);
}
body.single-product .nt-visual-module__body {
  flex: 1 1 auto;
  min-width: 0;
}
body.single-product .nt-visual-module__body h3 {
  margin: 0 0 .6rem;
}
body.single-product .nt-visual-module__body p,
body.single-product .nt-visual-module__body ol {
  margin: 0;
  color: var(--nt-text-muted);
}
body.single-product .nt-visual-module__body ol {
  padding-inline-start: 1.2rem;
}
body.single-product .nt-visual-module__body ol li {
  margin: 0 0 .4rem;
}
@media (max-width: 767px) {
  body.single-product .nt-visual-module,
  body.single-product .nt-visual-module--reverse {
    flex-direction: column;
  }
  body.single-product .nt-visual-module__media {
    flex-basis: auto;
    width: 100%;
  }
}

/* "Ce que vous recevez" — bloc compact, source unique pour le contenu de la boîte.
   height:auto explicite (le bloc n'a jamais eu de hauteur fixée — la hauteur excessive
   observée venait du reset de liste générique ci-dessus qui imposait sa propre marge/
   padding/filet à ce <ul> ; exclu nommément ci-dessus, donc ces règles governent seules). */
body.single-product .nt-receive-block {
  height: auto;
  border: 1px solid var(--nt-line);
  border-radius: var(--nt-radius-sm);
  padding: var(--nt-space-md);
  margin-block: var(--nt-space-lg);
}
body.single-product .nt-receive-block h3 {
  margin: 0 0 .6rem;
}
body.single-product .nt-receive-block ul {
  list-style: none;
  margin: 0;
  padding: 0;
  border-inline-start: none;
}
body.single-product .nt-receive-block li {
  margin: 0 0 .3rem;
  padding: 0;
  font-size: .92rem;
  line-height: var(--nt-leading-snug);
  color: var(--nt-text-muted);
}
body.single-product .nt-receive-block li:last-child {
  margin-bottom: 0;
}

/* Accordéons détails techniques — <details>/<summary> natifs : 0 JS requis, contenu
   toujours dans le DOM, navigation clavier native, aucun saut de mise en page. */
body.single-product .nt-accordion-group {
  margin-block: var(--nt-space-xl);
  border-top: 1px solid var(--nt-line);
}
body.single-product .nt-accordion {
  border-bottom: 1px solid var(--nt-line);
}
body.single-product .nt-accordion summary {
  cursor: pointer;
  list-style: none;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--nt-space-sm);
  padding: var(--nt-space-sm) 0;
  font-family: var(--nt-font-heading);
  font-size: var(--nt-text-lg);
  color: var(--nt-text);
}
body.single-product .nt-accordion summary::-webkit-details-marker {
  display: none;
}
body.single-product .nt-accordion summary::after {
  content: '+';
  flex-shrink: 0;
  font-family: var(--nt-font-ui);
  font-size: 1.1em;
  color: var(--nt-gold);
}
body.single-product .nt-accordion[open] summary::after {
  content: '\2013';
}
body.single-product .nt-accordion summary:focus-visible {
  outline: 2px solid var(--nt-gold);
  outline-offset: 3px;
}
body.single-product .nt-accordion__content {
  padding: 0 0 var(--nt-space-md);
  color: var(--nt-text-muted);
}
body.single-product .nt-accordion__content > *:first-child {
  margin-top: 0;
}
body.single-product .nt-accordion__content > *:last-child {
  margin-bottom: 0;
}

/* Marchepied — cross-sell éditorial en fin de fiche (distinct du cross-sell natif panier).
   27/07 : restructuré en pile verticale (zone média pleine largeur, image centrée en
   object-fit:contain) — l'ancienne colonne 120px collait l'image à gauche du bloc. Même
   ligne desktop/mobile : plus de flex-direction à inverser par breakpoint. */
body.single-product .nt-marchepied-cross {
  border: 1px solid var(--nt-line);
  border-radius: var(--nt-radius-sm);
  padding: var(--nt-space-md);
  margin-block: var(--nt-space-xl);
}
body.single-product .nt-marchepied-cross__media {
  display: flex;
  justify-content: center;
  align-items: center;
  width: 100%;
  height: 180px;
  margin: 0 0 var(--nt-space-sm);
}
body.single-product .nt-marchepied-cross__media img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: contain;
}
/* 27/07 (fondateur) — image centrée + texte/bouton laissés à gauche créait un
   déséquilibre visuel. Choix : tout centrer (traitement "carte premium" cohérent),
   plutôt que tout ramener à gauche (aurait désaxé l'image de son cadre pleine largeur). */
body.single-product .nt-marchepied-cross__body {
  text-align: center;
}
body.single-product .nt-marchepied-cross__body h3 {
  margin: 0 0 .4rem;
}
body.single-product .nt-marchepied-cross__body p {
  max-width: 46ch;
  margin: 0 auto .8rem;
  color: var(--nt-text-muted);
}
body.single-product .nt-marchepied-cross__note {
  margin: .6rem 0 0;
  font-size: var(--nt-text-sm);
  color: var(--nt-text-faint);
}

/* ====================================================================
   FICHE PRODUIT — LARGEUR DESKTOP (27/07, fondateur — généralisé 27/07)
   --------------------------------------------------------------------
   Racine du "grand vide à droite" : .entry-content{max-width:var(--nt-prose)}
   (65ch ≈ 617px) est une règle SITE-WIDE pensée pour la largeur de lecture
   des articles de blog — elle capturait aussi l'onglet Description du
   produit, alors que son propre conteneur parent (.woocommerce-tabs)
   offre déjà ~1242px. Override par `:has()` — la spécificité bat déjà la
   règle générique (2 classes seules) sans !important. Marqueurs génériques
   (n'importe quel produit utilisant ces composants en profite, 0 ID en dur) :
   .nt-video-decision-row (vidéo produit) OU .nt-visual-module (modules
   image+texte seuls, ex. fiche marchepied). Desktop uniquement (>=1024px) ;
   mobile intact (aucune règle ici active sous ce seuil). */
@media (min-width: 1024px) {
  body.single-product .woocommerce-Tabs-panel--description:has(.nt-video-decision-row, .nt-visual-module) {
    max-width: 1240px;
    margin-inline: auto;
  }

  /* 2) Module vidéo + aide à la décision — pleine largeur du nouveau
     conteneur, grille 58/42, alignement haut déjà en place (align-items:
     flex-start, inchangé). */
  body.single-product .nt-video-decision-row {
    width: 100%;
  }
  body.single-product .nt-video-decision-row .nt-product-video {
    flex: 0 0 58%;
  }
  body.single-product .nt-decision-aid {
    flex: 0 0 42%;
  }

  /* 3) Texte introductif — largeur de lecture dédiée, centrée dans le
     nouveau conteneur large (jamais collée à gauche). */
  body.single-product .nt-intro {
    max-width: var(--nt-prose-wide); /* 800px, déjà dans la fourchette 760-820 demandée */
    margin-inline: auto;
  }

  /* 4) Trois modules visuels — grille 50/50, images plus grandes en
     object-fit:contain (les 3 photos sont carrées, contain ne recadre
     rien), gap élargi, module centré dans le conteneur. */
  body.single-product .nt-visual-module {
    max-width: 1080px;
    margin-inline: auto;
    gap: clamp(3rem, 6vw, 5rem);
  }
  body.single-product .nt-visual-module__media {
    flex: 0 0 50%;
  }
  body.single-product .nt-visual-module__media img {
    aspect-ratio: 1 / 1;
    object-fit: contain;
  }

  /* 5) "Ce que vous recevez", module litières, accordéons, marchepied —
     même largeur de lecture, centrés, hauteur/padding déjà auto-équilibrés
     par leurs règles propres ci-dessus (var(--nt-space-md) uniforme). */
  body.single-product .nt-receive-block,
  body.single-product .nt-litter-compat,
  body.single-product .nt-accordion-group,
  body.single-product .nt-marchepied-cross {
    max-width: 900px;
    margin-inline: auto;
  }
}

/* Litières compatibles — module visuel recommandé/non recommandé (27/07, fiche Furoomate).
   Texte + glyphes typographiques discrets uniquement (0 image, 0 icône décorative) : fond
   sobre déjà utilisé partout ailleurs sur la fiche (--nt-surface-1), 0 rond coloré. */
body.single-product .nt-litter-compat {
  display: flex;
  gap: var(--nt-space-lg);
  background: var(--nt-surface-1);
  border: 1px solid var(--nt-line);
  border-radius: var(--nt-radius-sm);
  padding: var(--nt-space-md);
  margin-block: var(--nt-space-lg);
}
body.single-product .nt-litter-compat__col {
  flex: 1 1 0;
  min-width: 0;
}
body.single-product .nt-litter-compat__label {
  margin: 0 0 .6rem;
  font-family: var(--nt-font-ui);
  font-size: .68rem;
  font-weight: var(--nt-weight-semibold);
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--nt-text-muted);
}
body.single-product .nt-litter-compat__list {
  margin: 0;
  padding: 0;
  list-style: none;
}
body.single-product .nt-litter-compat__list li {
  position: relative;
  padding-inline-start: 1.4em;
  margin: 0 0 .5rem;
  font-family: var(--nt-font-body);
  color: var(--nt-text);
}
body.single-product .nt-litter-compat__list li:last-child {
  margin-bottom: 0;
}
body.single-product .nt-litter-compat__list--yes li::before {
  content: '\2713';
  position: absolute;
  left: 0;
  font-family: var(--nt-font-ui);
  color: var(--nt-gold);
}
body.single-product .nt-litter-compat__list--no li::before {
  content: '\2013';
  position: absolute;
  left: 0;
  font-family: var(--nt-font-ui);
  color: var(--nt-text-faint);
}
@media (max-width: 767px) {
  body.single-product .nt-litter-compat {
    flex-direction: column;
  }
}

/* D014 (audit 27/07) — zones tactiles panier sous 44×44px (WCAG 2.5.8) :
   boutons quantité −/+ (30×26px) et suppression (24×24px, WooCommerce Blocks).
   On agrandit la zone cliquable via un ::before invisible centré, sans toucher
   à la taille visuelle du bouton/icône (aucun changement de rendu). */
.wc-block-cart-item__remove-link,
.wc-block-components-quantity-selector__button {
  position: relative;
}
.wc-block-cart-item__remove-link::before,
.wc-block-components-quantity-selector__button::before {
  content: '';
  position: absolute;
  top: 50%;
  left: 50%;
  width: 44px;
  height: 44px;
  transform: translate(-50%, -50%);
}

/* D002 (audit 27/07) — les résultats de recherche mélangent produits et articles dans des
   cartes identiques (aucun prix, CTA générique "Lire la suite"). Badge texte discret (pas
   de pilule/pastille colorée, anti-IA strict) + prix ajoutés via functions.php et
   template-parts/content/entry_actions-product.php, scopés à is_search(). */
.search-results .nt-search-result-badge {
  display: block;
  font-family: var(--nt-font-ui);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  margin: 0 0 4px;
}
.search-results .nt-search-result-badge--product {
  color: var(--nt-gold);
}
.search-results .nt-search-result-badge--article {
  color: var(--nt-text-faint);
}
.search-results .nt-search-result-price {
  font-family: var(--nt-font-ui);
  font-size: var(--nt-text-lg);
  color: var(--nt-text-strong);
  margin: 0 0 var(--nt-space-xs);
}
.search-results .type-product .posted-on {
  display: none;
}

/* D016 (audit 27/07) — le bloc "Validation de commande express" (Apple Pay/Google Pay,
   WooCommerce Blocks) apparaît vide 1-2s avant l'hydratation des SDK, provoquant un saut
   de mise en page (CLS) et un effet "cassé" perçu en tout début de checkout. On réserve
   la hauteur d'un bouton dès le rendu serveur (avant hydratation JS) : aucun saut visuel,
   que le bloc finisse vide (aucun wallet éligible) ou peuplé. */
.wp-block-woocommerce-checkout-express-payment-block:empty {
  min-height: 48px;
}

/* Panier vide, "Nouveau dans la boutique" (WooCommerce Blocks Product New) — Lot Final,
   correctif ciblé (28/07, fondateur).
   RÈGLE SOURCE DU BUG (27/07, retirée ici) : `body .wc-block-grid.has-4-columns
   .wc-block-grid__products { grid-template-columns: repeat(2, 1fr); }` — posée sans media
   query ET sans scope de page (juste `body`) pour battre le has-4-columns natif. Elle forçait
   2 colonnes à TOUTES les largeurs, y compris mobile étroit, écrasant au passage le
   comportement natif WooCommerce (all-products.css, @media max-width:480px, qui repasse
   nativement en 1 colonne — jamais atteint à cause de cette règle non conditionnée).
   Mesuré en direct : bouton "Ajouter au panier" à 296px de hauteur à 320px, 152px à 375px
   (texte réparti sur 5-6 lignes, carte 108-136px de large).
   PORTÉE ACTUELLE (avant ce fix) : `body` = site entier, toutes largeurs. Un seul bloc de ce
   type existe sur le site (scan REST API, 152 pages/articles) — la portée large ne créait pas
   de régression ailleurs aujourd'hui, mais restait plus large que nécessaire.
   NOUVELLE PORTÉE : scopée à `body.woocommerce-cart .wp-block-woocommerce-empty-cart-block`
   (uniquement ce widget, cette page) ET conditionnée à `min-width:481px` (seuil repris tel
   quel du breakpoint déjà décidé par WooCommerce dans all-products.css, pas une valeur
   inventée) ET à la présence d'au moins 2 produits (`:has()`, déjà utilisé ailleurs dans ce
   thème). Sous 481px ou avec 1 seul produit affiché : 1 colonne pleine largeur. */
body.woocommerce-cart .wp-block-woocommerce-empty-cart-block .wc-block-grid.has-4-columns .wc-block-grid__products {
  grid-template-columns: 1fr;
}
@media (min-width: 481px) {
  body.woocommerce-cart .wp-block-woocommerce-empty-cart-block .wc-block-grid.has-4-columns .wc-block-grid__products:has(.wc-block-grid__product ~ .wc-block-grid__product) {
    grid-template-columns: repeat(2, 1fr);
  }
}

/* ============================================================
 * DIAGNOSTIC PONDÉRÉ + HERO LIFESTYLE — fiche produit (28/07, V2 test 65L)
 * Additif : ne touche à aucune règle existante (visual-module/accordion/nk-ui-card
 * restent inchangés). .nk-ui-card lui-même vient de barometre/assets/framework.css,
 * chargé conditionnellement via nk_baro_enqueue() dans le shortcode nt_pdp_diagnostics.
 * ========================================================== */
body.single-product .nk-baro-pdp {
  margin: var(--nt-space-md) 0;
}
body.single-product .nk-baro-pdp__label {
  font-family: var(--nt-font-ui);
  font-size: 0.78rem;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--nt-text-faint);
  margin: 0 0 var(--nt-space-xs);
}
body.single-product .nk-baro-pdp__grid {
  display: grid;
  grid-template-columns: 1.6fr 1fr;
  gap: var(--nt-space-sm);
  align-items: stretch;
}
body.single-product .nk-baro-pdp__secondary .nk-ui-card {
  font-size: 0.92em;
}
@media (max-width: 600px) {
  body.single-product .nk-baro-pdp__grid {
    grid-template-columns: 1fr;
  }
}

body.single-product .nt-hero-lifestyle {
  margin: var(--nt-space-md) 0;
}
body.single-product .nt-hero-lifestyle img {
  display: block;
  width: 100%;
  height: auto;
}
body.single-product .nt-hero-lifestyle figcaption {
  font-family: var(--nt-font-ui);
  font-size: 0.82rem;
  color: var(--nt-text-faint);
  margin-top: var(--nt-space-2xs);
}

body.single-product .nt-pdp-glance {
  margin: var(--nt-space-md) 0;
  padding: var(--nt-space-sm);
  border: 1px solid var(--nt-line);
  border-radius: var(--nt-radius-sm);
}
body.single-product .nt-pdp-glance__label {
  font-family: var(--nt-font-ui);
  font-size: 0.78rem;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--nt-text-faint);
  margin: 0 0 var(--nt-space-xs);
}
body.single-product .nt-pdp-glance ul {
  margin: 0;
  padding: 0;
  list-style: none;
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--nt-space-2xs) var(--nt-space-sm);
}
@media (max-width: 480px) {
  body.single-product .nt-pdp-glance ul {
    grid-template-columns: 1fr;
  }
}

/* ============================================================
 * HERO PREMIUM PDP — fiche 65L uniquement (28/07, V2.1 test conversion)
 * Scopé strictement à ce produit (postid-5270, cf. body_class WordPress natif) :
 * aucune règle ne s'applique à Furoomate/Marchepied ni à aucune autre page.
 * ========================================================== */
body.single-product.postid-5270 .nt-pdp-hero {
  position: relative;
  max-width: var(--nt-container);
  margin: 0 auto var(--nt-space-sm);
  min-height: 560px;
  display: flex;
  align-items: center;
  overflow: hidden;
}
body.single-product.postid-5270 .nt-pdp-hero__media {
  position: absolute;
  inset: 0;
}
body.single-product.postid-5270 .nt-pdp-hero__media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: right center;
  display: block;
}
body.single-product.postid-5270 .nt-pdp-hero__veil {
  position: absolute;
  inset: 0;
  background: linear-gradient(90deg, var(--nt-bg) 0%, var(--nt-bg) 40%, rgba(243, 241, 234, 0.55) 58%, rgba(243, 241, 234, 0) 72%);
}
body.single-product.postid-5270 .nt-pdp-hero__body {
  position: relative;
  z-index: 1;
  max-width: 460px;
  padding: var(--nt-space-xl) var(--nt-space-lg);
}
body.single-product.postid-5270 .nt-pdp-hero__kicker {
  font-family: var(--nt-font-ui);
  font-size: 0.78rem;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--nt-gold);
  margin: 0 0 var(--nt-space-xs);
}
body.single-product.postid-5270 .nt-pdp-hero__title {
  font-family: var(--nt-font-heading);
  font-size: var(--nt-h2);
  line-height: var(--nt-lh-h1);
  margin: 0 0 var(--nt-space-xs);
  color: var(--nt-text);
}
body.single-product.postid-5270 .nt-pdp-hero__sub {
  font-size: var(--nt-fs-lead, 1.05rem);
  line-height: var(--nt-leading-relaxed);
  color: var(--nt-text);
  margin: 0 0 var(--nt-space-sm);
}
body.single-product.postid-5270 .nt-pdp-hero__actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--nt-space-xs);
  margin-bottom: var(--nt-space-sm);
}
body.single-product.postid-5270 .nt-pdp-hero__cta-primary {
  display: inline-block;
  padding: 0.85em 1.6em;
  background: var(--nt-gold);
  color: var(--nt-bg);
  text-decoration: none;
  border: 1px solid var(--nt-gold);
  border-radius: 0;
  font-family: var(--nt-font-ui);
  font-size: 0.92rem;
}
body.single-product.postid-5270 .nt-pdp-hero__cta-secondary {
  display: inline-block;
  padding: 0.85em 1.6em;
  background: transparent;
  color: var(--nt-text);
  text-decoration: none;
  border: 1px solid var(--nt-line-strong);
  border-radius: 0;
  font-family: var(--nt-font-ui);
  font-size: 0.92rem;
}
body.single-product.postid-5270 .nt-pdp-hero__reassurance {
  font-family: var(--nt-font-ui);
  font-size: 0.8rem;
  color: var(--nt-text-faint);
  margin: 0;
}
body.single-product.postid-5270 div.summary.entry-summary {
  margin-top: var(--nt-space-xs);
}
@media (max-width: 782px) {
  body.single-product.postid-5270 .nt-pdp-hero {
    flex-direction: column;
    align-items: stretch;
    min-height: 0;
  }
  body.single-product.postid-5270 .nt-pdp-hero__media {
    position: relative;
    inset: auto;
    height: 240px;
  }
  body.single-product.postid-5270 .nt-pdp-hero__veil {
    display: none;
  }
  body.single-product.postid-5270 .nt-pdp-hero__body {
    max-width: none;
    background: var(--nt-bg);
    padding: var(--nt-space-md) var(--nt-space-sm);
  }
  body.single-product.postid-5270 .nt-pdp-hero__title {
    font-size: var(--nt-h2);
  }
  body.single-product.postid-5270 .nt-pdp-hero__cta-primary {
    display: block;
    text-align: center;
  }
  body.single-product.postid-5270 .nt-pdp-hero__cta-secondary {
    display: inline-block;
    padding: 0.6em 1.2em;
    font-size: 0.85rem;
  }
}
