diff --git a/messages/de.json b/messages/de.json
index ce28bb09c..43740d2e4 100644
--- a/messages/de.json
+++ b/messages/de.json
@@ -35,7 +35,8 @@
"showPassword": "Passwort anzeigen",
"hidePassword": "Passwort verbergen",
"learnMore": "Mehr erfahren",
- "dismiss": "Schließen"
+ "dismiss": "Schließen",
+ "moreInfo": "Mehr Informationen"
},
"doctorReport": {
"title": "Gesundheitsbericht",
@@ -750,7 +751,8 @@
"sectionFactors": "Faktoren",
"sectionNoteDetails": "Notiz & Details",
"quickTagsHelp": "Häufig genutzte Tags – ein Tipp genügt",
- "quickTagsExpand": "Weitere"
+ "quickTagsExpand": "Weitere",
+ "loadError": "Stimmungseinträge konnten nicht geladen werden."
},
"medications": {
"title": "Medikamente",
@@ -1852,7 +1854,20 @@
"sat": "Samstag",
"sun": "Sonntag"
},
- "rangeBand": "Bereich"
+ "rangeBand": "Bereich",
+ "a11y": {
+ "summary": "{metric}-Diagramm. Bereich {min} bis {max}, aktuell {latest}, Trend {trend}.",
+ "noData": "{metric}-Diagramm. Keine Daten verfügbar.",
+ "trendUp": "steigend",
+ "trendDown": "fallend",
+ "trendFlat": "gleichbleibend",
+ "scatterSummary": "Korrelationsdiagramm, {count} Punkte: {xLabel} gegen {yLabel}.",
+ "scatterNoData": "Korrelationsdiagramm {xLabel} gegen {yLabel}. Keine Daten verfügbar.",
+ "moodHeatmap": "Stimmungs-Heatmap von {start} bis {end}, {days} Tage erfasst.",
+ "moodHeatmapEmpty": "Stimmungs-Heatmap, noch keine Tage erfasst.",
+ "complianceHeatmap": "Heatmap zur Medikamenteneinnahme von {start} bis {end}, {days} aktive Tage.",
+ "complianceHeatmapEmpty": "Heatmap zur Medikamenteneinnahme, noch keine aktiven Tage."
+ }
},
"chart": {
"overlay": {
@@ -6173,7 +6188,9 @@
"resetToDefault": "Auf Standard zurücksetzen",
"saveSuccess": "Zielbereich aktualisiert",
"saveError": "Zielbereich konnte nicht gespeichert werden",
- "resetSuccess": "Zielbereich auf Standard zurückgesetzt"
+ "resetSuccess": "Zielbereich auf Standard zurückgesetzt",
+ "validationOrder": "Der Minimalwert muss unter dem Maximalwert liegen.",
+ "validationBounds": "Werte innerhalb des unten angegebenen Bereichs eingeben."
},
"currentValue": "Aktuell: {value} {unit}",
"targetRangeValue": "Zielbereich: {min}–{max} {unit}",
@@ -6831,7 +6848,8 @@
"empty": "Keine anstehenden Vorsorge-Erinnerungen.",
"openLink": "Vorsorge öffnen"
},
- "showMeasurements": "Messergebnisse anzeigen"
+ "showMeasurements": "Messergebnisse anzeigen",
+ "loadError": "Erinnerungen konnten nicht geladen werden."
},
"moduleList": {
"viewToggleLabel": "Ansicht",
@@ -7312,7 +7330,8 @@
"BLOOD_PRESSURE_DIA": "Diastolic blood pressure",
"PULSE": "Pulse",
"WEIGHT": "Weight"
- }
+ },
+ "listLoadError": "Episoden konnten nicht geladen werden."
},
"coach": {
"reminderSuggestion": {
@@ -7372,5 +7391,12 @@
"glucoseHighDoctor": "Zwei aktuelle Messungen lagen bei {value} mg/dL oder höher. Miss erneut, trink ausreichend und kontaktiere möglichst bald deine Ärztin oder deinen Arzt, wenn es so hoch bleibt.",
"glucoseHighEmergency": "Zwei aktuelle Messungen lagen bei {value} mg/dL oder höher und du hast Beschwerden angegeben. Bei Erbrechen, schneller Atmung oder Verwirrtheit sofort den Notruf wählen."
}
+ },
+ "version": {
+ "updateAvailable": {
+ "title": "Eine neue Version ist verfügbar",
+ "reload": "Neu laden",
+ "dismiss": "Schließen"
+ }
}
}
diff --git a/messages/en.json b/messages/en.json
index 14fa8b085..2ebe72db7 100644
--- a/messages/en.json
+++ b/messages/en.json
@@ -35,7 +35,8 @@
"showPassword": "Show password",
"hidePassword": "Hide password",
"learnMore": "Learn more",
- "dismiss": "Dismiss"
+ "dismiss": "Dismiss",
+ "moreInfo": "More information"
},
"doctorReport": {
"title": "Health Report",
@@ -750,7 +751,8 @@
"sectionFactors": "Factors",
"sectionNoteDetails": "Note & details",
"quickTagsHelp": "Your frequent tags — one tap",
- "quickTagsExpand": "More"
+ "quickTagsExpand": "More",
+ "loadError": "Could not load your mood entries."
},
"medications": {
"title": "Medications",
@@ -1852,7 +1854,20 @@
"sat": "Saturday",
"sun": "Sunday"
},
- "rangeBand": "Range"
+ "rangeBand": "Range",
+ "a11y": {
+ "summary": "{metric} chart. Range {min} to {max}, latest {latest}, trend {trend}.",
+ "noData": "{metric} chart. No data available.",
+ "trendUp": "rising",
+ "trendDown": "falling",
+ "trendFlat": "steady",
+ "scatterSummary": "Correlation chart, {count} points plotting {xLabel} against {yLabel}.",
+ "scatterNoData": "Correlation chart of {xLabel} against {yLabel}. No data available.",
+ "moodHeatmap": "Mood heatmap from {start} to {end}, {days} days logged.",
+ "moodHeatmapEmpty": "Mood heatmap, no days logged yet.",
+ "complianceHeatmap": "Medication compliance heatmap from {start} to {end}, {days} active days.",
+ "complianceHeatmapEmpty": "Medication compliance heatmap, no active days yet."
+ }
},
"chart": {
"overlay": {
@@ -6173,7 +6188,9 @@
"resetToDefault": "Reset to default",
"saveSuccess": "Target range updated",
"saveError": "Could not save the target range",
- "resetSuccess": "Target range reset to default"
+ "resetSuccess": "Target range reset to default",
+ "validationOrder": "The minimum must be lower than the maximum.",
+ "validationBounds": "Enter values within the allowed range shown below."
},
"currentValue": "Current: {value} {unit}",
"targetRangeValue": "Target: {min}–{max} {unit}",
@@ -6831,7 +6848,8 @@
"empty": "No upcoming checkup reminders.",
"openLink": "Open checkups"
},
- "showMeasurements": "Show measurements"
+ "showMeasurements": "Show measurements",
+ "loadError": "Could not load your reminders."
},
"moduleList": {
"viewToggleLabel": "View",
@@ -7312,7 +7330,8 @@
"BLOOD_PRESSURE_DIA": "Diastolic blood pressure",
"PULSE": "Pulse",
"WEIGHT": "Weight"
- }
+ },
+ "listLoadError": "Could not load your episodes."
},
"coach": {
"reminderSuggestion": {
@@ -7372,5 +7391,12 @@
"glucoseHighDoctor": "Two recent readings were {value} mg/dL or higher. Re-check, hydrate, and contact your doctor as soon as possible if it stays this high.",
"glucoseHighEmergency": "Two recent readings were {value} mg/dL or higher and you noted symptoms. If you have vomiting, fast breathing, or confusion, call emergency services now."
}
+ },
+ "version": {
+ "updateAvailable": {
+ "title": "A new version is available",
+ "reload": "Reload",
+ "dismiss": "Dismiss"
+ }
}
}
diff --git a/messages/es.json b/messages/es.json
index ce2ee6de9..bbbaa6b8b 100644
--- a/messages/es.json
+++ b/messages/es.json
@@ -35,7 +35,8 @@
"showPassword": "Mostrar contraseña",
"hidePassword": "Ocultar contraseña",
"learnMore": "Más información",
- "dismiss": "Descartar"
+ "dismiss": "Descartar",
+ "moreInfo": "Más información"
},
"doctorReport": {
"title": "Informe de salud",
@@ -750,7 +751,8 @@
"sectionFactors": "Factores",
"sectionNoteDetails": "Nota y detalles",
"quickTagsHelp": "Tus etiquetas frecuentes: un toque",
- "quickTagsExpand": "Más"
+ "quickTagsExpand": "Más",
+ "loadError": "No se pudieron cargar tus registros de estado de ánimo."
},
"medications": {
"title": "Medicamentos",
@@ -1852,7 +1854,20 @@
"sat": "Sábado",
"sun": "Domingo"
},
- "rangeBand": "Rango"
+ "rangeBand": "Rango",
+ "a11y": {
+ "summary": "Gráfico de {metric}. Rango de {min} a {max}, último {latest}, tendencia {trend}.",
+ "noData": "Gráfico de {metric}. No hay datos disponibles.",
+ "trendUp": "en aumento",
+ "trendDown": "en descenso",
+ "trendFlat": "estable",
+ "scatterSummary": "Gráfico de correlación, {count} puntos que comparan {xLabel} con {yLabel}.",
+ "scatterNoData": "Gráfico de correlación de {xLabel} frente a {yLabel}. No hay datos disponibles.",
+ "moodHeatmap": "Mapa de calor de estado de ánimo de {start} a {end}, {days} días registrados.",
+ "moodHeatmapEmpty": "Mapa de calor de estado de ánimo, aún no hay días registrados.",
+ "complianceHeatmap": "Mapa de calor de cumplimiento de medicación de {start} a {end}, {days} días activos.",
+ "complianceHeatmapEmpty": "Mapa de calor de cumplimiento de medicación, aún no hay días activos."
+ }
},
"chart": {
"overlay": {
@@ -6173,7 +6188,9 @@
"resetToDefault": "Restablecer por defecto",
"saveSuccess": "Rango objetivo actualizado",
"saveError": "No se ha podido guardar el rango objetivo",
- "resetSuccess": "Rango objetivo restablecido por defecto"
+ "resetSuccess": "Rango objetivo restablecido por defecto",
+ "validationOrder": "El mínimo debe ser inferior al máximo.",
+ "validationBounds": "Introduce valores dentro del rango permitido que se muestra debajo."
},
"currentValue": "Actual: {value} {unit}",
"targetRangeValue": "Rango objetivo: {min}–{max} {unit}",
@@ -6831,7 +6848,8 @@
"empty": "No hay revisiones próximas.",
"openLink": "Abrir revisiones"
},
- "showMeasurements": "Ver mediciones"
+ "showMeasurements": "Ver mediciones",
+ "loadError": "No se pudieron cargar tus recordatorios."
},
"moduleList": {
"viewToggleLabel": "Vista",
@@ -7312,7 +7330,8 @@
"BLOOD_PRESSURE_DIA": "Diastolic blood pressure",
"PULSE": "Pulse",
"WEIGHT": "Weight"
- }
+ },
+ "listLoadError": "No se pudieron cargar tus episodios."
},
"coach": {
"reminderSuggestion": {
@@ -7372,5 +7391,12 @@
"glucoseHighDoctor": "Dos lecturas recientes fueron de {value} mg/dL o más. Vuelve a medir, hidrátate y contacta a tu médico cuanto antes si sigue así de alta.",
"glucoseHighEmergency": "Dos lecturas recientes fueron de {value} mg/dL o más e indicaste síntomas. Si tienes vómitos, respiración rápida o confusión, llama a emergencias ya."
}
+ },
+ "version": {
+ "updateAvailable": {
+ "title": "Hay una nueva versión disponible",
+ "reload": "Recargar",
+ "dismiss": "Descartar"
+ }
}
}
diff --git a/messages/fr.json b/messages/fr.json
index 69f085b74..b3002dc3e 100644
--- a/messages/fr.json
+++ b/messages/fr.json
@@ -35,7 +35,8 @@
"showPassword": "Afficher le mot de passe",
"hidePassword": "Masquer le mot de passe",
"learnMore": "En savoir plus",
- "dismiss": "Ignorer"
+ "dismiss": "Ignorer",
+ "moreInfo": "Plus d'informations"
},
"doctorReport": {
"title": "Rapport de santé",
@@ -750,7 +751,8 @@
"sectionFactors": "Facteurs",
"sectionNoteDetails": "Note et détails",
"quickTagsHelp": "Vos tags fréquents — en un geste",
- "quickTagsExpand": "Plus"
+ "quickTagsExpand": "Plus",
+ "loadError": "Impossible de charger vos entrées d'humeur."
},
"medications": {
"title": "Médicaments",
@@ -1852,7 +1854,20 @@
"sat": "Samedi",
"sun": "Dimanche"
},
- "rangeBand": "Plage"
+ "rangeBand": "Plage",
+ "a11y": {
+ "summary": "Graphique {metric}. Plage de {min} à {max}, dernier {latest}, tendance {trend}.",
+ "noData": "Graphique {metric}. Aucune donnée disponible.",
+ "trendUp": "en hausse",
+ "trendDown": "en baisse",
+ "trendFlat": "stable",
+ "scatterSummary": "Graphique de corrélation, {count} points comparant {xLabel} et {yLabel}.",
+ "scatterNoData": "Graphique de corrélation de {xLabel} et {yLabel}. Aucune donnée disponible.",
+ "moodHeatmap": "Carte thermique de l'humeur du {start} au {end}, {days} jours enregistrés.",
+ "moodHeatmapEmpty": "Carte thermique de l'humeur, aucun jour enregistré pour l'instant.",
+ "complianceHeatmap": "Carte thermique d'observance des médicaments du {start} au {end}, {days} jours actifs.",
+ "complianceHeatmapEmpty": "Carte thermique d'observance des médicaments, aucun jour actif pour l'instant."
+ }
},
"chart": {
"overlay": {
@@ -6173,7 +6188,9 @@
"resetToDefault": "Restaurer la valeur par défaut",
"saveSuccess": "Plage cible mise à jour",
"saveError": "Impossible d’enregistrer la plage cible",
- "resetSuccess": "Plage cible réinitialisée"
+ "resetSuccess": "Plage cible réinitialisée",
+ "validationOrder": "Le minimum doit être inférieur au maximum.",
+ "validationBounds": "Saisissez des valeurs dans la plage autorisée indiquée ci-dessous."
},
"currentValue": "Actuel : {value} {unit}",
"targetRangeValue": "Plage cible : {min}–{max} {unit}",
@@ -6831,7 +6848,8 @@
"empty": "Aucun rappel d’examen à venir.",
"openLink": "Ouvrir les examens"
},
- "showMeasurements": "Afficher les mesures"
+ "showMeasurements": "Afficher les mesures",
+ "loadError": "Impossible de charger vos rappels."
},
"moduleList": {
"viewToggleLabel": "Affichage",
@@ -7312,7 +7330,8 @@
"BLOOD_PRESSURE_DIA": "Diastolic blood pressure",
"PULSE": "Pulse",
"WEIGHT": "Weight"
- }
+ },
+ "listLoadError": "Impossible de charger vos épisodes."
},
"coach": {
"reminderSuggestion": {
@@ -7372,5 +7391,12 @@
"glucoseHighDoctor": "Deux mesures récentes étaient à {value} mg/dL ou plus. Remesure, hydrate-toi et contacte ton médecin dès que possible si cela reste aussi élevé.",
"glucoseHighEmergency": "Deux mesures récentes étaient à {value} mg/dL ou plus et tu as signalé des symptômes. En cas de vomissements, de respiration rapide ou de confusion, appelle les secours immédiatement."
}
+ },
+ "version": {
+ "updateAvailable": {
+ "title": "Une nouvelle version est disponible",
+ "reload": "Recharger",
+ "dismiss": "Ignorer"
+ }
}
}
diff --git a/messages/it.json b/messages/it.json
index 60e5288d4..2a234387f 100644
--- a/messages/it.json
+++ b/messages/it.json
@@ -35,7 +35,8 @@
"showPassword": "Mostra password",
"hidePassword": "Nascondi password",
"learnMore": "Scopri di più",
- "dismiss": "Ignora"
+ "dismiss": "Ignora",
+ "moreInfo": "Maggiori informazioni"
},
"doctorReport": {
"title": "Rapporto sanitario",
@@ -750,7 +751,8 @@
"sectionFactors": "Fattori",
"sectionNoteDetails": "Nota e dettagli",
"quickTagsHelp": "I tuoi tag frequenti: un tocco",
- "quickTagsExpand": "Altro"
+ "quickTagsExpand": "Altro",
+ "loadError": "Impossibile caricare le voci dell'umore."
},
"medications": {
"title": "Farmaci",
@@ -1852,7 +1854,20 @@
"sat": "Sabato",
"sun": "Domenica"
},
- "rangeBand": "Intervallo"
+ "rangeBand": "Intervallo",
+ "a11y": {
+ "summary": "Grafico {metric}. Intervallo da {min} a {max}, ultimo {latest}, tendenza {trend}.",
+ "noData": "Grafico {metric}. Nessun dato disponibile.",
+ "trendUp": "in aumento",
+ "trendDown": "in calo",
+ "trendFlat": "stabile",
+ "scatterSummary": "Grafico di correlazione, {count} punti che confrontano {xLabel} con {yLabel}.",
+ "scatterNoData": "Grafico di correlazione di {xLabel} e {yLabel}. Nessun dato disponibile.",
+ "moodHeatmap": "Mappa di calore dell'umore dal {start} al {end}, {days} giorni registrati.",
+ "moodHeatmapEmpty": "Mappa di calore dell'umore, nessun giorno ancora registrato.",
+ "complianceHeatmap": "Mappa di calore dell'aderenza ai farmaci dal {start} al {end}, {days} giorni attivi.",
+ "complianceHeatmapEmpty": "Mappa di calore dell'aderenza ai farmaci, nessun giorno attivo."
+ }
},
"chart": {
"overlay": {
@@ -6173,7 +6188,9 @@
"resetToDefault": "Ripristina predefinito",
"saveSuccess": "Range obiettivo aggiornato",
"saveError": "Impossibile salvare il range obiettivo",
- "resetSuccess": "Range obiettivo ripristinato"
+ "resetSuccess": "Range obiettivo ripristinato",
+ "validationOrder": "Il minimo deve essere inferiore al massimo.",
+ "validationBounds": "Inserisci valori entro l'intervallo consentito indicato sotto."
},
"currentValue": "Attuale: {value} {unit}",
"targetRangeValue": "Range obiettivo: {min}–{max} {unit}",
@@ -6831,7 +6848,8 @@
"empty": "Nessun promemoria di controllo in arrivo.",
"openLink": "Apri controlli"
},
- "showMeasurements": "Mostra le misurazioni"
+ "showMeasurements": "Mostra le misurazioni",
+ "loadError": "Impossibile caricare i promemoria."
},
"moduleList": {
"viewToggleLabel": "Vista",
@@ -7312,7 +7330,8 @@
"BLOOD_PRESSURE_DIA": "Diastolic blood pressure",
"PULSE": "Pulse",
"WEIGHT": "Weight"
- }
+ },
+ "listLoadError": "Impossibile caricare gli episodi."
},
"coach": {
"reminderSuggestion": {
@@ -7372,5 +7391,12 @@
"glucoseHighDoctor": "Due misurazioni recenti erano di {value} mg/dL o superiori. Rimisura, idratati e contatta il medico al più presto se resta così alta.",
"glucoseHighEmergency": "Due misurazioni recenti erano di {value} mg/dL o superiori e hai segnalato sintomi. In caso di vomito, respiro affannoso o confusione, chiama subito i soccorsi."
}
+ },
+ "version": {
+ "updateAvailable": {
+ "title": "È disponibile una nuova versione",
+ "reload": "Ricarica",
+ "dismiss": "Ignora"
+ }
}
}
diff --git a/messages/pl.json b/messages/pl.json
index 5631b6f90..8d04bfe04 100644
--- a/messages/pl.json
+++ b/messages/pl.json
@@ -35,7 +35,8 @@
"showPassword": "Pokaż hasło",
"hidePassword": "Ukryj hasło",
"learnMore": "Dowiedz się więcej",
- "dismiss": "Odrzuć"
+ "dismiss": "Odrzuć",
+ "moreInfo": "Więcej informacji"
},
"doctorReport": {
"title": "Raport zdrowotny",
@@ -750,7 +751,8 @@
"sectionFactors": "Czynniki",
"sectionNoteDetails": "Notatka i szczegóły",
"quickTagsHelp": "Twoje częste tagi — jedno dotknięcie",
- "quickTagsExpand": "Więcej"
+ "quickTagsExpand": "Więcej",
+ "loadError": "Nie udało się załadować wpisów nastroju."
},
"medications": {
"title": "Leki",
@@ -1852,7 +1854,20 @@
"sat": "Sobota",
"sun": "Niedziela"
},
- "rangeBand": "Zakres"
+ "rangeBand": "Zakres",
+ "a11y": {
+ "summary": "Wykres {metric}. Zakres od {min} do {max}, ostatnio {latest}, trend {trend}.",
+ "noData": "Wykres {metric}. Brak dostępnych danych.",
+ "trendUp": "rosnący",
+ "trendDown": "malejący",
+ "trendFlat": "stały",
+ "scatterSummary": "Wykres korelacji, {count} punktów porównujących {xLabel} z {yLabel}.",
+ "scatterNoData": "Wykres korelacji {xLabel} i {yLabel}. Brak dostępnych danych.",
+ "moodHeatmap": "Mapa cieplna nastroju od {start} do {end}, zarejestrowano {days} dni.",
+ "moodHeatmapEmpty": "Mapa cieplna nastroju, brak zarejestrowanych dni.",
+ "complianceHeatmap": "Mapa cieplna przyjmowania leków od {start} do {end}, {days} aktywnych dni.",
+ "complianceHeatmapEmpty": "Mapa cieplna przyjmowania leków, brak aktywnych dni."
+ }
},
"chart": {
"overlay": {
@@ -6173,7 +6188,9 @@
"resetToDefault": "Przywróć wartość domyślną",
"saveSuccess": "Zakres docelowy zaktualizowany",
"saveError": "Nie udało się zapisać zakresu docelowego",
- "resetSuccess": "Zakres docelowy przywrócono do domyślnego"
+ "resetSuccess": "Zakres docelowy przywrócono do domyślnego",
+ "validationOrder": "Wartość minimalna musi być niższa niż maksymalna.",
+ "validationBounds": "Wprowadź wartości w dozwolonym zakresie podanym poniżej."
},
"currentValue": "Aktualnie: {value} {unit}",
"targetRangeValue": "Zakres docelowy: {min}–{max} {unit}",
@@ -6831,7 +6848,8 @@
"empty": "Brak nadchodzących przypomnień o badaniach.",
"openLink": "Otwórz badania"
},
- "showMeasurements": "Pokaż pomiary"
+ "showMeasurements": "Pokaż pomiary",
+ "loadError": "Nie udało się załadować przypomnień."
},
"moduleList": {
"viewToggleLabel": "Widok",
@@ -7312,7 +7330,8 @@
"BLOOD_PRESSURE_DIA": "Diastolic blood pressure",
"PULSE": "Pulse",
"WEIGHT": "Weight"
- }
+ },
+ "listLoadError": "Nie udało się załadować epizodów."
},
"coach": {
"reminderSuggestion": {
@@ -7372,5 +7391,12 @@
"glucoseHighDoctor": "Dwa ostatnie pomiary wyniosły {value} mg/dL lub więcej. Zmierz ponownie, nawodnij się i jak najszybciej skontaktuj się z lekarzem, jeśli pozostaje tak wysoki.",
"glucoseHighEmergency": "Dwa ostatnie pomiary wyniosły {value} mg/dL lub więcej i zgłosiłeś objawy. W razie wymiotów, przyspieszonego oddechu lub dezorientacji natychmiast zadzwoń po pomoc."
}
+ },
+ "version": {
+ "updateAvailable": {
+ "title": "Dostępna jest nowa wersja",
+ "reload": "Załaduj ponownie",
+ "dismiss": "Odrzuć"
+ }
}
}
diff --git a/src/app/auth/register/page.tsx b/src/app/auth/register/page.tsx
index 4c6173af1..73c1f10a6 100644
--- a/src/app/auth/register/page.tsx
+++ b/src/app/auth/register/page.tsx
@@ -194,7 +194,13 @@ export default function RegisterPage() {
{t("auth.hasAccount")}{" "}
-
+
{t("auth.login")}
diff --git a/src/app/coach/page.tsx b/src/app/coach/page.tsx
index 85870cf99..c956134fc 100644
--- a/src/app/coach/page.tsx
+++ b/src/app/coach/page.tsx
@@ -136,7 +136,7 @@ export default function CoachPage() {
// `env(safe-area-inset-bottom)`) so the docked composer / Stop control
// always clears the nav instead of sitting under it. On `md+` the nav
// is hidden, so the page reclaims the full height below the TopBar.
- className="bg-background -mx-4 -mt-6 -mb-20 flex h-[calc(100dvh-8rem-env(safe-area-inset-bottom,0px))] min-h-[32rem] flex-col overflow-hidden md:-mx-6 md:h-[calc(100dvh-4rem)]"
+ className="bg-background -mx-4 -mt-6 -mb-20 flex h-[calc(100dvh-8rem-env(safe-area-inset-top,0px)-env(safe-area-inset-bottom,0px))] min-h-[32rem] flex-col overflow-hidden md:-mx-6 md:h-[calc(100dvh-4rem)]"
>
{/* `useSearchParams` requires a Suspense boundary so the client-search
bailout never opts the whole route out of static optimisation. */}
diff --git a/src/components/__tests__/version-poller.test.ts b/src/components/__tests__/version-poller.test.ts
index b079fea7a..fb3a6b938 100644
--- a/src/components/__tests__/version-poller.test.ts
+++ b/src/components/__tests__/version-poller.test.ts
@@ -1,12 +1,16 @@
/**
- * Unit tests for the version-poller reload decision.
+ * Unit tests for the version-poller decision.
*
* The guard is keyed on the TARGET (live) version: a repeat mismatch
- * against the SAME version is suppressed (no reload loop on a misset
- * server), but a SECOND deploy in one session moves the live version
- * past the recorded one and the heal flow re-arms. The pre-v1.16.8
- * guard disabled all polling after one attempt, which stranded stale
- * shells on multi-deploy days.
+ * against the SAME version is suppressed (no loop on a misset server),
+ * but a SECOND deploy in one session moves the live version past the
+ * recorded one and the flow re-arms.
+ *
+ * The runtime behaviour — a detected bump surfaces a Reload toast and
+ * never reloads the page on its own — lives in `version-poller.tsx`:
+ * the service-worker eviction + `location.reload()` run only from the
+ * toast action's `onClick`, so an in-progress form or chat draft is
+ * never destroyed unprompted.
*/
import { describe, expect, it } from "vitest";
diff --git a/src/components/admin/backups-section.tsx b/src/components/admin/backups-section.tsx
index 1ec8bbb11..f63244557 100644
--- a/src/components/admin/backups-section.tsx
+++ b/src/components/admin/backups-section.tsx
@@ -467,74 +467,134 @@ export function BackupsSection() {
/>
) : (
-
-
-
-
-
- {t("admin.section.backups.colUser")}
-
-
- {t("admin.section.backups.colType")}
-
-
- {t("admin.section.backups.colSize")}
-
-
- {t("admin.section.backups.colCreatedAt")}
-
-
- {t("admin.section.backups.colActions")}
-
-
-
-
- {rows.map((row, i) => (
-
-
{row.username}
-
-
- {formatBackupType(row.type, t)}
-
-
-
- {formatBytes(row.sizeBytes, fmt)}
-
-
- {fmt.dateTime(row.createdAt)}
-
-
-
-
- restore.mutate(row)}
- />
-
-
+
+ {/* Wide layout: the canonical table. Hidden below `md`, where the
+ five columns push Download / Restore off-screen behind a
+ horizontal scroll; the card list below takes over there. */}
+
+
+
+
+
+ {t("admin.section.backups.colUser")}
+
+
+ {t("admin.section.backups.colType")}
+
+
+ {t("admin.section.backups.colSize")}
+
+
+ {t("admin.section.backups.colCreatedAt")}
+
+
+ {t("admin.section.backups.colActions")}
+
- ))}
-
-
+
+
+ {rows.map((row, i) => (
+
+
{row.username}
+
+
+ {formatBackupType(row.type, t)}
+
+
+
+ {formatBytes(row.sizeBytes, fmt)}
+
+
+ {fmt.dateTime(row.createdAt)}
+
+
+
+
+ restore.mutate(row)}
+ />
+
+
+
+ ))}
+
+
+
+
+ {/* Narrow layout: each backup as a self-contained card with the
+ meta line + a flex-wrapping action row, so Download / Restore
+ stay reachable on a phone instead of scrolling off-screen. */}
+