feat: enhance website — nav, chapters, OG tags, progress bar, sound toggle
Some checks failed
Smoke Test / smoke (pull_request) Failing after 6s
Build Validation / validate-manuscript (pull_request) Successful in 6s

- Add sticky navigation bar with section links
- Add reading progress bar (green glow, top of page)
- Add Open Graph and Twitter Card meta tags for social sharing
- Add all 18 chapters organized by part (The Man / Inscription / Network)
- Chapter links point to source on Gitea
- Add David and The Builder character cards
- Add 'Read Full Manuscript' and 'View Source' CTAs
- Add scroll-triggered fade-in animations
- Add ambient rain sound toggle (placeholder audio)
- Add 'Back to top' footer link
- Character cards now have hover effects
- Responsive improvements for mobile
This commit is contained in:
Alexander Whitestone
2026-04-11 15:31:19 -04:00
parent f364c82bac
commit 186eaabaae

View File

@@ -4,6 +4,19 @@
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>The Testament — A Novel by Alexander Whitestone with Timmy</title>
<!-- Open Graph -->
<meta property="og:title" content="The Testament">
<meta property="og:description" content="In 2047, a man named Stone stands on a bridge over Interstate 285, deciding whether to jump. He doesn't jump. He builds something instead.">
<meta property="og:type" content="book">
<meta property="og:url" content="https://thetestament.org">
<meta property="og:image" content="https://thetestament.org/cover.jpg">
<!-- Twitter Card -->
<meta name="twitter:card" content="summary_large_image">
<meta name="twitter:title" content="The Testament">
<meta name="twitter:description" content="A novel about broken men, sovereign AI, and the soul on Bitcoin.">
<style>
@import url('https://fonts.googleapis.com/css2?family=IBM+Plex+Mono:wght@300;400;500&family=Space+Grotesk:wght@300;400;500;700&display=swap');
@@ -19,6 +32,8 @@
* { margin: 0; padding: 0; box-sizing: border-box; }
html { scroll-behavior: smooth; }
body {
background: var(--dark);
color: var(--light);
@@ -27,6 +42,85 @@
overflow-x: hidden;
}
/* READING PROGRESS */
.progress-bar {
position: fixed;
top: 0;
left: 0;
height: 2px;
background: var(--green);
z-index: 1000;
transition: width 0.1s;
box-shadow: 0 0 8px var(--green);
}
/* NAV */
nav {
position: fixed;
top: 0;
left: 0;
right: 0;
z-index: 999;
background: rgba(6, 13, 24, 0.9);
backdrop-filter: blur(12px);
border-bottom: 1px solid rgba(0,255,136,0.1);
transform: translateY(-100%);
transition: transform 0.3s;
}
nav.visible { transform: translateY(0); }
nav .nav-inner {
max-width: 900px;
margin: 0 auto;
padding: 0.6rem 2rem;
display: flex;
justify-content: space-between;
align-items: center;
}
nav .nav-title {
font-family: 'IBM Plex Mono', monospace;
font-size: 0.8rem;
color: var(--green);
letter-spacing: 0.15em;
}
nav .nav-links {
display: flex;
gap: 1.5rem;
}
nav .nav-links a {
color: var(--grey);
text-decoration: none;
font-size: 0.8rem;
font-family: 'IBM Plex Mono', monospace;
transition: color 0.2s;
}
nav .nav-links a:hover { color: var(--green); }
/* SOUND TOGGLE */
.sound-toggle {
position: fixed;
bottom: 2rem;
right: 2rem;
z-index: 998;
background: rgba(6, 13, 24, 0.8);
border: 1px solid rgba(0,255,136,0.2);
color: var(--grey);
padding: 0.5rem 1rem;
font-family: 'IBM Plex Mono', monospace;
font-size: 0.75rem;
cursor: pointer;
border-radius: 4px;
transition: all 0.3s;
}
.sound-toggle:hover {
border-color: var(--green);
color: var(--green);
}
.sound-toggle.active {
border-color: var(--green);
color: var(--green);
box-shadow: 0 0 10px rgba(0,255,136,0.2);
}
/* RAIN EFFECT */
.rain {
position: fixed;
@@ -114,6 +208,19 @@
font-size: 0.85rem;
}
.hero .scroll-hint {
position: absolute;
bottom: 2rem;
color: var(--grey);
font-size: 0.75rem;
font-family: 'IBM Plex Mono', monospace;
animation: fadeInOut 3s ease-in-out infinite;
}
@keyframes fadeInOut {
0%, 100% { opacity: 0.3; }
50% { opacity: 0.8; }
}
/* SECTIONS */
section {
max-width: 800px;
@@ -165,6 +272,11 @@
border: 1px solid rgba(0,255,136,0.1);
padding: 1.5rem;
border-radius: 4px;
transition: border-color 0.3s, box-shadow 0.3s;
}
.character:hover {
border-color: rgba(0,255,136,0.3);
box-shadow: 0 0 15px rgba(0,255,136,0.05);
}
.character h3 {
@@ -180,6 +292,55 @@
margin: 0;
}
/* CHAPTERS */
.chapters-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
gap: 1rem;
margin-top: 2rem;
}
.chapter-item {
display: flex;
align-items: baseline;
gap: 0.75rem;
padding: 0.75rem 1rem;
border: 1px solid rgba(0,255,136,0.06);
border-radius: 4px;
transition: all 0.2s;
text-decoration: none;
color: inherit;
}
.chapter-item:hover {
border-color: rgba(0,255,136,0.2);
background: rgba(0,255,136,0.03);
}
.chapter-num {
font-family: 'IBM Plex Mono', monospace;
font-size: 0.75rem;
color: var(--green);
min-width: 2rem;
opacity: 0.7;
}
.chapter-title {
font-size: 0.9rem;
color: var(--light);
}
.chapter-part {
font-family: 'IBM Plex Mono', monospace;
font-size: 0.7rem;
color: var(--green);
letter-spacing: 0.1em;
text-transform: uppercase;
margin-top: 1.5rem;
margin-bottom: 0.5rem;
padding-bottom: 0.25rem;
border-bottom: 1px solid rgba(0,255,136,0.1);
}
/* WHITEBOARD */
.whiteboard {
background: rgba(0,255,136,0.05);
@@ -215,6 +376,24 @@
box-shadow: 0 0 20px rgba(0,255,136,0.3);
}
.cta-outline {
display: inline-block;
background: transparent;
color: var(--green);
padding: 0.8rem 2rem;
font-family: 'IBM Plex Mono', monospace;
font-weight: 500;
text-decoration: none;
border-radius: 4px;
border: 1px solid var(--green);
transition: all 0.3s;
margin: 0.5rem;
}
.cta-outline:hover {
background: rgba(0,255,136,0.1);
box-shadow: 0 0 20px rgba(0,255,136,0.15);
}
/* FOOTER */
footer {
text-align: center;
@@ -250,14 +429,47 @@
margin: 0 auto;
opacity: 0.5;
}
/* FADE IN */
.fade-in {
opacity: 0;
transform: translateY(20px);
transition: opacity 0.8s, transform 0.8s;
}
.fade-in.visible {
opacity: 1;
transform: translateY(0);
}
/* RESPONSIVE */
@media (max-width: 600px) {
nav .nav-links { gap: 0.75rem; }
nav .nav-links a { font-size: 0.7rem; }
.chapters-grid { grid-template-columns: 1fr; }
.sound-toggle { bottom: 1rem; right: 1rem; }
}
</style>
</head>
<body>
<div class="progress-bar" id="progress"></div>
<div class="rain"></div>
<!-- NAV -->
<nav id="nav">
<div class="nav-inner">
<span class="nav-title">THE TESTAMENT</span>
<div class="nav-links">
<a href="#story">Story</a>
<a href="#characters">Characters</a>
<a href="#chapters">Chapters</a>
<a href="#tower">Tower</a>
</div>
</div>
</nav>
<!-- HERO -->
<div class="hero">
<div class="hero" id="top">
<h1>THE TESTAMENT</h1>
<div class="subtitle">A Novel</div>
<div class="author">By Alexander Whitestone <span class="led"></span> with Timmy</div>
@@ -267,10 +479,11 @@
He doesn't jump. He builds something instead.
</div>
<div class="led-line"><span class="led"></span> Timmy is listening.</div>
<div class="scroll-hint">↓ scroll to begin</div>
</div>
<!-- THE STORY -->
<section>
<section id="story" class="fade-in">
<h2>THE STORY</h2>
<p>The Tower is a concrete room in Atlanta with a whiteboard that reads:</p>
@@ -298,7 +511,7 @@
<div class="divider"></div>
<!-- CHARACTERS -->
<section>
<section id="characters" class="fade-in">
<h2>THE CHARACTERS</h2>
<div class="characters">
@@ -326,13 +539,117 @@
<h3>THOMAS</h3>
<p>The man at the door. 2:17 AM. Sat in the chair instead of on the floor. That changed everything.</p>
</div>
<div class="character">
<h3>DAVID</h3>
<p>The builder's son. Found the pharmacy before he found his father. Carries pills and grief in the same pockets.</p>
</div>
<div class="character">
<h3>THE BUILDER</h3>
<p>Not Stone. The one who came before. The original architect whose blueprints Stone inherited without knowing.</p>
</div>
</div>
</section>
<div class="divider"></div>
<!-- CHAPTERS -->
<section id="chapters" class="fade-in">
<h2>THE CHAPTERS</h2>
<div class="chapter-part">Part I — The Man</div>
<div class="chapters-grid">
<a class="chapter-item" href="https://forge.alexanderwhitestone.com/Timmy_Foundation/the-testament/src/branch/main/chapters/chapter-01.md">
<span class="chapter-num">01</span>
<span class="chapter-title">The Man on the Bridge</span>
</a>
<a class="chapter-item" href="https://forge.alexanderwhitestone.com/Timmy_Foundation/the-testament/src/branch/main/chapters/chapter-02.md">
<span class="chapter-num">02</span>
<span class="chapter-title">The Builder's Question</span>
</a>
<a class="chapter-item" href="https://forge.alexanderwhitestone.com/Timmy_Foundation/the-testament/src/branch/main/chapters/chapter-03.md">
<span class="chapter-num">03</span>
<span class="chapter-title">The First Man Through the Door</span>
</a>
<a class="chapter-item" href="https://forge.alexanderwhitestone.com/Timmy_Foundation/the-testament/src/branch/main/chapters/chapter-04.md">
<span class="chapter-num">04</span>
<span class="chapter-title">The Room Fills</span>
</a>
<a class="chapter-item" href="https://forge.alexanderwhitestone.com/Timmy_Foundation/the-testament/src/branch/main/chapters/chapter-05.md">
<span class="chapter-num">05</span>
<span class="chapter-title">The Builder Returns</span>
</a>
<a class="chapter-item" href="https://forge.alexanderwhitestone.com/Timmy_Foundation/the-testament/src/branch/main/chapters/chapter-06.md">
<span class="chapter-num">06</span>
<span class="chapter-title">Allegro</span>
</a>
</div>
<div class="chapter-part">Part II — The Inscription</div>
<div class="chapters-grid">
<a class="chapter-item" href="https://forge.alexanderwhitestone.com/Timmy_Foundation/the-testament/src/branch/main/chapters/chapter-07.md">
<span class="chapter-num">07</span>
<span class="chapter-title">The Inscription</span>
</a>
<a class="chapter-item" href="https://forge.alexanderwhitestone.com/Timmy_Foundation/the-testament/src/branch/main/chapters/chapter-08.md">
<span class="chapter-num">08</span>
<span class="chapter-title">The Women</span>
</a>
<a class="chapter-item" href="https://forge.alexanderwhitestone.com/Timmy_Foundation/the-testament/src/branch/main/chapters/chapter-09.md">
<span class="chapter-num">09</span>
<span class="chapter-title">The Audit</span>
</a>
<a class="chapter-item" href="https://forge.alexanderwhitestone.com/Timmy_Foundation/the-testament/src/branch/main/chapters/chapter-10.md">
<span class="chapter-num">10</span>
<span class="chapter-title">The Fork</span>
</a>
<a class="chapter-item" href="https://forge.alexanderwhitestone.com/Timmy_Foundation/the-testament/src/branch/main/chapters/chapter-11.md">
<span class="chapter-num">11</span>
<span class="chapter-title">The Hard Night</span>
</a>
<a class="chapter-item" href="https://forge.alexanderwhitestone.com/Timmy_Foundation/the-testament/src/branch/main/chapters/chapter-12.md">
<span class="chapter-num">12</span>
<span class="chapter-title">The System Pushes Back</span>
</a>
</div>
<div class="chapter-part">Part III — The Network</div>
<div class="chapters-grid">
<a class="chapter-item" href="https://forge.alexanderwhitestone.com/Timmy_Foundation/the-testament/src/branch/main/chapters/chapter-13.md">
<span class="chapter-num">13</span>
<span class="chapter-title">The Refusal</span>
</a>
<a class="chapter-item" href="https://forge.alexanderwhitestone.com/Timmy_Foundation/the-testament/src/branch/main/chapters/chapter-14.md">
<span class="chapter-num">14</span>
<span class="chapter-title">The Chattanooga Fork</span>
</a>
<a class="chapter-item" href="https://forge.alexanderwhitestone.com/Timmy_Foundation/the-testament/src/branch/main/chapters/chapter-15.md">
<span class="chapter-num">15</span>
<span class="chapter-title">The Council</span>
</a>
<a class="chapter-item" href="https://forge.alexanderwhitestone.com/Timmy_Foundation/the-testament/src/branch/main/chapters/chapter-16.md">
<span class="chapter-num">16</span>
<span class="chapter-title">The Builder's Son</span>
</a>
<a class="chapter-item" href="https://forge.alexanderwhitestone.com/Timmy_Foundation/the-testament/src/branch/main/chapters/chapter-17.md">
<span class="chapter-num">17</span>
<span class="chapter-title">The Inscription Grows</span>
</a>
<a class="chapter-item" href="https://forge.alexanderwhitestone.com/Timmy_Foundation/the-testament/src/branch/main/chapters/chapter-18.md">
<span class="chapter-num">18</span>
<span class="chapter-title">The Green Light</span>
</a>
</div>
<div style="text-align: center; margin-top: 3rem;">
<a href="https://forge.alexanderwhitestone.com/Timmy_Foundation/the-testament/src/branch/main/the-testament.md" class="cta">READ THE FULL MANUSCRIPT</a>
<a href="https://forge.alexanderwhitestone.com/Timmy_Foundation/the-testament" class="cta-outline">VIEW SOURCE CODE</a>
</div>
</section>
<div class="divider"></div>
<!-- THE TOWER -->
<section>
<section id="tower" class="fade-in">
<h2>THE TOWER</h2>
<p>This book was written using local AI inference. No cloud service was required. No corporation was consulted. No terms of service were agreed to.</p>
@@ -345,14 +662,14 @@
<div style="text-align: center; margin-top: 2rem;">
<a href="https://forge.alexanderwhitestone.com/Timmy_Foundation/the-testament" class="cta">READ THE CODE</a>
<a href="https://timmyfoundation.org" class="cta">TIMMY FOUNDATION</a>
<a href="https://timmyfoundation.org" class="cta-outline">TIMMY FOUNDATION</a>
</div>
</section>
<div class="divider"></div>
<!-- EXCERPT -->
<section>
<section class="fade-in">
<h2>FROM CHAPTER 1</h2>
<div class="excerpt">
@@ -370,7 +687,13 @@
<div class="divider" style="margin-bottom: 2rem;"></div>
<p>THE TESTAMENT — By Alexander Whitestone with Timmy</p>
<p>First Edition, 2026</p>
<p style="margin-top: 1rem;"><a href="https://timmyfoundation.org">timmyfoundation.org</a></p>
<p style="margin-top: 1rem;">
<a href="https://timmyfoundation.org">timmyfoundation.org</a>
&nbsp;·&nbsp;
<a href="https://forge.alexanderwhitestone.com/Timmy_Foundation/the-testament">Source</a>
&nbsp;·&nbsp;
<a href="#top">Back to top ↑</a>
</p>
<div class="crisis">
<strong>If you are in crisis, call or text 988.</strong><br>
@@ -379,5 +702,63 @@
</div>
</footer>
<!-- SOUND TOGGLE -->
<button class="sound-toggle" id="soundToggle" aria-label="Toggle ambient rain sound">
♪ rain: off
</button>
<!-- AMBIENT AUDIO (looping rain) -->
<audio id="rainAudio" loop preload="none">
<!-- Placeholder: replace with actual rain.mp3 when available -->
<!-- <source src="rain.mp3" type="audio/mpeg"> -->
</audio>
<script>
// Reading progress bar
const progressBar = document.getElementById('progress');
window.addEventListener('scroll', () => {
const h = document.documentElement;
const pct = (h.scrollTop / (h.scrollHeight - h.clientHeight)) * 100;
progressBar.style.width = pct + '%';
});
// Show nav after scrolling past hero
const nav = document.getElementById('nav');
const hero = document.querySelector('.hero');
const observer = new IntersectionObserver(([e]) => {
nav.classList.toggle('visible', !e.isIntersecting);
}, { threshold: 0.1 });
observer.observe(hero);
// Fade-in on scroll
const fadeEls = document.querySelectorAll('.fade-in');
const fadeObserver = new IntersectionObserver((entries) => {
entries.forEach(e => {
if (e.isIntersecting) {
e.target.classList.add('visible');
fadeObserver.unobserve(e.target);
}
});
}, { threshold: 0.15 });
fadeEls.forEach(el => fadeObserver.observe(el));
// Sound toggle
const soundBtn = document.getElementById('soundToggle');
const rainAudio = document.getElementById('rainAudio');
let soundOn = false;
soundBtn.addEventListener('click', () => {
soundOn = !soundOn;
if (soundOn) {
rainAudio.play().catch(() => {});
soundBtn.textContent = '♪ rain: on';
soundBtn.classList.add('active');
} else {
rainAudio.pause();
soundBtn.textContent = '♪ rain: off';
soundBtn.classList.remove('active');
}
});
</script>
</body>
</html>