**Scope** : frontend-only sprint, 5 livrables coordonnés. Pas de backend, pas de schéma, pas de nouvelle API. Pas de modif tokens couleurs/spacing/font dans tailwind.config.
Analyse Spectrum (`/home/user/Documents/01_Projects/spectrum`) faite via workflow. Résultat : Spectrum n'a **pas de design system** (Tailwind raw + violet ramp + recipes inlinées 30× partout). Mimic est structurellement meilleur. On ne porte pas la philosophie Spectrum — on extrait **5 patterns isolés** qui survivent au brutalisme Mimic.
- **Q1 → B** : Tabs primitive **+ consumer EngagementDetailPage** (3 tabs : Schedule / Description / Simulations au lieu du stack vertical actuel).
- **Q2 → B** : **Compact density GLOBAL** — toutes les tables passent à 32px row, pas opt-in. User accepte le tradeoff WCAG (touch target) sur Engagements list.
-`frontend/src/styles/index.css` — nouvelle recipe (mais appliquée comme default, pas opt-in cette sprint per user decision Q2-B) :
- Soit : modifier la recipe `.card-product table` existante pour passer à 32px row, `caption-md` text, `py-xxs px-xs` cells, divider `border-hairline`.
- Soit : ajouter `.table-compact` puis l'appliquer à TOUTES les list pages (Engagements, Templates, Users, etc.).
- **Choix builder** : pick the cleaner path. Préférer modifier le default si toutes les tables doivent suivre, sinon `.table-compact` + apply partout.
- Apply sur :
-`frontend/src/pages/EngagementsListPage.tsx`
-`frontend/src/pages/TemplatesListPage.tsx`
-`frontend/src/pages/UsersAdminPage.tsx`
-`frontend/src/components/SimulationList.tsx` (utilisé dans EngagementDetailPage)
- Toute autre table dans le code (grep `<table` dans `frontend/src/`)
-`DESIGN.md` — `### Data Tables` section : modifier la ligne "Row min-height 44px" → "Row min-height 32px (compact density, all surfaces)". Documenter le tradeoff WCAG (touch target dérogé en faveur de la densité opérateur — c'est un BAS tool, pas un site grand public).
**ATTENTION** : WCAG SC 2.5.5 (Target Size: Minimum) recommande 44×44. Tu déroges. Garder les boutons d'action des rows ≥ 24px d'icône avec padding pour préserver le hit area minimal. Tester en clavier + lecteur d'écran nicht regressé.
- Underline tabs : pas de transition, pas de bg fill, border-b instantané
- Count pill : `rounded-pill` est dans l'exception DESIGN.md, OK
- AlertBanner : `border-l-4` semantic OK, pas de shadow
- BackLink : caption + icon align baseline
- 32px tables : densité lisible ? Hit area boutons d'action OK ?
3.**code-reviewer** : sprint diff. Focus :
- Aucune transition / shadow / rounded leak
- useHashTab : `hashchange` listener cleanup dans useEffect return
- Tabs : prop API stable, fallback default ID si hash invalide
- AlertBanner : ARIA `role="alert"` ou `role="status"` selon variant
- BackLink : `to` est `string` ou objet React Router ? Choisir un seul
4.**spec-reviewer** : `SPEC.md` n'a pas vocation à mentionner ces primitives, **skip ce sprint** sauf si tu détectes une feature côté backend qui aurait dérivé.
## Contraintes tests
-`vitest --run` baseline **212/212** doit tenir.
- **Ajouter 4 specs** (1 par new component) :
-`Tabs.test.tsx` — active state, hash sync, count pill render
-`AlertBanner.test.tsx` — 4 variants rendent les bonnes classes
- Brutalism unit assertions : pour chaque new component, un test qui vérifie `expect(el).not.toHaveClass('rounded-md')` (sauf pill counter) + `.not.toHaveClass(/transition-/)` + `.not.toHaveClass(/shadow-/)`.