/* =========================================================================
   CPPA — animations
   Chargee en dernier, sur le site public, l'espace connecte et les pages de
   connexion. Trois regles tiennent l'ensemble :
   - rien n'est masque sans JavaScript (tout est prefixe par html.js) ;
   - une animation accompagne une arrivee ou repond a un geste, jamais plus ;
   - tout s'arrete pour qui a demande moins de mouvement.
   ========================================================================= */

/* --- Apparition au defilement -------------------------------------------
   animations.js pose la classe .revele, puis .visible quand l'element entre
   dans la fenetre, puis retire les deux : l'element retrouve alors ses
   propres transitions. La classe .vu, elle, reste. */

html.js .revele {
  opacity: 0; transform: translateY(32px); will-change: opacity, transform;
  transition: opacity .7s ease, transform .9s cubic-bezier(.2, .7, .2, 1), filter .8s ease, background-size 1.1s cubic-bezier(.2, .7, .2, 1) !important;
  transition-delay: var(--delai, 0s) !important;
}
html.js .revele[data-depart='gauche'] { transform: translateX(-44px); }
html.js .revele[data-depart='droite'] { transform: translateX(44px); }
html.js .revele[data-depart='zoom'] { transform: scale(.9); }
html.js .revele[data-depart='flou'] { transform: translateY(14px); filter: blur(12px); }
html.js .revele.visible { opacity: 1; transform: none; filter: none; }

/* Le filet du surtitre se trace quand son bloc arrive. */
html.js .revele:not(.visible) .surtitre::before { width: 0; }
.surtitre::before { transition: width .7s cubic-bezier(.2, .7, .2, 1) .25s; }

/* --- Titres : les mots montent un a un ---------------------------------- */

html.js .mots .mot { display: inline-block; overflow: hidden; vertical-align: bottom; padding: .1em 0 .24em; margin: -.1em 0 -.24em; }
html.js .mots .mot > span { display: inline-block; transform: translateY(112%); animation: leve .95s cubic-bezier(.2, .75, .2, 1) forwards; animation-delay: calc(var(--i) * 75ms + 120ms); }
@keyframes leve { to { transform: none; } }

/* --- Barre de progression de lecture ------------------------------------ */

.progression-lecture { position: fixed; inset: 0 0 auto 0; height: 3px; z-index: 120; pointer-events: none; transform-origin: left; transform: scaleX(var(--p, 0)); background: linear-gradient(90deg, var(--logo), var(--accent), var(--ciel)); }

/* --- Boutons : onde au clic --------------------------------------------- */

.onde { position: absolute; width: 14px; height: 14px; margin: -7px; border-radius: 50%; background: currentColor; opacity: .32; pointer-events: none; animation: onde .65s ease-out forwards; }
@keyframes onde { from { transform: scale(0); } to { transform: scale(24); opacity: 0; } }

/* --- Cartes : une lueur suit le pointeur -------------------------------- */

.projecteur { position: relative; overflow: hidden; }
.projecteur::before {
  content: ''; position: absolute; inset: 0; z-index: 0; pointer-events: none; opacity: 0; transition: opacity .35s ease;
  background: radial-gradient(260px circle at var(--mx, 50%) var(--my, 50%), rgba(38, 122, 170, .14), transparent 62%);
}
.projecteur:hover::before { opacity: 1; }
.projecteur > * { position: relative; z-index: 1; }
.section-encre .projecteur::before { background: radial-gradient(280px circle at var(--mx, 50%) var(--my, 50%), rgba(127, 188, 224, .24), transparent 62%); }

/* --- Formulaires -------------------------------------------------------- */

.champ > label, .champ > .libelle { transition: color var(--transition), transform var(--transition); transform-origin: left; }
.champ:focus-within > label { color: var(--accent-fonce); transform: translateX(2px); }
.saisie { transition: border-color var(--transition), box-shadow var(--transition), transform var(--transition); }
.saisie:focus { transform: translateY(-1px); }
.champ-erreur { animation: secousse .4s ease; }
@keyframes secousse { 20% { transform: translateX(-5px); } 45% { transform: translateX(4px); } 70% { transform: translateX(-2px); } }

/* =========================================================================
   Site public
   ========================================================================= */

/* --- En-tete : il se resserre au defilement ----------------------------- */

.site-entete .contenu { transition: height .3s cubic-bezier(.2, .7, .2, 1); }
.site-entete.defile .contenu { height: 60px; }
.site-entete .logo img { transition: height .3s cubic-bezier(.2, .7, .2, 1), transform .4s cubic-bezier(.3, 1.4, .5, 1); }
.site-entete.defile .logo img { height: 38px; }
.site-nav a { transition: color var(--transition), transform var(--transition); }
.site-nav a:hover { transform: translateY(-1px); }
.bandeau-haut .contenu > * { animation: entree .6s cubic-bezier(.2, .7, .2, 1) both; }
.bandeau-haut .contenu > *:last-child { animation-delay: .12s; }
.site-entete .contenu > * { animation: descente .6s cubic-bezier(.2, .7, .2, 1) both; }
.site-entete .contenu > *:nth-child(2) { animation-delay: .08s; }
.site-entete .contenu > *:nth-child(3) { animation-delay: .16s; }
@keyframes descente { from { opacity: 0; transform: translateY(-12px); } }

/* --- Heros -------------------------------------------------------------- */

.heros-orbe { position: absolute; z-index: 0; width: 520px; height: 520px; right: -140px; top: -180px; border-radius: 50%; pointer-events: none; background: radial-gradient(circle, rgba(127, 188, 224, .5), transparent 66%); animation: orbite 16s ease-in-out infinite alternate; }
.heros-orbe.deux { width: 380px; height: 380px; left: -120px; right: auto; top: auto; bottom: -160px; background: radial-gradient(circle, rgba(38, 122, 170, .22), transparent 66%); animation-duration: 21s; animation-direction: alternate-reverse; }
@keyframes orbite { from { transform: translate(0, 0) scale(1); } to { transform: translate(-60px, 50px) scale(1.18); } }

/* La photo suit le pointeur, la carte du parcours flotte au-dessus. */
.heros-visuel { padding: 0 0 104px 48px; perspective: 1100px; }
.heros-photo { transform: rotateX(var(--rx, 0deg)) rotateY(var(--ry, 0deg)); transition: transform .5s cubic-bezier(.2, .7, .2, 1), scale .8s cubic-bezier(.2, .7, .2, 1); }
.heros-visuel:hover .heros-photo { transform: rotateX(var(--rx, 0deg)) rotateY(var(--ry, 0deg)); scale: 1.02; }
.heros-visuel .copie { translate: var(--dx, 0px) var(--dy, 0px); transition: translate .5s cubic-bezier(.2, .7, .2, 1); width: min(84%, 390px); }
.heros-visuel::before { translate: calc(var(--dx, 0px) * -1.4) calc(var(--dy, 0px) * -1.4); transition: translate .6s cubic-bezier(.2, .7, .2, 1); animation: respire 6s ease-in-out infinite; }
@keyframes respire { 50% { opacity: .55; scale: 1.06; } }

.copie-ligne { animation: entree .6s cubic-bezier(.2, .7, .2, 1) both; }
.copie-ligne:nth-of-type(2) { animation-delay: .9s; }
.copie-ligne:nth-of-type(3) { animation-delay: 1.1s; }
.copie-ligne.copie-resultat { animation-delay: 1.55s; }
.copie-trait { transform-origin: left; animation: remplissage .7s cubic-bezier(.2, .7, .2, 1) 1.3s both; }
.copie-resultat strong { animation: eclat 1.4s ease 2.1s both; }
@keyframes eclat { 0% { scale: 1; } 30% { scale: 1.5; } 100% { scale: 1; } }

/* Invitation a faire defiler. */
.defiler { position: absolute; left: 50%; bottom: 22px; z-index: 2; width: 26px; height: 42px; margin-left: -13px; border: 2px solid var(--accent); border-radius: 14px; opacity: .8; animation: entree .8s ease 1.8s both; }
.defiler span { position: absolute; left: 50%; top: 8px; width: 4px; height: 8px; margin-left: -2px; border-radius: 2px; background: var(--accent); animation: molette 1.8s ease-in-out infinite; }
@keyframes molette { 0% { opacity: 0; transform: translateY(0); } 30% { opacity: 1; } 100% { opacity: 0; transform: translateY(14px); } }
@media (max-width: 960px) { .defiler, .heros-orbe { display: none; } .heros-visuel { padding: 0 0 96px; } }

/* --- Bande photo : zoom lent -------------------------------------------- */

.bande-photo { overflow: hidden; }
.bande-photo::after { content: ''; position: absolute; inset: 0; z-index: 0; background: inherit; animation: zoom-lent 24s ease-in-out infinite alternate; }
.bande-photo::before { z-index: 1; }
.bande-photo .contenu { z-index: 2; }
@keyframes zoom-lent { from { transform: scale(1); } to { transform: scale(1.14) translate(-1.5%, -1%); } }

/* --- Bandeau defilant --------------------------------------------------- */

.defilant { overflow: hidden; background: var(--surface); border-block: 1px solid var(--bord); mask-image: linear-gradient(90deg, transparent, #000 8%, #000 92%, transparent); }
.defilant-piste { display: flex; align-items: center; gap: 44px; width: max-content; padding: 18px 0; animation: defile 46s linear infinite; }
.defilant:hover .defilant-piste { animation-play-state: paused; }
.defilant span { display: inline-flex; align-items: center; gap: 44px; white-space: nowrap; font-family: var(--police-titre); font-size: 1.05rem; font-weight: 500; letter-spacing: .08em; text-transform: uppercase; color: var(--noir); }
.defilant span::after { content: ''; width: 7px; height: 7px; border-radius: 50%; background: var(--accent); }
.defilant span.valeur-mot { font-family: var(--police-main); font-style: italic; text-transform: none; letter-spacing: 0; font-size: 1.15rem; color: var(--accent-fonce); }
@keyframes defile { to { transform: translateX(-50%); } }

/* --- Chiffres, parcours, maquette --------------------------------------- */

.chiffre .nombre { transition: text-shadow .4s ease, transform var(--transition); }
.chiffre:hover .nombre { transform: translateY(-3px); text-shadow: 0 0 26px rgba(127, 188, 224, .65); }

/* La ligne du parcours se trace etape apres etape. */
html.js .parcours-etape { border-top-color: transparent; background: linear-gradient(var(--noir), var(--noir)) left top / 0 2px no-repeat; }
html.js .parcours-etape.vu { background-size: 100% 2px; }
html.js .parcours-etape::before { scale: 0; transition: scale .5s cubic-bezier(.3, 1.6, .5, 1) .5s, transform var(--transition); }
html.js .parcours-etape.vu::before { scale: 1; }

/* Les jauges de la maquette ne se remplissent qu'une fois a l'ecran. */
html.js .maquette:not(.vu) .jauge > span { animation: none; transform: scaleX(0); }
.maquette-ligne { transition: background var(--transition), padding-left var(--transition); }
.maquette-ligne:not(.entete):not(.bloc):not(.total):hover { background: var(--accent-pale); padding-left: 28px; }

.etape::before { transition: background var(--transition), color var(--transition), transform var(--transition); }
.etape:hover::before { background: var(--accent); border-color: var(--accent); color: #fff; transform: scale(1.1); }
.actualite h3, .partenaire .sigle, .espace-carte h3 { transition: color var(--transition), letter-spacing .35s ease; }
.actualite:hover h3 { color: var(--accent-fonce); }
.portrait { transition: transform .5s cubic-bezier(.3, 1.4, .5, 1), box-shadow var(--transition); }
.membre:hover .portrait, article:hover > .rangee > .portrait { transform: scale(1.07) rotate(-2deg); }
.membre { transition: transform var(--transition), box-shadow var(--transition); }
.membre:hover { transform: translateY(-4px); box-shadow: var(--ombre); }
.citation { background: linear-gradient(var(--accent), var(--accent)) left top / 3px 100% no-repeat; border-left-color: transparent; }
html.js .citation.revele:not(.visible) { background-size: 3px 0; }
.rubriques a { transition: all var(--transition); }
.rubriques a:hover { transform: translateY(-2px); }
.pied a { transition: color var(--transition), padding-left var(--transition); }
.pied ul a:hover { padding-left: 6px; }
.appel-action { background-size: 200% 100%; background-image: linear-gradient(110deg, var(--accent), var(--logo), var(--accent)); animation: degrade 12s ease-in-out infinite alternate; }
@keyframes degrade { to { background-position: 100% 0; } }
.reference { animation: tampon-ref .6s cubic-bezier(.3, 1.5, .5, 1) both; }
@keyframes tampon-ref { from { opacity: 0; transform: scale(.85); } }

/* =========================================================================
   Pages de connexion
   ========================================================================= */

.auth-volet { animation: derive-auth 50s linear infinite; }
@keyframes derive-auth { to { background-position: 32px 32px; } }
.auth-volet > * { animation: entree .8s cubic-bezier(.2, .7, .2, 1) both; }
.auth-volet > *:nth-child(2) { animation-delay: .15s; }
.auth-volet > *:nth-child(3) { animation-delay: .3s; }
.auth-role { animation: entree .6s cubic-bezier(.2, .7, .2, 1) both; }
.auth-role:nth-child(1) { animation-delay: .5s; }
.auth-role:nth-child(2) { animation-delay: .62s; }
.auth-role:nth-child(3) { animation-delay: .74s; }
.auth-role .icone { transition: transform var(--transition); }
.auth-role:hover .icone { transform: scale(1.25) rotate(-8deg); }
.auth-boite > * { animation: entree .6s cubic-bezier(.2, .7, .2, 1) both; }
.auth-boite > *:nth-child(2) { animation-delay: .08s; }
.auth-boite > *:nth-child(3) { animation-delay: .14s; }
.auth-boite > *:nth-child(n+4) { animation-delay: .2s; }
.auth-boite form > * { animation: entree .5s cubic-bezier(.2, .7, .2, 1) both; }
.auth-boite form > *:nth-child(3) { animation-delay: .28s; }
.auth-boite form > *:nth-child(4) { animation-delay: .34s; }
.auth-boite form > *:nth-child(5) { animation-delay: .4s; }
.auth-boite form > *:nth-child(6) { animation-delay: .46s; }

/* =========================================================================
   Espace connecte
   ========================================================================= */

/* Le menu se deroule a la premiere arrivee de la session, pas a chaque page. */
.laterale.intro .laterale-entete { animation: entree .5s cubic-bezier(.2, .7, .2, 1) both; }
.laterale.intro .laterale-nav > * { animation: glisse-menu .45s cubic-bezier(.2, .7, .2, 1) both; animation-delay: calc(var(--n, 0) * 26ms + 120ms); }
@keyframes glisse-menu { from { opacity: 0; transform: translateX(-16px); } }

/* La cloche tinte quand des notifications attendent. */
.bouton-rond:has(.point-notif) .icone { transform-origin: 50% 12%; animation: tinte 5s ease-in-out 1.2s infinite; }
@keyframes tinte { 0%, 84%, 100% { transform: rotate(0); } 87% { transform: rotate(-16deg); } 90% { transform: rotate(13deg); } 93% { transform: rotate(-8deg); } 96% { transform: rotate(4deg); } }

.barre-haute { animation: descente .45s cubic-bezier(.2, .7, .2, 1) both; }
.menu-flottant { transform-origin: top right; transform: translateY(-8px) scale(.96); }
.menu-flottant.ouvert { transform: none; }

.stat { transition: box-shadow var(--transition); }
.stat:hover { box-shadow: var(--ombre-sm); }

.tableau tbody tr { animation: entree .4s cubic-bezier(.2, .7, .2, 1) both; }
.tableau tbody tr:nth-child(2) { animation-delay: .03s; }
.tableau tbody tr:nth-child(3) { animation-delay: .06s; }
.tableau tbody tr:nth-child(4) { animation-delay: .09s; }
.tableau tbody tr:nth-child(5) { animation-delay: .12s; }
.tableau tbody tr:nth-child(6) { animation-delay: .15s; }
.tableau tbody tr:nth-child(n+7) { animation-delay: .18s; }

.programme-ligne { animation: entree .45s cubic-bezier(.2, .7, .2, 1) both; }
.programme-ligne:nth-child(2) { animation-delay: .05s; }
.programme-ligne:nth-child(3) { animation-delay: .1s; }
.programme-ligne:nth-child(4) { animation-delay: .15s; }
.programme-ligne:nth-child(5) { animation-delay: .2s; }
.programme-ligne:nth-child(n+6) { animation-delay: .25s; }
.programme-ligne.aujourdhui .programme-date .numero { animation: battement 2.4s ease-in-out infinite; }
@keyframes battement { 50% { color: var(--accent); scale: 1.08; } }

.onglet { transition: color var(--transition), border-color var(--transition), transform var(--transition); }
.onglet:hover { transform: translateY(-1px); }
.feuille-section { transition: background var(--transition); }
.feuille-section:not(.travail):hover { background: var(--papier); }
.planning-jour-entete.aujourdhui .numero { animation: battement-fond 2.6s ease-in-out infinite; }
@keyframes battement-fond { 50% { box-shadow: 0 0 0 6px rgba(38, 122, 170, .18); } }
.vide .vide-icone { animation: flotte-doux 4s ease-in-out infinite; }
@keyframes flotte-doux { 50% { transform: translateY(-5px); } }
.avatar-grand { transition: transform .4s cubic-bezier(.3, 1.4, .5, 1); }
.carte-cours:hover .avatar-grand { transform: scale(1.06) rotate(-3deg); }

/* --- Moins de mouvement, impression ------------------------------------- */

@media (prefers-reduced-motion: reduce) {
  html.js .revele { opacity: 1 !important; transform: none !important; filter: none !important; }
  html.js .mots .mot > span { transform: none !important; animation: none !important; }
  html.js .parcours-etape { background-size: 100% 2px; }
  html.js .parcours-etape::before { scale: 1; }
  html.js .maquette .jauge > span { transform: none !important; }
  .defilant-piste, .heros-orbe, .bande-photo::after { animation: none !important; }
  .progression-lecture { display: none; }
}

@media print {
  html.js .revele { opacity: 1 !important; transform: none !important; filter: none !important; }
  .progression-lecture, .defiler { display: none; }
}
