/* ============ PROTO v2 : moteur 2021 (prouvé) + contenu approuvé (book.css) ============
 * Le contenu (typo cqw, .txt, .tdm-list, .page-art, fonds papier et couvertures) est
 * stylé tel quel par book.css. Ici on ne fait QUE le modèle de feuilletage du live :
 * 1 .page = 1 face, collée à un côté, z-index statique (en JS), AUCUN translateZ. */

/* ---- Neutralise le modèle .sheet/.face de book.css ---- */
.book {
  perspective: none;                 /* la perspective vit sur .pages */
  transform: translateX(var(--shift, 0%));
  /* PAS de transition : le recentrage --shift est piloté image par image par flip.js
     (verrouillé sur l'assise = même `o` → glissement et ombre parfaitement alignés,
     y compris au GLISSER). Au repos, les classes ci-dessous posent la valeur finale
     (déjà atteinte par la dernière frame → aucun saut). Mouvement réduit = instantané. */
  transition: none;
  pointer-events: auto;              /* book.css la mettait à none */
}
/* Livre fermé : seule la couverture (moitié droite) est visible → on recentre.
   Fin du livre : seule la 4e de couv (moitié gauche) → on recentre de l'autre côté.
   (Valeur de repos ; pendant le virage de la couverture, flip.js pilote --shift inline.) */
/* --shift est posé sur .book-stage (parent commun) → hérité par .book ET .book-shadow
   (l'assise est un SIBLING de .book, pas un descendant : une var sur .book ne l'atteindrait pas).
   Les deux glissent donc ensemble via translateX(var(--shift)). */
.book-stage:has(.book.is-closed) { --shift: -25cqw; }
.book-stage:has(.book.is-closed-back) { --shift: 25cqw; }

/* ---- Scène 3D ---- */
.pages {
  position: relative;
  width: 100%;
  height: 100%;
  transform-style: preserve-3d;
  backface-visibility: hidden;
  perspective: 281cqw;               /* = perspective du 2021, constante */
}

/* ---- Une feuille = une face ---- */
.page {
  position: absolute;
  top: 0;
  width: 50cqw;
  height: 100%;
  transform-origin: 0 0;
  transition: transform 1.4s;        /* durée du 2021 ; la cascade décale les départs */
  backface-visibility: hidden;
  transform-style: preserve-3d;
  background-color: #fbfbfb;
  background-size: cover;
  background-position: center;
  overflow: hidden;                  /* clippe l'illustration aux coins arrondis */
  cursor: grab;
  user-select: none;
  -webkit-user-select: none;
  touch-action: none;                /* le glisser horizontal appartient au livre */
  /* Ombre de virage = box-shadow par page (flip.js anime sa VALEUR sur les pages en vol).
     Déclarée TRANSPARENTE ici → toujours présente → pas de promotion/démotion de calque au
     virage (ajouter une ombre en plein -90° re-rastérisait la page = « page blanche »). Au
     repos / hors vol, flip.js retire l'inline → on retombe sur cette valeur transparente. */
  box-shadow: 0 0 0 rgba(0, 0, 0, 0);
}
.pages.no-anim .page { transition: none; }
.page.is-grabbing { cursor: grabbing; }

/* ---- Mouvement réduit : virages INSTANTANÉS (a11y, exigence KICKOFF) ----
   !important pour couvrir AUSSI les durées posées en inline par le glisser/snap.
   Le recentrage .book est coupé ici (la règle équivalente de book.css est masquée
   par le .book de ce fichier, chargé après). La cascade sommaire, elle, saute d'un
   coup côté JS (flip.js : goToPage → setInstant sous reduce). */
@media (prefers-reduced-motion: reduce) {
  .page { transition-duration: 0s !important; }
  .book { transition: none !important; }
}

/* DROITE (nth-child impair) : à plat (0°) au repos, tournée à -180°. */
.page:nth-child(odd) {
  right: 0;
  transform: rotateY(0deg);
  border-radius: 0 1.875cqw 1.875cqw 0;
}
.page.flipped:nth-child(odd) { transform: rotateY(-180deg); }

/* GAUCHE (nth-child pair) : repliée (180°, invisible par backface) au repos, dépliée (0°). */
.page:nth-child(even) {
  left: 0;
  transform-origin: 100% 0;
  transform: rotateY(180deg);
  border-radius: 1.875cqw 0 0 1.875cqw;
}
.page.flipped:nth-child(even) { transform: rotateY(0deg); }

/* Survol : SEULE la page du dessus à DROITE se soulève (invite à tourner en avant),
   comme oiseaumargelle.fr. La classe .is-top est posée par flip.js sur la SEULE page
   courante du dessus — sinon n'importe quelle page de droite découverte (ex. une
   couverture qui dépasse) se soulèverait au survol. */
.pages:not(.is-flipping) .page.is-top:hover { transform: rotateY(-10deg); }

/* Idem à GAUCHE : la page du dessus à gauche se soulève (invite à revenir en
   arrière). Origine au dos (100% 0) → rotateY POSITIF pour lever le bord libre
   gauche vers le lecteur (miroir du -10deg de droite). Posée APRÈS
   .flipped:nth-child(even) (même spécificité) pour l'emporter sur son rotateY(0). */
.pages:not(.is-flipping) .page.is-top-left:hover { transform: rotateY(10deg); }

/* ---- OMBRES DE VIRAGE ----
   VIRAGE SIMPLE (clic / grab / swipe) = box-shadow ANIMÉE par l'angle, posée en inline par
   flip.js sur la face en vol (op/flou/taille suivent la courbe KEYS).
   CASCADE (éventail) = box-shadow STATIQUE ci-dessous. Animer l'ombre par frame sur 10+ pages
   en cascade = tempête de peinture → frames lâchées, ombres bloquées en rectangles durs. Une
   ombre CONSTANTE est portée par le transform (composée) → fluide, comme la v1. Posée via les
   classes is-cascading (sur .pages, par goToPage) + turning (par addFlight, sur la paire en
   vol), AJOUTÉES quand la page est À PLAT (début/fin de virage) → jamais de churn de calque en
   plein -90°. 3 vars tunables. Miroir gauche comme la v1 (.flipped:nth-child(even)). */
.pages.is-cascading .page.turning {
  box-shadow: var(--casc-sh-x, 1cqw) 0 var(--casc-sh-blur, 0.6cqw) rgba(0, 0, 0, var(--casc-sh-op, 0.18));
}
.pages.is-cascading .page.turning.flipped:nth-child(even) {
  box-shadow: calc(-1 * var(--casc-sh-x, 1cqw)) 0 var(--casc-sh-blur, 0.6cqw) rgba(0, 0, 0, var(--casc-sh-op, 0.18));
}

/* ---- ASSISE DU LIVRE (calque dédié .book-shadow) ----
   Calque PLAT placé SOUS le livre (1er enfant de .book-stage, derrière .book). Pas un
   ::before du livre : un vrai div, jamais en conflit de Z, toujours derrière. C'est
   l'ombre portée du livre sur l'étoffe — l'élément LUI-MÊME est l'ombre (noir plein +
   flou), décalée bas-droite (lumière haut-gauche). Physique DISTINCTE du balayage des
   pages (ne pas la modeler dessus). Régler à l'œil via les variables.
   MORPHING : le livre fermé ne montre qu'UNE couverture, recentrée (shift ±25%) → un
   CARRÉ centré (insets gauche/droite = --book-sh-half). À l'ouverture (clic ou
   relâché d'un glisser), is-closed/is-closed-back tombe → les insets passent à 0 :
   l'ombre GLISSE et S'ÉTEND symétriquement (bord gauche vers la gauche + bord droit
   vers la droite) = la planche pleine, en suivant le recentrage. Reste TOUJOURS
   présente (pas de fondu) : la moitié droite ancre le livre pendant que la gauche
   pousse. transition left/right = durée du glissement. */
.book-shadow {
  --book-sh-op: 0.75;        /* opacité du noir plein */
  --book-sh-blur: 1.5cqw;    /* douceur / étalement */
  --book-sh-y: 1.5cqw;       /* décalage vers le bas (lumière zénithale) */
  --book-sh-x: 0.5cqw;       /* décalage vers la droite (lumière de gauche) */
  --book-sh-spread: 0.4cqw;  /* débord haut/bas */
  position: absolute;
  z-index: 0;                /* sous .book (z-index 1) */
  pointer-events: none;
  /* Haut/bas toujours débordés du spread. */
  top: calc(-1 * var(--book-sh-spread));
  bottom: calc(-1 * var(--book-sh-spread));
  /* Largeur (--book-sh-l/-r, posés par flip.js, en coords LIVRE-LOCAL) : la largeur de
     l'assise n'élargit que selon BOOK_KEYS (palier carré jusqu'à -92°). Le GLISSEMENT (recentrage)
     est porté par translateX(--shift) ci-dessous — la MÊME variable que .book → l'assise glisse
     avec le livre (compositeur, fluide), sans calcul de slide image par image. Défaut = ouvert (0). */
  left:  var(--book-sh-l, 0cqw);
  right: var(--book-sh-r, 0cqw);
  border-radius: 2cqw;
  background: rgba(0, 0, 0, var(--book-sh-op));
  filter: blur(var(--book-sh-blur));
  /* translateX(--shift) = l'assise SUIT le recentrage du livre (même var, même transition CSS
     quand snapPair l'active) → glissement fluide et collé au livre. */
  transform: translateY(var(--book-sh-y)) translateX(calc(var(--book-sh-x) + var(--shift, 0cqw)));
  /* PAS de transition par défaut (glisser au doigt = instantané). snapPair pose une transition
     transform inline pendant le snap couverture → glissement lissé par le compositeur. */
}
/* Repos FERMÉ → assise à la largeur d'une couverture (50cqw, coords livre-local) ; le translateX
   --shift (classe is-closed/-back) la place sous la couverture visible. AVANT = moitié droite,
   ARRIÈRE = moitié gauche (miroir). Ouvert (défaut) = pleine planche (0). */
.book-stage:has(.book.is-closed) .book-shadow { --book-sh-l: 50cqw; --book-sh-r: 0cqw; }
.book-stage:has(.book.is-closed-back) .book-shadow { --book-sh-l: 0cqw; --book-sh-r: 50cqw; }
/* .book passe au-dessus du calque d'ombre. */
.book { z-index: 1; }

/* Couvertures : plus grandes que les pages — débord EXTÉRIEUR 0.5cqw + haut/bas 0.5% —
   2 coins arrondis (bord extérieur seulement, --r = 1.5cqw). PAS de débord côté pli (le
   débord -0.3cqw du modèle .face de 2021 ferait dépasser la couverture PAR-DESSUS le pli
   dans le modèle à pages plates → bande sombre au pli + survol parasite). Bord intérieur
   exactement au centre (50cqw). */
.page.cover { width: 50.5cqw; height: 101%; top: -0.5%; }
.page.cover:nth-child(odd) { right: -0.5cqw; border-radius: 0 1.5cqw 1.5cqw 0; }
.page.cover:nth-child(even) { left: -0.5cqw; border-radius: 1.5cqw 0 0 1.5cqw; }

/* Couvertures EXTÉRIEURES seules (couve-1 devant, couve-4 dos) : léger débord
   de 0.3cqw côté PLI. Sans lui, leur bord intérieur tombe pile au centre (50cqw),
   exactement sur le bord des pages blanches dessous → liseré blanc d'1 px (bord
   anticrénelé) + pages qui percent au pli, livre fermé. En débordant, l'illustration
   recouvre la jointure et le bord passe au-delà du centre : le liseré disparaît.
   SÛR uniquement pour les couv. extérieures : à plat (livre fermé) elles font face
   au FOND SOMBRE au centre. Les couv. INTÉRIEURES (couve-2/3) gardent leur bord au
   centre exact — un débord baverait sur la page blanche voisine (bande sombre au
   pli, livre ouvert). couve-1 : nth-child impair (ancré à droite) → déborde à
   gauche ; couve-4 : nth-child pair (ancré à gauche) → déborde à droite. */
.page.cover.face-couve-1,
.page.cover.face-couve-4 { width: 50.8cqw; }

/* Liseré de lumière du bord HAUT sur CHAQUE page (book.css .face::before), épousant
   les coins arrondis. Caché derrière l'illustration sur les pages d'art (img par-dessus). */
.page::before {
  content: '';
  position: absolute;
  inset: 0;
  pointer-events: none;
  border-radius: inherit;
  box-shadow: inset 0 0.14cqw 0.22cqw -0.06cqw rgba(255, 255, 255, 0.2);
}

/* Extérieur des couvertures (couve-1 devant, couve-4 dos) : biseau de carton —
   liseré haut + vignettage + assise sombre d'angle (couve-4 en miroir), comme 2021. */
.page.face-couve-1::before,
.page.face-couve-4::before {
  box-shadow:
    inset 0 0.14cqw 0.22cqw -0.06cqw rgba(255, 255, 255, 0.3),
    inset -0.18cqw -0.18cqw 0.35cqw rgba(0, 0, 0, 0.3);
}
/* 4e de couv. : coin sombre EN MIROIR (le pli est à sa droite). */
.page.face-couve-4::before {
  box-shadow:
    inset 0 0.14cqw 0.22cqw -0.06cqw rgba(255, 255, 255, 0.3),
    inset 0.18cqw -0.18cqw 0.35cqw rgba(0, 0, 0, 0.3);
}

/* ⚠ L'ancienne ombre de virage « PLAN JUMEAU 3D » (#turn-shadow) a été RETIRÉE le 2026-06-25,
   remplacée par l'ombre box-shadow par page (virage simple animée + cascade statique, plus haut).
   Le code complet du jumeau est archivé (revival kit) : Memory Vault → Docs/Tech/ref_twin-plane-shadow.md */

/* Texte au-dessus de l'illustration (book.css le faisait via .face > .txt). */
.page > .txt { position: relative; z-index: 1; }
