/* Fichier produit par le build (scripts/build/styles.mjs) à partir de styles/*.css : c'est là qu'il faut modifier. */
/* fabiendorey.fr — styles communs aux versions FR et EN */

/* Polices auto-hébergées (SIL OFL 1.1, licences dans /fonts) */
@font-face {
  font-family: "IBM Plex Mono";
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url("/fonts/ibm-plex-mono-latin-500-normal.woff2") format("woff2");
}
@font-face {
  font-family: "Fraunces";
  font-style: normal;
  font-weight: 300;
  font-display: swap;
  /* instance statique (graisse 300, SOFT 100, opsz 144), réduite aux caractères latins */
  src: url("/fonts/fraunces-300-normal-v2.woff2") format("woff2");
}
@font-face {
  font-family: "Fraunces";
  font-style: italic;
  font-weight: 300;
  font-display: swap;
  /* instance statique (graisse 300, SOFT 100, opsz 144), réduite aux caractères latins */
  src: url("/fonts/fraunces-300-italic-v2.woff2") format("woff2");
}
@font-face {
  font-family: "Marcellus";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("/fonts/marcellus-latin-400-normal.woff2") format("woff2");
}
@font-face {
  font-family: "Inter";
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url("/fonts/inter-latin-600-normal.woff2") format("woff2");
}
@font-face {
  font-family: "Inter";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("/fonts/inter-latin-400-normal.woff2") format("woff2");
}

/* — Palettes : nuit (ardoise et fougère) par défaut, jour (lin) — */
:root {
  --bg: #1E2824;
  --ink: #E8E5DA;
  --soft: #CFCDC2;
  --muted: #A3ADA3;
  --accent: #A9BC86;
  --motif: #ECE8DE;
  --photo-bg: #2B3832;
  --texture-nuit: 0.45;
  --texture-jour: 0;
  --photo-shadow: 0 1px 1px rgba(0, 0, 0, 0.3), 0 4px 8px -2px rgba(0, 0, 0, 0.45), 0 16px 32px -10px rgba(0, 0, 0, 0.6);
  /* nom gravé dans l'ardoise : reflet dessous, ombre dessus */
  --relief: 0 1px 0 rgba(255, 255, 255, 0.07), 0 -1px 0 rgba(0, 0, 0, 0.55);

  --serif: "Fraunces", Georgia, "Times New Roman", serif;
  --engraved: "Marcellus", "Trajan Pro", Georgia, serif;
  --mono: "IBM Plex Mono", ui-monospace, "SFMono-Regular", Menlo, Consolas, monospace;
  --sans: "Inter", system-ui, -apple-system, "Segoe UI", sans-serif;

  --gutter: clamp(24px, 4vw, 56px);
  --ease: cubic-bezier(0.2, 0.7, 0.2, 1);
  /* bascule jour / nuit instantanée : une seule peinture de la page, seul le curseur glisse */
  --fade: 0s;
}

:root[data-theme="jour"] {
  --bg: #ECE8DE;
  --ink: #22302A;
  --soft: #36433C;
  --muted: #566058;
  --accent: #4D6B3C;
  --motif: #1E2824;
  --photo-bg: #DAD5C8;
  --texture-nuit: 0;
  --texture-jour: 0.5;
  --photo-shadow: 0 1px 1px rgba(34, 48, 42, 0.12), 0 4px 8px -2px rgba(34, 48, 42, 0.18), 0 16px 32px -10px rgba(34, 48, 42, 0.32);
  /* nom estampé dans le lin */
  --relief: 0 1px 0 rgba(255, 255, 255, 0.75), 0 -1px 0 rgba(34, 48, 42, 0.12);
}

/* — Saisons — */
/* La base (ardoise / lin) ne change pas ; seuls la couleur d'accent (« Dorey », filets,
   curseur, pastille) et les arbres du bocage suivent l'année : pommiers en fleurs au printemps,
   fougère l'été, cuivre l'automne, arbres nus l'hiver. */
:root:not([data-theme="jour"])[data-saison="printemps"] { --accent: #E6B3BD; --tree: #E6B3BD; }
:root[data-theme="jour"][data-saison="printemps"]        { --accent: #974659; --tree: #C07585; }

:root:not([data-theme="jour"])[data-saison="automne"]   { --accent: #D29C6E; --tree: #C98A5B; }
:root[data-theme="jour"][data-saison="automne"]          { --accent: #8C502B; --tree: #A8653B; }

:root:not([data-theme="jour"])[data-saison="hiver"]     { --accent: #AFC2C9; }
:root[data-theme="jour"][data-saison="hiver"]            { --accent: #4D6672; }

/* Sans JavaScript : on suit la préférence du système */
@media (prefers-color-scheme: light) {
  :root:not([data-theme]) {
    --bg: #ECE8DE; --ink: #22302A; --soft: #36433C; --muted: #566058; --accent: #4D6B3C;
    --motif: #1E2824; --photo-bg: #DAD5C8; --texture-nuit: 0; --texture-jour: 0.5;
    --relief: 0 1px 0 rgba(255, 255, 255, 0.75), 0 -1px 0 rgba(34, 48, 42, 0.12);
    --photo-shadow: 0 1px 1px rgba(34, 48, 42, 0.12), 0 4px 8px -2px rgba(34, 48, 42, 0.18), 0 16px 32px -10px rgba(34, 48, 42, 0.32);
  }
}

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

html, body { margin: 0; }

body {
  background: var(--bg);
  color: var(--ink);
  font-family: var(--sans);
  font-size: 15px;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
  transition: background-color var(--fade), color var(--fade);
}

::selection { background: var(--accent); color: var(--bg); }

.page {
  position: relative;
  overflow: hidden;
  overflow: clip; /* coupe ce qui dépasse sans faire de la page une zone de défilement à part */
  min-height: 100vh;
  min-height: 100dvh;
  display: grid;
  grid-template-rows: auto 1fr auto;
  padding: clamp(16px, 3.5vh, 56px) var(--gutter);
}

.page > header, .page > main, .page > footer { position: relative; }

/* — Matières — */
/* Le fond est calé sur la fenêtre, pas sur la page : le calcul des textures (bruit SVG)
   coûte la même chose sur une longue note que sur l'accueil.
   Il porte lui-même la couleur de fond et s'isole : la matière se mélange à cette couleur,
   à l'intérieur du fond, jamais à ce qui défile par-dessus. Sinon le navigateur doit refaire
   le mélange à chaque image du défilement (scintillement, textes qui sautent sur iOS). */
.fond {
  position: fixed;
  top: 0;
  left: 0;
  width: 100vw;
  height: 100vh;
  height: 100lvh;
  overflow: hidden;
  pointer-events: none;
  background: var(--bg);
  isolation: isolate;
  transition: background-color var(--fade);
}
.layer {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  transform: translate3d(calc(var(--px, 0) * 5px), calc(var(--py, 0) * 4px), 0) scale(1.03);
  transition: opacity var(--fade), transform 1.4s var(--ease);
}
.layer--nuit { mix-blend-mode: overlay; opacity: var(--texture-nuit); }
.layer--jour { mix-blend-mode: multiply; opacity: var(--texture-jour); }
/* une seule matière est calculée à la fois : celle du thème affiché */
:root:not([data-theme="jour"]) .layer--jour, :root[data-theme="jour"] .layer--nuit { visibility: hidden; }
@media (prefers-color-scheme: light) {
  :root:not([data-theme]) .layer--jour { visibility: visible; }
  :root:not([data-theme]) .layer--nuit { visibility: hidden; }
}

.bocage {
  position: absolute;
  top: 0;
  right: 0;
  width: 52%;
  height: 72%;
  pointer-events: none;
  color: var(--motif);
  opacity: 0.23;
  /* fondu depuis le coin haut droit, pour ne pas passer sous l'accroche */
  -webkit-mask-image: radial-gradient(140% 115% at 100% 0%, #000 45%, transparent 85%);
  mask-image: radial-gradient(140% 115% at 100% 0%, #000 45%, transparent 85%);
  transform: translate3d(calc(var(--px, 0) * -18px), calc(var(--py, 0) * -12px), 0);
  transition: color var(--fade), transform 1.4s var(--ease), opacity 1.8s ease;
}

/* Les haies se dessinent, puis les arbres poussent ; ensuite le bocage dérive très lentement */
/* la dérive déplace le dessin entier (un simple glissement de calque, sans le redessiner) */
.bocage { animation: drift 28s ease-in-out 3s infinite alternate; }
/* l'hiver, les arbres sont nus : de simples cercles tracés */
[data-saison="hiver"] .bocage circle { fill: none; stroke: currentColor; stroke-width: 1.3; }
.bocage path, .motif ellipse {
  stroke-dasharray: 1;
  animation: draw 2s var(--ease) both;
  animation-delay: calc(var(--i) * 0.1s);
}
.bocage circle {
  fill: var(--tree, currentColor); /* bourgeons au printemps, feuillage roux à l'automne */
  transform-box: fill-box;
  transform-origin: center;
  animation: pop 0.7s var(--ease) both;
  animation-delay: calc(0.9s + var(--i) * 0.07s);
}

/* Ce qui tombe ou s'envole, sur toutes les pages, une chose à la fois et lentement :
   pétales au printemps, graines qui montent l'été, feuilles à l'automne, flocons l'hiver.
   Ce sont de petits calques déplacés par la carte graphique : rien n'est redessiné. */
.chute { position: absolute; top: 0; right: 0; width: 52%; height: 72%; pointer-events: none; }
.page--inner .chute { height: min(72vh, 640px); }
.chute span {
  position: absolute;
  left: var(--x);
  top: var(--y);
  width: 6px;
  height: 4px;
  border-radius: 50%;
  background: var(--tree, var(--motif));
  opacity: 0;
  will-change: transform, opacity;
  animation: chute 17s linear infinite;
  animation-delay: calc(4s + var(--i) * 5.3s);
}
[data-saison="automne"] .chute span { --o: 0.42; }
[data-saison="printemps"] .chute span { --o: 0.5; width: 5px; animation-duration: 21s; }
[data-saison="hiver"] .chute span { --o: 0.32; width: 3px; height: 3px; background: var(--motif); animation-name: neige; animation-duration: 25s; }
[data-saison="ete"] .chute span { --o: 0.28; width: 2.5px; height: 2.5px; background: var(--motif); animation-name: envol; animation-duration: 27s; }

/* ================================================================
   Le ciel de Rennes (voir assets/theme.js et assets/site.js) : le fond suit
   l'heure et le temps qu'il fait vraiment. Tout reste discret, et rien n'est
   redessiné : un dégradé fixe et quelques petits calques déplacés.
   ================================================================ */
/* Lumière rasante : dans les cinquante minutes autour du lever et du coucher du soleil,
   une lueur vient du coin du bocage. --lueur (0 à 1) est calculé d'après l'heure ;
   --eclaircie l'atténue quand le ciel est pris. */
.fond::after {
  content: "";
  position: absolute;
  inset: 0;
  opacity: calc(var(--lueur, 0) * var(--eclaircie, 1));
  background: radial-gradient(125% 95% at 100% 0%, var(--lueur-c, transparent) 0%, transparent 64%);
  transition: opacity 2.4s ease;
}
:root[data-lueur="soir"] { --lueur-c: rgba(214, 138, 84, 0.17); }
:root[data-lueur="matin"] { --lueur-c: rgba(204, 146, 160, 0.15); }
:root[data-theme="jour"][data-lueur="soir"] { --lueur-c: rgba(224, 146, 70, 0.24); }
:root[data-theme="jour"][data-lueur="matin"] { --lueur-c: rgba(228, 150, 150, 0.21); }
[data-ciel="nuages"] { --eclaircie: 0.7; }
[data-ciel="couvert"], [data-ciel="brume"] { --eclaircie: 0.3; }
[data-ciel="bruine"], [data-ciel="pluie"], [data-ciel="neige"] { --eclaircie: 0.18; }

/* Le bocage s'estompe quand le ciel se couvre ; par grand vent, il dérive plus vite */
[data-ciel="couvert"] .bocage, [data-ciel="bruine"] .bocage, [data-ciel="pluie"] .bocage, [data-ciel="neige"] .bocage { opacity: 0.19; }
[data-ciel="brume"] .bocage { opacity: 0.13; }
[data-vent="fort"] .bocage { animation-duration: 13s; }
/* sous la pluie ou la neige, rien d'autre ne tombe */
[data-ciel="bruine"] .chute, [data-ciel="pluie"] .chute, [data-ciel="neige"] .chute { display: none; }

/* Ce que le ciel ajoute, posé par site.js au même endroit que ce qui tombe selon la saison */
.meteo { position: absolute; top: 0; right: 0; width: 52%; height: 72%; pointer-events: none; animation: fondu 2.4s ease both; }
.page--inner .meteo { height: min(72vh, 640px); }
.page--inner:has(.note) .meteo { display: none; } /* une note se lit au calme */
.meteo span { position: absolute; left: var(--x); top: var(--y); opacity: 0; will-change: transform, opacity; }
/* pluie et bruine : quelques traits fins, penchés par le vent */
.meteo--pluie span, .meteo--bruine span {
  width: 1px; height: 16px;
  background: linear-gradient(to bottom, transparent, var(--motif));
  rotate: 10deg;
  animation: pluie var(--t) linear var(--d) infinite;
}
.meteo--pluie span { --o: 0.3; }
.meteo--bruine span { --o: 0.22; height: 8px; animation-duration: calc(var(--t) * 1.9); }
[data-vent="fort"] .meteo--pluie span, [data-vent="fort"] .meteo--bruine span { rotate: 24deg; }
/* neige : les flocons de l'hiver, un peu plus nombreux */
.meteo--neige span { --o: 0.36; width: 3px; height: 3px; border-radius: 50%; background: var(--motif); animation: neige calc(var(--t) * 11) linear calc(var(--d) * 6) infinite; }
/* nuit claire : quelques étoiles qui respirent */
.meteo--clair span { width: 2px; height: 2px; border-radius: 50%; background: var(--motif); animation: etoile calc(var(--t) * 3.4) ease-in-out var(--d) infinite alternate; }
:root[data-theme="jour"] .meteo--clair { display: none; }
/* nuages et ciel couvert : de grandes ombres traversent lentement le bocage,
   plus nombreuses et plus denses quand le ciel est pris */
.meteo--nuages, .meteo--couvert { --ombre: rgba(0, 0, 0, 0.3); }
:root[data-theme="jour"] .meteo--nuages, :root[data-theme="jour"] .meteo--couvert { --ombre: rgba(34, 48, 42, 0.13); }
.meteo--nuages span, .meteo--couvert span {
  width: 78%; height: 46%; --o: 0.75;
  background: radial-gradient(closest-side, var(--ombre) 0%, transparent 100%);
  animation: ombre calc(var(--t) * 30) linear calc(var(--d) * -16) infinite;
}
.meteo--couvert span { --o: 1; }
[data-vent="fort"] .meteo--nuages span, [data-vent="fort"] .meteo--couvert span { animation-duration: calc(var(--t) * 16); }
/* brume : deux nappes de la couleur du fond passent lentement devant le bocage */
.meteo--brume span {
  left: -20%; width: 140%; height: 22%; opacity: 1;
  background: linear-gradient(to bottom, transparent, color-mix(in srgb, var(--bg) 62%, transparent) 45% 55%, transparent);
  animation: brume calc(var(--t) * 17) ease-in-out var(--d) infinite alternate;
}
@keyframes pluie {
  0% { opacity: 0; transform: translateY(0); }
  14%, 78% { opacity: var(--o); }
  100% { opacity: 0; transform: translateY(240px); }
}
@keyframes ombre {
  0% { opacity: 0; transform: translateX(-35%); }
  22%, 78% { opacity: var(--o); }
  100% { opacity: 0; transform: translateX(45%); }
}
@keyframes etoile { from { opacity: 0.12; } to { opacity: 0.62; } }
@keyframes brume { from { transform: translateX(-5%); } to { transform: translateX(5%); } }
/* sans mouvement, il ne reste que le bocage estompé, la lueur et les étoiles */
@media (prefers-reduced-motion: reduce) {
  .meteo:not(.meteo--clair) { display: none; }
  .meteo--clair span { opacity: 0.4; }
}

/* Accueil : le temps qu'il fait, sous les coordonnées */
.meta__ciel { display: block; margin-top: 5px; color: inherit; text-decoration: none; animation: fondu 1.6s ease both; }
a.meta__ciel:hover { color: var(--ink); }
a.meta__ciel:focus-visible { outline: 1px solid var(--ink); outline-offset: 4px; }

/* — Bandeau haut — */
.meta {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  flex-wrap: wrap;
  gap: 8px 24px;
  font-family: var(--engraved);
  font-size: 12px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--muted);
  transition: color var(--fade);
}

.meta__place { padding-top: 15px; }

.meta__right {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
}

.meta__now {
  display: flex;
  align-items: center;
  gap: 14px;
}

.switch {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  min-height: 44px;
  margin: 0;
  padding: 0 2px;
  border: 0;
  background: transparent;
  color: var(--ink);
  font: inherit;
  cursor: pointer;
}

.switch svg { transition: opacity 0.3s ease, transform 0.4s var(--ease); }
.switch__sun { opacity: 0.45; transform: rotate(-90deg) scale(0.85); }
.switch__moon { opacity: 1; }
[data-theme="jour"] .switch__sun { opacity: 1; transform: none; }
[data-theme="jour"] .switch__moon { opacity: 0.45; transform: rotate(25deg) scale(0.85); }

.switch__track {
  position: relative;
  display: block;
  width: 40px;
  height: 22px;
  border: 1px solid var(--muted);
  border-radius: 999px;
  transition: border-color var(--fade);
}

.switch__knob {
  position: absolute;
  top: 3px;
  left: 3px;
  width: 14px;
  height: 14px;
  border-radius: 50%;
  background: var(--accent);
  transform: translateX(18px);
  transition: transform 0.2s var(--ease), background-color var(--fade);
}
.switch[aria-checked="false"] .switch__knob { transform: translateX(0); }

.switch:focus-visible { outline: 1px solid var(--ink); outline-offset: 4px; }

/* Sans JavaScript, l'interrupteur ne servirait à rien */
html:not([data-mode]) .switch { display: none; }

/* — Bloc principal — */
main {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  align-content: flex-end;
  gap: clamp(20px, 4vh, 44px) 72px;
  padding: clamp(16px, 4vh, 96px) 0 clamp(20px, 4vh, 72px);
}

h1 {
  flex: 999 1 560px;
  margin: 0;
  font-family: var(--serif);
  font-weight: 300;
  /* taille limitée par la largeur ET la hauteur de l'écran, pour que tout tienne */
  font-size: clamp(48px, min(14vw, 22vh), 200px);
  font-size: clamp(48px, min(14vw, 22dvh), 200px);
  line-height: 0.88;
  letter-spacing: -0.03em;
  text-shadow: var(--relief);
}

h1 .line {
  display: block;
  overflow: hidden;
  /* marge large pour les jambages (le « y » italique) sans décaler les lignes :
     le jambage sort du masque dès le début de la montée, pas à la toute fin */
  padding: 0 0.12em 0.36em 0;
  margin-bottom: -0.3em;
}

/* La branche du « y » italique dépasse de sa boîte : pendant la montée, Safari
   découpe le texte animé au bord de cette boîte. On l'élargit à droite sans
   rien décaler, pour que la lettre tienne dedans. */
h1 .line > span { display: inline-block; padding-right: 0.15em; margin-right: -0.15em; }

h1 em {
  font-style: italic;
  color: var(--accent);
  padding-left: 0.5em;
  transition: color var(--fade);
}

.intro {
  flex: 1 1 280px;
  max-width: 320px;
  display: flex;
  flex-direction: column;
  gap: clamp(12px, 2.2vh, 22px);
  padding-bottom: clamp(4px, 1.4vh, 14px);
}

.intro__rule {
  width: 32px;
  height: 1px;
  background: var(--accent);
  transition: background-color var(--fade);
}

.intro p {
  margin: 0;
  font-size: 15px;
  line-height: 1.7;
  color: var(--soft);
  text-wrap: pretty;
  transition: color var(--fade);
}

.now {
  display: flex;
  align-items: flex-start;
  gap: 14px;
}

.now__photo {
  flex: 0 0 auto;
  width: 60px;
  height: 60px;
  border-radius: 12px; /* carré aux angles adoucis, comme une ardoise taillée */
  background: var(--photo-bg);
  /* posée sur la matière : ombre douce en plusieurs couches, sans cadre */
  box-shadow: var(--photo-shadow);
  overflow: hidden;
  transition: background-color var(--fade), color var(--fade);
}

.now__photo img { display: block; width: 100%; height: 100%; object-fit: cover; border-radius: inherit; }

.now__text { display: flex; flex-direction: column; gap: 4px; }

/* Partie « pro » : capitales gravées et espacées, comme une étiquette */
.now__label {
  display: inline-flex;
  align-self: flex-start;
  align-items: center;
  gap: 8px;
  font-family: var(--engraved);
  font-size: 12px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--muted);
}

.now__label::before {
  content: "";
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--accent);
  order: 1; /* après le mot : « Actuellement » reste aligné sur le rôle */
}
/* un pouls lent : c'est le présent (un halo qui s'élargit et s'efface, sans rien redessiner) */
.now__label { position: relative; }
.now__label::after {
  content: "";
  position: absolute;
  right: 0;
  top: 50%;
  width: 6px;
  height: 6px;
  margin-top: -3px;
  border-radius: 50%;
  background: var(--accent);
  opacity: 0;
  will-change: transform, opacity;
  animation: pouls 4.5s ease-out 2.5s infinite;
}

.now__role {
  font-family: var(--engraved);
  font-size: 13px;
  line-height: 1.45;
  letter-spacing: 0.14em;
  text-transform: uppercase;
}

.now__company { margin-top: 2px; font-size: 13px; line-height: 1.5; color: var(--muted); text-wrap: pretty; }
/* Ce que je fais : trois lignes courtes, les deux premières mènent à la note qui le montre */
.now__faits { list-style: none; margin: 4px 0 0; padding: 0; font-size: 13px; line-height: 1.35; color: var(--muted); }
.now__faits li { border-top: 1px solid color-mix(in srgb, var(--ink) 12%, transparent); }
.now__faits li:last-child { border-bottom: 1px solid color-mix(in srgb, var(--ink) 12%, transparent); }
.now__faits a, .now__faits span { display: flex; align-items: center; justify-content: space-between; gap: 12px; min-height: 30px; padding: 4px 0; }
.now__faits a { color: var(--soft); text-decoration: none; transition: color 0.3s ease; }
.now__faits a:hover, .now__faits a:focus-visible { color: var(--ink); }
.now__faits a:hover .go, .now__faits a:focus-visible .go { transform: translateX(4px); }
.now__faits a:focus-visible { outline: 1px solid var(--ink); outline-offset: 2px; }
.now__faits .go { flex: none; color: var(--accent); }

/* — Pied de page — */
footer { display: flex; flex-direction: column; gap: 2px; }

.hedge {
  display: block;
  width: 100%;
  height: 14px;
  color: var(--ink);
  transition: color var(--fade);
  animation: reveal 1.8s var(--ease) 0.9s both;
}

.footer__row {
  display: flex;
  justify-content: space-between;
  align-items: center;
  flex-wrap: wrap;
  gap: 8px 40px;
}

footer nav ul {
  display: flex;
  flex-wrap: wrap;
  gap: 0 36px;
  margin: 0;
  padding: 0;
  list-style: none;
}

footer nav a {
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: 8px;
  min-height: 44px;
  color: var(--ink);
  text-decoration: none;
  font-family: var(--engraved);
  font-size: 12px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  transition: color var(--fade);
}

footer nav a::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: 12px;
  height: 1px;
  background: currentColor;
  transform: scaleX(0);
  transform-origin: right;
  transition: transform 0.45s var(--ease);
}

footer nav a:hover::after,
footer nav a:focus-visible::after { transform: scaleX(1); transform-origin: left; }

footer nav a svg { transition: transform 0.45s var(--ease); }
footer nav a:hover svg { transform: translate(2px, -2px); }
footer nav a:focus-visible { outline: 1px solid var(--ink); outline-offset: 4px; }

/* — Apparition — */
@keyframes rise { from { transform: translateY(140%); } to { transform: translateY(0); } }
@keyframes fade { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: none; } }
@keyframes draw { from { stroke-dashoffset: 1; } to { stroke-dashoffset: 0; } }
@keyframes pop { from { opacity: 0; transform: scale(0); } to { opacity: 1; transform: scale(1); } }
@keyframes reveal { from { clip-path: inset(0 100% 0 0); } to { clip-path: inset(0 0 0 0); } }
@keyframes drift { to { translate: -12px 8px; } }
@keyframes chute {
  0% { opacity: 0; transform: translate(0, 0) rotate(0deg); }
  6% { opacity: var(--o); }
  35% { transform: translate(-20px, 74px) rotate(110deg); }
  65% { transform: translate(-5px, 148px) rotate(200deg); }
  88% { opacity: var(--o); }
  100% { opacity: 0; transform: translate(-24px, 220px) rotate(310deg); }
}
@keyframes neige {
  0% { opacity: 0; transform: translate(0, 0); }
  8% { opacity: var(--o); }
  50% { transform: translate(8px, 130px); }
  90% { opacity: var(--o); }
  100% { opacity: 0; transform: translate(-4px, 260px); }
}
@keyframes envol {
  0% { opacity: 0; transform: translate(0, 60px); }
  12% { opacity: var(--o); }
  50% { transform: translate(34px, -30px); }
  85% { opacity: var(--o); }
  100% { opacity: 0; transform: translate(60px, -130px); }
}
@keyframes pouls {
  0% { opacity: 0.5; transform: scale(1); }
  45%, 100% { opacity: 0; transform: scale(3.4); }
}
@keyframes glisse { from { transform: translateY(10px); } to { transform: none; } }
@keyframes trait { from { transform: scaleX(0); } to { transform: scaleX(1); } }
@keyframes fondu { from { opacity: 0; } to { opacity: 1; } }
@keyframes apparait { from { opacity: 0; transform: translateY(18px); } to { opacity: 1; transform: none; } }

h1 .line > span { animation: rise 1.1s var(--ease) both; }
h1 .line:nth-child(2) > span { animation-delay: 0.12s; }

.meta, .intro, footer { animation: fade 1s var(--ease) both; }
.meta { animation-delay: 0.05s; }
.intro { animation-delay: 0.45s; }
footer { animation-delay: 0.6s; }

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation: none !important; transition: none !important; }
}

/* — Page 404 — */
.back {
  align-self: flex-start;
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  color: var(--ink);
  font-family: var(--engraved);
  font-size: 12px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  text-decoration: underline;
  text-decoration-color: var(--accent);
  text-underline-offset: 6px;
}
.back:hover { text-decoration-thickness: 2px; }
.back:focus-visible { outline: 1px solid var(--ink); outline-offset: 4px; }

/* — Étiquette : petites capitales gravées (dates, numéros, coordonnées) — */
.label {
  font-family: var(--engraved);
  font-size: 12px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--muted);
}
.label a { color: var(--ink); }

/* ================================================================
   Accueil : le sommaire. Une ligne par rubrique, avec ce qu'elle
   contient de plus récent — la page reste une page d'accueil.
   ================================================================ */
.sommaire {
  flex: 1 1 100%;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(240px, 380px));
  column-gap: 44px;
}
.sommaire a {
  position: relative;
  display: grid;
  grid-template-columns: 26px auto minmax(0, 1fr) auto;
  align-items: center;
  column-gap: 10px;
  min-height: 48px;
  color: var(--ink);
  text-decoration: none;
  animation: fade 1s var(--ease) both;
  animation-delay: calc(0.75s + var(--i) * 0.1s);
}
/* le filet se trace de gauche à droite, une ligne après l'autre */
.sommaire a::before {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 1px;
  background: color-mix(in srgb, var(--ink) 18%, transparent);
  transform-origin: left;
  animation: trait 1.3s var(--ease) both;
  animation-delay: calc(0.7s + var(--i) * 0.1s);
}
.sommaire__n { font-family: var(--engraved); font-size: 12px; letter-spacing: 0.1em; color: var(--accent); transition: color var(--fade); }
.sommaire__nom { font-family: var(--engraved); font-size: 12px; letter-spacing: 0.18em; text-transform: uppercase; }
.sommaire__dernier {
  overflow: hidden;
  font-size: 13px;
  color: var(--muted);
  text-align: right;
  white-space: nowrap;
  text-overflow: ellipsis;
  transition: color 0.3s ease;
}
.go { transition: transform 0.45s var(--ease); }
.sommaire a:hover .sommaire__dernier, .sommaire a:focus-visible .sommaire__dernier { color: var(--ink); }
.sommaire a:hover .go, .sommaire a:focus-visible .go { transform: translateX(4px); }
.sommaire a:focus-visible { outline: 1px solid var(--ink); outline-offset: 2px; }

/* Sommaire de l'accueil : la plante du moment, selon la saison */
.sommaire__dernier [data-s] { display: none; }
[data-saison="printemps"] .sommaire__dernier [data-s="printemps"],
[data-saison="ete"] .sommaire__dernier [data-s="ete"],
[data-saison="automne"] .sommaire__dernier [data-s="automne"],
[data-saison="hiver"] .sommaire__dernier [data-s="hiver"] { display: inline; }
/* ================================================================
   Pages intérieures (Carnet, Ailleurs, En ce moment) — même matière
   que l'accueil, une colonne de lecture, la page peut défiler
   ================================================================ */
.page--inner { display: flex; flex-direction: column; }
.page--inner > nav { position: relative; }
.page--inner main { display: block; flex: 1; padding: clamp(40px, 9vh, 128px) 0 clamp(48px, 9vh, 112px); }

.meta__home {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  font-family: var(--serif);
  font-weight: 300;
  font-size: 22px;
  letter-spacing: -0.01em;
  text-transform: none;
  color: var(--ink);
  text-decoration: none;
  transition: color 0.3s ease;
}
.meta__home:hover { color: var(--accent); }
.meta__home:focus-visible { outline: 1px solid var(--ink); outline-offset: 4px; }

/* — Menu des rubriques, sous le nom — */
.pages { animation: fade 1s var(--ease) 0.1s both; }
.pages ul { display: flex; flex-wrap: wrap; gap: 0 26px; margin: 0; padding: 0; list-style: none; }
html:not([data-atelier]) .pages__atelier { display: none; } /* l'atelier : pour les seuls appareils reliés */
.pages a {
  position: relative;
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  font-family: var(--engraved);
  font-size: 12px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--muted);
  text-decoration: none;
  transition: color 0.3s ease;
}
.pages a::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: 11px;
  height: 1px;
  background: var(--accent);
  transform: scaleX(0);
  transform-origin: right;
  transition: transform 0.45s var(--ease);
}
.pages a:hover, .pages a[aria-current="page"] { color: var(--ink); }
.pages a:hover::after, .pages a:focus-visible::after, .pages a[aria-current="page"]::after { transform: scaleX(1); transform-origin: left; }
.pages a:focus-visible { outline: 1px solid var(--ink); outline-offset: 4px; }

/* — Le menu reste en haut quand on défile —
   Il se cale tout seul (position: sticky, sans calcul) ; quand il touche le haut de la fenêtre,
   le script pose la classe « colle » : un fond léger apparaît, le nom parti avec l'en-tête revient
   en monogramme « fd » à gauche et les rubriques se décalent pour lui faire place.
   Seuls opacity et transform bougent : rien n'est remis en page pendant le défilement. */
html { scroll-padding-top: 64px; }
html[data-mode] .pages { position: sticky; top: 0; z-index: 3; }
.pages::before {
  content: "";
  position: absolute;
  z-index: -1;
  inset: 0 calc(var(--gutter) * -1);
  background: var(--bg);
  background: color-mix(in srgb, var(--bg) 93%, transparent);
  -webkit-backdrop-filter: blur(14px);
  backdrop-filter: blur(14px);
  border-bottom: 1px solid color-mix(in srgb, var(--ink) 14%, transparent);
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.35s ease, background-color var(--fade);
}
html.colle .pages::before { opacity: 1; }
.pages ul { transition: transform 0.5s var(--ease); }
html.colle .pages ul { transform: translateX(44px); }
.pages .pages__fd {
  position: absolute;
  top: 0;
  left: 0;
  font-family: var(--serif);
  font-weight: 300;
  font-size: 22px;
  letter-spacing: -0.01em;
  text-transform: none;
  color: var(--ink);
  opacity: 0;
  visibility: hidden;
  transform: translateY(-12px);
  transition: opacity 0.3s ease, transform 0.5s var(--ease), visibility 0s 0.5s;
}
.pages .pages__fd::after { content: none; }
.pages__fd em { color: var(--accent); transition: color var(--fade); }
html.colle .pages .pages__fd { opacity: 1; visibility: visible; transform: none; transition-delay: 0.08s, 0.08s, 0s; }
/* sur une note, la haie de lecture descend se poser sur le bord du menu */
html.colle .lecture { transform: translateY(39px); }
/* petits écrans : les trois rubriques et le monogramme tiennent sur une ligne */
@media (max-width: 420px) { .pages ul { gap: 0 18px; } }
@media (max-width: 350px) { .pages ul { gap: 0 12px; } .pages a { letter-spacing: 0.1em; } }
/* quatre rubriques sur un téléphone : le menu tient sur une ligne, monogramme compris */
@media (max-width: 420px) { .pages ul:has(li:nth-child(4)) { gap: 0 12px; } .pages ul:has(li:nth-child(4)) a { font-size: 11px; letter-spacing: 0.1em; } }
@media (max-width: 350px) { .pages ul:has(li:nth-child(4)) { gap: 0 8px; } .pages ul:has(li:nth-child(4)) a { letter-spacing: 0.04em; } }

h1.page-title {
  flex: none;
  margin: 0 0 clamp(24px, 4vh, 40px);
  font-size: clamp(56px, 10vw, 136px);
  font-size: clamp(56px, min(10vw, 17dvh), 136px);
}
h1.page-title em { padding-left: 0.4em; }

.page-intro {
  max-width: 34rem;
  margin: 0 0 clamp(32px, 6vh, 64px);
  font-size: 17px;
  line-height: 1.7;
  color: var(--soft);
  text-wrap: pretty;
  animation: fade 1s var(--ease) 0.45s both;
}
.page-vide { margin: 0; animation: fade 1s var(--ease) 0.55s both; }

/* Le motif reste en haut, il ne descend pas sous le texte */
.page--inner .bocage { height: min(72vh, 640px); }
.motif--cernes { opacity: 0.2; }
.motif--sillons { opacity: 0.3; }
.motif--rameau { opacity: 0.26; }
/* sur une note, il se fait plus discret : il ne passe pas sous le texte */
.page--inner:has(.note) .bocage { height: 240px; opacity: 0.16; }

/* Le numéro d'une note (Carnet) ou d'un départ (Ailleurs) */
.note-n { color: var(--accent); transition: color var(--fade); }
/* — En ce moment — */
.moment-date { margin: -8px 0 clamp(28px, 5vh, 48px); animation: fade 1s var(--ease) 0.45s both; }
.moment { max-width: 44rem; margin: 0; }
.moment > div {
  display: grid;
  grid-template-columns: 9.5rem minmax(0, 1fr);
  column-gap: 24px;
  padding: 22px 0;
  border-top: 1px solid color-mix(in srgb, var(--ink) 16%, transparent);
  animation: fade 0.9s var(--ease) both;
  animation-delay: calc(0.5s + var(--i) * 0.09s);
}
.moment > div:last-child { border-bottom: 1px solid color-mix(in srgb, var(--ink) 16%, transparent); }
.moment dt { padding-top: 0.5em; }
.moment dd {
  margin: 0;
  font-family: var(--serif);
  font-weight: 300;
  font-size: clamp(20px, 2.2vw, 24px);
  line-height: 1.35;
  text-wrap: pretty;
}

/* — Pied de page : page en cours — */
footer nav a[aria-current="page"] { text-decoration: underline; text-decoration-color: var(--accent); text-underline-offset: 5px; }

@media (max-width: 600px) {
  .sommaire a { min-height: 46px; }
  .moment > div { grid-template-columns: 6.5rem minmax(0, 1fr); column-gap: 16px; }
}

@media (min-width: 601px) {
  /* le jambage du « y » de Dorey descend bas : on laisse de l'air au-dessus du sommaire */
  .sommaire { margin-top: 16px; }
}

/* — Accueil, grand écran : une grille de trois colonnes —
   Le nom en prend deux, la présentation la troisième, et les trois rubriques du sommaire
   tombent chacune sous une colonne : le texte de droite s'aligne sur « En ce moment »
   au lieu de flotter contre le bord, et il gagne en taille. */
@media (min-width: 900px) {
  main:has(> .sommaire) {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    align-items: end;
    gap: clamp(20px, 4vh, 44px) clamp(32px, 3.4vw, 64px);
  }
  main:has(> .sommaire) > h1 { grid-column: span 2; }
  main:has(> .sommaire) > .intro { max-width: 460px; gap: clamp(14px, 2.4vh, 26px); }
  main:has(> .sommaire) .intro p { font-size: clamp(16px, 1.22vw, 19px); line-height: 1.65; }
  main:has(> .sommaire) .now { gap: 18px; }
  main:has(> .sommaire) .now__photo { width: 72px; height: 72px; border-radius: 14px; }
  main:has(> .sommaire) .now__role { font-size: 14px; }
  main:has(> .sommaire) .now__company { font-size: 14.5px; }
  main:has(> .sommaire) .now__faits { font-size: 14.5px; }
  main:has(> .sommaire) .now__faits :is(a, span) { min-height: 34px; }
  .sommaire { grid-column: 1 / -1; grid-template-columns: inherit; column-gap: clamp(32px, 3.4vw, 64px); }
  /* quatre rubriques : quatre colonnes, la présentation reste calée sur le dernier tiers */
  .sommaire:has(a:nth-child(4)) { grid-template-columns: repeat(4, minmax(0, 1fr)); column-gap: clamp(24px, 2.6vw, 48px); }
  .sommaire a { min-height: 56px; }
  .sommaire__nom { font-size: 13px; }
  .sommaire__dernier { font-size: 14px; }
}

/* — Accueil, téléphone : un vrai sommaire, puis un pied de page discret —
   Les rubriques se lisent en liste (numéro, nom, dernière entrée) ; les liens du pied
   passent en retrait, pour qu'il n'y ait plus deux rangées de capitales qui se répondent. */
@media (max-width: 600px) {
  main:has(> .sommaire) { gap: clamp(16px, 3vh, 28px) 72px; padding-bottom: clamp(16px, 3vh, 28px); }
  .intro p { font-size: 15.5px; }
  .sommaire a { min-height: 44px; grid-template-columns: 24px auto minmax(0, 1fr) auto; }
  .sommaire a:last-child::after {
    content: "";
    position: absolute;
    left: 0;
    right: 0;
    bottom: 0;
    height: 1px;
    background: color-mix(in srgb, var(--ink) 18%, transparent);
    transform-origin: left;
    animation: trait 1.3s var(--ease) 1s both;
  }
  .page:has(.sommaire) footer .hedge { display: none; }
  .page:has(.sommaire) footer nav a { color: var(--muted); font-size: 11px; }
  .page:has(.sommaire) footer nav ul { gap: 0 24px; }
}

/* ================================================================
   Mouvement
   ================================================================ */
/* Entrée en scène en deux temps (voir assets/theme.js) : rien ne bouge avant que la première
   image soit affichée, puis le motif se trace, puis le contenu arrive. Sans JavaScript,
   [data-mode] est absent et tout s'anime dès le chargement. */
html[data-mode]:not(.pret) .bocage,
html[data-mode]:not(.pret) .bocage *,
html[data-mode]:not(.pret) .chute span,
html[data-mode]:not(.pret-contenu) .page > :is(header, nav, main, footer),
html[data-mode]:not(.pret-contenu) .page > :is(header, nav, main, footer)::before,
html[data-mode]:not(.pret-contenu) .page > :is(header, nav, main, footer) *,
html[data-mode]:not(.pret-contenu) .page > :is(header, nav, main, footer) *::before,
html[data-mode]:not(.pret-contenu) .page > :is(header, nav, main, footer) *::after { animation-play-state: paused !important; }

/* Pages suivantes de la même visite : le contenu est là tout de suite, sans mise en scène.
   Restent le tracé du motif, le pouls du présent et ce qui arrive au défilement. */
html.deja .page > :is(header, nav, main, footer),
html.deja .page > :is(header, nav, main, footer) :not(.photo, .notes-list li, .schema, .schema *, .note-voisine, .carte *, .jardin__plan *, .eau__courbe *, .cuve__dessin *),
html.deja .page > :is(header, nav, main, footer) *::before,
html.deja .page > :is(header, nav, main, footer) :not(.now__label)::after { animation: none !important; }

/* D'une page à l'autre : fondu court ; le nom glisse du grand titre de l'accueil
   vers l'en-tête, la haie du pied de page et l'interrupteur restent en place. */
@view-transition { navigation: auto; }
h1[data-nom], .meta__home { view-transition-name: nom; }
footer .hedge { view-transition-name: haie; }
.switch { view-transition-name: interrupteur; }
::view-transition-old(root), ::view-transition-new(root) { animation-duration: 0.35s; }
::view-transition-group(nom) { animation-duration: 0.6s; animation-timing-function: cubic-bezier(0.2, 0.7, 0.2, 1); }
::view-transition-old(nom), ::view-transition-new(nom) { height: 100%; object-fit: contain; object-position: left center; }

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

/* — Sélecteur de langue — */
.lang {
  display: flex;
  align-items: center;
  gap: 10px;
  font-family: var(--engraved);
  font-size: 12px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--muted);
}

.lang a {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  color: var(--muted);
  text-decoration: none;
  transition: color var(--fade);
}

.lang a:hover,
.lang a[aria-current="true"] { color: var(--ink); }

.lang a[aria-current="true"] {
  text-decoration: underline;
  text-decoration-color: var(--accent);
  text-underline-offset: 5px;
}

.lang a:focus-visible { outline: 1px solid var(--ink); outline-offset: 4px; }

/* — Performance — */
/* Avec une souris, la texture et le bocage bougent : on les place sur leur propre
   calque GPU pour que les filtres SVG ne soient pas recalculés à chaque mouvement. */
@media (hover: hover) and (pointer: fine) {
  .layer { will-change: transform; }
}

/* Les deux matières restent sur leur propre calque : le fondu jour / nuit
   ne fait que changer leur opacité, sans recalculer les filtres SVG. */
.layer { will-change: opacity; }

/* — Bascule jour / nuit — */
/* Le curseur est sur son propre calque : il glisse sans à-coup même pendant
   que la page se repeint dans l'autre thème. */
.switch__knob { will-change: transform; }

/* — Petits écrans : tout doit tenir sans défiler — */
@media (max-width: 600px) {
  h1 {
    font-size: clamp(52px, min(18vw, 10.5vh), 96px);
    font-size: clamp(52px, min(18vw, 10.5dvh), 96px);
  }
  .intro { max-width: none; }
  .intro p { line-height: 1.6; }
  .now__photo { width: 52px; height: 52px; }
}

@media (max-width: 600px) and (max-height: 620px) {
  .intro p { font-size: 14px; line-height: 1.5; }
  .now__company { font-size: 12.5px; line-height: 1.4; }
  .now__photo { width: 46px; height: 46px; }
}

/* Téléphone à l'horizontale : nom et texte côte à côte */
@media (max-height: 500px) and (orientation: landscape) {
  h1 { flex-basis: 320px; font-size: clamp(44px, min(10vw, 19vh), 96px); font-size: clamp(44px, min(10vw, 19dvh), 96px); }
  .intro { flex-basis: 300px; max-width: 380px; gap: 10px; padding-bottom: 0; }
  .intro__rule { display: none; }
  .intro p { font-size: 13.5px; line-height: 1.5; }
  .now__photo { width: 44px; height: 44px; }
  .bocage { width: 40%; }
}

