/* ==================================================================== */
/* Fiona Lebre — ABOUT                                                  */
/* La page, et le geste qui y mène depuis la home.                      */
/* ==================================================================== */
/*
 * TOUT CE QUI CONCERNE ABOUT VIT ICI, y compris la mise en page de la
 * vraie page /about/ — déplacée depuis theme.css. Une mise en page à
 * moitié définie dans un fichier et à moitié dans l'autre finit toujours
 * par diverger, et c'est précisément ce qui était arrivé : la page About
 * était restée sur une grille de 9 lignes quand la home est passée à 7,
 * donc plus rien ne pouvait s'aligner entre les deux.
 *
 * LE GESTE : le beige, puis le montage (passe-partout + tirage), se
 * referment sur leur bord droit.
 *
 * ==================================================================
 * DEUX RÈGLES, ET ELLES ONT COÛTÉ CHER À TROUVER.
 *
 * ------------------------------------------------------------------
 * 1. LA DURÉE EST PROPORTIONNELLE À LA LARGEUR.
 *
 * L'invariant qui compte n'est pas le temps que met chaque couche, c'est
 * LA VITESSE DE SON BORD. Quand tout durait 900ms, le bord du beige
 * (769px de large à 1280) filait à 1709 px/s contre 853 pour le montage
 * (384px) : deux fois plus vite. Il rattrapait le montage et lui passait
 * au travers — mesuré, le croisement arrivait à 445ms. On voyait
 * littéralement le beige couper le blanc en deux.
 *
 * À vitesse de bord égale, le bord du beige démarre 269px à gauche de
 * celui du montage et garde cet écart pour toujours : le croisement
 * devient géométriquement impossible. D'où --about-fold-ratio.
 *
 * ------------------------------------------------------------------
 * 2. ON DÉCOUPE, ON NE COMPRIME PAS.
 *
 * Le pli était un scaleX. Pour un aplat uni c'est parfait — mais le
 * tirage, lui, se retrouvait écrasé sur un axe, et une image déformée se
 * lit comme un bug d'affichage, jamais comme un geste.
 *
 * Trois tentatives pour s'en sortir par le réglage, toutes ratées :
 *   - fondu long : la photo restait visible à 25 % de compression ;
 *   - fondu court : elle disparaissait avant qu'on ait vu le pli ;
 *   - pas de pli du tout : elle restait rigide pendant que son support
 *     bougeait, donc elle s'en détachait.
 * Le problème n'était pas la valeur, c'était la propriété animée.
 *
 * LE BALAYAGE règle tout d'un coup — d'abord au clip-path, aujourd'hui
 * par un masque, qui fait exactement la même chose mais dont le bord est
 * réglable (cf. --about-wipe-edge). POUR LES DEUX APLATS C'EST STRICTEMENT
 * LE MÊME RENDU — un rectangle uni rétréci vers la droite ou rogné par la
 * gauche, ce sont les mêmes pixels. Mais le tirage n'est plus jamais
 * déformé : il est balayé. Il peut donc accompagner le pli du début à la
 * fin, à pleine opacité, et il n'y a plus rien à arbitrer. Les tokens
 * --about-photo-duration et compagnie ont disparu avec le problème.
 * ==================================================================
 *
 * L'ORDRE EST LE MÊME DANS LES DEUX SENS : le beige, puis le montage.
 *
 * À l'aller on partait au début de la photo pour finir par le beige, avec
 * l'idée que chaque couche découvre celle du dessous. Raté, pour une
 * raison qui n'a rien à voir avec la géométrie : le beige est de loin le
 * plus grand élément à l'écran, et tant qu'il ne bouge pas la page a
 * l'air de ne pas avoir entendu le clic. Une interface accuse réception
 * tout de suite, et à la mesure de ce qu'on lui a demandé.
 *
 * LE TIRAGE ET SON PASSE-PARTOUT PARTAGENT EXACTEMENT LES MÊMES VALEURS.
 * Ce n'est pas une simplification, c'est une contrainte : s'ils se
 * décalaient, le bord de coupe du tirage se retrouverait à gauche de
 * celui du blanc, donc la photo déborderait sur le beige. Ils se
 * referment comme un seul objet — ce qu'ils sont.
 *
 * LA RÈGLE À GARDER EN TÊTE si on retouche quoi que ce soit : UNE COUCHE
 * N'EST JAMAIS VISIBLE ET IMMOBILE PENDANT QUE LES AUTRES BOUGENT, et
 * aucun bord n'en dépasse un autre. Tout ce qui a raté sur ce geste
 * violait l'une ou l'autre.
 */

/* LA POSITION DU BORD DE COUPE, déclarée pour pouvoir être ANIMÉE.
   Une propriété personnalisée ordinaire n'est qu'un bout de texte : le
   navigateur ne sait pas l'interpoler, il la remplacerait d'un coup.
   @property lui donne un type, et elle devient animable comme n'importe
   quelle longueur. C'est ce qui permet de faire glisser un dégradé au
   lieu de déplacer une frontière nette. */
@property --about-wipe {
	syntax: "<percentage>";
	inherits: false;
	initial-value: 0%;
}

:root {
	/* Largeur du DÉGRADÉ du bord de coupe, en part de la largeur de la
	   couche.

	   À ZÉRO : le bord est net.

	   Ce dégradé avait été introduit à 10 % pour adoucir le balayage plein
	   écran du trajet About -> Overview, qui se lisait comme une lame.
	   Mais ce trajet NE BALAIE PLUS DU TOUT — le beige s'y contente d'un
	   fondu, cf. fl-beige-fade — et la douceur a alors dégradé le seul
	   geste qui plie encore : sur le beige de la home, 10 % font 77px de
	   bande semi-transparente traversant un aplat, ce qui ne se lit pas
	   comme un bord doux mais comme un FLOU.

	   Le masque, lui, reste en place : à 0 % il est rigoureusement
	   équivalent au clip-path d'avant, et le mécanisme sert de toute façon
	   au fondu d'About <-> Overview. Ce seul chiffre suffit donc à rouvrir
	   la question si le bord franc redevenait gênant — en se souvenant
	   qu'au-delà de quelques pourcents, ça floute au lieu d'adoucir. */
	--about-wipe-edge: 0%;
	/* Durée du pli DU BEIGE — la couche la plus large, donc celle qui fixe
	   le tempo. Les autres s'en déduisent par leur largeur (cf. ci-dessous),
	   il n'y a donc qu'un seul chiffre à toucher pour changer l'allure du
	   geste entier. */
	--about-fold-duration: 0.9s;
	/* Largeur du montage rapportée à celle du beige. C'est CE rapport qui
	   donne la durée du pli du montage, et c'est ce qui garantit une
	   vitesse de bord identique pour les deux.

	   Le vrai rapport dépend du format de l'écran — parce que le beige se
	   mesure en colonnes et le montage en lignes. On prend la valeur BASSE
	   volontairement : sous-estimer fait replier le montage un peu plus
	   vite que le beige, et l'écart entre les deux bords ne peut alors que
	   se creuser. Sur-estimer, à l'inverse, ramènerait le croisement. Dans
	   le doute, toujours baisser.

	   0,5 CORRESPOND AU BEIGE SUR 5 COLONNES, sa largeur actuelle
	   (rapports réels 0,50 en 16:9 et 0,56 en 16:10). La valeur est donc
	   juste en 16:9 et prudente en 16:10, comme voulu.

	   ELLE EST LIÉE À LA LARGEUR DU BEIGE, et c'est le piège à connaître :
	   le beige a été essayé sur 6 colonnes (cf. .home-beige dans
	   theme.css), ce qui l'élargit d'un cinquième et fait tomber le
	   rapport à 0,42 en 16:9. Garder 0,5 dans ce cas en aurait fait une
	   SUR-estimation sur écran large — exactement la condition qui ramène
	   le beige à couper le montage. Si on réélargit le beige un jour, il
	   faut rebaisser ce nombre avec lui. */
	--about-fold-ratio: 0.5;
	/* Écart entre le départ du beige et celui du montage. Vérifié par
	   simulation : à 120ms il reste 37px de marge au plus serré, dans un
	   sens comme dans l'autre ; en montant, le beige finit par recouper le
	   montage. C'est donc un plafond, pas un goût. */
	--about-fold-stagger: 120ms;
	/* COURBE SYMÉTRIQUE, et ce n'est pas un détail de goût : c'est la
	   condition pour que l'aller et le retour se ressemblent.

	   Une transition CSS rejoue LA MÊME courbe dans les deux sens. Le
	   retour ne ressemble donc à l'aller joué à l'envers que si la courbe
	   est symétrique par rapport à son centre — si e(1-x) = 1-e(x).

	   On avait cubic-bezier(0.42, 0.02, 0.18, 1), reprise de l'Overview.
	   Elle ne l'est pas du tout : 57 % d'écart maximal entre les deux
	   sens. À mi-parcours le retour était ouvert à 79 %, l'aller ne
	   l'était plus qu'à 21 % — l'aller claquait puis rampait, le retour
	   bondissait puis se posait. Aucun réglage de délai ne pouvait le
	   rattraper.

	   NOTE : l'Overview a le même défaut, avec la même courbe. Personne ne
	   s'en est plaint ; si ça arrive, c'est la même correction.

	   DEUXIÈME CRITÈRE, LA LONGUEUR DE LA QUEUE. On était d'abord passé à
	   ease-in-out (0.42, 0, 0.58, 1), symétrique et proche de l'ancienne.
	   Symétrie réglée, mais la fin du retour restait sèche — et là encore
	   c'est mesurable : la durée étant proportionnelle à la largeur, le
	   montage doit caser toute sa décélération dans deux fois moins de
	   temps que le beige, donc il se posait deux fois plus fort (227 px/s
	   sur ses 60 dernières ms, contre 111). Or au retour c'est justement
	   lui qu'on regarde arriver.

	   (0.65, 0, 0.35, 1) allonge la queue de 22 à 29 % de la durée : le
	   montage tombe à 107 px/s — la douceur qu'avait le beige — et le
	   beige à 49. Le prix, c'est un milieu plus rapide (pointe x2,86 au
	   lieu de x1,72), qui réduit la marge anti-croisement de 102 à 37px.
	   Toujours positive, mais c'est elle qui limite : une courbe encore
	   plus creusée (inOutQuart, x4,17) tombe à 3px, et inOutQuint croise
	   franchement. On ne peut donc pas aller plus loin de ce côté-là. */
	--about-fold-ease: cubic-bezier(0.65, 0, 0.35, 1);
	/* Part de son propre pli pendant laquelle une couche s'efface, calée
	   sur la fin. Ce qui claquait, ce n'était pas le pli mais sa
	   conclusion : les derniers pourcents, quand la couche devient un
	   trait. À 0,5 elle est déjà pâle quand elle se referme.
	   Exprimé en PART et non en durée, pour que ça suive automatiquement
	   la durée propre de chaque couche. */
	--about-fade-share: 0.5;
	/* Le texte de la colonne de gauche : sortie de l'index, entrée de la
	   bio. C'est une substitution sur place, pas un événement. Le délai la
	   fait arriver une fois le premier pli engagé. */
	--about-text-duration: 0.5s;
	--about-text-delay: 0.3s;
	/* Interlignage du texte About. 1,8 — LA MÊME VALEUR QUE .home-index,
	   et c'est le but : la bio et l'index sont désormais dans la même
	   fonte, au même corps, avec le même tracking. En leur donnant le même
	   interlignage, leurs lignes de base tombent exactement au même
	   endroit, et la substitution devient invisible au pixel près.
	   À 1,4 la bio démarrait 2,4px plus haut que l'index — écart minuscule,
	   mais qui se voyait justement parce que les deux se remplacent sur
	   place. Sert aussi d'écart entre paragraphes, pour que le blanc
	   vaille une ligne pleine. */
	--about-line-height: 1.8;
}

/* ------------------------------------------------------------------ */
/* La page About                                                       */
/* ------------------------------------------------------------------ */

/* Header superposé à la ligne 1, comme sur la home — sinon sa hauteur
   s'ajoute au-dessus de la grille et décale tout vers le bas. */
body.fl-about {
	position: relative;
}

body.fl-about .site-header {
	position: absolute;
	top: 0;
	left: 0;
	right: 0;
	z-index: 3;
}

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

/* LA MÊME GRILLE QUE LA HOME : 8 colonnes, --grid-rows lignes (7), mêmes
   marges. C'est la condition pour que la bio tombe exactement sur l'index
   des projets qu'elle remplace. Vérifié : les deux démarrent à 119px, et
   leurs premières lignes de texte sont à 1px l'une de l'autre malgré des
   interlignages différents.

   UN SEUL RENDU DÉSORMAIS. La bio existait en deux exemplaires — une mise
   en page dans page-about.php pour l'accès direct, ce calque pour la
   transition — et les deux avaient divergé sans que personne le voie : la
   vraie page était restée sur 9 lignes quand la home est passée à 7. Le
   calque est maintenant le seul rendu, ici comme pendant le geste (cf.
   page-about.php, qui ne met plus rien en page). */
.fl-about-overlay {
	display: grid;
	grid-template-columns: repeat(var(--grid-columns), 1fr);
	grid-template-rows: repeat(var(--grid-rows), 1fr);
	column-gap: var(--grid-gap);
	padding: var(--grid-margin-top) var(--grid-margin) var(--grid-margin);
	box-sizing: border-box;
}

/* Ligne 2 : exactement celle de .home-index. Ligne 5 pour les contacts —
   deux lignes vides entre les deux blocs, qui les séparent sans qu'on ait
   à inventer une marge. */
.about-bio {
	grid-column: 1 / 4;
	/* Trois lignes et non deux : depuis que la bio est interlignée comme
	   l'index (1,8), le même texte occupe environ un quart de hauteur en
	   plus. La ligne 4 était vide de toute façon, autant que la zone
	   déclarée corresponde à ce qui s'y trouve. */
	grid-row: 2 / 5;
}

.about-details {
	grid-column: 1 / 4;
	grid-row: 5 / 6;
}

/* LOUIZE DISPLAY, comme l'index des projets qu'elle vient remplacer — et
   donc, règle typo du thème oblige, en 12px trackés à 10 % (cf.
   --font-size-louize dans theme.css : cette fonte ne s'emploie jamais
   autrement). C'était en Hagel, ce qui faisait cohabiter deux serifs dans
   la même colonne à une seconde d'intervalle. */
.about-bio,
.about-details {
	font-family: var(--font-louize);
	font-style: normal;
	font-weight: 400;
	font-size: var(--font-size-louize);
	letter-spacing: var(--letter-spacing-wide);
	line-height: var(--about-line-height);
}

/* Un blanc d'exactement une ligne entre deux paragraphes : le texte reste
   sur sa propre trame, au lieu d'un écart choisi à vue. */
.about-bio p,
.about-details p {
	margin: 0 0 calc( 1em * var(--about-line-height) );
}

.about-bio p:last-child,
.about-details p:last-child {
	margin-bottom: 0;
}

.about-details a {
	transition: color 0.6s ease;
}

.about-details a:hover {
	color: var(--color-accent);
}

/* ------------------------------------------------------------------ */
/* Le calque — pendant la transition ET sur la vraie page              */
/* ------------------------------------------------------------------ */

/* position:fixed : il ne participe pas à la grille de la home, où il
   pousserait tout vers le bas. Même procédé que la mosaïque.

   Rendu sur les TROIS vues (cf. template-parts/home-content.php), et
   c'est lui qui fait la page /about/ elle-même depuis qu'elle n'a plus de
   mise en page propre.

   LIMITE ASSUMÉE : la grille est en lignes fixes (7 fractions du
   viewport), donc une bio qui dépasserait sa zone déborderait au lieu de
   pousser la suite. overflow-y ci-dessous n'est qu'un filet — il ne
   rattrape que le cas où la grille entière dépasse. Le jour où la bio
   s'allonge vraiment, c'est le parti pris "tout tient dans un écran" qu'il
   faudra rouvrir, pas ce réglage : ce sont les lignes fixes qui font
   tomber la bio exactement sur l'index qu'elle remplace. */
.fl-about-overlay {
	position: fixed;
	top: 0;
	left: 0;
	right: 0;
	bottom: 0;
	z-index: 2;
	overflow-y: auto;

	/* État de repos : absent. visibility (et pas seulement opacity) pour
	   que les liens mailto/tel ne soient ni tabulables ni lus par un
	   lecteur d'écran tant qu'on est sur la home. Le délai la fait
	   basculer À LA FIN du fondu sortant, et immédiatement au fondu
	   entrant (cf. la règle d'état, qui remet le délai à zéro). */
	opacity: 0;
	visibility: hidden;
	transition: opacity var(--about-text-duration) var(--about-fold-ease),
	            visibility 0s linear var(--about-text-duration);

	/* ET INERTE, PAS SEULEMENT INVISIBLE. Le calque couvre les quatre
	   bords de l'écran : tant qu'il accepte le pointeur, il intercepte
	   TOUT — le clic sur la photo du centre comme le survol de l'index.

	   visibility:hidden le neutralisait déjà, mais avec un retard : la
	   déclaration ci-dessus la fait basculer à la FIN du fondu sortant,
	   pour que le texte ne disparaisse pas d'un coup. Il restait donc une
	   demi-seconde, au retour d'Info vers la home, où le calque était à
	   peu près transparent et pourtant seul à recevoir les clics —
	   mesuré : à +400ms, l'élément sous la photo du centre était encore
	   .about-bio. Un visiteur qui revient et touche aussitôt la photo ne
	   déclenchait rien.

	   pointer-events, lui, n'a aucune raison d'être différé : on veut
	   rendre la main dès l'instant où l'on quitte Info. Les deux
	   propriétés disent la même chose à deux échéances, et c'est
	   volontaire. */
	pointer-events: none;
}

/* Deux classes, deux moments : fl-to-about pendant le geste, fl-about
   une fois installé. Le calque doit rester visible dans les deux. */
body.fl-to-about .fl-about-overlay,
body.fl-about .fl-about-overlay {
	opacity: 1;
	visibility: visible;
	transition: opacity var(--about-text-duration) var(--about-fold-ease) var(--about-text-delay),
	            visibility 0s;

	/* Le calque reprend la main dès le début du pli : ses liens mailto/tel
	   doivent être cliquables, et le reste de la page ne doit plus l'être.
	   C'est la contrepartie exacte du pointer-events:none de l'état de
	   repos. */
	pointer-events: auto;
}

/* ON PART D'ABOUT VERS L'OVERVIEW : la bio s'en va.

   fl-about reste posée pendant tout le trajet — c'est elle qui maintient
   le header en position, et le retirer le ferait sauter au milieu du
   geste. Il faut donc être PLUS SPÉCIFIQUE qu'elle pour faire sortir le
   calque, d'où les deux classes cumulées ici. */
body.fl-about.fl-to-overview .fl-about-overlay {
	opacity: 0;
	visibility: hidden;
	transition: opacity var(--about-text-duration) var(--about-fold-ease),
	            visibility 0s linear var(--about-text-duration);

	/* Même raison que l'état de repos : fl-about reste posée pendant tout
	   le trajet, donc sans cette ligne le calque garderait le
	   pointer-events:auto de sa règle d'état et continuerait d'intercepter
	   les clics par-dessus la mosaïque qui arrive. */
	pointer-events: none;
}

/* ------------------------------------------------------------------ */
/* Le pli                                                              */
/* ------------------------------------------------------------------ */

/* LES TRANSITIONS SONT SUR L'ÉTAT DE REPOS, jamais dans la règle d'état.
   Trois fois ce piège a coûté une correction sur ce site : une transition
   qui ne vit que dans la règle de l'état d'arrivée disparaît EN MÊME
   TEMPS que la classe, et le retour se fait d'un bloc.

   Ce qui varie selon le sens ne passe donc PAS par une seconde
   déclaration, mais par des variables lues depuis celle-ci. Une propriété
   personnalisée redéfinie dans la règle d'état est bien prise en compte :
   le navigateur lit les propriétés transition-* dans l'état d'ARRIVÉE,
   variables résolues comprises. Même procédé que --tile-delay dans
   overview.css.

   Le bord de coupe balaie vers la droite, donc la couche se referme sur
   son bord droit. Aucun calcul en JS, aucune coordonnée à mesurer : les
   pourcentages se rapportent à la boîte de chaque élément, qui est déjà à
   la bonne place.

   Trois variables suffisent à distinguer les couches :
     --about-fold-span   sa durée propre, tirée de sa largeur ;
     --about-fold-lead   quand elle part À L'ALLER ;
     --about-fade-offset où tombe son fondu dans son pli : au repos à 0
                         (elle réapparaît dès le début de son dépliage, on
                         doit la voir s'ouvrir), à la fin du pli dans
                         l'état. */
.home-beige,
.fl-home-frame::before,
.fl-home-stack {
	/* LE MASQUE. Le dégradé va de transparent (à gauche du bord) à opaque
	   (à droite) : tout ce qui est à gauche de --about-wipe a disparu, et
	   la bascule s'étale sur --about-wipe-edge au lieu de tenir sur un
	   pixel. Faire glisser --about-wipe de 0% à 110% referme donc la
	   couche vers la droite, exactement comme le faisait clip-path, mais
	   avec un bord qui s'éteint.

	   110% et pas 100% : il faut que même la queue du dégradé soit sortie
	   de la boîte, sinon il resterait un voile sur le bord droit. */
	--about-wipe: 0%;
	-webkit-mask-image: linear-gradient( to right,
		transparent calc( var(--about-wipe) - var(--about-wipe-edge) ),
		#000 var(--about-wipe) );
	mask-image: linear-gradient( to right,
		transparent calc( var(--about-wipe) - var(--about-wipe-edge) ),
		#000 var(--about-wipe) );
	--about-fade-duration: calc( var(--about-fold-span) * var(--about-fade-share) );

	/* DÉLAI AU RETOUR — calculé, jamais recopié : c'est le miroir exact du
	   départ à l'aller, dans un geste qui dure --about-fold-duration.

	   Les délais étaient comptés depuis le début dans les deux sens, ce
	   qui ne marchait que tant que toutes les couches avaient la même
	   durée. Depuis qu'elles sont proportionnelles à leur largeur, ça
	   décale tout : le montage se refermait de 120 à 570ms (donc 330ms
	   AVANT le beige), et se rouvrait de 120 à 570 aussi — il était donc
	   entièrement révélé alors que le beige n'était ouvert qu'au tiers, et
	   la photo apparaissait avant son fond.

	   La formule vaut aussi pour le beige : 900 - 0 - 900 = 0. Une seule
	   règle, pas de cas particulier. */
	--about-fold-delay: calc(
		var(--about-fold-duration) - var(--about-fold-lead) - var(--about-fold-span)
	);
	transition:
		--about-wipe var(--about-fold-span) var(--about-fold-ease) var(--about-fold-delay),
		opacity var(--about-fade-duration) var(--about-fold-ease)
			calc( var(--about-fold-delay) + var(--about-fade-offset) );
}

/* Le beige : le plus large, donc le plus lent, et le premier à bouger
   dans les deux sens. C'est le plus grand élément de l'écran : c'est lui
   qui accuse réception du clic. */
.home-beige {
	--about-fold-span: var(--about-fold-duration);
	--about-fold-lead: 0ms;
	--about-fade-offset: 0ms;
}

/* LE MONTAGE — le passe-partout blanc et le tirage qu'il porte. Deux
   éléments, VALEURS RIGOUREUSEMENT IDENTIQUES, et il faut que ça le
   reste : le moindre décalage entre eux mettrait le bord de coupe du
   tirage à gauche de celui du blanc, donc la photo déborderait sur le
   beige. Ils se referment comme un seul objet.

   (Ils restent deux règles plutôt qu'un pli posé sur .fl-home-frame parce
   que .fl-home-stack a justement été créé pour pouvoir les traiter
   séparément — on s'en est servi, on pourrait s'en resservir.) */
.fl-home-frame::before,
.fl-home-stack {
	--about-fold-span: calc( var(--about-fold-duration) * var(--about-fold-ratio) );
	--about-fold-lead: var(--about-fold-stagger);
	--about-fade-offset: 0ms;
}

/* La légende ne se replie pas : c'est du texte, et rogner du texte se lit
   comme un bug. Elle s'efface simplement — immédiatement à l'aller, et
   donc, en miroir, en toute fin de retour. */
.home-caption {
	--about-caption-duration: calc( var(--about-fold-duration) * var(--about-fade-share) );
	--about-fade-delay: calc( var(--about-fold-duration) - var(--about-caption-duration) );
	transition: opacity var(--about-caption-duration) var(--about-fold-ease) var(--about-fade-delay);
}

/* ------------------------------------------------------------------ */
/* ÉTAT PLIÉ                                                           */
/* ------------------------------------------------------------------ */

/* Deux choses seulement basculent ici, et aucune n'est un chiffre écrit à
   la main : le délai de départ redevient --about-fold-lead (au repos il
   en est le miroir, cf. plus haut), et le fondu passe du début à la fin
   du pli — la couche est déjà pâle quand elle se referme, là où au retour
   elle réapparaît en s'ouvrant. Ni durée, ni courbe, ni ordre, ni
   transition ne sont redéclarés. */
body.fl-to-about .home-beige,
body.fl-to-about .fl-home-frame::before,
body.fl-to-about .fl-home-stack {
	--about-wipe: calc( 100% + var(--about-wipe-edge) );
	opacity: 0;
	--about-fold-delay: var(--about-fold-lead);
	--about-fade-offset: calc( var(--about-fold-span) * ( 1 - var(--about-fade-share) ) );
}

/* ------------------------------------------------------------------ */
/* About <-> Overview : le beige ne se replie pas, il se fond          */
/* ------------------------------------------------------------------ */

/* SUR CE TRAJET LE BEIGE NE BALAIE PAS. Il occupe déjà tout l'écran et
   il n'y a aucun montage à refermer : le faire défiler de droite à gauche
   en faisait un rideau, un mouvement qui existait pour lui-même. Il ne
   fait donc que passer du blanc de la page au beige, et inversement — un
   changement de fond, pas un geste.

   --about-wipe est forcé ouvert. Cette règle vient APRÈS body.fl-to-about
   et à spécificité égale c'est la dernière qui gagne : le beige reste
   déployé pendant que le montage, lui, se referme bien par la règle du
   dessus. Une seule classe distingue les deux comportements.

   La durée est celle de la MOSAÏQUE et non celle du pli : sur ce trajet
   le fond et les tirages appartiennent au même geste, ils doivent se
   poser ensemble. */
body.fl-beige-fade .home-beige {
	--about-wipe: 0%;
	transition: opacity var(--overview-morph-duration) var(--overview-morph-ease);
}

/* La légende part avec le montage, immédiatement : rien ne doit rester en
   place pendant que le beige s'ouvre. */
body.fl-to-about .home-caption {
	opacity: 0;
	--about-fade-delay: 0ms;
}

body.fl-to-about .home-work {
	pointer-events: none;
}

/* ------------------------------------------------------------------ */
/* La colonne de gauche : l'index cède la place à la bio               */
/* ------------------------------------------------------------------ */

/* Même colonne, même ligne de départ (row 2) : ce n'est pas une
   disparition suivie d'une apparition, c'est une substitution sur place.
   Le déplacement est minuscule — 8px — parce que l'effet doit se lire
   comme un remplacement, pas comme un défilé. */
/* LES TITRES PARTENT ET REVIENNENT UN PAR UN, pas en bloc. L'index était
   la seule chose de la page à se comporter comme un rectangle opaque
   pendant que tout le reste avait des temps propres.

   ET C'EST UN FONDU SEUL, SANS DÉPLACEMENT — c'est la condition pour que
   ça ne tombe pas dans l'effet. La version d'avant décalait l'index de
   8px vers le haut : additionné à une séquence, ça aurait fait une
   cascade, le cliché du motion design. Le décalage seul, sur des lignes
   qui ne bougent pas, ne fait qu'épouser la façon dont on lit une liste —
   en série, de haut en bas. C'est aussi pour ça qu'il ne s'inverse PAS au
   retour : une liste se lit toujours par le haut, quel que soit le sens
   du geste. C'est la seule chose ici qui échappe volontairement à la
   symétrie.

   45ms, la valeur des tuiles de l'Overview (--overview-tile-stagger) :
   les deux vues emploient le même vocabulaire, autant qu'elles aient le
   même tempo. Le rang de chaque titre arrive en --fl-i, posé côté PHP
   (cf. template-parts/home-content.php) parce que le nombre de projets
   change et qu'une pile de :nth-child ne saurait pas jusqu'où aller. */
.home-index {
	--about-index-stagger: 45ms;
}

/* ATTENTION : cette règle REDÉCLARE la transition de couleur posée sur
   .home-index a dans theme.css (survol, et surlignage du projet affiché).
   Il fallait ajouter l'opacité à la MÊME déclaration — un second
   "transition" sur le même sélecteur écraserait le premier au lieu de s'y
   ajouter. Si le réglage de couleur bouge là-bas, le répercuter ici. */
.home-index a {
	transition:
		color var(--index-highlight-duration) var(--caption-reveal-ease),
		opacity var(--about-text-duration) var(--about-fold-ease)
			calc( var(--fl-i, 0) * var(--about-index-stagger) );
}

body.fl-to-about .home-index {
	pointer-events: none;
}

body.fl-to-about .home-index a {
	opacity: 0;
}

/* Une fois le geste terminé, toute la grille de la home sort du flux —
   il ne reste que le calque. Posé seulement à la fin : pendant le geste,
   l'index doit rester là pour s'effacer. */
.home-layout.is-about-done {
	display: none;
}

/* ------------------------------------------------------------------ */
/* Petit écran                                                         */
/* ------------------------------------------------------------------ */

@media (max-width: 900px) {
	.fl-about-overlay {
		grid-template-columns: 1fr;
	}

	.about-bio,
	.about-details {
		grid-column: 1 / -1;
	}
}

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

/* On ne raccourcit pas, on supprime. Le JS n'intercepte alors plus le
   clic du tout et "About" redevient un lien ordinaire vers /about/,
   servi par page-about.php. */
@media (prefers-reduced-motion: reduce) {
	.fl-about-overlay,
	.home-beige,
	.fl-home-stack,
	.fl-home-frame::before,
	.home-caption,
	.home-index,
	.home-index a {
		transition: none;
	}
}
