feat(deck): add the 14 pitch slides
Title, vision, network, technology, two nodes, city, farm, revenue, the raise, cost breakdown, angel tiers, contributor tiers, roadmap, ask. Contributor CTAs are a presentational seam for LNbits/nostr later. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
fbbd4af50c
commit
cb4b845f90
14 changed files with 495 additions and 0 deletions
52
src/deck/slides/AngelSlide.vue
Normal file
52
src/deck/slides/AngelSlide.vue
Normal file
|
|
@ -0,0 +1,52 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
import SlideFrame from '../components/SlideFrame.vue'
|
||||||
|
import Icon from '../components/Icon.vue'
|
||||||
|
import PlaceholderBadge from '../components/PlaceholderBadge.vue'
|
||||||
|
import { angelTiers, fmtUsd } from '../data'
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<SlideFrame
|
||||||
|
kicker="Ways to invest · Angels"
|
||||||
|
title="Equity, benefits, and a seat at the table"
|
||||||
|
subtitle="Angel investors are who we're after — capital plus belief, rewarded with ownership and lifelong access."
|
||||||
|
>
|
||||||
|
<div class="grid gap-5 md:grid-cols-3">
|
||||||
|
<div
|
||||||
|
v-for="tier in angelTiers"
|
||||||
|
:key="tier.name"
|
||||||
|
class="relative flex flex-col rounded-2xl border p-6"
|
||||||
|
:class="
|
||||||
|
tier.featured
|
||||||
|
? 'border-amber-400/50 bg-amber-400/[0.06]'
|
||||||
|
: 'border-white/10 bg-white/[0.03]'
|
||||||
|
"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
v-if="tier.featured"
|
||||||
|
class="absolute -top-3 left-6 rounded-full bg-amber-400 px-3 py-0.5 text-[11px] font-semibold uppercase tracking-wider text-ink"
|
||||||
|
>
|
||||||
|
Most popular
|
||||||
|
</span>
|
||||||
|
|
||||||
|
<h3 class="font-display text-xl font-semibold text-sand">{{ tier.name }}</h3>
|
||||||
|
<div class="mt-2 flex items-baseline gap-1">
|
||||||
|
<span class="text-sm text-sand-dim">from</span>
|
||||||
|
<span class="font-display text-3xl font-bold text-sand">{{ fmtUsd(tier.minAmount) }}</span>
|
||||||
|
</div>
|
||||||
|
<p class="mt-1 text-xs font-medium text-pine-300">{{ tier.equity }}</p>
|
||||||
|
|
||||||
|
<ul class="mt-5 flex-1 space-y-2.5">
|
||||||
|
<li v-for="b in tier.benefits" :key="b" class="flex items-start gap-2 text-sm text-sand-dim">
|
||||||
|
<Icon name="Check" class="mt-0.5 size-4 shrink-0 text-pine-300" />
|
||||||
|
{{ b }}
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p class="mt-5 flex items-center gap-2 text-xs text-sand-dim">
|
||||||
|
<PlaceholderBadge label="terms" /> Amounts, equity structure & benefits are indicative — final terms per the round.
|
||||||
|
</p>
|
||||||
|
</SlideFrame>
|
||||||
|
</template>
|
||||||
41
src/deck/slides/AskSlide.vue
Normal file
41
src/deck/slides/AskSlide.vue
Normal file
|
|
@ -0,0 +1,41 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
import SlideFrame from '../components/SlideFrame.vue'
|
||||||
|
import Icon from '../components/Icon.vue'
|
||||||
|
import PlaceholderBadge from '../components/PlaceholderBadge.vue'
|
||||||
|
import { brand, raiseTotal, fmtUsd } from '../data'
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<SlideFrame center>
|
||||||
|
<p class="text-xs font-semibold uppercase tracking-[0.3em] text-amber-400">The ask</p>
|
||||||
|
<h2 class="mt-4 font-display text-4xl font-semibold text-sand sm:text-5xl">
|
||||||
|
Help us grow the first two flowers
|
||||||
|
</h2>
|
||||||
|
|
||||||
|
<div class="mt-8 flex items-baseline justify-center gap-3">
|
||||||
|
<span class="font-display text-6xl font-bold text-sand">{{ fmtUsd(raiseTotal) }}</span>
|
||||||
|
<PlaceholderBadge />
|
||||||
|
</div>
|
||||||
|
<p class="mt-2 max-w-xl text-sand-dim">
|
||||||
|
to launch {{ brand.fullName }} — an angel round for equity partners, open to backers of every size.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<div class="mt-10 flex flex-col items-center gap-3 sm:flex-row">
|
||||||
|
<a
|
||||||
|
:href="`mailto:${brand.contactEmail}`"
|
||||||
|
class="inline-flex items-center gap-2 rounded-full bg-amber-400 px-6 py-3 font-semibold text-ink transition hover:bg-amber-300"
|
||||||
|
>
|
||||||
|
<Icon name="Mail" class="size-5" />
|
||||||
|
{{ brand.contactEmail }}
|
||||||
|
</a>
|
||||||
|
<button
|
||||||
|
class="inline-flex items-center gap-2 rounded-full border border-white/15 bg-white/5 px-6 py-3 font-semibold text-sand transition hover:bg-white/10"
|
||||||
|
>
|
||||||
|
<Icon name="CalendarClock" class="size-5" />
|
||||||
|
Book an investor call
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p class="mt-10 font-display text-lg text-pine-300">{{ brand.tagline }}</p>
|
||||||
|
</SlideFrame>
|
||||||
|
</template>
|
||||||
8
src/deck/slides/CitySlide.vue
Normal file
8
src/deck/slides/CitySlide.vue
Normal file
|
|
@ -0,0 +1,8 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
import LocationDetail from '../components/LocationDetail.vue'
|
||||||
|
import { locations } from '../data'
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<LocationDetail :location="locations.city" accent="pine" />
|
||||||
|
</template>
|
||||||
49
src/deck/slides/ContributorSlide.vue
Normal file
49
src/deck/slides/ContributorSlide.vue
Normal file
|
|
@ -0,0 +1,49 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
import SlideFrame from '../components/SlideFrame.vue'
|
||||||
|
import Icon from '../components/Icon.vue'
|
||||||
|
import { contributorTiers, brand, fmtUsdFull } from '../data'
|
||||||
|
|
||||||
|
// Seam: when brand.lnbitsBaseUrl is set, these become live Lightning
|
||||||
|
// checkouts (see src/features/lnbits). Until then they're "coming soon".
|
||||||
|
const live = !!brand.lnbitsBaseUrl
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<SlideFrame
|
||||||
|
kicker="Ways to invest · Everyone else"
|
||||||
|
title="Own a piece of the network for the price of dinner"
|
||||||
|
subtitle="You don't need to be an angel to build this. Back a specific piece of hardware — or an alpaca."
|
||||||
|
>
|
||||||
|
<div class="grid gap-4 sm:grid-cols-2 lg:grid-cols-4">
|
||||||
|
<div
|
||||||
|
v-for="tier in contributorTiers"
|
||||||
|
:key="tier.name"
|
||||||
|
class="flex flex-col rounded-2xl border p-5"
|
||||||
|
:class="tier.featured ? 'border-pine-500/50 bg-pine-500/[0.06]' : 'border-white/10 bg-white/[0.03]'"
|
||||||
|
>
|
||||||
|
<span class="grid size-11 place-items-center rounded-xl bg-white/5 text-pine-300">
|
||||||
|
<Icon :name="tier.icon" class="size-5" />
|
||||||
|
</span>
|
||||||
|
<div class="mt-4 flex items-baseline gap-1">
|
||||||
|
<span class="font-display text-2xl font-bold text-sand">{{ fmtUsdFull(tier.amount) }}</span>
|
||||||
|
<span v-if="tier.unit" class="text-sm text-sand-dim">{{ tier.unit }}</span>
|
||||||
|
</div>
|
||||||
|
<h3 class="mt-1 font-display text-base font-semibold text-sand">{{ tier.name }}</h3>
|
||||||
|
<p class="mt-1.5 flex-1 text-sm text-sand-dim">{{ tier.blurb }}</p>
|
||||||
|
|
||||||
|
<button
|
||||||
|
class="mt-4 flex items-center justify-center gap-1.5 rounded-lg border border-white/10 bg-white/5 px-3 py-2 text-sm font-medium text-sand transition hover:bg-white/10 disabled:cursor-not-allowed disabled:opacity-60"
|
||||||
|
:disabled="!live"
|
||||||
|
>
|
||||||
|
<Icon name="Zap" class="size-4 text-amber-300" />
|
||||||
|
{{ live ? 'Contribute' : 'Coming soon' }}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p class="mt-5 flex items-center gap-2 text-xs text-sand-dim">
|
||||||
|
<Icon name="Zap" class="size-3.5 text-amber-300" />
|
||||||
|
Contributions settle over Bitcoin Lightning — wired to LNbits & nostr when we go live.
|
||||||
|
</p>
|
||||||
|
</SlideFrame>
|
||||||
|
</template>
|
||||||
50
src/deck/slides/CostBreakdownSlide.vue
Normal file
50
src/deck/slides/CostBreakdownSlide.vue
Normal file
|
|
@ -0,0 +1,50 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
import SlideFrame from '../components/SlideFrame.vue'
|
||||||
|
import Icon from '../components/Icon.vue'
|
||||||
|
import PlaceholderBadge from '../components/PlaceholderBadge.vue'
|
||||||
|
import { costCategories, categoryTotal, fmtUsd } from '../data'
|
||||||
|
|
||||||
|
const heads = ['text-pine-300', 'text-amber-300', 'text-clay-400']
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<SlideFrame
|
||||||
|
kicker="The raise · line by line"
|
||||||
|
title="Cost breakdown"
|
||||||
|
subtitle="Every figure lives in one file — swap placeholders for your real budget in src/deck/data.ts."
|
||||||
|
>
|
||||||
|
<div class="grid gap-4 md:grid-cols-3">
|
||||||
|
<div
|
||||||
|
v-for="(c, i) in costCategories"
|
||||||
|
:key="c.id"
|
||||||
|
class="flex flex-col rounded-2xl border border-white/10 bg-white/[0.03] p-5"
|
||||||
|
>
|
||||||
|
<div class="flex items-center gap-2">
|
||||||
|
<Icon :name="c.icon" class="size-5" :class="heads[i]" />
|
||||||
|
<h3 class="font-display text-base font-semibold text-sand">{{ c.title }}</h3>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<ul class="mt-4 flex-1 space-y-2.5">
|
||||||
|
<li v-for="item in c.items" :key="item.label" class="text-sm">
|
||||||
|
<div class="flex items-baseline justify-between gap-3">
|
||||||
|
<span class="text-sand-dim">{{ item.label }}</span>
|
||||||
|
<span class="shrink-0 tabular-nums text-sand">{{ fmtUsd(item.amount) }}</span>
|
||||||
|
</div>
|
||||||
|
<p v-if="item.note" class="text-[11px] text-sand-dim/70">{{ item.note }}</p>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<div class="mt-4 flex items-center justify-between border-t border-white/10 pt-3">
|
||||||
|
<span class="text-xs uppercase tracking-wider text-sand-dim">Subtotal</span>
|
||||||
|
<span class="font-display text-lg font-semibold" :class="heads[i]">
|
||||||
|
{{ fmtUsd(categoryTotal(c)) }}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p class="mt-5 flex items-center gap-2 text-xs text-sand-dim">
|
||||||
|
<PlaceholderBadge /> All amounts are illustrative pending your real quotes & salary bands.
|
||||||
|
</p>
|
||||||
|
</SlideFrame>
|
||||||
|
</template>
|
||||||
8
src/deck/slides/FarmSlide.vue
Normal file
8
src/deck/slides/FarmSlide.vue
Normal file
|
|
@ -0,0 +1,8 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
import LocationDetail from '../components/LocationDetail.vue'
|
||||||
|
import { locations } from '../data'
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<LocationDetail :location="locations.farm" accent="clay" />
|
||||||
|
</template>
|
||||||
58
src/deck/slides/InvestmentOverviewSlide.vue
Normal file
58
src/deck/slides/InvestmentOverviewSlide.vue
Normal file
|
|
@ -0,0 +1,58 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
import SlideFrame from '../components/SlideFrame.vue'
|
||||||
|
import Icon from '../components/Icon.vue'
|
||||||
|
import PlaceholderBadge from '../components/PlaceholderBadge.vue'
|
||||||
|
import { costCategories, categoryTotal, raiseTotal, fmtUsd } from '../data'
|
||||||
|
|
||||||
|
const tones = ['bg-pine-500', 'bg-amber-400', 'bg-clay-400']
|
||||||
|
const dot = ['text-pine-300', 'text-amber-300', 'text-clay-400']
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<SlideFrame kicker="The raise" title="Where the investment goes">
|
||||||
|
<div class="grid items-center gap-10 lg:grid-cols-[1fr_1.1fr]">
|
||||||
|
<!-- headline number + proportion bar -->
|
||||||
|
<div>
|
||||||
|
<div class="flex items-end gap-3">
|
||||||
|
<span class="font-display text-6xl font-bold text-sand">{{ fmtUsd(raiseTotal) }}</span>
|
||||||
|
<PlaceholderBadge />
|
||||||
|
</div>
|
||||||
|
<p class="mt-2 text-sand-dim">Total to launch both proof-of-concept nodes.</p>
|
||||||
|
|
||||||
|
<div class="mt-8 flex h-4 w-full overflow-hidden rounded-full">
|
||||||
|
<div
|
||||||
|
v-for="(c, i) in costCategories"
|
||||||
|
:key="c.id"
|
||||||
|
:class="tones[i]"
|
||||||
|
:style="{ width: `${(categoryTotal(c) / raiseTotal) * 100}%` }"
|
||||||
|
class="h-full"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="mt-3 flex flex-wrap gap-x-6 gap-y-1 text-xs text-sand-dim">
|
||||||
|
<span v-for="(c, i) in costCategories" :key="c.id" class="flex items-center gap-2">
|
||||||
|
<span class="size-2 rounded-full" :class="tones[i]" />
|
||||||
|
{{ Math.round((categoryTotal(c) / raiseTotal) * 100) }}%
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- three categories -->
|
||||||
|
<div class="space-y-3">
|
||||||
|
<div
|
||||||
|
v-for="(c, i) in costCategories"
|
||||||
|
:key="c.id"
|
||||||
|
class="flex items-center gap-4 rounded-2xl border border-white/10 bg-white/[0.03] p-5"
|
||||||
|
>
|
||||||
|
<span class="grid size-11 shrink-0 place-items-center rounded-xl bg-white/5" :class="dot[i]">
|
||||||
|
<Icon :name="c.icon" class="size-5" />
|
||||||
|
</span>
|
||||||
|
<div class="min-w-0 flex-1">
|
||||||
|
<h3 class="font-display text-lg font-semibold text-sand">{{ c.title }}</h3>
|
||||||
|
<p class="truncate text-xs text-sand-dim">{{ c.subtitle }}</p>
|
||||||
|
</div>
|
||||||
|
<span class="font-display text-xl font-semibold text-sand">{{ fmtUsd(categoryTotal(c)) }}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</SlideFrame>
|
||||||
|
</template>
|
||||||
51
src/deck/slides/LocationsSlide.vue
Normal file
51
src/deck/slides/LocationsSlide.vue
Normal file
|
|
@ -0,0 +1,51 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
import SlideFrame from '../components/SlideFrame.vue'
|
||||||
|
import Icon from '../components/Icon.vue'
|
||||||
|
import PlaceholderBadge from '../components/PlaceholderBadge.vue'
|
||||||
|
import { locations } from '../data'
|
||||||
|
|
||||||
|
const list = [locations.city, locations.farm]
|
||||||
|
const accents = ['text-pine-300 border-pine-500/30 bg-pine-500/5', 'text-clay-400 border-clay-400/30 bg-clay-400/5']
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<SlideFrame
|
||||||
|
kicker="Two proof-of-concept launches"
|
||||||
|
title="One network, two very different flowers"
|
||||||
|
subtitle="Deliberately opposite environments — an urban flagship and an off-grid farm — to prove the stack works anywhere."
|
||||||
|
>
|
||||||
|
<div class="grid gap-6 md:grid-cols-2">
|
||||||
|
<div
|
||||||
|
v-for="(loc, i) in list"
|
||||||
|
:key="loc.id"
|
||||||
|
class="flex flex-col rounded-2xl border p-6"
|
||||||
|
:class="accents[i]"
|
||||||
|
>
|
||||||
|
<div class="flex items-center gap-3">
|
||||||
|
<span class="grid size-11 place-items-center rounded-xl bg-white/5">
|
||||||
|
<Icon :name="loc.icon" class="size-6" />
|
||||||
|
</span>
|
||||||
|
<div>
|
||||||
|
<div class="flex items-center gap-2">
|
||||||
|
<h3 class="font-display text-2xl font-semibold text-sand">{{ loc.name }}</h3>
|
||||||
|
<PlaceholderBadge label="name" />
|
||||||
|
</div>
|
||||||
|
<p class="text-xs uppercase tracking-wider text-sand-dim">{{ loc.kind }}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p class="mt-4 text-sm leading-relaxed text-sand-dim">{{ loc.blurb }}</p>
|
||||||
|
|
||||||
|
<div class="mt-5 flex flex-wrap gap-2">
|
||||||
|
<span
|
||||||
|
v-for="s in loc.spaces"
|
||||||
|
:key="s"
|
||||||
|
class="rounded-full border border-white/10 bg-white/5 px-3 py-1 text-xs text-sand"
|
||||||
|
>
|
||||||
|
{{ s }}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</SlideFrame>
|
||||||
|
</template>
|
||||||
14
src/deck/slides/NetworkSlide.vue
Normal file
14
src/deck/slides/NetworkSlide.vue
Normal file
|
|
@ -0,0 +1,14 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
import SlideFrame from '../components/SlideFrame.vue'
|
||||||
|
import MyceliumNetwork from '../components/MyceliumNetwork.vue'
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<SlideFrame
|
||||||
|
kicker="The network"
|
||||||
|
title="A mycelial network"
|
||||||
|
subtitle="What you see are the locations. What makes them work is the network beneath them — and it grows the same way mycelium does: spread the network once, then fruit anywhere."
|
||||||
|
>
|
||||||
|
<MyceliumNetwork />
|
||||||
|
</SlideFrame>
|
||||||
|
</template>
|
||||||
33
src/deck/slides/RevenueSlide.vue
Normal file
33
src/deck/slides/RevenueSlide.vue
Normal file
|
|
@ -0,0 +1,33 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
import SlideFrame from '../components/SlideFrame.vue'
|
||||||
|
import Icon from '../components/Icon.vue'
|
||||||
|
import { revenueStreams } from '../data'
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<SlideFrame
|
||||||
|
kicker="Not a cost centre — a business"
|
||||||
|
title="The nodes are fully operational event spaces"
|
||||||
|
subtitle="Every location earns while it demonstrates the technology. Six revenue streams across both nodes."
|
||||||
|
>
|
||||||
|
<div class="grid gap-4 sm:grid-cols-2 lg:grid-cols-3">
|
||||||
|
<div
|
||||||
|
v-for="r in revenueStreams"
|
||||||
|
:key="r.title"
|
||||||
|
class="flex items-start gap-4 rounded-2xl border border-white/10 bg-white/[0.03] p-5"
|
||||||
|
>
|
||||||
|
<span class="grid size-11 shrink-0 place-items-center rounded-xl bg-amber-400/10 text-amber-300">
|
||||||
|
<Icon :name="r.icon" class="size-5" />
|
||||||
|
</span>
|
||||||
|
<div>
|
||||||
|
<h3 class="font-display text-lg font-semibold text-sand">{{ r.title }}</h3>
|
||||||
|
<p class="mt-1 text-sm text-sand-dim">{{ r.note }}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p class="mt-8 text-sm text-sand-dim">
|
||||||
|
Investors get access to these spaces — stays, retreats and residencies included in angel tiers.
|
||||||
|
</p>
|
||||||
|
</SlideFrame>
|
||||||
|
</template>
|
||||||
37
src/deck/slides/RoadmapSlide.vue
Normal file
37
src/deck/slides/RoadmapSlide.vue
Normal file
|
|
@ -0,0 +1,37 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
import SlideFrame from '../components/SlideFrame.vue'
|
||||||
|
import { roadmap } from '../data'
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<SlideFrame
|
||||||
|
kicker="The replication play"
|
||||||
|
title="Prove it twice, then grow it anywhere"
|
||||||
|
subtitle="The two nodes aren't the endgame — they're the seed. The blueprint is the business."
|
||||||
|
>
|
||||||
|
<ol class="relative grid gap-6 md:grid-cols-4">
|
||||||
|
<!-- connecting line -->
|
||||||
|
<div class="absolute left-0 right-0 top-5 hidden h-px bg-gradient-to-r from-pine-500/40 via-amber-400/40 to-clay-400/40 md:block" />
|
||||||
|
|
||||||
|
<li v-for="(p, i) in roadmap" :key="p.phase" class="relative">
|
||||||
|
<div class="flex items-center gap-3 md:block">
|
||||||
|
<span
|
||||||
|
class="z-10 grid size-10 shrink-0 place-items-center rounded-full border border-white/15 bg-ink font-display text-sm font-bold text-amber-300"
|
||||||
|
>
|
||||||
|
{{ i + 1 }}
|
||||||
|
</span>
|
||||||
|
<span class="mt-3 block text-[11px] font-semibold uppercase tracking-wider text-pine-300">
|
||||||
|
{{ p.phase }} · {{ p.when }}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<h3 class="mt-2 font-display text-lg font-semibold text-sand">{{ p.title }}</h3>
|
||||||
|
<p class="mt-1 text-sm text-sand-dim">{{ p.body }}</p>
|
||||||
|
</li>
|
||||||
|
</ol>
|
||||||
|
|
||||||
|
<p class="mt-10 rounded-2xl border border-pine-500/20 bg-pine-500/5 p-5 text-center text-sand">
|
||||||
|
Once the mycelium runs, every new flower is
|
||||||
|
<span class="font-semibold text-pine-300">marginal cost, not a new company.</span>
|
||||||
|
</p>
|
||||||
|
</SlideFrame>
|
||||||
|
</template>
|
||||||
27
src/deck/slides/TechSlide.vue
Normal file
27
src/deck/slides/TechSlide.vue
Normal file
|
|
@ -0,0 +1,27 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
import SlideFrame from '../components/SlideFrame.vue'
|
||||||
|
import Icon from '../components/Icon.vue'
|
||||||
|
import { tech } from '../data'
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<SlideFrame
|
||||||
|
kicker="The technology"
|
||||||
|
title="Open hardware, sovereign software"
|
||||||
|
subtitle="The stack under every node — owned by the network, documented to be rebuilt anywhere."
|
||||||
|
>
|
||||||
|
<div class="grid gap-4 sm:grid-cols-2 lg:grid-cols-3">
|
||||||
|
<div
|
||||||
|
v-for="t in tech"
|
||||||
|
:key="t.title"
|
||||||
|
class="rounded-2xl border border-white/10 bg-white/[0.03] p-5 transition hover:border-pine-500/40 hover:bg-pine-500/5"
|
||||||
|
>
|
||||||
|
<span class="grid size-10 place-items-center rounded-xl bg-pine-500/10 text-pine-300">
|
||||||
|
<Icon :name="t.icon" class="size-5" />
|
||||||
|
</span>
|
||||||
|
<h3 class="mt-4 font-display text-lg font-semibold text-sand">{{ t.title }}</h3>
|
||||||
|
<p class="mt-1.5 text-sm leading-relaxed text-sand-dim">{{ t.body }}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</SlideFrame>
|
||||||
|
</template>
|
||||||
33
src/deck/slides/TitleSlide.vue
Normal file
33
src/deck/slides/TitleSlide.vue
Normal file
|
|
@ -0,0 +1,33 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
import SlideFrame from '../components/SlideFrame.vue'
|
||||||
|
import PlaceholderBadge from '../components/PlaceholderBadge.vue'
|
||||||
|
import { brand } from '../data'
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<SlideFrame center>
|
||||||
|
<div class="flex flex-col items-center">
|
||||||
|
<span class="mb-6 inline-flex items-center gap-2 rounded-full border border-pine-500/30 bg-pine-500/10 px-4 py-1.5 text-xs uppercase tracking-[0.3em] text-pine-300">
|
||||||
|
Investment prospectus
|
||||||
|
<PlaceholderBadge label="draft" />
|
||||||
|
</span>
|
||||||
|
|
||||||
|
<h1 class="font-display text-6xl font-bold tracking-tight text-sand sm:text-7xl lg:text-8xl">
|
||||||
|
{{ brand.name }}
|
||||||
|
</h1>
|
||||||
|
<p class="mt-4 text-lg text-pine-300 sm:text-xl">{{ brand.fullName }}</p>
|
||||||
|
|
||||||
|
<p class="mt-8 max-w-2xl text-balance text-xl text-sand sm:text-2xl">
|
||||||
|
{{ brand.tagline }}
|
||||||
|
</p>
|
||||||
|
<p class="mt-4 max-w-xl text-balance text-sm text-sand-dim sm:text-base">
|
||||||
|
{{ brand.subtagline }}
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p class="mt-14 text-xs text-sand-dim">
|
||||||
|
Use <kbd class="rounded border border-white/15 px-1.5 py-0.5">→</kbd> /
|
||||||
|
<kbd class="rounded border border-white/15 px-1.5 py-0.5">←</kbd> to navigate
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</SlideFrame>
|
||||||
|
</template>
|
||||||
34
src/deck/slides/VisionSlide.vue
Normal file
34
src/deck/slides/VisionSlide.vue
Normal file
|
|
@ -0,0 +1,34 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
import SlideFrame from '../components/SlideFrame.vue'
|
||||||
|
import Icon from '../components/Icon.vue'
|
||||||
|
import { problem } from '../data'
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<SlideFrame kicker="The problem" :title="problem.headline">
|
||||||
|
<div class="grid gap-10 lg:grid-cols-[1.1fr_1fr]">
|
||||||
|
<ul class="space-y-5">
|
||||||
|
<li
|
||||||
|
v-for="(p, i) in problem.points"
|
||||||
|
:key="i"
|
||||||
|
class="flex items-start gap-4 text-lg text-sand-dim"
|
||||||
|
>
|
||||||
|
<span class="mt-1 grid size-6 shrink-0 place-items-center rounded-full bg-white/5 text-xs font-semibold text-amber-300">
|
||||||
|
{{ i + 1 }}
|
||||||
|
</span>
|
||||||
|
{{ p }}
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<div class="flex flex-col justify-center rounded-2xl border border-pine-500/20 bg-pine-500/5 p-8">
|
||||||
|
<Icon name="HeartHandshake" class="size-8 text-pine-300" />
|
||||||
|
<p class="mt-4 text-xs font-semibold uppercase tracking-[0.2em] text-pine-300">
|
||||||
|
Our thesis
|
||||||
|
</p>
|
||||||
|
<p class="mt-3 font-display text-2xl leading-snug text-sand">
|
||||||
|
{{ problem.thesis }}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</SlideFrame>
|
||||||
|
</template>
|
||||||
Loading…
Add table
Add a link
Reference in a new issue