Index: src/assets/css/ward.css
===================================================================
--- src/assets/css/ward.css	(revision 52188632909b3b1b9120748844eed2779f7fc030)
+++ src/assets/css/ward.css	(revision 4bb93aa4a060a71f9d58edb59da3c88711d16844)
@@ -10,4 +10,9 @@
 }
 * { box-sizing: border-box; }
+/* Het hidden-attribuut wint ALTIJD. Zonder deze regel verslaat elke eigen
+   display-regel (zoals de flex van #thread) de browser-default display:none,
+   en dan staat een 'verborgen' overlay gewoon over de pagina heen. Dat was
+   precies de vastzittende gespreks-overlay van 12-8. */
+[hidden] { display: none !important; }
 body {
   margin: 0; padding: 16px calc(16px + env(safe-area-inset-right)) 32px calc(16px + env(safe-area-inset-left));
Index: test/ward-pwa.test.js
===================================================================
--- test/ward-pwa.test.js	(revision 52188632909b3b1b9120748844eed2779f7fc030)
+++ test/ward-pwa.test.js	(revision 4bb93aa4a060a71f9d58edb59da3c88711d16844)
@@ -212,2 +212,15 @@
   } finally { server.close(); }
 });
+
+test('hidden wint van elke display-regel in de stylesheet', async () => {
+  // De gespreks-overlay heeft display:flex; zonder een [hidden]-regel met
+  // !important verslaat die de browser-default en staat een "verborgen"
+  // overlay permanent over de pagina (Robins schermafdruk, 12-8). De CSS is
+  // hier de waarheid, dus die bewaken we, niet de DOM.
+  const fs = await import('node:fs');
+  const css = fs.readFileSync(new URL('../src/assets/css/ward.css', import.meta.url), 'utf8');
+  assert.match(css, /\[hidden\]\s*\{\s*display:\s*none\s*!important/, 'de [hidden]-regel ontbreekt');
+  // En hij moet VOOR de #thread-regel staan is niet nodig (important wint),
+  // maar de flex-regel moet er wel zijn, anders bewaakt deze test niets.
+  assert.match(css, /#thread\s*\{[^}]*display:\s*flex/);
+});
