/* =========================================================================
   Site Protect — Audit IA : feuille de style unique.

   Ordre : polices · jetons · socle · utilitaires · en-tete · menu ·
   rideau · hero · scanner · rapport · sections · pied · impression ·
   mouvement reduit.

   Trois regles tenues partout :
   · le fond est sombre et PLAT. La seule lumiere de la page vient de la
     scene 3D et des degrades de marque, employes avec parcimonie : un
     mot par titre, les boutons, les filets d'etat. Posee partout, la
     couleur ne signale plus rien.
   · les couleurs d'etat (rouge, ambre, vert) sont reservees au rapport
     de scan. Elles ne servent jamais de decor, sinon un vrai risque
     critique ne se distingue plus d'un titre stylise.
   · les etats initiaux d'animation sont accroches a `html.js`. Sans
     JavaScript la page reste entierement lisible, et la classe est
     posee dans le <head> — aucun contenu n'apparait puis ne disparait.
   ========================================================================= */

/* --------------------------------------------------------------- POLICES */
/* Le systeme typographique d'orealys.com, repris tel quel :

   · Instrument SANS en 600 pour les titres — un grotesque serre,
     letter-spacing -.035em, interligne 1 ;
   · Instrument SERIF ITALIQUE pour LE mot accentue au milieu du titre.
     C'est le contraste de dessin qui fait l'accent, pas la couleur ;
   · Inter pour le texte courant.

   S'y ajoute, propre a ce site : IBM Plex Mono, une seule graisse,
   UNIQUEMENT la ou le texte est une donnee machine (l'URL saisie,
   l'adresse analysee, le code en ligne, les extraits bruts du site
   ausculte). Partout ailleurs la chasse fixe ne signale rien.

   Instrument Serif n'existe qu'en 400 : lui demander du 500 fabriquerait
   une graisse synthetique. Auto-hebergees, donc rien a demander a un
   tiers et aucun consentement a collecter.
*/

@font-face {
  font-family: 'Instrument Sans';
  src: url('../fonts/instrument-sans-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: 'Instrument Sans';
  src: url('../fonts/instrument-sans-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+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: 'Instrument Serif';
  src: url('../fonts/instrument-serif-latin.woff2') format('woff2');
  font-weight: 400; 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: 'Instrument Serif';
  src: url('../fonts/instrument-serif-latin-ext.woff2') format('woff2');
  font-weight: 400; font-style: normal; font-display: swap;
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7,
                 U+02DD-02FF, 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: 'Instrument Serif';
  src: url('../fonts/instrument-serif-italique-latin.woff2') format('woff2');
  font-weight: 400; font-style: italic; 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: 'Instrument Serif';
  src: url('../fonts/instrument-serif-italique-latin-ext.woff2') format('woff2');
  font-weight: 400; font-style: italic; font-display: swap;
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7,
                 U+02DD-02FF, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020,
                 U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: 'Inter';
  src: url('../fonts/inter-latin.woff2') format('woff2');
  font-weight: 100 900; 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: 'Inter';
  src: url('../fonts/inter-latin-ext.woff2') format('woff2');
  font-weight: 100 900; font-style: normal; font-display: swap;
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7,
                 U+02DD-02FF, 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: 'IBM Plex Mono';
  src: url('../fonts/plex-mono-latin.woff2') format('woff2');
  font-weight: 400; 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: 'IBM Plex Mono';
  src: url('../fonts/plex-mono-latin-ext.woff2') format('woff2');
  font-weight: 400; font-style: normal; font-display: swap;
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7,
                 U+02DD-02FF, 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;
}

/* ---------------------------------------------------------------- JETONS */

:root {
  /* Encres. Le fond n'est pas noir : un bleu tres sombre, qui laisse la
     scene 3D respirer sans creer de bande visible a la jointure. */
  --nuit:       #05070E;
  --nuit-2:     #080B15;
  --carte:      #0C1020;
  --carte-2:    #111731;
  --trait:      rgba(142, 156, 210, .14);
  --trait-fort: rgba(142, 156, 210, .30);

  --texte:   #E8ECF9;
  --texte-2: #A3ADCC;
  --texte-3: #7B87AB;

  /* La couleur de marque est CELLE DU LOGO, et il n'y en a qu'une :
     le teal de la barre oblique. Aucun degrade nulle part — un degrade
     est une couleur qui n'existe pas, on ne peut ni l'imprimer, ni la
     citer, ni la retrouver sur une carte de visite. Un aplat, oui.
     #2FB7A6 sur le fond : 8,1:1, tres au-dessus du seuil AA, donc
     utilisable aussi bien en texte qu'en aplat. */
  --marque:      #2FB7A6;
  --marque-vif:  #55D9C8;                      /* survols, etats actifs */
  --marque-voile: rgba(47, 183, 166, .12);     /* fonds tres legers */

  /* Etats — reserves au rapport de scan. */
  --crit: #FF5470;
  --warn: #FFB13D;
  --ok:   #34E5A0;

  /* La barre oblique du LOGOTYPE ne suit pas le theme : c'est la
     couleur de la marque, pas une couleur d'interface. Elle reste
     #2FB7A6 sur fond sombre comme sur fond clair. */
  --marque-logo: #2FB7A6;

  --gouttiere: clamp(20px, 5vw, 56px);
  --rayon:     14px;
  --rayon-lg:  22px;

  --t-court: .22s cubic-bezier(.4, 0, .2, 1);
  --t-long:  .6s  cubic-bezier(.22, 1, .36, 1);

  --z-entete: 70;
  --z-menu:   90;
  --z-rideau: 120;
}


/* ------------------------------------------------------------ THEME CLAIR */
/* Le meme site, sur papier. Trois choses ne se transposent PAS telles
   quelles d'un fond noir a un fond ivoire :

   1. la couleur de marque. #2FB7A6 donne 8,1:1 sur le noir et seulement
      2,5:1 sur l'ivoire — inutilisable en texte. Le clair prend donc un
      teal fonce, 6,1:1, qui est la MEME couleur assombrie, pas une
      autre couleur ;
   2. les couleurs d'etat. Rouge, ambre et vert clairs sont illisibles
      sur blanc : elles descendent toutes au-dessus de 4,5:1 ;
   3. la plage de gris. Sur ivoire elle est plus courte que sur noir :
      les niveaux se resserrent, et la hierarchie se joue sur la taille
      et la graisse plutot que sur la clarte. */

[data-theme="light"] {
  --nuit:       #F7F7F4;
  --nuit-2:     #FFFFFF;
  --carte:      #FFFFFF;
  --carte-2:    #F1F1EC;
  --trait:      rgba(16, 22, 34, .13);
  --trait-fort: rgba(16, 22, 34, .26);

  --texte:   #0C1019;
  --texte-2: #4A505C;                          /* 7,4:1 */
  --texte-3: #5E6472;                          /* 5,4:1 */

  /* La couleur de marque NE CHANGE PAS avec le theme : #2FB7A6 sur
     le papier comme sur la nuit — decision du 19/09/2026. A savoir :
     sur l ivoire elle donne 2,5:1, ce qui passe tres bien en APLAT
     (bouton, puce, filet, logo) mais reste sous le seuil AA partout ou
     elle porte du TEXTE. Les endroits concernes sont listes dans le
     LISEZMOI. La variante vive est legerement assombrie : sur fond
     clair, un survol plus lumineux ne se verrait pas. */
  --marque:       #2FB7A6;
  --marque-vif:   #22A192;
  --marque-voile: rgba(47, 183, 166, .12);

  --crit: #D42A4E;                             /* 4,6:1 */
  --warn: #9A6300;                             /* 4,8:1 */
  --ok:   #10784F;                             /* 5,1:1 */
}

/* Le bouton plein : encre claire sur teal fonce. */
[data-theme="light"] .bouton--plein:hover { box-shadow: 0 10px 34px -12px rgba(47, 183, 166, .7); }
[data-theme="light"] ::selection { background: var(--marque); color: #05070E; }

/* Le repli du hero quand WebGL manque, et le voile de lisibilite : les
   deux etaient calcules pour du noir. */
[data-theme="light"] .hero::before {
  background:
    radial-gradient(62% 52% at 74% 38%, rgba(47, 183, 166, .14), transparent 70%),
    var(--nuit);
}
[data-theme="light"] .hero__voile {
  background:
    linear-gradient(100deg, var(--nuit) 4%, rgba(247, 247, 244, .86) 34%, rgba(247, 247, 244, .12) 62%, transparent 82%),
    linear-gradient(to top, var(--nuit) 1%, transparent 26%);
}
@media (max-width: 860px) {
  [data-theme="light"] .hero__voile {
    background: linear-gradient(to bottom,
      transparent 0%,
      transparent 24%,
      rgba(247, 247, 244, .40) 32%,
      rgba(247, 247, 244, .88) 41%,
      var(--nuit) 49%);
  }
  [data-theme="light"] .hero::before {
    background:
      radial-gradient(74% 30% at 50% 17%, rgba(47, 183, 166, .14), transparent 70%),
      var(--nuit);
  }
}

/* L'en-tete pose et le loader. */
[data-theme="light"] .entete.est-pose { background: rgba(247, 247, 244, .82); }

/* Le code en ligne : le fond teinte devient trop sourd sur blanc. */
[data-theme="light"] code {
  background: rgba(47, 183, 166, .10);
  border-color: rgba(47, 183, 166, .30);
}
[data-theme="light"] .point__preuve { background: rgba(16, 22, 34, .04); }

/* Les fonds poses en rgba() ne suivent aucun jeton : ils restaient
   sombres sur le theme clair. On les reprend un par un — c'est le prix
   d'une couleur ecrite en dur, et la raison de ne pas en ecrire. */
[data-theme="light"] .scanner__ligne { background: rgba(255, 255, 255, .86); }
[data-theme="light"] .bouton--trait,
[data-theme="light"] .bouton-rond { background: rgba(16, 22, 34, .04); }
[data-theme="light"] .bouton--trait:hover,
[data-theme="light"] .bouton-rond:hover { background: rgba(47, 183, 166, .14); }
[data-theme="light"] .champ input,
[data-theme="light"] .champ select,
[data-theme="light"] .champ textarea { background: rgba(16, 22, 34, .035); }
[data-theme="light"] .rapport__pied { background: rgba(16, 22, 34, .035); }
[data-theme="light"] .cadran {
  background: conic-gradient(var(--teinte) calc(var(--p) * 1%), rgba(16, 22, 34, .10) 0);
}
[data-theme="light"] .famille__jauge { background: rgba(16, 22, 34, .10); }
[data-theme="light"] .scanner__ligne:focus-within {
  box-shadow: 0 0 0 4px rgba(47, 183, 166, .18), 0 18px 50px -24px rgba(47, 183, 166, .6);
}
[data-theme="light"] .champ input:focus,
[data-theme="light"] .champ select:focus,
[data-theme="light"] .champ textarea:focus { box-shadow: 0 0 0 3px rgba(47, 183, 166, .18); }
[data-theme="light"] .evitement { color: #05070E; }

/* ------------------------------------------------ BASCULE DE THEME */

.theme-bascule { position: relative; }
.theme-bascule .ico {
  position: absolute; width: 19px; height: 19px;
  transition: opacity .3s var(--t-court), transform .35s cubic-bezier(.22, 1, .36, 1);
}
.theme-bascule .ico--soleil { opacity: 0; transform: rotate(-90deg) scale(.6); }
[data-theme="light"] .theme-bascule .ico--lune   { opacity: 0; transform: rotate(90deg) scale(.6); }
[data-theme="light"] .theme-bascule .ico--soleil { opacity: 1; transform: none; }

/* ----------------------------------------------------------------- SOCLE */

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

html {
  /* Reserve la place de la barre de defilement : sans cela, chaque
     verrouillage du scroll (menu ouvert) decale toute la page de
     quelques pixels vers la droite. */
  scrollbar-gutter: stable;
  -webkit-text-size-adjust: 100%;
}

body {
  margin: 0;
  background: var(--nuit);
  color: var(--texte);
  font: 400 clamp(15px, .55vw + 13px, 17px)/1.65 'Inter', system-ui, -apple-system, 'Segoe UI', sans-serif;
  font-feature-settings: 'kern', 'liga', 'cv11';
  overflow-x: hidden;
}

h1, h2, h3, h4 {
  font-family: 'Instrument Sans', 'Inter', sans-serif;
  font-weight: 600;
  line-height: 1;
  letter-spacing: -.035em;
  margin: 0;
  text-wrap: balance;
}

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

a { color: inherit; text-decoration-color: var(--trait-fort); text-underline-offset: .18em; }
a:hover { text-decoration-color: currentColor; }

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

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

code {
  font-family: 'IBM Plex Mono', ui-monospace, monospace;
  font-size: .86em;
  color: var(--marque);
  background: rgba(47, 183, 166, .08);
  border: 1px solid rgba(47, 183, 166, .16);
  border-radius: 5px;
  padding: .08em .35em;
  /* Pas de `white-space: nowrap` : un jeton comme
     `X-Content-Type-Options` mesure 150 px et ne tient pas dans une
     colonne etroite — il faisait deborder la carte. Sans nowrap, les
     courts (`.env`) restent d'un bloc de toute facon, et les longs se
     coupent proprement sur leurs traits d'union. */
  overflow-wrap: break-word;
}

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

::selection { background: var(--marque); color: #05070E; }

/* --------------------------------------------- BARRE DE DEFILEMENT */
/* Les pseudo-elements d'abord, les proprietes standard SEULEMENT pour
   les moteurs qui n'en ont pas.

   Chromium comprend desormais `scrollbar-width` / `scrollbar-color` —
   et des qu'elles sont posees sur un element, il IGNORE tous les
   `::-webkit-scrollbar*` de cet element. On perdrait la largeur, le
   pouce arrondi et surtout les etats de survol, que `scrollbar-color`
   ne sait pas exprimer. La garde @supports evite le piege : elle est
   vraie sous Firefox, fausse sous Chromium. */
::-webkit-scrollbar { width: 12px; height: 12px; }
::-webkit-scrollbar-track { background: var(--nuit-2); }
::-webkit-scrollbar-thumb {
  background-color: var(--marque);
  /* Une bordure transparente + `background-clip` fabriquent une
     gouttiere : le rail se voit au travers, le pouce parait plus fin
     sans qu'on reduise la zone cliquable. */
  border: 3px solid transparent;
  background-clip: padding-box;
  border-radius: 999px;
}
::-webkit-scrollbar-thumb:hover { background-color: var(--marque-vif); }
::-webkit-scrollbar-corner { background: var(--nuit-2); }

@supports not selector(::-webkit-scrollbar) {
  html { scrollbar-width: thin; scrollbar-color: var(--marque) var(--nuit-2); }
}

/* Lu par les lecteurs d'ecran, invisible a l'ecran. Sert a dire le
   niveau d'un constat du rapport, que la couleur seule porterait. */
.sr-only {
  position: absolute; width: 1px; height: 1px;
  margin: -1px; padding: 0; border: 0;
  clip-path: inset(50%); overflow: hidden; white-space: nowrap;
}

/* Le lien d'evitement, visible seulement au clavier. */
.evitement {
  position: fixed; top: 10px; left: 10px; z-index: 200;
  padding: .7em 1.1em; border-radius: 8px;
  background: var(--marque); color: #fff; text-decoration: none;
  transform: translateY(-160%);
  transition: transform var(--t-court);
}
.evitement:focus { transform: none; }

/* ------------------------------------------------------------ UTILITAIRES */

.enveloppe {
  width: min(1240px, 100% - var(--gouttiere) * 2);
  margin-inline: auto;
}

/* Les listes de la page sont en grille : leurs <li> sont donc des
   ELEMENTS DE GRILLE, et un element de grille a `min-width: auto` — il
   ne descend jamais sous la largeur minimale de son contenu et elargit
   sa colonne au-dela de la carte qui le contient. La carte deborde,
   `overflow-x: hidden` sur body coupe le depassement, et rien ne le
   signale : le texte est simplement rogne sur mobile. Un mini a zero
   sur les enfants regle le cas sans toucher aux gabarits de colonnes. */
.coordonnees > li, .console__etapes > li,
.pied__col > a, .champ > * { min-width: 0; }

.section { padding: clamp(72px, 10vw, 148px) 0; position: relative; }
.section--constat,
.section--niveaux,
.section--publics,
.section--contact { background: var(--nuit-2); }

.section__tete { max-width: 62ch; margin-bottom: clamp(40px, 5vw, 72px); }
.section__tete--centree { margin-inline: auto; text-align: center; }
.section__tete--centree .surtitre { justify-content: center; }

.surtitre {
  display: flex; align-items: center; gap: .7em;
  font-family: 'Instrument Sans', system-ui, sans-serif;
  font-size: 11px; font-weight: 500;
  letter-spacing: .26em; text-transform: uppercase;
  color: var(--texte-3);
  margin: 0 0 1.4em;
}
.surtitre__puce {
  width: 4px; height: 9px; flex: none;
  background: var(--marque);
  transform: skewX(-20deg);         /* la barre oblique du logotype */
}

.titre-section {
  font-size: clamp(2rem, 1.2rem + 3.1vw, 3.6rem);
  margin-bottom: .55em;
}
.titre-section:last-child { margin-bottom: 0; }

/* Titre decoupe en lignes par main.js. Le masque descend SOUS la ligne de
   base (`padding-bottom`) et la marge negative annule la place prise :
   sans ca, il tranche le jambage des `p` et des `g`. */
.ligne-t {
  display: block;
  overflow: hidden;
  padding-bottom: .16em;
  margin-bottom: -.16em;
}
.ligne-t__in { display: block; will-change: transform; }
.titre-decoupe .mot.accent { display: inline-block; }

@media (prefers-reduced-motion: reduce) {
  .ligne-t { overflow: visible; }
}

/* Le mot accentue : un degrade dans le texte, une seule fois par titre. */
/* Dans un titre, le mot accentue est compose dans L'AUTRE typo : un
   Instrument Serif italique au milieu d'un Instrument Sans. C'est le
   contraste de DESSIN qui porte l'accent ; la couleur ne fait que le
   confirmer. Systeme repris d'orealys.com.
   Plus de `background-clip: text` : avec une couleur pleine il ne sert
   a rien, et il rognait la jambe des italiques. */
.accent {
  font-family: 'Instrument Serif', 'Times New Roman', serif;
  font-style: italic;
  font-weight: 400;
  letter-spacing: -.01em;
  color: var(--marque);
}

.texte { color: var(--texte-2); max-width: 62ch; }
.texte--large { font-size: clamp(1.02rem, .98rem + .3vw, 1.16rem); }

.duo {
  display: grid; gap: clamp(28px, 4vw, 72px);
  grid-template-columns: minmax(0, 1fr);
  align-items: start;
}
@media (min-width: 900px) {
  .duo { grid-template-columns: minmax(0, 1.05fr) minmax(0, 1fr); }
  .duo--contact { grid-template-columns: minmax(0, 1fr) minmax(0, 1.1fr); }
}

/* ---------------------------------------------------------------- BOUTONS */

.bouton {
  display: inline-flex; align-items: center; justify-content: center; gap: .6em;
  font-family: 'Instrument Sans', system-ui, sans-serif;
  font-size: .98rem; font-weight: 500; letter-spacing: -.01em;
  padding: .92em 1.5em;
  border: 1px solid transparent; border-radius: 10px;
  text-decoration: none; cursor: pointer;
  transition: transform var(--t-court), box-shadow var(--t-court),
              background-color var(--t-court), border-color var(--t-court);
}
.bouton--plein {
  background: var(--marque); color: #05070E;
  box-shadow: 0 0 0 0 rgba(47, 183, 166, .5);
}
.bouton--plein:hover {
  background: var(--marque-vif);
  transform: translateY(-2px);
  box-shadow: 0 10px 34px -12px rgba(47, 183, 166, .85);
}
.bouton--trait {
  border-color: var(--trait-fort); color: var(--texte);
  background: rgba(142, 156, 210, .05);
}
.bouton--trait:hover { border-color: var(--marque); background: rgba(47, 183, 166, .12); }
.bouton--petit { padding: .62em 1.05em; font-size: .88rem; border-radius: 8px; }
.bouton--bloc { display: flex; width: 100%; }

/* Un verbe en gros, son complement dessous. La coupe est ECRITE, pas
   subie : dans une colonne de cinq, « Demander l'audit code » se coupait
   ou bon lui semblait. Le `gap` du bouton est remis a zero — il vaut
   .6em pour la fleche des boutons d'une seule ligne. */
.bouton--duo {
  flex-direction: column;
  gap: 0;
  padding-block: .78em;
  line-height: 1.18;
  text-align: center;
}
.bouton__fort   { font-size: 1.04rem; font-weight: 600; letter-spacing: -.02em; }
.bouton__faible { font-size: .82rem; font-weight: 400; opacity: .72; }
.bouton[disabled] { opacity: .55; pointer-events: none; }

/* ----------------------------------------------------------------- RIDEAU */
/* Il masque le premier rendu le temps que les polices arrivent. Aucune
   barre de progression : une progression fausse est pire que pas de
   progression du tout. */

.rideau {
  position: fixed; inset: 0; z-index: var(--z-rideau);
  display: grid; place-items: center;
  background: var(--nuit);
  transition: opacity .5s ease, visibility .5s;
}
html.pret .rideau,
html:not(.chargement) .rideau { opacity: 0; visibility: hidden; pointer-events: none; }
html:not(.js) .rideau { display: none; }

/* Le loader : la barre oblique du logo, blanche, qui se remplit a la
   couleur de la marque. Deux exemplaires exactement superposes, et c'est
   le CONTENEUR du plein qu'on rogne — `clip-path` en pourcentage sur un
   element HTML se calcule contre sa boite, ce qui est sur partout ; sur
   un <path> SVG, la boite de reference n'est pas la meme d'un moteur a
   l'autre. */
.loader { position: relative; width: min(230px, 56vw); }
.loader .logo-mot { width: 100%; height: auto; display: block; color: var(--texte); }
/* La barre du dessous : presque effacee, c'est le contenant. */
.loader .logo-mot__slash { fill: var(--marque-logo); opacity: .15; }

.loader__plein {
  position: absolute; inset: 0;
  clip-path: inset(100% 0 0 0);
  animation: remplir 1.9s cubic-bezier(.65, 0, .35, 1) infinite;
}
/* Les lettres du dessus disparaissent — elles sont en `currentColor` —
   et il ne reste que la barre, pleine, que le rognage decouvre. */
.loader__plein .logo-mot { color: transparent; }
.loader__plein .logo-mot__slash { fill: var(--marque-logo); opacity: 1; }

/* Il se remplit du bas vers le haut, marque un temps plein, puis se vide
   du bas vers le haut a son tour : la boucle ne montre jamais de saut. */
@keyframes remplir {
  0%   { clip-path: inset(100% 0 0 0); }
  40%  { clip-path: inset(0 0 0 0); }
  58%  { clip-path: inset(0 0 0 0); }
  98%  { clip-path: inset(0 0 100% 0); }
  100% { clip-path: inset(0 0 100% 0); }
}

/* ----------------------------------------------------------------- ENTETE */

.entete {
  position: fixed; inset: 0 0 auto; z-index: var(--z-entete);
  transition: background-color var(--t-court), border-color var(--t-court);
  border-bottom: 1px solid transparent;
}
.entete.est-pose {
  background: rgba(5, 7, 14, .78);
  backdrop-filter: blur(14px) saturate(140%);
  border-bottom-color: var(--trait);
}

/* --r va de 0 (en haut de page) a 1 (defile), pose par main.js a chaque
   defilement. Tout ce qui retrecit s'y accroche, donc la reduction est
   CONTINUE : pas de bascule entre deux etats, pas de saut. Sans
   JavaScript la variable reste a 0 et l'en-tete garde sa grande
   taille — c'est le bon repli. */
:root { --r: 0; --logo-max: clamp(132px, 12vw, 200px); --logo-min: 110px; }

.entete__in {
  width: min(1240px, 100% - var(--gouttiere) * 2);
  margin-inline: auto;
  display: flex; align-items: center; gap: clamp(16px, 3vw, 40px);
  padding: calc(24px - 10px * var(--r)) 0;
}

.entete__logo {
  display: flex; align-items: center; gap: .8rem;
  text-decoration: none; color: var(--texte);
  flex: none;
}
.logo-mot { width: calc(var(--logo-max) - (var(--logo-max) - var(--logo-min)) * var(--r)); height: auto; }
/* La barre oblique garde la couleur du logo, au survol comme au repos :
   un logotype qui change de couleur quand la souris passe dessus se
   comporte comme un bouton. Ce n'en est pas un. */
.logo-mot__slash { fill: var(--marque-logo); }


.nav-inline { display: none; margin-left: auto; gap: clamp(14px, 2vw, 30px); }
@media (min-width: 1060px) { .nav-inline { display: flex; } }
.nav-inline a {
  font-size: .92rem; color: var(--texte-2); text-decoration: none;
  padding: .3em 0; position: relative;
  transition: color var(--t-court);
}
.nav-inline a::after {
  content: ''; position: absolute; left: 0; right: 100%; bottom: 0; height: 1px;
  background: var(--marque);
  transition: right var(--t-court);
}
.nav-inline a:hover, .nav-inline a.est-active { color: var(--texte); }
.nav-inline a:hover::after, .nav-inline a.est-active::after { right: 0; }

.entete__actions { display: flex; align-items: center; gap: 10px; margin-left: auto; }
@media (min-width: 1060px) { .entete__actions { margin-left: 0; } }
@media (max-width: 720px) { .entete__actions .bouton { display: none; } }

/* Le bouton de menu et celui de fermeture sont le MEME objet : un carre
   arrondi de 46 px, dessine une seule fois. Le mot « Menu » a ete retire —
   un libelle a cote de trois traits, c'est la barre de navigation par
   defaut de n'importe quel gabarit. Le nom passe en `aria-label`, lu par
   les lecteurs d'ecran sans encombrer la barre.

   Les traits sont INCLINES a -20 degres, comme la barre oblique du
   logotype et la puce des surtitres. C'est le seul signe de la marque,
   et il ne coute pas un pixel de plus. */
/* Le cercle est pour la bascule de theme, et pour elle seule : deux
   boutons encadres cote a cote se lisaient comme une paire, alors
   qu'ils ne font pas le meme genre de chose. Le burger, lui, est nu. */
.bouton-rond {
  display: grid; place-items: center;
  width: 42px; height: 42px; padding: 0; flex: none;
  background: rgba(142, 156, 210, .05);
  border: 1px solid var(--trait); border-radius: 50%;
  color: var(--texte); cursor: pointer;
  transition: border-color var(--t-court), background-color var(--t-court);
}
.bouton-rond:hover { border-color: var(--marque); background: rgba(47, 183, 166, .14); }

/* Le burger, sans cadre. La zone TOUCHABLE fait quand meme 44 px — le
   minimum confortable au doigt — grace au remplissage : le dessin est
   petit, la cible ne l'est pas. */
.menu-bascule {
  display: grid; place-items: center;
  width: 44px; height: 44px; padding: 0; flex: none;
  background: none; border: 0;
  color: var(--texte); cursor: pointer;
  transition: color var(--t-court);
}
.menu-bascule:hover { color: var(--marque); }

/* L'icone d'orealys.com : deux traits DROITS de 26 px, 2 px d'epaisseur,
   5 px d'ecart. Plus allonge que ce qu'il y avait, et sans inclinaison
   — le signe oblique de la marque reste sur la puce des surtitres et
   dans le logotype, ou il ne peut pas se confondre avec une croix. */
.menu-bascule__traits { display: grid; gap: 5px; width: 26px; }
.menu-bascule__traits i {
  display: block; height: 2px; border-radius: 2px;
  background: currentColor;
  transition: transform .35s cubic-bezier(.22, 1, .36, 1);
}
/* Les centres des deux traits sont distants de 7 px (2 px de haut + 5 de
   gouttiere) : chacun se deplace de la moitie pour se rejoindre. */
body.menu-ouvert .menu-bascule__traits i:first-child { transform: translateY(3.5px) rotate(45deg); }
body.menu-ouvert .menu-bascule__traits i:last-child  { transform: translateY(-3.5px) rotate(-45deg); }

/* Menu ouvert : l'en-tete passe AU-DESSUS du voile, sinon le bouton qui
   vient de se transformer en croix serait recouvert et injoignable. Il
   se depouille au passage — le voile lui sert de fond. */
body.menu-ouvert .entete {
  z-index: calc(var(--z-menu) + 1);
  background: transparent;
  backdrop-filter: none;
  border-bottom-color: transparent;
}

@media (min-width: 1060px) { .menu-bascule { display: none; } }

/* ------------------------------------------------------------ MENU PLEIN */

/* Le menu DESCEND : le voile se decouvre du haut vers le bas, puis les
   entrees montent l'une apres l'autre. Un simple fondu d'opacite ne se
   voit pas — l'oeil n'y percoit qu'un changement d'etat, pas une arrivee.

   Tout est en CSS, rien en GSAP : ce voile contient la seule porte de
   sortie du menu, il ne doit dependre d'aucun ticker. */
.menu-plein {
  position: fixed; inset: 0; z-index: var(--z-menu);
  background: var(--nuit-2);
  display: grid; align-content: center;
  padding: clamp(80px, 12vh, 140px) var(--gouttiere);
  clip-path: inset(0 0 100% 0);
  transition: clip-path .58s cubic-bezier(.76, 0, .24, 1);
}
/* Pas de `visibility` dans la transition : un element encore
   `visibility:hidden` n'est pas focusable, et le focus donne a
   l'ouverture retomberait sur <body>. L'etat « non rendu » est deja
   porte par l'attribut [hidden]. */
.menu-plein[hidden] { display: none; }
.menu-plein.est-ouvert { clip-path: inset(0); }

.menu-plein__nav { display: grid; gap: clamp(2px, 1.2vh, 10px); }
/* La ligne est un masque : le lien monte DERRIERE elle au lieu
   d'apparaitre sur place. */
.menu-plein__ligne { display: block; overflow: hidden; }
.menu-plein__nav a {
  display: flex; align-items: baseline; gap: 1.1rem;
  font-family: 'Instrument Sans', 'Inter', sans-serif;
  font-weight: 700;
  font-size: clamp(2.2rem, 7.6vw, 4.6rem);
  line-height: 1.04;
  letter-spacing: -.035em; text-decoration: none; color: var(--texte);
}
/* Chaque entree porte son rang dans --i : le retard se calcule en CSS,
   sans une ligne de script. Reglages repris de gwstudio.fr — 40 px de
   montee, 0,6 s, 0,07 s d'ecart, 0,12 s d'attente. */
.menu-plein__nav a {
  opacity: 0; transform: translateY(40px);
  transition: opacity .6s cubic-bezier(.22, 1, .36, 1),
              transform .6s cubic-bezier(.22, 1, .36, 1),
              color var(--t-court);
}
.menu-plein.est-ouvert .menu-plein__nav a {
  opacity: 1; transform: none;
  transition-delay: calc(.12s + var(--i, 0) * .07s);
}
/* Le survol doit battre la regle d'ouverture, qui est plus specifique. */
.menu-plein.est-ouvert .menu-plein__nav a:hover {
  color: var(--marque); transform: translateX(12px);
  transition-delay: 0s;
}
.menu-plein__num {
  font-family: 'Instrument Sans', system-ui, sans-serif;
  font-size: .7rem; font-weight: 600; color: var(--marque);
  letter-spacing: .12em; flex: none;
}
.menu-plein__pied {
  margin-top: clamp(28px, 5vh, 56px);
  display: flex; flex-wrap: wrap; gap: 1.4rem;
  font-family: 'Instrument Sans', system-ui, sans-serif; font-size: .82rem;
  color: var(--texte-2);
  opacity: 0; transform: translateY(18px);
  transition: opacity .45s ease, transform .55s cubic-bezier(.22, 1, .36, 1);
}
.menu-plein.est-ouvert .menu-plein__pied {
  opacity: 1; transform: none;
  transition-delay: calc(.16s + var(--n, 6) * .055s);
}

/* ------------------------------------------------------------------- HERO */

.hero {
  position: relative;
  min-height: 100svh;
  display: grid; align-items: center;
  padding: clamp(104px, 14vh, 152px) 0 clamp(56px, 8vh, 96px);
  isolation: isolate;
  overflow: hidden;
}

/* Fond de repli : si WebGL manque ou que la scene est retiree, il reste
   une nuit degradee credible, pas un aplat noir. */
.hero::before {
  content: ''; position: absolute; inset: 0; z-index: -3;
  background:
    radial-gradient(62% 52% at 74% 38%, rgba(47, 183, 166, .16), transparent 70%),
    var(--nuit);
}
.hero__scene {
  position: absolute; inset: 0; z-index: -2;
  width: 100%; height: 100%;
  opacity: 0; transition: opacity 1.1s ease;
}
.hero__scene.est-prete { opacity: 1; }

/* Le voile : il assombrit le cote du texte pour tenir le contraste,
   quoi que fasse la scene derriere. */
.hero__voile {
  position: absolute; inset: 0; z-index: -1;
  background:
    linear-gradient(100deg, var(--nuit) 4%, rgba(5, 7, 14, .82) 34%, rgba(5, 7, 14, .1) 62%, transparent 82%),
    linear-gradient(to top, var(--nuit) 1%, transparent 26%);
}
@media (max-width: 860px) {
  /* Sur un telephone, le texte occupe TOUTE la largeur. La scene ne
     passe plus DERRIERE lui : elle est calee en haut, on n'en voit que
     la moitie basse (le cadrage est fait dans hero3d.js), et le texte
     commence dessous.

     Elle reste donc a pleine lumiere — plus d'opacite baissee. Le voile
     ne l'assombrit plus : il est transparent sur la bande du haut, et
     devient plein juste au-dessus du texte. */
  .hero__scene.est-prete { opacity: 1; }
  .hero__voile {
    background: linear-gradient(to bottom,
      transparent 0%,
      transparent 24%,
      rgba(5, 7, 14, .35) 32%,
      rgba(5, 7, 14, .86) 41%,
      var(--nuit) 49%);
  }
  /* La lueur de repli suit la sphere : en haut, centree. */
  .hero::before {
    background:
      radial-gradient(74% 30% at 50% 17%, rgba(47, 183, 166, .18), transparent 70%),
      var(--nuit);
  }
  /* La place de la sphere, reservee en haut du cadre. */
  .hero { padding-top: 42svh; }
  .hero__titre { font-size: clamp(1.78rem, 7.4vw, 2.4rem); }
  .hero__chapeau { font-size: 1rem; }
}

.hero__in { width: min(1240px, 100% - var(--gouttiere) * 2); margin-inline: auto; position: relative; }

.surtitre--hero { color: var(--texte-2); }

.hero__titre {
  /* La taille suit la largeur pour que chaque ligne ecrite dans le HTML
     reste UNE ligne a l'ecran : ce sont les coupes voulues, et la
     revelation ligne par ligne n'a de sens que si elles tiennent. En
     dessous de 760 px on laisse le texte se replier — mieux vaut une
     coupe subie qu'un titre qui deborde. */
  font-size: clamp(2.05rem, 4.7vw, 4.4rem);
  font-weight: 600;
  margin-bottom: .42em;
}
.hero__titre .ligne { display: block; overflow: hidden; padding-bottom: .05em; }
.hero__titre .ligne > span { display: block; }
@media (min-width: 760px) { .hero__titre .ligne > span { white-space: nowrap; } }

.hero__chapeau {
  color: var(--texte-2);
  font-size: clamp(1rem, .95rem + .4vw, 1.14rem);
  max-width: 54ch;
  margin-bottom: 1.9em;
}

.hero__defile {
  position: absolute; bottom: 26px; left: 50%; translate: -50% 0;
  width: 1px; height: 54px; overflow: hidden;
  background: var(--trait);
}
.hero__defile span {
  position: absolute; inset: 0;
  background: var(--marque);
  animation: descend 2.6s cubic-bezier(.7, 0, .3, 1) infinite;
}
@keyframes descend {
  0%   { transform: translateY(-100%); }
  60%  { transform: translateY(100%); }
  100% { transform: translateY(100%); }
}
@media (max-width: 860px) { .hero__defile { display: none; } }

/* --------------------------------------------------------------- SCANNER */

.scanner { max-width: 660px; }
.scanner__label {
  display: block;
  font-family: 'Instrument Sans', system-ui, sans-serif;
  font-size: .7rem; font-weight: 500; letter-spacing: .14em; text-transform: uppercase;
  color: var(--texte-3); margin-bottom: .9em;
}

.scanner__ligne {
  display: flex; align-items: center; gap: 8px;
  background: rgba(12, 16, 32, .82);
  border: 1px solid var(--trait-fort);
  border-radius: var(--rayon);
  padding: 7px 7px 7px clamp(12px, 2vw, 18px);
  backdrop-filter: blur(10px);
  transition: border-color var(--t-court), box-shadow var(--t-court);
}
.scanner__ligne:focus-within {
  border-color: var(--marque);
  box-shadow: 0 0 0 4px rgba(47, 183, 166, .16), 0 18px 50px -24px rgba(47, 183, 166, .8);
}
.scanner.est-erreur .scanner__ligne { border-color: var(--crit); }

.scanner__protocole {
  font-family: 'IBM Plex Mono', monospace;
  font-size: .9rem; color: var(--texte-3); flex: none;
}
@media (max-width: 520px) { .scanner__protocole { display: none; } }

.scanner__champ {
  flex: 1 1 auto; min-width: 0;
  background: none; border: 0; color: var(--texte);
  font: 400 clamp(1rem, .95rem + .3vw, 1.12rem) 'IBM Plex Mono', monospace;
  padding: .7em 0;
}
.scanner__champ::placeholder { color: var(--texte-3); opacity: .7; }
.scanner__champ:focus { outline: none; }

.scanner__bouton { flex: none; padding: .85em 1.25em; }
.scanner__bouton-fleche { transition: transform var(--t-court); }
.scanner__bouton:hover .scanner__bouton-fleche { transform: translateX(3px); }
@media (max-width: 460px) {
  .scanner__ligne { flex-wrap: wrap; }
  .scanner__bouton { width: 100%; }
}

.scanner__aide { margin: 1em 0 0; font-size: .84rem; color: var(--texte-3); }
/* `display:flex` est une regle AUTEUR : elle ecrase le `display:none`
   que le navigateur applique via [hidden] (les styles auteur battent la
   feuille UA quelle que soit la specificite). Sans la ligne qui suit,
   le message d'erreur — et sa puce — s'affichent des le chargement.
   Verifier un element masque par [hidden], c'est lire son `display`
   calcule, jamais l'attribut. */
.scanner__erreur[hidden] { display: none; }
.scanner__erreur {
  margin: .9em 0 0; font-size: .88rem; color: var(--crit);
  display: flex; align-items: flex-start; gap: .5em;
}
.scanner__erreur::before { content: '△'; flex: none; }

/* ---------------------------------------------------------------- RAPPORT */

.rapport { padding: clamp(40px, 6vw, 80px) 0 clamp(60px, 8vw, 110px); scroll-margin-top: 90px; }
.rapport[hidden] { display: none; }

.rapport__cadre {
  width: min(1240px, 100% - var(--gouttiere) * 2);
  margin-inline: auto;
  background: var(--carte-2);
  border: 1px solid var(--trait-fort);
  border-radius: var(--rayon-lg);
  overflow: hidden;
}

/* --- pendant l'analyse : la console --- */

.console { padding: clamp(28px, 4vw, 48px); }
.console__cible {
  font-family: 'IBM Plex Mono', monospace; font-size: .9rem;
  color: var(--texte-2); margin-bottom: 1.6em;
  display: flex; align-items: center; gap: .6em; flex-wrap: wrap;
}
.console__cible b { color: var(--texte); font-weight: 500; }
.console__pastille {
  width: 8px; height: 8px; border-radius: 50%; background: var(--marque);
  animation: pulse 1.1s ease-in-out infinite;
}
@keyframes pulse { 0%, 100% { opacity: .25; } 50% { opacity: 1; } }

.console__etapes { display: grid; gap: .45em; font-family: 'Instrument Sans', system-ui, sans-serif; font-size: .84rem; }
.console__etape {
  display: flex; align-items: center; gap: .8em;
  color: var(--texte-3);
  opacity: .35;
  transition: opacity .3s ease, color .3s ease;
}
.console__etape.est-faite { opacity: 1; color: var(--texte-2); }
.console__etape.est-courante { opacity: 1; color: var(--marque); }
.console__etape::before {
  content: '·'; width: 1.2em; text-align: center; flex: none;
}
.console__etape.est-faite::before { content: '✓'; color: var(--ok); }
.console__etape.est-courante::before { content: '▸'; }

.console__barre { height: 2px; background: var(--trait); margin-top: 2em; overflow: hidden; border-radius: 2px; }
.console__barre i { display: block; height: 100%; width: 0; background: var(--marque); transition: width .4s ease; }

/* --- le resultat --- */

.resultat__tete {
  display: grid; gap: clamp(24px, 3vw, 44px);
  grid-template-columns: minmax(0, 1fr);
  align-items: center;
  padding: clamp(28px, 4vw, 48px);
  border-bottom: 1px solid var(--trait);
}
@media (min-width: 820px) { .resultat__tete { grid-template-columns: auto minmax(0, 1fr) auto; } }

/* Le cadran. Un conic-gradient pilote par une variable : pas de SVG a
   redessiner, pas de JS pour animer — une transition sur --p suffirait
   si elle etait animable ; on anime donc la valeur depuis le script. */
.cadran {
  --p: 0;
  position: relative;
  width: 148px; height: 148px; flex: none;
  border-radius: 50%;
  background: conic-gradient(var(--teinte) calc(var(--p) * 1%), rgba(142, 156, 210, .12) 0);
  display: grid; place-items: center;
}
.cadran::after {
  content: ''; position: absolute; inset: 9px;
  border-radius: 50%; background: var(--carte);
}
.cadran__valeur {
  position: relative; z-index: 1; text-align: center;
  font-family: 'Instrument Sans', 'Inter', sans-serif; font-weight: 600;
  font-size: 2.9rem; line-height: 1; letter-spacing: -.035em;
  color: var(--teinte);
}
.cadran__sur {
  display: block;
  font-family: 'Instrument Sans', system-ui, sans-serif;
  font-size: .62rem; letter-spacing: .14em; color: var(--texte-3);
  margin-top: .5em;
}
.cadran--bon      { --teinte: var(--ok); }
.cadran--moyen    { --teinte: var(--warn); }
.cadran--faible   { --teinte: var(--warn); }
.cadran--critique { --teinte: var(--crit); }

.resultat__dire { min-width: 0; }
.resultat__verdict {
  font-family: 'Instrument Sans', 'Inter', sans-serif; font-weight: 600;
  font-size: clamp(1.4rem, 1.1rem + 1.2vw, 2rem);
  letter-spacing: -.035em; margin-bottom: .35em;
}
.resultat__phrase { color: var(--texte-2); font-size: .98rem; max-width: 52ch; }
.resultat__cible {
  font-family: 'IBM Plex Mono', monospace; font-size: .8rem;
  color: var(--texte-3); margin-bottom: .8em;
  overflow-wrap: anywhere;
}
.resultat__stack { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 1.1em; }
.resultat__stack span {
  font-family: 'Instrument Sans', system-ui, sans-serif; font-size: .68rem;
  letter-spacing: .06em;
  color: var(--texte-2);
  border: 1px solid var(--trait); border-radius: 5px; padding: .3em .55em;
}

.compteurs { display: flex; gap: 10px; flex-wrap: wrap; }
@media (min-width: 820px) { .compteurs { flex-direction: column; } }
.compteur {
  display: flex; align-items: center; gap: .7em;
  border: 1px solid var(--trait); border-radius: 10px;
  padding: .6em .9em; min-width: 132px;
  font-size: .82rem; color: var(--texte-2);
}
.compteur b {
  font-family: 'Instrument Sans', system-ui, sans-serif; font-size: 1.25rem; font-weight: 500;
  color: var(--texte);
}
.compteur--critique { border-color: rgba(255, 84, 112, .4); }
.compteur--critique b { color: var(--crit); }
.compteur--important { border-color: rgba(255, 177, 61, .34); }
.compteur--important b { color: var(--warn); }
.compteur--ok b { color: var(--ok); }

/* --- les familles --- */

/* Le gabarit de colonne est EXPLICITE meme sur une seule colonne : une
   grille sans `grid-template-columns` cree une colonne implicite en
   `auto`, qui ne descend pas sous la largeur mini de son contenu. La
   carte depassait alors du cadre et se faisait rogner en silence. */
.familles { display: grid; gap: 1px; background: var(--trait); grid-template-columns: minmax(0, 1fr); }
@media (min-width: 900px) { .familles { grid-template-columns: repeat(2, minmax(0, 1fr)); } }

.famille { background: var(--carte); padding: clamp(22px, 3vw, 34px); }
.famille__tete {
  display: flex; align-items: baseline; justify-content: space-between; gap: 1em;
  margin-bottom: .3em;
}
.famille__titre { font-size: 1.16rem; }
.famille__note {
  font-family: 'Instrument Sans', system-ui, sans-serif; font-size: .9rem; font-weight: 600;
  flex: none;
}
.famille__chapeau { font-size: .84rem; color: var(--texte-3); margin-bottom: 1.3em; }
.famille__jauge { height: 3px; border-radius: 3px; background: rgba(142, 156, 210, .12); margin-bottom: 1.4em; overflow: hidden; }
.famille__jauge i { display: block; height: 100%; width: 0; transition: width .9s cubic-bezier(.22, 1, .36, 1); }

.point { border-top: 1px solid var(--trait); padding: .85em 0; }
.point:first-of-type { border-top: 0; padding-top: 0; }
.point__tete {
  display: flex; align-items: flex-start; gap: .7em;
  width: 100%; background: none; border: 0; padding: 0;
  color: inherit; text-align: left; cursor: pointer;
  font: inherit;
}
.point__marque { flex: none; width: 1.25em; margin-top: .15em; font-size: .9em; }
.point--critique  .point__marque { color: var(--crit); }
.point--important .point__marque { color: var(--warn); }
.point--mineur    .point__marque { color: var(--texte-3); }
.point--ok        .point__marque { color: var(--ok); }
.point__titre { flex: 1 1 auto; min-width: 0; font-size: .94rem; }
.point--ok .point__titre { color: var(--texte-2); }
.point__chevron { flex: none; color: var(--texte-3); transition: transform var(--t-court); font-size: .8em; }
.point.est-ouvert .point__chevron { transform: rotate(90deg); }

.point__corps { display: none; padding: .7em 0 .3em 1.95em; }
.point.est-ouvert .point__corps { display: block; }
.point__detail { font-size: .88rem; color: var(--texte-2); }
.point__preuve {
  display: block; margin-top: .7em;
  font-family: 'IBM Plex Mono', monospace; font-size: .74rem;
  color: var(--texte-3);
  background: rgba(5, 7, 14, .6);
  border: 1px solid var(--trait); border-radius: 7px;
  padding: .6em .75em;
  overflow-wrap: anywhere;
}

/* --- le pied du rapport --- */

.rapport__pied {
  padding: clamp(26px, 4vw, 44px);
  border-top: 1px solid var(--trait);
  background: rgba(5, 7, 14, .45);
  display: grid; gap: 1.4em;
}
@media (min-width: 820px) {
  .rapport__pied { grid-template-columns: 1fr auto; align-items: center; }
}
.rapport__suite { color: var(--texte-2); font-size: .94rem; max-width: 64ch; }
.rapport__suite strong { color: var(--texte); font-weight: 500; }
.rapport__actions { display: flex; gap: 10px; flex-wrap: wrap; }

.rapport__note {
  padding: 0 clamp(26px, 4vw, 44px) clamp(26px, 4vw, 44px);
  font-size: .78rem; color: var(--texte-3); max-width: 80ch;
}

/* ---------------------------------------------------------------- CHIFFRES */

.chiffres {
  display: grid; gap: 1px; background: var(--trait);
  border: 1px solid var(--trait); border-radius: var(--rayon-lg);
  overflow: hidden;
  margin-top: clamp(40px, 5vw, 72px);
  grid-template-columns: minmax(0, 1fr);
}
@media (min-width: 680px) { .chiffres { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (min-width: 1080px) { .chiffres { grid-template-columns: repeat(4, minmax(0, 1fr)); } }

.chiffre { background: var(--carte); padding: clamp(24px, 3vw, 34px); }
.chiffre__valeur {
  font-family: 'Instrument Sans', 'Inter', sans-serif; font-weight: 600;
  /* 5,4 rem est le PLAFOND, atteint vers 1 355 px. En dessous la
     taille suit la largeur : a 5,4 rem fixes, « +81 % » deborde de sa
     carte sur un telephone. */
  font-size: clamp(3rem, 1rem + 5.2vw, 5.4rem); line-height: 1;
  letter-spacing: -.04em;
  color: var(--marque);
  margin-bottom: .45em;
}
.chiffre__phrase { font-size: .92rem; color: var(--texte-2); }
.chiffre__source { margin-top: 1em; font-size: .72rem; }
.chiffre__source a { color: var(--texte-3); text-decoration-color: var(--trait); }
.chiffre__source a:hover { color: var(--marque); }

/* -------------------------------------------------------------- CONTROLES */

.grille-controles {
  display: grid; gap: 1px; background: var(--trait);
  border: 1px solid var(--trait); border-radius: var(--rayon-lg); overflow: hidden;
  grid-template-columns: minmax(0, 1fr);
}
@media (min-width: 760px) { .grille-controles { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (min-width: 1120px) { .grille-controles { grid-template-columns: repeat(3, minmax(0, 1fr)); } }

.ctrl {
  background: var(--carte);
  padding: clamp(26px, 3vw, 38px);
  transition: background-color var(--t-court);
}
.ctrl:hover { background: var(--carte-2); }
.ctrl__num {
  font-family: 'Instrument Sans', system-ui, sans-serif; font-size: .72rem;
  letter-spacing: .14em; color: var(--marque); margin-bottom: 1.5em;
}
.ctrl__titre { font-size: 1.3rem; margin-bottom: .4em; }
.ctrl__chapeau { font-size: .9rem; color: var(--texte-2); margin-bottom: 1.5em; }
/* Les puces de liste ne sont PAS en flex, et c'est delibere.

   Un `<li>` en `display: flex` transforme chacun de ses enfants en
   element de grille : le texte devient un element anonyme, mais chaque
   <code> inline en devient un AUTRE. La ligne « Fichiers sensibles
   accessibles : .env, .git » se retrouve decoupee en six colonnes, et
   le navigateur les repartit dans l'ordre du flux — ce qui se lit
   « Fichiers .env , .git sensibles accessibles : ». Sans `min-width: 0`
   les colonnes refusent de retrecir et la carte deborde ; avec, elles
   retrecissent et le texte part en morceaux. Les deux sont faux.

   La puce est donc posee en absolu et le texte reste du texte, qui
   s'ecoule normalement autour de ses <code>. */
.ctrl__liste { display: grid; gap: .62em; font-size: .86rem; color: var(--texte-3); }
.ctrl__liste li { position: relative; padding-left: 1.35em; line-height: 1.55; }
.ctrl__liste li::before {
  content: ''; position: absolute; left: 0; top: .58em;
  width: 6px; height: 6px;
  background: var(--marque); opacity: .55;
  transform: skewX(-20deg);
}

/* ---------------------------------------------------------------- NIVEAUX */

.niveaux { display: grid; gap: clamp(18px, 2.4vw, 28px); grid-template-columns: minmax(0, 1fr); }
@media (min-width: 880px) { .niveaux { grid-template-columns: repeat(2, minmax(0, 1fr)); } }

.niveau {
  background: var(--carte);
  border: 1px solid var(--trait);
  border-radius: var(--rayon-lg);
  padding: clamp(28px, 3.4vw, 44px);
  display: flex; flex-direction: column;
}
.niveau--fort {
  border-color: rgba(47, 183, 166, .42);
  background: var(--marque-voile);
}
.niveau__num {
  font-family: 'Instrument Sans', system-ui, sans-serif; font-size: .74rem;
  letter-spacing: .16em; color: var(--texte-3); margin-bottom: 1.6em;
}
.niveau__titre { font-size: clamp(1.5rem, 1.2rem + 1vw, 2rem); margin-bottom: .25em; }
.niveau__sous {
  font-family: 'Instrument Sans', system-ui, sans-serif; font-size: .76rem;
  letter-spacing: .06em; color: var(--marque); margin-bottom: 1.6em;
}
.niveau__texte { color: var(--texte-2); font-size: .95rem; margin-bottom: 1.6em; }
.niveau__atouts { display: grid; gap: .6em; margin-bottom: 2em; font-size: .88rem; color: var(--texte-2); }
.niveau__atouts li { position: relative; padding-left: 1.5em; }
.niveau__atouts li::before { content: '✓'; position: absolute; left: 0; top: 0; color: var(--ok); }
.niveau__prix {
  font-family: 'Instrument Sans', 'Inter', sans-serif; font-size: 1.6rem; font-weight: 600;
  letter-spacing: -.03em; margin-bottom: 1em; margin-top: auto;
}

/* --------------------------------------------------------------- PARCOURS */

.parcours {
  display: grid; gap: clamp(20px, 2.6vw, 34px);
  grid-template-columns: minmax(0, 1fr);
  counter-reset: etape;
  position: relative;
}
@media (min-width: 860px) {
  .parcours { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  /* Le trait qui relie les trois etapes, derriere les pastilles. */
  .parcours::before {
    content: ''; position: absolute; top: 26px; left: 12%; right: 12%; height: 1px;
    background: linear-gradient(90deg, transparent, var(--trait-fort) 12%, var(--trait-fort) 88%, transparent);
  }
}
.etape { position: relative; text-align: center; padding-top: 0; }
.etape__num {
  display: grid; place-items: center;
  width: 52px; height: 52px; margin: 0 auto 1.4em;
  border-radius: 50%;
  background: var(--nuit-2);
  border: 1px solid var(--trait-fort);
  font-family: 'Instrument Sans', 'Inter', sans-serif; font-size: 1.15rem; font-weight: 600;
  color: var(--marque);
  position: relative; z-index: 1;
}
.etape__titre { font-size: 1.35rem; margin-bottom: .5em; }
.etape__texte { color: var(--texte-2); font-size: .92rem; max-width: 42ch; margin-inline: auto; }

/* ---------------------------------------------------------------- TARIFS */

.formules {
  display: grid; gap: clamp(14px, 1.8vw, 20px);
  grid-template-columns: minmax(0, 1fr);
}
@media (min-width: 620px)  { .formules { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (min-width: 1120px) { .formules { grid-template-columns: repeat(5, minmax(0, 1fr)); } }

.formule {
  background: var(--carte);
  border: 1px solid var(--trait);
  border-radius: var(--rayon);
  padding: clamp(22px, 2.4vw, 28px);
  display: flex; flex-direction: column;
  position: relative;
}
.formule--fort {
  border-color: rgba(47, 183, 166, .45);
  background: var(--marque-voile);
}
.formule__badge {
  position: absolute; top: -10px; left: clamp(22px, 2.4vw, 28px);
  font-family: 'Instrument Sans', system-ui, sans-serif; font-size: .62rem; font-weight: 600;
  letter-spacing: .12em; text-transform: uppercase;
  background: var(--marque); color: #05070E;
  padding: .3em .6em; border-radius: 5px;
}
.formule__nom { font-size: 1.05rem; margin-bottom: .6em; }
.formule__prix {
  font-family: 'Instrument Sans', 'Inter', sans-serif; font-weight: 600;
  font-size: clamp(1.85rem, 1.5rem + 1.1vw, 2.3rem); letter-spacing: -.035em;
  line-height: 1; margin-bottom: .8em;
}
.formule__unite { font-size: .5em; color: var(--texte-3); margin-left: .2em; letter-spacing: 0; }
.formule__chapeau { font-size: .84rem; color: var(--texte-2); margin-bottom: 1.4em; }
.formule__liste { display: grid; gap: .55em; font-size: .8rem; color: var(--texte-3); margin-bottom: 1.8em; }
.formule__liste li { position: relative; padding-left: 1em; line-height: 1.5; }
.formule__liste li::before { content: '·'; position: absolute; left: .2em; top: 0; color: var(--marque); }
.formule .bouton { margin-top: auto; }

/* ---------------------------------------------------------------- PUBLICS */

.publics { display: grid; gap: clamp(16px, 2vw, 24px); grid-template-columns: minmax(0, 1fr); }
@media (min-width: 760px) { .publics { grid-template-columns: repeat(2, minmax(0, 1fr)); } }

.public {
  border: 1px solid var(--trait); border-radius: var(--rayon);
  padding: clamp(24px, 3vw, 34px);
  background: var(--carte);
}
.public__titre { font-size: 1.18rem; margin-bottom: .6em; }
.public__texte { color: var(--texte-2); font-size: .92rem; }

/* ----------------------------------------------------------------- HUMAIN */

.humain { display: grid; gap: clamp(28px, 4vw, 64px); grid-template-columns: minmax(0, 1fr); align-items: start; }
@media (min-width: 900px) { .humain { grid-template-columns: auto minmax(0, 1fr); } }

.humain__symbole { width: clamp(90px, 12vw, 148px); color: var(--marque); }
.humain__symbole .logo-symbole { width: 100%; height: auto; }
.humain__symbole .logo-symbole__slash { fill: currentColor; }

.humain__points {
  display: grid; gap: .6em; margin: 2em 0 1.6em;
  font-size: .9rem; color: var(--texte-2);
}
.humain__points li { position: relative; padding-left: 1.35em; }
.humain__points li::before {
  content: ''; position: absolute; left: 0; top: .6em;
  width: 6px; height: 6px;
  background: var(--marque); transform: skewX(-20deg);
}
.humain__marque {
  font-family: 'Instrument Sans', system-ui, sans-serif; font-size: .76rem;
  color: var(--texte-3); letter-spacing: .04em;
}

/* -------------------------------------------------------------------- FAQ */

.faq { border-top: 1px solid var(--trait); max-width: 88ch; }
.faq__item { border-bottom: 1px solid var(--trait); }
.faq__q {
  display: flex; align-items: flex-start; gap: 1em;
  padding: 1.25em 0; cursor: pointer;
  font-family: 'Instrument Sans', 'Inter', sans-serif;
  font-size: clamp(1.04rem, .98rem + .38vw, 1.26rem);
  letter-spacing: -.025em;
  list-style: none;
}
.faq__q::-webkit-details-marker { display: none; }
.faq__q::after {
  content: '+'; margin-left: auto; flex: none;
  color: var(--marque); font-size: 1.2em; line-height: 1;
  transition: transform var(--t-court);
}
.faq__item[open] .faq__q::after { transform: rotate(45deg); }
.faq__r { padding: 0 0 1.6em; color: var(--texte-2); max-width: 72ch; font-size: .95rem; }

/* -------------------------------------------------------------- FORMULAIRE */

.form {
  background: var(--carte);
  border: 1px solid var(--trait);
  border-radius: var(--rayon-lg);
  padding: clamp(24px, 3vw, 40px);
}
/* `align-items: start` est necessaire : sans lui, le second champ d'une
   rangee (sans marge basse) recoit l'espace en trop, le redistribue a
   sa ligne de libelle, et les deux champs se decalent de huit pixels. */
.form__duo { display: grid; gap: 0 18px; grid-template-columns: minmax(0, 1fr); align-items: start; }
@media (min-width: 560px) { .form__duo { grid-template-columns: repeat(2, minmax(0, 1fr)); } }

.champ { display: grid; gap: .5em; margin-bottom: 1.2em; }
.champ label {
  font-family: 'Instrument Sans', system-ui, sans-serif;
  font-size: .7rem; font-weight: 500; letter-spacing: .1em; text-transform: uppercase;
  color: var(--texte-3);
}
.champ input, .champ select, .champ textarea {
  width: 100%;
  background: rgba(5, 7, 14, .55);
  border: 1px solid var(--trait);
  border-radius: 9px;
  color: var(--texte);
  font: 400 .98rem/1.5 'Instrument Sans', system-ui, sans-serif;
  padding: .78em .9em;
  transition: border-color var(--t-court), box-shadow var(--t-court);
}
.champ textarea { resize: vertical; min-height: 7em; }
.champ input:focus, .champ select:focus, .champ textarea:focus {
  outline: none; border-color: var(--marque);
  box-shadow: 0 0 0 3px rgba(47, 183, 166, .16);
}
.champ select {
  appearance: none;
  background-image: linear-gradient(45deg, transparent 50%, var(--texte-3) 50%),
                    linear-gradient(135deg, var(--texte-3) 50%, transparent 50%);
  background-position: calc(100% - 18px) 55%, calc(100% - 13px) 55%;
  background-size: 5px 5px, 5px 5px;
  background-repeat: no-repeat;
}
.champ--case {
  grid-template-columns: auto 1fr; align-items: start; gap: .8em;
  margin-top: .4em;
}
.champ--case input { width: 18px; height: 18px; margin-top: .15em; accent-color: var(--marque); }
.champ--case label {
  font-family: 'Instrument Sans', system-ui, sans-serif; font-size: .82rem;
  text-transform: none; letter-spacing: 0; color: var(--texte-2);
  line-height: 1.5;
}

/* Le champ appat : sorti de l'ecran plutot que `display:none`, que
   certains robots savent reconnaitre. */
.appat { position: absolute; left: -9999px; width: 1px; height: 1px; overflow: hidden; }

.form__retour {
  padding: .9em 1.1em; border-radius: 9px; margin-bottom: 1.4em;
  font-size: .9rem;
  border: 1px solid;
}
.form__retour--ok { border-color: rgba(52, 229, 160, .4); background: rgba(52, 229, 160, .08); color: var(--ok); }
.form__retour--ko { border-color: rgba(255, 84, 112, .4); background: rgba(255, 84, 112, .08); color: var(--crit); }
.form__mention { margin-top: 1.1em; font-size: .76rem; color: var(--texte-3); }

.coordonnees { display: grid; gap: .5em; margin-top: 2em; font-family: 'Instrument Sans', system-ui, sans-serif; font-size: .88rem; color: var(--texte-2); }
.coordonnees a { text-decoration-color: var(--trait-fort); }
.coordonnees a:hover { color: var(--marque); }

/* ------------------------------------------------------------------- PIED */

.pied {
  border-top: 1px solid var(--trait);
  padding: clamp(56px, 7vw, 92px) 0 32px;
  background: var(--nuit);
}
.pied__haut {
  display: grid; gap: clamp(32px, 4vw, 56px);
  grid-template-columns: minmax(0, 1fr);
  padding-bottom: clamp(40px, 5vw, 64px);
}
@media (min-width: 720px)  { .pied__haut { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (min-width: 1020px) { .pied__haut { grid-template-columns: 1.6fr repeat(3, 1fr); } }

.pied__logo { width: 140px; color: var(--texte); margin-bottom: 1.4em; }
.pied__base { font-size: .88rem; color: var(--texte-2); }
.pied__signature {
  margin-top: 1.2em;
  font-family: 'Instrument Sans', system-ui, sans-serif; font-size: .76rem;
  letter-spacing: .06em;
  color: var(--marque);
}
.pied__col { display: grid; gap: .55em; align-content: start; }
.pied__col h3 {
  font-family: 'Instrument Sans', system-ui, sans-serif; font-size: .68rem; font-weight: 500;
  letter-spacing: .14em; text-transform: uppercase; color: var(--texte-3);
  margin-bottom: .6em;
}
.pied__col a { font-size: .88rem; color: var(--texte-2); text-decoration: none; }
.pied__col a:hover { color: var(--texte); }

.pied__bas {
  border-top: 1px solid var(--trait);
  padding-top: 24px;
  display: flex; flex-wrap: wrap; gap: 1em 1.6em;
  justify-content: space-between;
  font-size: .78rem; color: var(--texte-3);
}
.pied__bas nav { display: flex; flex-wrap: wrap; gap: 1.2em; }
.pied__bas a { text-decoration: none; }
.pied__bas a:hover { color: var(--texte-2); }

/* ------------------------------------------------------------- REVELATIONS */
/* Accrochees a `html.js` : sans JavaScript, rien n'est masque. */

html.js [data-reveal] {
  opacity: 0;
  transform: translateY(20px);
}
html.js [data-reveal].est-revelee {
  opacity: 1 !important;
  transform: none !important;
  transition: opacity .75s cubic-bezier(.22, 1, .36, 1),
              transform .75s cubic-bezier(.22, 1, .36, 1);
}

/* ------------------------------------------------------------- IMPRESSION */

@media print {
  .entete, .menu-plein, .rideau, .hero__scene, .hero__voile, .hero__defile,
  .evitement, .scanner, .form { display: none !important; }
  body { background: #fff; color: #111; }
  .section { padding: 18px 0; }
  a { color: #111; }
  html.js [data-reveal] { opacity: 1 !important; transform: none !important; }
}

/* --------------------------------------------------------- MOUVEMENT REDUIT */

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .001ms !important;
    scroll-behavior: auto !important;
  }
  html.js [data-reveal] { opacity: 1; transform: none; }
}

/* ------------------------------------------------ RETOUR EN HAUT */
/* Le cercle se remplit avec la progression dans la page : le meme
   bouton dit ou on en est et permet d'en revenir. Il passe SOUS le menu
   plein ecran (z-index 60 contre 90) — un bouton flottant par-dessus un
   menu ouvert est une faute qu'on ne voit qu'une fois le menu ouvert. */
.haut {
  position: fixed;
  right: clamp(14px, 2.2vw, 26px);
  bottom: clamp(14px, 2.2vw, 26px);
  z-index: 60;
  width: 48px; height: 48px; padding: 0;
  display: grid; place-items: center;
  border: 0; border-radius: 50%;
  background: conic-gradient(var(--marque) calc(var(--haut-p, 0) * 1%), var(--trait) 0);
  color: var(--texte);
  cursor: pointer;
  opacity: 0; visibility: hidden;
  transform: translateY(12px);
  transition: opacity .35s cubic-bezier(.4, 0, .2, 1),
              transform .45s cubic-bezier(.22, 1, .36, 1),
              visibility .35s;
}
.haut.est-visible { opacity: 1; visibility: visible; transform: none; }

/* Le disque interieur laisse voir l'anneau de progression sur 2 px. */
.haut__fond {
  position: absolute; inset: 2px;
  border-radius: 50%;
  background: var(--nuit);
  transition: background-color var(--t-court);
}
.haut__fleche {
  position: relative;
  width: 20px; height: 20px;
  transition: transform .3s cubic-bezier(.22, 1, .36, 1);
}
/* Bouts francs et angles vifs : c'est le trait du logotype, pas une
   fleche d'interface arrondie. */
.haut__fleche path {
  fill: none; stroke: currentColor; stroke-width: 1.7;
  stroke-linecap: butt; stroke-linejoin: miter;
}
.haut:hover .haut__fond { background: rgba(47, 183, 166, .16); }
.haut:hover .haut__fleche { transform: translateY(-2px); }
.haut:focus-visible { outline: 2px solid var(--marque); outline-offset: 3px; }

[data-theme="light"] .haut:hover .haut__fond { background: rgba(47, 183, 166, .16); }

@media (prefers-reduced-motion: reduce) {
  .haut { transform: none; transition: opacity .2s linear, visibility .2s; }
  .haut:hover .haut__fleche { transform: none; }
}
