Index: src/middleware/site.js
===================================================================
--- src/middleware/site.js	(revision ffb371c9ca5e604bafcaa70ff4da6cb5c673cf82)
+++ src/middleware/site.js	(revision 34e63f06ca6b67732e6929f4e9fc59c0017e608c)
@@ -12,4 +12,5 @@
 import { audioUrl } from '../services/AudioStreamService.js';
 import { audioEnabled } from '../config/features.js';
+import * as Guardianship from '../services/guardianship/index.js';
 
 /**
@@ -33,4 +34,12 @@
     res.locals.site = defaultSite;
     res.locals.siteUrlBase = '';
+    // Mag deze account antwoorden (shaer-r4c)? Eén keer hier, zodat de
+    // antwoordvelden in de views hem kunnen lezen zonder dat elke route hem
+    // apart doorgeeft. De server weigert het antwoord toch al in deliverReply;
+    // dit voorkomt alleen dat een kind tegen een deur duwt die op slot zit.
+    try {
+      const isWard = Guardianship.listGuardians(defaultSite.slug).length > 0;
+      res.locals.mayReply = Guardianship.wardGateAllowed(defaultSite.gate_replies, isWard);
+    } catch { res.locals.mayReply = true; }
   }
 
Index: src/views/pages/authorize-interaction.ejs
===================================================================
--- src/views/pages/authorize-interaction.ejs	(revision ffb371c9ca5e604bafcaa70ff4da6cb5c673cf82)
+++ src/views/pages/authorize-interaction.ejs	(revision 34e63f06ca6b67732e6929f4e9fc59c0017e608c)
@@ -174,4 +174,5 @@
       </form>
     </div>
+    <% if (locals.mayReply !== false) { %>
     <p class="auth-interact-or"><%= t('fedi.or_reply') %></p>
     <p class="auth-interact-where">💬 <%= t('fedi.reply_where') %></p>
@@ -191,4 +192,5 @@
       <div class="auth-interact-actions"><a href="<%= uri %>" class="btn"><%= t('comments.cancel') %></a></div>
     </div>
+    <% } %>
     <p class="auth-interact-note"><%= t('fedi.remote_as', { site: siteTitle }) %></p>
     <details class="auth-report">
Index: src/views/partials/fedi-node.ejs
===================================================================
--- src/views/partials/fedi-node.ejs	(revision ffb371c9ca5e604bafcaa70ff4da6cb5c673cf82)
+++ src/views/partials/fedi-node.ejs	(revision 34e63f06ca6b67732e6929f4e9fc59c0017e608c)
@@ -46,4 +46,5 @@
         <button type="submit" class="fedi-cact fedi-cact-boost<%= n.acted_boost ? ' is-on' : '' %>" title="<%= n.acted_boost ? t('tl.unboost') : t('fedi.boost_short') %>" aria-label="<%= n.acted_boost ? t('tl.unboost') : t('fedi.boost_short') %>"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><polyline points="17 1 21 5 17 9"/><path d="M3 11V9a4 4 0 0 1 4-4h14"/><polyline points="7 23 3 19 7 15"/><path d="M21 13v2a4 4 0 0 1-4 4H3"/></svg></button>
       </form>
+      <% if (locals.mayReply !== false) { %>
       <details class="fedi-owner-reply">
         <summary class="fedi-cact fedi-cact-reply" title="<%= t('fedi.remote_reply_short') %>" aria-label="<%= t('fedi.remote_reply_short') %>"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><polyline points="9 17 4 12 9 7"/><path d="M20 18v-2a4 4 0 0 0-4-4H4"/></svg></summary>
@@ -57,4 +58,5 @@
         }) %>
       </details>
+      <% } %>
       <%# Owner moderation: report to their instance + remove (tombstoned: never comes back via re-delivery or thread-crawl). %>
       <form method="post" action="<%= _base %>/interactions/<%= n.id %>/report" class="fedi-owner-react" data-confirm="<%= t('fedi.mod_report_confirm') %>">
Index: src/views/partials/msg-item.ejs
===================================================================
--- src/views/partials/msg-item.ejs	(revision ffb371c9ca5e604bafcaa70ff4da6cb5c673cf82)
+++ src/views/partials/msg-item.ejs	(revision 34e63f06ca6b67732e6929f4e9fc59c0017e608c)
@@ -48,5 +48,10 @@
               draad aan een post krijgt een reply, een draad aan een persoon een
               direct bericht. %>
-          <% var _rt = n.replyTo || {}; var _kan = canMutate && ((_rt.interactionId && _rt.postSlug) || _rt.actorUri); %>
+          <%# shaer-r4c: precies de tak die de server ook kiest. /messages/reply
+              gaat naar deliverReply als er een interaction+post is (dat is een
+              ANTWOORD en valt onder de poort), en anders naar deliverDirectNote
+              (dat is een bericht, andere poort). Alleen de eerste verbergen. %>
+          <% var _rt = n.replyTo || {}; var _thread = _rt.interactionId && _rt.postSlug; %>
+          <% var _kan = canMutate && ((_thread && locals.mayReply !== false) || (!_thread && _rt.actorUri)); %>
           <% if (_kan) { %>
             <div class="msg-thread-foot">
