# Maquettes — convention Excalidraw

Décision Enguerran 07/08/2026 : les wireframes/maquettes de structure sont des
fichiers **`.excalidraw` versionnés ici** — trace conservée, partage simple,
co-édition possible entre Enguerran, Claude et les devs/designers.

## Utilisation

- **Ouvrir/éditer** : [excalidraw.com](https://excalidraw.com) → menu ☰ → *Ouvrir* →
  choisir le fichier ; ou l'extension VS Code « Excalidraw ». Enregistrer → commit.
- **Convention** : un fichier par écran (`page-cours-apprenant.excalidraw`,
  `mes-cours.excalidraw`, …). Une évolution de maquette = un commit (l'historique
  git EST l'historique des versions de maquette).
- **Cycle** : maquette proposée (par Claude ou un humain) → **validation
  d'Enguerran** notée dans l'issue concernée (lien vers le fichier au commit
  près) → implémentation → recette visuelle sur l'écran réel.
- La maquette fige la **structure et les états** ; la référence de style fin
  (couleurs exactes, typographies) reste **l'écran réel** en local/staging.

## ⚠️ Lire la maquette AVANT d'implémenter — pas au moment de la mettre à jour

**Une maquette porte des décisions qui ne figurent nulle part ailleurs.** Ses blocs
« DÉCIDÉ LE … / À NOTER » sont le cœur du fichier ; les rectangles ne sont que la mise en
page. Un écran développé sans les avoir lus part d'un CA incomplet.

| Quand | Quoi |
|---|---|
| **Au début d'un lot** | lire cet index — un seul fichier — pour savoir quels écrans ont une maquette, et laquelle est validée |
| **Avant d'implémenter** une issue qui touche un écran maquetté | ouvrir sa maquette et la lire **en entier, annotations comprises**. Pas toutes les maquettes du dépôt : *intégralement* celles des écrans concernés |
| **Toujours** | le CA d'une issue **n'est pas exhaustif** — suivre les liens : maquette, issues liées, cahier de recette |

### Le cas qui a fait écrire cette section (09/08/2026)

Le cockpit (EA-051, #61) a été implémenté en lisant le CA de l'issue, les décisions de
l'atelier P0 et le cahier de recette — **mais pas la maquette**. En la reprenant pour la
passer en v3, une annotation portait déjà la décision **#182**, que le code violait :
l'horizon de 24 mois ne borne **que la mesure d'activité**, jamais le dossier de formation
(résultats de quiz, achèvements, certificats), qui est une **preuve de qualification**.
Le borner aurait détruit le dossier d'un collaborateur présent depuis dix ans.

#182 existait pourtant comme issue. Mais le CA de #61 ne la citait pas : **la maquette
était le seul endroit où le lien était visible.** Le défaut a été corrigé avant que
l'écran ne soit construit (PR #214) — c'est exactement ce que le cycle
« maquette → validation → implémentation » sert à obtenir.

## Index

| Fichier | Écran | Statut |
|---|---|---|
| `page-cours-apprenant.excalidraw` | Page cours apprenant (EA-029/030/032) | **Validée 07/08** (v2 : visionneuse fixe + onglets Sommaire/Ressources/Chat + À propos dessous ; mobile empilé, plein écran en paysage) |
| `l4-mes-collaborateurs.excalidraw` | Mes collaborateurs (EA-049) — L4 | **v2 — arbitrages du 09/08 intégrés** |
| `l4-cockpit-apprenant-formation.excalidraw` | Cockpit apprenant × formation (EA-051) — L4 | **VALIDÉE — écran livré et recetté** (11/08, nom de l'apprenant #55 inclus) |
| `l4-dashboard-pilotage.excalidraw` | Dashboard de pilotage (EA-055) — L4 | **VALIDÉE — écran livré et recetté** (11/08, jetons du site appliqués) |

## Maquettes L4 — ce qu'elles fixent, et ce qu'elles demandent

Les trois écrans de pilotage se posent sur la **DataTable livrée en L3** : recherche, tris,
filtres par colonne, choix des colonnes, export. Ils n'ont rien à redévelopper de ce côté —
seulement à câbler. C'est la raison pour laquelle L3 passait avant L4.

### Arbitrages rendus le 09/08 (Enguerran)

| Écran | Décision | Conséquence technique |
|---|---|---|
| Mes collaborateurs | **E-mail affiché en clair**, masquable par chacun via le menu Colonnes | ⚠️ **Révise le CA d'EA-049 (#59)**, qui demandait l'inverse — l'issue est à amender |
| Mes collaborateurs | Compteurs de formations **éclatés en 4 colonnes triables** | 4 clés triables à déclarer dans le `ListSchema` back |
| Mes collaborateurs | Badge d'usage OK **si seuils et fenêtre paramétrables par l'admin** | Les seuils F11 deviennent des réglages, plus des constantes → écran Paramètres |
| Cockpit | Affichage « données disponibles depuis [date] » conservé | — |
| Cockpit | Timeline **limitée à 60 jours** à l'écran, **historique complet téléchargeable en Excel** | Nouveau bouton d'export ; réutilise le socle EA-022 (périmètre appliqué côté serveur) ; ⚠️ à réconcilier avec la rétention de 24 mois des événements bruts (F11) |
| Cockpit | KPI conformes aux définitions figées (spec Lot 2.5) | — |

### Arbitrages du 09/08 — dashboard (EA-055)

| Décision | Conséquence |
|---|---|
| **Complétion = terminés / DÉMARRÉS** | Le ratio sur les inscrits devient le **« taux de démarrage »** (démarrés / inscrits), plus actionnable qu'un inscrits→terminés qui mélangeait deux ruptures |
| **Calcul par inscription** (apprenant × formation), jamais sur des totaux de période | ⚠️ « ratio » + « période » produit des valeurs **> 100 %** dès qu'un apprenant démarre avant la période et termine pendant. Règle retenue : **cohorte** — on suit les inscriptions démarrées dans la période. **À confirmer avant implémentation** |
| **Tout se recalcule sur les filtres** actifs et le périmètre du rôle | Le dashboard ne redéfinit pas le périmètre, il reprend celui des listes (F11) |
| **Tutos : bascule dans l'écran**, pas d'onglet séparé ; indicateurs clés tutos dans le bloc général | Un onglet se visite peu. Contenu détaillé = EA-085, hors V1 : réserver la place |
| **Deux funnels, deux unités** | ① apprenants (personnes) en premier, ② inscriptions (couples) en second |

**Sur les deux funnels** — leur divergence n'est pas un défaut, c'est de l'arithmétique : ①
compte des **personnes**, ② des **couples apprenant × formation**. La somme des lignes du tableau
par module donne toujours ②, jamais ①. D'où la règle : **toujours afficher l'unité**
(« 148 apprenants » / « 312 inscriptions »), jamais deux nombres nus côte à côte.

S'y ajoute **« pas à jour »** (≥ 1 formation non terminée) : ce n'est pas une étape de funnel mais
la **liste de relance** — l'indicateur le plus actionnable de l'écran pour un manager.

## Règle transverse — les colonnes appartiennent à l'utilisateur

**Décision 09/08 : sur TOUTES les listes de TOUTES les vues**, l'utilisateur doit pouvoir
afficher, masquer et **réordonner les colonnes par glisser-déposer**.

Le mécanisme est déjà livré (EA-021, L3) : `useColumnPreferences` + `ColumnPreferencesMenu`,
persistés par utilisateur **et par écran** côté serveur. Généraliser ne demande donc aucun
développement de composant — mais chaque écran repris coûte :

1. sa migration vers `DataTable` (le gros du travail quand la table est faite main) ;
2. un identifiant d'écran (`admin.users`, `manager.collaborateurs`, …) ;
3. **son `ListSchema` côté back** — c'est là qu'est le vrai coût : déclarer ce qui est cherchable,
   triable, filtrable et exportable, sinon les colonnes bougent mais ne trient rien.

Inventaire et suivi : issue dédiée dans EFEKTIVACADEMIE-BACK.

Un point commun aux trois, à ne pas perdre : l'historique de mesure **démarre à la mise en
production d'EA-035**. Avant, le front n'appelait aucune route de tracking. D'où la mention
« Données disponibles depuis [date] » dans le cockpit : sans elle, un manager lit « 0 connexion »
comme un désengagement alors que c'est un trou de mesure.

## v3 des maquettes L4 (dashboard et cockpit) — ce qui a changé, et pourquoi

Les volets **serveur** de #65 et #61 sont livrés ; leurs écrans restent à faire. Les
maquettes sont donc reprises pour décrire **ce que l'API sert réellement**, avant de
construire — c'est l'ordre que la convention impose, et il vient de prouver son utilité.

### Le défaut que la reprise a révélé

En relisant la maquette v2 du cockpit pour la mettre à jour, une annotation disait déjà
ce que l'implémentation ne faisait pas : **l'horizon de 24 mois ne doit borner que la
mesure d'activité**, jamais le dossier de formation (décision #182). Le code appliquait
le plafond à tout, y compris aux résultats de quiz et aux achèvements — c'est-à-dire à
une **preuve de qualification**, que borner par l'ancienneté détruirait pour un
collaborateur fidèle.

Corrigé avant que l'écran ne soit construit. C'est exactement ce que le cycle
« maquette → validation → implémentation » sert à éviter : j'avais implémenté #61 sans
relire la maquette.

### Deltas v2 → v3

| Écran | Ajout |
|---|---|
| **Cockpit** | La timeline distingue **deux matières** : activité plafonnée à 24 mois, dossier de formation non borné. Le bouton d'export ne promet plus « tout l'historique » sans nuance, et l'écran dit ce que chacune contient. Horizon **administrable** (Paramètres), affiché quand il s'applique. |
| **Dashboard** | Mention « **données disponibles depuis [date]** », qui manquait alors que le cockpit l'avait — sans elle, un « 0 démarré » se lit comme un désengagement au lieu d'un trou de mesure. Bloc **comptes exclus des statistiques** (F11) : 4 comptes de test actifs en production comptent aujourd'hui dans les indicateurs. La règle **cohorte**, qui était « à confirmer avant implémentation », est confirmée et livrée. |

### Ce que ces deux maquettes attendent

Une **validation d'Enguerran notée dans les issues #65 et #61**, avec le lien vers le
fichier au commit près — puis l'implémentation des deux écrans.

## Maquettes des écrans manquants de L4 (10/08)

Trois écrans dont le back était livré et l'interface absente. Ajoutées avant tout code,
conformément à la règle : une maquette validée, puis l'implémentation.

| Fichier | Issue | État |
|---|---|---|
| `l4-navigation-pilotage-options` | FRONT#70/#75 | **DÉCISION RENDUE — option B** (11/08), livrée jusqu'au volet 2 de #75 |
| `l4-onboarding-premiere-connexion` | #55 | **VALIDÉE PAR LA RECETTE** — onboarding complété en réel par Enguerran (11/08) |
| `l4-referentiels-societes-profils` | #51 | **VALIDÉE PAR LA RECETTE** — création d'entrée jouée en réel (11/08) |
| `l4-apprenants-sans-manager` | #160 | **VALIDÉE PAR LA RECETTE** — réaffectation réelle jouée (11/08) |

## Étape ajoutée au process (règle du 11/08) — la maquette HTML stylée

Constat qui a fixé la règle : les listes de pilotage, **conformes aux wireframes validés**,
sont sorties avec des filtres tronqués (« Tous » affiché « Tc »), des en-têtes sur deux
lignes et une densité illisible (FRONT#76). Le wireframe valide la **structure et les
décisions** ; il ne peut pas montrer le rendu — densité réelle, vraies polices, vraies
largeurs, débordements.

Le parcours complet pour **toute nouvelle page** :

1. **Wireframe** (`.excalidraw`, ce dossier) — structure, décisions, états d'erreur.
   → validation d'Enguerran, tracée dans l'issue.
2. **Maquette HTML stylée** (`html/` dans ce dossier) — page statique, vraies polices,
   vraies couleurs, vrais espacements, données factices réalistes (les libellés les plus
   longs, pas les plus courts). Ouvrable dans un navigateur, sans build.
   → validation d'Enguerran, tracée dans l'issue.
3. **Développement**, conforme aux deux.
4. Après livraison, **l'écran réel devient la référence de style** (règle existante) ; la
   maquette HTML n'est pas maintenue — c'est un jeté de validation, pas un second front.

Le point 4 est ce qui empêche la dérive : deux artefacts stylés maintenus en parallèle
divergeraient. On valide avec, on jette après.

## Toute liste de sélection qui peut s'allonger est cherchable (règle du 13/08)

Un sélecteur dont les options viennent d'un **référentiel** — catégories,
sous-catégories, balises, parcours, sociétés, profils métier, utilisateurs,
types de supports — porte une **barre de recherche**, en choix simple comme en
choix multiple.

Le critère est la **nature** de la liste, pas sa longueur du jour : un
référentiel s'allonge avec les données du client, il est donc cherchable dès
la première maquette, même s'il n'a que six entrées en recette.

Un filtre qui énumère des **valeurs fixes** (statut, type, tranche de durée)
reste une liste simple : l'alourdir n'aide personne.

Côté implémentation, la plateforme n'a que **deux** sélecteurs et n'en
accueillera pas un troisième — un pour le choix simple, un pour le choix
multiple, habillés par un module de styles commun. Dans une liste, un filtre
de référentiel se déclare cherchable, il ne se réinvente pas.

**Origine (recette du 12/08, BACK#359)** : un écran livré d'après une maquette
où la recherche n'apparaissait pas l'avait perdue, alors que tous les autres
écrans l'avaient. C'est le cas qui a fondé la règle ci-dessous.

## Une maquette AJOUTE, elle ne retire jamais

Une capacité présente sur les écrans existants et **absente d'une maquette est
un oubli du maquettiste**, jamais une décision de suppression. Le
développement la conserve et le signale.

Avant d'implémenter un écran d'après une maquette : **inventorier ce que
l'écran existant sait faire** (recherche dans les listes, filtres, tris,
exports, raccourcis) et vérifier que chaque capacité survit. En cas de doute
sur un élément manquant, **demander l'arbitrage plutôt que de trancher**.

## Wireframes en attente de validation

| Fichier | Couvre | État |
|---|---|---|
| `l46-apprentissage-laterale.excalidraw` | Apprentissage — navigation LATÉRALE au lieu des onglets horizontaux (retour du 12/08) | **À VALIDER** — revient sur la règle « le plein écran est réservé à l'apprentissage » ; décisions A1 (nouvelle règle), A2 (6 écrans touchés), A3 (sous-onglets de Mes formations) |
| `l46-ea054-mes-apprenants.excalidraw` | EA-054 (#64) — liste « Mes apprenants » du formateur, bloc A du lot 4.6 | **WIREFRAME VALIDÉ 12/08** — D1 à D4 tranchées dans l'issue #64. Maquette HTML produite : `html/l46-ea054-mes-apprenants.html`. |

## Maquettes HTML stylées (process du 11/08)

| Fichier | Couvre | État |
|---|---|---|
| `html/pilotage-liste-collaborateurs.html` | FRONT#76 + barre latérale option B | **VALIDÉE (10/08)** — écran livré et recetté |
| `html/pilotage-invitations.html` | FRONT#70 puis #96 (v3 : Inviter · Suivi) | **VALIDÉE (11/08)** — écran livré, en recette |
| `html/pilotage-inscriptions.html` | FRONT#96 (Inscrire · Demandes) | **VALIDÉE (11/08)** — écran livré, en recette |
| `html/apprentissage-mes-formations.html` | FRONT#77 — option 2 + gamification en en-tête (décisions 11/08) | **Validée 11/08** |
| `html/apprentissage-catalogue-interne.html` | FRONT#83 — rails type YouTube par sous-catégorie | **Validée 11/08** |
| `html/admin-types-de-supports.html` | BACK#164 — liste + gardes API + modale « Nouveau type » | **Validée 11/08** (D1, D2 tranchées) |
| `html/phase3-formateur-mes-cours.html` | FRONT#78 + BACK#180 — liste de gestion (DataTable + 5 règles) | **VALIDÉE 11/08** (v2 : latérale option B **à gauche**, confirmé ; restent D1-p3 et D2-p3, cf. issue) |
| `html/phase3-geste-commun.html` | FRONT#78 — geste commun des écrans de gestion sans liste (latérale option B du rôle) | **VALIDÉE 11/08** (v2 : le plein écran est réservé à l'apprentissage) |
| `html/l46-admin-coquille-cours.html` | Lot 4.6 bloc B — coquille admin (EA-057) + écran Cours UNIFIÉ v2 : Cours/Tutos/Parcours en une liste, colonne + filtre Type, « + Créer » avec choix (EA-058 v2/059/060 + EA-062) | **VALIDÉE 12/08** (B-1 actée : Points et Chat sous Paramètres ; Catégories/Sous-catégories/Balises/Types de supports sous Cours) |
| `html/l46-studio-tuto.html` | Lot 4.6 bloc B — création d'un tuto allégée (#317, EA-084a) : une vidéo courte, rattachement processus | **VALIDÉE 12/08** (T-1 : L4.6 = écran + modèle unitaire seulement ; T-2 : liste unifiée, pas d'écran séparé) — **corrigée le 12/08 (#349)** : la vidéo est un LIEN Vimeo/YouTube, pas un dépôt de fichier (la plateforme n'héberge aucune vidéo : 192 leçons sur 282 en lien, 0 en fichier) |
| `html/l46-editeur-parcours.html` | Lot 4.6 bloc B — éditeur de parcours (#318) : composition cours+tutos + timeline de déclenchement | **VALIDÉE 12/08** (P-1 : composition = cours + tutos, PAS d'imbrication de parcours — précision Enguerran ; P-2 : 4 modes de déclenchement ; P-3 : visible-verrouillée par défaut, réglable par parcours) |
| `html/l46-studio-creation.html` | Lot 4.6 bloc B — studio de création refondu (EA-063) : accordéons, DnD direct, libellés au clic, ajout par type du référentiel #164 | **VALIDÉE 12/08** (B-2 actée : l'aperçu apprenant = la vraie page cours en lecture — le back laisse déjà passer admin/formateur propriétaire sur un brouillon, PR #324) — **remplacée pour le style par `l46-studio-creation-v2.html`** |
| `html/l46-studio-creation-v2.html` | Lot 4.6 bloc B — **même écran, nouvelle identité visuelle** (EA-063, #76) : tokens du DA, latérale repliable, barre générale réelle | **À VALIDER** — porte les décisions déjà actées (accordéons sections **et** leçons, DnD direct, libellés au clic, types servis par le référentiel #164 avec barre de recherche, confirmations publication/suppression, B-2 aperçu = vraie page cours). Points ouverts : **S-1** état section vs état cours, **S-2** retour arrière/annulation, **S-3** durée affichée, + arbitrage transverse « 13 px » |
| `html/l46-ea054-mes-apprenants.html` | Lot 4.6 bloc A — « Mes apprenants » du formateur (EA-054, #64), nouvelle identité visuelle | **À VALIDER** — applique **D1 à D4 tranchées le 12/08** : une ligne = apprenant × formation ; 6 colonnes par défaut + ajout par « Colonnes » ; action de ligne « écrire à cet apprenant » **en plus** de Discussions ; « En retard » sur le délai paramétrable de **#183** (absent → pas de statut « En retard »). Exporter présent (règle transverse). Points ouverts : **A-1** homonymes, **A-2** couleur d'alerte, **A-3** retard sur formation démarrée, **A-4** sélection multiple, **A-5** action « Écrire » en icône seule |

Les 4 règles de tableau fixées par la maquette liste : police jamais sous 13 px ; en-tête
sur une ligne (libellé court + infobulle) ; filtre jamais tronqué (largeur mini = plus
longue option) ; cellule longue ellipsée, ne pousse jamais les colonnes numériques.
**Règle 5 — la maquette reproduit la barre générale RÉELLE, elle ne la redessine pas.**
L'avatar est une **photo** (l'image par défaut `public/images/user.png` est embarquée en
data-URI), à sa place de droite, et le menu s'ouvre **sous** lui, aligné à droite. Des
initiales à la place de la photo, ou le menu détaché en bas de page, ne montrent pas
l'écran que l'utilisateur aura sous les yeux.
La première version amputait le bloc profil (avatar rond 32 px + menu nom/e-mail/Profil/
Changer le mot de passe/Déconnexion), la cloche de notifications et la recherche : une
maquette qui ampute l'existant ne permet pas de valider l'écran. La barre est désormais
calquée sur `NavbarPanel.jsx`.

## Nouvelle identité visuelle (12/08) — d'où viennent les jetons

Les maquettes livrées par le directeur artistique vivent dans
`docs/design/refonte-2026-08/html/MAQUETTES FORMIND/`. Elles portent un système
de jetons complet dans `:root` : couleurs (`--bg`, `--surface`, `--ink*`,
`--accent*`, `--type-cours/tuto/parcours-*`, `--ok*`), échelle d'espacements
`--s1…--s9`, échelle typographique `--t-h1…--t-xs`, rayons `--r-*`, ombres
`--shadow-*`, et dimensions de layout (`--header-h`, `--sidebar-w`,
`--sidebar-rail`, `--content-max`) avec `body.nav-collapsed` pour la latérale
repliable.

**Règle : on reprend ces jetons tels quels, on n'en réinvente aucun.** Ce que
les maquettes du DA ne portent pas et qui reste imposé par le produit :

1. **Le logo est celui du staging**, embarqué en data-URI, pas la marque
   redessinée du DA.
2. **La barre générale est reproduite** (règle 5) : recherche, bascule
   Pilotage⇄Apprentissage, cloche + compteur, bloc profil avatar photo. Seul le
   style passe à la nouvelle identité ; rien n'est amputé.
3. **La barre de recherche dans les listes de sélection est conservée** partout
   où la liste peut être longue (formations, apprenants, types de supports).
   Elle existe sur le staging, elle est absente des maquettes du DA : c'est un
   **oubli**, jamais une suppression.
4. **Arbitrage en attente** : la règle « police jamais sous 13 px » et les
   jetons du DA (11 px pour les en-têtes de tableau, 12 px pour les pastilles)
   se contredisent. Choix appliqué dans les deux maquettes du 12/08 : jetons du
   DA repris tels quels, mais **aucune donnée écrite sous 13 px** — les
   pastilles de statut passent à `--t-sm`. Les 11 px restent réservés aux
   étiquettes d'en-tête en majuscules espacées.
5. **La palette du DA n'a pas de paire « alerte »** : le statut « En retard »
   réutilise la paire ambrée `--type-parcours-*`. À trancher — paire dédiée
   fournie par le DA, ou réaffectation actée.

**Rendu : Chrome headless à 1280 px, jamais `qlmanage`.**
```bash
"/Applications/Google Chrome.app/Contents/MacOS/Google Chrome" --headless --disable-gpu \
  --hide-scrollbars --force-device-scale-factor=1 --window-size=1280,800 \
  --screenshot=/tmp/maquette.png "file://$PWD/docs/design/maquettes/html/<fichier>.html"
```
`qlmanage` rend dans une fenêtre virtuelle étroite puis met à l'échelle : il a affiché un
tableau débordant là où il tenait, et masqué un bloc qui s'affichait. Une maquette jugée
sur un rendu faux ne vaut rien. Les fichiers fixent `width:1280px` pour que le cadre de
jugement soit le même partout.

Deux règles ci-dessus ont été découvertes en construisant les maquettes : la 4 (le premier
rendu, avec un e-mail réaliste, éjectait les six colonnes numériques) et la 3 dans sa forme
actuelle (les filtres placés en deuxième ligne d'en-tête élargissaient trois colonnes et
poussaient « Profil » hors de l'écran — ils vivent maintenant dans la barre d'outils).
L'étape a payé avant même d'exister officiellement.
