Index: src/assets/css/style.css
===================================================================
--- src/assets/css/style.css	(revision 7ca3ffcf846109ed0ca6ebd1a0832365fc85be1f)
+++ src/assets/css/style.css	(revision a036251bd8eca14e2618a9480a696594cf90f548)
@@ -63,4 +63,7 @@
     --radius: 8px; --transition: 180ms cubic-bezier(.4,0,.2,1);
     --safe-top: env(safe-area-inset-top, 0); --safe-bot: env(safe-area-inset-bottom, 0);
+    /* iOS top inset: starts from env(), but a tiny boot script overrides it with a
+       real/measured value (env() resolves to 0 in some iOS standalone states). */
+    --ios-safe-top: env(safe-area-inset-top, 0px);
     color-scheme: light dark;
 }
@@ -507,5 +510,5 @@
 .masthead {
     border-bottom: 1px solid var(--rule);
-    padding: calc(1rem + env(safe-area-inset-top, 0px)) 0 1rem;
+    padding: calc(1rem + var(--ios-safe-top, 0px)) 0 1rem;
     /* GEEN backdrop-filter hier: een voorouder met backdrop-filter blokkeert de
        frosted blur van het user-menu-dropdown eronder. Masthead is toch bijna
@@ -1620,5 +1623,5 @@
         border-top-right-radius: 0;
         box-shadow: none;
-        padding-top: calc(.75rem + env(safe-area-inset-top, 0px));
+        padding-top: calc(.75rem + var(--ios-safe-top, 0px));
         padding-bottom: calc(2rem + env(safe-area-inset-bottom, 0px));
     }
@@ -1678,5 +1681,5 @@
 }
 @media (max-width: 400px) {
-    .masthead { padding: calc(.5rem + env(safe-area-inset-top, 0px)) 0 .5rem; }
+    .masthead { padding: calc(.5rem + var(--ios-safe-top, 0px)) 0 .5rem; }
     .masthead-inner { gap: .25rem; }
     .site-title { font-size: 1.05rem; }
@@ -2759,5 +2762,5 @@
 
 /* Masthead: compacter */
-.masthead { padding: calc(.55rem + env(safe-area-inset-top, 0px)) 0 .55rem; }
+.masthead { padding: calc(.55rem + var(--ios-safe-top, 0px)) 0 .55rem; }
 .masthead-inner { gap: 1rem; }
 .site-title { font-size: 1.25rem; }
Index: src/views/shell.ejs
===================================================================
--- src/views/shell.ejs	(revision 7ca3ffcf846109ed0ca6ebd1a0832365fc85be1f)
+++ src/views/shell.ejs	(revision a036251bd8eca14e2618a9480a696594cf90f548)
@@ -198,5 +198,30 @@
 
 <!-- v9 stylesheet (full palette system) -->
-<link rel="stylesheet" href="/assets/css/style.css?v=53">
+<link rel="stylesheet" href="/assets/css/style.css?v=54">
+<script>
+/* iOS safe-area, built by hand: env(safe-area-inset-top) resolves to 0 in some iOS
+   states (Safari + standalone) even with viewport-fit=cover. Measure it directly, and
+   if it comes back empty on a notch/Dynamic-Island iPhone, fall back to a fixed inset.
+   The masthead reads --ios-safe-top. */
+(function(){
+  var ua = navigator.userAgent || '';
+  var isIOS = /iP(hone|od|ad)/.test(ua) || (navigator.platform === 'MacIntel' && navigator.maxTouchPoints > 1);
+  if (!isIOS) return;
+  function setInset(){
+    if (!document.body) return;
+    var p = document.createElement('div');
+    p.style.cssText = 'position:fixed;top:0;left:0;width:0;height:0;padding-top:env(safe-area-inset-top,0px);visibility:hidden;pointer-events:none';
+    document.body.appendChild(p);
+    var i = parseFloat(getComputedStyle(p).paddingTop) || 0;
+    p.remove();
+    // env() gave nothing but this looks like a notched iPhone (logical height >= 812)
+    // -> use a fixed status-bar inset so the masthead clears the camera anyway.
+    if (i < 20 && Math.max(screen.width, screen.height) >= 812) i = 50;
+    document.documentElement.style.setProperty('--ios-safe-top', i + 'px');
+  }
+  if (document.body) setInset(); else document.addEventListener('DOMContentLoaded', setInset);
+  window.addEventListener('orientationchange', function(){ setTimeout(setInset, 250); });
+})();
+</script>
 
 <!-- Audio player styles: loaded on every page so the mini-player works
