/* ============================================================
   home.css · accueil (fond clair chaleureux)
   Hero immersif + index éditorial des projets.
   ============================================================ */

/* ===== HERO ===== */
.hero{height:100vh;min-height:580px;position:relative;overflow:hidden;display:flex;align-items:center;background:#ffffff}

/* instances de halos du hero (fond chaud) */
/* ces halos-ci dérivent en boucle : le calque dédié est justifié */
.hb-cool,.hb-warm1,.hb-warm2,.hb-warm3,.hb-warm4,.hb-warm5{will-change:transform}
.hb-cool{width:52vw;height:40vw;left:6%;bottom:-10vw;opacity:.16;
  background:radial-gradient(circle at 45% 50%,var(--c-connect),transparent 68%);
  filter:blur(100px);animation:coolmove calc(34s / var(--motion)) ease-in-out infinite}
.hb-warm1{width:60vw;height:60vw;background:var(--c-accent);top:-14vw;left:-6vw;opacity:.5;filter:blur(110px);animation:warm1 calc(18s / var(--motion)) ease-in-out infinite}
.hb-warm2{width:32vw;height:32vw;background:var(--halo-tr);top:2vw;right:4vw;opacity:.5;filter:blur(80px);animation:warm2 calc(22s / var(--motion)) ease-in-out infinite}
.hb-warm3{width:46vw;height:46vw;background:var(--halo-br);bottom:-14vw;right:6%;opacity:.4;filter:blur(105px);animation:warm3 calc(20s / var(--motion)) ease-in-out infinite}
.hb-warm4{width:22vw;height:22vw;background:var(--halo-br);bottom:8vw;left:10%;opacity:.4;filter:blur(70px);animation:warm4 calc(24s / var(--motion)) ease-in-out infinite}
.hb-warm5{width:38vw;height:38vw;background:var(--c-accent);top:24%;left:30%;opacity:.3;filter:blur(120px);animation:warm5 calc(26s / var(--motion)) ease-in-out infinite}
@keyframes warm1{0%,100%{transform:translate(0,0) scale(1)}50%{transform:translate(7vw,6vw) scale(1.14)}}
@keyframes warm2{0%,100%{transform:translate(0,0) scale(1)}50%{transform:translate(-6vw,7vw) scale(1.16)}}
@keyframes warm3{0%,100%{transform:translate(0,0) scale(1)}50%{transform:translate(-7vw,-5vw) scale(1.12)}}
@keyframes warm4{0%,100%{transform:translate(0,0) scale(1)}50%{transform:translate(6vw,-6vw) scale(1.18)}}
@keyframes warm5{0%,100%{transform:translate(0,0) scale(1)}50%{transform:translate(5vw,4vw) scale(1.2)}}
@keyframes coolmove{0%,100%{transform:translate(0,0) scale(1)}50%{transform:translate(4vw,-3vw) scale(1.1)}}

.hero-inner{position:relative;z-index:2;max-width:var(--colonne);margin:0 auto;padding:0 clamp(20px,5vw,64px);width:100%}
.hero h1{font-family:var(--title-font),serif;font-weight:400;font-size:clamp(42px,8vw,112px);line-height:.96;letter-spacing:-.03em;max-width:13ch}
.hero h1 em{font-style:italic}

/* mot qui se réécrit */
#morph{font-style:italic;color:var(--morph-color);position:relative;cursor:pointer}
.cursor{display:inline-block;width:3px;height:.82em;background:var(--morph-color);margin-left:3px;vertical-align:baseline;animation:blink 1s step-end infinite;transform:translateY(.06em)}
@keyframes blink{0%,100%{opacity:1}50%{opacity:0}}

/* La cascade : chaque élément du hero part un peu après le précédent. La
   première visite a droit à la mise en scène complète. Quand on revient
   (html.revu, posé dans le head d'après localStorage), tout part un cran
   plus tôt : le même mouvement, lisible une demi-seconde plus vite. */
/* Sur un téléphone, ce n'est pas `max-width` qui borne le titre mais la
   colonne : 320 px de texte disponible à 360 px d'écran. Le plus long des
   mots qui se réécrivent y passait à la ligne. Trois pixels de corps en
   moins suffisent, et personne ne les voit. */
@media (max-width:400px){.hero h1{font-size:clamp(39px,8vw,112px)}}
.fade-line{opacity:0;transform:translateY(20px);animation:rise .8s cubic-bezier(.2,.8,.2,1) forwards}
.hero h1 .fade-line:nth-child(1){animation-delay:.05s}
.hero h1 .fade-line:nth-child(2){animation-delay:.2s}
.hero h1 .fade-line:nth-child(3){animation-delay:.35s}
.revu .hero h1 .fade-line:nth-child(2){animation-delay:.15s}
.revu .hero h1 .fade-line:nth-child(3){animation-delay:.25s}
.revu .hero .sub{animation-delay:.4s}
.revu .hero .hero-facts{animation-delay:.5s}
.revu .scroll{animation-delay:.65s}
.hero .sub{font-size:clamp(15px,1.8vw,19px);color:var(--ink-soft);margin-top:26px;
  /* 94ch donnait des lignes de 78 caractères : au-delà de 75, l'oeil perd
     le début de la ligne suivante. 58ch fait trois lignes plus courtes. */
  max-width:min(58ch,70vw);opacity:0;animation:rise .8s .55s forwards;
  /* deux lignes de largeur voisine, au lieu d'une pleine suivie d'un reste */
  text-wrap:balance}
/* Les faits, sous l'accroche. Même voix, même graisse, même couleur que la
   phrase du dessus : ce sont deux paragraphes du même texte, rien ne justifie
   qu'ils aient l'air de venir de deux endroits différents. Seul le retard à
   l'apparition les sépare. */
.hero .hero-facts{font-size:clamp(15px,1.8vw,19px);line-height:inherit;
  color:var(--ink-soft);margin-top:1em;max-width:min(58ch,70vw);
  opacity:0;animation:rise .8s .75s forwards;text-wrap:pretty}
@keyframes rise{to{opacity:1;transform:none}}

.scroll{position:absolute;bottom:34px;left:50%;transform:translateX(-50%);font-size:13px;color:var(--ink-soft);display:flex;flex-direction:column;align-items:center;gap:10px;z-index:2;opacity:0;animation:rise .8s .9s forwards;text-decoration:none}
.scroll .mouse{width:24px;height:38px;border:1.5px solid var(--ink-soft);border-radius:13px;position:relative}
.scroll .mouse::after{content:"";position:absolute;top:7px;left:50%;transform:translateX(-50%);width:3px;height:7px;border-radius:2px;background:var(--ink-soft);animation:sc 1.6s ease-in-out infinite}
@keyframes sc{0%{opacity:0;transform:translate(-50%,0)}40%{opacity:1}100%{opacity:0;transform:translate(-50%,11px)}}

/* ===== INDEX ÉDITORIAL ===== */
.index{position:relative;z-index:1;max-width:var(--colonne);margin:0 auto;padding:var(--s-6) clamp(20px,5vw,64px) 0;min-height:100vh;display:flex;flex-direction:column;justify-content:flex-start;scroll-margin-top:28px}
/* L'entête de section porte la bascule pro / perso : à 12px en gris
   pâle, on ne la voyait pas passer. */
.eyebrow{font-size:13px;font-weight:600;letter-spacing:.16em;color:var(--ink);
  padding-bottom:var(--s-2);border-bottom:1px solid rgba(0,0,0,.14)}
/* la bascule pro -> perso se lit au premier coup d'oeil : c'est le grand
   blanc qui la marque, pas seulement le titre */
.eyebrow.mt{margin-top:var(--s-6)}
/* Le décalage et la couleur partaient sur deux durées et deux courbes
   différentes : le titre glissait avant de se colorer, ce qui se voyait comme
   deux gestes au lieu d'un. Même durée, même courbe, et la couleur prend son
   temps maintenant que la ligne ne se déplie plus : c'est devenu le seul
   mouvement de la ligne, il n'a plus besoin d'être rapide. */
/* Les respirations de la liste sont écrites en clair, et pas sur l'échelle
   --s-*, parce qu'elles ont été réglées à la mesure : la liste faisait 1659 px,
   soit près de deux écrans à faire défiler, et 82 % de cette hauteur venait des
   huit lignes de projet. Resserrées ici, elles la ramènent à 1387 px, un sixième
   de moins, sans qu'un seul mot ni une seule taille de titre ne bouge. Toucher
   à --s-3 aurait déplacé le reste du site avec. */
.proj{display:block;text-decoration:none;color:inherit;padding:13px 0;border-bottom:1px solid var(--line);cursor:pointer;transition:padding-left .55s cubic-bezier(.2,.8,.2,1);--line:rgba(0,0,0,.08)}
/* Le mot-clé passe sous le titre, à gauche. À droite il tombait pile
   sous l'aperçu qui suit le curseur, et personne ne le lisait. */
.proj-top{display:block}
.proj-name{display:block;font-family:var(--title-font),serif;font-weight:500;font-size:clamp(26px,4vw,44px);line-height:1;letter-spacing:-.02em;transition:color .55s cubic-bezier(.2,.8,.2,1);text-wrap:balance}
/* Deux niveaux, et pas trois. La description qui se dépliait au survol
   disait à peu près la même chose que l'accroche, dans un corps à peine
   différent : les deux se marchaient dessus et la liste s'allongeait pour
   rien. Il reste la nature du travail et une phrase. Le reste est dans
   l'étude de cas, c'est là qu'il doit être. */
/* La catégorie porte la couleur du projet, en version assombrie : c'est le
   seul endroit de la liste où la couleur peut servir sans coûter en lisibilité,
   et elle donne à chaque ligne son identité avant même le survol. --pci est
   posé sur chaque .proj, à côté de --pc (voir index.html). */
.proj-kind{display:block;font-size:12px;font-weight:600;letter-spacing:.14em;
  text-transform:uppercase;color:var(--pci,var(--ink-faint));margin-bottom:5px;
  transition:color .55s cubic-bezier(.2,.8,.2,1)}
.proj-meta{display:block;margin-top:6px;font-size:clamp(14.5px,1.25vw,15.5px);
  line-height:1.38;letter-spacing:.01em;color:var(--ink-soft);max-width:58ch;
  transition:color .3s;text-wrap:pretty}
.proj:hover{padding-left:24px}

/* L'étiquette « Aperçu » vivait ici. Elle occupait la colonne vide à droite
   des titres et annonçait qu'il y avait quelque chose derrière la ligne. La
   vignette permanente fait les deux, en montrant au lieu d'annoncer. */
.proj:hover .proj-name{color:var(--pcg,var(--ink))}
/* L'accroche ne prend plus la couleur du projet au survol : à cette taille
   il lui faut 4,5:1, et six des neuf teintes tombent sous 2,5:1 sur le crème. */

/* La bande de visuels posée dans la ligne. Elle prend le relais dès qu'il
   n'y a plus assez de place à droite des titres pour l'aperçu flottant :
   sur une tablette, celui-ci devait se poser au-dessus ou en dessous de la
   ligne, et recouvrait alors les projets voisins. Les visuels dans la ligne
   ne cachent rien et se parcourent au doigt. */
.proj-bande,.proj-cta{display:none}
/* Deux conditions, pas une. La largeur d'abord : sous 1050px il n'y a plus
   de marge vide à droite des titres. Mais aussi l'absence de survol : un
   iPad en paysage fait 1194px, l'aperçu flottant y était donc actif alors
   qu'aucun doigt ne déclenche jamais un survol. La liste y restait nue. */
@media (max-width:1050px),(hover:none){
  #hoverwrap{display:none}
  .proj-bande{display:flex;gap:9px;margin-top:19px;overflow-x:auto;overscroll-behavior-x:contain;
    scroll-snap-type:x mandatory;-webkit-overflow-scrolling:touch;
    /* le snap ignore le padding et collait le premier visuel au bord du
       conteneur, 20px à gauche du texte : le point d'accroche doit se
       déclarer lui aussi */
    scroll-padding:0 20px;
    scrollbar-width:none;
    /* De l'air des quatre côtés : le conteneur qui défile rognait l'ombre
       portée. Elle descend de 30px (8 de décalage + 22 de flou), monte de
       14 et déborde de 22 à gauche comme à droite, donc la réserve suit
       ces chiffres. Les marges négatives ramènent ensuite la bande au bord
       du texte, et le débord latéral va se perdre dans la gouttière de la
       page (20px au plus étroit). */
    padding:14px 20px 30px;margin-inline:-20px;margin-bottom:-24px}
  .proj-bande::-webkit-scrollbar{display:none}
  /* le zoom glisse un .zoomable-box autour de chaque capture : la largeur
     se pose donc sur l'un ou sur l'autre, selon qu'il est déjà là */
  .proj-bande > .zoomable-box,
  .proj-bande > img{flex:0 0 auto;width:min(58%,240px);scroll-snap-align:start}
  .proj-bande .zoomable-box > img{width:100%}
  .proj-bande img{display:block;aspect-ratio:16/10;
    object-fit:cover;object-position:top center;
    border-radius:10px;border:1px solid rgba(0,0,0,.08);background:#fff;
    box-shadow:0 8px 22px color-mix(in srgb,var(--pc) 16%,rgba(0,0,0,.06))}
  .proj-bande img.fit{object-fit:contain}
  /* l'invitation à ouvrir le projet, puisque la capture, elle, agrandit */
  /* Une seule couleur pour toutes les lignes : en couleur de projet, la
     mention changeait de teinte à chaque ligne et se lisait comme une
     décoration de plus. En foncé, c'est un libellé, et il est le même
     partout. */
  .proj-cta{display:block;margin-top:15px;font-size:14.5px;font-weight:600;
    letter-spacing:.01em;color:var(--ink)}
}

/* ===== Projets annoncés mais pas encore écrits =====
   Ils gardent leur ligne et leur description, mais plus aucun signal
   de lien : ni curseur, ni décalage, ni changement de couleur. Le badge
   dit pourquoi on ne peut pas cliquer. (js/home.js les exclut aussi de
   l'aperçu qui suit le curseur.) */
.proj.soon{cursor:default}
.proj.soon:hover{padding-left:0}
.proj.soon:hover .proj-name{color:var(--ink)}
.proj.soon:hover .proj-meta{color:var(--ink-faint)}

/* Groupes de projets. Quand plusieurs études de cas parlent du même
   produit, l'entête le dit et un filet vertical les tient ensemble :
   on lit un produit, puis ses chapitres. */
.grp{position:relative;margin:0}
/* L'entête est en italique et nettement plus grande qu'avant : à 22 px en
   romain, elle paraissait plus petite que les titres de ses propres
   chapitres, ce qui inversait la hiérarchie. L'italique la distingue des
   titres de projets sans avoir à les dépasser en taille. La période suit
   le titre en petit libellé, sans point médian : à côté d'un titre en
   italique, le point se lisait comme une faute de frappe. */
/* L'entête se tient près de ce qu'elle annonce : peu d'air en dessous,
   beaucoup au-dessus. Sinon « Edenred France » flottait à mi-chemin entre
   deux groupes et n'appartenait à aucun. */
.grp-head{display:flex;align-items:baseline;justify-content:flex-start;gap:16px;flex-wrap:wrap;padding:22px 0 8px}
.grp-head + .proj{padding-top:20px}
.grp-title{font-family:var(--title-font),serif;font-style:italic;font-weight:400;font-size:clamp(22px,2.35vw,29px);letter-spacing:-.015em;line-height:1.1;/* Le titre de groupe était un mélange d'encre et d'accent. L'accent ayant
     été réveillé vers le rouge, le mélange virait au bordeaux. C'est une
     rubrique, pas une couleur de projet : elle prend l'encre des titres, à
     peine éclaircie, et laisse la couleur aux huit lignes. */
  color:#33333F;text-wrap:balance}
.grp-years{font-size:12px;letter-spacing:.14em;text-transform:uppercase;color:var(--ink-faint);font-weight:600;white-space:nowrap;transform:translateY(-.15em)}
/* d'un groupe au suivant, toujours le même écart : c'est l'entête qui le
   porte, pas un cas particulier par groupe */
/* Un peu plus d'air au-dessus d'« Edenred France » et d'« En dehors du
   travail » qu'entre deux projets : c'est là qu'on change de sujet, et le
   resserrement général de la liste avait rendu ces deux passages trop
   discrets. Vingt pixels sur toute la page, c'est ce que ça coûte. */
.grp + .grp .grp-head{padding-top:60px}
/* L'introduction du produit, sous le titre du groupe : ce qu'il est et
   depuis quand je le porte. Elle s'aligne sur les chapitres, le long du
   filet, parce qu'elle ouvre la même histoire qu'eux. */
.grp-lead{font-size:clamp(14.5px,1.25vw,15.5px);line-height:1.5;color:var(--ink-soft);
  max-width:60ch;margin:12px 0 8px 26px;text-wrap:pretty}
.grp-lead + .proj{padding-top:20px}
/* Les chapitres se décalent le long du filet ; l'entête, elle, s'aligne
   sur le bord gauche. Le dernier chapitre garde son filet de fin, aligné
   sur les autres : la ligne pleine largeur qui fermait la partie tombait
   26 px à gauche des titres et cassait l'alignement. */
.grp.family > .proj{margin-left:26px}
.grp.family::before{content:"";position:absolute;left:0;top:calc(var(--s-4) + 46px);bottom:0;width:2px;border-radius:2px;opacity:.5;
  background:linear-gradient(var(--c-affil),var(--c-merchant),var(--c-connect),var(--c-ds),var(--c-workshop))}
@media (max-width:820px){
  .grp.family > .proj{margin-left:16px}
  .grp-lead{margin-left:16px}
  .grp-head{gap:12px}
  .grp.family::before{top:calc(var(--s-4) + 42px)}
}

/* ===== L'arrivée des éléments =====
   Tout ce qui entre dans l'écran arrive en trois temps : le filet se
   trace de gauche à droite, le titre monte hors de son masque, puis la
   catégorie et la phrase suivent en se posant. La catégorie prend sa
   couleur en arrivant. Le même mouvement sert aux lignes de projets, aux
   entêtes de groupe, à la passerelle et aux lignes du contact ; --d est
   le retard posé par home.js quand plusieurs éléments arrivent ensemble.
   Tout est sous .js (le script tourne) et hors « réduire les
   animations » : dans les deux autres cas, rien n'est caché. */
@media (prefers-reduced-motion:no-preference){
  .js .proj,.js .hc-list li{position:relative;border-bottom-color:transparent}
  .js .proj::after,.js .hc-list li::after{content:"";position:absolute;left:0;right:0;bottom:-1px;height:1px;
    background:var(--line,rgba(0,0,0,.1));transform:scaleX(0);transform-origin:left;
    transition:transform .9s cubic-bezier(.2,.8,.2,1) var(--d,0s)}
  .js .proj.in::after,.js .hc-list li.in::after{transform:scaleX(1)}
  /* le titre monte hors de son masque ; le masque déborde un peu du bloc
     pour ne pas rogner les jambages de la Fraunces */
  .js .proj-name,.js .grp-title,.js .hc-lbl,.js .hc-hook{clip-path:inset(-.25em 0 -.35em 0)}
  /* vertical-align:top : un inline-block calé sur la ligne de base laisse
     sous lui la place des jambages, et chaque titre gagnait 12 px de haut */
  /* Le titre monte peu (deux tiers de sa hauteur) et il apparaît en fondu
     pendant qu'il monte : le mouvement démarre vite et le fondu démarre
     lentement, donc le texte est encore presque transparent au moment où
     il franchit le bord du masque. On voit un titre qui se pose, pas un
     titre qui sort d'une fente. */
  .js .proj-name>.t,.js .grp-title>.t,.js .hc-lbl>.t,.js .hc-hook>.t{display:inline-block;vertical-align:top;
    transform:translateY(66%);opacity:0;
    transition:transform .9s cubic-bezier(.2,.8,.2,1) calc(var(--d,0s) + .08s),opacity .8s cubic-bezier(.5,0,.6,1) calc(var(--d,0s) + .08s)}
  .js .in .proj-name>.t,.js .in .grp-title>.t,.js .in .hc-lbl>.t,.js .in .hc-hook>.t{transform:none;opacity:1}
  /* ce qui accompagne le titre se pose après lui */
  .js .proj-kind,.js .proj-meta,.js .grp-years,.js .grp-lead,.js .habout p,.js .hc-sub,.js .hc-note,.js .hc-link .ar{
    opacity:0;transform:translateY(8px);
    transition:opacity .7s ease-out calc(var(--d,0s) + .28s),transform .8s cubic-bezier(.2,.8,.2,1) calc(var(--d,0s) + .28s),color .8s ease}
  .js .proj.in .proj-kind,.js .proj.in .proj-meta,.js .grp-head.in .grp-years,.js .grp-lead.in,.js .habout p.in,
  .js .hc-txt.in .hc-sub,.js .hc-list li.in .hc-note,.js .hc-list li.in .ar{opacity:1;transform:none}
  /* la catégorie arrive grise et prend la couleur du projet */
  .js .proj-kind{color:var(--ink-faint)}
  .js .proj.in .proj-kind{color:var(--pci,var(--ink-faint))}
  /* le filet du groupe descend avec ses chapitres */
  .js .grp.family::before{transform:scaleY(var(--fil,0));transform-origin:top;transition:transform 1s cubic-bezier(.2,.8,.2,1)}
}

/* aperçu qui suit le curseur */
/* L'aperçu est posé exactement sous le curseur. Invisible mais toujours
   présent, il restait composité à cet endroit et empêchait le curseur de
   se mettre à jour : on le sort donc vraiment du rendu au repos. */
/* L'aperçu entre par la droite : il vient de l'extérieur de la page, du
   côté où il n'y a rien d'écrit, et jamais de la colonne des titres. */
/* La position vient de --hx / --hy, posés par le script au changement de
   ligne, et c'est le navigateur qui interpole d'une ligne à l'autre. Une
   boucle en JavaScript écrivait `left` et `top` soixante fois par seconde,
   ce qui relançait la mise en page à chaque image : de là le mouvement
   haché, et une arrivée jamais tout à fait au même endroit. Une transition
   CSS sur `transform` se joue sur le compositeur, et tombe pile. */
#hoverwrap{position:fixed;top:0;left:0;width:min(38vw,440px);aspect-ratio:4/3;pointer-events:none;z-index:5;
  opacity:0;visibility:hidden;
  transform:translate3d(var(--hx,0px),var(--hy,0px),0) translate(-50%,-50%) translateX(54px) scale(.94);
  /* La vignette suit le curseur, et sa cible se remet à jour à chaque
     image : la transition n'est donc plus un trajet d'une ligne à
     l'autre, c'est un amortisseur. Sa durée fait la souplesse du suivi.
     Trop courte, la vignette colle au curseur et tremble ; trop longue,
     elle traîne derrière. Autour de 200ms, elle glisse. */
  /* Le tempo vient du script, par --tdur : 200 ms pour suivre le curseur,
     780 ms pour changer de taille. La largeur s'anime avec, sinon le
     passage du repos au survol se lit comme un saut. */
  transition:opacity .5s ease,visibility .5s,
    transform var(--tdur,.2s) cubic-bezier(.22,1,.3,1),
    width var(--tdur,.2s) cubic-bezier(.22,1,.3,1);
  border-radius:16px;overflow:hidden;box-shadow:0 40px 80px rgba(0,0,0,.28)}
#hoverwrap.show{opacity:1;visibility:visible;
  transform:translate3d(var(--hx,0px),var(--hy,0px),0) translate(-50%,-50%) scale(1)}
/* le temps de se poser à l'arrivée, et pendant un scroll : pas d'interpolation */
#hoverwrap.sansanim{transition:opacity .5s ease,visibility .5s}

/* Le retrait, quand on quitte la liste. Les 200 ms du suivi sont faites pour
   amortir le curseur, pas pour sortir : la vignette finissait de reculer et
   de rétrécir en 200 ms puis restait là à s'effacer pendant 300 de plus. On
   lisait deux gestes, un coup sec puis une disparition. Ici les deux durées
   sont les mêmes, donc c'est un seul mouvement. */
/* `:not(.sansanim)` sur les trois règles qui suivent, et ce n'est pas un
   détail : `sansanim` sert à poser la vignette d'un coup, sans interpoler,
   quand elle arrive pour la première fois. Sans elle, le déplacement part de
   --hx et --hy encore vides, c'est-à-dire du coin haut-gauche de l'écran, et
   la vignette traverse la page en diagonale avant de se poser. Ces règles
   étant plus spécifiques que `#hoverwrap.sansanim`, elles la faisaient
   perdre : le visuel arrivait par la gauche au lieu de glisser depuis la
   droite sur 54 px. */
#hoverwrap:not(.show):not(.sansanim){transition:opacity .42s ease,visibility .42s,
  transform .42s cubic-bezier(.3,.7,.25,1),width .42s cubic-bezier(.3,.7,.25,1)}


/* `z-index:0` : la scène doit créer son propre contexte d'empilement,
   sinon les z-index de ses deux aplats sortent et se mesurent à ceux des
   visuels. L'aplat entrant (z-index 2) passait alors au-dessus du visuel
   sortant (z-index 1) : on voyait la couleur du nouveau projet s'afficher
   en grand avant que son visuel n'arrive par-dessus. */
#hoverscene{position:relative;z-index:0;width:100%;height:100%;display:flex;align-items:center;justify-content:center}
/* les deux calques d'aplat, croisés au changement de projet, au même
   rythme et sur la même courbe que le déplacement de la vignette */
.hv-fond{position:absolute;inset:0;opacity:0;
  transition:opacity .58s cubic-bezier(.3,.72,.18,1)}
.hv-fond.on{opacity:1;z-index:2}
/* même principe que pour les visuels : l'aplat qu'on quitte reste opaque
   dessous le temps que le nouveau se pose */
.hv-fond.sous{opacity:1;z-index:1;transition:none}
#hoverscene .m{position:relative;color:rgba(255,255,255,.95);font-weight:500;font-size:16px;transform:rotate(-2deg)}

/* (footer : style partagé dans base.css) */

/* ===== Responsive ===== */
@media (max-width:820px){
  /* svh, et non vh : sur un téléphone, 100vh compte la barre d'adresse et
     déborde de ce qu'on voit. Le hero tient donc exactement l'écran. */
  .hero{height:100svh;min-height:520px}
  .index{min-height:auto;padding-top:56px}

  /* Liste des projets : rien ne se déplie, la description est toujours
     visible et un tap ouvre directement le projet.
     C'est l'air entre les lignes qui allège, pas le fait d'en montrer moins :
     des blocs serrés séparés par un filet net se lisent comme un tableau, et
     un tableau paraît toujours plus long qu'il n'est. On respire donc entre
     les projets, et les filets s'effacent presque. */
  .proj{padding:18px 0;transition:none;--line:rgba(0,0,0,.055)}
  .proj:hover{padding-left:0}
  .proj-meta{margin-top:7px}


}

/* Les halos du hero : les tailles sont en vw, donc plus l'écran est étroit
   plus les taches rétrécissent, pendant que le flou reste fixe et mange la
   couleur. On regonfle donc en descendant. Mais le regonflage du mobile,
   appliqué tel quel autour de 700 px, écrasait la page : les taches y sont
   encore grandes et le fond devenait beaucoup trop soutenu. D'où un palier
   intermédiaire, entre le rendu desktop et le rendu mobile. */
@media (max-width:820px) and (min-width:561px){
  .hb-cool{width:80vw;height:62vw;left:-6vw;bottom:-18vw;opacity:.15;filter:blur(80px)}
  .hb-warm1{width:94vw;height:94vw;top:-22vw;left:-16vw;opacity:.5;filter:blur(90px)}
  .hb-warm2{width:54vw;height:54vw;top:-1vw;right:-6vw;opacity:.48;filter:blur(68px)}
  .hb-warm3{width:72vw;height:72vw;bottom:-22vw;right:-8vw;opacity:.4;filter:blur(86px)}
  .hb-warm4{width:38vw;height:38vw;bottom:11vw;left:2%;opacity:.4;filter:blur(58px)}
  .hb-warm5{width:62vw;height:62vw;top:26%;left:20%;opacity:.3;filter:blur(96px)}
}
@media (max-width:560px){
  .hb-cool{width:120vw;height:90vw;left:-12vw;bottom:-28vw;opacity:.15;filter:blur(60px)}
  .hb-warm1{width:135vw;height:135vw;top:-34vw;left:-28vw;opacity:.55;filter:blur(70px)}
  .hb-warm2{width:80vw;height:80vw;top:-4vw;right:-18vw;opacity:.55;filter:blur(55px)}
  .hb-warm3{width:105vw;height:105vw;bottom:-32vw;right:-22vw;opacity:.45;filter:blur(65px)}
  .hb-warm4{width:58vw;height:58vw;bottom:14vw;left:-6vw;opacity:.45;filter:blur(45px)}
  .hb-warm5{width:95vw;height:95vw;top:28%;left:12%;opacity:.35;filter:blur(70px)}
}
@media (prefers-reduced-motion:reduce){
  .fade-line,.hero .sub,.hero .hero-facts,.scroll{animation:none;opacity:1;transform:none}
  .cursor{animation:none}
  /* base.css arrête déjà les halos, mais .hb-warm1 à 5 et .hb-cool sont
     redéclarés ici avec leur animation, à la même spécificité et plus loin
     dans la cascade : c'est cette feuille qui gagnait. Sur l'accueil et sur
     la 404, six halos continuaient donc de tourner pour quelqu'un qui a
     demandé qu'on arrête de bouger. */
  .hblob,.hb-cool,.hb-warm1,.hb-warm2,.hb-warm3,.hb-warm4,.hb-warm5{animation:none}
}

/* ============================================================
   Bloc contact en fin d'accueil (HOME-10)
   Même traitement que la page À propos : la typographie est large,
   le contact ne se cherche plus dans le pied de page.
   ============================================================ */
/* La passerelle vers « Qui je suis » : une phrase et un lien, posés juste
   avant le contact. Volontairement plus sobre que l'accroche du contact.
   D'une partie à l'autre de la fin de page, c'est toujours le même écart,
   le grand (--s-6) : la liste, la passerelle et le contact se suivent
   au même pas, comme la liste suivait le hero. */
/* La fin de page tient un écran : la passerelle et le contact sont
   centrés dans la hauteur de la fenêtre, ce qui les détache nettement
   de la liste et donne au contact la place d'une vraie page. */
/* Un écran, pied de page compris, entre la dernière ligne de projet et le
   bas : la hauteur de la fenêtre moins celle du pied (145 px sur
   ordinateur, plus haut sur téléphone où il s'empile). */
.hfin{min-height:calc(100svh - 145px);display:flex;flex-direction:column;justify-content:center;padding:110px 0 0}
@media (max-width:640px){.hfin{min-height:calc(100svh - 200px)}}
/* dans une colonne flex, « margin:0 auto » rétrécit les sections à leur
   contenu : elles doivent garder toute la largeur pour que leur gabarit
   de 1180 px s'aligne sur celui de la liste */
.hfin > *{width:100%}
.habout{max-width:var(--colonne);margin:0 auto;padding:0 clamp(20px,5vw,64px)}
.habout p{margin:0;max-width:60ch;font-size:clamp(16px,1.7vw,20px);line-height:1.55;color:var(--ink-soft);text-wrap:pretty}
.ha-link{display:inline-flex;align-items:center;gap:8px;white-space:nowrap;
  color:var(--ink);text-decoration:none;font-weight:500;border-bottom:2px solid var(--c-accent);padding-bottom:2px;
  transition:color .25s,gap .25s}
.ha-link .ar{color:var(--c-accent);transition:transform .25s}
.ha-link:hover{gap:12px}
.ha-link:hover .ar{transform:translateX(3px)}

/* Le contact : l'accroche et une phrase à gauche, trois lignes à droite.
   Trois liens soulignés sur une même ligne se lisaient comme une note de
   bas de page ; en lignes séparées par un filet, avec le même décalage au
   survol que les projets, ils font partie de la page. */
.hcontact{max-width:var(--colonne);margin:0 auto;padding:var(--s-6) clamp(20px,5vw,64px) 0}
.hc-grid{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1.1fr);gap:clamp(28px,5vw,88px);align-items:start;
  border-top:1px solid rgba(0,0,0,.14);padding-top:var(--s-4)}
.hc-hook{font-family:var(--title-font),serif;font-weight:400;font-size:clamp(26px,4vw,44px);line-height:1.05;letter-spacing:-.02em;color:var(--ink);margin:0 0 14px}
.hc-hook em{font-style:italic;color:var(--cg-accent)}
.hc-sub{font-size:clamp(15px,1.4vw,17px);line-height:1.6;color:var(--ink-soft);max-width:38ch;margin:0;text-wrap:pretty}
.hc-list{list-style:none;margin:0;padding:0}
.hc-list li{border-bottom:1px solid rgba(0,0,0,.1)}
.hc-link{display:flex;align-items:baseline;gap:16px;padding:16px 0;text-decoration:none;color:var(--ink);
  transition:padding-left .45s cubic-bezier(.2,.8,.2,1)}
.hc-lbl{font-family:var(--title-font),serif;font-weight:500;font-size:clamp(21px,2.1vw,27px);letter-spacing:-.015em;line-height:1.1}
.hc-note{margin-left:auto;font-size:14px;line-height:1.4;color:var(--ink-soft);text-align:right}
.hc-link .ar{flex:0 0 auto;color:var(--c-accent);transition:transform .25s}
.hc-link:hover{padding-left:14px}
.hc-link:hover .ar{transform:translate(3px,-3px)}
@media (max-width:820px){
  .hc-grid{grid-template-columns:1fr;gap:22px}
  .hc-note{display:none}
}/* ============================================================
   Aperçu au survol · plusieurs visuels par projet (HOME-02)
   Les vignettes défilent toutes les trois secondes, et la barre du bas
   dit où l'on en est et combien il y en a. Les projets sans visuel
   gardent l'aplat de couleur du projet.
   ============================================================ */
/* la vignette suit la taille de l'écran, sans jamais descendre sous une
   taille où l'on ne verrait plus rien */
#hoverwrap{aspect-ratio:16/10;width:clamp(470px,44vw,700px)}
/* le visuel occupe toute la vignette : il est calé sur la largeur et
   c'est le bas qui se rogne, plutôt que de laisser des bandes de couleur */
/* et les visuels passent devant la scène, quoi qu'il arrive */
.hv-shots{position:absolute;inset:0;z-index:1}
.hv-shots img{
  position:absolute;inset:0;width:100%;height:100%;display:block;
  object-fit:cover;object-position:top center;
  opacity:0;transition:opacity .55s cubic-bezier(.35,.6,.25,1)}
.hv-shots img.on{opacity:1;z-index:2}
/* Le visuel qui arrive se pose PAR-DESSUS celui qui part, lequel reste
   opaque jusqu'au bout puis s'efface d'un coup, caché derrière. Deux
   calques qui se croisent en fondu laissent en effet passer le fond au
   milieu du trajet : à mi-course, la couverture tombe à 75% et la page
   claire transparaît, ce qui se voit comme un petit éclair. En posant
   l'un sur l'autre, la couverture ne descend jamais sous 100%. */
.hv-shots img.sous{opacity:1;z-index:1;transition:none}
/* à la première apparition, le visuel se pose d'un coup : c'est la
   vignette entière qui arrive en fondu */
.hv-shots.sansanim img{transition:none}
/* sauf celui qu'on ne veut pas voir rogné sur les côtés : il se pose en
   entier, et c'est le fond du projet qui comble la bande du bas */
.hv-shots img.fit{object-fit:contain}
/* l'aplat reste sous les visuels : il sert de fond pendant le chargement
   et de vignette complète pour les projets sans capture */
#hoverscene .m{transition:opacity .35s}
#hoverwrap.has-shots #hoverscene .m{opacity:0}

/* un voile discret sous la barre : blanche sur une capture claire, elle
   disparaissait complètement */
#hoverwrap.has-shots::after{content:"";position:absolute;left:0;right:0;bottom:0;height:76px;
  background:linear-gradient(transparent,rgba(18,22,38,.58));pointer-events:none;z-index:1}
/* Le compteur : sans lui on ne devine pas qu'il y a d'autres visuels
   derrière celui qu'on regarde, et on passe à côté du carrousel. */
.hv-count{position:absolute;top:12px;right:12px;z-index:2;
  padding:5px 11px;border-radius:999px;font-size:12.5px;font-weight:600;letter-spacing:.04em;
  color:#fff;background:rgba(18,22,38,.52);backdrop-filter:blur(6px);-webkit-backdrop-filter:blur(6px);
  opacity:0;transition:opacity .35s ease}
#hoverwrap.has-shots .hv-count{opacity:1}
/* le compteur et le rappel des touches changent de projet en même temps
   que le visuel : la barre, elle, se redessine et n'a rien à fondre */
.hv-count,.hv-keys{transition:opacity .45s ease}
/* Le mode d'emploi de la vignette, en bas à gauche, au-dessus de la
   barre. Il était en 10,5px sous le compteur : personne ne le lisait,
   et le carrousel passait pour une animation qu'on subit. */
.hv-keys{position:absolute;left:12px;bottom:28px;z-index:2;
  display:flex;align-items:center;gap:7px;
  padding:6px 12px 6px 8px;border-radius:999px;font-size:13px;font-weight:600;letter-spacing:.02em;
  color:#fff;background:rgba(18,22,38,.62);
  backdrop-filter:blur(6px);-webkit-backdrop-filter:blur(6px);
  opacity:0;transition:opacity .35s ease}
/* La pastille est le seul endroit de l'aperçu qui reçoit la souris : tout
   le reste laisse passer, pour qu'un clic sur la ligne ouvre le projet. */
.hv-keys{pointer-events:auto}
.hv-keys .hv-k{display:grid;place-items:center;width:21px;height:21px;padding:0;
  border:0;border-radius:5px;background:rgba(255,255,255,.9);color:#121626;
  line-height:0;cursor:pointer;
  transition:background .18s ease,transform .18s ease}
.hv-keys .hv-k svg{display:block;width:12px;height:12px}
/* la flèche de droite, c'est la même en miroir : un seul tracé à régler */
.hv-keys .hv-k-d svg{transform:scaleX(-1)}
.hv-keys .hv-k:hover{background:#fff;transform:translateY(-1px)}
.hv-keys .hv-k:active{transform:none;background:rgba(255,255,255,.75)}
.hv-keys .hv-k:focus-visible{outline:2px solid #fff;outline-offset:2px}
#hoverwrap.has-shots .hv-keys{opacity:1}
/* ---- la vignette au repos ----
   Elle est là en permanence, plus petite, et montre le projet dont la ligne
   passe à sa hauteur. Ses commandes n'ont alors personne à servir : le
   défilé ne tourne pas tant qu'on ne survole pas, donc ni flèches, ni
   compteur, ni barre. Tout revient au survol. */
#hoverwrap.mini .hv-keys,
#hoverwrap.mini .hv-count,
#hoverwrap.mini .hv-bar{opacity:0}
#hoverwrap.mini.has-shots::after{opacity:.5}
/* on garde le rappel des flèches une fois qu'on s'en est servi : c'est
   maintenant lui qui affiche l'état de pause */
#hoverwrap.has-shots .hv-keys.used{opacity:.55}
/* sauf quand on vient la chercher : la vignette s'immobilise et la
   pastille se rallume, le temps de se servir des flèches */
#hoverwrap.has-shots.fixe .hv-keys,
#hoverwrap.has-shots .hv-keys:hover{opacity:1}
#hoverwrap.paused .hv-keys{opacity:1;background:rgba(18,22,38,.78)}
/* maintenue, la vignette se fige : le défilé s'arrête là où il en est */
#hoverwrap.paused .hv-bar i.run::after{animation-play-state:paused}
.hv-bar{position:absolute;left:12px;right:12px;bottom:12px;display:flex;gap:6px;z-index:2}
.hv-bar i{flex:1;height:4px;border-radius:3px;background:rgba(255,255,255,.42);overflow:hidden;position:relative}
.hv-bar i::after{content:"";position:absolute;inset:0;background:rgba(255,255,255,.95);transform-origin:left;transform:scaleX(0)}
.hv-bar i.done::after{transform:scaleX(1)}
.hv-bar i.run::after{animation:hv-fill 3s linear forwards}
@keyframes hv-fill{from{transform:scaleX(0)}to{transform:scaleX(1)}}
@media (prefers-reduced-motion:reduce){
  .hv-shots img,.hv-fond,.hv-shots img.sous,.hv-fond.sous{transition:none}
  .hv-bar i.run::after{animation:none;transform:scaleX(1)}
  /* La vignette est là en permanence : elle change de taille au survol et
     se déplace au défilement. Pour qui a demandé qu'on arrête de bouger,
     elle se pose et se repose sans trajet. */
  #hoverwrap{transition:opacity .3s ease,visibility .3s}
}

