diff --git a/frontend/js/app.js b/frontend/js/app.js
index ad2eb63..8adda3b 100644
--- a/frontend/js/app.js
+++ b/frontend/js/app.js
@@ -120,16 +120,8 @@ async function init() {
}
document.addEventListener("DOMContentLoaded", async () => {
- try {
- await init();
- Sync.init();
- } finally {
- // Signale au splash de démarrage (index.html #boot-splash) que l'app est
- // initialisée : le splash est retiré et le squelette stylé révélé.
- // Set AFTER init() resolves so every handler (search, tabs, …) is bound.
- window.__OBSIGATE_BOOTED = true;
- if (typeof window.__obsigateBootReady === "function") window.__obsigateBootReady();
- }
+ await init();
+ Sync.init();
// Show version in header — always visible, fallback before the async fetch
populateVersions();
fetch('/api/health')
diff --git a/tests/test_sans_splash_demarrage.py b/tests/test_sans_splash_demarrage.py
new file mode 100644
index 0000000..6d6fae1
--- /dev/null
+++ b/tests/test_sans_splash_demarrage.py
@@ -0,0 +1,75 @@
+"""Tests — démarrage ObsiGate sans écran de chargement plein écran.
+
+Le splash (``#boot-splash`` dans ``frontend/index.html`` : icône
+livre, titre, spinner, « Démarrage… ») masquait tout le reste de la
+page via ``body:not(.app-booted) > * { display: none !important }``
+jusqu'au signal de ``frontend/js/app.js`` (ou un repli à 10 s).
+Les autres applications (TikTak, Kanbante, Flowdeck, console Spark)
+n'affichent aucun splash de ce type au démarrage : le contenu y
+apparaît dès qu'il est prêt. Le retrait supprime donc l'écran, son
+CSS de masquage, son script de pilotage et le signal côté ``app.js``,
+sans toucher aux indicateurs internes aux vues ni à l'écran de
+connexion.
+"""
+
+from __future__ import annotations
+
+from pathlib import Path
+
+ROOT = Path(__file__).resolve().parent.parent
+FRONTEND = ROOT / "frontend"
+
+MARQUEURS_SPLASH = (
+ "boot-splash",
+ "app-booted",
+ "__OBSIGATE_BOOTED",
+ "__obsigateBootReady",
+ "__setBootStatus",
+ "bs-card",
+ "bs-logo",
+ "bs-title",
+ "bs-spinner",
+ "bs-status",
+ "bs-spin",
+ "Démarrage…",
+)
+
+
+def _index() -> str:
+ return (FRONTEND / "index.html").read_text(encoding="utf-8")
+
+
+def _app_js() -> str:
+ return (FRONTEND / "js" / "app.js").read_text(encoding="utf-8")
+
+
+def test_aucun_marqueur_splash():
+ index = _index()
+ app_js = _app_js()
+ for marqueur in MARQUEURS_SPLASH:
+ assert marqueur not in index, f"{marqueur} encore dans index.html"
+ assert marqueur not in app_js, f"{marqueur} encore dans js/app.js"
+
+
+def test_pas_de_masquage_global_au_demarrage():
+ """Aucune règle ne cache tout le en attendant un signal :
+ sans elle, un chargement lent ne peut plus donner un écran blanc
+ bloqué."""
+ index = _index()
+ assert "body:not(.app-booted)" not in index
+ assert "display: none !important" not in index
+
+
+def test_boot_js_conserve_et_indicateurs_internes_intacts():
+ """Le démarrage SPA reste branché ; seuls le splash et son signal
+ disparaissent. L'écran de connexion et la barre de progression
+ de recherche (indicateurs internes aux vues) ne sont PAS visés."""
+ app_js = _app_js()
+ assert 'document.addEventListener("DOMContentLoaded"' in app_js
+ assert "await init();" in app_js
+ assert "Sync.init();" in app_js
+ assert "populateVersions" in app_js
+ index = _index()
+ assert 'id="login-screen"' in index
+ assert 'id="search-progress-bar"' in index
+ assert 'id="app"' in index