/* =========================================================================
   MOMA — Animations et etats de revelation
   Principe : legeres, rapides, uniquement opacity et transform (composites
   sur le GPU, aucun reflow). Aucune animation decorative gratuite.

   Regle de securite : l'etat masque n'est applique QUE si le document porte
   la classe .js-reveal-ready, posee par js/animations.js apres avoir
   verifie la presence d'IntersectionObserver et l'absence de
   prefers-reduced-motion. Sans JavaScript, ou si le script echoue, tout le
   contenu reste visible : aucune information ne depend de l'animation.
   ========================================================================= */

/* --- Revelation a l'entree dans le viewport ----------------------------- */
.js-reveal-ready [data-reveal] {
  opacity: 0;
  transform: translate3d(0, 10px, 0);
  transition:
    opacity var(--dur-slow) var(--ease-out),
    transform var(--dur-slow) var(--ease-out),
    filter var(--dur-slow) var(--ease-out);
  will-change: opacity, transform;
}

/* Flou d'entree (D-29) : reserve aux blocs PHOTOGRAPHIQUES, jamais au texte
   — un flou anime sur du texte degraderait la lisibilite pendant la
   transition pour les troubles visuels et cognitifs (revue
   accessibility-lead, verdict bloquant). Les blocs de texte (eyebrow,
   titres, prose, listes...) n'ont donc pas de regle de flou et ne gardent
   que fondu + translation, comme avant.
   Seul .duo__media est concerne : il ne contient qu'une image, jamais
   d'element focusable. .trouver__figure (iframe Google Maps) n'a plus de
   data-reveal du tout — voir le commentaire dans index.html. */
.js-reveal-ready [data-reveal].duo__media {
  filter: blur(8px);
}

.js-reveal-ready [data-reveal].is-revealed {
  opacity: 1;
  transform: translate3d(0, 0, 0);
  filter: none;
  will-change: auto;
}

/* Decalages successifs, volontairement courts pour ne jamais retarder la
   lecture. Au-dela de 3 elements le decalage n'augmente plus : le delai
   maximal (210ms) reste sous le plafond de ~240ms recommande par la revue
   accessibility-lead pour qu'un utilisateur clavier rapide ne rencontre
   jamais un ecart perceptible avant qu'un element ne soit revele. */
.js-reveal-ready [data-reveal-delay="1"] { transition-delay: 70ms; }
.js-reveal-ready [data-reveal-delay="2"] { transition-delay: 140ms; }
.js-reveal-ready [data-reveal-delay="3"] { transition-delay: 210ms; }

/* --- Garde clavier (D-29, bloquant) ---------------------------------------
   Un element qui recoit reellement le focus (au clavier, ou parce qu'il
   contient l'element focus, cas des conteneurs [data-reveal]) doit
   apparaitre IMMEDIATEMENT, meme s'il n'a pas encore croise le viewport
   scroll : sinon le focus serait pose sur un contenu invisible, en echec de
   2.4.7. Complete par le gestionnaire `focusin` de js/animations.js, qui
   evite que l'element ne redisparaisse quand le focus le quitte ensuite. */
.js-reveal-ready [data-reveal]:focus-visible,
.js-reveal-ready [data-reveal]:has(:focus-visible) {
  opacity: 1 !important;
  transform: none !important;
  filter: none !important;
  transition: none !important;
}

/* --- Carte : cascade interne des panneaux (D-30) -------------------------
   Le panneau actif ([role=tabpanel], tabindex="0") ne porte pas
   [data-reveal] lui-meme : ce sont ses enfants directs (intro, photos,
   liste de plats) qui s'animent individuellement. Nicher un [data-reveal]
   dans un autre aurait compose deux fondus d'opacite independants
   (le panneau ET son contenu), visuellement plus terne qu'un vrai fondu.
   Le declencheur est la classe .is-revealed, posee par js/menu.js : une
   fois au premier passage de .tabs dans le viewport (evenement
   moma:revealed diffuse par js/animations.js), puis rejouee a chaque
   changement d'onglet (cascadePanel()). Sans JavaScript, sans support
   d'IntersectionObserver ou avec un mouvement reduit, .js-reveal-ready
   n'existe jamais et tout ce qui suit ne s'applique pas : voir le principe
   de securite en tete de ce fichier. */

/* --i (pose sur chaque <li class="dish"> par renderDish) pilote le
   decalage d'un plat ; --group-delay celui du groupe auquel appartient un
   enfant direct du panneau. Assignation separee de la regle visuelle
   ci-dessous : une custom property se transmet par heritage DOM reel, pas
   par selecteur — .dish-list doit la recevoir comme les autres enfants
   pour la retransmettre a ses <li>, meme si elle n'anime pas sa propre
   opacite (cascade de deuxieme rang, .mediaPosition:"after" inclus). */
.tabpanel > * { --group-delay: 0ms; }
.tabpanel > *:nth-child(2) { --group-delay: 60ms; }
.tabpanel > *:nth-child(3) { --group-delay: 120ms; }

.js-reveal-ready .tabpanel > *:not(.dish-list) {
  opacity: 0;
  transform: translate3d(0, 12px, 0);
  transition:
    opacity var(--dur-slow) var(--ease-out),
    transform var(--dur-slow) var(--ease-out);
  transition-delay: var(--group-delay, 0ms);
  will-change: opacity, transform;
}

.js-reveal-ready .tabpanel.is-revealed > *:not(.dish-list) {
  opacity: 1;
  transform: none;
  will-change: auto;
}

/* Plats : decalage individuel qui s'ajoute au delai du groupe (pose sur
   .dish-list par la regle ci-dessus). Plafonne a l'index 5 (renderDish,
   DISH_STAGGER_CAP) : au-dela, une longue categorie (Pizzas, 11 entrees)
   ne fait pas attendre ses derniers plats plus longtemps que les
   precedents — meme principe que le plafond a 3 paliers de data-reveal-delay
   plus haut. */
.js-reveal-ready .tabpanel .dish-list > .dish {
  opacity: 0;
  transform: translate3d(0, 9px, 0);
  transition:
    opacity var(--dur-slow) var(--ease-out),
    transform var(--dur-slow) var(--ease-out);
  transition-delay: calc(var(--group-delay, 0ms) + (var(--i, 0) * 24ms));
  will-change: opacity, transform;
}

.js-reveal-ready .tabpanel.is-revealed .dish-list > .dish {
  opacity: 1;
  transform: none;
  will-change: auto;
}

/* Garde clavier (2.4.7) : aucun element n'est independamment focusable a
   l'interieur d'un panneau (seul le panneau lui-meme, tabindex="0", l'est),
   donc pas besoin d'un pendant :has() ici — a la difference de la garde
   generique sur [data-reveal] plus haut. Le pendant JavaScript (ecouteur
   focusin permanent, non rejouable) est dans js/menu.js. */
.tabpanel:focus-visible > *,
.tabpanel:focus-visible .dish-list > .dish {
  opacity: 1 !important;
  transform: none !important;
  transition: none !important;
}

/* --- Micro-interactions -------------------------------------------------
   Le survol ne porte jamais d'information : il ne fait qu'accompagner.
   Neutralise sur les appareils sans survol reel. */
@media (hover: hover) and (pointer: fine) {
  /* Leger zoom des photographies au survol, contenu par overflow:hidden
     du conteneur .ratio. */
  .zoomable img {
    transition: transform var(--dur-slow) var(--ease-out);
  }

  .zoomable:hover img {
    transform: scale(1.035);
  }
}

/* =========================================================================
   REDUCTION DE MOUVEMENT
   reset.css neutralise deja durees et transitions globalement. Ici on
   s'assure en plus qu'aucun element ne reste bloque dans un etat masque
   ou decale, et on supprime les transformations de survol.
   ========================================================================= */
@media (prefers-reduced-motion: reduce) {
  .js-reveal-ready [data-reveal],
  .js-reveal-ready [data-reveal].is-revealed {
    opacity: 1 !important;
    transform: none !important;
    filter: none !important;
    transition: none !important;
  }

  .tabpanel > *,
  .tabpanel.is-revealed > *,
  .dish-list > .dish,
  .tabpanel.is-revealed .dish-list > .dish {
    opacity: 1 !important;
    transform: none !important;
    transition: none !important;
  }

  .zoomable:hover img {
    transform: none !important;
  }
}
