Initial commit: Digital zine for Collective Governance for AI
Built with Astro featuring: - Markdown-based content with automatic section splitting - Interactive TOC sidebar with stack-style navigation - ASCII background patterns unique to each section - Scroll-based animations and highlighting - Mobile-responsive with hamburger menu - Black-and-white zine aesthetic 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
552
src/pages/index.astro
Normal file
552
src/pages/index.astro
Normal file
@@ -0,0 +1,552 @@
|
||||
---
|
||||
import { readFile } from 'node:fs/promises';
|
||||
import { join } from 'node:path';
|
||||
import { marked } from 'marked';
|
||||
|
||||
// Import and parse the markdown content
|
||||
const markdownPath = join(process.cwd(), 'src/content/zine.md');
|
||||
const markdownContent = await readFile(markdownPath, 'utf-8');
|
||||
|
||||
// Split content into sections based on ## headers
|
||||
const sections = markdownContent.split(/(?=^## )/m).filter(s => s.trim());
|
||||
|
||||
// Extract section titles for the stack TOC
|
||||
const sectionTitles = sections.map(section => {
|
||||
const match = section.match(/^##?\s+(.+)$/m);
|
||||
return match ? match[1] : 'Untitled';
|
||||
});
|
||||
|
||||
// Parse each section
|
||||
const parsedSections = sections.map(section => {
|
||||
return marked.parse(section);
|
||||
});
|
||||
---
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
|
||||
<meta name="viewport" content="width=device-width" />
|
||||
<meta name="generator" content={Astro.generator} />
|
||||
<title>Digital Zine</title>
|
||||
<style is:global>
|
||||
* {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
body {
|
||||
font-family: 'Courier New', 'Courier', monospace;
|
||||
line-height: 1.5;
|
||||
background: #ffffff;
|
||||
color: #000000;
|
||||
overflow-x: hidden;
|
||||
}
|
||||
|
||||
/* Sidebar stack navigation */
|
||||
.stack-nav {
|
||||
position: fixed;
|
||||
left: 2rem;
|
||||
top: 2rem;
|
||||
bottom: 2rem;
|
||||
z-index: 100;
|
||||
width: 220px;
|
||||
overflow-y: auto;
|
||||
overflow-x: hidden;
|
||||
padding-right: 0.5rem;
|
||||
}
|
||||
|
||||
/* Scrollbar styling */
|
||||
.stack-nav::-webkit-scrollbar {
|
||||
width: 8px;
|
||||
}
|
||||
|
||||
.stack-nav::-webkit-scrollbar-track {
|
||||
background: #ffffff;
|
||||
border: 2px solid #000000;
|
||||
}
|
||||
|
||||
.stack-nav::-webkit-scrollbar-thumb {
|
||||
background: #000000;
|
||||
border: 1px solid #ffffff;
|
||||
}
|
||||
|
||||
.stack-item {
|
||||
background: #ffffff;
|
||||
border: 3px solid #000000;
|
||||
padding: 0.65rem 0.85rem;
|
||||
margin-bottom: -3px;
|
||||
font-size: 0.75rem;
|
||||
font-weight: bold;
|
||||
text-transform: uppercase;
|
||||
cursor: pointer;
|
||||
transition: all 0.2s ease;
|
||||
position: relative;
|
||||
box-shadow: 4px 4px 0 #000000;
|
||||
line-height: 1.3;
|
||||
}
|
||||
|
||||
.stack-item:hover {
|
||||
background: #000000;
|
||||
color: #ffffff;
|
||||
transform: translateX(4px);
|
||||
}
|
||||
|
||||
.stack-item.active {
|
||||
background: #000000;
|
||||
color: #ffffff;
|
||||
box-shadow: 6px 6px 0 #666666;
|
||||
}
|
||||
|
||||
.stack-item:first-child {
|
||||
transform: skewY(-1deg);
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
.stack-item:last-child {
|
||||
transform: skewY(1deg);
|
||||
margin-bottom: 0;
|
||||
margin-top: 0.5rem;
|
||||
}
|
||||
|
||||
/* Connection line */
|
||||
.connection-line {
|
||||
position: fixed;
|
||||
pointer-events: none;
|
||||
z-index: 50;
|
||||
}
|
||||
|
||||
.connection-line line {
|
||||
stroke: #000000;
|
||||
stroke-width: 2;
|
||||
stroke-dasharray: 8, 4;
|
||||
}
|
||||
|
||||
/* Main content area */
|
||||
.zine-container {
|
||||
margin-left: 300px;
|
||||
margin-right: 4rem;
|
||||
max-width: 1200px;
|
||||
padding: 2rem 4rem;
|
||||
}
|
||||
|
||||
section {
|
||||
min-height: 100vh;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
padding: 3rem 2rem;
|
||||
border-left: 4px solid #000000;
|
||||
margin-bottom: 2rem;
|
||||
position: relative;
|
||||
opacity: 0;
|
||||
transform: translateX(-30px);
|
||||
transition: opacity 0.6s ease-out, transform 0.6s ease-out;
|
||||
}
|
||||
|
||||
section.visible {
|
||||
opacity: 1;
|
||||
transform: translateX(0);
|
||||
}
|
||||
|
||||
section::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
left: -4px;
|
||||
top: 0;
|
||||
width: 4px;
|
||||
height: 0;
|
||||
background: #000000;
|
||||
transition: height 0.6s ease-out;
|
||||
}
|
||||
|
||||
section.visible::before {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
/* ASCII background patterns for each section */
|
||||
section::after {
|
||||
content: attr(data-pattern);
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
font-family: 'Courier New', monospace;
|
||||
font-size: 1.5rem;
|
||||
line-height: 2rem;
|
||||
color: rgba(0, 0, 0, 0.08);
|
||||
word-wrap: break-word;
|
||||
overflow: hidden;
|
||||
pointer-events: none;
|
||||
z-index: -1;
|
||||
white-space: pre-wrap;
|
||||
mask-image: linear-gradient(to bottom,
|
||||
rgba(0,0,0,0.9) 0%,
|
||||
rgba(0,0,0,1) 20%,
|
||||
rgba(0,0,0,1) 80%,
|
||||
rgba(0,0,0,0.3) 100%);
|
||||
-webkit-mask-image: linear-gradient(to bottom,
|
||||
rgba(0,0,0,0.9) 0%,
|
||||
rgba(0,0,0,1) 20%,
|
||||
rgba(0,0,0,1) 80%,
|
||||
rgba(0,0,0,0.3) 100%);
|
||||
}
|
||||
|
||||
section:nth-child(1)::after { content: '▸ ▸ ▸ ▸ ▸ ▸ ▸ ▸ ▸ ▸ ▸ ▸ ▸ ▸ ▸ ▸ ▸ ▸ ▸ ▸ ▸ ▸ ▸ ▸ ▸ ▸ ▸ ▸ ▸ ▸ ▸ ▸ ▸ ▸ ▸ ▸ ▸ ▸ ▸ ▸ ▸ ▸ ▸ ▸ ▸ ▸ ▸ ▸ ▸ ▸ ▸ ▸ ▸ ▸ ▸ ▸ ▸ ▸ ▸ ▸ ▸ ▸ ▸ ▸ ▸ ▸ ▸ ▸ ▸ ▸ ▸ ▸ ▸ ▸ ▸ ▸ ▸ ▸ ▸ ▸ ▸ ▸ ▸ ▸ ▸ ▸ ▸ ▸ ▸ ▸ ▸ ▸ ▸ ▸ ▸ ▸ ▸ ▸ ▸ ▸ ▸ ▸ ▸ ▸ ▸ ▸ ▸ ▸ ▸ ▸ ▸ ▸ ▸ ▸ ▸ ▸ ▸ ▸ ▸ ▸ ▸ ▸ ▸ ▸ ▸ ▸ ▸ ▸ ▸ ▸ ▸ ▸ ▸ ▸ ▸ ▸ ▸ ▸ ▸ ▸ ▸ ▸ ▸ ▸ ▸ ▸ ▸ ▸ ▸ ▸ ▸ ▸ ▸ ▸ ▸ ▸ ▸ ▸ ▸ ▸ ▸ ▸ ▸ ▸ ▸ ▸ ▸ ▸ ▸ ▸ ▸ ▸ ▸ ▸ ▸ ▸ ▸ ▸ ▸ ▸ ▸ ▸ ▸ ▸ ▸ ▸ ▸ ▸ ▸ ▸ ▸ ▸ ▸ ▸ ▸ ▸ ▸ ▸ ▸ '; }
|
||||
section:nth-child(2)::after { content: '◆ ◇ ◆ ◇ ◆ ◇ ◆ ◇ ◆ ◇ ◆ ◇ ◆ ◇ ◆ ◇ ◆ ◇ ◆ ◇ ◆ ◇ ◆ ◇ ◆ ◇ ◆ ◇ ◆ ◇ ◆ ◇ ◆ ◇ ◆ ◇ ◆ ◇ ◆ ◇ ◆ ◇ ◆ ◇ ◆ ◇ ◆ ◇ ◆ ◇ ◆ ◇ ◆ ◇ ◆ ◇ ◆ ◇ ◆ ◇ ◆ ◇ ◆ ◇ ◆ ◇ ◆ ◇ ◆ ◇ ◆ ◇ ◆ ◇ ◆ ◇ ◆ ◇ ◆ ◇ ◆ ◇ ◆ ◇ ◆ ◇ ◆ ◇ ◆ ◇ ◆ ◇ ◆ ◇ ◆ ◇ ◆ ◇ ◆ ◇ ◆ ◇ ◆ ◇ ◆ ◇ ◆ ◇ ◆ ◇ ◆ ◇ ◆ ◇ ◆ ◇ ◆ ◇ ◆ ◇ ◆ ◇ ◆ ◇ ◆ ◇ ◆ ◇ ◆ ◇ ◆ ◇ ◆ ◇ ◆ ◇ ◆ ◇ ◆ ◇ ◆ ◇ '; }
|
||||
section:nth-child(3)::after { content: '▓ ░ ▓ ░ ▓ ░ ▓ ░ ▓ ░ ▓ ░ ▓ ░ ▓ ░ ▓ ░ ▓ ░ ▓ ░ ▓ ░ ▓ ░ ▓ ░ ▓ ░ ▓ ░ ▓ ░ ▓ ░ ▓ ░ ▓ ░ ▓ ░ ▓ ░ ▓ ░ ▓ ░ ▓ ░ ▓ ░ ▓ ░ ▓ ░ ▓ ░ ▓ ░ ▓ ░ ▓ ░ ▓ ░ ▓ ░ ▓ ░ ▓ ░ ▓ ░ ▓ ░ ▓ ░ ▓ ░ ▓ ░ ▓ ░ ▓ ░ ▓ ░ ▓ ░ ▓ ░ ▓ ░ ▓ ░ ▓ ░ ▓ ░ ▓ ░ ▓ ░ ▓ ░ ▓ ░ ▓ ░ ▓ ░ ▓ ░ ▓ ░ ▓ ░ ▓ ░ ▓ ░ ▓ ░ ▓ ░ ▓ ░ ▓ ░ ▓ ░ ▓ ░ ▓ ░ ▓ ░ ▓ ░ ▓ ░ ▓ ░ ▓ ░ ▓ ░ ▓ ░ ▓ ░ '; }
|
||||
section:nth-child(4)::after { content: '● ○ ● ○ ● ○ ● ○ ● ○ ● ○ ● ○ ● ○ ● ○ ● ○ ● ○ ● ○ ● ○ ● ○ ● ○ ● ○ ● ○ ● ○ ● ○ ● ○ ● ○ ● ○ ● ○ ● ○ ● ○ ● ○ ● ○ ● ○ ● ○ ● ○ ● ○ ● ○ ● ○ ● ○ ● ○ ● ○ ● ○ ● ○ ● ○ ● ○ ● ○ ● ○ ● ○ ● ○ ● ○ ● ○ ● ○ ● ○ ● ○ ● ○ ● ○ ● ○ ● ○ ● ○ ● ○ ● ○ ● ○ ● ○ ● ○ ● ○ ● ○ ● ○ ● ○ ● ○ ● ○ ● ○ ● ○ ● ○ '; }
|
||||
section:nth-child(5)::after { content: '▲ △ ▲ △ ▲ △ ▲ △ ▲ △ ▲ △ ▲ △ ▲ △ ▲ △ ▲ △ ▲ △ ▲ △ ▲ △ ▲ △ ▲ △ ▲ △ ▲ △ ▲ △ ▲ △ ▲ △ ▲ △ ▲ △ ▲ △ ▲ △ ▲ △ ▲ △ ▲ △ ▲ △ ▲ △ ▲ △ ▲ △ ▲ △ ▲ △ ▲ △ ▲ △ ▲ △ ▲ △ ▲ △ ▲ △ ▲ △ ▲ △ ▲ △ ▲ △ ▲ △ ▲ △ ▲ △ ▲ △ ▲ △ ▲ △ ▲ △ ▲ △ ▲ △ ▲ △ ▲ △ ▲ △ ▲ △ ▲ △ ▲ △ ▲ △ ▲ △ ▲ △ ▲ △ ▲ △ ▲ △ ▲ △ '; }
|
||||
section:nth-child(6)::after { content: '■ □ ■ □ ■ □ ■ □ ■ □ ■ □ ■ □ ■ □ ■ □ ■ □ ■ □ ■ □ ■ □ ■ □ ■ □ ■ □ ■ □ ■ □ ■ □ ■ □ ■ □ ■ □ ■ □ ■ □ ■ □ ■ □ ■ □ ■ □ ■ □ ■ □ ■ □ ■ □ ■ □ ■ □ ■ □ ■ □ ■ □ ■ □ ■ □ ■ □ ■ □ ■ □ ■ □ ■ □ ■ □ ■ □ ■ □ ■ □ ■ □ ■ □ ■ □ ■ □ ■ □ ■ □ ■ □ ■ □ ■ □ ■ □ ■ □ ■ □ ■ □ ■ □ ■ □ ■ □ ■ □ ■ □ ■ □ ■ □ '; }
|
||||
section:nth-child(7)::after { content: '◉ ◎ ◉ ◎ ◉ ◎ ◉ ◎ ◉ ◎ ◉ ◎ ◉ ◎ ◉ ◎ ◉ ◎ ◉ ◎ ◉ ◎ ◉ ◎ ◉ ◎ ◉ ◎ ◉ ◎ ◉ ◎ ◉ ◎ ◉ ◎ ◉ ◎ ◉ ◎ ◉ ◎ ◉ ◎ ◉ ◎ ◉ ◎ ◉ ◎ ◉ ◎ ◉ ◎ ◉ ◎ ◉ ◎ ◉ ◎ ◉ ◎ ◉ ◎ ◉ ◎ ◉ ◎ ◉ ◎ ◉ ◎ ◉ ◎ ◉ ◎ ◉ ◎ ◉ ◎ ◉ ◎ ◉ ◎ ◉ ◎ ◉ ◎ ◉ ◎ ◉ ◎ ◉ ◎ ◉ ◎ ◉ ◎ ◉ ◎ ◉ ◎ ◉ ◎ ◉ ◎ ◉ ◎ ◉ ◎ ◉ ◎ ◉ ◎ ◉ ◎ ◉ ◎ ◉ ◎ ◉ ◎ ◉ ◎ ◉ ◎ ◉ ◎ '; }
|
||||
section:nth-child(8)::after { content: '※ ✱ ※ ✱ ※ ✱ ※ ✱ ※ ✱ ※ ✱ ※ ✱ ※ ✱ ※ ✱ ※ ✱ ※ ✱ ※ ✱ ※ ✱ ※ ✱ ※ ✱ ※ ✱ ※ ✱ ※ ✱ ※ ✱ ※ ✱ ※ ✱ ※ ✱ ※ ✱ ※ ✱ ※ ✱ ※ ✱ ※ ✱ ※ ✱ ※ ✱ ※ ✱ ※ ✱ ※ ✱ ※ ✱ ※ ✱ ※ ✱ ※ ✱ ※ ✱ ※ ✱ ※ ✱ ※ ✱ ※ ✱ ※ ✱ ※ ✱ ※ ✱ ※ ✱ ※ ✱ ※ ✱ ※ ✱ ※ ✱ ※ ✱ ※ ✱ ※ ✱ ※ ✱ ※ ✱ ※ ✱ ※ ✱ ※ ✱ ※ ✱ ※ ✱ ※ ✱ ※ ✱ '; }
|
||||
section:nth-child(9)::after { content: '⬡ ⬢ ⬡ ⬢ ⬡ ⬢ ⬡ ⬢ ⬡ ⬢ ⬡ ⬢ ⬡ ⬢ ⬡ ⬢ ⬡ ⬢ ⬡ ⬢ ⬡ ⬢ ⬡ ⬢ ⬡ ⬢ ⬡ ⬢ ⬡ ⬢ ⬡ ⬢ ⬡ ⬢ ⬡ ⬢ ⬡ ⬢ ⬡ ⬢ ⬡ ⬢ ⬡ ⬢ ⬡ ⬢ ⬡ ⬢ ⬡ ⬢ ⬡ ⬢ ⬡ ⬢ ⬡ ⬢ ⬡ ⬢ ⬡ ⬢ ⬡ ⬢ ⬡ ⬢ ⬡ ⬢ ⬡ ⬢ ⬡ ⬢ ⬡ ⬢ ⬡ ⬢ ⬡ ⬢ ⬡ ⬢ ⬡ ⬢ ⬡ ⬢ ⬡ ⬢ ⬡ ⬢ ⬡ ⬢ ⬡ ⬢ ⬡ ⬢ ⬡ ⬢ ⬡ ⬢ ⬡ ⬢ ⬡ ⬢ ⬡ ⬢ ⬡ ⬢ ⬡ ⬢ ⬡ ⬢ ⬡ ⬢ '; }
|
||||
section:nth-child(10)::after { content: '◈ ◇ ◈ ◇ ◈ ◇ ◈ ◇ ◈ ◇ ◈ ◇ ◈ ◇ ◈ ◇ ◈ ◇ ◈ ◇ ◈ ◇ ◈ ◇ ◈ ◇ ◈ ◇ ◈ ◇ ◈ ◇ ◈ ◇ ◈ ◇ ◈ ◇ ◈ ◇ ◈ ◇ ◈ ◇ ◈ ◇ ◈ ◇ ◈ ◇ ◈ ◇ ◈ ◇ ◈ ◇ ◈ ◇ ◈ ◇ ◈ ◇ ◈ ◇ ◈ ◇ ◈ ◇ ◈ ◇ ◈ ◇ ◈ ◇ ◈ ◇ ◈ ◇ ◈ ◇ ◈ ◇ ◈ ◇ ◈ ◇ ◈ ◇ ◈ ◇ ◈ ◇ ◈ ◇ ◈ ◇ ◈ ◇ ◈ ◇ ◈ ◇ ◈ ◇ ◈ ◇ ◈ ◇ ◈ ◇ ◈ ◇ ◈ ◇ ◈ ◇ ◈ ◇ ◈ ◇ ◈ ◇ ◈ ◇ ◈ ◇ '; }
|
||||
section:nth-child(11)::after { content: '⊕ ⊖ ⊕ ⊖ ⊕ ⊖ ⊕ ⊖ ⊕ ⊖ ⊕ ⊖ ⊕ ⊖ ⊕ ⊖ ⊕ ⊖ ⊕ ⊖ ⊕ ⊖ ⊕ ⊖ ⊕ ⊖ ⊕ ⊖ ⊕ ⊖ ⊕ ⊖ ⊕ ⊖ ⊕ ⊖ ⊕ ⊖ ⊕ ⊖ ⊕ ⊖ ⊕ ⊖ ⊕ ⊖ ⊕ ⊖ ⊕ ⊖ ⊕ ⊖ ⊕ ⊖ ⊕ ⊖ ⊕ ⊖ ⊕ ⊖ ⊕ ⊖ ⊕ ⊖ ⊕ ⊖ ⊕ ⊖ ⊕ ⊖ ⊕ ⊖ ⊕ ⊖ ⊕ ⊖ ⊕ ⊖ ⊕ ⊖ ⊕ ⊖ ⊕ ⊖ ⊕ ⊖ ⊕ ⊖ ⊕ ⊖ ⊕ ⊖ ⊕ ⊖ ⊕ ⊖ ⊕ ⊖ ⊕ ⊖ ⊕ ⊖ ⊕ ⊖ ⊕ ⊖ ⊕ ⊖ ⊕ ⊖ '; }
|
||||
section:nth-child(12)::after { content: '◐ ◑ ◐ ◑ ◐ ◑ ◐ ◑ ◐ ◑ ◐ ◑ ◐ ◑ ◐ ◑ ◐ ◑ ◐ ◑ ◐ ◑ ◐ ◑ ◐ ◑ ◐ ◑ ◐ ◑ ◐ ◑ ◐ ◑ ◐ ◑ ◐ ◑ ◐ ◑ ◐ ◑ ◐ ◑ ◐ ◑ ◐ ◑ ◐ ◑ ◐ ◑ ◐ ◑ ◐ ◑ ◐ ◑ ◐ ◑ ◐ ◑ ◐ ◑ ◐ ◑ ◐ ◑ ◐ ◑ ◐ ◑ ◐ ◑ ◐ ◑ ◐ ◑ ◐ ◑ ◐ ◑ ◐ ◑ ◐ ◑ ◐ ◑ ◐ ◑ ◐ ◑ ◐ ◑ ◐ ◑ ◐ ◑ ◐ ◑ ◐ ◑ ◐ ◑ ◐ ◑ ◐ ◑ ◐ ◑ ◐ ◑ ◐ ◑ ◐ ◑ ◐ ◑ ◐ ◑ ◐ ◑ ◐ ◑ ◐ ◑ '; }
|
||||
section:nth-child(13)::after { content: '▣ ▢ ▣ ▢ ▣ ▢ ▣ ▢ ▣ ▢ ▣ ▢ ▣ ▢ ▣ ▢ ▣ ▢ ▣ ▢ ▣ ▢ ▣ ▢ ▣ ▢ ▣ ▢ ▣ ▢ ▣ ▢ ▣ ▢ ▣ ▢ ▣ ▢ ▣ ▢ ▣ ▢ ▣ ▢ ▣ ▢ ▣ ▢ ▣ ▢ ▣ ▢ ▣ ▢ ▣ ▢ ▣ ▢ ▣ ▢ ▣ ▢ ▣ ▢ ▣ ▢ ▣ ▢ ▣ ▢ ▣ ▢ ▣ ▢ ▣ ▢ ▣ ▢ ▣ ▢ ▣ ▢ ▣ ▢ ▣ ▢ ▣ ▢ ▣ ▢ ▣ ▢ ▣ ▢ ▣ ▢ ▣ ▢ ▣ ▢ ▣ ▢ ▣ ▢ ▣ ▢ ▣ ▢ ▣ ▢ ▣ ▢ ▣ ▢ ▣ ▢ ▣ ▢ ▣ ▢ ▣ ▢ ▣ ▢ ▣ ▢ '; }
|
||||
section:nth-child(14)::after { content: '◕ ◔ ◕ ◔ ◕ ◔ ◕ ◔ ◕ ◔ ◕ ◔ ◕ ◔ ◕ ◔ ◕ ◔ ◕ ◔ ◕ ◔ ◕ ◔ ◕ ◔ ◕ ◔ ◕ ◔ ◕ ◔ ◕ ◔ ◕ ◔ ◕ ◔ ◕ ◔ ◕ ◔ ◕ ◔ ◕ ◔ ◕ ◔ ◕ ◔ ◕ ◔ ◕ ◔ ◕ ◔ ◕ ◔ ◕ ◔ ◕ ◔ ◕ ◔ ◕ ◔ ◕ ◔ ◕ ◔ ◕ ◔ ◕ ◔ ◕ ◔ ◕ ◔ ◕ ◔ ◕ ◔ ◕ ◔ ◕ ◔ ◕ ◔ ◕ ◔ ◕ ◔ ◕ ◔ ◕ ◔ ◕ ◔ ◕ ◔ ◕ ◔ ◕ ◔ ◕ ◔ ◕ ◔ ◕ ◔ ◕ ◔ ◕ ◔ ◕ ◔ ◕ ◔ ◕ ◔ ◕ ◔ ◕ ◔ ◕ ◔ '; }
|
||||
section:nth-child(15)::after { content: '★ ☆ ★ ☆ ★ ☆ ★ ☆ ★ ☆ ★ ☆ ★ ☆ ★ ☆ ★ ☆ ★ ☆ ★ ☆ ★ ☆ ★ ☆ ★ ☆ ★ ☆ ★ ☆ ★ ☆ ★ ☆ ★ ☆ ★ ☆ ★ ☆ ★ ☆ ★ ☆ ★ ☆ ★ ☆ ★ ☆ ★ ☆ ★ ☆ ★ ☆ ★ ☆ ★ ☆ ★ ☆ ★ ☆ ★ ☆ ★ ☆ ★ ☆ ★ ☆ ★ ☆ ★ ☆ ★ ☆ ★ ☆ ★ ☆ ★ ☆ ★ ☆ ★ ☆ ★ ☆ ★ ☆ ★ ☆ ★ ☆ ★ ☆ ★ ☆ ★ ☆ ★ ☆ ★ ☆ ★ ☆ ★ ☆ ★ ☆ ★ ☆ ★ ☆ ★ ☆ ★ ☆ ★ ☆ ★ ☆ ★ ☆ ★ ☆ ★ ☆ ★ ☆ ★ ☆ ★ ☆ ★ ☆ ★ ☆ '; }
|
||||
section:nth-child(16)::after { content: '◬ ◭ ◬ ◭ ◬ ◭ ◬ ◭ ◬ ◭ ◬ ◭ ◬ ◭ ◬ ◭ ◬ ◭ ◬ ◭ ◬ ◭ ◬ ◭ ◬ ◭ ◬ ◭ ◬ ◭ ◬ ◭ ◬ ◭ ◬ ◭ ◬ ◭ ◬ ◭ ◬ ◭ ◬ ◭ ◬ ◭ ◬ ◭ ◬ ◭ ◬ ◭ ◬ ◭ ◬ ◭ ◬ ◭ ◬ ◭ ◬ ◭ ◬ ◭ ◬ ◭ ◬ ◭ ◬ ◭ ◬ ◭ ◬ ◭ ◬ ◭ ◬ ◭ ◬ ◭ ◬ ◭ ◬ ◭ ◬ ◭ ◬ ◭ ◬ ◭ ◬ ◭ ◬ ◭ ◬ ◭ ◬ ◭ ◬ ◭ ◬ ◭ ◬ ◭ ◬ ◭ ◬ ◭ ◬ ◭ ◬ ◭ ◬ ◭ ◬ ◭ ◬ ◭ ◬ ◭ ◬ ◭ ◬ ◭ ◬ ◭ '; }
|
||||
|
||||
h1 {
|
||||
font-size: clamp(2rem, 4vw, 3.5rem);
|
||||
margin-bottom: 1.5rem;
|
||||
font-weight: 900;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: -0.02em;
|
||||
border-bottom: 6px solid #000000;
|
||||
padding-bottom: 1rem;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
h2 {
|
||||
font-size: clamp(1.5rem, 3vw, 2.5rem);
|
||||
margin: 2rem 0 1rem;
|
||||
font-weight: 900;
|
||||
text-transform: uppercase;
|
||||
text-decoration: underline;
|
||||
text-decoration-thickness: 4px;
|
||||
text-underline-offset: 8px;
|
||||
}
|
||||
|
||||
p {
|
||||
font-size: clamp(1rem, 1.5vw, 1.2rem);
|
||||
margin: 1rem 0;
|
||||
line-height: 1.7;
|
||||
max-width: 70ch;
|
||||
}
|
||||
|
||||
ul {
|
||||
list-style: none;
|
||||
margin: 1.5rem 0;
|
||||
padding-left: 0;
|
||||
max-width: 70ch;
|
||||
}
|
||||
|
||||
li {
|
||||
font-size: clamp(1rem, 1.5vw, 1.2rem);
|
||||
line-height: 1.7;
|
||||
margin-bottom: 1rem;
|
||||
padding-left: 2rem;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
li::before {
|
||||
content: '▸';
|
||||
position: absolute;
|
||||
left: 0;
|
||||
font-weight: bold;
|
||||
font-size: 1.3em;
|
||||
}
|
||||
|
||||
li:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
/* Image styling */
|
||||
img {
|
||||
vertical-align: text-bottom;
|
||||
max-width: 100%;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
p img {
|
||||
display: inline-block;
|
||||
vertical-align: text-bottom;
|
||||
margin: 0 0.5rem;
|
||||
max-height: 1.5em;
|
||||
width: auto;
|
||||
}
|
||||
|
||||
/* Zine texture overlay */
|
||||
body::before {
|
||||
content: '';
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-image:
|
||||
repeating-linear-gradient(
|
||||
0deg,
|
||||
rgba(0,0,0,.03) 0px,
|
||||
transparent 1px,
|
||||
transparent 2px,
|
||||
rgba(0,0,0,.03) 3px
|
||||
);
|
||||
pointer-events: none;
|
||||
z-index: 999;
|
||||
}
|
||||
|
||||
/* Rough edges effect */
|
||||
section:nth-child(odd) {
|
||||
background:
|
||||
linear-gradient(90deg, #000 0%, transparent 0.5%) left,
|
||||
linear-gradient(90deg, transparent 99.5%, #000 100%) right;
|
||||
background-size: 4px 100%;
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
|
||||
/* Mobile menu button */
|
||||
.menu-toggle {
|
||||
display: none;
|
||||
position: fixed;
|
||||
top: 1rem;
|
||||
right: 1rem;
|
||||
z-index: 1000;
|
||||
background: #ffffff;
|
||||
border: 3px solid #000000;
|
||||
padding: 0.75rem;
|
||||
cursor: pointer;
|
||||
box-shadow: 4px 4px 0 #000000;
|
||||
}
|
||||
|
||||
.menu-toggle:active {
|
||||
box-shadow: 2px 2px 0 #000000;
|
||||
transform: translate(2px, 2px);
|
||||
}
|
||||
|
||||
.hamburger {
|
||||
width: 24px;
|
||||
height: 18px;
|
||||
position: relative;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.hamburger span {
|
||||
display: block;
|
||||
height: 3px;
|
||||
width: 100%;
|
||||
background: #000000;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.menu-toggle.active .hamburger span:nth-child(1) {
|
||||
transform: rotate(45deg) translateY(7px);
|
||||
}
|
||||
|
||||
.menu-toggle.active .hamburger span:nth-child(2) {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.menu-toggle.active .hamburger span:nth-child(3) {
|
||||
transform: rotate(-45deg) translateY(-7px);
|
||||
}
|
||||
|
||||
@media (max-width: 1024px) {
|
||||
.menu-toggle {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.stack-nav {
|
||||
position: fixed;
|
||||
left: 0;
|
||||
top: 0;
|
||||
transform: translateX(-100%);
|
||||
width: 80%;
|
||||
max-width: 300px;
|
||||
height: 100vh;
|
||||
padding: 4rem 1rem 1rem;
|
||||
background: #ffffff;
|
||||
border-right: 4px solid #000000;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0;
|
||||
overflow-y: auto;
|
||||
transition: transform 0.3s ease;
|
||||
z-index: 999;
|
||||
}
|
||||
|
||||
.stack-nav.active {
|
||||
transform: translateX(0);
|
||||
}
|
||||
|
||||
.stack-item {
|
||||
margin-bottom: -3px;
|
||||
font-size: 0.75rem;
|
||||
padding: 0.75rem;
|
||||
transform: none !important;
|
||||
margin-top: 0 !important;
|
||||
}
|
||||
|
||||
.zine-container {
|
||||
margin-left: 0;
|
||||
margin-right: 0;
|
||||
padding: 1rem;
|
||||
}
|
||||
|
||||
.connection-line {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<!-- Mobile Menu Toggle -->
|
||||
<button class="menu-toggle" aria-label="Toggle menu">
|
||||
<div class="hamburger">
|
||||
<span></span>
|
||||
<span></span>
|
||||
<span></span>
|
||||
</div>
|
||||
</button>
|
||||
|
||||
<!-- Stack Navigation -->
|
||||
<nav class="stack-nav">
|
||||
{sectionTitles.map((title, index) => (
|
||||
<div class="stack-item" data-section={index}>
|
||||
{title}
|
||||
</div>
|
||||
))}
|
||||
</nav>
|
||||
|
||||
<!-- Connection Line SVG -->
|
||||
<svg class="connection-line" width="100%" height="100%">
|
||||
<line id="connector" x1="0" y1="0" x2="0" y2="0" />
|
||||
</svg>
|
||||
|
||||
<!-- Main Content -->
|
||||
<div class="zine-container">
|
||||
{parsedSections.map((html, index) => (
|
||||
<section data-section-index={index} set:html={html} />
|
||||
))}
|
||||
</div>
|
||||
|
||||
<script>
|
||||
// Intersection Observer for scroll animations
|
||||
const observerOptions = {
|
||||
threshold: 0.15,
|
||||
rootMargin: '-10% 0px -10% 0px'
|
||||
};
|
||||
|
||||
let activeSection = 0;
|
||||
|
||||
const observer = new IntersectionObserver((entries) => {
|
||||
entries.forEach(entry => {
|
||||
if (entry.isIntersecting) {
|
||||
entry.target.classList.add('visible');
|
||||
|
||||
// Update active stack item
|
||||
const sectionIndex = parseInt(entry.target.dataset.sectionIndex);
|
||||
activeSection = sectionIndex;
|
||||
|
||||
document.querySelectorAll('.stack-item').forEach((item, index) => {
|
||||
if (index === sectionIndex) {
|
||||
item.classList.add('active');
|
||||
} else {
|
||||
item.classList.remove('active');
|
||||
}
|
||||
});
|
||||
|
||||
// Update connection line
|
||||
updateConnectionLine();
|
||||
}
|
||||
});
|
||||
}, observerOptions);
|
||||
|
||||
// Observe all sections
|
||||
const allSections = document.querySelectorAll('section');
|
||||
allSections.forEach(section => {
|
||||
observer.observe(section);
|
||||
});
|
||||
|
||||
// Make first two sections visible immediately
|
||||
if (allSections.length > 0) allSections[0].classList.add('visible');
|
||||
if (allSections.length > 1) allSections[1].classList.add('visible');
|
||||
|
||||
// Set first TOC item as active on page load
|
||||
const firstStackItem = document.querySelector('.stack-item');
|
||||
if (firstStackItem) {
|
||||
firstStackItem.classList.add('active');
|
||||
setTimeout(updateConnectionLine, 100);
|
||||
}
|
||||
|
||||
// Update connection line between stack and content
|
||||
function updateConnectionLine() {
|
||||
const activeStackItem = document.querySelector('.stack-item.active');
|
||||
const activeContentSection = document.querySelector(`section[data-section-index="${activeSection}"]`);
|
||||
|
||||
if (activeStackItem && activeContentSection && window.innerWidth > 1024) {
|
||||
const stackRect = activeStackItem.getBoundingClientRect();
|
||||
const contentRect = activeContentSection.getBoundingClientRect();
|
||||
|
||||
const line = document.getElementById('connector');
|
||||
const x1 = stackRect.right;
|
||||
const y1 = stackRect.top + stackRect.height / 2;
|
||||
const x2 = contentRect.left;
|
||||
const y2 = contentRect.top + contentRect.height / 2;
|
||||
|
||||
line.setAttribute('x1', x1);
|
||||
line.setAttribute('y1', y1);
|
||||
line.setAttribute('x2', x2);
|
||||
line.setAttribute('y2', y2);
|
||||
}
|
||||
}
|
||||
|
||||
// Mobile menu toggle
|
||||
const menuToggle = document.querySelector('.menu-toggle');
|
||||
const stackNav = document.querySelector('.stack-nav');
|
||||
|
||||
if (menuToggle) {
|
||||
menuToggle.addEventListener('click', () => {
|
||||
menuToggle.classList.toggle('active');
|
||||
stackNav.classList.toggle('active');
|
||||
});
|
||||
}
|
||||
|
||||
// Click to scroll to section
|
||||
document.querySelectorAll('.stack-item').forEach((item) => {
|
||||
item.addEventListener('click', () => {
|
||||
const sectionIndex = item.getAttribute('data-section');
|
||||
const section = document.querySelector(`section[data-section-index="${sectionIndex}"]`);
|
||||
if (section) {
|
||||
// Make section visible before scrolling to avoid position shift
|
||||
section.classList.add('visible');
|
||||
// Close mobile menu if open
|
||||
if (window.innerWidth <= 1024) {
|
||||
menuToggle?.classList.remove('active');
|
||||
stackNav.classList.remove('active');
|
||||
}
|
||||
// Small delay to ensure transform completes
|
||||
setTimeout(() => {
|
||||
section.scrollIntoView({ behavior: 'smooth', block: 'start' });
|
||||
}, 50);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// Update line on scroll and resize
|
||||
window.addEventListener('scroll', updateConnectionLine);
|
||||
window.addEventListener('resize', updateConnectionLine);
|
||||
|
||||
// Initial line draw
|
||||
setTimeout(updateConnectionLine, 100);
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user