/* genere au build */
:root {
  --radius-card: 0;
  --shadow-card: 0 2px 8px rgba(0,0,0,.08);
  --font-heading: 'Bricolage Grotesque', system-ui, sans-serif;
  --font-body: 'Lexend', system-ui, sans-serif;
  --color-sur-secondary: #FFFFFF;
  --color-sur-primary: #FFFFFF;
  --focus-ring: #13803A;
  --color-primary: #13803A;
  --color-secondary: #10233F;
  --color-bg: #FFFFFF;
  --color-text: #27364A;
  --color-surface: #F5F5F5;
  --color-surface-alt: #F2F3F4;
  --color-border: #D8DBDE;
  --color-text-muted: #687280;
}

: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-faq — les questions frequentes.

   Le depliant est un <details> natif : le contenu vit dans le HTML servi, donc un moteur
   qui n'execute rien le lit quand meme. Une FAQ montee en JavaScript est invisible pour
   la moitie de ceux a qui elle s'adresse. */

.jdp__lib-faq {
  padding-top: 1rem;
}

.jdp__lib-faq__titre {
  margin: 0 0 1.1rem;
  font-family: var(--font-heading);
  font-size: clamp(1.3rem, 1.1rem + 1vw, 1.8rem);
  font-weight: 800;
  line-height: 1.18;
  letter-spacing: -.02em;
  color: var(--color-text);
  scroll-margin-top: 5.5rem;
  text-wrap: balance;
}

.jdp__lib-faq__liste {
  display: grid;
  gap: .6rem;
}

.jdp__lib-faq__liste details {
  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;
  transition: border-color .18s ease;
}

.jdp__lib-faq__liste details[open] { border-color: var(--accent-trait, var(--color-primary)); }

.jdp__lib-faq__liste summary {
  position: relative;
  padding: .9em 3em .9em 1.15em;
  font-family: var(--font-heading);
  font-size: 1rem;
  font-weight: 700;
  line-height: 1.4;
  color: var(--color-text);
  cursor: pointer;
  list-style: none;
}

.jdp__lib-faq__liste summary::-webkit-details-marker { display: none; }

/* Le chevron pivote a l'ouverture : deux traits en CSS, aucune requete. */
.jdp__lib-faq__liste summary::after {
  content: "";
  position: absolute;
  right: 1.25em;
  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;
}

.jdp__lib-faq__liste details[open] > summary::after {
  transform: rotate(-135deg);
  margin-top: -.15rem;
}

.jdp__lib-faq__liste summary:hover,
.jdp__lib-faq__liste summary:focus-visible { color: var(--color-primary); }

.jdp__lib-faq__liste summary:focus-visible {
  outline: 2px solid var(--color-primary);
  outline-offset: -2px;
}

.jdp__lib-faq__liste details > :not(summary) {
  margin: 0 1.15em 1.1em;
  font-family: var(--font-body);
  font-size: .97rem;
  line-height: 1.65;
  color: var(--color-text-muted);
  text-wrap: pretty;
}

.jdp__lib-faq__liste details a {
  color: var(--color-primary);
  text-decoration: underline;
  text-underline-offset: .18em;
}

@media (prefers-reduced-motion: reduce) {
  .jdp__lib-faq__liste details,
  .jdp__lib-faq__liste summary::after { transition: none; }
}

/* lib-figure — une image, sa legende, son credit. Habille aussi lib-figure-lcp.

   LA BOITE EST RESERVEE PAR L'IMAGE ELLE-MEME. width et height sont poses par l'etape 3c
   du build, relevés sur le fichier servi ; `height: auto` laisse alors le navigateur
   deduire l'aspect-ratio de ces deux attributs et garder la place avant meme le premier
   octet de pixel. C'est ce couple — attributs justes + height:auto — qui supprime le saut,
   pas l'un des deux seul. Une `aspect-ratio` ecrite ici casserait au contraire les images
   qui n'ont pas le format prevu.

   LA LEGENDE N'EST PAS UNE REDITE DE L'ALT. L'alt s'adresse a qui ne voit pas l'image, la
   legende a qui la voit : si les deux disent la meme chose, l'une des deux est inutile.
   Le CSS ne peut pas verifier ca — il peut seulement faire disparaitre proprement la
   legende absente, pour qu'une figure sans commentaire ne laisse pas un blanc. */

.jdp__lib-figure {
  margin: 1.8rem 0;
}

.jdp__lib-figure__image {
  display: block;
  width: 100%;
  height: auto;
  border-radius: var(--fig-rayon, var(--radius-card, 10px));
  /* Un fond sous l'image : pendant le chargement, la boite reservee est une surface et
     non un trou blanc au milieu du texte. */
  background: var(--color-surface, #f2f2f2);
}

.jdp__lib-figure__legende {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: .2rem .6rem;
  margin-top: .55rem;
  font-family: var(--font-body, system-ui, sans-serif);
  font-size: .84rem;
  line-height: 1.55;
  color: var(--color-text-muted, #666);
  text-wrap: pretty;
}

/* Une legende vide ne laisse pas d'espace. Le :has() couvre le cas ou seul le credit est
   vide ; sans lui, la marge du bloc subsiste alors qu'il n'y a rien a lire. */
.jdp__lib-figure__legende:empty { display: none; }

.jdp__lib-figure__credit {
  font-size: .76rem;
  opacity: .85;
}

.jdp__lib-figure__credit:empty { display: none; }

.jdp__lib-figure__legende a {
  color: inherit;
  text-underline-offset: .18em;
}

.jdp__lib-figure__legende a:focus-visible {
  outline: 2px solid var(--focus-ring, currentColor);
  outline-offset: 2px;
  border-radius: 2px;
}

/* lib-plan-site — le sommaire du domaine.

   LA FORME SUIT LES TROIS USAGES. Groupement par famille pour que le lecteur voie
   l'etendue ; titre ET promesse pour qu'un moteur de reponse reprenne une couverture
   thematique plutot qu'une liste d'URL ; compteurs par famille pour que le desequilibre de
   couverture se voie.

   Une page qui liste cent cinquante entrees doit rester parcourable a l'oeil : d'ou les
   familles en grille intrinseque, et un rythme typographique serre a l'interieur de
   chacune. */

.jdp__lib-plan-site { padding: var(--pas-section, 3rem) 0; }

.jdp__lib-plan-site__entete { margin-bottom: clamp(1.8rem, 1.2rem + 2vw, 3rem); }

.jdp__lib-plan-site__titre {
  margin: 0 0 .6rem;
  font-family: var(--font-heading);
  font-size: clamp(1.55rem, 1.2rem + 1.7vw, 2.4rem);
  font-weight: 800;
  line-height: 1.12;
  letter-spacing: -.02em;
  color: var(--color-text);
  text-wrap: balance;
}

.jdp__lib-plan-site__intro {
  margin: 0 0 .8rem;
  max-width: 58ch;
  font-family: var(--font-body);
  font-size: 1rem;
  line-height: 1.65;
  color: var(--color-text-muted);
  text-wrap: pretty;
}

.jdp__lib-plan-site__intro:empty { display: none; }

.jdp__lib-plan-site__total {
  display: inline-block;
  margin: 0;
  padding: .3rem .85rem;
  border: 1px solid var(--trait, var(--color-border));
  border-radius: 999px;
  font-family: var(--font-body);
  font-size: .78rem;
  font-weight: 700;
  letter-spacing: .04em;
  font-variant-numeric: tabular-nums;
  color: var(--color-text-muted);
}

.jdp__lib-plan-site__total:empty { display: none; }

/* --- les familles ---------------------------------------------------------------
   Deux colonnes des qu'il y a la place : cent cinquante entrees sur une seule colonne
   font une page qu'on ne parcourt pas, on la subit. */
.jdp__lib-plan-site__familles {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 24rem), 1fr));
  gap: clamp(1.8rem, 1.2rem + 2vw, 3rem);
  align-items: start;
}

.jdp__lib-plan-site__famille { min-width: 0; }

.jdp__lib-plan-site__famille-titre {
  display: flex;
  align-items: baseline;
  gap: .6rem;
  margin: 0 0 .4rem;
  padding-bottom: .5rem;
  border-bottom: 2px solid var(--color-primary);
  font-family: var(--font-heading);
  font-size: clamp(1.05rem, .98rem + .4vw, 1.22rem);
  font-weight: 700;
  letter-spacing: -.015em;
  color: var(--color-text);
}

/* Le compteur est un outil, pas un ornement : cote a cote, les familles montrent ou la
   couverture est mince. */
.jdp__lib-plan-site__compte {
  margin-left: auto;
  flex: none;
  font-family: var(--font-body);
  font-size: .74rem;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  color: var(--color-primary);
}

.jdp__lib-plan-site__famille-intro {
  margin: .6rem 0 .9rem;
  font-family: var(--font-body);
  font-size: .88rem;
  line-height: 1.55;
  color: var(--color-text-muted);
  text-wrap: pretty;
}

.jdp__lib-plan-site__famille-intro:empty { display: none; }

/* --- les entrees ------------------------------------------------------------------ */
.jdp__lib-plan-site__liste {
  margin: 0;
  padding: 0;
  list-style: none;
  counter-reset: plan;
}

.jdp__lib-plan-site__entree {
  counter-increment: plan;
  position: relative;
  display: grid;
  gap: .1rem;
  padding: .55rem 0 .55rem 2rem;
  border-top: 1px solid var(--trait, var(--color-border));
}

.jdp__lib-plan-site__entree:first-child { border-top: 0; }

/* Le rang vient d'un compteur CSS : il suit l'ordre reel de la liste, et il n'a pas a
   etre saisi dans la donnee ni a etre maintenu quand on intercale une page. */
.jdp__lib-plan-site__entree::before {
  content: counter(plan, decimal-leading-zero);
  position: absolute;
  left: 0;
  top: .62rem;
  font-family: var(--font-body);
  font-size: .7rem;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  color: var(--color-text-muted);
  opacity: .6;
}

.jdp__lib-plan-site__lien {
  font-family: var(--font-body);
  font-size: .95rem;
  font-weight: 600;
  line-height: 1.35;
  color: var(--color-text);
  text-decoration: none;
  text-wrap: pretty;
}

.jdp__lib-plan-site__lien:hover,
.jdp__lib-plan-site__lien:focus-visible {
  color: var(--color-primary);
  text-decoration: underline;
  text-underline-offset: .18em;
}

/* La promesse est ce qui rend ce sommaire lisible par une machine : une liste d'URL ne se
   resume pas, une liste de « ce que fait chaque page » si. */
.jdp__lib-plan-site__promesse {
  font-family: var(--font-body);
  font-size: .82rem;
  line-height: 1.45;
  color: var(--color-text-muted);
  text-wrap: pretty;
}

.jdp__lib-plan-site__promesse:empty { display: none; }

.jdp__lib-plan-site__date {
  font-family: var(--font-body);
  font-size: .7rem;
  letter-spacing: .04em;
  font-variant-numeric: tabular-nums;
  color: var(--color-text-muted);
  opacity: .7;
}

.jdp__lib-plan-site__date:empty { display: none; }

.jdp__lib-plan-site a:focus-visible {
  outline: 2px solid var(--color-primary);
  outline-offset: 3px;
  border-radius: 3px;
}

/* A l'impression, une colonne : le sommaire sert alors de table des matieres papier. */
@media print {
  .jdp__lib-plan-site__familles { grid-template-columns: 1fr; }
  .jdp__lib-plan-site__famille { break-inside: avoid; }
  .jdp__lib-plan-site__famille-titre { border-bottom-color: #999; }
}

/* 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. */

.jdp__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;
}

.jdp__lib-prose > :first-child { margin-top: 0; }
.jdp__lib-prose > :last-child { margin-bottom: 0; }

.jdp__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. */
.jdp__lib-prose > p:first-of-type {
  font-size: 1.14rem;
  line-height: 1.68;
  color: var(--color-text);
}

/* --- titres --------------------------------------------------------------------- */
.jdp__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. */
.jdp__lib-prose h2::before {
  content: "";
  position: absolute;
  inset: 0 auto auto 0;
  width: 2.6rem;
  height: 3px;
  border-radius: 2px;
  background: var(--color-primary);
}

.jdp__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);
}

.jdp__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 --------------------------------------------------------------------- */
.jdp__lib-prose ul,
.jdp__lib-prose ol {
  margin: 0 0 1.35em;
  padding-left: 1.4em;
}

.jdp__lib-prose li { margin-bottom: .5em; }
.jdp__lib-prose li::marker { color: var(--color-primary); }

.jdp__lib-prose li > ul,
.jdp__lib-prose li > ol { margin: .5em 0 0; }

/* --- liens ----------------------------------------------------------------------- */
.jdp__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;
}

.jdp__lib-prose a:hover,
.jdp__lib-prose a:focus-visible { text-decoration-color: var(--color-primary); }

.jdp__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. */
.jdp__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);
}

.jdp__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;
}

.jdp__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. */
.jdp__lib-prose figure:has(> blockquote) {
  margin: 2em 0;
  padding: 0;
}

.jdp__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. */
.jdp__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. */
.jdp__lib-prose figure > blockquote + figcaption::before {
  content: "\2014";
  color: var(--color-primary);
  opacity: .7;
}

.jdp__lib-prose figcaption a {
  font-weight: 600;
  color: var(--color-text);
  text-decoration-color: color-mix(in srgb, var(--color-primary) 45%, transparent);
}

.jdp__lib-prose figcaption a:hover,
.jdp__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. */
.jdp__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);
}

.jdp__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;
}

.jdp__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. */
.jdp__lib-prose table {
  display: block;
  overflow-x: auto;
  width: 100%;
  margin: 1.7em 0;
  border-collapse: collapse;
  font-size: .95rem;
}

.jdp__lib-prose th,
.jdp__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. */
.jdp__lib-prose thead th {
  position: sticky;
  top: 0;
  z-index: 1;
  background: var(--color-bg);
}

.jdp__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. */
.jdp__lib-prose tbody th,
.jdp__lib-prose tbody td:first-child {
  font-weight: 700;
  color: var(--color-text);
}

.jdp__lib-prose tbody tr:hover { background: var(--accent-doux, var(--color-surface)); }

.jdp__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. */
.jdp__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;
}

.jdp__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. */
.jdp__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. */
.jdp__lib-prose dl {
  margin: 1.6em 0;
  display: grid;
  gap: .1em;
}

.jdp__lib-prose dt {
  margin-top: .9em;
  font-family: var(--font-heading);
  font-weight: 700;
  font-size: 1.02rem;
  color: var(--color-text);
}

.jdp__lib-prose dt:first-child { margin-top: 0; }

.jdp__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. */
.jdp__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;
}

.jdp__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;
}

.jdp__lib-prose summary::-webkit-details-marker { display: none; }

.jdp__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;
}

.jdp__lib-prose details[open] > summary::after {
  transform: rotate(-135deg);
  margin-top: -.15rem;
}

.jdp__lib-prose summary:hover,
.jdp__lib-prose summary:focus-visible { color: var(--color-primary); }

.jdp__lib-prose details > :not(summary) {
  margin: 0 1.1em 1.1em;
}

@media (prefers-reduced-motion: reduce) {
  .jdp__lib-prose summary::after { transition: none; }
}

/* --- surlignage et mentions ------------------------------------------------------- */
.jdp__lib-prose mark {
  padding: .05em .25em;
  border-radius: 3px;
  background: var(--accent-doux, var(--color-surface));
  color: var(--color-text);
}

.jdp__lib-prose small {
  font-size: .84rem;
  color: var(--color-text-muted);
}

/* --- media ------------------------------------------------------------------------ */
.jdp__lib-prose img {
  display: block;
  max-width: 100%;
  height: auto;
  margin: 1.7em 0;
  border-radius: var(--rayon-m, var(--radius-card));
}

.jdp__lib-prose figure { margin: 1.7em 0; }
.jdp__lib-prose figure img { margin: 0 0 .6em; }

.jdp__lib-prose figcaption {
  font-size: .85rem;
  line-height: 1.5;
  color: var(--color-text-muted);
}

.jdp__lib-prose hr {
  margin: 2.4em 0;
  border: 0;
  border-top: 1px solid var(--trait, var(--color-border));
}

.jdp__lib-prose strong { font-weight: 700; color: var(--color-text); }

.jdp__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. */
.jdp__lib-prose q {
  quotes: "\00ab\00a0" "\00a0\00bb" "\201c" "\201d";
  font-style: italic;
  color: var(--color-text);
}

.jdp__lib-prose q::before { content: open-quote; }
.jdp__lib-prose q::after { content: close-quote; }

/* --- titre de source cite dans le texte ------------------------------------------- */
.jdp__lib-prose cite {
  font-style: normal;
  font-weight: 600;
  color: var(--color-text);
}

/* --- date en chiffres alignes ----------------------------------------------------- */
.jdp__lib-prose time { font-variant-numeric: tabular-nums; }

/* --- appel de note ------------------------------------------------------------------ */
.jdp__lib-prose sup {
  font-size: .7em;
  line-height: 0;
  vertical-align: super;
}

.jdp__lib-prose sup a { text-decoration: none; }

/* lib-related — les 983 pages qui servaient ce bloc sans aucune regle CSS en ont une. */

.jdp__lib-related {
  margin: 2.5rem 0 0;
  padding: 1.25rem 1.4rem 1.4rem;
  background: var(--color-surface-alt);
  border-radius: var(--radius-card);
}

.jdp__lib-related__titre {
  margin: 0 0 .8rem;
  font-family: var(--font-heading);
  font-size: 1.05rem;
  color: var(--color-text);
}

/* Grille intrinseque : les liens se repartissent selon la place disponible, sans une
   seule media query. C'est la technique la plus generalisable du depot et elle n'avait
   jamais franchi la frontiere de POWERiti. min(100%, ...) est le garde-fou qui empeche
   le debordement quand le conteneur est plus etroit que la colonne demandee. */
.jdp__lib-related__liste {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 15rem), 1fr));
  gap: .45rem 1.4rem;
  margin: 0;
  padding: 0;
  list-style: none;
}

.jdp__lib-related__liste li {
  padding-left: .9rem;
  position: relative;
  line-height: 1.5;
}

.jdp__lib-related__liste li::before {
  content: "";
  position: absolute;
  left: 0;
  top: .62em;
  width: .32rem;
  height: .32rem;
  border-radius: 50%;
  background: var(--color-primary);
}

.jdp__lib-related__liste a {
  color: var(--color-text);
  font-family: var(--font-body);
  text-decoration: none;
}

.jdp__lib-related__liste a:hover,
.jdp__lib-related__liste a:focus-visible {
  color: var(--color-primary);
  text-decoration: underline;
}

.jdp__lib-related a:focus-visible {
  outline: 2px solid var(--color-primary);
  outline-offset: 2px;
}

/* lib-sommaire — le sommaire d'une page longue.

   Il colle en haut de sa colonne pendant la lecture. C'est tout l'interet : un sommaire
   qui defile avec le texte ne sert qu'une fois, au premier ecran. position:sticky suffit,
   aucun script — le seul prerequis est que sa colonne ne soit pas en overflow, ce dont
   la mise en page de l'article se charge.

   Il n'indique PAS la section courante : le faire demanderait un observateur
   d'intersection, donc du JavaScript, donc une dependance sur 48 sites pour un gain de
   confort mineur. */

.jdp__lib-sommaire {
  position: sticky;
  top: 5.5rem;
  padding: 1.1rem 1.2rem 1.2rem;
  border: 1px solid var(--trait, var(--color-border));
  border-radius: var(--rayon-m, var(--radius-card));
  background: var(--surface-haute, var(--color-surface));
  font-family: var(--font-body);
}

.jdp__lib-sommaire__titre {
  margin: 0 0 .75rem;
  font-family: var(--font-body);
  font-size: .72rem;
  font-weight: 700;
  letter-spacing: .13em;
  text-transform: uppercase;
  color: var(--color-text-muted);
}

/* Les numeros sont poses par un compteur CSS et non ecrits dans le HTML : contrairement
   au rang d'un item de listicle, celui-ci n'a aucun sens hors de sa page, et personne ne
   copiera un sommaire ailleurs. */
.jdp__lib-sommaire__liste {
  margin: 0;
  padding: 0;
  list-style: none;
  counter-reset: sommaire;
  display: grid;
  gap: .1rem;
}

.jdp__lib-sommaire__liste li { counter-increment: sommaire; }

.jdp__lib-sommaire__liste a {
  display: grid;
  grid-template-columns: 1.5rem 1fr;
  gap: .1rem;
  padding: .38rem 0;
  font-size: .88rem;
  line-height: 1.4;
  color: var(--color-text-muted);
  text-decoration: none;
  border-radius: 4px;
  transition: color .15s ease;
}

.jdp__lib-sommaire__liste a::before {
  content: counter(sommaire, decimal-leading-zero);
  font-size: .72rem;
  font-weight: 700;
  color: var(--color-primary);
  opacity: .7;
  padding-top: .12em;
}

.jdp__lib-sommaire__liste a:hover,
.jdp__lib-sommaire__liste a:focus-visible { color: var(--color-text); }

.jdp__lib-sommaire__liste a:hover::before,
.jdp__lib-sommaire__liste a:focus-visible::before { opacity: 1; }

.jdp__lib-sommaire__liste a:focus-visible {
  outline: 2px solid var(--color-primary);
  outline-offset: 2px;
}

/* La cible d'une ancre se place SOUS la barre de tete collante : sans cette marge, le
   titre vise atterrit derriere elle et le lecteur croit avoir rate son clic. */
.jdp__lib-prose h2[id],
.jdp__lib-prose h3[id] { scroll-margin-top: 5.5rem; }

@media (prefers-reduced-motion: reduce) {
  .jdp__lib-sommaire__liste a { transition: none; }
}

/* lib-sources — la webographie.

   C'est un appareil de PREUVE, et sa lisibilite fait partie de la preuve. Une liste de
   titres bleus ne dit pas d'ou vient l'information ; « developers.google.com » le dit
   d'un coup d'oeil. Chaque entree porte donc les deux : ce que dit la source, et qui la
   publie.

   Les entrees sont NUMEROTEES. Un lecteur qui veut renvoyer vers la troisieme reference
   doit pouvoir la nommer, et un moteur qui reprend le passage garde l'ordre. */

.jdp__lib-sources {
  margin: 2.5rem 0 0;
  padding: 1.2rem 1.3rem 1.3rem;
  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));
}

.jdp__lib-sources__titre {
  margin: 0 0 .8rem;
  font-family: var(--font-body);
  font-size: .72rem;
  font-weight: 700;
  color: var(--color-text-muted);
  text-transform: uppercase;
  letter-spacing: .13em;
}

/* --- la forme enrichie : titre + domaine ------------------------------------------- */
.jdp__lib-sources__ordre {
  margin: 0;
  padding: 0;
  list-style: none;
  counter-reset: source;
  display: grid;
  gap: .1rem;
}

.jdp__lib-sources__item {
  counter-increment: source;
  font-family: var(--font-body);
  font-size: .9rem;
  line-height: 1.5;
  color: var(--color-text-muted);
}

.jdp__lib-sources__lien {
  display: grid;
  grid-template-columns: 1.7rem 1fr;
  gap: 0 .2rem;
  padding: .45rem 0;
  text-decoration: none;
  border-radius: 4px;
}

/* Le numero est pose par un compteur : la liste reste une <ol> semantique, et le style
   ne depend pas d'un chiffre ecrit dans le HTML. */
.jdp__lib-sources__lien::before {
  content: counter(source, decimal-leading-zero);
  grid-row: span 2;
  font-size: .72rem;
  font-weight: 700;
  color: var(--color-primary);
  opacity: .65;
  padding-top: .18em;
}

.jdp__lib-sources__nom {
  font-weight: 600;
  color: var(--color-text);
  /* Le titre d'une source est parfois tres long : on coupe plutot que de deborder. */
  overflow-wrap: anywhere;
}

/* Le domaine : ce qui permet de juger la source avant de cliquer. */
.jdp__lib-sources__hote {
  font-size: .78rem;
  color: var(--color-text-muted);
  overflow-wrap: anywhere;
}

.jdp__lib-sources__lien:hover .jdp__lib-sources__nom,
.jdp__lib-sources__lien:focus-visible .jdp__lib-sources__nom {
  color: var(--color-primary);
  text-decoration: underline;
  text-underline-offset: .2em;
}

.jdp__lib-sources__lien:hover::before,
.jdp__lib-sources__lien:focus-visible::before { opacity: 1; }

/* --- le repli : la liste nue emise par build_sources_html -------------------------- */
.jdp__lib-sources__liste ul,
.jdp__lib-sources__liste ol {
  margin: 0;
  padding-left: 1.1rem;
}

.jdp__lib-sources__liste li {
  margin: .25rem 0;
  color: var(--color-text-muted);
  font-family: var(--font-body);
  font-size: .9rem;
  line-height: 1.55;
}

.jdp__lib-sources__liste a {
  color: var(--color-text-muted);
  overflow-wrap: anywhere;
}

.jdp__lib-sources__liste a:hover,
.jdp__lib-sources__liste a:focus-visible { color: var(--color-primary); }

.jdp__lib-sources a:focus-visible {
  outline: 2px solid var(--color-primary);
  outline-offset: 2px;
}

/* =================================================================================
   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,
.jdp__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>. */
.jdp__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);
}

.jdp__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. */
.jdp__lib-trib-bande__inner[data-largeur="moyen"]   { max-width: var(--trib-moyen); }
.jdp__lib-trib-bande__inner[data-largeur="lecture"] { max-width: var(--trib-lecture); }
.jdp__lib-trib-bande__inner[data-largeur="etroit"]  { max-width: var(--trib-etroit); }

/* --- les fonds ------------------------------------------------------------------- */

.jdp__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);
}

.jdp__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. */
.jdp__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);
}

.jdp__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. */
.jdp__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));
}

.jdp__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. */
.jdp__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.
   ================================================================================= */

.jdp__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) {
  .jdp__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. */
.jdp__lib-trib-bio__visuel {
  position: relative;
}

.jdp__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;
}

.jdp__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;
}

.jdp__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);
}

.jdp__lib-trib-bio__pastille:empty { display: none; }

/* --- le propos --------------------------------------------------------------------- */

.jdp__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);
}

.jdp__lib-trib-bio__titre:empty { display: none; }

.jdp__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);
}

.jdp__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. */
.jdp__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. */
.jdp__lib-trib-bio__texte strong { font-weight: 700; }

/* =================================================================================
   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.
   ================================================================================= */

.jdp__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. */
.jdp__lib-trib-carte-article:hover {
  box-shadow: var(--trib-ombre-haute);
}

/* --- la ligne haute : rubrique, puce, duree ------------------------------------------ */

.jdp__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);
}

.jdp__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. */
.jdp__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. */
.jdp__lib-trib-carte-article__categorie:empty + .jdp__lib-trib-carte-article__duree::before {
  content: none;
}

/* --- le titre, et le lien qui le porte ------------------------------------------------ */

.jdp__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);
}

.jdp__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. */
.jdp__lib-trib-carte-article:hover .jdp__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. */
.jdp__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. */
.jdp__lib-trib-carte-article:has(.jdp__lib-trib-carte-article__lien:focus-visible) {
  outline: 2px solid var(--trib-lien);
  outline-offset: 2px;
}

.jdp__lib-trib-carte-article__lien:focus-visible {
  outline: none;
}

/* --- l’extrait ------------------------------------------------------------------------ */

.jdp__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 ----------------------------------- */

.jdp__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. */
.jdp__lib-trib-carte-article__quand {
  display: inline-flex;
  align-items: center;
  gap: .5rem;
}

.jdp__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. */
.jdp__lib-trib-carte-article__action::after {
  content: " \2192";
}

.jdp__lib-trib-carte-article:hover .jdp__lib-trib-carte-article__action {
  text-decoration: underline;
}

/* --- ce qui manque se retire, plutot que de laisser un trou ---------------------------- */

.jdp__lib-trib-carte-article__categorie:empty,
.jdp__lib-trib-carte-article__duree:empty,
.jdp__lib-trib-carte-article__extrait:empty,
.jdp__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. */
.jdp__lib-trib-carte-article__meta:has(> .jdp__lib-trib-carte-article__categorie:empty) > .jdp__lib-trib-carte-article__icone,
.jdp__lib-trib-carte-article__quand:has(> .jdp__lib-trib-carte-article__date:empty),
.jdp__lib-trib-carte-article__meta:has(> .jdp__lib-trib-carte-article__categorie:empty):has(> .jdp__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.
   ================================================================================= */

.jdp__lib-trib-carte-article__sans-lien { color: var(--trib-texte-fort); }

.jdp__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. */
.jdp__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. */
.jdp__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. */
.jdp__lib-trib-chiffre[data-ton="1"] .jdp__lib-trib-chiffre__valeur { color: var(--trib-accent-clair); }
.jdp__lib-trib-chiffre[data-ton="2"] .jdp__lib-trib-chiffre__valeur { color: var(--trib-chaud); }
.jdp__lib-trib-chiffre[data-ton="3"] .jdp__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. */
.jdp__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. */
.jdp__lib-trib-chiffre__detail {
  margin: .5rem 0 0;
  font-size: .875rem;
  line-height: 1.25rem;
  color: var(--trib-texte-faible);
}

.jdp__lib-trib-chiffre__label:empty,
.jdp__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. */
.jdp__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-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.
   ================================================================================= */

.jdp__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) {
  .jdp__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. */

.jdp__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);
}

.jdp__lib-trib-diptyque__titre:empty { display: none; }

.jdp__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;
}

.jdp__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. */
.jdp__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. */
.jdp__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. */

.jdp__lib-trib-diptyque__volet[data-ton="actuel"] .jdp__lib-trib-diptyque__titre {
  color: var(--trib-lien);
}

.jdp__lib-trib-diptyque__volet[data-ton="actuel"] .jdp__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;
}

.jdp__lib-trib-diptyque__volet[data-ton="actuel"] .jdp__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.
   ================================================================================= */

.jdp__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)) {
  .jdp__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. */
.jdp__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 -------------------------------------------------------------------- */

.jdp__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. */
.jdp__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;
}

.jdp__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. */
.jdp__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. */
.jdp__lib-trib-entete__marque:hover .jdp__lib-trib-entete__mot,
.jdp__lib-trib-entete__marque:focus-visible .jdp__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. */
.jdp__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. */
.jdp__lib-trib-entete__nav:has(.jdp__lib-trib-entete__liste:empty) { display: none; }

/* 24px d'ecart, mesures (space-x-6) — la valeur serree de l'echelle du theme. */
.jdp__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. */
.jdp__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. */
.jdp__lib-trib-entete__lien,
.jdp__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;
}

.jdp__lib-trib-entete__lien {
  color: var(--trib-corps);
  transition: color var(--trib-transition);
}

.jdp__lib-trib-entete__lien:hover,
.jdp__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. */
.jdp__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(). */
.jdp__lib-trib-entete__entree[data-courant="oui"] .jdp__lib-trib-entete__lien,
.jdp__lib-trib-entete__lien[href=""] {
  display: none;
}

.jdp__lib-trib-entete__entree[data-courant="oui"] .jdp__lib-trib-entete__ici,
.jdp__lib-trib-entete__entree:has(.jdp__lib-trib-entete__lien[href=""]) .jdp__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. */
.jdp__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. */
.jdp__lib-trib-entete__action:hover,
.jdp__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. */
.jdp__lib-trib-entete__action:empty,
.jdp__lib-trib-entete__action[href=""] {
  display: none;
}

/* --- le parcours au clavier --------------------------------------------------------- */

.jdp__lib-trib-entete__marque:focus-visible,
.jdp__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. */
.jdp__lib-trib-entete__lien:focus-visible {
  outline: 2px solid var(--trib-accent);
  outline-offset: -2px;
}

@media (prefers-reduced-motion: reduce) {
  .jdp__lib-trib-entete__mot,
  .jdp__lib-trib-entete__lien,
  .jdp__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) {
  .jdp__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. */
.jdp__lib-trib-exergue { color: var(--trib-lien); }

.jdp__lib-trib-exergue[data-ton="vif"]    { color: var(--trib-accent-vif); }
.jdp__lib-trib-exergue[data-ton="clair"]  { color: var(--trib-accent-clair); }
.jdp__lib-trib-exergue[data-ton="chaud"]  { color: var(--trib-chaud); }
.jdp__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. */
.jdp__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. */
.jdp__lib-trib-frise::before {
  content: "";
  position: absolute;
  top: 0;
  bottom: 0;
  left: 50%;
  margin-left: -1px;
  width: 2px;
  background: var(--trib-accent-pale);
}

.jdp__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. */
.jdp__lib-trib-frise__etape + .jdp__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. */
.jdp__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. */
.jdp__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;
}

.jdp__lib-trib-frise__etape:nth-child(even) .jdp__lib-trib-frise__carte {
  margin-left: calc(50% + var(--trib-ecart));
  text-align: left;
}

.jdp__lib-trib-frise__carte:hover {
  box-shadow: var(--trib-ombre-haute);
}

.jdp__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. */
.jdp__lib-trib-frise__periode {
  margin: 0 0 .5rem;
  font-size: .875rem;
  line-height: 1.25rem;
  font-weight: 500;
  color: var(--trib-lien);
}

.jdp__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. */
.jdp__lib-trib-frise__titre:empty,
.jdp__lib-trib-frise__periode:empty,
.jdp__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) {
  .jdp__lib-trib-frise::before,
  .jdp__lib-trib-frise__etape::before {
    left: .5rem;
  }

  .jdp__lib-trib-frise__etape {
    padding-left: calc(var(--trib-ecart) + .5rem);
  }

  .jdp__lib-trib-frise__carte,
  .jdp__lib-trib-frise__etape:nth-child(even) .jdp__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.
   ================================================================================= */

.jdp__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. */
.jdp__lib-trib-heros__halo {
  position: absolute;
  border-radius: var(--trib-rayon-pastille);
  filter: blur(64px); /* releve section 2 */
  opacity: .2;
  pointer-events: none;
}

.jdp__lib-trib-heros__halo--droite {
  top: 25%;
  right: 0;
  width: 384px;  /* releve : 384 x 384 */
  height: 384px;
  background: var(--trib-accent-vif);
}

.jdp__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. */
.jdp__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. */
.jdp__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. */
.jdp__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. */
.jdp__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). */
.jdp__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);
}

.jdp__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. */
.jdp__lib-trib-heros__actions {
  display: flex;
  flex-direction: column;
  gap: var(--trib-ecart-serre);   /* releve : 24 px */
}

.jdp__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. */
.jdp__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);
}

.jdp__lib-trib-heros__action:hover,
.jdp__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. */
.jdp__lib-trib-heros__action[data-ton="fantome"] {
  border-color: var(--trib-clair);
  background: transparent;
  color: var(--trib-clair);
}

.jdp__lib-trib-heros__action[data-ton="fantome"]:hover,
.jdp__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) {

  .jdp__lib-trib-heros__titre { font-size: 4.5rem; }

  .jdp__lib-trib-heros__chapo {
    font-size: 1.5rem;
    line-height: 2rem;
  }

  .jdp__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.
   ================================================================================= */

.jdp__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. */
.jdp__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. */
.jdp__lib-trib-pied__grille {
  display: grid;
  gap: var(--trib-ecart);
  margin-bottom: var(--trib-ecart-large);
}

.jdp__lib-trib-pied__marque { min-width: 0; }

/* --- la colonne de marque ---------------------------------------------------------- */

.jdp__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. */
.jdp__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;
}

.jdp__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. */
.jdp__lib-trib-pied__actions {
  margin: 0;
  display: flex;
  flex-wrap: wrap;
  gap: 1rem;
}

.jdp__lib-trib-pied__actions:empty { display: none; }

.jdp__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);
}

.jdp__lib-trib-pied__actions a:hover,
.jdp__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. */
.jdp__lib-trib-pied__actions svg { flex: none; }

/* --- une colonne titree ------------------------------------------------------------ */

.jdp__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. */
.jdp__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);
}

.jdp__lib-trib-pied__colonne-liste {
  margin: 0;
  padding: 0;
  list-style: none;
  display: grid;
  gap: .5rem;
}

.jdp__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);
}

.jdp__lib-trib-pied__colonne-liste a:hover,
.jdp__lib-trib-pied__colonne-liste a:focus-visible {
  color: var(--trib-texte-fort);
  text-decoration: underline;
  text-underline-offset: .2em;
}

/* --- sous le filet ------------------------------------------------------------------ */

.jdp__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. */
.jdp__lib-trib-pied__ligne {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 1rem;
}

.jdp__lib-trib-pied__copyright {
  margin: 0;
  font-size: .875rem;
  line-height: 1.25rem;
  color: var(--trib-texte-faible);
}

.jdp__lib-trib-pied__legaux {
  margin: 0;
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 1.5rem;
}

.jdp__lib-trib-pied__legaux:empty { display: none; }

.jdp__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);
}

.jdp__lib-trib-pied__legaux a:hover,
.jdp__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. */
.jdp__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);
}

.jdp__lib-trib-pied__signature:empty { display: none; }

/* --- la rupture ---------------------------------------------------------------------- */

/* Rupture en rem : voir lib-trib-bande.css, « Les ruptures ». */
@media (min-width: 48rem) {

  .jdp__lib-trib-pied__grille { grid-template-columns: repeat(4, 1fr); }

  .jdp__lib-trib-pied__marque { grid-column: span 2; }

  .jdp__lib-trib-pied__ligne {
    flex-direction: row;
    justify-content: space-between;
  }

  .jdp__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. */
.jdp__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. */
.jdp__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. */
.jdp__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. */
.jdp__lib-trib-section__entete[data-ecart="serre"] { margin-bottom: var(--trib-ecart-serre); }
.jdp__lib-trib-section__entete[data-ecart="moyen"] { margin-bottom: var(--trib-ecart); }
.jdp__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. */
.jdp__lib-trib-section__entete[data-align="gauche"] { text-align: left; }
.jdp__lib-trib-section__entete[data-align="gauche"] .jdp__lib-trib-section__chapo { margin-inline: 0; }
.jdp__lib-trib-section__entete[data-align="gauche"] .jdp__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. */
.jdp__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. */
.jdp__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. */
.jdp__lib-trib-section__entete[data-filet="oui"] .jdp__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). */
.jdp__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. */
.jdp__lib-trib-section__surtitre:empty,
.jdp__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. */
.jdp__lib-trib-section__contenu[data-colonnes="2"],
.jdp__lib-trib-section__contenu[data-colonnes="3"],
.jdp__lib-trib-section__contenu[data-colonnes="4"],
.jdp__lib-trib-section__contenu[data-colonnes="2-3"],
.jdp__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. */
.jdp__lib-trib-section__contenu[data-gouttiere="serre"] { gap: var(--trib-ecart-serre); }
.jdp__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) {
  .jdp__lib-trib-section__titre {
    font-size: 3rem;        /* 48 px */
    line-height: 1;         /* 48 px — le releve donne 48/48 */
  }
  .jdp__lib-trib-section__contenu[data-colonnes="2"],
  .jdp__lib-trib-section__contenu[data-colonnes="2-3"],
  .jdp__lib-trib-section__contenu[data-colonnes="2-4"] { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .jdp__lib-trib-section__contenu[data-colonnes="3"]   { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .jdp__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) {
  .jdp__lib-trib-section__contenu[data-colonnes="2-3"] { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .jdp__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. */
.jdp__lib-trib-section--bloc .jdp__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) {
  .jdp__lib-trib-section--bloc[data-taille="grand"] .jdp__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. */
.jdp__lib-trib-section--bloc .jdp__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. */
.jdp__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) {
  .jdp__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.
   ================================================================================= */

.jdp__lib-trib-section[data-taille="legal"] .jdp__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. */
.jdp__lib-trib-section--titre[data-taille="legal"] .jdp__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. */
.jdp__lib-trib-section[data-pose="carte"][data-taille="legal"] .jdp__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. */
.jdp__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) {
  .jdp__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. */
.jdp__lib-trib-section[data-pose="carte"] .jdp__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. */
.jdp__lib-trib-entete + .jdp__lib-trib-bande:not(:has(.jdp__lib-trib-heros)) > .jdp__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. */
.jdp__lib-trib-section[data-taille="moyen"] .jdp__lib-trib-section__titre {
  font-size: 2.25rem;
  line-height: 2.5rem;
  letter-spacing: -.025em;
}


/* ============================================================================
   journeeinternationaledupulldenoel.fr — feuille LOCALE, prefixe jdp.

   ORDRE DE CASCADE, ecrit par le build dans la COPIE et jamais dans cette source :
     1. le prelude de tokens derive de config.theme (--color-*, --font-*)
     2. les partielles des briques REELLEMENT rendues (socle + tribune)
     3. cette feuille, en dernier : elle surcharge la bibliotheque.

   LES CLASSES SONT PREFIXEES A LA MAIN : le prefixage automatique ne touche que les
   partielles du theme. Une regle ecrite .lib-prose ne rencontrerait rien, la classe
   servie est jdp__lib-prose.

   AUCUNE COULEUR HORS TOKENS : toute valeur de couleur vit dans une declaration --trib-*
   ci-dessous, et les regles ne lisent que des var().
   ============================================================================ */

/* --- l'echelle --trib-*, redefinie EN ENTIER --------------------------------------
   README tribune : deux sites qui gardent l'echelle par defaut servent la meme palette.
   Aucune valeur ci-dessous n'est celle du theme (donc celle de 0clic.com/.fr, qui ne la
   redefinissent pas). Un vert de sapin pour l'accent, un bleu de nuit d'hiver pour les
   fonds sombres, un rouge et un or pour les tons chauds des chiffres.

   SEULS LES TOKENS PRIMITIFS sont redefinis ici. Les tokens de lecture (--trib-fond,
   --trib-texte, --trib-surface...) sont des var() que chaque variante de bande
   reaffecte : les redeclarer sur .jdp__lib-trib-bande, a specificite egale et plus bas
   dans la cascade, ecraserait les bandes sombres. */
:root,
.jdp__lib-trib-bande {
  --trib-accent: #13803A;
  --trib-accent-bas: #0D6A2F;
  --trib-accent-vif: #1FA152;
  --trib-accent-clair: #6FD39A;
  --trib-accent-pale: #BDE8CC;
  --trib-accent-voile: #E4F5EA;
  --trib-accent-brume: #F2FAF5;
  --trib-accent-profond: #0A4F24;
  --trib-accent-nuit: #06351A;

  --trib-chaud: #E8604C;
  --trib-chaud-plein: #C8412D;
  --trib-jaune: #F4C65A;
  --trib-jaune-plein: #D9A21B;

  --trib-nuit: #10233F;
  --trib-nuit-douce: #1B3356;
  --trib-nuit-pleine: #081527;
  --trib-nuit-trait: #2D4A73;

  --trib-clair: #FFFEFA;
  --trib-clair-alt: #F5F8F3;
  --trib-trait: #E4EAE2;
  --trib-trait-fort: #D2DBCF;

  --trib-titre: #10233F;
  --trib-corps: #3D4B5E;
  --trib-second: #5D6A7B;
  --trib-tertiaire: #A3AFBF;
  --trib-sur-nuit: #D6DFEB;

  --trib-pas-section: 4.5rem;
  --trib-pas-heros: 8.5rem;
  --trib-pas-pied: 3.5rem;
  --trib-gouttiere: 1.125rem;

  --trib-large: 70rem;
  --trib-moyen: 54rem;
  --trib-lecture: 46rem;
  --trib-etroit: 40rem;

  --trib-ecart-serre: 1.25rem;
  --trib-ecart: 1.75rem;
  --trib-ecart-large: 2.75rem;

  --trib-rayon-carte: .875rem;
  --trib-rayon-bloc: .625rem;
  --trib-rayon-pastille: 999rem;

  --trib-ombre: 0 1px 3px 0 rgba(16, 35, 63, .08);
  --trib-ombre-haute: 0 12px 20px -6px rgba(16, 35, 63, .16),
                      0 4px 8px -4px rgba(16, 35, 63, .1);

  --trib-transition: 160ms ease-out;
  --trib-transition-lente: 280ms ease-out;
}

/* Deux litteraux du theme vivent dans la variante accent et non dans l'echelle. */
.jdp__lib-trib-bande--accent {
  --trib-surface: rgba(255, 254, 250, .12);
  --trib-bordure: rgba(255, 254, 250, .3);
}

/* Les tokens que les partielles declarent sur leur propre racine : redefinis sur la
   meme racine, sinon la declaration de la brique gagnerait sur :root. */
.jdp__lib-trib-heros {
  --trib-heros-bleu: #C8412D;
}

.jdp__lib-trib-carte {
  --trib-voile-bleu: #E1EAF6;
  --trib-signe-bleu: #2C5BA6;
  --trib-voile-violet: #F8E3E0;
  --trib-signe-violet: #B5362B;
  --trib-voile-vert: #DFF2E5;
}

/* --- les briques du socle posees sur un fond sombre --------------------------------
   lib-prose, lib-figure et les autres briques du socle lisent le prelude (--color-*),
   calcule pour un fond clair. Dans une bande sombre, on le reaffecte depuis l'echelle
   tribune : le texte reste lisible sans variante de brique. */
.jdp__lib-trib-bande--sombre,
.jdp__lib-trib-bande--nuit,
.jdp__lib-trib-bande--encre {
  --color-text: var(--trib-sur-nuit);
  --color-text-muted: var(--trib-tertiaire);
  --color-primary: var(--trib-accent-clair);
  --color-surface: var(--trib-nuit-douce);
  --color-border: var(--trib-nuit-trait);
}

/* --- le socle de page ---------------------------------------------------------------- */
*, *::before, *::after { box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; }

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;
}

/* Les titres du site portent la police de titre ; le theme n'en choisit aucune. */
.jdp__lib-trib-entete__mot,
.jdp__lib-trib-heros__titre,
.jdp__lib-trib-section__titre,
.jdp__lib-trib-chiffre__valeur,
.jdp__lib-trib-diptyque__titre,
.jdp__lib-trib-frise__titre,
.jdp__lib-trib-carte-article__titre,
.jdp__lib-trib-bio__titre,
.jdp__lib-trib-pied__nom,
.jdp__lib-trib-pied__colonne-titre {
  font-family: var(--font-heading);
}

.jdp__lib-trib-heros__titre { font-weight: 800; }

/* --- le haut des pages sans heros ----------------------------------------------------
   La barre de tete est fixe. Le heros compense deja sa hauteur (--trib-pas-heros) ; le
   titre d'une page sans heros reprend la meme compensation, sinon il passe dessous. */
.jdp__lib-trib-section--titre {
  padding-top: calc(var(--trib-pas-heros) - var(--trib-pas-section));
}

/* Le fil d'Ariane et la signature, sous le chapo d'un article. */
.jdp__lib-trib-section--titre .jdp__lib-trib-section__contenu > nav,
.jdp__lib-trib-section--titre .jdp__lib-trib-section__contenu > p {
  margin: 0 0 .25rem;
  font-size: .875rem;
  line-height: 1.5;
  color: var(--trib-texte-faible);
}

.jdp__lib-trib-section--titre .jdp__lib-trib-section__contenu > nav p { margin: 0; }

.jdp__lib-trib-section--titre .jdp__lib-trib-section__contenu > nav a::after {
  content: "\203A";
  margin: 0 .5rem;
  color: var(--trib-texte-faible);
}

.jdp__lib-trib-section--titre .jdp__lib-trib-section__contenu a {
  color: var(--trib-lien);
  text-underline-offset: .2em;
}

/* --- l'article : sommaire a gauche, lecture a droite ---------------------------------
   Le sommaire du socle est `sticky` : dans une colonne unique il glisserait par-dessus
   le texte. Sous 64rem il redevient un bloc ordinaire, au-dessus du texte ; au-dela, il
   prend sa colonne et accompagne la lecture. */
#article-lecture .jdp__lib-sommaire {
  position: static;
  margin: 0 0 var(--trib-ecart);
}

#article-lecture .jdp__lib-figure { margin-top: 0; }

@media (min-width: 64rem) {
  #article-lecture > .jdp__lib-trib-bande__inner {
    display: grid;
    grid-template-columns: minmax(0, 15rem) minmax(0, 1fr);
    column-gap: var(--trib-ecart-large);
    align-items: start;
  }

  #article-lecture > .jdp__lib-trib-bande__inner > * {
    grid-column: 2;
    max-width: 44rem;
  }

  #article-lecture .jdp__lib-sommaire {
    grid-column: 1;
    grid-row: 1 / span 3;
    position: sticky;
    top: 6rem;
    margin: 0;
  }
}

/* Les reperes, apres le texte : publication, mise a jour, prochaine journee. */
#article-lecture .jdp__lib-trib-section--bloc { margin-top: var(--trib-ecart-large); }

/* --- les tableaux du corps -----------------------------------------------------------
   Le socle n'habille pas les tableaux ; cinq articles en portent un. Il defile seul sur
   telephone au lieu d'elargir la page. */
.jdp__lib-prose table {
  display: block;
  width: 100%;
  overflow-x: auto;
  margin: 0 0 1.5em;
  border-collapse: collapse;
  font-size: .95rem;
  line-height: 1.5;
}

.jdp__lib-prose th,
.jdp__lib-prose td {
  padding: .55em .75em;
  border-bottom: 1px solid var(--trib-trait-fort);
  text-align: left;
  vertical-align: top;
}

.jdp__lib-prose thead th {
  background: var(--trib-accent-voile);
  color: var(--trib-titre);
  font-weight: 700;
}

/* --- l'accueil ------------------------------------------------------------------------ */
.jdp__lib-trib-section__chapo a,
.jdp__lib-trib-diptyque__points a {
  color: var(--trib-lien);
  text-underline-offset: .2em;
}

.jdp__lib-trib-chiffre__detail a {
  color: inherit;
  text-underline-offset: .2em;
}

.jdp__lib-trib-chiffre__label {
  max-width: 18rem;
  margin-inline: auto;
  font-size: 1rem;
  line-height: 1.5;
}

/* La bande nocturne porte le texte courant : colonne de lecture, pas de centrage. */
.jdp__lib-trib-bande--nuit .jdp__lib-prose { max-width: none; }

/* --- les reperes d'un article : trois dates cote a cote --------------------------------
   La frise alternee du theme est faite pour une histoire. Pour trois reperes, elle
   laissait de grands vides a 1440 px et prenait un ecran entier a 390 px. */
#article-lecture .jdp__lib-trib-frise {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 9.5rem), 1fr));
  gap: var(--trib-ecart-serre);
}

#article-lecture .jdp__lib-trib-frise::before,
#article-lecture .jdp__lib-trib-frise__etape::before { display: none; }

#article-lecture .jdp__lib-trib-frise__etape + .jdp__lib-trib-frise__etape { margin-top: 0; }

/* Sans axe, le retrait du theme sur telephone (la place de la ligne) n'a plus de raison. */
#article-lecture .jdp__lib-trib-frise__etape { padding-left: 0; }

#article-lecture .jdp__lib-trib-frise__carte,
#article-lecture .jdp__lib-trib-frise__etape:nth-child(even) .jdp__lib-trib-frise__carte {
  width: auto;
  height: 100%;
  margin-left: 0;
  text-align: left;
}

/* --- sous 1024 px, la barre de tete rejoint le flux ------------------------------------
   Sous 64rem le ruban de navigation passe sur une seconde rangee : fixe, la barre montait
   a 167 px a 390 px de large (un cinquieme de l'ecran), cachait la pastille de date du
   heros et recouvrait le titre vise par le sommaire (marge d'ancre de 88 px). Dans le
   flux, elle ne recouvre plus rien ; la compensation de la barre fixe tombe avec elle.
   Au-dela, elle reste fixe et fait 77 px, sous les 88 px de marge d'ancre. */
@media (max-width: 63.99rem) {
  .jdp__lib-trib-entete { position: static; }

  :root,
  .jdp__lib-trib-bande { --trib-pas-heros: var(--trib-pas-section); }
}

/* --- telephone : rien ne deborde a 360 px -------------------------------------------- */
@media (max-width: 47.99rem) {
  .jdp__lib-trib-heros__titre { font-size: 2.5rem; line-height: 1.05; }
  .jdp__lib-trib-section__titre { font-size: 1.875rem; line-height: 1.15; }
  .jdp__lib-trib-chiffre__valeur { font-size: 2.5rem; }

  /* Les reperes en deux colonnes : la prochaine journee, qui porte une phrase, prend toute la
     largeur au lieu d'une colonne de 160 px. */
  #article-lecture .jdp__lib-trib-frise__etape:last-child { grid-column: 1 / -1; }

  /* Un tableau de trois ou quatre colonnes tient dans 354 px si ses intitules passent a la
     ligne (le socle les garde sur une ligne) et si ses mots peuvent se couper. */
  .jdp__lib-prose table { font-size: .8125rem; }

  .jdp__lib-prose th,
  .jdp__lib-prose td {
    padding: .45em .5em;
    white-space: normal;
    hyphens: auto;
    overflow-wrap: anywhere;
  }
}

@media (prefers-reduced-motion: reduce) {
  .jdp__lib-trib-carte-article,
  .jdp__lib-trib-frise__carte { transition: none; }
}
