/* =====================================================================
   OVUNIX — feuille de style du site vitrine
   ---------------------------------------------------------------------
   Identité assumée en UN SEUL monde visuel : papier clair, encre presque
   noire, et le rouge de la marque comme unique couleur. Pas de thème
   sombre — un site institutionnel
   qui bascule en sombre selon le réglage du visiteur perd le contrôle de
   son identité, et rien ici ne se lit assez longtemps pour le justifier.
   Conséquence : chaque couleur est posée explicitement, jamais héritée
   du navigateur.

   Le rythme du site tient à trois choses, et à rien d'autre :
     1. un filet horizontal pleine largeur entre les sections ;
     2. une colonne d'intitulé à gauche, collante, en regard du contenu ;
     3. l'angle droit — aucun arrondi, sauf 2px sur les champs de
        saisie, où l'œil attend une zone cliquable.
   ===================================================================== */

/* ── Jetons ──────────────────────────────────────────────────────────
   La palette est tirée du logo, pas choisie à côté : les deux rouges
   sont les deux extrémités du dégradé de la marque. Le reste est neutre
   et froid — un rouge de cette intensité ne supporte aucune autre
   couleur à ses côtés, seulement du gris et du noir. */
:root {
  /* Les deux rouges de la marque. */
  --rouge:        #E10613;  /* identité : étiquettes, signes, filets    */
  --rouge-fonce:  #C00C17;  /* interface : aplats de bouton, liens      */
  --rouge-clair:  #FF5A62;  /* sur fond encre uniquement                */
  --rouge-voile:  #FBE4E5;  /* halo de focus                            */

  /* Encres et papiers. Neutres franchement froids : un gris tiède à
     côté de ce rouge tourne au rose sale. */
  --encre:        #14181D;
  --encre-doux:   #2A3038;
  --gris:         #5A6068;
  --gris-clair:   #8A9099;
  --papier:       #FAFAFB;
  --brume:        #F1F2F4;
  --trait:        #E2E4E8;
  --trait-fort:   #C4C8CF;

  /* Sur fond encre. */
  --sur-encre:        #EDEFF2;
  --sur-encre-doux:   #A8B0BA;

  /* Typographie */
  --police-titre: "IBM Plex Serif", Georgia, "Times New Roman", serif;
  --police-texte: "IBM Plex Sans", system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  --police-mono:  "IBM Plex Mono", ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;

  --t-xs:    0.75rem;
  --t-sm:    0.875rem;
  --t-base:  1.0625rem;
  --t-lg:    1.1875rem;
  --t-xl:    clamp(1.35rem, 1.1rem + 0.9vw, 1.75rem);
  --t-2xl:   clamp(1.75rem, 1.2rem + 2.1vw, 2.75rem);
  --t-3xl:   clamp(2.3rem, 1.3rem + 3.6vw, 4rem);

  /* Espacement */
  --e-1: 0.25rem;
  --e-2: 0.5rem;
  --e-3: 0.75rem;
  --e-4: 1rem;
  --e-5: 1.5rem;
  --e-6: 2rem;
  --e-7: 3rem;
  --e-8: 4rem;
  --e-9: 6rem;

  --largeur: 74rem;
  --duree: 280ms;
  --courbe: cubic-bezier(0.22, 0.61, 0.36, 1);
}

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

html {
  scroll-behavior: smooth;
  /* La barre collante ne doit pas recouvrir la cible d'une ancre. */
  scroll-padding-top: 5.5rem;
}

body {
  margin: 0;
  background: var(--papier);
  color: var(--encre-doux);
  font-family: var(--police-texte);
  font-size: var(--t-base);
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
}

h1, h2, h3 {
  margin: 0;
  font-family: var(--police-titre);
  color: var(--encre);
  font-weight: 600;
  line-height: 1.15;
  letter-spacing: -0.012em;
  text-wrap: balance;
}

p { margin: 0; }
ul, ol { margin: 0; padding: 0; list-style: none; }
img, svg { max-width: 100%; }

a {
  color: var(--rouge-fonce);
  text-decoration-thickness: 1px;
  text-underline-offset: 3px;
}
a:hover { color: var(--encre); }

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

.saut-contenu {
  position: absolute;
  left: -9999px;
  top: 0;
  z-index: 100;
  padding: var(--e-3) var(--e-4);
  background: var(--encre);
  color: var(--sur-encre);
  font-size: var(--t-sm);
}
.saut-contenu:focus { left: var(--e-4); top: var(--e-4); }

/* `min-width: auto` est la valeur par défaut d'un enfant de grille : il
   refuse de descendre sous sa largeur intrinsèque et déborde la page.
   Les colonnes sont déclarées en minmax(0, …) partout ; ceci couvre les
   enfants directs qui ne passent pas par une colonne. */
.hero__grille > *,
.section__grille > *,
.contact__grille > *,
.pied__grille > * { min-width: 0; }

.conteneur {
  width: 100%;
  max-width: var(--largeur);
  margin-inline: auto;
  padding-inline: var(--e-5);
}

/* ── Étiquettes en capitales ──────────────────────────────────────────
   Le mono n'est pas un clin d'œil : c'est la seule police du site qui
   vienne du monde qu'on décrit. Il porte tout ce qui nomme plutôt que
   ce qui raconte. */
.etiquette {
  margin: 0 0 var(--e-4);
  font-family: var(--police-mono);
  font-size: var(--t-xs);
  font-weight: 500;
  letter-spacing: 0.13em;
  text-transform: uppercase;
  color: var(--rouge);
}
.etiquette--claire { color: var(--rouge-clair); }

/* ── Boutons ───────────────────────────────────────────────────────── */
.bouton {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--e-2);
  padding: 0.8rem 1.4rem;
  border: 1px solid transparent;
  border-radius: 0;
  font-family: var(--police-texte);
  font-size: var(--t-sm);
  font-weight: 600;
  letter-spacing: 0.01em;
  text-decoration: none;
  cursor: pointer;
  transition: background-color var(--duree) var(--courbe),
              color var(--duree) var(--courbe),
              border-color var(--duree) var(--courbe);
}

.bouton--plein {
  background: var(--rouge-fonce);
  border-color: var(--rouge-fonce);
  color: #FFFFFF;
}
.bouton--plein:hover {
  background: var(--encre);
  border-color: var(--encre);
  color: #FFFFFF;
}

.bouton--fantome {
  background: transparent;
  border-color: var(--trait-fort);
  color: var(--encre);
}
.bouton--fantome:hover {
  border-color: var(--encre);
  background: var(--brume);
  color: var(--encre);
}

.lien-fleche {
  display: inline-flex;
  align-items: center;
  gap: var(--e-2);
  font-size: var(--t-sm);
  font-weight: 600;
  color: var(--rouge-fonce);
  text-decoration: none;
}
.lien-fleche::after {
  content: "→";
  transition: transform var(--duree) var(--courbe);
}
.lien-fleche:hover { color: var(--encre); }
.lien-fleche:hover::after { transform: translateX(4px); }

/* ── Marque ────────────────────────────────────────────────────────── */
.marque {
  display: inline-flex;
  align-items: center;
  gap: var(--e-3);
  color: var(--encre);
  text-decoration: none;
}
/* Le logo est une image, pas un texte redessiné : c'est la marque
   déposée, elle ne se réinterprète pas en CSS. La hauteur pilote, la
   largeur suit — les attributs width/height du HTML donnent le ratio au
   navigateur pour qu'il réserve la place avant le chargement. */
.marque__logo {
  display: block;
  height: 1.75rem;
  width: auto;
}
.marque--pied .marque__logo { height: 2rem; }

/* ── En-tête ───────────────────────────────────────────────────────── */
.entete {
  position: sticky;
  top: 0;
  z-index: 40;
  background: rgba(250, 250, 251, 0.92);
  backdrop-filter: blur(8px);
  border-bottom: 1px solid transparent;
  transition: border-color var(--duree) var(--courbe);
}
.entete.est-detachee { border-bottom-color: var(--trait); }

.entete__grille {
  display: flex;
  align-items: center;
  gap: var(--e-5);
  min-height: 4.5rem;
}

.nav { margin-left: auto; }
.nav__liste {
  display: flex;
  align-items: center;
  gap: var(--e-5);
}
.nav__liste a {
  font-size: var(--t-sm);
  font-weight: 500;
  color: var(--encre-doux);
  text-decoration: none;
  padding-block: var(--e-2);
  border-bottom: 2px solid transparent;
  transition: border-color var(--duree) var(--courbe),
              color var(--duree) var(--courbe);
}
.nav__liste a:hover { color: var(--encre); border-bottom-color: var(--rouge); }

.bascule-nav {
  display: none;
  margin-left: auto;
  width: 2.75rem;
  height: 2.75rem;
  padding: 0;
  background: transparent;
  border: 1px solid var(--trait-fort);
  cursor: pointer;
}
.bascule-nav__trait {
  display: block;
  width: 1.1rem;
  height: 1.5px;
  margin: 4px auto;
  background: var(--encre);
  transition: transform var(--duree) var(--courbe),
              opacity var(--duree) var(--courbe);
}
.bascule-nav[aria-expanded="true"] .bascule-nav__trait:first-child {
  transform: translateY(2.75px) rotate(45deg);
}
.bascule-nav[aria-expanded="true"] .bascule-nav__trait:last-child {
  transform: translateY(-2.75px) rotate(-45deg);
}

/* ── Héro ──────────────────────────────────────────────────────────── */
.hero {
  position: relative;
  /* Un contexte d'empilement propre : les deux couches décoratives sont
     en z-index négatif, elles passent donc au-dessus du fond du héros et
     sous son contenu, sans jamais remonter au-dessus de l'en-tête. */
  isolation: isolate;
  overflow: hidden;
  padding-block: clamp(var(--e-7), 7vw, var(--e-9)) var(--e-9);
  background:
    linear-gradient(180deg, var(--brume) 0%, var(--papier) 62%);
}

/* ── La carte du monde, en fond ───────────────────────────────────────
   Elle dit l'ambition sans l'écrire. Chargée en image de fond et non
   insérée dans le HTML : le document reste léger, et le fichier porte
   sa propre couleur — un SVG en background-image n'hérite pas du
   `color` de la page.

   ELLE EST RANGÉE À GAUCHE, pas centrée : elle tient derrière la thèse,
   dont elle est le fond. Le côté du schéma reste NU — une trame de points
   derrière des filets d'un pixel, ce sont deux quadrillages qui se
   disputent le même endroit, et c'est le dessin qui perd. */
.hero__monde {
  position: absolute;
  inset: 0;
  z-index: -2;
  background-image: url("../img/monde-pointille.svg");
  background-repeat: no-repeat;
  background-position: 0% 50%;
  background-size: min(1060px, 58%) auto;
  opacity: 0.62;
  pointer-events: none;
}

/* Le voile qui fond la carte dans la page. Des dégradés de la couleur du
   fond plutôt qu'un mask-image : même résultat, et aucun navigateur à qui
   il faille demander la permission.

   Il y en a deux, et le second n'est pas un raffinement :
   — le vertical empêche les points d'être tranchés net au bord de la
     section, en haut comme au raccord avec la section suivante. Il est
     écrit EN PREMIER, donc peint par-dessus l'autre : sinon le voile
     latéral effacerait la brume du haut sur une moitié seulement, et la
     couture se verrait ;
   — l'horizontal efface complètement la colonne de DROITE, celle du
     schéma, et relâche la carte à gauche, derrière la thèse. Il ne la
     relâche pas tout à fait : un lavis léger y reste, juste assez pour
     que le titre en serif ne vibre pas sur la trame. */
.hero::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  background:
    linear-gradient(180deg,
      var(--brume) 0%,
      rgba(250, 250, 251, 0) 26%,
      rgba(250, 250, 251, 0) 62%,
      var(--papier) 96%),
    /* Le bord gauche : selon la largeur, la carte s'arrête d'elle-même
       avant le bord ou s'y trouve coupée net. Ce demi-centimètre de fond
       rend le second cas indiscernable du premier. */
    linear-gradient(90deg,
      var(--papier) 0%,
      rgba(250, 250, 251, 0) 4%),
    linear-gradient(268deg,
      var(--papier) 0%,
      var(--papier) 48%,
      rgba(250, 250, 251, 0.40) 57%,
      rgba(250, 250, 251, 0.24) 72%,
      rgba(250, 250, 251, 0.22) 100%);
}

/* Sous 62rem — le point EXACT où le héros retombe en une colonne — il n'y
   a plus de gauche ni de droite : le schéma est sous le texte, et un
   voile latéral n'a plus rien à dégager. La carte remonte derrière le
   titre, s'efface avant le paragraphe, et recule beaucoup : sur un écran
   étroit on n'en voit plus qu'un fragment, la trame y pèse pour rien. */
@media (max-width: 62rem) {
  .hero__monde {
    opacity: 0.3;
    background-position: 50% 16%;
    background-size: min(1100px, 175%) auto;
  }

  /* Le voile s'opacifie vite : passé le titre, le schéma arrive, et il
     doit se lire ici sur le même papier nu qu'en deux colonnes. */
  .hero::after {
    background:
      linear-gradient(180deg,
        var(--brume) 0%,
        rgba(250, 250, 251, 0.5) 14%,
        rgba(250, 250, 251, 0.85) 36%,
        var(--papier) 58%);
  }
}

/* La thèse à gauche, le schéma à droite — l'ordre du document, sans
   croisement. La carte est du côté du texte ; le schéma est seul. */
.hero__grille {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: clamp(var(--e-6), 5vw, var(--e-8));
  align-items: center;
}

.hero__titre {
  font-size: var(--t-3xl);
  letter-spacing: -0.025em;
  margin-bottom: var(--e-5);
}

.hero__texte {
  max-width: 34rem;
  font-size: var(--t-lg);
  color: var(--gris);
  margin-bottom: var(--e-6);
}

.hero__actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--e-3);
}


/* Le schéma : hairlines, pas d'ombre, pas de perspective. Il montre une
   architecture, il ne mime pas une capture d'écran. */
.hero__schema { margin: 0; }
.hero__schema svg { display: block; width: 100%; height: auto; }

.schema__nom {
  font-family: var(--police-mono);
  font-size: 13px;
  font-weight: 500;
  fill: var(--encre);
}
.schema__note {
  font-family: var(--police-texte);
  font-size: 11.5px;
  fill: var(--gris);
}
.schema__bus {
  font-family: var(--police-mono);
  font-size: 11px;
  letter-spacing: 0.08em;
  fill: var(--sur-encre);
}
.schema__bus-note {
  font-family: var(--police-texte);
  font-size: 8.5px;
  fill: var(--sur-encre-doux);
}

/* La colonne d'intitulés du schéma reprend celle des sections : même
   police, même graisse, même rouge. Le schéma se lit alors comme le
   reste de la page et non comme une image rapportée. */
.schema__palier {
  font-family: var(--police-mono);
  font-size: 8.5px;
  font-weight: 500;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  fill: var(--rouge);
}

/* Translation et non animation de `cx` : les propriétés géométriques SVG
   ne sont pas animables en CSS partout, un `transform` l'est partout. */
.schema__jeton {
  animation: circule 5.5s var(--courbe) infinite;
}
@keyframes circule {
  0%   { transform: translateX(0);     opacity: 0; }
  10%  { opacity: 1; }
  90%  { opacity: 1; }
  100% { transform: translateX(140px); opacity: 0; }
}



/* ── Sections ──────────────────────────────────────────────────────── */
.section {
  padding-block: clamp(var(--e-7), 7vw, var(--e-9));
  border-top: 1px solid var(--trait);
  background: var(--papier);
  color: var(--encre-doux);
}
.section--brume { background: var(--brume); border-top-color: var(--trait); }
.section--encre {
  background: var(--encre);
  color: var(--sur-encre-doux);
  border-top-color: var(--encre);
}
.section--encre h2,
.section--encre h3 { color: var(--sur-encre); }

.section__grille {
  display: grid;
  grid-template-columns: minmax(0, 20rem) minmax(0, 1fr);
  gap: clamp(var(--e-6), 5vw, var(--e-8));
  align-items: start;
}

.section__intitule { position: sticky; top: 7rem; }

.section__titre { font-size: var(--t-2xl); }

.section__chapeau {
  margin-top: var(--e-4);
  font-size: var(--t-base);
  color: var(--gris);
  max-width: 32rem;
}
.section--encre .section__chapeau { color: var(--sur-encre-doux); }

.section__corps { display: grid; gap: var(--e-6); }

/* ── Blocs « métiers » ─────────────────────────────────────────────── */
.bloc {
  padding-top: var(--e-5);
  border-top: 1px solid var(--trait);
  display: grid;
  gap: var(--e-3);
  max-width: 42rem;
}
.bloc:first-child { padding-top: 0; border-top: 0; }
.bloc__titre { font-size: var(--t-xl); }
.bloc p { color: var(--gris); }

/* Les noms de progiciels tiers se détachent du texte courant : ce sont
   des repères que le lecteur cherche des yeux, pas des mots de la
   phrase. Pas de rouge — la couleur de la marque ne se prête pas à
   d'autres marques. */
.bloc p b {
  color: var(--encre);
  font-weight: 600;
}

/* ── Produits ──────────────────────────────────────────────────────── */
/* Deux colonnes à l'intérieur du bloc : le nom et sa promesse tiennent
   la gauche, la démonstration occupe la droite. C'est la mise en page
   d'une fiche technique, pas d'une carte de produit. */
.produit {
  display: grid;
  grid-template-columns: minmax(0, 15rem) minmax(0, 1fr);
  gap: var(--e-4) var(--e-6);
  padding: var(--e-6);
  background: var(--papier);
  border: 1px solid var(--trait);
}
/* La colonne de gauche tient toute la hauteur du bloc et RÉPARTIT son
   contenu : le nom en haut, l'action en bas. Ancrée en haut seulement,
   elle laissait un vide d'un tiers de bloc qui se lisait comme un défaut
   de mise en page — l'espace est le même, mais il travaille. */
.produit__entete {
  /* `1 / 3` et surtout PAS `1 / -1` : sans grid-template-rows, la ligne
     -1 désigne la fin de la grille EXPLICITE, c'est-à-dire la ligne 1.
     L'en-tête ne couvrait donc qu'une rangée, et la liste retombait
     dans la colonne de gauche. */
  grid-row: 1 / 3;
  display: grid;
  /* Trois rangées, dont la dernière élastique : le nom et sa promesse
     restent serrés en haut, et c'est le VIDE qui s'étire, pas l'espace
     entre eux. `space-between` répartissait les trois, et la promesse
     se retrouvait à flotter au milieu de la colonne. */
  grid-template-rows: auto auto 1fr;
  gap: var(--e-2);
  padding-right: var(--e-5);
  border-right: 1px solid var(--trait);
}
.produit__entete .lien-fleche {
  align-self: end;
  margin-top: var(--e-5);
}
.produit__nom { font-size: var(--t-xl); }
.produit__baseline {
  font-family: var(--police-mono);
  font-size: var(--t-sm);
  color: var(--rouge);
}
/* Colonne imposée : le placement automatique ne doit pas pouvoir
   renvoyer un de ces blocs sous l'en-tête. */
.produit__texte,
.produit__points { grid-column: 2; }

.produit__texte { color: var(--gris); max-width: 40rem; }

.produit__points {
  display: grid;
  gap: var(--e-2);
  font-size: var(--t-sm);
  color: var(--encre-doux);
}
.produit__points li {
  padding-left: var(--e-5);
  position: relative;
}
/* 2 px et non 1 : un filet d'un pixel tombe une fois sur deux à cheval
   sur la grille de l'écran et se rend à demi-opacité — d'où des tirets
   qui paraissaient tantôt rouges, tantôt gris, sans raison. */
.produit__points li::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0.6em;
  width: 0.55rem;
  height: 2px;
  background: var(--rouge);
}

/* Le repère « à compléter » est DÉSACTIVÉ : la page est en état d'être
   montrée. Les attributs data-a-completer restent dans le HTML — ils ne
   coûtent rien, ils ne s'affichent plus, et ils gardent la trace de ce
   qui n'est pas écrit :

       grep -n 'data-a-completer' index.html

   Pour les revoir à l'écran pendant une passe de rédaction, décommenter
   le bloc ci-dessous. */
/*
[data-a-completer] { position: relative; }
[data-a-completer]::after {
  content: "à compléter";
  position: absolute;
  top: 0;
  right: 0;
  transform: translateY(-50%);
  padding: 2px 6px;
  background: var(--rouge);
  color: #FFFFFF;
  font-family: var(--police-mono);
  font-size: 10px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}
*/

/* ── Étapes (une vraie séquence : la numérotation dit l'ordre) ─────── */
.etapes { counter-reset: etape; }
.etape {
  display: grid;
  grid-template-columns: 3.5rem minmax(0, 1fr);
  gap: var(--e-4);
  padding-top: var(--e-5);
  border-top: 1px solid var(--trait);
}
.etape:first-child { padding-top: 0; border-top: 0; }
.etape__rang {
  font-family: var(--police-mono);
  font-size: var(--t-lg);
  font-weight: 500;
  color: var(--rouge);
  line-height: 1.3;
}
.etape__propos { display: grid; gap: var(--e-2); max-width: 40rem; }
.etape__titre { font-size: var(--t-xl); }
.etape p { color: var(--gris); }

/* ── Socle technique ───────────────────────────────────────────────── */
.socle { margin: 0; display: grid; }
.socle__ligne {
  display: grid;
  grid-template-columns: minmax(0, 11rem) minmax(0, 1fr);
  gap: var(--e-4);
  padding-block: var(--e-4);
  border-top: 1px solid rgba(168, 176, 186, 0.24);
  align-items: baseline;
}
.socle__ligne:first-child { border-top: 0; padding-top: 0; }
.socle__ligne dt {
  font-family: var(--police-mono);
  font-size: var(--t-xs);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--rouge-clair);
}
.socle__ligne dd {
  margin: 0;
  font-size: var(--t-lg);
  color: var(--sur-encre);
}
.socle__note {
  margin-top: var(--e-5);
  padding-top: var(--e-4);
  border-top: 1px solid rgba(168, 176, 186, 0.24);
  font-size: var(--t-sm);
  color: var(--sur-encre-doux);
  max-width: 38rem;
}

/* ── Engagements ───────────────────────────────────────────────────── */
.engagements {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(16rem, 1fr));
  gap: var(--e-6);
}
.engagement {
  display: grid;
  gap: var(--e-2);
  padding-top: var(--e-4);
  border-top: 2px solid var(--encre);
}
.engagement__titre { font-size: var(--t-lg); }
.engagement p { color: var(--gris); font-size: var(--t-sm); }

/* ── Contact ───────────────────────────────────────────────────────── */
.contact__grille {
  display: grid;
  grid-template-columns: minmax(0, 0.9fr) minmax(0, 1.1fr);
  gap: clamp(var(--e-6), 5vw, var(--e-8));
  align-items: start;
}

.coordonnees {
  display: grid;
  gap: var(--e-3);
  margin-top: var(--e-6);
  padding-top: var(--e-5);
  border-top: 1px solid var(--trait-fort);
}
.coordonnees li { display: grid; gap: 2px; }
.coordonnees__cle {
  font-family: var(--police-mono);
  font-size: var(--t-xs);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--gris-clair);
}
/* La valeur est parfois un lien (tel:, mailto:) : elle ne doit pas pour
   autant passer au rouge des liens — dans un bloc de coordonnées, c'est
   l'information qui prime, et le rouge en ferait quatre points d'appel
   pour rien. */
.coordonnees__valeur {
  color: var(--encre);
  font-weight: 500;
  text-decoration: none;
}
a.coordonnees__valeur:hover { text-decoration: underline; }

.formulaire {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--e-4);
  padding: var(--e-6);
  background: var(--papier);
  border: 1px solid var(--trait);
}
/* `align-content: start` n'est pas un détail : sans lui, deux champs
   côte à côte partagent la hauteur de leur rangée, et celui qui n'affiche
   PAS de message d'erreur voit sa boîte de saisie s'étirer pour combler le
   vide laissé par le message d'à côté. Le défaut de la grille est
   `stretch` ; ici le surplus doit rester en bas, pas dans le champ. */
.champ {
  display: grid;
  gap: var(--e-2);
  align-content: start;
}
.champ--large { grid-column: 1 / -1; }

.champ label {
  font-size: var(--t-sm);
  font-weight: 600;
  color: var(--encre);
}
.champ__facultatif { font-weight: 400; color: var(--gris-clair); }

.champ input,
.champ select,
.champ textarea {
  width: 100%;
  padding: 0.7rem 0.8rem;
  border: 1px solid var(--trait-fort);
  border-radius: 2px;
  background: #FFFFFF;
  color: var(--encre);
  font-family: var(--police-texte);
  font-size: var(--t-sm);
  transition: border-color var(--duree) var(--courbe),
              box-shadow var(--duree) var(--courbe);
}
.champ textarea { resize: vertical; min-height: 8rem; }

.champ input:focus,
.champ select:focus,
.champ textarea:focus {
  outline: none;
  border-color: var(--rouge-fonce);
  box-shadow: 0 0 0 3px var(--rouge-voile);
}

.champ input[aria-invalid="true"],
.champ select[aria-invalid="true"],
.champ textarea[aria-invalid="true"] {
  border-color: #A8342A;
}
.champ__erreur {
  font-size: var(--t-xs);
  color: #A8342A;
}

/* Piège à robots : hors écran, jamais masqué par display:none — un
   robot ignore ce qui n'est pas rendu. */
.piege {
  position: absolute;
  left: -9999px;
  width: 1px;
  height: 1px;
  overflow: hidden;
}

.formulaire__pied {
  grid-column: 1 / -1;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--e-4);
  padding-top: var(--e-4);
  border-top: 1px solid var(--trait);
}
.formulaire__mention {
  flex: 1 1 16rem;
  font-size: var(--t-xs);
  color: var(--gris);
}
.formulaire__retour {
  grid-column: 1 / -1;
  padding: var(--e-3) var(--e-4);
  font-size: var(--t-sm);
  border-left: 3px solid var(--rouge-fonce);
  background: var(--brume);
  color: var(--encre);
}
.formulaire__retour.est-erreur {
  border-left-color: #A8342A;
  background: #FBEFEE;
  color: #7B2A22;
}

/* ── Pied de page ──────────────────────────────────────────────────── */
.pied {
  background: var(--encre);
  color: var(--sur-encre-doux);
  padding-top: var(--e-8);
  font-size: var(--t-sm);
}
.pied__grille {
  display: grid;
  grid-template-columns: minmax(0, 1.5fr) repeat(3, minmax(0, 1fr));
  gap: var(--e-6);
  padding-bottom: var(--e-7);
}
.pied__phrase {
  margin-top: var(--e-4);
  max-width: 24rem;
  color: var(--sur-encre-doux);
}
.pied__titre {
  font-family: var(--police-mono);
  font-size: var(--t-xs);
  font-weight: 500;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--rouge-clair);
  margin-bottom: var(--e-3);
}
.pied__colonne ul { display: grid; gap: var(--e-2); }
.pied__colonne a { color: var(--sur-encre); text-decoration: none; }
.pied__colonne a:hover { color: var(--rouge-clair); text-decoration: underline; }

.pied__bas {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  gap: var(--e-3);
  padding-block: var(--e-4);
  border-top: 1px solid rgba(168, 176, 186, 0.20);
  font-size: var(--t-xs);
  color: var(--gris-clair);
}
.pied__bas a { color: var(--sur-encre-doux); }
.pied__bas a:hover { color: var(--rouge-clair); }

/* ── Apparition au défilement ─────────────────────────────────────────
   Un seul geste, discret, et seulement sur les blocs de contenu : le
   héros et les intitulés sont là dès le premier rendu. */
.a-reveler {
  opacity: 0;
  transform: translateY(14px);
  transition: opacity 620ms var(--courbe), transform 620ms var(--courbe);
}
.a-reveler.est-visible { opacity: 1; transform: none; }

/* ── Adaptations ───────────────────────────────────────────────────── */
@media (max-width: 62rem) {
  .hero__grille,
  .section__grille,
  .contact__grille { grid-template-columns: minmax(0, 1fr); }

  .section__intitule { position: static; }

  /* La thèse d'abord, le schéma ensuite : en une colonne, remonter la
     figure repousserait le titre sous la ligne de flottaison.
     `min()` et non `32rem` seul — une figure plus large que la colonne
     déborde la page entière, et c'est tout le site qui se met à défiler
     latéralement. */
  .hero__schema { max-width: min(32rem, 100%); }
  .pied__grille { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .pied__marque { grid-column: 1 / -1; }
}

/* Six entrées de menu plus un bouton ne tiennent plus sous 1150 px : le
   bouton part le premier — il double une action déjà présente en bas de
   chaque section — et la navigation garde sa place. Sous 60rem, tout
   passe au menu déroulant. */
@media (max-width: 72rem) {
  .entete__action { display: none; }
}

@media (max-width: 60rem) {
  .bascule-nav { display: block; }

  .nav {
    position: absolute;
    left: 0;
    right: 0;
    top: 100%;
    margin: 0;
    background: var(--papier);
    border-bottom: 1px solid var(--trait);
    display: none;
  }
  .nav.est-ouverte { display: block; }
  .nav__liste {
    flex-direction: column;
    align-items: stretch;
    gap: 0;
    padding: var(--e-3) var(--e-5) var(--e-5);
  }
  .nav__liste a {
    display: block;
    padding-block: var(--e-3);
    border-bottom: 1px solid var(--trait);
  }

}

/* Le repli des CONTENUS reste à 48rem : la navigation passe au menu
   déroulant bien avant, mais une fiche produit en deux colonnes tient
   encore parfaitement sur une tablette. Deux bornes, deux raisons. */
@media (max-width: 48rem) {
  .formulaire { grid-template-columns: minmax(0, 1fr); padding: var(--e-5); }
  .produit { grid-template-columns: minmax(0, 1fr); padding: var(--e-5); }
  .produit__texte,
  .produit__points { grid-column: 1; }

  .produit__entete {
    grid-row: auto;
    align-content: start;
    padding-right: 0;
    padding-bottom: var(--e-4);
    border-right: 0;
    border-bottom: 1px solid var(--trait);
  }
  .etape { grid-template-columns: minmax(0, 1fr); gap: var(--e-2); }
  .socle__ligne { grid-template-columns: minmax(0, 1fr); gap: var(--e-1); }
  .pied__grille { grid-template-columns: minmax(0, 1fr); }
}

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  .schema__jeton { animation: none; opacity: 0; }
  .a-reveler { opacity: 1; transform: none; transition: none; }
  * { transition-duration: 1ms !important; }
}

@media print {
  .entete, .bascule-nav, .hero__actions, .formulaire { display: none; }
  body { background: #FFFFFF; }
  .section, .hero { border: 0; background: #FFFFFF; }
}

/* ── « Et ce qui n'est pas sur cette page » ───────────────────────────
   Volontairement PAS une cinquième carte : ce bloc ne présente aucun
   produit, il invite à demander. Lui donner la même forme qu'une fiche
   ferait chercher un nom qui n'y est pas. D'où le filet plein et
   l'absence de cadre — c'est une note en bas de section, pas un article
   de catalogue. */
.autres {
  display: grid;
  gap: var(--e-3);
  justify-items: start;
  padding-top: var(--e-5);
  border-top: 2px solid var(--encre);
}
.autres__texte {
  max-width: 44rem;
  font-size: var(--t-lg);
  color: var(--encre-doux);
}

/* ── Les progiciels tiers, en liste ───────────────────────────────────
   En mono comme tout ce qui NOMME sur ce site, et détachée du
   paragraphe par un filet : ce sont des mots-clés qu'un lecteur cherche
   des yeux — souvent le seul endroit de la page qu'il lira — et non la
   suite de la phrase. */
.bloc__outils {
  display: flex;
  flex-wrap: wrap;
  gap: var(--e-2) var(--e-4);
  margin-top: var(--e-2);
  padding-top: var(--e-3);
  border-top: 1px solid var(--trait);
  font-family: var(--police-mono);
  font-size: var(--t-xs);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--gris);
}
.bloc__outils li:last-child { color: var(--gris-clair); }



/* ── Pages de texte long (Protection des données, Mentions légales) ───
   Une seule colonne, largeur de lecture bornée. La grammaire du site —
   colonne d'intitulés à gauche — n'a pas de sens ici : ce sont des
   paragraphes qui se suivent, pas des blocs à mettre en regard. */
.texte-long {
  max-width: 46rem;
}

.texte-long h2 {
  margin: var(--e-8) 0 var(--e-4);
  font-size: var(--t-xl);
}
.texte-long h3 {
  margin: var(--e-6) 0 var(--e-3);
  font-size: var(--t-lg);
}
.texte-long p {
  margin-bottom: var(--e-4);
  color: var(--gris);
}
.texte-long p strong,
.texte-long li strong { color: var(--encre); }

.texte-long .section__chapeau { margin-bottom: var(--e-6); }

.mono {
  font-family: var(--police-mono);
  font-size: 0.94em;
}

.liste-marquee { margin-bottom: var(--e-4); }
.liste-marquee li {
  position: relative;
  padding-left: var(--e-5);
  margin-bottom: var(--e-3);
  color: var(--gris);
}
/* Un filet, pas une puce ronde : le site n'a pas un seul cercle. */
.liste-marquee li::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0.72em;
  width: 12px;
  height: 2px;
  background: var(--rouge);
}

/* Le tableau des cookies. `display:block` + défilement sur mobile : un
   tableau de quatre colonnes ne se replie pas, et le laisser déborder
   ferait défiler la PAGE entière au lieu du seul tableau. */
.tableau {
  width: 100%;
  border-collapse: collapse;
  margin: var(--e-5) 0 var(--e-6);
  font-size: var(--t-sm);
}
.tableau caption {
  text-align: left;
  padding-bottom: var(--e-3);
  color: var(--gris-clair);
  font-size: var(--t-xs);
}
.tableau th,
.tableau td {
  text-align: left;
  vertical-align: top;
  padding: var(--e-3) var(--e-4) var(--e-3) 0;
  border-bottom: 1px solid var(--trait);
}
.tableau thead th {
  border-bottom: 1px solid var(--trait-fort);
  color: var(--encre);
  font-size: var(--t-xs);
  letter-spacing: 0.04em;
  text-transform: uppercase;
}
.tableau td { color: var(--gris); }

.mention-datee {
  margin-top: var(--e-8);
  padding-top: var(--e-4);
  border-top: 1px solid var(--trait);
  font-size: var(--t-sm);
  color: var(--gris-clair);
}

@media (max-width: 40rem) {
  .tableau { display: block; overflow-x: auto; white-space: nowrap; }
  .tableau td:nth-child(2) { white-space: normal; min-width: 18rem; }
}
