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:
24
.gitignore
vendored
Normal file
24
.gitignore
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
# build output
|
||||
dist/
|
||||
# generated types
|
||||
.astro/
|
||||
|
||||
# dependencies
|
||||
node_modules/
|
||||
|
||||
# logs
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
pnpm-debug.log*
|
||||
|
||||
|
||||
# environment variables
|
||||
.env
|
||||
.env.production
|
||||
|
||||
# macOS-specific files
|
||||
.DS_Store
|
||||
|
||||
# jetbrains setting folder
|
||||
.idea/
|
||||
4
.vscode/extensions.json
vendored
Normal file
4
.vscode/extensions.json
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"recommendations": ["astro-build.astro-vscode"],
|
||||
"unwantedRecommendations": []
|
||||
}
|
||||
11
.vscode/launch.json
vendored
Normal file
11
.vscode/launch.json
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"command": "./node_modules/.bin/astro dev",
|
||||
"name": "Development server",
|
||||
"request": "launch",
|
||||
"type": "node-terminal"
|
||||
}
|
||||
]
|
||||
}
|
||||
131
README.md
Normal file
131
README.md
Normal file
@@ -0,0 +1,131 @@
|
||||
# Collective Governance for AI: Points of Intervention
|
||||
|
||||
A single-page, responsive, static website for a digital zine with interactive scroll effects. Built in Astro with Claude Code.
|
||||
|
||||
## Features
|
||||
|
||||
- **Markdown-based content**: Edit your zine content in `src/content/zine.md`
|
||||
- **Scroll animations**: Sections fade in as you scroll
|
||||
- **ASCII background patterns**: Each section has unique repeating ASCII symbols with gradient fades
|
||||
- **Interactive TOC sidebar**: Stack-style navigation with connecting lines to current section
|
||||
- **Mobile hamburger menu**: Touch-friendly navigation for small screens
|
||||
- **Responsive design**: Optimized for all screen sizes
|
||||
- **Zero JavaScript framework**: Uses vanilla JavaScript for interactions
|
||||
- **Black-and-white zine aesthetic**: Bold typography, rough edges, and texture overlay
|
||||
|
||||
## Prerequisites
|
||||
|
||||
Node.js >= 18.20.8 (or upgrade to Node.js 20+ for best compatibility)
|
||||
|
||||
## Getting Started
|
||||
|
||||
1. **Install dependencies**:
|
||||
```bash
|
||||
npm install
|
||||
```
|
||||
|
||||
2. **Start the development server**:
|
||||
```bash
|
||||
npm run dev
|
||||
```
|
||||
|
||||
3. **Build for production**:
|
||||
```bash
|
||||
npm run build
|
||||
```
|
||||
|
||||
4. **Preview production build**:
|
||||
```bash
|
||||
npm run preview
|
||||
```
|
||||
|
||||
## Project Structure
|
||||
|
||||
```
|
||||
├── src/
|
||||
│ ├── content/
|
||||
│ │ └── zine.md # Your zine content in Markdown
|
||||
│ └── pages/
|
||||
│ └── index.astro # Main page that renders the zine
|
||||
├── public/ # Static assets
|
||||
└── astro.config.mjs # Astro configuration
|
||||
```
|
||||
|
||||
## Editing Your Zine
|
||||
|
||||
1. Open `src/content/zine.md`
|
||||
2. Write your content using Markdown
|
||||
3. Use `## Heading` for section breaks (each becomes a full-height section)
|
||||
4. The dev server will hot-reload your changes
|
||||
|
||||
### Markdown Tips
|
||||
|
||||
- `# Main Title` - Top-level heading (animated)
|
||||
- `## Section Title` - Creates a new scrolling section
|
||||
- Regular Markdown formatting works: **bold**, *italic*, [links](url), etc.
|
||||
|
||||
## Customization
|
||||
|
||||
### Changing ASCII Patterns
|
||||
|
||||
Edit the CSS in `src/pages/index.astro` (lines 198-213) to change the ASCII symbols for each section:
|
||||
```css
|
||||
section:nth-child(2)::after { content: '◆ ◇ ◆ ◇ ...' }
|
||||
```
|
||||
|
||||
### Adjusting Colors
|
||||
|
||||
All styling is black-and-white by default. Edit the CSS variables:
|
||||
- Border color: `#000000` throughout
|
||||
- Background: `#ffffff`
|
||||
- Hover states: lines 91-95
|
||||
|
||||
### Adjusting Scroll Effects
|
||||
|
||||
Modify the JavaScript in `index.astro`:
|
||||
- Intersection threshold: Line 444 (currently 0.15 = 15% visibility)
|
||||
- Root margin: Line 445 (currently -10% = middle 80% of viewport)
|
||||
- Scroll behavior: Line 531 (`'smooth'` for animated scrolling)
|
||||
|
||||
### Adding More Interactive Elements
|
||||
|
||||
The page uses:
|
||||
- **Intersection Observer API** for scroll-based section visibility and TOC highlighting
|
||||
- **SVG line drawing** for connecting TOC to current section
|
||||
- **CSS animations** for fade-in effects
|
||||
- **Mobile menu toggle** with hamburger icon
|
||||
|
||||
You can extend the JavaScript in the `<script>` tag for additional interactivity.
|
||||
|
||||
## Deployment
|
||||
|
||||
1. **Build the site**:
|
||||
```bash
|
||||
npm run build
|
||||
```
|
||||
This creates a `dist/` folder with the optimized static site.
|
||||
|
||||
2. **Deploy the `dist/` folder** to your hosting provider:
|
||||
- **Netlify**: Drag and drop `dist/` to [netlify.com/drop](https://app.netlify.com/drop)
|
||||
- **GitHub Pages**: Push `dist/` contents to gh-pages branch
|
||||
- **Vercel**: Run `vercel` CLI in project root
|
||||
- **Any static host**: Upload `dist/` folder via FTP/SFTP
|
||||
|
||||
Note: Deploy the `dist/` folder, not `public/`. The `public/` folder contains source assets that get copied into the build.
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Node.js Version Error
|
||||
|
||||
If you see "Node.js version not supported", you have two options:
|
||||
|
||||
1. **Upgrade Node.js** (recommended):
|
||||
- Use [nvm](https://github.com/nvm-sh/nvm): `nvm install 20 && nvm use 20`
|
||||
- Or download from [nodejs.org](https://nodejs.org/)
|
||||
|
||||
2. **Use an older Astro version**:
|
||||
```bash
|
||||
npm install astro@4
|
||||
```
|
||||
|
||||
## License: MIT
|
||||
5
astro.config.mjs
Normal file
5
astro.config.mjs
Normal file
@@ -0,0 +1,5 @@
|
||||
// @ts-check
|
||||
import { defineConfig } from 'astro/config';
|
||||
|
||||
// https://astro.build/config
|
||||
export default defineConfig({});
|
||||
6315
package-lock.json
generated
Normal file
6315
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
15
package.json
Normal file
15
package.json
Normal file
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"name": "dark-debris",
|
||||
"type": "module",
|
||||
"version": "0.0.1",
|
||||
"scripts": {
|
||||
"dev": "astro dev",
|
||||
"build": "astro build",
|
||||
"preview": "astro preview",
|
||||
"astro": "astro"
|
||||
},
|
||||
"dependencies": {
|
||||
"astro": "^4.5.18",
|
||||
"marked": "^9.1.6"
|
||||
}
|
||||
}
|
||||
9
public/favicon.svg
Normal file
9
public/favicon.svg
Normal file
@@ -0,0 +1,9 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 128 128">
|
||||
<path d="M50.4 78.5a75.1 75.1 0 0 0-28.5 6.9l24.2-65.7c.7-2 1.9-3.2 3.4-3.2h29c1.5 0 2.7 1.2 3.4 3.2l24.2 65.7s-11.6-7-28.5-7L67 45.5c-.4-1.7-1.6-2.8-2.9-2.8-1.3 0-2.5 1.1-2.9 2.7L50.4 78.5Zm-1.1 28.2Zm-4.2-20.2c-2 6.6-.6 15.8 4.2 20.2a17.5 17.5 0 0 1 .2-.7 5.5 5.5 0 0 1 5.7-4.5c2.8.1 4.3 1.5 4.7 4.7.2 1.1.2 2.3.2 3.5v.4c0 2.7.7 5.2 2.2 7.4a13 13 0 0 0 5.7 4.9v-.3l-.2-.3c-1.8-5.6-.5-9.5 4.4-12.8l1.5-1a73 73 0 0 0 3.2-2.2 16 16 0 0 0 6.8-11.4c.3-2 .1-4-.6-6l-.8.6-1.6 1a37 37 0 0 1-22.4 2.7c-5-.7-9.7-2-13.2-6.2Z" />
|
||||
<style>
|
||||
path { fill: #000; }
|
||||
@media (prefers-color-scheme: dark) {
|
||||
path { fill: #FFF; }
|
||||
}
|
||||
</style>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 749 B |
BIN
public/metagov.png
Normal file
BIN
public/metagov.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 94 KiB |
151
src/content/zine.md
Normal file
151
src/content/zine.md
Normal file
@@ -0,0 +1,151 @@
|
||||
# Collective Governance for AI: Points of Intervention
|
||||
|
||||
Made for  by [Metagov](https://metagov.org)
|
||||
|
||||
## Invitation
|
||||
|
||||
People often speak about AI as if it is one thing. It can seem like that when we use today’s most popular interfaces: a single product, packaged by an unfathomably big company. But that view is both misleading and disempowering. It implies that only the big companies could possibly create and control this technology, because only they can manage the complexity. But another orientation is possible.
|
||||
|
||||
When presented with a hard math problem, often the best way to tackle it is to break it up into smaller, easier problems. As we understand AI systems in more social and technical detail, similarly, we can recognize them as involving a sequence of smaller operations, and those can start to seem more approachable for community-scale governance. Feasible interventions start to seem possible. We can think beyond how the post-2022 AI corporate “labs” want us to think about what AI is or could be. We don’t need to be a trillion-dollar tech company to make a dent in shaping this technology through our communities’ needs and knowledge. We can remember the long history of developing and using AI techniques—in ways less visible than the current consumer products—to the future where we can more easily disentangle and co-govern these toolsets.
|
||||
|
||||
This is a collective document meant to do two things. First, it identifies distinct layers of the AI stack that can be isolated and reimagined. Second, for each layer, it points to both potential strategies and existing projects that could steer that layer toward meaningful collective governance.
|
||||
|
||||
We understand collective governance as an emergent and context-sensitive practice that makes structures of power accountable to those affected by them. It can take many forms—sometimes highly participatory, and sometimes more removed. It might mean voting on members of a board, proposing a policy, submitting a code improvement, organizing a union, or many other things. Governance is usually referred to as something that humans do, but we (and AI systems) are part of broader ecosystems that might be part of governance processes as well. In that sense, maybe a drought caused by AI-accelerated climate change is an input to governance.
|
||||
|
||||
The idea of “points of intervention” here comes from the systems thinker Donella Meadows—especially her essay “[Leverage Points: Places to Intervene in a System](https://donellameadows.org/archives/leverage-points-places-to-intervene-in-a-system/).” One idea that she stresses there is the power of feedback loops, which is when change in one part of a system produces change in another, and that in turn creates further change in the first, and so on. Collective governance is a way of introducing powerful feedback loops that draw on diverse knowledge and experience.
|
||||
|
||||
We recognize that not everyone is comfortable referring to these technologies as “intelligence.” We use the term “AI” most of all because it is now familiar to most people, as a shorthand for the models based on large datasets that are currently widely available through interfaces designed for mass user adoption. But a fundamental premise of ours is that the advent of this technology should enable, inspire, and augment human intelligence, not replace it—and the best way to ensure that is to cultivate spaces of creative, collective governance.
|
||||
|
||||
These points of intervention do not focus on asserting ethical best practices for AI, or on defining what AI should look like or how it should work. We hope that, in the struggle to cultivate self-governance in our relationships with technology, our collective goals will evolve and sharpen in ways that we cannot now anticipate.
|
||||
|
||||
## Model design
|
||||
|
||||
How are foundational models designed, and who does the designing? What institutions regulate the designers?
|
||||
|
||||
* Organize [worker governance and ownership of AI labs](https://www.cip.org/blog/shared-code) could help ensure that ethical considerations take precedence over profit motives
|
||||
* Develop [smaller, purpose-specific](https://dl.acm.org/doi/10.1145/3442188.3445922) models that involve less costly and environmentally destructive training, and can be [less error-prone](https://research.nvidia.com/labs/lpr/slm-agents/); ensure models are fit for purpose, with large-data models used only when probabilistic outputs are required
|
||||
* Design models through institutions oriented around the common good, such as democratic governments and nonprofit organizations, such as the Swiss [Apertus model](https://ethz.ch/en/news-and-events/eth-news/news/2025/09/press-release-apertus-a-fully-open-transparent-multilingual-language-model.html)
|
||||
* Train developers to understand and be aware of their worldviews, and to engage in collective governance practices with affected communities rooted in [design justice](https://designjustice.org/principles-overview)
|
||||
|
||||
## Data
|
||||
|
||||
What data is used to train models? Where does it come from? What permission and reciprocity is involved?
|
||||
|
||||
* Ensure that all training data is transparent and retrievable, such as the [Apertus](https://ethz.ch/en/news-and-events/eth-news/news/2025/09/press-release-apertus-a-fully-open-transparent-multilingual-language-model.html) and [Pythia](https://www.eleuther.ai/artifacts/pythia) models, as well as standards such as the [OSI Open Source AI Definition](https://opensource.org/ai)
|
||||
* Establish and rely on [data cooperatives](https://www.projectliberty.io/news/data-coops-as-alternative-to-centralized-digital-economy/), [data collaboratives](https://doi.org/10.1007/s12525-025-00831-6), and [data trusts](https://theodi.org/insights/explainers/what-is-a-data-trust/) to provide ethical, consensual data sourcing and compensate data providers, such as [Transfer Data Trust](http://youtube.com/watch?v=QLIW_TfVR4k) and [Choral Data Trust](http://youtube.com/watch?v=SO_IcQvjMDU&feature=youtu.be)
|
||||
* Adopt a clear, accessible, and usable [data policy](https://metagov.pubpub.org/pub/data-policy/) in any organizational context
|
||||
* Reflect best practices of community accountability from the [Indigenous Data Alliance](https://indigenousdata.org/) and the [Collaboratory for Indigenous Data Governance](https://indigenousdatalab.org/)
|
||||
* Leverage existing data under cooperative control, as in cases such as [agricultural co-ops](https://www.fertilizerdaily.com/20241112-how-land-olakes-is-using-ai-to-revolutionize-farming-practices/) and [credit unions](https://creditunions.com/features/perspectives/is-your-credit-union-part-of-the-ai-revolution/)
|
||||
* Require robust [data provenance](https://hypha.coop/data-provenance/) and [traceability](https://www.researchgate.net/publication/395416141_Using_Blockchain_to_Trace_Data_Sources_in_AI) techniques, with robust anonymization, to enable auditing and oversight
|
||||
* Use datasets that reflect demonstrable cultural diversity to allow diverse forms of interaction and participation; disclose limitations where this is not possible
|
||||
|
||||
## Training
|
||||
|
||||
How are foundational models trained? What infrastructures and natural resources do they rely on?
|
||||
|
||||
* Organize training processes through accountability-oriented institutions such as [democratic governments or nonprofit consortia](https://metagov.org/projects/public-ai)
|
||||
* Provide robust benefit-sharing arrangements for communities that host data centers
|
||||
* Participatory taxonomy development and data labeling and annotation processes that help ensure models are better reflective of community norms, language, and values, such as [Reliabl.ai](http://Reliabl.ai)
|
||||
* Ensure that data annotation workers can build collective power through unions and collectives, such as through NGOs like [Techworker Community Africa](https://www.techworkercommunityafrica.com/) and [She Codes Africa](https://shecodeafrica.org/), which can help negotiate rates and provide legal support
|
||||
* Monitor and evaluate labor practices within the supply chain, following the example of [Fairwork](https://fair.work/en/fw/about/)
|
||||
* Utilize community-governed standards like [participatory guarantee systems](https://en.wikipedia.org/wiki/Participatory_Guarantee_Systems) so that communities that host data centers or data labor can set locally appropriate standards
|
||||
|
||||
## Tuning
|
||||
|
||||
What fine-tuning do models receive before deployment? What collective intervention is involved?
|
||||
|
||||
* Utilize collective intelligence processes such as [alignment assemblies](https://www.cip.org/alignmentassemblies) to set standards for AI behavior and define system prompts, resulting in [community models](https://blog.cip.org/p/community-models)
|
||||
* Implement co-design practices that include alignment workers fully in the process of ethical oversight, rather than the [dehumanizing roles](https://www.bloomsbury.com/us/feeding-the-machine-9781639734979/) they are often expected to assume
|
||||
* Design tuning processes around an [ethics of care](https://iep.utm.edu/care-ethics/), ensuring that all workers in the process experience respect and dignity in their work
|
||||
* Identify and promote [evaluation processes](https://weval.org) that improve safety and alignment over time
|
||||
* Create [bias bounty](https://humane-intelligence.org/programs-services/bias-bounty/) programs that encourage users to identify and report evidence of bias in model behavior
|
||||
|
||||
## Context
|
||||
|
||||
How do AIs obtain contextual information? What kinds of actions are agents able to carry out?
|
||||
|
||||
* Enable privacy-sensitive tools for connecting local models with community data, such as [RooLLM](https://github.com/hyphacoop/RooLLM) and [KOI Pond](https://metagov.org/projects/koi-pond)
|
||||
* Utilize cooperative worker ownership, like [READ-COOP](https://open-research-europe.ec.europa.eu/articles/5-16/v1), for human-in-the-loop, AI-assisted activities
|
||||
* Manage and protect contextual data through user-owned cooperatives, like [Land O’Lakes’s Oz platform](https://www.fastcompany.com/91438757/the-wizard-of-crops-microsofts-oz-aims-to-transform-farming)
|
||||
* Adopt open standards, like [Model Context Protocol,](https://modelcontextprotocol.io/docs/getting-started/intro) that enable context-holders to define more accurate, appropriate, and ethically sourced data-use policies
|
||||
* Utilize community-governed and transparently curated infrastructure, such as [Stract optics](https://github.com/c-host/mg-stract-optics-library-and-search-engine), for agent web searches
|
||||
* Establish clear, privacy-respecting, and consent-based norms for model access to user data, such as through the [Human Context Protocol](https://humancontextprotocol.com/) or [data pods](https://www.secoda.co/glossary/what-are-data-pods)
|
||||
|
||||
## Hosting
|
||||
|
||||
Where are AIs running while they are interacting with users? How do they treat user data?
|
||||
|
||||
* Deploy AI systems at data centers powered by renewable energy, such as [GreenPT](https://greenpt.ai/) and [Earth Friendly Computation](https://earthfriendlycomputation.com/), and that respect local ecosystems
|
||||
* Host AI services on cooperatively owned and governed servers, such as [Cosy AI](https://cosyai.net/), especially with ownership by local communities
|
||||
* Run local models on personal or community computers with tools like [Ollama](https://ollama.com/) and [Jan](https://www.jan.ai/)
|
||||
* Use decentralized or federated solutions for hosting like [Golem](https://www.golem.network/) or [Internet Computer](https://internetcomputer.org/)
|
||||
|
||||
## User experience
|
||||
|
||||
What kinds of interfaces and expectations are users presented with? What options do users have? How do interfaces nudge user behavior?
|
||||
|
||||
* Ensure [worker control](https://www.microsoft.com/insidetrack/blog/deploying-microsoft-places-at-microsoft-with-our-works-councils/) over the deployment of AI systems in their workplaces
|
||||
* Provide for user choice around the worldviews and model moderation practices, such as locally deployed [open-weights models allow](https://opensource.org/ai/open-weights)
|
||||
* Establish sectoral agreements over AI use, as in the outcome of the [2023–2024 Hollywood strike](https://cdt.org/insights/the-sag-aftra-strike-is-over-but-the-ai-fight-in-hollywood-is-just-beginning/)
|
||||
* Create interfaces that enable user choice among different models, such as [Duck.ai](https://duck.ai/)
|
||||
* Provide privacy-protecting mechanisms, including user-[data mixers](https://duckduckgo.com/duckai/privacy-terms) and [data-protection compliance](https://greenpt.ai/privacy/)
|
||||
* Expect user interfaces and models to respect local law and global treaties by design
|
||||
|
||||
## Public policy
|
||||
|
||||
How does public policy shape the design, development, and deployment of AI systems?
|
||||
|
||||
* Demand high standards for procurement of foundational model providers, ensuring that both the providers and the models are audited according to best practices of human rights and sustainability
|
||||
* Develop policy with [AI-augmented citizen assemblies](https://www.demnext.org/projects/five-dimensions-of-scaling-democratic-deliberation-with-and-beyond-ai) that lay out clear guidelines in highly sensitive contexts, such as education, healthcare, law enforcement, and public benefits
|
||||
* Convene public debates about limits on AI resource usage without positive social purpose
|
||||
* Hold AI companies responsible for the behavior of models that they monopolistically control, such as through lawsuits and legislative advocacy
|
||||
|
||||
## Culture
|
||||
|
||||
What cultural norms form around expectations for AI providers and users? How do these norms shape behavior?
|
||||
|
||||
* Promote clear statements of shared values like the [DWeb Principles](https://getdweb.net/principles/)
|
||||
* Establish clear, context-sensitive agreements on AI use at sites such as classrooms, workplaces, and communities
|
||||
* Cultivate awareness of the risks around addictive design, surveillance, and user profiling from personal use of corporate AI platforms that are not collectively governed
|
||||
* Encourage practices of collaboration, creative thinking, and disconnection that resist dependency on corporate AI
|
||||
|
||||
## Economics
|
||||
|
||||
How is the development and maintenance of AI funded, and who benefits economically from its use? What models ensure that value flows back to communities rather than being extracted from them?
|
||||
|
||||
* Ensure that workforce-displacing AI adoption accompanies universal benefits that provide more time for self-governance, like [shorter working hours](https://www.axios.com/2025/06/29/ai-productivity-four-day-work-week) and [guaranteed income](https://blogs.lse.ac.uk/businessreview/2025/04/29/universal-basic-income-as-a-new-social-contract-for-the-age-of-ai-1/)
|
||||
* Organize cooperative funding pools to invest in community-owned computing power and shared model development
|
||||
* Invest democratically controlled public funds in AI for public benefit
|
||||
* Promote revenue-sharing frameworks for self-governing communities who contribute data, such as [royalty frameworks](https://arxiv.org/abs/2406.11857) or [data unions](https://www.radicalxchange.org/wiki/data-dignity/)
|
||||
|
||||
## Ecosystems
|
||||
|
||||
How do different community-governed AI systems connect, share information, and make decisions together? What standards or protocols enable collective governance across networks and jurisdictions? How do AI systems relate to their local and planetary environments?
|
||||
|
||||
* Establish more traceable, collectively governed data repositories that can be used across models and contexts, like [ImageNet](https://image-net.org/) and [Dataverse](https://dataverse.org/)
|
||||
* Share audit logs across networks with standard tools like [Petri](https://www.anthropic.com/research/petri-open-source-auditing)
|
||||
* [Map](https://www.fractracker.org/2025/07/national-data-centers-tracker/) and [document](https://datasociety.net/points/digital-infrastructures-material-consequences/) the impacts of data centers on communities and ecology
|
||||
* Develop cross-border [standards](https://www.sandia.gov/app/uploads/sites/148/2025/04/Challenges-and-Opportunities-for-US-China-Collaboration-on-Artificial-Intelligence-Governance.pdf) and [collaborations](https://www.nature.com/articles/s41598-024-79863-5) among stakeholders that challenge the international arms-race mentality through co-governance
|
||||
|
||||
## Feedback loops
|
||||
|
||||
Finally, what feedback loops can we imagine across these layers of the stack? How could change in one area lead to greater change through its effects at other layers?
|
||||
|
||||
* Constraints introduced through collective power at the level of deployment can then put pressure on changing norms in training and tuning processes
|
||||
* Successful training of narrower, more efficient models can enable AI systems that are less costly and easier for communities to own and govern
|
||||
* Economies more conducive to investment for collective ownership can open the door to collective governance at multiple levels
|
||||
* Interconnected ecosystems through open standards and shared norms can spread best practices developed in one policy context to others
|
||||
|
||||
Feedback loops can be messy. Remember that collective governance demands working with care and consideration for others. Let’s keep that in mind as we define our AI interventions and adaptations.
|
||||
|
||||
## Now, time to intervene!
|
||||
|
||||
## Credits
|
||||
|
||||
Initiated and edited by Nathan Schneider, with contributions from Cormac Callanan, Coraline Ada Ehmke, Val Elefante, Cent Hosten, Joseph Low, Thomas Renkert, Julija Rukanskaitė, Ann Stapleton, Madisen Taylor, Freyja van den Boom, Jojo Vargas, Mohsin Y. K. Yousufi, and Michael Zargham.
|
||||
|
||||
Built by the Media Economies Design Lab with open-source software and AI collaboration.
|
||||
|
||||
Made for  by [Metagov](https://metagov.org)
|
||||
|
||||
November 2025
|
||||
2
src/env.d.ts
vendored
Normal file
2
src/env.d.ts
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
/// <reference path="../.astro/types.d.ts" />
|
||||
/// <reference types="astro/client" />
|
||||
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>
|
||||
5
tsconfig.json
Normal file
5
tsconfig.json
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"extends": "astro/tsconfigs/strict",
|
||||
"include": [".astro/types.d.ts", "**/*"],
|
||||
"exclude": ["dist"]
|
||||
}
|
||||
Reference in New Issue
Block a user