/* =============================================================================
   GrowLED Academy — V2 « passe de craft » sur la homepage /academy
   (2026-08-07d, task-29 du chantier academy-generalisation-3-10).

   Contexte : la V1 (academy-front-20260807c.css, commit ee1d353f) a été
   validée dans sa STRUCTURE par le commanditaire ("là c'est pas mal").
   Consigne explicite : "Propose-moi une V2 de ça amélioré niveau design."
   Même hero, même chemin, mêmes cartes — ce fichier élève l'exécution
   (anneau, halo, contours, pastilles, chips, en-tête de section, badges,
   micro-interactions), il ne restructure rien.

   Charge en TOUT DERNIER, après academy-front-20260805e.css,
   academy-front-20260807.css, academy-front-20260807b.css et
   academy-front-20260807c.css (cf. les 3 contrôleurs front, juste avant
   views/dist/academy.css) : aucun des quatre fichiers précédents n'est
   modifié, celui-ci les surcharge à spécificité égale ou supérieure, même
   technique de cascade que 807b et 807c avant lui.

   Deux points de la liste (anneau centré dans le SVG, accent dégradé sur le
   dernier mot du h1) sont impossibles en CSS pur — le premier parce que
   "centrer du texte dans un cercle" n'a pas de solution HTML-overlay fiable
   (c'est justement le bug corrigé ici), le second parce que CSS n'a pas de
   sélecteur "dernier mot d'un nœud de texte". Les deux ont donc nécessité
   une touche minimale et ciblée dans academy.tpl (documentée dans le tpl
   lui-même et dans le rapport de tâche), en plus des trois zones prévues
   par le brief (chips, en-tête de section, étagère badges). Tout le reste
   de cette liste est purement CSS, contre les classes ga-state-*, ga-step-*
   et data-pos déjà en place — aucune n'est renommée ni supprimée (E2E).
   ============================================================================= */

/* ═════════════════════════════════ HERO ═══════════════════════════════════ */

/* --- 1. Anneau centré : le texte vit maintenant dans le <svg> (cf. tpl) --- */

.gwps-academy .ga-ring-text {
  fill: #fff;
  font-variant-numeric: tabular-nums;
}

.gwps-academy .ga-ring-num {
  font-size: 30px;
  font-weight: 900;
}

.gwps-academy .ga-ring-total {
  font-size: 12.5px;
  font-weight: 700;
  fill: #cdbbe6;
}

/* L'ancien overlay HTML (.ga-ring-value / strong / em) n'existe plus dans le
   tpl : les règles qui le ciblaient dans academy-front-20260807c.css
   (y compris l'override #center_column ... strong { color:#fff !important })
   deviennent inertes, sans effet, sans rien casser — ce fichier n'y touche
   pas. Le fill du SVG n'est de toute façon jamais concerné par la règle
   #center_column strong{color:#b51b5d !important} du thème (elle cible
   `color`, pas `fill`, et un <text> SVG n'est pas un <strong>) : le hack
   n'était nécessaire QUE pour l'ancienne implémentation HTML.
   ----------------------------------------------------------------------- */

/* --- 2. Trait de l'anneau animé au chargement --------------------------
   Essayé d'abord avec @starting-style (zéro octet de JS, zéro variable
   inline) : marche dans une page isolée mais PAS sur /academy (vérifié en
   échantillonnant stroke-dashoffset via requestAnimationFrame dès le premier
   paint — la valeur était déjà figée à la cible dès l'échantillon le plus
   précoce, l'animation ne se jouait jamais). Cause probable : la page charge
   6 feuilles de style du module en série avant celle-ci, et @starting-style
   n'a d'effet que sur la toute première résolution de style de l'élément —
   trop fragile pour un premier rendu réel avec autant de CSS en amont.
   Remplacé par une animation @keyframes classique (comportement identique
   dans tous les moteurs, aucune ambiguïté de "premier style") : la
   circonférence de départ (2π×54) est une CONSTANTE (rayon figé en dur dans
   academy.php, $ringRadius = 54), la valeur d'arrivée est la vraie
   progression de l'utilisateur, exposée en variable CSS via le style inline
   déjà présent sur le cercle (--ga-ring-offset, un seul attribut ajouté au
   tpl, aucune restructuration). animation-fill-mode:both fixe l'état avant
   ET après l'animation : pas de flash à la valeur statique inline avant que
   l'animation démarre. --------------------------------------------------- */

.gwps-academy .ga-ring-fill {
  animation: ga-ring-draw .8s cubic-bezier(.16, 1, .3, 1) both;
}

@keyframes ga-ring-draw {
  from { stroke-dashoffset: 339.29; }
  to { stroke-dashoffset: var(--ga-ring-offset); }
}

/* --- 3. Accent dégradé sur le dernier mot du h1 (cf. tpl : <span class="ga-hero-accent">) --- */

.gwps-academy .ga-hero-accent {
  color: var(--ga-glow-amber);
}

@supports (background-clip: text) or (-webkit-background-clip: text) {
  .gwps-academy .ga-hero-accent {
    background: linear-gradient(96deg, var(--ga-glow-amber) 0%, #ffd889 38%, #a9d977 70%, var(--ga-green) 100%);
    -webkit-background-clip: text;
    background-clip: text;
    color: transparent;
  }
}

#center_column .gwps-academy .ga-hero-accent { color: transparent !important; }
@supports not ((background-clip: text) or (-webkit-background-clip: text)) {
  #center_column .gwps-academy .ga-hero-accent { color: var(--ga-glow-amber) !important; }
}

/* --- 4. Fond du hero : halo à deux temps (cœur ambré chaud puis lavis
   violet) + vignette de bord. Toujours des dégradés, zéro particule/étoile
   (sobriété = premium, cf. brief). Remplace entièrement le `background` de
   academy-front-20260807.css (même sélecteur, spécificité égale, cascade). */

.gwps-academy .ga-hero {
  background:
    radial-gradient(140% 95% at 50% 45%, transparent 58%, rgba(6, 2, 12, .38) 100%),
    radial-gradient(260px 190px at 84% -4%, color-mix(in srgb, var(--ga-glow-amber) 70%, transparent), transparent 62%),
    radial-gradient(640px 420px at 82% -8%, color-mix(in srgb, var(--ga-glow-amber) 40%, transparent), transparent 72%),
    radial-gradient(820px 560px at 13% 118%, color-mix(in srgb, var(--ga-glow-violet) 36%, transparent), transparent 74%),
    linear-gradient(160deg, var(--ga-night) 0%, var(--ga-night-2) 100%);
}

/* ═════════════════════════ BANDEAU BADGES (connecté) ══════════════════════ */

/* --- 11. Étagère à badges : gagné en couleur, pas gagné en silhouette
   gravée (opacité réduite + gris + relief en creux). L'intitulé au survol
   est porté par l'attribut title, ajouté dans le tpl (point 11). --------- */

.gwps-academy .ga-badge-chip:not(.is-earned) {
  filter: grayscale(1);
  opacity: .55;
  box-shadow: inset 0 1px 2px rgba(43, 17, 66, .22), inset 0 -1px 0 rgba(255, 255, 255, .55);
  cursor: help;
}

.gwps-academy .ga-badge-chip.is-earned {
  cursor: help;
}

/* ══════════════════════ EN-TÊTE DE SECTION (point 10) ═════════════════════ */

.gwps-academy .ga-path-head {
  margin: 34px 0 24px;
  padding-top: 26px;
  border-top: 1px solid rgba(43, 17, 66, .10);
}

.gwps-academy .ga-path-eyebrow {
  margin: 0 0 8px;
  font-family: ui-monospace, "SFMono-Regular", Menlo, Consolas, "Liberation Mono", monospace;
  font-size: 11.5px;
  font-weight: 700;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--ga-green-dark);
}

.gwps-academy .ga-path-title {
  margin: 0;
  color: var(--ga-violet);
  font-size: 21px;
  font-weight: 800;
  line-height: 1.3;
}

#center_column .gwps-academy .ga-path-title { color: var(--ga-violet) !important; }

@media (min-width: 900px) {
  .gwps-academy .ga-path-head {
    margin: 44px 0 30px;
  }

  .gwps-academy .ga-path-title {
    font-size: 25px;
  }
}

/* ══════════════════════════ LE CHEMIN (ZIGZAG) ═════════════════════════════ */

/* --- 5. Numéros fantômes en creux : contour plutôt que remplissage plein
   pâle. Repli propre (garde le remplissage plein actuel) si le navigateur
   ne supporte pas text-stroke. --------------------------------------- */

@supports (-webkit-text-stroke: 1px black) or (text-stroke: 1px black) {
  .gwps-academy .ga-step-ghost {
    color: transparent;
    -webkit-text-stroke: 2px rgba(59, 17, 85, .13);
    text-stroke: 2px rgba(59, 17, 85, .13);
  }
}

/* --- 6. La ligne raconte la progression (connecté) ----------------------
   La ligne pointillée d'origine (.ga-steps::before, academy-front-20260807c.css)
   reste intacte et continue de courir sur toute la hauteur — c'est elle qui
   garde "le reste... en pointillé neutre" tel quel, sans qu'on y touche.
   On superpose un segment PLEIN vert uniquement sur les <li> déjà parcourus
   (terminé ou étape courante), à la même position X que la ligne d'origine :
   il peint par-dessus le pointillé existant à cet endroit précis, sans
   dédoubler le motif ailleurs (pas de double pointillé décalé). ---------- */

.gwps-academy .ga-state-done::before,
.gwps-academy .ga-step-current::before {
  content: "";
  position: absolute;
  left: 17px;
  top: -4px;
  bottom: -4px;
  width: 2px;
  background: var(--ga-green);
  z-index: 0;
}

/* Nœuds : à venir = contour pointillé (au lieu du contour plein actuel). */
.gwps-academy .ga-step-node {
  border-style: dashed;
  border-color: rgba(59, 17, 85, .3);
}

.gwps-academy .ga-state-read .ga-step-node,
.gwps-academy .ga-state-done .ga-step-node {
  border-style: solid;
}

/* Nœud terminé : coche pleine (le chiffre texte s'efface, une coche le
   remplace — même tracé que le badge de coin .ga-step-check déjà en place,
   redimensionné pour le petit nœud). */
.gwps-academy .ga-state-done .ga-step-node {
  color: transparent;
}

.gwps-academy .ga-state-done .ga-step-node::after {
  content: "";
  position: absolute;
  inset: 6px;
  background-color: #fff;
  -webkit-mask: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='3.4' stroke-linecap='round' stroke-linejoin='round'><path d='M5 12l5 5L19 7'/></svg>") center/contain no-repeat;
  mask: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='3.4' stroke-linecap='round' stroke-linejoin='round'><path d='M5 12l5 5L19 7'/></svg>") center/contain no-repeat;
}

/* Nœud courant : halo ambré qui pulse lentement (2s), pas le halo violet
   statique d'avant. */
.gwps-academy .ga-step-current .ga-step-node {
  box-shadow: 0 0 0 4px rgba(242, 161, 20, .24);
  animation: ga-node-pulse 2s ease-in-out infinite;
}

@keyframes ga-node-pulse {
  0%, 100% { box-shadow: 0 0 0 0 rgba(242, 161, 20, .45), 0 0 0 4px rgba(242, 161, 20, .24); }
  50% { box-shadow: 0 0 0 7px rgba(242, 161, 20, 0), 0 0 0 4px rgba(242, 161, 20, .24); }
}

/* --- 7. Icônes en pastilles teintées selon l'état ------------------------
   Piège trouvé en vérifiant la capture (pas juste le code) : .ga-step-icon
   dessine l'icône via `mask` (academy-front-20260807.css) — hors le masque
   CSS d'un élément découpe TOUT son rendu, y compris son propre ::before,
   même positionné en dehors de sa boîte (inset négatif). Un ::before posé
   sur .ga-step-icon était donc invisible malgré un background-color calculé
   correct (vérifié en pixel-sampling la première capture : aucun pixel
   teinté autour de l'icône). La pastille est donc posée sur la CARTE
   (.ga-step-card / le <a>, ni masquée ni clippée), aux mêmes coordonnées que
   l'icône, en dessous d'elle dans l'ordre de peinture (z-index négatif dans
   le contexte d'empilement de la carte, déjà positionnée). ---------------- */

.gwps-academy .ga-steps .ga-step-card,
.gwps-academy .ga-steps .ga-step a {
  isolation: isolate; /* borne le contexte d'empilement local, évite toute fuite */
}

.gwps-academy .ga-steps .ga-step-card::before,
.gwps-academy .ga-steps .ga-step a::before {
  content: "";
  position: absolute;
  left: 10px;
  top: 10px;
  width: 44px;
  height: 44px;
  border-radius: 50%;
  background: var(--ga-violet);
  opacity: .13;
  z-index: -1;
  pointer-events: none;
  transition: opacity .2s ease;
}

/* Chaînes de sélecteur IDENTIQUES à la règle de base ci-dessus (même
   .gwps-academy .ga-steps ...), avec juste la classe d'état en plus : la
   variante ".ga-step a::before" de la règle de base (0,0,3,2 : le type "a"
   compte) est PLUS spécifique que ".ga-state-X .ga-step-card::before"
   (0,0,3,1) si on retire ".ga-steps" de la chaîne — piège trouvé en
   vérifiant les pixels de la capture (le vert n'apparaissait jamais). En
   gardant ".ga-steps" partout, chaque état bat la base à spécificité égale
   ou supérieure, sans dépendre de l'ordre source. */
.gwps-academy .ga-steps .ga-state-read .ga-step-card::before,
.gwps-academy .ga-steps .ga-state-read .ga-step a::before,
.gwps-academy .ga-steps .ga-step-current .ga-step-card::before,
.gwps-academy .ga-steps .ga-step-current .ga-step a::before {
  background: var(--ga-amber);
}

.gwps-academy .ga-steps .ga-state-done .ga-step-card::before,
.gwps-academy .ga-steps .ga-state-done .ga-step a::before {
  background: var(--ga-green);
}

.gwps-academy .ga-steps .ga-state-preview .ga-step-card::before,
.gwps-academy .ga-steps .ga-state-preview .ga-step a::before {
  background: var(--ga-muted);
  opacity: .10;
}

/* Icône de l'étape courante : ambre, pour matcher le halo du nœud (point 6)
   et le liseré de la carte (point 8) — même signal "tu es ici" partout. */
.gwps-academy .ga-step-current .ga-step-icon {
  color: var(--ga-amber);
}

/* --- 8. La carte courante rayonne : liseré ambré subtil + ombre teintée,
   remplace le traitement violet plus appuyé de academy-front-20260807c.css. */

.gwps-academy .ga-step-current .ga-step-card,
.gwps-academy .ga-step-current .ga-step a {
  border-color: color-mix(in srgb, var(--ga-amber) 55%, transparent);
  border-left-color: var(--ga-amber);
  box-shadow: 0 0 0 1px rgba(242, 161, 20, .35), 0 20px 38px -24px rgba(242, 161, 20, .55), var(--ga-shadow-hover);
}

/* --- 9. Méta en chips : pilules mono plutôt qu'une ligne de texte courue
   avec point médian (cf. tpl : .ga-chip dans .ga-step-meta). ------------- */

.gwps-academy .ga-steps .ga-step-meta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 6px;
  text-transform: none;
  letter-spacing: normal;
}

.gwps-academy .ga-chip {
  display: inline-flex;
  align-items: center;
  padding: 3px 10px;
  border-radius: 999px;
  background: var(--ga-bg-light);
  border: 1px solid rgba(43, 17, 66, .08);
  color: var(--ga-muted);
  font-family: ui-monospace, "SFMono-Regular", Menlo, Consolas, "Liberation Mono", monospace;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: .02em;
  font-variant-numeric: tabular-nums;
}

.gwps-academy .ga-state-read .ga-chip-state {
  background: rgba(242, 161, 20, .14);
  border-color: transparent;
  color: #8a5a00;
}

.gwps-academy .ga-state-done .ga-chip-state {
  background: rgba(122, 193, 67, .18);
  border-color: transparent;
  color: var(--ga-green-dark);
}

.gwps-academy .ga-chip-preview {
  background: rgba(109, 100, 128, .10);
}

/* --- 12. Survol de carte : l'icône glisse d'un demi-cran et se teinte plus
   fort — rien d'autre (l'élévation/ombre existante de academy-front-20260807c.css
   reste inchangée, cascade normale). ---------------------------------- */

.gwps-academy .ga-steps .ga-step-icon {
  transition: transform .2s ease;
}

.gwps-academy .ga-steps .ga-step a:hover .ga-step-icon,
.gwps-academy .ga-steps .ga-step a:focus-visible .ga-step-icon {
  transform: translateX(4px);
}

.gwps-academy .ga-steps .ga-step a:hover::before,
.gwps-academy .ga-steps .ga-step a:focus-visible::before {
  opacity: .26;
}

.gwps-academy .ga-steps .ga-state-preview .ga-step a:hover::before,
.gwps-academy .ga-steps .ga-state-preview .ga-step a:focus-visible::before {
  opacity: .18;
}

/* ------------------------------- Desktop : zigzag ------------------------- */

@media (min-width: 900px) {
  .gwps-academy .ga-ring-num { font-size: 34px; }
  .gwps-academy .ga-ring-total { font-size: 13px; }

  .gwps-academy .ga-state-done::before,
  .gwps-academy .ga-step-current::before {
    left: 50%;
    margin-left: -1px;
    top: -2px;
    bottom: -2px;
  }

  /* Pastille recentrée sur la nouvelle position/taille desktop de l'icône
     (left:26px/top:26px/32px, cf. academy-front-20260807c.css). */
  .gwps-academy .ga-steps .ga-step-card::before,
  .gwps-academy .ga-steps .ga-step a::before {
    left: 18px;
    top: 18px;
    width: 48px;
    height: 48px;
  }
}

/* ═══════════════════════════════ ACCESSIBILITÉ ═══════════════════════════ */

@media (prefers-reduced-motion: reduce) {
  .gwps-academy .ga-ring-fill {
    animation: none;
  }

  .gwps-academy .ga-step-current .ga-step-node {
    animation: none;
  }

  .gwps-academy .ga-steps .ga-step-icon,
  .gwps-academy .ga-steps .ga-step-card::before,
  .gwps-academy .ga-steps .ga-step a::before {
    transition: none;
  }
}
