Index: c/routes/admin-comments.js
===================================================================
--- src/routes/admin-comments.js	(revision 2e9773f664c16b98d6ebb6626b4e5a498f38c448)
+++ 	(revision )
@@ -1,81 +1,0 @@
-/**
- * Admin: Comment moderation queue — Phase E.
- *
- * GET  /admin/comments              -> list pending + recent (god-only)
- * POST /admin/comments/:id/approve  -> set status = 'approved'
- * POST /admin/comments/:id/reject   -> set status = 'rejected' (keeps the row
- *                                      so we have a paper trail; admin can
- *                                      hard-delete via the post page).
- *
- * Scope: shows comments for the resolved site only (the one matched by
- * /sites/:slug or default). Future: filter by status / search.
- */
-
-import express from 'express';
-import db from '../config/database.js';
-import { renderPage } from '../middleware/render.js';
-import { requireSiteManager } from '../middleware/auth.js';
-
-const router = express.Router();
-
-router.get('/', requireSiteManager, (req, res) => {
-  const site = res.locals.site;
-  if (!site) return res.status(404).send('No site');
-
-  const pending = db.prepare(`
-    SELECT c.id, c.content, c.created_at, c.parent_comment_id,
-           u.username AS author_username,
-           p.slug AS post_slug, p.title AS post_title
-    FROM comments c
-    JOIN users u ON u.id = c.author_id
-    JOIN posts p ON p.id = c.post_id
-    WHERE p.site_id = ? AND c.status = 'pending'
-    ORDER BY c.created_at ASC
-    LIMIT 200
-  `).all(site.id);
-
-  const recent = db.prepare(`
-    SELECT c.id, c.content, c.created_at, c.status,
-           u.username AS author_username,
-           p.slug AS post_slug, p.title AS post_title
-    FROM comments c
-    JOIN users u ON u.id = c.author_id
-    JOIN posts p ON p.id = c.post_id
-    WHERE p.site_id = ? AND c.status IN ('approved', 'rejected')
-    ORDER BY c.created_at DESC
-    LIMIT 30
-  `).all(site.id);
-
-  renderPage(req, res, 'pages/admin-comments', {
-    pageTitle: 'Comment moderation',
-    bodyClass: 'on-admin',
-    pending,
-    recent,
-    moderationMode: site.comments_moderation_mode || 'trust',
-    success: req.query.success || null,
-    error: req.query.error || null,
-  });
-});
-
-function setStatus(req, res, status) {
-  const site = res.locals.site;
-  if (!site) return res.status(404).send('No site');
-  const base = res.locals.siteUrlBase || ''; // /user/<slug> in hub artist context, otherwise ''
-
-  const row = db.prepare(`
-    SELECT c.id FROM comments c JOIN posts p ON p.id = c.post_id
-    WHERE c.id = ? AND p.site_id = ?
-  `).get(req.params.id, site.id);
-
-  if (!row) return res.redirect(base + '/admin/comments?error=Not+found');
-
-  db.prepare(
-    'UPDATE comments SET status = ?, updated_at = CURRENT_TIMESTAMP WHERE id = ?'
-  ).run(status, req.params.id);
-  res.redirect(base + '/admin/comments?success=' + encodeURIComponent('Comment ' + status));
-}
-
-router.post('/:id/approve', requireSiteManager, (req, res) => setStatus(req, res, 'approved'));
-router.post('/:id/reject',  requireSiteManager, (req, res) => setStatus(req, res, 'rejected'));
-
-export default router;
Index: c/routes/comments.js
===================================================================
--- src/routes/comments.js	(revision 2e9773f664c16b98d6ebb6626b4e5a498f38c448)
+++ 	(revision )
@@ -1,131 +1,0 @@
-/**
- * Comments — phase G v1.
- *
- * POST /comments              -> create a comment on a post (auth required)
- * POST /comments/:id/delete   -> delete (own, or god/site-admin)
- *
- * Threading: 1 level deep (top-level + replies). Replies-of-replies fold up
- * into the same parent (UI keeps it shallow).
- *
- * Status: auto-approved for logged-in users (trust mode). The schema's
- * `status` column stays so we can switch to moderation later without changing
- * shape. Anonymous comments (require_login_to_comment = 0 + no user) come
- * later — for now we always require login.
- */
-
-import express from 'express';
-import { v4 as uuid } from 'uuid';
-import db from '../config/database.js';
-import { requireAuth } from '../middleware/auth.js';
-import PermissionsService from '../services/PermissionsService.js';
-import { notify } from '../services/NotificationService.js';
-
-const router = express.Router();
-
-// Limits
-const MAX_LEN = 4000;
-const MIN_LEN = 1;
-
-router.post('/', requireAuth, (req, res) => {
-  const site = res.locals.site;
-  if (!site) return res.status(404).send('Site required');
-
-  const postSlug = (req.body.post_slug || '').trim();
-  const rawContent = (req.body.content || '').trim();
-  const parentId = (req.body.parent_comment_id || '').trim() || null;
-
-  if (!postSlug) return res.status(400).send('post_slug required');
-  if (rawContent.length < MIN_LEN) return res.status(400).send('Comment cannot be empty');
-  if (rawContent.length > MAX_LEN) return res.status(413).send(`Comment too long (max ${MAX_LEN} chars)`);
-
-  const post = db.prepare(
-    'SELECT id, slug, title, author_id FROM posts WHERE site_id = ? AND slug = ? AND status = ?'
-  ).get(site.id, postSlug, 'published');
-  if (!post) return res.status(404).send('Post not found');
-
-  if (!PermissionsService.canComment(req.session.user, site, post)) {
-    return res.status(403).send('Comments not allowed');
-  }
-
-  // Validate parent (must belong to this post; collapses replies-of-replies
-  // up to the top-level parent so we never go deeper than 1)
-  let resolvedParent = null;
-  let parentAuthorId = null;
-  if (parentId) {
-    const parent = db.prepare(
-      'SELECT id, parent_comment_id, author_id FROM comments WHERE id = ? AND post_id = ?'
-    ).get(parentId, post.id);
-    if (!parent) return res.status(400).send('Invalid parent comment');
-    resolvedParent = parent.parent_comment_id || parent.id;
-    parentAuthorId = parent.author_id; // recipient of the "reply" notification
-  }
-
-  // Status depends on the site's moderation mode.
-  // 'trust'    = auto-approve immediately (default).
-  // 'moderate' = pending until an admin reviews in /admin/comments.
-  // Author is the post author or god → always trusted (no point gatekeeping yourself).
-  const isTrustedAuthor = req.session.user.role === 'god'
-    || req.session.user.id === post.author_id;
-  const status = (site.comments_moderation_mode === 'moderate' && !isTrustedAuthor)
-    ? 'pending'
-    : 'approved';
-
-  const commentId = uuid();
-  db.prepare(`
-    INSERT INTO comments (id, post_id, author_id, parent_comment_id, content, status)
-    VALUES (?, ?, ?, ?, ?, ?)
-  `).run(commentId, post.id, req.session.user.id, resolvedParent, rawContent, status);
-
-  // Notification (only for visible comments): reply → author of the parent comment;
-  // top-level comment → author of the post. notify() skips self-notifications.
-  if (status === 'approved') {
-    const url = `${res.locals.siteUrlBase || ''}/${post.slug}#comment-${commentId}`;
-    const actorId = req.session.user.id;
-    const actorName = req.session.user.username;
-    if (parentId) {
-      notify({ userId: parentAuthorId, actorId, actorName, type: 'reply', postSlug: post.slug, postTitle: post.title, url });
-    } else {
-      notify({ userId: post.author_id, actorId, actorName, type: 'comment', postSlug: post.slug, postTitle: post.title, url });
-    }
-  }
-
-  // Where to land after submit:
-  //   approved → scroll to the new comment
-  //   pending  → comments anchor + ?pending=1 query so post page can flash a notice
-  const target = status === 'approved'
-    ? `${res.locals.siteUrlBase || ''}/${post.slug}#comment-${commentId}`
-    : `${res.locals.siteUrlBase || ''}/${post.slug}?pending=1#comments`;
-  if (req.headers['hx-request']) {
-    res.setHeader('HX-Redirect', target);
-    return res.send('OK');
-  }
-  res.redirect(target);
-});
-
-router.post('/:id/delete', requireAuth, (req, res) => {
-  const site = res.locals.site;
-  if (!site) return res.status(404).send('Site required');
-
-  const comment = db.prepare(`
-    SELECT c.id, c.author_id, c.post_id, p.slug AS post_slug
-    FROM comments c JOIN posts p ON p.id = c.post_id
-    WHERE c.id = ? AND p.site_id = ?
-  `).get(req.params.id, site.id);
-
-  if (!comment) return res.status(404).send('Not found');
-  if (!PermissionsService.canDeleteComment(req.session.user, comment, site)) {
-    return res.status(403).send('No permission');
-  }
-
-  // Delete the comment plus any replies that hung off it
-  db.prepare('DELETE FROM comments WHERE id = ? OR parent_comment_id = ?')
-    .run(req.params.id, req.params.id);
-
-  if (req.headers['hx-request']) {
-    res.setHeader('HX-Redirect', `${res.locals.siteUrlBase || ''}/${comment.post_slug}#comments`);
-    return res.send('OK');
-  }
-  res.redirect(`${res.locals.siteUrlBase || ''}/${comment.post_slug}#comments`);
-});
-
-export default router;
Index: src/routes/posts.js
===================================================================
--- src/routes/posts.js	(revision 2e9773f664c16b98d6ebb6626b4e5a498f38c448)
+++ src/routes/posts.js	(revision 59f017026eb35cc17dbb5f9fcf7cb3f5a9d9a538)
@@ -710,26 +710,6 @@
   }
 
-  // Comments: top-level + replies. Two-pass build: fetch all approved
-  // comments for the post, then group replies under their parent.
-  const commentRows = db.prepare(`
-    SELECT c.id, c.parent_comment_id, c.content, c.status, c.created_at,
-           c.author_id, u.username AS author_username,
-           COALESCE(u.avatar_url, (SELECT profile_photo FROM sites WHERE owner_id = u.id AND profile_photo IS NOT NULL ORDER BY is_primary DESC, created_at ASC LIMIT 1)) AS author_avatar
-    FROM comments c JOIN users u ON u.id = c.author_id
-    WHERE c.post_id = ? AND c.status = 'approved'
-    ORDER BY c.created_at ASC
-  `).all(post.id);
-  const topLevel = [];
-  const repliesById = new Map();
-  for (const c of commentRows) {
-    if (c.parent_comment_id) {
-      if (!repliesById.has(c.parent_comment_id)) repliesById.set(c.parent_comment_id, []);
-      repliesById.get(c.parent_comment_id).push(c);
-    } else {
-      topLevel.push(c);
-    }
-  }
-  for (const c of topLevel) c.replies = repliesById.get(c.id) || [];
-  const totalComments = commentRows.length;
+  // Native comments removed: social interaction is fediverse-only (see the
+  // "From the fediverse" section below).
 
   // Prev / next chronological (kept for back-compat — "post-nav" feature
@@ -818,6 +798,4 @@
     olderPost,
     relatedPosts,
-    comments: topLevel,
-    totalComments,
     fediverse,
     canManageSite,
Index: src/server.js
===================================================================
--- src/server.js	(revision 2e9773f664c16b98d6ebb6626b4e5a498f38c448)
+++ src/server.js	(revision 59f017026eb35cc17dbb5f9fcf7cb3f5a9d9a538)
@@ -32,10 +32,8 @@
 import adminSitesRoutes from './routes/admin-sites.js';
 import adminUsersRoutes from './routes/admin-users.js';
-import adminCommentsRoutes from './routes/admin-comments.js';
 import adminSettingsRoutes from './routes/admin-settings.js';
 import adminSeoRoutes from './routes/admin-seo.js';
 import audioRoutes from './routes/audio.js';
 import searchRoutes from './routes/search.js';
-import commentsRoutes from './routes/comments.js';
 import tagsRoutes from './routes/tags.js';
 import typesRoutes from './routes/types.js';
@@ -305,5 +303,4 @@
 app.use('/admin/sites', adminSitesRoutes);
 app.use('/admin/users', adminUsersRoutes);
-app.use('/admin/comments', adminCommentsRoutes);
 app.use('/admin/settings', adminSettingsRoutes);
 app.use('/admin/seo', adminSeoRoutes);
@@ -318,5 +315,4 @@
 if (audioEnabled()) app.use('/audio', audioRoutes);
 app.use('/search', searchRoutes);
-app.use('/comments', commentsRoutes);
 app.use('/tag', tagsRoutes);
 app.use('/type', typesRoutes);
Index: c/views/pages/admin-comments.ejs
===================================================================
--- src/views/pages/admin-comments.ejs	(revision 2e9773f664c16b98d6ebb6626b4e5a498f38c448)
+++ 	(revision )
@@ -1,128 +1,0 @@
-<div class="container admin-comments-page">
-  <p><a href="/admin" class="btn">&larr; <%= t('acom.back') %></a></p>
-  <h1><%= t('acom.title') %></h1>
-
-  <p class="muted">
-    <%= t('acom.mode_for_site') %> <strong><%= moderationMode %></strong>
-    <% if (moderationMode === 'trust') { %>
-      &mdash; <%= t('acom.mode_trust_a') %> <em><%= t('acom.mode_moderate_word') %></em>
-      <a href="/admin/sites/<%= site.slug %>/edit"><%= t('acom.site_settings') %></a> <%= t('acom.mode_trust_b') %>
-    <% } else { %>
-      &mdash; <%= t('acom.mode_moderate_hint') %>
-    <% } %>
-  </p>
-
-  <% if (success) { %><div class="audio-flash audio-flash--ok"><%= success %></div><% } %>
-  <% if (error)   { %><div class="audio-flash audio-flash--err"><%= error %></div><% } %>
-
-  <h2><%= t('acom.pending', { n: pending.length }) %></h2>
-  <% if (!pending.length) { %>
-    <p class="muted"><%= t('acom.nothing_waiting') %></p>
-  <% } else { %>
-    <%
-      var _c_reply    = t('acom.reply');
-      var _c_on       = t('acom.on');
-      var _c_approve  = t('acom.approve');
-      var _c_reject   = t('acom.reject');
-    %>
-    <ol class="moderation-list">
-      <% pending.forEach(function(c) { %>
-        <li class="moderation-item">
-          <div class="moderation-meta">
-            <strong><%= c.author_username %></strong>
-            <% if (c.parent_comment_id) { %><span class="muted">(<%= _c_reply %>)</span><% } %>
-            <%= _c_on %> <a href="<%= siteUrlBase %>/<%= c.post_slug %>"><%= c.post_title || c.post_slug %></a>
-            <span class="muted">&middot; <%= formatDateTime(c.created_at) %></span>
-          </div>
-          <blockquote class="moderation-content"><%= c.content %></blockquote>
-          <div class="moderation-actions">
-            <form method="post" action="<%= siteUrlBase %>/admin/comments/<%= c.id %>/approve" style="display:inline">
-              <button type="submit" class="btn btn-primary"><%= _c_approve %></button>
-            </form>
-            <form method="post" action="<%= siteUrlBase %>/admin/comments/<%= c.id %>/reject" style="display:inline">
-              <button type="submit" class="btn btn-danger"><%= _c_reject %></button>
-            </form>
-          </div>
-        </li>
-      <% }); %>
-    </ol>
-  <% } %>
-
-  <h2><%= t('acom.recent') %></h2>
-  <% if (!recent.length) { %>
-    <p class="muted"><%= t('acom.nothing_yet') %></p>
-  <% } else { %>
-    <ul class="decision-list">
-      <% recent.forEach(function(c) { %>
-        <li class="decision-card decision-card--<%= c.status %>">
-          <span class="status-pill status-pill--<%= c.status %>"><%= c.status %></span>
-          <div class="decision-main">
-            <span class="decision-author"><%= c.author_username %></span>
-            <a class="decision-post" href="<%= siteUrlBase %>/<%= c.post_slug %>"><%= c.post_title || c.post_slug %></a>
-          </div>
-          <span class="decision-date"><%= formatDateTime(c.created_at) %></span>
-        </li>
-      <% }); %>
-    </ul>
-  <% } %>
-</div>
-
-<style>
-.admin-comments-page { max-width: 900px; margin: 3rem auto; padding: 0 1rem; }
-.admin-comments-page h1 { font-family: var(--font-display, serif); font-size: 2rem; margin: 0 0 1rem; }
-.admin-comments-page h2 { font-family: var(--font-display, serif); font-size: 1.25rem; margin: 1.5rem 0 0.75rem; }
-.muted { color: var(--ink-muted, var(--ink-soft)); }
-.muted a { color: var(--accent); }
-
-.moderation-list { list-style: none; padding: 0; margin: 0; display: flex; flex-direction: column; gap: 1rem; }
-.moderation-item {
-  background: var(--paper-2);
-  border: 1px solid var(--rule);
-  border-radius: 8px;
-  padding: 1rem;
-}
-.moderation-meta { font-size: 0.85rem; margin-bottom: 0.5rem; color: var(--ink-soft); }
-.moderation-meta a { color: var(--accent); }
-.moderation-content {
-  margin: 0 0 0.75rem;
-  padding: 0.5rem 0.75rem;
-  border-left: 3px solid var(--accent);
-  background: var(--paper);
-  white-space: pre-wrap;
-  word-wrap: break-word;
-  color: var(--ink);
-}
-.moderation-actions { display: flex; gap: 0.5rem; }
-
-.status-pill {
-  display: inline-block; padding: 0.1rem 0.5rem; border-radius: 10px;
-  font-size: 0.7rem; text-transform: uppercase; letter-spacing: 0.05em;
-}
-.status-pill--approved { background: rgba(40, 160, 90, 0.15); color: #2a9d5e; }
-.status-pill--rejected { background: rgba(200, 60, 60, 0.15); color: #c33; }
-.status-pill--pending  { background: var(--paper); color: var(--ink-muted, var(--ink-soft)); }
-
-/* Recent decisions als cards (i.p.v. een platte tabel) */
-.decision-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 0.6rem; }
-.decision-card {
-  display: flex; align-items: center; gap: 0.85rem;
-  padding: 0.7rem 0.9rem;
-  background: var(--paper-2); border: 1px solid var(--rule);
-  border-left: 3px solid var(--rule); border-radius: 10px;
-}
-.decision-card--approved { border-left-color: #2a9d5e; }
-.decision-card--rejected { border-left-color: #c33; }
-.decision-main { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; }
-.decision-author { font-weight: 600; }
-.decision-post { color: var(--accent); text-decoration: none; font-size: 0.88rem; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
-.decision-post:hover { text-decoration: underline; }
-.decision-date { flex: 0 0 auto; color: var(--ink-muted, var(--ink-soft)); font-size: 0.8rem; white-space: nowrap; font-variant-numeric: tabular-nums; }
-@media (max-width: 520px) {
-  .decision-card { flex-wrap: wrap; }
-  .decision-date { width: 100%; }
-}
-
-.audio-flash { padding: 0.75rem 1rem; border-radius: 6px; margin: 1rem 0; font-size: 0.9rem; }
-.audio-flash--ok { background: rgba(40, 160, 90, 0.15); color: #2a9d5e; border: 1px solid rgba(40, 160, 90, 0.3); }
-.audio-flash--err { background: rgba(200, 60, 60, 0.15); color: #c33; border: 1px solid rgba(200, 60, 60, 0.3); }
-</style>
Index: src/views/pages/admin-site-edit.ejs
===================================================================
--- src/views/pages/admin-site-edit.ejs	(revision 2e9773f664c16b98d6ebb6626b4e5a498f38c448)
+++ src/views/pages/admin-site-edit.ejs	(revision 59f017026eb35cc17dbb5f9fcf7cb3f5a9d9a538)
@@ -147,15 +147,4 @@
         <input type="checkbox" name="robots_index" value="1" <%= site.robots_index ? 'checked' : '' %>>
         <span><%= t('asite.robots_index') %></span>
-      </label>
-      <label class="cb">
-        <input type="checkbox" name="require_login_to_comment" value="1" <%= site.require_login_to_comment ? 'checked' : '' %>>
-        <span><%= t('asite.require_login_comment') %></span>
-      </label>
-      <label>
-        <span><%= t('asite.comment_moderation') %></span>
-        <select name="comments_moderation_mode">
-          <option value="trust"    <%= (site.comments_moderation_mode || 'trust') === 'trust'    ? 'selected' : '' %>><%= t('asite.moderation_trust') %></option>
-          <option value="moderate" <%= site.comments_moderation_mode === 'moderate' ? 'selected' : '' %>><%= t('asite.moderation_moderate') %></option>
-        </select>
       </label>
       <% if (typeof audioEnabled === 'undefined' || audioEnabled) { %>
Index: src/views/pages/admin.ejs
===================================================================
--- src/views/pages/admin.ejs	(revision 2e9773f664c16b98d6ebb6626b4e5a498f38c448)
+++ src/views/pages/admin.ejs	(revision 59f017026eb35cc17dbb5f9fcf7cb3f5a9d9a538)
@@ -31,5 +31,4 @@
       <a href="/admin/playlists" class="btn"><%= t('admin.b_playlists') %></a>
       <% } %>
-      <a href="/admin/comments" class="btn"><%= t('admin.b_comments') %></a>
       <% if (primarySite) { %><a href="/admin/seo" class="btn"><%= t('admin.b_seo') %></a><% } %>
       <a href="/admin/settings" class="btn"><%= t('admin.b_settings') %></a>
@@ -39,5 +38,4 @@
       <a href="/admin/audio" class="btn"><%= t('admin.b_audio') %></a>
       <% } %>
-      <a href="/admin/comments" class="btn"><%= t('admin.b_comments') %></a>
       <% if (primarySite) { %>
         <a href="/admin/sites/<%= primarySite.slug %>/edit" class="btn"><%= t('admin.b_look') %></a>
Index: src/views/pages/my-site.ejs
===================================================================
--- src/views/pages/my-site.ejs	(revision 2e9773f664c16b98d6ebb6626b4e5a498f38c448)
+++ src/views/pages/my-site.ejs	(revision 59f017026eb35cc17dbb5f9fcf7cb3f5a9d9a538)
@@ -7,5 +7,4 @@
     <a href="/user/<%= mySite.slug %>/posts/new" class="btn">✍️ <%= t('myst.new_post') %></a>
     <a href="/admin/sites/<%= mySite.slug %>/edit" class="btn">🎨 <%= t('myst.appearance') %></a>
-    <a href="/user/<%= mySite.slug %>/admin/comments" class="btn">💬 <%= t('myst.comments') %></a>
     <a href="/user/<%= mySite.slug %>" class="btn">👁️ <%= t('myst.view_site') %></a>
     <a href="/account" class="btn">👤 <%= t('myst.account') %></a>
Index: src/views/pages/post.ejs
===================================================================
--- src/views/pages/post.ejs	(revision 2e9773f664c16b98d6ebb6626b4e5a498f38c448)
+++ src/views/pages/post.ejs	(revision 59f017026eb35cc17dbb5f9fcf7cb3f5a9d9a538)
@@ -112,159 +112,4 @@
   </script>
 
-  <!-- Comments -->
-  <section class="post-comments" id="comments">
-    <h2 class="comments-heading">
-      <%= t(totalComments === 1 ? 'comments.heading_one' : 'comments.heading_other', { n: totalComments }) %>
-    </h2>
-
-    <% if (typeof currentPath === 'string' && currentPath && currentPath.indexOf('/' + post.slug) === 0) { %>
-      <% /* If the URL has ?pending=1, the previous submit landed in the moderation queue */ %>
-    <% } %>
-    <script>
-      (function() {
-        if (location.search.indexOf('pending=1') !== -1) {
-          var s = document.createElement('div');
-          s.className = 'comments-pending-flash';
-          s.textContent = <%- JSON.stringify(t('comments.pending')) %>;
-          document.currentScript.parentNode.insertBefore(s, document.currentScript);
-        }
-      })();
-    </script>
-
-    <% if (!comments || !comments.length) { %>
-      <p class="comments-empty"><%= t('comments.empty') %><% if (!user) { %> <a href="/auth/login?next=<%= encodeURIComponent(_base + '/' + post.slug + '#comments') %>"><%= t('nav.login') %></a> <%= t('comments.to_start') %><% } %></p>
-    <% } else { %>
-      <ol class="comments-list">
-        <% comments.forEach(function(c) { %>
-          <li class="comment" id="comment-<%= c.id %>">
-            <div class="comment-avatar">
-              <% if (c.author_avatar) { %>
-                <img src="<%= c.author_avatar %>" alt="">
-              <% } else { %>
-                <span><%= c.author_username.charAt(0).toUpperCase() %></span>
-              <% } %>
-            </div>
-            <div class="comment-body">
-              <div class="comment-meta">
-                <a class="comment-author" href="/users/<%= encodeURIComponent(c.author_username) %>"><%= c.author_username %></a>
-                <span class="comment-time" title="<%= c.created_at %>"><%= formatDateTime(c.created_at) %></span>
-              </div>
-              <div class="comment-content"><%= c.content %></div>
-              <div class="comment-actions">
-                <% if (user && canMutate) { %>
-                  <button type="button" class="comment-reply-btn" data-reply-to="<%= c.id %>"><%= t('comments.reply') %></button>
-                <% } %>
-                <% if (user && permissions.canDeleteComment(user, c, site)) { %>
-                  <form method="post" action="<%= _base %>/comments/<%= c.id %>/delete" onsubmit="return confirm('<%= t('comments.delete_confirm') %>')">
-                    <button type="submit" class="comment-delete-btn"><%= t('comments.delete') %></button>
-                  </form>
-                <% } %>
-              </div>
-
-              <!-- Inline reply form (hidden by default) -->
-              <% if (user && canMutate) { %>
-                <form method="post" action="<%= _base %>/comments" class="comment-reply-form" hidden data-reply-form-for="<%= c.id %>">
-                  <input type="hidden" name="post_slug" value="<%= post.slug %>">
-                  <input type="hidden" name="parent_comment_id" value="<%= c.id %>">
-                  <textarea name="content" rows="3" maxlength="4000" placeholder="<%= t('comments.reply_to', { name: c.author_username }) %>" required></textarea>
-                  <div class="comment-reply-form-actions">
-                    <button type="submit" class="btn btn-primary"><%= t('comments.reply') %></button>
-                    <button type="button" class="btn comment-cancel-reply"><%= t('comments.cancel') %></button>
-                  </div>
-                </form>
-              <% } %>
-
-              <!-- Replies (1 level deep) -->
-              <% if (c.replies && c.replies.length) { %>
-                <ol class="comment-replies">
-                  <% c.replies.forEach(function(r) { %>
-                    <li class="comment comment-reply" id="comment-<%= r.id %>">
-                      <div class="comment-avatar">
-                        <% if (r.author_avatar) { %>
-                          <img src="<%= r.author_avatar %>" alt="">
-                        <% } else { %>
-                          <span><%= r.author_username.charAt(0).toUpperCase() %></span>
-                        <% } %>
-                      </div>
-                      <div class="comment-body">
-                        <div class="comment-meta">
-                          <a class="comment-author" href="/users/<%= encodeURIComponent(r.author_username) %>"><%= r.author_username %></a>
-                          <span class="comment-time"><%= formatDateTime(r.created_at) %></span>
-                        </div>
-                        <div class="comment-content"><%= r.content %></div>
-                        <div class="comment-actions">
-                          <% if (user && canMutate) { %>
-                            <button type="button" class="comment-reply-btn" data-reply-to="<%= r.id %>"><%= t('comments.reply') %></button>
-                          <% } %>
-                          <% if (user && permissions.canDeleteComment(user, r, site)) { %>
-                            <form method="post" action="<%= _base %>/comments/<%= r.id %>/delete" onsubmit="return confirm('<%= t('comments.delete_confirm') %>')">
-                              <button type="submit" class="comment-delete-btn"><%= t('comments.delete') %></button>
-                            </form>
-                          <% } %>
-                        </div>
-
-                        <%# Replying to a reply — lands (via resolvedParent on the
-                            server) in the same thread, so the 1-level depth is preserved. %>
-                        <% if (user && canMutate) { %>
-                          <form method="post" action="<%= _base %>/comments" class="comment-reply-form" hidden data-reply-form-for="<%= r.id %>">
-                            <input type="hidden" name="post_slug" value="<%= post.slug %>">
-                            <input type="hidden" name="parent_comment_id" value="<%= r.id %>">
-                            <textarea name="content" rows="3" maxlength="4000" placeholder="<%= t('comments.reply_to', { name: r.author_username }) %>" required></textarea>
-                            <div class="comment-reply-form-actions">
-                              <button type="submit" class="btn btn-primary"><%= t('comments.reply') %></button>
-                              <button type="button" class="btn comment-cancel-reply"><%= t('comments.cancel') %></button>
-                            </div>
-                          </form>
-                        <% } %>
-                      </div>
-                    </li>
-                  <% }); %>
-                </ol>
-              <% } %>
-            </div>
-          </li>
-        <% }); %>
-      </ol>
-    <% } %>
-
-    <!-- Top-level comment form (only for logged-in users for now) -->
-    <% if (user && canMutate) { %>
-      <form method="post" action="<%= _base %>/comments" class="comment-form">
-        <input type="hidden" name="post_slug" value="<%= post.slug %>">
-        <label class="comment-form-label">
-          <span><%= t('comments.add_as') %> <strong><%= user.username %></strong></span>
-          <textarea name="content" rows="3" maxlength="4000" placeholder="<%= t('comments.placeholder') %>" required></textarea>
-        </label>
-        <button type="submit" class="btn btn-primary"><%= t('comments.post') %></button>
-      </form>
-    <% } else if (!user) { %>
-      <p class="comments-login-cta">
-        <a href="/auth/login?next=<%= encodeURIComponent(_base + '/' + post.slug + '#comments') %>" class="btn"><%= t('comments.login_to_comment') %></a>
-      </p>
-    <% } else { %>
-      <p class="comments-login-cta" style="color:var(--ink-muted)">👁️ Kijker-modus — reageren is uitgeschakeld.</p>
-    <% } %>
-  </section>
-
-  <!-- Reply form toggle -->
-  <script>
-  (function() {
-    document.querySelectorAll('.comment-reply-btn').forEach(function(btn) {
-      btn.addEventListener('click', function() {
-        var id = btn.dataset.replyTo;
-        var form = document.querySelector('[data-reply-form-for="' + id + '"]');
-        if (form) {
-          form.hidden = !form.hidden;
-          if (!form.hidden) form.querySelector('textarea').focus();
-        }
-      });
-    });
-    document.querySelectorAll('.comment-cancel-reply').forEach(function(btn) {
-      btn.addEventListener('click', function() {
-        btn.closest('.comment-reply-form').hidden = true;
-      });
-    });
-  })();
-  </script>
 
   <%# ── Related posts (3-card grid) ─────────────────────────────
