/**
 * Theme Name: Blocksy Child
 * Description: Blocksy Child theme
 * Author: Creative Themes
 * Template: blocksy
 * Text Domain: blocksy
 * Version: 2.0.0
 */

/* ==========================================================================
   carteantennesuisse.ch — système de design
   Refonte du 15.08.2026.

   DIRECTION : « champ de signal ». Les courbes de niveau d'une carte
   topographique et les ondes d'une antenne ont la même grammaire — des
   courbes fermées imbriquées qui rayonnent depuis une source. La bannière
   est construite là-dessus ; le reste de la page reste clair et lisible.

   ⚠ AUCUNE valeur n'est décidée dans ce fichier. Chacune est LUE depuis
   theme.json via les variables --wp--preset--* et --wp--custom--*. Pour
   changer une couleur ou un espacement, modifier theme.json : l'éditeur de
   blocs affichera aussitôt la même chose que le site. Les valeurs après la
   virgule ne sont qu'un filet de sécurité.
   ========================================================================== */

:root {
	/* Couleurs — theme.json → settings.color.palette */
	--cas-signal:        var(--wp--preset--color--signal, #35d6b0);
	--cas-accent:        var(--wp--preset--color--accent, #1f9e86);
	--cas-accent-fonce:  var(--wp--preset--color--accent-fonce, #17715f);
	--cas-encre:         var(--wp--preset--color--encre, #0d1b19);
	--cas-encre-douce:   var(--wp--preset--color--encre-douce, #4a5b57);
	--cas-ligne:         var(--wp--preset--color--ligne, #e3e9e7);
	--cas-fond:          var(--wp--preset--color--fond, #ffffff);
	--cas-fond-doux:     var(--wp--preset--color--fond-doux, #f6f9f8);

	/* Couleurs hors palette — theme.json → settings.custom */
	--cas-nuit:          var(--wp--custom--nuit, #0a1a24);
	--cas-nuit-claire:   var(--wp--custom--nuit-claire, #12303e);

	/* Le fond des bandeaux de carte — barre mobile ET en-tête de bureau.
	   Défini UNE fois : les deux avaient dérivé (nuit pur d'un côté, nuit
	   teinté de rouge de l'autre) et l'écart se voyait en passant d'un écran
	   à l'autre. Le soupçon de rouge rappelle le #640b0b d'origine.
	   ⚠ Ne jamais nommer une variable --cas-top ni --cas-gap : ce sont
	   celles de l'application de carte (voir section 9 bis). */
	--cas-bandeau-fond: color-mix(in srgb, var(--cas-nuit) 92%, var(--cas-accent-fonce));

	/* Espacement — theme.json → settings.spacing.spacingSizes */
	--cas-e-1: var(--wp--preset--spacing--20, 0.5rem);
	--cas-e-2: var(--wp--preset--spacing--30, 1rem);
	--cas-e-3: var(--wp--preset--spacing--40, 1.75rem);
	--cas-e-4: var(--wp--preset--spacing--50, 3rem);
	--cas-e-5: var(--wp--preset--spacing--60, 5rem);
	--cas-e-6: var(--wp--preset--spacing--70, 7.5rem);

	/* Rôles typographiques.
	   Titres : Poppins, déjà chargée par Blocksy — c'est l'identité du site.
	   Données : pile monospace système, pour que les chiffres s'alignent. */
	--cas-f-titres:  var(--theme-font-family, "Poppins", sans-serif);
	/* Chasse fixe réservée aux ÉTIQUETTES techniques (pastilles, légendes).
	   Surtout pas aux grands chiffres : en chasse fixe, une espace occupe une
	   pleine cellule, et « 39 297 » s'affiche avec un écart double. Les
	   chiffres utilisent la police de titres avec des glyphes tabulaires. */
	--cas-f-donnees: ui-monospace, "SF Mono", "JetBrains Mono", "Roboto Mono", Menlo, monospace;

	--cas-r-s: 8px;
	--cas-r-m: 14px;
	--cas-r-l: 20px;
	--cas-ombre-1: 0 1px 2px rgba(13, 27, 25, 0.05);
	--cas-ombre-2: 0 1px 3px rgba(13, 27, 25, 0.06), 0 8px 24px -10px rgba(13, 27, 25, 0.18);
	--cas-ombre-3: 0 2px 6px rgba(13, 27, 25, 0.08), 0 20px 48px -14px rgba(13, 27, 25, 0.26);

	/* Surfaces du design sombre — les cartes et sections sont des surfaces
	   surélevées translucides sur le fond nuit. Fusion du 16.08.2026 : ces
	   valeurs étaient dupliquées dans une couche « body.home » posée par-dessus
	   un design clair devenu obsolète ; elles sont désormais LA base, lues
	   depuis theme.json, et l'éditeur les voit comme le site. */
	--cas-surface:        var(--wp--custom--surface, rgba(255, 255, 255, 0.045));
	--cas-surface-survol: var(--wp--custom--surface-survol, rgba(255, 255, 255, 0.075));
	--cas-surface-douce:  var(--wp--custom--surface-douce, rgba(255, 255, 255, 0.028));
	--cas-surface-visuel: var(--wp--custom--surface-visuel, rgba(255, 255, 255, 0.05));
	--cas-filet-clair:    var(--wp--custom--filet-clair, rgba(255, 255, 255, 0.10));
	--cas-filet-doux:     var(--wp--custom--filet-doux, rgba(255, 255, 255, 0.07));

	/* Rayon des boutons Blocksy : sa variable de design, à qui aucune clé du
	   Customizer ne répond (vérifié le 16.08.2026 — la couleur de texte, elle,
	   a sa clé : buttonTextColor). Surcharger la VARIABLE est la voie douce
	   recommandée par l'étape 8, pas une couche par-dessus ses sélecteurs. */
	--theme-button-border-radius: 999px;

	/* ----------------------------------------------------------------------
	   CONTRASTE DES DÉCORS — le seul endroit où ces opacités se règlent

	   18.08.2026, à sa demande : « partout augmente le contraste de l'antenne
	   l'onde et les montagnes et drapeaux ».

	   Ces vingt-trois opacités étaient jusqu'ici écrites au fil de la feuille,
	   à onze endroits différents, dont deux blocs @keyframes. Les régler
	   demandait de les retrouver ; en régler une sans voir les autres cassait
	   la hiérarchie des plans. Elles sont désormais TOUTES ici, chacune avec
	   sa valeur d'avant en commentaire.

	   🔴 UNE OPACITÉ DE DÉCOR N'EST JAMAIS UN GOÛT. Elle est plafonnée par le
	   contraste du TEXTE qui passe dessus — bug n°59 : à 0,5 de montagnes, une
	   étiquette #c9bcb6 de l'accueil tombait à 4,06 sur un fond composé à
	   (138, 61, 51), sous le seuil de 4,5. Toute hausse se REMESURE, page par
	   page, en composant réellement les couches. Les valeurs ci-dessous sont
	   des valeurs D'OUVERTURE, posées à sa demande et en attente de mesure.

	   🔴 UN SEUL LEVIER PAR DÉCOR. Les opacités se MULTIPLIENT (groupe SVG ×
	   calque parent) : monter les deux à la fois d'un tiers donne +78 % à
	   l'arrivée, pas +33 %. On ne touche donc qu'à l'opacité du CALQUE
	   (--cas-decor-montagnes, --cas-decor-antenne) ; les valeurs internes
	   restent à leur niveau du 18.08 et ne sont ici que pour être réglables.
	   La hiérarchie des plans — lointain plus pâle que proche — est ainsi
	   conservée telle qu'elle avait été mesurée. */

	/* Les montagnes : opacité du calque entier. */
	--cas-decor-montagnes:        0.72;  /* 0.4 → 0.55 → 0.72 (2e cran, 18.08 soir) */
	--cas-decor-montagnes-mobile: 0.65;  /* 0.36 → 0.5 → 0.65 */
	/* La bande du menu des pages de carte (18.08.2026, point 1). Volontairement
	   plus basse que la bannière : la barre est haute de 61 px et DENSE en
	   texte — sept liens de menu blancs y passent par-dessus le décor, alors
	   qu'une bannière n'y met qu'un titre et un chapeau. */
	--cas-decor-montagnes-menu:   0.55;  /* 0.42 → 0.55 */

	/* Les deux plans de crêtes, à l'intérieur du calque. Inchangés : c'est le
	   calque qui a monté. */
	--cas-decor-lointain:         0.45;  /* inchangé */
	--cas-decor-lointain-fond:    0.05;  /* inchangé */
	--cas-decor-proche:           0.9;   /* inchangé */
	--cas-decor-proche-fond:      0.12;  /* inchangé */
	--cas-decor-neige:            1;     /* inchangé */

	/* Les deux drapeaux suisses. Ce sont les DEUX valeurs qu'il a nommées, et
	   les seules du décor à avoir été plafonnées pour elles-mêmes : la croix
	   blanche est le point le plus lumineux que le dessin puisse produire. */
	--cas-drapeau-carre:          0.5;   /* 0.2 → 0.35 → 0.5 */
	--cas-drapeau-croix:          0.6;   /* 0.3 → 0.45 → 0.6 */

	/* L'antenne : opacité du calque entier, par largeur d'écran. */
	--cas-decor-antenne:          0.85;  /* 0.5 → 0.68 → 0.85 */
	--cas-decor-antenne-900:      0.44;  /* 0.26 → 0.35 → 0.44 */
	--cas-decor-antenne-480:      0.4;   /* 0.24 → 0.32 → 0.4 */
	--cas-decor-antenne-pied:     0.55;  /* 0.32 → 0.44 → 0.55 */
	--cas-decor-antenne-pied-900: 0.31;  /* 0.18 → 0.25 → 0.31 */

	/* Les pièces du dessin d'antenne, à l'intérieur du calque. Inchangées. */
	--cas-decor-treillis:         0.5;   /* inchangé */
	--cas-decor-traverse:         0.6;   /* inchangé */
	--cas-decor-panneau:          0.16;  /* inchangé */
	--cas-decor-parabole:         0.1;   /* inchangé */
	--cas-decor-feu-bas:          0.3;   /* inchangé — le battement du balisage */
	--cas-decor-feu-haut:         1;     /* inchangé */

	/* Les ondes de page, émises par les deux antennes. Trois paliers du même
	   cycle : elles doivent monter ENSEMBLE, sinon la décroissance du signal
	   change de forme. */
	--cas-onde-page-naissance:    0.46;  /* 0.26 → 0.35 → 0.46 */
	--cas-onde-page-milieu:       0.3;   /* 0.17 → 0.23 → 0.3 */
	--cas-onde-page-fin:          0.16;  /* 0.09 → 0.12 → 0.16 */

	/* Les ondes du logotype — pages de carte uniquement. */
	--cas-onde-logo-naissance:    0.85;  /* 0.55 → 0.72 → 0.85 */
	--cas-onde-logo-course:       0.52;  /* 0.3 → 0.4 → 0.52 */

	/* L'ÉCRAN SOUS LES TEXTES — la contrepartie de la hausse ci-dessus.

	   Mesure du 18.08.2026 sur la prod, décors montés : quatre textes réels
	   passaient sous 4,5 — `.cas-stat__valeur` à 2,96 et 3,71, son
	   `.cas-stat__libelle` à 3,84, le chapeau du blog à 3,97. Le propriétaire
	   veut le contraste des décors : on ne redescend donc AUCUNE opacité, on
	   pose un écran nuit translucide LOCAL sous les seuls textes en défaut.

	   🔴 C'est une ALPHA, et elle s'AJOUTE à ce qui existe déjà : sur les
	   cartes de chiffres, elle se pose PAR-DESSUS le fond de carte (voir
	   section 8 quater), elle ne le remplace pas. Transmission résiduelle du
	   décor sous le texte = (1 − alpha) × transmission d'avant.

	   Calcul d'ouverture, ancré sur les ratios MESURÉS par le superviseur (le
	   modèle retrouve son 2,96 à 0,01 près, en repartant du fond composé
	   (116, 54, 45) déjà relevé au bug n°59) :
	       alpha   corail 2,96 →   libellé 3,84 →   chapeau 3,97 →
	       0,45        4,31            5,38             6,40
	       0,55        4,65            5,81             7,08
	       0,62        4,90            6,11             7,57
	       0,65        5,00            6,23             7,78
	   Le facteur limitant est le chiffre corail (--cas-signal, #ff5a47) : à
	   0,55 il passe, avec 3 % de marge seulement. Si la mesure en composition
	   réelle le place plus bas, monter cette seule valeur à 0,62 ou 0,65. */
	--cas-ecran-texte: 0.55;
}

/* ==========================================================================
   1. Ossature commune
   ========================================================================== */

.cas-shell {
	width: min(1180px, 100% - 2.5rem);
	margin-inline: auto;
}

.cas-section { padding-block: var(--cas-e-5); }

/* La section « douce » est une surélévation sur le fond nuit. */
.cas-section--doux {
	background: var(--cas-surface-douce);
	border-block: 1px solid var(--cas-filet-doux);
}

.cas-section__titre {
	font-family: var(--cas-f-titres);
	font-size: clamp(1.75rem, 1.2rem + 1.8vw, 2.25rem);
	line-height: 1.14;
	letter-spacing: -0.022em;
	margin: 0 0 var(--cas-e-1);
	color: var(--wp--custom--banniere--titre, #ffffff);
	text-wrap: balance;
}

.cas-section__intro {
	max-width: 52ch;
	margin: 0 0 var(--cas-e-4);
	color: var(--wp--custom--banniere--texte, #c9bcb6);
	font-size: 1.0625rem;
	line-height: 1.6;
}

/* Étiquette de section : petites capitales précédées d'un trait, comme la
   légende d'une carte. */
.cas-eyebrow {
	display: flex;
	align-items: center;
	gap: 0.7rem;
	font-family: var(--cas-f-donnees);
	font-size: 0.75rem;
	letter-spacing: 0.14em;
	text-transform: uppercase;
	color: var(--cas-accent-fonce);
	margin: 0 0 var(--cas-e-2);
}

.cas-eyebrow::before {
	content: "";
	width: 28px;
	height: 1px;
	background: currentColor;
	flex: none;
}

/* ==========================================================================
   2. BANNIÈRE — le champ de signal
   ========================================================================== */

.cas-hero {
	position: relative;
	isolation: isolate;
	overflow: hidden;
	padding-block: clamp(7rem, 5rem + 7vw, 11rem) clamp(4rem, 3rem + 3vw, 6rem);
	/* ⚠ FOND TRANSLUCIDE, volontairement.
	   Un dégradé opaque ici masquait les ondes : celles de l'antenne du haut
	   n'apparaissaient qu'une fois SORTIES de la bannière, et celles de
	   l'antenne du pied n'y entraient jamais. Le corps de page fournit déjà
	   la couleur de fond ; ce dégradé ne sert qu'à nuancer la profondeur, il
	   n'a donc pas besoin d'être opaque. Même correctif que pour le pied. */
	background: linear-gradient(168deg,
		transparent 0%,
		color-mix(in srgb, var(--cas-nuit-claire) 52%, transparent) 100%);
	color: var(--wp--custom--banniere--texte, #c9bcb6);
}

/* Halo du point d'émission */
.cas-hero::after {
	content: "";
	position: absolute;
	inset: 0;
	z-index: -1;
	background: radial-gradient(48rem 34rem at 76% 40%,
		color-mix(in srgb, var(--cas-signal) 20%, transparent), transparent 64%);
	pointer-events: none;
}

.cas-hero > .cas-shell { position: relative; z-index: 1; }

.cas-hero__eyebrow {
	display: inline-flex;
	align-items: center;
	gap: 0.6rem;
	font-family: var(--cas-f-donnees);
	font-size: 0.75rem;
	letter-spacing: 0.13em;
	text-transform: uppercase;
	color: var(--cas-signal);
	background: color-mix(in srgb, var(--cas-signal) 9%, transparent);
	border: 1px solid color-mix(in srgb, var(--cas-signal) 28%, transparent);
	border-radius: 999px;
	padding: 0.45rem 0.95rem;
	margin: 0 0 var(--cas-e-3);
}

/* Pastille clignotante : la donnée est vivante. */
.cas-hero__eyebrow::before {
	content: "";
	width: 7px;
	height: 7px;
	border-radius: 50%;
	background: var(--cas-signal);
	box-shadow: 0 0 0 0 color-mix(in srgb, var(--cas-signal) 60%, transparent);
	animation: cas-pouls 2.4s ease-out infinite;
	flex: none;
}

@keyframes cas-pouls {
	0%   { box-shadow: 0 0 0 0 color-mix(in srgb, var(--cas-signal) 60%, transparent); }
	70%  { box-shadow: 0 0 0 10px color-mix(in srgb, var(--cas-signal) 0%, transparent); }
	100% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--cas-signal) 0%, transparent); }
}

.cas-hero h1 {
	font-family: var(--cas-f-titres);
	font-size: clamp(2.1rem, 1.1rem + 3.5vw, 3.5rem);
	line-height: 1.04;
	letter-spacing: -0.032em;
	max-width: 19ch;
	margin: 0 0 var(--cas-e-2);
	color: var(--wp--custom--banniere--titre, #ffffff);
	text-wrap: balance;
}

.cas-hero__lead {
	font-size: clamp(1.0625rem, 1rem + 0.3vw, 1.1875rem);
	line-height: 1.62;
	color: var(--wp--custom--banniere--texte, #c9bcb6);
	max-width: 54ch;
	margin: 0 0 var(--cas-e-3);
}

/* --- Les chiffres, traités comme des relevés d'instrument --------------- */

/* 🔴 COMPACTION du 18.08.2026, demandée par le propriétaire (« rendre le bloc
   des compteurs plus compact »). Le niveau choisi est CELUI-CI, et pas un
   autre — vérifié avant d'écrire :
   · les blocs du générateur ne portent AUCUN attribut d'espacement
     (`generer_accueils.py` n'écrit que `className`), donc rien à compacter au
     niveau 2 « attributs de blocs » ;
   · l'échelle `--cas-e-*` de theme.json est commune à TOUT le site : la
     toucher déplacerait 40 pages pour en compacter deux blocs ;
   · « Espacement du contenu : Confortable » est son choix délibéré et GLOBAL
     dans Blocksy — interdit d'y toucher.
   Les hauteurs de ces deux composants sont donc décidées ici, et nulle part
   ailleurs : on corrige à la source, on n'empile pas une couche.
   ⚠ AUCUN texte ne bouge, aucun élément n'est retiré (règle ②). Seuls des
   espacements changent, et les classes `cas-` étant identiques dans les trois
   langues, la structure FR / DE / IT ne peut pas diverger. */
.cas-stats {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
	gap: 1px;
	/* ⚠ MESURÉ INERTE : Gutenberg met `margin-block-start: 0` sur les enfants
	   d'un groupe « is-layout-flow », et sa feuille passe devant. La valeur
	   calculée est 0 px, ici comme avec l'ancien --cas-e-4. L'écart réel
	   au-dessus du bloc est la marge BASSE du chapeau (15,2 px, posée par
	   Blocksy). On garde la déclaration comme repli si le groupe cessait un
	   jour d'être en flux, mais elle ne compacte rien — voir CSS-24. */
	margin-top: var(--cas-e-3);
	background: rgba(255, 255, 255, 0.10);
	border: 1px solid rgba(255, 255, 255, 0.10);
	border-radius: var(--cas-r-m);
	overflow: hidden;
}

.cas-stat {
	background: rgba(10, 26, 36, 0.55);
	/* compaction : le vertical passe de --cas-e-3 (28 px) à --cas-e-2 (16 px),
	   l'horizontal ne bouge pas — c'est la HAUTEUR qu'il veut réduire. */
	padding: var(--cas-e-2) var(--cas-e-3);
	transition: background 0.3s ease;
}

/* Blocksy ajoute son "espacement du contenu" aux enfants des groupes
   Gutenberg, même quand ces groupes sont devenus des grilles CSS. Dans une
   rangée, tous les blocs sauf :last-child recevaient donc une marge basse :
   statistiques et opérateurs, mais aussi cartes d'outils et citations presse.
   Le dernier bloc semblait plus grand que les autres. Les grilles ont déjà
   leur propre `gap` ; leurs cartes ne doivent porter aucune marge. */
.cas-stats > .cas-stat,
.cas-ops > .cas-op,
.cas-outils > .cas-outil,
.cas-presse > .cas-citation {
	margin-block: 0;
}

/* 🔴 CSS-24 (18.08.2026) — la MÊME cause, un cran plus bas dans l'arbre.
   CSS-21 avait neutralisé l'espacement Blocksy sur les CARTES ; il reste
   entier sur ce qu'il y a DEDANS. `--theme-content-spacing` vaut « 0.8em »,
   donc une marge proportionnelle à la police : sous un chiffre de 41,6 px
   elle pèse 33,28 px. C'est là qu'était la hauteur, et non dans nos
   `margin` — écrites sans parent, elles étaient à égalité de spécificité
   avec la feuille Blocksy, chargée APRÈS : elles ne s'appliquaient pas.
   Mesuré avant/après, valeur calculée : 33,28 px → 4,8 px.
   ⚠ On ne touche PAS au réglage « Espacement du contenu : Confortable »,
   qui est son choix délibéré et global : on l'écarte uniquement dans les
   deux composants que la demande vise. */
.cas-stats > .cas-stat > .cas-stat__valeur { margin-block-end: 0.3rem; }
.cas-ops   > .cas-op   > .cas-op__logo     { margin-block-end: 0.55rem; }
.cas-ops   > .cas-op   > .cas-op__phrase   { margin-block-end: 0.55rem; }
.cas-ops   > .cas-op   > .cas-op__5g       { margin-block-end: 0.4rem; }

.cas-stat:hover { background: rgba(18, 48, 62, 0.75); }

.cas-stat__valeur {
	display: block;
	font-family: var(--cas-f-titres);
	font-feature-settings: "tnum" 1;
	font-size: clamp(1.85rem, 1.2rem + 2vw, 2.6rem);
	font-weight: 700;
	line-height: 1;
	letter-spacing: -0.02em;
	color: var(--wp--custom--banniere--titre, #ffffff);
	font-variant-numeric: tabular-nums;
}

.cas-stat--accent .cas-stat__valeur { color: var(--cas-signal); }

.cas-stat__libelle {
	display: block;
	margin-top: 0.3rem;                  /* compaction : était 0.5rem */
	font-size: 0.875rem;
	line-height: 1.4;
	color: var(--wp--custom--banniere--attenue, #b0a29b);
}

/* ==========================================================================
   3. Boutons
   ========================================================================== */

.cas-actions { display: flex; flex-wrap: wrap; gap: 0.75rem; }

.cas-actions .wp-block-button__link {
	display: inline-flex;
	align-items: center;
	gap: 0.5rem;
	padding: 0.9rem 1.55rem;
	border-radius: 999px;
	font-family: var(--cas-f-titres);
	font-weight: 600;
	font-size: 0.9688rem;
	line-height: 1.2;
	text-decoration: none;
	transition: transform 0.2s ease, box-shadow 0.2s ease,
	            background 0.2s ease, border-color 0.2s ease, color 0.2s ease;
}

/* Sur la bannière sombre, le bouton plein est le point le plus lumineux. */
.cas-btn--plein .wp-block-button__link {
	background: var(--cas-signal);
	color: var(--cas-nuit);
	border: 1px solid transparent;
	box-shadow: 0 10px 30px -12px color-mix(in srgb, var(--cas-signal) 75%, transparent);
}

.cas-btn--plein .wp-block-button__link:hover {
	background: var(--wp--preset--color--signal-clair, #ff7a6a);
	transform: translateY(-2px);
	box-shadow: 0 16px 38px -14px color-mix(in srgb, var(--cas-signal) 90%, transparent);
}

.cas-btn--ligne .wp-block-button__link {
	background: transparent;
	color: var(--wp--custom--banniere--titre, #ffffff);
	border: 1px solid rgba(255, 255, 255, 0.28);
}

.cas-btn--ligne .wp-block-button__link:hover {
	border-color: var(--cas-signal);
	color: var(--cas-signal);
	transform: translateY(-2px);
}

/* Hors bannière : le fond des sections est nuit lui aussi (fusion du
   16.08.2026), le bouton plein garde le ton foncé — opaque, il reste à 5,89:1
   sur n'importe quel sol — et le bouton contour reprend les valeurs sombres. */
.cas-section .cas-btn--plein .wp-block-button__link {
	background: var(--cas-accent-fonce);
	color: var(--cas-fond);
	box-shadow: var(--cas-ombre-2);
}

.cas-section .cas-btn--plein .wp-block-button__link:hover {
	background: color-mix(in srgb, var(--cas-accent-fonce) 86%, #000);
}

.cas-section .cas-btn--ligne .wp-block-button__link {
	background: transparent;
	color: var(--wp--custom--banniere--titre, #ffffff);
	border-color: rgba(255, 255, 255, 0.28);
}

.cas-section .cas-btn--ligne .wp-block-button__link:hover {
	border-color: var(--cas-signal);
	color: var(--cas-signal);
}

/* ==========================================================================
   4. Opérateurs
   ========================================================================== */

/* 🔴 COMPACTION du 18.08.2026 — même demande, même raisonnement que pour
   `.cas-stats` ci-dessus (voir le commentaire, il vaut pour les deux blocs).
   ⚠ Le cadre de la section, lui, ne peut PAS se compacter sur `.cas-section` :
   cette classe habille QUATRE sections par accueil (opérateurs, blog, outils,
   presse) et deux autres pages. La règle est donc scopée par `:has(.cas-ops)`,
   la seule condition qui désigne exactement le bloc des trois opérateurs — et
   elle est écrite en UNE règle, sans annulation séparée à départager
   (leçon CSS-17). */
.cas-section:has(.cas-ops) {
	padding-block: var(--cas-e-4);       /* compaction : était --cas-e-5 */
}

.cas-section:has(.cas-ops) .cas-section__intro {
	margin-bottom: var(--cas-e-3);       /* compaction : était --cas-e-4 */
}

/* Le titre de section : 20,8 px de marge basse posés par Blocksy, contre les
   8 px que dit notre règle générale — même duel de spécificité que CSS-24. */
.cas-section:has(.cas-ops) .cas-section__titre {
	margin-block-end: 0.5rem;
}

/* 🔴 365 px et non 260 px (18.08.2026, 2ᵉ passe sur ces cartes). Entre 600 et
   900 px, `minmax(260px, 1fr)` fabriquait des colonnes de 272 px — soit
   216 px de contenu utile, contre 327 px sur bureau. La phrase de l'opérateur
   y passait à TROIS lignes (mesuré en allemand à 600 px et à 899 px), alors
   même qu'elle tenait sur une seule à 480 px. La largeur mini exigée d'une
   colonne est donc désormais celle qui laisse la phrase d'un seul tenant.
   ⚠ Le bureau ne bouge pas d'un pixel : à 1180 px de conteneur, 3 colonnes de
   382 px passent toujours (382 ≥ 365). Vérifié à 1280 et 1710 px. */
.cas-ops {
	display: grid;
	/* ⚠ `min(365px, 100%)` et non `365px` tout court : un `minmax()` dont le
	   minimum dépasse le conteneur impose sa taille et FAIT DÉBORDER la piste.
	   Mesuré à 360 px avant ce correctif : carte de 365 px dans une colonne de
	   320 — et le contrôle `scrollWidth <= innerWidth` ne le voyait pas, un
	   ancêtre masquant le dépassement. C'est l'idiome à retenir pour tout
	   `auto-fit`. */
	grid-template-columns: repeat(auto-fit, minmax(min(365px, 100%), 1fr));
	gap: var(--cas-e-2);
}

.cas-op {
	background: var(--cas-surface);
	border: 1px solid var(--cas-filet-clair);
	border-radius: var(--cas-r-m);
	padding: var(--cas-e-2) var(--cas-e-3);   /* compaction : était --cas-e-3 */
	transition: background 0.3s ease, box-shadow 0.3s ease, transform 0.3s ease,
	            border-color 0.3s ease;
}

.cas-op:hover {
	background: var(--cas-surface-survol);
	border-color: color-mix(in srgb, var(--cas-signal) 42%, transparent);
	box-shadow: 0 20px 46px -20px rgba(0, 0, 0, 0.7);
	transform: translateY(-2px);
}

/* ⚠ Le cartouche blanc des logos n'est pas décoratif : le logo Salt est du
   texte NOIR sur fond transparent, il disparaîtrait sur le nuit. C'est aussi
   la façon correcte d'afficher une marque tierce. */
.cas-op__logo {
	display: inline-block;
	margin: 0 0 var(--cas-e-1);          /* compaction : était --cas-e-2 */
	background: var(--cas-fond, #ffffff);
	border-radius: var(--cas-r-s);
	padding: 0.4rem 0.85rem;             /* compaction : était 0.55rem */
}
/* 32 px et non 34 : le cartouche perd 5 px de haut sans que la marque
   devienne moins lisible — vérifié à la mesure, les trois logos gardent leur
   largeur d'origine (`width: auto`). */
.cas-op__logo img { height: 32px; width: auto; object-fit: contain; }

/* 🔴 SUR TÉLÉPHONE, LA CARTE GARDE L'ORGANISATION DU BUREAU — 18.08.2026,
   après sa capture d'iPhone : « sur mobile le bloc avec les 3 opérateurs est
   trop moche, cela ne ressemble pas à la version sur ordinateur ».

   Ce qui avait été essayé, et pourquoi c'est ABANDONNÉ. Il avait d'abord
   demandé que le chiffre passe à DROITE du logo sur mobile ; c'était fait, en
   grille. Mais poser le cartouche à côté lui prend 75 px de largeur, et la
   phrase n'a plus de quoi tenir sur une ligne. Relevé sur la plage complète,
   nombre de lignes des trois cartes (phrase / ligne 5G) :

     largeur   360    375        390        414        600        899
     avant    2/2   2/2·2/1·1/2  2/1·1/1   2/1·1/1    3/2·2/2    3/2·2/2

   À 375 px — la largeur de SON téléphone (1125 px physiques ÷ 3) — les trois
   cartes ne se pliaient même pas pareil : c'est exactement sa capture. Et le
   défaut revenait entre 600 et 900 px, où la grille remet des colonnes
   étroites.

   🔴 La conclusion est mesurée, pas esthétique : le cartouche à côté n'est
   pas tenable sur la plage. On revient donc à l'organisation du bureau —
   logo au-dessus, phrase pleine largeur, ligne 5G, jauge — qui est
   précisément ce qu'il demande de reproduire. Relevé après : **1 ligne / 1
   ligne et trois cartes au même gabarit, de 360 à 1710 px, dans les trois
   langues.**

   ⚠ Le `margin-block-end` du cartouche porte son parent dans le sélecteur :
   sans ce cran de spécificité, l'espacement Blocksy chargé après nous le
   remettrait (CSS-24). */
@media (max-width: 900px) {
	.cas-ops > .cas-op > .cas-op__logo { margin-block-end: 0.5rem; }

	/* La ligne 5G est le seul endroit qui ne tient pas à taille fixe sous
	   414 px : en allemand, « 11443 mit 5G (3500 MHz) kompatibel 61 % »
	   réclame 293 px à 14 px de corps, pour 264 px disponibles à 360 px.
	   Mesuré au canevas, étalonné (écart 0 px sur une largeur connue) :
	   14 px → 293 · 13 px → 273 · 12,5 px → 263 · 12 px → 253.
	   D'où une taille fluide qui suit la largeur et plafonne à la valeur du
	   bureau dès 418 px : le pliage devient identique à toutes les largeurs
	   au lieu de basculer d'un téléphone à l'autre. */
	/* ⚠ Le parent est DANS le sélecteur, et ce n'est pas décoratif : écrites
	   `.cas-op__5g { … }`, ces deux règles étaient à égalité de spécificité
	   avec leur définition de base — qui vient PLUS BAS dans le fichier, donc
	   qui gagnait. Mesuré : 14 px rendus au lieu des 12,06 px demandés, la
	   règle était inerte sans que rien ne le signale. Même leçon que CSS-24,
	   cette fois contre notre propre feuille et non celle de Blocksy. */
	.cas-ops > .cas-op > .cas-op__5g            { font-size: clamp(0.75rem, 3.35vw, 0.875rem); }
	.cas-ops > .cas-op > .cas-op__5g .cas-op__pct { font-size: clamp(0.9rem, 4.05vw, 1.0625rem); }
}

/* La phrase est reprise MOT POUR MOT du site d'origine ; seuls les deux
   nombres sont mis en valeur. */
.cas-op__phrase {
	margin: 0;
	font-size: 1.0313rem;
	line-height: 1.55;
	color: var(--wp--custom--banniere--texte, #c9bcb6);
	text-wrap: pretty;
}

.cas-op__total {
	font-family: var(--cas-f-titres);
	font-feature-settings: "tnum" 1;
	font-size: 1.7rem;
	font-weight: 700;
	letter-spacing: -0.02em;
	color: var(--wp--custom--banniere--titre, #ffffff);
	font-variant-numeric: tabular-nums;
}

.cas-op__phrase strong:not(.cas-op__total) {
	color: var(--wp--custom--banniere--titre, #ffffff);
	font-weight: 700;
}

/* ==========================================================================
   5. Cartes d'outils
   ========================================================================== */

.cas-outils {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
	gap: var(--cas-e-3);
}

.cas-outil {
	position: relative;
	display: flex;
	flex-direction: column;
	background: var(--cas-surface);
	border: 1px solid var(--cas-filet-clair);
	border-radius: var(--cas-r-l);
	overflow: hidden;
	transition: background 0.34s ease, box-shadow 0.34s ease, transform 0.34s ease,
	            border-color 0.34s ease;
}

.cas-outil:hover {
	background: var(--cas-surface-survol);
	border-color: color-mix(in srgb, var(--cas-signal) 42%, transparent);
	box-shadow: 0 20px 46px -20px rgba(0, 0, 0, 0.7);
	transform: translateY(-4px);
}

.cas-outil__visuel {
	margin: 0;
	aspect-ratio: 16 / 9;
	overflow: hidden;
	background: var(--cas-surface-visuel);
	border-bottom: 1px solid var(--cas-filet-clair);
}

.cas-outil__visuel img {
	width: 100%;
	height: 100%;
	object-fit: cover;
	display: block;
	transition: transform 0.55s cubic-bezier(0.22, 1, 0.36, 1);
}

.cas-outil:hover .cas-outil__visuel img { transform: scale(1.045); }

.cas-outil__corps {
	padding: var(--cas-e-3);
	display: flex;
	flex-direction: column;
	gap: 0.55rem;
	flex: 1;
}

.cas-outil__corps h3 {
	font-family: var(--cas-f-titres);
	font-size: 1.1875rem;
	line-height: 1.26;
	letter-spacing: -0.015em;
	margin: 0;
	color: var(--wp--custom--banniere--titre, #ffffff);
	text-wrap: balance;
}

.cas-outil__corps p {
	margin: 0;
	color: var(--wp--custom--banniere--texte, #c9bcb6);
	font-size: 0.9688rem;
	line-height: 1.58;
}

.cas-outil__lien { margin: auto 0 0; padding-top: var(--cas-e-2); }

.cas-outil__lien a {
	font-weight: 600;
	font-size: 0.9375rem;
	color: var(--cas-signal);
	text-decoration: none;
	display: inline-flex;
	align-items: center;
	gap: 0.4rem;
}

.cas-outil__lien a::after { content: "→"; transition: transform 0.25s ease; }
.cas-outil:hover .cas-outil__lien a::after { transform: translateX(4px); }

/* Toute la carte devient cliquable, sans imbriquer de liens. */
.cas-outil__lien a::before { content: ""; position: absolute; inset: 0; }

/* ==========================================================================
   6. Mentions presse
   ========================================================================== */

.cas-presse {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
	gap: var(--cas-e-2);
}

.cas-citation {
	display: flex;
	flex-direction: column;
	gap: var(--cas-e-2);
	background: var(--cas-surface);
	border: 1px solid var(--cas-filet-clair);
	border-radius: var(--cas-r-m);
	padding: var(--cas-e-3);
}

.cas-citation:hover {
	background: var(--cas-surface-survol);
	border-color: color-mix(in srgb, var(--cas-signal) 42%, transparent);
	box-shadow: 0 20px 46px -20px rgba(0, 0, 0, 0.7);
}

.cas-citation__portrait { margin: 0; }

/* Mesuré le 15.08.2026 : les trois visuels de cette section n'ont PAS la même
   nature. Romain Boisset est un portrait carré (640×640), les deux autres
   sont des logos larges (281×114 et 438×166). Les enfermer dans un cercle en
   « cover » en rognait 59 % et 62 %.

   On n'impose donc aucune forme : une hauteur commune, une largeur libre, et
   « contain » — chaque visuel s'affiche en entier, quel que soit son format.
   Cela vaut aussi pour ceux que le propriétaire ajoutera plus tard. */
.cas-citation__portrait img {
	height: 46px;
	width: auto;
	max-width: 170px;
	object-fit: contain;
	object-position: left center;
	border-radius: 0;
	display: block;
}

.cas-citation__nom {
	font-family: var(--cas-f-titres);
	font-size: 1.0625rem !important;
	line-height: 1.3;
	letter-spacing: -0.01em;
	margin: 0;
	color: var(--wp--custom--banniere--titre, #ffffff);
}

.cas-citation__bio {
	margin: 0;
	font-size: 0.9375rem;
	line-height: 1.62;
	color: var(--wp--custom--banniere--texte, #c9bcb6);
}

.cas-citation__lien { margin: auto 0 0; padding-top: var(--cas-e-1); }

.cas-citation__lien a {
	font-weight: 600;
	font-size: 0.9375rem;
	color: var(--cas-signal);
	text-decoration: none;
	display: inline-flex;
	align-items: center;
	gap: 0.4rem;
}

.cas-citation__lien a::after { content: "→"; transition: transform 0.25s ease; }
.cas-citation__lien a:hover::after { transform: translateX(4px); }

/* ==========================================================================
   6 bis. Encadré générique de contenu
   La carte du système de design, posée par la CLASSE cas-encadre sur un
   wp:group — jamais par des attributs figés dans le bloc (voir CSS-20).
   Premier usage : « Analyse juin 2025 » sur les pages Graphique, première
   case d'une grille de trois colonnes ; le propriétaire duplique le groupe
   dans une case voisine pour chaque nouvelle analyse, et l'habillage suit.
   ========================================================================== */

.cas-encadre {
	background: var(--cas-surface);
	border: 1px solid var(--cas-filet-clair);
	border-radius: var(--cas-r-m);
	padding: var(--cas-e-3);
	text-align: center;
}

.cas-encadre .wp-block-buttons { justify-content: center; }

/* ==========================================================================
   7. Apparition au défilement

   Le masquage est conditionné à .cas-js, que le script pose lui-même. Si le
   JavaScript ne s'exécute pas — erreur, blocage, robot d'indexation — RIEN
   n'est masqué : la page reste entièrement lisible.
   ========================================================================== */

.cas-js .cas-anim {
	opacity: 0;
	transform: translateY(18px);
	transition: opacity 0.62s cubic-bezier(0.22, 1, 0.36, 1),
	            transform 0.62s cubic-bezier(0.22, 1, 0.36, 1);
}

.cas-js .cas-est-visible.cas-anim,
.cas-js .cas-est-visible .cas-anim { opacity: 1; transform: none; }

.cas-anim:nth-child(2) { transition-delay: 0.07s; }
.cas-anim:nth-child(3) { transition-delay: 0.14s; }
.cas-anim:nth-child(4) { transition-delay: 0.21s; }
.cas-anim:nth-child(5) { transition-delay: 0.28s; }

/* ==========================================================================
   8. L'antenne de la bannière
   ========================================================================== */

.cas-antenne {
	position: absolute;
	z-index: 0;

	/* La marge qui la sépare du bord de la bannière. Elle sert DEUX fois :
	   pour la poser (right) et pour plafonner sa taille (voir --cas-ant-h).
	   Une seule valeur, donc les deux ne peuvent plus diverger. */
	--cas-ant-marge: clamp(1rem, 6vw, 7rem);

	/* La borne de hauteur propre à la largeur d'écran. Elle est isolée dans
	   une variable pour que les media queries n'aient qu'elle à redéfinir :
	   le plafond de largeur ci-dessous reste écrit UNE fois. */
	--cas-ant-h: clamp(277px, 34.3vw, 528px);

	right: var(--cas-ant-marge);
	top: 50%;
	translate: 0 -50%;

	/* 🔴 La taille se pilote par la HAUTEUR, jamais par la largeur — voir CSS-18.
	   Une largeur fixe donnait toujours 410 px de haut, quelle que soit la
	   bannière : sur « À propos », haute de 249 px, 39 % de l'antenne passaient
	   sous le bord et le mât était coupé net. Le « 90% » la fait tenir dans la
	   bannière qui l'accueille ; les bornes en px reprennent exactement
	   l'ancienne taille (largeur × 264/200), donc rien ne bouge là où il y a
	   la place. La largeur suit toute seule par le rapport du dessin.

	   🔴 TROISIÈME borne, ajoutée le 17.08.2026 — voir CSS-22. La hauteur
	   commandait bien, mais RIEN ne bornait la largeur qui en découle : sur
	   téléphone, le dessin sortait par la droite et la bannière le coupait
	   (17 % visible seulement sur la 404). On plafonne donc AUSSI la hauteur
	   par la place horizontale disponible, convertie au rapport du dessin.
	   ⚠ Le plafond doit rester une HAUTEUR : un « max-width » clampe la
	   largeur sans recalculer la hauteur, et le dessin se déforme —
	   mesuré, rapport tombé de 0,758 à 0,644.
	   ⚠ Les 3,5rem retirés couvrent la marge de gauche ET l'écart possible
	   entre 100vw et innerWidth quand la barre de défilement occupe de la
	   place. */
	aspect-ratio: 200 / 264;
	width: auto;
	height: min(
		90%,
		var(--cas-ant-h),
		calc((100vw - 3.5rem) * 264 / 200)
	);

	color: var(--cas-signal);
	/* 🔴 Réglée dans :root — voir « CONTRASTE DES DÉCORS ». Valait 0,5 en dur
	   jusqu'au 18.08.2026. */
	opacity: var(--cas-decor-antenne);
	pointer-events: none;
	fill: none;
	stroke: currentColor;
	stroke-linecap: round;
	stroke-linejoin: round;
	-webkit-mask-image: linear-gradient(to bottom, #000 0%, #000 58%, transparent 94%);
	mask-image: linear-gradient(to bottom, #000 0%, #000 58%, transparent 94%);
}

/* Sur mobile elle passe DERRIÈRE le texte, atténuée : le trait ne doit
   jamais gêner la lecture — mais il doit être ENTIER. La marge redevient
   positive (elle valait -14 % et -22 %, c'est-à-dire hors champ) et la borne
   de hauteur passe par la variable, le plafond de largeur s'appliquant tout
   seul. */
@media (max-width: 900px) {
	.cas-antenne {
		--cas-ant-marge: clamp(0.75rem, 3vw, 1.5rem);
		--cas-ant-h: min(113.5vw, 554px);
		top: 46%;
		opacity: var(--cas-decor-antenne-900);
	}
}

@media (max-width: 480px) {
	.cas-antenne {
		--cas-ant-h: 142.6vw;
		opacity: var(--cas-decor-antenne-480);
	}
}

/* --- Les pièces du dessin ------------------------------------------------

   Enrichi le 17.08.2026 à sa demande — « qu'elle ressemble encore plus à une
   antenne ». Le viewBox ne bouge PAS (200 × 264) : les bornes de taille
   ci-dessus et l'ancrage des ondes sont calibrés sur ce rapport. */

/* Les deux montants du pylône, qui s'évasent vers le sol. */
.cas-antenne__mat { stroke-width: 2.2; }

/* Le croisillon de chaque travée — c'est lui qui fait lire « treillis ». */
.cas-antenne__treillis { stroke-width: 1; opacity: var(--cas-decor-treillis); }

/* Les traverses horizontales entre les montants. */
.cas-antenne__traverse { stroke-width: 1.2; opacity: var(--cas-decor-traverse); }

/* Le fût de tête et les deux bras qui portent les panneaux. */
.cas-antenne__tete { stroke-width: 2; }

/* Les trois panneaux émetteurs : deux secteurs vus de profil, un de face.
   Un aplat très léger suffit à les distinguer du treillis. */
.cas-antenne__panneau {
	stroke-width: 1.6;
	fill: currentColor;
	fill-opacity: var(--cas-decor-panneau);
}

/* La parabole du faisceau hertzien, avec sa tête de source. */
.cas-antenne__parabole {
	stroke-width: 1.4;
	fill: currentColor;
	fill-opacity: var(--cas-decor-parabole);
}

/* Le feu de balisage du sommet : il bat lentement, comme sur un vrai pylône. */
.cas-antenne__feu {
	stroke: none;
	fill: currentColor;
	animation: cas-balise 3.6s ease-in-out infinite;
}

@keyframes cas-balise {
	0%, 100% { opacity: var(--cas-decor-feu-bas); }
	50%      { opacity: var(--cas-decor-feu-haut); }
}


/* ==========================================================================
   8 bis. LES MONTAGNES — la Suisse posée derrière l'antenne

   Demandé le 17.08.2026 : « des montagnes dessinées dans le même style que
   l'antenne, pour représenter la Suisse ». Même trait, même jeton de couleur
   (--cas-signal), même discrétion — c'est un DÉCOR, il passe derrière le
   texte et derrière l'antenne.

   Pourquoi du CSS et du SVG plutôt qu'un réglage ou une image : ni Blocksy ni
   un attribut de bloc ne savent poser un décor vectoriel dans le bandeau de
   titre, et une image bitmap coûterait un téléchargement pour un dessin de
   quelques centaines d'octets. Même justification que l'antenne.

   Deux plans pour la profondeur :
     · lointain — crêtes hautes, trait fin, très atténué ;
     · proche   — crêtes plus basses et plus anguleuses, dont une dent
                  asymétrique qui donne la silhouette alpine, trait plus franc.
   Trois névés (petits zigzags) marquent les sommets principaux.

   ⚠ preserveAspectRatio="xMidYMax slice" : le dessin remplit la largeur en
   gardant SON rapport — il est rogné, jamais étiré. Et la boîte fait
   « width: 100% », donc elle ne peut pas créer de débordement horizontal.
   ========================================================================== */

.cas-montagnes {
	position: absolute;
	left: 0;
	right: 0;
	bottom: 0;
	width: 100%;
	/* 🔴 16vw, ce n'est pas un chiffre décoratif : c'est 192/1200 de la
	   largeur, le rapport exact du viewBox. La boîte a donc la taille que le
	   dessin prend une fois mis à l'échelle de la largeur, et l'on ne rogne
	   rien. Le « max » garde une bande lisible sur écran étroit ; le « min »
	   empêche le décor d'occuper une bannière courte en entier.
	   🔴 18.08.2026, montagnes AGRANDIES EN HAUTEUR à sa demande : le viewBox
	   est passé de 1200 × 130 à 1200 × 192 (dessin redessiné, toutes les
	   ordonnées multipliées par 192/130) et la hauteur CSS de 10,8vw à 16vw.
	   Les deux ont bougé ENSEMBLE : 130/1200 = 10,8 % et 192/1200 = 16 %.
	   Changer l'un sans l'autre étirerait ou rognerait le dessin — c'est
	   exactement le piège CSS-22/CSS-23, et il se mesure : le rapport
	   largeur/hauteur de la boîte doit rester égal à celui du viewBox. */
	/* 🔴 80 % (18.08.2026, 2ᵉ passe). Le plafond n'est plus le vrai remède :
	   c'est la HAUTEUR MINIMALE des bandeaux (`.cas-bandeau`, section 17) qui
	   garantit désormais que le décor n'est jamais rogné — il fallait 20vw de
	   bannière pour 16vw de décor à 80 %, la min-height en donne 26vw. Ce
	   plafond ne reste qu'en filet de sécurité, pour un gabarit qu'on n'aurait
	   pas prévu. Relevé après : première unité du viewBox encore visible = 0
	   sur les 26 pages à bannière, contre 56,7 (Contact, Mentions…) et 82,9
	   (404) avant. */
	height: min(max(106px, 16vw), 80%);
	z-index: 0;
	color: var(--cas-signal);
	/* 🔴 0,4 et pas 0,5 : MESURÉ. À 0,5, un trait de crête passant sous une
	   carte de chiffres de l'accueil composait un fond de (138, 61, 51), et
	   l'étiquette #c9bcb6 y tombait à 4,06 — sous le seuil de 4,5. À 0,4 le
	   pire fond de toute la bande vaut (116, 54, 45) : 4,92 pour l'étiquette,
	   9,10 pour un titre blanc. Mesure faite en composant réellement les
	   couches sur un canevas, étalonnée sur le fond nuit (22, 17, 15).
	   🔴 18.08.2026 — la valeur passe à 0,55 à sa demande (« partout augmente
	   le contraste ») et QUITTE cette règle : elle se règle désormais dans
	   :root, section « CONTRASTE DES DÉCORS ». La mesure ci-dessus reste le
	   garde-fou : 0,55 est au-dessus du 0,5 qui avait fait tomber l'étiquette
	   à 4,06, et doit être REVÉRIFIÉE page par page avant d'être tenue pour
	   acquise. C'est une valeur d'ouverture, pas une valeur validée. */
	opacity: var(--cas-decor-montagnes);
	pointer-events: none;
	fill: none;
	stroke: currentColor;
	stroke-linecap: round;
	stroke-linejoin: round;
	/* Les crêtes émergent du fond et s'y refondent : aucun bord franc ne
	   vient couper la bannière en deux.
	   ⚠ 84 % et non 76 % depuis le 18.08.2026 : le fondu du bas commençait
	   pile là où le drapeau de la butte se termine (y = 154 sur 192, soit
	   80 %), et lui mangeait son quart inférieur. Le bas reste fondu, sur
	   16 % au lieu de 24 %.
	   ⚠ Et 6 % et non 30 % en haut, même jour, 2ᵉ passe : le fondu du haut
	   couvrait toute la zone des sommets. Le drapeau planté sur la POINTE LA
	   PLUS ÉLEVÉE (y = 10 à 44) n'y aurait laissé passer que 17 à 76 % de son
	   encre — un fantôme. Ce fondu n'a plus lieu d'être : la min-height des
	   bandeaux empêche désormais tout rognage par le haut, donc il n'y a plus
	   de bord franc à adoucir, et rien n'est dessiné au-dessus de y = 10.
	   ⚠ Conséquence mesurée : les crêtes du haut ne sont plus atténuées. Le
	   contraste a été REVÉRIFIÉ page par page après ce changement, c'est lui
	   qui a fixé les opacités du drapeau du sommet. */
	-webkit-mask-image: linear-gradient(to bottom, transparent 0%, #000 6%, #000 84%, transparent 100%);
	mask-image: linear-gradient(to bottom, transparent 0%, #000 6%, #000 84%, transparent 100%);
}

/* ⚠ Les opacités des deux plans n'ont PAS bougé le 18.08.2026, alors même que
   le contraste global montait. C'est voulu : elles se multiplient par celle du
   calque, et les monter aussi aurait donné +78 % au lieu de +37 %, en écrasant
   au passage la différence de profondeur entre le lointain et le proche —
   laquelle est le seul moyen qu'a un dessin au trait de suggérer la distance.
   Elles restent réglables depuis :root. */
.cas-montagnes__lointain {
	stroke-width: 1.1;
	opacity: var(--cas-decor-lointain);
	fill: currentColor;
	fill-opacity: var(--cas-decor-lointain-fond);
}

.cas-montagnes__proche {
	stroke-width: 1.6;
	opacity: var(--cas-decor-proche);
	fill: currentColor;
	fill-opacity: var(--cas-decor-proche-fond);
}

.cas-montagnes__neige {
	stroke-width: 1.8;
	fill: none;
	opacity: var(--cas-decor-neige);
}

/* --- Le drapeau suisse planté sur une crête du plan proche --------------- */
/* Demandé le 18.08.2026. Il est DANS le groupe « proche », donc il hérite du
   même trait et du même plan que les crêtes : c'est le sommet qui le porte,
   pas un objet posé par-dessus le dessin.
   ⚠ Position choisie PAR LA MESURE, pas au jugé. Trois contraintes, et une
   seule zone les satisfait toutes — la butte d'avant-plan de x = 430 :
     1. LE MASQUE. Le fondu du haut laisse passer 0 % à y = 0 et 100 % à
        y = 58. La grande dent de x = 646 culmine à y = 35 : un drapeau
        planté dessus n'aurait laissé passer que 61 % de son encre, et son
        mât 24 %. À y = 110-154, le masque est à 100 %.
     2. LE ROGNAGE VERTICAL. Sur les bannières courtes, le plafond de
        hauteur se déclenche et « slice » coupe le HAUT du dessin. Mesurée
        page par page à 1710 px, la première unité encore visible vaut 82
        sur la 404, la pire de toutes. Un drapeau posé sur le sommet de
        x = 744 (y = 97) a été essayé : mesuré 42 % visible seulement sur
        « À propos ». D'où le haut du drapeau à y = 110, qui laisse 28
        unités de marge sur la page la plus défavorable.
     3. LE ROGNAGE LATÉRAL. Sur téléphone le dessin est mis à l'échelle de
        sa hauteur : il ne reste que 640 unités, centrées (x 280 à 920).
        x = 430 à 474 y tient avec 150 unités de marge.
   ⚠ Aucun sommet du tracé ne réunissait les trois — les vrais sommets sont
   tous trop hauts dans le viewBox. Une BUTTE d'avant-plan a donc été
   ajoutée au plan proche pour porter le mât : c'est une crête du dessin,
   pas un socle décoratif. */
.cas-montagnes__hampe {
	stroke-width: 2.2;
	stroke-linecap: round;
	fill: none;
}

/* 🔴 Les DEUX opacités qui suivent sont fixées PAR LA MESURE, exactement
   comme celle du calque l'avait été le 17.08 (bug n°59) — et il en a fallu
   trois passes, parce que la croix blanche est, par construction, le point le
   plus lumineux que le décor puisse produire.
     · croix à pleine opacité : pire fond de la bande (106, 102, 101) au lieu
       de (110, 45, 36), et le chapeau #c9bcb6 du blog ET de la page
       « Graphique » tombait à 3,03. Défauts RÉELS, relevés en ligne.
     · 0,50 / 0,35 : encore 4,28 sur « Graphique ».
     · 0,30 / 0,20 : 4,86 — soit le niveau déjà validé le 17.08 pour les
       crêtes elles-mêmes (4,89). Le drapeau n'est donc plus le facteur
       limitant du décor, il s'aligne dessus.
   Le trait du carré, lui, reste à pleine force : c'est de l'encre
   --cas-signal au même niveau que les crêtes, donc il n'ajoute aucun pixel
   plus clair que ce qui existait déjà. C'est LUI qui porte la forme ; les
   remplissages ne portent que la couleur. */
/* 🔴 18.08.2026 — les deux valeurs remontent à sa demande explicite (« les
   drapeaux »), à 0,35 et 0,45. On REVIENT donc, en connaissance de cause,
   au-dessus du palier « 0,50 / 0,35 » qui avait mesuré 4,28 sur « Graphique »
   — mais pas à pleine opacité, qui avait mesuré 3,03. Ces deux valeurs sont
   les PREMIÈRES à revoir si une mesure passe sous 4,5 : ce sont elles qui
   produisent le pixel le plus clair de tout le décor, et le chapeau #c9bcb6
   du blog et de « Graphique » est le texte qui les rencontre. */
.cas-montagnes__drapeau {
	stroke-width: 1.8;
	stroke: currentColor;
	fill: currentColor;                  /* --cas-signal : le rouge du drapeau */
	fill-opacity: var(--cas-drapeau-carre);
}

/* La croix blanche reprend le jeton de titre de bannière, comme partout
   ailleurs dans cette feuille — aucun blanc en dur hors repli. */
.cas-montagnes__croix {
	stroke: none;
	fill: var(--wp--custom--banniere--titre, #ffffff);
	fill-opacity: var(--cas-drapeau-croix);
}

/* Sur téléphone, le dessin est vu de plus près (il est rogné) : on l'allège
   pour qu'il ne concurrence pas le titre. */
@media (max-width: 900px) {
	/* Sur téléphone, 16vw ne ferait que 62 px : la bande serait un filet.
	   On la grossit — le dessin est alors mis à l'échelle de la HAUTEUR et
	   rogné sur les côtés, ce qui est exactement l'effet voulu (on est plus
	   près des crêtes).
	   🔴 30vw et non plus 22vw (18.08.2026) : à viewBox constant, garder 22vw
	   aurait laissé les montagnes EXACTEMENT à leur taille d'avant sur
	   téléphone — la boîte étant pilotée par sa hauteur, c'est elle, et non le
	   viewBox, qui décide de ce qu'on voit. Mesuré : à 30vw / 390 px la bande
	   passe de 86 px à 117 px et l'on voit 640 unités du viewBox (x 280 à 920),
	   ce qui garde le drapeau (x 744 à 780) entier. */
	.cas-montagnes { height: min(max(94px, 30vw), 52%); opacity: var(--cas-decor-montagnes-mobile); }
}


/* --- 8 ter. LES MONTAGNES DERRIÈRE LE MENU — pages de carte -------------

   Demandé le 18.08.2026 : « dans les pages avec les cartes, là où y a que le
   menu en haut, ajoute aussi les montagnes derrière sur toute la longueur ».

   Ces quatre pages (carte interactive, carte de déploiement, carte de débit,
   Speedtest — celles qui portent .cas-bandeau-carte) n'ont pas de bannière :
   leur décor se réduisait aux ondes du logotype. Le script y injecte donc la
   MÊME silhouette, dans la rangée du menu, en fond.

   🔴 CE QUI NE DOIT PAS BOUGER. La carte se dimensionne sur la position de son
   ancre (`gap = position absolue de #cas-root`) : tout pixel ajouté au-dessus
   d'elle lui est retiré. Le décor est donc en POSITION ABSOLUE dans la rangée
   — hauteur nulle en flux, aucune marge, aucun rembourrage. La barre garde sa
   hauteur exacte, et la marge nulle entre bandeau et carte (bug CSS-21) n'est
   pas réintroduite.

   🔴 SILHOUETTE ENTIÈRE, RÉDUITE ET RÉPÉTÉE — 2ᵉ passe, 18.08.2026, à sa
   demande : « faut réduire la taille des montagnes pour qu'on les voie bien et
   qu'elles ne soient pas en dehors de l'écran, par contre rajoute des
   montagnes sur tout l'espace horizontal disponible ».

   La première version recadrait le dessin sur une bande de crêtes et le
   laissait déborder : les drapeaux sortaient de l'écran. On ne rogne plus DU
   TOUT. Le dessin entier — drapeau du sommet compris — est mis à l'échelle de
   la HAUTEUR de la barre, ce qui le rend petit, puis RÉPÉTÉ côte à côte pour
   couvrir la largeur.

   Étendue verticale retenue : y = 8 à 192, soit 184 unités. Le 8 n'est pas
   arrondi au jugé — le point le plus haut du dessin est le drapeau du sommet,
   dont le rectangle commence à y = 10 et dont le trait, large de 1,8, déborde
   de 0,9 vers le haut : le sommet réel de l'encre est à y = 9,1. On garde une
   unité d'air. Une tuile fait donc 1200 × 184, soit un rapport de 6,52:1.

   🔴 AUCUNE DÉFORMATION (leçon CSS-23). `slice` met à l'échelle DE FAÇON
   UNIFORME. Et le viewBox est délibérément BEAUCOUP plus allongé que la barre
   (12 tuiles = 14400 × 184, soit 78:1, contre 28:1 pour une barre de 1710 px
   et 7,7:1 pour une barre de téléphone) : comme `slice` prend le plus grand
   des deux facteurs, c'est TOUJOURS la hauteur qui commande, et c'est la
   largeur qui se fait rogner. La silhouette tient donc entière dans la hauteur
   de la barre, à toutes les largeurs. Vérifié aux deux bouts :
       barre 1710 × 61 → échelle 61/184 → tuile de 398 px → 4,3 tuiles visibles
       barre  386 × 50 → échelle 50/184 → tuile de 326 px → 1,2 tuile visible
   Douze tuiles couvrent jusqu'à 4770 px de barre. Au-delà, c'est la largeur
   qui reprendrait la main et le haut du dessin serait rogné : c'est le seul
   régime où les drapeaux se perdraient, et il demande un écran de 4,8 m.

   🔴 LES TUILES SE RACCORDENT PARCE QU'UNE SUR DEUX EST MIROIR. Le dessin ne
   boucle pas : son bord gauche est à y = 130 / 171 et son bord droit à
   y = 112 / 130. Les aboucher tels quels ferait une MARCHE à chaque jointure.
   En retournant horizontalement une tuile sur deux, chaque jointure met face à
   face deux fois la MÊME abscisse du dessin — donc exactement la même
   ordonnée. La ligne de crête est continue d'un bout à l'autre de la barre,
   sans une seule marche. La croix suisse étant symétrique, un drapeau miroir
   reste un drapeau suisse ; seul le sens du vent alterne.

   ⚠ Ce qui SUBSISTE aux jointures : le tracé de chaque plan est une forme
   FERMÉE (il redescend en x = 0 et x = 1200 jusqu'à y = 192 pour porter son
   remplissage), et ces deux segments verticaux sont eux aussi tracés. À chaque
   jointure, deux d'entre eux se superposent exactement — même position, même
   géométrie, donc aucune marche, mais l'encre s'y compose deux fois : l'alpha
   local passe de 0,378 à 0,613 sur une ligne large de 1,6 unité, soit 0,43 px
   sur téléphone et 0,53 px sur écran large. C'est sous le pixel, et c'est
   MESURABLE — si la jointure se voit, le remède est de scinder chaque plan en
   deux tracés (un fermé rempli sans trait, un ouvert tracé sans remplissage),
   ce qui n'a pas été fait ici pour ne pas dupliquer les coordonnées du dessin
   et risquer qu'elles divergent de celles des bannières.

   ⚠ AUCUNE ONDE AJOUTÉE. La règle « une seule source d'ondes par page » tient :
   ces pages gardent celles du logotype, et n'ont toujours PAS d'antenne. */

/* L'hôte : la rangée du menu devient un contexte de positionnement.
   ⚠ Pas d'`overflow: hidden` ici — il découperait le sous-menu déroulant de
   « PLUS ». Inutile de toute façon : un SVG rogne déjà son contenu à sa propre
   zone de dessin. */
body:has(.cas-bandeau-carte) #header [data-row="top"],
body:has(.cas-bandeau-carte) #header [data-row="top:boxed"] {
	position: relative;
}

/* Le décor : toute la rangée, derrière tout.
   ⚠ `inset: 0` et non `100vw` : la rangée EST déjà pleine largeur (c'est son
   conteneur interne qui est en retrait), donc on épouse la barre sans risquer
   les 15 px de débordement horizontal que 100vw ajoute quand la barre de
   défilement occupe de la place.
   🔴 SÉLECTEUR DOUBLÉ, `.cas-montagnes.cas-montagnes--menu`, ET C'EST UNE
   CORRECTION MESURÉE. Il était d'abord porté par #header — ce qui marchait
   tant que le décor ne vivait que dans l'en-tête. Depuis qu'un exemplaire est
   posé dans `.cas-bandeau-carte` (voir plus bas), cet exemplaire-là n'est PAS
   sous #header : il retombait sur les règles de bannière et se retrouvait haut
   de 29 px au lieu de 56, calé en bas, et à l'opacité des montagnes mobiles
   (0,5) au lieu de la sienne (0,42). Relevé en ligne dans un iframe de 386 px.
   Répéter la classe porte la spécificité à (0,2,0), ce qui bat `.cas-montagnes`
   et sa redéfinition mobile — toutes deux à (0,1,0) — PARTOUT, sans dépendre
   d'un ancêtre ni de l'ordre des règles. */
.cas-montagnes.cas-montagnes--menu {
	position: absolute;
	inset: 0;
	/* Les deux écritures disent la même chose et se confirment l'une l'autre :
	   si une feuille tierce imposait une largeur d'icône aux SVG de l'en-tête,
	   `inset` seul ne la battrait pas (une largeur explicite l'emporte sur
	   `right`). */
	width: 100%;
	height: 100%;
	z-index: 0;
	opacity: var(--cas-decor-montagnes-menu);
	pointer-events: none;
	/* Pas de fondu : le masque des bannières efface le haut et le bas du
	   dessin, or ici la bande visible fait 38 à 95 unités — il n'en resterait
	   presque rien. Le bord de la barre suffit à couper net. */
	-webkit-mask-image: none;
	mask-image: none;
}

/* Le menu repasse devant son décor. Le conteneur est le seul autre enfant de
   la rangée : lui donner z-index 1 suffit, logo, liens et bouton compris. */
body:has(.cas-bandeau-carte) #header [data-row="top"] > .ct-container,
body:has(.cas-bandeau-carte) #header [data-row="top:boxed"] > .ct-container {
	position: relative;
	z-index: 1;
	/* ⚠ Sinon le fond blanc que Blocksy peint sur CE conteneur en mode mobile
	   épinglé (voir la règle [data-transparent-row="no"] plus haut) recouvrirait
	   le décor entre 768 px et le seuil mobile de Blocksy. La rangée, elle,
	   porte déjà --cas-bandeau-fond : rien ne manque à l'écran. */
	background-color: transparent;
}

/* --- QUELLE BARRE NOIRE ? PAS LA MÊME SELON LA LARGEUR ------------------

   🔴 MESURÉ le 18.08.2026 dans un iframe de 386 px, sur la prod, parce que le
   propriétaire signalait depuis son téléphone : « le menu noir descend et les
   montagnes/logo restent en haut ». Relevé, au repos :

       ≥ 768 px   .cas-bandeau-carte   height 0, fond transparent
                  [data-row="top"]     h 61, fond --cas-bandeau-fond   ← LA BARRE
       ≤ 767 px   [data-row="top:boxed"]  h 50, fond TRANSPARENT (règle plus bas)
                  .cas-bandeau-carte      h 56, fond --cas-bandeau-fond ← LA BARRE

   Autrement dit, sur téléphone la barre noire n'est PAS l'en-tête : c'est le
   bandeau de titre, qui vit dans le CONTENU et défile avec lui, tandis que
   l'en-tête, lui, est `position: absolute` et transparent, posé par-dessus.
   Les deux se superposent exactement au repos (tous deux à y = 46), ce qui les
   fait passer pour un seul objet — jusqu'au premier défilement, où ils se
   séparent. Le décor logé dans l'en-tête restait donc avec l'en-tête pendant
   que la barre noire s'en allait : c'est très exactement ce qu'il a vu.

   ⚠ Le diagnostic « c'est le conteneur sticky qui bouge » a été écarté PAR LA
   MESURE : `[data-sticky]` passe bien en `position: fixed` quand Blocksy
   épingle (relevé `data-sticky="fixed:shrink"` sur écran large), mais la
   rangée est son ENFANT — un décor posé dans la rangée suit donc l'épinglage
   de lui-même. Ce n'était pas là qu'était le défaut.

   Correction : le script pose le décor dans les DEUX hôtes possibles, et le
   CSS n'en montre qu'un — celui qui peint réellement le noir à cette largeur.
   Le décor fait alors corps avec la barre par CONSTRUCTION, sans rien savoir
   de la mécanique d'épinglage de Blocksy. */

/* Sur écran large, la barre est la rangée : l'exemplaire du bandeau ne sert
   pas (il y serait de toute façon dans une boîte de hauteur nulle). */
@media (min-width: 768px) {
	.cas-bandeau-carte > .cas-montagnes--menu { display: none; }
}

/* Sur téléphone, la barre est le bandeau : c'est l'exemplaire de l'en-tête qui
   ne sert pas. */
@media (max-width: 767px) {
	#header .cas-montagnes--menu { display: none; }

	/* L'hôte du décor. `position: relative` seul — aucune hauteur, aucune
	   marge, aucun rembourrage ne change : le bandeau garde ses 56 px et
	   #cas-root reste à 102 px du haut (mesuré avant/après). */
	.cas-bandeau-carte { position: relative; }

	/* Le titre repasse devant le décor. Sur écran large il est déjà en
	   `position: absolute; z-index: 3` (la pastille), donc rien à faire. */
	.cas-bandeau-carte__titre { position: relative; z-index: 1; }
}


/* ==========================================================================
   8 quater. L'ÉCRAN SOUS LES TEXTES POSÉS SUR LE DÉCOR

   Mesure du 18.08.2026 sur la prod, décors montés (géométrie réelle,
   isPointInStroke/isPointInFill + composition sur canevas) : quatre textes
   réels passaient sous le seuil de 4,5 —

       accueil  .cas-stat__valeur     2,96  et  3,71
       accueil  .cas-stat__libelle    3,84
       blog     .page-description     3,97   (#c9bcb6)

   Le propriétaire veut le contraste des décors : on n'en redescend AUCUN. On
   pose à la place un écran nuit translucide, LOCAL, sous les seuls textes en
   défaut. Son alpha est `--cas-ecran-texte`, réglable seul (voir :root).

   🔴 AUCUNE PROPRIÉTÉ DE MISE EN PAGE N'EST TOUCHÉE. Pas de padding, pas de
   marge, pas de largeur : uniquement `background-image`, `background-color`,
   `border-radius` et `box-shadow`, qui sont toutes des propriétés de PEINTURE.
   La géométrie ne peut donc pas bouger — ce n'est pas une mesure, c'est une
   propriété du modèle de rendu.

   ⚠ C'est pour cela que le rembourrage demandé est rendu par un `box-shadow`
   à étalement plutôt que par un `padding`. Un padding sur un bloc en
   `max-width: 62ch` (les deux chapeaux) rétrécit sa boîte de contenu d'autant
   et REDÉCOUPE le paragraphe : les retours à la ligne se déplacent. Une marge
   négative ne le rattrape pas, puisque `max-width` replafonne aussitôt la
   boîte. L'étalement d'ombre donne le même liseré, en ne participant à aucun
   calcul de mise en page.
   ========================================================================== */

/* --- Les cartes de chiffres de l'accueil ---------------------------------

   🔴 background-IMAGE, et non background-color, ET C'EST LE POINT CLÉ : la
   carte porte DÉJÀ un fond, `rgba(10, 26, 36, 0.55)` (section 2). Le remplacer
   par un écran de même alpha n'aurait strictement rien changé au contraste —
   même opacité, seule la teinte aurait viré. Ici on AJOUTE un calque par
   dessus : les deux transmissions se multiplient, et le décor ne passe plus
   qu'à (1 − 0,55) × 45 % ≈ 20 %.

   ⚠ `.cas-stat:hover` emploie le raccourci `background`, qui remet
   `background-image` à `none` : le survol est cité ici, sinon l'écran
   disparaissait sous le doigt ou la souris — et avec lui la lisibilité. */
.cas-hero .cas-stat,
.cas-hero .cas-stat:hover {
	background-image: linear-gradient(
		rgba(22, 17, 15, var(--cas-ecran-texte)),
		rgba(22, 17, 15, var(--cas-ecran-texte)));
}

/* --- Les chapeaux posés sur les crêtes -----------------------------------

   `.page-description` est le chapeau des bandeaux natifs de Blocksy — blog,
   archives ET articles (vérifié dans le rendu : c'est bien la même classe sur
   `body.single`). `.cas-bandeau__chapeau` est son équivalent sur les pages à
   bandeau construit par le script. Les deux vivent dans un hôte qui porte les
   montagnes ; aucun autre texte de ces bandeaux n'est en défaut.

   ⚠ `rgba()` et non `color-mix()` : la valeur ne contient de `var()` que dans
   la fente ALPHA, où il n'est qu'un nombre. Un `color-mix(… calc(var(…) *
   100%) …)` qui échouerait rendrait la déclaration invalide À LA VALEUR
   CALCULÉE — et dans ce cas une déclaration de repli placée avant ne reprend
   PAS la main, contrairement à ce qu'on attend d'un repli CSS. L'écran
   disparaîtrait en silence. Pour une correction de lisibilité, le mode de
   défaillance prime sur l'élégance.
   ⚠ 22, 17, 15 = #16110f = `custom.nuit` de theme.json, la seule valeur en dur
   de cette feuille et elle est ici volontaire. Si `nuit` change dans
   theme.json, ces deux triplets doivent suivre. */
.hero-section .page-description,
.cas-bandeau__chapeau {
	background-color: rgba(22, 17, 15, var(--cas-ecran-texte));
	border-radius: 12px;
	/* Le « rembourrage » : 0,45em tout autour, peint et non mis en page. */
	box-shadow: 0 0 0 0.45em rgba(22, 17, 15, var(--cas-ecran-texte));
}


/* ==========================================================================
   9. En-tête

   ⚠ PIÈGE, vérifié à la mesure. La classe « .ct-header » désigne DEUX
   éléments, et le panneau hors-champ du menu mobile vient EN PREMIER dans le
   document. Tout ce qu'on écrit sur « .ct-header » habille donc un panneau
   invisible. Le vrai en-tête est « #header », et ce n'est même pas lui qui
   peint le fond : c'est sa rangée interne, div[data-row="top"], qui porte le
   blanc opaque de Blocksy. C'est elle qu'il faut viser, avec l'identifiant
   #header pour passer devant les réglages du thème.

   Sur l'accueil, cette rangée blanche s'imposait sur une page devenue sombre.
   On lui donne le fond de la page. Ailleurs, le contenu est encore clair :
   le blanc de Blocksy y est le bon choix, on n'y touche pas.
   ========================================================================== */

#header [data-row="top"] {
	transition: background-color 0.35s ease, box-shadow 0.35s ease;
}

/* --- L'ÉTAT DE L'EN-TÊTE EST CELUI DE BLOCKSY, PAS LE NÔTRE ---

   Blocksy gère déjà exactement le comportement voulu, et il le PUBLIE dans un
   attribut. Il suffit de le lire :

       data-transparent-row="yes"  →  en haut de page, en-tête transparent
       data-transparent-row="no"   →  épinglé au défilement, fond peint

   C'est son fond épinglé qui était BLANC, et c'est le seul défaut à corriger.
   La première version peignait un fond sombre EN PERMANENCE : la bannière ne
   se voyait plus derrière l'en-tête, et l'épinglage semblait actif dès le
   chargement. Signalé par le propriétaire, vérifié : l'attribut bascule bien
   yes → no → yes au fil du défilement.

   Les couleurs de liens, elles, restent posées dans tous les états : elles
   doivent tenir aussi bien sur la bannière sombre que sur l'en-tête épinglé. */

body.home #header [data-row="top"],
body:has(.cas-page-sombre) #header [data-row="top"],
body.blog #header [data-row="top"],
body.archive #header [data-row="top"]
{
	--theme-link-initial-color: var(--wp--custom--banniere--titre, #fff);
	--theme-link-hover-color: var(--cas-signal);
	--theme-text-color: var(--wp--custom--banniere--texte, #c9bcb6);
}

/* ① ACCUEIL ET BLOG — la bannière est sombre : au repos, on ne peint RIEN,
   et l'en-tête transparent de Blocksy laisse voir les ondes et l'antenne.
   Le fond n'apparaît qu'une fois épinglé.

   Le blog a rejoint ce groupe le 16.08.2026, à la demande du propriétaire :
   « faudrait utiliser le même principe que la page d'accueil, avec les
   antennes et le menu transparent sauf quand on glisse ». */
/* Le FOND de l'état épinglé est servi par Blocksy depuis le 16.08.2026
   (réglage stickyHeaderBackground, rgba(22,17,15,.92)) : plus besoin de le
   peindre ici, ni de répéter la règle pour six contextes de page. Ne restent
   que le flou et le liseré, que le Customizer ne sait pas exprimer. Les pages
   de carte l'annulent plus bas (backdrop-filter: none), comme avant. */
#header [data-row][data-transparent-row="no"] {
	-webkit-backdrop-filter: saturate(1.4) blur(16px);
	backdrop-filter: saturate(1.4) blur(16px);
	box-shadow: inset 0 -1px 0 rgba(255, 255, 255, 0.09), 0 14px 34px -22px rgba(0, 0, 0, 0.9);
}

/* ⚠ EXCEPTION VÉRIFIÉE (16.08.2026, sondage du pixel) : dans l'état épinglé,
   la feuille GÉNÉRÉE de Blocksy peint la rangée en color8 — blanc — par-dessus
   stickyHeaderBackground :
       [data-header*="type-1"] .ct-header [data-sticky*="yes"] [data-row*="top"]
           { background-color: var(--theme-palette-color-8) }
   Aucun réglage n'expose cette couleur, et color8 ne peut pas devenir nuit
   (CSS-19 : il sert aussi de texte aux boutons). On neutralise donc la rangée ;
   le fond épinglé reste celui, NATIF, du conteneur [data-sticky]. L'identifiant
   #header suffit à battre la feuille générée, sans !important. */
#header [data-sticky] [data-row] { background-color: transparent; }

/* ⚠ EXCEPTION MOBILE, VÉRIFIÉE (16.08.2026, iframe 390 px défilée pour de
   vrai) : sous son seuil mobile, Blocksy n'applique PAS stickyHeaderBackground
   ([data-sticky] y reste transparent) et le conteneur interne de la rangée
   « boxed » repeint du BLANC — le troisième peintre de WP-12. On peint donc le
   conteneur, à la même valeur que le réglage natif du bureau. Pas de condition
   de largeur : l'attribut top:boxed n'existe qu'en mode mobile (WP-19). */
#header [data-row="top:boxed"][data-transparent-row="no"] > .ct-container {
	background-color: color-mix(in srgb, var(--cas-nuit) 92%, transparent);
}

/* ② PAGES DE CARTE — le fond, lui, est CLAIR : la carte occupe tout l'écran.
   Un en-tête transparent y rendrait les liens blancs illisibles. Il garde
   donc son fond dans les deux états. */
/* ⚠ ON PEINT LA RANGÉE, PAS SON CONTENEUR.

   Le conteneur est en retrait de 16 à 18 px de chaque côté : le peindre lui
   laissait deux bandes non peintes sur les bords, visibles comme des marges
   claires de part et d'autre du menu. Signalé par le propriétaire le
   16.08.2026, mesuré à 898 px (18 px) et 788 px (16 px).

   Vérifié auparavant sur une page non refaite : Blocksy ne peint nativement
   NI la rangée NI le conteneur — il n'y avait donc aucune barre flottante
   voulue à préserver.

   ⚠ LES DEUX RANGÉES, sans condition de largeur.

   Blocksy bascule sur sa rangée mobile [data-row="top:boxed"] à une largeur
   SUPÉRIEURE à 768 px — mesuré : à 776 px il l'affiche déjà. Nos règles de
   bureau, elles, démarrent à 768. Dans cette bande, la barre de titre était
   masquée (règle bureau) ET la rangée affichée n'était peinte par personne
   (elle n'était traitée que sous 768) : menu transparent sur carte claire,
   donc illisible. Signalé par le propriétaire le 16.08.2026.

   On ne cherche pas à retrouver le seuil exact de Blocksy — il changerait à
   la prochaine mise à jour. On peint les DEUX rangées, et c'est le mobile
   qui, lui, les rend transparentes plus bas. */
body:has(.cas-page-sombre) #header [data-row="top"],
body:has(.cas-page-sombre) #header [data-row="top:boxed"] {
	/* MÊME fond que la barre mobile, et opaque : l'en-tête est ici dans le
	   flux, rien ne passe derrière, un flou d'arrière-plan n'aurait rien à
	   flouter. C'est ce qui rend les deux écrans identiques. */
	background-color: var(--cas-bandeau-fond);
	-webkit-backdrop-filter: none;
	backdrop-filter: none;
	box-shadow: inset 0 -1px 0 rgba(255, 255, 255, 0.06);
}

/* --- Les ondes du logo -------------------------------------------------

   Le logotype porte déjà une antenne dessinée avec ses arcs. On la prolonge :
   deux anneaux naissent à sa pointe et traversent la barre de menu.

   ⚠ On anime le DIAMÈTRE, pas un transform: scale(). Une mise à l'échelle
   multiplie aussi la bordure : un trait de 1 px à scale(30) devient une bande
   de 30 px. Le piège avait déjà été payé sur les ondes de la page.

   Le centrage passe par translate(-50%, -50%), qui reste juste quelle que
   soit la taille atteinte — une marge négative, elle, devrait suivre le
   diamètre animé.

   L'ancrage est en POURCENTAGE (87 % de la largeur du logotype) : l'antenne
   se trouve à sa pointe droite, et la valeur reste vraie quand le logo
   rétrécit sur téléphone. Mesuré : logo 115 px de large, antenne à 100 px.

   ⚠ UNIQUEMENT SUR LES PAGES DE CARTE. Demandé le 16.08.2026 : l'accueil a
   déjà ses propres ondes, qui montent de l'antenne de la bannière et
   traversent toute la page. Deux systèmes d'ondes superposés s'y annulaient
   visuellement. Le marqueur .cas-page-sombre ne vit que sur ces pages.

   ⚠ ELLES NE DOIVENT PAS DÉBORDER SUR LE CORPS DE PAGE — ET RESTER RONDES.

   Première tentative : des ellipses, hauteur plafonnée à 56 px. Elles
   tenaient dans la barre, mais l'onde s'écrasait en s'éloignant, ce qu'une
   onde ne fait pas. Défaut signalé le 16.08.2026.

   Solution retenue : le cercle reste un CERCLE (width = height), et on n'en
   affiche que la tranche qui tient dans la barre, par clip-path. Ce qu'on voit
   alors, ce sont deux arcs de cercle qui s'écartent — la forme réelle d'une
   onde traversant un couloir. La géométrie n'est jamais déformée, seulement
   masquée.

       clip-path: inset(calc(50% - 28px) 0 …)

   Le pourcentage se calcule sur la boîte du pseudo-élément, donc il SUIT le
   diamètre animé : la fenêtre visible reste haute de 56 px quelle que soit la
   taille atteinte. Le max(0px, …) évite un retrait négatif tant que le cercle
   est plus petit que la barre.

   Préféré à « overflow: hidden » sur la rangée, qui aurait aussi découpé le
   sous-menu déroulant de « PLUS ». */

body:has(.cas-page-sombre) #header .site-branding {
	position: relative;
}

/* ⚠ UNIQUEMENT sur les pages de carte. Une extension automatique des règles
   d'en-tête vers le blog, les pages et les articles avait emporté celle-ci :
   l'onde apparaissait dans le menu partout. Or ailleurs, l'antenne de la
   bannière émet déjà les siennes — deux sources d'ondes se superposaient.
   Signalé par le propriétaire le 16.08.2026. Ne pas réélargir ce sélecteur. */
body:has(.cas-page-sombre) #header .site-branding::before,
body:has(.cas-page-sombre) #header .site-branding::after {
	content: "";
	position: absolute;
	left: 87%;
	top: 50%;
	transform: translate(-50%, -50%);
	border: 1px solid var(--cas-signal);
	border-radius: 50%;
	opacity: 0;
	pointer-events: none;   /* ne jamais gêner le clic sur le logo */
	z-index: 0;
	/* La tranche visible : 56 px de haut, centrée, quel que soit le diamètre. */
	clip-path: inset(max(0px, calc(50% - 28px)) 0 max(0px, calc(50% - 28px)) 0);
	animation: cas-onde-logo 6s cubic-bezier(0.3, 0, 0.7, 1) infinite;
}

/* Le second anneau part à mi-parcours : l'émission paraît continue
   avec deux éléments au lieu d'une file d'attente. */
body:has(.cas-page-sombre) #header .site-branding::after {
	animation-delay: 3s;
}

/* Un cercle, et rien qu'un cercle : la hauteur suit toujours la largeur.
   C'est le clip-path qui le confine, pas la géométrie qui se déforme. */
/* ⚠ Les opacités sont lues dans :root (section « CONTRASTE DES DÉCORS »).
   Une variable dans un @keyframes est résolue sur l'ÉLÉMENT animé, pas au
   moment où la règle est écrite : ces deux pseudo-éléments héritent donc bien
   des valeurs de :root. Valaient 0,55 et 0,30 en dur jusqu'au 18.08.2026. */
@keyframes cas-onde-logo {
	0%   { width: 8px;    height: 8px;    opacity: 0; }
	7%   { width: 40px;   height: 40px;   opacity: var(--cas-onde-logo-naissance); }
	35%  { width: 700px;  height: 700px;  opacity: var(--cas-onde-logo-course); }
	100% { width: 2000px; height: 2000px; opacity: 0; }
}

/* Les couleurs du menu (liens blancs, survol et élément actif au signal,
   trait actif) sont réglées NATIVEMENT dans le constructeur d'en-tête depuis
   le 16.08.2026 — menuFontColor, menuIndicatorColor et leurs variantes
   d'état transparent. Les 54 sélecteurs qui les forçaient ici ont été retirés. */

/* Le FOND du sous-menu déroulant vient du réglage headerDropdownBackground
   depuis le 16.08.2026. Ne reste ici que sa bordure, que le Customizer ne
   sait pas exprimer. */
body.home #header .sub-menu,
body:has(.cas-page-sombre) #header .sub-menu,
body.blog #header .sub-menu,
body.page:not(:has(.cas-page-sombre)) #header .sub-menu,
body.single #header .sub-menu,
body.archive #header .sub-menu
{
	border: 1px solid rgba(255, 255, 255, 0.08);
}

/* --- MOBILE : la rangée « boxed » ---

   En dessous du seuil mobile, Blocksy n'affiche plus la rangée [data-row="top"]
   mais [data-row="top:boxed"]. Son FOND épinglé est désormais celui du réglage
   natif, comme sur écran large : il ne reste ici que la transition. */

#header [data-row="top:boxed"] {
	transition: background-color 0.35s ease, box-shadow 0.35s ease;
}

/* --- Le panneau coulissant du menu mobile ---

   C'est l'élément que « .ct-header » désignait par erreur. Blocksy le sert déjà
   sombre, mais dans un gris BLEUTÉ — rgba(18, 21, 25, 0.98) — étranger à la
   palette chaude du site : deux noirs différents se voient à la jonction.
   Et son élément actif porte encore le turquoise.

   Non restreint à l'accueil, volontairement : le panneau est le même partout et
   déjà sombre partout. Un menu rouge sur l'accueil et turquoise ailleurs serait
   plus incohérent que le défaut qu'on corrige. */

/* ⚠ Sélecteur volontairement lourd, établi à la mesure en deux temps :

   1. « #offcanvas .ct-panel-inner » (1,1,0) perd, même réinjecté en dernier —
      donc l'adversaire est plus spécifique que 1,1,0.
   2. « #offcanvas.ct-panel .ct-panel-inner » (1,2,0) gagnait dans un test
      injecté en fin de document, mais PERD depuis la feuille enfant : à
      spécificité égale, la feuille adverse est chargée après la nôtre.

   D'où html + body, qui portent la spécificité à (1,2,2) et retirent la
   question de l'ordre. Aucun !important n'est en jeu — un style en ligne
   simple passait déjà, ce qui l'exclut. */
html body #offcanvas.ct-panel .ct-panel-inner {
	background-color: color-mix(in srgb, var(--cas-nuit) 97%, transparent);
}

#offcanvas .current-menu-item > a,
#offcanvas .current_page_item > a,
#offcanvas .ct-menu-link:hover,
#offcanvas .ct-menu-link:focus-visible {
	color: var(--cas-signal);
}

/* Les sections pleine largeur ne doivent pas hériter du rembourrage
   horizontal du conteneur de Blocksy — .cas-shell s'en charge. */
.entry-content > .alignfull.cas-hero,
.entry-content > .alignfull.cas-section { padding-inline: 0; }

/* ==========================================================================
   9 bis. Page de la carte interactive

   ⚠ NE RIEN CASSER ICI. La carte est une application de 161 Ko servie par le
   raccourci [wpcode id="7898"], commune aux trois langues. Elle se dimensionne
   toute seule :

       gap = position absolue de #cas-root depuis le haut du document
       #cas-root { height: calc(100dvh - var(--cas-gap)) }

   et recalcule au chargement, au redimensionnement, huit fois toutes les
   250 ms après le chargement, plus un ResizeObserver sur <header>. Autrement
   dit : tout ce qu'on retire au-dessus d'elle lui est rendu automatiquement.

   ⚠⚠ COLLISION DE NOMS. Son script écrit les variables --cas-top et --cas-gap
   sur #cas-root. Nos 28 variables utilisent le même préfixe « cas- ».
   NE JAMAIS définir --cas-top ni --cas-gap dans cette feuille : la carte se
   replierait à une hauteur nulle, sur la page la plus consultée du site.
   ========================================================================== */

.cas-bandeau-carte {
	display: flex;
	align-items: flex-end;
	justify-content: center;
	min-height: 56px;             /* la hauteur d'origine, préservée */
	margin: 0;
	padding: 1.2rem;
	background-color: var(--cas-bandeau-fond);
}

/* Le réglage Blocksy « Espacement du contenu » est volontairement conservé
   pour les blocs Gutenberg ordinaires, mais il ne doit pas séparer la barre
   de titre de l'application. Sa règle est chargée après la nôtre ; le parent
   `.entry-content` apporte le cran de spécificité nécessaire. Mesuré avant
   correction : 24 px sur ordinateur et 18 px sur mobile. */
.entry-content > .cas-bandeau-carte {
	margin-block-end: 0;
}

.cas-bandeau-carte__titre {
	margin: 0;
	font-size: 12px;              /* sa taille : le H1 sert le référencement,
	                                 pas la lecture — il ne doit pas manger la carte */
	font-weight: 700;
	line-height: 1.25;
	text-align: center;
	color: var(--wp--custom--banniere--titre, #fff);
}

/* --- Sur écran large, le titre quitte le flux et se pose SUR la carte ---

   Demandé le 15.08.2026 : « sur pc on peut l'afficher par-dessus la carte en
   haut à gauche, par contre sur téléphone faut laisser où il est car j'ai
   optimisé pour gagner de la place. »

   La barre sortant du flux, #cas-root remonte de 56 px et sa hauteur suit —
   la carte gagne donc la place au lieu de la perdre. Le décalage de 4.75rem
   passe sous l'en-tête, avec ou sans la barre d'administration. */

/* --- Sur écran large : l'en-tête REPREND SA PLACE, la barre devient pastille

   Diagnostic du propriétaire, vérifié à la mesure : sur ces pages, l'en-tête
   transparent de Blocksy est activé —

       [data-device="desktop"]  position: absolute   data-transparent=""
       [data-row="top"]         data-transparent-row="yes"
       <header>                 hauteur en flux : 0

   — il ne prend donc AUCUNE place et se superpose en permanence, exactement
   comme une épingle qui ne se relâcherait jamais. La barre de 56 px n'était
   qu'un contournement : elle poussait le contenu sous l'en-tête.

   Première tentative de correction : sortir la barre du flux. La carte a gagné
   56 px, et 51 px de SES PROPRES contrôles sont passés sous l'en-tête — les
   boutons Salt / Swisscom / Sunrise devenaient inatteignables.

   La vraie correction est de rendre l'en-tête au flux. Il occupe alors ses
   61 px, le contenu commence dessous, et plus rien ne peut se cacher derrière.
   Le gain de hauteur est modeste (7 px), mais la carte redevient entièrement
   utilisable et le titre peut enfin flotter sur elle.

   ⚠ Sur téléphone, on ne touche à rien : la mise en page y est optimisée par
   le propriétaire et fonctionne. */

@media (min-width: 768px) {
	/* ⚠ TOUS les wrappers, pas seulement celui de bureau.

	   Blocksy en rend deux — [data-device="desktop"] et [data-device="mobile"] —
	   et masque celui qui ne sert pas. Entre 768 px et son propre seuil, c'est
	   le wrapper MOBILE qui est affiché : viser « desktop » ne touchait donc
	   qu'un élément de hauteur nulle, et l'en-tête visible restait en absolute.
	   Mesuré à 773 px : panneaux de classement et d'opérateurs masqués sur
	   38 px chacun. */
	body:has(.cas-bandeau-carte) #header > div[data-device] {
		position: relative;
	}

	/* Le titre flotte en HAUT AU CENTRE de la carte.

	   ⚠ Pas en haut à gauche. Ce coin était libre sur la carte interactive et
	   sur celle de déploiement — mais la carte de DÉBIT y place son panneau de
	   classement, et la pastille le recouvrait sur 168 × 29 px.

	   Bandes horizontales libres sous l'en-tête, relevées sur les trois cartes
	   à 1596 px de large :

	       interactive     0 → 1164
	       déploiement     0 → 1318
	       débit         196 → 1290
	       ──────────────────────────
	       commune       196 → 1164

	   Le centre y est confortablement inclus. La largeur est en outre plafonnée
	   pour réserver ~13 rem de chaque côté : la pastille ne peut donc atteindre
	   aucun panneau, même sur un écran étroit. Les applications de carte ancrent
	   toujours leurs contrôles aux COINS — le centre est la seule zone fiable.

	   ⚠ Le bandeau reste DANS LE FLUX, à hauteur nulle. Il sert uniquement de
	   point d'ancrage, et il se place naturellement juste sous l'en-tête,
	   c'est-à-dire au sommet exact de la carte. Le rendre absolu le rattachait
	   à #main-container, qui commence plus haut : la pastille atterrissait
	   alors dans la bande de l'en-tête, mesurée à 48 px au lieu de 109. */
	.cas-bandeau-carte {
		position: relative;
		height: 0;
		min-height: 0;
		padding: 0;
		overflow: visible;
		background-color: transparent;
	}

	.cas-bandeau-carte__titre {
		position: absolute;
		z-index: 3;
		top: 1rem;
		left: 50%;
		transform: translateX(-50%);
		/* 13 rem réservés de chaque côté, pour les panneaux de l'application. */
		max-width: min(34rem, calc(100vw - 26rem));
		margin: 0;
		padding: 0.34rem 0.9rem;
		border: 1px solid rgba(255, 255, 255, 0.14);
		border-radius: 999px;
		background-color: color-mix(in srgb, var(--cas-nuit) 72%, transparent);
		-webkit-backdrop-filter: blur(12px) saturate(1.3);
		backdrop-filter: blur(12px) saturate(1.3);
		box-shadow: 0 10px 30px -14px rgba(0, 0, 0, 0.9);
		font-size: 0.8125rem;
		text-align: center;
		/* Le titre s'enroule plutôt que d'être tronqué : il porte le
		   référencement, on n'en coupe pas un mot. */
		white-space: normal;
		line-height: 1.3;
	}
}

/* --- Sur téléphone, l'en-tête redevient transparent SUR CES PAGES ---

   Mesuré : le titre occupe la bande 68-83 px, l'en-tête 46-96 px. Ils se
   recouvrent entièrement. Si l'en-tête est opaque, le titre disparaît.

   C'est ainsi que la page fonctionnait à l'origine : un en-tête transparent
   posé sur la barre sombre, le titre se lisant au travers. En donnant à
   l'en-tête un fond sombre, on l'a masqué — un défaut introduit en croyant
   harmoniser. La barre fournit déjà le fond sombre : l'en-tête n'en a pas
   besoin ici, et les liens restent lisibles.

   Sur écran large la question ne se pose pas : la carte, elle, est claire,
   donc l'en-tête garde son fond sombre, et le titre flotte en dessous. */

@media (max-width: 767px) {
	body:has(.cas-bandeau-carte) #header [data-row="top:boxed"],
	body:has(.cas-bandeau-carte) #header [data-row="top:boxed"] > .ct-container,
	body:has(.cas-bandeau-carte) #header [data-row="top"] {
		background-color: transparent;
		-webkit-backdrop-filter: none;
		backdrop-filter: none;
		box-shadow: none;
	}

	/* Le titre se cale ENTRE le logo et le bouton de menu.
	   Ses valeurs viennent du réglage d'origine du propriétaire — 175 px de
	   large, centré, 9 px — et elles n'ont rien d'arbitraire : sans la
	   contrainte de largeur, le titre passe sous le logo. Constaté en
	   remettant tout à plat, puis corrigé en revenant à ses chiffres. */
	.cas-bandeau-carte {
		align-items: center;
		padding: 0.67rem 0.67rem 0.44rem;
	}

	.cas-bandeau-carte__titre {
		max-width: 175px;
		margin-inline: auto;
		font-size: 9px;
		line-height: 1.3;
	}
}

/* ==========================================================================
   10. Mouvement réduit — tout s'arrête, rien ne disparaît
   ========================================================================== */

@media (prefers-reduced-motion: reduce) {
	.cas-js .cas-anim { opacity: 1; transform: none; transition: none; }
	.cas-hero::after { animation: none; }
	.cas-hero__eyebrow::before { animation: none; }
	/* Le feu de balisage s'arrête, mais il ne DISPARAÎT pas : un point allumé
	   reste cohérent avec le dessin. Même règle que pour les ondes du logo. */
	.cas-antenne__feu { animation: none; opacity: 0.85; }
	/* Les ondes du logo s'arrêtent, mais on ne les fait pas DISPARAÎTRE :
	   un anneau figé reste un décor cohérent avec l'antenne du logotype.
	   ⚠ Même portée que la règle qu'elle annule : les ondes du logo n'existent
	   que sur les pages de carte (voir section 8). */
	body:has(.cas-page-sombre) #header .site-branding::before,
	body:has(.cas-page-sombre) #header .site-branding::after { animation: none; opacity: 0; }
	.cas-outil, .cas-op, .cas-stat, .cas-outil__visuel img,
	.cas-actions .wp-block-button__link { transition: none; }
	.cas-outil:hover, .cas-op:hover,
	.cas-actions .wp-block-button__link:hover { transform: none; }
}

/* ==========================================================================
   11. DERNIERS ARTICLES

   WordPress rend ce bloc entièrement nu : ni fond, ni bordure, ni ombre, ni
   rembourrage, et un titre à 16px. On lui donne le même traitement qu'aux
   cartes d'outils, pour que la page tienne d'un seul tenant.

   L'ordre du balisage est imposé par WordPress (image, titre, date, extrait) :
   on remonte la date au-dessus du titre avec « order », sans toucher au HTML.
   ========================================================================== */

.cas-derniers.wp-block-latest-posts__list {
	display: grid !important;
	grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
	gap: var(--cas-e-3);
	list-style: none;
	margin: 0;
	padding: 0;
}

.cas-derniers.wp-block-latest-posts__list > li {
	position: relative;
	display: flex;
	flex-direction: column;
	gap: 0.55rem;

	/* WordPress impose « width: calc(33.33% - 1.25em) » à ses éléments de
	   grille. Le conteneur étant passé en « grid », ce pourcentage se
	   rapporte désormais à la COLONNE et non au conteneur : chaque carte
	   faisait un tiers de sa propre piste et les titres se coupaient lettre
	   par lettre. On rend la largeur à la grille. */
	width: auto !important;
	max-width: none !important;
	min-width: 0;
	margin: 0 !important;
	padding: 0 0 var(--cas-e-3);
	background: var(--cas-surface);
	border: 1px solid var(--cas-filet-clair);
	border-radius: var(--cas-r-l);
	overflow: hidden;
	transition: background 0.34s ease, box-shadow 0.34s ease, transform 0.34s ease,
	            border-color 0.34s ease;
}

.cas-derniers > li:hover {
	background: var(--cas-surface-survol);
	border-color: color-mix(in srgb, var(--cas-signal) 42%, transparent);
	box-shadow: 0 20px 46px -20px rgba(0, 0, 0, 0.7);
	transform: translateY(-4px);
}

/* Le rembourrage est porté par les enfants, pas par la carte : c'est ce qui
   permet à l'image d'occuper toute la largeur. */
.cas-derniers > li > :not(.wp-block-latest-posts__featured-image) {
	padding-inline: var(--cas-e-3);
}

/* --- Le visuel ---------------------------------------------------------- */

.cas-derniers .wp-block-latest-posts__featured-image {
	order: -2;
	margin: 0 0 var(--cas-e-1);
	aspect-ratio: 16 / 10;
	overflow: hidden;
	background: var(--cas-surface-visuel);
	border-bottom: 1px solid var(--cas-filet-clair);
}

.cas-derniers .wp-block-latest-posts__featured-image a,
.cas-derniers .wp-block-latest-posts__featured-image img {
	display: block;
	width: 100%;
	height: 100%;
}

.cas-derniers .wp-block-latest-posts__featured-image img {
	object-fit: cover;
	transition: transform 0.55s cubic-bezier(0.22, 1, 0.36, 1);
}

.cas-derniers > li:hover .wp-block-latest-posts__featured-image img {
	transform: scale(1.045);
}

/* --- La date, remontée au-dessus du titre et traitée en étiquette ------- */

.cas-derniers .wp-block-latest-posts__post-date {
	order: -1;
	font-family: var(--cas-f-donnees);
	font-size: 0.6875rem;
	letter-spacing: 0.12em;
	text-transform: uppercase;
	color: var(--cas-signal);
	margin: 0;
}

/* --- Titre -------------------------------------------------------------- */

.cas-derniers .wp-block-latest-posts__post-title {
	font-family: var(--cas-f-titres);
	font-size: 1.1875rem !important;
	font-weight: 700;
	line-height: 1.26;
	letter-spacing: -0.015em;
	color: var(--wp--custom--banniere--titre, #ffffff) !important;
	text-decoration: none !important;
	text-wrap: balance;
	transition: color 0.2s ease;
}

.cas-derniers > li:hover .wp-block-latest-posts__post-title {
	color: var(--cas-signal) !important;
}

/* Le titre rend TOUTE la carte cliquable, sans imbriquer de liens. */
.cas-derniers .wp-block-latest-posts__post-title::before {
	content: "";
	position: absolute;
	inset: 0;
	z-index: 1;
}

/* --- Extrait ------------------------------------------------------------ */

.cas-derniers .wp-block-latest-posts__post-excerpt {
	margin: 0;
	color: var(--wp--custom--banniere--texte, #c9bcb6);
	font-size: 0.9688rem;
	line-height: 1.58;
	/* Trois lignes au plus : les cartes gardent la même hauteur. */
	display: -webkit-box;
	-webkit-line-clamp: 3;
	-webkit-box-orient: vertical;
	overflow: hidden;
}

/* Le « Lire la suite » que WordPress glisse dans l'extrait devient une
   incitation discrète, alignée sur le reste du site. */
.cas-derniers .wp-block-latest-posts__post-excerpt a {
	color: var(--cas-signal);
	font-weight: 600;
	text-decoration: none;
}

@media (prefers-reduced-motion: reduce) {
	.cas-derniers > li,
	.cas-derniers .wp-block-latest-posts__featured-image img { transition: none; }
	.cas-derniers > li:hover { transform: none; }
	.cas-derniers > li:hover .wp-block-latest-posts__featured-image img { transform: none; }
}

/* ==========================================================================
   12. PAGE SOMBRE — accueil (FUSIONNÉE le 16.08.2026)
   Cette section repeignait en sombre, sous « body.home », des composants dont
   la base était restée au design CLAIR de la première époque. Conséquence
   signalée par le propriétaire : l'éditeur — qui n'est pas body.home — montrait
   des cartes blanches (aux titres blancs, via theme.json). Le site étant nuit
   PARTOUT depuis les migrations, le sombre est devenu la seule base : les
   valeurs vivent en jetons dans theme.json (surface, filetClair…), les
   sections 1, 3, 4, 5, 6 et 11 les lisent, et l'éditeur voit ce que voit le
   visiteur. NE PAS recréer de couche « body.home » : s'il faut une variante,
   c'est la base qu'on change.
   ========================================================================== */

/* ==========================================================================
   13. PIED DE PAGE — le champ de signal se referme
   Même sol et mêmes courbes que la bannière, avec sa propre antenne.
   ========================================================================== */

.ct-footer {
	position: relative;
	isolation: isolate;
	overflow: hidden;

	--theme-link-initial-color: var(--cas-signal);
	--theme-link-hover-color: var(--wp--custom--banniere--titre, #fff);
	--theme-text-color: var(--wp--custom--banniere--texte, #c9bcb6);
	--theme-headings-color: var(--wp--custom--banniere--titre, #fff);

	/* 🔴 LE PIED PORTE SON PROPRE SOL, PAR DÉFAUT.

	   Il a d'abord été laissé transparent, pour que les ondes venues de la
	   bannière le traversent. C'était juste — mais SEULEMENT sur les pages au
	   corps sombre. Sur les 29 pages encore claires, le pied se retrouvait en
	   texte blanc sur fond blanc : titres de widgets et liens à un contraste
	   de 1,0, purement invisibles. Défaut mesuré le 16.08.2026, sur une page
	   que je n'avais jamais regardée — je n'avais vérifié que l'accueil et les
	   cartes.

	   La leçon reste vraie ; seul le SUPPORT a changé. Depuis le 16.08.2026 ce
	   sol est posé par le réglage Blocksy footerBackground (#16110f), et non
	   plus par une déclaration d'ici. Ne pas la réintroduire : elle
	   redoublerait le réglage natif sans rien y ajouter. */
	border-top: 1px solid rgba(255, 255, 255, 0.08);
	color: var(--wp--custom--banniere--texte, #c9bcb6);
}

/* …sauf là où le corps de page est DÉJÀ sombre et porte les ondes : le pied
   s'efface alors pour les laisser passer, ce qui était l'intention d'origine. */
body.home .ct-footer,
body:has(.cas-page-sombre) .ct-footer {
	background: transparent !important;
}

.ct-footer::after {
	content: "";
	position: absolute;
	inset: 0;
	z-index: -1;
	background: radial-gradient(44rem 30rem at 18% 78%,
		color-mix(in srgb, var(--cas-signal) 16%, transparent), transparent 66%);
	pointer-events: none;
}

/* Les rangées du pied passent devant le champ d'ondes — mais PAS le champ
   lui-même, qui est aussi un enfant direct : sans cette exclusion il héritait
   d'un z-index de 1 et ses cercles se dessinaient par-dessus le texte. */
.ct-footer > div {
	position: relative;
	z-index: 1;
}

/* Le fond transparent des deux rangées (footerRowBackground) et le filet qui
   les sépare (footerRowTopDivider, blanc à 8 %) sont servis nativement depuis
   le 16.08.2026. */
.ct-footer > div:nth-child(2) { padding-block: var(--cas-e-4); }

.ct-footer .widget-title {
	color: var(--wp--custom--banniere--titre, #fff) !important;
	font-family: var(--cas-f-donnees);
	font-size: 0.75rem !important;
	font-weight: 600;
	letter-spacing: 0.13em;
	text-transform: uppercase;
	margin-bottom: 0.9rem;
}

.ct-footer :is(p, li, .textwidget) {
	color: var(--wp--custom--banniere--texte, #c9bcb6);
	font-size: 0.9063rem;
	line-height: 1.65;
}

/* ⚠ :not(.stk-link) — les boutons Stackable de SES widgets (« Faire un don »)
   portent leur propre fond ; leur imposer le lien signal donnait du rouge sur
   son rouge, 1,62 (mesuré le 16.08.2026). Ils gardent leur habillage à eux. */
.ct-footer a:not(.stk-link) { color: var(--cas-signal); text-decoration: none; transition: color 0.2s ease; }
.ct-footer a:not(.stk-link):hover { color: var(--wp--custom--banniere--titre, #fff); }

.ct-footer > div:last-child {
	border-top: 1px solid rgba(255, 255, 255, 0.08);
	font-size: 0.8438rem;
	color: var(--wp--custom--banniere--attenue, #b0a29b);
}

.ct-footer img { max-width: 100%; height: auto; }

/* L'antenne du pied : plus petite, à gauche, et plus discrète — elle ferme
   la page sans concurrencer celle de la bannière. */
/* ⚠ Le pied n'a pas de bannière à respecter : son antenne reste pilotée par la
   LARGEUR, et il faut donc lui rendre « height: auto ». Sans cette ligne, la
   hauteur héritée de la règle générale et la largeur d'ici se contredisent, et
   le dessin se déforme. */
/* ⚠ 17.08.2026 — la marge de gauche était NÉGATIVE (-8 % au repos, -18 % sur
   mobile) : le dessin sortait par la gauche et le pied le coupait (78 % visible
   à 390 px). Elle est désormais positive partout, et la largeur est plafonnée
   par la place réellement disponible. Voir CSS-22. */
.cas-antenne--pied {
	right: auto;
	left: clamp(0.75rem, 2vw, 4rem);
	top: 58%;
	width: min(clamp(180px, 20vw, 300px), calc(100vw - 3.5rem));
	height: auto;
	opacity: var(--cas-decor-antenne-pied);
	transform: scaleX(-1);
}

@media (max-width: 900px) {
	.cas-antenne--pied {
		left: clamp(0.75rem, 3vw, 1.5rem);
		width: min(70vw, 380px, calc(100vw - 3.5rem));
		height: auto;
		opacity: var(--cas-decor-antenne-pied-900);
	}
}

/* ==========================================================================
   14. LES DEUX ANTENNES ÉMETTENT

   Les antennes de la bannière ET du pied émettent réellement. Sur les
   accueils, leurs zones sont désormais séparées pour laisser le centre de la
   page aux massifs : haut → avant Explorer ; bas → seulement après le Blog.
   Les autres pages gardent le champ complet validé auparavant.

   Cela remplace deux tentatives qui étaient des impasses :
     · des anneaux de dégradé qui ne faisaient que respirer sur place ;
     · des ondes enfermées dans leur section par « overflow: hidden ».
   Une onde qui s'arrête au bord d'une section n'est pas une onde.

   Le calque est posé sur l'ancêtre commun de l'en-tête, du corps et du pied,
   pour qu'aucune limite de section ne le découpe. Le script mesure la
   position RÉELLE de chaque antenne et la transmet en --x / --y.
   ========================================================================== */

.cas-emissions {
	position: absolute;
	inset: 0;
	z-index: 0;
	overflow: hidden;
	pointer-events: none;
}

.cas-emissions__zone {
	position: absolute;
	inset: 0;
	overflow: hidden;
}

.cas-emissions--accueil .cas-emissions__zone--haut {
	bottom: auto;
	height: var(--cas-zone-fin, 0px);
}

.cas-emissions--accueil .cas-emissions__zone--bas {
	top: var(--cas-zone-debut, 100%);
}

/* Tout le site passe devant les ondes. */
.cas-emissions ~ * { position: relative; z-index: 1; }

.cas-emetteur {
	position: absolute;
	left: var(--x, 50%);
	top: var(--y, 0);
}

.cas-emetteur span {
	position: absolute;

	/* ⚠ Le cercle part DÉJÀ grand et ne grandit que d'un facteur 3.
	   « transform: scale() » agrandit aussi la bordure : partir d'un point
	   de 2px pour aller à l'échelle 1400 transformait un trait d'un pixel
	   en un anneau de plus de mille pixels — une bande, pas une onde. */
	width: 120vmax;
	height: 120vmax;
	margin: -60vmax 0 0 -60vmax;

	border: 1px solid var(--cas-signal);
	border-radius: 50%;
	opacity: 0;
	will-change: transform, opacity;
	/* Progression qui ACCÉLÈRE.
	   Les ondes sont émises à intervalle régulier ; si le rayon accélère,
	   deux crêtes successives s'écartent de plus en plus. Résultat : dense
	   près de l'antenne, aéré en s'éloignant — le corps de page ne se
	   retrouve pas saturé de cercles. */
	animation: cas-emission var(--duree, 34s) cubic-bezier(0.45, 0, 0.85, 0.5) infinite;
}

/* Sept ondes par antenne, décalées d'un septième de cycle. Les décalages
   sont exprimés en fraction de --duree : changer la durée suffit, la
   répartition suit. */
.cas-emetteur span:nth-child(2) { animation-delay: calc(var(--duree, 34s) / -7); }
.cas-emetteur span:nth-child(3) { animation-delay: calc(var(--duree, 34s) / -7 * 2); }
.cas-emetteur span:nth-child(4) { animation-delay: calc(var(--duree, 34s) / -7 * 3); }
.cas-emetteur span:nth-child(5) { animation-delay: calc(var(--duree, 34s) / -7 * 4); }
.cas-emetteur span:nth-child(6) { animation-delay: calc(var(--duree, 34s) / -7 * 5); }
.cas-emetteur span:nth-child(7) { animation-delay: calc(var(--duree, 34s) / -7 * 6); }

/* L'onde s'affaiblit en s'éloignant, comme un vrai signal — mais reste
   visible assez longtemps pour TRAVERSER toute la page.

   ⚠ L'échelle maximale est de 5, pas de 3. Mesuré le 15.08.2026 : à
   l'échelle 3, l'onde de l'antenne du haut portait jusqu'à y = 3317 alors
   que le pied commence à y = 3971 — il lui manquait 654 px. Elle n'y
   arrivait jamais, et ce que l'on voyait en bas n'était que l'onde de
   l'antenne du pied : d'où une impression d'arrêt puis de reprise. */
/* ⚠ Les trois paliers sont lus dans :root et doivent monter ENSEMBLE : c'est
   leur RAPPORT qui dessine la décroissance du signal. Valaient 0,26 / 0,17 /
   0,09 en dur jusqu'au 18.08.2026. */
@keyframes cas-emission {
	0%   { transform: scale(0.02); opacity: 0; }
	3%   { opacity: var(--cas-onde-page-naissance); }
	40%  { opacity: var(--cas-onde-page-milieu); }
	75%  { opacity: var(--cas-onde-page-fin); }
	100% { transform: scale(5);    opacity: 0; }
}

/* Deux cadences distinctes : à durées égales les deux antennes finiraient
   par battre à l'unisson, ce qui se voit et fait mécanique. */
.cas-emetteur--haut { --duree: 34s; }
.cas-emetteur--bas  { --duree: 43s; }

@media (prefers-reduced-motion: reduce) {
	.cas-emissions { display: none; }
}

.cas-op__jauge-piste {
	height: 6px;
	border-radius: 999px;
	background: rgba(255, 255, 255, 0.10);
	overflow: hidden;
}

.cas-op__jauge-part {
	display: block;
	height: 100%;
	width: 0;
	border-radius: inherit;
	background: linear-gradient(90deg, var(--cas-accent), var(--cas-signal));
	transition: width 1.25s cubic-bezier(0.22, 1, 0.36, 1);
}

/* La jauge se remplit au moment où la carte apparaît. */
.cas-est-visible .cas-op__jauge-part { width: var(--part, 0%); }

@media (prefers-reduced-motion: reduce) {
	.cas-op__jauge-part { transition: none; width: var(--part, 0%); }
}

/* --- La ligne « part 5G » porte le pourcentage et la barre --------------- */

/* 🔴 18.08.2026 — trois griefs du propriétaire sur cette ligne, tous les trois
   REPRODUITS par la mesure avant d'y toucher (accueil DE à 390 px, accueil FR
   à 360 px) :
     · « le pourcentage doit rester sur la même ligne » — il passait à la ligne
       dès que le libellé s'allongeait. `flex-wrap: wrap` faisait basculer le
       `%` en seconde rangée : mesuré 2 lignes au lieu d'1 en DE à 390 px.
     · « 11443 doit être PROCHE de compatibles 5G » — conséquence du premier :
       une fois le `%` descendu, il n'absorbait plus l'espace libre par son
       `margin-left: auto`, et `justify-content: space-between` écartait alors
       le chiffre de son libellé. Écart mesuré : 12 px en FR à 1710 px, mais
       **41 px** en DE à 390 px et 29 px en FR à 360 px.
   D'où `nowrap` + `flex-start` : le chiffre est collé à son libellé quelle que
   soit la largeur, et le `%` reste sur la rangée, poussé à droite par sa
   marge automatique. Le libellé, lui, garde le droit de se replier à
   l'intérieur de son propre bloc — c'est la rangée qui ne se casse plus. */
.cas-op__5g {
	display: flex;
	flex-wrap: nowrap;
	align-items: baseline;
	justify-content: flex-start;
	gap: 0 0.4rem;
	margin: var(--cas-e-1) 0 0.4rem;     /* compaction : était --cas-e-2 / 0.5rem */
	font-size: 0.875rem;
	line-height: 1.4;
	color: var(--wp--custom--banniere--attenue, #b0a29b);
}

.cas-op__5g strong {
	flex: 0 0 auto;                      /* le chiffre ne se comprime pas */
	font-family: var(--cas-f-titres);
	font-weight: 700;
	color: var(--wp--custom--banniere--texte, #c9bcb6);
	font-variant-numeric: tabular-nums;
}

/* Le pourcentage est POSÉ par le script — il ne fait pas partie du texte. */
.cas-op__pct {
	margin-left: auto;
	padding-left: 0.4rem;
	/* Il ne se coupe jamais en deux, et il ne rétrécit pas : c'est le libellé
	   qui cède la place, pas le chiffre. */
	white-space: nowrap;
	flex: 0 0 auto;
	font-family: var(--cas-f-titres);
	font-weight: 700;
	font-size: 1.0625rem;
	line-height: 1;
	color: var(--cas-signal);
	font-variant-numeric: tabular-nums;
}

/* ==========================================================================
   16. LE BLOG — archive et catégories

   Cette page n'a PAS de contenu : 218 octets en base, tout est rendu par le
   gabarit d'archive de Blocksy. Elle se traite donc entièrement ici, et ce
   qu'on écrit vaut pour l'archive comme pour les pages de catégorie.

   Décidé le 16.08.2026 : fond sombre, comme l'accueil.

   La bannière photo a été retirée à la SOURCE, pas masquée ici :
   blog_page_title_bg_type et single_blog_post_page_title_bg_type sont passés
   de « custom_image » à « color » dans les réglages Blocksy.
   ========================================================================== */

/* Le fond nuit du site est réglé nativement (site_background + theme.json) depuis le 16.08.2026. */

/* --- Le bandeau de titre ------------------------------------------------ */

/* ⚠ L'attribut [data-type] est là pour la SPÉCIFICITÉ, pas pour cibler.
   Le gris #edeff2 ne vient PLUS de Blocksy : le bandeau est réglé transparent
   nativement depuis le 16.08.2026, il n'y a donc plus de fond à dépeindre.
   Mais le cran de spécificité reste NÉCESSAIRE pour les déclarations qui
   suivent : Blocksy sert ce bandeau depuis sa feuille en ligne
   « ct-main-styles-inline-css », chargée APRÈS la nôtre, et à spécificité
   égale il l'emporterait — notamment sur le rembourrage. Mesuré :
       body.blog .hero-section              → perd
       body.blog .hero-section[data-type]   → gagne
   Un cran de spécificité suffit ; inutile de recourir à !important. */
body.blog .hero-section[data-type],
body.archive .hero-section[data-type] {
	padding-block: var(--cas-e-5) var(--cas-e-4);
	/* Hôte de l'antenne : elle est en position absolue et a besoin d'un
	   ancêtre positionné. isolation crée le contexte d'empilement, overflow
	   l'empêche de déborder sur les cartes. Mêmes réglages que .cas-hero. */
	position: relative;
	isolation: isolate;
	overflow: hidden;
}

/* Le titre passe DEVANT l'antenne.

   ⚠ :not(.cas-antenne) est INDISPENSABLE. Sans lui, la règle remettait
   l'antenne en position: relative — donc DANS LE FLUX : elle se plaçait en
   haut à gauche et allongeait le bandeau de 417 à 953 px. Mesuré. */
body.blog .hero-section[data-type] > *:not(.cas-antenne):not(.cas-montagnes),
body.archive .hero-section[data-type] > *:not(.cas-antenne):not(.cas-montagnes) {
	position: relative;
	z-index: 1;
}

/* Les couleurs du titre et du chapeau sont servies par les réglages Blocksy
   depuis le 16.08.2026 (blog_pageTitleFontColor, blog_pageExcerptColor). */
body.blog .page-title,
body.archive .page-title {
	font-family: var(--cas-f-titres);
	letter-spacing: -0.028em;
	text-wrap: balance;
}

body.blog .page-description,
body.archive .page-description {
	max-width: 62ch;
	margin-inline: auto;
}

/* --- Les cartes d'articles ----------------------------------------------

   L'image arrive désormais PREMIÈRE dans le HTML : blog_archive_order a été
   remonté dans les réglages Blocksy le 16.08.2026, et son ratio 16/9 vient
   du réglage thumb_ratio. Plus rien à corriger ici sur l'ordre ni la forme.

   ⚠ Le rembourrage se porte sur les ENFANTS, pas sur la carte : une marge
   négative ne dilaterait pas l'image jusqu'aux bords (voir CSS-07). */

body.blog .entry-card,
body.archive .entry-card {
	display: flex;
	flex-direction: column;
	padding: 0 0 var(--cas-e-3);
	background-color: color-mix(in srgb, var(--cas-nuit-claire) 55%, transparent);
	border: 1px solid rgba(255, 255, 255, 0.08);
	border-radius: var(--cas-r-l);
	overflow: hidden;
	transition: transform 0.34s ease, border-color 0.34s ease, box-shadow 0.34s ease;
}

body.blog .entry-card:hover,
body.archive .entry-card:hover {
	transform: translateY(-4px);
	border-color: color-mix(in srgb, var(--cas-signal) 34%, transparent);
	box-shadow: 0 22px 46px -26px rgba(0, 0, 0, 0.95);
}

/* ⚠ `.entry-button` est EXCLU volontairement. Ce rembourrage gonflait la boîte
   du bouton au lieu de l'écarter du bord : mesuré, son cadre commençait à
   0,0 px du bord intérieur de la carte — il TOUCHAIT le périmètre, alors que
   son libellé, lui, était bien aligné sur le texte. Le bouton est écarté par
   une MARGE, quelques règles plus bas. */
body.blog .entry-card > *:not(.ct-media-container):not(.entry-button),
body.archive .entry-card > *:not(.ct-media-container):not(.entry-button) {
	padding-inline: var(--cas-e-3);
}

body.blog .entry-card .ct-media-container,
body.archive .entry-card .ct-media-container {
	display: block;
	margin: 0 0 var(--cas-e-2);
	overflow: hidden;
	background-color: var(--cas-nuit);
}

body.blog .entry-card .ct-media-container img,
body.archive .entry-card .ct-media-container img {
	width: 100%;
	height: 100%;
	object-fit: cover;
	transition: transform 0.5s ease;
}

body.blog .entry-card:hover .ct-media-container img,
body.archive .entry-card:hover .ct-media-container img {
	transform: scale(1.045);
}

body.blog .entry-title,
body.archive .entry-title {
	font-family: var(--cas-f-titres);
	font-size: 1.1875rem;
	line-height: 1.28;
	letter-spacing: -0.018em;
	margin: 0 0 var(--cas-e-1);
}

body.blog .entry-title a,
body.archive .entry-title a {
	color: var(--wp--custom--banniere--titre, #fff);
	text-decoration: none;
}

body.blog .entry-card:hover .entry-title a,
body.archive .entry-card:hover .entry-title a {
	color: var(--cas-signal);
}

body.blog .entry-excerpt,
body.archive .entry-excerpt {
	color: var(--wp--custom--banniere--texte, #c9bcb6);
	font-size: 0.9375rem;
	line-height: 1.6;
}

/* --- Les pastilles de catégorie, encore en turquoise --------------------- */

body.blog .entry-meta a[class*="ct-term-"],
body.archive .entry-meta a[class*="ct-term-"] {
	/* 10 % et non 16 : à 16 % le fond de la pastille remontait trop et le
	   contraste tombait à 4,46 — juste sous le seuil AA de 4,5. Mesuré. */
	background-color: color-mix(in srgb, var(--cas-signal) 10%, transparent) !important;
	color: var(--cas-signal) !important;
	border: 1px solid color-mix(in srgb, var(--cas-signal) 32%, transparent);
	border-radius: 999px;
}

body.blog .entry-meta,
body.archive .entry-meta {
	color: var(--wp--custom--banniere--attenue, #b0a29b);
}

body.blog .entry-meta a:not([class*="ct-term-"]),
body.archive .entry-meta a:not([class*="ct-term-"]) {
	color: var(--wp--custom--banniere--attenue, #b0a29b);
}

/* --- Le bouton « Lire la suite » ----------------------------------------

   Demande du propriétaire, 18.08.2026 : « mets lire la suite à droite et le
   bouton doit être aligné avec le texte et pas collé comme c'est le cas
   actuellement avec le périmètre du bloc ».

   Ce qui était mesuré AVANT, sur les trois langues et à toutes les largeurs :
   bouton à gauche (`align-self: flex-start`, valeur par défaut de Blocksy),
   cadre à **0,0 px** du bord intérieur de la carte — donc collé au périmètre —
   et bord droit du bouton à 131 à 354 px du bord droit du texte.

   🔴 Niveau 1 de la hiérarchie (section 3 du CLAUDE.md) VÉRIFIÉ et écarté.
   Deux réglages natifs pouvaient prétendre l'exprimer :
     · le calque `read_more` de `blog_archive_order` — ses seules options sont
       `button_type`, `read_more_text`, `read_more_arrow` et `spacing` (marge
       BASSE). Aucune position, aucun alignement ;
     · `blog_content_horizontal_alignment` (Customizer → Articles → Alignement
       horizontal). Il existe, mais il pose `--text-horizontal-alignment` ET
       `--horizontal-alignment` sur `.entry-card` tout entière : le titre,
       l'extrait et les deux lignes de méta partiraient à droite avec le
       bouton. Il ne sait pas dire « le bouton seul ».
   Le libellé, lui, reste servi par le réglage natif `read_more_text` dans les
   trois langues (« Lire la suite », « Weiterlesen », « Leggi tutto ») — cette
   règle ne touche à aucun texte.

   Le bouton retrouve donc son rembourrage NATIF Blocksy (`5px 15px`), et
   c'est une marge qui l'aligne sur la colonne de texte : son bord droit
   tombe exactement sur celui du titre et de l'extrait.

   ⚠ Blocksy écrit `.entry-button { align-self: var(--horizontal-alignment,
   flex-start) }` dans une feuille chargée APRÈS la nôtre (leçon CSS-24) :
   à une seule classe, elle gagnerait. Le `body` et le parent dans le
   sélecteur donnent les deux crans qui manquent. Vérifié par la valeur
   CALCULÉE, pas par la feuille. */
body.blog .entry-card > .entry-button,
body.archive .entry-card > .entry-button {
	align-self: flex-end;
	margin-inline: var(--cas-e-3);
}

body.blog .entry-button,
body.archive .entry-button {
	color: var(--cas-signal);
	background-color: transparent;
}

/* --- La colonne latérale ------------------------------------------------ */

body.blog .ct-sidebar,
body.archive .ct-sidebar {
	color: var(--wp--custom--banniere--texte, #c9bcb6);
}

body.blog .ct-sidebar .widget-title,
body.blog .ct-sidebar h2,
body.archive .ct-sidebar .widget-title,
body.archive .ct-sidebar h2 {
	color: var(--wp--custom--banniere--titre, #fff);
}

body.blog .ct-sidebar a,
body.archive .ct-sidebar a {
	color: var(--wp--custom--banniere--texte, #c9bcb6);
	text-decoration: none;
}

body.blog .ct-sidebar a:hover,
body.archive .ct-sidebar a:hover {
	color: var(--cas-signal);
}

/* ⚠ Le type « email » doit être listé : le widget Newsletter peint ses champs
   depuis SA feuille (.tnp-widget input[…], #f4f4f4), qui passe devant le
   système de formulaires natif de Blocksy — un réglage ne l'atteindrait pas.
   Signalé par le propriétaire le 16.08.2026 : « Prénom » sombre, « E-mail »
   resté clair. */
/* ⚠ Les six sélecteurs qui habillaient ces champs ont été RETIRÉS le
   16.08.2026 : `formBackgroundColor`, `formBorderColor` et `formTextColor` les
   font nativement, et pour TOUS les champs du site — pas seulement ceux de la
   barre latérale du blog. Leur bordure valait `rgba(255,255,255,.12)`, soit
   1,39 pour un seuil de 3 (défaut D de l'audit).
   Ne reste ici que le rayon, qu'aucun réglage n'exprime à ce niveau. */
body.blog .ct-sidebar :is(input[type="search"], input[type="text"], input[type="email"]),
body.archive .ct-sidebar :is(input[type="search"], input[type="text"], input[type="email"]) {
	border-radius: var(--cas-r-s);
}

/* Le plugin Newsletter écrit encore `#f4f4f4`, `#dddddd` et `#444444` dans
   SA feuille, chargée après le thème. Les réglages natifs de formulaire sont
   donc bien présents mais ne peuvent pas gagner la cascade. Le `body` ajoute
   un cran à ses propres sélecteurs, pour les widgets latéraux comme pour les
   formulaires insérés dans une page, sans toucher au bouton d'inscription. */
body .tnp-widget input:is([type="text"], [type="email"]),
body .tnp-subscription input:is([type="text"], [type="email"]) {
	background-color: var(--theme-form-field-background-initial-color);
	border-color: var(--theme-form-field-border-initial-color);
	color: var(--theme-form-text-initial-color, var(--theme-text-color));
	border-radius: var(--cas-r-s);
}

/* --- La pagination ------------------------------------------------------ */

body.blog .ct-pagination a,
body.blog .ct-pagination span,
body.archive .ct-pagination a,
body.archive .ct-pagination span {
	color: var(--wp--custom--banniere--texte, #c9bcb6);
	border-color: rgba(255, 255, 255, 0.12);
}

body.blog .ct-pagination .ct-active,
body.archive .ct-pagination .ct-active {
	color: var(--cas-signal);
	border-color: color-mix(in srgb, var(--cas-signal) 40%, transparent);
}

@media (prefers-reduced-motion: reduce) {
	body.blog .entry-card,
	body.blog .entry-card .ct-media-container img,
	body.archive .entry-card,
	body.archive .entry-card .ct-media-container img { transition: none; }
	body.blog .entry-card:hover,
	body.archive .entry-card:hover { transform: none; }
	body.blog .entry-card:hover .ct-media-container img,
	body.archive .entry-card:hover .ct-media-container img { transform: none; }
}

/* ==========================================================================
   17. PAGES DE CONTENU ET ARTICLES

   Même principe que l'accueil et le blog, en CSS scopé : fond nuit, antenne
   dans le bandeau, en-tête transparent au repos et peint une fois épinglé.

   Applicable seulement depuis que Stackable a été retiré du contenu : tant
   que ses blocs y figeaient leurs couleurs, un fond sombre aurait donné du
   texte foncé sur foncé. C'est l'ordre de la procédure — le contenu d'abord,
   l'habillage ensuite.
   ========================================================================== */

/* Le fond nuit du site est réglé nativement (site_background + theme.json) depuis le 16.08.2026. */

/* --- Le bandeau de titre ------------------------------------------------ */

/* ⚠ Le bandeau n'a plus à être dépeint ici : les réglages Blocksy du
   16.08.2026 le rendent transparent nativement. Le cran de spécificité
   [data-type] reste NÉCESSAIRE pour les déclarations qui suivent — la feuille
   en ligne du thème est chargée après la nôtre, et à spécificité égale elle
   l'emporterait sur le contexte d'empilement qui héberge l'antenne. */
body.page .hero-section[data-type],
body.single .hero-section[data-type] {
	position: relative;
	isolation: isolate;
	overflow: hidden;
}

/* ⚠ :not(.cas-antenne) — sans quoi l'antenne repasse dans le flux et
   allonge le bandeau (voir CSS-14). */
body.page .hero-section[data-type] > *:not(.cas-antenne):not(.cas-montagnes),
body.single .hero-section[data-type] > *:not(.cas-antenne):not(.cas-montagnes) {
	position: relative;
	z-index: 1;
}

/* Les COULEURS du bandeau viennent des réglages Blocksy depuis le 16.08.2026
   (single_page_pageTitleFontColor, single_blog_post_pageTitleFontColor,
   pageExcerptColor, pageMetaFontColor). Ne reste ici que la typographie. */
body.page .page-title, body.page .entry-title,
body.single .page-title, body.single .entry-title {
	font-family: var(--cas-f-titres);
	letter-spacing: -0.026em;
	text-wrap: balance;
}

/* --- Le corps du texte -------------------------------------------------- */

body.page .entry-content,
body.single .entry-content {
	color: var(--wp--custom--banniere--texte, #c9bcb6);
}

body.page .entry-content :is(h1, h2, h3, h4, h5, h6),
body.single .entry-content :is(h1, h2, h3, h4, h5, h6) {
	color: var(--wp--custom--banniere--titre, #fff);
}

body.page .entry-content :is(p, li, td, th, dd, dt),
body.single .entry-content :is(p, li, td, th, dd, dt) {
	color: var(--wp--custom--banniere--texte, #c9bcb6);
}

/* ⚠ « :not(… __link *) » est indispensable : un <strong> DANS un bouton doit
   garder la couleur du bouton, pas le blanc du corps de texte — sinon on
   repasse à 3,09 sur le fond signal. */
body.page .entry-content strong:not(.wp-block-button__link *):not(.wp-element-button *),
body.single .entry-content strong:not(.wp-block-button__link *):not(.wp-element-button *) {
	color: var(--wp--custom--banniere--titre, #fff);
}

/* Les pastilles de catégorie que Blocksy pose sous le titre d'un article :
   elles prennent le fond d'accent, donc le texte doit être la couleur NUIT
   (6,07) et non le blanc que Blocksy y met d'office (3,09). */
body.single :is(.entry-meta, .ct-meta-element) a[class*="ct-term-"],
body.single a[class*="ct-term-"] {
	color: var(--cas-nuit);
}

body.page .entry-content a:not(.wp-block-button__link),
body.single .entry-content a:not(.wp-block-button__link) {
	color: var(--cas-signal);
	text-underline-offset: 0.2em;
}

/* --- Les boutons qu'il pose lui-même ------------------------------------ */

/* Depuis le 16.08.2026, les boutons d'éditeur sont NATIFS, en trois pièces
   vérifiées à la mesure :
     · fond signal        → palette Blocksy (color1) ;
     · texte nuit         → clé Customizer buttonTextColor (#16110f), 6,07:1 ;
     · gélule             → variable --theme-button-border-radius: 999px (:root).
   ⚠ Ne PAS déclarer styles.elements.button dans theme.json : la feuille
   d'héritage de Stackable fait couler ces valeurs dans les boutons Stackable
   des WIDGETS du propriétaire (son bouton de don passait au texte nuit sur son
   rouge, 3,64 — vérifié). Ne restent ici que la variante contour et le petit
   soulèvement au survol, pur décor. */

body.page .entry-content .wp-block-button__link,
body.single .entry-content .wp-block-button__link {
	transition: transform 0.2s ease;
}
body.page .entry-content .wp-block-button__link:hover,
body.single .entry-content .wp-block-button__link:hover {
	transform: translateY(-2px);
}

/* Le bouton « contour » de WordPress ne doit PAS recevoir de fond plein. */
body.page .entry-content .is-style-outline .wp-block-button__link,
body.single .entry-content .is-style-outline .wp-block-button__link {
	background-color: transparent;
	color: var(--cas-signal);
	border: 1px solid currentColor;
}

/* --- Tableaux ----------------------------------------------------------- */

body.page .entry-content table,
body.single .entry-content table {
	border-color: rgba(255, 255, 255, 0.12);
}

body.page .entry-content :is(th, td),
body.single .entry-content :is(th, td) {
	border-color: rgba(255, 255, 255, 0.12);
}

body.page .entry-content thead th,
body.single .entry-content thead th {
	background-color: color-mix(in srgb, var(--cas-nuit-claire) 55%, transparent);
	color: var(--wp--custom--banniere--titre, #fff);
}

body.page .entry-content tbody tr:nth-child(even),
body.single .entry-content tbody tr:nth-child(even) {
	background-color: color-mix(in srgb, var(--cas-nuit-claire) 26%, transparent);
}

/* --- Le sommaire : dernier bloc Stackable, et une FONCTION, pas un
       habillage — il régénère sa liste depuis les titres. On l'habille
       plutôt que de le convertir, pour ne pas le figer. -------------------- */

body.page .entry-content [class*="table-of-contents"],
body.single .entry-content [class*="table-of-contents"] {
	background-color: color-mix(in srgb, var(--cas-nuit-claire) 46%, transparent) !important;
	border: 1px solid rgba(255, 255, 255, 0.09);
	border-radius: var(--cas-r-m);
}

body.page .entry-content [class*="table-of-contents"] a,
body.single .entry-content [class*="table-of-contents"] a {
	color: var(--cas-signal) !important;
}

/* --- Citations et code -------------------------------------------------- */

body.page .entry-content blockquote,
body.single .entry-content blockquote {
	border-left: 3px solid color-mix(in srgb, var(--cas-signal) 55%, transparent);
	color: var(--wp--custom--banniere--texte, #c9bcb6);
}

body.page .entry-content :is(code, pre),
body.single .entry-content :is(code, pre) {
	background-color: color-mix(in srgb, var(--cas-nuit-claire) 55%, transparent);
	color: var(--wp--custom--banniere--titre, #fff);
	border-radius: var(--cas-r-s);
}

/* --- L'article ne doit jamais redevenir une carte BLANCHE ---------------- */

/* Le « carton blanc » des articles sous 768 px a été éteint À SA SOURCE le
   16.08.2026 : single_blog_post_content_style était en « boxed » sur tablette
   et mobile, il est passé en « wide » partout. Voir CSS-19 ③ pour l'histoire. */

/* --- Les commentaires, sur les articles --------------------------------- */

/* ⚠ « :not(.wpd-rating-value *) » est DANS la règle, et pas dans une règle
   d'annulation à côté : celle-ci contient un :is(#comments …), donc un ID, et
   aucune règle de classe ne peut la battre. Même piège qu'en CSS-17. */
body.single :is(#comments, .wpdiscuz-comment-message, .wpd-thread-wrapper),
body.single :is(#comments, .wpdiscuz-comment-message, .wpd-thread-wrapper)
	:is(p, li, span:not([class*="icon"])):not(.wpd-rating-value *):not(.wpd-comment-label *) {
	color: var(--wp--custom--banniere--texte, #c9bcb6);
}

body.single :is(#comments, .wpd-thread-wrapper) :is(h2, h3, .wpd-thread-head) {
	color: var(--wp--custom--banniere--titre, #fff);
}

/* 🔴 wpDiscuz scope TOUTES ses règles par un identifiant — « #wpdcom … »,
   « #wpd-post-rating … ». Une règle de classe, si longue soit-elle, ne les
   atteint pas. On reprend donc leur propre point d'ancrage et on y ajoute le
   « body.single » du site : la nôtre passe devant sans un seul !important.
   Vérifié à la mesure, pas déduit — voir CSS-19. */

/* Le compteur « 0 Commentaires » : gris #555 d'origine, prévu pour du blanc. */
body.single #wpdcom .wpd-thread-head .wpd-thread-info,
body.single #wpdcom .wpd-thread-head .wpd-thread-info :is(span, a) {
	color: var(--wp--custom--banniere--texte, #c9bcb6);
}

/* ⚠ Cette règle disait « la barre d'outils reste une surface CLAIRE, à lui »
   et y posait un gris foncé. Ce n'est plus vrai depuis la section 18, qui rend
   cette surface sombre : le gris y tombait à 1,92. Corrigé le 16.08.2026 —
   quand on change une surface, on relit ce qui était écrit POUR elle. */
body.single #wpdcom .ql-toolbar :is(button, .ql-picker-label) {
	color: var(--wp--custom--banniere--texte, #c9bcb6);
}

body.single :is(#comments, .wpd-thread-wrapper) a:not(.wpd-rating-value a) {
	color: var(--cas-signal);
}

/* --- Pages SANS bannière : on leur en donne une -------------------------

   Beaucoup de pages ont leur bandeau de titre désactivé dans Blocksy
   (has_hero_section: disabled) : leur H1 est dans le contenu, qui commence
   donc tout en haut. Un en-tête transparent s'y superposait — le titre
   passait littéralement sous le menu.

   Première correction : peindre l'en-tête et le remettre dans le flux. Elle
   marchait, mais donnait à ces pages un menu opaque quand tout le reste du
   site l'a transparent. Demandé le 16.08.2026 : « faut aussi faire en-tête
   transparent comme l'accueil et le blog ».

   Solution retenue : leur créer une bande d'accueil. L'ESPACE est réservé
   ici, en CSS, donc dès le premier rendu ; le script y pose ensuite l'antenne.
   Si l'espace dépendait du JavaScript, le titre passerait sous le menu le
   temps qu'il s'exécute.

   ⚠ Les trois exclusions : .hero-section est le bandeau de Blocksy, .cas-hero
   celui de l'accueil, .cas-page-sombre les pages de carte. En omettre une
   attrape des pages déjà refaites. */

body.page:not(:has(.hero-section)):not(:has(.cas-hero)):not(:has(.cas-page-sombre)) .site-main,
body.single:not(:has(.hero-section)):not(:has(.cas-hero)):not(:has(.cas-page-sombre)) .site-main {
	position: relative;
}

/* Repli : tant que le script n'a pas posé la bannière, le contenu garde ses
   distances et le titre ne passe pas sous le menu.

   ⚠ La condition d'annulation est DANS la règle, par un quatrième :not().
   Écrite comme une règle séparée — « body:has(.cas-bandeau) .site-main
   { padding-top: 0 } » — elle ne gagnait jamais : chaque :not() apporte la
   spécificité de son argument, et les trois premiers rendaient la règle
   d'origine bien plus forte. Résultat : la bannière commençait 144 px trop
   bas et ne fusionnait pas avec le menu. Signalé le 16.08.2026. */
body.page:not(:has(.hero-section)):not(:has(.cas-hero)):not(:has(.cas-page-sombre)):not(:has(.cas-bandeau)) .site-main,
body.single:not(:has(.hero-section)):not(:has(.cas-hero)):not(:has(.cas-page-sombre)):not(:has(.cas-bandeau)) .site-main {
	padding-top: 9rem;
}

/* --- La bannière construite pour ces pages ------------------------------

   Même grammaire que .cas-hero sur l'accueil : une zone à part, avec son
   dégradé, son antenne et son titre — puis le corps commence en dessous.
   Demandé le 16.08.2026 : « qu'on sépare bien le titre et l'antenne du
   body comme pour l'accueil ». */

.cas-bandeau {
	position: relative;
	isolation: isolate;
	overflow: hidden;
	padding-block: clamp(7rem, 5rem + 5vw, 9.5rem) clamp(2.5rem, 2rem + 2vw, 4rem);
	padding-inline: var(--cas-e-3);
	/* Translucide, comme la bannière de l'accueil : les ondes la traversent
	   au lieu d'être masquées par un aplat. */
	background: linear-gradient(168deg,
		transparent 0%,
		color-mix(in srgb, var(--cas-nuit-claire) 52%, transparent) 100%);
	border-bottom: 1px solid rgba(255, 255, 255, 0.07);
	margin-bottom: var(--cas-e-4);
}

/* Le halo du point d'émission, repris de l'accueil. */
.cas-bandeau::after {
	content: "";
	position: absolute;
	inset: 0;
	z-index: -1;
	background: radial-gradient(42rem 28rem at 78% 42%,
		color-mix(in srgb, var(--cas-signal) 16%, transparent), transparent 64%);
	pointer-events: none;
}

/* ⚠ :not(.cas-antenne):not(.cas-montagnes) — sinon le décor repasse dans le
   flux (voir CSS-14). Les montagnes sont venues s'ajouter le 17.08.2026 : la
   liste d'exceptions doit citer CHAQUE décor, sans quoi le nouveau se place en
   haut à gauche et allonge le bandeau. */
.cas-bandeau > *:not(.cas-antenne):not(.cas-montagnes) {
	position: relative;
	z-index: 1;
	max-width: 1180px;
	margin-inline: auto;
}

.cas-bandeau h1 {
	font-family: var(--cas-f-titres);
	font-size: clamp(1.9rem, 1.2rem + 2.6vw, 3rem);
	line-height: 1.08;
	letter-spacing: -0.03em;
	margin: 0;
	color: var(--wp--custom--banniere--titre, #fff);
	text-wrap: balance;
}

.cas-bandeau__chapeau {
	margin: var(--cas-e-2) auto 0;
	max-width: 62ch;
	font-size: clamp(1rem, 0.95rem + 0.3vw, 1.125rem);
	line-height: 1.6;
	color: var(--wp--custom--banniere--texte, #c9bcb6);
}

/* 🔴 HAUTEUR MINIMALE DES BANNIÈRES — 18.08.2026, à sa demande : « sur les
   pages où il n'y a que le titre, prévoir assez de hauteur pour voir
   correctement les montagnes ET l'antenne » (exemple qu'il cite : la page
   Contact).

   Ce que la mesure disait avant, sur les 11 pages à titre seul : bandeau
   269 px, décor plafonné à 193 px, et « slice » lui coupant le HAUT — la
   première unité du viewBox encore visible valait 56,7 sur 192, soit 30 % du
   dessin perdu (82,9 sur la 404, 50,5 sur Communauté). L'antenne plafonnait
   à 241 px, contre 432 px sur une page à chapeau.

   🔴 26vw n'est pas un chiffre rond : le décor vaut 16vw et son plafond 80 %
   de la bannière, il faut donc au moins 20vw de bannière pour qu'il ne soit
   JAMAIS rogné. 26vw ajoute de l'air entre le titre et les crêtes.

   🔴 Le sélecteur vise L'HÔTE DU DÉCOR, pas une classe nommée — et c'est la
   leçon de cette passe. Écrite d'abord sur `.cas-bandeau`, la règle a laissé
   la page « Communauté » à 280 px : elle garde le bandeau natif de Blocksy
   (`.hero-section`) au lieu de recevoir celui du script, et le drapeau du
   sommet n'y était visible qu'à 27 %. `:has(> .cas-montagnes)` désigne
   exactement ce qui héberge les montagnes, quel que soit son nom — et jamais
   les pages de carte, qui n'en ont pas.

   ⚠ Le contenu reste calé en haut par le padding : le haut de la bannière ne
   bouge pas d'un pixel, donc la fusion avec le menu tient (CSS-17), et c'est
   le BAS qui s'ouvre — là où vivent les montagnes.

   🔴🔴 `:not(.cas-montagnes--menu)` — AJOUTÉ LE 18.08.2026, ET IL EST VITAL.
   Cette règle ne nomme pas son hôte : elle frappe TOUT élément qui contient
   directement des montagnes. Depuis que le script en pose aussi dans la rangée
   du menu des pages de carte, cette rangée entrait dans le sélecteur — une
   barre de menu de 61 px se serait vu imposer 300 px de haut, et la carte,
   qui se dimensionne sur ce qui la précède, aurait perdu la même hauteur, sur
   les quatre pages les plus consultées du site.
   ⚠ Le :not() fait monter la spécificité du sélecteur de (0,1,0) à (0,2,0).
   Vérifié : rien ne s'appuie sur sa faiblesse — aucune autre règle ne pose de
   min-height sur ces hôtes. */
:has(> .cas-montagnes:not(.cas-montagnes--menu)) {
	min-height: clamp(300px, 26vw, 520px);
}

/* Sur téléphone, 26vw ne ferait que 101 px : c'est la largeur qui commande le
   décor mobile (30vw), donc la bannière doit suivre la même unité. */
@media (max-width: 900px) {
	:has(> .cas-montagnes:not(.cas-montagnes--menu)) { min-height: clamp(260px, 70vw, 440px); }
}


/* ==========================================================================
   18. COMMENTAIRES — ce que les RÉGLAGES de wpDiscuz ne savent pas exprimer

   Ordre respecté (CLAUDE.md § 3) : les couleurs de la zone de commentaires ont
   d'abord été réglées NATIVEMENT dans le plugin — `wc_options → thread_styles`
   (fonds, textes, bordures, couleur principale) et `labels → blogRoles` (la
   couleur par rôle, seconde source du vert, invisible au premier passage).

   Ne restent ici que des valeurs écrites EN DUR dans la feuille du plugin, sur
   lesquelles aucun réglage n'a prise. Chaque règle cite sa ligne d'origine dans
   `wp-content/plugins/wpdiscuz/themes/default/style.css` — c'est la
   vérification que toute règle CSS doit pouvoir raconter.

   ⚠ Le site est en layout-3 : ce sont les sélecteurs `.wpd-layout-3` qui
   s'appliquent, pas leurs équivalents layout-1/2. Corriger le mauvais layout
   ne produirait aucun effet visible et l'on chercherait ailleurs.

   ⚠ Le `body` en tête de chaque sélecteur n'est PAS décoratif : à spécificité
   ÉGALE, c'est l'ordre de chargement qui tranche, et la feuille du plugin est
   chargée APRÈS la nôtre. Sans ce cran, les règles ci-dessous sont présentes,
   correctes… et sans le moindre effet. Mesuré le 16.08.2026 : fond d'en-tête
   toujours `#f7f7f7` alors que la règle était bien dans la feuille.

   ⚠ Et le gris `#999999` du plugin n'est PAS le défaut : sur le fond nuit il
   tient 6,44. Il ne tombait à 2,66 que posé sur les surfaces claires ci-dessous.
   Ce sont les SURFACES qu'on corrige, pas les textes — une correction des
   textes aurait éteint le symptôme en laissant la cause.
   ========================================================================== */

/* l. 623 — `background-color: #f7f7f7` sur l'en-tête de chaque commentaire.
   C'est lui qui faisait tomber la date, le nom et les icônes sous le seuil. */
body #wpdcom.wpd-layout-3 .wpd-comment .wpd-comment-header {
	background-color: transparent;
}

/* l. 657 — même `#f7f7f7` sur la mention « Répondre à ». On garde une surface,
   mais celle du système de design : elle sert encore à détacher le bloc. */
body #wpdcom.wpd-layout-3 .wpd-comment .wpd-reply-to {
	background-color: var(--wp--custom--surface, rgba(255, 255, 255, 0.045));
	border-radius: var(--cas-r-s);
}

/* l. 646 — la pastille de vote est un rond `#fff`. */
body #wpdcom.wpd-layout-3 .wpd-comment .wpd-comment-footer .wpd-vote-result {
	background-color: var(--wp--custom--surface, rgba(255, 255, 255, 0.045));
}

/* l. 261 — la barre d'outils de l'éditeur reste `#fafafa` avec ses bordures
   `#dddddd`, quel que soit le réglage : c'est une surface, pas une couleur de
   texte, et `defaultCommentFieldsBG` ne descend que jusqu'au `.ql-container`. */
body #wpdcom .ql-toolbar {
	background-color: var(--wp--custom--surface, rgba(255, 255, 255, 0.045));
	border-color: var(--wp--custom--filetClair, rgba(255, 255, 255, 0.10));
}

/* l. 1813 de `utils/class.WpdiscuzHelper.php` — l'étiquette de rôle reçoit
   `color: #ffffff` EN DUR, sur un fond qui est la couleur du rôle. Blanc sur
   le rouge signal ne donne que 3,09 ; la couleur nuit en donne 6,07. C'est le
   même piège que les boutons du bug n°33. */
body #wpdcom .wpd-comment-label,
body #wpdcom .wpd-comment-label span {
	color: var(--cas-nuit);
}

/* l. 563 et 639 — les pastilles du pied de commentaire (voir les réponses,
   voter) sont des ronds `#fff` bordés de `#aaaaaa`. */
body #wpdcom.wpd-layout-3 .wpd-comment-footer .wpd-toggle .wpd-view-replies,
body #wpdcom.wpd-layout-3 .wpd-comment .wpd-comment-footer :is(.wpd-vote-up, .wpd-vote-down) {
	background-color: var(--wp--custom--surface, rgba(255, 255, 255, 0.045));
	border-color: var(--wp--custom--filetClair, rgba(255, 255, 255, 0.10));
}

/* l. 673 — wpDiscuz sort son pied de commentaire du cadre avec une marge
   basse négative de 14 px. La bordure horizontale de `.wpd-comment-right`
   traverse alors exactement le milieu des votes et de « Répondre ». À partir
   de 601 px, où cette bordure existe, le pied reste dans le cadre ; sous ce
   seuil le plugin retire déjà la bordure et conserve sa géométrie mobile. */
@media (min-width: 601px) {
	body #wpdcom.wpd-layout-3 .wpd-comment .wpd-comment-footer {
		margin-bottom: 0;
	}
}

/* l. 514-516 — « Répondre » et sa flèche, en `#999999`. Le gris tenait sur le
   fond nuit ; il ne tenait plus sur les pastilles blanches ci-dessus. */
body #wpdcom.wpd-layout-3 .wpd-comment .wpd-comment-footer .wpd-reply-button {
	background-color: transparent;
}

body #wpdcom .wpd-comment-footer .wpd-reply-button {
	color: var(--wp--custom--banniere--texte, #c9bcb6);
}

body #wpdcom .wpd-comment-footer .wpd-reply-button svg {
	fill: var(--wp--custom--banniere--texte, #c9bcb6);
}

/* l. 133 et 450 — les replis gris `#666666` / `#777777` du bandeau de fil :
   l'abonnement, les réglages d'utilisateur, le filtre. */
body #wpdcom .wpd-sbs-toggle,
body #wpdcom .wpd-sbs-toggle i[class*="fa"],
body #wpdcom .wpd-thread-head .wpdiscuz-user-settings,
body #wpdcom .wpd-thread-filter .wpd-filter {
	color: var(--wp--custom--banniere--texte, #c9bcb6);
}

/* l. 31-32 — le vert `#009149` du vote positif, et c'est le SEUL endroit de
   tout le fichier où le plugin pose un `!important`. On ne peut donc y
   répondre qu'en nature ; ce n'est pas une facilité, c'est la seule voie.
   Le vert part avec le reste : sur ce site, la couleur du « oui » est le
   signal, comme partout ailleurs. */
body #wpdcom .wpd-up {
	color: var(--cas-signal) !important;
}

body #wpdcom .wpd-up svg {
	fill: var(--cas-signal) !important;
}

/* ==========================================================================
   19. SES APPLICATIONS EMBARQUÉES — leur rendre la main sur leurs surfaces

   Le Speedtest, les cartes et les graphiques sont du PHP à lui, injectés dans
   `.entry-content`. Le thème y peint donc ses couleurs de contenu — et sa
   fenêtre « Avant de lancer le test », qui a un fond BLANC, recevait un titre
   BLANC : contraste 1,00, texte purement invisible. Mesuré le 16.08.2026.

   ⚠ La cause n'est PAS dans ce fichier mais dans `theme.json`
   (`styles.elements.heading`), qui peint tous les titres du site. Un réglage
   natif n'est pas pour autant le bon réglage : il est décidé à UN endroit, et
   ici l'endroit est trop haut. Comme on ne peut pas restreindre theme.json par
   sélecteur, l'exception se pose ici — c'est la justification de ces règles.

   ⚠ On ne corrige QUE ce que le thème a débordé. Les bordures et libellés de
   SES boutons de carte (1,13 à 2,27) sont ses couleurs à lui, sur ses propres
   surfaces : elles relèvent de sa décision, comme le bug n°21. On n'y touche
   pas.
   ========================================================================== */

#cas-speedtest-root .popup-content :is(h1, h2, h3, h4, h5, h6) {
	color: var(--cas-nuit);
}

#cas-speedtest-root .popup-content :is(p, li, dd, dt, strong, span) {
	color: var(--wp--custom--encre-sur-clair, #3d322d);
}

/* --- Les icônes de réseaux sociaux --------------------------------------
   WordPress pose `color: currentcolor` sur l'icône : elle prend donc la
   couleur du TEXTE de la page. Sur un site sombre, cela donne du beige
   `#c9bcb6` posé sur des pastilles aux couleurs de marque — 2,29 sur le rose
   d'Instagram, 1,86 sur le bleu de Facebook.

   Vérifié avant d'écrire : le bloc expose bien un réglage `iconColor`, mais il
   se pose bloc par bloc DANS LE CONTENU, donc sur chaque page et dans chaque
   langue. Une règle ici vaut pour toutes d'un coup, y compris les pages qu'il
   ajoutera — c'est l'avantage que le CSS garde sur l'attribut de bloc.

   Les pastilles restent aux couleurs des marques : ce sont leurs logos. */
.wp-block-social-links:not(.is-style-logos-only) .wp-social-link .wp-block-social-link-anchor {
	color: var(--wp--custom--blanc-pur, #ffffff);
}

/* ========================================================================== 
   Massifs au défilement — bureau validé le 18.08, essai mobile du 19.08.2026

   Huit silhouettes réellement différentes alimentent les variantes bureau et
   mobile, avec un aplat rouge allégé pour préserver la lecture. Le drapeau
   réutilise les classes et les proportions
   du drapeau du bandeau. Sur mobile, cinq silhouettes en flux remplacent les
   trois grands fonds : elles ne peuvent plus disparaître sous les images.
   ========================================================================== */

.site-main:has(> .cas-defile) {
	position: relative;
	isolation: isolate;
}

.cas-defile {
	position: absolute;
	top: 0;
	left: 0;
	width: 100%;
	height: 100%;
	z-index: 0;
	pointer-events: none;
	overflow: hidden;
}

.cas-defile__panorama {
	position: absolute;
	left: 0;
	right: 0;
	--cas-revelation: 0;
	--cas-parallaxe: 0px;
	opacity: var(--cas-revelation);
	will-change: opacity, transform;
}

/* Le massif occupe presque la largeur et se lit comme une grande matière
   de fond, pas comme une vignette. Le remplissage vit dans le SVG ; ici on
   garde seulement la géométrie et le léger mouvement vertical. */
.cas-defile__panorama {
	height: clamp(330px, 42vw, 690px);
	transform: translate3d(0, var(--cas-parallaxe), 0);
}

.cas-defile__massif {
	display: block;
	width: 110%;
	height: 100%;
	margin-left: -5%;
	color: var(--cas-signal);
	filter: drop-shadow(0 24px 60px color-mix(in srgb, var(--cas-signal) 5%, transparent));
}

.cas-defile__massif-fond {
	opacity: var(--cas-revelation);
}

.cas-defile__neige {
	fill: color-mix(in srgb, var(--wp--custom--blanc-pur, #ffffff) 18%, transparent);
	stroke: var(--wp--custom--blanc-pur, #ffffff);
	stroke-width: 1.6;
	opacity: 0.28;
}

.cas-defile__trait {
	fill: none;
	stroke: var(--cas-signal, #ff5a47);
	stroke-width: 2.5;
	stroke-linecap: round;
	stroke-linejoin: round;
}

.cas-defile__trait--fort {
	stroke-width: 3.4;
	opacity: 0.34;
}

/* Le MOTIF reste strictement celui du bandeau (mêmes classes, carré 44 × 44,
   croix pleine aux proportions suisses). Seule sa force d'encre est propre au
   corps de page : une croix blanche à 0,60 derrière du texte ferait chuter le
   contraste. À 0,18, son pire fond composé sous une surface blanche à 4,5 %
   reste à 5,12:1 face au texte secondaire #c9bcb6. */
.cas-defile .cas-montagnes__drapeau,
.cas-defile__panorama--mobile .cas-montagnes__drapeau {
	fill-opacity: 0.14;
	stroke-opacity: 0.24;
}

.cas-defile .cas-montagnes__croix,
.cas-defile__panorama--mobile .cas-montagnes__croix {
	fill-opacity: 0.18;
}

.cas-defile__panorama--mobile { display: none; }

@media (max-width: 700px) {
	/* Les cartes mobiles font 350 px dans un écran de 390 px : tout massif
	   absolu placé derrière elles est presque entièrement masqué. Le décor est
	   donc inséré ENTRE les blocs et participe au flux. À 45vw, il gagne 50 %
	   de hauteur face au premier essai à 30vw ; le `slice` ne rogne que les
	   extrémités horizontales, jamais les sommets ni les cinq drapeaux. */
	.cas-defile { display: none; }

	.cas-defile__panorama--mobile {
		display: block;
		position: relative;
		left: auto;
		right: auto;
		grid-column: 1 / -1;
		width: 100vw;
		height: clamp(150px, 45vw, 190px);
		margin: 0;
		margin-left: calc((100vw - 100%) / -2);
		overflow: hidden;
		line-height: 0;
		font-size: 0;
		list-style: none;
		pointer-events: none;
		transform: translate3d(0, var(--cas-parallaxe), 0);
	}

	.cas-defile__panorama--mobile .cas-defile__massif {
		width: 100%;
		height: 100%;
		margin-left: 0;
	}

	.cas-defile__panorama--mobile .cas-montagnes__drapeau {
		fill-opacity: 0.24;
		stroke-opacity: 0.34;
	}

	.cas-defile__panorama--mobile .cas-montagnes__croix {
		fill-opacity: 0.34;
	}
}

@media (prefers-reduced-motion: reduce) {
	.cas-defile__panorama { will-change: auto; transform: none; }
}
