/* ═══════════════════════════════════════════════════════════
   POLICES AUTO-HÉBERGÉES (RGPD — CLAUDE.md §8)
   Aucune police n'est chargée depuis Google Fonts.
   Toutes les familles sont servies en local (woff2) depuis
   assets/fonts/, avec font-display: swap.
   Trois familles : Ubuntu (voix du site), Spectral (œuvres &
   citations), Ubuntu Sans Mono (cartel technique).
   ═══════════════════════════════════════════════════════════ */

/* ── Ubuntu — la voix du site ── */
@font-face {
  font-family: "Ubuntu";
  font-style: normal;
  font-weight: 300;
  font-display: swap;
  src: url("../fonts/Ubuntu-Light.woff2") format("woff2");
}
@font-face {
  font-family: "Ubuntu";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("../fonts/Ubuntu-Regular.woff2") format("woff2");
}
@font-face {
  font-family: "Ubuntu";
  font-style: italic;
  font-weight: 400;
  font-display: swap;
  src: url("../fonts/Ubuntu-Italic.woff2") format("woff2");
}
@font-face {
  font-family: "Ubuntu";
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url("../fonts/Ubuntu-Medium.woff2") format("woff2");
}
@font-face {
  font-family: "Ubuntu";
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url("../fonts/Ubuntu-Bold.woff2") format("woff2");
}

/* ── Spectral — titres d'œuvres & citations ── */
@font-face {
  font-family: "Spectral";
  font-style: normal;
  font-weight: 200;
  font-display: swap;
  src: url("../fonts/Spectral-ExtraLight.woff2") format("woff2");
}
@font-face {
  font-family: "Spectral";
  font-style: italic;
  font-weight: 200;
  font-display: swap;
  src: url("../fonts/Spectral-ExtraLightItalic.woff2") format("woff2");
}
@font-face {
  font-family: "Spectral";
  font-style: normal;
  font-weight: 300;
  font-display: swap;
  src: url("../fonts/Spectral-Light.woff2") format("woff2");
}
@font-face {
  font-family: "Spectral";
  font-style: italic;
  font-weight: 300;
  font-display: swap;
  src: url("../fonts/Spectral-LightItalic.woff2") format("woff2");
}
@font-face {
  font-family: "Spectral";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("../fonts/Spectral-Regular.woff2") format("woff2");
}
@font-face {
  font-family: "Spectral";
  font-style: italic;
  font-weight: 400;
  font-display: swap;
  src: url("../fonts/Spectral-Italic.woff2") format("woff2");
}
@font-face {
  font-family: "Spectral";
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url("../fonts/Spectral-Medium.woff2") format("woff2");
}
@font-face {
  font-family: "Spectral";
  font-style: italic;
  font-weight: 500;
  font-display: swap;
  src: url("../fonts/Spectral-MediumItalic.woff2") format("woff2");
}
@font-face {
  font-family: "Spectral";
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url("../fonts/Spectral-SemiBold.woff2") format("woff2");
}

/* ── Ubuntu Sans Mono — cartel technique (dates, formats, générique) ── */
@font-face {
  font-family: "Ubuntu Sans Mono";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("../fonts/UbuntuSansMono-Regular.woff2") format("woff2");
}
@font-face {
  font-family: "Ubuntu Sans Mono";
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url("../fonts/UbuntuSansMono-Medium.woff2") format("woff2");
}
@font-face {
  font-family: "Ubuntu Sans Mono";
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url("../fonts/UbuntuSansMono-Bold.woff2") format("woff2");
}

/* ═══════════════════════════════════════════════════════════
   Ci-dessous : système graphique repris À L'IDENTIQUE de la
   source validée (_design-source/work/v11.css puis pages.css).
   Aucune valeur de couleur / typo / espacement n'est modifiée.
   ═══════════════════════════════════════════════════════════ */
/* ─────────────────────────────────────────────────────────
   V7 — Atlas DPB
   Charte V5/V6 (Ubuntu + Ubuntu Mono, papier crème, encre)
   N&B strict avec gris chaud comme seul accent.
   ───────────────────────────────────────────────────────── */

:root {
  --sans: "Ubuntu", "Helvetica Neue", Arial, sans-serif;
  --mono: "Ubuntu Sans Mono", ui-monospace, monospace;
  --serif: "Spectral", Georgia, serif;   /* titres d'œuvres & citations (CLAUDE.md §8bis) — disponible partout */

  /* Light — blanc presque pur, à peine chaud */
  --paper:      #fcfcfb;
  --paper-2:    #e8e8e6;     /* surfaces secondaires */
  --paper-3:    #e2dfd6;     /* hover, accents secondaires */
  --ink:        #0a0a0a;

  /* ── COULEURS D'ATLAS — VERROUILLÉES (CLAUDE.md §4-5, ROADMAP Lot 2-2) ──
     Les DEUX seules couleurs du système d'atlas, définies ICI et nulle part
     ailleurs. Valeurs reprises de _design-source/work/v11.css, la source
     validée (l. 441 et 718), où elles n'existaient que comme valeurs de
     repli d'variables jamais déclarées — d'où leur perte lors des reprises.

     Elles servent SANS EXCEPTION leurs trois consommateurs : le tableau de
     l'accueil, les pictos « position dans l'atlas » des fiches, et le
     générateur de portfolios. Jamais de valeur locale, jamais --paper-2 ni
     --paper-3 à leur place : ces derniers sont plus clairs et plus froids,
     et les y substituer délave l'atlas. */
  --atlas-creme: #e0dccf;    /* fond des tableaux carrés (vues 1 et 4) */
  --atlas-gris:  #dededb;    /* remplissage des triangles (vues 3 et 5) */
  --ink-2:      #2a2a28;
  --ink-mute:   #7a7773;
  --ink-faint:  #b8b4ad;
  --rule:       rgba(10,10,8,0.16);
  --rule-soft:  rgba(10,10,8,0.07);
  --grid-line:  rgba(10,10,8,0.12);
  --grid-dot:   rgba(10,10,8,0.28);
  --logo-tint:  #0a0a0a;
  --shadow-card:0 1px 0 rgba(10,10,8,0.04);

  /* ── MÉTRIQUE DE LA GRILLE MÈRE — système Canvas (GABARITS.md §3) ──
     Les trois seules mesures dont dépendent les 19 gabarits. Reprises de
     _design-source/canvas-lot1-grille-3canvas.html, la référence web.
     Elles se projettent à l'identique en A4 (166 × 253 mm portrait) : un
     canvas à l'écran et le même canvas imprimé partagent leur structure. */
  --baseline:   26px;    /* ligne de base — toutes les hauteurs en sont multiples */
  --gutter:     24px;    /* gouttière inter-colonne */
  --measure:  1180px;    /* zone de composition centrée */

  /* ── Géométrie atlas (V11.1 : tableaux réduits ~15%, de 800 → 680) ── */
  --map:        680px;   /* côté du tableau (carré / triangle) */
  --map-top:    28px;    /* buffer haut pour le pôle sommet du triangle */
  --map-left:   10px;
  --map-foot:   42px;    /* zone basse pour l'axe X / pôles bas */
  --panel-w:    360px;

  /* Échelle des marqueurs de l'atlas (style « N »).
     1 = tailles d'origine du design validé · 1.10 = +10 %.
     Réglage du propriétaire : mieux voir les points et dégager les numéros
     de leurs bords. SEUL endroit où la taille des formes se règle — il est
     relu par markerRadiusPx() dans assets/js/main.js pour que
     l'anti-chevauchement suive automatiquement. */
  --pt-scale:   1.10;

  /* Emprise de la ligne 1D de la vue V2, en POURCENTAGE retiré de CHAQUE côté
     du tableau. 15 = réglage d'origine (ligne de 15 % à 85 %) · 8 = ligne
     allongée d'environ 20 %, pour mieux répartir les points.
     Les libellés « Dispositif d'inscription / de rencontre » sont pivotés à
     90°, donc très étroits (17 px) : la marge de 15 % leur était très
     surdimensionnée. SEUL endroit où cette emprise se règle — il est relu par
     posFor() dans assets/js/main.js, qui place les points sur la même plage. */
  --v2-inset:   8;
}
[data-theme="dark"] {
  --paper:      #0a0a09;
  --paper-2:    #0a0a09;     /* fond tableau identique au site en nuit (lisibilité) */
  --paper-3:    #1f1e18;
  --ink:        #f5f3ef;

  /* Atlas en thème sombre. Dans le grand tableau, ces fonds sont de toute
     façon neutralisés (le tableau passe en transparent, les triangles à
     opacité 0) : ces valeurs servent donc surtout aux PICTOS des fiches,
     qui ont besoin d'une assise pour rester lisibles. Reprises du gabarit
     du design source, elles conservent le rendu nocturne validé. */
  --atlas-creme: #1f1e18;
  --atlas-gris:  #0a0a09;
  --ink-2:      #d8d5cf;
  --ink-mute:   #908d86;
  --ink-faint:  #4a4843;
  --rule:       rgba(245,243,239,0.18);
  --rule-soft:  rgba(245,243,239,0.08);
  --grid-line:  rgba(245,243,239,0.07);
  --grid-dot:   rgba(245,243,239,0.18);
  --logo-tint:  #f5f3ef;
}

* { box-sizing: border-box; }
html, body {
  margin: 0; padding: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--sans);
  font-weight: 300;
  font-size: 14px;
  line-height: 1.45;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  transition: background-color 320ms ease, color 320ms ease;
}
body { padding-top: 70px; }
::selection { background: var(--ink); color: var(--paper); }

/* ─── FOCUS CLAVIER — règle générique (LOT 11B, 04/09/2026) ───────────────
   `style.css` ne rendait le focus visible que sur DEUX objets — `.index-row`
   et `.stamp-cell`. Partout ailleurs, le contour était celui du navigateur :
   présent, mais étranger au système graphique et inégal d'un moteur à l'autre.

   Le contour ci-dessous reprend AU CARACTÈRE PRÈS celui de `.index-row` :
   2 px d'encre pleine, décalés de 2 px. **Aucune valeur nouvelle n'est
   inventée** (`CLAUDE.md` §4-1) — c'est le patron existant, généralisé.

   `:focus-visible` et non `:focus` : le contour ne paraît qu'au CLAVIER, jamais
   au clic ni au toucher. Les deux règles d'origine restent en place, plus
   spécifiques ; elles gardent leur décalage propre (2 px et 3 px).

   ⚠️ LES 72 POINTS DE L'ATLAS (`.pt`) N'EN REÇOIVENT RIEN, et c'est voulu ici :
   `.pt:focus { outline: none }` (plus bas) est plus spécifique et l'emporte.
   Le cas est SIGNALÉ au propriétaire, non tranché — voir le handoff. */
a:focus-visible,
button:focus-visible,
input:focus-visible,
select:focus-visible,
textarea:focus-visible,
[tabindex]:focus-visible {
  outline: 2px solid var(--ink);
  outline-offset: 2px;
}

/* ─── Images : glisser-déposer et « enregistrer » découragés ───
   Point h du cahier des charges 7I (consigne du propriétaire, 30/08/2026).
   Le pendant CSS des deux écouteurs de main.js (PARTIE 1) : -webkit-user-drag
   supprime le fantôme de glissement au bureau, -webkit-touch-callout la
   fenêtre « Enregistrer l'image » de l'appui long sur iOS — que preventDefault()
   seul n'arrête pas.
   ⚠️ GÊNE, PAS PROTECTION : l'image reste accessible par le cache, par
   l'inspecteur, par son URL directe et par une capture d'écran.
   Le TEXTE, lui, reste sélectionnable partout : rien ici n'y touche. */
img {
  -webkit-touch-callout: none;
  -webkit-user-drag: none;
  user-drag: none;
}

/* ⚠️ `min(1240px, 100%)` ET NON `1240px` — corrigé au 11B (04/09/2026).
   Une largeur FIXE de 1240 px, alors que le repli mobile n'ouvre qu'à 900 px,
   laissait une plage de 339 px sans réponse : mesuré, l'accueil débordait
   horizontalement de 1 à 339 px entre 901 et 1239 px — la plage des fenêtres
   de bureau réduites et des tablettes en paysage.
   ⚠️ AU-DESSUS DE 1240 px, RIEN NE CHANGE : `min()` rend exactement 1240 px.
   La composition du grand écran est donc intacte (`CLAUDE.md` §2bis-4). */
.page { width: min(1240px, 100%); margin: 0 auto; padding: 0 20px; }

.sep { color: var(--ink-faint); margin: 0 6px; }

/* ──────────── MENUBAR ──────────── */
.menubar {
  position: fixed; top: 0; left: 0; right: 0; z-index: 100;
  background: var(--paper);
  border-bottom: 1px solid var(--rule);
  transition: transform 360ms cubic-bezier(.4,0,.2,1), background-color 320ms ease, border-color 320ms ease;
}
.menubar.is-hidden { transform: translateY(-100%); }
.menubar-inner {
  width: min(1240px, 100%); margin: 0 auto; padding: 0 20px;   /* 11B : voir .page */
  height: 70px;
  display: grid;
  grid-template-columns: 1fr 1fr 1fr;
  align-items: center;
}
.menubar-left { display: flex; align-items: center; gap: 14px; }
.menubar-left .logo-mark {
  display: inline-grid; place-items: center;
  width: 52px; height: 52px;
  border: 0;
  text-decoration: none;
  transition: transform 220ms ease;
  flex-shrink: 0;
}
.menubar-left .logo-mark:hover { transform: rotate(-4deg); }
.menubar-left .logo-img {
  width: 100%;
  height: 100%;
  object-fit: contain;
  display: block;
  filter: var(--logo-filter, none);
}
[data-theme="dark"] .menubar-left .logo-img { filter: invert(1) brightness(1.15); }
.menubar-left .sig {
  display: flex; flex-direction: column; gap: 2px;
  line-height: 1.1;
}
.sig-name {
  font-family: var(--sans);
  font-size: 13px;
  font-weight: 500;
  letter-spacing: 0.01em;
  color: var(--ink);
}
.sig-since {
  font-family: var(--mono);
  font-size: 9px;
  font-weight: 400;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--ink-mute);
}

.menu-nav { display: flex; justify-content: center; gap: 30px; }
.menu-nav a {
  position: relative;
  font-family: var(--sans);
  font-size: 13px;
  font-weight: 400;
  letter-spacing: 0.01em;
  color: var(--ink-2);
  text-decoration: none;
  padding: 4px 0;
  transition: color 160ms ease;
}
.menu-nav a::after {
  content: ""; position: absolute;
  left: 0; right: 0; bottom: -2px; height: 1px;
  background: var(--ink);
  transform: scaleX(0); transform-origin: center;
  transition: transform 220ms cubic-bezier(.4,0,.2,1);
}
.menu-nav a:hover { color: var(--ink); }
.menu-nav a:hover::after { transform: scaleX(1); }
.menu-nav a.active { color: var(--ink); font-weight: 500; }
.menu-nav a.active::after { transform: scaleX(1); }

.menubar-right {
  display: flex; justify-content: flex-end; align-items: center; gap: 14px;
}
.lang {
  display: inline-flex;
  border: 1px solid var(--rule);
  border-radius: 999px;
  overflow: hidden;
  height: 26px;
}
.lang-btn {
  font-family: var(--mono);
  font-size: 10.5px; line-height: 1;
  padding: 0 11px;
  border: none; background: transparent;
  color: var(--ink-mute);
  cursor: pointer;
  letter-spacing: 0.08em;
  transition: background-color 200ms, color 200ms;
}
.lang-btn.active { background: var(--ink); color: var(--paper); }

/* Bouton jour/nuit — glyphe Contraste (Mode) #10 — sans cercle */
.theme-toggle {
  width: 40px; height: 40px;
  border: 0;
  background: transparent;
  padding: 2px;
  cursor: pointer;
  color: var(--ink);
  display: grid; place-items: center;
  transition: transform 600ms cubic-bezier(.4,0,.2,1);
}
.theme-toggle svg { width: 100%; height: 100%; display: block; }
[data-theme="dark"] .theme-toggle { transform: rotate(180deg); }
/* Le survol n'existe que sur un écran qui en a un (LOT 16, 12/09/2026). Sur
   téléphone, le navigateur GARDE l'état :hover sur le dernier élément touché :
   le bouton restait penché de 20° après la bascule, jusqu'à ce qu'on touche
   autre chose (FR/EN). Les deux règles sont inchangées, seulement abritées. */
@media (hover: hover) {
  .theme-toggle:hover { transform: rotate(20deg); }
  [data-theme="dark"] .theme-toggle:hover { transform: rotate(200deg); }
}

/* ──────────── HERO ──────────── */
.hero {
  padding: 36px 0 44px;
  border-bottom: 1px solid var(--rule);
}
.hero-monogram {
  width: 64px; height: 64px;
  margin: 0 auto 10px;
  display: block;
}
.hero-monogram img {
  width: 100%; height: 100%;
  object-fit: contain; display: block;
  filter: var(--logo-filter, none);
}
[data-theme="dark"] .hero-monogram img { filter: invert(1) brightness(1.15); }
.hero-meta {
  display: flex;
  gap: 6px;
  align-items: baseline;
  font-family: var(--mono);
  font-size: 10px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--ink-mute);
  margin-bottom: 28px;
}
.hero-meta b { color: var(--ink); font-weight: 500; }
.hero-body {
  display: grid;
  grid-template-columns: 1.25fr 1fr;
  column-gap: 64px;
  align-items: start;
}
.hero-left { padding-top: 0; }
.hero-name {
  margin: 0;
  font-family: var(--sans);
  font-size: 112px;
  line-height: 0.92;
  letter-spacing: -0.045em;
  color: var(--ink);
  font-weight: 300;
}
.hero-name .given   { display: block; font-weight: 300; }
.hero-name .surname { display: block; font-weight: 500; }
.hero-intro {
  margin: 30px 0 0;
  font-family: var(--sans);
  font-size: 18px;
  font-weight: 300;
  line-height: 1.55;
  color: var(--ink);
  max-width: 56ch;
  text-wrap: pretty;
}
.hero-intro em { font-style: italic; font-weight: 400; color: var(--ink-2); }
.hero-intro .since { opacity: 0.8; }
.hero-roles {
  text-align: right;
  color: var(--ink);
  padding-top: 0;
}
.hero-roles .hero-monogram { margin: 0 0 10px auto; }
.hero-roles ul {
  list-style: none; margin: 0; padding: 0;
  font-family: var(--sans);
  font-size: 22px;
  line-height: 1.5;
  text-align: right;
}
.hero-roles li { font-weight: 300; }
.hero-roles li.accent {
  font-style: italic; font-weight: 400; color: var(--ink-2);
}

/* ──────────── ATLAS HEAD (aligné à gauche avec le nom) ──────────── */
.atlas { padding: 48px 0 40px; }
.colophon { padding: 100px 0 60px; }
.atlas-head {
  display: grid;
  grid-template-columns: auto 1fr;
  column-gap: 60px;
  align-items: center;
  margin-bottom: 36px;
  padding-bottom: 26px;
}
/* La barre sous le titre Atlas est supprimée (point 7). Conservée pour Démarche. */
.colophon > .atlas-head { border-bottom: 1px solid var(--rule); }
.atlas-kicker {
  display: block;
  font-family: var(--mono);
  font-size: 10.5px;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--ink-mute);
  margin-bottom: 14px;
}
.atlas-title {
  margin: 0;
  font-family: var(--sans);
  font-weight: 300;
  font-size: 128px;
  letter-spacing: -0.045em;
  line-height: 1;
  color: var(--ink);
  display: flex;
  align-items: center;
  gap: 24px;
}
/* "Atlas" en premier (gauche), emblème à droite */
.atlas-title .atlas-word { font-weight: 500; }
.atlas-title-2 { font-size: 72px; }
.atlas-title-2 .atlas-word { font-weight: 300; }
.atlas-title .title-suffix {
  font-style: italic;
  font-weight: 300;
  color: var(--ink-mute);
  font-size: 0.45em;
  letter-spacing: -0.01em;
  margin-left: 4px;
}
.atlas-emblem {
  width: 112px; height: 112px;
  display: block;
  color: var(--ink);
  flex-shrink: 0;
  align-self: center;
  margin: 0;
  /* compensation optique : centre la barre horizontale du glyphe
     sur la hauteur visuelle des lettres minuscules d'"Atlas". */
  transform: translateY(14px);
}
.atlas-emblem svg { width: 100%; height: 100%; display: block; }
.atlas-glose {
  margin: 0;
  font-family: var(--sans);
  font-size: 18px;
  font-weight: 300;
  color: var(--ink-2);
  line-height: 1.45;
  text-wrap: pretty;
  text-align: right;
  margin-top: 14px;
}
.atlas-glose em {
  font-style: italic; font-weight: 400; color: var(--ink);
}
.atlas-head-r {
  text-align: right;
  align-self: center;
}
.atlas-stats {
  display: inline-grid;
  grid-template-columns: auto auto;
  column-gap: 18px;
  row-gap: 6px;
  margin: 0;
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: 0.08em;
  color: var(--ink-mute);
  text-transform: uppercase;
  text-align: left;
}
.atlas-stats dt { font-size: 9.5px; }
.atlas-stats dd { margin: 0; }
.atlas-stats b { color: var(--ink); font-weight: 500; font-size: 13px; }

/* ──────────── VIEW SELECTOR ──────────── */
.view-selector {
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  gap: 12px;
  border: 0;
  margin: 0 0 36px;   /* point 8 — plus d'air entre boutons & tableau */
}
.view-btn {
  appearance: none;
  background: var(--paper);
  border: 1px solid var(--rule);
  padding: 16px 18px 14px;
  text-align: left;
  cursor: pointer;
  display: flex; flex-direction: column; gap: 10px;
  font-family: var(--sans);
  color: var(--ink-2);
  transition: background-color 180ms, color 180ms, border-color 180ms;
  min-height: 116px;
}
.view-btn:hover { border-color: var(--ink); color: var(--ink); }
.view-btn.is-active { background: var(--ink); color: var(--paper); border-color: var(--ink); }
.view-btn .vb-glyph {
  display: block;
  width: 32px; height: 32px;
  color: var(--ink);
  transition: color 180ms;
}
.view-btn .vb-glyph svg { width: 100%; height: 100%; display: block; }
.view-btn.is-active .vb-glyph { color: var(--paper); }
.view-btn .vb-name {
  font-size: 14.5px;
  font-weight: 400;
  letter-spacing: -0.005em;
  line-height: 1.2;
  margin-top: 4px;
}
.view-btn.is-active .vb-name { font-weight: 500; }
.view-btn .vb-axes {
  font-family: var(--mono);
  font-size: 9px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink-mute);
  margin-top: auto;
}
/* ⚠️ CORRIGÉ AU 11B (04/09/2026) — la valeur était ÉCRITE EN DUR, et un texte
   en dur ne s'inverse pas avec le thème. `rgba(245,243,239,…)` est l'encre du
   thème NUIT ; or le bouton actif porte `background: var(--ink)`, donc un fond
   CLAIR en nuit. Mesuré : le libellé y valait ratio 1,00 — exactement la
   couleur de son fond, donc INVISIBLE. Voir GABARITS.md §4, « cinquième piège ».
   Le mélange ci-dessous rejoue l'intention d'origine — l'encre inverse à 55 % —
   mais avec des TOKENS, donc dans les deux thèmes : 6,13 en clair (contre 5,75
   avant : l'œil ne fait pas la différence) et 4,29 en nuit. Le repli sert les
   navigateurs sans `color-mix`. ⚠️ 4,29 reste sous les 4,50 de AA, comme
   `--ink-mute` (4,34) partout ailleurs sur le site : c'est le régime du site,
   non une exception — signalé au relevé du 11B. */
.view-btn.is-active .vb-axes {
  color: var(--paper);                                        /* repli */
  color: color-mix(in srgb, var(--paper) 55%, var(--ink));
}

/* ──────────── ATLAS GRID ──────────── */
.atlas-grid {
  display: grid;
  grid-template-columns: calc(var(--map) + var(--map-left)) var(--panel-w);
  column-gap: 30px;
  justify-content: space-between;   /* tableau réduit → panneau poussé vers la droite */
  align-items: start;
}

.map-wrap {
  position: relative;
  width: calc(var(--map) + var(--map-left));
  height: calc(var(--map-top) + var(--map) + var(--map-foot));
  padding-left: var(--map-left);
}
.map {
  position: absolute;
  top: var(--map-top);
  left: var(--map-left);
  width: var(--map);
  height: var(--map);
  background: var(--paper-2);
  border: 1px solid var(--rule);
  overflow: visible;
  transition: background-color 180ms ease, border-color 180ms ease, border-width 180ms ease;
}

/* V11 — Grille active : cadre noir épais (renforce la lecture du tableau) */
.map-wrap[data-grid="on"][data-view="v1"] .map,
.map-wrap[data-grid="on"][data-view="v4"] .map {
  border: 2px solid var(--ink);
}
[data-theme="dark"] .map { background: transparent; border-color: var(--rule); }

/* V11 — deux fonds distincts selon la nature du tableau :
   tableaux carrés (v1, v4) = gris crème légèrement dense
   tableaux triangle (v3, v5) = remplissage UNIQUEMENT dans le triangle (via .ternary-bg)
   tableau 1D (v2) = pas de fond
   Le bouton "Fond" de la légende permute on/off.

   Le crème vient de --atlas-creme et de lui seul (§4-5). La règle appelait
   auparavant `var(--bg-cream, #e0dccf)` : la variable n'ayant jamais été
   déclarée, c'est le repli qui s'appliquait — la BONNE couleur, mais par
   accident, et invisible pour qui relisait le CSS. C'est ce qui l'a fait
   perdre une première fois. Elle est maintenant un token nommé, et les
   pictos des fiches l'utilisent aussi. */
.map-wrap[data-view="v1"] .map,
.map-wrap[data-view="v4"] .map { background: var(--atlas-creme); }

/* Triangle ternaire — V11 : le map est transparent, seul le polygone est coloré */
.map-wrap[data-view="v3"] .map,
.map-wrap[data-view="v5"] .map { background: transparent; }

/* Densités alternatives via tweak — V11 : standard fixé (le tweak densité a été supprimé) */

/* Toggle légende : fond OFF — le tableau perd son fond coloré (papier) */
.map-wrap[data-bg="off"] .map { background: transparent !important; }

[data-theme="dark"] .map-wrap[data-view="v1"] .map,
[data-theme="dark"] .map-wrap[data-view="v3"] .map,
[data-theme="dark"] .map-wrap[data-view="v4"] .map,
[data-theme="dark"] .map-wrap[data-view="v5"] .map { background: transparent !important; }

/* Quadrillage — V11 : OFF par défaut, ON via toggle légende sur tableaux carrés+triangle */
.map-grid {
  position: absolute; inset: 0;
  background-image:
    linear-gradient(to right, var(--grid-line) 1px, transparent 1px),
    linear-gradient(to bottom, var(--grid-line) 1px, transparent 1px);
  background-size: 50px 50px;
  /* V11 — alignée sur les axes centraux (une ligne tombe sur le centre à 400px) :
     resubdivise chaque quadrant en 8×8 petits carrés égaux. */
  background-position: 0 0;
  pointer-events: none;
  opacity: 0;
  transition: opacity 240ms ease;
}
/* Grid fine — UNIQUEMENT sur les deux tableaux carrés (v1, v4).
   Les triangles (v3, v5) utilisent .ternary-grid à la place. */
.map-wrap[data-grid="on"][data-view="v1"] .map-grid,
.map-wrap[data-grid="on"][data-view="v4"] .map-grid {
  opacity: 1;
}
.map-wrap[data-grid-style="dot"] .map-grid {
  background-image: radial-gradient(var(--grid-dot) 0.9px, transparent 1.4px);
  background-size: 22px 22px;
}

/* Axes centraux (croix V/H au milieu du tableau)
   V11 — visibles UNIQUEMENT quand la grille est active, sur les tableaux carrés.
   Plus marqués que les subdivisions pour hiérarchiser la lecture en 4 quarts.
   Implémentés en pseudo-éléments (lignes nettes, rendu fiable). */
.map-crosshair {
  position: absolute;
  inset: 0;
  pointer-events: none;
  opacity: 0;
  transition: opacity 240ms ease;
}
.map-crosshair::before,
.map-crosshair::after {
  content: "";
  position: absolute;
  background: var(--ink);
}
/* ligne verticale centrale — ligne UNIQUE, plus épaisse que les subdivisions */
.map-crosshair::before {
  left: 50%; top: 0; bottom: 0;
  width: 2px;
  transform: translateX(-50%);
}
/* ligne horizontale centrale */
.map-crosshair::after {
  top: 50%; left: 0; right: 0;
  height: 2px;
  transform: translateY(-50%);
}
.map-wrap[data-grid="on"][data-view="v1"] .map-crosshair,
.map-wrap[data-grid="on"][data-view="v4"] .map-crosshair {
  opacity: 0.42;
}

/* Frame ternaire — V11 : le bord noir du triangle n'apparaît QUE si la grille est active */
.ternary-frame {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  color: var(--rule);
  opacity: 0;
  pointer-events: none;
  transition: opacity 360ms ease;
}
.map-wrap[data-grid="on"][data-view="v3"] .ternary-frame,
.map-wrap[data-grid="on"][data-view="v5"] .ternary-frame { opacity: 1; }
/* Frame ternaire — V11 : bord noir plein, même poids que le cadre des carrés (2px) */
.ternary-frame polygon {
  stroke: var(--ink);
  opacity: 1;
  vector-effect: non-scaling-stroke;
  stroke-width: 2;
}

/* Grille triangulaire — V11 : adaptée au triangle (lignes parallèles aux 3 côtés),
   uniquement à l'intérieur du triangle, au-DESSUS du fond gris (z-index 2).
   Visible seulement quand la grille est active, sur les tableaux triangulaires. */
.ternary-grid {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  pointer-events: none;
  opacity: 0;
  transition: opacity 360ms ease;
  z-index: 2;
}
.map-wrap[data-grid="on"][data-view="v3"] .ternary-grid,
.map-wrap[data-grid="on"][data-view="v5"] .ternary-grid { opacity: 1; }
/* Cohérence graphique avec les carrés :
   tg-fine = subdivisions fines (1px @ 0.12, comme .map-grid)
   tg-med  = 3 axes centraux (2px @ 0.42, comme .map-crosshair) */
.ternary-grid line { vector-effect: non-scaling-stroke; }
.ternary-grid .tg-fine { stroke: var(--ink); stroke-width: 1; opacity: 0.12; }
.ternary-grid .tg-med  { stroke: var(--ink); stroke-width: 2; opacity: 0.42; }
[data-theme="dark"] .ternary-grid .tg-fine { stroke: #fff; }
[data-theme="dark"] .ternary-grid .tg-med  { stroke: #fff; }

/* Pôles ternaires — V11 : HORS du triangle (3a)
   tp-top au-dessus du sommet ; tp-left/right sous les côtés bas */
.ternary-pole {
  position: absolute;
  font-family: var(--mono);
  font-size: 12px;
  font-weight: 500;
  letter-spacing: 0.06em;
  color: var(--ink);
  text-transform: lowercase;
  opacity: 0;
  pointer-events: none;
  white-space: nowrap;
  transition: opacity 360ms ease;
  z-index: 5;
}
.map-wrap[data-view="v3"] .ternary-pole,
.map-wrap[data-view="v5"] .ternary-pole { opacity: 1; }
.tp-top   { top: 4px;    left: calc(50% + 5px); transform: translateX(-50%); }
.tp-left  { top: calc(var(--map-top) + var(--map) + 6px);  left: 14px; }
.tp-right { top: calc(var(--map-top) + var(--map) + 6px);  right: 14px; }

/* Ligne 1D — visible seulement vue 2. Son emprise est pilotée par --v2-inset
   (retrait en % de chaque côté), partagé avec posFor() dans main.js. */
.line-1d {
  position: absolute;
  left: calc(var(--v2-inset) * 1%); right: calc(var(--v2-inset) * 1%);
  top: 50%;
  height: 1px;
  background: var(--ink);
  opacity: 0;
  transform: translateY(-0.5px);
  pointer-events: none;
  transition: opacity 360ms ease;
  z-index: 1;
}
.line-1d::before, .line-1d::after {
  content: ""; position: absolute;
  top: 50%; transform: translateY(-50%);
  width: 7px; height: 7px;
  background: var(--ink);
  border-radius: 50%;
}
.line-1d::before { left: -3.5px; }
.line-1d::after  { right: -3.5px; }
.map-wrap[data-view="v2"] .line-1d { opacity: 1; }

/* Étiquettes 1D (vue 2 — V11 : "Dispositif d'inscription" / "Dispositif de rencontre")
   Pivotées à 90° comme les titres de l'axe Y, centrées verticalement sur la ligne 1D.
   Les dots sont à 15% et 85% du tableau (= 130px et 690px dans le map-wrap). */
.axis-1d {
  position: absolute;
  top: calc(var(--map-top) + var(--map) / 2);     /* y centre de la ligne */
  font-family: var(--mono);
  font-size: 12px;
  font-weight: 500;
  letter-spacing: 0.06em;
  color: var(--ink);
  white-space: nowrap;
  opacity: 0;
  pointer-events: none;
  transition: opacity 360ms ease;
  z-index: 4;
  text-transform: uppercase;
  writing-mode: vertical-rl;
  transform: translate(-50%, -50%) rotate(180deg);
  transform-origin: center;
}
.axis-1d-l { left: 74px; }
.axis-1d-r { left: 746px; }
.map-wrap[data-view="v2"] .axis-1d { opacity: 1; }

/* ════════ V11.1 — VUE 2 (1D inscription/rencontre) EN PLEINE LARGEUR ════════
   Uniquement pour v2 : l'axe horizontal occupe toute la largeur (sous les 5 boutons),
   et la fiche passe SOUS l'axe au lieu d'être à sa droite — plus de place pour
   répartir les œuvres le long de l'axe. Les 4 autres vues ne sont pas affectées. */
.atlas-grid[data-view="v2"] {
  grid-template-columns: 1fr;
  justify-content: stretch;
}
.atlas-grid[data-view="v2"] .map-wrap {
  width: 100%;
  height: 392px;
  padding-left: 0;
}
.atlas-grid[data-view="v2"] .map {
  top: 48px;
  left: 0;
  width: 100%;
  height: 300px;
  background: transparent !important;
  border: 0 !important;
}
/* Axe + labels recentrés sur la ligne (centre de la ligne = top 48 + 150 = 198px) */
.atlas-grid[data-view="v2"] .axis-1d {
  top: 198px;
  transform: translateY(-50%);
}
/* Libellés posés juste au-delà des extrémités de la ligne : ils suivent donc
   --v2-inset. Le dégagement (34 px / 18 px) tient compte du marqueur le plus
   large, qui peut déborder de l'extrémité de la ligne. */
.atlas-grid[data-view="v2"] .axis-1d-l { left: calc(var(--v2-inset) * 1% - 34px); }
.atlas-grid[data-view="v2"] .axis-1d-r { left: calc(100% - var(--v2-inset) * 1% + 18px); }
/* La fiche passe sous l'axe, alignée à gauche, largeur contenue */
.atlas-grid[data-view="v2"] .panel {
  width: var(--panel-w);
  max-width: 100%;
  margin-top: 6px;
  max-height: none !important;
}

/* ════════ V11.2 — VUE 2 : LA FICHE S'ÉTEND À L'HORIZONTALE ════════
   Consigne du propriétaire, 01/09/2026 : « uniquement pour le tableau
   inscription/rencontre, et uniquement quand celui-ci est actif », la fiche
   doit s'étendre à l'horizontale et non à la verticale — « une succession de
   colonnes de gauche à droite : titre puis carton technique puis vignette ».

   Le bloc V11.1 ci-dessus avait déjà mis l'axe en pleine largeur et poussé la
   fiche SOUS lui ; il lui restait à s'y étaler. Elle passait 360 px de large
   pour 549 de haut sous un axe qui en fait 1200 : une colonne étroite et une
   grande plage vide à sa droite.

   TOUT est porté par le sélecteur .atlas-grid[data-view="v2"] : les vues 1, 3,
   4 et 5 ne voient rien de ce bloc.

   ⚠️ Les DEUX états sont mis à l'horizontale, pas seulement le rempli. Sans
   cela le panneau vide (haut) et le panneau rempli (plat) n'auraient pas la
   même hauteur et la page sauterait à chaque survol — c'est déjà le cas
   aujourd'hui, à hauteur de 158 px. Le min-height commun ci-dessous fixe les
   deux à 8 lignes de base et supprime le saut. */
.atlas-grid[data-view="v2"] .panel { width: 100%; }

/* La bande des quatre colonnes, commune aux deux états : titre · cartel
   technique · vignette · coordonnées. Les minmax() gardent chaque colonne
   lisible ; la dernière se règle sur son contenu. */
.atlas-grid[data-view="v2"] .panel-empty,
.atlas-grid[data-view="v2"] .panel-content {
  grid-template-columns: minmax(240px, 1.3fr) minmax(230px, 1.1fr) minmax(200px, 0.9fr) auto;
  grid-auto-rows: min-content;
  column-gap: 34px;
  align-content: start;
  /* 130 px = 5 lignes de base, et c'est EXACTEMENT la hauteur naturelle de
     l'état vide — la fiche au repos n'a donc plus un pixel de vide sous elle
     (2ᵉ consigne du propriétaire, 01/09/2026 : « moins grande par défaut […]
     et s'ajuster quand vraiment il y a besoin »). Elle passe ainsi de 323 à
     219 px au repos.
     ⚠️ Ce plancher bas n'est tenable que parce que les MOTS-CLÉS ont quitté la
     colonne du cartel (voir plus bas) : c'étaient eux qui poussaient le contenu
     de 175 à 231 px. Il rend maintenant 137 ou 140 px sur 52 entrées des 72, et
     ne dépasse que là où le titre court sur deux lignes. */
  min-height: calc(var(--baseline) * 5);
  overflow: visible;
}

/* État rempli. La spécificité (0,5,0) l'emporte sur .panel.is-on .panel-content. */
.atlas-grid[data-view="v2"] .panel.is-on .panel-content { display: grid; row-gap: 6px; }
.atlas-grid[data-view="v2"] .panel-num   { grid-column: 1; grid-row: 1; }
.atlas-grid[data-view="v2"] .panel-title { grid-column: 1; grid-row: 2; }
.atlas-grid[data-view="v2"] .panel-sub   { grid-column: 1; grid-row: 3; }
.atlas-grid[data-view="v2"] .panel-meta  { grid-column: 2; grid-row: 1 / 5; margin: 0; align-self: start; }
/* ⚠️ LES MOTS-CLÉS VONT EN COLONNE 1, sous le sous-titre — et non sous le
   cartel technique, où ils s'empilaient. Deux raisons, qui vont dans le même
   sens : ils décrivent l'œuvre, comme le titre qu'ils suivent ; et surtout,
   empilés en colonne 2, ils S'AJOUTAIENT aux 137 px du cartel et commandaient
   à eux seuls la hauteur de toute la bande (de 175 à 231 px selon l'entrée).
   Posés en colonne 1, plus large de 51 px, ils reviennent moins souvent à la
   ligne et tiennent sous un bloc titre qui ne fait que 70 px : la bande retombe
   à la hauteur du cartel technique, 137 px, et s'y tient sur 52 entrées. */
.atlas-grid[data-view="v2"] .panel-tags  { grid-column: 1; grid-row: 4; margin-top: 10px; align-self: start; }
.atlas-grid[data-view="v2"] .panel-stamp { grid-column: 3; grid-row: 1 / 5; margin: 0; align-self: start; }
/* Les coordonnées perdent leur filet et leur margin-top:auto, qui les collaient
   au BAS d'une colonne : en bande, il n'y a plus de bas où les pousser. */
.atlas-grid[data-view="v2"] .panel-coord {
  grid-column: 4; grid-row: 1 / 5;
  margin-top: 0; padding-top: 0; border-top: 0;
  align-self: start;
}

/* État vide, sur les mêmes colonnes. Le :not(.is-on) est indispensable : sans
   lui, cette règle (0,3,0) l'emporterait sur le display:none de
   « .panel.is-on .panel-empty » (0,2,0) et les deux états paraîtraient
   ensemble. */
.atlas-grid[data-view="v2"] .panel:not(.is-on) .panel-empty { display: grid; row-gap: 10px; }
.atlas-grid[data-view="v2"] .empty-glyph      { grid-column: 1; grid-row: 1; }
.atlas-grid[data-view="v2"] .panel-empty .lead { grid-column: 1; grid-row: 2; }
.atlas-grid[data-view="v2"] .empty-body       { grid-column: 2; grid-row: 1 / 3; }
.atlas-grid[data-view="v2"] .empty-meta {
  grid-column: 3 / 5; grid-row: 1 / 3;
  margin-top: 0; padding-top: 0; border-top: 0;
  align-content: start;
}

/* Graduations 1D — V11 : le long de l'axe inscription–rencontre, quand la grille est active.
   Graduation centrale (au milieu) accentuée — divise l'axe en deux. */
.line-1d-ticks {
  position: absolute;
  left: 15%; right: 15%;
  top: 50%;
  height: 0;
  pointer-events: none;
  opacity: 0;
  transition: opacity 360ms ease;
  z-index: 2;
}
.map-wrap[data-grid="on"][data-view="v2"] .line-1d-ticks { opacity: 1; }
.line-1d-ticks .tk {
  position: absolute;
  top: 0;
  width: 1px; height: 11px;
  background: var(--ink);
  opacity: 0.5;
  transform: translate(-50%, -50%);
}
.line-1d-ticks .tk.tk-mid {
  width: 2px; height: 24px;
  opacity: 0.9;
}

/* Triangle ternaire — V11 : le fond du tableau reste visible (gris neutre)
   Le cadre CARRÉ ne doit JAMAIS apparaître sur les triangles (même grille active). */
.map-wrap[data-view="v3"] .map,
.map-wrap[data-view="v5"] .map {
  border-color: transparent !important;
}
.map-wrap[data-view="v3"] .map-grid,
.map-wrap[data-view="v5"] .map-grid { /* géré par toggle grille */ }

/* Vue 2 — 1D : pas de fond ni de cadre carré (la ligne + graduations se suffisent),
   même quand la grille est active. */
.map-wrap[data-view="v2"] .map {
  background: transparent !important;
  border-color: transparent !important;
}

/* Calque triangulaire teinté — épouse la forme du triangle (vues 3 & 5)
   V11 : fond gris neutre, UNIQUEMENT dans le polygone (épouse la forme) */
.ternary-bg {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  pointer-events: none;
  opacity: 0;
  transition: opacity 360ms ease;
  z-index: 0;
}
.map-wrap[data-view="v3"] .ternary-bg,
.map-wrap[data-view="v5"] .ternary-bg { opacity: 1; }
/* Même histoire que le crème : la règle appelait `var(--bg-neutral, #dededb)`,
   variable jamais déclarée. Le gris est désormais le token nommé
   --atlas-gris, partagé avec les pictos des fiches (§4-5). */
.ternary-bg polygon { fill: var(--atlas-gris); }
/* Mode nuit : le fond des triangles est désactivé (même avec le bouton «fond» actif) */
[data-theme="dark"] .ternary-bg { opacity: 0 !important; }

/* Toggle légende : fond OFF — plus aucun fond coloré (papier) */
.map-wrap[data-bg="off"] .ternary-bg { opacity: 0 !important; }

/* Fils de série (calque SVG) — coords 0..800 */
.series-thread {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  pointer-events: none;
  z-index: 2;
}
.series-thread line {
  stroke: var(--ink);
  stroke-width: 0.6;
  opacity: 0;
  transition: opacity 200ms ease;
}
.series-thread.is-on line { opacity: 0.55; }

/* ──────────── AXES — point 11 ──────────── */
/* X sous le tableau — V11 : position ajustée (map déplacé à top:32px) */
.axis-x {
  position: absolute;
  top: calc(var(--map-top) + var(--map) + 6px); left: var(--map-left);
  width: var(--map); height: 30px;
  pointer-events: none;
  font-family: var(--mono);
  color: var(--ink);
  display: flex;
  justify-content: space-between;
  align-items: center;
}
.axis-x .axis-name {
  position: absolute;
  left: 50%; top: 50%;
  transform: translate(-50%, -50%);
  color: var(--ink-mute);
  font-size: 9.5px;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  opacity: 0.6;
}
.axis-x .pole {
  color: var(--ink);
  white-space: nowrap;
  font-size: 13px;
  font-weight: 500;
  letter-spacing: 0.04em;
  text-transform: lowercase;
}
.map-wrap[data-view="v2"] .axis-x { opacity: 0; }
.map-wrap[data-view="v2"] .axis-x .axis-name { display: none; }
.map-wrap[data-view="v3"] .axis-x,
.map-wrap[data-view="v5"] .axis-x { opacity: 0; }

/* Y à gauche — V11 : top ajusté (map à top:32px) */
.axis-y {
  position: absolute;
  top: var(--map-top); left: -22px;
  width: 22px; height: var(--map);
  pointer-events: none;
  font-family: var(--mono);
  color: var(--ink);
  writing-mode: vertical-rl;
  display: flex;
  flex-direction: row-reverse;
  align-items: center;
  justify-content: space-between;
  padding: 0;
}
.axis-y .pole {
  color: var(--ink);
  white-space: nowrap;
  font-size: 13px;
  font-weight: 500;
  letter-spacing: 0.04em;
  text-transform: lowercase;
  transform: rotate(180deg);
}
.axis-y .axis-name {
  position: absolute;
  top: 50%; left: 50%;
  transform: translate(-50%, -50%) rotate(180deg);
  color: var(--ink-mute);
  font-size: 9.5px;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  opacity: 0.6;
}
.map-wrap[data-view="v2"] .axis-y .axis-name { display: none; }
.map-wrap[data-view="v2"] .axis-y { opacity: 0; }
.map-wrap[data-view="v3"] .axis-y,
.map-wrap[data-view="v5"] .axis-y { opacity: 0; }

/* ──────────── MARQUEURS — 12 nomenclatures A–L ──────────── */
.pt {
  position: absolute;
  transform: translate(-50%, -50%);
  cursor: pointer;
  z-index: 3;
  background: transparent;
  border: 0; padding: 0;
  font-family: var(--mono);
  color: var(--ink);
  transition: left 520ms cubic-bezier(.4,0,.2,1),
              top 520ms cubic-bezier(.4,0,.2,1),
              color 150ms ease, background-color 150ms ease;
  display: flex;
  align-items: center;
  justify-content: center;
}
/* ─── LE POINT D'ŒUVRE AU CLAVIER (11B, 04/09/2026) ───────────────────────
   Avant ce lot, les 72 points de l'atlas étaient MUETS au clavier : le
   `outline: none` ci-dessous supprimait le contour, et TOUS les autres retours
   du point — étiquette, glyphe, agrandissement, dans les douze nomenclatures
   N et A à L — étaient keyés sur `:hover` et `.is-active`, jamais sur `:focus`.

   Deux gestes, et aucune valeur nouvelle :
   1. Les 23 sélecteurs de survol du point portent désormais leur jumeau
      `:focus-visible` : au clavier, le point rend EXACTEMENT ce qu'il rend au
      survol — son étiquette, son glyphe agrandi, selon la nomenclature active.
   2. Le contour du système s'y ajoute, pour que le repère soit le même dans
      les douze nomenclatures — certaines ne changent qu'une graisse.

   ⚠️ `outline: none` RESTE sur `:focus` simple : au CLIC, le point ne dessine
   toujours rien. Seul le clavier marque. */
.pt:focus { outline: none; }
.pt:focus-visible { outline: 2px solid var(--ink); outline-offset: 2px; }
/* V11.1 — au survol/actif, le point passe au-dessus de tous les autres
   pour que son étiquette (tooltip) ne soit jamais masquée par un point voisin. */
.pt:hover,
.pt:focus-visible,
.pt.is-active { z-index: 50; }
.pt .lbl {
  font-family: var(--mono);
  font-size: 9.5px;
  font-weight: 500;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ink);
  white-space: nowrap;
  pointer-events: none;
}
/* glyph & badge sont masqués par défaut — affichés seulement par styles spécifiques */
.pt .glyph, .pt .badge { display: none; }

/* ============ N · TROIS FORMES NOIRES (V11 DEFAULT) ============
   - Rond noir         = œuvre
   - Triangle noir     = conférence
   - Carré noir à 45°  = écrit
   3 tailles selon le niveau d'importance (data-poids 1/2/3).
   Toggle "N°" : affiche le numéro en blanc, centré dans la forme.
   On utilise l'élément réel .glyph comme forme (au lieu d'un ::before). */
[data-style="N"] .pt {
  width: 30px; height: 30px;
  background: transparent;
}
[data-style="N"] .pt .lbl { display: none; }

/* La forme = .glyph remplie de noir */
[data-style="N"] .pt .glyph {
  display: block;
  position: absolute;
  left: 50%; top: 50%;
  width: calc(14px * var(--pt-scale)); height: calc(14px * var(--pt-scale));
  background: var(--ink);
  transform: translate(-50%, -50%);
  transition: transform 180ms ease;
}
[data-style="N"] .pt .glyph svg { display: none; }

/* œuvre = rond — niveaux 1/2/3 */
[data-style="N"] .pt[data-type="oeuvre"] .glyph {
  width: calc(14px * var(--pt-scale)); height: calc(14px * var(--pt-scale));
  border-radius: 50%;
}
[data-style="N"] .pt[data-type="oeuvre"][data-poids="1"] .glyph {
  width: calc(9px * var(--pt-scale)); height: calc(9px * var(--pt-scale));
}
[data-style="N"] .pt[data-type="oeuvre"][data-poids="3"] .glyph {
  width: calc(22px * var(--pt-scale)); height: calc(22px * var(--pt-scale));
}

/* écrit = carré à 45° (losange noir) — niveaux 1/2/3 */
[data-style="N"] .pt[data-type="ecrit"] .glyph {
  width: calc(13px * var(--pt-scale)); height: calc(13px * var(--pt-scale));
  border-radius: 0;
  transform: translate(-50%, -50%) rotate(45deg);
}
[data-style="N"] .pt[data-type="ecrit"][data-poids="1"] .glyph {
  width: calc(9px * var(--pt-scale)); height: calc(9px * var(--pt-scale));
}
[data-style="N"] .pt[data-type="ecrit"][data-poids="3"] .glyph {
  width: calc(20px * var(--pt-scale)); height: calc(20px * var(--pt-scale));
}

/* conférence = triangle (clip-path) — niveaux 1/2/3 */
[data-style="N"] .pt[data-type="conference"] .glyph {
  width: calc(17px * var(--pt-scale)); height: calc(14px * var(--pt-scale));
  background: var(--ink);
  clip-path: polygon(50% 0%, 100% 100%, 0% 100%);
  border-radius: 0;
}
[data-style="N"] .pt[data-type="conference"][data-poids="1"] .glyph {
  width: calc(11px * var(--pt-scale)); height: calc(9px * var(--pt-scale));
}
[data-style="N"] .pt[data-type="conference"][data-poids="3"] .glyph {
  width: calc(25px * var(--pt-scale)); height: calc(21px * var(--pt-scale));
}

/* Hover / active : léger zoom uniforme */
[data-style="N"] .pt:hover .glyph,
[data-style="N"] .pt:focus-visible .glyph,
[data-style="N"] .pt.is-active .glyph {
  transform: translate(-50%, -50%) scale(1.18);
}
[data-style="N"] .pt[data-type="ecrit"]:hover .glyph,
[data-style="N"] .pt[data-type="ecrit"]:focus-visible .glyph,
[data-style="N"] .pt[data-type="ecrit"].is-active .glyph {
  transform: translate(-50%, -50%) rotate(45deg) scale(1.18);
}

/* Badge numéro (toggle "N°") — masqué par défaut, centré sur la forme, blanc sur noir */
[data-style="N"] .pt .badge {
  display: none;
  position: absolute;
  left: 50%; top: 50%;
  transform: translate(-50%, -50%);
  z-index: 2;
  pointer-events: none;
  color: var(--paper);
  font-family: var(--mono);
  font-size: 9px;
  font-weight: 600;
  line-height: 1;
  letter-spacing: 0;
  text-align: center;
}
.map-wrap[data-num="on"][data-style="N"] .pt .badge { display: block; }
.map-wrap[data-num="on"][data-style="N"] .pt[data-poids="1"] .badge { font-size: 7.5px; }
.map-wrap[data-num="on"][data-style="N"] .pt[data-poids="3"] .badge { font-size: 11px; font-weight: 700; }
/* Légère compensation optique pour le triangle (centre visuel plus bas) */
.map-wrap[data-num="on"][data-style="N"] .pt[data-type="conference"] .badge {
  transform: translate(-50%, -25%);
}
.map-wrap[data-num="on"][data-style="N"] .pt[data-type="conference"][data-poids="3"] .badge {
  transform: translate(-50%, -20%);
}

/* Tooltip discret au survol (au-dessus de la forme) */
[data-style="N"] .pt::after {
  content: attr(data-tooltip);
  position: absolute;
  left: 50%; top: -6px;
  transform: translate(-50%, -100%);
  font-family: var(--mono);
  font-size: 10px;
  font-weight: 500;
  letter-spacing: 0.04em;
  color: var(--ink);
  background: var(--paper);
  border: 1px solid var(--rule);
  padding: 3px 7px;
  white-space: nowrap;
  opacity: 0;
  pointer-events: none;
  transition: opacity 160ms ease;
  z-index: 6;
}
[data-style="N"] .pt:hover::after,
[data-style="N"] .pt:focus-visible::after,
[data-style="N"] .pt.is-active::after { opacity: 1; }

/* ============ A · Code A-xx (cartel codé : conf=A-23, écrit=A-65,
   peinture=A-24, film=A-02, installation=A-253) ============ */
[data-style="A"] .pt { width: 60px; height: 22px; }
[data-style="A"] .pt .lbl {
  width: 100%; height: 100%;
  line-height: 20px;
  border: 1px solid var(--ink);
  background: var(--paper);
  text-align: center;
  font-family: var(--mono);
  font-size: 10px;
  letter-spacing: 0.06em;
}
[data-style="A"] .pt:hover .lbl,
[data-style="A"] .pt:focus-visible .lbl,
[data-style="A"] .pt.is-active .lbl { background: var(--ink); color: var(--paper); }
[data-style="A"] .pt[data-poids="3"] .lbl { border-width: 2px; font-weight: 700; }

/* ============ B · Forme · type (point / cercle / triangle plein) ============ */
[data-style="B"] .pt { width: 22px; height: 22px; }
[data-style="B"] .pt::before {
  content: ""; display: block;
  transition: transform 180ms ease;
}
[data-style="B"] .pt[data-type="oeuvre"]::before {
  width: 11px; height: 11px;
  background: var(--ink);
  border-radius: 50%;
}
[data-style="B"] .pt[data-type="ecrit"]::before {
  width: 11px; height: 11px;
  background: transparent;
  border: 1.6px solid var(--ink);
  border-radius: 50%;
}
[data-style="B"] .pt[data-type="conference"]::before {
  width: 0; height: 0;
  background: transparent;
  border-left: 6.5px solid transparent;
  border-right: 6.5px solid transparent;
  border-bottom: 12px solid var(--ink);
}
[data-style="B"] .pt[data-poids="1"]::before { transform: scale(0.62); }
[data-style="B"] .pt[data-poids="3"]::before { transform: scale(1.55); }
[data-style="B"] .pt .lbl {
  position: absolute;
  top: 18px; left: 50%;
  transform: translateX(-50%);
  opacity: 0;
  transition: opacity 160ms ease;
  background: var(--paper);
  padding: 1px 5px;
  border: 1px solid var(--rule);
}
[data-style="B"] .pt:hover::before,
[data-style="B"] .pt:focus-visible::before,
[data-style="B"] .pt.is-active::before { transform: scale(1.5); }
[data-style="B"] .pt[data-poids="1"]:hover::before,
[data-style="B"] .pt[data-poids="1"]:focus-visible::before { transform: scale(0.9); }
[data-style="B"] .pt[data-poids="3"]:hover::before,
[data-style="B"] .pt[data-poids="3"]:focus-visible::before { transform: scale(1.85); }
[data-style="B"] .pt:hover .lbl,
[data-style="B"] .pt:focus-visible .lbl,
[data-style="B"] .pt.is-active .lbl { opacity: 1; }

/* ============ C · Titre court ============ */
[data-style="C"] .pt { max-width: 160px; }
[data-style="C"] .pt .lbl {
  font-family: var(--sans);
  font-size: 11.5px;
  font-weight: 400;
  letter-spacing: 0;
  text-transform: none;
  color: var(--ink-2);
  background: var(--paper);
  padding: 1px 5px;
  line-height: 1.25;
  white-space: nowrap;
}
[data-style="C"] .pt[data-poids="3"] .lbl { font-weight: 500; color: var(--ink); }
[data-style="C"] .pt:hover .lbl,
[data-style="C"] .pt:focus-visible .lbl,
[data-style="C"] .pt.is-active .lbl { color: var(--ink); font-weight: 500; }

/* ============ D · Forme indicée (point/cercle/triangle avec n° à l'intérieur,
   blanc sur noir pour les œuvres niveau 3) ============ */
[data-style="D"] .pt {
  width: 26px; height: 26px;
  background: var(--ink);
  border-radius: 50%;
  color: var(--paper);
  transition: transform 180ms ease;
}
[data-style="D"] .pt[data-poids="1"] { width: 20px; height: 20px; }
[data-style="D"] .pt[data-poids="3"] { width: 32px; height: 32px; }
/* Écrit = cercle vide, numéro noir au centre */
[data-style="D"] .pt[data-type="ecrit"] {
  background: var(--paper);
  color: var(--ink);
  border: 1.5px solid var(--ink);
}
[data-style="D"] .pt[data-type="ecrit"][data-poids="3"] { border-width: 2.4px; }
/* Conférence = triangle plein avec numéro blanc */
[data-style="D"] .pt[data-type="conference"] {
  width: 28px; height: 24px;
  background: var(--ink);
  border-radius: 0;
  border: 0;
  clip-path: polygon(50% 0, 100% 100%, 0 100%);
  color: var(--paper);
}
[data-style="D"] .pt[data-type="conference"][data-poids="1"] { width: 22px; height: 19px; }
[data-style="D"] .pt[data-type="conference"][data-poids="3"] { width: 34px; height: 30px; }
[data-style="D"] .pt .lbl { display: none; }
[data-style="D"] .pt .glyph { display: none; }
[data-style="D"] .pt .badge {
  display: block;
  position: relative;
  z-index: 2;
  font-family: var(--mono);
  font-size: 10px;
  font-weight: 600;
  line-height: 1;
  text-align: center;
  letter-spacing: 0;
}
[data-style="D"] .pt[data-poids="1"] .badge { font-size: 8px; }
[data-style="D"] .pt[data-poids="3"] .badge { font-size: 13px; font-weight: 700; }
[data-style="D"] .pt[data-type="conference"] .badge {
  /* le centre visuel du triangle est plus bas que son centre géométrique */
  margin-top: 5px;
  font-size: 8.5px;
}
[data-style="D"] .pt[data-type="conference"][data-poids="3"] .badge {
  margin-top: 6px;
  font-size: 10.5px;
}
[data-style="D"] .pt:hover,
[data-style="D"] .pt:focus-visible,
[data-style="D"] .pt.is-active { transform: translate(-50%, -50%) scale(1.12); }

/* ============ E · Numéro ============ */
[data-style="E"] .pt .lbl {
  font-family: var(--mono);
  font-size: 13px;
  font-weight: 300;
  color: var(--ink-2);
  letter-spacing: 0;
  text-transform: none;
}
[data-style="E"] .pt[data-poids="3"] .lbl { font-weight: 500; color: var(--ink); }
[data-style="E"] .pt:hover .lbl,
[data-style="E"] .pt:focus-visible .lbl,
[data-style="E"] .pt.is-active .lbl { color: var(--ink); font-weight: 500; }

/* ============ F · Étiquette (puce + texte aligné) ============ */
[data-style="F"] .pt::before {
  content: "";
  width: 5px; height: 5px;
  background: var(--ink);
  border-radius: 50%;
  margin-right: 6px;
  flex-shrink: 0;
}
[data-style="F"] .pt .lbl {
  color: var(--ink-2);
  font-weight: 400;
  font-family: var(--sans);
  font-size: 11.5px;
  letter-spacing: 0;
  text-transform: none;
}
[data-style="F"] .pt:hover .lbl,
[data-style="F"] .pt:focus-visible .lbl,
[data-style="F"] .pt.is-active .lbl { color: var(--ink); font-weight: 500; }

/* ============ G · Pastille (disque seul + label au survol) ============ */
[data-style="G"] .pt { width: 16px; height: 16px; }
[data-style="G"] .pt::before {
  content: "";
  width: 8px; height: 8px;
  background: var(--ink);
  border-radius: 50%;
  transition: transform 180ms ease;
}
[data-style="G"] .pt[data-poids="1"]::before { width: 5px; height: 5px; opacity: 0.7; }
[data-style="G"] .pt[data-poids="3"]::before { width: 12px; height: 12px; }
[data-style="G"] .pt[data-type="ecrit"]::before {
  background: transparent;
  border: 1.5px solid var(--ink);
}
[data-style="G"] .pt .lbl {
  position: absolute;
  left: 14px; top: 50%;
  transform: translateY(-50%);
  opacity: 0;
  transition: opacity 160ms ease;
  background: var(--paper);
  padding: 2px 6px;
  border: 1px solid var(--rule);
}
[data-style="G"] .pt:hover::before,
[data-style="G"] .pt:focus-visible::before,
[data-style="G"] .pt.is-active::before { transform: scale(1.5); }
[data-style="G"] .pt:hover .lbl,
[data-style="G"] .pt:focus-visible .lbl,
[data-style="G"] .pt.is-active .lbl { opacity: 1; }

/* ============ H · Cartel (code court POR · 19) ============ */
[data-style="H"] .pt { width: 64px; height: 20px; }
[data-style="H"] .pt .lbl {
  width: 100%; height: 100%;
  line-height: 18px;
  border: 1px solid var(--ink);
  background: var(--paper);
  text-align: center;
}
[data-style="H"] .pt:hover .lbl,
[data-style="H"] .pt:focus-visible .lbl,
[data-style="H"] .pt.is-active .lbl { background: var(--ink); color: var(--paper); }
[data-style="H"] .pt[data-poids="3"] .lbl { border-width: 2px; }

/* ============ I · Glyphe unique (un caractère différent par œuvre) ============ */
[data-style="I"] .pt { width: 22px; height: 22px; }
[data-style="I"] .pt .glyph {
  display: block;
  width: 22px; height: 22px;
  color: var(--ink);
  transition: transform 180ms ease;
}
[data-style="I"] .pt .glyph svg { width: 100%; height: 100%; display: block; }
[data-style="I"] .pt[data-poids="1"] .glyph { width: 14px; height: 14px; opacity: 0.7; }
[data-style="I"] .pt[data-poids="3"] .glyph { width: 30px; height: 30px; }
[data-style="I"] .pt .lbl {
  position: absolute;
  top: 24px; left: 50%;
  transform: translateX(-50%);
  opacity: 0;
  transition: opacity 160ms ease;
  background: var(--paper);
  padding: 1px 5px;
  border: 1px solid var(--rule);
}
[data-style="I"] .pt:hover .glyph,
[data-style="I"] .pt:focus-visible .glyph,
[data-style="I"] .pt.is-active .glyph { transform: scale(1.2); }
[data-style="I"] .pt:hover .lbl,
[data-style="I"] .pt:focus-visible .lbl,
[data-style="I"] .pt.is-active .lbl { opacity: 1; }

/* ============ J · Glyphe par type (un caractère = un type) ============ */
[data-style="J"] .pt { width: 22px; height: 22px; }
[data-style="J"] .pt .glyph {
  display: block;
  width: 22px; height: 22px;
  color: var(--ink);
  transition: transform 180ms ease;
}
[data-style="J"] .pt .glyph svg { width: 100%; height: 100%; display: block; }
[data-style="J"] .pt[data-poids="1"] .glyph { width: 14px; height: 14px; opacity: 0.7; }
[data-style="J"] .pt[data-poids="3"] .glyph { width: 30px; height: 30px; }
[data-style="J"] .pt .lbl {
  position: absolute;
  top: 24px; left: 50%;
  transform: translateX(-50%);
  opacity: 0;
  transition: opacity 160ms ease;
  background: var(--paper);
  padding: 1px 5px;
  border: 1px solid var(--rule);
}
[data-style="J"] .pt:hover .glyph,
[data-style="J"] .pt:focus-visible .glyph,
[data-style="J"] .pt.is-active .glyph { transform: scale(1.2); }
[data-style="J"] .pt:hover .lbl,
[data-style="J"] .pt:focus-visible .lbl,
[data-style="J"] .pt.is-active .lbl { opacity: 1; }

/* ============ K · Forme type (carré / barre / losange par type) ============ */
[data-style="K"] .pt { width: 18px; height: 18px; }
[data-style="K"] .pt::before {
  content: ""; display: block;
  transition: transform 180ms ease;
}
[data-style="K"] .pt[data-type="oeuvre"]::before {
  width: 11px; height: 11px;
  background: var(--ink);
}
[data-style="K"] .pt[data-type="ecrit"]::before {
  width: 11px; height: 11px;
  background: transparent;
  border: 1.6px solid var(--ink);
}
[data-style="K"] .pt[data-type="conference"]::before {
  width: 10px; height: 10px;
  background: var(--ink);
  transform: rotate(45deg);
}
[data-style="K"] .pt[data-poids="1"]::before { transform: scale(0.62); }
[data-style="K"] .pt[data-poids="3"]::before { transform: scale(1.55); }
[data-style="K"] .pt[data-type="conference"][data-poids="1"]::before { transform: rotate(45deg) scale(0.62); }
[data-style="K"] .pt[data-type="conference"][data-poids="3"]::before { transform: rotate(45deg) scale(1.55); }
[data-style="K"] .pt .lbl {
  position: absolute;
  top: 16px; left: 50%;
  transform: translateX(-50%);
  opacity: 0;
  transition: opacity 160ms ease;
  background: var(--paper);
  padding: 1px 5px;
  border: 1px solid var(--rule);
}
[data-style="K"] .pt:hover .lbl,
[data-style="K"] .pt:focus-visible .lbl,
[data-style="K"] .pt.is-active .lbl { opacity: 1; }

/* ============ L · Glyphe alternatif (combinaison glyphe + lettre type) ============ */
[data-style="L"] .pt { width: 26px; height: 26px; }
[data-style="L"] .pt .glyph {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 26px; height: 26px;
  color: var(--ink);
  border: 1px solid var(--ink);
  border-radius: 0;
  background: var(--paper);
  font-family: var(--mono);
  font-size: 11px;
  font-weight: 500;
  letter-spacing: 0;
  text-transform: uppercase;
  transition: background-color 180ms, color 180ms;
}
[data-style="L"] .pt .glyph svg { display: none; }
[data-style="L"] .pt[data-poids="1"] .glyph { width: 20px; height: 20px; font-size: 9px; }
[data-style="L"] .pt[data-poids="3"] .glyph { width: 32px; height: 32px; font-size: 13px; border-width: 2px; }
[data-style="L"] .pt .lbl {
  position: absolute;
  top: 28px; left: 50%;
  transform: translateX(-50%);
  opacity: 0;
  transition: opacity 160ms ease;
  background: var(--paper);
  padding: 1px 5px;
  border: 1px solid var(--rule);
}
[data-style="L"] .pt:hover .glyph,
[data-style="L"] .pt:focus-visible .glyph,
[data-style="L"] .pt.is-active .glyph { background: var(--ink); color: var(--paper); }
[data-style="L"] .pt:hover .lbl,
[data-style="L"] .pt:focus-visible .lbl,
[data-style="L"] .pt.is-active .lbl { opacity: 1; }

/* ──────────── PANNEAU — point 10 ──────────── */
.panel {
  border: 1px solid var(--rule);
  background: var(--paper);
  margin-top: 0;
  padding: 22px 24px;
  display: flex;
  flex-direction: column;
  transition: background-color 320ms ease, border-color 320ms ease;
  overflow: hidden;
  position: sticky;
  top: 90px;
  /* V11 — la fiche ne dépasse jamais le tableau (max = hauteur map-wrap : 872px),
     mais sa hauteur s'adapte à son contenu : plus de hauteur fixe imposée. */
  height: auto;
  max-height: 872px;
  align-self: start;
}
[data-theme="dark"] .panel { background: transparent; }
.panel-head {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  padding-bottom: 12px;
  margin-bottom: 14px;
  border-bottom: 1px solid var(--rule);
}
.panel-head .tag {
  font-family: var(--mono);
  font-size: 10px;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--ink-mute);
}
/* ⚠️ INEMPLOYÉES depuis le 01/09/2026 : l'état « En attente / Lecture » a été
   retiré du .panel-head, où la note a pris sa place (consigne du propriétaire).
   Les règles sont conservées et signalées, comme .panel-coord .voir et
   .sc-count : elles décrivent un objet du système. */
.panel-head .state {
  font-family: var(--mono);
  font-size: 10px;
  letter-spacing: 0.14em;
  color: var(--ink-faint);
  text-transform: uppercase;
}
.panel-head .state .dot {
  display: inline-block;
  width: 6px; height: 6px;
  border-radius: 50%;
  background: var(--ink-faint);
  margin-right: 7px;
  transform: translateY(-1px);
  transition: background-color 200ms;
}
.panel.is-on .panel-head .state .dot { background: var(--ink); }

/* État vide */
.panel-empty {
  flex: 1;
  display: flex;
  flex-direction: column;
  justify-content: flex-start;
  gap: 18px;
  padding-top: 10px;
}
.empty-glyph {
  width: 56px; height: 56px;
  color: var(--ink-mute);
  opacity: 0.55;
}
.empty-glyph svg { width: 100%; height: 100%; display: block; }
.panel-empty .lead {
  font-family: var(--sans);
  font-size: 20px;
  font-weight: 300;
  line-height: 1.35;
  color: var(--ink);
  letter-spacing: -0.01em;
  max-width: 22ch;
}
.panel-empty .lead em { font-style: italic; color: var(--ink-2); }
.empty-body {
  font-family: var(--sans);
  font-size: 13px;
  font-weight: 300;
  line-height: 1.55;
  color: var(--ink-mute);
  max-width: 38ch;
}
.empty-meta {
  margin-top: auto;
  display: grid;
  grid-template-columns: 86px 1fr;
  row-gap: 8px;
  column-gap: 14px;
  border-top: 1px solid var(--rule-soft);
  padding-top: 16px;
  font-family: var(--mono);
  font-size: 11px;
}
.empty-meta dt {
  color: var(--ink-mute);
  letter-spacing: 0.12em;
  text-transform: uppercase;
  font-size: 9.5px;
  padding-top: 2px;
}
.empty-meta dd { margin: 0; color: var(--ink-2); font-weight: 400; }

/* État rempli */
.panel-content {
  display: none;
  flex-direction: column;
  gap: 12px;
  flex: 1;
  min-height: 0;
  overflow: auto;
}
.panel.is-on .panel-empty   { display: none; }
.panel.is-on .panel-note    { display: block; }
.panel.is-on .panel-content { display: flex; }

.panel-num {
  font-family: var(--mono);
  font-size: 10px;
  letter-spacing: 0.18em;
  color: var(--ink-mute);
  text-transform: uppercase;
}
.panel-num b { color: var(--ink); font-weight: 500; }
/* Titre d'œuvre du panneau de l'atlas — même règle §8bis-3. */
.panel-title {
  margin: 0;
  font-family: var(--serif);
  font-style: italic;
  font-weight: 400;
  font-size: 26px;
  line-height: 1.1;
  letter-spacing: -0.018em;
  color: var(--ink);
  text-wrap: pretty;
}
.panel-sub {
  font-family: var(--sans);
  font-style: italic;
  font-weight: 300;
  font-size: 13.5px;
  color: var(--ink-2);
  line-height: 1.4;
}
.panel-meta {
  display: grid;
  grid-template-columns: 70px 1fr;
  row-gap: 7px;
  column-gap: 14px;
  border-top: 1px solid var(--rule-soft);
  border-bottom: 1px solid var(--rule-soft);
  padding: 12px 0;
  margin: 4px 0 0;
  font-family: var(--mono);
  font-size: 11.5px;
}
.panel-meta dt {
  color: var(--ink-mute);
  letter-spacing: 0.12em;
  text-transform: uppercase;
  font-size: 9.5px;
  padding-top: 2px;
}
.panel-meta dd { margin: 0; color: var(--ink); font-weight: 400; }
.panel-tags { display: flex; flex-wrap: wrap; gap: 6px 7px; }
.panel-tags span {
  font-family: var(--mono);
  font-size: 9.5px;
  letter-spacing: 0.05em;
  color: var(--ink-mute);
  padding: 3px 7px;
  border: 1px solid var(--rule);
  border-radius: 999px;
}

/* Vignette timbre-poste dans le panneau */
.panel-stamp {
  display: grid;
  grid-template-columns: 80px 1fr;
  gap: 12px;
  align-items: center;
  margin-top: 4px;
}
.stamp-frame {
  width: 64px; height: 80px;
  border: 1px solid var(--ink);
  position: relative;
  background:
    repeating-radial-gradient(circle at 0 0, var(--paper) 0 2px, transparent 2px 4px);
  /* perforation effect with radial dots on edges */
  background-image:
    radial-gradient(circle at 50% 0, transparent 1.5px, var(--paper) 1.6px),
    radial-gradient(circle at 50% 100%, transparent 1.5px, var(--paper) 1.6px);
  background-size: 6px 4px;
  background-repeat: repeat-x, repeat-x;
  background-position: 0 0, 0 100%;
  padding: 6px 4px;
  display: flex; flex-direction: column;
}
.stamp-img {
  flex: 1;
  background: var(--paper-2);
  border: 1px solid var(--rule);
  background-image:
    repeating-linear-gradient(45deg, transparent 0 4px, rgba(10,10,8,0.04) 4px 5px);
}
/* Le timbre du PANNEAU peuplé : ni fond ni filet autour de la boîte, comme
   celui de l'Index (31/08/2026). */
.stamp-img[data-vues] {
  display: flex;
  align-items: center;
  justify-content: center;
  background: none;
  border: 0;
}
.stamp-meta {
  margin-top: 4px;
  display: flex;
  justify-content: space-between;
  font-family: var(--mono);
  font-size: 7.5px;
  letter-spacing: 0.08em;
  color: var(--ink);
}
.stamp-note {
  font-family: var(--sans);
  font-style: italic;
  font-weight: 300;
  font-size: 11.5px;
  line-height: 1.4;
  color: var(--ink-mute);
}
.stamp-note em { font-style: italic; font-weight: 400; color: var(--ink-2); }

.panel-coord {
  margin-top: auto;
  padding-top: 14px;
  border-top: 1px solid var(--rule-soft);
  display: flex;
  justify-content: space-between;
  align-items: flex-end;
  gap: 12px;
}
/* ── La section des coordonnées, réagencée le 31/08/2026 ────────────────
   Le glyphe du plan actif tient sur la HAUTEUR DES DEUX LIGNES, à gauche ;
   le titre et les valeurs sont au fer à droite, contre la marge qui les
   sépare de « Voir la fiche ». Le glyphe passe ainsi de 11 à 34 px — il
   était trop petit pour dire de quel tableau viennent les chiffres. */
.panel-coord .coords {
  flex: 1;
  font-family: var(--mono);
  font-size: 10px;
  color: var(--ink-mute);
  letter-spacing: 0.08em;
  line-height: 1.8;
  display: flex;
  align-items: center;
  gap: 10px;
}
.panel-coord .coord-txt {
  margin-left: auto;              /* pousse les deux lignes contre la marge droite */
  display: flex;
  flex-direction: column;
  align-items: flex-end;          /* … et les met au fer à droite */
  text-align: right;
}
.panel-coord .coords span { white-space: nowrap; }
.panel-coord .coords b { color: var(--ink); font-weight: 500; }
.panel-coord .coords .hint { color: var(--ink-faint); }
.panel-coord .coord-vals .sep { margin: 0 0.35em; color: var(--ink-faint); }
/* Le glyphe du plan actif, cloné du bouton de vue (main.js). */
.panel-coord .coord-glyph {
  flex: none;
  width: 34px; height: 34px;
  color: var(--ink-mute);
}
.panel-coord .coord-glyph svg { width: 100%; height: 100%; display: block; }
/* ⚠️ INEMPLOYÉES depuis le 31/08/2026 : le lien « Voir la fiche » a été retiré
   du panneau — il vivait dans un bloc qui se vide au moindre mouvement de
   souris, donc on ne pouvait jamais l'atteindre. Les règles sont conservées,
   comme .legal-strip et .sc-count : elles décrivent un objet du système. */
.panel-coord .voir {
  font-family: var(--sans);
  font-size: 13px;
  font-weight: 500;
  color: var(--ink);
  text-decoration: none;
  border-bottom: 1px solid var(--ink);
  padding-bottom: 2px;
  letter-spacing: 0.01em;
  transition: color 160ms, border-color 160ms;
}
.panel-coord .voir:hover { color: var(--ink-mute); border-color: var(--ink-mute); }

/* La note qui remplace le lien : elle dit ce qu'un clic donne. Au fer à droite,
   dans le .panel-head depuis le 01/09/2026 — elle y a pris la place de l'état,
   et se lit donc aussi quand le panneau est vide. */
.panel-note {
  /* Depuis le 01/09/2026 elle vit dans le .panel-head, à la place de l'état :
     plus rien au-dessus d'elle, donc plus de marge haute. */
  margin-top: 0;
  /* Et elle ne paraît QUE sur fiche active : sur un panneau vide, il n'y a
     aucune entrée à rejoindre, la phrase n'y voudrait rien dire. C'est aussi
     ce qui rend l'en-tête du panneau vide au repos. */
  display: none;
  font-family: var(--sans);
  font-style: italic;
  font-weight: 300;
  font-size: 11.5px;
  line-height: 1.4;
  /* --ink-mute, et non --ink-faint : c'est le jeton de l'AUTRE note du panneau
     (.stamp-note), et le faint tombe à 2,2:1 sur le fond de nuit. */
  color: var(--ink-mute);
  text-align: right;
}

/* ──────────── LÉGENDE ATLAS — V11 (compacte, sans cadre) ──────────── */
.atlas-legend {
  margin-top: 22px;
  padding: 0;
  border: 0;
  background: transparent;
  display: flex;
  align-items: flex-start;
  gap: 28px;
  flex-wrap: wrap;
  /* V11 — la rangée s'aligne sur la largeur du tableau (810px) afin
     que les toggles, poussés à droite, tombent sous "anthropologie". */
  width: 810px;
}
.lg-shapes {
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.lg-toggles {
  display: inline-flex;
  gap: 8px;
  align-items: center;
  margin-left: auto;   /* V11 — pousse les 3 boutons à droite (sous "anthropologie") */
}
.lg-item {
  display: flex; align-items: center; gap: 10px;
  font-family: var(--sans);
  font-size: 12.5px;
  color: var(--ink-2);
  line-height: 1;
}
.lg-mk {
  width: 18px; height: 18px;
  display: inline-grid; place-items: center;
  flex-shrink: 0;
}
.lg-mk.mk-oeuvre::before {
  content: ""; width: 11px; height: 11px;
  background: var(--ink); border-radius: 50%;
}
.lg-mk.mk-conf::before {
  content: "";
  width: 0; height: 0;
  border-left: 6.5px solid transparent;
  border-right: 6.5px solid transparent;
  border-bottom: 11px solid var(--ink);
}
.lg-mk.mk-ecrit::before {
  content: ""; width: 9px; height: 9px;
  background: var(--ink); transform: rotate(45deg);
}

/* Toggle bouton (Fond / Grille / N°) — V11 : icône seule, carré */
/* Toggles V11 : aucun cadre — glyphes seuls, état actif = pleine opacité */
.lg-tg {
  appearance: none;
  display: inline-grid;
  place-items: center;
  width: 30px;
  height: 30px;
  padding: 0;
  background: transparent;
  border: none;
  color: var(--ink);
  cursor: pointer;
  opacity: 0.34;
  transition: opacity 160ms ease, color 160ms ease;
}
/* On masque les libellés texte — l'icône suffit */
.lg-tg .lg-tg-lbl { display: none; }
.lg-tg:hover { opacity: 0.7; }
.lg-tg.is-on { opacity: 1; }
.lg-tg-icon {
  display: inline-block;
  width: 20px; height: 20px;
  color: currentColor;
}
.lg-tg-icon svg { width: 100%; height: 100%; display: block; }

/* Pictogramme "Fond" — carré crème plein (référence de taille des 3 boutons).
   Même crème verrouillé --atlas-creme que le fond qu'il commande (§4-5). */
.lg-tg .lg-tg-swatch {
  display: inline-block;
  width: 20px; height: 20px;
  background: var(--atlas-creme);
  border: 1px solid rgba(10,10,8,0.22);
}

/* ──────────── INDEX ──────────── */
.index-section { margin-top: 44px; padding-top: 30px; border-top: 1px solid var(--rule); }
.index-head {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 22px;
  gap: 30px;
}
/* Groupe gauche : icônes vue + titre Index */
.index-title-group {
  display: flex;
  align-items: center;
  gap: 20px;
}
.index-title-group .index-toggle-view {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  height: 40px;
}
.index-title-group .ix-btn {
  display: inline-grid; place-items: center;
  width: 34px; height: 34px;
  border: 0;
  background: transparent;
  color: var(--ink-mute);
  cursor: pointer;
  padding: 0;
  transition: color 200ms;
}
.index-title-group .ix-btn svg { width: 100%; height: 100%; display: block; }
.index-title-group .ix-btn:hover { color: var(--ink); }
.index-title-group .ix-btn.is-on { color: var(--ink); }
.index-head h3 {
  margin: 0;
  font-family: var(--sans);
  font-weight: 300;
  font-size: 40px;
  letter-spacing: -0.025em;
  color: var(--ink);
}
.index-head h3 em { font-style: italic; font-weight: 300; color: var(--ink-mute); }
.index-controls {
  display: flex; align-items: center;
  font-family: var(--mono);
}
/* Vue : liste/timbres — déplacé dans .index-title-group (voir ci-dessus) */

/* Tris : trois icônes (sans bordure, plus grandes) */
.index-toggle-sort {
  display: inline-flex;
  align-items: center;
  gap: 14px;
  margin-left: 6px;
  height: 30px;
}
.index-toggle-sort .srt-btn {
  display: inline-grid; place-items: center;
  width: 44px; height: 44px;
  border: 0;
  border-radius: 0;
  background: transparent;
  color: var(--ink-mute);
  cursor: pointer;
  padding: 0;
  transition: color 200ms, transform 200ms;
}
.index-toggle-sort .srt-btn svg { width: 100%; height: 100%; display: block; }
.index-toggle-sort .srt-btn:hover { color: var(--ink); transform: translateY(-1px); }
.index-toggle-sort .srt-btn.is-on { color: var(--ink); }

.index-table { border-top: 1px solid var(--rule); border-bottom: 1px solid var(--rule); }
/* Colonnes V8 : N° · Type · Titre · Médium · Série · Fiche (pas d'année — point 13a) */
.index-row {
  display: grid;
  grid-template-columns: 50px 96px 1.6fr 1fr 130px 80px;
  column-gap: 18px;
  padding: 14px 0;
  border-bottom: 1px solid var(--rule-soft);
  align-items: baseline;
  transition: background-color 120ms ease, padding-left 220ms ease;
  /* La bande entière est un lien vers la fiche (main.js) : elle est donc
     cliquable sur toute sa largeur, et non seulement sur « → Voir ». */
  cursor: pointer;
  color: inherit;
  text-decoration: none;
}
/* Le focus clavier doit se voir sur la bande entière (§11-7, accessibilité). */
.index-row:focus-visible {
  outline: 2px solid var(--ink);
  outline-offset: 2px;
}
[data-theme="dark"] .index-row.is-active { background: transparent; }
.index-row:last-child { border-bottom: none; }
.index-row.is-active {
  background: var(--paper-2);
  padding-left: 10px;
}
.index-row .col-num {
  font-family: var(--mono);
  font-size: 10.5px;
  color: var(--ink-mute);
  letter-spacing: 0.06em;
}
.index-row .col-type {
  font-family: var(--mono);
  font-size: 9.5px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink-mute);
  display: flex; align-items: baseline; gap: 6px;
}
.index-row .col-type::before {
  content: ""; display: inline-block; flex-shrink: 0;
  transform: translateY(2px);
}
.index-row[data-type="oeuvre"] .col-type::before {
  width: 7px; height: 7px;
  background: var(--ink); border-radius: 50%;
}
.index-row[data-type="ecrit"] .col-type::before {
  width: 7px; height: 7px;
  background: var(--ink);
  transform: translateY(1px) rotate(45deg);
}
.index-row[data-type="conference"] .col-type::before {
  width: 0; height: 0;
  border-left: 4px solid transparent;
  border-right: 4px solid transparent;
  border-bottom: 7px solid var(--ink);
}
/* Titre d'œuvre dans l'Index — Spectral italique. C'est bien un titre
   d'œuvre, il relève donc de la même règle que celui des fiches
   (CLAUDE.md §8bis-3), et non de la voix du site. */
.index-row .col-title {
  font-family: var(--serif);
  font-style: italic;
  font-size: 16.5px;
  font-weight: 400;
  line-height: 1.25;
  color: var(--ink);
  letter-spacing: -0.005em;
  text-wrap: pretty;
}
.index-row[data-poids="3"] .col-title { font-weight: 500; }
.index-row[data-poids="1"] .col-title { color: var(--ink-2); font-weight: 300; }
.index-row .col-medium {
  font-family: var(--sans);
  font-style: italic;
  font-weight: 300;
  font-size: 13px;
  color: var(--ink-2);
}
.index-row .col-serie {
  font-family: var(--mono);
  font-size: 10px;
  letter-spacing: 0.08em;
  color: var(--ink-mute);
  text-transform: lowercase;
}
.index-row .col-link {
  font-family: var(--sans);
  font-size: 12.5px;
  font-weight: 500;
  color: var(--ink);
  text-decoration: none;
  text-align: right;
  letter-spacing: 0.01em;
}
.index-row .col-link:hover { color: var(--ink-mute); }
.index-head-row {
  display: grid;
  grid-template-columns: 50px 96px 1.6fr 1fr 130px 80px;
  column-gap: 18px;
  padding: 0 0 12px;
  font-family: var(--mono);
  font-size: 9.5px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--ink-faint);
  border-bottom: 1px solid var(--rule);
}
.index-head-row .col-link { text-align: right; }

/* Grille de timbres */
.stamp-grid {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  gap: 32px 18px;
  padding: 24px 0;
}
.stamp-grid[hidden] { display: none; }
.stamp-cell {
  display: flex; flex-direction: column; gap: 8px;
  /* Le timbre entier est un lien vers la fiche (main.js), comme la bande de
     l'Index : mêmes trois lignes que .index-row. */
  cursor: pointer;
  color: inherit;
  text-decoration: none;
}
/* Le focus clavier doit se voir sur le timbre entier (§11-7, accessibilité). */
.stamp-cell:focus-visible {
  outline: 2px solid var(--ink);
  outline-offset: 3px;
}
.stamp-cell .sc-frame {
  width: 64px; height: 80px;
  border: 1px solid var(--ink);
  margin: 0 auto;
  position: relative;
  padding: 5px 4px;
  display: flex; flex-direction: column;
  background-image:
    radial-gradient(circle at 50% 0, transparent 1.5px, var(--paper) 1.6px),
    radial-gradient(circle at 50% 100%, transparent 1.5px, var(--paper) 1.6px);
  background-size: 6px 4px;
  background-repeat: repeat-x;
  background-position: 0 0, 0 100%;
  transition: transform 220ms ease;
}
/* Timbre série SANS image : compartiments vides à l'intérieur du cadre.
   Depuis les micro-vignettes (31/08/2026), ce repli ne sert plus qu'à une
   entrée en série dont le dossier d'images serait vide. */
.stamp-cell.is-series .sc-img:not([data-vues]) {
  display: grid;
  gap: 1px;
  background-image: none;
  background-color: var(--ink);
}
.stamp-cell.is-series .sc-img:not([data-vues]) > .sc-tile {
  background: var(--paper-2);
  background-image:
    repeating-linear-gradient(45deg, transparent 0 4px, rgba(10,10,8,0.04) 4px 5px);
}
.stamp-cell.is-series[data-count="2"] .sc-img:not([data-vues]) { grid-template-columns: 1fr 1fr; }
.stamp-cell.is-series[data-count="3"] .sc-img:not([data-vues]) { grid-template-columns: 1fr 1fr; grid-template-rows: 1fr 1fr; }
.stamp-cell.is-series[data-count="3"] .sc-img:not([data-vues]) > .sc-tile:nth-child(1) { grid-column: 1 / 3; }
.stamp-cell.is-series[data-count="4"] .sc-img:not([data-vues]),
.stamp-cell.is-series[data-count="5"] .sc-img:not([data-vues]),
.stamp-cell.is-series[data-count="6"] .sc-img:not([data-vues]) {
  grid-template-columns: 1fr 1fr;
  grid-template-rows: 1fr 1fr;
}
.stamp-cell.is-series[data-count="7"] .sc-img:not([data-vues]),
.stamp-cell.is-series[data-count="8"] .sc-img:not([data-vues]),
.stamp-cell.is-series[data-count="9"] .sc-img:not([data-vues]) {
  grid-template-columns: 1fr 1fr 1fr;
  grid-template-rows: 1fr 1fr 1fr;
}
/* ⚠️ INEMPLOYÉE depuis le 31/08/2026 : le compte de série ne s'affiche plus
   à côté de la date (main.js ne l'écrit plus). La règle est conservée, comme
   .w-kicker et .w-data — elle décrit un objet du système. */
.stamp-cell.is-series .sc-cap .sc-count {
  display: inline-block;
  margin-left: 5px;
  font-family: var(--mono);
  font-size: 8.5px;
  letter-spacing: 0.06em;
  color: var(--ink-mute);
}
.stamp-cell:hover .sc-frame,
.stamp-cell.is-active .sc-frame { transform: translate(-2px, -2px); box-shadow: 4px 4px 0 var(--ink); }
.stamp-cell .sc-img {
  flex: 1;
  background: var(--paper-2);
  border: 1px solid var(--rule);
  background-image:
    repeating-linear-gradient(45deg, transparent 0 4px, rgba(10,10,8,0.04) 4px 5px);
  position: relative;
  overflow: hidden;
}
/* ── Micro-vignettes du timbre (data/vignettes.js) ──────────────────────
   1, 2 ou 4 vues selon le nombre d'images de l'entrée. Le cadre ne grandit
   pas : le principe du timbre reste entier (GABARITS.md §4) — il ne s'agit
   pas de donner l'œuvre à voir, mais de poser une pointe de couleur.

   ⚠️ AUCUN CADRE EN PLUS DE CELUI DU TIMBRE (consigne du propriétaire,
   31/08/2026). Le filet de .sc-img et le liseré intérieur du niveau 3
   doublaient le cadre du timbre et chevauchaient l'image : ils ne
   s'appliquent plus qu'aux timbres SANS image.

   ⚠️ LA BOÎTE SUIT LE FORMAT DES IMAGES. Sa taille et sa grille sont posées
   en style local par main.js, depuis le manifeste : lui seul connaît les
   formats. Les fichiers étant déjà recadrés au format de leur case, le
   `cover` ci-dessous n'est qu'une sécurité — il n'a rien à rogner. */
.stamp-cell .sc-img[data-vues] {
  display: flex;
  align-items: center;
  justify-content: center;
  /* ⚠️ NI FOND NI FILET (31/08/2026). L'aplat --paper-2 de la zone se lisait
     comme des « bandes grises » autour de l'image ; ce qui entoure la boîte
     doit être le PAPIER du timbre, rien d'autre. La boîte, elle, épouse
     désormais le format du fichier à 6 % près (seuil du script) : le vide
     qu'elle laisse est assumé, il n'a pas à se signaler par une couleur. */
  background: none;
  border: 0;
}
.sc-planche {
  display: grid;
  gap: 1px;                      /* le filet d'encre entre deux vues */
  background: var(--ink);
  overflow: hidden;
}
.sc-planche img {
  width: 100%; height: 100%;
  display: block;
  object-fit: cover;
  background: var(--paper-2);
}
/* Le liseré du niveau 3 ne vaut plus que pour un timbre sans image ; ailleurs,
   le niveau se lit comme dans l'Index — par la graisse du titre
   (cf. .index-row[data-poids="3"] .col-title). */
.stamp-cell[data-poids="3"] .sc-cap .sc-t { font-weight: 500; }
.stamp-cell[data-poids="3"] .sc-img:not([data-vues])::after {
  content: "";
  position: absolute; inset: 4px;
  border: 1px solid var(--ink);
}
.stamp-cell .sc-meta {
  margin-top: 3px;
  display: flex; justify-content: space-between;
  font-family: var(--mono); font-size: 7px;
  color: var(--ink);
  letter-spacing: 0.06em;
}
.stamp-cell .sc-cap {
  text-align: center;
  font-family: var(--sans);
  font-size: 11.5px;
  line-height: 1.25;
  color: var(--ink);
  letter-spacing: -0.005em;
  text-wrap: pretty;
}
.stamp-cell .sc-cap .sc-num {
  display: block;
  font-family: var(--mono);
  font-size: 9px;
  letter-spacing: 0.16em;
  color: var(--ink-mute);
  margin-bottom: 3px;
}

/* ──────────── MENTIONS LÉGALES (legacy class — supprimé) ──────────── */
.legal-strip { display: none; }

/* ──────────── COLOPHON ──────────── */
.colo-grid {
  display: grid;
  grid-template-columns: 2fr 1fr;
  gap: 60px;
  align-items: start;
  padding: 28px 0;
  border-bottom: 1px solid var(--rule);
}
.colo-quote {
  margin: 0;
  font-family: var(--sans);
  font-weight: 300;
  font-style: italic;
  font-size: 30px;
  line-height: 1.32;
  color: var(--ink);
  letter-spacing: -0.015em;
  text-wrap: pretty;
  padding-left: 22px;
  border-left: 2px solid var(--ink);
}
.colo-side .cs-label {
  font-family: var(--mono);
  font-size: 10px;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--ink-mute);
  margin-bottom: 12px;
}
.colo-side .cs-tags {
  list-style: none; margin: 0; padding: 0;
  display: flex; flex-wrap: wrap; gap: 6px 8px;
}
.colo-side .cs-tags li {
  font-family: var(--mono);
  font-size: 10.5px;
  letter-spacing: 0.05em;
  color: var(--ink-mute);
  padding: 4px 9px;
  border: 1px solid var(--rule);
  border-radius: 999px;
}

.colo-grid-2 {
  grid-template-columns: 1fr 1fr 1fr;
  border-bottom: none;
  padding-top: 40px;
}
.colo-block h4 {
  margin: 0 0 12px;
  font-family: var(--mono);
  font-size: 10px;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--ink-mute);
  font-weight: 500;
}
.colo-block p {
  margin: 0 0 14px;
  font-family: var(--sans);
  font-size: 14.5px;
  line-height: 1.6;
  font-weight: 300;
  color: var(--ink);
  text-wrap: pretty;
}
.colo-block p em { font-style: italic; font-weight: 400; color: var(--ink-2); }
.colo-link {
  font-family: var(--sans);
  font-size: 13px;
  font-weight: 500;
  color: var(--ink);
  text-decoration: none;
  border-bottom: 1px solid var(--ink);
  padding-bottom: 2px;
  letter-spacing: 0.01em;
}
.colo-link:hover { color: var(--ink-mute); border-color: var(--ink-mute); }

/* ──────────── FOOTER (mentions légales fusionnées) ──────────── */
.footer {
  margin-top: 60px;
  padding: 26px 0 36px;
  border-top: 1px solid var(--rule);
  font-family: var(--mono);
  font-size: 10px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--ink-mute);
}
.ft-row-1 {
  display: grid;
  grid-template-columns: 1fr 1fr 1fr;
  align-items: center;
  gap: 16px;
}
.ft-row-2 {
  margin-top: 16px;
  padding-top: 14px;
  border-top: 1px solid var(--rule-soft);
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
  font-size: 10px;
  letter-spacing: 0.08em;
  text-transform: none;
  color: var(--ink-mute);
}
.ft-row-2 a {
  color: var(--ink-2);
  text-decoration: none;
  border-bottom: 1px solid var(--rule);
  padding-bottom: 1px;
  transition: color 160ms, border-color 160ms;
}
.ft-row-2 a:hover { color: var(--ink); border-color: var(--ink); }
.ft-row-2 .ft-dim { color: var(--ink-faint); margin-left: auto; }
.ft-row-2 .sep { color: var(--ink-faint); margin: 0 2px; }
.ft-l { display: flex; align-items: center; gap: 12px; }
.ft-logo {
  width: 32px; height: 32px;
  object-fit: contain;
}
[data-theme="dark"] .ft-logo { filter: invert(1) brightness(1.15); }
.ft-sig { color: var(--ink); font-weight: 500; }
.ft-c { text-align: center; }
.ft-r { text-align: right; }
.ft-c .dot {
  display: inline-block;
  width: 6px; height: 6px;
  background: var(--ink);
  border-radius: 50%;
  margin-right: 8px;
  transform: translateY(-1px);
}

/* V11 — Cadre lié au toggle grille de la légende */
.map-wrap[data-frame="none"] .map { border-color: transparent !important; }
.map-wrap[data-frame="hairline"] .map { border-color: var(--rule); }

/* V11 — Titres des axes : Capitales par défaut (axisstyle = caps) */
.map-wrap[data-axisstyle="caps"] .axis-x .pole,
.map-wrap[data-axisstyle="caps"] .axis-y .pole,
.map-wrap[data-axisstyle="caps"] .ternary-pole {
  font-family: var(--mono);
  text-transform: uppercase;
  letter-spacing: 0.18em;
  font-size: 10.5px;
}
/* Les labels 1D sont déjà en uppercase via .axis-1d (CSS). */

/* V11 — Fils de série : toggle off */
.map-wrap[data-threads="off"] .series-thread { display: none; }


/* ═══ pages.css (fiches / pages intérieures) — repris à l'identique ═══ */

/* ─────────────────────────────────────────────────────────
   V11 — pages.css
   Styles partagés aux pages internes : Démarche, Biographie,
   Œuvre. Repose sur v11.css (menubar, footer, tokens).
   ───────────────────────────────────────────────────────── */

/* ────── Conteneur de page interne ────── */
.subpage {
  /* ⚠️ 1240px FIXE, et il le reste à partir de 1280 px de fenêtre (LOT 15) :
     elle déborde de 40 px le cadre de `.page` (1240 − 2 × 20 px de padding),
     et c'est CE rendu qui est validé. Un `min(1240px, 100%)` la rétrécissait
     de 40 px sur grand écran — mesuré, puis écarté. Elle ne se libère que
     sous 1280 px (bloc « LOT 15 », plus bas). */
  width: 1240px;
  margin: 0 auto;
  padding: 56px 20px 80px;
  position: relative;
}

/* Fil d'Ariane / breadcrumb */
.crumbs {
  display: flex;
  align-items: center;
  gap: 8px;
  font-family: var(--mono);
  font-size: 10.5px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--ink-mute);
  margin: 0 0 28px;
}
.crumbs a {
  color: var(--ink-mute);
  text-decoration: none;
  border-bottom: 1px solid transparent;
  transition: border-color 160ms ease, color 160ms ease;
}
.crumbs a:hover { color: var(--ink); border-color: var(--ink); }
.crumbs .sep { color: var(--rule); }

/* ────── Titre de page ────── */
.page-head {
  display: grid;
  grid-template-columns: 1fr 320px;
  gap: 60px;
  align-items: end;
  margin-bottom: 64px;
  padding-bottom: 28px;
  border-bottom: 1px solid var(--rule);
}
.page-title {
  font-family: var(--sans);
  font-size: 96px;
  font-weight: 300;
  letter-spacing: -0.02em;
  line-height: 0.95;
  margin: 0 0 16px;
  color: var(--ink);
}
.page-title em {
  font-style: italic;
  font-weight: 300;
  color: var(--ink-2);
}
.page-tagline {
  font-family: var(--sans);
  font-size: 17px;
  font-style: italic;
  line-height: 1.5;
  color: var(--ink-2);
  margin: 0;
  max-width: 56ch;
}
.page-meta {
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--ink-mute);
  line-height: 1.9;
}
.page-meta dt {
  display: inline;
  color: var(--rule);
}
.page-meta dt::after { content: " "; }
.page-meta dd {
  display: inline;
  margin: 0;
  color: var(--ink-2);
}
.page-meta dd::after { content: "\A"; white-space: pre; }

/* ────── Section heading ────── */
.s-head {
  display: flex;
  align-items: baseline;
  gap: 16px;
  margin: 56px 0 22px;
  padding-bottom: 10px;
  border-bottom: 1px solid var(--rule);
}
.s-num {
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: 0.18em;
  color: var(--ink-mute);
  font-weight: 500;
}
/* Titre de section — Spectral italique Medium (charte : .w-sectitle). */
.s-title {
  font-family: var(--serif);
  font-style: italic;
  font-size: 30px;
  font-weight: 500;
  letter-spacing: -0.005em;
  color: var(--ink);
  margin: 0;
  flex: 1;
}
.s-aside {
  font-family: var(--mono);
  font-size: 10.5px;
  letter-spacing: 0.15em;
  text-transform: uppercase;
  color: var(--ink-mute);
}

/* ────── Bloc texte long ────── */
.long-prose {
  font-family: var(--sans);
  font-size: 16px;
  font-weight: 300;
  line-height: 1.65;
  color: var(--ink-2);
  max-width: 70ch;
}
.long-prose p {
  margin: 0 0 18px;
}
.long-prose p:first-child::first-letter {
  font-family: var(--sans);
  font-size: 56px;
  font-weight: 300;
  line-height: 0.9;
  float: left;
  padding: 6px 10px 0 0;
  color: var(--ink);
}
.long-prose em { font-style: italic; color: var(--ink); }
.long-prose strong { font-weight: 500; color: var(--ink); }
.long-prose a {
  color: var(--ink);
  text-decoration: none;
  border-bottom: 1px solid var(--rule);
  padding-bottom: 1px;
  transition: border-color 160ms ease;
}
.long-prose a:hover { border-color: var(--ink); }

/* Pull-quote */
/* Citation — Spectral italique (§8bis-3 : Spectral = titres d'œuvres ET
   citations ; charte : .w-quote .qt). */
.pull-quote {
  font-family: var(--serif);
  font-size: 26px;
  font-weight: 300;
  font-style: italic;
  line-height: 1.4;
  letter-spacing: -0.005em;
  color: var(--ink);
  padding: 28px 0 28px 28px;
  margin: 36px 0;
  border-left: 1px solid var(--ink);
  max-width: 60ch;
}
.pull-quote cite {
  display: block;
  margin-top: 14px;
  font-family: var(--mono);
  font-size: 10.5px;
  font-style: normal;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--ink-mute);
}

/* ────── Layout 2-cols (texte + side) ────── */
.split {
  display: grid;
  grid-template-columns: 1fr 320px;
  gap: 80px;
  align-items: start;
}
.split-l { min-width: 0; }
.split-r { font-family: var(--mono); }

.side-card {
  border: 1px solid var(--rule);
  padding: 22px 22px 24px;
  background: var(--paper);
  font-family: var(--mono);
  font-size: 11.5px;
  letter-spacing: 0.04em;
  color: var(--ink-2);
  line-height: 1.55;
  margin-bottom: 22px;
}
.side-card h4 {
  font-family: var(--mono);
  font-size: 10px;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--ink-mute);
  margin: 0 0 14px;
  font-weight: 500;
}
.side-card ul { margin: 0; padding: 0; list-style: none; }
.side-card li {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  padding: 6px 0;
  border-bottom: 1px dotted var(--rule);
  gap: 10px;
}
.side-card li:last-child { border-bottom: 0; }
.side-card .k {
  font-size: 10px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-mute);
  flex-shrink: 0;
}
.side-card .v { color: var(--ink); text-align: right; }

/* ────── Bouton "Lire plus" / lien d'action ────── */
.cta {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--ink);
  text-decoration: none;
  padding: 12px 18px;
  border: 1px solid var(--ink);
  transition: background-color 160ms ease, color 160ms ease;
}
.cta:hover { background: var(--ink); color: var(--paper); }
.cta .arrow { font-family: var(--mono); }

/* ────── Tag / chip ────── */
.chips {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin: 12px 0 0;
}
.chip {
  display: inline-flex;
  align-items: center;
  font-family: var(--mono);
  font-size: 10.5px;
  letter-spacing: 0.06em;
  padding: 4px 9px;
  border: 1px solid var(--rule);
  color: var(--ink-2);
  background: transparent;
}

/* ────── Bilinguisme FR/EN ──────
   Un bloc `[data-texte="fr"]` ou `[data-texte="en"]` n'est visible que si
   <html> porte le `data-langue` correspondant. Il est posé DEUX fois : par le
   script d'amorçage du <head>, avant le premier affichage, et par main.js
   (PARTIE 1) à chaque clic sur les boutons du menubar.
   Par défaut, sans `data-langue`, c'est le français qui est servi.
   `revert` rend à chaque élément son affichage naturel (bloc pour un <p>,
   en ligne pour un <span>) : une seule règle suffit pour tous les cas.

   ⚠️ L'attribut s'appelle `data-texte` et NON `data-lang` : les deux boutons
   de bascule du menubar portent déjà `data-lang="fr"` et `data-lang="en"`.
   Un sélecteur sur `data-lang` masquerait donc le bouton EN lui-même — ce
   qui est arrivé, et se voyait au premier chargement. */
[data-texte="en"] { display: none; }
[data-langue="en"] [data-texte="en"] { display: revert; }
[data-langue="en"] [data-texte="fr"] { display: none; }

/* Bloc « Référence Atlas » de la colonne latérale d'une fiche : les chiffres
   bruts de l'entrée dans le tableau maître. Reprend les valeurs que le
   gabarit du design source portait en styles en ligne. */
.atlas-ref {
  margin: 0;
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: 0.04em;
  line-height: 1.7;
  color: var(--ink-2);
}
.atlas-ref .ar-k { color: var(--ink-mute); }

/* ────── Mini-Atlas (pour fiche œuvre) ────── */
.miniatlas {
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  gap: 14px;
  margin: 22px 0 0;
}
.miniatlas-cell {
  position: relative;
  background: var(--paper-2);
  border: 1px solid var(--rule);
  aspect-ratio: 1 / 1;
  display: grid;
  place-items: center;
  overflow: hidden;
}
/* Le fond des cases, posé par CLASSE et non plus en ligne (01/09/2026) :
   main.js (PARTIE 3) marque chaque case `ma-carre` ou `ma-nu`, les couleurs
   vivent ici. Un style en ligne l'emportait sur toute règle de thème. */
/* ⚠️ LE CADRE DES CARRÉS PREND L'ENCRE PLEINE — consigne du propriétaire,
   01/09/2026. Il héritait du --rule de .miniatlas-cell, c'est-à-dire de 16 %
   d'encre en jour et 18 % en nuit, quand le tracé des triangles est en
   `currentColor`, donc à --ink plein. Le picto rendait ainsi deux gris et deux
   noirs (ou deux blancs) côte à côte. Les quatre traits sont désormais de la
   même encre, dans les deux thèmes.
   ⚠️ Ne PAS étendre à `.ma-nu` : la case de la vue 1D (inscription ↔ rencontre)
   garde son filet en --rule, que le propriétaire trouve juste. */
.miniatlas-cell.ma-carre {
  background: var(--atlas-creme);
  /* Le `border` s'efface : le cadre est désormais un tracé SVG posé par
     main.js (PARTIE 3), seul moyen de tenir 0,7 px — un border-width
     fractionnaire est rabattu sur le pixel de l'écran et rendait 0,5.
     0,7 px est l'épaisseur commune des quatre traits, arbitrée par le
     propriétaire le 01/09/2026 : c'était celle des triangles. */
  border: none;
}
.miniatlas-cell.ma-nu    { background: transparent; border: none; }

/* ⚠️ EN NUIT, LES CASES CARRÉES N'ONT PAS DE FOND — consigne du propriétaire,
   01/09/2026. Le grand tableau ne l'a pas davantage : la règle
   `[data-theme="dark"] .map-wrap[data-view="v1"|"v3"|"v4"|"v5"] .map` le passe
   en `transparent !important` dans les quatre vues. Le picto, lui, rendait un
   rectangle #1f1e18 sur un papier #0a0a09 — une boîte que l'atlas n'a pas.
   Désormais seul le CADRE dit la forme du tableau, comme le tracé le fait pour
   les triangles.
   ⚠️ Le token --atlas-creme n'est NI renommé NI redéfini (CLAUDE.md §4-5) : il
   n'est simplement pas CONSOMMÉ en nuit, là où l'atlas ne le consomme pas non
   plus. Ne pas « rétablir » ce fond en croyant réparer un oubli. */
[data-theme="dark"] .miniatlas-cell.ma-carre { background: transparent; }

.miniatlas-cell .lbl {
  position: absolute;
  bottom: 6px; left: 8px;
  font-family: var(--mono);
  font-size: 9px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-mute);
}
/* Marqueur du picto — réduit de 80 % (12 px → 2,4 px).
   Deux raisons, qui vont dans le même sens :
   · les points débordaient des carrés et surtout des triangles. Un marqueur
     de 12 px dans une case de 58 px déborde de près de 5 px dès qu'il
     approche un bord, alors que posFor() place légitimement des points
     jusqu'à 2 % du bord. Réduire la FORME suffit à régler le débordement,
     sans fausser la position — on ne déplace rien, on dégonfle.
   · à l'échelle, le picto retrouve la justesse du grand tableau : là, un
     marqueur mesure de 1,3 % à 3,2 % du côté ; ici il en faisait 20,7 %.
     À 2,4 px sur 58, il en fait 4,1 % — enfin du même ordre.
   Une seule valeur à régler pour les trois formes. */
.miniatlas {
  --picto-pos: 2.4px;
}
.miniatlas-cell .pos {
  position: absolute;
  background: var(--ink);
  border-radius: 50%;
  width: var(--picto-pos); height: var(--picto-pos);
  transform: translate(-50%, -50%);
}
.miniatlas-cell svg.tri,
.miniatlas-cell svg.cadre {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  opacity: 0.3;
}
.miniatlas-cell .pos.diamond {
  border-radius: 0;
  transform: translate(-50%, -50%) rotate(45deg);
}
/* Triangle (conférences) — dessiné en bordures, donc dimensionné à part.
   Mêmes proportions qu'avant, à la même échelle réduite que le rond. */
.miniatlas-cell .pos.triangle {
  background: transparent;
  width: 0; height: 0;
  border-left:  calc(var(--picto-pos) * 0.58) solid transparent;
  border-right: calc(var(--picto-pos) * 0.58) solid transparent;
  border-bottom: var(--picto-pos) solid var(--ink);
}

/* Disposition validée du picto (reprise de l'en-tête de
   _design-source/oeuvre-contrat-social.html, qui surchargeait la grille
   ci-dessus) : les 5 vues en une seule rangée, chacune surmontée de son
   icône. Les `!important` de la source ne sont plus nécessaires, ces règles
   venant après celles qu'elles remplacent — le rendu est identique. */
.miniatlas {
  display: flex;
  gap: 20px;
  align-items: center;
  flex-wrap: nowrap;
}
.ma-item {
  display: flex;
  flex-direction: column-reverse;   /* l'icône se retrouve AU-DESSUS de la case */
  align-items: center;
  gap: 6px;
}
.miniatlas .miniatlas-cell {
  width: 58px; height: 58px;
  flex-shrink: 0;
}
.ma-icon {
  width: 20px; height: 20px;
  color: var(--ink-mute);
  flex-shrink: 0;
}
.ma-icon svg { width: 100%; height: 100%; display: block; }
/* Dans le picto, le triangle ternaire est opaque (dans l'atlas il est
   estompé, car il y sert de fond à 72 marqueurs et non à un seul). */
.miniatlas-cell svg.tri,
.miniatlas-cell svg.cadre { opacity: 1; }

/* Repli mobile : 5 cases de 58 px + 4 gouttières de 20 px font 370 px et
   déborderaient d'un écran de 375 px. Même seuil que le reste du site. */
@media (max-width: 900px) {
  .miniatlas { gap: 10px; }
  .miniatlas .miniatlas-cell { width: 48px; height: 48px; }
}

/* ────── Toggles (pour bio) ────── */
.toggle-row {
  display: flex;
  flex-wrap: wrap;
  gap: 36px;
  align-items: center;
  padding: 18px 0;
  border-top: 1px solid var(--rule);
  border-bottom: 1px solid var(--rule);
  margin-bottom: 40px;
}
.toggle-group {
  display: flex;
  align-items: center;
  gap: 14px;
}
.toggle-label {
  font-family: var(--mono);
  font-size: 10px;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--ink-mute);
}
.toggle-segs {
  display: inline-flex;
  border: 1px solid var(--rule);
}
.toggle-segs button {
  appearance: none;
  background: transparent;
  border: 0;
  border-right: 1px solid var(--rule);
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: 0.06em;
  padding: 8px 16px;
  color: var(--ink-2);
  cursor: pointer;
  text-transform: uppercase;
  transition: background-color 160ms ease, color 160ms ease;
}
.toggle-segs button:last-child { border-right: 0; }
.toggle-segs button:hover { color: var(--ink); }
.toggle-segs button.is-active {
  background: var(--ink);
  color: var(--paper);
}

/* ────── Bio cells (modular content) ────── */
.bio-card {
  display: none;
}
.bio-card.is-visible { display: block; }
.bio-meta {
  display: grid;
  grid-template-columns: 90px 1fr;
  gap: 6px 16px;
  font-family: var(--mono);
  font-size: 12px;
  margin: 24px 0;
}
.bio-meta dt {
  font-size: 10px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-mute);
  align-self: center;
}
.bio-meta dd {
  margin: 0;
  color: var(--ink-2);
  padding-bottom: 6px;
  border-bottom: 1px dotted var(--rule);
}

/* ────── Timeline (bio) ────── */
.tl {
  list-style: none;
  margin: 28px 0 0;
  padding: 0;
  border-top: 1px solid var(--rule);
}
.tl-item {
  display: grid;
  grid-template-columns: 86px 1fr;
  gap: 22px;
  padding: 14px 0;
  border-bottom: 1px dotted var(--rule);
  align-items: baseline;
}
.tl-year {
  font-family: var(--mono);
  font-size: 12px;
  letter-spacing: 0.1em;
  color: var(--ink);
  font-weight: 500;
}
.tl-body {
  font-family: var(--sans);
  font-size: 14.5px;
  font-weight: 300;
  line-height: 1.5;
  color: var(--ink-2);
}
.tl-body em { font-style: italic; color: var(--ink); }
.tl-body .tl-tag {
  display: inline-block;
  font-family: var(--mono);
  font-size: 9.5px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--ink-mute);
  margin-right: 10px;
}

/* ────── Œuvre — Hero ────── */
.work-hero {
  display: grid;
  grid-template-columns: 1.2fr 1fr;
  gap: 56px;
  align-items: end;
  margin-bottom: 36px;
  padding-bottom: 28px;
  border-bottom: 1px solid var(--rule);
}
.work-hero-l { min-width: 0; }
.work-cartel {
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: 0.06em;
  color: var(--ink-mute);
  text-transform: uppercase;
  margin: 0 0 14px;
}
.work-cartel .sep {
  margin: 0 8px;
  color: var(--rule);
}
/* Titre d'œuvre — Spectral italique (CLAUDE.md §8bis-3 et charte des 19
   gabarits validés : .w-worktitle). Spectral a une hauteur d'œil plus
   basse qu'Ubuntu : à corps égal elle paraîtrait plus petite, d'où le
   passage de 64 à 68 px, qui rétablit la présence optique du titre. */
.work-title {
  font-family: var(--serif);
  font-style: italic;
  font-size: 68px;
  font-weight: 300;
  letter-spacing: -0.02em;
  line-height: 1;
  margin: 0 0 18px;
  color: var(--ink);
}
/* Sous-titre d'œuvre — Spectral italique (charte : .w-worksub). */
.work-subtitle {
  font-family: var(--serif);
  font-size: 21px;
  font-style: italic;
  font-weight: 300;
  line-height: 1.45;
  color: var(--ink-2);
  margin: 0 0 18px;
  max-width: 50ch;
}
.work-tags {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin: 18px 0 0;
}

/* Media placeholder (œuvre) */
.media-slot {
  position: relative;
  width: 100%;
  aspect-ratio: 16 / 9;
  background:
    repeating-linear-gradient(135deg,
      var(--paper-2),
      var(--paper-2) 14px,
      var(--paper) 14px,
      var(--paper) 28px);
  border: 1px solid var(--rule);
  display: grid;
  place-items: center;
  overflow: hidden;
}
.media-slot .ms-label {
  font-family: var(--mono);
  font-size: 10.5px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--ink-mute);
  background: var(--paper);
  padding: 8px 14px;
  border: 1px solid var(--rule);
}
.media-slot[data-format="portrait"] { aspect-ratio: 3 / 4; }
.media-slot[data-format="square"]   { aspect-ratio: 1 / 1; }

/* Image RÉELLE d'une fiche — CLAUDE.md §4-3 et §4-4.
   Posée DIRECTEMENT sur la grille : ni filet, ni passe-partout, ni padding
   de cadre. Et au ratio de son propre fichier, jamais recadrée : les
   attributs width/height portés par le <img> donnent ce ratio au
   navigateur, qui réserve donc la bonne place avant même le chargement
   (aucun saut de mise en page).
   À ne pas confondre avec .media-slot juste au-dessus, qui matérialise
   l'emplacement VIDE d'une image encore à fournir — son filet hachuré
   signale un manque, il n'encadre aucune œuvre.

   ── LE TIMBRE (décision propriétaire, principe fondateur) ──────────────
   Les images du site sont DÉLIBÉRÉMENT minuscules, à l'échelle d'un timbre
   poste. Elles attestent que l'œuvre existe ; elles ne la donnent pas à
   voir. Pour la voir, il faut se déplacer dans l'espace d'exposition.
   Ce n'est donc PAS une contrainte technique à desserrer : agrandir une
   image ici contredirait le propos du site. Le cahier des charges des
   canvas pose le même invariant — « ne jamais agrandir un timbre pour
   *remplir* l'écran ».
   La largeur est bornée, jamais la hauteur : le ratio reste intact (§4-4),
   et une image en portrait occupe la même largeur qu'une en paysage. */
.work-media {
  display: block;
  width: 100%;
  max-width: var(--timbre, 140px);
  height: auto;
  border: 0;
}
/* Dans une planche de plusieurs timbres, ils sont plus petits encore. */
.media-grid .work-media { max-width: var(--timbre-planche, 110px); }

.media-grid {
  display: grid;
  gap: 14px;
  margin-top: 18px;
}
.media-grid.cols-2 { grid-template-columns: 1fr 1fr; }
.media-grid.cols-3 { grid-template-columns: 1fr 1fr 1fr; }
.media-cap {
  font-family: var(--mono);
  font-size: 10.5px;
  letter-spacing: 0.06em;
  color: var(--ink-mute);
  margin: 8px 2px 0;
  line-height: 1.4;
}

/* Crédits techniques (cartel détaillé) */
.tech-list {
  display: grid;
  grid-template-columns: 130px 1fr;
  gap: 4px 22px;
  font-family: var(--mono);
  font-size: 12px;
  margin: 14px 0 0;
}
.tech-list dt {
  font-size: 10px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--ink-mute);
  align-self: baseline;
  padding-top: 8px;
}
.tech-list dd {
  margin: 0;
  color: var(--ink-2);
  padding: 6px 0;
  border-bottom: 1px dotted var(--rule);
  line-height: 1.55;
}

/* Œuvres apparentées (grid) */
.related-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 20px;
  margin-top: 22px;
}
.rel-card {
  display: block;
  text-decoration: none;
  color: inherit;
  border: 1px solid var(--rule);
  padding: 18px 18px 20px;
  background: var(--paper);
  transition: border-color 160ms ease, transform 160ms ease;
}
.rel-card:hover {
  border-color: var(--ink);
  transform: translateY(-1px);
}
.rel-card .rel-type {
  font-family: var(--mono);
  font-size: 9.5px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--ink-mute);
  margin-bottom: 10px;
}
.rel-card .rel-title {
  font-family: var(--sans);
  font-size: 15.5px;
  font-weight: 400;
  letter-spacing: -0.005em;
  color: var(--ink);
  line-height: 1.3;
  margin: 0 0 6px;
}
.rel-card .rel-medium {
  font-family: var(--mono);
  font-size: 10.5px;
  color: var(--ink-2);
}

/* Festivals / projections (œuvre) */
.fest-list {
  list-style: none;
  margin: 18px 0 0;
  padding: 0;
}
.fest-list li {
  display: grid;
  grid-template-columns: 80px 1fr 200px;
  gap: 22px;
  padding: 10px 0;
  border-bottom: 1px dotted var(--rule);
  font-family: var(--mono);
  font-size: 11.5px;
  color: var(--ink-2);
}
.fest-list .fest-year { color: var(--ink); font-weight: 500; }
.fest-list .fest-name { color: var(--ink-2); }
.fest-list .fest-place { color: var(--ink-mute); text-align: right; }

/* Section spacing helper */
.section { margin-top: 72px; }
.section:first-of-type { margin-top: 0; }

/* ═══════════════════════════════════════════════════════════════════════
   REPLI MOBILE — Lot 4b (CLAUDE.md §2bis-4)

   Tout ce qui suit ne s'applique QUE sous 900 px. Au-dessus du seuil, le
   rendu est strictement celui d'avant ce lot : aucune règle existante n'a
   été modifiée, ce bloc n'est qu'ajouté.
   Les sept sous-pages (biographie, démarche…) ont leur propre bloc, plus
   bas (« REPLI MOBILE DES SOUS-PAGES — LOT 15 ») ; les règles partagées
   ci-dessous (conteneurs, menubar, footer) les concernent aussi.
   ═══════════════════════════════════════════════════════════════════════ */
@media (max-width: 900px) {

  /* ────── Conteneurs partagés : plus de largeur fixe, donc plus de
     débordement horizontal ────── */
  .page { width: auto; max-width: 100%; padding: 0 16px; }
  .menubar-inner { width: auto; max-width: 100%; padding: 8px 16px; }

  /* ────── Menubar sur deux lignes ──────
     Le prototype impose height:60px en style en ligne sur les 3 pages :
     !important est le seul moyen de laisser la barre respirer ici. */
  .menubar-inner {
    height: auto !important;
    grid-template-columns: 1fr auto;
    row-gap: 8px;
  }
  /* Placement explicite : sans lui, la grille repousse .menubar-right sur une
     troisième rangée et la barre atteint 152 px de haut. */
  .menubar-left  { grid-column: 1; grid-row: 1; }
  .menubar-right { grid-column: 2; grid-row: 1; }
  .menu-nav {
    grid-column: 1 / -1; grid-row: 2;
    justify-content: flex-start;
    flex-wrap: wrap;
    gap: 18px;
  }
  /* La ligne sous le nom — « ART · ANTHROPOLOGIE · CINÉMA » depuis le 01/09/2026,
     « ANC. RIO VÀN EIR » avant lui. Masquée ici faute de place : la barre passe
     à deux rangées et la navigation prend toute la largeur. */
  .sig-since { display: none; }
  body { padding-top: 112px; }    /* dégagement de la barre fixe (104 px) + le même jeu qu'en grand écran */

  /* ────── Héro ────── */
  .hero { padding: 24px 0 30px; }
  .hero-body { grid-template-columns: 1fr; row-gap: 26px; }
  .hero-name { font-size: 40px; letter-spacing: -0.03em; }
  .hero-intro { margin-top: 20px; font-size: 16px; }
  .hero-roles { text-align: left; }
  .hero-roles .hero-monogram { margin: 0 0 10px 0; }

  /* ────── Titres de section ────── */
  .atlas-head { grid-template-columns: 1fr; column-gap: 0; row-gap: 10px; margin-bottom: 24px; }
  .atlas-title { font-size: 54px; }
  .atlas-title-2 { font-size: 34px; }
  .atlas-glose { font-size: 16px; }

  /* ────── Atlas interactif : masqué ──────
     Le tableau et son panneau reposent sur le survol et sur 1 030 px de
     large : ni l'un ni l'autre n'existe au doigt. Ils cèdent la place aux
     5 vues figées ci-dessous. Le sélecteur de vues n'a plus d'objet
     puisque les 5 vues sont montrées ensemble. */
  .atlas-grid, .view-selector { display: none; }

  /* ────── Atlas figé — les 5 vues (peuplé par main.js) ──────
     --map et --pt-scale sont redéfinis ICI, sur ce conteneur seul, et
     JAMAIS sur :root : main.js lit --pt-scale au chargement pour calculer
     l'anti-chevauchement, il doit continuer à lire la valeur de référence.
     Le facteur 300/680 rend la réduction exactement homothétique — une
     forme occupe la même fraction du tableau qu'en grand écran — et les
     libellés d'axes, eux, gardent leur taille de lecture. */
  .atlas-static {
    --map: 300px;
    --pt-scale: calc(1.10 * 300 / 680);
    padding-left: 24px;      /* dégagement de l'axe Y, posé à -22px du tableau */
    pointer-events: none;    /* figé : rien n'est cliquable */
  }
  .as-view { margin: 0 0 30px; }

  /* Les étiquettes 1D n'apparaissent qu'en vue V2. Ailleurs elles restent
     invisibles (opacity:0) mais gardent leur position d'origine, calibrée
     pour un tableau de 680 px (left: 746px) : dans une copie de 300 px elles
     débordaient de l'écran. On les retire de la mise en page. */
  .atlas-static .map-wrap:not([data-view="v2"]) .axis-1d { display: none; }
  .as-cap {
    margin-bottom: 12px;
    font-family: var(--mono);
    font-size: 10px;
    font-weight: 500;
    letter-spacing: 0.12em;
    text-transform: uppercase;
    color: var(--ink-mute);
  }

  /* Vue V2 : en grand écran sa mise en page vient du parent
     .atlas-grid[data-view="v2"], que la copie n'a plus — on la reporte ici.
     V2 est une ligne 1D : seule l'abscisse porte du sens, l'ordonnée ne sert
     qu'à désempiler les marqueurs. Le bandeau garde donc la HAUTEUR du grand
     écran (300 px = var(--map)) alors que sa largeur est réduite : les piles
     retrouvent exactement l'air qu'elles ont sur grand écran, et les libellés
     verticaux (≈150 px, taille de lecture conservée) tiennent largement. */
  .atlas-static .map-wrap[data-view="v2"] {
    width: var(--map);
    height: calc(var(--map-top) + var(--map) + var(--map-foot));
    padding-left: 0;
  }
  .atlas-static .map-wrap[data-view="v2"] .map {
    top: var(--map-top); left: 0;
    width: var(--map);
    height: var(--map);
    background: transparent;
    border: 0;
  }
  .atlas-static .map-wrap[data-view="v2"] .axis-1d {
    top: calc(var(--map-top) + var(--map) / 2);
    transform: translateY(-50%);
  }
  .atlas-static .map-wrap[data-view="v2"] .axis-1d-l { left: calc(var(--v2-inset) * 1% - 20px); }
  .atlas-static .map-wrap[data-view="v2"] .axis-1d-r { left: calc(100% - var(--v2-inset) * 1% + 10px); }

  /* ────── Légende ────── */
  .atlas-legend { width: auto; gap: 20px; }
  /* Les bascules « Grille » et « N° » n'agissent que sur le tableau
     interactif, masqué ici : elles n'auraient aucun effet visible. */
  .lg-toggles { display: none; }

  /* ────── Index — il reste l'accès réel aux œuvres, donc cliquable ────── */
  .index-head { flex-wrap: wrap; gap: 14px; margin-bottom: 16px; }
  .index-head h3 { font-size: 30px; }
  .index-head-row { display: none; }   /* en-têtes de colonnes : la ligne compacte se lit seule */
  .index-row {
    grid-template-columns: 52px 1fr auto;
    column-gap: 10px;
    row-gap: 3px;
    padding: 12px 0;
  }
  .index-row .col-num    { grid-column: 1; grid-row: 1; }
  .index-row .col-title  { grid-column: 2; grid-row: 1; }
  .index-row .col-type   { grid-column: 2; grid-row: 2; }
  .index-row .col-medium { grid-column: 2; grid-row: 3; }
  .index-row .col-serie  { grid-column: 2; grid-row: 4; }
  .index-row .col-link {
    grid-column: 3; grid-row: 1 / span 4;
    display: flex; align-items: center;
    min-height: 44px;                  /* cible tactile confortable */
    padding-left: 12px;
    text-align: right;
  }

  /* ────── Timbres ────── */
  .stamp-grid { grid-template-columns: repeat(2, 1fr); gap: 24px 14px; }

  /* ────── Colophon (démarche · biographie · contact) ────── */
  .colo-grid { grid-template-columns: 1fr; gap: 30px; }
  .colo-quote { font-size: 22px; }

  /* ────── Footer ────── */
  .ft-row-1 { grid-template-columns: 1fr; gap: 10px; }
  .ft-c, .ft-r { text-align: left; }
  .ft-row-2 .ft-dim { margin-left: 0; }
}

/* ═══════════════════════════════════════════════════════════════════════
   REPLI MOBILE DES SOUS-PAGES — LOT 15 (11/09/2026)

   Les sept pages en `.subpage` (404, biographie, contact, démarche,
   trajectoire, mentions légales, démarche B) passent en viewport
   device-width. Rien ne change à partir de 1240 px : ces règles ne vivent
   que sous leur media query. Arbitrages du propriétaire du 11/09/2026 :
   titre à 40 px (la taille du nom sur l'accueil mobile), emblème réduit
   dans la même proportion (règle locale de chaque page), et entre 901 et
   1239 px le bloc d'informations passe SOUS le titre. Les réglages propres
   à une page (emblème, curseur S/M/L, facettes) vivent dans son <style>.
   ═══════════════════════════════════════════════════════════════════════ */

/* Sous 1280 px, la `.subpage` de 1240 px fixe sortait de l'écran : centrée
   dans `.page`, son bord droit tombe à V/2 + 640, qui dépasse V dès que
   V < 1280. Elle prend alors la largeur de son conteneur. À partir de 1280 px,
   rien ne change. */
@media (max-width: 1279px) {
  .subpage { width: auto; }
}

/* Tablette et petit écran : le titre (96 px + emblème) et le bloc de droite
   ne tiennent plus côte à côte — le bloc passe dessous. */
@media (max-width: 1239px) {
  .page-head { grid-template-columns: 1fr; row-gap: 26px; }
}

@media (max-width: 900px) {
  /* La marge latérale de 16 px de `.page` suffit, comme sur l'accueil. */
  .subpage { padding-left: 0; padding-right: 0; }
  .page-title { font-size: 40px; }
  /* Texte puis colonne d'encadrés, l'une sous l'autre. */
  .split { grid-template-columns: 1fr; gap: 56px; }
  .pull-quote { font-size: 22px; }              /* valeur de .colo-quote mobile */
  .toggle-row { gap: 18px; }                    /* valeur de .menu-nav mobile */
}

/* ═════════════════════════════════════════════════════════════════════
   SYSTÈME CANVAS — grille mère et objets typographiques
   ═════════════════════════════════════════════════════════════════════

   Source : _design-source/canvas-lot1-grille-3canvas.html (référence web)
            _design-source/canvas-lot5-export-a4-v2.html   (référence A4)
   Relevé des 18 canvas et de leurs empans : GABARITS.md §5.

   Ce bloc porte UNIQUEMENT ce qui est commun aux 18 canvas : la grille et
   les objets typographiques. Les EMPANS (quel élément occupe quelles
   colonnes, quelles lignes) sont propres à chaque canvas et vivent avec la
   fiche qui l'emploie — la colonne « canvas » de data/oeuvres.js dit lequel.

   ⚠️ Le gabarit FILM est un système DISTINCT : il a ses propres sections
   (.cv) et ses propres objets (.w-*), plus riches. Ne pas confondre les
   deux vocabulaires ; voir GABARITS.md §2.

   TRANSPOSITION SUR LA PALETTE DU SITE. Les gabarits ont été validés sur un
   papier chaud (#F6F4EF) que CLAUDE.md §4-2 remplace par #fcfcfb. Les
   graisses, corps, interlignes et interlettrages sont repris à l'identique ;
   seules les couleurs changent de nom :
       --paper   → --paper (le fond du site)      --grey   → --ink-mute
       --hair    → --rule                         --grey-2 → --ink-faint
       --hair-2  → --rule-soft                    --img    → --paper-3
   Les valeurs littérales de la source (#34322e du texte, #4a4843 de
   l'accent de cartel) passent sur --ink-2 : une couleur en dur resterait
   sombre sur fond de nuit, alors que le site a deux thèmes.
   ───────────────────────────────────────────────────────────────────── */

/* ────── Le canvas : la marge, autour de la grille ──────
   Nom « .canvas-page » et non « .canvas » : ce dernier désigne déjà, dans
   _design-source/canvas-lot1, l'enveloppe des planches de démonstration.
   CLAUDE.md §4-6 : « les marges de page vivent DANS le canvas, autour de la
   grille ». C'est ce conteneur qui les porte — jamais @page, dont la marge
   serait celle de l'imprimante et rognerait le fond perdu (§13bis).
   ⚠️ LA MARGE N'EST PAS DÉCORATIVE : elle fixe la largeur de la zone de
   composition, donc TOUS les retours à la ligne. La source la compose en deux
   temps — 40 px de gouttière de page (.wrap) + 56 px de marge de feuille
   (.sheet) = 96 px de chaque côté. Dans les 1180 px de --measure, il reste
   988 px de composition. Une marge de 64 px avait élargi la zone à 1052 px et
   suffisait à faire tenir sur une ligne un titre qui, dans la référence, en
   occupe deux (erreur relevée le 22/07/2026). */
.canvas-page {
  max-width: var(--measure);
  margin: 0 auto;
  padding: 40px clamp(20px, 7.5vw, 96px);
}

/* ⚠️ Le conteneur .page est calé à 1240 px FIXES : il a été écrit pour
   l'accueil, qui n'est pas responsive (viewport 1280) et que le repli mobile
   ne relâche qu'en dessous de 900 px. Entre 901 et 1239 px, toute page qui
   l'emploie déborde donc horizontalement — c'est vrai aussi de biographie et
   de démarche aujourd'hui (à traiter au Lot 6).
   Or les gabarits, eux, prévoient un palier TABLETTE (768–1023 px) où la
   grille se resserre : sans cette ligne, ce palier ne serait jamais visible.
   La règle ne vise donc QUE les pages qui portent un canvas — les fiches —
   et laisse l'accueil rigoureusement intact. */
.page:has(.canvas-page) { width: auto; max-width: 1240px; }

/* ────── La grille mère ──────
   12 colonnes numérotées de 1 à 13 en lignes de grille : « grid-column:2/10 »
   couvre 8 colonnes. Les rangées valent une ligne de base, si bien qu'un
   empan « grid-row:3/9 » se lit directement en multiples de 26 px.
   Le nom « .grid » est celui des deux fichiers de référence : on le conserve
   plutôt que d'introduire un second vocabulaire (GABARITS.md §3). */
/* ─────────────────────────────────────────────────────────────────────────
   .c-planche — LA COLONNE D'IMAGES EN GRILLE IMBRIQUÉE   (30/08/2026, 7I-j)
   ─────────────────────────────────────────────────────────────────────────
   Cadrée par le propriétaire (CLAUDE.md §5.6), à une condition qu'elle tient
   PAR CONSTRUCTION : « la grille 12 colonnes doit rester juste et prioritaire ».

   POURQUOI. Sur une grille unique, la colonne de texte et la colonne d'images
   partagent les mêmes pistes de lignes. Trois exigences s'y disputaient donc le
   même réglage, et deux seulement pouvaient être tenues à la fois :
     · la gouttière entre rangées de vues        = 1 ligne de base (26 px) ;
     · la justification du titre sur la 1re vue  = 4,5 px ;
     · la norme des espaces verticaux            = 37,2 / 54,5 / 73,5 px.
   Un empan de vue en « floor » étire la piste du titre — qui y est calé en bas —
   et la vue passe au-dessus de son titre ; un empan en « ceil » laisse du vide
   mort sous la vue, et la gouttière grossit d'autant.

   LA SORTIE. On sort la colonne d'images de la grille de page : ses rangées sont
   espacées par un row-gap FIXE, que rien ne peut étirer. C'est exactement ce que
   fait .s-docs .planche du gabarit FILM, dont les neuf fiches rendent leur écart
   uniforme sans aucun calcul d'empan.

   ⚠️ grid-template-columns: subgrid — LA CONDITION DU PROPRIÉTAIRE.
   Le conteneur n'invente AUCUNE colonne : il hérite littéralement de celles de
   la grille mère. Une vue en « 8/12 » de la page reste en 8/12 à l'écran, au
   pixel. Vérifié sur C05 (2×5), C15 (6×6), C10 et C11 : les bords gauche et
   droit de chaque vue sont inchangés, au pixel près. La grille 12 colonnes reste
   donc juste ET prioritaire, et la projection A4 la suit puisqu'elle projette
   les mêmes empans (GABARITS.md §3).

   ⚠️ align-content: start — les rangées se calent en haut, jamais réparties.
   ⚠️ L'empan de LIGNES du conteneur vaut ceil(hauteur / 26) : lui seul se
      déclare, les vues n'ont plus de grid-row. */
.c-planche {
  display: grid;
  grid-template-columns: subgrid;
  column-gap: var(--gutter);
  row-gap: var(--baseline);
  align-content: start;
}

.grid {
  position: relative;
  display: grid;
  grid-template-columns: repeat(12, 1fr);
  column-gap: var(--gutter);

  /* ⚠️ HAUTEUR LIBRE, COLONNES FIXES (décision du propriétaire, 23/07/2026).
     Les 12 colonnes sont fixes et identiques : c'est l'arrangement HORIZONTAL
     qui a été validé, et il ne bouge jamais. La VERTICALE, elle, grandit ou se
     réduit selon le contenu — « il suffit d'ajouter des lignes ». Une rangée
     vaut donc AU MOINS une ligne de base (26 px, la trame de référence) et
     s'étire au besoin pour contenir un cartel long ou un timbre plus haut que
     son empan. minmax(--baseline, auto) : le minimum garde l'alignement de
     référence quand le contenu tient dans son empan (cas de la fiche 006) ; le
     maximum « auto » laisse la rangée grandir sinon (cas du cartel long de 001,
     qui dépassait son empan fixe et chevauchait la section suivante). */
  grid-auto-rows: minmax(var(--baseline), auto);

  /* ⚠️ MÉTRIQUE DE BASE HÉRITÉE — 16 px × 1.625 = 26 px, la ligne de base.
     C'est la valeur du <body> des gabarits ; celle du site est 14 px / 1.45.
     Tout objet qui ne déclare pas son propre interligne hérite d'ici : sans
     cette ligne, la source d'une citation (.c-quote .src) tombait à 14,5 px
     au lieu de 16,25 et le bloc perdait un dixième de ligne de base. */
  font-size: 16px;
  line-height: 1.625;
}

/* ⚠️ RÉINITIALISATION DES MARGES, indispensable et volontairement locale.
   Les gabarits ont été composés sous un « *{margin:0;padding:0} » global que
   la feuille du site n'a pas — elle ne pose qu'un box-sizing. Sans cela, un
   <h3 class="c-titre"> conserve la marge par défaut du navigateur (1em, soit
   26 px à ce corps) : combinée à « align-self:end », elle décale le titre
   d'exactement UNE LIGNE DE BASE, et l'écart se propage à tout le canvas.
   On neutralise ici tout le CONTENU de la grille — poser la règle globalement
   bouleverserait les 3 200 lignes de mise en page qui précèdent.

   La descendance compte autant que les enfants directs : le <p class="src">
   d'une citation gardait sa marge basse par défaut et allongeait le bloc d'un
   dixième de ligne de base. Les règles d'objets qui suivent, plus spécifiques,
   reposent leurs propres marges (.c-texte p+p, .c-quote .src). */
.grid, .grid * { margin: 0; }

/* ────── Cartel : titre ──────
   Invariant du système : le cartel ne porte JAMAIS le nom de l'artiste.
   Spectral italique — les gabarits l'emportent ici (GABARITS.md §4). */
.c-titre {
  font-family: var(--serif);
  font-weight: 500;
  font-style: italic;
  font-size: 26px;
  line-height: 1.2;
  letter-spacing: -0.005em;
  align-self: end;
}
.c-titre .annee { font-style: normal; font-weight: 300; color: var(--ink-mute); }

/* ────── Cartel : données techniques ──────
   Ubuntu Sans Mono (CLAUDE.md §8bis-1 ; les gabarits disaient Ubuntu Mono).
   Le souffle reste APRÈS le filet ; les lignes, elles, se serrent en paquet
   autonome — d'où l'interligne réduit sous un padding-top généreux. */
.c-data {
  font-family: var(--mono);
  font-weight: 400;
  font-size: 12.5px;
  line-height: 1.6;
  color: var(--ink-mute);
  border-top: 1px solid var(--rule);
  padding-top: 14px;
}
.c-data .accent {
  color: var(--ink-2);
  font-weight: 700;
  display: inline-block;
  margin-bottom: 3px;      /* 1ʳᵉ ligne du cartel, en accent */
}
/* Lien dans le cartel (ex. « Publiée » → PDF des actes). Même idiome que
   .long-prose a : encre + soulignement au filet, thème-aware, sans
   text-decoration bleu. Focus clavier visible (accessibilité, Lot 11). */
.c-data a {
  color: var(--ink-2);
  text-decoration: none;
  border-bottom: 1px solid var(--rule);
  padding-bottom: 1px;
  transition: border-color 160ms ease;
}
.c-data a:hover,
.c-data a:focus-visible { border-color: var(--ink); }

/* Les listes du CV : un RETRAIT SUSPENDU (11bis-d, 10/09/2026 — arbitrage du
   propriétaire, sur comparatif : 8 signes). La première ligne d'une entrée
   reste sur le bord de la colonne, ses suites passent 8 signes plus loin :
   une ligne qui revient à la ligne ne se lit plus comme une entrée de plus.
   Ubuntu Sans Mono étant à chasse fixe, `ch` vaut exactement un signe, et
   suit le corps du cartel à l'écran comme sur la feuille A4.
   ⚠️ Bornée aux listes du CV (`data-cv-section`) — aucun autre cartel du
   site n'est touché. Le retrait vit DANS le bloc : ses bords, donc la
   grille, ne bougent pas. Ici et non dans la page, parce que le portfolio
   prélève la grille du CV sans son <style> local. */
.c-data[data-cv-section] > div { padding-left: 8ch; text-indent: -8ch; }

/* ────── Corps de texte long ──────
   Ubuntu Light 16 px calé sur la ligne de base : l'interligne EST le pas de
   la grille, donc le texte reste solidaire des rangées. */
.c-texte {
  font-family: var(--sans);
  font-weight: 300;
  font-size: 16px;
  line-height: var(--baseline);
  color: var(--ink-2);
  text-wrap: pretty;
}
.c-texte p + p { margin-top: var(--baseline); }
/* ─── Bouton en FIN de cartel long ───
   Point k du cahier des charges 7I (consigne du propriétaire, 30/08/2026) :
   « pour toute la série panoramique + portrait (escalade 2013) il faut déplacer
   le bouton "le dispositif panoramique" du corpus voisin vers la fin du cartel
   long ». Sept fiches le portent désormais à la fin de CHACUN de leurs deux
   cartels (fr et en), le bloc de langue étant l'unité qui s'affiche ou se cache.
   La marge doit être RÉÉTABLIE : « .grid, .grid * { margin: 0 } » les remet
   toutes à zéro, et le bouton viendrait coller au dernier paragraphe. Une ligne
   de base — la même respiration qu'entre deux paragraphes, le bouton étant
   présenté comme la fin du texte et non comme un bloc à part. C'est le pendant
   canvas de « .cv .cta { margin-top: 22px } » du gabarit film. */
.c-texte .cta { margin-top: var(--baseline); }
/* Emphase de l'auteur dans un cartel long. Quatre entrées en portent une
   (016, 021, 023, 047) ; le site compose partout son gras en 500 sur l'encre
   pleine, jamais au 700 du navigateur. */
.c-texte strong { font-weight: 500; color: var(--ink); }
.c-texte .intro {
  font-family: var(--serif);
  font-style: italic;
  font-weight: 500;
  font-size: 17px;
}

/* ────── Page-titre / intercalaire (C12) ──────
   Spectral ExtraLight en grand display, blanc dominant. */
.c-bigtitle {
  font-family: var(--serif);
  font-weight: 200;
  font-size: 76px;
  line-height: 1;
  letter-spacing: -0.02em;
  color: var(--ink);
  align-self: center;
  text-wrap: balance;
  margin: 0;
}
.c-bigtitle em { font-style: italic; font-weight: 300; }

.c-kicker {
  align-self: start;
  font-family: var(--sans);
  font-weight: 700;
  font-size: 12px;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--ink);
  line-height: var(--baseline);
}
.c-kicker .reg {
  font-family: var(--mono);
  font-weight: 400;
  letter-spacing: 0.05em;
  text-transform: none;
  color: var(--ink-mute);
}

/* ────── Citation en exergue (C13 · C14) ──────
   Spectral Light italique. Les guillemets français sont posés par la
   propriété « quotes », espaces insécables comprises (CLAUDE.md §10) :
   ils ne sont donc jamais saisis dans le HTML. */
.c-quote { align-self: center; quotes: "«\00a0" "\00a0»"; }
.c-quote .qt {
  font-family: var(--serif);
  font-weight: 300;
  font-style: italic;
  font-size: 30px;
  line-height: 1.22;
  letter-spacing: -0.005em;
  color: var(--ink);
  text-wrap: pretty;
  margin: 0;
}
.c-quote .qt::before { content: open-quote; }
.c-quote .qt::after  { content: close-quote; }
.c-quote .qt strong  { font-weight: 500; }
.c-quote .src {
  font-family: var(--mono);
  font-size: 10px;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--ink-mute);
  margin-top: 12px;
}
/* C14 — trois citations : corps réduit, chacune calée en haut de son empan. */
.c-quote--trio { align-self: start; }
.c-quote--trio .qt  { font-size: 21px; line-height: 1.26; }
.c-quote--trio .src { font-size: 9px; margin-top: 8px; }

/* ────── Image « timbre » ──────
   ⚠️ DEUX DÉROGATIONS AUX GABARITS, décidées par le propriétaire :

   1. AUCUN CADRE (CLAUDE.md §4-3). Les gabarits montaient le timbre comme
      un timbre-poste : filet d'encre 1 px, passe-partout de 4 px et un
      « .mat » en retrait. Tout cela est retiré — l'image se pose directement
      sur la grille.
   2. RATIO NATIF (§4-4). Le format d'origine de chaque image est conservé ;
      aucun recadrage uniforme, aucune déformation.

   Ce qui NE change PAS, en revanche, c'est le principe du timbre : l'image
   est délibérément minuscule. Elle atteste que l'œuvre existe, elle ne la
   donne pas à voir ; pour la voir, il faut se déplacer dans l'espace
   d'exposition. Ne jamais agrandir un timbre pour « remplir » l'écran
   (GABARITS.md §4).

   ⚠️ LES « 140 px » NE SONT PAS UNE LARGEUR À ÉCRIRE. C'est le RÉSULTAT d'un
   empan de 2 colonnes (2 × 67 + 24 = 158 dans la zone de 1180, 140 dans celle
   de la source). La largeur du timbre vient donc TOUJOURS de son empan de
   colonnes, jamais d'un max-width : c'est ce qui l'aligne sur la grille.
   L'avoir bridé à 140 px avait produit des vignettes de tailles arbitraires,
   désalignées — erreur corrigée le 22/07/2026.

   ARBITRAGE DU PROPRIÉTAIRE (22/07/2026) — « largeur de la grille, hauteur
   libre ». Le timbre prend la largeur de son empan ; sa hauteur suit le ratio
   natif du fichier. Bords gauche, droit et SUPÉRIEUR sur la grille ; seul le
   bord inférieur flotte. Aucun recadrage, aucune déformation (§4-4). L'empan
   de lignes déclaré par le canvas devient alors une hauteur indicative. */
.c-image {
  position: relative;
  display: block;
  align-self: start;      /* le timbre se cale en haut de son empan */
  margin: 0;
}
.c-image img {
  display: block;
  width: 100%;            /* la largeur vient de l'empan, pas d'un max-width */
  height: auto;           /* ratio natif préservé */
}

/* Aplat de remplacement, tant qu'une image n'a pas été fournie.
   Faute de ratio connu, il occupe EXACTEMENT le rectangle que le canvas avait
   prévu — c'est le seul cas où le timbre retrouve les quatre bords de la
   grille, et cela vaut mieux qu'un carré arbitraire posé n'importe où. */
.c-image:has(.ms) { align-self: stretch; }
.c-image .ms {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 100%;
  background: var(--paper-3);
  font-family: var(--mono);
  font-size: 9px;
  letter-spacing: 0.04em;
  line-height: 1.45;
  color: var(--ink-mute);
  text-align: center;
  padding: 6px;
}

/* ────── Légende mono, sous le timbre ──────
   Les images des FICHES n'ont pas de légende : le cartel en tient lieu
   (GABARITS.md §4). Cet objet sert les canvas qui, eux, en prévoient une —
   une vue d'installation, un plan d'accrochage. */
.c-cap {
  margin-top: 7px;
  font-family: var(--mono);
  font-size: 9.5px;
  line-height: 1.55;
  letter-spacing: 0.02em;
  color: var(--ink-mute);
}
.c-cap em { font-style: italic; color: var(--ink-2); }

/* ═══════════ TABLETTE (768–1023 px) — la grille se resserre ═══════════
   Douze colonnes maintenues, gouttière réduite ; les couples texte-gauche /
   image-droite tiennent tant que la colonne de texte garde ≥ 45 signes
   (cahier des charges des canvas, §8). */
@media (min-width: 768px) and (max-width: 1023px) {
  .grid { column-gap: 18px; padding-bottom: 60px; } /* air = espace inter-sections tablette */
}

/* ═══════════════ MOBILE (< 768 px) — une seule colonne ═══════════════
   Empilement dans l'ordre du source, que les fiches écrivent en ordre
   mobile : titre → image(s) → texte → cartel. Les empans de colonnes et de
   rangées sont neutralisés d'un bloc, sans quoi chaque canvas devrait
   redéclarer les siens.

   INVARIANT : le timbre ne grandit pas pour remplir l'écran. Il est
   simplement borné à 60 % de la colonne, aligné à gauche (§8). */
@media (max-width: 767px) {
  .grid {
    grid-template-columns: 1fr;
    grid-auto-rows: auto;
    row-gap: var(--baseline);
    padding-bottom: 44px; /* air = espace inter-sections mobile */
  }
  .grid > * { grid-column: 1 !important; grid-row: auto !important; }
  /* Ici, et ici SEULEMENT, une largeur maximale : la colonne unique ferait
     sinon grandir le timbre pour remplir l'écran.
     Le cahier des charges (§8) dit « largeur max ≈ 60 % de la colonne » — mais
     sur un écran de 375 px cela donne 191 px, soit PLUS GRAND qu'au bureau
     (≈ 145 px sur 2 colonnes). Or l'invariant est de ne JAMAIS agrandir un
     timbre. Les deux bornes s'appliquent donc ensemble, et c'est ici — et
     nulle part ailleurs — que les 140 px de GABARITS.md servent de plafond. */
  .c-image { max-width: min(60%, 140px); align-self: start; }
  .c-image:has(.ms) .ms { aspect-ratio: 3 / 2; height: auto; }
  .c-bigtitle { font-size: clamp(40px, 11vw, 76px); }
  .c-quote .qt { font-size: 22px; }
}

/* ═════════════════════════════════════════════════════════════════════
   GABARIT FILM — le 19ᵉ gabarit, sections .cv et objets .w-*
   ═════════════════════════════════════════════════════════════════════

   Source : _design-source/oeuvre-contrat-social-web.html  (référence web)
            _design-source/oeuvre-contrat-social-v3.html   (référence A4)
   Relevé : GABARITS.md §2. Les 9 entrées concernées sont celles dont la
   colonne « Canvas » de data/oeuvres.js vaut FILM : 044, 045, 049, 051,
   057, 060, 063, 068, 069.

   ⚠️ SYSTÈME DISTINCT DU SYSTÈME CANVAS QUI PRÉCÈDE. Les films ont plus de
   matière (synopsis, dispositif, transcriptions, planche de photogrammes,
   générique, diffusion) et leur gabarit est plus riche : il compose en
   SECTIONS successives (.cv), chacune reprenant l'esprit d'un canvas, là
   où une fiche d'œuvre tient sur UNE grille (.grid) et UN canvas. Les deux
   vocabulaires ne se mêlent jamais : pas de .c-* dans une section .cv, pas
   de .w-* dans une .grid.

   Différence de métrique à ne pas confondre : la grille canvas cale tout
   sur la ligne de base de 26 px (rangées fixes) ; les sections .cv, elles,
   ont des rangées AUTO et un row-gap de 10 px — elles suivent le flux du
   texte. C'est le gabarit validé qui en décide ainsi.

   Transposition sur la palette du site, comme pour le bloc canvas :
       --grey → --ink-mute        --hair → --rule        --img → --paper-3
       --grey-2 → --ink-faint     --hair-2 → --rule-soft
   Les littéraux #34322e (texte) et #4a4843 (accents de cartel) passent sur
   --ink-2 : en dur, ils resteraient sombres sur fond de nuit.
   ───────────────────────────────────────────────────────────────────── */

/* ────── La section : une grille de 12 colonnes, un filet en tête ──────
   Le SOURCE d'une section est écrit en ordre MOBILE (titre → image → texte
   → cartel) ; le bureau replace ensuite chaque bloc sur la grille. C'est ce
   qui permet à la version < 768 px de n'être qu'un simple passage en flux. */
.cv {
  display: grid;
  grid-template-columns: repeat(12, 1fr);
  column-gap: var(--gutter);
  row-gap: 10px;
  padding: 72px 0;
  border-top: 1px solid var(--rule);

  /* ⚠️ MÉTRIQUE DE BASE HÉRITÉE — 16 px / 1.6, valeur du <body> du gabarit
     film. Celle du site est 14 px / 1.45, et celle des canvas 16 px / 1.625 :
     les trois diffèrent. Sans cette ligne, tout objet qui ne déclare pas son
     propre interligne composerait au pas du site. */
  font-size: 16px;
  line-height: 1.6;
}
.cv:first-of-type { border-top: 0; }

/* ⚠️ GABARIT FILM — AUCUN FILET ENTRE LE HERO ET « 01 — Le film ».
   Point f du cahier des charges 7I (consigne du propriétaire, 30/08/2026) :
   « supprimer le second filet qui sépare le cartel technique de 01 — le film ».
   Le hero se termine désormais sur le seul filet de son cartel (.w-data).

   ⚠️ Il y avait DEUX traits à cet endroit, exactement superposés (bord bas du
   hero = bord haut de la section), ce qui les faisait lire comme un seul :
     1. un border-bottom HÉRITÉ de « .hero » (l. 372) — la règle du hero de
        l'ACCUEIL, que le gabarit film attrape parce qu'il réemploie le même
        nom de classe. Elle n'a jamais été écrite pour lui ;
     2. le border-top de section de .s-synopsis, donné par .cv.
   Les retirer tous les deux, sans quoi la ligne subsiste. C'est le même
   raisonnement qu'« un seul filet par respiration » (22/07/2026).
   Ne vise QUE le gabarit film : .cv.hero n'existe nulle part ailleurs, et les
   filets de toutes les autres sections (.s-docs, .s-fiche, .s-atlas…) restent. */
.cv.hero       { border-bottom: 0; }
.cv.hero + .cv { border-top: 0; }

/* ⚠️ FICHE CANVAS — le premier .cv suit la GRILLE, pas un hero.
   Sur une fiche d'œuvre en système canvas, le corps est un .grid (un canvas),
   suivi des sections sœurs communes .cv « Position dans l'Atlas » puis, s'il y
   en a un, « Corpus voisin ». Le premier .cv y est donc « Position dans
   l'Atlas », à qui .cv:first-of-type retire à tort son filet de section : plus
   rien ne le séparerait alors du cartel long qui le précède. On le lui rend —
   c'est le SEUL filet à cet endroit (à la différence du gabarit film, où il
   fallait au contraire RETIRER le filet propre de .w-atlas, qui doublait celui
   de la section — décision du 22/07/2026).
   La règle ne vise QUE les fiches canvas : sur une fiche film, aucun .grid ne
   précède un .cv, donc « .grid + .cv » ne s'y déclenche jamais (068 intact).
   Spécificité (0,3,0) : l'emporte sur .cv:first-of-type (0,2,0). */
.canvas-page .grid + .cv { border-top: 1px solid var(--rule); }

/* ⚠️ AIR SOUS LA GRILLE, avant le filet de la première section sœur.
   En hauteur libre, un cartel long remplit sa zone et vient coller au filet de
   « Position dans l'Atlas ». On ménage donc, sous la grille, EXACTEMENT l'espace
   qui sépare deux sections .cv (72 px au bureau, décliné aux paliers) : chaque
   filet respire alors pareil, en haut comme en bas (demande du propriétaire,
   23/07/2026). Ne concerne que les fiches canvas — .grid n'existe que là. */
.canvas-page .grid { padding-bottom: 72px; }

/* ⚠️ RÉINITIALISATION DES MARGES — même piège que pour la grille canvas.
   Le gabarit a été composé sous un « *{margin:0;padding:0} » global que la
   feuille du site n'a pas : sans cela, un <h1 class="w-worktitle"> garde la
   marge par défaut du navigateur et décroche du haut de sa section.
   Elle est posée AVANT les objets : les règles qui suivent reposent leurs
   propres marges (.w-figcap, .w-subhead, .w-text p+p, .w-quote .src) et,
   à spécificité égale, c'est la dernière déclarée qui gagne. */
.cv, .cv * { margin: 0; }

/* ────── Objets typographiques (échelle web du gabarit, §4.2) ────── */

/* ⚠️ .w-kicker et .w-worksub ne sont plus employés par aucune fiche : le
   propriétaire les a retirés le 22/07/2026 (voir le placement du hero, plus
   bas). Leurs règles typographiques restent — elles décrivent le gabarit
   validé et ne coûtent rien — mais elles sont, en l'état, du code inemployé :
   signalé ici plutôt que supprimé (CLAUDE.md §5.3). */
.w-kicker {
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--ink-mute);
}
.w-kicker b { color: var(--ink); font-weight: 700; }

/* Titre de l'œuvre — Spectral italique (CLAUDE.md §8bis-3). Le clamp est
   celui du gabarit : le titre se réduit avec la fenêtre sans jamais casser.

   Le titre s'écrit EN ENTIER (décision du propriétaire, 22/07/2026), mais
   « (La désinstitutionnalisation) » est un mot de 24 signes : à 76 px il
   mesure à lui seul plus que l'empan de 8 colonnes. Coupé par une césure, il
   mangeait trois lignes et déséquilibrait la page.
   PARADE : le qualificatif entre parenthèses passe à la ligne et se compose
   un cran plus bas, ce qui le fait tenir d'un seul tenant sous le titre. La
   césure reste déclarée en dernier recours — sur un téléphone, la colonne
   unique peut encore être plus étroite que lui. */
.w-worktitle {
  font-family: var(--serif);
  font-weight: 300;
  font-style: italic;
  font-size: clamp(40px, 6.6vw, 76px);
  line-height: 1;
  letter-spacing: -0.02em;
  color: var(--ink);
  -webkit-hyphens: auto;
  hyphens: auto;
}
/* Le qualificatif d'un titre : « (La désinstitutionnalisation) », « (Portrait) »,
   ou le sous-titre d'un essai (« Contre le romantisme institutionnel… », fiche
   070). Proportionnel au titre — en em — donc il suit ses paliers de corps. Sert
   deux contextes : le titre film (.w-worktitle) ET le titre canvas (.c-titre),
   où il passe sous le titre + année, un cran plus bas et sur sa propre ligne. */
.w-worktitle .qualif,
.c-titre .qualif { display: block; font-size: 0.72em; }
.w-worksub {
  font-family: var(--serif);
  font-weight: 300;
  font-style: italic;
  font-size: clamp(17px, 2vw, 21px);
  line-height: 1.34;
  color: var(--ink-2);
  max-width: 30ch;
}

/* ────── En-tête de section : numéro mono + titre Spectral ────── */
.w-secnum {
  font-family: var(--mono);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.1em;
  color: var(--ink);
}
.w-sectitle {
  font-family: var(--serif);
  font-weight: 500;
  font-style: italic;
  font-size: clamp(24px, 3vw, 30px);
  line-height: 1.12;
  letter-spacing: -0.01em;
  color: var(--ink);
}
.w-sectitle .annee { font-style: normal; font-weight: 300; color: var(--ink-mute); }
.w-head { display: flex; flex-direction: column; gap: 10px; }
.w-head .w-sectitle { margin-top: 2px; }

/* ────── Corps de texte ────── */
.w-text {
  font-family: var(--sans);
  font-weight: 300;
  font-size: 16.5px;
  line-height: 1.62;
  color: var(--ink-2);
  text-wrap: pretty;
  max-width: 62ch;        /* la mesure de lecture, en plus de l'empan */
}
.w-text p + p { margin-top: 1.05em; }
/* Nom de personnage dans une transcription. On réemploie l'objet .w-subhead
   — mono, capitales espacées — plutôt que d'en créer un de plus ; il lui
   manque seulement l'air au-dessus, que le flux du texte ne lui donne pas. */
.w-text .w-subhead { margin-top: 1.7em; }
.w-text .lead {
  font-family: var(--serif);
  font-style: italic;
  font-weight: 500;
  font-size: 18px;
}

/* ────── Cartel technique ──────
   Ubuntu Sans Mono (CLAUDE.md §8bis-1 ; le gabarit disait Ubuntu Mono). */
.w-data {
  font-family: var(--mono);
  font-weight: 400;
  font-size: 12.5px;
  line-height: 1.72;
  color: var(--ink-mute);
  border-top: 1px solid var(--rule);
  padding-top: 14px;
}
.w-data .accent {
  color: var(--ink-2);
  font-weight: 700;
  display: inline-block;
  margin-bottom: 4px;      /* 1ʳᵉ ligne du cartel, en accent */
}
/* Sous une PLANCHE, le cartel n'a pas de filet (décision du propriétaire,
   22/07/2026) : ailleurs le trait sépare deux blocs de nature différente —
   dans le hero, c'est même lui qui souligne le titre —, mais sous des timbres
   il vient doubler le blanc qui les suit déjà, avant celui de la section
   suivante. Trois traits pour une seule respiration.

   ⚠️ CODE INEMPLOYÉ DEPUIS LE 30/08/2026 — cette règle et ses trois placements
   (plus bas, dans les trois media-queries) n'ont plus d'objet : le point j du
   cahier des charges 7I a fait retirer des neuf fiches film le cartel qui
   redisait « Photogrammes » sous la planche, la section le nommant déjà dans
   son « 02 — Photogrammes ». Conservées et signalées plutôt que supprimées
   (CLAUDE.md §5.3), comme .w-kicker et .w-worksub : elles décrivent le
   gabarit validé, et une planche future pourrait reprendre un cartel. */
.s-docs .w-data { border-top: 0; padding-top: 0; }

/* ────── Image « timbre » ──────
   MÊMES DEUX DÉROGATIONS que pour .c-image, et pour les mêmes raisons :
   AUCUN CADRE (CLAUDE.md §4-3 — le gabarit montait l'image en timbre-poste,
   filet 1 px + passe-partout 4 px + un « .mat » en retrait : tout est retiré)
   et RATIO NATIF (§4-4 — le gabarit imposait un aspect-ratio 16/9, qui
   recadrerait). La largeur vient de l'empan de colonnes, jamais d'un
   max-width ; seule la hauteur flotte.

   NON PORTÉ : la légende « ↗ visible en salle » qui apparaissait au survol
   (.salle) — c'était du contenu de démonstration —, et l'agrandissement du
   timbre au clic, écarté par le propriétaire le 22/07/2026 (GABARITS.md §4). */
.w-figure { margin: 0; }
.w-image { position: relative; display: block; }
.w-image img { display: block; width: 100%; height: auto; }

/* Aplat de remplacement, tant qu'une image n'a pas été fournie. Faute de
   ratio connu, il prend celui que le gabarit prévoyait pour l'emplacement
   (16/9, ou 4/3 avec .r43) — c'est le seul cas où une proportion s'écrit. */
.w-image .ms {
  display: flex;
  align-items: center;
  justify-content: center;
  aspect-ratio: 16 / 9;
  background: var(--paper-3);
  font-family: var(--mono);
  font-size: 10px;
  letter-spacing: 0.03em;
  line-height: 1.5;
  color: var(--ink-mute);
  text-align: center;
  padding: 10px;
}
.w-image.r43 .ms { aspect-ratio: 4 / 3; }

.w-figcap {
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: 0.02em;
  line-height: 1.5;
  color: var(--ink-mute);
  margin-top: 10px;
}
.w-figcap b { color: var(--ink-2); font-weight: 700; }

/* ────── Citation en exergue ──────
   Le gabarit film écrit ses guillemets français en contenu généré, espaces
   insécables comprises (CLAUDE.md §10) : ils ne sont jamais saisis dans le
   HTML. (Le système canvas obtient le même résultat par « quotes ».) */
.w-quote { margin: 0; }
.w-quote .qt {
  font-family: var(--serif);
  font-weight: 300;
  font-style: italic;
  font-size: clamp(21px, 2.4vw, 27px);
  line-height: 1.28;
  letter-spacing: -0.005em;
  color: var(--ink);
  text-wrap: pretty;
}
.w-quote .qt::before { content: "«\00a0"; }
.w-quote .qt::after  { content: "\00a0»"; }
.w-quote .qt strong  { font-weight: 500; }
.w-quote .src {
  font-family: var(--mono);
  font-size: 10.5px;
  color: var(--ink-mute);
  margin-top: 12px;
  letter-spacing: 0.05em;
  text-transform: uppercase;
}

/* ────── Fiche : générique, diffusion, corpus voisin ────── */
.w-subhead {
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-mute);
  margin-bottom: 14px;
}
.w-subhead b { color: var(--ink); font-weight: 700; }

.w-defs {
  font-family: var(--mono);
  font-size: 12.5px;
  line-height: 1.55;
  color: var(--ink-mute);
  display: grid;
  grid-template-columns: auto 1fr;
  gap: 6px 18px;
  border-top: 1px solid var(--rule);
  padding-top: 14px;
}
.w-defs dt {
  text-transform: uppercase;
  letter-spacing: 0.08em;
  font-size: 10.5px;
  color: var(--ink-faint);
}
.w-defs dd { margin: 0; color: var(--ink-2); }

/* 4ᵉ de couverture (fiche 072) : la liste de champs se lit comme une FICHE
   d'enquête. Colonne de label FIXE (les valeurs s'alignent verticalement) et
   valeur en pleine largeur — d'où des lignes longues, sans coupe après un mot.
   Scopé à .s-backcover : la fiche du film (.s-fiche .w-defs) garde sa
   disposition. Le placement pleine largeur de la section est réglé dans les
   media-queries (comme .s-atlas .w-atlas). */
.s-backcover .w-defs {
  grid-template-columns: 190px 1fr;
  gap: 10px 24px;
}

.w-fest {
  font-family: var(--mono);
  font-size: 12.5px;
  line-height: 1.5;
  color: var(--ink-mute);
  border-top: 1px solid var(--rule);
  padding-top: 14px;
  list-style: none;
  padding-left: 0;
}
.w-fest li {
  display: grid;
  grid-template-columns: 46px 1fr;
  gap: 12px;
  padding: 7px 0;
  border-bottom: 1px dotted var(--rule);
}
.w-fest li:last-child { border-bottom: 0; }
.w-fest .yr { color: var(--ink); font-weight: 700; }
.w-fest .pl { color: var(--ink-faint); }

.w-corpus {
  font-family: var(--mono);
  font-size: 12px;
  line-height: 1.5;
  color: var(--ink-mute);
  border-top: 1px solid var(--rule);
  padding-top: 14px;
  list-style: none;
  padding-left: 0;
}
.w-corpus li { padding: 7px 0; border-bottom: 1px dotted var(--rule); }
.w-corpus li:last-child { border-bottom: 0; }
.w-corpus .ty {
  display: block;
  font-size: 9.5px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink-faint);
}
.w-corpus .ti { color: var(--ink-2); }

/* ────── Position dans l'Atlas ──────
   Le gabarit dessinait ici sa propre bande de 5 vues, aux coordonnées
   écrites en dur. On ne la porte PAS : le picto du site est engendré par
   assets/js/main.js (PARTIE 3) depuis data/oeuvres.js, avec la fonction de
   placement du grand tableau et les tokens d'atlas verrouillés — règle de
   la source unique (CLAUDE.md §14). Ne reste ici que l'habillage de la
   section ; le picto lui-même est stylé plus haut (.miniatlas).

   ⚠️ PAS DE FILET PROPRE (décision du propriétaire, 22/07/2026). Le gabarit
   en posait un, à l'encre, juste sous celui que la section porte déjà : deux
   traits parallèles à quelques dizaines de pixels, en bas de page, là où les
   sections sont les plus courtes. Un seul suffit — celui des sections, le
   même partout. Le sous-titre reste un .w-subhead, comme « Générique » ou
   « Corpus voisin », qui n'en ont pas davantage. */
.w-atlas { padding-top: 4px; }

/* ────── Corpus voisin ──────
   Section propre, en FIN de fiche (décision du propriétaire, 22/07/2026) : les
   entrées apparentées s'alignent à l'horizontale, comme la planche de
   photogrammes, en boîtes cliquables vers leur fiche.
   Le contenu est ENGENDRÉ par main.js (PARTIE 4) depuis la clé « corpus » de
   data/oeuvres.js : rien n'est écrit en dur ici (CLAUDE.md §14).
   La bordure est celle du bouton du site (.cta) et s'inverse au survol : c'est
   un bouton, pas une image — la règle « aucun cadre » (§4-3) vise les images. */
.corpus-voisin {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: var(--gutter);
  margin-top: 22px;
}
.cv-lien {
  display: block;
  padding: 14px 16px 16px;
  border: 1px solid var(--ink);
  text-decoration: none;
  transition: background-color 160ms ease, color 160ms ease;
}
.cv-lien:hover, .cv-lien:focus-visible { background: var(--ink); color: var(--paper); }
.cv-lien .ty {
  display: block;
  font-family: var(--mono);
  font-size: 9.5px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink-mute);
}
.cv-lien .ti {
  display: block;
  margin-top: 8px;
  font-family: var(--serif);   /* titre d'œuvre — CLAUDE.md §8bis-3 */
  font-style: italic;
  font-size: 17px;
  line-height: 1.25;
  color: var(--ink-2);
}
/* Au survol, les deux lignes suivent la couleur du bouton. */
.cv-lien:hover .ty, .cv-lien:hover .ti,
.cv-lien:focus-visible .ty, .cv-lien:focus-visible .ti { color: inherit; }

/* ⚠️ EFFET DE BORD DE LA RÉINITIALISATION CI-DESSUS, à corriger ici.
   « .cv * { margin: 0 } » écrase aussi les marges des objets du SITE qu'une
   section .cv réemploie — le picto d'atlas (.miniatlas, qui porte 22 px), le
   bloc de chiffres et le bouton. Déclarée plus bas dans la feuille, elle
   l'emporte à spécificité égale : sans ces trois lignes, les trois blocs se
   touchent. On leur rend leur air, et à eux seuls. */
.cv .miniatlas { margin-top: 22px; }
.cv .atlas-ref { margin-top: 18px; }
.cv .cta       { margin-top: 22px; }

/* ═══════════════ PLACEMENTS BUREAU (≥ 1024 px) ═══════════════
   Repris tels quels du gabarit validé. Une section absente d'une fiche
   (faute de matière) ne laisse aucun trou : la grille ne place que ce
   qu'elle reçoit. */
@media (min-width: 1024px) {
  /* HERO — page-signature : titre à gauche, timbre à droite (esprit C02)
     ⚠️ RANGÉES RESSERRÉES (décision du propriétaire, 22/07/2026). Le gabarit
     en comptait quatre : kicker, titre, sous-titre, cartel. Le KICKER (n°
     d'atlas, type, poids, années) et le SOUS-TITRE (cartel court) ont été
     retirés de toutes les fiches — le premier ne porte que des informations
     déjà lisibles ailleurs ou internes à l'atlas, le second fait doublon avec
     le cartel long qui ouvre la page. Il reste trois blocs, sur deux rangées ;
     les laisser aux rangées 2 et 4 aurait creusé deux gouttières vides. */
  .cv.hero { align-items: start; row-gap: 18px; }
  .cv.hero .w-worktitle { grid-column: 1/9;  grid-row: 1; }
  /* ⚠️ LE CARTEL NE PREND PLUS L'EMPAN DU TITRE — point f du cahier des
     charges 7I (consigne du propriétaire, 30/08/2026), qui RENVERSE
     l'arbitrage du 22/07/2026 (« le filet s'arrête où s'arrête le titre »).
     Le filet du cartel « ne doit pas dépasser la taille du texte du cartel
     technique » : à 8 colonnes il mesurait 651 px pour un texte de 252 à
     567 px selon le film. Chaque fiche porte donc la classe de l'empan le
     plus court qui contienne sa ligne la plus longue — mesurée au navigateur
     en width:max-content, DANS LES DEUX LANGUES, l'anglais étant parfois le
     plus long (Perdus en mer : 413 fr / 420 en).
     1/9 reste le repli : une fiche sans classe garde l'ancien empan.

     ⚠️ LES DEUX PALIERS SONT FLUIDES — la colonne mesure 47,2 px à 1024 et
     60,33 px à partir de 1280 (au-delà, la zone de composition est plafonnée).
     L'empan est donc calé sur le point le PLUS LARGE du palier : c'est là,
     et là seulement, que le filet risquerait de dépasser le texte. Plus bas
     dans le palier, le texte revient à la ligne et remplit la largeur — le
     filet ne dépasse alors jamais.

     ⚠️ 057 ERRATA garde ses 8 colonnes : sa première ligne de cartel court sur
     80 signes (« Film (fiction expérimentale) ; version installée à quatre
     projections simultanées ») et mesure 567 px, quand 7 colonnes en font
     566,3. La raccourcir serait une re-lineation du CARTEL, qui relève du
     7I-b — signalé au propriétaire, non décidé ici. */
  .cv.hero .w-data      { grid-column: 1/9;  grid-row: 2; }
  .cv.hero .w-data--c4  { grid-column: 1/5; }   /* 313 px — 044 · 049 · 060 · 069 */
  .cv.hero .w-data--c5  { grid-column: 1/6; }   /* 398 px — 063 · 068 */
  .cv.hero .w-data--c6  { grid-column: 1/7; }   /* 482 px — 045 · 051 */
  .cv.hero .w-data--c8  { grid-column: 1/9; }   /* 651 px — 057 (voir ci-dessus) */
  .cv.hero .w-figure    { grid-column: 9/13; grid-row: 1/3; align-self: start; }

  /* C03 — cartel + texte + timbre */
  .s-synopsis .w-head   { grid-column: 1/7;  grid-row: 1; }
  .s-synopsis .w-text   { grid-column: 1/7;  grid-row: 2; }
  .s-synopsis .w-figure { grid-column: 9/13; grid-row: 1/3; align-self: start; }

  /* C06 — installation : texte à gauche, deux images à droite.
     ⚠️ SIX colonnes et non cinq (décision du propriétaire, 22/07/2026). Quand
     la section n'a pas d'image à droite, une colonne de 398 px allongeait la
     page sans nécessité. À 482 px, on reste sous la mesure de lecture du
     gabarit (62 signes, soit 577 px) : c'est un élargissement, pas un
     débordement. Les sections QUI ONT leurs images gardent leurs empans. */
  .s-dispositif .w-head    { grid-column: 1/7;  grid-row: 1; }
  .s-dispositif .w-text    { grid-column: 1/7;  grid-row: 2; }
  .s-dispositif .w-figure.a{ grid-column: 7/13; grid-row: 1/2; align-self: start; }
  .s-dispositif .w-figure.b{ grid-column: 9/13; grid-row: 2; align-self: start; margin-top: 18px; }

  /* C14 — texte + citations en exergue.
     ⚠️ Sur une TRANSCRIPTION, les exergues ne sont plus employées (décision du
     propriétaire, 22/07/2026) : détacher des répliques d'un dialogue en brouille
     la lecture. Les répliques vivent désormais dans le corps du texte, où elles
     gardent leur ordre et leur enchaînement. Les empans q1 et q2 restent
     déclarés — ils appartiennent au gabarit validé et serviront à une section
     de citations véritables — mais aucune fiche ne les emploie aujourd'hui. */
  .s-transcript .w-head     { grid-column: 1/7;  grid-row: 1; }
  .s-transcript .w-text     { grid-column: 1/7;  grid-row: 2; }
  .s-transcript .w-quote.q1 { grid-column: 8/13; grid-row: 1/2; align-self: start; margin-top: 6px; }
  .s-transcript .w-quote.q2 { grid-column: 8/13; grid-row: 2; align-self: start; }

  /* C07/C05 — planche : quatre timbres sur une ligne */
  .s-docs .w-head  { grid-column: 1/13; grid-row: 1; margin-bottom: 6px; }
  .s-docs .planche { grid-column: 1/13; grid-row: 2;
                     display: grid; grid-template-columns: repeat(4, 1fr); gap: var(--gutter); }
  .s-docs .w-data  { grid-column: 1/8;  grid-row: 3; margin-top: 18px; }  /* inemployé — voir « .s-docs .w-data » plus haut */

  /* Fiche — générique / diffusion / corpus */
  .s-fiche .w-head     { grid-column: 1/13; grid-row: 1; margin-bottom: 8px; }
  .s-fiche .blk-gen    { grid-column: 1/5;  grid-row: 2; }
  .s-fiche .blk-diff   { grid-column: 6/9;  grid-row: 2; }
  .s-fiche .blk-corpus { grid-column: 10/13;grid-row: 2; }
  /* ⚠️ UN GÉNÉRIQUE SANS RIEN À SA DROITE PREND LA PLACE — consigne du
     propriétaire sur 063 Jours Blancs (30/08/2026) : « la fiche générique est
     trop resserrée (et donc haute), les lignes peuvent être plus large avant
     un retour à la ligne ». Sur 4 colonnes (313 px), la colonne de libellés du
     .w-defs en mange une centaine et le générique de 063 s'étirait sur 510 px
     de haut, une valeur revenant à la ligne jusqu'à neuf fois. Le bloc va
     donc jusqu'à la ligne 9, là où finirait la diffusion : 220 px de haut.
     :last-child dit exactement la condition — aucun bloc à droite. HUIT films
     sur neuf sont dans ce cas et y gagnent la même lisibilité ; seul 068, qui
     porte une diffusion, garde ses 4 colonnes (son générique reste le plus
     resserré du corpus : à signaler au propriétaire). */
  .s-fiche .blk-gen:last-child { grid-column: 1/9; }

  /* Atlas — pleine largeur */
  .s-atlas .w-atlas { grid-column: 1/13; }

  /* Corpus voisin — pleine largeur, en dernière section */
  .s-corpus .w-atlas { grid-column: 1/13; }

  /* 4ᵉ de couverture (072) — les sous-sections s'empilent verticalement,
     pleine largeur (sinon elles s'auto-placent en bandes d'une colonne). */
  .s-backcover .w-head,
  .s-backcover .w-subhead,
  .s-backcover .w-defs,
  .s-backcover .w-text { grid-column: 1/13; }
}

/* ═══════════════ TABLETTE (768–1023 px) — resserrement ═══════════════ */
@media (min-width: 768px) and (max-width: 1023px) {
  .cv { column-gap: 18px; padding: 60px 0; }

  .cv.hero .w-worktitle { grid-column: 1/11; grid-row: 1; }
  .cv.hero .w-data      { grid-column: 1/11; grid-row: 2; }
  /* Même point f, au palier tablette : la colonne y est plus étroite (52,6 px
     à 1023, 35,2 à 768) et la gouttière plus mince (18 px), donc le même
     texte réclame une à deux colonnes de plus qu'au bureau. Empans calés sur
     1023 px, le point le plus large du palier. c4 et c5 y partagent la même
     valeur : 069 Hémythologie (294 px) demande la même largeur que 063 et
     068 (315 px) dès que la colonne se resserre.

     ⚠️ PLAFOND À LA LIGNE 8 — le timbre du hero commence ici en colonne 8
     (contre 9 au bureau) et couvre les DEUX rangées. Un cartel qui dépasse
     cette ligne passe donc SOUS l'image, dans la même piste. Mesuré : à 1/10,
     057 chevauchait le timbre à 900 et à 768 px. Aucun cartel ne va au-delà
     de 1/8 : c8 y rejoint c6, et le cartel d'ERRATA revient à la ligne — ce
     qui vaut mieux qu'un chevauchement. */
  .cv.hero .w-data--c4  { grid-column: 1/6; }   /* 335 px */
  .cv.hero .w-data--c5  { grid-column: 1/6; }   /* 335 px */
  .cv.hero .w-data--c6  { grid-column: 1/8; }   /* 476 px */
  .cv.hero .w-data--c8  { grid-column: 1/8; }   /* 476 px — plafonné, voir ci-dessus */
  .cv.hero .w-figure    { grid-column: 8/13; grid-row: 1/3; align-self: start; }

  .s-synopsis .w-head   { grid-column: 1/8;  grid-row: 1; }
  .s-synopsis .w-text   { grid-column: 1/8;  grid-row: 2; }
  .s-synopsis .w-figure { grid-column: 9/13; grid-row: 1/3; align-self: start; }

  .s-dispositif .w-head    { grid-column: 1/7;  grid-row: 1; }
  .s-dispositif .w-text    { grid-column: 1/7;  grid-row: 2; }
  .s-dispositif .w-figure.a{ grid-column: 8/13; grid-row: 1/3; align-self: start; }
  .s-dispositif .w-figure.b{ grid-column: 8/13; grid-row: 3; align-self: start; margin-top: 18px; }

  .s-transcript .w-head     { grid-column: 1/13; grid-row: 1; }
  .s-transcript .w-text     { grid-column: 1/7;  grid-row: 2; }
  .s-transcript .w-quote.q1 { grid-column: 8/13; grid-row: 2; align-self: start; }
  .s-transcript .w-quote.q2 { grid-column: 8/13; grid-row: 3; align-self: start; margin-top: 26px; }

  .s-docs .w-head  { grid-column: 1/13; grid-row: 1; }
  .s-docs .planche { grid-column: 1/13; grid-row: 2;
                     display: grid; grid-template-columns: repeat(4, 1fr); gap: 18px; }
  .s-docs .w-data  { grid-column: 1/9;  grid-row: 3; margin-top: 16px; }  /* inemployé — voir « .s-docs .w-data » plus haut */

  .s-fiche .w-head     { grid-column: 1/13; grid-row: 1; }
  .s-fiche .blk-gen    { grid-column: 1/7;  grid-row: 2; }
  .s-fiche .blk-diff   { grid-column: 8/13; grid-row: 2; }
  /* Même règle au palier tablette : le bloc va jusqu'à la ligne 11, ce qui
     lui donne 672 px — la largeur la plus proche des 651 px du bureau. */
  .s-fiche .blk-gen:last-child { grid-column: 1/11; }
  .s-fiche .blk-corpus { grid-column: 1/7;  grid-row: 3; margin-top: 26px; }

  .s-atlas .w-atlas { grid-column: 1/13; }
  .s-corpus .w-atlas { grid-column: 1/13; }

  /* 4ᵉ de couverture (072) — empilée pleine largeur (cf. desktop) */
  .s-backcover .w-head,
  .s-backcover .w-subhead,
  .s-backcover .w-defs,
  .s-backcover .w-text { grid-column: 1/13; }
}

/* ═══════ MOBILE (< 768 px) — une colonne, ordre du source ═══════
   §8 du cahier des charges : 1 titre · 2 image(s), timbres à gauche et
   jamais agrandis · 3 texte · 4 cartel. Le source étant déjà écrit dans cet
   ordre, il suffit de repasser la section en flux. */
@media (max-width: 767px) {
  .cv { display: block; padding: 44px 0; }
  .cv > * + * { margin-top: 22px; }
  .w-worksub, .w-text { max-width: none; }

  /* Timbres : petits, alignés à gauche — jamais agrandis pour remplir */
  .w-figure { max-width: 62%; }
  .cv.hero .w-figure { margin-top: 26px; }
  .s-dispositif .w-figure.b { max-width: 48%; }

  /* Planche-contact → grille de deux colonnes (§8) */
  .s-docs .planche { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; }
  .s-docs .w-figure { max-width: none; }
  .s-docs .w-data { margin-top: 22px; }  /* inemployé — voir « .s-docs .w-data » plus haut */

  .s-transcript .w-quote { margin-top: 26px; }
  .s-fiche .blk-gen, .s-fiche .blk-diff, .s-fiche .blk-corpus { margin-top: 26px; }
  /* Corpus voisin : deux boîtes de front, comme la planche-contact (§8) */
  /* ⚠️ LOT 12, point R2 (11/09/2026, arbitrage du propriétaire : « césure
     française »). Une piste `1fr` ne descend jamais sous le mot le plus long
     qu'elle contient : « désinstitutionnalisation », « cinématographiques »
     élargissaient une colonne — boîtes inégales (jusqu'à 197 contre 75 px) sur
     six fiches, et 49 px de débordement à 375 px sur fictionner-le-reel.
     `minmax(0, 1fr)` rend aux deux boîtes leur largeur égale, et le mot trop
     long se coupe avec un trait d'union (césure de la langue de la page).
     Mesuré sur les 62 fiches à corpus voisin : 0 débordement ; rien ne bouge
     au-dessus de 767 px.
     `overflow-wrap: break-word` est un FILET (arbitrage du même jour) : la
     césure anglaise ne coupait pas « Cinematographic… Anthropological » (titre
     EN de 043), qui sortait de 13 px de sa boîte à 375 px. Il ne coupe que le
     mot que la césure laisse entier, et ne change pas la largeur des pistes. */
  .corpus-voisin { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 14px; }
  .cv-lien .ti { -webkit-hyphens: auto; hyphens: auto; overflow-wrap: break-word; }
}
