diff --git a/public/index.html b/public/index.html
index a5a1441..e4a50ca 100644
--- a/public/index.html
+++ b/public/index.html
@@ -38,8 +38,6 @@
-
-
@@ -62,6 +60,22 @@
Zum Hauptinhalt springen
+
+
+
diff --git a/public/locales/ar.json b/public/locales/ar.json
index e965958..35e3ed1 100644
--- a/public/locales/ar.json
+++ b/public/locales/ar.json
@@ -868,5 +868,8 @@
"next": "Next",
"done": "Get started",
"skip": "Skip"
+ },
+ "offline": {
+ "banner": "Offline – reconnecting…"
}
-}
+}
\ No newline at end of file
diff --git a/public/locales/de.json b/public/locales/de.json
index c7ab779..9f07956 100644
--- a/public/locales/de.json
+++ b/public/locales/de.json
@@ -888,5 +888,8 @@
"next": "Weiter",
"done": "Loslegen",
"skip": "Überspringen"
+ },
+ "offline": {
+ "banner": "Offline – Verbindung wird wiederhergestellt…"
}
}
diff --git a/public/locales/el.json b/public/locales/el.json
index 320751b..f61fb32 100644
--- a/public/locales/el.json
+++ b/public/locales/el.json
@@ -868,5 +868,8 @@
"next": "Next",
"done": "Get started",
"skip": "Skip"
+ },
+ "offline": {
+ "banner": "Offline – reconnecting…"
}
-}
+}
\ No newline at end of file
diff --git a/public/locales/en.json b/public/locales/en.json
index d258257..58e04be 100644
--- a/public/locales/en.json
+++ b/public/locales/en.json
@@ -869,5 +869,8 @@
"next": "Next",
"done": "Get started",
"skip": "Skip"
+ },
+ "offline": {
+ "banner": "Offline – reconnecting…"
}
-}
+}
\ No newline at end of file
diff --git a/public/locales/es.json b/public/locales/es.json
index 550dead..c5adbf3 100644
--- a/public/locales/es.json
+++ b/public/locales/es.json
@@ -868,5 +868,8 @@
"next": "Next",
"done": "Get started",
"skip": "Skip"
+ },
+ "offline": {
+ "banner": "Offline – reconnecting…"
}
-}
+}
\ No newline at end of file
diff --git a/public/locales/fr.json b/public/locales/fr.json
index eda86aa..52f6f5d 100644
--- a/public/locales/fr.json
+++ b/public/locales/fr.json
@@ -868,5 +868,8 @@
"next": "Next",
"done": "Get started",
"skip": "Skip"
+ },
+ "offline": {
+ "banner": "Offline – reconnecting…"
}
-}
+}
\ No newline at end of file
diff --git a/public/locales/hi.json b/public/locales/hi.json
index 9581739..3652c2d 100644
--- a/public/locales/hi.json
+++ b/public/locales/hi.json
@@ -868,5 +868,8 @@
"next": "Next",
"done": "Get started",
"skip": "Skip"
+ },
+ "offline": {
+ "banner": "Offline – reconnecting…"
}
-}
+}
\ No newline at end of file
diff --git a/public/locales/it.json b/public/locales/it.json
index 045e49e..e823a10 100644
--- a/public/locales/it.json
+++ b/public/locales/it.json
@@ -868,5 +868,8 @@
"next": "Next",
"done": "Get started",
"skip": "Skip"
+ },
+ "offline": {
+ "banner": "Offline – reconnecting…"
}
-}
+}
\ No newline at end of file
diff --git a/public/locales/ja.json b/public/locales/ja.json
index 64aabbe..99532e5 100644
--- a/public/locales/ja.json
+++ b/public/locales/ja.json
@@ -868,5 +868,8 @@
"next": "Next",
"done": "Get started",
"skip": "Skip"
+ },
+ "offline": {
+ "banner": "Offline – reconnecting…"
}
-}
+}
\ No newline at end of file
diff --git a/public/locales/pt.json b/public/locales/pt.json
index f41b9d7..63f71a7 100644
--- a/public/locales/pt.json
+++ b/public/locales/pt.json
@@ -869,5 +869,8 @@
"next": "Next",
"done": "Get started",
"skip": "Skip"
+ },
+ "offline": {
+ "banner": "Offline – reconnecting…"
}
-}
+}
\ No newline at end of file
diff --git a/public/locales/ru.json b/public/locales/ru.json
index bba83d1..354d8d4 100644
--- a/public/locales/ru.json
+++ b/public/locales/ru.json
@@ -868,5 +868,8 @@
"next": "Next",
"done": "Get started",
"skip": "Skip"
+ },
+ "offline": {
+ "banner": "Offline – reconnecting…"
}
-}
+}
\ No newline at end of file
diff --git a/public/locales/sv.json b/public/locales/sv.json
index 6c351c9..b3871f1 100644
--- a/public/locales/sv.json
+++ b/public/locales/sv.json
@@ -868,5 +868,8 @@
"next": "Next",
"done": "Get started",
"skip": "Skip"
+ },
+ "offline": {
+ "banner": "Offline – reconnecting…"
}
-}
+}
\ No newline at end of file
diff --git a/public/locales/tr.json b/public/locales/tr.json
index 7b817f2..b6d8720 100644
--- a/public/locales/tr.json
+++ b/public/locales/tr.json
@@ -868,5 +868,8 @@
"next": "Next",
"done": "Get started",
"skip": "Skip"
+ },
+ "offline": {
+ "banner": "Offline – reconnecting…"
}
-}
+}
\ No newline at end of file
diff --git a/public/locales/uk.json b/public/locales/uk.json
index 755fa6d..b7caa69 100644
--- a/public/locales/uk.json
+++ b/public/locales/uk.json
@@ -868,5 +868,8 @@
"next": "Next",
"done": "Get started",
"skip": "Skip"
+ },
+ "offline": {
+ "banner": "Offline – reconnecting…"
}
-}
+}
\ No newline at end of file
diff --git a/public/locales/zh.json b/public/locales/zh.json
index 0daccb1..abfb61a 100644
--- a/public/locales/zh.json
+++ b/public/locales/zh.json
@@ -868,5 +868,8 @@
"next": "Next",
"done": "Get started",
"skip": "Skip"
+ },
+ "offline": {
+ "banner": "Offline – reconnecting…"
}
-}
+}
\ No newline at end of file
diff --git a/public/router.js b/public/router.js
index d72dc6c..6934195 100644
--- a/public/router.js
+++ b/public/router.js
@@ -541,6 +541,20 @@ function renderAppShell(container) {
initMoreSheet(container);
initNavHideOnScroll(container);
initSearch(container);
+ initOfflineBanner();
+}
+
+function initOfflineBanner() {
+ const banner = document.getElementById('offline-banner');
+ if (!banner) return;
+ const i18nSpan = banner.querySelector('[data-i18n]');
+ function update() {
+ banner.hidden = navigator.onLine;
+ if (i18nSpan) i18nSpan.textContent = t('offline.banner');
+ }
+ window.addEventListener('online', update);
+ window.addEventListener('offline', update);
+ update();
}
/**
diff --git a/public/styles/layout.css b/public/styles/layout.css
index 3f94ef8..9a5c4ea 100755
--- a/public/styles/layout.css
+++ b/public/styles/layout.css
@@ -1897,6 +1897,40 @@
}
}
+/* --------------------------------------------------------
+ * Offline-Banner
+ * -------------------------------------------------------- */
+.offline-banner {
+ position: fixed;
+ top: 0;
+ left: 0;
+ right: 0;
+ z-index: calc(var(--z-toast) + 1);
+ display: flex;
+ align-items: center;
+ gap: var(--space-2);
+ padding: var(--space-2) var(--space-4);
+ background-color: var(--color-warning-light);
+ color: var(--color-warning);
+ font-size: var(--text-sm);
+ font-weight: var(--font-weight-medium);
+ border-bottom: 1px solid color-mix(in srgb, var(--color-warning) 20%, transparent);
+ animation: offline-banner-in 0.2s var(--ease-out);
+}
+
+.offline-banner[hidden] {
+ display: none;
+}
+
+@keyframes offline-banner-in {
+ from { opacity: 0; transform: translateY(-100%); }
+ to { opacity: 1; transform: translateY(0); }
+}
+
+@media (prefers-reduced-motion: reduce) {
+ .offline-banner { animation: none; }
+}
+
/* --------------------------------------------------------
* Print-Styles
* -------------------------------------------------------- */