/* ==========================================================================
   Retour de chargement

   Mesure préalable : les pages se rendent entre 50 et 210 ms. Rien n'est
   réellement lent — ce qu'on ressent comme de la lenteur, c'est le silence
   entre le clic et l'affichage. On répond, on n'accélère pas.
   ========================================================================== */

.chargement-barre {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  height: 3px;
  z-index: 9999;
  pointer-events: none;
  opacity: 0;
  background: linear-gradient(
    90deg,
    transparent,
    var(--accent, #1a7f5a),
    color-mix(in srgb, var(--accent, #1a7f5a) 45%, transparent),
    transparent
  );
  background-size: 40% 100%;
  background-repeat: no-repeat;
  background-position: -40% 0;
  transition: opacity .12s ease;
}

.chargement-barre.est-active {
  opacity: 1;
  animation: chargement-glisse 1.1s ease-in-out infinite;
}

@keyframes chargement-glisse {
  0%   { background-position: -40% 0; }
  100% { background-position: 140% 0; }
}

/* --- Lien cliqué ---------------------------------------------------------- */

/* Un clic sur un lien du menu ou d'un tableau ne remplissait aucun formulaire :
   il n'avait donc aucun retour, et la barre seule ne suffisait pas. Le lien
   s'estompe le temps que la page suivante arrive. */
a.est-parti {
  opacity: .6;
  transition: opacity .08s ease;
}

/* --- Arrivée de la page --------------------------------------------------- */

/* C'est le seul retour visible à COUP SÛR : il ne dépend d'aucun seuil de
   durée, puisqu'il se joue à l'arrivée et non pendant l'attente.

   Volontairement limité à l'opacité. Une translation poserait `transform` sur
   un ancêtre, ce qui rendrait les modales `position: fixed` du contenu
   solidaires de ce bloc au lieu de la fenêtre. */
.app-content,
.auth-card {
  animation: chargement-entree .16s ease-out;
}

@keyframes chargement-entree {
  from { opacity: 0; }
  to   { opacity: 1; }
}

/* --- Bouton occupé -------------------------------------------------------- */

.btn.est-occupe {
  position: relative;
  /* Le bouton n'est PAS désactivé : le désactiver retirerait son name/value
     de la requête en cours. On le rend seulement inopérant au clic. */
  pointer-events: none;
  opacity: .72;
}

.btn.est-occupe::after {
  content: '';
  position: absolute;
  right: .55rem;
  top: 50%;
  width: .8rem;
  height: .8rem;
  margin-top: -.4rem;
  border: 2px solid currentColor;
  border-right-color: transparent;
  border-radius: 50%;
  animation: chargement-tourne .6s linear infinite;
}

@keyframes chargement-tourne { to { transform: rotate(360deg); } }

/* Un formulaire parti ne se remodifie pas : la saisie qu'on y ferait ne
   partirait nulle part, et laisserait croire qu'elle a été prise. */
form.est-envoye { opacity: .85; }
form.est-envoye input,
form.est-envoye textarea,
form.est-envoye select { pointer-events: none; }

/* --- Mouvement réduit ----------------------------------------------------- */

/* Les animations continues déclenchent des malaises chez certaines personnes.
   Le retour reste — la barre s'affiche, le bouton se marque — seul le
   mouvement s'arrête. */
@media (prefers-reduced-motion: reduce) {
  .chargement-barre.est-active {
    animation: none;
    background: var(--accent, #1a7f5a);
    background-size: 100% 100%;
    background-position: 0 0;
  }
  .btn.est-occupe::after { animation: none; }
  .app-content,
  .auth-card { animation: none; }
}
