/* ==========================================================================
   GESFIA — landing page vitrine
   Charte : encre #1B3A6B / ambre #D97706. Aucune ressource distante :
   ni CDN, ni police téléchargée, ni script tiers. La page doit s'afficher
   à l'identique sur une connexion coupée — c'est ce que vendent les produits.
   ========================================================================== */

:root {
  --encre:          #1B3A6B;
  --encre-profonde: #0F2547;
  --encre-claire:   #35619E;
  --ambre:          #D97706;
  --ambre-clair:    #F3A93C;
  --papier:         #FCFBF9;
  --papier-tint:    #F4F1EC;
  --graphite:       #2A2E35;
  --graphite-doux:  #5B626D;
  --filet:          rgba(27, 58, 107, .14);
  --filet-tenu:     rgba(27, 58, 107, .07);

  --display: Georgia, "Iowan Old Style", "Times New Roman", serif;
  --texte:   system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  --mono:    ui-monospace, "Cascadia Mono", "SF Mono", Consolas, "Liberation Mono", monospace;

  --large:   1160px;
  --gouttiere: clamp(1.25rem, 4vw, 3rem);
}

*, *::before, *::after { box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }

/* DÉCISION EXPLICITE (07/08/2026) : les schémas s'animent pour TOUS les
   visiteurs, y compris ceux dont le système demande des animations réduites.
   Motif : une part du public visé — administrations équipées de machines
   anciennes — désactive les effets d'animation de Windows pour la performance,
   et non par gêne vestibulaire ; la page leur restait entièrement figée, donc
   muette sur ce qu'elle a de plus démonstratif.
   C'est un recul d'accessibilité assumé : le mouvement peut gêner les personnes
   sensibles. Pour revenir en arrière, il suffit de rétablir ici
   `animation-duration: .001ms !important` sur `*` et de figer les schémas dans
   leur état final (`.schema .cd-doc { transform: translate(720px,0) }`, rails et
   câbles à `stroke-dashoffset: 0`).
   Le défilement, lui, continue de respecter la préférence. */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after { transition-duration: .001ms !important; }
}

body {
  margin: 0;
  background: var(--papier);
  color: var(--graphite);
  font-family: var(--texte);
  font-size: clamp(1rem, .96rem + .2vw, 1.075rem);
  line-height: 1.65;
  -webkit-font-smoothing: antialiased;
}

img { max-width: 100%; height: auto; display: block; }

a { color: var(--encre); }
a:focus-visible, button:focus-visible {
  outline: 3px solid var(--ambre);
  outline-offset: 3px;
  border-radius: 2px;
}

/* --- primitives partagées ------------------------------------------------ */

.enveloppe { width: 100%; max-width: var(--large); margin-inline: auto; padding-inline: var(--gouttiere); }

.surtitre {
  font-family: var(--mono);
  font-size: .74rem;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--graphite-doux);
  margin: 0 0 .9rem;
}
.surtitre::before {
  content: "";
  display: inline-block;
  width: 1.6rem; height: 2px;
  background: var(--ambre);
  vertical-align: .28em;
  margin-right: .6rem;
}

h1, h2, h3 { font-family: var(--display); font-weight: 700; color: var(--encre); line-height: 1.15; margin: 0; }
h1 { font-size: clamp(2.1rem, 1.4rem + 3vw, 3.5rem); letter-spacing: -.015em; }
h2 { font-size: clamp(1.7rem, 1.2rem + 2vw, 2.6rem); letter-spacing: -.01em; }
h3 { font-size: 1.14rem; letter-spacing: 0; }

/* --- en-tête -------------------------------------------------------------- */

.entete {
  position: sticky; top: 0; z-index: 20;
  background: rgba(252, 251, 249, .93);
  backdrop-filter: blur(8px);
  border-bottom: 1px solid var(--filet-tenu);
}
.entete__contenu { display: flex; align-items: center; gap: 1.5rem; min-height: 76px; }
/* `flex-shrink: 0` n'est pas cosmétique : les liens de nav sont en
   `white-space: nowrap` et ne se compriment pas, si bien que la marque était le
   SEUL élément compressible de la barre. Elle absorbait tout le manque de place
   et fondait — 43 px à 390, 13 px à 360, 0 px à 320 (et 0 px dès 390 sur les
   pages d'issue, dont le lien « Retour à l'accueil » est plus long). */
.entete__marque { display: flex; align-items: center; gap: .7rem; text-decoration: none; margin-right: auto; flex-shrink: 0; }
.entete__logo { width: 76px; }
.entete__nav { display: flex; gap: 1.6rem; align-items: center; }
.entete__nav a {
  font-size: .9rem; text-decoration: none; color: var(--graphite);
  padding: .35rem 0; border-bottom: 2px solid transparent; transition: border-color .18s, color .18s;
}
.entete__nav a:hover { color: var(--encre); border-bottom-color: var(--ambre); }
.entete__nav .est-contact { font-weight: 600; color: var(--encre); }
@media (max-width: 620px) {
  .entete__contenu { gap: .75rem; }
  .entete__logo { width: 64px; }
  .entete__nav { gap: .8rem; }
  .entete__nav a { font-size: .8rem; white-space: nowrap; }
  .entete__nav .est-facultatif { display: none; }
}
/* Sous cette largeur, les libellés de section ne tiennent plus à côté de la
   marque : on ne garde que l'appel à l'action. La page est d'un seul tenant —
   les sections restent atteignables au défilement et par les deux boutons de la
   couverture. Seuil calé sur la barre la plus large, celle des pages d'issue
   (« Retour à l'accueil »), qui réclame 471 px. */
@media (max-width: 560px) {
  .entete__nav a:not(.est-contact) { display: none; }
}
/* Téléphone couché : le bandeau est collant et sa hauteur ne dépendait que de
   `min-height`, pas de l'écran. Il occupait donc 77 px sur 360, soit 21 % de la
   fenêtre, en permanence et sur toute la longueur de la page — au point
   qu'aucun des deux boutons de la couverture n'était visible sans défiler.
   Le critère porte sur la HAUTEUR : c'est bien elle qui manque ici, la largeur
   en paysage étant confortable. */
@media (max-height: 480px) {
  .entete__contenu { min-height: 52px; }
  .entete__logo    { width: 48px; }
}

/* --- couverture ----------------------------------------------------------- */

.couverture { position: relative; overflow: hidden; border-bottom: 1px solid var(--filet-tenu); }
/* filigrane : trame fine de papier sécurisé, à peine perceptible */
.couverture::before {
  content: "";
  position: absolute; inset: 0;
  background-image:
    repeating-linear-gradient(58deg,  var(--filet-tenu) 0 1px, transparent 1px 9px),
    repeating-linear-gradient(-58deg, var(--filet-tenu) 0 1px, transparent 1px 9px);
  opacity: .5;
  mask-image: radial-gradient(120% 90% at 78% 40%, #000 10%, transparent 72%);
  pointer-events: none;
}
.couverture__contenu {
  position: relative;
  display: grid; grid-template-columns: minmax(0, 1.15fr) minmax(0, .85fr);
  gap: clamp(2rem, 5vw, 4.5rem); align-items: center;
  padding-block: clamp(3.25rem, 7vw, 6rem);
}
.couverture h1 { max-width: 15ch; }
.couverture__chapo {
  font-size: clamp(1.06rem, 1rem + .35vw, 1.28rem);
  color: var(--graphite-doux);
  max-width: 46ch;
  margin: 1.25rem 0 0;
}
.reperes { display: flex; flex-wrap: wrap; gap: .5rem .55rem; list-style: none; padding: 0; margin: 2rem 0 0; }
.reperes li {
  font-size: .84rem;
  color: var(--encre);
  border: 1px solid var(--filet);
  border-radius: 2px;
  padding: .42rem .7rem;
  background: rgba(255, 255, 255, .6);
}
.couverture__appel { margin-top: 2.25rem; display: flex; flex-wrap: wrap; align-items: center; gap: 1rem 1.4rem; }

.bouton {
  display: inline-block;
  font-family: var(--texte); font-size: .96rem; font-weight: 600;
  text-decoration: none;
  padding: .8rem 1.5rem;
  border-radius: 3px;
  background: var(--encre); color: #fff;
  border: 1px solid var(--encre);
  transition: background .18s, transform .18s;
}
.bouton:hover { background: var(--encre-profonde); transform: translateY(-1px); }
.bouton--fantome { background: transparent; color: var(--encre); }
.bouton--fantome:hover { background: rgba(27, 58, 107, .06); }

/* --- le cachet : signature de la page ------------------------------------- */

.cachet { justify-self: center; width: min(330px, 78vw); }
.cachet svg { width: 100%; height: auto; overflow: visible; }
.cachet__empreinte {
  transform-origin: 50% 50%;
  animation: apposer .8s cubic-bezier(.2, .9, .25, 1) both;
}
@keyframes apposer {
  0%   { opacity: 0; transform: rotate(-14deg) scale(1.22); }
  60%  { opacity: 1; }
  100% { opacity: 1; transform: rotate(-6.5deg) scale(1); }
}
.cachet__legende {
  font-size: .88rem; color: var(--graphite-doux);
  text-align: center; margin-top: 1.15rem;
}

@media (max-width: 900px) {
  .couverture__contenu { grid-template-columns: 1fr; gap: 2.5rem; }
  .couverture h1 { max-width: none; }
  .cachet { width: min(250px, 62vw); }
}

/* --- sections produit ----------------------------------------------------- */

.produit { padding-block: clamp(3.5rem, 7vw, 6rem); scroll-margin-top: 76px; }
.produit--atelier { background: var(--papier-tint); border-block: 1px solid var(--filet-tenu); }

.produit__tete { max-width: 54ch; }

/* Le logo de chaque produit, réduit à son symbole et posé à hauteur du titre.
   Les logos complets n'ont pas été employés : l'un est horizontal, l'autre
   vertical — ils n'auraient pas eu le même poids d'une section à l'autre — et
   leurs baselines répètent, en moins juste, la phrase déjà écrite dessous. */
.produit__titre { display: flex; align-items: center; gap: .85rem; }
.produit__icone {
  width: clamp(44px, 4vw, 58px);
  height: auto;
  flex: none;
  display: block;
}
/* Compensation optique : le symbole de CollabDoc est un dessin au trait, les
   deux autres sont des aplats pleins. À largeur égale, il paraissait fade et
   deux fois plus petit. On l'agrandit donc légèrement — c'est le poids perçu
   qu'on égalise, pas la mesure. */
#collabdoc .produit__icone { width: clamp(50px, 4.6vw, 66px); }
@media (max-width: 480px) { .produit__titre { gap: .6rem; } }
.produit__phrase { font-size: clamp(1.05rem, 1rem + .3vw, 1.22rem); color: var(--graphite-doux); margin: .9rem 0 0; }

/* Trois colonnes FIXES, et trois arguments par produit : en `auto-fit`, une
   quatrième fiche retombait seule sur sa rangée en laissant les deux tiers de
   la largeur vides — c'est ce déséquilibre qui faisait « brouillon », bien plus
   que le nombre d'informations. Une rangée pleine, ou rien. */
.fiches {
  display: grid;
  gap: clamp(1.5rem, 3vw, 2.75rem);
  grid-template-columns: repeat(3, minmax(0, 1fr));
  margin-top: clamp(2.5rem, 5vw, 3.5rem);
}
@media (max-width: 780px) { .fiches { grid-template-columns: 1fr; } }

/* Aucun cadre : un filet court en tête suffit à poser la colonne. Le cadre
   complet doublé d'une barre de couleur encadrait tout, donc ne hiérarchisait
   plus rien. */
.fiche { padding-top: 1.1rem; border-top: 2px solid var(--encre); }
.produit--atelier .fiche { border-top-color: var(--ambre); }
.fiche h3 {
  font-family: var(--texte); font-size: 1.04rem; font-weight: 700;
  line-height: 1.35; margin-bottom: .55rem;
}
.fiche p { margin: 0; font-size: .96rem; color: var(--graphite-doux); }

.complement {
  margin-top: 1.75rem; padding-top: 1.4rem;
  border-top: 1px solid var(--filet-tenu);
  font-size: .92rem; color: var(--graphite-doux);
}
.complement strong { color: var(--encre); font-weight: 600; }

/* --- figures (captures) ---------------------------------------------------- */

/* Une seule capture par produit, donc plus de grille : c'est la juxtaposition
   d'une image paysage et d'une image portrait qui creusait un trou blanc sous
   la plus courte. Une figure, pleine largeur, alignée sur le reste. */
.planche { margin: clamp(2.5rem, 5vw, 3.5rem) 0 0; }
.planche img { border: 1px solid var(--filet); border-radius: 3px; background: #fff; }
.planche figcaption {
  font-size: .9rem; color: var(--graphite-doux);
  margin-top: .85rem; line-height: 1.55; max-width: 68ch;
}
/* min() est indispensable : un max-width fixe l'emporterait sur max-width:100%
   et imposerait son minimum au conteneur — donc un débordement horizontal sur
   petit écran. */
.planche--portrait img { margin-inline: auto; max-width: min(430px, 100%); }
.planche--portrait figcaption { margin-inline: auto; text-align: center; max-width: 52ch; }

/* --- schémas animés --------------------------------------------------------
   Une capture montre un écran ; elle ne montre pas un processus. Ces deux
   schémas racontent ce qui se passe entre les écrans — le trajet d'un document,
   la salle qui suit dans quatre langues.

   Tout est en CSS : la page conserve `script-src 'none'`, ce qui est autant un
   choix technique qu'un argument — un acheteur qui inspecte les en-têtes ne
   doit pas trouver de script sur la vitrine de deux produits vendus sur leur
   autonomie.

   Synchronisation : dans un schéma, TOUS les éléments animés partagent la même
   durée (`--cycle`) et démarrent au même instant. L'échelonnement se fait
   uniquement par `animation-delay`. Deux durées différentes dériveraient l'une
   par rapport à l'autre au fil des boucles, et le récit se disloquerait au bout
   de quelques minutes — invisible à la relecture, flagrant chez le visiteur.
   -------------------------------------------------------------------------- */

.schema {
  margin: 2.75rem 0 0;
  border: 1px solid var(--filet);
  border-radius: 3px;
  background: #fff;
  overflow: hidden;
}
.schema__tete {
  font-size: .95rem; font-weight: 600; color: var(--encre); padding: .85rem 1.1rem;
  border-bottom: 1px solid var(--filet-tenu);
  background: var(--papier);
}
.schema__cadre { overflow-x: auto; overscroll-behavior-x: contain; }
.schema__dessin { display: block; width: 100%; height: auto; padding: 1.1rem 1rem .4rem; }
.schema__note {
  margin: 0; padding: .5rem 1.1rem .9rem;
  font-size: .84rem; color: var(--graphite-doux);
}
.schema__glisser { display: none; }

/* Le dessin fait 1160 unités de large — la largeur maximale de la page — alors
   que la colonne de contenu n'en offre que 1064 une fois les gouttières
   retirées. Il n'atteignait donc sa taille de plan à AUCUNE largeur, et ses
   textes rétrécissaient avec lui : 11,9 px sur un grand écran, 6,5 px sur un
   téléphone.
   Il reçoit maintenant une largeur plancher égale à celle qu'il occupe sur un
   grand écran : le schéma se rend PARTOUT à l'identique, et c'est la fenêtre
   qui glisse dessus quand elle est plus étroite — dans son propre cadre, jamais
   la page. Le rattrapage qui agrandissait les textes au cas par cas devient
   inutile et a été supprimé (il était de toute façon sans effet, écrasé par les
   tailles de base à spécificité égale).
   ⚠ Deux nombres liés, à recalculer ensemble si `--large` ou `--gouttiere`
   bouge, sinon le schéma se met à défiler sur grand écran ou l'invite à faire
   glisser s'affiche sous un schéma qui tient déjà :
     · 1064 = `--large` (1160) moins deux gouttières de 48 : la largeur que le
       dessin occupe sur un grand écran ;
     · 1156 = la largeur de fenêtre en dessous de laquelle la colonne devient
       plus étroite que 1064. La gouttière vaut `4vw` tant qu'elle n'a pas
       atteint son plafond de 48, donc la colonne vaut 0,92 × fenêtre, et
       0,92 × 1156 ≈ 1064. */
@media (max-width: 1156px) {
  .schema__dessin  { min-width: 1064px; }
  .schema__glisser {
    display: block; margin: 0; padding: .1rem 1.1rem 0;
    font-size: .8rem; color: var(--graphite-doux);
  }
}

/* --- vocabulaire graphique commun aux deux schémas --- */

.sc-rail            { stroke: var(--filet); stroke-width: 2; stroke-dasharray: 5 6; fill: none; }
.sc-rail--plein     { stroke: var(--ambre); stroke-width: 2.5; stroke-dasharray: 960; stroke-dashoffset: 960; }
.sc-rond            { fill: #fff; stroke: var(--encre); stroke-width: 2; }
.sc-picto           { fill: none; stroke: var(--encre); stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
.sc-picto--plein    { fill: var(--encre); stroke: none; }
.sc-etiq {
  font-family: var(--mono); font-size: 13px; font-weight: 700; letter-spacing: .08em;
  fill: var(--encre); text-anchor: middle;
}
.sc-sous {
  font-family: var(--mono); font-size: 11.5px; letter-spacing: .04em;
  fill: var(--graphite-doux); text-anchor: middle;
}
.sc-feuille  { fill: #fff; stroke: var(--encre); stroke-width: 2; }
.sc-ligne    { fill: rgba(90, 98, 109, .42); }
.sc-cachet   { fill: var(--ambre); }
.sc-cachet-coche { fill: none; stroke: #fff; stroke-width: 2.4; stroke-linecap: round; stroke-linejoin: round; }
.sc-module   { fill: var(--encre); }
.sc-maillon  { fill: var(--papier-tint); stroke: var(--encre); stroke-width: 1.5; }
.sc-maillon-txt {
  font-family: var(--mono); font-size: 11px; letter-spacing: .06em;
  fill: var(--encre); text-anchor: middle;
}
.sc-liaison  { stroke: var(--encre); stroke-width: 1.5; fill: none; }

/* encarts d'affluent (l'atelier IA en amont, le diaporama en aval) */
.sc-encart   { fill: var(--papier-tint); stroke: var(--filet); stroke-width: 1.5; }
.sc-encart-titre {
  font-family: var(--mono); font-size: 13px; font-weight: 700; letter-spacing: .08em;
  fill: var(--encre); text-anchor: start;
}
.sc-encart-sous {
  font-family: var(--mono); font-size: 11.5px; letter-spacing: .04em;
  fill: var(--graphite-doux); text-anchor: start;
}
.sc-fleche   { stroke: var(--encre); stroke-width: 2; fill: none; stroke-linecap: round; }
.sc-pointe   { fill: var(--encre); }

/* Chaque pièce entre au moment que lui assigne son nom (sc-a16 = à 16 % du
   cycle), tient jusqu'à 93 %, puis s'efface avec toutes les autres.

   Ce sont bien des keyframes datés, et non un `animation-delay` : un délai
   décalerait aussi la FIN de la pièce, qui survivrait donc au redémarrage du
   récit — au deuxième tour, le document repartirait de la rédaction en portant
   déjà les trois cachets qu'il n'a pas encore obtenus. Le défaut n'apparaît
   qu'au bout d'un cycle complet, ce qui le rend facile à livrer sans le voir. */
.sc-pose {
  transform-box: fill-box;
  transform-origin: 50% 50%;
  animation-duration: var(--cycle);
  animation-iteration-count: infinite;
  animation-fill-mode: both;
  animation-timing-function: cubic-bezier(.2, .9, .25, 1);
}

@keyframes sc-pose-16 {
  0%, 15% { opacity: 0; transform: scale(1.55) rotate(-16deg); }
  22%     { opacity: 1; transform: scale(1) rotate(0deg); }
  93%     { opacity: 1; transform: scale(1) rotate(0deg); }
  100%    { opacity: 0; transform: scale(1) rotate(0deg); }
}
@keyframes sc-pose-36 {
  0%, 35% { opacity: 0; transform: scale(1.55) rotate(-16deg); }
  42%     { opacity: 1; transform: scale(1) rotate(0deg); }
  93%     { opacity: 1; transform: scale(1) rotate(0deg); }
  100%    { opacity: 0; transform: scale(1) rotate(0deg); }
}
@keyframes sc-pose-56 {
  0%, 55% { opacity: 0; transform: scale(1.55) rotate(-16deg); }
  62%     { opacity: 1; transform: scale(1) rotate(0deg); }
  93%     { opacity: 1; transform: scale(1) rotate(0deg); }
  100%    { opacity: 0; transform: scale(1) rotate(0deg); }
}
@keyframes sc-pose-64 {
  0%, 63% { opacity: 0; transform: scale(1.35) rotate(0deg); }
  70%     { opacity: 1; transform: scale(1) rotate(0deg); }
  93%     { opacity: 1; transform: scale(1) rotate(0deg); }
  100%    { opacity: 0; transform: scale(1) rotate(0deg); }
}
@keyframes sc-pose-82 {
  0%, 81% { opacity: 0; transform: scale(1.55) rotate(-16deg); }
  88%     { opacity: 1; transform: scale(1) rotate(0deg); }
  95%     { opacity: 1; transform: scale(1) rotate(0deg); }
  100%    { opacity: 0; transform: scale(1) rotate(0deg); }
}
@keyframes sc-pose-06 {
  0%, 5%  { opacity: 0; transform: scale(1.55) rotate(-16deg); }
  12%     { opacity: 1; transform: scale(1) rotate(0deg); }
  93%     { opacity: 1; transform: scale(1) rotate(0deg); }
  100%    { opacity: 0; transform: scale(1) rotate(0deg); }
}
@keyframes sc-pose-70 {
  0%, 69% { opacity: 0; transform: scale(1.45) rotate(-10deg); }
  76%     { opacity: 1; transform: scale(1) rotate(0deg); }
  93%     { opacity: 1; transform: scale(1) rotate(0deg); }
  100%    { opacity: 0; transform: scale(1) rotate(0deg); }
}
.sc-a06 { animation-name: sc-pose-06; }
.sc-a70 { animation-name: sc-pose-70; }
.sc-a16 { animation-name: sc-pose-16; }
.sc-a36 { animation-name: sc-pose-36; }
.sc-a56 { animation-name: sc-pose-56; }
.sc-a64 { animation-name: sc-pose-64; }
.sc-a82 { animation-name: sc-pose-82; }

/* fondus simples : liaisons de la chaîne, mentions */
@keyframes sc-fondu-18 { 0%, 17% { opacity: 0; } 24% { opacity: 1; } 93% { opacity: 1; } 100% { opacity: 0; } }
@keyframes sc-fondu-38 { 0%, 37% { opacity: 0; } 44% { opacity: 1; } 93% { opacity: 1; } 100% { opacity: 0; } }
@keyframes sc-fondu-58 { 0%, 57% { opacity: 0; } 64% { opacity: 1; } 93% { opacity: 1; } 100% { opacity: 0; } }
@keyframes sc-fondu-64 { 0%, 63% { opacity: 0; } 70% { opacity: 1; } 93% { opacity: 1; } 100% { opacity: 0; } }
@keyframes sc-fondu-70 { 0%, 69% { opacity: 0; } 76% { opacity: 1; } 93% { opacity: 1; } 100% { opacity: 0; } }
.sc-fondu {
  animation-duration: var(--cycle);
  animation-iteration-count: infinite;
  animation-fill-mode: both;
  animation-timing-function: ease;
}
.sc-f18 { animation-name: sc-fondu-18; }
.sc-f38 { animation-name: sc-fondu-38; }
.sc-f58 { animation-name: sc-fondu-58; }
.sc-f64 { animation-name: sc-fondu-64; }
.sc-f70 { animation-name: sc-fondu-70; }

/* --- schéma CollabDoc : le trajet d'un document --------------------------- */

.schema--collabdoc { --cycle: 15s; }

/* Le document emporte ses cachets : ils sont posés dans son groupe, donc ils
   voyagent avec lui — c'est le point du produit, un document qui revient
   portant la preuve de son parcours. */
@keyframes cd-trajet {
  0%      { opacity: 0; transform: translate(0px, 0px); }
  4%      { opacity: 1; transform: translate(0px, 0px); }
  16%     { transform: translate(240px, 0px); }
  24%     { transform: translate(240px, 0px); }
  36%     { transform: translate(480px, 0px); }
  44%     { transform: translate(480px, 0px); }
  56%     { transform: translate(720px, 0px); }
  93%     { opacity: 1; transform: translate(720px, 0px); }
  100%    { opacity: 0; transform: translate(720px, 0px); }
}
.cd-doc {
  animation: cd-trajet var(--cycle) cubic-bezier(.65, 0, .35, 1) infinite both;
}

@keyframes cd-rail {
  0%, 4%  { stroke-dashoffset: 960; }
  16%     { stroke-dashoffset: 720; }
  24%     { stroke-dashoffset: 720; }
  36%     { stroke-dashoffset: 480; }
  44%     { stroke-dashoffset: 480; }
  56%     { stroke-dashoffset: 240; }
  72%     { stroke-dashoffset: 0; }
  93%     { stroke-dashoffset: 0; opacity: 1; }
  100%    { stroke-dashoffset: 0; opacity: 0; }
}
.cd-rail-plein { animation: cd-rail var(--cycle) cubic-bezier(.65, 0, .35, 1) infinite both; }

/* le faisceau du QR vers le téléphone qui vérifie */
@keyframes cd-faisceau {
  0%, 72% { stroke-dashoffset: 240; opacity: 0; }
  74%     { opacity: 1; }
  81%     { stroke-dashoffset: 0; opacity: 1; }
  93%     { stroke-dashoffset: 0; opacity: 1; }
  100%    { stroke-dashoffset: 0; opacity: 0; }
}
.cd-faisceau {
  stroke: var(--ambre); stroke-width: 2.5; fill: none;
  stroke-dasharray: 240; stroke-dashoffset: 240; stroke-linecap: round;
  animation: cd-faisceau var(--cycle) ease infinite both;
}
.sc-verdict { fill: var(--ambre); }

/* --- schéma Atelier Live PRO : la salle ----------------------------------- */

.schema--atelier { --cycle: 12s; }

.sc-boitier     { fill: var(--encre-profonde); }
.sc-ecran       { fill: var(--papier-tint); }
.sc-chassis     { fill: none; stroke: var(--encre); stroke-width: 2.5; }
.sc-cable       { fill: none; stroke: var(--encre); stroke-width: 2.5; stroke-linecap: round; }
.sc-onde        { fill: none; stroke: var(--ambre); stroke-width: 2.5; stroke-linecap: round; }
.sc-titre-diapo { fill: var(--encre); }
.sc-filet-ambre { fill: var(--ambre); }
.sc-trait-clair { fill: rgba(255, 255, 255, .42); }
.sc-badge       { fill: var(--encre); }
.sc-pied        { fill: var(--encre); }
.sc-nuage       { fill: #DFE3EA; }
.sc-barre       { stroke: var(--graphite-doux); stroke-width: 3.5; stroke-linecap: round; }
/* Le second nuage n'est pas barré : c'est la connexion facultative, celle qui
   ajoute la diffusion en ligne. Teinte plus soutenue pour qu'on ne confonde pas
   les deux d'un coup d'œil. */
.sc-nuage-ligne { fill: #C7D4E6; }
.sc-hors--ligne { fill: var(--encre); }
.sc-langue {
  font-family: var(--mono); font-size: 12px; font-weight: 700; letter-spacing: .08em;
  fill: #fff; text-anchor: middle;
}
.sc-hors {
  font-family: var(--mono); font-size: 11.5px; font-weight: 700; letter-spacing: .1em;
  fill: var(--graphite-doux); text-anchor: middle;
}

/* Le voyant du boîtier : la seule chose qui bat en permanence, comme sur
   l'appareil réel. */
@keyframes alp-voyant {
  0%, 44%, 100% { opacity: 1; }
  22%, 66%      { opacity: .25; }
}
.alp-voyant { fill: var(--ambre); animation: alp-voyant 2.4s ease-in-out infinite; }

/* Les ondes partent du boîtier et vont mourir sur les téléphones. */
@keyframes alp-onde {
  0%   { opacity: 0; transform: scale(.35); }
  12%  { opacity: .95; }
  100% { opacity: 0; transform: scale(1.5); }
}
/* Les trois arcs sont décalés d'un tiers de cycle : la respiration du signal
   ne dépend pas du récit, elle peut donc vivre sur sa propre horloge. */
.alp-onde {
  transform-box: fill-box;
  transform-origin: 0% 50%;
  animation: alp-onde 3s ease-out infinite;
}
.alp-onde--2 { animation-delay: 1s; }
.alp-onde--3 { animation-delay: 2s; }

/* Le câble se branche, puis les écrans s'allument l'un après l'autre — le
   châssis des téléphones, lui, reste visible : ils sont dans la salle avant
   d'afficher quoi que ce soit. */
@keyframes alp-cable { 0%, 8% { stroke-dashoffset: 150; } 20% { stroke-dashoffset: 0; } 100% { stroke-dashoffset: 0; } }
.alp-cable {
  stroke-dasharray: 150; stroke-dashoffset: 150;
  animation: alp-cable var(--cycle) ease-out infinite both;
}

@keyframes alp-allume-30 { 0%, 29% { opacity: 0; } 34% { opacity: 1; } 94% { opacity: 1; } 100% { opacity: 0; } }
@keyframes alp-allume-35 { 0%, 34% { opacity: 0; } 39% { opacity: 1; } 94% { opacity: 1; } 100% { opacity: 0; } }
@keyframes alp-allume-40 { 0%, 39% { opacity: 0; } 44% { opacity: 1; } 94% { opacity: 1; } 100% { opacity: 0; } }
@keyframes alp-allume-45 { 0%, 44% { opacity: 0; } 49% { opacity: 1; } 94% { opacity: 1; } 100% { opacity: 0; } }
.alp-allume {
  animation-duration: var(--cycle);
  animation-iteration-count: infinite;
  animation-fill-mode: both;
  animation-timing-function: ease;
}
.alp-e1 { animation-name: alp-allume-30; }
.alp-e2 { animation-name: alp-allume-35; }
.alp-e3 { animation-name: alp-allume-40; }
.alp-e4 { animation-name: alp-allume-45; }

/* Le contenu bascule d'une diapo à l'autre — sur les quatre écrans au même
   instant, ce qui est tout le propos de la synchronisation. */
/* La bascule est placée à 68 %, soit après l'allumage du dernier écran (49 %) :
   sinon le changement de diapo se jouerait sur des écrans encore éteints et
   la démonstration de synchronisation tomberait à plat. */
@keyframes alp-diapo-a {
  0%, 66%   { opacity: 1; }
  70%, 100% { opacity: 0; }
}
@keyframes alp-diapo-b {
  0%, 66% { opacity: 0; }
  70%     { opacity: 1; }
  94%     { opacity: 1; }
  100%    { opacity: 0; }
}
.alp-diapo-a { animation: alp-diapo-a var(--cycle) ease infinite both; }
.alp-diapo-b { animation: alp-diapo-b var(--cycle) ease infinite both; }

/* --- schéma GESFIA Meet : le parcours d'une réunion ----------------------- */

.schema--meet { --cycle: 14s; }

.sc-vignette  { fill: var(--papier-tint); }
.sc-anse      { fill: none; stroke: var(--ambre); stroke-width: 4; }
.sc-anse-mini { fill: none; stroke: var(--ambre); stroke-width: 3; }

/* L'invitation voyage en portant déjà son mot de passe — c'est tout l'argument :
   l'invité n'a rien à saisir. */
@keyframes mt-trajet {
  0%   { opacity: 0; transform: translate(0px, 0px); }
  4%   { opacity: 1; transform: translate(0px, 0px); }
  18%  { transform: translate(280px, 0px); }
  26%  { transform: translate(280px, 0px); }
  38%  { transform: translate(560px, 0px); }
  93%  { opacity: 1; transform: translate(560px, 0px); }
  100% { opacity: 0; transform: translate(560px, 0px); }
}
.mt-carte { animation: mt-trajet var(--cycle) cubic-bezier(.65, 0, .35, 1) infinite both; }

/* Le rail de ce schéma ne fait que 560 unités, pas 960 : le tiret doit couvrir
   sa propre longueur, sinon le remplissage démarre déjà à moitié fait. */
@keyframes mt-rail {
  0%, 4% { stroke-dashoffset: 560; }
  18%    { stroke-dashoffset: 280; }
  26%    { stroke-dashoffset: 280; }
  38%    { stroke-dashoffset: 0; }
  93%    { stroke-dashoffset: 0; opacity: 1; }
  100%   { stroke-dashoffset: 0; opacity: 0; }
}
.mt-rail-plein {
  stroke: var(--ambre); stroke-width: 2.5; fill: none;
  stroke-dasharray: 560; stroke-dashoffset: 560;
  animation: mt-rail var(--cycle) cubic-bezier(.65, 0, .35, 1) infinite both;
}

/* Pas de repli figé pour les schémas : voir la décision explicite en tête de
   cette feuille — ils s'animent pour tous les visiteurs. */

/* Aucun rattrapage de taille de texte ici : le dessin garde partout sa taille
   de plan (voir la largeur plancher plus haut), donc ses étiquettes aussi.
   ⚠ Si l'envie revient d'agrandir des textes de schéma sur petit écran, le
   bloc devra être posé APRÈS toutes les règles `.sc-*` : une media query
   n'ajoute aucune spécificité, et placé avant il est purement et simplement
   écrasé — c'est le défaut qui avait laissé les étiquettes à 6,5 px sans que
   personne ne le voie, le code semblant les corriger. */

/* --- bandeau garanties ----------------------------------------------------- */

.garanties {
  background: var(--encre-profonde); color: #E8EDF5;
  padding-block: clamp(3.25rem, 6vw, 5rem);
  scroll-margin-top: 76px;
}
.garanties h2 { color: #fff; }
.garanties .surtitre { color: rgba(232, 237, 245, .72); }
.garanties__grille {
  display: grid; gap: 1.75rem 2.25rem; margin-top: 2.5rem;
  grid-template-columns: repeat(auto-fit, minmax(230px, 1fr));
}
.garantie h3 { color: var(--ambre-clair); font-family: var(--texte); font-size: 1rem; font-weight: 700; margin-bottom: .45rem; }
.garantie p { margin: 0; font-size: .94rem; color: rgba(232, 237, 245, .82); }

/* --- contact --------------------------------------------------------------- */

.contact { padding-block: clamp(3.25rem, 6vw, 5rem); scroll-margin-top: 76px; }
.contact__bloc {
  /* cadre simple : la barre ambre en plus du filet faisait, ici aussi, deux
     encadrements superposés */
  border: 1px solid var(--filet);
  border-radius: 3px; padding: clamp(1.75rem, 4vw, 2.75rem);
  display: grid; gap: 2rem 3rem; grid-template-columns: minmax(0, 1fr) minmax(300px, 420px);
  align-items: start;
}
@media (max-width: 760px) { .contact__bloc { grid-template-columns: 1fr; } }
.contact p { margin: .9rem 0 0; color: var(--graphite-doux); max-width: 52ch; }
.contact__direct { display: flex; flex-wrap: wrap; gap: .5rem 1.1rem; align-items: baseline; }
.contact__adresse {
  font-family: var(--mono); font-size: clamp(.95rem, .9rem + .3vw, 1.1rem);
  color: var(--encre); text-decoration: none; font-weight: 600;
  border-bottom: 2px solid var(--ambre); padding-bottom: .15rem; white-space: nowrap;
}
.contact__adresse:hover { color: var(--encre-profonde); }

/* --- formulaire de contact -------------------------------------------------
   Envoi par `mailto` : rien ne transite par le site, donc aucune collecte et
   aucun cookie — la promesse de la page reste vraie. La contrepartie (si le
   visiteur n'a pas de messagerie configurée, rien ne part) est écrite sous le
   bouton, et l'adresse reste affichée en clair juste à côté.
   -------------------------------------------------------------------------- */

.formulaire { display: grid; gap: .9rem; }
.formulaire__champ { margin: 0; display: grid; gap: .35rem; }
.formulaire__champ label {
  font-size: .85rem; font-weight: 600; color: var(--encre);
}
.formulaire__note { font-weight: 400; color: var(--graphite-doux); }
.formulaire input,
.formulaire textarea {
  font: inherit; font-size: .95rem;
  color: var(--graphite);
  background: #fff;
  border: 1px solid var(--filet);
  border-radius: 3px;
  padding: .6rem .7rem;
  width: 100%;
}
.formulaire textarea { resize: vertical; min-height: 6.5rem; }
.formulaire input:focus-visible,
.formulaire textarea:focus-visible {
  outline: 3px solid var(--ambre);
  outline-offset: 1px;
  border-color: var(--encre);
}
.formulaire .bouton { justify-self: start; border: 0; cursor: pointer; }
/* 16 px pile, pas moins : sous ce seuil, Safari iOS zoome de lui-même à la mise
   au point du champ — et ne dézoome pas ensuite. Le visiteur se retrouve dans
   une page agrandie dont il doit sortir à la main. */
@media (max-width: 620px) {
  .formulaire input,
  .formulaire textarea { font-size: 16px; }
}
/* Champ piège : hors écran plutôt que `display:none`, que certains robots
   détectent pour l'éviter. `aria-hidden` sur le paragraphe le retire déjà des
   lecteurs d'écran. */
.formulaire__piege {
  position: absolute; left: -9999px; width: 1px; height: 1px;
  overflow: hidden; margin: 0;
}

/* --- pages d'issue (message envoyé / échec) -------------------------------- */

.issue { padding-block: clamp(4rem, 12vw, 8rem); min-height: 46vh; }
.issue h1 { max-width: 18ch; margin-bottom: 1.25rem; }
.issue__texte { font-size: clamp(1.02rem, 1rem + .3vw, 1.18rem); color: var(--graphite-doux); max-width: 56ch; }
.issue__direct { display: flex; flex-wrap: wrap; gap: .6rem 1.4rem; margin-top: 1.4rem; }
.issue__appel { margin-top: 2.25rem; display: flex; flex-wrap: wrap; gap: 1rem 1.4rem; }
.formulaire__mention {
  margin: 0; font-size: .82rem; line-height: 1.5;
  color: var(--graphite-doux);
}

/* --- pied ------------------------------------------------------------------ */

.pied { border-top: 1px solid var(--filet-tenu); padding-block: 2rem; }
.pied__contenu { display: flex; flex-wrap: wrap; gap: .6rem 1.5rem; align-items: center; justify-content: space-between; }
.pied p { margin: 0; font-size: .85rem; color: var(--graphite-doux); }
.pied__produits { font-size: .85rem; color: var(--graphite-doux); }
.pied__joindre { display: flex; flex-wrap: wrap; gap: .3rem .6rem; align-items: center; }
.pied__joindre a {
  font-size: .85rem; color: var(--encre);
  text-decoration: none; border-bottom: 1px solid var(--filet); padding-bottom: .1rem;
  white-space: nowrap;
}
.pied__joindre a:hover { border-bottom-color: var(--ambre); }
.pied__joindre span { color: var(--filet); }
