/* =============================================================
   PRISON ISLAND — MOUVEMENT
   « Profondeur, pas mouvement. » La prison se donne par des plans,
   pas par des objets qui se déplacent.

   Tout ce fichier est un enrichissement. L'état final est déjà écrit
   dans composants.css : un navigateur sans animations pilotées par le
   scroll affiche la page entière et lisible, jamais un contenu invisible.

   Note de calibrage — pour la scène épinglée, `animation-range: contain`
   couvre exactement la durée d'épinglage. La piste faisait 320vh : la scène
   coûtait 2 880 px, soit 25 % du défilement de l'accueil pour 83 mots, cinq
   fois le prix au mot du reste de la page. Elle est ramenée à 213vh — un
   tiers de moins, 1 920 px — et déplacée APRÈS les cellules : les cellules
   sont la preuve du produit, le concept en est l'argument, et on montre
   avant d'argumenter.

   Avec un enfant sticky de 100svh, la plage `contain` vaut désormais
   (213 − 100) / (213 + 100) = 36,1 % de la timeline `cover`, contre 52,38 %
   auparavant. Ce n'est pas un plafonnement : la progression de l'effet va
   toujours de 0 à 100 % à l'intérieur de la plage — les six légendes
   s'enchaînent simplement sur moins de défilement.
   Les keyframes ci-dessous sont donc écrites sur 0–100 %, sans recalibrage.
   ============================================================= */

@media (prefers-reduced-motion: no-preference) {
  @supports (animation-timeline: view()) {

    /* ---- Bandeau : avance avec le scroll, jamais avec une horloge ---- */
    .bandeau_piste {
      animation: bandeau-defiler linear both;
      animation-timeline: view(); animation-range: cover 0% cover 100%;
    }
    @keyframes bandeau-defiler { from { transform: translateX(0); } to { transform: translateX(-25%); } }

    /* ---- Révélation : jamais en dessous de 15 % d'opacité ---- */
    .reveal {
      animation: reveler var(--easing-sortie) both;
      animation-timeline: view(); animation-range: entry 0% entry 55%;
    }
    @keyframes reveler { from { opacity: .15; transform: translateY(1.5rem); } to { opacity: 1; transform: none; } }

    /* ---- Plans de profondeur, desktop seulement ---- */
    @media (min-width: 48rem) {
      .section_cellules .fond_grillage, .section_avis .fond_grillage {
        animation: texture-respirer linear both;
        animation-timeline: view(); animation-range: cover 0% cover 100%;
      }
      @keyframes texture-respirer {
        from { transform: scale(1) translateY(-1rem); } to { transform: scale(1.05) translateY(1rem); }
      }
      .fond_halo {
        animation: plan-pres linear both;
        animation-timeline: view(); animation-range: cover 0% cover 100%;
      }
      @keyframes plan-pres { from { transform: translateY(5rem); } to { transform: translateY(-5rem); } }
    }

    /* ---- Le mur des portes : chaque porte s'éclaire en entrant, et reste allumée ---- */
    .porte_ombre {
      animation: porte-eclairer linear both;
      animation-timeline: view(); animation-range: entry 0% entry 100%;
    }
    @keyframes porte-eclairer { from { opacity: .78; } to { opacity: 0; } }

    .porte_feu {
      animation: porte-feu-allumer steps(1, end) both;
      animation-timeline: view(); animation-range: entry 0% entry 100%;
    }
    @keyframes porte-feu-allumer {
      0% { background: #3a3531; box-shadow: none; }
      78% { background: var(--feu-color-vert); box-shadow: 0 0 .625rem var(--feu-color-vert), 0 0 .125rem var(--feu-color-vert); }
    }

    /* Les numéros se remélangent : aucun ordre imposé */
    .porte_numero-avant, .porte_numero-final {
      animation-timing-function: steps(1, end); animation-fill-mode: both;
      animation-timeline: view(); animation-range: entry 0% entry 100%;
    }
    .porte_numero-avant { animation-name: numero-avant; }
    .porte_numero-final { animation-name: numero-final; }
    @keyframes numero-avant { 0% { opacity: 1; } 70% { opacity: 0; } }
    @keyframes numero-final { 0% { opacity: 0; } 70% { opacity: 1; } }

    /* =========================================================
       Scène concept : la silhouette enchaîne trois cellules,
       rate la deuxième, y retourne, repart. Jamais de fermeture.
       ========================================================= */
    /* timeline-scope étend la portée du nom au sous-arbre de la section : sans lui,
       certains moteurs ne résolvent pas --concept depuis l'intérieur du SVG. */
    .section_concept { timeline-scope: --concept; }
    .concept_piste { height: 213vh; view-timeline-name: --concept; view-timeline-axis: block; }
    .concept_scene { position: sticky; top: 0; height: 100svh; }
    .concept_scene-contenu { height: 100%; display: grid; align-items: center; padding-top: var(--espace-8); padding-bottom: var(--espace-8); }

    /* Les six légendes se superposent dans une même cellule de grille :
       la hauteur est réservée par la plus haute, rien ne saute. */
    .concept_legendes { display: grid; }
    /* État par défaut : la première phrase est lisible, les suivantes attendent.
       Si la timeline ne s'active pas — navigateur, extension, cas limite — la scène
       affiche une phrase juste au lieu d'un bloc vide. Jamais d'écran muet. */
    .concept_legende { grid-area: 1 / 1; }
    .concept_legende:not(:first-child) { opacity: 0; }
    .concept_legende {
      /* Bascule nette, jamais de fondu croisé : pendant un croisement, deux
         phrases se superposent au même endroit et deviennent illisibles.
         Le feu passe du vert au rouge d'un coup, la phrase aussi. */
      animation-timing-function: steps(1, end); animation-fill-mode: both;
      animation-timeline: --concept; animation-range: contain 0% contain 100%;
    }
    .concept_legende:nth-child(1) { animation-name: legende-1; }
    .concept_legende:nth-child(2) { animation-name: legende-2; }
    .concept_legende:nth-child(3) { animation-name: legende-3; }
    .concept_legende:nth-child(4) { animation-name: legende-4; }
    .concept_legende:nth-child(5) { animation-name: legende-5; }
    .concept_legende:nth-child(6) { animation-name: legende-6; }
    /* Six plages qui se succèdent sans se toucher : une seule phrase à l'écran. */
    @keyframes legende-1 { 0% { opacity: 1; } 33% { opacity: 0; } }
    @keyframes legende-2 { 0% { opacity: 0; } 33% { opacity: 1; } 44% { opacity: 0; } }
    @keyframes legende-3 { 0% { opacity: 0; } 44% { opacity: 1; } 56% { opacity: 0; } }
    @keyframes legende-4 { 0% { opacity: 0; } 56% { opacity: 1; } 70% { opacity: 0; } }
    @keyframes legende-5 { 0% { opacity: 0; } 70% { opacity: 1; } 82% { opacity: 0; } }
    @keyframes legende-6 { 0% { opacity: 0; } 82% { opacity: 1; } }

    /* Badge : 0 pt avant la réussite, le score après. Un seul des deux est rendu.
       Défaut : le badge vierge. Si l'animation ne tourne pas, on lit « 0 pt »,
       jamais les deux chiffres collés. */
    .concept_badge .badge_apres { display: none; }
    .concept_badge .badge_avant, .concept_badge .badge_apres {
      animation-timing-function: steps(1, end); animation-fill-mode: both;
      animation-timeline: --concept; animation-range: contain 0% contain 100%;
    }
    .concept_badge .badge_avant { animation-name: badge-avant; }
    .concept_badge .badge_apres { animation-name: badge-apres; }
    @keyframes badge-avant { 0% { display: inline; } 71% { display: none; } }
    @keyframes badge-apres { 0% { display: none; } 71% { display: inline; } }

    /* La silhouette et ses poses */
    .concept_figure, .figure_corps, .figure_orientation, .figure_pose,
    .concept_porte.is-deux .concept_etat, .concept_points {
      animation-fill-mode: both;
      animation-timeline: --concept; animation-range: contain 0% contain 100%;
    }
    .concept_figure { animation-name: figure-avancer; animation-timing-function: linear; }
    @keyframes figure-avancer {
      0%, 6% { transform: translate(170px, 640px); }
      30%, 70% { transform: translate(500px, 640px); }
      94%, 100% { transform: translate(830px, 640px); }
    }
    .figure_corps { animation-name: figure-visible; animation-timing-function: linear; }
    @keyframes figure-visible {
      0%, 3% { opacity: 0; } 6%, 34% { opacity: 1; } 35%, 44% { opacity: 0; }
      45%, 61% { opacity: 1; } 62%, 69% { opacity: 0; } 70%, 95% { opacity: 1; } 96%, 100% { opacity: 0; }
    }
    .figure_orientation { animation-name: figure-tourner; animation-timing-function: steps(1, end); }
    @keyframes figure-tourner { 0% { transform: scaleX(1); } 58% { transform: scaleX(-1); } 62% { transform: scaleX(1); } 100% { transform: scaleX(1); } }

    .figure_pose { animation-timing-function: steps(1, end); }
    .figure_pose.is-debout { animation-name: pose-debout; }
    .figure_pose.is-marche-a { animation-name: pose-marche-a; }
    .figure_pose.is-marche-b { animation-name: pose-marche-b; }
    .figure_pose.is-rate { animation-name: pose-rate; }
    .figure_pose.is-hesite { animation-name: pose-hesite; }
    .figure_pose.is-vert { animation-name: pose-vert; }
    @keyframes pose-debout { 0% { opacity: 1; } 9% { opacity: 0; } 30% { opacity: 1; } 45% { opacity: 0; } 94% { opacity: 1; } 100% { opacity: 1; } }
    @keyframes pose-marche-a {
      0% { opacity: 0; } 9% { opacity: 1; } 11.5% { opacity: 0; } 14% { opacity: 1; } 16.5% { opacity: 0; }
      19% { opacity: 1; } 21.5% { opacity: 0; } 24% { opacity: 1; } 26.5% { opacity: 0; }
      78% { opacity: 1; } 80.5% { opacity: 0; } 83% { opacity: 1; } 85.5% { opacity: 0; } 88% { opacity: 1; } 90.5% { opacity: 0; } 100% { opacity: 0; }
    }
    @keyframes pose-marche-b {
      0% { opacity: 0; } 11.5% { opacity: 1; } 14% { opacity: 0; } 16.5% { opacity: 1; } 19% { opacity: 0; }
      21.5% { opacity: 1; } 24% { opacity: 0; } 26.5% { opacity: 1; } 29% { opacity: 0; }
      80.5% { opacity: 1; } 83% { opacity: 0; } 85.5% { opacity: 1; } 88% { opacity: 0; } 90.5% { opacity: 1; } 93% { opacity: 0; } 100% { opacity: 0; }
    }
    @keyframes pose-rate { 0% { opacity: 0; } 45% { opacity: 1; } 55% { opacity: 0; } 100% { opacity: 0; } }
    @keyframes pose-hesite { 0% { opacity: 0; } 55% { opacity: 1; } 62% { opacity: 0; } 100% { opacity: 0; } }
    @keyframes pose-vert { 0% { opacity: 0; } 70% { opacity: 1; } 78% { opacity: 0; } 100% { opacity: 0; } }

    /* Le feu de la deuxième porte : vert, ambre pendant l'essai, rouge au raté, vert à la reprise */
    .concept_porte.is-deux .concept_etat { animation-timing-function: steps(1, end); }
    .concept_porte.is-deux .concept_etat.is-vert { animation-name: etat-vert; }
    .concept_porte.is-deux .concept_etat.is-ambre { animation-name: etat-ambre; }
    .concept_porte.is-deux .concept_etat.is-rouge { animation-name: etat-rouge; }
    @keyframes etat-vert { 0% { opacity: 1; } 34% { opacity: 0; } 70% { opacity: 1; } 100% { opacity: 1; } }
    @keyframes etat-ambre { 0% { opacity: 0; } 34% { opacity: 1; } 44% { opacity: 0; } 62% { opacity: 1; } 70% { opacity: 0; } 100% { opacity: 0; } }
    @keyframes etat-rouge { 0% { opacity: 0; } 44% { opacity: 1; } 62% { opacity: 0; } 100% { opacity: 0; } }

    .concept_points { transform-box: fill-box; animation-name: points-marquer; animation-timing-function: linear; }
    @keyframes points-marquer {
      0%, 69% { opacity: 0; transform: translateY(14px); }
      72%, 84% { opacity: 1; transform: translateY(0); }
      90%, 100% { opacity: 0; transform: translateY(-14px); }
    }
  }

  /* ---- Transition entre pages : la porte de cellule ----
     Consomme une attente qui existe déjà, n'en crée aucune. */
  @view-transition { navigation: auto; }
  ::view-transition-old(root) { animation: porte-sortir 360ms var(--easing-porte) both; }
  ::view-transition-new(root) { animation: porte-entrer 480ms var(--easing-porte) both; }
  @keyframes porte-sortir { to { opacity: 0; transform: perspective(80rem) rotateY(-8deg) translateX(-4%); } }
  @keyframes porte-entrer { from { clip-path: inset(0 0 0 100%); } to { clip-path: inset(0); } }
}

/* Sans support des animations pilotées par le scroll :
   la scène se lit comme une liste de six phrases, toutes visibles. */
@supports not (animation-timeline: view()) {
  .concept_legendes { gap: var(--espace-3); }
  .concept_badge .badge_avant { display: none; }
}

/* Mouvement réduit : le site reste entier, il cesse juste de bouger.
   Le chrono de cellule garde sa durée réelle : c'est une information de jeu,
   pas une décoration — la fausser mentirait au joueur. */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .01ms !important;
    scroll-behavior: auto !important;
  }
  .cellules_porte:hover .porte_battant,
  .cellules_porte:focus-visible .porte_battant,
  .cellules_porte.is-ouverte .porte_battant,
  .cellules_porte.is-validee .porte_battant { transform: none; }
  .defi_fil-curseur { animation-duration: 1.8s !important; animation-iteration-count: infinite !important; }
  .cellule_chrono.is-en-cours .cellule_chrono-barre { animation-duration: 12s !important; }
  .hero_video { display: none; }
}
