diff --git a/frontend/src/api/mock/dataset.ts b/frontend/src/api/mock/dataset.ts
index 43d52cd..c6725ae 100644
--- a/frontend/src/api/mock/dataset.ts
+++ b/frontend/src/api/mock/dataset.ts
@@ -210,6 +210,7 @@ export function buildMockState(): MockState {
if (slotIndex % 7 === 0) target = Math.max(1, shift.min_staff - 1);
else if (slotIndex % 5 === 0) target = shift.min_staff;
else if (slotIndex % 3 === 0) target = Math.max(shift.min_staff, shift.ideal_staff - 1);
+ else if (slotIndex % 8 === 0) target = shift.ideal_staff + 2; // sureffectif
const duration = hoursBetween(shift.starts_at, shift.ends_at);
const dateStr = shift.starts_at.slice(0, 10);
diff --git a/frontend/src/i18n/locales/fr.json b/frontend/src/i18n/locales/fr.json
index eb82266..f8cf445 100644
--- a/frontend/src/i18n/locales/fr.json
+++ b/frontend/src/i18n/locales/fr.json
@@ -85,6 +85,7 @@
"grille.legend.critical": "SOUS-EFFECTIF CRITIQUE",
"grille.legend.incomplete": "INCOMPLET",
"grille.legend.complete": "COMPLET",
+ "grille.legend.overstaffed": "SUREFFECTIF",
"grille.positionsCount": "{count} POSTES",
"grille.assignedRequired": "AFFECTÉS / IDÉAL",
"grille.footnote": "Chaque cellule est un créneau. Nombre = bénévoles affectés, / = effectif idéal. Cliquer ouvre le panneau d'affectation à droite.",
diff --git a/frontend/src/pages/GrillePage.tsx b/frontend/src/pages/GrillePage.tsx
index 1d5ba8d..4b4f8bb 100644
--- a/frontend/src/pages/GrillePage.tsx
+++ b/frontend/src/pages/GrillePage.tsx
@@ -83,6 +83,9 @@ export function GrillePage() {