/* =========================================================================
   Logo-Deco : socle commun aux deux propositions.
   Jetons, reprise, typographie, primitives partagees (bouton, champ, lien,
   surfaces du navigateur). Les propositions A et B ne redefinissent que la
   composition, jamais ces valeurs.
   ========================================================================= */

/* --- Fontes auto-hebergees ------------------------------------------------
   Familjen Grotesk (Letters from Sweden) et Schibsted Grotesk (Schibsted) sont
   deux grotesques scandinaves. Variables : un fichier couvre toutes les graisses.
   Auto-hebergees pour eviter tout appel a un serveur tiers, ce qui evite aussi
   la question du transfert d'adresses IP vers Google Fonts.                 */

@font-face {
  font-family: "Familjen Grotesk";
  src: url("../fonts/familjen-grotesk-latin.woff2") format("woff2");
  font-weight: 400 700;
  font-style: normal;
  font-display: swap;
  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: "Familjen Grotesk";
  src: url("../fonts/familjen-grotesk-latin-ext.woff2") format("woff2");
  font-weight: 400 700;
  font-style: normal;
  font-display: swap;
  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: "Schibsted Grotesk";
  src: url("../fonts/schibsted-grotesk-latin.woff2") format("woff2");
  font-weight: 400 600;
  font-style: normal;
  font-display: swap;
  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: "Schibsted Grotesk";
  src: url("../fonts/schibsted-grotesk-latin-ext.woff2") format("woff2");
  font-weight: 400 600;
  font-style: normal;
  font-display: swap;
  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: "Urbanist";
  src: url("../fonts/urbanist-latin.woff2") format("woff2");
  font-weight: 800;
  font-style: normal;
  font-display: swap;
  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: "Urbanist";
  src: url("../fonts/urbanist-latin-ext.woff2") format("woff2");
  font-weight: 800;
  font-style: normal;
  font-display: swap;
  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;
}

/* Repli metrique du logotype. Mesure au navigateur, a 28 px et en graisse 800 :
   l'ancienne pile de secours dessinait "logo-deco" sur 143,1 px la ou Urbanist
   le dessine sur 123,2 px, soit 16 % de trop. Le logo apparaissait donc plus
   gros, puis retrecissait d'un coup des qu'Urbanist arrivait. Ce repli vise la
   graisse grasse d'Arial (126,4 px brut) et la ramene par size-adjust a moins
   d'un pixel d'Urbanist, ce qui rend l'echange invisible. Si aucune de ces
   polices n'est installee, la declaration echoue et la pile d'origine reprend
   la main. */
@font-face {
  font-family: "Urbanist secours";
  src: local("Arial Bold"), local("Arial-BoldMT"), local("Helvetica Neue Bold"),
    local("Helvetica-Bold"), local("Liberation Sans Bold"), local("Arimo Bold");
  font-weight: 800;
  font-style: normal;
  size-adjust: 97.5%;
}

/* --- Jetons ------------------------------------------------------------- */

:root {
  color-scheme: light;

  /* Palette. Le blanc porte la page, le creme se pose par-dessus pour separer
     les blocs. Aucune couleur d'accent, aucun fond sombre : le client a pose
     l'absence de sombre comme sa premiere consigne. Encre et creme viennent de
     la charte du logotype. */
  --papier: #ffffff;
  /* Le creme de la charte (#f3f1eb) est juste pour un logotype, mais trop
     proche du blanc pour qu'une bande se distingue a l'ecran. Les fonds sont
     donc descendus de deux crans, en gardant la meme teinte. */
  --papier-2: #eee9dd;
  --papier-3: #e2dbc9;
  --encre: #242521;
  --encre-2: #55564f;
  --trait: #d8d2c2;
  --trait-fort: #b0aa99;

  /* Etats fonctionnels. Employes uniquement dans le formulaire, jamais en decor. */
  --alerte: #8a3520;
  --valide: #33513e;

  /* Typographie */
  --f-titre: "Familjen Grotesk", "Helvetica Neue", Arial, sans-serif;
  --f-texte: "Schibsted Grotesk", "Helvetica Neue", Arial, sans-serif;
  --f-logo: "Urbanist", "Urbanist secours", "Helvetica Neue", Arial, sans-serif;

  --t-h1: clamp(2.25rem, 5.6vw, 4.5rem);
  --t-h2: clamp(1.65rem, 3.4vw, 2.75rem);
  --t-h3: clamp(1.2rem, 1.8vw, 1.5rem);
  --t-texte: clamp(1rem, 0.96rem + 0.2vw, 1.125rem);
  --t-grand: clamp(1.15rem, 1.02rem + 0.6vw, 1.5rem);
  --t-petit: 0.875rem;
  --t-etiquette: 0.75rem;

  /* Rythme vertical. Une seule echelle pour tout le site. */
  --pas-1: 0.5rem;
  --pas-2: 1rem;
  --pas-3: 1.5rem;
  --pas-4: 2.5rem;
  --pas-5: 4rem;
  --pas-6: clamp(5.5rem, 11vw, 10rem);
  --pas-7: clamp(7rem, 15vw, 13rem);

  --gouttiere: clamp(1.25rem, 4vw, 4rem);
  --largeur-max: 1500px;
  --mesure: 64ch;

  --entete-h: 5rem;

  /* Mouvement. Sortie exponentielle, depuis un etat deja visible. */
  --sortie: cubic-bezier(0.16, 1, 0.3, 1);
  --duree: 480ms;
  --duree-courte: 180ms;
}

/* --- Reprise ------------------------------------------------------------ */

*,
*::before,
*::after {
  box-sizing: border-box;
}

/* L'attribut hidden n'a aucun poids propre : la moindre regle qui pose un
   display explicite sur le meme element le neutralise, et l'element reste
   visible alors que le balisage le dit cache. Le site s'y est repris six
   fois, une exception par composant (.nav, .bandeau-cookies__panneau,
   .confirmation, .liste__choix, .devis__avis, .calendrier). Celle-ci vaut
   pour tous. Le !important est a sa place : il n'y a aucun cas ou l'on
   veuille afficher un element porteur de hidden. */
[hidden] {
  display: none !important;
}

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
}

@media (prefers-reduced-motion: reduce) {
  html {
    scroll-behavior: auto;
  }
}

body {
  margin: 0;
  background: var(--papier);
  color: var(--encre);
  font-family: var(--f-texte);
  font-size: var(--t-texte);
  line-height: 1.6;
  font-feature-settings: "kern" 1;
  text-rendering: optimizeLegibility;
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}

h1,
h2,
h3,
h4,
p,
figure,
blockquote,
ul,
ol,
dl {
  margin: 0;
}

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

img,
picture,
svg,
video {
  display: block;
  max-width: 100%;
}

img {
  height: auto;
}

button,
input,
select,
textarea {
  font: inherit;
  color: inherit;
}

/* --- Surfaces du navigateur ---------------------------------------------
   Selection, curseur de saisie, barre de defilement, anneau de focus et
   soulignement : autant de details rendus par defaut en bleu systeme, et qui
   n'appartiennent a aucun systeme de design tant qu'on ne les habille pas. */

::selection {
  background: var(--encre);
  color: var(--papier);
}

:root {
  scrollbar-color: var(--trait-fort) var(--papier);
  scrollbar-width: thin;
  accent-color: var(--encre);
  caret-color: var(--encre);
}

::-webkit-scrollbar {
  width: 11px;
  height: 11px;
}
::-webkit-scrollbar-track {
  background: var(--papier);
}
::-webkit-scrollbar-thumb {
  background: var(--trait-fort);
  border: 3px solid var(--papier);
}
::-webkit-scrollbar-thumb:hover {
  background: var(--encre-2);
}

:focus-visible {
  outline: 2px solid var(--encre);
  outline-offset: 3px;
}

/* --- Typographie -------------------------------------------------------- */

.h1,
.h2,
.h3 {
  font-family: var(--f-titre);
  font-weight: 500;
  letter-spacing: -0.024em;
  text-wrap: balance;
}

.h1 {
  font-size: var(--t-h1);
  line-height: 1.06;
}

.h2 {
  font-size: var(--t-h2);
  line-height: 1.1;
}

.h3 {
  font-size: var(--t-h3);
  line-height: 1.16;
  letter-spacing: -0.012em;
}

.texte {
  max-width: var(--mesure);
  color: var(--encre-2);
}

.texte-grand {
  font-size: var(--t-grand);
  line-height: 1.42;
  max-width: 46ch;
  color: var(--encre);
}

.etiquette {
  font-size: var(--t-etiquette);
  font-weight: 500;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--encre-2);
}

.chiffres {
  font-variant-numeric: tabular-nums;
  font-feature-settings: "tnum" 1;
}

/* --- Liens -------------------------------------------------------------- */

a {
  color: inherit;
  text-decoration-thickness: 1px;
  text-underline-offset: 0.22em;
}

.lien {
  color: var(--encre);
  text-decoration: underline;
  text-decoration-color: var(--trait-fort);
  transition: text-decoration-color var(--duree-courte) var(--sortie);
}

.lien:hover {
  text-decoration-color: var(--encre);
}

/* --- Boutons ------------------------------------------------------------
   Angles vifs, sans exception : contrainte posee par le client.            */

.bouton {
  display: inline-flex;
  align-items: center;
  gap: 0.6em;
  padding: 1em 1.75em;
  border: 1px solid var(--encre);
  border-radius: 0;
  background: var(--encre);
  color: var(--papier);
  font-family: var(--f-texte);
  font-size: var(--t-petit);
  font-weight: 500;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  text-decoration: none;
  white-space: nowrap;
  cursor: pointer;
  transition:
    background-color var(--duree-courte) var(--sortie),
    color var(--duree-courte) var(--sortie),
    transform var(--duree-courte) var(--sortie);
}

.bouton:hover {
  background: transparent;
  color: var(--encre);
}

.bouton:active {
  transform: translateY(1px);
}

.bouton--creux {
  background: transparent;
  color: var(--encre);
}

.bouton--creux:hover {
  background: var(--encre);
  color: var(--papier);
}

.bouton .icone {
  transition: transform var(--duree-courte) var(--sortie);
}

.bouton:hover .icone {
  transform: translateX(3px);
}

.icone {
  display: inline-block;
  flex: none;
  fill: currentColor;
  vertical-align: middle;
}

/* Rangee de boutons. Partagee par les deux propositions. */
.actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--pas-2);
}

/* Sous 520px, deux boutons cote a cote ne tiennent plus : ils prennent alors
   toute la largeur, ce qui agrandit aussi la cible tactile. */
@media (max-width: 519px) {
  .actions {
    width: 100%;
  }

  .actions .bouton {
    flex: 1 1 100%;
    justify-content: center;
  }
}

/* --- Gabarit ------------------------------------------------------------ */

.enveloppe {
  width: 100%;
  max-width: var(--largeur-max);
  margin-inline: auto;
  padding-inline: var(--gouttiere);
}

.grille {
  display: grid;
  grid-template-columns: repeat(12, minmax(0, 1fr));
  gap: var(--pas-3) var(--gouttiere);
}

@media (max-width: 767px) {
  .grille {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

/* --- Accessibilite ------------------------------------------------------ */

.hors-ecran {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

.saut-contenu {
  position: absolute;
  z-index: 100;
  top: 0;
  left: 0;
  padding: 0.85em 1.4em;
  background: var(--encre);
  color: var(--papier);
  font-size: var(--t-petit);
  text-decoration: none;
  transform: translateY(-120%);
  transition: transform var(--duree-courte) var(--sortie);
}

.saut-contenu:focus {
  transform: translateY(0);
}

/* --- Entete ------------------------------------------------------------- */

.entete {
  position: sticky;
  z-index: 40;
  top: 0;
  background: var(--papier);
  border-bottom: 1px solid transparent;
  transition: border-color var(--duree-courte) linear;
}

.entete[data-defile="oui"] {
  border-bottom-color: var(--trait);
}

.entete__interieur {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--pas-3);
  min-height: var(--entete-h);
}

/* Logotype : le sceau d'origine, inchange, et le nom pose a cote.
   Dimensions, interlettrage et ecart viennent de la charte : sceau 48px et
   texte 28px sur grand ecran, 40 et 23 sur telephone, ecart 12 puis 10.

   Le fichier du sceau porte 5,86 % de marge transparente sur chaque bord,
   mesuree sur logo-sceau.png : encre de x=15 a x=239 sur 256. Sans
   correction, le cercle flotte a trois pixels de la gouttiere pendant que le
   texte des pages s'y pose, et les deux bords gauches ne sont pas sur la meme
   ligne. Le decalage negatif rattrape exactement cette marge, a l'une et
   l'autre taille. Retoucher le fichier plutot que la feuille grossirait le
   cercle dans le meme encombrement : la charte fixe une taille de sceau, pas
   une taille de cercle. */
.logotype {
  --sceau: 48px;
  display: inline-flex;
  align-items: center;
  gap: 12px;
  margin-left: calc(var(--sceau) * -0.0586);
  text-decoration: none;
}

.logotype__sceau {
  width: var(--sceau);
  height: var(--sceau);
}

.logotype__nom {
  font-family: var(--f-logo);
  font-size: 28px;
  font-weight: 800;
  font-style: normal;
  letter-spacing: -0.025em;
  line-height: 1;
  text-transform: lowercase;
}

@media (max-width: 767px) {
  .logotype {
    gap: 10px;
  }

  .logotype {
    --sceau: 40px;
  }

  .logotype__nom {
    font-size: 23px;
  }
}

.nav {
  display: flex;
  align-items: center;
  gap: clamp(1rem, 2.2vw, 2.2rem);
}

.nav__lien {
  font-size: var(--t-petit);
  font-weight: 500;
  letter-spacing: 0.02em;
  text-decoration: none;
  padding-block: 0.4em;
  border-bottom: 1px solid transparent;
  transition: border-color var(--duree-courte) var(--sortie);
}

.nav__lien:hover {
  border-bottom-color: var(--trait-fort);
}

.nav__lien[aria-current="page"] {
  border-bottom-color: var(--encre);
}

/* Le selecteur de langue n'est pas une cinquieme entree de menu. Un filet
   vertical le detache de la navigation et la respiration passe au double du pas
   des liens, pour qu'il se lise comme un reglage et non comme une page de plus.
   La barre oblique qui separait les trois codes a ete retiree : a 2,3 pour 1 sur
   blanc elle etait sous le seuil de contraste, et l'ecart suffit a les separer. */
.langues {
  display: flex;
  align-items: center;
  gap: 0.9rem;
  padding-left: var(--pas-3);
  border-left: 1px solid var(--trait);
  font-size: var(--t-etiquette);
  font-weight: 500;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.langues__lien {
  text-decoration: none;
  color: var(--encre-2);
  padding: 0.3em 0.15em;
}

.langues__lien[aria-current="true"] {
  color: var(--encre);
  text-decoration: underline;
  text-decoration-color: var(--encre);
}

/* --- Mise en page de l'en-tete sur grand ecran --------------------------
   Trois zones : le logotype a gauche, les liens au centre de la page, le
   selecteur de langue a droite.

   Les deux colonnes de bord sont egales (1fr chacune), seule facon de centrer
   vraiment celle du milieu. En flex avec space-between, un logotype de 200 px
   et un selecteur de 140 px posaient les liens 30 px a cote du centre, ce qui
   se voit des qu'on cherche l'axe de la page.

   La nav passe en display: contents pour que ses deux enfants deviennent des
   cellules de cette grille. Le reperage « nav » et son aria-label restent
   annonces : display: contents ne retire plus l'element de l'arbre
   d'accessibilite dans les navigateurs actuels.

   Ce bloc vient apres .nav et .langues, et non avant : a specificite egale
   c'est la derniere regle qui gagne, et pose plus haut il etait annule par
   « .nav { display: flex } ». */
@media (min-width: 900px) {
  .entete__interieur {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr);
  }

  .nav {
    display: contents;
  }

  .nav__liens {
    display: flex;
    align-items: center;
    gap: clamp(1rem, 2.2vw, 2.2rem);
    justify-self: center;
  }

  /* Le filet vertical separait les langues des liens quand ils se touchaient.
     Les liens etant maintenant au centre et les langues au bord, il ne
     separerait plus rien : il flotterait seul au milieu du vide. */
  .langues {
    justify-self: end;
    padding-left: 0;
    border-left: 0;
  }
}

.bascule-menu {
  display: none;
  align-items: center;
  justify-content: center;
  width: 2.75rem;
  height: 2.75rem;
  padding: 0;
  border: 1px solid var(--trait);
  background: transparent;
  cursor: pointer;
}

@media (max-width: 899px) {
  .bascule-menu {
    display: inline-flex;
  }

  .nav {
    position: fixed;
    z-index: 39;
    inset: var(--entete-h) 0 auto 0;
    flex-direction: column;
    align-items: stretch;
    gap: 0;
    padding: var(--pas-2) var(--gouttiere) var(--pas-4);
    background: var(--papier);
    border-bottom: 1px solid var(--trait);
  }

  .nav[hidden] {
    display: none;
  }

  /* L'enveloppe des liens ne sert qu'a les centrer sur grand ecran. En
     panneau deplie elle doit redevenir une colonne, sinon les quatre liens
     se suivent sur une seule ligne, comme du texte courant. */
  .nav__liens {
    display: flex;
    flex-direction: column;
  }

  .nav__lien {
    padding-block: 0.85em;
    border-bottom: 1px solid var(--trait);
    font-size: var(--t-grand);
  }

  .nav__lien:hover,
  .nav__lien[aria-current="page"] {
    border-bottom-color: var(--encre);
  }

  /* En panneau deplie le filet vertical n'a plus de sens : les langues se
     posent sous les liens, separees par la meme respiration que le reste. */
  .nav .langues {
    margin-left: 0;
    padding-left: 0;
    padding-top: var(--pas-3);
    border-left: 0;
  }
}

/* --- Avis de traduction ------------------------------------------------- */

/* Centre, contrairement au reste du site qui se pose sur le rail de
   l'enveloppe : c'est un avis de service et non du contenu de page, et pose a
   gauche il se lisait comme une premiere ligne de texte. */
.avis-traduction {
  padding: 0.7em 0;
  border-bottom: 1px solid var(--trait);
  background: var(--papier-2);
  font-size: var(--t-petit);
  color: var(--encre-2);
  text-align: center;
}

/* --- Pied --------------------------------------------------------------- */

/* Le pied ne pose pas sa propre respiration : chaque section porte deja la
   sienne, et les cumuler creusait un vide de plus de trois cents pixels sur les
   pages courtes. La derniere bande vient ainsi buter directement sur le filet
   du pied, ce qui est l'effet recherche. */
.pied {
  border-top: 1px solid var(--trait);
  padding-block: var(--pas-5) var(--pas-4);
  margin-top: 0;
}

.pied__logotype {
  margin-bottom: var(--pas-4);
  padding-bottom: var(--pas-4);
  border-bottom: 1px solid var(--trait);
  width: 100%;
}

.pied__grille {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 15rem), 1fr));
  gap: var(--pas-4) var(--gouttiere);
  align-items: start;
}

.pied__titre {
  font-size: var(--t-etiquette);
  font-weight: 500;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--encre-2);
  margin-bottom: var(--pas-2);
}

.pied__liste li + li {
  margin-top: 0.45em;
}

.pied__liste a {
  text-decoration: none;
  border-bottom: 1px solid transparent;
  transition: border-color var(--duree-courte) var(--sortie);
}

.pied__liste a:hover {
  border-bottom-color: var(--trait-fort);
}

.pied__bas {
  display: flex;
  flex-wrap: wrap;
  gap: var(--pas-2) var(--pas-4);
  justify-content: space-between;
  margin-top: var(--pas-5);
  padding-top: var(--pas-3);
  border-top: 1px solid var(--trait);
  font-size: var(--t-petit);
  color: var(--encre-2);
}

/* --- Bandeau de consentement ---------------------------------------------
   Une carte dans le coin bas GAUCHE, posee sur la gouttiere : elle tombe sur la
   meme verticale que le logotype, les titres et le texte courant. Ni voile plein
   ecran, ni barre pleine largeur : le visiteur lit la page et repond quand il
   veut.

   Elle reprend le motif de la note en marge des avis du formulaire : filet epais
   d'encre sur le seul bord gauche, fond creme, angles vifs, aucune ombre. Pose a
   gauche, ce bord epais regarde la gouttiere et ancre la carte au bord de
   l'ecran au lieu de la laisser flotter.                                    */

.bandeau-cookies {
  position: fixed;
  left: var(--gouttiere);
  bottom: var(--gouttiere);
  z-index: 60;
  width: min(26rem, calc(100vw - 2 * var(--gouttiere)));
  margin-bottom: env(safe-area-inset-bottom, 0px);
  background: var(--papier-2);
  border: 1px solid var(--trait-fort);
  padding: var(--pas-3);
}

.bandeau-cookies__interieur {
  display: flex;
  flex-direction: column;
  gap: var(--pas-3);
}

/* Le titre et le filet sur la meme ligne : le filet prend ce que le mot laisse.
   Une etiquette en capitales grises etait la seule hierarchie de la carte, qui
   n'avait donc aucun niveau fort. */
.bandeau-cookies__tete {
  display: grid;
  grid-template-columns: auto 1fr;
  align-items: center;
  gap: var(--pas-2);
}

.bandeau-cookies__titre {
  margin: 0;
  font-family: var(--f-titre);
  font-size: var(--t-h3);
  font-weight: 500;
  line-height: 1.1;
  color: var(--encre);
}

.bandeau-cookies__filet {
  height: 1px;
  background: var(--trait-fort);
}

.bandeau-cookies p {
  margin: 0;
  max-width: 78ch;
  font-size: var(--t-petit);
  line-height: 1.55;
  color: var(--encre-2);
}

/* La note du signal, dans les reglages : du texte courant, et rien autour. En
   bloc cite elle se lisait comme une citation, ce qu'elle n'est pas. */
.bandeau-cookies__note[hidden] {
  display: none;
}

/* Les deux actions secondaires sur une seule ligne, separees par un point : en
   deux paragraphes l'un sous l'autre, elles prenaient le poids d'une reponse. */
.bandeau-cookies__pied {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0.5em;
  font-size: var(--t-petit);
}

.bandeau-cookies__separateur {
  color: var(--trait-fort);
}

.bandeau-cookies__actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--pas-2);
}

/* Base nulle plutot que 10rem : a 10rem les deux boutons ne tenaient pas cote
   a cote sur un telephone et passaient sur deux rangees, soit soixante-dix
   pixels de plus pour une carte qui occupait deja le tiers de l'ecran.
   Egalite stricte entre accepter et refuser : meme classe, meme largeur,
   meme hauteur. C'est une exigence, pas une preference. */
.bandeau-cookies__actions .bouton {
  flex: 1 1 0;
  min-width: 0;
  justify-content: center;
}

/* « Personnaliser » ouvre le detail par finalite. Un bouton deguise en lien :
   il agit sur la page et ne mene nulle part, mais il ne doit pas concurrencer
   les deux reponses du dessus. */
.lien--bouton {
  padding: 0;
  border: 0;
  background: none;
  font: inherit;
  cursor: pointer;
}

.bandeau-cookies__panneau {
  border-top: 1px solid var(--trait);
  padding-top: var(--pas-3);
  display: flex;
  flex-direction: column;
  gap: var(--pas-3);
}

/* Un display pose sur un element masque par l'attribut hidden le rend de
   nouveau visible : la regle de l'agent utilisateur est moins forte que la
   notre. Le panneau se referme donc explicitement. */
.bandeau-cookies__panneau[hidden] {
  display: none;
}

.bandeau-cookies__liste {
  display: flex;
  flex-direction: column;
  gap: var(--pas-2);
  list-style: none;
  margin: 0;
  padding: 0;
}

/* Un filet entre les categories, aucun autour : la liste se lisait comme deux
   blocs flottants sans rapport l'un avec l'autre. */
.bandeau-cookies__liste li + li {
  border-top: 1px solid var(--trait);
  padding-top: var(--pas-2);
}

.bandeau-cookies__case {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: 0.7em;
  align-items: start;
  cursor: pointer;
}

/* Une case figee reste cochee et se voit : elle informe, elle ne demande
   rien. Le curseur dit qu'il n'y a rien a y faire. */
.bandeau-cookies__case:has(input[disabled]) {
  cursor: default;
}

.bandeau-cookies__case input {
  width: 1.1em;
  height: 1.1em;
  margin: 0.2em 0 0;
  accent-color: var(--encre);
}

.bandeau-cookies__categorie {
  display: block;
  font-size: var(--t-petit);
  font-weight: 500;
  color: var(--encre);
}

.bandeau-cookies__detail {
  display: block;
  margin-top: 0.15em;
  font-size: var(--t-petit);
  line-height: 1.5;
  color: var(--encre-2);
}

.bandeau-cookies__panneau .bouton {
  align-self: flex-start;
}

@media (max-width: 599px) {
  .bandeau-cookies {
    padding: var(--pas-2);
  }

  .bandeau-cookies__interieur {
    gap: var(--pas-2);
  }
}

/* Entree et sortie du bandeau.

   Le meme geste que la confirmation du formulaire : une montee d'un rem et
   une opacite, sur la courbe de sortie du systeme. Le bandeau vient du bas
   de l'ecran, il monte donc pour entrer et redescend pour partir, moitie
   moins loin et deux fois plus vite : on regarde une arrivee, on ne regarde
   pas un depart.

   L'entree attend que la page se soit posee. Sans ce delai, le bandeau
   monte pendant que les images arrivent et l'ensemble parait desordonne.

   L'etat est porte par un attribut et non par la seule presence du bandeau :
   le lien du pied peut le rouvrir, et une animation deja jouee ne rejoue
   pas. Le script retire l'attribut, force un calcul, et le repose.

   Les durees sont ecrites aussi dans consentement.js, qui compte la sortie
   avant de masquer pour de bon. Les deux valeurs vont ensemble. */
.bandeau-cookies[data-etat="entre"] {
  animation: cookies-entre var(--duree) var(--sortie) 300ms both;
}

@keyframes cookies-entre {
  from { opacity: 0; transform: translateY(1rem); }
  to   { opacity: 1; transform: none; }
}

.bandeau-cookies[data-etat="part"] {
  animation: cookies-part var(--duree-courte) var(--sortie) both;
  pointer-events: none;
}

@keyframes cookies-part {
  from { opacity: 1; transform: none; }
  to   { opacity: 0; transform: translateY(0.5rem); }
}

@media (prefers-reduced-motion: reduce) {
  /* Le bandeau parait et disparait sans glisser. Le script compte la meme
     duree dans les deux cas : il masque a la fin, anime ou non. */
  .bandeau-cookies[data-etat="entre"],
  .bandeau-cookies[data-etat="part"] {
    animation: none;
  }
}

/* --- Formulaire --------------------------------------------------------- */

.champ {
  display: flex;
  flex-direction: column;
  gap: var(--pas-1);
}

.champ__etiquette {
  font-size: var(--t-petit);
  font-weight: 500;
}

.champ__note {
  font-size: var(--t-petit);
  color: var(--encre-2);
}

/* Le renvoi vers la politique de confidentialite prend sa ligne : a la suite
   de la phrase, le lien se lisait comme sa fin. */
.champ__note-suite {
  display: block;
  margin-top: 0.35em;
}

.champ__requis {
  color: var(--encre-2);
  font-weight: 400;
}

.champ input,
.champ select,
.champ textarea {
  width: 100%;
  padding: 0.8em 0.9em;
  border: 1px solid var(--trait-fort);
  border-radius: 0;
  background: var(--papier);
  color: var(--encre);
  transition:
    border-color var(--duree-courte) var(--sortie),
    background-color var(--duree-courte) var(--sortie);
}

.champ input::placeholder,
.champ textarea::placeholder {
  color: var(--encre-2);
  opacity: 1;
}

.champ input:hover,
.champ select:hover,
.champ textarea:hover {
  border-color: var(--encre-2);
}

.champ input:focus,
.champ select:focus,
.champ textarea:focus {
  border-color: var(--encre);
  outline: 2px solid var(--encre);
  outline-offset: 1px;
}

.champ textarea {
  min-height: 11rem;
  resize: vertical;
}

.champ select {
  appearance: none;
  background-image: linear-gradient(transparent, transparent);
  padding-right: 2.6em;
}

.champ__select {
  position: relative;
}

.champ__select .icone {
  position: absolute;
  top: 50%;
  right: 0.9em;
  transform: translateY(-50%);
  pointer-events: none;
  color: var(--encre-2);
}

.champ[data-erreur] input,
.champ[data-erreur] select,
.champ[data-erreur] textarea {
  border-color: var(--alerte);
}

.champ__erreur {
  display: flex;
  gap: 0.4em;
  font-size: var(--t-petit);
  color: var(--alerte);
}

/* --- Avis d'envoi ---------------------------------------------------------
   Le cadre d'un pixel dans la couleur de l'etat faisait une boite vide qui se
   lisait comme un champ de formulaire, juste au-dessus des vrais champs. Un
   filet epais sur le seul bord gauche, comme une note en marge, dit la meme
   chose sans imiter une saisie.

   Le texte reste en encre et non dans la couleur de l'etat : une phrase
   entiere en vert ou en rouge se lit moins bien, et la couleur n'a pas besoin
   d'etre repetee. C'est le filet qui porte la nouvelle, le texte l'explique.  */

/* Pas de disposition en boite flexible ici : le message contient du texte
   courant, et parfois une adresse de courriel dans son propre element. En
   flexible, chaque morceau devient une colonne et la phrase se disloque. Le
   texte coule donc normalement, et la pastille est un caractere de plus. */
.message {
  /* L'ancre du formulaire mene ici : sans cette marge, l'en-tete collante
     recouvrirait l'avis a l'arrivee. */
  scroll-margin-top: calc(var(--entete-h) + var(--pas-3));
  margin-bottom: var(--pas-3);
  padding: var(--pas-3);
  border-left: 3px solid var(--encre);
  background: var(--papier-2);
  color: var(--encre);
  line-height: 1.5;
  max-width: 62ch;
}

.message--succes {
  border-left-color: var(--valide);
}

.message--echec {
  border-left-color: var(--alerte);
}

/* Une pastille reprend la couleur de l'etat en tete de ligne : elle donne le
   ton avant meme la lecture, sans colorer la phrase. */
.message__texte::before {
  content: "";
  display: inline-block;
  width: 0.5em;
  height: 0.5em;
  margin-right: 0.65em;
  vertical-align: 0.04em;
  background: currentColor;
}

.message--succes .message__texte::before {
  background: var(--valide);
}

.message--echec .message__texte::before {
  background: var(--alerte);
}

/* Le bloc porte tabindex="-1" et le formulaire renvoie sur son ancre : au
   retour, le navigateur lui donne le focus pour que la lecture reprenne la, et
   dessine son anneau autour. Un cadre noir sur un panneau qui en a deja un a
   gauche, cela fait deux cadres pour une seule nouvelle. On le retire : cet
   element n'est jamais atteint par la tabulation, personne ne perd de repere. */
.message:focus {
  outline: none;
}

.message > p {
  margin: 0;
}

/* Sous un avis d'echec : le numero et l'adresse, sur une ligne qui se replie.
   Le meme dessin que la suite du formulaire guide. Un refus que le visiteur ne
   peut pas lever lui-meme ne doit pas etre une impasse. */
.secours {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--pas-1) var(--pas-3);
  margin-top: var(--pas-2);
  padding-top: var(--pas-2);
  border-top: 1px solid var(--trait-fort);
  font-size: var(--t-petit);
}

.secours__intro {
  color: var(--encre-2);
}

.secours__lien {
  display: inline-flex;
  align-items: center;
  gap: 0.45em;
  padding-bottom: 0.15em;
  border-bottom: 1px solid var(--trait-fort);
  color: var(--encre);
  text-decoration: none;
  transition: border-color var(--duree-courte) var(--sortie);
}

.secours__lien:hover {
  border-bottom-color: var(--encre);
}

/* Piege a miel : hors du flux et hors de portee du clavier et des lecteurs. */
.piege {
  position: absolute;
  left: -9999px;
  width: 1px;
  height: 1px;
  overflow: hidden;
}

/* --- Formulaire et pages legales, communes aux deux propositions ---------
   Ces deux blocs etaient ecrits a l'identique dans les deux feuilles de theme.
   Ils relevent du socle : seule la composition distingue les propositions, pas
   la mise en forme d'un champ ni la largeur de mesure d'un texte legal.      */

.formulaire {
  display: grid;
  gap: var(--pas-3);
  /* Repere du panneau de confirmation, qui se pose par-dessus. */
  position: relative;
}

.formulaire__paire {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--pas-3) var(--gouttiere);
}

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

/* --- Le temps de l'envoi -------------------------------------------------
   Quand le script prend l'envoi en charge, la page ne se recharge plus et
   l'aller-retour devient visible. Il se raconte en trois moments : les champs
   s'effacent derriere un flou pendant l'attente, l'avis du serveur entre net
   par-dessus, puis le formulaire vierge se reforme dessous.

   Sans le script, aucun de ces attributs n'est pose et ces regles ne
   s'appliquent jamais : le formulaire se recharge comme il l'a toujours fait.
                                                                            */

/* Le conteneur de l'avis n'est qu'un point d'ancrage pour le script. Il
   s'efface de la grille pour que l'avis en reste l'element, place et espace
   comme avant, et pour que rien n'occupe de ligne tant qu'il n'y a rien a
   dire. */
.formulaire__avis {
  display: contents;
}

.formulaire > * {
  transition: opacity 0.3s ease, filter 0.3s ease;
}

/* Pendant l'attente, les champs s'eloignent : ils ne sont plus a modifier et
   cela se voit, sans qu'un voile vienne se poser par-dessus. L'avis est hors
   d'atteinte de cette regle, il doit arriver net. */
.formulaire[data-envoi] > *:not([data-avis], [data-confirmation]) {
  filter: blur(4px);
  opacity: 0.45;
  pointer-events: none;
}

/* Au retour, l'ordre fait la phrase. L'avis entre le premier ; le retard pose
   sur l'animation des champs les tient flous le temps qu'il se lise, puis ils
   reviennent vierges. */
/* Remplissage « backwards » et non « both » : l'animation tient l'etat de
   depart pendant son retard, puis rend la main. Avec « both » elle laisse un
   `filter: blur(0px)` colle au champ, invisible mais suffisant pour en faire
   un contexte d'empilement : le panneau de la liste deroulante s'y trouvait
   enferme et passait sous les champs suivants. */
.formulaire[data-retour] .message {
  animation: avis-entre 0.35s ease backwards;
}

.formulaire[data-retour] > *:not([data-avis], [data-confirmation]) {
  animation: champs-neufs 0.45s ease 0.25s backwards;
}

@keyframes avis-entre {
  from { opacity: 0; transform: translateY(-0.4rem); }
  to   { opacity: 1; transform: none; }
}

@keyframes champs-neufs {
  from { opacity: 0.45; filter: blur(4px); }
  to   { opacity: 1; filter: none; }
}

/* Le bouton est desactive le temps de la reponse : il ne doit pas continuer a
   se presenter comme cliquable. */
.bouton:disabled {
  cursor: default;
}

/* --- Confirmation posee par-dessus le formulaire -------------------------
   Un envoi abouti merite mieux qu'une ligne de plus au bas d'une page. Le
   panneau se pose par-dessus les champs devenus flous, laisse le temps de
   lire, puis s'efface et decouvre un formulaire vierge.

   Il n'existe que pour le script : sans JavaScript il reste `hidden`, et
   l'avis ordinaire dit la meme chose au meme endroit.                       */

.confirmation {
  position: absolute;
  inset: 0;
  z-index: 2;
  display: grid;
  place-items: center;
  padding: var(--pas-3);
}

/* `hidden` doit l'emporter sur la grille ci-dessus. */
.confirmation[hidden] {
  display: none;
}

.confirmation__panneau {
  display: grid;
  justify-items: center;
  gap: var(--pas-2);
  max-width: 34rem;
  padding: var(--pas-4) var(--pas-3);
  border: 1px solid var(--trait-fort);
  background: var(--papier);
  text-align: center;
  animation: confirmation-entre var(--duree) var(--sortie) both;
}

/* Le panneau recoit le focus a l'ouverture, pour que la lecture reprenne la.
   Il n'est jamais atteint par la tabulation : l'anneau n'apprendrait rien. */
.confirmation__panneau:focus {
  outline: none;
}

.confirmation__sceau {
  color: var(--valide);
}

/* Le sceau se trace, cercle puis coche : le meme geste que le formulaire
   guide, pour la meme nouvelle. */
.confirmation__cercle {
  stroke-dasharray: 208;
  stroke-dashoffset: 208;
  animation: tracer 760ms var(--sortie) 120ms forwards;
}

.confirmation__trait {
  stroke-dasharray: 60;
  stroke-dashoffset: 60;
  animation: tracer 620ms var(--sortie) 300ms forwards;
}

@keyframes tracer {
  to { stroke-dashoffset: 0; }
}

@keyframes confirmation-entre {
  from { opacity: 0; transform: translateY(0.75rem); }
  to   { opacity: 1; transform: none; }
}

.confirmation[data-part] {
  animation: confirmation-part var(--duree-courte) var(--sortie) both;
}

@keyframes confirmation-part {
  to { opacity: 0; }
}

.confirmation__titre {
  margin: 0;
  font-family: var(--f-titre);
  font-size: var(--t-grand);
}

.confirmation__texte {
  margin: 0;
  max-width: 40ch;
  color: var(--encre-2);
}

/* Ce que le visiteur fait s'il ne veut pas attendre la reponse. */
.confirmation__suite {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: var(--pas-1) var(--pas-3);
  width: 100%;
  margin: 0;
  padding-top: var(--pas-2);
  border-top: 1px solid var(--trait);
  font-size: var(--t-petit);
}

/* Le filet se retire pendant la lecture : le panneau s'en va tout seul,
   autant le dire avant qu'il parte. La duree est posee par le script, pour
   qu'une seule valeur commande le compte et le filet. */
.confirmation__minuterie {
  width: 100%;
  height: 1px;
  background: var(--trait-fort);
  transform-origin: left center;
  animation-name: minuterie;
  animation-timing-function: linear;
  animation-fill-mode: both;
}

@keyframes minuterie {
  from { transform: scaleX(1); }
  to   { transform: scaleX(0); }
}

@media (prefers-reduced-motion: reduce) {
  .formulaire > *,
  .formulaire[data-retour] .message,
  .formulaire[data-retour] > *:not([data-avis], [data-confirmation]) {
    animation: none;
    transition: none;
  }

  /* L'opacite dit deja que l'envoi est en cours : le flou, lui, part. */
  .formulaire[data-envoi] > *:not([data-avis], [data-confirmation]) {
    filter: none;
  }

  /* Le panneau parait sans se tracer ni glisser. Le sceau, lui, doit rester
     dessine : une animation coupee ne doit jamais effacer un contenu. */
  .confirmation__panneau,
  .confirmation[data-part],
  .confirmation__minuterie {
    animation: none;
  }

  .confirmation__cercle,
  .confirmation__trait {
    animation: none;
    stroke-dashoffset: 0;
  }
}

/* Les pages legales suivent la grille du site plutot qu'une colonne posee a
   gauche : le titre de section occupe les quatre premieres colonnes, le texte
   les sept suivantes. La mesure de lecture reste courte, mais la page se cale
   sur le meme canevas que le reste du site. */
.legal {
  padding-block: var(--pas-4) var(--pas-6);
}

/* La date de mise a jour est une note de service, pas une accroche : elle se
   pose en petit au-dessus de la premiere section, sur le rail du texte. */
.legal__maj {
  font-size: var(--t-petit);
  color: var(--encre-2);
  margin-bottom: var(--pas-3);
}

.legal section {
  display: grid;
  grid-template-columns: repeat(12, minmax(0, 1fr));
  gap: var(--pas-2) var(--gouttiere);
  padding-block: var(--pas-4);
  border-top: 1px solid var(--trait);
}

.legal section > h2 {
  grid-column: 1 / span 4;
}

.legal section > p {
  grid-column: 5 / span 7;
  max-width: 68ch;
}

@media (max-width: 899px) {
  .legal section > h2,
  .legal section > p {
    grid-column: 1 / -1;
  }
}

.legal h2 {
  font-family: var(--f-titre);
  font-size: var(--t-h3);
  font-weight: 500;
  letter-spacing: -0.018em;
}

.legal p {
  color: var(--encre-2);
  white-space: pre-line;
}

/* Le tableau des cookies et celui des prestataires. Aucun cadre autour, un
   filet entre les lignes : la meme regle que partout ailleurs sur le site, et
   ce sont les colonnes qui tiennent la lecture, pas une grille dessinee. */
.legal__tableau {
  grid-column: 5 / span 7;
  width: 100%;
  margin-top: var(--pas-2);
  border-collapse: collapse;
  font-size: var(--t-petit);
  color: var(--encre-2);
  text-align: left;
}

.legal__tableau caption {
  margin-bottom: var(--pas-2);
  color: var(--encre-2);
  font-size: var(--t-etiquette);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  text-align: left;
}

.legal__tableau th,
.legal__tableau td {
  padding: var(--pas-2) var(--pas-2) var(--pas-2) 0;
  border-top: 1px solid var(--trait);
  vertical-align: top;
}

.legal__tableau thead th {
  border-top: 0;
  padding-top: 0;
  color: var(--encre);
  font-weight: 500;
}

/* La premiere colonne nomme la ligne : en encre, et sans se couper au milieu
   d'un nom de cookie. */
.legal__tableau tbody th {
  color: var(--encre);
  font-weight: 500;
  white-space: nowrap;
}

@media (max-width: 899px) {
  .legal__tableau {
    grid-column: 1 / -1;
  }

  /* Sous neuf cents pixels, quatre colonnes ne tiennent plus : chaque ligne
     devient un bloc, et l'en-tete de colonne passe devant sa valeur. */
  .legal__tableau thead {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip-path: inset(50%);
  }

  .legal__tableau tbody tr {
    display: block;
    border-top: 1px solid var(--trait);
    padding-block: var(--pas-2);
  }

  .legal__tableau tbody th,
  .legal__tableau tbody td {
    display: block;
    border-top: 0;
    padding: 0 0 var(--pas-1);
    white-space: normal;
  }

  .legal__tableau tbody td::before {
    content: attr(data-entete) " ";
    color: var(--encre);
    font-weight: 500;
  }
}

/* --- Revelation au defilement -------------------------------------------
   Le contenu est visible par defaut : le script ajoute data-revele="attente"
   seulement s'il s'execute, donc une panne de JavaScript ne cache rien.     */

[data-revele="attente"] {
  opacity: 0;
  transform: translateY(14px);
}

[data-revele="vu"] {
  opacity: 1;
  transform: none;
  transition:
    opacity var(--duree) var(--sortie),
    transform var(--duree) var(--sortie);
}

@media (prefers-reduced-motion: reduce) {
  [data-revele] {
    opacity: 1 !important;
    transform: none !important;
    transition: none !important;
  }

  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
}

/* --- Utilitaires d'espacement -------------------------------------------
   Strictement decoratifs : marges et retraits uniquement. Aucune propriete
   structurelle ici, pour qu'ils ne puissent jamais deplacer un composant
   dont la position est declaree plus haut.                                */

.adresse {
  font-style: normal;
}

.decale-haut-court {
  padding-top: var(--pas-2);
}

.decale-haut-mince {
  margin-top: var(--pas-1);
}

.decale-bas {
  margin-bottom: var(--pas-3);
}

/* --- Impression --------------------------------------------------------- */

@media print {
  .entete,
  .pied,
  .bouton {
    display: none;
  }

  body {
    background: #fff;
    color: #000;
  }
}

/* --- Pistes qui defilent en continu -------------------------------------
   Un seul mecanisme pour deux usages : le bandeau de marques et l'accrochage
   des realisations. Deux pistes identiques se suivent, chacune large de cent
   pour cent, et translatent d'exactement une largeur : quand la premiere sort
   du cadre, la seconde occupe sa place et la boucle est invisible. Tout se
   fait en CSS, donc rien a synchroniser et rien qui casse sans JavaScript.  */

.defile {
  display: flex;
  width: 100%;
  overflow: hidden;
  /* Les deux extremites s'effacent plutot que de couper net : une piste qui
     boucle ne peut pas s'aligner sur la gouttiere, le degrade rend donc la
     coupe voulue au lieu de la faire passer pour un defaut de calage. */
  mask-image: linear-gradient(
    to right,
    transparent 0,
    #000 var(--defile-fondu, clamp(1.5rem, 7vw, 9rem)),
    #000 calc(100% - var(--defile-fondu, clamp(1.5rem, 7vw, 9rem))),
    transparent 100%
  );
  -webkit-mask-image: linear-gradient(
    to right,
    transparent 0,
    #000 var(--defile-fondu, clamp(1.5rem, 7vw, 9rem)),
    #000 calc(100% - var(--defile-fondu, clamp(1.5rem, 7vw, 9rem))),
    transparent 100%
  );
}

.defile__piste {
  display: flex;
  flex: 0 0 auto;
  align-items: center;
  gap: var(--defile-ecart, 3rem);
  min-width: 100%;
  padding-right: var(--defile-ecart, 3rem);
  animation: defiler var(--defile-duree, 48s) linear infinite;
  will-change: transform;
}

/* Le survol et l'atteinte au clavier suspendent le defilement, pour qu'on
   puisse lire ou cliquer ce qui passe. */
.defile:hover .defile__piste,
.defile:focus-within .defile__piste {
  animation-play-state: paused;
}

.defile__item {
  flex: none;
}

@keyframes defiler {
  from {
    transform: translateX(0);
  }
  to {
    transform: translateX(-100%);
  }
}

/* Mouvement reduit : la piste s'arrete et se replie en grille, pour que tout
   reste lisible sans defilement. */
@media (prefers-reduced-motion: reduce) {
  .defile {
    mask-image: none;
    -webkit-mask-image: none;
    overflow-x: auto;
  }

  .defile__piste {
    animation: none;
    padding-inline: var(--gouttiere);
  }

  .defile__piste[aria-hidden="true"] {
    display: none;
  }
}

/* --- Bandeau de marques -------------------------------------------------- */

.defile-bloc {
  padding-block: var(--pas-5);
  border-block: 1px solid var(--trait);
  background: var(--papier-2);
  overflow: hidden;
}

.defile-bloc .etiquette {
  margin-bottom: var(--pas-4);
}

.defile--marques {
  --defile-ecart: clamp(2rem, 4vw, 4rem);
  /* Fondu lateral plus large que la valeur commune : sur une rangee de logos,
     une marque qui se coupe net au bord se lit comme un defaut d'affichage.
     Environ une vignette de fondu, pour qu'elle s'efface avant d'y arriver. */
  --defile-fondu: clamp(3rem, 13vw, 16rem);
}

/* La boite epouse le logo ; seule sa hauteur est commune, c'est la ligne sur
   laquelle la rangee se pose.

   Elle avait d'abord une largeur fixe, et l'ecart entre deux marques s'en
   trouvait fausse : un logotype large remplissait sa boite et touchait
   presque son voisin, tandis qu'un ecusson centre dans la meme boite
   paraissait isole par deux marges vides. L'ecart est maintenant partout
   celui de la piste, et c'est le calcul de surface du gabarit qui regle les
   tailles. */
.defile--marques .defile__item {
  display: flex;
  align-items: center;
  justify-content: center;
  height: clamp(3.5rem, 4.4vw, 4.5rem);
}

/* Le mot « stoco » se pose sous le centre de la marque, son colibri montant
   au-dessus : l'image remonte d'une part de sa propre hauteur pour que le mot
   s'aligne sur la ligne des autres. En pourcentage, donc valable a toutes les
   tailles.

   Valeur relevee et non estimee : le mot occupe la bande basse de l'image, de
   54 a 97 pour cent de sa hauteur, et son centre tombait 4,4 px sous celui du
   mot voisin. Vingt-six pour cent referment l'ecart. */
.defile--marques .marque--stoco {
  translate: 0 -26%;
}

/* La largeur et la hauteur calculees par le gabarit font loi : ce sont elles
   qui donnent a chaque marque la meme surface optique. Un width: auto les
   ecrasait et ramenait chaque image a la taille de son fichier, bornee par la
   boite : le calcul ne servait plus a rien. */
.defile--marques img {
  opacity: 0.8;
  transition: opacity var(--duree-courte) var(--sortie);
}

.defile--marques img:hover {
  opacity: 1;
}

@media (prefers-reduced-motion: reduce) {
  .defile--marques .defile__piste {
    flex-wrap: wrap;
    justify-content: center;
    gap: var(--pas-3) var(--pas-4);
  }
}

/* --- Questions frequentes ------------------------------------------------
   Ouverture native par <details>, donc sans script et lisible meme si le
   JavaScript ne se charge pas. Le marqueur par defaut du navigateur est retire
   et remplace par un signe dessine, pour qu'il suive la palette.            */

.faq {
  display: grid;
  grid-template-columns: repeat(12, minmax(0, 1fr));
  gap: var(--pas-3) var(--gouttiere);
}

.faq__titre {
  grid-column: 1 / span 4;
}

.faq__liste {
  grid-column: 5 / span 8;
  border-top: 1px solid var(--trait);
}

.faq__item {
  border-bottom: 1px solid var(--trait);
}

.faq__question {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--pas-3);
  padding-block: var(--pas-3);
  font-family: var(--f-titre);
  font-size: var(--t-h3);
  font-weight: 500;
  letter-spacing: -0.018em;
  line-height: 1.24;
  cursor: pointer;
  list-style: none;
}

.faq__question::-webkit-details-marker {
  display: none;
}

/* Le signe est dessine en CSS plutot qu'avec une icone : deux traits d'un
   pixel qui suivent l'encre. A l'ouverture, le trait vertical disparait et il
   ne reste qu'un moins. Aucune rotation : faire pivoter un trait unique
   donnerait une diagonale, pas un moins. */
.faq__question::after {
  content: "";
  flex: none;
  width: 0.75em;
  height: 0.75em;
  align-self: center;
  background:
    linear-gradient(var(--encre), var(--encre)) center / 100% 1px no-repeat,
    linear-gradient(var(--encre), var(--encre)) center / 1px 100% no-repeat;
  transition: background-size var(--duree-courte) var(--sortie);
}

.faq__item[open] .faq__question::after {
  background: linear-gradient(var(--encre), var(--encre)) center / 100% 1px no-repeat;
}

.faq__question:hover {
  color: var(--encre);
}

.faq__reponse {
  padding-bottom: var(--pas-3);
  max-width: 68ch;
  color: var(--encre-2);
}

@media (max-width: 899px) {
  .faq__titre,
  .faq__liste {
    grid-column: 1 / -1;
  }
}

/* --- Images ouvrables en grand ------------------------------------------
   Le declencheur est un bouton, pas un lien : rien ne change d'adresse. Il
   n'ajoute aucune bordure ni fond, seulement un signe discret en haut a
   droite, pour ne pas alourdir la galerie.

   Le curseur est dessine ici plutot que laisse au systeme : la loupe de
   `zoom-in` est celle du navigateur, avec son epaisseur et son ombre a lui,
   et elle n'appartient a aucune identite. Le carre d'encre aux quatre
   equerres reprend le meme signe que celui pose sur l'image. Trente-deux
   pixels de cote : au-dela, Windows ignore un curseur personnalise. Le repli
   `zoom-in` sert si le navigateur refuse l'image.                          */

.agrandir {
  position: relative;
  display: block;
  width: 100%;
  padding: 0;
  border: 0;
  background: none;
  cursor:
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='32' height='32'%3E%3Crect width='32' height='32' fill='%23242521'/%3E%3Cg fill='none' stroke='%23eee9dd' stroke-width='2' stroke-linecap='square'%3E%3Cpath d='M9 14V9h5'/%3E%3Cpath d='M18 9h5v5'/%3E%3Cpath d='M23 18v5h-5'/%3E%3Cpath d='M14 23H9v-5'/%3E%3C/g%3E%3C/svg%3E") 16 16,
    zoom-in;
  overflow: hidden;
}

.agrandir picture,
.agrandir img {
  display: block;
  width: 100%;
}

.agrandir img {
  transition: transform 700ms var(--sortie);
}

.agrandir:hover img {
  transform: scale(1.02);
}

/* Le signe dans le coin ne sert que la ou il n'y a pas de curseur.
 *
 * Sur un appareil a pointeur, le curseur dessine plus haut dit deja que
 * l'image s'agrandit, et il le dit au meme instant : les deux se repetaient.
 * Au clavier, la regle globale de focus cerne l'image d'un filet d'encre, ce
 * qui suffit.
 *
 * Sur un ecran tactile, en revanche, il n'y a ni curseur ni survol : le signe
 * y restait donc invisible en permanence, et rien n'indiquait qu'une image
 * s'ouvre. Il y est desormais pose en clair, sans attendre un geste qui ne
 * viendra pas. */
.agrandir__signe {
  display: none;
}

@media (hover: none) {
  .agrandir__signe {
    position: absolute;
    top: var(--pas-2);
    right: var(--pas-2);
    display: flex;
    align-items: center;
    justify-content: center;
    width: 2.5rem;
    height: 2.5rem;
    background: var(--encre);
    color: var(--papier);
  }
}

@media (prefers-reduced-motion: reduce) {
  .agrandir img,
  .agrandir:hover img {
    transition: none;
    transform: none;
  }
}

/* --- Boite de dialogue de la visionneuse --------------------------------- */

/* La boite epouse l'image plutot que l'inverse : une largeur fixe laissait des
   bandes de papier de chaque cote d'une photographie moins large. */
.visionneuse {
  width: max-content;
  max-width: 94vw;
  max-height: 92vh;
  padding: 0;
  border: 0;
  /* Transparent, et non papier : la boite s'ajuste a l'image, mais quand c'est
     la hauteur qui la borne, sa largeur tombe sur une fraction de pixel de plus
     que la photographie. Un fond clair se voyait alors comme un filet sur un
     bord, surtout sur une image sombre. Le voile de l'arriere-plan passe
     dessous, et il n'y a plus rien a depasser. */
  background: transparent;
  overflow: hidden;
}

.visionneuse::backdrop {
  background: rgb(20 19 16 / 0.86);
}

.visionneuse__image {
  display: block;
  width: auto;
  max-width: 94vw;
  max-height: 92vh;
}

.visionneuse__fermer {
  position: absolute;
  top: 0;
  right: 0;
  z-index: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 3rem;
  height: 3rem;
  border: 0;
  background: var(--papier);
  color: var(--encre);
  cursor: pointer;
}

.visionneuse__fermer:hover {
  background: var(--encre);
  color: var(--papier);
}

/* --- Zoom dans la visionneuse -------------------------------------------
   Repris du geste des visionneuses de Kibo UI et d'Origin UI, deux
   bibliotheques du registre 21st.dev, et refait ici sans leur pile : molette
   pour approcher au point vise, glisser pour se deplacer, double clic pour
   revenir. Trois regles de comportement valent d'etre notees.

   L'approche se fait sur le point du curseur et non sur le centre de l'image :
   on zoome pour regarder un detail, et un zoom centre l'eloigne du regard.

   Le deplacement est borne : une image agrandie ne peut pas sortir de son
   cadre, sinon on se perd dans du vide.

   Le curseur dit ce qui est possible : la main ouverte quand il y a de la
   place a explorer, la loupe tant qu'on est au repos.                       */

.visionneuse__cadre {
  position: relative;
  overflow: hidden;
  touch-action: none;
}

.visionneuse__image {
  /* Le centre, et non le coin : le calcul des bornes de deplacement du
     script part de la meme hypothese. */
  transform-origin: center center;
  will-change: transform;
}

.visionneuse__cadre[data-zoom="oui"] {
  cursor: grab;
}

.visionneuse__cadre[data-zoom="oui"][data-glisse="oui"] {
  cursor: grabbing;
}

.visionneuse__cadre[data-zoom="oui"] .visionneuse__image {
  transition: none;
}

.visionneuse__cadre[data-zoom="non"] .visionneuse__image {
  transition: transform var(--duree) var(--sortie),
              filter 300ms var(--sortie),
              scale 300ms var(--sortie);
}

/* A l'ouverture, la vignette deja chargee tient la place pendant que la grande
   arrive. Nette, elle montrait un saut de definition qu'on remarquait ; floutee,
   elle se lit comme une mise au point, et c'est le meme geste que l'ouverture.
   L'echelle couvre le bord delave que le flou laisse autour de l'image. */
.visionneuse__image[data-apercu] {
  filter: blur(14px);
  scale: 1.04;
}

/* La boite recoit le focus a l'ouverture pour qu'aucune commande ne porte le
   contour de depart. Elle n'est pas une commande : elle ne montre rien. */
.visionneuse:focus,
.visionneuse:focus-visible {
  outline: none;
}

/* Le rappel du geste s'efface des qu'on s'en sert, il n'a rien a dire ensuite. */
.visionneuse__aide {
  position: absolute;
  left: 50%;
  bottom: var(--pas-2);
  translate: -50% 0;
  padding: 0.35em 0.9em;
  background: rgb(20 19 16 / 0.72);
  color: var(--papier);
  font-size: var(--t-petit);
  pointer-events: none;
  opacity: 1;
  transition: opacity var(--duree) var(--sortie);
}

.visionneuse__cadre[data-zoom="oui"] .visionneuse__aide {
  opacity: 0;
}

/* Un ecran tactile n'a ni molette ni double-clic, et le cadre ne prend pas le
   pincement : le rappel du zoom y parlait d'un geste qui n'existe pas. Chaque
   rappel ne parait donc que la ou son geste existe. */
@media (hover: none) and (pointer: coarse) {
  .visionneuse__aide--pointeur {
    display: none;
  }
}

@media (hover: hover) and (pointer: fine) {
  .visionneuse__aide--doigt {
    display: none;
  }
}

@media (prefers-reduced-motion: reduce) {
  .visionneuse__cadre .visionneuse__image,
  .visionneuse__aide {
    transition: none;
  }

  /* Sans transition, le flou ne serait pas une mise au point mais deux images
     differentes a la suite : autant servir la vignette telle quelle. */
  .visionneuse__image[data-apercu] {
    filter: none;
    scale: 1;
  }
}

/* --- Serie de photographies dans la visionneuse -------------------------
   Une realisation porte souvent plusieurs cliches. Le calque de glissement
   tient la place dans la serie, l'image tient le zoom : deux translations sur
   le meme element se chasseraient l'une l'autre.                            */

.visionneuse__glisse {
  display: block;
  transition: transform var(--duree-courte) var(--sortie),
              opacity var(--duree-courte) var(--sortie);
}

/* Les deux fleches se posent sur les bords de la boite, hors du cadre : a
   l'interieur, elles recevaient le glisser destine au zoom. */
.visionneuse__pas {
  position: absolute;
  top: 50%;
  translate: 0 -50%;
  z-index: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 3rem;
  height: 3.75rem;
  border: 0;
  background: var(--papier);
  color: var(--encre);
  cursor: pointer;
  transition: background var(--duree-courte) var(--sortie),
              color var(--duree-courte) var(--sortie);
}

.visionneuse__pas:hover {
  background: var(--encre);
  color: var(--papier);
}

.visionneuse__pas--avant { left: 0; }
.visionneuse__pas--apres { right: 0; }

/* Le jeu d'icones du site n'a qu'un chevron, dirige vers le bas. Un quart de
   tour de chaque cote evite d'en ajouter deux au sprite pour ce seul usage. */
.visionneuse__pas--avant .icone { rotate: 90deg; }
.visionneuse__pas--apres .icone { rotate: -90deg; }

/* Le compteur se pose en bas a droite : en bas au centre il tombait sur le
   rappel du geste de zoom. */
.visionneuse__compteur {
  position: absolute;
  right: var(--pas-2);
  bottom: var(--pas-2);
  margin: 0;
  padding: 0.35em 0.9em;
  background: rgb(20 19 16 / 0.72);
  color: var(--papier);
  font-size: var(--t-petit);
  pointer-events: none;
}

/* Sous 600 px, la boite occupe presque toute la largeur : les fleches se
   resserrent pour ne pas manger la photographie, sans descendre sous la
   cible tactile de 44 px. */
@media (max-width: 599px) {
  .visionneuse__pas {
    width: 2.75rem;
    height: 3.25rem;
  }
}

@media (prefers-reduced-motion: reduce) {
  .visionneuse__glisse {
    transition: opacity var(--duree-courte) linear;
  }
}

/* Le nombre de photographies, dans la legende de la vignette. Il ne parait
   que sur les series de plus d'une image. */
.vignette__nombre {
  display: block;
  color: var(--encre-2);
}

/* --- Champs qui se signalent au bon moment ------------------------------
   Comportement repris des champs de formulaire du registre 21st.dev, ceux
   d'anubra266 et d'Origin UI, refait ici sans leur pile.

   La regle qui compte est celle du moment : un champ ne signale rien pendant
   la frappe, il attend que le visiteur l'ait quitte. Signaler pendant qu'on
   ecrit revient a dire « faux » a quelqu'un qui n'a pas fini sa phrase. En
   revanche, des qu'il corrige, le message part immediatement : la correction
   se recompense tout de suite, l'erreur se signale avec retard.             */

.champ__erreur[data-vif] {
  animation: erreur-apparait var(--duree-courte) var(--sortie);
}

@keyframes erreur-apparait {
  from { opacity: 0; transform: translateY(-0.25rem); }
  to   { opacity: 1; transform: none; }
}

/* Le compte des caracteres est la des la premiere frappe : a huit cents
   caracteres la limite se touche pour de bon, et quelqu'un qui ecrit un long
   message doit le savoir avant d'y arriver, pas au moment ou le champ se
   bloque. Les chiffres sont en chasse fixe, sinon la ligne saute a chaque
   changement de largeur de chiffre. */
.champ__compte {
  align-self: flex-end;
  font-size: var(--t-petit);
  color: var(--encre-2);
  font-variant-numeric: tabular-nums;
  transition: color var(--duree-courte) var(--sortie);
}

/* Dans le dernier cinquieme, le compte passe en encre pleine : il prend du
   poids sans crier, la couleur d'alerte etant reservee au blocage reel. */
.champ__compte[data-proche] {
  color: var(--encre);
}

.champ__compte[data-limite] {
  color: var(--alerte);
}

@media (prefers-reduced-motion: reduce) {
  .champ__erreur[data-vif] {
    animation: none;
  }

  .champ__compte {
    transition: none;
  }
}

/* --- Liste deroulante ----------------------------------------------------
   La liste native affiche le menu du systeme : gris de Windows, coins
   arrondis, police qui n'est pas celle du site, et aucune prise pour
   l'habiller. Le script la remplace donc par une liste dessinee ici, sur le
   modele des composants Select du registre 21st.dev, ceux de shadcn et de
   HeroUI, refaits sans leur pile.

   La liste native reste dans le document, masquee : c'est elle qui porte la
   valeur et qui part avec le formulaire. Sans JavaScript, elle reapparait et
   la page fonctionne comme avant.                                           */

.liste {
  position: relative;
}

.liste__bouton {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--pas-2);
  width: 100%;
  padding: 0.85em 1em;
  border: 1px solid var(--trait-fort);
  background: var(--papier);
  color: var(--encre);
  font: inherit;
  text-align: left;
  cursor: pointer;
  transition: border-color var(--duree-courte) var(--sortie);
}

.liste__bouton:hover {
  border-color: var(--encre-2);
}

.liste__bouton:focus-visible {
  outline: 2px solid var(--encre);
  outline-offset: 2px;
}

.liste__bouton .icone {
  flex: 0 0 auto;
  color: var(--encre-2);
  transition: rotate var(--duree-courte) var(--sortie);
}

.liste__bouton[aria-expanded="true"] {
  border-color: var(--encre);
}

.liste__bouton[aria-expanded="true"] .icone {
  rotate: 180deg;
}

/* Le panneau se pose sous le bouton et recouvre la suite : une liste qui
   pousse le formulaire vers le bas fait sauter la page a chaque ouverture. */
.liste__choix {
  position: absolute;
  z-index: 20;
  top: calc(100% - 1px);
  left: 0;
  right: 0;
  max-height: 16rem;
  margin: 0;
  padding: 0;
  overflow-y: auto;
  list-style: none;
  border: 1px solid var(--encre);
  background: var(--papier);
}

.liste__choix[hidden] {
  display: none;
}

.liste__option {
  padding: 0.7em 1em;
  cursor: pointer;
}

.liste__option + .liste__option {
  border-top: 1px solid var(--trait);
}

/* Deux etats distincts : celui que la souris ou le clavier designe, et celui
   qui est reellement choisi. Les confondre fait perdre le fil quand on
   parcourt la liste au clavier. */
.liste__option[data-vise] {
  background: var(--papier-2);
}

.liste__option[aria-selected="true"] {
  font-weight: 500;
}

.liste__option[aria-selected="true"]::after {
  content: "";
  float: right;
  width: 0.45em;
  height: 0.45em;
  margin-top: 0.45em;
  background: var(--encre);
}

.champ[data-erreur] .liste__bouton {
  border-color: var(--alerte);
}

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