/*
 * Loader NexRh — « l'aiguille du pointage », charte « Lime Spark & Graphite ».
 *
 * Source : maquettes de marque NexRh, fichier « NexRh Loader.dc.html ».
 *
 * ⚠️ Ce fichier est un asset public, servi tel quel par `application.blade.php`
 * AVANT le bundle Vite : c'est lui qui anime l'écran d'amorçage, quand aucun
 * composant Vue n'existe encore. Il est donc chargé pour toute la SPA, et
 * `components/NexRhLoader.vue` réutilise EXACTEMENT ces classes plutôt que de
 * recopier les keyframes — une seule définition de l'animation, un seul endroit
 * à corriger.
 *
 * ── Le scénario, en trois temps (cycle de 5,2 s) ──────────────────────────
 *   0 → 0,4 s   le fût droit du N est au repos : c'est l'aiguille, posée sur
 *               son pied.
 *   0,4 → 3,3 s l'aiguille fait UN tour complet à vitesse égale ; la diagonale
 *               du N s'écrit pendant la course. Le geste est celui d'une
 *               horloge, pas d'un logo qui s'anime.
 *   3,3 → 5,2 s l'aiguille s'arrête pile à la verticale — le N est écrit. Le
 *               nœud se pose d'un coup net et une onde en part : le pointage
 *               est enregistré.
 *
 * ── Pourquoi les coordonnées ne sont pas celles de `nexrh-mark.svg` ────────
 * La maquette centre la marque par un groupe `translate(32 32) scale(.6)
 * translate(-30 -29.75)`, ce qui contient le tour entier de l'aiguille dans le
 * cadre 64 × 64. Ce groupe a été REPORTÉ dans les coordonnées des tracés au
 * lieu d'être conservé : avec `transform-box: view-box` (le défaut SVG), un
 * `transform-origin` en pixels se résout dans le repère du viewBox, pas dans
 * celui du parent transformé — le pivot de l'aiguille aurait donc atterri à
 * côté. Tous les tracés d'ici sont déjà dans le repère final.
 *
 * Deux variables pilotent le rendu :
 *   --nexrh-loader-color     couleur de la BARRE de progression. Elle suit le
 *                            thème (`rgb(var(--v-theme-primary))` côté Vue,
 *                            localStorage côté amorçage). Elle ne peint PAS le
 *                            symbole : la marque NexRh porte les mêmes couleurs
 *                            en clair et en sombre, codées en dur dans le SVG.
 *   --nexrh-loader-duration  durée du cycle complet (5,2 s dans la maquette).
 *
 * Les accents lime (#7FA82C / #D9F940 / #3D4A18) sont fixes : c'est la couleur
 * de la marque, elle ne suit pas la primaire (cf. `resources/images/logo.svg`).
 *
 * ⚠️ Seules les COULEURS ont changé le 2026-09-06. Le scénario, les durées et
 * les tracés sont ceux de « l'aiguille du pointage » — la refonte de forme
 * proposée par « NexRh Loader Lime Spark.dc.html » a été écartée.
 */

body {
  margin: 0;
}

html {
  overflow: hidden scroll;
}

/*
 * `fixed` et non `absolute`, et SIBLING de `#app` dans le blade — pas enfant.
 *
 * Le modèle Vuexy d'origine plaçait ce bloc DANS `#app` : `app.mount('#app')`
 * remplaçait alors son contenu, donc le loader disparaissait à l'instant précis
 * où Vue prenait la main, en plein milieu du scénario. Sorti de `#app`, c'est
 * `application.blade.php` qui décide quand le retirer — à `airrh:app-ready`,
 * donc quand la première route est résolue et peinte. Le scénario boucle tant
 * que le chargement dure et n'allonge jamais le démarrage.
 *
 * `z-index` doit dépasser tout ce que l'application peut poser pendant son
 * amorçage, barre de navigation Vuetify (1004) comprise.
 */
#loading-bg {
  position: fixed;
  z-index: 10000;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  background: var(--initial-loader-bg, #f3f4f1);
  inset: 0;
  transition: opacity 0.4s ease;
}

#loading-bg.is-leaving {
  opacity: 0;
  pointer-events: none;
}

.nexrh-loader {
  --nexrh-loader-color: var(--initial-loader-color, #23262f);
  --nexrh-loader-duration: 5.2s;

  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 2.75rem;
}

/*
 * L'écran d'amorçage ne connaît pas le thème Vuetify — il n'existe pas encore.
 * Il suit donc la préférence système, qui est aussi le défaut de `themeConfig`
 * (`theme: 'system'`). Côté Vue, `NexRhLoader.vue` écrase ces deux variables
 * avec les vraies valeurs du thème courant.
 */
@media (prefers-color-scheme: dark) {
  .nexrh-loader {
    --nexrh-loader-heading: #f2f4ef;
    --nexrh-loader-muted: #868c96;
  }
}

/* ── La marque animée ──────────────────────────────────────────────────────
 * Le tour complet de l'aiguille tient EXACTEMENT dans le cadre : le pivot est
 * en (41,6 ; 44,15) et le rayon vaut 15,6 + 3,9 de demi-épaisseur, soit un
 * maximum de 61,1 en x et 63,65 en y. D'où `overflow: hidden` — il ne rogne
 * rien, il garantit qu'un futur ajustement d'échelle ne débordera pas sur la
 * mise en page.
 */
.nexrh-loader__mark {
  overflow: hidden;
}

.nexrh-loader__stroke {
  animation: nexrh-draw-stroke var(--nexrh-loader-duration) cubic-bezier(0.45, 0.02, 0.35, 1) infinite;
}

.nexrh-loader__hand {
  animation: nexrh-hand-sweep var(--nexrh-loader-duration) cubic-bezier(0.42, 0.02, 0.38, 1) infinite;
  transform-origin: 41.6px 44.15px;
}

.nexrh-loader__hand-line {
  animation: nexrh-hand-wake var(--nexrh-loader-duration) ease-in-out infinite;
}

.nexrh-loader__ripple {
  animation: nexrh-stamp-ripple var(--nexrh-loader-duration) cubic-bezier(0.2, 0.6, 0.3, 1) infinite;
  transform-origin: 41.6px 18.95px;
}

.nexrh-loader__node {
  animation: nexrh-node-stamp var(--nexrh-loader-duration) cubic-bezier(0.25, 0.7, 0.3, 1) infinite;
  transform-origin: 41.6px 18.95px;
}

/* ── Le wordmark, qui monte pendant que l'aiguille tourne ─────────────────── */
.nexrh-loader__word {
  display: flex;
  flex-direction: column;
  align-items: center;
  animation: nexrh-word-rise var(--nexrh-loader-duration) cubic-bezier(0.34, 0, 0.3, 1) infinite;
  font-family: "Public Sans", -apple-system, blinkmacsystemfont, "Segoe UI", roboto, sans-serif;
  gap: 0.625rem;
}

/*
 * « Nex » en 800, « Rh » en 500 dans le ciel : c'est la règle de wordmark de la
 * charte. Deux `span` et non un `b`/`i` : la graisse et la couleur sont de la
 * présentation, pas de l'emphase sémantique.
 */
.nexrh-loader__title {
  display: flex;
  align-items: baseline;
  font-size: 2.375rem;
  letter-spacing: -0.04em;
  line-height: 1;
}

.nexrh-loader__title-nex {
  color: var(--nexrh-loader-heading, #23262f);
  font-weight: 800;
}

/*
 * « Jamais de lettres lime : le wordmark reste monochrome dans les deux
 * modes. » Seule la graisse separe « Nex » de « Rh ».
 */
.nexrh-loader__title-rh {
  color: var(--nexrh-loader-heading, #23262f);
  font-weight: 500;
}

.nexrh-loader__tagline {
  color: var(--nexrh-loader-muted, #8a8f99);
  font-size: 0.6875rem;
  font-weight: 700;
  letter-spacing: 0.24em;
  text-transform: uppercase;
}

/* ── La barre de progression, calée sur le cycle ──────────────────────────── */
.nexrh-loader__bar {
  overflow: hidden;
  border-radius: 50rem;
  background: var(--nexrh-loader-track, rgba(217, 249, 64, 14%));
  block-size: 3px;
  inline-size: 250px;
}

.nexrh-loader__bar-fill {
  border-radius: 50rem;
  animation: nexrh-track-fill var(--nexrh-loader-duration) cubic-bezier(0.32, 0.06, 0.28, 1) infinite;
  background: linear-gradient(90deg, var(--nexrh-loader-color), #d9f940);
  block-size: 100%;
  transform-origin: left;
}

.nexrh-loader__caption {
  display: flex;
  align-items: center;
  color: var(--nexrh-loader-muted, #8a8f99);
  font-family: "Public Sans", -apple-system, blinkmacsystemfont, "Segoe UI", roboto, sans-serif;
  font-size: 0.8125rem;
  gap: 0.5rem;
}

.nexrh-loader__dots {
  display: flex;
  gap: 3px;
}

.nexrh-loader__dots > span {
  border-radius: 50%;
  animation: nexrh-loader-dots 1.2s ease-in-out infinite;
  background: #d9f940;
  block-size: 3px;
  inline-size: 3px;
}

.nexrh-loader__dots > span:nth-child(2) {
  animation-delay: 0.15s;
}

.nexrh-loader__dots > span:nth-child(3) {
  animation-delay: 0.3s;
}

/*
 * ⚠️ `opacity` est déclarée de bout en bout, pas seulement à la fin.
 *
 * Une propriété absente des autres keyframes reçoit un keyframe implicite à 0 %
 * construit sur la valeur calculée de l'élément : elle interpole alors sur le
 * cycle ENTIER, avec la courbe de l'animation. C'est ce qui avait éteint la
 * barre de l'ancien loader (mesuré à 0,0019 d'opacité à 94 %). La règle vaut
 * pour les cinq scénarios ci-dessous.
 */
@keyframes nexrh-draw-stroke {
  0%,
  14% {
    opacity: 0;
    stroke-dashoffset: 100;
  }

  20% {
    opacity: 1;
  }

  58% {
    stroke-dashoffset: 0;
  }

  88% {
    opacity: 1;
    stroke-dashoffset: 0;
  }

  96%,
  100% {
    opacity: 0;
    stroke-dashoffset: 0;
  }
}

/*
 * Un tour complet à vitesse égale, puis l'arrêt PILE à la verticale : c'est
 * l'arrêt net qui fait lire l'aiguille, pas la rotation. Ne remplace pas le
 * palier 64 → 100 % par une courbe élastique — le N cesserait d'être écrit.
 */
@keyframes nexrh-hand-sweep {
  0%,
  8% {
    transform: rotate(0deg);
  }

  64% {
    transform: rotate(360deg);
  }

  100% {
    transform: rotate(360deg);
  }
}

@keyframes nexrh-hand-wake {
  0% {
    opacity: 0;
  }

  8% {
    opacity: 0.92;
  }

  88% {
    opacity: 0.92;
  }

  96%,
  100% {
    opacity: 0;
  }
}

@keyframes nexrh-node-stamp {
  0%,
  64% {
    opacity: 0;
    transform: scale(1.9);
  }

  72% {
    opacity: 1;
    transform: scale(1);
  }

  88% {
    opacity: 1;
    transform: scale(1);
  }

  96%,
  100% {
    opacity: 0;
    transform: scale(1);
  }
}

@keyframes nexrh-stamp-ripple {
  0%,
  66% {
    opacity: 0;
    transform: scale(0.35);
  }

  73% {
    opacity: 0.5;
    transform: scale(1);
  }

  88%,
  100% {
    opacity: 0;
    transform: scale(2.4);
  }
}

@keyframes nexrh-word-rise {
  0% {
    opacity: 0;
    transform: translateY(9px);
  }

  28% {
    opacity: 1;
    transform: translateY(0);
  }

  88% {
    opacity: 1;
    transform: translateY(0);
  }

  100% {
    opacity: 0;
    transform: translateY(-5px);
  }
}

@keyframes nexrh-track-fill {
  0% {
    transform: scaleX(0);
  }

  88% {
    transform: scaleX(1);
  }

  100% {
    transform: scaleX(1);
  }
}

@keyframes nexrh-loader-dots {
  0%,
  80%,
  100% {
    opacity: 0.25;
  }

  40% {
    opacity: 1;
  }
}

/*
 * Mouvement réduit : la marque se fige sur sa forme d'arrivée — le SVG est
 * dessiné AU repos (aiguille à la verticale, diagonale complète, nœud posé),
 * donc « pas d'animation » = logo correct. Seule l'onde doit être neutralisée :
 * elle porte `opacity="0"` en attribut, c'est ce qui la masque hors animation.
 * La barre reste, en va-et-vient discret, pour signaler l'activité.
 */
@media (prefers-reduced-motion: reduce) {
  .nexrh-loader__stroke,
  .nexrh-loader__hand,
  .nexrh-loader__hand-line,
  .nexrh-loader__ripple,
  .nexrh-loader__node,
  .nexrh-loader__word,
  .nexrh-loader__dots > span {
    animation: none;
  }

  .nexrh-loader__stroke {
    stroke-dashoffset: 0;
  }

  .nexrh-loader__bar-fill {
    animation: nexrh-loader-slide 1.6s cubic-bezier(0.45, 0, 0.35, 1) infinite;
    inline-size: 40%;
  }
}

@keyframes nexrh-loader-slide {
  0% {
    transform: translateX(-100%);
  }

  100% {
    transform: translateX(280%);
  }
}
