/* ============================================================
   PAGE HERO (bandeau intérieur commun)
   ============================================================ */
.page-hero {
  position: relative;
  min-height: 0;
  display: flex;
  align-items: flex-start;
  padding-block: var(--spacing-xl);
  overflow: hidden;
  background-color: var(--color-text);
}

.page-hero__bg {
  position: absolute;
  inset: 0;
}

.page-hero__bg img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center;
  opacity: 0.45;
}

.page-hero__overlay {
  position: absolute;
  inset: 0;
  background: linear-gradient(
    to right,
    rgba(44, 31, 20, 0.80) 0%,
    rgba(44, 31, 20, 0.40) 70%,
    rgba(44, 31, 20, 0.15) 100%
  );
}

.page-hero__content {
  position: relative;
  z-index: 2;
  width: 100%;
}

.page-hero__breadcrumb {
  display: none;
}

.page-hero__breadcrumb a {
  color: var(--color-primary);
  opacity: 0.75;
  transition: opacity var(--duration) var(--ease-out);
}

.page-hero__breadcrumb a:hover { opacity: 1; }

.page-hero__breadcrumb span { opacity: 0.5; }

/* Un sur-titre est une étiquette qui appartient au titre sous lui. Tant que
   l'écart au-dessous de lui égalait celui du titre, il flottait entre les
   deux et l'œil ne savait pas s'il coiffait le titre ou concluait le bloc
   précédent. xs le colle à son titre, comme le faisait déjà — seul des
   quatre — .page-section__eyebrow. */
.page-hero__eyebrow {
  font-family: var(--font-hero);
  font-size: 0.75rem;
  font-weight: 600;
  letter-spacing: 0.15em;
  text-transform: uppercase;
  color: var(--color-primary);
  margin-bottom: var(--spacing-xs);
  display: block;
}

.page-hero__title {
  font-family: var(--font-display);
  font-size: clamp(2.25rem, 5.5vw, 4rem);
  font-weight: 700;
  color: var(--color-bg);
  line-height: 1.1;
  letter-spacing: -0.02em;
  /* sm et non xs : le sur-titre étant remonté à xs, garder xs ici rendrait
     les trois éléments équidistants — étiquette, titre et ligne d'accent au
     même écart, donc sans hiérarchie interne. sm rend au titre le pas de
     recul que le sur-titre lui a cédé. Le bloc ne bouge pas : −8 px au-dessus,
     +8 px au-dessous, somme nulle. */
  margin-bottom: var(--spacing-sm);
  max-width: 18ch;
}

.page-hero__script {
  font-family: var(--font-script);
  font-size: clamp(1.25rem, 2.5vw, 1.75rem);
  color: var(--color-primary);
  line-height: 1.3;
  display: block;
}

/* ============================================================
   BREADCRUMB PLACEHOLDER (hero sans image)
   ============================================================ */
.page-hero--plain {
  background-color: var(--color-text);
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='40' height='40' viewBox='0 0 40 40'%3E%3Cpath d='M0 20 L10 10 L20 20 L10 30 Z M20 20 L30 10 L40 20 L30 30 Z' fill='none' stroke='%23CBBBA0' stroke-width='0.6' opacity='0.18'/%3E%3C/svg%3E");
  min-height: 0;
  padding-block: var(--spacing-xl);
  align-items: flex-start;
}

.page-hero--plain .page-hero__bg,
.page-hero--plain .page-hero__overlay {
  display: none;
}

.actu-hero.page-hero--plain {
  background-color: #111;
  background-image: none;
}

.page-hero--trame {
  background-image: none;
  isolation: isolate;
}

.page-hero--trame::before {
  content: '';
  position: absolute;
  inset: 0;
  background-image: url("../images-opt/Fond/A4-vertical-grege.png");
  background-repeat: repeat;
  background-size: 700px auto;
  filter: invert(1) grayscale(1) brightness(3) contrast(10);
  mix-blend-mode: screen;
  opacity: 0.2;
  pointer-events: none;
  z-index: 0;
}

.page-hero--trame .container {
  position: relative;
  z-index: 1;
}

.page-hero--compact {
  min-height: 280px;
  padding-block: var(--spacing-xl) var(--spacing-lg);
}

.page-hero--compact .page-hero__bg img {
  object-fit: cover;
  object-position: center 30%;
}

/* ============================================================
   PAGE SECTION (wrapper commun pour chaque bloc)
   ============================================================ */
/* Chaque section occupe au minimum la hauteur de l'écran, comme le font déjà
   les sections de la page d'accueil. On ne voit donc plus la lisière de la
   section suivante sous celle qu'on lit.
   min-height et non height : une section plus longue que l'écran s'étend
   normalement au lieu d'être rognée. 100vh d'abord pour les navigateurs qui
   ignorent dvh, 100dvh ensuite pour que la barre d'adresse mobile ne compte
   pas dans la hauteur. */
.page-section {
  padding-block: var(--spacing-2xl);
  min-height: calc(100vh - 64px);
  min-height: calc(100dvh - 64px);
  display: flex;
  flex-direction: column;
  justify-content: center;
}

/* L'en-tête est collant et haut de 64 px : il recouvre en permanence le haut
   de la fenêtre. Une section de 100dvh dépasse donc de 64 px la zone qu'on
   peut réellement voir d'un coup — c'est ce qui laissait apparaître la
   lisière de la section suivante et donnait une impression de trop-plein.
   On soustrait la hauteur de l'en-tête à chaque palier, comme le fait déjà
   le hero de la page d'accueil. Les valeurs suivent navigation.css : 64 px
   par défaut, 70 sous 1024, 60 sous 480. */
@media (max-width: 1024px) {
  .page-section {
    min-height: calc(100vh - 70px);
    min-height: calc(100dvh - 70px);
  }
}

@media (max-width: 480px) {
  .page-section {
    min-height: calc(100vh - 60px);
    min-height: calc(100dvh - 60px);
  }
}

/* Une section par écran est un parti pris de grand écran, et il tient tant que
   le contenu remplit la hauteur. Sur téléphone une gamme peut n'avoir qu'une
   carte : les 560 px de contenu se retrouvaient centrés dans 752, soit 56 px de
   vide au-dessus et autant en dessous. Ce vide ne se lit pas comme une
   respiration mais comme un défaut d'affichage — le titre de section semble
   décroché de la barre de gammes qui le surmonte.

   La section prend donc la hauteur de son contenu, et part du haut. Le retrait
   de bloc suffit à séparer deux sections. Ce palier vient après celui de 480 px
   pour le recouvrir : sans quoi la hauteur pleine y reviendrait.

   Le bloc d'appel final est exclu : lui remplit sa hauteur par construction —
   sur-titre, titre surligné, paragraphe, bouton et trame d'épis — et la pleine
   page fait partie de son effet. Il garde donc la règle générale. */
@media (max-width: 600px) {
  .page-section:not(.page-cta) {
    min-height: 0;
    justify-content: flex-start;
  }
}

/* ------------------------------------------------------------
   LA PHOTOGRAPHIE OUVRE LA SECTION
   Nos valeurs, Nos engagements, Les Moments — Les Moments ne charge pas
   company.css, ce dispositif vit donc ici, avec .page-section et .page-inline.
   Sur téléphone, elle remonte jusqu'au bord haut de sa section : ce n'est plus
   un visuel posé à l'intérieur d'un bloc, c'est la séparation entre deux
   sections. D'où la hauteur en bande plutôt qu'un rapport de cadrage, et la
   marge basse qui rétablit la respiration avant le sur-titre.

   L'image intérieure est plus haute que son cadre : cette réserve est la course
   du mouvement de parallaxe, consommée au défilement par main.js. Sans le
   script — ou si l'utilisateur demande moins d'animations — elle reste
   simplement cadrée par object-fit, et rien ne manque.
   ------------------------------------------------------------ */
@media (max-width: 600px) {
  /* Le retrait haut de la section est annulé plutôt que compensé par une marge
     négative : sa valeur change selon le palier, et une marge devinée laissait
     la photographie mordre de 24 px sur la section précédente. */
  /* Doublé en .page-section pour passer devant le retrait de bloc redéfini
     plus bas dans cette feuille : sans cela l'ordre des règles l'emporterait. */
  .page-section.page-section--opens-with-image {
    padding-top: 0;
  }

  .page-inline__image[data-parallax] {
    aspect-ratio: auto;
    height: 62vw;
    min-height: 210px;
  }

  /* Trois espacements s'additionnaient sous la photographie — sa marge, la
     gouttière de la grille et le retrait du bloc de texte — soit 138 px de vide
     avant le sur-titre. La photographie ouvre la section : le texte doit suivre
     de près, sinon elle n'annonce plus rien. La gouttière seule s'en charge. */
  .page-section--opens-with-image .page-inline {
    row-gap: var(--spacing-md);
  }

  .page-inline__image[data-parallax] img {
    height: 128%;
    will-change: transform;
  }

  /* Page Engagements : le visuel de production porte sous lui le macaron IFS.
     Le groupe qui les tient doit donc laisser la photographie déborder jusqu'aux
     bords, sans que le macaron suive — il garde sa gouttière et reste centré. */
  .page-inline__image-wrap {
    width: 100%;
  }

  .page-inline__image-wrap .page-inline__image[data-parallax] {
    /* Le groupe fixe une largeur de 100 % à son visuel : les marges négatives
       le décalaient sans l'élargir. En le laissant s'étirer de lui-même, elles
       le portent bien jusqu'aux deux bords. */
    width: auto;
    align-self: stretch;
    margin-bottom: 0;
  }
}

.products-section {
  padding-block-start: var(--spacing-lg);
  padding-block-end: var(--spacing-2xl);
}

.page-section--alt {
  background-color: var(--color-bg-alt);
}

.page-section--dark {
  background-color: var(--color-text);
  color: var(--color-bg);
}

.page-section__header {
  margin-bottom: var(--spacing-xl);
}

.page-section__eyebrow {
  font-family: var(--font-hero);
  font-size: 0.75rem;
  font-weight: 600;
  letter-spacing: 0.15em;
  text-transform: uppercase;
  color: var(--color-accent-text);
  display: block;
  margin-bottom: var(--spacing-xs);
}

.page-section__title {
  font-family: var(--font-display);
  font-size: clamp(1.75rem, 4vw, 2.75rem);
  color: var(--color-text);
  margin-bottom: var(--spacing-sm);
}

.page-section--dark .page-section__title {
  color: var(--color-bg);
}

.page-section__script {
  font-family: var(--font-script);
  font-size: clamp(1.125rem, 2.2vw, 1.625rem);
  color: var(--color-text-light);
  line-height: 1.3;
  display: block;
  max-width: none;
}

/* Chapô. À 1,0625rem il ne faisait que 6 % de plus que le corps courant :
   un écart que l'œil ne voit pas, donc un chapô qui n'en était pas un.
   La justification descend de 60 à 54 caractères pour compenser le corps
   plus grand : le bloc garde sa largeur — 647 px contre 643 px — et
   contient simplement moins de signes par ligne, ce qu'on attend d'un
   chapô. L'interligne se resserre parce qu'un texte plus grand n'a pas
   besoin d'autant d'air proportionnel. */
.page-section__intro {
  font-size: 1.1875rem;
  line-height: 1.6;
  color: var(--color-text-light);
  max-width: 54ch;
  margin-top: var(--spacing-sm);
}

/* ============================================================
   ACCORDÉON — volets repliables du tiroir produit
   L'animation de hauteur passe par grid-template-rows : 0fr → 1fr. Aucune
   mesure en JavaScript, aucune hauteur en dur — le panneau s'adapte à son
   contenu quelle que soit sa longueur.
   L'état est porté par aria-expanded sur le bouton ; .is-open sur le panneau
   n'en est que le reflet visuel.
   ============================================================ */
.accordion {
  margin-bottom: var(--spacing-md);
  /* Absorbe l'espace libre du cadre : volets fermés, la rangée Cuisson /
     Poids / Portions et le bouton restent en bas plutôt que de flotter au
     milieu d'un panneau devenu plus grand qu'eux. */
  flex: 1;
}

.accordion__header {
  margin: 0;
}

.accordion__trigger {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--spacing-sm);
  width: 100%;
  padding: 0.75rem 0;
  border: none;
  border-bottom: 1px solid rgba(203, 187, 160, 0.5);
  background: none;
  cursor: pointer;
  text-align: left;
  font-family: var(--font-hero);
  font-size: 0.8125rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--color-text);
  transition: color var(--duration) var(--ease-out);
}

.accordion__trigger:hover {
  color: var(--color-accent-text);
}

.accordion__chevron {
  flex-shrink: 0;
  transition: transform var(--duration) var(--ease-out);
}

.accordion__trigger[aria-expanded="true"] .accordion__chevron {
  transform: rotate(180deg);
}

.accordion__panel {
  display: grid;
  grid-template-rows: 0fr;
  transition: grid-template-rows 280ms var(--ease-out);
}

.accordion__panel.is-open {
  grid-template-rows: 1fr;
}

/* overflow: hidden est indispensable : sans lui, le contenu déborderait de
   la rangée de hauteur nulle au lieu d'être masqué. */
.accordion__content {
  overflow: hidden;
}

.accordion__panel.is-open .accordion__content {
  padding-block: var(--spacing-sm);
}

.product-drawer__ingredients,
.product-detail__ingredients {
  list-style: none;
  display: flex;
  flex-direction: column;
  gap: 0.35rem;
  font-size: 0.9375rem;
  color: var(--color-text-light);
  line-height: 1.5;
}

.product-drawer__ingredients li,
.product-detail__ingredients li {
  padding-left: 1rem;
  position: relative;
}

.product-drawer__ingredients li::before,
.product-detail__ingredients li::before {
  content: '';
  position: absolute;
  left: 0;
  top: 0.6em;
  width: 5px;
  height: 5px;
  border-radius: 50%;
  background: var(--color-accent);
}

/* Deux lignes, pas une énumération : « Contient : … » puis « Peut contenir : … ».
   Pas de puce, donc — une puce ferait lire ces deux phrases comme des
   ingrédients de plus. La première porte l'information qui engage, elle prend
   la couleur du texte principal ; la seconde reste au second plan. */
.product-drawer__allergenes,
.product-detail__allergenes {
  list-style: none;
  display: flex;
  flex-direction: column;
  gap: 0.25rem;
  font-size: 0.9375rem;
  color: var(--color-text-light);
  line-height: 1.5;
}

.product-drawer__allergenes li:first-child,
.product-detail__allergenes li:first-child {
  color: var(--color-text);
}

/* Vue détail : le tiroir range ces deux listes dans un accordéon, la page les
   pose l'une sous l'autre. Il leur faut donc le titre que le bouton portait. */
.product-detail__list {
  margin-bottom: var(--spacing-md);
}

.product-detail__list-title {
  font-family: var(--font-hero);
  font-size: 0.675rem;
  font-weight: 700;
  letter-spacing: 0.15em;
  text-transform: uppercase;
  color: var(--color-accent-text);
  margin-bottom: 0.5rem;
}

@media (prefers-reduced-motion: reduce) {
  .accordion__panel,
  .accordion__chevron {
    transition: none;
  }
}

/* ============================================================
   CARROUSEL — chrome partagé (piste, commandes, pastilles)
   Le module JavaScript est commun avec celui de l'accueil : un seul
   [data-carousel] par section, il n'a rien à savoir de l'habillage des
   cartes. Les règles ci-dessous sont l'équivalent de .section-products__*
   dans home.css, qui n'est pas chargé ici — la même duplication assumée que
   pour les cases à cocher entre contact.css et home.css.
   ============================================================ */
.carousel__nav {
  display: flex;
  gap: 0.5rem;
  justify-content: flex-end;
  margin-bottom: var(--spacing-md);
}

.carousel__btn {
  width: 44px;
  height: 44px;
  border: 1.5px solid var(--color-primary);
  background: transparent;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--color-text);
  transition: background var(--duration) var(--ease-out),
              color var(--duration) var(--ease-out),
              opacity var(--duration);
}

.carousel__btn:hover:not(:disabled) {
  background: var(--color-primary);
}

.carousel__btn:disabled {
  opacity: 0.3;
  cursor: default;
}

/* La piste déborde de .container pour que les cartes suivantes se devinent
   au bord de l'écran. Les retraits latéraux ramènent la première carte sur
   la colonne de texte, et scroll-padding aligne l'arrêt du défilement sur ce
   même bord. */
.carousel__track {
  display: flex;
  gap: 20px;
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  scroll-behavior: smooth;
  scrollbar-width: none;
  -ms-overflow-style: none;
  margin-inline: calc(-1 * var(--spacing-md));
  padding-inline: var(--spacing-md);
  scroll-padding-inline-start: var(--spacing-md);
}

.carousel__track::-webkit-scrollbar {
  display: none;
}

.carousel__dots {
  display: flex;
  justify-content: center;
  align-items: center;
  gap: 0;
  margin-top: var(--spacing-md);
  padding: 0;
}

.carousel__dot {
  width: 24px;
  height: 24px;
  padding: 0;
  border: none;
  background: none;
  cursor: pointer;
  display: grid;
  place-items: center;
}

.carousel__dot::before {
  content: '';
  display: block;
  width: 8px;
  height: 8px;
  border-radius: 4px;
  background: var(--color-primary);
  opacity: 0.3;
  transition: opacity var(--duration) var(--ease-out),
              width var(--duration) var(--ease-out);
}

.carousel__dot.is-active::before {
  opacity: 1;
  width: 24px;
}

/* La carte de catégorie devient un élément de piste. Son habillage — image,
   corps crème, sur-titre, titre, texte, bouton — n'est pas touché : seules
   sa largeur et son ancrage de défilement sont ajoutés. */
.carousel__track > .category-card {
  flex-shrink: 0;
  width: 340px;
  scroll-snap-align: start;
}

@media (max-width: 480px) {
  .carousel__track > .category-card {
    width: 80vw;
    max-width: 300px;
  }
}

/* ============================================================
   CATEGORY CARDS (hub Nos Produits)
   ============================================================ */
.category-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--spacing-md);
}

@media (max-width: 900px) {
  .category-grid { grid-template-columns: repeat(2, 1fr); }
}

.category-card {
  position: relative;
  overflow: hidden;
  background-color: var(--color-bg-alt);
  border-radius: 8px;
  display: flex;
  flex-direction: column;
  text-decoration: none;
  color: inherit;
  transition: transform var(--duration) var(--ease-out),
              box-shadow var(--duration) var(--ease-out);
}

.category-card:hover {
  transform: translateY(-4px);
  box-shadow: 0 16px 40px rgba(44, 31, 20, 0.14);
}

.category-card__image {
  position: relative;
  aspect-ratio: 4/3;
  overflow: hidden;
  background-color: var(--color-muted);
}

.category-card__image img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform 500ms var(--ease-out);
}

.category-card:hover .category-card__image img {
  transform: scale(1.04);
}

.category-card__image-placeholder {
  width: 100%;
  height: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  background: linear-gradient(135deg, var(--color-bg-alt) 0%, var(--color-muted) 100%);
}

.category-card__image-placeholder svg {
  opacity: 0.3;
  width: 60px;
  height: 60px;
}

.category-card__body {
  padding: var(--spacing-lg) var(--spacing-md);
  display: flex;
  flex-direction: column;
  flex: 1;
}

.category-card__eyebrow {
  font-family: var(--font-hero);
  font-size: 0.7rem;
  font-weight: 700;
  letter-spacing: 0.15em;
  text-transform: uppercase;
  color: var(--color-accent-text);
  margin-bottom: var(--spacing-xs);
}

.category-card__title {
  font-family: var(--font-display);
  font-size: clamp(1.25rem, 2vw, 1.625rem);
  color: var(--color-text);
  margin-bottom: var(--spacing-sm);
  line-height: 1.2;
}

.category-card__desc {
  font-size: 0.9375rem;
  color: var(--color-text-light);
  line-height: 1.65;
  margin-bottom: var(--spacing-md);
  flex: 1;
  max-width: none;
}

.category-card__link {
  align-self: flex-start;
}

/* ============================================================
   PRODUCT GRID (grille de produits)
   ============================================================ */
.product-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--spacing-md);
}

@media (max-width: 1024px) {
  .product-grid { grid-template-columns: repeat(2, 1fr); }
}

@media (max-width: 480px) {
  .product-grid { grid-template-columns: 1fr; }
}

.product-card {
  background-color: var(--color-bg-alt);
  border: 1px solid rgba(203, 187, 160, 0.4);
  border-radius: 6px;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  flex: 1;
  transition: box-shadow var(--duration) var(--ease-out),
              transform var(--duration) var(--ease-out);
}

.product-card:hover {
  box-shadow: 0 8px 32px rgba(44, 31, 20, 0.10);
  transform: translateY(-3px);
}

.page-section--alt .product-card {
  background-color: var(--color-bg);
}

.product-card__image {
  aspect-ratio: 1;
  overflow: hidden;
  background-color: var(--color-bg-alt);
  position: relative;
}

.product-card__image img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform 500ms var(--ease-out);
}

.product-card:hover .product-card__image img {
  transform: scale(1.04);
}

.product-card__image-placeholder {
  width: 100%;
  height: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  background: linear-gradient(145deg, var(--color-bg-alt) 0%, var(--color-muted) 100%);
}

.product-card__body {
  padding: var(--spacing-md);
  flex: 1;
  display: flex;
  flex-direction: column;
}

.product-card__tag {
  font-family: var(--font-hero);
  font-size: 0.675rem;
  font-weight: 700;
  letter-spacing: 0.15em;
  text-transform: uppercase;
  color: var(--color-accent-text);
  margin-bottom: 0.375rem;
  display: block;
}

.product-card__name {
  font-family: var(--font-display);
  font-size: clamp(1rem, 1.5vw, 1.25rem);
  color: var(--color-text);
  margin-bottom: var(--spacing-xs);
  line-height: 1.25;
}

.product-card__desc {
  font-size: 0.875rem;
  color: var(--color-text-light);
  line-height: 1.6;
  margin-bottom: var(--spacing-sm);
  max-width: none;
  flex: 1;
  display: -webkit-box;
  -webkit-line-clamp: 3;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

.product-card__meta {
  display: flex;
  gap: var(--spacing-sm);
  flex-wrap: wrap;
  padding-top: var(--spacing-sm);
  border-top: 1px solid rgba(203, 187, 160, 0.3);
  margin-top: auto;
}

.product-card__meta-item {
  font-family: var(--font-hero);
  font-size: 0.75rem;
  color: var(--color-text-light);
  display: flex;
  align-items: center;
  gap: 0.25rem;
}

/* ============================================================
   INLINE SECTION (image + texte côte à côte)
   ============================================================ */
.page-inline {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--spacing-xl);
  align-items: center;
}

/* Un élément de grille refuse par défaut de descendre sous la largeur de son
   contenu. Une photographie de 1920 px empêchait donc sa colonne de se réduire,
   et toute la section débordait de l'écran sur téléphone — la page se décalait
   vers la droite et le texte sortait du cadre. min-width: 0 lève ce plancher. */
.page-inline > * {
  min-width: 0;
}

.page-inline--reverse {
  direction: rtl;
}

.page-inline--stretch {
  align-items: stretch;
}

.page-inline--stretch .page-inline__image {
  aspect-ratio: unset;
  min-height: 300px;
}

.page-inline--stretch .page-inline__image img {
  height: 100%;
  object-fit: cover;
}

.page-inline--stretch .page-inline__text {
  max-width: none;
  font-size: 0.9375rem;
  line-height: 1.65;
}

.page-inline--stretch .page-inline__text + .page-inline__text {
  margin-top: var(--spacing-xs);
}

.page-inline--reverse > * {
  direction: ltr;
}

@media (max-width: 768px) {
  .page-inline {
    grid-template-columns: 1fr;
    direction: ltr;
  }

  /* Palier intermédiaire du rythme vertical. Sans lui, la respiration des
     sections tombait de 2xl (96px) à lg (40px) en une seule marche à 480px,
     soit −58 %. xl (64px) rétablit une progression : 96 → 64 → 40. */
  .page-section {
    padding-block: var(--spacing-xl);
  }
}

.page-inline__image {
  position: relative;
  aspect-ratio: 4/3;
  overflow: hidden;
  background-color: var(--color-bg-alt);
  /* 12px — la valeur des grandes images éditoriales du système, celle de
     .section-about__figure img. overflow: hidden est déjà là, l'image
     intérieure est donc découpée par ce rayon. */
  border-radius: 12px;
}

.page-inline__image img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* Sur téléphone, la page alterne trois fois « photographie encadrée, puis
   paragraphe », dans une colonne étroite : tout se ressemble et rien n'appelle
   la lecture. Les photographies passent donc d'un bord à l'autre de l'écran et
   perdent leur cadre. Elles cessent d'être des vignettes alignées pour devenir
   des respirations entre les blocs de texte — la mise en page d'un magazine
   plutôt que d'un tableau. Le texte, lui, garde sa gouttière : c'est ce décalage
   qui crée le rythme. */
@media (max-width: 600px) {
  .page-inline__image {
    margin-inline: calc(-1 * var(--spacing-md));
    border-radius: 0;
  }
}

/* Cette image-là s'aligne sur le bas du texte voisin, plus long que les autres.
   Le calage vivait en style dans le gabarit, où aucun palier ne pouvait le
   reprendre : sur téléphone il ajoutait 155 px de vide au-dessus de la photo,
   la colonne étant alors seule. Il ne s'applique donc plus qu'à deux colonnes. */
@media (min-width: 769px) {
  .page-inline__image--aligned {
    aspect-ratio: unset;
    align-self: stretch;
    padding-top: 9.7rem;
    box-sizing: border-box;
  }
}

.page-inline__image-wrap {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--spacing-sm);
}

.page-inline__image-wrap .page-inline__image {
  width: 100%;
}

.page-inline__badge {
  width: 132px;
  height: auto;
  object-fit: contain;
}

.page-inline__image-placeholder {
  width: 100%;
  height: 100%;
  background: linear-gradient(135deg, var(--color-bg-alt) 0%, var(--color-muted) 100%);
  display: flex;
  align-items: center;
  justify-content: center;
}

.page-inline__content {
  padding-block: var(--spacing-md);
}

/* xs : le sur-titre colle à son titre. Voir .page-hero__eyebrow. */
.page-inline__eyebrow {
  font-family: var(--font-hero);
  font-size: 0.75rem;
  font-weight: 600;
  letter-spacing: 0.15em;
  text-transform: uppercase;
  color: var(--color-accent-text);
  display: block;
  margin-bottom: var(--spacing-xs);
}

.page-inline__title {
  font-family: var(--font-display);
  font-size: clamp(1.5rem, 3vw, 2.25rem);
  color: var(--color-text);
  margin-bottom: var(--spacing-sm);
  line-height: 1.2;
}

/* Titre long à garder sur une seule ligne. La taille de départ est volontairement
   prudente : main.js mesure la largeur réelle du texte et l'agrandit jusqu'à
   remplir la colonne, sans dépasser 2.25rem (taille des autres titres). */
.page-inline__title--fit {
  white-space: nowrap;
  font-size: 1.45rem;
}

/* Bloc dont le titre occupe toute la colonne : les paragraphes suivent la même
   largeur, sinon le texte paraît trop court sous un titre pleine largeur. */
.page-inline__content--wide .page-inline__text {
  max-width: none;
}

.page-inline__script {
  font-family: var(--font-script);
  font-size: clamp(1.125rem, 2vw, 1.5rem);
  color: var(--color-text-light);
  display: block;
  margin-bottom: var(--spacing-md);
  max-width: none;
}

.page-inline__text {
  font-size: 1rem;
  color: var(--color-text-light);
  line-height: var(--lh-body);
  max-width: 52ch;
}

.page-inline__text + .page-inline__text {
  margin-top: var(--spacing-sm);
}

/* ============================================================
   PILLARS / ARGUMENTS (3 ou 4 colonnes icône+texte)
   ============================================================ */
.pillars {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--spacing-lg);
}

.pillars--4 {
  grid-template-columns: repeat(4, 1fr);
}

.pillars--5 {
  grid-template-columns: repeat(5, 1fr);
}

@media (max-width: 1100px) {
  .pillars--5 { grid-template-columns: repeat(3, 1fr); }
}

@media (max-width: 900px) {
  .pillars { grid-template-columns: repeat(2, 1fr); }
  .pillars--4 { grid-template-columns: repeat(2, 1fr); }
  .pillars--5 { grid-template-columns: repeat(2, 1fr); }
}

@media (max-width: 480px) {
  .pillars { grid-template-columns: 1fr; }
  .pillars--4 { grid-template-columns: 1fr; }
  .pillars--5 { grid-template-columns: 1fr; }
}

.pillar {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  gap: var(--spacing-sm);
}

/* Cascade des piliers.

   Cinq valeurs alignées sont une énumération : les faire arriver d'un bloc
   dit « voici un pavé », l'une après l'autre dit « voici cinq choses
   distinctes ». C'est la seule animation de la page qui porte un sens.

   Rien de nouveau n'est introduit : durée, courbe et déplacement viennent de
   l'utilitaire .js-reveal de style.css. On n'ajoute que le décalage.

   Le pas est de 130 ms. À 70 ms, l'écart passait sous le seuil où l'œil
   sépare deux apparitions : les colonnes semblaient arriver ensemble, avec
   un simple flou de bord. 130 ms se lisent de gauche à droite sans que la
   dernière se fasse attendre.

   Portée : les règles ne mordent que si .js-reveal est présente. Elle est
   posée dans company-valeurs.php (cinq valeurs) et products-hub.php (trois
   engagements qualité). Les trois autres gabarits qui emploient .pillar —
   Carrières, Engagements, Gamme pro — ne voient rien.

   Mouvement réduit : la media query de style.css pose transition: none sur
   .js-reveal, ce qui rend ces délais sans objet. Sans JavaScript, la règle
   .no-js les neutralise également. Aucun garde-fou à ajouter ici. */
.pillar.js-reveal:nth-child(2) { transition-delay: 130ms; }
.pillar.js-reveal:nth-child(3) { transition-delay: 260ms; }
.pillar.js-reveal:nth-child(4) { transition-delay: 390ms; }
.pillar.js-reveal:nth-child(5) { transition-delay: 520ms; }

/* En-tête de section à révélation — même partition que le bloc d'appel de
   fin de page, pour que les deux moments forts d'une page battent au même
   rythme :
     0 → 1200 ms   le titre monte et se révèle ;
     650 → 1350 ms le surlignage jaune balaie le mot ;
     1150 ms       le texte d'introduction suit.
   Portée : ces règles ne mordent que si .js-reveal est posée sur le titre
   ou l'introduction, ce qui n'est le cas que dans company-valeurs.php. Les
   en-têtes des autres gabarits sont affichés d'emblée, inchangés.
   Sous mouvement réduit ou sans script, transition-property vaut none : ni
   la durée ni les délais n'ont d'effet. */
.page-section__title.js-reveal {
  transition-duration: 1200ms;
}

.page-section__title.js-reveal .marker-wrap {
  transition-delay: 650ms;
}

.page-section__intro.js-reveal {
  transition-delay: 1150ms;
}

/* Même partition pour un bloc texte-et-image : le titre, puis le surlignage,
   puis la ligne manuscrite et les paragraphes ensemble. Ces règles ne mordent
   que là où .js-reveal est posée sur ces classes — aujourd'hui la seule
   section « Les origines » de Qui sommes-nous. */
.page-inline__title.js-reveal {
  transition-duration: 1200ms;
}

.page-inline__title.js-reveal .marker-wrap {
  transition-delay: 650ms;
}

.page-inline__script.js-reveal,
.page-inline__text.js-reveal {
  transition-delay: 1150ms;
}

/* ------------------------------------------------------------
   SECTION COMPACTE
   Une section dont le contenu dépasse la hauteur visible : le visiteur y
   arrive et le bas lui échappe. Les retraits sont resserrés pour la faire
   tenir d'un seul regard, sans toucher au texte ni aux images.
   Mesuré sur « Les origines » (colonne de 544 px, 17 lignes de texte) :
   853 px avant, 693 px après. min-height reste en place — sur un grand
   écran, la section occupe toujours la hauteur visible et centre son
   contenu.
   ------------------------------------------------------------ */
.page-section--compact {
  padding-block: var(--spacing-lg);
}

.page-section--compact .page-inline__content {
  padding-block: 0;
}

/* Les piliers arrivent APRÈS l'introduction, pas en même temps : le décalage
   de base les repousse au-delà des 1150 ms de celle-ci, puis le pas de 130 ms
   ci-dessus reprend la main de gauche à droite.
   Le décalage est porté par un modificateur explicite, .pillars--sequenced, et
   non par le nombre de colonnes : il ne vaut que là où l'en-tête de section
   est lui-même révélé — Nos valeurs et Nos engagements. Les trois engagements
   qualité de Nos Produits n'ont pas d'en-tête à révélation et gardent leur
   départ immédiat. */
.pillars--sequenced .pillar.js-reveal:nth-child(1) { transition-delay: 1400ms; }
.pillars--sequenced .pillar.js-reveal:nth-child(2) { transition-delay: 1530ms; }
.pillars--sequenced .pillar.js-reveal:nth-child(3) { transition-delay: 1660ms; }
.pillars--sequenced .pillar.js-reveal:nth-child(4) { transition-delay: 1790ms; }
.pillars--sequenced .pillar.js-reveal:nth-child(5) { transition-delay: 1920ms; }

/* En dessous de 900 px ces piliers passent sur deux colonnes, puis sur une
   seule : ils n'arrivent plus en même temps que l'introduction, mais
   l'un après l'autre au fil du défilement. Le décalage de base perd alors son
   objet et se retourne contre l'utilisateur — le dernier attendrait près de
   deux secondes après être entré dans le champ, ce qui se lit comme un
   blocage et non comme une apparition. Seul le pas de cascade est conservé. */
/* Remettre les piliers à zéro sous 900 px les faisait passer DEVANT
   l'introduction, qui attend 1150 ms — un délai calé sur le balayage du
   surlignage, pensé pour le grand écran. On lisait donc le titre, puis les
   piliers, puis seulement le texte qui devait les annoncer.

   L'ordre est rétabli en raccourcissant l'introduction plutôt qu'en retardant
   les piliers : sur un écran étroit ils entrent dans le champ l'un après
   l'autre, et un pilier qui arrive seul ne doit jamais attendre une seconde et
   demie — c'est la raison d'être de ce palier. Aucune attente ne dépasse ici la
   seconde. Seules Nos valeurs et Nos engagements portent .pillars--sequenced,
   la portée est donc exactement celle de ces deux pages. */
@media (max-width: 900px) {
  .page-section:has(.pillars--sequenced) .page-section__intro.js-reveal {
    transition-delay: 300ms;
  }

  .pillars--sequenced .pillar.js-reveal:nth-child(1) { transition-delay: 550ms; }
  .pillars--sequenced .pillar.js-reveal:nth-child(2) { transition-delay: 660ms; }
  .pillars--sequenced .pillar.js-reveal:nth-child(3) { transition-delay: 770ms; }
  .pillars--sequenced .pillar.js-reveal:nth-child(4) { transition-delay: 880ms; }
  .pillars--sequenced .pillar.js-reveal:nth-child(5) { transition-delay: 990ms; }
}

/* Piliers qui suivent un TITRE SEUL, sans introduction entre les deux.
   Le décalage de .pillars--sequenced (1400 ms) est calé sur les 1150 ms d'un
   paragraphe d'introduction : sans lui, l'attente se lirait comme un blocage.
   On repart donc du seul repère disponible, le titre.

   600 ms. Le titre est révélé sur 1200 ms, mais la courbe --ease-out est très
   en avance sur sa durée nominale : à 600 ms il est déjà à 96,1 % d'opacité,
   c'est-à-dire visuellement posé (il franchit 95 % à 570 ms). Comparer les
   durées aurait fait attendre 1200 ms pour rien. C'est aussi la valeur de la
   première carte d'actualités de l'accueil : même situation, même repère.

   Puis le pas de 130 ms des piliers reprend la main, de gauche à droite.
   Portée : Carrières uniquement — c'est le seul en-tête de section réduit à
   un titre dont les piliers sont révélés. */
.pillars--after-title .pillar.js-reveal:nth-child(1) { transition-delay: 600ms; }
.pillars--after-title .pillar.js-reveal:nth-child(2) { transition-delay: 730ms; }
.pillars--after-title .pillar.js-reveal:nth-child(3) { transition-delay: 860ms; }

/* Même raison qu'au-dessus : empilés, les piliers n'entrent plus dans le champ
   en même temps que le titre. Le décalage de base perd son objet. */
@media (max-width: 900px) {
  .pillars--after-title .pillar.js-reveal:nth-child(1) { transition-delay: 0ms; }
  .pillars--after-title .pillar.js-reveal:nth-child(2) { transition-delay: 130ms; }
  .pillars--after-title .pillar.js-reveal:nth-child(3) { transition-delay: 260ms; }
}

/* En-tête dont l'introduction tient en PLUSIEURS blocs — Les Moments.
   La règle générale pose les quatre paragraphes à 1150 ms ; ils arriveraient
   donc ensemble, ce qui redonne le pavé que la partition cherche à défaire.
   Le pas est de 180 ms, celui des cartes d'actualités, et non les 130 ms des
   piliers : ceux-ci sont côte à côte et l'œil les balaie d'un mouvement,
   ici les blocs sont empilés et se lisent l'un après l'autre.
   nth-of-type compte les <p> : le sur-titre et le titre qui les précèdent ne
   décalent pas la numérotation. */
/* En-tête SANS surlignage — Nos Produits, « Notre gamme ».
   Les 1150 ms de la règle générale ne sont pas une valeur de confort : elles
   laissent passer le balayage jaune, qui court de 650 à 1350 ms. Ce titre-là
   n'en a pas ; l'introduction n'aurait donc rien à attendre et le silence se
   verrait. Elle repart du seul repère qui reste, le titre lui-même : à 600 ms
   il est à 96,1 % d'opacité, le même instant que les blocs de Carrières.
   Le nom dit la condition, pas la valeur : le jour où ce titre reçoit un
   surlignage, la classe saute et la règle générale reprend, d'elle-même. */
.page-section__header--no-marker .page-section__intro.js-reveal {
  transition-delay: 600ms;
}

/* Le carrousel arrive en dernier, d'un seul bloc : commandes, piste et
   pastilles partagent le même délai, sans quoi on verrait les flèches
   attendre leurs cartes.
   1050 ms. L'introduction part à 600 ms et dure 900 ms — la durée de base de
   .js-reveal — ce qui la pose à 1021 ms ; à 1050 ms elle est à 96,1 %. Un
   départ à 1000 ms la prendrait encore à 94 %, c'est-à-dire en mouvement.
   Portée : la présence de .js-reveal. Le carrousel de l'accueil ne la porte
   pas et ne voit rien de ces règles. */
.carousel__nav.js-reveal,
.carousel__track.js-reveal,
.carousel__dots.js-reveal {
  transition-delay: 1050ms;
}

.page-section__header--cascade .page-section__intro.js-reveal:nth-of-type(2) { transition-delay: 1330ms; }
.page-section__header--cascade .page-section__intro.js-reveal:nth-of-type(3) { transition-delay: 1510ms; }
.page-section__header--cascade .page-section__intro.js-reveal:nth-of-type(4) { transition-delay: 1690ms; }

.pillar__icon {
  width: 48px;
  height: 48px;
  color: var(--color-accent-text);
  flex-shrink: 0;
}

/* Les piliers portent le sujet de leur section, et ils étaient composés à
   1,12 fois le corps courant quand les titres des blocs narratifs qui les
   illustrent montent à 2,25rem : l'œil lisait les récits d'abord et les
   piliers comme des légendes.
   1,25rem est le dernier palier qui tienne : dans une colonne de 198 px —
   cinq colonnes et quatre gouttières de 40 px dans un conteneur de 1152 —
   le plus long des titres, « Plaisir & Convivialité », mesure 190 px. À
   1,375rem il passe à deux lignes et casse l'alignement de la rangée, ce
   qui coûte plus que le gain de hiérarchie ne rapporte.
   1,15 d'interligne parce que ces titres tiennent sur une ligne : 1,3
   n'ajoutait que de l'espace sous eux, que le gap du pilier fournit déjà. */
.pillar__title {
  font-family: var(--font-display);
  font-size: 1.25rem;
  color: var(--color-text);
  line-height: 1.15;
}

.page-section--dark .pillar__title {
  color: var(--color-bg);
}

/* Un pilier occupe une colonne de 198 px : à 0,9375rem, cela fait une
   justification réelle de 21 signes, et le texte y est centré. Sur une
   ligne aussi courte, 1,7 d'interligne empile des fragments détachés au
   lieu de composer un paragraphe — plus la ligne est courte, plus
   l'interligne doit se resserrer.
   Le plafond de 30ch a été retiré et non ajusté : la colonne plafonne à
   21ch bien avant, il n'a donc jamais rien fait. Une déclaration qui ne
   produit aucun effet en décrit un faux au prochain qui la lira. */
.pillar__text {
  font-size: 0.9375rem;
  color: var(--color-text-light);
  line-height: 1.5;
}

.page-section--dark .pillar__text {
  color: var(--color-primary);
}

/* ============================================================
   CTA BLOCK (bande de contact)
   ============================================================ */
.page-cta {
  padding-block: var(--spacing-2xl);
  text-align: center;
}

/* Dernière section avant le pied de page : elle prend un fond supplémentaire.
   L'ancienne valeur additionnait trois termes dont un sans rapport avec
   l'échelle — xl × 0.8, soit 51,2 px — pour un total de 171,2 px. Deux
   jetons donnent 160 px : 11 px de moins, invisibles en fond de page. */
.page-cta--spaced {
  padding-bottom: calc(var(--spacing-2xl) + var(--spacing-xl));
}

#career-hero-title {
  font-size: clamp(1.75rem, 3.8vw, 2.875rem);
  max-width: none;
  white-space: nowrap;
}

.page-cta__text a {
  color: #1565c0;
  font-weight: 700;
}

/* xs : le sur-titre colle à son titre. Voir .page-hero__eyebrow. */
/* Rythme calé sur celui de « Notre mission », qui sert de référence : cette
   section est une colonne flex dont le gap de 24 px s'AJOUTE aux marges de
   ses éléments, ce qui donne 32 / 40 / 64 px entre ses quatre blocs. Le bloc
   d'appel n'a que des marges ; il reprend donc ces écarts directement.
   Le premier vaut md (24) et non 32 : 32 px ne figure pas sur l'échelle
   xs/sm/md/lg/xl, et une valeur inventée coûterait plus au système que les
   8 px d'écart ne rapportent à l'œil.
   Portée : les neuf gabarits qui portent un bloc d'appel de fin de page. */
.page-cta__eyebrow {
  font-family: var(--font-hero);
  font-size: 0.75rem;
  font-weight: 600;
  letter-spacing: 0.15em;
  text-transform: uppercase;
  color: var(--color-primary);
  display: block;
  margin-bottom: var(--spacing-md);
}

/* Titre centré, sans plafond de justification : à 2,75rem certains de ces
   titres tiennent sur une seule ligne de plus de 700 px, où le retour à la
   ligne suivante devient un long trajet de l'œil — que le centrage aggrave,
   le point de départ se déplaçant d'une ligne à l'autre.
   text-wrap: balance et non un max-width en ch : cette règle sert neuf
   gabarits dont les titres n'ont pas la même longueur, et un plafond calé
   sur l'un d'eux couperait mal les huit autres. Le navigateur équilibre
   chaque titre pour lui-même ; là où il ne connaît pas la propriété, la
   composition reste celle d'aujourd'hui. */
.page-cta__title {
  font-family: var(--font-display);
  font-size: clamp(1.75rem, 3.5vw, 2.75rem);
  color: var(--color-bg);
  margin-bottom: var(--spacing-lg);
  max-width: none;
  text-wrap: balance;
}

.page-cta__text {
  font-size: 1rem;
  color: var(--color-primary);
  margin-bottom: var(--spacing-xl);
  margin-inline: auto;
  max-width: 55ch;
}

/* Séquence du bloc d'appel, en trois temps. On lit d'abord ce qui est
   promis, puis le mot sur lequel la promesse repose, puis ce qu'on peut
   faire :
     0 → 1200 ms   le titre monte et se révèle, plus lentement que le
                   défaut de 900 ms : c'est lui qu'on doit lire en premier ;
     650 → 1350 ms le surlignage jaune balaie le mot important, le titre
                   étant alors lisible à plus de la moitié ;
     1150 ms       le texte et les boutons suivent — après le début du
                   balayage, pas après sa fin, pour qu'aucun temps mort ne
                   s'installe.
   Le décalage se fait ici et non dans le JavaScript : l'observateur pose
   .is-visible sur chaque élément à son propre passage, ce qui ne garantit
   pas l'ordre. Ces délais le garantissent, quelle que soit la vitesse de
   défilement.
   Sous mouvement réduit ou sans script, transition-property vaut none et
   ni ces délais ni cette durée n'ont d'effet : tout reste visible d'emblée. */
.page-cta__title.js-reveal {
  transition-duration: 1200ms;
}

.page-cta__title.js-reveal .marker-wrap {
  transition-delay: 650ms;
}

.page-cta__text.js-reveal,
.page-cta__actions.js-reveal {
  transition-delay: 1150ms;
}

.page-cta__actions {
  display: flex;
  gap: var(--spacing-sm);
  justify-content: center;
  flex-wrap: wrap;
}

.page-cta--light .page-cta__title {
  color: var(--color-text);
}

.page-cta--light .page-cta__text {
  color: var(--color-text-light);
}

.page-cta--light .page-cta__eyebrow {
  color: var(--color-accent-text);
}

/* Sur fond clair, un bouton resté en contour doit foncer son trait et son
   texte pour se détacher. Les variantes qui portent déjà leur propre fond en
   sont exclues, sinon la règle leur imposerait un texte sombre sur ce fond.
   .btn--flow en fait partie : son disque brun se déploie au survol, moment où
   son libellé doit passer en crème. Sans cette exclusion, la spécificité de
   ce sélecteur — quatre fois celle de .btn--flow:hover — le maintenait brun
   sur brun, et le libellé disparaissait. */
.page-cta--light .btn:not(.btn--filled):not(.btn--primary):not(.btn--beige):not(.btn--flow) {
  border-color: var(--color-text);
  color: var(--color-text);
}

/* ============================================================
   PRODUCT CARD — CLICKABLE WRAPPER
   ============================================================ */
.product-card__link-wrap {
  display: flex;
  flex-direction: column;
  flex: 1;
  color: inherit;
  text-decoration: none;
}

.product-card__devis {
  display: inline-block;
  margin-top: var(--spacing-sm);
  font-family: var(--font-hero);
  font-size: 0.75rem;
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--color-accent-text);
  border-bottom: 1px solid var(--color-accent);
  padding-bottom: 0.1em;
  transition: color var(--duration) var(--ease-out),
              border-color var(--duration) var(--ease-out);
}

.product-card__devis:hover {
  color: var(--color-text);
  border-color: var(--color-text);
}

.product-card__link-wrap:focus-visible {
  outline: 2px solid var(--color-accent);
  outline-offset: 2px;
}

/* ============================================================
   PRODUCT DETAIL VIEW
   ============================================================ */
.product-detail__back {
  margin-bottom: var(--spacing-xl);
}

.product-detail__back a {
  font-family: var(--font-hero);
  font-size: 0.775rem;
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--color-text-light);
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  transition: color var(--duration) var(--ease-out);
}

.product-detail__back a:hover {
  color: var(--color-accent-text);
}

.product-detail__meta-grid {
  display: flex;
  gap: var(--spacing-lg);
  flex-wrap: wrap;
  padding-block: var(--spacing-md);
  border-top: 1px solid rgba(203, 187, 160, 0.4);
  border-bottom: 1px solid rgba(203, 187, 160, 0.4);
  margin-bottom: var(--spacing-lg);
}

.product-detail__meta-item {
  display: flex;
  flex-direction: column;
  gap: 0.2rem;
}

.product-detail__meta-label {
  font-family: var(--font-hero);
  font-size: 0.675rem;
  font-weight: 700;
  letter-spacing: 0.15em;
  text-transform: uppercase;
  color: var(--color-accent-text);
}

.product-detail__meta-value {
  font-family: var(--font-display);
  font-size: 1.125rem;
  color: var(--color-text);
}

.product-detail__long-desc {
  font-size: 1rem;
  color: var(--color-text-light);
  line-height: var(--lh-body);
  max-width: none;
  margin-bottom: var(--spacing-lg);
  /* Les descriptions sont saisies en paragraphes : on respecte les retours
     à la ligne du champ ACF sans avoir à y injecter du HTML. */
  white-space: pre-line;
}

.product-detail__actions {
  display: flex;
  gap: var(--spacing-sm);
  flex-wrap: wrap;
  align-items: center;
}

/* ============================================================
   LINE SEPARATOR
   ============================================================ */
.page-divider {
  border: none;
  border-top: 1px solid rgba(203, 187, 160, 0.35);
  margin-block: 0;
}

/* ============================================================
   SECTIONS ANCHOR NAV (tartes fines, pages multi-sections)
   ============================================================ */
.products-sections-nav {
  position: sticky;
  /* Hauteur réelle de ce qui la surplombe (en-tête + barre d'admin WordPress
     le cas échéant), mesurée par main.js. Sans cela, la barre passe sous
     l'en-tête dès que la barre d'admin est affichée. */
  top: var(--mp-header-offset, 64px);
  z-index: 50;
  background: var(--color-bg);
  border-bottom: 1px solid rgba(203, 187, 160, 0.35);
  box-shadow: 0 2px 8px rgba(44, 31, 20, 0.05);
}

.products-sections-nav__inner {
  display: flex;
  overflow-x: auto;
  scrollbar-width: none;
  -ms-overflow-style: none;
}

.products-sections-nav__inner::-webkit-scrollbar {
  display: none;
}

.products-sections-nav__link {
  flex-shrink: 0;
  display: block;
  padding: 0.875rem 1rem;
  font-family: var(--font-hero);
  font-size: 0.7rem;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--color-text-light);
  white-space: nowrap;
  border-bottom: 2px solid transparent;
  margin-bottom: -1px;
  text-decoration: none;
  transition: color var(--duration) var(--ease-out),
              border-color var(--duration) var(--ease-out);
}

.products-sections-nav__link:hover,
.products-sections-nav__link.is-active {
  color: var(--color-text);
  border-bottom-color: var(--color-primary);
}

.products-sections-nav__link:focus-visible {
  outline: 2px solid var(--color-accent);
  outline-offset: -2px;
}

/* Offset scroll pour compenser les barres collantes (en-tête + onglets).
   La valeur exacte est mesurée par main.js et injectée dans --mp-sticky-offset ;
   les valeurs de repli ci-dessous servent si le JS ne s'exécute pas. */
.products-section[id] {
  scroll-margin-top: var(--mp-sticky-offset, 113px);
}

@media (max-width: 1024px) {
  .products-sections-nav {
    top: var(--mp-header-offset, 70px);
  }

  .products-section[id] {
    scroll-margin-top: var(--mp-sticky-offset, 119px);
  }
}

/* ============================================================
   PRODUCT LINE HEADING (Originales / Incontournables)
   ============================================================ */
.product-line {
  margin-bottom: var(--spacing-2xl);
}

.product-line:last-child {
  margin-bottom: 0;
}

.product-line__header {
  display: flex;
  align-items: baseline;
  gap: var(--spacing-md);
  margin-bottom: var(--spacing-lg);
  padding-bottom: var(--spacing-sm);
  border-bottom: 2px solid var(--color-primary);
}

.product-line__title {
  font-family: var(--font-display);
  font-size: clamp(1.25rem, 2.5vw, 1.75rem);
  color: var(--color-text);
}

.product-line__script {
  font-family: var(--font-script);
  font-size: clamp(1rem, 1.8vw, 1.375rem);
  color: var(--color-text-light);
  display: block;
  max-width: none;
}

/* ============================================================
   PRODUCT DRAWER (modale centrée, deux colonnes)
   ============================================================ */
.product-drawer {
  position: fixed;
  inset: 0;
  z-index: 1000;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 1.5rem;
  pointer-events: none;
  visibility: hidden;
}

.product-drawer.is-open {
  pointer-events: auto;
  visibility: visible;
}

.product-drawer__overlay {
  position: absolute;
  inset: 0;
  background: rgba(30, 24, 16, 0.6);
  opacity: 0;
  transition: opacity 0.28s ease;
}

.product-drawer.is-open .product-drawer__overlay {
  opacity: 1;
}

/* Rectangle centré : image gauche | contenu droite */
.product-drawer__panel {
  position: relative;
  z-index: 1;
  width: min(820px, 100%);
  /* Hauteur FIXE, et non plafonnée : avec max-height, le panneau se réglait
     sur son contenu, si bien que la fiche changeait de taille selon le volet
     ouvert — et la photographie avec elle. Une hauteur ferme donne un cadre
     constant ; ce qui dépasse défile dans la colonne de droite, qui porte
     déjà overflow-y: auto. dvh d'abord pour que la barre d'adresse mobile ne
     compte pas, vh en repli. */
  height: min(680px, 86vh);
  height: min(680px, 86dvh);
  background: var(--color-bg);
  border-radius: 4px;
  display: grid;
  grid-template-columns: 300px 1fr;
  overflow: hidden;
  box-shadow: 0 28px 80px rgba(0, 0, 0, 0.32);
  opacity: 0;
  transform: translateY(-12px) scale(0.97);
  transition: transform 0.3s cubic-bezier(0.34, 1.2, 0.64, 1),
              opacity 0.25s ease;
}

.product-drawer.is-open .product-drawer__panel {
  opacity: 1;
  transform: translateY(0) scale(1);
}

/* Bouton fermer — coin supérieur droit du panneau */
.product-drawer__close {
  position: absolute;
  top: 0.75rem;
  right: 0.75rem;
  width: 2rem;
  height: 2rem;
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(242, 237, 230, 0.92);
  border: none;
  border-radius: 50%;
  cursor: pointer;
  color: var(--color-text);
  z-index: 2;
  backdrop-filter: blur(4px);
  transition: background 0.2s ease, color 0.2s ease;
}

.product-drawer__close:hover {
  background: #F2EDE6;
  color: var(--color-accent-text);
}

.product-drawer__close:focus-visible {
  outline: 2px solid var(--color-accent);
  outline-offset: 2px;
}

/* Colonne gauche : image pleine hauteur */
.product-drawer__image-wrap {
  grid-column: 1;
  overflow: hidden;
  background: linear-gradient(160deg, #EDE7DC, #D4CFC8);
}

.product-drawer__image-wrap img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

/* Colonne droite : contenu scrollable */
.product-drawer__inner {
  grid-column: 2;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
}

.product-drawer__content {
  padding: var(--spacing-xl);
  padding-top: calc(var(--spacing-xl) + 0.5rem);
  display: flex;
  flex-direction: column;
  min-height: 100%;
}

.product-drawer__tag {
  font-family: var(--font-hero);
  font-size: 0.6rem;
  font-weight: 700;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--color-accent-text);
  display: block;
  margin-bottom: 0.375rem;
}

.product-drawer__name {
  font-family: var(--font-display);
  font-size: clamp(1.25rem, 2.5vw, 1.625rem);
  color: var(--color-text);
  line-height: 1.2;
  margin-bottom: var(--spacing-md);
  max-width: none;
}

.product-drawer__desc-long {
  font-size: 0.9375rem;
  color: var(--color-text-light);
  line-height: var(--lh-body);
  margin-bottom: var(--spacing-lg);
  max-width: none;
  /* Respecte les paragraphes du champ ACF (voir .product-detail__long-desc) */
  white-space: pre-line;
}

.product-drawer__meta {
  display: flex;
  gap: var(--spacing-lg);
  flex-wrap: wrap;
  padding-block: var(--spacing-md);
  border-top: 1px solid rgba(203, 187, 160, 0.4);
  border-bottom: 1px solid rgba(203, 187, 160, 0.4);
  margin-bottom: var(--spacing-lg);
}

.product-drawer__meta-item {
  display: flex;
  flex-direction: column;
  gap: 0.15rem;
}

/* Un `display` déclaré l'emporte sur l'attribut hidden : sans ces deux règles,
   product-drawer.js masquerait ces éléments sans que rien ne disparaisse à
   l'écran. Elles rendent le masquage effectif, filets compris — une rangée
   vide entre deux traits se lirait comme un défaut d'affichage plutôt que
   comme une donnée manquante. */
.product-drawer__meta[hidden],
.product-drawer__meta-item[hidden] {
  display: none;
}

.product-drawer__meta-label {
  font-family: var(--font-hero);
  font-size: 0.575rem;
  font-weight: 700;
  letter-spacing: 0.15em;
  text-transform: uppercase;
  color: var(--color-accent-text);
}

.product-drawer__meta-value {
  font-family: var(--font-display);
  font-size: 0.9375rem;
  color: var(--color-text);
}

.product-drawer__actions {
  padding-bottom: 0.25rem;
}

body.drawer-open {
  overflow: hidden;
}

/* Mobile : colonne unique, image en haut, panel remonte depuis le bas */
@media (max-width: 580px) {
  .product-drawer {
    padding: 0;
    align-items: flex-end;
  }

  .product-drawer__panel {
    width: 100%;
    /* En feuille de bas d'écran, la hauteur ferme n'a pas lieu d'être : on
       revient à un plafond, le contenu commande. */
    height: auto;
    max-height: 90vh;
    max-height: 90dvh;
    border-radius: 12px 12px 0 0;
    grid-template-columns: 1fr;
    transform: translateY(24px);
  }

  .product-drawer.is-open .product-drawer__panel {
    transform: translateY(0);
  }

  .product-drawer__image-wrap {
    grid-column: 1;
    aspect-ratio: 16 / 9;
    height: auto;
  }

  .product-drawer__inner {
    grid-column: 1;
  }

  .product-drawer__content {
    padding: var(--spacing-md);
    padding-top: var(--spacing-md);
  }
}

/* ============================================================
   MOMENTS — hero titre sur une ligne
   ============================================================ */
#moments-hero-title {
  max-width: none;
  white-space: nowrap;
}

/* ============================================================
   PAGE SECTION HEADER — variante centrée
   ============================================================ */
.page-section__header--centered {
  text-align: center;
}

.page-section__header--centered .page-section__intro {
  margin-inline: auto;
}

/* ============================================================
   MOMENTS — layout inline aligné sur la hauteur de l'image
   ============================================================ */
.page-inline--moments {
  align-items: stretch;
}

.page-inline--moments .page-inline__image {
  aspect-ratio: unset;
  min-height: 340px;
  border-radius: 8px;
  overflow: hidden;
}

.page-inline--moments .page-inline__image img {
  height: 100%;
  object-fit: cover;
}

/* Sur téléphone ces visuels ouvrent leur section comme ceux de Nos valeurs et
   Nos engagements. Deux règles plus spécifiques doivent être reprises ici pour
   que le palier général s'applique : l'angle arrondi, qui se lit comme un
   défaut contre le bord de l'écran, et la hauteur minimale de 340 px, qui
   empêcherait la bande de garder ses proportions. */
@media (max-width: 600px) {
  .page-inline--moments .page-inline__image[data-parallax] {
    border-radius: 0;
    min-height: 210px;
  }

  /* Ces visuels-là déclarent height: 100% sur leur image, ce qui annulait la
     réserve de 28 % dans laquelle se prend le mouvement. */
  .page-inline--moments .page-inline__image[data-parallax] img {
    height: 128%;
  }
}

.page-inline--moments .page-inline__content {
  display: flex;
  flex-direction: column;
  padding-top: 0;
  padding-bottom: var(--spacing-sm);
}

.page-inline--moments .page-inline__content .btn {
  margin-top: var(--spacing-lg);
  align-self: center;
}

/* Sur-titre, titre, accroche et texte centrés comme le bouton */
.page-inline--moments .page-inline__content {
  text-align: center;
}

/* Le paragraphe est limité à 52ch : sans marges auto, le bloc resterait
   collé à gauche même avec le texte centré. */
.page-inline--moments .page-inline__text {
  margin-inline: auto;
}

/* ============================================================
   RESPONSIVE — HERO INTERNE & SECTIONS
   ============================================================ */

@media (max-width: 768px) {
  /* Hero titre réduit */
  .page-hero__title {
    font-size: clamp(2rem, 4vw, 3rem);
  }

  /* Anchor nav : colle sous le header 70px */
  .products-sections-nav {
    top: 70px;
  }
}

@media (max-width: 480px) {
  /* Respiration des sections : lg (40px) au lieu des 2xl (96px) du grand
     écran. Le jeton et non le littéral 2.5rem — c'est la même valeur, mais
     elle suivra l'échelle le jour où celle-ci sera retouchée. L'ancien
     commentaire annonçait « 80px » alors que la base est de 96. */
  .page-section {
    padding-block: var(--spacing-lg);
  }

  /* Category grid hub : 1 colonne */
  .category-grid {
    grid-template-columns: 1fr;
  }

  /* Hero interne : texte centré */
  .page-hero {
    padding-block: var(--spacing-xl) var(--spacing-lg);
  }

  .page-hero__content {
    text-align: center;
  }

  .page-hero__breadcrumb {
    justify-content: center;
  }

  .page-hero__eyebrow {
    text-align: center;
  }

  .page-hero__title {
    max-width: none;
    font-size: clamp(1.875rem, 7vw, 2.25rem);
  }

  .page-hero__script {
    font-size: clamp(1.125rem, 5vw, 1.375rem);
  }

  /* Anchor nav : header 60px mobile */
  .products-sections-nav {
    top: var(--mp-header-offset, 60px);
  }

  .products-section[id] {
    scroll-margin-top: var(--mp-sticky-offset, 109px);
  }

  /* Product line header : empilé */
  .product-line__header {
    flex-direction: column;
    gap: var(--spacing-xs);
  }
}
