/* Polices auto-hébergées (fichiers variables, sous-ensembles latin et latin étendu).
   Aucune requête vers fonts.googleapis.com / fonts.gstatic.com : pas de transfert
   d'adresse IP des visiteurs à un tiers, et pas de CSS bloquant hors du domaine. */
@font-face {
  font-family: "Inter";
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  src: url("/fonts/inter-latin-ext.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: "Inter";
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  src: url("/fonts/inter-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "Roboto Condensed";
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  src: url("/fonts/roboto-condensed-latin-ext.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: "Roboto Condensed";
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  src: url("/fonts/roboto-condensed-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

/* Montserrat : la police de la graveuse. Elle ne sert qu'aux champs d'initiale et à leur
   rappel dans le récapitulatif, pour que le client lise sa lettre telle qu'elle sera gravée. */
@font-face {
  font-family: "Montserrat";
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  src: url("/fonts/montserrat-latin-ext.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: "Montserrat";
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  src: url("/fonts/montserrat-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

/* Les six polices des affiches de naissance. Elles ne servent qu'à ces cinq fiches, mais
   elles sont déclarées ici comme les autres : une déclaration `@font-face` ne télécharge
   rien tant qu'aucun texte rendu ne l'appelle — une fiche bracelet ne paie donc rien pour
   elles. Toutes sous licence SIL Open Font (voir `public/fonts/LICENCES.md`), récupérées une
   fois et versionnées : le point 2 interdit qu'une page aille les chercher chez Google.
   Chacune porte un rôle et un seul, et c'est ce qui justifie d'en embarquer six : la serif
   des textes (Cormorant Garamond, avec son italique — la moitié des lignes d'une affiche de
   naissance sont en italique), les deux anglaises qui écrivent le prénom (Pinyon Script,
   fine et classique ; Sacramento, plus ronde), la romaine en capitales espacées du modèle
   étoilé (Marcellus), la ronde du modèle animal (Fredoka) et la sans-serif légère des
   étiquettes (Josefin Sans). */
@font-face {
  font-family: "Cormorant Garamond";
  font-style: normal;
  font-weight: 300 700;
  font-display: swap;
  src: url("/fonts/cormorant-garamond-latin-ext.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: "Cormorant Garamond";
  font-style: normal;
  font-weight: 300 700;
  font-display: swap;
  src: url("/fonts/cormorant-garamond-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "Cormorant Garamond";
  font-style: italic;
  font-weight: 300 700;
  font-display: swap;
  src: url("/fonts/cormorant-garamond-italic-latin-ext.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: "Cormorant Garamond";
  font-style: italic;
  font-weight: 300 700;
  font-display: swap;
  src: url("/fonts/cormorant-garamond-italic-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "Pinyon Script";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("/fonts/pinyon-script-latin-ext.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: "Pinyon Script";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("/fonts/pinyon-script-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "Sacramento";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("/fonts/sacramento-latin-ext.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: "Sacramento";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("/fonts/sacramento-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "Marcellus";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("/fonts/marcellus-latin-ext.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: "Marcellus";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("/fonts/marcellus-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "Fredoka";
  font-style: normal;
  font-weight: 300 600;
  font-display: swap;
  src: url("/fonts/fredoka-latin-ext.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: "Fredoka";
  font-style: normal;
  font-weight: 300 600;
  font-display: swap;
  src: url("/fonts/fredoka-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "Josefin Sans";
  font-style: normal;
  font-weight: 100 700;
  font-display: swap;
  src: url("/fonts/josefin-sans-latin-ext.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: "Josefin Sans";
  font-style: normal;
  font-weight: 100 700;
  font-display: swap;
  src: url("/fonts/josefin-sans-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
/* Playfair Display, la Didone de l'affiche des noces « en chiffres » (23 sept. 2026) : le
   grand nombre d'années, les compteurs et les titres en capitales. Une police variable
   (400 à 900) en deux sous-ensembles, comme les autres ; rien ne se télécharge tant qu'aucun
   texte ne l'appelle, donc les neuf autres fiches ne la paient pas. */
@font-face {
  font-family: "Playfair Display";
  font-style: normal;
  font-weight: 400 900;
  font-display: swap;
  src: url("/fonts/playfair-display-latin-ext.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: "Playfair Display";
  font-style: normal;
  font-weight: 400 900;
  font-display: swap;
  src: url("/fonts/playfair-display-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}


/* 1rem = 10px : les blocs de personnalisation sont dimensionnés en rem sur cette base. */
:root {
  /* ————————————————————————— La charte ————————————————————————— *
   * Une couleur écrite ailleurs que dans ce bloc est une couleur qui échappe à la charte :
   * c'est ainsi que le site s'est retrouvé avec cinq crèmes, cinq gris chauds, cinq bleus
   * profonds et cinq rouges d'erreur, tous à deux points les uns des autres. Un test refuse
   * désormais une nouvelle valeur écrite en dur hors d'ici.
   *
   * Les triplets sont sans `rgb()` pour que `rgba(var(--x), .5)` reste possible — c'est la
   * convention déjà en place sur `--color-foreground`.
   *
   * **Ce qui est dans l'affiche n'est pas dans la charte.** Le papier et l'encre d'une
   * affiche (`#fbf9f4`, `#14324a`, le rouge du tracé) sont les styles du produit, définis
   * dans `public/js/affiche-*.js` et choisis par le client : les changer changerait
   * l'article, et ce qui part à l'impression. Ils restent écrits en clair, hors charte.
   */

  /* — Encres — Un noir chaud plutôt qu'un gris neutre : c'est le cerne du dessin de la
     marque, et il s'accorde aux crèmes et au bois de la gamme. 17,8 de contraste sur blanc,
     contre 18,7 pour le gris qu'il remplace — imperceptible, et bien au-delà du seuil. */
  --encre: 28, 23, 19;
  --encre-douce: 79, 70, 62;   /* paragraphes de section : 9,2 sur blanc, 8,2 sur crème */
  --encre-pale: 103, 94, 85;   /* mentions et compteurs : 5,4 sur blanc. Jamais sur sable. */

  /* — La marque — Relevée dans le dessin de la vache. */
  --ocre: 193, 128, 49;        /* la robe. Un aplat, jamais du texte : 3,3 sur blanc. */
  --ocre-fonce: 154, 102, 39;  /* la robe assombrie de 20 % : 4,88, elle porte du blanc. */
  --brun: 120, 86, 61;         /* surtitres et prix : 6,6 sur blanc, 5,8 sur crème, 5,0 sur sable */
  --navy: 30, 57, 71;          /* les actions et les fonds profonds : blanc à 12,1 dessus */
  --navy-fonce: 24, 46, 57;
  /* Le cercle de focus garde le bleu, et c'est volontaire : il ne doit ressembler à aucune
     couleur de décor, sinon on ne le distingue plus d'un élément mis en avant. */
  --bleu-focus: 62, 119, 170;

  /* — Surfaces — Une seule crème remplace les cinq qui traînaient (L* 94,3 à 95,9). */
  --creme: 244, 241, 234;
  --sable: 238, 222, 203;      /* les blocs chauds mis en avant */
  --sauge: 240, 244, 240;      /* le monde des affiches, et sa carte plus dense */
  --sauge-dense: 226, 235, 226;
  --gris: 243, 243, 243;       /* fonds d'image et pied de page : un gris sans teinte */
  --bordure: 236, 236, 236;

  /* — Les quatre intentions — Elles codent quatre catégories, elles ne se confondent donc
     pas ; mais elles étaient de clarté et de saturation inégales (L* 88,8 à 91,0, chroma 12
     à 34) et ne se lisaient pas comme une série. Toutes ramenées à L* 89 et chroma 22. */
  --teinte-lien: 238, 220, 216;
  --teinte-aventure: 207, 229, 207;
  --teinte-lieu: 210, 226, 232;
  --teinte-instant: 230, 223, 208;

  /* — Alerte — Un seul rouge au lieu de cinq : 6,5 sur blanc. */
  /* Les portraits des auteurs (`views/avatar.liquid`). Deux carnations et deux couleurs de
     cheveux : ce sont les seules couleurs de la charte qui décrivent des personnes réelles,
     et elles sont là plutôt qu'en attribut `fill` parce qu'aucune couleur ne s'écrit hors
     de ce bloc. */
  --peau-claire: 231, 190, 163;
  --peau-foncee: 118, 74, 48;
  --cheveux-clairs: 92, 70, 52;
  --cheveux-fonces: 38, 30, 26;

  --rouge: 179, 38, 30;
  --rouge-fond: 253, 236, 236;

  /* ————— Les rôles, en termes du gabarit ————— */
  --color-foreground: var(--encre);
  --color-background: 255, 255, 255;
  --color-accent: var(--bleu-focus);
  --color-annonce: var(--ocre-fonce);
  --color-button: var(--navy);
  --color-button-text: 255, 255, 255;
  --font-body-family: "Roboto Condensed", system-ui, sans-serif;
  --font-heading-family: "Inter", system-ui, sans-serif;
  --font-gravure-family: "Montserrat", system-ui, sans-serif;
  --page-width: 120rem;
  --buttons-radius: 6px;
  --inputs-radius: 6px;
  --variant-pills-radius: 20px;
  --card-radius: 0.6rem;
}
html { font-size: 62.5%; -webkit-text-size-adjust: 100%; }
body { margin: 0; background: rgb(var(--color-background)); color: rgb(var(--color-foreground)); font-family: var(--font-body-family); font-size: 1.5rem; line-height: 1.6; min-height: 100vh; display: flex; flex-direction: column; }
*, *::before, *::after { box-sizing: border-box; }
img { max-width: 100%; height: auto; }
a { color: inherit; }
h1, h2, h3, .h4 { font-family: var(--font-heading-family); font-weight: 400; letter-spacing: .06rem; line-height: 1.3; margin: 0; }
h1 { font-size: 3rem; }
h2 { font-size: 2.4rem; }
.visually-hidden { position: absolute !important; overflow: hidden; width: 1px; height: 1px; margin: -1px; padding: 0; border: 0; clip: rect(0 0 0 0); word-wrap: normal !important; }
.page-width { width: 100%; max-width: var(--page-width); margin: 0 auto; padding: 0 1.5rem; }
@media screen and (min-width: 750px) { .page-width { padding: 0 5rem; } }
.section-padding { padding-top: 2.4rem; padding-bottom: 3.6rem; }
@media screen and (min-width: 750px) { .section-padding { padding-top: 3.6rem; padding-bottom: 5.2rem; } }
.caption { font-size: 1.2rem; letter-spacing: .05rem; }
.rte { font-size: 1.6rem; line-height: 1.7; }
.rte p { margin: 0 0 1.6rem; }
.rte ul, .rte ol { padding-left: 2rem; }
.rte h2, .rte h3 { margin: 2.4rem 0 1rem; }
.underlined-link { text-decoration: underline; text-underline-offset: .3rem; font-size: 1.4rem; }
.link { background: none; border: none; padding: 0; font: inherit; color: inherit; cursor: pointer; text-decoration: underline; text-underline-offset: .3rem; }

/* Annonce + en-tête */
.announcement-bar { background: rgb(var(--color-annonce)); color: #fff; text-align: center; }
.announcement-bar__message { margin: 0; padding: .9rem 1.5rem; font-size: 1.3rem; letter-spacing: .06rem; }
/* Le bandeau entier est cliquable quand il annonce une fête : la cible est la barre, pas
   trois mots de 12 px. `flex` et non `inline-flex` : la marge intérieure d'une boîte en
   ligne ne compte pas dans la hauteur de son parent, et la barre tombait à 20 px de haut
   pendant que le texte, lui, en faisait 17. */
.announcement-bar__lien { display: flex; flex-wrap: wrap; align-items: baseline; justify-content: center; gap: .2rem 1rem; color: inherit; text-decoration: none; }
.announcement-bar__lien b { font-weight: 600; text-decoration: underline; text-underline-offset: .3rem; }
.announcement-bar__lien:hover b { text-decoration-thickness: .2rem; }
/* Sur téléphone le bandeau prend deux lignes : il mange le haut du premier écran, déjà
   occupé par l'en-tête. Marge et interlettrage resserrés, et « Nos idées » remonte sur la
   même ligne dès qu'il y tient. */
@media screen and (max-width: 480px) {
  .announcement-bar__lien { padding: .7rem 1.2rem; gap: .1rem .7rem; letter-spacing: 0; line-height: 1.35; }
}
/* Quatre colonnes pour quatre enfants : logo, menu, langues, et les deux icônes
   groupées. Un enfant de plus que de colonnes tombe dans une rangée implicite, tout à
   gauche — c'est ce qui envoyait le panier sous le logo dès 750 px. */
.header { display: grid; grid-template-columns: auto 1fr auto auto; align-items: center; gap: 2rem; padding-top: 1rem; padding-bottom: 1rem; border-bottom: .1rem solid rgba(var(--color-foreground), .08); }
.header__logo { display: block; width: 7rem; height: 7rem; object-fit: contain; }
@media screen and (min-width: 990px) { .header__logo { width: 9rem; height: 9rem; } }
/* `wrap` : sous 750 px le menu prend sa propre rangée, et cinq entrées n'y tiennent pas
   d'un seul tenant sur un écran de 320 px — sans le retour à la ligne, tout le document
   devient défilable de travers. Ce garde-fou avait été posé une fois, puis emporté par un
   retour en arrière sur le logo : trois entrées tenaient encore, cinq non. Un test le tient
   désormais, parce que rien d'autre ne le voyait. */
.list-menu { display: flex; flex-wrap: wrap; gap: 2rem; list-style: none; margin: 0; padding: 0; }
/* Les trois entrées du menu sont la même boîte, sinon la troisième ne s'aligne pas sur les
   deux autres : un `<a>` en ligne se pose sur la ligne de base, un `<summary>` en `inline-flex`
   se centre sur sa propre hauteur, et les deux ne tombent pas au même endroit. */
/* 1,1 rem de marge intérieure et −.3 rem de marge extérieure : la cible fait 44 px de haut, la
   rangée garde ses 38 px de mise en page — l'en-tête ne bouge pas d'un pixel. */
.header__menu-item { display: inline-flex; align-items: center; text-decoration: none; font-size: 1.4rem; letter-spacing: .06rem; padding: 1.1rem 0; margin: -.3rem 0; }
.header__menu-item:hover { text-decoration: underline; text-underline-offset: .3rem; }

/* « Pour quelle occasion ? » — le menu d'intention.
   Le panneau est posé sur la page (`absolute`) et non intercalé : dans l'en-tête en grille,
   un bloc qui pousse ses voisins déplacerait le panier et le sélecteur de langue à chaque
   ouverture. Il est ancré sur l'en-tête entier, pas sur l'élément de liste, pour rester dans
   la gouttière sur téléphone au lieu de sortir par la droite. */
.header { position: relative; }
.menu-occasions { position: static; }
.menu-court { display: none; }
@media screen and (max-width: 749px) {
  .menu-long { display: none; }
  .menu-court { display: inline; }
}
/* Le libellé ne se coupe jamais : sans cela la flèche partait seule à la ligne suivante,
   à trois lignes du texte qu'elle accompagne. */
.menu-occasions__declencheur { list-style: none; cursor: pointer; display: inline-flex; align-items: center; gap: .5rem; text-decoration: none; white-space: nowrap; }
.menu-occasions__declencheur:hover { text-decoration: underline; text-underline-offset: .3rem; }
.menu-occasions__declencheur::-webkit-details-marker { display: none; }
.menu-occasions__declencheur::after { content: "▾"; font-size: 1.1rem; transition: transform .15s ease; }
.menu-occasions details[open] .menu-occasions__declencheur::after,
.menu-occasions > details[open] > .menu-occasions__declencheur::after { transform: rotate(180deg); }
.menu-occasions__panneau { position: absolute; z-index: 20; left: 0; right: 0; top: 100%; margin-top: .6rem; padding: 1.2rem; background: rgb(var(--color-background)); border: .1rem solid rgba(var(--encre), .12); border-radius: var(--card-radius); box-shadow: 0 1.2rem 3rem rgba(var(--encre), .14); max-height: min(70vh, 52rem); overflow-y: auto; overscroll-behavior: contain; }
.menu-occasions__liste { display: grid; gap: .1rem; list-style: none; margin: 0; padding: 0; }
/* Cible tactile : 4,4 rem de haut, mesuré au navigateur — un menu de dix entrées serrées
   est un menu où l'on se trompe de ligne. */
/* Une seule colonne, une ligne par entrée : le symbole à gauche, le libellé, l'échéance
   poussée à droite. En deux colonnes, les quatre entrées datées faisaient deux lignes et les
   six autres une seule — les cellules ne s'alignaient plus d'une colonne à l'autre et le
   panneau partait en désordre. Dix lignes régulières se lisent plus vite que six colonnes
   ragotées. */
.menu-occasions__liste a { display: grid; grid-template-columns: auto 1fr auto; align-items: center; column-gap: 1.2rem; row-gap: .1rem; min-height: 4.4rem; padding: .6rem 1rem; border-radius: var(--card-radius); text-decoration: none; color: inherit; }
.menu-occasions__liste a:hover, .menu-occasions__liste a:focus-visible { background: rgb(var(--creme)); }
.menu-occasions__liste b { font-size: 1.5rem; font-weight: 500; }
.menu-occasions__liste small { font-size: 1.25rem; color: rgb(var(--encre-douce)); text-align: right; }
/* Le symbole suit la couleur du texte, et s'efface un peu : il aide à repérer la ligne,
   il ne doit pas la disputer au libellé. */
.icone-occasion { display: block; color: rgb(var(--brun)); opacity: .85; }
.menu-occasions__liste a:hover .icone-occasion { opacity: 1; }
/* La page courante : le symbole plein plutôt qu'une couleur de fond, qui se confondrait
   avec le survol. */
.menu-occasions__liste a[aria-current] { background: rgb(var(--creme)); }
.menu-occasions__liste a[aria-current] b { font-weight: 650; }
/* Sous 420 px, l'échéance passe sous le libellé plutôt que de comprimer les deux. */
@media screen and (max-width: 419px) {
  .menu-occasions__liste a { grid-template-columns: auto 1fr; }
  .menu-occasions__liste small { grid-column: 2; text-align: left; }
}
/* Le décompte des trente-cinq derniers jours : c'est lui qu'on vient chercher. */
.menu-occasions__urgent { color: rgb(var(--ocre-fonce)); font-weight: 600; }
@media screen and (min-width: 750px) {
  .menu-occasions { position: relative; }
  .menu-occasions__panneau { left: 0; right: auto; width: 40rem; }
}
/* Les deux icônes se touchent presque : c'est un groupe, pas deux entrées de menu — le
   gap de 2 rem de l'en-tête les aurait séparées comme deux rubriques. Quatre pixels
   suffisent à ne pas cliquer l'une pour l'autre, les cibles restant à 44 px. */
.header__actions { display: flex; align-items: center; gap: .4rem; justify-self: end; }
.header__icon { position: relative; display: inline-flex; width: 4.4rem; height: 4.4rem; align-items: center; justify-content: center; color: rgb(var(--color-foreground)); }
.header__icon .icon { width: 3rem; height: 3rem; }
/* Le bonhomme est plus petit que le panier dans sa boîte, et son trait plus fin : c'est ce
   qui les met au même poids. Mesuré au rendu, en comptant les pixels encrés — à 3 rem et
   1,6 d'épaisseur il faisait 21,6 px de haut pour 119 px² de matière, contre 16,8 px et
   47 px² au panier, soit **deux fois et demie** plus d'encre. Il écrasait son voisin. À
   2,3 rem et 1,15, les deux tombent à 16 px de haut et 50 px² de matière. Un dessin au
   trait ne se compare pas à un dessin plein à la taille de boîte : il se compare à l'encre. */
.header__icon--compte .icon { width: 2.3rem; height: 2.3rem; }
.cart-count-bubble { position: absolute; bottom: .4rem; right: .2rem; min-width: 1.7rem; height: 1.7rem; padding: 0 .4rem; border-radius: 100%; background: rgb(var(--color-accent)); color: #fff; font-size: .9rem; font-weight: 700; display: flex; align-items: center; justify-content: center; }
main { flex: 1; }
.footer { margin-top: 4rem; background: rgb(var(--gris)); font-size: 1.3rem; }
.footer__content { padding-top: 2.4rem; padding-bottom: 2.4rem; text-align: center; }

/* Boutons et champs */
.button, button.button { display: inline-flex; align-items: center; justify-content: center; min-height: 4.5rem; padding: 0 3rem; border: 0; border-radius: var(--buttons-radius); background: rgb(var(--color-button)); color: rgb(var(--color-button-text)); font-family: inherit; font-size: 1.5rem; letter-spacing: .1rem; line-height: 1; text-decoration: none; cursor: pointer; transition: box-shadow .15s ease; }
.button:hover { box-shadow: 0 0 0 .2rem rgba(var(--color-button), .35); }
.button:disabled { opacity: .5; cursor: not-allowed; box-shadow: none; }
.button--full-width { width: 100%; }
/* La même classe existe en anglais dans trois gabarits (`cart`, `404`) : même défaut, même
   remède que `.button--secondaire` plus bas — sans le préfixe, un <button> restait navy. */
.button--secondary, button.button--secondary { background: transparent; color: rgb(var(--color-foreground)); box-shadow: inset 0 0 0 .1rem rgba(var(--color-foreground), .5); }
.button--small { min-height: 3.6rem; padding: 0 1.6rem; font-size: 1.3rem; white-space: nowrap; }
.form__label { display: block; margin-bottom: .6rem; font-size: 1.3rem; }
.field__input, input[type="text"], input[type="number"], input[type="date"], input[type="email"], select, textarea { width: 100%; padding: 1.1rem 1.4rem; border: .1rem solid rgba(var(--color-foreground), .55); border-radius: var(--inputs-radius); background: rgb(var(--color-background)); color: rgb(var(--color-foreground)); font-family: inherit; font-size: 1.6rem; line-height: 1.4; }
input:focus-visible, select:focus-visible, textarea:focus-visible, button:focus-visible { outline: .2rem solid rgba(var(--color-accent), .8); outline-offset: .2rem; }
.form__message--error { margin: 0 0 1.2rem; padding: 1rem 1.4rem; border-radius: var(--inputs-radius); background: rgb(var(--rouge-fond)); color: rgb(var(--rouge)); font-size: 1.4rem; }
.error-msg { color: rgb(var(--rouge)); font-size: 1.3rem; }

/* Champs d'initiale : capitale automatique, dans la police de la graveuse. */
/* `input[type="text"]` de la feuille de base impose `font-family: inherit` :
   il faut la même spécificité pour que la police de la graveuse passe devant. */
input.gravure-initiale, .gravure-initiale {
  font-family: var(--font-gravure-family);
  font-weight: 400;
  text-transform: uppercase;
  text-align: center;
  letter-spacing: .1rem;
}
input.gravure-initiale::placeholder, .gravure-initiale::placeholder { text-transform: uppercase; opacity: .45; letter-spacing: .1rem; }
.personalization-recap__list dd.est-initiale { font-family: var(--font-gravure-family); font-weight: 500; letter-spacing: .12rem; }

/* Sélecteurs de variantes (pastilles) */
variant-selects { display: block; }
.product-form__input { margin: 0 0 1.6rem; padding: 0; border: 0; min-width: 0; }
.product-form__input--pill { display: flex; flex-wrap: wrap; gap: 0; }
.product-form__input--pill legend { padding: 0; margin-bottom: .2rem; }
.product-form__input--pill input[type="radio"] { position: absolute; opacity: 0; width: 0; height: 0; pointer-events: none; }
/* 4,4 rem de haut : la cible tactile minimale recommandée. Les pastilles faisaient 36 px,
   et ce sont les commandes les plus utilisées de la fiche — dix coloris, trois à cinq tailles. */
.product-form__input--pill label { display: inline-flex; align-items: center; min-height: 4.4rem; margin: .7rem .5rem .2rem 0; padding: 1rem 2rem; border: .1rem solid rgba(var(--color-foreground), .55); border-radius: var(--variant-pills-radius); font-size: 1.4rem; line-height: 1; cursor: pointer; transition: box-shadow .15s ease, background .15s ease; }
.product-form__input--pill label:hover { box-shadow: 0 0 0 .1rem rgb(var(--color-foreground)); }
.product-form__input--pill input[type="radio"]:checked + label { background: rgb(var(--color-foreground)); color: rgb(var(--color-background)); border-color: rgb(var(--color-foreground)); }
.product-form__input--pill input[type="radio"]:focus-visible + label { outline: .2rem solid rgba(var(--color-accent), .8); outline-offset: .2rem; }

/* Quantité */
/* 4,6 rem : 44 px de cible une fois la bordure retirée, pas 43. */
.quantity { display: inline-flex; align-items: center; height: 4.6rem; width: 14rem; border: .1rem solid rgba(var(--color-foreground), .55); border-radius: var(--inputs-radius); overflow: hidden; }
.quantity__button { width: 4.5rem; height: 100%; flex: 0 0 auto; border: 0; background: none; color: inherit; font-size: 2rem; cursor: pointer; }
.quantity__input { width: 100%; height: 100%; padding: 0; border: 0; border-radius: 0; text-align: center; font-size: 1.4rem; -moz-appearance: textfield; }
.quantity__input::-webkit-outer-spin-button, .quantity__input::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }

/* Fiche produit */
.grid { display: grid; gap: 2.4rem; }
.grid__item { min-width: 0; }
.product { align-items: start; }
@media screen and (min-width: 750px) { .grid--2-col-tablet { grid-template-columns: 55fr 45fr; gap: 4rem; } }
@media screen and (min-width: 990px) { .product__column-sticky { position: sticky; top: 2rem; } }
/* Galerie : carrousel à défilement calé sur mobile, toutes les photos empilées sur
   grand écran (charte des coloris, tableau des tailles, emballage cadeau — ce sont
   les arguments de vente, ils ne doivent pas rester cachés derrière des vignettes). */
.product__media-list { display: flex; gap: 1rem; margin: 0; padding: 0; list-style: none; overflow-x: auto; scroll-snap-type: x mandatory; scrollbar-width: none; -webkit-overflow-scrolling: touch; }
.product__media-list::-webkit-scrollbar { display: none; }
.product__media-item { flex: 0 0 100%; scroll-snap-align: center; min-width: 0; }
/* Sur mobile toutes les diapositives font la même hauteur (le défilement ne saute pas),
   mais rien n'est rogné : les visuels d'information (coloris, tailles, dimensions)
   doivent rester lisibles en entier. */
.product__media-image { display: block; width: 100%; aspect-ratio: 1; height: auto; object-fit: contain; border-radius: var(--card-radius); background: rgb(var(--gris)); }
.product__media-placeholder { aspect-ratio: 1; display: grid; place-items: center; background: rgb(var(--gris)); border-radius: var(--card-radius); color: rgba(var(--color-foreground), .5); }
.product__media-count { margin: .8rem 0 0; font-size: 1.2rem; letter-spacing: .1rem; color: rgba(var(--color-foreground), .65); text-align: center; }
.thumbnail-list { display: flex; gap: 1rem; margin: .8rem 0 0; padding: 0 0 .4rem; list-style: none; overflow-x: auto; }
.thumbnail { display: block; width: 8rem; height: 8rem; flex: 0 0 auto; padding: 0; border: .1rem solid rgba(var(--color-foreground), .1); border-radius: var(--card-radius); overflow: hidden; background: none; cursor: pointer; }
.thumbnail[aria-current="true"] { border-color: rgb(var(--color-foreground)); }
.thumbnail img { display: block; width: 100%; height: 100%; object-fit: cover; }
@media screen and (min-width: 750px) {
  .product__media-list { display: grid; grid-template-columns: repeat(2, 1fr); gap: 1.2rem; align-items: start; overflow: visible; }
  .product__media-item--full { grid-column: 1 / -1; }
  .product__media-image { aspect-ratio: auto; object-fit: fill; }
  .thumbnail-list, .product__media-count { display: none; }
}
/* Sur téléphone, la bande de vignettes coûtait 96 px sous une photo qui en fait déjà 360 —
   soit le titre et le prix repoussés d'autant, hors du premier écran. Le doigt fait déjà ce
   qu'elle propose (le carrousel est calé au défilement) et le compteur « 1 / 5 » dit combien
   il en reste : elle ne sert plus que sur une souris, où elle reste. */
@media screen and (max-width: 749px) {
  .thumbnail-list { display: none; }
  .product__media-count { margin-top: .6rem; }
}
.product__info-container > * + * { margin-top: 1.5rem; }
.product__text.caption-with-letter-spacing { margin: 0 0 .6rem; font-size: 1rem; letter-spacing: .13rem; text-transform: uppercase; }
.product__title { margin-top: 0; }
/* Résumé factuel de la fiche : cinquante mots au plus, entre le titre et le prix. C'est le
   premier texte que lit un visiteur pressé, et celui qu'un moteur génératif reprend. */
.product__resume { margin: 1.2rem 0 1.8rem; max-width: 60ch; color: rgba(var(--color-foreground), .85); }

.product__title h1 { font-size: 2.6rem; }
@media screen and (min-width: 750px) { .product__title h1 { font-size: 3rem; } }
.price { font-size: 1.8rem; letter-spacing: .1rem; }
.product__tax { margin-top: .4rem; color: rgba(var(--color-foreground), .75); }
.shipping-date { margin-top: 1.2rem; padding: 1rem 1.4rem; border-radius: var(--inputs-radius); background: rgb(var(--creme)); font-size: 1.4rem; }
.shipping-top { color: rgba(var(--color-foreground), .75); }
.product-form__buttons { margin-top: 1rem; }
/* 5,6 rem de haut : le bouton principal se touche du pouce sans viser, et il porte
   maintenant son prix — « Ajouter au panier — 23,90 € » tient sur une ligne dès 320 px. */
/* `button.` dans le sélecteur, sinon `button.button { min-height: 4.5rem }` reste devant :
   c'est la même spécificité 0-1-0 des deux côtés, et la règle générique gagne à l'ancienneté.
   La barre collante portait le même défaut, ses 4,8 rem n'ont jamais été appliqués. */
button.product-form__submit { margin-top: .5rem; min-height: 5.6rem; font-size: 1.6rem; }

/* ————— La preuve, une ligne sous le prix ————— */
/* Même forme que sur l'accueil : un chiffre de plus, pas un bloc, et un lien vers les avis.
   Le nombre d'avis n'y est pas (voir le gabarit). */
.product__preuve { margin: .6rem 0 0; font-size: 1.4rem; }
.product__preuve a { display: inline-flex; align-items: center; gap: .6rem; min-height: 4.4rem; color: inherit; text-decoration: none; }
.product__preuve a:hover, .product__preuve a:focus-visible { text-decoration: underline; }
.product__preuve-etoiles { color: rgb(var(--ocre-fonce)); letter-spacing: .08em; }

/* ————— Le choix, en étapes numérotées ————— */
/* Trois blocs s'étirent ici sur plus d'un écran et demi de téléphone. Sans repère, on ne
   sait ni où l'on en est ni s'il reste quelque chose à remplir — et c'est ce qui fait
   abandonner avant le bouton. La pastille numérotée est le seul ornement ajouté : elle
   remplace un titre de section, elle n'en ajoute pas un. */
.etape { margin: 0 0 2.4rem; }
.etape__titre { display: flex; align-items: baseline; flex-wrap: wrap; gap: .2rem .8rem; width: 100%; margin: 0 0 .2rem; padding: 0; font-size: 1.4rem; }
.etape__numero {
  flex: 0 0 auto; display: inline-grid; place-items: center; width: 2.2rem; height: 2.2rem;
  border-radius: 50%; background: rgb(var(--navy)); color: #fff;
  font-size: 1.2rem; font-weight: 600; line-height: 1; transform: translateY(.2rem);
}
.etape__nom { font-weight: 600; letter-spacing: .02rem; }
.etape__valeur { color: rgb(var(--brun)); }
.etape__manque { margin: 1.2rem 0 0; }

/* Les coloris, en photos. « MAJESTIC » ne dit pas de quelle couleur il s'agit, et la charte
   qui le montre est six écrans plus bas : personne ne fait l'aller-retour. Les photos sont
   celles de la planche, à la déclinaison de 200 px — donc déjà dans le cache quand on arrive
   en bas de page. Deux par ligne à 320 px, trois ensuite : la cible reste très au-dessus
   des 44 px. */
.product-form__input--pill.etape--coloris,
.product-form__input--pill.etape--taille { display: grid; gap: .8rem; }
/* 8,4 rem : c'est la largeur qui donne **trois colonnes dès 320 px** (3 × 84 + 2 × 8 = 268,
   pour 290 disponibles). À 9,6 rem il n'en tenait que deux, et les dix coloris faisaient cinq
   rangées — un demi-écran pour la première étape. Mesuré, pas supposé. */
.etape--coloris { grid-template-columns: repeat(auto-fill, minmax(8.4rem, 1fr)); }
.etape--coloris legend, .etape--taille legend { grid-column: 1 / -1; }
.product-form__input--pill.etape--coloris label,
.product-form__input--pill.etape--taille label {
  display: flex; margin: 0; border-radius: var(--card-radius);
  border: .1rem solid rgba(var(--color-foreground), .22);
  background: rgb(var(--color-background)); color: inherit;
}
.product-form__input--pill.etape--coloris label {
  flex-direction: column; align-items: stretch; gap: .4rem; padding: .5rem .5rem .7rem; text-align: center;
}
.choix__vignette { display: block; width: 100%; height: auto; border-radius: .4rem; background: rgb(var(--bordure)); }
.choix__nom { font-size: 1.2rem; line-height: 1.25; letter-spacing: .02rem; }
/* Le choix retenu se marque par un cerne et un fond, jamais par un aplat : un aplat sombre
   recouvrirait la photo du cordon, qui est justement ce qu'on regarde. */
.product-form__input--pill.etape--coloris input[type="radio"]:checked + label,
.product-form__input--pill.etape--taille input[type="radio"]:checked + label {
  background: rgb(var(--creme)); color: inherit;
  border-color: rgb(var(--color-foreground));
  box-shadow: inset 0 0 0 .1rem rgb(var(--color-foreground));
}

/* Les tailles disent leur mesure. « 2: Homme Standard » ne répond pas à la question posée,
   qui est « est-ce que ça ira à mon poignet » ; « 18–21 cm » y répond. Le relevé vient des
   planches d'origine (`planches.POIGNET`), il n'est pas réinventé ici. */
.etape--taille { grid-template-columns: repeat(auto-fit, minmax(13rem, 1fr)); }
.product-form__input--pill.etape--taille label {
  flex-direction: column; align-items: flex-start; justify-content: center;
  gap: .2rem; min-height: 5.4rem; padding: .9rem 1.4rem;
}
.etape--taille .choix__nom { font-size: 1.4rem; }
.choix__mesure { font-size: 1.3rem; color: rgb(var(--brun)); font-variant-numeric: tabular-nums; }
.product-form__input--pill.etape--taille input[type="radio"]:checked + label .choix__mesure { color: rgb(var(--encre-douce)); }

/* ————— Le bloc de personnalisation importé ————— */
/* Son HTML n'est pas le nôtre et l'import le réécrit : les corrections vivent ici. Elles ne
   visent **aucune** des classes d'origine — il y en a une douzaine pour les mêmes trois
   objets — mais le vocabulaire commun que `lib/customizer.js` pose sur les blocs à partir de
   leur forme : `perso` le cadre, `perso__grille` une grille de choix, `perso__choix` une
   vignette, `perso__champ` un champ de saisie.
   Le `!important` est nécessaire et il est de règle ici : le `<style>` du bloc est dans le
   corps du document, donc après cette feuille, et la moitié des blocs habillent leur cadre
   avec des styles en ligne, que seul `!important` dépasse. Même raison que les deux
   contrastes corrigés plus bas. */
.etape--gravure > .perso {
  margin: 0 0 1.2rem !important;
  padding: 1.4rem !important;
  border: .1rem solid rgba(var(--color-foreground), .22) !important;
  border-radius: var(--card-radius) !important;
  background: rgb(var(--color-background)) !important;
}
.etape--gravure > .perso:last-of-type { margin-bottom: 0 !important; }
/* La bannière du bloc redit le titre de l'étape : elle s'efface en mention, elle ne
   disparaît pas — c'est elle qui dit « obligatoire ». */
.etape--gravure .perso__banniere {
  margin: 0 0 1.2rem !important; font-size: 1.2rem !important; font-weight: 500 !important;
  text-align: left !important; letter-spacing: .08rem !important;
  color: rgb(var(--encre-pale)) !important;
}
.etape--gravure .perso__label {
  display: block !important; margin: 1.6rem 0 .8rem !important;
  font-size: 1.4rem !important; font-weight: 600 !important; color: inherit !important;
}
.etape--gravure .perso > .perso__label:first-child,
.etape--gravure .perso__banniere + .perso__label { margin-top: 0 !important; }

/* Les grilles de choix. Deux colonnes sous 360 px — à quatre, chaque cellule tombait à 62 px
   et le dessin devenait illisible dès qu'un nom passait à deux lignes (« Coeurs
   entrelacés ») —, puis des colonnes de 7,4 rem au moins, ce qui donne quatre choix à
   390 px et six aux douze signes du zodiaque sur grand écran. */
.etape--gravure .perso__grille {
  display: grid !important; grid-template-columns: repeat(2, minmax(0, 1fr)) !important;
  gap: .8rem !important; margin: 0 !important; padding: 0 !important; list-style: none;
  /* Deux blocs posent leur grille dans une colonne centrée (`align-items: center`) : sans
     largeur imposée, elle se rétracte à la taille d'une vignette et les choix s'empilent
     un par rangée. */
  width: 100% !important;
}
@media screen and (min-width: 360px) {
  .etape--gravure .perso__grille {
    grid-template-columns: repeat(auto-fit, minmax(7.4rem, 1fr)) !important; gap: .6rem !important;
  }
}
/* La colonne qui porte une grille de choix prend la place qui reste, et **à toutes les
   largeurs** : deux blocs rangent la gravure en rangée (initiale, symboles, initiale) sans
   donner à la grille de quoi s'étendre, si bien qu'elle tenait dans 74 px — quatre symboles
   l'un sous l'autre, sur mobile comme sur grand écran. Le premier correctif ne visait que le
   téléphone et laissait l'ordinateur en l'état : mesuré, pas supposé.
   Sous 750 px elle passe en dessous, sur toute la largeur, et les deux initiales restent
   côte à côte sur la ligne du dessus. */
.etape--gravure .perso__rangee { flex-wrap: wrap !important; }
.etape--gravure .perso__large { flex: 1 1 22rem !important; min-width: 0 !important; }
@media screen and (max-width: 749px) {
  .etape--gravure .perso__large { flex-basis: 100% !important; width: 100% !important; order: 1; margin-top: 1.2rem; }
}

/* Une vignette est une cible tactile avant d'être une image : 8,8 rem de haut, le dessin
   au-dessus, le nom dessous, et le même cerne que les pastilles de coloris quand elle est
   choisie — un aplat sombre recouvrirait le dessin, qui est ce qu'on regarde. */
.etape--gravure .perso__choix {
  width: 100% !important; height: auto !important; min-height: 8.8rem;
  margin: 0 !important; padding: .8rem .4rem !important;
  border: .1rem solid rgba(var(--color-foreground), .22) !important;
  border-radius: var(--card-radius) !important;
  background: rgb(var(--color-background)) !important;
  font: inherit; color: inherit !important; text-align: center; cursor: pointer;
  display: flex !important; flex-direction: column; align-items: center; justify-content: center;
  gap: .6rem; overflow-wrap: anywhere;
}
/* Un bloc estompe les symboles non choisis à 60 % : c'était son affordance de sélection, le
   cerne et le fond la portent maintenant, et un dessin délavé à côté de treize fiches nettes
   se lit comme une image qui n'a pas fini de charger. */
/* Une boîte plus large que haute : les dessins vont du carré (poisson, valknut) au paysage
   très allongé (les sept sommets, 460 x 300). Un carré de 3,6 rem rendait un Everest de
   36 x 23 px, où il ne restait plus de montagne. */
.etape--gravure .perso__choix img,
.etape--gravure .perso__choix svg {
  width: 100% !important; max-width: 5.6rem !important; height: 4rem !important;
  object-fit: contain; margin: 0 !important; opacity: 1 !important;
}
/* La moitié des blocs habillent le `<label>` d'une vignette radio — cadre, fond, ombre de
   sélection — et l'autre moitié habillent la vignette elle-même. Les deux à la fois donnent
   un cadre dans un cadre. C'est la vignette qui porte la surface, partout : le libellé
   redevient du texte. */
.etape--gravure .perso__choix span,
.etape--gravure .perso__choix label {
  display: block !important; margin: 0 !important; padding: 0 !important;
  border: 0 !important; background: none !important; box-shadow: none !important;
  height: auto !important; width: auto !important;
  font-size: 1.15rem !important; font-weight: 500 !important; line-height: 1.2;
  color: rgb(var(--color-foreground)) !important; cursor: pointer;
}
/* Le dessin ajouté dans un choix qui n'en avait pas (`customizer.illustrerLesChoix`) : il
   passe avant le libellé, la vignette étant une colonne. */
.etape--gravure .perso__choix .perso__dessin { order: -1; }
/* Les glyphes du zodiaque sont du texte, pas une image : ils prennent la place du dessin. */
.etape--gravure .perso__choix .icon { font-size: 2.8rem !important; line-height: 1 !important; }
/* Le bouton radio d'une vignette ne s'affiche pas : c'est la vignette entière qui est la
   cible, et son `<label>` la couvre. Il reste focalisable au clavier, donc atteignable. */
.etape--gravure .perso__choix input[type="radio"] {
  position: absolute; width: 1px; height: 1px; opacity: 0; margin: 0; pointer-events: none;
}
.etape--gravure .perso__choix { position: relative; }
.etape--gravure .perso__choix label { position: static; }
.etape--gravure .perso__choix label::after { content: ""; position: absolute; inset: 0; }
.etape--gravure .perso__choix:hover { border-color: rgba(var(--color-foreground), .5) !important; }
.etape--gravure .perso__choix.selected,
.etape--gravure .perso__choix:has(input[type="radio"]:checked) {
  border-color: rgb(var(--color-foreground)) !important;
  background: rgb(var(--creme)) !important;
  box-shadow: inset 0 0 0 .1rem rgb(var(--color-foreground));
}
/* Deux formes de vignette, deux façons de recevoir le focus : celle qui enferme un bouton
   radio le reçoit par lui, celle qui est elle-même un bouton le reçoit directement. Il
   fallait les deux règles — la seconde forme est celle que ces retouches ont créée, et elle
   ne tenait que par le `button:focus-visible` générique de la feuille. */
.etape--gravure .perso__choix:has(input[type="radio"]:focus-visible),
.etape--gravure .perso__choix:focus-visible {
  outline: .2rem solid rgba(var(--color-accent), .8); outline-offset: .2rem;
}

/* Les champs de saisie : une seule hauteur, une seule police, quel que soit le bloc. Les
   1,6 rem sont ce qui évite à iOS de zoomer sur la page et de ne jamais revenir. */
.etape--gravure .perso__champ {
  width: 100% !important; min-height: 5rem !important; padding: 1rem 1.2rem !important;
  font-size: 1.6rem !important;
  border: .1rem solid rgba(var(--color-foreground), .35) !important;
  border-radius: var(--inputs-radius) !important;
  background: rgb(var(--color-background)) !important; color: inherit !important;
}
/* Les initiales et le numéro de département se lisent comme ils seront gravés : en capitale,
   au centre, dans la police de la graveuse. */
.etape--gravure .gravure-initiale,
.etape--gravure input[name="properties[Département]"] {
  height: 5.4rem !important; font-size: 2.4rem !important; text-align: center !important;
}
.etape--gravure .perso__erreur {
  display: block; margin: 1.2rem 0 0 !important; padding: 1rem 1.4rem !important;
  border-radius: var(--inputs-radius); background: rgb(var(--rouge-fond)) !important;
  color: rgb(var(--rouge)) !important; font-size: 1.4rem !important; font-weight: 500 !important;
  text-align: left !important;
}

/* Le prix répété sur le bouton d'achat : à ce moment-là le bloc de prix est sorti de l'écran
   depuis longtemps. Le tiret est décoratif, le prix est `aria-hidden` (voir le gabarit). */
.product-form__prix::before { content: "—"; margin: 0 .8rem; opacity: .6; }
.product-form__prix { font-weight: 600; }
/* Agrandissement : la charte des coloris et le tableau des tailles portent du texte
   qui n'est pas lisible à 285 px de large. */
/* ---------------------------------------------------------------- le bloc de gravure
   L'aperçu dessiné qui vivait ici a été retiré le 17 sept. 2026 (Fred) : ses quatre règles
   partent avec lui, elles étaient du chemin critique sur toutes les pages. Ce qui reste met en
   forme le **bloc de personnalisation** lui-même, qui n'a pas changé. */
/* Un groupe de choix garde son `<fieldset>` et sa `<legend>` : c'est ce qui le nomme à un
   lecteur d'écran. `normaliser` ne pose `perso__label` que sur les `<label>`, la légende
   reprend donc la même mise en forme ici plutôt que de renoncer au groupe. */
.etape--gravure .gravure__bloc { margin: 0 0 1.6rem; padding: 0; border: 0; }
.etape--gravure .gravure__bloc:last-child { margin-bottom: 0; }
.etape--gravure .gravure__bloc > legend.form__label {
  display: block; margin: 0 0 .8rem; padding: 0; font-size: 1.4rem; font-weight: 600;
}
/* `.perso__erreur` est un encadré rouge posé par la feuille commune : vide, il resterait
   affiché en permanence sous chaque champ. */
.etape--gravure .gravure__erreur:empty { display: none !important; }

.product__media-item { cursor: zoom-in; }
.media-lightbox { position: fixed; inset: 0; z-index: 100; display: flex; align-items: center; justify-content: center; padding: 2rem; border: 0; background: rgba(0, 0, 0, .88); cursor: zoom-out; }
.media-lightbox img { max-width: 100%; max-height: 100%; width: auto; height: auto; object-fit: contain; border-radius: var(--card-radius); }
.media-lightbox__close { position: absolute; top: 1.2rem; right: 1.2rem; width: 4.4rem; height: 4.4rem; display: grid; place-items: center; border: 0; border-radius: 100%; background: rgba(255, 255, 255, .15); color: #fff; font-size: 2.4rem; line-height: 1; cursor: pointer; }
.media-lightbox__close:hover { background: rgba(255, 255, 255, .3); }

/* Vidéo : vignette locale, l'iframe YouTube n'est insérée qu'au clic — aucune
   requête vers youtube.com / doubleclick.net tant que le visiteur n'a rien demandé. */
.product-youtube-video { position: relative; border-radius: var(--card-radius); overflow: hidden; }
.video-facade { display: block; width: 100%; padding: 0; border: 0; background: #000; cursor: pointer; position: relative; line-height: 0; }
.video-facade img { display: block; width: 100%; height: auto; aspect-ratio: 16 / 9; object-fit: cover; opacity: .85; transition: opacity .2s ease, transform .4s ease; }
.video-facade:hover img { opacity: 1; transform: scale(1.02); }
.video-facade__play { position: absolute; inset: 0; margin: auto; width: 6.8rem; height: 4.8rem; border-radius: 1.2rem; background: rgba(0, 0, 0, .7); transition: background .2s ease; }
.video-facade:hover .video-facade__play { background: rgb(var(--rouge)); }
.video-facade__play::after { content: ""; position: absolute; inset: 0; margin: auto; width: 0; height: 0; border-left: 1.7rem solid #fff; border-top: 1.05rem solid transparent; border-bottom: 1.05rem solid transparent; }
.video-facade::after { content: ""; position: absolute; left: 0; right: 0; bottom: 0; height: 6rem; background: linear-gradient(rgba(0, 0, 0, 0), rgba(0, 0, 0, .55)); pointer-events: none; }
.video-facade__label { position: absolute; left: 1.4rem; bottom: 1.2rem; z-index: 1; color: #fff; font-size: 1.3rem; line-height: 1.4; letter-spacing: .05rem; text-shadow: 0 .1rem .3rem rgba(0, 0, 0, .7); }
.product-youtube-video--playing { height: 0; padding-bottom: 56.25%; }
.product-youtube-video iframe { position: absolute; inset: 0; width: 100%; height: 100%; border: 0; }

/* Récapitulatif de personnalisation, juste au-dessus du bouton d'achat : ce qui
   partira à la gravure, y compris les champs calculés (latitude, longitude…). */
.personalization-recap { padding: 1.2rem 1.4rem; border-radius: var(--inputs-radius); background: rgb(var(--creme)); border: .1rem solid rgba(var(--color-foreground), .1); }
.personalization-recap__title { margin: 0 0 .8rem; font-size: 1.1rem; letter-spacing: .13rem; text-transform: uppercase; color: rgba(var(--color-foreground), .7); }
.personalization-recap__list { margin: 0; font-size: 1.5rem; }
.personalization-recap__row { display: flex; gap: 1.2rem; align-items: baseline; justify-content: space-between; }
.personalization-recap__row + .personalization-recap__row { margin-top: .4rem; }
.personalization-recap__list dt { color: rgba(var(--color-foreground), .7); font-size: 1.3rem; }
.personalization-recap__list dd { margin: 0; font-weight: 600; text-align: right; overflow-wrap: anywhere; }
.personalization-recap__note { margin: .9rem 0 0; color: rgba(var(--color-foreground), .7); }
/* La description est maintenant un `<details>` comme les planches : elle garde son filet
   de séparation, et ses titres de niveau 2 internes redescendent d'un cran visuellement —
   sinon le titre du repli et le premier titre du texte importé pèsent pareil. */
.product__description { margin-top: 3rem; padding-top: 2rem; border-top: .1rem solid rgba(var(--color-foreground), .08); }
.product__description > .rte > h2:first-child { font-size: 1.9rem; margin-top: 0; }

/* Accueil */

/* Collection */
.collection-hero__title { margin-bottom: .6rem; }
.collection-hero__description { max-width: 70rem; }
.collection-product-count { margin: 1.6rem 0; font-size: 1.3rem; color: rgba(var(--color-foreground), .7); }
.product-grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: 1.6rem 1.2rem; margin: 0; padding: 0; list-style: none; }
@media screen and (min-width: 750px) { .product-grid { grid-template-columns: repeat(3, 1fr); gap: 3rem 2.4rem; } }
@media screen and (min-width: 990px) { .product-grid { grid-template-columns: repeat(4, 1fr); } }
.card__media { display: block; overflow: hidden; border-radius: var(--card-radius); background: rgb(var(--gris)); }
.card__media img { display: block; width: 100%; aspect-ratio: 1; object-fit: cover; transition: transform .4s ease; }
.card:hover .card__media img { transform: scale(1.03); }
.card__heading { margin: 1.2rem 0 .4rem; font-size: 1.4rem; line-height: 1.4; }
.card__heading a { text-decoration: none; }
.card__heading a:hover { text-decoration: underline; text-underline-offset: .3rem; }
.card__price { font-size: 1.4rem; }

/* Panier */
.cart__header { display: flex; align-items: baseline; justify-content: space-between; gap: 2rem; margin-bottom: 2.4rem; }
.cart__empty-text { font-size: 1.8rem; margin: 3rem 0 2rem; }
/* Les deux chemins du catalogue, côte à côte sur grand écran et empilés sur téléphone —
   jamais deux boutons serrés l'un contre l'autre sous le pouce. */
.cart__reprendre { display: flex; flex-wrap: wrap; gap: 1.2rem; margin: 0; }
/* Sur téléphone chaque bouton prend la ligne ; au-delà, ils se dimensionnent sur leur
   texte. Les laisser s'étirer sur toute la largeur donnait deux barres de 544 px pour
   trois mots — le lien le plus large de la page pour l'action la moins engageante. */
.cart__reprendre .button { flex: 1 1 100%; }
@media screen and (min-width: 750px) { .cart__reprendre .button { flex: 0 0 auto; } }
.cart-items { border-top: .1rem solid rgba(var(--color-foreground), .1); }
.cart-item { display: grid; grid-template-columns: 9rem 1fr; gap: 1.6rem; padding: 2rem 0; border-bottom: .1rem solid rgba(var(--color-foreground), .1); }
@media screen and (min-width: 750px) { .cart-item { grid-template-columns: 12rem 1fr 22rem 10rem; align-items: start; } }
.cart-item__media img { display: block; width: 100%; aspect-ratio: 1; object-fit: cover; border-radius: var(--card-radius); background: rgb(var(--gris)); }
.cart-item__name { display: block; font-size: 1.6rem; text-decoration: none; margin-bottom: .6rem; }
.product-option { margin: 0; font-size: 1.3rem; color: rgba(var(--color-foreground), .8); }
.product-option dt, .product-option dd { display: inline; margin: 0; }
.product-option dt { color: rgba(var(--color-foreground), .6); }
.product-option--properties { margin-top: .4rem; padding: .8rem 1rem; border-radius: var(--inputs-radius); background: rgb(var(--creme)); }
.product-option--properties div + div { margin-top: .2rem; }
.cart-item__price { margin-top: .8rem; font-size: 1.3rem; }
.cart-item__quantity { display: flex; flex-direction: column; gap: .8rem; }
.cart-item__quantity-form { display: flex; gap: .8rem; align-items: center; }
.cart-item__quantity-form .quantity__input { width: 7rem; height: 3.6rem; border: .1rem solid rgba(var(--color-foreground), .55); border-radius: var(--inputs-radius); }
.cart-remove-button { font-size: 1.3rem; align-self: flex-start; }
.cart-item__totals { font-size: 1.6rem; text-align: right; grid-column: 2; }
@media screen and (min-width: 750px) { .cart-item__totals { grid-column: auto; } }
.cart__footer { max-width: 40rem; margin: 2.4rem 0 0 auto; }
.totals { display: flex; justify-content: space-between; align-items: baseline; font-size: 1.8rem; }
.totals__total-value { font-size: 2.2rem; }
.tax-note { margin: .8rem 0 1.6rem; color: rgba(var(--color-foreground), .7); }

/* Planches d'information reconstruites (coloris, tailles, dimensions, emballage).
   Elles remplacent des images dont le texte était gravé dans le pixel : la mise en page
   doit donc rester lisible à 285 px de large, là où l'image ne l'était pas. */
/* Les planches vivent dans la colonne de gauche, sous les photos — c'est là qu'elles
   étaient sur la boutique d'origine, où elles n'étaient que des images de la galerie.
   Dans le HTML elles viennent en dernier, donc en dernier sur mobile : le bouton d'achat
   reste haut. C'est la grille qui les remonte à gauche sur grand écran. */
.planche { margin-top: 3.2rem; padding-top: 2.4rem; border-top: 0.1rem solid rgba(var(--encre), .12); }
.planche__titre { font-size: 1.6rem; margin: 0 0 1.6rem; letter-spacing: .04rem; text-transform: uppercase; }
/* Les planches d'une fiche sont des `<details>` : sur téléphone elles forment sinon un mur
   de plusieurs écrans entre le bouton d'achat et le bas de page, et on ne sait plus ce qu'il
   reste à lire. `product.js` les déplie au-delà de 750 px ; sans JavaScript elles restent
   repliées, leur contenu étant dans le HTML (donc indexé) et atteignable en un geste.
   Le titre reste un `<h2>` **dans** le `<summary>` : le plan du document ne bouge pas. */
details.planche > summary.planche__titre {
  display: flex; align-items: center; justify-content: space-between; gap: 1.6rem;
  min-height: 4.4rem; margin: 0; cursor: pointer; list-style: none;
}
details.planche > summary.planche__titre::-webkit-details-marker { display: none; }
details.planche > summary.planche__titre h2 { font: inherit; letter-spacing: inherit; text-transform: inherit; margin: 0; }
/* Le chevron est dessiné en CSS : une image de plus pour une flèche serait une requête de
   trop, et il suit la couleur du texte. */
details.planche > summary.planche__titre::after {
  content: ""; flex: 0 0 auto; width: .9rem; height: .9rem; margin-right: .4rem;
  border-right: .17rem solid currentColor; border-bottom: .17rem solid currentColor;
  transform: rotate(45deg) translate(-.2rem, -.2rem); opacity: .55; transition: transform .15s ease;
}
details.planche[open] > summary.planche__titre::after { transform: rotate(-135deg) translate(-.2rem, -.2rem); }
details.planche > summary.planche__titre:focus-visible { outline: .2rem solid rgba(var(--color-accent), .8); outline-offset: .2rem; }
details.planche[open] > summary.planche__titre { margin-bottom: 1.6rem; }
.planche__sous-titre { font-size: 1.4rem; margin: 0 0 .6rem; }
.planche__note { margin-top: 1.2rem; opacity: .75; }

.planche__cordons { display: grid; grid-template-columns: repeat(2, 1fr); gap: 1.6rem 1.2rem; list-style: none; padding: 0; margin: 0; }
@media screen and (min-width: 750px) { .planche__cordons { grid-template-columns: repeat(3, 1fr); } }
.planche__cordon { text-align: center; }
.planche__cordon img { width: 100%; height: auto; border-radius: .6rem; background: rgb(var(--bordure)); }
.planche__cordon span { display: block; margin-top: .4rem; font-size: 1.2rem; letter-spacing: .04rem; }

.planche__tailles { width: 100%; border-collapse: collapse; font-size: 1.4rem; }
.planche__tailles th, .planche__tailles td { text-align: left; padding: .8rem 0; border-bottom: 0.1rem solid rgba(var(--encre), .1); }
.planche__tailles thead th { font-size: 1.2rem; text-transform: uppercase; letter-spacing: .04rem; opacity: .7; }
.planche__tailles tbody th { font-weight: 500; }
.planche__tailles td { text-align: right; white-space: nowrap; }

.planche__mesurer { display: grid; gap: 1.2rem; margin-top: 1.6rem; }
@media screen and (min-width: 750px) { .planche__mesurer { grid-template-columns: 26rem 1fr; align-items: center; gap: 1.8rem; } }
.planche__mesurer img { width: 100%; height: auto; border-radius: .6rem; }
.planche__mesurer p { margin: 0; }

/* Tableau des caractéristiques : libellé à gauche, valeur à droite, une ligne par fait.
   C'est la forme qu'un moteur ou un assistant extrait sans se tromper — et elle remplace
   la planche « dimensions », qui disait la même chose en image puis en liste. */
.planche__carac { width: 100%; border-collapse: collapse; font-size: 1.4rem; }
.planche__carac th, .planche__carac td { padding: .9rem 0; border-bottom: 0.1rem solid rgba(var(--encre), .1); vertical-align: top; text-align: left; }
.planche__carac th { width: 38%; padding-right: 1.6rem; font-weight: 500; font-size: 1.2rem; text-transform: uppercase; letter-spacing: .04rem; opacity: .7; }
.planche__carac td { font-variant-numeric: tabular-nums; }

/* « Idéal pour » et « à savoir avant de commander ». Les deux marqueurs se distinguent au
   premier regard : une fiche qui n'annonce aucune réserve n'est pas crue, et la réserve lue
   à temps évite la commande qu'on regrette — sur un objet gravé, c'est le sujet. */
.planche__liste { list-style: none; padding: 0; margin: 0; display: grid; gap: .9rem; }
.planche__liste li { position: relative; padding-left: 2.2rem; max-width: 70ch; }
.planche__liste li::before { position: absolute; left: 0; top: 0; font-weight: 600; opacity: .6; }
.planche__liste--oui li::before { content: "✓"; }
.planche__liste--non li::before { content: "!"; }
.planche__titre--limites { margin-top: 2.8rem; }
.planche--conseils p { max-width: 70ch; }
.planche__intro { margin: -0.5rem 0 1.6rem; }
.planche__symboles { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 2rem 1.2rem; list-style: none; padding: 0; margin: 0; }
@media screen and (min-width: 750px) { .planche__symboles { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
/* Chaque symbole a ses propres proportions : la vignette s'inscrit dans une boîte de
   rapport fixe (`contain`, jamais `cover` — un symbole rogné n'est plus le symbole).
   Les cellules gardent ainsi la même hauteur, et les libellés s'alignent quelle que soit
   la langue, y compris quand l'allemand rallonge le texte. */
.planche__symboles { align-items: start; }
/* Quatre symboles tiennent mieux en 2 × 2 qu'en 3 + 1 orphelin, et gagnent en taille. */
.planche__symboles--peu { grid-template-columns: repeat(2, minmax(0, 1fr)); }
@media screen and (min-width: 750px) { .planche__symboles--peu { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
/* Les symboles vikings portent un paragraphe chacun : une colonne, vignette à gauche. */
.planche__symboles--texte { grid-template-columns: 1fr; gap: 1.6rem; }
@media screen and (min-width: 750px) { .planche__symboles--texte { grid-template-columns: 1fr; } }
.planche__symboles--texte .planche__symbole {
  display: grid; grid-template-columns: 8rem 1fr; grid-template-rows: auto auto 1fr;
  gap: .4rem 1.2rem; text-align: left; align-items: start;
}
/* La vignette tient les deux rangées, le titre et le texte occupent la colonne de droite :
   sans ce placement, le paragraphe retombe sous la vignette, dans les 8 rem. */
/* La vignette couvre les **trois** rangées, dont la dernière est vide et élastique : avec
   deux rangées seulement, la hauteur de la vignette se répartissait entre elles et le nom
   se retrouvait à un demi-centimètre de la phrase qu'il annonce. */
.planche__symboles--texte .planche__symbole img { grid-column: 1; grid-row: 1 / -1; aspect-ratio: 1; }
.planche__symboles--texte .planche__symbole .planche__sous-titre { grid-column: 2; grid-row: 1; margin-top: 0; }
.planche__symboles--texte .planche__symbole p { grid-column: 2; grid-row: 2; }
.planche__symbole { display: flex; flex-direction: column; text-align: center; }
/* Pas de fond ni de retrait ajoutés : la vignette porte déjà celui de sa planche d'origine,
   en superposer un second dessinait un rectangle clair dans une tuile grise. */
.planche__symbole img {
  display: block; width: 100%; aspect-ratio: 4 / 3; object-fit: contain;
  border-radius: .6rem; background: #fff;
}
.planche__symbole .planche__sous-titre { margin-top: .8rem; }
.planche__symbole p { margin: 0; font-size: 1.3rem; text-align: left; }
/* La période d'un signe se lit sous son nom, en retrait : c'est ce qu'on vient chercher
   quand on ne connaît pas le sien. Centrée comme le nom, et non alignée à gauche comme les
   descriptions vikings — d'où la règle après celle qui les couvre. */
.planche__symbole .planche__periode { margin-top: .2rem; font-size: 1.2rem; text-align: center; opacity: .7; }

/* Deux colonnes indépendantes, pas deux rangées : la colonne d'achat est plus haute que
   les photos, et si elle s'étale sur deux rangées de grille elle gonfle la première — d'où
   un demi-écran de vide entre les vignettes et la première planche. Photos et planches sont
   donc réunies dans une seule colonne, qui les empile simplement.
   Sur mobile cette colonne s'efface (`display: contents`) pour que ses enfants redeviennent
   des éléments de la grille : l'ordre remet alors l'achat avant les planches, et le bouton
   reste haut. */
@media screen and (max-width: 749px) {
  .product__colonne { display: contents; }
  .product__media-wrapper { order: 1; }
  .product__info-wrapper { order: 2; }
  .product__planches { order: 3; }
}
@media screen and (min-width: 750px) {
  .product__colonne { display: flex; flex-direction: column; gap: 2.4rem; min-width: 0; }
}

/* Sélecteur de langue de l'en-tête : présent sur toutes les pages, en vrais liens vers
   l'URL de la page dans chaque langue. Les codes à deux lettres tiennent sur un téléphone
   là où les noms de langue ne tiendraient pas. */
.header__langues { display: flex; gap: .2rem; align-items: center; }
.header__langue {
  display: inline-block; padding: .5rem .6rem; font-size: 1.2rem; line-height: 1;
  text-transform: uppercase; letter-spacing: .06rem; text-decoration: none; border-radius: .4rem;
  color: rgba(var(--color-foreground), .65);
}
.header__langue:hover { color: rgb(var(--color-foreground)); background: rgba(var(--color-foreground), .06); }
.header__langue--actuelle { color: rgb(var(--color-foreground)); font-weight: 600; }
.header__langue:focus-visible { outline: .2rem solid rgba(var(--color-accent), .8); outline-offset: .2rem; }
/* Sous 750 px, le menu prend sa propre rangée.
   Sur une seule rangée, la piste `1fr` du menu a un `min-width: auto` implicite : elle
   refuse de descendre sous sa largeur min-content (197 px en français, 204 en allemand).
   Le total incompressible atteignait 371 px, la page défilait latéralement de 44 px sur un
   iPhone SE — et le panier sortait entièrement de l'écran : un client qui venait d'ajouter
   au panier ne pouvait plus l'ouvrir. Le logo, servi en dernier, tombait à 0 px. */
@media screen and (max-width: 749px) {
  .header {
    gap: .8rem;
    grid-template-columns: auto 1fr auto;
    grid-template-areas: "logo langues actions" "menu menu menu";
    row-gap: .4rem;
  }
  .header__heading-link { grid-area: logo; }
  .header__inline-menu { grid-area: menu; min-width: 0; }
  .header__langues { grid-area: langues; justify-self: end; }
  .header__actions { grid-area: actions; }
  .header__logo { width: 5.6rem; height: 5.6rem; }
  .header__inline-menu .list-menu { gap: .8rem 1.6rem; }
  /* Cible tactile : 1,55 rem de marge intérieure verticale portent le lien à 44 px de
     haut, mesuré au navigateur — la valeur précédente n'en donnait que 34. */
  .header__langue { padding: 1.65rem .7rem; font-size: 1.1rem; }
}

/* iOS zoome sur tout champ de saisie dont la police est sous 16 px, et ne revient jamais à
   l'échelle initiale : le client tape son adresse sur une page dont le bouton d'achat est
   sorti du cadre. Le bloc de personnalisation importé impose 1,4 rem à ses champs, et son
   `<style>` est dans le corps du document, donc après cette feuille : il faut une
   spécificité de 0-2-1 pour repasser devant. Le HTML du bloc n'est pas le nôtre — l'import
   le réécrit à chaque fois —, la correction vit donc ici. */
.product__info-container input.field__input[type="text"],
.product__info-container input.field__input[type="email"],
.product__info-container input.field__input[type="search"],
.fiche-produit input[type="text"], .fiche-produit input[type="search"],
.fiche-produit input[type="date"], .fiche-produit input[type="time"],
.fiche-produit textarea { font-size: 1.6rem; }

/* ————— Le blog ————— */
.blog__titre { margin: 0 0 1.2rem; }
.blog__intro { max-width: 62ch; margin: 0 0 4rem; font-size: 1.7rem; color: rgb(var(--encre-douce)); }
.blog__liste { display: grid; gap: 1.6rem; list-style: none; margin: 0; padding: 0; }
@media screen and (min-width: 750px) { .blog__liste { grid-template-columns: 1fr 1fr; gap: 2.4rem; } }
.blog__carte a { display: block; height: 100%; padding: 2.4rem; border: .1rem solid rgba(var(--encre), .12); border-radius: var(--card-radius); text-decoration: none; color: inherit; transition: background .15s ease; }
.blog__carte a:hover { background: rgb(var(--creme)); }
.blog__carte time { font-size: 1.2rem; letter-spacing: .06em; text-transform: uppercase; color: rgb(var(--brun)); }
.blog__carte h2 { margin: .8rem 0 1rem; font-size: 2rem; line-height: 1.25; }
.blog__carte p { margin: 0 0 1.6rem; color: rgb(var(--encre-douce)); }
.blog__lire { font-weight: 600; text-decoration: underline; text-underline-offset: .3rem; }

/* Un article. La mesure de ligne est bornée : au-delà de 70 signes l'œil perd le début de
   la ligne suivante, et un article se lit en entier ou pas du tout. */
.article { max-width: 78rem; }
.article__fil { font-size: 1.3rem; color: rgb(var(--encre-douce)); margin-bottom: 2.4rem; }
.article__fil a { color: inherit; }
.article__titre { margin: 0 0 1.2rem; }
.article__date { font-size: 1.3rem; letter-spacing: .06em; text-transform: uppercase; color: rgb(var(--brun)); margin: 0 0 2.4rem; }
.article__chapo { font-size: 1.9rem; line-height: 1.5; margin: 0 0 3.2rem; }
.article__reponse-courte { margin: -1.2rem 0 3.2rem; padding: 1.6rem 1.8rem; line-height: 1.65; background: rgb(var(--creme)); border-left: .3rem solid rgb(var(--brun)); }
/* L'illustration : posée à droite du texte sur grand écran, pleine largeur en dessous.
   `float` et non une grille : le texte doit passer autour, pas s'arrêter à côté. */
.article__illustration { margin: 0 0 3.2rem; }
.article__illustration img { display: block; width: 100%; height: auto; border-radius: var(--card-radius); box-shadow: 0 1.2rem 3rem rgba(var(--encre), .16); }
.article__illustration figcaption { margin: 1.2rem 0 0; font-size: 1.3rem; line-height: 1.5; color: rgb(var(--encre-douce)); }
@media screen and (min-width: 900px) {
  .article__illustration { float: right; width: 32rem; margin: .6rem 0 2.4rem 4rem; }
}
.article__corps { max-width: 68ch; }
.article__corps h2 { margin: 4rem 0 1.2rem; font-size: 2.2rem; }
.article__corps p { margin: 0 0 1.6rem; line-height: 1.7; }
.article__liste { margin: 0 0 2.4rem; padding-left: 2.2rem; }
.article__liste li { margin: 0 0 .9rem; line-height: 1.6; }
.article__illustration-section { margin: 2.4rem 0 3.2rem; }
.article__illustration-section img { display: block; width: 100%; height: auto; border-radius: var(--card-radius); }
.article__illustration-section figcaption { margin: 1rem 0 0; font-size: 1.3rem; line-height: 1.5; color: rgb(var(--encre-douce)); }
.article__sources { clear: both; margin: 4rem 0 0; padding: 2rem; background: rgb(var(--creme)); border-radius: var(--card-radius); }
.article__sources h2 { margin: 0 0 1.2rem; font-size: 1.8rem; }
.article__sources p { margin: 0 0 1.2rem; line-height: 1.6; }
.article__sources ul { margin: 0; padding-left: 2rem; }
.article__sources li + li { margin-top: .8rem; }
.article__corps code { font-size: .92em; padding: .1rem .4rem; border-radius: .3rem; background: rgb(var(--creme)); }
/* Le portrait d'un auteur. Trente-six pixels dans une signature, quarante-huit en tête
   d'article : à cette taille c'est la silhouette qui distingue, pas le détail du visage. */
.avatar { display: block; flex: none; border-radius: 50%; }
.avatar__fond { fill: rgb(var(--sable)); }
.avatar__vetement { fill: rgb(var(--navy)); }
.avatar__traits { fill: rgba(var(--encre), .8); }
.avatar__sourire { fill: none; stroke: rgba(var(--encre), .8); stroke-width: 1.3; stroke-linecap: round; }
.avatar--cornelia .avatar__peau { fill: rgb(var(--peau-foncee)); }
.avatar--cornelia .avatar__cheveux { fill: rgb(var(--cheveux-fonces)); }
.avatar--cornelia .avatar__traits { fill: rgba(255, 255, 255, .9); }
.avatar--cornelia .avatar__sourire { stroke: rgba(255, 255, 255, .9); }
.avatar--fred .avatar__peau { fill: rgb(var(--peau-claire)); }
.avatar--fred .avatar__cheveux { fill: rgb(var(--cheveux-clairs)); }
.avatar--fred .avatar__barbe { fill: rgb(var(--cheveux-clairs)); }

/* La signature : portrait, nom, date. En tête d'article elle remplace la ligne de date
   seule ; sur une carte d'index elle passe sous le chapô. */
.article__signature { display: flex; align-items: center; gap: 1.2rem; margin: 0 0 2.4rem; }
.article__signature .avatar { width: 4.8rem; height: 4.8rem; }
.article__signature-texte { display: flex; flex-direction: column; gap: .2rem; font-size: 1.3rem; line-height: 1.3; }
.article__signature-nom { font-weight: 600; font-size: 1.5rem; color: rgb(var(--encre)); }
.article__signature time { letter-spacing: .06em; text-transform: uppercase; color: rgb(var(--brun)); }
.blog__carte-signature { display: flex; align-items: center; gap: .8rem; margin: 0 0 1.6rem; font-size: 1.3rem; color: rgb(var(--encre-douce)); }
.blog__carte-signature .avatar { width: 2.8rem; height: 2.8rem; }

.commande-etat__facture { margin: 0 0 2.4rem; }
.commande-etat__facture a { text-decoration: underline; text-underline-offset: .3rem; }

/* « Mes commandes » : un champ, un bouton. Pas de compte, donc pas d'écran de compte. */
.mes-commandes { max-width: 52rem; }
.mes-commandes__intro { color: rgb(var(--encre-douce)); margin: 0 0 3.2rem; }
.mes-commandes__form { display: grid; gap: 1.2rem; justify-items: start; }
.mes-commandes__form input { width: 100%; }
/* L'attribut `hidden` doit gagner sur toute règle d'affichage : la feuille du navigateur le
   déclare avec la spécificité la plus faible, et un simple sélecteur de classe le contredit.
   C'est ce qui laissait le bouton « Imprimer » visible et sans effet sans JavaScript. */
[hidden] { display: none !important; }

.mes-commandes__reponse--erreur { background: rgb(var(--rouge-fond)); border-color: rgba(var(--rouge), .4); }
.mes-commandes__reponse { padding: 1.4rem 1.6rem; border-radius: var(--card-radius); background: rgb(var(--creme)); border: .1rem solid rgba(var(--encre), .12); margin: 0 0 1.6rem; }

/* La facture. Elle se lit à l'écran et s'imprime : le papier retire tout ce qui n'est pas
   le document — en-tête, pied de page, bouton d'impression. */
.facture { max-width: 76rem; }
.facture__actions { margin: 0 0 2.4rem; }
.facture__entete { margin: 0 0 3.2rem; }
.facture__entete h1 { margin: 0 0 .8rem; }
.facture__reference { font-weight: 600; margin: 0 0 .4rem; }
.facture__commande { color: rgb(var(--encre-douce)); font-size: 1.4rem; margin: 0 0 .4rem; }
.facture__date { color: rgb(var(--encre-douce)); font-size: 1.4rem; margin: 0; }
.facture__parties { display: grid; gap: 2.4rem; margin: 0 0 3.2rem; }
@media screen and (min-width: 600px) { .facture__parties { grid-template-columns: 1fr 1fr; } }
.facture__parties h2 { font-size: 1.2rem; text-transform: uppercase; letter-spacing: .06em; color: rgb(var(--brun)); margin: 0 0 .8rem; }
.facture__parties p { margin: 0; line-height: 1.6; }
.facture__lignes { width: 100%; border-collapse: collapse; font-size: 1.4rem; }
.facture__lignes th, .facture__lignes td { padding: 1rem 0; border-bottom: .1rem solid rgba(var(--encre), .12); text-align: left; vertical-align: top; font-weight: 400; }
.facture__lignes thead th { font-size: 1.2rem; text-transform: uppercase; letter-spacing: .04em; opacity: .7; }
.facture__nombre { text-align: right; font-variant-numeric: tabular-nums; white-space: nowrap; }
.facture__variante { display: block; font-size: 1.3rem; color: rgb(var(--encre-douce)); }
.facture__lignes tfoot th { font-weight: 500; }
.facture__total th, .facture__total td { font-weight: 700; font-size: 1.6rem; border-bottom: 0; }
.facture__mention { margin: 2.4rem 0 0; font-size: 1.3rem; color: rgb(var(--encre-douce)); }
@media print {
  .header, .footer, .announcement-bar, .facture__actions, .haut, .occasions-nav { display: none !important; }
  .facture { max-width: none; padding: 0; }
  body { background: #fff; }
}

/* Le bouton « remonter ». Discret : un disque crème cerné d'un trait d'encre, la taille
   exacte d'une cible tactile (44 px), posé dans le coin bas-droit au-dessus de la barre
   d'achat quand elle est là. Il n'existe que défilé — le script l'ajoute et lui pose
   `--visible` quand l'en-tête sort de l'écran. */
.haut {
  position: fixed; z-index: 19;
  right: max(1.6rem, env(safe-area-inset-right, 0px));
  bottom: calc(1.6rem + env(safe-area-inset-bottom, 0px));
  display: flex; align-items: center; justify-content: center;
  width: 4.4rem; height: 4.4rem; border-radius: 50%;
  color: rgb(var(--encre)); background: rgb(var(--creme));
  border: .1rem solid rgba(var(--encre), .16);
  box-shadow: 0 .4rem 1.6rem rgba(var(--encre), .14);
  /* Il monte d'un demi-centimètre en apparaissant : c'est le geste qu'il propose. */
  opacity: 0; visibility: hidden; transform: translateY(.6rem);
  transition: opacity .2s ease, transform .2s ease, visibility 0s linear .2s, background .15s ease;
}
.haut--visible { opacity: 1; visibility: visible; transform: none; transition-delay: 0s; }
.haut:hover { background: rgb(var(--sable)); }
.haut:focus-visible { outline: .2rem solid rgb(var(--bleu-focus)); outline-offset: .3rem; }
/* La barre d'achat occupe déjà le bas de l'écran sur une fiche produit : le bouton passe
   au-dessus plutôt que par-dessous. */
body:has(.barre-achat:not([hidden])) .haut { bottom: calc(10.2rem + env(safe-area-inset-bottom, 0px)); }
@media (prefers-reduced-motion: reduce) { .haut { transition: none; transform: none; } }

/* Ce qu'il y a à lire depuis une page d'occasion : deux renvois, pas une grille de cartes —
   la page vend, elle ne se termine pas sur un sommaire. */
.occasion__lectures { margin: 4.8rem 0 0; padding: 3.2rem 0 0; border-top: .1rem solid rgba(var(--encre), .12); }
.occasion__lectures ul { display: grid; gap: 1.6rem; list-style: none; margin: 2rem 0 0; padding: 0; }
@media screen and (min-width: 750px) { .occasion__lectures ul { grid-template-columns: 1fr 1fr; gap: 2.4rem; } }
.occasion__lectures a { font-weight: 600; text-decoration: underline; text-underline-offset: .3rem; }
.occasion__lectures p { margin: .6rem 0 0; font-size: 1.4rem; line-height: 1.6; color: rgb(var(--encre-douce)); }

/* Le tableau d'un article. Il défile dans sa propre boîte plutôt que d'élargir la page :
   une liste de quatre-vingts lignes à trois colonnes ne tient pas dans 320 px, et c'est la
   seule chose de l'article qui ait le droit de dépasser — à l'intérieur de son cadre. */
.article__tableau-cadre { overflow-x: auto; margin: 0 0 2.4rem; }
/* Il est focalisable au clavier (Firefox et Safari ne le font pas d'eux-mêmes pour une
   zone qui défile) : il lui faut donc l'anneau de focus des autres éléments. */
.article__tableau-cadre:focus-visible { outline: .2rem solid rgb(var(--bleu-focus)); outline-offset: .4rem; }
.article__tableau { width: 100%; border-collapse: collapse; font-size: 1.4rem; }
.article__tableau caption { text-align: left; font-size: 1.3rem; color: rgb(var(--encre-douce)); padding: 0 0 1.2rem; }
.article__tableau th, .article__tableau td { padding: .8rem 1.6rem .8rem 0; border-bottom: .1rem solid rgba(var(--encre), .1); text-align: left; vertical-align: top; }
.article__tableau thead th { font-size: 1.2rem; text-transform: uppercase; letter-spacing: .04rem; font-weight: 500; opacity: .7; white-space: nowrap; }
/* La première colonne est l'année : elle se lit en chiffres alignés, et elle ne se coupe pas. */
.article__tableau tbody th { font-weight: 600; font-variant-numeric: tabular-nums; white-space: nowrap; }
.article__produits { margin: 5.6rem 0 0; padding: 3.2rem 0 0; border-top: .1rem solid rgba(var(--encre), .12); }
.article__produits ul { display: grid; gap: 2.4rem; list-style: none; margin: 2.4rem 0 0; padding: 0; }
@media screen and (min-width: 750px) { .article__produits ul { grid-template-columns: 1fr 1fr; } }
.article__produits li > a { display: grid; grid-template-columns: 8rem 1fr; align-items: center; gap: 1.6rem; text-decoration: none; color: inherit; }
.article__produits img { width: 8rem; height: 8rem; object-fit: cover; border-radius: var(--card-radius); background: rgb(var(--gris)); }
.article__produit-nom { font-weight: 500; }
.article__produit-prix { color: rgb(var(--brun)); }
.article__produits li p { margin: .8rem 0 0; font-size: 1.4rem; color: rgb(var(--encre-douce)); }
.article__faq { margin: 4.8rem 0 0; }
.article__faq details { border-top: .1rem solid rgba(var(--encre), .12); }
.article__faq details:last-of-type { border-bottom: .1rem solid rgba(var(--encre), .12); }
.article__faq summary { cursor: pointer; font-weight: 600; padding: 1.4rem 0; list-style: none; }
.article__faq summary::-webkit-details-marker { display: none; }
.article__faq summary::after { content: " +"; opacity: .6; }
.article__faq details[open] summary::after { content: " −"; }
.article__faq p { margin: 0 0 1.6rem; max-width: 68ch; color: rgba(var(--encre), .82); }
.article__autres { margin: 4.8rem 0 0; }
.article__autres ul { display: flex; flex-wrap: wrap; gap: 1.2rem 2.4rem; list-style: none; margin: 1.6rem 0 0; padding: 0; }

/* Réassurance, sous le bouton d'achat. Discrète : pas d'encadré ni de couleur d'alerte,
   c'est une note de bas de bloc, pas une bannière. Deux colonnes dès qu'il y a la place. */
/* L'offre de gamme, entre le bouton d'achat et la réassurance. Les couleurs viennent de la
   charte : l'ocre foncé porte du blanc (4,88 de contraste), le crème sert de fond. */
.offre-duo { display: flex; flex-direction: column; gap: .3rem; margin: 1.2rem 0 0;
  padding: 1.1rem 1.3rem; border: 1px solid rgba(var(--ocre-fonce), .35);
  border-radius: .8rem; background: rgba(var(--ocre), .12); }
.offre-duo__titre { font-weight: 600; color: rgb(var(--brun)); }
.offre-duo__detail { font-size: 1.4rem; color: rgb(var(--encre-douce)); }

.reassurance { list-style: none; margin: 2rem 0 0; padding: 1.6rem 0 0; border-top: .1rem solid rgba(var(--color-foreground), .1); display: grid; gap: 1.2rem; }
@media screen and (min-width: 750px) { .reassurance { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 1.4rem 1.8rem; } }
.reassurance__item { display: grid; grid-template-columns: 2rem 1fr; gap: .9rem; align-items: start; }
.reassurance__icone { width: 2rem; height: 2rem; color: rgb(var(--color-accent)); flex: none; margin-top: .1rem; }
.reassurance__item strong { display: block; font-size: 1.3rem; font-weight: 600; letter-spacing: .02rem; }
.reassurance__item span { display: block; font-size: 1.2rem; line-height: 1.45; color: rgba(var(--color-foreground), .72); }
/* Sous 750 px et **sur la fiche d'un bracelet seulement**, deux colonnes et les promesses
   seules : quatre lignes de titre + détail faisaient 200 px juste sous le bouton, à l'endroit
   précis où l'on hésite, et les détails y répètent ce que disent déjà le bandeau d'annonce,
   la date d'expédition et la planche d'emballage.
   Le `.fiche-produit` du sélecteur n'est pas décoratif : la rangée est rendue aussi par
   l'accueil, les pages d'occasion et les fiches d'affiche, où aucun de ces trois éléments
   n'existe — la règle y effaçait des détails que rien d'autre ne disait, et quatre au lieu
   de deux sur une affiche, dont les promesses (impression à la commande, cadres standard)
   ne se devinent pas d'un titre. Une justification qui ne vaut que pour une page se borne à
   cette page. */
@media screen and (max-width: 749px) {
  .fiche-produit:not(.fiche-affiche) .reassurance { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 1rem 1.2rem; }
  .fiche-produit:not(.fiche-affiche) .reassurance__item span { display: none; }
  .fiche-produit:not(.fiche-affiche) .reassurance__item { grid-template-columns: 1.8rem 1fr; gap: .7rem; align-items: center; }
  .fiche-produit:not(.fiche-affiche) .reassurance__icone { width: 1.8rem; height: 1.8rem; margin-top: 0; }
  .fiche-produit:not(.fiche-affiche) .reassurance__item strong { font-size: 1.25rem; line-height: 1.3; }
}

/* Bande de paiement : une seule ligne sous la réassurance, volontairement effacée.
   Les logos sont petits — ils rassurent d'un coup d'œil, ils ne vendent pas. */
.paiement { display: flex; flex-wrap: wrap; align-items: center; gap: .5rem; margin: 1.4rem 0 0; }
.paiement__titre { font-size: 1.2rem; color: rgba(var(--color-foreground), .72); margin-right: .3rem; }
.paiement__logo { display: block; width: 3.4rem; height: 2.15rem; }

/* ---------- affiches personnalisées : éditeur et planches ---------- */
/* **`stretch` et non `start` : dans une colonne en `flex-direction: column`, l'axe
   transversal est l'horizontale.** `align-self: start` ne plaçait donc rien en haut — il
   rendait la scène « au contenu », si bien que la largeur de l'aperçu venait de la largeur
   intrinsèque du dessin de l'affiche et non de la colonne. Les cinq affiches de naissance,
   dessinées en unités de conteneur, n'en donnaient que 345 px là où la colonne en offre 583 :
   un aperçu d'un tiers trop petit, et illisible. Les quatre autres s'en tiraient à 426 px,
   sous le plafond de 460 voulu par `.affiche__cadre` — le défaut était là aussi, plus discret. */
.affiche__scene { display: grid; gap: .75rem; justify-items: center; align-self: stretch; }
/* L'aperçu suit le défilement : on choisit style et textes dans la colonne d'achat, plus
   longue que lui, et l'on doit voir l'affiche changer sans remonter. Les planches sont
   sous la grille pour qu'il n'ait rien à recouvrir. */
@media screen and (min-width: 990px) {
  /* La grille produit aligne ses colonnes en haut (`align-items: start`) : la colonne de
     gauche n'aurait que la hauteur de l'affiche et rien ne collerait. On l'étire. */
  .fiche-affiche .product__colonne { align-self: stretch; }
  .affiche__scene { position: sticky; top: 2rem; }
}
.affiche__planches { margin-top: 4rem; display: grid; gap: 3.2rem; }
/* L'aperçu réduit (`product.js`), téléphone et tablette seulement : sous 990 px la scène n'est
   pas collante — elle ferait tout l'écran — et l'on choisissait style et textes deux écrans sous
   l'affiche, sans la voir changer. Tant que l'éditeur est à l'écran, la scène elle-même (jamais
   une copie : c'est l'affiche exacte, MapLibre suit la taille de son conteneur) se pose en haut
   à droite, à 44 % de la largeur ; la colonne garde sa hauteur, rien ne saute. Le bouton
   transparent qui la recouvre ramène à l'affiche en grand. */
.affiche__socle { display: block; }
@media screen and (min-width: 990px) { .affiche__socle { display: contents; } }
@media screen and (max-width: 989px) {
  /* En bas à gauche, pas en haut à droite : posée en haut, elle recouvrait le bouton
     « Chercher » du champ de lieu au moment même où l'on vient de taper une ville. En bas,
     elle passe derrière le clavier pendant qu'on écrit et ne gêne aucun champ en cours de
     saisie ; à gauche, elle laisse le bouton « remonter » et la barre d'achat à leur place. */
  .affiche__scene--mini { position: fixed; top: auto; bottom: calc(.8rem + env(safe-area-inset-bottom, 0px)); left: .8rem; width: 40vw; max-width: 20rem; z-index: 25; gap: 0; }

  .affiche__scene--mini .affiche__mur { padding: 0; background: transparent; border-radius: 0; }
  .affiche__scene--mini .affiche__cadre { box-shadow: 0 .6rem 2rem rgba(var(--encre), .3); transition: none; }
  .affiche__scene--mini .affiche__aide, .affiche__scene--mini .affiche__erreur, .affiche__scene--mini .affiche__outils-carte { display: none; }
  .affiche__mini-retour { position: absolute; inset: 0; z-index: 3; border: 0; padding: 0; margin: 0; background: transparent; cursor: pointer; }
  .affiche__mini-retour:focus-visible { outline: .2rem solid rgb(var(--bleu-focus)); outline-offset: .2rem; }
}
.affiche__mini-retour[hidden] { display: none; }
.affiche__mur { width: 100%; background: rgb(var(--bordure)); border-radius: 10px; padding: clamp(16px, 4vw, 40px); display: grid; place-items: center; }
.affiche__cadre { container-type: inline-size; --bois: transparent; --bois-epaisseur: 0px; width: min(100%, 460px); padding: var(--bois-epaisseur); background: var(--bois); box-shadow: 0 18px 40px rgba(0, 0, 0, .18); transition: padding .25s ease; }
.affiche__cache { display: none !important; }
/* Hors charte, et volontairement : ce sont le papier et l'encre de l'affiche, c'est-à-dire
   le produit. Ces deux valeurs sont le style « Marin » de `public/js/affiche-carte.js`, que
   le script réécrit dès que le client change de style. Les aligner sur la charte changerait
   l'article, et ce qui part à l'impression. */
/* **Le conteneur de requête est le cadre, pas la feuille — et c'est la feuille qui porte les
   marges.** Un élément ne peut pas mesurer ses propres `cqw` : posé sur le conteneur lui-même,
   un `padding: 9cqw` se résout contre la **fenêtre** (aucun conteneur au-dessus), puis ampute
   le boîtier de contenu, qui est justement ce que `cqw` mesure pour les descendants. Les cinq
   affiches de naissance en vivaient : à 1 440 px de fenêtre, leur `padding: 9cqw` valait
   129,6 px de chaque côté d'une feuille de 460, si bien que `100cqw` ne valait plus 460 mais
   **201**. Tout le dessin sortait à 43 % de sa taille — l'ourson à 27 % de la largeur quand la
   feuille de style en demande 62, le prénom à 6,5 % au lieu de 15, et une lunule dessinée par
   le script à 7 % de la feuille écrasait un nom de phase de 5,8 px. Pire, le rapport dépendait
   de la largeur de la fenêtre : la même affiche ne se composait pas pareil à l'écran et sous
   le navigateur de fabrication.
   Le cadre, lui, a une largeur définie (`min(100%, 460px)`) et son boîtier de contenu **est**
   la feuille, cadre en bois déduit : `cqw` y vaut exactement un pour-cent de la largeur de
   l'affiche, ce que la feuille de style des naissances dit partout. `position: relative` rend
   à la feuille le rôle de bloc conteneur que le confinement lui donnait, sans quoi les décors
   en `position: absolute` se caleraient sur le bois du cadre. */
.affiche__affiche { --fond: #fbf9f4; --texte: #14324a; position: relative; width: 100%; aspect-ratio: 5 / 7; display: flex; flex-direction: column; background: var(--fond); color: var(--texte); overflow: hidden; }
.affiche__carte { flex: 1; min-height: 0; }
/* Carte du ciel : un disque dans le haut de l'affiche, la légende dessous. */
/* Le diamètre du disque est calculé par le script d'après la hauteur de l'affiche (bordé
   par sa largeur) : il suit le format — plus grand sur un 40 × 60, plus petit sur un 30 × 40 —
   au lieu de rester figé pendant que seule la légende bouge. Une hauteur en pourcentage ne
   se résout pas dans une boîte dont la hauteur vient d'un aspect-ratio, d'où le script. */
.affiche__ciel { flex: 1; min-height: 0; display: grid; place-items: center; padding: 6% 8% 1%; }
.affiche__ciel canvas { display: block; }
.affiche__affiche--ciel { justify-content: space-between; }
.affiche__affiche--ciel .affiche__legende { padding-bottom: 7%; }
/* Carte du ciel avec photo : le médaillon mord le bas du disque (Fred, 24 sept. 2026). Tout se
   mesure sur `--disque`, le diamètre que l'éditeur écrit en pixels : le médaillon en fait
   46 % (à 40, un visage de couple faisait 1,5 cm sur l'A4), 30 % de sa hauteur chevauche le
   ciel, et la marge sous le disque réserve le reste
   — sans elle il tomberait sur la légende. Le double anneau (un liseré de papier, puis un
   filet d'encre) détache la photo des étoiles qu'elle recouvre ; c'est ce qui fait un sceau
   plutôt qu'une image collée. Les couleurs sont celles du style, jamais écrites ici. */
.affiche__ciel--photo { padding-bottom: 0; }
.affiche__disque { position: relative; margin-bottom: calc(var(--disque, 0px) * .46 * .7); }
.affiche__medaillon { position: absolute; left: 50%; top: 100%; width: calc(var(--disque, 0px) * .46); aspect-ratio: 1; transform: translate(-50%, -30%); border-radius: 50%; overflow: hidden; background: var(--fond); box-shadow: 0 0 0 calc(var(--disque, 0px) * .014) var(--fond), 0 0 0 calc(var(--disque, 0px) * .022) color-mix(in srgb, var(--texte) 60%, transparent); }
/* Le filet d'encre fait 0,8 % du disque : 1,4 mm sur un 30 × 40. Plus fin, le papier mat le boit. */
.affiche__medaillon[data-photo] { touch-action: none; cursor: grab; }
.affiche__medaillon[data-nb] img { filter: grayscale(1) contrast(1.05); }
.affiche__medaillon img { display: block; width: 100%; height: 100%; object-fit: cover; object-position: var(--photo-x, 50%) var(--photo-y, 40%); transform: scale(var(--photo-zoom, 1)); transform-origin: var(--photo-x, 50%) var(--photo-y, 40%); }
.affiche__medaillon-vide { position: absolute; inset: 0; display: grid; cursor: pointer; margin: 0; place-content: center; justify-items: center; gap: .3em; padding: 12%; border: 1px dashed; border-radius: 50%; color: var(--texte); opacity: .75; font-size: calc(var(--disque, 0px) * .038); line-height: 1.2; text-align: center; }
.affiche__medaillon-vide svg { width: 32%; height: auto; }
.affiche__medaillon img[hidden], .affiche__medaillon-vide[hidden] { display: none; }
.affiche__photo { display: grid; gap: 1rem; }
.affiche__photo-titre { margin: 0; font-weight: 600; }
.affiche__photo-bouton { min-height: 4.8rem; cursor: pointer; }
/* Le vrai champ est masqué : son focus clavier se voit sur le bouton qui le porte. */
.affiche__photo input[type="file"]:focus-visible + .affiche__photo-bouton { outline: .2rem solid rgb(var(--bleu-focus)); outline-offset: .3rem; }
.affiche__photo-reglages { display: grid; gap: .6rem; }
.affiche__photo-reglages label { display: flex; align-items: center; justify-content: space-between; gap: 1.2rem; font-weight: 400; }
.affiche__photo-reglages input[type="range"] { width: 60%; min-height: 4.4rem; accent-color: rgb(var(--color-accent)); padding: 0; border: 0; background: none; }
.affiche__photo-avis { margin: 0; font-size: 1.2rem; }
.affiche__photo-avis[data-gravite="alerte"] { color: rgb(var(--rouge)); }
.affiche__phase { text-transform: none; letter-spacing: .12em; font-size: clamp(9px, 2.3cqw, 12px); }
/* FAQ : questions dépliables, la première ouverte. */
/* L'avancement de la fabrication d'une affiche. Le chiffre porte l'information, la barre ne
   fait que la rendre lisible d'un coup d'œil — d'où sa discrétion. */
.telechargement__etat { margin: 2rem 0 0; padding: 1.6rem 1.8rem; background: rgb(var(--creme)); border-radius: 1rem; }
.telechargement__compteur { margin: 0 0 .8rem; font-size: 1.6rem; font-weight: 600; }
.telechargement__barre { height: .6rem; border-radius: .3rem; background: rgba(var(--color-foreground), .12); overflow: hidden; }
.telechargement__barre span { display: block; height: 100%; background: rgb(var(--ocre-fonce)); transition: width .3s ease; }
.telechargement__etat .caisse__note { margin: 1rem 0 0; }

/* Les avis. Rien d'orné : ce qui compte est la phrase du client, pas le cadre autour.
   Les étoiles portent l'ocre sombre — celui qui passe sur du blanc — et non un jaune importé
   d'ailleurs, qui ne serait dans la charte de personne. */
.avis { list-style: none; margin: 0; padding: 0; display: grid; gap: 1.6rem; }
.avis__item { border-top: 1px solid rgba(var(--color-foreground), .15); padding-top: 1.2rem; }
.avis__note { margin: 0 0 .4rem; color: rgb(var(--ocre-fonce)); letter-spacing: .1em; font-size: 1.3rem; }
.avis__texte { margin: 0; padding: 0; border: 0; font-size: 1.5rem; line-height: 1.55; }
.avis__signature { margin: .6rem 0 0; font-size: 1.3rem; color: rgba(var(--color-foreground), .7); }
.avis__mention { margin: 1.6rem 0 0; font-size: 1.2rem; line-height: 1.5; color: rgba(var(--color-foreground), .7); }

.planche--faq details { border-top: 1px solid rgba(var(--color-foreground), .15); }
.planche--faq details:last-of-type { border-bottom: 1px solid rgba(var(--color-foreground), .15); }
.planche--faq summary { cursor: pointer; font-weight: 600; padding: 1.2rem 0; list-style: none; display: flex; justify-content: space-between; gap: 1.2rem; }
.planche--faq summary::-webkit-details-marker { display: none; }
.planche--faq summary::after { content: "+"; font-weight: 400; opacity: .6; }
.planche--faq details[open] summary::after { content: "−"; }
.planche--faq p { margin: 0 0 1.4rem; max-width: 70ch; color: rgba(var(--color-foreground), .75); }
.affiche__champ input[type="date"], .affiche__champ input[type="time"] { font-variant-numeric: tabular-nums; }
.affiche__carte canvas:focus-visible { outline: 2px solid rgb(var(--bleu-focus)); }
.affiche__repere { width: 26px; height: 36px; }
.affiche__repere svg { width: 100%; height: 100%; display: block; overflow: visible; }
.repere-forme { fill: var(--texte); stroke: var(--fond); stroke-width: 6; paint-order: stroke; }
.repere-creux { fill: var(--fond); }
/* Hors charte, et volontairement : ce cœur est imprimé sur l'affiche. Sa couleur est
   celle du tracé des styles (`public/js/affiche-trajet.js`), c'est-à-dire le produit. */
.repere-coeur { fill: #d7263d; stroke: #fff; stroke-width: 5; paint-order: stroke; }
/* Pastilles de repère : celles des options, plus une icône. `currentColor` suit l'inversion
   de la pastille cochée ; pas de liseré dans la pastille, il ne sert que sur la carte. */
.affiche__reperes legend { font-size: 1.3rem; font-weight: 600; }
.affiche__reperes label { --texte: currentColor; --fond: transparent; }
.affiche__reperes label svg { width: 1.4rem; height: 1.5rem; overflow: visible; vertical-align: -.2rem; margin-right: .6rem; }
.affiche__reperes .repere-coeur { stroke: none; }
.affiche__legende { padding: 4% 8% 5%; text-align: center; }
/* Le titre tient dans la largeur de l'affiche : un nom de parcours (« Sentier des douaniers du
   Cap Corse ») fait le double d'un nom de ville. Le script mesure la ligne et pose l'échelle et
   l'interlettrage ; sans lui, le titre passe simplement à la ligne. */
.affiche__nom { font-size: calc(clamp(16px, 5cqw, 30px) * var(--titre-echelle, 1)); letter-spacing: var(--titre-espace, .32em); text-transform: uppercase; margin: 0; padding-left: var(--titre-espace, .32em); text-wrap: balance; }
.affiche__nom--ligne { white-space: nowrap; }
/* Même mécanique que le titre : le sous-titre porte la région (« Rhénanie-du-Nord-Westphalie ·
   Allemagne »), que le script resserre plutôt que de la tronquer. La ligne de phase de la lune
   partage la classe, et la même règle. */
.affiche__sous { font-size: calc(clamp(9px, 2.4cqw, 13px) * var(--sous-echelle, 1)); letter-spacing: var(--sous-espace, .28em); text-transform: uppercase; margin: .6em 0 0; padding-left: var(--sous-espace, .28em); opacity: .85; }
.affiche__sous--ligne { white-space: nowrap; }
.affiche__dedicace { font-style: italic; font-size: clamp(9px, 2.6cqw, 14px); letter-spacing: .04em; margin: .9em 0 0; opacity: .85; }
/* Date, dédicace et chiffres sont facultatifs : une ligne vide ne doit pas laisser de trou. */
.affiche__dedicace:empty, .affiche__sous:empty, .affiche__coord:empty { display: none; }
.affiche__coord { font-size: clamp(8px, 2cqw, 11px); letter-spacing: .12em; margin: .8em 0 0; font-variant-numeric: tabular-nums; opacity: .75; }
.affiche__trait { width: 14%; height: 1px; background: currentColor; margin: 1.2em auto 0; opacity: .6; }
.affiche__affiche { position: relative; }
/* Sur la carte, en haut à droite, comme sur toute carte : zoom et recadrage. Blanc sur ombre,
   lisible sur tous les styles ; hors de l'affiche imprimée, qui est rendue depuis les données. */
.affiche__outils-carte { position: absolute; top: 10px; right: 10px; z-index: 2; display: grid; gap: 6px; }
.affiche__outils-carte button { font: inherit; font-size: 1.8rem; line-height: 1; width: 3.6rem; height: 3.6rem; border: 0; border-radius: 50%; background: rgba(255, 255, 255, .92); color: rgb(var(--navy)); box-shadow: 0 2px 8px rgba(0, 0, 0, .28); cursor: pointer; display: grid; place-items: center; padding: 0; }
/* La cible tactile fait 44 px (4 px de débord tout autour d'un disque de 36) sans agrandir le
   disque, qui recouvre la carte qu'on cadre. */
.affiche__outils-carte button { position: relative; }
.affiche__outils-carte button::before { content: ""; position: absolute; inset: -.4rem; border-radius: 50%; }
.affiche__outils-carte button:hover { background: #fff; }
.affiche__outils-carte button:focus-visible { outline: 2px solid rgb(var(--bleu-focus)); outline-offset: 2px; }
.affiche__outils-carte svg { width: 1.8rem; height: 1.8rem; }
.affiche__aide { font-size: 1.2rem; color: rgba(var(--color-foreground), .65); text-align: center; margin: 0; }
.affiche__erreur { color: rgb(var(--rouge)); text-align: center; }
.affiche__editeur { border: 1px solid rgba(var(--color-foreground), .2); border-radius: 10px; overflow: hidden; margin: 1rem 0; }
.affiche__editeur > summary { list-style: none; cursor: pointer; display: flex; align-items: center; justify-content: space-between; gap: 12px; padding: 1.2rem 1.6rem; background: rgba(var(--color-foreground), .05); font-weight: 600; }
.affiche__editeur > summary::-webkit-details-marker { display: none; }
.affiche__editeur > summary::after { content: "▾"; transition: transform .2s; }
.affiche__editeur[open] > summary::after { transform: rotate(180deg); }
.affiche__pas { font-size: 1.2rem; font-weight: 400; color: rgba(var(--color-foreground), .68); }
/* La dernière étape du parcours numéroté (point 4 bis) : sa pastille est dans le résumé du
   `<details>`, à côté du nom, et le sous-titre reste calé à droite. */
.affiche__editeur-titre { display: inline-flex; align-items: baseline; gap: .8rem; }
.affiche__editeur-titre .etape__numero { transform: translateY(.3rem); }
.fiche-affiche .etape:not(.affiche__editeur) { margin-bottom: 2rem; }
.affiche__corps { padding: 1.6rem; display: grid; gap: 1.4rem; }
.affiche__champ { display: grid; gap: .4rem; border: 0; padding: 0; margin: 0; min-width: 0; }
.affiche__champ legend, .affiche__champ label { font-size: 1.3rem; font-weight: 600; padding: 0; margin-bottom: .2rem; }
.affiche__champ label small { font-weight: 400; color: rgba(var(--color-foreground), .6); }
.affiche__champ input { font: inherit; font-size: 1.4rem; padding: .8rem .9rem; border: 1px solid rgba(var(--color-foreground), .3); border-radius: 6px; width: 100%; background: rgb(var(--color-background)); color: inherit; }
.affiche__deux { display: grid; grid-template-columns: 1fr 1fr; gap: 1.2rem; }
/* Trajet : dépôt d'un GPX, bloc Strava avec ses éléments de marque officiels. */
.affiche__champ input[type="file"] { padding: .6rem; font-size: 1.3rem; }
/* **Une pastille reste une pastille dans un champ d'affiche.** La règle des libellés de champ
   ci-dessus a la même spécificité que celle des pastilles (`.product-form__input--pill label`)
   et s'écrit plus bas : elle lui reprenait son rembourrage. Une étiquette de 4,4 rem de haut,
   sans rembourrage horizontal et avec le rayon des pastilles, devient une **ellipse** dont le
   mot déborde — « Fille » tenait dans 23 px de large. Vu sur l'accord des affiches de
   naissance, la seule pastille posée dans un champ d'affiche. */
.affiche__champ .product-form__input--pill label { padding: 1rem 2rem; font-size: 1.4rem; font-weight: 400; }
.affiche__ou { margin: 0; font-size: 1.2rem; text-transform: uppercase; letter-spacing: .12em; color: rgba(var(--color-foreground), .55); }
.affiche__strava { gap: .8rem; }
.affiche__strava-bouton { display: inline-block; width: 237px; max-width: 100%; }
.affiche__strava-bouton img { display: block; width: 100%; height: auto; }
.affiche__strava-logo { display: block; width: 130px; height: auto; margin-top: .4rem; }
.affiche__strava-sortie { margin: .4rem 0 0; }
.affiche__lien { font: inherit; font-size: 1.2rem; background: none; border: 0; padding: 0; color: rgba(var(--color-foreground), .7); text-decoration: underline; cursor: pointer; }
.affiche__aide--gauche { text-align: left; }
#strava-liste { display: grid; gap: .4rem; }
#strava-liste label { font-size: 1.3rem; font-weight: 600; }
#strava-activite { font: inherit; font-size: 1.3rem; padding: .7rem .8rem; border: 1px solid rgba(var(--color-foreground), .3); border-radius: 6px; background: rgb(var(--color-background)); color: inherit; min-width: 0; flex: 1; }
.affiche__recherche { display: flex; gap: .5rem; }
.affiche__recherche input { flex: 1; min-width: 0; }
.affiche__retour { margin: 0; font-size: 1.2rem; min-height: 1.5em; color: rgba(var(--color-foreground), .7); }
.affiche__styles { display: grid; grid-template-columns: repeat(3, 1fr); gap: .5rem; }
.affiche__style { font: inherit; font-size: 1.2rem; border: 1px solid rgba(var(--color-foreground), .25); background: transparent; color: inherit; padding: .5rem; cursor: pointer; display: grid; gap: .4rem; border-radius: 8px; text-align: center; }
.affiche__style[aria-pressed="true"] { border-color: rgb(var(--color-foreground)); box-shadow: 0 0 0 1px rgb(var(--color-foreground)); }
.affiche__echantillon { display: block; height: 38px; border-radius: 5px; position: relative; overflow: hidden; }
.affiche__echantillon::before, .affiche__echantillon::after { content: ""; position: absolute; left: -10%; right: -10%; height: 2px; background: var(--r); transform: rotate(-18deg); top: 40%; }
.affiche__echantillon::after { transform: rotate(32deg); top: 62%; height: 1px; }
.affiche__bascule { display: flex; gap: .8rem; align-items: center; font-size: 1.3rem; }
.affiche__bascule input { width: 1.6rem; height: 1.6rem; }
.product-form__input--pill label.affiche__valeur-fichier, .affiche__valeur-fichier { display: none; }
/* Les visuels d'une affiche une fois imprimée. Une rangée qui défile au doigt sous 750 px
   — deux cartes et demie par écran, donc rien ne laisse croire qu'il n'y a que ça à voir —
   et une grille au-delà. Ratio naturel, jamais de recadrage : une mise en situation qui
   rogne le cadre ne dit plus la taille, qui est tout ce qu'on lui demande. */
.affiche__situations { display: grid; grid-auto-flow: column; grid-auto-columns: 78%; gap: 1.2rem; margin: 0; padding: 0 0 .8rem; list-style: none; overflow-x: auto; scroll-snap-type: x mandatory; overscroll-behavior-x: contain; }
.affiche__situations > li { scroll-snap-align: start; }
.affiche__situations img { display: block; width: 100%; height: auto; border-radius: 10px; }
@media (min-width: 750px) {
  .affiche__situations { grid-auto-flow: row; grid-template-columns: repeat(3, 1fr); grid-auto-columns: auto; overflow: visible; padding-bottom: 0; }
  /* Une affiche qui n'a que deux mises en situation ne laisse pas la troisième colonne vide :
     la rangée se lirait comme une photo manquante. Les huit affiches qui attendent encore
     leurs visuels y passeront. */
  .affiche__situations:has(> li:nth-child(2):last-child) { grid-template-columns: repeat(2, 1fr); }
}
.affiche__formats { display: grid; gap: 1.2rem; }
@media (min-width: 640px) { .affiche__formats { grid-template-columns: 1fr 1fr; } }
.affiche__format { border: 1px solid rgba(var(--color-foreground), .15); border-radius: 10px; padding: 1.4rem; display: grid; grid-template-columns: auto 1fr; gap: 1.4rem; align-items: center; }
.affiche__silhouette { background: rgb(var(--bordure)); border: 6px solid rgb(var(--color-foreground)); box-shadow: inset 0 0 0 4px rgb(var(--color-background)); }
.affiche__format h3 { margin: 0 0 .3rem; font-size: 1.6rem; }
/* Le mot posé sur le 30 × 40 : ocre foncé, la seule teinte de la marque qui porte du blanc (4,88). */
.affiche__badge { display: inline-block; margin-left: .4rem; padding: .15rem .6rem; border-radius: 999px; background: rgb(var(--ocre-fonce)); color: #fff; font-size: 1.1rem; font-weight: 700; letter-spacing: .03em; text-transform: uppercase; vertical-align: middle; line-height: 1.5; }
.affiche__format p { margin: 0; font-size: 1.3rem; color: rgba(var(--color-foreground), .7); }
.affiche__fichier-note { margin: 1.2rem 0 0; font-size: 1.3rem; color: rgba(var(--color-foreground), .7); }
.affiche__etapes { display: grid; gap: 1.2rem; padding: 0; margin: 0; list-style: none; counter-reset: etape; }
@media (min-width: 640px) { .affiche__etapes { grid-template-columns: repeat(3, 1fr); } }
.affiche__etapes li { counter-increment: etape; padding: 1.4rem; border: 1px solid rgba(var(--color-foreground), .15); border-radius: 10px; }
.affiche__etapes li::before { content: counter(etape); display: inline-grid; place-items: center; width: 2.6rem; height: 2.6rem; border-radius: 50%; background: rgb(var(--bleu-focus)); color: #fff; font-weight: 600; font-size: 1.3rem; margin-bottom: .8rem; }
.affiche__etapes b { display: block; margin-bottom: .3rem; }
.affiche__etapes p { margin: 0; font-size: 1.3rem; color: rgba(var(--color-foreground), .7); }

/* Barre d'achat collante, sous 750 px seulement. Le bouton de la page se trouvait à 2,1 à
   3,1 écrans du haut — dix coloris et cinq tailles s'intercalent entre le prix et lui — et
   rien n'était épinglé nulle part. `env(safe-area-inset-bottom)` la tient au-dessus de la
   barre d'accueil d'un iPhone ; sans ça elle passerait dessous. Elle n'apparaît qu'une fois
   le bouton d'origine sorti de l'écran, pour ne pas doubler ce qui est déjà là. */
.barre-achat {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 20;
  display: none; align-items: center; gap: 1.2rem;
  padding: 1rem 1.6rem calc(1rem + env(safe-area-inset-bottom, 0px));
  background: rgb(var(--color-background)); border-top: .1rem solid rgba(var(--color-foreground), .12);
  box-shadow: 0 -.2rem 1.2rem rgba(var(--encre), .08);
}
.barre-achat__prix { font-size: 1.8rem; font-weight: 600; white-space: nowrap; }
/* 5,6 rem : la hauteur d'une cible qu'on touche du pouce sans regarder, et la même que le
   bouton de la page une fois son prix posé dessus. */
button.barre-achat__bouton { flex: 1; min-height: 5.6rem; margin: 0; padding: 0 1.6rem; font-size: 1.6rem; }
@media screen and (max-width: 749px) {
  .barre-achat:not([hidden]) { display: flex; }
  /* La réserve va sur le **corps**, pas sur la section produit : le pied de page vient
     après elle, et la barre enterrait le sélecteur de langue du pied — hors d'atteinte,
     sans possibilité de défiler plus bas. */
  body:has(.barre-achat:not([hidden])) { padding-bottom: 9.8rem; }
}

/* Deux contrastes du bloc de personnalisation importé, mesurés sous le seuil de 4,5:1 :
   l'astérisque de champ obligatoire en rouge pur (4,0:1) et le compteur de caractères en
   gris clair (2,6:1). Le HTML du bloc n'est pas le nôtre et l'import le réécrit : la
   correction vit ici, avec la spécificité qu'il faut pour passer devant son `<style>`. */
.product__info-container .required-star,
.product__info-container .field__label .required,
.product__info-container span[style*="red"] { color: rgb(var(--rouge)) !important; }
.product__info-container .char-counter,
.product__info-container .counter,
.product__info-container .prenom-counter,
.product__info-container [class$="-counter"] { color: rgb(var(--encre-pale)) !important; }

/* La face cachée du shaka : une photo large et sa légende, sans encadré. */
.planche--dos img { display: block; width: 100%; height: auto; border-radius: .6rem; }
.planche--dos p { margin: 1.2rem 0 0; max-width: 70ch; }

/* Pages d'occasion. Elles ne reprennent pas la grille du catalogue : chaque produit y porte
   une raison écrite pour l'occasion, donc une ligne de texte sous sa vignette — c'est ce
   texte qui fait la page, pas la vignette. */
.occasion__titre { font-size: clamp(2.2rem, 5vw, 3.4rem); line-height: 1.15; margin: 0 0 1.6rem; }
.occasion__intro { max-width: 72ch; font-size: 1.6rem; line-height: 1.6; margin: 0 0 3.2rem; }
.occasion__liste { list-style: none; margin: 0 0 3.2rem; padding: 0; display: grid; gap: 2.4rem; }
@media screen and (min-width: 750px) { .occasion__liste { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 3.2rem 2.4rem; } }
@media screen and (min-width: 990px) { .occasion__liste { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
/* Sur téléphone, la photo va à gauche du texte. Une vignette pleine largeur par produit
   donnait une page de dix-huit mille pixels de haut pour sept bracelets, et faisait charger
   une déclinaison de 1200 px pour une liste — c'est la raison qu'on lit pour choisir, pas
   la photo. Au-delà de 750 px la carte se rempile, la grille ayant deux ou trois colonnes. */
.occasion__lien { display: grid; grid-template-columns: 36vw minmax(0, 1fr); gap: 1.6rem; align-items: start; text-decoration: none; color: inherit; }
@media screen and (min-width: 750px) { .occasion__lien { display: block; } }
/* `contain` et non `cover` : les dix-sept premières photos sont carrées, le rendu est donc
   le même aujourd'hui — mais la première photo non carrée importée serait rognée en haut et
   en bas sans que rien ne le signale, et c'est exactement le défaut qu'on a déjà corrigé sur
   les planches. Le fond neutre tient la place quand le rapport n'est pas 1:1. */
.occasion__lien img { display: block; width: 100%; height: auto; aspect-ratio: 1; object-fit: contain; border-radius: .6rem; background: rgb(var(--gris)); }
.occasion__nom { font-size: 1.6rem; line-height: 1.3; margin: 0 0 .6rem; }
@media screen and (min-width: 750px) { .occasion__nom { margin-top: 1.2rem; } }
.occasion__lien:hover .occasion__nom { text-decoration: underline; }
.occasion__raison { margin: 0; font-size: 1.4rem; line-height: 1.55; color: rgba(var(--color-foreground), .85); }
.occasion__prix { margin: .8rem 0 0; font-weight: 600; }
.planche--departage th[scope="row"], .planche--reperes th[scope="row"] { width: 46%; }
.planche--reperes td { font-variant-numeric: tabular-nums; }
.occasion__retour { margin-top: 3.2rem; font-size: 1.4rem; }

/* Le maillage par l'intention : accueil, collections et pages d'occasion. Des pastilles de
   44 px de haut au moins — c'est la cible tactile minimale, et ces liens sont les premiers
   qu'on touche sur un téléphone quand on ne sait pas encore quoi offrir. */
.occasions-nav { margin: 4.8rem 0 3.2rem; }
.section-padding > .occasions-nav:only-child { margin-top: 0; }
.occasions-nav__titre { font-size: 1.8rem; margin: 0 0 1.6rem; }
.occasions-nav__liste { list-style: none; margin: 0; padding: 0; display: flex; flex-wrap: wrap; gap: 1rem; }
.occasions-nav__lien {
  display: flex; align-items: center; min-height: 4.4rem; padding: 0 1.6rem;
  border: .1rem solid rgba(var(--color-foreground), .25); border-radius: 2.2rem;
  font-size: 1.4rem; text-decoration: none; color: rgb(var(--color-foreground));
}
.occasions-nav__lien:hover { border-color: rgb(var(--color-foreground)); }
/* Dix pastilles tenaient en cinq rangées sur un téléphone, soit 260 px posés juste sous la
   bannière. Resserrées — et les libellés raccourcis, le titre du bandeau disant déjà « pour
   qui » —, elles en font quatre à 320 et 390 px, trois à partir de 430 px et deux sur grand
   écran. Mesuré, pas supposé. La cible tactile de 44 px reste entière : c'est l'air autour
   du texte qui se réduit, pas la zone qu'on touche. */
@media screen and (max-width: 749px) {
  .occasions-nav__liste { gap: .8rem; }
  .occasions-nav__lien { padding: 0 1.2rem; font-size: 1.3rem; }
}

/* Le lien remontant d'une fiche vers sa page d'occasion : une phrase, pas un bouton. Le
   lien reste malgré tout une cible tactile — d'où les 44 px de haut, gagnés par la hauteur
   de ligne et non par une marge, pour ne pas écarter les lignes du paragraphe. */
.fiche__occasion { margin: 2.4rem 0 0; font-size: 1.4rem; }
.fiche__occasion a { display: inline-flex; align-items: center; min-height: 4.4rem; }

/* ---------------------------------------------------------------- accueil

   Refait le 11 sept. 2026. La règle qui tient le reste : **aucun texte posé sur une image**.
   L'ancienne bannière demandait un voile dégradé et une mesure de contraste à chaque
   changement de photo ; ici l'accroche est du texte sur fond uni, donc lisible par
   construction, et la première image est un produit avec son prix. */

.accueil-hero { display: grid; gap: 2.4rem; align-items: center; }
.accueil-hero__titre { font-size: clamp(2.4rem, 6.2vw, 4.6rem); line-height: 1.12; margin: 0 0 1.4rem; letter-spacing: -.02em; }
.accueil-hero__lead { font-size: 1.6rem; line-height: 1.5; max-width: 46ch; margin: 0 0 2.2rem; color: rgba(var(--color-foreground), .82); }
.accueil-hero__boutons { display: flex; flex-wrap: wrap; gap: 1.2rem; margin: 0; }
/* Sur téléphone la photo passe sous les boutons, recadrée en 3/2 : un carré de 92 vw
   mangerait l'écran comme le faisait l'ancienne bannière. Le poignet est au centre du
   cadre, la coupe ne retire donc rien de ce qu'on vient voir. */
.accueil-hero__photo { display: block; width: 100%; height: auto; aspect-ratio: 3 / 2; object-fit: cover; border-radius: var(--card-radius, .8rem); }
/* Deuxième bouton : même cible tactile, poids visuel moindre — deux boutons pleins se
   disputent le clic au lieu de le guider. */
/* `button.` en plus du sélecteur de classe, pour la raison de la ligne 482 : sur un
   <button>, `button.button { background: … }` fait 0-1-1 et écrasait ces 0-1-0. La variante
   secondaire n'a donc jamais fonctionné sur un bouton — seulement sur les <a>. À la caisse,
   « Appliquer » sortait peint du même navy que « Payer », 70 px au-dessus : deux actions de
   même poids dont une seule fait gagner de l'argent. La classe de base reste, sinon les
   liens perdent le style. */
.button--secondaire, button.button--secondaire { background: transparent; color: rgb(var(--color-foreground)); box-shadow: inset 0 0 0 .1rem rgba(var(--color-foreground), .5); }
.button--secondaire:hover { box-shadow: inset 0 0 0 .2rem rgba(var(--color-foreground), .75); }
@media screen and (min-width: 750px) {
  .accueil-hero { grid-template-columns: minmax(0, 1fr) minmax(28rem, 40rem); gap: 4rem; }
  /* En deux colonnes la photo reprend son carré : la colonne lui donne la place. */
  .accueil-hero__photo { aspect-ratio: 1; }
}
@media screen and (min-width: 1200px) { .accueil-hero { grid-template-columns: minmax(0, 1fr) 44rem; gap: 6.4rem; } }

.accueil-rangee__entete { display: flex; align-items: baseline; justify-content: space-between; gap: 1.6rem; margin-bottom: 1.6rem; }
.accueil-rangee__entete h2 { margin: 0; font-size: clamp(2rem, 4vw, 2.6rem); }
/* 47 × 22 px mesuré : c'est le seul chemin vers les quatre bracelets que la rangée ne
   montre pas d'emblée. La hauteur vient de la ligne, pas d'une marge, pour ne pas décaler
   la ligne de base du titre. */
.accueil-rangee__entete a { display: inline-flex; align-items: center; min-height: 4.4rem; }

/* Les avis de l'accueil. Même rangée qui défile que les produits — deux cartes et un bout de
   la troisième sous 750 px, une grille de trois au-delà. Aucune image : la section ne coûte
   rien au chargement, ce qui est la condition pour qu'elle ne freine pas un achat.
   Les cartes sont un peu plus larges que celles des produits : une phrase de client a besoin
   de plus de lignes qu'un titre, et deux cartes de 42 % rendaient les textes illisibles. */
.accueil-avis { padding-top: 4rem; padding-bottom: 4rem; }
.accueil-avis h2 { margin: .4rem 0 2.4rem; font-size: clamp(2rem, 5vw, 2.8rem); letter-spacing: -.02em; }
.accueil-avis__rangee {
  list-style: none; margin: 0; padding: 0 0 1.2rem;
  display: grid; grid-auto-flow: column; grid-auto-columns: 78%; gap: 1.6rem;
  overflow-x: auto; scroll-snap-type: x mandatory; overscroll-behavior-x: contain;
  -webkit-overflow-scrolling: touch; scrollbar-width: none;
}
.accueil-avis__rangee::-webkit-scrollbar { display: none; }
.accueil-avis__carte {
  scroll-snap-align: start; display: flex; flex-direction: column; gap: .6rem;
  background: rgb(var(--creme)); border-radius: 1rem; padding: 1.8rem;
}
.accueil-avis__carte .avis__texte { flex: 1; font-size: 1.5rem; }
/* La cible tactile de 4,4 rem, comme partout : un lien de 22 px de haut ne se vise pas. */
.accueil-avis__lien { display: inline-flex; align-items: center; min-height: 4.4rem; font-size: 1.3rem; color: rgb(var(--navy)); }
/* **La rangée défile à toutes les largeurs**, et non plus seulement sur téléphone : dix avis
   en grille feraient un mur au milieu de l'accueil. Les cartes s'y rétrécissent quand l'écran
   grandit — on en voit trois et le bord de la quatrième, ce qui dit qu'il y en a d'autres.

   Sur grand écran, **la barre de défilement redevient visible** : au doigt une rangée se
   pousse, à la souris il ne se passe rien — la molette fait défiler la page, pas la rangée.
   C'est l'affordance du système, elle ne demande aucun script et elle reste là si celui-ci ne
   charge pas. Les flèches, elles, sont ajoutées par `rangee.js` par-dessus. */
.accueil-avis__cadre { position: relative; }
@media (min-width: 750px) {
  .accueil-avis__rangee { grid-auto-columns: 30%; gap: 2rem; scrollbar-width: thin; padding-bottom: 1.6rem; }
  .accueil-avis__rangee::-webkit-scrollbar { display: block; height: 8px; }
  .accueil-avis__rangee::-webkit-scrollbar-thumb { background: rgba(var(--color-foreground), .25); border-radius: 4px; }
}
@media (min-width: 1100px) {
  .accueil-avis__rangee { grid-auto-columns: 23%; }
}

/* Les flèches : posées sur les bords de la rangée, cible de 4,4 rem comme partout. Elles
   n'existent que si le script a chargé — une flèche qui ne défile pas serait pire que rien. */
.rangee-fleche {
  position: absolute; top: 50%; transform: translateY(-50%); z-index: 2;
  width: 4.4rem; height: 4.4rem; border-radius: 50%; cursor: pointer;
  display: none; align-items: center; justify-content: center;
  background: rgb(var(--creme)); color: rgb(var(--color-foreground));
  border: 1px solid rgba(var(--color-foreground), .18);
  box-shadow: 0 2px 8px rgba(0, 0, 0, .08);
}
.rangee-fleche--avant { left: -1.2rem; }
.rangee-fleche--apres { right: -1.2rem; }
.rangee-fleche:hover { background: #fff; }
/* Au doigt on pousse la rangée : les flèches ne servent qu'à la souris et au clavier. */
@media (min-width: 750px) and (hover: hover) {
  .rangee-fleche { display: inline-flex; }
  .rangee-fleche[hidden] { display: none; }
}

/* La ligne de preuve du premier écran. Elle suit le prix : un chiffre de plus, pas un bloc. */
.accueil-preuve { margin: 1.2rem 0 0; font-size: 1.4rem; }
.accueil-preuve a { display: inline-flex; align-items: center; gap: .6rem; min-height: 4.4rem; color: inherit; text-decoration: none; }
.accueil-preuve a:hover, .accueil-preuve a:focus-visible { text-decoration: underline; }
.accueil-preuve__etoiles { color: rgb(var(--ocre-fonce)); letter-spacing: .08em; }

/* Rangée qui défile au doigt sous 750 px : pas de flèches, pas de JavaScript. Un carrousel
   qui dépend d'un script est un carrousel vide tant que le script n'a pas chargé.
   Pas de marge négative pour la faire déborder de la gouttière : mesuré, elle élargissait
   le document et rendait toute la page défilable de travers. */
.accueil-cartes {
  list-style: none; margin: 0; padding: 0 0 1.2rem;
  display: grid; grid-auto-flow: column; grid-auto-columns: 42%; gap: 1.2rem;
  overflow-x: auto; scroll-snap-type: x mandatory; overscroll-behavior-x: contain;
  -webkit-overflow-scrolling: touch; scrollbar-width: none;
}
.accueil-cartes::-webkit-scrollbar { display: none; }
.accueil-carte { scroll-snap-align: start; }
.accueil-carte a { display: block; text-decoration: none; color: inherit; }
.accueil-carte img {
  display: block; width: 100%; height: auto; aspect-ratio: 1;
  object-fit: contain; background: rgb(var(--gris)); border-radius: var(--card-radius, .8rem);
}
.accueil-carte__nom { display: block; margin: 1rem 0 .2rem; font-size: 1.4rem; line-height: 1.35; }
.accueil-carte a:hover .accueil-carte__nom { text-decoration: underline; }
.accueil-carte__prix { display: block; font-weight: 600; font-size: 1.4rem; }
@media screen and (min-width: 750px) {
  .accueil-cartes { padding: 0; grid-auto-flow: row; grid-auto-columns: auto; grid-template-columns: repeat(3, minmax(0, 1fr)); overflow: visible; gap: 2.4rem; }
}
@media screen and (min-width: 750px) { .accueil-cartes--affiches { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media screen and (min-width: 990px) {
  .accueil-cartes { grid-template-columns: repeat(6, minmax(0, 1fr)); }
  .accueil-cartes--affiches { grid-template-columns: repeat(4, minmax(0, 1fr)); }
}

.accueil-etapes h2 { font-size: clamp(2rem, 4vw, 2.6rem); margin: 0 0 2.4rem; }
.accueil-etapes__liste { list-style: none; counter-reset: etape; margin: 0; padding: 0; display: grid; gap: 2.4rem; }
.accueil-etapes__liste li { counter-increment: etape; padding-left: 4.4rem; position: relative; }
.accueil-etapes__liste li::before {
  content: counter(etape); position: absolute; left: 0; top: 0;
  width: 3.2rem; height: 3.2rem; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  font-size: 1.5rem; font-weight: 600;
  background: rgba(var(--color-foreground), .07); color: rgb(var(--color-foreground));
}
.accueil-etapes__liste strong { display: block; margin-bottom: .4rem; }
.accueil-etapes__liste span { color: rgba(var(--color-foreground), .82); line-height: 1.55; }
@media screen and (min-width: 750px) { .accueil-etapes__liste { grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 3.2rem; } }

.accueil-atelier h2 { font-size: clamp(2rem, 4vw, 2.6rem); margin: 0 0 1.6rem; }
.accueil-atelier p { max-width: 68ch; line-height: 1.6; color: rgba(var(--color-foreground), .82); margin: 0 0 3.2rem; }

/* ---------------------------------------------------------------- accueil — récit de marque

   Le téléphone est la référence : une seule action principale, des cartes à toucher et
   aucun texte sur image. Les composants de catalogue existants restent réemployés pour
   garder les images responsives et le défilement natif, sans JavaScript. */
.accueil-nouvelle-hero { overflow: hidden; background: rgb(var(--creme)); }
.accueil-nouvelle-hero__grille { display: grid; padding-top: 3.2rem; padding-bottom: 0; }
.accueil-nouvelle-hero__texte { padding: 0 0 3.2rem; }
.accueil-surtitre { margin: 0 0 1.2rem; color: rgb(var(--brun)); font-family: var(--font-heading-family); font-size: 1.1rem; font-weight: 650; letter-spacing: .16em; line-height: 1.3; text-transform: uppercase; }
.accueil-nouvelle-hero h1 { max-width: 11ch; font-size: clamp(3.7rem, 11vw, 7.2rem); font-weight: 500; letter-spacing: -.055em; line-height: .98; }
.accueil-nouvelle-hero__lead { max-width: 38ch; margin: 2rem 0 2.4rem; color: rgb(var(--encre-douce)); font-size: 1.8rem; line-height: 1.45; }
.accueil-cta-principal { width: 100%; min-height: 5.4rem; background: rgb(var(--navy)); font-weight: 600; }
.accueil-cta-principal:hover { box-shadow: 0 0 0 .25rem rgba(var(--navy), .24); }
.accueil-nouvelle-hero__prix { margin: 1rem 0 0; color: rgb(var(--encre-douce)); font-size: 1.3rem; text-align: center; }
.accueil-nouvelle-hero__visuel { display: block; margin: 0 -1.5rem; background: rgb(var(--sable)); }
.accueil-nouvelle-hero__visuel img { display: block; width: 100%; aspect-ratio: 4 / 3; object-fit: cover; object-position: center; }

.accueil-intentions { padding-top: 5.6rem; padding-bottom: 5.6rem; }
.accueil-intentions h2, .accueil-fabrication h2, .accueil-selection h2, .accueil-manifeste h2, .accueil-affiches h2, .accueil-promesses h2 { max-width: 17ch; font-size: clamp(2.7rem, 8vw, 4.6rem); letter-spacing: -.04em; line-height: 1.05; }
.accueil-intentions__grille { display: grid; grid-template-columns: 1fr 1fr; gap: 1rem; margin-top: 2.4rem; }
.accueil-intentions .occasions-nav { margin: 3.2rem 0 0; }
.accueil-intentions .occasions-nav__titre { color: rgb(var(--encre-douce)); font-size: 1.5rem; }
.accueil-intention { min-height: 16.4rem; padding: 1.6rem; border-radius: 1.2rem; color: rgb(var(--navy-fonce)); text-decoration: none; transition: transform .18s ease, box-shadow .18s ease; }
.accueil-intention:hover { box-shadow: 0 .7rem 1.8rem rgba(var(--navy-fonce), .12); transform: translateY(-.2rem); }
.accueil-intention > span { display: block; margin-bottom: 2.7rem; font-family: Georgia, serif; font-size: 3.1rem; font-weight: 400; line-height: .8; }
.accueil-intention strong { display: block; font-family: var(--font-heading-family); font-size: 1.7rem; font-weight: 550; line-height: 1.1; }
.accueil-intention small { display: block; margin-top: .7rem; font-size: 1.25rem; line-height: 1.25; }
.accueil-intention--lien { background: rgb(var(--teinte-lien)); }.accueil-intention--aventure { background: rgb(var(--teinte-aventure)); }.accueil-intention--lieu { background: rgb(var(--teinte-lieu)); }.accueil-intention--instant { background: rgb(var(--teinte-instant)); }

.accueil-choisir { padding-top: 5.6rem; padding-bottom: 5.6rem; }
.accueil-choisir__grille { display: grid; gap: 0; margin-top: 3rem; border-top: .1rem solid rgba(var(--color-foreground), .16); }
.accueil-choisir__grille article { padding: 2.4rem 0; border-bottom: .1rem solid rgba(var(--color-foreground), .16); }
.accueil-choisir__grille span { color: rgb(var(--brun)); font-family: var(--font-heading-family); font-size: 1.2rem; font-weight: 650; letter-spacing: .12em; }
.accueil-choisir__grille h3 { margin: .8rem 0; font-size: 2rem; font-weight: 500; letter-spacing: -.025em; }
.accueil-choisir__grille p { max-width: 33ch; margin: 0; color: rgb(var(--encre-douce)); font-size: 1.5rem; line-height: 1.5; }

.accueil-fabrication { background: rgb(var(--navy)); color: #fff; }
.accueil-fabrication .accueil-surtitre { color: rgb(var(--sable)); }
.accueil-fabrication__etapes { display: grid; gap: 2.4rem; margin: 3.2rem 0 0; padding: 0; list-style: none; }
.accueil-fabrication__etapes li { display: grid; grid-template-columns: 4.4rem 1fr; column-gap: 1.2rem; }
.accueil-fabrication__etapes b { color: rgb(var(--sable)); font-family: var(--font-heading-family); font-size: 1.3rem; letter-spacing: .08em; }
.accueil-fabrication__etapes strong { font-family: var(--font-heading-family); font-size: 1.8rem; font-weight: 500; line-height: 1.2; }
.accueil-fabrication__etapes span { grid-column: 2; margin-top: .7rem; color: rgba(255,255,255,.78); font-size: 1.45rem; line-height: 1.5; }

.accueil-selection { padding-top: 5.6rem; padding-bottom: 5.6rem; }
.accueil-selection__entete, .accueil-affiches__entete { display: flex; align-items: end; justify-content: space-between; gap: 1.6rem; margin-bottom: 2.6rem; }
.accueil-selection__entete .underlined-link { display: inline-flex; align-items: center; min-height: 4.4rem; flex: 0 0 auto; }
.accueil-cartes { grid-auto-columns: 62%; gap: 1.4rem; }
.accueil-carte img { border-radius: 1rem; background: rgb(var(--creme)); }
.accueil-carte__nom { margin-top: 1.1rem; font-size: 1.5rem; }
.accueil-carte__prix { color: rgb(var(--brun)); }

.accueil-manifeste { display: grid; gap: 0; padding-top: 0; padding-bottom: 5.6rem; }
.accueil-manifeste__texte { padding: 4.2rem 2.4rem; background: rgb(var(--sable)); }
.accueil-manifeste__texte h2 { max-width: 13ch; }
.accueil-manifeste__texte > p:not(.accueil-surtitre) { max-width: 37ch; margin: 2rem 0 2.4rem; color: rgb(var(--encre-douce)); font-size: 1.7rem; line-height: 1.5; }
.accueil-manifeste img { display: block; width: 100%; aspect-ratio: 1; object-fit: cover; }
.accueil-manifeste .button--secondaire { border-color: rgb(var(--navy)); color: rgb(var(--navy)); }

.accueil-affiches { background: rgb(var(--sauge)); }
.accueil-affiches__recit { display: grid; margin: -3.6rem -1.5rem 3.6rem; }
.accueil-affiches__recit > img { display: block; width: 100%; aspect-ratio: 1; object-fit: cover; }
.accueil-affiches__recit .accueil-affiches__entete { padding: 3.6rem 1.5rem 0; margin: 0; }
.accueil-affiches__entete { display: block; }
.accueil-affiches__entete > div > p:not(.accueil-surtitre) { max-width: 40ch; margin: 1.5rem 0 2.2rem; color: rgb(var(--encre-douce)); font-size: 1.7rem; line-height: 1.5; }
.accueil-affiches__entete .accueil-affiches__detail { font-size: 1.4rem; }
.accueil-affiches__entete .button { min-height: 5rem; width: 100%; background: rgb(var(--navy)); }
.accueil-promesses { padding-top: 5.6rem; padding-bottom: 5.6rem; }
.accueil-promesses .reassurance { margin-top: 3rem; }
.accueil-dernier-cta { padding: 5.6rem 0 calc(5.6rem + env(safe-area-inset-bottom, 0px)); background: rgb(var(--navy)); color: #fff; text-align: center; }
.accueil-dernier-cta .accueil-surtitre { color: rgb(var(--sable)); }
.accueil-dernier-cta h2 { max-width: 17ch; margin: 0 auto; font-size: clamp(3rem, 9vw, 5rem); letter-spacing: -.05em; line-height: 1.02; }
.accueil-dernier-cta > div > p:not(.accueil-surtitre) { max-width: 42ch; margin: 2rem auto 2.8rem; color: rgba(255,255,255,.75); font-size: 1.7rem; line-height: 1.5; }
.accueil-dernier-cta .button { min-height: 5.2rem; width: 100%; background: rgb(var(--sable)); color: rgb(var(--navy-fonce)); font-weight: 650; }
.accueil-dernier-cta__lien { display: inline-flex; align-items: center; min-height: 4.4rem; margin-top: 1.2rem; color: #fff; font-size: 1.4rem; text-decoration: underline; text-underline-offset: .3rem; }

@media screen and (min-width: 750px) {
  .accueil-nouvelle-hero__grille { grid-template-columns: minmax(0, .9fr) minmax(34rem, 1.1fr); align-items: center; min-height: 58rem; padding-top: 0; }
  .accueil-nouvelle-hero__texte { padding: 5.6rem 4rem 5.6rem 0; }
  .accueil-cta-principal { width: auto; min-width: 25rem; }
  .accueil-nouvelle-hero__prix { text-align: left; }
  .accueil-nouvelle-hero__visuel { height: 100%; margin: 0; }
  .accueil-nouvelle-hero__visuel img { height: 100%; aspect-ratio: auto; }
  .accueil-intentions__grille { grid-template-columns: repeat(4, 1fr); }
  .accueil-intention { min-height: 20rem; padding: 2.2rem; }
  .accueil-choisir__grille { grid-template-columns: repeat(3, 1fr); gap: 2.8rem; }
  .accueil-choisir__grille article { min-height: 23rem; padding: 2.6rem 0; }
  .accueil-fabrication__etapes { grid-template-columns: repeat(3, 1fr); gap: 3.2rem; }
  .accueil-fabrication__etapes li { grid-template-columns: 1fr; }
  .accueil-fabrication__etapes span { grid-column: 1; }
  .accueil-cartes { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .accueil-cartes--affiches { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .accueil-manifeste { grid-template-columns: 1fr 1fr; align-items: stretch; }
  .accueil-manifeste__texte { padding: 6rem; }
  .accueil-manifeste img { height: 100%; }
  .accueil-affiches__entete { display: flex; }
  .accueil-affiches__recit { grid-template-columns: 1fr 1fr; align-items: stretch; margin: -5.2rem 0 4.8rem; background: rgb(var(--sauge-dense)); }
  .accueil-affiches__recit > img { height: 100%; }
  .accueil-affiches__recit .accueil-affiches__entete { padding: 5rem; }
  .accueil-affiches__entete .button { width: auto; min-width: 21rem; }
  .accueil-dernier-cta .button { width: auto; min-width: 24rem; }
  .accueil-dernier-cta__lien { margin: 0 0 0 2.4rem; }
}
@media screen and (min-width: 990px) {
  .accueil-cartes { grid-template-columns: repeat(6, minmax(0, 1fr)); }
  .accueil-cartes--affiches { grid-template-columns: repeat(4, minmax(0, 1fr)); }
}

/* ---------- pages fixes : mentions légales, CGV, remboursement, contact ---------- */
/* Ce sont des pages qu'on lit vraiment, souvent au moment de décider d'acheter ou après un
   problème : mesure de lecture bornée, titres qui se repèrent, et le couple terme/valeur des
   identités d'entreprise en deux colonnes plutôt qu'en retrait par défaut du navigateur. */
.page-fixe__titre { margin: 0 0 .4rem; }
.page-fixe__maj { margin: 0 0 2.4rem; font-size: 1.3rem; color: rgba(var(--color-foreground), .6); }
.page-fixe__intro { max-width: 68ch; font-size: 1.7rem; line-height: 1.6; margin: 0 0 3.2rem; }
.page-fixe__corps { max-width: 68ch; }
.page-fixe__corps h2 { font-size: 1.9rem; margin: 3.2rem 0 1rem; }
.page-fixe__corps h2:first-child { margin-top: 0; }
.page-fixe__corps p, .page-fixe__corps li { line-height: 1.7; }
.page-fixe__corps ul { padding-left: 2rem; }
.page-fixe__corps li { margin-bottom: .6rem; }
.page-fixe__liste { display: grid; grid-template-columns: minmax(12rem, 18rem) 1fr; gap: .6rem 2.4rem; margin: 1.6rem 0; }
.page-fixe__liste dt { font-weight: 600; }
.page-fixe__liste dd { margin: 0; }
@media screen and (max-width: 600px) {
  .page-fixe__liste { grid-template-columns: 1fr; gap: .2rem; }
  .page-fixe__liste dd { margin-bottom: 1.2rem; }
}
.page-fixe__soeurs { margin-top: 4.8rem; padding-top: 2.4rem; border-top: 1px solid rgba(var(--color-foreground), .15); max-width: 68ch; }
.page-fixe__soeurs p { margin: 0 0 .8rem; font-weight: 600; }
.page-fixe__soeurs ul { display: flex; flex-wrap: wrap; gap: .6rem 2rem; }
/* Le pied de page porte les mêmes liens, sur toutes les pages : c'est l'obligation légale. */
.footer__pages ul { display: flex; flex-wrap: wrap; justify-content: center; gap: .6rem 1.8rem; margin-bottom: 1.2rem; }
.footer__pages a { font-size: 1.3rem; }

/* Le focus au clavier se voit sur tout ce qui se clique, pas seulement sur les champs. */
a:focus-visible, .accueil-carte a:focus-visible, .occasions-nav__lien:focus-visible {
  outline: .2rem solid rgb(var(--color-foreground)); outline-offset: .2rem; border-radius: .2rem;
}

/* ---------- caisse : adresse, livraison, récapitulatif ---------- */
/* Deux colonnes sur grand écran, le récapitulatif à droite et collant : on remplit une
   adresse en regardant ce qu'on achète. Sur téléphone tout s'empile, le récapitulatif
   passe en dernier — avant le bouton, qui reste la dernière chose qu'on voit. */
.caisse__titre { margin: 0 0 2.4rem; }
.caisse__grille { display: grid; gap: 3.2rem; align-items: start; }
@media screen and (min-width: 990px) { .caisse__grille { grid-template-columns: 1fr 34rem; } }
.caisse__colonne { display: grid; gap: 2.4rem; min-width: 0; }
.caisse__bloc { border: 0; padding: 0; margin: 0; display: grid; gap: 1.2rem; }
.caisse__bloc legend { font-size: 1.7rem; font-weight: 600; padding: 0; margin-bottom: .8rem; }
.caisse__deux { display: grid; gap: 1.2rem; grid-template-columns: 1fr 1fr; }
@media screen and (max-width: 600px) { .caisse__deux { grid-template-columns: 1fr; } }
.caisse__champ { display: grid; gap: .4rem; }
.caisse__champ label { font-size: 1.3rem; font-weight: 600; }
.caisse__champ small { font-weight: 400; color: rgba(var(--color-foreground), .6); }
/* 1,6 rem et non 1,5 : c'est la règle de la ligne 972, qui n'avait couvert que la fiche —
   iOS zoome sur tout champ sous 16 px et ne revient jamais à l'échelle initiale. Neuf
   champs d'adresse, neuf zooms, sur la page où il faut justement voir le bouton. Et la
   bordure repasse à .55, la valeur du reste du site : à .35 elle tombait à 2,22 de
   contraste, sous le seuil de 3 d'un élément d'interface. La caisse était le seul endroit
   qui affaiblissait ses champs. */
.caisse__champ input, .caisse__champ select { width: 100%; padding: 1rem 1.2rem; font-size: 1.6rem; border: 1px solid rgba(var(--color-foreground), .55); border-radius: .4rem; background: rgb(var(--color-background)); color: rgb(var(--color-foreground)); }
.caisse__champ input[aria-invalid="true"] { border-color: rgb(var(--rouge)); box-shadow: 0 0 0 1px rgb(var(--rouge)); }
/* Safari applique à un <select> son dessin natif — le « menulist » — et jette la police et
   le fond écrits : mesuré à 25,6 px sur fond transparent, au milieu de huit champs blancs à
   16 px, sur le champ qui fixe le prix du port. `appearance: none` le ramène dans le rang,
   mais efface aussi la flèche, et sans elle une liste ressemble à un champ où l'on ne peut
   pas taper. Le chevron est donc redessiné par l'enveloppe, en `currentColor` — aucune
   couleur écrite (point 6 quater) — et le champ lui garde sa place à droite. */
.caisse__select { position: relative; display: block; }
.caisse__select select { -webkit-appearance: none; appearance: none; padding-right: 3.6rem; }
.caisse__select::after { content: ''; position: absolute; right: 1.5rem; top: 50%; width: .8rem; height: .8rem; border-right: .15rem solid currentColor; border-bottom: .15rem solid currentColor; transform: translateY(-70%) rotate(45deg); pointer-events: none; }
.caisse__recalculer { justify-self: start; margin-top: .8rem; }
.caisse__mode { display: grid; grid-template-columns: auto 1fr auto; gap: .4rem 1.2rem; align-items: center; padding: 1.2rem; border: 1px solid rgba(var(--color-foreground), .2); border-radius: .6rem; cursor: pointer; }
.caisse__mode:has(input:checked) { border-color: rgb(var(--color-foreground)); box-shadow: inset 0 0 0 1px rgb(var(--color-foreground)); }
.caisse__mode-nom { font-weight: 600; }
/* Le transporteur à côté du mode : c'est un nom propre, il ne se traduit pas, mais il doit
   se lire — une « livraison offerte » sans transporteur nommé n'est qu'une promesse vague. */
.caisse__mode-transporteur { font-weight: 400; color: rgba(var(--color-foreground), .65); }
.caisse__mode-delai { grid-column: 2; font-size: 1.3rem; color: rgba(var(--color-foreground), .7); }
.caisse__mode-prix { grid-row: 1 / span 2; grid-column: 3; font-variant-numeric: tabular-nums; }
.caisse__resume { display: grid; gap: 1.2rem; padding: 2rem; border: 1px solid rgba(var(--color-foreground), .15); border-radius: .8rem; background: rgba(var(--color-foreground), .03); }
@media screen and (min-width: 990px) { .caisse__resume { position: sticky; top: 2rem; } }
.caisse__resume h2 { font-size: 1.7rem; margin: 0; }
.caisse__articles { display: grid; gap: 1.2rem; margin: 0; padding: 0; list-style: none; }
.caisse__articles li { display: grid; gap: .2rem; padding-bottom: 1.2rem; border-bottom: 1px solid rgba(var(--color-foreground), .12); }
.caisse__article-nom { font-weight: 600; }
.caisse__article-variante, .caisse__article-perso { font-size: 1.3rem; color: rgba(var(--color-foreground), .7); }
.caisse__article-prix { font-variant-numeric: tabular-nums; }
.caisse__totaux { display: grid; grid-template-columns: 1fr auto; gap: .6rem 1.2rem; margin: 0; }
.caisse__totaux dd { margin: 0; text-align: right; font-variant-numeric: tabular-nums; }
.caisse__total { font-weight: 700; font-size: 1.7rem; }
/* 5,6 rem comme le bouton d'achat de la fiche, et `button.` dans le sélecteur pour la même
   raison qu'à la ligne 482 : `button.button { min-height: 4.5rem }` a la même spécificité
   0-1-0 et gagnerait à l'ancienneté. Le bouton qui encaisse était resté le plus petit des
   trois de l'entonnoir — 45 px contre 56 pour l'« Ajouter au panier » qui le précède. */
button.caisse__payer { min-height: 5.6rem; font-size: 1.6rem; }
/* Et le bouton « remonter » disparaît de cette page. Mesuré au navigateur, Safari comme
   Chrome : son disque mordait 24 × 36 px sur le coin bas droit du bouton Payer — là où
   tombe un pouce droit sur un bouton pleine largeur. Le client visait Payer, remontait de
   2 400 px sans un mot et croyait avoir raté sa cible. La fiche l'avait déjà écarté de sa
   barre d'achat (ligne 1108) ; la caisse n'avait jamais été couverte. Ici il n'a de toute
   façon aucun sens : rien en haut ne se revoit, et le seul geste qui compte est en bas. */
body:has(#caisse) .haut { display: none; }
.caisse__note { font-size: 1.2rem; color: rgba(var(--color-foreground), .7); margin: 0; }
.caisse__erreur { padding: 1.2rem 1.6rem; border-radius: .6rem; background: rgba(var(--rouge), .1); color: rgb(var(--rouge)); font-weight: 600; margin: 0 0 2.4rem; }
.caisse__etat, .caisse__reference { max-width: 60ch; font-size: 1.6rem; }
.caisse__suite { margin: 3.2rem 0; max-width: 60ch; }
.caisse__suite ol { padding-left: 2rem; }
.caisse__suite li { margin-bottom: .8rem; }
.caisse__recu { display: grid; gap: 3.2rem; margin-top: 3.2rem; }
@media screen and (min-width: 750px) { .caisse__recu { grid-template-columns: 1fr 1fr; } }
.caisse__adresse { line-height: 1.7; }

/* ---------------------------------------------------------------- notre histoire

   La seule page fixe qui raconte. Elle est longue à dessein : on ne lit pas une histoire
   en trois lignes. Tous les dessins sont du SVG écrit dans la page — aucune image à
   charger, aucun appel extérieur — et ils prennent la couleur du texte, donc ils suivent
   la charte sans qu'on ait à les refaire. */

.histoire { display: block; }
/* Une colonne de lecture, centrée : sur un écran large, 62 signes de texte collés au bord
   gauche d'une bande de 1 100 px laissent un demi-écran de blanc à droite et la page a
   l'air inachevée. La scène, elle, reste pleine largeur. */
.histoire > section, .histoire > header, .histoire > nav { padding-top: 2.4rem; padding-bottom: 2.4rem; max-width: 74rem; margin-inline: auto; }
.histoire h1 { font-size: clamp(3rem, 8vw, 5.6rem); line-height: 1.05; letter-spacing: -.02em; margin: 0 0 1.6rem; }
.histoire h2 { font-size: clamp(2rem, 4.4vw, 2.8rem); line-height: 1.2; margin: 0 0 1.6rem; }
.histoire p { max-width: 62ch; line-height: 1.7; font-size: 1.6rem; margin: 0 0 1.6rem; }
.histoire__chapo { font-size: clamp(1.7rem, 3.4vw, 2.1rem); line-height: 1.5; color: rgba(var(--color-foreground), .78); max-width: 44ch; }
.histoire__ouverture { padding-bottom: 3.2rem; }

/* La scène : pleine largeur, hauteur bornée pour qu'elle ne mange pas l'écran d'un
   téléphone comme le faisait l'ancienne bannière. */
.histoire__scene { width: 100%; overflow: hidden; background: rgb(var(--creme)); }
.histoire__scene svg { display: block; width: 100%; height: clamp(17rem, 26vw, 30rem); }

/* Ce qui bouge, et pourquoi. Le soleil monte une fois au chargement. La brume dérive sans
   fin, très lentement. Et les bêtes vivent : la queue bat pour chasser les mouches, la tête
   descend brouter puis se relève, l'oreille tressaille. Chaque bête a ses propres durées et
   ses propres décalages — quatre animaux synchronisés, ce serait un logo, pas un troupeau.
   Tout s'arrête si le système demande moins d'animation. */
@keyframes histoire-soleil { from { transform: translateY(30px); opacity: .5; } to { transform: translateY(0); opacity: 1; } }
@keyframes histoire-brume { from { transform: translateX(-120px); } to { transform: translateX(120px); } }
/* Le mouvement est au **début** du cycle, pas à la fin. Il y était : la queue ne partait
   qu'à 54 % d'un cycle de six secondes, et les retards d'entrée allaient jusqu'à 5,5 s —
   une bête pouvait rester immobile huit secondes après l'ouverture de la page, c'est-à-dire
   plus longtemps qu'on ne regarde un dessin. */
@keyframes histoire-queue {
  0% { transform: rotate(0deg); }
  8% { transform: rotate(-16deg); }
  18% { transform: rotate(11deg); }
  28% { transform: rotate(-6deg); }
  36% { transform: rotate(3deg); }
  44%, 100% { transform: rotate(0deg); }
}
@keyframes histoire-broute {
  0%, 6% { transform: rotate(0deg); }
  22%, 58% { transform: rotate(11deg); }
  74%, 100% { transform: rotate(0deg); }
}
@keyframes histoire-oreille {
  0% { transform: rotate(0deg); }
  6% { transform: rotate(-20deg); }
  12% { transform: rotate(7deg); }
  18%, 100% { transform: rotate(0deg); }
}
.histoire__soleil { animation: histoire-soleil 5s cubic-bezier(.22,.61,.36,1) both; }
.histoire__brume { animation: histoire-brume 26s ease-in-out infinite alternate; }
/* `fill-box` cale le pivot sur la boîte du dessin lui-même : la queue tourne depuis la
   croupe, l'encolure depuis le garrot, l'oreille depuis sa base. Sans ça, chaque bête
   tournerait autour d'un point du plan et partirait en travers. */
.histoire__queue, .histoire__tete, .histoire__oreille { transform-box: fill-box; }
.histoire__queue { transform-origin: 100% 0%; animation: histoire-queue 3.2s ease-in-out infinite; }
.histoire__tete { transform-origin: 0% 45%; animation: histoire-broute 5.5s ease-in-out infinite; }
.histoire__oreille { transform-origin: 100% 20%; animation: histoire-oreille 4s ease-in-out infinite; }

/* Les retards sont **négatifs** : un retard positif fait attendre, un retard négatif place
   la bête plus loin dans son cycle dès la première image. Le troupeau reste désynchronisé —
   ce qu'on voulait — mais tout le monde est déjà en mouvement à l'ouverture. */
.histoire__bete--a .histoire__queue { animation-duration: 3.6s; animation-delay: -1.2s; }
.histoire__bete--a .histoire__tete { animation-duration: 6.2s; animation-delay: -2.5s; }
.histoire__bete--a .histoire__oreille { animation-duration: 4.6s; animation-delay: -.6s; }
.histoire__bete--b .histoire__queue { animation-duration: 2.9s; animation-delay: -.4s; }
.histoire__bete--b .histoire__tete { animation-duration: 5.1s; animation-delay: -3.4s; }
.histoire__bete--b .histoire__oreille { animation-duration: 3.7s; animation-delay: -2.1s; }
.histoire__bete--c .histoire__queue { animation-duration: 4.1s; animation-delay: -2.8s; }
.histoire__bete--c .histoire__tete { animation-duration: 6.8s; animation-delay: -1.1s; }
.histoire__bete--c .histoire__oreille { animation-duration: 5.2s; animation-delay: -3.9s; }
/* Marcel ne broute pas : il regarde. Un taureau au milieu de ses blondes lève la tête,
   et c'est le seul détail qui le distingue avec la taille et le pis en moins. */
.histoire__bete--marcel .histoire__tete { animation: none; }
.histoire__bete--marcel .histoire__queue { animation-duration: 2.6s; animation-delay: -.2s; }
.histoire__bete--marcel .histoire__pis { display: none; }
@media (prefers-reduced-motion: reduce) {
  .histoire__soleil, .histoire__brume, .histoire__queue, .histoire__tete, .histoire__oreille { animation: none; }
}
.histoire__bete--marcel { filter: drop-shadow(0 .2rem .4rem rgba(0, 0, 0, .12)); }
/* La montée à l'estive se trace au chargement : le trait part de mai et rejoint le sommet.
   C'est le seul mouvement de la page qui dit quelque chose, les autres sont de l'ambiance. */
@keyframes histoire-trace { from { stroke-dashoffset: 340; } to { stroke-dashoffset: 0; } }
.histoire__estive-montee { stroke-dasharray: 340; animation: histoire-trace 2.2s ease-out both; }
@media (prefers-reduced-motion: reduce) { .histoire__estive-montee { stroke-dasharray: none; animation: none; } }
@media (prefers-reduced-motion: reduce) {
  .histoire__soleil, .histoire__brume, .histoire__queue { animation: none; }
}

/* La phrase de Cornélia : c'est elle qui a donné le nom, elle a droit à la taille. */
.histoire__citation { margin: 3.2rem 0; padding-left: 2rem; border-left: .3rem solid rgba(var(--color-foreground), .18); }
.histoire__citation blockquote { margin: 0; }
.histoire__citation p { font-size: clamp(2rem, 4.6vw, 2.8rem); line-height: 1.3; font-style: italic; margin: 0 0 1rem; max-width: 26ch; }
.histoire__citation figcaption { font-size: 1.4rem; color: rgba(var(--color-foreground), .62); }

/* Les quatre formats emboîtés : même traitement que le schéma de la plaque, puisqu'ils
   racontent la même chose à l'autre bout de l'échelle. */
.histoire__formats { margin: 3.2rem 0 0; max-width: 34rem; }
.histoire__formats svg { width: 100%; height: auto; color: rgb(var(--brun)); }
.histoire__formats figcaption { margin: 1rem 0 0; font-size: 1.3rem; color: rgb(var(--encre-douce)); }
.histoire__affiches p { max-width: 68ch; }
.histoire__estive, .histoire__chemin, .histoire__gravure {
  margin: 3.2rem 0 0; padding: 2.4rem; border-radius: var(--card-radius, .8rem);
  background: rgba(var(--color-foreground), .035);
}
.histoire__estive svg, .histoire__gravure svg { display: block; width: 100%; height: auto; color: rgb(var(--color-foreground)); }
.histoire__estive figcaption, .histoire__chemin figcaption { font-size: 1.5rem; font-weight: 700; margin-bottom: 1.6rem; }
.histoire__gravure { display: grid; gap: 1.6rem; justify-items: center; }
.histoire__gravure svg { max-width: 38rem; }
.histoire__gravure figcaption { font-size: 1.4rem; color: rgba(var(--color-foreground), .7); max-width: 46ch; }
/* La gravure d'exemple est en Montserrat, la police de la graveuse : c'est ce que le
   client relit dans le récapitulatif, autant que ce soit la même ici. */
.histoire__gravure-texte { font-family: var(--font-heading-family, inherit); }

/* Le chemin : une ligne d'étapes, Estaing marqué. En colonne sur téléphone — six noms de
   villages en ligne à 320 px, ce serait six mots coupés. */
.histoire__etapes { list-style: none; margin: 0 0 1.2rem; padding: 0; display: grid; gap: 0; }
.histoire__etapes li { position: relative; padding: 0 0 1.8rem 2.8rem; font-size: 1.5rem; line-height: 1.3; }
.histoire__etapes li::before { content: ""; position: absolute; left: .55rem; top: 1.2rem; bottom: -.6rem; width: .2rem; background: rgba(var(--color-foreground), .2); }
.histoire__etapes li:last-child::before { display: none; }
.histoire__etapes li span { position: absolute; left: 0; top: .35rem; width: 1.3rem; height: 1.3rem; border-radius: 50%; background: rgba(var(--color-foreground), .25); }
.histoire__etape--ici { font-weight: 700; }
.histoire__etape--ici span { background: rgb(var(--color-accent)); box-shadow: 0 0 0 .4rem rgba(var(--color-accent), .18); }

.histoire__promesses { display: grid; gap: 2.4rem; margin: 0 0 4rem; max-width: 74rem; }
.histoire__promesses dt { font-weight: 700; margin-bottom: .4rem; }
.histoire__promesses dd { margin: 0; line-height: 1.65; color: rgba(var(--color-foreground), .84); }
@media screen and (min-width: 750px) { .histoire__promesses { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 3.2rem 4rem; } }
.histoire__jamais-titre { margin-top: 0; }
.histoire__jamais { max-width: 62ch; line-height: 1.7; padding-left: 2rem; }
.histoire__jamais li { margin-bottom: .8rem; }

.histoire__frise { list-style: none; margin: 0; padding: 0; display: grid; gap: 2.4rem; max-width: 74rem; }
.histoire__frise li { display: grid; grid-template-columns: 11rem 1fr; gap: 1.6rem; align-items: baseline; }
.histoire__frise strong { font-size: 1.8rem; color: rgb(var(--color-accent)); }
.histoire__frise span { line-height: 1.6; }
@media screen and (max-width: 479px) { .histoire__frise li { grid-template-columns: 1fr; gap: .4rem; } }

.histoire__fin-boutons { display: flex; flex-wrap: wrap; gap: 1.2rem; margin-top: 2.4rem; }

/* ---------- caisse : le choix du point relais ---------- */
/* La liste et la carte côte à côte, et la liste seule sur téléphone — une carte de 300 px de
   haut sur un écran de téléphone mange la page pour montrer six repères. La liste défile,
   elle porte tout ce qu'il faut décider : le nom, l'enseigne, l'adresse, la distance. */
.caisse__relais { margin-top: 1.6rem; display: grid; gap: 1.2rem; }
.caisse__relais-titre { font-weight: 600; margin: 0; }
.caisse__relais-bloc { display: grid; gap: 1.6rem; }
@media screen and (min-width: 750px) { .caisse__relais-bloc { grid-template-columns: 1fr 1fr; } }
.caisse__relais-carte { height: 34rem; border-radius: .6rem; overflow: hidden; background: rgb(var(--creme)); }
.caisse__relais-carte[aria-hidden="true"] { display: none; }
.caisse__relais-liste { list-style: none; margin: 0; padding: 0; max-height: 34rem; overflow-y: auto; display: grid; gap: .8rem; }
.caisse__relais-liste label { display: grid; grid-template-columns: auto 1fr auto; gap: .2rem .8rem; padding: 1rem 1.2rem; border: 1px solid rgba(var(--color-foreground), .2); border-radius: .6rem; cursor: pointer; }
.caisse__relais-liste label:has(input:checked) { border-color: rgb(var(--color-foreground)); box-shadow: inset 0 0 0 1px rgb(var(--color-foreground)); }
.caisse__relais-nom { font-weight: 600; }
.caisse__relais-reseau { grid-column: 3; font-size: 1.2rem; color: rgba(var(--color-foreground), .6); }
.caisse__relais-adresse { grid-column: 2 / span 2; font-size: 1.3rem; color: rgba(var(--color-foreground), .75); }
.caisse__relais-distance { grid-column: 2 / span 2; font-size: 1.2rem; color: rgba(var(--color-foreground), .6); font-variant-numeric: tabular-nums; }
.caisse__relais-horaires { margin: .2rem 0 0 1.2rem; font-size: 1.2rem; }
.caisse__relais-horaires summary { cursor: pointer; color: rgba(var(--color-foreground), .7); }
.caisse__relais-horaires dl { display: grid; grid-template-columns: auto 1fr; gap: .2rem 1.2rem; margin: .6rem 0 0; }
.caisse__relais-horaires dd { margin: 0; font-variant-numeric: tabular-nums; }
/* Le repère sur la carte : une pastille cliquable, plus grande quand elle est choisie. */
.caisse__repere { width: 1.8rem; height: 1.8rem; border-radius: 50%; border: 2px solid #fff; background: rgb(var(--navy)); box-shadow: 0 1px 4px rgba(0, 0, 0, .4); cursor: pointer; padding: 0; transition: transform .12s ease; }
.caisse__repere--actif { background: rgb(var(--rouge)); transform: scale(1.45); }

/* ---------- atelier : la liste des commandes et le bon de travail ---------- */
/* Une page d'outil, pas une vitrine : on y vient pour voir ce qu'il y a à faire et cliquer
   un bouton. Lisible, dense, sans décor. */

/* La page de téléchargement des fichiers d'affiche : une liste de liens, pas un tableau —
   il y a deux choses à lire par ligne, le format et ce que pèse le fichier. */
.telechargement__liste { list-style: none; margin: 1.6rem 0 0; padding: 0; display: grid; gap: .8rem; grid-template-columns: repeat(auto-fill, minmax(24rem, 1fr)); }
.telechargement__liste a { display: flex; align-items: baseline; justify-content: space-between; gap: 1.2rem; padding: 1.4rem 1.6rem; border: .1rem solid rgb(var(--bordure)); border-radius: var(--inputs-radius); text-decoration: none; color: rgb(var(--color-foreground)); }
.telechargement__liste a:hover { border-color: rgb(var(--navy)); background: rgb(var(--creme)); }
.telechargement__liste strong { font-size: 1.6rem; }
.telechargement__liste span { color: rgb(var(--encre-pale)); font-size: 1.3rem; }

/* Le code promo, à la caisse. Il est au-dessus des totaux et non en haut de page : c'est au
   moment de voir le prix qu'on se souvient d'en avoir un. */
.caisse__promo { margin: 2rem 0 1.2rem; }
.caisse__promo label { display: block; font-size: 1.3rem; font-weight: 600; margin-bottom: .6rem; }
.caisse__promo-ligne { display: flex; gap: .8rem; }
.caisse__promo-ligne input { text-transform: uppercase; }
.caisse__promo-ligne button { flex: 0 0 auto; }
.caisse__promo-refus { margin: .6rem 0 0; font-size: 1.3rem; color: rgb(var(--rouge)); }
.caisse__promo-ok { margin: .6rem 0 0; font-size: 1.3rem; color: rgb(var(--brun)); }

/* ---------- partager une page ---------- */
/* De vrais liens vers la fenêtre de partage des plateformes, sans un script chargé (voir
   `views/partage.liquid`). Ils sont en bas de la colonne de gauche sur une fiche : la colonne
   d'achat ne garde que ce qui sert à commander. Cibles à 44 px, comme partout ailleurs. */
.partage { margin: 2.4rem 0 0; padding: 1.6rem 0 0; border-top: .1rem solid rgb(var(--bordure)); display: flex; flex-wrap: wrap; align-items: center; gap: .8rem 1.6rem; }
.partage__titre { font-size: 1.3rem; font-weight: 600; color: rgb(var(--encre-pale)); letter-spacing: .04rem; text-transform: uppercase; }
.partage__liste { list-style: none; margin: 0; padding: 0; display: flex; flex-wrap: wrap; gap: .8rem; }
.partage__lien { display: inline-flex; align-items: center; gap: .8rem; min-height: 4.4rem; padding: 0 1.6rem; border: .1rem solid rgb(var(--bordure)); border-radius: var(--inputs-radius); text-decoration: none; font-size: 1.4rem; color: rgb(var(--color-foreground)); }
.partage__lien:hover { border-color: rgb(var(--navy)); background: rgb(var(--creme)); }
/* Les marques gardent leurs couleurs propres : c'est ce qui les rend reconnaissables en
   diagonale, et c'est déjà la règle des logos de paiement. Elles ne suivent pas le texte. */
.icone-reseau { flex: none; display: block; }

/* Les profils sociaux, au pied de page. Le nom du réseau et rien d'autre : un logo de
   plateforme est une marque déposée servie par un tiers, et le nom se reconnaît aussi bien. */
/* Le libellé et les liens sur une ligne, le libellé en retrait de ton : c'est lui qui dit
   qu'on change de registre après les liens légaux. Il passe à la ligne sur un écran étroit. */
.footer__reseaux { display: flex; flex-wrap: wrap; align-items: center; gap: .4rem 1.6rem; }
.footer__reseaux-titre { font-size: 1.2rem; font-weight: 600; letter-spacing: .06rem; text-transform: uppercase; color: rgb(var(--encre-pale)); }
.footer__reseaux ul { list-style: none; margin: 0; padding: 0; display: flex; flex-wrap: wrap; gap: 1.6rem; }
.footer__reseaux a { display: inline-flex; align-items: center; gap: .6rem; min-height: 4.4rem; font-size: 1.4rem; font-weight: 500; color: rgb(var(--color-foreground)); }

/* ————————————————————————— Le bandeau d'atelier ————————————————————————— *
 * La fiche servie à l'atelier quand il compose l'affiche d'une commande Etsy : ce que
 * l'acheteur a tapé reste sous les yeux pendant qu'on remplit les champs. Il ne paraît
 * jamais pour un visiteur — la variable `atelier` n'existe que sur cette page-là. */
.atelier-bandeau { background: rgb(var(--navy)); color: #fff; padding: 1.2rem 0; }
.atelier-bandeau__titre { margin: 0; font-size: 1.4rem; font-weight: 600; }
.atelier-bandeau__saisie { margin: .4rem 0 0; font-size: 1.5rem; white-space: pre-wrap; }
.atelier-bandeau__retour { margin: .6rem 0 0; font-size: 1.3rem; }
.atelier-bandeau a { color: #fff; text-decoration: underline; }
