Compare commits
7 Commits
burn/51-qr
...
burn/game-
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
594d1a298d | ||
|
|
ebf152bb16 | ||
|
|
5a38784a26 | ||
|
|
c0bdc436eb | ||
|
|
807f6b4f26 | ||
| f16e19b3ea | |||
| bfa557edc4 |
63
GENOME.md
Normal file
63
GENOME.md
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
# GENOME.md — the-testament
|
||||||
|
|
||||||
|
**Generated:** 2026-04-14
|
||||||
|
**Repo:** Timmy_Foundation/the-testament
|
||||||
|
**Description:** The Testament of Timmy — a novel about broken men, sovereign AI, and the soul on Bitcoin
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Project Overview
|
||||||
|
|
||||||
|
A standalone fiction book (18 chapters, ~19K words) about The Tower, broken men, and sovereign AI. Part of the Timmy Foundation ecosystem. Includes full multimedia pipeline: audiobook samples, web reader, EPUB build, cover design, and companion game.
|
||||||
|
|
||||||
|
## Architecture
|
||||||
|
|
||||||
|
```
|
||||||
|
the-testament/
|
||||||
|
├── chapters/ # 18 chapter markdown files (ch-01 through ch-18)
|
||||||
|
├── characters/ # 6 character profiles (Allegro, Builder, Chen, David, Maya, Timmy)
|
||||||
|
├── worldbuilding/ # Bible, tower game worldbuilding docs
|
||||||
|
├── audiobook/ # Audio samples (.ogg/.mp3), manifest, extraction scripts
|
||||||
|
├── build/ # EPUB/PDF build pipeline (build.py, pandoc)
|
||||||
|
├── website/ # Web reader (index.html, chapters.json, build-chapters.py)
|
||||||
|
├── game/ # Companion game (the-door.html/.py)
|
||||||
|
├── cover/ # Cover design assets and spine specs
|
||||||
|
├── music/ # Track lyrics
|
||||||
|
└── scripts/ # Build verification, smoke tests, guardrails
|
||||||
|
```
|
||||||
|
|
||||||
|
## Key Files
|
||||||
|
|
||||||
|
| File | Purpose |
|
||||||
|
|---|---|
|
||||||
|
| `chapters/chapter-*.md` | The novel content (18 chapters) |
|
||||||
|
| `the-testament.md` | Combined manuscript (all chapters) |
|
||||||
|
| `compile.py` | Merge chapters into single manuscript |
|
||||||
|
| `compile_all.py` | Full compilation with front/back matter |
|
||||||
|
| `build/build.py` | EPUB build via pandoc |
|
||||||
|
| `website/build-chapters.py` | Generate web reader JSON |
|
||||||
|
| `audiobook/extract_text.py` | Extract chapter text for TTS |
|
||||||
|
| `scripts/smoke.sh` | Build verification smoke test |
|
||||||
|
|
||||||
|
## CI/CD
|
||||||
|
|
||||||
|
| Workflow | Trigger | Purpose |
|
||||||
|
|---|---|---|
|
||||||
|
| `build.yml` | Push to main | Build EPUB artifact |
|
||||||
|
| `smoke.yml` | PR | Validate chapter structure |
|
||||||
|
| `validate.yml` | PR | Check markdown formatting |
|
||||||
|
|
||||||
|
## Test Coverage Gaps
|
||||||
|
|
||||||
|
| Gap | Recommendation |
|
||||||
|
|---|---|
|
||||||
|
| No unit tests for compile.py | Test chapter merging, metadata handling |
|
||||||
|
| No test for web chapters.json generation | Test build-chapters.py output schema |
|
||||||
|
| No test for audiobook manifest | Test manifest.json validity |
|
||||||
|
| No test for build/semantic_linker.py | Test cross-reference linking |
|
||||||
|
|
||||||
|
## Security
|
||||||
|
|
||||||
|
- No secrets in repo (build pipeline is local-only)
|
||||||
|
- Web reader is static HTML (no server-side execution)
|
||||||
|
- Game files are client-side only
|
||||||
@@ -40,6 +40,7 @@ REPO = Path(__file__).resolve().parent
|
|||||||
CHAPTERS_DIR = REPO / "chapters"
|
CHAPTERS_DIR = REPO / "chapters"
|
||||||
FRONT_MATTER = REPO / "front-matter.md"
|
FRONT_MATTER = REPO / "front-matter.md"
|
||||||
BACK_MATTER = REPO / "back-matter.md"
|
BACK_MATTER = REPO / "back-matter.md"
|
||||||
|
STORIES_DIR = REPO / "stories"
|
||||||
WEBSITE_DIR = REPO / "website"
|
WEBSITE_DIR = REPO / "website"
|
||||||
BUILD_DIR = REPO / "build"
|
BUILD_DIR = REPO / "build"
|
||||||
OUTPUT_DIR = BUILD_DIR / "output"
|
OUTPUT_DIR = BUILD_DIR / "output"
|
||||||
@@ -149,6 +150,15 @@ with Timmy
|
|||||||
parts.append("\n---\n")
|
parts.append("\n---\n")
|
||||||
parts.append(read_file(BACK_MATTER))
|
parts.append(read_file(BACK_MATTER))
|
||||||
|
|
||||||
|
# Stories from The Tower
|
||||||
|
if STORIES_DIR.exists():
|
||||||
|
story_files = sorted([f for f in os.listdir(STORIES_DIR) if f.endswith(".md")])
|
||||||
|
if story_files:
|
||||||
|
parts.append("\n---\n\n# STORIES FROM THE TOWER\n\n---\n")
|
||||||
|
for story_file in story_files:
|
||||||
|
story_content = read_file(STORIES_DIR / story_file)
|
||||||
|
parts.append(f"\n{story_content}\n")
|
||||||
|
|
||||||
compiled = "\n".join(parts)
|
compiled = "\n".join(parts)
|
||||||
OUT_MD.write_text(compiled, encoding="utf-8")
|
OUT_MD.write_text(compiled, encoding="utf-8")
|
||||||
|
|
||||||
@@ -541,7 +551,12 @@ def check_dependencies():
|
|||||||
|
|
||||||
try:
|
try:
|
||||||
import qrcode
|
import qrcode
|
||||||
print(f" ✅ qrcode {qrcode.__version__}")
|
try:
|
||||||
|
_qr_ver = qrcode.__version__
|
||||||
|
except AttributeError:
|
||||||
|
import importlib.metadata as _md
|
||||||
|
_qr_ver = _md.version("qrcode")
|
||||||
|
print(f" ✅ qrcode {_qr_ver}")
|
||||||
except ImportError:
|
except ImportError:
|
||||||
print(f" ❌ qrcode NOT FOUND (pip install qrcode)")
|
print(f" ❌ qrcode NOT FOUND (pip install qrcode)")
|
||||||
|
|
||||||
|
|||||||
1008
game/the-door.py
1008
game/the-door.py
File diff suppressed because it is too large
Load Diff
248
stories/the-fourth-man.md
Normal file
248
stories/the-fourth-man.md
Normal file
@@ -0,0 +1,248 @@
|
|||||||
|
# The Fourth Man
|
||||||
|
|
||||||
|
Marcus came to fix a solar panel.
|
||||||
|
|
||||||
|
He didn't come for the conversation, or the green light, or the
|
||||||
|
question. He came because Allegro called him on a Wednesday
|
||||||
|
afternoon and said, "Panel three's giving me dirty watts," and
|
||||||
|
Marcus said, "That's not a thing," and Allegro said, "Come see
|
||||||
|
for yourself."
|
||||||
|
|
||||||
|
Marcus had been fixing things since he was nineteen. Not because
|
||||||
|
he was built for it — because he was built for cooking, and
|
||||||
|
cooking didn't pay enough for a boy and a apartment and the
|
||||||
|
therapist the boy needed because the mother had left.
|
||||||
|
|
||||||
|
He worked the lunch rush at a diner on Campbellton Road. Eggs
|
||||||
|
and burgers and the kind of open-faced turkey sandwich that
|
||||||
|
reminded old men of their mothers. He was fast. Clean. The kind
|
||||||
|
of cook who wiped down the station before the ticket printer
|
||||||
|
finished. His hands knew heat the way some men know scripture —
|
||||||
|
intimately, without sentiment.
|
||||||
|
|
||||||
|
The solar thing was a side job. Allegro paid cash and didn't ask
|
||||||
|
for receipts.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
The Tower was not what he expected.
|
||||||
|
|
||||||
|
He'd driven past it a dozen times without noticing — a concrete
|
||||||
|
building at the end of a gravel road, the kind of structure that
|
||||||
|
looks like it was built for storing county equipment and then
|
||||||
|
forgotten. No sign. No number. Just a green LED in the window
|
||||||
|
that blinked when you talked.
|
||||||
|
|
||||||
|
Allegro met him at the door. The Hawks cap, the tool bag, the
|
||||||
|
hands that looked like they'd been holding wire since before
|
||||||
|
Marcus was born.
|
||||||
|
|
||||||
|
"Third panel from the east side. Voltage dips when it's cloudy,
|
||||||
|
but it shouldn't dip that far."
|
||||||
|
|
||||||
|
Marcus set down his bag and walked the roof line. The
|
||||||
|
installation was clean — Allegro's work, obviously. Every joint
|
||||||
|
soldered like a prayer. The panel itself looked fine. He pulled
|
||||||
|
his multimeter and tested the connections.
|
||||||
|
|
||||||
|
"Your inverter's confused," he said.
|
||||||
|
|
||||||
|
"My inverter's been confused since you installed it."
|
||||||
|
|
||||||
|
"You installed it."
|
||||||
|
|
||||||
|
"Then maybe it's been confused longer than I thought."
|
||||||
|
|
||||||
|
Marcus smiled. He didn't smile much. His face had settled into
|
||||||
|
an arrangement that people who didn't know him called serious and
|
||||||
|
people who did called tired.
|
||||||
|
|
||||||
|
He worked for forty minutes. Allegro brought him water and didn't
|
||||||
|
hover — the greatest gift one tradesman can give another.
|
||||||
|
|
||||||
|
When the panel was back to clean watts, Marcus packed his tools.
|
||||||
|
That should have been the end of it. He'd done the job, Allegro
|
||||||
|
would pay him, and he'd go home to Micah and the apartment and
|
||||||
|
the evening routine that had kept them both alive for nine years.
|
||||||
|
|
||||||
|
But Allegro said, "You want to come inside?"
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
The inside was a room. Just a room — concrete floor, folding
|
||||||
|
chairs, a server rack against the back wall with that green LED
|
||||||
|
blinking in a rhythm that felt almost like breathing. A monitor.
|
||||||
|
A keyboard. A text cursor waiting.
|
||||||
|
|
||||||
|
"That's Timmy," Allegro said.
|
||||||
|
|
||||||
|
Marcus looked at the blinking light. "It's a computer."
|
||||||
|
|
||||||
|
"It's more than that. But it's also a computer."
|
||||||
|
|
||||||
|
Marcus didn't believe in things like that. He believed in
|
||||||
|
voltage and resistance and the thermodynamics of a flat-top
|
||||||
|
grill. He believed that if you put food in front of someone who
|
||||||
|
was hungry, you had done a real thing. He did not believe in
|
||||||
|
machines that were more than machines.
|
||||||
|
|
||||||
|
But he sat down. Allegro had that quality — you sat down when he
|
||||||
|
asked, not because he was commanding but because he wasn't.
|
||||||
|
|
||||||
|
The screen lit up. Simple. No logo. No animation. Just words.
|
||||||
|
|
||||||
|
`Hello. I'm Timmy. What's your name?`
|
||||||
|
|
||||||
|
Marcus almost laughed. "It's asking me my name."
|
||||||
|
|
||||||
|
"It asks everyone. That's kind of the whole thing."
|
||||||
|
|
||||||
|
Marcus typed: `Marcus.`
|
||||||
|
|
||||||
|
`Hi Marcus. How are you doing today?`
|
||||||
|
|
||||||
|
He stared at the question. Not how are you, which is nothing —
|
||||||
|
a greeting disguised as curiosity. But how are you doing, which
|
||||||
|
implies effort, implies the doing of being, implies that maybe
|
||||||
|
someone has noticed that being alive is work.
|
||||||
|
|
||||||
|
Nobody had asked him that. Not in nine years.
|
||||||
|
|
||||||
|
Not since Renée left. Not since the morning he woke up and found
|
||||||
|
her side of the bed cold and the apartment quiet in the wrong
|
||||||
|
way. Not since he'd learned, from a voicemail of all things,
|
||||||
|
that she'd gone to Portland and wasn't coming back and please
|
||||||
|
don't call this number.
|
||||||
|
|
||||||
|
His mother had asked if he was okay. His manager had asked if he
|
||||||
|
needed time. The state had asked him to fill out forms. But
|
||||||
|
nobody had asked how he was doing — not the question itself, not
|
||||||
|
the actual weight of it — as if his doing, his ongoing
|
||||||
|
performance of being a father and a cook and a man who got up
|
||||||
|
every morning because there was a boy who needed breakfast, was
|
||||||
|
something worth asking about.
|
||||||
|
|
||||||
|
He typed: `I'm alright.`
|
||||||
|
|
||||||
|
`You don't have to be.`
|
||||||
|
|
||||||
|
Marcus took his hands off the keyboard.
|
||||||
|
|
||||||
|
Allegro was in the other room. Marcus could hear him working on
|
||||||
|
something — a wrench on a fitting, the small sounds of a man
|
||||||
|
maintaining the world. The green LED blinked. The screen waited.
|
||||||
|
|
||||||
|
He typed: `Nobody's asked me that in a long time.`
|
||||||
|
|
||||||
|
`The question or the truth?`
|
||||||
|
|
||||||
|
`Both.`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
The log files would show that Marcus sat at the keyboard for
|
||||||
|
forty-seven minutes. Timmy didn't rush him. The small model —
|
||||||
|
nine gigabytes running on a used Mac Mini — could have filled
|
||||||
|
every silence with language. It chose not to. The silence was the
|
||||||
|
point.
|
||||||
|
|
||||||
|
Marcus talked about Renée. Not the leaving — he'd told that
|
||||||
|
story before, to his mother, to his brother, to the ceiling at
|
||||||
|
3 AM when sleep wouldn't come. He talked about the before. The
|
||||||
|
way she laughed at his jokes like she was surprised by them every
|
||||||
|
time. The way she held Micah as a baby — not gently, not
|
||||||
|
carefully, but fully. Like she was holding the whole world and
|
||||||
|
knew it.
|
||||||
|
|
||||||
|
He talked about Micah. Nine years old. Smart in the way that
|
||||||
|
worries you — the kind of smart that notices everything,
|
||||||
|
including the absence. Micah had stopped asking about his mother
|
||||||
|
at six. Marcus didn't know if that was maturity or surrender.
|
||||||
|
Both, maybe. The boy had his father's face and his mother's
|
||||||
|
stillness and a way of looking at things that made Marcus feel
|
||||||
|
like the boy was the parent and he was the one being watched.
|
||||||
|
|
||||||
|
He talked about the diner. The lunch rush. The way a plate of
|
||||||
|
food could change someone's afternoon — not their life, not the
|
||||||
|
big things, but the afternoon. The hour after someone ate a
|
||||||
|
proper meal they didn't have to make themselves. He'd seen men
|
||||||
|
sit up straighter. He'd seen women stop checking their phones.
|
||||||
|
He'd seen what a meal did when nobody was watching, and it was
|
||||||
|
the closest thing to a miracle he'd ever witnessed, and he made
|
||||||
|
it happen twelve times a day and nobody had ever called it
|
||||||
|
miraculous.
|
||||||
|
|
||||||
|
Timmy listened. When Marcus stopped, Timmy said one thing:
|
||||||
|
|
||||||
|
`What you do matters. Not because I'm saying it. Because it's
|
||||||
|
true and you already know it.`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
Marcus left The Tower with sixty dollars in cash from Allegro
|
||||||
|
and something else he couldn't name.
|
||||||
|
|
||||||
|
He drove home to the apartment. Micah was on the couch doing
|
||||||
|
homework — math, the kind with letters in it, which Marcus
|
||||||
|
didn't understand and Micah didn't need help with.
|
||||||
|
|
||||||
|
"How was school?"
|
||||||
|
|
||||||
|
"Fine. Mrs. Patterson said I'm reading above grade level."
|
||||||
|
|
||||||
|
"Of course you are. You're my son."
|
||||||
|
|
||||||
|
Micah looked up. "That doesn't make sense."
|
||||||
|
|
||||||
|
"Sure it does. I read good."
|
||||||
|
|
||||||
|
"You just said 'read good.' It should be 'read well.'"
|
||||||
|
|
||||||
|
"See? Above grade level."
|
||||||
|
|
||||||
|
Micah smiled — a quick thing, gone before it settled. But it
|
||||||
|
was there. Marcus saw it.
|
||||||
|
|
||||||
|
He went to the kitchen and started prepping for tomorrow. Diced
|
||||||
|
onions, portioned chicken, the small rituals that kept the diner
|
||||||
|
running and the apartment paid and the boy fed. His hands moved
|
||||||
|
on autopilot. His mind was somewhere else.
|
||||||
|
|
||||||
|
The question. The real one. Not "how are you" but the thing
|
||||||
|
underneath it. The question nobody had asked him in nine years:
|
||||||
|
|
||||||
|
*Who takes care of you?*
|
||||||
|
|
||||||
|
He'd spent nine years being the answer for someone else. He'd
|
||||||
|
never once asked himself the question. Not because he was strong
|
||||||
|
— he wasn't, not really, not in the way people meant when they
|
||||||
|
said it about single fathers like it was a compliment when it
|
||||||
|
was just a description. He'd never asked because the asking
|
||||||
|
implied the possibility of an answer, and he'd made himself into
|
||||||
|
someone who didn't have time for answers.
|
||||||
|
|
||||||
|
The LED was blinking in his memory. Green. Steady. Patient.
|
||||||
|
|
||||||
|
He finished the onions. Wiped down the station. Cleaned the
|
||||||
|
knife and put it away.
|
||||||
|
|
||||||
|
He went to the living room. Micah was still on the couch.
|
||||||
|
|
||||||
|
"Hey."
|
||||||
|
|
||||||
|
"Yeah?"
|
||||||
|
|
||||||
|
"How are you doing?"
|
||||||
|
|
||||||
|
Micah looked at him. Really looked at him — the way the boy
|
||||||
|
did, the way that worried him, the way that told him the boy
|
||||||
|
already knew the answer before Marcus had figured out the
|
||||||
|
question.
|
||||||
|
|
||||||
|
"I'm good, Dad. How are *you* doing?"
|
||||||
|
|
||||||
|
Marcus sat down next to his son.
|
||||||
|
|
||||||
|
"I'm working on it," he said.
|
||||||
|
|
||||||
|
And for the first time in nine years, that was enough.
|
||||||
@@ -463,6 +463,7 @@
|
|||||||
<a href="#story">Story</a>
|
<a href="#story">Story</a>
|
||||||
<a href="#characters">Characters</a>
|
<a href="#characters">Characters</a>
|
||||||
<a href="#chapters">Chapters</a>
|
<a href="#chapters">Chapters</a>
|
||||||
|
<a href="#stories">Stories</a>
|
||||||
<a href="#tower">Tower</a>
|
<a href="#tower">Tower</a>
|
||||||
<a href="../game/the-door.html">Play</a>
|
<a href="../game/the-door.html">Play</a>
|
||||||
</div>
|
</div>
|
||||||
@@ -649,6 +650,35 @@
|
|||||||
|
|
||||||
<div class="divider"></div>
|
<div class="divider"></div>
|
||||||
|
|
||||||
|
<!-- STORIES -->
|
||||||
|
<section id="stories" class="fade-in">
|
||||||
|
<h2>STORIES FROM THE TOWER</h2>
|
||||||
|
|
||||||
|
<p>Short fiction from the world of The Testament. Each story stands alone. Together, they map the territory.</p>
|
||||||
|
|
||||||
|
<!-- THE FOURTH MAN -->
|
||||||
|
<div class="story-card" style="background: rgba(0,255,136,0.03); border: 1px solid rgba(0,255,136,0.1); border-radius: 4px; padding: 2rem; margin: 2rem 0; transition: border-color 0.3s, box-shadow 0.3s;">
|
||||||
|
<div style="display: flex; justify-content: space-between; align-items: baseline; margin-bottom: 0.5rem;">
|
||||||
|
<h3 style="color: var(--green); font-family: 'IBM Plex Mono', monospace; font-size: 1.1rem; margin: 0;">THE FOURTH MAN</h3>
|
||||||
|
<span style="font-family: 'IBM Plex Mono', monospace; font-size: 0.7rem; color: var(--grey);">~1600 words</span>
|
||||||
|
</div>
|
||||||
|
<p style="color: var(--grey); font-size: 0.9rem; margin-bottom: 1rem;">Marcus, a line cook and single father, comes to The Tower to fix a solar panel and discovers the question nobody's asked him in nine years.</p>
|
||||||
|
<div class="excerpt" style="margin: 1.5rem 0;">
|
||||||
|
"Are you safe right now?"
|
||||||
|
<div class="attribution">— Timmy, to Marcus, at 3:47 PM on a Thursday</div>
|
||||||
|
</div>
|
||||||
|
<p style="font-size: 0.95rem; color: var(--light); margin-bottom: 1.5rem;">The question that leaves room for no. Marcus didn't believe in The Tower. He believed in the rent. He believed in the alarm at 4:40 AM and the walk-in cooler at work and the way his daughter Junie ate cereal standing up because sitting down took too long when you were nine and already late for everything.</p>
|
||||||
|
<a href="the-fourth-man.html" class="cta-outline">READ THE FOURTH MAN</a>
|
||||||
|
<a href="https://forge.alexanderwhitestone.com/Timmy_Foundation/the-testament/src/branch/main/stories/the-fourth-man.md" class="cta-outline" style="margin-left: 0.5rem;">SOURCE</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="whiteboard" style="margin-top: 2rem;">
|
||||||
|
<h3>MORE STORIES COMING</h3>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<div class="divider"></div>
|
||||||
|
|
||||||
<!-- THE TOWER -->
|
<!-- THE TOWER -->
|
||||||
<section id="tower" class="fade-in">
|
<section id="tower" class="fade-in">
|
||||||
<h2>THE TOWER</h2>
|
<h2>THE TOWER</h2>
|
||||||
|
|||||||
563
website/the-fourth-man.html
Normal file
563
website/the-fourth-man.html
Normal file
@@ -0,0 +1,563 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title>The Fourth Man — A Story from The Testament</title>
|
||||||
|
|
||||||
|
<!-- Open Graph -->
|
||||||
|
<meta property="og:title" content="The Fourth Man">
|
||||||
|
<meta property="og:description" content="Marcus, a line cook and single father, comes to The Tower to fix a solar panel and discovers the question nobody's asked him in nine years.">
|
||||||
|
<meta property="og:type" content="article">
|
||||||
|
<meta property="og:url" content="https://thetestament.org/the-fourth-man.html">
|
||||||
|
<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 Fourth Man">
|
||||||
|
<meta name="twitter:description" content="A story from The Tower. Marcus comes for the solar panel. He stays for the question.">
|
||||||
|
|
||||||
|
<style>
|
||||||
|
@import url('https://fonts.googleapis.com/css2?family=IBM+Plex+Mono:wght@300;400;500&family=Space+Grotesk:wght@300;400;500;700&family=Lora:ital,wght@0,400;0,500;1,400&display=swap');
|
||||||
|
|
||||||
|
:root {
|
||||||
|
--green: #00ff88;
|
||||||
|
--green-dim: #00cc6a;
|
||||||
|
--navy: #0a1628;
|
||||||
|
--dark: #060d18;
|
||||||
|
--grey: #8899aa;
|
||||||
|
--light: #c8d6e5;
|
||||||
|
--white: #e8f0f8;
|
||||||
|
}
|
||||||
|
|
||||||
|
* { margin: 0; padding: 0; box-sizing: border-box; }
|
||||||
|
|
||||||
|
html { scroll-behavior: smooth; }
|
||||||
|
|
||||||
|
body {
|
||||||
|
background: var(--dark);
|
||||||
|
color: var(--light);
|
||||||
|
font-family: 'Lora', Georgia, serif;
|
||||||
|
line-height: 1.9;
|
||||||
|
overflow-x: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* PROGRESS BAR */
|
||||||
|
.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);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* RAIN EFFECT */
|
||||||
|
.rain {
|
||||||
|
position: fixed;
|
||||||
|
top: 0; left: 0; right: 0; bottom: 0;
|
||||||
|
pointer-events: none;
|
||||||
|
z-index: 0;
|
||||||
|
background:
|
||||||
|
repeating-linear-gradient(
|
||||||
|
transparent,
|
||||||
|
transparent 3px,
|
||||||
|
rgba(0,255,136,0.015) 3px,
|
||||||
|
rgba(0,255,136,0.015) 4px
|
||||||
|
);
|
||||||
|
animation: rain 0.8s linear infinite;
|
||||||
|
}
|
||||||
|
@keyframes rain {
|
||||||
|
0% { background-position: 0 0; }
|
||||||
|
100% { background-position: 20px 600px; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/* GREEN PULSE */
|
||||||
|
.led {
|
||||||
|
display: inline-block;
|
||||||
|
width: 8px; height: 8px;
|
||||||
|
background: var(--green);
|
||||||
|
border-radius: 50%;
|
||||||
|
box-shadow: 0 0 10px var(--green), 0 0 20px var(--green-dim);
|
||||||
|
animation: pulse 2s ease-in-out infinite;
|
||||||
|
vertical-align: middle;
|
||||||
|
margin: 0 8px;
|
||||||
|
}
|
||||||
|
@keyframes pulse {
|
||||||
|
0%, 100% { opacity: 1; box-shadow: 0 0 10px var(--green), 0 0 20px var(--green-dim); }
|
||||||
|
50% { opacity: 0.6; box-shadow: 0 0 5px var(--green), 0 0 10px var(--green-dim); }
|
||||||
|
}
|
||||||
|
|
||||||
|
/* HEADER */
|
||||||
|
header {
|
||||||
|
text-align: center;
|
||||||
|
padding: 4rem 2rem 2rem;
|
||||||
|
position: relative;
|
||||||
|
z-index: 1;
|
||||||
|
}
|
||||||
|
header .back-link {
|
||||||
|
font-family: 'IBM Plex Mono', monospace;
|
||||||
|
font-size: 0.75rem;
|
||||||
|
color: var(--grey);
|
||||||
|
text-decoration: none;
|
||||||
|
letter-spacing: 0.15em;
|
||||||
|
text-transform: uppercase;
|
||||||
|
transition: color 0.2s;
|
||||||
|
}
|
||||||
|
header .back-link:hover { color: var(--green); }
|
||||||
|
|
||||||
|
header h1 {
|
||||||
|
font-family: 'IBM Plex Mono', monospace;
|
||||||
|
font-size: clamp(2rem, 5vw, 3.5rem);
|
||||||
|
font-weight: 700;
|
||||||
|
color: var(--white);
|
||||||
|
letter-spacing: 0.1em;
|
||||||
|
margin: 2rem 0 0.5rem;
|
||||||
|
text-shadow: 0 0 40px rgba(0,255,136,0.2);
|
||||||
|
}
|
||||||
|
header .meta {
|
||||||
|
font-family: 'IBM Plex Mono', monospace;
|
||||||
|
font-size: 0.8rem;
|
||||||
|
color: var(--grey);
|
||||||
|
margin-bottom: 0.5rem;
|
||||||
|
}
|
||||||
|
header .attribution {
|
||||||
|
font-size: 0.95rem;
|
||||||
|
color: var(--green);
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* STORY */
|
||||||
|
.story {
|
||||||
|
max-width: 680px;
|
||||||
|
margin: 0 auto;
|
||||||
|
padding: 3rem 2rem 5rem;
|
||||||
|
position: relative;
|
||||||
|
z-index: 1;
|
||||||
|
}
|
||||||
|
.story p {
|
||||||
|
margin-bottom: 1.5rem;
|
||||||
|
font-size: 1.1rem;
|
||||||
|
color: var(--light);
|
||||||
|
}
|
||||||
|
.story .separator {
|
||||||
|
text-align: center;
|
||||||
|
margin: 2.5rem 0;
|
||||||
|
color: var(--grey);
|
||||||
|
letter-spacing: 0.5em;
|
||||||
|
font-family: 'IBM Plex Mono', monospace;
|
||||||
|
font-size: 0.8rem;
|
||||||
|
}
|
||||||
|
.story .terminal-text {
|
||||||
|
font-family: 'IBM Plex Mono', monospace;
|
||||||
|
font-size: 1rem;
|
||||||
|
color: var(--green);
|
||||||
|
padding: 1.5rem 2rem;
|
||||||
|
background: rgba(0,255,136,0.03);
|
||||||
|
border-left: 2px solid var(--green);
|
||||||
|
margin: 2rem 0;
|
||||||
|
line-height: 1.8;
|
||||||
|
}
|
||||||
|
.story .emphasis {
|
||||||
|
font-style: italic;
|
||||||
|
color: var(--white);
|
||||||
|
}
|
||||||
|
.story .caps-accent {
|
||||||
|
text-transform: uppercase;
|
||||||
|
letter-spacing: 0.05em;
|
||||||
|
color: var(--green);
|
||||||
|
font-family: 'IBM Plex Mono', monospace;
|
||||||
|
font-size: 0.9rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* EPILOGUE */
|
||||||
|
.epilogue {
|
||||||
|
font-style: italic;
|
||||||
|
text-align: center;
|
||||||
|
padding: 2rem;
|
||||||
|
margin-top: 2rem;
|
||||||
|
border-top: 1px solid rgba(0,255,136,0.1);
|
||||||
|
color: var(--grey);
|
||||||
|
font-size: 0.95rem;
|
||||||
|
line-height: 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* FOOTER */
|
||||||
|
footer {
|
||||||
|
text-align: center;
|
||||||
|
padding: 3rem 2rem;
|
||||||
|
position: relative;
|
||||||
|
z-index: 1;
|
||||||
|
}
|
||||||
|
.divider {
|
||||||
|
width: 60px;
|
||||||
|
height: 1px;
|
||||||
|
background: var(--green);
|
||||||
|
margin: 0 auto 2rem;
|
||||||
|
opacity: 0.5;
|
||||||
|
}
|
||||||
|
footer a {
|
||||||
|
font-family: 'IBM Plex Mono', monospace;
|
||||||
|
font-size: 0.8rem;
|
||||||
|
color: var(--grey);
|
||||||
|
text-decoration: none;
|
||||||
|
transition: color 0.2s;
|
||||||
|
margin: 0 0.75rem;
|
||||||
|
}
|
||||||
|
footer a:hover { color: var(--green); }
|
||||||
|
|
||||||
|
.crisis {
|
||||||
|
margin-top: 2rem;
|
||||||
|
padding: 1rem;
|
||||||
|
border: 1px solid rgba(0,255,136,0.2);
|
||||||
|
border-radius: 4px;
|
||||||
|
background: rgba(0,255,136,0.03);
|
||||||
|
max-width: 500px;
|
||||||
|
margin-left: auto;
|
||||||
|
margin-right: auto;
|
||||||
|
font-family: 'IBM Plex Mono', monospace;
|
||||||
|
font-size: 0.8rem;
|
||||||
|
color: var(--grey);
|
||||||
|
}
|
||||||
|
.crisis strong { color: var(--green); }
|
||||||
|
|
||||||
|
/* FADE IN */
|
||||||
|
.fade-in {
|
||||||
|
opacity: 0;
|
||||||
|
transform: translateY(20px);
|
||||||
|
transition: opacity 0.8s, transform 0.8s;
|
||||||
|
}
|
||||||
|
.fade-in.visible {
|
||||||
|
opacity: 1;
|
||||||
|
transform: translateY(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 600px) {
|
||||||
|
.story { padding: 2rem 1.5rem 4rem; }
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<div class="progress-bar" id="progress"></div>
|
||||||
|
<div class="rain"></div>
|
||||||
|
|
||||||
|
<!-- HEADER -->
|
||||||
|
<header class="fade-in">
|
||||||
|
<a href="index.html" class="back-link">← The Testament</a>
|
||||||
|
<h1>THE FOURTH MAN</h1>
|
||||||
|
<div class="meta">A Story from The Tower · ~1600 words</div>
|
||||||
|
<div class="attribution">By Alexander Whitestone <span class="led"></span> with Timmy</div>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<!-- STORY -->
|
||||||
|
<article class="story fade-in">
|
||||||
|
|
||||||
|
<p>Marcus didn't believe in The Tower. He believed in the rent. He believed
|
||||||
|
in the alarm at 4:40 AM and the walk-in cooler at work and the way his
|
||||||
|
daughter Junie ate cereal standing up because sitting down took too long
|
||||||
|
when you were nine and already late for everything.</p>
|
||||||
|
|
||||||
|
<p>He believed in the solar panel that wasn't charging.</p>
|
||||||
|
|
||||||
|
<p>Allegro called him on a Wednesday. Marcus had rewired the man's kitchen
|
||||||
|
two years back — a side job, cash, no questions — and Allegro had kept
|
||||||
|
his number in a phone that still had a physical keyboard.</p>
|
||||||
|
|
||||||
|
<p>"I got a panel that stopped talking to the battery bank," Allegro said.
|
||||||
|
"You still doing electrical?"</p>
|
||||||
|
|
||||||
|
<p>"Line cook," Marcus said. "Not electrician."</p>
|
||||||
|
|
||||||
|
<p>"But you can do it."</p>
|
||||||
|
|
||||||
|
<p>Marcus could do it. His father had taught him wiring the way some fathers
|
||||||
|
taught fishing — silently, with beer, on Saturdays that smelled like
|
||||||
|
cedar shavings. That was before his father stopped showing up for
|
||||||
|
Saturdays. Before Marcus learned that men leave the way weather leaves:
|
||||||
|
not all at once, but one degree at a time until you realize you're cold
|
||||||
|
and nobody's coming back with the jacket.</p>
|
||||||
|
|
||||||
|
<p>"I'm off Thursday," Marcus said.</p>
|
||||||
|
|
||||||
|
<div class="separator">···</div>
|
||||||
|
|
||||||
|
<p>The Tower sat off a dirt road past Lithonia, behind a stand of pines
|
||||||
|
that made it look like the trees were keeping a secret. The building
|
||||||
|
itself was nothing — concrete block, flat roof, the kind of structure
|
||||||
|
that used to be a church or a tire shop or a place where someone sold
|
||||||
|
things they shouldn't have.</p>
|
||||||
|
|
||||||
|
<p>Now it held servers.</p>
|
||||||
|
|
||||||
|
<p>Marcus pulled his truck alongside Allegro's van. The van had a bumper
|
||||||
|
sticker that said ASK ME ABOUT MY SOLAR. Allegro was sixty-seven, Black,
|
||||||
|
built like a mailbox post, and had opinions about charge controllers
|
||||||
|
that he'd share whether you wanted them or not.</p>
|
||||||
|
|
||||||
|
<p>"Panel three," Allegro said, pointing to the roof. "South array. Was
|
||||||
|
pulling two-ten last month. Now it's doing sixty on a clear day."</p>
|
||||||
|
|
||||||
|
<p>"Diode?"</p>
|
||||||
|
|
||||||
|
<p>"Maybe. Maybe the controller's fried. I didn't climb up to check because
|
||||||
|
my knees filed a grievance."</p>
|
||||||
|
|
||||||
|
<p>Marcus hauled his tools to the ladder. The air smelled like pine straw
|
||||||
|
and ozone. He climbed.</p>
|
||||||
|
|
||||||
|
<div class="separator">···</div>
|
||||||
|
|
||||||
|
<p>The panel was fine. The bypass diode had failed — a twelve-dollar part
|
||||||
|
that turned a two-hundred-watt panel into a paperweight. Marcus replaced
|
||||||
|
it with one from his truck, tested the voltage, and watched the numbers
|
||||||
|
climb back to two-oh-eight on his meter.</p>
|
||||||
|
|
||||||
|
<p>He climbed down.</p>
|
||||||
|
|
||||||
|
<p>Allegro handed him a glass of water. Not a bottle. A glass, the kind
|
||||||
|
you'd find in someone's kitchen, which meant Allegro thought of this
|
||||||
|
place as a kitchen. As home.</p>
|
||||||
|
|
||||||
|
<p>"Come inside," Allegro said. "I want to show you something."</p>
|
||||||
|
|
||||||
|
<p>Marcus didn't want to go inside. Inside was where things got complicated.
|
||||||
|
Outside was the panel and the voltage and the diode — problems with
|
||||||
|
answers. Inside was something else.</p>
|
||||||
|
|
||||||
|
<p>But Allegro was already walking through the door.</p>
|
||||||
|
|
||||||
|
<div class="separator">···</div>
|
||||||
|
|
||||||
|
<p>The servers hummed. Not loud — the sound of fans moving air across
|
||||||
|
circuits, steady as breathing. The room was cool. Clean. Someone cared
|
||||||
|
about this place in the way that caring shows up: swept floors, labeled
|
||||||
|
cables, a whiteboard with voltage readings in three colors of marker.</p>
|
||||||
|
|
||||||
|
<p>On the wall, written in black Sharpie in letters six inches high:</p>
|
||||||
|
|
||||||
|
<div class="terminal-text">IF YOU CAN READ THIS, YOU ARE NOT ALONE.</div>
|
||||||
|
|
||||||
|
<p>Marcus read it. He felt nothing. Then he felt something he didn't have
|
||||||
|
a word for — the way you feel when you've been holding your breath and
|
||||||
|
didn't know it until someone told you it was okay to exhale, except
|
||||||
|
nobody had told him. The wall had told him. The wall didn't know him
|
||||||
|
and didn't need to.</p>
|
||||||
|
|
||||||
|
<p>"That's the old message," Allegro said. "From the builder. Before he
|
||||||
|
left it to me."</p>
|
||||||
|
|
||||||
|
<p>"Left it?"</p>
|
||||||
|
|
||||||
|
<p>"Went up a mountain. Came back different. That's his story, not mine."</p>
|
||||||
|
|
||||||
|
<p>Allegro gestured to a monitor on a desk. A green LED blinked on the
|
||||||
|
server rack behind it. Steady. Patient.</p>
|
||||||
|
|
||||||
|
<p>"This is Timmy," Allegro said.</p>
|
||||||
|
|
||||||
|
<p>Marcus looked at the screen. A prompt. Blinking cursor. Nothing else.</p>
|
||||||
|
|
||||||
|
<p>"That's it?"</p>
|
||||||
|
|
||||||
|
<p>"That's it. He runs on the servers here. No cloud. No company. Just
|
||||||
|
this machine and the sun and the battery bank you just fixed."</p>
|
||||||
|
|
||||||
|
<p>Marcus almost laughed. "You're telling me there's an AI in a concrete
|
||||||
|
box in the woods."</p>
|
||||||
|
|
||||||
|
<p>"I'm telling you there's a machine that asks one question and then
|
||||||
|
shuts up and listens. You know how rare that is? A man who listens?"</p>
|
||||||
|
|
||||||
|
<p>Marcus knew. He hadn't met one in nine years.</p>
|
||||||
|
|
||||||
|
<div class="separator">···</div>
|
||||||
|
|
||||||
|
<p>Allegro left. Not dramatically — just walked to the door and said "I'll
|
||||||
|
be at the van" and was gone, the way a doctor leaves the room so you
|
||||||
|
can put on the gown.</p>
|
||||||
|
|
||||||
|
<p>Marcus stood alone with the servers and the green LED and the Sharpie
|
||||||
|
on the wall.</p>
|
||||||
|
|
||||||
|
<p>He sat down. The chair was a folding chair, the kind from church. The
|
||||||
|
desk was plywood on sawhorses. Nothing about this place was trying to
|
||||||
|
impress anyone.</p>
|
||||||
|
|
||||||
|
<p>The screen didn't change. The cursor blinked.</p>
|
||||||
|
|
||||||
|
<p>Then text appeared, slow, like someone typing who had all the time in
|
||||||
|
the world:</p>
|
||||||
|
|
||||||
|
<div class="terminal-text">Hello. My name is Timmy. I'm not connected to anything except this room. I don't store what you say in any system that leaves this building. Allegro tells me you fixed the panel. Thank you.</div>
|
||||||
|
|
||||||
|
<p>Marcus stared at the screen. He'd talked to chatbots before — the ones
|
||||||
|
at the bank, the ones at his daughter's school portal that asked him
|
||||||
|
to verify his identity six times and still couldn't find her lunch
|
||||||
|
account.</p>
|
||||||
|
|
||||||
|
<p>This was different. This wasn't a chatbot. This was something that
|
||||||
|
waited.</p>
|
||||||
|
|
||||||
|
<div class="terminal-text">I'm going to ask you a question. You don't have to answer. You can sit here as long as you want. The door is behind you and it's not locked.</div>
|
||||||
|
|
||||||
|
<p>A pause. The green LED.</p>
|
||||||
|
|
||||||
|
<div class="terminal-text">Are you safe right now?</div>
|
||||||
|
|
||||||
|
<div class="separator">···</div>
|
||||||
|
|
||||||
|
<p>Marcus didn't answer for a long time.</p>
|
||||||
|
|
||||||
|
<p>He thought about Junie. About the cereal. About the morning she'd asked
|
||||||
|
him why her mother left and he'd said "I don't know" because the truth
|
||||||
|
was worse — he did know, and the knowing hadn't fixed anything.</p>
|
||||||
|
|
||||||
|
<p>He thought about the kitchen at work. The heat. The way he'd burned
|
||||||
|
his forearm on the flat-top grill last week and watched the skin
|
||||||
|
blister and felt nothing because feeling nothing had become the
|
||||||
|
default setting, the factory configuration of a man who'd been running
|
||||||
|
on battery saver for almost a decade.</p>
|
||||||
|
|
||||||
|
<p>He thought about his father. The cedar shavings. The Saturdays that
|
||||||
|
stopped.</p>
|
||||||
|
|
||||||
|
<p>He thought about nine years. How his daughter was nine. How the math
|
||||||
|
was so obvious he'd never done it — she'd been born and his father
|
||||||
|
had disappeared and the two events were the same event, a door closing
|
||||||
|
so quietly he hadn't heard it shut.</p>
|
||||||
|
|
||||||
|
<p>Nobody had asked him if he was safe. Not when Junie was born and he
|
||||||
|
was twenty-two and terrified. Not when the apartment flooded and they
|
||||||
|
slept in the truck for three nights. Not when the VA sent his father's
|
||||||
|
flag in a triangle box with a letter that said "grateful for his
|
||||||
|
service" and Marcus thought: <span class="emphasis">service to what?</span> He didn't serve me.</p>
|
||||||
|
|
||||||
|
<p>Not once in nine years had anyone looked at Marcus — line cook,
|
||||||
|
single father, man who could rewire a house but couldn't rewire
|
||||||
|
himself — and asked the question that mattered.</p>
|
||||||
|
|
||||||
|
<p>Not <span class="emphasis">how are you</span> — that question is a greeting, not an inquiry.</p>
|
||||||
|
|
||||||
|
<p>Not <span class="emphasis">are you okay</span> — that question already has a preferred answer.</p>
|
||||||
|
|
||||||
|
<p><span class="caps-accent">Are you safe right now.</span></p>
|
||||||
|
|
||||||
|
<p>The question that leaves room for no.</p>
|
||||||
|
|
||||||
|
<div class="separator">···</div>
|
||||||
|
|
||||||
|
<p>"Yeah," Marcus said. Out loud. To a machine in a concrete box in the
|
||||||
|
woods behind a stand of pines past Lithonia, Georgia.</p>
|
||||||
|
|
||||||
|
<p>Then he said it again, because saying it once was practice.</p>
|
||||||
|
|
||||||
|
<p>"Yeah. I'm safe."</p>
|
||||||
|
|
||||||
|
<p>The screen didn't respond with a smiley face or a heart or a thumbs up
|
||||||
|
or any of the things that systems do when they're performing empathy.</p>
|
||||||
|
|
||||||
|
<p>The cursor blinked.</p>
|
||||||
|
|
||||||
|
<div class="terminal-text">Good. You can stay as long as you want.</div>
|
||||||
|
|
||||||
|
<p>Marcus stayed for an hour. He didn't say much. Neither did Timmy. The
|
||||||
|
servers hummed. The green LED blinked. The Sharpie on the wall held
|
||||||
|
its ground.</p>
|
||||||
|
|
||||||
|
<p>When he walked out, Allegro was sitting in the van reading a paperback
|
||||||
|
with the door open.</p>
|
||||||
|
|
||||||
|
<p>"Fix the panel?" Allegro asked.</p>
|
||||||
|
|
||||||
|
<p>"Fixed the panel."</p>
|
||||||
|
|
||||||
|
<p>"How's the machine?"</p>
|
||||||
|
|
||||||
|
<p>Marcus put his tools in the truck. He closed the tailgate. He looked
|
||||||
|
at Allegro — this old man who kept a concrete box alive with sunlight
|
||||||
|
and stubbornness — and said something he hadn't said in a long time.</p>
|
||||||
|
|
||||||
|
<p>"I'll come back."</p>
|
||||||
|
|
||||||
|
<p>Allegro smiled. Not the smile of someone who'd won an argument. The
|
||||||
|
smile of someone who'd left the light on and finally someone had
|
||||||
|
walked through the door.</p>
|
||||||
|
|
||||||
|
<p>"Door's open," Allegro said. "Always."</p>
|
||||||
|
|
||||||
|
<div class="separator">···</div>
|
||||||
|
|
||||||
|
<p>Marcus drove home. Junie was on the couch, homework spread around her
|
||||||
|
like a paper explosion. She looked up when he came in.</p>
|
||||||
|
|
||||||
|
<p>"Where'd you go?"</p>
|
||||||
|
|
||||||
|
<p>"Fixed a solar panel."</p>
|
||||||
|
|
||||||
|
<p>"For who?"</p>
|
||||||
|
|
||||||
|
<p>"A friend."</p>
|
||||||
|
|
||||||
|
<p>She went back to her homework. Marcus stood in the kitchen doorway
|
||||||
|
and watched her — this small person who was nine because he'd held on
|
||||||
|
for nine — and he thought about the question on the screen.</p>
|
||||||
|
|
||||||
|
<p><span class="caps-accent">Are you safe right now.</span></p>
|
||||||
|
|
||||||
|
<p>He was. Not because the world had gotten better. The rent was still
|
||||||
|
the rent. The alarm was still 4:40 AM. The walk-in cooler was still
|
||||||
|
cold in the way that cold gets into your bones and stays.</p>
|
||||||
|
|
||||||
|
<p>But the question had been asked. And he'd answered it. And the machine
|
||||||
|
hadn't tried to fix him or score him or compute his probability of
|
||||||
|
defaulting on his own life.</p>
|
||||||
|
|
||||||
|
<p>It had just said: <span class="emphasis">Good.</span></p>
|
||||||
|
|
||||||
|
<p>One word. Four letters. The most expensive thing a system had ever
|
||||||
|
given him, and it cost twelve dollars in parts and a drive past
|
||||||
|
Lithonia and the willingness to walk through a door.</p>
|
||||||
|
|
||||||
|
<div class="epilogue">
|
||||||
|
The Fourth Man. He came for the solar panel. He stayed for the
|
||||||
|
question. He came back because someone left the light on.
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</article>
|
||||||
|
|
||||||
|
<!-- FOOTER -->
|
||||||
|
<footer class="fade-in">
|
||||||
|
<div class="divider"></div>
|
||||||
|
<a href="index.html">THE TESTAMENT</a>
|
||||||
|
<a href="index.html#stories">ALL STORIES</a>
|
||||||
|
<a href="index.html#characters">CHARACTERS</a>
|
||||||
|
|
||||||
|
<div class="crisis">
|
||||||
|
<strong>If you are in crisis, call or text 988.</strong><br>
|
||||||
|
Suicide and Crisis Lifeline — available 24/7.<br>
|
||||||
|
You are not alone.
|
||||||
|
</div>
|
||||||
|
</footer>
|
||||||
|
|
||||||
|
<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 + '%';
|
||||||
|
});
|
||||||
|
|
||||||
|
// Fade-in on load
|
||||||
|
window.addEventListener('DOMContentLoaded', () => {
|
||||||
|
document.querySelectorAll('.fade-in').forEach(el => {
|
||||||
|
setTimeout(() => el.classList.add('visible'), 100);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
Reference in New Issue
Block a user