/* ================= LA VITRINE VIDÉO =================

   Sous la bande Webdesign. Même principe de calage — une course, un « cale »
   collé qui fait un écran — mais ce qui varie ici n'est pas le contenu : c'est
   LA TAILLE DE LA FENÊTRE.

   ---- LE ZOOM, SANS JAMAIS ROGNER ----

   La carte grandit d'un tiers d'ecran jusqu'a l'ecran entier, et la video la
   remplit a chaque etape. Le point qui a demande deux essais :

   LA CARTE GARDE LE RAPPORT DE LA VIDEO, TOUT DU LONG. Sans ca, plus elle
   grandit plus elle rogne — et c'est inevitable des que la carte finit au
   rapport de l'ECRAN pendant que la video, elle, garde le sien. Un ecran de
   portable fait souvent 1.55 ou 1.60 une fois la barre du navigateur
   enlevee ; une video en 1.78 y perd un bon huitieme de sa largeur.

   Deux choses le garantissent :

   — `aspect-ratio: var(--vv-ratio)` sur la fenetre. Le rapport n'est pas
     ecrit en dur : vitrine-video.js le lit sur le fichier lui-meme
     (videoWidth / videoHeight) des que les metadonnees arrivent. Change la
     video, le cadre suit. 16/9 n'est qu'un repli le temps du chargement.

   — La largeur d'arrivee est `min(100vw, 100vh * ratio)` : le plus grand
     rectangle DE CE RAPPORT qui tienne dans la fenetre. Sur un ecran plus
     large que la video, elle est bornee par la hauteur ; sur un ecran plus
     etroit, par la largeur. Dans les deux cas, l'image entiere est visible.

   « Plein ecran » veut donc dire ici : aussi grand que possible sans rien
   perdre — et non « qui touche les quatre bords en coupant ce qui depasse ».

   Le cout, assume : faire varier une largeur coute une mise en page par
   image, la ou `transform` n'en coute aucune. La fenetre est UN element
   isole et `contain: layout paint` dit au navigateur que rien en dehors n'a
   besoin d'etre recalcule.

   Le coin de 3 s'efface avec l'ouverture : en grand, une image n'a pas de
   coins arrondis.

   ---- LE SON ----

   Voir vitrine-video.js : aucun navigateur ne laisse démarrer une vidéo avec
   le son avant que l'utilisateur ait touché la page. Le CSS ci-dessous
   prévoit donc l'état de repli — un bouton « activer le son ». */

.vv {
  position: relative;
  z-index: 6;
  /* De l'air entre la fin de la vitrine et le pied : une fois la fenetre
     pleinement ouverte, la course s'acheve et le pied montait aussitot sous
     la video (51 px d'ecart — demi-chatbar). 144 de reserve en plus : le
     pied arrive apres un temps, pas colle a l'image (demande de Quentin). */
  padding-bottom: var(--f-144);
  /* --pv : l'ouverture de la fenêtre, de 0 (petite carte) à 1 (plein écran).
     Écrite par vitrine-video.js, elle ne pilote plus la mise en page : la
     fenêtre garde sa taille finale et son ouverture passe par un scale GPU. */
  --pv: 0;
  /* Le rapport de la video, ecrit par vitrine-video.js d'apres le fichier.
     16/9 est le repli, le temps que les metadonnees arrivent. */
  --vv-ratio: 16 / 9;
  /* La fenetre de depart : une carte paysage au tiers de l'ecran. */
  --vv-w0: 34vw;
  /* La fenetre d'arrivee : le plus grand rectangle du rapport de la video
     qui tienne dans l'ecran — MOINS la place de la barre de l'assistant.
     La fenetre est centree dans l'ecran ; son bord bas s'arrete au MILIEU de
     la chatbar (bas 34 + la moitie de ses 34 = 51 du bord), et son bord haut
     a la meme distance, par symetrie (demande de Quentin, 23/08/2026 : la
     video ne monte jamais derriere la barre, elle s'arrete a sa ligne
     mediane). C'est ce min() qui empeche le rognage. */
  --vv-marge: calc(var(--barre-bas) + var(--barre-hauteur) / 2);
  --vv-w1: min(100vw, (100vh - 2 * var(--vv-marge)) * (var(--vv-ratio)));
}

/* La course : un écran pour se caler, 144vh pour ouvrir la fenêtre. */
.vv-course { height: calc(100vh + 144vh); }

.vv-cale {
  position: sticky;
  top: 0;
  height: 100vh;
  display: grid;
  place-items: center;
}

/* LA FENÊTRE. Elle garde sa taille finale dans le flux ; son ouverture est un
   scale composité. Une largeur interpolée image par image forçait le navigateur
   à recalculer la grille et la hauteur de la fenêtre pendant le scroll. */
.vv-fenetre {
  position: relative;
  width: var(--vv-w1);
  aspect-ratio: var(--vv-ratio);
  overflow: hidden;
  border-radius: calc(var(--radius-xs) * (1 - var(--pv)));
  contain: layout paint;
  transform: scale(var(--vv-scale, 0.34));
  transform-origin: center;
  will-change: transform;
}

.vv-video {
  display: block;
  width: 100%;
  height: 100%;
  /* Le cadre a deja le rapport de la video : cover et contain donnent donc
     la meme image. `contain` est choisi parce qu'il est le seul a garantir
     que rien ne sera coupe, meme si un arrondi de sous-pixel fait diverger
     les deux rapports d'un cheveu. */
  object-fit: contain;
  background-color: #000;
}

/* ---- LES COMMANDES ----
   Elles n'existent que quand la souris bouge sur la vidéo, et s'effacent
   après deux secondes d'immobilité. `visibility` en plus de l'opacité : une
   commande invisible ne doit pas être cliquable ni tabulable. */
.vv-commandes {
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  z-index: 2;
  display: flex;
  align-items: center;
  gap: var(--f-13);
  opacity: 0;
  visibility: hidden;
  transition: opacity 233ms cubic-bezier(0.22, 1, 0.36, 1),
              visibility 0s linear 233ms;
}
.vv[data-commandes] .vv-commandes {
  opacity: 1;
  visibility: visible;
  transition-delay: 0s;
}

/* Le bouton : du verre, pas un pavé noir — il est POSÉ SUR l'image, et un
   pavé opaque y ferait un trou. Même matière que la barre de chat : filet
   blanc d'un cheveu, fond fumé, flou derrière. */
.vv-bouton {
  display: grid;
  place-items: center;
  width: var(--f-55);
  height: var(--f-55);
  padding: 0;
  cursor: pointer;
  color: var(--color-text);
  background-color: var(--barre-verre);
  -webkit-backdrop-filter: blur(var(--barre-flou)) saturate(1.4);
  backdrop-filter: blur(var(--barre-flou)) saturate(1.4);
  border: var(--border-hair) solid var(--color-text);
  border-radius: 50%;
  transition: transform 144ms cubic-bezier(0.22, 1, 0.36, 1);
}
.vv-bouton:hover,
.vv-bouton:focus-visible { transform: scale(1.08); outline: none; }
.vv-bouton svg {
  width: var(--f-21);
  height: var(--f-21);
  fill: currentColor;
}
/* Une seule icône visible : c'est l'état de la vidéo qui décide. */
.vv-bouton .vv-pause { display: none; }
.vv[data-joue] .vv-bouton .vv-pause { display: block; }
.vv[data-joue] .vv-bouton .vv-play { display: none; }

/* ---- RENDRE LA MAIN AUX COMMANDES ----

   `.section2` porte `pointer-events: none` (styles.css) — et pointer-events
   S'HÉRITE. Tout ce que cette section contient naissait donc inerte, la
   vitrine comprise : le bouton « Activer le son » était bien dessiné, bien
   placé, bien visible, et ne recevait aucun clic. Mesuré : elementFromPoint
   au centre du bouton renvoyait BODY.

   On ne touche pas à la règle de la section — on ignore ce qu'elle protège,
   et une section entière rendue cliquable pourrait rattraper des clics
   destinés au décor. On rend la main aux SEULES commandes, nommément. */
.vv-son,
.vv-bouton { pointer-events: auto; }

/* ---- L'INVITE AU SON ----

   Elle n'apparaît QUE si le navigateur a refusé le son — c'est-à-dire presque
   toujours, tant que la page n'a pas été touchée : aucun navigateur ne lance
   une vidéo NON MUETTE avant une vraie interaction.

   Elle vivait dans .vv-commandes, qui ne paraît qu'au survol de la vidéo et
   s'efface après deux secondes d'immobilité. Une invite qu'il faut découvrir
   par accident n'est pas une invite. Elle est donc SORTIE de ce groupe : tant
   que le son est coupé, elle est posée en permanence dans le coin de l'image.

   En BAS À GAUCHE. Pas au centre : elle y masquerait le sujet du film et se
   confondrait avec le bouton lecture/pause qui paraît là au survol. Et pas à
   droite : le filigrane « graphen » est incrusté dans ce coin-là de l'image,
   et le bouton lui tombait dessus (vu à l'écran, pas déduit). Le coin bas
   gauche est le seul qui reste libre à toutes les tailles de la fenêtre. */
.vv-son {
  display: none;
  position: absolute;
  left: var(--f-21);
  bottom: var(--f-21);
  z-index: 3;
  align-items: center;
  gap: var(--f-8);
  /* PAS DE CADRE. Ni filet, ni fond fume, ni flou : l'icone et le mot sont
     poses a meme l'image. Un pave de verre dans le coin faisait un objet de
     plus dans une composition qui n'en demandait pas — et il annoncait une
     commande d'interface la ou il ne faut qu'un signe.

     La contrepartie est la lisibilite : sans fond, le blanc doit tenir sur
     n'importe quelle image, y compris un ciel clair. C'est l'ombre portee
     qui s'en charge — deux passes, une serree pour detacher le trait, une
     large pour asseoir l'ensemble. Elle ne se voit pas ; on voit seulement
     que ca reste lisible. */
  padding: var(--f-8);
  margin: calc(var(--f-8) * -1);         /* la cible de clic deborde du dessin, sans decaler ce qu'on voit */
  cursor: pointer;
  font-family: inherit;
  font-size: var(--text-sm);
  line-height: var(--l-18);
  font-weight: var(--fw-light);
  letter-spacing: var(--ls-normal);
  color: #fff;
  background: none;
  border: 0;
  text-shadow: 0 1px 2px rgb(0 0 0 / 0.55), 0 2px 13px rgb(0 0 0 / 0.35);
  filter: drop-shadow(0 1px 2px rgb(0 0 0 / 0.55));
  transition: opacity 233ms cubic-bezier(0.22, 1, 0.36, 1);
}
/* [data-joue] autant que [data-muet] : l'invite dit « le son tourne, tu ne
   l'entends pas ». Sur une video a l'arret elle mentirait, et elle se poserait
   sur l'image fixe avant meme que le film ait commence. */
.vv[data-muet][data-joue] .vv-son { display: flex; }
.vv-son:hover, .vv-son:focus-visible { opacity: 0.82; }

/* Le halo qui battait autour du bouton est parti avec le cadre : un anneau
   qui pulse sans boite a entourer ne veut plus rien dire. Ce qui dit « ça se
   clique », maintenant, c'est le MOT — et le mouvement continu des barres,
   qui distingue tout de suite ce signe d'un filigrane imprime sur l'image.
   Au survol, le mot se souligne : la seule confirmation dont on a besoin. */
.vv-son:hover .vv-son-mot,
.vv-son:focus-visible .vv-son-mot { text-decoration: underline; text-underline-offset: 3px; }

/* ---- LES TROIS BARRES ----

   Elles montent et descendent en boucle, décalées d'un tiers de cycle. Aucun
   mot à lire : quelque chose JOUE. Le trait en travers dit qu'on ne l'entend
   pas. C'est la seule façon de montrer un son — un haut-parleur dessiné, lui,
   ne dit pas si quelque chose tourne ou pas.

   Les hauteurs ne sont pas symétriques d'une barre à l'autre (0.35 / 1 / 0.6
   contre 1 / 0.4 / 0.85) : trois barres qui font exactement le même geste
   décalé se lisent comme un engrenage, pas comme du son. */
.vv-son-icone {
  position: relative;
  display: flex;
  align-items: center;
  gap: 2px;
  width: 16px;
  height: 16px;
  justify-content: center;
}
.vv-barre {
  display: block;
  width: 2px;
  border-radius: 1px;
  background-color: currentColor;
  transform-origin: 50% 50%;
  animation: vv-barre-a 987ms ease-in-out infinite alternate;
}
.vv-barre:nth-child(1) { height: 7px;  animation-delay: 0ms; }
.vv-barre:nth-child(2) { height: 14px; animation-delay: 233ms; animation-name: vv-barre-b; }
.vv-barre:nth-child(3) { height: 10px; animation-delay: 466ms; }
@keyframes vv-barre-a { from { transform: scaleY(0.35); } to { transform: scaleY(1); } }
@keyframes vv-barre-b { from { transform: scaleY(1); } to { transform: scaleY(0.4); } }
/* LE TRAIT : le son tourne, mais coupé. */
.vv-coupe {
  position: absolute;
  left: -2px;
  top: 50%;
  width: 20px;
  height: var(--border-hair);
  background-color: currentColor;
  transform: rotate(-45deg);
  transform-origin: 50% 50%;
}

@media (max-width: 987px) {
  .vv { --vv-w0: calc(100vw - var(--menu-inset) * 2); }
  .vv-course { height: calc(100vh + 89vh); }
  /* Le mot tombe, l'icone reste : sur un ecran de telephone la place manque,
     et trois barres barrees d'un trait se comprennent sans legende. Le bouton
     devient carre et garde sa cible de 44 px — la taille du pouce. */
  .vv-son-mot { display: none; }
  .vv-son {
    left: var(--f-13);
    bottom: var(--f-13);
    width: calc(var(--f-34) + var(--f-13));    /* 47 px : au-dessus des 44 px de cible tactile ; l'echelle Fibonacci n'a pas de cran entre 34 et 55, on compose */
    height: calc(var(--f-34) + var(--f-13));
    padding: 0;
    justify-content: center;
  }
}

/* Mouvement réduit : la fenêtre s'ouvre quand même — c'est la mise en page
   qui suit le défilement, pas une décoration. Seuls les petits mouvements
   des commandes partent. */
@media (prefers-reduced-motion: reduce) {
  .vv-commandes,
  .vv-bouton { transition: none; }
  .vv-bouton:hover,
  .vv-bouton:focus-visible { transform: none; }
  /* L'invite au son RESTE — c'est une commande, pas une decoration : la
     retirer priverait de son celui qui demande moins de mouvement. Seuls le
     battement du halo et le saut des barres partent ; les barres gardent des
     hauteurs inegales, donc l'icone se lit encore comme du son. */
  .vv-son { transition: none; }
  .vv-son::after { animation: none; }
  .vv-barre { animation: none; }
}
