@charset "UTF-8";
/* ============================================================
   PamiProduct — fiche produit clean pamisa.ch
   Charte Best Practices : tokens --pp-* partout, @layer, BEM pp-,
   zéro !important, zéro #id de styling, fluid clamp() + Grid.
   Source rendu : fiches 42014/42016 (El Primer Beso 2023).
   Cross-browser : Firefox + Safari + Chrome.
   ============================================================ */

@layer pp-base, pp-components, pp-wc, pp-utilities, pp-responsive;

/* ============================================================
   STRATÉGIE @layer (documentée — H1)
   Ordre : base < components < wc < utilities < pp-responsive.
   TOUTES les media-queries de LAYOUT vivent dans @layer pp-responsive
   (section 6) → elles restent dans la cascade des layers, ne « gagnent »
   pas accidentellement sur tout le CSS comme le ferait du code hors-layer.
   Exceptions hors-layer assumées (sémantique « doit gagner sur tout ») :
   @media (prefers-reduced-motion) et @media print (sections 7 et 8).
   ============================================================ */

/* ============================================================
   1. TOKENS  (seul endroit où vivent les valeurs brutes)
   ============================================================ */
@layer pp-base {
  :root {
    /* --- Couleurs (extraites du CSS inline Shopkeeper, §5.1) --- */
    --pp-color-primary:        #ac0b0b;
    --pp-color-primary-hover:  #7d0808;
    --pp-color-text-main:      #333333;
    --pp-color-text-muted:     #565656;
    --pp-color-text-light:     #606060;
    --pp-color-bg-page:        #ffffff;
    --pp-color-bg-subtle:      #f9f9f9;
    /* Bande SPECS — gris des CELLULES (réel pamisa.ch `.mikespec` mesuré 2026-06-10 :
       background-color #f9f9f9). Chaque section est une cellule grise posée sur le fond
       BLANC ; les séparations sont des GOUTTIÈRES BLANCHES (bordure 1px blanche par
       cellule + gap de grille), PAS des lignes dessinées. Le gris est volontairement
       très subtil (Δluminance ~2 % vs blanc) — c'est exactement le rendu du site. */
    --pp-color-bg-specs:       #f9f9f9;
    --pp-color-bg-footer:      #1a1a1a; /* footer dark (rendu réel) */
    --pp-color-text-on-dark:   rgba(255, 255, 255, 0.82); /* AA sur footer dark */
    --pp-color-text-on-dark-strong: #ffffff;
    --pp-color-on-dark-faint:  rgba(255, 255, 255, 0.55); /* copyright */
    --pp-color-on-dark-border: rgba(255, 255, 255, 0.12); /* séparateur footer */
    --pp-color-border:         rgba(86, 86, 86, 0.15);
    --pp-color-border-strong:  rgba(86, 86, 86, 0.45);
    --pp-color-breadcrumb:     #767676; /* fil d'Ariane pâle mais WCAG AA (4.54 sur blanc) */
    --pp-color-link-delivery:  #0059FF; /* bleu EXACT du site (.bluemsj/.wooh2, demande MSJ R2 v2) */
    --pp-color-error:          #c4321f; /* assombri pour AA */
    --pp-color-white:          #ffffff;
    --pp-color-overlay:        rgba(0, 0, 0, 0.72);
    --pp-color-star:           var(--pp-color-primary); /* étoiles = accent du site #ac0b0b (CSS réel fiche) */

    /* --- Typographie : famille --- */
    --pp-font-main: "Lato", -apple-system, BlinkMacSystemFont,
                    Arial, Helvetica, "Helvetica Neue", Verdana, sans-serif;

    /* --- Échelle typo FLUIDE (clamp calé sur 3 viewports : mobile ~390, desktop ~1440).
       Bornes en rem (accessibilité zoom), fluide en vw. R4.8 / Sin 36 --- */
    --pp-fs-xs:   0.75rem;                                  /* ~12px constant */
    --pp-fs-sm:   clamp(0.8125rem, 0.79rem + 0.10vw, 0.875rem);   /* 13 -> 14 */
    --pp-fs-base: clamp(0.875rem, 0.84rem + 0.16vw, 1rem);        /* 14 -> 16 */
    --pp-fs-md:   clamp(0.9375rem, 0.89rem + 0.20vw, 1.0625rem);  /* 15 -> 17 */
    --pp-fs-lg:   clamp(1.0625rem, 0.98rem + 0.35vw, 1.25rem);    /* 17 -> 20 */
    --pp-fs-xl:   clamp(1.25rem, 1.12rem + 0.55vw, 1.5rem);       /* 20 -> 24 */
    --pp-fs-2xl:  clamp(1.5rem, 1.27rem + 0.97vw, 2rem);          /* 24 -> 32 */
    --pp-fs-4xl:  clamp(2.125rem, 1.5rem + 2.6vw, 3.125rem);      /* 34 -> 50 (h1) */

    /* --- Poids --- */
    --pp-fw-light:    300;
    --pp-fw-normal:   400;
    --pp-fw-semibold: 600;  /* titres réels (h1, Bodega/AOC, prix) = 600 (critique #1/#2/#7) */
    --pp-fw-bold:     700;
    --pp-fw-black:    900;

    /* --- Line-heights --- */
    --pp-lh-tight:   1.15;
    --pp-lh-snug:    1.3;
    --pp-lh-normal:  1.6;

    /* --- Letter-spacing (Shopkeeper uppercase titles) --- */
    --pp-ls-wide:    0.08em;
    --pp-ls-wider:   0.14em;

    /* --- Espacements : échelle fluide + contextuels par RÔLE (R4.11) --- */
    --pp-space-3xs: 0.25rem;
    --pp-space-2xs: 0.5rem;
    --pp-space-xs:  0.75rem;
    --pp-space-sm:  1rem;
    --pp-space-md:  1.5rem;
    --pp-space-lg:  2rem;
    --pp-space-xl:  clamp(2.5rem, 1.8rem + 3vw, 4rem);
    --pp-space-2xl: clamp(3.5rem, 2.5rem + 4vw, 5.5rem);

    --pp-gutter:        clamp(1rem, 0.4rem + 2.6vw, 2.5rem); /* marge latérale de page */
    --pp-container-gap: var(--pp-space-2xl);                 /* entre sections empilées */
    --pp-content-gap:   var(--pp-space-sm);                  /* entre éléments d'un bloc */
    --pp-grid-gap:      clamp(1.25rem, 0.8rem + 1.8vw, 2.5rem); /* entre cellules de grille */

    /* --- Conteneurs --- */
    /* R3 item 10 (MESURÉ) : ancien Shopkeeper utile @1440 = 1340px · nôtre = 1120px ·
       CHOISI = 1280px utile (cible chef 1280-1320). 85rem container − 2×gutter 40px
       = 1280 utile. Fluide sous le max → 1024/768 inchangés ; cap fixe = clamp
       naturel pour très grands écrans. */
    --pp-container-max: 85rem;   /* ~1360px (utile ~1280 @1440+) — était 75rem/1200 */
    --pp-prose-max:     70ch;    /* ligne lisible, Sin 15 */

    /* R3 item 9 (MESURÉ) : gap header→contenu — ancien 81px · nôtre 64px ·
       CHOISI 76px desktop (entre les deux, consigne MSJ), fluide en dessous. */
    --pp-main-top: clamp(3rem, 2.2rem + 3vw, 4.75rem); /* 48px mobile → 76px desktop */

    /* R3 item 8 : retrait des blocs nav/outils vis-à-vis du logo central (desktop). */
    --pp-header-inset: clamp(1.5rem, 3vw, 3.5rem);

    /* R3 items 1-2 : cadre bouteille COUCHÉE du mini-panier (hauteur du cadre crop)
       et longueur rendue de la bouteille une fois tournée.
       R6 (verdict MSJ, panier 4 lignes) : CROP MOINS AGRESSIF — bases de bouteilles
       coupées à gauche et badge volume « 1.5 » tranché à droite. Longueur réduite
       26rem→14.5rem (≈232px dans un cadre ≈346px → ~15% de marge de chaque côté ;
       fenêtre verticale ≈ moitié centrale de l'image = badge adjacent visible) ;
       cadre 6.5→5.25rem, bloc image 80% de la modale, lignes plus compactes
       (objectif MSJ : panier moins « plein », encourager plus de positions). */
    /* R7 (MSJ : « tu as un peu exagéré » en R6) : cible = −20% de la taille
       ORIGINALE R3-R5 (26rem) → 20.75rem (≈332px). Crop doux R6 CONSERVÉ :
       fenêtre verticale = moitié centrale (frame ∝ bouteille, ratio ~0.36) →
       7.5rem (120px). Bouteille alignée À GAUCHE, croix à droite (item 3). */
    --pp-mc-frame-h:    7.5rem;
    --pp-mc-bottle-len: 20.75rem;

    /* --- Rayons (coins peu arrondis, préférence MSJ) --- */
    --pp-radius-sm:   2px;
    --pp-radius-md:   4px;
    --pp-radius-pill: 999px;     /* pastilles cart-count / tags (L3/L5) */
    --pp-radius-square: 0;       /* boutons AJOUTER / +/− : ANGLES CARRÉS (demande MSJ R2 v2) */

    /* --- Galerie : plafond de largeur de la bouteille en 1 COLONNE (mobile/tablette).
       Règle MSJ « jamais plus grande que le site actuel » : on borne la photo et on
       l'aligne à GAUCHE (cohérent avec le texte aligné à gauche). En desktop 2 col,
       la photo remplit sa colonne (≈483px réel) sans ce plafond. --- */
    --pp-gallery-max-1col: clamp(13rem, 58vw, 26rem); /* ~208px@390 → ~416px@768, < réel */

    /* --- Ombres --- */
    --pp-shadow-pop: 0 8px 30px rgba(0, 0, 0, 0.18);

    /* --- Bordures --- */
    --pp-border-width:      1px;
    --pp-border-width-bold:  2px; /* indicateur onglet actif (L3) */
    --pp-border-width-accent: 4px; /* liseré gauche notices / notif erreur (L3) */

    /* --- UI sizing --- */
    --pp-tap-min:        44px;   /* cible tactile a11y (zone cliquable, conservée) */
    --pp-tools-btn-w:    2.25rem; /* largeur visuelle resserrée des boutons outils (MSJ R2 v2 §2c) */
    --pp-tools-gap:      var(--pp-space-3xs); /* icônes outils resserrées (MSJ R2 v2 §2c) */
    --pp-header-h:       clamp(4rem, 5vw, 5.75rem); /* 64→92px en rem (L1, R4.8 zoom) */
    --pp-icon-size:      20px;   /* glyphes outils, resserrés (était 22px, MSJ R2 v2 §2c) */
    --pp-qty-icon-size:  14px;   /* glyphes +/− des contrôles quantité */
    /* Logo — R4 item 4 (verdict MSJ « presque un peu trop » grand, MESURÉ @1440) :
       ancien Shopkeeper h=35px · nôtre h=47px · CHOISI h≈41px (entre-deux) → cap
       largeur 272→236px (ratio 272/47≈5.79). Min mobile/tablette 180px INCHANGÉ
       (les paliers ×1.2/×1.04 de @layer pp-responsive s'appliquent au min). */
    --pp-logo-width:     clamp(11.25rem, 20vw, 14.75rem); /* 180→236px (était 272px) */
    --pp-cart-count-size: 1.125rem;  /* 18px badge panier (L3/L5) */
    --pp-notif-thumb-size: 4rem;     /* 64px miniature notif (L3/L5, lié au grid) */
    --pp-spec-table-w:   16rem;      /* largeur table cépages en contexte specs */
    --pp-spec-th-w:      4.5rem;     /* largeur colonne clé table specs */
    --pp-spec-th-w-narrow: 3.5rem;   /* largeur réduite en contexte specs */
    --pp-spec-cell-pad:  1.25rem;    /* 20px : padding interne d'une cellule grise (réel .mikespec) */
    --pp-spec-col-gutter: 1.25rem;   /* 20px : gouttière blanche verticale entre les 2 colonnes (réel) */
    --pp-qty-input-w:    2.5rem;     /* largeur champ quantité (compact) */
    --pp-qty-btn-w:      2.25rem;    /* largeur bouton +/- (compact, fin) */
    --pp-qty-h:          2.25rem;    /* hauteur du widget quantité (compact) */

    /* --- Transitions (≤ 300ms micro-interaction, R2.9) --- */
    --pp-transition: 0.2s ease;
    --pp-transition-slow: 0.3s ease;

    /* --- Z-index --- */
    --pp-z-header:    100;
    --pp-z-overlay:   200;
    --pp-z-offcanvas: 210;
    --pp-z-minicart:  220;
    --pp-z-notif:     300;
  }

  /* ============================================================
     2. BASE  (reset minimal, typo, body) — même @layer pp-base (L12)
     ============================================================ */
  *, *::before, *::after { box-sizing: border-box; }

  html { -webkit-text-size-adjust: 100%; text-size-adjust: 100%; overflow-x: clip; }

  body.pp-body {
    margin: 0;
    /* off-canvas/mini-panier sont positionnés hors écran (translateX 100%) :
       clip horizontal (html + body) pour qu'ils ne créent pas de scroll latéral (T10).
       html nécessaire car les panneaux sont position:fixed (relatifs au viewport). */
    overflow-x: clip;
    font-family: var(--pp-font-main);
    font-size: var(--pp-fs-base);
    line-height: var(--pp-lh-normal);
    font-weight: var(--pp-fw-normal);
    color: var(--pp-color-text-main);
    background: var(--pp-color-bg-page);
    -webkit-font-smoothing: antialiased;
    text-rendering: optimizeLegibility;
  }

  /* Resets scopés au body en :where() → specificity (0,0,1), pas (0,1,1) (L6).
     Faciles à surcharger par les composants BEM. */
  :where(.pp-body) img { max-width: 100%; height: auto; }

  :where(.pp-body) a {
    color: var(--pp-color-text-main);
    text-decoration: none;
    transition: color var(--pp-transition);
  }
  :where(.pp-body) a:hover { color: var(--pp-color-primary); }

  :where(.pp-body) h1, :where(.pp-body) h2, :where(.pp-body) h3,
  :where(.pp-body) h4, :where(.pp-body) h5, :where(.pp-body) h6 {
    margin: 0;
    line-height: var(--pp-lh-snug);
    font-weight: var(--pp-fw-bold);
    color: var(--pp-color-text-main);
  }

  :where(.pp-body) p { margin: 0 0 var(--pp-space-sm); }
  :where(.pp-body) p:last-child { margin-bottom: 0; }

  :where(.pp-body) ul, :where(.pp-body) ol { margin: 0; padding: 0; list-style: none; }

  /* Focus visible global (R2.1) */
  .pp-body :focus-visible {
    outline: 2px solid var(--pp-color-primary);
    outline-offset: 2px;
    border-radius: var(--pp-radius-sm);
  }

  /* a11y helpers — V2 : `.screen-reader-text` AJOUTÉ. C'est l'utilitaire WP/WC
     (label quantité « <produit> Menge », textes lecteurs d'écran WC) défini par
     woocommerce.css… que nous dequeuons désormais. Sans cette règle, le label
     quantité devient VISIBLE et gonfle le wrapper .quantity (377px vs 114px banc). */
  .pp-visually-hidden,
  .screen-reader-text {
    position: absolute;
    width: 1px; height: 1px;
    padding: 0; margin: -1px;
    overflow: hidden;
    clip: rect(0 0 0 0);
    clip-path: inset(50%);
    white-space: nowrap;
    border: 0;
  }

  .pp-skip-link {
    position: absolute;
    left: var(--pp-space-2xs);
    top: -100px;
    z-index: calc(var(--pp-z-notif) + 10);
    padding: var(--pp-space-2xs) var(--pp-space-sm);
    background: var(--pp-color-primary);
    color: var(--pp-color-white);
    border-radius: var(--pp-radius-md);
    transition: top var(--pp-transition);
  }
  .pp-skip-link:focus { top: var(--pp-space-2xs); color: var(--pp-color-white); }

  .pp-container {
    width: 100%;
    max-width: var(--pp-container-max);
    margin-inline: auto;
    padding-inline: var(--pp-gutter);
  }
}

/* ============================================================
   3. COMPOSANTS BEM
   ============================================================ */
@layer pp-components {

  /* --------- HEADER (3 zones en Grid) --------- */
  /* Structure RÉELLE du site (MSJ R3 §1) : bloc GAUCHE (nav Shop+Plus) | LOGO central |
     bloc DROITE (langues FR|DE, puis outils search→user→cart, cart tout à droite).
     PAS de ligne horizontale sous le header (MSJ R3 §2 : le site n'en a pas). */
  .pp-header {
    --pp-header-bg: var(--pp-color-bg-page);
    position: relative;
    z-index: var(--pp-z-header);
    background: var(--pp-header-bg);
  }
  .pp-header__inner {
    display: grid;
    /* MOBILE/TABLETTE (mobile-first) : LOGO à GAUCHE (sur le bord du contenu),
       OUTILS à DROITE (sur le bord du contenu). Le 1er 1fr fantôme (nav cachée)
       est retiré → 2 colonnes « logo | tools » (MSJ R3 §3 : 768/390 logo gauche,
       icônes alignées content-width droite). Le centrage 3-blocs arrive en desktop. */
    grid-template-columns: auto 1fr;
    align-items: center;
    gap: var(--pp-space-sm);
    min-height: var(--pp-header-h);
    width: 100%;
    max-width: var(--pp-container-max);
    margin-inline: auto;
    padding-inline: var(--pp-gutter);
  }
  /* Mobile/tablette : la nav primaire (cachée) n'occupe pas de cellule de grille. */
  .pp-header__logo { justify-self: start; line-height: 0; }
  .pp-header__logo img {
    width: var(--pp-logo-width);
    height: auto;
    display: block;
  }
  /* Fallback texte si aucun logo Customizer (L13 : était sans styles) */
  .pp-header__logo-text {
    font-size: var(--pp-fs-xl);
    font-weight: var(--pp-fw-black);
    letter-spacing: var(--pp-ls-wide);
    text-transform: uppercase;
    color: var(--pp-color-text-main);
    line-height: 1;
  }
  .pp-header__tools { justify-self: end; }

  /* Nav principale (gauche) — mobile-first : cachée par défaut, révélée en desktop
     via min-width (L8). Le burger prend le relais en mobile. */
  .pp-nav--primary { justify-self: start; display: none; }
  .pp-nav__list {
    display: flex;
    align-items: center;
    gap: clamp(var(--pp-space-sm), 1.5vw, var(--pp-space-lg));
  }
  .pp-nav__link {
    display: inline-block;
    padding-block: var(--pp-space-2xs);
    font-size: var(--pp-fs-sm);
    font-weight: var(--pp-fw-bold);
    letter-spacing: var(--pp-ls-wide);
    text-transform: uppercase;
    color: var(--pp-color-text-main);
  }
  .pp-nav__link[aria-current="page"] { color: var(--pp-color-primary); }

  /* Sous-menu déroulant (parent « Plus » → Events/Team/Contact), hiérarchie réelle.
     Au survol / focus-within du parent, le sous-menu apparaît en pop dessous. */
  .pp-nav__list .menu-item-has-children { position: relative; }
  /* R9 item 1 — chevron « vers le bas » sur les entrées AVEC sous-menu (référence
     home Shopkeeper : glyphe IcoMoon \e91b 16px, couleur du lien, collé à droite
     du libellé, aligné sur la ligne de texte). La font d'icônes est dequeuée chez
     nous → chevron équivalent en BORDERS (currentColor = suit le hover du lien). */
  .pp-nav--primary .menu-item-has-children > a > .pp-nav__link::after {
    content: "";
    display: inline-block;
    width: 0.4em;
    height: 0.4em;
    margin-left: 0.45em;
    border-right: 1.5px solid currentColor;
    border-bottom: 1.5px solid currentColor;
    transform: rotate(45deg) translateY(-30%);
    vertical-align: middle;
  }
  /* V2 item 12 — WP émet <ul class="sub-menu"> (classe core), le banc utilisait
     .pp-submenu : les deux classes reçoivent le MÊME dropdown. */
  .pp-nav__list .sub-menu,
  .pp-submenu {
    position: absolute;
    top: 100%;
    left: 0;
    min-width: 12rem;
    display: flex;
    flex-direction: column;
    gap: var(--pp-space-2xs);
    padding: var(--pp-space-sm) var(--pp-space-md);
    background: var(--pp-color-bg-page);
    border: var(--pp-border-width) solid var(--pp-color-border);
    box-shadow: var(--pp-shadow-pop);
    opacity: 0;
    visibility: hidden;
    transform: translateY(var(--pp-space-3xs));
    transition: opacity var(--pp-transition), visibility var(--pp-transition), transform var(--pp-transition);
    z-index: calc(var(--pp-z-header) + 1);
  }
  .pp-nav__list .menu-item-has-children:hover > .pp-submenu,
  .pp-nav__list .menu-item-has-children:focus-within > .pp-submenu,
  .pp-nav__list .menu-item-has-children:hover > .sub-menu,
  .pp-nav__list .menu-item-has-children:focus-within > .sub-menu {
    opacity: 1; visibility: visible; transform: translateY(0);
  }
  .pp-submenu .pp-nav__link,
  .pp-nav__list .sub-menu .pp-nav__link { display: block; padding-block: var(--pp-space-3xs); white-space: nowrap; }

  /* Outils — ORDRE COHÉRENT PARTOUT (MSJ R3 §3) : langues FR|DE, puis RECHERCHE,
     USER, CADDIE (caddie tout à droite), + burger en dernier sur mobile/tablette.
     L'ordre est porté par le DOM (header.php + banc). Alignés À DROITE, sur le bord
     du contenu (le bloc droite est justify-self:end dans la grille). */
  .pp-tools {
    display: flex;
    align-items: center;
    justify-content: flex-end;
    gap: var(--pp-tools-gap); /* resserré (MSJ R2 v2 §2c) */
  }
  /* Boutons outils RESSERRÉS visuellement (largeur réduite) tout en gardant une
     cible tactile de 44px de HAUT (a11y) — MSJ R2 v2 §2c. */
  .pp-tools__btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: var(--pp-tools-btn-w);
    height: var(--pp-tap-min);
    padding: 0;
    border: 0;
    background: none;
    color: var(--pp-color-text-main);
    cursor: pointer;
    position: relative;
  }
  .pp-tools__btn:hover { color: var(--pp-color-primary); }
  .pp-tools__btn svg { width: var(--pp-icon-size); height: var(--pp-icon-size); }

  .pp-cart-count {
    position: absolute;
    top: var(--pp-space-3xs); right: var(--pp-space-3xs);
    min-width: var(--pp-cart-count-size); height: var(--pp-cart-count-size);
    padding-inline: var(--pp-space-3xs);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-size: var(--pp-fs-xs);
    font-weight: var(--pp-fw-bold);
    line-height: 1;
    color: var(--pp-color-white);
    background: var(--pp-color-primary);
    border-radius: var(--pp-radius-pill);
  }

  /* Switcher de langue */
  .pp-lang {
    display: inline-flex;
    align-items: center;
    gap: var(--pp-space-3xs);
    margin-right: var(--pp-space-2xs);
  }
  .pp-lang__link {
    font-size: var(--pp-fs-sm);
    font-weight: var(--pp-fw-bold);
    text-transform: uppercase;
    letter-spacing: var(--pp-ls-wide);
    color: var(--pp-color-text-muted);
  }
  .pp-lang__link[aria-current="page"] { color: var(--pp-color-primary); }
  .pp-lang__sep { color: var(--pp-color-border-strong); }

  /* Mobile-first : le switcher langue du HEADER est masqué par défaut (repris
     dans l'off-canvas) ; révélé en desktop. Scopé .pp-tools pour ne PAS toucher
     le switcher du footer ni celui de l'off-canvas (L8). */
  .pp-tools .pp-lang { display: none; }

  /* Mobile-first : l'icône COMPTE est RETIRÉE de la barre header (reprise dans
     l'off-canvas en entrée « Mon compte » / « Konto ») ; révélée en desktop (≥64em).
     La barre mobile ne garde donc que : recherche, panier, burger. */
  .pp-tools__btn--account { display: none; }

  /* Mobile-first : le burger est visible par défaut, masqué en desktop (L8). */
  .pp-tools__btn--burger { display: inline-flex; }

  /* --------- OFF-CANVAS (burger) --------- */
  .pp-overlay {
    position: fixed;
    inset: 0;
    background: var(--pp-color-overlay);
    opacity: 0;
    visibility: hidden;
    z-index: var(--pp-z-overlay);
    transition: opacity var(--pp-transition-slow), visibility var(--pp-transition-slow);
  }
  .pp-overlay.is-visible { opacity: 1; visibility: visible; }

  .pp-offcanvas {
    position: fixed;
    top: 0; right: 0;
    height: 100%;
    width: min(320px, 86vw);
    background: var(--pp-color-bg-page);
    z-index: var(--pp-z-offcanvas);
    transform: translateX(100%);
    transition: transform var(--pp-transition-slow);
    overflow-y: auto;
    padding: var(--pp-space-lg) var(--pp-space-md);
    box-shadow: var(--pp-shadow-pop);
  }
  .pp-offcanvas.is-open { transform: translateX(0); }
  .pp-offcanvas__close {
    margin-left: auto;
    margin-bottom: var(--pp-space-md);
  }
  .pp-offcanvas__nav + .pp-offcanvas__nav { margin-top: var(--pp-space-md); }
  .pp-offcanvas__list { display: flex; flex-direction: column; gap: var(--pp-space-2xs); }
  /* En off-canvas : le sous-menu « Plus » reste déplié en liste indentée (mobile). */
  .pp-offcanvas__list .pp-submenu {
    position: static;
    opacity: 1; visibility: visible; transform: none;
    box-shadow: none; border: 0; background: none;
    padding: var(--pp-space-2xs) 0 0 var(--pp-space-md);
    min-width: 0;
  }
  .pp-offcanvas__link {
    display: block;
    padding-block: var(--pp-space-2xs);
    font-size: var(--pp-fs-md);
    font-weight: var(--pp-fw-bold);
    letter-spacing: var(--pp-ls-wide);
    text-transform: uppercase;
  }
  /* Entrée COMPTE dans l'off-canvas (icône user + libellé) — reprise de l'icône
     retirée de la barre header en mobile. Posée après le menu, avant la langue. */
  .pp-offcanvas__account {
    display: flex;
    align-items: center;
    gap: var(--pp-space-2xs);
    margin-top: var(--pp-space-md);
    color: inherit;
  }
  .pp-offcanvas__account svg { width: var(--pp-icon-size); height: var(--pp-icon-size); flex: none; }
  .pp-offcanvas__account .pp-offcanvas__link { padding-block: 0; }
  .pp-offcanvas__account:hover { color: var(--pp-color-primary); }
  /* La langue qui suit l'entrée compte garde son espacement (le sélecteur
     .pp-offcanvas__nav + .pp-offcanvas__nav ne s'applique plus, l'<a> s'intercale). */
  .pp-offcanvas__account + .pp-offcanvas__nav { margin-top: var(--pp-space-md); }

  /* ZONE UTILITAIRE — fond subtil pleine largeur pour séparer visuellement les
     menus (navigation) de la zone compte/langue/recherche. Full-bleed via marges
     négatives compensant le padding du panneau (--pp-space-md = 1.5rem). */
  .pp-offcanvas__util {
    margin-top: var(--pp-space-lg);
    margin-inline: calc(-1 * var(--pp-space-md));
    padding: var(--pp-space-md);
    background: var(--pp-color-bg-subtle);
  }
  /* À l'intérieur de la zone utilitaire : réinitialiser les marges-top des éléments
     enfants qui suivaient la logique de l'ancien off-canvas sans wrapper. */
  .pp-offcanvas__util .pp-offcanvas__account { margin-top: 0; }
  .pp-offcanvas__util .pp-offcanvas__account + .pp-offcanvas__nav { margin-top: var(--pp-space-sm); }
  .pp-offcanvas__util .pp-search { margin-top: var(--pp-space-sm); }

  /* --------- MINI-PANIER (slide-out) --------- */
  .pp-minicart {
    position: fixed;
    top: 0; right: 0;
    height: 100%;
    width: min(360px, 90vw);
    background: var(--pp-color-bg-page);
    z-index: var(--pp-z-minicart);
    transform: translateX(100%);
    transition: transform var(--pp-transition-slow);
    overflow-y: auto;
    box-shadow: var(--pp-shadow-pop);
    display: flex;
    flex-direction: column;
  }
  .pp-minicart.is-open { transform: translateX(0); }
  /* R3 item 6 — modale PLUS LARGE en desktop (le texte sautait à 360px) ; en
     mobile/small la même modale garde sa largeur compacte (règle de base). */
  @media (min-width: 48em) {
    .pp-minicart { width: 30rem; } /* 480px */
  }
  .pp-minicart__head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: var(--pp-space-md);
    border-bottom: var(--pp-border-width) solid var(--pp-color-border);
  }
  .pp-minicart__title {
    font-size: var(--pp-fs-md);
    text-transform: uppercase;
    letter-spacing: var(--pp-ls-wide);
  }
  .pp-minicart__body { padding: var(--pp-space-md); }

  /* --------- SEARCH (form GET) — variante off-canvas (burger mobile) --------- */
  .pp-search {
    display: flex;
    gap: var(--pp-space-2xs);
    margin-top: var(--pp-space-md);
  }
  .pp-search__input {
    flex: 1;
    min-width: 0;
    padding: var(--pp-space-2xs) var(--pp-space-xs);
    font: inherit;
    font-size: var(--pp-fs-base);
    color: var(--pp-color-text-main);
    border: var(--pp-border-width) solid var(--pp-color-border-strong);
    border-radius: var(--pp-radius-square); /* ANGLES CARRÉS (MSJ R2 v2 §7) */
    background: var(--pp-color-bg-page);
  }
  .pp-search__submit {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: var(--pp-tap-min);
    border: 0;
    background: var(--pp-color-primary);
    color: var(--pp-color-white);
    border-radius: var(--pp-radius-square); /* ANGLES CARRÉS (MSJ R2 v2 §7) */
    cursor: pointer;
  }
  .pp-search__submit svg { width: var(--pp-icon-size); height: var(--pp-icon-size); }

  /* --------- SEARCHBAR (overlay qui DESCEND et recouvre le header, MSJ R2 v2 §3) ---------
     Reproduit l'off-canvas top du site (« Recherche de produits… »). Panneau
     position:fixed en haut, translateY(-100%) au repos, glisse vers le bas à
     l'ouverture. Champ + bouton « Rechercher » dans nos couleurs. Accessible :
     role=dialog, focus auto sur le champ, Escape ferme, focus trap (JS Panel). */
  .pp-searchbar {
    position: fixed;
    top: 0; left: 0; right: 0;
    z-index: var(--pp-z-minicart); /* au-dessus du header */
    background: var(--pp-color-bg-page);
    box-shadow: var(--pp-shadow-pop);
    transform: translateY(-100%);
    transition: transform var(--pp-transition-slow);
    padding-block: var(--pp-space-md);
  }
  .pp-searchbar.is-open { transform: translateY(0); }
  .pp-searchbar__inner {
    width: 100%;
    max-width: var(--pp-container-max);
    margin-inline: auto;
    padding-inline: var(--pp-gutter);
    display: flex;
    align-items: center;
    gap: var(--pp-space-sm);
  }
  .pp-searchbar__form {
    flex: 1;
    min-width: 0;
    display: flex;
    align-items: stretch;
    gap: var(--pp-space-2xs);
  }
  .pp-searchbar__input {
    flex: 1;
    min-width: 0;
    padding: var(--pp-space-2xs) var(--pp-space-sm);
    min-height: var(--pp-tap-min);
    font: inherit;
    font-size: var(--pp-fs-md);
    color: var(--pp-color-text-main);
    border: var(--pp-border-width) solid var(--pp-color-border-strong);
    border-radius: var(--pp-radius-square); /* champ carré, cohérent boutons (MSJ §7) */
    background: var(--pp-color-bg-page);
  }
  .pp-searchbar__submit {
    flex: none;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--pp-space-2xs);
    min-height: var(--pp-tap-min);
    padding-inline: var(--pp-space-lg);
    border: 0;
    background: var(--pp-color-primary);
    color: var(--pp-color-white);
    border-radius: var(--pp-radius-square);
    font: inherit;
    font-size: var(--pp-fs-base);
    font-weight: var(--pp-fw-bold);
    text-transform: uppercase;
    letter-spacing: var(--pp-ls-wide);
    cursor: pointer;
    transition: background var(--pp-transition);
  }
  .pp-searchbar__submit:hover { background: var(--pp-color-primary-hover); color: var(--pp-color-white); }
  .pp-searchbar__close {
    flex: none;
    margin-left: var(--pp-space-2xs);
  }

  /* --------- MAIN / ARTICLE PRODUIT --------- */
  .pp-main { display: block; }

  .pp-product {
    display: flex;
    flex-direction: column;
    gap: var(--pp-container-gap);
    /* R3 item 9 : respiration sous le header (76px desktop, mesuré entre l'ancien
       81px et l'ancien nôtre 64px) ; le bas garde l'espacement précédent. */
    padding-block: var(--pp-main-top) var(--pp-space-xl);
  }

  /* Overview : galerie + résumé (2 colonnes en desktop) */
  .pp-overview {
    display: grid;
    grid-template-columns: 1fr;
    gap: var(--pp-grid-gap);
    align-items: start;
  }

  /* --------- GALERIE (1 photo, figure) --------- */
  /* Bouteille posée sur FOND BLANC PUR : aucun cadre, fond gris, liseré ni ombre
     (demande MSJ). La photo « flotte » sur --pp-color-bg-page. */
  /* En 1 COLONNE (mobile/tablette) : largeur plafonnée + CENTRÉE horizontalement
     (MSJ R3 §5 — révision : plus alignée à gauche). margin-inline:auto = centrage.
     Le plafond saute en desktop 2 colonnes (la photo reprend la largeur de sa colonne). */
  .pp-gallery {
    margin: 0 auto;
    max-width: var(--pp-gallery-max-1col);
    width: 100%;
  }
  .pp-gallery__frame {
    display: block;
    width: 100%;
    cursor: zoom-in;
    background: var(--pp-color-bg-page);
  }
  .pp-gallery__img {
    display: block;
    width: 100%;
    height: auto;
    aspect-ratio: 618 / 856;
    object-fit: contain;
  }
  .pp-gallery__badge {
    display: inline-block;
    margin-bottom: var(--pp-space-2xs);
    padding: var(--pp-space-3xs) var(--pp-space-2xs);
    font-size: var(--pp-fs-xs);
    font-weight: var(--pp-fw-bold);
    text-transform: uppercase;
    letter-spacing: var(--pp-ls-wide);
    color: var(--pp-color-white);
    background: var(--pp-color-primary);
    border-radius: var(--pp-radius-square); /* badge carré (MSJ R2 v2 §7) */
  }

  /* Lightbox vanilla minimale */
  .pp-lightbox {
    position: fixed;
    inset: 0;
    z-index: calc(var(--pp-z-notif) + 5);
    display: flex;
    align-items: center;
    justify-content: center;
    padding: var(--pp-space-lg);
    background: var(--pp-color-overlay);
    opacity: 0;
    visibility: hidden;
    transition: opacity var(--pp-transition-slow), visibility var(--pp-transition-slow);
  }
  .pp-lightbox.is-open { opacity: 1; visibility: visible; cursor: zoom-out; }
  .pp-lightbox__img {
    max-width: 92vw;
    max-height: 88vh;
    width: auto; height: auto;
    box-shadow: var(--pp-shadow-pop);
  }
  .pp-lightbox__close {
    position: absolute;
    top: var(--pp-space-md);
    right: var(--pp-space-md);
    color: var(--pp-color-white);
  }

  /* --------- SUMMARY (titre, prix, étoiles, ACF, add-to-cart) --------- */
  .pp-summary {
    display: flex;
    flex-direction: column;
    gap: var(--pp-content-gap);
  }
  /* Titre = DISCRET comme le réel (28px/600), pas un display 50px/900 (critique #1).
     Fluide léger 24→30px, jamais énorme. Le réel pèse 28.4px weight 600. */
  .pp-summary__title {
    font-size: clamp(1.5rem, 1.35rem + 0.6vw, 1.875rem); /* 24 → 30px */
    font-weight: var(--pp-fw-semibold); /* 600 comme le réel — surtout PAS black/900 */
    line-height: var(--pp-lh-tight);
    color: var(--pp-color-text-main);
  }
  /* V2 — l'extrait WC (woocommerce_template_single_excerpt) émet le markup natif
     SANS notre classe pp-summary__excerpt : on étend le sélecteur à la classe WC,
     scopée à .pp-summary (pas de hack markup, fingerprint 2026-06-11 écart #3). */
  .pp-summary__excerpt,
  .pp-summary .woocommerce-product-details__short-description {
    max-inline-size: var(--pp-prose-max);
    color: var(--pp-color-text-muted);
    font-size: var(--pp-fs-md);
  }
  .pp-summary__meta {
    display: flex;
    flex-direction: column;
    gap: var(--pp-space-3xs);
    font-size: var(--pp-fs-base);
  }
  .pp-summary__meta b { font-weight: var(--pp-fw-bold); color: var(--pp-color-text-main); }

  /* Bloc PRIX → LIVRAISON → UNITÉ : COMPACT, sans gaspiller de real estate vertical
     (MSJ R2 v2 §9). Le flex gap du .pp-summary (1rem) est resserré ici à 3xs entre
     ces trois lignes via marges négatives ciblées + line-height serré. */
  .pp-delivery {
    align-self: flex-start;
    margin-top: calc(-1 * var(--pp-content-gap) + var(--pp-space-3xs));
    /* Police EXACTE du site : .bluemsj = texte courant (PAS bold), bleu #0059FF. */
    font-weight: var(--pp-fw-normal);
    font-size: var(--pp-fs-base);
    line-height: var(--pp-lh-snug);
    color: var(--pp-color-link-delivery);
  }
  .pp-unit {
    margin-top: calc(-1 * var(--pp-content-gap) + var(--pp-space-3xs));
    color: var(--pp-color-text-muted);
    font-size: var(--pp-fs-base);
    line-height: var(--pp-lh-snug);
  }
  /* État rupture de stock (L13 : était sans styles) */
  .pp-out-of-stock {
    align-self: flex-start;
    font-weight: var(--pp-fw-bold);
    color: var(--pp-color-error);
  }

  /* R8 item 2 — cépages sur UNE ligne (« 60% Garnacha, 40% Cariñena »).
     Typo du bloc conservée (mêmes taille/couleur que les <p> des specs) ;
     chaque paire %–nom est insécable, le wrap se fait ENTRE paires. */
  .pp-cepages {
    margin: 0;
    line-height: var(--pp-lh-normal); /* wrap confortable entre paires */
  }
  .pp-cepages__item { white-space: nowrap; }

  /* --------- PRODUCT META (UGS / Catégories / Étiquettes) — maillage WC --------- */
  /* Rendu réel : petites capitales grises, libellés + liens vers catégories. */
  .product_meta, .pp-product-meta {
    display: flex;
    flex-direction: column;
    gap: var(--pp-space-3xs);
    margin-top: var(--pp-space-sm);
    font-size: var(--pp-fs-xs);
    color: var(--pp-color-text-muted);
    text-transform: uppercase;
    letter-spacing: var(--pp-ls-wide);
  }
  .pp-product-meta a, .product_meta a { color: var(--pp-color-text-muted); }
  .pp-product-meta a:hover, .product_meta a:hover { color: var(--pp-color-primary); }
  .pp-product-meta .sku, .product_meta .sku { color: var(--pp-color-text-main); }

  /* --------- BREADCRUMB --------- */
  /* MAJUSCULES + compact (rendu réel). JAMAIS de troncature/ellipsis (MSJ R2 v2) :
     une ligne quand ça tient, SAUT DE LIGNE propre sinon (white-space: normal +
     overflow-wrap). Le 1er segment « Accueil » est retiré côté template (filtre WC). */
  /* Discret comme le réel (critique #9) : ~11px, gris pâle, pas de tracking. Le réel
     est à rgba(86,86,86,.55)=#a2a2a2 (contraste 2.55, échoue WCAG AA). On retient le
     gris AA-minimum #767676 (contraste 4.54 sur blanc) : reste un fil d'Ariane discret
     ET accessible (doctrine PAMISA WCAG AA / 0 violation sérieuse). Majuscules gardées. */
  .pp-breadcrumb {
    font-size: 0.6875rem; /* ~11px (le réel ~10px) */
    color: var(--pp-color-breadcrumb);
    line-height: var(--pp-lh-snug);
    text-transform: uppercase;
    letter-spacing: normal;
    white-space: normal;
    overflow-wrap: anywhere;
    word-break: normal;
    max-width: 100%;
  }
  .pp-breadcrumb a { color: var(--pp-color-breadcrumb); white-space: nowrap; }
  .pp-breadcrumb a:hover { color: var(--pp-color-primary); }
  .pp-breadcrumb [aria-current="page"] { color: var(--pp-color-breadcrumb); }
  .pp-breadcrumb .breadcrump_sep { color: var(--pp-color-border-strong); margin-inline: var(--pp-space-3xs); }

  /* --------- SPECS (cellules grises indépendantes sur fond blanc) --------- */
  /* STRUCTURE RÉELLE pamisa.ch (`.mikespec`, mesurée 2026-06-10) — chaque section
     (Cépages | Terroir | Vieillissement à gauche ; Labels | Information | Organoleptique
     à droite) est une CELLULE GRISE INDÉPENDANTE (#f9f9f9) posée sur le fond BLANC de la
     page. Les séparations sont des GOUTTIÈRES BLANCHES (le blanc qui transparaît), JAMAIS
     des bordures dessinées ni un seul gros bloc gris. Mécanique fidèle au réel :
       • bordure 1px blanche PAR cellule → fine gouttière horizontale ~2px entre cellules
         empilées (réel : .mikespec { border:1px solid white });
       • gouttière VERTICALE ~20px entre les deux colonnes = column-gap de la grille (réel :
         padding 10px+10px des colonnes Foundation .large-6).
     AUCUN background / padding / border-radius sur le CONTENEUR : le fond blanc reste
     visible partout entre les cellules. Responsive : 2 colonnes ≥64em (≈1024px), sinon
     1 colonne empilée (le réel stacke dès 768) — mêmes gouttières dans les deux cas. */
  .pp-specs {
    /* API locale : la table cépages se reconfigure via ces variables HÉRITÉES
       (L4/L10), pas via des sélecteurs descendants .pp-specs .pp-spec-table. */
    --pp-spec-table-max-w: var(--pp-spec-table-w);
    --pp-spec-table-th-align: right;
    --pp-spec-table-td-color: var(--pp-color-text-main);
    --pp-spec-table-border: none; /* aucune bordure interne : la table cépages = texte plat (réel pamisa.ch = texte inline, MSJ R4 §1) */
    --pp-spec-table-th-w: var(--pp-spec-th-w-narrow);

    display: grid;
    grid-template-columns: 1fr;   /* 1 colonne : mobile + tablette (réel stacke <1024px) */
    /* pas de gap : les cellules se touchent, leur bordure blanche fait la gouttière */
  }
  /* Une colonne = pile verticale de cellules grises ; elles se touchent, la bordure
     blanche 1px de chaque cellule crée la fine gouttière horizontale (~2px) du réel. */
  .pp-specs__col { display: flex; flex-direction: column; }
  /* Look « petit titre capitales » conservé même en h3 (D : restyle identique). */
  .pp-specs__heading {
    font-size: var(--pp-fs-sm);
    font-weight: var(--pp-fw-bold);
    text-transform: uppercase;
    letter-spacing: var(--pp-ls-wider);
    color: var(--pp-color-text-main);
    text-align: center;
    margin-bottom: var(--pp-space-2xs);
  }
  /* CHAQUE groupe = cellule grise indépendante (réel : .mikespec). La cellule remplit
     toute la largeur de sa colonne ; la bordure blanche 1px EST la gouttière. */
  .pp-specs__group {
    background: var(--pp-color-bg-specs);                          /* gris PAR CELLULE (#f9f9f9) */
    border: var(--pp-border-width) solid var(--pp-color-bg-page);  /* gouttière blanche 1px */
    padding: var(--pp-spec-cell-pad);                             /* 20px interne (réel) */
    text-align: center;
  }
  .pp-specs__group p { font-size: var(--pp-fs-base); color: var(--pp-color-text-muted); }
  .pp-specs .pp-tags { justify-content: center; }

  /* Table clé/valeur réelle pour cépages — défauts « généraux » via var(--x, def),
     surchargés par l'héritage du contexte .pp-specs (L4/L10), sans descendant. */
  .pp-spec-table {
    width: 100%;
    max-width: var(--pp-spec-table-max-w, 100%);
    margin-inline: auto;
    border-collapse: collapse;
    font-size: var(--pp-fs-base);
  }
  /* Séparateurs PARTOUT (MSJ R2 v2 §15) : haut + bas sur chaque cellule → la 1re et
     la dernière ligne sont aussi délimitées (pas seulement les inter-lignes). */
  .pp-spec-table th, .pp-spec-table td {
    padding: var(--pp-space-2xs) var(--pp-space-sm);
    border-block: var(--pp-spec-table-border, var(--pp-border-width) solid var(--pp-color-border));
    vertical-align: top;
  }
  .pp-spec-table th {
    text-align: var(--pp-spec-table-th-align, left);
    font-weight: var(--pp-fw-bold);
    color: var(--pp-color-text-main);
    white-space: nowrap;
    width: var(--pp-spec-table-th-w, var(--pp-spec-th-w));
  }
  /* séparateur vertical hairline entre clé et valeur (rendu réel grille) */
  .pp-spec-table td {
    text-align: left;
    color: var(--pp-spec-table-td-color, var(--pp-color-text-muted));
    border-left: var(--pp-spec-table-border, var(--pp-border-width) solid var(--pp-color-border));
  }

  /* Tags bio/vegan/naturel — HASHTAGS TEXTE rouges (rendu réel : .product-tags-links),
     pas des pills. Liste sémantique conservée (a11y) mais affichée inline en texte. */
  .pp-tags {
    display: inline-flex;
    flex-wrap: wrap;
    gap: var(--pp-space-sm);
    justify-content: center;
  }
  .pp-tags__item {
    display: inline;
    font-size: var(--pp-fs-md);
    font-weight: var(--pp-fw-bold);
    color: var(--pp-color-primary);
  }
  .pp-tags__item a { color: var(--pp-color-primary); }
  .pp-tags__item a:hover { color: var(--pp-color-primary-hover); }

  /* --------- BODEGA / AOC (prose, 2 colonnes) --------- */
  .pp-origins {
    display: grid;
    grid-template-columns: 1fr;
    gap: var(--pp-grid-gap);
    padding: var(--pp-space-xl) 0 0;
    border-top: var(--pp-border-width) solid var(--pp-color-border);
  }
  /* block parent + modifiers (L13 : étaient sans styles) */
  .pp-origin { display: flex; flex-direction: column; }
  /* Titres Bodega/AOC = 600 comme le réel (critique #7 : on les avait en 300 light). */
  .pp-origin__title {
    font-size: clamp(1.5rem, 1.35rem + 0.6vw, 1.875rem); /* aligné sur le h1 réel ~28px */
    font-weight: var(--pp-fw-semibold);
    margin-bottom: var(--pp-space-3xs);
  }
  .pp-origin__sub {
    font-size: var(--pp-fs-md);
    font-weight: var(--pp-fw-bold);
    color: var(--pp-color-text-muted);
    margin-bottom: var(--pp-space-sm);
  }
  .pp-origin__body { max-inline-size: var(--pp-prose-max); color: var(--pp-color-text-muted); }
  .pp-origin__body p { font-size: var(--pp-fs-base); }

  /* --------- LIRE PLUS (compact + déroulant) — MSJ R3 §7 ---------
     Progressive enhancement : SANS JS, le texte est INTÉGRAL (aucune coupe). Le clamp
     n'est posé QUE par JS (classe is-clamped sur le wrapper) et seulement si le texte
     dépasse le seuil. line-clamp ~9 lignes (calibré sur le rendu que MSJ aime). Bouton
     « Lire plus » discret en couleur d'accent ; « Réduire » pour refermer. */
  .pp-origin__more {
    /* wrapper du texte clampable — pas de style propre tant que JS n'agit pas */
    position: relative;
  }
  .pp-origin__more.is-clamped .pp-origin__more-text {
    display: -webkit-box;
    -webkit-line-clamp: 9;
    line-clamp: 9;
    -webkit-box-orient: vertical;
    overflow: hidden;
  }
  /* Bouton « Lire plus / Réduire » : injecté par JS, masqué sans JS (jamais rendu). */
  .pp-origin__toggle {
    appearance: none;
    margin-top: var(--pp-space-2xs);
    padding: var(--pp-space-3xs) 0;
    border: 0;
    background: none;
    font: inherit;
    font-size: var(--pp-fs-sm);
    font-weight: var(--pp-fw-bold);
    color: var(--pp-color-primary); /* couleur ACCENT (MSJ R3 §7) */
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    gap: var(--pp-space-3xs);
  }
  .pp-origin__toggle:hover { color: var(--pp-color-primary-hover); }
  /* Le « + » devient « − » à l'ouverture (piloté par le libellé JS + aria-expanded). */

  /* --------- ONGLETS --------- */
  .pp-tabs { display: block; }
  .pp-tabs__nav {
    display: flex;
    gap: var(--pp-space-md);
    border-bottom: var(--pp-border-width) solid var(--pp-color-border);
    margin-bottom: var(--pp-space-md);
  }
  /* Onglet AVIS plus sobre, proche du réel (critique #11 : on l'avait 17px/700/MAJ). */
  .pp-tabs__tab {
    appearance: none;
    border: 0;
    background: none;
    padding: var(--pp-space-2xs) 0;
    font: inherit;
    font-size: var(--pp-fs-sm); /* ~13px comme le réel */
    font-weight: var(--pp-fw-semibold);
    text-transform: uppercase;
    letter-spacing: var(--pp-ls-wide);
    color: var(--pp-color-text-muted);
    cursor: pointer;
    border-bottom: var(--pp-border-width-bold) solid transparent;
    margin-bottom: calc(-1 * var(--pp-border-width)); /* chevauche la bordure de la nav */
  }
  .pp-tabs__tab[aria-selected="true"] {
    color: var(--pp-color-primary);
    border-bottom-color: var(--pp-color-primary);
  }
  .pp-tabs__panel { max-inline-size: var(--pp-prose-max); }
  .pp-tabs__panel[hidden] { display: none; }

  /* V2 (sweep systémique post-dequeue woocommerce.css) — onglets WC NATIFS.
     Le live rend les onglets WC (C7 pendant) : leur nav (ul.wc-tabs) était stylée
     par woocommerce(-layout).css, désormais dequeués → on la restyle sur le modèle
     des .pp-tabs du banc (uppercase, accent, soulignement). Le panel WC reçoit la
     largeur prose comme .pp-tabs__panel. */
  .pp-tabs-section ul.wc-tabs {
    display: flex;
    gap: var(--pp-space-md);
    margin: 0 0 var(--pp-space-md);
    padding: 0;
    list-style: none;
    border-bottom: var(--pp-border-width) solid var(--pp-color-border);
  }
  .pp-tabs-section ul.wc-tabs li { margin: 0; padding: 0; list-style: none; }
  .pp-tabs-section ul.wc-tabs li a {
    display: inline-block;
    padding: var(--pp-space-2xs) 0;
    font-size: var(--pp-fs-sm);
    font-weight: var(--pp-fw-semibold);
    text-transform: uppercase;
    letter-spacing: var(--pp-ls-wide);
    color: var(--pp-color-primary);
    border-bottom: var(--pp-border-width-bold) solid var(--pp-color-primary);
    margin-bottom: calc(-1 * var(--pp-border-width));
  }
  .pp-tabs-section .woocommerce-Tabs-panel { max-inline-size: var(--pp-prose-max); }
  .pp-tabs-section .woocommerce-Reviews-title {
    margin: 0 0 var(--pp-space-sm);
    font-size: var(--pp-fs-md);
    font-weight: var(--pp-fw-semibold);
  }
  .pp-tabs-section .woocommerce-review__verified {
    font-size: var(--pp-fs-xs);
    color: var(--pp-color-text-muted);
  }

  /* --------- AVIS COMPACTS (MSJ R2 v2 §10) ---------
     Affichage DIRECT des avis récents : par avis = une ligne compacte
     « nom + étoiles (accent) » puis le texte. Police compacte, jusqu'à 10 avis.
     En prod : style les classes générées par Customer Reviews (commentlist /
     woocommerce-review__author / star-rating) pour obtenir CE rendu sans toucher
     au plugin. Le banc simule avec les 4 vrais avis sauvegardés. */
  .pp-reviews { display: flex; flex-direction: column; gap: var(--pp-space-sm); }
  .pp-reviews__summary {
    font-size: var(--pp-fs-sm);
    color: var(--pp-color-text-muted);
    margin-bottom: var(--pp-space-2xs);
  }
  /* V2 (consigne MSJ « pourquoi les encadrés ? non, rien ») — les sélecteurs sont
     élargis de .pp-tabs__panel à .pp-tabs-section : les onglets LIVE sont WC natifs
     (décision C7 pendante) et la liste d'avis vit hors .pp-tabs__panel. Liste PLATE :
     nom · étoiles · date · texte — AUCUNE carte/bordure/fond, AUCUN avatar. */
  .pp-reviews__list,
  .pp-tabs-section ol.commentlist {
    display: flex;
    flex-direction: column;
    gap: var(--pp-space-sm);
    margin: 0; padding: 0; list-style: none;
  }
  .pp-review,
  .pp-tabs-section ol.commentlist > li {
    display: flex;
    flex-direction: column;
    gap: var(--pp-space-3xs);
    margin: 0;
    padding: 0 0 var(--pp-space-sm);
    border: 0;
    background: none;
    box-shadow: none;
    border-bottom: var(--pp-border-width) solid var(--pp-color-border);
    list-style: none;
  }
  .pp-review:last-child,
  .pp-tabs-section ol.commentlist > li:last-child { border-bottom: 0; padding-bottom: 0; }
  /* Ligne 1 = nom + étoiles (accent) côte à côte, compacte. */
  .pp-review__head,
  .pp-tabs-section ol.commentlist p.meta {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: var(--pp-space-2xs);
    margin: 0;
    font-size: var(--pp-fs-sm);
  }
  .pp-review__author,
  .pp-tabs-section .woocommerce-review__author {
    font-weight: var(--pp-fw-bold);
    font-style: normal;
    color: var(--pp-color-text-main);
  }
  .pp-review__date,
  .pp-tabs-section .woocommerce-review__published-date {
    font-size: var(--pp-fs-xs);
    color: var(--pp-color-text-muted);
  }
  .pp-review__text,
  .pp-tabs-section .description p {
    margin: 0;
    font-size: var(--pp-fs-base);
    color: var(--pp-color-text-muted);
    line-height: var(--pp-lh-snug);
  }
  /* Avatars gravatar MASQUÉS (consigne MSJ) ; les wrappers WC (comment_container /
     comment-text) sont aplatis en display:contents pour que la colonne flex du <li>
     pilote directement étoiles / méta / texte. Le formulaire d'avis n'est pas touché. */
  .pp-tabs-section ol.commentlist .avatar { display: none; }
  .pp-tabs-section ol.commentlist .comment_container,
  .pp-tabs-section ol.commentlist .comment-text {
    display: contents;
  }
  /* Les étoiles WC dans un avis restent en couleur d'accent (héritent .star-rating). */

  /* --------- PRODUITS LIÉS --------- */
  .pp-related { padding-top: var(--pp-space-xl); border-top: var(--pp-border-width) solid var(--pp-color-border); }
  .pp-related__heading {
    font-size: var(--pp-fs-xl);
    font-weight: var(--pp-fw-light);
    text-transform: uppercase;
    letter-spacing: var(--pp-ls-wide);
    margin-bottom: var(--pp-space-md);
  }

  /* --------- NOTIFICATION POPUP (slide-out, reproduite à l'identique) --------- */
  .pp-notif {
    position: fixed;
    right: var(--pp-space-md);
    bottom: var(--pp-space-md);
    z-index: var(--pp-z-notif);
    width: min(360px, calc(100vw - 2 * var(--pp-space-md)));
    background: var(--pp-color-bg-page);
    border-radius: var(--pp-radius-square); /* notification carrée (MSJ R2 v2 §7) */
    box-shadow: var(--pp-shadow-pop);
    overflow: hidden;
    transform: translateX(calc(100% + var(--pp-space-lg)));
    opacity: 0;
    transition: transform var(--pp-transition-slow), opacity var(--pp-transition-slow);
    pointer-events: none;
  }
  .pp-notif.is-open { transform: translateX(0); opacity: 1; pointer-events: auto; }
  .pp-notif--error { border-left: var(--pp-border-width-accent) solid var(--pp-color-error); }
  .pp-notif__inner {
    display: grid;
    grid-template-columns: var(--pp-notif-thumb-size) 1fr; /* DRY : lié au thumb (L3) */
    gap: var(--pp-space-sm);
    align-items: center;
    padding: var(--pp-space-sm);
  }
  .pp-notif__thumb {
    width: var(--pp-notif-thumb-size); height: var(--pp-notif-thumb-size);
    background-size: cover;
    background-position: center;
    background-color: var(--pp-color-bg-subtle);
    border-radius: var(--pp-radius-sm);
  }
  .pp-notif__text { font-size: var(--pp-fs-sm); color: var(--pp-color-text-main); }
  .pp-notif__btn {
    display: inline-block;
    margin-top: var(--pp-space-2xs);
    font-weight: var(--pp-fw-bold);
    color: var(--pp-color-primary);
    text-decoration: underline;
  }

  /* --------- FOOTER (dark, rendu réel) --------- */
  .pp-footer {
    background: var(--pp-color-bg-footer);
    color: var(--pp-color-text-on-dark);
    padding-top: var(--pp-space-xl);
    margin-top: var(--pp-space-2xl);
  }

  /* CONTACT (coordonnées + showroom + newsletter) — AVANT les colonnes de liens
     (MSJ R2 v2 §12 : « plus important que les liens régions »). Présentation compacte :
     mobile = stacké ; tablette/desktop = 2-3 colonnes (adresse | showroom | newsletter). */
  /* MOBILE 390 (MSJ R3 §6e) : coordonnées | showroom en GRID 2 COLONNES (comme les
     colonnes Régions/Producteurs en dessous) ; le CTA newsletter seul sur sa ligne,
     CENTRÉ (span 2 colonnes + justify-self center). Tablette/desktop : 3 colonnes (§6). */
  .pp-footer__contact {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: var(--pp-grid-gap);
    padding-bottom: var(--pp-space-lg);
    margin-bottom: var(--pp-space-lg);
    border-bottom: var(--pp-border-width) solid var(--pp-color-on-dark-border);
  }
  .pp-footer__contact-block--cta {
    grid-column: 1 / -1;       /* le CTA occupe toute la largeur de ligne */
    justify-self: center;      /* … et se centre (MSJ R3 §6e) */
  }
  .pp-footer__contact-block { font-size: var(--pp-fs-sm); line-height: var(--pp-lh-snug); }
  .pp-footer__contact-title {
    font-size: var(--pp-fs-sm);
    font-weight: var(--pp-fw-bold);
    text-transform: uppercase;
    letter-spacing: var(--pp-ls-wider);
    color: var(--pp-color-text-on-dark-strong);
    margin-bottom: var(--pp-space-2xs);
  }
  .pp-footer__contact-block p { margin: 0 0 var(--pp-space-3xs); color: var(--pp-color-text-on-dark); }
  /* :not(.pp-footer__newsletter) — sinon ce sélecteur (spécificité (0,2,0)) écrase la
     couleur NOIRE du CTA inversé (le CTA est un <a> dans un contact-block). */
  .pp-footer__contact-block a:not(.pp-footer__newsletter) { color: var(--pp-color-text-on-dark); text-decoration: underline; }
  .pp-footer__contact-block a:not(.pp-footer__newsletter):hover { color: var(--pp-color-text-on-dark-strong); }
  /* « PAMISA Vinos » MIS EN AVANT (MSJ R3 §6b) : plus grand, ressort, suivi de l'adresse. */
  .pp-footer__brand {
    font-size: var(--pp-fs-lg);
    font-weight: var(--pp-fw-bold);
    letter-spacing: var(--pp-ls-wide);
    color: var(--pp-color-text-on-dark-strong);
    margin-bottom: var(--pp-space-2xs);
  }
  .pp-footer__address { color: var(--pp-color-text-on-dark); }
  /* Tél + e-mail regroupés en SOUS-BLOC sous l'adresse (MSJ R3 §6c). */
  .pp-footer__reach { margin-top: var(--pp-space-2xs); color: var(--pp-color-text-on-dark); }
  /* CTA NEWSLETTER — COULEURS INVERSÉES (MSJ R3 §6d) : fond BLANC, texte/contour NOIR.
     Sur le footer noir, ça ressort. Une seule ligne (white-space:nowrap), police réduite.
     Style appliqué à TOUTES les vues (token, pas de breakpoint). */
  .pp-footer__newsletter {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-height: 2.5rem; /* compact (police réduite, une ligne) */
    padding-inline: var(--pp-space-md);
    border: var(--pp-border-width) solid var(--pp-color-bg-footer);
    border-radius: var(--pp-radius-square);
    font-size: var(--pp-fs-xs); /* police réduite (MSJ R3 §6d) */
    font-weight: var(--pp-fw-bold);
    text-transform: uppercase;
    letter-spacing: var(--pp-ls-wide);
    white-space: nowrap; /* une seule ligne */
    color: var(--pp-color-bg-footer); /* texte NOIR */
    background: var(--pp-color-white); /* fond BLANC */
    text-decoration: none;
    transition: background var(--pp-transition), color var(--pp-transition);
  }
  .pp-footer__newsletter:hover {
    background: var(--pp-color-primary); /* survol = accent bordeaux, texte blanc */
    color: var(--pp-color-white);
    border-color: var(--pp-color-primary);
  }

  /* Colonnes de liens : mobile = GRID 2 colonnes (MSJ R2 v2 §13), tablette/desktop = 3.
     TOUTES les entrées affichées (jamais tronquer). */
  .pp-footer__widgets {
    display: grid;
    grid-template-columns: 1fr 1fr; /* 390 = 2 colonnes côte à côte (§13) */
    gap: var(--pp-grid-gap);
    padding-bottom: var(--pp-space-xl);
  }
  .pp-footer__col-title {
    font-size: var(--pp-fs-sm);
    font-weight: var(--pp-fw-bold);
    text-transform: uppercase;
    letter-spacing: var(--pp-ls-wider);
    color: var(--pp-color-text-on-dark-strong);
    margin-bottom: var(--pp-space-sm);
  }
  .pp-footer__list { display: flex; flex-direction: column; gap: var(--pp-space-3xs); }
  .pp-footer__list a { font-size: var(--pp-fs-sm); color: var(--pp-color-text-on-dark); }
  .pp-footer__list a:hover { color: var(--pp-color-text-on-dark-strong); }

  .pp-footer__bar {
    border-top: var(--pp-border-width) solid var(--pp-color-on-dark-border);
    padding-block: var(--pp-space-md);
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: var(--pp-space-sm);
  }
  .pp-footer__legal { display: flex; flex-wrap: wrap; gap: var(--pp-space-md); align-items: center; }
  /* V4 (a11y) — le menu légal a retrouvé son <ul> wrapper (règle axe `listitem`) :
     le layout flex des items est porté par la LISTE — rendu identique à l'ancien
     (les <li> orphelins étaient flex-items du nav, ils le sont du ul désormais). */
  .pp-footer__legal-list {
    display: flex;
    flex-wrap: wrap;
    gap: var(--pp-space-md);
    align-items: center;
    margin: 0;
    padding: 0;
    list-style: none;
  }
  .pp-footer__legal-list li { margin: 0; padding: 0; list-style: none; }
  .pp-footer__legal a { font-size: var(--pp-fs-xs); color: var(--pp-color-text-on-dark); }
  .pp-footer__legal a:hover { color: var(--pp-color-text-on-dark-strong); }
  /* Switcher langue du footer = élément BEM dédié (L4 : plus de .pp-footer .pp-lang__link). */
  .pp-footer__lang .pp-lang__link { color: var(--pp-color-text-on-dark); }
  .pp-footer__lang .pp-lang__link[aria-current="page"] { color: var(--pp-color-text-on-dark-strong); }
  .pp-footer__copyright { font-size: var(--pp-fs-xs); color: var(--pp-color-on-dark-faint); }
}

/* ============================================================
   4. CLASSES WOOCOMMERCE / PLUGINS CONSERVÉES  (AX3 : on style, on ne renomme pas)

   NOTE SPÉCIFICITÉ (L4 / Charte §9 — tension résolue) : les sélecteurs
   .pp-summary .price, .pp-summary .quantity .minus-btn, .pp-related .products li img…
   sont des OVERRIDES DE CLASSES WOOCOMMERCE générées (qu'on ne peut pas renommer).
   La descendance est ASSUMÉE et LÉGITIME : on ne maîtrise pas le markup WC, on
   l'ancre dans notre contexte BEM (.pp-summary / .pp-related). Toute la cascade
   reste dans @layer pp-wc → spécificité contenue à cette couche. Les imbrications
   sur NOTRE propre code (.pp-specs .pp-spec-table, .pp-footer .pp-lang__link) ont
   été éliminées (variables locales héritées / élément BEM dédié).
   ============================================================ */
@layer pp-wc {
  /* Prix WC */
  /* Prix = bordeaux accent, 22px comme le réel (critique #2), CHF et montant MÊME
     taille (pas de hiérarchie petit/gros), weight 600. */
  .pp-summary .price {
    margin: 0;
    font-size: clamp(1.25rem, 1.18rem + 0.3vw, 1.375rem); /* 20 → 22px */
    font-weight: var(--pp-fw-semibold);
    color: var(--pp-color-primary); /* accent #ac0b0b comme le site, MSJ R2 v2 §6 */
  }
  .pp-summary .price del { color: var(--pp-color-text-light); font-weight: var(--pp-fw-normal); }
  .pp-summary .price ins { text-decoration: none; color: var(--pp-color-primary); }
  /* CHF à la MÊME taille que le montant (réel : « CHF 21.00 » homogène, critique refine). */
  .woocommerce-Price-currencySymbol { font-size: 1em; margin-right: 0.2em; }

  /* Étoiles WC */
  .woocommerce-product-rating {
    display: flex;
    align-items: center;
    gap: var(--pp-space-2xs);
    font-size: var(--pp-fs-sm);
  }
  /* Étoiles : on n'utilise PAS la font "star" de WC (dequeuée) — glyphes ★ Unicode,
     robustes cross-browser et indépendants de tout chargement de font. */
  /* Étoiles plus discrètes (critique #8 : on les avait ~15px, réel ~10-12px). */
  .star-rating {
    position: relative;
    display: inline-block;
    width: 5.4em;
    height: 1em;
    overflow: hidden;
    font-size: var(--pp-fs-sm); /* ~13px (était fs-md ~15px) */
    font-family: var(--pp-font-main);
    line-height: 1;
  }
  .star-rating::before {
    content: "\2605\2605\2605\2605\2605";
    color: var(--pp-color-border-strong);
    position: absolute;
    left: 0; top: 0;
    z-index: 0; /* fond grisé EN DESSOUS */
    letter-spacing: 0.05em;
  }
  /* La couche « remplie » (accent) DOIT peindre PAR-DESSUS le fond grisé.
     ⚠ CAUSE RÉELLE du bug « étoiles grises » signalé 3× par MSJ : quand le span est
     VIDE (markup généré sans nœud texte), il s'effondre à HAUTEUR 0 ; avec
     overflow:hidden, son ::before (étoiles accent) est ENTIÈREMENT clippé → seules
     les étoiles grises du ::before parent restent visibles. Fix : forcer la hauteur
     (top:0;bottom:0) pour que le span couvre toute la bande, indépendamment du texte. */
  .star-rating span {
    position: absolute;
    left: 0; top: 0; bottom: 0;
    height: 1em;
    z-index: 1;
    overflow: hidden;
    white-space: nowrap;
    /* V2 item 11 — le span WC/CR contient un TEXTE fallback (« Note de 5 sur 5 »)
       qui se superposait aux étoiles depuis le dequeue de woocommerce.css (qui le
       poussait hors champ). Même pattern WC : padding-top 1.5em > height 1em →
       le texte démarre SOUS la fenêtre 1em overflow:hidden, le ::before (étoiles
       accent, top:0) reste visible. GLOBAL — tous viewports, summary + avis,
       AUCUN media query. A11y intacte (aria-label du conteneur role=img). */
    padding-top: 1.5em;
  }
  .star-rating span::before {
    content: "\2605\2605\2605\2605\2605";
    position: absolute;
    left: 0; top: 0;
    color: var(--pp-color-star);
    letter-spacing: 0.05em;
  }
  /* Compteur « (N avis) » = BORDEAUX comme le réel (critique #6), petit, près des étoiles. */
  .woocommerce-review-link {
    font-size: var(--pp-fs-xs);
    color: var(--pp-color-primary);
  }
  .woocommerce-review-link:hover { color: var(--pp-color-primary-hover); }

  /* Formulaire add-to-cart */
  .pp-summary form.cart {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--pp-space-sm);
    margin: var(--pp-space-2xs) 0 0;
  }
  /* Input quantité + boutons +/- — markup WC, attributs min/max/step intacts (R5.4).
     Esthétique HAIRLINE demandée par MSJ : cadre + séparateurs en trait fin clair
     (--pp-color-border), boutons sans fond, glyphes filaires légers. Aérien. */
  .pp-summary .quantity {
    display: inline-flex;
    align-items: stretch;
    border: var(--pp-border-width) solid var(--pp-color-border);
    border-radius: var(--pp-radius-square); /* ANGLES CARRÉS (MSJ R2 v2 §7) */
    overflow: hidden;
  }
  /* V2 — le template quantité SHOPKEEPER (override woocommerce/global/quantity-input.php)
     injecte ses propres ancres <a.minus-btn>/<a.plus-btn> (icônes spk-icon, font
     dequeuée → carrés vides 36px) EN PLUS de nos boutons JS [data-pp-qty] →
     steppers DOUBLÉS et wrapper à 186px (vs 114px banc). On masque les ancres du
     thème (leur JS est dequeué = liens morts) ; nos boutons restent seuls. */
  .pp-summary .quantity > a.minus-btn,
  .pp-summary .quantity > a.plus-btn { display: none; }
  .pp-summary .quantity .minus-btn,
  .pp-summary .quantity .plus-btn,
  .pp-qty-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: var(--pp-qty-btn-w);
    min-height: var(--pp-qty-h);
    border: 0;
    background: transparent;
    color: var(--pp-color-text-muted);
    cursor: pointer;
    user-select: none;
  }
  .pp-summary .quantity .minus-btn:hover,
  .pp-summary .quantity .plus-btn:hover,
  .pp-qty-btn:hover { color: var(--pp-color-primary); }
  /* Glyphes +/− filaires (SVG viewBox sans width intrinsèque) : dimensionner
     explicitement, sinon le SVG rend à sa taille par défaut (« carrés vides »). */
  .pp-summary .quantity .minus-btn svg,
  .pp-summary .quantity .plus-btn svg,
  .pp-qty-btn svg { width: var(--pp-qty-icon-size); height: var(--pp-qty-icon-size); display: block; }
  .pp-summary .quantity input.qty,
  .pp-summary .quantity .custom-qty {
    width: var(--pp-qty-input-w);
    min-height: var(--pp-qty-h);
    border: 0;
    border-inline: var(--pp-border-width) solid var(--pp-color-border);
    text-align: center;
    font: inherit;
    font-size: var(--pp-fs-sm);
    color: var(--pp-color-text-main);
    background: var(--pp-color-bg-page);
    -moz-appearance: textfield;
  }
  .pp-summary .quantity input.qty::-webkit-outer-spin-button,
  .pp-summary .quantity input.qty::-webkit-inner-spin-button {
    -webkit-appearance: none; margin: 0;
  }

  /* AJOUTER : bouton CARRÉ (§7), LARGE comme le réel (~220px, critique #5), texte
     13px sans letter-spacing (le tracking faisait « bouton web générique »). Le réel
     n'est PAS en majuscules — on garde le label tel quel (« Ajouter »/« Hinzufügen »). */
  .pp-summary .single_add_to_cart_button,
  .pp-summary button.button.alt {
    appearance: none;
    border: 0;
    border-radius: var(--pp-radius-square);
    min-width: 13.75rem; /* ~220px comme le réel */
    padding: 0 var(--pp-space-lg);
    min-height: 3.1875rem; /* ~51px comme le réel */
    font: inherit;
    font-size: var(--pp-fs-sm); /* ~13px */
    font-weight: var(--pp-fw-bold);
    text-transform: none;
    letter-spacing: normal; /* neutralise le tracking (critique #5) */
    color: var(--pp-color-white);
    background: var(--pp-color-primary);
    cursor: pointer;
    transition: background var(--pp-transition);
  }
  .pp-summary .single_add_to_cart_button:hover,
  .pp-summary button.button.alt:hover { background: var(--pp-color-primary-hover); color: var(--pp-color-white); }
  /* V2 item 9 (consigne MSJ « tu supprimes ici voir panier, il est déjà dans le
     header ») — après un ajout AJAX, WC injecte un lien « Voir le panier »
     (a.added_to_cart.wc-forward) à côté du bouton. Supprimé sur nos fiches : le
     feedback d'ajout = popup .pp-notif + compteur panier du header. */
  .pp-summary .added_to_cart { display: none; }

  /* V3 R2b — wrapper notices WC VIDE : rendu en premier enfant de .pp-product
     (flex column avec gap), il consommait un gap (~88px) et décalait TOUT le
     contenu vers le bas (h1 y=289 vs 201 banc, mesuré passe finale V2). Vérifié
     live : le wrapper est strictement vide (0 octet, pas de nœud texte) → :empty
     matche. Quand WC y rend de vraies notices (fallback POST, erreur stock), il
     n'est plus :empty → affichage normal conservé. */
  .woocommerce-notices-wrapper:empty { display: none; }

  /* Notices WC (fallback no-JS / erreur) */
  .woocommerce-message, .woocommerce-error, .woocommerce-info {
    list-style: none;
    margin: var(--pp-space-sm) 0;
    padding: var(--pp-space-sm) var(--pp-space-md);
    border-left: var(--pp-border-width-accent) solid var(--pp-color-primary);
    background: var(--pp-color-bg-subtle);
    font-size: var(--pp-fs-base);
  }
  .woocommerce-error { border-left-color: var(--pp-color-error); }

  /* Mini-panier widget WC (dans le slide-out) — R3 redesign validé MSJ.
     Markup = notre override cart/mini-cart.php (.pp-mc__media / .pp-mc__line). */

  /* Liste d'articles */
  .pp-minicart .woocommerce-mini-cart {
    display: flex;
    flex-direction: column;
    gap: var(--pp-space-sm); /* R6 item 3 — lignes plus compactes (était md) */
    margin: 0;
    padding: 0;
    list-style: none;
  }
  .pp-minicart .woocommerce-mini-cart-item {
    position: relative;
    margin: 0;
    padding: 0 0 var(--pp-space-2xs); /* R6 item 3 — compact (était sm) */
    border-bottom: var(--pp-border-width) solid var(--pp-color-border);
    list-style: none;
  }
  .pp-minicart .woocommerce-mini-cart-item:last-child { border-bottom: 0; padding-bottom: 0; }

  /* R3 items 1-2 — BOUTEILLE COUCHÉE recadrée : cadre à hauteur fixe + overflow
     hidden ; l'image (JPEG portrait à grandes marges blanches) est centrée,
     tournée 90° et dimensionnée pour que sa LONGUEUR ≈ largeur du cadre — le
     débord vertical (= marges blanches latérales du JPEG) est croppé. Générique
     bouteilles portrait ; cas quasi carrés (brandy/cigares) : bande centrale,
     présentable (toléré). Reprise du principe de la variante banc « rotated »
     (DIFF-REPORT item 16), appliqué au minicart UNIQUEMENT. */
  .pp-mc__media {
    position: relative;
    height: var(--pp-mc-frame-h);
    overflow: hidden;
    /* R7 item 3 — bloc image PLEINE largeur de la ligne : bouteille alignée À
       GAUCHE, croix au bout DROIT (alignée avec la colonne des montants). */
    width: 100%;
  }
  /* R7 — modale compacte (<48em, ~351px → cadre ~303px) : 20.75rem (332px) y
     serait tranchée. Proportionnel mobile : bouteille 17.5rem (280px, marge droite
     ~23px) + cadre 6.25rem (fenêtre = moitié centrale conservée). */
  @media (max-width: 47.99em) {
    .pp-minicart {
      --pp-mc-bottle-len: 17.5rem;
      --pp-mc-frame-h: 6.25rem;
    }
  }
  .pp-mc__thumb { position: absolute; inset: 0; display: block; }
  .pp-mc__media img {
    position: absolute;
    top: 50%;
    /* R7 item 3 — bouteille à GAUCHE : l'étendue horizontale post-rotation vaut
       --pp-mc-bottle-len ; son centre est ancré à len/2 du bord gauche du cadre. */
    left: calc(var(--pp-mc-bottle-len) / 2);
    height: var(--pp-mc-bottle-len);
    width: auto;
    max-width: none;
    transform: translate(-50%, -50%) rotate(90deg);
  }

  /* R3 item 3 + R4 item 2 (consigne précise MSJ) — croix de suppression en OVERLAY
     coin supérieur droit : (a) SANS encadré ni fond (transparente, directement sur
     l'image) ; (b) plus ÉPAISSE et plus grande, même style que la croix de fermeture
     du panneau en haut ; (c) REMONTÉE à top:0 (le goulot de la bouteille couchée ne
     passe plus dessous — ⚠ le cadre .pp-mc__media est overflow:hidden, top négatif
     impossible). Zone cliquable 36px ≥32 ✓, aria-label conservé (markup). Contraste
     sur image claire/foncée : halo blanc en text-shadow (pas de cadre). */
  .pp-minicart .mini_cart_item a.remove_from_cart_button {
    position: absolute;
    top: 0;
    right: 0;
    z-index: 2;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 2.25rem;
    height: 2.25rem;
    background: transparent;
    border: 0;
    color: var(--pp-color-text-main);
    font-size: var(--pp-fs-xl);
    font-weight: var(--pp-fw-semibold);
    line-height: 1;
    text-shadow:
      0 0 3px var(--pp-color-white),
      0 0 6px var(--pp-color-white),
      0 1px 8px var(--pp-color-white);
  }
  .pp-minicart .mini_cart_item a.remove_from_cart_button:hover {
    color: var(--pp-color-primary);
  }

  /* R3 item 4 — ligne produit 2 blocs : nom à GAUCHE, « 12 × CHF 21.00 » aligné
     COMPLÈTEMENT à droite en petite police (plus de wrap du nom dans les chiffres). */
  .pp-mc__line {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    gap: var(--pp-space-sm);
    margin-top: var(--pp-space-3xs); /* R6 item 3 — compact (était 2xs) */
  }
  .pp-mc__name {
    flex: 1 1 auto;
    min-width: 0;
    font-size: var(--pp-fs-sm);
    /* R4 item 1 — le nom doit RESSORTIR : semibold 600, cohérent avec la typo du
       banc (titres/poids forts en --pp-fw-semibold). Taille inchangée. */
    font-weight: var(--pp-fw-semibold);
    color: var(--pp-color-text-main);
  }
  .pp-mc__name:hover { color: var(--pp-color-primary); }
  .pp-minicart .mini_cart_item .quantity {
    flex: 0 0 auto;
    white-space: nowrap;
    font-size: var(--pp-fs-xs);
    color: var(--pp-color-text-muted);
  }

  /* R3 item 5 — ZWISCHENSUMME 2 blocs : libellé à gauche, montant à droite. */
  .pp-minicart__body .woocommerce-mini-cart__total,
  .pp-minicart__body .total {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    gap: var(--pp-space-sm);
    margin: var(--pp-space-sm) 0 0;
    font-weight: var(--pp-fw-bold);
  }

  .pp-minicart__body .button {
    display: inline-block;
    margin-top: var(--pp-space-2xs);
    padding: var(--pp-space-2xs) var(--pp-space-md);
    background: var(--pp-color-primary);
    color: var(--pp-color-white);
    border-radius: var(--pp-radius-square); /* bouton carré (MSJ R2 v2 §7) */
    font-weight: var(--pp-fw-bold);
  }

  /* R3 item 7 — « Warenkorb anzeigen » / « Kasse » : 2 boutons DISTINCTS, rouge
     plein conservé, séparés par un TRAIT VERTICAL PLEINE HAUTEUR (plus un seul
     bloc rouge fusionné). align-items:stretch → le trait court sur toute la
     hauteur des boutons. */
  .pp-minicart__body .woocommerce-mini-cart__buttons {
    display: flex;
    align-items: stretch;
    margin: var(--pp-space-sm) 0 0;
  }
  .pp-minicart__body .woocommerce-mini-cart__buttons .button {
    flex: 1 1 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    margin: 0;
    padding: var(--pp-space-sm) var(--pp-space-2xs);
    text-align: center;
  }
  .pp-minicart__body .woocommerce-mini-cart__buttons .button + .button {
    border-left: var(--pp-border-width) solid var(--pp-color-white);
  }

  /* Related products grid WC */
  .pp-related .products {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(min(100%, 14rem), 1fr));
    gap: var(--pp-grid-gap);
    list-style: none;
    margin: 0; padding: 0;
  }
  .pp-related .products li img { width: 100%; height: auto; }
}

/* ============================================================
   5. UTILITIES
   ============================================================ */
@layer pp-utilities {
  .pp-hidden { display: none; }
  /* [hidden] dans pp-utilities (après pp-components) pour battre les display
     des composants : .pp-tabs__panel[hidden], .pp-notif[hidden], .pp-overlay[hidden]. */
  [hidden] { display: none; }
}

/* ============================================================
   6. RESPONSIVE  (mobile-first, 100 % min-width ; layout de page seulement, R4.9)
   Tout dans @layer pp-responsive (H1) → reste dans la cascade des layers.
   ============================================================ */
@layer pp-responsive {
  /* MOBILE 390 (MSJ R3 §3) : logo +30% vs round 2, icônes serrées (gap réduit),
     alignées à droite sur le content-width. Borne haute 47.99em = juste avant 768. */
  @media (max-width: 47.99em) {
    /* Logo −20% vs v0.4.1 (MSJ R4 §1b) : 1.3 × 0.8 = 1.04 */
    .pp-header__logo img { width: calc(var(--pp-logo-width) * 1.04); }
    /* Icônes resserrées (MSJ R4 §1a) : gap=0 + bouton plus étroit */
    .pp-tools { gap: 0; --pp-tools-btn-w: 1.75rem; }
    /* Image bouteille +20% vs round 2 (MSJ R3 §5 : trop réduite à 390). 58vw→70vw
       (≈226px→272px @390), plafond relevé en conséquence. Reste centrée. */
    .pp-gallery { max-width: clamp(15.5rem, 70vw, 26rem); }
  }
  /* TABLETTE 768 (MSJ R3 §3) : logo +20% vs round 2, toujours aligné content-width
     gauche ; icônes alignées content-width droite. 48em..63.99em = avant desktop. */
  @media (min-width: 48em) and (max-width: 63.99em) {
    .pp-header__logo img { width: calc(var(--pp-logo-width) * 1.2); }
  }

  @media (min-width: 48em) { /* ~768px tablette */
    /* SPECS : reste en 1 COLONNE à 768 — le site réel stacke toutes les cellules dès
       la tablette (colonnes Foundation .medium-12). Le passage 2 colonnes est à 64em. */
    .pp-origins { grid-template-columns: 1fr 1fr; }
    /* Contact (MSJ R3 §6) : 3 blocs côte à côte (coordonnées | showroom | newsletter).
       On annule le span/centrage 390 du CTA → il reprend sa colonne dédiée. */
    .pp-footer__contact { grid-template-columns: 2fr 1.4fr 1.2fr; align-items: start; }
    .pp-footer__contact-block--cta { grid-column: auto; justify-self: start; align-self: start; }
    .pp-footer__widgets { grid-template-columns: repeat(3, 1fr); }
  }

  @media (min-width: 64em) { /* desktop : 3 colonnes de liens confortables (§14) */
    .pp-footer__widgets { grid-template-columns: repeat(3, 1fr); }
  }

  @media (min-width: 64em) { /* ~1024px : seuil burger / desktop */
    /* SPECS — 2 colonnes côte à côte (réel : .large-6, ≥1024px). La gouttière VERTICALE
       blanche entre les deux colonnes = column-gap ~20px (réel : padding des colonnes
       Foundation). Pas de row-gap : la pile interne garde ses fines gouttières 1px. */
    .pp-specs { grid-template-columns: 1fr 1fr; column-gap: var(--pp-spec-col-gutter); }

    /* DESKTOP — STRUCTURE 3 BLOCS (MSJ R3 §1) : nav GAUCHE | LOGO central | bloc DROITE.
       Colonnes latérales 1fr égales → le logo (auto) au CENTRE EXACT de la page.
       R3 item 8 (retour design MSJ) : les blocs latéraux sont REGROUPÉS VERS LE
       CENTRE — nav alignée vers le logo (justify-self:end), outils vers le logo
       (justify-self:start), chacun avec un retrait --pp-header-inset vis-à-vis du
       logo, et un peu d'air interne (gap nav/outils). Composition centrée autour
       du logo au lieu d'éléments collés aux bords. Mobile/tablette : INCHANGÉS
       (règles hors de ce media). */
    .pp-header__inner { grid-template-columns: 1fr auto 1fr; }
    .pp-header__logo { justify-self: center; }
    .pp-nav--primary { display: block; justify-self: end; margin-right: var(--pp-header-inset); }
    .pp-header__tools { justify-self: start; margin-left: var(--pp-header-inset); }
    .pp-nav__list { gap: var(--pp-space-lg); }
    /* R10 — le switcher FR/DE doit AUSSI se poser sur la ligne de base (sa boîte
       était centrée dans la rangée outils 44px → il flottait ~9px au-dessus). */
    .pp-tools { gap: var(--pp-space-2xs); align-items: end; }

    /* R11 (ligne de base MSJ — alignement du CONTENU, pas des boîtes). R10 avait
       calé les BOÎTES (retraits 12/12/12/12) mais le CONTENU VISIBLE flottait
       encore : icônes svg centrées dans le bouton 44px (bas −12px), texte nav
       avec padding-bas 8px (baseline −11px), switcher centré (−5px). On pose le
       BAS VISIBLE de chaque élément sur le bas d'ENCRE du logo. Mesuré live
       (Chromium) : spread ≤0.5px de 1024 à 1920px ; les écrans 5K plafonnent
       comme ≥1360px (fs-sm clampé à 14px, logo à 236px) → identique. */
    /* icônes : bas du svg sur la ligne (au lieu de centré dans le bouton 44px) */
    .pp-tools .pp-tools__btn { align-items: flex-end; }
    /* R11b — le compteur panier (« 24 ») suit l'icône descendue : ancré en haut du
       bouton 44px, il flottait trop haut quand le chariot est passé au bas. On le
       décale du MÊME offset de centrage que l'icône a parcouru : (44−20)/2 = 12px,
       il recoiffe ainsi le coin haut-droit du chariot comme avant. Desktop only
       (mobile garde l'icône centrée → top inchangé). */
    .pp-tools .pp-tools__btn .pp-cart-count {
      top: calc(var(--pp-space-3xs) + (var(--pp-tap-min) - var(--pp-icon-size)) / 2);
    }
    /* texte nav : baseline sur la ligne (padding reporté en haut + nudge descent) */
    .pp-nav__list { align-items: flex-end; }
    .pp-nav__link { padding-block: var(--pp-space-sm) 0; transform: translateY(var(--pp-header-baseline-nudge)); }
    /* switcher FR/DE : baseline sur la ligne */
    .pp-tools .pp-lang { align-items: flex-end; transform: translateY(var(--pp-header-baseline-nudge)); }
    /* R4 item 3 (MESURÉ @1440) : espace au-dessus du logo — ancien Shopkeeper 58px ·
       nôtre 12px · CHOISI ≈35px (entre-deux, même doctrine que le gap sous header R3).
       7rem=112px. Le gap SOUS le header (76px, R3) est porté par .pp-product : INCHANGÉ. */
    .pp-header { --pp-header-h: 7rem; }
    /* R9 item 2 + R10 (ligne de base MSJ) — le GROUPE ENTIER (logo + nav + outils)
       est POSÉ sur une ligne de base située vers le BAS du bandeau : align-items:end,
       petit retrait --pp-header-baseline-inset (12px, consigne ~10-14px) SOUS la
       ligne, le padding-top absorbe le reste (hauteur totale du header INCHANGÉE,
       gap 76px sous header INCHANGÉ). L'air au-dessus du logo ≈ 62px — cohérent
       avec la home Shopkeeper (58px au-dessus du logo). Référence home re-mesurée
       R10 : header intérieur Shopkeeper = fond continu SANS bandeau délimité
       (retrait élément 83px non pertinent) → le ~12px de la consigne fait foi.
       Mobile/tablette : hors media, INCHANGÉS (centrage de base). */
    .pp-header { --pp-header-baseline-inset: 0.75rem; --pp-header-baseline-nudge: 0.4rem; } /* 12px ligne de base ; 6.4px nudge baseline texte (descent police) */
    .pp-header__inner {
      align-items: end;
      padding-top: calc(var(--pp-header-h) - 2.5625rem - var(--pp-header-baseline-inset)); /* 2.5625rem = logo 41px */
      padding-bottom: var(--pp-header-baseline-inset);
      min-height: 0; /* la hauteur vient du padding + contenu (sinon le min-height re-centre) */
    }
    /* R9 item 3 — le dropdown s'ouvre SOUS le header, jamais sur le logo : la zone
       hover du parent est ÉTENDUE jusqu'au bas du header (= le retrait baseline,
       compensé par margin négative) → top:100% du sous-menu = bas du header, et le
       survol ne se rompt pas en traversant l'espace. */
    .pp-nav--primary .menu-item-has-children {
      padding-bottom: var(--pp-header-baseline-inset);
      margin-bottom: calc(-1 * var(--pp-header-baseline-inset));
    }

    .pp-overview { grid-template-columns: minmax(0, 0.92fr) minmax(0, 1fr); gap: var(--pp-space-xl); }
    /* Desktop 2 colonnes : la photo remplit sa colonne (≈483px réel) → on lève le
       plafond 1-colonne et on recentre dans la cellule (MSJ R2 v2 §1). */
    .pp-gallery { max-width: 100%; margin-inline: 0; }
    /* Desktop : on révèle la langue ET l'icône compte dans le bloc droite, on masque
       le burger (L8). L'icône compte revient donc à sa place sur desktop (inchangé). */
    .pp-tools .pp-lang { display: inline-flex; }
    .pp-tools__btn--account { display: inline-flex; }
    .pp-tools__btn--burger { display: none; }
  }
}

/* ============================================================
   7. REDUCED MOTION  (R2.9)
   ============================================================ */
@media (prefers-reduced-motion: reduce) {
  .pp-body *,
  .pp-overlay, .pp-offcanvas, .pp-minicart, .pp-notif, .pp-lightbox,
  .pp-skip-link {
    transition-duration: 0.01ms !important; /* override tiers : neutralise toute anim pour reduced-motion */
    animation-duration: 0.01ms !important;
  }
}

/* ============================================================
   8. PRINT  (hors @layer : doit gagner sur tout)
   ============================================================ */
@media print {
  /* L9 : figer les tokens fluides — en print, vw = largeur du papier (imprévisible). */
  :root {
    --pp-gutter: 1.5rem;
    --pp-grid-gap: 1.25rem;
    --pp-space-xl: 2rem;
    --pp-space-2xl: 3rem;
    --pp-fs-base: 1rem;
    --pp-fs-2xl: 1.5rem;
    --pp-fs-4xl: 2rem; /* h1 figé en print */
  }
  .pp-header, .pp-footer, .pp-overlay, .pp-offcanvas, .pp-searchbar,
  .pp-minicart, .pp-notif, .pp-lightbox, .pp-related,
  .pp-summary form.cart, .pp-skip-link { display: none; }
  .pp-product { padding-block: 0; }
}
