/* =================================================================
   Youen Frémont — Section projets, cartes, vitrine, filtres, présentation
   Feuille 3 sur 8. La feuille unique a été découpée le 2026-09-19 aux
   frontières de ses sections, sans qu'une règle ne change de place : les huit
   fichiers se chargent dans l'ordre de base.njk, et cet ordre EST la cascade.
   Les tokens et les surfaces vivent dans style.css, chargée en premier.
   ================================================================= */

/* -----------------------------------------------------------------
   8. Section projets
   ----------------------------------------------------------------- */
.section-projets {
  padding: var(--pas-8) var(--marge-page) var(--pas-7);
}

.entete-section {
  display: grid;
  gap: var(--pas-4);
  margin-bottom: var(--pas-6);
}

.entete-section__titre {
  display: grid;
  font-size: var(--texte-l);
  font-family: var(--police-titre);
  font-weight: var(--graisse-forte);
  line-height: var(--interligne-titre);
  letter-spacing: var(--approche-titre);
  text-transform: uppercase;
}

.grille-projets {
  display: grid;
  gap: var(--pas-4);
}

/* La carte est la photo, rien d'autre : ni cadre, ni bandeau sous l'image. Le
   titre est posé dessus, l'année ne se découvre qu'au survol. Elle n'a pas de
   fond propre : le visuel la remplit d'un bord à l'autre, et c'est lui qui porte
   l'image ou, tant qu'elle manque, la couleur de la page. */
.carte-projet {
  position: relative;
  overflow: hidden;
  border-radius: var(--rayon-m);
}

/* Survol et focus clavier : la carte se soulève. Le déplacement lui-même est
   dans le bloc « motion », l'ombre suffit à signaler l'état sans lui. */
.carte-projet:hover,
.carte-projet:focus-within {
  box-shadow: var(--ombre);
}

/* Le titre prend la couleur de la page au survol, décision du 2026-08-19 : c'est
   le seul endroit où la carte se colore. Sur l'emplacement gris il tient de 5,2
   à 9,1:1 selon la page.
   Sur une photo, c'est la plaque voilée et floutée du titre qui tient le
   contraste, réglée le 2026-08-21 — voir --voile-titre-carte. */
.carte-projet:hover .carte-projet__titre,
.carte-projet:focus-within .carte-projet__titre {
  color: var(--titre);
}

/* Le lien du titre couvre la carte entière : elle devient cliquable partout,
   sans imbriquer de second lien. */
/* Toute la carte est cliquable. Le lien reste posé sur le titre — un seul lien
   par carte, donc un seul arrêt au clavier et un nom accessible qui est le titre
   du projet — et c'est son pseudo-élément qui s'étend sur la carte entière.
   Il se cale sur .carte-projet__legende, qui couvre déjà la carte. Le voile du
   titre est pour cette raison porté par une plaque intérieure : un
   backdrop-filter ferait du titre un bloc conteneur, et ce pseudo-élément ne
   couvrirait plus que le titre. Constaté le 2026-08-21. */
.carte-projet__lien::after {
  position: absolute;
  inset: 0;
  z-index: 1;
  content: "";
}

/* Le lien couvre toute la carte : le souligner au survol n'aurait aucun sens,
   c'est le soulèvement et l'année qui signalent l'état. */
.carte-projet__titre a:hover {
  text-decoration: none;
}

.carte-projet__visuel {
  aspect-ratio: 3 / 2;
  background-color: var(--emplacement);
}

.carte-projet__visuel img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* La légende est posée sur la photo sans prendre de place dans le flux : un
   titre long reste dans le cadre de l'image au lieu d'allonger la carte, et
   toutes les cartes d'une même rangée gardent la même hauteur. */
.carte-projet__legende {
  position: absolute;
  inset: 0;
  display: grid;
  place-content: center;
  justify-items: center;
  padding: var(--pas-4);
  text-align: center;
}

/* Le titre est posé sur l'emplacement de l'image, pas sur le papier : il prend
   donc l'encre de l'emplacement. Tant qu'aucune photo n'est fournie, celui-ci
   est l'aplat de la page et le couple est contrasté par construction — jamais
   sous 5,47:1 sur les six déclinaisons.
   Sur une photo, aucune couleur ne tiendrait seule — titre en aplat, il tombait
   à 1,32:1 sur un plan clair. C'est la plaque voilée et floutée qui répond,
   tranchée le 2026-08-21 avec les images en main. */
.carte-projet__titre {
  max-width: 100%;
  color: var(--emplacement-texte);
  font-size: var(--texte-titre-carte);
  font-family: var(--police-titre);
  font-weight: var(--graisse-forte);
  line-height: var(--interligne-titre);
  letter-spacing: var(--approche-titre);
  text-transform: uppercase;
  text-wrap: balance;
  overflow-wrap: break-word;
}

/* L'emplacement en attente garde les capitales du titre : sinon la seule chose
   qu'on voit à l'écran, tant qu'aucun projet n'a de titre, ne ressemble pas au
   résultat. Il reste en italique et en retrait, donc toujours reconnaissable. */
/* La plaque porte le voile et le flou qui détachent le titre de la photo. */
.carte-projet__plaque {
  display: inline-block;
  max-width: 100%;
  padding: var(--pas-2) var(--pas-3);
  border-radius: var(--rayon-s);
  background-color: color-mix(in srgb, var(--fond) var(--voile-titre-carte), transparent);
  backdrop-filter: blur(var(--flou-titre-carte));
}

/* Sur une carte, le sous-titre suit le titre dans la même plaque : il en fait
   partie, il ne s'en détache pas. Corps réduit et encre atténuée — le titre
   reste ce qu'on lit d'abord.
   `display: block` pour qu'il passe à la ligne : accolé, « BOOMIN FEST ARTISTE »
   se lit comme un seul titre, ce qui est exactement ce qu'on cherche à éviter.
   Traitement validé tel quel le 2026-09-19. */
.carte-projet__sous-titre {
  display: block;
  font-size: var(--texte-s);
  font-weight: var(--graisse-moyenne);
  letter-spacing: var(--approche-libelle);
  opacity: 0.72;
}

.carte-projet__titre .a-renseigner {
  text-transform: uppercase;
  letter-spacing: var(--approche-titre);
}

/* Les libellés d'attente d'une carte sont posés sur l'emplacement de l'image,
   pas sur le papier : ils suivent son encre. Sans cette règle, ils gardaient le
   noir atténué du panneau et disparaissaient sur une carte bleue ou verte. */
.carte-projet .a-renseigner {
  color: var(--emplacement-texte-attenue);
}

/* Le rôle et l'année restent dans le HTML, ils ne sont que masqués à l'œil :
   les lecteurs d'écran les lisent, et ils réapparaissent au survol comme au
   focus clavier. Le pied sort du flux : sans cela il pousserait le titre vers
   le haut même invisible, et le titre ne serait pas au centre. */
.carte-projet__pied {
  position: absolute;
  inset-inline: 0;
  inset-block-end: var(--pas-4);
  display: grid;
  justify-items: center;
  gap: var(--pas-1);
  padding-inline: var(--pas-4);
  opacity: 0;
  /* Il ne paraît pas sur place : il monte d'une demi-ligne en même temps. Le
     geste prend une direction, pour rien de plus qu'une seconde propriété. */
  transform: translateY(0.5em);
}

.carte-projet:hover .carte-projet__pied,
.carte-projet:focus-within .carte-projet__pied {
  opacity: 1;
  transform: translateY(0);
}

/* Sous un filtre de métier, le rôle n'apprend plus rien : toutes les cartes
   affichées le partagent, c'est même la raison pour laquelle elles sont là.
   L'année, elle, reste. L'attribut est posé par main.js. */
.grille-projets[data-filtre] .carte-projet__role {
  display: none;
}

.carte-projet__role,
.carte-projet__annee {
  max-width: 100%;
  /* Même plaque que le titre, en plus discrète : sans elle, ces deux libellés
     étaient les seuls à reposer sur la photo nue, et le contraste n'y tenait
     que par chance. Le voile reprend le fond de la surface, seul fond dont la
     charte garantisse qu'il contraste avec l'encre, quelle que soit la page et
     quelle que soit la photo. */
  padding: var(--pas-1) var(--pas-2);
  border-radius: var(--rayon-s);
  background-color: color-mix(in srgb, var(--noir) var(--voile-legende-carte), transparent);
  backdrop-filter: blur(var(--flou-titre-carte));
  /* Le blanc en dur, et non l'encre de l'emplacement : c'est un libellé posé
     sur sa propre plaque sombre, pas sur la surface. Le seul endroit du site où
     un composant nomme une neutre directement — la plaque en répond. */
  color: var(--blanc);
  font-size: var(--texte-xs);
  font-weight: var(--graisse-moyenne);
  letter-spacing: var(--approche-libelle);
  text-align: center;
}

/* Le rôle reste la mention de service des deux, mais il ne se distingue plus
   par la couleur — les deux sont en blanc sur la même plaque. Ce sont les
   capitales et l'ordre de lecture qui le tiennent au second plan. */
.carte-projet__role {
  text-transform: uppercase;
}

/* Sans survol — un écran tactile —, rien de tout cela ne se découvrirait. */
@media (hover: none) {
  .carte-projet__pied {
    opacity: 1;
    transform: none;
  }
}

/* --- Vitrine des projets mis en avant -----------------------------------
   Une boîte qui ne laisse voir qu'un projet, la moitié du précédent et la
   moitié du suivant. Elle se parcourt d'elle-même : c'est une zone de
   défilement ordinaire, calée projet par projet — molette, pavé tactile,
   doigt, barre et clavier fonctionnent sans une ligne de script.
   Le script n'ajoute qu'une chose, facultative : le titre du projet en face. */

/* Le cadre tire sa hauteur de sa propre largeur : deux cartes en 3/2 plus deux
   gouttières, soit exactement un projet entier et deux moitiés. La largeur de
   référence vient du conteneur, seule mesure disponible en CSS — un pourcentage
   de hauteur se rapporterait à la hauteur du parent, pas à sa largeur.
   Plafonné à la fenêtre moins les marges de la section depuis le 2026-09-20 :
   sur un écran large, deux cartes faisaient 1 500 px, plus que la fenêtre. On
   arrivait sur 500 px de blanc avant la première image, et le titre en face,
   centré sur ce cadre, tombait hors champ. Deux cartes entières n'existent
   guère qu'en dessous de 48 em, où le cadre est étroit. */
.vitrine {
  container-type: inline-size;
}

.vitrine__cadre {
  /* Le cadre est à son tour conteneur, en hauteur aussi : c'est sa hauteur
     réelle, plafonnée ou non, que la liste lit pour se centrer dedans. */
  container-type: size;
  height: min(
    calc(100cqw * 2 / 3 * 2 + var(--pas-5) * 2),
    calc(100svh - var(--pas-9) - var(--pas-8))
  );
  overflow-y: auto;
  border-radius: var(--rayon-m);
  /* Un calage impératif : on ne s'arrête jamais entre deux projets. */
  scroll-snap-type: y mandatory;
  /* La barre ne courrait que le long des cartes, et la carte coupée en bas dit
     déjà qu'il y a une suite. */
  scrollbar-width: none;
}

.vitrine__cadre::-webkit-scrollbar {
  display: none;
}

/* Le retrait vaut la moitié de ce que le cadre laisse autour d'une carte : au
   repos, le premier projet est au milieu du cadre et rien ne dépasse au-dessus
   de lui ; en fin de liste, le dernier l'est aussi. Quand le cadre fait ses
   deux cartes, ça vaut une demi-carte plus une gouttière ; quand la fenêtre le
   plafonne, ça vaut ce qui reste. Sans lui, on arriverait sur deux projets
   entiers. */
.vitrine__liste {
  display: grid;
  gap: var(--pas-5);
  padding-block: calc((100cqh - 100cqw * 2 / 3) / 2);
}

.vitrine__liste > li {
  scroll-snap-align: center;
}

/* L'intitulé de section passe en pastille, comme la référence : ce n'est plus
   lui qui porte, c'est le titre du projet en vue. Les deux morceaux du titre
   se remettent sur une ligne — leur empilement n'avait de sens qu'en gros. */
.section-projets:has(.vitrine) .entete-section__titre {
  display: inline-flex;
  flex-wrap: wrap;
  gap: 0 0.35em;
  justify-self: start;
  padding: 0.45em 1.1em;
  border-radius: var(--rayon-pilule);
  /* La pastille prend la couleur de la page : c'est le seul aplat du haut du
     panneau, et il annonce celle qu'on retrouvera sur les cartes. */
  background-color: var(--remplissage);
  color: var(--remplissage-texte);
  /* Sur l'accueil ce titre n'en est plus un : c'est une pastille de 11 px. Il
     reprend donc la fonte du corps, comme tous les libellés — une fonte
     d'affiche à cette taille se referme et ne sert à rien. */
  font-family: var(--police);
  font-size: var(--texte-xs);
  font-weight: var(--graisse-moyenne);
  letter-spacing: var(--approche-libelle);
}

/* Le titre du projet en vue. Il double ce qui nomme déjà chaque carte : il est
   donc décoratif, et masqué aux lecteurs d'écran, qui l'entendraient changer à
   chaque cran de molette pour une information qu'ils viennent de lire. */
/* Seul titre du site à ne pas prendre la couleur, sur ta demande du 2026-08-19 :
   il double ce qui nomme déjà chaque carte, il change à chaque cran de
   défilement, et en couleur il concurrençait les cartes qu'il annonce. Il garde
   donc l'encre du papier. */
.vitrine__encours {
  font-size: var(--texte-l);
  font-family: var(--police-titre);
  font-weight: var(--graisse-forte);
  line-height: var(--interligne-titre);
  letter-spacing: var(--approche-titre);
  text-wrap: balance;
}

/* Le titre roule avec le défilement : celui qu'on quitte monte et sort par le
   haut, celui qui vient entre par le bas, poussés par le geste lui-même et non
   par un minuteur. Il n'y a donc jamais d'instant sans titre — c'est ce trou que
   le fondu laissait voir, et rien ne peut se désynchroniser puisque rien n'est
   compté en secondes.
   Deux calques dans la même case de grille : la boîte prend la hauteur du plus
   grand des deux, et rien ne saute quand un titre tient sur deux lignes.
   L'attribut est posé par main.js : sans lui, le titre reste un paragraphe. */
.vitrine__encours[data-roulement] {
  display: grid;
  overflow: hidden;
  /* L'interligne des titres est serré (0,92) : accents et jambages sortent de
     la boîte de ligne, et le rognage les couperait. Cette réserve leur laisse la
     place, la marge négative la reprend — la mise en page ne bouge pas d'un
     pixel. */
  padding-block: 0.18em;
  margin-block: -0.18em;
}

.vitrine__encours[data-roulement] > span {
  grid-area: 1 / 1;
}

/* Mouvement refusé : pas de roulement, et surtout pas deux titres l'un sur
   l'autre. Le calque du bas disparaît, et le script bascule celui du haut sur le
   projet le plus proche. */
.vitrine__encours[data-roulement] > span:last-child {
  visibility: hidden;
}

/* Sans script, il resterait bloqué sur le premier projet quel que soit celui
   qu'on regarde : mieux vaut qu'il ne s'affiche pas. */
html:not(.js) .vitrine__encours {
  display: none;
}

/* Le masquage de la légende des cartes n'a lieu qu'à partir de 48 em, avec la
   colonne collante — voir plus bas. Sur téléphone il n'y a pas de colonne, et
   des photos sans nom ne diraient plus quel projet est lequel. */

/* -----------------------------------------------------------------
   9. Présentation
   ----------------------------------------------------------------- */
/* Une seule photo, bord à bord, en tête du panneau. */
.image-pleine {
  aspect-ratio: 16 / 10;
  overflow: hidden;
  background-color: var(--emplacement);
}

.image-pleine img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.presentation {
  /* La maquette étire le texte d'une marge à l'autre ; on plafonne la mesure,
     au-delà de ~90 signes par ligne l'œil perd le début de la ligne suivante. */
  max-width: 90ch;
  margin-inline: auto;
  padding: var(--pas-7) var(--marge-page) var(--pas-8);
}

.presentation__titre {
  margin-bottom: var(--pas-6);
  color: var(--titre);
  font-size: var(--texte-l);
  font-family: var(--police-titre);
  font-weight: var(--graisse-forte);
  line-height: var(--interligne-titre);
  letter-spacing: var(--approche-titre);
  text-align: center;
  text-transform: uppercase;
}

.presentation p + p {
  margin-top: var(--pas-4);
}

/* Un paragraphe qui suit une grille de crédits en est détaché : sans cela il se
   lit comme une dernière ligne de la grille. */
.presentation .credits + p {
  margin-top: var(--pas-5);
}

/* Bio de la page Contact : titre à gauche, texte à droite, plein
   cadre sur la couleur de la page. Empilés sur téléphone, deux colonnes dès
   48 em — même palier que la landing d'une page projet (planche--landing),
   pour la même raison : c'est là que le texte a la place de respirer à côté
   d'une colonne fixe. */
.bio {
  display: grid;
  gap: var(--pas-5) var(--pas-6);
  padding: var(--pas-8) var(--marge-page);
}

.bio__titre {
  color: var(--titre);
  font-size: var(--texte-titre-projet);
  font-family: var(--police-titre);
  font-weight: var(--graisse-forte);
  line-height: var(--interligne-titre);
  letter-spacing: var(--approche-titre);
  text-transform: uppercase;
}

.bio__texte {
  display: grid;
  gap: var(--pas-4);
  max-width: 70ch;
}

@media (min-width: 48em) {
  .bio {
    grid-template-columns: minmax(0, 38%) 1fr;
    align-items: start;
  }
}
