/* =====================================================================
   WTV web — le mouvement

   Deux choses ici, et elles ne se ressemblent pas :

   1. LA MORPHOSE de l'affiche vers la fiche, pilotee par morphose.js.
   2. LE RESSORT applique a ce qui bougeait encore sans elan.

   Tout est sous `prefers-reduced-motion` : un systeme regle sur
   « animations reduites » ne doit rien recevoir de tout cela. C'est un
   reglage d'accessibilite, pas une preference esthetique — certaines
   personnes ont mal au coeur devant une interface qui glisse.
   ===================================================================== */

/* La courbe. Elle part vite et finit en douceur : un objet qui a de
   l'elan, pas une valeur qu'on interpole lineairement. C'est celle de
   la pastille de la barre et de la feuille du profil — une seule, pour
   que toute l'application bouge de la meme main. */
:root {
  --wtv-elan: cubic-bezier(.32, .72, 0, 1);
  --wtv-elan-court: cubic-bezier(.22, 1.2, .36, 1);

  /* DEUX VRAIS RESSORTS, et non des courbes dessinees a la main.

     Une courbe de Bezier ne sait pas depasser puis revenir : au mieux
     on l'incline pour en donner l'illusion. `linear()` accepte une
     SUITE DE POINTS, donc n'importe quelle forme — y compris la
     solution d'une equation de ressort amorti.

     Celles-ci sont calculees, pas copiees : masse 1, raideur 190,
     amortissement 17 pour la premiere (rapport 0,62 — sous-amortie,
     8,5 % de depassement, stabilisee en 495 ms) ; raideur 240,
     amortissement 26 pour la seconde (rapport 0,84 — elle se pose sans
     jamais depasser, en 305 ms).

     La premiere pour ce qui se DEPLACE : un objet qui a une masse
     depasse legerement sa cible avant de s'y poser. La seconde pour ce
     qui se REVELE : une opacite qui depasse 1 ne veut rien dire, et un
     rebond sur un fondu se remarque comme un defaut.

     Supporte depuis Safari 17.2. */
  --wtv-ressort: linear(0, 0.0332, 0.1177, 0.2335, 0.3643, 0.4978, 0.6246,
                        0.7388, 0.8368, 0.917, 0.9796, 1.0255, 1.0567, 1.0754,
                        1.084, 1.0849, 1.0802, 1.0718, 1.0613, 1.0499, 1.0387,
                        1.0282, 1.019, 1.0112, 1.0049, 1);
  --wtv-pose: linear(0, 0.0161, 0.0578, 0.1169, 0.187, 0.2628, 0.3404, 0.4172,
                     0.4908, 0.56, 0.6238, 0.6817, 0.7336, 0.7795, 0.8197,
                     0.8545, 0.8842, 0.9094, 0.9305, 0.948, 0.9623, 0.9739,
                     0.9832, 0.9904, 0.9959, 1);
}

/* Le ressort ne sert QUE si le navigateur le comprend : sinon les
   courbes precedentes restent en place, et rien ne change. */
@supports (animation-timing-function: linear(0, 1)) {
  @media (prefers-reduced-motion: no-preference) {
    /* La feuille du profil : elle sort du bouton, elle doit donc avoir
       une masse. */
    html.wtv-tactile #wtv-feuille {
      transition: opacity .16s ease,
                  transform .5s var(--wtv-ressort);
    }
    /* La pastille qui glisse d'une section a l'autre. */
    html.wtv-tactile #wtv-barre .wbar__pastille {
      transition: transform .5s var(--wtv-ressort),
                  width .5s var(--wtv-ressort),
                  opacity .2s ease;
    }
    /* Ce qui se revele se pose, sans rebondir. */
    html.wtv-tactile .chan__art { transition: background-image .34s var(--wtv-pose); }
  }
}

@media (prefers-reduced-motion: no-preference) {

  /* ---- 1. L'AFFICHE QUI DEVIENT LA FICHE --------------------------- */

  ::view-transition-group(wtv-affiche) {
    animation-duration: .46s;
    animation-timing-function: var(--wtv-elan);
  }

  /* SANS CECI l'effet est rate, et c'est le piege du procede : par
     defaut les deux photographies sont ETIREES au cadre qui se deforme
     (`object-fit: fill`). Or on passe d'une affiche en 2:3 a une
     banniere en 16:9 — les visages s'ecrasaient. En `cover`, chacune
     garde ses proportions et se recadre, comme le ferait la vraie
     image. */
  ::view-transition-old(wtv-affiche),
  ::view-transition-new(wtv-affiche) {
    height: 100%; width: 100%;
    object-fit: cover;
    animation-duration: .46s;
    animation-timing-function: var(--wtv-elan);
  }

  /* LE GLITCH DE LA PREMIERE OUVERTURE.

     L'image de la banniere n'est pas encore chargee quand le mouvement
     part : l'affiche grandissait donc vers un cadre VIDE, et l'image
     tombait dedans apres coup. La deuxieme fois elle est en cache, d'ou
     « ca ne le fait que la premiere fois ».

     On ne peut pas attendre l'image sans retarder tout le mouvement. On
     fait donc l'inverse : l'ANCIENNE affiche reste en place presque
     jusqu'au bout, et la nouvelle ne se revele qu'apres un dixieme de
     seconde. Le temps que l'image arrive, c'est la vignette de depart
     qu'on regarde — et s'il manque encore quelque chose, c'est couvert.

     Elles ne se croisent pas longtemps pour autant : ce sont deux images
     DIFFERENTES du meme film, et les fondre lentement l'une dans l'autre
     donnerait une bouillie. */
  ::view-transition-old(wtv-affiche) { animation-duration: .40s; }
  ::view-transition-new(wtv-affiche) {
    animation-delay: .10s;
    animation-duration: .34s;
  }

  /* Le reste de la page se contente d'un fondu : l'affiche doit rester
     l'objet que l'oeil suit. */
  ::view-transition-old(root),
  ::view-transition-new(root) { animation-duration: .30s; }

  /* ---- LA FICHE QUI MONTE, au lieu de se poser d'un bloc -----------

     Premier essai : l'affiche grandissait bien, puis le degrade, le
     titre et le bouton Lecture apparaissaient D'UN COUP par-dessus, a
     plat. Normal — tout ce qui n'est pas nomme est photographie ensemble
     et se fond en une seule fois, plus vite que la morphose. A mi-chemin
     l'affiche grandissait encore sous un texte deja entierement pose.

     On donne donc au voile et au texte leur PROPRE entree : ils montent
     du bas, un peu apres l'affiche, comme une feuille qui se souleve.
     Les noms sont poses en CSS et non par le script : ces elements ne
     sont dessines que lorsque la fiche est a l'ecran, ils ne sont donc
     photographies que la. */
  html.wtv-tactile #detail-scroll { view-transition-name: wtv-fiche; }
  html.wtv-tactile #screen-detail .hero__scrim { view-transition-name: wtv-voile; }

  @keyframes wtv-monte {
    from { opacity: 0; transform: translateY(26px); }
    to   { opacity: 1; transform: none; }
  }
  @keyframes wtv-descend {
    from { opacity: 1; transform: none; }
    to   { opacity: 0; transform: translateY(16px); }
  }

  ::view-transition-new(wtv-fiche) {
    animation: wtv-monte .40s var(--wtv-elan) .12s both;
  }
  /* Au retour elle s'efface vite : c'est l'affiche qui doit conduire
     l'oeil vers la rangee, pas le texte qui s'attarde. */
  ::view-transition-old(wtv-fiche) {
    animation: wtv-descend .18s ease both;
  }

  /* Le voile arrive entre les deux : il assombrit l'image juste assez
     tot pour que le texte reste lisible en montant. */
  ::view-transition-new(wtv-voile) {
    animation: wtv-apparait .34s ease .06s both;
  }
  ::view-transition-old(wtv-voile) {
    animation: wtv-apparait .16s ease reverse both;
  }
  @keyframes wtv-apparait { from { opacity: 0; } to { opacity: 1; } }

  /* ---- 2. LE RESSORT, LA OU IL MANQUAIT ---------------------------- */

  /* Les vignettes. Elles changeaient d'etat sans transition : le cadre
     blanc du focus apparaissait d'un coup. */
  html.wtv-tactile .card__art,
  html.wtv-tactile .scard__art {
    transition: transform .3s var(--wtv-elan),
                box-shadow .3s var(--wtv-elan);
  }
  html.wtv-tactile .card:active .card__art,
  html.wtv-tactile .scard:active .scard__art {
    transform: scale(.965);
  }

  /* Les boutons d'une fiche et les puces : meme main, meme courbe. */
  html.wtv-tactile .detail__actions button,
  html.wtv-tactile .chips .chip,
  html.wtv-tactile .rchip {
    transition: transform .22s var(--wtv-elan-court),
                background .2s ease, color .2s ease;
  }
  html.wtv-tactile .detail__actions button:active { transform: scale(.94); }

  /* Les vignettes de chaines, qui recoivent leur image en cours de
     route : elle ne doit pas apparaitre d'un coup. */
  html.wtv-tactile .chan__art { transition: background-image .3s ease; }
}
