/* ==========================================================================
   Système Percer : jetons de design
   14 septembre 2026. Relevé du Figma "goyaze-percer-system" complété.
   Les valeurs marquées PROPOSÉ ne sont pas dans le Figma, elles attendent validation.
   ========================================================================== */

:root {
  /* --- Unités -------------------------------------------------------------
     spacing reste fixe : il pilote les rayons et les bordures, un rayon de
     12 px doit rester à 12 px sur toutes les tailles d'écran.
     type-unit est fluide : il pilote la typographie et le rythme vertical.
     À racine 16 px, type-unit vaut 0,88 px à 1280 et 1,25 px à 1920.       */
  /* Ce qu'un glyphe de titre peut déborder de sa boîte sur les côtés, à
     l'interlettrage serré. Garniture des boîtes qui portent un dégradé
     découpé sur le texte, rendue par une marge négative. 17 septembre 2026. */
  --garniture-glyphe: .12em;

  --spacing: .0625rem;
  --type-unit: clamp(.055rem, .045rem + .078vw, .0781rem); /* PROPOSÉ */

  /* --- Couleurs ----------------------------------------------------------- */
  --violet:        #6647F0;  /* labels et gradient uniquement, jamais du texte courant */
  /* ⚠️ Couleurs du design system du 16 septembre 2026 (da-video), relevées du
     Figma : le noir passe de #202020 à #1C1C1C, le fond de #FAF9F6 à #FAFAFA,
     le gris du texte courant de #6F6F6F au Neutral 600, #646464. */
  --noir:          #1C1C1C;  /* Black, Neutral 700 */
  --gris-texte:    #8F8F8F;  /* PROPOSÉ restreint : 18 px gras ou 24 px minimum, contraste 3,24:1 */
  --gris-lisible:  #646464;  /* Neutral 600 : 5,78:1 sur #FAFAFA, 5,92:1 sur blanc */
  --gris-grille:   #E8E8E8;  /* traits, séparateurs */
  --gris-clair:    #F0F0F0;  /* bouton secondaire, fond de carte */
  --blanc:         #FFFFFF;
  /* Le fond de page, en blanc cassé depuis le 15 septembre 2026. Il ne
     remplace pas --blanc, qui reste la couleur des surfaces : une carte, une
     pilule et un bouton restent en blanc franc, et c'est ce qui les détache du
     fond au lieu de les y fondre.
     ⚠️ Sa valeur est bornée par le contraste. Le gris lisible du texte courant
     donne 5,02 pour 1 sur du blanc ; il faut rester au-dessus de 4,5, et le
     plancher mesuré est aux environs de #F8F8F6. Descendre plus bas demande de
     remesurer, pas de regarder. */
  --fond-page:     #FAFAFA;  /* White, Neutral 50 */

  /* États, PROPOSÉ. Le Figma n'a aucun état en dehors du toggle. */
  --noir-hover:    #383838;
  --noir-actif:    #000000;
  --gris-hover:    #E4E4E4;
  --gris-actif:    #D8D8D8;
  --focus:         var(--violet);
  --erreur:        #C4321C;  /* contraste 5,4:1 sur blanc */

  /* La hiérarchie par l'opacité : une seule encre, quatre niveaux.
     ⚠️ ink-3 et ink-4 ne portent jamais un texte à lire : à 40 %, l'encre
     tombe à 2,5:1 sur le fond, sous le minimum AA. Axes, traits, pistes. */
  --encre: 28 28 28;
  --ink-1: rgb(var(--encre) / 1);
  --ink-2: rgb(var(--encre) / .64);
  --ink-3: rgb(var(--encre) / .40);
  --ink-4: rgb(var(--encre) / .12);

  /* --- Gradients : les trois seuls styles nommés du Figma ------------------ */
  /* ⚠️ L'angle est passé de 129,74 à 50,26 degrés le 15 septembre 2026, sur
     demande : l'extrémité claire était en bas à droite, elle est maintenant en
     haut à droite. C'est le miroir exact du relevé, 180 moins l'angle, donc la
     même inclinaison et les mêmes arrêts, dans l'autre sens vertical.
     ⚠️ Le jeton sert à tous les titres en dégradé, pas au seul H1 du hero. */
  /* Le dégradé de titre du design system : 129,74°, du noir au Neutral 500.
     Posé sur h1, h2 et h3, tous au-dessus de 24 px : l'extrémité claire y tient
     3,13:1 sur #FAFAFA, au-dessus des 3:1 du grand texte. */
  --gradient-titre:  linear-gradient(129.74deg, #1C1C1C 43.855%, #8F8F8F 87.018%);

  /* ⚠️ **Le dégradé du H2 est un jeton à lui depuis le 16 septembre 2026, et il
     l'est pour une raison précise.** Le 15, le H2 est descendu à 40 px et son
     dégradé a été écrit **en littéral** dans la règle, pour que son extrémité
     claire passe AA à cette taille. Le thème Signal, lui, redéfinit
     « --gradient-titre » : la redéfinition ne servait donc plus à rien, et le H2
     de Signal s'est retrouvé en noir sur noir, **1,16 pour 1**. C'est une
     régression introduite le 15 et trouvée le 16.
     **Un littéral dans une règle qu'un thème doit pouvoir reprendre est un
     piège** : ce qui se redéfinit doit être un jeton. */
  --degrade-h2:      var(--gradient-titre);
  --gradient-site:   linear-gradient(90deg, #6647F0 21.844%, #0091FF 80.12%);
  --gradient-signal: linear-gradient(270deg, #FF02F0 3.45%, #F76808 79.757%);

  /* Le dégradé des surfaces sombres, posé le 16 septembre 2026. Une seule
     vérité pour la home et pour la page d’étude. Sa teinte la plus claire,
     #323232, est plafonnée par le contraste : le gris #9A9A9A posé à même le
     fond y tient 4,56 pour 1, et passe sous le minimum AA au-delà. */
  --degrade-fond-sombre: radial-gradient(ellipse 95% 105% at 100% 0%, #323232 0%, #2A2A2A 22%, #1E1E1E 50%, rgb(17 17 17 / 0) 85%);

  /* --- Typographie -------------------------------------------------------- */
  /* ⚠️ **Les familles sont celles de pulsor.agency depuis le 16 septembre
     2026, sur demande.** Relevé sur leur site : PP Mori 600 pour les titres,
     Geist pour le corps, Geist Mono 500 en capitales pour les étiquettes.
     PP Mori est commerciale et n'est pas encore dans le projet : Plus Jakarta
     Sans reste en deuxième position et porte les titres en attendant le fichier
     sous licence. Voir fonts/fonts.css.
     Inter sort de la pile. Ses fichiers restent dans fonts/ et ne sont plus
     demandés : une police déclarée et jamais utilisée ne se télécharge pas. */
  --font-titre: "PP Mori", "Plus Jakarta Sans", system-ui, sans-serif;
  --font-corps: "Geist", system-ui, sans-serif;
  --font-mono:  "Geist Mono", ui-monospace, monospace;

  /* Graisses et réglages relevés sur pulsor.agency.
     Le titre est en 600 chez eux. Plus Jakarta Sans n'a que 400 et 700 : une
     demande de 600 y tombe sur 700, sans graisse synthétique, et prendra le
     vrai 600 le jour où PP Mori arrive. */
  --graisse-titre: 600;
  --ls-titre-grand: -.04em;   /* h1, h2 et h5 chez eux */
  --ls-titre-petit: -.015em;  /* h3, h4 et h6 chez eux */
  --lh-titre-pulsor: 1.1;     /* tous leurs titres */
  --ls-corps: -.015em;        /* -0,24 px sur leur corps de 16 px */

  /* Display. Interlettrage constant à -0,04 em, interligne constant à 1,1.   */
  /* ⛔ **L'échelle typographique est celle de pulsor.agency depuis le
     16 septembre 2026**, par le design system da-video/design-system.md. Tout
     est en multiples d'une unité qui suit la largeur de la fenêtre, comme chez
     eux : 1 em = 16 px sur une fenêtre de 1 440 px. Les paliers sont plus bas.
     Les anciens noms sont gardés et pointent sur les niveaux de Pulsor : les
     règles qui les lisent suivent sans être réécrites. */
  --u: calc(clamp(1080px, 100vw, 1440px) / 90);
  --h1: calc(var(--u) * 4.875);
  --h2: calc(var(--u) * 3.75);
  --h3: calc(var(--u) * 2);
  --h4: calc(var(--u) * 1.5);
  --h5: calc(var(--u) * 1.25);
  --h6: var(--u);
  --text-xxl: calc(var(--u) * 1.5);
  --text-xl:  calc(var(--u) * 1.25);
  --text-l:   calc(var(--u) * 1.125);
  --text-m:   var(--u);
  --text-s:   calc(var(--u) * .875);
  --text-xs:  calc(var(--u) * .75);

  --lh-display: var(--lh-titre-pulsor);
  --ls-display: var(--ls-titre-grand);
  --ls-display-2xl: var(--ls-titre-grand);
  --lh-corps: 1.4;
  --lh-titre: var(--lh-titre-pulsor);

  --display-4xl: var(--h1);   /* chiffres seuls */
  --display-3xl: var(--h1);
  --display-2xl: var(--h1);   /* H1 du hero */
  --titre-lg: var(--h2);      /* H2 */
  --titre-md: var(--h3);      /* H3 */
  --titre-sm: var(--h4);      /* titres de carte */
  --corps-lg: var(--text-xl); /* chapô, sous-titre */
  --corps:    var(--text-m);  /* le corps de base */
  --corps-sm: var(--text-s);
  --legende:  var(--text-s);
  --cta-lg:   var(--text-m);
  --cta-md:   var(--text-m);
  --cta:      var(--text-s);
  --eyebrow:  var(--text-s);

  /* --- Largeurs de mesure, PROPOSÉ ---------------------------------------- */
  --mesure-display: 20ch;
  --mesure-titre:   32ch;
  --mesure-corps:   66ch;
  --mesure-incise:  48ch;

  /* --- Rythme vertical, PROPOSÉ -------------------------------------------
     Trois valeurs seulement. Un rythme à cinq valeurs ne se tient pas.      */
  /* ⚠️ Relevé sur heysimon.fr le 15 septembre 2026, sur demande, et porté ici.
     Leurs valeurs à 1440 px : section 80, blocs 60, 52 et 44 selon les
     endroits, titre et paragraphe 32. À 390 px : section 64, blocs 44, 40 et
     28, titre et paragraphe 32.

     Les multiplicateurs tombent sur leur relevé à 1440 px, puisque l'unité est
     fluide chez nous et fixe chez eux. Ce que ça donne :

       | Rythme  | 1280 | 1440 | 1920 |
       | intra   |  31  |  32  |  34  |
       | bloc    |  58  |  60  |  64  |
       | section |  78  |  80  |  86  |

     ⚠️ Ils sont calculés sur le `--type-unit` **de ce fichier**, pas sur celui
     que CLAUDE.md recopie en section 4 : les deux diffèrent, et c'est une
     divergence connue, à reprendre. Sur la valeur du document, les mêmes
     multiplicateurs donneraient 78 au lieu de 80 à 1440.

     ⚠️ **Le rapport entre section et bloc tombe à 1,33**, quand la section 5.3
     en demande au moins 2,5 et dit que c'est la règle qui compte plus que les
     valeurs. Leur système est bâti à l'envers du nôtre : sections serrées,
     blocs larges. L'arbitrage est ouvert et il est écrit dans CLAUDE.md. */
  --rythme-intra:   calc(var(--type-unit) * 31);   /* titre vers son paragraphe */
  --rythme-bloc:    calc(var(--type-unit) * 58);   /* deux blocs d'une même section */
  /* ⚠️ **Le rythme de section passe de 78 à 112 le 15 septembre 2026, sur
     demande** : 80 px à 1440 devenaient 116. C'est le premier levier du registre
     qu'on vise, avant toute couleur : l'air entre deux idées est ce qui sépare
     une page d'agence d'une page de cabinet.
     ⚠️ **Le rapport section sur bloc remonte de 1,35 à 1,93**, quand la
     section 5.3 en demande 2,5. Ce n'est donc pas encore la règle, mais ça s'en
     approche, et l'arbitrage reste ouvert. */
  --rythme-section: calc(var(--type-unit) * 112);  /* deux sections */

  /* --- Grille, PROPOSÉ ---------------------------------------------------- */
  --colonnes: 12;
  /* Relevé sur heysimon.fr : gouttière de 1em, marge latérale de 20 px sur
     téléphone et 40 au-delà. Les nôtres valaient 24, et 24 puis 48. */
  --gouttiere: calc(var(--spacing) * 16);
  --marge-laterale: calc(var(--spacing) * 20);
  --largeur-max: calc(var(--spacing) * 1280);

  /* --- Rayons -------------------------------------------------------------
     ATTENTION : le relevé du Figma donne xs 4, sm 4 (doublon), xl 15 (qui
     n'est pas un multiple de 4) et 2xl 16 (qui double xl). L'échelle
     ci-dessous corrige ces trois anomalies. Voir design-system.md.         */
  --r-xs:  calc(var(--spacing) * 4);
  --r-sm:  calc(var(--spacing) * 8);
  --r-md:  calc(var(--spacing) * 12);
  --r-lg:  calc(var(--spacing) * 16);
  --r-xl:  calc(var(--spacing) * 24);
  --r-2xl: calc(var(--spacing) * 32);
  --r-3xl: calc(var(--spacing) * 52);
  --r-full: 999px;

  /* --- Mouvement : proposition du vault du 9 septembre, reprise telle quelle */
  --motion-instant: 120ms;
  --motion-quick:   220ms;
  --motion-slow:    450ms;
  --ease-out:   cubic-bezier(.16, 1, .3, 1);
  --ease-inout: cubic-bezier(.65, 0, .35, 1);
  --stagger: 60ms;

  /* --- Mouvement du design system (da-video), 16 septembre 2026 ----------
     ⛔ Pulsor (texte) et Gemeos (éléments) sont revenus le même soir, sur
     demande : ces jetons ne servent plus aux apparitions. Deux courbes, ease-out et ease-inout, déjà ci-dessus. Cinq
     durées. Six gestes : montée masquée, mise au point, tracé, compteur,
     glissement, bascule. Aucun rebond, aucune rotation, aucun texte brouillé. */
  --t-micro:  200ms;   /* changement d'état */
  --t-base:   400ms;   /* carte, icône, label */
  --t-texte:  800ms;   /* révélation d'un titre */
  --t-trace:  1200ms;  /* tracé, compteur, bascule */
  --t-scene:  1600ms;  /* transition de plan */
  --pas-mot: 60ms;
  --pas-element: 120ms;
  --pas-lettre: 30ms;
  --montee: 100%;      /* montée masquée */
  --flou-point: 12px;  /* mise au point */
  --glissement: 40px;  /* glissement */

  /* ⛔ **Les animations de texte sont celles de pulsor.agency**, rétablies le
     16 septembre 2026 au soir, sur demande : « toutes les animations de textes,
     mets celles de Pulsor ». Les gestes ci-dessus restent pour les éléments. */
  /* Pulsor, courbes déclarées (:root et CustomEase.create) */
  --pulsor-smooth:  cubic-bezier(.66, .01, .17, .97);   /* « smooth-ease », défaut de tout GSAP chez eux */
  --pulsor-elastic: cubic-bezier(.34, 1.35, .64, 1);    /* « elastic-ease », dépassement léger */
  --pulsor-opacity: cubic-bezier(.4, 0, .2, 1);         /* « opacity-ease », fondus de fond */
  /* Pulsor, courbes GSAP nommées, traduites */
  --pulsor-expo-out:    cubic-bezier(.19, 1, .22, 1);   /* expo.out : sous-titres, étiquettes, en-tête */
  --pulsor-expo-inout:  cubic-bezier(.87, 0, .13, 1);   /* expo.inOut : rideaux du préchargement */
  --pulsor-power4-inout: cubic-bezier(.83, 0, .17, 1);  /* power4.inOut (quintique chez GSAP) : texte brouillé */
  --pulsor-power2-out:  cubic-bezier(.33, 1, .68, 1);   /* power2.out (cubique chez GSAP) : hauteur des listes */
  /* Pulsor, durées (objet durations du script et variables CSS) */
  --pulsor-xs:  300ms;
  --pulsor-s:   450ms;
  --pulsor-m:   600ms;
  --pulsor-l:   800ms;
  --pulsor-xl:  1000ms;   /* 1 s dans le script ; leur variable CSS dit 2 s, le script gagne */
  --pulsor-xxl: 1200ms;
  --pulsor-stagger: 75ms;

  /* Pulsor, les animations de texte. Relevées une seconde fois le
     16 septembre 2026 au soir sur leur script (slater 17824/50442.js) et leur
     feuille, sur demande : « toutes les animations de textes, mêmes courbes ».
     Là où le premier relevé s'écartait du script, c'est le script qui gagne. */
  --texte-flou: 10px;                 /* flou de départ, titres, sous-titres, étiquettes */

  /* La chronologie du chargement. ⚠️ **Pulsor en a deux** : celle du premier
     chargement, qui passe par leur préchargement (initPreloaderAnimation), et
     celle des changements de page (runPageEnterAnimation). **C'est la
     première que voit un visiteur**, et c'est elle qui est reprise pour le
     texte : titre mot par mot à E, sous-titre et étiquette à E + 0,4 s, en
     1,2 s expo.out et 50 ms. La home n'ayant pas de préchargement, l'en-tête
     et E sont ceux de runPageOnceAnimation : 0,25 s et 0,65 s. */
  --entete-montee: -125%;             /* yPercent -125, expo.out, 1 s */
  --entete-retard: 250ms;
  --titre-charge-retard: 650ms;       /* E : 0,25 + 0,3 + 0,1 */
  --suite-retard: 400ms;              /* E + 0,4 */

  --titre-mots-montee: 20%;           /* data-load-heading : yPercent 20, mot par mot */
  --titre-mots-duree: var(--pulsor-xl);
  --titre-mots-courbe: var(--pulsor-smooth);
  --titre-mots-pas: var(--pulsor-stagger);
  /* data-load-sub et data-load-tag, au premier chargement : 1,2 s, expo.out,
     50 ms. (Aux changements de page, c'est 1 s en smooth-ease et 75 ms.) */
  --sous-titre-montee: 60%;
  --sous-titre-duree: var(--pulsor-xxl);
  --sous-titre-courbe: var(--pulsor-expo-out);
  --sous-titre-pas: 50ms;
  --fondu-montee: 2em;                /* data-load-fade : y 2em, 1,2 s expo.out */

  --lignes-montee: 110%;              /* data-reveal : lignes masquées, H2 et chapôs */
  --lignes-duree: var(--pulsor-l);
  --lignes-courbe: var(--pulsor-smooth);
  --lignes-pas: var(--pulsor-stagger);
  --lignes-seuil: 10%;                /* start « clamp(top 90%) » */

  /* La frappe des H2 et des H3, 17 septembre 2026, sur demande : lettre par
     lettre, en sortant du flou, comme l'ouverture de la méthode. Le pas vaut
     min(--pas-lettre, budget / nombre de lettres) : un long titre ne met pas
     plus longtemps à s'écrire que le budget. */
  --frappe-duree: 450ms;
  --frappe-courbe: var(--ease-out);
  --frappe-budget: 1400ms;

  --lettres-pas: 10ms;                /* data-stagger-char : boutons et liens de navigation */
  --lettres-duree: var(--pulsor-s);
  --lettres-courbe: var(--pulsor-smooth);
  --lettres-saut: 1.3em;

  --brouille-pas: 50ms;               /* data-scramble, par caractère, power4.inOut */
  --brouille-faux: 80ms;
  --brouille-sortie: 160ms;
  --brouille-revele: 300ms;
  --brouille-seuil: 15%;              /* start « top 85% » */

  --menu-montee: -1em;                /* data-menu-reveal : liens du menu déplié */
  --menu-pas: 40ms;                   /* --stagger-default */
  --menu-retard: 250ms;               /* --reveal-delay */
  --menu-duree: var(--pulsor-s);


  /* Sans emploi sur la home : les mots qui tournent (data-cycle), faute de
     texte qui tourne. Gardés pour que le relevé soit complet. */
  --cycle-montee: 50%;
  --cycle-duree: var(--pulsor-m);
  --cycle-pas-entree: 45ms;
  --cycle-pas-sortie: 20ms;

  /* ⛔ **Gemeos pour les éléments**, rétabli le 16 septembre 2026 au soir, sur
     demande (« les icônes arrivent en roulant »). Revérifié sur
     gemeosagency.com : hand-move, sticker-move et rocket-move dans leurs
     feuilles inline, popcorn, panneaux et dépliés dans @gemeosagency/gemeos-v2. */
  --gemeos-out-quint:   cubic-bezier(.22, 1, .36, 1);        /* entrées des autocollants du hero */
  --gemeos-out-cubic:   cubic-bezier(.215, .61, .355, 1);    /* panneaux, menus, dépliés : la courbe par défaut */
  --gemeos-out-back:    cubic-bezier(.175, .885, .32, 1.275); /* hand-move, apparitions à l'échelle */
  --gemeos-popcorn:     cubic-bezier(.34, 1.56, .64, 1);     /* lettres qui éclatent */
  --gemeos-inout-cubic: cubic-bezier(.645, .045, .355, 1);
  --gemeos-inout-quart: cubic-bezier(.77, 0, .175, 1);
  --gemeos-inout-back:  cubic-bezier(.68, -.55, .265, 1.55);
  --gemeos-out-circ:    cubic-bezier(.075, .82, .165, 1);

  --monte-distance: 120%;            /* sticker-move : translate(0, 120%) */
  --monte-duree: 1100ms;
  --monte-courbe: var(--gemeos-out-quint);
  --monte-pas: 200ms;                /* 200, 400, 600 ms */
  --diagonale-x: -120%;              /* rocket-move : translate(-120%, 140%) */
  --diagonale-y: 140%;
  --glisse-x: 120%;                  /* hand-move : translate(120%) puis rotate(-360deg) */
  --glisse-duree: 600ms;
  --glisse-courbe: var(--gemeos-out-back);
  --glisse-retard: 400ms;
  --popcorn-montee: 30px;            /* popcorn-in : translateY(30px) scale(0) */
  --popcorn-duree: 400ms;
  --popcorn-courbe: var(--gemeos-popcorn);
  --popcorn-budget: 600ms;           /* pas = min(40 ms, 600 / nombre de lettres), ordre tiré */
  --panneau-distance: 150%;          /* tabs3-pane-in / out : translateX(±150%) */
  --panneau-duree: 1100ms;
  --panneau-courbe: var(--gemeos-out-cubic);
  --panneau-contenu-duree: 400ms;
  --panneau-contenu-retard: 600ms;
  --panneau-sortie-duree: 200ms;
  --deplie-duree: 600ms;             /* faq : grid-template-rows */
  --deplie-courbe: var(--gemeos-out-cubic);

  --compte-decalage: -1rem;           /* data-count : translate(-1rem, -1rem) */
  --compte-flou: 8px;
  --compte-pas: 35ms;

  /* --- Le prix, source unique --------------------------------------------
     En attente de validation ferme. Un changement de prix se fait ici.      */
  --prix-mensuel: "1 500 €";
  --prix-total: "18 000 €";
}

/* ==========================================================================
   Thème Signal : le seul moment sombre du site. PROPOSÉ, le Figma ne le pose pas.
   S'applique en portée locale sur la section Signal, jamais sur la page entière.
   ========================================================================== */
[data-theme="signal"] {
  --fond:            #111111;
  --surface:         #1A1A1A;
  --surface-haute:   #222222;
  --bordure:         #2E2E2E;
  --texte:           #F5F5F5;   /* contraste 17,4:1 */
  --texte-secondaire:#9A9A9A;   /* contraste 6,7:1 */
  /* DA Signal : titres en blanc vers gris, l'accent chaud reste à l'accent. */
  --gradient-titre:  linear-gradient(129.74deg, #FFFFFF 43.855%, #8F8F8F 87.018%);
  --encre: 255 255 255;
  /* Le H2 reprend le gradient chaud du thème. Ses deux extrémités tiennent
     5,86 et 6,24 pour 1 sur le fond du thème, là où le dégradé clair du site
     tombe à 1,16. */
  --degrade-h2:      var(--gradient-titre);
  --accent:          #FF02F0;
}

/* ==========================================================================
   Bases
   ========================================================================== */

html { color-scheme: light; }

body {
  background: var(--fond-page);
  color: var(--noir);
  font-family: var(--font-corps);
  font-size: var(--corps);
  line-height: var(--lh-corps);
  letter-spacing: var(--ls-corps);
  -webkit-font-smoothing: antialiased;
}

h1, h2, h3 {
  font-family: var(--font-titre);
  font-weight: var(--graisse-titre);
  text-wrap: balance;
}

h1 {
  font-size: var(--display-3xl);
  line-height: var(--lh-display);
  letter-spacing: var(--ls-display);
  max-width: var(--mesure-display);
}

/* ⚠️ **Tous les H2 portent le dégradé de titre depuis le 15 septembre 2026.**
   Ce n'est pas une décoration de section : la section 2 dit que le dégradé noir
   vers gris est réservé aux titres, et la 7.05 le demandait déjà sur les H2. Il
   est donc posé sur le niveau, pas sur une classe, pour qu'un H2 ne puisse plus
   l'oublier.

   ⚠️ **Trois pièges viennent avec, et les trois sont muets.**

   1. **La boîte du dégradé n'est pas le texte.** Un titre en drapeau laisse du
      vide à droite de sa mesure, et l'extrémité claire du dégradé y tombe : le
      titre paraît alors uniformément sombre. La largeur au contenu fait coller
      la boîte à la ligne la plus longue, et les deux extrémités retombent sur
      du texte. C'est la version CSS de ce que le H1 fait en JS, où la découpe
      en mots interdit de s'en remettre à la boîte.
   2. **Les jambages sortent de la boîte peinte.** À l'interligne du display,
      la ligne est plus courte que les glyphes : le g et le p dépassent, et rien
      ne se peint sous ce qui dépasse. La garniture verticale agrandit la boîte
      peinte, la marge négative de même valeur rend les pixels à la mise en
      page, et l'interligne relevé du Figma ne bouge pas.
   3. **L'extrémité claire du dégradé de titre ne passe AA qu'à 60 px.** Le H2
      n'y est plus, donc **il ne prend pas le dégradé du système, il prend le
      sien** : même angle, mêmes arrêts, et l'extrémité claire au gris lisible,
      qui tient 5,02 pour 1 sur blanc et **4,77 sur le blanc cassé de la page**,
      à toutes les tailles, quand celle du système vaut 3,24. Aucune valeur neuve
      n'entre, c'est un jeton existant. Le H1, lui, garde le dégradé du système,
      il est encore à 61,6 px. */

/* ⚠️ **Le H2 descend au niveau « titre-lg » le 15 septembre 2026, sur demande,
   et c'est l'arbitrage de la section 5.2 qui se referme.** Le H1 du hero et le
   H2 de section avaient le même corps depuis que le H1 est passé en
   « display-2xl » pour tenir sur deux lignes, et la hiérarchie n'y tenait plus
   que par la place et par le dégradé.

   **Des trois sorties écrites, c'est la seule qui ne casse rien d'autre.**
   Remonter le H1 lui ferait reprendre une troisième ligne, ce que le calcul de
   la section 7.01 interdit ; ouvrir un quatrième niveau display ajouterait une
   valeur au système. Le H2 descend donc d'un cran sur l'échelle existante, et
   le rapport passe de 1 à **1,5**.

   **Les trois valeurs sont celles du niveau « titre-lg »**, prises ensemble : 40
   px, interligne 1,15, interlettrage -0,02 em. C'est la règle du système, une
   taille qui descend desserre son interlettrage et ouvre son interligne.

   La garniture reste à .26em : elle couvrait les jambages à l'interligne du
   display, elle les couvre largement à 1,15, où ils ne dépassent plus que de
   .055em. */
h2 {
  font-size: var(--titre-lg);
  line-height: var(--lh-titre);
  letter-spacing: var(--ls-titre-grand);
  max-width: var(--mesure-titre);
  width: fit-content;
  padding-block: .26em;
  margin-block: -.26em;
  background-image: var(--degrade-h2);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}

h3 {
  font-size: var(--titre-md);
  line-height: var(--lh-titre);
  letter-spacing: var(--ls-titre-petit);
}

p { max-width: var(--mesure-corps); }

/* Le gradient noir vers gris est réservé aux titres.
   Il ne s'applique qu'à partir de 60 px : son extrémité claire tombe à
   3,24:1 de contraste, ce qui ne passe AA qu'en grande taille.            */
.titre-gradient {
  background: var(--gradient-titre);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}

/* Le violet ne sert qu'ici. */
.label {
  font-family: var(--font-mono);
  font-size: var(--eyebrow);
  font-weight: 500;
  letter-spacing: var(--ls-corps);
  color: var(--violet);
  text-transform: uppercase;
  font-variant-numeric: tabular-nums;
}

/* Focus : jamais supprimé, jamais remplacé par un outline nul. */
:focus-visible {
  outline: 2px solid var(--focus);
  outline-offset: 2px;
  border-radius: var(--r-xs);
}

/* Chiffres tabulaires partout où un chiffre est un objet de lecture. */
.chiffre {
  font-variant-numeric: tabular-nums;
  font-feature-settings: "tnum" 1;
}

/* ==========================================================================
   Mouvement
   L'animation est un argument dans la section Signal, un ornement partout
   ailleurs. Aucune apparition au défilement sur le reste de la page.
   ========================================================================== */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .01ms !important;
    scroll-behavior: auto !important;
  }
}

/* ==========================================================================
   Grille
   ========================================================================== */
.conteneur {
  width: 100%;
  max-width: var(--largeur-max);
  margin-inline: auto;
  padding-inline: var(--marge-laterale);
}

.section { padding-block: var(--rythme-section); }

/* Les paliers de Pulsor : maquette de 834 px sous 992, 550 sous 768, 390 sous 480. */
@media (max-width: 991px) {
  :root { --u: calc(clamp(768px, 100vw, 991px) / 52.125); }
}
@media (max-width: 767px) {
  :root {
    --u: calc(clamp(480px, 100vw, 767px) / 34.375);
    --h1: calc(var(--u) * 2.5);
    --h2: calc(var(--u) * 2);
    --h3: calc(var(--u) * 1.5);
    --h4: calc(var(--u) * 1.25);
    --h5: calc(var(--u) * 1.125);
  }
}
@media (max-width: 479px) {
  :root { --u: calc(clamp(320px, 100vw, 479px) / 24.375); }
}

@media (min-width: 1024px) {
  :root { --marge-laterale: calc(var(--spacing) * 40); }
}

/* ⚠️ **Le retrait mobile du dégradé des H2 est sorti le 15 septembre 2026**, et
   c'est une conséquence du changement de corps ci-dessus. Il existait parce que
   l'extrémité claire du dégradé du système vaut 3,24 pour 1 et exige 60 px :
   sous 768, le H2 y tombait. Le H2 porte maintenant son propre dégradé, dont
   l'extrémité claire tient 5,02 pour 1 **à toutes les tailles**. Le motif du
   retrait a donc disparu avec la couleur, et le dégradé descend jusqu'au
   téléphone. */

@media (max-width: 767px) {
  :root {
    /* Leur relevé à 390 px : section 64, bloc 44. Sous 1280 l'unité est à son
       plancher, les multiplicateurs y valent donc des pixels à un centième. */
    --rythme-section: calc(var(--type-unit) * 92);
    --rythme-bloc: calc(var(--type-unit) * 50);
  }
}
