From 9e74000f9f043998a19608a7a7204e649890584d Mon Sep 17 00:00:00 2001 From: Patrick Mulligan Date: Tue, 28 Jul 2026 18:34:19 +0200 Subject: [PATCH] feat(deck): show three entity flowers in the mycelium viz City and farm render as permanent blooms; Solunar Society is an ephemeral pop-up cluster (indigo, dashed stem, floats + fades). Underground caption reframed as the shared core stack every entity runs. Co-Authored-By: Claude Opus 4.8 (1M context) --- src/deck/components/MyceliumNetwork.vue | 211 ++++++++++++++++-------- 1 file changed, 141 insertions(+), 70 deletions(-) diff --git a/src/deck/components/MyceliumNetwork.vue b/src/deck/components/MyceliumNetwork.vue index d8b2293..8cf3e3d 100644 --- a/src/deck/components/MyceliumNetwork.vue +++ b/src/deck/components/MyceliumNetwork.vue @@ -2,35 +2,37 @@ /** * The core metaphor, as an animated SVG. * - * Underground → the mycelium = our tech foundation / custom software - * stacks. Unseen, always working, connects everything. - * Surface → "flowers" (fruiting bodies) = physical locations - * (City + Farm) that people actually experience. - * Ghost flowers→ once the mycelium runs, new locations sprout cheaply, - * anywhere in the world. + * Underground → the mycelium = the shared core stack / custom software. + * Unseen, always working, connects every entity. + * Flowers → the three entities people actually experience: + * • Archipelago (city center) — a permanent bloom + * • Solunar Society (pop-up fest.) — ephemeral cluster + * • Chateau du Faune (farm center) — a permanent bloom + * Ghost flowers→ once the mycelium runs, new locations & festivals sprout + * cheaply, anywhere in the world. * * Pure SVG + CSS so it scales crisply on a projector and respects * prefers-reduced-motion. */ import Icon from './Icon.vue' -import { locations } from '../data' +import { entityById } from '../data' const GROUND = 300 // underground mycelium nodes (below the ground line) const nodes: [number, number][] = [ - [330, 340], // root under city - [670, 340], // root under farm - [150, 335], // root under ghost 1 - [500, 335], // root under ghost 2 - [850, 335], // root under ghost 3 - [90, 430], - [250, 480], - [410, 420], + [230, 340], // root · Archipelago + [500, 335], // root · Solunar + [770, 340], // root · Chateau + [100, 340], // root · ghost + [900, 340], // root · ghost + [160, 430], + [330, 470], + [430, 420], [560, 470], - [720, 430], - [900, 470], - [180, 560], + [660, 430], + [840, 470], + [240, 560], [430, 560], [620, 560], [810, 560], @@ -38,33 +40,30 @@ const nodes: [number, number][] = [ // threads weaving the mycelium together (indices into `nodes`) const edges: [number, number][] = [ - [0, 7], [0, 6], - [0, 2], + [0, 5], + [0, 7], [0, 3], - [1, 8], - [1, 9], - [1, 3], - [1, 4], - [2, 5], - [2, 6], - [3, 7], - [3, 8], - [4, 9], - [4, 10], + [3, 5], [5, 11], [6, 11], [6, 12], [7, 12], + [7, 1], + [1, 8], + [8, 12], [8, 13], + [1, 9], [9, 13], - [9, 14], + [9, 2], + [2, 10], [10, 14], - [3, 0], - [3, 1], + [4, 10], + [9, 14], + [7, 8], + [2, 4], ] -// organic curved path between two nodes function thread([a, b]: [number, number], i: number) { const [ax, ay] = nodes[a] const [bx, by] = nodes[b] @@ -73,14 +72,25 @@ function thread([a, b]: [number, number], i: number) { return `M ${ax} ${ay} Q ${mx} ${my} ${bx} ${by}` } -// surface flowers: the two real nodes + three faint "future" ones +const arch = entityById('archipelago') +const sol = entityById('solunar') +const cha = entityById('chateau') + +// surface flowers: three entities + two faint "future" ones const flowers = [ - { x: 330, kind: 'real', color: 'var(--color-pine-400)', name: locations.city.name, tag: 'City node' }, - { x: 670, kind: 'real', color: 'var(--color-clay-400)', name: locations.farm.name, tag: 'Farm node' }, - { x: 150, kind: 'ghost' }, - { x: 500, kind: 'ghost' }, - { x: 850, kind: 'ghost' }, + { x: 230, kind: 'bloom', color: 'var(--color-pine-400)', name: arch.name, tag: arch.role }, + { x: 500, kind: 'festival', color: 'var(--color-indigo-400)', name: sol.name, tag: sol.role }, + { x: 770, kind: 'bloom', color: 'var(--color-clay-400)', name: cha.name, tag: cha.role }, + { x: 100, kind: 'ghost' }, + { x: 900, kind: 'ghost' }, ] as const + +// small pop-up caps for the ephemeral festival flower +const festivalCaps = [ + { dx: -18, dy: -58, r: 15 }, + { dx: 0, dy: -74, r: 20 }, + { dx: 20, dy: -60, r: 14 }, +]