/* SFTS EXPERIENCE COMPONENT #001 — "Video Experience"
   Extrait de MT Univers (mt-univers/page-zone-realisations.php +
   style.css, 2026-09-24) le 2026-09-23/24 pour devenir un composant SFTS
   générique du générateur, réutilisable sur n'importe quel site client.

   Règle d'extraction (voir la mémoire "maturité extraction composant") :
   aucune dépendance métier ou d'identité visuelle propre à un client. Toute
   couleur vient des tokens --sfts-vx-* (posés en inline style par
   component.php, valeurs de repli ci-dessous si le client n'en fournit
   aucune) — jamais une couleur MT Univers (--deep-2/--deep-ink/--accent-gold)
   codée en dur ici. Les proportions vidéo (aspect-ratio) et la fenêtre de
   matérialisation de la signature viennent aussi de variables, pas de
   valeurs figées sur le fichier 1280×800 de MT Univers.

   Comportement identique à la version MT Univers validée en direct le
   2026-09-24 (7 bugs réels trouvés et corrigés à cette occasion) : voir
   le README.md de ce dossier pour la liste, reprise ici comme la checklist
   de non-régression de ce composant. */

.sfts-vx {
  --sfts-vx-bg: #14161c;
  --sfts-vx-fg: #f5f5f0;
  --sfts-vx-accent: #c9a227;
  --sfts-vx-control-bg: rgba(10, 12, 16, 0.4);
  --sfts-vx-control-fg: rgba(255, 255, 255, 0.4);
  --sfts-vx-aspect-ratio: 16 / 9;
  --sfts-vx-shadow: 0 24px 60px -30px rgba(0, 0, 0, 0.45);
}

/* Cadre contenu, responsive, jamais plein écran par défaut — extraction du
   bug réel "les dimensions en hauteur de la vidéo dépasse la hauteur de
   l'écran ordinateur" (MT Univers, 2026-09-24) : min() calcule la plus
   petite des 3 largeurs possibles (100% du conteneur, un plafond de
   confort, et la largeur qui donnerait exactement 70vh de haut avec le
   ratio de CE client) — jamais de max-height posé directement sur un
   aspect-ratio, peu fiable selon les navigateurs. Le plafond "1080px" de
   MT Univers (hérité de la largeur de son .wrap) devient un plafond
   générique raisonnable de 1100px, mais reste dans le flux normal du
   conteneur qui l'accueille : un site avec un .wrap plus étroit borne déjà
   naturellement cette largeur avant que 1100px n'entre en jeu.

   Bug réel trouvé le 23/09 lors du test de fidélité MT Univers post-
   extraction ("aucune hypothèse implicite 16/9") : ce 3ᵉ candidat codait
   `16 / 9` en dur au lieu de dériver de --sfts-vx-aspect-ratio (déjà la
   source de vérité pour la propriété aspect-ratio juste au-dessus) — pour
   un ratio différent de 16/9 (MT Univers = 1280/800 = 1.6), le plafond de
   70vh visé devenait ~77.8vh en pratique. `var(--sfts-vx-aspect-ratio)`
   substitue directement le token "L / H" de la variable dans le calc() —
   équivalent mathématiquement à `70vh * (L/H)` puisque * et / ont la même
   précédence en CSS (évalués de gauche à droite) : jamais de valeur en
   dur, jamais une 2ᵉ source de vérité pour ce ratio. */
.sfts-vx-frame {
  position: relative;
  aspect-ratio: var(--sfts-vx-aspect-ratio);
  overflow: hidden;
  border-radius: 20px;
  box-shadow: var(--sfts-vx-shadow);
  background: var(--sfts-vx-bg);
  width: min(100%, 1100px, calc(70vh * var(--sfts-vx-aspect-ratio)));
  margin: 0 auto;
}
.sfts-vx-media {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  transform-origin: center center;
  will-change: transform;
}
.sfts-vx-frame::before {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  z-index: 1;
  /* Dégradé de lisibilité pur (jamais teinté par un token client) : sert
     uniquement à garder les légendes lisibles quelle que soit l'image en
     dessous, pas une signature visuelle de marque. */
  background: linear-gradient(to top, rgba(0, 0, 0, 0.72) 0%, rgba(0, 0, 0, 0.18) 42%, rgba(0, 0, 0, 0) 68%);
}
/* Plein écran natif du navigateur (Fullscreen API) : dans :fullscreen,
   l'élément casse déjà sa boîte normale (calque propre, plein écran) — on
   efface seulement les habillages "vignette dans la page" qui n'ont plus
   de sens une fois plein écran. */
.sfts-vx-frame:fullscreen,
.sfts-vx-frame.is-fullscreen {
  border-radius: 0;
  box-shadow: none;
  aspect-ratio: auto;
  width: 100vw;
  height: 100vh;
}

/* Fin de vidéo : la classe "is-ending" ne touche JAMAIS .sfts-vx-media (la
   vidéo se termine normalement, sur n'importe quelle image, jamais
   retouchée) — elle efface seulement les éléments secondaires (barre,
   légendes) pendant que la signature de sortie prend le relais. */
.sfts-vx-bar,
.sfts-vx-chapters {
  transition: opacity 0.6s ease;
}
.sfts-vx.is-ending .sfts-vx-bar,
.sfts-vx.is-ending .sfts-vx-chapters {
  opacity: 0;
}

/* Signature de sortie (logo réel du client, jamais un texte reconstruit —
   voir component.php, sfts_video_experience_inline_svg()). Positionnée par
   défaut en bas-gauche : bug réel trouvé sur MT Univers (chevauchement
   avec le bouton son une fois le cadre réduit, plus un problème une fois
   plein écran retiré) — bas-gauche, son bas-droite, plein écran haut-
   droite : 3 coins distincts, jamais de collision. --sfts-vx-signature-pos
   permet de choisir un autre coin (voir component.php, seal.position) sans
   dupliquer cette règle. */
.sfts-vx-signature {
  position: absolute;
  z-index: 2;
  left: 28px;
  bottom: 28px;
  pointer-events: none;
  opacity: 0;
  filter: drop-shadow(0 2px 8px rgba(0, 0, 0, 0.5));
}
.sfts-vx-signature--pos-bottom-right { left: auto; right: 28px; bottom: 28px; }
.sfts-vx-signature--pos-top-left { left: 28px; bottom: auto; top: 28px; }
.sfts-vx-signature--pos-top-right { left: auto; right: 28px; bottom: auto; top: 28px; }
.sfts-vx-signature-mark {
  display: block;
  height: 40px;
  width: auto;
  color: var(--sfts-vx-fg);
}
@media (max-width: 700px) {
  .sfts-vx-signature { left: 20px; bottom: 20px; }
  .sfts-vx-signature--pos-bottom-right { left: auto; right: 20px; bottom: 20px; }
  .sfts-vx-signature--pos-top-left { left: 20px; bottom: auto; top: 20px; }
  .sfts-vx-signature--pos-top-right { left: auto; right: 20px; bottom: auto; top: 20px; }
  .sfts-vx-signature-mark { height: 30px; }
}
@media (prefers-reduced-motion: reduce) {
  .sfts-vx-signature { display: none; }
}
/* Repli à 4 niveaux (voir script.js pour le détail) : sous reduced-motion,
   ce rectangle statique (poster affiché, JS jamais lancé) EST déjà le
   repli — transform neutralisé par sécurité si jamais un style venait à
   s'y glisser. */
@media (prefers-reduced-motion: reduce) {
  .sfts-vx-media { transform: none !important; }
}

.sfts-vx-bar {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 2;
  height: 2px;
  background: rgba(255, 255, 255, 0.18);
}
.sfts-vx-bar-fill {
  display: block;
  height: 100%;
  width: 0%;
  background: var(--sfts-vx-accent);
}
@media (prefers-reduced-motion: reduce) {
  .sfts-vx-bar { display: none; }
}

/* Porte d'entrée sonore : un geste utilisateur explicite est le seul moyen
   d'obtenir un son audible dans n'importe quel navigateur. "is-hidden" est
   l'état PAR DÉFAUT côté HTML (voir component.php) : sans JS, jamais
   retirée, donc jamais affichée ni cliquable — ce même comportement reste
   valable quel que soit le client. */
.sfts-vx-gate {
  position: absolute;
  inset: 0;
  z-index: 3;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
  padding: 24px;
  opacity: 1;
  transition: opacity 0.5s ease;
}
.sfts-vx-gate.is-hidden {
  opacity: 0;
  pointer-events: none;
}
@media (prefers-reduced-motion: reduce) {
  .sfts-vx-gate { display: none; }
}

/* Sceau d'entrée : la marque du client (lettre/mot court, voir seal.letter
   dans component.php) devient elle-même le bouton lecture, jamais un bouton
   générique + logo séparé — reconnu nativement, pas un motif abstrait.
   .sfts-vx-gate-btn est le <button> réel (toute la zone, cible large). */
.sfts-vx-gate-btn {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 12px;
  background: none;
  border: none;
  padding: 8px;
  cursor: pointer;
  transition: transform 0.15s cubic-bezier(0.19, 1, 0.22, 1);
}
.sfts-vx-gate-btn:active { transform: scale(0.96); }
.sfts-vx-seal {
  position: relative;
  width: 76px;
  height: 76px;
  border-radius: 50%;
  background: var(--sfts-vx-bg);
  border: 1.5px solid var(--sfts-vx-accent);
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
  box-shadow: 0 8px 24px -10px rgba(0, 0, 0, 0.55);
  transition: border-color 0.3s ease;
}
.sfts-vx-gate-btn:hover .sfts-vx-seal { border-color: color-mix(in srgb, var(--sfts-vx-accent) 75%, transparent); }
.sfts-vx-seal-mark {
  font-family: Arial, sans-serif;
  font-weight: 700;
  font-size: 34px;
  line-height: 1;
  color: var(--sfts-vx-fg);
  user-select: none;
}
/* Variante SVG du sceau d'entrée (24/09, "mettre le logo à la place [...] pour
   renforcer l'identité visuelle" — Benoit) : le vrai tracé vectoriel (voir
   seal.asset dans component.php), jamais un caractère "M" reconstruit.
   .sfts-vx-seal-mark--svg (span conteneur) hérite déjà `color` de
   .sfts-vx-seal-mark pour le fill="currentColor" — mais un <svg> sans
   width/height propres a sa propre boîte de remplacement, non affectée par
   la taille du span parent : il faut cibler .sfts-vx-seal-mark-svg, la
   classe posée directement SUR la balise <svg> par
   sfts_video_experience_inline_svg() (extra_class), sinon le SVG reste à
   0×0 (bug réel trouvé en testant sur /agencement/, sceau vide). 38px :
   proportionné au cercle de 76px, même poids visuel que la lettre
   (font-size 34px) qu'il remplace. */
.sfts-vx-seal-mark-svg {
  display: block;
  height: 38px;
  width: auto;
}
/* Badge "lecture" en coin bas-droit du sceau — convention universelle de
   badge vidéo/app, jamais superposé à la marque du client. */
.sfts-vx-seal-play {
  position: absolute;
  z-index: 1;
  right: 2px;
  bottom: 2px;
  width: 26px;
  height: 26px;
  border-radius: 50%;
  background: var(--sfts-vx-bg);
  border: 1.5px solid var(--sfts-vx-accent);
  display: flex;
  align-items: center;
  justify-content: center;
  box-shadow: 0 2px 6px -1px rgba(0, 0, 0, 0.6);
}
.sfts-vx-seal-play::before {
  content: "";
  display: block;
  width: 0;
  height: 0;
  border-top: 5px solid transparent;
  border-bottom: 5px solid transparent;
  border-left: 8px solid var(--sfts-vx-accent);
  margin-left: 2px; /* optique : centre le triangle, pas son cadre */
}
.sfts-vx-gate-label {
  font-family: Georgia, "Times New Roman", serif;
  font-style: italic;
  font-size: 1.05rem;
  color: var(--sfts-vx-fg);
}
.sfts-vx-gate-sublabel {
  text-transform: uppercase;
  letter-spacing: 0.14em;
  font-size: 0.68rem;
  font-weight: 600;
  color: color-mix(in srgb, var(--sfts-vx-fg) 65%, transparent);
}

/* Bouton son persistant, révélé par JS seulement après le clic sur la
   porte (attribut HTML "hidden" par défaut). ".sfts-vx-sound[hidden]" est
   nécessaire (bug réel trouvé sur MT Univers, 2026-09-24) : "display:flex"
   d'une classe l'emporte sinon sur la règle par défaut du navigateur pour
   [hidden] (qui n'utilise pas !important) — piège CSS générique, pas
   spécifique à ce client, donc corrigé une fois ici pour tous les clients
   futurs de ce composant. */
.sfts-vx-sound[hidden] { display: none; }
.sfts-vx-sound {
  position: absolute;
  z-index: 3;
  right: 24px;
  bottom: 20px;
  width: 34px;
  height: 34px;
  border-radius: 50%;
  background: var(--sfts-vx-control-bg);
  border: 1px solid var(--sfts-vx-control-fg);
  display: flex;
  align-items: center;
  justify-content: center;
  transition: border-color 0.3s ease, background 0.3s ease;
}
.sfts-vx-sound:hover { border-color: var(--sfts-vx-accent); }
.sfts-vx-sound-icon { width: 14px; height: 14px; position: relative; display: block; }
.sfts-vx-sound-icon::before {
  content: "\266B";
  color: var(--sfts-vx-accent);
  font-size: 15px;
  line-height: 14px;
  position: absolute;
  inset: 0;
  text-align: center;
}
.sfts-vx-sound.is-muted .sfts-vx-sound-icon::before { color: var(--sfts-vx-control-fg); }
.sfts-vx-sound.is-muted .sfts-vx-sound-icon::after {
  content: "";
  position: absolute;
  left: 50%;
  top: 50%;
  width: 140%;
  height: 1px;
  background: color-mix(in srgb, var(--sfts-vx-fg) 75%, transparent);
  transform: translate(-50%, -50%) rotate(-45deg);
}
@media (max-width: 700px) {
  .sfts-vx-sound { right: 16px; bottom: 16px; }
}

/* Bouton plein écran natif — icône dessinée en CSS pur (deux coins qui
   s'écartent), jamais une police d'icônes importée pour un seul glyphe.
   Coin haut-droit : ne se superpose jamais au son (bas-droit) ni à la
   signature de sortie (bas-gauche par défaut). */
.sfts-vx-fullscreen {
  position: absolute;
  z-index: 3;
  right: 16px;
  top: 16px;
  width: 34px;
  height: 34px;
  border-radius: 50%;
  background: var(--sfts-vx-control-bg);
  border: 1px solid var(--sfts-vx-control-fg);
  display: flex;
  align-items: center;
  justify-content: center;
  transition: border-color 0.3s ease;
}
.sfts-vx-fullscreen:hover { border-color: var(--sfts-vx-accent); }
.sfts-vx-fullscreen-icon { position: relative; width: 12px; height: 12px; }
.sfts-vx-fullscreen-icon::before,
.sfts-vx-fullscreen-icon::after {
  content: "";
  position: absolute;
  width: 6px;
  height: 6px;
  border: 1.5px solid var(--sfts-vx-accent);
}
.sfts-vx-fullscreen-icon::before { top: 0; left: 0; border-right: none; border-bottom: none; }
.sfts-vx-fullscreen-icon::after { bottom: 0; right: 0; border-left: none; border-top: none; }
@media (max-width: 700px) {
  .sfts-vx-fullscreen { right: 12px; top: 12px; }
}

/* Légendes ("chapitres") synchronisées à la progression RÉELLE de lecture
   (currentTime / duration, voir script.js), jamais au scroll. Ancrées en
   bas, dans la zone déjà assombrie par le dégradé de lisibilité. */
.sfts-vx-chapters {
  position: absolute;
  inset: 0;
  z-index: 2;
  pointer-events: none;
  display: flex;
  align-items: flex-end;
  padding: 0 24px 72px;
}
.sfts-vx-chapter {
  position: absolute;
  left: 24px;
  right: 24px;
  bottom: 72px;
  max-width: 520px;
  opacity: 0;
  transform: translateY(18px);
  transition: opacity 0.6s ease, transform 0.6s ease;
}
/* 1ère légende visible par défaut, SANS classe "is-visible" : état de
   repli pour prefers-reduced-motion ET pour un navigateur sans JS — un
   seul état par défaut sert les deux cas. La classe "--js" n'est posée
   qu'une fois le script réellement lancé (jamais sous reduced-motion, qui
   s'arrête avant) : CSS ne peut pas détecter "JS actif" autrement. */
.sfts-vx:not(.sfts-vx--js) .sfts-vx-chapter:first-child { opacity: 1; transform: none; }
.sfts-vx-chapter.is-visible { opacity: 1; transform: translateY(0); }
.sfts-vx-chapter-num {
  font-family: Georgia, "Times New Roman", serif;
  font-size: 1.4rem;
  color: var(--sfts-vx-accent);
  line-height: 1;
  margin-bottom: 10px;
}
.sfts-vx-chapter h3 {
  color: var(--sfts-vx-fg);
  font-size: clamp(1.4rem, 3vw, 2rem);
  text-shadow: 0 2px 12px rgba(0, 0, 0, 0.4);
  margin: 0;
}
@media (max-width: 700px) {
  .sfts-vx-chapter { max-width: calc(100% - 48px); bottom: 52px; }
}
@media (prefers-reduced-motion: reduce) {
  .sfts-vx-chapter:not(:first-child) { display: none; }
}
