# AUDIT.md — Diagnostic CSS/HTML Birdwants

Document de référence issu d'un audit en lecture seule du CSS et du HTML du
projet, réalisé avant tout refactoring assisté. **Ce n'est pas un plan
d'implémentation** — voir la section "PLAN DE SESSIONS" pour l'ordre de
traitement prévu, sans détail d'exécution.

---

## 1. Inventaire des classes CSS

### Composants partagés (nav-header, footer, btn, keyboard-hints) — présents sur les 7 pages

**Nav** (`components/_nav.css`) : `.nav-header`, `.nav-header__inner`, `.nav-header__brand`, `.nav-header__burger`, `.nav-header__burger-bar`, `.nav-header__list`, `.nav-header__link`, `.nav-header__link-active`, `.nav-header__nav`, `.is-open` (piloté par Alpine, vivant).

- **Classe utilisée en HTML sans règle CSS** : `.nav-header__item` (ex. index.html:30, répété sur les 7 pages) — aucune règle `.nav-header__item` dans `_nav.css`. Risque **faible** (le `<li>` hérite du flex du parent `.nav-header__list`), mais artefact BEM sans fonction.
- **Réutilisation cross-bloc** : `.nav-header__brand` est réemployé dans le footer (ex. index.html:260) pour le lien "BirdWants", alors qu'il est structurellement dans `.footer__brand`. Un élément d'un bloc (`nav-header`) utilisé dans un autre bloc (`footer`) — voir section 2 (BEM).

**Bouton** (`components/_button.css`) : `.btn`, `.btn--secondary`, `.btn--cta`, `.btn-icon` — utilisées.
- **Classes mortes confirmées** (déclarées, jamais présentes dans aucun des 7 HTML) : `.btn--sm` (_button.css:43), `.btn--lg` (_button.css:49), `.btn-letter` (_button.css:106), `.letter--dark` (_button.css:112), `.letter--light` (_button.css:118), et tout le variant `.btn--border-draw` avec son appareillage de pseudo-éléments (_button.css:138-229). Risque **moyen** : ~90 lignes de CSS (dont une animation entière documentée) qui ne correspond à rien de livré.

**Footer** (`components/_footer.css`) : toutes les classes déclarées sont utilisées, sauf :
- `.footer__nav` (classe posée sur le `<nav>` en HTML, ex. index.html:267) — aucune règle CSS ne cible `.footer__nav` seul (seulement `.footer__nav-list` et `.footer__nav-link` existent). Risque **faible**.

**Keyboard-hints** : toutes les classes utilisées, sauf `.is-hidden` — jamais présente statiquement dans le HTML analysé.
- **Question ouverte** : est-elle appliquée dynamiquement par `assets/js/theme.js` (hors périmètre CSS/HTML de cette analyse) ? Si non, c'est une classe morte. *(non tranchée)*

### Page d'accueil (`index.html` + `style.css`)

Classes : `.hero`, `.hero__inner`, `.hero__content-wrapper`, `.hero__content`, `.hero__title`, `.hero__lead`, `.hero__actions`, `.hero__features`, `.feature`, `.feature__title`, `.feature__list`, `.feature__item`, `.service*` (9 classes), `.about*` (6 classes), `.cta`, `.cta__inner`, `.cta__statement`. Toutes utilisées dans `index.html`, aucune classe morte détectée dans ce bloc.

- **Quasi-doublon flagrant** : `.about__title` utilise `font-family: var(--font-mono)` (style.css:271-274), alors que **tous les autres titres de bloc du site** (`.service__title`, `.ethique__title`, `.dpia__title`, `.manifeste__title`) utilisent `font-family: var(--font-brand)` avec la même recette (`fw-regular` + `fs-xl`).
- **Question ouverte** : `.about__title` est-il un oubli de migration vers `font-brand`, ou un choix volontaire pour distinguer le nom propre du DPO des titres de section ? Risque **faible** visuellement, mais incohérence de système. *(non tranchée)*

### Page AIPD (`aipd.html` + `pages/_aipd.css`)

Toutes les classes `.dpia*` sont utilisées et stylées, y compris `.dpia__mobile-notice`. Aucune classe morte.

- **Valeur suspecte** : `.dpia__table-head th` utilise `background-color: lightpink;` (_aipd.css:139) — une couleur nommée CSS générique, hors de tout le système de tokens (`--color-*`), qui ressemble à une valeur de debug/placeholder oubliée. Risque **élevé** : couleur non intentionnelle visible sur une page publique.

### Pages Confidentialité / Éthique / Mentions légales — bloc `.ethique` partagé

Ces **trois pages distinctes** (`confidentialite.html`, `ethique.html`, `mentions-legales.html`) réutilisent toutes le même bloc CSS `.ethique` / `.ethique__section` / `.ethique__title` / `.ethique__list-item`, etc. (`pages/_ethique.css`).

> Voir section **DÉCISIONS ACTÉES** : ce point a été tranché par l'utilisateur (renommage prévu en `.legal-page`), il n'est donc plus une question ouverte.

- **Classe HTML sans CSS** (risque **élevé**) : `.ethique__notice` et `.ethique__notice-text`, utilisées dans mentions-legales.html:111-118 pour l'encart "Note technique" sur l'obfuscation d'e-mail — **aucune règle CSS ne les cible**, confirmé par grep. Ce bloc s'affiche donc en texte brut, sans le traitement visuel (bordure/fond) qu'ont tous les autres encarts du site.
- `.contact__encart--legal` et `.contact__subtitle` ont été supprimées intégralement (code mort + commentaire, CSS et HTML) par le commit 820b707 — aucune trace résiduelle dans le repo.

### Page Contact (`contact.html` + `pages/_contact.css`)

- **Classe bloc jamais appliquée** (risque **moyen**) : `.contact__encart` (le bloc de base avec `padding` + `border`, _contact.css:52-55) n'apparaît **jamais** dans `contact.html` — seul son élément enfant `.contact__encart-text` est posé (3 occurrences, ex. contact.html:77), toujours dans un `<div role="note">` nu sans la classe parente. Résultat : les encarts d'avertissement (sécurité e-mail, conseil OpSec, RGPD) n'ont ni bordure ni fond — juste du texte flottant. Par conséquent `.contact__encart--opsec` et `.contact__encart--rgpd` (bordures en pointillés) sont également des modificateurs entièrement morts, puisque leur classe de base n'est jamais posée.
- **Classes hors convention BEM** (voir section 2) : `.border-alert`, `.space-up`, `.space-cards`.

### Page Manifeste (`manifeste.html` + `pages/_manifeste.css`)

Toutes les classes `.manifeste*` utilisées, aucune classe morte. RAS sur ce plan.

---

## 2. Écarts BEM

Le CLAUDE.md impose strictement `Block__Element--Modifier`. Écarts repérés :

| Classe actuelle | Fichier:ligne | Problème | Nommage BEM strict suggéré | Risque |
|---|---|---|---|---|
| `.border-alert` | _contact.css:147 | Pas de préfixe de bloc, ressemble à une classe utilitaire | `.contact__card-body--alert` ou équivalent selon le contexte réel | Faible |
| `.space-up` | _contact.css:174 | Classe utilitaire pure (espacement), aucun lien à un bloc | À intégrer dans l'élément concerné comme modificateur, ou assumer une couche utilitaire explicite (le fichier `utilities/_utils.css` est déjà prévu et commenté dans style.css:24, mais jamais créé) | Faible |
| `.space-cards` | _contact.css:182 | Idem, classe utilitaire hors BEM | Idem | Faible |
| `.btn-icon` | _button.css:102 | Tiret simple au lieu du double-underscore élément (`btn-icon` au lieu de `btn__icon`) | `.btn__icon` | Faible — cohérence pure |
| `.btn-letter` / `.letter--dark` / `.letter--light` | _button.css:106-122 | `.letter--dark` est un modificateur sans bloc explicite (devrait être `.btn-letter--dark`) — mais la classe entière est morte (section 1) | N/A (à supprimer plutôt qu'à renommer) | Faible (mort) |
| `.text-link` | _base.css:101 | Classe globale hors BEM (assumé comme utilitaire de base, cohérent avec son usage transverse) | — | Faible |
| `.accronym` | _base.css:83 | Hors BEM (utilitaire), et faute d'orthographe ("accronym" au lieu de "acronym") | — | Faible |
| `.obf`, `.obf__part`, `.obf__at`, `.obf__noise` | _ethique.css:193-214 | Respecte BEM (bloc `.obf`, éléments `__part`/`__at`/`__noise`) — mentionné pour confirmer la conformité, pas une anomalie | — | — |

**Questions ouvertes non tranchées** :
- `.nav-header__brand` réutilisé dans le footer (voir section 1) — reste ouvert.
- `.text-link` comme utilitaire de base hors BEM : à traiter comme exception documentée, ou à intégrer dans un bloc ? *(non tranchée)*

Le reste de la base (`.hero__title`, `.service__spec--price`, `.contact__card--full`, etc.) respecte la convention Block__Element--Modifier de façon cohérente.

---

## 3. Custom properties

### Variables déclarées mais jamais consommées (confirmé par grep, hors leur propre ligne de déclaration)

| Variable | Fichier:ligne | Risque |
|---|---|---|
| `--color-bg-alt` | _colors.css:25 | Faible |
| `--color-btn-bg-alt` | _colors.css:75 | Faible |
| `--color-btn-border` | _colors.css:77 (+ redéfinie en dark mode, jamais consommée) | Faible |
| `--color-card-border` | _colors.css:93 | **Moyen** — voir doublon de valeur ci-dessous |
| `--font-heading` (Fraunces) | _typography.css:11 | **Élevé** — police jamais appliquée nulle part (aucun sélecteur h1-h6 ne l'utilise ; ils héritent de `--font-body`) |
| `--font-disco-alice`, `--font-disco-gayle` | _typography.css:15-16 | **Élevé** — 2 polices custom déclarées en `@font-face` (_font-face.css:111-130) et en variable, jamais référencées dans une seule règle CSS |
| `--fs-display` | _typography.css:48 | Moyen — sa seule occurrence (style.css:82) est à l'intérieur d'un bloc **commenté** |
| `--fw-light` | _typography.css:22 | Faible |
| `--ls-base`, `--ls-wider` | _typography.css:72,75 | Faible |
| `--space-12`, `--space-16` | _spacing.css:28,30 | Faible — `--space-12` ne sert qu'à définir `--gap-2xl`, lui-même jamais utilisé |
| `--gap-2xl` | _spacing.css:55 | Faible |
| `--duration-slow` | _motion.css:14 | Faible |
| `--ease-in` | _motion.css:21 | **Moyen** — voir incohérence ci-dessous |
| `--shadow-sm`, `--shadow-md`, `--shadow-lg` (ombres avec flou) | _shadows.css:14-16 | Faible — seules les variantes `--shadow-hard-*` (sans flou) sont utilisées |
| `--text-shadow-sm`, `--text-shadow-md` | _shadows.css:29-30 | Faible |
| `--radius-xs`, `--radius-md`, `--radius-lg`, `--radius-xl`, `--radius-2xl` | _shape.css:12-17 | Faible — seuls `--radius-sm` et `--radius-full` sont utilisés |
| `--radius-top/bottom/left/right` | _shape.css:25-28 | Faible — composites basés sur `--radius-xl`, lui-même inutilisé |
| `--border-width-lg` | _shape.css:37 | Faible — son unique usage (`.contact__encart--legal`, _contact.css:70) a été supprimé par le commit 820b707, la variable est donc désormais totalement inutilisée. |

### Valeurs codées en dur qui auraient dû utiliser une variable existante

- **`#575757`** répété identiquement dans _nav.css:115 et _footer.css:84 (hover des liens) — correspond exactement à `--color-card-border` (_colors.css:93), qui existe mais n'est jamais référencée. Risque **moyen** : si la couleur doit changer, il faut la modifier à 3 endroits au lieu d'un.
- **`#6c6c6c`** répété identiquement dans _nav.css:145 et _footer.css:12 — aucune variable ne porte cette valeur ; à factoriser. Risque **faible-moyen**.
- **`#423E3B`** (valeur exacte de `--raw-dark`) codée en dur dans _button.css:115 et _button.css:121 (`border: ... #423E3B solid`), et aussi dans les `stroke` SVG inline d'index.html:81 et 83. Risque **faible** (cohérence de maintenance uniquement).
- **`ease-in` / `linear`** utilisés comme mots-clés bruts dans les transitions de `.btn--border-draw` (_button.css:180,185,203,217), alors que `--ease-in` existe comme token dans `_motion.css` et n'est jamais consommé via `var()`. Risque **faible** (le composant est de toute façon mort, cf. section 1).
- **`lightpink`** (_aipd.css:139) — déjà signalé section 1, aucune variable de fond n'est utilisée ici alors que `--color-bg-dpia` existe et sert déjà ailleurs dans le même fichier.

### Incohérences de nommage/usage de variable (tokens utilisés hors de leur axe)

- **style.css:59** — `.hero__inner` utilise `padding-inline: var(--section-padding-x-mobile)` comme règle de **base** (hors media query), alors que toutes les autres sections du site utilisent `--section-padding-x` en base et ne basculent sur `--section-padding-x-mobile` que dans le bloc `@media (max-width: 768px)`.
- **Question ouverte** : volontaire (le hero doit toujours avoir un padding réduit) ou copier-coller erroné ? Risque **moyen**. *(non tranchée)*
- **style.css:193** — `.about` applique `padding-block: var(--section-padding-x-mobile)` : une variable dont le nom indique explicitement l'axe horizontal (`-x-`) est utilisée pour une propriété verticale (`padding-block`). Ressemble fortement à une confusion de copier-coller. Risque **moyen**.

### Incohérence de valeurs proches non factorisées

- `--raw-bg: #c4c5c3` et `--color-border-light: #babcb6` sont deux gris très proches mais distincts (rôles différents : fond vs séparateur). Le hex codé en dur `#c0bfbf` (utilisé dans _base.css:162 pour le tooltip `abbr::after`, et _aipd.css:50 pour `.dpia__placeholder`) est une **troisième** valeur de gris très proche des deux précédentes, non reliée à une variable.
- **Question ouverte** : ces 3 gris (`#c4c5c3`, `#babcb6`, `#c0bfbf`) devraient-ils être une seule variable, ou est-ce une nuance volontaire ? Risque **faible-moyen**. *(non tranchée)*
- `--raw-cloud-dancer: RGB(240, 238, 233)` utilise la syntaxe fonctionnelle `RGB()` en majuscules alors que tout le reste du fichier utilise du hex — incohérence stylistique mineure, pas fonctionnelle. Risque **faible**.

---

## 4. Points de rupture mobile (< 768px)

- **index.html:60-61** — `.hero__title` contient un `<br>` codé en dur ("Vos data sont quelque part en Californie. `<br>` Plus pour longtemps.") combiné à `font-size: var(--fs-xl)` en mobile (style.css:344). Ce saut de ligne forcé ignore la largeur réelle de l'écran : sur un viewport étroit (~360px), la première portion de texte est déjà proche de la largeur disponible à cette taille de police, ce qui peut produire un rendu très dense ou un retour à la ligne en cascade juste après le `<br>` forcé. Risque **moyen**.
- **_footer.css:54** — `.footer__description` a `width: 70%` fixe, sans override dans le bloc `@media (max-width: 768px)` (_footer.css:178-195) alors que `.footer__top` repasse en une seule colonne en mobile. Résultat : le paragraphe de description reste artificiellement contraint à 70% de la largeur de la colonne unique, avec un vide inutile à droite et des retours à la ligne plus fréquents que nécessaire. Risque **moyen**.
- **_aipd.css:206-222** — sous 768px, `.dpia__table-wrapper`, `.dpia__section` et `.dpia__placeholder` passent tous en `display: none`, remplacés par `.dpia__mobile-notice` ("à consulter sur desktop").
  - **Question ouverte** : est-ce un choix assumé et documenté (la page AIPD est à "usage interne — non indexé" selon aipd.html:72), ou une limitation à lever dans un futur lot mobile ? Le contenu entier de la page devient inaccessible sur mobile — risque **élevé** si ce n'est pas un choix pleinement assumé. *(non tranchée)*
- **style.css:385-387** — dans le bloc mobile, `.about__title { font-size: var(--fs-xl); }` reproduit exactement la valeur déjà définie en base (style.css:273) : ce n'est pas une rupture visuelle, mais une règle mobile qui ne change rien — signalé ici car cela peut masquer l'intention initiale (peut-être une autre taille était prévue). Risque **faible**.
- **style.css:59 / _spacing.css:39** — `--section-padding-x-mobile: clamp(2.5rem, 5vw, 4rem)` impose un minimum de 40px de padding de chaque côté du hero, y compris sur les très petits écrans (~320-360px). Ce n'est pas un débordement, mais une zone de contenu utile réduite à environ 75-80% de la largeur de l'écran sur les plus petits mobiles. Risque **faible**, à surveiller.
- Pages `ethique.html`, `manifeste.html`, `confidentialite.html`, `mentions-legales.html`, `contact.html`, `aipd.html` : les grilles à 2 colonnes (`.ethique__section-inner`, `.manifeste__section-inner`, `.contact__grid`, `.service__inner`, `.contact__card-split`) basculent proprement en `1fr` sous 768px — aucune rupture identifiée sur ces blocs.

---

## 5. Accessibilité — repérage structurel

- **contact.html:52-63 — risque élevé** : `contact.html` contient un **second document HTML complet imbriqué** dans le premier (`<!DOCTYPE html><html lang="fr"><head>...<body>` réapparaît en plein milieu du `<body>` du premier document, après le header). Le second `<head>` référence en plus une feuille de style inexistante (`href="css/style.css"`, alors que le vrai fichier est `style.css` à la racine — déjà lié correctement à la ligne 8 du premier `<head>`). Conséquences structurelles : deux `<html>`, deux `<head>`, deux `<body>`, deux `<title>` dans un seul fichier — invalide au sens HTML5, comportement de correction d'erreur du navigateur non garanti d'un navigateur à l'autre, landmarks potentiellement dédoublés ou mal imbriqués (`<main>` se trouve uniquement dans le document imbriqué, pas de `<footer>` explicite associé à l'`<header>` du document externe). C'est le point le plus critique de tout cet audit.
- **manifeste.html — risque élevé** : aucune balise `<h1>` dans toute la page. Les trois sections utilisent directement `<h2 class="manifeste__title">`, ce qui casse la hiérarchie de titres attendue (un seul h1 par page, point de départ de la structure de navigation par lecteur d'écran).
- **mentions-legales.html:2 — risque élevé** : `<html lang="fe">` — attribut `lang` invalide (typo, "fe" n'est pas un code de langue ISO valide ; devrait être `"fr"` comme sur les 6 autres pages).
- **mentions-legales.html:111-118** — déjà signalé en section 1 : `.ethique__notice-text` sans CSS, mentionné ici aussi car c'est un bloc de type "note" qui perd sa distinction visuelle structurelle (pas un problème de contraste, un problème d'absence totale de traitement).
- **Landmarks** : sur les 6 pages non affectées par le bug ci-dessus, la structure `<header>` → `<nav aria-label="Navigation principale">` → `<main>` → `<footer>` avec un second `<nav aria-label="Navigation secondaire">` est cohérente et bien labellisée (les deux `<nav>` ont des `aria-label` distincts, ce qui évite l'ambiguïté de landmarks dupliqués). Aucun problème structurel sur ce point pour index/aipd/confidentialite/ethique/mentions-legales.
- **Hiérarchie h1-h6** : correcte (h1 → h2 → h3 sans saut) sur index.html, aipd.html, confidentialite.html, ethique.html, mentions-legales.html. Seul manifeste.html est en défaut (voir ci-dessus).
- **Attribut `alt`** : la seule image `<img>` du site (index.html:220, portrait) a un `alt="E. Victor Barthélémy"` — acceptable pour un portrait qui identifie une personne, aucun problème détecté.
- **Formulaires** : **non applicable** — aucun élément `<form>`, `<input>`, `<textarea>` ou `<select>` n'existe sur le site (le contact se fait par e-mail obfusqué en texte, pas par formulaire). Le point "labels associés aux champs" ne peut donc pas être évalué faute de champs.
- **Icônes SVG décoratives** : les SVG inline répétés dans les liens du footer (ex. index.html:270-273) n'ont ni `aria-hidden="true"` ni `role="img"`/`<title>`. Comme chaque lien contient déjà un texte visible ("Accueil", "Manifeste", etc.), l'absence de `aria-hidden="true"` sur l'icône décorative est un point mineur mais réel. Risque **faible**.

---

## DÉCISIONS ACTÉES

- Le bloc CSS `.ethique` / `.ethique__section` / `.ethique__title` etc.
  (`pages/_ethique.css`) est **renommé en composant générique `.legal-page`**
  (`.legal-page__section`, `.legal-page__title`, etc.) sur les 3 pages
  concernées : `confidentialite.html`, `ethique.html`, `mentions-legales.html`.
  Ce renommage **n'est pas encore effectué** — il sera traité dans la session
  CSS/BEM (voir PLAN DE SESSIONS, point b).

- `.sr-only` ajoutée dans `base/_base.css` (session corrections critiques) —
  à évaluer pour déplacement vers `utilities/_utils.css` lors de la session
  CSS/BEM.

---

## PLAN DE SESSIONS

Ordre de traitement retenu, chaque point ci-dessous fera l'objet d'un Plan
Mode dédié — aucun détail d'exécution n'est fixé à ce stade.

**a. Corrections critiques isolées** (session suivante)
- Structure HTML dupliquée dans `contact.html`.
- `lang="fe"` → `lang="fr"` dans `mentions-legales.html`.
- Absence de `<h1>` dans `manifeste.html`.

**b. CSS/BEM**
- Nettoyage des classes mortes (section 1).
- Corrections BEM (section 2).
- Renommage `.ethique` → `.legal-page` (voir DÉCISIONS ACTÉES).
- Factorisation des variables/couleurs dupliquées (section 3).

**c. Mobile**
- Points de rupture listés en section 4.

**d. Accessibilité, passe complète**
- Contraste, reflow, focus — après stabilisation du mobile.

**e. Design par page**

---

## Questions ouvertes (non tranchées)

- `.nav-header__brand` réutilisé dans le footer (section 1/2).
- `.about__title` en `font-mono` au lieu de `font-brand` comme les autres titres (section 1).
- `.is-hidden` (keyboard-hints) potentiellement piloté par `assets/js/theme.js`, jamais présent statiquement en HTML (section 1).
- `.text-link` comme utilitaire de base hors BEM — exception à documenter ou à intégrer dans un bloc ? (section 2).
- `.hero__inner` en base utilise `--section-padding-x-mobile` hors media query : volontaire ou copier-coller erroné ? (section 3).
- Les 3 gris proches non factorisés (`#c4c5c3`, `#babcb6`, `#c0bfbf`) : nuance volontaire ou à unifier ? (section 3).
- Masquage complet du contenu de `aipd.html` sous 768px : choix assumé ou limitation à lever ? (section 4).
