/* ==========================================================================
   VoxNote — couche MOTION de page (View Transitions API, vanilla, zero React)
   feat/aa-motion-voxnote

   Grammaire a 4 roles (verdict CEO 2026-07-03) mappee au SENS du saut, pilotee
   par deux data-attributs poses sur <html> par voxnote-motion.js :
     data-vt  = peer | depth | sheet | shared   (role)
     data-dir = fwd | back                       (sens)

   - peer   B « Fondu-glisse »  : onglets de nav (defaut discret, 75 %).
   - depth  A « Glisse iOS »     : drill-down (home -> fiche, liste -> detail).
   - sheet  D « Recouvrement »   : memos/valider + modales (feuille verticale).
   - shared C « Element partage » : carte appareil -> carnet (le hero morphe).

   PIEGE (note memoire) : le pseudo ::view-transition-* est ATTACHE a html, SANS
   espace. `html[data-vt] ::view-transition-old(root)` (avec espace) = combinateur
   descendant -> ne matche PAS le pseudo-tree genere sur :root -> ignore.

   FALLBACK : Firefox / navigateurs sans VT -> navigation instantanee, zero
   erreur (le @view-transition et les pseudos sont simplement ignores). Le JS
   garde le support (startViewTransition) avant tout appel.
   ========================================================================== */

/* Active les transitions cross-document (MPA) pour toute nav same-origin.
   Les vraies navigations de l'app sont des <a href> plein-ecran -> ceci suffit,
   sans toucher htmx.config.globalViewTransitions (qui envelopperait AUSSI les
   swaps de fond, ex. le poll 90 s du badge cloche = flash periodique). */
@view-transition {
  navigation: auto;
}

/* --------------------------------------------------------------------------
   Elements PERSISTANTS (snapshot propre, hors racine) : ils ne clignotent pas.
   -------------------------------------------------------------------------- */
/* En-tete unifie des 4 shells : reste fixe pendant chaque transition. */
.aa-appheader {
  view-transition-name: aa-appheader;
}
/* Le header a sa propre image -> pas de morph parasite (memes bords).
   z-index:20 : les familles depth/sheet remontent le root ENTRANT (z-index:2 sur
   ::view-transition-new(root)) pour l'effet de recouvrement ; sans un z-index
   ELEVE sur le groupe de chrome, le contenu recouvrirait l'en-tete. Le chrome
   doit rester AU-DESSUS du root (cf. note memoire motion-scope-global). */
::view-transition-group(aa-appheader) {
  animation-duration: 1ms;
  z-index: 20;
}

/* Lanceur Voxa (#jarvis-tab / .aa-jarvis-tab, position:fixed bas-droite) : chrome
   PERSISTANT present sur toutes les pages /app (sauf le dictaphone). Sans
   view-transition-name il est capture DANS le root -> il GLISSE avec le contenu
   (« seul le contenu doit slider », retour CEO). Element UNIQUE par page -> nom
   STATIQUE en CSS (pas de JS, contrairement aux cartes appareil multiples). */
.aa-jarvis-tab {
  view-transition-name: aa-voxa-tab;
}
::view-transition-group(aa-voxa-tab) {
  animation-duration: 1ms; /* snappe a sa position -> reste FIXE, ne slide pas */
  z-index: 20; /* au-dessus du root:2 en depth/sheet (idem chrome header) */
}

/* Hero du carnet appareil (element UNIQUE de la page) : cote destination du
   morph « carte -> carnet ». La carte source recoit le meme nom au clic via JS
   (jamais en statique : plusieurs cartes = noms dupliques = VT annulee). */
.aa-vt-appareil-hero {
  view-transition-name: aa-appareil-hero;
}
::view-transition-group(aa-appareil-hero) {
  animation-duration: 360ms;
  animation-timing-function: cubic-bezier(0.2, 0, 0, 1);
}

/* Duree de reference d'un changement d'ecran (design-craft §7). */
::view-transition-group(root) {
  animation-duration: 320ms;
}

/* ==========================================================================
   Keyframes
   ========================================================================== */
@keyframes aa-vt-fade-in {
  from { opacity: 0; }
  to   { opacity: 1; }
}
@keyframes aa-vt-fade-out {
  from { opacity: 1; }
  to   { opacity: 0; }
}

/* B peer — fondu-glisse discret (28px). */
@keyframes aa-vt-peer-in-fwd {
  from { opacity: 0; transform: translateX(24px); }
  to   { opacity: 1; transform: translateX(0); }
}
@keyframes aa-vt-peer-in-back {
  from { opacity: 0; transform: translateX(-24px); }
  to   { opacity: 1; transform: translateX(0); }
}

/* A depth — glisse iOS (plein ecran + parallaxe + assombrissement). */
@keyframes aa-vt-in-from-right {
  from { transform: translateX(100%); }
  to   { transform: translateX(0); }
}
@keyframes aa-vt-out-to-left {
  from { transform: translateX(0); opacity: 1; }
  to   { transform: translateX(-28%); opacity: 0.55; }
}
@keyframes aa-vt-in-from-left {
  from { transform: translateX(-28%); opacity: 0.55; }
  to   { transform: translateX(0); opacity: 1; }
}
@keyframes aa-vt-out-to-right {
  from { transform: translateX(0); }
  to   { transform: translateX(100%); }
}

/* D sheet — recouvrement vertical (feuille qui monte, page qui s'enfonce). */
@keyframes aa-vt-up-from-bottom {
  from { transform: translateY(100%); }
  to   { transform: translateY(0); }
}
@keyframes aa-vt-down-to-bottom {
  from { transform: translateY(0); }
  to   { transform: translateY(100%); }
}
@keyframes aa-vt-recede {
  from { transform: scale(1); opacity: 1; }
  to   { transform: scale(0.96); opacity: 0.6; }
}
@keyframes aa-vt-return {
  from { transform: scale(0.96); opacity: 0.6; }
  to   { transform: scale(1); opacity: 1; }
}

/* ==========================================================================
   B « Fondu-glisse » — DEFAUT (peer, et repli si data-vt absent).
   ========================================================================== */
html[data-vt="peer"]::view-transition-old(root) {
  animation: 220ms ease both aa-vt-fade-out;
}
html[data-vt="peer"][data-dir="fwd"]::view-transition-new(root) {
  animation: 300ms cubic-bezier(0.2, 0, 0, 1) both aa-vt-peer-in-fwd;
}
html[data-vt="peer"][data-dir="back"]::view-transition-new(root) {
  animation: 300ms cubic-bezier(0.2, 0, 0, 1) both aa-vt-peer-in-back;
}

/* ==========================================================================
   A « Glisse iOS » — depth (drill-down). Retour = inverse.
   ========================================================================== */
html[data-vt="depth"][data-dir="fwd"]::view-transition-new(root) {
  animation: 340ms cubic-bezier(0.32, 0.72, 0, 1) both aa-vt-in-from-right;
  z-index: 2;
}
html[data-vt="depth"][data-dir="fwd"]::view-transition-old(root) {
  animation: 340ms cubic-bezier(0.32, 0.72, 0, 1) both aa-vt-out-to-left;
  z-index: 1;
}
html[data-vt="depth"][data-dir="back"]::view-transition-new(root) {
  animation: 340ms cubic-bezier(0.32, 0.72, 0, 1) both aa-vt-in-from-left;
  z-index: 1;
}
html[data-vt="depth"][data-dir="back"]::view-transition-old(root) {
  animation: 340ms cubic-bezier(0.32, 0.72, 0, 1) both aa-vt-out-to-right;
  z-index: 2;
}

/* ==========================================================================
   D « Recouvrement » — sheet (memos/valider, presentations). Retour = inverse.
   ========================================================================== */
html[data-vt="sheet"][data-dir="fwd"]::view-transition-new(root) {
  animation: 380ms cubic-bezier(0.32, 0.72, 0, 1) both aa-vt-up-from-bottom;
  z-index: 2;
}
html[data-vt="sheet"][data-dir="fwd"]::view-transition-old(root) {
  animation: 380ms ease both aa-vt-recede;
  z-index: 1;
}
html[data-vt="sheet"][data-dir="back"]::view-transition-new(root) {
  animation: 380ms ease both aa-vt-return;
  z-index: 1;
}
html[data-vt="sheet"][data-dir="back"]::view-transition-old(root) {
  animation: 380ms cubic-bezier(0.32, 0.72, 0, 1) both aa-vt-down-to-bottom;
  z-index: 2;
}

/* ==========================================================================
   C « Element partage » — shared (carte appareil -> carnet).
   La racine se contente d'un fondu ; le hero nomme (aa-appareil-hero) morphe
   tout seul. Si le hero n'existe pas des deux cotes (acces direct au carnet),
   il n'y a rien a morpher -> fondu simple = degradation propre exigee (CEO).
   ========================================================================== */
html[data-vt="shared"]::view-transition-old(root) {
  animation: 260ms ease both aa-vt-fade-out;
}
html[data-vt="shared"]::view-transition-new(root) {
  animation: 320ms ease both aa-vt-fade-in;
}

/* ==========================================================================
   a11y — prefers-reduced-motion : tous les roles retombent en FONDU bref.
   (exigence projet AAA + note memoire « reduced-motion = fondu »).
   ========================================================================== */
@media (prefers-reduced-motion: reduce) {
  html[data-vt]::view-transition-old(root) {
    animation: 120ms ease both aa-vt-fade-out !important;
  }
  html[data-vt]::view-transition-new(root) {
    animation: 120ms ease both aa-vt-fade-in !important;
  }
  ::view-transition-group(root),
  ::view-transition-group(aa-appareil-hero),
  ::view-transition-group(aa-appheader),
  ::view-transition-group(aa-voxa-tab) {
    animation-duration: 120ms !important;
  }
}
