# Module — Démo virtuelle (captures animées + curseur fantôme)

Alternative au module "aperçu applicatif interactif" (qui recode chaque écran
en HTML/CSS), pensée pour être posée sur **toutes les pages de réalisation
sans reconstruire l'interface** : on part de vraies captures d'écran de
l'application livrée, et le module les met en scène — fondu, léger zoom
(Ken Burns), et un curseur qui se déplace et "clique" tout seul pour simuler
une navigation, façon story Instagram plutôt que lecteur vidéo classique.

Fichier de référence : `demo-virtuelle.html` (démo complète avec des
captures de substitution en SVG — à remplacer par les vraies captures du
projet, voir section 2).

---

## 1. Ce que fait le module

- **4 captures** (ou plus) affichées en fondu-enchaîné, une à la fois, dans
  le même cadre "navigateur" que le module précédent.
- **Zoom lent automatique** (Ken Burns) sur l'image affichée, pour éviter
  l'effet "diapo figée".
- **Curseur fantôme** qui parcourt un chemin défini sur l'image (1 à 3
  points), s'arrête sur un élément, déclenche un effet de clic (halo), puis
  fait apparaître une **infobulle** expliquant la fonctionnalité pointée —
  exactement comme les hotspots du module précédent, mais synchronisés dans
  le temps plutôt que déclenchés au survol.
- **Barre de progression façon "story"** en haut du cadre : une barre par
  écran, qui se remplit pendant la durée d'affichage puis passe à l'écran
  suivant automatiquement.
- **Lecture automatique en boucle** dès que le module entre dans le viewport
  (`IntersectionObserver`), avec un **bouton pause/lecture**.
- **Onglets manuels** sous le cadre : le visiteur peut sauter directement à
  un écran, ce qui met la lecture automatique en pause.
- Se dégrade proprement si `prefers-reduced-motion` est actif : pas de
  curseur animé, pas de lecture automatique, image statique + navigation
  manuelle uniquement.

**Pourquoi c'est plus rapide qu'une vidéo classique :**
- Pas de montage, pas d'export, pas d'hébergement vidéo.
- Le poids reste celui de quelques images compressées (quelques centaines de
  Ko), pas d'un flux vidéo.
- Pas de lecteur natif avec barre de contrôle / plein écran qui casse
  l'intégration au design — tout reste dans l'esthétique du site.
- Le texte des infobulles reste éditable en HTML, indexable, et
  accessible — contrairement à une info incrustée dans une vidéo.

---

## 2. Ce qu'il faut fournir par projet

Pour chaque réalisation à présenter, il suffit de :

1. **3 à 6 captures d'écran** de l'application livrée (au format 1000×620 ou
   proche, mêmes proportions pour toutes), exportées en `.jpg` ou `.webp`
   compressé (viser < 150 Ko par image).
2. **Un titre + une phrase de légende** par écran (ce que fait cette vue).
3. **1 à 2 points à mettre en avant par écran** (ce que le curseur va
   pointer) + le texte de l'infobulle associée.

Aucune reconstruction d'interface n'est nécessaire : on ne fait que rejouer
une navigation sur des images fixes.

---

## 3. Intégration dans une page

### Étape 1 — Copier le bloc HTML

Copier tout le contenu de :

```html
<section class="vdemo" id="demo-virtuelle" ...>
  ...
</section>
```

Renommer l'`id` si plusieurs instances coexistent sur la même page
(ex. `id="demo-virtuelle-helpdesk"`).

### Étape 2 — Copier les styles et le script

Comme pour le module précédent : soit dans un fichier CSS/JS partagé
(recommandé pour toutes les pages de réalisation), soit collés directement
dans la page. Le module réutilise les mêmes tokens de couleur que le reste du
site (`--violet`, `--panel`, `--border`…) — ne pas redéclarer `:root` si la
page les définit déjà.

### Étape 3 — Remplacer les captures

Dans le HTML, remplacer les 4 `<img class="shot" ...>` par les vraies
captures du projet :

```html
<img class="shot" data-active="true" data-screen="dashboard"
     src="assets/mon-projet/screen-dashboard.jpg"
     alt="Tableau de bord de l'application X">
```

- Garder `data-screen="clé"` cohérent avec la config JS (section 4).
- La première image de la liste doit porter `data-active="true"`.
- Toujours renseigner un `alt` descriptif (accessibilité + SEO).

---

## 4. Configurer le déroulé (fichier JS, objet `CONFIG`)

Toute la mise en scène est pilotée par deux constantes en haut du script :

```js
const SEQUENCE = ['dashboard','tickets','sla','reports'];

const CONFIG = {
  dashboard: {
    caption: "Étape en cours : <b>Tableau de bord</b> — ...",
    duration: 6500,                 // ms avant de passer à l'écran suivant
    path: [
      {x:70, y:40},                              // point de passage
      {x:38, y:20, click:true, cue:{             // point final = "clic"
        title:"Vue consolidée",
        text:"Tous les contrats et clients suivis sur un seul écran.",
        side:"right"                              // "left" ou "right" : évite que l'infobulle sorte du cadre
      }}
    ]
  },
  // ... un bloc par écran, même clé que data-screen
};
```

- **`SEQUENCE`** : ordre de lecture automatique et ordre des onglets.
- **`duration`** : temps d'affichage de l'écran (doit couvrir le temps du
  trajet du curseur + la lecture de l'infobulle, ~5,5 à 7 s est un bon
  repère).
- **`path`** : liste de points en **pourcentage** de la zone d'image
  (0–100). Le curseur s'y déplace dans l'ordre. Seul le dernier point doit
  porter `click:true` et un objet `cue` (titre + texte de l'infobulle).
- Pour un écran sans mise en avant particulière, `path` peut ne contenir
  qu'un seul point sans `click`.

### Ajouter/retirer un écran

1. Ajouter/retirer une entrée dans `SEQUENCE`.
2. Ajouter/retirer le bloc correspondant dans `CONFIG`.
3. Ajouter/retirer l'`<img class="shot" data-screen="...">` correspondant.
4. Ajouter/retirer le `<button data-target="...">` correspondant dans
   `#tabs`.

Le nombre de segments de la barre de progression et les onglets se génèrent
automatiquement à partir de `SEQUENCE` — rien d'autre à toucher.

---

## 5. Simuler un défilement vertical (écran plus haut que le cadre)

Pour une capture de page longue (ex. une page de rapports avec plusieurs
blocs), on peut garder le cadre à sa hauteur habituelle et faire "défiler"
l'image à l'intérieur, comme un vrai scroll — plutôt que de la comprimer ou
de la recadrer.

### Marquer l'écran comme "haut"

Dans `CONFIG`, ajouter `tall: true` à l'écran concerné, et donner un
`scrollTo` (0 à 100, en % de la hauteur défilable) à chaque point du
`path` :

```js
reports: {
  tall: true,
  duration: 8500,
  path: [
    {x:50, y:20, scrollTo:0},    // en haut de la page
    {x:55, y:55, scrollTo:48},   // milieu de page
    {x:40, y:78, scrollTo:100, click:true, cue:{
      title:"Export en un clic",
      text:"Les rapports partent directement au format attendu.",
      side:"right"
    }}
  ]
}
```

- `scrollTo:0` = tout en haut de l'image, `scrollTo:100` = tout en bas.
- Le défilement est interpolé automatiquement entre deux points successifs,
  au même rythme que le déplacement du curseur (transition CSS de 1,1s) —
  pas besoin de calculer les valeurs intermédiaires.
- `x`/`y` du curseur restent exprimés en % **du cadre visible** (pas de
  l'image entière) : le curseur reste toujours dans la fenêtre, seule
  l'image défile derrière lui.

### Préparer l'image

- Utiliser une capture **plus haute que large** par rapport aux autres
  écrans (ex. 1000×1400, 1000×2000…), à la largeur exacte des autres
  captures pour rester cohérent.
- Toujours renseigner `width` et `height` sur la balise `<img>` (dimensions
  réelles du fichier) — le module s'en sert pour calculer la distance de
  défilement disponible :

```html
<img class="shot is-tall" data-screen="reports"
     src="assets/mon-projet/screen-reports-tall.jpg"
     alt="Page de rapports, du résumé jusqu'au bloc d'export"
     width="1000" height="1400">
```

- La classe `is-tall` désactive le zoom Ken Burns (incompatible avec un
  défilement) et active le mode "image qui glisse".

### Ce que ça change visuellement

- Un repère de défilement (petite piste verticale avec un curseur) apparaît
  sur le bord droit du cadre pendant la durée de l'écran, pour renforcer la
  sensation de scroll — il se masque automatiquement sur les écrans
  classiques (`tall` absent ou `false`).
- Le curseur fantôme et l'infobulle fonctionnent exactement comme sur un
  écran normal, ils suivent juste une image qui bouge derrière eux plutôt
  qu'une image fixe.

### Limites à connaître

- Un seul axe de défilement (vertical). Pour un contenu très large
  (tableau qui déborde horizontalement), il faudrait dupliquer la même
  logique sur `translateX` — non inclus par défaut.
- Le calcul de la distance de défilement se fait une fois l'image chargée
  (`naturalWidth`/`naturalHeight`) : vérifier que `width`/`height` sur la
  balise `<img>` correspondent bien aux dimensions réelles du fichier,
  sinon le calcul sera faux.

---

## 6. Accessibilité & performance

- Respecte `prefers-reduced-motion` : pas d'animation de curseur, pas de
  lecture automatique — l'utilisateur garde une navigation manuelle complète
  via les onglets.
- Bouton pause/lecture toujours disponible et étiqueté (`aria-label`
  dynamique).
- Chaque capture a un texte alternatif descriptif.
- Poids : uniquement des images (pas de flux vidéo à charger/décoder), donc
  compatible avec une page contenant plusieurs démos.
- Recommandation : livrer les captures en `.webp`, dimensions identiques
  entre elles pour éviter tout saut de mise en page pendant le fondu.

---

## 7. Plusieurs instances sur une même page

Comme pour le module précédent, le script cible actuellement le premier jeu
d'éléments trouvé par ID (`#vstage`, `#deviceBody`, etc.). Pour poser
plusieurs démos virtuelles sur une même page (rare, mais possible sur une
page comparant deux projets) :

1. Donner un suffixe unique à chaque `id` du bloc HTML et de son
   `<script>` associé.
2. Dupliquer l'IIFE du script pour chaque instance en adaptant les
   sélecteurs, ou refactoriser en fonction `initDemo(containerEl, config)`
   appelée une fois par bloc `[data-vdemo]` trouvé sur la page.

Pour l'usage courant (une démo par page de réalisation), aucune adaptation
n'est nécessaire.

---

## 8. Choisir entre les deux modules

| | Aperçu interactif (CSS recodé) | Démo virtuelle (captures + curseur) |
|---|---|---|
| Temps de préparation par projet | Élevé (recoder chaque écran) | Faible (captures + quelques réglages) |
| Fidélité visuelle | Approximative (interprétation) | Exacte (vraie interface) |
| Interaction du visiteur | Libre, clic sur n'importe quel écran | Guidée, façon visite commentée |
| Bon pour | Un projet phare, mis en avant longuement | Toutes les pages de réalisation, en volume |

Les deux partagent le même habillage visuel (cadre navigateur, palette,
typographie) : ils peuvent être utilisés côte à côte sans rupture de style
selon l'importance donnée à chaque réalisation.
