Index: src/views/pages/admin-site-edit.ejs
===================================================================
--- src/views/pages/admin-site-edit.ejs	(revision 746d98a771aa1e4a4241958d88582d516570cf4b)
+++ src/views/pages/admin-site-edit.ejs	(revision b4aaaddef9ee9b6109381addc714faa320110e88)
@@ -103,4 +103,27 @@
       </fieldset>
 
+      <%# ── De lay-out (experimental/theme) ──────────────────────────────
+          Een thema uit src/themes/. Alleen de beheerder kiest; een bezoeker
+          niet. Het beheer zelf houdt altijd de gewone kop, zodat een kapot
+          thema je nooit buitensluit van deze instelling. %>
+      <% if (typeof layouts !== 'undefined' && layouts && layouts.length) { %>
+      <fieldset class="layout-choice">
+        <legend><%= t('asite.layout') %></legend>
+        <% const lc = site.layout || ''; %>
+        <label class="cb">
+          <input type="radio" name="layout" value="" <%= lc === '' ? 'checked' : '' %>>
+          <span><%= t('asite.layout_top') %></span>
+        </label>
+        <% layouts.forEach(function (l) { %>
+        <label class="cb">
+          <input type="radio" name="layout" value="<%= l.id %>" <%= lc === l.id ? 'checked' : '' %>>
+          <span><%= l.name %></span>
+          <% if (site.slug) { %><a class="layout-preview" href="/?layout=<%= encodeURIComponent(l.id) %>" target="_blank" rel="noopener">voorproefje</a><% } %>
+        </label>
+        <% }); %>
+        <p class="hint"><%= t('asite.layout_hint') %></p>
+      </fieldset>
+      <% } %>
+
       <fieldset class="palette-grid">
         <legend><%= t('asite.palette') %></legend>
Index: src/views/shell.ejs
===================================================================
--- src/views/shell.ejs	(revision 746d98a771aa1e4a4241958d88582d516570cf4b)
+++ src/views/shell.ejs	(revision b4aaaddef9ee9b6109381addc714faa320110e88)
@@ -132,5 +132,5 @@
 const MOD_V = 68;
 %><!DOCTYPE html>
-<html lang="<%- _e(lang) %>" data-palette="<%- _e((typeof palette !== 'undefined' && palette) ? palette : (safeSite.palette || 'klonkt')) %>">
+<html lang="<%- _e(lang) %>" data-palette="<%- _e((typeof palette !== 'undefined' && palette) ? palette : (safeSite.palette || 'klonkt')) %>" data-layout="<%- _e((typeof layoutTheme !== 'undefined' && layoutTheme) ? layoutTheme.id : 'top') %>">
 <head>
 <meta charset="utf-8">
@@ -234,4 +234,11 @@
 <!-- v9 stylesheet (full palette system) -->
 <link rel="stylesheet" href="/assets/css/style.css?v=111">
+<%# De lay-outthema's (experimental/theme): de stylesheet van het thema dat de
+    site koos, plus die van een voorproefje voor wie de site beheert. Hun regels
+    gelden alleen onder <html data-layout="...">, dat de server hierboven al zet
+    -- dus geen script, geen flits, en geen bezoeker die iets anders kiest. %>
+<% if (typeof layoutSheets !== 'undefined' && layoutSheets) { layoutSheets.forEach(function (href) { %>
+<link rel="stylesheet" href="<%= href %>">
+<% }); } %>
 <script>
 /* iOS safe-area, built by hand. env(safe-area-inset-top) resolves to 0 on this iOS in
@@ -485,4 +492,11 @@
     if (d.palette && /^[a-z0-9-]+$/i.test(d.palette)) {
       document.documentElement.setAttribute('data-palette', d.palette);
+    }
+    // De lay-out van de NIEUWE pagina (experimental/theme). De <html> wordt bij
+    // htmx-navigatie niet opnieuw gerenderd, dus zonder dit hield het beheer de
+    // zijbalk van de pagina ervoor -- terwijl beheer altijd de gewone kop hoort
+    // te hebben. Zelfde vorm als een thema-id, dus niets anders kan erin.
+    if (typeof d.layout === 'string' && /^[a-z0-9][a-z0-9.-]{0,63}$/.test(d.layout)) {
+      document.documentElement.setAttribute('data-layout', d.layout);
     }
 
