feat: port module landing pages from standalone Next.js sites

Replace template landing pages for 10 modules with unique designs ported
from their original standalone Next.js/Tailwind sites. Each page now has
distinctive visuals, SVG icons, and content matching the original:

- rfunds: funnel metaphor diagram, amber/emerald/blue theme
- rtube: video streaming workflow, red/pink/orange theme
- rtrips: travel planning with teal/cyan SVG icons
- rforum: Discourse pricing tiers, indigo/violet theme
- rcal: temporal zoom visualization, blue gradient bars
- rvote: quadratic voting calculator, indigo/purple theme
- rpubs: group buy tiers, cross-title batching diagram
- rchoices: spider plot SVG, ranking mockup, live voting bars
- rwork: kanban board workflow, blue/teal/green theme
- rinbox: encrypted chat features, blue/teal gradient

All pages use dark mode and the shared rl-* CSS utility classes.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Jeff Emmett 2026-02-28 04:09:23 +00:00
parent 32ed06d43a
commit c3deb18df8
10 changed files with 1709 additions and 1180 deletions

View File

@ -1,152 +1,202 @@
/**
* rCal landing page relational calendar.
* Ported from rcal-online Next.js page.tsx (318 lines).
*/
export function renderLanding(): string {
return `
<!-- Hero -->
<div class="rl-hero">
<span class="rl-tagline">rCal</span>
<h1 class="rl-heading">(You)rCal, your rhythm.</h1>
<p class="rl-subtitle">Time is shared. Your calendar should be too.</p>
<span class="rl-tagline" style="color:#60a5fa;background:rgba(96,165,250,0.1);border-color:rgba(96,165,250,0.2)">
Relational Calendar
</span>
<h1 class="rl-heading" style="background:linear-gradient(to right,#60a5fa,#818cf8,#a78bfa);-webkit-background-clip:text;-webkit-text-fill-color:transparent;background-clip:text">
Time is shared. Your calendar should be too.
</h1>
<p class="rl-subtitle">
A collaborative calendar for communities, cooperatives, and coordinated groups.
</p>
<p class="rl-subtext">
A spatiotemporal calendar that couples where and when, supports natural cycles,
and zooms from 30-second moments to geological epochs.
rCal rethinks the calendar as a <span style="color:#60a5fa;font-weight:600">shared, spatial, and cyclical</span> tool.
See events across time and place, overlay lunar cycles, zoom from a single hour to a whole decade,
and keep everyone on the same page &mdash; without the back-and-forth.
</p>
<div class="rl-cta-row">
<a href="https://demo.rspace.online/rcal" class="rl-cta-primary" id="ml-primary">Open Calendar</a>
<a href="/create-space" class="rl-cta-secondary">Create a Space</a>
<a href="https://demo.rspace.online/rcal" class="rl-cta-primary" id="ml-primary"
style="background:linear-gradient(to right,#60a5fa,#6366f1);color:#0b1120">
Try the Demo
</a>
<a href="#features" class="rl-cta-secondary">Learn More</a>
</div>
</div>
<!-- Features -->
<section class="rl-section">
<!-- Principles (4-card grid) -->
<section class="rl-section" style="border-top:none">
<div class="rl-container">
<h2 class="rl-heading" style="text-align:center">What rCal Handles</h2>
<div class="rl-grid-4">
<div class="rl-card rl-card--center">
<div class="rl-icon-box">&#128301;</div>
<h3>Temporal Zoom</h3>
<p>Ten zoom levels from 30-second moments to cosmic time. Year, month, week, day &mdash; and beyond.</p>
<div class="rl-card rl-card--center" style="padding:2rem">
<div class="rl-icon-box" style="background:rgba(96,165,250,0.12);font-size:1.5rem">
<span style="font-size:1.5rem">&#129309;</span>
</div>
<h3>Shared by Default</h3>
<p>One calendar for the whole group. Everyone sees the same context &mdash; no more fragmented schedules.</p>
</div>
<div class="rl-card rl-card--center">
<div class="rl-icon-box">&#128197;</div>
<h3>Shared Events</h3>
<p>Calendars belong to spaces, not individuals. Everyone sees the same schedule by default.</p>
<div class="rl-card rl-card--center" style="padding:2rem">
<div class="rl-icon-box" style="background:rgba(129,140,248,0.12);font-size:1.5rem">
<span style="font-size:1.5rem">&#128506;</span>
</div>
<h3>Spatiotemporal</h3>
<p>Events have a where, not just a when. See your schedule on a map and a timeline simultaneously.</p>
</div>
<div class="rl-card rl-card--center">
<div class="rl-icon-box">&#127769;</div>
<h3>Lunar Phases</h3>
<p>Moon phases, solstices, and seasonal rhythms overlaid on the Gregorian grid. Plan with natural cycles.</p>
<div class="rl-card rl-card--center" style="padding:2rem">
<div class="rl-icon-box" style="background:rgba(167,139,250,0.12);font-size:1.5rem">
<span style="font-size:1.5rem">&#127769;</span>
</div>
<h3>Natural Cycles</h3>
<p>Lunar phases, eclipses, and solstices built in. Reconnect your planning to the rhythms of the natural world.</p>
</div>
<div class="rl-card rl-card--center">
<div class="rl-icon-box">&#128506;</div>
<h3>Location-Aware</h3>
<p>Events have places, not just times. Spatial and temporal zoom are coupled at every level.</p>
<div class="rl-card rl-card--center" style="padding:2rem">
<div class="rl-icon-box" style="background:rgba(52,211,153,0.12);font-size:1.5rem">
<span style="font-size:1.5rem">&#128301;</span>
</div>
<h3>Multi-Scale Zoom</h3>
<p>Ten levels of time &mdash; from a 30-second moment to a cosmic era. See today or plan a decade ahead.</p>
</div>
</div>
</div>
</section>
<!-- How It Works -->
<section class="rl-section rl-section--alt">
<!-- Why rCal -->
<section id="features" class="rl-section rl-section--alt">
<div class="rl-container">
<h2 class="rl-heading" style="text-align:center">How It Works</h2>
<div class="rl-grid-3">
<div class="rl-step">
<span class="rl-step__num">1</span>
<h3>Create events</h3>
<p>Add events with time, location, and source context. Pull from ICS feeds, CalDAV, or other r* modules.</p>
<span class="rl-tagline" style="color:#60a5fa;background:rgba(96,165,250,0.1);border-color:rgba(96,165,250,0.2)">
Why rCal?
</span>
<h2 class="rl-heading" style="background:linear-gradient(135deg,#60a5fa,#818cf8);-webkit-background-clip:text;-webkit-text-fill-color:transparent;background-clip:text">
Calendars were never meant to be personal silos
</h2>
<p class="rl-subtext" style="margin-bottom:2.5rem">
Mainstream calendars treat time as private property. rCal treats it as a <span style="color:#60a5fa;font-weight:600">commons</span> &mdash;
something groups navigate together. Here&rsquo;s what makes it different.
</p>
<div class="rl-grid-2">
<div class="rl-card" style="border-color:rgba(96,165,250,0.12)">
<div style="font-size:1.75rem;margin-bottom:1rem">&#128205;</div>
<h3>Where + When, Together</h3>
<p>Every event lives on both a timeline and a map. rCal&rsquo;s split view lets you see where everyone is meeting and when &mdash; with nine spatial zoom levels from planet to street address.</p>
</div>
<div class="rl-step">
<span class="rl-step__num">2</span>
<h3>Zoom and explore</h3>
<p>Navigate across ten temporal zoom levels. Spatial and temporal zoom are coupled &mdash; zoom out in time and the map zooms out too.</p>
<div class="rl-card" style="border-color:rgba(96,165,250,0.12)">
<div style="font-size:1.75rem;margin-bottom:1rem">&#128279;</div>
<h3>Coupled Zoom</h3>
<p>Lock temporal and spatial zoom together: zoom out in time and the map zooms out to match. Planning a week? See the city. Planning a decade? See the continent.</p>
</div>
<div class="rl-step">
<span class="rl-step__num">3</span>
<h3>Share with your space</h3>
<p>Space members see the same calendar. rWork sprints, rVote deadlines, rTrips itineraries &mdash; all in one view.</p>
<div class="rl-card" style="border-color:rgba(96,165,250,0.12)">
<div style="font-size:1.75rem;margin-bottom:1rem">&#128225;</div>
<h3>Multi-Source Sync</h3>
<p>Import from Google, Outlook, Apple, CalDAV, ICS feeds, and Obsidian. Layer multiple sources with per-source color coding and visibility controls.</p>
</div>
<div class="rl-card" style="border-color:rgba(96,165,250,0.12)">
<div style="font-size:1.75rem;margin-bottom:1rem">&#127761;</div>
<h3>Lunar Overlay</h3>
<p>Eight moon phases rendered on every calendar view with illumination percentages and eclipse detection. Plan gatherings, gardens, and ceremonies around natural cycles.</p>
</div>
<div class="rl-card" style="border-color:rgba(96,165,250,0.12)">
<div style="font-size:1.75rem;margin-bottom:1rem">&#129513;</div>
<h3>r* Ecosystem Embeds</h3>
<p>rTrips, rMaps, rNetwork, rCart, and rNotes can all embed a calendar view through the context API. One calendar, surfaced everywhere it&rsquo;s needed.</p>
</div>
<div class="rl-card" style="border-color:rgba(96,165,250,0.12)">
<div style="font-size:1.75rem;margin-bottom:1rem">&#127968;</div>
<h3>Self-Hosted &amp; Sovereign</h3>
<p>Open source and Dockerized. Your events live on your infrastructure &mdash; not in a corporate cloud. Full data sovereignty with rIDs authentication.</p>
</div>
</div>
</div>
</section>
<!-- Temporal Zoom -->
<!-- Temporal Zoom Levels -->
<section class="rl-section">
<div class="rl-container">
<h2 class="rl-heading" style="text-align:center">Temporal zoom</h2>
<p class="rl-subtext" style="text-align:center">Ten levels of time &mdash; from the blink of an eye to deep time.</p>
<div class="rl-card" style="max-width:700px;margin:2rem auto 0">
<div class="rl-zoom-bar">
<span class="rl-tagline" style="color:#818cf8;background:rgba(129,140,248,0.1);border-color:rgba(129,140,248,0.2)">
Temporal Navigation
</span>
<h2 class="rl-heading" style="background:linear-gradient(135deg,#818cf8,#a78bfa);-webkit-background-clip:text;-webkit-text-fill-color:transparent;background-clip:text">
Ten levels of time
</h2>
<p class="rl-subtext">
Most calendars show you a month. rCal lets you zoom from a single moment to a cosmic era &mdash;
each level revealing a different kind of pattern.
</p>
<div class="rl-card" style="max-width:700px;margin:2rem auto 0;overflow-x:auto">
<div class="rl-zoom-bar" style="min-width:460px">
<div class="rl-zoom-bar__row">
<span class="rl-zoom-bar__label">0</span>
<div class="rl-zoom-bar__bar" style="width:10%;background:rgba(99,102,241,0.3)">
<div class="rl-zoom-bar__bar" style="width:4%;background:rgba(59,130,246,0.25)">
<span class="rl-zoom-bar__name">Moment</span>
</div>
<span class="rl-zoom-bar__span">30 s</span>
<span class="rl-zoom-bar__span">30 seconds</span>
</div>
<div class="rl-zoom-bar__row">
<span class="rl-zoom-bar__label">1</span>
<div class="rl-zoom-bar__bar" style="width:15%;background:rgba(99,102,241,0.28)">
<span class="rl-zoom-bar__name">Minute</span>
<div class="rl-zoom-bar__bar" style="width:8%;background:rgba(96,165,250,0.25)">
<span class="rl-zoom-bar__name">Hour</span>
</div>
<span class="rl-zoom-bar__span">1&ndash;10 min</span>
<span class="rl-zoom-bar__span">60 minutes</span>
</div>
<div class="rl-zoom-bar__row">
<span class="rl-zoom-bar__label">2</span>
<div class="rl-zoom-bar__bar" style="width:22%;background:rgba(99,102,241,0.25)">
<span class="rl-zoom-bar__name">Hour</span>
<div class="rl-zoom-bar__bar" style="width:14%;background:rgba(96,165,250,0.22)">
<span class="rl-zoom-bar__name">Day</span>
</div>
<span class="rl-zoom-bar__span">1&ndash;6 hrs</span>
<span class="rl-zoom-bar__span">24 hours</span>
</div>
<div class="rl-zoom-bar__row">
<span class="rl-zoom-bar__label">3</span>
<div class="rl-zoom-bar__bar" style="width:30%;background:rgba(99,102,241,0.22)">
<span class="rl-zoom-bar__name">Day</span>
</div>
<span class="rl-zoom-bar__span">24 hrs</span>
</div>
<div class="rl-zoom-bar__row">
<span class="rl-zoom-bar__label">4</span>
<div class="rl-zoom-bar__bar" style="width:40%;background:rgba(99,102,241,0.20)">
<div class="rl-zoom-bar__bar" style="width:22%;background:rgba(129,140,248,0.22)">
<span class="rl-zoom-bar__name">Week</span>
</div>
<span class="rl-zoom-bar__span">7 days</span>
</div>
<div class="rl-zoom-bar__row">
<span class="rl-zoom-bar__label">5</span>
<div class="rl-zoom-bar__bar" style="width:50%;background:rgba(99,102,241,0.18)">
<span class="rl-zoom-bar__name">Lunar</span>
<span class="rl-zoom-bar__label">4</span>
<div class="rl-zoom-bar__bar" style="width:32%;background:rgba(129,140,248,0.20)">
<span class="rl-zoom-bar__name">Month</span>
</div>
<span class="rl-zoom-bar__span">29.5 days</span>
<span class="rl-zoom-bar__span">~30 days</span>
</div>
<div class="rl-zoom-bar__row">
<span class="rl-zoom-bar__label">5</span>
<div class="rl-zoom-bar__bar" style="width:44%;background:rgba(167,139,250,0.20)">
<span class="rl-zoom-bar__name">Season</span>
</div>
<span class="rl-zoom-bar__span">~3 months</span>
</div>
<div class="rl-zoom-bar__row">
<span class="rl-zoom-bar__label">6</span>
<div class="rl-zoom-bar__bar" style="width:60%;background:rgba(99,102,241,0.16)">
<span class="rl-zoom-bar__name">Season</span>
</div>
<span class="rl-zoom-bar__span">~90 days</span>
</div>
<div class="rl-zoom-bar__row">
<span class="rl-zoom-bar__label">7</span>
<div class="rl-zoom-bar__bar" style="width:70%;background:rgba(99,102,241,0.14)">
<div class="rl-zoom-bar__bar" style="width:58%;background:rgba(167,139,250,0.18)">
<span class="rl-zoom-bar__name">Year</span>
</div>
<span class="rl-zoom-bar__span">365 days</span>
</div>
<div class="rl-zoom-bar__row">
<span class="rl-zoom-bar__label">8</span>
<div class="rl-zoom-bar__bar" style="width:85%;background:rgba(99,102,241,0.12)">
<span class="rl-zoom-bar__name">Epoch</span>
<span class="rl-zoom-bar__label">7</span>
<div class="rl-zoom-bar__bar" style="width:72%;background:rgba(192,132,252,0.18)">
<span class="rl-zoom-bar__name">Decade</span>
</div>
<span class="rl-zoom-bar__span">decades&ndash;centuries</span>
<span class="rl-zoom-bar__span">10 years</span>
</div>
<div class="rl-zoom-bar__row">
<span class="rl-zoom-bar__label">8</span>
<div class="rl-zoom-bar__bar" style="width:86%;background:rgba(168,85,247,0.16)">
<span class="rl-zoom-bar__name">Century</span>
</div>
<span class="rl-zoom-bar__span">100 years</span>
</div>
<div class="rl-zoom-bar__row">
<span class="rl-zoom-bar__label">9</span>
<div class="rl-zoom-bar__bar" style="width:100%;background:rgba(99,102,241,0.10)">
<div class="rl-zoom-bar__bar" style="width:100%;background:rgba(147,51,234,0.15)">
<span class="rl-zoom-bar__name">Cosmic</span>
</div>
<span class="rl-zoom-bar__span">geological</span>
<span class="rl-zoom-bar__span">Geological</span>
</div>
</div>
</div>
@ -156,31 +206,63 @@ export function renderLanding(): string {
<!-- Calendar Views -->
<section class="rl-section rl-section--alt">
<div class="rl-container">
<h2 class="rl-heading" style="text-align:center">Four views</h2>
<div class="rl-grid-4" style="margin-top:2rem">
<div class="rl-card rl-card--center">
<div class="rl-icon-box"><span style="font-size:1.25rem">&#128197;</span></div>
<h3>Temporal</h3>
<p>Classic calendar grid &mdash; day, week, month. The view you know.</p>
<p style="font-size:0.7rem;color:#64748b;margin-top:0.5rem"><kbd style="background:rgba(255,255,255,0.1);padding:0.1rem 0.3rem;border-radius:3px;font-size:0.65rem">T</kbd> to switch</p>
<span class="rl-tagline" style="color:#a78bfa;background:rgba(167,139,250,0.1);border-color:rgba(167,139,250,0.2)">
Four Views
</span>
<h2 class="rl-heading" style="background:linear-gradient(135deg,#a78bfa,#c084fc);-webkit-background-clip:text;-webkit-text-fill-color:transparent;background-clip:text">
One calendar, four perspectives
</h2>
<p class="rl-subtext">
Switch between views with keyboard shortcuts (1&ndash;4) to see your events from the angle that matters most right now.
</p>
<div class="rl-grid-2" style="margin-top:2rem">
<div class="rl-card">
<div style="display:flex;align-items:center;gap:0.75rem;margin-bottom:1rem">
<div style="width:2.5rem;height:2.5rem;border-radius:0.75rem;background:rgba(59,130,246,0.12);display:flex;align-items:center;justify-content:center;font-size:1.1rem">
&#128197;
</div>
<div>
<h3 style="margin-bottom:0">Temporal</h3>
<span style="font-size:0.7rem;color:#64748b;font-family:monospace">Press 1</span>
</div>
</div>
<p>The classic calendar view &mdash; month, week, day, year, and season &mdash; enhanced with multi-granularity zoom and event indicators.</p>
</div>
<div class="rl-card rl-card--center">
<div class="rl-icon-box"><span style="font-size:1.25rem">&#128506;</span></div>
<h3>Spatial</h3>
<p>Map view with events pinned to locations. Zoom couples time and space.</p>
<p style="font-size:0.7rem;color:#64748b;margin-top:0.5rem"><kbd style="background:rgba(255,255,255,0.1);padding:0.1rem 0.3rem;border-radius:3px;font-size:0.65rem">S</kbd> to switch</p>
<div class="rl-card">
<div style="display:flex;align-items:center;gap:0.75rem;margin-bottom:1rem">
<div style="width:2.5rem;height:2.5rem;border-radius:0.75rem;background:rgba(52,211,153,0.12);display:flex;align-items:center;justify-content:center;font-size:1.1rem">
&#128506;
</div>
<div>
<h3 style="margin-bottom:0">Spatial</h3>
<span style="font-size:0.7rem;color:#64748b;font-family:monospace">Press 2</span>
</div>
</div>
<p>Interactive map powered by Leaflet. Events cluster by location with nine spatial granularity levels from planet to GPS coordinates.</p>
</div>
<div class="rl-card rl-card--center">
<div class="rl-icon-box"><span style="font-size:1.25rem">&#127769;</span></div>
<h3>Lunar</h3>
<p>Moon-phase overlay with illumination percentages. Plan with natural rhythms.</p>
<p style="font-size:0.7rem;color:#64748b;margin-top:0.5rem"><kbd style="background:rgba(255,255,255,0.1);padding:0.1rem 0.3rem;border-radius:3px;font-size:0.65rem">L</kbd> to switch</p>
<div class="rl-card">
<div style="display:flex;align-items:center;gap:0.75rem;margin-bottom:1rem">
<div style="width:2.5rem;height:2.5rem;border-radius:0.75rem;background:rgba(245,158,11,0.12);display:flex;align-items:center;justify-content:center;font-size:1.1rem">
&#127769;
</div>
<div>
<h3 style="margin-bottom:0">Lunar</h3>
<span style="font-size:0.7rem;color:#64748b;font-family:monospace">Press 3</span>
</div>
</div>
<p>Moon phase overlay with illumination percentages, eclipse detection, and phase-colored day cells. Plan around the eight phases of the lunar cycle.</p>
</div>
<div class="rl-card rl-card--center">
<div class="rl-icon-box"><span style="font-size:1.25rem">&#129513;</span></div>
<h3>Context</h3>
<p>Events grouped by r* source module. See your rWork sprints next to rVote deadlines.</p>
<p style="font-size:0.7rem;color:#64748b;margin-top:0.5rem"><kbd style="background:rgba(255,255,255,0.1);padding:0.1rem 0.3rem;border-radius:3px;font-size:0.65rem">C</kbd> to switch</p>
<div class="rl-card">
<div style="display:flex;align-items:center;gap:0.75rem;margin-bottom:1rem">
<div style="width:2.5rem;height:2.5rem;border-radius:0.75rem;background:rgba(34,211,238,0.12);display:flex;align-items:center;justify-content:center;font-size:1.1rem">
&#129513;
</div>
<div>
<h3 style="margin-bottom:0">Context</h3>
<span style="font-size:0.7rem;color:#64748b;font-family:monospace">Press 4</span>
</div>
</div>
<p>When embedded inside another r* tool, this view shows calendar data filtered for that tool&rsquo;s entity &mdash; a trip, a network, a map layer.</p>
</div>
</div>
</div>
@ -189,115 +271,78 @@ export function renderLanding(): string {
<!-- Ecosystem Integration -->
<section class="rl-section">
<div class="rl-container">
<h2 class="rl-heading" style="text-align:center">Ecosystem integration</h2>
<p class="rl-subtext" style="text-align:center">rCal pulls events from across the r* ecosystem automatically.</p>
<span class="rl-tagline" style="color:#34d399;background:rgba(52,211,153,0.1);border-color:rgba(52,211,153,0.2)">
Ecosystem
</span>
<h2 class="rl-heading" style="background:linear-gradient(135deg,#34d399,#22d3ee);-webkit-background-clip:text;-webkit-text-fill-color:transparent;background-clip:text">
Part of the r* stack
</h2>
<p class="rl-subtext">
rCal connects to the full suite of community tools. Any r* app can display or create calendar events through the shared context API.
</p>
<div class="rl-grid-3" style="margin-top:2rem">
<div class="rl-integration">
<div class="rl-icon-box" style="flex-shrink:0"><span style="font-size:1.25rem">&#9992;&#65039;</span></div>
<div>
<h3><a href="/rtrips" style="color:#e2e8f0;text-decoration:none">rTrips</a></h3>
<p>Travel itineraries appear as multi-day calendar events with location pins.</p>
</div>
</div>
<div class="rl-integration">
<div class="rl-integration" style="border-color:rgba(52,211,153,0.15)">
<div class="rl-icon-box" style="flex-shrink:0"><span style="font-size:1.25rem">&#128506;</span></div>
<div>
<h3><a href="/rmaps" style="color:#e2e8f0;text-decoration:none">rMaps</a></h3>
<p>Location-tagged events render on the spatial view map layer.</p>
<h3>rTrips</h3>
<p>Trip itineraries auto-populate with calendar events for departure, accommodation, and activities.</p>
</div>
</div>
<div class="rl-integration">
<div class="rl-integration" style="border-color:rgba(52,211,153,0.15)">
<div class="rl-icon-box" style="flex-shrink:0"><span style="font-size:1.25rem">&#128205;</span></div>
<div>
<h3>rMaps</h3>
<p>Location-tagged events appear on shared community maps with time-filtered layers.</p>
</div>
</div>
<div class="rl-integration" style="border-color:rgba(52,211,153,0.15)">
<div class="rl-icon-box" style="flex-shrink:0"><span style="font-size:1.25rem">&#128101;</span></div>
<div>
<h3><a href="/rnetwork" style="color:#e2e8f0;text-decoration:none">rNetwork</a></h3>
<p>Meeting events auto-link to participant profiles and relationship context.</p>
<h3>rNetwork</h3>
<p>See when your community members are available and schedule group meetings.</p>
</div>
</div>
<div class="rl-integration">
<div class="rl-integration" style="border-color:rgba(52,211,153,0.15)">
<div class="rl-icon-box" style="flex-shrink:0"><span style="font-size:1.25rem">&#128722;</span></div>
<div>
<h3><a href="/rcart" style="color:#e2e8f0;text-decoration:none">rCart</a></h3>
<p>Group-buy deadlines and fulfillment ETAs show up as calendar milestones.</p>
<h3>rCart</h3>
<p>Product launches, market days, and delivery windows sync to your calendar.</p>
</div>
</div>
<div class="rl-integration">
<div class="rl-integration" style="border-color:rgba(52,211,153,0.15)">
<div class="rl-icon-box" style="flex-shrink:0"><span style="font-size:1.25rem">&#128221;</span></div>
<div>
<h3><a href="/rnotes" style="color:#e2e8f0;text-decoration:none">rNotes</a></h3>
<p>Meeting notes link back to the calendar event that spawned them.</p>
<h3>rNotes</h3>
<p>Meeting notes link back to calendar events. Transcriptions attach to the moment they happened.</p>
</div>
</div>
<div class="rl-integration">
<div class="rl-integration" style="border-color:rgba(52,211,153,0.15)">
<div class="rl-icon-box" style="flex-shrink:0"><span style="font-size:1.25rem">&#127760;</span></div>
<div>
<h3><a href="/" style="color:#e2e8f0;text-decoration:none">rSpace</a></h3>
<p>Space-level milestones and deadlines aggregate across all modules into one timeline.</p>
<h3>rSpace</h3>
<p>Each space gets its own calendar. Subdomain routing means each community has a dedicated view.</p>
</div>
</div>
</div>
</div>
</section>
<!-- Built on Open Source -->
<section class="rl-section rl-section--alt">
<div class="rl-container">
<h2 class="rl-heading" style="text-align:center">Built on Open Source</h2>
<p class="rl-subtext" style="text-align:center">The libraries and tools that power rCal.</p>
<div class="rl-grid-3">
<div class="rl-card rl-card--center">
<div class="rl-icon-box">&#128451;</div>
<h3>PostgreSQL</h3>
<p>Rock-solid relational database for events, sources, locations, and calendar metadata.</p>
</div>
<div class="rl-card rl-card--center">
<div class="rl-icon-box">&#128663;</div>
<h3>OSRM</h3>
<p>Open-source routing engine for location-based scheduling, travel times, and spatial queries.</p>
</div>
<div class="rl-card rl-card--center">
<div class="rl-icon-box">&#128293;</div>
<h3>Hono</h3>
<p>Ultrafast web framework for the API layer. Lightweight, edge-ready, and built for speed.</p>
</div>
</div>
</div>
</section>
<!-- Your Data, Protected -->
<section class="rl-section">
<div class="rl-container" style="text-align:center">
<h2 class="rl-heading">Your Data, Protected</h2>
<p class="rl-subtext">How rCal keeps your information safe.</p>
<div class="rl-grid-3">
<div class="rl-card rl-card--center">
<div class="rl-icon-box">&#128274;</div>
<h3>End-to-End Encryption</h3>
<span class="rl-badge">Coming Soon</span>
<p>All content encrypted before it leaves your device. Not even the server can read it.</p>
</div>
<div class="rl-card rl-card--center">
<div class="rl-icon-box">&#128373;</div>
<h3>Zero-Knowledge Architecture</h3>
<span class="rl-badge">Coming Soon</span>
<p>The server processes your requests without ever seeing your data in the clear.</p>
</div>
<div class="rl-card rl-card--center">
<div class="rl-icon-box">&#127968;</div>
<h3>Self-Hosted</h3>
<p>Run on your own infrastructure. Your server, your rules, your data.</p>
</div>
</div>
</div>
</section>
<!-- CTA -->
<section class="rl-section rl-section--alt">
<div class="rl-container" style="text-align:center">
<h2 class="rl-heading">(You)rCal, your rhythm.</h2>
<p class="rl-subtext">Try the demo or create a space to get started.</p>
<h2 class="rl-heading" style="background:linear-gradient(to right,#60a5fa,#818cf8,#a78bfa);-webkit-background-clip:text;-webkit-text-fill-color:transparent;background-clip:text">
See time differently
</h2>
<p class="rl-subtext">
Try the spatiotemporal calendar with lunar overlays, multi-source sync, and community sharing.
No account needed for the demo.
</p>
<div class="rl-cta-row">
<a href="https://demo.rspace.online/rcal" class="rl-cta-primary">Open Calendar</a>
<a href="/create-space" class="rl-cta-secondary">Create a Space</a>
<a href="https://demo.rspace.online/rcal" class="rl-cta-primary"
style="background:linear-gradient(to right,#60a5fa,#6366f1);color:#0b1120">
Open the Demo
</a>
<a href="https://rstack.online" class="rl-cta-secondary">Explore rStack</a>
</div>
</div>
</section>

View File

@ -1,165 +1,198 @@
/**
* rChoices rich landing page body.
* Returned by landingPage() in the module export;
* the shell wraps it with header, CSS, and analytics.
* rChoices landing page quick collaborative decisions.
* Ported from the Next.js page.tsx. Interactive React demos (SpiderDemo,
* RankingDemo, VotingDemo) replaced with text descriptions.
*/
export function renderLanding(): string {
return `
return `
<!-- Hero -->
<div class="rl-hero">
<span class="rl-tagline">rChoices</span>
<h1 class="rl-heading">(You)rChoices, your voice.</h1>
<p class="rl-subtitle">Decide Together, Fairly</p>
<span class="rl-tagline">Quick collaborative decisions</span>
<h1 class="rl-heading">What should <span style="color:#5eead4">5 friends</span><br>do tonight?</h1>
<p class="rl-subtext">
Quadratic voting, ranked choice, and multi-criteria scoring &mdash; all as
interactive shapes on your canvas. Drop a choice, let members vote,
watch results emerge in real time.
Spider plots to weigh trade-offs. Rankings to sort preferences.
Live voting to decide fast. Powered by rSpace real-time sync.
</p>
<div class="rl-cta-row">
<a href="https://demo.rspace.online/rchoices" class="rl-cta-primary" id="ml-primary">Start Deciding</a>
<a href="https://demo.rspace.online/rchoices" class="rl-cta-primary" id="ml-primary">Create a Choice Room</a>
<a href="/create-space" class="rl-cta-secondary">Create a Space</a>
</div>
</div>
<!-- Features -->
<!-- Three tools -->
<section class="rl-section">
<div class="rl-container">
<h2 class="rl-heading" style="text-align:center">What rChoices Handles</h2>
<div class="rl-grid-4">
<div class="rl-card rl-card--center">
<div class="rl-icon-box">&#9878;</div>
<h3>Quadratic Voting</h3>
<p>Express intensity of preference. The cost of additional votes grows exponentially, balancing passion with fairness.</p>
<h2 class="rl-heading" style="text-align:center">Three decision tools</h2>
<div class="rl-grid-3">
<!-- Spider Plots -->
<div class="rl-card">
<div style="display:flex;align-items:center;gap:0.5rem;margin-bottom:0.5rem">
<span style="font-size:0.7rem;padding:0.2rem 0.6rem;border-radius:9999px;background:rgba(168,85,247,0.1);color:#c084fc">Compare</span>
</div>
<h3 style="font-size:1.05rem;margin-bottom:0.35rem">Spider Plots</h3>
<p>Everyone rates options on multiple criteria. See where preferences
overlap &mdash; and where they don&rsquo;t.</p>
<div style="margin-top:1rem;padding:1rem;border-radius:0.75rem;background:rgba(168,85,247,0.05);border:1px solid rgba(168,85,247,0.1);text-align:center">
<svg width="120" height="100" viewBox="0 0 120 100" style="margin:0 auto;display:block">
<!-- Spider web axes -->
<line x1="60" y1="10" x2="60" y2="90" stroke="#334155" stroke-width="0.5"/>
<line x1="17" y1="35" x2="103" y2="65" stroke="#334155" stroke-width="0.5"/>
<line x1="17" y1="65" x2="103" y2="35" stroke="#334155" stroke-width="0.5"/>
<!-- Outer ring -->
<polygon points="60,10 103,35 103,65 60,90 17,65 17,35" fill="none" stroke="#334155" stroke-width="0.5"/>
<!-- Mid ring -->
<polygon points="60,30 88,42 88,58 60,70 32,58 32,42" fill="none" stroke="#334155" stroke-width="0.5"/>
<!-- Data shape 1 (purple) -->
<polygon points="60,18 96,38 90,62 60,78 28,55 25,38" fill="rgba(168,85,247,0.15)" stroke="#c084fc" stroke-width="1.5"/>
<!-- Data shape 2 (teal) -->
<polygon points="60,25 85,45 98,58 60,72 35,60 22,42" fill="rgba(20,184,166,0.15)" stroke="#14b8a6" stroke-width="1.5"/>
<!-- Axis labels -->
<text x="60" y="6" text-anchor="middle" fill="#64748b" font-size="7">Price</text>
<text x="110" y="34" text-anchor="start" fill="#64748b" font-size="7">Vibe</text>
<text x="110" y="70" text-anchor="start" fill="#64748b" font-size="7">Menu</text>
<text x="60" y="98" text-anchor="middle" fill="#64748b" font-size="7">Distance</text>
<text x="10" y="70" text-anchor="end" fill="#64748b" font-size="7">Speed</text>
<text x="10" y="34" text-anchor="end" fill="#64748b" font-size="7">Reviews</text>
</svg>
<p style="font-size:0.7rem;color:#64748b;margin-top:0.5rem">Multi-criteria comparison at a glance</p>
</div>
</div>
<div class="rl-card rl-card--center">
<div class="rl-icon-box">&#128203;</div>
<h3>Ranked Choice Voting</h3>
<p>Order preferences from first to last. Instant-runoff tabulation finds the option with the broadest support.</p>
<!-- Rankings -->
<div class="rl-card">
<div style="display:flex;align-items:center;gap:0.5rem;margin-bottom:0.5rem">
<span style="font-size:0.7rem;padding:0.2rem 0.6rem;border-radius:9999px;background:rgba(245,158,11,0.1);color:#fbbf24">Rank</span>
</div>
<h3 style="font-size:1.05rem;margin-bottom:0.35rem">Rankings</h3>
<p>Drag to order your top picks. Borda count or instant-runoff finds
the group&rsquo;s true consensus.</p>
<div style="margin-top:1rem;padding:0.75rem;border-radius:0.75rem;background:rgba(245,158,11,0.05);border:1px solid rgba(245,158,11,0.1)">
<div style="display:flex;flex-direction:column;gap:0.4rem">
<div style="display:flex;align-items:center;gap:0.5rem;padding:0.4rem 0.6rem;border-radius:0.375rem;background:rgba(245,158,11,0.12);border:1px solid rgba(245,158,11,0.2)">
<span style="font-size:0.7rem;font-weight:700;color:#fbbf24;width:1.2rem">1st</span>
<span style="font-size:0.8rem;color:#e2e8f0">Thai place on 5th</span>
</div>
<div style="display:flex;align-items:center;gap:0.5rem;padding:0.4rem 0.6rem;border-radius:0.375rem;background:rgba(255,255,255,0.03);border:1px solid rgba(255,255,255,0.06)">
<span style="font-size:0.7rem;font-weight:700;color:#94a3b8;width:1.2rem">2nd</span>
<span style="font-size:0.8rem;color:#e2e8f0">New pizza spot</span>
</div>
<div style="display:flex;align-items:center;gap:0.5rem;padding:0.4rem 0.6rem;border-radius:0.375rem;background:rgba(255,255,255,0.03);border:1px solid rgba(255,255,255,0.06)">
<span style="font-size:0.7rem;font-weight:700;color:#94a3b8;width:1.2rem">3rd</span>
<span style="font-size:0.8rem;color:#e2e8f0">Taco truck</span>
</div>
<div style="display:flex;align-items:center;gap:0.5rem;padding:0.4rem 0.6rem;border-radius:0.375rem;background:rgba(255,255,255,0.03);border:1px solid rgba(255,255,255,0.06)">
<span style="font-size:0.7rem;font-weight:700;color:#94a3b8;width:1.2rem">4th</span>
<span style="font-size:0.8rem;color:#e2e8f0">Sushi bar</span>
</div>
</div>
<p style="font-size:0.7rem;color:#64748b;margin-top:0.5rem;text-align:center">Drag to reorder &mdash; consensus emerges</p>
</div>
</div>
<div class="rl-card rl-card--center">
<div class="rl-icon-box">&#128260;</div>
<h3>CRDT-Based Shared State</h3>
<p>Automerge CRDTs keep all participants in sync &mdash; no conflicts, no lost votes, even offline.</p>
</div>
<div class="rl-card rl-card--center">
<div class="rl-icon-box">&#9889;</div>
<h3>Real-Time Collaboration</h3>
<p>Tallies, rankings, and spider charts update live as members vote. Results emerge instantly.</p>
<!-- Live Voting -->
<div class="rl-card">
<div style="display:flex;align-items:center;gap:0.5rem;margin-bottom:0.5rem">
<span style="font-size:0.7rem;padding:0.2rem 0.6rem;border-radius:9999px;background:rgba(34,211,238,0.1);color:#22d3ee">Vote</span>
</div>
<h3 style="font-size:1.05rem;margin-bottom:0.35rem">Live Voting</h3>
<p>Cast your vote and watch results shift in real time. Perfect for
quick polls and tiebreakers.</p>
<div style="margin-top:1rem;padding:0.75rem;border-radius:0.75rem;background:rgba(34,211,238,0.05);border:1px solid rgba(34,211,238,0.1)">
<div style="display:flex;flex-direction:column;gap:0.5rem">
<div>
<div style="display:flex;justify-content:space-between;font-size:0.75rem;margin-bottom:0.25rem">
<span style="color:#e2e8f0">Hike</span>
<span style="color:#22d3ee;font-weight:600">45%</span>
</div>
<div style="height:0.4rem;border-radius:9999px;background:rgba(255,255,255,0.06);overflow:hidden">
<div style="height:100%;width:45%;border-radius:9999px;background:#22d3ee"></div>
</div>
</div>
<div>
<div style="display:flex;justify-content:space-between;font-size:0.75rem;margin-bottom:0.25rem">
<span style="color:#e2e8f0">Beach</span>
<span style="color:#22d3ee;font-weight:600">35%</span>
</div>
<div style="height:0.4rem;border-radius:9999px;background:rgba(255,255,255,0.06);overflow:hidden">
<div style="height:100%;width:35%;border-radius:9999px;background:#22d3ee"></div>
</div>
</div>
<div>
<div style="display:flex;justify-content:space-between;font-size:0.75rem;margin-bottom:0.25rem">
<span style="color:#e2e8f0">Stay in</span>
<span style="color:#22d3ee;font-weight:600">20%</span>
</div>
<div style="height:0.4rem;border-radius:9999px;background:rgba(255,255,255,0.06);overflow:hidden">
<div style="height:100%;width:20%;border-radius:9999px;background:#22d3ee"></div>
</div>
</div>
</div>
<p style="font-size:0.7rem;color:#64748b;margin-top:0.5rem;text-align:center">Results update live &mdash; 9 votes in</p>
</div>
</div>
</div>
</div>
</section>
<!-- How It Works -->
<!-- How it works -->
<section class="rl-section rl-section--alt">
<div class="rl-container">
<h2 class="rl-heading" style="text-align:center">How It Works</h2>
<h2 class="rl-heading" style="text-align:center">How it works</h2>
<div class="rl-grid-3">
<div class="rl-step">
<div class="rl-step__num">1</div>
<h3>Create a Decision</h3>
<p>Pick a voting method, name it, and add options. The choice shape appears on the canvas.</p>
<h3>Create</h3>
<p>Name your choice room. It comes pre-loaded with vote, rank, and spider tools.</p>
</div>
<div class="rl-step">
<div class="rl-step__num">2</div>
<h3>Add Options &amp; Invite Voters</h3>
<p>Space members interact with the shape to cast votes, rank preferences, or score criteria.</p>
<h3>Share</h3>
<p>Send the link. Everyone joins the same real-time canvas &mdash; add options, cast votes.</p>
</div>
<div class="rl-step">
<div class="rl-step__num">3</div>
<h3>Results Calculated Fairly in Real Time</h3>
<p>Live tallies update as votes arrive. View charts, rankings, and spider diagrams instantly.</p>
<h3>Decide</h3>
<p>Results aggregate live. The group sees consensus emerge in seconds.</p>
</div>
</div>
</div>
</section>
<!-- Voting Methods -->
<!-- Use cases -->
<section class="rl-section">
<div class="rl-container">
<h2 class="rl-heading" style="text-align:center">Voting Methods</h2>
<h2 class="rl-heading" style="text-align:center">Decisions, not debates</h2>
<p class="rl-subtext" style="text-align:center">
Three powerful mechanisms, each designed for different decision contexts.
Built for the everyday choices that stall group chats
</p>
<div class="rl-grid-3">
<div class="rl-card rl-card--center">
<div class="rl-icon-box">&#9878;</div>
<h3>Quadratic Voting</h3>
<p>Express intensity of preference. The cost of additional votes on one option grows exponentially, balancing passion with fairness.</p>
<div class="rl-grid-2" style="margin-top:2rem">
<div class="rl-card">
<h3 style="margin-bottom:0.35rem">Where to eat?</h3>
<p>Rate restaurants on price, distance, vibe. The spider plot finds the sweet spot.</p>
</div>
<div class="rl-card rl-card--center">
<div class="rl-icon-box">&#128203;</div>
<h3>Ranked Choice</h3>
<p>Order your preferences from first to last. Instant-runoff tabulation finds the option with the broadest support.</p>
<div class="rl-card">
<h3 style="margin-bottom:0.35rem">What to watch?</h3>
<p>Everyone ranks their top 3 movies. Instant-runoff picks the winner.</p>
</div>
<div class="rl-card rl-card--center">
<div class="rl-icon-box">&#128376;</div>
<h3>Multi-Criteria Scoring</h3>
<p>Score options across weighted attributes. Spider diagrams reveal trade-offs at a glance.</p>
<div class="rl-card">
<h3 style="margin-bottom:0.35rem">Weekend plans?</h3>
<p>Quick poll: hike, beach, or stay in? Results in 30 seconds.</p>
</div>
</div>
</div>
</section>
<!-- Built on Open Source -->
<section class="rl-section">
<div class="rl-container">
<h2 class="rl-heading" style="text-align:center">Built on Open Source</h2>
<p class="rl-subtext" style="text-align:center">The libraries and tools that power rChoices.</p>
<div class="rl-grid-3">
<div class="rl-card rl-card--center">
<div class="rl-icon-box">&#128260;</div>
<h3>Automerge</h3>
<p>Conflict-free replicated data types for shared state &mdash; real-time sync without merge conflicts.</p>
</div>
<div class="rl-card rl-card--center">
<div class="rl-icon-box">&#128451;</div>
<h3>PostgreSQL</h3>
<p>Reliable relational storage for decisions, vote records, and result history.</p>
</div>
<div class="rl-card rl-card--center">
<div class="rl-icon-box">&#9889;</div>
<h3>Hono</h3>
<p>Ultrafast web framework for the API layer &mdash; lightweight, typed, and edge-ready.</p>
</div>
</div>
</div>
</section>
<!-- Your Data, Protected -->
<section class="rl-section rl-section--alt">
<div class="rl-container" style="text-align:center">
<h2 class="rl-heading">Your Data, Protected</h2>
<p class="rl-subtext">How rChoices keeps your information safe.</p>
<div class="rl-grid-3">
<div class="rl-card rl-card--center">
<div class="rl-icon-box">&#128274;</div>
<h3>End-to-End Encryption</h3>
<span class="rl-badge">Coming Soon</span>
<p>All content encrypted before it leaves your device. Not even the server can read it.</p>
</div>
<div class="rl-card rl-card--center">
<div class="rl-icon-box">&#128373;</div>
<h3>Zero-Knowledge Architecture</h3>
<span class="rl-badge">Coming Soon</span>
<p>The server processes your requests without ever seeing your data in the clear.</p>
</div>
<div class="rl-card rl-card--center">
<div class="rl-icon-box">&#127968;</div>
<h3>Self-Hosted</h3>
<p>Run on your own infrastructure. Your server, your rules, your data.</p>
<div class="rl-card">
<h3 style="margin-bottom:0.35rem">Team retro priorities?</h3>
<p>Rank improvement ideas by impact. Borda count surfaces what the team really wants.</p>
</div>
</div>
</div>
</section>
<!-- CTA -->
<section class="rl-section">
<section class="rl-section rl-section--alt">
<div class="rl-container" style="text-align:center">
<h2 class="rl-heading">(You)rChoices, your voice.</h2>
<p class="rl-subtext">Try the demo or create a space to get started.</p>
<h2 class="rl-heading">What should 5 friends do tonight?</h2>
<p class="rl-subtext">Create a room and find out in 30 seconds.</p>
<div class="rl-cta-row">
<a href="https://demo.rspace.online/rchoices" class="rl-cta-primary">Start Deciding</a>
<a href="https://demo.rspace.online/rchoices" class="rl-cta-primary">Create a Choice Room</a>
<a href="/create-space" class="rl-cta-secondary">Create a Space</a>
</div>
</div>

View File

@ -1,5 +1,6 @@
/**
* Forum module landing page static HTML, no React.
* rForum landing page Discourse forum provisioning.
* Ported from /opt/apps/rforum-online/src/app/page.tsx
*/
export function renderLanding(): string {
return `
@ -18,61 +19,41 @@ export function renderLanding(): string {
</div>
</div>
<!-- Features -->
<section class="rl-section">
<div class="rl-container">
<h2 class="rl-heading" style="text-align:center">What rForum Handles</h2>
<div class="rl-grid-4">
<div class="rl-card rl-card--center">
<div class="rl-icon-box">&#9881;</div>
<h3>Automated Provisioning</h3>
<p>One-click Discourse deployment. Server creation, installation, and configuration handled automatically.</p>
</div>
<div class="rl-card rl-card--center">
<div class="rl-icon-box">&#9729;</div>
<h3>Cloud VPS Deployment</h3>
<p>Deploy on Hetzner Cloud in Germany, Finland, or the US. Transparent pricing with no markup.</p>
</div>
<div class="rl-card rl-card--center">
<div class="rl-icon-box">&#127760;</div>
<h3>DNS Integration</h3>
<p>Automatic DNS setup for your subdomain via Cloudflare. SSL certificates provisioned with Let's Encrypt.</p>
</div>
<div class="rl-card rl-card--center">
<div class="rl-icon-box">&#128736;</div>
<h3>No DevOps Required</h3>
<p>No command line, no SSH &mdash; just fill in your settings and watch your forum come online.</p>
</div>
</div>
</div>
</section>
<!-- How It Works -->
<section class="rl-section rl-section--alt">
<section class="rl-section">
<div class="rl-container">
<h2 class="rl-heading" style="text-align:center">How It Works</h2>
<div class="rl-grid-3">
<div class="rl-step">
<div class="rl-step__num">1</div>
<h3>Configure</h3>
<p>Choose your subdomain, server region, and instance size. Add SMTP credentials for email delivery. Set your admin email.</p>
<div class="rl-card rl-card--center">
<div class="rl-icon-box" style="background:rgba(99,102,241,0.15)">
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#818cf8" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M10.325 4.317c.426-1.756 2.924-1.756 3.35 0a1.724 1.724 0 002.573 1.066c1.543-.94 3.31.826 2.37 2.37a1.724 1.724 0 001.066 2.573c1.756.426 1.756 2.924 0 3.35a1.724 1.724 0 00-1.066 2.573c.94 1.543-.826 3.31-2.37 2.37a1.724 1.724 0 00-2.573 1.066c-.426 1.756-2.924 1.756-3.35 0a1.724 1.724 0 00-2.573-1.066c-1.543.94-3.31-.826-2.37-2.37a1.724 1.724 0 00-1.066-2.573c-1.756-.426-1.756-2.924 0-3.35a1.724 1.724 0 001.066-2.573c-.94-1.543.826-3.31 2.37-2.37.996.608 2.296.07 2.572-1.065z"/><circle cx="12" cy="12" r="3"/></svg>
</div>
<h3>1. Configure</h3>
<p>Choose your subdomain, server region, and instance size.
Add SMTP credentials for email delivery. Set your admin email.</p>
</div>
<div class="rl-step">
<div class="rl-step__num">2</div>
<h3>Provision</h3>
<p>We create a cloud server on Hetzner, install Discourse, configure SSL via Let's Encrypt, and set up DNS. Takes about 10-15 minutes.</p>
<div class="rl-card rl-card--center">
<div class="rl-icon-box" style="background:rgba(139,92,246,0.15)">
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#a78bfa" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M5 12h14M12 5l7 7-7 7"/></svg>
</div>
<h3>2. Provision</h3>
<p>We create a cloud server on Hetzner, install Discourse,
configure SSL via Let's Encrypt, and set up DNS. Takes about 10-15 minutes.</p>
</div>
<div class="rl-step">
<div class="rl-step__num">3</div>
<h3>Go Live</h3>
<p>Your forum is ready. Log in as admin, customize your community, invite members, and start conversations. Full SSH access included.</p>
<div class="rl-card rl-card--center">
<div class="rl-icon-box" style="background:rgba(168,85,247,0.15)">
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#c084fc" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M13 10V3L4 14h7v7l9-11h-7z"/></svg>
</div>
<h3>3. Go Live</h3>
<p>Your forum is ready. Log in as admin, customize your community,
invite members, and start conversations. Full SSH access included.</p>
</div>
</div>
</div>
</section>
<!-- Pricing -->
<section class="rl-section" id="pricing">
<section class="rl-section rl-section--alt" id="pricing">
<div class="rl-container">
<h2 class="rl-heading" style="text-align:center">Transparent Pricing</h2>
<p class="rl-subtext" style="text-align:center">
@ -132,31 +113,49 @@ export function renderLanding(): string {
</section>
<!-- What You Get -->
<section class="rl-section rl-section--alt">
<section class="rl-section">
<div class="rl-container">
<h2 class="rl-heading" style="text-align:center">What You Get</h2>
<div class="rl-grid-3" style="margin-top:2rem">
<div class="rl-card rl-card--center">
<div class="rl-icon-box" style="background:rgba(99,102,241,0.12)">
<svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="#818cf8" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z"/></svg>
</div>
<h3>Automated SSL</h3>
<p>Let's Encrypt certificates provisioned automatically during setup.</p>
</div>
<div class="rl-card rl-card--center">
<div class="rl-icon-box" style="background:rgba(99,102,241,0.12)">
<svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="#818cf8" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><line x1="2" y1="12" x2="22" y2="12"/><path d="M12 2a15.3 15.3 0 014 10 15.3 15.3 0 01-4 10 15.3 15.3 0 01-4-10 15.3 15.3 0 014-10z"/></svg>
</div>
<h3>Multiple Regions</h3>
<p>Deploy in Germany, Finland, or the US East/West Coast.</p>
</div>
<div class="rl-card rl-card--center">
<div class="rl-icon-box" style="background:rgba(99,102,241,0.12)">
<svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="#818cf8" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><rect x="2" y="4" width="20" height="16" rx="2"/><path d="M7 15l3-3 3 3"/><path d="M8 8h.01M12 8h.01"/></svg>
</div>
<h3>Full SSH Access</h3>
<p>Your server, your rules. SSH in anytime for custom configuration.</p>
</div>
<div class="rl-card rl-card--center">
<div class="rl-icon-box" style="background:rgba(99,102,241,0.12)">
<svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="#818cf8" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><polyline points="17 1 21 5 17 9"/><path d="M3 11V9a4 4 0 014-4h14"/><polyline points="7 23 3 19 7 15"/><path d="M21 13v2a4 4 0 01-4 4H3"/></svg>
</div>
<h3>One-Click Updates</h3>
<p>Discourse's built-in admin panel handles version upgrades.</p>
</div>
<div class="rl-card rl-card--center">
<div class="rl-icon-box" style="background:rgba(99,102,241,0.12)">
<svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="#818cf8" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M21 12a9 9 0 01-9 9m9-9a9 9 0 00-9-9m9 9H3m9 9a9 9 0 01-9-9m9 9c1.657 0 3-4.03 3-9s-1.343-9-3-9m0 18c-1.657 0-3-4.03-3-9s1.343-9 3-9"/></svg>
</div>
<h3>DNS Management</h3>
<p>Automatic DNS setup for *.rforum.online subdomains.</p>
</div>
<div class="rl-card rl-card--center">
<div class="rl-icon-box" style="background:rgba(99,102,241,0.12)">
<svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="#818cf8" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><polyline points="22 12 18 12 15 21 9 3 6 12 2 12"/></svg>
</div>
<h3>Real-Time Logs</h3>
<p>Watch your forum provision step-by-step in the dashboard.</p>
</div>
@ -165,24 +164,36 @@ export function renderLanding(): string {
</section>
<!-- Built on Open Source -->
<section class="rl-section">
<section class="rl-section rl-section--alt">
<div class="rl-container">
<h2 class="rl-heading" style="text-align:center">Built on Open Source</h2>
<p class="rl-subtext" style="text-align:center">The libraries and tools that power rForum.</p>
<div class="rl-grid-4">
<div class="rl-card rl-card--center">
<div class="rl-icon-box" style="background:rgba(139,92,246,0.12)">
<svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="#a78bfa" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M21 15a2 2 0 01-2 2H7l-4 4V5a2 2 0 012-2h14a2 2 0 012 2z"/></svg>
</div>
<h3>Discourse</h3>
<p>The world's most popular open-source forum platform.</p>
</div>
<div class="rl-card rl-card--center">
<div class="rl-icon-box" style="background:rgba(139,92,246,0.12)">
<svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="#a78bfa" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><rect x="2" y="2" width="20" height="8" rx="2" ry="2"/><rect x="2" y="14" width="20" height="8" rx="2" ry="2"/><line x1="6" y1="6" x2="6.01" y2="6"/><line x1="6" y1="18" x2="6.01" y2="18"/></svg>
</div>
<h3>Hetzner Cloud API</h3>
<p>Automated VPS provisioning in multiple regions.</p>
</div>
<div class="rl-card rl-card--center">
<div class="rl-icon-box" style="background:rgba(139,92,246,0.12)">
<svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="#a78bfa" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z"/></svg>
</div>
<h3>Cloudflare API</h3>
<p>DNS management and SSL termination.</p>
</div>
<div class="rl-card rl-card--center">
<div class="rl-icon-box" style="background:rgba(139,92,246,0.12)">
<svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="#a78bfa" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M13 10V3L4 14h7v7l9-11h-7z"/></svg>
</div>
<h3>Hono</h3>
<p>Ultra-fast, lightweight API framework powering the backend.</p>
</div>
@ -191,7 +202,7 @@ export function renderLanding(): string {
</section>
<!-- Your Data, Protected -->
<section class="rl-section rl-section--alt">
<section class="rl-section">
<div class="rl-container" style="text-align:center">
<h2 class="rl-heading">Your Data, Protected</h2>
<p class="rl-subtext">How rForum keeps your information safe.</p>
@ -218,12 +229,12 @@ export function renderLanding(): string {
</section>
<!-- CTA -->
<section class="rl-section">
<section class="rl-section rl-section--alt">
<div class="rl-container" style="text-align:center">
<h2 class="rl-heading">(You)rForum, your community.</h2>
<p class="rl-subtext">Try the demo or create a space to get started.</p>
<h2 class="rl-heading">Ready to launch your community?</h2>
<p class="rl-subtext">Deploy a production Discourse forum in under 15 minutes. No DevOps experience needed.</p>
<div class="rl-cta-row">
<a href="https://demo.rspace.online/rforum" class="rl-cta-primary">Get Started</a>
<a href="https://demo.rspace.online/rforum" class="rl-cta-primary">Launch Your Forum</a>
<a href="/create-space" class="rl-cta-secondary">Create a Space</a>
</div>
</div>
@ -231,6 +242,5 @@ export function renderLanding(): string {
<div class="rl-back">
<a href="/">&larr; Back to rSpace</a>
</div>
`;
</div>`;
}

View File

@ -1,5 +1,6 @@
/**
* rFunds rich landing page body.
* Ported from rfunds-online/app/page.tsx (Next.js/Tailwind).
* Returned by landingPage() in the module export;
* the shell wraps it with header, CSS, and analytics.
*/
@ -8,66 +9,107 @@ export function renderLanding(): string {
<!-- Hero -->
<div class="rl-hero">
<span class="rl-tagline">rFunds</span>
<h1 class="rl-heading">(You)rFunds, your flow.</h1>
<p class="rl-subtitle">Visualize Your Community's Money</p>
<p class="rl-subtext">
Budget flows, river visualization, and conviction funding.
Watch resources move through your community in real time.
<h1 class="rl-heading" style="background:linear-gradient(to right,#fcd34d,#6ee7b7,#93c5fd);-webkit-background-clip:text;-webkit-text-fill-color:transparent;background-clip:text">
Threshold-Based Flow Funding
</h1>
<p class="rl-subtext" style="font-size:1.25rem;max-width:48rem;margin:0 auto 2rem">
Design continuous funding flows that respond dynamically to threshold conditions.
Connect funnels, set overflow rules, and track outcomes in real-time.
</p>
<div class="rl-cta-row">
<a href="https://demo.rspace.online/rfunds" class="rl-cta-primary" id="ml-primary">View Flows</a>
<a href="/create-space" class="rl-cta-secondary">Create a Space</a>
<a href="https://demo.rspace.online/rfunds" class="rl-cta-secondary" id="ml-primary">Try the Demo</a>
<a href="/create-space" class="rl-cta-primary">Create Your Own</a>
</div>
</div>
<!-- Features -->
<!-- How It Works -->
<section class="rl-section">
<div class="rl-container">
<h2 class="rl-heading" style="text-align:center">What rFunds Handles</h2>
<div class="rl-grid-4">
<h2 class="rl-heading" style="text-align:center">How It Works</h2>
<div class="rl-grid-3">
<div class="rl-card rl-card--center">
<div class="rl-icon-box">&#127754;</div>
<h3>Budget Flow Visualization</h3>
<p>Animated flow diagram showing how funds move between pools, funnels, and outcomes in real time.</p>
<div style="width:3rem;height:3rem;background:rgba(245,158,11,0.2);border-radius:0.75rem;display:flex;align-items:center;justify-content:center;margin:0 auto 1rem">
<svg style="width:1.5rem;height:1.5rem;color:#fbbf24" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 4a1 1 0 011-1h16a1 1 0 011 1v2.586a1 1 0 01-.293.707l-6.414 6.414a1 1 0 00-.293.707V17l-4 4v-6.586a1 1 0 00-.293-.707L3.293 7.293A1 1 0 013 6.586V4z" />
</svg>
</div>
<h3>Create Funnels</h3>
<p>Each funnel represents a funding pool with three zones: overflow (above max),
healthy (between thresholds), and critical (below min). Set thresholds by
dragging handles.</p>
</div>
<div class="rl-card rl-card--center">
<div class="rl-icon-box">&#128202;</div>
<h3>Treasury Dashboards</h3>
<p>Full overview of balances, inflows, outflows, and historical transaction data for your community.</p>
<div style="width:3rem;height:3rem;background:rgba(16,185,129,0.2);border-radius:0.75rem;display:flex;align-items:center;justify-content:center;margin:0 auto 1rem">
<svg style="width:1.5rem;height:1.5rem;color:#34d399" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 7h8m0 0v8m0-8l-8 8-4-4-6 6" />
</svg>
</div>
<h3>Connect Flows</h3>
<p>Connect funnels with overflow edges (sideways) so excess funds automatically
route to other pools. Add spending edges (downward) to fund outcomes and
deliverables.</p>
</div>
<div class="rl-card rl-card--center">
<div class="rl-icon-box">&#128161;</div>
<h3>Conviction-Based Funding</h3>
<p>Continuous signaling lets community members express preferences that compound over time.</p>
</div>
<div class="rl-card rl-card--center">
<div class="rl-icon-box">&#128168;</div>
<h3>River Metaphor</h3>
<p>Named budget streams between funding pools with configurable rates, thresholds, and activation rules.</p>
<div style="width:3rem;height:3rem;background:rgba(59,130,246,0.2);border-radius:0.75rem;display:flex;align-items:center;justify-content:center;margin:0 auto 1rem">
<svg style="width:1.5rem;height:1.5rem;color:#60a5fa" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M14.752 11.168l-3.197-2.132A1 1 0 0010 9.87v4.263a1 1 0 001.555.832l3.197-2.132a1 1 0 000-1.664z" />
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M21 12a9 9 0 11-18 0 9 9 0 0118 0z" />
</svg>
</div>
<h3>Simulate &amp; Share</h3>
<p>Run simulations to see how funds flow through your system. Watch edge widths
scale proportionally. Save your space locally and share it with a link.</p>
</div>
</div>
</div>
</section>
<!-- How It Works -->
<!-- The Funnel Metaphor -->
<section class="rl-section rl-section--alt">
<div class="rl-container">
<h2 class="rl-heading" style="text-align:center">How It Works</h2>
<div class="rl-grid-3">
<div class="rl-step">
<div class="rl-step__num">1</div>
<h3>Connect Your Treasury</h3>
<p>Link funding pools and define budget streams with rates, thresholds, and allocation rules.</p>
</div>
<div class="rl-step">
<div class="rl-step__num">2</div>
<h3>Map Budget Flows Visually</h3>
<p>The river visualization animates budget movement in real time &mdash; deposits, withdrawals, and funnels.</p>
</div>
<div class="rl-step">
<div class="rl-step__num">3</div>
<h3>Decide Funding with Conviction</h3>
<p>Community members signal preferences through conviction funding. Resources flow where attention goes.</p>
<div style="background:rgba(30,41,59,0.3);border-radius:1rem;border:1px solid rgba(51,65,85,0.5);padding:2rem">
<h2 class="rl-heading" style="text-align:center;margin-bottom:2rem">The Funnel Metaphor</h2>
<div style="max-width:28rem;margin:0 auto;font-family:monospace;font-size:0.875rem;text-align:center">
<!-- Overflow Zone -->
<div style="color:#fbbf24">
<div style="background:rgba(245,158,11,0.1);border:1px solid rgba(245,158,11,0.3);border-radius:0.75rem 0.75rem 0 0;padding:0.75rem 2rem">
<div style="font-weight:600">OVERFLOW ZONE</div>
<div style="font-size:0.75rem;color:#fcd34d">Above MAX threshold</div>
<div style="font-size:0.75rem;color:rgba(252,211,77,0.7)">Excess funds redistribute to other funnels</div>
</div>
</div>
<!-- Max Threshold Line -->
<div style="font-size:0.75rem;color:#f59e0b;font-weight:700;border-bottom:2px dashed rgba(245,158,11,0.5);padding:0.25rem 0;background:rgba(245,158,11,0.05)">
-- MAX THRESHOLD --
</div>
<!-- Healthy Zone -->
<div style="color:#34d399">
<div style="background:rgba(16,185,129,0.1);border-left:1px solid rgba(16,185,129,0.3);border-right:1px solid rgba(16,185,129,0.3);padding:1rem 2rem">
<div style="font-weight:600">HEALTHY ZONE</div>
<div style="font-size:0.75rem;color:#6ee7b7">Normal operations</div>
<div style="font-size:0.75rem;color:rgba(110,231,183,0.7)">Full flow rate, balanced funding</div>
</div>
</div>
<!-- Min Threshold Line -->
<div style="font-size:0.75rem;color:#ef4444;font-weight:700;border-bottom:2px dashed rgba(239,68,68,0.5);padding:0.25rem 0;background:rgba(239,68,68,0.05)">
-- MIN THRESHOLD --
</div>
<!-- Critical Zone -->
<div style="color:#94a3b8">
<div style="background:rgba(51,65,85,0.3);border:1px solid rgba(71,85,105,0.3);border-radius:0 0 0.75rem 0.75rem;padding:0.75rem 2rem">
<div style="font-weight:600;color:#f87171">CRITICAL ZONE</div>
<div style="font-size:0.75rem;color:#fca5a5">Below MIN threshold</div>
<div style="font-size:0.75rem;color:#64748b">Outflow restricted, conservation mode</div>
</div>
</div>
</div>
</div>
</div>
@ -100,7 +142,7 @@ export function renderLanding(): string {
</section>
<!-- Built on Open Source -->
<section class="rl-section">
<section class="rl-section rl-section--alt">
<div class="rl-container">
<h2 class="rl-heading" style="text-align:center">Built on Open Source</h2>
<p class="rl-subtext" style="text-align:center">The libraries and tools that power rFunds.</p>
@ -125,7 +167,7 @@ export function renderLanding(): string {
</section>
<!-- Your Data, Protected -->
<section class="rl-section rl-section--alt">
<section class="rl-section">
<div class="rl-container" style="text-align:center">
<h2 class="rl-heading">Your Data, Protected</h2>
<p class="rl-subtext">How rFunds keeps your information safe.</p>
@ -152,13 +194,13 @@ export function renderLanding(): string {
</section>
<!-- CTA -->
<section class="rl-section">
<section class="rl-section rl-section--alt">
<div class="rl-container" style="text-align:center">
<h2 class="rl-heading">(You)rFunds, your flow.</h2>
<p class="rl-subtext">Try the demo or create a space to get started.</p>
<h2 class="rl-heading">Ready to design your funding flows?</h2>
<p class="rl-subtext">Start with the interactive demo or create your own space with custom funnels and connections.</p>
<div class="rl-cta-row">
<a href="https://demo.rspace.online/rfunds" class="rl-cta-primary">View Flows</a>
<a href="/create-space" class="rl-cta-secondary">Create a Space</a>
<a href="https://demo.rspace.online/rfunds" class="rl-cta-primary">Try the Demo</a>
<a href="/create-space" class="rl-cta-secondary">Create Your Own</a>
</div>
</div>
</section>

View File

@ -1,203 +1,188 @@
/**
* Inbox module landing page static HTML, no React.
* rInbox (rChats) landing page encrypted community chat.
* Ported from rchats-online Next.js page.tsx (shadcn/ui + Lucide).
*/
export function renderLanding(): string {
return `
return `
<!-- Hero -->
<div class="rl-hero">
<span class="rl-tagline">rInbox</span>
<h1 class="rl-heading" style="background:linear-gradient(135deg,#67e8f9,#93c5fd,#c4b5fd);-webkit-background-clip:text;background-clip:text">(You)rInbox, your team's voice.</h1>
<p class="rl-subtitle" style="background:linear-gradient(135deg,#67e8f9,#93c5fd,#c4b5fd);-webkit-background-clip:text;background-clip:text">Collaborative Multi-Sig Inbox</p>
<span class="rl-tagline">Part of the rSpace Ecosystem</span>
<h1 class="rl-heading">Encrypted<br>
<span style="background:linear-gradient(135deg,#3b82f6,#14b8a6);-webkit-background-clip:text;background-clip:text;color:transparent">Community Chat</span>
</h1>
<p class="rl-subtext">
A shared email client where teams read, discuss, and approve messages
together &mdash; with cryptographic multi-signature workflows before anything gets sent.
Secure messaging powered by <strong style="color:#e2e8f0">EncryptID passkeys</strong>.
No passwords, no seed phrases &mdash; just <strong style="color:#e2e8f0">hardware-backed encryption</strong> and
full data ownership for your community.
</p>
<div class="rl-cta-row">
<a href="https://demo.rspace.online/rinbox" class="rl-cta-primary" id="ml-primary">Open Inbox</a>
<a href="/create-space" class="rl-cta-secondary">Create a Space</a>
<a href="https://demo.rspace.online/rinbox" class="rl-cta-primary" id="ml-primary">
Try the Demo &rarr;
</a>
<a href="https://demo.rspace.online/rinbox" class="rl-cta-secondary">Get Started</a>
</div>
</div>
<!-- Features -->
<section class="rl-section">
<div class="rl-container">
<h2 class="rl-heading" style="text-align:center">What rInbox Handles</h2>
<div class="rl-grid-4">
<div class="rl-card rl-card--center">
<div class="rl-icon-box">&#128231;</div>
<h3>Shared Team Email</h3>
<p>Your team shares one real email address. Every member sees every thread in real time &mdash; no forwarding, no BCC chains.</p>
</div>
<div class="rl-card rl-card--center">
<div class="rl-icon-box">&#9989;</div>
<h3>Multi-Signature Approval</h3>
<p>Outbound emails require M-of-N cryptographic signatures before sending. Every approval is auditable &mdash; no rogue replies.</p>
</div>
<div class="rl-card rl-card--center">
<div class="rl-icon-box">&#128172;</div>
<h3>Threaded Discussions</h3>
<p>Comment on any thread privately before replying. Tag members, discuss strategy, and reach consensus alongside the original message.</p>
</div>
<div class="rl-card rl-card--center">
<div class="rl-icon-box">&#128273;</div>
<h3>Cryptographic Signing</h3>
<p>Every outbound message is cryptographically signed. Full audit trail of approvals, rejections, and edits.</p>
</div>
</div>
</div>
</section>
<!-- How It Works -->
<section class="rl-section rl-section--alt">
<div class="rl-container">
<h2 class="rl-heading" style="text-align:center">How It Works</h2>
<div style="text-align:center;margin-bottom:1.5rem">
<span class="rl-badge">How It Works</span>
<h2 class="rl-heading" style="margin-top:0.75rem">Secure Chat in 30 Seconds</h2>
<p class="rl-subtext">
<strong style="color:#3b82f6">Create a passkey</strong> on your device,
<strong style="color:#14b8a6">join a community</strong>, and
<strong style="color:#e2e8f0">chat with end-to-end encryption</strong>.
</p>
</div>
<div class="rl-grid-3">
<div class="rl-step">
<div class="rl-step__num">1</div>
<h3>Connect a Mailbox</h3>
<p>Your team shares one real email address. Every member sees every thread in real time &mdash; no forwarding, no lost context.</p>
<div class="rl-card" style="border:2px solid rgba(59,130,246,0.4);background:linear-gradient(135deg,rgba(59,130,246,0.1),rgba(59,130,246,0.05))">
<div style="display:flex;align-items:center;gap:0.5rem;margin-bottom:0.75rem">
<div style="height:2rem;width:2rem;border-radius:50%;background:#3b82f6;display:flex;align-items:center;justify-content:center">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 10V4a2 2 0 00-4 0v6"/><path d="M18 11a6 6 0 00-12 0v3"/><rect x="3" y="14" width="18" height="8" rx="2"/><line x1="12" y1="18" x2="12" y2="18"/></svg>
</div>
<h3 style="font-weight:700;font-size:1.125rem;color:#e2e8f0">1. Create a Passkey</h3>
</div>
<p style="font-size:0.875rem;color:#94a3b8;line-height:1.6">
Register with EncryptID using your device's biometrics or security key.
No passwords to remember or leak.
<strong style="color:#e2e8f0;display:block;margin-top:0.5rem">Your keys never leave your device.</strong>
</p>
</div>
<div class="rl-step">
<div class="rl-step__num">2</div>
<h3>Discuss Messages as a Team</h3>
<p>Comment on any thread privately before replying. Tag members, discuss strategy, and reach consensus alongside the original message.</p>
<div class="rl-card" style="border:2px solid rgba(20,184,166,0.4);background:linear-gradient(135deg,rgba(20,184,166,0.1),rgba(20,184,166,0.05))">
<div style="display:flex;align-items:center;gap:0.5rem;margin-bottom:0.75rem">
<div style="height:2rem;width:2rem;border-radius:50%;background:#14b8a6;display:flex;align-items:center;justify-content:center">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M16 21v-2a4 4 0 00-4-4H6a4 4 0 00-4-4v2"/><circle cx="9" cy="7" r="4"/><path d="M22 21v-2a4 4 0 00-3-3.87"/><path d="M16 3.13a4 4 0 010 7.75"/></svg>
</div>
<h3 style="font-weight:700;font-size:1.125rem;color:#e2e8f0">2. Join a Community</h3>
</div>
<p style="font-size:0.875rem;color:#94a3b8;line-height:1.6">
Create or join a community chat space. Invite members with role-based
access: viewers, participants, moderators, and admins.
<strong style="color:#e2e8f0;display:block;margin-top:0.5rem">One identity across all r* apps.</strong>
</p>
</div>
<div class="rl-step">
<div class="rl-step__num">3</div>
<h3>Approve and Send with Multi-Sig</h3>
<p>Outbound emails require M-of-N cryptographic signatures before sending. Every approval is auditable &mdash; no rogue replies.</p>
<div class="rl-card" style="border:2px solid rgba(100,116,139,0.4);background:linear-gradient(135deg,rgba(100,116,139,0.1),rgba(100,116,139,0.05))">
<div style="display:flex;align-items:center;gap:0.5rem;margin-bottom:0.75rem">
<div style="height:2rem;width:2rem;border-radius:50%;background:#64748b;display:flex;align-items:center;justify-content:center">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 15a2 2 0 01-2 2H7l-4 4V5a2 2 0 012-2h14a2 2 0 012 2z"/><rect x="9" y="9" width="6" height="1" rx="0.5"/></svg>
</div>
<h3 style="font-weight:700;font-size:1.125rem;color:#e2e8f0">3. Chat Securely</h3>
</div>
<p style="font-size:0.875rem;color:#94a3b8;line-height:1.6">
Messages are encrypted with keys derived from your passkey.
Only community members can read them.
<strong style="color:#e2e8f0;display:block;margin-top:0.5rem">True end-to-end encryption.</strong>
</p>
</div>
</div>
</div>
</section>
<!-- Collaboration Features -->
<!-- Features Row 1 -->
<section class="rl-section">
<div class="rl-container">
<h2 class="rl-heading" style="text-align:center">Collaboration Features</h2>
<p class="rl-subtext" style="text-align:center">Built for collective intelligence, not individual productivity.</p>
<div class="rl-grid-2" style="margin-top:2rem">
<div class="rl-card">
<h3 style="color:#06b6d4;margin-bottom:0.75rem">Real-Time Collaboration</h3>
<ul class="rl-check-list">
<li><strong>Threaded Comments</strong> &mdash; discuss any email privately before replying</li>
<li><strong>Draft Reviews</strong> &mdash; collaborative draft editing with inline suggestions</li>
<li><strong>Forwarding Rules</strong> &mdash; route incoming messages by sender, subject, or tag</li>
<li><strong>Inline Signatures</strong> &mdash; per-mailbox signature templates with merge fields</li>
<li><strong>Read Receipts</strong> &mdash; see who has read each thread and when</li>
</ul>
</div>
<div class="rl-card">
<h3 style="color:#8b5cf6;margin-bottom:0.75rem">Approval Workflows</h3>
<ul class="rl-check-list">
<li><strong>Multi-sig sending</strong> &mdash; outbound emails require M-of-N approval</li>
<li><strong>Configurable thresholds</strong> &mdash; set approval requirements per mailbox</li>
<li><strong>Audit trail</strong> &mdash; every approval, rejection, and edit is logged</li>
<li><strong>Role-based access</strong> &mdash; Admin, Reviewer, Approver, Viewer, Bot</li>
<li><strong>Deadline alerts</strong> &mdash; notifications when approvals are waiting</li>
</ul>
</div>
</div>
</div>
</section>
<h2 class="rl-heading" style="text-align:center">Built on Self-Sovereign Identity</h2>
<p class="rl-subtext" style="text-align:center">Security without compromise, powered by EncryptID</p>
<!-- Team Roles -->
<section class="rl-section rl-section--alt">
<div class="rl-container">
<h2 class="rl-heading" style="text-align:center">Team Roles</h2>
<p class="rl-subtext" style="text-align:center">Fine-grained access control for every team member.</p>
<div style="display:grid;grid-template-columns:repeat(5,1fr);gap:0.75rem;margin-top:2rem">
<div class="rl-card rl-card--center" style="padding:1.25rem">
<p style="font-size:0.875rem;font-weight:600;color:#06b6d4">Admin</p>
<p style="font-size:0.75rem;color:#64748b;margin-top:0.35rem">Full control, manage members</p>
</div>
<div class="rl-card rl-card--center" style="padding:1.25rem">
<p style="font-size:0.875rem;font-weight:600;color:#3b82f6">Reviewer</p>
<p style="font-size:0.75rem;color:#64748b;margin-top:0.35rem">Read, comment, suggest edits</p>
</div>
<div class="rl-card rl-card--center" style="padding:1.25rem">
<p style="font-size:0.875rem;font-weight:600;color:#8b5cf6">Approver</p>
<p style="font-size:0.75rem;color:#64748b;margin-top:0.35rem">Sign outbound emails</p>
</div>
<div class="rl-card rl-card--center" style="padding:1.25rem">
<p style="font-size:0.875rem;font-weight:600;color:#94a3b8">Viewer</p>
<p style="font-size:0.75rem;color:#64748b;margin-top:0.35rem">Read-only access</p>
</div>
<div class="rl-card rl-card--center" style="padding:1.25rem">
<p style="font-size:0.875rem;font-weight:600;color:#94a3b8">Bot</p>
<p style="font-size:0.75rem;color:#64748b;margin-top:0.35rem">Automated integrations</p>
</div>
</div>
</div>
</section>
<!-- Built on Open Source -->
<section class="rl-section">
<div class="rl-container">
<h2 class="rl-heading" style="text-align:center">Built on Open Source</h2>
<p class="rl-subtext" style="text-align:center">The libraries and tools that power rInbox.</p>
<div class="rl-grid-4">
<div class="rl-card rl-card--center">
<h3>ImapFlow</h3>
<p>High-performance IMAP client for real-time email synchronization.</p>
<div class="rl-icon-box" style="background:linear-gradient(135deg,#3b82f6,rgba(59,130,246,0.6))">
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="11" width="18" height="11" rx="2" ry="2"/><path d="M7 11V7a5 5 0 0110 0v4"/></svg>
</div>
<h3>End-to-End Encryption</h3>
<p>AES-256-GCM encryption with keys derived from your passkey. Messages are unreadable to the server.</p>
</div>
<div class="rl-card rl-card--center">
<h3>Mailparser</h3>
<p>Email parsing and MIME handling for reliable message processing.</p>
<div class="rl-icon-box" style="background:linear-gradient(135deg,#14b8a6,rgba(20,184,166,0.6))">
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 10V4a2 2 0 00-4 0v6"/><path d="M18 11a6 6 0 00-12 0v3"/><rect x="3" y="14" width="18" height="8" rx="2"/><line x1="12" y1="18" x2="12" y2="18"/></svg>
</div>
<h3>Passkey Authentication</h3>
<p>WebAuthn passkeys backed by biometrics or hardware security keys. Phishing-resistant by design.</p>
</div>
<div class="rl-card rl-card--center">
<h3>Gnosis Safe</h3>
<p>Multisig approval protocol adapted for email signing workflows.</p>
<div class="rl-icon-box" style="background:linear-gradient(135deg,#22c55e,#059669)">
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M16 21v-2a4 4 0 00-4-4H6a4 4 0 00-4-4v2"/><circle cx="9" cy="7" r="4"/><path d="M22 21v-2a4 4 0 00-3-3.87"/><path d="M16 3.13a4 4 0 010 7.75"/></svg>
</div>
<h3>Community Spaces</h3>
<p>Create isolated chat spaces with role-based access. Viewer, participant, moderator, and admin roles.</p>
</div>
<div class="rl-card rl-card--center">
<h3>PostgreSQL</h3>
<p>Threads, approvals, and audit trails stored in a reliable relational database.</p>
<div class="rl-icon-box" style="background:linear-gradient(135deg,#f97316,#d97706)">
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><line x1="2" y1="12" x2="22" y2="12"/><path d="M12 2a15.3 15.3 0 014 10 15.3 15.3 0 01-4 10 15.3 15.3 0 01-4-10 15.3 15.3 0 014-10z"/></svg>
</div>
<h3>Cross-App SSO</h3>
<p>One identity across rSpace, rVote, rMaps, rWork, and the full r* ecosystem via EncryptID.</p>
</div>
</div>
</div>
</section>
<!-- Your Data, Protected -->
<section class="rl-section rl-section--alt">
<div class="rl-container" style="text-align:center">
<h2 class="rl-heading">Your Data, Protected</h2>
<p class="rl-subtext">How rInbox keeps your information safe.</p>
<div class="rl-grid-3">
<!-- Features Row 2 -->
<div class="rl-grid-4" style="margin-top:1rem">
<div class="rl-card rl-card--center">
<div class="rl-icon-box">&#128274;</div>
<h3>End-to-End Encryption</h3>
<span class="rl-badge">Coming Soon</span>
<p>All content encrypted before it leaves your device. Not even the server can read it.</p>
<div class="rl-icon-box" style="background:linear-gradient(135deg,#a855f7,#7c3aed)">
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M20.42 4.58a5.4 5.4 0 00-7.65 0l-.77.78-.77-.78a5.4 5.4 0 00-7.65 7.65l.78.77L12 20.64l7.64-7.64.78-.77a5.4 5.4 0 000-7.65z"/><path d="M12 5.36V12"/><path d="M8.5 8.5L12 12l3.5-3.5"/></svg>
</div>
<h3>Social Recovery</h3>
<p>No seed phrases. Designate trusted guardians who can help you recover access to your account.</p>
</div>
<div class="rl-card rl-card--center">
<div class="rl-icon-box">&#128373;</div>
<h3>Zero-Knowledge Architecture</h3>
<span class="rl-badge">Coming Soon</span>
<p>The server processes your requests without ever seeing your data in the clear.</p>
<div class="rl-icon-box" style="background:linear-gradient(135deg,#3b82f6,#0891b2)">
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 2l-2 2m-7.61 7.61a5.5 5.5 0 11-7.778 7.778 5.5 5.5 0 017.777-7.777zm0 0L15.5 7.5m0 0l3 3L22 7l-3-3m-3.5 3.5L19 4"/></svg>
</div>
<h3>No Passwords</h3>
<p>Passkeys replace passwords entirely. Nothing to leak, nothing to forget, nothing to phish.</p>
</div>
<div class="rl-card rl-card--center">
<div class="rl-icon-box">&#127968;</div>
<h3>Self-Hosted</h3>
<p>Run on your own infrastructure. Your server, your rules, your data.</p>
<div class="rl-icon-box" style="background:linear-gradient(135deg,#f43f5e,#ec4899)">
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z"/></svg>
</div>
<h3>Self-Sovereign</h3>
<p>You own your identity and encryption keys. No platform lock-in, no central authority.</p>
</div>
<div class="rl-card rl-card--center">
<div class="rl-icon-box" style="background:linear-gradient(135deg,#14b8a6,#0891b2)">
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 15a2 2 0 01-2 2H7l-4 4V5a2 2 0 012-2h14a2 2 0 012 2z"/><rect x="9" y="9" width="6" height="1" rx="0.5"/></svg>
</div>
<h3>rSpace Ecosystem</h3>
<p>Chat integrates with rSpace canvas, rVote governance, rFunds treasury, and more.</p>
</div>
</div>
</div>
</section>
<!-- CTA -->
<section class="rl-section">
<div class="rl-container" style="text-align:center">
<h2 class="rl-heading">(You)rInbox, your team's voice.</h2>
<p class="rl-subtext">Try the demo or create a space to get started.</p>
<div class="rl-cta-row">
<a href="https://demo.rspace.online/rinbox" class="rl-cta-primary">Open Inbox</a>
<a href="/create-space" class="rl-cta-secondary">Create a Space</a>
<section class="rl-section rl-section--alt">
<div class="rl-container">
<div class="rl-card" style="border:2px solid rgba(59,130,246,0.3);background:linear-gradient(135deg,rgba(59,130,246,0.1),rgba(20,184,166,0.05),rgba(100,116,139,0.1));text-align:center;padding:3rem 1.5rem;position:relative;overflow:hidden">
<div style="position:absolute;top:0;right:0;width:16rem;height:16rem;background:rgba(59,130,246,0.1);border-radius:50%;filter:blur(48px)"></div>
<div style="position:absolute;bottom:0;left:0;width:16rem;height:16rem;background:rgba(20,184,166,0.1);border-radius:50%;filter:blur(48px)"></div>
<div style="position:relative">
<span class="rl-badge">Try EncryptID</span>
<h2 class="rl-heading" style="margin-top:1rem">See it in action</h2>
<p class="rl-subtext" style="max-width:36rem;margin:0.5rem auto 0">
Try the interactive EncryptID demo &mdash; register a passkey, derive encryption keys,
and test signing and encryption right in your browser. No account needed.
</p>
<div class="rl-cta-row" style="margin-top:1.5rem">
<a href="https://demo.rspace.online/rinbox" class="rl-cta-primary">
Launch Demo &rarr;
</a>
</div>
</div>
</div>
</div>
</section>
<div class="rl-back">
<a href="/">&larr; Back to rSpace</a>
</div>
`;
</div>`;
}

View File

@ -1,109 +1,90 @@
/**
* rPubs landing page community pocket press.
* Ported from the Next.js page.tsx with all unique visual elements preserved.
*/
export function renderLanding(): string {
return `
<!-- Hero -->
<div class="rl-hero">
<span class="rl-tagline">rPubs</span>
<h1 class="rl-heading">(You)rPubs, your press.</h1>
<p class="rl-subtitle">Write it. Press it. Share it.</p>
<span class="rl-tagline">Community Pocket Press</span>
<h1 class="rl-heading">Write it. Press it.<br>Share it.</h1>
<p class="rl-subtext">
Drop in a markdown document, pick a pocket format, and get a print-ready PDF in seconds.
Group up with other authors to unlock bulk pricing through collaborative print runs.
Instant local publishing for your writing. Paste in your text, pick a
pocket format, and get a print-ready book in seconds &mdash; then find a
local print shop or bind it yourself.
</p>
<div class="rl-cta-row">
<a href="https://demo.rspace.online/rpubs" class="rl-cta-primary" id="ml-primary">Try the Press</a>
<a href="https://demo.rspace.online/rpubs" class="rl-cta-primary" id="ml-primary">
<span style="display:inline-flex;align-items:center;gap:0.5rem">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 20h9"/><path d="M16.5 3.5a2.12 2.12 0 0 1 3 3L7 19l-4 1 1-4Z"/></svg>
Start Writing
</span>
</a>
<a href="/create-space" class="rl-cta-secondary">Create a Space</a>
</div>
</div>
<!-- Features -->
<section class="rl-section">
<div class="rl-container">
<h2 class="rl-heading" style="text-align:center">What rPubs Handles</h2>
<div class="rl-grid-4">
<div class="rl-card rl-card--center">
<div class="rl-icon-box">&#128196;</div>
<h3>Markdown &#8594; PDF</h3>
<p>Drop in markdown or rich text. rPubs typesets it with Typst and produces a print-ready PDF in seconds.</p>
</div>
<div class="rl-card rl-card--center">
<div class="rl-icon-box">&#128214;</div>
<h3>4 Pocket Formats</h3>
<p>A7 Pocket, Quarter Letter, A6 Booklet, and Digest. All print-ready at 300&nbsp;dpi with bleeds.</p>
</div>
<div class="rl-card rl-card--center">
<div class="rl-icon-box">&#129309;</div>
<h3>Collaborative Print Runs</h3>
<p>Pool orders across titles and authors. The more copies in a run, the cheaper each one gets.</p>
</div>
<div class="rl-card rl-card--center">
<div class="rl-icon-box">&#128722;</div>
<h3>rCart Integration</h3>
<p>Publish your artifact to the rCart catalog with one click. Group carts, revenue splits, and fulfillment built in.</p>
</div>
</div>
</div>
</section>
<!-- How It Works -->
<!-- How it works -->
<section class="rl-section rl-section--alt">
<div class="rl-container">
<h2 class="rl-heading" style="text-align:center">How It Works</h2>
<h2 class="rl-heading" style="text-align:center">From draft to booklet in three steps</h2>
<div class="rl-grid-3">
<div class="rl-step">
<span class="rl-step__num">1</span>
<h3>Write / paste</h3>
<p>Drop in markdown or rich text. Headings, images, footnotes &mdash; it all just works.</p>
<div class="rl-step__num" style="position:relative">
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="#14b8a6" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M12 20h9"/><path d="M16.5 3.5a2.12 2.12 0 0 1 3 3L7 19l-4 1 1-4Z"/></svg>
</div>
<h3>Write or paste</h3>
<p>Type directly, paste your markdown, or drop in a .md file. The editor handles the rest.</p>
</div>
<div class="rl-step">
<span class="rl-step__num">2</span>
<div class="rl-step__num" style="position:relative">
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="#14b8a6" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/><polyline points="14 2 14 8 20 8"/></svg>
</div>
<h3>Press it</h3>
<p>Pick a pocket format. rPubs typesets your document with Typst and generates a print-ready PDF.</p>
<p>Pick a pocket format &mdash; from A7 pocket to digest &mdash; and generate a typeset PDF in seconds.</p>
</div>
<div class="rl-step">
<span class="rl-step__num">3</span>
<div class="rl-step__num" style="position:relative">
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="#14b8a6" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M21 10c0 7-9 13-9 13s-9-6-9-13a9 9 0 0 1 18 0z"/><circle cx="12" cy="10" r="3"/></svg>
</div>
<h3>Print locally</h3>
<p>Print at home, at a local shop, or list it on rCart for cosmolocal fulfillment.</p>
<p>Find a community print shop nearby, or download an imposition PDF and bind it at home.</p>
</div>
</div>
</div>
</section>
<!-- Pocket Formats -->
<!-- Four pocket formats -->
<section class="rl-section">
<div class="rl-container">
<h2 class="rl-heading" style="text-align:center">Four pocket formats</h2>
<p class="rl-subtext" style="text-align:center">From palm-sized zines to digest readers. All print-ready at 300 dpi with bleeds.</p>
<p class="rl-subtext" style="text-align:center">
From tiny zines that fit in your back pocket to digest-sized readers for longer works.
</p>
<div class="rl-grid-4" style="margin-top:2rem">
<div class="rl-card rl-card--center">
<div class="rl-icon-box">
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M4 19.5A2.5 2.5 0 016.5 17H20"/><path d="M6.5 2H20v20H6.5A2.5 2.5 0 014 19.5v-15A2.5 2.5 0 016.5 2z"/></svg>
</div>
<h3>A7 Pocket</h3>
<p>74 &times; 105 mm &mdash; fits in a shirt pocket. Perfect for poems, manifestos, tiny zines.</p>
<div class="rl-card" style="text-align:left">
<h3 style="margin-bottom:0.15rem">A7 Pocket</h3>
<p style="font-size:0.75rem;color:#14b8a6;margin-bottom:0.5rem">74 &times; 105 mm</p>
<p>Fits in your pocket. Perfect for poems, manifestos, and quick reads.</p>
<p style="font-size:0.75rem;color:#64748b;margin-top:0.5rem">8&ndash;32 pages</p>
</div>
<div class="rl-card rl-card--center">
<div class="rl-icon-box">
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M4 19.5A2.5 2.5 0 016.5 17H20"/><path d="M6.5 2H20v20H6.5A2.5 2.5 0 014 19.5v-15A2.5 2.5 0 016.5 2z"/></svg>
</div>
<h3>Quarter Letter</h3>
<p>4.25 &times; 5.5&quot; &mdash; half a half-sheet. Great for chapbooks and field guides.</p>
<div class="rl-card" style="text-align:left">
<h3 style="margin-bottom:0.15rem">Quarter Letter</h3>
<p style="font-size:0.75rem;color:#14b8a6;margin-bottom:0.5rem">4.25 &times; 5.5&quot;</p>
<p>Classic zine size. Great for essays, short stories, and pamphlets.</p>
<p style="font-size:0.75rem;color:#64748b;margin-top:0.5rem">16&ndash;64 pages</p>
</div>
<div class="rl-card rl-card--center">
<div class="rl-icon-box">
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M4 19.5A2.5 2.5 0 016.5 17H20"/><path d="M6.5 2H20v20H6.5A2.5 2.5 0 014 19.5v-15A2.5 2.5 0 016.5 2z"/></svg>
</div>
<h3>A6 Booklet</h3>
<p>105 &times; 148 mm &mdash; postcard size. The workhorse format for essays and readers.</p>
<div class="rl-card" style="text-align:left">
<h3 style="margin-bottom:0.15rem">A6 Booklet</h3>
<p style="font-size:0.75rem;color:#14b8a6;margin-bottom:0.5rem">105 &times; 148 mm</p>
<p>Postcard-sized. Ideal for field guides, chapbooks, and handbooks.</p>
<p style="font-size:0.75rem;color:#64748b;margin-top:0.5rem">24&ndash;96 pages</p>
</div>
<div class="rl-card rl-card--center">
<div class="rl-icon-box">
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M4 19.5A2.5 2.5 0 016.5 17H20"/><path d="M6.5 2H20v20H6.5A2.5 2.5 0 014 19.5v-15A2.5 2.5 0 016.5 2z"/></svg>
</div>
<h3>Digest</h3>
<p>5.5 &times; 8.5&quot; &mdash; half-letter. Standard trade paperback for longer works.</p>
<div class="rl-card" style="text-align:left">
<h3 style="margin-bottom:0.15rem">Digest</h3>
<p style="font-size:0.75rem;color:#14b8a6;margin-bottom:0.5rem">5.5 &times; 8.5&quot;</p>
<p>Standard indie publishing size. For novellas, collections, and readers.</p>
<p style="font-size:0.75rem;color:#64748b;margin-top:0.5rem">32&ndash;200+ pages</p>
</div>
</div>
</div>
@ -112,117 +93,253 @@ export function renderLanding(): string {
<!-- Group Buys -->
<section class="rl-section rl-section--alt">
<div class="rl-container">
<h2 class="rl-heading" style="text-align:center">Group buys &mdash; better together</h2>
<p class="rl-subtext" style="text-align:center">Pool orders across titles. The more copies in a run, the cheaper each one gets.</p>
<h2 class="rl-heading" style="text-align:center">Bulk orders, better prices</h2>
<p class="rl-subtext" style="text-align:center">
The more copies a community funds together, the cheaper each one gets.
Group buys unlock better binding and lower per-copy costs.
</p>
<!-- Tier cards -->
<div class="rl-grid-3" style="margin-top:2rem">
<div class="rl-card rl-card--center">
<h3>25+ copies</h3>
<p>Saddle-stitch binding</p>
<p style="font-size:1.5rem;font-weight:700;color:#14b8a6;margin:0.5rem 0">$8</p>
<p style="font-size:0.75rem;color:#64748b">per copy</p>
<div class="rl-card rl-card--center" style="position:relative">
<p style="font-size:1.75rem;font-weight:700;color:#e2e8f0;margin-bottom:0.15rem">25+</p>
<p style="font-size:0.9rem;font-weight:600;color:#14b8a6;margin-bottom:0.5rem">Saddle-stitch</p>
<p style="font-size:0.8rem;margin-bottom:1rem">Staple-bound booklet. Quick, lightweight, great for zines and short runs.</p>
<p style="font-size:1.25rem;font-weight:700;color:#e2e8f0">$8<span style="font-size:0.75rem;color:#94a3b8;font-weight:400">/copy</span></p>
</div>
<div class="rl-card rl-card--center">
<h3>50+ copies</h3>
<p>Perfect-bind</p>
<p style="font-size:1.5rem;font-weight:700;color:#14b8a6;margin:0.5rem 0">$6</p>
<span class="rl-badge">Save 25%</span>
<p style="font-size:0.75rem;color:#64748b;margin-top:0.5rem">per copy</p>
<div class="rl-card rl-card--center" style="position:relative">
<span class="rl-badge" style="position:absolute;top:-0.6rem;right:0.75rem">save 25%</span>
<p style="font-size:1.75rem;font-weight:700;color:#e2e8f0;margin-bottom:0.15rem">50+</p>
<p style="font-size:0.9rem;font-weight:600;color:#14b8a6;margin-bottom:0.5rem">Perfect-bind</p>
<p style="font-size:0.8rem;margin-bottom:1rem">Glued spine with cover wrap. Professional feel, sits on a shelf like a real book.</p>
<p style="font-size:1.25rem;font-weight:700;color:#e2e8f0">$6<span style="font-size:0.75rem;color:#94a3b8;font-weight:400">/copy</span></p>
</div>
<div class="rl-card rl-card--center">
<h3>100+ copies</h3>
<p>Trade edition</p>
<p style="font-size:1.5rem;font-weight:700;color:#14b8a6;margin:0.5rem 0">$4.50</p>
<span class="rl-badge">Save 44%</span>
<p style="font-size:0.75rem;color:#64748b;margin-top:0.5rem">per copy</p>
<div class="rl-card rl-card--center" style="position:relative">
<span class="rl-badge" style="position:absolute;top:-0.6rem;right:0.75rem">save 44%</span>
<p style="font-size:1.75rem;font-weight:700;color:#e2e8f0;margin-bottom:0.15rem">100+</p>
<p style="font-size:0.9rem;font-weight:600;color:#14b8a6;margin-bottom:0.5rem">Trade edition</p>
<p style="font-size:0.8rem;margin-bottom:1rem">Full trade paperback. Robust binding, printed cover, retail-ready quality.</p>
<p style="font-size:1.25rem;font-weight:700;color:#e2e8f0">$4.50<span style="font-size:0.75rem;color:#94a3b8;font-weight:400">/copy</span></p>
</div>
</div>
</div>
</section>
<!-- How collaborative print runs work -->
<section class="rl-section">
<div class="rl-container">
<h2 class="rl-heading" style="text-align:center">How collaborative print runs work</h2>
<div class="rl-grid-4" style="margin-top:2rem">
<div class="rl-step">
<span class="rl-step__num">1</span>
<h3>Authors list titles</h3>
<p>Publish your print-ready artifact to the rCart catalog.</p>
</div>
<div class="rl-step">
<span class="rl-step__num">2</span>
<h3>Readers pre-order</h3>
<p>Buyers add copies to a shared cart. Orders accumulate toward tier thresholds.</p>
</div>
<div class="rl-step">
<span class="rl-step__num">3</span>
<h3>Threshold met</h3>
<p>When the combined order hits a tier, the print run triggers automatically.</p>
</div>
<div class="rl-step">
<span class="rl-step__num">4</span>
<h3>Local fulfillment</h3>
<p>The nearest cosmolocal provider prints and ships. Revenue splits to creator, community, and provider.</p>
<!-- How collaborative print runs work -->
<div class="rl-card" style="margin-top:2.5rem">
<h3 style="text-align:center;margin-bottom:1.25rem">How collaborative print runs work</h3>
<div class="rl-grid-4" style="text-align:center">
<div>
<div style="width:2rem;height:2rem;border-radius:9999px;background:rgba(20,184,166,0.1);display:flex;align-items:center;justify-content:center;margin:0 auto 0.5rem">
<span style="font-size:0.7rem;font-weight:700;color:#14b8a6">1</span>
</div>
<p style="font-size:0.75rem;color:#94a3b8;line-height:1.5">
A title gets <a href="https://demo.rspace.online/rpubs" style="color:#14b8a6;text-decoration:none">funded</a> by the community
</p>
</div>
<div>
<div style="width:2rem;height:2rem;border-radius:9999px;background:rgba(20,184,166,0.1);display:flex;align-items:center;justify-content:center;margin:0 auto 0.5rem">
<span style="font-size:0.7rem;font-weight:700;color:#14b8a6">2</span>
</div>
<p style="font-size:0.75rem;color:#94a3b8;line-height:1.5">
Backers join the group buy as it hits each tier
</p>
</div>
<div>
<div style="width:2rem;height:2rem;border-radius:9999px;background:rgba(20,184,166,0.1);display:flex;align-items:center;justify-content:center;margin:0 auto 0.5rem">
<span style="font-size:0.7rem;font-weight:700;color:#14b8a6">3</span>
</div>
<p style="font-size:0.75rem;color:#94a3b8;line-height:1.5">
Order is placed with the nearest print shop via <a href="https://rcart.online" style="color:#14b8a6;text-decoration:none">rCart</a>
</p>
</div>
<div>
<div style="width:2rem;height:2rem;border-radius:9999px;background:rgba(20,184,166,0.1);display:flex;align-items:center;justify-content:center;margin:0 auto 0.5rem">
<span style="font-size:0.7rem;font-weight:700;color:#14b8a6">4</span>
</div>
<p style="font-size:0.75rem;color:#94a3b8;line-height:1.5">
Books are printed locally and distributed to backers
</p>
</div>
</div>
</div>
</div>
</section>
<!-- Cross-title batching -->
<section class="rl-section rl-section--alt">
<section class="rl-section">
<div class="rl-container">
<h2 class="rl-heading" style="text-align:center">Cross-title batching</h2>
<h2 class="rl-heading" style="text-align:center">Bundle across titles, not just within them</h2>
<p class="rl-subtext" style="text-align:center">
Orders from <em>different</em> titles count toward the same tier. A community reading list
can hit trade-edition pricing even if no single title has 100 orders.
Printer discounts are based on <em>total volume at the press</em>, not copies of a single book.
When multiple titles route to the same local printer, everyone benefits from the combined run.
</p>
<div class="rl-card" style="max-width:640px;margin:2rem auto 0">
<h3 style="margin-bottom:1rem">Example batch</h3>
<div style="display:flex;flex-direction:column;gap:0.5rem">
<div style="display:flex;justify-content:space-between;font-size:0.875rem">
<span style="color:#e2e8f0">The Commons</span><span style="color:#14b8a6;font-weight:600">35 copies</span>
<!-- Cross-title batching example -->
<div class="rl-card" style="max-width:680px;margin:2rem auto 0">
<p style="font-size:0.7rem;font-weight:600;color:#94a3b8;text-transform:uppercase;letter-spacing:0.08em;margin-bottom:1rem;text-align:center">
How cross-title batching unlocks tiers
</p>
<div class="rl-grid-3" style="margin-bottom:1rem">
<div style="border:1px solid rgba(255,255,255,0.06);border-radius:0.5rem;padding:0.75rem;text-align:center">
<p style="font-size:0.875rem;font-weight:600;color:#e2e8f0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis">The Commons</p>
<p style="font-size:0.75rem;color:#94a3b8">J. Emmett</p>
<p style="font-size:0.65rem;color:#64748b;margin-top:0.25rem">governance</p>
<p style="font-size:1.25rem;font-weight:700;color:#14b8a6;margin-top:0.5rem">35</p>
<p style="font-size:0.6rem;color:#94a3b8">pre-committed copies</p>
</div>
<div style="display:flex;justify-content:space-between;font-size:0.875rem">
<span style="color:#e2e8f0">Mycelial Networks</span><span style="color:#14b8a6;font-weight:600">40 copies</span>
<div style="border:1px solid rgba(255,255,255,0.06);border-radius:0.5rem;padding:0.75rem;text-align:center">
<p style="font-size:0.875rem;font-weight:600;color:#e2e8f0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis">Mycelial Networks</p>
<p style="font-size:0.75rem;color:#94a3b8">M. Stamets</p>
<p style="font-size:0.65rem;color:#64748b;margin-top:0.25rem">ecology</p>
<p style="font-size:1.25rem;font-weight:700;color:#14b8a6;margin-top:0.5rem">40</p>
<p style="font-size:0.6rem;color:#94a3b8">pre-committed copies</p>
</div>
<div style="display:flex;justify-content:space-between;font-size:0.875rem">
<span style="color:#e2e8f0">Cosmolocal Reader</span><span style="color:#14b8a6;font-weight:600">30 copies</span>
<div style="border:1px solid rgba(255,255,255,0.06);border-radius:0.5rem;padding:0.75rem;text-align:center">
<p style="font-size:0.875rem;font-weight:600;color:#e2e8f0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis">Cosmolocal Reader</p>
<p style="font-size:0.75rem;color:#94a3b8">Collective</p>
<p style="font-size:0.65rem;color:#64748b;margin-top:0.25rem">economics</p>
<p style="font-size:1.25rem;font-weight:700;color:#14b8a6;margin-top:0.5rem">30</p>
<p style="font-size:0.6rem;color:#94a3b8">pre-committed copies</p>
</div>
</div>
<div class="rl-divider"><span>combined</span></div>
<div class="rl-divider"><span>at the same local printer</span></div>
<div style="text-align:center">
<span style="font-size:1.5rem;font-weight:700;color:#14b8a6">105 copies</span>
<span style="display:block;font-size:0.8rem;color:#64748b;margin-top:0.25rem">= Trade edition @ $4.50/copy</span>
<p style="font-size:1.5rem;font-weight:700;color:#e2e8f0">105 copies</p>
<p style="font-size:0.875rem;color:#14b8a6;font-weight:500">
Trade edition tier unlocked &mdash; $4.50/copy for all three titles
</p>
<p style="font-size:0.75rem;color:#94a3b8;margin-top:0.25rem">
No single title hit 100 alone, but together they clear the threshold
</p>
</div>
</div>
<!-- Pre-commitments from rSpace -->
<div class="rl-integration" style="margin-top:2rem;max-width:680px;margin-left:auto;margin-right:auto">
<div style="width:2.5rem;height:2.5rem;border-radius:0.5rem;background:rgba(20,184,166,0.2);display:flex;align-items:center;justify-content:center;flex-shrink:0">
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="#14b8a6" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M2 3h6a4 4 0 0 1 4 4v14a3 3 0 0 0-3-3H2zM22 3h-6a4 4 0 0 0-4 4v14a3 3 0 0 1 3-3h7z"/></svg>
</div>
<div>
<h3>Pre-commitments flow from rSpace</h3>
<p style="margin-bottom:0.75rem">
Every reading group, community, and network keeps a
<span style="color:#e2e8f0;font-weight:500">CRDT ledger</span> in their
<a href="https://rspace.online" style="color:#14b8a6;text-decoration:none">{space}</a>.
When members signal intent to buy, those pre-commitments sync across
clients &mdash; conflict-free, append-only, and auditable.
</p>
<p style="margin-bottom:0.75rem">
As pre-commitments accumulate across titles, genres, and networks that share a
local printer, the combined volume triggers better pricing tiers.
A poetry collective and a tech reading group in the same city don&rsquo;t need to know
each other &mdash; their orders batch automatically at the press.
</p>
<div style="display:flex;flex-wrap:wrap;gap:0.5rem">
<a href="https://demo.rspace.online/rpubs" style="display:inline-flex;align-items:center;gap:0.4rem;padding:0.5rem 1rem;border-radius:0.5rem;background:#14b8a6;color:white;font-size:0.75rem;font-weight:500;text-decoration:none">
<svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 2v20M2 12h20"/></svg>
Fund a print run
</a>
<a href="https://rspace.online" style="display:inline-block;padding:0.5rem 1rem;border-radius:0.5rem;border:1px solid rgba(255,255,255,0.15);color:#94a3b8;font-size:0.75rem;font-weight:500;text-decoration:none">
Learn about {space} ledgers
</a>
</div>
</div>
</div>
<!-- Signal / Aggregate / Release -->
<div class="rl-grid-3" style="margin-top:2rem;text-align:center">
<div>
<div style="width:2rem;height:2rem;border-radius:9999px;background:rgba(20,184,166,0.1);display:flex;align-items:center;justify-content:center;margin:0 auto 0.5rem">
<span style="font-size:0.7rem;font-weight:700;color:#14b8a6">1</span>
</div>
<p style="font-size:0.8rem;font-weight:600;color:#e2e8f0;margin-bottom:0.15rem">Signal</p>
<p style="font-size:0.75rem;color:#94a3b8;line-height:1.5">
Communities pre-commit in their {space} CRDT ledger &mdash; &ldquo;I want 3 copies&rdquo;
</p>
</div>
<div>
<div style="width:2rem;height:2rem;border-radius:9999px;background:rgba(20,184,166,0.1);display:flex;align-items:center;justify-content:center;margin:0 auto 0.5rem">
<span style="font-size:0.7rem;font-weight:700;color:#14b8a6">2</span>
</div>
<p style="font-size:0.8rem;font-weight:600;color:#e2e8f0;margin-bottom:0.15rem">Aggregate</p>
<p style="font-size:0.75rem;color:#94a3b8;line-height:1.5">
Pre-commitments across titles and networks
<a href="https://demo.rspace.online/rpubs" style="color:#14b8a6;text-decoration:none">flow into the fund</a>,
batched by printer region
</p>
</div>
<div>
<div style="width:2rem;height:2rem;border-radius:9999px;background:rgba(20,184,166,0.1);display:flex;align-items:center;justify-content:center;margin:0 auto 0.5rem">
<span style="font-size:0.7rem;font-weight:700;color:#14b8a6">3</span>
</div>
<p style="font-size:0.8rem;font-weight:600;color:#e2e8f0;margin-bottom:0.15rem">Release</p>
<p style="font-size:0.75rem;color:#94a3b8;line-height:1.5">
When volume hits a tier threshold, the print run triggers &mdash; everyone gets the bulk rate
</p>
</div>
</div>
</div>
</section>
<!-- rCart integration -->
<section class="rl-section">
<section class="rl-section rl-section--alt">
<div class="rl-container">
<div class="rl-grid-2">
<div>
<h2 class="rl-heading">rCart integration</h2>
<p class="rl-subtext" style="margin-bottom:1.5rem">
Group purchasing is built right into the shop. Every rPubs artifact can be listed,
batched, and fulfilled through rCart.
<div style="display:flex;align-items:center;gap:0.5rem;margin-bottom:1rem">
<span style="width:1.75rem;height:1.75rem;border-radius:0.375rem;background:#fdba74;display:flex;align-items:center;justify-content:center;font-size:0.6rem;font-weight:900;color:#0f172a;line-height:1">rCt</span>
<span style="font-size:0.875rem;font-weight:600;color:#e2e8f0">rCart</span>
<span style="font-size:0.75rem;color:#94a3b8">&times;</span>
<span style="width:1.75rem;height:1.75rem;border-radius:0.375rem;background:#fda4af;display:flex;align-items:center;justify-content:center;font-size:0.6rem;font-weight:900;color:#0f172a;line-height:1">rP</span>
<span style="font-size:0.875rem;font-weight:600;color:#e2e8f0">rPubs</span>
</div>
<h2 class="rl-heading">Group purchasing, built in</h2>
<p style="color:#94a3b8;line-height:1.65;margin-bottom:1rem;font-size:0.95rem">
rCart handles the commerce side of group buys &mdash; collecting orders,
splitting payments, and coordinating delivery. When a title hits its
funding goal, rCart automatically batches the order to the best local
print shop.
</p>
<ul class="rl-check-list">
<li><strong>One-click listing</strong> &mdash; publish to the rCart catalog straight from the press</li>
<li><strong>Group carts</strong> &mdash; space members pool orders automatically</li>
<li><strong>Revenue splits</strong> &mdash; creator, community, and provider shares via <a href="/rfunds" style="color:#14b8a6">rFunds</a></li>
<li><strong>Cosmolocal fulfillment</strong> &mdash; nearest provider prints and ships</li>
<li><strong>Order tracking</strong> &mdash; real-time status from press to doorstep</li>
<li><strong>Shared carts</strong> &mdash; friends, reading groups, or whole communities pool orders for better rates</li>
<li><strong>Automatic tier unlock</strong> &mdash; as more copies are ordered, the price drops for everyone</li>
<li><strong>Local fulfillment</strong> &mdash; orders route to the nearest registered print shop, not a distant warehouse</li>
<li><strong>Transparent pricing</strong> &mdash; 30% to the author, 10% to the community, 60% to print and delivery</li>
</ul>
</div>
<div class="rl-card rl-card--center" style="display:flex;align-items:center;justify-content:center">
<div>
<div class="rl-icon-box" style="margin:0 auto 1rem">
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="9" cy="21" r="1"/><circle cx="20" cy="21" r="1"/><path d="M1 1h4l2.68 13.39a2 2 0 002 1.61h9.72a2 2 0 002-1.61L23 6H6"/></svg>
<div class="rl-card" style="padding:1.5rem">
<p style="font-size:0.7rem;font-weight:600;color:#94a3b8;text-transform:uppercase;letter-spacing:0.08em;margin-bottom:1rem">Example group buy</p>
<!-- Mini order summary -->
<div style="margin-bottom:1rem">
<div style="display:flex;align-items:center;justify-content:space-between;font-size:0.875rem;margin-bottom:0.75rem">
<span style="font-weight:500;color:#e2e8f0">The Commons</span>
<span style="color:#94a3b8">by J. Emmett</span>
</div>
<h3>Shop + Press</h3>
<p>rPubs creates the artifact.<br>rCart sells and fulfills it.</p>
<div class="rl-progress">
<div class="rl-progress__fill" style="width:72%"></div>
</div>
<div style="display:flex;align-items:center;justify-content:space-between;font-size:0.75rem;color:#94a3b8;margin-top:0.5rem">
<span>36 of 50 copies ordered</span>
<span style="color:#14b8a6;font-weight:500">72%</span>
</div>
</div>
<!-- Tier indicator -->
<div class="rl-tier">
<div class="rl-tier__item rl-tier__item--active">
<p><strong>25+</strong></p>
<p style="opacity:0.7">$8/copy</p>
</div>
<div class="rl-tier__item rl-tier__item--active">
<p><strong>50+</strong></p>
<p style="opacity:0.7">$6/copy</p>
</div>
<div class="rl-tier__item">
<p><strong style="color:#64748b">100+</strong></p>
<p style="color:#64748b">$4.50</p>
</div>
</div>
<div style="font-size:0.75rem;color:#94a3b8;line-height:1.55;margin-top:1rem">
<p style="margin-bottom:0.25rem"><span style="font-weight:500;color:#e2e8f0">Current tier:</span> Saddle-stitch at $8/copy</p>
<p><span style="font-weight:500;color:#e2e8f0">14 more copies</span> to unlock perfect-bind at $6/copy &mdash; everyone saves.</p>
</div>
</div>
</div>
@ -230,76 +347,38 @@ export function renderLanding(): string {
</section>
<!-- Cosmolocal -->
<section class="rl-section rl-section--alt">
<section class="rl-section">
<div class="rl-container" style="text-align:center">
<span class="rl-tagline">rPubs &times; Cosmolocal</span>
<h2 class="rl-heading">Design global, manufacture local</h2>
<p class="rl-subtext">
Every print run is routed to the nearest capable provider. Reduce shipping emissions,
support local economies, and still benefit from shared design and pooled demand.
rPubs connects you to a cosmolocal network of independent print shops.
Your writing is typeset in the cloud and printed close to where it&rsquo;s
needed &mdash; reducing shipping, supporting local makers, and keeping
publishing accessible.
</p>
</div>
</section>
<!-- Built on Open Source -->
<section class="rl-section">
<div class="rl-container">
<h2 class="rl-heading" style="text-align:center">Built on Open Source</h2>
<p class="rl-subtext" style="text-align:center">The libraries and tools that power rPubs.</p>
<div class="rl-grid-3">
<div class="rl-card rl-card--center">
<div class="rl-icon-box">&#9881;</div>
<h3>Typst</h3>
<p>Document compilation engine. Transforms markdown into beautifully typeset, print-ready PDFs.</p>
</div>
<div class="rl-card rl-card--center">
<div class="rl-icon-box">&#128293;</div>
<h3>Hono</h3>
<p>Ultrafast web framework for the API layer. Lightweight, edge-ready, and built for speed.</p>
</div>
<div class="rl-card rl-card--center">
<div class="rl-icon-box">&#128451;</div>
<h3>PostgreSQL</h3>
<p>Rock-solid relational database for catalog storage, orders, and artifact metadata.</p>
</div>
</div>
</div>
</section>
<!-- Your Data, Protected -->
<section class="rl-section rl-section--alt">
<div class="rl-container" style="text-align:center">
<h2 class="rl-heading">Your Data, Protected</h2>
<p class="rl-subtext">How rPubs keeps your information safe.</p>
<div class="rl-grid-3">
<div class="rl-card rl-card--center">
<div class="rl-icon-box">&#128274;</div>
<h3>End-to-End Encryption</h3>
<span class="rl-badge">Coming Soon</span>
<p>All content encrypted before it leaves your device. Not even the server can read it.</p>
</div>
<div class="rl-card rl-card--center">
<div class="rl-icon-box">&#128373;</div>
<h3>Zero-Knowledge Architecture</h3>
<span class="rl-badge">Coming Soon</span>
<p>The server processes your requests without ever seeing your data in the clear.</p>
</div>
<div class="rl-card rl-card--center">
<div class="rl-icon-box">&#127968;</div>
<h3>Self-Hosted</h3>
<p>Run on your own infrastructure. Your server, your rules, your data.</p>
</div>
<div style="display:flex;align-items:center;justify-content:center;gap:0.75rem;flex-wrap:wrap">
<a href="https://demo.rspace.online/rpubs" style="display:inline-flex;align-items:center;gap:0.4rem;padding:0.5rem 1rem;border-radius:0.5rem;border:1px solid rgba(20,184,166,0.3);color:#14b8a6;font-size:0.875rem;font-weight:500;text-decoration:none">
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 10c0 7-9 13-9 13s-9-6-9-13a9 9 0 0 1 18 0z"/><circle cx="12" cy="10" r="3"/></svg>
Register Your Print Shop
</a>
<a href="https://demo.rspace.online/rpubs" style="display:inline-block;padding:0.5rem 1rem;border-radius:0.5rem;border:1px solid rgba(255,255,255,0.15);color:#94a3b8;font-size:0.875rem;font-weight:500;text-decoration:none">
Fund a Title
</a>
<a href="https://rcart.online" style="display:inline-flex;align-items:center;gap:0.4rem;padding:0.5rem 1rem;border-radius:0.5rem;border:1px solid rgba(255,255,255,0.15);color:#94a3b8;font-size:0.875rem;font-weight:500;text-decoration:none">
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="9" cy="21" r="1"/><circle cx="20" cy="21" r="1"/><path d="M1 1h4l2.68 13.39a2 2 0 0 0 2 1.61h9.72a2 2 0 0 0 2-1.61L23 6H6"/></svg>
Browse on rCart
</a>
</div>
</div>
</section>
<!-- CTA -->
<section class="rl-section">
<section class="rl-section rl-section--alt">
<div class="rl-container" style="text-align:center">
<h2 class="rl-heading">(You)rPubs, your press.</h2>
<h2 class="rl-heading">Write it. Press it. Share it.</h2>
<p class="rl-subtext">Try the demo or create a space to get started.</p>
<div class="rl-cta-row">
<a href="https://demo.rspace.online/rpubs" class="rl-cta-primary">Try the Press</a>
<a href="https://demo.rspace.online/rpubs" class="rl-cta-primary">Start Writing</a>
<a href="/create-space" class="rl-cta-secondary">Create a Space</a>
</div>
</div>

View File

@ -1,79 +1,177 @@
/**
* rTrips landing page group travel planning.
* Ported from /opt/websites/rtrips-online/src/app/page.tsx
*/
export function renderLanding(): string {
return `
<!-- Hero -->
<div class="rl-hero">
<span class="rl-tagline">rTrips</span>
<h1 class="rl-heading">(You)rTrips, your horizon.</h1>
<p class="rl-subtitle">Plan Your Trip, Naturally</p>
<h1 class="rl-heading" style="background:linear-gradient(135deg,#5eead4,#67e8f9,#93c5fd);-webkit-background-clip:text;background-clip:text">(You)rTrips, your horizon.</h1>
<p class="rl-subtitle" style="background:linear-gradient(135deg,#5eead4,#67e8f9,#93c5fd);-webkit-background-clip:text;background-clip:text">Plan Your Trip, Naturally</p>
<p class="rl-subtext">
Describe your dream trip in plain language. We'll structure it into
itineraries, budgets, and bookings &mdash; then give you a collaborative
canvas to plan together in real-time.
</p>
<div class="rl-cta-row">
<a href="https://demo.rspace.online/rtrips" class="rl-cta-primary" id="ml-primary">Plan a Trip</a>
<a href="https://demo.rspace.online/rtrips" class="rl-cta-primary" id="ml-primary">Start Planning</a>
<a href="/create-space" class="rl-cta-secondary">Create a Space</a>
</div>
</div>
<!-- Features -->
<!-- How It Works -->
<section class="rl-section">
<div class="rl-container">
<h2 class="rl-heading" style="text-align:center">What rTrips Handles</h2>
<div class="rl-grid-4">
<h2 class="rl-heading" style="text-align:center">How It Works</h2>
<div class="rl-grid-3">
<div class="rl-card rl-card--center">
<div class="rl-icon-box">&#128506;</div>
<h3>Route Planning</h3>
<p>Visualize your entire trip on rMaps. See routes between destinations and nearby points of interest.</p>
<div class="rl-icon-box" style="background:rgba(20,184,166,0.15)">
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#2dd4bf" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M8 10h.01M12 10h.01M16 10h.01M9 16H5a2 2 0 01-2-2V6a2 2 0 012-2h14a2 2 0 012 2v8a2 2 0 01-2 2h-5l-5 5v-5z"/></svg>
</div>
<h3>Describe It</h3>
<p>Tell us about your trip in natural language. &ldquo;Fly from Toronto to Bali
for 2 weeks in March, budget $3000.&rdquo; We parse it into structured data
you can refine.</p>
</div>
<div class="rl-card rl-card--center">
<div class="rl-icon-box">&#128197;</div>
<h3>Itinerary Building</h3>
<p>Build day-by-day plans together. Add destinations, suggest activities, and rearrange the schedule.</p>
<div class="rl-icon-box" style="background:rgba(6,182,212,0.15)">
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#22d3ee" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"/></svg>
</div>
<h3>We Structure It</h3>
<p>AI extracts destinations, dates, budgets, and bookings into organized views.
Edit itineraries, track expenses, manage packing lists &mdash; all structured
and searchable.</p>
</div>
<div class="rl-card rl-card--center">
<div class="rl-icon-box">&#128176;</div>
<h3>Expense Splitting</h3>
<p>Split costs and track expenses across the group. Everyone knows exactly where the money goes.</p>
</div>
<div class="rl-card rl-card--center">
<div class="rl-icon-box">&#128101;</div>
<h3>Group Coordination</h3>
<p>Real-time collaborative canvas for travel partners. Plan visually, brainstorm together, stay in sync.</p>
<div class="rl-icon-box" style="background:rgba(59,130,246,0.15)">
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#60a5fa" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M17 20h5v-2a3 3 0 00-5.356-1.857M17 20H7m10 0v-2c0-.656-.126-1.283-.356-1.857M7 20H2v-2a3 3 0 015.356-1.857M7 20v-2c0-.656.126-1.283.356-1.857m0 0a5.002 5.002 0 019.288 0M15 7a3 3 0 11-6 0 3 3 0 016 0z"/></svg>
</div>
<h3>Collaborate on Canvas</h3>
<p>Open the collaborative canvas to plan visually with your travel partners.
Drag destinations, connect itineraries, and brainstorm together in real-time
or async.</p>
</div>
</div>
</div>
</section>
<!-- How It Works -->
<!-- Features -->
<section class="rl-section rl-section--alt">
<div class="rl-container">
<h2 class="rl-heading" style="text-align:center">How It Works</h2>
<div class="rl-grid-3">
<div class="rl-step">
<span class="rl-step__num">1</span>
<h3>Create a trip</h3>
<p>Describe your trip in natural language. &ldquo;Fly from Toronto to Bali for 2 weeks in March, budget $3000.&rdquo; We parse it into structured data you can refine.</p>
<h2 class="rl-heading" style="text-align:center">Everything You Need to Travel Together</h2>
<p class="rl-subtext" style="text-align:center">
rTrips brings every piece of trip planning into one place &mdash; so your group
spends less time coordinating and more time exploring.
</p>
<div class="rl-grid-3" style="margin-top:2rem">
<!-- Collaborative Itineraries -->
<div class="rl-card rl-card--center">
<div class="rl-icon-box" style="background:rgba(16,185,129,0.12)">
<svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="#34d399" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M18 18.72a9.094 9.094 0 003.741-.479 3 3 0 00-4.682-2.72m.94 3.198l.001.031c0 .225-.012.447-.037.666A11.944 11.944 0 0112 21c-2.17 0-4.207-.576-5.963-1.584A6.062 6.062 0 016 18.719m12 0a5.971 5.971 0 00-.941-3.197m0 0A5.995 5.995 0 0012 12.75a5.995 5.995 0 00-5.058 2.772m0 0a3 3 0 00-4.681 2.72 8.986 8.986 0 003.74.477m.94-3.197a5.971 5.971 0 00-.94 3.197M15 6.75a3 3 0 11-6 0 3 3 0 016 0zm6 3a2.25 2.25 0 11-4.5 0 2.25 2.25 0 014.5 0zm-13.5 0a2.25 2.25 0 11-4.5 0 2.25 2.25 0 014.5 0z"/></svg>
</div>
<h3>Collaborative Itineraries</h3>
<p>Build day-by-day plans together in real-time. Everyone can add destinations,
suggest activities, and rearrange the schedule &mdash; changes sync instantly.</p>
</div>
<div class="rl-step">
<span class="rl-step__num">2</span>
<h3>Plan your route</h3>
<p>AI extracts destinations, dates, budgets, and bookings into organized views. Edit itineraries, track expenses, manage packing lists.</p>
<!-- Smart Suggestions -->
<div class="rl-card rl-card--center">
<div class="rl-icon-box" style="background:rgba(16,185,129,0.12)">
<svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="#34d399" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M9.813 15.904L9 18.75l-.813-2.846a4.5 4.5 0 00-3.09-3.09L2.25 12l2.846-.813a4.5 4.5 0 003.09-3.09L9 5.25l.813 2.846a4.5 4.5 0 003.09 3.09L15.75 12l-2.846.813a4.5 4.5 0 00-3.09 3.09zM18.259 8.715L18 9.75l-.259-1.035a3.375 3.375 0 00-2.455-2.456L14.25 6l1.036-.259a3.375 3.375 0 002.455-2.456L18 2.25l.259 1.035a3.375 3.375 0 002.455 2.456L21.75 6l-1.036.259a3.375 3.375 0 00-2.455 2.456z"/></svg>
</div>
<h3>Smart Suggestions</h3>
<p>AI-powered recommendations for destinations, restaurants, and activities based
on your group's interests, budget, and travel dates.</p>
</div>
<div class="rl-step">
<span class="rl-step__num">3</span>
<h3>Split expenses</h3>
<p>Track costs across the group with automatic splitting. Pay your share, see the running total, and keep finances transparent.</p>
<!-- Budget Tracking -->
<div class="rl-card rl-card--center">
<div class="rl-icon-box" style="background:rgba(16,185,129,0.12)">
<svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="#34d399" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M2.25 18.75a60.07 60.07 0 0115.797 2.101c.727.198 1.453-.342 1.453-1.096V18.75M3.75 4.5v.75A.75.75 0 013 6h-.75m0 0v-.375c0-.621.504-1.125 1.125-1.125H20.25M2.25 6v9m18-10.5v.75c0 .414.336.75.75.75h.75m-1.5-1.5h.375c.621 0 1.125.504 1.125 1.125v9.75c0 .621-.504 1.125-1.125 1.125h-.375m1.5-1.5H21a.75.75 0 00-.75.75v.75m0 0H3.75m0 0h-.375a1.125 1.125 0 01-1.125-1.125V15m1.5 1.5v-.75A.75.75 0 003 15h-.75M15 10.5a3 3 0 11-6 0 3 3 0 016 0zm3 0h.008v.008H18V10.5zm-12 0h.008v.008H6V10.5z"/></svg>
</div>
<h3>Budget Tracking</h3>
<p>Split costs, track expenses across the group, and keep a running total so
everyone knows exactly where the money goes. No more messy spreadsheets.</p>
</div>
<!-- Map Integration -->
<div class="rl-card rl-card--center">
<div class="rl-icon-box" style="background:rgba(16,185,129,0.12)">
<svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="#34d399" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M9 6.75V15m6-6v8.25m.503 3.498l4.875-2.437c.381-.19.622-.58.622-1.006V4.82c0-.836-.88-1.38-1.628-1.006l-3.869 1.934c-.317.159-.69.159-1.006 0L9.503 3.252a1.125 1.125 0 00-1.006 0L3.622 5.689C3.24 5.88 3 6.27 3 6.695V19.18c0 .836.88 1.38 1.628 1.006l3.869-1.934c.317-.159.69-.159 1.006 0l4.994 2.497c.317.158.69.158 1.006 0z"/></svg>
</div>
<h3>Map Integration</h3>
<p>Visualize your entire trip on rMaps. See routes between destinations,
nearby points of interest, and real-time location sharing during travel days.</p>
</div>
<!-- Packing Lists -->
<div class="rl-card rl-card--center">
<div class="rl-icon-box" style="background:rgba(16,185,129,0.12)">
<svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="#34d399" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M9 12h3.75M9 15h3.75M9 18h3.75m3 .75H18a2.25 2.25 0 002.25-2.25V6.108c0-1.135-.845-2.098-1.976-2.192a48.424 48.424 0 00-1.123-.08m-5.801 0c-.065.21-.1.433-.1.664 0 .414.336.75.75.75h4.5a.75.75 0 00.75-.75 2.25 2.25 0 00-.1-.664m-5.8 0A2.251 2.251 0 0113.5 2.25H15a2.25 2.25 0 012.15 1.586m-5.8 0c-.376.023-.75.05-1.124.08C9.095 4.01 8.25 4.973 8.25 6.108V8.25m0 0H4.875c-.621 0-1.125.504-1.125 1.125v11.25c0 .621.504 1.125 1.125 1.125h9.75c.621 0 1.125-.504 1.125-1.125V9.375c0-.621-.504-1.125-1.125-1.125H8.25zM6.75 12h.008v.008H6.75V12zm0 3h.008v.008H6.75V15zm0 3h.008v.008H6.75V18z"/></svg>
</div>
<h3>Packing Lists</h3>
<p>Shared checklists so nothing gets forgotten. Assign items to people, mark
off as you pack, and see at a glance what the group still needs.</p>
</div>
<!-- Offline Access -->
<div class="rl-card rl-card--center">
<div class="rl-icon-box" style="background:rgba(16,185,129,0.12)">
<svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="#34d399" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M3 16.5v2.25A2.25 2.25 0 005.25 21h13.5A2.25 2.25 0 0021 18.75V16.5M16.5 12L12 16.5m0 0L7.5 12m4.5 4.5V3"/></svg>
</div>
<h3>Offline Access</h3>
<p>Download your full itinerary, maps, and booking confirmations for travel
without connectivity. Everything you need, even without a signal.</p>
</div>
</div>
</div>
</section>
<!-- Built for Groups -->
<section class="rl-section">
<div class="rl-container">
<h2 class="rl-heading" style="text-align:center">Built for Groups</h2>
<p class="rl-subtext" style="text-align:center">
Solo trip planners are everywhere. rTrips is purpose-built for the messy, beautiful
reality of traveling with other people.
</p>
<div class="rl-grid-3" style="margin-top:2rem">
<!-- Friends & Family -->
<div class="rl-card rl-card--center">
<div class="rl-icon-box" style="background:rgba(16,185,129,0.08)">
<svg width="28" height="28" viewBox="0 0 24 24" fill="none" stroke="#34d399" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M21 8.25c0-2.485-2.099-4.5-4.688-4.5-1.935 0-3.597 1.126-4.312 2.733-.715-1.607-2.377-2.733-4.313-2.733C5.1 3.75 3 5.765 3 8.25c0 7.22 9 12 9 12s9-4.78 9-12z"/></svg>
</div>
<h3>Friends &amp; Family</h3>
<p>Family reunions, friend getaways, multi-generational trips. Everyone contributes
ideas, votes on restaurants, and stays in sync without endless group chats.</p>
</div>
<!-- Teams & Offsites -->
<div class="rl-card rl-card--center">
<div class="rl-icon-box" style="background:rgba(16,185,129,0.08)">
<svg width="28" height="28" viewBox="0 0 24 24" fill="none" stroke="#34d399" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M20.25 14.15v4.25c0 1.094-.787 2.036-1.872 2.18-2.087.277-4.216.42-6.378.42s-4.291-.143-6.378-.42c-1.085-.144-1.872-1.086-1.872-2.18v-4.25m16.5 0a2.18 2.18 0 00.75-1.661V8.706c0-1.081-.768-2.015-1.837-2.175a48.114 48.114 0 00-3.413-.387m4.5 8.006c-.194.165-.42.295-.673.38A23.978 23.978 0 0112 15.75c-2.648 0-5.195-.429-7.577-1.22a2.016 2.016 0 01-.673-.38m0 0A2.18 2.18 0 013 12.489V8.706c0-1.081.768-2.015 1.837-2.175a48.111 48.111 0 013.413-.387m7.5 0V5.25A2.25 2.25 0 0013.5 3h-3a2.25 2.25 0 00-2.25 2.25v.894m7.5 0a48.667 48.667 0 00-7.5 0M12 12.75h.008v.008H12v-.008z"/></svg>
</div>
<h3>Teams &amp; Offsites</h3>
<p>Company retreats, conference travel, team offsites. Coordinate logistics,
share flight details, and manage group bookings from a single shared workspace.</p>
</div>
<!-- Retreats & Events -->
<div class="rl-card rl-card--center">
<div class="rl-icon-box" style="background:rgba(16,185,129,0.08)">
<svg width="28" height="28" viewBox="0 0 24 24" fill="none" stroke="#34d399" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M12.75 3.03v.568c0 .334.148.65.405.864l1.068.89c.442.369.535 1.01.216 1.49l-.51.766a2.25 2.25 0 01-1.161.886l-.143.048a1.107 1.107 0 00-.57 1.664c.369.555.169 1.307-.427 1.605L9 13.125l.423 1.059a.956.956 0 01-1.652.928l-.679-.906a1.125 1.125 0 00-1.906.172L4.5 15.75l-.612.153M12.75 3.031a9 9 0 00-8.862 12.872M12.75 3.031a9 9 0 016.69 14.036m0 0l-.177-.529A2.25 2.25 0 0017.128 15H16.5l-.324-.324a1.453 1.453 0 00-2.328.377l-.036.073a1.586 1.586 0 01-.982.816l-.99.282c-.55.157-.894.702-.8 1.267l.073.438a2.25 2.25 0 01-1.228 2.446L10.5 21l-.652-.174M12.75 3.031l.176.53"/></svg>
</div>
<h3>Retreats &amp; Events</h3>
<p>Yoga retreats, wedding trips, festival crews. Organize large groups with
sub-itineraries, optional activities, and shared costs that stay transparent.</p>
</div>
</div>
</div>
</section>
<!-- Built on Open Source -->
<section class="rl-section">
<section class="rl-section rl-section--alt">
<div class="rl-container">
<h2 class="rl-heading" style="text-align:center">Built on Open Source</h2>
<p class="rl-subtext" style="text-align:center">The libraries and tools that power rTrips.</p>
@ -98,7 +196,7 @@ export function renderLanding(): string {
</section>
<!-- Your Data, Protected -->
<section class="rl-section rl-section--alt">
<section class="rl-section">
<div class="rl-container" style="text-align:center">
<h2 class="rl-heading">Your Data, Protected</h2>
<p class="rl-subtext">How rTrips keeps your information safe.</p>
@ -125,10 +223,10 @@ export function renderLanding(): string {
</section>
<!-- CTA -->
<section class="rl-section">
<section class="rl-section rl-section--alt">
<div class="rl-container" style="text-align:center">
<h2 class="rl-heading">(You)rTrips, your horizon.</h2>
<p class="rl-subtext">Try the demo or create a space to get started.</p>
<h2 class="rl-heading">Ready to plan your next adventure?</h2>
<p class="rl-subtext">Just describe where you want to go. We'll handle the rest.</p>
<div class="rl-cta-row">
<a href="https://demo.rspace.online/rtrips" class="rl-cta-primary">Plan a Trip</a>
<a href="/create-space" class="rl-cta-secondary">Create a Space</a>

View File

@ -1,163 +1,195 @@
/**
* Tube module landing page rich content for rspace.online/rtube
* rTube rich landing page body.
* Ported from rtube-online/app/page.tsx (Next.js/Tailwind).
* Returned by landingPage() in the module export;
* the shell wraps it with header, CSS, and analytics.
*/
export function renderLanding(): string {
return `
<!-- Hero -->
<div class="rl-hero">
<span class="rl-tagline">rTube</span>
<h1 class="rl-heading">(You)rTube, your channel.</h1>
<p class="rl-subtitle">Community Video Platform</p>
<p class="rl-subtext">
Host, stream, and share video without big tech.
Your community's video library with HLS streaming and RTMP ingest.
</p>
<div class="rl-cta-row">
<a href="https://demo.rspace.online/rtube" class="rl-cta-primary" id="ml-primary">Start Streaming</a>
<a href="/create-space" class="rl-cta-secondary">Create a Space</a>
<!-- Hero -->
<div class="rl-hero">
<span class="rl-tagline">rTube</span>
<h1 class="rl-heading" style="background:linear-gradient(to right,#f87171,#f9a8d4,#fdba74);-webkit-background-clip:text;-webkit-text-fill-color:transparent;background-clip:text">
Community Video Hosting, Storage &amp; Streaming
</h1>
<p class="rl-subtitle">Who needs YouTube, when you have (ou)rTube!</p>
<p class="rl-subtext">
Self-hosted video recording, live streaming, and storage for your rSpace community.
No corporate surveillance. No algorithmic feeds. Just your community's content.
</p>
<div class="rl-cta-row">
<a href="https://demo.rspace.online/rtube" class="rl-cta-secondary" id="ml-primary">Browse Videos</a>
<a href="https://demo.rspace.online/rtube" class="rl-cta-primary" style="background:#dc2626">Start Streaming</a>
</div>
</div>
<!-- How It Works -->
<section class="rl-section">
<div class="rl-container">
<h2 class="rl-heading" style="text-align:center">How It Works</h2>
<div class="rl-grid-3">
<div class="rl-card rl-card--center">
<div style="width:3rem;height:3rem;background:rgba(239,68,68,0.2);border-radius:0.75rem;display:flex;align-items:center;justify-content:center;margin:0 auto 1rem">
<svg style="width:1.5rem;height:1.5rem;color:#f87171" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<circle cx="12" cy="12" r="10" stroke-width="2" />
<circle cx="12" cy="12" r="4" fill="currentColor" />
</svg>
</div>
<h3>Record</h3>
<p>Stream directly from OBS, browser, or any RTMP-compatible tool. Your content
goes straight to your community's server &mdash; no third-party platforms involved.</p>
</div>
<div class="rl-card rl-card--center">
<div style="width:3rem;height:3rem;background:rgba(236,72,153,0.2);border-radius:0.75rem;display:flex;align-items:center;justify-content:center;margin:0 auto 1rem">
<svg style="width:1.5rem;height:1.5rem;color:#f472b6" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 10l4.553-2.276A1 1 0 0121 8.618v6.764a1 1 0 01-1.447.894L15 14M5 18h8a2 2 0 002-2V8a2 2 0 00-2-2H5a2 2 0 00-2 2v8a2 2 0 002 2z" />
</svg>
</div>
<h3>Stream Live</h3>
<p>Community members watch in real-time via HLS adaptive streaming.
Low-latency delivery through your own nginx-rtmp server with automatic
quality adaptation.</p>
</div>
<div class="rl-card rl-card--center">
<div style="width:3rem;height:3rem;background:rgba(249,115,22,0.2);border-radius:0.75rem;display:flex;align-items:center;justify-content:center;margin:0 auto 1rem">
<svg style="width:1.5rem;height:1.5rem;color:#fb923c" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 8h14M5 8a2 2 0 110-4h14a2 2 0 110 4M5 8v10a2 2 0 002 2h10a2 2 0 002-2V8m-9 4h4" />
</svg>
</div>
<h3>Archive &amp; Store</h3>
<p>Completed streams are automatically converted to MP4 and archived to
R2 cloud storage. Browse, search, and replay your community's entire
video library anytime.</p>
</div>
</div>
</div>
</section>
<!-- Features -->
<section class="rl-section">
<div class="rl-container">
<h2 class="rl-heading" style="text-align:center">What rTube Handles</h2>
<div class="rl-grid-4">
<div class="rl-card rl-card--center">
<div class="rl-icon-box">&#128250;</div>
<h3>Video Hosting</h3>
<p>Upload video files in any major format. MP4, WebM, MKV, MOV &mdash; they all work.</p>
<!-- Built for Communities -->
<section class="rl-section rl-section--alt">
<div class="rl-container">
<div style="background:rgba(30,41,59,0.3);border-radius:1rem;border:1px solid rgba(51,65,85,0.5);padding:2rem">
<h2 class="rl-heading" style="text-align:center;margin-bottom:2rem">Built for Communities</h2>
<div class="rl-grid-2" style="max-width:48rem;margin:0 auto">
<div style="display:flex;align-items:flex-start;gap:0.75rem">
<span style="color:#f87171;font-size:1.125rem;margin-top:2px">&#9679;</span>
<div>
<h4 style="font-weight:500;margin-bottom:0.25rem">Self-Hosted</h4>
<p style="font-size:0.875rem;color:#94a3b8">Your server, your data. No YouTube, no Twitch, no corporate middlemen.</p>
</div>
</div>
<div class="rl-card rl-card--center">
<div class="rl-icon-box">&#128225;</div>
<h3>HLS Adaptive Streaming</h3>
<p>Adaptive bitrate streaming ensures smooth playback on any connection speed or device.</p>
<div style="display:flex;align-items:flex-start;gap:0.75rem">
<span style="color:#f472b6;font-size:1.125rem;margin-top:2px">&#9679;</span>
<div>
<h4 style="font-weight:500;margin-bottom:0.25rem">RTMP Ingest</h4>
<p style="font-size:0.875rem;color:#94a3b8">Standard RTMP protocol &mdash; works with OBS, Streamlabs, FFmpeg, and more.</p>
</div>
</div>
<div class="rl-card rl-card--center">
<div class="rl-icon-box">&#128225;</div>
<h3>RTMP Live Ingest</h3>
<p>Go live with OBS, Streamlabs, or any RTMP-compatible streaming software. One URL, instant broadcast.</p>
<div style="display:flex;align-items:flex-start;gap:0.75rem">
<span style="color:#fb923c;font-size:1.125rem;margin-top:2px">&#9679;</span>
<div>
<h4 style="font-weight:500;margin-bottom:0.25rem">R2 Cloud Storage</h4>
<p style="font-size:0.875rem;color:#94a3b8">Cloudflare R2 for cost-effective, globally distributed video storage.</p>
</div>
</div>
<div class="rl-card rl-card--center">
<div class="rl-icon-box">&#127909;</div>
<h3>R2 Cloud Storage &amp; Community Channels</h3>
<p>Videos stored on Cloudflare R2 for fast delivery. Each space gets its own channel.</p>
<div style="display:flex;align-items:flex-start;gap:0.75rem">
<span style="color:#fbbf24;font-size:1.125rem;margin-top:2px">&#9679;</span>
<div>
<h4 style="font-weight:500;margin-bottom:0.25rem">HLS Playback</h4>
<p style="font-size:0.875rem;color:#94a3b8">Adaptive bitrate streaming works on every device and browser.</p>
</div>
</div>
<div style="display:flex;align-items:flex-start;gap:0.75rem">
<span style="color:#fb7185;font-size:1.125rem;margin-top:2px">&#9679;</span>
<div>
<h4 style="font-weight:500;margin-bottom:0.25rem">Auto-Archive</h4>
<p style="font-size:0.875rem;color:#94a3b8">Streams are automatically converted to MP4 and uploaded when they end.</p>
</div>
</div>
<div style="display:flex;align-items:flex-start;gap:0.75rem">
<span style="color:#e879f9;font-size:1.125rem;margin-top:2px">&#9679;</span>
<div>
<h4 style="font-weight:500;margin-bottom:0.25rem">Community-Scoped</h4>
<p style="font-size:0.875rem;color:#94a3b8">Each rSpace community gets its own video library and streaming channel.</p>
</div>
</div>
</div>
</div>
</section>
</div>
</section>
<!-- How It Works -->
<section class="rl-section rl-section--alt">
<div class="rl-container">
<h2 class="rl-heading" style="text-align:center">How It Works</h2>
<div class="rl-grid-3">
<div class="rl-step">
<div class="rl-step__num">1</div>
<h3>Upload or Stream Live</h3>
<p>Drop video files in any format or point OBS at your space's RTMP ingest URL and go live instantly.</p>
</div>
<div class="rl-step">
<div class="rl-step__num">2</div>
<h3>Automatic HLS Transcoding</h3>
<p>FFmpeg transcodes uploads into adaptive bitrate HLS streams for smooth playback on any device.</p>
</div>
<div class="rl-step">
<div class="rl-step__num">3</div>
<h3>Share with Your Community</h3>
<p>Videos are organized by space. Share links, embed on your canvas, or browse the community library.</p>
</div>
<!-- Built on Open Source -->
<section class="rl-section">
<div class="rl-container">
<h2 class="rl-heading" style="text-align:center">Built on Open Source</h2>
<p class="rl-subtext" style="text-align:center">The libraries and tools that power rTube.</p>
<div class="rl-grid-4">
<div class="rl-card rl-card--center">
<div class="rl-icon-box">&#9729;</div>
<h3>AWS S3 SDK</h3>
<p>Cloudflare R2 object storage via the S3-compatible API. Fast, globally distributed, no egress fees.</p>
</div>
<div class="rl-card rl-card--center">
<div class="rl-icon-box">&#128250;</div>
<h3>HLS.js</h3>
<p>Adaptive bitrate streaming library. Smooth playback with automatic quality switching in the browser.</p>
</div>
<div class="rl-card rl-card--center">
<div class="rl-icon-box">&#127910;</div>
<h3>FFmpeg</h3>
<p>Industry-standard video transcoding. Converts uploads into multi-bitrate HLS streams automatically.</p>
</div>
<div class="rl-card rl-card--center">
<div class="rl-icon-box">&#128293;</div>
<h3>Hono</h3>
<p>Ultrafast web framework for the API layer. Lightweight, type-safe, and runs on any JavaScript runtime.</p>
</div>
</div>
</section>
</div>
</section>
<!-- Technical Details (module-specific) -->
<section class="rl-section">
<div class="rl-container">
<h2 class="rl-heading" style="text-align:center">Technical Details</h2>
<div class="rl-card" style="max-width:600px;margin:0 auto;">
<ul class="rl-check-list">
<li><strong>H.264 / H.265</strong> hardware-accelerated codec support</li>
<li><strong>WebM</strong> (VP8/VP9) for open-format video</li>
<li><strong>Adaptive bitrate HLS</strong> for smooth playback on any connection</li>
<li><strong>HTTP Range requests</strong> for efficient seeking and partial downloads</li>
<li><strong>RTMP ingest</strong> compatible with OBS, Streamlabs, and ffmpeg</li>
</ul>
<!-- Your Data, Protected -->
<section class="rl-section rl-section--alt">
<div class="rl-container" style="text-align:center">
<h2 class="rl-heading">Your Data, Protected</h2>
<p class="rl-subtext">How rTube keeps your information safe.</p>
<div class="rl-grid-3">
<div class="rl-card rl-card--center">
<div class="rl-icon-box">&#128274;</div>
<h3>End-to-End Encryption</h3>
<span class="rl-badge">Coming Soon</span>
<p>All content encrypted before it leaves your device. Not even the server can read it.</p>
</div>
<div class="rl-card rl-card--center">
<div class="rl-icon-box">&#128373;</div>
<h3>Zero-Knowledge Architecture</h3>
<span class="rl-badge">Coming Soon</span>
<p>The server processes your requests without ever seeing your data in the clear.</p>
</div>
<div class="rl-card rl-card--center">
<div class="rl-icon-box">&#127968;</div>
<h3>Self-Hosted</h3>
<p>Run on your own infrastructure. Your server, your rules, your data.</p>
</div>
</div>
</section>
</div>
</section>
<!-- Built on Open Source -->
<section class="rl-section rl-section--alt">
<div class="rl-container">
<h2 class="rl-heading" style="text-align:center">Built on Open Source</h2>
<p class="rl-subtext" style="text-align:center">The libraries and tools that power rTube.</p>
<div class="rl-grid-4">
<div class="rl-card rl-card--center">
<div class="rl-icon-box">&#9729;</div>
<h3>AWS S3 SDK</h3>
<p>Cloudflare R2 object storage via the S3-compatible API. Fast, globally distributed, no egress fees.</p>
</div>
<div class="rl-card rl-card--center">
<div class="rl-icon-box">&#128250;</div>
<h3>HLS.js</h3>
<p>Adaptive bitrate streaming library. Smooth playback with automatic quality switching in the browser.</p>
</div>
<div class="rl-card rl-card--center">
<div class="rl-icon-box">&#127910;</div>
<h3>FFmpeg</h3>
<p>Industry-standard video transcoding. Converts uploads into multi-bitrate HLS streams automatically.</p>
</div>
<div class="rl-card rl-card--center">
<div class="rl-icon-box">&#128293;</div>
<h3>Hono</h3>
<p>Ultrafast web framework for the API layer. Lightweight, type-safe, and runs on any JavaScript runtime.</p>
</div>
</div>
<!-- CTA -->
<section class="rl-section">
<div class="rl-container" style="text-align:center">
<h2 class="rl-heading">Ready to take back your video?</h2>
<p class="rl-subtext">Browse the community video library or start a live stream for your rSpace.</p>
<div class="rl-cta-row">
<a href="https://demo.rspace.online/rtube" class="rl-cta-primary" style="background:#dc2626">Start Streaming</a>
<a href="https://demo.rspace.online/rtube" class="rl-cta-secondary">Browse Videos</a>
</div>
</section>
</div>
</section>
<!-- Your Data, Protected -->
<section class="rl-section">
<div class="rl-container" style="text-align:center">
<h2 class="rl-heading">Your Data, Protected</h2>
<p class="rl-subtext">How rTube keeps your information safe.</p>
<div class="rl-grid-3">
<div class="rl-card rl-card--center">
<div class="rl-icon-box">&#128274;</div>
<h3>End-to-End Encryption</h3>
<span class="rl-badge">Coming Soon</span>
<p>All content encrypted before it leaves your device. Not even the server can read it.</p>
</div>
<div class="rl-card rl-card--center">
<div class="rl-icon-box">&#128373;</div>
<h3>Zero-Knowledge Architecture</h3>
<span class="rl-badge">Coming Soon</span>
<p>The server processes your requests without ever seeing your data in the clear.</p>
</div>
<div class="rl-card rl-card--center">
<div class="rl-icon-box">&#127968;</div>
<h3>Self-Hosted</h3>
<p>Run on your own infrastructure. Your server, your rules, your data.</p>
</div>
</div>
</div>
</section>
<!-- CTA -->
<section class="rl-section rl-section--alt">
<div class="rl-container" style="text-align:center">
<h2 class="rl-heading">(You)rTube, your channel.</h2>
<p class="rl-subtext">Try the demo or create a space to get started.</p>
<div class="rl-cta-row">
<a href="https://demo.rspace.online/rtube" class="rl-cta-primary">Start Streaming</a>
<a href="/create-space" class="rl-cta-secondary">Create a Space</a>
</div>
</div>
</section>
<div class="rl-back">
<a href="/">&larr; Back to rSpace</a>
</div>`;
<div class="rl-back">
<a href="/">&larr; Back to rSpace</a>
</div>`;
}

View File

@ -1,216 +1,353 @@
/**
* rVote landing page democratic backlog prioritization.
* Ported from rvote-online Next.js page.tsx (423 lines, shadcn/ui).
*/
export function renderLanding(): string {
return `
<!-- Hero -->
<div class="rl-hero">
<span class="rl-tagline">rVote</span>
<h1 class="rl-heading">(You)rVote, your voice.</h1>
<p class="rl-subtitle">Democratic Backlog Prioritization</p>
<p class="rl-subtext">
Quadratic conviction voting with time-decay. Surface the ideas your community actually cares about &mdash;
not just the loudest voices.
<span class="rl-tagline" style="color:#818cf8;background:rgba(129,140,248,0.1);border-color:rgba(129,140,248,0.2)">
Part of the rSpace Ecosystem
</span>
<h1 class="rl-heading" style="background:linear-gradient(to right,#818cf8,#c084fc);-webkit-background-clip:text;-webkit-text-fill-color:transparent;background-clip:text;font-size:2.5rem">
Democratic<br>Backlog Prioritization
</h1>
<p class="rl-subtitle">
rVote uses <strong style="color:#e2e8f0">Quadratic Proposal Ranking</strong> to let your community democratically
prioritize proposals. The best ideas rise to the top through collective intelligence,
then advance to final voting.
</p>
<div class="rl-cta-row">
<a href="https://demo.rspace.online/rvote" class="rl-cta-primary" id="ml-primary">Start Voting</a>
<a href="https://demo.rspace.online/rvote" class="rl-cta-primary" id="ml-primary"
style="background:linear-gradient(to right,#818cf8,#6366f1);color:white">
<span style="display:inline-flex;align-items:center;gap:0.5rem">
<svg width="18" height="18" viewBox="0 0 24 24" fill="currentColor" stroke="none"><polygon points="5,3 19,12 5,21"/></svg>
Try the Demo
</span>
</a>
<a href="/create-space" class="rl-cta-secondary">Create a Space</a>
</div>
</div>
<!-- Features -->
<section class="rl-section">
<!-- ELI5 Section: rVote in 30 Seconds -->
<section class="rl-section" style="border-top:none">
<div class="rl-container">
<h2 class="rl-heading" style="text-align:center">What rVote Handles</h2>
<div class="rl-grid-4">
<div class="rl-card rl-card--center">
<div class="rl-icon-box"><span style="font-size:1.25rem;font-weight:700">x&#178;</span></div>
<h3>Conviction Voting</h3>
<p>Proposals accumulate conviction score from community votes. The most supported ideas float to the top.</p>
</div>
<div class="rl-card rl-card--center">
<div class="rl-icon-box">&#9878;</div>
<h3>Quadratic Voting</h3>
<p>Each additional vote costs quadratically more credits. Balances intensity of preference with breadth of support.</p>
</div>
<div class="rl-card rl-card--center">
<div class="rl-icon-box">&#128336;</div>
<h3>Proposal Lifecycle</h3>
<p>From ranking through promotion to final pass/fail vote. Proposals advance automatically when thresholds are met.</p>
</div>
<div class="rl-card rl-card--center">
<div class="rl-icon-box">&#127963;</div>
<h3>Democratic Governance</h3>
<p>Daily credit allowances, vote decay, and sybil resistance. One person, one identity, one voice.</p>
</div>
<div style="text-align:center;margin-bottom:2rem">
<span class="rl-badge" style="background:#1e293b;color:#94a3b8;font-size:0.7rem;padding:0.25rem 0.75rem">ELI5</span>
<h2 class="rl-heading" style="margin-top:0.75rem;background:linear-gradient(135deg,#e2e8f0,#cbd5e1);-webkit-background-clip:text;-webkit-text-fill-color:transparent;background-clip:text">
rVote in 30 Seconds
</h2>
<p style="font-size:1.05rem;color:#94a3b8;max-width:640px;margin:0.5rem auto 0">
A <strong style="color:#f97316">quadratic</strong>
<strong style="color:#3b82f6"> Reddit-style ranking system</strong>
with <strong style="color:#a855f7"> time-delayed vote decay</strong>
for proposal prioritization.
</p>
</div>
</div>
</section>
<!-- How It Works -->
<section class="rl-section rl-section--alt">
<div class="rl-container">
<h2 class="rl-heading" style="text-align:center">How It Works</h2>
<div class="rl-grid-3">
<div class="rl-step">
<span class="rl-step__num">1</span>
<h3>Ranking (QPR)</h3>
<p>Community members spend credits to upvote proposals. Conviction score accumulates with quadratic cost.</p>
<!-- Quadratic -->
<div class="rl-card" style="border:2px solid rgba(249,115,22,0.35);background:linear-gradient(to bottom right,rgba(249,115,22,0.08),rgba(249,115,22,0.03))">
<div style="display:flex;align-items:center;gap:0.5rem;margin-bottom:0.75rem">
<div style="width:2rem;height:2rem;border-radius:9999px;background:#f97316;display:flex;align-items:center;justify-content:center">
<span style="color:white;font-weight:700;font-size:0.8rem">x&sup2;</span>
</div>
<h3 style="color:#fb923c;font-size:1.05rem;margin-bottom:0">Quadratic</h3>
</div>
<p>
Voting more costs exponentially more credits. 1 vote = 1 credit, 2 votes = 4, 3 votes = 9.
<strong style="display:block;margin-top:0.5rem;color:#e2e8f0">No single voice can dominate.</strong>
</p>
</div>
<div class="rl-step">
<span class="rl-step__num">2</span>
<h3>Score reaches +100</h3>
<p>When a proposal crosses the promotion threshold (default 100), it automatically enters the final vote.</p>
<!-- Reddit-style -->
<div class="rl-card" style="border:2px solid rgba(59,130,246,0.35);background:linear-gradient(to bottom right,rgba(59,130,246,0.08),rgba(59,130,246,0.03))">
<div style="display:flex;align-items:center;gap:0.5rem;margin-bottom:0.75rem">
<div style="width:2rem;height:2rem;border-radius:9999px;background:#3b82f6;display:flex;align-items:center;justify-content:center">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="white" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><polyline points="18 15 12 9 6 15"/></svg>
</div>
<h3 style="color:#60a5fa;font-size:1.05rem;margin-bottom:0">Reddit-style</h3>
</div>
<p>
Upvote or downvote proposals. Scores aggregate from all community votes.
<strong style="display:block;margin-top:0.5rem;color:#e2e8f0">Best ideas rise to the top.</strong>
</p>
</div>
<div class="rl-step">
<span class="rl-step__num">3</span>
<h3>Pass / Fail Vote</h3>
<p>A time-limited binary vote (Yes / No / Abstain) decides the outcome. Simple majority wins.</p>
<!-- Vote Decay -->
<div class="rl-card" style="border:2px solid rgba(168,85,247,0.35);background:linear-gradient(to bottom right,rgba(168,85,247,0.08),rgba(168,85,247,0.03))">
<div style="display:flex;align-items:center;gap:0.5rem;margin-bottom:0.75rem">
<div style="width:2rem;height:2rem;border-radius:9999px;background:#a855f7;display:flex;align-items:center;justify-content:center">
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><path d="M12 6v6l4 2"/></svg>
</div>
<h3 style="color:#c084fc;font-size:1.05rem;margin-bottom:0">Vote Decay</h3>
</div>
<p>
Votes fade after 30&ndash;60 days. Old support expires, requiring renewed interest.
<strong style="display:block;margin-top:0.5rem;color:#e2e8f0">Rankings stay fresh and relevant.</strong>
</p>
</div>
</div>
</div>
</section>
<!-- What is QPR -->
<!-- Live Demo (textual description, no interactive component) -->
<section class="rl-section rl-section--alt">
<div class="rl-container" style="text-align:center">
<span class="rl-badge" style="background:#1e293b;color:#94a3b8;font-size:0.7rem;padding:0.25rem 0.75rem">Live Demo</span>
<h2 class="rl-heading" style="margin-top:0.75rem;background:linear-gradient(135deg,#e2e8f0,#cbd5e1);-webkit-background-clip:text;-webkit-text-fill-color:transparent;background-clip:text">
Try It Yourself
</h2>
<p style="color:#94a3b8;max-width:640px;margin:0 auto 2rem">
Vote on live polls synced across the r* ecosystem. Changes appear in real-time for everyone.
</p>
<a href="https://demo.rspace.online/rvote" class="rl-cta-primary"
style="background:linear-gradient(to right,#818cf8,#6366f1);color:white">
Open Interactive Demo
</a>
</div>
</section>
<!-- What is Quadratic Proposal Ranking -->
<section class="rl-section">
<div class="rl-container">
<h2 class="rl-heading" style="text-align:center">What is Quadratic Priority Ranking?</h2>
<div class="rl-grid-2" style="margin-top:2rem">
<div class="rl-card">
<h3 style="color:#f87171">The Problem</h3>
<p>Traditional voting (1 person = 1 vote) lets small, passionate groups dominate.
Token-weighted voting lets whales decide everything. Neither reflects genuine community preference.</p>
<div style="text-align:center;margin-bottom:2.5rem">
<span class="rl-tagline" style="color:#818cf8;background:rgba(129,140,248,0.1);border-color:rgba(129,140,248,0.2)">
The Core Concept
</span>
<h2 class="rl-heading" style="background:linear-gradient(135deg,#e2e8f0,#cbd5e1);-webkit-background-clip:text;-webkit-text-fill-color:transparent;background-clip:text">
What is Quadratic Proposal Ranking?
</h2>
<p style="font-size:1.05rem;color:#94a3b8;max-width:640px;margin:0 auto">
A system where expressing <em>strong</em> preference costs progressively more,
creating a fair and balanced priority list that reflects true community consensus.
</p>
</div>
<div class="rl-grid-2" style="max-width:900px;margin:0 auto">
<!-- The Problem -->
<div class="rl-card" style="border:2px solid rgba(239,68,68,0.2);background:rgba(239,68,68,0.04)">
<div style="display:flex;align-items:center;gap:0.5rem;margin-bottom:1rem">
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="#ef4444" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 3l2 7h7l-5.5 4 2 7L12 17l-5.5 4 2-7L3 10h7z"/></svg>
<h3 style="color:#f87171;margin-bottom:0;font-size:1.05rem">The Problem</h3>
</div>
<p style="margin-bottom:0.75rem">
Traditional priority systems let those with more time, resources, or influence dominate what gets attention.
</p>
<ul style="list-style:disc;padding-left:1.25rem;margin:0">
<li style="font-size:0.85rem;color:#94a3b8;line-height:1.6">Loudest voices set the agenda</li>
<li style="font-size:0.85rem;color:#94a3b8;line-height:1.6">Important but less flashy ideas get buried</li>
<li style="font-size:0.85rem;color:#94a3b8;line-height:1.6">No way to express intensity of preference</li>
<li style="font-size:0.85rem;color:#94a3b8;line-height:1.6">Backlogs become political battlegrounds</li>
</ul>
</div>
<div class="rl-card">
<h3 style="color:#14b8a6">The Solution</h3>
<p>Quadratic voting makes strong preferences expensive. You <em>can</em> signal that you care a lot &mdash;
but it costs quadratically more. This balances intensity of preference with breadth of support.</p>
<!-- The Solution -->
<div class="rl-card" style="border:2px solid rgba(129,140,248,0.25);background:linear-gradient(to bottom right,rgba(129,140,248,0.05),rgba(192,132,252,0.05))">
<div style="display:flex;align-items:center;gap:0.5rem;margin-bottom:1rem">
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="#818cf8" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M22 11.08V12a10 10 0 1 1-5.93-9.14"/><polyline points="22 4 12 14.01 9 11.01"/></svg>
<h3 style="color:#a5b4fc;margin-bottom:0;font-size:1.05rem">The Solution: QPR</h3>
</div>
<p style="margin-bottom:0.75rem">
Quadratic Proposal Ranking balances participation and conviction by making additional votes progressively more expensive.
</p>
<ul style="list-style:disc;padding-left:1.25rem;margin:0">
<li style="font-size:0.85rem;color:#94a3b8;line-height:1.6">1 vote = 1 credit, 2 votes = 4, 3 = 9</li>
<li style="font-size:0.85rem;color:#94a3b8;line-height:1.6">Everyone can participate meaningfully</li>
<li style="font-size:0.85rem;color:#94a3b8;line-height:1.6">Express strong opinions, but at a cost</li>
<li style="font-size:0.85rem;color:#94a3b8;line-height:1.6">Naturally surfaces community consensus</li>
</ul>
</div>
</div>
<!-- Vote Cost Calculator -->
<div style="margin-top:2.5rem;max-width:540px;margin-left:auto;margin-right:auto">
<h3 style="text-align:center;font-size:1rem;font-weight:600;color:#e2e8f0;margin-bottom:1rem">
Vote Cost Calculator
</h3>
<div style="display:grid;grid-template-columns:repeat(5,1fr);gap:0.5rem;text-align:center">
<div class="rl-card" style="padding:0.75rem">
<div style="font-size:1.5rem;font-weight:700;color:#818cf8">1</div>
<div style="font-size:0.7rem;color:#64748b">vote</div>
<div style="font-size:1rem;font-family:monospace;margin-top:0.5rem;color:#c084fc">1</div>
<div style="font-size:0.65rem;color:#64748b">credit</div>
</div>
<div class="rl-card" style="padding:0.75rem">
<div style="font-size:1.5rem;font-weight:700;color:#818cf8">2</div>
<div style="font-size:0.7rem;color:#64748b">votes</div>
<div style="font-size:1rem;font-family:monospace;margin-top:0.5rem;color:#c084fc">4</div>
<div style="font-size:0.65rem;color:#64748b">credits</div>
</div>
<div class="rl-card" style="padding:0.75rem">
<div style="font-size:1.5rem;font-weight:700;color:#818cf8">3</div>
<div style="font-size:0.7rem;color:#64748b">votes</div>
<div style="font-size:1rem;font-family:monospace;margin-top:0.5rem;color:#c084fc">9</div>
<div style="font-size:0.65rem;color:#64748b">credits</div>
</div>
<div class="rl-card" style="padding:0.75rem">
<div style="font-size:1.5rem;font-weight:700;color:#818cf8">4</div>
<div style="font-size:0.7rem;color:#64748b">votes</div>
<div style="font-size:1rem;font-family:monospace;margin-top:0.5rem;color:#c084fc">16</div>
<div style="font-size:0.65rem;color:#64748b">credits</div>
</div>
<div class="rl-card" style="padding:0.75rem">
<div style="font-size:1.5rem;font-weight:700;color:#818cf8">5</div>
<div style="font-size:0.7rem;color:#64748b">votes</div>
<div style="font-size:1rem;font-family:monospace;margin-top:0.5rem;color:#c084fc">25</div>
<div style="font-size:0.65rem;color:#64748b">credits</div>
</div>
</div>
<p style="text-align:center;font-size:0.8rem;color:#64748b;margin-top:1rem">
Spreading votes across proposals you support is more efficient than concentrating on one.
</p>
</div>
</div>
</section>
<!-- Vote Cost Calculator -->
<!-- From Chaos to Consensus (How It Works) -->
<section class="rl-section rl-section--alt">
<div class="rl-container">
<h2 class="rl-heading" style="text-align:center">Vote cost calculator</h2>
<p class="rl-subtext" style="text-align:center">The cost of conviction grows quadratically.</p>
<div class="rl-card" style="max-width:500px;margin:2rem auto 0">
<div style="display:grid;grid-template-columns:repeat(5,1fr);gap:0.5rem;text-align:center">
<div>
<div style="font-size:1.5rem;font-weight:700;color:#14b8a6">1</div>
<div style="font-size:0.7rem;color:#64748b">vote</div>
<div style="font-size:0.85rem;font-weight:600;color:#e2e8f0;margin-top:0.25rem">1 credit</div>
<div style="text-align:center;margin-bottom:2.5rem">
<span class="rl-tagline" style="color:#818cf8;background:rgba(129,140,248,0.1);border-color:rgba(129,140,248,0.2)">
How It Works
</span>
<h2 class="rl-heading" style="background:linear-gradient(135deg,#e2e8f0,#cbd5e1);-webkit-background-clip:text;-webkit-text-fill-color:transparent;background-clip:text">
From Chaos to Consensus
</h2>
<p style="font-size:1.05rem;color:#94a3b8;max-width:640px;margin:0 auto">
Transform your community&rsquo;s ideas into a democratically prioritized backlog
through two simple stages.
</p>
</div>
<div class="rl-grid-3">
<!-- Stage 1: QPR -->
<div class="rl-card" style="border-color:rgba(129,140,248,0.2)">
<div style="display:flex;align-items:center;gap:0.75rem;margin-bottom:1rem">
<div style="width:2.5rem;height:2.5rem;border-radius:9999px;background:linear-gradient(to bottom right,#818cf8,rgba(129,140,248,0.6));display:flex;align-items:center;justify-content:center">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="10" y1="6" x2="21" y2="6"/><line x1="10" y1="12" x2="21" y2="12"/><line x1="10" y1="18" x2="21" y2="18"/><path d="M4 6h1v4"/><path d="M4 10h2"/><path d="M6 18H4c0-1 2-2 2-3s-1-1.5-2-1"/></svg>
</div>
<div>
<span class="rl-badge" style="background:rgba(129,140,248,0.1);color:#818cf8;margin-bottom:0.25rem">Stage 1</span>
<h3 style="margin-bottom:0;font-size:1rem">Quadratic Proposal Ranking</h3>
</div>
</div>
<div>
<div style="font-size:1.5rem;font-weight:700;color:#14b8a6">2</div>
<div style="font-size:0.7rem;color:#64748b">votes</div>
<div style="font-size:0.85rem;font-weight:600;color:#e2e8f0;margin-top:0.25rem">4 credits</div>
<ul style="list-style:none;padding:0;margin:0">
<li style="display:flex;align-items:flex-start;gap:0.5rem;font-size:0.85rem;color:#94a3b8;line-height:1.6;padding:0.2rem 0">
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="#818cf8" stroke-width="2" style="flex-shrink:0;margin-top:3px"><polyline points="23 6 13.5 15.5 8.5 10.5"/><polyline points="17 6 7.5 15.5 2.5 10.5"/></svg>
<span>All proposals enter the ranking pool</span>
</li>
<li style="display:flex;align-items:flex-start;gap:0.5rem;font-size:0.85rem;color:#94a3b8;line-height:1.6;padding:0.2rem 0">
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="#818cf8" stroke-width="2" style="flex-shrink:0;margin-top:3px"><circle cx="12" cy="12" r="10"/><path d="M12 6v6l4 2"/></svg>
<span>Upvote/downvote with quadratic cost</span>
</li>
<li style="display:flex;align-items:flex-start;gap:0.5rem;font-size:0.85rem;color:#94a3b8;line-height:1.6;padding:0.2rem 0">
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="#818cf8" stroke-width="2" style="flex-shrink:0;margin-top:3px"><polyline points="22 12 18 12 15 21 9 3 6 12 2 12"/></svg>
<span>Votes decay over 30&ndash;60 days</span>
</li>
<li style="display:flex;align-items:flex-start;gap:0.5rem;font-size:0.85rem;color:#94a3b8;line-height:1.6;padding:0.2rem 0">
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="#818cf8" stroke-width="2" style="flex-shrink:0;margin-top:3px"><circle cx="12" cy="12" r="3"/><circle cx="12" cy="12" r="10"/></svg>
<span>Creates a living priority queue</span>
</li>
</ul>
</div>
<!-- Threshold -->
<div class="rl-card" style="border-color:rgba(192,132,252,0.25);background:linear-gradient(to bottom right,rgba(192,132,252,0.08),rgba(129,140,248,0.06))">
<div style="display:flex;align-items:center;gap:0.75rem;margin-bottom:1rem">
<div style="width:2.5rem;height:2.5rem;border-radius:9999px;background:linear-gradient(to bottom right,#c084fc,#818cf8);display:flex;align-items:center;justify-content:center">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="5" y1="12" x2="19" y2="12"/><polyline points="12 5 19 12 12 19"/></svg>
</div>
<div>
<span class="rl-badge" style="background:rgba(192,132,252,0.15);color:#c084fc;margin-bottom:0.25rem">Threshold</span>
<h3 style="margin-bottom:0;font-size:1rem">Score +100</h3>
</div>
</div>
<div>
<div style="font-size:1.5rem;font-weight:700;color:#14b8a6">3</div>
<div style="font-size:0.7rem;color:#64748b">votes</div>
<div style="font-size:0.85rem;font-weight:600;color:#e2e8f0;margin-top:0.25rem">9 credits</div>
</div>
<div>
<div style="font-size:1.5rem;font-weight:700;color:#14b8a6">4</div>
<div style="font-size:0.7rem;color:#64748b">votes</div>
<div style="font-size:0.85rem;font-weight:600;color:#e2e8f0;margin-top:0.25rem">16 credits</div>
</div>
<div>
<div style="font-size:1.5rem;font-weight:700;color:#14b8a6">5</div>
<div style="font-size:0.7rem;color:#64748b">votes</div>
<div style="font-size:0.85rem;font-weight:600;color:#e2e8f0;margin-top:0.25rem">25 credits</div>
<p>
When a proposal reaches a score of <strong style="color:#e2e8f0">+100</strong>, it
automatically advances to the final voting stage.
</p>
<p style="margin-top:0.5rem;font-size:0.8rem">
This ensures only proposals with genuine community support move
forward for implementation decisions.
</p>
</div>
<!-- Stage 2: Pass/Fail -->
<div class="rl-card" style="border-color:rgba(148,163,184,0.2)">
<div style="display:flex;align-items:center;gap:0.75rem;margin-bottom:1rem">
<div style="width:2.5rem;height:2.5rem;border-radius:9999px;background:linear-gradient(to bottom right,#94a3b8,rgba(148,163,184,0.6));display:flex;align-items:center;justify-content:center">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M22 11.08V12a10 10 0 1 1-5.93-9.14"/><polyline points="22 4 12 14.01 9 11.01"/></svg>
</div>
<div>
<span class="rl-badge" style="background:rgba(148,163,184,0.1);color:#94a3b8;margin-bottom:0.25rem">Stage 2</span>
<h3 style="margin-bottom:0;font-size:1rem">Pass/Fail Vote</h3>
</div>
</div>
<ul style="list-style:none;padding:0;margin:0">
<li style="display:flex;align-items:flex-start;gap:0.5rem;font-size:0.85rem;color:#94a3b8;line-height:1.6;padding:0.2rem 0">
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="#94a3b8" stroke-width="2" style="flex-shrink:0;margin-top:3px"><path d="M22 11.08V12a10 10 0 1 1-5.93-9.14"/><polyline points="22 4 12 14.01 9 11.01"/></svg>
<span>Yes / No / Abstain voting</span>
</li>
<li style="display:flex;align-items:flex-start;gap:0.5rem;font-size:0.85rem;color:#94a3b8;line-height:1.6;padding:0.2rem 0">
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="#94a3b8" stroke-width="2" style="flex-shrink:0;margin-top:3px"><path d="M17 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2"/><circle cx="9" cy="7" r="4"/><path d="M23 21v-2a4 4 0 0 0-3-3.87"/><path d="M16 3.13a4 4 0 0 1 0 7.75"/></svg>
<span>One member = one vote</span>
</li>
<li style="display:flex;align-items:flex-start;gap:0.5rem;font-size:0.85rem;color:#94a3b8;line-height:1.6;padding:0.2rem 0">
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="#94a3b8" stroke-width="2" style="flex-shrink:0;margin-top:3px"><circle cx="12" cy="12" r="10"/><path d="M12 6v6l4 2"/></svg>
<span>7-day voting period</span>
</li>
<li style="display:flex;align-items:flex-start;gap:0.5rem;font-size:0.85rem;color:#94a3b8;line-height:1.6;padding:0.2rem 0">
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="#94a3b8" stroke-width="2" style="flex-shrink:0;margin-top:3px"><polyline points="20 6 9 17 4 12"/></svg>
<span>Majority decides implementation</span>
</li>
</ul>
</div>
</div>
</div>
</section>
<!-- Built for real governance -->
<!-- Features: Built for Fair Prioritization -->
<section class="rl-section">
<div class="rl-container">
<h2 class="rl-heading" style="text-align:center">Built for real governance</h2>
<div class="rl-grid-4" style="margin-top:2rem">
<div class="rl-card rl-card--center">
<div class="rl-icon-box">
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><path d="M12 6v6l4 2"/></svg>
<div style="text-align:center;margin-bottom:2.5rem">
<h2 class="rl-heading" style="background:linear-gradient(135deg,#e2e8f0,#cbd5e1);-webkit-background-clip:text;-webkit-text-fill-color:transparent;background-clip:text">
Built for Fair Prioritization
</h2>
<p style="color:#94a3b8">Everything you need for democratic backlog management</p>
</div>
<div class="rl-grid-4">
<div class="rl-card rl-card--center" style="border-color:rgba(129,140,248,0.15)">
<div style="width:3rem;height:3rem;border-radius:9999px;background:linear-gradient(to bottom right,#22c55e,#059669);display:flex;align-items:center;justify-content:center;margin:0 auto 0.75rem">
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><path d="M12 6v6l4 2"/></svg>
</div>
<h3>Earn Credits Daily</h3>
<p>Every verified member receives a daily credit allowance. No pay-to-play.</p>
<p>Get 10 credits every day. Start with 50. Max 500.</p>
</div>
<div class="rl-card rl-card--center">
<div class="rl-icon-box">
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="22 12 18 12 15 21 9 3 6 12 2 12"/></svg>
<div class="rl-card rl-card--center" style="border-color:rgba(129,140,248,0.15)">
<div style="width:3rem;height:3rem;border-radius:9999px;background:linear-gradient(to bottom right,#3b82f6,#0891b2);display:flex;align-items:center;justify-content:center;margin:0 auto 0.75rem">
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="22 12 18 12 15 21 9 3 6 12 2 12"/></svg>
</div>
<h3>Vote Decay</h3>
<p>Votes decay linearly from day 30 to day 60. Stale support fades, keeping rankings fresh.</p>
<p>Old votes fade away, keeping rankings fresh and dynamic.</p>
</div>
<div class="rl-card rl-card--center">
<div class="rl-icon-box">
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z"/></svg>
<div class="rl-card rl-card--center" style="border-color:rgba(129,140,248,0.15)">
<div style="width:3rem;height:3rem;border-radius:9999px;background:linear-gradient(to bottom right,#a855f7,#7c3aed);display:flex;align-items:center;justify-content:center;margin:0 auto 0.75rem">
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z"/></svg>
</div>
<h3>Sybil Resistant</h3>
<p>Passkey authentication via EncryptID. One person, one identity, one credit stream.</p>
<p>Quadratic costs make fake account attacks expensive.</p>
</div>
<div class="rl-card rl-card--center">
<div class="rl-icon-box">
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="17 1 21 5 17 9"/><path d="M3 11V9a4 4 0 014-4h14"/><polyline points="7 23 3 19 7 15"/><path d="M21 13v2a4 4 0 01-4 4H3"/></svg>
<div class="rl-card rl-card--center" style="border-color:rgba(129,140,248,0.15)">
<div style="width:3rem;height:3rem;border-radius:9999px;background:linear-gradient(to bottom right,#f97316,#d97706);display:flex;align-items:center;justify-content:center;margin:0 auto 0.75rem">
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polygon points="13 2 3 14 12 14 11 22 21 10 12 10 13 2"/></svg>
</div>
<h3>Auto Promotion</h3>
<p>Proposals that hit the threshold automatically move to a final pass/fail vote. No admin bottleneck.</p>
</div>
</div>
</div>
</section>
<!-- Built on Open Source -->
<section class="rl-section rl-section--alt">
<div class="rl-container">
<h2 class="rl-heading" style="text-align:center">Built on Open Source</h2>
<p class="rl-subtext" style="text-align:center">The libraries and tools that power rVote.</p>
<div class="rl-grid-3">
<div class="rl-card rl-card--center">
<div class="rl-icon-box">&#128451;</div>
<h3>PostgreSQL</h3>
<p>Rock-solid relational database for proposals, votes, credit balances, and governance history.</p>
</div>
<div class="rl-card rl-card--center">
<div class="rl-icon-box"><span style="font-size:1.25rem;font-weight:700">x&#178;</span></div>
<h3>Conviction Voting Algorithm</h3>
<p>Continuous preference signaling with quadratic cost and time-decay. Open-source governance math.</p>
</div>
<div class="rl-card rl-card--center">
<div class="rl-icon-box">&#128293;</div>
<h3>Hono</h3>
<p>Ultrafast web framework for the API layer. Lightweight, edge-ready, and built for speed.</p>
</div>
</div>
</div>
</section>
<!-- Your Data, Protected -->
<section class="rl-section">
<div class="rl-container" style="text-align:center">
<h2 class="rl-heading">Your Data, Protected</h2>
<p class="rl-subtext">How rVote keeps your information safe.</p>
<div class="rl-grid-3">
<div class="rl-card rl-card--center">
<div class="rl-icon-box">&#128274;</div>
<h3>End-to-End Encryption</h3>
<span class="rl-badge">Coming Soon</span>
<p>All content encrypted before it leaves your device. Not even the server can read it.</p>
</div>
<div class="rl-card rl-card--center">
<div class="rl-icon-box">&#128373;</div>
<h3>Zero-Knowledge Architecture</h3>
<span class="rl-badge">Coming Soon</span>
<p>The server processes your requests without ever seeing your data in the clear.</p>
</div>
<div class="rl-card rl-card--center">
<div class="rl-icon-box">&#127968;</div>
<h3>Self-Hosted</h3>
<p>Run on your own infrastructure. Your server, your rules, your data.</p>
<p>Top proposals automatically advance to voting.</p>
</div>
</div>
</div>
@ -218,12 +355,33 @@ export function renderLanding(): string {
<!-- CTA -->
<section class="rl-section rl-section--alt">
<div class="rl-container" style="text-align:center">
<h2 class="rl-heading">(You)rVote, your voice.</h2>
<p class="rl-subtext">Try the demo or create a space to get started.</p>
<div class="rl-cta-row">
<a href="https://demo.rspace.online/rvote" class="rl-cta-primary">Start Voting</a>
<a href="/create-space" class="rl-cta-secondary">Create a Space</a>
<div class="rl-container">
<div class="rl-card" style="border:2px solid rgba(129,140,248,0.25);background:linear-gradient(to bottom right,rgba(129,140,248,0.08),rgba(192,132,252,0.04),rgba(148,163,184,0.06));text-align:center;padding:3rem 2rem;position:relative;overflow:hidden">
<span class="rl-badge" style="background:rgba(129,140,248,0.1);color:#818cf8;font-size:0.7rem;padding:0.25rem 0.75rem">
Join the rSpace Ecosystem
</span>
<h2 style="font-size:1.75rem;font-weight:700;color:#e2e8f0;margin:1rem 0">
Ready to prioritize democratically?
</h2>
<p style="font-size:1.05rem;color:#94a3b8;max-width:560px;margin:0 auto 2rem;line-height:1.6">
Create a Space for your community and start using Quadratic Proposal Ranking.
Invite members, allot credits, and let the best ideas rise to the top.
</p>
<div class="rl-cta-row" style="margin-top:0">
<a href="/create-space" class="rl-cta-primary"
style="background:linear-gradient(to right,#818cf8,#c084fc);color:white">
<span style="display:inline-flex;align-items:center;gap:0.5rem">
Create a Space
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="5" y1="12" x2="19" y2="12"/><polyline points="12 5 19 12 12 19"/></svg>
</span>
</a>
<a href="https://demo.rspace.online/rvote" class="rl-cta-secondary">
<span style="display:inline-flex;align-items:center;gap:0.5rem">
<svg width="16" height="16" viewBox="0 0 24 24" fill="currentColor" stroke="none"><polygon points="5,3 19,12 5,21"/></svg>
Interactive Demo
</span>
</a>
</div>
</div>
</div>
</section>

View File

@ -1,136 +1,183 @@
/**
* rWork landing page collective task management.
* Ported from rwork-online Next.js page.tsx (shadcn/ui + Lucide).
*/
export function renderLanding(): string {
return `
<!-- Hero -->
<div class="rl-hero">
<span class="rl-tagline">rWork</span>
<h1 class="rl-heading">(You)rWork, your flow.</h1>
<p class="rl-subtitle">Get things done, together</p>
<span class="rl-tagline">Part of the rSpace Ecosystem</span>
<h1 class="rl-heading">Collective<br>
<span style="background:linear-gradient(135deg,#3b82f6,#14b8a6);-webkit-background-clip:text;background-clip:text;color:transparent">Task Management</span>
</h1>
<p class="rl-subtext">
Kanban boards, team spaces, and real-time collaboration &mdash; built for groups
that share work, not just assign it.
Create <strong style="color:#e2e8f0">Spaces</strong> for your community to collaborate on shared projects.
Track tasks through pipelines with <strong style="color:#e2e8f0">real-time kanban boards</strong> powered
by markdown-native task management.
</p>
<div class="rl-cta-row">
<a href="https://demo.rspace.online/rwork" class="rl-cta-primary" id="ml-primary">Start Working</a>
<a href="/create-space" class="rl-cta-secondary">Create a Space</a>
<a href="https://demo.rspace.online/rwork" class="rl-cta-primary" id="ml-primary">
Get Started &rarr;
</a>
<a href="https://demo.rspace.online/rwork" class="rl-cta-secondary">View Dashboard</a>
</div>
</div>
<!-- Features -->
<section class="rl-section">
<div class="rl-container">
<h2 class="rl-heading" style="text-align:center">What rWork Handles</h2>
<div class="rl-grid-4">
<div class="rl-card rl-card--center">
<div class="rl-icon-box">&#128203;</div>
<h3>Kanban Boards</h3>
<p>Drag-and-drop columns with customizable statuses. See everything at a glance.</p>
</div>
<div class="rl-card rl-card--center">
<div class="rl-icon-box">&#9745;</div>
<h3>Task Management</h3>
<p>Create tasks with titles, descriptions, labels, and priorities. Track progress across your team.</p>
</div>
<div class="rl-card rl-card--center">
<div class="rl-icon-box">&#128200;</div>
<h3>Activity Logging</h3>
<p>Every change is tracked. See who moved what, when, and why &mdash; full audit trail.</p>
</div>
<div class="rl-card rl-card--center">
<div class="rl-icon-box">&#128101;</div>
<h3>Workspace Collaboration</h3>
<p>Each workspace is scoped to a space. Members share boards, tasks, and activity in real time.</p>
</div>
</div>
</div>
</section>
<!-- How It Works -->
<section class="rl-section rl-section--alt">
<div class="rl-container">
<h2 class="rl-heading" style="text-align:center">How It Works</h2>
<div style="text-align:center;margin-bottom:1.5rem">
<span class="rl-badge">How It Works</span>
<h2 class="rl-heading" style="margin-top:0.75rem">rWork in 30 Seconds</h2>
<p class="rl-subtext">
<strong style="color:#3b82f6">Create a Space</strong> for your community,
<strong style="color:#14b8a6">add tasks</strong> to your pipeline, and
<strong style="color:#e2e8f0">track progress</strong> together in real-time.
</p>
</div>
<div class="rl-grid-3">
<div class="rl-step">
<span class="rl-step__num">1</span>
<h3>Create a workspace</h3>
<p>Every workspace lives inside an rSpace &mdash; shared by default with your team.</p>
<div class="rl-card" style="border:2px solid rgba(59,130,246,0.4);background:linear-gradient(135deg,rgba(59,130,246,0.1),rgba(59,130,246,0.05))">
<div style="display:flex;align-items:center;gap:0.5rem;margin-bottom:0.75rem">
<div style="height:2rem;width:2rem;border-radius:50%;background:#3b82f6;display:flex;align-items:center;justify-content:center">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M20 20a2 2 0 002-2V8a2 2 0 00-2-2h-7.9a2 2 0 01-1.69-.9L9.6 3.9A2 2 0 007.93 3H4a2 2 0 00-2 2v13a2 2 0 002 2h16z"/><rect x="8" y="10" width="8" height="6" rx="1"/></svg>
</div>
<h3 style="font-weight:700;font-size:1.125rem;color:#e2e8f0">1. Create a Space</h3>
</div>
<p style="font-size:0.875rem;color:#94a3b8;line-height:1.6">
Set up a workspace for your project or community. Configure your pipeline
statuses and invite members.
<strong style="color:#e2e8f0;display:block;margin-top:0.5rem">Each Space gets its own kanban board.</strong>
</p>
</div>
<div class="rl-step">
<span class="rl-step__num">2</span>
<h3>Add tasks and boards</h3>
<p>Create tasks with titles, descriptions, labels, and priorities. Drag them across columns.</p>
<div class="rl-card" style="border:2px solid rgba(20,184,166,0.4);background:linear-gradient(135deg,rgba(20,184,166,0.1),rgba(20,184,166,0.05))">
<div style="display:flex;align-items:center;gap:0.5rem;margin-bottom:0.75rem">
<div style="height:2rem;width:2rem;border-radius:50%;background:#14b8a6;display:flex;align-items:center;justify-content:center">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="3" width="7" height="7"/><rect x="14" y="3" width="7" height="7"/><rect x="3" y="14" width="7" height="7"/><rect x="14" y="14" width="7" height="7"/></svg>
</div>
<h3 style="font-weight:700;font-size:1.125rem;color:#e2e8f0">2. Add Tasks</h3>
</div>
<p style="font-size:0.875rem;color:#94a3b8;line-height:1.6">
Create tasks with descriptions, priorities, labels, and acceptance criteria.
Assign them to team members.
<strong style="color:#e2e8f0;display:block;margin-top:0.5rem">Tasks are stored as plain markdown files.</strong>
</p>
</div>
<div class="rl-step">
<span class="rl-step__num">3</span>
<h3>Track progress together</h3>
<p>Assign, comment, and track progress in real time. Everyone sees the same board.</p>
<div class="rl-card" style="border:2px solid rgba(100,116,139,0.4);background:linear-gradient(135deg,rgba(100,116,139,0.1),rgba(100,116,139,0.05))">
<div style="display:flex;align-items:center;gap:0.5rem;margin-bottom:0.75rem">
<div style="height:2rem;width:2rem;border-radius:50%;background:#64748b;display:flex;align-items:center;justify-content:center">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polygon points="13 2 3 14 12 14 11 22 21 10 12 10 13 2"/></svg>
</div>
<h3 style="font-weight:700;font-size:1.125rem;color:#e2e8f0">3. Collaborate</h3>
</div>
<p style="font-size:0.875rem;color:#94a3b8;line-height:1.6">
Drag tasks through your pipeline in real-time. Everyone sees updates instantly
via WebSocket sync.
<strong style="color:#e2e8f0;display:block;margin-top:0.5rem">Work together, stay in sync.</strong>
</p>
</div>
</div>
</div>
</section>
<!-- Built on Open Source -->
<!-- Features Row 1 -->
<section class="rl-section">
<div class="rl-container">
<h2 class="rl-heading" style="text-align:center">Built on Open Source</h2>
<p class="rl-subtext" style="text-align:center">The libraries and tools that power rWork.</p>
<div class="rl-grid-3">
<h2 class="rl-heading" style="text-align:center">Built for Community Collaboration</h2>
<p class="rl-subtext" style="text-align:center">Everything you need to coordinate shared work</p>
<div class="rl-grid-4">
<div class="rl-card rl-card--center">
<div class="rl-icon-box">&#128293;</div>
<h3>Hono</h3>
<p>Ultrafast web framework for the API layer. Lightweight, edge-ready, and built for speed.</p>
<div class="rl-icon-box" style="background:linear-gradient(135deg,#3b82f6,rgba(59,130,246,0.6))">
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="3" width="7" height="7"/><rect x="14" y="3" width="7" height="7"/><rect x="3" y="14" width="7" height="7"/><rect x="14" y="14" width="7" height="7"/></svg>
</div>
<h3>Kanban Boards</h3>
<p>Drag-and-drop tasks through customizable pipeline stages.</p>
</div>
<div class="rl-card rl-card--center">
<div class="rl-icon-box">&#128451;</div>
<h3>PostgreSQL</h3>
<p>Rock-solid relational database for task storage, workspaces, boards, and activity logs.</p>
<div class="rl-icon-box" style="background:linear-gradient(135deg,#14b8a6,rgba(20,184,166,0.6))">
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M16 21v-2a4 4 0 00-4-4H6a4 4 0 00-4-4v2"/><circle cx="9" cy="7" r="4"/><path d="M22 21v-2a4 4 0 00-3-3.87"/><path d="M16 3.13a4 4 0 010 7.75"/></svg>
</div>
<h3>Team Spaces</h3>
<p>Create isolated workspaces with role-based access control.</p>
</div>
<div class="rl-card rl-card--center">
<div class="rl-icon-box">&#9889;</div>
<h3>Bun</h3>
<p>All-in-one JavaScript runtime. Fast startup, native TypeScript, and built-in bundling.</p>
<div class="rl-icon-box" style="background:linear-gradient(135deg,#22c55e,#059669)">
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polygon points="13 2 3 14 12 14 11 22 21 10 12 10 13 2"/></svg>
</div>
<h3>Real-time Sync</h3>
<p>Changes appear instantly for all members via WebSocket.</p>
</div>
<div class="rl-card rl-card--center">
<div class="rl-icon-box" style="background:linear-gradient(135deg,#f97316,#d97706)">
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="6" y1="3" x2="6" y2="15"/><circle cx="18" cy="6" r="3"/><circle cx="6" cy="18" r="3"/><path d="M18 9a9 9 0 01-9 9"/></svg>
</div>
<h3>Markdown Native</h3>
<p>Tasks stored as plain .md files. Version-controllable, AI-friendly.</p>
</div>
</div>
</div>
</section>
<!-- Your Data, Protected -->
<section class="rl-section rl-section--alt">
<div class="rl-container" style="text-align:center">
<h2 class="rl-heading">Your Data, Protected</h2>
<p class="rl-subtext">How rWork keeps your information safe.</p>
<div class="rl-grid-3">
<!-- Features Row 2 -->
<div class="rl-grid-4" style="margin-top:1rem">
<div class="rl-card rl-card--center">
<div class="rl-icon-box">&#128274;</div>
<h3>End-to-End Encryption</h3>
<span class="rl-badge">Coming Soon</span>
<p>All content encrypted before it leaves your device. Not even the server can read it.</p>
<div class="rl-icon-box" style="background:linear-gradient(135deg,#a855f7,#7c3aed)">
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="2" y="7" width="20" height="14" rx="2" ry="2"/><path d="M16 21V5a2 2 0 00-2-2h-4a2 2 0 00-2 2v16"/></svg>
</div>
<h3>Custom Pipelines</h3>
<p>Define your own workflow stages beyond To Do / In Progress / Done.</p>
</div>
<div class="rl-card rl-card--center">
<div class="rl-icon-box">&#128373;</div>
<h3>Zero-Knowledge Architecture</h3>
<span class="rl-badge">Coming Soon</span>
<p>The server processes your requests without ever seeing your data in the clear.</p>
<div class="rl-icon-box" style="background:linear-gradient(135deg,#3b82f6,#0891b2)">
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M18 8A6 6 0 006 8c0 7-3 9-3 9h18s-3-2-3-9"/><path d="M13.73 21a2 2 0 01-3.46 0"/></svg>
</div>
<h3>Notifications</h3>
<p>Stay informed when tasks are assigned, updated, or completed.</p>
</div>
<div class="rl-card rl-card--center">
<div class="rl-icon-box">&#127968;</div>
<h3>Self-Hosted</h3>
<p>Run on your own infrastructure. Your server, your rules, your data.</p>
<div class="rl-icon-box" style="background:linear-gradient(135deg,#f43f5e,#ec4899)">
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M22 11.08V12a10 10 0 11-5.93-9.14"/><polyline points="22 4 12 14.01 9 11.01"/></svg>
</div>
<h3>Acceptance Criteria</h3>
<p>Define checklists for what &ldquo;done&rdquo; means on each task.</p>
</div>
<div class="rl-card rl-card--center">
<div class="rl-icon-box" style="background:linear-gradient(135deg,#14b8a6,#0891b2)">
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><line x1="2" y1="12" x2="22" y2="12"/><path d="M12 2a15.3 15.3 0 014 10 15.3 15.3 0 01-4 10 15.3 15.3 0 01-4-10 15.3 15.3 0 014-10z"/></svg>
</div>
<h3>rSpace Ecosystem</h3>
<p>Integrates with rVote, rMaps, rNotes, and the full r* suite.</p>
</div>
</div>
</div>
</section>
<!-- CTA -->
<section class="rl-section">
<div class="rl-container" style="text-align:center">
<h2 class="rl-heading">(You)rWork, your flow.</h2>
<p class="rl-subtext">Try the demo or create a space to get started.</p>
<div class="rl-cta-row">
<a href="https://demo.rspace.online/rwork" class="rl-cta-primary">Start Working</a>
<a href="/create-space" class="rl-cta-secondary">Create a Space</a>
<section class="rl-section rl-section--alt">
<div class="rl-container">
<div class="rl-card" style="border:2px solid rgba(59,130,246,0.3);background:linear-gradient(135deg,rgba(59,130,246,0.1),rgba(20,184,166,0.05),rgba(100,116,139,0.1));text-align:center;padding:3rem 1.5rem;position:relative;overflow:hidden">
<div style="position:absolute;top:0;right:0;width:16rem;height:16rem;background:rgba(59,130,246,0.1);border-radius:50%;filter:blur(48px)"></div>
<div style="position:absolute;bottom:0;left:0;width:16rem;height:16rem;background:rgba(20,184,166,0.1);border-radius:50%;filter:blur(48px)"></div>
<div style="position:relative">
<span class="rl-badge">Join the rSpace Ecosystem</span>
<h2 class="rl-heading" style="margin-top:1rem">Ready to collaborate?</h2>
<p class="rl-subtext" style="max-width:36rem;margin:0.5rem auto 0">
Create a Space for your community and start tracking tasks together.
Invite members, configure your pipeline, and ship faster as a team.
</p>
<div class="rl-cta-row" style="margin-top:1.5rem">
<a href="https://demo.rspace.online/rwork" class="rl-cta-primary">
Create a Space &rarr;
</a>
</div>
</div>
</div>
</div>
</section>