diff --git a/messages/de.json b/messages/de.json
index 9d5e4c563..553ab6c1a 100644
--- a/messages/de.json
+++ b/messages/de.json
@@ -921,6 +921,12 @@
"componentMood": "Stimmung",
"componentCompliance": "Einnahmetreue",
"disclaimer": "Orientierungshilfe — keine ärztliche Bewertung.",
+ "deltaExplainer": {
+ "trigger": "Was bedeutet diese Veränderung?",
+ "title": "So wird die Veränderung berechnet",
+ "description": "Veränderung gegenüber letzter Woche: {delta}",
+ "body": "Der Score kombiniert Blutdruck, Gewicht, Stimmung und Einnahmetreue. Wir vergleichen den heutigen Stand mit demselben Zeitpunkt vor einer Woche. Erfasse eine frische Messung oder einen Stimmungs-Check, um den Wert nach oben zu schubsen."
+ },
"provenance": {
"toggle": "Zusammensetzung",
"weightLabel": "Anteil",
diff --git a/messages/en.json b/messages/en.json
index 8ecd87c26..af3ee8585 100644
--- a/messages/en.json
+++ b/messages/en.json
@@ -921,6 +921,12 @@
"componentMood": "Mood",
"componentCompliance": "Meds",
"disclaimer": "Indicative — not a clinical assessment.",
+ "deltaExplainer": {
+ "trigger": "What does this delta mean?",
+ "title": "How the delta is computed",
+ "description": "Change vs last week: {delta}",
+ "body": "The score combines BP, weight, mood and meds. We compare today's score with the same time last week. Log a fresh reading or a mood check to nudge it up."
+ },
"provenance": {
"toggle": "Driven by",
"weightLabel": "share",
diff --git a/messages/es.json b/messages/es.json
index 4db619488..d1bcb844b 100644
--- a/messages/es.json
+++ b/messages/es.json
@@ -921,6 +921,12 @@
"componentMood": "Estado de ánimo",
"componentCompliance": "Meds",
"disclaimer": "Indicative — not a clinical assessment.",
+ "deltaExplainer": {
+ "trigger": "¿Qué significa este cambio?",
+ "title": "Cómo se calcula el cambio",
+ "description": "Cambio respecto a la semana pasada: {delta}",
+ "body": "La puntuación combina PA, peso, ánimo y adherencia. Comparamos la puntuación de hoy con la del mismo momento de la semana anterior. Registra una medición nueva o una nota de ánimo para empujarla hacia arriba."
+ },
"provenance": {
"toggle": "Compuesto por",
"weightLabel": "peso",
diff --git a/messages/fr.json b/messages/fr.json
index fa16f5ccb..d921873e5 100644
--- a/messages/fr.json
+++ b/messages/fr.json
@@ -921,6 +921,12 @@
"componentMood": "Humeur",
"componentCompliance": "Meds",
"disclaimer": "Indicative — not a clinical assessment.",
+ "deltaExplainer": {
+ "trigger": "Que signifie cet écart ?",
+ "title": "Comment l'écart est calculé",
+ "description": "Écart par rapport à la semaine dernière : {delta}",
+ "body": "Le score combine TA, poids, humeur et observance. Nous comparons le score d'aujourd'hui à celui de la semaine précédente à la même période. Enregistre une nouvelle mesure ou une note d'humeur pour le faire remonter."
+ },
"provenance": {
"toggle": "Composé de",
"weightLabel": "part",
diff --git a/messages/it.json b/messages/it.json
index 482034b86..a1b99a756 100644
--- a/messages/it.json
+++ b/messages/it.json
@@ -921,6 +921,12 @@
"componentMood": "Umore",
"componentCompliance": "Meds",
"disclaimer": "Indicative — not a clinical assessment.",
+ "deltaExplainer": {
+ "trigger": "Cosa significa questa variazione?",
+ "title": "Come si calcola la variazione",
+ "description": "Variazione rispetto alla settimana scorsa: {delta}",
+ "body": "Il punteggio combina PA, peso, umore e aderenza. Confrontiamo il punteggio di oggi con quello dello stesso momento della settimana scorsa. Registra una nuova misurazione o una nota di umore per spingerlo verso l'alto."
+ },
"provenance": {
"toggle": "Composto da",
"weightLabel": "peso",
diff --git a/messages/pl.json b/messages/pl.json
index 07647b3a8..6e12a7bf9 100644
--- a/messages/pl.json
+++ b/messages/pl.json
@@ -921,6 +921,12 @@
"componentMood": "Nastrój",
"componentCompliance": "Meds",
"disclaimer": "Indicative — not a clinical assessment.",
+ "deltaExplainer": {
+ "trigger": "Co oznacza ta zmiana?",
+ "title": "Jak liczona jest ta zmiana",
+ "description": "Zmiana względem ubiegłego tygodnia: {delta}",
+ "body": "Wynik łączy ciśnienie, wagę, nastrój i przyjmowanie leków. Porównujemy dzisiejszy wynik z tym samym momentem tydzień wcześniej. Dodaj świeży pomiar lub wpis o nastroju, żeby pchnąć go w górę."
+ },
"provenance": {
"toggle": "Składa się z",
"weightLabel": "udział",
diff --git a/src/components/insights/__tests__/health-score-delta-explainer.test.tsx b/src/components/insights/__tests__/health-score-delta-explainer.test.tsx
new file mode 100644
index 000000000..4f89d7c1d
--- /dev/null
+++ b/src/components/insights/__tests__/health-score-delta-explainer.test.tsx
@@ -0,0 +1,145 @@
+import { describe, it, expect } from "vitest";
+import { renderToStaticMarkup } from "react-dom/server";
+import { I18nProvider, useTranslations } from "@/lib/i18n/context";
+import { HealthScoreDeltaExplainer } from "../health-score-delta-explainer";
+
+/**
+ * v1.4.28 R3c-Insights — FB-I1 — the "?" affordance next to the delta
+ * line opens a 3-sentence read of which components contributed, what
+ * the comparison window is, and one concrete next step.
+ *
+ * Tests run through SSR so they don't depend on a browser surface.
+ * The popover / sheet body mounts on click on the live page; the
+ * SSR snapshot captures the trigger button (always present) plus a
+ * locale-grounded check that the body copy actually exists in the
+ * translation payload — the load-bearing constraint is "every
+ * locale ships the 3-sentence read", not the popover open animation.
+ */
+
+function ssr(node: React.ReactNode, locale: "en" | "de" = "en") {
+ return renderToStaticMarkup(
+ {node},
+ );
+}
+
+/**
+ * Helper that paints the explainer body via the same `t()` call the
+ * popover uses. If a future refactor drops a locale key the test
+ * fails at the `t()` call site rather than silently rendering the
+ * fallback chevron.
+ */
+function BodyProbe() {
+ const { t } = useTranslations();
+ return (
+