Index: src/views/shell.ejs
===================================================================
--- src/views/shell.ejs	(revision 7990e00cc41b0f25b16bedc4750c4c1bf552519f)
+++ src/views/shell.ejs	(revision 389aa99294100a3fd7e7e09992a06dd980257fb1)
@@ -478,4 +478,13 @@
 
   var lastPath = location.pathname + location.search;
+  var navTimer = null;
+
+  // Eén plek voor alle programmatische navigatie-swaps. Annuleert eerst een nog
+  // lopende request op #pcms-main (anti-race: bij snel klikken/terug-gaan kan een
+  // trage oude response anders een nieuwe pagina overschrijven → "kale content").
+  function doNav(dest) {
+    try { window.htmx.trigger('#pcms-main', 'htmx:abort'); } catch (_) {}
+    window.htmx.ajax('GET', dest, { target: '#pcms-main', swap: 'innerHTML' });
+  }
 
   document.addEventListener('click', function (e) {
@@ -492,5 +501,6 @@
     if (dest !== lastPath) history.pushState({ b: 1 }, '', dest);
     lastPath = dest;
-    window.htmx.ajax('GET', dest, { target: '#pcms-main', swap: 'innerHTML' });
+    if (navTimer) { clearTimeout(navTimer); navTimer = null; }
+    doNav(dest);
     try { window.scrollTo(0, 0); } catch (_) {}
   });
@@ -500,5 +510,11 @@
     if (here === lastPath) return;
     lastPath = here;
-    window.htmx.ajax('GET', here, { target: '#pcms-main', swap: 'innerHTML' });
+    // Debounce: bij heel snel/herhaald terug-vooruit niet elke tussenpagina ophalen,
+    // alleen de LAATSTE bestemming. Voorkomt overlappende swaps ("kale content").
+    if (navTimer) clearTimeout(navTimer);
+    navTimer = setTimeout(function () {
+      navTimer = null;
+      doNav(location.pathname + location.search);
+    }, 90);
   });
 
