/* ==========================================================================
   Maison Léonard — feuille de style unique
   Mobile-first. Breakpoint principal : 900 px. Contenu : 1180 px max.
   ========================================================================== */

/* --------------------------------------------------------------------------
   0. Polices hébergées sur le site (29/09/2026) : aucun appel à Google Fonts
   ni à Fontshare. Fichiers officiels, non modifiés (assets/fonts/).
   - Satoshi (Indian Type Foundry, ITF Free Font License v2.0) : 500 et 700.
     Auto-hébergement autorisé pour nos propres sites ; interdit de modifier
     les fichiers ou de les redistribuer (dépôt GitHub privé). Pour un site
     de cliente, la cliente télécharge sa propre copie sur Fontshare.
   - Source Serif 4 (Adobe, SIL OFL 1.1, licence jointe) : Regular 400,
     Semibold 600, Italique 400, versions fixes (sans axe optique).
   Satoshi Bold (titre du hero) est préchargée dans le <head> des pages.
   -------------------------------------------------------------------------- */
@font-face {
  font-family: "Satoshi";
  src: url("../assets/fonts/Satoshi-Medium.woff2") format("woff2");
  font-weight: 500;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "Satoshi";
  src: url("../assets/fonts/Satoshi-Bold.woff2") format("woff2");
  font-weight: 700;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "Source Serif 4";
  src: url("../assets/fonts/SourceSerif4-Regular.woff2") format("woff2");
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "Source Serif 4";
  src: url("../assets/fonts/SourceSerif4-Semibold.woff2") format("woff2");
  font-weight: 600;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "Source Serif 4";
  src: url("../assets/fonts/SourceSerif4-It.woff2") format("woff2");
  font-weight: 400;
  font-style: italic;
  font-display: swap;
}

/* --------------------------------------------------------------------------
   1. Variables (palette et réglages du brief, à reprendre telles quelles)
   -------------------------------------------------------------------------- */
:root {
  --ecru:   #F1EAD9;   /* fond dominant */
  --ecru-2: #E8DFCB;   /* fonds secondaires, bordures */
  --ecru-clair: #F8F4EB; /* fond de « Nous contacter » sur Infos pratiques : écru très clair, proche
                            d'un blanc cassé chaud (ajouté le 21/09/2026, validé dans OpenDesign) */
  --blanc:  #FBF8F2;   /* sections claires, texte sur kaki */
  --kaki:   #4F5A3C;   /* boutons, liens actifs, menu */
  --kaki-2: #3E4830;   /* footer */
  --kaki-clair: #647249; /* survol des boutons kaki (ajouté le 16/09/2026, contraste 4,9:1 avec le blanc) */
  --brun:   #7B5A3B;   /* texte secondaire, accents */
  --encre:  #2B2620;   /* texte principal */

  /* --- Les deux familles ---
     Satoshi : Fontshare, graisses 500 / 700 / 900. Géométrique à forte
     hauteur d'x : elle exige un interlettrage négatif dès qu'elle grandit.
     Source Serif 4 : Google Fonts, axe optique 8..60 et vrai italique
     cursif. Seules les graisses 400 et 600 (romain) et 400 (italique) sont
     chargées : aucun élément au serif ne doit demander 500. */
  --satoshi: "Satoshi", "Helvetica Neue", "Segoe UI", Arial, sans-serif;
  --serif:   "Source Serif 4", "Iowan Old Style", Georgia, "Times New Roman", serif;

  --hauteur-header: 72px;
  --hauteur-barre-mobile: 60px;
  --largeur-contenu: 1180px;
  --rayon: 3px;
  --transition: 180ms ease;
}

/* --------------------------------------------------------------------------
   1b. L'échelle typographique (direction validée dans OpenDesign)

   Chaque rôle a sa taille, sa graisse, son interlettrage et son interligne.
   Tout est centralisé ici : changer une valeur la change partout.

   Satoshi porte ce que la maison annonce ou ce qui sert à agir : titres,
   étiquettes, nomenclature, interface, données. Source Serif 4 porte ce que
   la maison raconte ou dit d'elle-même : récit, affirmations, voix.
   L'italique appartient à Source Serif 4 et quitte les tailles de titre
   pour les tailles de parole.

   Le h1 est en graisse 700 à −0,03em : valeurs retenues dans OpenDesign le
   20/09/2026 (variante « titres 700 espacé »). Le −0,035em d'origine avait
   été calibré pour du Satoshi Black, dont les fûts très épais rapprochent
   optiquement les lettres ; un 700 est moins dense et a besoin de cette
   respiration.
   -------------------------------------------------------------------------- */
:root {
  /* Logotype et titres — Satoshi */
  --t-logo-taille:    1.375rem;                      /* 22 px */
  --t-logo-graisse:   700;
  --t-logo-lettres:   -0.02em;

  --t-h1-taille:      clamp(3rem, 7.5vw, 5.5rem);    /* 48 → 88 px */
  --t-h1-graisse:     700;
  --t-h1-lettres:     -0.03em;
  --t-h1-interligne:  0.95;

  --t-h2-taille:      clamp(1.875rem, 3.4vw, 2.625rem); /* 30 → 42 px */
  --t-h2-graisse:     700;
  --t-h2-lettres:     -0.025em;
  --t-h2-interligne:  1.08;

  --t-h3-taille:      1.25rem;                       /* 20 px */
  --t-h3-graisse:     600;
  --t-h3-lettres:     -0.015em;
  --t-h3-interligne:  1.25;

  /* Libellé tracé en capitales — Satoshi. Registre étiquette. */
  --t-label-taille:   0.8125rem;                     /* 13 px */
  --t-label-graisse:  500;
  --t-label-lettres:  0.1em;

  /* Interface : navigation, boutons, horaires — Satoshi */
  --t-ui-taille:      0.9375rem;                     /* 15 px */
  --t-ui-graisse:     500;

  /* Voix — Source Serif 4 italique. Registre parole, jamais titre. */
  --t-voix-taille:    clamp(1.25rem, 2.2vw, 1.625rem); /* 20 → 26 px */
  --t-voix-interligne: 1.35;

  /* Texte courant — Source Serif 4 */
  --t-intro-taille:   1.1875rem;                     /* 19 px */
  --t-intro-interligne: 1.6;

  --t-corps-taille:   1.0625rem;                     /* 17 px */
  --t-corps-interligne: 1.65;

  --t-affirm-taille:  1.125rem;                      /* 18 px */
  --t-affirm-graisse: 600;

  /* Largeur de lecture : 38rem au lieu de 46rem.
     La chasse de Source Serif 4 est plus étroite que celle de DM Sans ;
     à largeur égale la ligne passerait à 85 signes. 38rem à 17 px
     ramène la ligne autour de 68 signes. */
  --largeur-lecture:  38rem;
}

/* --------------------------------------------------------------------------
   2. Base
   -------------------------------------------------------------------------- */
*,
*::before,
*::after {
  box-sizing: border-box;
}

html {
  scroll-behavior: smooth;
  /* Les ancres s'arrêtent sous le header fixe */
  scroll-padding-top: calc(var(--hauteur-header) + 16px);
}

body {
  margin: 0;
  font-family: var(--serif);
  font-weight: 400;
  font-size: var(--t-corps-taille);
  line-height: var(--t-corps-interligne);
  color: var(--encre);
  background: var(--ecru);
  -webkit-font-smoothing: antialiased;
  /* Chiffres alignés dans les horaires et l'adresse */
  font-variant-numeric: lining-nums;
}

/* Les pages intérieures laissent la place au header fixe.
   L'accueil n'en a pas besoin : le hero passe dessous. */
main {
  padding-top: var(--hauteur-header);
}
.accueil main {
  padding-top: 0;
}

img,
video {
  display: block;
  max-width: 100%;
  height: auto;
}

a {
  color: var(--kaki);
  text-decoration-thickness: 1px;
  text-underline-offset: 3px;
  transition: color var(--transition);
}
a:hover {
  color: var(--kaki-2);
}

p {
  margin: 0 0 1.15em;
}
p:last-child {
  margin-bottom: 0;
}

ul,
ol {
  margin: 0;
  padding: 0;
  list-style: none;
}

/* Focus clavier visible partout */
:focus-visible {
  outline: 2px solid var(--kaki);
  outline-offset: 3px;
}
.fond-sombre :focus-visible,
.hero :focus-visible,
.footer :focus-visible {
  outline-color: var(--blanc);
}

/* --------------------------------------------------------------------------
   3. Typographie
   Titres en Satoshi : ils annoncent. Texte en Source Serif 4 : il raconte.
   Toutes les valeurs viennent des jetons du bloc 1b.
   -------------------------------------------------------------------------- */
h1,
h2,
h3 {
  font-family: var(--satoshi);
  margin: 0 0 0.5em;
  color: inherit;
  text-wrap: balance;
}

h1 {
  font-size: var(--t-h1-taille);
  font-weight: var(--t-h1-graisse);
  letter-spacing: var(--t-h1-lettres);
  line-height: var(--t-h1-interligne);
}

h2 {
  font-size: var(--t-h2-taille);
  font-weight: var(--t-h2-graisse);
  letter-spacing: var(--t-h2-lettres);
  line-height: var(--t-h2-interligne);
}

h3 {
  font-size: var(--t-h3-taille);
  font-weight: var(--t-h3-graisse);
  letter-spacing: var(--t-h3-lettres);
  line-height: var(--t-h3-interligne);
}

/* Registre voix : ce que la maison dit d'elle-même. L'italique est celui de
   Source Serif 4, un vrai italique cursif, à une taille de parole et non de
   titre. */
.italique {
  font-family: var(--serif);
  font-style: italic;
  font-weight: 400;
  font-size: var(--t-voix-taille);
  line-height: var(--t-voix-interligne);
  letter-spacing: 0;
  text-wrap: balance;
}

.texte-secondaire {
  color: var(--brun);
}

/* Largeur de lecture confortable pour les blocs de texte */
.texte-lecture {
  max-width: var(--largeur-lecture);
  font-size: var(--t-intro-taille);
  line-height: var(--t-intro-interligne);
}

/* --------------------------------------------------------------------------
   4. Conteneur et sections
   -------------------------------------------------------------------------- */
.conteneur {
  width: 100%;
  max-width: var(--largeur-contenu);
  margin: 0 auto;
  padding-left: 1.25rem;
  padding-right: 1.25rem;
}

.section {
  padding-top: 3.5rem;
  padding-bottom: 3.5rem;
}

.section--ecru   { background: var(--ecru); }
.section--ecru-2 { background: var(--ecru-2); }
.section--blanc  { background: var(--blanc); }
.section--kaki   { background: var(--kaki); color: var(--blanc); }

.section--centre {
  text-align: center;
}
.section--centre .texte-lecture {
  margin-left: auto;
  margin-right: auto;
}

/* En-tête de section avec un titre à gauche et un bouton à droite */
.section__entete {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: 1rem 2rem;
  margin-bottom: 2rem;
}
.section__entete h2 {
  margin-bottom: 0;
}

/* --------------------------------------------------------------------------
   5. Boutons
   Rectangulaires, rayon 3 px, padding 14/26 px. Un seul style par contexte.
   -------------------------------------------------------------------------- */
.bouton {
  display: inline-block;
  padding: 14px 26px;
  border-radius: var(--rayon);
  border: 1.5px solid transparent;
  font-family: var(--satoshi);
  font-weight: 700;
  font-size: var(--t-ui-taille);
  line-height: 1.2;
  letter-spacing: 0;
  text-decoration: none;
  text-align: center;
  cursor: pointer;
  transition: background-color var(--transition), color var(--transition), border-color var(--transition);
}

/* Plein kaki : sur fond clair */
.bouton--plein {
  background: var(--kaki);
  border-color: var(--kaki);
  color: var(--blanc);
}
.bouton--plein:hover {
  background: var(--kaki-clair);
  border-color: var(--kaki-clair);
  color: var(--blanc);
}

/* Contour : kaki sur fond clair, blanc sur fond sombre ou photo */
.bouton--contour {
  background: transparent;
  border-color: currentColor;
  color: var(--kaki);
}
.bouton--contour:hover {
  background: var(--kaki);
  border-color: var(--kaki);
  color: var(--blanc);
}
.fond-sombre .bouton--contour,
.hero .bouton--contour {
  color: var(--blanc);
}
.fond-sombre .bouton--contour:hover,
.hero .bouton--contour:hover {
  background: var(--blanc);
  border-color: var(--blanc);
  color: var(--kaki);
}

/* Blanc plein : sur fond kaki */
.bouton--blanc {
  background: var(--blanc);
  border-color: var(--blanc);
  color: var(--kaki);
}
.bouton--blanc:hover {
  background: var(--ecru-2);
  border-color: var(--ecru-2);
  color: var(--kaki-2);
}

/* Zoom au survol (boutons « Passer une commande ») */
.bouton--zoom {
  transition: background-color var(--transition), color var(--transition), border-color var(--transition),
              transform var(--transition), box-shadow var(--transition);
}
.bouton--zoom:hover,
.bouton--zoom:focus-visible {
  transform: scale(1.05);
  box-shadow: 0 10px 24px rgba(43, 38, 32, 0.25);
}

/* Groupe de boutons */
.boutons {
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem;
}
.boutons--centre {
  justify-content: center;
}

/* --------------------------------------------------------------------------
   5b. Les appels à l'action de l'accueil (validés dans OpenDesign)

   Trois registres pour trois intentions, et trois signes qui ne se
   ressemblent pas. « Nous trouver » est l'action pratique : un cadre au rayon
   court et au contour fin, identifié par son épingle de localisation.
   « Nos produits » est une invitation à poursuivre : pas de cadre, un mot, un
   trait, une flèche. « Passer une commande » est la seule action de la page
   qui engage : c'est le seul aplat.

   Chaque bouton porte un seul pictogramme, et ce pictogramme dit sa nature.
   L'épingle situe, la flèche entraîne.

   Le mouvement est calibré : entrée 280 ms en ease-out, sortie 180 ms en
   ease-in, soit 64 % de l'entrée. Une interface se pose lentement et se
   retire vite. Ni ombre portée, ni halo, ni agrandissement : sur une vidéo de
   fournil, le moindre effet appuyé ferait basculer la page du côté
   démonstration.
   -------------------------------------------------------------------------- */

/* Les deux boutons du hero n'ont pas la même hauteur de boîte — l'un a un
   contour, l'autre non. On les aligne sur leur centre optique plutôt que de
   les étirer à la même hauteur. */
.hero .boutons {
  align-items: center;
  gap: 1.25rem;
}

.cta {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  font-family: var(--satoshi);
  font-weight: 700;
  font-size: var(--t-ui-taille);
  line-height: 1.2;
  text-decoration: none;
  cursor: pointer;
  transition: background-color 180ms ease-in, border-color 180ms ease-in,
              color 180ms ease-in;
}

/* Icônes : une seule famille, tracé ouvert, même épaisseur de 1,6 px,
   terminaisons rondes. Elles prennent la couleur du texte et se dimensionnent
   en em, donc elles suivent la typographie sans réglage séparé. */
.cta__icone,
.cta__fleche {
  flex: none;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.6;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.cta__icone {
  width: 1.15em;
  height: 1.15em;
}
.cta__fleche {
  width: 0.95em;
  height: 0.95em;
  transition: transform 180ms ease-in;
}

/* --- « Nous trouver » : cadre à coins courts et contour fin ---
   Rayon de 12 px plutôt qu'une capsule. La capsule est une forme qui parle
   d'elle-même et tire vers l'application mobile ; un rayon court laisse le
   pictogramme et le mot porter l'identification. */
.cta--cadre {
  padding: 13px 22px;   /* 46 px de haut avec la bordure : au-dessus du plancher tactile de 44 px */
  border: 1px solid;
  border-radius: 12px;
}

/* Sur la vidéo du hero : blanc cassé, fond à peine teinté pour décoller
   le bouton de l'image sans l'opacifier. Le contour à 45 % d'alpha donne
   ~3,3:1 sur le dégradé sombre, au-dessus du plancher de 3:1 exigé pour un
   élément graphique porteur de sens. */
.hero .cta--cadre {
  color: var(--blanc);
  border-color: rgba(251, 248, 242, 0.45);
  background: rgba(251, 248, 242, 0.06);
}

/* --- « Nos produits » : sans cadre, trait fin dessous ---
   Deux filets superposés : ::before est le trait au repos, ::after le même
   trait en blanc plein, réduit à zéro et ancré à gauche. Au survol il se
   déploie horizontalement par-dessus l'autre. L'ordre compte : ::after est
   peint après ::before, donc il le recouvre sans z-index. */
.cta--trait {
  position: relative;
  padding: 13px 2px;    /* 44 px de haut, aligné sur le plancher tactile */
}
.cta--trait::before,
.cta--trait::after {
  content: "";
  position: absolute;
  left: 2px;
  right: 2px;
  bottom: 8px;
  height: 1px;
}
.cta--trait::after {
  transform: scaleX(0);
  transform-origin: left center;
  transition: transform 180ms ease-in;
}
.hero .cta--trait {
  color: var(--blanc);
}
.hero .cta--trait::before {
  background: rgba(251, 248, 242, 0.4);
}
.hero .cta--trait::after {
  background: var(--blanc);
}

/* --- « Passer une commande » : le seul bouton plein de la page ---

   Pas de pictogramme, volontairement : l'épingle et la flèche du hero sont
   déjà prises, un troisième signe ferait de l'icône un tic de page. Ici la
   forme pleine dit à elle seule le poids de l'action.

   Le rayon s'écarte du hero : 8 px contre 12 px. Un angle plus court durcit
   légèrement la forme et la distingue au premier regard, sans sortir du
   vocabulaire. 48 px de haut, soit 2 px de plus que les boutons du hero —
   l'écart se voit à peine et suffit à le poser au-dessus d'eux.

   Le fond et le texte ne se transitionnent pas à la même vitesse, et c'est
   délibéré. Une inversion crème ↔ vert passe par un milieu trouble : à
   mi-parcours le fond est à moitié vidé et le texte à moitié éclairci, donc
   le contraste plonge. Le texte est réglé à 200 ms et le fond à 280 ms : il
   s'éclaircit d'abord, le sol se retire sous lui ensuite. */
.cta--plein {
  justify-content: center;
  padding: 15px 32px;
  border: 1px solid;
  border-radius: 8px;
  transition: background-color 180ms ease-in, border-color 180ms ease-in,
              color 180ms ease-in, transform 180ms ease-in;
}

/* Au repos : texte kaki sur crème, 6,9:1. La bordure est crème elle aussi,
   donc invisible — elle se confond avec l'aplat. C'est son rôle : elle ne
   sert pas au repos, elle devient l'arête du bouton quand le fond s'évide. */
.fond-sombre .cta--plein {
  color: var(--kaki);
  border-color: var(--blanc);
  background: var(--blanc);
}

/* --- Survol : réservé aux appareils à pointeur réel ---
   Sur écran tactile, :hover reste collé après le tap et laisserait le bouton
   dans son état survolé. */
@media (hover: hover) and (pointer: fine) {
  .cta:hover {
    transition-duration: 280ms;
    transition-timing-function: ease-out;
  }
  .cta:hover .cta__fleche {
    transform: translateX(3px);
    transition: transform 280ms ease-out;
  }
  .hero .cta--cadre:hover {
    border-color: rgba(251, 248, 242, 0.8);
    background: rgba(251, 248, 242, 0.16);
  }
  .cta--trait:hover::after {
    transform: scaleX(1);
    transition: transform 280ms ease-out;
  }

  /* Le survol vide le bouton. Le fond crème s'efface et laisse remonter le
     kaki de la section, le texte passe au crème, la bordure reste. Le bouton
     ne change pas de couleur : il change d'état, de plein à évidé.

     Le fond d'arrivée s'écrit rgba(251, 248, 242, 0) plutôt que `transparent` :
     même couleur, alpha nul, la transition reste dans le crème jusqu'au bout
     au lieu de risquer un passage par le noir transparent sur un moteur qui
     n'interpolerait pas en alpha prémultiplié. */
  .fond-sombre .cta--plein:hover {
    color: var(--blanc);
    border-color: var(--blanc);
    background: rgba(251, 248, 242, 0);
    transform: translateY(-1px);
    transition: background-color 280ms ease-out, border-color 280ms ease-out,
                color 200ms ease-out, transform 280ms ease-out;
  }
  /* Le clic ramène le bouton à son niveau : l'enfoncement est le mouvement
     inverse de la levée, il n'a pas besoin d'être inventé. */
  .fond-sombre .cta--plein:active {
    transform: translateY(0);
  }
}

/* --- Focus clavier : même information que le survol ---
   Hors media query : un utilisateur au clavier doit voir l'état, qu'il ait
   un pointeur ou non. L'anneau de focus lui-même vient de la règle globale
   :focus-visible, en blanc dans le hero. */
.cta:focus-visible .cta__fleche {
  transform: translateX(3px);
  transition: transform 280ms ease-out;
}
.hero .cta--cadre:focus-visible {
  border-color: rgba(251, 248, 242, 0.8);
  background: rgba(251, 248, 242, 0.16);
}
.cta--trait:focus-visible::after {
  transform: scaleX(1);
  transition: transform 280ms ease-out;
}

/* Au clavier, le bouton plein prend le même changement de couleur, mais pas
   la levée d'un pixel : l'anneau de focus marque déjà l'élément, et déplacer
   ce que l'on vient d'atteindre à l'aveugle est désagréable. */
.fond-sombre .cta--plein:focus-visible {
  color: var(--blanc);
  border-color: var(--blanc);
  background: rgba(251, 248, 242, 0);
  transition: background-color 280ms ease-out, border-color 280ms ease-out,
              color 200ms ease-out;
}

/* --- Arrivée du bouton de commande ---

   Le bouton arrive évidé — exactement son état de survol — et se remplit. On
   voit donc le mouvement qu'il sait faire, à l'envers, avant même de le
   survoler. Rien de nouveau n'est inventé : c'est sa propre mécanique jouée
   une fois.

   Pas de fill-mode : à la fin, l'animation relâche et l'élément retrouve ses
   valeurs CSS normales — identiques à l'image finale, donc aucun saut. Un
   `forwards` figerait les valeurs animées au-dessus des règles de survol, qui
   cesseraient de fonctionner.

   La classe est posée par js/main.js (initArriveeBoutonCommande) quand le
   bouton entre dans le champ, retirée quand il en sort. */
@media (prefers-reduced-motion: no-preference) {
  .fond-sombre .cta--plein.est-en-vue {
    animation: cta-remplissage 400ms ease-out;
  }
}

@keyframes cta-remplissage {
  from {
    background-color: rgba(251, 248, 242, 0);
    color: var(--blanc);
    transform: translateY(6px);
  }
  to {
    background-color: var(--blanc);
    color: var(--kaki);
    transform: translateY(0);
  }
}

/* --------------------------------------------------------------------------
   5c. Les actions pratiques : Itinéraire et Appeler (validées dans OpenDesign)

   Quatre boutons verts pleins portaient jusqu'ici deux actions seulement,
   répétées à trois endroits. Le vert plein est la forme la plus forte de la
   page : l'employer pour « venir » et « téléphoner » mettait ces deux
   services au même niveau que la seule action qui engage vraiment, la
   commande.

   Une famille les remplace, bâtie sur la grammaire du hero : l'action
   principale porte un cadre fin et une épingle, celle qui l'accompagne n'a ni
   cadre ni fond, juste un combiné et un filet. Les deux partagent la
   typographie, la famille de pictogrammes, le rayon et la courbe de
   mouvement — on les lit comme un duo, pas comme deux objets.

   Trois contextes, trois déclinaisons, un seul langage : la section Infos
   pratiques de l'accueil, la barre du header, la barre fixe mobile.
   -------------------------------------------------------------------------- */
.action {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
  min-height: 44px;
  font-family: var(--satoshi);
  font-weight: 700;
  font-size: var(--t-ui-taille);
  line-height: 1.2;
  letter-spacing: 0;
  text-decoration: none;
  cursor: pointer;
  transition: background-color 180ms ease-in, border-color 180ms ease-in,
              color 180ms ease-in;
}

.action__icone {
  width: 1.15em;
  height: 1.15em;
  flex: none;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.6;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.action:focus-visible {
  outline: 2px solid currentColor;
  outline-offset: 3px;
}

/* --- L'action principale : un cadre fin, pas un aplat ---
   Même rayon de 12 px et mêmes proportions que « Nous trouver » dans le hero.
   Le contour à 45 % du kaki tient à 3,4:1 sur le fond clair, au-dessus du
   plancher de 3:1 exigé d'un élément graphique porteur de sens ; le libellé,
   lui, reste à 6,9:1. */
.action--cadre {
  padding: 13px 22px;
  border: 1px solid rgba(79, 90, 60, 0.45);
  border-radius: 12px;
  background: rgba(79, 90, 60, 0.04);
  color: var(--kaki);
}

@media (hover: hover) and (pointer: fine) {
  .action--cadre:hover {
    border-color: rgba(79, 90, 60, 0.8);
    background: rgba(79, 90, 60, 0.1);
    transition: background-color 280ms ease-out, border-color 280ms ease-out;
  }
}

/* --- L'action qui accompagne : ni cadre ni fond ---
   Le filet est doublé, comme sur les deux invitations éditoriales : celui du
   repos ne disparaît jamais, le second se remplit par-dessus. Le combiné
   reste le seul signe qui dit la nature de l'action. */
.action--lien {
  position: relative;
  padding: 13px 0;
  color: var(--kaki);
}

.action--lien::before,
.action--lien::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: 6px;
  height: 1px;
}

.action--lien::before {
  background: var(--brun);
  opacity: 0.45;
}

.action--lien::after {
  background: var(--kaki);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform 180ms ease-in;
}

.action--lien:focus-visible::after {
  transform: scaleX(1);
  transition: transform 280ms ease-out;
}

@media (hover: hover) and (pointer: fine) {
  .action--lien:hover::after {
    transform: scaleX(1);
    transition: transform 280ms ease-out;
  }
}

/* --- La déclinaison compacte du header ---
   Même cadre, resserré pour tenir dans la barre à côté de l'horaire du jour.
   Le contour descend à 30 % : dans un header clair et peu chargé, 45 % ferait
   un objet plus lourd que l'information d'ouverture qu'il suit. */
.action--compact {
  min-height: 38px;
  padding: 8px 14px;
  border-radius: 10px;
  border-color: rgba(79, 90, 60, 0.3);
  font-size: 0.875rem;
}

/* --- La barre fixe mobile ---
   Les deux cellules perdent leur aplat et passent au crème sur le kaki foncé
   de la barre, avec leur pictogramme. La hiérarchie du duo est conservée
   autrement : Itinéraire reçoit un voile crème à 12 %, Appeler reste nu. Les
   deux cibles gardent toute la hauteur de la barre. */
.action--barre {
  height: var(--hauteur-barre-mobile);
  border: 0;
  border-radius: 0;
  background: transparent;
  color: var(--blanc);
  font-size: 1rem;
}

.action--barre-principale {
  background: rgba(251, 248, 242, 0.12);
}

.action--barre:focus-visible {
  outline-offset: -3px;
}

@media (hover: hover) and (pointer: fine) {
  .action--barre:hover {
    background: rgba(251, 248, 242, 0.18);
    transition: background-color 280ms ease-out;
  }
  .action--barre-principale:hover {
    background: rgba(251, 248, 242, 0.24);
  }
}

/* Le mouvement de ces trois déclinaisons n'est que de la couleur : rien ne se
   déplace, rien ne change de taille. Sous prefers-reduced-motion, où le bloc
   19 coupe toutes les transitions, chaque état reste donc intégralement
   lisible — il arrive simplement d'un coup. */

/* --------------------------------------------------------------------------
   5d. Les invitations à poursuivre la visite (validées dans OpenDesign)

   « Voir tous nos produits » et « Découvrir notre histoire » avaient deux
   apparences différentes — un bouton plein, un bouton à contour — alors
   qu'ils font la même chose : proposer d'aller plus loin. Ils partagent
   maintenant un seul traitement, qui n'est plus celui d'un bouton.

   La grammaire est celle de « Nos produits » dans le hero : un libellé, une
   flèche, un filet dessous qui se remplit au survol. Le filet de repos ne
   disparaît jamais — ce n'est pas un soulignement qui apparaît, c'est le même
   trait qui se remplit.
   -------------------------------------------------------------------------- */
.suite {
  display: flex;
  margin: 2rem 0 0;
}

/* Sous les quatre produits, l'action se range à droite : elle ferme la grille
   au lieu d'ouvrir une nouvelle colonne de lecture. Sous les trois
   engagements elle reste à gauche, dans l'axe du texte qu'elle prolonge. */
.suite--droite {
  justify-content: flex-end;
}

.lien-suite {
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  /* 44 px de haut : la cible tactile est respectée sans que le lien
     ressemble pour autant à un bouton. */
  min-height: 44px;
  padding: 0.6rem 0;
  font-family: var(--satoshi);
  font-weight: 700;
  font-size: 0.9375rem;
  line-height: 1.2;
  color: var(--kaki);
  text-decoration: none;
}

/* Le filet de repos, puis celui qui se remplit par-dessus. */
.lien-suite::before,
.lien-suite::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: 1px;
}

.lien-suite::before {
  background: var(--brun);
  opacity: 0.45;
}

.lien-suite::after {
  background: var(--kaki);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform 180ms ease-in;
}

.lien-suite__fleche {
  width: 1.1em;
  height: 1.1em;
  flex: none;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.6;
  stroke-linecap: round;
  stroke-linejoin: round;
  transition: transform 180ms ease-in;
}

/* Le focus clavier reçoit exactement la même information que le survol, et
   cette règle vit hors de la media query de survol : elle fonctionne avec ou
   sans pointeur. */
.lien-suite:focus-visible {
  outline: 2px solid var(--kaki);
  outline-offset: 4px;
}

.lien-suite:focus-visible::after {
  transform: scaleX(1);
  transition: transform 280ms ease-out;
}

.lien-suite:focus-visible .lien-suite__fleche {
  transform: translateX(3px);
  transition: transform 280ms ease-out;
}

@media (hover: hover) and (pointer: fine) {
  .lien-suite:hover::after {
    transform: scaleX(1);
    transition: transform 280ms ease-out;
  }

  .lien-suite:hover .lien-suite__fleche {
    transform: translateX(3px);
    transition: transform 280ms ease-out;
  }
}

/* --------------------------------------------------------------------------
   6. Header fixe
   Fond écru à 94 % avec flou, hauteur 72 px.
   -------------------------------------------------------------------------- */
.header {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: 100;
  height: var(--hauteur-header);
  background: rgba(241, 234, 217, 0.94);
  -webkit-backdrop-filter: blur(10px);
  backdrop-filter: blur(10px);
  border-bottom: 1px solid var(--ecru-2);
}

/* Composition du header : le logo prend la place qu'il lui faut, le bloc de
   droite garde la sienne, l'espace restant est entre les deux. Le gap est un
   minimum, pas une réserve : à 320 px il se réduit, sinon il vole au logo la
   largeur dont celui-ci a besoin. */
.header__interieur {
  height: 100%;
  display: flex;
  flex-wrap: nowrap;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
}

.header__logo {
  /* 0 1 auto : le logo ne s'étire pas, et il cède avant le bloc de droite. */
  flex: 0 1 auto;
  font-family: var(--satoshi);
  font-weight: var(--t-logo-graisse);
  font-size: var(--t-logo-taille);
  letter-spacing: var(--t-logo-lettres);
  line-height: 1;
  color: var(--encre);
  text-decoration: none;
  white-space: nowrap;
}
.header__logo:hover {
  color: var(--kaki);
}

/* Menu principal : caché sur mobile, déroulé sous le header quand ouvert */
.header__nav {
  position: absolute;
  top: var(--hauteur-header);
  left: 0;
  right: 0;
  display: none;
  background: var(--ecru);
  border-bottom: 1px solid var(--ecru-2);
  padding: 0.75rem 1.25rem 1.25rem;
}
.header.est-ouvert .header__nav {
  display: block;
}

.header__menu {
  display: flex;
  flex-direction: column;
}
.header__menu a {
  display: block;
  padding: 0.85rem 0;
  font-family: var(--satoshi);
  font-size: var(--t-ui-taille);
  font-weight: var(--t-ui-graisse);
  color: var(--encre);
  text-decoration: none;
  border-bottom: 1px solid var(--ecru-2);
}
.header__menu a:hover {
  color: var(--kaki);
}
/* Page active : soulignée en kaki */
.header__menu a[aria-current="page"] {
  color: var(--kaki);
  text-decoration: underline;
  text-decoration-thickness: 1.5px;
  text-underline-offset: 6px;
}

/* Bloc de droite : horaires du jour + bouton Itinéraire + burger */
/* Le bloc de droite ne se comprime jamais : il porte la seule commande
   toujours visible du header, sa largeur est donc un dû, pas un reste. */
.header__droite {
  display: flex;
  flex: none;
  align-items: center;
  gap: 1.25rem;
}

/* Horaires masquées sur mobile. La plage horaire est en Satoshi 700 kaki :
   avant, le <strong> avait la même graisse que son voisin, l'emphase était
   donc nulle. */
.header__horaires {
  display: none;
  font-family: var(--satoshi);
  font-size: var(--t-ui-taille);
  font-weight: var(--t-ui-graisse);
  white-space: nowrap;
}
.header__horaires strong {
  font-weight: 700;
  color: var(--kaki);
}

/* L'action du header est un peu plus compacte */
.header__droite .bouton {
  padding: 11px 20px;
  font-size: 0.875rem;
}

/* --- Header mobile : trois occupants pour une largeur de deux ---

   Sous 900 px le header contenait le logo, l'action Itinéraire et le burger.
   Aucun des trois n'étant compressible, c'est le dernier — le burger — qui
   sortait de l'écran, autour de 390 px de viewport.

   La correction ne rogne rien : elle retire l'occupant en trop. Sous 900 px
   la barre fixe du bas affiche déjà Itinéraire en permanence, donc l'action du
   header était un doublon de la même action dans le même écran. Le header
   mobile garde le logo et le burger ; Itinéraire reste atteignable en
   permanence, en bas, dans une cible de 60 px de haut.

   Les deux sélecteurs sont conservés : `.action` est le balisage validé,
   `.bouton` reste un filet de sécurité si une page gardait l'ancien. */
@media (max-width: 899.98px) {
  .header__droite .bouton,
  .header__droite .action {
    display: none;
  }
}

/* Burger : trois traits, 44 px de zone tactile */
.burger {
  display: inline-flex;
  flex: none;
  flex-direction: column;
  justify-content: center;
  gap: 5px;
  width: 44px;
  height: 44px;
  padding: 0 10px;
  margin-right: -10px;
  border: 0;
  border-radius: var(--rayon);
  background: transparent;
  cursor: pointer;
}
.burger span {
  display: block;
  height: 1.5px;
  width: 100%;
  background: var(--encre);
  transition: transform var(--transition), opacity var(--transition);
}
.header.est-ouvert .burger span:nth-child(1) {
  transform: translateY(6.5px) rotate(45deg);
}
.header.est-ouvert .burger span:nth-child(2) {
  opacity: 0;
}
.header.est-ouvert .burger span:nth-child(3) {
  transform: translateY(-6.5px) rotate(-45deg);
}

/* --------------------------------------------------------------------------
   7. Barre fixe mobile (Appeler · Itinéraire), < 900 px uniquement
   -------------------------------------------------------------------------- */
.barre-mobile {
  position: fixed;
  bottom: 0;
  left: 0;
  right: 0;
  z-index: 100;
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 1px;
  background: var(--kaki-2); /* le filet entre les deux boutons */
  padding-bottom: env(safe-area-inset-bottom, 0px);
}
.barre-mobile .bouton {
  border-radius: 0;
  border: 0;
  padding: 0;
  height: var(--hauteur-barre-mobile);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 1rem;
}

/* --------------------------------------------------------------------------
   8. Footer
   -------------------------------------------------------------------------- */
.footer {
  background: var(--kaki-2);
  color: var(--blanc);
  padding-top: 2.5rem;
  /* Place pour la barre fixe mobile */
  padding-bottom: calc(2.5rem + var(--hauteur-barre-mobile) + env(safe-area-inset-bottom, 0px));
}

/* Sous 900 px le footer s'empile en colonne : le nom, la ligne italique et
   les trois liens se suivent. Alignés à gauche, ils laissaient un bord droit
   irrégulier ; les blocs se centrent dans la colonne, leur texte dans les
   blocs, et la rangée de liens se recentre à son tour (c'est une flexbox à
   part). Validé dans OpenDesign le 20/09/2026 sur la page produits, appliqué
   aux quatre pages le 21/09/2026. La rangée desktop du bloc 18 est intacte. */
.footer__interieur {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 1.5rem;
  text-align: center;
}

.footer__nom {
  font-family: var(--satoshi);
  font-weight: 700;
  font-size: 1.375rem;
  letter-spacing: -0.02em;
  line-height: 1.1;
  margin-bottom: 0;
}
.footer__sous-titre {
  margin: 0.4rem 0 0;
  font-family: var(--serif);
  font-style: italic;
  font-size: 1.0625rem;
  color: var(--ecru-2);
}

.footer__liens {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 0.5rem 1.75rem;
}
.footer__liens a {
  font-family: var(--satoshi);
  font-size: var(--t-ui-taille);
  font-weight: var(--t-ui-graisse);
  color: var(--blanc);
  text-decoration: none;
  /* Zone cliquable portée de 19 à 25 px de haut (cible tactile minimale
     24 px) ; la marge négative annule l'effet sur la mise en page, le
     footer garde la même hauteur (29/09/2026). */
  padding-block: 3px;
  margin-block: -3px;
}
.footer__liens a:hover {
  color: var(--ecru-2);
  text-decoration: underline;
}

/* --------------------------------------------------------------------------
   9. Hero (accueil) — vidéo de fond sur 100 vh, texte en bas à gauche
   -------------------------------------------------------------------------- */
.hero {
  position: relative;
  min-height: 100vh;
  min-height: 100svh;
  display: flex;
  align-items: flex-end;
  color: var(--blanc);
  overflow: hidden;
  isolation: isolate;
}

/* Fond kaki derrière la vidéo. La photo de devanture (image de secours)
   n'est posée qu'en mouvement réduit, où la vidéo est masquée (bloc 19) :
   sinon le navigateur la téléchargeait pour rien, cachée par la vidéo
   (≈ 180 Ko, décision du 29/09/2026). Avant lecture, le poster de la
   vidéo tient ce rôle. */
.hero__fond {
  position: absolute;
  inset: 0;
  z-index: -3;
  background: var(--kaki-2) center / cover no-repeat;
}

.hero__video {
  position: absolute;
  inset: 0;
  z-index: -2;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* Dégradé vertical 15 % → 72 % d'encre pour la lisibilité */
.hero__overlay {
  position: absolute;
  inset: 0;
  z-index: -1;
  background: linear-gradient(to bottom, rgba(43, 38, 32, 0.15), rgba(43, 38, 32, 0.72));
}

.hero__contenu {
  padding-top: calc(var(--hauteur-header) + 3rem);
  padding-bottom: calc(3rem + var(--hauteur-barre-mobile));
}

.hero h1 {
  margin-bottom: 0.18em;
}
/* L'italique du hero passe en écru plutôt qu'en blanc pur : il se pose
   derrière le titre au lieu de lutter avec lui. */
.hero .italique {
  margin-bottom: 1.1rem;
  color: var(--ecru-2);
}
.hero p:not(.italique) {
  max-width: 32rem;
  font-size: var(--t-intro-taille);
  line-height: var(--t-intro-interligne);
  margin-bottom: 1.75rem;
}

/* --------------------------------------------------------------------------
   10. Cartes « Nos spécialités » : 1 colonne, 2×2, puis 4 colonnes
   -------------------------------------------------------------------------- */
.cartes {
  display: grid;
  grid-template-columns: 1fr;
  gap: 2rem 1.5rem;
}

.carte__image {
  aspect-ratio: 4 / 3;
  width: 100%;
  object-fit: cover;
  border-radius: var(--rayon);
  background: var(--ecru-2);
}

/* Titre de carte en Satoshi 600 : registre étiquette, pas registre titre.
   Le descriptif reste au serif — c'est du récit, pas de la nomenclature. */
.carte h3 {
  margin: 1rem 0 0.35rem;
}
.carte p {
  font-size: 1rem;
  line-height: 1.6;
}

/* --------------------------------------------------------------------------
   11. Sections en deux colonnes (image + texte)
   Sur mobile, l'image passe toujours au-dessus.
   -------------------------------------------------------------------------- */
.duo {
  display: grid;
  grid-template-columns: 1fr;
  gap: 2rem;
  align-items: center;
}

.duo__media img,
.duo__media iframe {
  width: 100%;
  border-radius: var(--rayon);
}
.duo__media img {
  object-fit: cover;
}

/* Liste « Nos engagements » : lignes séparées par un filet brun */
.engagements {
  margin: 1.5rem 0 2rem;
  border-top: 1px solid var(--brun);
}
/* Les trois engagements sont des affirmations, pas des titres : ils passent
   en Source Serif 4 600. Ça reste du texte, mais du texte qui affirme. */
.engagements li {
  padding: 0.9rem 0;
  border-bottom: 1px solid var(--brun);
  font-family: var(--serif);
  font-weight: var(--t-affirm-graisse);
  font-size: var(--t-affirm-taille);
  line-height: 1.4;
}

/* Section Commandes spéciales (accueil) : fondu enchaîné des trois photos
   (23/09/2026, remplace « l'étal »). Un seul cadre carré ; les trois <li>
   y sont empilés et une animation sur l'opacité les fait tourner, sans
   JavaScript, au même rythme sur tous les écrans : plateau → gâteau → pains.

   Cycle de 9 s, trois créneaux de 3 s. Dans le cycle d'une photo :
   0 → 0,5 s elle apparaît en fondu par-dessus la précédente ; 0,5 → 3,5 s
   pleine ; à 3,0 s la suivante commence son fondu au-dessus d'elle, et elle
   ne s'éteint qu'à 3,5 s, quand la suivante est entièrement opaque. À aucun
   instant le cadre n'est donc vide : pas de flash du fond kaki. Le z-index
   suit (2 pendant l'entrée et la tenue, 1 dès que la suivante arrive) pour
   que l'arrivante soit toujours au-dessus, y compris pains → plateau.
   Les décalages : la première démarre à −0,5 s (déjà pleine au chargement),
   la deuxième à 2,5 s, la troisième à 5,5 s ; avant leur départ, les deux
   dernières restent à l'opacité 0 de la règle de base. */
.commandes {
  position: relative;
  width: 100%;
  max-width: 26rem;
  aspect-ratio: 1 / 1;
  margin: 0 auto;
  padding: 0;
  list-style: none;
}
.commandes li {
  position: absolute;
  inset: 0;
  opacity: 0;
  z-index: 1;
  animation: fondu-commandes 9s ease-in-out infinite;
}
.commandes li:nth-child(1) { animation-delay: -0.5s; }
.commandes li:nth-child(2) { animation-delay: 2.5s; }
.commandes li:nth-child(3) { animation-delay: 5.5s; }

@keyframes fondu-commandes {
  0%       { opacity: 0; z-index: 2; }
  5.556%   { opacity: 1; z-index: 2; }   /* 0,5 s : entrée finie */
  33.333%  { opacity: 1; z-index: 2; }   /* 3,0 s : la suivante entre */
  33.334%  { opacity: 1; z-index: 1; }
  38.888%  { opacity: 1; z-index: 1; }   /* 3,5 s : la suivante est pleine */
  38.889%  { opacity: 0; z-index: 1; }
  100%     { opacity: 0; z-index: 1; }
}

.commandes figure {
  margin: 0; /* le navigateur met 40 px de marge latérale par défaut sur <figure> */
  height: 100%;
}
/* Le cadre porte les coins arrondis, le fond et l'ombre douce */
.commandes__cadre {
  height: 100%;
  overflow: hidden;
  border-radius: var(--rayon);
  background: var(--kaki-2);
  box-shadow: 0 14px 32px rgba(43, 38, 32, 0.28);
}
.commandes img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}
/* Mouvement réduit : pas de rotation, la première photo reste affichée. */
@media (prefers-reduced-motion: reduce) {
  .commandes li {
    animation: none;
  }
  .commandes li:nth-child(1) {
    opacity: 1;
  }
}
/* Les trois carrés n'ont plus de légende depuis le 20/09/2026 : les photos
   parlent d'elles-mêmes. Chaque image garde son attribut `alt` descriptif,
   qui reste la seule chose dont un lecteur d'écran a besoin ici. */

/* Bouton « Passer une commande » centré sous les trois carrés.
   32 px au lieu de 28 : le bouton ayant gagné en hauteur et en chasse, il lui
   faut un peu plus d'air pour ne pas se coller aux trois carrés. */
.commandes-bloc .boutons--centre {
  justify-content: center;
  margin-top: 2rem;
}

/* Paragraphe volontairement plus étroit (section Fournil de l'accueil) */
.texte-court {
  max-width: 30rem;
}

/* Page produits, bandeau Commandes : ligne des trois offres, en capitales espacées */
/* Même objet que les légendes des trois carrés de l'accueil : une étiquette
   de catégorie. Elle passe donc sur le jeton étiquette, en Satoshi. */
.ligne-offre {
  margin: 1.5rem 0 0;
  font-family: var(--satoshi);
  font-size: var(--t-label-taille);
  font-weight: var(--t-label-graisse);
  letter-spacing: var(--t-label-lettres);
  text-transform: uppercase;
  line-height: 1.8;
  color: var(--ecru-2);
}

/* --------------------------------------------------------------------------
   11b. Coverflow des pâtisseries (page produits)
   Quatre portraits 4:5 empilés dans une scène en perspective. Le JS pose sur
   chaque image un attribut data-decalage (0 = au centre, -1/1 = voisines,
   -2/2 = arrière-plan, au-delà = masquée) ; le CSS ci-dessous traduit ce
   décalage en position, rotation, échelle et opacité. Pas de légende sous la
   scène depuis le 20/09/2026 : la liste des pâtisseries nomme déjà les
   produits, l'attribut alt de chaque photo reste pour les lecteurs d'écran.
   La colonne qui porte la scène est réglée dans le bloc 14b.
   -------------------------------------------------------------------------- */
.coverflow {
  margin-top: 0; /* seul visuel de la section Pâtisseries */
}

.coverflow__scene {
  position: relative;
  aspect-ratio: 4 / 3;           /* image centrale = 60 % de large, 4:5 → hauteur 75 % */
  perspective: 1100px;
  touch-action: pan-y;           /* le balayage horizontal est géré en JS, le vertical reste au navigateur */
  user-select: none;
  -webkit-user-select: none;
  border-radius: var(--rayon);
}
.coverflow__scene:focus-visible {
  outline: 2px solid var(--kaki);
  outline-offset: 6px;
}

.coverflow__item {
  position: absolute;
  top: 0;
  left: 20%;
  width: 60%;
  cursor: pointer;
  transform-style: preserve-3d;
  transition: transform 420ms ease, opacity 420ms ease;
  opacity: 0;
  pointer-events: none;
}
.coverflow__item img {
  display: block;
  width: 100%;
  aspect-ratio: 4 / 5;
  object-fit: cover;
  border-radius: var(--rayon);
  box-shadow: 0 10px 30px rgba(43, 38, 32, 0.18);
  -webkit-user-drag: none;
}

.coverflow__item[data-decalage="0"] {
  transform: translateX(0) scale(1);
  z-index: 3;
  opacity: 1;
  pointer-events: auto;
  cursor: default;
}
.coverflow__item[data-decalage="-1"],
.coverflow__item[data-decalage="1"] {
  z-index: 2;
  opacity: 0.85;
  pointer-events: auto;
}
.coverflow__item[data-decalage="-1"] { transform: translateX(-55%) rotateY(40deg) scale(0.75); }
.coverflow__item[data-decalage="1"]  { transform: translateX(55%) rotateY(-40deg) scale(0.75); }

.coverflow__item[data-decalage="-2"],
.coverflow__item[data-decalage="2"] {
  z-index: 1;
  opacity: 0.55;
  pointer-events: auto;
}
.coverflow__item[data-decalage="-2"] { transform: translateX(-64%) rotateY(50deg) scale(0.6); }
.coverflow__item[data-decalage="2"]  { transform: translateX(64%) rotateY(-50deg) scale(0.6); }

/* --------------------------------------------------------------------------
   12. Témoignages (accueil, validés dans OpenDesign le 21/09/2026)
   Entre « Commandes spéciales » et « Infos pratiques ». Fond écru clair :
   une respiration après l'aplat kaki. Ordinateur : rail en défilement
   continu, lent, en pause au survol et au focus. Mobile et mouvement
   réduit : rangée défilable au doigt, arrêt net sur chaque carte, sans
   animation. Tout est dans la feuille de style : aucun JavaScript.
   Les avis sont des textes de démonstration (voir le commentaire dans
   index.html) : à remplacer par de vrais avis avant toute mise en ligne.
   -------------------------------------------------------------------------- */

.temoignages {
  --temoignages-fond: var(--ecru-clair);   /* même blanc cassé chaud que « Nous contacter » d'Infos pratiques */
  --beurre: #B98320;             /* étoiles : 3,2:1 sur blanc, lisibles sans crier */
  /* Une série (3 cartes + 3 écarts = 73,5 rem ≈ 1176 px) est plus large que
     la fenêtre (1100 px au maximum) : un même avis n'apparaît jamais deux
     fois en entier à l'écran. */
  --carte-largeur: 23rem;
  --carte-ecart: 1.5rem;
  --defilement-duree: 70s;       /* ≈ 18 px/s : on lit une carte sans la poursuivre */
  background: var(--temoignages-fond);
}

.temoignages__accroche {
  margin: 0 0 0.75rem;
  font-family: var(--satoshi);
  font-size: var(--t-label-taille);
  font-weight: var(--t-label-graisse);
  letter-spacing: var(--t-label-lettres);
  text-transform: uppercase;
  color: var(--brun);
}

.temoignages h2 {
  margin: 0 0 2.5rem;
}

/* Fenêtre : c'est elle qui coupe le rail et reçoit le focus clavier.
   `contain: layout` (ajouté le 21/09/2026, absent de l'archive 35) : sans
   lui, Chrome sur téléphone élargit la fenêtre d'affichage à la largeur de
   la rangée de cartes (690 px sur un écran de 390), header et barre fixe
   débordant de l'écran. Aucun effet sur le rendu ni sur le défilement. */
.temoignages__fenetre {
  overflow: hidden;
  border-radius: var(--rayon);
  contain: layout;
}
.temoignages__fenetre:focus-visible {
  outline: 2px solid var(--kaki);
  outline-offset: 4px;
}

/* Le rail aligne les deux séries côte à côte ; il glisse de la largeur
   exacte d'une série (-50 %), puis repart : la jonction est invisible. */
.temoignages__rail {
  display: flex;
  width: max-content;
  animation: temoignages-defile var(--defilement-duree) linear infinite;
}
.temoignages__fenetre:hover .temoignages__rail,
.temoignages__fenetre:focus-within .temoignages__rail {
  animation-play-state: paused;
}

@keyframes temoignages-defile {
  from { transform: translateX(0); }
  to   { transform: translateX(-50%); }
}

.temoignages__serie {
  display: flex;
  gap: var(--carte-ecart);
  margin: 0;
  padding: 0 var(--carte-ecart) 0 0;   /* l'écart de fin = l'écart entre cartes */
  list-style: none;
}

/* Carte : blanche, sobre, rayon léger, aucune ombre. */
.temoignage {
  display: flex;
  flex-direction: column;
  flex: none;
  width: var(--carte-largeur);
  padding: 1.75rem 1.75rem 1.5rem;
  background: #FFFFFF;
  border: 1px solid rgba(79, 90, 60, 0.22);   /* le filet des listes de Produits et La maison */
  border-radius: 8px;
}

.temoignage__note {
  margin: 0 0 1rem;
  line-height: 1;
}
.temoignage__etoiles {
  display: block;
  font-size: 0.9375rem;
  letter-spacing: 0.2em;
  color: var(--beurre);
}

.temoignage__texte {
  flex: 1 1 auto;
  margin: 0 0 1.25rem;
}
.temoignage__texte p {
  margin: 0;
  font-family: var(--serif);
  font-style: italic;
  font-size: var(--t-corps-taille);
  line-height: var(--t-corps-interligne);
  color: var(--encre);
}

.temoignage__auteur {
  margin: 0;
  font-family: var(--satoshi);
  font-size: var(--t-ui-taille);
  font-weight: 700;
  color: var(--kaki);
}

/* Texte réservé aux lecteurs d'écran (la note des étoiles). */
.visuellement-cache {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}

/* Mobile et tablette étroite : aucun défilement automatique.
   La rangée se fait défiler au doigt et s'arrête net sur chaque carte.
   La copie technique disparaît : on ne voit que les trois avis. */
@media (max-width: 899.98px) {
  .temoignages {
    --carte-largeur: min(19rem, 82vw);
    --carte-ecart: 1rem;
  }
  .temoignages__fenetre {
    overflow-x: auto;
    scroll-snap-type: x mandatory;
    scroll-padding-inline: 0;
    overscroll-behavior-x: contain;
    scrollbar-width: none;
    padding-bottom: 0.25rem;
  }
  .temoignages__fenetre::-webkit-scrollbar { display: none; }
  .temoignages__rail {
    animation: none;
  }
  .temoignages__serie--copie {
    display: none;
  }
  .temoignage {
    scroll-snap-align: start;
    scroll-snap-stop: always;
  }
  /* ESSAI (21/09/2026, sur demande d'Estelle) : sans cadre blanc sur mobile.
     Les avis se posent directement sur l'écru clair, alignés à gauche sur le
     titre ; l'écart entre deux avis grandit pour que deux textes voisins ne
     se touchent pas. Le rendu ordinateur (cartes blanches) ne change pas. */
  .temoignages {
    --carte-ecart: 2rem;
  }
  .temoignage {
    padding: 0.25rem 0 0.5rem;
    background: transparent;
    border: 0;
    border-radius: 0;
  }
}

/* Mouvement réduit, à toutes les largeurs : même comportement que mobile.
   Le bloc 19 coupe déjà l'animation ; restent la copie à masquer et la
   rangée à rendre défilable. */
@media (prefers-reduced-motion: reduce) {
  .temoignages__rail {
    animation: none;
  }
  .temoignages__serie--copie {
    display: none;
  }
  .temoignages__fenetre {
    overflow-x: auto;
    scroll-snap-type: x mandatory;
  }
  .temoignage {
    scroll-snap-align: start;
  }
}

/* --------------------------------------------------------------------------
   13. Infos pratiques : coordonnées, horaires, carte
   -------------------------------------------------------------------------- */
.infos {
  display: grid;
  grid-template-columns: 1fr;
  gap: 2.5rem;
}

/* Adresse et horaires au serif : ce sont des informations qu'on lit, pas des
   commandes qu'on actionne. */
.adresse {
  font-style: normal;
  font-size: var(--t-corps-taille);
  line-height: 1.75;
}
.adresse a {
  color: var(--encre);
  font-weight: 600;
}
.adresse a:hover {
  color: var(--kaki);
}

.horaires {
  width: 100%;
  border-collapse: collapse;
  font-size: var(--t-corps-taille);
}
.horaires th,
.horaires td {
  padding: 0.7rem 0;
  border-bottom: 1px solid var(--ecru-2);
  text-align: left;
  vertical-align: top;
}
.horaires th {
  font-weight: 600;
  padding-right: 1rem;
}
.horaires td {
  color: var(--brun);
  white-space: nowrap;
}

.carte-maps {
  width: 100%;
  aspect-ratio: 4 / 3;
  border: 0;
  border-radius: var(--rayon);
  background: var(--ecru-2);
}
/* --------------------------------------------------------------------------
   14b. Page produits (direction OpenDesign validée le 20/09/2026)

   Cinq familles, cinq mises en page différentes. La photo cesse d'illustrer à
   côté du texte, elle occupe une place que le texte doit contourner. Aucune
   section n'est construite comme sa voisine, mais toutes partagent la même
   grammaire : mêmes marges, même échelle typographique, mêmes filets.

   Les règles qui toucheraient une autre page (bandeau, en-tête de page,
   débord de main) sont préfixées par la classe de body « page-produits ».
   Les autres (ancres, listes de produits, compositions) n'existent que sur
   cette page et restent sans préfixe.
   -------------------------------------------------------------------------- */

/* `overflow-x: clip` autorise les débords pleine largeur ci-dessous sans
   créer de barre de défilement horizontale — contrairement à
   `overflow: hidden`, il ne fabrique pas de conteneur de défilement. */
.page-produits main {
  overflow-x: clip;
}

/* Sortie du conteneur jusqu'aux bords de l'écran. */
.pleine-largeur {
  width: 100vw;
  margin-left: calc(50% - 50vw);
}

/* Les ancres du haut de page mènent ici. */
.famille {
  scroll-margin-top: calc(var(--hauteur-header) + 1rem);
}

/* --- Bandeau d'en-tête (Produits et La maison) ----------------------------
   La photo occupe toute la largeur et le titre se pose dessus, en bas à
   gauche : le coin bas gauche est le point de repos du regard après le
   header, et il laisse la partie haute de la photo intacte. Le voile est un
   dégradé qui ne travaille que sous le titre : la photo reste franche aux
   trois quarts. Même réglage sur les deux pages à bandeau, posé sur la base
   du bloc 15. */
.page-produits .bandeau,
.page-la-maison .bandeau {
  display: block;
  height: clamp(16rem, 42vw, 29rem);
  min-height: 0;
}

.page-produits .bandeau::after,
.page-la-maison .bandeau::after {
  background: linear-gradient(to top, rgba(43, 38, 32, 0.68) 0%, rgba(43, 38, 32, 0.25) 42%, rgba(43, 38, 32, 0) 70%);
}

.page-produits .bandeau .conteneur,
.page-la-maison .bandeau .conteneur {
  position: relative;
  display: flex;
  height: 100%;
  align-items: flex-end;
  padding-top: 0;
  padding-bottom: 2rem;
}

/* Le jeton `--t-h1-taille` est calibré pour le hero de l'accueil, où le titre
   occupe un écran entier. Sur un bandeau de 29 rem il écraserait la photo :
   l'échelle est ramenée à une taille de titre de page. C'est le seul écart
   typographique de ces deux pages. */
.page-produits .bandeau h1,
.page-la-maison .bandeau h1 {
  margin: 0;
  font-size: clamp(2.25rem, 5.5vw, 3.75rem);
  color: var(--blanc);
}

/* --- Introduction et ancres ----------------------------------------------
   L'en-tête reprend les marges d'une section ordinaire ; c'est la seule
   page qui utilise encore `.page-entete` depuis le 21/09/2026 (Infos
   pratiques a son titre dans « Nous contacter », bloc 16). Les cinq ancres
   ne sont pas des boutons : ce
   sont des repères de lecture. Elles reprennent le filet doublé du système —
   celui du repos ne disparaît jamais, le second se remplit au survol. */
.page-produits .page-entete {
  padding-top: 3.5rem;
  padding-bottom: 3.5rem;
}
@media (min-width: 900px) {
  .page-produits .page-entete {
    padding-top: 5.5rem;
    padding-bottom: 5.5rem;
  }
}

.page-produits .page-entete .texte-lecture {
  margin-top: 0;
  font-size: var(--t-intro-taille);
}

.ancres {
  display: flex;
  flex-wrap: wrap;
  gap: 0.25rem 1.75rem;
  margin-top: 1.75rem;
}

.ancres a {
  position: relative;
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  padding: 0.5rem 0;
  font-family: var(--satoshi);
  font-weight: 700;
  font-size: 0.8125rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--kaki);
  text-decoration: none;
}

.ancres a::before,
.ancres a::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0.35rem;
  height: 1px;
}

.ancres a::before {
  background: var(--brun);
  opacity: 0.4;
}

.ancres a::after {
  background: var(--kaki);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform 180ms ease-in;
}

.ancres a:focus-visible {
  outline: 2px solid var(--kaki);
  outline-offset: 4px;
}

.ancres a:focus-visible::after {
  transform: scaleX(1);
  transition: transform 280ms ease-out;
}

@media (hover: hover) and (pointer: fine) {
  .ancres a:hover::after {
    transform: scaleX(1);
    transition: transform 280ms ease-out;
  }
}

/* --- Les listes de produits ----------------------------------------------
   Le point qui ne doit jamais céder : les photos gagnent en place, les listes
   gardent leur lisibilité. Chaque produit est une ligne de tableau — un nom
   en Satoshi, une précision en serif dessous, un filet entre deux. Jamais de
   carte autour de chaque produit. */
.produits {
  margin: 1.75rem 0 0;
  padding: 0;
  list-style: none;
  border-top: 1px solid var(--brun);
}

.produits li {
  display: grid;
  gap: 0.1rem;
  padding: 0.8rem 0;
  border-bottom: 1px solid var(--brun);
}

.produits strong {
  font-family: var(--satoshi);
  font-weight: 700;
  font-size: 1.0625rem;
  letter-spacing: -0.01em;
  line-height: 1.3;
}

.produits span {
  font-family: var(--serif);
  font-size: 1rem;
  line-height: 1.45;
  color: var(--brun);
}

/* Deux colonnes quand la liste est courte et la mise en page large. */
@media (min-width: 720px) {
  .produits--deux {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    column-gap: 3rem;
    border-top: 0;
  }
}

/* Sur le bloc kaki du snacking, les filets et la précision changent de
   couleur : le brun disparaîtrait sur le vert. */
.produits--clair {
  border-top-color: rgba(251, 248, 242, 0.3);
}
.produits--clair li {
  border-bottom-color: rgba(251, 248, 242, 0.3);
}
.produits--clair span {
  color: var(--ecru-2);
}

/* --- PAINS : le plein cadre ----------------------------------------------
   La photo touche le bord gauche de l'écran : c'est elle qui ouvre la page.
   Le texte occupe la colonne de droite et s'aligne sur la marge du conteneur,
   pas sur celle de la photo. Le calcul du padding droit aligne la colonne de
   texte sur le bord du conteneur quand l'écran est large, et retombe sur la
   gouttière de 20 px quand il ne l'est plus. */
.famille--pains .grille {
  display: grid;
  gap: 2rem;
}

.pains__photo {
  margin: 0;
}

.pains__photo img {
  display: block;
  width: 100%;
  height: auto;
}

/* Sous 900 px la grille s'empile et la photo reste pleine largeur. Le bloc
   de texte n'est pas dans un `.conteneur` et n'hérite d'aucune gouttière :
   1,25 rem de chaque côté, soit exactement le padding de `.conteneur`, pour
   que le titre, le paragraphe et les filets de la liste s'alignent sur le
   logo du header. */
@media (max-width: 899.98px) {
  .famille--pains .pains__texte {
    padding-left: 1.25rem;
    padding-right: 1.25rem;
  }
}

@media (min-width: 900px) {
  .famille--pains .grille {
    /* 1,4 : la photo prend nettement le dessus sur la colonne de texte, qui
       garde sa largeur de lecture grâce au max-width ci-dessous. */
    grid-template-columns: minmax(0, 1.4fr) minmax(0, 1fr);
    gap: clamp(2rem, 5vw, 4rem);
    align-items: center;
    padding-right: max(1.25rem, calc(50vw - var(--largeur-contenu) / 2 + 1.25rem));
  }
  .pains__texte {
    max-width: 32rem;
  }
}

/* --- VIENNOISERIES : la bande --------------------------------------------
   La photo est au-dessus, sur toute la largeur, et le texte se déploie
   dessous en deux colonnes. Le format 2,4:1 est un recadrage de bandeau
   assumé : la photo d'origine est en 3:2, on n'en garde que la bande
   centrale. */
.bande__photo {
  margin: 0 0 2.5rem;
  aspect-ratio: 2.4 / 1;
  background: var(--ecru-2);
}

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

@media (max-width: 719.98px) {
  /* Sous 720 px, 2,4:1 réduirait la photo à un filet : on revient à un
     cadrage large mais respirable. */
  .bande__photo {
    aspect-ratio: 16 / 10;
  }
}

.bande__texte {
  max-width: 34rem;
}

/* --- PÂTISSERIES : le coverflow ------------------------------------------
   Le composant du bloc 11b, repris dans sa mécanique et ses proportions. Ce
   qui grandit ici, c'est la scène entière, par la colonne qui la porte : les
   proportions internes ne bougent pas. */
.famille--patisseries .grille {
  display: grid;
  gap: 2.5rem;
}

@media (min-width: 900px) {
  .famille--patisseries .grille {
    grid-template-columns: minmax(0, 1.6fr) minmax(0, 1fr);
    gap: clamp(2rem, 4vw, 3.5rem);
    align-items: center;
  }
}

/* --- SNACKING : le chevauchement -----------------------------------------
   La seule section où deux blocs se superposent réellement. Le texte vit
   dans un aplat kaki, la photo le mord par la droite et remonte au-dessus.

   L'aplat kaki est porté par deux éléments plutôt qu'un seul : l'introduction
   occupe la première rangée de la grille, la liste et la photo la seconde.
   Le haut de la photo est donc le haut de cette rangée, quelle que soit la
   longueur du paragraphe. Les deux éléments sont adjacents et de même
   couleur : ils se lisent comme un bloc unique.

   Le seuil est à 760 px et non 900 : à 760 px la rangée tient encore. En
   dessous, deux blocs qui se recouvrent deviennent illisibles — la photo
   passe alors au-dessus du bloc, sans recouvrement. */
.famille--snacking .grille {
  display: grid;
  gap: 0;
}

.snack__intro,
.snack__corps {
  background: var(--kaki);
  color: var(--blanc);
}

.snack__intro {
  padding: 2rem 1.5rem 0;
}

.snack__corps {
  padding: 0 1.5rem 2rem;
}

.snack__intro h2 {
  margin-top: 0;
}

/* Les filets s'arrêtent au bout du plus long libellé au lieu de courir
   jusqu'au bord de l'aplat : plus aucun trait ne passe derrière la photo.
   `fit-content` mesure le contenu, le plafond à 100 % le protège sur petit
   écran. */
.famille--snacking .produits {
  width: fit-content;
  max-width: 100%;
}

.snack__photo {
  margin: 0;
}

.snack__photo img {
  display: block;
  width: 100%;
  height: auto;
  border-radius: var(--rayon);
}

@media (max-width: 759.98px) {
  /* Ordre inversé sur petit écran : la photo ouvre, le bloc suit, avec un
     léger recouvrement vertical. */
  .snack__photo {
    order: -1;
  }
  .snack__intro {
    margin-top: -1.5rem;
    position: relative;
    z-index: 1;
  }
}

@media (min-width: 760px) {
  .famille--snacking .grille {
    /* Deux rangées : l'introduction en haut de la colonne de gauche, la
       liste et la photo en dessous. Pas d'`align-items` : l'étirement par
       défaut laisse l'aplat kaki descendre jusqu'au bas de la photo. */
    grid-template-columns: minmax(0, 1.85fr) minmax(0, 1fr);
  }
  /* `position: relative` sur les trois : positionner explicitement supprime
     toute ambiguïté d'empilement, la photo est devant l'aplat vert. */
  .snack__intro {
    grid-column: 1;
    grid-row: 1;
    padding: 3rem 2.5rem 0;
    position: relative;
    z-index: 1;
  }
  .snack__corps {
    grid-column: 1;
    grid-row: 2;
    padding: 0 2.5rem 3rem;
    position: relative;
    z-index: 1;
  }
  .snack__photo {
    /* Le chevauchement vient de la marge négative gauche : le bord droit
       reste aligné sur la marge du conteneur et la photo gagne cette largeur.
       Sur un conteneur de 1180 px, la morsure dans l'aplat atteint ~252 px.
       La marge haute descend la photo sous la première ligne de la rangée ;
       la rangée s'agrandit d'autant et l'aplat vert la suit. */
    grid-column: 2;
    grid-row: 2;
    margin-left: -15.75rem;
    margin-top: 2.25rem;
    position: relative;
    z-index: 2;
    /* Légère inclinaison (21/09/2026) : la composition est volontairement
       moins rigide, son équilibre ne dépend plus d'un alignement exact avec
       les mots du paragraphe. Sens antihoraire : le coin haut gauche descend
       et s'éloigne du texte, le coin qui passe sous le bas de l'aplat est
       celui de droite, déjà hors du vert. Sur 638 px de large, chaque coin
       bouge d'environ 11 px. Pas d'inclinaison sous 760 px. */
    transform: rotate(-2deg);
  }
}

/* --- COMMANDES SPÉCIALES : le repos --------------------------------------
   La seule section sans photographie, et c'est volontaire : après quatre
   compositions denses, la page a besoin d'un palier. */
.famille--commandes .boutons {
  margin-top: 2rem;
}

/* Le bouton « Passer une commande » : même famille que celui de l'accueil
   (même base `.cta`, même Satoshi 700 à 15 px, mêmes 15 px de padding
   vertical et 32 px horizontal, même rayon de 8 px, mêmes durées). Le
   traitement de couleur est inversé : sur l'accueil il arrive plein et se
   vide au survol, ici il arrive évidé et se remplit. Il ferme une page où
   quatre photographies ont déjà pris toute l'attention : un aplat crème de
   plus y ferait un sixième point fort. Contraste crème sur kaki : 6,9:1 au
   repos comme au survol. */
.cta--contour-clair {
  justify-content: center;
  padding: 15px 32px;
  border: 1px solid var(--blanc);
  border-radius: 8px;
  background: rgba(251, 248, 242, 0);
  color: var(--blanc);
}

.cta--contour-clair:focus-visible {
  outline: 2px solid var(--blanc);
  outline-offset: 3px;
  background: var(--blanc);
  color: var(--kaki);
  transition: background-color 280ms ease-out, color 200ms ease-out;
}

@media (hover: hover) and (pointer: fine) {
  .cta--contour-clair:hover {
    background: var(--blanc);
    color: var(--kaki);
    /* Le texte vire avant que le fond n'ait fini d'arriver : sans ce
       décalage, l'inversion passe par un milieu où le contraste plonge. */
    transition: background-color 280ms ease-out, color 200ms ease-out,
                transform 280ms ease-out;
    transform: translateY(-1px);
  }
  .cta--contour-clair:active {
    transform: translateY(0);
  }
}

@media (prefers-reduced-motion: reduce) {
  .cta--contour-clair:hover,
  .cta--contour-clair:focus-visible {
    transform: none;
  }
}

/* --------------------------------------------------------------------------
   15. Page La maison (direction OpenDesign validée le 21/09/2026)

   La page d'origine, section par section, habillée avec la direction
   validée : bandeau, introduction en registre voix, deux duos texte / photo,
   la photo d'équipe inclinée, la journée horodatée, les trois engagements
   avec leur étoile, et la phrase de fin qui se révèle.

   Les règles qui toucheraient une autre page (bandeau de base, `.duo` de
   l'accueil, marges des sections) sont préfixées par la classe de body
   « page-la-maison ». Les autres n'existent que sur cette page.
   -------------------------------------------------------------------------- */

/* --- Bandeau de base ------------------------------------------------------
   Photo absolue derrière, voile en pseudo-élément, texte par-dessus. Les
   deux pages à bandeau (Produits, La maison) posent leur réglage commun dans
   le bloc 14b. */
.bandeau {
  position: relative;
  display: flex;
  align-items: flex-end;
  min-height: 55vh;
  min-height: 55svh;
  color: var(--blanc);
  overflow: hidden;
  isolation: isolate;
}
.bandeau img {
  position: absolute;
  inset: 0;
  z-index: -2;
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.bandeau::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background: linear-gradient(to bottom, rgba(43, 38, 32, 0.15), rgba(43, 38, 32, 0.72));
}
.bandeau .conteneur {
  padding-top: 3rem;
  padding-bottom: 3rem;
}
.bandeau h1 {
  margin-bottom: 0;
}

/* --- Introduction ----------------------------------------------------------
   La phrase d'ouverture est en registre voix (Source Serif 4 italique),
   comme sur la page d'origine où elle était déjà en italique. */
.maison-intro .italique {
  margin: 0;
  max-width: var(--largeur-lecture);
}

/* --- Duos texte / photo ----------------------------------------------------
   La grille `.duo` est celle du bloc 11. Les photos gardent leur format
   entier : aucune hauteur n'est imposée, la largeur suit la colonne. Notre
   histoire : photo à droite (`.duo--texte-gauche`). Notre journée : texte
   d'abord dans le balisage, donc à gauche sur ordinateur et avant la photo
   sur mobile. */
.page-la-maison .duo__media img {
  display: block;
  height: auto;
}

.page-la-maison .duo h2 {
  margin-top: 0;
}

/* --- Une équipe à taille humaine -------------------------------------------
   Photo à gauche, texte à droite sur grand écran, empilés sur mobile avec la
   photo d'abord. La photo garde son format paysage entier (3:2, aucun
   recadrage) mais reste compacte : jamais plus de 34 rem de large.

   L'inclinaison de 2° est une rotation statique, pas une animation : elle
   n'a donc rien à couper sous prefers-reduced-motion. Une boîte tournée de
   2° déborde de sa place d'environ 1,75 % de sa hauteur de chaque côté,
   4 px à 375 px de large. La photo est donc posée dans une largeur réduite
   de 1 rem (8 px de marge par côté), ce qui absorbe le débordement sans
   `overflow: hidden`. */
.equipe {
  display: grid;
  grid-template-columns: 1fr;
  gap: 2.5rem;
  align-items: center;
}

.equipe__texte h2 {
  margin-top: 0;
}
.equipe__texte p {
  max-width: var(--largeur-lecture);
  margin-bottom: 0;
}

.equipe__photo {
  margin: 0 auto;
  width: calc(100% - 1rem);
  max-width: 34rem;
  transform: rotate(2deg);
}

.equipe__photo img {
  display: block;
  width: 100%;
  height: auto;
  border-radius: var(--rayon);
  box-shadow: 0 10px 24px rgba(43, 38, 32, 0.14);
}

@media (min-width: 900px) {
  .equipe {
    /* Photo à gauche (1,1 part), texte à droite (1 part). */
    grid-template-columns: minmax(0, 1.1fr) minmax(0, 1fr);
    gap: 4rem;
  }
}

/* --- Notre journée ---------------------------------------------------------
   Quatre lignes horodatées. L'heure est en Satoshi, dans une colonne fixe,
   la phrase en serif à côté ; un filet sépare les lignes, comme les listes
   de « Nos produits ». */
.journee {
  list-style: none;
  margin: 0;
  padding: 0;
}

.journee li {
  display: grid;
  grid-template-columns: 3.5rem minmax(0, 1fr);
  gap: 1rem;
  align-items: baseline;
  padding: 1rem 0;
  border-top: 1px solid rgba(79, 90, 60, 0.22);
}
.journee li:last-child {
  border-bottom: 1px solid rgba(79, 90, 60, 0.22);
}

.journee strong {
  display: block;
  font-family: var(--satoshi);
  font-weight: 700;
  font-size: 1.25rem;
  letter-spacing: -0.015em;
  color: var(--kaki);
  white-space: nowrap;
}

.journee span {
  display: block;
}

/* --- Nos engagements -------------------------------------------------------
   Trois blocs côte à côte sur grand écran, empilés sur mobile. Les titres
   sont des affirmations : même registre que les engagements de l'accueil.
   Chaque bloc s'ouvre sur une étoile à quatre branches en kaki, suivie d'un
   filet fin qui court jusqu'au bord de la colonne. Purement décoratif : le
   span porte `aria-hidden`, les lecteurs d'écran ne le lisent pas. */
.trois-blocs {
  display: grid;
  grid-template-columns: 1fr;
  gap: 2rem;
  margin-top: 2rem;
}

.trois-blocs h3 {
  margin: 0 0 0.5rem;
  font-family: var(--serif);
  font-size: var(--t-affirm-taille);
  font-weight: var(--t-affirm-graisse);
  letter-spacing: 0;
  line-height: 1.35;
}

.trois-blocs p {
  margin: 0;
}

.engagement__ornement {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  margin-bottom: 0.75rem;
  font-size: 0.875rem;
  line-height: 1;
  color: var(--kaki);
}
.engagement__ornement::after {
  content: "";
  flex: 1 1 auto;
  height: 1px;
  background: rgba(79, 90, 60, 0.25);
}

/* --- Fin de page -----------------------------------------------------------
   La phrase de fin reste en registre voix, un cran plus grande que
   l'introduction. « Nous trouver » prend la forme de l'action pratique
   « Itinéraire » (cadre fin, épingle, bloc 5c) : le bouton vert plein a été
   retiré des actions pratiques sur l'accueil. */
.phrase-fin {
  position: relative;
  margin: 0 auto 1.75rem;
  max-width: 32rem;
  font-family: var(--serif);
  font-style: italic;
  font-weight: 400;
  font-size: clamp(1.5rem, 3vw, 2.125rem);
  line-height: 1.3;
  text-wrap: balance;
}

/* --- La révélation de la phrase de fin -------------------------------------
   Trois états, posés par initRevelationPhraseFin dans js/main.js :
   · sans classe : phrase et trait visibles d'emblée (pas de JavaScript,
     mouvement réduit, ou observateur muet) ;
   · `est-armee` : phrase masquée par un volet, trait replié, sans
     transition — c'est l'état de repos tant que la section est hors écran ;
   · `est-armee est-revelee` : le volet s'ouvre de gauche à droite en 1,5 s,
     puis le trait se dessine en 600 ms.

   La révélation passe par `clip-path`, pas par un découpage lettre à
   lettre : c'est un volet qui s'ouvre, pas une machine à écrire. Les marges
   négatives de l'inset laissent respirer l'italique, dont les jambages
   débordent légèrement de la boîte, et descendent assez bas pour inclure le
   trait. La transition n'existe que sur l'état révélé : retirer la classe
   referme le volet d'un coup, hors écran, prêt à rejouer au retour.

   Le trait est posé en absolu dans la marge basse de la phrase : il
   n'ajoute aucune hauteur, l'espacement jusqu'au bouton « Nous trouver »
   reste celui d'avant. */
.phrase-fin::after {
  content: "";
  position: absolute;
  left: calc(50% - 1.75rem);
  bottom: -0.875rem;
  width: 3.5rem;
  height: 1px;
  background: var(--kaki);
  transform-origin: left center;
}

.phrase-fin.est-armee {
  clip-path: inset(-0.25em 100% -1.25rem -0.25em);
}
.phrase-fin.est-armee::after {
  transform: scaleX(0);
}

.phrase-fin.est-armee.est-revelee {
  clip-path: inset(-0.25em -0.25em -1.25rem -0.25em);
  transition: clip-path 1500ms cubic-bezier(0.25, 0.1, 0.25, 1);
}
.phrase-fin.est-armee.est-revelee::after {
  transform: scaleX(1);
  /* Le trait attend la fin de la phrase, puis se dessine en 600 ms. */
  transition: transform 600ms ease-out 1500ms;
}

@media (prefers-reduced-motion: reduce) {
  .phrase-fin.est-armee {
    clip-path: none;
  }
  .phrase-fin.est-armee::after {
    transform: none;
  }
}

/* --- Grands écrans ---------------------------------------------------------
   Les sections de cette page respirent à 5 rem, un cran sous les 5,5 rem du
   bloc 18 : c'est la valeur validée dans OpenDesign. */
@media (min-width: 900px) {
  .page-la-maison .section {
    padding-top: 5rem;
    padding-bottom: 5rem;
  }

  .trois-blocs {
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 3rem;
  }
}

/* --------------------------------------------------------------------------
   16. Page Infos pratiques (direction OpenDesign validée le 21/09/2026)

   Quatre sections : « Nous contacter » (titre de page, coordonnées à gauche,
   formulaire à droite), les horaires avec « Appeler », « Venir à la
   boutique » (texte, photo, « Itinéraire », carte) et les questions
   fréquentes. Fonds alternés, filets fins, accents kaki, aucune carte
   encadrée. Le formulaire est un formulaire HTML natif relié à Netlify
   Forms ; son comportement (date conditionnelle, validation, animation
   d'envoi) est dans initFormulaireContact, js/main.js.

   Les règles qui toucheraient une autre page (rythme des sections) sont
   préfixées par la classe de body « page-infos-pratiques ». Les autres
   n'existent que sur cette page.
   -------------------------------------------------------------------------- */

/* Filet commun à la page : le même que les listes de « Nos produits » et de
   « La maison ». */
.page-infos-pratiques {
  --filet: 1px solid rgba(79, 90, 60, 0.22);
}

/* Rythme vertical propre à cette page : 4,5 rem sur mobile, 6,5 rem sur
   ordinateur, un cran au-dessus des autres pages (validé le 21/09/2026). */
.page-infos-pratiques .section {
  padding-top: 4.5rem;
  padding-bottom: 4.5rem;
}

/* --- Nous contacter --------------------------------------------------------
   Bloc resserré (55 rem) et centré : texte et coordonnées à gauche, champs à
   droite sur ordinateur ; empilés sur mobile. Fond écru clair, plus doux que
   l'écru de la palette sur ce bloc. */
.section.infos-accueil {
  background: var(--ecru-clair);
}

/* Titre de page visible, à taille de titre de section élargie : pas de grand
   hero. Aligné sur le bloc contact. */
.infos-accueil__titre {
  max-width: 55rem;
  margin: 0 auto 4rem;
  font-size: clamp(2rem, 4vw, 2.75rem);
  line-height: 1.1;
}

.contact {
  max-width: 55rem;
  margin: 0 auto;
  display: grid;
  gap: 2rem;
}

.contact__intro h2 {
  margin-top: 0;
}
.contact__intro p {
  margin: 0;
  max-width: var(--largeur-lecture);
}

/* Coordonnées sous le texte d'introduction, dans la colonne de gauche. */
.contact__adresse {
  display: grid;
  gap: 0.125rem;
  margin: 1.75rem 0 0;
  padding-top: 1.25rem;
  border-top: var(--filet);
  line-height: 1.5;
}
.contact__nom {
  font-family: var(--satoshi);
  font-weight: 700;
  color: var(--encre);
}

/* --- Formulaire HTML ------------------------------------------------------
   Posé directement sur le fond de la section, sans encadré. Libellés en
   Satoshi (registre interface), saisie en Source Serif 4 (registre texte).
   Champs : filet kaki fin, rayon 8 px comme « Passer une commande ». */
.formulaire-contact {
  --champ-filet: rgba(79, 90, 60, 0.35);
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 1.25rem;
}

.champ {
  display: grid;
  gap: 0.375rem;
  min-width: 0;
}
/* `.champ` est une grille : l'attribut hidden doit reprendre la main. */
.champ[hidden] {
  display: none;
}

.champ__libelle {
  font-family: var(--satoshi);
  font-weight: var(--t-ui-graisse);
  font-size: 0.9375rem;
  line-height: 1.3;
  color: var(--encre);
}

/* Astérisque des champs obligatoires. Masqué aux lecteurs d'écran :
   l'attribut `required` des champs annonce déjà l'obligation. */
.champ__obligatoire {
  margin-left: 0.125rem;
  font-weight: 700;
  color: var(--kaki);
}

.champ__aide {
  margin: -0.125rem 0 0.125rem;
  font-size: 0.875rem;
  font-style: italic;
  color: var(--brun);
}

.champ__saisie {
  display: block;
  width: 100%;
  min-height: 3rem;
  padding: 0.75rem 0.875rem;
  font-family: var(--serif);
  font-size: 1.0625rem;
  line-height: 1.4;
  color: var(--encre);
  background: var(--blanc);
  border: 1px solid var(--champ-filet);
  border-radius: 8px;
  transition: border-color 180ms ease-in;
}
.champ__saisie:hover {
  border-color: rgba(79, 90, 60, 0.6);
}
.champ__saisie:focus {
  border-color: var(--kaki);
}
.champ__saisie:focus-visible {
  outline: 2px solid var(--kaki);
  outline-offset: 2px;
}

/* Menu déroulant : flèche kaki dessinée, la flèche système est retirée. */
.champ__saisie--liste {
  appearance: none;
  -webkit-appearance: none;
  padding-right: 2.75rem;
  cursor: pointer;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%234F5A3C' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 0.875rem center;
  background-size: 1.125rem;
}

.champ__saisie--date {
  max-width: 16rem;
}

.champ__saisie--message {
  min-height: 8.5rem;
  resize: vertical;
}

/* Erreur : texte sous le champ et filet plus marqué, jamais la couleur seule. */
.champ__saisie[aria-invalid="true"] {
  border-color: #9a3b2e;
  border-width: 2px;
  padding: calc(0.75rem - 1px) calc(0.875rem - 1px);
}
.champ__erreur {
  margin: 0;
  font-family: var(--satoshi);
  font-size: 0.875rem;
  font-weight: var(--t-ui-graisse);
  color: #9a3b2e;
}

/* Bouton d'envoi : même famille que « Passer une commande » (Satoshi 700,
   15 / 32 px, rayon 8 px, 280 ms à l'entrée, 180 ms à la sortie, levée d'un
   pixel). Plein kaki ici, puisqu'il est posé sur fond clair. */
.formulaire-contact__pied {
  gap: 0.75rem;
  justify-items: center;
  margin-top: 0.5rem;
  text-align: center;
}

.formulaire-contact__envoi {
  position: relative;
  display: inline-grid;
  place-items: center;
  min-width: 16.5rem;
  min-height: 3rem;
  padding: 15px 32px;
  font-family: var(--satoshi);
  font-weight: 700;
  font-size: var(--t-ui-taille);
  line-height: 1.2;
  color: var(--blanc);
  background: var(--kaki);
  border: 1px solid var(--kaki);
  border-radius: 8px;
  cursor: pointer;
  transition: background-color 180ms ease-in, border-color 180ms ease-in,
              transform 180ms ease-in;
}
.formulaire-contact__envoi:focus-visible {
  outline: 2px solid var(--kaki);
  outline-offset: 3px;
  background: var(--kaki-2);
  border-color: var(--kaki-2);
}
@media (hover: hover) and (pointer: fine) {
  .formulaire-contact__envoi:hover {
    background: var(--kaki-2);
    border-color: var(--kaki-2);
    transform: translateY(-1px);
    transition: background-color 280ms ease-out, border-color 280ms ease-out,
                transform 280ms ease-out;
  }
}
.formulaire-contact__envoi:active {
  transform: translateY(0);
}
.formulaire-contact__envoi[aria-busy="true"] {
  cursor: default;
}

/* --- Animation d'envoi « Les grains » -------------------------------------
   Jouée par initFormulaireContact uniquement quand Netlify a accepté la
   demande, jamais au simple clic. Le bouton se tasse, seize grains posés par
   le script jaillissent autour de lui, puis la coche se trace avec « Demande
   envoyée ». Libellé et confirmation occupent la même case de la grille : la
   largeur du bouton ne bouge pas. */
.formulaire-contact__envoi > .envoi__libelle,
.formulaire-contact__envoi > .envoi__ok {
  grid-area: 1 / 1;
}

.envoi__libelle {
  transition: opacity 200ms ease-in;
}
.envoi__ok {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  opacity: 0;
  transform: translateY(6px);
  pointer-events: none;
}
.envoi__coche {
  width: 1.25em;
  height: 1.25em;
  fill: none;
  stroke: currentColor;
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.envoi__coche path {
  stroke-dasharray: 100;
  stroke-dashoffset: 100;
}

.formulaire-contact__envoi.is-ok .envoi__libelle {
  opacity: 0;
}
.formulaire-contact__envoi.is-ok .envoi__ok {
  opacity: 1;
  transform: none;
  transition: opacity 300ms ease-out, transform 300ms ease-out;
}
.formulaire-contact__envoi.is-ok .envoi__coche path {
  stroke-dashoffset: 0;
  transition: stroke-dashoffset 420ms ease-out 120ms;
}

.formulaire-contact__envoi.is-envoi {
  animation: envoi-presse 360ms ease-out;
}
@keyframes envoi-presse {
  0%   { transform: scale(1); }
  30%  { transform: scale(0.94); }
  100% { transform: scale(1); }
}

.envoi__grain {
  position: absolute;
  top: 50%;
  left: 50%;
  width: var(--taille, 6px);
  height: var(--taille, 6px);
  margin: calc(var(--taille, 6px) / -2) 0 0 calc(var(--taille, 6px) / -2);
  border-radius: 50%;
  background: var(--teinte, var(--kaki));
  pointer-events: none;
  opacity: 0;
  animation: envoi-grain 800ms cubic-bezier(0.2, 0.7, 0.3, 1) forwards;
}
@keyframes envoi-grain {
  0%   { opacity: 0; transform: translate(0, 0) scale(0.4); }
  15%  { opacity: 1; }
  70%  { opacity: 1; transform: translate(var(--dx), var(--dy)) scale(1); }
  100% { opacity: 0; transform: translate(var(--dx), calc(var(--dy) + 14px)) scale(1); }
}

.formulaire-contact__mention {
  margin: 0;
  font-size: 0.875rem;
  color: var(--brun);
}

/* Message de statut : confirmation ou échec de l'envoi, écrit par le script. */
.formulaire-contact__statut {
  margin: 0;
  font-family: var(--satoshi);
  font-size: 0.9375rem;
  font-weight: var(--t-ui-graisse);
  color: var(--kaki);
}
.formulaire-contact__statut:empty {
  display: none;
}
.formulaire-contact__statut.est-erreur {
  color: #9a3b2e;
}

/* Nom et téléphone côte à côte dès que la largeur le permet. */
@media (min-width: 600px) {
  .formulaire-contact {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    column-gap: 1rem;
  }
  .champ--large {
    grid-column: 1 / -1;
  }
}

/* --- Horaires --------------------------------------------------------------
   Tableau large aligné à gauche, « Appeler » à droite. Même largeur de bloc
   que « Nous contacter » (55 rem). Sur ordinateur, « Appeler » est centré
   verticalement face au tableau, séparé par un filet ; sur mobile, il passe
   sous la note. */
.horaires-bloc {
  display: grid;
  gap: 2rem;
  max-width: 55rem;
  margin: 0 auto;
}
.horaires-bloc h2 {
  margin: 0 0 1.25rem;
}
.horaires-bloc .horaires--liste {
  width: 100%;
  max-width: none;
}
.horaires-bloc__action {
  display: flex;
  justify-content: flex-start;
}

/* Tableau en liste serrée : jour à gauche, plage à droite. */
.horaires--liste {
  max-width: var(--largeur-lecture);
}
.horaires--liste th,
.horaires--liste td {
  padding: 0.55rem 0;
  border-bottom: var(--filet);
}
.horaires--liste td {
  text-align: right;
  color: var(--encre);
}

.note {
  margin: 0.875rem 0 0;
  max-width: var(--largeur-lecture);
  font-size: 0.9375rem;
  color: var(--brun);
}

/* --- Venir à la boutique ---------------------------------------------------
   Carte, photo de devanture et « Itinéraire » ; l'adresse est dans « Nous
   contacter ». Sur mobile : titre, texte, photo, « Itinéraire », carte. Sur
   ordinateur : titre, texte, photo et « Itinéraire » à gauche, carte dans la
   colonne large, sur toute la hauteur. */

/* Filet de séparation avec les horaires : les deux sections partagent le
   fond blanc. Posé à la jonction des deux sections, il profite de leur
   padding de part et d'autre, et prend la largeur du bloc horaires (55 rem). */
.infos-venir {
  position: relative;
}
.infos-venir::before {
  content: "";
  position: absolute;
  top: 0;
  left: 50%;
  width: min(calc(100% - 2.5rem), 55rem);
  border-top: var(--filet);
  transform: translateX(-50%);
}

.venir {
  display: grid;
  gap: 2rem;
}

.venir__entete h2 {
  margin-top: 0;
}

.venir__texte p {
  margin: 0;
  max-width: var(--largeur-lecture);
}

/* Photo de devanture : entre le texte d'accès et « Itinéraire », format
   paysage entier (devanture-paysage-v2.webp, 1672 × 941, photo du 29/09/2026), sans recadrage.
   Taille modérée : largeur de la colonne de gauche sur ordinateur, 26 rem au
   plus sur mobile. */
.venir__photo {
  display: block;
  width: 100%;
  max-width: 26rem;
  height: auto;
  aspect-ratio: 1296 / 729;
  margin: 1.75rem 0 0;
  border-radius: var(--rayon);
}

.venir__actions {
  margin-top: 1.25rem;
}

/* Sur mobile, la photo et le bouton « Itinéraire » sont centrés. */
@media (max-width: 899.98px) {
  .venir__photo {
    margin-inline: auto;
  }
  .venir__actions {
    justify-content: center;
  }
}

/* --- Questions fréquentes --------------------------------------------------
   Accordéon natif (details / summary), sans JavaScript. Une seule colonne :
   le titre, puis les questions. Question en registre affirmation (Source
   Serif 4 600, 18 px), signe + / – en Satoshi kaki. */
.faq-bloc {
  display: grid;
  gap: 2.75rem;
}
.faq-bloc h2 {
  margin: 0;
}

.faq {
  border-top: var(--filet);
}
.faq details {
  border-bottom: var(--filet);
}
.faq summary {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 1rem;
  padding: 1rem 0;
  cursor: pointer;
  list-style: none;
  font-family: var(--serif);
  font-weight: var(--t-affirm-graisse);
  font-size: var(--t-affirm-taille);
  line-height: 1.35;
}
.faq summary::-webkit-details-marker {
  display: none;
}
/* Signe + / – dessiné en texte, pas d'icône décorative. Signe d'interface,
   pas du texte : Satoshi. */
.faq summary::after {
  content: "+";
  flex-shrink: 0;
  font-family: var(--satoshi);
  font-size: 1.25rem;
  color: var(--kaki);
}
.faq details[open] summary::after {
  content: "–";
}
.faq summary:hover {
  color: var(--kaki);
}
/* Les réponses sont du récit courant : elles héritent du serif du corps de
   page. */
.faq details p {
  margin: 0;
  padding-bottom: 1.25rem;
  max-width: var(--largeur-lecture);
}

/* --- Grands écrans --------------------------------------------------------- */
@media (min-width: 900px) {
  .page-infos-pratiques .section {
    padding-top: 6.5rem;
    padding-bottom: 6.5rem;
  }

  .contact {
    grid-template-columns: minmax(0, 1fr) minmax(0, 1.6fr);
    gap: 4rem;
    align-items: start;
  }
  /* Un filet kaki sépare le texte des champs. */
  .contact__intro {
    padding-right: 2.5rem;
    border-right: var(--filet);
  }

  .horaires-bloc {
    grid-template-columns: minmax(0, 1.6fr) minmax(0, 1fr);
    align-items: center;
    gap: 4rem;
  }
  .horaires-bloc__action {
    justify-content: center;
    align-self: stretch;
    align-items: center;
    border-left: var(--filet);
  }

  .venir {
    grid-template-columns: minmax(0, 1fr) minmax(0, 1.8fr);
    grid-template-areas:
      "entete carte"
      "texte  carte";
    grid-template-rows: auto 1fr;
    column-gap: 4rem;
    row-gap: 2rem;
  }
  .venir__entete {
    grid-area: entete;
  }
  .venir__texte {
    grid-area: texte;
  }
  .venir__carte {
    grid-area: carte;
    align-self: center;
  }
  .venir .carte-maps {
    aspect-ratio: 16 / 10;
  }
}

/* --- Mouvement réduit ------------------------------------------------------
   Le bloc 19 coupe déjà toutes les transitions et animations. Restent la
   levée d'un pixel du bouton, qui deviendrait un sursaut sec, et les grains,
   qui resteraient invisibles mais présents : les deux sont retirés. Le
   script, lui, confirme directement sans les semer. */
@media (prefers-reduced-motion: reduce) {
  .formulaire-contact__envoi,
  .formulaire-contact__envoi:hover {
    transform: none;
  }
  .envoi__grain {
    display: none;
  }
}

/* --------------------------------------------------------------------------
   16b. Page Mentions légales (annexe, hors des quatre pages, 23/09/2026)
   En-tête texte sans photo, sur le modèle de « Nos produits » : le titre de
   page à taille de titre de section élargie, puis une ligne de résumé en
   Satoshi. Le texte suit à largeur de lecture, en corps courant ; les parties
   en Satoshi à taille de sous-titre, les sous-parties un cran en dessous.
   -------------------------------------------------------------------------- */
.page-mentions-legales .page-entete {
  padding-top: 3.5rem;
  padding-bottom: 3.5rem;
}
.page-mentions-legales h1 {
  font-size: clamp(2.25rem, 4.5vw, 3.25rem);
  margin: 0;
}
.mentions__resume {
  margin: 1rem 0 0;
  font-family: var(--satoshi);
  font-size: var(--t-ui-taille);
  font-weight: var(--t-ui-graisse);
  color: var(--brun);
}
.mentions__texte {
  max-width: var(--largeur-lecture);
  font-size: var(--t-corps-taille);
  line-height: var(--t-corps-interligne);
}
.mentions__texte h2 {
  font-size: var(--t-h3-taille);
  font-weight: var(--t-h3-graisse);
  letter-spacing: var(--t-h3-lettres);
  line-height: var(--t-h3-interligne);
  margin: 2.25rem 0 0.75rem;
}
.mentions__texte h2:first-of-type {
  margin-top: 2rem;
}
.mentions__texte h3 {
  font-size: 1.0625rem;
  font-weight: 700;
  letter-spacing: -0.01em;
  margin: 1.5rem 0 0.5rem;
}
.mentions__texte p {
  margin: 0 0 0.9rem;
}
/* Le bloc 2 retire les puces de toutes les listes : ici, ce sont de vraies
   énumérations, on les remet. */
.mentions__texte ul {
  margin: 0 0 0.9rem;
  padding-left: 1.25rem;
  list-style: disc;
}
.mentions__texte li {
  margin-bottom: 0.35rem;
}
@media (min-width: 900px) {
  .page-mentions-legales .page-entete {
    padding-top: 5.5rem;
    padding-bottom: 5.5rem;
  }
}

/* --------------------------------------------------------------------------
   17. Tablette : cartes en 2×2 à partir de 600 px
   -------------------------------------------------------------------------- */
@media (min-width: 600px) {
  .cartes {
    grid-template-columns: repeat(2, 1fr);
  }
  .infos {
    grid-template-columns: repeat(2, 1fr);
  }
  .trois-blocs {
    grid-template-columns: repeat(3, 1fr);
  }
}

/* --------------------------------------------------------------------------
   18. Desktop : à partir de 900 px
   -------------------------------------------------------------------------- */
@media (min-width: 900px) {
  .conteneur {
    padding-left: 2.5rem;
    padding-right: 2.5rem;
  }

  .section {
    padding-top: 5.5rem;
    padding-bottom: 5.5rem;
  }

  /* Header : menu inline, horaires visibles, burger caché */
  .header__nav {
    position: static;
    display: block;
    background: transparent;
    border: 0;
    padding: 0;
  }
  .header__menu {
    flex-direction: row;
    gap: 2rem;
  }
  .header__menu a {
    padding: 0;
    border: 0;
  }
  .header__horaires {
    display: block;
  }
  .burger {
    display: none;
  }

  /* Plus de barre mobile, footer sans marge supplémentaire */
  .barre-mobile {
    display: none;
  }
  .footer {
    padding-bottom: 2.5rem;
  }
  .footer__interieur {
    flex-direction: row;
    align-items: flex-end;
    justify-content: space-between;
    text-align: start;
  }
  .footer__liens {
    justify-content: flex-start;
  }

  .hero__contenu {
    padding-bottom: 4.5rem;
  }

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

  /* Deux colonnes. Par défaut : image à gauche, texte à droite.
     .duo--texte-gauche inverse l'ordre visuel. */
  .duo {
    grid-template-columns: 1fr 1fr;
    gap: 4rem;
  }
  .duo--texte-gauche .duo__media {
    order: 2;
  }

  .infos {
    grid-template-columns: 1fr 1fr 1.35fr;
    gap: 3rem;
  }

  .bandeau .conteneur {
    padding-bottom: 4rem;
  }

  /* Section Commandes : la colonne du cadre est élargie (1 / 1,8), le cadre
     y est plafonné à 26 rem et centré. */
  .duo--commandes {
    grid-template-columns: minmax(0, 1fr) minmax(0, 1.8fr);
    gap: 3rem;
  }
}

/* --------------------------------------------------------------------------
   19. Mouvement réduit : vidéo masquée (l'image de secours reste), pas de
   défilement doux, pas de transitions (le coverflow change d'image sans
   animation : la règle « transition: none » ci-dessous le couvre).
   -------------------------------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
  html {
    scroll-behavior: auto;
  }
  *,
  *::before,
  *::after {
    transition: none !important;
    animation: none !important;
  }
  .hero__video {
    display: none;
  }
  /* Image de secours du hero : portrait sous 900 px, paysage au-delà
     (règle suivante). Seul cas où elle est téléchargée. */
  .hero__fond {
    background-image: url("../assets/img/devanture-portrait-v2.webp");
  }

  /* Les transitions étant coupées ci-dessus, un déplacement de flèche
     deviendrait un saut sec : on le supprime. L'état reste lisible sans aucun
     mouvement — le fond et le contour du cadre changent, et le trait de
     « Nos produits » se remplit d'un coup au lieu de se déployer. */
  .cta:hover .cta__fleche,
  .cta:focus-visible .cta__fleche,
  .lien-suite:hover .lien-suite__fleche,
  .lien-suite:focus-visible .lien-suite__fleche {
    transform: none;
  }
  .cta--trait:hover::after,
  .cta--trait:focus-visible::after,
  .lien-suite:hover::after,
  .lien-suite:focus-visible::after,
  .action--lien:hover::after,
  .action--lien:focus-visible::after {
    transform: scaleX(1);
  }
  /* La levée d'un pixel du bouton de commande deviendrait un sursaut sec.
     Le changement de couleur, lui, reste : l'état est toujours lisible. */
  .cta--plein:hover,
  .cta--plein:active {
    transform: none;
  }
}
@media (prefers-reduced-motion: reduce) and (min-width: 900px) {
  .hero__fond {
    background-image: url("../assets/img/devanture-paysage-v2.webp");
  }
}

/* --------------------------------------------------------------------------
   20. Retour en haut (bouton flottant, cinq pages, ajouté le 23/09/2026)
   Rond de 44 px (cible tactile minimale) en kaki plein, flèche crème : le
   registre des boutons pleins. Caché au repos ; « est-visible », posée par
   js/main.js après 400 px de défilement, le fait monter en fondu. Sous le
   header et la barre mobile (z-index 100), au-dessus du contenu. Sous 900 px
   il se pose au-dessus de la barre fixe pour ne recouvrir ni « Appeler » ni
   « Itinéraire ». Le bloc 19 coupe sa transition en mouvement réduit.
   -------------------------------------------------------------------------- */
.retour-haut {
  position: fixed;
  right: 1.5rem;
  bottom: 1.5rem;
  z-index: 90;
  width: 44px;
  height: 44px;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: var(--kaki);
  color: var(--blanc);
  box-shadow: 0 4px 14px rgba(62, 72, 48, 0.22);
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  opacity: 0;
  visibility: hidden;
  transform: translateY(0.5rem);
  transition: opacity 250ms ease, transform 250ms ease, visibility 0s linear 250ms, background-color 150ms ease;
}
.retour-haut.est-visible {
  opacity: 1;
  visibility: visible;
  transform: none;
  transition-delay: 0s;
}
.retour-haut svg {
  width: 22px;
  height: 22px;
  stroke: currentColor;
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.retour-haut:hover,
.retour-haut:focus-visible {
  background: var(--kaki-clair);
}
.retour-haut:focus-visible {
  outline: 2px solid var(--kaki);
  outline-offset: 3px;
}
@media (max-width: 899.98px) {
  .retour-haut {
    right: 1rem;
    bottom: calc(var(--hauteur-barre-mobile) + env(safe-area-inset-bottom, 0px) + 1rem);
  }
}

/* --------------------------------------------------------------------------
   21. Pause de la vidéo du hero (accueil, WCAG 2.2.2, ajouté le 29/09/2026)
   Rond de 44 px en bas à droite du hero, fond d'encre translucide et icône
   blanche pour rester lisible sur la vidéo. Le focus reprend le contour
   blanc du hero (bloc 2). Sous 900 px, il se pose 16 px au-dessus de la barre
   fixe mobile, et le texte du hero remonte (marge basse 3 → 4,75 rem) pour
   que le bouton reste seul dans le coin, sous les boutons d'action (décision
   du 29/09/2026). « est-en-pause », posée par js/main.js, montre l'icône
   Lecture.
   Caché avec la vidéo en mouvement réduit (le JS ne le révèle pas).
   -------------------------------------------------------------------------- */
.hero__lecture {
  position: absolute;
  right: 1.5rem;
  bottom: 1.5rem;
  width: 44px;
  height: 44px;
  padding: 0;
  border: 1px solid rgba(255, 255, 255, 0.55);
  border-radius: 50%;
  background: rgba(43, 38, 32, 0.45);
  color: var(--blanc);
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: background-color 150ms ease;
}
.hero__lecture[hidden] {
  display: none;
}
.hero__lecture:hover {
  background: rgba(43, 38, 32, 0.7);
}
.hero__lecture-lire,
.hero__lecture.est-en-pause .hero__lecture-pause {
  display: none;
}
.hero__lecture.est-en-pause .hero__lecture-lire {
  display: block;
}
@media (max-width: 899.98px) {
  .hero__lecture {
    right: 1rem;
    bottom: calc(var(--hauteur-barre-mobile) + env(safe-area-inset-bottom, 0px) + 1rem);
  }
  /* 16 px sous le bouton + 44 px de bouton + 16 px d'écart = 4,75 rem.
     La marge de sécurité basse s'ajoute comme pour la barre et le bouton :
     Firefox Android la rend non nulle quand sa barre d'adresse est visible,
     sans elle le bouton remontait sur « Nos produits ». */
  .hero__contenu {
    padding-bottom: calc(4.75rem + var(--hauteur-barre-mobile) + env(safe-area-inset-bottom, 0px));
  }
}

/* --------------------------------------------------------------------------
   22. Pastille des horaires du jour dans le hero (accueil, < 900 px,
   ajoutée le 29/09/2026)
   Sous 900 px, les horaires du header sont masqués faute de place : la
   pastille les reprend en haut à droite du hero, 16 px sous le header et
   16 px du bord droit (alignée sur le bouton pause). Même texte, rempli par
   afficherHorairesDuJour (attribut data-horaires-jour). Fond d'encre à 72 % :
   même sur un pixel blanc de la vidéo, le texte écru garde un contraste
   d'environ 5:1 (minimum 4,5:1). Masquée dès 900 px, où le header affiche
   les horaires. Le texte du hero commence 72 px sous le header au lieu de
   48 pour que, sur un écran bas, le titre ne remonte pas sous la pastille.
   -------------------------------------------------------------------------- */
.hero__horaires {
  position: absolute;
  top: calc(var(--hauteur-header) + 1rem);
  right: 1rem;
  padding: 0.4rem 0.85rem;
  border-radius: 999px;
  background: rgba(43, 38, 32, 0.72);
  color: var(--blanc);
  font-family: var(--satoshi);
  font-size: var(--t-ui-taille);
  font-weight: var(--t-ui-graisse);
  line-height: 1.3;
  white-space: nowrap;
}
.hero__horaires strong {
  font-weight: 700;
}
@media (max-width: 899.98px) {
  .hero__contenu {
    padding-top: calc(var(--hauteur-header) + 4.5rem);
  }
}
@media (min-width: 900px) {
  .hero__horaires {
    display: none;
  }
}

/* --------------------------------------------------------------------------
   23. Carte Google Maps chargée au clic (accueil, infos pratiques, ajouté le
   29/09/2026)
   Le bloc porte aussi la classe carte-maps : même taille et même fond écru
   que l'iframe qui le remplacera, donc rien ne bouge au clic. Pas de capture
   de carte Google (droits d'image) : fond neutre aux couleurs du site.
   L'adresse, le bouton « Afficher la carte » (action--cadre, comme
   « Itinéraire ») et la ligne d'information sont centrés. Le bouton et la
   ligne restent cachés sans JS : .action impose display: inline-flex, qui
   l'emporterait sur l'attribut hidden, d'où la règle [hidden] ci-dessous.
   -------------------------------------------------------------------------- */
.carte-au-clic {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 1rem;
  padding: 1.5rem;
  text-align: center;
  color: var(--encre);
}
.carte-au-clic [hidden] {
  display: none;
}
.carte-au-clic__adresse {
  margin: 0;
  font-family: var(--satoshi);
  font-weight: 700;
  font-size: var(--t-ui-taille);
}
.carte-au-clic__note {
  max-width: 22rem;
  margin: 0;
  font-size: 0.875rem;
  line-height: 1.45;
}

/* --------------------------------------------------------------------------
   24. Lien d'évitement « Aller au contenu » (six pages, ajouté le 29/09/2026)
   Premier élément focusable de chaque page. Sorti de l'écran par un
   décalage (pas display: none, sinon il ne recevrait pas le focus) ; il
   descend au focus, en haut à gauche, au-dessus du header (z-index 100) et
   de la vidéo. Kaki plein, texte blanc : le registre des boutons pleins
   (contraste 7,6:1). Il mène au <main id="contenu" tabindex="-1">, qui ne
   montre pas de contour : un cadre autour de toute la page n'aide personne.
   -------------------------------------------------------------------------- */
.lien-evitement {
  position: fixed;
  top: 0.75rem;
  left: 0.75rem;
  z-index: 200;
  padding: 0.75rem 1.1rem;
  border-radius: 12px;
  background: var(--kaki);
  color: var(--blanc);
  font-family: var(--satoshi);
  font-weight: 700;
  font-size: var(--t-ui-taille);
  text-decoration: none;
  transform: translateY(calc(-100% - 1.5rem));
}
.lien-evitement:focus {
  transform: none;
}
.lien-evitement:focus-visible {
  outline: 2px solid var(--blanc);
  outline-offset: 2px;
  box-shadow: 0 0 0 4px var(--kaki);
}
#contenu:focus {
  outline: none;
}
