/*
Theme Name: Nicolas Guichard
Author: Nicolas Guichard
Description: Thème sur-mesure pour le site de Nicolas Guichard.
Version: 0.1.0
Text Domain: nicolasguichard
*/

/*
Convention CSS : BEM (.bloc, .bloc__element, .bloc--modificateur).
Exception assumée : quelques classes utilitaires courtes (.display,
.muted) pour les styles typographiques transverses directement liés
aux tokens du theme.json, plutôt que de les redéclarer dans chaque
__élément.
*/

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

/* Espacement minimal des galeries photo (bloc Galerie de Gutenberg) :
   --wp--style--gallery-gap-default est le point d'extension prévu par
   WordPress pour qu'un thème fixe l'espacement par défaut d'une
   galerie sans gap explicite (cf. le commentaire "should be used by
   themes that want to set a default gap on the gallery" dans
   wp-includes/blocks/gallery.php). Cette variable alimente à la fois
   le calcul de largeur des images (--wp--style--unstable-gallery-gap)
   et la propriété gap réellement appliquée : les deux restent donc
   synchronisés, sans début de recouvrement des images en ligne.
   Passer par un override direct de `gap` (ex. gap: max(…) !important)
   casse cette synchronisation : la largeur des images reste calculée
   avec l'ancien espacement pendant que le gap affiché grandit, ce qui
   fait déborder la ligne et renvoyer une image à la ligne suivante
   (répété sur la galerie Simuleau, 2 images en ligne). */
:root {
	--wp--style--gallery-gap-default: var(--wp--preset--spacing--sm);
}

/*
Échelle typographique (taille : interlettre / interligne) : les
tailles sont posées en tokens theme.json (fontSizes), chaînés en
quarte juste (ratio 4/3) depuis --font-size--base. L'interlettre et
l'interligne restent en dur au fil du CSS (pas de preset pour ces
propriétés côté theme.json). Tailles indiquées ci-dessous à la valeur
haute de --font-size--base (viewport large, voir le fluide ci-après).
- --font-size--display (~56.9px) : -2px    / 1.1
- --font-size--title (~42.7px), h1 : 0px    / 1.1
- --font-size--heading (32px) : -1.2px / 1.1
- --font-size--subheading (24px), .carte-projet__titre / .grille-projets__titre : -1px / 1.2
- --font-size--base (18px), body : 0px  / 1.2

Fluide : --font-size--base (theme.json) et --spacing--xs (theme.json)
sont posés en clamp(min, min + pente*vw, max) plutôt qu'en valeur fixe.
Comme toute la suite de la gamme (fontSizes en quarte juste, spacingSizes
en nombre d'or) est chaînée par calc() depuis ces deux tokens, la
fluidité se propage automatiquement à toutes les tailles de texte et
tous les espacements, sans autre changement CSS.
Bornes retenues : 22.5rem/360px (petit mobile) -> 87.5rem/1400px
(= --wp--style--global--wide-size, déjà posé dans theme.json).
- --font-size--base : 16px -> 18px (valeur fixe d'origine, gardée en haut de fourchette)
- --spacing--xs : 16px -> 24px (valeur fixe d'origine, gardée en haut de fourchette)
Calcul (formule Utopia) : pente = (max-min)/(largeurMax-largeurMin) ;
ordonnée à l'origine = min - largeurMin*pente ; clamp(min, ordonnée +
pente*100vw, max).
*/

@media (prefers-reduced-motion: no-preference) {
	html {
		scroll-behavior: smooth;
	}
}

body {
	margin: 0;
	background: var(--wp--preset--color--background);
	color: var(--wp--preset--color--text);
	font-family: var(--wp--preset--font-family--bricolage);
	font-size: var(--wp--preset--font-size--base);
	font-weight: 400;
	letter-spacing: 0;
	line-height: 1.2;
}

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

a {
	color: var(--wp--preset--color--accent);
	text-decoration: none;
}

a:hover {
	text-decoration: underline;
}

.muted {
	color: var(--wp--preset--color--text-muted);
	font-size: var(--wp--preset--font-size--muted);
}

.display {
	font-size: var(--wp--preset--font-size--display);
	font-weight: 700;
	letter-spacing: -2px;
	line-height: 1.1;
	margin: 0 0 var(--wp--preset--spacing--md) 0;
}

h1 {
	font-size: var(--wp--preset--font-size--title);
	font-weight: 700;
	line-height: 1.1;
	margin: 0 0 var(--wp--preset--spacing--sm) 0;
	text-wrap: balance;
}

/* En-tête du site */
.site-header {
	display: flex;
	align-items: center;
	justify-content: space-between;
	padding: var(--wp--preset--spacing--sm) var(--wp--preset--spacing--md);
}

.site-header__brand {
	display: flex;
	align-items: center;
	gap: var(--wp--preset--spacing--xs);
	color: var(--wp--preset--color--text);
}

.site-header__avatar {
	width: 2rem;
	height: 2rem;
	border-radius: 50%;
	background: var(--wp--preset--color--background-cool);
	display: inline-block;
	object-fit: cover;
}

.site-header__nav ul {
	list-style: none;
	display: flex;
	gap: var(--wp--preset--spacing--sm);
	margin: 0;
	padding: 0;
}

/* Pied de page du site */
.site-footer {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	justify-content: space-between;
	gap: var(--wp--preset--spacing--sm);
	padding: var(--wp--preset--spacing--md);
	background: var(--wp--preset--color--background-cool);
	border-top: 1px solid var(--wp--preset--color--background-cool);
}

.site-footer__brand {
	display: flex;
	flex-direction: column;
}

.site-footer__nav ul {
	list-style: none;
	display: flex;
	gap: var(--wp--preset--spacing--sm);
	margin: 0;
	padding: 0;
}

.site-footer__legal {
	display: flex;
	gap: var(--wp--preset--spacing--sm);
}

.site-main {
	padding: var(--wp--preset--spacing--md);
}

/* Fond gris froid derrière la liste de tags + la grille (home, archive
   de tag mutualisée, et reprise en bas de la fiche projet).
   Marge négative pour toucher les bords du site-main, padding pour
   garder le contenu aligné avec le reste de la page. */
.section-projets {
	background: var(--wp--preset--color--background-cool);
	margin: 0 calc( -1 * var(--wp--preset--spacing--md) );
	padding: var(--wp--preset--spacing--md);
}

.tag-list {
	display: flex;
	flex-wrap: wrap;
	margin: 0 0 var(--wp--preset--spacing--md) 0;
	padding: 0;
	list-style: none;
}

/* Le bleu de .tag-list vient de la règle générale sur `a` (couleur
   réservée aux éléments cliquables) : rien à redéclarer ici. */

.tag-list a {
	display: inline-block;
	border: 1px solid currentColor;
	border-radius: 999px;
	padding: 0em .9em;
}

.tag-list--home {
	gap: 1em;
	line-height: 2.2;
}

/* outline plutôt qu'un border-width plus épais, text-shadow plutôt
   qu'un font-weight plus gras : ni l'un ni l'autre ne participe au
   layout, donc le passage à l'état actif ne décale ni la largeur ni
   la hauteur de la pill (contrairement à border-width/font-weight,
   qui redimensionnent réellement la boîte et son texte). */
.tag-list--home a.is-active {
	text-decoration: underline;
	font-weight: 500;
	outline: 1px solid currentColor;
	outline-offset: 0;
}

.categorie-selectionnee {
	font-size: var(--wp--preset--font-size--heading);
	letter-spacing: -1.2px;
	line-height: 1.1;
	margin: 0 0 var(--wp--preset--spacing--md) 0;
}

.categorie-selectionnee__nom {
	font-weight: 500;
}

.categorie-selectionnee__description {
	font-weight: 200;
}

.categorie-selectionnee__separateur {
	font-weight: 500;
}

/* Grille en masonry posée par assets/js/masonry-projets.js (Masonry.js) :
   positionnement en absolu, largeur de colonne calculée en JS pour
   poser autant de colonnes de 350px minimum que la largeur disponible
   le permet, sans palier à maintenir à la main.
   Choisi plutôt que les colonnes CSS (qui remplissent la colonne 1 en
   entier avant de passer à la colonne 2) pour que la 1ʳᵉ rangée reste
   fidèle à l'ordre hiérarchisé donné aux projets ; l'algorithme place
   ensuite chaque carte suivante dans la colonne la plus courte, ce qui
   peut légèrement dévier de cet ordre plus loin dans la grille.
   position: relative nécessaire pour que Masonry positionne les cartes
   en absolu par rapport à ce conteneur. La hauteur du conteneur est
   fixée par Masonry lui-même (JS) une fois la mise en page calculée.
   column-gap n'a ici aucun effet visuel (pas de multi-colonnes CSS) :
   posé uniquement pour que masonry-projets.js puisse lire sa valeur
   résolue en px via getComputedStyle et garder un seul token comme
   source de vérité pour l'écart entre cartes. */
.grille-projets {
	position: relative;
	column-gap: var(--wp--preset--spacing--md);
}

.carte-projet {
	margin-bottom: var(--wp--preset--spacing--md);
}

.carte-projet__lien {
	color: inherit;
	display: block;
}

.carte-projet__lien:hover {
	text-decoration: none;
}

.carte-projet__visuel {
	margin-bottom: var(--wp--preset--spacing--xs);
	background: var(--wp--preset--color--background-cool);
}

.carte-projet__visuel img {
	width: 100%;
}

.carte-projet__titre {
	font-size: var(--wp--preset--font-size--subheading);
	font-weight: 500;
	letter-spacing: -1px;
	line-height: 1.2;
	margin: 0 0 .35em 0;
	text-wrap: balance;
}

.carte-projet__accroche {
	font-weight: 200;
}

.tag-list--carte {
	gap: .5em;
}

.tag-list--carte a,
.tag-list--detail a {
	padding: .3em .6em .35em;
}

.tag-list--carte a {
	font-size: var(--wp--preset--font-size--muted);
}

/* Fiche projet dépliée : fond gris chaud sur l'ensemble (titre, texte,
   image), plein-bord comme .section-projets (marge négative + padding
   pour toucher les bords du site-main sans décaler le contenu). */
/* --projet-detail-texte-width : largeur de .projet-detail__texte dans
   .projet-detail__corps (flex 2 1 0 face à flex 1 1 0 sur .meta, écart
   --spacing--lg entre les deux). Calculée ici pour être réutilisable
   ailleurs dans la fiche (légendes des visuels notamment) sans dupliquer
   la logique flex ; réajustée dans les deux mêmes points de rupture que
   .projet-detail__corps plus bas.
   Le calc() ci-dessous utilise 100cqw (container query units), pas 100%.
   Un % dans un calc() stocké en custom property se résout, à l'usage,
   contre le bloc conteneur de l'élément qui consomme la variable — pas
   contre .projet-detail où elle est déclarée. Pour une légende (figcaption)
   posée directement dans .projet-detail__visuels, ça tombait juste par
   coïncidence (même largeur de conteneur), mais dès qu'elle est imbriquée
   dans un bloc Colonnes ou Galerie, le % se serait résolu contre la
   colonne/galerie (proche de la largeur de l'image) au lieu du texte.
   container-type ci-dessous fait de .projet-detail un contexte de
   container query : cqw reste ancré à SA largeur à lui, quelle que soit
   la profondeur d'imbrication de l'élément qui lit la variable. */
.projet-detail {
	--projet-detail-texte-width: calc( ( 100cqw - var(--wp--preset--spacing--lg) ) * 2 / 3 );
	container-type: inline-size;
	container-name: projet-detail;
	background: var(--wp--preset--color--background-warm);
	margin: 0 calc( -1 * var(--wp--preset--spacing--md) ) var(--wp--preset--spacing--lg) calc( -1 * var(--wp--preset--spacing--md) );
	padding: var(--wp--preset--spacing--lg) var(--wp--preset--spacing--md);
}

.projet-detail__titre {
	margin-bottom: var(--wp--preset--spacing--md);
	text-wrap: balance;
}

.projet-detail__accroche {
	font-weight: 200;
}

/* Visuels de la fiche détail : contenu natif de l'article (blocs Gutenberg
   Image/Galerie/Intégration), saisi librement par Nicolas après le bloc
   texte/crédits/date/tags. */
.projet-detail__visuels {
	/* Plafond de hauteur des vidéos : lu par la vidéo elle-même et par le
	   cadre de la pastille de lecture, qui doit se caler sur elle (voir
	   plus bas). Token plutôt que valeur répétée, pour que les deux
	   règles ne puissent pas diverger. */
	--projet-detail-visuel-max-height: 60vw;
	margin-top: var(--wp--preset--spacing--lg);
}

/* Seule option de mise en page Gutenberg prise en charge pour l'instant :
   "Grande largeur" remplit toute la largeur disponible dans la fiche
   projet (celle du bloc .projet-detail lui-même, fluide, d'où l'absence
   de valeur fixe). Les autres options (pleine largeur, aligné à
   gauche/droite) n'ont pas encore d'effet — à ajouter si besoin. */
.projet-detail__visuels > .alignwide {
	max-width: none;
	width: 100%;
}

/* Légendes des visuels : même écart que vignette/titre de carte-projet
   (--spacing--xs), gris muted, largeur alignée sur le paragraphe
   principal de la fiche (voir --projet-detail-texte-width plus haut).
   min(..., 100%) : plafond nécessaire pour les blocs Colonnes (visuels
   posés deux par deux, ex. novae) où la colonne d'une image est plus
   étroite que --projet-detail-texte-width ; sans ce plafond la légende
   déborderait de sa colonne (et potentiellement de la page) au lieu de
   simplement se caler sur la largeur disponible. */
.projet-detail__visuels figcaption,
.infos__section figcaption  {
	margin-top: var(--wp--preset--spacing--xs);
	margin-bottom: var(--wp--preset--spacing--sm);
	color: var(--wp--preset--color--text-muted);
	width: min(var(--projet-detail-texte-width), 100%);
}

/* Légendes des images en galerie : le bloc Galerie de Gutenberg les pose
   par défaut en incrustation blanche sur l'image (figcaption en
   position absolute, fond dégradé, texte blanc, ombre portée), un
   habillage très différent de la légende d'une image seule ci-dessus.
   On annule cet habillage pour retrouver le même style (texte gris
   muted sous l'image) mais sans reprendre width: var(--projet-detail-texte-width) :
   dans une galerie, chaque image a sa propre largeur (mise en page en
   flex façon galerie justifiée, voir cote à cote sur novae par ex.),
   donc la légende doit rester à 100% de SA colonne/image, pas de la
   largeur du texte de description.
   Sélecteurs recopiés avec les mêmes classes que le bloc gallery de
   WordPress (.has-nested-images, figure.wp-block-image) : nécessaire
   pour égaler/dépasser leur spécificité et l'emporter sur les styles de
   wp-includes/css/dist/block-library/style.css, chargé après le CSS du
   thème. */
.projet-detail__visuels .wp-block-gallery.has-nested-images figure.wp-block-image::before,
.projet-detail__visuels .wp-block-gallery.has-nested-images figure.wp-block-image:has(figcaption)::before {
	content: none;
}

.projet-detail__visuels .wp-block-gallery.has-nested-images figure.wp-block-image figcaption {
	position: static;
	width: 100%;
	max-height: none;
	overflow: visible;
	margin-top: var(--wp--preset--spacing--xs);
	margin-bottom: var(--wp--preset--spacing--sm);
	padding: 0;
	color: var(--wp--preset--color--text-muted);
	font-size: inherit;
	text-align: left;
	text-shadow: none;
	background: none;
}

/* Vidéos : le bloc Gutenberg pose un style inline "aspect-ratio: W / H"
   sur la balise <video> (dimensions réelles du fichier). Combiné à un
   max-height, ce aspect-ratio inline fait calculer la largeur à partir
   de la hauteur plutôt que l'inverse : le navigateur ne remplit alors
   plus le conteneur et cale la vidéo, minuscule, dans un coin. On
   neutralise cet aspect-ratio (d'où le !important, obligatoire pour
   passer devant un style inline) pour revenir au calcul standard
   largeur → hauteur d'un élément remplacé.
   width: 100% (et non auto) reste nécessaire pour qu'une vidéo de
   résolution modeste remplisse quand même son conteneur (ex. colonne
   d'un bloc Colonnes plus large que sa résolution native) au lieu de
   rester à sa taille en pixels ; max-height vient seulement plafonner
   le résultat pour les ratios portrait, et le navigateur recalcule
   alors la largeur au même ratio.
   Le plafond est exprimé en vw (proportionnel à la largeur de la zone,
   quasi plein viewport ici) et non en vh : une limite en vh dépend de la
   hauteur de la fenêtre et bridait aussi les vidéos paysage sur les
   écrans peu hauts. 60vw laisse passer toutes les vidéos 16/9 et plus
   larges (marge au-delà du seuil exact 56.25vw) et ne coupe que les
   ratios plus hauts que larges.
   object-position : filet de sécurité si une vidéo se retrouve un jour
   avec une boîte plus large que son image utile (ex. object-fit imposé
   ailleurs) ; la zone visible est alors ferrée à gauche plutôt que
   centrée. */
.projet-detail__visuels video {
	aspect-ratio: auto !important;
	width: 100%;
	height: auto;
	max-height: var(--projet-detail-visuel-max-height);
	object-position: left;
}

/* Classe additionnelle .screencast (posée sur le bloc vidéo Gutenberg) :
   détache la vidéo du fond blanc pour lui donner l'allure d'une capture
   d'écran macOS. Ombre neutre (pas de teinte grise) et large pour
   l'effet "flottant" typique des captures macOS, sans halo dur.
   La marge de part et d'autre (et la largeur réduite d'autant, pour ne
   pas déborder du conteneur) dégage l'espace où cette ombre se déploie ;
   sans elle, l'ombre serait coupée par les bords de la colonne. */
.screencast video {
	display: block;
	width: calc(100% - 2 * var(--wp--preset--spacing--sm));
	margin: var(--wp--preset--spacing--lg) auto;
	border-radius: 11px;
	box-shadow: 0 20px 50px rgba(0, 0, 0, 0.3);
}

/* Pastille de lecture, injectée par assets/js/lecteur-video.js sur les
   vidéos à contrôles qui ne démarrent pas seules. Elle compense
   l'absence de gros bouton central dans Chrome et le fait que les
   commandes natives ne sont pas stylables. Grammaire reprise des tags
   et de l'état actif : fond blanc, liseret 1px bleu, épaissi à 2px au
   survol. */
.lecteur-video {
	position: relative;
}

/* Curseur pointeur sur toute la zone avant lecture, pas seulement sur
   le disque : simple écho visuel du liseret ci-dessous (même logique
   que les cartes projet, où toute la carte affiche déjà ce curseur
   pour un seul lien). Le clic hors du disque n'est géré par notre JS
   que sur le bouton ; Chrome/Safari font en plus basculer play/pause
   au clic sur l'image elle-même (comportement natif, hors contrôle
   du thème), Firefox non. */
.lecteur-video:not(.is-playing) {
	cursor: pointer;
}

/* Le cadre doit épouser la vidéo, pas la largeur disponible : dès que
   le plafond de hauteur s'applique (formats portrait), la vidéo devient
   plus étroite que son conteneur et reste ferrée à gauche, donc un
   bouton centré sur le cadre tomberait à côté de l'image. On rejoue ici
   le calcul du navigateur (hauteur plafond x ratio). Le ratio est posé
   en JS à la lecture des métadonnées ; tant qu'il est inconnu, le
   facteur 100 revient à ne poser aucune limite. */
.projet-detail__visuels .lecteur-video {
	max-width: calc( var(--projet-detail-visuel-max-height) * var(--lecteur-video-ratio, 100) );
}

.lecteur-video__bouton {
	position: absolute;
	top: 50%;
	left: 50%;
	transform: translate( -50%, -50% );
	display: flex;
	align-items: center;
	justify-content: center;
	/* Plafonnée en rem pour les grandes vidéos, en % pour ne pas manger
	   une vignette étroite (vidéo en colonne, petit écran). */
	width: min( 4.5rem, 25% );
	aspect-ratio: 1;
	padding: 0;
	border: 1px solid var(--wp--preset--color--accent);
	border-radius: 50%;
	background: var(--wp--preset--color--background);
	color: var(--wp--preset--color--accent);
	cursor: pointer;
	transition: border-width .15s ease, opacity .15s ease, visibility .15s ease;
}

.lecteur-video__bouton::before {
	content: "";
	width: 30%;
	height: 34%;
	/* Décalage optique : un triangle centré géométriquement paraît trop
	   à gauche dans un cercle. */
	transform: translateX( 12% );
	background: currentColor;
	clip-path: polygon( 0 0, 100% 50%, 0 100% );
}

/* Sur le cadre entier (donc dès que le curseur est sur la vidéo) et pas
   seulement sur le bouton : survoler l'image doit déjà signaler qu'elle
   est cliquable, pas seulement le petit disque au centre. */
.lecteur-video:hover .lecteur-video__bouton {
	border-width: 2px;
}

.lecteur-video__bouton:focus-visible {
	outline: 1px solid currentColor;
	outline-offset: 3px;
}

/* Pendant la lecture, la pastille s'efface et rend la main aux
   contrôles natifs. visibility (et pas seulement opacity) pour la
   sortir aussi du parcours clavier. */
.lecteur-video.is-playing .lecteur-video__bouton {
	opacity: 0;
	visibility: hidden;
}

/* Dans un bloc Colonnes, une image utilise par défaut max-width: 100%
   (règle cœur WordPress) et non width: 100% : si sa résolution native
   est plus petite que sa colonne, elle ne la remplit pas. La vidéo, elle,
   est déjà forcée en width: 100% ci-dessus. Résultat sans cette règle :
   à ratio identique, l'image et la vidéo n'ont pas la même largeur
   affichée, donc pas la même hauteur. On force ici la même règle sur
   l'image, mais seulement dans les Colonnes (pas sur les visuels seuls
   en pleine largeur, où le comportement actuel convient). */
.projet-detail__visuels .wp-block-columns img {
	width: 100%;
	height: auto;
}

/* Texte en 2/3, tags/date/crédits en 1/3 */
.projet-detail__corps {
	display: flex;
	gap: var(--wp--preset--spacing--lg);
}

.projet-detail__texte {
	flex: 2 1 0;
}

.projet-detail__meta {
	flex: 1 1 0;
	color: var(--wp--preset--color--text-muted);
}

/* Au-delà du point où .grille-projets passe à 4 colonnes, le texte/meta
   de la fiche projet ne s'étire plus sur toute la largeur du fond
   plein-bord mais reste contenu dans la largeur de 3 cartes de la
   grille (350px, le plancher LARGEUR_MIN_COLONNE de
   assets/js/masonry-projets.js) + 2 écarts entre elles, ferré à
   gauche (pas de centrage).
   106.75rem = 1708px, seuil mesuré au Playwright (viewports 1707px:
   3 colonnes, 1708px: 4 colonnes) ; --wp--preset--spacing--md est
   alors figé à sa valeur haute, au-delà des 1400px où --spacing--xs
   cesse d'être fluide (voir plus haut). */
@media (min-width: 106.75rem) {
	.projet-detail {
		--projet-detail-corps-max-width: calc( 3 * 350px + 2 * var(--wp--preset--spacing--md) );
		--projet-detail-texte-width: calc( ( var(--projet-detail-corps-max-width) - var(--wp--preset--spacing--lg) ) * 2 / 3 );
	}

	.projet-detail__titre,
	.projet-detail__corps {
		max-width: var(--projet-detail-corps-max-width);
	}
}

/* En dessous du point où .grille-projets repasse à 1 colonne, la
   répartition 2/3 texte / 1/3 meta n'a plus de sens sur une seule
   colonne : le texte prend toute la largeur, les meta infos
   s'enchaînent juste en dessous, également en pleine largeur (stretch,
   valeur par défaut de align-items sur l'axe croisé d'un flex column).
   54rem = 864px, seuil mesuré au Playwright (864px : 1 colonne,
   865px : 2 colonnes). */
@media (max-width: 54rem) {
	.projet-detail {
		--projet-detail-texte-width: 100cqw;
	}

	.projet-detail__corps {
		flex-direction: column;
	}

	.projet-detail__texte,
	.projet-detail__meta {
		flex: 1 1 auto;
	}
}

.tag-list--detail {
	gap: .5em;
}

.tag-list--detail a {
	color: var(--wp--preset--color--text-muted);
}

.projet-detail__texte p,
.projet-detail__meta p {
	margin: 0 0 var(--wp--preset--spacing--xs) 0;
}

/* Page légale (politique de confidentialité) : même traitement que la
   fiche projet (fond gris chaud plein-bord, texte 2/3 / colonne 1/3
   réservée pour plus tard). */
.page-legale {
	background: var(--wp--preset--color--background-warm);
	margin: 0 calc( -1 * var(--wp--preset--spacing--md) );
	padding: var(--wp--preset--spacing--lg);
}

.page-legale__titre {
	margin-bottom: var(--wp--preset--spacing--md);
}

.page-legale__corps {
	display: flex;
	gap: var(--wp--preset--spacing--lg);
}

.page-legale__texte {
	flex: 2 1 0;
}

.page-legale__meta {
	flex: 1 1 0;
}

.page-legale__texte p {
	margin: 0 0 var(--wp--preset--spacing--sm) 0;
}

/* Bloc Infos (pied de page, sur toutes les pages) : titre + les deux
   sections (apropos, contact) posés sur une même grille pour que les
   fonds gris chaud/froid démarrent au-dessus de "Infos", comme le fond de .projet-detail démarre
   au-dessus de son titre. .infos__content passe en display: contents
   pour laisser ses enfants (les deux .infos__section, saisis en HTML
   dans l'éditeur) devenir des items de la grille au même titre que le
   titre, sans rien changer à l'éditable Gutenberg.
   .infos__contact-fond occupe seul la 1ʳᵉ ligne de la colonne contact :
   un simple aplat gris froid, de la même hauteur que .infos__titre
   (calculée par la grille), pour que "Contact" démarre en 2ᵉ ligne,
   aligné avec "À propos", sans valeur codée en dur.
   Contrairement à .section-projets et .projet-detail (posés dans
   .site-main, d'où la marge négative qui compense son padding),
   .infos est un frère de .site-main (posé dans footer.php, après
   </main>) : il touche déjà les bords du viewport sans rien à
   compenser, donc pas de marge négative ici. */
.infos {
	display: grid;
	grid-template-columns: minmax(min(32rem, 100%), 2fr) minmax(min(16rem, 100%), 1fr);
	margin: 0 0 var(--wp--preset--spacing--lg) 0;
}

.infos__titre {
	grid-column: 1;
	grid-row: 1;
	margin-bottom: 0;
	padding: var(--wp--preset--spacing--lg) var(--wp--preset--spacing--lg) 0 var(--wp--preset--spacing--lg);
}

.infos__contact-fond {
	grid-column: 2;
	grid-row: 1;
}

.infos__content {
	display: contents;
}

.infos__section--apropos {
	grid-column: 1;
	grid-row: 2;
	padding: 0 var(--wp--preset--spacing--lg) var(--wp--preset--spacing--lg) var(--wp--preset--spacing--lg);
}

.infos__section--contact {
	grid-column: 2;
	grid-row: 2;
	color: var(--wp--preset--color--text-muted);
	padding: 0 var(--wp--preset--spacing--lg) var(--wp--preset--spacing--lg) var(--wp--preset--spacing--lg);
}

/* "À propos" et "Contact" reprennent le poids de .projet-detail__accroche,
   avec l'interlignage de .display pour que "À propos" enchaîne comme une
   ligne du titre plutôt que comme un nouveau bloc. */
.infos__content h2 {
	font-size: var(--wp--preset--font-size--display);
	font-weight: 200;
	line-height: 1.1;
	margin: 0 0 var(--wp--preset--spacing--sm) 0;
}

.infos__content p {
	margin: 0 0 var(--wp--preset--spacing--sm) 0;
}

/* En dessous de 67.5rem/1080px, la grille repasse en une seule colonne :
   "Infos", "À propos" et "Contact" s'enchaînent l'un sous l'autre plutôt
   que de comprimer les deux colonnes. Testé (Playwright, largeurs 480 à
   1400px) : même avec --font-size--base et --spacing--xs fluides
   (voir plus haut), la colonne "Contact" déborde dès ~920px, "Contact"
   étant un mot-titre de taille display insécable ; le fluide adoucit la
   bascule mais ne suffit pas à l'éviter. 1080px garde une marge de
   sécurité au-delà de ce seuil mesuré.
   .infos__contact-fond n'a plus lieu d'être (il n'existe que pour aligner
   "Contact" sur la 2ᵉ colonne) ; sa hauteur manquante est reprise par un
   padding-top sur .infos__section--contact. */
@media (max-width: 67.5rem) {
	.infos {
		grid-template-columns: 1fr;
	}

	.infos__contact-fond {
		display: none;
	}

	.infos__section--contact {
		grid-column: 1;
		grid-row: 3;
		padding-top: var(--wp--preset--spacing--lg);
	}
}
