/* TOWeb — la feuille de la boutique (fiche, index, collections). */
  .toweb-product__breadcrumb {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.5rem;
    font-size: 0.875rem;
    color: var(--tw-text-muted, #64748b);
    margin-bottom: 1.5rem;
  }

  /* La couleur des LIENS du texte (accent pincé pour rester lisible, blocks-base.css),
     plus l'accent brut : 2 à 3:1 sur le fond clair de plusieurs DNA (axe-core sur la
     démo, 2026-09-28). */
  .toweb-product__breadcrumb a {
    color: var(--tw-prose-link, var(--tw-accent, #3b82f6));
    text-decoration: none;
  }

  .toweb-product__breadcrumb a:hover {
    text-decoration: underline;
  }

  .toweb-product__layout {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 3rem;
    align-items: start;
  }

  @media (max-width: 768px) {
    .toweb-product__layout {
      grid-template-columns: 1fr;
      gap: 2rem;
    }
  }

  /* ═══ #187 — LES QUATRE DISPOSITIONS D'IMAGES ═══════════════════════════
     Le balisage est le MÊME pour les quatre : carrousel + vignettes + grille.
     C'est le CSS qui choisit ce qui paraît, ce qui donne gratuitement la
     promesse de la légende de l'éditeur — « Disposition desktop. Mobile :
     carrousel. » Sous 768 px, on retombe partout sur le carrousel seul. */

  /* Vignettes — thumbnails-bottom (défaut) et thumbnails-left */
  .toweb-product__thumbs {
    display: flex;
    gap: 0.5rem;
    margin-top: 0.75rem;
    flex-wrap: wrap;
  }
  .toweb-product__thumb {
    width: 64px;
    height: 64px;
    padding: 0;
    border: 0;
    cursor: pointer;
    border-radius: var(--tw-radius-media, 8px);
    overflow: hidden;
    background: var(--tw-media-placeholder, #f1f5f9);
  }
  /* La vignette de l'image affichee : un lisere de la couleur d'accent. Sans etat
     visible, cliquer une vignette ne se distingue pas de ne rien faire. */
  .toweb-product__thumb--active {
    outline: 2px solid var(--tw-accent, #3b82f6);
    outline-offset: 1px;
  }
  /* Le focus clavier doit rester DISTINCT de la sélection, sinon tabuler dans la
     bande donne l'impression d'avoir changé d'image. */
  .toweb-product__thumb:focus-visible {
    outline: 2px dashed var(--tw-text, currentColor);
    outline-offset: 3px;
  }
  .toweb-product__thumb:hover {
    filter: brightness(1.06);
  }

  .toweb-product__thumb img,
  .toweb-product__thumb video {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
  }

  @media (min-width: 769px) {
    /* Vignettes à GAUCHE : la galerie devient une rangée, les vignettes en colonne. */
    .toweb-product__gallery[data-layout='thumbnails-left'] {
      display: grid;
      grid-template-columns: 72px 1fr;
      gap: 0.75rem;
      align-items: start;
    }
    .toweb-product__gallery[data-layout='thumbnails-left'] .toweb-product__thumbs {
      order: -1;
      flex-direction: column;
      margin-top: 0;
      flex-wrap: nowrap;
    }

    /* Vignettes visibles → les points du carrousel font double emploi : ils suivent
       la même position dans un autre vocabulaire, et doublent les cibles de clic. */
    .toweb-product__gallery[data-layout^='thumbnails'] .tw-carousel__dots {
      display: none;
    }

    /* Mosaïque et grille : le carrousel s'efface, la grille prend toute la place. */
    .toweb-product__gallery[data-layout='masonry'] .toweb-product__carousel,
    .toweb-product__gallery[data-layout='gallery-2col'] .toweb-product__carousel {
      display: none;
    }
    .toweb-product__grid {
      display: grid;
      gap: 0.75rem;
    }
    /* ⚠️ ELLE RENDAIT COMME LA MOSAIQUE, et c'est ce que Yann a vu. Deux colonnes
       de largeur egale ne suffisent pas : si les images gardent leur proportion
       naturelle, les lignes ne s'alignent pas et des trous apparaissent — donc
       la meme impression que la mosaique, en moins bien.

       Ce qui SEPARE les deux dispositions n'est pas le nombre de colonnes, c'est
       la REGULARITE : la mosaique laisse chaque image respirer a sa hauteur, la
       galerie aligne des cases identiques. D'ou le recadrage en 4/3. */
    .toweb-product__gallery[data-layout='gallery-2col'] .toweb-product__grid {
      grid-template-columns: 1fr 1fr;
      align-items: start;
    }
    /* Les vidéos gardent leur proportion : les recadrer en 4/3 couperait l'image. */
    .toweb-product__gallery[data-layout='gallery-2col'] .toweb-product__grid-item:not(.toweb-product__grid-item--video) {
      aspect-ratio: 4 / 3;
    }
    .toweb-product__gallery[data-layout='gallery-2col'] .toweb-product__grid-item img,
    .toweb-product__gallery[data-layout='gallery-2col'] .toweb-product__grid-item video {
      width: 100%;
      height: 100%;
      object-fit: cover;
    }
    .toweb-product__gallery[data-layout='masonry'] .toweb-product__grid {
      display: block;
      columns: 2;
      column-gap: 0.75rem;
    }
    .toweb-product__gallery[data-layout='masonry'] .toweb-product__grid-item {
      break-inside: avoid;
      margin: 0 0 0.75rem;
    }
  }

  .toweb-product__grid-item {
    margin: 0;
    border-radius: var(--tw-radius-media, 8px);
    overflow: hidden;
    background: var(--tw-media-placeholder, #f1f5f9);
    cursor: zoom-in;
  }
  .toweb-product__grid-item img,
  .toweb-product__grid-item video {
    width: 100%;
    height: auto;
    display: block;
  }
  /* Dans une grille, toutes les images sont déjà là : le saut de galerie piloté par
     la couleur (#117) n'a rien à faire défiler, il doit DÉSIGNER. Sans ça, choisir
     « Rouge » sur une mosaïque ne changeait pas un pixel. */
  .toweb-product__grid-item--current {
    outline: 2px solid var(--tw-accent, #3b82f6);
    outline-offset: 2px;
  }

  /* ⚠️ MOBILE : le carrousel, TOUJOURS — c'est ce que la légende promet, et
     une mosaïque à deux colonnes sur un téléphone rend des images minuscules. */
  @media (max-width: 768.98px) {
    .toweb-product__thumbs,
    .toweb-product__grid { display: none; }
    .toweb-product__gallery .toweb-product__carousel { display: block; }
  }

  /* Zoom au survol — reglage productImageZoom, jamais lu jusqu'ici (#187).
     Sur les appareils sans survol réel, la règle ne s'applique pas : un doigt
     ne survole pas, et un zoom collant au premier contact serait un défaut. */
  @media (hover: hover) {
    .toweb-product__gallery[data-zoom] .toweb-product__main-image img,
    .toweb-product__gallery[data-zoom] .toweb-product__slide img,
    .toweb-product__gallery[data-zoom] .toweb-product__grid-item img {
      transition: transform 240ms ease;
    }
    .toweb-product__gallery[data-zoom] .toweb-product__main-image:hover img,
    .toweb-product__gallery[data-zoom] .toweb-product__slide:hover img,
    .toweb-product__gallery[data-zoom] .toweb-product__grid-item:hover img {
      transform: scale(1.06);
    }
  }
  @media (prefers-reduced-motion: reduce) {
    .toweb-product__gallery[data-zoom] img { transition: none; }
    .toweb-product__gallery[data-zoom] *:hover img { transform: none; }
  }

  .toweb-product__main-image {
    border-radius: var(--tw-radius-media, 8px);
    overflow: hidden;
    background: var(--tw-media-placeholder, #f1f5f9);
  }

  .toweb-product__main-image img {
    width: 100%;
    height: auto;
    display: block;
  }

  .toweb-product__no-image {
    aspect-ratio: 1;
    display: flex;
    align-items: center;
    justify-content: center;
    background: var(--tw-media-placeholder, #f1f5f9);
    border-radius: var(--tw-radius-media, 8px);
    color: var(--tw-text-muted, #94a3b8);
  }

  .toweb-product__carousel {
    border-radius: var(--tw-radius-media, 8px);
    overflow: hidden;
    background: var(--tw-media-placeholder, #f1f5f9);
  }

  /* HELO 74960 — LE CADRE DU CARROUSEL SUIT LA PREMIÈRE IMAGE, ET CHAQUE PHOTO S'Y
     MONTRE ENTIÈRE. La piste est une rangée flex : toutes les diapos y prenaient la
     hauteur de la PLUS HAUTE. Une photo verticale imposait donc un cadre haut, où
     une horizontale restait collée en haut au-dessus d'un grand vide gris, tandis
     que la verticale, plafonnée à 70vh et en `cover`, était rognée.
     Standard Shopify Dawn / WooCommerce : le cadre prend le ratio de la première
     image ; les suivantes s'y logent ENTIÈRES (`contain`), centrées. Seule la
     première diapo est dans le flux et donne la hauteur ; les autres remplissent
     ce cadre en absolu. Les vignettes, elles, restent recadrées en carré. */
  .toweb-product__slide {
    margin: 0;
    position: relative;
  }

  .toweb-product__slide img {
    width: 100%;
    height: auto;
    display: block;
    object-fit: contain;
  }

  .toweb-product__carousel .toweb-product__slide:not(:first-child) > img,
  .toweb-product__carousel .toweb-product__slide:not(:first-child) > video {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    max-height: none;
    object-fit: contain;
  }

  /* Taille et interligne du titre de la fiche : le h1 de l'échelle de LECTURE du
     style (`buildReadingRules`, shared/theme/themeElementRules.ts). Il partage la
     largeur avec la galerie : la grande échelle des sections (48 px sur Atelier)
     y faisait une affiche (Yann, 2026-10-08). */
  .toweb-product__title {
    font-weight: 700;
    margin: 0 0 0.25rem;
  }

  .toweb-product__brand {
    font-size: 0.9375rem;
    color: var(--tw-text-muted, #64748b);
    margin: 0 0 1rem;
  }

  .toweb-product__pricing {
    display: flex;
    align-items: baseline;
    gap: 0.75rem;
    margin-bottom: 0.75rem;
  }

  .toweb-product__price {
    font-size: 1.5rem;
    font-weight: 700;
    color: var(--tw-price-color, #0f172a);
  }

  .toweb-product__price--sale {
    color: var(--tw-price-color, #ef4444);
  }

  .toweb-product__compare-price {
    font-size: 1.125rem;
    color: var(--tw-text-muted, #64748b);
    text-decoration: line-through;
  }

  .toweb-product__tax {
    font-size: 0.8125rem;
    color: var(--tw-text-muted, #94a3b8);
  }

  .toweb-product__price-unit {
    font-size: 0.875rem;
    font-weight: 400;
    color: var(--tw-text-muted, #64748b);
  }

  .toweb-product__unit-price-line {
    font-size: 0.8125rem;
    color: var(--tw-text-muted, #64748b);
    margin: -0.25rem 0 0.75rem;
  }

  .toweb-product__qty-unit {
    font-size: 0.875rem;
    color: var(--tw-text-muted, #64748b);
    font-weight: 500;
  }

  .toweb-product__sku {
    font-size: 0.8125rem;
    color: var(--tw-text-muted, #94a3b8);
    margin: 0 0 1rem;
  }

  /* Signaux de stock (P0-3 #118) — urgence « plus que X » (ambre sémantique littéral) +
     note de précommande. */
  .toweb-product__low-stock {
    font-size: 0.85rem;
    font-weight: 600;
    color: #b45309;
    margin: 0.25rem 0 0.5rem;
  }
  .toweb-product__backorder-note {
    font-size: 0.85rem;
    color: var(--tw-text-muted, #64748b);
    margin: 0.25rem 0 0.5rem;
  }
  /* Champs de personnalisation produit (P0 #124) */
  .toweb-product__custom { display: flex; flex-direction: column; gap: 0.6rem; margin: 0.75rem 0; }
  .toweb-cf__field { display: flex; flex-direction: column; gap: 0.25rem; }
  .toweb-cf__label { font-size: 0.82rem; font-weight: 600; color: var(--tw-text, #0f172a); }
  .toweb-cf__req { color: #dc2626; }
  .toweb-cf__input { padding: 0.5rem 0.65rem; border: 1px solid var(--tw-border, #d1d5db); border-radius: var(--tw-radius-field, 6px); font: inherit; font-size: 0.9rem; background: var(--tw-surface, #fff); color: inherit; width: 100%; box-sizing: border-box; }
  .toweb-cf__input:focus { outline: 2px solid var(--tw-accent, #2563eb); outline-offset: 1px; }
  .toweb-cf--error { border-color: #dc2626; }
  textarea.toweb-cf__input { min-height: 3.5rem; resize: vertical; }
  /* Avis produits (P1 #126) */
  .toweb-reviews { max-width: 48rem; margin: 3rem auto 1rem; padding: 0 1rem; }
  .toweb-reviews__title { font-size: 1.5rem; margin: 0 0 1rem; }
  .toweb-reviews__summary { display: flex; align-items: center; gap: 0.6rem; margin-bottom: 1.5rem; }
  .toweb-reviews__avg { font-size: 2rem; font-weight: 700; }
  .toweb-reviews__stars, .toweb-review__stars { color: #f59e0b; letter-spacing: 1px; }
  .toweb-reviews__count { color: var(--tw-text-muted, #64748b); font-size: 0.9rem; }
  .toweb-reviews__empty { color: var(--tw-text-muted, #64748b); margin-bottom: 1.5rem; }
  .toweb-reviews__list { list-style: none; padding: 0; margin: 0 0 2rem; display: flex; flex-direction: column; gap: 1.25rem; }
  .toweb-review { border-bottom: 1px solid var(--tw-border, rgba(128,128,128,0.15)); padding-bottom: 1.25rem; }
  .toweb-review__head { display: flex; align-items: center; gap: 0.5rem; margin-bottom: 0.35rem; flex-wrap: wrap; }
  .toweb-review__author { font-size: 0.9rem; }
  .toweb-review__date { color: var(--tw-text-muted, #64748b); font-size: 0.8rem; }
  .toweb-review__content { margin: 0; line-height: 1.55; white-space: pre-line; }
  .toweb-star--on { color: #f59e0b; }
  .toweb-star--off { color: #d1d5db; }
  .toweb-reviews__form { background: var(--tw-surface, rgba(128,128,128,0.05)); padding: 1.25rem; border-radius: var(--tw-radius, 10px); display: flex; flex-direction: column; gap: 0.6rem; }
  .toweb-reviews__form-title { margin: 0 0 0.25rem; font-size: 1.1rem; }
  .toweb-reviews__rating { display: flex; gap: 0.15rem; }
  .toweb-star-btn { background: none; border: 0; cursor: pointer; font-size: 1.6rem; color: #d1d5db; padding: 0; line-height: 1; }
  .toweb-star-btn--on { color: #f59e0b; }
  .toweb-reviews__field { padding: 0.6rem 0.7rem; border: 1px solid var(--tw-border, #d1d5db); border-radius: var(--tw-radius-field, 6px); font: inherit; background: var(--tw-bg, #fff); color: inherit; width: 100%; box-sizing: border-box; }
  .toweb-reviews__hp { position: absolute; left: -9999px; width: 1px; height: 1px; opacity: 0; }
  /* Brique BOUTON du DNA (`tw-button` + data-variant) : ce bouton peignait son propre
     `--tw-primary`, jeton qu'aucun DNA ne pose — il restait bleu par défaut au milieu
     d'une fiche aux couleurs du style (démo, 2026-09-26). Seule la mise en page reste ici. */
  .toweb-reviews__submit { align-self: flex-start; }
  .toweb-reviews__submit:disabled { opacity: 0.6; cursor: default; }
  .toweb-reviews__error { color: #dc2626; font-size: 0.85rem; margin: 0; }
  .toweb-reviews__thanks { background: #dcfce7; color: #166534; padding: 0.9rem; border-radius: 8px; }
  /* Cross-sell + récemment vus (P1 #127) */
  .toweb-recos { max-width: 64rem; margin: 3rem auto 1rem; padding: 0 1rem; }
  .toweb-recos__title { font-size: 1.4rem; margin: 0 0 1.25rem; }
  .toweb-recos__grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 1.25rem; }
  .toweb-minicard { display: flex; flex-direction: column; text-decoration: none; color: inherit; gap: 0.4rem; }
  .toweb-minicard__img { width: 100%; aspect-ratio: 1; object-fit: cover; border-radius: 8px; background: var(--tw-surface, rgba(128,128,128,0.08)); display: block; }
  .toweb-minicard__title { font-size: 0.9rem; font-weight: 600; line-height: 1.3; }
  .toweb-minicard__price { font-size: 0.85rem; color: var(--tw-text-muted, #64748b); }
  .toweb-minicard:hover .toweb-minicard__title { text-decoration: underline; }
  /* Lightbox galerie (P1 #128) */
  .toweb-lightbox { position: fixed; inset: 0; z-index: 9999; background: rgba(0,0,0,0.9); display: flex; align-items: center; justify-content: center; }
  .toweb-lightbox__img { max-width: 92vw; max-height: 88vh; object-fit: contain; user-select: none; }
  .toweb-lightbox__close { position: absolute; top: 0.75rem; right: 1.25rem; background: none; border: 0; color: #fff; font-size: 2.5rem; line-height: 1; cursor: pointer; padding: 0.25rem 0.5rem; }
  .toweb-lightbox__nav { position: absolute; top: 50%; transform: translateY(-50%); background: rgba(255,255,255,0.15); border: 0; color: #fff; font-size: 2rem; width: 3rem; height: 3rem; border-radius: 50%; cursor: pointer; display: flex; align-items: center; justify-content: center; }
  .toweb-lightbox__nav:hover { background: rgba(255,255,255,0.28); }
  .toweb-lightbox__prev { left: 1rem; }
  .toweb-lightbox__next { right: 1rem; }
  .toweb-lightbox__counter { position: absolute; bottom: 1.25rem; left: 50%; transform: translateX(-50%); color: #fff; font-size: 0.85rem; background: rgba(0,0,0,0.4); padding: 0.2rem 0.7rem; border-radius: 999px; }
  /* Vidéo self-host en galerie (P1 #129) */
  .toweb-product__slide--video { display: flex; align-items: center; justify-content: center; background: #000; }
  .toweb-product__video { width: 100%; max-height: 100%; object-fit: contain; display: block; background: #000; }
  /* Vidéo YouTube / Vimeo en galerie (#511) : 16:9, son image d'aperçu en fond ;
     le cadre attend le consentement « marketing », comme le bloc vidéo (#420). */
  .toweb-product__embed { position: relative; width: 100%; aspect-ratio: 16 / 9; background: #000 center / cover no-repeat; }
  .toweb-product__embed iframe { position: absolute; inset: 0; width: 100%; height: 100%; border: 0; }
  .toweb-product__embed > .tw-consentement { position: absolute; inset: 0; z-index: 1; background: rgba(0,0,0,0.6); color: #fff; }
  .toweb-product__thumb { position: relative; }
  .toweb-product__thumb-play { position: absolute; inset: 0; display: flex; align-items: center; justify-content: center; background: rgba(0,0,0,0.25); pointer-events: none; }
  .toweb-product__thumb-play::before { content: ''; border-style: solid; border-width: 8px 0 8px 13px; border-color: transparent transparent transparent #fff; margin-left: 3px; }
  /* Barre d'achat sticky mobile (roadmap #116, P1 média riche) — mobile uniquement */
  .toweb-sticky-buy { position: fixed; left: 0; right: 0; bottom: 0; z-index: 900; display: none; align-items: center; justify-content: space-between; gap: 1rem; padding: .7rem 1rem; background: var(--tw-surface, #fff); border-top: 1px solid var(--tw-border, rgba(128,128,128,0.2)); box-shadow: 0 -2px 12px rgba(0,0,0,0.1); }
  @media (max-width: 768px) { .toweb-sticky-buy { display: flex; } }
  .toweb-sticky-buy__price { font-weight: 700; font-size: 1.1rem; white-space: nowrap; }
  /* Même brique que le bouton principal qu'elle pilote : elle peignait `--tw-primary`
     (qu'aucun DNA ne pose) et restait bleue sous un « Ajouter au panier » aux couleurs
     du style (démo, 2026-09-26). */
  .toweb-sticky-buy__btn { flex: 0 0 auto; }
  /* Éco-participation FR (P2 #116) */
  .toweb-product__eco-fee { font-size: .8rem; color: var(--tw-text-muted, #64748b); margin: .2rem 0 0; }
  .toweb-product__bundle { margin: 1rem 0; padding: .8rem 1rem; border: 1px solid var(--tw-border, rgba(128,128,128,.2)); border-radius: 10px; background: var(--tw-surface-alt, rgba(128,128,128,.05)); }
  .toweb-product__bundle-head { font-weight: 600; font-size: .9rem; margin: 0 0 .4rem; }
  .toweb-product__bundle-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: .25rem; }
  .toweb-product__bundle-list li { font-size: .9rem; }
  .toweb-product__bundle-qty { font-weight: 700; color: var(--tw-accent, #2563eb); } /* --tw-accent : --tw-primary n'est posé par aucun DNA */
  .toweb-product__bundle-list a { color: inherit; text-decoration: none; }
  .toweb-product__bundle-list a:hover { text-decoration: underline; }
  /* Table de paliers dégressifs par quantité (P0 #120) */
  .toweb-product__tiers {
    border-collapse: collapse;
    font-size: 0.85rem;
    margin: 0.5rem 0 0.75rem;
  }
  .toweb-product__tiers td {
    padding: 0.15rem 0.9rem 0.15rem 0;
    color: var(--tw-text-muted, #64748b);
  }
  .toweb-product__tiers td:last-child {
    color: var(--tw-text, #0f172a);
    font-weight: 600;
    font-variant-numeric: tabular-nums;
  }

  /* "Rupture de stock" : rouge sémantique universel (pas une couleur de palette
     DNA → littéral, lisible clair comme sombre). */
  .toweb-product__out-of-stock {
    display: inline-block;
    padding: 0.375rem 0.75rem;
    font-size: 0.875rem;
    font-weight: 600;
    color: #ef4444;
    background: color-mix(in srgb, #ef4444 10%, transparent);
    border-radius: var(--tw-radius-field, 6px);
    margin-bottom: 1rem;
  }

  .toweb-product__description {
    margin-top: 1.5rem;
    padding-top: 1.5rem;
    border-top: 1px solid var(--tw-border, #e2e8f0);
  }

  /* Taille, interligne et intertitres de la description : l'échelle de LECTURE
     du style (`buildReadingRules`), comme un article. Ils étaient fixés ici
     (16 px, 1,8, h2 22 px, h3 18 px) quel que soit le Thème (2026-10-08). */

  .toweb-product__description :global(p) {
    margin-bottom: 1rem;
  }

  .toweb-product__description :global(ul),
  .toweb-product__description :global(ol) {
    margin-bottom: 1rem;
    padding-left: 1.5rem;
  }

  .toweb-product__description :global(a) {
    color: var(--tw-accent, #3b82f6);
    text-decoration: underline;
  }

  /* Intertitres de la description (HELO 75019 : Titre 2 et Titre 3 dans sa
     barre). L'échelle de lecture seule laissait un h2 à 87 % du NOM du produit
     sur mobile (23,8 px sous 27,2 px, corps de 17) : deux titres de même rang
     à l'œil, alors que la description est SOUS le nom. Plafonds relatifs au
     h1 de lecture, celui du nom (`.toweb-product__title`) : h2 ≤ 80 %, h3 ≤ 68 %,
     h4 (importé) ≤ 60 % — jamais sous le corps du texte. Au bureau, le plafond
     ne mord pas (h2 28,8 px sous un nom de 37,4 sur Atelier). Scopé par
     Astro (attribut), il bat la règle commune `buildReadingRules`. */
  .toweb-product__description :global(h2:not([class*="tw-"])) {
    font-size: min(min(var(--tw-size-h2, var(--theme-size-h2)), clamp(calc(var(--tw-size-base, 1.0625rem) * 1.4), calc(var(--tw-size-h2, var(--theme-size-h2)) * 0.6), calc(var(--tw-size-base, 1.0625rem) * 1.75))), calc(min(var(--tw-size-h1, var(--theme-size-h1)), clamp(calc(var(--tw-size-base, 1.0625rem) * 1.6), calc(var(--tw-size-h1, var(--theme-size-h1)) * 0.5), calc(var(--tw-size-base, 1.0625rem) * 2.2))) * 0.8));
  }
  .toweb-product__description :global(h3:not([class*="tw-"])) {
    font-size: max(calc(var(--tw-size-base, 1.0625rem) * 1.05), min(min(var(--tw-size-h3, var(--theme-size-h3)), clamp(calc(var(--tw-size-base, 1.0625rem) * 1.1), calc(var(--tw-size-h3, var(--theme-size-h3)) * 0.8), calc(var(--tw-size-base, 1.0625rem) * 1.35))), calc(min(var(--tw-size-h1, var(--theme-size-h1)), clamp(calc(var(--tw-size-base, 1.0625rem) * 1.6), calc(var(--tw-size-h1, var(--theme-size-h1)) * 0.5), calc(var(--tw-size-base, 1.0625rem) * 2.2))) * 0.68)));
  }
  .toweb-product__description :global(h4:not([class*="tw-"])) {
    font-size: max(var(--tw-size-base, 1.0625rem), min(min(var(--tw-size-h4, var(--theme-size-h4)), clamp(calc(var(--tw-size-base, 1.0625rem) * 1.05), calc(var(--tw-size-h4, var(--theme-size-h4)) * 0.85), calc(var(--tw-size-base, 1.0625rem) * 1.15))), calc(min(var(--tw-size-h1, var(--theme-size-h1)), clamp(calc(var(--tw-size-base, 1.0625rem) * 1.6), calc(var(--tw-size-h1, var(--theme-size-h1)) * 0.5), calc(var(--tw-size-base, 1.0625rem) * 2.2))) * 0.6)));
  }

  /* Variant selector */
  .toweb-product__option {
    margin-bottom: 1rem;
  }
  .toweb-product__option-label {
    display: block;
    font-size: 0.875rem;
    font-weight: 600;
    margin-bottom: 0.5rem;
    color: var(--tw-text, #0f172a);
  }
  .toweb-product__option-values {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem;
  }
  .toweb-product__option-btn {
    padding: 0.5rem 1rem;
    border: 1px solid var(--tw-border, #e2e8f0);
    border-radius: var(--tw-radius-field, 6px);
    background: var(--tw-surface, #fff);
    color: var(--tw-text, #0f172a);
    font-size: 0.875rem;
    cursor: pointer;
    transition: border-color 0.15s ease, background 0.15s ease;
  }
  .toweb-product__option-btn:hover {
    border-color: var(--tw-accent, #3b82f6);
  }
  .toweb-product__option-btn--active {
    border-color: var(--tw-accent, #3b82f6);
    background: var(--tw-accent, #3b82f6);
    color: var(--tw-on-accent, #fff);
  }
  /* Pastilles couleur (swatches) — P0-1 #117 */
  .toweb-product__swatch {
    width: 34px;
    height: 34px;
    padding: 0;
    border-radius: 50%;
    border: 1px solid var(--tw-border, #e2e8f0);
    background: var(--sw, #ccc);
    background-clip: padding-box;
    cursor: pointer;
    transition: transform 0.12s ease, box-shadow 0.12s ease;
  }
  .toweb-product__swatch:hover {
    transform: scale(1.1);
  }
  .toweb-product__swatch--active {
    box-shadow: 0 0 0 2px var(--tw-surface, #fff), 0 0 0 4px var(--tw-accent, #3b82f6);
  }

  /* Quantity + Add to Cart */
  .toweb-product__actions {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    margin-top: 1rem;
  }
  .toweb-product__qty {
    display: flex;
    align-items: center;
    border: 1px solid var(--tw-border, #e2e8f0);
    border-radius: var(--tw-radius-field, 8px);
    overflow: hidden;
  }
  .toweb-product__qty button {
    width: 36px;
    height: 40px;
    border: none;
    background: var(--tw-surface, #f1f5f9);
    color: var(--tw-text, #0f172a);
    font-size: 1rem;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
  }
  .toweb-product__qty button:hover {
    background: var(--tw-border, #e2e8f0);
  }
  .toweb-product__qty input {
    width: 48px;
    height: 40px;
    text-align: center;
    border: none;
    border-left: 1px solid var(--tw-border, #e2e8f0);
    border-right: 1px solid var(--tw-border, #e2e8f0);
    font-size: 0.9375rem;
    color: var(--tw-text, #0f172a);
    background: var(--tw-surface, #fff);
    -moz-appearance: textfield;
  }
  .toweb-product__qty input::-webkit-inner-spin-button,
  .toweb-product__qty input::-webkit-outer-spin-button {
    -webkit-appearance: none;
    margin: 0;
  }
  .toweb-product__add-to-cart {
    flex: 1;
    height: 40px;
    /* Consomme la brique BOUTON du DNA (--tw-btn-*), PAS l'accent brut : sinon le
       bouton reste « bleu accent » au lieu de prendre le style bouton du DNA
       (noir + ombre dure en Brutalist, dégradé + glow en Aurora…) — retour Yann. */
    border: var(--tw-border-width, 1px) solid var(--tw-btn-border, transparent);
    border-radius: var(--tw-radius-button, 8px);
    background: var(--tw-btn-bg, var(--tw-accent, #3b82f6));
    color: var(--tw-btn-text, var(--tw-on-accent, #fff));
    box-shadow: var(--tw-shadow-button, none);
    font-family: var(--tw-font-body, inherit);
    font-size: 0.9375rem;
    font-weight: var(--tw-btn-weight, 600);
    cursor: pointer;
    transition: transform .18s ease, box-shadow .18s ease, background .18s ease, color .18s ease;
  }
  .toweb-product__add-to-cart:hover:not(:disabled) {
    transform: translateY(var(--tw-btn-hover-lift, -1px));
    background: var(--tw-btn-bg-hover, var(--tw-btn-bg, #222));
    color: var(--tw-btn-text-hover, var(--tw-btn-text, #fff));
    box-shadow: var(--tw-shadow-button-hover, var(--tw-shadow-button, none));
  }
  .toweb-product__add-to-cart:disabled {
    opacity: 0.5;
    cursor: not-allowed;
  }

  /* Alpine x-cloak */
  [x-cloak] {
    display: none !important;
  }


  .toweb-shop-index__title {
    font-size: 2rem;
    font-weight: 700;
    margin-bottom: 1rem;
  }
  .toweb-shop-index__empty {
    color: var(--tw-text-muted, #64748b);
    font-size: 1.05rem;
    padding: 2rem 0 3rem;
  }
  .toweb-shop-collection__ariane {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.5rem;
    font-size: 0.875rem;
    color: var(--tw-text-muted, #64748b);
    margin-bottom: 1.5rem;
  }
  .toweb-shop-collection__ariane a {
    color: var(--tw-prose-link, var(--tw-accent, #3b82f6));
    text-decoration: none;
  }
  .toweb-shop-collection__ariane a:hover {
    text-decoration: underline;
  }
  .toweb-shop-collection__image {
    width: 100%;
    max-height: 300px;
    object-fit: cover;
    border-radius: 8px;
    margin-bottom: 1.5rem;
  }
  .toweb-shop-collection__title {
    font-size: 2rem;
    font-weight: 700;
    margin-bottom: 0.25rem;
  }
  .toweb-shop-collection__desc {
    opacity: 0.75;
    margin-bottom: 0.5rem;
    max-width: 640px;
  }
  .toweb-shop-collection__desc p { margin: 0; }
  .toweb-shop-collection__desc p + p { margin-top: 0.75em; }
  .toweb-shop-collection__count {
    opacity: 0.5;
    font-size: 0.875rem;
    margin-bottom: 1.5rem;
  }
  .toweb-shop-collection__empty {
    opacity: 0.7;
    margin: 2rem 0;
  }
  .toweb-shop-collection__back {
    margin-top: 2rem;
    padding-top: 1.5rem;
    border-top: 1px solid var(--tw-border, #e2e8f0);
  }
  .toweb-shop-collection__back a {
    color: var(--tw-accent, #3b82f6);
    text-decoration: none;
    font-size: 0.875rem;
  }
  .toweb-shop-collection__back a:hover {
    text-decoration: underline;
  }
  .toweb-shop-index__sortbar {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    margin-bottom: 1.5rem;
    justify-content: flex-end;
  }
  .toweb-shop-index__sortlabel {
    font-size: 0.875rem;
    color: var(--tw-text-muted, #64748b);
  }
  .toweb-shop-index__sortselect {
    padding: 0.4rem 0.75rem;
    border: 1px solid var(--tw-border, #e2e8f0);
    border-radius: var(--tw-radius-field, 6px);
    background: var(--tw-surface, #fff);
    color: var(--tw-text, #0f172a);
    font-size: 0.875rem;
    cursor: pointer;
  }
  .toweb-shop-collections {
    list-style: none;
    margin: 0 0 2.5rem;
    padding: 0;
    display: grid;
    grid-template-columns: 1fr;
    gap: 1.25rem;
  }
  @media (min-width: 481px) {
    .toweb-shop-collections { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 1.5rem; }
  }
  @media (min-width: 900px) {
    .toweb-shop-collections { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  }
  .toweb-shop-collections__tile {
    display: flex;
    flex-direction: column;
    height: 100%;
    margin: 0;
  }
  .toweb-shop-collections__link {
    display: flex;
    flex-direction: column;
    flex: 1;
  }
  .toweb-shop-collections__link .product-card__body { flex: 1; }
  /* Paysage (4:3) : une collection se lit comme une entrée de rayon, pas comme un produit. */
  .toweb-shop-collections__media { padding-bottom: 75%; }
  .toweb-shop-collections__placeholder {
    opacity: 1;
    background: color-mix(in oklab, var(--tw-accent, #3b82f6) 14%, var(--tw-surface, #fff));
    color: color-mix(in oklab, var(--tw-accent, #3b82f6) 70%, var(--tw-on-surface, #0f172a));
  }
  .toweb-shop-collections__placeholder span {
    font-family: var(--tw-font-heading, inherit);
    font-size: clamp(2.5rem, 8vw, 3.5rem);
    font-weight: 600;
    line-height: 1;
  }
  .toweb-shop-collections__count {
    margin: 0;
    font-size: 0.875rem;
    color: var(--tw-text-muted, #64748b);
  }
  .toweb-shop-index__subtitle {
    font-size: 1.375rem;
    font-weight: 600;
    margin: 0 0 1rem;
  }
  .toweb-shop-index__all {
    margin: -1rem 0 2.5rem;
  }
  .toweb-shop-index__all a {
    color: var(--tw-prose-link, var(--tw-accent, #3b82f6));
    font-weight: 600;
    text-decoration: none;
  }
  .toweb-shop-index__all a:hover { text-decoration: underline; }
  /* « Les collections » : la grille complète reste dans la page (liens suivis par
     les moteurs, pagination intacte) et s'ouvre par « Voir tous les produits ». */
  .toweb-shop-index__produits--repliee:not(:target) { display: none; }
  .toweb-shop-index__produits { scroll-margin-top: 6rem; }