/* ==========================================================================
   SKYNET — GRAMMAIRE DES BLOCS  (socle visuel de la direction artistique)
   Créé le 12/08/2026. Source : docs/design-concurrents-20260812/AAA-direction-artistique.md

   CE QUE FAIT CETTE FEUILLE, ET RIEN D'AUTRE :
     1. la police des ÉTIQUETTES (JetBrains Mono, décision 1 validée par Yann) ;
     2. la classe `.etiquette` qui fabrique l'autorité technique ;
     3. la traduction en CSS des règles d'enchaînement 4, 5 et 7 ;
     4. un MODE DIAGNOSTIC qui rend les fautes de grammaire VISIBLES à l'écran.

   ⚠️ ELLE SE CHARGE EN DERNIER, APRÈS skynet.css, -design, -nuit et -clair.
      Elle AJOUTE, elle ne casse rien : toutes ses règles sont portées par des
      classes NEUVES (`.bloc`, `.etiquette`, `.fond-*`, `.bloc-sombre`,
      `.degrade-plein`, `.mesure`). Vérifié le 12/08 : aucun de ces noms
      n'existait dans les 46 pages ni dans les 5 feuilles.
      → Une page qui n'emploie aucune de ces classes est rendue À L'IDENTIQUE.
      Preuve : 150 valeurs calculées (15 propriétés × 10 éléments) relevées sur
      index.html avant et après ajout de cette feuille — 0 écart, et la même
      hauteur de page au pixel (9 849 px).

   🪤 ET LA LEÇON D'INSTRUMENT QUI VA AVEC, PARCE QU'ELLE A FAILLI ME FAIRE
      ANNONCER UNE FAUSSE RÉGRESSION. Ma première sonde mesurait AVANT que les
      polices soient chargées. Or `.hero-xl .display` porte `max-width:13ch`, et
      le `ch` vaut la largeur du chiffre « 0 » de la police RÉELLEMENT en place :
      0,5871 em avec le repli (Arial × size-adjust 105,6 %) contre 0,6570 em
      avec Poppins 800 — soit 476 px contre 533 px pour le même code.
      Deux mesures de la MÊME page peuvent donc différer sans qu'une ligne ait
      bougé. La sonde attend désormais `document.fonts.ready`.
      → Toute mesure de mise en page sur ce site se fait POLICES CHARGÉES.

   ⛔ AUCUNE VALEUR HEXADÉCIMALE DANS UNE DÉCLARATION DE CETTE FEUILLE (vérifié :
      0 hex hors commentaire). C'est la règle qui ferme la palette (direction
      artistique, § « La palette SkyNet ») : les 5 audits ont tous le même
      défaut, un hex en dur dans une feuille de composant. Toutes les couleurs
      ci-dessous sont des jetons déjà déclarés ailleurs. Les quelques hex
      présents dans les COMMENTAIRES citent les valeurs des concurrents ou un
      contraste de référence : ils ne sont jamais appliqués.
   ========================================================================== */


/* ==========================================================================
   1. LA POLICE DES ÉTIQUETTES — JetBrains Mono SemiBold, sous-ensemble maison
   ==========================================================================
   POURQUOI ELLE EXISTE : c'est le seul geste du trio typographique d'Aircall
   qui nous manquait. Une police à chasse fixe (toutes les lettres ont la même
   largeur, comme sur l'écran d'un développeur) employée UNIQUEMENT en
   majuscules pour les étiquettes techniques. Elle dit « nous sommes des
   techniciens » sans qu'aucune phrase n'ait à le prétendre.

   LICENCE — VÉRIFIÉE LE 12/08, PAS SUPPOSÉE. La direction artistique la
   signalait honnêtement comme INCERTAINE (« je ne l'ai PAS lue dans le fichier
   de licence »). Je l'ai téléchargée et lue :
     · SIL Open Font License 1.1 — usage commercial et MODIFICATION autorisés ;
     · AUCUN « Reserved Font Name » n'est déclaré par le projet JetBrains Mono,
       donc le sous-ensemble peut conserver le nom d'origine (clause 3) ;
     · clause 2 : la licence doit accompagner le fichier. Elle est présente
       DEUX fois — dans assets/fonts/jetbrains-mono-OFL.txt, et dans les
       métadonnées internes du .woff2 (name ID 13 + 14), ce que l'OFL accepte
       explicitement comme « machine-readable metadata field ».

   POIDS — MESURÉ, PAS ESTIMÉ : 6 564 octets (6,4 Ko).
     [VALEUR] 6 564 octets
     [COMMANDE] python -m fontTools.subset JetBrainsMono-SemiBold.ttf
                --unicodes=<190 caractères> --flavor=woff2 --layout-features=
                --no-hinting --desubroutinize
     [PÉRIMÈTRE] le seul fichier assets/fonts/jetbrains-mono-600-latin.woff2
   Le sous-ensemble « latin » servi par Google pèse 21 860 octets : on divise
   par 3,3 en ne gardant que ce dont une étiquette a besoin.

   ⚠️ POURQUOI LES MINUSCULES SONT DEDANS alors que les étiquettes sont en
   majuscules (coût : 1 624 octets de plus que la variante capitales seules,
   4 940 octets). Parce que `unicode-range` filtre par CARACTÈRE : un caractère
   absent du sous-ensemble ne casse rien, il retombe SILENCIEUSEMENT sur la
   police suivante — et on obtient deux dessins de lettres DANS LE MÊME MOT.
   C'est exactement le « faux vert » déjà décrit pour le polonais de Poppins
   dans skynet-i18n.css. 1,6 Ko est un prix dérisoire pour supprimer une classe
   entière de bug silencieux. Les capitales accentuées d'Europe centrale
   (Ł Ż Ą Ę Ś Ć Ń Ź Č Š Ž Ő Ű Ș Ț) sont incluses pour la même raison.

   ⚠️ LIGATURES DE CODE NEUTRALISÉES. JetBrains Mono est une police de
   PROGRAMMATION : elle transforme `->` en flèche et `==` en signe composé.
   Dans une étiquette ce serait un désastre. Elles sont retirées à DEUX
   niveaux — toutes les fonctions OpenType sont absentes du fichier
   (`--layout-features=`, vérifié : 0 fonction GSUB restante), ET désactivées
   en CSS ci-dessous. Ceinture et bretelles : une police est un fichier qu'on
   peut remplacer, une règle CSS reste.                                       */

@font-face{
  font-family:"JetBrains Mono";
  font-style:normal;
  font-weight:600;
  font-display:swap;
  src:url(fonts/jetbrains-mono-600-latin.woff2) format("woff2");
  /* Déclaré au caractère près : ce qui n'est pas dans le fichier n'est pas
     dans la plage, donc le navigateur ne demande jamais un glyphe absent. */
  unicode-range:U+0020-005B,U+005D,U+005F,U+0061-007E,U+00A0,U+00AB,U+00B0,U+00B7,U+00BB,U+00C0-00CF,U+00D1-00DD,U+00DF-00EF,U+00F1-00F6,U+00F8-00FD,U+0102,U+0104,U+0106,U+010C,U+010E,U+0110,U+0118,U+011A,U+0141,U+0143,U+0147,U+0150,U+0152,U+0158,U+015A,U+0160,U+0164,U+016E,U+0170,U+0178-0179,U+017B,U+017D,U+0218,U+021A,U+2013-2014,U+2018-2019,U+201C-201D,U+2026,U+20AC,U+2192;
}

:root{
  /* ⚠️ JETON NEUF, VOLONTAIREMENT SÉPARÉ DE `--police-mono`.
     `--police-mono` (skynet.css:114) est déjà employée par `.kicker,.sur-titre`
     (skynet-clair.css:514) sur 486 éléments répartis sur les 46 pages — mesuré
     le 12/08 : `grep -oh 'class="[^"]*\bkicker\b[^"]*"' *.html | wc -l` → 486.
     Y ajouter JetBrains Mono changerait l'apparence des 46 pages d'un coup.
     Ce n'est PAS ma décision et ce n'est pas mon fichier : je la signale à
     Claudia, elle tranche. En attendant, les deux jetons coexistent sans se
     gêner et `--police-mono` continue de retomber sur la pile système. */
  --police-etiquette:"JetBrains Mono",ui-monospace,SFMono-Regular,Menlo,Consolas,"Liberation Mono",monospace;

  /* Règle 7 : la hauteur maximale d'un bloc à 1440 px de large. */
  --bloc-hauteur-max:900px;

  /* Le blanc entre deux sections. 96 px est la médiane d'Aircall, et tout y
     est en multiples de 8 sans exception. Calculé pour valoir exactement
     96 px à 1440 px et 48 px à 390 px.
     ⚠️ ESPACES AUTOUR DU `+` — sans eux le clamp() est INVALIDE et jeté en
     silence par le navigateur. Piège tombé sur ce projet le 03/08 : le H1
     affichait 34 px au lieu de 83. */
  --bloc-respiration:clamp(3rem, 1.886rem + 4.571vw, 6rem);
}


/* ==========================================================================
   2. LA CLASSE `.etiquette` — celle qui fabrique l'autorité technique
   ==========================================================================
   EMPLOI : CENTREX · LIEN SECOURU · FTTO · GTR 4 H · OPÉRATEUR DÉCLARÉ ARCEP.
   Le vocabulaire d'opérateur qu'un éditeur de logiciel sans réseau ne PEUT pas
   prononcer (0 occurrence de Centrex, SIP, FTTO, GTR et QoS sur les 30 pages
   d'Aircall). C'est la preuve du métier, pas du jargon à cacher.

   ⛔ ELLE NE SERT À RIEN D'AUTRE. Ni un titre, ni un bouton, ni un paragraphe.
      Une police d'étiquette employée ailleurs cesse d'être une signature.

   ⚠️ LA CASSE EST FAITE PAR LE CSS, PAS PAR LE TEXTE SOURCE — et c'est capital
   sur ce projet : le corpus de traduction indexe chaque phrase FRANÇAISE à
   l'octet près. On écrit donc `<span class="etiquette">Opérateur déclaré
   auprès de l'ARCEP</span>` en casse normale, et `text-transform` l'affiche en
   majuscules. Écrire les majuscules en dur dans le HTML perdrait la traduction
   dans les 11 autres langues, EN SILENCE.                                     */

.etiquette{
  font-family:var(--police-etiquette);
  font-weight:600;
  font-size:var(--t-xs);          /* 12 px — l'échelle de la direction artistique  */
  line-height:1.25;
  letter-spacing:.08em;      /* approche positive : une capitale a besoin d'air */
  text-transform:uppercase;
  color:var(--texte-doux);   /* 5,88:1 sur blanc · 5,54:1 sur papier          */
  display:inline-block;
  /* Neutralise les ligatures de programmation (`->`, `==`, `!=`) au cas où le
     fichier de police serait un jour remplacé par une version non sous-ensemblée. */
  font-variant-ligatures:none;
  font-feature-settings:"liga" 0,"calt" 0;
  /* Les chiffres d'une étiquette s'alignent en colonne (GTR 4 H, 99,9 %). */
  font-variant-numeric:tabular-nums;
}

/* L'étiquette qui porte l'action ou le mot-clé passe en indigo — 10,66:1.
   ⛔ Jamais le cyan sur fond clair : 2,62:1, il ne porte JAMAIS de texte. */
.etiquette-marque{color:var(--indigo-500)}

/* Sur le bloc sombre, c'est le cyan qui allume — 6,95:1 sur l'encre, vérifié.
   C'est la loi : l'indigo vit sur le clair, le cyan vit sur le sombre. */
.bloc-sombre .etiquette,.etiquette-lumiere{color:var(--cyan-500)}

/* Le filet de 6 px sous un sur-titre : un des cinq emplois autorisés de
   l'indigo. Optionnel, porté par une classe pour rester rare. */
.etiquette-filet{padding-bottom:.5rem;border-bottom:6px solid var(--indigo-500)}

/* ── UNE RANGÉE D'ÉTIQUETTES ──────────────────────────────────────────────
   🐞 DÉFAUT TROUVÉ EN REGARDANT LA PAGE, PAS EN LA CODANT. Au premier rendu,
   « CENTREX · LIEN SECOURU · FTTO · GTR 4 H » posés côte à côte se lisaient
   comme UNE SEULE longue étiquette : l'approche de +0,08em écarte les lettres
   autant que l'espace des mots, donc la frontière entre deux étiquettes
   disparaît. À l'écran on lisait « CENTREXLIENSECOURUFTTOGTR4H ».
   C'est exactement ce que la capture attrape et que le code ne dit pas.
   ⛔ Une rangée d'étiquettes emploie donc TOUJOURS ce conteneur.             */
.etiquettes{
  display:flex;flex-wrap:wrap;align-items:center;
  gap:.5rem 1.25rem;          /* l'écart entre deux étiquettes doit être plus
                                 grand que l'écart entre deux mots de la même */
  list-style:none;padding:0;margin:0;
}
/* La variante à points médians, celle de la direction artistique :
   CENTREX · LIEN SECOURU · FTTO.
   ⚠️ CORRECTION D'UNE PHRASE FAUSSE QUE J'AVAIS D'ABORD ÉCRITE ICI : j'avais
   noté que le contenu généré « n'est pas lu par les lecteurs d'écran ». C'EST
   INEXACT — Chrome et Firefox exposent le contenu des ::before à l'arbre
   d'accessibilité, et NVDA comme VoiceOver peuvent l'annoncer. Ce qui reste
   vrai, et qui suffit ici : le séparateur est UN SIGNE DE PONCTUATION isolé,
   que les lecteurs d'écran traitent selon leur réglage de ponctuation (le plus
   souvent une pause). Le gain réel est ailleurs : le point n'est pas dans le
   HTML, donc il n'entre PAS dans le corpus de traduction et ne peut pas être
   traduit par erreur dans les 11 autres langues.
   ⛔ ET C'EST LA RAISON POUR LAQUELLE AUCUN MOT ne sera jamais mis en `content`
      dans une page publique : seuls les libellés du mode diagnostic ci-dessous
      en emploient, et ce mode ne part jamais en production.                   */
.etiquettes-points{gap:.5rem .75rem}
.etiquettes-points > * + *::before{
  content:"·";
  margin-inline-end:.75rem;
  color:var(--ligne-forte);
}

/* ── LES 11 AUTRES LANGUES ────────────────────────────────────────────────
   Même raisonnement que skynet-i18n.css, appliqué à `.etiquette` :
   · l'arabe est CURSIF — l'approche de +0,08em insère des blancs DANS les mots
     et disloque l'écriture ;
   · l'arabe et le CJK n'ont PAS de majuscules : `text-transform` n'y fait rien
     et la police latine n'a aucun glyphe pour eux, donc on rend la main à la
     police de la langue au lieu de laisser une pile monospace décider.
   Écrit avec :lang() : aucune page latine n'est touchée.                      */
:lang(ar) .etiquette,:lang(ja) .etiquette,
:lang(ko) .etiquette,:lang(zh) .etiquette{
  font-family:var(--police);
  letter-spacing:0;
  text-transform:none;
}


/* ==========================================================================
   3. LE BLOC — le rythme vertical, et le budget de hauteur (RÈGLE 7)
   ==========================================================================
   RÈGLE 7 : aucun bloc ne dépasse 900 px de haut à 1440 px de large.
   Mesure de départ : 89 sections sur 407 (22 %) dépassent 1 000 px.

   ⚠️ HONNÊTETÉ TECHNIQUE — CE QUE LE CSS PEUT ET NE PEUT PAS FAIRE.
   Le CSS ne sait pas dire « si ce bloc dépasse 900 px, refuse-le » : il n'a
   aucun sélecteur conditionnel sur la hauteur. Poser `max-height:900px`
   COUPERAIT le contenu — le remède serait pire que le mal.
   Cette feuille fait donc les deux seules choses honnêtes :
     (a) elle donne le RYTHME qui permet de tenir 900 px (respiration calée sur
         96 px au lieu des 119 px de `.section`) ;
     (b) elle rend le dépassement VISIBLE au navigateur (§ 5, mode diagnostic).
   Le contrôle final reste une MESURE dans Chrome, pas une règle de style.     */

.bloc{
  position:relative;
  padding-block:var(--bloc-respiration);
}

/* Un bloc qui n'a qu'une phrase à dire ne prend pas la respiration d'un bloc
   qui argumente. C'est ce qui évite le « tout se ressemble » vertical. */
.bloc-court{padding-block:calc(var(--bloc-respiration) * .6)}

/* ⛔ Le HERO et le CTA sont les deux seuls blocs autorisés à respirer plus
   large : l'un ouvre la page, l'autre la referme. */
.bloc-ample{padding-block:calc(var(--bloc-respiration) * 1.25)}

/* La largeur de ligne. Le seuil de confort est 75 caractères ; les quatre
   concurrents sont à 170, 144, 107 et 90.
   ⚠️ VOLONTAIREMENT OPT-IN (`.mesure`) ET NON APPLIQUÉ À `p, li` GLOBALEMENT.
   La direction artistique appelle `p, li { max-width: 64ch }` « le meilleur
   rapport effort/avance de tout le dossier », et c'est vrai — mais posé
   globalement il CHANGERAIT l'apparence des 46 pages existantes, ce que ma
   mission m'interdit explicitement. La règle est donc écrite, prête, et son
   application globale appartient à Claudia. Signalé dans mon rapport.        */
.mesure{max-width:64ch}
.mesure-centre{max-width:64ch;margin-inline:auto}
/* Dans un corps d'article la colonne est unique et alignée à gauche : la
   mesure y est automatique, sans risque de décentrer quoi que ce soit. */
.bloc-corps :is(p,li,h2,h3){max-width:64ch}


/* ==========================================================================
   4. LES FONDS — l'alternance blanc / papier (RÈGLE 3)
   ==========================================================================
   RÈGLE 3 : jamais deux fonds identiques consécutifs. blanc -> papier -> blanc.
   ⛔ IL N'Y A QUE TROIS FONDS, ET IL N'Y EN AURA JAMAIS UN QUATRIÈME.
      Netcom a QUATRE blancs cassés pour le même rôle (#F9FAFB #F8FAFC #F3F4F6
      #F8FCFC) : son alternance est écrite dans le code et ne se voit pas à
      l'écran. Une alternance qu'on ne voit pas ne sert à rien.                */

.fond-blanc{background-color:var(--blanc)}
.fond-papier{background-color:var(--papier)}

/* ── LE BLOC SOMBRE (RÈGLE 4) ─────────────────────────────────────────────
   Un seul par page, ni premier ni dernier, entre 60 % et 72 % de la
   profondeur. C'est la loi commune d'Aircall (49-71 %), d'unyc et de Netcom :
   ils ne font pas alterner clair/foncé à chaque section, ils gardent UNE
   cartouche et la tirent au bon moment.
   Chez nous il porte ce que les concurrents ne peuvent pas dire :
   l'infrastructure, la supervision, le lien secouru, l'identifiant ARCEP.    */
.bloc-sombre{
  background-color:var(--encre);
  color:var(--blanc);
}
.bloc-sombre :is(h1,h2,h3,h4,p,li){color:inherit}
/* Le mot-clé du titre en cyan : 6,95:1 sur l'encre. C'est le seul endroit du
   site où le cyan porte du texte, et c'est ce qui allume le bloc. */
.bloc-sombre em,.bloc-sombre .cle{font-style:normal;color:var(--cyan-500)}
/* Une carte posée sur l'encre existe par un voile clair, jamais par un filet
   blanc franc qui ferait « tableau de bord ». */
.bloc-sombre .carte-sombre{
  background-color:rgba(var(--rgb-cyan),.06);
  border:1px solid rgba(var(--rgb-cyan),.16);
  border-radius:var(--r-lg);
  padding:var(--s6);
}

/* ── LE DÉGRADÉ PLEIN (RÈGLE 5) ───────────────────────────────────────────
   UNE SEULE FOIS PAR PAGE, sur UN SEUL bloc. C'est la signature de marque,
   pas un fond de section : un dégradé répété cesse d'être une signature et
   devient un papier peint.
   ⛔ Et jamais sous du texte de lecture : la rampe s'arrête au cyan pur, qui
      ne donne que 2,62:1 avec du blanc. Pour un bloc qui porte du texte, on
      emploie `.degrade-texte`, dont la rampe s'arrête à #1B7AA6 (4,79:1). */
.degrade-plein{background-image:var(--degrade-d);color:var(--blanc)}
.degrade-texte{background-image:var(--degrade-texte);color:var(--blanc)}
.degrade-plein :is(h1,h2,h3,h4,p,li),
.degrade-texte :is(h1,h2,h3,h4,p,li){color:inherit}

/* ── LA RÈGLE 6, RENDUE AUTOMATIQUE ───────────────────────────────────────
   Deux blocs DÉMONSTRATION consécutifs inversent le côté de l'image. C'est la
   seule répétition autorisée du site, et elle ne l'est QUE parce qu'elle
   alterne. Plutôt que de compter à la main, on le déclare :
   `<section class="bloc demonstration" data-image="droite">`.
   L'ordre visuel suit, la source HTML reste dans l'ordre de lecture (texte
   d'abord) — donc l'ordre du clavier et des lecteurs d'écran reste juste.    */
.demonstration{display:grid;gap:var(--s10);align-items:center}
@media(min-width:900px){
  .demonstration{grid-template-columns:1fr 1fr}
  .demonstration[data-image="droite"] > :first-child{order:1}
  .demonstration[data-image="droite"] > :last-child{order:2}
  .demonstration[data-image="gauche"] > :first-child{order:2}
  .demonstration[data-image="gauche"] > :last-child{order:1}
}


/* ==========================================================================
   5. LE MODE DIAGNOSTIC — les fautes de grammaire deviennent VISIBLES
   ==========================================================================
   S'active en posant `data-grammaire="diagnostic"` sur la balise <html> ou
   <body>. ⛔ IL NE CHANGE RIEN EN PRODUCTION : sans cet attribut, aucune règle
   de ce chapitre ne s'applique. Vérifié au navigateur.

   POURQUOI IL EXISTE : « ces règles se vérifient à la machine, page par page,
   avant tout commit. Une page qui en viole une n'est pas perfectible, elle est
   REFUSÉE. » Un contrôle qu'on ne peut pas VOIR n'est pas appliqué : autant le
   faire dessiner par le navigateur lui-même.

   CE QU'IL ATTRAPE VRAIMENT — et c'est plus que je ne l'attendais : la
   sélection par adjacence (`+`) et par frère général (`~`) suffit à détecter
   mécaniquement les règles 1, 2, 3, 4, 5 et 6. Seule la règle 7 demande une
   ruse (un dégradé de fond est CLIPPÉ à la boîte : la ligne rouge n'apparaît
   QUE si le bloc dépasse réellement 900 px).                                 */

[data-grammaire="diagnostic"] .bloc{outline:1px dashed rgba(var(--rgb-indigo),.35)}

/* RÈGLE 7 — la règle de 900 px, dessinée dans le bloc lui-même.
   Le dégradé est clippé à la boîte : si le bloc fait moins de 900 px, RIEN ne
   se voit. S'il dépasse, une barre rouge marque le 900e pixel et tout ce qui
   suit est voilé. C'est un détecteur exact, pas une approximation. */
[data-grammaire="diagnostic"] .bloc{
  background-image:linear-gradient(to bottom,
    transparent calc(var(--bloc-hauteur-max) - 3px),
    var(--erreur) calc(var(--bloc-hauteur-max) - 3px),
    var(--erreur) var(--bloc-hauteur-max),
    color-mix(in srgb,var(--erreur) 10%,transparent) var(--bloc-hauteur-max));
}

/* Le bandeau d'alerte commun à toutes les fautes d'enchaînement. */
[data-grammaire="diagnostic"] .bloc + .bloc::before,
[data-grammaire="diagnostic"] .bloc ~ .bloc::before{
  font-family:var(--police-etiquette);font-size:var(--t-xs);font-weight:600;
  letter-spacing:.08em;text-transform:uppercase;
  color:var(--blanc);background-color:var(--erreur);
  padding:.35rem .75rem;border-radius:var(--r-sm);
  position:absolute;top:.5rem;left:.5rem;z-index:9;
}

/* RÈGLE 1 — jamais deux blocs du même type à la suite.
   Un sélecteur par type : le CSS ne sait pas comparer deux attributs entre
   eux, mais il sait très bien reconnaître une paire nommée. */
[data-grammaire="diagnostic"] .bloc[data-type="hero"] + .bloc[data-type="hero"]::before,
[data-grammaire="diagnostic"] .bloc[data-type="preuve"] + .bloc[data-type="preuve"]::before,
[data-grammaire="diagnostic"] .bloc[data-type="triptyque"] + .bloc[data-type="triptyque"]::before,
[data-grammaire="diagnostic"] .bloc[data-type="demonstration"] + .bloc[data-type="demonstration"]::before,
[data-grammaire="diagnostic"] .bloc[data-type="schema"] + .bloc[data-type="schema"]::before,
[data-grammaire="diagnostic"] .bloc[data-type="tableau"] + .bloc[data-type="tableau"]::before,
[data-grammaire="diagnostic"] .bloc[data-type="faq"] + .bloc[data-type="faq"]::before,
[data-grammaire="diagnostic"] .bloc[data-type="citation"] + .bloc[data-type="citation"]::before,
[data-grammaire="diagnostic"] .bloc[data-type="cta"] + .bloc[data-type="cta"]::before{
  content:"Regle 1 - deux blocs du meme type a la suite";
}

/* RÈGLE 2 — jamais deux blocs À GRILLE à la suite, même de types différents.
   La faute exacte de Netcom : SIX blocs « en-tête + grille de cartes »
   d'affilée. L'oeil ne lit pas le contenu, il lit le squelette. */
[data-grammaire="diagnostic"] .bloc[data-grille] + .bloc[data-grille]::before{
  content:"Regle 2 - deux grilles consecutives";
}

/* RÈGLE 3 — jamais deux fonds identiques consécutifs.
   Les classes historiques `.s-blanc` et `.s-papier` sont surveillées elles
   aussi : le diagnostic doit pouvoir auditer les 46 pages existantes, pas
   seulement les blocs neufs. */
[data-grammaire="diagnostic"] .fond-blanc + .fond-blanc::before,
[data-grammaire="diagnostic"] .fond-papier + .fond-papier::before,
[data-grammaire="diagnostic"] .s-blanc + .s-blanc::before,
[data-grammaire="diagnostic"] .s-papier + .s-papier::before{
  content:"Regle 3 - deux fonds identiques consecutifs";
}

/* RÈGLE 4 — un seul bloc sombre par page. Le frère général `~` marque le
   DEUXIÈME et tous les suivants : le premier reste innocent. */
[data-grammaire="diagnostic"] .bloc-sombre ~ .bloc-sombre::before{
  content:"Regle 4 - deuxieme bloc sombre de la page";
}

/* RÈGLE 5 — le dégradé plein n'habille qu'un seul bloc par page. */
[data-grammaire="diagnostic"] .degrade-plein ~ .degrade-plein::before{
  content:"Regle 5 - deuxieme degrade plein de la page";
}

/* RÈGLE 6 — deux démonstrations consécutives doivent inverser l'image. */
[data-grammaire="diagnostic"] .demonstration[data-image="droite"] + .demonstration[data-image="droite"]::before,
[data-grammaire="diagnostic"] .demonstration[data-image="gauche"] + .demonstration[data-image="gauche"]::before{
  content:"Regle 6 - image du meme cote deux fois de suite";
}

/* Le mode diagnostic ne doit jamais partir en production par accident : on le
   dit à l'écran, en grand, en haut de page. */
[data-grammaire="diagnostic"] body::after{
  content:"MODE DIAGNOSTIC - GRAMMAIRE DES BLOCS";
  position:fixed;top:0;left:0;right:0;z-index:9999;
  font-family:var(--police-etiquette);font-size:var(--t-xs);font-weight:600;
  letter-spacing:.12em;text-align:center;padding:.3rem;
  color:var(--blanc);background-color:var(--erreur);
}

/* Le diagnostic est un outil de travail : il ne s'imprime pas, et il se tait
   pour qui a demandé moins d'animation ou une lecture simplifiée. */
@media print{[data-grammaire="diagnostic"] body::after{display:none}}

/* ══════════════════════════════════════════════════════════════════════════
   LES BANDES SANS PHOTO — ajouté le 16/08/2026 par _export-site.py
   ══════════════════════════════════════════════════════════════════════════
   Les 12 pages « secteurs » ont été écrites avant la séance photo. L'export
   retire les images introuvables et marque la section « sans-photo ».

   ⚠️ POURQUOI CETTE RÈGLE EXISTE, ET CE QU'ELLE ÉVITE.
   Le voile de « .bande::before » va de 92 % à 34 % d'opacité — il SUPPOSE
   qu'une photo se trouve dessous. Sans elle, la moitié droite de la bande
   devient quasi transparente sur le fond clair de la page, et le texte blanc
   y devient illisible.
   ## UN VOILE N'EST PAS UN FOND : il assombrit ce qui est derrière, il ne
   ## remplace rien. Retirer l'image casse donc le contraste du texte.

   On pose ici un fond plein, aux couleurs de la marque. Le texte reste
   parfaitement lisible, et la bande garde son intention graphique.
   👉 Le jour où la photo est déposée dans img/site/, l'export cesse d'ajouter
      « sans-photo » et cette règle ne s'applique plus. Rien à défaire. */
.bande.sans-photo{
  background:linear-gradient(100deg,#0A1230 0%,#141F4E 52%,#1B3168 100%);
}
/* Le voile devient inutile : il ne ferait qu'assombrir un fond déjà sombre. */
.bande.sans-photo::before{opacity:.35}
