Index: src/themes/sidebar/layout.css
===================================================================
--- src/themes/sidebar/layout.css	(revision 495b0191f40d1e9e9de36d8ce98cad627ffb13cb)
+++ src/themes/sidebar/layout.css	(revision 495b0191f40d1e9e9de36d8ce98cad627ffb13cb)
@@ -0,0 +1,198 @@
+/*
+ * Lay-out "zijbalk" -- het eerste ingebouwde thema (experimental/theme, op weg
+ * naar 2.0). Een thema is een pakket: theme.json ernaast, dit bestand erin.
+ *
+ * DEZELFDE MARKUP, EEN ANDER STELSEL. Dit thema verandert geen template; het
+ * ordent wat er al staat. Dat is het contract (`"contract": 1` in theme.json):
+ * de ids en klassen waar de JS en de custom_css van beheerders op leunen,
+ * blijven waar ze zijn, en een thema mag alleen daarop bouwen.
+ *
+ * ELKE REGEL ONDER html[data-layout="sidebar"]. De shell zet dat attribuut
+ * alleen als dit het gekozen thema is, dus zolang hij niet gekozen is raakt
+ * dit bestand niets. Voor ingebouwde thema's staat die afbakening er met de
+ * hand; een thema van buiten krijgt hem straks bij installatie opgelegd.
+ *
+ * WIE KIEST: de beheerder van de site, in het beheer. Een bezoeker niet.
+ *
+ * ALLEEN OP EEN BREED SCHERM. Onder de 1024px blijft alles zoals het was: daar
+ * is de onderste tabbalk de navigatie, en een zijbalk zou de inhoud opeten.
+ */
+@media (min-width: 1024px) {
+
+  html[data-layout="sidebar"] { --sidebar-w: 15rem; }
+
+  /* Alleen ruimte maken als er ook een zijbalk IS. De hub-landing en de
+     in- en uitlogschermen hebben geen kop; die houden de volle breedte. */
+  html[data-layout="sidebar"] body:has(#pcms-chrome .masthead) {
+    padding-left: var(--sidebar-w);
+  }
+
+  /* ── De chrome wordt de zijbalk ─────────────────────────────── */
+  /* Niet de masthead maar het hele #pcms-chrome-slot: daar zitten de
+     masthead, de identiteit van de site (profile-header) en de Lezen/Grid-
+     wissel al samen in, en het slot wordt bij elke htmx-navigatie als
+     geheel ververst. Zo blijft alles bij elkaar dat bij de site hoort, en
+     bepaalt `order` de volgorde -- zonder dat er een regel markup verschuift. */
+  html[data-layout="sidebar"] #pcms-chrome:has(.masthead) {
+    position: fixed;
+    top: 0; bottom: 0; left: 0;
+    width: var(--sidebar-w);
+    display: flex;
+    flex-direction: column;
+    padding-top: var(--ios-safe-top, 0px);
+    border-right: 1px solid var(--rule);
+    background: var(--paper);
+    z-index: 30;
+    /* GEEN overflow hier: de taal- en gebruikersmenu's klappen naar rechts
+       uit de balk, en een scrollende balk zou ze afknippen. */
+  }
+
+  /* ── 1. Bovenaan: wie dit is ─────────────────────────────────── */
+  /* De specificiteit is opzet: de compacte stand op post-, zoek- en
+     archiefpagina's (foto 40px, geen bio) bestaat om ruimte boven de inhoud
+     te sparen. In een kolom is die ruimte er wel, en een identiteit die per
+     pagina van maat verspringt leest als een andere site. */
+  html[data-layout="sidebar"] #pcms-chrome .profile-header {
+    order: -2;
+    padding: 1.75rem 0 1.25rem;
+    border-bottom: 1px solid var(--rule);
+    background: transparent;
+  }
+  html[data-layout="sidebar"] #pcms-chrome .profile-header-inner {
+    max-width: none;
+    margin: 0;
+    padding: 0 1.6rem;
+    flex-direction: column;
+    align-items: flex-start;
+    gap: .85rem;
+  }
+  html[data-layout="sidebar"] #pcms-chrome .profile-photo {
+    width: 72px;
+    height: 72px;
+    border-width: 2px;
+  }
+  html[data-layout="sidebar"] #pcms-chrome .profile-photo-fallback { font-size: 1.75rem; }
+  html[data-layout="sidebar"] #pcms-chrome .profile-name {
+    font-size: 1.4rem;
+    margin: 0 0 .3rem;
+    overflow-wrap: anywhere;
+  }
+  html[data-layout="sidebar"] #pcms-chrome .profile-bio {
+    display: block;
+    font-size: .85rem;
+  }
+  html[data-layout="sidebar"] #pcms-chrome .profile-links { flex-wrap: wrap; }
+
+  /* ── 2. Hoe je de site leest ─────────────────────────────────── */
+  /* De Lezen/Grid-wissel zit in hetzelfde slot, dus hij komt mee: onder de
+     identiteit, als keuze die bij de site hoort in plaats van boven de stroom. */
+  html[data-layout="sidebar"] #pcms-chrome .view-switcher-wrap {
+    order: -1;
+    margin: 0;
+    padding: .9rem 0;
+    border-bottom: 1px solid var(--rule);
+    background: transparent;
+  }
+  html[data-layout="sidebar"] #pcms-chrome .view-switcher-wrap .container {
+    max-width: none;
+    padding-inline: 1.6rem;
+    justify-content: flex-start;
+  }
+
+  /* ── 3. De navigatie vult de rest ────────────────────────────── */
+  html[data-layout="sidebar"] #pcms-chrome .masthead {
+    position: static;
+    flex: 1 1 auto;
+    display: flex;
+    flex-direction: column;
+    padding: 1rem 0 1.25rem;
+    border: 0;
+    background: transparent;
+  }
+
+  html[data-layout="sidebar"] .masthead-inner {
+    flex: 1 1 auto;
+    max-width: none;
+    margin: 0;
+    padding-inline: .75rem;
+    flex-direction: column;
+    align-items: stretch;
+    justify-content: flex-start;
+    gap: 1rem;
+  }
+
+  /* Het merk is overal verborgen (de profielkop draagt het), en dan is het
+     een leeg vak met een gat eronder. Behalve op beheerpagina's: daar staat
+     "terug naar de site", en dat is daar de enige weg terug. */
+  html[data-layout="sidebar"] .masthead-brand:not(:has(.nav-link-admin)) {
+    display: none;
+  }
+  html[data-layout="sidebar"] .masthead-brand {
+    flex: 0 0 auto;
+    overflow: visible;
+  }
+  html[data-layout="sidebar"] .masthead-brand .nav-link-admin {
+    width: 100%;
+  }
+
+  /* ── De navigatie staat onder elkaar ──────────────────────────── */
+  html[data-layout="sidebar"] .top-nav-desktop {
+    flex: 1 1 auto;
+    flex-direction: column;
+    align-items: stretch;
+    gap: .15rem;
+  }
+
+  html[data-layout="sidebar"] .top-nav-desktop > .nav-link,
+  html[data-layout="sidebar"] .top-nav-desktop > .nav-btn,
+  html[data-layout="sidebar"] .top-nav-desktop > details > summary {
+    width: 100%;
+    justify-content: flex-start;
+    padding: .55rem .85rem;
+  }
+  html[data-layout="sidebar"] .top-nav-desktop .nav-label { display: inline; }
+
+  /* Knoppen die in de kop alleen een pictogram zijn, krijgen hier hun naam.
+     De naam stond al in de markup, als title of aria-label; er is niets bij
+     gekomen. In een kolom onder elkaar leest een rij losse pictogrammen als
+     een raadsel. */
+  html[data-layout="sidebar"] .top-nav-desktop > .nav-btn[title]::after,
+  html[data-layout="sidebar"] .top-nav-desktop .lang-toggle[title]::after {
+    content: attr(title);
+  }
+  html[data-layout="sidebar"] .top-nav-desktop .user-toggle[aria-label]::after {
+    content: attr(aria-label);
+  }
+  /* Het pijltje hoort bij een menu dat naar beneden valt; hier klapt hij
+     opzij, en tussen de taalcode en de naam las het als "EN ⌄ Language". */
+  html[data-layout="sidebar"] .top-nav-desktop .lang-caret { display: none; }
+
+  /* Bovenin wat je zoekt (archief, zoeken); onderin wat bij JOU hoort
+     (thema, taal, meldingen, je account). Het thema is de eerste van dat
+     tweede rijtje, dus die duwt de rest naar beneden. */
+  html[data-layout="sidebar"] .top-nav-desktop > #theme-toggle {
+    margin-top: auto;
+  }
+
+  /* ── De uitklapmenu's klappen naar rechts open ───────────────── */
+  /* In de kop vielen ze naar beneden, rechts uitgelijnd. Onderin een smalle
+     balk zou dat buiten beeld vallen, dus: naast de knop, naar boven toe. */
+  html[data-layout="sidebar"] .user-dropdown,
+  html[data-layout="sidebar"] .lang-dropdown {
+    top: auto;
+    right: auto;
+    bottom: 0;
+    left: calc(100% + .6rem);
+    transform-origin: bottom left;
+  }
+  html[data-layout="sidebar"] .user-menu,
+  html[data-layout="sidebar"] .lang-menu {
+    position: relative;
+  }
+
+  /* ── Wat over de volle breedte vastzat, begint nu na de balk ──── */
+  html[data-layout="sidebar"] body:has(#pcms-chrome .masthead) .audio-player,
+  html[data-layout="sidebar"] body:has(#pcms-chrome .masthead) .audio-sheet {
+    left: var(--sidebar-w);
+  }
+}
Index: src/themes/sidebar/theme.json
===================================================================
--- src/themes/sidebar/theme.json	(revision 495b0191f40d1e9e9de36d8ce98cad627ffb13cb)
+++ src/themes/sidebar/theme.json	(revision 495b0191f40d1e9e9de36d8ce98cad627ffb13cb)
@@ -0,0 +1,10 @@
+{
+  "id": "sidebar",
+  "name": "Zijbalk",
+  "description": "De identiteit van de site en de navigatie in een vaste kolom links; de inhoud ernaast. Alleen op een breed scherm -- smaller blijft het de gewone kop met de tabbalk.",
+  "version": "1.0.0",
+  "contract": 1,
+  "stylesheet": "layout.css",
+  "author": "Klonkt",
+  "license": "AGPL-3.0-or-later"
+}
