EXPERT 03 — Socle couleur, accessibilité WCAG 2.2 et performance — TERO GROUP

Périmètre : tero.be (maison mère) et toutes les sous-activités du groupe Tero.

Objet : socle couleur + accessibilité + performance, chiffré, vérifiable, directement

intégrable dans tero-group-rules.md, le design system et les skills.

Méthode : recalcul intégral des contrastes (formule WCAG de luminance relative),

relevé réseau du 15 octobre 2026 sur https://tero.be/fr/, lecture critique de

tero-group-rules.md v1.0.0 (645 lignes), DESIGN.md, tokens.css, design-tokens.json

et du modèle _ref/teropadelclub/…/tero-rules.md.

Étiquettes : [MESURE] = relevé ou calcul reproductible · [RÈGLE] = décision de système

proposée, opposable une fois validée · [À VALIDER CLIENT] = question ouverte.

Aucun fait de marque n'est inventé ici : les couleurs utilisées sont celles mesurées dans

l'audit du 15/10/2026 ; les seules valeurs nouvelles proposées sont des neutres de système

(texte et bordure), explicitement étiquetées.

---

1. Verdict sur l'existant — ce qui tient, ce qui casse

1.1 Ce qui est exact (vérifié par recalcul indépendant)

Les 21 ratios de contraste publiés dans le contexte, dans docs/AUDIT-TERO-BE-2026.md § 3.5,

dans tero-group-rules.md § 2.4 et dans design-tokens.json ont été recalculés un par un avec la

formule WCAG (sRGB → linéarisation → 0,2126 R + 0,7152 V + 0,0722 B → (L1+0,05)/(L2+0,05)).

Résultat : 21/21 exacts, écart maximal 0,00. La base chiffrée du lead est fiable, y compris

pour les dérives (#5E93A7 = 3,38 · #B00000 = 7,38 · #680224 = 12,94 · #323232 = 12,82). [MESURE]

Cela signifie que les erreurs relevées ci-dessous ne sont pas des erreurs de calcul : ce sont

des erreurs de règle (une valeur juste utilisée dans un contexte où elle échoue).

1.2 Les 20 constats qui cassent le système — par priorité

Priorité P0 = bloque la conformité, à trancher avant toute production de composants.

Priorité P1 = à corriger avant la première livraison. P2 = dette de qualité.

#PrioConstatOù (fichier:ligne)Preuve chiffréeCorrection attendue
F1P0L'anneau de focus teal est unique et imposé partout : il disparaît sur les surfaces que la charte autorise (bouton teal, bouton pétrole, aplat rose vif, aplat cyan, bande #212121).tero-group-rules.md:372 et 438 · tokens.css (--focus-ring) · design-tokens.json (components.focus)teal/teal = 1,00:1 · teal/#004B69 = 1,75 · teal/#FF1D58 = 1,44 · teal/#00B7FF = 2,38 · teal/#212121 = 2,97 (sous le seuil non-texte de 3:1)Double anneau à jeton contextuel (§ 3.3). Un seul anneau ne peut pas être conforme sur tout le système.
F2P0#B9B9B9 (--tero-muted) est affecté aux « libellés de champ » et aux placeholders. Le placeholder d'un champ actif n'est pas exempté par WCAG 1.4.3 : il doit atteindre 4,5:1.tero-group-rules.md:129 et 436 · DESIGN.md § 2 · tokens.css#B9B9B9/#FFFFFF = 1,96:1 (échec AA, facteur 2,3)Nouveau neutre --tero-ink-muted: #5F5F5F (6,39 / 5,83 / 5,10 / 4,52 sur les 4 fonds clairs). #B9B9B9 devient réservé au désactivé (seul cas exempté).
F3P0La bordure de champ #D9D9D9 sur fond blanc, et le champ #E5E6E5 bordé de #D9D9D9 : la limite du contrôle est invisible. Aucun jeton de bordure interactive n'existe.tero-group-rules.md:378 et 411 · tokens.css (--tero-line, --tero-line-soft)#D9D9D9/#FFFFFF = 1,41:1 · #D9D9D9/#E5E6E5 = 1,13:1 · seuil 1.4.11 = 3:1Ajouter --tero-border-field: #767676 (4,54 / 4,15 / 3,63 / 3,22). #D9D9D9 reste décoratif (filets, séparateurs).
F4P0Contradiction à trois voix sur le teal en bande profonde : tero-group-rules.md § 7.3 le liste comme « accent autorisé » puis l'interdit en texte ; DESIGN.md § 6 l'exclut ; design-tokens.json ne le liste pas dans deepBand.accents. Sur #212121 le teal tombe même sous le seuil graphique de 3:1.tero-group-rules.md:385-386 · DESIGN.md § 6 · design-tokens.json (components.deepBand)teal/#000000 = 3,87 · teal/#212121 = 2,97Règle unique : teal interdit sur #212121 (texte ET graphique) ; sur #000000 toléré uniquement comme graphique décoratif ≥ 3:1, jamais comme texte.
F5P0Les largeurs de contrôle et de capture s'arrêtent à 360 px. WCAG 2.2 SC 1.4.10 Reflow exige l'absence de défilement horizontal à 320 px (équivalent zoom 400 %).tero-group-rules.md:407 et 558 · DESIGN.md § 4320 px absent des deux listesAjouter 320 px en tête de la liste des 5 largeurs → 6 largeurs : 320 / 360 / 390 / 768 / 1024 / 1440.
F6P0Aucun jeton d'état n'existe (succès, avertissement, erreur, information) alors que § 7.4 exige que tout composant déclare l'état « erreur ». Les 7 couleurs déclarées ne portent aucune règle d'état.tokens.css · design-tokens.json (aucune entrée) · tero-group-rules.md:388-3910 jeton d'état pour 7 états exigés§ 3.4 : table d'états opposable, dérivée sans nouvelle couleur de marque.
F7P1Le mot-symbole est décrit en capitales (« le mot-symbole s'écrit TERO »). Le logo officiel est en minuscules : _audit/logo-tero-2025.svg, viewBox 0 0 100 40, 5 tracés, fill noir.tero-group-rules.md:257, 276, 292 · DESIGN.md § 8 · design-tokens.json (brand.wordmarkCase)Fichier de référence : minusculesCorriger partout : mot-symbole = tero (minuscules) ; graphie rédactionnelle = Tero ; jamais TERO en capitales.
F8P1La description du monogramme est fausse : le glyphe officiel est le o stylisé (anneau plein + barre horizontale sous l'anneau), pas « un anneau ». Décrit comme « anneau » dans les règles et le JSON.tero-group-rules.md:262 · design-tokens.json (brand.logoForbidden)_audit/monogram-tero-2026.png, 1272 × 1861Reformuler : « glyphe o isolé de tero ». L'usage reste interdit comme Organization.logo (ratio 0,68, portrait) mais devient possible comme pastille/monogramme avec alt = tero.
F9P1Le seuil « grand texte » est mal énoncé : « ≥ 3:1 pour ≥ 24 px gras ». WCAG : 3:1 pour ≥ 24 px normal OU ≥ 18,66 px (14 pt) gras. Énoncé actuel = faux négatif sur les gros boutons.tero-group-rules.md:60014 pt gras = 18,66 px« ≥ 3:1 pour ≥ 24 px, ou ≥ 18,66 px en graisse 700 ».
F10P1Le socle exige font-display: swap + préchargement des polices. Le site ne le fait pas : 4 @font-face en font-display: auto, 0 preload de police.tero-group-rules.md:450-452 vs relevé live4 @font-face, toutes font-display: auto · 0 link rel=preload as=fontswap obligatoire + 1 seul preload (graisse du H1) + repli métrique (size-adjust).
F11P1§ 11 Performance = 3 lignes, aucun budget chiffré hors LCP/INP/CLS. Impossible d'opposer un refus à une page de 400 Ko de CSS.tero-group-rules.md:449-453CSS mesuré : 170,5 Ko (gzip) pour 10 des ≥ 34 feuilles de l'accueil§ 5.2 : budget complet, mesurable, avec l'outil de contrôle.
F12P1Les 9 critères nouveaux de WCAG 2.2 sont absents (§ 10 en compte 0), alors que le niveau visé est « AA minimum partout ».tero-group-rules.md:433-4429 SC absents : 2.4.11, 2.4.12, 2.4.13, 2.5.7, 2.5.8, 3.2.6, 3.3.7, 3.3.8, 3.3.9§ 4.1 et § 4.2.
F13P1Aucune règle contraste élevé / forced-colors / prefers-contrast, aucun test de zoom 200 %, aucun test 320 px, aucune règle de sous-titres vidéo.tero-group-rules.md:433-442 · § 16.2 (8 contrôles, 0 a11y automatisé)0 occurrence de forced-colors / prefers-contrast / 1.2.2 dans les 645 lignes§ 4.2 et § 4.3.
F14P1Le relevé live montre 2 H1 et 0 H2/H3 sur l'accueil (100 premiers ko de HTML) : la hiérarchie de titres est cassée, alors que § 6.1 l'interdit.tero-group-rules.md:328 vs relevé live 15/10/2026h1 = 2 · h2 = 0 · h3 = 0Contrôle automatisé : exactement 1 H1, aucun saut de niveau (§ 4.3, porte CI).
F15P2La dérive sauge est exposée comme jeton CSS utilisable (--tero-drift-sage). Un jeton exposé finit utilisé.tokens.css--tero-drift-sage: #97ab83Préfixer les dérives --x-drift- hors du bloc :root livré, ou les sortir de tokens.css.
F16P2L'audit classe #323232 en « dérive » (§ 3.5) alors que la charte l'adopte comme neutre n° 2 (--tero-ink-soft). Incohérence de qualification entre les deux documents.AUDIT:193 vs tero-group-rules.md:127même valeur, deux statutsDans l'audit : « neutre adopté, non déclaré dans le kit Elementor ».
F17P2design-tokens.json annonce « method: WCAG 2.1 » alors que la cible est 2.2 (formules identiques, libellé faux).design-tokens.json (contrast.method)—« WCAG 2.2 AA, formule de luminance relative W3C ».
F18P2La liste des dérives du JSON omet le magenta #FF2E82 et le lime #E9F44E mesurés sur teropadelclub.be, pourtant cités par l'audit § 8.design-tokens.json (color.drift)magenta #FF2E82 / blanc = 3,20:1 · lime #E9F44E / blanc = 1,20:1Ajouter les deux valeurs, avec mention « palette padel, sous-marque — à trancher (question client n° 2) ».
F19P2DESIGN.md § 9 liste 12 anti-patterns, aucun d'accessibilité (focus supprimé, placeholder comme label, état en couleur seule, texte sur fond non conforme).DESIGN.md § 90/12Ajouter les 4 anti-patterns a11y (§ 4.4).
F20P2§ 16.2 « Contrôles minimaux avant livraison » = 8 contrôles, aucun automatisé pour l'accessibilité et la performance (pas d'axe, pas de Lighthouse, pas de budget de poids).tero-group-rules.md:552-5610/8Ajouter les 5 portes CI du § 4.3.

---

2. Matrice de contraste complète (recalculée)

2.1 Méthode exacte — reproductible

Formule W3C utilisée pour tous les chiffres de ce document (aucune valeur recopiée) :

// sRGB -> luminance relative

c = canal / 255

c_lin = (c <= 0.03928) ? c / 12.92 : ((c + 0.055) / 1.055) ^ 2.4

L = 0.2126R_lin + 0.7152V_lin + 0.0722*B_lin

ratio = (max(L1,L2) + 0.05) / (min(L1,L2) + 0.05)

Seuils appliqués : texte 4,5:1 (AA) / 7:1 (AAA) ; grand texte 3:1 (≥ 24 px, ou

≥ 18,66 px en graisse 700) ; non-texte (bordure, icône porteuse de sens, anneau de focus,

graphique) 3:1 (SC 1.4.11).

Luminances relatives calculées (utiles aux calculs de dérivées) :

CouleurHexL
Blanc#FFFFFF1,000000
Surface#F6F4F40,908259
Filet léger#E5E6E50,789088
Filet#D9D9D90,693872
Sable#FAD2820,680289
Rose poudré#D7B4B40,503849
Gris désactivé#B9B9B90,485150
Cyan#00B7FF0,410870
Rose vif#FF1D580,228433
Teal#0078640,143530
Terracotta#B938150,131968
Pétrole#004B690,060521
Encre douce#3232320,031896
Encre profonde#2121210,015209
Noir#0000000,000000

2.2 Neutres et couleurs de marque × fonds clairs — texte

Lecture : ratio sur fond #FFFFFF / #F6F4F4 / #E5E6E5 / #D9D9D9, puis verdict pour du texte courant.

TexteHex/#FFFFFF/#F6F4F4/#E5E6E5/#D9D9D9Rôle texte autorisé
Noir#00000021,00 AAA19,17 AAA16,78 AAA14,88 AAATexte principal sur les 4 fonds
Encre profonde#21212116,10 AAA14,70 AAA12,87 AAA11,41 AAATitres, aplats sombres — texte sur les 4 fonds
Encre douce#32323212,82 AAA11,70 AAA10,25 AAA9,08 AAATexte secondaire sur les 4 fonds
Pétrole#004B699,50 AAA8,67 AAA7,59 AAA6,73 AATexte, titres, liens sur les 4 fonds
Teal#0078645,43 AA4,95 AA4,34 ÉCHEC3,84 ÉCHECTexte uniquement sur #FFFFFF et #F6F4F4
Terracotta#B938155,77 AA5,27 AA4,61 AA4,09 ÉCHECTexte sur blanc, surface, filet léger — jamais sur #D9D9D9
Rose vif#FF1D583,77 grand3,44 grand3,01 grand2,67 ÉCHECGrand texte (≥ 24 px / ≥ 18,66 px gras) sur fonds très clairs uniquement
Gris désactivé#B9B9B91,96 ÉCHEC1,79 ÉCHEC1,57 ÉCHEC1,39 ÉCHECAucun texte actif. Désactivé uniquement (exempt SC 1.4.3)
Sable#FAD2821,44 ÉCHEC1,31 ÉCHEC1,15 ÉCHEC1,02 ÉCHECAucun texte — aplat seulement
Rose poudré#D7B4B41,90 ÉCHEC1,73 ÉCHEC1,52 ÉCHEC1,34 ÉCHECAucun texte — aplat seulement
Cyan#00B7FF2,28 ÉCHEC2,08 ÉCHEC1,82 ÉCHEC1,61 ÉCHECAucun texte — aplat seulement
Filet#D9D9D91,41 ÉCHEC1,29 ÉCHEC1,13 ÉCHEC1,00 ÉCHECAucun texte — séparateur décoratif
Surface#F6F4F41,10 ÉCHEC1,00 ÉCHEC1,14 ÉCHEC1,29 ÉCHECAucun texte — fond
Blanc#FFFFFF1,00 ÉCHEC1,10 ÉCHEC1,25 ÉCHEC1,41 ÉCHECAucun texte — fond

Trois échecs non documentés par le lead, à intégrer :

champ ou sur une plaque filet échoue AA. [MESURE]

gris clair (3,01 est à la limite, marge nulle). [MESURE]

2.3 Fonds sombres — texte et graphique

TexteHex/#000000/#212121Rôle autorisé
Blanc#FFFFFF21,00 AAA16,10 AAATexte principal sur bande profonde
Sable#FAD28214,61 AAA11,20 AAATexte, sur-titre, accent, graphique
Filet#D9D9D914,88 AAA11,41 AAAFilet visible sur fond sombre
Rose poudré#D7B4B411,08 AAA8,49 AAATexte, accent
Gris désactivé#B9B9B910,70 AAA8,21 AAATexte secondaire sur bande profonde (et désactivé)
Cyan#00B7FF9,22 AAA7,07 AAATexte, accent, graphique
Rose vif#FF1D585,57 AA4,27 AAAccent rare, texte ≥ 18,66 px gras
Teal#0078643,87 grand/UI2,97 ÉCHECSur #000000 : graphique décoratif uniquement. Sur #212121 : interdit totalement
Terracotta#B938153,64 grand/UI2,79 ÉCHECSur #000000 : graphique uniquement. Sur #212121 : interdit (utiliser un badge terracotta + texte blanc)
Pétrole#004B692,21 ÉCHEC1,69 ÉCHECInterdit sur toute bande profonde, texte comme graphique
Encre douce#3232321,64 ÉCHEC1,26 ÉCHECInterdit sur bande profonde
Encre profonde#2121211,30 ÉCHEC1,00 ÉCHECInterdit
Noir#0000001,00 ÉCHEC1,30 ÉCHECInterdit

Conséquence opposable : sur bande profonde, seuls **blanc, sable, rose poudré, cyan, rose vif

(≥ 18,66 px gras) et gris désactivé #B9B9B9 (texte secondaire)** sont utilisables en texte.

Le teal et le terracotta n'y sont que des graphiques sur noir pur, et jamais sur #212121.

2.4 Texte sur aplat de marque — la règle du texte noir

AplatHextexte noir #000texte blanc #FFFVerdict opposable
Teal#0078643,875,43 AATexte blanc
Pétrole#004B692,219,50 AAATexte blanc
Terracotta#B938153,645,77 AATexte blanc
Sable#FAD28214,61 AAA1,44Texte noir
Rose poudré#D7B4B411,08 AAA1,90Texte noir
Cyan#00B7FF9,22 AAA2,28Texte noir
Rose vif#FF1D585,57 AA3,77 grandTexte noir (jamais blanc sous 18,66 px gras)
Gris désactivé#B9B9B910,70 AAA1,96Texte noir — aplat désactivé
Filet#D9D9D914,88 AAA1,41Texte noir

Règle des trois familles [RÈGLE] :

Interdits en texte sur fond clair.

Jamais utilisés comme aplat sous du texte blanc sauf #004B69 (9,50).

2.5 Accents sur aplats clairs (texte posé sur une pastille sable / rose / cyan)

Textesur sable #FAD282sur rose #D7B4B4sur cyan #00B7FFVerdict
#00000014,6111,089,22✅ AAA sur les trois
#3232328,926,765,63✅ AA/AAA sur les trois
#004B696,615,014,17✅ sur sable et rose — échoue sur cyan (4,17)
#B938154,013,042,53⚠️ grand texte sur sable seulement — sinon interdit
#0078643,772,862,38❌ interdit en texte sur aplat
#FF1D582,621,991,66❌ interdit

Règle : sur un aplat coloré, le texte est noir, sauf sur sable et rose poudré où le pétrole

#004B69 est également autorisé (6,61 / 5,01). Jamais de teal, jamais de rose vif en texte sur aplat.

2.6 Anneau de focus — pourquoi un seul anneau ne peut pas marcher

Ratio de l'anneau (couleur) contre le fond adjacent à l'anneau. Seuil 3:1 (SC 1.4.11 + 2.4.13).

Anneau \ Fond#FFFFFF#F6F4F4#000000#212121tealpétrolerose vifcyan
teal (actuel)5,43 ✅4,95 ✅3,87 ✅2,97 ❌1,00 ❌1,75 ❌1,44 ❌2,38 ❌
noir21,00 ✅19,17 ✅1,00 ❌1,30 ❌3,87 ✅2,21 ❌5,57 ✅9,22 ✅
blanc1,00 ❌1,10 ❌21,00 ✅16,10 ✅5,43 ✅9,50 ✅3,77 ✅2,28 ❌
sable1,44 ❌1,31 ❌14,61 ✅11,20 ✅3,77 ✅6,61 ✅2,62 ❌1,58 ❌
rose vif3,77 ✅3,44 ✅5,57 ✅4,27 ✅1,44 ❌2,52 ❌1,00 ❌1,66 ❌

Aucune ligne n'est conforme sur toute la largeur. Le teal — imposé aujourd'hui — est conforme

sur 4 fonds sur 8 et échoue sur 4, dont deux surfaces directement produites par la charte

(bouton teal § 7.1, bande #212121 § 7.3). D'où la solution du double anneau (§ 3.3), seule

construction qui reste ≥ 3:1 quel que soit le fond.

2.7 Non-texte (SC 1.4.11) — bordures, icônes, graphiques porteurs de sens

ÉlémentRatio mesuréSeuil 3:1Décision
Bordure de champ #D9D9D9 sur blanc1,41❌Remplacer par #767676 (4,54)
Bordure de champ #D9D9D9 sur #E5E6E51,13❌Remplacer par #767676 (3,63)
Filet séparateur #D9D9D9 sur blanc1,41exemptDécoratif uniquement — ne doit jamais être le seul indice d'un contrôle
Sous-titre / icône teal sur blanc5,43✅OK
Icône cyan sur blanc2,28❌Icône cyan uniquement dans un aplat, ou doubler l'information par un texte
Icône/soulignement rose vif sur blanc3,77✅OK pour le non-texte
Bordure de carte sur bande noire (si filet #D9D9D9)14,88✅OK
Bordure interactive sur bande noire#767676 / #000000 = 4,62✅Utiliser #767676 (ou #FFFFFF)
Indicateur de sélection (onglet actif, case cochée)doit être ≥ 3:1 contre son voisin—À instrumenter : aucun jeton n'existe (voir § 3.1, --tero-border-field)

2.8 Rôles autorisés par couleur — table de décision opposable

CouleurHexTexteAplatGraphique / bordureFocusInterditSubstitution si besoin
Noir#000000✅ principal (fonds clairs)✅ bande profonde✅✅ anneau (fonds clairs)texte sur sombre—
Blanc#FFFFFF✅ sur bande profonde et aplats teal/pétrole/terracotta✅ fond✅✅ anneau (bandes profondes)texte sur aplat sable/rose/cyan/vifnoir
Surface#F6F4F4❌✅ fond de section✅ fond—texte—
Filet#D9D9D9❌❌✅ séparateur décoratif—bordures de contrôles#767676
Filet léger#E5E6E5❌✅ fond de champ❌—bordures de contrôles#767676
Encre profonde#212121✅ titres✅ bande profonde✅—texte sur sombre—
Encre douce#323232✅ texte secondaire❌✅—texte sur sombre—
Gris désactivé#B9B9B9✅ désactivé uniquement + texte secondaire sur fond sombre✅ aplat désactivé✅ sur fond sombre—placeholders, libellés, mentions#5F5F5F
Teal#007864✅ texte/lien sur #FFFFFF et #F6F4F4 uniquement✅ texte blanc✅ sur fonds clairs⚠️ insuffisant seul (voir § 3.3)texte sur #E5E6E5, #D9D9D9 ; texte et graphique sur #212121 ; texte sur noirpétrole (9,50)
Pétrole#004B69✅ texte sur les 4 fonds clairs✅ texte blanc✅ sur fonds clairs✅ anneau sur fonds clairs (9,50)toute bande profonde (2,21 / 1,69)blanc/sable
Terracotta#B93815✅ texte sur blanc/surface/filet léger✅ texte blanc✅⚠️ 2,79 sur #212121texte sur #D9D9D9, sur bandes profondesbadge terracotta + texte blanc
Sable#FAD282❌✅ texte noir✅ sur fond sombre✅ anneau sur fonds sombres (14,61)texte sur fond clair#000000
Rose poudré#D7B4B4❌✅ texte noir✅ sur fond sombre—texte sur fond clair#000000
Cyan#00B7FF❌✅ texte noir❌ icône sur fond clair—texte et graphique sur fond clairnoir
Rose vif#FF1D58⚠️ grand texte seul (≥ 24 px / ≥ 18,66 px gras)✅ texte noir✅✅ anneau sur fonds clairs (3,77)texte blanc sur son aplat ; texte courant sur fond clair#B93815 (texte)

2.9 Échecs mesurés et substitution imposée

Couple en échecRatioSubstitution
teal sur #E5E6E5 / #D9D9D94,34 / 3,84pétrole #004B69 (7,59 / 6,73) ou noir
terracotta sur #D9D9D94,09#000000 (14,88) ou #323232 (9,08)
#B9B9B9 texte actif1,96#5F5F5F (6,39) — proposé
#D9D9D9 bordure de champ1,41#767676 (4,54) — proposé
blanc sur rose vif sous 18,66 px gras3,77texte noir sur rose vif (5,57)
teal en texte sur noir3,87sable (14,61) ou blanc (21,00)
teal sur #2121212,97sable (11,20) ou blanc (16,10)
terracotta sur bande profonde3,64 / 2,79badge terracotta + texte blanc (5,77)
pétrole sur bande profonde2,21 / 1,69aucun usage — interdiction totale
rose vif sur #E5E6E5 en grand texte3,01bord de marge nulle → noir
#FF4A4A (dérive) en erreur sur blanc3,32terracotta #B93815 (5,77)
magenta padel #FF2E82 sur blanc3,20terracotta sur le périmètre groupe ; hors groupe = dérive
lime padel #E9F44E sur blanc1,20aplat + texte noir uniquement

---

3. Rôles sémantiques couleur (jetons) et états

3.1 Jetons sémantiques — à ajouter au design system

Les jetons de base existent (tokens.css § 2.1/2.2). Il manque la couche sémantique complète

et deux neutres de système. Proposition [RÈGLE] :

Jeton sémantiqueValeurSourceUsagePreuveInterdit
--surface#FFFFFFmesuréFond principal——
--surface-alt#F6F4F4mesuréFond de section alternée—texte teal/terracotta
--surface-elevated#FFFFFF + filet 1 px --linerègleSurface élevée = filet, jamais ombre (§ 7.2)filet décoratiffond + bordure + rayon + ombre empilés
--surface-inverse#000000mesuréBande profonde——
--surface-inverse-alt#212121mesuréBande profonde alternative—teal, terracotta, pétrole
--text#000000mesuréTexte principal21,00sur fond sombre
--text-secondary#323232mesuréTexte secondaire, chapô, meta12,82sur fond sombre
--text-muted#5F5F5F (proposé)neutre de systèmePlaceholders, libellés, mentions, dates6,39 / 5,83 / 5,10 / 4,52—
--text-disabled#B9B9B9mesuréComposant inactif exclusivement1,96 (exempt SC 1.4.3)jamais un placeholder actif
--text-inverse#FFFFFFmesuréTexte sur bande profonde et aplats famille A21,00aplat famille B
--text-inverse-secondary#B9B9B9mesuréTexte secondaire sur bande profonde10,70 / 8,21fonds clairs
--border#D9D9D9mesuréFilet séparateur décoratif1,41 (exempt)bordures de contrôles
--border-field#767676 (proposé)neutre de systèmeBordure de champ, case, onglet, sélection4,54 / 4,15 / 3,63 / 3,22—
--border-inverse#767676proposéBordure sur bande profonde4,62 / 3,55—
--accent#007864mesuréAccent n° 1 : lien en ligne, pastille, aplat5,43 (blanc)#E5E6E5, #D9D9D9, bandes profondes
--accent-hover#004B69mesuréSurvol/enfoncé de l'accent (pas de nouvelle couleur)9,50bandes profondes
--accent-on-dark#FAD282mesuréAccent sur bande profonde14,61fonds clairs
--focus-ring#000000 (fonds clairs) / #FFFFFF (bandes profondes)règleAnneau de focus extérieur21,00—
--focus-halo#FFFFFF / #000000règleAnneau intérieur (gorge de séparation)21,00—
--success#007864mesuréFond de badge succès, texte #FFFFFF5,43en couleur de texte d'état
--warning#FAD282mesuréFond de badge avertissement, texte #00000014,61en couleur de texte
--error#B93815mesuréFond de badge erreur, texte #FFFFFF ; texte d'erreur sur fond clair5,77texte sur #D9D9D9 et bandes profondes
--info#004B69mesuréFond de badge information, texte #FFFFFF9,50sur bandes profondes (2,21)
--link#007864 + soulignementrègleLien en lignevoir § 3.5couleur seule
--link-visited#004B69mesuréLien visité — doit rester conforme9,50toute teinte non conforme

Deux seuls neutres nouveaux sont nécessaires (#5F5F5F, #767676). Ce ne sont pas des couleurs

de marque : ce sont des neutres de lisibilité, exigés par SC 1.4.3 et SC 1.4.11. Ils n'augmentent

pas la palette (7 couleurs + 4 neutres + 2 jetons d'accessibilité) et doivent être documentés comme tels.

[À VALIDER CLIENT — arbitrage charte : accepter 2 neutres de lisibilité, ou accepter des échecs AA.]

3.2 Ce qu'il faut retirer du socle livré

--x-drift-, dans un fichier de résorption, jamais dans les jetons distribués. [RÈGLE]

Un nom qui dit « désactivé » empêche l'usage en placeholder. [RÈGLE]

3.3 Focus visible — le double anneau (correction de F1)

Construction conforme partout, sans dépendre du fond :

:root{

--focus-ring:#000000; / anneau extérieur /

--focus-halo:#FFFFFF; / gorge : reprend le fond de la page /

--focus-width:2px;

--focus-offset:2px;

}

.surface-inverse,[data-theme="dark"]{

--focus-ring:#FFFFFF; --focus-halo:#000000;

}

:where(a,button,input,select,textarea,summary,[tabindex]):focus-visible{

outline:var(--focus-width) solid var(--focus-ring);

outline-offset:var(--focus-offset);

box-shadow:0 0 0 calc(var(--focus-offset) + var(--focus-width)) var(--focus-halo);

}

@media (forced-colors:active){

:focus-visible{ outline:3px solid Highlight; }

}

Preuve de conformité : de l'intérieur vers l'extérieur, bouton teal sur section blanche →

teal/halo blanc = 5,43:1 ✅ → halo blanc/anneau noir = 21,00:1 ✅. Bouton noir → noir/halo

blanc 21,00 ✅ → blanc/anneau noir 21,00 ✅. Badge sable sur bande noire → sable/halo noir

14,61 ✅ → noir/anneau blanc 21,00 ✅. Aucun cas d'échec possible.

Compléments opposables (SC 2.4.11 / 2.4.12 / 2.4.13) :

serait rogné.

focalisable : un en-tête collant ne doit jamais recouvrir l'élément focalisé (2.4.11), et

scroll-padding-block-start: 6rem seul ne suffit pas pour le focus clavier.

3.4 États — quelles couleurs peuvent porter un état

ÉtatFondTexteRatioEmploi autoriséInterdit
Succès#007864 (teal)#FFFFFF5,43 AABadge, bandeau, encart de confirmationteal en couleur de texte d'état (collision avec le lien teal)
Avertissement#FAD282 (sable)#00000014,61 AAABadge, encart, bordure gauche 4 pxsable en couleur de texte (1,44 sur blanc)
Erreur#B93815 (terracotta)#FFFFFF5,77 AABadge, encart, texte d'erreur de champ sur fond clairterracotta en texte sur #D9D9D9 (4,09) et sur bande profonde (3,64 / 2,79)
Information#004B69 (pétrole)#FFFFFF9,50 AAABadge, encart, bandeau neutrepétrole sur bande profonde (2,21)
Désactivé#E5E6E5#B9B9B91,57Composant inactif uniquement (exempt)tout composant actif
Chargement———aria-busy="true" + libellé « Envoi… »spinner sans texte
Sélection#F6F4F4 + bordure #767676#00000019,17Onglet actif, option retenuecouleur seule (1.4.1)
Erreur sur bande profonde#B93815#FFFFFF5,77Badge uniquementterracotta en texte ou icône sur #000/#212121

Trois règles d'état opposables [RÈGLE] :

jamais un état en couleur de texte (aucune ne passe 4,5:1 sur fond clair). Elles ne peuvent

être que le fond d'un badge à texte noir.

toujours par icône + texte + couleur — jamais par la couleur seule. Sinon le lecteur ne peut

pas distinguer un lien d'un succès.

interdit : il appartient à la dérive ; l'erreur est terracotta #B93815.

#FF4A4A (3,32 sur blanc) est non conforme en plus d'être une dérive.

SC 1.4.1 — l'information ne passe jamais par la couleur seule : tout état porte une icône

distincte et un libellé explicite (« Erreur : le téléphone doit être au format +32 4XX XX XX XX »).

3.5 Liens en ligne — la règle du soulignement

Teal #007864 contre le texte noir #000000 = 3,87:1 (≥ 3:1, technique G183 satisfaite).

Mais G183 exige un indice supplémentaire au survol/focus. [RÈGLE] :

1 px, underline-offset 0,15em). C'est la seule solution non ambiguë pour un daltonien et pour le

mode contraste élevé.

3.6 Contraste élevé / forced-colors / préférences

PréférenceRègleMise en œuvre
forced-colors: active (Windows contraste élevé)Les icônes utilisent currentColor, les bordures passent par border (jamais background-image), les états ne reposent pas sur une imagemedia query dédiée + border-color: CanvasText
prefers-contrast: more--border et --line passent à #000000 ; l'accent passe à #004B69media query
prefers-reduced-motion: reduceAucune animation, aucun zoom, aucune vidéo chargée (poster seul)media query + JS
color-schemecolor-scheme: light explicite sur :root tant que le mode sombre n'existe pas (évite l'assombrissement natif des champs):root
Zoom 200 %Aucune perte d'information, aucun défilement horizontal à 200 % sur 1280 pxtest obligatoire
Zoom texte seultext-size-adjust: 100% et aucune hauteur de texte figée en pxCSS

---

4. Checklist de conformité WCAG 2.2 — testable

4.1 Les 9 critères ajoutés par WCAG 2.2 (aujourd'hui absents des règles)

SCNiv.ExigenceApplication TEROTest
2.4.11 Focus non masqué (minimum)AAL'élément focalisé n'est pas entièrement cachéHeader collant, bandeau cookies, barre de réservationTab jusqu'au dernier élément du header : le focus doit rester visible
2.4.12 Focus non masqué (renforcé)AAAAucune partie cachéeIdem, viséIdem, contrôle visuel
2.4.13 Apparence du focusAAAAnneau ≥ 2 px de périmètre, contraste ≥ 3:1Double anneau § 3.3Mesure des ratios, 8 contextes
2.5.7 Mouvements de glissementAAAlternative au glisser-déposer sur un seul pointeurCarrousels, galeries, sélecteurs de date, cartes de lieuxBoutons précédent/suivant présents et clavier
2.5.8 Taille de cible (minimum)AA≥ 24 × 24 px CSS, ou espacement suffisant (exception : lien dans une phrase)La règle groupe de 44 px dépasse l'exigence : à conserverMesure DOM de toutes les cibles ; 44 px au doigt
3.2.6 Aide cohérenteAAide (contact, FAQ, chat) au même endroit relatif sur chaque pageBloc « nous revenons vers vous endéans les 48 h » + contactComparaison sur 5 pages
3.3.7 Saisie redondanteANe pas redemander une information déjà saisieDevis, réservation multi-étapesParcours clavier complet
3.3.8 Authentification accessibleAAPas de test cognitif ; collage autorisé ; alternative au CAPTCHAFormulaires, espaces partenairesColler un mot de passe, collage d'un code de vérification
3.3.9 Authentification accessible (renforcée)AAAPas de reconnaissance d'objetsIdem, viséContrôle manuel

4.2 Checklist AA — par famille, avec la preuve exigée

A. Perceptible

#CritèreExigence TEROPreuve exigée
A11.1.1 Contenu non textuelAlt réel et factuel ; alt vide uniquement pour le décoratif ; le monogramme tero a pour alt « tero »Export du listing alt/texte du DOM, 0 alt générique (« image », nom de fichier)
A21.2.2 Sous-titresToute vidéo avec son : sous-titres FR et une piste par langue publiée + transcriptionFichier .vtt livré, test lecteur
A31.2.5 AudiodescriptionSi l'information visuelle est essentielleDécision documentée par vidéo
A41.3.1 Information et relationsStructure sémantique : header/nav/main/aside/footer, listes réelles, tableaux avec th scope, exactement 1 H1, aucun saut de niveauAudit axe + extraction des titres (le live en compte 2 H1, 0 H2)
A51.3.5 Identification des champsautocomplete sur nom, e-mail, téléphone, adresse, sociétéRevue DOM des formulaires
A61.4.3 Contraste (minimum)§ 2.2 et § 2.4 à la lettre ; placeholder ≥ 4,5:1 ; jamais de placeholder comme labelMatrice de contraste versionnée dans le dépôt
A71.4.4 Redimensionnement200 % de zoom sans perte ni défilement horizontalCapture à 200 % sur 1280 px
A81.4.10 Réadaptation320 px sans défilement horizontal (2 dimensions)Capture 320 px, 0 débordement
A91.4.11 Contraste non textuelBordures de contrôles ≥ 3:1 (#767676), anneaux ≥ 3:1, icônes porteuses de sens ≥ 3:1Mesure : 6 couples minimum
A101.4.12 Espacement du texteInterligne 1,5× ; espacement de paragraphe 2× ; lettrage 0,12em ; mots 0,16em — appliqués par feuille utilisateur, sans perteTest avec CSS de surcharge
A111.4.13 Contenu au survol/focusInfobulles : fermables par Échap, survolables, persistantesTest clavier et souris
A121.4.5 / 1.4.11 Images de texteAucune image de texte porteuse d'information (hors logo)Revue
A13prefers-contrast / forced-colors§ 3.6Capture en contraste élevé Windows

B. Utilisable

#CritèreExigence TEROPreuve exigée
B12.1.1 ClavierTout est atteignable et activable au clavier ; le survol a un équivalent focusParcours clavier complet enregistré (accueil → lieu → formulaire)
B22.1.2 Pas de piège clavierModales fermables par Échap, focus renduTest
B32.2.1 / 2.2.2 TempsAucune limite de temps ; sinon extensibleRevue
B42.3.1 / 2.3.3 Clignotement et mouvementAucun clignotement > 3 Hz ; animations neutralisées sous prefers-reduced-motion ; vidéo non chargée en mouvement réduitTest en préférence système
B52.4.1 Contourner les blocsLien d'évitement visible au focus, en tête, avant le headerTab depuis le chargement : premier arrêt = « Aller au contenu »
B62.4.2 Titre de pageTitre unique, explicite, ≤ 65 caractères, distinct par langueExtraction de tous les title
B72.4.3 Ordre de focusOrdre identique au sens de lecture ; pas de tabindex positifAudit DOM (0 tabindex > 0)
B82.4.4 / 2.4.9 Intitulé du lienIntitulé explicite hors contexte ; « en savoir plus » interdit seulAudit des liens
B92.4.6 En-têtes et étiquettesTitres descriptifs, labels explicites, 1 H1, ordre sans sautExtraction des titres
B102.4.7 Focus visibleAnneau du § 3.3, jamais suppriméCapture des 8 contextes
B112.4.11 (2.2)§ 4.1Test header collant
B122.5.1 / 2.5.2 Gestes et annulationAucun geste multipoint obligatoire ; l'action se déclenche au relâchement et peut être annuléeRevue
B132.5.3 Intitulé dans le nomLe texte visible est contenu dans le nom accessibleAudit (bouton « Réserver » avec aria-label différent = échec)
B142.5.4 Action par mouvementAucune action déclenchée par secousse/inclinaisonRevue
B152.5.7 / 2.5.8 (2.2)§ 4.1Mesure DOM des cibles
B162.1.4 Raccourcis clavierAucun raccourci à une touche non désactivableRevue
B17Langue de la pagelang par page : fr-BE / nl-BE / en-GB (aujourd'hui fr-FR sur un site belge)Extraction du html lang sur 3 langues

C. Compréhensible

#CritèreExigence TEROPreuve exigée
C13.1.1 Langue de la pageConforme et cohérent avec hreflang (fr, nl, en)Extraction
C23.1.2 Langue d'un passagelang sur tout passage dans une autre langue (noms propres exclus)Audit
C33.2.1 / 3.2.2 ContexteAucun changement de contexte au focus ou à la saisieTest
C43.2.3 / 3.2.4 Navigation cohérenteOrdre de navigation identique sur toutes les pages et toutes les languesComparaison de 5 pages × 3 langues
C53.2.6 (2.2) Aide cohérente§ 4.1Comparaison
C63.3.1 Identification des erreursL'erreur est textuelle, liée au champ (aria-describedby), aria-invalid="true", cause et correction1 formulaire testé par type
C73.3.2 Étiquettes et instructionsLabel visible et lié ; jamais le placeholder pour label ; format attendu annoncéRevue DOM
C83.3.3 Suggestion après erreurExemple conforme : « Le téléphone doit être au format +32 4XX XX XX XX »Capture
C93.3.4 Prévention (financier)Récapitulatif, révision, confirmation avant paiement/réservation engageanteParcours
C103.3.7 / 3.3.8 / 3.3.9 (2.2)§ 4.1Parcours clavier

D. Robuste

#CritèreExigence TEROPreuve exigée
D14.1.2 Nom, rôle, valeurComposants maison (accordéon, onglets, carrousel, menu) : rôle et états ARIA correctsAudit axe + test lecteur d'écran
D24.1.3 Messages d'étatErreur, succès, chargement annoncés par role="status" / role="alert" / aria-liveTest NVDA/VoiceOver
D3Lecteurs d'écranParcours complet NVDA + Firefox (Windows) et VoiceOver + Safari (macOS/iOS)Compte rendu de test daté
D4Zoom texte seul200 % sans perteCapture

4.3 Portes CI obligatoires (à ajouter à § 16.2, aujourd'hui 0/8)

PorteOutilSeuil de refus
P1axe-core (ou @axe-core/cli / playwright-axe) sur les 5 gabarits × 3 langues0 violation de niveau serious/critical
P2Lighthouse (accessibilité)100 sur chaque gabarit
P3Comptage de couleurs / tailles / rayons introduitsToute valeur hors § 2.1/2.2 et hors rampe → échec
P4Matrice de contraste générée et versionnéeTout couple < 4,5:1 (texte) ou < 3:1 (non-texte) → échec
P5Budget de poids (size-limit / Lighthouse CI budgets)CSS > 45 Ko brotli, JS > 70 Ko brotli, polices > 54 Ko → échec
P6Structure de titres≠ 1 H1, ou saut de niveau → échec
P7Largeurs de capture320 / 360 / 390 / 768 / 1024 / 1440 — 0 débordement horizontal
P8tabindex positif, outline: none, aria-label divergent du texte visibleÉchec

4.4 Anti-patterns d'accessibilité à ajouter à DESIGN.md § 9

---

5. Performance — budget mesurable et pièges mesurés

5.1 Ce que le site sert aujourd'hui — [MESURE 15/10/2026]

MesureValeurMéthode
Corpus CSS Elementor536 feuilles, 9,1 Moaudit § 3.5
Feuilles CSS déclarées sur l'accueil≥ 34 (HTML tronqué à 100 ko)comptage des link rel=stylesheet
Poids de 10 de ces feuilles, compressées (gzip)170,5 Korequêtes réseau réelles
dont jet-engine frontend.css62,7 Ko (36,8 %)—
dont elementor frontend.min.css54,7 Ko (32,1 %)—
dont mega-menu Elementor Pro19,9 Ko—
dont post-4246.css15,3 Ko—
dont post-6.css — le kit de palette/typo du groupe3,8 Kole socle de marque pèse 2 % du CSS
dont jet-theme-core frontend.css0 octet (fichier servi vide)requête inutile
Scripts externes10 (dont jQuery 3.7.1 + jquery-migrate 3.4.1, Cookiebot, Brevo SDK, WonderPush) + 12 inlineextraction
Polices4 woff2 (400/500/600/700), font-display: auto, 0 préchargement@font-face + link rel=preload
Poids des 4 graisses Almarose18,0 + 17,9 + 18,1 + 16,2 = 70,2 Kofichiers du miroir local
Images (100 premiers ko)9 img, 0 loading=lazy, 0 srcset, 9/9 avec width+height ✅extraction
Indices de préconnexion19 dns-prefetch, 0 preconnectsur-déclaration inutile
Styles inline14 blocs style dans les 100 premiers koextraction
og:imageannoncé 800 × 534, servi 1024 × 683audit § 5.5, confirmé
Structure de titres (100 premiers ko)2 H1, 0 H2, 0 H3extraction
langfr-FR (site belge, hreflang fr)extraction

Lecture : la dette n'est pas la marque — le kit de palette pèse 3,8 Ko. La dette est

le framework (jet-engine + Elementor + mega-menu = 137 Ko compressés pour 10 feuilles sur ≥ 34).

Le socle TERO peut et doit viser ≤ 45 Ko brotli tout compris, soit un tiers de ce que sert

aujourd'hui une fraction de l'accueil. [RÈGLE]

5.2 Budget cible — à inscrire dans § 11

RessourcePlafondMesure actuelleContrôle
CSS (brotli, 1re visite, toutes feuilles)≤ 45 Ko · ≤ 3 requêtes · 1 seul fichier bloquant≥ 170,5 Ko pour 10 des ≥ 34 feuillessize-limit / Lighthouse CI budgets
JS (brotli)≤ 70 Ko · ≤ 4 requêtes · 0 jQuery10 scripts externes + jQuery + migrateBundle analyzer
Polices≤ 3 woff2 = 54 Ko · 1 seul preload (graisse du H1) · font-display: swap · size-adjust4 woff2 = 70,2 Ko, display auto, 0 preloadRequête réseau + capture LCP
ImagesHero ≤ 150 Ko AVIF · vignette ≤ 40 Ko · srcset + sizes sur 100 % des images0 srcset mesuré, 1024 × 683 annoncé 800 × 534Audit d'images
Requêtes totales≤ 35≥ 34 CSS + 10 JS + tiersDevTools / WebPageTest
Tiers0 requête tierce avant consentementCookiebot + Brevo + WonderPush chargésAnalyse réseau à froid
TTFB≤ 500 ms p75 mobilenon mesuréCrUX / WebPageTest
LCP≤ 1,5 s p75 mobile terrainnon mesuréCrUX, pas Lighthouse labo
INP≤ 200 ms p75 mobile terrainnon mesuréCrUX
CLS≤ 0,1 (viser ≤ 0,02 avec repli métrique)non mesuréCrUX
Cacheimmutable, max-age=31536000 sur tout asset hachéà vérifierEn-têtes
Compressionbrotli (gzip en repli)gzip serviEn-têtes
TBT / tâches longues≤ 200 ms · aucune tâche > 100 ms avant interaction—Lighthouse

Précision importante [RÈGLE] : la cible LCP < 1,5 s du groupe est plus stricte que le

seuil « bon » de Google (≤ 2,5 s). Elle n'est opposable que si elle est mesurée **au p75 sur le

terrain (CrUX / RUM)**, pas en laboratoire. Sinon elle devient un chiffre invérifiable. À inscrire

explicitement : « LCP ≤ 1,5 s au p75 mobile, données terrain, calculées sur 28 jours ».

5.3 Polices — le levier le plus rentable

conservé que si un usage réel est mesuré ; sinon il sort du socle (−18 Ko). [RÈGLE]

ij, ij) ; jamais de sous-ensemble latin seul sur un site FR/NL/EN.

concurrence de la photo — c'est le LCP sur tero.be. [RÈGLE]

@font-face{font-family:"Almarose Fallback";src:local("Arial");size-adjust:…;ascent-override:…;}

Les valeurs se mesurent (une fois) avec le font-metrics tool, puis se figent. [RÈGLE]

font-display: swap, préchargée uniquement sur les pages qui l'utilisent. Sans arbitrage :

non chargée.

5.4 Images et LCP

préchargeable, non indexable), loading="lazy" sur le hero, image redimensionnée par le CSS.

≤ 150 Ko.

à rien. Mesure de référence sur le projet padel : 1 209 Ko d'images sur une page en 390 px

avec une seule taille de fichier par image. [MESURE — projet padel, non transposée au groupe]

(9/9 mesurées) ✅ — c'est à maintenir dans le socle.

decoding="async" hors LCP.

tero-entite-sujet-largeur.ext (§ 15) conservé.

5.5 INP et JavaScript

−1 requête bloquante).

l'accueil. Un SDK de push (WonderPush) est un coût d'INP et un sujet RGPD — à trancher.

[À VALIDER CLIENT]

requestAnimationFrame court.

principal : content-visibility sous le pli, IntersectionObserver plutôt que scroll listener.

fois, écouteurs posés en double → INP et focus dégradés).

5.6 CLS

consultent »).

5.7 Protocole de mesure opposable

VérificationCommande / outilPreuve à joindre
Poids et budgetLighthouse CI avec assert.budgets (resourceSizes / resourceCounts)Rapport JSON daté
Web Vitals terrainPageSpeed Insights API (CrUX) p75 mobileCapture 28 jours
Poids réel des polices/imagesOnglet réseau, filtre Font/ImgCapture
TiersListe des domaines tiers de la 1re visiteCapture
CompressionEn-têtes content-encodingCapture
Structureaxe + extraction des titresRapport JSON
ContrasteMatrice générée par script (§ 2.1)Fichier versionné

---

6. Mode sombre — décision et construction

Recommandation : ne pas livrer de thème sombre global au lancement. [RÈGLE proposée]

Motifs : (1) aucun signal de marque ni de demande mesurée ; (2) le site groupe est **noir et blanc

sur fond blanc, la « bande profonde » existe déjà comme variante de section** ; (3) un thème

sombre double la matrice de contraste, la campagne de captures et la QA images.

[À VALIDER CLIENT — question à trancher, avec le coût.]

Trois choses sont néanmoins obligatoires dès maintenant [RÈGLE] :

assombrissent nativement champs, listes déroulantes et barres de défilement — sans contrôle.

.surface-inverse porte --surface: #000000, --surface-alt: #212121, --text: #FFFFFF,

--text-secondary: #B9B9B9, --border: #767676, --accent: #FAD282, --focus-ring: #FFFFFF,

--focus-halo: #000000. Le jour où le client dit oui, le thème sombre devient un **échange de

jetons**, pas une refonte.

(déjà prévu § 4.2.5).

Si le client valide le mode sombre, la matrice à respecter est la suivante (colonnes #000000 et

#212121 du § 2.3) : texte #FFFFFF (21,00 / 16,10), secondaire #B9B9B9 (10,70 / 8,21), accent

#FAD282 (14,61 / 11,20) ou #00B7FF (9,22 / 7,07), bordure #767676 (4,62 / 3,55), erreur = badge

terracotta + texte blanc (5,77). Interdits en sombre : pétrole (2,21 / 1,69), teal en texte

(3,87 / 2,97), terracotta en texte (3,64 / 2,79), encre douce (1,64 / 1,26).

Coût à annoncer : **+1 matrice de contraste, +6 captures par gabarit, +1 test lecteur d'écran,

+1 QA images** (≈ +15 à 20 % de la charge de recette). [RÈGLE]

---

7. Limites de cette étude

comptages d'assets sont des minorants (≥ 34 feuilles CSS, ≥ 10 scripts).

rendus : une opacité, un voile photo ou un dégradé peut modifier le contraste réel. La

vérification au navigateur reste obligatoire (§ 5.7).

règle « version blanche + voile sombre » (§ 4.2.5) doit être mesurée au pixel sur chaque

visuel portant du texte.

anti-bot : HTTP 403 hors navigateur) : à refaire en WebPageTest ou Lighthouse CI.

LCP/INP/CLS restent à instrumenter avant d'être opposables.

sombre » repose sur l'absence de demande mesurée, pas sur un comptage d'utilisateurs.

---

DELTA A INTEGRER DANS LA CHARTE

design-tokens.json (brand.wordmarkCase) : le mot-symbole officiel est tero, en minuscules

(_audit/logo-tero-2025.svg) ; Tero = graphie rédactionnelle. Remplacer toute mention de

« mot-symbole TERO ».

brand.logoForbidden) : le glyphe est le o stylisé (anneau plein + barre horizontale sous

l'anneau) ; il reste interdit comme Organization.logo, mais devient utilisable en pastille avec

alt = « tero ».

#B9B9B9 comme jeton « désactivé » uniquement** ; interdire #B9B9B9 pour placeholders, libellés

et mentions (SC 1.4.3, preuve : 1,96:1).

contre ses fonds adjacents ; #D9D9D9 et #E5E6E5 sont décoratifs et ne délimitent jamais un

contrôle » (SC 1.4.11, preuve : 1,41:1 et 1,13:1).

#FFFFFF sur fonds clairs ; inverse sur bandes profondes), avec les 6 compléments de § 3.3

(épaisseur ≥ 2 px, offset ≥ 2 px, pas de rognage, scroll-margin, retour de focus, inert).

design-tokens.json) : teal interdit sur #212121 (2,97:1) ; sur #000000 **graphique

décoratif uniquement** (3:1), jamais en texte.

= texte blanc ; famille B (sable, rose poudré, cyan, rose vif, #B9B9B9, #D9D9D9) = texte noir,

jamais en couleur de texte sur fond clair.

texte sur #D9D9D9 (4,09) ; interdire pétrole sur toute bande profonde (2,21 / 1,69)**.

≥ 18,66 px en graisse 700 — et non « ≥ 24 px gras ».

surface-inverse, text, text-secondary, text-muted, text-disabled, text-inverse,

text-inverse-secondary, border, border-field, border-inverse, accent, accent-hover,

accent-on-dark, focus-ring, focus-halo, success, warning, error, info, link, link-visited) à

tokens.css et design-tokens.json.

les isoler dans un fichier de résorption (un jeton exposé finit utilisé).

noir ; erreur = terracotta + texte blanc ; information = pétrole + texte blanc ; et

l'interdiction pour sable, rose poudré, cyan, rose vif, #B9B9B9, #D9D9D9 de porter un état en

couleur de texte.

une icône distincte + un libellé (SC 1.4.1), et **tout lien en ligne dans un paragraphe est

souligné en permanence** (§ 3.5).

design-tokens.json, avec renvoi à la question client n° 2 (preuves : 3,20:1 et 1,20:1 sur blanc).

2.4.11, 2.4.12, 2.4.13, 2.5.7, 2.5.8, 3.2.6, 3.3.7, 3.3.8, 3.3.9, avec portée TERO et test.

aujourd'hui un résumé de 9 puces, sans preuve, sans vidéo, sans zoom, sans 320 px, sans

autocomplete, sans espacement du texte, sans contenu au survol, sans annulation de pointeur.

320 / 360 / 390 / 768 / 1024 / 1440 (SC 1.4.10 Reflow).

(§ 16.2), avec seuils de refus : axe = 0 violation, Lighthouse a11y = 100, 1 seul H1, matrice de

contraste versionnée, budget de poids, 0 tabindex positif, 0 outline: none.

≤ 3 requêtes, JS ≤ 70 Ko / ≤ 4 requêtes / 0 jQuery, polices ≤ 3 woff2 = 54 Ko avec **1 seul

preload**, images hero ≤ 150 Ko AVIF avec srcset + sizes, ≤ 35 requêtes, 0 tiers avant

consentement, TTFB ≤ 500 ms, cache immutable 1 an, brotli.

plus stricte que le seuil Google de 2,5 s, donc invérifiable en laboratoire seul.

l'écart mesuré : le site sert aujourd'hui font-display: auto × 4 et 0 preload.

(−18 Ko ; les 4 graisses pèsent 70,2 Ko).

aujourd'hui sur l'accueil (Cookiebot, Brevo SDK, WonderPush) comme points à trancher avec le

client (RGPD + INP).

utilisé comme label ; état signalé par la couleur seule ; texte posé sur un fond non conforme.

relative W3C » (et non 2.1), et requalifier #323232 dans l'audit (§ 3.5) comme **neutre

adopté** par la charte, non comme dérive.

fr / nl / en (le live sert fr-FR sur un site belge), et lang sur tout passage alloglotte.

prefers-reduced-motion: reduce, aucune animation et la vidéo n'est pas chargée (poster

seul) — la règle existe sur le projet padel, elle manque au groupe.

son, dans une piste par langue publiée.

formalisé comme jeu de jetons complet, et décision client explicite avant tout

développement de thème sombre (coût : +15 à 20 % de recette).

dépassé) et 44 × 44 px comme règle de marque, avec l'exception explicite du lien en ligne

dans une phrase (ne pas étirer le corps de texte pour atteindre 44 px).