/* ==================================================================== */
/* Fiona Lebre — PAGE PROJET                                            */
/* ==================================================================== */
/*
 * LA FEUILLE DE CONTACT ET LE TIRAGE.
 *
 * Trois zones, de gauche à droite :
 *   colonnes 1-2  vides — l'index a disparu, et ce vide est le sujet ;
 *   colonnes 3-6  un grand cadre blanc, pleine hauteur, où une seule
 *                 image est développée, légendée en bas sur le carton ;
 *   colonnes 7-8  la feuille de contact — toutes les images du projet en
 *                 vignettes. On en survole une, elle passe au centre.
 *
 * C'EST LE GESTE DU LABORATOIRE : on lit la planche, on choisit une vue,
 * on la tire en grand. Le site avait déjà cette grammaire ailleurs — la
 * planche de l'Overview d'où un tirage s'envole — et la page projet en est
 * la version intime : une seule série, et le choix reste sous la main.
 *
 * UNE VERSION PRÉCÉDENTE FAISAIT DÉFILER LES TIRAGES HORIZONTALEMENT, en
 * boucle. Elle marchait, mais elle imposait un ordre et une seule image à
 * la fois : pour revoir la troisième, il fallait repasser devant les
 * autres. La feuille de contact donne la série d'un coup d'œil ET le
 * détail à la demande. C'est ce qui a fait abandonner le défilement.
 *
 * LA PAGE NE DÉFILE PAS. Comme les trois autres vues : le site n'a aucune
 * exception à sa règle d'écran verrouillé.
 */

:root {
	/* Une ligne et une colonne de la grille, en pixels réels. La grille de
	   la home raisonne en fractions ; ici on a besoin des deux comme
	   UNITÉS DE MESURE, pour caler la hauteur de l'image dans son cadre et
	   la largeur de la feuille de contact — qui, elle, est en
	   position:fixed et ne peut donc pas se poser sur la grille. */
	--fl-row: calc( ( 100vh - var(--grid-margin-top) - var(--grid-margin) ) / var(--grid-rows) );
	--fl-col: calc(
		( 100vw - 2 * var(--grid-margin) - ( var(--grid-columns) - 1 ) * var(--grid-gap) )
		/ var(--grid-columns)
	);

	/* LE PASSE-PARTOUT DU GRAND CADRE, et c'est lui qui donne sa taille à
	   l'image. Le cadre fait 7 lignes (toute la hauteur utile) ; une marge
	   d'une ligne en haut et en bas laisse donc 5 lignes à la photo —
	   exactement la hauteur demandée pour une verticale.
	   Changer ce seul nombre change la taille de l'image, ET la bande de
	   blanc où la légende vient se poser en bas. */
	--project-mat: var(--fl-row);

	/* ------------------------------------------------------------------
	   LE RETRAIT LATÉRAL EST DISSOCIÉ DU VERTICAL, et c'est une correction.

	   --project-mat vaut UNE LIGNE DE GRILLE, donc une valeur tirée de la
	   HAUTEUR de la fenêtre. Employée telle quelle à gauche et à droite,
	   elle ne bouge pas quand on resserre la fenêtre — alors que le cadre,
	   lui, rétrécit avec elle. Le retrait mange donc une part de plus en
	   plus grosse du carton.

	   ET ÇA NE TOUCHE QUE LES HORIZONTALES. Une verticale est bornée par la
	   HAUTEUR du carton : le retrait latéral ne la limite pas, elle reste
	   juste. Une horizontale, elle, est bornée par la LARGEUR — c'est donc
	   exactement ce retrait qui décide de sa taille, et il l'écrase.

	   Mesuré à hauteur de fenêtre constante (900px), sur une 3:2 :
	     fenêtre 1500  carton 725 large  retrait 122  photo 481 large
	     fenêtre 1100  carton 525 large  retrait 122  photo 282 large
	   La fenêtre perd 27 % de largeur, la photo 41 %.

	   PREMIER ESSAI, ÉCARTÉ : min( var(--project-mat), 9vw ). L'idée était
	   de plafonner la ligne de grille par une valeur en largeur, de sorte
	   que le rendu reste identique au-dessus de ~1350px et se resserre en
	   dessous. Ça corrigeait bien le resserrement, mais deux défauts :
	   les horizontales restaient trop à l'étroit, et les VERTICALES se
	   mettaient à grandir sous 1400px — devenues bornées par la largeur à
	   leur tour, ce qui n'était pas demandé.

	   UN POURCENTAGE DU CARTON, et pas une longueur : c'est ce qui est en
	   place. Il règle les deux défauts d'un coup. Il suit la largeur du carton
	   par construction, donc le retrait reste visuellement constant à
	   toutes les tailles de fenêtre ; et il est assez généreux pour que les
	   verticales restent bornées par la HAUTEUR partout, donc strictement
	   inchangées — vérifié à 1728, 1200 et 1100 : 406x609 dans les trois
	   cas, exactement leur plafond de 5 lignes.

	   7 % DE CHAQUE CÔTÉ, C'EST LA MÊME VALEUR QUE LA HOME (où la photo est
	   capée à 86 % du carton, cf. css/transition-project.css). Les deux
	   vues ont donc enfin le même filet proportionnel, ce qui n'était pas
	   le cas avant — la home était proportionnelle, la page projet non.

	   Mesuré sur une 3:2, à 900 de haut. Largeur de la photo, retrait
	   latéral entre parenthèses :
	     fenêtre 1728  avant 596 (122)  après 722 (59)
	     fenêtre 1512  avant 488 (122)  après 629 (51)
	     fenêtre 1200  avant 359 (108)  après 494 (40)
	     fenêtre 1100  avant 327 ( 99)  après 452 (37)

	   C'EST LE SEUL NOMBRE À TOUCHER si le filet latéral paraît trop fin ou
	   trop épais. À 10 % la photo redescend à ~654 sur un écran de 1728.

	   Le retrait HAUT/BAS n'est pas touché : il reste --project-mat, donc
	   une ligne pleine. C'est lui qui réserve la bande de blanc où la
	   légende vient se poser, et c'est lui qui donne ses 5 lignes à une
	   verticale. Les deux ne doivent pas être confondus, malgré le
	   commentaire ci-dessus qui parlait d'« une marge sur les quatre
	   côtés » — ce n'est plus vrai, et c'est volontaire.
	   ------------------------------------------------------------------ */
	--project-mat-x: 7%;

	/* La feuille de contact. Le blanc entre deux vues est à elle : la
	   gouttière de la grille du site vaut zéro (--grid-gap: 0px), donc s'y
	   adosser collerait les vignettes bord à bord. Une planche contact a
	   des interstices — c'est ce qui fait lire des vues séparées plutôt
	   qu'une image découpée. */
	--project-sheet-gap: 12px;
	--project-sheet-dim: 0.4;          /* opacité des vues non retenues */
	--project-sheet-fade: 0.35s;
	/* TAILLE D'UNE VUE. Une planche contact se lit de près : les vignettes
	   doivent rester petites, sinon ce ne sont plus des indices mais des
	   images concurrentes du tirage central. Deux colonnes de vues occupent
	   donc moins que les deux colonnes de grille où elles vivent — la
	   planche est centrée dedans. Exprimé en fraction de colonne pour
	   suivre la largeur de l'écran. C'est une LARGEUR seulement : la
	   hauteur de chaque vue suit le format de sa photo. */
	--project-thumb: calc( var(--fl-col) * 0.42 );

	/* LE DÉVELOPPEMENT — la bascule d'une image à l'autre au centre.
	   C'est la transition du carrousel de la home (dissolution, passage
	   par le blanc, mise au point) mais RACCOURCIE : là-bas elle dure
	   3,8s parce qu'elle se déclenche toute seule et qu'on la regarde ;
	   ici elle répond à la main, et au-delà d'une seconde le survol
	   traînerait derrière le curseur. */
	--project-swap-out: 0.32s;
	--project-swap-gap: 0.14s;
	--project-swap-in: 0.55s;
}

/* ------------------------------------------------------------------ */
/* L'écran                                                             */
/* ------------------------------------------------------------------ */

html:has(body.fl-project) {
	height: 100%;
	overflow: hidden;
}

/* LES 50 PIXELS FANTÔMES — la cause réelle du premier écran cassé.
   padding: 0 n'est pas décoratif ici, il ANNULE une règle.

   theme.css contient encore .single-project { padding-top/bottom:
   var(--grid-margin) }, vestige du tout premier jet de cette page. Or
   .single-project est une classe que WordPress pose SUR LE BODY : elle
   retirait donc 25px en haut et 25px en bas aux seules pages projet.

   Conséquence, invisible mais systématique : une ligne de grille y valait
   114,6px quand la home est à 121,7. Toute la page se mesure en lignes —
   la hauteur de l'image dans son cadre, la planche qui s'aligne dessus —
   et le geste depuis la home, quand il existera, partira d'une grille
   pour arriver dans une autre. Les deux vues DOIVENT avoir la même ligne.

   À SUPPRIMER en même temps que le bloc mort de theme.css (chercher
   ".single-project"). En attendant, la neutralisation vit ici, à côté du
   code qu'elle protège. */
body.fl-project {
	height: 100vh;
	padding-top: 0;
	padding-bottom: 0;
	overflow: hidden;
	position: relative;
	background: var(--color-bg);

	/* Réglages de la bascule au centre, hérités par .fl-home-img.
	   --fl-gap-delay est le token que theme.css lit pour retarder l'image
	   ENTRANTE : le redéfinir ici suffit à recaler la respiration, sans
	   toucher à la règle .is-active. */
	--fl-blur: 10px;
	--fl-scale: 1.015;
	--fl-gap-delay: calc( var(--project-swap-out) + var(--project-swap-gap) );
}

body.fl-project.admin-bar {
	height: calc( 100vh - 32px );
}

@media screen and (max-width: 782px) {
	body.fl-project.admin-bar {
		height: calc( 100vh - 46px );
	}
}

/* Le beige à fond perdu. Sur la home c'est un rectangle posé dans les
   marges (un objet sur la page) ; ici il couvre tout (la table). C'est le
   même élément qui change de statut — et c'est LUI que le geste depuis la
   home fait grandir, il doit donc finir exactement là. */
body.fl-project .home-beige {
	position: fixed;
	top: 0;
	left: 0;
	right: 0;
	bottom: 0;
	z-index: 0;
}

/* Header superposé à la ligne 1, comme partout ailleurs. Il passe
   AU-DESSUS du grand cadre, qui monte jusqu'à la marge haute — mais le
   titre est colonne 1 et la nav colonne 8, donc rien ne se recouvre. */
body.fl-project .site-header {
	position: absolute;
	top: 0;
	left: 0;
	right: 0;
	z-index: 3;
}

body.fl-project .site-footer {
	display: none;
}

/* LE MAILLON MANQUANT DE LA CHAÎNE DE HAUTEUR, l'autre moitié du premier
   écran cassé.

   .home-layout est en height:100%. Un pourcentage de hauteur ne vaut que
   si le PARENT a une hauteur définie — sinon la règle est simplement
   ignorée et la grille retombe sur la hauteur de son contenu. C'est ce
   qui s'est passé : 258px au lieu de 850, donc sept lignes écrasées, un
   cadre haut comme trois lignes de texte et une image qui débordait.

   Le <main> n'a aucune hauteur propre : theme.css la lui donne, mais
   seulement sous body.fl-home. La version précédente de cette page ne
   s'en apercevait pas parce qu'elle plaçait tout en position:fixed, hors
   du flux ; dès qu'on revient dans la grille, il faut refermer la chaîne
   body → main → .home-layout. */
body.fl-project .site-main.front-page {
	height: 100%;
	min-height: 0;
	overflow: hidden;
	position: relative;
}

/* L'INDEX DISPARAÎT. On ne change pas de projet depuis un projet : on
   repasse par la home. C'est un parti pris, pas un oubli — il ferme la
   page sur elle-même, et il évite que la colonne de gauche propose autre
   chose pendant qu'on regarde une série.

   DEPUIS QUE L'INDEX TRAVERSE LA PAGE (cf. theme.css), ce display:none
   fait plus que libérer une colonne : il retire des bandes qui
   passeraient en travers du grand tirage. Le masquer restait de toute
   façon la bonne décision, mais elle n'est plus seulement conceptuelle.

   Conséquence assumée : il n'y a aucun lien "projet suivant". Le titre du
   site et "Overview" restent les deux sorties. */
body.fl-project .home-index {
	display: none;
}

/* ------------------------------------------------------------------ */
/* Le grand cadre                                                      */
/* ------------------------------------------------------------------ */

/* PLEINE HAUTEUR, QUATRE COLONNES, CENTRÉ. Les colonnes 3 à 6 sur 8 : il
   reste deux colonnes à gauche (vides) et deux à droite (la feuille de
   contact), donc la composition est symétrique.

   C'est le MÊME élément que le montage de la home — même nœud, même
   contenu — simplement replacé et agrandi. C'est ce qui permet au geste
   depuis la home de le faire grandir sur place au lieu de le
   reconstruire. */
body.fl-project .home-work {
	grid-column: 3 / 7;
	grid-row: 1 / -1;
	align-items: stretch;
	visibility: visible;
}

/* Sur la home, le cadre prend le FORMAT DE LA PHOTO (aspect-ratio piloté
   par --image-ratio) : c'est une fenêtre qui épouse son image. Ici c'est
   l'inverse — le cadre est fixe, et c'est la photo qui s'y loge. Un tirage
   monté ne change pas de carton quand on change de vue ; c'est ce qui rend
   possible le va-et-vient avec la feuille de contact. */
body.fl-project .fl-home-frame {
	aspect-ratio: auto;
	width: 100%;
	height: 100%;
	flex: 1 1 auto;
}

/* L'IMAGE FAIT 5 LIGNES DE HAUT — pour une verticale. object-fit:contain
   fait le reste : une horizontale est bridée par la largeur du cadre et
   sera donc moins haute. Jamais de recadrage, jamais de déformation.

   LE RETRAIT N'EST PLUS LE MÊME SUR LES QUATRE CÔTÉS : une ligne de grille
   en haut et en bas, mais --project-mat-x sur les côtés, qui se resserre
   avec la fenêtre. Cf. le pavé du token — c'est ce qui empêchait une
   horizontale d'être écrasée dès qu'on réduisait la largeur.

   NOTE : ce padding est écrasé par transition-project.css, qui remet la
   boîte de l'image à la taille de son contenu (padding: 0 + max-width /
   max-height). Il est tenu à jour quand même pour que les deux fichiers
   racontent la même chose, et parce qu'il redeviendrait actif si cette
   correction-là était un jour retirée. */
body.fl-project .fl-home-img {
	padding: var(--project-mat) var(--project-mat-x);
	transition:
		opacity var(--project-swap-in) cubic-bezier( 0.4, 0, 0.2, 1 ),
		filter var(--project-swap-in) cubic-bezier( 0.2, 0.55, 0.35, 1 ),
		transform var(--project-swap-in) cubic-bezier( 0.2, 0.55, 0.35, 1 );
}

/* La sortante part sans délai, comme sur la home — mais trois fois plus
   vite. Règle plus spécifique que celle de theme.css, qui pose elle aussi
   un raccourci "transition" complet : à spécificité égale il l'aurait
   remplacée en silence, ce qui est arrivé une fois entre about.css et
   overview.css. */
body.fl-project .fl-home-img.is-leaving {
	transition:
		opacity var(--project-swap-out) cubic-bezier( 0.4, 0, 1, 1 ),
		filter var(--project-swap-out) cubic-bezier( 0.4, 0, 1, 1 );
}

/* ------------------------------------------------------------------ */
/* La légende                                                          */
/* ------------------------------------------------------------------ */

/* SOUS LE TIRAGE, COMME SUR LA HOME — mais une ligne plus bas.

   Sur la home elle se cale au bas de la ligne 6 ; ici elle descend dans la
   ligne 7, où elle se centre. Ce n'est pas un déplacement arbitraire : le
   cadre occupe toute la hauteur et son passe-partout laisse exactement une
   ligne de blanc en bas (cf. --project-mat). La légende tombe donc DANS
   cette bande, sur le carton lui-même. Un cartel écrit sur le montage,
   pas une ligne posée à côté.

   Un essai précédent la mettait en bas à gauche, alignée sur "FIONA
   LEBRE". Composition plus tendue sur le papier, mais elle sortait du
   tirage pour aller se coller à la signature : deux textes de même taille
   dans la même colonne, et on ne savait plus lequel nommait quoi.

   ELLE EST DÉSORMAIS FERRÉE À GAUCHE, et ce n'est PAS un retour à cet
   essai-là. Le fer se fait sur la colonne 3, c'est-à-dire sur le bord
   gauche du tirage lui-même — la légende reste donc sous SON image, ce
   qui était tout l'enjeu. L'essai écarté la renvoyait en colonne 1, dans
   la colonne de la signature, et c'est de là que venait la confusion.

   Ce fer et ces COLONNES sont imposés par css/transition-project.css,
   qui charge après ce fichier : ce sont des contraintes du passage depuis
   la home, pas des choix de mise en page propres à cette vue, donc elles
   vivent là-bas. Les valeurs déclarées ici (3/7, centré) restent ce que
   serait la page si le passage n'existait pas. */
body.fl-project .home-caption {
	grid-column: 3 / 7;
	grid-row: -2 / -1;
	align-self: center;
	text-align: center;
	position: relative;
	z-index: 2;
}

/* ------------------------------------------------------------------ */
/* La feuille de contact                                               */
/* ------------------------------------------------------------------ */

/* Colonnes 7-8, centrée en hauteur. En position:fixed et non dans la
   grille : elle est rendue par single-project.php en dehors de
   .home-layout, qui est un template partagé avec les trois autres vues et
   qu'on ne veut pas encombrer d'un bloc propre aux projets. D'où les
   unités --fl-col : elles reconstituent la colonne de grille à la main.

   S'il y a plus de vignettes que de hauteur, la planche défile — c'est le
   SEUL défilement de la page, et il est contenu dans un bloc de deux
   colonnes. Le reste ne bouge pas. */
.project-sheet {
	position: fixed;
	right: var(--grid-margin);
	top: 50%;
	transform: translateY( -50% );
	width: calc( 2 * var(--fl-col) + var(--grid-gap) );
	/* MÊME HAUTEUR QUE L'IMAGE DU CENTRE — construite de la même façon, la
	   hauteur utile moins le passe-partout haut et bas. Les deux se
	   répondent donc quel que soit l'écran, et un seul token (--project-mat)
	   les déplace ensemble. */
	max-height: calc( var(--grid-rows) * var(--fl-row) - 2 * var(--project-mat) );
	z-index: 2;
	display: grid;
	/* Deux colonnes À LA TAILLE DE LA VIGNETTE, et non deux fractions : les
	   vues gardent leur échelle et c'est la planche qui se centre dans les
	   deux colonnes de grille (justify-content). Avec des 1fr, chaque vue
	   ferait une colonne entière — la planche pèserait alors autant que le
	   tirage, ce qui est exactement ce qu'on ne veut pas. */
	grid-template-columns: repeat( 2, var(--project-thumb) );
	gap: var(--project-sheet-gap);
	justify-content: center;
	align-content: center;
	/* Chaque vue se pose en haut de sa rangée au lieu d'être étirée à la
	   hauteur de sa voisine. Les vues n'ayant plus de format imposé, une
	   verticale et une horizontale se retrouvent côte à côte : sans ça,
	   l'horizontale serait tirée pour rattraper la verticale. */
	align-items: start;
	overflow-y: auto;
	overscroll-behavior: contain;
	scrollbar-width: none;
}

.project-sheet::-webkit-scrollbar {
	display: none;
}

/* UNE VUE DE LA PLANCHE — L'IMAGE NUE, SANS CARTON.

   Une version précédente montait chaque vignette sur un carré blanc, par
   symétrie avec le grand cadre. C'était une erreur de niveau : le montage
   est ce qui distingue le TIRAGE, et le répéter sur la planche mettait les
   deux au même rang. Une feuille de contact, ce sont des images brutes
   posées côte à côte ; le carton vient après, quand on choisit.

   Conséquence directe : plus de format imposé. Chaque vue garde le sien —
   la largeur est celle de la colonne, la hauteur suit la photo. La planche
   est donc légèrement irrégulière, ce qui est exactement ce qu'on voit sur
   une vraie feuille de contact, et ce qui évite surtout de recadrer :
   remplir un carré aurait voulu dire rogner, et on ne rogne nulle part sur
   ce site. */
.project-frame {
	display: block;
	width: 100%;
	padding: 0;
	margin: 0;
	border: 0;
	background: none;
	cursor: pointer;
	/* Les vues non retenues sont en retrait, pas éteintes : on doit encore
	   lire la série entière. Celle qui est au centre est à pleine valeur —
	   c'est le seul repère qui dit laquelle on regarde. */
	opacity: var(--project-sheet-dim);
	transition: opacity var(--project-sheet-fade) var(--caption-reveal-ease);
}

.project-frame:hover,
.project-frame:focus-visible,
.project-frame.is-current {
	opacity: 1;
}

/* PAS DE MARQUE SUR LA VUE RETENUE. J'avais posé un filet couleur accent
   autour d'elle, pour qu'on sache où l'on retombera en quittant la
   planche. Retiré : sur une image nue, un filet redevient un cadre — donc
   exactement ce qu'on venait d'enlever, en plus fin.

   La classe .is-locked reste posée par js/project.js (elle porte l'état,
   et aria-pressed avec elle) : elle ne peint simplement plus rien. Le
   seul repère visible est l'opacité pleine de la vue en cours, et ça
   suffit — l'image du centre dit déjà ce qu'on regarde, et lâcher la
   planche y ramène la vue retenue. */

/* AUCUN LISERÉ, D'OÙ QU'IL VIENNE. Un <button> arrive avec bordure, fond
   et contour du navigateur ; on les coupe tous les trois explicitement,
   ici comme au repos, pour qu'aucune feuille de style d'agent utilisateur
   ne repeigne un bord autour de la photo. */
.project-frame,
.project-frame:hover,
.project-frame:focus,
.project-frame:active,
.project-frame.is-locked,
.project-frame.is-current {
	border: 0;
	outline: none;
	box-shadow: none;
	background: transparent;
}

/* Le contour du navigateur reste POUR LE CLAVIER, et seulement là : sans
   lui, on tabule dans la planche sans savoir où l'on est. focus-visible
   ne se déclenche pas au clic de souris, donc ça ne réintroduit pas de
   liseré à l'usage courant. */
.project-frame:focus-visible {
	outline: 1px solid var(--color-accent);
	outline-offset: 3px;
}

/* La photo à sa taille naturelle dans la largeur de colonne. Pas de
   height ni d'object-fit : c'est le rapport de l'image qui décide, donc
   aucun recadrage et aucun bord vide. */
.project-frame img {
	display: block;
	width: 100%;
	height: auto;
	border: 0;
	background: transparent;
}

/* ------------------------------------------------------------------ */
/* Réduire les animations                                              */
/* ------------------------------------------------------------------ */

/* IL FAUT REDIRE ICI CE QUE theme.css DIT DÉJÀ, et c'est le point à ne pas
   rater. theme.css coupe le mouvement de .fl-home-img sous ce réglage,
   mais nos règles ci-dessus sont préfixées de body.fl-project : elles sont
   PLUS SPÉCIFIQUES, et une media query n'ajoute aucune spécificité. La
   coupure de theme.css serait donc purement et simplement écrasée sur les
   pages projet, et une image resterait floue pour toujours chez quelqu'un
   qui a demandé qu'on ne l'anime pas. */
@media (prefers-reduced-motion: reduce) {
	body.fl-project .fl-home-img,
	body.fl-project .fl-home-img.is-active,
	body.fl-project .fl-home-img.is-leaving {
		transition: none;
		transition-delay: 0s;
		filter: none;
		transform: none;
		will-change: auto;
	}

	.project-frame {
		transition: none;
	}
}
