feat: enhance website — nav, chapters, OG tags, progress bar, sound toggle
- 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:
@@ -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>
|
||||
·
|
||||
<a href="https://forge.alexanderwhitestone.com/Timmy_Foundation/the-testament">Source</a>
|
||||
·
|
||||
<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>
|
||||
|
||||
Reference in New Issue
Block a user