diff --git a/package.json b/package.json index 7d0268c..b6559af 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "the-fold-within", - "version": "3.0.0", + "version": "3.1.0", "dependencies": { "pdf-parse": "^1.1.1" } -} \ No newline at end of file +} diff --git a/public/app.js b/public/app.js index 5eea0f3..829d184 100755 --- a/public/app.js +++ b/public/app.js @@ -167,9 +167,8 @@ function renderSubNav(parent) { async function handleHash() { els.viewer.innerHTML = ""; const rel = location.hash.replace(/^#\//, ""); - const parts = rel.split("/").filter(Boolean); // e.g., ["about", "Mark"] + const parts = rel.split("/").filter(Boolean); - // Determine current depth parent for subnav const currentParentPath = parts.slice(0, -1).join("/") || parts[0] || null; if (currentParentPath !== currentParent) { @@ -177,7 +176,6 @@ async function handleHash() { renderSubNav(currentParent); } - // Sync sidebar section to top-level const topSection = parts[0] || null; if (topSection && indexData.sections.includes(topSection)) { els.sectionSelect.value = topSection; @@ -186,7 +184,6 @@ async function handleHash() { if (!rel) return renderDefault(); - // CASE: Trailing slash → render index at *current* level if (rel.endsWith('/')) { const currentPath = parts.join("/"); @@ -202,34 +199,12 @@ async function handleHash() { const html = marked.parse(src || `# ${currentPath.split("/").pop()}\n\nNo content yet.`); els.viewer.innerHTML = `
${html}
`; } else { - const iframe = document.createElement("iframe"); - iframe.src = "/" + indexFile.path; - iframe.loading = "eager"; - iframe.setAttribute("sandbox", "allow-same-origin allow-scripts allow-forms"); - els.viewer.appendChild(iframe); - - iframe.onload = () => { - try { - const doc = iframe.contentDocument; - const body = doc.body; - const hasContent = body && body.innerText.trim().length > 50; - if (!hasContent) { - doc.body.innerHTML = ` -
-

${currentPath.split("/").pop()}

-

No content yet.

-
- `; - doc.body.style.background = "#0b0b0b"; - } - } catch (e) {} - }; + renderIframe("/" + indexFile.path); } } catch (e) { els.viewer.innerHTML = `

${currentPath.split("/").pop()}

No content yet.

`; } } else { - // No index → show children or fallback if (topSection) { els.sectionSelect.value = topSection; renderList(); @@ -239,14 +214,13 @@ async function handleHash() { } } } - // CASE: Direct file else { const file = indexData.flat.find(f => f.path === rel); if (!file) { els.viewer.innerHTML = "

404

Not found.

"; return; } - file.ext === ".md" ? await renderMarkdown(file.path) : renderIframe(file.path); + file.ext === ".md" ? await renderMarkdown(file.path) : renderIframe("/" + file.path); } } @@ -255,11 +229,17 @@ async function renderMarkdown(rel) { els.viewer.innerHTML = `
${marked.parse(src || "# Untitled")}
`; } -function renderIframe(rel) { +function renderIframe(src) { const iframe = document.createElement("iframe"); - iframe.src = "/" + rel; + iframe.src = src; iframe.loading = "eager"; - iframe.setAttribute("sandbox", "allow-same-origin allow-scripts allow-forms"); + iframe.setAttribute("sandbox", "allow-same-origin allow-scripts allow-forms allow-popups"); + iframe.style.width = "100vw"; + iframe.style.height = "calc(100vh - var(--topbar-h) - var(--subnav-h))"; + iframe.style.border = "none"; + iframe.style.borderRadius = "0"; + iframe.style.margin = "0"; + els.viewer.appendChild(iframe); iframe.onload = () => { @@ -267,11 +247,29 @@ function renderIframe(rel) { const doc = iframe.contentDocument; const style = doc.createElement("style"); style.textContent = ` - html,body{background:#0b0b0b;color:#e6e3d7;font-family:Inter,sans-serif;margin:0;padding:2rem;} - *{max-width:720px;margin:auto;} - img, video, iframe {max-width:100%;height:auto;} + html, body { + background: transparent; + color: inherit; + font-family: inherit; + margin: 0; + padding: 3rem 4vw; + } + * { max-width: 100%; } + img, video, iframe { max-width: 100%; height: auto; } `; doc.head.appendChild(style); + + const body = doc.body; + const hasContent = body && body.innerText.trim().length > 50; + if (!hasContent) { + doc.body.innerHTML = ` +
+

${src.split("/").pop().replace(/\..*$/, "")}

+

No content yet.

+
+ `; + doc.body.style.background = "transparent"; + } } catch (e) {} }; } @@ -287,4 +285,4 @@ function renderDefault() { } } -init(); \ No newline at end of file +init(); diff --git a/public/styles.css b/public/styles.css index 4ca4c03..667e7aa 100755 --- a/public/styles.css +++ b/public/styles.css @@ -172,7 +172,7 @@ body.sidebar-open #sidebar { transform: translateX(0); } margin-top: calc(var(--topbar-h) + var(--subnav-h)); margin-left: 0; transition: margin-left var(--transition), margin-top var(--transition); min-height: calc(100vh - var(--topbar-h) - var(--subnav-h)); - padding: 2rem 1rem; + padding: 0; } @media (min-width: 1024px) { @@ -180,8 +180,22 @@ body.sidebar-open #sidebar { transform: translateX(0); } .content { margin-left: 300px; } } +/* BREATHING HORIZON: Full-Field Viewer */ +.viewer { + display: flex; + flex-direction: column; + height: 100%; + transition: background 1s ease; +} + +.viewer:hover { + background: radial-gradient(circle at center, #111 0%, #0b0b0b 80%); +} + .viewer > * { - max-width: 720px; margin: auto; padding: 2rem 1rem; + width: 100%; + margin: 0; + padding: 3rem 4vw; animation: fadeIn .4s ease-out; } @@ -191,7 +205,11 @@ body.sidebar-open #sidebar { transform: translateX(0); } } .viewer iframe { - width: 100%; height: calc(100vh - var(--topbar-h) - var(--subnav-h) - 80px); - border: 0; border-radius: var(--radius); background: transparent; + flex: 1; + width: 100vw; + min-height: 100vh; + border: none; + border-radius: 0; + margin: 0; display: block; -} \ No newline at end of file +}