Compare commits

..

No commits in common. "9f71d346e9a4c9daaaeead732f6d1c2f2b4e3690" and "5cdbb76ab7f2f9a410ddf09f18e0c6613263a749" have entirely different histories.

13 changed files with 46 additions and 32 deletions

View file

@ -6,9 +6,9 @@
* Unseen, always working, connects every entity (the mycelium). * Unseen, always working, connects every entity (the mycelium).
* Flowers → the three experiences people actually engage with: * Flowers → the three experiences people actually engage with:
* • SolLunar Punk Society (city center) — a permanent bloom * • SolLunar Punk Society (city center) — a permanent bloom
* • Pop-up Summit Gatherings (travelling) — ephemeral cluster * • Pop-up Festivals (travelling) — ephemeral cluster
* • Château du Faune (farm center) — a permanent bloom * • Château du Faune (farm center) — a permanent bloom
* Ghost flowers→ once the mycelium runs, new locations & summit gatherings sprout * Ghost flowers→ once the mycelium runs, new locations & festivals sprout
* cheaply, anywhere in the world. * cheaply, anywhere in the world.
* *
* Pure SVG + CSS so it scales crisply on a projector and respects * Pure SVG + CSS so it scales crisply on a projector and respects
@ -290,7 +290,7 @@ const festivalCaps = [
<span class="mt-0.5 text-amber"><Icon name="Sparkles" class="size-5" /></span> <span class="mt-0.5 text-amber"><Icon name="Sparkles" class="size-5" /></span>
<p class="text-fg-muted"> <p class="text-fg-muted">
<span class="font-medium text-fg">Take root anywhere.</span> <span class="font-medium text-fg">Take root anywhere.</span>
Plug into a rich substrate of decentralized tech and grow your own flower — a city hub, a travelling summit gathering, a farm. Plug into a rich substrate of decentralized tech and grow your own flower — a city hub, a travelling festival, a farm.
</p> </p>
</div> </div>
</div> </div>

View file

@ -5,14 +5,14 @@
* *
* The financials are REAL, from SolLunarSociety.md, and belong exclusively to * The financials are REAL, from SolLunarSociety.md, and belong exclusively to
* the first node — SolLunar Society (Austin). Lab 484, Pop-up * the first node — SolLunar Society (Austin). Lab 484, Pop-up
* Summit Gatherings and Château du Faune are narrative/vision only and have no * Festivals and Château du Faune are narrative/vision only and have no
* standalone numbers. P&L totals are recomputed from line items; the doc's * standalone numbers. P&L totals are recomputed from line items; the doc's
* own summary totals didn't reconcile (kept in `pnlDocSummary`). * own summary totals didn't reconcile (kept in `pnlDocSummary`).
* *
* Lab 484 is the shared backbone — open hardware + sovereign software (the * Lab 484 is the shared backbone — open hardware + sovereign software (the
* "mycelium"). Three surface entities run on top of it: * "mycelium"). Three surface entities run on top of it:
* • SolLunar Society — city members' club, Austin (the funded first node) * • SolLunar Society — city members' club, Austin (the funded first node)
* • Pop-up Summit Gatherings — travelling gatherings (e.g. Solarpunk Summit) * • Pop-up Festivals — travelling gatherings (e.g. Solarpunk Summit)
* • Château du Faune — regenerative farm center * • Château du Faune — regenerative farm center
* *
* Currency: all figures are USD unless noted. * Currency: all figures are USD unless noted.
@ -26,7 +26,7 @@ export const brand = {
// Lab 484 — the tech co / shared backbone (also the 45% operating partner). // Lab 484 — the tech co / shared backbone (also the 45% operating partner).
tagline: 'One network. Three ways to experience it.', tagline: 'One network. Three ways to experience it.',
subtagline: subtagline:
'A sovereign network on shared, open infrastructure. The first node — SolLunar Society, a members’ club in Austin — is live, modeled and raising now; the summit gathering and the farm are next.', 'A sovereign network on shared, open infrastructure. The first node — SolLunar Society, a members’ club in Austin — is live, modeled and raising now; the festival and the farm are next.',
firstNode: 'SolLunar Society · Austin, TX', firstNode: 'SolLunar Society · Austin, TX',
contactEmail: 'invest@sollunar.example', // PLACEHOLDER contactEmail: 'invest@sollunar.example', // PLACEHOLDER
// Seam for later: an LNbits instance + the founder's nostr npub power the // Seam for later: an LNbits instance + the founder's nostr npub power the
@ -56,7 +56,7 @@ export type Entity = {
kind: string kind: string
accent: Accent accent: Accent
layer: 'backbone' | 'surface' layer: 'backbone' | 'surface'
example?: string // for the generic summit-gathering entity example?: string // for the generic festival entity
blurb: string blurb: string
traits: string[] // what makes THIS entity unique traits: string[] // what makes THIS entity unique
spaces: string[] spaces: string[]
@ -89,18 +89,18 @@ export const entities: Entity[] = [
}, },
{ {
id: 'festivals', id: 'festivals',
name: 'Pop-up Summit Gatherings', name: 'Pop-up Festivals',
role: 'Travelling gatherings', role: 'Travelling gatherings',
kind: 'Travelling · ephemeral', kind: 'Travelling · ephemeral',
accent: 'rose', accent: 'rose',
layer: 'surface', layer: 'surface',
example: 'Solar Punk Summit', example: 'Solar Punk Summit',
blurb: blurb:
'The travelling node: a repeatable summit-gathering format — like Solar Punk Summit — that deploys the entire stack anywhere for a few days, then packs down and moves on.', 'The travelling node: a repeatable festival format — like Solar Punk Summit — that deploys the entire stack anywhere for a few days, then packs down and moves on.',
traits: [ traits: [
'Deploys the full stack from a mobile kit — anywhere', 'Deploys the full stack from a mobile kit — anywhere',
'Proves the network is portable, not tied to a building', 'Proves the network is portable, not tied to a building',
'Turns every summit gathering into a member-onboarding event', 'Turns every festival into a member-onboarding event',
], ],
spaces: ['Main stage', 'Mobile exchange kiosk', 'Mesh & power rig', 'Camp & vendors', 'Workshop tents'], spaces: ['Main stage', 'Mobile exchange kiosk', 'Mesh & power rig', 'Camp & vendors', 'Workshop tents'],
revenue: ['Ticket sales', 'Vendor & bar revenue', 'Sponsorships'], revenue: ['Ticket sales', 'Vendor & bar revenue', 'Sponsorships'],
@ -155,7 +155,7 @@ export const surfaceEntities = entities.filter((e) => e.layer === 'surface')
export const userEcosystem = [ export const userEcosystem = [
{ {
title: 'One membership card', title: 'One membership card',
body: 'A single NFC card is your identity, access and wallet everywhere — the society, a summit gathering, the farm.', body: 'A single NFC card is your identity, access and wallet everywhere — the society, a festival, the farm.',
icon: 'CreditCard', icon: 'CreditCard',
}, },
{ {
@ -222,7 +222,7 @@ export const tech = [
/* ───────────────────────────────────────────────────────────── /* ─────────────────────────────────────────────────────────────
SolLunar Society — the first node's REAL business (from SolLunar Society — the first node's REAL business (from
SolLunarSociety.md). All figures below are SolLunar Society's SolLunarSociety.md). All figures below are SolLunar Society's
only; Lab 484, Summit Gatherings and Château have no only; Lab 484, Festivals and Château have no
standalone numbers yet. Lab 484's economics appear here as standalone numbers yet. Lab 484's economics appear here as
revenue lines INTO SolLunar (~$16k/mo) — don't double-count. revenue lines INTO SolLunar (~$16k/mo) — don't double-count.
───────────────────────────────────────────────────────────── */ ───────────────────────────────────────────────────────────── */
@ -486,7 +486,7 @@ export const roadmap = [
}, },
{ {
phase: 'Phase 2', phase: 'Phase 2',
title: 'Add the summit gathering', title: 'Add the festival',
when: '~12–18 mo', when: '~12–18 mo',
body: 'Deploy the same stack to a travelling Solarpunk Summit — proving the network is portable, not tied to a building.', body: 'Deploy the same stack to a travelling Solarpunk Summit — proving the network is portable, not tied to a building.',
}, },

View file

@ -6,7 +6,7 @@
* *
* src/deck/gallery/city/ → City (SolLunar Punk Society) * src/deck/gallery/city/ → City (SolLunar Punk Society)
* src/deck/gallery/farm/ → Farm (Château du Faune) * src/deck/gallery/farm/ → Farm (Château du Faune)
* src/deck/gallery/festival/ → Summit Gathering (Pop-up Summit Gatherings) * src/deck/gallery/festival/ → Festival (Pop-up Festivals)
* *
* Supported: jpg jpeg png webp avif gif svg. Images show sorted by filename, * Supported: jpg jpeg png webp avif gif svg. Images show sorted by filename,
* so prefix with 01-, 02-, … to control order. The seeded *-placeholder.svg * so prefix with 01-, 02-, … to control order. The seeded *-placeholder.svg
@ -73,7 +73,7 @@ export const gallerySections: GallerySection[] = [
}, },
{ {
id: 'festival', id: 'festival',
label: 'Summit Gathering', label: 'Festival',
entityName: entityById('festivals').name, entityName: entityById('festivals').name,
accent: 'rose', accent: 'rose',
folder: 'src/deck/gallery/festival/', folder: 'src/deck/gallery/festival/',

View file

@ -7,7 +7,7 @@ they appear automatically** — no code to touch.
| ----------- | -------- | --------------------- | | ----------- | -------- | --------------------- |
| `city/` | City | SolLunar Punk Society | | `city/` | City | SolLunar Punk Society |
| `farm/` | Farm | Château du Faune | | `farm/` | Farm | Château du Faune |
| `festival/` | Summit Gathering | Pop-up Summit Gatherings | | `festival/` | Festival | Pop-up Festivals |
- Supported formats: `jpg` `jpeg` `png` `webp` `avif` `gif` `svg`. - Supported formats: `jpg` `jpeg` `png` `webp` `avif` `gif` `svg`.
- Images display **sorted by filename** — prefix `01-`, `02-`, … to order them. - Images display **sorted by filename** — prefix `01-`, `02-`, … to order them.

View file

@ -9,7 +9,7 @@
<rect width="800" height="800" fill="url(#g)"/> <rect width="800" height="800" fill="url(#g)"/>
<circle cx="740" cy="60" r="120" fill="hsl(256 78% 68%)" opacity="0.12"/> <circle cx="740" cy="60" r="120" fill="hsl(256 78% 68%)" opacity="0.12"/>
<circle cx="70" cy="730" r="90" fill="hsl(256 78% 68%)" opacity="0.10"/> <circle cx="70" cy="730" r="90" fill="hsl(256 78% 68%)" opacity="0.10"/>
<text x="400" y="360" text-anchor="middle" fill="hsl(256 78% 68%)" font-size="46" font-weight="bold">Summit Gathering</text> <text x="400" y="360" text-anchor="middle" fill="hsl(256 78% 68%)" font-size="46" font-weight="bold">Festival</text>
<text x="400" y="406" text-anchor="middle" fill="hsl(44 30% 90%)" font-size="26" opacity="0.85">Photo 01</text> <text x="400" y="406" text-anchor="middle" fill="hsl(44 30% 90%)" font-size="26" opacity="0.85">Photo 01</text>
<text x="400" y="444" text-anchor="middle" fill="hsl(150 8% 62%)" font-size="18" letter-spacing="3">PLACEHOLDER · 800×800</text> <text x="400" y="444" text-anchor="middle" fill="hsl(150 8% 62%)" font-size="18" letter-spacing="3">PLACEHOLDER · 800×800</text>
</svg> </svg>

Before

Width:  |  Height:  |  Size: 1,000 B

After

Width:  |  Height:  |  Size: 992 B

Before After
Before After

View file

@ -9,7 +9,7 @@
<rect width="800" height="560" fill="url(#g)"/> <rect width="800" height="560" fill="url(#g)"/>
<circle cx="740" cy="60" r="120" fill="hsl(256 78% 68%)" opacity="0.12"/> <circle cx="740" cy="60" r="120" fill="hsl(256 78% 68%)" opacity="0.12"/>
<circle cx="70" cy="490" r="90" fill="hsl(256 78% 68%)" opacity="0.10"/> <circle cx="70" cy="490" r="90" fill="hsl(256 78% 68%)" opacity="0.10"/>
<text x="400" y="240" text-anchor="middle" fill="hsl(256 78% 68%)" font-size="46" font-weight="bold">Summit Gathering</text> <text x="400" y="240" text-anchor="middle" fill="hsl(256 78% 68%)" font-size="46" font-weight="bold">Festival</text>
<text x="400" y="286" text-anchor="middle" fill="hsl(44 30% 90%)" font-size="26" opacity="0.85">Photo 02</text> <text x="400" y="286" text-anchor="middle" fill="hsl(44 30% 90%)" font-size="26" opacity="0.85">Photo 02</text>
<text x="400" y="324" text-anchor="middle" fill="hsl(150 8% 62%)" font-size="18" letter-spacing="3">PLACEHOLDER · 800×560</text> <text x="400" y="324" text-anchor="middle" fill="hsl(150 8% 62%)" font-size="18" letter-spacing="3">PLACEHOLDER · 800×560</text>
</svg> </svg>

Before

Width:  |  Height:  |  Size: 1,000 B

After

Width:  |  Height:  |  Size: 992 B

Before After
Before After

View file

@ -9,7 +9,7 @@
<rect width="800" height="1040" fill="url(#g)"/> <rect width="800" height="1040" fill="url(#g)"/>
<circle cx="740" cy="60" r="120" fill="hsl(256 78% 68%)" opacity="0.12"/> <circle cx="740" cy="60" r="120" fill="hsl(256 78% 68%)" opacity="0.12"/>
<circle cx="70" cy="970" r="90" fill="hsl(256 78% 68%)" opacity="0.10"/> <circle cx="70" cy="970" r="90" fill="hsl(256 78% 68%)" opacity="0.10"/>
<text x="400" y="480" text-anchor="middle" fill="hsl(256 78% 68%)" font-size="46" font-weight="bold">Summit Gathering</text> <text x="400" y="480" text-anchor="middle" fill="hsl(256 78% 68%)" font-size="46" font-weight="bold">Festival</text>
<text x="400" y="526" text-anchor="middle" fill="hsl(44 30% 90%)" font-size="26" opacity="0.85">Photo 03</text> <text x="400" y="526" text-anchor="middle" fill="hsl(44 30% 90%)" font-size="26" opacity="0.85">Photo 03</text>
<text x="400" y="564" text-anchor="middle" fill="hsl(150 8% 62%)" font-size="18" letter-spacing="3">PLACEHOLDER · 800×1040</text> <text x="400" y="564" text-anchor="middle" fill="hsl(150 8% 62%)" font-size="18" letter-spacing="3">PLACEHOLDER · 800×1040</text>
</svg> </svg>

Before

Width:  |  Height:  |  Size: 1,005 B

After

Width:  |  Height:  |  Size: 997 B

Before After
Before After

View file

@ -9,7 +9,7 @@
<rect width="800" height="700" fill="url(#g)"/> <rect width="800" height="700" fill="url(#g)"/>
<circle cx="740" cy="60" r="120" fill="hsl(256 78% 68%)" opacity="0.12"/> <circle cx="740" cy="60" r="120" fill="hsl(256 78% 68%)" opacity="0.12"/>
<circle cx="70" cy="630" r="90" fill="hsl(256 78% 68%)" opacity="0.10"/> <circle cx="70" cy="630" r="90" fill="hsl(256 78% 68%)" opacity="0.10"/>
<text x="400" y="310" text-anchor="middle" fill="hsl(256 78% 68%)" font-size="46" font-weight="bold">Summit Gathering</text> <text x="400" y="310" text-anchor="middle" fill="hsl(256 78% 68%)" font-size="46" font-weight="bold">Festival</text>
<text x="400" y="356" text-anchor="middle" fill="hsl(44 30% 90%)" font-size="26" opacity="0.85">Photo 04</text> <text x="400" y="356" text-anchor="middle" fill="hsl(44 30% 90%)" font-size="26" opacity="0.85">Photo 04</text>
<text x="400" y="394" text-anchor="middle" fill="hsl(150 8% 62%)" font-size="18" letter-spacing="3">PLACEHOLDER · 800×700</text> <text x="400" y="394" text-anchor="middle" fill="hsl(150 8% 62%)" font-size="18" letter-spacing="3">PLACEHOLDER · 800×700</text>
</svg> </svg>

Before

Width:  |  Height:  |  Size: 1,000 B

After

Width:  |  Height:  |  Size: 992 B

Before After
Before After

View file

@ -9,7 +9,7 @@
<rect width="800" height="600" fill="url(#g)"/> <rect width="800" height="600" fill="url(#g)"/>
<circle cx="740" cy="60" r="120" fill="hsl(256 78% 68%)" opacity="0.12"/> <circle cx="740" cy="60" r="120" fill="hsl(256 78% 68%)" opacity="0.12"/>
<circle cx="70" cy="530" r="90" fill="hsl(256 78% 68%)" opacity="0.10"/> <circle cx="70" cy="530" r="90" fill="hsl(256 78% 68%)" opacity="0.10"/>
<text x="400" y="260" text-anchor="middle" fill="hsl(256 78% 68%)" font-size="46" font-weight="bold">Summit Gathering</text> <text x="400" y="260" text-anchor="middle" fill="hsl(256 78% 68%)" font-size="46" font-weight="bold">Festival</text>
<text x="400" y="306" text-anchor="middle" fill="hsl(44 30% 90%)" font-size="26" opacity="0.85">Photo 05</text> <text x="400" y="306" text-anchor="middle" fill="hsl(44 30% 90%)" font-size="26" opacity="0.85">Photo 05</text>
<text x="400" y="344" text-anchor="middle" fill="hsl(150 8% 62%)" font-size="18" letter-spacing="3">PLACEHOLDER · 800×600</text> <text x="400" y="344" text-anchor="middle" fill="hsl(150 8% 62%)" font-size="18" letter-spacing="3">PLACEHOLDER · 800×600</text>
</svg> </svg>

Before

Width:  |  Height:  |  Size: 1,000 B

After

Width:  |  Height:  |  Size: 992 B

Before After
Before After

View file

@ -53,7 +53,7 @@ const shares = investorAsk.scenarios.map((s) => ({ equity: s, annual: Math.round
</div> </div>
<p class="mt-9 max-w-xl text-sm text-fg-muted"> <p class="mt-9 max-w-xl text-sm text-fg-muted">
Prove the model in Austin, then replicate it on Lab 484 — the summit gathering and the farm are next. Prove the model in Austin, then replicate it on Lab 484 — the festival and the farm are next.
</p> </p>
</SlideFrame> </SlideFrame>
</template> </template>

View file

@ -8,7 +8,7 @@ import { userEcosystem, surfaceEntities as entities } from '../data'
<SlideFrame <SlideFrame
kicker="One membership, everywhere" kicker="One membership, everywhere"
title="The same full experience, at every location" title="The same full experience, at every location"
subtitle="Wherever you are in the network — city, summit gathering or farm — the ecosystem is identical. Your card, your money, your identity travel with you." subtitle="Wherever you are in the network — city, festival or farm — the ecosystem is identical. Your card, your money, your identity travel with you."
> >
<div class="grid gap-4 sm:grid-cols-2 lg:grid-cols-3"> <div class="grid gap-4 sm:grid-cols-2 lg:grid-cols-3">
<div <div

View file

@ -10,7 +10,7 @@ const backbone = entityById('lab484')
<SlideFrame <SlideFrame
kicker="The collaboration" kicker="The collaboration"
title="Three experiences, one backbone" title="Three experiences, one backbone"
subtitle="One is funded and opening now — SolLunar Society in Austin. The summit gathering and the farm follow, on the same Lab 484 stack." subtitle="One is funded and opening now — SolLunar Society in Austin. The festival and the farm follow, on the same Lab 484 stack."
> >
<div class="grid gap-5 md:grid-cols-3"> <div class="grid gap-5 md:grid-cols-3">
<div <div

View file

@ -1,5 +1,6 @@
<script setup lang="ts"> <script setup lang="ts">
import SlideFrame from '../components/SlideFrame.vue' import SlideFrame from '../components/SlideFrame.vue'
import Icon from '../components/Icon.vue'
import { partnership, fmtUsd } from '../data' import { partnership, fmtUsd } from '../data'
const barBg: Record<string, string> = { const barBg: Record<string, string> = {
@ -24,9 +25,9 @@ const pct = (e: number) => Math.round(e * 100)
<SlideFrame <SlideFrame
kicker="Ownership" kicker="Ownership"
title="A three-way partnership" title="A three-way partnership"
subtitle="SolLunar Society is a joint venture — investors buy in alongside the two founding partners." subtitle="SolLunar Society is a joint venture. Investors buy in alongside the two operating partners."
> >
<!-- equity split bar --> <!-- equity bar -->
<div class="flex h-5 w-full overflow-hidden rounded-full"> <div class="flex h-5 w-full overflow-hidden rounded-full">
<div <div
v-for="p in partnership.partners" v-for="p in partnership.partners"
@ -39,20 +40,33 @@ const pct = (e: number) => Math.round(e * 100)
</div> </div>
</div> </div>
<!-- the three entities --> <div class="mt-6 grid gap-4 md:grid-cols-3">
<div class="mt-8 grid gap-5 sm:grid-cols-3">
<div <div
v-for="p in partnership.partners" v-for="p in partnership.partners"
:key="p.name" :key="p.name"
class="flex flex-col items-center rounded-2xl border px-6 py-8 text-center" class="flex flex-col rounded-2xl border p-5"
:class="ring[p.accent]" :class="ring[p.accent]"
> >
<span class="font-display text-5xl font-bold" :class="text[p.accent]">{{ pct(p.equity) }}%</span> <div class="flex items-baseline justify-between gap-2">
<h3 class="mt-3 font-display text-lg font-semibold text-fg">{{ p.name }}</h3> <h3 class="font-display text-lg font-semibold text-fg">{{ p.name }}</h3>
<span class="font-display text-2xl font-bold" :class="text[p.accent]">{{ pct(p.equity) }}%</span>
</div>
<p class="text-xs uppercase tracking-wider" :class="text[p.accent]">{{ p.role }}</p>
<ul class="mt-4 flex-1 space-y-1.5">
<li v-for="r in p.responsibilities" :key="r" class="flex items-start gap-2 text-sm text-fg-muted">
<Icon name="Check" class="mt-0.5 size-3.5 shrink-0" :class="text[p.accent]" />
{{ r }}
</li>
</ul>
<p v-if="p.note" class="mt-3 border-t border-line pt-3 text-[11px] leading-relaxed text-fg-muted">
{{ p.note }}
</p>
</div> </div>
</div> </div>
<div class="mt-8 flex flex-wrap items-center justify-center gap-x-6 gap-y-1 text-sm text-fg-muted"> <div class="mt-5 flex flex-wrap items-center justify-center gap-x-6 gap-y-1 text-sm text-fg-muted">
<span>The ask:</span> <span>The ask:</span>
<span class="font-display text-lg font-semibold text-fg"> <span class="font-display text-lg font-semibold text-fg">
{{ fmtUsd(partnership.raiseAmount) }} for {{ pct(partnership.equityOffered) }}% {{ fmtUsd(partnership.raiseAmount) }} for {{ pct(partnership.equityOffered) }}%