/* ==========================================================================
   LEAKHORN — feuille de style unique
   ==========================================================================

   Blanc, noir, deux aplats de marque. Un seul mode : le fond est blanc pur,
   l'encre est noire pure, partout, sur tous les appareils. Il n'y a plus de
   gris dans ce fichier — ni pour le texte, ni pour les filets. Ce qui était
   hiérarchisé par la couleur l'est désormais par la taille, la graisse et le
   blanc autour.
     rose #FC3A9B · cyan #07C9D8 — fonds pleins et filets uniquement, jamais
     du texte coloré : le texte reste noir ou blanc, le contraste tient partout.

   Interlettrage : zéro. Une seule exception, 0.02em sur les très petites
   capitales (barre de rubriques, pastilles, métadonnées), sans quoi les
   lettres se touchent physiquement à 12 px. C'est le minimum optique, pas un
   effet de style : les anciennes valeurs, 0.09em à 0.15em, sont ce qui donnait
   au site son air de gabarit.

   Zéro script, zéro requête vers un tiers. Le mouvement est en CSS pur.

   Aucun dégradé décoratif, aucune ombre portée floue, aucun flou. Deux
   dégradés et une ombre subsistent, aucun n'est décoratif :
     · le fondu de coupe de la barre de rubriques est un repère de défilement,
       il dit qu'il reste des rubriques à droite ;
     · le halo de l'anneau de focus est une exigence d'accessibilité.
   ========================================================================== */

@font-face {
  font-family: 'Archivo';
  src: url('fonts/archivo.woff2') format('woff2-variations');
  font-weight: 100 900;
  font-stretch: 62% 125%;
  font-display: swap;
}
@font-face {
  font-family: 'Newsreader';
  src: url('fonts/newsreader.woff2') format('woff2-variations');
  font-weight: 200 800;
  font-display: swap;
}

/* ==========================================================================
   1. JETONS
   ========================================================================== */

:root {
  /* Un seul mode. Le réglage système du visiteur n'inverse plus le site :
     ce qui est validé est ce qui s'affiche, partout. */
  color-scheme: light;

  /* Marque. Relevées dans le CDF Canva des posts, jamais recalculées. */
  --pink: #fc3a9b;
  --cyan: #07c9d8;

  /* Surfaces et encres. Blanc pur, noir pur : c'est le parti pris. Le blanc
     cassé et l'encre bleutée de la version précédente donnaient au site un
     voile qui ne se voyait qu'une fois enlevé. */
  --paper: #ffffff;
  --ink: #000000;

  /* Les alias de texte secondaire pointent tous sur l'encre : plus aucun
     niveau de gris. La hiérarchie passe par le corps, la graisse et le blanc.
     Ces variables restent déclarées pour ne pas avoir à réécrire chaque règle,
     et pour qu'un futur ajout ne réintroduise pas un gris par la bande. */
  --ink-2: var(--ink);
  --muted: var(--ink);

  /* Deux surfaces non blanches subsistent, et une seule raison à chacune :
     le noir plein des blocs graphiques (tuile de secours, encarts) et le
     blanc du papier. Rien entre les deux. */
  --fill: #000000;

  /* Filets. Noirs, fins, et rares : un filet noir sépare mieux que trois
     filets gris. Le filet fort marque les têtes de section. */
  --line: #000000;
  --rule: #000000;

  /* Le pied de page n'est plus un îlot sombre. C'est la même page, séparée
     par un filet épais — un journal ne change pas de papier en bas de page. */
  --footer-bg: #ffffff;
  --footer-fg: #000000;
  --footer-muted: #000000;
  --footer-line: #000000;
  --footer-input: #ffffff;

  /* Anneau de focus : trait noir doublé d'un halo blanc, pour rester visible
     aussi bien sur le papier que sur une pastille rose ou une tuile photo. */
  --focus: #000000;
  --focus-halo: #ffffff;

  --accent: var(--pink);

  /* ⚠ POLICES PROVISOIRES.
     Archivo et Newsreader ne sont PAS les polices de la charte : ce sont deux
     substituts libres, choisis pour approcher la graisse et l'interlignage des
     posts. Les vraies polices sont dans le fichier Canva (références internes
     YADsg7KMEKM pour les titres, YAFdJojEC3M pour la pastille) ; leurs noms se
     lisent dans la barre d'outils Canva en cliquant sur un bloc de texte.
     Une fois les noms connus et la licence web vérifiée, il suffit de remplacer
     les deux @font-face en haut de ce fichier et ces deux lignes.
     Sur les tuiles, la question ne se pose pas : le titre est dans l'image. */
  --display: 'Archivo', 'Helvetica Neue', Arial, sans-serif;
  --serif: 'Newsreader', Georgia, 'Times New Roman', serif;

  /* Échelle typographique. Une seule source, pour que le rythme tienne d'une
     page à l'autre. L'écart entre les degrés a été creusé : c'est lui qui
     porte la hiérarchie maintenant que le gris ne la porte plus. */
  --t-micro: 0.72rem;
  --t-label: 0.78rem;
  --t-small: 0.9rem;
  --t-body: 1rem;
  --t-read: clamp(1.12rem, 1rem + 0.45vw, 1.26rem);
  --t-lede: clamp(1.2rem, 1rem + 0.9vw, 1.5rem);
  --t-h2: clamp(1.5rem, 1.1rem + 1.6vw, 2.2rem);
  --t-h1: clamp(2.2rem, 1.25rem + 4.4vw, 4.4rem);

  /* Rythme vertical. Une gamme, pas des clamp() improvisés à chaque section.
     Les deux derniers degrés sont plus larges qu'avant : le blanc est la
     seule matière décorative qui reste. */
  --s-1: 6px;
  --s-2: 10px;
  --s-3: 16px;
  --s-4: 26px;
  --s-5: clamp(32px, 4.5vw, 48px);
  --s-6: clamp(48px, 7vw, 80px);
  --s-7: clamp(72px, 10vw, 128px);

  --wrap: 1240px;
  --gap: clamp(16px, 2.4vw, 30px);

  /* Une seule famille de rayons : angles francs partout, pastille en gélule.
     Rien d'autre n'est arrondi sur ce site. */
  --r-0: 0px;
  --r-pill: 999px;

  /* Courbes et durées.
     Trois principes repris de l'école Emil Kowalski (animations.dev), qui vont
     bien avec un site sans JavaScript :
       1. court. Une interface qui répond en 150 ms est perçue comme instantanée ;
          au-delà de 400 ms, l'animation devient une attente.
       2. sortie douce. On accélère vite puis on freine longuement (`ease-out`),
          jamais l'inverse : le mouvement doit avoir l'air d'arriver, pas de partir.
       3. transform et opacity seulement. Tout le reste repasse par la mise en
          page et saute sur mobile. */
  --ease-out: cubic-bezier(0.23, 1, 0.32, 1);      /* entrées, sorties, survols */
  --ease-drawer: cubic-bezier(0.32, 0.72, 0, 1);   /* course longue, très amortie */
  --d-press: 120ms;   /* retour d'appui */
  --d-fast: 160ms;    /* changement de couleur */
  --d-base: 240ms;    /* survol, révélation */
  --d-slow: 300ms;    /* plafond : au-delà, l'interface est perçue comme lente */
}

[data-accent='cyan'] { --accent: var(--cyan); }
[data-accent='pink'] { --accent: var(--pink); }

/* ==========================================================================
   2. BASE
   ========================================================================== */

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

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  background: var(--paper);
}
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
}

body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--display);
  font-size: 17px;
  line-height: 1.5;
  letter-spacing: 0;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

a { color: inherit; text-decoration: none; }
img { display: block; max-width: 100%; }
button, input { font: inherit; }

.wrap {
  width: 100%;
  max-width: var(--wrap);
  margin: 0 auto;
  padding: 0 clamp(18px, 4vw, 40px);
}

.sr {
  position: absolute;
  width: 1px; height: 1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
}

/* L'anneau de focus est doublé : trait noir, halo blanc. Il reste donc
   visible sur le papier, sur une pastille de couleur et sur une tuile
   photographique. */
:focus-visible {
  outline: 3px solid var(--focus);
  outline-offset: 2px;
  box-shadow: 0 0 0 6px var(--focus-halo);
}

/* Filet de tête : deux aplats francs, pas de dégradé. C'est la seule couleur
   qui apparaît avant le premier mot de la page. */
.topline { display: flex; height: 6px; }
.topline span { flex: 1; }
.topline span:first-child { background: var(--pink); }
.topline span:last-child { background: var(--cyan); }

/* Étiquette générique : petites capitales à 0.02em, pas davantage.
   Sert de base à la barre du haut, aux fils d'Ariane et aux métadonnées. */
.topbar__inner,
.crumbs,
.byline,
.card__meta,
.page__count {
  font-family: var(--display);
  font-size: var(--t-micro);
  font-weight: 600;
  letter-spacing: 0.02em;
  text-transform: uppercase;
}

/* ---------- pastille de rubrique ---------- */

.pill {
  display: inline-block;
  background: var(--accent);
  color: #000;
  font-family: var(--display);
  font-weight: 700;
  font-size: 0.74rem;
  letter-spacing: 0.02em;
  line-height: 1;
  padding: 0.5em 0.85em 0.55em;
  border-radius: var(--r-pill);
  white-space: nowrap;
}

/* ==========================================================================
   3. EN-TÊTE
   ========================================================================== */

/* Le bandeau de service est sur le même papier que le reste : un aplat gris
   clair en haut de page était le premier gris rencontré, et le seul dont
   personne n'avait besoin. Un filet le sépare, cela suffit. */
.topbar {
  border-bottom: 1px solid var(--line);
  background: var(--paper);
}
.topbar__inner {
  max-width: var(--wrap);
  margin: 0 auto;
  padding: 10px clamp(18px, 4vw, 40px) 10px;
  display: flex;
  align-items: center;
  gap: var(--s-2);
  color: var(--ink);
}
.topbar__inner > span,
.topbar__inner > a { white-space: nowrap; }
.topbar__sep { flex: 1 1 auto; min-width: 8px; }
@media (max-width: 620px) { .topbar__tag { display: none; } }
.topbar a { color: var(--ink); }
.topbar a:hover { text-decoration: underline; text-underline-offset: 3px; }

.masthead {
  padding: var(--s-5) 0 var(--s-4);
  text-align: center;
}

/* Variante compacte, utilisée sur les pages article.
   Le site est distribué par lien : le visiteur arrive sur un article, pas sur
   l'accueil. Trois bandeaux de chrome avant le titre lui coûtent un écran
   entier de défilement sur mobile. Ici le bloc de tête tient en une ligne. */
.masthead--compact {
  padding: var(--s-3) 0 var(--s-3);
}
.masthead--compact .wordmark img { height: clamp(44px, 6.5vw, 58px); }
.masthead--compact .wordmark__fallback { font-size: clamp(1.5rem, 5vw, 2.1rem); }
.masthead--compact .baseline { display: none; }

/* Le logo est une image : il n'est jamais reconstitué en typographie.
   `.wordmark__fallback` n'apparaît que si le fichier manque encore. */
.wordmark { display: inline-block; max-width: 100%; }
/* On contraint la hauteur, pas la largeur : un logo se cale sur sa hauteur de
   bandeau, quelles que soient ses proportions.
   Le logo est un écusson, pas un logotype horizontal : ses proportions sont
   proches du carré (563 × 449). Calé sur sa hauteur, il faut donc le monter
   plus haut qu'un lettrage en bandeau pour qu'il occupe la même largeur
   optique dans la tête de page. */
.wordmark img {
  display: block;
  height: clamp(88px, 13vw, 168px);
  width: auto;
  max-width: 100%;
  margin: 0 auto;
}
.wordmark__fallback,
.footer__wordmark .wordmark__fallback {
  display: inline-block;
  font-family: var(--display);
  font-weight: 900;
  font-size: clamp(2.9rem, 11vw, 6.4rem);
  line-height: 0.86;
  letter-spacing: -0.02em;
  text-transform: uppercase;
  color: var(--ink);
}

.baseline {
  font-family: var(--serif);
  font-size: clamp(0.98rem, 1.6vw, 1.12rem);
  font-style: italic;
  color: var(--ink);
  margin: var(--s-2) 0 0;
}

/* ---------- navigation ---------- */

.nav {
  position: sticky;
  top: 0;
  z-index: 20;
  background: var(--paper);
  border-top: 1px solid var(--rule);
  border-bottom: 1px solid var(--rule);
}
.nav__inner {
  display: flex;
  align-items: center;
  justify-content: flex-start;
  gap: 0;
  overflow-x: auto;
  overscroll-behavior-x: contain;
  scrollbar-width: none;
  padding: 0 clamp(18px, 4vw, 40px);
  max-width: var(--wrap);
  margin: 0 auto;
  /* Sur mobile la barre déborde. Le fondu de coupe à droite dit qu'il reste
     des rubriques, au lieu de laisser croire que la liste s'arrête là. */
  -webkit-mask-image: linear-gradient(90deg, #000 0, #000 calc(100% - 28px), transparent 100%);
  mask-image: linear-gradient(90deg, #000 0, #000 calc(100% - 28px), transparent 100%);
}
@media (min-width: 1240px) {
  .nav__inner { -webkit-mask-image: none; mask-image: none; }
}
.nav__inner::-webkit-scrollbar { display: none; }
.nav a {
  position: relative;
  flex: 0 0 auto;
  padding: 14px 14px 12px;
  font-size: 0.74rem;
  font-weight: 600;
  letter-spacing: 0.02em;
  text-transform: uppercase;
  color: var(--ink);
}
/* Le trait de survol est un pseudo-élément mis à l'échelle, pas une bordure
   qui apparaît : la bordure décalerait le texte d'un pixel à chaque survol. */
.nav a::after {
  content: '';
  position: absolute;
  left: 10px; right: 10px; bottom: 0;
  height: 3px;
  background: var(--accent);
  transform: scaleX(0);
  transform-origin: left;
}
.nav a:hover::after,
.nav a[aria-current]::after { transform: scaleX(1); }
/* Sans gris pour éteindre les rubriques inactives, c'est la graisse qui
   distingue la page courante. */
.nav a[aria-current] { font-weight: 800; }
.nav__spacer { flex: 1 1 auto; min-width: 12px; }

@media (prefers-reduced-motion: no-preference) {
  .nav a::after { transition: transform var(--d-base) var(--ease-out); }
}

/* ==========================================================================
   4. TUILE — la composition du post Instagram
   ========================================================================== */

.tile {
  position: relative;
  display: block;
  aspect-ratio: 4 / 5;
  overflow: hidden;
  background: var(--fill);
  isolation: isolate;
  container-type: inline-size;   /* le titre se dimensionne sur la tuile, pas sur l'écran */
}
/* Avec le visuel du post : l'image occupe toute la tuile et rien ne se
   superpose. La pastille, le titre et le logo sont déjà dessus. */
.tile__media {
  position: absolute;
  inset: 0;
  width: 100%; height: 100%;
  object-fit: cover;
  z-index: 0;
}
.tile--img { background: var(--paper); }

/* Sans photo, la tuile devient une affiche : noir plein, titre en blanc, à la
   manière des posts typographiques du compte. Sur un site blanc, ce bloc noir
   est un objet graphique franc — c'est exactement ce qu'on veut d'une tuile
   qui n'a pas d'image.

   Le bloc est centré verticalement et non calé en haut. Au format 4/5, un
   titre court accroché à 9 % du bord laissait les deux tiers inférieurs vides,
   ce qui se voyait surtout sur la grille de /liens/. La réserve basse de 22 %
   garde la place du logo. */
.tile--noimg {
  display: flex;
  flex-direction: column;
  justify-content: center;
  padding: 10% 7.5% 22%;
}
.tile--noimg .tile__body {
  position: static;
  left: auto; right: auto; top: auto; bottom: auto;
}
.tile--noimg .tile__title { font-size: clamp(0.9rem, 8.4cqw, 2.6rem); }

.tile__body {
  position: absolute;
  z-index: 2;
  left: 7.5%;
  right: 7.5%;
  bottom: 8%;
}
.tile .pill { font-size: clamp(0.54rem, 3.1cqw, 0.8rem); }

.tile__title {
  position: relative;
  margin: -6px 0 0;
  padding: 14px 10% 2px 14px;
  font-family: var(--display);
  font-weight: 800;
  font-size: clamp(0.8rem, 6.4cqw, 1.75rem);
  line-height: 0.9;            /* valeur relevée dans le CDF Canva */
  letter-spacing: -0.015em;
  color: #fff;
  text-wrap: balance;
}
/* La barre verticale d'accent, glissée sous la pastille. */
.tile__title::before {
  content: '';
  position: absolute;
  left: 0;
  top: -14px;
  bottom: 4px;
  width: 4px;
  background: var(--accent);
  transform-origin: top;
}

.tile__logo {
  position: absolute;
  z-index: 3;
  left: 50%;
  transform: translateX(-50%);
  bottom: 5.5%;
  width: 34cqw;
  max-width: 190px;
  height: auto;
}

/* Survol et appui.

   Le survol est réservé aux pointeurs fins. Sur un écran tactile, `:hover` se
   déclenche à l'effleurement et reste collé après le relâchement : la tuile
   resterait agrandie sans raison. `(hover: hover) and (pointer: fine)` écarte
   ce cas au lieu d'espérer qu'il ne se produise pas.

   L'appui, lui, concerne tout le monde. Il est volontairement plus rapide que
   le relâchement : c'est ce décalage qui donne la sensation de toucher un
   objet plutôt que de cliquer sur un rectangle.

   Transform et opacity uniquement, rien qui repasse par la mise en page. */
@media (prefers-reduced-motion: no-preference) {
  @media (hover: hover) and (pointer: fine) {
    .tile__media { transition: transform var(--d-slow) var(--ease-out); }
    a:hover .tile__media { transform: scale(1.03); }
  }
  a:active .tile { transform: scale(0.98); transition: transform var(--d-press) var(--ease-out); }
}

/* ---------- carte du feed ---------- */

.card { display: flex; flex-direction: column; gap: var(--s-2); }
.card__kicker {
  font-family: var(--serif);
  font-size: 1.05rem;
  line-height: 1.4;
  color: var(--ink);
  margin: var(--s-2) 0 0;
  text-wrap: pretty;
}
/* Les métadonnées sont séparées du titre par un filet, pas par une pastille
   de couleur : un point coloré devant chaque ligne est une décoration, pas
   une information. */
.card__meta {
  display: flex;
  align-items: baseline;
  gap: var(--s-2);
  margin-top: auto;
  padding-top: var(--s-2);
  border-top: 1px solid var(--line);
  color: var(--ink);
}
/* Le soulignement est une ombre intérieure et non une bordure : il peut donc
   s'épaissir au survol sans déplacer la ligne de base d'un pixel. */
.card__read {
  font-weight: 800;
  color: var(--ink);
  padding-bottom: 2px;
  box-shadow: inset 0 -2px 0 var(--accent);
}
@media (prefers-reduced-motion: no-preference) {
  .card__read { transition: box-shadow var(--d-fast) var(--ease-out); }
}
@media (hover: hover) and (pointer: fine) {
  .card:hover .card__read { box-shadow: inset 0 -5px 0 var(--accent); }
}

/* ==========================================================================
   5. LA UNE
   ========================================================================== */

.lead { padding: var(--s-6) 0 var(--s-5); }
.lead__grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: clamp(22px, 3.2vw, 48px);
  align-items: start;              /* aligné en tête, pas centré : la colonne
                                      de texte commence là où commence l'image */
}
@media (min-width: 860px) {
  /* Asymétrique et non 50/50 : la tuile porte le titre, la colonne de droite
     porte la lecture. Elles n'ont pas le même poids, elles n'ont donc pas la
     même largeur. */
  .lead__grid { grid-template-columns: minmax(0, 0.86fr) minmax(0, 1.14fr); }
  .lead__text { padding-top: 2px; }
}
/* La tuile de une reste au format 4/5 du post, mais plafonnée à 440 px : à
   520 px elle mesurait 650 px de haut et écrasait la colonne de lecture, qui
   se retrouvait avec un tiers de vide en dessous. */
.lead__tile { max-width: 440px; width: 100%; }
.lead__eyebrow {
  display: inline-block;
  background: var(--accent);
  color: #000;
  font-size: var(--t-micro);
  font-weight: 700;
  letter-spacing: 0.02em;
  text-transform: uppercase;
  padding: 6px 10px 7px;
  margin-bottom: var(--s-3);
}
.lead__kicker {
  font-family: var(--display);
  font-weight: 800;
  font-size: var(--t-h2);
  line-height: 1.06;
  letter-spacing: -0.02em;
  margin: 0 0 var(--s-3);
  max-width: 24ch;
  text-wrap: balance;
}
.lead__lede {
  font-family: var(--serif);
  font-size: var(--t-lede);
  line-height: 1.5;
  color: var(--ink);
  margin: 0 0 var(--s-4);
  max-width: 44ch;
  text-wrap: pretty;
}

/* ==========================================================================
   6. GRILLES ET TÊTES DE SECTION
   ========================================================================== */

/* La tête de section est un vrai titre, pas une micro-étiquette en capitales
   posée au-dessus de chaque bloc. Le filet fait le travail de séparation. */
.section-head {
  display: flex;
  align-items: baseline;
  gap: var(--s-3);
  margin: var(--s-6) 0 var(--s-4);
  border-bottom: 1px solid var(--rule);
  padding-bottom: var(--s-2);
}
.section-head h2 {
  margin: 0;
  font-family: var(--display);
  font-size: clamp(1.3rem, 1rem + 1vw, 1.8rem);
  font-weight: 800;
  letter-spacing: -0.02em;
  text-transform: none;
  color: var(--ink);
}
.section-head .rule { flex: 1; }
.section-head .count {
  font-size: var(--t-micro);
  font-weight: 600;
  letter-spacing: 0.02em;
  text-transform: uppercase;
  color: var(--ink);
  white-space: nowrap;
}

.grid {
  display: grid;
  gap: var(--s-5) var(--gap);
  grid-template-columns: repeat(2, minmax(0, 1fr));
}
@media (min-width: 700px) { .grid { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
@media (min-width: 1020px) { .grid { grid-template-columns: repeat(4, minmax(0, 1fr)); } }

/* ==========================================================================
   7. BOUTONS
   ========================================================================== */

.btn {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  background: var(--ink);
  color: var(--paper);
  font-weight: 700;
  font-size: 0.8rem;
  letter-spacing: 0.02em;
  text-transform: uppercase;
  padding: 14px 22px;
  border: 1px solid var(--ink);
  border-radius: var(--r-0);
  white-space: nowrap;           /* un libellé de bouton ne passe jamais à la ligne */
  cursor: pointer;
}
.btn--ghost { background: transparent; color: var(--ink); }
@media (hover: hover) and (pointer: fine) {
  .btn:hover { background: var(--accent); color: #000; border-color: var(--accent); }
  .btn--ghost:hover { background: var(--ink); color: var(--paper); border-color: var(--ink); }
}
/* L'échelle plutôt que le décalage vertical : un bouton qui rétrécit de trois
   pour cent se lit comme un objet qu'on enfonce, un bouton qui descend d'un
   pixel se lit comme un défaut d'alignement. */
.btn:active { transform: scale(0.97); }

@media (prefers-reduced-motion: no-preference) {
  .btn {
    transition:
      background-color var(--d-fast) var(--ease-out),
      color var(--d-fast) var(--ease-out),
      border-color var(--d-fast) var(--ease-out),
      transform var(--d-press) var(--ease-out);
  }
}

/* ==========================================================================
   8. ARTICLE — la page d'entrée du site
   ========================================================================== */

.article { padding: var(--s-5) 0 0; }
.article__inner { max-width: 720px; margin: 0 auto; }

.crumbs {
  display: flex;
  align-items: center;
  gap: 9px;
  color: var(--ink);
  margin-bottom: var(--s-4);
}
.crumbs a:hover { text-decoration: underline; text-underline-offset: 3px; }

h1.article__title {
  font-family: var(--display);
  font-weight: 800;
  font-size: var(--t-h1);
  line-height: 0.95;
  letter-spacing: -0.025em;
  margin: var(--s-3) 0 var(--s-4);
  text-wrap: balance;
  /* Réserve sous la ligne de base : les titres portent des guillemets et des
     lettres à jambage, un interlignage inférieur à 1 les rognerait sinon. */
  padding-bottom: 2px;
}

.article__lede {
  font-family: var(--serif);
  font-size: var(--t-lede);
  line-height: 1.45;
  color: var(--ink);
  margin: 0 0 var(--s-4);
  padding-left: var(--s-3);
  border-left: 4px solid var(--accent);
  text-wrap: pretty;
}

.byline {
  display: flex;
  align-items: center;
  gap: var(--s-2) var(--s-3);
  flex-wrap: wrap;
  color: var(--ink);
  padding: var(--s-2) 0;
  border-top: 1px solid var(--line);
  border-bottom: 1px solid var(--line);
  margin-bottom: var(--s-5);
}
.byline strong { color: var(--ink); font-weight: 800; }

.article__cover { margin: 0 auto var(--s-5); max-width: 420px; }

.prose {
  font-family: var(--serif);
  font-size: var(--t-read);
  line-height: 1.7;
  color: var(--ink);
}
.prose p { margin: 0 0 1.35em; text-wrap: pretty; }
/* L'attaque est plus grande que le reste : c'est la seule marque de rang dans
   le corps de l'article, et elle suffit. */
.prose p:first-of-type {
  font-size: 1.1em;
  line-height: 1.6;
}
.prose .pull {
  margin: 2em 0;
  padding: 0 0 0 22px;
  border-left: 4px solid var(--accent);
  font-family: var(--display);
  font-weight: 800;
  font-size: clamp(1.25rem, 2.6vw, 1.7rem);
  line-height: 1.14;
  letter-spacing: -0.02em;
  color: var(--ink);
  text-wrap: balance;
}

/* Renvoi vers le post d'origine. Volontairement traité en bloc ouvert, filets
   haut et bas, et non en cadre fermé : l'encart « Vous êtes sur LEAKHORN »
   quelques lignes plus bas est déjà un bloc plein. Deux cadres identiques qui
   s'enchaînent en pied d'article se lisent comme un seul motif répété. */
.ig-box {
  margin: var(--s-6) 0 0;
  border-top: 1px solid var(--ink);
  border-bottom: 1px solid var(--line);
  padding: var(--s-4) 0;
}
.ig-box__label {
  font-size: var(--t-micro);
  font-weight: 600;
  letter-spacing: 0.02em;
  text-transform: uppercase;
  color: var(--ink);
  margin-bottom: var(--s-2);
}
.ig-box__quote {
  font-family: var(--display);
  font-weight: 800;
  font-size: clamp(1.1rem, 2.2vw, 1.35rem);
  line-height: 1.2;
  letter-spacing: -0.015em;
  margin: 0 0 var(--s-3);
  text-wrap: pretty;
}

.note {
  margin: var(--s-5) 0 0;
  font-size: var(--t-small);
  line-height: 1.6;
  color: var(--ink);
  border-top: 1px solid var(--line);
  padding-top: var(--s-3);
  max-width: 68ch;
}

/* Encart de présentation : la plupart des visiteurs arrivent ici sans
   connaître le site, il faut leur dire où ils ont atterri. C'est aussi la
   pièce qui matérialise le caractère parodique, page par page.
   Le fond gris clair a laissé place à un encadré noir d'un pixel : sur un
   papier blanc, le trait sépare mieux qu'un aplat à peine plus foncé. */
.whatis {
  margin: var(--s-6) 0 0;
  background: var(--paper);
  border: 1px solid var(--ink);
  border-top-width: 4px;
  padding: clamp(22px, 3.4vw, 34px);
}
.whatis h2 {
  margin: 0 0 var(--s-2);
  font-family: var(--display);
  font-size: 1.15rem;
  font-weight: 800;
  letter-spacing: -0.015em;
}
.whatis p {
  font-family: var(--serif);
  font-size: 1.08rem;
  line-height: 1.6;
  color: var(--ink);
  margin: 0 0 var(--s-3);
  max-width: 62ch;
  text-wrap: pretty;
}
.whatis__actions { display: flex; gap: var(--s-2); flex-wrap: wrap; }

/* ==========================================================================
   9. PIED DE PAGE
   ========================================================================== */

/* Le pied de page n'est plus un îlot sombre : même papier, même encre, séparé
   par un filet épais. Un bloc noir en bas d'un site blanc est un vestige de
   gabarit, pas une hiérarchie. */
.footer {
  margin-top: var(--s-7);
  background: var(--footer-bg);
  color: var(--footer-fg);
  padding: var(--s-6) 0 0;
  border-top: 4px solid var(--ink);
}
.footer__top {
  display: grid;
  gap: var(--s-5);
  grid-template-columns: 1fr;
  padding-bottom: var(--s-5);
}
@media (min-width: 720px) { .footer__top { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (min-width: 1000px) { .footer__top { grid-template-columns: 1.15fr 0.85fr 0.85fr 1.5fr; } }

.footer__wordmark { display: inline-block; margin-bottom: var(--s-3); }
.footer__wordmark img { display: block; height: 84px; width: auto; max-width: 100%; }
.footer__wordmark .wordmark__fallback { font-size: 2rem; color: var(--footer-fg); }
.footer__baseline {
  font-family: var(--serif);
  font-style: italic;
  color: var(--ink);
  line-height: 1.55;
  margin: 0;
  max-width: 30ch;
}

.footer h3 {
  font-size: var(--t-micro);
  font-weight: 700;
  letter-spacing: 0.02em;
  text-transform: uppercase;
  color: var(--footer-fg);
  margin: 0 0 var(--s-3);
}
.footer ul { list-style: none; margin: 0; padding: 0; }
.footer li { margin-bottom: 10px; }
.footer li a { color: var(--ink); font-size: 0.95rem; }
.footer li a:hover { text-decoration: underline; text-underline-offset: 3px; }

/* bloc newsletter */
.news__intro {
  font-family: var(--serif);
  color: var(--ink);
  line-height: 1.55;
  margin: 0 0 var(--s-3);
  max-width: 40ch;
}
.news__form { display: flex; flex-wrap: wrap; gap: 8px; }
.news__input {
  flex: 1 1 200px;
  min-width: 0;
  background: var(--footer-input);
  border: 1px solid var(--ink);
  color: var(--ink);
  padding: 13px 14px;
  font-size: 0.95rem;
  border-radius: var(--r-0);
}
/* La mention d'aide est noire comme le reste, à pleine opacité. Le
   placeholder gris est le dernier endroit où le gris se cache d'habitude ;
   ici le champ est reconnaissable à son cadre, pas à la pâleur de son texte. */
.news__input::placeholder { color: var(--ink); opacity: 1; }
.news__input:focus-visible { outline: 3px solid var(--ink); outline-offset: -1px; box-shadow: none; }
.news__btn {
  flex: 0 0 auto;
  background: var(--pink);
  color: #000;
  border: 1px solid var(--pink);
  font-weight: 700;
  font-size: 0.78rem;
  letter-spacing: 0.02em;
  text-transform: uppercase;
  padding: 13px 20px;
  white-space: nowrap;
  cursor: pointer;
}
.news__btn:hover { background: var(--ink); color: var(--paper); border-color: var(--ink); }
.news__legal {
  font-size: 0.78rem;
  color: var(--ink);
  line-height: 1.5;
  margin: var(--s-2) 0 0;
  max-width: 46ch;
}

/* rangée sociale */
.footer__social {
  display: flex;
  align-items: center;
  gap: var(--s-2);
  border-top: 1px solid var(--footer-line);
  padding: var(--s-3) 0;
}
.footer__social a {
  display: grid;
  place-items: center;
  width: 42px;
  height: 42px;
  border: 1px solid var(--ink);
  color: var(--ink);
}
.footer__social a:hover { color: var(--paper); background: var(--ink); }
.footer__social svg { width: 19px; height: 19px; fill: currentColor; }
@media (prefers-reduced-motion: no-preference) {
  .footer__social a { transition: color var(--d-fast) var(--ease-out), background-color var(--d-fast) var(--ease-out); }
}

/* barre légale */
.footer__legal {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 6px 18px;
  border-top: 1px solid var(--footer-line);
  padding: var(--s-3) 0;
  font-size: 0.8rem;
  color: var(--ink);
}
.footer__legal a:hover { text-decoration: underline; text-underline-offset: 3px; }

.footer__disclaimer {
  border-top: 1px solid var(--footer-line);
  padding: var(--s-3) 0 var(--s-5);
  font-size: 0.85rem;
  line-height: 1.65;
  color: var(--ink);
  max-width: 78ch;
  margin: 0;
}
/* Le seul mot en couleur du pied de page, et il est là pour être vu. */
.footer__disclaimer strong { color: #000; background: var(--pink); padding: 1px 6px; }

/* ==========================================================================
   10. PAGE LINK IN BIO — /liens/
   ========================================================================== */

/* 100dvh et non 100vh : sur iOS la barre d'adresse fait varier vh, ce qui
   provoque un saut de mise en page au premier défilement. */
.lib { min-height: 100dvh; }
.lib__wrap { max-width: 960px; }
.lib__head { text-align: center; padding: var(--s-6) 0 var(--s-5); }
.lib__logo {
  display: inline-grid;
  place-items: center;
  width: clamp(104px, 24vw, 132px);
  aspect-ratio: 1;
  border-radius: var(--r-pill);
  overflow: hidden;
  background: var(--ink);
  margin-bottom: var(--s-3);
}
.lib__logo img { width: 100%; height: 100%; object-fit: cover; }
.lib__logo span {
  font-family: var(--display);
  font-weight: 900;
  font-size: clamp(1.05rem, 3.2vw, 1.35rem);
  line-height: 0.86;
  text-transform: uppercase;
  text-align: center;
  color: var(--paper);
}
.lib__handle {
  font-family: var(--display);
  font-weight: 800;
  font-size: 1.1rem;
  letter-spacing: -0.01em;
  margin: 0 0 var(--s-1);
}
.lib__bio {
  font-family: var(--serif);
  font-style: italic;
  color: var(--ink);
  margin: 0 auto var(--s-4);
  max-width: 36ch;
  line-height: 1.5;
}
.lib__actions { display: flex; gap: var(--s-2); justify-content: center; flex-wrap: wrap; }

.lib__grid {
  display: grid;
  gap: 10px;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  padding-bottom: var(--s-4);
}
@media (min-width: 620px) { .lib__grid { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
@media (min-width: 900px) { .lib__grid { grid-template-columns: repeat(4, minmax(0, 1fr)); } }

.lib__tile { position: relative; }
.lib__cta {
  position: absolute;
  inset: 0;
  z-index: 4;
  display: grid;
  place-items: center;
  background: rgba(0, 0, 0, 0.72);
  opacity: 0;
}
.lib__tile:hover .lib__cta,
.lib__tile:focus-visible .lib__cta { opacity: 1; }
.lib__cta span {
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.02em;
  text-transform: uppercase;
  color: #fff;
  border: 1px solid #fff;
  padding: 10px 16px;
}
@media (prefers-reduced-motion: no-preference) {
  .lib__cta { transition: opacity var(--d-base) var(--ease-out); }
  .lib__tile:active { transform: scale(0.985); transition: transform 90ms ease-out; }
}

.lib__foot {
  text-align: center;
  padding: var(--s-5) 0;
  border-top: 1px solid var(--line);
  font-size: 0.85rem;
  color: var(--ink);
  line-height: 1.7;
  max-width: 62ch;
  margin: 0 auto;
}
.lib__foot a { color: var(--ink); border-bottom: 2px solid var(--accent); }

/* ==========================================================================
   11. PAGE SIMPLE (à propos, mentions, rubrique, 404)
   ========================================================================== */

.page { padding: var(--s-6) 0; }
.page__inner { max-width: 720px; }
.page h1 {
  font-family: var(--display);
  font-weight: 800;
  font-size: clamp(2.1rem, 1.3rem + 3vw, 3.4rem);
  line-height: 0.98;
  letter-spacing: -0.025em;
  margin: 0 0 var(--s-4);
  text-wrap: balance;
}
.page h2 {
  font-family: var(--display);
  font-weight: 800;
  font-size: 1.15rem;
  letter-spacing: -0.015em;
  text-transform: none;
  margin: 2em 0 0.6em;
}
.page__inner p,
.page__inner li {
  font-family: var(--serif);
  font-size: 1.1rem;
  line-height: 1.65;
  color: var(--ink);
  text-wrap: pretty;
}
.page__inner a { border-bottom: 2px solid var(--accent); }
.page__inner code {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 0.9em;
  background: var(--paper);
  border: 1px solid var(--ink);
  padding: 1px 5px;
}
.page__title-cat {
  font-family: var(--display);
  font-weight: 800;
  font-size: clamp(2.2rem, 1.3rem + 3.2vw, 3.6rem);
  line-height: 0.98;
  letter-spacing: -0.025em;
  margin: var(--s-3) 0 var(--s-1);
}
.page__count {
  color: var(--ink);
  margin: 0 0 var(--s-5);
  padding-bottom: var(--s-3);
  border-bottom: 1px solid var(--rule);
}
.todo {
  background: var(--paper);
  border: 1px solid var(--ink);
  border-left: 4px solid var(--pink);
  padding: 14px 16px;
  font-family: var(--display) !important;
  font-size: 0.95rem !important;
  color: var(--ink) !important;
}

/* ==========================================================================
   12. MOUVEMENT SANS JAVASCRIPT
   ==========================================================================

   Deux mécanismes récents, tous deux entièrement déclaratifs. Aucun script,
   aucun observateur, aucun écouteur de défilement — donc rien à nettoyer et
   rien qui puisse casser. Les navigateurs qui ne les connaissent pas ignorent
   simplement les règles : le site reste identique, sans transition.
   ========================================================================== */

/* ---------- 12.1 transitions de page ----------
   Le site est un ensemble de documents statiques. `@view-transition` fait
   enchaîner deux pages par un fondu court au lieu du flash blanc habituel.
   C'est ce qui rend un site en HTML pur proche d'une application, sans en
   payer le prix. Volontairement limité au document entier : nommer des
   éléments individuels obligerait à garantir l'unicité des noms sur chaque
   page, et un doublon annule la transition au lieu de la dégrader. */
@view-transition { navigation: auto; }

::view-transition-group(root) { animation-duration: var(--d-base); }
::view-transition-old(root) { animation: vt-out var(--d-fast) var(--ease-out) both; }
::view-transition-new(root) { animation: vt-in var(--d-base) var(--ease-out) both; }

@keyframes vt-out { to { opacity: 0; } }
@keyframes vt-in { from { opacity: 0; transform: translateY(6px); } }

@media (prefers-reduced-motion: reduce) {
  @view-transition { navigation: none; }
}

/* ---------- 12.2 apparition au défilement ----------
   `animation-timeline: view()` lie l'animation à la position de l'élément dans
   la fenêtre plutôt qu'à une horloge. Les cartes montent de huit pixels en
   entrant dans le champ, une seule fois, et ne bougent plus ensuite.

   Le garde-fou compte : la règle vit sous `@supports`, donc là où la fonction
   n'existe pas encore, aucune opacité nulle n'est jamais posée. Un contenu
   qui reste invisible parce qu'une animation n'a pas démarré est le pire
   défaut de cette technique ; ici il est structurellement impossible. */
@supports (animation-timeline: view()) {
  @media (prefers-reduced-motion: no-preference) {
    .grid > .card,
    .section-head,
    .whatis,
    .ig-box {
      animation: rise-in linear both;
      animation-timeline: view();
      animation-range: entry 0% entry 42%;
    }
  }
}

@keyframes rise-in {
  from { opacity: 0; transform: translateY(8px); }
  to { opacity: 1; transform: none; }
}

/* ==========================================================================
   13. PRÉFÉRENCES SYSTÈME
   ========================================================================== */

/* Mouvement réduit ne veut pas dire aucune animation : cela veut dire aucun
   DÉPLACEMENT. Les changements de couleur et d'opacité aident à comprendre ce
   qui vient de se passer, on les garde ; les translations, les mises à
   l'échelle et les révélations au défilement partent. */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation: none !important;
    transition-property: color, background-color, border-color, box-shadow, opacity, outline-color !important;
    transition-duration: 160ms !important;
    scroll-behavior: auto !important;
  }
  /* La barre de rubrique active est exclue : son `scaleX(1)` n'est pas un
     mouvement, c'est ce qui la rend visible. La neutraliser effacerait
     l'indication de page courante. */
  .tile__media,
  .tile,
  .btn,
  .lib__tile {
    transform: none !important;
  }
}

/* Contraste renforcé : il n'y a plus de gris à durcir. Reste à épaissir les
   filets, qui sont la seule chose fine du site. */
@media (prefers-contrast: more) {
  .nav, .section-head, .byline, .card__meta, .note, .footer__legal { border-width: 2px; }
}

@media print {
  .nav, .footer, .topbar, .whatis, .ig-box, .lib__cta { display: none; }
  body { font-size: 12pt; background: #fff; color: #000; }
  .article__inner, .page__inner { max-width: none; }
  a[href^='http']::after { content: ' (' attr(href) ')'; font-size: 9pt; word-break: break-all; }
}
