thefoldwithin-earth/public/app.js
Mark Randall Havens bac53539b4 revision
2025-11-09 19:22:23 +00:00

309 lines
6.7 KiB
JavaScript
Executable file
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

:root {
--bg: #0b0b0b;
--fg: #e6e3d7;
--accent: #e0b84b;
--topbar-h: 56px;
--subnav-h: 44px;
--transition: .3s ease;
--radius: 8px;
}
* { box-sizing: border-box; }
html, body {
margin: 0; padding: 0; height: 100%;
background: var(--bg); color: var(--fg);
font-family: 'Inter', system-ui, sans-serif;
line-height: 1.6;
}
/* === TOPBAR & NAV === */
.topbar {
position: fixed; top: 0; left: 0; right: 0;
height: var(--topbar-h); display: flex; align-items: center;
background: #111; border-bottom: 1px solid #222;
padding: 0 1rem; z-index: 1000; gap: 1.5rem;
overflow: hidden;
}
#menuBtn {
background: none; border: 0; color: var(--accent);
font-size: 1.4rem; cursor: pointer; font-weight: bold;
line-height: 1; padding: 0; margin: 0;
min-width: 2.5rem;
}
.primary-nav {
display: flex; flex-wrap: wrap; gap: 1.5rem; align-items: center;
overflow-x: auto;
white-space: nowrap;
}
.primary-nav a {
color: var(--accent); text-decoration: none;
font-weight: 600; font-size: 1.1rem;
transition: all var(--transition);
}
.primary-nav a:hover {
text-shadow: 0 0 10px var(--accent);
}
/* === SUBNAV === */
.sub-nav {
display: none;
position: fixed;
top: var(--topbar-h);
left: 0; right: 0;
height: var(--subnav-h);
background: #0e0e0e;
border-bottom: 1px solid #222;
padding: 0 1rem;
gap: 1rem;
overflow-x: auto;
white-space: nowrap;
z-index: 950;
align-items: center;
opacity: 0;
transform: translateY(-5px);
transition: opacity var(--transition), transform var(--transition);
}
.sub-nav.visible {
display: flex;
opacity: 1;
transform: translateY(0);
animation: fadeSlideDown .3s ease forwards;
}
@keyframes fadeSlideDown {
from { opacity: 0; transform: translateY(-5px); }
to { opacity: 1; transform: translateY(0); }
}
.sub-nav a {
color: var(--accent);
text-decoration: none;
font-weight: 500;
font-size: 0.95rem;
transition: all var(--transition);
}
.sub-nav a:hover {
text-shadow: 0 0 8px var(--accent);
}
/* === SIDEBAR === */
#sidebar {
position: fixed; top: calc(var(--topbar-h) + var(--subnav-h)); left: 0;
width: 300px; bottom: 0; overflow: auto;
background: #111; border-right: 1px solid #222;
transform: translateX(-100%); transition: transform var(--transition);
z-index: 900; padding: 1rem;
}
body.sidebar-open #sidebar { transform: translateX(0); }
.sidebar-header {
display: flex; justify-content: space-between; align-items: center;
margin-bottom: 1rem; padding-bottom: .5rem; border-bottom: 1px solid #222;
}
.sidebar-header h3 {
margin: 0; font-size: 1.1rem; color: var(--accent);
}
.toggle-btn {
background: none; border: 1px solid #333; color: var(--fg);
padding: .25rem .5rem; border-radius: var(--radius);
font-size: .8rem; cursor: pointer;
}
#postListSection { margin-bottom: 1rem; }
#postList {
list-style: none; margin: 0; padding: 0;
}
#postList li {
margin: .75rem 0; padding: .5rem 0;
border-bottom: 1px dashed #222;
transition: color var(--transition);
}
#postList a {
color: var(--fg); text-decoration: none; font-weight: 500;
display: block;
}
#postList a:hover { color: var(--accent); }
#postList small {
display: block; font-size: .8rem; color: #888; margin-top: .25rem;
}
.filter-panel {
background: #0a0a0a; border: 1px solid #222;
border-radius: var(--radius); padding: .75rem;
margin-top: 1rem;
}
.filter-panel summary {
cursor: pointer; font-weight: 600; color: var(--accent);
margin-bottom: .5rem; user-select: none;
}
.filter-controls {
display: flex; flex-direction: column; gap: .75rem;
}
.filter-controls label {
font-size: .85rem; color: var(--accent); margin-bottom: .25rem;
}
.filter-controls select, .filter-controls input {
background: #111; color: var(--fg); border: 1px solid #333;
padding: .5rem; border-radius: var(--radius); font-size: .9rem;
}
.filter-controls select[multiple] {
height: 80px;
}
.content {
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: 0;
}
@media (min-width: 1024px) {
#sidebar { transform: translateX(0); top: calc(var(--topbar-h) + var(--subnav-h)); }
.content { margin-left: 300px; }
}
/* === VIEWER BREATHING FIELD === */
.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 > * {
width: 100%;
margin: 0;
padding: 0;
animation: fadeIn .4s ease-out;
}
@keyframes fadeIn {
from { opacity: 0; transform: translateY(10px); }
to { opacity: 1; transform: translateY(0); }
}
/* === PREVIEW + PORTAL === */
.preview-header {
display: flex;
justify-content: flex-end;
padding: 0.5rem 1rem;
background: rgba(224, 184, 75, 0.08);
border-bottom: 1px solid #333;
position: sticky;
top: 0;
z-index: 10;
}
.portal-btn {
background: none;
border: 1px solid var(--accent);
color: var(--accent);
border-radius: 6px;
padding: 0.25rem 0.75rem;
font-size: 0.85rem;
cursor: pointer;
transition: all 0.2s ease;
}
.portal-btn:hover {
background: var(--accent);
color: var(--bg);
}
.preview-content {
padding: 3rem 4vw;
max-width: 90ch;
margin: auto;
line-height: 1.7;
color: var(--fg);
font-family: 'Inter', system-ui, sans-serif;
}
.preview-content * {
background: transparent !important;
color: inherit !important;
font-family: inherit !important;
}
.preview-content img,
.preview-content video,
.preview-content iframe {
max-width: 100%;
height: auto;
border-radius: 8px;
margin: 1.5rem 0;
display: block;
}
.preview-content a {
color: var(--accent);
text-decoration: underline;
text-decoration-thickness: 1px;
text-underline-offset: 2px;
}
.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;
animation: fadeEllipsis 1.2s ease-in-out infinite alternate;
}
@keyframes fadeEllipsis {
from { opacity: 0.3; letter-spacing: 0.15em; }
to { opacity: 0.6; letter-spacing: 0.25em; }
}