/* ==============================================================
   PIERRE THENAISIE
   Fond blanc, vert forêt & marron clair, typographie très grosse.
   Petrona (titres) / Karla (corps) / IBM Plex Mono (étiquettes).
   ============================================================== */

:root {
  /* fonds */
  --blanc: #ffffff;
  --sable: #f7f1e8;        /* marron très clair, pour les cartes */
  --sable-2: #efe4d5;
  --sable-fonce: #ffefcb;  /* beige clair — accueil et titres sur fond vert */
  --ligne: #e3d8c8;

  /* verts */
  --vert: #2f5233;         /* vert forêt profond — titres, liens */
  --vert-clair: #5b8c3e;   /* accent vif — décor et grands textes */
  --vert-pale: #eaf0e2;

  /* marrons */
  --marron: #a97f57;       /* marron clair — accents décoratifs */
  --marron-fonce: #7d5a3a; /* marron lisible sur blanc */

  /* textes */
  --encre: #23241f;
  --mut: #6e6f63;

  /* équivalents "r, g, b" des couleurs ci-dessus, pour les usages en
     rgba() à opacité variable — une seule source de vérité, plus de
     littéraux dupliqués qui se désynchronisent silencieusement au
     prochain changement de teinte (voir LRN-010 dans .claude/memory). */
  --blanc-rgb: 255, 255, 255;
  --sable-fonce-rgb: 255, 239, 203;
  --vert-rgb: 47, 82, 51;
  --vert-clair-rgb: 91, 140, 62;
  --vert-pale-rgb: 234, 240, 226;
  --marron-rgb: 169, 127, 87;

  /* typo */
  --f-disp: 'Petrona', Georgia, serif;
  --f-body: 'Karla', system-ui, sans-serif;
  --f-mono: 'IBM Plex Mono', Consolas, monospace;

  --ease-out: cubic-bezier(0.16, 1, 0.3, 1);
  --t-fast: 0.2s ease;
}

*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
html { font-size: 16px; scroll-behavior: smooth; }
body {
  font-family: var(--f-body);
  background: var(--blanc);
  color: var(--encre);
  line-height: 1.7;
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}
a { color: inherit; text-decoration: none; }
img { max-width: 100%; display: block; }
i { font-style: normal; }
::selection { background: var(--vert-clair); color: #fff; }
:focus-visible { outline: 3px solid var(--vert); outline-offset: 3px; border-radius: 2px; }

::-webkit-scrollbar { width: 11px; }
::-webkit-scrollbar-track { background: var(--blanc); }
::-webkit-scrollbar-thumb { background: var(--ligne); border-radius: 999px; border: 3px solid var(--blanc); }
::-webkit-scrollbar-thumb:hover { background: var(--marron); }

/* ==============================================================
   TRANSITIONS DE PAGE (View Transitions API, cross-document)
   Une seule règle CSS active un fondu natif entre deux pages du
   site, géré par le navigateur lui-même : aucun JS, aucun poids
   ajouté. Dégradation totale et invisible sur les navigateurs qui
   ne la supportent pas encore (Firefox à ce jour) — ils gardent le
   changement de page classique, sans fondu.
   ============================================================== */

@view-transition {
  navigation: auto;
}

::view-transition-old(root),
::view-transition-new(root) {
  animation-duration: 0.45s;
  animation-timing-function: var(--ease-out);
}

@media (prefers-reduced-motion: reduce) {
  ::view-transition-group(*),
  ::view-transition-old(*),
  ::view-transition-new(*) {
    animation: none !important;
  }
}

/* ==============================================================
   RÉVÉLATION AU DÉFILEMENT
   ============================================================== */

.reveal { opacity: 0; transform: translateY(28px); transition: opacity 0.6s ease, transform 0.7s var(--ease-out); }
.reveal.in { opacity: 1; transform: none; }
.articles-grid .reveal:nth-child(2) { transition-delay: 0.1s; }
.skills-grid .reveal:nth-child(2) { transition-delay: 0.08s; }
.skills-grid .reveal:nth-child(3) { transition-delay: 0.16s; }
.skills-grid .reveal:nth-child(4) { transition-delay: 0.24s; }

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  .reveal { opacity: 1; transform: none; transition: none; }
  .nav-dot { animation: none !important; }
  .hero-immersif__contenu > * { opacity: 1 !important; animation: none !important; }
  .hero-immersif__contenu, .hero-scroll, .hero-wash, .hero-peaks { animation-timeline: none !important; }
  .index-row::before, .index-n, .index-body h2, .index-arrow { transition: none; }
}

/* ==============================================================
   EN-TÊTE — volontairement sans navigation
   ============================================================== */

/* L'en-tête flotte au-dessus du bandeau à shader, présent sur toutes les pages. */
.nav {
  position: absolute; top: 0; left: 0; right: 0; z-index: 20;
  display: flex; align-items: center; justify-content: space-between;
  padding: 26px 48px;
}
.nav-logo {
  font-family: var(--f-mono);
  font-size: 13px; font-weight: 500;
  letter-spacing: 0.08em; text-transform: uppercase;
  color: #ffffff;
  transition: opacity var(--t-fast);
}
.nav-logo:hover { opacity: 0.75; }
.nav-status {
  display: inline-flex; align-items: center; gap: 10px;
  font-family: var(--f-mono);
  font-size: 11px; letter-spacing: 0.06em; text-transform: uppercase;
  color: rgba(var(--blanc-rgb), 0.78);
}
.nav-dot { width: 7px; height: 7px; border-radius: 50%; background: #c3d6a8; animation: pulse 2.4s ease-in-out infinite; }
@keyframes pulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.25; } }

/* ==============================================================
   HÉROS
   ============================================================== */

/* --- Bandeaux à fond « ethereal » (voir theme/js/ethereal.js) -----
   Filtre SVG natif (bruit + rotation de teinte animée) : toujours
   rendu à pleine résolution par le navigateur, jamais pixellisé.
   Un voile assombri par-dessus garantit le contraste du texte blanc
   quelle que soit la phase de l'animation.
   ------------------------------------------------------------------ */

/* Palette « vert complet », en harmonie avec le reste du site : le
   fond ethereal est composé de DEUX calques, tous deux verts — un
   calque --vert-clair (la matière principale qui bouge) et un calque
   d'accent plus clair, à la même teinte/saturation que --vert du pied
   de page mais éclairci (voir BDR-007), en fusion « screen » et
   opacité réduite pour un dégradé de profondeur plutôt que des blocs
   séparés. Plus aucun beige ni blanc dans le shader. Le fond du
   conteneur est un vert forêt très sombre — plus aucun noir neutre
   nulle part. */
.shader-hero { position: relative; overflow: hidden; background: #111f16; }
.ethereal { position: absolute; inset: 0; overflow: hidden; z-index: 0; }
.ethereal--accent { mix-blend-mode: screen; opacity: 0.62; }
.ethereal-defs { position: absolute; width: 0; height: 0; overflow: hidden; }
.ethereal-fill { position: absolute; inset: -60px; }
.ethereal-grain {
  position: absolute; inset: 0; pointer-events: none;
  opacity: 0.22; mix-blend-mode: overlay;
  background-repeat: repeat; background-size: 140px 140px;
}
/* Voile uniforme (pas de dégradé) : une version dégradée, plus claire
   sur la fin de la largeur, laissait apparaître une tache plus claire
   dans le bruit du shader lui-même (feTurbulence, variance naturelle
   du motif, pas un artefact de rendu) — visible comme une coupure de
   couleur sur toutes les pages secondaires, confirmé par capture
   d'écran réelle. Une opacité fixe et suffisamment sombre supprime
   cette variance quel que soit l'endroit où le bruit est plus clair,
   au lieu de la démasquer volontairement sur une zone donnée. */
.shader-scrim {
  position: absolute; inset: 0; z-index: 1; pointer-events: none;
  background: rgba(11, 20, 14, 0.8);
}

/* --------------------------------------------------------------
   HÉROS IMMERSIF (accueil) — revu en BDR-030 : vert immersif gardé,
   mais désencombré. Un seul calque de fond (.hero-wash, dégradés CSS
   animés, aucun JS/filtre SVG) au lieu de deux calques ethereal +
   grain + voile de contraste superposés. Le canevas n'est plus en
   position:fixed : le geste marquant de la page est maintenant le
   scroll lui-même (voir plus bas), pas un fond qui reste plaqué
   derrière tout le reste.
   -------------------------------------------------------------- */

.hero-immersif {
  position: relative;
  min-height: 100vh;
  display: flex; flex-direction: column;
  align-items: center; justify-content: center;
  text-align: center;
  padding: 120px 48px 104px;
  background: var(--vert);
  overflow: clip;
}
/* Dégradés radiaux qui dérivent lentement en fond de plan — la même
   ambiance que l'ancien shader ethereal, pour une fraction du coût
   (pas de filtre SVG recalculé par frame, juste `background-position`
   animé). Toujours composé des couleurs déjà en place ailleurs sur le
   site (--vert, --vert-clair, --vert-pale), jamais de teinte inédite. */
.hero-wash {
  position: absolute; inset: 0; z-index: 0;
  background:
    radial-gradient(60% 50% at 20% 15%, rgba(var(--vert-clair-rgb), 0.5), transparent 65%),
    radial-gradient(55% 45% at 85% 80%, rgba(var(--vert-pale-rgb), 0.16), transparent 60%),
    radial-gradient(80% 70% at 50% 50%, rgba(var(--vert-rgb), 0) 0%, rgba(20, 36, 23, 0.35) 100%);
  background-size: 160% 160%, 140% 140%, 100% 100%;
  animation: hero-wash-drift 26s ease-in-out infinite alternate;
}
@keyframes hero-wash-drift {
  0%   { background-position: 0% 0%, 100% 100%, center; }
  100% { background-position: 30% 20%, 70% 60%, center; }
}
@media (prefers-reduced-motion: reduce) { .hero-wash { animation: none; } }
/* Silhouette de sommets vectorisée (BDR-041) — deux calques issus du
   même tracé, alignés par construction. `slice` cale le bas des crêtes
   sur le bas du hero et rogne les bords plutôt que déformer le tracé.
   Fondu bas + droite : la zone droite du tracé vient d'une partie de la
   photo plus éparse (rochers dispersés) que le pic principal de gauche
   — à pleine opacité elle lit comme du bruit, on l'estompe. Dérive
   lente sur chaque calque, comme la brume qui glisse sur la roche à
   deux vitesses différentes, même esprit que .hero-wash. */
.hero-peaks {
  position: absolute; inset: 0; z-index: 0;
  overflow: hidden;
  -webkit-mask-image:
    linear-gradient(to bottom, black 82%, transparent 100%),
    linear-gradient(to right, black 68%, transparent 94%);
  -webkit-mask-composite: source-in;
          mask-image:
    linear-gradient(to bottom, black 82%, transparent 100%),
    linear-gradient(to right, black 68%, transparent 94%);
          mask-composite: intersect;
}
.hero-peaks svg { width: 100%; height: 100%; display: block; }
.peaks-back { fill: var(--vert-pale); opacity: 0.1; }
.peaks-front { fill: var(--vert-clair); opacity: 0.19; }
.peaks-back-drift { animation: peaks-drift-back 32s ease-in-out infinite alternate; }
.peaks-front-drift { animation: peaks-drift-front 22s ease-in-out infinite alternate; }
@keyframes peaks-drift-back { from { transform: translateX(-5px); } to { transform: translateX(5px); } }
@keyframes peaks-drift-front { from { transform: translateX(7px); } to { transform: translateX(-7px); } }
@media (prefers-reduced-motion: reduce) {
  .peaks-back-drift, .peaks-front-drift { animation: none; }
}
/* Conteneur large et corps mesuré : chaque moitié du titre doit tenir
   sur une seule ligne, sinon le héros dépasse la hauteur d'écran et
   l'effet « une seule vue » se perd. */
.hero-immersif__contenu { position: relative; z-index: 2; max-width: 1120px; }
/* Entrée en fondu du hero (accueil uniquement) : anciennement Anime.js
   (stagger 110ms, 900ms, outQuad), retiré en faveur d'un équivalent
   CSS pur — voir /impeccable optimize. Version reduced-motion plus
   bas (état final directement, sans animation). */
.hero-immersif__contenu > * { opacity: 0; animation: hero-in 0.9s var(--ease-out) forwards; }
.hero-immersif__contenu > *:nth-child(1) { animation-delay: 0s; }
.hero-immersif__contenu > *:nth-child(2) { animation-delay: 0.11s; }
@keyframes hero-in { from { opacity: 0; transform: translateY(18px); } to { opacity: 1; transform: translateY(0); } }
/* Geste marquant de la page (BDR-030) : au scroll, le hero se dissout
   doucement dans le sommaire — animation liée nativement au défilement
   (`animation-timeline`), aucun JS, aucun coût de scroll-listener.
   Repli sans support (Firefox à ce jour) : la règle @supports ne
   s'applique jamais, le hero garde son état de départ normal, jamais
   bloqué invisible. */
@supports (animation-timeline: scroll()) {
  .hero-immersif__contenu, .hero-scroll, .hero-peaks {
    animation: hero-dissolve linear both;
    animation-timeline: scroll(root);
    animation-range: 0 62vh;
  }
  .hero-wash {
    animation: hero-wash-drift 26s ease-in-out infinite alternate, hero-wash-fade linear both;
    animation-timeline: auto, scroll(root);
    animation-range: normal, 0 70vh;
  }
}
@keyframes hero-dissolve { to { opacity: 0; transform: translateY(-26px) scale(0.96); filter: blur(2px); } }
@keyframes hero-wash-fade { to { opacity: 0.15; } }
/* Règle générale de l'accueil : tout ce qui repose directement sur le
   vert (hero, sommaire) passe en beige — c'est la charte d'origine du
   site (fond vert forêt + beige/marron). Une seule exception, en
   nuance : le mot mis en italique dans le titre passe dans un vert
   pâle, plus clair que le fond (jamais de noir neutre) — une touche
   distincte du reste du titre plutôt qu'un aplat beige de plus. */
.hero-immersif h1 {
  font-family: var(--f-disp);
  font-weight: 700;
  font-size: clamp(40px, 6.4vw, 84px);
  line-height: 1.02;
  letter-spacing: -0.035em;
  color: var(--sable-fonce);
  margin-bottom: 30px;
  text-wrap: balance;
}
.hero-immersif h1 em { font-style: italic; font-weight: 500; color: var(--vert-pale); }
.hero-immersif .hero-sub {
  font-size: 19px; line-height: 1.75;
  color: rgba(var(--sable-fonce-rgb), 0.92);
  max-width: 620px;
  margin: 0 auto 40px;
}
/* --------------------------------------------------------------
   SOMMAIRE — index éditorial (BDR-030)
   Remplace le sommaire en cartes de verre : une liste sobre sur fond
   beige opaque, chiffres en grand (contour au repos, s'encrent au
   survol), une trame qui glisse en fond de ligne au survol. Toujours
   pleinement visible dès l'arrivée (pas de .reveal ici, cf. BDR-014).
   -------------------------------------------------------------- */
.index-section {
  position: relative; z-index: 1;
  background: var(--sable);
  padding: 32px 48px;
}
/* Quadrillage de points en canvas (BDR-041) : un seul élément à
   repeindre, quel que soit le nombre de points — pas de centaines de
   <div> à animer individuellement. Le suivi de la souris se fait sur
   .index-section elle-même (voir dot-field.js dans animations.js),
   jamais sur le canvas (`pointer-events: none`), donc les liens du
   sommaire restent cliquables sans arbitrage. */
.dot-field { position: absolute; inset: 0; z-index: -1; pointer-events: none; display: block; }
.index-list { max-width: 860px; margin: 0 auto; }
.index-row {
  position: relative; isolation: isolate; overflow: clip;
  display: grid; grid-template-columns: 112px 1fr auto; align-items: center; gap: 32px;
  padding: 44px 28px;
  margin: 0 -28px;
}
/* Trame qui glisse au survol : vert pâle sur le fond beige, le même
   geste que celui qui remplit le chiffre juste à côté. */
.index-row::before {
  content: ''; position: absolute; inset: 0; z-index: -1;
  background: var(--vert-pale);
  transform: scaleX(0); transform-origin: left;
  transition: transform 0.5s var(--ease-out);
}
.index-row:hover::before { transform: scaleX(1); }
/* Chiffre en grand, contour seul au repos (silhouette plutôt que
   décoration) : se remplit de couleur et grossit légèrement au
   survol, comme une encre qui prend. */
.index-n {
  font-family: var(--f-disp); font-weight: 600;
  font-size: clamp(54px, 7vw, 88px); line-height: 1;
  font-variant-numeric: tabular-nums;
  color: transparent;
  -webkit-text-stroke: 1.5px var(--marron-fonce);
  opacity: 0.6;
  transition: color 0.4s var(--ease-out), -webkit-text-stroke-color 0.4s var(--ease-out), transform 0.4s var(--ease-out), opacity 0.3s var(--ease-out);
}
.index-row:hover .index-n {
  color: var(--vert-clair);
  -webkit-text-stroke-color: var(--vert-clair);
  opacity: 1;
  transform: scale(1.08);
}
.index-body h2 {
  font-family: var(--f-disp); font-weight: 700; font-size: clamp(24px, 3.4vw, 34px);
  letter-spacing: -0.02em; color: var(--vert);
  margin: 0 0 10px;
  transition: color 0.25s, transform 0.4s var(--ease-out);
}
.index-body p { margin: 0; color: var(--mut); font-size: 16px; max-width: 46ch; }
.index-row:hover .index-body h2 { color: var(--vert-clair); transform: translateX(4px); }
.index-arrow {
  font-family: var(--f-mono); font-size: 13px; letter-spacing: 0.06em; text-transform: uppercase;
  color: var(--marron-fonce);
  align-self: center;
  opacity: 0.75;
  transition: opacity 0.2s, transform 0.35s var(--ease-out);
}
.index-row:hover .index-arrow { opacity: 1; transform: translateX(6px); }

.hero-sub {
  font-size: 19px; line-height: 1.75;
  color: rgba(var(--blanc-rgb), 0.86);
  max-width: 620px;
}
.hero-scroll {
  position: absolute; right: 48px; bottom: 44px; z-index: 3;
  display: flex; flex-direction: column; align-items: center; gap: 12px;
  font-family: var(--f-mono);
  font-size: 10px; letter-spacing: 0.2em; text-transform: uppercase;
  color: rgba(var(--sable-fonce-rgb), 0.8);
  writing-mode: vertical-rl;
}
.hero-scroll-line { width: 1px; height: 56px; background: linear-gradient(to bottom, transparent, var(--sable-fonce)); }

/* bandeau des pages intérieures : même shader, plus court */
.page-hero { padding: 130px 48px 74px; }
.page-hero .page-header { padding: 0; position: relative; z-index: 3; }
/* Même beige clair que les titres/boutons de l'accueil, repris ici pour
   que le titre des autres pages (CV, RCH, galerie) soit cohérent avec
   la couleur retenue sur la page d'accueil. */
.page-hero .page-header h1 { color: var(--sable-fonce); }
.page-hero .page-header p { color: rgba(var(--blanc-rgb), 0.85); }
.page-hero .section-label { color: #c3d6a8; margin-bottom: 0; }
.page-hero .section-label::before { color: #d9bd97; }
.page-hero .section-label::after { background: rgba(var(--blanc-rgb), 0.22); }

/* ==============================================================
   SECTIONS
   ============================================================== */

.section { padding: 110px 48px; max-width: 1180px; margin: 0 auto; }
.section-tight { padding: 48px 48px 110px; max-width: 1180px; margin: 0 auto; }
.section-label {
  display: flex; align-items: center; gap: 18px;
  font-family: var(--f-mono);
  font-size: 13px; letter-spacing: 0.08em; text-transform: uppercase;
  color: var(--marron-fonce);
  margin-bottom: 52px;
}
.section-label::before { content: '//'; color: var(--vert-clair); }
.section-label::after { content: ''; flex: 1; height: 2px; background: var(--ligne); }

/* ==============================================================
   JOURNAL
   ============================================================== */

.articles-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(320px, 1fr)); gap: 0 52px; }
.article-card { padding: 38px 0; border-top: 2px solid var(--ligne); }
.article-meta { display: flex; gap: 16px; margin-bottom: 14px; align-items: center; }
.article-date { font-family: var(--f-mono); font-size: 12px; letter-spacing: 0.05em; color: var(--mut); }
.article-category { font-family: var(--f-mono); font-size: 12px; letter-spacing: 0.05em; color: var(--marron-fonce); }
.article-title { font-family: var(--f-disp); font-weight: 700; font-size: 34px; line-height: 1.1; margin-bottom: 14px; letter-spacing: -0.025em; }
.article-title a { color: var(--vert); background-image: linear-gradient(var(--vert-clair), var(--vert-clair)); background-size: 0% 3px; background-repeat: no-repeat; background-position: left bottom; transition: background-size 0.3s var(--ease-out); }
.article-title a:hover { background-size: 100% 3px; }
.article-summary { font-size: 15px; color: var(--mut); line-height: 1.8; margin-bottom: 20px; }
.article-link {
  font-family: var(--f-mono);
  font-size: 12px; letter-spacing: 0.08em; text-transform: uppercase;
  color: var(--vert);
  border-bottom: 2px solid var(--vert);
  padding-bottom: 3px;
  transition: color var(--t-fast), border-color var(--t-fast);
}
.article-link:hover { color: var(--marron-fonce); border-color: var(--marron); }

.article-hero-img { width: 100%; max-height: 480px; object-fit: cover; display: block; }
.article-container { max-width: 760px; margin: 0 auto; padding: 72px 24px; }
.article-header { margin-bottom: 56px; padding-bottom: 36px; border-bottom: 2px solid var(--ligne); }
.article-header h1 {
  font-family: var(--f-disp);
  font-weight: 700;
  font-size: clamp(40px, 6.5vw, 76px);
  line-height: 1.0; letter-spacing: -0.03em;
  margin: 16px 0;
  color: var(--vert);
}
.article-subtitle { font-size: 17px; color: var(--mut); font-style: italic; margin-top: 8px; }
.article-body { font-size: 18px; line-height: 1.85; color: var(--encre); }
.article-body p { margin-bottom: 1.5em; }
.article-body > p:first-of-type::first-letter {
  font-family: var(--f-disp); font-weight: 900;
  font-size: 4em; line-height: 0.8;
  float: left; padding: 8px 14px 0 0;
  color: var(--marron);
}
.article-body h2 { font-family: var(--f-disp); font-weight: 700; font-size: 32px; letter-spacing: -0.02em; margin: 2.2em 0 0.8em; color: var(--vert); }
.article-body h3 { font-family: var(--f-mono); font-size: 13px; letter-spacing: 0.08em; text-transform: uppercase; margin: 2em 0 0.8em; color: var(--marron-fonce); }
.article-body blockquote {
  border-left: 4px solid var(--marron);
  margin: 2em 0; padding: 0 0 0 28px;
  font-family: var(--f-disp); font-size: 24px; font-style: italic;
  color: var(--vert);
}
.article-body ul, .article-body ol { margin: 0 0 1.5em 1.2em; }
.article-body hr { border: none; border-top: 2px solid var(--ligne); margin: 2.5em 0; }
.article-footer { margin-top: 72px; padding-top: 36px; border-top: 2px solid var(--ligne); }

/* ==============================================================
   EN-TÊTES DE PAGE + PROSE
   ============================================================== */

.page-header { padding: 60px 48px 0; max-width: 1180px; margin: 0 auto; }
.page-header h1 {
  font-family: var(--f-disp);
  font-weight: 700;
  font-size: clamp(52px, 9vw, 124px);
  line-height: 0.94; letter-spacing: -0.035em;
  margin-top: 12px;
  color: var(--vert);
}
.page-header p { color: var(--mut); margin-top: 22px; max-width: 58ch; font-size: 18px; }

.page-content { padding-bottom: 110px; }
.lead { font-size: 21px; line-height: 1.7; color: var(--encre); max-width: 680px; margin-bottom: 1em; }

.prose { max-width: 720px; font-size: 18px; line-height: 1.85; color: var(--encre); }
.prose + .prose { margin-top: 1.4em; }
.prose h2 { font-family: var(--f-disp); font-weight: 700; font-size: 32px; letter-spacing: -0.02em; margin: 1.6em 0 0.7em; color: var(--vert); }
.prose h3 { font-family: var(--f-mono); font-size: 13px; letter-spacing: 0.08em; text-transform: uppercase; color: var(--marron-fonce); margin: 1.8em 0 0.7em; }
.prose p { margin-bottom: 1.3em; }
.prose ul, .prose ol { margin: 0 0 1.3em 1.2em; }
.prose li { margin-bottom: 0.55em; }
.prose blockquote {
  border-left: 4px solid var(--marron);
  padding-left: 28px;
  font-family: var(--f-disp); font-size: 23px; font-style: italic;
  color: var(--vert);
  margin: 1.6em 0;
}
.prose a { color: var(--vert); border-bottom: 2px solid var(--marron); transition: color var(--t-fast), border-color var(--t-fast); }
.prose a:hover { color: var(--marron-fonce); border-color: var(--vert); }
.prose hr { border: none; border-top: 2px solid var(--ligne); margin: 2em 0; }

/* ==============================================================
   ENCARTS
   ============================================================== */

.callout {
  position: relative;
  border: 2px solid var(--ligne);
  border-radius: 22px 22px 22px 5px;
  background: var(--sable);
  padding: 32px 36px;
  margin: 2em 0;
  font-size: 16px; line-height: 1.8;
  color: var(--mut);
  max-width: 720px;
}
/* Barre de gauche retirée à la demande de Pierre (page RCH) : les blocs
   de contexte/explication (.callout) s'appuient uniquement sur le fond
   --sable et la bordure --ligne pour se distinguer, sans accent latéral. */
.callout::before { display: none; }
.callout strong { color: var(--encre); }
.callout p { margin-bottom: 0.8em; }
.callout p:last-child { margin-bottom: 0; }
.callout-label {
  display: block;
  font-family: var(--f-mono);
  font-size: 12px; letter-spacing: 0.07em; text-transform: uppercase;
  color: var(--vert);
  margin-bottom: 12px;
}
/* Disclaimer d'ouverture (page RCH) : plus sobre que l'encart beige des
   autres callouts (demande Pierre) — même logique que .prose blockquote
   (filet gauche, pas d'aplat) plutôt qu'un style inédit. */
.callout--intro {
  border: none;
  border-left: 3px solid var(--marron);
  border-radius: 0;
  background: none;
  padding: 2px 0 2px 26px;
}
.callout--intro .callout-label {
  font-family: var(--f-disp);
  font-style: italic;
  font-weight: 500;
  text-transform: none;
  letter-spacing: 0;
  font-size: 18px;
  color: var(--marron-fonce);
}

/* ==============================================================
   CV
   ============================================================== */

.cv-block { margin-bottom: 80px; }
.cv-block[id] { scroll-margin-top: 24px; }
.cv-timeline { border-left: 3px solid var(--ligne); margin-left: 28px; }
.cv-entry { position: relative; padding: 0 0 52px 46px; }
.cv-entry:last-child { padding-bottom: 4px; }
/* La pastille de logo tient lieu de repère sur la frise. */
.cv-entry::before {
  content: '';
  position: absolute; left: -9px; top: 6px;
  width: 15px; height: 15px; border-radius: 50%;
  background: var(--blanc); border: 4px solid var(--vert-clair);
}
.cv-entry:has(.logo-chip)::before { display: none; }

.cv-entry-head { display: flex; align-items: flex-start; gap: 20px; margin-bottom: 14px; }
.logo-chip {
  position: absolute; left: -29px; top: -4px;
  width: 58px; height: 58px; flex: none;
  border-radius: 50%;
  background: var(--blanc);
  border: 2px solid var(--ligne);
  display: grid; place-items: center;
  overflow: hidden;
  transition: border-color var(--t-fast), transform 0.25s var(--ease-out);
}
.cv-entry:hover .logo-chip { border-color: var(--vert-clair); transform: scale(1.06); }
/* Vrai logo auto-hébergé quand il existe (voir BDR-029) : récupéré une
   fois depuis le site officiel de l'entreprise/école, jamais rechargé
   depuis un service tiers au runtime — cohérent avec BDR-002/003.
   Le monogramme `::before` reste le repli pour les entrées sans logo
   (ex. Université de Tours), masqué dès qu'un logo est présent. */
.logo-chip img { width: 100%; height: 100%; object-fit: cover; }
.logo-chip:has(img)::before { content: none; }
.logo-chip::before {
  content: attr(data-mono);
  font-family: var(--f-mono); font-size: 15px; font-weight: 600;
  letter-spacing: -0.02em;
  color: var(--vert);
}
.cv-entry-period { font-family: var(--f-mono); font-size: 12px; letter-spacing: 0.06em; text-transform: uppercase; color: var(--marron-fonce); margin-bottom: 8px; }
.cv-entry h3 { font-family: var(--f-disp); font-weight: 700; font-size: 26px; margin-bottom: 5px; letter-spacing: -0.02em; color: var(--vert); }
.cv-entry .place { font-size: 14px; color: var(--mut); margin-bottom: 12px; }
.cv-entry p { font-size: 15px; color: var(--mut); line-height: 1.75; }
.cv-entry ul { margin: 0 0 0 1.1em; font-size: 15px; color: var(--mut); line-height: 1.75; }
.cv-entry li { margin-bottom: 0.4em; }

.skills-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(210px, 1fr)); gap: 40px; margin-top: 28px; }
.skills-group h4 { font-family: var(--f-mono); font-size: 12px; letter-spacing: 0.08em; text-transform: uppercase; color: var(--marron-fonce); margin-bottom: 16px; }
.skills-group ul { list-style: none; display: flex; flex-wrap: wrap; gap: 9px; }
.skills-group li { font-family: var(--f-mono); font-size: 13px; border: 2px solid var(--ligne); border-radius: 999px; padding: 6px 14px; color: var(--encre); }

/* ==============================================================
   GALERIE
   ============================================================== */

.gallery-masonry { columns: 3; column-gap: 12px; margin: 48px 0 72px; }
.gallery-masonry .photo-item { break-inside: avoid; margin-bottom: 12px; overflow: hidden; border-radius: 16px; }
.gallery-masonry .photo-item img { width: 100%; display: block; transition: transform 0.5s var(--ease-out); }
.gallery-masonry .photo-item:hover img { transform: scale(1.04); }

.gallery-empty {
  border: 3px dashed var(--ligne);
  border-radius: 22px;
  padding: 72px 32px;
  text-align: center;
  font-family: var(--f-mono);
  font-size: 14px;
  color: var(--mut);
  margin: 48px 0 72px;
}
.gallery-empty span { color: var(--vert-clair); }

/* ==============================================================
   BOUTONS
   ============================================================== */

.btn-outline {
  display: inline-flex; align-items: center; gap: 10px;
  font-family: var(--f-mono);
  font-size: 13px; letter-spacing: 0.06em; text-transform: uppercase;
  color: var(--vert);
  border: 2px solid var(--vert);
  border-radius: 999px;
  padding: 15px 30px;
  cursor: pointer;
  transition: background var(--t-fast), color var(--t-fast), border-color var(--t-fast);
}
.btn-outline:hover { background: var(--vert); color: #fff; }
.center { text-align: center; margin-top: 56px; }

/* ==============================================================
   PIED DE PAGE — bloc vert profond
   ============================================================== */

.footer {
  position: relative;
  background: var(--vert);
  color: #cfdcc0;
  margin-top: 110px;
  padding: 80px 48px 44px;
  overflow: hidden;
}
/* Sur l'accueil, .index-section a déjà son propre fond opaque et son
   propre padding généreux juste au-dessus : la marge par défaut du pied
   de page laissait apparaître une bande de fond blanc (body) entre les
   deux, la seule page du site où le pied de page suit directement une
   section déjà colorée plutôt qu'un contenu de page classique. */
.home .footer { margin-top: 0; }
.footer-ghost {
  position: absolute;
  left: 50%; bottom: -4vw; transform: translateX(-50%);
  font-family: var(--f-disp);
  font-weight: 900; font-style: italic;
  font-size: 17vw; line-height: 1;
  color: transparent;
  -webkit-text-stroke: 2px rgba(223, 232, 207, 0.14);
  white-space: nowrap; user-select: none; pointer-events: none;
}
.footer-inner {
  position: relative; z-index: 1;
  display: flex; justify-content: space-between; align-items: center; gap: 16px;
  max-width: 1180px; margin: 0 auto;
}
.footer-logo { font-family: var(--f-disp); font-weight: 700; font-size: 24px; color: #fff; letter-spacing: -0.02em; transition: opacity var(--t-fast); }
.footer-logo:hover { opacity: 0.75; }
.footer-sub { font-family: var(--f-mono); font-size: 12px; letter-spacing: 0.04em; }

/* ==============================================================
   SOMMAIRE ANCRÉ (pages longues)
   ============================================================== */

.toc {
  max-width: 720px;
  border: 2px solid var(--ligne);
  border-radius: 22px 22px 22px 5px;
  background: var(--sable);
  padding: 30px 34px;
  margin: 2.5em 0;
}
.toc-label {
  display: block;
  font-family: var(--f-mono);
  font-size: 12px; letter-spacing: 0.07em; text-transform: uppercase;
  color: var(--marron-fonce);
  margin-bottom: 16px;
}
.toc ol { margin: 0; padding-left: 1.3em; }
.toc li { margin-bottom: 0.5em; font-size: 16px; }
.toc a { color: var(--vert); border-bottom: 1px solid transparent; transition: border-color var(--t-fast); }
.toc a:hover { border-color: var(--vert-clair); }

/* Titres de section ancrés : décalage pour ne pas coller au haut de l'écran */
.page-content h2[id] { scroll-margin-top: 24px; }
.page-content > h2 {
  font-family: var(--f-disp);
  font-weight: 700;
  font-size: clamp(30px, 4.2vw, 48px);
  letter-spacing: -0.025em;
  color: var(--vert);
  margin: 2.2em 0 0.8em;
  padding-top: 0.4em;
  border-top: 3px solid var(--ligne);
  max-width: 720px;
}

/* Renvois de source en exposant */
sup a {
  font-family: var(--f-mono);
  font-size: 11px;
  color: var(--marron-fonce);
  padding: 0 2px;
  border-bottom: none;
}
sup a:hover { color: var(--vert); }

/* ==============================================================
   FIGURES ET SCHÉMAS SVG
   ============================================================== */

.figure {
  margin: 2.6em 0;
  max-width: 860px;
  border: 2px solid var(--ligne);
  border-radius: 22px;
  background: var(--sable);
  padding: 28px 30px 22px;
}
.figure svg { width: 100%; height: auto; display: block; }
.figure figcaption {
  margin-top: 20px;
  padding-top: 16px;
  border-top: 2px solid var(--ligne);
  font-size: 14px; line-height: 1.7;
  color: var(--mut);
}
.figure figcaption strong { color: var(--encre); }

/* styles internes aux schémas */
.svg-h { font-family: var(--f-disp); font-size: 17px; font-weight: 700; fill: #2f5233; }
.svg-sub { font-family: var(--f-body); font-size: 11px; fill: #6e6f63; }
.svg-lbl { font-family: 'IBM Plex Mono', monospace; font-size: 11px; fill: #23241f; }
.svg-lbl--red { fill: #a8442f; }
.svg-lbl--green { fill: #4a6b3a; }
.svg-lbl--mut { fill: #6e6f63; }
/* Halo de la couleur du fond de carte : certaines étiquettes (ex.
   « inflammation continue ») passent au-dessus du tracé du schéma —
   le halo garde le texte lisible quel que soit ce qu'il y a en
   dessous, sans avoir à recalculer précisément des positions qu'on
   ne peut pas vérifier visuellement. */
.svg-h, .svg-sub, .svg-lbl {
  paint-order: stroke fill;
  stroke: var(--sable);
  stroke-width: 4px;
  stroke-linejoin: round;
}
.svg-rot { transform: rotate(-90deg); transform-origin: 14px 128px; }
.svg-colon { fill: none; stroke: #cfc6b4; stroke-width: 17; stroke-linecap: round; stroke-linejoin: round; }
.svg-inflamme { fill: none; stroke: #b84a31; stroke-width: 17; stroke-linecap: round; stroke-linejoin: round; }
.svg-pt { fill: #2f5233; }
.svg-sep { stroke: #e3d8c8; stroke-width: 2; }
.svg-axis { stroke: #b8b0a0; stroke-width: 2; }
.svg-seuil { stroke: #a97f57; stroke-width: 2; stroke-dasharray: 6 5; }
.svg-courbe { fill: none; stroke: #2f5233; stroke-width: 3.5; stroke-linecap: round; }
.svg-zone { fill: rgba(184, 74, 49, 0.09); }
.svg-noeud rect { fill: #ffffff; stroke: #cfc6b4; stroke-width: 2; }
.svg-noeud--red rect { stroke: #b84a31; }
.svg-nt { font-family: var(--f-disp); font-size: 15px; font-weight: 700; fill: #2f5233; text-anchor: middle; }
.svg-noeud--red .svg-nt { fill: #a8442f; }
.svg-nsub { font-family: var(--f-body); font-size: 11px; fill: #6e6f63; text-anchor: middle; }
.svg-lien { stroke: #8a7a5c; stroke-width: 2.2; fill: none; }
.svg-lien--boucle { stroke-dasharray: 5 4; }
.svg-fleche { fill: #8a7a5c; }
.figure svg text[x="350"][y="262"], .figure svg text[x="350"][y="284"] { text-anchor: middle; }

/* Tracé animé des schémas (voir animations.js) : chaque élément porte
   `pathLength="1"` dans le HTML (maladie.md), donc `stroke-dasharray`/
   `stroke-dashoffset` valent toujours 0-1 quelle que soit la longueur
   réelle du tracé. L'animation elle-même est pilotée en JS image par
   image (boucle requestAnimationFrame) plutôt que par une transition
   CSS : le style est posé directement en ligne par le script, aucune
   règle CSS n'est nécessaire ici. Rien n'est jamais masqué avant que
   le script ne s'exécute — dégradation : script absent = tracés
   pleinement visibles par défaut. */

/* ==============================================================
   CHIFFRES CLÉS
   ============================================================== */

.stat-row {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(210px, 1fr));
  gap: 2px;
  background: var(--ligne);
  border: 2px solid var(--ligne);
  border-radius: 20px;
  overflow: hidden;
  margin: 2.4em 0;
  max-width: 860px;
}
.stat { background: var(--blanc); padding: 26px 24px; display: flex; flex-direction: column; gap: 8px; }
.stat-n { font-family: var(--f-disp); font-weight: 700; font-size: 34px; letter-spacing: -0.02em; color: var(--vert); line-height: 1; }
.stat-l { font-size: 13px; line-height: 1.6; color: var(--mut); }

/* ==============================================================
   CONSEILS
   ============================================================== */

.advice-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(290px, 1fr));
  gap: 20px;
  margin: 2.4em 0 3em;
  max-width: 1000px;
}
.advice {
  position: relative;
  border: 2px solid var(--ligne);
  border-radius: 20px 20px 20px 5px;
  background: var(--sable);
  padding: 30px 28px 26px;
  transition: border-color var(--t-fast), transform 0.25s var(--ease-out);
}
.advice:hover { border-color: var(--vert-clair); transform: translateY(-3px); }
.advice-n {
  font-family: var(--f-disp);
  font-weight: 900; font-style: italic;
  font-size: 40px; line-height: 1;
  color: transparent;
  -webkit-text-stroke: 1.6px rgba(var(--marron-rgb), 0.5);
  display: block; margin-bottom: 10px;
}
.advice h3 { font-family: var(--f-disp); font-weight: 700; font-size: 21px; letter-spacing: -0.02em; color: var(--vert); margin-bottom: 10px; line-height: 1.15; }
.advice p { font-size: 15px; line-height: 1.75; color: var(--mut); }

/* ==============================================================
   SOURCES
   ============================================================== */

.source-list { margin: 2.4em 0 3em; max-width: 860px; }
.source {
  display: flex; gap: 22px; align-items: flex-start;
  padding: 26px 0;
  border-top: 2px solid var(--ligne);
  scroll-margin-top: 24px;
}
.source:last-child { border-bottom: 2px solid var(--ligne); }
.source-n {
  flex: none;
  width: 40px; height: 40px; border-radius: 50%;
  background: var(--vert); color: #fff;
  display: grid; place-items: center;
  font-family: var(--f-mono); font-size: 14px;
}
.source h3 { font-family: var(--f-disp); font-weight: 700; font-size: 19px; line-height: 1.3; margin-bottom: 8px; letter-spacing: -0.015em; }
.source h3 a { color: var(--vert); border-bottom: 2px solid var(--marron); transition: color var(--t-fast); }
.source h3 a:hover { color: var(--marron-fonce); }
.source p { font-size: 15px; color: var(--mut); line-height: 1.7; margin-bottom: 10px; }
.source-dom {
  font-family: var(--f-mono); font-size: 11px;
  color: var(--marron-fonce);
  border: 2px solid var(--ligne);
  border-radius: 999px;
  padding: 3px 11px;
}

/* encart d'avertissement */
.callout--warn { background: #fbf5ec; border-color: #e3cdae; }
.callout--warn::before { background: linear-gradient(to bottom, var(--marron), #b84a31); }

.page-updated { font-family: var(--f-mono); font-size: 12px; color: var(--mut); margin-top: 2.5em; }

/* ==============================================================
   RÉCIT PAR LES PROJETS (CV)
   ============================================================== */

.story { max-width: 780px; margin-top: 2em; }
.story-item {
  position: relative;
  padding: 0 0 44px 30px;
  border-left: 3px solid var(--ligne);
}
.story-item:last-child { border-left-color: transparent; padding-bottom: 0; }
.story-item::before {
  content: '';
  position: absolute; left: -8px; top: 8px;
  width: 13px; height: 13px; border-radius: 50%;
  background: var(--marron); border: 3px solid var(--blanc);
}
.story-year {
  display: inline-block;
  font-family: var(--f-mono); font-size: 12px;
  letter-spacing: 0.05em; text-transform: uppercase;
  color: var(--marron-fonce);
  margin-bottom: 10px;
}
.story-item h3 {
  font-family: var(--f-disp); font-weight: 700;
  font-size: 26px; letter-spacing: -0.025em;
  color: var(--vert);
  margin-bottom: 14px; line-height: 1.15;
}
.story-item p { font-size: 17px; line-height: 1.8; color: var(--encre); margin-bottom: 1.1em; }
.story-item p:last-child { margin-bottom: 0; }
.story-item a { color: var(--vert); border-bottom: 2px solid var(--marron); }
.story-item a:hover { color: var(--marron-fonce); }

/* ==============================================================
   BANDEAU ABSTRAIT
   Respiration pleine largeur entre deux sections : un fond ethereal
   animé, sans texte ni image. Voir theme/js/ethereal.js. Pas de
   voile ici (aucun texte par-dessus) : les couleurs peuvent être
   pleinement visibles.

   --sbw = largeur réelle de la barre de défilement, mesurée en JS.
   Sans cette soustraction, 100vw dépasse la zone de contenu et provoque
   un défilement horizontal. La valeur par défaut 0px reste correcte
   si le JS ne s'exécute pas (barres flottantes, mobile).
   ============================================================== */

.bande-abstraite {
  position: relative;
  width: calc(100vw - var(--sbw, 0px));
  margin-left: calc(50% - (100vw - var(--sbw, 0px)) / 2);
  height: 300px;
  margin-top: 3.5em; margin-bottom: 3.5em;
  overflow: hidden;
  background: #111f16;
}

/* ==============================================================
   RESPONSIVE
   ============================================================== */

@media (max-width: 768px) {
  .nav { padding: 18px 22px; }
  .hero-scroll { display: none; }
  .hero-sub { font-size: 17px; }
  .section { padding: 68px 22px; }
  .section-tight { padding: 32px 22px 72px; }
  .page-header { padding: 40px 22px 0; }
  .index-section { padding: 24px 22px; }
  .index-row { grid-template-columns: 72px 1fr; padding: 34px 20px; margin: 0 -20px; row-gap: 10px; }
  .index-n { font-size: clamp(40px, 16vw, 60px); }
  .index-arrow { grid-column: 2; margin-top: 4px; }
  .articles-grid { grid-template-columns: 1fr; }
  .gallery-masonry { columns: 2; }
  .footer { padding: 60px 22px 34px; margin-top: 72px; }
  .footer-inner { flex-direction: column; text-align: center; }
  /* la frise et les pastilles de logo repassent en colonne simple */
  .cv-timeline { margin-left: 0; }
  /* Même décalage que .story-item plus bas sur la page (22px) : le
     contenu ne doit jamais toucher le trait vertical de la frise. */
  .cv-entry { padding-left: 22px; padding-bottom: 44px; border-left: none; }
  .cv-entry::before { display: none; }
  /* Pastille au-dessus du texte plutôt qu'à côté : sur mobile, une
     ligne (chip + texte) décalait le titre/lieu de la largeur de la
     pastille, désaligné avec le reste du contenu de l'entrée (liste,
     paragraphe) qui démarre à gauche. Empiler les deux corrige l'aplomb. */
  .cv-entry-head { flex-direction: column; align-items: flex-start; gap: 10px; }
  .logo-chip { position: static; width: 48px; height: 48px; }
  .story-item { padding-left: 22px; }
  .figure { padding: 20px 18px 16px; border-radius: 18px; }
  .toc { padding: 24px 24px; }
  .advice-grid { grid-template-columns: 1fr; }
  .source { gap: 16px; }
  .bande-abstraite { height: 200px; margin-top: 2.4em; margin-bottom: 2.4em; }
  .hero-immersif { padding: 96px 22px 80px; }
  .hero-immersif h1 { font-size: clamp(38px, 11vw, 60px); }
}

@media (max-width: 480px) {
  .gallery-masonry { columns: 1; }
}
