/* ══════════════════════════════════════════════════════════════
   BON SANS LA RONDELLE — bslr.css
   Direction « instrument » · 25 août 2026

   PRINCIPE
   La voix dans le cadre, le calme dans la lecture. La colonne de
   texte reste sobre — c'est du respect pour l'œil de quelqu'un
   qui lit sept minutes. Tout le reste est du mobilier, et le
   mobilier a le droit d'avoir des dents.

   LE SIGNE
   L'arc partiel. Il n'apparaît QUE là où il mesure vraiment :
   cadran de données, progression de lecture, mot-symbole, pied
   de page. Jamais en ornement — un arc qui décore dévalue les
   arcs qui informent.

   ORGANISATION
     1. Jetons              10. Cadrans et barres
     2. Thèmes              11. Registre
     3. Les 32 équipes      12. Le fil
     4. Base                13. Fiche de l'auteur
     5. En-tête             14. Courriel et pied
     6. Ruban de statut     15. Mobile
     7. Grille              16. Accessibilité et impression
     8. Entrée et article
     9. Blocs de données

   RÈGLE DE TRAVAIL
   Aucune couleur ni mesure en dur après la section 3.
   ══════════════════════════════════════════════════════════════ */


/* ═══ 0. LES POLICES — CHEZ NOUS (v70) ═══════════════════════════

   Elles venaient de Google Fonts, demandees par une ligne de
   base.html. Elles vivent maintenant dans « ressources/polices/ » :
   plus de deux connexions a Google avant le premier mot (100 a
   300 ms de gagnes au premier affichage), plus aucune visite
   signalee a Google, plus de dependance a un service tiers.

   ⚠ LES MEMES FICHIERS, LES MEMES TRANCHES. Pris dans la copie
   officielle de Google sur GitHub (google/fonts), bornes aux
   graisses que la ligne de Google demandait, et coupes selon les
   DEUX tranches que Google sert : « latin » (le francais et
   l'anglais) et « latin-ext » (Dobeš, Slafkovský, Søgaard est deja
   dans « latin »). Le navigateur ne telecharge la seconde que si la
   page contient une de ses lettres. Une lettre hors des deux
   tranches — une fleche, un « № » — tombe dans la police de
   secours, exactement comme avant : RIEN NE CHANGE A L'ECRAN.

   ⚠ « font-display: block », comme le « display=block » de Google :
   un instant de vide plutot qu'un saut. Teko est tres etroite — le
   mot-symbole gonflait de 82 % dans une police de secours.

   ⚠ ET C'EST AUSSI LE DANGER : une police mal declaree laisse le
   texte INVISIBLE, pas dans une autre police. Le nom de famille
   doit etre celui que la feuille emploie (« Source Serif 4 »,
   « Chakra Petch »…), et l'adresse doit exister. Verifie dans
   Chromium avant la livraison.

   ⚠ « latin-ext » EST DECLAREE AVANT « latin » : quand deux
   tranches se chevauchent (U+0304, U+0308, U+0329), la derniere
   declaree gagne — comme chez Google.

   Les licences (SIL Open Font License, toutes les sept) sont dans
   « ressources/polices/LICENCES/ ». ══════════════════════════════ */

@font-face {
  font-family: "Source Serif 4";
  font-style: normal;
  font-weight: 400 700;
  font-display: block;
  src: url("/ressources/polices/source-serif-4-latin-ext.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

@font-face {
  font-family: "Source Serif 4";
  font-style: normal;
  font-weight: 400 700;
  font-display: block;
  src: url("/ressources/polices/source-serif-4-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: "Source Serif 4";
  font-style: italic;
  font-weight: 400;
  font-display: block;
  src: url("/ressources/polices/source-serif-4-italique-latin-ext.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

@font-face {
  font-family: "Source Serif 4";
  font-style: italic;
  font-weight: 400;
  font-display: block;
  src: url("/ressources/polices/source-serif-4-italique-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: "Archivo";
  font-style: normal;
  font-weight: 400 700;
  font-display: block;
  src: url("/ressources/polices/archivo-latin-ext.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

@font-face {
  font-family: "Archivo";
  font-style: normal;
  font-weight: 400 700;
  font-display: block;
  src: url("/ressources/polices/archivo-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: "Teko";
  font-style: normal;
  font-weight: 300 700;
  font-display: block;
  src: url("/ressources/polices/teko-latin-ext.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

@font-face {
  font-family: "Teko";
  font-style: normal;
  font-weight: 300 700;
  font-display: block;
  src: url("/ressources/polices/teko-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: "Chakra Petch";
  font-style: normal;
  font-weight: 500;
  font-display: block;
  src: url("/ressources/polices/chakra-petch-500-latin-ext.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

@font-face {
  font-family: "Chakra Petch";
  font-style: normal;
  font-weight: 500;
  font-display: block;
  src: url("/ressources/polices/chakra-petch-500-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: "Chakra Petch";
  font-style: normal;
  font-weight: 600;
  font-display: block;
  src: url("/ressources/polices/chakra-petch-600-latin-ext.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

@font-face {
  font-family: "Chakra Petch";
  font-style: normal;
  font-weight: 600;
  font-display: block;
  src: url("/ressources/polices/chakra-petch-600-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: "Chakra Petch";
  font-style: normal;
  font-weight: 700;
  font-display: block;
  src: url("/ressources/polices/chakra-petch-700-latin-ext.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

@font-face {
  font-family: "Chakra Petch";
  font-style: normal;
  font-weight: 700;
  font-display: block;
  src: url("/ressources/polices/chakra-petch-700-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: "JetBrains Mono";
  font-style: normal;
  font-weight: 400 700;
  font-display: block;
  src: url("/ressources/polices/jetbrains-mono-latin-ext.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

@font-face {
  font-family: "JetBrains Mono";
  font-style: normal;
  font-weight: 400 700;
  font-display: block;
  src: url("/ressources/polices/jetbrains-mono-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: "Caveat";
  font-style: normal;
  font-weight: 500 700;
  font-display: block;
  src: url("/ressources/polices/caveat-latin-ext.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

@font-face {
  font-family: "Caveat";
  font-style: normal;
  font-weight: 500 700;
  font-display: block;
  src: url("/ressources/polices/caveat-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: "Caveat Brush";
  font-style: normal;
  font-weight: 400;
  font-display: block;
  src: url("/ressources/polices/caveat-brush-latin-ext.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

@font-face {
  font-family: "Caveat Brush";
  font-style: normal;
  font-weight: 400;
  font-display: block;
  src: url("/ressources/polices/caveat-brush-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}


/* ═══ 1. JETONS ═══════════════════════════════════════════════ */

:root {

  /* — Typographie ————————————————————————————————
     Cinq familles, un poste chacune.

     lecture    tout ce qui se lit en continu
     affichage  le titre d'article, rien d'autre
     sans       mobilier général : mot-symbole, menu, sous-titres
     etiquette  UNIQUEMENT dans un contexte de données
     donnees    dates, chiffres, métadonnées

     Chakra Petch n'apparaît jamais hors d'un contexte de données.
     C'est ce qui fait qu'elle veut dire quelque chose quand elle
     apparaît.                                                  */

  --lecture:   "Source Serif 4", Georgia, "Times New Roman", serif;
  --affichage: "Teko", "Archivo", Helvetica, sans-serif;
  --sans:      "Teko", "Archivo", Helvetica, sans-serif;
  --etiquette: "Chakra Petch", "Archivo", Helvetica, sans-serif;
  --donnees:   "JetBrains Mono", ui-monospace, Consolas, monospace;

  /* Le filet des jetons d'equipe. Sur charbon il est TRANSPARENT :
     il y etait de toute facon invisible, et une valeur figee
     laissait un coin sombre quand la rangee changeait de fond au
     survol. Transparent, le biseau laisse simplement voir ce qu'il
     y a derriere. */
  --jeton-filet: transparent;

  /* Deux ecritures a la main, pour Le bilan. « Caveat » est posee
     et lisible; « Caveat Brush » est plus large et plus nerveuse,
     tracee au feutre. */
  --main:      'Caveat', cursive;
  --main-gras: 'Caveat Brush', cursive;

  /* — Échelle fluide ————————————————————————————— */
  /* Teko est condensée : à taille égale elle occupe moins de
     largeur, donc l'échelle des titres monte. */
  --t-titre:    clamp(2.5rem, 5.6vw, 4.5rem);
  --t-chapeau:  clamp(1.1875rem, 0.43vw + 1.08rem, 1.375rem);
  --t-corps:    clamp(1.125rem, 0.43vw + 1.018rem, 1.3125rem);
  --t-section:  clamp(1.375rem, 0.4vw + 1.28rem, 1.5rem);
  --t-exergue:  clamp(1.3125rem, 0.6vw + 1.19rem, 1.5625rem);

  /* — Mesures ————————————————————————————————————
     La largeur totale du site. Sur grand écran, c'est la marge
     qui grossit; le contenu, lui, ne dépasse jamais ce chiffre.
     La colonne de LECTURE est un réglage à part : « --mesure »,
     plus bas. */
  --largeur-max:    1320px;
  --marge-laterale: max(1.5rem, calc((100% - var(--largeur-max)) / 2));
  --largeur-marge:  176px;
  /* La colonne de texte demarre au quart de la largeur, c'est-a-
     dire pile sur le filet gauche de la deuxieme case de mesures.
     Exprime en pourcentage plutot qu'en pixels : les cases font
     un quart chacune, donc l'alignement tient a toutes les
     largeurs. Le « max » evite une gouttiere negative sur un
     ecran etroit. */
  --gouttiere:      max(1.5rem, calc(25% - var(--largeur-marge)));

  /* Le dessin de la croix qui vide un champ de recherche. */
  --croix: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12'%3E%3Cpath d='M1.4 0 6 4.6 10.6 0 12 1.4 7.4 6 12 10.6 10.6 12 6 7.4 1.4 12 0 10.6 4.6 6 0 1.4Z'/%3E%3C/svg%3E");

  /* La vedette en photo. « bande » est ce qu'on voit au repos,
     « recouvre » de combien le panneau glisse sous la barre,
     « remonte » de combien le texte se hisse dans le voile. */
  --photo-bande:    6.25rem;
  --photo-recouvre: 4px;
  --photo-remonte:  17.5px;

  /* ⚠ LE TITRE DE LA VEDETTE A SA PROPRE TAILLE.

     Il portait « --t-titre », celle de la PAGE D'ARTICLE — autour
     de 75 px. Cette taille-la est pensee pour un titre qui occupe
     toute la largeur du site; le panneau de la vedette fait 890 px,
     et un titre un peu long y debordait de sa bande.

     Deux boites de largeurs differentes, deux metiers differents.
     Les lier obligeait a choisir un compromis qui ne servait ni
     l'un ni l'autre.

     Le « clamp » retombe a 2,5 rem sous 1 100 px : c'est exactement
     ce que l'ancienne regle donnait sur un telephone, et le petit
     ecran ne change donc pas d'un pixel. */
  --t-titre-vedette: clamp(2.5rem, 3.64vw, 3rem);

  /* L'air sous le titre, dans la bande au repos. La bande est
     MESUREE par theme.js a partir du titre reel — voir la note de
     « centrerVedette ». Ce jeton est le seul reglage a l'oeil qui
     reste : il dit de combien le voile depasse sous la derniere
     ligne. */
  --photo-air:      4px;
  /* De combien le bloc de texte descend UNE FOIS LA FENETRE
     OUVERTE, pour se centrer dans le cadre. Au repos il ne bouge
     pas : le titre y occupe deja toute la bande.

     Ce chiffre ne suffit pas a lui seul — le rembourrage du bas
     vaut presque le double de celui du haut, et il faut le
     reduire pour que les deux marges se rejoignent. Voir le
     rembourrage du panneau plus bas. */
  --photo-centre:   58.5px;
  --photo-glisse:   420ms cubic-bezier(.66, 0, .28, 1);
  --photo-balai:    680ms cubic-bezier(.33, 0, .2, 1) 180ms;

  /* La colonne de lecture. Elle etait ecrite « 66ch », mais le
     « ch » se mesure sur la police du conteneur — Teko, qui est
     condensee. La colonne tombait a 438 px, soit 39 caracteres
     par ligne au lieu des 66 voulus. En rem, elle suit l'echelle
     du site sans dependre de la police du cadre. */
  /* Du quart de l'encadre jusqu'aux environs du 95e centieme,
     soit a peu pres le milieu du vide de la derniere case de
     mesures. ATTENTION : ca porte la ligne a 83 caracteres,
     au-dela des 66 que le cahier fixe. */
  --mesure:         54.5rem;

  /* — Motif ——————————————————————————————————————
     Coin biseauté : repris des cartouches d'habillage vidéo de
     l'auteur, présent dans ses archives depuis 2024.          */
  /* ⚠ LA SOURCE SOUS UNE FIGURE — deux chiffres d'oeil.

     « retrait » la décale du bord droit de la photo : PLUS PETIT,
     plus elle s'approche du bord. « air » la descend sous le
     cadre : plus grand, plus elle s'en éloigne.

     ⚠ LES DEUX SONT EN PIXELS, ET C'EST VOULU. « retrait » valait
     0,625 rem — soit 10,625 px sur une racine à 17. Un ajustement
     d'un pixel y devenait une fraction de rem illisible. Ce sont
     des chiffres réglés à l'oeil, ils s'écrivent dans l'unité où
     l'oeil les mesure. */
  --figure-retrait: 9.625px;
  --figure-air:     3px;

  --biseau:       6px;
  --biseau-large: 14px;

  /* Le trait noir qui cerne toutes les étiquettes.
     Il ne se voit pas toujours — sur un badge déjà sombre, il
     disparaît. Il est là quand même : c'est ce qui garantit que
     toutes les étiquettes ont exactement la même taille
     optique, cernées ou non. */
  --cerne: #0A0A09;

  --glisse: 0.16s ease;
}


/* ═══ 2. THÈMES ═══════════════════════════════════════════════ */

/* — Foncé (défaut) —————————————————————————————————
   Trois couches, chacune avec sa job :
     marque   le mobilier permanent — os sur charbon
     ambre    la ponctuation. Chaud, pas sportif, pas partisan.
              Couleur des afficheurs techniques. L'auteur
              l'employait déjà dans ses chevrons.
     sens     le jugement porté sur une donnée                 */

:root,
html[data-theme="fonce"] {
  --fond:      #161614;
  --surface:   #1D1D1A;
  --surface2:  #24241F;
  --os:        #ECE8E4;
  --titre:     #ECE8E4;
  --corps:     #C9C5BD;
  --attenue:   #8B877E;
  --faible:    #726E66;   /* remonté : plus bas, le monospace
                             devient illisible sur --surface2 */
  --filet:     #272721;
  --filet2:    #36362F;

  --ambre:     #877B66;
  --ambre-vif: #9C8F76;

  --bon:       #5FBF6A;
  --moyen:     #D9A62B;
  --mauvais:   #D2453F;

  --nav:        #ECE8E4;
  --nav-survol: #877B66;
  --ruban-fond:      #1D1D1A;
  --ruban-etiquette: #726E66;
  --ruban-valeur:    #ECE8E4;
  --cadre-fond:      #101010;
  --cadre-tete:      #1A1A17;

  /* Les quatre bandes du site : le ruban, l'en-tête de la
     dernière publication, l'en-tête du fil, le bandeau courriel.
     En foncé, un simple creux de valeur. */
  --bande-fond:      #1D1D1A;
  --bande-bord:      #35352E;

  /* Le contour des boutons et du formulaire d'inscription. Il ne
     suit AUCUN des jetons existants, parce qu'il fait le trajet
     inverse de la plupart : il reste sombre dans les deux themes.

     En fonce, c'est le fond de la page — le bouton parait donc
     decoupe A MEME le papier. En clair, c'est l'encre rechauffee,
     le meme noir chaud que les titres. C'est la paire papier-encre
     du cahier, prise du bon bord chaque fois.

     Un jeton a lui parce que ni « --fond » ni « --titre » ne
     donnent cette combinaison-la. */
  --bouton-filet:    #161614;
  --bande-etiquette: #726E66;
  --bande-valeur:    #ECE8E4;
  --bande-titre:     #ECE8E4;
  --bande-texte:     #877B66;

  --section-titre:   #ECE8E4;
  --lueur:           #272721;

  /* L'arc de progression de lecture, epingle au coin de l'article.
     Il ne peut pas prendre --ambre : en mode clair, --ambre et
     --filet2 tombent sur la meme valeur et l'arc disparaitrait
     dans sa propre piste. */
  --arc-lecture:     #877B66;


  /* La piste des instruments — progression, cadran, barres. Elle
     doit s'effacer presque completement : c'est le remplissage
     qu'on regarde arriver, pas le contenant. */
  --piste:           #36362F;

  /* Un voile, pas un fond : en foncé on pose un peu d'os
     par-dessus, en clair un peu d'encre. Comme c'est une couche
     translucide, le survol eclaircit toujours sur fond sombre et
     assombrit toujours sur fond pale, quel que soit l'objet. */
  --voile:           rgba(236, 232, 228, 0.045);

  /* Le voile de la vedette en photo : l'interieur du panneau du
     fil, rendu translucide. Presque opaque, pour que le texte
     tienne par-dessus n'importe quelle image. */
  --photo-voile:     rgba(16, 16, 16, 0.93);

  /* Les deux courbes de la fiche de joueur. Sur charbon, deux
     valeurs franches qui portent leur halo — c'est le seul
     endroit du site ou une couleur est la pour briller plutot
     que pour mesurer. La lueur est la meme teinte, diluee. */
  --courbe-pts:       #FF932B;
  --courbe-b:         #0CE000;

  /* Les deux verdicts du Bilan. Le vert des courbes ne pouvait pas
     servir : a 1,48:1 sur papier, il y est illisible. */
  --verdict-juste:    #3FAE72;
  --verdict-moyen:    #E0A81E;
  --verdict-croche:   #E8474B;
  --courbe-pts-lueur: rgba(255, 147, 43, 0.75);
  --courbe-b-lueur:   rgba(12, 224, 0, 0.75);


  /* Identique à --faible en foncé : le jeton n'existe que pour
     diverger en clair. */
  --service:         #726E66;
}

/* — Clair —————————————————————————————————————————
   La référence change : plus l'écran d'un outil, mais la page
   d'un annuaire statistique imprimé. Même densité, même
   monospace, mêmes filets — sur papier plutôt que sur verre.

   L'os devient de l'encre : sur papier, un gris pâle
   disparaîtrait. L'ambre descend : trop vif, il vibre.       */

html[data-theme="clair"] {
  /* Voir la note de « html » : le navigateur doit savoir de
     quelle famille est la page. La barre, elle, suit ses jetons. */
  color-scheme: light;
  --fond:      #ECE8E4;
  --surface:   #E2DDD8;
  --surface2:  #D7D1CA;
  /* L'encre du mode clair est le fond du mode foncé : les deux
     thèmes se renvoient exactement la même valeur, l'un en papier,
     l'autre en encre. */
  /* L'encre du mode clair est RECHAUFFEE. A #161614 elle etait un
     noir quasi neutre — deux points d'ecart entre ses canaux —
     alors que tout le reste de la palette est chaud. Elle
     detonnait, non pas parce qu'elle etait trop foncee, mais parce
     qu'elle etait etrangere.

     #211A12 garde la profondeur (14,11:1 contre 14,87) et rejoint
     la famille : quinze points d'ecart entre canaux, entre l'os du
     mode sombre et l'ambre. */
  --os:        #211A12;
  --titre:     #211A12;
  --corps:     #3B3A34;
  --attenue:   #6E6A62;
  --faible:    #857F76;
  /* Contours et séparateurs : une seule valeur, la même que les
     bordures de bande. Le trait structure la page au lieu de
     s'effacer. */
  --filet:     #595143;
  --filet2:    #595143;

  --ambre:     #595143;
  --ambre-vif: #453F34;

  --bon:       #2F7D3A;
  --moyen:     #96700D;
  --mauvais:   #A5231E;

  --nav:        #877B66;
  --nav-survol: #595143;
  --ruban-fond:      #DFDAD4;
  --ruban-etiquette: #877B66;
  --ruban-valeur:    #595143;
  --cadre-fond:      #DFDAD3;
  --cadre-tete:      #877B66;

  /* En clair, les bandes sont pleines : elles structurent la page
     au lieu de la creuser. Le texte s'inverse en conséquence. */
  --bande-fond:      #877B66;
  --bande-bord:      #595143;
  /* L'encre rechauffee, comme les titres. Voir le mode fonce. */
  --bouton-filet:    #211A12;
  --bande-etiquette: #DCD6CA;
  --bande-valeur:    #FBF9F6;
  --bande-titre:     #FBF9F6;
  --bande-texte:     #E8E3D9;

  /* Le nom de section prend la valeur claire de l'ambre : sur
     papier, le ton foncé le rapprochait trop d'un titre d'article.
     Il annonce une zone, il n'a pas à porter comme un titre. */
  /* Sur papier, les titres de section prennent l'encre plutot que
     le taupe : a #877B66 ils s'effacaient dans le fond clair, et
     rien ne separait plus le tableau de ce qui le precede.
     Sur charbon, le taupe garde tout son sens. */
  --section-titre:   #211A12;
  /* Le survol d'une rangée : un gris neutre, à peine sous le fond
     de la page. Assez pour suivre l'œil, pas assez pour crier. */
  --lueur:           #E3DED7;

  /* Le ton appuye, comme en fonce mais inverse. */
  --arc-lecture:     #595143;


  /* Sur papier il faut une valeur BEAUCOUP plus pale que le
     remplissage : a #877B66, la piste etait deux fois trop
     presente et l'arc arrivait comme un ajout. */
  --piste:           #BFB6AA;

  --voile:           rgba(22, 22, 20, 0.08);

  --photo-voile:     rgba(223, 218, 211, 0.93);

  /* Sur papier, deux valeurs sourdes : un halo n'a rien a
     eclairer sur un fond pale. */
  /* Choisi pour se detacher de l'encre ordinaire plutot que du
     papier : c'est de l'encre noire que le meneur doit se
     distinguer, pas du fond. */
  /* Sur papier, deux valeurs sourdes : un halo n'a rien a
     eclairer sur un fond pale, et un trait vif s'y delave. Le
     vert vif du meneur, lui, reste — il marque un seul mot, pas
     une courbe entiere. */
  --courbe-pts:       #1C333B;
  --courbe-b:         #3A6E62;

  /* Sur papier, les deux verdicts s'assombrissent : le vert passe
     de 2,29 a 5,31:1, le rouge de 3,57 a 5,57. */
  --verdict-juste:    #1E6B45;
  --verdict-moyen:    #8F6205;
  --verdict-croche:   #B02128;
  --courbe-pts-lueur: rgba(28, 51, 59, 0.75);
  --courbe-b-lueur:   rgba(58, 110, 98, 0.75);

  /* Le gris de service : numéros, dates, temps de lecture, pied de
     page. En foncé il vaut --faible; sur papier, ce gris-là se
     délave et l'ambre tient mieux. */
  --service:         #877B66;
  /* Sur papier, le filet est bien visible et prend la temperature
     de l'encre : sans lui, un logo clair flotterait sans contour. */
  --jeton-filet:     #211A12;
}


/* ═══ 3. LES 32 ÉQUIPES ═══════════════════════════════════════
   Deux valeurs chacune : la vive pour le texte, l'assombrie
   pour le fond de l'étiquette.

   Les teintes officielles brutes ne fonctionnent pas — le jaune
   de Boston et le vert du Wild sont illisibles à petite taille
   sur charbon. Ces valeurs-ci sont calibrées : reconnaissables,
   mais lisibles. À ajuster à l'œil.                           */

.ana { --eq:#FFFFFF; --eqf:#E34920; }
.bos { --eq:#FFB81C; --eqf:#151515; }
.buf { --eq:#FFB81C; --eqf:#003087; }
.cgy { --eq:#F1BE48; --eqf:#C8102E; }
.car { --eq:#FFFFFF; --eqf:#C8102E; }
.chi { --eq:#FFFFFF; --eqf:#C20814; }
.col { --eq:#C6CBCC; --eqf:#6F263D; }
.cbj { --eq:#C6CBCC; --eqf:#041E42; }
.dal { --eq:#E9EBEB; --eqf:#00843D; }
.det { --eq:#FFFFFF; --eqf:#C8102E; }
.edm { --eq:#FF5113; --eqf:#00205B; }
.fla { --eq:#CFB78D; --eqf:#BE0000; }
.lak { --eq:#A2AAAD; --eqf:#151515; }
.min { --eq:#DDCBA4; --eqf:#154734; }
.mtl { --eq:#FFFFFF; --eqf:#A71819; }
.nsh { --eq:#041E42; --eqf:#FFB81C; }
.njd { --eq:#FFFFFF; --eqf:#CB0607; }
.nyi { --eq:#FC4C02; --eqf:#003087; }
.nyr { --eq:#FFFFFF; --eqf:#0032A0; }
.ott { --eq:#C8102E; --eqf:#151515; }
.phi { --eq:#151515; --eqf:#FA4616; }
.pit { --eq:#151515; --eqf:#FFB81C; }
.sjs { --eq:#C6C7C5; --eqf:#006271; }
.sea { --eq:#9CDBD9; --eqf:#051C2C; }
.stl { --eq:#FFB81C; --eqf:#003087; }
.tbl { --eq:#FFFFFF; --eqf:#00205B; }
.tor { --eq:#FFFFFF; --eqf:#002663; }
.uta { --eq:#69B3E7; --eqf:#151515; }
.van { --eq:#00843D; --eqf:#00205B; }
.vgk { --eq:#B9975B; --eqf:#333F48; }
.wsh { --eq:#FFFFFF; --eqf:#C8102E; }
.wpg { --eq:#A2AAAD; --eqf:#041E42; }
.lnh { --eq:#A2AAAD; --eqf:#151515; }   /* texte sans équipe */

/* Le site lui-même. Sert quand une note ou un texte parle de
   « Bon sans la rondelle » plutôt que d'une équipe : une annonce,
   un changement, un mot sur la démarche. Il prend l'ambre du
   site, donc il n'entre en concurrence avec aucune des 32. */
.bslr { --eq:#ECE8E4; --eqf:#595143; }

/* ── LA TEINTE DU FIL ────────────────────────────────────────
   Les cartes du fil, leur filet et leur pastille se colorent avec
   « --eqt ». Il n'est defini nulle part : chaque usage ecrit
   « var(--eqt, var(--eqf)) », donc la couleur de FOND sert par
   defaut. C'est elle qui porte l'identite — le texte est souvent
   du blanc ou du gris pale, qui ne teinte rien.

   Six exceptions : leur fond est noir ou marine, et c'est leur
   couleur de TEXTE qui les identifie. La ligue elle-meme en fait
   partie — son fond est du charbon, qui ne teinte rien. */
.bos, .sea, .uta, .van, .vgk, .lnh { --eqt: var(--eq); }

/* Et une septieme, qui ne marche pas pareil : Winnipeg.

   Son fond est un marine trop sombre pour teinter — a 9 % sur le
   papier, la carte tombe a rgb(203,201,198) quand les autres
   s'eclaircissent. Elle est la seule qui FONCE.

   Mais l'argent de son lettrage ne dit rien de Winnipeg : il
   sert a decouper le texte sur le marine, pas a identifier
   l'equipe. Renvoyer a « --eq » reglait le contraste et perdait
   la couleur.

   Alors on IMPOSE. « --eqt » est un jeton comme un autre : rien
   ne l'oblige a reprendre une valeur de la paire. Celle-ci est
   l'Aviator Blue des Jets, le bleu de l'avion sur le chandail.
   Assez clair pour teinter, et a eux.

   C'est le seul cas du site. Si une autre equipe se retrouve
   dans la meme situation, elle vient ici — pas dans la ligne
   du dessus, qui veut dire autre chose. */
.wpg { --eqt: #004C97; }

/* ── LA LIGNE DE DATE DU FIL, EN SOMBRE ──────────────────────
   La ligne de date d'une carte prend la couleur de TEXTE de son
   equipe (« --eq »), parce que le texte d'equipe est presque
   toujours clair. PRESQUE : trois equipes ont l'inverse, un fond
   vif et un texte fonce. Melange au gris de service, leur noir ou
   leur marine tombait sous 1,5:1 — une date invisible (trouve par
   l'auteur sur une note des Flyers, 24 septembre).

   Pour ces trois-la, la ligne prend leur couleur de FOND, qui est
   vive : Philadelphie monte de 1,48 a 4,00:1, Pittsburgh et
   Nashville de 1,4 a 6,45:1.

   « --eqm » n'est defini nulle part ailleurs : la regle ecrit
   « var(--eqm, var(--eq, ...)) », donc les 31 autres ne bougent
   pas. Le mode clair a sa propre regle et ne le lit pas.

   Ottawa (2,91) et Vancouver (3,45) sont faibles aussi, mais leur
   fond est plus fonce encore : ce jeton ne les aiderait pas. */
.phi, .pit, .nsh { --eqm: var(--eqf); }


/* ═══ 4. BASE ═════════════════════════════════════════════════ */

*, *::before, *::after { box-sizing: border-box; }

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;

  /* ⚠ LA BARRE DE DÉFILEMENT PORTE LES COULEURS DU SITE.

     Elle sortait du système : un rectangle clair au bord d'une
     page charbon, la seule chose à l'écran que le site ne
     dessinait pas.

     ⚠ DEUX PROPRIÉTÉS SUFFISENT, ET IL NE FAUT PAS ÉCRIRE LES
     AUTRES.

     « scrollbar-color » et « scrollbar-width » sont standard, et
     pris en charge partout depuis 2025. La documentation est
     formelle : dès qu'elles valent autre chose que « auto », elles
     ÉCRASENT « ::-webkit-scrollbar ». Écrire les anciennes
     pseudo-classes en plus serait du code qui ne s'exécute jamais
     — et qu'on croirait pourtant vivant en le relisant.

     ⚠ ELLES S'HÉRITENT. Posées ici, elles valent pour toutes les
     zones qui défilent, y compris celles qu'on n'a pas encore
     écrites.

     ⚠ ET ELLES SUIVENT LE THÈME TOUTES SEULES, parce qu'elles
     lisent des jetons qui changent avec lui. Le jour où la
     palette claire bouge, la barre suit sans qu'on y pense.

     « color-scheme » va avec : il dit au navigateur de quelle
     famille est la page, ce qui teinte aussi les menus déroulants
     et les champs qu'il dessine lui-même. */
  color-scheme: dark;
  scrollbar-color: var(--filet2) var(--fond);
  scrollbar-width: thin;

  /* ÉCHELLE DU SITE — le seul chiffre à changer.
     Tout est en rem : monter cette valeur agrandit le site au
     complet, proportions intactes. 16px est le défaut des
     navigateurs; 18px convient mieux à un grand écran.        */
  font-size: 17px;

  /* Réserve la place de la barre de défilement en permanence.
     Sans ça, une page courte est quelques pixels plus large
     qu'une page longue, et le contenu saute d'une page à
     l'autre.                                                  */
  scrollbar-gutter: stable;
}

body {
  margin: 0;
  background: var(--fond);
  color: var(--corps);
  font-family: var(--sans);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  transition: background var(--glisse), color var(--glisse);
}

a { color: inherit; text-decoration: none; }
img { max-width: 100%; height: auto; display: block; }

.biseau {
  clip-path: polygon(
    0 0, calc(100% - var(--biseau)) 0, 100% var(--biseau),
    100% 100%, var(--biseau) 100%, 0 calc(100% - var(--biseau)));
}

/* Étiquette de code d'équipe.
   Largeur fixe : une colonne d'étiquettes doit s'aligner comme
   une colonne de chiffres. Sans ça, WPG est plus large que TOR
   et l'œil accroche à chaque rangée.
   Le text-indent compense l'interlettrage, qui ajoute un espace
   après la dernière lettre et décentre le texte.              */
.code {
  position: relative;
  isolation: isolate;
  display: inline-flex;
  justify-content: center;
  align-items: center;
  width: 52px;
  height: 22px;
  text-indent: .1em;
  font-family: var(--etiquette);
  font-size: 0.78125rem;
  font-weight: 700;
  letter-spacing: .1em;
  color: var(--eq, var(--os));
  background: var(--cerne);
  clip-path: polygon(
    0 0, calc(100% - var(--biseau)) 0, 100% var(--biseau),
    100% 100%, var(--biseau) 100%, 0 calc(100% - var(--biseau)));
}
.code::before {
  content: "";
  position: absolute;
  inset: 1px;
  z-index: -1;
  background: var(--eqf, var(--surface2));
  clip-path: polygon(
    0 0, calc(100% - 5px) 0, 100% 5px,
    100% 100%, 5px 100%, 0 calc(100% - 5px));
}

.jeton {
  position: relative;
  isolation: isolate;
  display: inline-flex;
  align-items: center;
  height: 22px;
  padding: 0 0.625rem;
  font-family: var(--etiquette);
  font-size: 0.78125rem;
  font-weight: 700;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--fond);
  background: var(--cerne);
  clip-path: polygon(
    0 0, calc(100% - var(--biseau)) 0, 100% var(--biseau),
    100% 100%, var(--biseau) 100%, 0 calc(100% - var(--biseau)));
}
.jeton::before {
  content: "";
  position: absolute;
  inset: 1px;
  z-index: -1;
  background: var(--os);
  clip-path: polygon(
    0 0, calc(100% - 5px) 0, 100% 5px,
    100% 100%, 5px 100%, 0 calc(100% - 5px));
}


/* ═══ 5. EN-TÊTE ══════════════════════════════════════════════ */

.entete {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1.125rem;
  flex-wrap: wrap;
  padding: 0 var(--marge-laterale);
  min-height: 56px;
  border-bottom: 1px solid var(--filet);
}

/* L'ecart resserre : le logo est plus large que le cadran, il n'a
   plus besoin d'autant d'air pour se detacher du mot. */
.marque { display: flex; align-items: center; gap: 0.5rem; }

/* ESSAI — le logo a la place du cadran. Un cinquieme plus gros
   que le signe qu'il remplace, et il ne se comprime pas. */
.marque__logo {
  flex-shrink: 0;
  width: 31px;
  height: 31px;
  display: block;
}

/* Le signe. Ici il est la marque, pas un ornement. */

.motsymbole {
  font-family: var(--sans);
  font-size: 1.5rem;
  font-weight: 400;
  letter-spacing: 0;
  color: var(--os);
  white-space: nowrap;
  line-height: 1;
  /* Teko porte sa masse dans le haut de la ligne : la boite est
     centree, mais l'encre parait 4 px plus haute que le cadran a
     cote. On decale l'encre, pas la boite — « position: relative »
     ne change rien a la mise en page. */
  position: relative;
  /* Cale sur l'encre du mot « CLAIR » dans sa boite, pas sur le
     milieu geometrique de la barre : c'est le mot voisin que
     l'oeil compare. Le rendu arrondit au pixel entier, donc
     0,11em a 0,14em donnent tous le meme resultat — on se pose
     au milieu du plateau pour resister aux arrondis. */
  top: 0.125em;
}
/* « BONSANSLA » en os plein, « RONDELLE » en accent : le nom
   reprend de la couleur, comme du temps où RONDELLE était rouge. */
.motsymbole__la  { color: inherit; }
.motsymbole__ron { color: var(--ambre); }

/* En mode clair, les deux moitiés du nom changent de valeur
   plutôt que de teinte : même famille, deux intensités. */
/* En clair, « BONSANSLA » prend la valeur foncée et « RONDELLE »
   la claire — l'inverse de ce qu'on avait. C'est la moitié qui
   porte le nom qui recule, et l'accent qui avance. */
html[data-theme="clair"] .motsymbole     { color: #877B66; }
html[data-theme="clair"] .motsymbole__ron { color: #595143; }

/* Menu en Archivo, comme le mot-symbole : deux polices sur la
   même ligne se lisent comme une hésitation. */
.nav { display: flex; align-items: center; flex-wrap: wrap; }
.nav a {
  font-family: var(--sans);
  font-size: 1.125rem;
  font-weight: 400;
  letter-spacing: 0;
  text-transform: uppercase;
  color: var(--nav);
  /* Deux causes se cumulaient : la masse haute de Teko, et la
     bordure de 2 px en bas qui raccourcit la zone de texte par
     le bas. Ce qu'on ajoute en haut, on le retire en bas — la
     hauteur du lien ne bouge pas, seule l'encre descend. */
  padding: calc(0.4rem + 0.15em) 0.8125rem calc(0.4rem - 0.15em);
  border-bottom: 2px solid transparent;
  transition: color var(--glisse);
}
.nav a:hover,
.nav a[aria-current="page"] {
  color: var(--nav-survol);
  border-bottom-color: var(--nav-survol);
}

/* Même police, même graisse, mêmes couleurs que le menu : la
   bascule fait partie de la même ligne, donc du même objet.

   Largeur fixe : « CLAIR » fait 32 px et « SOMBRE » 46 px. Sans
   largeur imposée, la boîte change de taille quand on bascule,
   et le menu à sa gauche se déplace. 4,75 rem loge le plus long
   des deux avec la même respiration de chaque bord.

   Le décalage de 0,15em est celui du bouton EMBARQUE : Teko
   porte sa masse dans le haut de la ligne, donc le texte paraît
   collé au bord supérieur. Ce qu'on ajoute en haut, on le retire
   en bas — la boîte garde exactement la même hauteur. */
.bascule {
  margin-left: 0.75rem;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 4.75rem;
  background: none;
  border: 1px solid var(--filet2);
  color: var(--nav);
  font-family: var(--sans);
  /* Taille nulle sur le bouton lui-meme : seul le mot ecrit par
     « ::after » s'affiche. Si un vieux gabarit laisse trainer du
     texte dans le HTML, il ne se voit pas — au lieu de s'ajouter
     au mot de la feuille et d'ecrire CLAIRSOMBRE. */
  font-size: 0;
  font-weight: 400;
  letter-spacing: 0;
  line-height: 1;
  text-transform: uppercase;
  /* 0,58 rem plutot que 0,35 : « line-height: 1 » raccourcit la
     ligne, on rend au padding ce que l'interligne a perdu pour
     que la boite garde sa hauteur d'avant. Le decalage optique
     passe en rem, sinon il vaudrait zero avec la taille nulle. */
  padding: calc(0.58rem + 0.1125rem) 0.75rem calc(0.58rem - 0.1125rem);
  cursor: pointer;
  transition: color var(--glisse), border-color var(--glisse);
}
/* Le mot du bouton vient d'ici, pas du HTML. Le theme est pose
   sur la page avant le premier affichage, donc la bonne valeur
   est la des le depart : aucun script n'a a la corriger apres
   coup, et la transition de page ne peut plus photographier le
   bouton entre deux etats. C'est ce qui faisait apparaitre CLAIR
   et SOMBRE l'un sur l'autre, uniquement sur papier — en foncé
   les deux mots coincidaient, donc rien ne paraissait. */
.bascule::after { content: "Clair"; font-size: 1.125rem; }
html[data-theme="clair"] .bascule::after { content: "Sombre"; }

.bascule:hover { color: var(--nav-survol); border-color: var(--nav-survol); }


/* — Trois objets qui se comportent autrement en clair ————
   En foncé, ces boîtes sont des creux : un fond à peine plus
   sombre, un filet discret. Sur papier ça ne tient pas — un
   creux ne se voit pas. Elles deviennent donc pleines, comme les
   quatre bandes du site. */

/* Le cadre du bouton reprend la valeur du menu, à côté duquel il
   vit, au lieu du filet foncé des séparateurs. */
html[data-theme="clair"] .bascule { border-color: var(--nav); }

/* La boîte du filtre devient pleine : fond de bande, texte
   inversé. « --fond » sert ici de couleur de texte — c'est la
   valeur du papier, posée sur un aplat. */
/* L'invite du champ courriel, sur papier. Valeur ecrite en clair :
   « --ambre » vaut #595143 de ce cote-la, pas #877B66. */
html[data-theme="clair"] .formulaire input::placeholder { color: #877B66; }

html[data-theme="clair"] .filtre__declencheur,
html[data-theme="clair"] .recherche input {
  background: var(--bande-fond);
  border-color: var(--bande-bord);
  color: var(--fond);
}
html[data-theme="clair"] .recherche input { color: var(--fond); }
html[data-theme="clair"] .recherche input::placeholder { color: var(--fond); }

/* Dates et mots-clés du fil : le gris de service disparaît sur
   papier, l'ambre foncé tient. */
html[data-theme="clair"] .note-fil__meta { color: var(--ambre); }

/* Le chapeau sous un titre de registre : même traitement que les
   autres textes de service. En foncé il garde son gris atténué. */
html[data-theme="clair"] .registre__titre small { color: var(--service); }

/* Les etiquettes de la marge d'article : sur papier, elles
   prennent la valeur des categories de mesures. */
html[data-theme="clair"] .marge__e { color: var(--ambre); }

/* Sur papier, ce qui doit valoir #877B66 change de jeton :
   --ambre y vaut #595143, c'est --service qui porte la bonne
   valeur. */
/* Sur papier, --filet2 et --ambre tombent tous les deux sur
   #595143 : la piste disparaitrait sous son remplissage. On
   redistribue. La piste prend le taupe clair et le remplissage le
   ton foncé : sur papier, c'est le foncé qui tranche, donc c'est
   lui qui doit porter la valeur mesuree — le meme rapport qu'en
   sombre, ou la piste s'efface et le remplissage ressort. Meme
   correctif pour les bandes de temps, qui souffraient exactement
   du meme telescopage. */
/* Sur papier, la ligne de metadonnees se melange a l'ENCRE et non
   au gris de service : a 62 % d'une couleur vive, Boston tombait a
   1,73:1 et Seattle a 1,86. A 35 % dans l'encre, la pire equipe
   tient a 5,58:1. */
html[data-theme="clair"] .mur__note--meta {
  color: color-mix(in srgb, var(--eqt, var(--eqf)) 45%, var(--titre));
}

html[data-theme="clair"] .cadran .piste  { stroke: var(--piste); }
html[data-theme="clair"] .cadran .arc    { stroke: var(--ambre); }
html[data-theme="clair"] .barre__piste   { background: var(--piste); }
html[data-theme="clair"] .barre__jus     { background: var(--ambre); }

/* Sur papier, le titre d'un tableau prend la meme valeur que la
   mention de droite : sur un aplat taupe, les deux se lisent en
   retrait plutot qu'en encre pleine. */
html[data-theme="clair"] .bloc__titre,
html[data-theme="clair"] .joueur__stats th { color: var(--bande-etiquette); }

/* LIRE LA SUITE prend un cerne. Le clip-path coupe une bordure,
   donc c'est le fond de la languette qui devient le trait, et un
   pseudo-élément biseauté d'un pixel de moins qui remplit
   l'intérieur — la méthode des étiquettes.
   Au survol, c'est le REMPLISSAGE qui fonce; le texte ne bouge
   pas. */
html[data-theme="clair"] .vedette .lire-suite {
  isolation: isolate;
  /* Le fond fait le trait — voir le pseudo-element plus bas. */
  background: var(--ambre);
  /* Un pixel plus bas et un pixel plus a droite : la languette
     vient s'asseoir SUR le filet de l'encadre au lieu de laisser
     une rainure. L'encadre coupe ce qui deborde, mais son filet
     est de la meme valeur que le cerne — la couture ne se voit
     donc pas. */
  right: -1px;
  bottom: -1px;
}
html[data-theme="clair"] .vedette .lire-suite::before {
  content: "";
  position: absolute;
  inset: 1px;
  z-index: -1;
  background: var(--bande-fond);
  clip-path: polygon(16px 0, 100% 0, 100% 100%, 0 100%, 0 16px);
  transition: background var(--glisse);
}
html[data-theme="clair"] .vedette .lire-suite:hover { color: var(--bande-valeur); }
html[data-theme="clair"] .vedette .lire-suite:hover::before { background: var(--ambre); }


/* ═══ 6. RUBAN DE STATUT ══════════════════════════════════════
   Le ticker que l'auteur avait dessiné pour YouTube sans jamais
   l'utiliser. Mauvais médium, bonne idée.

   L'ambre ne marque qu'UNE chose : la prochaine parution. C'est
   la seule information qui regarde vers l'avant, et c'est la
   promesse du site. Un point ambre se remarque; quatre font du
   bruit.                                                      */

.ruban {
  display: flex;
  overflow-x: auto;
  border-bottom: 1px solid var(--bande-bord);
  background: var(--bande-fond);
  font-family: var(--donnees);
  font-size: 0.75rem;
  scrollbar-width: none;
  /* Aligné sur le contenu, pas sur l'écran : sur un moniteur
     ultra-large, un ruban pleine largeur se détache du reste. */
  padding: 0 calc(var(--marge-laterale) - 0.9375rem);
}
.ruban::-webkit-scrollbar { display: none; }
.ruban__c {
  padding: 0.4375rem 0.9375rem;
  white-space: nowrap;
  color: var(--bande-etiquette);
  border-right: 1px solid var(--bande-bord);
}
.ruban__c b { color: var(--bande-valeur); font-weight: 500; }
.ruban__c--fin { margin-left: auto; border-right: 0; border-left: 1px solid var(--bande-bord); }


/* ═══ 7. GRILLE ═══════════════════════════════════════════════ */

.page { padding: 0 var(--marge-laterale) 2.25rem; }

/* « display: flex » ecrase la valeur par defaut de l'attribut
   « hidden » : sans cette ligne, un titre de saison qu'on demande
   de cacher reste affiche. */
.tete-section[hidden] { display: none; }
.tete-section {
  display: flex;
  align-items: baseline;
  gap: 0.75rem;
  padding: 1.375rem 0 0.4375rem;
  border-bottom: 1px solid var(--filet2);
}
/* Sur Le bilan, la tete de section garde la hauteur de son TITRE.
   Le bulletin, bien plus haut, en est sorti : pose en absolu, il
   deborde vers le haut sans rien pousser, et le tableau reste a
   sa place. */
.bilan__saison .tete-section { position: relative; }
/* Le « h3 » du Bilan porte le meme titre de saison que le « h2 »
   des rubriques : meme police, meme taille, meme valeur. */
.tete-section h2,
.tete-section h3 {
  font-family: var(--sans);
  font-size: 1.375rem;
  font-weight: 400;
  letter-spacing: 0;
  text-transform: uppercase;
  color: var(--section-titre);
  margin: 0;
  line-height: 1;
}
.tete-section .ref {
  margin-left: auto;
  font-family: var(--donnees);
  font-size: 0.75rem;
  color: var(--service);
}

.grille {
  display: flex;
  gap: var(--gouttiere);
  align-items: flex-start;
  margin-top: 2.625rem;
}
.grille__marge { width: var(--largeur-marge); flex-shrink: 0; position: sticky; top: 1.25rem; }

/* La marge reste ancrée à gauche; seule la colonne de texte se
   centre dans l'espace qui reste. Les marges automatiques d'un
   élément flexible absorbent le vide également des deux côtés. */
/* La colonne s'ancre desormais a gauche, contre la gouttiere,
   au lieu de se centrer dans l'espace restant : c'est ce qui la
   fait tomber sur le filet de la case de mesures. */
.grille__contenu {
  flex: 1;
  min-width: 0;
  max-width: var(--mesure);
  margin-inline: 0 auto;
}

.marge__b { border-left: 2px solid var(--filet2); padding-left: 0.75rem; margin-bottom: 1.0625rem; }
/* JetBrains Mono, comme les etiquettes du ruban en haut de page,
   dont elles reprennent aussi la valeur en mode sombre. */
.marge__e {
  font-family: var(--donnees);
  font-size: 0.75rem;
  font-weight: 400;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--faible);
  margin-bottom: 0.1875rem;
}
.marge__v {
  font-family: var(--donnees);
  font-size: 0.8125rem;
  /* Meme valeur que le gras du ruban en sombre, que le titre de
     l'article en clair : dans les deux cas, c'est --titre. */
  color: var(--titre);
  /* Une adresse courriel est un mot long : sans ça, elle déborde
     de la colonne. */
  overflow-wrap: anywhere;
  line-height: 1.5;
}
.marge__v--nom { font-family: var(--sans); font-size: 1.5rem; line-height: 1.15; color: var(--titre); }
/* « Chaque mardi » a la valeur du titre, « par courriel » a
   celle du chapeau : le rappel rejoue le rapport de l'en-tete. */
.marge__rappel {
  border-top: 1px solid var(--filet2);
  padding-top: 0.9375rem;
  font-family: var(--sans);
  font-size: 1.1875rem;
  line-height: 1.5;
  color: var(--titre);
}
.marge__rappel a { color: var(--ambre); }
.marge__rappel a:hover { text-decoration: underline; }

/* ⚠ LE PARTENAIRE (v71).

   Un logo carré sous « Chaque mardi par courriel » : 176 px ici, la
   largeur de la marge; 300 px au centre sur un téléphone (voir le
   bloc mobile). L'auteur fournit un carré de 600 px — net partout,
   même à double densité.

   ⚠ LE CADRE A SA TAILLE AVANT LE LOGO. C'est le navigateur qui pige
   le partenaire, donc l'image arrive un instant après la page. Le
   carré est réservé d'avance (« aspect-ratio ») : sur un téléphone,
   où il est AU-DESSUS du texte, rien ne saute quand le logo arrive.

   ⚠ DEUX VERSIONS, OU UNE SEULE SUR UNE CARTE PÂLE.
     — Le partenaire a un logo foncé : le mode sombre le montre, le
       mode clair montre le pâle. Le script pose les deux images;
       la feuille cache celle qui ne va pas. Celle qui est cachée
       ne se télécharge pas (« loading=lazy ») — sauf si le lecteur
       bascule le thème.
     — Il n'a que le pâle : en mode sombre, il est posé sur une
       carte pâle, sinon un logo noir disparaîtrait dans le fond.

   ⚠ LA COULEUR DE LA CARTE EST ÉCRITE ICI, ET C'EST VOULU. C'est
   le fond du mode CLAIR, mais en mode sombre « --fond » vaut autre
   chose : on ne peut pas le lire au moment où on en a besoin. Une
   seule copie, nommée — si la palette claire change, c'est ici. */
.partenaire {
  --partenaire-carte: #ECE8E4;
  border-top: 1px solid var(--filet2);
  padding-top: 0.9375rem;
  margin-top: 1.0625rem;
  /* Centré, à l'ordinateur comme sur un téléphone (v71, décision de
     l'auteur) : l'étiquette remercie, elle ne classe pas. */
  text-align: center;
}
/* Sans script, personne ne pige : le cadre resterait vide. */
html:not(.js) .partenaire { display: none; }

.partenaire__e { margin-bottom: 0.5rem; }

.partenaire__cadre {
  display: block;
  position: relative;
  width: 100%;
  aspect-ratio: 1 / 1;
  overflow: hidden;
  transition: filter .2s ease;
}
.partenaire__cadre:hover { filter: brightness(.9); }
.partenaire__cadre:focus-visible { outline: 2px solid var(--ambre); outline-offset: 3px; }

.partenaire__logo {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: contain;
}
.partenaire__logo--fonce { display: none; }
html[data-theme="fonce"] .partenaire__cadre--double .partenaire__logo--pale { display: none; }
html[data-theme="fonce"] .partenaire__cadre--double .partenaire__logo--fonce { display: block; }
html[data-theme="fonce"] .partenaire__cadre--carte { background: var(--partenaire-carte); }


/* ═══ 8. ENTRÉE ET ARTICLE ════════════════════════════════════ */

/* Le meme creux que l'encadre « Derniere publication » de
   l'accueil : --cadre-fond, plus fonce que la page en mode
   sombre, plus chaud qu'elle en mode clair. Les deux boites
   presentent la meme chose, elles doivent se ressembler. */
.entree {
  border: 1px solid var(--filet2);
  background: var(--cadre-fond);
  margin-top: 1.125rem;
}

.barre-meta {
  display: flex;
  align-items: center;
  gap: 0.6875rem;
  flex-wrap: wrap;
  min-height: 2.5rem;
  padding: 0.375rem 1rem;
  border-bottom: 1px solid var(--bande-bord);
  background: var(--bande-fond);
  font-family: var(--donnees);
  font-size: 0.75rem;
  color: var(--bande-etiquette);
}
.barre-meta .s { color: var(--bande-bord); }

/* Le bord droit du contenu tombe la ou finit la colonne de
   texte : la colonne demarre au quart et fait --mesure de large,
   donc il reste « 75% - --mesure ». Le retrait de gauche ne
   bouge pas — c'est le bord droit qu'on aligne. */
.entree__corps {
  padding: 1.875rem calc(75% - var(--mesure)) 1.625rem 1.625rem;
}
/* Dans l'article seulement, le chapeau perd son plafond en
   caracteres : c'est le retrait de la boite qui fixe la fin de
   ligne. Sur l'accueil, la vedette garde ses 64 caracteres —
   une amorce dans une boite de 30 rem n'a pas le meme travail
   a faire. */
.entree .chapeau { max-width: none; }

.titre-article {
  font-family: var(--affichage);
  font-weight: 500;
  font-size: var(--t-titre);
  line-height: 0.95;
  letter-spacing: 0;
  color: var(--titre);
  margin: 0 0 1rem;
  max-width: 17ch;
}

/* ⚠ ET LE TITRE NON PLUS, POUR EXACTEMENT LA MEME RAISON.

   Il trainait un plafond de dix-sept caracteres, herite de rien —
   « .titre-article » le porte pour tout le site. Dans cette boite,
   il cassait ses lignes bien avant le bord : « Ceci est un texte
   temporaire » passait sur deux lignes alors que la place etait
   la.

   Le bord droit est deja decide, et il l'est UNE FOIS : par le
   retrait de « .entree__corps », cale sur la fin de la colonne de
   lecture. Le titre et le chapeau finissent donc a la meme
   verticale, sans qu'aucun des deux ait a connaitre l'autre.

   ⚠ TROISIEME FOIS QUE CE VESTIGE SE PRESENTE.

   Le meme plafond a ete retire au chapeau de la vedette, puis au
   titre de la vedette, et le voici au titre de l'article. Chaque
   fois, une moitie avait ete faite et l'autre oubliee. La lecon
   pour la suite : quand on retire un plafond herite a un element,
   REGARDER SES VOISINS DANS LA MEME BOITE. */
.entree .titre-article { max-width: none; }

/* L'ambre, comme dans la vedette de l'accueil. Le chapeau se
   detache entre le titre et le corps au lieu de s'effacer. */
.chapeau {
  font-family: var(--lecture);
  font-size: var(--t-chapeau);
  line-height: 1.55;
  max-width: 64ch;
  color: var(--ambre);
  margin: 0;
  text-align: justify;
  /* ⚠ AUCUN MOT COUPÉ (v65, demande de l'auteur) : « nou-velle ». Le
     texte reste justifié; sur un téléphone, les espaces entre les mots
     s'élargissent un peu plus, c'est le prix. */
  hyphens: manual;
  -webkit-hyphens: manual;
}

.legende { font-family: var(--sans); font-size: 0.75rem; color: var(--attenue); margin: 0 0 0.5rem; }

/* — Le texte — */

/* ENFANT DIRECT, et c'est important.
   « .texte p » vaut une classe plus un type; « .cadrans__cat » ne
   vaut qu'une classe. Ecrite sans le chevron, cette regle gagnait
   sur les classes des blocs : les textes des blocs sortaient en
   serif justifie au lieu de leur propre fonte.
   Le corps du texte est toujours un enfant direct de la colonne;
   ce qui vit dans un bloc ne l'est jamais. */
.texte > p {
  font-family: var(--lecture);
  font-size: var(--t-corps);
  line-height: 1.78;
  /* Meme valeur que l'extrait de l'accueil : les deux presentent
     le meme texte, ils se lisent pareil. */
  color: var(--os);
  margin: 0 0 1.375rem;
  text-align: justify;
  /* ⚠ AUCUN MOT COUPÉ (v65) — voir « .chapeau ». « manual » plutôt que
     « none » : un trait d'union VOULU, tapé dans le mot (« porte-
     parole »), peut encore servir de point de coupe; aucun autre. */
  hyphens: manual;
  -webkit-hyphens: manual;
}
.texte > p.centre { text-align: center; }
.texte > p.gauche { text-align: left; }
.texte > p.legende { font-family: var(--sans); font-size: 0.75rem; color: var(--attenue); text-align: left; }

.texte strong { font-weight: 700; color: var(--titre); }
.texte em { font-style: italic; }

.texte a {
  color: var(--corps);
  text-decoration: underline;
  text-decoration-color: var(--ambre);
  text-underline-offset: 3px;
  text-decoration-thickness: 1px;
}
.texte a:hover { color: var(--titre); }

/* Sous-titre : filet horizontal, pas d'arc. Un arc qui décore
   dévalue les arcs qui mesurent. */
/* Meme famille que le titre — c'etait deja Teko — mais aussi
   meme graisse et meme interlettrage. C'est la ou l'ecart se
   voyait : 600 contre 500, et un pas de plus. */
.texte h2 {
  font-family: var(--affichage);
  font-weight: 500;
  font-size: calc(var(--t-section) * 1.2);
  letter-spacing: 0;
  line-height: 1.15;
  color: var(--titre);
  margin: 2.5rem 0 0.9375rem;
  padding-top: 0.875rem;
  border-top: 1px solid var(--filet2);
}

.texte ul, .texte ol {
  font-family: var(--lecture);
  font-size: var(--t-corps);
  line-height: 1.78;
  color: var(--corps);
  padding-left: 1.5rem;
  margin: 0 0 1.375rem;
}
.texte li { margin-bottom: 0.4375rem; }

/* — LA VIDEO ————————————————————————————————————————
   ⚠ RIEN NE PART CHEZ GOOGLE TANT QU'ON N'A PAS CLIQUE.

   Ce qu'on voit ici est une VIGNETTE : une image et un bouton. Le
   vrai lecteur ne se charge qu'au premier clic — voir le script
   de « base.html ». Le site reste donc sans temoins, ce qui lui
   evite la banniere de consentement et les obligations de la loi
   25.

   Le rapport 16/9 est pose sur le cadre plutot que sur l'image :
   la vignette de YouTube arrive en 4/3 avec des bandes noires, et
   « object-fit: cover » les fait disparaitre. */
.video { margin: 2rem 0; }

.video__vue {
  position: relative;
  display: block;
  aspect-ratio: 16 / 9;
  overflow: hidden;
  background: #000;
  /* Le meme filet que les tableaux et les images du corps. Une
     video et une photo sont deux illustrations : elles se posent
     de la meme facon. */
  border: 1px solid var(--filet2);
}

.video__vue img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

/* Le triangle de lecture. Dessine en CSS : une image de plus
   serait une requete de plus pour un triangle. */
.video__jouer {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: 4.5rem;
  height: 3.125rem;
  background: rgba(0, 0, 0, 0.72);
  border: 1px solid var(--ambre);
  transition: background var(--glisse);
}

.video__jouer::after {
  content: "";
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-40%, -50%);
  border-left: 1.0625rem solid var(--os);
  border-top: 0.625rem solid transparent;
  border-bottom: 0.625rem solid transparent;
}

.video__vue:hover .video__jouer { background: var(--ambre); }
.video__vue:hover .video__jouer::after { border-left-color: var(--fond); }

/* ⚠ ET LE LECTEUR GARDE LE FILET.

   Il remplace la vignette au clic. Sans cette regle, le cadre
   disparaissait au moment ou l'on commence a regarder — la video
   sautait d'un pixel et perdait sa bordure. */
.video iframe {
  width: 100%;
  aspect-ratio: 16 / 9;
  border: 1px solid var(--filet2);
  display: block;
}


/* ⚠ UNE IMAGE DU CORPS NE DEBORDE PAS, ET NE S'ETIRE PAS.

   La regle ne portait qu'une marge : une photo plus large que la
   colonne la debordait, et une photo plus etroite — un portrait
   recadre — se collait a gauche en laissant un trou a droite.

   « max-width » borne la premiere. « margin: 0 auto » centre la
   seconde. Et « height: auto » garde les proportions quand la
   largeur est bornee : sans lui, l'image s'ecrase.

   ⚠ L'image est un bloc. Sans ca, le navigateur la traite comme
   du texte et lui ajoute la place d'un jambage sous la ligne —
   un espace de quatre pixels sous la photo, que personne ne
   trouve jamais. */
.figure { margin: 2rem 0; }

.figure img {
  display: block;
  max-width: 100%;
  height: auto;
  margin: 0 auto;
  /* Le meme filet que les tableaux. Une photo posee sans bordure
     flotte dans la colonne; le filet la POSE, comme il pose un
     bloc de donnees. */
  border: 1px solid var(--filet2);
}


/* ⚠ LA LEGENDE A GAUCHE, LA SOURCE A DROITE.

   Elles etaient centrees toutes les deux. Le centrage allait tant
   qu'il n'y avait qu'une legende; des qu'une source s'ajoute, deux
   textes centres l'un a cote de l'autre ne se lisent plus comme
   deux informations, mais comme une phrase coupee.

   C'est le meme dessin que le PIED D'UN BLOC : la source a droite,
   en JetBrains Mono, en petites capitales. Une figure n'avait
   aucune raison d'inventer sa propre facon d'attribuer.

   Le leger retrait cale la legende sur le bord de l'image plutot
   que de la coller au filet. Et la marge du haut perd deux pixels :
   la ligne se rapproche de ce qu'elle decrit. */
.figure figcaption,
.video figcaption {
  /* ⚠ IL N'Y A PLUS QUE LA SOURCE.

     Une figure a porté une légende à gauche et une source à
     droite. Trois dessins ont été essayés — deux textes nus, un
     pied pleine largeur, un onglet biseauté — et aucun ne tenait :
     deux informations de natures différentes sur une même ligne se
     lisaient toujours comme une phrase coupée.

     Une photo dans un texte n'a pas besoin qu'on la décrive, le
     texte le fait déjà. Elle a besoin d'être attribuée.

     ⚠ ELLE REVIENT À JETBRAINS MONO. C'est la fonte des données et
     des mentions de service — celle du pied des blocs, où « SOURCE ·
     NHL.COM » s'écrit déjà. Une attribution n'est pas de la lecture.

     La casse est posée ici, pas dans le générateur : une seule
     source de vérité, la même que le pied des blocs. */
  display: block;
  text-align: right;
  padding-right: var(--figure-retrait);
  margin-top: var(--figure-air);
  font-family: var(--donnees);
  font-size: 0.59375rem;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--service);
}

/* La légende cède la place : c'est elle qui passe sur deux lignes
   si besoin, jamais la source. *

/* ⚠ L'ONGLET, ET SON BISEAU.

   Le biseau coupe le coin HAUT-GAUCHE : l'onglet paraît glissé
   sous la bande depuis la droite, comme une languette.

   ⚠ AUCUNE BORDURE ICI — c'est le piège nº 13, rencontré quatre
   fois dans ce projet. « clip-path » coupe une bordure au lieu de
   la suivre : elle disparaîtrait le long de la diagonale. C'est le
   FOND qui dessine l'onglet, et « --voile » est fait pour ça — il
   éclaircit sur charbon et assombrit sur papier, donc il se lit
   dans les deux thèmes sans qu'on ait à l'écrire deux fois.

   ⚠ Et le rembourrage de gauche RATTRAPE la coupe : sans lui, le
   « S » de SOURCE viendrait s'asseoir sur la diagonale. *

/* La legende cede la place : c'est elle qui passe sur deux lignes
   si besoin, jamais la source. *

/* ⚠ « margin-left: auto » PLUTOT QUE « space-between ».
   Une source SANS legende doit rester a droite quand meme — avec
   « space-between », elle se serait collee a gauche, seule dans sa
   rangee. *

/* Un fond derriere la citation pour que la barre se decoupe au
   lieu de flotter dans la colonne. Meme creux que l'encadre
   d'entete de l'article. La barre reste en --ambre : elle valait
   deja #877B66 en sombre et #595143 en clair. */
.exergue {
  margin: 2rem 0;
  padding: 1rem 1.3125rem;
  border-left: 3px solid var(--ambre);
  background: var(--cadre-fond);
}
.exergue p {
  font-family: var(--lecture);
  font-style: italic;
  font-size: var(--t-exergue);
  line-height: 1.42;
  /* Meme valeur que le chapeau de l'article. */
  color: var(--ambre);
  margin: 0;
  text-align: left;
}

/* Meme chevron, meme raison : sans lui, cette regle posait 2 rem
   de marge sur les tableaux des blocs, qui ont pourtant deja leur
   cadre. C'etait la bande vide au-dessus de « JOUEUR » et de
   « SAISON », et le financier remontait d'une taille. */
.texte > table { width: 100%; border-collapse: collapse; margin: 2rem 0; font-family: var(--donnees); font-size: 0.78125rem; }
.texte th {
  font-family: var(--etiquette);
  font-size: 0.65625rem;
  font-weight: 700;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--faible);
  text-align: left;
  padding: 0.5625rem 0.75rem 0.5625rem 0;
  border-bottom: 1px solid var(--ambre);
}
.texte td { padding: 0.5625rem 0.75rem 0.5625rem 0; border-bottom: 1px solid var(--filet); color: var(--corps); }

/* ⚠ « .commandite » A ÉTÉ RETIRÉE (v71) : jamais servie, remplacée
   par le PARTENAIRE de la marge — voir « .partenaire ». */

/* ⚠ LA SUITE — DEUX CARTES SOUS LA CHRONIQUE (v69).

   Photo, titre, et une etiquette qui dit POURQUOI la carte est la :
   « À lire aussi », « Aussi sur MTL », « Aussi dans La Ligue ».
   Pas de chapeau (decision de l'auteur) : trop de texte a lire pour
   quelqu'un qui vient de finir.

   Le filet du haut est celui des intertitres du corps : la suite
   se lit comme une derniere section du texte, pas comme un bloc
   rapporte.

   ⚠ LE BISEAU DE LA PHOTO SUIT LA RECETTE DE R10. « clip-path »
   coupe la bordure : c'est donc le FOND de la boite qui fait le
   trait, et l'image, biseautee de 0,586 px de moins (2 - √2), le
   laisse paraitre d'un pixel vrai jusque dans la diagonale. */
.suite {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: 1.5rem;
  margin-top: 3rem;
  padding-top: 1.25rem;
  border-top: 1px solid var(--filet2);
}
/* ⚠ « .texte .suite__carte », PAS « .suite__carte » SEUL.
   La suite vit dans la colonne du texte, et « .texte a » (classe +
   type) bat une classe seule (R8.5) : sans ca, les titres sortaient
   soulignes d'ambre, comme un lien du corps. */
.texte .suite__carte { display: flex; flex-direction: column; color: var(--titre); text-decoration: none; }
.texte .suite__carte:hover { color: var(--titre); }
/* Meme voix que les etiquettes de la marge — PAR, PUBLIÉ, LECTURE —
   mais en ambre : c'est la ponctuation qui invite. */
.suite__e {
  font-family: var(--donnees);
  font-size: 0.75rem;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--ambre);
  margin-bottom: 0.5rem;
}
.suite__photo {
  display: block;
  padding: 1px;
  background: var(--filet2);
  clip-path: polygon(
    0 0, calc(100% - var(--biseau-large)) 0, 100% var(--biseau-large),
    100% 100%, var(--biseau-large) 100%, 0 calc(100% - var(--biseau-large)));
}
/* Le format de la vedette (1,747) : c'est pour lui que la photo a
   ete cadree. */
.suite__photo img {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 891 / 510;
  object-fit: cover;
  clip-path: polygon(
    0 0, calc(100% - var(--biseau-large) + 0.586px) 0, 100% calc(var(--biseau-large) - 0.586px),
    100% 100%, calc(var(--biseau-large) - 0.586px) 100%, 0 calc(100% - var(--biseau-large) + 0.586px));
  transition: filter var(--glisse);
}
/* La coupure se fait au nombre de lignes, jamais a la hauteur
   (R12.7). Deux lignes : un titre plus long garde sa fin. */
.suite__t {
  font-family: var(--affichage);
  font-weight: 500;
  font-size: 1.625rem;
  line-height: 1.1;
  color: var(--titre);
  margin-top: 0.75rem;
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
  line-clamp: 2;
  overflow: hidden;
}
/* Un survol ASSOMBRIT (R12.3) — la photo, pas le titre. */
.suite__carte:hover .suite__photo img,
.suite__carte:focus-visible .suite__photo img { filter: brightness(0.82); }
.texte .suite__carte:focus-visible { outline: 2px solid var(--ambre); outline-offset: 4px; }


/* ═══ 9. BLOCS DE DONNÉES ═════════════════════════════════════
   Tirés des archives graphiques de l'auteur. Ses tableaux
   n'étaient pas des illustrations : chacun ÉTAIT un argument.

   Chaque bloc porte sa source et l'adresse du site — ils sont
   faits pour être capturés et collés dans un fil de discussion.
   C'est le modèle JFresh.                                     */

/* Le corps du tableau prend le meme creux que l'encadre d'entete
   de l'article. Les deux etaient a deux profondeurs differentes
   dans la meme colonne; ils n'en font plus qu'une. Le bandeau et
   le pied ont leur propre fond, donc celui-ci ne se voit qu'entre
   les deux. */
/* Deux coins coupes : en haut a droite, en bas a gauche.
   « clip-path » coupe une bordure, donc on reprend la methode du
   panneau du fil : le FOND de la boite fait le trait, un pixel de
   rembourrage rentre les enfants, et un pseudo-element biseaute
   d'un pixel de moins remplit l'interieur. Le bandeau et le pied
   portent chacun leur propre coin. */
.bloc {
  position: relative;
  isolation: isolate;
  border: 0;
  padding: 1px;
  background: var(--filet2);
  margin: 2rem 0;
  clip-path: polygon(0 0, calc(100% - 18px) 0, 100% 18px,
                     100% 100%, 18px 100%, 0 calc(100% - 18px));
}
.bloc::before {
  content: "";
  position: absolute;
  inset: 1px;
  z-index: -1;
  background: var(--cadre-fond);
  clip-path: polygon(0 0, calc(100% - 17px) 0, 100% 17px,
                     100% 100%, 17px 100%, 0 calc(100% - 17px));
}

/* Le bandeau d'un tableau est de la meme famille que la barre
   d'entete de l'article : meme fond, meme filet. Les deux coiffent
   des donnees, ils doivent se lire comme le meme objet. */
/* Bandeau et pied : meme hauteur imposee, contenu centre
   verticalement plutot qu'aligne sur la ligne de base — les deux
   textes n'ont pas la meme taille, donc la ligne de base les
   decalait l'un par rapport a l'autre. */
.bloc__tete {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 0.75rem;
  min-height: 2.25rem;
  /* Un pixel de plus en haut, un de moins en bas : le contenu
     descend d'un pixel et la boite ne change pas de hauteur.

     Mesure a l'image : le texte etait a 13 px du filet du haut et
     a 15 du filet du bas. Le decalage vaut ce pixel-la.

     Pose sur la TETE et non sur les textes : les deux — le titre en
     Chakra Petch et la reference en JetBrains Mono — descendent
     ensemble et restent alignes entre eux. Un correctif par texte
     les aurait desolidarises. */
  padding: calc(0.25rem + 1px) 0.9375rem calc(0.25rem - 1px);
  border-bottom: 1px solid var(--bande-bord);
  background: var(--bande-fond);
  clip-path: polygon(0 0, calc(100% - 17px) 0, 100% 17px, 100% 100%, 0 100%);
}
.bloc__titre {
  font-family: var(--etiquette);
  font-size: 0.78125rem;
  font-weight: 700;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--titre);
}
/* Le titre prend ce qui reste, la reference ne se casse jamais.
   Sans ca, « · 2025-26 » se coupait en « 2025- / 26 ». */
.bloc__titre {
  flex: 1;
  min-width: 0;
  /* PAS de correctif optique ici — les metriques de la police ont
     ete mesurees, et elles disent que l'encre est deja centree a un
     dixieme de pixel pres :

       hauteur de capitale  700 / 1000
       montee 992 · descente 308
       centre de la boite  +342   centre de l'encre  +350

     Un rembourrage de 0,12 em avait ete pose ici; il descendait le
     texte de 1,6 px sans raison. Si le titre parait encore mal
     cale, la cause est ailleurs que dans la police. */
}
/* Meme valeur que les etiquettes du ruban et de la barre
   d'article. La taille, elle, ne bouge pas. En capitales : c'est
   une etiquette, quoi que l'auteur ait tape dans le markdown. */
.bloc__ref { flex-shrink: 0; white-space: nowrap; text-transform: uppercase; font-family: var(--donnees); font-size: 0.59375rem; color: var(--bande-etiquette); }
/* Aucun decalage ici : mesure sur la hauteur de capitale, les
   quatre textes des bandeaux et des pieds tombent deja au meme
   endroit, a un demi-pixel du milieu. Un correctif pose plus tot
   sur une mesure d'encre faussee par les jambages les poussait
   1,4 px trop bas — il est retire. */
/* Le pied est le meme objet que le bandeau, en bas plutot qu'en
   haut : meme fond, meme filet, meme valeur de texte. */
.bloc__pied {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 0.625rem;
  min-height: 2.25rem;
  padding: 0.25rem 0.9375rem;
  border-top: 1px solid var(--bande-bord);
  background: var(--bande-fond);
  font-family: var(--donnees);
  font-size: 0.59375rem;
  text-transform: uppercase;
  color: var(--bande-etiquette);
  clip-path: polygon(0 0, 100% 0, 100% 100%, 17px 100%, 0 calc(100% - 17px));
}

/* — Fiche de joueur — */

/* Le nom et sa ligne d'informations a gauche, l'etiquette
   d'equipe a droite. Les retraits valent ceux du bandeau du
   dessus (0,9375 rem), donc le nom tombe sous « FICHE DE JOUEUR »
   et l'etiquette sous « MISE A JOUR ». */
.joueur__tete {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.875rem;
  padding: 0.875rem 0.9375rem;
}
.joueur__id { display: flex; flex-direction: column; gap: 0.3125rem; min-width: 0; }

/* ── LA PHOTO D'UNE FICHE (v64) ─────────────────────────────
   A gauche du nom, et la MEME taille que le jeton d'equipe a
   droite : la tete est tenue par deux carres assortis.

   ⚠ LES BISEAUX SONT INVERSES : haut-gauche et bas-droite, quand
   le jeton les porte en haut-droite et bas-gauche. Decision de
   l'auteur — les deux carres se repondent en miroir.

   ⚠ LE CADRAGE VIT DANS DEUX VARIABLES, posees par le generateur :
   « --z » grossit, « --y » dit a quelle hauteur. Le point « --y »
   reste immobile quand on zoome — c'est le visage qu'on garde en
   place, pas le centre de l'image. */
.joueur__photo {
  flex-shrink: 0;
  display: block;
  width: 3.5rem;
  height: 3.5rem;
  padding: 1px;
  line-height: 0;
  background: var(--jeton-filet);
  clip-path: polygon(11px 0, 100% 0, 100% calc(100% - 11px),
                     calc(100% - 11px) 100%, 0 100%, 0 11px);
}
.joueur__cadre {
  display: block;
  width: 100%;
  height: 100%;
  overflow: hidden;
  /* Une trace de l'equipe derriere une photo detouree : sans elle,
     le portrait flotterait sur le degrade de la tete. */
  background: color-mix(in srgb, var(--eqt, var(--eqf, #888)) 16%, transparent);
  clip-path: polygon(10.414px 0, 100% 0, 100% calc(100% - 10.414px),
                     calc(100% - 10.414px) 100%, 0 100%, 0 10.414px);
}
.joueur__cadre img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: 50% var(--y, 22%);
  transform: scale(var(--z, 1.35));
  transform-origin: 50% var(--y, 22%);
}
/* ⚠ LE NOM COLLE A LA PHOTO. La tete range ses enfants en
   « space-between » : avec trois enfants, le nom partait au
   milieu. La marge automatique lui donne tout l'espace libre, a
   droite — la photo et le nom restent ensemble, le jeton au bout. */
.joueur__photo + .joueur__id { margin-right: auto; }

/* ⚠ UNE FOIS ET DEMIE PLUS GRANDS, SUR GRAND ÉCRAN SEULEMENT (v64).
   Demande de l'auteur après avoir vu la première photo : 56 px
   faisaient un timbre. La photo ET le jeton grandissent ensemble —
   les deux carrés doivent rester assortis.

   ⚠ LE JETON GRANDIT DANS LA FICHE, PAS AILLEURS. « .code--jeton »
   sert aussi au registre, où sa hauteur est comptée au pixel près
   (piège de la demande 52) : la règle passe par « .joueur__tete ».

   ⚠ LES BISEAUX SUIVENT : 11 px sur 84 auraient l'air d'un coin
   arrondi, c'est justement ce que 11 corrigeait à 56. Sous
   1000 px, tout reste comme avant — la photo y disparaît. */
/* ⚠ UN FILET NOIR DE 1 PX, DANS LES DEUX THÈMES (v64).
   Le jeton porte « --jeton-filet », qui vaut TRANSPARENT sur
   charbon — un choix voulu pour le registre, où le filet se
   confondait avec le fond. Dans la tête d'une fiche, l'auteur le
   veut visible : les deux carrés biseautés se découpent sur le
   dégradé de l'équipe. Ailleurs sur le site, rien ne change. */
.joueur__tete .code--jeton,
.joueur__photo { background: #000; }

/* ⚠⚠ « UN PIXEL DE MOINS » NE DONNE PAS UN PIXEL SUR LA DIAGONALE
   (piège nº 384).

   La recette du piège nº 13 est juste — le FOND fait le trait, un
   rembourrage de 1 px le laisse voir, l'intérieur est biseauté
   d'un peu moins. Mais « un peu moins » n'est pas « 1 px de
   moins ». L'intérieur commence 1 px plus loin sur les DEUX axes :
   avec un biseau réduit d'un pixel, la diagonale intérieure tombe
   à 1/√2 = 0,7 px de l'extérieure. Un trait de 0,7 px s'adoucit à
   l'affichage jusqu'à disparaître — c'est ce que l'auteur voyait :
   un contour partout, sauf dans les coins.

   Pour 1 px vrai, le biseau intérieur vaut l'extérieur MOINS
   2 − √2 = 0,586 px. D'où les « .414 » : 11 → 10,414, 16 → 15,414.

   ⚠ Tout le site porte la même recette, avec le même 0,7 px. On ne
   corrige ici que la tête des fiches — demande de l'auteur. */
/* ⚠⚠ ET LA COULEUR D'ÉQUIPE SE GLISSAIT DANS LE TRAIT (piège nº 385).
   Le jeton hérite de « .code », et « .code::before » peint la
   couleur de l'équipe un pixel à l'intérieur, avec un biseau de
   5 px — la recette de l'étiquette de texte. Sous un logo, elle ne
   se voit pas… sauf dans la fente de la diagonale, qu'elle
   remplissait : rouge sur la pastille du Canadien, bleu sur celle
   des Jets. Le trait noir y était, recouvert. Un jeton n'a pas de
   texte à colorer : la couche s'éteint. Vu en faisant rendre la
   tête par un vrai navigateur, grossie huit fois. */
.joueur__tete .code--jeton::before { content: none; }

.joueur__tete .code--jeton img {
  clip-path: polygon(0 0, calc(100% - 10.414px) 0, 100% 10.414px,
                     100% 100%, 10.414px 100%, 0 calc(100% - 10.414px));
}

@media (min-width: 1001px) {
  .joueur__tete .code--jeton,
  .joueur__photo { width: 5.25rem; height: 5.25rem; }

  .joueur__tete .code--jeton {
    clip-path: polygon(0 0, calc(100% - 16px) 0, 100% 16px,
                       100% 100%, 16px 100%, 0 calc(100% - 16px));
  }
  .joueur__tete .code--jeton img {
    clip-path: polygon(0 0, calc(100% - 15.414px) 0, 100% 15.414px,
                       100% 100%, 15.414px 100%, 0 calc(100% - 15.414px));
  }
  .joueur__photo {
    clip-path: polygon(16px 0, 100% 0, 100% calc(100% - 16px),
                       calc(100% - 16px) 100%, 0 100%, 0 16px);
  }
  .joueur__cadre {
    clip-path: polygon(15.414px 0, 100% 0, 100% calc(100% - 15.414px),
                       calc(100% - 15.414px) 100%, 0 100%, 0 15.414px);
  }
}
.joueur__nom { font-family: var(--sans); font-weight: 500; font-size: 1.625rem; letter-spacing: .01em; line-height: 1; color: var(--titre); }
/* La police des etiquettes, comme le titre du bandeau. */
.joueur__pos {
  font-family: var(--etiquette);
  font-size: 0.65625rem;
  font-weight: 600;
  letter-spacing: .12em;
  line-height: 1;
  color: var(--attenue);
}

/* « table-layout: fixed » : sans lui, chaque colonne se cale sur
   son contenu et « MIN/PJ » finit deux fois plus large que « B ».
   Les largeurs viennent d'un <colgroup> ecrit par le generateur —
   voir « colonnes_stats ». */
.joueur__stats {
  width: 100%;
  table-layout: fixed;
  border-collapse: collapse;
  font-family: var(--donnees);
  font-size: 0.78125rem;
}

/* La ligne de titres reprend le bandeau du tableau : meme fond,
   meme valeur de texte. Cales a droite comme les chiffres, avec
   le meme retrait a droite — les deux tombent donc exactement
   l'un sous l'autre. */
.joueur__stats th {
  font-family: var(--etiquette);
  font-size: 0.65625rem;
  font-weight: 700;
  letter-spacing: .12em;
  color: var(--titre);
  text-align: center;
  padding: 0.5rem 0.5rem;
  background: var(--bande-fond);
  border-top: 1px solid var(--filet);
  border-bottom: 1px solid var(--filet);
}
.joueur__stats th:first-child { text-align: left; padding-left: 0.9375rem; }
/* Chiffres centres sous leur titre, avec les memes retraits que
   lui — un centre ne tombe au milieu que si les deux marges sont
   egales. Ils prennent l'encre pleine : c'est la donnee, elle ne
   doit pas reculer. */
.joueur__stats td { text-align: center; font-weight: 400; padding: 0.5625rem 0.5rem; color: var(--titre); border-bottom: 1px solid var(--filet); }
/* La ligne de titres n'a que des « th », elle n'est donc jamais
   touchee par le survol. */
.joueur__stats tr:hover td { background: var(--voile); }
/* La saison et « Carriere » sont des reperes, pas des donnees :
   meme valeur que la ligne d'informations sous le nom du joueur.
   En capitales, comme toutes les etiquettes du site. */
.joueur__stats td:first-child {
  text-align: left;
  text-transform: uppercase;
  padding-left: 0.9375rem;
  font-family: var(--etiquette);
  font-weight: 600;
  letter-spacing: .1em;
  color: var(--attenue);
}

/* La note d'enjeu : ce n'est pas une donnée, c'est un enjeu.
   La fiche pose la question sans la poser.

   Meme police que le nom du joueur, en plus petit et plus leger —
   la note commente la fiche, elle ne la titre pas. Une seule
   valeur pour tout le texte, mise en evidence comprise. */
.joueur__note {
  padding: 0.9375rem;
  border-top: 1px solid var(--filet);
  font-family: var(--sans);
  font-size: 1.25rem;
  font-weight: 400;
  line-height: 1.3;
  text-align: center;
  color: var(--titre);
}
/* La note se lit d'une seule voix : ni couleur ni graisse ne
   distinguent la mise en evidence du markdown. Le « b » reste
   dans le HTML — il porte encore le sens — mais ne se voit plus. */
.joueur__note b { color: inherit; font-weight: inherit; }

/* La courbe sur cinq ans : ce qui distingue le plus. Cinq paires
   de nombres tracées en SVG — rien à fabriquer. */
.courbe { padding: 0.875rem 0.5rem 0.25rem; }
/* Le SVG porte height="180" en attribut pendant que sa largeur
   suit la colonne. Sans ceci, le dessin retrecit mais pas la
   boite : 82 px de vide au milieu de la fiche. */
.courbe svg { height: auto; display: block; }
.courbe .axe       { stroke: var(--filet); }
/* Le halo : la meme couleur que le trait, diluee et etalee. Pose
   par « drop-shadow » et non par une ombre de boite, pour qu'il
   suive la forme du trace et non son cadre. */
.courbe .ligne-pts { stroke: var(--courbe-pts); fill: none; stroke-width: 2.5;
                     filter: drop-shadow(0 0 3px var(--courbe-pts-lueur)); }
.courbe .ligne-b   { stroke: var(--courbe-b);   fill: none; stroke-width: 2.5;
                     filter: drop-shadow(0 0 3px var(--courbe-b-lueur)); }
.courbe .val-pts   { fill: var(--courbe-pts); }
.courbe .val-b     { fill: var(--courbe-b); }
/* Les annees de l'axe reprennent exactement la premiere colonne
   du tableau au-dessus. Attention : dans un SVG, une taille est
   en unites de dessin, mises a l'echelle avec la boite. Le
   rapport est ici de 1,375, donc 9,66 unites rendent a 13,28 px —
   la taille du tableau. Le CSS l'emporte sur l'attribut
   « font-size » pose par le generateur. */
.courbe .saison    { fill: var(--attenue); font-size: 9.66px; letter-spacing: 0.97px; }

.legende-courbe {
  display: flex;
  gap: 1.125rem;
  justify-content: center;
  /* Un peu d'air entre les annees de l'axe et la legende : sans
     lui, les deux lignes se lisaient comme une seule. */
  padding: 0.625rem 0 0.75rem;
  font-family: var(--etiquette);
  font-size: 0.65625rem;
  font-weight: 600;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--faible);
}
.legende-courbe i { display: inline-block; width: 9px; height: 9px; margin-right: 0.375rem; }

/* — Tableau financier — */

/* Meme taille que les chiffres de la fiche de joueur. */
.financier { width: 100%; border-collapse: collapse; font-family: var(--donnees); font-size: 0.78125rem; }
/* Pas de fond ici, contrairement a la fiche de joueur : le
   bandeau du bloc est juste au-dessus, et deux aplats de la meme
   valeur colles l'un sur l'autre se lisent comme un seul.
   L'ambre suffit a detacher la ligne. */
.financier th {
  font-family: var(--etiquette);
  font-size: 0.65625rem;
  font-weight: 700;
  letter-spacing: .12em;
  color: var(--ambre);
  text-align: right;
  padding: 0.5625rem 0.75rem;
  border-bottom: 1px solid var(--filet2);
}
.financier th:first-child { text-align: left; }
/* ⚠ PLUS DE FILET SOUS LES TITRES DE COLONNES (v65, demande de
   l'auteur). Leur couleur ambre les détache déjà; le filet enlevait de
   l'importance au SEUL qui compte — celui de la dernière place
   qualificative, dans un classement. Il reste, mais transparent : la
   rangée garde sa hauteur au pixel. Vaut pour les contrats ET le
   classement, qui emprunte la même table. */
.financier th { border-bottom-color: transparent; }
/* Interligne fixe et rembourrage recalcule pour que les rangees
   fassent exactement la hauteur de la ligne de titres. Sans
   « line-height: 1 », le nom en Teko traine 8 px d'interligne
   naturel et la rangee gonflait de 9,5 px. */
/* Noms et montants a l'encre pleine — c'est la donnee. La ligne
   de somme garde son ambre, plus bas.

   Pas de filet entre les joueurs : le bloc de noms se lit d'un
   seul tenant. Le filet ne subsiste qu'a deux endroits — sous la
   ligne de titres, porte par le « th », et sous la derniere
   rangee avant le total, ci-dessous. Ailleurs il reste, mais
   transparent, pour que toutes les rangees gardent la meme
   hauteur. */
.financier td { padding: 0.428rem 0.75rem; text-align: right; font-weight: 400; line-height: 1; color: var(--titre); border-bottom: 1px solid transparent; }
.financier tr:has(+ tr.total) td { border-bottom: 1px solid var(--filet); }
/* Teko et JetBrains Mono n'ont pas la meme hauteur de capitale a
   ces tailles-la — 12 px contre 10 — donc leurs centres optiques
   ne tombaient pas au meme endroit meme avec les pieds alignes.
   Chaque cellule est recalee sur le milieu de la rangee.

   Le decalage passe par le rembourrage, pas par « position:
   relative ». Avec « relative », c'est la BOITE qui descend, donc
   son fond de survol se decalait par rapport aux cellules
   voisines et laissait une coche a la jointure. Ce qu'on ajoute
   en haut, on le retire en bas : le texte bouge, la boite non. */
.financier td:first-child {
  padding-top: calc(0.428rem + 0.077em);
  padding-bottom: calc(0.428rem - 0.077em);
}
.financier td:not(:first-child) {
  padding-top: calc(0.428rem + 0.015em);
  padding-bottom: calc(0.428rem - 0.015em);
}
/* Exactement les reglages des noms du bloc de barres : meme
   fonte, meme taille, meme graisse, meme valeur. Un joueur doit
   s'ecrire pareil d'un bloc a l'autre. */
.financier td:first-child { text-align: left; font-family: var(--sans); font-weight: 400; font-size: 1.0625rem; color: var(--titre); }
/* La ligne de somme reprend la valeur des titres de colonnes :
   les deux encadrent les donnees sans en etre. Son filet devient
   transparent plutot que nul : sinon la rangee perd un pixel de
   hauteur et son contenu se recale ailleurs que celui des
   autres. */
.financier tr.total td { border-bottom: 1px solid transparent; color: var(--ambre); font-weight: 700; }
/* Le mot allege : entre les noms au-dessus (400) et les montants
   de la meme rangee (700). Il se distingue sans peser. */
.financier tr.total td:first-child { text-transform: uppercase; font-weight: 500; color: var(--ambre); }
/* Meme voile que les rangees de la fiche de joueur. La ligne de
   titres n'a que des « th », elle reste donc intacte; la ligne de
   somme est exclue explicitement — ce n'est pas une donnee. */
.financier tr:not(.total):hover td { background: var(--voile); }

/* ── L'ÉQUIPE, L'ÉCHÉANCE ET LE STATUT (v65) ─────────────────
   ⚠ LE LOGO DE LA LNH, PAS LA PASTILLE BISEAUTÉE : à 20 px, le
   biseau se lit mal (demande de l'auteur). Deux versions, foncée et
   pâle, et la feuille montre celle du thème. */
/* ⚠ UNE BOÎTE QUI CENTRE, PAS « vertical-align » (v65). Le logo,
   le nom en Teko et une pastille en Chakra Petch n'ont pas la même
   hauteur de capitale : alignés sur la ligne de base, ils tombaient
   chacun à sa hauteur. Une boîte flexible les centre l'un sur
   l'autre, quelle que soit la police. */
.financier__joueur,
.financier__echeance {
  display: inline-flex;
  align-items: center;
  vertical-align: middle;
}
.financier__echeance { gap: 0.4375rem; }
/* ⚠ LES MESURES DU CLASSEMENT DE L'ATELIER, AU PIXEL (demande de
   l'auteur, v65) : « .rec__cla-logo » — 22 × 22 px, 10 px avant le
   nom, remonté de 2 px, « contain ». Trois essais en rem (20, 26,
   32) ne rendaient pas comme lui. En PIXELS, pas en rem : 1 rem vaut
   ici 17 px, et « 2rem » tombait sur 34 — une taille qui n'est pas
   celle que la LNH a dessinée, redessinée entre deux grilles. */
.financier__eq {
  display: inline-flex;
  flex: none;
  width: 22px;
  height: 22px;
  margin-right: 10px;
  line-height: 0;
}
/* La boîte du joueur a la hauteur d'une ligne : le logo en déborde
   sans pousser la rangée. */
.financier__joueur { height: 1.0625rem; }
/* ⚠ MESURÉ AU PIXEL, AVEC LES VRAIES POLICES (v65) : la boîte centre
   le logo sur la boîte du nom, mais la capitale de Teko se tient plus
   haut que le milieu de sa boîte — le logo tombait 1,75 px sous le
   nom et les montants. Il remonte d'autant. */
.financier__eq { position: relative; top: -2px; }
/* ⚠ LA PASTILLE : 24 px, carrée, sans biseau (trop petit pour
   valoir la peine — décision de l'auteur, v65), un filet noir de
   1 px, et remontée de 2 px comme le logo : centrée sur sa boîte,
   elle tombait sous la capitale de Teko, qui se tient haut.
   Le filet est une ombre sans flou : elle ne prend aucune place, et
   la pastille garde exactement ses 24 px. */
.financier__eq--pastille { width: 24px; height: 24px; top: -2px; }
.financier__eq--pastille img { box-shadow: 0 0 0 1px #000; }
/* ⚠⚠ UN DÉCALAGE EN PIXELS ENTIERS, PAS UN « transform » (piège nº 394).
   La première version remontait le logo de 0,109 rem — 1,74 px. Une
   image posée à cheval sur deux pixels est redessinée à moitié dans
   chacun : le logo sortait FLOU, et plus pâle que dans l'atelier
   (relevé par l'auteur). L'atelier, lui, remonte ses logos de « top:
   -2px » depuis la v42 (« .rec__cla-logo ») : on reprend sa recette. */
.financier__eq img { width: 100%; height: 100%; object-fit: contain; }
.financier__eq i { display: none; }
.financier__eq .logo--pale { display: none; }
html[data-theme="clair"] .financier__eq .logo--fonce { display: none; }
html[data-theme="clair"] .financier__eq .logo--pale { display: block; }
.financier__nom { vertical-align: middle; }
/* Le code en trois lettres, quand le logo manque sur le disque. */
.financier__code {
  display: inline-block;
  min-width: 1.75rem;
  margin-right: 0.5rem;
  font-family: var(--donnees);
  font-size: 0.625rem;
  letter-spacing: .06em;
  color: var(--ambre);
  vertical-align: middle;
}
/* L'échéance ne se coupe jamais : « 2034 UFA » est une seule idée.
   ⚠ La couleur des montants, pas une valeur atténuée (demande de
   l'auteur, v65) : l'échéance est une donnée comme les autres. */
.financier td.financier__fin { white-space: nowrap; color: var(--titre); }

/* ⚠ LES PASTILLES DE RECHERCHE → ÉQUIPES → CONTRATS (demande de
   l'auteur, v65) : un fond pâle, le mot dans sa couleur franche.
   En clair, l'inverse — le fond franc, le mot pâle par-dessus — :
   un fond pâle sur du papier ne se détacherait plus. */
/* ⚠ LE MOT CENTRÉ DANS SA PASTILLE : une hauteur fixe et une boîte
   qui centre, comme « .ctr__statut » de RECHERCHE — pas un
   rembourrage, qui laisse la police décider de la hauteur. */
.financier__statut {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 2.25rem;
  height: 1rem;
  padding: 0 0.375rem;
  box-sizing: border-box;
  border: 1px solid;
  border-radius: 3px;
  font-family: var(--etiquette);
  font-size: 0.5625rem;
  font-weight: 700;
  letter-spacing: .06em;
  line-height: 1;
}
/* Même mesure : la capitale de Chakra Petch montait d'un pixel dans
   sa pastille. */
.financier__statut { padding-top: 2px; }
.financier__statut--ufa { color: #B42A2A; background: #FDE2E2; border-color: #F5BDBD; }
.financier__statut--rfa { color: #2F5EA8; background: #DDE8FB; border-color: #B9CEF1; }
html[data-theme="clair"] .financier__statut--ufa { color: #FDE2E2; background: #B42A2A; border-color: #B42A2A; }
html[data-theme="clair"] .financier__statut--rfa { color: #DDE8FB; background: #2F5EA8; border-color: #2F5EA8; }

/* — Duel — */

/* Chaque rangee est close et porte son propre filet : c'est ce
   qui permet de la survoler d'un bloc. */
.duel__r {
  display: grid;
  grid-template-columns: 1fr 128px 1fr;
  align-items: center;
  border-top: 1px solid var(--filet);
}
.duel__r--tete { border-top: 0; }
.duel__r:not(.duel__r--tete):hover { background: var(--voile); }

/* La rangee d'identite : etiquette et nom sur une seule ligne,
   l'etiquette a l'exterieur de chaque bord. */
.duel__r--tete .duel__g,
.duel__r--tete .duel__d { display: flex; align-items: center; gap: 0.625rem; padding-block: 0.6875rem; }
.duel__r--tete .duel__d { justify-content: flex-end; }

/* ── LES DEUX CAMPS, CHACUN SA COULEUR ─────────────────────────
   Chaque cote prend la teinte de SON equipe, en degrade : la
   couleur nait sous le logo et s'eteint vers le centre. Les deux
   se rejoignent transparentes au milieu.

   DEUX BLOCS PARTAGENT CETTE REGLE — le duel et les transactions.
   Ils font la meme chose : opposer deux equipes de part et
   d'autre d'un axe. Ecrire la couleur deux fois aurait garanti
   qu'elles finissent par diverger.

   Ce n'est pas du decor. Rien dans ces tableaux ne dit a qui
   appartient quel cote une fois qu'on a quitte la ligne des
   logos. La teinte le dit sans un mot.

   Meme melange que les cartes du fil, en plus fort au depart : un
   degrade perd la moitie de sa force percue en s'eteignant. */
.duel__r--tete .duel__g,
.duel__r--tete .duel__d,
.transac__cg,
.transac__cd,
/* ⚠ LA FICHE REJOINT LA MEME FAMILLE.

   Elle ne portait aucune teinte : son en-tete etait la seule bande
   d'identite du site a ne pas dire a qui elle appartient. Le duel
   et les transactions le font depuis le 1er septembre, avec la
   meme recette — et une fiche fait exactement le meme travail,
   pour un seul camp au lieu de deux.

   ⚠ ELLE EST DU COTE DROIT, sous l'etiquette d'equipe, parce que
   c'est de la que la couleur doit naitre. Le duel ancre chaque
   degrade sous son logo; ici il n'y a qu'un logo, et il est a
   droite. */
.joueur__tete {
  /* Ou le degrade finit de s'eteindre, en part de sa moitie. */
  --duel-fin: 100%;
  background-repeat: no-repeat;
}
.duel__r--tete .duel__g,
.transac__cg {
  background-image: linear-gradient(
    to right,
    color-mix(in srgb, var(--eqt, var(--eqf)) 14%, transparent) 0%,
    transparent var(--duel-fin));
  /* Le degrade est ancre sous le logo : c'est de la qu'il grandira
     quand le bloc entrera a l'ecran. */
  background-position: left center;
}
.duel__r--tete .duel__d,
.transac__cd,
.joueur__tete {
  background-image: linear-gradient(
    to left,
    color-mix(in srgb, var(--eqt, var(--eqf)) 14%, transparent) 0%,
    transparent var(--duel-fin));
  background-position: right center;
}

.duel__g, .duel__d { padding: 0.5625rem 0.9375rem; font-family: var(--donnees); font-weight: 700; font-size: 0.9375rem; color: var(--titre); }
.duel__d { text-align: right; }
/* Teko porte sa masse en haut de la ligne : le nom paraissait
   2,7 px plus haut que l'etiquette a cote. Le decalage porte sur
   le texte seul — le fond de survol vit sur la rangee, il ne
   bouge donc pas. */
.duel__nom { font-family: var(--sans); font-weight: 500; font-size: 1.25rem; line-height: 1.1; color: var(--titre); position: relative; top: 0.127em; }

/* Le nom et ses deux lignes de details forment un bloc, centre sur
   le jeton d'equipe pose a cote. Sans « duel__id », le nom seul
   s'alignait sur la ligne de base; a trois lignes, c'est le bloc
   entier qu'il faut centrer. */
/* ⚠ LE REPÊCHAGE EST UNE LIGNE À PART, PAS UNE MENSURATION.

   Il porte donc la même fonte et la même couleur que la ligne
   au-dessus — c'est la même nature d'information — mais il a sa
   propre ligne, et un peu d'air pour qu'on voie qu'elle est
   voulue. */
.joueur__repe { margin-top: 0.1875rem; }

.duel__id { display: flex; flex-direction: column; gap: 0.1875rem; }
.duel__id--d { align-items: flex-end; text-align: right; }

/* Les details reprennent exactement la ligne sous le nom d'une
   fiche de joueur : meme police, meme taille, meme couleur. */
/* ⚠ TRANSPARENTE SUR GRAND ECRAN.

   « display: contents » fait disparaitre la boite sans toucher a
   son contenu : les deux lignes de details restent exactement ou
   elles etaient. Elle ne sert qu'au petit ecran, ou elle devient
   une colonne — voir plus bas. */
.duel__dets { display: contents; }

.duel__det {
  font-family: var(--etiquette);
  font-size: 0.65625rem;
  font-weight: 600;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--service);
  line-height: 1.25;
}

/* — Les transactions : un jeton de chaque cote —————————
   Chaque moitie devient une rangee horizontale : le jeton, puis le
   texte. Le tout se centre verticalement, quel que soit le nombre
   de lignes du texte. */
.transac__cg, .transac__cd {
  display: flex;
  align-items: center;
  gap: 0.875rem;
  min-width: 0;
  /* La rangee centre ses trois cases; une case ne fait donc que la
     hauteur de son contenu, et la teinte s'arretait avec elle.
     Une transaction a deux joueurs est plus haute qu'une a un
     seul : la bande de couleur devenait une barre flottante.

     Le cote s'etire sur toute la hauteur, et centre son contenu
     lui-meme : la teinte remplit, le texte reste au milieu. */
  align-self: stretch;
  padding-block: 0.875rem;
}
/* Le rembourrage exterieur, celui du bord du cadre. */
.transac__cg { padding-left: 0.9375rem; }
.transac__cd { padding-right: 0.9375rem; }
.transac__cd { justify-content: flex-end; }
.transac__cg > span, .transac__cd > span {
  font-family: var(--sans);
  font-size: 1.0625rem;
  font-weight: 400;
  line-height: 1.35;
  color: var(--titre);
  padding-top: 0.11em;
}
.transac__cd > span { text-align: right; }
.transac__cg .code, .transac__cd .code { flex-shrink: 0; }
.duel__l {
  font-family: var(--etiquette);
  font-size: 0.65625rem;
  font-weight: 600;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--ambre);
  text-align: center;
  padding: 0.5625rem 0.25rem;
}
/* La notion de meneur est en veilleuse : l'asterisque du markdown
   pose toujours la classe « gagne », mais elle ne colore plus
   rien. Une seule regle a reecrire le jour ou on la reprend. */

/* — Décompte — */

/* Le nombre de cases est libre, et la grille les replie toute
   seule : deux par rangee sur un ecran etroit, quatre sur un
   large. Le filet doit donc apparaitre entre DEUX rangees aussi,
   pas seulement entre deux colonnes.

   ⚠ POURQUOI PAS UNE BORDURE. Une bordure a droite ne connait pas
   la rangee du dessous. Et un filet fait par les gouttieres — un
   fond colore qui parait dans les interstices — remplirait la case
   VIDE quand le compte est impair : trois cases sur deux colonnes
   laissent un trou, et ce trou serait peint.

   Chaque case porte donc son propre trait, a droite et en dessous,
   par une OMBRE : une ombre ne prend pas de place et ne deplace
   rien. Le confinement de la grille coupe celles qui tombent sur
   le bord exterieur — il ne reste que les filets interieurs. */
.decompte {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));
  overflow: hidden;
}
.decompte > div {
  padding: 1.125rem 1rem;
  box-shadow: 1px 0 0 var(--filet), 0 1px 0 var(--filet);
}
/* Les memes reglages que les chiffres de l'en-tete d'article
   d'article : c'est le meme objet — un chiffre et sa categorie —
   il n'y avait aucune raison qu'ils s'ecrivent autrement. */
.decompte__n {
  font-family: var(--donnees);
  font-weight: 700;
  font-size: 1.6875rem;
  line-height: 1;
  letter-spacing: -.02em;
  color: var(--titre);
}
.decompte__l {
  font-family: var(--etiquette);
  font-size: 0.75rem;
  font-weight: 600;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--ambre);
  margin-top: 0.5625rem;
}

/* — Journal de transactions — */

/* ⚠ LA RANGEE NE PORTE PLUS DE REMBOURRAGE.

   Il vit dans les cotes. Pose sur la rangee, il laissait une
   bordure vide tout autour — et la teinte s'arretait avant les
   bords du cadre. Deplace dans les cotes, la couleur touche le
   haut, le bas et les deux bords, et le texte garde son air. */
.transac { display: grid; grid-template-columns: 1fr auto 1fr; align-items: stretch; gap: 0; padding: 0; border-bottom: 1px solid var(--filet); }
.transac:last-of-type { border-bottom: 0; }
/* Meme voile que partout ailleurs. */
/* Aucun survol ici. Il servait a designer la rangee qu'on lit;
   la teinte d'equipe le fait maintenant en permanence, et sur
   toute la hauteur. Deux marques pour la meme chose se nuisent. */
/* La date reste en chiffres. --ambre vaut deja #877B66 en foncé
   et #595143 sur papier. */
/* La rangee etire ses cases pour que la teinte remplisse toute la
   hauteur — mais la date, elle, n'a rien a remplir. Etiree comme
   les autres, son texte s'assoyait tout en haut. Elle se recentre
   donc pour son propre compte. */
.transac__date { font-family: var(--donnees); font-size: 0.6875rem; color: var(--ambre); white-space: nowrap; padding: 0 0.5rem; align-self: center; }


/* ═══ 10. CADRANS ET BARRES ═══════════════════════════════════
   DES cadrans pour situer une equipe. DES barres pour comparer
   une liste. L'œil compare mal des angles, très bien des
   longueurs. (C'est ce qu'EA applique sans le dire.)

   ⚠ CE BLOC NE MONTRAIT QU'UN SEUL CADRAN, AVEC UN TEXTE A COTE.

   La note d'alors disait : « UN cadran seulement — l'œil compare
   mal des angles. » C'est vrai pour des angles qui mesurent des
   choses differentes. Ici les quatre mesurent la MEME chose — un
   rang sur trente-deux — et se comparent donc sans peine.

   Le texte d'accompagnement est parti : quatre cadrans remplissent
   la largeur, et ce qu'il y avait a dire se dit dans la chronique.

   ⚠ ET L'ARC SUIT LE RANG, PAS LA VALEUR. « 214 buts pour » n'a
   aucune echelle; « 19e de 32 » en a une, et c'est celle qui
   compte.                                                      */

/* Le nombre de cadrans vient du generateur : la feuille ne peut
   pas le deviner, et un cadran seul ne doit pas se retrouver
   large comme quatre. */
.cadrans {
  display: grid;
  gap: 1.5rem 1.25rem;
  padding: 1.625rem 1.25rem 1.375rem;
  grid-template-columns: repeat(4, minmax(0, 1fr));
}

.cadrans[data-combien="1"] { grid-template-columns: minmax(0, 16rem); justify-content: center; }
.cadrans[data-combien="2"] { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.cadrans[data-combien="3"] { grid-template-columns: repeat(3, minmax(0, 1fr)); }

.cadrans__c {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.625rem;
  min-width: 0;
}

/* La categorie, au-dessus. Elle nomme ce que l'arc mesure : sans
   elle, quatre arcs ne veulent rien dire. */
.cadrans__cat {
  margin: 0;
  font-family: var(--etiquette);
  font-size: 0.6875rem;
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  /* ⚠ L'ENCRE PLEINE, PAS L'ATTENUEE.
     La categorie NOMME ce que l'arc mesure : sans elle, quatre
     arcs ne veulent rien dire. Elle porte donc autant que le
     chiffre, et « --os » donne deja les deux teintes voulues —
     #ECE8E4 en sombre, #211A12 en clair. */
  color: var(--os);
  text-align: center;
  line-height: 1.3;
}

.cadrans .cadran { width: 100%; max-width: 8.5rem; height: auto; display: block; }

/* Le rang, en dessous. C'est lui que l'arc mesure — il doit donc
   se lire tout de suite apres. */
.cadrans__rang {
  margin: 0;
  font-family: var(--donnees);
  font-size: 0.75rem;
  color: var(--ambre);
  text-align: center;
}

/* ⚠ UN BLOC VIDE LE DIT PLUTOT QUE DE S'EVAPORER.
   Un tableau qui disparait de la page sans un mot fait chercher
   pendant vingt minutes ce qui ne s'affiche pas. Celui-ci reste
   visible et explique ce qu'il attend. */
.bloc__vide {
  margin: 0;
  padding: 1.625rem 1.25rem;
  font-family: var(--lecture);
  font-size: 0.9375rem;
  font-style: italic;
  color: var(--service);
  text-align: center;
}


/* Sur un telephone, quatre cadrans cote a cote deviennent des
   confettis : ils passent a deux par rangee. */
@media (max-width: 640px) {
  .cadrans,
  .cadrans[data-combien="3"],
  .cadrans[data-combien="4"] { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .cadrans[data-combien="1"] { grid-template-columns: minmax(0, 13rem); }
}

/* Meme rapport que les bandes de temps du bloc de barres : une
   piste discrete, a peine detachee du fond, et un remplissage en
   ambre. La piste donne l'echelle sans se faire remarquer. */
.cadran .piste        { stroke: var(--piste); }
.cadran .arc          { stroke: var(--ambre); }
/* Exactement les reglages des chiffres de l'en-tete d'article
   avant son retrait : meme fonte, meme graisse, meme chasse. */
.cadran .valeur { font-family: var(--donnees); font-weight: 700; letter-spacing: -.02em; fill: var(--titre); }
/* L'unite prend la valeur de la base du cadran. */
/* Un cran plus grasse : a neuf pixels dans un cercle, une
   graisse de 600 se dilue. */
.cadran .unite  { font-family: var(--etiquette); font-weight: 700; letter-spacing: 0.06em; fill: var(--titre); }

.barres { padding: 0.375rem 0; }
.barre { display: grid; grid-template-columns: 132px 1fr 58px; gap: 0.8125rem; align-items: center; padding: 0.5rem 0.9375rem; }
/* Meme voile que les rangees de la fiche de joueur et du
   financier : une couche translucide, pas un fond fixe. */
.barre:hover { background: var(--voile); }
/* Teko porte sa masse en haut de la ligne : la boite est centree
   par la grille, mais l'encre paraissait 2 px trop haute par
   rapport au temps et a la bande. On decale l'encre seule. */
.barre__nom { font-family: var(--sans); font-size: 1.0625rem; color: var(--titre); position: relative; top: 0.11em; }
.barre__piste { display: block; height: 8px; background: var(--piste); }
.barre__jus { display: block; height: 8px; background: var(--ambre); }
.barre__v { font-family: var(--donnees); font-size: 0.78125rem; color: var(--titre); text-align: right; }
/* ⚠ AVEC LES PASTILLES (v65) : la colonne des noms gagne la place de
   la pastille et de son espace — 24 + 10 px —, pour que les noms
   gardent la largeur qu'ils avaient. Les classes sont celles du tableau
   de contrats : une seule recette pour la pastille. */
.barres--eq .barre { grid-template-columns: 166px 1fr 58px; }
.barres--eq .barre__nom { min-width: 0; }
/* ⚠⚠ LA COUPE DES NOMS TROP LONGS SE FAIT SUR LE NOM, PAS SUR SA BOÎTE
   (v65, piège nº 396). « overflow: hidden » était posé sur la boîte qui
   porte AUSSI la pastille : haute d'une ligne de texte, elle rognait le
   haut et le bas de la pastille de 24 px. Le filet disparaissait en
   haut, l'image paraissait décentrée dans son cadre — puis RECTANGULAIRE
   quand on l'a remontée d'un pixel (relevé par l'auteur, deux fois). */
.barres--eq .financier__joueur { max-width: 100%; }
.barres--eq .financier__nom { min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.financier__eq--vide { width: 24px; height: 24px; }

/* ── LE TABLEAU DE CLASSEMENT (v65) ──────────────────────────
   Il emprunte le tableau de contrats (« financier ») : mêmes fontes,
   même pas de ligne, même pastille. Ce qui lui est propre : les
   chiffres centrés, le rang discret, l'équipe en évidence, et le trait
   de la dernière place qualificative. */
.classement td, .classement th { text-align: center; }
.classement th:nth-child(2), .classement td:nth-child(2) { text-align: left; width: 26%; }
.classement td:first-child {
  font-family: var(--donnees); font-size: 0.78125rem; color: var(--attenue);
  width: 2.5rem; padding-top: calc(0.428rem + 0.015em); padding-bottom: calc(0.428rem - 0.015em);
}
.classement td:nth-child(2) {
  font-family: var(--sans); font-weight: 400; font-size: 1.0625rem; color: var(--titre);
  padding-top: calc(0.428rem + 0.077em); padding-bottom: calc(0.428rem - 0.077em);
}
/* Le nom d'une ville ne se coupe pas en deux lignes (« Tampa / Bay » à
   360 px) : il se tronque plutôt. La coupe se fait sur le NOM, jamais
   sur la boîte qui porte la pastille (piège nº 396). */
.classement .financier__joueur { max-width: 100%; }
.classement .financier__nom { min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
/* ⚠ LES TITRES DE GROUPE (v65) : la ligne d'en-têtes reprise sous
   chaque division, comme le classement de RECHERCHE. Le nom du groupe
   prend la place du « # » et d'« Équipe ». Un peu d'air au-dessus, sauf
   pour le premier. */
.classement tr.classement__groupe th { padding-top: 1.125rem; }
.classement tr.classement__groupe:first-child th { padding-top: 0.5625rem; }
.classement th.classement__groupe-nom { text-align: left; }
/* ⚠ Dans une ligne de titre, le 2e « th » est « PJ », pas « Équipe » : la
   règle de largeur et d'alignement de la colonne d'équipe ne doit pas
   l'attraper (vu au rendu : « PJ » était poussé à gauche). */
.classement tr.classement__groupe th:nth-child(2) { width: auto; text-align: center; }
/* ⚠ TROIS LARGEURS (v65, demande de l'auteur) — voir « bloc_classement ».
   Le code en trois lettres n'existe que sur un téléphone. */
.classement .cla-code { display: none; }
@media (max-width: 1000px) {
  .classement .cla-g { display: none; }
}
@media (max-width: 600px) {
  .classement .cla-t { display: none; }
  .classement .cla-ville { display: none; }
  .classement .cla-code { display: inline; }
  .classement .cla-mot { display: none; }
  .classement th:nth-child(2), .classement td:nth-child(2) { width: auto; }
  /* ⚠ MESURÉ À 360 PX : avec le rembourrage de grand écran, le P%
     sortait du cadre de 44 px. Moitié moins d'air entre les colonnes, et
     la pastille se rapproche de son code. */
  .classement th, .classement td { padding-left: 0.375rem; padding-right: 0.375rem; }
  .classement .financier__eq { margin-right: 6px; }
}
/* Les points : la colonne qui range, un cran plus appuyée. */
.classement td:nth-child(7) { font-weight: 700; }
.classement tr.classement__evidence td { background: color-mix(in srgb, var(--ambre) 16%, transparent); }
/* ⚠ LE TRAIT EST UN FILET SOUS LA RANGÉE, PAS UNE RANGÉE DE PLUS : le
   tableau garde son pas. Le MÊME mince filet que le classement de
   RECHERCHE (demande de l'auteur, v65) — pas le pointillé ambre du
   premier essai. */
.classement tr.classement__trait td { border-bottom: 1px solid var(--filet); }

/* Progression de lecture — le seul autre endroit où l'arc
   mesure. Épinglé au coin, discret. */
.progression { position: fixed; bottom: 1.25rem; right: 1.25rem; z-index: 15; opacity: .85; }
/* La progression avait « --filet2 » et « --ambre » : en mode
   clair ces deux jetons tombent sur la MEME valeur, et la piste
   devenait invisible sous son propre remplissage. */
.progression .piste { stroke: var(--piste); }
.progression .arc { stroke: var(--arc-lecture); transition: stroke-dasharray .2s linear; }
.progression text { font-family: var(--donnees); font-weight: 700; fill: var(--corps); }


/* ═══ 11. REGISTRE ════════════════════════════════════════════
   Les pages de rubrique sont l'archive. Elles se lisent comme
   un index de Hockey-Reference.                               */

.registre { width: 100%; border-collapse: collapse; font-family: var(--donnees); font-size: 0.8125rem; }
/* La ligne de titres reprend le fond des en-têtes d'encadré :
   c'est la même famille d'objet — une bande qui coiffe des
   données. */
.registre th {
  font-family: var(--etiquette);
  font-size: 0.75rem;
  font-weight: 700;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--bande-etiquette);
  background: var(--bande-fond);
  text-align: left;
  padding: 0.6875rem 0.75rem;
  border-bottom: 1px solid var(--bande-bord);
}
.registre th:first-child { padding-left: 0.9375rem; }
.registre th:last-child { padding-right: 0.9375rem; }
.registre td { padding: 0.875rem 0.75rem 0.875rem 0; border-bottom: 1px solid var(--filet); color: var(--attenue); vertical-align: middle; }
/* Le survol balaie la rangee de GAUCHE A DROITE plutot que de
   s'allumer d'un coup.

   Un fond pose sur chaque cellule ne peut pas faire ca : chacune
   s'allumerait separement. On pose donc une seule couche sur la
   PREMIERE cellule, assez large pour couvrir toute la rangee, et
   c'est elle qui se devoile.

   « clip-path » plutot qu'un degrade : il coupe net, donc le bord
   du balayage reste franc au lieu de s'estomper. */
.registre tr[data-lien] > td:first-child { position: relative; }
.registre tr[data-lien] > td:first-child::before {
  content: '';
  position: absolute;
  top: 0;
  bottom: 0;
  left: 0;
  width: 1320px;
  background: var(--lueur);
  pointer-events: none;
  z-index: -1;
  clip-path: inset(0 100% 0 0);
  transition: clip-path 420ms cubic-bezier(.22, 0, .2, 1);
}
.registre tr[data-lien]:hover > td:first-child::before {
  clip-path: inset(0 0 0 0);
}

@media (prefers-reduced-motion: reduce) {
  .registre tr[data-lien] > td:first-child::before { transition: none; }
}
/* La rangée entière est cliquable — voir le script de base.html. */
.registre tr[data-lien] { cursor: pointer; }
/* « td.classe » plutot que « .classe » : la regle « .registre td »
   plus haut vaut une classe plus un type, et gagnait sur chacune
   de ces colonnes. Numeros, dates, temps et titres sortaient tous
   dans le meme gris delave au lieu de leurs couleurs propres. */
.registre td.registre__no { width: 54px; color: var(--faible); }
.registre td.registre__date { width: 96px; color: var(--faible); }
/* Dans une liste dense, le code d'équipe redevient du texte
   coloré : l'étiquette pleine paraît trop lourde à côté d'un
   corps de tableau plus petit. */
.registre__eq { width: 92px; padding-right: 1.75rem; }
.registre__eq span {
  font-family: var(--etiquette);
  font-size: 0.8125rem;
  font-weight: 700;
  letter-spacing: .1em;
  color: var(--eq, var(--os));
}
.registre td.registre__titre { font-family: var(--sans); font-weight: 500; font-size: 1.3125rem; letter-spacing: .01em; line-height: 1.2; color: var(--titre); }
.registre__titre small { display: block; font-family: var(--lecture); font-weight: 400; font-size: 1rem; letter-spacing: 0; color: var(--attenue); margin-top: 0.25rem; }
.registre td.registre__mm { text-align: right; color: var(--faible); }
/* La deuxieme ligne, quand la colonne en porte deux : les
   minutes sous les mots, dans le meme gris de service. */
.registre__mm small { display: block; font-size: inherit; }

.lire-suite {
  display: inline-block;
  font-family: var(--sans);
  font-size: 1.375rem;
  font-weight: 400;
  letter-spacing: 0;
  line-height: 1;
  text-transform: uppercase;
  /* Os au repos, ambre au survol : l'inverse de l'ancien
     reglage. Le filet suit le texte plutot que d'avoir sa
     propre couleur — sinon le survol ne deplace que la moitie
     de l'objet. */
  color: var(--os);
  border-bottom: 2px solid currentColor;
  padding-bottom: 2px;
  transition: color var(--glisse);
}
.lire-suite:hover { color: var(--ambre); }


/* ═══ 12. LE TEXTE D'INTRODUCTION ═════════════════════════════
   Le paragraphe qui ouvre une section, sous le titre. Il sert au
   Fil, au Mur, au Bilan, à À propos et aux rubriques.

   Les CARTES du fil, elles, vivent dans la section 20.        */

.fil__intro { font-family: var(--lecture); font-size: 1.0625rem; line-height: 1.6; color: var(--attenue); max-width: 60ch; margin: 1.125rem 0 0.375rem; }


/* ═══ 14. COURRIEL ET PIED ════════════════════════════════════
   Ne jamais écrire le mot « infolettre ». C'est la chronique
   du mardi.                                                   */

.courriel {
  border-top: 1px solid var(--bande-bord);
  background: var(--bande-fond);
  padding: 2.125rem var(--marge-laterale) 2.625rem;
  margin-top: 1.75rem;
}
.courriel__e { font-family: var(--donnees); font-size: 0.75rem; color: var(--bande-etiquette); margin-bottom: 0.625rem; }
/* L'accroche et sa glose s'ecrivent a l'os dans les DEUX themes.
   Valeur ecrite en clair plutot qu'en jeton : aucun des jetons de
   la palette ne vaut #ECE8E4 des deux bords — l'os devient de
   l'encre en mode clair. Le bandeau, lui, est fonce en clair
   comme en sombre, donc son texte reste pale. */
.courriel__a { font-family: var(--sans); font-weight: 600; font-size: 1.875rem; letter-spacing: .01em; line-height: 1.1; color: #ECE8E4; margin: 0 0 0.5rem; }
/* Le plafond passe de 46 a 58 caracteres : le sous-titre porte
   maintenant ses propres retours de ligne, et une brisure du
   navigateur par-dessus les siennes coupait la phrase au mauvais
   endroit. */
.courriel__s { font-family: var(--lecture); font-size: 1.0625rem; line-height: 1.6; color: #ECE8E4; margin: 0 0 1.1875rem; max-width: 58ch; }

/* Le contour fait le tour de la case ET du bouton : c'est une
   seule boite. Il porte « --bouton-filet » plutot que le contour
   ordinaire des bandes — plus fonce, plus net, et le meme trait
   que le bouton du hors-jeu. */
.formulaire { display: flex; max-width: 430px; border: 1px solid var(--bouton-filet); }
.formulaire input {
  flex: 1;
  min-width: 0;
  background: var(--fond);
  border: 0;
  color: var(--corps);
  font-family: var(--donnees);
  font-size: 0.78125rem;
  padding: 0.8125rem 0.875rem;
  outline: none;
}
.formulaire input::placeholder { color: var(--faible); }
/* ⚠ CE BLOC HABILLE DEUX BOUTONS. Le second est « Je veux
   retourner a la page d'accueil », sur le HORS-JEU. Ecrire les
   memes valeurs a deux endroits les aurait laisses diverger au
   premier ajustement — c'est le piege nº 28.

   L'IDENTITE est partagee : l'ambre, l'encre du fond par-dessus,
   la fonte, les majuscules, le survol. La BOITE, elle, ne l'est
   pas : celui du formulaire tire sa hauteur de la rangee qui le
   contient, celui du hors-jeu est seul et doit se la donner. */
.formulaire button,
.horsjeu__banc {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: var(--ambre);
  color: var(--fond);
  border: 0;
  font-family: var(--sans);
  font-weight: 400;
  font-size: 1.1875rem;
  letter-spacing: 0;
  text-transform: uppercase;
  line-height: 1;
  padding: 0 1.5rem;
  /* Teko porte sa masse en haut de la ligne : on descend le texte
     d'un cheveu pour qu'il paraisse centré. */
  padding-top: 0.15em;
  cursor: pointer;
  white-space: nowrap;
  transition: background var(--glisse);
}
.formulaire button:hover,
.horsjeu__banc:hover,
.horsjeu__banc:focus-visible { background: var(--ambre-vif); }

/* ── LE FORMULAIRE QUI REPOND SUR PLACE ────────────────────────
   Le lecteur ne quitte JAMAIS le site pour s'abonner. Son adresse
   part en arriere-plan chez le portier, et le formulaire se
   transforme en message ecrit de la main de l'auteur.

   Sans script, rien de tout ca ne s'applique : le formulaire
   redevient un formulaire ordinaire qui s'envoie normalement.
   C'est voulu — le piege nº 32 en tete. */

/* Le piege a robots. Il doit rester dans la page (un programme qui
   lit le HTML le trouvera), mais hors de vue et hors du chemin du
   clavier. « display: none » suffirait a le rendre suspect. */
.formulaire__miel {
  position: absolute;
  left: -9999px;
  width: 1px;
  height: 1px;
  opacity: 0;
  pointer-events: none;
}

/* Pendant l'envoi : le bouton devient inerte et le dit. */
.formulaire.envoi input,
.formulaire.envoi button { opacity: .55; pointer-events: none; }

/* La reponse prend la place du formulaire, dans la meme boite —
   sans quoi le contenu autour sauterait au moment du changement. */
.formulaire__reponse {
  display: none;
  max-width: 430px;
  font-family: var(--donnees);
  font-size: 0.78125rem;
  line-height: 1.7;
  padding: 0.8125rem 0.875rem;
  border: 1px solid var(--bande-bord);
  color: var(--corps);
}
.formulaire__reponse.vu { display: block; }
.formulaire.repondu { display: none; }

/* Un echec garde le formulaire ouvert : le lecteur doit pouvoir
   corriger son adresse sans tout recommencer. */
.formulaire__reponse--rate {
  border-color: var(--mauvais);
  color: var(--mauvais);
  margin-top: 0.5rem;
}
.formulaire.rate { display: flex; }

/* Sur la porte d'entree, le formulaire est centre : sa reponse
   doit l'etre aussi. */
.attente__form + .formulaire__reponse,
.attente .formulaire__reponse { margin: 2.25rem auto 0; text-align: center; }

.pied {
  border-top: 1px solid var(--filet);
  /* Sept pixels de jeu au-dessus et sous le logo : le pied est une
     ligne de service, pas une section. Il vit a la hauteur du
     logo plutot qu'a celle du texte. */
  padding: 7px var(--marge-laterale);
  display: flex;
  justify-content: space-between;
  gap: 0.875rem;
  flex-wrap: wrap;
  align-items: center;
  font-family: var(--donnees);
  font-size: 0.65625rem;
  color: var(--service);
}
/* Le logo du pied, au centre. Meme taille que celui de l'en-tete
   pour que ce soit le meme objet, pas un cousin.

   Les deux textes prennent la meme part de l'espace : sans ca, le
   plus long pousse le logo de cote — il etait 26,7 px hors du
   centre, parce que « BONSANSLARONDELLE.COM · JONATHAN LORD » est
   plus large que « REGISTRE OUVERT LE… ». */
.pied > span { flex: 1; }
.pied > span:last-child { text-align: right; }
.pied__logo { flex-shrink: 0; width: 31px; height: 31px; display: block; }


/* ═══ 15. MOBILE ══════════════════════════════════════════════ */

@media (max-width: 900px) {
  .grille { flex-direction: column; gap: 1.625rem; }
  .grille__marge { width: 100%; position: static; display: flex; flex-wrap: wrap; gap: 1.25rem 1.75rem; }
  .marge__b { margin-bottom: 0; }
  .marge__rappel { width: 100%; }
  .grille__contenu { max-width: 100%; margin-inline: 0; }

  /* Le justifié devient laid sous ~400 px, même avec la césure.
     Sans chevron, volontairement : sur un téléphone, TOUT passe à
     gauche, y compris ce qui vit dans un bloc. */
  .texte p, .chapeau { text-align: left; }

  /* ⚠ Les DEUX moitiés, sinon la table casse.

     Les cellules de contenu portent une classe; les cellules
     d'EN-TÊTE, elles, n'ont que leur position. Cacher les
     premières sans les secondes laissait « Date » et « Lecture »
     dans la ligne de titres — et cette ligne-là décide de la
     largeur de toutes les colonnes, parce que la table est en
     largeur imposée.

     Résultat : cinq en-têtes réclamaient 400 px dans une boîte de
     312, et le surplus était volé à la seule colonne flexible.
     Les titres descendaient un mot par ligne. */
  .registre__date, .registre__mm,
  .registre th:nth-child(2),
  .registre th:nth-child(5) { display: none; }

  /* Il ne reste que trois colonnes : le numéro, le jeton, le
     titre. Les deux premières gardent leur largeur, la troisième
     prend tout ce qui reste. */
  .registre th:nth-child(1) { width: 3rem; }
  .registre th:nth-child(3) { width: 4.5rem; }
  .registre th:nth-child(4) { padding-left: 0.625rem; }
  .registre__titre { padding-left: 0.625rem; }
  .duel { grid-template-columns: 1fr 96px 1fr; }
  .barre { grid-template-columns: 104px 1fr 50px; }
  .barres--eq .barre { grid-template-columns: 138px 1fr 50px; }
  .progression { display: none; }
  .entree__corps { padding: 1.375rem 1.125rem 1.25rem; }
}

@media (max-width: 560px) {
  /* La suite s'empile : deux cartes de 150 px rendraient les
     titres illisibles. */
  .suite { grid-template-columns: minmax(0, 1fr); gap: 1.75rem; }
  .formulaire { flex-direction: column; }
  .formulaire button { width: 100%; }
  /* Ce rembourrage ne vaut QUE pour l'en-tete d'origine. Sous
     1000 px, l'en-tete se replie en deux rangees et porte son
     propre rembourrage — voir la fin du fichier. */
  @media (min-width: 1001px) {
    .entete { padding-top: 0.625rem; padding-bottom: 0.625rem; }
  }
}


/* ═══ 16. ACCESSIBILITÉ ET IMPRESSION ═════════════════════════ */

:focus-visible { outline: 2px solid var(--ambre); outline-offset: 3px; }

.saut-au-contenu {
  position: absolute;
  left: -9999px;
  top: 0;
  z-index: 100;
  background: var(--ambre);
  color: var(--fond);
  font-family: var(--sans);
  font-weight: 600;
  font-size: 0.875rem;
  padding: 0.75rem 1.25rem;
}
.saut-au-contenu:focus { left: 0; }

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    transition-duration: 0.01ms !important;
    animation-duration: 0.01ms !important;
  }
}

@media print {
  .entete, .nav, .bascule, .ruban, .courriel, .pied,
  .partenaire, .marge__rappel, .progression, .suite { display: none; }
  body { background: #fff; color: #000; }
  .texte p, .chapeau { text-align: left; }
  .bloc, .entree { border-color: #999; break-inside: avoid; }
}


/* ═══ 17. PAGE D'ACCUEIL ══════════════════════════════════════
   Deux blocs en haut : l'entrée récente et le fil, côte à côte.
   Le registre en dessous. Un filtre par équipe recompose les
   trois. Tout ce qui défile est piloté par accueil.js.
   ══════════════════════════════════════════════════════════════ */

/* — Les encadrés ————————————————————————————————————
   L'intérieur est plus foncé que le site : le creux de valeur
   suffit à détacher le bloc, sans texture ni éclaircissement. */

.cadre {
  position: relative;
  border: 1px solid var(--filet2);
  background: var(--cadre-fond);
  overflow: hidden;
}
.cadre > * { position: relative; z-index: 1; }

/* — La disposition ————————————————————————————————— */

/* Hauteur fixe et identique pour les deux boîtes. Les pastilles
   vivent EN DEHORS du cadre : elles ne comptent pas dans sa
   hauteur, donc les deux blocs restent alignés. */
.duo { display: flex; gap: 1.25rem; align-items: flex-start; margin: 1rem 0 1.25rem; }
.duo__principal { flex: 1; min-width: 0; display: flex; flex-direction: column; }
.duo__cote { width: 24rem; flex-shrink: 0; display: flex; flex-direction: column; }
.duo__principal > .cadre,
.duo__cote > .cadre { height: 30rem; flex: none; }

.vedette { touch-action: pan-y; display: flex; flex-direction: column; height: 100%; }
.vedette__corps { padding: 1.75rem 1.625rem 1.5rem; }
/* ⚠ LE TITRE DE LA VEDETTE N'EST PAS CELUI D'UN ARTICLE.

   Il heritait de « .titre-article » au complet : la taille de la
   page d'article, et surtout un plafond de DIX-SEPT CARACTERES de
   large. Il cassait donc ses lignes bien avant le bord du panneau,
   et un titre de trois mots passait sur deux lignes pour rien.

   ⚠ C'EST LE MEME VESTIGE QUE CELUI DU CHAPEAU, A MOITIE REGLE.

   Le chapeau trainait le meme genre de plafond — 64 caracteres —
   et il a recu « max-width: none » quelques dizaines de lignes
   plus bas, avec son commentaire. Personne n'a fait le meme geste
   pour le titre, qui est pourtant dans la meme boite.

   ⚠ ET PAS DE MOTS COUPES.

   « hyphens: auto » vaut sur la page d'article, ou le texte est
   justifie sur une large colonne. Dans un panneau etroit, il
   coupait des mots pour rien — « affi-chés » au milieu de
   l'amorce. C'est la meme decision qu'a la page A propos : l'auteur
   ne veut pas de mots coupes. */
.vedette .titre-article {
  font-size: var(--t-titre-vedette);
  max-width: none;
  margin-bottom: 0.875rem;
  hyphens: none;
  -webkit-hyphens: none;
}

.vedette .chapeau,
.vedette .texte > p {
  hyphens: none;
  -webkit-hyphens: none;
}
/* Trois valeurs qui se succedent dans l'encadre : le titre en os,
   le chapeau en ambre, puis le corps en os. Le chapeau se detache
   au lieu de s'effacer. Uniquement dans la vedette — la page
   d'article garde ses reglages. */
/* La couleur vient maintenant de « .chapeau » lui-meme. */
.vedette .chapeau { margin-bottom: 1.25rem; }

/* LIRE LA SUITE quitte le fil du texte et va se loger dans le
   coin inferieur droit de l'encadre, en languette coupee a 45
   degres — le meme biseau que l'onglet du fil, de l'autre bord
   de la page. Meme police qu'avant; le soulignement disparait,
   c'est la boite qui fait le travail maintenant. */
.vedette .lire-suite {
  position: absolute;
  right: 0;
  bottom: 0;
  z-index: 2;
  display: inline-flex;
  align-items: center;
  /* Meme hauteur que l onglet du fil : les deux se lisent comme
     deux exemplaires du meme objet, un de chaque bord. */
  min-height: 2.5rem;
  border-bottom: 0;
  padding: calc(0.5rem + 0.1em) 1.375rem calc(0.5rem - 0.1em);
  background: var(--bande-fond);
  color: var(--bande-valeur);
  clip-path: polygon(17px 0, 100% 0, 100% 100%, 0 100%, 0 17px);
}
.vedette .lire-suite:hover { color: var(--ambre); }
.vedette .texte > p { color: var(--os); }
.vedette .texte { flex: 1; min-height: 0; overflow: hidden; }
.vedette .texte p {
  margin-bottom: 1rem;
  display: -webkit-box;
  -webkit-line-clamp: 5;
  -webkit-box-orient: vertical;
  overflow: hidden;
}


/* — La vedette en photo ————————————————————————————————
   Quand un texte porte une image, l'encadre devient la photo et
   le texte se replie dans une bande au bas. Au survol, la bande
   remonte comme un store et le texte se revele de gauche a
   droite. Sur un ecran tactile, tout est ouvert d'office : il n'y
   a pas de survol au doigt. */
/* La photo occupe tout l'encadre, sous la barre de metadonnees. */
.duo__principal .cadre--photo {
  background-image: var(--photo);
  background-size: cover;
  background-position: center;
  background-repeat: no-repeat;
}

/* Le panneau coulissant. Il reste dans le fil normal de la boite,
   juste sous la barre : il prend donc automatiquement la hauteur
   qui reste, quelle que soit celle de la barre. C'est ce qui le
   rend solide sur un telephone, ou la barre passe sur deux lignes.
   Une marge negative le fait glisser de quelques pixels SOUS la
   barre, pour qu'aucun arrondi d'ecran ne laisse voir la photo. */
.cadre--photo .vedette__corps {
  position: relative;
  z-index: 2;
  flex: 1;
  min-height: 0;
  margin-top: calc(-1 * var(--photo-recouvre));
  display: flex;
  flex-direction: column;
  /* Le rembourrage du haut rattrape ce que le chevauchement
     cache. Celui du bas est reduit a 0,8235 rem : a 1,25 rem, le
     texte se retrouvait 21 px du bas contre 8 du haut, et aucun
     decalage ne pouvait rattraper ca sans rogner l'amorce. */
  padding: calc(1.5rem + var(--photo-recouvre) - var(--photo-remonte)) 1.875rem 0.8235rem;
  background: var(--photo-voile);
  /* Un filet au sommet, de la meme valeur que le cadre : sans lui,
     le voile se fond dans la photo et la coupure ne se lit pas. */
  border-top: 1px solid var(--filet2);
  transform: translateY(calc(100% - var(--photo-bande) + var(--photo-remonte)));
  transition: transform var(--photo-glisse);
  will-change: transform;
}
.cadre--photo:hover .vedette__corps,
.cadre--photo:focus-within .vedette__corps { transform: translateY(0); }

/* La barre de metadonnees reste par-dessus la photo. Elle garde
   son fond de bande, donc la meme valeur que l'en-tete du panneau
   du fil a cote. Aucune hauteur imposee : elle prend ce qu'il lui
   faut, et le panneau s'ajuste tout seul. */
.cadre--photo .barre-meta {
  position: relative;
  z-index: 3;
  background: var(--bande-fond);
}

/* Le titre garde sa place en haut du panneau : c'est lui qu'on
   voit au repos, et c'est lui qui monte. Une fois la fenetre
   ouverte, tout le bloc descend d'un cran pour se centrer dans le
   cadre — il se collait a 8 px de la barre alors qu'il en restait
   21 en dessous. Le bouton, pose en absolu, ne suit pas. */
.cadre--photo .titre-article {
  margin: 0 0 1rem;
  transition: margin-top var(--photo-glisse);
}
.cadre--photo:hover .titre-article,
.cadre--photo:focus-within .titre-article { margin-top: var(--photo-centre); }
/* Rien pour le tactile ici : le panneau y reste ferme, donc le
   titre garde sa place de repos. */

/* Le chapeau traine un plafond de 64 caracteres, herite de la
   page d'article. Dans le panneau, il rendait sa colonne 77 px
   plus etroite que celle de l'extrait juste dessous : les deux
   blocs se justifiaient sur des largeurs differentes, et le
   chapeau cassait ses lignes trop tot. */
.cadre--photo .chapeau { max-width: none; }

/* Chapeau et amorce n'apparaissent qu'une fois le panneau leve,
   et pas d'un coup : un masque degrade balaie de gauche a droite,
   comme si le texte s'ecrivait. Le masque fait deux fois et demie
   la largeur du bloc; on ne fait que deplacer sa position, ce qui
   est une animation que la carte graphique sait faire seule. */
.cadre--photo .chapeau,
.cadre--photo .vedette .texte {
  /* La zone opaque va jusqu'a 44 %, pas 34.

     Le masque fait 250 % de la largeur du bloc, et se termine a la
     position 0. Le bord DROIT du texte tombe donc a 100/250, soit
     40 % du masque. A 34 %, il etait deja dans le fondu : la fin
     des lignes restait a 75 % d'opacite pour toujours — 92 % sur
     les lettres, qui n'atteignent pas tout a fait le bord.

     C'est le piege nº 25, sous une autre forme : un masque doit
     couvrir PLUS que ce qu'il revele. */
  -webkit-mask-image: linear-gradient(90deg, #000 0%, #000 44%, transparent 68%, transparent 100%);
  mask-image: linear-gradient(90deg, #000 0%, #000 44%, transparent 68%, transparent 100%);
  -webkit-mask-size: 250% 100%;
  mask-size: 250% 100%;
  -webkit-mask-position: 100% 0;
  mask-position: 100% 0;
  transition: mask-position 200ms ease, -webkit-mask-position 200ms ease;
}
.cadre--photo:hover .chapeau,
.cadre--photo:hover .vedette .texte,
.cadre--photo:focus-within .chapeau,
.cadre--photo:focus-within .vedette .texte {
  -webkit-mask-position: 0 0;
  mask-position: 0 0;
  transition: mask-position var(--photo-balai), -webkit-mask-position var(--photo-balai);
}

/* La languette reste dans son coin et suit le panneau. */
.cadre--photo .lire-suite {
  opacity: 0;
  transition: opacity 200ms linear 140ms;
}
.cadre--photo:hover .lire-suite,
.cadre--photo:focus-within .lire-suite { opacity: 1; }

/* Sur un ecran tactile, le panneau reste FERME et la carte entiere
   devient cliquable — voir la fin de la feuille, section « LA
   VEDETTE TACTILE ».

   Il etait ouvert d'office ici avant, pour que rien ne soit
   inatteignable au doigt. Mais un panneau ouvert cache la photo,
   et sur un telephone c'est elle qui occupe l'ecran. */

/* Quelqu'un qui a demande moins d'animation ne recoit pas de
   glissement — le panneau change d'etat, sans transition. */
@media (prefers-reduced-motion: reduce) {
  .cadre--photo .vedette__corps,
  .cadre--photo .chapeau,
  .cadre--photo .vedette .texte,
  .cadre--photo .lire-suite { transition: none; }
  .cadre--photo .chapeau,
  .cadre--photo .vedette .texte {
    -webkit-mask-image: none;
    mask-image: none;
  }
}


/* — Le fil, en panneau —————————————————————————————— */

.cadre--fil {
  display: flex;
  flex-direction: column;
  border: 0;
  padding: 1px;
  background: var(--filet2);
  clip-path: polygon(18px 0, 100% 0, 100% calc(100% - 18px),
                     calc(100% - 18px) 100%, 0 100%, 0 18px);
}
/* Onglet coupé à 45° dans le coin supérieur gauche. */
.fil-tete {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  min-height: 2.5rem;
  padding: 0.375rem 0.9375rem;
  background: var(--bande-fond);
  border-bottom: 1px solid var(--bande-bord);
  clip-path: polygon(17px 0, 100% 0, 100% 100%, 0 100%, 0 17px);
  font-family: var(--donnees);
  font-size: 0.75rem;
  font-weight: 400;
  letter-spacing: 0;
  text-transform: uppercase;
  color: var(--bande-etiquette);
}
.fil-tete a:hover { color: var(--bande-valeur); }

.fil-liste {
  flex: 1;
  min-height: 0;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  padding: 0 0.9375rem;
  background: var(--cadre-fond);
  touch-action: pan-y;
  clip-path: polygon(0 0, 100% 0, 100% calc(100% - 17px),
                     calc(100% - 17px) 100%, 0 100%);
}

.note-fil {
  flex: 1;
  min-height: 0;
  display: flex;
  flex-direction: column;
  justify-content: center;
  padding: 0.5rem 0;
  border-bottom: 1px solid var(--filet);
}
.note-fil:last-child { border-bottom: 0; }
.note-fil__meta {
  font-family: var(--donnees);
  font-size: 0.6875rem;
  color: var(--faible);
  margin-bottom: 0.4375rem;
}
.note-fil__meta .s { color: var(--filet2); margin: 0 0.4375rem; }
.note-fil__t {
  font-family: var(--sans);
  font-size: 1.0625rem;
  line-height: 1.35;
  color: var(--corps);
  margin: 0;
  /* Trois lignes maximum : une note trop longue ne doit pas
     déformer la case qu'elle occupe. */
  display: -webkit-box;
  -webkit-line-clamp: 3;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.note-fil__t b { color: var(--titre); font-weight: 600; }
/* Le fil se lit d'un coup d'oeil, pas en continu : son texte
   prend l'os plein plutot que le gris du corps. */
.note-fil__t { color: var(--os); }
/* Pas de liseré d'équipe ni de lueur : une note peut concerner
   plusieurs équipes, et une animation permanente finit par
   distraire plus qu'elle n'anime. */

/* — Les pastilles ——————————————————————————————————— */

.pastilles { display: flex; justify-content: center; gap: 0.5rem; padding: 0.875rem 0 0; }
.pastille {
  width: 8px; height: 8px; padding: 0;
  border: 0; border-radius: 50%;
  background: var(--filet2);
  cursor: pointer;
  transition: background var(--glisse), transform var(--glisse);
}
.pastille:hover { background: var(--attenue); }
.pastille.actif { background: var(--ambre); transform: scale(1.25); }

/* — Le filtre ————————————————————————————————————— */

.filtre { position: relative; margin-left: auto; display: flex; align-items: center; gap: 0.625rem; }
/* Même police, même corps, même interlettrage que les
   métadonnées de la barre d'entrée. */
.filtre__mot {
  font-family: var(--donnees);
  font-size: 0.75rem;
  letter-spacing: 0;
  text-transform: uppercase;
  color: var(--faible);
}
.filtre__declencheur {
  display: inline-flex;
  align-items: center;
  justify-content: space-between;
  gap: 1.25rem;
  background: var(--surface2);
  border: 1px solid var(--filet2);
  color: var(--nav);
  font-family: var(--sans);
  font-size: 1.0625rem;
  text-transform: uppercase;
  /* Même distance à gauche et à droite : le texte et la flèche
     sont à égale distance du cadre. Le décalage de 0,15em relève
     le texte de Teko au centre optique, comme la bascule et le
     bouton EMBARQUE; retiré en bas pour ne pas grandir la boîte. */
  padding: calc(0.53rem + 0.1em) 0.75rem calc(0.53rem - 0.1em);
  line-height: 1;
  /* Largeur fixe, calée sur « Toutes les équipes » : la boîte ne
     doit pas changer de taille selon la sélection. */
  width: 10.75rem;
  cursor: pointer;
  transition: color var(--glisse), border-color var(--glisse);
}
.filtre__fleche { flex-shrink: 0; }
#filtre-etiquette { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.filtre__declencheur:hover,
.filtre__declencheur[aria-expanded="true"] {
  color: var(--nav-survol); border-color: var(--nav-survol);
}
.filtre__menu {
  position: absolute; top: calc(100% + 0.375rem); right: 0; z-index: 25;
  min-width: 15rem; max-height: 22rem; overflow-y: auto;
  background: var(--surface); border: 1px solid var(--filet2);
  box-shadow: 0 14px 34px rgba(0,0,0,.45);
  padding: 0.25rem 0;
}
.filtre__menu[hidden] { display: none; }
.filtre__menu button {
  display: flex; align-items: center; gap: 0.625rem;
  width: 100%; text-align: left;
  background: none; border: 0; border-left: 2px solid transparent;
  color: var(--corps);
  font-family: var(--sans); font-size: 1.0625rem;
  padding: 0.4375rem 0.9375rem; cursor: pointer;
}
.filtre__menu button:hover { background: var(--surface2); color: var(--titre); }
.filtre__menu button.actif { border-left-color: var(--ambre); color: var(--titre); }

/* — La boite de saison (v70) ————————————————————————
   LE MUR, puis LE BILAN. Le DESSIN est celui du filtre de l'accueil
   (« filtre__declencheur », « filtre__menu », « filtre__mot ») :
   le lecteur apprend le geste une fois. Ce qui suit n'ajuste que la
   position — l'enveloppe « saisons » est a elle, et accueil.js ne
   la connait pas. */
.saisons { display: flex; align-items: center; gap: 0.625rem; }
/* Le menu se cale sous le BOUTON, pas sous le mot « Saison », et
   prend exactement sa largeur : quelques saisons, pas trente-deux
   equipes. */
.saisons__boite { position: relative; }
.saisons .filtre__menu { left: 0; right: auto; min-width: 0; width: 100%; }
.saisons__etiquette { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* SUR LE MUR (demande de l'auteur) : « Saison » AU-DESSUS de la
   boite, et la boite plus etroite, centree sous le mot — tout sur
   l'axe des boucliers. Sept caracteres a afficher, pas les dix-huit
   de « Toutes les équipes ». Le Bilan garde la disposition en ligne. */
.mur32__barre .saisons { flex-direction: column; gap: 0.4375rem; }
.mur32__barre .saisons__declencheur { width: 8.5rem; }
/* SUR LE BILAN : la boite prend la place du titre « Saison
   2026-27 », a gauche, et le bulletin reste a droite. Le titre ne
   sert plus qu'a qui n'a pas de script — et la boite, inversement,
   ne sert a rien sans script. */
.js .bilan__titre { display: none; }
html:not(.js) .bilan__saison .saisons { display: none; }
.bilan__saison .tete-section { align-items: center; }
.bilan__saison .saisons__declencheur { width: 8.5rem; }
.bilan__vide { margin-top: 2.5rem; }

/* Le champ de recherche d'une page de rubrique. Il prend la
   place que la mention de droite occupait, et reprend trait pour
   trait la boite du filtre de l'accueil : meme fond, meme filet,
   meme fonte, meme largeur, meme decalage optique de Teko. */
/* La ligne s'aligne sur les lignes de base, mais un champ de
   saisie ne pose pas la sienne au meme endroit qu'un bouton : il
   tombait 4,5 px plus bas que le filtre de l'accueil. On le
   remonte d'autant pour que les deux couples titre/boite se
   ressemblent d'une page a l'autre. */
.recherche {
  display: flex;
  align-items: center;
  gap: 1.25rem;
  margin-left: auto;
  position: relative;
  top: -0.5px;
}

.recherche input {
  display: inline-flex;
  align-items: center;
  background: var(--surface2);
  border: 1px solid var(--filet2);
  border-radius: 0;
  /* Le mot tape s'ecrit a l'encre pleine; c'est l'invite, elle,
     qui reste dans le gris du menu. */
  color: var(--titre);
  font-family: var(--sans);
  font-size: 1.0625rem;
  text-transform: uppercase;
  padding: calc(0.53rem + 0.1em) 0.75rem calc(0.53rem - 0.1em);
  /* Un champ de saisie tire sa hauteur des metriques de la
     police, pas de l'interligne : il faisait 46 px la ou le
     filtre en fait 38. On la lui impose, ecrite avec les memes
     valeurs que le rembourrage et la taille du texte, pour que
     les deux boites restent liees si l'echelle change. */
  line-height: 1;
  height: calc(0.53rem * 2 + 1.0625rem + 2px);
  width: 10.75rem;
  box-sizing: border-box;
  appearance: none;
  transition: color var(--glisse), border-color var(--glisse);
}
.recherche input::placeholder { color: var(--nav); opacity: 1; }
.recherche input:hover,
.recherche input:focus { border-color: var(--nav-survol); }
.recherche input:focus { outline: none; }
.recherche input:focus::placeholder { color: transparent; }

/* La croix qui vide le champ. Celle du navigateur est bleue et
   ne se colore pas : on la remplace par un dessin qu'on peint
   soi-meme, en ambre — #877B66 en foncé, #595143 sur papier. */
.recherche input::-webkit-search-cancel-button {
  -webkit-appearance: none;
  appearance: none;
  width: 0.6875rem;
  height: 0.6875rem;
  cursor: pointer;
  background-color: var(--ambre);
  -webkit-mask: var(--croix) center / contain no-repeat;
  mask: var(--croix) center / contain no-repeat;
}
.recherche input::-webkit-search-cancel-button:hover {
  background-color: var(--nav-survol);
}

/* Le compte se tient a gauche de la boite, dans la fonte des
   donnees comme toutes les mentions du site. */
.recherche__etat {
  font-family: var(--donnees);
  font-size: 0.6875rem;
  letter-spacing: .1em;
  color: var(--service);
  white-space: nowrap;
}
/* La ligne s'aligne sur les lignes de base, et celle du bloc de
   recherche est empruntee a son premier element — le compte.
   Vide, il n'en a aucune a donner, et le titre de saison sautait
   de 4 px des qu'un resultat s'affichait. Un espace de largeur
   nulle lui en donne une en permanence, sans rien montrer. */
.recherche__etat::after { content: "\200B"; }


/* Le bandeau d'une page de rubrique. Il se redimensionne dans
   les deux sens et garde son rapport : rien n'est jamais rogne.
   Il se cale sur la largeur du tableau, pas sur celle de l'ecran
   — sinon son rapport passerait de 4,5:1 a 11,8:1 sur un grand
   ecran, et aucun montage ne survit a ca. */
/* L'enveloppe porte le filet. Une bordure posee sur l'image se
   ferait couper par le biseau — c'est le piege nº 13, deja
   rencontre sur les etiquettes et le signet. Le FOND fait donc le
   trait, et l'image posee un pixel a l'interieur le laisse
   paraitre sur tout le pourtour, biseaux compris. */
.bandeau-cadre {
  /* Les deux ecarts sont repris de l'accueil : au-dessus, la
     distance qui separe le ruban du titre « DERNIÈRE PUBLICATION »
     (1,375 rem); en dessous, celle qui separe l'encadre de la
     vedette du titre « REGISTRE RÉCENT » (0,955 rem). */
  margin: 1.4632rem 0 1.25rem;
  padding: 1px;
  background: var(--filet2);
  clip-path: polygon(0 0, calc(100% - 18px) 0, 100% 18px,
                     100% 100%, 18px 100%, 0 calc(100% - 18px));
}

.bandeau-rubrique {
  display: block;
  width: 100%;
  height: auto;
  /* Un pixel de moins que l'enveloppe : c'est ce qui laisse le
     filet paraitre dans les biseaux. */
  clip-path: polygon(0 0, calc(100% - 17px) 0, 100% 17px,
                     100% 100%, 17px 100%, 0 calc(100% - 17px));
}


/* ═══ 20c. LE MUR ═════════════════════════════════════════════
   Trente-deux boucliers, gris tant qu'aucune chronique n'a parle
   de l'equipe. La lumiere ne vient pas d'une lampe dessinee : elle
   descend du bandeau d'en-tete, comme si la page entiere etait
   eclairee d'en haut. C'est une texture de fond, pas un decor.  */

.mur32__barre {
  display: flex;
  /* ⚠ EN COLONNE (v70) : la boite de saison au-dessus, le compteur
     en dessous, tous deux centres sur l'axe des boucliers. */
  flex-direction: column;
  gap: 0.875rem;
  align-items: center;
  justify-content: center;
  margin-top: 1.75rem;
}
.mur32__compte {
  font-family: var(--donnees);
  font-size: 0.6875rem;
  letter-spacing: .12em;
  color: var(--service);
}
.mur32__compte b { color: var(--titre); font-weight: 700; }

/* La scene n'a ni bord ni fond : seule la lumiere la distingue,
   et elle s'eteint bien avant les bords. Aucun rectangle a
   reperer. */
.mur32__scene {
  position: relative;
  margin-top: 2.25rem;
  padding-top: 2rem;
  isolation: isolate;
}

/* — La lumiere ————————————————————————————————————
   Une seule couche, tres large, tres pale, ancree en haut au
   centre. Elle deborde de la colonne de contenu pour que sa
   limite tombe hors de l'ecran. */
/* La page du mur porte la lumiere : elle doit donc etre le repere
   de son positionnement. Elle ne cree PAS de contexte
   d'empilement — sinon le halo, renvoye derriere, disparaitrait
   sous le fond de la page. */
.page--mur { position: relative; }

.mur32__lumiere {
  position: absolute;
  /* Zero : la lumiere demarre exactement sous le bandeau, quelle
     que soit la longueur du texte d'introduction. */
  top: 0;
  left: 50%;
  transform: translateX(-50%);
  width: 190vw;
  max-width: 2600px;
  height: 74rem;
  /* Sous le texte, pas dessus : a « z-index: 0 » le halo etait un
     element positionne, donc il passait par-dessus le titre et
     l'introduction, qui sont en flux normal — et il en teintait
     l'encre. Une valeur negative le renvoie derriere. */
  z-index: -1;
  pointer-events: none;
  background:
    radial-gradient(40% 52% at 50% 0%,
      rgba(255, 244, 220, .16) 0%,
      rgba(255, 244, 220, .07) 36%,
      rgba(255, 244, 220, .02) 64%,
      transparent 100%),
    radial-gradient(14% 20% at 50% 0%,
      rgba(255, 246, 226, .17) 0%, transparent 100%);
}

/* — Les boucliers : 9-8-9-6 ————————————————————————
   Dix-huit colonnes, deux par bouclier. Les rangees decalees se
   posent avec un depart explicite; les autres suivent toutes
   seules. */
.mur32 {
  display: grid;
  grid-template-columns: repeat(18, 1fr);
  column-gap: 0.5rem;
  row-gap: 1.25rem;
  position: relative;
  z-index: 2;
  padding-bottom: 2rem;
}
.mur32__case {
  grid-column: span 2;
  position: relative;
  transition: transform var(--glisse);
}
/* Rangee 2 : huit boucliers, decales d'une demi-case. */
.mur32__case:nth-child(10) { grid-column: 2 / span 2; }
/* Rangee 3 : neuf, alignes comme la premiere. */
.mur32__case:nth-child(18) { grid-column: 1 / span 2; }
/* Rangee 4 : six, centres. */
.mur32__case:nth-child(27) { grid-column: 4 / span 2; }

.mur32__case img {
  width: 100%; height: auto; display: block;
  filter: drop-shadow(0 5px 12px rgba(0, 0, 0, .55));
}
.mur32__case:hover { transform: translateY(-5px); }

/* Le code d'equipe, grave sur le bouclier. Provisoire : il
   disparaitra quand les boucliers porteront leur logo. */
.mur32__code {
  position: absolute; left: 0; right: 0; top: 41%;
  text-align: center; pointer-events: none;
  font-family: var(--etiquette);
  font-weight: 700;
  font-size: 0.8125rem;
  letter-spacing: .05em;
  color: rgba(58, 58, 52, .78);
  text-shadow: 0 1px 0 rgba(255, 255, 255, .3);
}
.est-allume .mur32__code {
  color: rgba(92, 68, 12, .8);
  text-shadow: 0 1px 0 rgba(255, 238, 190, .45);
}

/* — L'allumage —————————————————————————————————————
   La lumiere hesite deux fois avant de tenir. */
@keyframes mur-scintille {
  0%, 7%    { opacity: 0; }
  9%        { opacity: 1; }
  11%       { opacity: .15; }
  14%       { opacity: .9; }
  17%       { opacity: .2; }
  22%, 100% { opacity: 1; }
}
/* Le delai laisse le temps d'arriver sur la page et de la voir
   eteinte avant que la lumiere ne se decide. */
.js .mur32__lumiere { animation: mur-scintille 2.6s ease-out 1.5s both; }

/* L'or ne se revele qu'a l'allumage. Les boucliers gris, eux,
   sont la des la premiere image : ce n'est pas le mur que la
   lumiere fait apparaitre, c'est ce qu'on y a accompli.

   Le meme geste fonctionne sur papier comme sur charbon — une
   couleur qui arrive se voit sur n'importe quel fond, contrairement
   a une lumiere. */
.mur32__or {
  position: absolute;
  inset: 0;
  z-index: 2;
}
.js .mur32__or {
  opacity: 0;
  animation: mur-scintille 2.6s ease-out 1.5s both;
}

/* ⚠ CHANGER DE SAISON REJOUE L'ALLUMAGE (v70), sans l'attente du
   chargement : le lecteur vient de cliquer, il regarde deja. Le
   script retire et repose les animations; cette classe n'en change
   que le delai. */
.mur32--rejoue .mur32__lumiere,
.mur32--rejoue .mur32__or { animation-delay: 0.15s; }

@media (max-width: 900px) {
  /* Sous 900 px, la pyramide devient une grille de six : a neuf
     par rangee, les boucliers seraient illisibles. */
  .mur32 { grid-template-columns: repeat(6, 1fr); }
  .mur32__case,
  .mur32__case:nth-child(10),
  .mur32__case:nth-child(18),
  .mur32__case:nth-child(27) { grid-column: auto; }
}

@media (prefers-reduced-motion: reduce) {
  /* Sans mouvement, l'or est simplement la des le depart. */
  .js .mur32__lumiere, .js .mur32__or { animation: none; opacity: 1; }
  .mur32__case:hover { transform: none; }
}


/* ═══ 20d. LES ETIQUETTES ET PASTILLES DESSINEES ══════════════
   Quand une equipe a son etiquette ou sa pastille, l'image
   remplace le code en trois lettres. Le code reste dans le HTML,
   cache : lecteurs d'ecran, « Ctrl+F » et index de recherche le
   trouvent toujours.                                          */

/* Le code, quand une image le recouvre. Il occupe zero pixel mais
   reste lisible par les machines — la meme technique que le lien
   « aller au contenu ». */
.mur__note--rond--image > i {
  position: absolute;
  width: 1px; height: 1px;
  margin: -1px; padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

/* — Le jeton carre ————————————————————————————————
   La meme image que les ronds du fil, mais biseautee. Elle sert
   partout ou la place ne manque pas : registre, fiche de joueur,
   duel, transactions. Le logo y tient EN ENTIER, ce qu'un cadre
   allonge ne permet jamais a un dessin carre.

   Comme pour l'etiquette, c'est le fond qui fait le filet et
   l'image posee un pixel a l'interieur qui le laisse paraitre.
   Aucun « overflow » ici : il couperait ce pixel. */
/* La cellule qui porte un jeton se resserre a 8 px en haut et en
   bas. Le jeton fait 53 px alors que le reste de la rangee en
   demande 52 : sans ce resserrement, c'est LUI qui dictait la
   hauteur de toutes les rangees du registre, qui passaient de 82
   a 95 px. */
.registre__eq:has(.code--jeton) { padding-top: 8px; padding-bottom: 8px; }

.code--jeton {
  position: relative;
  display: inline-block;
  padding: 1px;
  /* Dans la tete d'une fiche, le jeton est un element flexible a
     cote du nom du joueur. Sans ceci, le nom le comprimait en
     LARGEUR pendant que sa hauteur restait fixe : le carre
     devenait un rectangle debout, et le logo s'etirait avec lui.

     Ca n'apparaissait qu'a l'etroit — donc jamais sur l'ecran de
     l'auteur. */
  flex-shrink: 0;
  /* « .code » impose 52 x 22 px en dur; il faut reprendre les deux
     ou le jeton sort ecrase. */
  /* Carre, comme l'image qu'il porte : rien n'est recadre, le logo
     tient en entier. C'est tout l'interet de cette forme-ci face a
     l'etiquette allongee. */
  width: 3.5rem;
  height: 3.5rem;
  line-height: 0;
  /* Le filet du jeton a SON PROPRE jeton. Il ne peut pas suivre
     « --titre » : celui-la vaut l'encre sur papier, mais l'OS sur
     charbon — le filet devenait alors clair, ce qui est l'inverse
     de ce qu'on veut.

     Sur charbon il se confond avec le fond et disparait, c'est
     voulu. Sur papier il detache le jeton, dans la meme
     temperature que l'encre. */
  background: var(--jeton-filet);
  /* Biseaux plus francs : a 6 px ils se confondaient avec un coin
     arrondi. */
  clip-path: polygon(0 0, calc(100% - 11px) 0, 100% 11px,
                     100% 100%, 11px 100%, 0 calc(100% - 11px));
}
.code--jeton img {
  display: block;
  width: 100%;
  height: 100%;
  clip-path: polygon(0 0, calc(100% - 10px) 0, 100% 10px,
                     100% 100%, 10px 100%, 0 calc(100% - 10px));
}
.code--jeton > i {
  position: absolute;
  width: 1px; height: 1px;
  margin: -1px; padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}


/* — La pastille ————————————————————————————————————
   L'image remplit le rond; le filet aux couleurs de l'equipe reste
   pose par la feuille, comme sur les pastilles en texte. */
.mur__note--rond--image {
  position: relative;
  padding: 0;
  background: none;
  overflow: hidden;
}
.mur__note--rond--image img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  border-radius: 50%;
}


/* ═══ 20e. LA PAGE D'ATTENTE ══════════════════════════════════
   La porte d'entree avant le lancement. Pas de menu, pas de ruban,
   pas de pied : une porte n'a pas de mobilier. Tout est centre sur
   une colonne etroite, et la lumiere descend du haut comme sur Le
   mur.                                                         */

.page--attente {
  position: relative;
  min-height: 100vh;
  min-height: 100dvh;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 3rem var(--marge-laterale);
}

.attente {
  position: relative;
  z-index: 2;
  width: 100%;
  max-width: 32rem;
  text-align: center;
}

/* La meme lumiere que Le mur, en plus resserree. Elle deborde
   largement pour que sa limite tombe hors de l'ecran. */
.attente__lumiere {
  position: absolute;
  top: -22rem;
  left: 50%;
  transform: translateX(-50%);
  width: 180vw;
  max-width: 2200px;
  height: 60rem;
  z-index: -1;
  pointer-events: none;
  background:
    radial-gradient(38% 48% at 50% 0%,
      rgba(255, 244, 220, .13) 0%,
      rgba(255, 244, 220, .05) 38%,
      rgba(255, 244, 220, .015) 66%,
      transparent 100%);
}
html[data-theme="clair"] .attente__lumiere {
  background:
    radial-gradient(38% 48% at 50% 0%,
      rgba(90, 82, 66, .10) 0%,
      rgba(90, 82, 66, .04) 38%,
      transparent 100%);
}

.attente__logo {
  display: block;
  width: 4.5rem;
  height: 4.5rem;
  margin: 0 auto 1.75rem;
}

/* Le nom sur deux lignes, comme le mot-symbole de l'en-tete : la
   premiere en os, la seconde en ambre. */
.attente__nom {
  font-family: var(--sans);
  font-weight: 700;
  font-size: 3.25rem;
  line-height: .95;
  letter-spacing: .01em;
  text-transform: uppercase;
  color: var(--titre);
  margin: 0;
  /* Teko porte sa masse en haut de sa ligne. */
  padding-top: 0.08em;
}
.attente__nom span { color: var(--ambre); }

.attente__manifeste {
  font-family: var(--lecture);
  font-size: 1.125rem;
  line-height: 1.55;
  color: var(--attenue);
  margin: 1.25rem auto 0;
  max-width: 24rem;
}

/* Un filet qui s'efface aux deux bouts, comme ceux de l'en-tete
   large. */
.attente__filet {
  height: 1px;
  margin: 2.25rem auto;
  max-width: 18rem;
  background: linear-gradient(90deg,
    transparent, var(--filet2) 22%, var(--filet2) 78%, transparent);
}

/* Deux lignes : la mention au-dessus, la date en dessous et plus
   grosse. C'est la date qu'on retient, pas l'etiquette. */
.attente__date {
  font-family: var(--donnees);
  font-size: 0.625rem;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--service);
  margin: 0;
  line-height: 1.9;
}
.attente__date b {
  display: block;
  font-size: 0.875rem;
  letter-spacing: .1em;
  color: var(--titre);
  font-weight: 700;
}

.attente__promesse {
  font-family: var(--lecture);
  font-size: 1rem;
  line-height: 1.6;
  color: var(--attenue);
  margin: 1.5rem auto 0;
  /* Assez large pour que les trois lignes du texte tiennent chacune
     sur une seule ligne d'ecran. La plus longue fait 62 caracteres. */
  max-width: 34rem;
}

.attente__form {
  margin: 2.25rem auto 0;
  justify-content: center;
}

.attente__fin {
  font-family: var(--donnees);
  font-size: 0.625rem;
  letter-spacing: .1em;
  line-height: 1.9;
  color: var(--service);
  margin: 1.125rem 0 0;
}

@media (max-width: 560px) {
  .attente__nom { font-size: 2.5rem; }
  .attente__logo { width: 3.5rem; height: 3.5rem; }
}


/* ═══ 20f. LE BILAN ═══════════════════════════════════════════
   Une checklist des affirmations, groupee par saison. Elle reprend
   la typographie du registre des rubriques : meme ligne de titres,
   memes dates, memes titres d'article. C'est la meme table de
   donnees vue sous un autre angle.

   Quatre colonnes : le bouton, la date, l'article, le verdict.
   L'affirmation occupe la ligne du dessous, sous l'article. */

/* Le titre de saison touche sa table, exactement comme dans le
   registre des rubriques : l'ecart y est de zero. */
.bilan__saison { margin-top: 2.75rem; }

/* — Le bulletin de la saison ————————————————————————
   La note encerclee, puis le compte. Les deux se calent sur la
   colonne du verdict : ils resument exactement les cases situees
   en dessous.

   La tete de section est un conteneur souple, pas une grille : on
   pousse donc le bulletin a droite et on lui donne la largeur ET
   le rembourrage de la colonne du verdict. */
/* Pose en absolu, cale sur le bas de la tete de section : le
   compte se retrouve ainsi sur la ligne du titre, et la note
   deborde vers le haut sans pousser le tableau. */
.bilan__bulletin {
  position: absolute;
  /* Cale pour que le COMPTE tombe pile sur la colonne du verdict.
     La marge de 2 rem qui decale le compte vers la droite est
     compensee ici : 0,9375 pour le rembourrage de la colonne,
     moins la moitie de ce decalage. */
  right: calc(0.9375rem + 0.875rem);
  /* 11 px au-dessus du tableau : la meme respiration que le titre
     a cote. */
  bottom: 11px;
  width: 5.5rem;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0;
}

/* La note et son cercle. Le cercle deborde largement de la lettre —
   c'est un geste, pas un cadre.

   « bilan__grade » et non « bilan__note » : cette derniere est
   deja la note d'explication d'une ligne, et son filet ambre
   venait se dessiner en travers du cercle. Piege nº 44. */
.bilan__grade {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 5.5rem;
  height: 5.5rem;
}
.bilan__lettre {
  font-family: var(--main-gras);
  /* Le double de sa taille d'origine : la note est le point
     d'arrivee de la page, elle doit se voir de loin. */
  font-size: 4.25rem;
  line-height: 1;
  /* Caveat Brush s'assoit haut dans sa ligne. */
  position: relative;
  top: 0.06em;
}
/* Le cercle est une image posee en MASQUE : sa forme decoupe un
   aplat de « currentColor ». Une seule image sert donc aux trois
   teintes, et le trace garde toute sa matiere de pinceau. */
.bilan__cercle {
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: currentColor;
  -webkit-mask-image: url("/images/verdicts/cercle.webp");
  mask-image: url("/images/verdicts/cercle.webp");
  -webkit-mask-size: contain;
  mask-size: contain;
  -webkit-mask-repeat: no-repeat;
  mask-repeat: no-repeat;
  -webkit-mask-position: center;
  mask-position: center;
}

/* Les couleurs des MARQUES, relevees dans les images elles-memes :
   la lettre doit etre du meme vert que les crochets et du meme
   rouge que les croix. Elles ne changent donc pas avec le theme —
   les images non plus.

   Le jaune n'a pas d'image de reference; il est choisi dans la
   meme famille : sature, franc, sans gris. */
.bilan__bulletin--haut  { color: #17B900; }
.bilan__bulletin--moyen { color: #E8A800; }
.bilan__bulletin--bas   { color: #C4000E; }

.bilan__compte {
  /* Au-dessus de la note, et decale a droite : c'est lui qui
     recouvre le bas du cercle. */
  position: relative;
  z-index: 2;
  margin-left: 2rem;
  /* Il remonte pour recouvrir le bas du cercle. */
  margin-top: -0.7rem;
  font-family: var(--main);
  font-size: 1.75rem;
  font-weight: 600;
  line-height: 1;
  letter-spacing: .01em;
  color: var(--section-titre);
  white-space: nowrap;
  /* Caveat s'assoit haut dans sa ligne. */
  position: relative;
  top: 0.11em;
}
.bilan__compte b { font-weight: 600; }

/* — L'arrivee de la note ————————————————————————————
   La lettre parait une fois tous les verdicts tombes, puis le
   cercle se trace autour d'elle comme l'aiguille d'un cadran.

   Le trait est un pointille dont on efface le vide : c'est la
   technique de l'arc du site, deja eprouvee. */
.js .bilan__grade { opacity: 0; }
.js .bilan__saison:has(.bilan__store.vu) .bilan__grade {
  animation: bilan-note 200ms cubic-bezier(.2, .9, .3, 1)
             var(--apres-verdicts, 2200ms) both;
}
/* L'etampe : la lettre arrive trop grosse et se pose d'un coup.
   C'est le geste d'un tampon — l'inverse du rebond des marques,
   qui elles partent de rien. */
@keyframes bilan-note {
  from { opacity: 0; transform: scale(1.9); }
  55%  { opacity: 1; }
  to   { opacity: 1; transform: scale(1); }
}

/* 262 : la longueur reelle du trace, mesuree. Un chiffre trop
   court laisserait un bout de cercle deja visible au depart. */
/* Le devoilement en cadran.

   DEUX couches, et il en faut deux : poser les deux masques sur le
   meme element ne marche pas — les couches de masque s'ADDITIONNENT
   par defaut, et le degrade conique laissait donc voir un carre
   plein. L'enveloppe porte l'aiguille, l'element interieur porte
   la forme du cercle.

   « --tour » se met a jour parce qu'il est declare : une propriete
   personnalisee ordinaire ne s'anime pas, elle saute d'une valeur
   a l'autre. */
@property --tour {
  syntax: '<angle>';
  initial-value: 0deg;
  inherits: false;
}
.bilan__cadran {
  position: absolute;
  inset: -16%;
  width: 132%;
  height: 132%;
  pointer-events: none;
}
.js .bilan__cadran {
  --tour: 360deg;
  /* « from 60deg » place le depart vers deux heures. L'angle
     negatif fait tourner l'aiguille dans le sens ANTIHORAIRE —
     c'est le geste naturel d'un droitier qui encercle. */
  -webkit-mask-image: conic-gradient(from 60deg, transparent var(--tour), #000 0);
  mask-image: conic-gradient(from 60deg, transparent var(--tour), #000 0);
}
.js .bilan__saison:has(.bilan__store.vu) .bilan__cadran {
  animation: bilan-encercle 700ms cubic-bezier(.35, 0, .25, 1)
             calc(var(--apres-verdicts, 2200ms) + 240ms) both;
}
@keyframes bilan-encercle {
  from { --tour: 360deg; }
  to   { --tour: -12deg; }
}

@media (prefers-reduced-motion: reduce) {
  .js .bilan__grade { opacity: 1; animation: none; }
  .js .bilan__cadran { --tour: -12deg; animation: none; }
}

/* — La ligne de titres, celle du registre ——————————— */
/* La ligne de titres reprend celle du registre : meme fond, meme
   hauteur, meme filet. Les cellules y sont centrees verticalement,
   d'ou « align-items: center » plutot que la ligne de base. */
.bilan__tete {
  display: grid;
  grid-template-columns: 4.25rem 8rem 1fr auto;
  align-items: center;
  gap: 0 1rem;
  min-height: 2.5625rem;
  padding: 0 0.9375rem;
  background: var(--bande-fond);
  border-bottom: 1px solid var(--filet2);
  font-family: var(--etiquette);
  font-size: 0.75rem;
  font-weight: 700;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--bande-etiquette);
}
/* Les deux premieres colonnes centrees, l'affirmation a gauche, le
   verdict a droite — l'ordre du registre. */
.bilan__tete span:nth-child(1),
.bilan__tete span:nth-child(2) { justify-self: center; }
.bilan__tete span:nth-child(4) {
  width: 5.25rem;
  text-align: center;
}

/* — Le store ————————————————————————————————————————
   Les lignes sortent de sous la ligne de titres, une par une,
   comme une feuille qu'on tire d'un dossier.

   L'enveloppe coupe ce qui n'est pas encore descendu. Elle reserve
   30 px de chaque cote et en bas — la marge que les marques
   debordent de leur case — et ne coupe donc QUE par le haut.
   Sans ca, les crochets se feraient trancher. */
.bilan__store {
  overflow: hidden;
  padding: 0 30px 30px;
  margin: 0 -30px -30px;
}

/* ── LE RYTHME DE LA PAGE ──────────────────────────────────
   Les six chiffres qui décident du tempo. Ils vivent ICI et
   nulle part ailleurs : « theme.js » vient les lire au lieu de
   les redire. Changer le tempo de la page, c'est changer ces
   six lignes — le script suit tout seul.

   AVANT, le compte était écrit une deuxième fois dans le
   script, et il partait toujours à 1,5 s. En arrivant d'une
   autre page, le store s'ouvrait immédiatement mais le compte
   attendait quand même : il montait une seconde et demie en
   retard sur ses crochets. C'est le piège nº 64. */
.page--bilan {
  /* Le temps mort avant que le store s'ouvre.

     Au CHARGEMENT DIRECT, il faut d'abord laisser passer la
     cascade d'ouverture — 1,5 s — sinon les lignes descendent
     derrière le voile de la page (piège nº 58). Le demi-seconde
     de plus est du confort : à 1,5 s pile, le geste commence
     avant que l'oeil soit arrivé sur la table. */
  --bilan-attente: 2000ms;

  /* En arrivant d'une AUTRE page, il n'y a pas de cascade : la
     page a glissé, c'est tout. Il faut quand même un temps mort,
     sinon le store joue pendant que la page est encore en
     mouvement — et on le manque. */
  --bilan-attente-glisse: 450ms;

  /* Les verdicts, après l'ouverture du store : un bon demi-
     seconde après que la dernière ligne se soit posée. */
  --verdict-depart: 1200ms;
  --verdict-pas:    130ms;

  /* Le chiffre du compte bouge un peu APRÈS sa marque : la
     marque met 420 ms à se poser, on attend qu'elle soit
     lisible avant de créditer le point. */
  --compte-retard:  200ms;

  /* La note lettrée arrive après le dernier verdict. */
  --note-apres:     700ms;
}

.bilan { list-style: none; margin: 0; padding: 0; }

/* Aucun survol ici — c'est voulu. Un surlignement qui suit la
   souris rappelle qu'on est devant un ecran; cette page doit se
   lire comme une copie corrigee, posee sur une table. */
.bilan__l {
  /* L'etat de depart : la ligne est remontee sous celle du dessus,
     donc hors du champ de l'enveloppe. Il ne s'applique que si le
     script tourne — sans lui, tout est en place. */
  display: grid;
  grid-template-columns: 4.25rem 8rem 1fr auto;
  /* Tout tient sur une ligne : c'est le milieu des elements qu'on
     aligne, pas leur ligne de base. */
  align-items: center;
  gap: 0.3125rem 1rem;
  padding: 1.0625rem 0.9375rem;
  border-bottom: 1px solid var(--filet);
}

.js .bilan__store .bilan__l {
  transform: translateY(-100%);
  opacity: 0;
}
.js .bilan__store.vu .bilan__l {
  animation: bilan-descend 520ms cubic-bezier(.24, .8, .3, 1)
             calc(var(--rang, 0) * 85ms) both;
}
@keyframes bilan-descend {
  from { transform: translateY(-100%); opacity: 0; }
  60%  { opacity: 1; }
  to   { transform: translateY(0); opacity: 1; }
}

/* — Le rebond ————————————————————————————————————————
   Une fois la liste descendue, les verdicts arrivent l'un apres
   l'autre. La marque part de rien, DEPASSE sa taille, puis revient
   se poser.

   Le sens compte : partir trop gros et retrecir donnait
   l'impression d'une image qui finit de charger. Partir de rien et
   depasser donne un geste — quelque chose qu'on pose.

   Elle demarre 1,2 s apres l'ouverture du store, soit un bon demi-
   seconde apres que la derniere ligne se soit posee. */
.js .bilan__store .bilan__marque { opacity: 0; }
.js .bilan__store.vu .bilan__marque {
  animation: bilan-rebond 420ms cubic-bezier(.3, 1.35, .5, 1)
             calc(var(--verdict-depart) + var(--rang, 0) * var(--verdict-pas)) both;
}
@keyframes bilan-rebond {
  from { opacity: 0; transform: var(--pose) scale(.2); }
  35%  { opacity: 1; }
  62%  { transform: var(--pose) scale(1.18); }
  to   { opacity: 1; transform: var(--pose) scale(1); }
}

/* Chaque marque garde sa position propre : le decalage est range
   dans « --pose » pour que l'animation puisse le reprendre sans
   l'ecraser. Une transformation remplace la precedente — elle ne
   s'y ajoute pas. */
.bilan__marque--juste  { --pose: translate(5px, -7px) rotate(-5deg); }
.bilan__marque--croche { --pose: translate(2px, 2px) rotate(3deg); }

@media (prefers-reduced-motion: reduce) {
  .js .bilan__store .bilan__l { transform: none; opacity: 1; animation: none; }
  .js .bilan__store .bilan__marque { opacity: 1; animation: none; }
}

/* — Le bouton d'ouverture ————————————————————————— */
.bilan__plus {
  grid-column: 1;
  justify-self: center;
  width: 1.375rem;
  height: 1.375rem;
  padding: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  background: none;
  border: 1px solid var(--filet2);
  border-radius: 3px;
  color: var(--service);
  font-family: var(--donnees);
  font-size: 0.875rem;
  line-height: 1;
  cursor: pointer;
  transition: color var(--glisse), border-color var(--glisse),
              transform var(--glisse);
}
.bilan__plus:hover { color: var(--titre); border-color: var(--ambre); }
/* Ouvert, le « + » devient une croix par simple rotation : un seul
   caractere, deux etats. */
.bilan__plus[aria-expanded="true"] {
  transform: rotate(45deg);
  color: var(--ambre);
  border-color: var(--ambre);
}
.bilan__plus--vide { border: 0; cursor: default; }

/* — La ligne du haut : date, article, verdict ——————— */
.bilan__date {
  grid-column: 2;
  justify-self: center;
  /* JetBrains Mono penche vers le bas : son encre tombait 0,99 px
     sous le milieu. */
  position: relative;
  top: -1px;
  font-family: var(--donnees);
  font-size: 0.8125rem;
  font-weight: 400;
  color: var(--service);
}

/* — Le verdict, corrige a la main ——————————————————
   Une case carree imprimee dans la page, qu'on a remplie au
   pinceau. La case appartient au site — meme filet que le reste du
   mobilier. La marque, elle, deborde et penche.

   La marque est une IMAGE : c'est le seul moyen de garder la
   texture des poils de pinceau.

   Aucun survol sur cette page — c'est voulu. Un surlignement qui
   suit la souris rappelle qu'on est devant un ecran; cette page
   doit se lire comme une copie corrigee, posee sur une table.  */
/* La colonne du verdict a une largeur fixe, et la case s'y centre.
   L'en-tete fait de meme : le mot VERDICT et la case se retrouvent
   donc sur le meme axe. */
.bilan__verdict {
  grid-column: 4;
  width: 5.25rem;
  display: flex;
  align-items: center;
  justify-content: center;
}

.bilan__case {
  position: relative;
  display: block;
  width: 1.75rem;
  height: 1.75rem;
  border: 1px solid var(--filet2);
  background: var(--fond);
}

/* La marque deborde de sa case, comme un feutre qui depasse. Elle
   est 15 % plus ample qu'a l'origine, d'ou l'ecart porte a -38 %.

   Le decalage passe par « translate », pas par « inset » : la
   boite garde ainsi sa taille, et rien ne peut se faire couper.
   La case ne confine pas — c'est deliberement une marque posee
   PAR-DESSUS, pas dedans. */
.bilan__marque {
  position: absolute;
  inset: -38%;
  background-repeat: no-repeat;
  background-position: center;
  background-size: contain;
}
/* Le crochet part vers la droite et remonte : sa masse est en bas
   a gauche, il faut la ramener au centre optique de la case. */
.bilan__marque--juste {
  background-image: url("/images/verdicts/juste.webp");
  transform: var(--pose);
}
.bilan__marque--croche {
  background-image: url("/images/verdicts/croche.webp");
  transform: var(--pose);
}
/* Sans script, les deux couches se superposent simplement : la
   croix entiere s'affiche, ce qui est le bon etat de repli. */

/* — L'affirmation, sous l'article ————————————————— */
/* L'affirmation porte l'ecriture d'un titre de registre.

   Teko porte sa masse dans le haut de sa ligne : centree sur sa
   boite, son encre tombait 1,38 px trop bas. Le decalage passe par
   « position: relative » — l'element n'a pas de fond, donc la
   boite peut bouger sans rien deplacer d'autre. */
.bilan__aff {
  grid-column: 3;
  margin: 0;
  min-width: 0;
  position: relative;
  top: 1.4px;
  font-family: var(--sans);
  font-size: 1.3125rem;
  /* Un cran plus leger que le titre d'un registre : ici
     l'affirmation partage la ligne avec un verdict, elle n'a pas
     besoin de porter seule. */
  font-weight: 500;
  letter-spacing: .01em;
  line-height: 1.2;
  color: var(--titre);
}

/* — La note ————————————————————————————————————————
   « display: flex » ecraserait l'attribut « hidden » — c'est le
   piege nº 35. */
.bilan__note {
  grid-column: 3 / -1;
  grid-row: 2;
  margin-top: 0.5rem;
  /* Exactement l'exergue des articles : meme filet, meme fond,
     meme ecriture. Une note de verdict, c'est un aparte de
     l'auteur — le site en a deja un. */
  /* Le filet ne depasse le texte que de quelques pixels en haut
     et en bas : il souligne l'aparte sans le cadrer. Il est dessine
     par un pseudo-element — une bordure prendrait toute la hauteur
     de la boite. */
  position: relative;
  padding: 0.25rem 0 0.25rem 1.0625rem;
  /* Pas de fond ici : le survol de la ligne passe derriere, et les
     deux teintes se battaient. Le filet suffit a marquer l'aparte. */
  font-family: var(--lecture);
  font-style: italic;
  /* La taille du texte d'introduction, pas celle de l'exergue :
     une note de verdict accompagne, elle ne proclame pas. */
  font-size: 1.0625rem;
  line-height: 1.6;
  color: var(--ambre);
}
.bilan__note::before {
  content: '';
  position: absolute;
  left: 0;
  top: 0;
  bottom: 0;
  width: 3px;
  background: var(--ambre);
}
.bilan__note[hidden] { display: none; }
.bilan__note p { margin: 0; }
.bilan__note p + p { margin-top: 0.625rem; }

@media (max-width: 760px) {
  .bilan__tete { display: none; }
  .bilan__l {
    grid-template-columns: 2rem 1fr;
    gap: 0.375rem 1rem;
  }
  .bilan__l { align-items: start; }
  .bilan__date, .bilan__verdict,
  .bilan__aff, .bilan__note { grid-column: 2; }
  .bilan__date { grid-row: 1; justify-self: start; }
  .bilan__aff { grid-row: 2; }
  .bilan__verdict { grid-row: 3; justify-self: start; }
  .bilan__note { grid-row: 4; }
}


/* ═══ 20g. LA FICHE DE L'AUTEUR ═══════════════════════════════
   La page A propos emprunte la forme d'une fiche de joueur, mais
   chaque champ y repond a cote. C'est la seule page du site qui
   doive convaincre par du texte seul — elle le fait par sa FORME
   autant que par son contenu.

   Deux colonnes : la fiche a gauche, le texte a droite.        */

/* Le texte d'introduction respire davantage avant la ligne de la
   fiche : c'est la seule page ou les deux se suivent. */
.page--apropos .tete-section { margin-top: 3rem; }

/* La mention de mise a jour : exactement celle du Mur. */
.apropos__maj {
  margin-left: auto;
  font-family: var(--donnees);
  font-size: 0.6875rem;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--service);
}
/* La date porte la meme couleur que la mention : c'est une
   information de service, pas une donnee vedette. */
.apropos__maj b { color: inherit; font-weight: inherit; }

/* Le bandeau courriel se rapproche : la signature ferme deja la
   page, une grande respiration de plus la laisserait flotter. */
.page--apropos { padding-bottom: 0; }

.apropos {
  display: grid;
  grid-template-columns: 19.5rem 1fr;
  gap: 0 2rem;
  align-items: start;
  margin-top: 1.5rem;
}

/* — La colonne de gauche ————————————————————————————
   Deux coins biseautes, comme un bloc de donnees. Elle est collante
   pour rester en vue pendant qu'on descend le texte. */
/* Le signet. Ses biseaux sont inverses par rapport au reste du
   mobilier : en haut a GAUCHE, en bas a DROITE. C'est ce qui lui
   donne son air de languette glissee dans la page.

   Une bordure ordinaire se ferait couper par le decoupage — c'est
   le piege nº 13. Le FOND fait donc le trait, et une couche
   interieure d'un pixel plus petite laisse ce trait paraitre sur
   tout le pourtour, biseaux compris. */
.apropos__fiche {
  position: relative;
  padding: 1px;
  background: var(--filet2);
  clip-path: polygon(28px 0, 100% 0, 100% calc(100% - 28px),
                     calc(100% - 28px) 100%, 0 100%, 0 28px);
}
.apropos__fiche > * { position: relative; z-index: 1; }
.apropos__fiche::before {
  content: '';
  position: absolute;
  inset: 1px;
  background: var(--cadre-fond);
  clip-path: polygon(27px 0, 100% 0, 100% calc(100% - 27px),
                     calc(100% - 27px) 100%, 0 100%, 0 27px);
}

.apropos__portrait {
  display: block;
  width: 100%;
  height: auto;
  /* Le portrait epouse le biseau du haut a gauche. */
  clip-path: polygon(27px 0, 100% 0, 100% 100%, 0 100%, 0 27px);
  /* Le portrait passe en noir et blanc : la page entiere est en
     valeurs, une photo en couleur y ferait tache. */
  filter: grayscale(1) contrast(1.06);
}

/* — Les champs de la fiche ——————————————————————————
   Etiquette en ambre, valeur en encre. Une seule colonne : les
   reponses sont souvent plus longues que le champ. */
.apropos__champs {
  margin: 0;
  padding: 1.25rem 1.375rem 1.5rem;
}
.apropos__champs dt {
  font-family: var(--donnees);
  font-size: 0.6875rem;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--ambre);
  margin-top: 1.125rem;
}
.apropos__champs dt:first-child { margin-top: 0; }
.apropos__champs dd {
  margin: 0.125rem 0 0;
  font-family: var(--donnees);
  font-size: 0.8125rem;
  line-height: 1.5;
  color: var(--os);
}
.apropos__champs dd ul {
  margin: 0;
  padding-left: 0.9375rem;
  list-style: none;
}
.apropos__champs dd li { position: relative; }
.apropos__champs dd li::before {
  content: '·';
  position: absolute;
  left: -0.8125rem;
  color: var(--service);
}

/* Un filet degrade separe les groupes de champs. Il s'efface aux
   deux bouts, comme ceux de l'en-tete large : une bordure pleine
   couperait le signet en deux. */
.apropos__champs .sep {
  height: 1px;
  margin: 1.5rem 0 0.375rem;
  background: linear-gradient(90deg,
    transparent, var(--filet2) 18%, var(--filet2) 82%, transparent);
}

/* — Les compteurs ————————————————————————————————————
   Quatre cases egales, la meme forme que le bloc « encadre » des
   articles. Le dernier porte une unite a cote du chiffre : elle
   tient sur deux lignes, alors le chiffre s'aligne a gauche. */
.apropos__compteurs {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 1px;
  background: var(--filet2);
  border: 1px solid var(--filet2);
}
/* Le chiffre en haut, l'etiquette collee au bas de la case : c'est
   la disposition d'un tableau de bord, pas d'une legende. */
.apropos__compteur {
  display: flex;
  flex-direction: column;
  align-items: center;
  /* Le chiffre se centre dans l'espace libre, l'etiquette colle au
     bas de la case — cinq pixels du bord. */
  justify-content: center;
  gap: 0;
  padding: 0.875rem 0.75rem 5px;
  min-height: 5.75rem;
  background: var(--cadre-fond);
  text-align: center;
}
.apropos__n {
  display: flex;
  align-items: center;
  gap: 0.625rem;
  font-family: var(--sans);
  font-weight: 500;
  /* Les trois quarts de sa taille precedente. */
  font-size: 4.875rem;
  line-height: .68;
  color: var(--titre);
  /* Teko porte sa masse en haut de sa ligne. */
  padding-top: 0.08em;
  /* Le chiffre prend tout l'espace au-dessus de l'etiquette et s'y
     centre. */
  flex: 1;
  justify-content: center;
}
/* L'unite se cale sur le MILIEU de l'encre du chiffre. Teko
   assoit sa masse haut dans sa ligne : centrer les boites laissait
   l'unite trop basse. */
.apropos__n i {
  font-family: var(--donnees);
  font-style: normal;
  font-size: 0.8125rem;
  font-weight: 400;
  line-height: 1.25;
  text-align: left;
  width: 5rem;
  /* La meme couleur que l'etiquette en dessous : l'unite en fait
     partie, elle ne se lit pas comme le chiffre. */
  color: var(--service);
  /* Mesure sur l'ENCRE, pas sur les boites : Teko assoit sa masse
     haut dans sa ligne. */
  position: relative;
  top: -6px;
}
.apropos__l {
  font-family: var(--donnees);
  font-size: 0.75rem;
  font-weight: 500;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--service);
}

/* — Le texte ————————————————————————————————————————
   Il garde la mesure de lecture des articles : une colonne large
   fatigue, meme quand la place existe. */
.apropos__texte {
  /* Une mesure de lecture confortable, centree sous les compteurs.
     C'est le BLOC qui se centre : le texte, lui, reste justifie.
     L'ecart au sceau est le meme des deux cotes. */
  max-width: 46rem;
  margin: 1.625rem auto 0;
}
.apropos__texte p {
  font-family: var(--lecture);
  font-size: 1.0625rem;
  line-height: 1.62;
  color: var(--os);
  margin: 0 0 1.375rem;
  /* Justifie des deux cotes, SANS cesure : l'auteur ne veut pas de
     mots coupes. Le texte encaisse donc quelques espaces un peu
     larges — c'est le prix. */
  text-align: justify;
  hyphens: none;
}
.apropos__texte p:last-of-type { margin-bottom: 0; }
.apropos__texte em { font-style: italic; }

/* — Le sceau ————————————————————————————————————————
   Le logo du site, flanque de deux filets qui s'effacent vers
   l'exterieur — la meme construction que l'en-tete large. Ils
   prennent tout l'espace restant, donc le logo reste centre
   quelle que soit la largeur.

   ⚠ NOM NEUTRE, ET C'EST VOULU. Il s'appelait « apropos__sceau »
   du temps ou il ne servait qu'a une page. Il ouvre maintenant
   aussi le HORS-JEU. Le seul reglage qui reste propre a A propos
   est celui du petit ecran, plus bas : il vise « .apropos__corps
   .sceau », donc il ne peut pas atteindre les autres. C'est le
   piege nº 44 pris a l'avance. */
.sceau {
  display: flex;
  align-items: center;
  gap: 1.25rem;
  margin: 1.625rem 0 0;
}
.sceau::before,
.sceau::after {
  content: '';
  flex: 1;
  height: 1px;
}
.sceau::before {
  background: linear-gradient(90deg, transparent, var(--filet2));
}
.sceau::after {
  background: linear-gradient(90deg, var(--filet2), transparent);
}
.sceau img {
  display: block;
  width: 2.125rem;
  height: 2.125rem;
  flex-shrink: 0;
  opacity: .82;
}

/* La signature est posee en MASQUE : sa forme decoupe un aplat de
   couleur, qui suit donc l'encre du theme. Une simple inversion
   donnait du noir pur sur papier — la valeur y etait, mais pas la
   temperature. */
/* La signature est posee en MASQUE : sa forme decoupe un aplat de
   couleur, qui suit donc l'encre du theme. Une simple inversion
   donnait du noir pur sur papier — la valeur y etait, mais pas la
   temperature. */
.apropos__signature {
  display: block;
  width: 17rem;
  height: 4.9rem;
  margin: 2rem 0 -5px auto;
  background: var(--os);
  -webkit-mask-image: url("/images/signature.png");
  mask-image: url("/images/signature.png");
  -webkit-mask-size: contain;
  mask-size: contain;
  -webkit-mask-repeat: no-repeat;
  mask-repeat: no-repeat;
  -webkit-mask-position: center;
  mask-position: center;
}


/* ⚠ PAS DE PHOTO SOUS 1000 PX. Le nom, sa ligne d'informations et
   le jeton prennent deja toute la largeur d'un telephone
   (decision de l'auteur, v64). */
@media (max-width: 1000px) {
  .joueur__photo { display: none; }
  .joueur__photo + .joueur__id { margin-right: 0; }
}

@media (max-width: 1000px) {
  /* Sous 1000 px, la fiche passe au-dessus du texte et cesse
     d'etre collante — elle prendrait tout l'ecran. */
  .apropos { grid-template-columns: 1fr; gap: 2rem 0; }
  .apropos__fiche { max-width: 24rem; }
  .apropos__compteurs { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 560px) {
  .apropos__compteurs { grid-template-columns: 1fr; }
  .apropos__n { font-size: 2.75rem; }
}


/* ═══ 20b. L'EN-TETE LARGE ════════════════════════════════════
   Un titre centre, flanque de deux filets qui s'effacent vers
   l'exterieur. Sert au Fil, au Mur, au Bilan et a A propos.

   Les filets sont des degrades, pas des bordures : une bordure
   ne peut pas disparaitre progressivement. Ils prennent tout
   l'espace restant de chaque cote, donc le titre reste au centre
   quelle que soit sa longueur.                                */
.tete-large {
  display: flex;
  align-items: center;
  gap: 1.5rem;
  padding: 1.375rem 0 0;
}
.tete-large::before,
.tete-large::after {
  content: '';
  flex: 1;
  height: 1px;
  min-width: 0;
}
.tete-large::before {
  background: linear-gradient(to right, transparent, var(--filet2));
}
.tete-large::after {
  background: linear-gradient(to left, transparent, var(--filet2));
}
.tete-large h2 {
  /* Le double du titre ordinaire : 23,375 px devient 46,75. */
  font-family: var(--sans);
  font-weight: 500;
  font-size: 2.75rem;
  line-height: 1;
  letter-spacing: .02em;
  text-transform: uppercase;
  color: var(--titre);
  margin: 0;
  /* Teko porte sa masse en haut de sa ligne : sans ce rattrapage,
     le mot flotte au-dessus des filets. Il passe par le
     rembourrage pour ne pas deplacer la boite. */
  padding-top: 0.11em;
  white-space: nowrap;
}

/* L'introduction centree, sous le titre. Meme police, meme taille
   et meme couleur que l'introduction ordinaire — seule la mise en
   page change. */
.fil__intro--centre {
  text-align: center;
  /* 112 caracteres, pour les deux pages qui s'ouvrent ainsi. Le
     plafond a monte deux fois : a 62 le texte du fil tenait sur
     quatre lignes, a 88 celui du mur en faisait quatre dont une
     derniere de 79 px — un mot orphelin. A 112, les deux
     remplissent leurs lignes. */
  max-width: 112ch;
  margin: 1.25rem auto 0;
}

/* Le mur a son texte a lui, et une largeur a lui : a 112
   caracteres, sa premiere ligne coupait au milieu d'une idee et la
   troisieme s'ouvrait sur « objectif… ». A 900 px, la premiere
   s'arrete a « annee, » et la troisieme part sur « mais aussi ».

   Ce reglage tient a CE texte : le reecrire demandera de le
   reverifier. */
.page--mur .fil__intro--centre { max-width: 930px; }

/* Le bilan a sa propre largeur : 30 px de moins que celle du fil. */
.page--bilan .fil__intro--centre { max-width: 958px; }

/* Le hors-jeu se resserre sur SA premiere phrase. Le texte porte
   une coupure ecrite — « Malheureusement… arena actuel. » puis
   « Deux options… » — et le cadre est cale dessus : les deux
   blocs font sensiblement la meme largeur, au lieu d'une ligne
   pleine suivie d'une ligne courte.

   700 px pour 82 caracteres. Valeur d'oeil, comme les deux
   au-dessus : mes mesures de coupure de ligne sont fausses,
   faute de polices sur mon banc (piege nº 59). */
.page--horsjeu .fil__intro--centre { max-width: 700px; }


/* ═══ 20. LE MUR DU FIL ═══════════════════════════════════════
   Le deuxieme registre du site : celui qui ne se prend pas au
   serieux. C'est le seul endroit ou une forme desordonnee est
   coherente avec le fond — d'ou les coins arrondis, qui disent
   « autre registre » sans avoir a l'expliquer.               */

.mur {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  /* Les cartes gardent leur hauteur : sans ca, toute une rangee
     prendrait celle de la plus haute et le mur deviendrait un
     tableau. */
  align-items: start;
  /* L'ecart vertical est plus grand que l'horizontal : le rond
     d'une rangee remonte de 23 px au-dessus de sa carte, et il ne
     restait qu'un pixel entre lui et la rangee du dessus. */
  column-gap: 1.375rem;
  row-gap: 2.75rem;
  /* La marge du haut absorbe la moitie de rond qui remonte
     au-dessus de la premiere rangee — 23 px — et laisse ensuite
     une soixantaine de pixels sous l'introduction. */
  margin-top: 5rem;
  padding: 0 0.75rem;
}

/* L'enveloppe porte le confinement — le navigateur ne dessine pas
   ce qui est hors de l'ecran, et la hauteur annoncee evite que la
   barre de defilement saute. Elle reserve aussi, par son
   rembourrage, la moitie de rond qui sort de la carte : le
   confinement coupe tout ce qui deborde de l'element qui le
   porte, donc le rond doit rester DANS l'enveloppe. */
.mur__case {
  content-visibility: auto;
  contain-intrinsic-size: auto 244px;
  /* Le rembourrage reserve TROIS choses, parce que le confinement
     coupe tout ce qui sort de cette boite :
       — en haut, la moitie du rond qui deborde de la carte;
       — partout, les 10 px que la carte gagne en grossissant au
         survol (8,4 px de large, jusqu'a 9 en haut d'une carte
         longue);
     Les marges negatives annulent cette reserve pour que la
     grille reste calee sur les cartes, pas sur les enveloppes. */
  content-visibility: auto;
  padding: calc(1.8125rem + 10px) 10px 10px;
  margin: calc(-1.8125rem - 10px) -10px -10px;
}

/* Le fond et le filet vivent sur une couche DERRIERE le contenu,
   pas sur la carte elle-meme. C'est cette couche qui grandit au
   survol : le texte, lui, ne bouge ni ne se redessine.

   Faire grandir la carte entiere obligeait le navigateur a
   recalculer chaque lettre a 105,5 % — rien ne se deplacait
   vraiment, mais tout tremblait. */
.mur__note::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: -1;
  border-radius: inherit;
  /* La carte prend une trace de la couleur de son equipe. On
     melange la couleur VIVE (« --eq ») dans le fond, pas le fond
     d'equipe (« --eqf ») : celui-la n'existe qu'en valeurs
     sombres, il donnerait des cartes noires sur papier. */
  background: var(--cadre-fond);
  background: color-mix(in srgb, var(--eqt, var(--eqf)) 9%, var(--cadre-fond));
  border: 1px solid var(--filet2);
  border: 1px solid color-mix(in srgb, var(--eqt, var(--eqf)) 30%, var(--filet2));
  transition: inset var(--glisse), border-color var(--glisse);
}

.mur__note {
  position: relative;
  border-radius: 14px;
  /* Le rembourrage du haut laisse la place au rond, qui deborde
     de la carte : c'est lui qui accroche l'oeil, pas la boite. */
  padding: 2.125rem 1.125rem 1.1875rem;
  transition: transform var(--glisse);
}

/* — Les ronds d'equipe ————————————————————————————— */
/* Le rond sort du haut de la carte, a demi dehors. La rangee
   garde son alignement parce qu'on le sort par un decalage, pas
   par une marge : la hauteur de la carte n'en tient pas compte. */
.mur__note--ronds {
  display: flex;
  align-items: center;
  position: absolute;
  top: 0;
  left: 1.125rem;
  transform: translateY(-50%);
}
.mur__note--rond {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  /* 3,625 rem au lieu de 2,75 : dans un rond, le logo doit tenir
     dans le CERCLE inscrit et reculer du bord, il n'occupait donc
     que 26 px sur 47. Un rond plus large lui rend cette surface. */
  width: 3.625rem;
  height: 3.625rem;
  border-radius: 50%;
  flex-shrink: 0;
  background: color-mix(in srgb, var(--eqt, var(--eqf)) 82%, var(--cadre-fond));
  color: var(--eqt, var(--eqf));
  /* Un filet de deux pixels aux couleurs de l'equipe, et rien
     d'autre : le cerne de la page qui l'entourait faisait un
     halo qui alourdissait le jeton. */
  border: 2px solid currentColor;
  font-family: var(--etiquette);
  font-weight: 700;
  font-size: 0.6875rem;
  letter-spacing: .06em;
}
/* Deux equipes : les ronds se chevauchent. Le cerne du second
   decoupe le premier, donc on lit deux jetons empiles et non une
   forme confuse. */
.mur__note--ronds--duo .mur__note--rond + .mur__note--rond {
  /* 7 px, pas davantage : un code d'equipe laisse 9 px de marge
     de chaque cote dans son rond, et au-dela le second jeton
     mange une lettre du premier. */
  /* Les deux jetons se touchent sans cerne : c'est leur propre
     filet, aux couleurs de chaque equipe, qui fait la separation. */
  margin-left: -8px;
}

/* — Le corps de la note ———————————————————————————— */
/* Resserree : a 0,1em d'interlettrage, la ligne s'etalait sur
   deux lignes des qu'un contexte etait long. Et le point median
   avait sa propre marge EN PLUS de l'interlettrage herite, ce qui
   creusait un trou apres la date. */
.mur__note--meta {
  font-family: var(--donnees);
  font-size: 0.625rem;
  letter-spacing: .04em;
  /* La ligne prend la couleur de son equipe, melangee au gris de
     service. Sur papier, voir la surcharge plus bas : il faut
     pousser vers l'encre, sinon un jaune ou un turquoise tombe
     sous 2:1 et devient illisible. */
  color: var(--service);
  /* La LIGNE, elle, garde la couleur du TEXTE de l'equipe : les
     fonds sont souvent noirs ou marine, et un noir melange a du
     gris ne donne qu'un gris plus sombre — 1,60:1 pour LNH. Le
     texte d'equipe, lui, est toujours clair par construction. */
  /* ⚠ Sauf trois equipes au texte fonce : voir « --eqm », sous
     la teinte du fil. */
  color: color-mix(in srgb, var(--eqm, var(--eq, var(--service))) 62%, var(--service));
  margin: 0.875rem 0 0.5rem;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.mur__note--meta .s { margin: 0 0.25rem; opacity: .55; letter-spacing: 0; }
.mur__note--t {
  font-family: var(--sans);
  font-weight: 400;
  font-size: 1.125rem;
  line-height: 1.3;
  color: var(--titre);
  margin: 0;
}

/* — Le survol ————————————————————————————————————
   La carte grandit PAR TRANSFORMATION : la mise en page n'est pas
   recalculee, donc rien ne saute. Ses deux voisines de rangee
   s'ecartent de la meme facon. Faire bouger tout le monde
   demanderait de designer les cartes du dessus et du dessous par
   leur position, un calcul qui casse des que le nombre de
   colonnes change. */
/* Pas d'ombre portee : elle s'etalait sur 28 px alors que
   l'enveloppe n'en reserve que 10, donc elle sortait coupee au
   carre. C'est le filet ambre qui signale le survol. */
/* Au survol, le cadre s'ouvre autour du texte et son filet monte
   a la couleur pleine de l'equipe : la carte se nomme elle-meme
   au lieu d'emprunter l'ambre du site. */
.mur__note:hover { z-index: 3; }
.mur__note:hover::before {
  inset: -9px -8px;
  border-color: var(--ambre);
  border-color: color-mix(in srgb, var(--eqt, var(--eqf)) 70%, var(--ambre));
}
/* Les cartes ne sont plus soeurs — ce sont les enveloppes qui le
   sont. On designe donc l'enveloppe voisine, puis la carte
   qu'elle contient. */
.mur__case:has(.mur__note:hover) + .mur__case .mur__note {
  transform: translateX(0.5rem);
}
.mur__case:has(+ .mur__case .mur__note:hover) .mur__note {
  transform: translateX(-0.5rem);
}

/* — L'apparition au defilement ————————————————————— */
.js .mur__note { opacity: 0; transform: translateY(14px); }
.js .mur__note.vu { opacity: 1; transform: none;
  transition: opacity 420ms ease, transform 420ms cubic-bezier(.33,0,.2,1); }
.js .mur__note.vu:hover { transform: none; }
.js .mur__case:has(.mur__note:hover) + .mur__case .mur__note.vu {
  transform: translateX(0.5rem);
}
.js .mur__case:has(+ .mur__case .mur__note:hover) .mur__note.vu {
  transform: translateX(-0.5rem);
}

/* — La saison en filigrane ————————————————————————— */
.mur__saison {
  position: fixed;
  right: 1.25rem;
  bottom: 1.25rem;
  z-index: 5;
  font-family: var(--sans);
  font-weight: 500;
  font-size: 3.25rem;
  line-height: 1;
  letter-spacing: .02em;
  color: var(--titre);
  opacity: .07;
  pointer-events: none;
  transition: opacity var(--glisse);
}

/* ⚠ UNE NOTE VISEE PAR UN LIEN (« /le-fil/#n-… ») s'arrete sous le
   haut de l'ecran, pas collee contre lui : son rond deborde de la
   carte vers le haut, et il se faisait couper. Le navigateur et
   theme.js visent tous deux le HAUT de la note — la meme marge sert
   aux deux. */
.mur__note { scroll-margin-top: 5rem; }

/* ⚠ LES PAGES DU FIL (v70). Sans script, deux liens au bas du mur;
   avec script, celui de la suite sert de guetteur et le fil se
   charge en defilant. La voix des etiquettes de la marge, en ambre :
   c'est un geste offert, pas du mobilier. */
.fil__pages {
  display: flex;
  justify-content: center;
  gap: 2.5rem;
  margin-top: 2.5rem;
}
.fil__page {
  font-family: var(--donnees);
  font-size: 0.75rem;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--ambre);
}
.fil__page:hover { text-decoration: underline; }
/* Pendant qu'une page arrive, le lien pâlit — il ne disparait pas :
   s'il tardait, le lecteur pourrait encore cliquer. */
.fil__page--charge { opacity: .45; pointer-events: none; }
/* Avec script, « plus recentes » n'a plus de sens : tout est sur la
   meme page. */
.js .fil__page[rel="prev"] { display: none; }

@media (max-width: 1100px) { .mur { grid-template-columns: repeat(3, 1fr); } }
@media (max-width: 820px)  { .mur { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 560px)  {
  .mur { grid-template-columns: 1fr; padding: 0; }
  .mur__saison { display: none; }
}

@media (prefers-reduced-motion: reduce) {
  .js .mur__note { opacity: 1; transform: none; }
  .mur__note, .mur__note:hover, .mur__note:hover + .mur__note { transition: none; transform: none; }
}


/* — Le registre, sur l'accueil comme en rubrique ———————— */

#registre-zone { touch-action: pan-y; }
.registre tr:hover .registre__titre a { color: var(--titre); }
/* Les en-têtes s'alignent sur ce qu'ils coiffent : centrés au-
   dessus des colonnes centrées, calés à gauche sur le début des
   titres, à droite sur le temps de lecture. */
/* Même distance au-dessus qu'en dessous : la ligne de titres est
   centrée dans sa bande. */
.registre th { padding-top: 0.6875rem; }
/* « table-layout: fixed » : sans lui, une cellule qui refuse de
   se briser force sa colonne a s'elargir, et le rognage a
   « ... » de l'amorce ne peut pas fonctionner. Avec, chaque
   colonne garde la largeur qu'on lui donne et le titre prend ce
   qui reste. */
.registre { table-layout: fixed; }
.registre th:nth-child(1) { width: 3.5rem; }
.registre th:nth-child(2) { width: 6.5rem; }
.registre th:nth-child(3) { width: 5.5rem; }
.registre th:nth-child(5) { width: 8rem; }

.registre th:nth-child(1),
.registre th:nth-child(2),
.registre th:nth-child(3) { text-align: center; }
.registre th:nth-child(4) { padding-left: 1.75rem; }

/* Une colonne centrée ne s'aligne que si l'en-tête et la cellule
   ont EXACTEMENT les mêmes retraits : le centre d'une boîte se
   calcule après les padding. Le « # » tombait 8 px à droite de
   ses numéros et la date 6 px à droite des siennes, simplement
   parce que les cellules n'avaient pas le retrait gauche de leur
   en-tête. */
.registre th:nth-child(1),
.registre td.registre__no {
  text-align: center;
  padding-left: 0.9375rem;
  padding-right: 0.75rem;
}
.registre td.registre__no,
.registre td.registre__date,
.registre td.registre__mm { color: var(--service); }
.registre th:nth-child(2),
.registre td.registre__date {
  text-align: center;
  padding-left: 0.75rem;
  padding-right: 0.75rem;
}

/* Le bord droit du tableau reprend le retrait du bord gauche :
   « LECTURE » et les temps respirent autant que le « # ». */
/* Chaque ligne reste d'un bloc; c'est l'empilement qui donne la
   deuxieme ligne, pas une cassure du navigateur. */
.registre th:nth-child(5),
.registre td.registre__mm { text-align: right; padding-right: 0.9375rem; white-space: nowrap; }

.registre .registre__eq { text-align: center; padding-right: 0; }
/* L'etiquette d'equipe respire au survol de sa rangee. Elle vit a
   95 % au repos et reprend sa taille pleine quand on la survole,
   plutot que de depasser 100 % — comme ca elle ne risque jamais
   de deborder de sa colonne, et la taille « vraie » est celle
   qu'on regarde. Le grossissement est progressif : c'est le
   mouvement qu'on doit voir, pas le changement d'etat. */
.registre .registre__eq .code {
  transform: scale(.9);
  transition: transform 260ms cubic-bezier(.33, 0, .2, 1);
}
.registre tr:hover .registre__eq .code { transform: scale(1); }

@media (prefers-reduced-motion: reduce) {
  .registre .registre__eq .code { transition: none; }
}
/* De l'air a droite du titre : sans ce retrait, un titre long
   venait mourir a vingt pixels de la colonne de lecture. */
.registre .registre__titre { padding-left: 1.75rem; padding-right: 2.75rem; }

/* L'amorce tient sur une seule ligne et se termine par des points
   de suspension. Le navigateur coupe au caractere qui deborde, pas
   au mot — c'est le seul rognage qui s'adapte a la largeur reelle
   de la colonne, laquelle change avec l'ecran. */
.registre__titre small {
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.registre .registre__titre a { transition: color var(--glisse); }

.vide {
  padding: 2.5rem 1.625rem;
  font-family: var(--lecture);
  font-size: 1.0625rem;
  color: var(--attenue);
  text-align: center;
}
td.vide { text-align: left; padding: 1.75rem 0; }

/* Sous 1100 px, le fil disparait au lieu de passer sous la
   vedette. Deux raisons : empile, il repoussait le registre hors
   de l'ecran, et une boite de quatre notes larges comme la page
   ne ressemble plus a rien. Le lecteur tombe donc sur la vedette
   pleine largeur, puis directement sur le registre — et « Le fil »
   du menu retrouve une raison d'exister.

   Le panneau reste dans la page, simplement masque : les notes
   vivent de toute facon sur /le-fil/. */
@media (max-width: 1100px) {
  .duo__cote { display: none; }
}
@media (max-width: 700px) {
  .filtre { width: 100%; margin-left: 0; }
  .filtre__declencheur { flex: 1; }
  .filtre__menu { left: 0; right: auto; width: 100%; }
}

/* ═══ 19. LE MOUVEMENT ════════════════════════════════════════
   Deux choses ici. La cascade a l'ouverture, et la transition
   d'une page a l'autre. Les deux sont du decor : si le navigateur
   ne sait pas les faire, la page s'affiche normalement.        */

:root {
  /* L'en-tete et le ruban arrivent ensemble, puis le corps se
     deroule. La pause entre les deux est un chiffre a elle seule :
     le retard du corps se recalcule tout seul autour. */
  --cascade-courbe:      cubic-bezier(.33, 0, .2, 1);
  --cascade-duree-haut:  700ms;
  --cascade-pause:       60ms;
  --cascade-duree-corps: 850ms;
  /* Separes, parce que le GROUPE — le conteneur qui porte les
     deux photos de page — ne prend pas de raccourci : il lui faut
     sa duree et sa courbe une par une. Sans ca il garde celle du
     navigateur, 250 ms, et les deux pages ne glissent pas au meme
     rythme. */
  --glisse-duree:  460ms;
  --glisse-courbe: cubic-bezier(.5, 0, .18, 1);
  /* Aucun decalage : les deux pages forment UNE SEULE bande qui
     coulisse. Des qu'on decale l'une, elles n'avancent plus a la
     meme vitesse et l'entrante parait rattraper l'autre. */
  --glisse-decalage: 0ms;
}

/* — Les instruments s'allument ————————————————————————
   Quand un bloc entre a l'ecran, ce qui MESURE se met en marche :
   l'arc se referme, les barres s'etirent, les courbes se tracent.
   Le cadre, lui, ne bouge pas — on anime la donnee, pas la boite.
   Les tableaux de chiffres n'ont rien ici : ca se lit, ca ne se
   regarde pas monter.

   Le declenchement vient de la classe « vu », posee une seule
   fois par theme.js. */

/* Le cadran : l'arc GRANDIT depuis midi. Le pointillé fait toute
   la circonference; on le decale d'abord de sa longueur entiere —
   rien ne parait — puis on ramene le decalage a « circonference
   moins l'arc ». Le trait s'allonge donc par son extremite, il ne
   se deplace pas. */
.js .cadran .arc { stroke-dashoffset: var(--arc-vide); }
.cadran .arc {
  stroke-dashoffset: var(--arc-plein);
  transition: stroke-dashoffset 1000ms cubic-bezier(.33, 0, .2, 1) 80ms;
}
.js .bloc.vu .cadran .arc { stroke-dashoffset: var(--arc-plein); }

/* Les barres s'etirent depuis la gauche, l'une apres l'autre.
   « scaleX » plutot qu'une largeur : c'est la carte graphique qui
   travaille, et la largeur inscrite par le generateur reste
   intacte. */
.js .barre__jus { transform: scaleX(0); }
.barre__jus {
  transform: scaleX(1);
  transform-origin: left center;
  transition: transform 640ms cubic-bezier(.33, 0, .2, 1);
}
.bloc.vu .barre__jus { transform: scaleX(1); }
.barre:nth-child(1) .barre__jus { transition-delay:  60ms; }
.barre:nth-child(2) .barre__jus { transition-delay: 150ms; }
.barre:nth-child(3) .barre__jus { transition-delay: 240ms; }
.barre:nth-child(4) .barre__jus { transition-delay: 330ms; }
.barre:nth-child(5) .barre__jus { transition-delay: 420ms; }
.barre:nth-child(6) .barre__jus { transition-delay: 510ms; }

/* Les deux camps se colorent en entrant a l'ecran. La couleur
   nait sous le logo et se repand vers le centre — le meme geste
   que les barres qui s'etirent, mais en teinte plutot qu'en
   longueur.

   On anime la TAILLE du fond, pas une opacite : la couleur balaie
   la bande au lieu d'apparaitre partout a la fois. C'est ce qui
   donne le sens de lecture — de son bord vers le milieu.

   Le second joueur part un cheveu apres le premier : deux camps
   qui s'allument ensemble se lisent comme un seul bloc. */
.js .duel__r--tete .duel__g,
.js .duel__r--tete .duel__d,
.js .transac__cg,
.js .transac__cd,
.js .joueur__tete { background-size: 0% 100%; }

.duel__r--tete .duel__g,
.duel__r--tete .duel__d,
.transac__cg,
.transac__cd,
.joueur__tete {
  background-size: 100% 100%;
  transition: background-size 820ms cubic-bezier(.33, 0, .2, 1);
}
.duel__r--tete .duel__g,
.transac__cg { transition-delay: 120ms; }
.duel__r--tete .duel__d,
.transac__cd { transition-delay: 260ms; }
/* ⚠ LA FICHE PART SEULE, DONC ELLE PART TOT.

   Les deux camps d'un duel sont decales de 140 ms l'un sur
   l'autre : deux bandes qui s'allument ensemble se lisent comme un
   seul bloc. Une fiche n'a personne avec qui se decaler — elle
   prend donc le premier temps. */
.joueur__tete { transition-delay: 120ms; }

/* Les transactions s'echelonnent : une rangee apres l'autre, comme
   les barres. Une liste qui s'allume d'un bloc se lit comme une
   image; echelonnee, elle se lit comme une suite. */
.transac:nth-of-type(2) .transac__cg { transition-delay: 220ms; }
.transac:nth-of-type(2) .transac__cd { transition-delay: 360ms; }
.transac:nth-of-type(3) .transac__cg { transition-delay: 320ms; }
.transac:nth-of-type(3) .transac__cd { transition-delay: 460ms; }
.transac:nth-of-type(n+4) .transac__cg { transition-delay: 420ms; }
.transac:nth-of-type(n+4) .transac__cd { transition-delay: 560ms; }

.bloc.vu .duel__r--tete .duel__g,
.bloc.vu .duel__r--tete .duel__d,
.bloc.vu .transac__cg,
.bloc.vu .transac__cd,
.bloc.vu .joueur__tete { background-size: 100% 100%; }

/* Les courbes se tracent de gauche a droite. Le generateur pose
   « pathLength="1" » sur chaque trace : sa longueur vaut donc une
   unite, quelle que soit sa longueur reelle. */
.js .courbe polyline { stroke-dashoffset: 1; }
.courbe polyline {
  stroke-dasharray: 1;
  stroke-dashoffset: 0;
  transition: stroke-dashoffset 1150ms cubic-bezier(.4, 0, .25, 1);
}
.bloc.vu .courbe polyline { stroke-dashoffset: 0; }
.courbe .ligne-b { transition-delay: 120ms; }

/* Les chiffres poses sur les points arrivent une fois le trace
   bien engage, sinon ils flottent au-dessus du vide. */
.js .courbe .val-pts, .js .courbe .val-b { opacity: 0; }
.courbe .val-pts, .courbe .val-b {
  opacity: 1;
  transition: opacity 420ms linear 620ms;
}
.bloc.vu .courbe .val-pts, .bloc.vu .courbe .val-b { opacity: 1; }

@media (prefers-reduced-motion: reduce) {
  .cadran .arc, .barre__jus, .courbe polyline,
  .courbe .val-pts, .courbe .val-b { transition: none; }
  .cadran .arc { stroke-dashoffset: 0; }
  .barre__jus { transform: scaleX(1); }
  .courbe polyline { stroke-dashoffset: 0; }
  .courbe .val-pts, .courbe .val-b { opacity: 1; }
  .js .duel__r--tete .duel__g,
  .js .duel__r--tete .duel__d,
  .js .transac__cg,
  .js .transac__cd { background-size: 100% 100%; }
}


/* — La cascade a l'ouverture ————————————————————————
   Le haut de la page se revele de gauche a droite, puis le corps
   du haut vers le bas, un quart de seconde plus tard. Le masque
   fait deux fois et demie la taille du bloc; on ne deplace que sa
   position, ce que la carte graphique fait seule. */

@keyframes cascade-h {
  from { -webkit-mask-position: 100% 0; mask-position: 100% 0; }
  to   { -webkit-mask-position: 0 0;    mask-position: 0 0; }
}
@keyframes cascade-v {
  from { -webkit-mask-position: 0 100%; mask-position: 0 100%; }
  to   { -webkit-mask-position: 0 0;    mask-position: 0 0; }
}

.entete, .ruban {
  /* Le masque fait 250 % de la largeur du bloc. A l'arrivee, le
     bloc n'occupe que les 40 premiers pour cent du masque : le
     noir doit donc couvrir AU MOINS 40 %, sinon le bord droit
     reste voile pour toujours. Au depart, le bloc occupe 60 a
     100 % : la transparence doit commencer avant 60. */
  -webkit-mask-image: linear-gradient(90deg, #000 0%, #000 42%, transparent 58%, transparent 100%);
  mask-image: linear-gradient(90deg, #000 0%, #000 42%, transparent 58%, transparent 100%);
  -webkit-mask-size: 250% 100%;
  mask-size: 250% 100%;
  animation: cascade-h var(--cascade-duree-haut) var(--cascade-courbe) both;
}

/* Le masque porte sur « .page » et non sur « main » : la
   progression de lecture est en position fixe, et un masque sur
   son ancetre la rattacherait a lui au lieu de l'ecran. */
main > .page {
  /* ⚠ RIEN NE DOIT ELARGIR LA PAGE.

     Plusieurs elements debordent volontairement sur les cotes : la
     lumiere du mur fait 190 % de la largeur de l'ecran, l'enveloppe
     du Bilan sort de 30 px pour ne pas trancher ses crochets, le
     balayage du registre fait 1320 px de large.

     Aucun n'est cense se VOIR au-dela du cadre — mais chacun
     elargit le document, ce qui donne une barre de defilement
     horizontale et fait glisser la page de cote.

     « clip » plutot que « hidden » : « hidden » creerait une boite
     de defilement, ce qui casserait le positionnement collant de
     ce qui vit dedans. « clip » coupe sans rien creer.

     Sur un ecran de 3440 en plein ecran, rien ne depassait : le
     bug ne se voyait qu'en fenetre reduite ou sur un telephone. */
  overflow-x: clip;

  /* Meme calcul que plus haut : le noir doit depasser 40 % et la
     transparence commencer avant 60. Avec 30 et 62, le bas de la
     page restait a 69 % d'opacite une fois l'animation finie —
     les etiquettes du registre en sortaient delavees. */
  -webkit-mask-image: linear-gradient(180deg, #000 0%, #000 42%, transparent 58%, transparent 100%);
  mask-image: linear-gradient(180deg, #000 0%, #000 42%, transparent 58%, transparent 100%);
  -webkit-mask-size: 100% 250%;
  mask-size: 100% 250%;
  animation: cascade-v var(--cascade-duree-corps) var(--cascade-courbe)
             calc(var(--cascade-duree-haut) + var(--cascade-pause)) both;
}

/* Arrivee par une transition : pas de cascade. La page doit
   apparaitre entiere et glisser d'un bloc — un devoilement
   pendant le glissement se lit comme un fondu, et l'effet de
   glissement disparait. */
.sans-cascade .entete,
.sans-cascade .ruban,
.sans-cascade main > .page {
  -webkit-mask-image: none;
  mask-image: none;
  animation: none;
}


/* — D'une page a l'autre ————————————————————————————
   L'article arrive par la droite, comme s'il attendait a cote de
   l'accueil. Le navigateur photographie les deux pages et anime
   la difference; aucun script, aucune bibliotheque. */

@view-transition { navigation: auto; }

/* L'en-tete, le ruban et le pied sont les memes d'une page a
   l'autre : on les nomme pour qu'ils restent en place pendant que
   le contenu glisse. Sans ca, tout le site coulisserait. */
.entete { view-transition-name: entete; }
.ruban  { view-transition-name: ruban; }
.pied   { view-transition-name: pied; }

/* Par defaut, le navigateur MELANGE les deux photos de page — il
   les isole et leur pose un mode de fusion additif. Meme si elles
   glissent, ca se lit comme un fondu. « isolation: auto » et un
   mode normal les empilent franchement : l'une passe VRAIMENT
   par-dessus l'autre. Sans ces deux lignes, aucun glissement
   n'est perceptible. */
::view-transition-image-pair(root) { isolation: auto; }
::view-transition-old(root),
::view-transition-new(root) { mix-blend-mode: normal; }

/* Les deux pages sont bord a bord et parcourent exactement la
   meme distance, dans le meme temps : l'article est litteralement
   colle a droite de l'accueil, et la bande glisse d'un cran. */
@keyframes page-sort  { to   { transform: translateX(-100%); } }
@keyframes page-entre { from { transform: translateX(100%); } }

/* Le groupe doit couvrir toute la duree, retard compris, sinon il
   finit avant le contenu qu'il porte. */
::view-transition-group(root) {
  animation-duration: calc(var(--glisse-duree) + var(--glisse-decalage));
  animation-timing-function: var(--glisse-courbe);
}
/* La sortante part la premiere ET finit en meme temps que
   l'entrante : sa duree absorbe le decalage. Sinon elle se fige a
   mi-course pendant que l'autre glisse encore, et on la voit
   plantee sur la gauche — c'est ce qui donnait l'impression
   qu'elle ne sortait pas au complet. */
::view-transition-old(root) { z-index: 0; animation: page-sort calc(var(--glisse-duree) + var(--glisse-decalage)) var(--glisse-courbe) both; }
::view-transition-new(root) { z-index: 1; animation: page-entre var(--glisse-duree) var(--glisse-courbe) var(--glisse-decalage) both; }

/* Au retour, tout s'inverse : c'est l'article qui part, donc c'est
   LUI qui passe par-dessus et sort vers la droite, pendant que la
   page precedente reapparait par la gauche, en dessous. */
@keyframes page-sort-inv  { to   { transform: translateX(100%); } }
@keyframes page-entre-inv { from { transform: translateX(-100%); } }

html.glisse-retour::view-transition-old(root) { z-index: 1; animation-name: page-sort-inv; }
html.glisse-retour::view-transition-new(root) { z-index: 0; animation-name: page-entre-inv; }

/* ── LE MOBILIER PENDANT LA TRANSITION ─────────────────────────
   L'en-tete, le ruban et le pied sont identiques d'une page a
   l'autre. Ils doivent donc rester parfaitement immobiles.

   ⚠ CE QUI NE MARCHAIT PAS, ET POURQUOI.

   La feuille demandait un ECHANGE SEC : l'ancienne photo a zero,
   la nouvelle a un, sans animation. Entre l'instant ou l'ancienne
   s'efface et celui ou la nouvelle est prete a etre peinte, il
   peut rester UNE IMAGE OU IL N'Y A RIEN — et l'en-tete
   disparaissait. C'etait le scintillement.

   Un fondu n'a jamais ce trou : les deux photos se chevauchent
   toujours. On laisse donc le navigateur faire le sien.

   L'echange sec avait ete choisi parce que le fondu dedoublait le
   menu et epaississait le texte. Mais ce n'etait pas la faute du
   fondu : c'est que Chrome mélange les deux photos en mode
   ADDITIF, et deux textes identiques superposes deviennent gras.

   Le correctif existait deja plus haut, pour la page. Il ne
   restait qu'a l'appliquer ici aussi.                          */

::view-transition-image-pair(entete),
::view-transition-image-pair(ruban),
::view-transition-image-pair(pied) { isolation: auto; }

::view-transition-old(entete),
::view-transition-new(entete),
::view-transition-old(ruban),
::view-transition-new(ruban),
::view-transition-old(pied),
::view-transition-new(pied) { mix-blend-mode: normal; }

/* Personne qui a demande moins d'animation ne recoit tout ca. */
@media (prefers-reduced-motion: reduce) {
  .entete, .ruban, main > .page {
    -webkit-mask-image: none;
    mask-image: none;
    animation: none;
  }
  ::view-transition-old(root), ::view-transition-new(root) { animation: none; }
}


/* ═══ 21b. HORS-JEU ═══════════════════════════════════════════
   La page 404. Le bouton du banc, le sceau, puis jusqu'a trois
   textes suggeres, cote a cote.

   Elle ne reprend PAS le registre : une table de cinq colonnes
   pour trois lignes serait un instrument sans mesure. Ici on
   propose, on ne classe pas.

   Tout est centre sous le titre, comme le paragraphe
   d'introduction juste au-dessus.                             */

.horsjeu { text-align: center; margin-top: 2rem; }

/* — Le retour au banc ——————————————————————————————————
   Son apparence vient du bloc « .formulaire button » de la
   section 14 — meme ambre, meme fonte, meme survol. Ici on ne
   pose que sa BOITE : seul dans la page, il doit se donner la
   hauteur que la rangee du formulaire donnait a l'autre. */
.horsjeu__banc {
  height: 3rem;
  padding: 0.15em 1.75rem 0;
  border: 1px solid var(--bouton-filet);
  text-decoration: none;
}

/* Le sceau ne prend pas toute la page : ses filets iraient d'un
   bord a l'autre sur 1320 px et l'objet perdrait son air de
   cachet. Il garde la largeur d'une colonne de lecture. */
.horsjeu .sceau { max-width: 44rem; margin: 1.875rem auto 0; }

/* — Les textes suggeres ————————————————————————————————
   Trois colonnes egales, et « auto-fit » plutot qu'un chiffre
   fixe : quand il n'y a que deux textes — Le CH n'ayant que la
   vedette, par exemple — ils remplissent la largeur au lieu de
   laisser un trou a droite.

   Le texte des cartes reste a GAUCHE. Centrer trois blocs de
   trois lignes de longueurs differentes donnerait un bord gauche
   en dents de scie, illisible. C'est l'ensemble qui est centre,
   pas son contenu.                                            */
.horsjeu__liste {
  list-style: none;
  margin: 1.875rem 0 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(17rem, 1fr));
  gap: 0.9375rem;
  text-align: left;
}

/* La carte occupe toute la hauteur de sa case : trois chapeaux de
   longueurs differentes laisseraient sinon trois bas de bloc a
   des hauteurs differentes. */
.horsjeu__t { display: flex; }
.horsjeu__t a {
  display: block;
  width: 100%;
  padding: 0.9375rem 1.125rem;
  border-left: 3px solid color-mix(in srgb, var(--eqt, var(--eqf)) 55%, var(--filet2));
  background: var(--cadre-fond);
  text-decoration: none;
  transition: background-color 220ms ease;
}
.horsjeu__t a:hover,
.horsjeu__t a:focus-visible { background: var(--surface); }

.horsjeu__meta {
  display: block;
  font-family: var(--donnees);
  font-size: 0.6875rem;
  letter-spacing: 0.08em;
  color: var(--service);
  margin-bottom: 0.3125rem;
}
.horsjeu__titre {
  display: block;
  font-family: var(--sans);
  font-weight: 500;
  font-size: 1.375rem;
  line-height: 1.15;
  color: var(--titre);
}
.horsjeu__chapeau {
  display: block;
  font-family: var(--lecture);
  font-size: 1rem;
  line-height: 1.45;
  color: var(--attenue);
  margin-top: 0.25rem;
}


/* ══════════════════════════════════════════════════════════════
   22. LE CELLULAIRE — CE BLOC RESTE EN DERNIER
   ══════════════════════════════════════════════════════════════

   ⚠ SA POSITION DANS LE FICHIER FAIT PARTIE DU CORRECTIF.

   Une requete « @media » n'ajoute AUCUNE specificite. A egalite,
   c'est donc la DERNIERE regle ecrite qui gagne — et ce bloc a
   d'abord ete pose au milieu du fichier, ou « .ruban { display:
   flex } », ecrit cent lignes plus bas, l'annulait en silence.

   Tout ce qui est propre au petit ecran s'ecrit ICI, apres tout
   le reste. Ne pas le deplacer vers le haut.
   ══════════════════════════════════════════════════════════════ */

/* ══ L'EN-TÊTE SUR PETIT ÉCRAN ═════════════════════════════════
   Sur grand écran, tout tient sur une ligne : le mot-symbole à
   gauche, le menu et la bascule à droite. Sous 1000 px, ça ne
   rentre plus et le menu cassait sur trois lignes.

   Il devient donc DEUX rangées :

     rangée 1   le mot-symbole à gauche, la bascule à droite
     rangée 2   les sept liens, sur une seule ligne

   Et l'en-tête reste COLLÉ EN HAUT. C'est un choix assumé : il
   coûte environ 90 px d'écran en permanence, en échange d'une
   navigation et d'une marque toujours visibles.

   ⚠ LE MENU DOIT TENIR SUR UNE LIGNE. Sept liens, 48 caractères.
   C'est serré à 360 px. Si ça déborde chez toi, le seul chiffre
   à toucher est « --nav-taille » ci-dessous — descends-le d'un
   demi-cran à la fois. Le filet « overflow-x » empêche la casse
   entre-temps : la barre glisse au doigt plutôt que de sauter à
   la ligne.                                                    */

@media (max-width: 1000px) {

  .entete {
    /* La bascule est ancrée sur cette boîte-ci. */
    position: sticky;
    top: 0;
    z-index: 40;


    flex-direction: column;
    align-items: stretch;
    flex-wrap: nowrap;
    gap: 0;
    padding: 0;
    min-height: 0;

    /* Collé en haut, il passe PAR-DESSUS le contenu : sans fond
       opaque, le texte défilerait au travers. */
    background: var(--fond);
  }

  /* La marge du bord, sur petit écran. Plus étroite que celle du
     contenu : 24 px de chaque côté d'un écran de 360, c'est 13 %
     de la largeur donnée au vide. L'en-tête est du mobilier, il
     peut s'approcher du bord — sans le toucher. */
  .entete { --marge-entete: 1rem; }

  /* — Rangée 1 : le mot-symbole — */
  .entete > .marque {
    padding: 0.5rem var(--marge-entete);
    /* La bascule occupe le coin droit : on lui réserve la place
       pour que le mot-symbole ne passe jamais dessous. */
    padding-right: 6rem;
  }

  /* La bascule sort du menu et monte dans le coin. Elle vit dans
     « .nav » en HTML — c'est du positionnement, pas un
     déplacement : le balisage ne change pas.

     Sa hauteur et son décalage sont ceux du LOGO, pas des valeurs
     choisies à l'oeil : même haut, même bas, donc même centre.
     Le jour où le logo change de taille, les deux suivent. */
  .entete .bascule {
    position: absolute;
    top: 0.5rem;
    right: var(--marge-entete);
    margin-left: 0;
    height: 31px;
    width: 4.25rem;
  }
  .entete .bascule::after { font-size: 1rem; }

  /* — Rangée 2 : les sept liens — */
  /* ⚠ ELLE PORTE UN FOND, ET C'EST POUR REMPLACER LE RUBAN.
     Sur grand ecran, la bande de statut fait la couture entre
     l'en-tete et la page. Elle disparait ici — decision de
     l'auteur, voir plus bas — et tout le haut devenait un seul
     aplat, sans limite entre le mobilier et le contenu.

     Le fond repris est celui de la BOITE DU FILTRE, pas une
     couleur choisie a l'oeil : les deux objets sont du mobilier
     de meme rang, et le site n'apprend pas une teinte de plus.
     En clair, cette boite est surchargee et prend le taupe de la
     bande courriel — le menu la suit jusque-la. */
  .nav {
    --nav-taille: 0.9375rem;   /* ← LE CHIFFRE À AJUSTER */

    flex-wrap: nowrap;
    justify-content: space-between;
    background: var(--surface2);
    border-top: 1px solid var(--filet);
    padding: 0 calc(var(--marge-entete) - 0.25rem);

    /* Le filet. Si les sept liens débordent malgré tout, la barre
       glisse au doigt au lieu de casser sur deux lignes. La barre
       de défilement elle-même reste cachée : c'est du mobilier,
       pas une donnée. */
    overflow-x: auto;
    scrollbar-width: none;
    -webkit-overflow-scrolling: touch;
  }
  .nav::-webkit-scrollbar { display: none; }

  .nav a {
    font-size: var(--nav-taille);
    padding-left: 0.25rem;
    padding-right: 0.25rem;
    /* Un lien qui se brise en deux mots casse la ligne entière. */
    white-space: nowrap;
  }

  /* ⚠ EN CLAIR, LES DEUX COULEURS DU MENU DOIVENT CHANGER.
     « --nav » et « --nav-survol » valent tous les deux du taupe de
     ce cote-la — la meme valeur que le fond qu'on vient de poser.
     Sans ces deux regles, les liens et la page courante
     disparaitraient purement et simplement dans leur propre
     bande. Le probleme n'existe pas en fonce, ou le taupe se
     detache du #24241F.

     Le lien ordinaire prend le creme, comme le texte de la boite
     du filtre. La page courante prend le blanc casse : a peine
     plus lumineuse que les autres, elle se signale surtout par
     son trait. Un mot fonce au milieu de mots pales aurait crie
     plus fort que le reste du mobilier. */
  /* Le fond AUSSI. « --surface2 » vaut du gris pale de ce
     cote-la, pas le taupe : c'est la surcharge de la boite du
     filtre qui lui donne sa couleur, et le menu doit la suivre
     jusque-la. L'oublier laissait des liens creme sur du gris
     pale — presque invisibles. */
  html[data-theme="clair"] .nav { background: var(--bande-fond); }

  html[data-theme="clair"] .nav a { color: var(--fond); }
  html[data-theme="clair"] .nav a:hover,
  html[data-theme="clair"] .nav a[aria-current="page"] {
    color: var(--bande-valeur);
    border-bottom-color: var(--bande-valeur);
  }
}

/* Le ruban disparaît DÈS QUE l'en-tête se replie — même seuil que
   ci-dessus, volontairement. Deux seuils différents auraient donné
   une bande intermédiaire où l'en-tête est en mode cellulaire mais
   le ruban encore là : personne n'aurait su lequel des deux était
   le bon.

   Décision de l'auteur : sur un écran de cette taille, la date de
   dernière publication n'aide personne — les articles portent déjà
   la leur. L'espace vaut plus que l'information.

   Il reste dans le HTML : les machines et les lecteurs d'écran le
   trouvent encore. */
@media (max-width: 1000px) {
  .ruban { display: none; }
}


/* ══ LE MOBILIER FIGÉ, SUR PETIT ÉCRAN SEULEMENT ═══════════════
   Sur grand écran, le navigateur fait glisser la boîte de l'ancien
   en-tête vers celle du nouveau. Les deux étant au même endroit,
   rien ne bouge : c'est le bon comportement, et il faut le laisser
   faire.

   Sur petit écran, l'en-tête est COLLANT. Un élément collant est
   photographié à sa position PEINTE, pas à sa position de mise en
   page — et selon l'instant où la photo est prise, le navigateur
   peut voir deux positions légèrement différentes. Il glisse alors
   de l'une à l'autre : c'était le glissement du haut de page.

   ⚠ POURQUOI SEULEMENT ICI. Figer la boîte partout ramenait un
   autre défaut sur grand écran : figée à la géométrie de
   l'ANCIENNE page, elle ne s'alignait plus avec la nouvelle photo,
   et le mot-symbole se peignait par-dessus le menu.

   Un réglage par cas, parce que les deux cas ne sont pas le même
   problème.                                                     */

@media (max-width: 1000px) {
  ::view-transition-group(entete),
  ::view-transition-group(ruban),
  ::view-transition-group(pied) { animation: none; }
}


/* ══ LA MARGE DU BORD, SUR PETIT ÉCRAN ═════════════════════════
   Le jeton vaut « max(1.5rem, ...) » : sur grand écran c'est le
   calcul qui gagne et centre le contenu; sur petit écran c'est le
   plancher de 1,5 rem qui s'applique.

   Ce plancher était pensé pour un moniteur qu'on rétrécit, pas
   pour un téléphone. Sur 360 px, il donne 51 px des deux bords —
   14 % de la largeur cédée au vide, sur l'écran qui en a le moins.

   On l'abaisse à 1 rem, la même valeur que l'en-tête. Tout le site
   s'aligne alors sur le même cadre : le menu, le contenu, le
   bandeau courriel et le pied.

   ⚠ Un seul jeton pour tout le site — ne pas régler les marges
   page par page en dessous. Si une page a besoin d'autre chose,
   c'est probablement le jeton qu'il faut revoir.               */

@media (max-width: 1000px) {
  :root { --marge-laterale: 1rem; }
}


/* ══ L'ACCUEIL SUR PETIT ÉCRAN ═════════════════════════════════
   Sur grand écran, le filtre vit au bout de la ligne « Dernière
   publication » — il y a la place, et il annonce ce qu'il va
   filtrer avant qu'on le voie.

   Sur un téléphone, il n'y a plus de place sur cette ligne : le
   titre cassait en deux et le filtre finissait par déborder en
   dessous, coincé sous son propre titre.

   Il descend donc APRÈS l'article vedette, juste avant le
   registre — c'est-à-dire juste avant ce qu'on filtre le plus
   souvent.

   ⚠ COMMENT, sans toucher au HTML : « display: contents » efface
   la BOÎTE de la tête de section sans effacer son contenu. Ses
   deux enfants — le titre et le filtre — deviennent alors des
   éléments de la page elle-même, et peuvent être replacés un par
   un avec « order ».

   Le prix : la boîte effacée emportait son filet du dessous. Le
   titre le reprend donc à son compte, avec le même rembourrage.
   Rien ne bouge à l'écran, sauf ce qu'on voulait bouger.        */

@media (max-width: 1000px) {

  .page--accueil { display: flex; flex-direction: column; }

  /* La boîte s'efface, ses enfants restent. */
  .page--accueil > .tete-section:first-child { display: contents; }

  /* Le titre reprend ce que la boîte portait — le rembourrage et
     le filet. Il occupe maintenant toute la largeur, donc
     « DERNIÈRE PUBLICATION » tient sur une ligne. */
  .page--accueil > .tete-section:first-child > h2 {
    order: 1;
    padding: 1.375rem 0 0.4375rem;
    border-bottom: 1px solid var(--filet2);
  }

  .page--accueil > .duo { order: 2; }

  /* Le filtre, descendu entre la vedette et le registre. */
  .page--accueil .filtre {
    order: 3;
    width: 100%;
    margin: 1.5rem 0 0;
  }
  .page--accueil .filtre__declencheur { flex: 1; }
  .page--accueil .filtre__menu { left: 0; right: auto; width: 100%; }

  /* Les repères sont nommés plutôt que comptés : « la tête de
     section qui SUIT le duo » ne se trompera pas le jour où un
     bloc s'ajoute entre les deux. */
  .page--accueil > .duo ~ .tete-section { order: 4; }
  .page--accueil > #registre-zone { order: 5; }

  /* Le filtre porte son propre filet, comme le titre plus haut :
     il ferme l'article vedette au lieu de flotter entre deux. */
  .page--accueil .filtre {
    border-top: 1px solid var(--filet2);
    padding-top: 1.25rem;
    margin-top: 0.75rem;
  }
}


/* ══ L'ARTICLE VEDETTE SUR PETIT ÉCRAN ═════════════════════════
   Trois coupes, et une raison unique derrière les trois : sur un
   écran de cette taille, la vedette n'a plus la place de faire
   deux choses. Elle doit donner envie de cliquer, pas raconter.

   L'amorce s'en va — c'est le rôle du chapeau. Les métadonnées
   s'en vont — le numéro d'entrée, le temps de lecture et le
   compte de mots sont des chiffres de registre, pas d'affiche.

   Il reste ce qui décide d'un clic : l'équipe, la date, le titre,
   le chapeau.                                                   */

@media (max-width: 1000px) {

  /* — La barre du haut : l'équipe à gauche, la date à droite —
     On efface tout, puis on rallume les deux qu'on garde. Écrit
     dans ce sens-là, le jour où un champ s'ajoute à la barre il
     restera caché par défaut plutôt que d'apparaître ici sans
     qu'on l'ait décidé.

     La règle vise « .barre-meta » sans préfixe : la vedette de
     l'accueil et l'en-tête d'un article portent EXACTEMENT la même
     barre, et doivent donc se réduire de la même façon. Deux
     en-têtes qui se comportent autrement, c'est le lecteur qui
     doit apprendre deux fois la même chose. */
  .barre-meta > * { display: none; }
  /* La rubrique et l'équipe, dans cet ordre : les deux étiquettes
     biseautées se suivent comme sur grand écran. */
  .barre-meta > .jeton { display: inline-flex; }
  .barre-meta > .code { display: inline-flex; }
  .barre-meta > span:last-child {
    display: inline-block;
    /* Elle prend tout l'espace du milieu et se colle à droite. */
    margin-left: auto;
  }
  .barre-meta { align-items: center; }

  /* — Le corps : titre et chapeau seulement — */
  .vedette .texte { display: none; }

  /* La fenêtre raccourcit. Elle faisait 30 rem sur grand écran,
     où elle porte l'amorce en plus; sans elle, la même hauteur
     laissait un grand vide sous le chapeau.

     ⚠ C'est le SEUL chiffre à toucher si la proportion ne te
     plaît pas — la photo, le store et le centrage s'y ajustent
     tous seuls. */
  .duo__principal > .cadre { height: 24rem; }

  /* Le bloc se centre dans la hauteur qui reste. « auto » des deux
     bords plutôt qu'un centrage de la boîte : le lien « lire la
     suite » garde ainsi sa place au bas, il ne monte pas avec le
     texte. */
  .vedette__corps {
    display: flex;
    flex-direction: column;
    flex: 1;
    min-height: 0;
  }
  .vedette .titre-article { margin-top: auto; }
  .vedette .chapeau { margin-bottom: auto; }

  /* ⚠ SAUF SUR UNE CARTE EN PHOTO.

     La marge automatique centre le bloc dans la hauteur qui reste,
     et c'est juste pour une carte sans photo : tout y est visible.

     Sur une carte en PHOTO, le panneau est descendu et seule sa
     bande dépasse. Une marge automatique y pousse le titre vers le
     BAS du panneau — donc hors de la bande. On ne voyait plus que
     du voile vide.

     ⚠ ET LE DÉFAUT NE SORT QUE DANS UN SEUL DES TROIS ÉTATS.

         large + souris     le panneau s'ouvre au survol
         ÉTROIT + souris    ← ici, et nulle part ailleurs
         tactile            « (hover: none) » donne au titre sa
                            propre boîte, et il s'y centre

     Une fenêtre étroite sur un ordinateur est le seul cas qui
     tombe entre les deux : le petit écran par la largeur, le grand
     par le survol. Le mode appareil de Chrome ne le montre PAS —
     il déclare le tactile, donc il bascule dans le troisième état.
     Le cahier le dit à la section 26 : une fenêtre simplement
     étroite ne remplace pas le mode appareil. */
  .cadre--photo .titre-article { margin-top: 0; }
}


/* ══ LE REGISTRE SUR PETIT ÉCRAN ═══════════════════════════════
   Deux colonnes : le jeton d'équipe, et le titre. Rien d'autre.

   Le numéro, la date, le temps de lecture et le compte de mots
   sont l'information d'un registre qu'on CONSULTE. Sur un
   téléphone, cette table est devenue une liste qu'on PARCOURT —
   et une liste qu'on parcourt n'a besoin que de deux choses :
   de qui ça parle, et de quoi ça parle.

   ⚠ Chaque colonne se cache DEUX fois : la cellule de contenu par
   sa classe, l'en-tête par sa position. C'est la ligne d'en-têtes
   qui fixe la largeur des colonnes — en oublier une suffit à
   écraser tout le reste. */

@media (max-width: 1000px) {

  .registre__no, .registre__date, .registre__mm,
  .registre th:nth-child(1),
  .registre th:nth-child(2),
  .registre th:nth-child(5) { display: none; }

  /* Le jeton garde sa largeur; le titre prend tout le reste. */
  .registre th:nth-child(3) { width: 4.5rem; }
  .registre th:nth-child(4) { width: auto; padding-left: 0.75rem; }

  /* Le chapeau s'en va : sur deux colonnes, il doublait la
     hauteur de chaque rangée pour une phrase tronquée. */
  .registre__titre small { display: none; }

  /* — LA LIGNE DE SERVICE —
     La date, le temps de lecture et le compte de mots remontent
     au-dessus du titre. Leurs colonnes ne rentrent plus, mais
     l'information reste utile — elle change juste de place.

     Même écriture que les colonnes qu'elle remplace : JetBrains
     Mono dans le ton de service.

     ⚠ SON CALAGE. Le haut de ses lettres doit tomber sur le haut
     du jeton d'à côté. Deux réglages pour ça : la cellule s'aligne
     par le HAUT, et un décalage rattrape l'écart entre le haut de
     la ligne et le haut de l'encre — une capitale s'assoit à
     environ deux dixièmes de sa taille sous le bord de sa boîte.

     C'est le SEUL chiffre à toucher si l'alignement penche. */
  /* ⚠ Le sélecteur porte DEUX classes, et c'est nécessaire.

     « .cel-seul { display: inline } » est écrit huit cents lignes
     plus bas dans la feuille. À poids égal, la dernière gagne — et
     la ligne se remettait donc en ligne avec le titre.

     Deux classes pèsent plus qu'une : la position dans le fichier
     ne compte plus. C'est le piège nº 16, et le nº 68 par-dessus. */
  .registre__titre .registre__service {
    --service-cale: 0.2em;

    display: block;
    font-family: var(--donnees);
    font-size: 0.625rem;
    letter-spacing: .08em;
    line-height: 1;
    color: var(--service);
    margin-top: calc(0em - var(--service-cale));
    /* L'écart avec le titre. Serré : les deux lignes forment un
       seul bloc, une entrée de registre, pas deux informations. */
    margin-bottom: 0.25rem;
  }

  /* Les deux cellules partent du même bord. Sans ça, la rangée les
     centre chacune sur sa propre hauteur et rien ne s'aligne. */
  .registre td.registre__eq,
  .registre td.registre__titre { vertical-align: top; }

  /* ⚠ « .registre td » a plus de poids que « .registre__titre »
     seul — un type compte, et il en a un de plus. Le retrait
     gauche restait donc à zéro pendant que l'en-tête était à
     0,75 rem, et les deux ne s'alignaient pas.

     La cellule est donc désignée par son type ET sa classe : même
     valeur que l'en-tête, et assez de poids pour l'imposer.
     C'est le piège nº 16. */
  .registre td.registre__titre {
    padding-left: 0.75rem;
    padding-right: 0.9375rem;
    /* Le titre peut respirer sur deux ou trois lignes. La rangée
       n'a plus de hauteur imposée : c'est le texte qui décide. */
    white-space: normal;
  }
  .registre__titre a { font-size: 1.0625rem; line-height: 1.25; }
  .registre tr { height: auto; }
  .registre td { padding-top: 0.875rem; padding-bottom: 0.875rem; }
}


/* ══ LES RUBRIQUES SUR PETIT ÉCRAN ═════════════════════════════
   La tête de section aligne ses enfants sur la LIGNE D'ÉCRITURE —
   le bas des lettres. C'est le bon réglage entre deux textes :
   « Saison 2026-27 » et la mention de droite s'assoient sur la
   même ligne.

   Mais la boîte de recherche n'est pas un texte : elle fait 40 px
   de haut, et sa ligne d'écriture est loin de son centre. Son
   texte s'alignait donc avec le titre pendant que sa BOÎTE
   descendait sous lui.

   Elle se cale donc sur le centre plutôt que sur la ligne — c'est
   ce qu'on veut quand on aligne un objet avec un mot.           */

@media (max-width: 1000px) {

  /* On recale la TÊTE au complet, pas seulement la boîte.

     Caler la boîte toute seule ne suffisait pas : le titre restait
     sur la ligne d'écriture, et comme la boîte est plus haute que
     lui, il se retrouvait au-dessus de son centre. Les deux
     doivent partager le même repère.

     « :has » désigne exactement la bonne tête — celle qui contient
     une recherche — sans toucher à celles du Bilan ou d'À propos,
     où deux textes s'alignent correctement sur leur ligne. */
  .tete-section:has(.recherche) { align-items: center; }

  .tete-section .recherche {
    /* Le demi-pixel servait à rattraper la ligne d'écriture. Il
       n'a plus de raison d'être. */
    top: 0;
    /* Elle prend ce qui reste après le titre, au lieu d'une
       largeur fixe qui déborderait sur un écran étroit. */
    flex: 1;
    min-width: 0;
  }
  .recherche input { width: 100%; min-width: 0; }
}


/* ══ L'EN-TÊTE LARGE SUR PETIT ÉCRAN ═══════════════════════════
   Partagé par Le fil, Le mur, Le bilan et À propos.

   Le titre est calé sur le DOUBLE du titre ordinaire — un rapport,
   pas un chiffre choisi. On garde le rapport et on baisse les deux
   ensemble : le titre passe de 2,75 à 2 rem, l'introduction de
   1,0625 à 0,9375.

   Sur un écran de cette largeur, un titre de 47 px mange le tiers
   de la hauteur visible avant qu'on ait lu un mot.

   ⚠ « white-space: nowrap » reste : « À PROPOS » et « LE BILAN »
   ne doivent jamais casser en deux. Les deux filets qui les
   flanquent se chargent d'absorber ce qui reste.                */

@media (max-width: 1000px) {
  .tete-large { gap: 1rem; padding-top: 1rem; }
  /* 30 px. Écrit en rem comme tout le reste de la feuille : le
     jour où « html { font-size } » bouge, les tailles suivent
     ensemble plutôt que de diverger. */
  .tete-large h2 { font-size: 1.7647rem; }

  /* 14 px, et l'écart sous le titre resserré — 20 px devenaient
     20 px sur un écran trois fois moins haut. Le texte remonte, et
     tout ce qui suit avec lui.

     Les deux règles, parce que l'introduction centrée écrase la
     marge de l'ordinaire : en corriger une seule laisserait le fil
     et le mur à un écart et le reste à un autre. */
  .fil__intro { font-size: 0.7647rem; margin-top: 0.5rem; }   /* 13 px */
  .fil__intro--centre { margin-top: 0.5rem; }
}


/* ══ LE MUR SUR PETIT ÉCRAN ════════════════════════════════════
   La pyramide 9 · 8 · 9 · 6 devenait une grille plate de six —
   32 boucliers alignés au carré, sans le décalage qui fait tout
   le dessin. Et à six par rangée, chacun tombait à 50 px.

   Ici : 5 · 4 · 5 · 4 · 5 · 4 · 5. Ça fait exactement 32, ça garde
   l'escalier, et un bouclier de moins par rangée lui rend un quart
   de sa taille.

   ⚠ COMMENT — dix colonnes, chaque bouclier en occupe deux. Il n'y
   a donc que TROIS règles à écrire : le premier bouclier de chaque
   rangée PAIRE est poussé d'une demi-case. Les autres se placent
   tout seuls derrière lui, et la rangée suivante repart à gauche
   parce que le dixième bouclier ne rentre plus.

   Les rangs sont ceux de la disposition : 6, 15, 24. Si le nombre
   d'équipes change un jour, ce sont ces trois chiffres-là qu'il
   faut refaire — pas la grille.                                 */

@media (max-width: 1000px) {

  .mur32 {
    grid-template-columns: repeat(10, 1fr);
    /* Resserré : à dix colonnes, chaque pixel de gouttière est pris
       trois fois sur la largeur du bouclier. */
    column-gap: 0.25rem;
    row-gap: 0.75rem;
  }

  /* On efface d'abord les décalages du grand écran, sinon ils se
     mêleraient aux nôtres. */
  .mur32__case,
  .mur32__case:nth-child(10),
  .mur32__case:nth-child(18),
  .mur32__case:nth-child(27) { grid-column: span 2; }

  /* Les trois rangées paires, décalées d'une demi-case. */
  .mur32__case:nth-child(6),
  .mur32__case:nth-child(15),
  .mur32__case:nth-child(24) { grid-column: 2 / span 2; }

  /* L'air au-dessus et en dessous des boucliers. UN SEUL jeton
     pour les deux : c'est la seule façon de garantir qu'ils
     restent égaux. Deux chiffres écrits séparément finissent
     toujours par diverger d'un demi-cran.

     Sur grand écran il y avait 72 px au-dessus — de l'air qui
     donne au mur son air de scène. Sur un téléphone, c'est un
     tiers de l'écran perdu avant le premier bouclier. */
  .page--mur { --mur-air: 1.25rem; }

  /* La mention se centre parce que les trois écarts sont le MÊME
     jeton : au-dessus d'elle, en dessous d'elle, et sous la
     dernière rangée. Un centrage écrit en un seul chiffre ne peut
     pas se décentrer tout seul. */
  .mur32__barre { margin-top: var(--mur-air); }
  .mur32__scene {
    margin-top: var(--mur-air);
    padding-top: 0;
  }
  .mur32 { padding-bottom: var(--mur-air); }

  /* Le code à trois lettres des boucliers encore au modèle : à
     cette taille, il ne se lit plus et salit le dessin. Le survol
     et le titre au doigt gardent le nom de l'équipe. */
  .mur32__code { font-size: 0.5rem; }
}


/* ══ LA FICHE DE JOUEUR SUR PETIT ÉCRAN ════════════════════════
   Même moule pour la fiche de gardien : les deux ne diffèrent que
   par leur graphique.                                            */

@media (max-width: 1000px) {

  /* L'en-tête du bloc. Le titre et sa référence se partagent une
     ligne étroite; « FICHE DE JOUEUR » cassait en deux. Les deux
     descendent d'un cran et l'interlettrage se resserre — c'est
     lui qui coûte le plus cher sur un titre court. */
  /* Le titre prend toute la largeur, et le droit de passer sur
     deux lignes : la tête n'a qu'une hauteur MINIMUM, elle grandit
     d'elle-même. Un titre de bloc est écrit par l'auteur, il peut
     être long — « Avantage numérique » ne rentre déjà pas. */
  .bloc__titre {
    font-size: 0.6875rem;
    letter-spacing: .1em;
    line-height: 1.35;
  }
  .bloc__ref { font-size: 0.5625rem; }

  /* ⚠ TOUT LE CALAGE DU CADRAN SUR PETIT ÉCRAN A ÉTÉ RETIRÉ.

     Il portait deux textes — le rang et sa glose — posés en
     miroir du cadran, à des hauteurs calculées au pixel près pour
     tomber exactement sur le chiffre et son unité. C'était un
     beau morceau, et il ne sert plus : le bloc porte maintenant
     PLUSIEURS cadrans, chacun avec sa catégorie au-dessus et son
     rang en dessous. Il n'y a plus de texte à caler à côté.

     Ce que le petit écran demande est maintenant une seule
     ligne — deux cadrans par rangée — et elle vit avec les autres
     règles du bloc, plus haut. */

  /* La ligne de détails se replie en trois : il lui faut un
     interligne. À 1, les trois lignes se touchaient. */
  .joueur__pos { line-height: 1.6; }

  /* Le nom raccourci laisse de la place, mais pas au point de
     garder sa taille de bureau. */
  .joueur__nom { font-size: 1.375rem; }

  /* La note d'enjeu. Elle est centrée et fait trois lignes sur un
     téléphone; à 21 px elle pesait plus lourd que le tableau
     qu'elle commente. */
  .joueur__note { font-size: 0.9375rem; padding: 0.75rem; }

  /* Le tableau de statistiques. Sept colonnes dans 326 px : la
     dernière sortait du cadre. Trois gestes plutôt qu'un seul,
     parce qu'aucun ne suffisait :

       — la police descend d'un cran;
       — l'interlettrage des en-têtes se resserre, c'est lui qui
         coûte le plus cher sur des libellés de deux lettres;
       — la colonne des saisons se raccourcit, côté générateur.

     Si ça ne rentre toujours pas, il restera à retirer une
     colonne — mais on l'aura essayé avant de couper. */
  .joueur__stats { font-size: 0.6875rem; }
  .joueur__stats th { letter-spacing: .06em; }
  .joueur__stats th,
  .joueur__stats td { padding-left: 0.25rem; padding-right: 0.25rem; }

  /* — SIX COLONNES, PAS SEPT —
     On a essayé : police réduite, interlettrage resserré, saisons
     abrégées. Il en manquait encore. Au-delà de six, les colonnes
     s'effacent — « MIN/PJ » pour un joueur, « GSAx » pour un
     gardien.

     Le générateur pose lui-même la classe « cel-cache » sur les
     cellules en trop : lui seul connaît le nombre de colonnes, qui
     n'est pas le même d'une fiche à l'autre. Une règle écrite ici
     sur une POSITION se serait trompée dès la première fiche
     bâtie autrement.

     Les cellules restent dans le HTML : les machines et
     l'impression y ont toujours accès. */

  /* Les largeurs. Le générateur écrit deux jeux de valeurs : celui
     du grand écran dans la balise, celui du petit dans des jetons
     « --m1 », « --m2 »… On les branche ici, et c'est tout.

     Le calcul de répartition est le même que sur grand écran, ce
     qui veut dire qu'une colonne dont la valeur la plus longue
     dépasse sept caractères garde sa part supplémentaire. C'est ce
     qui permet à « 275-173-41 » de tenir sur une ligne sans qu'on
     ait eu à le prévoir. */
  .joueur__stats {
    --c1: var(--m1); --c2: var(--m2); --c3: var(--m3);
    --c4: var(--m4); --c5: var(--m5); --c6: var(--m6);
    --c7: var(--m7); --c8: var(--m8); --c9: var(--m9);
    --c10: var(--m10); --c11: var(--m11); --c12: var(--m12);
  }

  /* La dernière colonne visible reprend la marge du logo au-dessus
     d'elle : le tableau et la tête de fiche finissent alors sur la
     même verticale.

     C'est le générateur qui la nomme « cel-fin » — sa position
     change d'une fiche à l'autre, la compter ici se tromperait. */
  .joueur__stats .cel-fin { padding-right: 0.9375rem; }

  /* Le pied. La source effacée, il ne reste qu'un élément — et un
     seul élément dans une répartition « aux deux bouts » se colle
     à gauche. La mention du site doit rester à droite, là où elle
     a toujours été. */
  .bloc__pied { justify-content: flex-end; }

  /* — LE GRAPHIQUE —
     Le dessin fait 660 unités de large et se réduit pour tenir
     dans la colonne. À 326 px, chaque unité vaut donc moins de la
     moitié d'un pixel : un chiffre écrit à 11 unités rend à 5 px.

     On ne peut pas agrandir le dessin — mais on peut écrire plus
     gros DEDANS. Les tailles sont en unités de dessin, pas en
     pixels : elles se réduiront avec lui, mais en partant de plus
     haut. C'est le piège nº 22, pris par le bon bout.

     La place ne manque pas : cinq saisons sur 660 unités laissent
     145 unités entre deux points, pour des nombres qui en font
     une trentaine. */
  .courbe .val-pts,
  .courbe .val-b { font-size: 18px; }

  /* Les valeurs vertes sont posées 14 unités SOUS leur point — un
     écart calibré pour du texte de 11 unités. À 18, la lettre est
     plus haute et vient combler cet écart : elle touchait la
     ligne.

     On les repousse de six unités. Le déplacement se fait ici
     plutôt que dans le générateur : celui-ci écrit une position
     qui vaut pour les deux écrans, et seul le petit a besoin
     d'être corrigé. */
  .courbe .val-b { transform: translateY(6px); }
  .courbe .saison { font-size: 15px; letter-spacing: 0.5px; }

  /* La légende, elle, est du vrai texte HTML sous le dessin : elle
     ne se réduit pas avec lui. Elle paraissait donc grosse à côté
     de chiffres écrasés — l'écart se referme des deux bords. */
  .legende-courbe { font-size: 0.5625rem; gap: 0.875rem; }
}


/* ══ LE TEXTE D'ARTICLE SUR PETIT ÉCRAN ════════════════════════
   L'alignement à gauche est déjà réglé plus haut, sous 900 px. Ce
   qui restait, c'est la CÉSURE — les mots coupés par un trait
   d'union en fin de ligne.

   Elle était là pour servir le justifié : en cassant les mots
   longs, elle évite les trous entre les mots. Sans justifié, elle
   n'a plus de raison d'être, et elle coûte quelque chose — un mot
   coupé demande à l'oeil de le recoller.

   L'auteur refuse les mots coupés. Sur la page À propos, ce refus
   avait forcé l'abandon du justifié; ici le justifié est déjà
   parti, il ne reste qu'à couper la césure.                     */

@media (max-width: 1000px) {
  .texte > p,
  .chapeau {
    hyphens: none;
    -webkit-hyphens: none;
  }
}


/* ══ LA MARGE DE L'ARTICLE SUR PETIT ÉCRAN ═════════════════════
   Sur grand écran, la marge est une colonne étroite à gauche du
   texte, qui suit le défilement. Ses trois blocs s'empilent et
   leur filet les tient alignés sur un même bord gauche.

   Ici elle passe au-dessus du texte, en pleine largeur. Empilés,
   les trois blocs faisaient une colonne maigre collée à gauche
   avec du vide à droite.

   Ils se répartissent donc : la signature à gauche, les données à
   droite. Et les blocs de droite retournent leur filet — un trait
   qui ouvre à gauche un texte aligné à droite regarderait dans le
   mauvais sens.                                                  */

@media (max-width: 1000px) {

  .grille__marge {
    display: grid;
    grid-template-columns: 1fr auto;
    gap: 1rem 1.5rem;
    align-items: start;
  }

  .marge__b { margin-bottom: 0; }

  /* « Par » tient la colonne de gauche sur les deux rangées. */
  .grille__marge > .marge__b:nth-of-type(1) { grid-column: 1; grid-row: 1 / span 2; }
  .grille__marge > .marge__b:nth-of-type(2) { grid-column: 2; grid-row: 1; }
  .grille__marge > .marge__b:nth-of-type(3) { grid-column: 2; grid-row: 2; }

  /* Les deux blocs de droite : filet retourné, texte à droite. */
  .grille__marge > .marge__b:nth-of-type(2),
  .grille__marge > .marge__b:nth-of-type(3) {
    border-left: 0;
    border-right: 2px solid var(--filet2);
    padding-left: 0;
    padding-right: 0.75rem;
    text-align: right;
  }

  .marge__rappel { grid-column: 1 / -1; grid-row: 3; }
  .partenaire { grid-column: 1 / -1; grid-row: 4; }
}

/* ⚠ SUR UN TÉLÉPHONE, LE PARTENAIRE PREND LA PLACE DU RAPPEL (v71).

   Sous 900 px, la marge passe AU-DESSUS du texte. « Chaque mardi par
   courriel » y flottait seul, au milieu de nulle part, et le bandeau
   du bas de page fait déjà la demande : il s'efface, partenaire ou
   pas. Le partenaire monte à sa place — 300 px, centré, juste avant
   le texte. Un partenaire relégué à la fin de la page ne serait vu
   que de ceux qui s'y rendent.

   Plus étroit que 300, le carré rapetisse avec l'écran. */
@media (max-width: 900px) {
  .marge__rappel { display: none; }
  .partenaire { grid-row: 3; }
  .partenaire__cadre { width: min(300px, 100%); margin-inline: auto; }
}


/* ══ LE DUEL SUR PETIT ÉCRAN ═══════════════════════════════════
   La tête du duel met les deux joueurs côte à côte, séparés par
   une colonne vide. Sur 326 px, chaque joueur aurait 100 px pour
   porter son étiquette, son nom et ses mensurations.

   Les deux se mettent donc l'un SOUS l'autre, en miroir :

     [DET] L. Raymond            AD · 23 ANS
                                 5'11 · 185 LB
     G · 22 ANS         M. Seider [DET]
     6'1 · 207 LB

   Le miroir n'est pas décoratif : c'est ce qui garde la lecture
   d'un duel — deux camps qui se font face — quand la mise en page
   ne peut plus les mettre côte à côte.

   Le rang de sélection s'efface (voir le générateur) : c'est du
   contexte, pas une comparaison.                                */

@media (max-width: 1000px) {

  /* La tête cesse d'être une grille à trois colonnes : les deux
     joueurs s'empilent, et le séparateur du milieu n'a plus rien
     à séparer. */
  .duel__r--tete { display: block; }
  .duel__r--tete .duel__l { display: none; }

  /* Le logo se rapproche du bord : sur cette largeur, 16 px de
     chaque côté valaient un dixième de l'écran donné au vide.

     La même valeur des deux bords, et c'est elle que les
     mensurations reprennent de leur côté — les quatre éléments
     tombent donc sur deux verticales, une par bord. */
  .duel__r--tete .duel__g,
  .duel__r--tete .duel__d {
    width: 100%;
    padding-block: 0.5rem;
    padding-inline: 0.5rem;

    /* Chaque moitié prend la teinte de SON équipe — le même
       mélange que les cartes du fil : 9 % de la couleur d'équipe.

       Sur grand écran les deux joueurs sont côte à côte et le
       lecteur voit d'un coup à qui appartient quoi. Empilés, ils
       perdent ce repère : la teinte le rend.

       Le dégradé lui-même vit plus haut, hors de ce bloc : il vaut
       pour les deux formats. Ici on ne change QUE l'endroit où il
       s'éteint.

       Empilées, les deux bandes font toute la largeur du cadre. Un
       dégradé qui court jusqu'au bout laisserait une couleur
       résiduelle sous les mensurations de l'autre bord — il finit
       donc plus tôt. */
    --duel-fin: 78%;
  }

  /* ⚠⚠ LE NOM EN HAUT, LES DÉTAILS DESSOUS — COMME SUR GRAND ÉCRAN
     (v64, demande de l'auteur).

     L'identité s'ouvrait en largeur : le nom d'un bord, les
     mensurations épinglées à l'autre, sans retour de ligne. Tant
     que le repêchage était court, ça tenait. « 1RE RONDE 2017 (13E
     AU TOTAL) » ne tient pas à côté d'un nom dans 360 px : la ligne
     débordait du cadre, et le nom se cassait sur deux lignes
     (« N. / Suzuki ») pour lui faire de la place.

     Trois lignes empilées, collées au logo, dans l'ordre où on lit
     un joueur :

         [MTL]  N. Suzuki
                C · 27 ANS · 5'11 · 207 LBS
                1RE RONDE 2017 (13E AU TOTAL)

     Le miroir reste : le joueur de droite s'aligne à droite,
     contre SON logo. */
  .duel__r--tete .duel__id {
    flex: 1;
    min-width: 0;
    flex-direction: column;
    align-items: flex-start;
    justify-content: center;
    gap: 0.1875rem;
    text-align: left;
  }
  .duel__r--tete .duel__id--d {
    align-items: flex-end;
    text-align: right;
  }
  .duel__r--tete .duel__nom { white-space: nowrap; }

  /* Les deux lignes de détails, sous le nom et du même bord. */
  .duel__dets {
    display: flex;
    flex-direction: column;
  }
  .duel__r--tete .duel__id--d .duel__dets { align-items: flex-end; }

  /* ⚠ PLUS D'ÉPINGLE AU BORD : elle ne veut rien dire sous le nom.
     Et le détail peut revenir à la ligne s'il le faut — un débord
     hors du cadre est pire qu'une ligne de plus. */
  .duel__r--tete .duel__det {
    line-height: 1.5;
    white-space: normal;
    margin-right: 0;
  }

  /* ⚠ LES MENSURATIONS SUR UNE SEULE LIGNE. Le générateur les coupe
     en deux sur petit écran (« C · 27 ANS » puis « 5'11 · 207
     LBS »), par la paire « cel-cache » / « cel-seul » — le repli de
     la fiche de joueur. Sous le nom, la ligne a toute la largeur :
     le repli ne sert plus ici, et SEULEMENT ici. */
  .duel__r--tete .cel-cache { display: inline; }
  .duel__r--tete br.cel-seul { display: none; }

  /* Les valeurs et leur catégorie descendent d'un cran : les
     libellés du milieu ne sont pas abrégeables — ils changent d'un
     duel à l'autre — donc c'est la taille qui doit céder. */
  .duel__g, .duel__d { font-size: 0.8125rem; }
  .duel__l { font-size: 0.5625rem; letter-spacing: .08em; }
}


/* ── LE CÔTÉ QUI MÈNE, DANS UN TABLEAU DE COMPARAISONS (v66) ──
   Comme le comparatif de l'APERÇU de l'atelier : la couleur du club, à
   42 %, qui part du CENTRE (la catégorie) et s'éteint à 88 % vers le
   bord. La cellule gagnante porte la classe de son équipe, qui lui
   donne « --eqf ». */
.duel__g.duel--mene {
  background: linear-gradient(to left,
    color-mix(in srgb, var(--eqf, var(--ambre)) 42%, transparent) 0%, transparent 88%);
}
.duel__d.duel--mene {
  background: linear-gradient(to right,
    color-mix(in srgb, var(--eqf, var(--ambre)) 42%, transparent) 0%, transparent 88%);
}

/* ⚠ ET ILS S'ALLUMENT AU DÉFILEMENT (v66, demande de l'auteur) — le même
   geste que la tête du duel, les transactions et la fiche : on anime la
   TAILLE du fond, qui balaie la case depuis le CENTRE vers son bord.
   Les rangées s'échelonnent, et partent APRÈS les deux camps de la tête
   (120 et 260 ms) : on voit d'abord qui s'affronte, puis qui mène. */
.duel__g.duel--mene { background-position: right center; background-repeat: no-repeat; }
.duel__d.duel--mene { background-position: left center;  background-repeat: no-repeat; }
.js .duel__r .duel--mene { background-size: 0% 100%; }
.duel__r .duel--mene {
  background-size: 100% 100%;
  transition: background-size 820ms cubic-bezier(.33, 0, .2, 1);
}
.bloc.vu .duel__r .duel--mene { background-size: 100% 100%; }
.duel__r:nth-child(2) .duel--mene { transition-delay: 420ms; }
.duel__r:nth-child(3) .duel--mene { transition-delay: 510ms; }
.duel__r:nth-child(4) .duel--mene { transition-delay: 600ms; }
.duel__r:nth-child(5) .duel--mene { transition-delay: 690ms; }
.duel__r:nth-child(6) .duel--mene { transition-delay: 780ms; }
.duel__r:nth-child(7) .duel--mene { transition-delay: 870ms; }
.duel__r:nth-child(n+8) .duel--mene { transition-delay: 960ms; }

/* ══ LES TRANSACTIONS SUR PETIT ÉCRAN ══════════════════════════
   Trois colonnes — ce qui part, la date, ce qui arrive — dans
   326 px : chaque nom tombait à un mot par ligne, et « 4e ronde
   2023 » en faisait trois.

   La rangée s'empile donc, dans l'ordre où on la lit :

     [DET]  F. Hronek, 4e ronde 2023
              ◄ 01.03.2023 ►
     1re ronde 2023, 2e ronde 2023  [VAN]

   La date reste au milieu — c'est le pivot de la transaction, ce
   qui part d'un bord, ce qui arrive de l'autre. Empilée, elle
   devient une charnière plutôt qu'une colonne.                 */

@media (max-width: 1000px) {

  .transac { display: block; padding: 0; }

  /* Les deux blocs SE TOUCHENT : leurs rembourrages intérieurs
     réservent la place de la date, et rien ne les sépare. La
     couleur va donc d'un bord à l'autre et du haut au bas, sans
     bande morte au milieu. */
  .transac__cg, .transac__cd {
    width: 100%;
    padding-inline: 0.625rem;
    gap: 0.625rem;
  }
  /* L'écart entre la date et chaque équipe. Il est écrit ici deux
     fois en miroir : le bas du premier bloc et le haut du second
     réservent ensemble la place du texte assis sur la couture. */
  .transac__cg { padding-block: 0.5rem 0.9375rem; }
  .transac__cd { padding-block: 0.9375rem 0.5rem; }

  /* Ce qui arrive se lit de l'autre bord : son logo ferme la
     rangée, comme il ouvre celle du haut. */
  .transac__cd { justify-content: flex-end; }

  /* ⚠ LA DATE N'OCCUPE AUCUNE HAUTEUR.

     Une boîte de hauteur nulle qui centre son contenu : le texte
     déborde également de part et d'autre de la couture, donc il
     s'assoit exactement dessus.

     C'est ce qui fait que chaque teinte se rend « jusqu'à la
     moitié de la date » — la couture EST cette moitié. Un espace
     réservé à la date aurait laissé une bande sans couleur entre
     les deux équipes. */
  .transac__date {
    height: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 0;
    position: relative;
    z-index: 1;
  }

  .transac__cg > span, .transac__cd > span { font-size: 0.9375rem; }
}


/* ══ LE BILAN SUR PETIT ÉCRAN ══════════════════════════════════
   L'affirmation prend la taille du titre d'un registre. Les deux
   objets font la même chose sur cet écran-là : une ligne de texte
   qu'on parcourt, dans une liste qu'on descend. Deux tailles
   différentes pour un même rôle, ça se voit sans se nommer.

   Le rapport d'origine est conservé : l'affirmation reste un cran
   plus légère que le titre d'un registre — elle partage sa ligne
   avec un verdict, elle n'a pas besoin de porter seule.         */

@media (max-width: 1000px) {

  /* — LE BULLETIN —
     La note est posée en absolu et déborde vers le haut sans
     pousser le tableau. Sur grand écran elle déborde dans du vide;
     ici, le texte d'introduction est juste au-dessus et elle lui
     passait au travers.

     Deux gestes : elle rapetisse, et la saison se décale pour lui
     réserver sa place. Le décalage vaut la hauteur du bulletin —
     écrit en jeton, pour que les deux ne puissent pas diverger. */
  .page--bilan { --bulletin-taille: 4rem; }

  .bilan__bulletin {
    width: var(--bulletin-taille);
    /* Le cercle est tracé à la main : il déborde de 16 % de sa
       boîte, de chaque côté. Le décalage vaut exactement ce
       débordement — le cercle vient donc se caler sur le bord du
       contenu, à la même verticale que les cases du verdict, sans
       dépasser d'un pixel.

       Écrit comme un CALCUL et non comme un chiffre : si la taille
       du bulletin change, le décalage suit. Un « 10,9 px » figé
       tronquerait le cercle à la première retouche. */
    right: calc(var(--bulletin-taille) * 0.16);
  }
  .bilan__grade {
    width: var(--bulletin-taille);
    height: var(--bulletin-taille);
  }
  .bilan__lettre { font-size: 2.875rem; }
  .bilan__compte { font-size: 1.25rem; margin-left: 1.375rem; margin-top: -0.5rem; }

  .bilan__saison { margin-top: var(--bulletin-taille); }

  /* — LA LIGNE —
     Trois colonnes, trois rangées :

       le bouton · la date · · · · · · · · · · · · le verdict
       l'affirmation, sur toute la largeur restante
       la note, quand il y en a une

     Le verdict remonte sur la ligne du haut : à droite de la date,
     il se lit d'un coup d'oeil en descendant la colonne, au lieu
     d'obliger à chercher sous chaque affirmation. */
  .bilan__l {
    /* La colonne du bouton vaut sa DIAGONALE, pas son côté : ouvert,
       il tourne de 45 degrés et devient un losange qui déborde de
       41 % de chaque bord. Une colonne à sa taille fermée le
       couperait à l'ouverture. */
    grid-template-columns: 1.75rem 1fr auto;
    gap: 0.4375rem 0.625rem;
    align-items: center;
    padding-left: 0.3125rem;
    /* Zéro à droite : la case du verdict vient alors se caler
       exactement sur le bout du filet qui sépare les lignes. Les
       deux bords de la ligne deviennent une seule verticale. */
    padding-right: 0;
  }

  .bilan__plus {
    grid-column: 1;
    grid-row: 1;
    justify-self: center;
    width: 1.125rem;
    height: 1.125rem;
    font-size: 0.75rem;
  }

  .bilan__date {
    grid-column: 2;
    grid-row: 1;
    justify-self: start;
    font-size: 0.6875rem;
  }

  .bilan__verdict {
    grid-column: 3;
    grid-row: 1;
    justify-self: end;
    /* Sur grand écran, cette boîte fait 5,25 rem et CENTRE sa case
       dedans, pour qu'elle tombe sous la colonne « VERDICT » de
       l'en-tête. Ici, cette colonne n'existe plus : la boîte
       touchait bien le bord, mais la case flottait 31 px avant.

       Elle prend donc la taille de son contenu, et le pousse à
       droite. */
    width: auto;
    justify-content: flex-end;
  }
  .bilan__case { width: 1.5rem; height: 1.5rem; }

  .bilan__aff {
    grid-column: 2 / -1;
    grid-row: 2;
    font-size: 1.0625rem;
    line-height: 1.25;
    /* Le rattrapage optique valait pour 21 px de Teko. À 18, il
       dépasse : l'affirmation descendait sous sa marque. */
    top: 1px;
  }

  .bilan__note {
    grid-column: 2 / -1;
    grid-row: 3;
    /* 14 px. Un cran sous l'affirmation : la note est un aparté,
       elle ne doit pas peser autant que ce qu'elle explique. */
    font-size: 0.8235rem;
    line-height: 1.5;
  }
}


/* ══ À PROPOS SUR PETIT ÉCRAN ══════════════════════════════════
   Trois gestes, et le troisième change l'ordre de lecture.

   Sur grand écran, les compteurs ouvrent la colonne de droite : le
   lecteur voit les chiffres pendant que son oeil descend encore le
   portrait, puis arrive au texte. Les deux colonnes se lisent en
   parallèle.

   Sur un téléphone il n'y a plus qu'une colonne, et tout s'enfile.
   Les compteurs se retrouvaient donc COINCÉS entre la fiche et le
   texte — quatre chiffres qui interrompent une lecture au lieu de
   l'accompagner.

   Ils passent après le texte, où ils deviennent ce qu'ils sont
   vraiment : la note en bas de page.                            */

@media (max-width: 1000px) {

  /* L'espace sous l'introduction, resserré. */
  .page--apropos .tete-section { margin-top: 1.25rem; }

  /* La date de mise à jour s'en va. Elle vit au bout de la ligne du
     titre, et sur cette largeur elle le poussait à la ligne pour
     une information que personne ne cherche. Elle reste dans le
     HTML — les machines la trouvent encore. */
  .apropos__maj { display: none; }

  /* Le texte d'abord, les chiffres ensuite. Le sceau reste collé au
     texte : c'est lui qui l'ouvre. */
  .apropos__corps { display: flex; flex-direction: column; }
  .apropos__corps .sceau { order: 1; margin-top: 0; }
  .apropos__texte  { order: 2; }
  .apropos__compteurs { order: 3; margin-top: 2rem; }

  /* 16 px. Sur une colonne de 326 px, 18 donnait des lignes de
     trente-cinq caractères — trop courtes pour une lecture
     suivie. */
  .apropos__texte p {
    font-size: 0.9375rem;
    line-height: 1.6;
    /* Le justifié étire les espaces pour que les deux bords tombent
       droit. Sur la colonne du bureau, le surplus se répartit sur
       une quinzaine d'espaces et personne ne le voit. Ici, la ligne
       porte six mots : le même surplus se partage entre cinq
       espaces, et un mot long qui ne rentre pas laisse un trou de
       sa propre largeur.

       Ce n'est pas un réglage à ajuster — c'est le justifié qui ne
       peut pas tenir à cette largeur sans césure, et la césure est
       refusée par l'auteur.

       La règle existait déjà pour le reste du site
       (« .texte p, .chapeau »). Cette page y échappait parce que
       son texte porte une autre classe. */
    text-align: left;
  }

  /* La signature suit la même réduction, et garde EXACTEMENT sa
     proportion : la hauteur vient du rapport du fichier source
     (900 × 260), pas d'un deuxième chiffre à tenir à jour. Une
     signature étirée d'un pixel se voit tout de suite.

     Elle reste à droite, avec un peu de jeu au bord — collée net
     contre la marge, elle avait l'air d'être tombée là. */
  .apropos__signature {
    width: 14rem;
    height: auto;
    aspect-ratio: 900 / 260;
    margin: 1.5rem 0.75rem -5px auto;
  }
}


/* ══ LE BANDEAU COURRIEL SUR PETIT ÉCRAN ═══════════════════════ */

/* Les chevrons et l'heure : présents dans le HTML, effacés ici.
   La ligne « PROCHAINE ENTRÉE · MARDI 29.09.2026 » tient alors
   d'un seul tenant, ce qui est tout ce qu'on lui demande. */
/* « cel-cache » — ce qui existe sur grand écran et s'efface sur
   petit. Une seule règle, écrite ici, pour tout le site : les
   chevrons du bandeau, l'heure de la prochaine parution, les
   coupures de ligne décidées pour une colonne large.

   Le texte n'est jamais écrit deux fois. C'est la même phrase, à
   qui on retire ce qui ne sert plus. */
/* Le tableau des contrats en version etroite. Il ne s'affiche que
   sous le seuil — « cel-seul » s'en charge — et il reprend
   exactement la mise en forme du tableau large : meme fonte, meme
   fond d'en-tete, meme ligne de total en ambre. Seules les
   largeurs changent.

   Le nom prend la moitie; la duree, un quart; le montant, le
   dernier quart, aligne a droite comme tous les chiffres du site. */
.financier--cel { table-layout: fixed; }
/* v65 : le joueur, son contrat, son échéance. */
.financier--cel th:nth-child(1),
.financier--cel td:nth-child(1) { width: 44%; text-align: left; }
.financier--cel th:nth-child(2),
.financier--cel td:nth-child(2) { width: 24%; text-align: right; }
.financier--cel th:nth-child(3),
.financier--cel td:nth-child(3) { width: 32%; text-align: right; }
/* Vu à 360 px : la pastille touchait le cadre. Un peu d'air au bout,
   et la pastille se serre contre l'année. */
.financier--cel th:last-child,
.financier--cel td:last-child { padding-right: 0.625rem; }
.financier--cel .financier__statut { min-width: 0; padding: 0 0.25rem; }
.financier--cel .financier__echeance { gap: 0.25rem; }
.financier--cel td:first-child { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }


/* Et son contraire : « cel-seul » n'existe QUE sur petit ecran.
   Les deux marqueurs vont par paire — l'un efface ce qui ne sert
   plus, l'autre pose ce qui manque. */
.cel-seul { display: none; }

@media (max-width: 1000px) {
  .cel-cache { display: none; }
  .cel-seul { display: inline; }
  /* Une table reste une table : « inline » la casserait. */
  table.cel-seul { display: table; }
  .courriel__e { white-space: nowrap; }

  /* Le plafond et le plancher, réduits de moitié. Sur grand écran
     le bandeau est une bande dans une page longue et il a besoin
     de son air pour se détacher; sur un téléphone il occupe déjà
     tout l'écran — l'air devient du vide. */
  .courriel { padding-top: 1.0625rem; padding-bottom: 1.3125rem; }

  /* L'écart entre la fin du contenu et le bandeau, réduit de
     moitié. Les deux valeurs se cumulent — le bas de la page, puis
     la marge du bandeau — et 68 px de vide entre deux blocs, c'est
     un dixième de l'écran d'un téléphone.

     ⚠ Ces deux règles valent pour TOUTES les pages, pas seulement
     Le mur : le bandeau est le même partout, et deux écarts
     différents selon la page se verraient. */
  .page { padding-bottom: 1.125rem; }
  .courriel { margin-top: 0.75rem; }

  /* La glose sous l'accroche : deux phrases séparées par une ligne
     vide, un cran plus petites. La ligne vide vient du « \n\n » de
     config.json — c'est l'auteur qui décide où elle tombe, pas la
     feuille. */
  .courriel__s { font-size: 0.9375rem; }
}

/* Le point de coupure de l'accroche. Le « | » de config.json
   devient une boîte vide : invisible et sans effet tant qu'elle
   reste en ligne, elle force le retour dès qu'elle devient un
   bloc.

   La coupure est donc DÉCIDÉE, pas subie — et elle est décidée à
   l'endroit où l'auteur écrit sa phrase, pas dans la feuille. */
.coupure-cel { display: none; }
@media (max-width: 1000px) {
  .coupure-cel { display: block; }
}


/* ══ LA VEDETTE TACTILE — LE PANNEAU RESTE FERMÉ ═══════════════
   Sur un écran tactile, il n'y a pas de survol. Le panneau était
   donc ouvert d'office, sinon la moitié du contenu aurait été
   inatteignable.

   Mais un panneau ouvert d'office cache la PHOTO — celle qu'on a
   choisie pour donner envie de cliquer. Sur un téléphone, elle
   occupe presque tout l'écran : la sacrifier pour un chapeau,
   c'est se priver de ce qui attire.

   Le panneau reste donc fermé, comme sur grand écran au repos :
   la photo, et le titre par-dessus. Le chapeau et l'amorce s'en
   vont, et le lien « lire la suite » aussi — il n'a plus rien à
   révéler.

   ⚠ CE QUI REMPLACE LE BOUTON. Le titre est déjà un lien; on
   étend sa zone de clic à toute la carte par une couche invisible
   posée dessus. Le doigt n'a donc pas à viser le texte — la photo
   entière ouvre l'article.

   Le lien reste UN lien : la navigation au clavier, le clic du
   milieu, « ouvrir dans un nouvel onglet » fonctionnent tous
   comme avant. */

@media (hover: none) {

  /* Le panneau ne monte plus — et on ne touche PAS à sa
     transformation. Son état de repos est déjà écrit plus haut :
     descendu de toute sa hauteur, MOINS la bande qui laisse voir
     le titre. Le pousser à 100 % l'aurait emporté au complet,
     titre compris. */

  /* Ce qu'il portait s'en va avec lui. */
  .cadre--photo .chapeau,
  .cadre--photo .vedette .texte,
  .cadre--photo .lire-suite { display: none; }

  /* Le titre se rapproche du bord : le rembourrage du panneau
     était calibré pour un texte de lecture, pas pour un titre posé
     sur une photo. */
  .cadre--photo .vedette__corps { padding: 0 0.9375rem; }

  /* — LE TITRE, CENTRÉ DANS SA BANDE —
     Sa boîte prend EXACTEMENT la hauteur de la bande visible :
     celle que le panneau laisse dépasser au repos, soit sa hauteur
     de bande moins ce dont il remonte. Écrite avec les mêmes
     jetons, elle suit si l'un des deux change.

     Le titre se centre alors dans cette boîte — sur une ligne
     comme sur deux, sans réglage à refaire. */
  .cadre--photo .titre-article {
    margin: 0;
    height: calc(var(--photo-bande) - var(--photo-remonte));
    display: flex;
    align-items: center;
  }

  /* Deux lignes au maximum, et ce qui dépasse se termine par des
     points de suspension. Un titre trop long ne doit pas repousser
     la photo ni déborder de sa bande — il se coupe.

     La règle des 40 caractères du cahier reste la bonne mesure :
     ceci est un filet, pas une permission d'écrire long. */
  .cadre--photo .titre-article a {
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
  }

  /* La carte entière devient la zone de clic du titre. */
  .cadre--photo { position: relative; }
  .cadre--photo .titre-article a::after {
    content: "";
    position: absolute;
    inset: 0;
    z-index: 3;
  }
}

/* ── HORS-JEU ─────────────────────────────────────────────────
   Les trois textes s'empilent, et la regle est ECRITE : voir plus
   bas. Compter sur « auto-fit » pour retomber tout seul etait une
   erreur — il retombe a sa largeur a lui, pas au seuil du site.

   Le bouton du banc perd un cran : « Je veux retourner a la page
   d'accueil » passe sur deux lignes a 360 px, ce qui lui donne
   l'air d'un paragraphe plutot que d'un bouton. Il devient donc
   pleine largeur — un bouton qui occupe sa ligne au complet reste
   un bouton, un bouton a moitie plein ne l'est plus.

   Et le « br » du texte d'introduction disparait ici, par
   « cel-cache » : voir la regle commune plus bas.

   ⚠ CE BLOC RESTE APRES TOUS LES AUTRES DE LA SECTION 22. */
@media (max-width: 1000px) {
  .horsjeu__banc {
    display: flex;
    width: 100%;
    height: auto;
    min-height: 2.75rem;
    padding: 0.5rem 1rem 0.35rem;
    font-size: 1.125rem;
    white-space: normal;
    line-height: 1.15;
  }
  /* La boite du texte se resserre encore. A 700 px, le paragraphe
     s'etalait d'un bord a l'autre entre 700 et 1000 px de fenetre,
     pendant que tout le reste s'etait deja resserre.

     En bas de 550 px de fenetre, ce plafond ne sert plus a rien :
     la marge laterale est deja plus contraignante que lui. Il ne
     travaille donc que dans cette bande-la. Valeur d'oeil. */
  .page--horsjeu .fil__intro--centre { max-width: 32rem; }

  .horsjeu .sceau { margin-top: 1.5rem; }

  /* ⚠ UNE COLONNE, ECRITE EXPLICITEMENT.
     « auto-fit » retombe tout seul — mais a la largeur ou les
     colonnes cessent d'entrer, calculee par le navigateur, pas au
     seuil du site. Entre les deux, le texte etait deja en petit
     ecran et les cartes encore a deux colonnes.
     Le seuil est unique : il s'ecrit ici. */
  .horsjeu__liste {
    grid-template-columns: 1fr;
    margin-top: 1.5rem;
    gap: 0.75rem;
  }
  .horsjeu__t a { padding: 0.8125rem 0.9375rem; }
  .horsjeu__titre { font-size: 1.25rem; }
  .horsjeu__chapeau { font-size: 0.9375rem; }
}
