/* tokens */
:root {
  --font-body: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
  --color-sur-secondary: #ffffff;
  --color-sur-primary: #ffffff;
  --focus-ring: #e30c28;
  --color-primary: #e30c28;
  --color-secondary: #111827;
  --color-bg: #ffffff;
  --color-text: #111827;
  --color-surface: #ffffff;
  --color-surface-alt: #f9fafb;
  --color-border: #f3f4f6;
  --color-text-muted: #4b5563;
  --radius-card: 1rem;
  --shadow-card: 0 1px 2px 0 rgba(0, 0, 0, .05);
  --font-heading: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
}

:focus-visible {
  outline: 2px solid var(--focus-ring);
  outline-offset: 2px;
}
@supports not selector(:focus-visible) {
  :focus { outline: 2px solid var(--focus-ring); outline-offset: 2px; }
}

/* lib-prose — la typographie d'un corps d'article.

   Tout est en tokens : deux sites qui tirent cette brique servent la meme structure
   typographique sous des couleurs, des polices et des selecteurs disjoints.

   La mesure de lecture est portee par la brique elle-meme (68 caracteres environ), pas
   par un conteneur exterieur : un corps de texte doit rester lisible meme si on le pose
   dans une bande large. */

.zce__lib-prose {
  max-width: 40rem;
  font-family: var(--font-body);
  font-size: 1.06rem;
  line-height: 1.75;
  color: var(--color-text);
  text-wrap: pretty;
}

.zce__lib-prose > :first-child { margin-top: 0; }
.zce__lib-prose > :last-child { margin-bottom: 0; }

.zce__lib-prose p { margin: 0 0 1.25em; }

/* Le premier paragraphe fait office de chapo quand l'article n'en declare pas : un peu
   plus grand, un peu plus aere. Une regle, pas une donnee de plus a saisir. */
.zce__lib-prose > p:first-of-type {
  font-size: 1.14rem;
  line-height: 1.68;
  color: var(--color-text);
}

/* --- titres --------------------------------------------------------------------- */
.zce__lib-prose h2 {
  position: relative;
  margin: 2.6em 0 .7em;
  padding-top: .9em;
  font-family: var(--font-heading);
  font-size: clamp(1.35rem, 1.15rem + .9vw, 1.72rem);
  font-weight: 700;
  line-height: 1.22;
  letter-spacing: -.02em;
  color: var(--color-text);
  text-wrap: balance;
}

/* Un filet court au-dessus de chaque H2 : la respiration se voit, sans trait pleine
   largeur qui couperait la colonne en tranches. */
.zce__lib-prose h2::before {
  content: "";
  position: absolute;
  inset: 0 auto auto 0;
  width: 2.6rem;
  height: 3px;
  border-radius: 2px;
  background: var(--color-primary);
}

.zce__lib-prose h3 {
  margin: 2em 0 .5em;
  font-family: var(--font-heading);
  font-size: clamp(1.08rem, 1rem + .4vw, 1.25rem);
  font-weight: 700;
  line-height: 1.3;
  letter-spacing: -.01em;
  color: var(--color-text);
}

.zce__lib-prose h4 {
  margin: 1.6em 0 .4em;
  font-family: var(--font-heading);
  font-size: 1rem;
  font-weight: 700;
  color: var(--color-text-muted);
}

/* --- listes --------------------------------------------------------------------- */
.zce__lib-prose ul,
.zce__lib-prose ol {
  margin: 0 0 1.35em;
  padding-left: 1.4em;
}

.zce__lib-prose li { margin-bottom: .5em; }
.zce__lib-prose li::marker { color: var(--color-primary); }

.zce__lib-prose li > ul,
.zce__lib-prose li > ol { margin: .5em 0 0; }

/* --- liens ----------------------------------------------------------------------- */
.zce__lib-prose a {
  color: var(--color-primary);
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: .18em;
  text-decoration-color: color-mix(in srgb, var(--color-primary) 40%, transparent);
  transition: text-decoration-color .15s ease;
}

.zce__lib-prose a:hover,
.zce__lib-prose a:focus-visible { text-decoration-color: var(--color-primary); }

.zce__lib-prose a:focus-visible {
  outline: 2px solid var(--color-primary);
  outline-offset: 2px;
}

/* --- citation --------------------------------------------------------------------
   Le guillemet est dessine par le CSS et retire du flux : il decore sans s'inserer
   dans ce qu'un lecteur d'ecran restitue. */
.zce__lib-prose blockquote {
  position: relative;
  margin: 1.8em 0;
  padding: 1.1em 1.3em 1.1em 2.6em;
  border-left: 3px solid var(--color-primary);
  border-radius: 0 var(--rayon-m, var(--radius-card)) var(--rayon-m, var(--radius-card)) 0;
  background: var(--accent-doux, var(--color-surface));
  font-size: 1.04rem;
  line-height: 1.62;
  color: var(--color-text);
}

.zce__lib-prose blockquote::before {
  content: "\201C";
  position: absolute;
  left: .5rem;
  top: .1em;
  font-family: var(--font-heading);
  font-size: 2.6rem;
  line-height: 1;
  color: var(--color-primary);
  opacity: .35;
}

.zce__lib-prose blockquote > :last-child { margin-bottom: 0; }

/* --- la citation attribuee ----------------------------------------------------------
   <figure> + <blockquote cite="URL"> + <figcaption> contenant le lien vers la source.

   POURQUOI C'EST UN BLOC A PART ENTIERE. Citer un tiers dans le corps et pointer vers lui
   est un geste editorial ET un signal : la page se retrouve associee aux entites qu'elle
   cite. Une reference reléguée en pied de page ne produit pas cet effet, parce qu'elle
   n'est pas dans le passage qu'un moteur de reponse extrait.

   La forme est imposee par des BALISES, pas par des classes : un corps d'article ne peut
   pas porter de classe sans echapper au prefixage. L'attribut cite= porte l'URL pour les
   machines, le lien du figcaption la porte pour le lecteur. */
.zce__lib-prose figure:has(> blockquote) {
  margin: 2em 0;
  padding: 0;
}

.zce__lib-prose figure > blockquote {
  margin: 0;
  border-left-width: 4px;
  border-radius: var(--rayon-m, var(--radius-card));
  border-left-color: var(--color-primary);
  font-size: 1.06rem;
}

/* La source est attachee sous la citation, sans espace : les deux forment un objet. */
.zce__lib-prose figure > blockquote + figcaption {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: .1rem .5rem;
  margin: .55em 0 0;
  padding-left: 2.6rem;
  font-family: var(--font-body);
  font-size: .85rem;
  line-height: 1.5;
  color: var(--color-text-muted);
}

/* Le tiret cadratin qui ouvre une attribution, dessine plutot qu'ecrit : le redacteur
   n'a pas a s'en souvenir, et un lecteur d'ecran ne lit pas un tiret orphelin. */
.zce__lib-prose figure > blockquote + figcaption::before {
  content: "\2014";
  color: var(--color-primary);
  opacity: .7;
}

.zce__lib-prose figcaption a {
  font-weight: 600;
  color: var(--color-text);
  text-decoration-color: color-mix(in srgb, var(--color-primary) 45%, transparent);
}

.zce__lib-prose figcaption a:hover,
.zce__lib-prose figcaption a:focus-visible { color: var(--color-primary); }

/* --- code -------------------------------------------------------------------------
   La pile monospace est ecrite ici : le theme n'expose pas de token de police a
   chasse fixe, et en inventer un obligerait a le derailler sur 48 sites. */
.zce__lib-prose code {
  padding: .12em .38em;
  border-radius: var(--rayon-s, 4px);
  background: var(--accent-doux, var(--color-surface));
  font-family: ui-monospace, "SFMono-Regular", "Cascadia Mono", Consolas, monospace;
  font-size: .89em;
  color: var(--color-text);
}

.zce__lib-prose pre {
  margin: 1.6em 0;
  padding: 1.1em 1.3em;
  border-radius: var(--rayon-m, var(--radius-card));
  background: var(--color-secondary);
  color: color-mix(in srgb, var(--color-bg) 88%, transparent);
  overflow-x: auto;
  font-size: .9rem;
  line-height: 1.6;
}

.zce__lib-prose pre code {
  padding: 0;
  background: none;
  color: inherit;
  font-size: 1em;
}

/* --- tableau ----------------------------------------------------------------------
   Il deborde de la mesure de lecture plutot que d'ecraser ses colonnes, et defile dans
   son propre conteneur : le corps de page, lui, ne defile jamais horizontalement. */
.zce__lib-prose table {
  display: block;
  overflow-x: auto;
  width: 100%;
  margin: 1.7em 0;
  border-collapse: collapse;
  font-size: .95rem;
}

.zce__lib-prose th,
.zce__lib-prose td {
  padding: .6em .8em;
  border-bottom: 1px solid var(--trait, var(--color-border));
  text-align: left;
  vertical-align: top;
}

/* L'en-tete reste visible pendant qu'on fait defiler un long tableau : sans lui, a la
   dixieme ligne on ne sait plus quelle colonne on lit. */
.zce__lib-prose thead th {
  position: sticky;
  top: 0;
  z-index: 1;
  background: var(--color-bg);
}

.zce__lib-prose th {
  font-family: var(--font-heading);
  font-weight: 700;
  color: var(--color-text);
  border-bottom-color: var(--color-primary);
  white-space: nowrap;
}

/* La premiere colonne nomme la ligne : elle porte le poids, comme un intitule. */
.zce__lib-prose tbody th,
.zce__lib-prose tbody td:first-child {
  font-weight: 700;
  color: var(--color-text);
}

.zce__lib-prose tbody tr:hover { background: var(--accent-doux, var(--color-surface)); }

.zce__lib-prose caption {
  caption-side: bottom;
  padding-top: .7em;
  font-size: .84rem;
  line-height: 1.5;
  color: var(--color-text-muted);
  text-align: left;
}

/* --- encadre ----------------------------------------------------------------------
   <aside> DANS un corps d'article, sans classe. C'est le pari de cette brique : donner
   au redacteur un vocabulaire de BALISES plutot qu'un vocabulaire de classes. Une classe
   ecrite dans un corps d'article echapperait au prefixage et sortirait nue sur la page —
   le piege deja rencontre deux fois le 2026-09-09. Une balise, elle, ne peut pas fuir. */
.zce__lib-prose aside {
  position: relative;
  margin: 1.9em 0;
  padding: 1.15em 1.35em 1.15em 1.5em;
  border: 1px solid var(--trait, var(--color-border));
  border-left: 3px solid var(--color-primary);
  border-radius: 0 var(--rayon-m, var(--radius-card)) var(--rayon-m, var(--radius-card)) 0;
  background: var(--surface-haute, var(--color-surface));
  font-size: .98rem;
  line-height: 1.62;
}

.zce__lib-prose aside > :last-child { margin-bottom: 0; }

/* Le premier <strong> d'un encadre sert d'intitule : un titre sans niveau de titre, donc
   sans casser la hierarchie des H2/H3 que le sommaire lit. */
.zce__lib-prose aside > p:first-child > strong:first-child {
  display: block;
  margin-bottom: .35em;
  font-family: var(--font-heading);
  font-size: .78rem;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--color-primary);
}

/* --- liste de definitions ----------------------------------------------------------
   La forme la plus juste pour un glossaire, et celle qu'un moteur de reponse extrait le
   plus proprement : un terme, sa definition, rien entre les deux. */
.zce__lib-prose dl {
  margin: 1.6em 0;
  display: grid;
  gap: .1em;
}

.zce__lib-prose dt {
  margin-top: .9em;
  font-family: var(--font-heading);
  font-weight: 700;
  font-size: 1.02rem;
  color: var(--color-text);
}

.zce__lib-prose dt:first-child { margin-top: 0; }

.zce__lib-prose dd {
  margin: 0;
  padding-left: 1rem;
  border-left: 2px solid var(--accent-trait, var(--color-primary));
  color: var(--color-text-muted);
}

/* --- accordeon ---------------------------------------------------------------------
   <details> natif : un depliant sans une ligne de JavaScript. Le triangle par defaut est
   remplace par un signe dessine en CSS, qui pivote a l'ouverture. */
.zce__lib-prose details {
  margin: .7em 0;
  border: 1px solid var(--trait, var(--color-border));
  border-radius: var(--rayon-m, var(--radius-card));
  background: var(--surface-haute, var(--color-surface));
  overflow: hidden;
}

.zce__lib-prose summary {
  position: relative;
  padding: .85em 3em .85em 1.1em;
  font-family: var(--font-heading);
  font-weight: 700;
  font-size: 1rem;
  line-height: 1.4;
  color: var(--color-text);
  cursor: pointer;
  list-style: none;
}

.zce__lib-prose summary::-webkit-details-marker { display: none; }

.zce__lib-prose summary::after {
  content: "";
  position: absolute;
  right: 1.2em;
  top: 50%;
  width: .5rem;
  height: .5rem;
  margin-top: -.35rem;
  border-right: 2px solid var(--color-primary);
  border-bottom: 2px solid var(--color-primary);
  transform: rotate(45deg);
  transition: transform .2s ease;
}

.zce__lib-prose details[open] > summary::after {
  transform: rotate(-135deg);
  margin-top: -.15rem;
}

.zce__lib-prose summary:hover,
.zce__lib-prose summary:focus-visible { color: var(--color-primary); }

.zce__lib-prose details > :not(summary) {
  margin: 0 1.1em 1.1em;
}

@media (prefers-reduced-motion: reduce) {
  .zce__lib-prose summary::after { transition: none; }
}

/* --- surlignage et mentions ------------------------------------------------------- */
.zce__lib-prose mark {
  padding: .05em .25em;
  border-radius: 3px;
  background: var(--accent-doux, var(--color-surface));
  color: var(--color-text);
}

.zce__lib-prose small {
  font-size: .84rem;
  color: var(--color-text-muted);
}

/* --- media ------------------------------------------------------------------------ */
.zce__lib-prose img {
  display: block;
  max-width: 100%;
  height: auto;
  margin: 1.7em 0;
  border-radius: var(--rayon-m, var(--radius-card));
}

.zce__lib-prose figure { margin: 1.7em 0; }
.zce__lib-prose figure img { margin: 0 0 .6em; }

.zce__lib-prose figcaption {
  font-size: .85rem;
  line-height: 1.5;
  color: var(--color-text-muted);
}

.zce__lib-prose hr {
  margin: 2.4em 0;
  border: 0;
  border-top: 1px solid var(--trait, var(--color-border));
}

.zce__lib-prose strong { font-weight: 700; color: var(--color-text); }

.zce__lib-prose abbr[title] {
  text-decoration: underline dotted;
  text-underline-offset: .18em;
  cursor: help;
}

/* --- citation en ligne --------------------------------------------------------------
   <q cite="URL"> pour quelques mots cites dans une phrase, la ou <blockquote> serait
   demesure. Les guillemets sont poses par le CSS, aux formes francaises : le redacteur
   n'a pas a s'en souvenir, et un lecteur d'ecran annonce deja la citation. */
.zce__lib-prose q {
  quotes: "\00ab\00a0" "\00a0\00bb" "\201c" "\201d";
  font-style: italic;
  color: var(--color-text);
}

.zce__lib-prose q::before { content: open-quote; }
.zce__lib-prose q::after { content: close-quote; }

/* --- titre de source cite dans le texte ------------------------------------------- */
.zce__lib-prose cite {
  font-style: normal;
  font-weight: 600;
  color: var(--color-text);
}

/* --- date en chiffres alignes ----------------------------------------------------- */
.zce__lib-prose time { font-variant-numeric: tabular-nums; }

/* --- appel de note ------------------------------------------------------------------ */
.zce__lib-prose sup {
  font-size: .7em;
  line-height: 0;
  vertical-align: super;
}

.zce__lib-prose sup a { text-decoration: none; }

/* =================================================================================
   lib-trib-bande — la bande pleine largeur, ET la couche de tokens du theme tribune.

   POURQUOI LES TOKENS SONT ICI ET PAS AILLEURS. Une partielle n'est livree que si son
   marqueur `<prefixe>__lib-trib-bande` apparait dans le HTML construit
   (build_network.py:5030-5031). Les tokens doivent donc vivre dans une brique presente
   sur TOUTES les pages, sinon une page sans bande sortirait sans echelle. La bande est
   cette brique : une page de tribune sans une seule bande n'existe pas.

   POURQUOI L'ECHELLE EST DECLAREE ET NON DERIVEE — la divergence avec `agence`.
   `agence` derive tout par color-mix() depuis les 12 tokens du builder, et c'est juste
   pour un parc : deux sites aux couleurs differentes sortent des teintes disjointes sans
   qu'on touche au CSS. Une tribune a un besoin contraire. Son identite est EXACTE : un
   rouge precis, pas « une nuance de la primaire ». Un accent de titre qui serait
   color-mix(primaire 80%) donnerait une valeur proche et fausse, et personne ne verrait
   l'ecart avant de comparer deux captures au pixel.

   L'echelle ci-dessous est donc nommee et posee. Un site qui veut la sienne la redefinit
   dans SA feuille, qui passe EN DERNIER dans la cascade (build_network.py:6195) et
   surcharge donc ce bloc sans effort et sans fork.
   ================================================================================= */

/* LES RUPTURES S'ECRIVENT EN REM, DANS TOUTES LES BRIQUES DU THEME. C'est la convention
   du depot — agence, dossier, socle et boutique ne portent pas une seule media query en
   px — et elle a une consequence concrete : une rupture en rem suit la taille de police
   que le lecteur a choisie, une rupture en px l'ignore. Melanger les deux unites dans un
   meme theme ferait basculer le heros et la grille de section a DEUX largeurs
   differentes des que le navigateur n'est pas a 16 px, et personne ne le verrait sur sa
   propre machine. 48rem = 768 px et 64rem = 1024 px a la taille par defaut : les deux
   seules ruptures effectives du releve (design.md 6). */

/* POURQUOI « :root, .lib-trib-bande » ET NON « .lib-trib-bande » SEUL. L'entete et le
   pied vivent HORS de la sequence de bandes. Sans la declaration sur :root, ils
   sortiraient sans echelle : la barre de tete perdrait son filet, le pied ses colonnes.

   La declaration reste AUSSI sur .lib-trib-bande, et ce n'est pas une redondance : une
   propriete personnalisee est resolue sur l'element qui la DECLARE. Les tokens de texte
   calcules une seule fois sur :root figeraient les valeurs du fond clair, et un titre
   sortirait sombre sur sombre a l'interieur d'une bande sombre. Declares sur les deux,
   ils se recalculent a l'entree de chaque bande. */
:root,
.zce__lib-trib-bande {

  /* --- l'accent : TROIS rouges, et c'est voulu ---------------------------------
     Le rouge de marque (boutons, pastilles, mots en exergue sur fond clair) n'est pas
     le rouge des accents de titre sur fond sombre, qui n'est pas celui des liens du
     pied. Les confondre aplatit le site : sur fond sombre, le rouge de marque vire au
     brun et perd sa lisibilite, c'est pour ca qu'un ton plus clair existe. */
  --trib-accent: #e30c28;
  --trib-accent-bas: #c1051f;
  --trib-accent-vif: #ef4444;
  --trib-accent-clair: #f87171;
  --trib-accent-pale: #fecaca;
  --trib-accent-voile: #fee2e2;
  --trib-accent-brume: #fef2f2;
  --trib-accent-profond: #991b1b;
  --trib-accent-nuit: #7f1d1d;

  /* --- les tons chauds : reserves aux ordres de grandeur ------------------------
     Un triptyque de chiffres qui monte en temperature se lit comme une progression.
     Ces deux tons n'apparaissent NULLE PART ailleurs, et c'est ce qui leur donne
     leur poids : les reutiliser pour un bouton les banaliserait. */
  --trib-chaud: #fb923c;
  --trib-chaud-plein: #f97316;
  --trib-jaune: #facc15;
  --trib-jaune-plein: #eab308;

  /* --- les fonds sombres : des gris NEUTRES, jamais des bleus -------------------
     La tentation de bleuir un fond sombre est forte — « bleu nuit » est ce qu'on croit
     voir. Ce n'en est pas un : ces trois valeurs n'ont aucune composante bleue
     dominante. Un fond bleute changerait le rendu de tous les accents chauds poses
     dessus. */
  --trib-nuit: #111827;
  --trib-nuit-douce: #1f2937;
  --trib-nuit-pleine: #000000;
  --trib-nuit-trait: #374151;

  /* --- les neutres clairs ------------------------------------------------------- */
  --trib-clair: #ffffff;
  --trib-clair-alt: #f9fafb;
  --trib-trait: #f3f4f6;
  --trib-trait-fort: #e5e7eb;

  /* --- le texte : quatre niveaux, pas deux --------------------------------------
     Le corps de texte n'est PAS la couleur des titres. Un site qui n'en distingue que
     deux niveaux donne des paragraphes aussi noirs que leurs titres, et la page perd
     sa hierarchie avant meme d'etre lue. */
  --trib-titre: #111827;
  --trib-corps: #4b5563;
  --trib-second: #6b7280;
  --trib-tertiaire: #9ca3af;
  --trib-sur-nuit: #d1d5db;

  /* --- rythme vertical ----------------------------------------------------------
     Trois valeurs seulement, et elles se suffisent : une section respire pareil
     partout, un heros respire plus haut parce qu'il passe sous une barre fixe, un
     pied respire moins parce qu'il ferme. */
  --trib-pas-section: 5rem;
  --trib-pas-heros: 8rem;
  --trib-pas-pied: 4rem;
  --trib-gouttiere: 1rem;

  /* --- largeurs de conteneur -----------------------------------------------------
     Quatre paliers, du plus large au plus resserre. Le premier porte l'essentiel des
     sections ; les autres servent a ramener une colonne de lecture a une longueur de
     ligne tenable. */
  --trib-large: 72rem;
  --trib-moyen: 56rem;
  --trib-lecture: 48rem;
  --trib-etroit: 42rem;

  /* --- gouttieres de grille : trois valeurs, pas une echelle ouverte ------------- */
  --trib-ecart-serre: 1.5rem;
  --trib-ecart: 2rem;
  --trib-ecart-large: 3rem;

  /* --- formes ---------------------------------------------------------------------
     Les boutons sont ENTIEREMENT arrondis, jamais a coins adoucis : c'est la signature
     de forme du theme, et un bouton a 8px le trahit immediatement. */
  --trib-rayon-carte: 1rem;
  --trib-rayon-bloc: .75rem;
  --trib-rayon-pastille: 9999px;

  /* --- elevation : deux niveaux, pas trois ---------------------------------------
     Un theme de tribune n'empile pas les plans. Une carte au repos, une carte au
     survol, et c'est tout. */
  --trib-ombre: 0 1px 2px 0 rgba(0, 0, 0, .05);
  --trib-ombre-haute: 0 10px 15px -3px rgba(0, 0, 0, .1),
                      0 4px 6px -4px rgba(0, 0, 0, .1);

  /* --- mouvement ------------------------------------------------------------------
     TOUT le mouvement du theme tient dans ces deux durees. Il n'y a volontairement
     aucune animation d'apparition au defilement : une prise de position qui se
     devoile par morceaux se lit comme une presentation commerciale. */
  --trib-transition: 150ms cubic-bezier(.4, 0, .2, 1);
  --trib-transition-lente: 300ms cubic-bezier(.4, 0, .2, 1);

  /* --- ce que les briques lisent, et que chaque fond redefinit ---------------------
     Une bande sombre ne change pas seulement son fond : elle change ce que les briques
     posees dedans lisent. C'est ce qui evite d'ecrire une variante de chaque brique
     par couleur de fond. */
  --trib-fond: var(--trib-clair);
  --trib-texte: var(--trib-corps);
  --trib-texte-fort: var(--trib-titre);
  --trib-texte-faible: var(--trib-second);
  --trib-surface: var(--trib-clair);
  --trib-bordure: var(--trib-trait);
  --trib-lien: var(--trib-accent);
}

/* La bande elle-meme. Ces proprietes restent sur .lib-trib-bande SEUL : appliquees a
   :root elles poseraient un 100vw et une marge negative sur <html>. */
.zce__lib-trib-bande {
  width: 100vw;
  margin-left: calc(50% - 50vw);
  /* une bande sort d'un conteneur etroit sans rien demander a ses parents : c'est ce
     qui permet d'alterner les fonds sur toute la largeur de l'ecran alors que le
     contenu vit dans une colonne. */
  overflow-x: clip;
  position: relative;
  background: var(--trib-fond);
  color: var(--trib-texte);
}

.zce__lib-trib-bande__inner {
  max-width: var(--trib-large);
  margin: 0 auto;
  padding-block: var(--trib-pas-section);
  padding-inline: var(--trib-gouttiere);
}

/* La largeur passe par un ATTRIBUT et non par une classe. Une classe arrivant par une
   donnee echapperait a prefixer_classes — qui tourne au CHARGEMENT du gabarit, quand le
   jeton n'est pas encore resolu (build_network.py:206) — et sortirait nue : elle ne
   rencontrerait jamais ce selecteur. Le prefixe vit sur la partie litterale ; la donnee
   ne transporte qu'un mot. */
.zce__lib-trib-bande__inner[data-largeur="moyen"]   { max-width: var(--trib-moyen); }
.zce__lib-trib-bande__inner[data-largeur="lecture"] { max-width: var(--trib-lecture); }
.zce__lib-trib-bande__inner[data-largeur="etroit"]  { max-width: var(--trib-etroit); }

/* --- les fonds ------------------------------------------------------------------- */

.zce__lib-trib-bande--alt {
  --trib-fond: var(--trib-clair-alt);
  /* une carte posee sur le fond alterne doit rester blanche, sinon elle disparait */
  --trib-surface: var(--trib-clair);
}

.zce__lib-trib-bande--brume {
  --trib-fond: var(--trib-accent-brume);
  --trib-surface: var(--trib-clair);
}

/* Le fond sombre inverse TOUT ce que les briques lisent, pas seulement le fond. */
.zce__lib-trib-bande--sombre {
  --trib-fond: var(--trib-nuit);
  --trib-texte: var(--trib-sur-nuit);
  --trib-texte-fort: var(--trib-clair);
  --trib-texte-faible: var(--trib-tertiaire);
  --trib-surface: var(--trib-nuit-douce);
  --trib-bordure: var(--trib-nuit-trait);
  --trib-lien: var(--trib-accent-clair);
  background: var(--trib-nuit);
}

.zce__lib-trib-bande--nuit {
  --trib-fond: var(--trib-nuit-pleine);
  --trib-texte: var(--trib-sur-nuit);
  --trib-texte-fort: var(--trib-clair);
  --trib-texte-faible: var(--trib-tertiaire);
  --trib-surface: var(--trib-nuit-douce);
  --trib-bordure: var(--trib-nuit-trait);
  --trib-lien: var(--trib-accent-clair);
  background: var(--trib-nuit-pleine);
}

/* Le heros qui argumente, par opposition a celui qui annonce. Mesure : les deux degrades
   de heros du site partagent leurs deux premieres etapes et divergent sur la troisieme —
   #000000 pour l'accueil, #7f1d1d pour le manifeste. Le rouge profond n'est jamais un
   fond de section ordinaire : il ne sert qu'a ouvrir une page de these. */
/* Le heros qui ANNONCE. Mesure : « bg-gradient-to-br from-gray-900 via-gray-800
   to-black », soit #111827 -> #1f2937 -> #000000. C'est la plus grande surface du site,
   et elle etait servie a plat avant le 2026-09-25. Voir lib-trib-bande-encre.html pour
   la paire qu'elle forme avec --braise. */
.zce__lib-trib-bande--encre {
  --trib-fond: var(--trib-nuit);
  --trib-texte: var(--trib-sur-nuit);
  --trib-texte-fort: var(--trib-clair);
  --trib-texte-faible: var(--trib-tertiaire);
  --trib-surface: var(--trib-nuit-douce);
  --trib-bordure: var(--trib-nuit-trait);
  --trib-lien: var(--trib-accent-clair);
  background: linear-gradient(to bottom right,
                              var(--trib-nuit),
                              var(--trib-nuit-douce),
                              var(--trib-nuit-pleine));
}

.zce__lib-trib-bande--braise {
  --trib-fond: var(--trib-nuit);
  --trib-texte: var(--trib-sur-nuit);
  --trib-texte-fort: var(--trib-clair);
  --trib-texte-faible: var(--trib-tertiaire);
  --trib-surface: var(--trib-nuit-douce);
  --trib-bordure: var(--trib-nuit-trait);
  --trib-lien: var(--trib-accent-clair);
  background: linear-gradient(to bottom right,
                              var(--trib-nuit),
                              var(--trib-nuit-douce),
                              var(--trib-accent-nuit));
}

/* La bande d'accent : le seul endroit du theme ou le rouge occupe toute la largeur.
   Elle se merite — deux sur une meme page et le site crie au lieu d'affirmer. */
.zce__lib-trib-bande--accent {
  --trib-fond: var(--trib-accent);
  --trib-texte: var(--trib-accent-voile);
  --trib-texte-fort: var(--trib-clair);
  --trib-texte-faible: var(--trib-accent-pale);
  --trib-surface: rgba(255, 255, 255, .1);
  --trib-bordure: rgba(255, 255, 255, .28);
  --trib-lien: var(--trib-clair);
  background: linear-gradient(to bottom right, var(--trib-accent), var(--trib-accent-bas));
}

/* =================================================================================
   lib-trib-bio — un portrait et ce qu’il raconte.

   La partielle porte le nom de la CLASSE RACINE rendue, pas du fichier HTML : c’est le
   marqueur `<prefixe>__lib-trib-bio` trouve dans la sortie construite qui decide de la
   livrer (build_network.py:5030-5031). Les deux noms coincident ici, et c’est ce qui
   doit rester vrai le jour ou l’un des deux bouge.
   ================================================================================= */

.zce__lib-trib-bio {
  display: grid;
  /* 48 px, et c’est une valeur RARE : le releve ne compte que trois gouttieres de
     grille sur tout le site — 24, 32 (la dominante) et 48 — et 48 ne sert QUE la ligne
     « Bloc texte + visuel » (design.md 6.1, 4.3). Descendre a 32 collerait le visage au
     texte et ferait de la brique une carte. */
  gap: var(--trib-ecart-large);
  /* Les deux colonnes se centrent l’une sur l’autre (mesure : `items-center`). La photo
     a une hauteur fixe, le propos non : sans ce centrage, le plus court des deux flotte
     en haut d’un trou dont personne ne sait a qui il appartient. */
  align-items: center;
}

/* La seule rupture de la brique. La grille « texte + visuel » est de la famille qui
   passe DIRECTEMENT de 1 a N — elle ne fait pas l’etape 1 -> 2 -> N par 1024 px, qui ne
   concerne que les grilles a 3 et 4 colonnes. Rupture en rem : voir lib-trib-bande.css. */
@media (min-width: 48rem) {
  .zce__lib-trib-bio {
    grid-template-columns: 1fr 1fr;
  }
}

/* --- la photo et ce qui se pose dessus -------------------------------------------- */

/* POURQUOI DEUX BOITES AUTOUR D’UNE SEULE IMAGE. Le cadre doit rogner la photo, donc il
   est en overflow: hidden ; une pastille posee dedans serait coupee par ce meme rognage,
   exactement a l’endroit ou on la veut a cheval. La pastille est donc SOEUR du cadre, et
   c’est ce parent-ci qui lui sert de repere. */
.zce__lib-trib-bio__visuel {
  position: relative;
}

.zce__lib-trib-bio__cadre {
  /* 384 px de haut, quelle que soit la largeur (mesure : `w-full h-96`). Une hauteur
     fixe plutot qu’un rapport : c’est elle qui garantit que les deux colonnes gardent le
     meme aplomb d’un portrait a l’autre, quel que soit le cadrage du fichier. */
  height: 24rem;
  border-radius: var(--trib-rayon-carte);
  overflow: hidden;
}

.zce__lib-trib-bio__photo {
  /* L’image porte sa propre classe plutot que d’etre visee par son type : un selecteur
     de TYPE n’est pas prefixe, et une regle sur `img` nu s’appliquerait a toutes les
     images du site. Ici la balise est ecrite DANS la brique, donc elle peut etre nommee. */
  display: block;      /* sans quoi la ligne de base laisse un filet sous la photo */
  width: 100%;
  height: 100%;
  /* Le cadrage est rogne, jamais deforme : un portrait etire se voit au premier coup
     d’oeil, et aucun reglage de la donnee ne le rattrape. */
  object-fit: cover;
}

.zce__lib-trib-bio__pastille {
  position: absolute;
  /* A cheval sur le BORD BAS, jamais sur le bord droit : un decalage lateral la ferait
     sortir du conteneur en colonne unique, ou la gouttiere de page ne fait que 16 px.
     Elle deborde donc de 32 px vers le bas, dans une gouttiere de grille qui en fait 48 :
     il reste 16 px avant le titre, a toutes les largeurs et sans une regle de plus. */
  right: var(--trib-ecart);
  bottom: 0;
  transform: translateY(50%);
  /* Declare ici et pas attendu d’un reset : les 4 px d’anneau se prennent SUR les 64,
     comme sur l’original. Sans ca la pastille fait 72 px et l’anneau ne rogne rien. */
  box-sizing: border-box;
  display: flex;
  align-items: center;
  justify-content: center;
  /* 64 x 64 : la taille relevee des pastilles pleines qui portent un signe (« 0 », « oo »,
     « -> »), la seule du site avec le point de frise a 16 px. */
  width: 4rem;
  height: 4rem;
  border-radius: var(--trib-rayon-pastille);
  /* CETTE PASTILLE N’EST PAS MESUREE, et il faut le savoir avant de la composer. Le site
     releve ne porte qu’UNE image (le portrait), sans rien pose dessus ; et le « 4px solid
     #ffffff » que design.md 5.3 intitule « anneau de pastille sur photo » est en realite
     l’anneau du POINT DE FRISE — les 4 occurrences de border-4 border-white du corpus sont
     toutes sur w-4 h-4 rounded-full, dans la chronologie du manifeste. C’est donc un
     ajout du theme, pas une copie : le trou de pastille laisse vide la retire entierement.
     L’anneau reste blanc plutot que couleur de bande : ce qu’il detache, c’est la
     pastille de la PHOTO, derriere lui sur toute sa moitie haute. Un anneau a la couleur
     du fond se couperait en deux au bord du cadre. */
  border: 4px solid var(--trib-clair);
  background: var(--trib-accent);
  color: var(--trib-clair);
  /* 20/28 en 700 : le signe des pastilles pleines. */
  font-size: 1.25rem;
  line-height: 1.75rem;
  font-weight: 700;
  /* L’ombre haute, celle des « cartes et pastilles en relief » — c’est elle qui dit que
     la pastille est POSEE sur la photo et non imprimee dedans. */
  box-shadow: var(--trib-ombre-haute);
}

.zce__lib-trib-bio__pastille:empty { display: none; }

/* --- le propos --------------------------------------------------------------------- */

.zce__lib-trib-bio__titre {
  /* 24 px sous le titre (mesure : `mb-6`), et la marge haute reste a 0 : dans ce theme
     l’ecart titre -> suivant appartient toujours au titre, jamais au suivant
     (design.md 4.4). */
  margin: 0 0 var(--trib-ecart-serre);
  font-size: 1.5rem;
  line-height: 2rem;
  font-weight: 700;
  /* -0.025em vaut les -0.6 px relevees sur ce corps. L’interlettrage negatif du theme ne
     touche QUE les titres — ni les chiffres, ni le corps. */
  letter-spacing: -.025em;
  color: var(--trib-texte-fort);
}

.zce__lib-trib-bio__titre:empty { display: none; }

.zce__lib-trib-bio__texte {
  /* Une grille, et non des marges de paragraphe : les <p> arrivent par la donnee, donc
     sans classe a prefixer, et la gouttiere d’une grille ne fusionne pas avec les marges
     du premier ni du dernier. 16 px, mesure (`space-y-4`). */
  display: grid;
  gap: 1rem;
  font-size: 1rem;
  /* 1.625 = les 26 px relevees sur 16 px. Ce n’est pas l’autre interligne de 16 px du
     site (25.6 px = 1.6) : celui-ci est celui de la PROSE LONGUE, et trois paragraphes
     de biographie en sont. */
  line-height: 1.625;
  color: var(--trib-texte);
}

.zce__lib-trib-bio__texte:empty { display: none; }

/* La regle part de la classe du bloc et jamais du type seul : les paragraphes et leur
   amorce arrivent par la donnee, sans classe a prefixer, et une regle sur `p` ou
   `strong` nu fuirait dans la feuille entiere du site. */
.zce__lib-trib-bio__texte > p { margin: 0; }

/* L’AMORCE GRASSE. 700 est pose en clair et non laisse a `bolder` du navigateur, qui est
   RELATIF : sur un paragraphe a 400 il donne bien 700, mais le jour ou un site passe son
   corps a 500, `bolder` glisse a 800 et l’amorce grossit sans que personne ait touche a
   cette brique. Aucune couleur ici, et c’est mesure : l’amorce garde #4b5563, la couleur
   du corps — la rougir est la tentation, pas le releve. */
.zce__lib-trib-bio__texte strong { font-weight: 700; }

/* =================================================================================
   lib-trib-carte — la carte de grille du theme tribune.

   POURQUOI SI PEU DE REGLES. Le releve compte 85 cartes portant exactement la meme
   bordure (design.md 5.3) et deux ombres pour tout le site (5.2). Une carte de
   tribune n’a donc qu’un seul etat a gerer : posee, ou survolee. Le nombre de
   colonnes, la largeur utile et la couleur de fond appartiennent a ce qui l’entoure
   — la grille et la bande — et rien ici ne doit les deviner.

   POURQUOI AUCUNE MEDIA QUERY. Le releve ne mesure aucun changement de marge
   interieure entre 390 et 1440 px (design.md 6) : seule la grille passe de 1 a 3
   colonnes. Une carte qui se resserrerait au telephone s’ecarterait du modele.
   ================================================================================= */

/* --- les trois accents episodiques, et pourquoi ils vivent ICI --------------------
   Le releve ne les compte qu’une ou deux fois chacun, sur un seul element du site :
   le disque pale (design.md 1.6 ; design.json palette — #dbeafe x2, #f3e8ff x2,
   #dcfce7 x1). Les poser dans la couche de tokens en ferait une echelle offerte a
   toutes les briques, alors qu’ils ne sont qu’un ornement de cette carte-ci. Un ton
   peint deux fois n’est pas un token, c’est un detail. */
/* La surface, elle, vient de la bande et non d’un blanc en dur : posee sur le fond
   alterne comme sur le fond sombre, la carte reste lisible sans variante dediee. */
.zce__lib-trib-carte {
  --trib-voile-bleu: #dbeafe;
  --trib-signe-bleu: #2563eb;
  --trib-voile-violet: #f3e8ff;
  --trib-signe-violet: #9333ea;
  --trib-voile-vert: #dcfce7;

  padding: 2rem;
  background: var(--trib-surface);
  border: 1px solid var(--trib-bordure);
  border-radius: var(--trib-rayon-carte);
  box-shadow: var(--trib-ombre);
  transition: box-shadow var(--trib-transition-lente);
}

/* :focus-within et pas seulement :hover — un lien atteint au clavier a l’interieur de
   la carte doit lever la meme elevation, sinon la carte ne signale rien a qui ne
   pointe pas a la souris. */
.zce__lib-trib-carte:hover,
.zce__lib-trib-carte:focus-within {
  box-shadow: var(--trib-ombre-haute);
}

/* --- le rang -----------------------------------------------------------------------
   Une pastille pleine de 64 px, entierement ronde : c’est la forme mesuree, et c’est
   la signature du theme. A 12 px de rayon elle passerait pour un bouton. */
.zce__lib-trib-carte__rang {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 4rem;
  height: 4rem;
  margin-bottom: 1rem;
  border-radius: var(--trib-rayon-pastille);
  background: var(--trib-accent);
  color: var(--trib-clair);
  font-size: 1.25rem;
  font-weight: 700;
  line-height: 1.75rem;
}

/* Apres la regle qui pose display: flex, jamais avant : l’ordre decide. */
.zce__lib-trib-carte__rang:empty { display: none; }

/* --- la tuile ----------------------------------------------------------------------
   64 x 64 px, rayon de carte, 24 px sous elle : les trois valeurs sont mesurees sur
   les trois tuiles de l’accueil. Le carre est exact, donc « to bottom right » vaut
   exactement 135 degres — l’ecrire en degres donnerait le meme rendu et masquerait
   la valeur peinte. */
.zce__lib-trib-carte__tuile {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 4rem;
  height: 4rem;
  margin-bottom: 1.5rem;
  border-radius: var(--trib-rayon-carte);
  font-size: 1.5rem;
  font-weight: 700;
  line-height: 1;
  color: var(--trib-clair);
}

.zce__lib-trib-carte__tuile:empty { display: none; }

/* Les trois degrades chauds, dans l’ordre du releve (design.md 2). Ils tournent : le
   ton de fin de l’un ouvre le suivant, et le troisieme referme sur le premier. Une
   rangee de trois tuiles se lit alors comme une montee en temperature, pas comme
   trois couleurs posees cote a cote. */
.zce__lib-trib-carte__tuile[data-ton="1"] {
  background: linear-gradient(to bottom right, var(--trib-accent-vif), var(--trib-chaud-plein));
}
.zce__lib-trib-carte__tuile[data-ton="2"] {
  background: linear-gradient(to bottom right, var(--trib-chaud-plein), var(--trib-jaune-plein));
}
.zce__lib-trib-carte__tuile[data-ton="3"] {
  background: linear-gradient(to bottom right, var(--trib-jaune-plein), var(--trib-accent-vif));
}

/* Le disque pale est l’autre tuile du site, et la forme suffit a l’annoncer : fond
   voile, signe colore, contour entierement rond. Elle ne porte jamais d’icone dans le
   releve, toujours un caractere — 0, un infini, un point d’interrogation. */
.zce__lib-trib-carte__tuile[data-ton="pale"],
.zce__lib-trib-carte__tuile[data-ton="pale-bleu"],
.zce__lib-trib-carte__tuile[data-ton="pale-violet"],
.zce__lib-trib-carte__tuile[data-ton="pale-vert"] {
  border-radius: var(--trib-rayon-pastille);
}

.zce__lib-trib-carte__tuile[data-ton="pale"] {
  background: var(--trib-accent-voile);
  color: var(--trib-accent);
}
.zce__lib-trib-carte__tuile[data-ton="pale-bleu"] {
  background: var(--trib-voile-bleu);
  color: var(--trib-signe-bleu);
}
.zce__lib-trib-carte__tuile[data-ton="pale-violet"] {
  background: var(--trib-voile-violet);
  color: var(--trib-signe-violet);
}

/* Le disque vert est le seul dont le SIGNE n’est pas mesure : son fond est peint une
   fois, mais aucune couleur verte de texte n’apparait dans les 35 relevees. Plutot
   que d’inventer un vert pour l’assortir, le signe reprend la couleur de titre — une
   valeur du theme, pas une supposition. */
.zce__lib-trib-carte__tuile[data-ton="pale-vert"] {
  background: var(--trib-voile-vert);
  color: var(--trib-texte-fort);
}

/* --- le texte ----------------------------------------------------------------------
   24/32 px, graisse 700 : le titre de carte mesure. L’interlettrage s’ecrit en em et
   non en px — -0.025em, la valeur du releve — pour que -0.6 px reste juste si un site
   du parc remonte l’echelle dans sa propre feuille. Une carte plus dense n’est pas une
   variante d’ici : lib-trib-carte-article porte sa propre racine. */
/* 20/28 ET NON 24/32. Le releve donne les deux valeurs — « titre de carte : 24/32, ou
   20/28 selon la taille » — et la premiere version a retenu la plus grande. Mesure du
   2026-09-25 au navigateur sur les huit premiers h3 de l'accueil d'origine :
   20 20 20 30 24 20 20 20. Les 20 px sont la regle, les autres tailles viennent de
   briques differentes (le sous-bloc a 30, le h3 du hub a 24). Une carte a 24 px partout
   grossissait chaque grille de la page. */
.zce__lib-trib-carte__titre {
  margin: 0 0 1rem;
  font-size: 1.25rem;
  line-height: 1.75rem;
  font-weight: 700;
  letter-spacing: -.025em;
  color: var(--trib-texte-fort);
}

/* 16/25.6 px : l’interligne le plus frequent du site, et il n’est pas celui de la
   prose longue (16/26). Les confondre desaligne une carte posee a cote d’un article. */
.zce__lib-trib-carte__texte {
  margin: 0;
  font-size: 1rem;
  line-height: 1.6;
  color: var(--trib-texte);
}

/* Le pied est separe par un filet et non par du vide : la hierarchie se voit sans
   qu’on ait a lire. L’ecart aux deux bords sert la paire la plus frequente du releve
   — une date a gauche, une invitation a droite — et ne coute rien a une ligne seule. */
.zce__lib-trib-carte__pied {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: .5rem;
  margin: 1rem 0 0;
  padding-top: 1rem;
  border-top: 1px solid var(--trib-bordure);
  font-size: .875rem;
  line-height: 1.25rem;
  color: var(--trib-texte-faible);
}

.zce__lib-trib-carte__pied:empty { display: none; }

/* =================================================================================
   Les variantes mesurees le 2026-09-25 sur la section « Pourquoi 0clic ? ».
   ================================================================================= */

/* UNE CARTE DANS UN PANNEAU NE PORTE PAS DE CADRE. Mesure : les trois items de
   « Pourquoi 0clic ? » sont de simples `text-center` — aucun fond, aucune bordure,
   aucune ombre. Le panneau gris qui les contient porte deja la surface ; une carte
   cadree dedans ferait deux surfaces empilees, ce que le site ne fait nulle part.
   Le survol part avec le cadre : il n'y a rien a soulever. */
.zce__lib-trib-carte[data-pose="nu"] {
  background: none;
  border: 0;
  box-shadow: none;
  padding: 0;
}

.zce__lib-trib-carte[data-pose="nu"]:hover {
  box-shadow: none;
}

/* Centre le contenu ET la tuile. `mx-auto` sur la tuile dans le releve : sans le
   margin-inline, une tuile de 64 px resterait collee a gauche d'un texte centre. */
.zce__lib-trib-carte[data-align="centre"] {
  text-align: center;
}

.zce__lib-trib-carte[data-align="centre"] .zce__lib-trib-carte__tuile {
  margin-inline: auto;
}

/* LA PASTILLE PLEINE : 64 x 64, ronde, a l'accent, signe blanc en 20/700.
   Mesure : « w-16 h-16 bg-red-600 rounded-full » + « text-white font-bold text-xl ».
   Elle se distingue des tuiles a degrade (tons 1 a 3, carrees a coins adoucis) et des
   pastilles pales : c'est la seule qui remplit l'accent. */
.zce__lib-trib-carte__tuile[data-ton="plein"] {
  width: 4rem;
  height: 4rem;
  border-radius: var(--trib-rayon-pastille);
  background: var(--trib-accent);
  color: var(--trib-clair);
  font-size: 1.25rem;
  line-height: 1.75rem;
  font-weight: 700;
}

/* --- lib-trib-carte--sous : la meme carte, titre en h4 ---------------------------
   Le niveau change, le dessin non. Mesure : les titres d'item de « Pourquoi 0clic ? »
   sont en `font-bold text-gray-900` sans classe de taille, donc 16 px — un cran sous
   les 20 px d'un titre de carte de section. */
.zce__lib-trib-carte--sous .zce__lib-trib-carte__titre {
  font-size: 1rem;
  line-height: 1.2;
  letter-spacing: -.025em;
}

/* LA CARTE EN RANGEE : pastille a gauche, texte a droite.
   Mesure du 2026-09-25 sur « Une approche unique du marketing digital » :
   `flex items-start`, pastille `w-8 h-8 bg-red-600 rounded-lg mr-4 mt-1`, nombre en
   `text-white font-bold text-sm`, titre en `font-bold text-gray-900` (h4), texte en
   `text-gray-600 text-sm`.

   POURQUOI CE N'EST PAS UN lib-trib-chiffre. Les deux se ressemblent — un nombre et ce
   qu'il mesure — et la premiere composition les avait confondus. Un lib-trib-chiffre
   pose le nombre EN GRAND au-dessus de sa legende ; ici le nombre est un jeton de 32 px
   a cote d'un titre et d'une phrase. La difference se voit : c'est un element de liste,
   pas un ordre de grandeur. Et elle s'entend : la legende d'un chiffre est un <p>,
   le titre d'une rangee est un <h4>. Deux titres manquaient au plan de la page. */
.zce__lib-trib-carte[data-align="ligne"] {
  display: flex;
  align-items: flex-start;
  gap: var(--trib-gouttiere);
  text-align: left;
}

.zce__lib-trib-carte[data-align="ligne"] .zce__lib-trib-carte__tuile {
  flex: 0 0 auto;
  margin-top: .25rem;
}

/* Le jeton : 32 x 32, rayon de bloc, accent plein, nombre en 14/700 blanc. */
.zce__lib-trib-carte__tuile[data-ton="jeton"] {
  width: 2rem;
  height: 2rem;
  border-radius: var(--trib-rayon-bloc);
  background: var(--trib-accent);
  color: var(--trib-clair);
  font-size: .875rem;
  line-height: 1.25rem;
  font-weight: 700;
}

/* TROIS TAILLES DE TITRE DE CARTE, TOUTES MESUREES. La source ne met pas toutes ses
   cartes au meme rang : les trois mutations du manifeste portent text-2xl, les trois
   promesses de la newsletter n'ont AUCUNE classe de taille (donc 16 px), tout le reste
   porte text-xl. Mesure du 2026-09-25 sur les deux pages. */
.zce__lib-trib-carte[data-taille="grand"] .zce__lib-trib-carte__titre {
  font-size: 1.5rem;
  line-height: 2rem;
}

.zce__lib-trib-carte[data-taille="petit"] .zce__lib-trib-carte__titre {
  font-size: 1rem;
  line-height: 1.5rem;
  letter-spacing: normal;
}

/* =================================================================================
   lib-trib-carte-article — la carte d’un article dans une liste.

   POURQUOI SA PROPRE FAMILLE, alors que le theme a deja des cartes. Le releve separe deux
   populations qu’il serait tentant de fondre : 85 cartes courantes bordees de #f3f4f6, et
   32 cartes d’article bordees de #e5e7eb (design.md 5.3). Un ton plus soutenu, sur la
   seule famille dont chaque element est un lien. Les confondre supprimerait la distinction
   la premiere fois que quelqu’un « nettoierait » la feuille, et personne ne verrait
   l’ecart avant de comparer deux captures au pixel.

   CE QUI VIENT DES TOKENS ET CE QUI N’EN VIENT PAS. Couleurs, rayon, ombre et durees
   sortent toutes de lib-trib-bande.css, sans exception. Le rythme interne de la carte
   (8 / 12 / 16 px) est ecrit en clair : le theme ne declare pas d’echelle a ce grain, et
   inventer quatre tokens pour trois marges ferait peser sur tout le parc une decision qui
   n’appartient qu’a cette brique. Chaque valeur en clair cite sa mesure.
   ================================================================================= */

.zce__lib-trib-carte-article {
  /* position: relative n’est pas du confort de mise en page : c’est le referent de la
     nappe du lien (voir __lien::after). Sans lui, la nappe se calerait sur le premier
     ancetre positionne — la bande, qui est en position: relative — et UNE carte
     recouvrirait la page entiere. */
  position: relative;

  /* la carte reste blanche sur le fond alterne, et bascule d’elle-meme sur une bande
     sombre : c’est tout l’interet de passer par --trib-surface plutot que par du blanc. */
  background: var(--trib-surface);

  /* #e5e7eb mesure sur les 32 cartes d’article, et surtout PAS le #f3f4f6 des 85 cartes
     courantes. Le token porte ce ton precis sous le nom --trib-trait-fort. */
  border: 1px solid var(--trib-trait-fort);
  border-radius: var(--trib-rayon-carte);

  /* p-6 mesure = 24px, et --trib-ecart-serre vaut exactement ce 1.5rem. */
  padding: var(--trib-ecart-serre);

  /* Au repos la carte ne porte AUCUNE ombre — le releve est formel, elle se tient sur sa
     seule bordure. Le survol la souleve, et c’est le seul mouvement de la brique. */
  transition: box-shadow var(--trib-transition-lente);
}

/* --ombre-haute est le shadow-lg mesure au pixel : 0 10px 15px -3px + 0 4px 6px -4px. */
.zce__lib-trib-carte-article:hover {
  box-shadow: var(--trib-ombre-haute);
}

/* --- la ligne haute : rubrique, puce, duree ------------------------------------------ */

.zce__lib-trib-carte-article__meta {
  display: flex;
  align-items: center;
  gap: .5rem;             /* 8px mesures, entre chacun des trois elements de la ligne */
  margin-bottom: .75rem;  /* 12px, l’ecart releve sous ce niveau de titre (design.md 4.4) */
  font-size: .875rem;
  line-height: 1.25rem;   /* 14/20 mesure */
  color: var(--trib-texte-faible);
}

.zce__lib-trib-carte-article__icone {
  /* 16px mesures. La taille est posee ici ET en attributs sur le <svg> : sans l’une, une
     icone saute a sa taille intrinseque le temps du rendu ; sans l’autre, elle occupe sa
     boite avant que la feuille n’arrive. Les deux, et la ligne ne bouge jamais. */
  width: 1rem;
  height: 1rem;
  /* sinon une date longue comprime le calendrier jusqu’a l’ovale */
  flex: none;
}

/* La puce mesuree est U+2022 BULLET, PAS le point median U+00B7 : deux glyphes voisins a
   l’oeil, deux chasses et deux hauteurs d’axe a l’ecran. Elle vit en CSS et non dans le
   HTML pour une raison simple — un separateur n’est pas du contenu, et pose ici il tombe
   tout seul avec la donnee qu’il separe. La marge reproduit le second ecart de 8px : la
   puce est un element de la ligne dans le releve, pas une decoration collee au texte. */
.zce__lib-trib-carte-article__duree::before {
  content: "\2022";
  margin-right: .5rem;
}

/* Sans rubrique, la puce n’a plus rien a separer : elle ouvrirait la ligne sur un point. */
.zce__lib-trib-carte-article__categorie:empty + .zce__lib-trib-carte-article__duree::before {
  content: none;
}

/* --- le titre, et le lien qui le porte ------------------------------------------------ */

.zce__lib-trib-carte-article__titre {
  margin: 0 0 .75rem;      /* 12px mesures ; la marge haute d’usine du titre est annulee */
  font-size: 1.25rem;
  line-height: 1.75rem;    /* 20/28 mesure */
  font-weight: 700;
  letter-spacing: -.025em; /* -0.5px a 20px. L’interlettrage negatif ne touche QUE les
                              titres du theme, jamais le corps ni les chiffres. */
  color: var(--trib-texte-fort);
}

.zce__lib-trib-carte-article__lien {
  color: inherit;
  text-decoration: none;
  transition: color var(--trib-transition);
}

/* Le titre rougit au survol de TOUTE la carte, pas seulement de son propre texte. C’est la
   seule chose qui annonce, avant le clic, que la cible deborde les deux lignes du titre. */
.zce__lib-trib-carte-article:hover .zce__lib-trib-carte-article__lien {
  color: var(--trib-lien);
}

/* LA NAPPE. Le lien n’enveloppe que le titre, pour que son intitule reste le titre (voir
   le .html) ; ce pseudo-element etend sa zone sensible a toute la carte. Un ::after n’a ni
   texte ni role : il agrandit la cible du pointeur sans ajouter un mot a ce que le lien
   annonce, et c’est exactement ce qu’on cherche. inset: 0 se cale sur la carte grace au
   position: relative pose plus haut. */
.zce__lib-trib-carte-article__lien::after {
  content: "";
  position: absolute;
  inset: 0;
}

/* Au clavier, l’anneau natif ne cerclerait que les lignes du titre alors que la cible
   reelle est la carte : on le deplace sur la carte, et on ne le retire du lien QUE parce
   qu’il est redessine juste au-dessus. Les deux regles vont ensemble ou pas du tout. */
.zce__lib-trib-carte-article:has(.zce__lib-trib-carte-article__lien:focus-visible) {
  outline: 2px solid var(--trib-lien);
  outline-offset: 2px;
}

.zce__lib-trib-carte-article__lien:focus-visible {
  outline: none;
}

/* --- l’extrait ------------------------------------------------------------------------ */

.zce__lib-trib-carte-article__extrait {
  margin: 0 0 1rem;     /* 16px mesures avant la ligne basse */
  font-size: 1rem;
  line-height: 1.625;   /* 16/26 mesure : l’interligne de prose, pas le 1.6 du corps court */
  /* --trib-texte vaut --trib-corps (#4b5563) sur fond clair, c’est-a-dire la couleur de
     corps la plus frequente du site — 130 elements, le record du releve. Ecrite en dur,
     elle rendrait la carte illisible des qu’une bande sombre la porte ; lue au token, elle
     suit son fond sans qu’on ecrive une variante. */
  color: var(--trib-texte);
}

/* --- la ligne basse : date a gauche, appel a droite ----------------------------------- */

.zce__lib-trib-carte-article__bas {
  display: flex;
  align-items: center;
  justify-content: space-between;
  /* la carte descend sous 300px de large utile sur telephone : une date longue et un verbe
     long passent a la ligne plutot que de se chevaucher. */
  flex-wrap: wrap;
  gap: .5rem;
  font-size: .875rem;
  line-height: 1.25rem;   /* 14/20 mesure, identique a la ligne haute */
  color: var(--trib-texte-faible);
}

/* Le calendrier et la date forment UN element de la ligne. Sans cette enveloppe,
   space-between les separerait l’un de l’autre autant que de l’appel. */
.zce__lib-trib-carte-article__quand {
  display: inline-flex;
  align-items: center;
  gap: .5rem;
}

.zce__lib-trib-carte-article__action {
  color: var(--trib-lien);
  font-weight: 500;   /* 14/20 en 500 mesure — le meme poids que la navigation */
}

/* La fleche est du DECOR : elle se lit pareil dans toutes les langues, donc elle n’entre
   pas dans une donnee traduisible. Posee en ::after, elle disparait d’elle-meme avec le
   bloc quand l’appel est vide. L’espace fait partie du content pour reproduire « Lire → »
   tel qu’il est mesure, plutot qu’un ecart de marge qui ne serait pas le meme. */
.zce__lib-trib-carte-article__action::after {
  content: " \2192";
}

.zce__lib-trib-carte-article:hover .zce__lib-trib-carte-article__action {
  text-decoration: underline;
}

/* --- ce qui manque se retire, plutot que de laisser un trou ---------------------------- */

.zce__lib-trib-carte-article__categorie:empty,
.zce__lib-trib-carte-article__duree:empty,
.zce__lib-trib-carte-article__extrait:empty,
.zce__lib-trib-carte-article__action:empty {
  display: none;
}

/* Une icone n’illustre que la donnee qu’elle annonce : sans rubrique pas d’etiquette, sans
   date pas de calendrier. Et quand rubrique ET duree manquent, la ligne haute s’efface au
   lieu de laisser 12px de blanc au-dessus du titre. */
.zce__lib-trib-carte-article__meta:has(> .zce__lib-trib-carte-article__categorie:empty) > .zce__lib-trib-carte-article__icone,
.zce__lib-trib-carte-article__quand:has(> .zce__lib-trib-carte-article__date:empty),
.zce__lib-trib-carte-article__meta:has(> .zce__lib-trib-carte-article__categorie:empty):has(> .zce__lib-trib-carte-article__duree:empty) {
  display: none;
}

/* =================================================================================
   LA CARTE SANS DESTINATION — voir lib-trib-carte-article-inerte.html.

   Elle ne porte aucun <a>, donc rien a masquer : il ne reste qu'a donner au titre en
   mention la meme couleur que le titre en lien au repos, et a retirer le relief au
   survol — une carte qui se souleve annonce qu'il va se passer quelque chose.
   ================================================================================= */

.zce__lib-trib-carte-article__sans-lien { color: var(--trib-texte-fort); }

.zce__lib-trib-carte-article--inerte:hover { box-shadow: var(--trib-ombre); }

/* =================================================================================
   lib-trib-chiffre — l’habillage d’un ordre de grandeur.

   POURQUOI CETTE BRIQUE A SA PROPRE PARTIELLE : elle rend sa classe racine
   `lib-trib-chiffre`, et c’est ce nom, prefixe, qui decide de la livraison de cette
   feuille (build_network.py:5030-5031). Un site du theme sans un seul chiffre ne
   l’embarque pas.

   Toute valeur ci-dessous est peinte sur le site releve, jamais deduite d’une classe
   utilitaire : design.md 1.5 pour les tons, 3.2 pour l’echelle, 5.1 et 5.3 pour le
   cadre.
   ================================================================================= */

/* Le bloc est centre — c’est le parti du bandeau d’origine. Cale a gauche, le rapport
   de masse entre la valeur et sa legende se perd, et c’est ce rapport qui fait lire le
   chiffre avant le texte. */
.zce__lib-trib-chiffre {
  text-align: center;
}

/* 48/48 en 700, mesure. L’interlettrage reste NORMAL : le -0.025em du theme appartient
   aux seuls titres (design.md 3.2), jamais aux chiffres. On le DECLARE au lieu de
   l’omettre, parce qu’un parent qui le porte le transmettrait en silence. */
.zce__lib-trib-chiffre__valeur {
  display: block;
  font-size: 3rem;
  line-height: 1;
  font-weight: 700;
  letter-spacing: normal;
  color: var(--trib-texte-fort);
}

/* Les trois degres du triptyque : 65 % en rouge clair, 80 % en orange, 90 % en jaune.
   La temperature MONTE avec la valeur — la couleur dit la progression avant que les
   nombres soient lus.

   Le degre passe par un ATTRIBUT parce qu’il vient d’une donnee : prefixer_classes
   tourne au chargement du gabarit, avant que les jetons soient resolus (blocks.py), et
   une classe transportee par une donnee sortirait nue, sans jamais rencontrer son
   selecteur. */
.zce__lib-trib-chiffre[data-ton="1"] .zce__lib-trib-chiffre__valeur { color: var(--trib-accent-clair); }
.zce__lib-trib-chiffre[data-ton="2"] .zce__lib-trib-chiffre__valeur { color: var(--trib-chaud); }
.zce__lib-trib-chiffre[data-ton="3"] .zce__lib-trib-chiffre__valeur { color: var(--trib-jaune); }

/* data-ton="neutre" n’a volontairement PAS de regle : il retombe sur la couleur de base
   ci-dessus, qui lit --trib-texte-fort et suit donc le fond de sa bande — blanc sur
   l’accent et sur le sombre, encre sur le clair. Un jeton vide y tombe aussi, et c’est
   la garantie recherchee : un degre absent ne doit jamais produire un chiffre
   illisible. */

/* 14/20, et l’ecart de 16 px sous la valeur est celui du bandeau. L’ecart est porte par
   la LEGENDE et non par la valeur : quand la legende est vide, :empty l’emporte avec
   son ecart, et le chiffre ne traine pas un blanc derriere lui. */
.zce__lib-trib-chiffre__label {
  margin: 1rem 0 0;
  font-size: .875rem;
  line-height: 1.25rem;
}

/* La precision se distingue par le CONTRASTE et non par la taille : meme 14/20, un cran
   en dessous. Deux tailles de petit texte dans un meme bloc donnent l’air d’une note de
   bas de page, ce que cette ligne n’est pas — c’est elle qui rend le chiffre verifiable. */
.zce__lib-trib-chiffre__detail {
  margin: .5rem 0 0;
  font-size: .875rem;
  line-height: 1.25rem;
  color: var(--trib-texte-faible);
}

.zce__lib-trib-chiffre__label:empty,
.zce__lib-trib-chiffre__detail:empty { display: none; }

/* Le cadre du bandeau sombre : 32 px de marge interne, rayon de carte, et le filet 1 px
   qui vaut #374151 sur fond sombre (design.md 5.3, « bloc sur fond sombre »). Fond et
   filet sont lus dans les tokens que chaque bande redefinit, donc le meme cadre tient
   sur les six fonds du theme sans une variante par couleur. */
.zce__lib-trib-chiffre[data-cadre="oui"] {
  padding: 2rem;
  background: var(--trib-surface);
  border: 1px solid var(--trib-bordure);
  border-radius: var(--trib-rayon-carte);
}

/* AUCUNE MEDIA QUERY, et ce n’est pas un oubli : le bloc d’origine ne porte aucune
   variante de taille selon la largeur — le chiffre fait 48 px du telephone au grand
   ecran. Le repli du triptyque en colonne appartient a la grille qui porte les trois
   blocs, pas au chiffre. */

/* =================================================================================
   lib-trib-citation — l’habillage de la phrase detachee, et de ses deux poses.

   LE FILET SE MERITE. « 4px solid #e30c28 » est releve UNE fois sur tout le site
   (design.md 5.3, colonne n = 1) : c’est la bordure la plus rare du releve, et la seule
   qui soit rouge et epaisse. Deux citations filetees sur une meme page annuleraient
   exactement ce qui lui donne son poids.

   POURQUOI PAS DE SECONDE PARTIELLE POUR LA POSE CENTREE. La pose ne change ni la
   structure ni la classe racine : elle retire un filet et recentre. Une partielle par
   pose voudrait dire une classe racine par pose, donc un marqueur par pose dans le HTML
   construit — deux fichiers a livrer la ou un suffit.
   ================================================================================= */

.zce__lib-trib-citation {
  /* Le navigateur pose « margin: 1em 40px » sur blockquote. Sans cette remise a zero, la
     citation se decale de 40px vers l’interieur et ne s’aligne plus sur le texte de la
     bande qui la porte — l’ecart se verrait immediatement sur une comparaison au pixel. */
  margin: 0;
  padding-left: var(--trib-ecart-serre);
  /* 4px : la mesure. Aucun token de theme ne porte une epaisseur de bordure, parce que
     le site n’en a que deux — 1px pour les cartes, 4px pour ce filet et pour l’anneau
     des pastilles (design.md 5.3). Deux valeurs ne font pas une echelle. */
  border-left: 4px solid var(--trib-accent);

  /* 24/32 sous la premiere rupture, 30/36 au-dessus (design.md 3.2 et 6). */
  font-size: 1.5rem;
  line-height: 2rem;

  /* 700 ET italique, parce que c’est la citation FILETEE qui les porte. Le releve
     mesure deux citations et une seule graisse chacune : celle du manifeste, la seule
     au filet rouge de 4 px, est en 700 italique ; celle de l’accueil, sans filet, est
     en 300 droit (design.md 3.2, ligne « Citation » : « 300 et 700 »). Le filet et la
     graisse vont ensemble — une phrase qu’on detache par un filet, on l’appuie aussi. */
  font-weight: 700;
  font-style: italic;

  /* #1f2937 est mesure sur les DEUX citations du site et sur aucun autre texte : ce
     n’est ni la couleur des titres (#111827) ni celle du corps (#4b5563). Elle est donc
     litterale et ne lit pas le contrat de fond de la bande — une citation vit sur un
     fond clair, et cette teinte intermediaire fait partie de son identite. La poser dans
     une bande sombre la ferait disparaitre : c’est une erreur de composition, pas un
     defaut de brique. */
  color: var(--trib-nuit-douce);

  /* L’interlettrage negatif du theme ne touche QUE les titres (design.md 3.2). A 30px,
     une citation qui en heriterait passerait pour un titre. */
  letter-spacing: normal;
}

/* La rupture a 768px est l’une des deux seules effectives du site (design.md 6). Un
   clamp() donnerait la bonne taille aux deux bouts et le mauvais interligne a l’un
   d’eux : 32/24 et 36/30 ne sont pas le meme rapport. */
@media (min-width: 48rem) {
  .zce__lib-trib-citation {
    font-size: 1.875rem;
    line-height: 2.25rem;
  }
}

/* Les deux graisses de la meme phrase, dans la pose legere. C’est la donnee qui place le
   <strong>, parce que le mot qui pese depend de ce qui est dit. Sans effet sur la pose
   filetee, deja en 700 : c’est voulu, une meme donnee se compose dans les deux poses. */
.zce__lib-trib-citation strong { font-weight: 700; }

/* --- la pose centree -------------------------------------------------------------
   La citation ne s’appuie plus sur une colonne, elle occupe la bande. Le filet tomberait
   alors loin a gauche d’un texte centre, rattache a rien : il part avec sa gouttiere.

   LA GRAISSE PART AVEC LUI. Sans filet, le releve donne 300 droit — la citation de
   l’accueil, posee dans une carte blanche, sans rien qui l’appuie. C’est la pose legere
   du theme : la phrase pese par sa taille, pas par son trait.

   LE CENTRAGE, LUI, N’EST PAS MESURE : les deux citations du releve sont alignees a
   gauche. Il reste ici parce qu’une phrase posee seule au milieu d’une bande est un
   usage que le theme veut offrir — mais c’est une decision de theme, pas un releve. */
.zce__lib-trib-citation[data-pose="centre"] {
  padding-left: 0;
  border-left: 0;
  text-align: center;
  font-weight: 300;
  font-style: normal;
}

/* --- l’attribution -----------------------------------------------------------------
   Elle n’est pas la citation : elle redescend au rang de mention. C’est pour ca qu’elle
   suit le contrat de fond de la bande, la ou la phrase garde sa teinte propre — une
   mention illisible sur fond sombre serait un vrai defaut, pas un choix. */
.zce__lib-trib-citation__source {
  display: block;
  margin-top: var(--trib-gouttiere);
  font-size: .875rem;
  line-height: 1.25rem;
  /* <cite> sort en italique d’usine, et aucune source du releve ne l’est. */
  font-style: normal;
  color: var(--trib-texte-faible);
}

/* Sans source, la ligne ne laisse pas non plus son ecart derriere elle. */
.zce__lib-trib-citation__source:empty { display: none; }

/* =================================================================================
   lib-trib-diptyque — deux volets qui s’opposent, ET le volet lui-meme.

   UNE SEULE FEUILLE POUR DEUX BRIQUES. lib-trib-volet ne porte pas de classe racine a
   lui : il rend `lib-trib-diptyque__volet`. C’est voulu, et c’est ce qui fait que cette
   partielle est livree par le seul marqueur du diptyque — un volet ne parait jamais
   sans lui, puisqu’un volet seul n’oppose rien.
   ================================================================================= */

.zce__lib-trib-diptyque {
  display: grid;
  /* 48px et non 32. Les deux sources se contredisaient : le tableau agrege de
     design.md 6.1 range « Comparatif avant/apres » a 32px, mais le DOM de la
     section que cette brique NOMME — « La Grande Bascule » sur /manifeste —
     porte gap-12. Mesure du 2026-09-25 sur le DOM rendu : c'est 48. La valeur
     peinte l'emporte sur le tableau qui la resume. */
  gap: var(--trib-ecart-large);
  /* Les volets se centrent l’un sur l’autre au lieu de s’aligner par le haut (mesure :
     `items-center`). Deux listes de longueurs inegales restent ainsi face a face, au
     lieu de laisser la plus courte flotter au-dessus d’un trou. */
  align-items: center;
}

/* La seule rupture de la brique. En dessous, les volets s’empilent et l’opposition se
   relit dans l’ordre du recit. L’autre rupture du site, 1024 px, ne sert que les grilles
   a 3 et 4 colonnes. Rupture en rem : voir lib-trib-bande.css. */
@media (min-width: 48rem) {
  .zce__lib-trib-diptyque {
    grid-template-columns: 1fr 1fr;
  }
}

/* Le volet n’a ni fond, ni cadre, ni retrait : ce qui l’oppose a son voisin, c’est son
   TON, pas une boite. Il n’existe ici que pour porter data-ton aux deux endroits qui le
   lisent — la couleur du titre et celle des puces. */

.zce__lib-trib-diptyque__titre {
  /* 24px sous le titre : la seule valeur de l’echelle des ecarts de titre qui soit
     assez large pour detacher la liste, et assez serree pour qu’elle reste rattachee
     au titre plutot qu’au volet voisin. */
  margin: 0 0 var(--trib-ecart-serre);
  /* 30/36, le « h3 large » du releve (design.md 3.2) — et non le 24/32 d’un h3 de carte.
     Les deux volets mesures le portent : « Avant : Exploration Active » et
     « Aujourd’hui : Orchestration Invisible » sont en text-3xl. Un volet titre a la
     taille d’une carte perd l’ecart de rang qui le distingue de ce qu’il enumere. */
  font-size: 1.875rem;
  line-height: 2.25rem;
  font-weight: 700;
  /* -0.025em : l’interlettrage negatif du theme ne touche QUE les titres, jamais les
     chiffres ni le corps. Sur 30px il vaut les -0.75px releves. */
  letter-spacing: -.025em;
  color: var(--trib-texte-fort);
}

.zce__lib-trib-diptyque__titre:empty { display: none; }

.zce__lib-trib-diptyque__points {
  display: grid;
  /* 16px entre deux items : assez pour que chaque point se compte a l’oeil, trop peu
     pour qu’il se lise comme un paragraphe autonome. */
  gap: 1rem;
  margin: 0;
  padding: 0;
  list-style: none;
}

.zce__lib-trib-diptyque__points:empty { display: none; }

/* La regle part de la classe de la liste et jamais du type seul : les <li> arrivent par
   la donnee, donc sans classe a prefixer, et une regle sur `li` nu fuirait dans toute la
   feuille du site. */
.zce__lib-trib-diptyque__points > li {
  position: relative;
  /* 24px = la puce (8px) plus son ecart au texte (16px). Le texte s’aligne donc sur une
     seule verticale, y compris quand un point passe a la ligne. */
  padding-left: 1.5rem;
  font-size: 1rem;
  line-height: 1.6;
  color: var(--trib-texte);
}

/* La puce est un ::before et non un element : elle n’enonce rien, et un lecteur d’ecran
   qui l’annoncerait ferait perdre le point qu’elle introduit. */
.zce__lib-trib-diptyque__points > li::before {
  content: "";
  position: absolute;
  left: 0;
  /* 12px depuis le haut de la ligne : la puce tombe legerement SOUS l’axe des majuscules
     plutot que sur le milieu optique. C’est la valeur relevee, et elle tient le meme
     alignement quelle que soit la casse du premier mot. */
  top: .75em;
  width: .5rem;
  height: .5rem;
  border-radius: var(--trib-rayon-pastille);
  background: var(--trib-tertiaire);
}

/* --- le ton : ce qui separe le volet revolu du volet actuel ------------------------
   Le volet sans ton, ou en « revolu », est deja habille par les regles ci-dessus : un
   diptyque compose a moitie ne sort donc jamais nu. Seul l’accent se declare.

   L’accent passe par --trib-lien et non par --trib-accent en dur, parce que la meme
   brique doit tenir sur les six fonds du theme. Le rouge de marque vire au brun sur un
   fond sombre ; la bande y bascule deja --trib-lien vers le ton clair, qui est
   exactement la couleur relevee pour les accents de titre sur fond sombre. Ecrire
   --trib-accent ici obligerait a une variante de la brique par couleur de fond. */

.zce__lib-trib-diptyque__volet[data-ton="actuel"] .zce__lib-trib-diptyque__titre {
  color: var(--trib-lien);
}

.zce__lib-trib-diptyque__volet[data-ton="actuel"] .zce__lib-trib-diptyque__points > li {
  /* Le volet actuel ne se distingue pas seulement par ses puces : son texte est plus
     sombre et un demi-cran plus gras. C’est ce qui fait que l’opposition survit au noir
     et blanc, et a un lecteur qui ne distingue pas le rouge du gris. */
  color: var(--trib-texte-fort);
  font-weight: 500;
}

.zce__lib-trib-diptyque__volet[data-ton="actuel"] .zce__lib-trib-diptyque__points > li::before {
  background: var(--trib-lien);
}

/* =================================================================================
   lib-trib-entete — la barre de tete fixe, et le ruban de navigation qu'elle porte.

   ELLE VIT HORS DES BANDES. C'est pour elle que lib-trib-bande.css declare son echelle
   sur « :root, .lib-trib-bande » et non sur la bande seule : sans ca la barre sortirait
   sans filet, sans rayon et sans duree. Elle ne lit donc PAS --trib-fond ni --trib-texte,
   qui se recalculent a l'entree de chaque bande. Une tete fixe ne traverse rien : elle
   reste claire au-dessus d'une bande sombre, exactement comme dans le releve.

   LA LIVRAISON DE CETTE PARTIELLE TIENT A LA CLASSE RACINE, PAS AUX CLASSES FILLES. Le
   marqueur cherche « <prefixe>__lib-trib-entete » suivi d'une FRONTIERE DE NOM
   (build_network.py:5031). « ...__lib-trib-entete__lien » ne matche donc pas, le « _ »
   qui suit etant un caractere de mot. C'est le <header class="lib-trib-entete"> qui
   declenche la livraison, et lui seul — lib-trib-lien-nav n'apparaissant jamais sans son
   header, le compte tombe juste.

   AUCUNE FAMILLE DE POLICE N'EST DECLAREE ICI. Le releve etablit qu'une seule famille est
   calculee sur l'ensemble du site (design.md 3.1) : la redeclarer par brique n'ajouterait
   que du bruit et une occasion de diverger.
   ================================================================================= */

.zce__lib-trib-entete {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: 50;
  /* Fond blanc a 95% d'opacite, mesure (design.md 4.1). Le color-mix part du token pour
     qu'un site qui redefinit son blanc emmene la barre avec lui. */
  background: color-mix(in srgb, var(--trib-clair) 95%, transparent);
  /* Le filet bas mesure : 1px solid #f3f4f6 — la meme valeur que la bordure de carte
     dominante du site (85 occurrences), d'ou le token partage. */
  border-bottom: 1px solid var(--trib-trait);
}

/* Le flou ne s'arme que la ou il existe : ailleurs un fond deja opaque a 95% reste
   parfaitement lisible, et rien ne se voit. */
@supports (backdrop-filter: blur(1px)) {
  .zce__lib-trib-entete { backdrop-filter: blur(12px); }
}

/* La rangee porte a elle seule le conteneur, la gouttiere et les marges haute et basse :
   le modele empilait deux divs pour ca. 16px sur les quatre cotes, mesures — la gouttiere
   laterale constante du site (design.md 4.2) est aussi sa marge verticale ici. C'est ce
   16px, plus les 40px de la rangee, plus le filet, qui font les 73px releves. */
.zce__lib-trib-entete__rang {
  max-width: var(--trib-large);
  margin: 0 auto;
  padding: var(--trib-gouttiere);
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: calc(var(--trib-gouttiere) / 2) var(--trib-gouttiere);
}

/* --- la marque -------------------------------------------------------------------- */

.zce__lib-trib-entete__marque {
  display: inline-flex;
  align-items: center;
  flex: none;
  /* 12px mesures entre la pastille et le mot ; derives de la gouttiere pour qu'un site
     qui resserre sa grille resserre aussi sa marque. */
  gap: calc(var(--trib-gouttiere) * .75);
  text-decoration: none;
}

/* La pastille : 32x32 mesures, rouge de marque, un signe blanc en gras. Le rayon releve
   vaut 10px ; la couche de tokens du theme n'en porte pas, et cette brique ne modifie pas
   le fichier d'un autre pour en ajouter un. --trib-rayon-bloc vaut 12px, qui EST un rayon
   du site — 12 pastilles le portent. L'ecart de 2px sur un carre de 32 ne se voit pas ;
   une valeur hors echelle, elle, se verrait partout ailleurs. */
.zce__lib-trib-entete__signe {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: none;
  width: 2rem;
  height: 2rem;
  border-radius: var(--trib-rayon-bloc);
  background: var(--trib-accent);
  color: var(--trib-clair);
  font-size: .875rem;
  font-weight: 700;
  line-height: 1.25rem;
}

.zce__lib-trib-entete__signe:empty { display: none; }

/* 20px / 28px / 700, mesures. AUCUN interlettrage : le tableau de design.md range le logo
   sur la meme ligne que le h3 courant et lui prete son -0.5px, mais le releve brut mesure
   « normal » sur le bouton du logo. C'est la valeur peinte qui fait foi. */
.zce__lib-trib-entete__mot {
  font-size: 1.25rem;
  line-height: 1.75rem;
  font-weight: 700;
  color: var(--trib-titre);
  transition: color var(--trib-transition);
}

/* Le survol du logo vire au rouge de marque, comme dans le releve. La seule transition du
   theme qui s'applique ici : 150ms sur la couleur, rien d'autre. */
.zce__lib-trib-entete__marque:hover .zce__lib-trib-entete__mot,
.zce__lib-trib-entete__marque:focus-visible .zce__lib-trib-entete__mot {
  color: var(--trib-accent);
}

/* --- le ruban de navigation --------------------------------------------------------- */

/* Sous 1024px la nav prend une ligne entiere et defile sur elle-meme. min-width: 0 n'est
   pas cosmetique : sans lui, la valeur initiale « auto » force l'element flex a au moins
   la largeur de son contenu, et c'est la BARRE ENTIERE qui deborde de l'ecran au lieu du
   seul ruban. overscroll-behavior evite que le balayage horizontal du ruban ne declenche
   le retour arriere du navigateur.

   overflow-x reste « auto » a TOUTES les largeurs, y compris au-dessus de 1024px : sans
   lui, un site qui declare douze rubriques au lieu de huit verrait sa nav recouvrir son
   action. Quand le contenu tient, un conteneur de defilement ne se voit pas. */
.zce__lib-trib-entete__nav {
  order: 1;
  flex: 1 0 100%;
  min-width: 0;
  overflow-x: auto;
  overscroll-behavior-x: contain;
  scrollbar-width: thin;
}

/* Sans entree, le ruban ne laisse pas une ligne vide derriere lui. */
.zce__lib-trib-entete__nav:has(.zce__lib-trib-entete__liste:empty) { display: none; }

/* 24px d'ecart, mesures (space-x-6) — la valeur serree de l'echelle du theme. */
.zce__lib-trib-entete__liste {
  display: flex;
  align-items: center;
  gap: var(--trib-ecart-serre);
  margin: 0;
  padding: 0;
  list-style: none;
}

/* Rien ne se comprime dans un ruban qui defile : un libelle casse en deux lignes fait
   grandir la barre au lieu de la faire defiler. */
.zce__lib-trib-entete__entree {
  display: flex;
  flex: none;
}

/* 14px / 20px / 500, mesures. La hauteur de 40px, elle, ne vient pas du menu d'origine —
   dont les entrees sont « des <button> sans padding », donc des cibles de 20px de haut.
   Elle vient du bouton d'action mesure (h-10, 40px) : toute cible de la barre fait la
   meme hauteur, et c'est ce 40px qui produit les 73px releves. */
.zce__lib-trib-entete__lien,
.zce__lib-trib-entete__ici {
  display: inline-flex;
  align-items: center;
  min-height: 2.5rem;
  font-size: .875rem;
  line-height: 1.25rem;
  font-weight: 500;
  white-space: nowrap;
  text-decoration: none;
}

.zce__lib-trib-entete__lien {
  color: var(--trib-corps);
  transition: color var(--trib-transition);
}

.zce__lib-trib-entete__lien:hover,
.zce__lib-trib-entete__lien:focus-visible {
  color: var(--trib-accent);
}

/* La mention de la page courante se distingue SANS couleur : le rouge est reserve au
   survol, et un etat permanent qui emprunte la couleur d'un etat transitoire se lit comme
   un survol coince. Elle prend donc le ton des titres et la graisse. */
.zce__lib-trib-entete__ici {
  display: none;
  color: var(--trib-titre);
  font-weight: 700;
}

/* Deux facons de dire « on y est deja » : le marqueur pose par le gabarit, et une cible
   vide — qui est la meme chose vue du HTML livre. Les deux retirent le lien. L'attribut
   est porte par le <li> et non par le lien : un selecteur descendant suffit alors pour la
   voie nominale, sans :has(). */
.zce__lib-trib-entete__entree[data-courant="oui"] .zce__lib-trib-entete__lien,
.zce__lib-trib-entete__lien[href=""] {
  display: none;
}

.zce__lib-trib-entete__entree[data-courant="oui"] .zce__lib-trib-entete__ici,
.zce__lib-trib-entete__entree:has(.zce__lib-trib-entete__lien[href=""]) .zce__lib-trib-entete__ici {
  display: inline-flex;
}

/* --- l'action --------------------------------------------------------------------- */

/* Mesures : 40px de haut (h-10), 24px de padding lateral (px-6), entierement arrondi,
   14px/500 blanc sur le rouge de marque. L'arrondi total est la signature de forme du
   theme : un bouton a coins adoucis la trahit immediatement. */
.zce__lib-trib-entete__action {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: none;
  min-height: 2.5rem;
  padding-inline: var(--trib-ecart-serre);
  border-radius: var(--trib-rayon-pastille);
  background: var(--trib-accent);
  color: var(--trib-clair);
  font-size: .875rem;
  line-height: 1.25rem;
  font-weight: 500;
  white-space: nowrap;
  text-decoration: none;
  transition: background-color var(--trib-transition), color var(--trib-transition);
}

/* Le ton bas du rouge de marque est exactement le survol mesure des boutons du site. */
.zce__lib-trib-entete__action:hover,
.zce__lib-trib-entete__action:focus-visible {
  background: var(--trib-accent-bas);
}

/* Sans libelle ou sans cible, il n'y a pas d'action : il y a une pastille rouge vide. */
.zce__lib-trib-entete__action:empty,
.zce__lib-trib-entete__action[href=""] {
  display: none;
}

/* --- le parcours au clavier --------------------------------------------------------- */

.zce__lib-trib-entete__marque:focus-visible,
.zce__lib-trib-entete__action:focus-visible {
  outline: 2px solid var(--trib-accent);
  outline-offset: 2px;
}

/* Dans le ruban, overflow-x: auto force overflow-y a « auto » lui aussi : un contour pose
   a l'EXTERIEUR du lien serait rogne en haut et en bas, voire ferait apparaitre un
   defilement vertical de quelques pixels. Il se pose donc en dedans — le lien fait 40px
   de haut pour 20px de texte, la place y est. */
.zce__lib-trib-entete__lien:focus-visible {
  outline: 2px solid var(--trib-accent);
  outline-offset: -2px;
}

@media (prefers-reduced-motion: reduce) {
  .zce__lib-trib-entete__mot,
  .zce__lib-trib-entete__lien,
  .zce__lib-trib-entete__action { transition: none; }
}

/* --- 1024px : la nav remonte sur la ligne ------------------------------------------- */

/* POURQUOI 1024 ET PAS 768. C'est la largeur ou les huit rubriques tiennent, et le releve
   le montre deux fois. Largeurs mesurees des libelles a 1024px : 46 + 39 + 47 + 116 + 64
   + 69 + 58 + 63 = 502px, plus sept gouttieres de 24px = 670px ; avec 92px de marque et
   96px d'action, 858px pour 992px utiles. A 768px il manque une centaine de pixels — et
   c'est exactement la que l'original fait apparaitre son menu (hidden lg:flex, design.md
   6.2). Le point de rupture n'est pas un gout, c'est une contrainte de place.

   Seuls l'ordre et la base changent : la nav reprend sa position de source, entre la
   marque et l'action, et space-between la depose au centre-droit — ce que la capture a
   1440px montre, nav centree a un ou deux pixels pres. */
@media (min-width: 64rem) {
  .zce__lib-trib-entete__nav {
    order: 0;
    flex: 0 1 auto;
  }
}

/* =================================================================================
   lib-trib-exergue — la portion de titre en couleur.

   ELLE A SA PROPRE PARTIELLE parce qu’elle a sa propre classe racine : le marqueur
   <prefixe>__lib-trib-exergue n’apparait que sur les pages qui s’en servent, et la regle
   n’est livree que la (build_network.py:5030-5031). Elle est minuscule et c’est normal —
   une exergue ne fait qu’une chose.

   QUATRE TONS, PAS UNE ECHELLE OUVERTE. Le releve ne mesure que quatre couleurs
   d’accent dans les titres du site : #ef4444, #f87171, #fb923c et #e30c28 (design.md 1.1,
   1.2, 1.5). Ouvrir la liste reviendrait a laisser chaque page inventer sa nuance, et
   c’est exactement ce qui fait qu’un site cesse de ressembler a lui-meme.
   ================================================================================= */

/* Sans ton declare, l’exergue prend la couleur de lien de sa bande — le seul token du
   theme qui sait deja s’il est pose sur du clair ou sur du sombre. Un ton oublie sort
   donc colore et lisible, au lieu de se fondre dans la couleur du titre. */
.zce__lib-trib-exergue { color: var(--trib-lien); }

.zce__lib-trib-exergue[data-ton="vif"]    { color: var(--trib-accent-vif); }
.zce__lib-trib-exergue[data-ton="clair"]  { color: var(--trib-accent-clair); }
.zce__lib-trib-exergue[data-ton="chaud"]  { color: var(--trib-chaud); }
.zce__lib-trib-exergue[data-ton="accent"] { color: var(--trib-accent); }

/* lib-trib-frise — l’axe, les points, et le cartouche de chaque etape.

   UNE SEULE PARTIELLE POUR DEUX BRIQUES. lib-trib-etape ne porte pas de classe racine a
   elle : elle rend lib-trib-frise__etape, donc elle est habillee ici. C’est voulu — son
   cote et sa largeur dependent de son rang DANS la frise, elle n’a aucun sens seule. */

/* Le zero de padding est porteur, pas cosmetique : un <ol> recoit 40px de retrait par
   defaut, et l’axe ci-dessous se place a 50% de la BOITE DE PADDING. Le laisser
   decalerait l’axe de 20px vers la gauche du milieu des cartes, un ecart trop petit pour
   sauter aux yeux et trop gros pour que la frise paraisse droite. */
.zce__lib-trib-frise {
  position: relative;
  margin: 0;
  padding: 0;
  list-style: none;
}

/* L’axe. 2px de large et le rouge le plus pale de l’echelle : mesure du 2026-09-25 sur
   /manifeste, w-0.5 peint en #fecaca (design.md §1.2). Un axe a la couleur de marque
   pleine ferait une barre qui hurle au milieu de la page ; ici il guide sans peser.
   Le -1px le centre sur la mediane malgre sa largeur paire. */
.zce__lib-trib-frise::before {
  content: "";
  position: absolute;
  top: 0;
  bottom: 0;
  left: 50%;
  margin-left: -1px;
  width: 2px;
  background: var(--trib-accent-pale);
}

.zce__lib-trib-frise__etape {
  position: relative;
}

/* L’ecart se pose ENTRE les etapes et jamais apres la derniere : la respiration du bas
   appartient a la bande qui contient la frise, pas a la frise. Mesure : 48px (mb-12),
   qui est exactement --trib-ecart-large. */
.zce__lib-trib-frise__etape + .zce__lib-trib-frise__etape {
  margin-top: var(--trib-ecart-large);
}

/* Le point sur l’axe. En ::before, donc absent de l’arbre d’accessibilite sans qu’on ait
   a poser un aria-hidden sur un element qui n’aurait aucune autre raison d’exister.
   16px de cote dont 4px d’anneau (mesure : w-4 h-4 + border-4, design.md §5.3), ce qui
   laisse un disque de 8px. L’anneau prend --trib-surface et non le blanc en dur : il doit
   detacher le point de l’AXE, donc valoir la couleur du fond de la bande — blanc sur les
   bandes claires, ou il vaut le #ffffff mesure.
   box-sizing est redeclare ici parce que ces 16px comptent l’anneau : sans lui, le point
   sortirait a 24px et mordrait sur les cartes. */
.zce__lib-trib-frise__etape::before {
  content: "";
  position: absolute;
  top: 50%;
  left: 50%;
  box-sizing: border-box;
  margin: -.5rem 0 0 -.5rem;
  width: 1rem;
  height: 1rem;
  border: 4px solid var(--trib-surface);
  border-radius: var(--trib-rayon-pastille);
  background: var(--trib-accent);
  box-shadow: var(--trib-ombre-haute);
}

/* LE CARTOUCHE — et toute l’alternance.
   Une moitie moins l’ecart a l’axe (mesure : pr-8 / pl-8 = 32px = --trib-ecart). Le cote
   se deduit du RANG et de rien d’autre, d’ou :nth-child : aucune donnee ne dit « a
   droite », donc inserer une etape au milieu rebascule la suite toute seule, et deux
   etapes du meme cote sont impossibles a ecrire. */
.zce__lib-trib-frise__carte {
  box-sizing: border-box;
  width: calc(50% - var(--trib-ecart));
  padding: var(--trib-ecart-serre);
  border: 1px solid var(--trib-bordure);
  border-radius: var(--trib-rayon-bloc);
  background: var(--trib-surface);
  box-shadow: var(--trib-ombre);
  /* La seule elevation du theme, sur la seule duree longue qu’il declare — mesure :
     transition-shadow 300ms cubic-bezier(.4,0,.2,1) sur ces cartes (design.md §7). */
  transition: box-shadow var(--trib-transition-lente);
  /* Le texte se range VERS l’axe : a gauche de l’axe il finit contre lui, a droite il en
     part. C’est ce qui fait lire la frise comme un seul mouvement plutot que comme deux
     colonnes. Mesure : text-right sur les etapes impaires, defaut sur les paires. */
  text-align: right;
}

.zce__lib-trib-frise__etape:nth-child(even) .zce__lib-trib-frise__carte {
  margin-left: calc(50% + var(--trib-ecart));
  text-align: left;
}

.zce__lib-trib-frise__carte:hover {
  box-shadow: var(--trib-ombre-haute);
}

.zce__lib-trib-frise__titre {
  margin: 0 0 .5rem;
  font-size: 1.25rem;
  line-height: 1.75rem;
  font-weight: 700;
  letter-spacing: -.025em;
  color: var(--trib-texte-fort);
}

/* La periode prend --trib-lien et non --trib-accent en dur : c’est le seul accent que la
   bande redefinit selon son fond. Sur la bande claire ou la frise est mesuree il resout
   exactement le #e30c28 releve ; sur une bande sombre il passe au ton clair au lieu de
   virer au brun illisible. */
.zce__lib-trib-frise__periode {
  margin: 0 0 .5rem;
  font-size: .875rem;
  line-height: 1.25rem;
  font-weight: 500;
  color: var(--trib-lien);
}

.zce__lib-trib-frise__texte {
  margin: 0;
  font-size: 1rem;
  line-height: 1.6;
  color: var(--trib-texte);
}

/* Une etape reduite a son titre ne doit pas trainer les deux ecarts de ce qui manque. */
.zce__lib-trib-frise__titre:empty,
.zce__lib-trib-frise__periode:empty,
.zce__lib-trib-frise__texte:empty {
  display: none;
}

/* SOUS 768px, TOUT PASSE A GAUCHE — et ce n’est pas un confort.
   L’original garde l’alternance jusqu’en bas : mesure du 2026-09-25 a 390px, chaque
   carte tombe a 163px de large et « Pages fixes, navigation manuelle » se casse sur
   trois lignes de deux mots. Une frise qu’on ne lit plus ne raconte plus rien.
   L’axe file donc au bord, les cartes s’alignent dessus, et l’ecart a l’axe reste le
   meme qu’en grand ecran : 8px pour le demi-point, plus les 32px de --trib-ecart.
   768 px est la premiere rupture reelle du releve (design.md §6). 47.99rem s'arrete
   juste sous les 48rem ou les briques voisines passent en deux colonnes — rupture en
   rem, voir lib-trib-bande.css. */
@media (max-width: 47.99rem) {
  .zce__lib-trib-frise::before,
  .zce__lib-trib-frise__etape::before {
    left: .5rem;
  }

  .zce__lib-trib-frise__etape {
    padding-left: calc(var(--trib-ecart) + .5rem);
  }

  .zce__lib-trib-frise__carte,
  .zce__lib-trib-frise__etape:nth-child(even) .zce__lib-trib-frise__carte {
    width: auto;
    margin-left: 0;
    text-align: left;
  }
}

/* =================================================================================
   lib-trib-heros — le haut de page.

   Toutes les valeurs ci-dessous sont relevees au navigateur sur le site copie
   (design.md, mesure du 2026-09-25), jamais deduites d’une classe utilitaire. Quand une
   valeur n’existe pas dans la couche de tokens de lib-trib-bande.css, elle est citee avec
   sa source et la raison pour laquelle elle reste locale.

   CE FICHIER HABILLE AUSSI lib-trib-heros-action. Une action de heros n’a pas de classe
   racine a elle — elle rend .lib-trib-heros__action — donc pas de partielle a elle non
   plus : c’est le marqueur <prefixe>__lib-trib-heros qui decide de la livraison
   (build_network.py:5030-5031), et ce marqueur est deja pose par le heros qui la contient.
   ================================================================================= */

.zce__lib-trib-heros {
  /* --- le seul bleu du site ------------------------------------------------------
     #3b82f6 n’apparait nulle part ailleurs : c’est le disque floute de gauche, et rien
     d’autre (releve 1.6). Il reste declare ICI et pas dans la couche globale parce qu’un
     token global est une invitation a le reutiliser — et un bleu de plus dans une tribune
     rouge et grise, c’est l’identite qui se dissout. */
  --trib-heros-bleu: #3b82f6;

  /* Dans ce theme la bande porte le rythme vertical, et les briques n’y touchent pas —
     lib-trib-section ne declare pas un seul padding. Un heros est le seul cas ou ca ne
     suffit pas : il passe sous une barre de tete fixe de 73 px et respire donc 128 px en
     haut, contre 80 pour une section courante (releve 4.1).

     Il ne REMPLACE pas le rythme de la bande, il COMPLETE ce qui manque : 8rem moins les
     5rem deja posees. Une marge negative aurait donne le meme total, mais aurait aussi
     fait monter le heros par-dessus ce qui le precede le jour ou quelqu’un le pose sous
     un autre contenu. En haut seulement : le bas du heros vaut deja 80 px.

     La gouttiere laterale de 16 px vient elle aussi de la bande et n’est pas redeclaree. */
  padding-top: calc(var(--trib-pas-heros) - var(--trib-pas-section));
  text-align: center;

  /* Volontairement SANS position: relative. Les halos remontent ainsi jusqu’a
     .lib-trib-bande, qui est la seule boite pleine largeur : c’est ce qui les colle aux
     bords de l’ECRAN et non aux bords de la colonne de 72rem, comme sur le releve
     (disque droit mesure a x=1056 pour une fenetre de 1440, soit le bord exact). */
}

/* --- les deux halos -------------------------------------------------------------
   Deux disques pleins, floutes a 64 px, a 20 % d’opacite. L’opacite ne vient pas des
   disques eux-memes (mesures a 1) mais de leur conteneur « absolute inset-0 opacity-20 »
   dans le DOM releve ; ce conteneur n’existe plus ici, son opacite est portee par chaque
   disque. A pleine opacite le heros vire au rouge vif et le texte devient illisible.

   Ils ne peuvent pas creer de barre de defilement horizontale : .lib-trib-bande porte
   deja overflow-x: clip. C’est dit ici parce que la regle vit dans un autre fichier, et
   qu’un halo qui deborde de 300 px est exactement le genre de chose qu’on cherche une
   heure dans la mauvaise partielle. */
.zce__lib-trib-heros__halo {
  position: absolute;
  border-radius: var(--trib-rayon-pastille);
  filter: blur(64px); /* releve section 2 */
  opacity: .2;
  pointer-events: none;
}

.zce__lib-trib-heros__halo--droite {
  top: 25%;
  right: 0;
  width: 384px;  /* releve : 384 x 384 */
  height: 384px;
  background: var(--trib-accent-vif);
}

.zce__lib-trib-heros__halo--gauche {
  bottom: 25%;
  left: 0;
  width: 320px;  /* releve : 320 x 320 */
  height: 320px;
  background: var(--trib-heros-bleu);
}

/* Le contenu passe devant les halos. Le z-index est indispensable : sans lui, deux
   elements positionnes situes PLUS HAUT dans le flux ne suffiraient pas — ce sont les
   derniers positionnes qui gagnent, et le titre passerait dessous. */
.zce__lib-trib-heros__contenu {
  position: relative;
  z-index: 1;
}

/* --- la pastille ----------------------------------------------------------------
   Fond et bordure sont translucides et derives du token d’accent plutot qu’ecrits en
   dur. Le releve donne rgba(227,12,40,.20) pour le fond et rgba(239,68,68,.30) pour la
   bordure (releve 5.3) — exactement ce que rendent les deux color-mix ci-dessous. Les
   deriver evite le seul vrai risque : un site qui redefinit --trib-accent dans sa propre
   feuille garderait sinon une pastille au rouge d’origine autour d’un theme retinte. */
.zce__lib-trib-heros__pastille {
  display: inline-flex;
  align-items: center;
  gap: .5rem;               /* releve : 8 px entre l’icone et le mot */
  margin-bottom: 2rem;      /* releve : 32 px sous la pastille */
  padding: .75rem 1.5rem;   /* releve : 12 px / 24 px */
  border: 1px solid color-mix(in srgb, var(--trib-accent-vif) 30%, transparent);
  border-radius: var(--trib-rayon-pastille);
  background: color-mix(in srgb, var(--trib-accent) 20%, transparent);
  color: var(--trib-accent-pale);
  font-size: 1rem;
  font-weight: 500;
  line-height: 1.5;
}

/* display: none et pas visibility: hidden — la marge de 32 px doit partir avec. */
.zce__lib-trib-heros__pastille:empty { display: none; }

/* --- le titre --------------------------------------------------------------------
   72/72 au-dessus de 768 px, 48/48 en dessous (releve 3.2). L’interligne vaut 1 : un
   titre de heros sur trois lignes se tient, il ne se deroule pas.

   L’interlettrage est donne en em et non en px, parce que les deux paliers du releve
   — moins 1.8 px a 72 et moins 1.2 px a 48 — sont la MEME valeur relative. En px il
   faudrait le redeclarer dans la media query, et l’un des deux finirait par diverger. */
.zce__lib-trib-heros__titre {
  margin: 0 0 2rem;       /* releve 4.4 : un h1 ouvre 32 px sous lui, jamais au-dessus */
  font-size: 3rem;
  line-height: 1;
  font-weight: 700;
  letter-spacing: -.025em;
  color: var(--trib-texte-fort);
}

/* --- le chapo ---------------------------------------------------------------------
   24/32 au-dessus de 768 px, 20/28 en dessous (releve 3.2). Il est ramene a 56rem alors
   que la bande en autorise 72 : au-dela la ligne devient trop longue pour etre relue, et
   le releve le confirme (896 px mesures sur le chapo, section 4.2). */
.zce__lib-trib-heros__chapo {
  max-width: var(--trib-moyen);
  margin: 0 auto 3rem;     /* releve : 48 px avant la ligne d’actions */
  font-size: 1.25rem;
  line-height: 1.75rem;
  font-weight: 400;
  color: var(--trib-texte);
}

.zce__lib-trib-heros__chapo:empty { display: none; }

/* --- la ligne d’actions -----------------------------------------------------------
   En colonne d’abord : la capture mobile du releve montre des actions PLEINE LARGEUR,
   ce que donne l’etirement par defaut d’un conteneur en colonne. Deux boutons cote a
   cote sur 390 px se toucheraient au doigt. */
.zce__lib-trib-heros__actions {
  display: flex;
  flex-direction: column;
  gap: var(--trib-ecart-serre);   /* releve : 24 px */
}

.zce__lib-trib-heros__actions:empty { display: none; }

/* --- l’action ---------------------------------------------------------------------
   L’etat plein est l’etat PAR DEFAUT, et non une valeur a declarer. Une action sans
   data-ton reste donc lisible au lieu de sortir transparente ; seul le second role, plus
   rare, se declare.

   Hauteur plancher 44 px et remplissage lateral de 32 px (releve boutons_hero). Le
   releve donne aussi 16 px de remplissage vertical, qui ne peint rien — la hauteur fixe
   le recouvre — et qui n’est donc pas reporte. 44 px est aussi le plancher confortable
   d’une cible tactile.

   Le rayon est celui des pastilles, pas celui des cartes : dans ce theme un bouton est
   ENTIEREMENT arrondi, et un bouton a coins adoucis le trahit immediatement. */
.zce__lib-trib-heros__action {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: .5rem;
  min-height: 2.75rem;
  padding: 0 2rem;
  border: 1px solid var(--trib-accent);
  border-radius: var(--trib-rayon-pastille);
  background: var(--trib-accent);
  color: var(--trib-clair);
  font-size: 1.125rem;      /* releve 3.2 : bouton principal 18/28, graisse 500 */
  line-height: 1.75rem;
  font-weight: 500;
  text-align: center;
  text-decoration: none;
  /* Le releve ne mesure que deux mouvements sur tout le site : 150 ms sur la couleur,
     300 ms sur l’ombre des cartes (design.md 7). Enumerer les proprietes plutot que
     « all » evite d’animer la hauteur le jour ou un libelle passe sur deux lignes. */
  transition: background-color var(--trib-transition),
              border-color var(--trib-transition),
              color var(--trib-transition);
}

.zce__lib-trib-heros__action:hover,
.zce__lib-trib-heros__action:focus-visible {
  border-color: var(--trib-accent-bas);
  background: var(--trib-accent-bas);
}

/* Le releve donne cette action avec un fond BLANC et un texte blanc : le libelle y est
   invisible (design.md 8, anomalie bloquante). Ce n’est pas un parti pris graphique,
   c’est un defaut — la bordure blanche seule trahit l’intention d’un bouton fantome.
   Le fond transparent est donc retabli. */
.zce__lib-trib-heros__action[data-ton="fantome"] {
  border-color: var(--trib-clair);
  background: transparent;
  color: var(--trib-clair);
}

.zce__lib-trib-heros__action[data-ton="fantome"]:hover,
.zce__lib-trib-heros__action[data-ton="fantome"]:focus-visible {
  background: var(--trib-clair);
  color: var(--trib-nuit-pleine);
}

/* --- au-dessus de 768 px ----------------------------------------------------------
   Le releve n’etablit que deux ruptures effectives, 768 et 1024 px (design.md 6), et
   rien de ce heros ne bouge a 1024 : une seule media query suffit. */
@media (min-width: 48rem) {

  .zce__lib-trib-heros__titre { font-size: 4.5rem; }

  .zce__lib-trib-heros__chapo {
    font-size: 1.5rem;
    line-height: 2rem;
  }

  .zce__lib-trib-heros__actions {
    flex-direction: row;
    flex-wrap: wrap;
    justify-content: center;
  }
}

/* =================================================================================
   lib-trib-pied — le pied de page sombre.

   IL DEPEND DE lib-trib-bande.css, qui declare l'echelle du theme sur « :root,
   .lib-trib-bande ». Le pied vit hors de la sequence de bandes : sans la moitie
   « :root » de cette declaration, il sortirait sans tokens. La bande etant presente sur
   toute page de tribune, la dependance tient.

   IL REDEFINIT CE QUE LES BRIQUES LISENT, comme .lib-trib-bande--sombre. Le fond mesure
   #111827 (design.md 1.3, « pied de page plein ») : c'est exactement --trib-nuit, donc
   les memes redefinitions, et aucune brique posee dedans n'a besoin d'une variante.
   ================================================================================= */

.zce__lib-trib-pied {
  --trib-fond: var(--trib-nuit);
  --trib-texte: var(--trib-sur-nuit);
  --trib-texte-fort: var(--trib-clair);
  --trib-texte-faible: var(--trib-tertiaire);
  --trib-surface: var(--trib-nuit-douce);
  --trib-bordure: var(--trib-nuit-trait);
  --trib-lien: var(--trib-accent-clair);

  background: var(--trib-nuit);
  color: var(--trib-texte);
}

/* 64 px en haut comme en bas (design.md 4.1) : le pied respire MOINS qu'une section a
   80 px, parce qu'il ferme au lieu d'ouvrir. C'est ce que porte --trib-pas-pied. */
.zce__lib-trib-pied__inner {
  max-width: var(--trib-large);
  margin: 0 auto;
  padding-block: var(--trib-pas-pied);
  padding-inline: var(--trib-gouttiere);
}

/* --- la grille des colonnes -------------------------------------------------------- */

/* Une seule colonne par defaut, quatre a partir de 768 px. La rupture est ECRITE et non
   intrinseque : un repeat(auto-fit) ferait passer la marque a une piste des que la place
   manque, et la description tomberait a la largeur d'un menu. Le partage 2/1/1 est une
   decision de lecture, pas une adaptation de place. */
.zce__lib-trib-pied__grille {
  display: grid;
  gap: var(--trib-ecart);
  margin-bottom: var(--trib-ecart-large);
}

.zce__lib-trib-pied__marque { min-width: 0; }

/* --- la colonne de marque ---------------------------------------------------------- */

.zce__lib-trib-pied__nom {
  margin: 0 0 1rem;
  font-size: 1.5rem;
  line-height: 2rem;
  font-weight: 700;
  letter-spacing: -.025em;
  color: var(--trib-texte-fort);
}

/* 448 px, mesure design.md 4.2 (« bloc etroit »). Ce plafond est la raison d'etre des
   deux pistes : la marque a de la place, la ligne de texte n'en prend pas plus qu'elle
   n'en peut lire. */
.zce__lib-trib-pied__description {
  margin: 0 0 1.5rem;
  max-width: 28rem;
  font-size: 1rem;
  line-height: 1.625;
  color: var(--trib-texte);
  text-wrap: pretty;
}

.zce__lib-trib-pied__description:empty { display: none; }

/* Les <a> viennent de la donnee, donc sans classe prefixable : ils sont atteints par
   descendance depuis une classe qui, elle, est prefixee. Un selecteur de TYPE nu fuirait
   dans toute la feuille du site. */
.zce__lib-trib-pied__actions {
  margin: 0;
  display: flex;
  flex-wrap: wrap;
  gap: 1rem;
}

.zce__lib-trib-pied__actions:empty { display: none; }

.zce__lib-trib-pied__actions a {
  display: inline-flex;
  align-items: center;
  gap: .5rem;
  color: var(--trib-lien);
  text-decoration: none;
  /* La seule transition du theme qui compte ici : 150 ms sur la couleur, mesuree sur 114
     elements (design.md 7). Rien ne bouge, seule la teinte repond. */
  transition: color var(--trib-transition);
}

.zce__lib-trib-pied__actions a:hover,
.zce__lib-trib-pied__actions a:focus-visible { color: var(--trib-accent-pale); }

/* L'icone porte ses propres width/height dans la donnee ; on l'empeche seulement d'etre
   ecrasee par un libelle long sur un petit ecran. */
.zce__lib-trib-pied__actions svg { flex: none; }

/* --- une colonne titree ------------------------------------------------------------ */

.zce__lib-trib-pied__colonne { min-width: 0; }

/* 16/19.2 px gras, interlettrage -0.025em (design.md 3.2). Ce n'est PAS l'oeil-de-boeuf
   majuscule espace du theme agence : la tribune titre ses colonnes en bas de casse, a la
   taille du corps. */
.zce__lib-trib-pied__colonne-titre {
  margin: 0 0 1rem;
  font-size: 1rem;
  line-height: 1.2;
  font-weight: 700;
  letter-spacing: -.025em;
  color: var(--trib-texte-fort);
}

.zce__lib-trib-pied__colonne-liste {
  margin: 0;
  padding: 0;
  list-style: none;
  display: grid;
  gap: .5rem;
}

.zce__lib-trib-pied__colonne-liste a {
  font-size: 1rem;
  line-height: 1.6;
  color: var(--trib-texte);
  text-decoration: none;
  transition: color var(--trib-transition);
}

.zce__lib-trib-pied__colonne-liste a:hover,
.zce__lib-trib-pied__colonne-liste a:focus-visible {
  color: var(--trib-texte-fort);
  text-decoration: underline;
  text-underline-offset: .2em;
}

/* --- sous le filet ------------------------------------------------------------------ */

.zce__lib-trib-pied__bas {
  border-top: 1px solid var(--trib-bordure);
  padding-top: var(--trib-ecart);
}

/* Empile et centre par defaut, deux blocs opposes a partir de 768 px. Le centrage mobile
   n'est pas un repli : c'est ce que la capture 390 px montre, copyright et liens legaux
   centres l'un sous l'autre. */
.zce__lib-trib-pied__ligne {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 1rem;
}

.zce__lib-trib-pied__copyright {
  margin: 0;
  font-size: .875rem;
  line-height: 1.25rem;
  color: var(--trib-texte-faible);
}

.zce__lib-trib-pied__legaux {
  margin: 0;
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 1.5rem;
}

.zce__lib-trib-pied__legaux:empty { display: none; }

.zce__lib-trib-pied__legaux a {
  font-size: .875rem;
  line-height: 1.25rem;
  color: var(--trib-texte-faible);
  text-decoration: none;
  transition: color var(--trib-transition);
}

.zce__lib-trib-pied__legaux a:hover,
.zce__lib-trib-pied__legaux a:focus-visible { color: var(--trib-texte-fort); }

/* La signature est d'un cran PLUS sourde que le copyright — #6b7280 contre #9ca3af, deux
   valeurs distinctes relevees (design.md 1.4). C'est la seule chose de la page qui a le
   droit d'etre a peine lisible : une devise qu'on lit deux fois est une devise de trop. */
.zce__lib-trib-pied__signature {
  margin: 1.5rem 0 0;
  text-align: center;
  font-size: .875rem;
  line-height: 1.25rem;
  font-style: italic;
  color: var(--trib-second);
}

.zce__lib-trib-pied__signature:empty { display: none; }

/* --- la rupture ---------------------------------------------------------------------- */

/* Rupture en rem : voir lib-trib-bande.css, « Les ruptures ». */
@media (min-width: 48rem) {

  .zce__lib-trib-pied__grille { grid-template-columns: repeat(4, 1fr); }

  .zce__lib-trib-pied__marque { grid-column: span 2; }

  .zce__lib-trib-pied__ligne {
    flex-direction: row;
    justify-content: space-between;
  }

  .zce__lib-trib-pied__legaux { justify-content: flex-end; }
}

/* --- l'accessibilite du clavier ------------------------------------------------------ */

/* Le focus se voit sur fond sombre, donc en rouge clair et pas en rouge de marque : sur
   #111827 le #e30c28 vire au brun et l'anneau disparait. */
.zce__lib-trib-pied a:focus-visible {
  outline: 2px solid var(--trib-accent-clair);
  outline-offset: 3px;
}

/* =================================================================================
   lib-trib-section — l’enveloppe de section.

   Toutes les valeurs ci-dessous sortent de design.md (releve du 2026-09-25, mesure au
   navigateur sur 5 routes x 4 largeurs). Chaque mesure est citee a sa ligne. Les couleurs
   et les formes passent par les tokens de lib-trib-bande.css : rien n’est invente ici.
   ================================================================================= */

/* Aucun padding, aucune largeur. La bande donne les 80 px de haut et de bas (design.md
   4.1, « Section courante ») et les 1152 px de conteneur (4.2). Une section qui les
   reprendrait les doublerait des que deux sections partagent une bande. */
.zce__lib-trib-section {
  display: block;
}

/* --- l’entete ------------------------------------------------------------------- */

/* 64 px sous l’entete : « text-center mb-16 », 9 fois sur 9 dans le corpus mesure.
   Ecrit en calc depuis --trib-ecart plutot qu’en 4rem en dur : un site qui resserre son
   echelle doit resserrer aussi cet ecart, sinon son rythme se dedouble. */
.zce__lib-trib-section__entete {
  text-align: center;
  margin-bottom: calc(var(--trib-ecart) * 2);
}

/* Les trois autres valeurs mesurees pour un ecart titre → suivant (design.md 4.4, ligne
   h2 : 24 · 32 · 48 · 64 px). Elles existent deja dans le theme, on les nomme au lieu de
   les reecrire. */
.zce__lib-trib-section__entete[data-ecart="serre"] { margin-bottom: var(--trib-ecart-serre); }
.zce__lib-trib-section__entete[data-ecart="moyen"] { margin-bottom: var(--trib-ecart); }
.zce__lib-trib-section__entete[data-ecart="large"] { margin-bottom: var(--trib-ecart-large); }

/* L’alignement a gauche ne se contente pas de text-align : le chapo et le filet sont
   centres par des marges automatiques, qui survivraient au changement d’alignement et
   laisseraient un titre a gauche sous un filet reste au milieu. */
.zce__lib-trib-section__entete[data-align="gauche"] { text-align: left; }
.zce__lib-trib-section__entete[data-align="gauche"] .zce__lib-trib-section__chapo { margin-inline: 0; }
.zce__lib-trib-section__entete[data-align="gauche"] .zce__lib-trib-section__titre::after { margin-inline: 0; }

/* Le sur-titre — SEUL interlettrage positif du site (design.md 3.2). Ecrit en em et non
   en px : la mesure vaut +0.35 px a 14 px, soit +0.025em, et un site qui grossit son
   sur-titre doit garder la meme respiration, pas la meme valeur absolue.
   La casse est rendue par le CSS : la donnee reste en minuscules, sinon certains lecteurs
   d’ecran epellent le mot lettre par lettre. */
.zce__lib-trib-section__surtitre {
  margin: 0 0 calc(var(--trib-ecart) / 2);   /* mb-4, 16 px mesure */
  font-size: .875rem;                        /* 14 px */
  line-height: 1.25rem;                      /* 20 px */
  font-weight: 500;
  letter-spacing: .025em;                    /* +0.35 px a 14 px */
  text-transform: uppercase;
  color: var(--trib-texte);
}

/* Le titre. Deux tailles mesurees, une seule declaration d’interlettrage : le releve donne
   -0.9 px a 36 px et -1.2 px a 48 px, soit -0.025em dans les deux cas. Les ecrire en px
   obligerait a maintenir les deux valeurs et a en ajouter une a chaque taille nouvelle. */
.zce__lib-trib-section__titre {
  margin: 0 0 var(--trib-ecart);   /* mb-8, 32 px mesure */
  font-size: 2.25rem;              /* 36 px sous 768 px */
  line-height: 2.5rem;             /* 40 px */
  font-weight: 700;
  letter-spacing: -.025em;
  color: var(--trib-texte-fort);
}

/* Le filet d’accent. Mesure : 96 x 4 px (« w-24 h-1 »), centre, 32 px de part et d’autre
   — le titre porte deja ces 32 px sous lui, le filet reprend les memes au-dessus.
   Le degrade « to right » est celui du releve (design.md 2, ligne « filet / barre
   d’accent »). L’exemplaire de l’accueil, lui, est peint en aplat #e30c28 : les deux
   extremes du degrade encadrent cette valeur, et c’est le degrade qui a ete retenu pour
   le theme. */
.zce__lib-trib-section__entete[data-filet="oui"] .zce__lib-trib-section__titre::after {
  content: "";
  display: block;
  width: 6rem;      /* 96 px */
  height: 4px;      /* releve : « 4px solid #e30c28 » */
  margin: var(--trib-ecart) auto 0;
  background: linear-gradient(to right, var(--trib-accent), var(--trib-accent-bas));
}

/* Le chapo. 20 / 32.5 px = interligne 1.625 (design.md 3.2, « Paragraphe d’introduction »).
   Ramene a la largeur de lecture mesuree : 768 px, soit --trib-lecture (design.md 4.2). */
.zce__lib-trib-section__chapo {
  margin: 0 auto;
  max-width: var(--trib-lecture);
  font-size: 1.25rem;      /* 20 px */
  line-height: 1.625;      /* 32.5 px */
  font-weight: 400;
  color: var(--trib-texte);
}

/* Les parties optionnelles se retirent d’elles-memes : un trou de gabarit vide laisse une
   balise vide, et elle disparait avec son ecart. Pas de variante a declarer dans le
   gabarit, pas de classe a faire passer par la donnee. */
.zce__lib-trib-section__surtitre:empty,
.zce__lib-trib-section__chapo:empty { display: none; }

/* --- la grille de contenu -------------------------------------------------------- */

/* POURQUOI DEUX MEDIA QUERIES ET NON LA GRILLE INTRINSEQUE — l’ecart a l’idiome maison.
   repeat(auto-fit, minmax(X, 1fr)) ne sait pas ARRETER de compter. Or le releve dit que
   rien ne bouge entre 1024 et 1440 px (design.md 6) : une grille a 3 colonnes en garde 3
   jusqu’en haut. L’arithmetique refuse cet arret, pour toutes les grilles mesurees sans
   exception. Les cartes de vision, 3 colonnes, gouttiere 32 px :
     — a 1440 px le contenu vaut 1120 px (1152 de conteneur moins 2 x 16 de gouttiere
       laterale) ; pour que la 4e colonne ne s’invite pas : 4X + 96 > 1120, donc X > 256 ;
     — a 768 px le contenu vaut 736 px ; pour que les 3 colonnes tiennent deja :
       3X + 64 <= 736, donc X <= 224.
   256 < X <= 224 est vide : aucune valeur de minmax ne reproduit le releve. Le meme calcul
   condamne la grille a 2 colonnes (qui passerait a 3 vers 1100 px) et celle a 4.
   L’intrinseque reste l’idiome du parc ; ici il donnerait une mise en page proche et
   fausse, et la fidelite prime. */
.zce__lib-trib-section__contenu[data-colonnes="2"],
.zce__lib-trib-section__contenu[data-colonnes="3"],
.zce__lib-trib-section__contenu[data-colonnes="4"],
.zce__lib-trib-section__contenu[data-colonnes="2-3"],
.zce__lib-trib-section__contenu[data-colonnes="2-4"] {
  display: grid;
  gap: var(--trib-ecart);   /* 32 px, la gouttiere dominante (design.md 4.3) */
}

/* Les deux autres gouttieres du releve — 24 et 48 px, il n’y en a pas d’autre. Posees
   apres les regles de colonnes, a specificite egale : c’est l’ordre qui tranche. */
.zce__lib-trib-section__contenu[data-gouttiere="serre"] { gap: var(--trib-ecart-serre); }
.zce__lib-trib-section__contenu[data-gouttiere="large"] { gap: var(--trib-ecart-large); }

/* 768 px — la premiere des deux seules ruptures du site. Sous cette largeur toute grille
   mesuree tient sur une colonne, ce qui est deja l’etat d’une grille sans template : rien
   a declarer pour le mobile. */
/* Rupture en rem : voir lib-trib-bande.css, « Les ruptures ». */
@media (min-width: 48rem) {
  .zce__lib-trib-section__titre {
    font-size: 3rem;        /* 48 px */
    line-height: 1;         /* 48 px — le releve donne 48/48 */
  }
  .zce__lib-trib-section__contenu[data-colonnes="2"],
  .zce__lib-trib-section__contenu[data-colonnes="2-3"],
  .zce__lib-trib-section__contenu[data-colonnes="2-4"] { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .zce__lib-trib-section__contenu[data-colonnes="3"]   { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .zce__lib-trib-section__contenu[data-colonnes="4"]   { grid-template-columns: repeat(4, minmax(0, 1fr)); }
}

/* 1024 px — la seconde rupture, et la seule raison d’etre de la famille « 2-N » : six
   cartes d’expertise et quatre indicateurs passent par deux colonnes avant d’atteindre
   leur compte (design.md 6.1). minmax(0, 1fr) et non 1fr : une piste en 1fr ne descend
   pas sous la taille de son contenu, et un enfant large — un mot sans cesure, un tableau —
   ferait deborder la grille au lieu d’etre contraint. */
@media (min-width: 64rem) {
  .zce__lib-trib-section__contenu[data-colonnes="2-3"] { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .zce__lib-trib-section__contenu[data-colonnes="2-4"] { grid-template-columns: repeat(4, minmax(0, 1fr)); }
}

/* =================================================================================
   .lib-trib-section--bloc — le SOUS-bloc, rendu par lib-trib-bloc.html.

   Il partage la classe racine de la section, donc tout son habillage : grille,
   gouttieres, alignement, ecarts. Ce qui suit ne dit que ce qui differe.
   ================================================================================= */

/* Le titre d'un sous-bloc est un h3 a 24/32, graisse 700, interlettrage -0.6px.
   Mesure du 2026-09-25 : les cinq sous-blocs de l'accueil portent tous `text-2xl
   font-bold` — « Nous ne vendons rien », « Une approche unique du marketing digital »,
   « Pourquoi 0clic ? », « Discutons de votre projet », « Ce n'est pas de la
   science-fiction ». C'est aussi la ligne « h3 de carte · h2 page legale » du releve. */
.zce__lib-trib-section--bloc .zce__lib-trib-section__titre {
  font-size: 1.5rem;
  line-height: 2rem;
  letter-spacing: -.0375em;
}

/* Un seul sous-bloc du corpus grandit au-dela du telephone : « Ce n'est pas de la
   science-fiction », en `text-2xl md:text-3xl`. Il vit dans la bande d'accent, ou il
   porte seul tout le poids de la page — d'ou les 30 px. */
@media (min-width: 48rem) {
  .zce__lib-trib-section--bloc[data-taille="grand"] .zce__lib-trib-section__titre {
    font-size: 1.875rem;
    line-height: 2.25rem;
    letter-spacing: -.025em;
  }
}

/* ENTETE SANS UN SEUL MOT = PAS D'ENTETE. Les trois champs portent deja `:empty`, mais
   un parent dont tous les enfants sont masques occupe quand meme sa marge basse : la
   grille descendait de 64 px sans rien au-dessus. `:has()` regarde s'il reste un enfant
   qui porte du texte ; sinon la rangee entiere sort du flux.

   C'est ce qui permet d'employer cette brique comme une GRILLE NUE, pour aligner une
   partie des enfants d'une section sans leur inventer un titre. */
.zce__lib-trib-section--bloc .zce__lib-trib-section__entete:not(:has(:not(:empty))) {
  display: none;
}

/* =================================================================================
   .lib-trib-section--titre — le h1 d'une page sans heros, rendu par lib-trib-titre.html.

   Mesure du 2026-09-25 sur /articles/ : « Articles & Analyses » y est peint en 48/48,
   graisse 700, interlettrage -1.2px — c'est-a-dire exactement le corps d'un h2 de
   section. Le niveau change, le dessin non : un h1 de page interne n'a pas a crier plus
   fort que les sections qu'il coiffe, il a a etre le premier.

   Aucune regle de taille n'est donc necessaire ici : la classe racine partagee sert deja
   les bonnes valeurs. Ce bloc existe pour le DIRE — sans lui, le prochain lecteur
   ajouterait une regle par prudence et creerait l'ecart qu'il croyait fermer.
   ================================================================================= */

/* Le bloc pose sur un panneau. Mesure du 2026-09-25 sur « Pourquoi 0clic ? » :
   `bg-gray-50 p-8 md:p-12 rounded-2xl` — surface alterne, 32 px de remplissage qui
   passent a 48 px au-dela du telephone, rayon de carte.

   POURQUOI SUR LE BLOC ET NON SUR UNE BANDE. Une bande occupe toute la largeur de
   l'ecran ; ce panneau-la vit A L'INTERIEUR d'une section claire, entre le portrait et
   le pied de page. Le confondre avec une bande ferait courir le gris d'un bord a
   l'autre et mangerait la respiration que la section lui donne. */
.zce__lib-trib-section--bloc[data-pose="panneau"] {
  background: var(--trib-clair-alt);
  border-radius: var(--trib-rayon-carte);
  padding: var(--trib-ecart);
}

@media (min-width: 48rem) {
  .zce__lib-trib-section--bloc[data-pose="panneau"] {
    padding: var(--trib-ecart-large);
  }
}

/* =================================================================================
   L'ECHELLE D'UNE PAGE LEGALE.

   Mesure du 2026-09-25 sur /mentions-legales/ : le h1 y est en text-4xl (36/40) et les
   quatre h2 en text-2xl (24/32) — contre 48/48 partout ailleurs. Ce n'est pas une
   coquetterie de l'original : une page de mentions se lit de haut en bas, elle n'a
   personne a convaincre, et des titres de 48 px y poussent le contenu vers le bas sans
   rien ajouter. Premiere version servie : 2 397 px de haut contre 1 826 mesures, soit
   un tiers de trop, dont l'essentiel venait de la.
   ================================================================================= */

.zce__lib-trib-section[data-taille="legal"] .zce__lib-trib-section__titre {
  font-size: 1.5rem;
  line-height: 2rem;
  letter-spacing: -.025em;
}

/* LE H1 APRES LE H2, ET CE N'EST PAS UN CAPRICE DE RANGEMENT. Les deux selecteurs
   pesent EXACTEMENT le meme poids : « --titre » est un suffixe dans le meme jeton de
   classe, pas une classe de plus. `.a--titre[attr] .b` et `.a[attr] .b` font tous deux
   une classe, un attribut, une classe. A egalite, c'est le dernier ecrit qui gagne —
   et le h1 de /mentions-legales/ sortait donc a 24 px au lieu de 36, mesure au
   navigateur le 2026-09-25. Inverser l'ordre suffit ; monter la specificite
   artificiellement serait se mentir sur la raison. */
.zce__lib-trib-section--titre[data-taille="legal"] .zce__lib-trib-section__titre {
  font-size: 2.25rem;
  line-height: 2.5rem;
  letter-spacing: -.025em;
}

/* Dans une carte de page legale, l'intitule d'un champ est un h3 de 16 px — mesure :
   « font-bold text-gray-900 » sans classe de taille. Le laisser a 20 px lui donnait le
   poids d'un titre de carte editoriale, et poussait la page d'un tiers en hauteur. */
.zce__lib-trib-section[data-pose="carte"][data-taille="legal"] .zce__lib-trib-carte__titre {
  font-size: 1rem;
  line-height: 1.5rem;
  letter-spacing: normal;
}

/* La section posee sur sa propre carte, titre compris. Les quatre sections de la page
   de mentions sont des cartes blanches ; le titre vit DEDANS, pas au-dessus. */
.zce__lib-trib-section[data-pose="carte"] {
  background: var(--trib-surface);
  border: 1px solid var(--trib-bordure);
  border-radius: var(--trib-rayon-carte);
  box-shadow: var(--trib-ombre);
  padding: var(--trib-ecart);
}

@media (min-width: 48rem) {
  .zce__lib-trib-section[data-pose="carte"] { padding: var(--trib-ecart-large); }
}

/* Dans une carte, l'entete n'est plus centree ni espacee comme une section de page :
   elle introduit ce qui suit immediatement. */
.zce__lib-trib-section[data-pose="carte"] .zce__lib-trib-section__entete {
  text-align: left;
  margin-bottom: var(--trib-ecart-serre);
}

/* LA PREMIERE BANDE PASSE SOUS UNE BARRE FIXE. L'entete est en `position: fixed` : elle
   ne prend aucune place dans le flux, donc le premier contenu de la page commence a
   zero et se glisse dessous. Un heros s'en sort seul — il porte 128 px de remplissage
   haut, ce qui est precisement la compensation. Une page sans heros, non : mesure du
   2026-09-25, le h1 de /mentions-legales/ demarrait a 80 px sous une barre de 73, soit
   sept pixels de repit, contre 128 sur l'original.

   Le selecteur d'adjacence dit exactement ce qu'on veut dire — « la bande qui suit
   l'entete » — sans rien demander a la donnee. */
.zce__lib-trib-entete + .zce__lib-trib-bande:not(:has(.zce__lib-trib-heros)) > .zce__lib-trib-bande__inner {
  padding-top: var(--trib-pas-heros);
}

/* SAUF SI ELLE PORTE UN HEROS. Celui-la compense deja, par construction : 128 px de
   remplissage haut, c'est la meme valeur. Les additionner decalait le h1 de l'accueil
   de 46 px vers le bas — mesure du 2026-09-25 : y=258 contre 212 sur l'original. Le
   :not(:has()) dit la condition exacte plutot que de la deviner d'une donnee. */

/* UN H2 DE SECTION A 36 PX, ET NON 48. Trois sections du corpus le font, et elles ont
   un point commun : elles n'ouvrent pas un chapitre, elles ferment une demonstration.
   « L'Evolution vers le Zero Clic » porte text-4xl seul, « Restez a la pointe de la
   mutation » et « Les Chiffres de la Mutation » portent text-3xl md:text-4xl — contre
   text-4xl md:text-5xl pour les huit autres. Mesure du 2026-09-25. */
.zce__lib-trib-section[data-taille="moyen"] .zce__lib-trib-section__titre {
  font-size: 2.25rem;
  line-height: 2.5rem;
  letter-spacing: -.025em;
}


/* ============================================================================
   0clic.com — feuille LOCALE.

   CE QU'ELLE CONTIENT, ET RIEN D'AUTRE : le socle de page (remise a zero, boite,
   rythme du corps) et les quelques regles que la bibliotheque n'a pas a connaitre.
   Tout l'habillage des sections vient des partielles du theme `tribune`.

   ORDRE DE CASCADE, ecrit par le build dans la COPIE et jamais dans cette source
   (build_network.py:6189-6199) :
       1. le prelude de tokens derive de config.theme
       2. les partielles des briques REELLEMENT rendues par ce site
       3. ce fichier, en dernier
   Ce qui est ecrit ici surcharge donc la bibliotheque. C'est le pouvoir et le piege :
   une regle trop large ecrase une brique sans qu'on l'ait voulu.

   LES CLASSES SONT PREFIXEES A LA MAIN ICI. Le prefixage automatique
   (blocks.prefixer_selecteurs) ne s'applique qu'aux partielles du theme ; cette
   feuille est concatenee telle quelle. Une regle ecrite `.lib-prose` ne rencontrerait
   donc jamais rien : la classe servie est `zce__lib-prose`.
   ============================================================================ */

*, *::before, *::after { margin: 0; padding: 0; box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; }

/* LA POLICE EST LA PILE SYSTEME, ET C'EST UNE MESURE, PAS UN DEFAUT DE PARESSE.
   Le site d'origine declare Space Grotesk dans son <head> et le charge depuis Google
   Fonts. Mesure du 2026-09-25 au navigateur : les quinze @font-face restent a l'etat
   `unloaded` et AUCUN element de la page ne calcule cette famille — une regle de corps
   heritee du starter la surcharge sur tout ce qui vit dans <body>. Rendu a l'identique
   d'une police inexistante : une meme chaine de 72 px mesure 516,45 px dans les deux
   cas, contre 544,36 px en pile systeme.
   Appliquer reellement Space Grotesk ici donnerait donc un site DIFFERENT de celui
   qu'on copie. La pile systeme est le rendu reel. */
body {
  margin: 0;
  background: var(--color-bg);
  color: var(--trib-corps);
  font-family: var(--font-body);
  font-size: 1rem;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

/* Le corps de page. Les bandes en sortent par width:100vw, donc il ne contraint rien —
   il sert de contexte de positionnement et evite un debordement horizontal sur les
   disques floutes du heros. */
.zce__page {
  overflow-x: clip;
  /* l'entete est `fixed` : sans cette reserve, le heros passerait dessous */
  padding-top: 0;
}

/* --- le corps d'un article -------------------------------------------------------
   lib-prose (socle) habille deja les balises nues d'un corps d'article. Ce qui suit
   ne comble qu'un manque : les triptyques de chiffres des deux articles longs, qui
   arrivent du JSON en <dl> parce que c'est ce qu'ils SONT — un terme et ce qu'il
   mesure — et que la bibliotheque partagee n'a pas de regle pour eux. */
.zce__lib-prose dl {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 14rem), 1fr));
  gap: var(--trib-ecart-serre);
  margin-block: var(--trib-ecart);
  padding: var(--trib-ecart);
  background: var(--trib-accent-brume);
  border-radius: var(--trib-rayon-carte);
}

.zce__lib-prose dt {
  font-size: 2rem;
  line-height: 1;
  font-weight: 700;
  color: var(--trib-accent);
  text-align: center;
}

.zce__lib-prose dd {
  margin: .5rem 0 0;
  font-size: .875rem;
  line-height: 1.43;
  color: var(--trib-corps);
  text-align: center;
}
