/* ══ LE SOCLE COMMUN : LE FONDU À L'ARRIVÉE ET LE LIEN D'ÉVITEMENT ═══════════
   Marc, 10 octobre 2026 : « don't forget to make every element fade in once I
   load into a page. »

   ⚠⚠ LA RÈGLE QUI GOUVERNE TOUT CE FICHIER : LE CONTENU EST VISIBLE AU REPOS.
     LE FONDU EST UN DÉPART, PAS UNE PERMISSION.
     Il n'y a donc AUCUNE déclaration `opacity:0` statique ici. L'état invisible
     n'existe que dans le `from{}` d'une `@keyframes`, qui ne s'applique que si
     l'animation tourne. Aucune ligne de JavaScript, aucune classe à ajouter,
     aucun observateur, aucun seuil, aucun événement attendu.

     POURQUOI ÇA, ET PAS UN `.rv` DE PLUS. Chaque façon de rater un fondu est
     une façon pour quelque chose de NE PAS ARRIVER : un script, une classe,
     une image, un seuil, une feuille. Avec un `opacity:0` statique, chacune de
     ces absences devient une disparition définitive — il faut un geste pour la
     défaire. Avec une animation, chacune devient une simple absence de fondu.
     Le pire défaut possible est « le contenu est apparu sans élégance »,
     jamais « le client ne l'a pas vu ».
     Et ce n'est pas théorique : ce matin, une rangée de liens à la bonne place
     et à la bonne taille était peinte sous un décor, quatre sondes au vert, et
     c'est Marc qui l'a vue manquer à l'œil.

   ⚠ « UNE @keyframes QUI PART DE 0 FINIT À 1 TOUTE SEULE » EST FAUX ICI, et il
     fallait le vérifier avant de s'y fier : `commun.css`, `accueil.css`,
     `connexion.html` et `tendances.html` portent tous les quatre
     `*{animation:none!important}` sous `prefers-reduced-motion`. Le réglage
     « Réduire les animations » d'un iPhone suffit à empêcher l'animation de
     tourner. Si l'état au repos était `opacity:0`, ces gens auraient une page
     blanche. Ce qui protège n'est donc pas la keyframe, c'est l'état au repos.

   ⚠ TROIS LIMITES, et elles sont la raison de chaque ligne ci-dessous :
     1. `animation-fill-mode:both` rend l'élément invisible PENDANT son délai.
        Le décalage est donc plafonné à 210 ms au total et posé à la main sur
        trois rangs, jamais calculé sur la place dans le DOM — `tendances.html`
        a 323 balises, un décalage par rang ferait dix-neuf secondes de page
        blanche.
     2. Un élément en `display:none` au chargement ne joue JAMAIS son animation
        (les dix `<details>` de l'aide, les panneaux du compagnon). Avec un
        état au repos visible, ils s'ouvrent pleins ; avec un `opacity:0`, ils
        s'ouvriraient vides. C'est ce cas qui tranche entre les deux façons de
        faire, et il est sur la page d'aide.
     3. UNE OPACITÉ INFÉRIEURE À 1 CRÉE UN CONTEXTE D'EMPILEMENT. Un élément en
        train de disparaître ou d'apparaître est peint comme s'il portait
        `z-index:0` : il peut monter au-dessus du décor pendant le fondu, puis
        redescendre dessous à la fin — le défaut de ce matin, remis en scène
        par le fondu lui-même. On anime donc les ENFANTS, et le conteneur garde
        `position:relative; z-index:1` en permanence, de sorte que le niveau
        d'empilement soit identique avant, pendant et après.

   ⚠ ON N'ANIME QUE `opacity`. Un `transform` sur un ancêtre déplace tous les
     `position:fixed` qu'il contient — la barre, la bande de lancement, la
     bulle du compagnon, les messages — et casse les ancres. Le fondu n'a pas
     besoin d'un déplacement pour être beau.
   ========================================================================== */

@keyframes tx-arrivee { from { opacity: 0 } to { opacity: 1 } }

/* le conteneur ne bouge jamais : c'est lui qui tient le niveau d'empilement */
main, .app { position: relative; z-index: 1 }

/* ⚠⚠ `:not(.entre)` N'EST PAS UN DÉTAIL — MESURÉ, PUIS CORRIGÉ. Une animation
   @keyframes ÉCRASE un `opacity:0` normal (mesuré : 0,77 au lieu de 0). Or
   `tendances.html` a son PROPRE système d'entrée : `.js .entre{opacity:0}`,
   rallumé par `#app.pret`. Sans cette exclusion, mon fondu allumait ses dix
   blocs trop tôt, puis la page les reprenait — une page qui s'allume deux
   fois. Les neuf autres pages étaient propres ; celle-là, non.
   ⚠ C'est la raison pour laquelle on vise `main > *` et jamais `main *` : sur
     un sélecteur large, le même mécanisme ferait clignoter TOUT ce qui est
     volontairement caché au repos — les messages, les blocs à révéler au
     défilement, les mots du titre. Une sonde de géométrie ne le verrait pas. */
@media (prefers-reduced-motion: no-preference) {
  main > *, .app > * { animation: tx-arrivee .55s cubic-bezier(.22, 1, .36, 1) both }
  main > *:nth-child(2),     .app > *:nth-child(2)     { animation-delay: .07s }
  main > *:nth-child(3),     .app > *:nth-child(3)     { animation-delay: .14s }
  main > *:nth-child(n + 4), .app > *:nth-child(n + 4) { animation-delay: .21s }

  /* ⚠ LES DEUX EXCLUSIONS, ÉCRITES UNE SEULE FOIS plutôt que répétées en
     `:not()` sur chaque ligne au-dessus. Quatre `:not()` identiques, c'est
     quatre endroits où en oublier un.
       · `.entre`   — tendances.html a SON propre système d'entrée
         (`.js .entre{opacity:0}` rallumé par `#app.pret`). Mesuré : sans cette
         ligne, mon fondu allumait ses dix blocs trop tôt et la page s'allumait
         deux fois.
       · `[hidden]` — le panneau de détail d'une tendance. Il est en
         `display:none` au repos, donc il ne joue pas son animation ; mais au
         moment où on l'ouvre, `both` le tiendrait invisible pendant son délai.
         Un panneau qu'on vient d'ouvrir ne doit pas attendre. */
  main > .entre, .app > .entre,
  main > [hidden], .app > [hidden] { animation: none }
}

/* ⚠ ÉCRIT, PAS LAISSÉ AU HASARD. Les quatre feuilles du site coupent déjà
   toutes les animations sous ce réglage, donc cette règle serait vraie par
   omission. On l'écrit quand même : une règle vraie par omission se fait
   casser par la première personne qui retire l'autre. */
@media (prefers-reduced-motion: reduce) {
  main > *, .app > * { animation: none; opacity: 1 }
}


/* ══ LE LIEN D'ÉVITEMENT ═════════════════════════════════════════════════════
   Mesuré le 10 octobre 2026 : AUCUNE des 21 pages n'en avait, et sur onze
   d'entre elles l'ordre au clavier est identique — bandeau de lancement, sa
   croix, le logo, six liens de navigation, le menu du compte, PUIS le contenu.
   Onze arrêts de tabulation avant la première chose qu'on est venu lire, et il
   faut les refaire à chaque page.

   ⚠ IL EST DANS CE FICHIER PARCE QUE CE FICHIER EST DÉJÀ LU PAR LES QUINZE
     PAGES. Le mettre dans commun.css obligerait à le recopier dans accueil.css
     et dans tendances.html, qui portent leur style en propre — et le projet a
     déjà trois règles écrites en triple pour cette raison. Le fichier change
     donc de nom dans son titre : il porte le socle, pas seulement le fondu.

   ⚠ IL NE SE CACHE PAS AVEC `display:none` NI `visibility:hidden` : ces deux-là
     le retirent aussi du parcours au clavier, ce qui en fait un lien
     d'évitement qu'on ne peut pas atteindre. On le sort de l'écran, et il
     revient dès qu'il reçoit le focus. */
.saut-contenu{position:absolute;left:var(--g,16px);top:-60px;z-index:60;
  background:var(--carte,#0d1014);color:var(--texte,#e8eaed);
  border:1px solid var(--vert,#5eead4);border-radius:10px;
  padding:10px 16px;font-size:14px;font-weight:600;
  transition:top .18s ease}
.saut-contenu:focus{top:calc(var(--bande,0px) + var(--nav,64px) + 8px);outline:none;
  box-shadow:0 0 0 3px var(--vertb,rgba(94,234,212,.24))}
/* ⚠ la cible reçoit le focus par programme : sans `tabindex="-1"` le navigateur
   déplace la vue mais pas le curseur du clavier, et la tabulation suivante
   repartirait du haut. */
#contenu:focus{outline:none}
