diff --git a/public/app.js b/public/app.js
index b89a022..40b0869 100755
--- a/public/app.js
+++ b/public/app.js
@@ -1,7 +1,8 @@
/**
- * app.js – v3.3.1 PREVIEW + PORTAL
+ * app.js – v3.3.2 PRECISION LAYOUT
* High-coherence, readable, maintainable.
* No hacks. No surgery. Only truth.
+ * Now with preview spacing precision.
*/
const els = {
@@ -248,6 +249,12 @@ async function generatePreview(rel) {
.replace(/\s+(on\w+)=["'][^"']*["']/gi, "")
.replace(/\s+style=["'][^"']*["']/gi, "");
+ // Normalize whitespace and strip blank nodes
+ content = content.replace(/^\s+|\s+$/g, '').replace(/(\n\s*){2,}/g, '\n');
+
+ // Remove stray
or empty paragraph tags that create phantom space
+ content = content.replace(/
\s*<\/p>/gi, '').replace(/
/gi, '');
+
const div = document.createElement("div");
div.innerHTML = content;
trimPreview(div, 3, 3000); // depth, char limit
diff --git a/public/styles.css b/public/styles.css
index c60e900..4a03e55 100755
--- a/public/styles.css
+++ b/public/styles.css
@@ -269,3 +269,35 @@ body.sidebar-open #sidebar { transform: translateX(0); }
.preview-content a:hover {
text-shadow: 0 0 6px var(--accent);
}
+
+/* === PREVIEW SPACING FIX === */
+
+/* Remove top margin from the first visible child */
+.preview-content > *:first-child {
+ margin-top: 0 !important;
+ padding-top: 0 !important;
+}
+
+/* Consistent bottom rhythm for the last visible element */
+.preview-content > *:last-child {
+ margin-bottom: 3rem;
+}
+
+/* Responsive typography scaling for mobile preview */
+@media (max-width: 768px) {
+ .preview-content {
+ padding: 2rem 6vw;
+ line-height: 1.65;
+ }
+}
+
+/* Ellipsis alignment fix */
+.preview-content p:empty::before {
+ content: "...";
+ color: var(--accent);
+ opacity: 0.6;
+ display: block;
+ text-align: center;
+ margin: 1.5rem 0;
+ letter-spacing: 0.2em;
+}