/* Chargement et transitions : écran bleu Magnetic + le « A » du logo, cerclé.
   Le A est le tracé exact du premier A du titre (mêmes coordonnées, même trait, même découpe à 55).
   Il existe en deux exemplaires qui font exactement le même vol :
   - crème, au-dessus du bleu, découpé à la forme du bleu (clip-path synchronisé sur sa rétractation) ;
   - bleu, sous le bleu, donc visible seulement là où la page est révélée.
   Le A a ainsi toujours la bonne couleur sans fondu, et l'exemplaire bleu se pose pixel pour pixel
   sur le A du titre (cible : matrice réelle du logo à l'écran, voir js/components/loader.js).
   La classe .has-loader n'est posée que si JS est actif et que l'utilisateur n'a pas demandé
   à réduire les animations (voir le <script> du <head>). */

.loader { display: none; }
.has-loader .loader, .loader.is-active {
  display: block;
  position: fixed; inset: 0; z-index: 1000;
  pointer-events: auto;
  --loader-a-w: clamp(96px, 9vw + 50px, 210px);  /* A au centre : point focal (~180 px à 1440 px) */
  --loader-ring: calc(var(--loader-a-w) * 1.75); /* diamètre du cercle */
}

.loader__layer { position: fixed; inset: 0; pointer-events: none; }
.loader__bg {
  position: absolute; inset: 0;
  background: var(--blue);
  transform-origin: 50% 50%;
  will-change: transform;
}

/* Le A : même repère que le logo entier (viewBox 0 0 372 55), seul le premier A est tracé.
   La boîte fait donc 372/81 fois la largeur du A ; elle est placée pour que le A (colonne x 96 → 177,
   centre 136,5) soit centré à l'écran. À l'arrivée, cette boîte coïncide avec celle du logo :
   même origine, même taille, même grille de pixels → tracé identique au pixel. */
.loader__a {
  position: absolute; /* calques en fixed inset 0 : coordonnées = viewport */
  width: calc(var(--loader-a-w) * 372 / 81);
  aspect-ratio: 372 / 55;
  left: calc(50% - var(--loader-a-w) * 136.5 / 81);
  top: calc(50% - var(--loader-a-w) * 27.5 / 81);
  overflow: hidden;
  color: var(--cream);
  max-width: none; /* la boîte (logo entier) peut dépasser l'écran sur mobile : base.css limite les svg à 100 % */
  transform-origin: 36.694% 50%; /* centre du A dans la boîte (136,5 / 372) */
  will-change: transform;
}
.loader__a polyline { fill: none; stroke: currentColor; stroke-width: 6; stroke-linejoin: miter; stroke-miterlimit: 10; }
.loader__a--under { color: var(--blue); opacity: 0; } /* n'apparaît que pendant le vol vers le titre */

/* Cercle : un anneau très fin + un arc crème en traîne qui tourne lentement (7 s par tour, pas un « spinner ») */
.loader__ring {
  position: absolute; left: 50%; top: 50%;
  width: var(--loader-ring); aspect-ratio: 1;
  translate: -50% -50%;
  border-radius: 50%;
  will-change: transform, opacity;
}
.loader__ring::before {
  content: ''; position: absolute; inset: 0; border-radius: 50%;
  border: 1px solid color-mix(in srgb, var(--cream) 16%, transparent);
}
.loader__ring::after {
  content: ''; position: absolute; inset: 0; border-radius: 50%;
  background: conic-gradient(from 0deg, transparent 0 66%, color-mix(in srgb, var(--cream) 85%, transparent) 99.6%, transparent 99.6%);
  -webkit-mask: radial-gradient(farthest-side, transparent calc(100% - 1.5px), #000 calc(100% - 1.5px));
  mask: radial-gradient(farthest-side, transparent calc(100% - 1.5px), #000 calc(100% - 1.5px));
  animation: loader-spin 7s linear infinite;
}
@keyframes loader-spin { to { transform: rotate(1turn); } }

/* Entrée : le A se trace, le cercle s'ouvre autour */
.has-loader:not(.loader-instant) .loader__a--over polyline {
  stroke-dasharray: 140; stroke-dashoffset: 140;
  animation: loader-draw 950ms cubic-bezier(0.65, 0, 0.35, 1) 150ms forwards;
}
.has-loader:not(.loader-instant) .loader__a--over {
  opacity: 0;
  animation: loader-a-in 700ms cubic-bezier(0.22, 1, 0.36, 1) 100ms forwards;
}
.has-loader:not(.loader-instant) .loader__ring {
  opacity: 0;
  animation: loader-ring-in 1100ms cubic-bezier(0.22, 1, 0.36, 1) 300ms forwards;
}
@keyframes loader-draw { to { stroke-dashoffset: 0; } }
@keyframes loader-a-in { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: none; } }
@keyframes loader-ring-in { from { opacity: 0; transform: scale(0.86) rotate(-40deg); } to { opacity: 1; transform: none; } }

/* Pendant le chargement : le titre du héros reste immobile (le A doit s'y poser au pixel près),
   son A réel est masqué jusqu'à l'arrivée ; les autres apparitions du héros attendent le reveal.
   .loader-used reste posée ensuite : l'animation d'origine du titre ne rejoue pas. */
.loader-used.js .hero__title { animation: none; opacity: 1; transform: none; }
.hero__logo [data-hero-a].is-hidden { visibility: hidden; }
.is-loading .hero, .is-loading .hero * { animation-play-state: paused !important; }

/* Pendant une transition de navigation */
.is-transitioning body { cursor: progress; }
