/* ===========================================================================
   STYLE — toutes les valeurs proviennent de tokens.css.
   Organisation : reset / primitives / layout / composants / utilitaires.
   =========================================================================== */

/* --- Reset --------------------------------------------------------------- */

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

html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  background: var(--c-bg);
  color: var(--c-text);
  font-family: var(--font-body);
  font-size: var(--fs-base);
  line-height: var(--lh-normal);
  display: flex;
  flex-direction: column;
  min-height: 100vh;
}

img, svg { max-width: 100%; height: auto; display: block; }

:focus-visible {
  outline: var(--focus-w) solid var(--c-focus);
  outline-offset: 2px;
}

/* --- Primitives ---------------------------------------------------------- */

/* Titres en serif vert : sur la maquette, aucun titre n'est en gris texte. */
h1, h2, h3 {
  font-family: var(--font-display);
  font-weight: var(--fw-bold);
  line-height: var(--lh-tight);
  letter-spacing: var(--tracking-tight);
  color: var(--c-accent);
  margin: 0 0 var(--sp-4);
  text-wrap: balance;
}

h1 { font-size: var(--fs-3xl); }
h2 { font-size: var(--fs-xl); }
h3 { font-size: var(--fs-md); font-family: var(--font-body); font-weight: var(--fw-semibold); }

p, ul, ol { margin: 0 0 var(--sp-4); }
p { max-width: 62ch; }

a { color: var(--c-accent); text-decoration-thickness: 1px; text-underline-offset: 2px; }
a:hover { color: var(--c-accent-hover); }

ul, ol { padding-left: var(--sp-5); }
li + li { margin-top: var(--sp-2); }

hr {
  border: 0;
  border-top: var(--border-w) solid var(--c-border);
  margin: var(--sp-7) 0;
}

/* --- Layout -------------------------------------------------------------- */

.wrap {
  width: 100%;
  max-width: var(--wrap-max);
  margin-inline: auto;
  padding-inline: var(--wrap-gutter);
}

.wrap--narrow { max-width: var(--wrap-narrow); }

/* Dans le contenu principal, le retrait latéral est géré une seule fois par
   `main`. Les sections ne rajoutent donc pas leur propre gouttière — sinon
   les deux s'additionnent et le contenu se décale par rapport au hero.
   L'en-tête et le pied de page, hors de `main`, gardent la leur. */
main .wrap { padding-inline: 0; }

main {
  flex: 1;
  padding-inline: var(--main-gutter);
}

.section { padding-block: var(--section-pad); }
.section--tight { padding-block: var(--section-pad-tight); }
.section--subtle {
  background: var(--c-bg-subtle);
  border-radius: var(--section-radius);
}

/* Le fond déborde du retrait de `main` pour ne laisser que --section-bleed de
   marge avec le bord de l'écran. La marge négative sort la section, le padding
   de même valeur remet son contenu là où il était : le texte reste donc aligné
   sur le reste de la page, seul l'aplat s'élargit.
   À poser explicitement sur une section — les autres ne bougent pas. */
.section--bleed {
  margin-inline: calc(var(--section-bleed) - var(--main-gutter));
  padding-inline: var(--section-bleed-pad-x);
}
.section + .section { padding-top: 0; }

/* La section qui suit le hero n'ajoute pas sa respiration : celle du hero
   suffit, les deux cumulées créaient un vide de plus de 100px. */
.hero + .section { padding-top: 0; }
.section--subtle + .section,
.section + .section--subtle { padding-top: var(--sp-8); }

/* Réglages propres à la section débordante. Placés après les règles générales
   ci-dessus, qu'ils doivent surcharger : `.section + .section--subtle` lui
   imposait sinon 64px de padding haut.
   `:has(+ ...)` vise la section qui la précède, pour resserrer l'écart entre
   les deux sans toucher aux autres enchaînements de la page. */
/* overflow : le décor d'angle est rogné par le coin arrondi du bandeau.
   position : il lui sert de repère. */
.section.section--bleed {
  padding-block: var(--section-bleed-pad);
  position: relative;
  overflow: hidden;
}

/* Décor purement ornemental, posé dans l'angle haut-droit et sous le contenu. */
.section__decor {
  position: absolute;
  top: 0;
  right: 0;
  width: var(--modalites-decor-w);
  height: auto;
  z-index: 0;
  pointer-events: none;
}

/* Le contenu passe au-dessus du décor. */
.section--bleed > .wrap { position: relative; z-index: 1; }

/* Écart avant et après le bandeau. Le padding interne du bandeau (30px) est
   sa respiration propre, à l'intérieur de l'aplat : il ne compte pas dans
   l'écart entre sections, qui se mesure de bord d'aplat à contenu voisin. */
.section:has(+ .section--bleed) { padding-bottom: var(--section-gap); }
.section--bleed + .section { padding-top: var(--section-gap); }

/* Avant le pied de page, le même écart que partout ailleurs. Il est porté par
   la dernière section seule : la marge haute du pied de page est neutralisée
   juste en dessous, sinon les deux s'additionneraient. */
main > section:last-child { padding-bottom: var(--section-gap); }

.grid {
  display: grid;
  gap: var(--sp-5);
  grid-template-columns: repeat(auto-fit, minmax(var(--card-min), 1fr));
}

/* Même seuil que le hero et le duo : la page bascule d'un seul coup. Sans
   cette règle, `auto-fit` tient deux colonnes jusque vers 620px — sur une
   tablette en portrait chaque carte tombait à 290px et son titre passait sur
   trois lignes à côté d'une icône qui n'avait pas rétréci. */
@media (max-width: 60rem) {
  .grid { grid-template-columns: 1fr; }
}

.stack > * + * { margin-top: var(--sp-4); }

/* Deux colonnes égales : texte d'un côté, illustration de l'autre. Même seuil
   de repli que le hero, pour que la page bascule d'un seul coup. */
.duo {
  display: grid;
  gap: var(--sp-7);
  grid-template-columns: 1fr;
  align-items: center;
}

@media (min-width: 60rem) {
  .duo { grid-template-columns: 1fr 1fr; }
}

.duo__texte > :last-child { margin-bottom: 0; }

.duo__media > svg,
.duo__media > img {
  width: 100%;
  height: auto;
}

/* --- Header -------------------------------------------------------------- */

.skip-link {
  position: absolute;
  left: -9999px;
  background: var(--c-bg);
  padding: var(--sp-3) var(--sp-4);
  z-index: 10;
}
.skip-link:focus { left: var(--sp-4); top: var(--sp-4); }

/* Bandeau sur le vert du pied de page, dont il devient le pendant en haut de
   page. Le filet passe donc au terracotta comme celui du pied : un filet beige
   sur le vert se lirait comme une bordure oubliée, la teinte de départ ayant
   été choisie pour se fondre dans le crème.
   Les couleurs de texte plus bas ne sont pas choisies ici : ce sont les tokens
   « inverse », calculés pour rester lisibles sur ce vert précis. */
.site-header {
  border-bottom: var(--header-border-w) solid var(--c-secondary);
  background: var(--c-bg-inverse);
  color: var(--c-text-inverse);
}

.site-header__inner {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-4);
  padding-block: var(--header-pad-y);
  /* Surcharge la gouttière de `.wrap` : le bandeau est plus aéré que le
     contenu des pages. Même spécificité, cette règle vient après. */
  padding-inline: calc(var(--wrap-gutter) + var(--header-gutter-extra));
}

/* Logotype : marque ronde + capitales serif espacées, sur deux lignes.
   Composant partagé par l'en-tête et le pied de page. Sa couleur vient du
   contexte : le tracé du SVG est en currentColor et la pastille en
   --logo-accent, ce qui permet le même logotype sur clair et sur foncé. */
.logotype {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  color: var(--c-accent);
  --logo-accent: var(--c-secondary);
  text-decoration: none;

  /* Ces dérivées sont déclarées ICI et non dans :root : une propriété
     personnalisée est résolue sur l'élément qui la déclare. Placées dans
     :root, elles figeraient l'échelle à 1 et une surcharge plus bas
     n'aurait aucun effet. Sur .logotype, elles se recalculent avec
     l'échelle en vigueur pour ce logotype-là. */
  --mark-size:       calc(var(--logo-mark-base) * var(--logo-echelle));
  --logo-name-fs:    calc(var(--logo-name-base) * var(--logo-echelle));
  --logo-sub-fs:     calc(var(--logo-sub-base)  * var(--logo-echelle));
  --logo-name-nudge: calc(var(--logo-name-nudge-base) * var(--logo-echelle));
  --logo-sub-nudge:  calc(var(--logo-sub-nudge-base)  * var(--logo-echelle));
  --logo-sub-shift:  calc(var(--logo-sub-shift-base)  * var(--logo-echelle));
}

/* Logotype de l'en-tête : même traitement que celui du pied de page, les deux
   étant désormais sur le vert. Passer par le contexte plutôt que par la classe
   de base est ce que le composant prévoit — voir le commentaire ci-dessus. */
.site-header .logotype {
  color: var(--c-text-inverse);
  --logo-accent: currentColor;
}

/* Logotype du pied de page : même dessin, à échelle réduite. Une seule valeur
   entraîne la marque, le nom, le sous-titre et les décalages fins. */
.logotype--pied {
  color: var(--c-text-inverse);
  /* Pastille de la même couleur que le reste : sur fond foncé, la marque se
     lit d'un seul tenant, comme sur la maquette du pied de page. */
  --logo-accent: currentColor;
  --logo-echelle: 0.8;
}

.logotype__mark {
  width: var(--mark-size);
  height: var(--mark-size);
  flex: none;
  color: inherit;
}

/* Le bloc texte occupe exactement la hauteur de la marque : le haut de
   « ÉMILIE SVT » s'aligne sur le haut du cercle, le bas du sous-titre sur son
   bas — comme sur la maquette. D'où la hauteur imposée et space-between. */
.logotype__lockup {
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  height: var(--mark-size);
}

.logotype__name {
  display: block;
  font-family: var(--font-display);
  font-size: var(--logo-name-fs);
  font-weight: var(--fw-bold);
  text-transform: uppercase;
  letter-spacing: var(--tracking-wide);
  /* Interligne à 1 : la boîte colle aux lettres, sinon l'alignement sur le
     cercle est faussé par l'espace au-dessus des capitales. */
  line-height: 1;
  /* Le nom ne se coupe jamais : le bloc a une hauteur fixe, un repli sur deux
     lignes le ferait chevaucher le sous-titre. */
  white-space: nowrap;
  /* origine à gauche : l'étirement ne doit pas décaler le mot vers la droite */
  transform-origin: left center;
  transform: translateY(var(--logo-name-nudge)) scaleY(var(--logo-name-stretch));
}

/* Ligne secondaire : petite et très espacée — sous-titre du logotype. */
.logotype__sub {
  display: block;
  font-size: var(--logo-sub-fs);
  letter-spacing: var(--tracking-wider);
  text-transform: uppercase;
  color: inherit;
  opacity: 0.85;
  font-weight: var(--fw-book);
  line-height: 1;
  /* Le bloc a une hauteur fixe : un repli sur deux lignes recouvrirait le nom. */
  white-space: nowrap;
  transform: translate(var(--logo-sub-shift), calc(-1 * var(--logo-sub-nudge)));
}

.site-nav__list {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--nav-gap);
  list-style: none;
  margin: 0;
  padding: 0;
}

.site-nav__list li + li { margin-top: 0; }

.site-nav a {
  position: relative;
  color: var(--c-text-inverse);
  text-decoration: none;
  font-size: var(--fs-xs);
  transition: color var(--dur-fast) var(--ease);
}

/* Le libellé ne change pas de couleur au survol, comme dans le pied de page :
   sur fond foncé c'est le filet qui signale l'état, pas la teinte. */
.site-nav a:hover { color: var(--c-text-inverse); }

/* Soulignement qui se déploie au survol. Un pseudo-élément mis à l'échelle
   plutôt qu'un text-decoration : seul transform s'anime sans recalculer la
   mise en page. Exclut le bouton Contact, qui a déjà son propre effet.
   L'origine bascule entre les deux états : le trait entre par la gauche et
   ressort par la droite, au lieu de se rétracter d'où il est venu. */
.site-nav a:not(.site-nav__cta)::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: calc(-1 * var(--nav-underline-gap));
  height: var(--nav-underline-w);
  background: var(--c-secondary);
  transform: scaleX(0);
  transform-origin: right center;
  transition: transform var(--dur-base) var(--ease);
}

.site-nav a:not(.site-nav__cta):hover::after,
.site-nav a:not(.site-nav__cta):focus-visible::after {
  transform: scaleX(1);
  transform-origin: left center;
}

/* Page courante : soulignement permanent, sans animation. Le filet reprend
   l'orange des intitulés du pied de page — le vert sauge d'origine, prévu pour
   ressortir sur le crème, s'éteint presque sur le vert foncé. */
.site-nav a[aria-current="page"] {
  color: var(--c-text-inverse);
  font-weight: var(--fw-semibold);
}

.site-nav a[aria-current="page"]:not(.site-nav__cta)::after {
  transform: scaleX(1);
  background: var(--c-inverse-heading);
}

/* Contact traité en bouton dans la nav, comme sur la maquette.
   Sélecteur `a.site-nav__cta` et non `.site-nav__cta` seul : `.site-nav a`
   est plus spécifique (classe + type) et écrasait sinon la couleur verte. */
.site-nav a.site-nav__cta {
  border: var(--border-w) solid var(--c-text-inverse);
  border-radius: var(--radius-md);
  padding: var(--nav-cta-pad-y) var(--nav-cta-pad-x);
  color: var(--c-text-inverse);
  font-weight: var(--fw-medium);
}

/* Le survol remplit le cadre en crème et repasse le texte au vert : sur fond
   foncé, un remplissage vert sur vert ne se verrait pas. */
.site-nav a.site-nav__cta:hover {
  background: var(--c-text-inverse);
  color: var(--c-accent);
}

.nav-toggle__button { display: none; }

@media (max-width: 46rem) {
  /* Cadre carré, taille imposée, contenu centré par la boîte. Les barres du
     haut et du bas sont des pseudo-éléments translatés : elles n'entrent dans
     aucun calcul de hauteur, si bien qu'un cadre ajusté à son contenu ne
     mesurait que la barre du milieu — 36×20 — et les deux autres touchaient
     la bordure. Ici le flex centre la barre centrale, et les deux autres,
     posées symétriquement autour d'elle, le sont aussi par construction :
     changer l'écart des barres ne demande plus de reprendre un rembourrage. */
  .nav-toggle__button {
    display: flex;
    align-items: center;
    justify-content: center;
    width: var(--burger-taille);
    height: var(--burger-taille);
    cursor: pointer;
    border: var(--border-w) solid var(--c-text-inverse);
    border-radius: var(--radius-sm);
  }
  /* Barres en crème : sur le vert du bandeau, le gris du texte courant ne se
     voit pas. */
  .nav-toggle__bar,
  .nav-toggle__bar::before,
  .nav-toggle__bar::after {
    display: block;
    width: var(--burger-w);
    height: var(--burger-bar-h);
    background: var(--c-text-inverse);
    content: "";
  }

  /* Les deux barres extérieures sont les pseudo-éléments de celle du milieu,
     décalées d'un pas de part et d'autre. Les deux décalages ne sont pas
     symétriques : `::before` part du haut de la barre centrale, mais `::after`
     le suit dans le flux et démarre donc déjà une épaisseur plus bas. D'où le
     `- var(--burger-bar-h)`, sans quoi la barre du bas s'écarte plus que
     celle du haut — et le décalage passait inaperçu tant que les trois
     valeurs étaient écrites en dur. */
  .nav-toggle__bar::before {
    transform: translateY(calc(-1 * var(--burger-pas)));
  }
  .nav-toggle__bar::after {
    transform: translateY(calc(var(--burger-pas) - var(--burger-bar-h)));
  }

  .site-nav { display: none; flex-basis: 100%; }
  .nav-toggle:checked ~ .site-nav { display: block; }

  .site-nav__list {
    flex-direction: column;
    align-items: flex-start;
    gap: var(--nav-mobile-gap);
    padding-bottom: var(--nav-mobile-gap);
  }

  /* Cibles au doigt. `display: block` est indispensable : sur un élément en
     ligne, un rembourrage vertical déborde sans pousser les voisins — la
     cible paraîtrait grandir tout en continuant de chevaucher la ligne d'à
     côté. La liste reste alignée à gauche, donc chaque lien garde la largeur
     de son libellé et le soulignement ne s'étire pas en séparateur. */
  .site-nav a {
    display: block;
    font-size: var(--nav-mobile-fs);
    padding-block: var(--nav-mobile-pad-y);
  }

  /* Le soulignement est posé sous la boîte du lien : il faut le remonter de
     la hauteur du rembourrage pour qu'il reste sous le texte, à la même
     distance que sur grand écran. */
  .site-nav a:not(.site-nav__cta)::after {
    bottom: calc(var(--nav-mobile-pad-y) - var(--nav-underline-gap));
  }

  /* Le bouton garde son propre rembourrage — la règle qui le pose est plus
     spécifique — mais il lui faut de l'air au-dessus : bordure comprise, il
     bordait « À propos » et on visait l'un pour l'autre. */
  .site-nav a.site-nav__cta { margin-top: var(--nav-mobile-cta-mt); }
}

/* --- Hero ---------------------------------------------------------------- */

.hero { padding-block: var(--hero-pad-top) var(--hero-pad-bottom); }

/* Hero en deux colonnes : texte à gauche, illustration à droite. */
.hero__grid {
  display: grid;
  gap: var(--sp-7);
  align-items: center;
  grid-template-columns: 1fr;
}

/* Marge basse du dernier élément : elle s'ajoutait au padding du hero et
   faussait l'écart avec les cartes. */
.hero__texte > :last-child { margin-bottom: 0; }

.hero__illu {
  width: 100%;
  max-width: var(--illu-max);
  justify-self: center;
}

/* --- Page « À propos » ---------------------------------------------------- */

.hero--portrait { padding-block: var(--apropos-hero-pad-y); }

/* Carte du haut de page. `overflow: hidden` : l'arc décoratif est bien plus
   grand qu'elle et n'y entre que par un fragment. */
.portrait-carte {
  position: relative;
  overflow: hidden;
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--sp-7);
  align-items: center;
  padding: var(--apropos-carte-pad);
  border-radius: var(--apropos-carte-radius);
  background: var(--c-apropos-carte);
}

/* Le portrait passe à droite dès que la place le permet — plus tôt que les
   autres bascules du site : la carte n'a que deux blocs à loger. Colonnes
   égales, le disque étant centré dans la sienne. */
@media (min-width: 48rem) {
  .portrait-carte { grid-template-columns: var(--apropos-carte-cols); }
}

.portrait-carte__texte > :last-child { margin-bottom: 0; }

.portrait-carte__media {
  position: relative;
  justify-self: center;
}

/* Arc de l'angle bas-gauche, purement ornemental. */
.portrait-carte::before {
  content: "";
  position: absolute;
  left: var(--apropos-arc-x);
  bottom: var(--apropos-arc-y);
  width: var(--apropos-arc-taille);
  height: var(--apropos-arc-taille);
  border: var(--border-w) solid var(--c-border-strong);
  border-radius: 50%;
  pointer-events: none;
}

/* Portrait recadré par le navigateur : `cover` remplit le disque et
   `object-position` décide de ce qu'on garde. Recadrer ainsi plutôt que dans
   le fichier permet d'ajuster le cadrage sans repasser par un éditeur — et
   évite de dégrader une image en la réenregistrant. */
.portrait {
  position: relative;
  z-index: 1;
  width: var(--portrait-taille);
  height: var(--portrait-taille);
  max-width: 100%;
  border-radius: 50%;
  object-fit: cover;
  object-position: var(--portrait-position);
}

/* Anneau ocre décalé, en partie masqué par le portrait qui passe devant. */
.portrait__anneau {
  position: absolute;
  inset: 0;
  border: var(--border-w) solid var(--c-secondary-text);
  border-radius: 50%;
  transform: translate(var(--portrait-anneau-x), var(--portrait-anneau-y));
  pointer-events: none;
}

/* Lignes de la page : repère ocre, titre en serif, description atténuée.
   Filet au-dessus de chacune, plus un dernier sous la liste — comme le
   sommaire de la page lycée. */
/* Écart modeste : le hero porte déjà sa respiration basse, les deux
   s'additionnent. */
.lignes {
  margin-top: var(--sp-4);
  border-bottom: var(--border-w) solid var(--c-jalon-rule);
}

.ligne {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--sp-3);
  padding-block: var(--ligne-pad-y);
  border-top: var(--border-w) solid var(--c-jalon-rule);
}

@media (min-width: 60rem) {
  .ligne {
    grid-template-columns: var(--apropos-col-label) var(--apropos-col-titre) 1fr;
    column-gap: var(--apropos-gap);
  }
}

.ligne__label {
  font-size: var(--ligne-label-fs);
  letter-spacing: var(--eyebrow-tracking);
  text-transform: uppercase;
  font-weight: var(--fw-semibold);
  color: var(--c-secondary-text);
  margin: 0;
}

.ligne__titre {
  font-size: var(--ligne-titre-fs);
  margin: 0;
}

.ligne__texte {
  color: var(--c-text-muted);
  margin: 0;
}

@media (min-width: 60rem) {
  .hero__grid { grid-template-columns: 1.1fr 0.9fr; }
}

/* Sous 60rem l'illustration ne ferait que repousser le contenu utile. */
@media (max-width: 60rem) {
  .hero__illu { display: none; }
}

/* Terracotta et non gris : c'est la seule touche de couleur chaude du haut
   de page. Version « texte » du terracotta, la vive manque de contraste.
   `.eyebrow` est la version réutilisable, employée en tête de section. */
.hero__eyebrow,
.eyebrow {
  font-size: var(--fs-xs);
  letter-spacing: var(--eyebrow-tracking);
  text-transform: uppercase;
  font-weight: var(--fw-semibold);
  color: var(--c-secondary-text);
  margin-bottom: var(--sp-4);
}

/* En tête de section, le bandeau colle davantage à son titre que dans le hero. */
.eyebrow { margin-bottom: var(--eyebrow-gap); }

/* Titre du hero élargi : il empiète sur la gouttière qui le sépare de
   l'illustration, ce qui lui laisse de quoi équilibrer ses lignes autrement.
   Limité au hero — les h1 des autres pages ne sont pas concernés. */
.hero h1 { width: calc(100% + var(--hero-h1-extra)); }

.hero__lead {
  font-size: var(--hero-lead-fs);
  color: var(--c-text);
  max-width: 54ch;
}

/* --- Hero à panneau (page lycée) ----------------------------------------- */

/* Les deux totaux sont déclarés ICI et non dans :root, pour la même raison que
   les dérivées du logotype : une propriété personnalisée est résolue là où
   elle est déclarée. Ils servent deux fois — au padding de la section, et à
   l'aplat qui doit remonter exactement d'autant pour couvrir ce padding. */
.hero--panneau {
  position: relative;
  --hero-panneau-haut: calc(var(--hero-pad-top) + var(--hero-panneau-pad-y));
  --hero-panneau-bas:  calc(var(--hero-pad-bottom) + var(--hero-panneau-pad-y));
  padding-block: var(--hero-panneau-haut) var(--hero-panneau-bas);
}

/* Colonnes égales, et contenus centrés chacun dans sa hauteur : les deux blocs
   n'ont pas la même longueur, leurs lignes ne se répondent donc pas d'une
   colonne à l'autre — c'est voulu. */
@media (min-width: 60rem) {
  .hero__grid--panneau {
    grid-template-columns: 1fr 1fr;
    align-items: center;
  }
}

/* La colonne s'étire sur toute la hauteur de la rangée et centre son contenu
   elle-même, au lieu d'être centrée par la grille. C'est ce qui permet à
   l'aplat de remonter jusqu'aux bords de la section : ancré sur une colonne
   centrée, il serait parti d'une origine flottante et n'aurait couvert ni le
   padding haut ni le bas. */
.hero__panneau {
  position: relative;
  align-self: stretch;
  display: flex;
  flex-direction: column;
  justify-content: center;
  padding-left: var(--hero-panneau-pad);
  border-left: var(--border-w) solid var(--c-secondary-text);
}

/* Étiré vers le haut et vers le bas par les paddings du hero : l'aplat couvre
   toute la hauteur de la section, padding compris, au lieu de s'arrêter à la
   hauteur du texte. Il démarre en retrait du filet, qui reste donc sur le
   crème avec les numéros, et s'arrête au bord du contenu — donc à la même
   verticale que les filets de séparation, et non au bord de l'écran. */
.hero__panneau::before {
  content: "";
  position: absolute;
  top: calc(-1 * var(--hero-panneau-haut));
  bottom: calc(-1 * var(--hero-panneau-bas));
  left: var(--hero-panneau-aplat-x);
  right: 0;
  background: var(--c-hero-panneau);
}

/* Le contenu repasse au-dessus de l'aplat. */
.hero__panneau > * { position: relative; z-index: 1; }

.hero__panneau .eyebrow { margin-bottom: var(--sp-5); }

/* En une seule colonne, le filet vertical n'a plus rien à séparer : il passe
   au-dessus du panneau, et l'aplat déborde des deux côtés. */
@media (max-width: 60rem) {
  .hero__panneau {
    padding-left: 0;
    padding-top: var(--hero-panneau-pad);
    border-left: 0;
    border-top: var(--border-w) solid var(--c-border-strong);
  }
  .hero__panneau::before { top: 0; left: 0; }
}

/* Sur téléphone, l'aplat file jusqu'au bord droit de l'écran et garde un
   retrait à gauche. Il s'arrêtait au retrait de `main`, ce qui laissait une
   bande crème de 24px de chaque côté : sur un grand écran cet alignement sur
   la colonne de texte est le réglage même du panneau, sur 360px il ne se lit
   plus que comme une marge perdue. Le contenu, lui, ne bouge pas — il garde
   le retrait de `main` comme respiration interne.

   Le retrait gauche reprend le parti du grand écran, où l'aplat démarre en
   retrait du filet et passe sous le texte : c'est une nappe, pas une boîte,
   et son bord n'a rien à aligner. Il se compte ici depuis le bord de l'écran,
   d'où le retrait de `main` retranché. */
@media (max-width: 46rem) {
  .hero__panneau::before {
    left:  calc(var(--hero-panneau-aplat-x) - var(--main-gutter));
    right: calc(-1 * var(--main-gutter));
  }
}

/* Accroche du hero : filet court à gauche, le texte dans la colonne voisine. */
.hero__accroche {
  display: grid;
  grid-template-columns: var(--accroche-rule-len) 1fr;
  gap: var(--accroche-rule-gap);
  margin-top: var(--sp-6);
  color: var(--c-accent);
}

.hero__accroche::before {
  content: "";
  height: var(--accroche-rule-w);
  background: var(--c-accent-mid);
  align-self: start;
  margin-top: var(--accroche-rule-top);
}

/* --- Section « Niveaux et objectifs » ------------------------------------ */

/* Filet de séparation entre deux sujets. Posé sur un élément et non en
   `border-top` de la section : il doit s'arrêter aux bords du contenu, alors
   que la section, elle, va d'un bord à l'autre de `main`.
   Le décalage haut le fait respirer après le hero, qui se termine par du texte
   et non par un bloc. */
.separateur {
  border: 0;
  border-top: var(--separateur-w) solid var(--c-separateur);
  margin: var(--separateur-decalage) 0 var(--separateur-marge);
}

/* Même trait, mais celui-ci ferme une section au lieu de l'ouvrir : sa marge
   passe donc au-dessus. */
.separateur--fin {
  margin: var(--separateur-marge) 0 0;
}

/* Filet entre deux blocs d'un même sujet, et non entre deux sections : la
   respiration y est bien plus courte. */
.separateur--serre {
  margin-block: var(--separateur-serre-haut) var(--separateur-serre-bas);
}

/* La maquette veut ce titre nettement plus grand que le h2 courant du site.
   Réglage porté par un token dédié : le ramener à --fs-xl le réaligne sur les
   autres sections. */
.niveaux h2 { font-size: var(--niveau-titre-fs); }

.niveaux__grille {
  display: grid;
  grid-template-columns: var(--niveau-cols);
  gap: var(--niveau-gap);
  margin-top: var(--niveau-grille-mt);
}

/* Déportées hors de l'écran plutôt que masquées : `display: none` les
   retirerait de l'ordre de tabulation et le clavier ne pourrait plus changer
   de niveau. */
.niveau-radio {
  position: absolute;
  width: 1px;
  height: 1px;
  opacity: 0;
  pointer-events: none;
}

.niveaux__onglets {
  display: flex;
  flex-direction: column;
  gap: var(--onglet-gap);
}

/* `position: relative` : le bouton radio vit dans l'étiquette et en est sorti
   par un positionnement absolu. Sans repère, il s'échapperait du cadre. */
.onglet {
  position: relative;
  display: grid;
  grid-template-columns: auto 1fr;
  align-items: baseline;
  gap: var(--onglet-num-gap);
  padding: var(--onglet-pad-y) var(--onglet-pad-x);
  border: var(--border-w) solid var(--c-border);
  border-radius: var(--radius-md);
  background: var(--c-bg-subtle);
  color: var(--c-accent);
  font-size: var(--onglet-fs);
  font-weight: var(--fw-semibold);
  cursor: pointer;
  transition: background var(--dur-fast) var(--ease),
              color var(--dur-fast) var(--ease);
}

.onglet__numero {
  font-size: var(--onglet-num-fs);
  font-weight: var(--fw-medium);
  letter-spacing: var(--tracking-wide);
  color: var(--c-secondary-text);
}

/* Onglet sélectionné. Le bouton radio étant DANS son étiquette, un seul
   sélecteur suffit — quel que soit le nombre d'onglets de la page. C'est ce
   qui permet à la page lycée d'en avoir cinq et au soutien scolaire trois,
   sans rien changer ici. */
.onglet:has(.niveau-radio:checked) {
  background: var(--c-accent);
  border-color: var(--c-accent);
  color: var(--c-text-inverse);
}

/* Le focus est porté par l'étiquette, la commande étant hors de l'écran :
   sans cela, naviguer au clavier n'afficherait aucun repère visible. */
.onglet:has(.niveau-radio:focus-visible) {
  outline: var(--focus-w) solid var(--c-focus);
  outline-offset: 2px;
}

/* Le dégradé, le filet épais et le décor sont portés par le conteneur : ils ne
   changent pas d'un niveau à l'autre, seul le contenu est permuté. */
.niveaux__panneaux {
  position: relative;
  overflow: hidden;
  min-height: var(--niveau-min-h);
  border-left: var(--niveau-bord-w) solid var(--c-secondary);
  background: linear-gradient(to right,
              var(--c-niveau-degrade-1), var(--c-niveau-degrade-2));
}

.niveaux__plante {
  position: absolute;
  right: var(--niveau-plante-droite);
  bottom: var(--niveau-plante-bas);
  width: var(--niveau-plante-w);
  height: auto;
}

/* Cercles au trait, comme ceux du hero d'accueil et du pied de page. */
.niveaux__cercle {
  position: absolute;
  border-radius: 50%;
}

/* Le décor est traité en filigrane : le texte lui passe dessus au lieu de
   s'arrêter avant. `pointer-events: none` pour que la sélection du texte ne
   bute pas dessus. */
.niveaux__plante,
.niveaux__cercle {
  opacity: var(--niveau-decor-opacite);
  pointer-events: none;
}

.niveaux__cercle--bleu {
  width: var(--niveau-cercle-bleu);
  height: var(--niveau-cercle-bleu);
  top: var(--niveau-cercle-bleu-haut);
  right: var(--niveau-cercle-bleu-droite);
  border: var(--border-w) solid var(--c-decor-blue-trait);
}

.niveaux__cercle--orange {
  width: var(--niveau-cercle-orange);
  height: var(--niveau-cercle-orange);
  bottom: var(--niveau-cercle-orange-bas);
  right: var(--niveau-cercle-orange-droite);
  border: var(--border-w) solid var(--c-secondary);
}

/* Les panneaux occupent la même place : un seul est affiché à la fois. */
.niveau { display: none; }

/* Les panneaux sont dans l'autre colonne que les boutons radio : il faut donc
   corréler le numéro coché avec celui du panneau, et cela ne se factorise pas
   sans boucle. La correspondance passe par `data-niveau` et non par le rang
   dans le document — l'ordre des panneaux n'a ainsi aucune importance.
   Six paires, une de plus que la page la plus fournie : au-delà, ajouter la
   ligne manquante. */
.niveaux__grille:has(#niveau-1:checked) .niveau[data-niveau="1"],
.niveaux__grille:has(#niveau-2:checked) .niveau[data-niveau="2"],
.niveaux__grille:has(#niveau-3:checked) .niveau[data-niveau="3"],
.niveaux__grille:has(#niveau-4:checked) .niveau[data-niveau="4"],
.niveaux__grille:has(#niveau-5:checked) .niveau[data-niveau="5"],
.niveaux__grille:has(#niveau-6:checked) .niveau[data-niveau="6"] {
  display: block;
}

/* Plus de réserve à droite : le décor étant en filigrane, le texte occupe
   toute la largeur du panneau et passe par-dessus. */
.niveau {
  position: relative;
  z-index: 1;
  padding: var(--niveau-pad);
}

.niveau__numero {
  font-family: var(--font-display);
  font-size: var(--niveau-num-fs);
  line-height: var(--lh-tight);
  color: var(--c-niveau-numero);
  margin: 0 0 var(--sp-3);
}

.niveau__objectif {
  font-size: var(--niveau-petit-fs);
  letter-spacing: var(--eyebrow-tracking);
  text-transform: uppercase;
  font-weight: var(--fw-semibold);
  color: var(--c-secondary-text);
  margin: 0 0 var(--sp-2);
}

.niveau__titre {
  font-family: var(--font-display);
  font-weight: var(--fw-bold);
  font-size: var(--fs-xl);
  color: var(--c-accent);
  margin: 0 0 var(--sp-4);
}

.niveau__texte {
  color: var(--c-text);
  margin: 0 0 var(--sp-5);
}

/* Mots-clés séparés par une pastille, posée en `::before` sur tous sauf le
   premier : elle relie deux mots, elle n'en ouvre pas la liste. */
.niveau__tags {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--tag-gap);
  list-style: none;
  margin: 0;
  padding: var(--sp-4) 0 0;
  border-top: var(--border-w) solid var(--c-border);
  font-size: var(--niveau-petit-fs);
  letter-spacing: var(--eyebrow-tracking);
  text-transform: uppercase;
  font-weight: var(--fw-semibold);
  color: var(--c-accent);
}

.niveau__tags li {
  display: flex;
  align-items: center;
  gap: var(--tag-gap);
  margin-top: 0; /* annule la règle générale li + li */
}

.niveau__tags li + li::before {
  content: "";
  width: var(--tag-point);
  height: var(--tag-point);
  border-radius: 50%;
  background: var(--c-secondary);
}

/* Sous 60rem, les onglets passent au-dessus du panneau et la plante n'a plus
   la place de tenir à côté du texte. */
@media (max-width: 60rem) {
  .niveaux__grille { grid-template-columns: 1fr; }
  .niveaux__plante,
  .niveaux__cercle { display: none; }
}

/* Sommaire des repères. Le filet sous chaque ligne, dernière comprise, est ce
   qui lui donne son allure de table des matières. */
.jalons {
  list-style: none;
  margin: 0;
  padding: 0;
}

/* Serif, comme le logotype et les titres : ce sommaire se lit comme une table
   des matières, pas comme du texte courant. */
/* Alignement sur la ligne de base, et non sur le haut des boîtes : le numéro
   est plus petit que son libellé, ses lignes ne tombent donc pas au même
   endroit et le décalage se voyait. */
.jalon {
  display: grid;
  grid-template-columns: auto 1fr;
  align-items: baseline;
  gap: var(--jalon-gap);
  padding-block: var(--jalon-pad-y);
  border-bottom: var(--border-w) solid var(--c-jalon-rule);
  font-family: var(--font-display);
  font-size: var(--jalon-fs);
  color: var(--c-accent);
}

.jalon + .jalon { margin-top: 0; } /* annule la règle générale li + li */

/* Même ocre que les surtitres — les numéros leur répondent. */
.jalon__numero {
  font-size: var(--jalon-num-fs);
  font-weight: var(--fw-medium);
  letter-spacing: var(--tracking-wide);
  color: var(--c-secondary-text);
}

/* --- Boutons ------------------------------------------------------------- */

.button {
  display: inline-block;
  font-size: var(--fs-sm);
  font-weight: var(--fw-medium);
  padding: var(--button-pad-y) var(--sp-5);
  border-radius: var(--radius-md);
  border: var(--border-w) solid transparent;
  text-decoration: none;
  cursor: pointer;
  transition: background var(--dur-fast) var(--ease), color var(--dur-fast) var(--ease);
}

/* Variante réduite : se combine avec --primary ou --ghost. */
.button--petit {
  font-size: var(--button-petit-fs);
  padding: var(--button-petit-pad-y) var(--button-petit-pad-x);
}

.button--primary {
  background: var(--c-accent);
  color: var(--c-accent-text);
}
.button--primary:hover {
  background: var(--c-accent-hover);
  color: var(--c-accent-text);
}

/* Cadre vert et fond clair : seul le contour porte la couleur, le libellé
   reste en couleur de texte pour ne pas concurrencer le bouton principal. */
.button--ghost {
  background: var(--c-surface);
  color: var(--c-text);
  border-color: var(--c-accent);
}
.button--ghost:hover { background: var(--c-bg-subtle); color: var(--c-text); }

.button-row {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-3);
  margin-top: var(--sp-5);
}

/* Boutons empilés : en colonne étroite, deux boutons côte à côte se
   couperaient. */
.button-row--empilee {
  flex-direction: column;
  align-items: flex-start;
}

/* Boutons centrés, pour une fin de page qui n'appartient à aucune colonne. */
.button-row--centree { justify-content: center; }

/* --- Fin de la page lycée ------------------------------------------------ */

/* Cette section touche le pied de page : l'aplat de sa colonne droite vient
   buter contre le filet terracotta, sans blanc entre les deux. Le sélecteur
   reprend celui de la règle générale, plus la classe, pour la surcharger —
   `main > section:last-child` est plus spécifique que `.final` seul. */
main > section.final:last-child { padding-bottom: 0; }

.final__grille {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--final-gap);
}

/* `overflow: hidden` : les cercles sont volontairement plus grands que la
   place disponible, et sans cette coupe ils remontent dans la section
   précédente. Ils s'arrêtent donc net au bord haut de l'aplat.
   Ce bloc précède la media query : à spécificité égale, c'est le dernier
   déclaré qui l'emporte, et placé après il écrasait le `padding-left` élargi
   du grand écran. */
.final__profil {
  position: relative;
  overflow: hidden;
  background: var(--c-final-profil);
  padding-block: var(--final-profil-pad);
  padding-left: var(--final-profil-pad-x);
  padding-right: var(--final-profil-pad-right);
}

/* Surtitres plus dégagés de leur titre que partout ailleurs sur le site. */
.final .eyebrow { margin-bottom: var(--final-eyebrow-gap); }

@media (min-width: 60rem) {
  .final__grille { grid-template-columns: var(--final-cols); }

  /* Le filet vertical est porté par la colonne de droite, et non par un
     élément à part : il suit ainsi exactement la hauteur de la rangée. */
  .final__profil {
    border-left: var(--final-filet-w) solid var(--c-final-filet);
    padding-left: var(--final-pad);
  }

  /* Même retrait haut que l'aplat d'en face : sans lui, le rembourrage de la
     colonne de droite décalerait son surtitre d'un cran vers le bas et les
     deux colonnes ne démarreraient plus sur la même ligne. */
  .final__travail { padding-top: var(--final-profil-pad); }
}

/* Même traitement que l'aplat du hero : sur téléphone la colonne de droite va
   d'un bord à l'autre. La marge négative annule le retrait de `main`, le
   rembourrage de même valeur ramène le texte où il était — l'aplat s'élargit
   seul. Ses deux rembourrages latéraux de grand écran, dissymétriques pour
   dégager les cercles, n'ont plus de raison d'être : il n'y a plus de colonne
   voisine, et 72px à droite sur 360 amputaient la ligne d'un cinquième.
   Déclaré après la requête `min-width` : à spécificité égale c'est le dernier
   bloc qui gagne, et les deux touchent aux mêmes propriétés. */
@media (max-width: 46rem) {
  .final__profil {
    margin-inline: calc(-1 * var(--main-gutter));
    padding-left:  var(--main-gutter);
    padding-right: var(--main-gutter);
  }
}

/* Repère de la colonne de gauche. Le filet est posé en haut de chacun, plus un
   dernier sous la liste : le premier item en a donc un au-dessus, comme sur la
   maquette. Même teinte à peine visible que le sommaire du hero. */
.reperes {
  list-style: none;
  margin: var(--sp-6) 0 0;
  padding: 0;
  border-bottom: var(--border-w) solid var(--c-jalon-rule);
}

.repere {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: var(--repere-gap);
  padding-block: var(--repere-pad-y);
  border-top: var(--border-w) solid var(--c-jalon-rule);
  margin-top: 0; /* annule la règle générale li + li */
}

.repere__numero {
  font-family: var(--font-display);
  font-size: var(--repere-num-fs);
  letter-spacing: var(--tracking-wide);
  color: var(--c-secondary-text);
}

.repere__titre {
  font-family: var(--font-display);
  font-weight: var(--fw-bold);
  font-size: var(--repere-titre-fs);
  color: var(--c-accent);
  margin: 0 0 var(--sp-1);
}

.repere__texte {
  color: var(--c-text-muted);
  margin: 0;
}

.final__texte { margin-bottom: var(--sp-5); }

/* Le seul passage de la page qui hausse la voix : plus grand que le texte
   courant, en serif, tenu par un guide ocre. */
.citation {
  margin: 0 0 var(--sp-6);
  padding-left: var(--citation-pad);
  padding-block: var(--citation-depasse);
  border-left: var(--citation-filet-w) solid var(--c-secondary-text);
}

.citation p {
  font-family: var(--font-display);
  font-size: var(--citation-fs);
  line-height: var(--lh-snug);
  color: var(--c-accent);
  margin: 0;
}

/* Décor d'angle. `z-index: 0` sur le décor et `1` sur le contenu : sans cela
   le disque plein recouvre le titre, le texte passant en dessous. */
/* `right`/`top` posent le coin, la translation de 50 % ramène le centre du
   cercle sur ce point : les trois diamètres se centrent donc au même endroit
   sans calcul par cercle. */
.final__cercle {
  position: absolute;
  top: var(--final-cercle-cy);
  right: var(--final-cercle-cx);
  transform: translate(50%, -50%);
  z-index: 0;
  border-radius: 50%;
  pointer-events: none;
}

.final__profil > :not(.final__cercle) {
  position: relative;
  z-index: 1;
}

.final__cercle--large,
.final__cercle--moyen {
  border: var(--border-w) solid var(--c-final-cercle-trait);
  opacity: var(--final-cercle-opacite);
}

.final__cercle--large {
  width: var(--final-cercle-large);
  height: var(--final-cercle-large);
}

.final__cercle--moyen {
  width: var(--final-cercle-moyen);
  height: var(--final-cercle-moyen);
}

.final__cercle--plein {
  width: var(--final-cercle-plein);
  height: var(--final-cercle-plein);
  background: var(--c-final-cercle-plein);
}

/* --- Card ---------------------------------------------------------------- */

/* Liseré vert en haut : signature de la maquette. Porté par un pseudo-élément
   posé en absolu et non par border-top, qui suivrait la courbure des angles
   et donnerait un trait incurvé à ses extrémités. La carte découpe ce trait
   grâce à overflow: hidden, d'où un bord supérieur parfaitement horizontal. */
.card {
  position: relative;
  overflow: hidden;
  border: var(--card-border-w) solid var(--c-border);
  border-radius: var(--card-radius);
  padding: var(--card-pad-y) var(--card-pad-x);
  /* Même fond que le contenu : la carte se lit par sa bordure et son liseré. */
  background: var(--c-bg);
}

.card::before {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: var(--card-accent-w);
  background: var(--c-accent);
  transition: background var(--dur-base) var(--ease);
}

.card > :last-child { margin-bottom: 0; }

/* Le contenu doit passer au-dessus de l'aplat décoratif. */
.card > * { position: relative; z-index: 1; }

/* Deux colonnes : icône à gauche, titre et texte à droite. Ciblé par :has()
   pour qu'une carte sans icône conserve la disposition empilée — aucune
   n'est dans ce cas aujourd'hui, mais les pages à rédiger en auront. */
.card:has(.card__icone) {
  display: grid;
  grid-template-columns: var(--card-icon-col) 1fr;
  column-gap: var(--card-col-gap);
  align-items: start;
}

/* Enveloppe de l'icône. Elle porte la taille et la couleur ; le SVG qu'elle
   contient n'a ni classe ni couleur propre et hérite de currentColor — c'est
   ce qui permet de réutiliser les mêmes fichiers d'icônes partout. */
.card__icone {
  display: block;
  width: var(--icon-size);
  height: var(--icon-size);
  color: var(--c-accent);
  /* L'icône occupe la colonne de gauche sur toute la hauteur du contenu. */
  grid-row: 1 / span 2;
}

.card__icone svg { width: 100%; height: auto; }

/* Seconde carte : icône terracotta, comme sur la maquette. */
.card--terracotta .card__icone { color: var(--c-secondary); }

/* Aplat d'angle en pied de carte, dessin fourni. Il est ancré dans l'angle,
   `position` et `overflow` étant déjà portés par `.card`. La hauteur suit la
   largeur : le dessin est presque carré et ne doit pas être étiré. */
.card__coin {
  position: absolute;
  bottom: 0;
  left: 0;
  width: var(--decor-size);
  height: auto;
  z-index: 0;
  pointer-events: none;
}

.card--decor-blue {
  --coin-fond:  var(--c-decor-blue);
  --coin-trait: var(--c-decor-blue-trait);
}

/* Seconde carte : même tracé, retourné pour venir dans l'angle droit. */
.card--decor-violet {
  --coin-fond:  var(--c-decor-violet);
  --coin-trait: var(--c-decor-violet-trait);
}

.card--decor-violet .card__coin {
  left: auto;
  right: 0;
  transform: scaleX(-1);
}

/* Titre serif vert souligné d'un filet court, comme sur la maquette. */
.card__title {
  font-size: var(--card-title-fs);
  color: var(--c-accent);
  margin-bottom: var(--sp-4);
  -webkit-text-stroke: var(--card-title-stroke) currentColor;
}

/* Texte de la colonne de droite, dans le vert du liseré. Sélecteur plus
   spécifique que `.muted`, qui reste posée sur le paragraphe. */
.card p {
  font-size: var(--card-text-fs);
  color: var(--c-accent);
}

.card__title::after {
  content: "";
  display: block;
  width: var(--rule-len);
  height: var(--rule-w);
  background: var(--c-accent-mid);
  margin-top: var(--sp-3);
}

.card--link { text-decoration: none; color: inherit; display: block; }
.card--link:hover {
  border-color: var(--c-border-strong);
  box-shadow: var(--shadow-md);
  color: inherit;
}

/* Le liseré passe au terracotta, comme le soulignement des items du menu :
   même signal de survol partout. :focus-visible pour le clavier. */
.card--link:hover::before,
.card--link:focus-visible::before {
  background: var(--c-secondary);
}

/* Faux bouton en pied de carte. Il a la taille d'un `.button--petit` — mêmes
   tokens — mais ne peut pas en porter la classe : les variantes de bouton
   posent un fond, et un aplat plein à l'intérieur d'une carte déjà bordée
   ferait deux boîtes emboîtées. Le contour suffit à le désigner comme
   cliquable. Il prend la couleur de la carte, d'où `currentColor` sur la
   bordure : une seule déclaration sert les deux variantes. */
.card__cta {
  display: inline-flex;
  align-items: center;
  gap: var(--card-cta-gap);
  /* Colonne du texte, sinon l'auto-placement le range sous l'icône. */
  grid-column: 2;
  /* Sans quoi il s'étire sur toute la largeur de la carte et cesse de se lire
     comme un bouton. */
  justify-self: start;
  margin-top: var(--card-cta-mt);
  padding: var(--button-petit-pad-y) var(--button-petit-pad-x);
  border: var(--border-w) solid currentColor;
  border-radius: var(--radius-md);
  font-size: var(--button-petit-fs);
  font-weight: var(--fw-medium);
  color: var(--c-accent);
}

.card--terracotta .card__cta { color: var(--c-secondary); }

.card--link:hover .card__cta { border-color: var(--c-border-strong); }

/* Le survol dit déjà le clic sur un écran large : ombre portée, bordure
   appuyée, liseré qui passe au terracotta. Rien de tout cela n'existe au
   doigt, et la carte y perd tout signal — c'est là, et là seulement, que le
   faux bouton se justifie. La requête porte donc sur le survol et non sur la
   largeur : une tablette de 1024px n'en a pas plus qu'un téléphone, et une
   fenêtre de bureau rétrécie garde le sien. */
@media (hover: hover) and (min-width: 60rem) {
  .card__cta { display: none; }
}

/* --- Liste de définitions (modalités, niveaux) --------------------------- */

.deflist { margin: 0; }
.deflist dt {
  font-weight: var(--fw-semibold);
  margin-top: var(--sp-5);
}
.deflist dt:first-child { margin-top: 0; }
.deflist dd {
  margin: var(--sp-1) 0 0;
  color: var(--c-text-muted);
  max-width: 62ch;
}

/* --- Formulaire ---------------------------------------------------------- */

/* --- Page des tarifs ------------------------------------------------------ */

/* Vraie table : c'est une grille à deux entrées, niveau × modalité, et un
   lecteur d'écran doit pouvoir annoncer la ligne et la colonne d'une cellule.
   `overflow-x` sur l'enveloppe : sur un écran étroit, la table défile plutôt
   que d'écraser ses colonnes. */
/* La marge haute est portée par l'enveloppe et non par la table : celle du
   paragraphe qui précède se fusionnerait sinon avec elle, et l'écart demandé
   ne serait pas celui obtenu. */
.tarifs-cadre {
  overflow-x: auto;
  margin-top: var(--tarifs-marge-haut);
}

.tarifs {
  width: 100%;
  border-collapse: collapse;
}

.tarifs th,
.tarifs td {
  text-align: left;
  padding: var(--tarifs-pad-y) var(--tarifs-pad-x);
  border-bottom: var(--border-w) solid var(--c-info-filet);
  vertical-align: top;
}

/* Colonne des niveaux. Posée sur la seule cellule d'en-tête : dans une table,
   la largeur d'une colonne se déclare sur une cellule et vaut pour toute la
   colonne. C'est une préférence, pas un plafond — un mot plus long que la
   valeur l'élargira quand même, la table ne coupe pas ses textes. */
.tarifs thead th:first-child { width: var(--tarifs-col-niveau); }

/* Intitulés de colonne, dans le style des surtitres du site. */
.tarifs thead th {
  font-family: var(--font-body);
  font-size: var(--tarifs-tete-fs);
  font-weight: var(--fw-semibold);
  letter-spacing: var(--eyebrow-tracking);
  text-transform: uppercase;
  color: var(--c-secondary-text);
  border-bottom-color: var(--c-accent);
}

/* Intitulés de ligne : les niveaux, en serif comme les titres. */
.tarifs tbody th {
  font-family: var(--font-display);
  font-size: var(--fs-md);
  font-weight: var(--fw-bold);
  color: var(--c-accent);
}

.tarifs__prix {
  display: block;
  font-size: var(--tarifs-prix-fs);
  color: var(--c-accent);
}

/* Le prix final passe devant : c'est lui qui décide de l'achat, le tarif
   facturé n'est qu'une étape. */
.tarifs__net {
  display: block;
  font-family: var(--font-display);
  font-size: var(--tarifs-net-fs);
  font-weight: var(--fw-bold);
  line-height: var(--lh-tight);
  color: var(--c-accent);
}

/* Le tarif facturé s'efface, mais n'est jamais barré : un prix barré annonce
   un ancien prix, donc une remise du vendeur. Ici les 40 € sont bel et bien
   facturés et la moitié vient de l'État, pas d'un rabais — le barré serait
   une annonce de réduction de prix, ce que la loi encadre. */
.tarifs__brut {
  display: block;
  font-size: var(--tarifs-brut-fs);
  color: var(--c-text-muted);
  margin-top: var(--sp-2);
}

/* Seule colonne ouvrant droit au crédit d'impôt. L'aplat la distingue sans
   qu'aucun texte n'ait à le dire. */
.tarifs__eligible { background: var(--c-tarifs-eligible); }

/* --- Page de contact ------------------------------------------------------ */

/* Le bandeau touche l'en-tête et le pied de page : occupant déjà toute la
   largeur, une bande de crème au-dessus ou en dessous le ferait flotter. Sa
   respiration intérieure est portée par son propre rembourrage.
   Ciblé par `:has()` plutôt que par une classe de plus sur la section — même
   procédé que les autres réglages d'écart entre sections. Cette règle passe
   devant `main > section:last-child`, qui pose sinon un retrait bas. */
.section:has(> .contact__panneau) { padding-block: 0; }

/* Bandeau pleine largeur : la marge négative annule le retrait de `main` pour
   atteindre les bords de l'écran, le rembourrage de même valeur ramène le
   contenu là où il était. Pas d'angles arrondis — il touche les bords, il n'y
   a plus de coin à adoucir. */
.contact__panneau {
  margin-inline: calc(-1 * var(--main-gutter));
  padding-block: var(--contact-panneau-pad-haut) var(--contact-panneau-pad);
  padding-inline: var(--main-gutter);
  background: var(--c-contact-panneau);
}

/* Bloc d'accroche centré. `max-width: none` sur les paragraphes : la mesure
   générale de 62ch les décalerait à gauche au lieu de les centrer. */
.contact__intro {
  max-width: var(--contact-intro-max);
  margin-inline: auto;
  text-align: center;
}

.contact__intro p { max-width: none; }

/* Surtitre et plume centrés ensemble, comme un seul bloc. Alignement par le
   bas : le bout de la plume tombe sur la ligne de base du libellé. */
.contact__eyebrow {
  display: flex;
  align-items: flex-end;
  justify-content: center;
  gap: var(--plume-gap);
}

.contact__plume {
  width: var(--plume-w);
  height: auto;
  margin-bottom: var(--plume-remontee);
}

.contact__citation {
  margin: var(--sp-5) 0 var(--sp-4);
  padding: 0;
  border: 0;
}

.contact__citation p {
  font-family: var(--font-display);
  font-style: italic;
  font-size: var(--contact-citation-fs);
  line-height: var(--lh-snug);
  color: var(--c-accent);
  margin: 0;
}

.contact__sous { color: var(--c-text-muted); margin: 0; }

/* Seul aplat blanc de la page, souligné d'un liseré vert : c'est l'action
   attendue, elle doit se détacher du panneau. */
.contact__carte {
  margin-top: var(--contact-carte-mt);
  padding: var(--contact-carte-pad);
  background: var(--c-surface);
  border-top: var(--contact-carte-liseret) solid var(--c-accent);
  border-radius: var(--radius-sm);
  box-shadow: var(--shadow-sm);
}

/* Sur téléphone, la carte va d'un bord à l'autre comme le panneau qui la
   porte : la marge négative annule le rembourrage de celui-ci. Elle gardait
   sinon 48px de rembourrage de chaque côté à l'intérieur d'un bloc déjà en
   retrait de 24 — 144px pris sur 360, et des champs deux fois plus étroits
   que le texte du reste du site. Ses angles sont remis à plat : touchant les
   bords, il n'y a plus de coin à adoucir, même raison que pour le panneau.
   Le liseré vert reste en haut, c'est lui qui désigne l'action attendue. */
@media (max-width: 46rem) {
  .contact__carte {
    margin-inline: calc(-1 * var(--main-gutter));
    border-radius: 0;
  }
}

.contact__carte > h2 { margin-bottom: var(--sp-6); }

/* Champs blancs sur la carte blanche : ce sont leurs contours qui les
   délimitent. Le crème du réglage général servait à les détacher d'un fond
   clair, il n'a plus lieu d'être ici. */
.contact__carte .field__control { background: var(--c-surface); }

/* Nom et email côte à côte dès que la place le permet. */
.form-grille {
  display: grid;
  grid-template-columns: 1fr;
  column-gap: var(--sp-5);
}

@media (min-width: 48rem) {
  .form-grille { grid-template-columns: 1fr 1fr; }
}

/* Mention légale à gauche, envoi à droite. */
.form-pied {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-5);
}

.form-pied .field__hint {
  max-width: var(--contact-hint-max);
  margin: 0;
}

/* Modalités pratiques, en quatre cases séparées par des filets. Plus étroit
   que le panneau et centré ; les textes, eux, restent alignés à gauche dans
   leur case. */
.infos {
  display: grid;
  grid-template-columns: 1fr;
  max-width: var(--infos-max);
  margin: var(--sp-8) auto 0;
  border-top: var(--border-w) solid var(--c-info-filet);
}

.info {
  padding-block: var(--info-pad-y);
  border-bottom: var(--border-w) solid var(--c-info-filet);
}

/* En deux colonnes, le filet vertical est porté par les cases de gauche. Les
   bords extérieurs ne prennent pas de rembourrage : le texte des cases reste
   ainsi aligné sur celui du reste du panneau. */
@media (min-width: 48rem) {
  .infos { grid-template-columns: 1fr 1fr; }

  .info { padding-inline: var(--info-pad-x); }
  .info:nth-child(odd) {
    padding-left: 0;
    border-right: var(--border-w) solid var(--c-info-filet);
  }
  .info:nth-child(even) { padding-right: 0; }
}

/* Même ocre que les surtitres du site : ces intitulés sont les repères du
   tableau, ils ne doivent pas se lire comme du texte secondaire. */
.info__label {
  font-size: var(--info-label-fs);
  letter-spacing: var(--eyebrow-tracking);
  text-transform: uppercase;
  font-weight: var(--fw-semibold);
  color: var(--c-secondary-text);
  margin: 0 0 var(--sp-2);
}

.info__titre {
  font-size: var(--info-titre-fs);
  margin: 0 0 var(--sp-3);
}

.info__texte { color: var(--c-text-muted); margin: 0; }

/* Communes séparées par une pastille, posée sur toutes sauf la première. */
.communes {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  column-gap: var(--commune-gap);
  row-gap: var(--commune-row-gap);
  list-style: none;
  margin: var(--sp-4) 0 0;
  padding: 0;
  font-size: var(--fs-xs);
  line-height: var(--lh-snug);
  color: var(--c-text-muted);
}

.communes li {
  display: flex;
  align-items: center;
  gap: var(--commune-gap);
  margin-top: 0; /* annule la règle générale li + li */
}

.communes li + li::before {
  content: "";
  width: var(--tag-point);
  height: var(--tag-point);
  border-radius: 50%;
  background: var(--c-secondary);
}

.field { margin-bottom: var(--sp-5); }

.field__label {
  display: block;
  font-size: var(--fs-sm);
  font-weight: var(--fw-medium);
  margin-bottom: var(--sp-2);
}

.field__hint {
  display: block;
  font-size: var(--fs-xs);
  color: var(--c-text-muted);
  margin-top: var(--sp-2);
}

.field__control {
  width: 100%;
  font: inherit;
  font-size: var(--fs-sm);
  color: var(--c-text);
  background: var(--c-bg);
  border: var(--border-w) solid var(--c-border-strong);
  border-radius: var(--radius-md);
  padding: var(--sp-3);
}

textarea.field__control { min-height: 9rem; resize: vertical; }

.field__control:disabled {
  background: var(--c-bg-subtle);
  color: var(--c-text-muted);
  cursor: not-allowed;
}

.field__control[aria-invalid='true'] { border-color: var(--c-danger); }

.field__error {
  display: block;
  font-size: var(--fs-xs);
  color: var(--c-danger);
  margin-top: var(--sp-2);
}

/* Piège à robots : hors écran, jamais au clavier, invisible aux lecteurs. */
.field--trap {
  position: absolute;
  left: -9999px;
  width: 1px;
  height: 1px;
  overflow: hidden;
}

/* Retour d'envoi. Reçoit le focus au clavier après réponse, d'où le tabindex. */
.form-status {
  border: var(--border-w) solid var(--c-border);
  border-left: 3px solid var(--c-border-strong);
  border-radius: var(--radius-sm);
  background: var(--c-bg-subtle);
  padding: var(--sp-4) var(--sp-5);
  margin-bottom: var(--sp-5);
  font-size: var(--fs-sm);
}
.form-status > :last-child { margin-bottom: 0; }

.form-status--ok {
  border-left-color: var(--c-success);
  background: var(--c-success-soft);
  color: var(--c-success);
}

.form-status--error {
  border-left-color: var(--c-danger);
  background: var(--c-danger-soft);
  color: var(--c-danger);
}

.form-status--ok a,
.form-status--error a { color: inherit; }

/* --- Téléphone ----------------------------------------------------------- */

/* Leurres insérés par le build. display:none et pas seulement une couleur :
   le navigateur exclut ce contenu du copier-coller et les lecteurs d'écran
   ne l'annoncent pas. Ne jamais remplacer par une astuce visuelle. */
.antispam { display: none; }

.phone { margin-top: var(--sp-5); }

/* Sous les boutons du hero : présent, mais en retrait de l'action principale. */
.hero__phone {
  margin-top: var(--sp-4);
  font-size: var(--fs-sm);
}

.hero__phone .phone__number { font-size: var(--hero-phone-fs); }

.phone__label {
  display: block;
  font-size: var(--fs-xs);
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  color: var(--c-text-muted);
  margin-bottom: var(--sp-1);
}

.phone__number {
  font-size: var(--fs-lg);
  font-weight: var(--fw-semibold);
  letter-spacing: var(--phone-tracking);
  color: var(--c-accent);
}

/* Souligné franc : sur la maquette le numéro se lit comme un lien. */
.phone__link {
  color: inherit;
  text-decoration: underline;
  text-decoration-thickness: var(--underline-w);
  text-underline-offset: var(--underline-offset);
}

/* --- Modalités (trois colonnes numérotées) -------------------------------- */

.etapes {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  list-style: none;
  margin: var(--etapes-gap) 0 0;
  padding: 0;
}

/* Le titre ne garde pas sa marge basse : l'écart avec les icônes est réglé
   par --etapes-gap seul, sinon les deux s'additionnent. Réservé au bandeau qui
   porte des étapes — avec un contenu ordinaire, la marge du titre est le seul
   écart disponible et le supprimer collerait le texte au titre. */
.section--bleed:has(.etapes) h2 { margin-bottom: 0; }

.etape {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  padding-inline: var(--sp-5);
}

.etape + .etape { margin-top: 0; } /* annule la règle générale li + li */

/* Filet reliant les pastilles. Posé sur l'étape et non sur la pastille : sa
   largeur vaut alors exactement l'écart entre deux centres de colonne, donc
   il s'arrête pile sur la pastille suivante. La position verticale est
   calculée, d'où la hauteur d'icône fixe. */
.etape:not(:last-child)::after {
  content: "";
  position: absolute;
  left: 50%;
  width: 100%;
  height: var(--border-w);
  top: calc(var(--etape-icon-h) + var(--sp-4) + var(--etape-num-size) / 2);
  background: var(--c-border-strong);
}

/* Séparateur vertical, sous les pastilles seulement. */
.etape + .etape::before {
  content: "";
  position: absolute;
  left: 0;
  top: calc(var(--etape-icon-h) + var(--sp-4) + var(--etape-num-size) + var(--sp-5));
  bottom: 0;
  width: var(--border-w);
  background: var(--c-border);
}

.etape__icone {
  display: flex;
  align-items: flex-end;
  justify-content: center;
  height: var(--etape-icon-h);
  color: var(--c-accent);
}

.etape__icone svg {
  width: var(--etape-icon-w);
  height: auto;
}

/* z-index : la pastille masque le filet qui passe derrière elle. */
.etape__numero {
  position: relative;
  z-index: 1;
  display: grid;
  place-items: center;
  width: var(--etape-num-size);
  height: var(--etape-num-size);
  margin-top: var(--sp-4);
  border-radius: 50%;
  background: var(--c-accent-mid);
  color: var(--c-accent-text);
  font-size: var(--etape-num-fs);
  font-weight: var(--fw-medium);
  letter-spacing: var(--tracking-wide);
  text-indent: var(--tracking-wide); /* recentre malgré l'interlettrage */
}

.etape--accent .etape__numero { background: var(--c-secondary); }

.etape__titre {
  font-family: var(--font-display);
  font-size: var(--fs-md);
  font-weight: var(--fw-bold);
  color: var(--c-accent);
  margin: var(--sp-5) 0 var(--sp-3);
}

/* Vert de la charte, comme le texte des cartes — pas le gris atténué. */
.etape__texte {
  font-size: var(--card-text-fs);
  color: var(--c-accent);
  margin: 0;
  max-width: var(--etape-texte-max);
}

/* Modalités en pile. Trois colonnes de 110px sur un téléphone ne tiennent
   pas : l'icône seule en occupe 72 et le texte tombe à deux mots par ligne.
   L'étape devient donc une ligne — icône à gauche, texte à droite — et le
   filet qui reliait les pastilles se redresse en un trait continu d'une icône
   à la suivante.

   Les pastilles numérotées disparaissent ici. Posées sous leur icône, elles
   coupaient la liaison en deux : le trait ne partait pas du dessin mais d'un
   disque situé plus bas, et l'écart entre les deux se lisait comme une
   rupture. Elles ne portent aucune information — le numéro est décoratif, la
   liste annonce déjà trois éléments — et rien n'est donc perdu. */
@media (max-width: 46rem) {
  .etapes {
    grid-template-columns: 1fr;
    row-gap: var(--etapes-row-gap);
    /* Le bloc se centre sous le titre au lieu de rester collé à gauche. Sa
       largeur est celle de son contenu — colonne d'icône, gouttière, et le
       texte borné par --etape-texte-max — et non celle de la section : le
       vide qui restait tout entier à droite se répartit des deux côtés.
       `fit-content` plutôt qu'une largeur calculée : le plafond du texte est
       en `ch`, unité qui dépend de la police du paragraphe et vaudrait autre
       chose ici. `max-width` le ramène dans la section quand l'écran est trop
       étroit pour ce bloc — c'est le cas sur un téléphone, où le centrage ne
       fait alors rien. */
    width: fit-content;
    max-width: 100%;
    margin-inline: auto;
  }

  .etape {
    display: grid;
    grid-template-columns: var(--etape-icon-w) 1fr;
    column-gap: var(--etape-col-gap);
    /* L'icône se cale sur le bloc entier, pas sur la ligne de titre : alignée
       en haut elle accompagnait le titre et laissait le texte descendre seul
       sous elle. Valeur héritée de la règle de base, redéclarée parce que la
       version à pastilles avait dû la contredire. */
    align-items: center;
    text-align: left;
    padding-inline: 0;
  }

  /* Voir le commentaire du bloc : la pastille coupait la liaison. */
  .etape__numero { display: none; }

  .etape__icone   { grid-area: 1 / 1; }
  .etape__contenu { grid-area: 1 / 2; }

  /* Le titre n'a plus l'icône au-dessus de lui pour l'en écarter. */
  .etape__titre { margin-top: 0; }

  /* La touche terracotta de la troisième modalité était portée par sa
     pastille. Sans elle, le bandeau devenait uniformément vert et « En visio »
     ne se distinguait plus des deux autres : l'icône la reprend. */
  .etape--accent .etape__icone { color: var(--c-secondary); }

  /* Le filet est écrit en deux moitiés qui se rejoignent dans l'écart entre
     deux étapes. Un seul segment ne pouvait pas marcher : il aurait fallu
     connaître, depuis une étape, la position de l'icône de la suivante. Or
     les icônes sont centrées dans des rangées dont la hauteur dépend du
     texte, différente à chaque fois — mesuré, le trait s'arrêtait 28px avant
     la deuxième icône et 40px avant la troisième, et paraissait pendre.

     Chaque moitié, elle, ne parle que de sa propre étape : l'icône y étant
     centrée, ses deux bords tombent à 50% ± la moitié de sa hauteur, quelle
     que soit la longueur du texte à côté. C'est ce que le centrage rend
     possible — la version à pastilles devait figer la hauteur de la rangée
     pour qu'un départ reste calculable. */
  .etape:not(:last-child)::after {
    left: calc(var(--etape-icon-w) / 2);
    transform: translateX(-50%);
    top: calc(50% + var(--etape-icon-h) / 2); /* bord bas de l'icône */
    bottom: 0;
    width: var(--border-w);
    height: auto;
  }

  /* Seconde moitié : du bas de l'étape précédente au bord haut de l'icône.
     Le séparateur de colonnes est réemployé — il n'y a plus de colonnes à
     séparer — plutôt que d'ajouter un élément au balisage pour un trait. */
  .etape + .etape::before {
    left: calc(var(--etape-icon-w) / 2);
    transform: translateX(-50%);
    top: calc(-1 * var(--etapes-row-gap));
    bottom: auto;
    height: calc(50% - var(--etape-icon-h) / 2 + var(--etapes-row-gap));
    /* Le beige clair du séparateur ne tiendrait pas la comparaison avec
       l'autre moitié : les deux ne font qu'un trait. */
    background: var(--c-border-strong);
  }
}

/* --- Callout ------------------------------------------------------------- */

.callout {
  border: var(--border-w) solid var(--c-border);
  border-left: 3px solid var(--c-accent);
  border-radius: var(--radius-sm);
  background: var(--c-bg-subtle);
  padding: var(--sp-4) var(--sp-5);
  margin-bottom: var(--sp-5);
}
.callout > :last-child { margin-bottom: 0; }

/* --- Placeholder (pages à rédiger) --------------------------------------- */

.placeholder {
  border: var(--border-w) dashed var(--c-border-strong);
  border-radius: var(--radius-lg);
  background: var(--c-bg-subtle);
  padding: var(--sp-7) var(--sp-5);
  text-align: center;
  color: var(--c-text-muted);
}
.placeholder > :last-child { margin-bottom: 0; }
.placeholder p { margin-inline: auto; }

/* --- Footer -------------------------------------------------------------- */

/* Pied de page sur fond vert foncé. Le filet terracotta du haut marque la
   rupture avec le contenu. overflow: hidden rogne le décor qui déborde. */
.site-footer {
  position: relative;
  overflow: hidden;
  border-top: var(--footer-rule-w) solid var(--c-secondary);
  background: var(--c-bg-inverse);
  color: var(--c-text-inverse);
  /* Zéro : l'écart avec le contenu est donné par la dernière section. */
  margin-top: 0;
  padding-top: var(--footer-pad-top);
  /* Retrait porté par le pied de page lui-même : ni les colonnes ni le
     logotype n'ont de marge propre, tout part donc de la même verticale.
     C'est aussi lui qui borne le filet de la barre légale, des deux côtés. */
  padding-inline: var(--footer-pad-left);
  font-size: var(--footer-fs);
}

/* Les liens héritent du fond clair par défaut : on les repasse en crème.
   Pas de changement de couleur au survol : seul le trait réagit, comme dans
   le menu du haut. */
.site-footer a { color: var(--c-text-inverse); }
.site-footer a:hover { color: var(--c-text-inverse); }

/* Exactement le traitement du menu principal : pas de soulignement au repos,
   un trait terracotta qui se déploie au survol et ressort par la droite, sans
   que le libellé ne change de couleur. Le numéro de téléphone est exclu — son
   soulignement permanent est ce qui le signale comme appelable. */
.site-footer a:not(.phone__link) {
  position: relative;
  text-decoration: none;
}

.site-footer a:not(.phone__link)::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: calc(-1 * var(--nav-underline-gap));
  height: var(--nav-underline-w);
  background: var(--c-secondary);
  transform: scaleX(0);
  transform-origin: right center;
  transition: transform var(--dur-base) var(--ease);
}

.site-footer a:not(.phone__link):hover::after,
.site-footer a:not(.phone__link):focus-visible::after {
  transform: scaleX(1);
  transform-origin: left center;
}

.site-footer__inner {
  position: relative;
  z-index: 1;
  display: grid;
  gap: var(--sp-6) var(--footer-col-gap);
  /* Toutes les colonnes dimensionnées par leur contenu, et non en fractions :
     c'est ce qui rend les écarts réellement constants. justify-content évite
     que les pistes `auto` ne s'étirent pour absorber la place restante, ce qui
     rouvrirait les écarts. */
  grid-template-columns: auto auto auto auto;
  justify-content: start;
  padding-bottom: var(--sp-8);
  /* Réserve pour le graphique. Exprimée en supplément du retrait déjà porté
     par le pied de page, pour que la distance totale au bord droit vaille
     bien --footer-pad-right. La barre légale, elle, n'en a pas. */
  padding-right: calc(var(--footer-pad-right) - var(--footer-pad-left));
}

@media (max-width: 62rem) {
  .site-footer__inner { grid-template-columns: repeat(auto-fit, minmax(13rem, 1fr)); }
}

/* Écart propre après le logotype, plus large qu'entre les colonnes de liens.
   Une grille n'ayant qu'une seule valeur d'écart, le supplément est porté ici.
   C'est une marge à droite : elle ne touche pas l'alignement à gauche. */
.site-footer__marque {
  margin-right: calc(var(--footer-logo-gap) - var(--footer-col-gap));
}

.site-footer__baseline {
  margin: var(--sp-5) 0 var(--sp-4);
  max-width: 34ch;
}

.site-footer__domaine {
  margin: 0;
  color: var(--c-inverse-muted);
}

/* Intitulé de colonne : capitales espacées, terracotta éclairci pour rester
   lisible sur le vert foncé — la teinte de la charte n'y suffit pas. */
.site-footer__heading {
  font-size: var(--footer-heading-fs);
  text-transform: uppercase;
  letter-spacing: var(--footer-heading-tracking);
  color: var(--c-inverse-heading);
  margin-bottom: var(--sp-5);
}

/* Lignes resserrées dans les colonnes. L'espace sous l'intitulé, lui, ne
   bouge pas : il est porté par .site-footer__heading. */
.site-footer__col .bare li + li { margin-top: var(--footer-link-gap); }

.site-footer__tel {
  color: var(--c-text-inverse);
  font-size: var(--footer-tel-fs);
}

.site-footer__legal {
  position: relative;
  z-index: 1;
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  gap: var(--sp-4);
  border-top: var(--border-w) solid var(--c-inverse-muted);
  padding-block: var(--footer-legal-pad-block);
  /* Aucun retrait propre : celui du pied de page suffit. La barre est donc
     alignée sur le logotype à gauche, et ses liens comme son filet s'arrêtent
     à la même distance du bord à droite — la réserve du graphique ne la
     concerne pas. */
}
.site-footer__legal p { margin: 0; max-width: none; }

/* Crédit de réalisation : plus effacé que le reste de la barre. Il informe,
   il ne revendique pas — le copyright à côté, lui, reste pleinement lisible. */
.site-footer__credit { color: var(--c-inverse-muted); }

.site-footer__legal-liens {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-6);
}

/* Bloc haut : colonnes et décor. Sa seule raison d'être est de rogner le
   décor au niveau du filet, pour qu'il ne descende pas dans la barre légale.

   Il annule puis restitue les retraits du pied de page — latéraux et haut —
   de sorte que ses bords coïncident avec ceux du pied de page. Sans cela le
   décor serait coupé en dedans : 40px trop tôt sur les côtés, et surtout
   sous le filet orange en haut, alors que l'arc doit y monter. Seul le bas
   rogne réellement, et c'est ce qu'on cherche. */
.site-footer__haut {
  position: relative;
  overflow: hidden;
  margin-inline: calc(-1 * var(--footer-pad-left));
  padding-inline: var(--footer-pad-left);
  margin-top: calc(-1 * var(--footer-pad-top));
  padding-top: var(--footer-pad-top);
}

/* Le contenu passe au-dessus du décor. Sans cela, un décor un peu large
   viendrait recouvrir les liens de la dernière colonne. */
.site-footer__inner,
.site-footer__legal {
  position: relative;
  z-index: 1;
}

/* Décor de l'angle droit, hors flux et sous le contenu. Le dessin est plus
   haut que le pied de page : il est ancré en haut et déborde vers le bas,
   où l'overflow du conteneur le rogne. Les deux décalages disent de combien
   il sort du cadre, d'où le signe négatif ici plutôt que dans le token. */
.site-footer__decor {
  position: absolute;
  top: calc(-1 * var(--footer-decor-haut));
  right: calc(-1 * var(--footer-decor-droite));
  width: var(--footer-decor-w);
  height: auto;
  z-index: 0;
  pointer-events: none;
}

/* --- Utilitaires --------------------------------------------------------- */

.bare { list-style: none; padding: 0; margin: 0; }
.bare li + li { margin-top: var(--sp-2); }

.muted { color: var(--c-text-muted); }

.lead { font-size: var(--fs-md); color: var(--c-text-muted); }

.tag-row {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-2);
  list-style: none;
  padding: 0;
  margin: 0 0 var(--sp-4);
}
.tag-row li { margin: 0; }
.tag-row li span {
  display: inline-block;
  font-size: var(--fs-xs);
  padding: var(--sp-1) var(--sp-3);
  border: var(--border-w) solid var(--c-border);
  border-radius: var(--radius-sm);
  background: var(--c-bg);
  color: var(--c-text-muted);
}

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