Index: src/views/pages/post.ejs
===================================================================
--- src/views/pages/post.ejs	(revision 6ea5f923743b370e17c3dbbafa7e544f9fa037d0)
+++ src/views/pages/post.ejs	(revision 8d054ca78b96ac3a4806f34e94230cd7da8f77a8)
@@ -383,4 +383,5 @@
   resize: vertical;
   min-height: 70px;
+  max-height: 200px;
   padding: 0.65rem 0.85rem;
   border: 1px solid var(--rule);
Index: src/views/shell.ejs
===================================================================
--- src/views/shell.ejs	(revision 6ea5f923743b370e17c3dbbafa7e544f9fa037d0)
+++ src/views/shell.ejs	(revision 8d054ca78b96ac3a4806f34e94230cd7da8f77a8)
@@ -684,7 +684,14 @@
   function autoSize(ta) {
     if (!ta || ta.tagName !== 'TEXTAREA') return;
-    ta.style.overflowY = 'hidden';
+    // Skip hidden textareas (e.g. inside a closed <details> or an unopened reply
+    // box): measuring scrollHeight there yields a bad height that sticks as inline
+    // style and makes the field open huge. They get sized on focus once visible.
+    if (ta.offsetParent === null && ta.offsetHeight === 0) return;
     ta.style.height = 'auto';
-    ta.style.height = ta.scrollHeight + 'px';
+    var maxH = parseFloat(getComputedStyle(ta).maxHeight);
+    var sh = ta.scrollHeight;
+    var h = (maxH && !isNaN(maxH)) ? Math.min(sh, maxH) : sh;   // respect a CSS max-height
+    ta.style.height = h + 'px';
+    ta.style.overflowY = sh > h ? 'auto' : 'hidden';
   }
   function sizeAll(root) {
