Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view

Large diffs are not rendered by default.

70 changes: 70 additions & 0 deletions site/src/components/blog/GrowthVsLeverage.astro
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
---
// The structural heart of post #5 (exploration 0245): two ways to get rich from
// the same economy. GROWTH makes a bigger pie and takes a slice — so more people,
// more makers, more customers is good for you. LEVERAGE controls a chokepoint and
// drains a fixed pie — so an empowered population is friction, and manufactured
// scarcity is the product. The inversion (people as asset → people as obstacle)
// is what makes the rest of the essay cohere. Mirrors the HydrostaticBalance /
// HonestStar card idiom (not-prose, bordered surface) so the posts read as one
// publication.
const modes = [
{
name: 'Growth',
sub: 'Make a bigger pie, take a slice',
behaviour:
'Value comes from building something more people want. More makers and more customers grow the pie, so a larger, freer, better-paid population is good for you. Your win and theirs point the same way.',
tone: 'good'
},
{
name: 'Leverage',
sub: 'Control a chokepoint, drain a fixed pie',
behaviour:
'Value comes from owning a thing everyone must pass through — housing, a platform, a feed — and from manufactured scarcity, debt, and rent. Here a population that can say no is friction. The prize stops being your money and becomes your compliance.',
tone: 'bad'
}
]
---

<section class="not-prose my-12">
<div class="rounded-2xl border border-border bg-surface/30 p-6 dark:bg-surface/40 lg:p-8">
<h3 class="text-xl font-bold tracking-tight text-gray-900 dark:text-white">
Two ways to get rich from the same economy
</h3>
<p class="mt-2 text-sm text-gray-500 dark:text-gray-400">
One needs you healthy and free. The other needs you stuck. They are
pulling in opposite directions.
</p>

<ul class="mt-6 space-y-5">
{
modes.map((m) => (
<li class="grid gap-2 sm:grid-cols-[1fr_1.6fr] sm:gap-6 sm:items-baseline">
<div>
<p
class:list={[
'font-mono font-semibold',
m.tone === 'good'
? 'text-rose-600 dark:text-rose-400'
: 'text-gray-500 dark:text-gray-400'
]}
>
{m.name}
</p>
<p class="mt-0.5 text-sm text-gray-500 dark:text-gray-400">{m.sub}</p>
</div>
<p class="text-sm leading-relaxed text-gray-700 dark:text-gray-200">{m.behaviour}</p>
</li>
))
}
</ul>

<p class="mt-6 border-t border-border pt-4 text-sm leading-relaxed text-gray-600 dark:text-gray-300">
<span class="font-semibold text-gray-900 dark:text-white">The tell</span>
is the inversion: under growth, more empowered people is the
<span class="text-rose-600 dark:text-rose-400">asset</span>; under leverage,
it becomes the <span class="text-gray-500 dark:text-gray-400">obstacle</span>.
Once you see which one you're inside, a lot of confusing news stops being
confusing.
</p>
</div>
</section>
53 changes: 53 additions & 0 deletions site/src/components/blog/HonestExit.astro
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
---
// The honesty beat (exploration 0245), modeled on HonestStar / HonestMycelium /
// HonestPirate. A privacy-first project writing about an extraction economy has
// to be loud about its own limits, or it's just selling another cure-all. So we
// say plainly what owning your data does and doesn't touch — it is one front, not
// the war.
const rows = [
{
isnt: 'We won’t pretend software fixes your rent.',
is: 'Local-first tools do nothing about housing, wages, your grocery bill, or your retirement account. This is one chokepoint — the one over your information and tools — not the whole machine.'
},
{
isnt: 'We won’t pretend leaving is free in real life.',
is: 'Switching costs are real: your friends are where they are, your files are in formats you didn’t choose. We can only make the part we control cheap to leave — your data exports whole, your identity is yours to carry. The rest is still work.'
},
{
isnt: 'We won’t claim to be un-buyable because we’re nice.',
is: 'Good intentions get acquired. The defence has to be structural: an open protocol anyone can re-implement from its test vectors, an MIT core that can’t be clawed back, and a build that fails if someone smuggles in a tracker. Check the receipts, not the vibes.'
},
{
isnt: 'We won’t tell you to log off and call it freedom.',
is: 'The point isn’t austerity — it’s leverage of your own. A tool you can pick up, use offline, and put down without it punishing you gives back the one asset the extraction economy is really after: your time, and your ability to refuse.'
}
]
---

<section class="not-prose my-12">
<div class="rounded-2xl border border-border bg-surface/30 p-6 dark:bg-surface/40 lg:p-8">
<h3 class="text-xl font-bold tracking-tight text-gray-900 dark:text-white">
An honest exit
</h3>
<p class="mt-2 text-sm text-gray-500 dark:text-gray-400">
A fix that oversells itself is just more marketing. Here’s the honest scope.
</p>

<ul class="mt-6 space-y-5">
{
rows.map((row) => (
<li class="grid gap-3 sm:grid-cols-[1fr_1.3fr] sm:gap-5">
<div class="flex gap-2.5">
<span class="select-none text-gray-400 dark:text-gray-600">✕</span>
<p class="text-sm leading-relaxed text-gray-500 dark:text-gray-400">{row.isnt}</p>
</div>
<div class="flex gap-2.5">
<span class="select-none text-rose-500">✓</span>
<p class="text-sm leading-relaxed text-gray-700 dark:text-gray-200">{row.is}</p>
</div>
</li>
))
}
</ul>
</div>
</section>
136 changes: 136 additions & 0 deletions site/src/components/blog/LeverHero.astro
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
---
// Original art for blog post #5 (exploration 0245). The fourth vantage of the
// series: PirateHero looked UP at a sea of islands, MycelialHero looked DOWN
// into the soil, StarHero looked UP AND OUT at a star — and LeverHero looks at
// the machine underneath the money. A lever: a small force on a long arm
// (the cosmic-X, glowing rose) pivots on a fulcrum and lifts a mass many times
// its weight on the short arm. That is "asymmetrical leverage" drawn literally —
// the move at the heart of the essay. All inline SVG, no external assets, so the
// page ships nothing third-party (Self-Audit parity with posts #1–#3).
interface Props {
title: string
deck: string
date: string
readingMinutes: number
tags: string[]
}
const { title, deck, date, readingMinutes, tags } = Astro.props

// Fulcrum apex and the beam it pivots. The beam is tilted: the long left arm is
// pressed down by a small force, so the short right arm — carrying the heavy
// mass — is levered up. Pivot lies on the beam at x = apexX.
const apexX = 545
const apexY = 176
const beam = { x1: 250, y1: 206, x2: 770, y2: 150 }
// Point on the beam directly above the fulcrum (so the apex touches the beam).
const t = (apexX - beam.x1) / (beam.x2 - beam.x1)
const pivotY = beam.y1 + t * (beam.y2 - beam.y1)

// The cosmic-X rides the long arm as the small force; the mass sits on the short
// arm. Endpoints of the beam (the X end and the mass end).
const forceX = beam.x1 + 24
const forceY = beam.y1 - 4
const massX = beam.x2 - 30
const massY = beam.y2 - 4
---

<section class="relative overflow-hidden border-b border-border bg-surface/20 dark:bg-[#0a0608]">
<svg
class="pointer-events-none absolute inset-0 h-full w-full"
viewBox="0 0 1040 340"
preserveAspectRatio="xMidYMid slice"
aria-hidden="true"
>
<defs>
<linearGradient id="leverbg" x1="0" y1="0" x2="0" y2="1">
<stop offset="0%" stop-color="#120a0e" />
<stop offset="55%" stop-color="#150b11" />
<stop offset="100%" stop-color="#0c0609" />
</linearGradient>
<radialGradient id="forceglow" cx="50%" cy="50%" r="50%">
<stop offset="0%" stop-color="#fb7185" stop-opacity="0.95" />
<stop offset="45%" stop-color="#f43f5e" stop-opacity="0.4" />
<stop offset="100%" stop-color="#f43f5e" stop-opacity="0" />
</radialGradient>
<linearGradient id="forcex" x1="0" y1="0" x2="1" y2="1">
<stop offset="0%" stop-color="#fecdd3" />
<stop offset="100%" stop-color="#fb7185" />
</linearGradient>
<marker id="up" viewBox="0 0 10 10" refX="5" refY="2" markerWidth="6" markerHeight="6" orient="auto">
<path d="M5 0 L10 8 L0 8 z" fill="#fb7185" opacity="0.9" />
</marker>
<marker id="down" viewBox="0 0 10 10" refX="5" refY="8" markerWidth="6" markerHeight="6" orient="auto">
<path d="M0 2 L10 2 L5 10 z" fill="#94a3b8" opacity="0.85" />
</marker>
</defs>

<rect width="1040" height="340" fill="url(#leverbg)" />

<!-- faint grid of "the market": ledger lines the lever quietly works against -->
<g stroke="#3b2a32" stroke-width="1" opacity="0.4">
<line x1="0" y1="250" x2="1040" y2="250" />
<line x1="0" y1="284" x2="1040" y2="284" />
<line x1="0" y1="318" x2="1040" y2="318" />
</g>

<!-- the mass on the short arm: heavy, lifted -->
<g transform={`translate(${massX} ${massY})`}>
<rect x="-34" y="-58" width="68" height="58" rx="6" fill="#1f2937" stroke="#475569" stroke-width="1.5" />
<rect x="-34" y="-58" width="68" height="14" rx="6" fill="#334155" opacity="0.7" />
<!-- being levered upward -->
<line x1="0" y1="14" x2="0" y2="40" stroke="#94a3b8" stroke-width="1.6" marker-end="url(#down)" transform="rotate(180)" />
</g>

<!-- the beam -->
<line
x1={beam.x1}
y1={beam.y1}
x2={beam.x2}
y2={beam.y2}
stroke="#cbd5e1"
stroke-width="5"
stroke-linecap="round"
opacity="0.85"
/>

<!-- the fulcrum: a triangle whose apex touches the beam -->
<path
d={`M ${apexX} ${pivotY} L ${apexX - 30} ${pivotY + 46} L ${apexX + 30} ${pivotY + 46} Z`}
fill="#3f2a33"
stroke="#fb7185"
stroke-width="1.5"
opacity="0.9"
/>

<!-- small downward force on the long arm (the lever's "tiny" input) -->
<line x1={forceX + 60} y1={forceY - 46} x2={forceX + 60} y2={forceY - 14} stroke="#fb7185" stroke-width="1.6" marker-end="url(#up)" transform={`rotate(180 ${forceX + 60} ${forceY - 30})`} />

<!-- the cosmic-X as the small force, glowing rose at the end of the long arm -->
<g transform={`translate(${forceX} ${forceY})`}>
<circle cx="0" cy="0" r="34" fill="url(#forceglow)" />
<g stroke="url(#forcex)" stroke-width="5" stroke-linecap="round" transform="translate(-9 -10)">
<line x1="0" y1="0" x2="18" y2="20" />
<line x1="18" y1="0" x2="0" y2="20" />
</g>
</g>
</svg>

<div class="relative mx-auto max-w-3xl px-6 pb-14 pt-44 lg:pt-52">
<div class="flex flex-wrap items-center gap-x-3 gap-y-1 text-xs text-rose-200/80">
<time datetime={date}>{date}</time>
<span aria-hidden="true">·</span>
<span>{readingMinutes} min read</span>
{
tags.map((tag) => (
<span class="rounded-full border border-rose-400/30 bg-rose-500/10 px-2 py-0.5 font-mono lowercase text-rose-200">
{tag}
</span>
))
}
</div>
<h1 class="mt-4 text-4xl font-bold tracking-tight text-white drop-shadow lg:text-5xl">
{title}
</h1>
<p class="mt-4 max-w-2xl text-lg leading-relaxed text-gray-300">{deck}</p>
</div>
</section>
90 changes: 90 additions & 0 deletions site/src/components/blog/WatchTheOriginal.astro
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
---
// The video card for post #5 (exploration 0245). The essay is a response to a
// specific video, and the video is worth watching in full — so we point at it
// prominently. But embedding YouTube's player would load a third-party tracker
// onto a page in a series that brags about shipping nothing third-party (see
// StarHero / SelfAudit). So this is a *facade*: our own inline-SVG poster that
// links out to the original. Nothing leaves your browser until you click — which
// is, conveniently, the whole point of the essay it sits inside.
interface Props {
href: string
title: string
author: string
length: string
}
const { href, title, author, length } = Astro.props
---

<aside class="not-prose my-12">
<a
href={href}
target="_blank"
rel="noopener noreferrer"
class="group block overflow-hidden rounded-2xl border border-border bg-surface/30 transition-all hover:border-rose-500/40 hover:bg-surface/50 dark:bg-surface/40"
>
<!-- poster: original art, no YouTube thumbnail (which would phone home) -->
<div class="relative aspect-[16/7] w-full overflow-hidden bg-[#0c0609]">
<svg
class="absolute inset-0 h-full w-full"
viewBox="0 0 1040 455"
preserveAspectRatio="xMidYMid slice"
aria-hidden="true"
>
<defs>
<linearGradient id="vbg" x1="0" y1="0" x2="0" y2="1">
<stop offset="0%" stop-color="#150b11" />
<stop offset="100%" stop-color="#0a0608" />
</linearGradient>
<radialGradient id="vglow" cx="50%" cy="50%" r="50%">
<stop offset="0%" stop-color="#fb7185" stop-opacity="0.5" />
<stop offset="60%" stop-color="#f43f5e" stop-opacity="0.12" />
<stop offset="100%" stop-color="#f43f5e" stop-opacity="0" />
</radialGradient>
</defs>
<rect width="1040" height="455" fill="url(#vbg)" />
<!-- a rising line chart that the play button sits on: "the richest country" -->
<polyline
points="0,360 130,348 260,352 390,300 520,312 650,236 780,250 910,150 1040,96"
fill="none"
stroke="#3f2a33"
stroke-width="2.5"
opacity="0.8"
/>
<circle cx="520" cy="228" r="150" fill="url(#vglow)" />
<!-- play triangle with the cosmic-X notched into it -->
<g transform="translate(520 228)">
<circle cx="0" cy="0" r="52" fill="#0c0609" stroke="#fb7185" stroke-width="2" opacity="0.95" />
<path d="M -16 -24 L 26 0 L -16 24 Z" fill="#fb7185" />
</g>
</svg>
<span
class="absolute bottom-3 right-3 rounded bg-black/55 px-2 py-1 font-mono text-xs text-rose-100 backdrop-blur-sm"
>
{length}
</span>
</div>

<div class="flex items-center justify-between gap-4 px-5 py-4 sm:px-6">
<div class="min-w-0">
<p class="text-xs font-medium uppercase tracking-wide text-rose-500 dark:text-rose-400">
Watch the original
</p>
<p class="mt-1 truncate font-semibold text-gray-900 dark:text-white">{title}</p>
<p class="text-sm text-gray-500 dark:text-gray-400">{author}</p>
</div>
<span
class="inline-flex shrink-0 items-center gap-1.5 rounded-lg border border-rose-500/30 bg-rose-500/10 px-3 py-2 text-sm font-medium text-rose-600 transition-colors group-hover:bg-rose-500/20 dark:text-rose-300"
>
YouTube
<svg class="h-4 w-4" fill="none" stroke="currentColor" viewBox="0 0 24 24" stroke-width="2" aria-hidden="true">
<path stroke-linecap="round" stroke-linejoin="round" d="M13.5 6H5.25A2.25 2.25 0 0 0 3 8.25v10.5A2.25 2.25 0 0 0 5.25 21h10.5A2.25 2.25 0 0 0 18 18.75V10.5m-10.5 6L21 3m0 0h-5.25M21 3v5.25" />
</svg>
</span>
</div>
</a>
<p class="mt-2 px-1 text-xs text-gray-400 dark:text-gray-500">
We link out instead of embedding a player, so this page still loads nothing
from YouTube until you choose to go there. That restraint is the essay in
miniature.
</p>
</aside>
11 changes: 11 additions & 0 deletions site/src/data/blog.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ export type BlogTag =
| 'protocol'
| 'nature'
| 'cosmos'
| 'economics'

export interface BlogPost {
/** URL slug; matches `site/src/pages/blog/<slug>.astro`. */
Expand Down Expand Up @@ -60,6 +61,16 @@ export const posts: BlogPost[] = [
tags: ['essay', 'philosophy', 'nature'],
readingMinutes: 13
},
{
slug: 'the-right-to-say-no',
title: 'The Right to Say No',
description:
"A musician on YouTube argues the economy quietly changed from growth to extraction, and the real prize isn't your money — it's your ability to refuse. He's mostly right. Here's the part software can actually give back.",
pubDate: '2026-06-28T19:30:00Z',
author: 'xNet',
tags: ['essay', 'philosophy', 'economics'],
readingMinutes: 13
},
{
slug: 'the-gentlest-furnace',
title: 'The Gentlest Furnace',
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"id": "2026-06-28-new-essay-the-right-to-say-no",
"date": "June 28, 2026",
"title": "New essay: The Right to Say No",
"summary": "Our fifth blog essay is live — a response to Benn Jordan's 'The Richest Country Is Pretty Mid Now' on how the economy shifted from growth to extraction, and the part local-first software can give back: the right to leave. Read it at /blog/the-right-to-say-no.",
"highlights": [],
"tags": [
"platform"
]
}
Loading
Loading