Index: src/views/pages/messages.ejs
===================================================================
--- src/views/pages/messages.ejs	(revision 39111c02cd42a6149a332d4b510b61873cbb2522)
+++ src/views/pages/messages.ejs	(revision 189e335181d42f72a28a9744f64da578c83bbda7)
@@ -2,6 +2,6 @@
   <%- include('../partials/fedi-tabs', { active: 'berichten' }) %>
   <h1 class="msg-title"><%= t('msg.title') %></h1>
-  <% if (typeof success !== 'undefined' && success) { %><div class="alert alert-success"><%= success === 'guardian_accepted' ? t('msg.guard_accepted') : (success === 'guardian_rejected' ? t('msg.guard_rejected') : (success === 'wave_sent' ? t('msg.wave_sent') : success)) %></div><% } %>
-  <% if (typeof error !== 'undefined' && error) { %><div class="alert alert-error"><%= error === 'guardianship' ? t('msg.guard_failed') : error %></div><% } %>
+  <% if (typeof success !== 'undefined' && success) { %><div class="alert alert-success"><%= success === 'guardian_accepted' ? t('msg.guard_accepted') : (success === 'guardian_rejected' ? t('msg.guard_rejected') : (success === 'wave_sent' ? t('msg.wave_sent') : (success === 'reply_sent' ? t('msg.reply_sent') : success))) %></div><% } %>
+  <% if (typeof error !== 'undefined' && error) { %><div class="alert alert-error"><%= error === 'guardianship' ? t('msg.guard_failed') : (error === 'reply_empty' ? t('msg.reply_empty') : ((error === 'reply_failed' || error === 'reply_target') ? t('msg.reply_failed') : error)) %></div><% } %>
 
   <%# FEP-633c: a pending guardianship offer is a special message: the kid
@@ -191,4 +191,14 @@
   .msg-sub .msg-line { flex-wrap: wrap; }
 
+  /* De voet van een gesprek: antwoorden en zwaaien naast elkaar, ingeklapt.
+     Een open editor onder elk gesprek maakt de lijst weer onleesbaar -- precies
+     wat deze weergave moest oplossen. */
+  .msg-thread-foot { display: flex; align-items: flex-start; gap: .5rem; margin-top: .5rem; flex-wrap: wrap; }
+  .msg-reply { flex: 1 1 12rem; min-width: 0; }
+  .msg-reply > summary { cursor: pointer; font-size: .82rem; color: var(--ink-soft, #888); }
+  .msg-reply[open] > summary { margin-bottom: .4rem; }
+  .msg-reply-form { min-width: 0; }
+  .msg-wave button { line-height: 1.2; }
+
   @media (max-width: 560px) {
     /* Op een telefoon is 40px avatar per bubbel puur verlies: de naam staat er
Index: src/views/partials/msg-item.ejs
===================================================================
--- src/views/partials/msg-item.ejs	(revision 39111c02cd42a6149a332d4b510b61873cbb2522)
+++ src/views/partials/msg-item.ejs	(revision 189e335181d42f72a28a9744f64da578c83bbda7)
@@ -30,4 +30,38 @@
             <% (n.messages || []).forEach(function (m) { %><%- include('msg-item', { n: m, seen: _tseen, inThread: true }) %><% }); %>
           </ul>
+          <%# Antwoorden vanuit de draad zelf. Ingeklapt, want een open editor
+              onder elk gesprek maakt de lijst onleesbaar -- juist het probleem
+              dat deze weergave moest oplossen. De route kiest het pad: een
+              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); %>
+          <% if (_kan) { %>
+            <div class="msg-thread-foot">
+              <details class="msg-reply">
+                <summary><%= t('fedi.reply') %></summary>
+                <div class="msg-reply-form">
+                  <%- include('../partials/reply-editor', {
+                    action: (typeof siteUrlBase !== 'undefined' ? siteUrlBase : '') + '/messages/reply',
+                    hiddenFields: [
+                      { name: 'interaction_id', value: _rt.interactionId || '' },
+                      { name: 'post_slug', value: _rt.postSlug || '' },
+                      { name: 'to', value: _rt.actorUri || '' },
+                    ],
+                    placeholder: t('fedi.reply_ph'),
+                    submitLabel: t('fedi.reply'),
+                    rows: 2,
+                  }) %>
+                </div>
+              </details>
+              <%# De zwaai blijft een eigen knop: het is geen antwoord maar een
+                  seintje (FEP-633c), en die twee horen niet op een hoop. %>
+              <% if (_rt.actorUri) { %>
+                <form method="post" action="<%= (typeof siteUrlBase !== 'undefined' ? siteUrlBase : '') %>/messages/quick-reply" class="msg-wave">
+                  <input type="hidden" name="to" value="<%= _rt.actorUri %>">
+                  <button class="btn small" name="text" value="&#128075;" title="<%= t('msg.wave_back') %>">&#128075;</button>
+                </form>
+              <% } %>
+            </div>
+          <% } %>
         </li>
 <% } else { %>
