Compare commits

..

No commits in common. "c20a79078a63131cb91e2d4d90d12ee4c9ba68e1" and "c59b7d85a1d241ab0a300abed1deeb40edbc00a4" have entirely different histories.

10 changed files with 1269 additions and 1798 deletions

View File

@ -1,202 +1,152 @@
/**
* 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" 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>
<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>
<p class="rl-subtext">
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.
A spatiotemporal calendar that couples where and when, supports natural cycles,
and zooms from 30-second moments to geological epochs.
</p>
<div class="rl-cta-row">
<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>
<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>
</div>
</div>
<!-- Principles (4-card grid) -->
<section class="rl-section" style="border-top:none">
<div class="rl-container">
<div class="rl-grid-4">
<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" 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" 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" 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>
<!-- Why rCal -->
<section id="features" class="rl-section rl-section--alt">
<div class="rl-container">
<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-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-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 Levels -->
<!-- Features -->
<section class="rl-section">
<div class="rl-container">
<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">
<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>
<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>
<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>
<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>
</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>Create events</h3>
<p>Add events with time, location, and source context. Pull from ICS feeds, CalDAV, or other r* modules.</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>
<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>
</div>
</div>
</section>
<!-- Temporal Zoom -->
<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">
<div class="rl-zoom-bar__row">
<span class="rl-zoom-bar__label">0</span>
<div class="rl-zoom-bar__bar" style="width:4%;background:rgba(59,130,246,0.25)">
<div class="rl-zoom-bar__bar" style="width:10%;background:rgba(99,102,241,0.3)">
<span class="rl-zoom-bar__name">Moment</span>
</div>
<span class="rl-zoom-bar__span">30 seconds</span>
<span class="rl-zoom-bar__span">30 s</span>
</div>
<div class="rl-zoom-bar__row">
<span class="rl-zoom-bar__label">1</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 class="rl-zoom-bar__bar" style="width:15%;background:rgba(99,102,241,0.28)">
<span class="rl-zoom-bar__name">Minute</span>
</div>
<span class="rl-zoom-bar__span">60 minutes</span>
<span class="rl-zoom-bar__span">1&ndash;10 min</span>
</div>
<div class="rl-zoom-bar__row">
<span class="rl-zoom-bar__label">2</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 class="rl-zoom-bar__bar" style="width:22%;background:rgba(99,102,241,0.25)">
<span class="rl-zoom-bar__name">Hour</span>
</div>
<span class="rl-zoom-bar__span">24 hours</span>
<span class="rl-zoom-bar__span">1&ndash;6 hrs</span>
</div>
<div class="rl-zoom-bar__row">
<span class="rl-zoom-bar__label">3</span>
<div class="rl-zoom-bar__bar" style="width:22%;background:rgba(129,140,248,0.22)">
<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)">
<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">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">~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 class="rl-zoom-bar__bar" style="width:50%;background:rgba(99,102,241,0.18)">
<span class="rl-zoom-bar__name">Lunar</span>
</div>
<span class="rl-zoom-bar__span">~3 months</span>
<span class="rl-zoom-bar__span">29.5 days</span>
</div>
<div class="rl-zoom-bar__row">
<span class="rl-zoom-bar__label">6</span>
<div class="rl-zoom-bar__bar" style="width:58%;background:rgba(167,139,250,0.18)">
<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)">
<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">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">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 class="rl-zoom-bar__bar" style="width:85%;background:rgba(99,102,241,0.12)">
<span class="rl-zoom-bar__name">Epoch</span>
</div>
<span class="rl-zoom-bar__span">100 years</span>
<span class="rl-zoom-bar__span">decades&ndash;centuries</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(147,51,234,0.15)">
<div class="rl-zoom-bar__bar" style="width:100%;background:rgba(99,102,241,0.10)">
<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>
@ -206,63 +156,31 @@ export function renderLanding(): string {
<!-- Calendar Views -->
<section class="rl-section rl-section--alt">
<div class="rl-container">
<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>
<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>
</div>
<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 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>
<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 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>
<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 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>
</div>
</div>
@ -271,78 +189,115 @@ export function renderLanding(): string {
<!-- Ecosystem Integration -->
<section class="rl-section">
<div class="rl-container">
<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>
<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>
<div class="rl-grid-3" style="margin-top:2rem">
<div class="rl-integration" style="border-color:rgba(52,211,153,0.15)">
<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-icon-box" style="flex-shrink:0"><span style="font-size:1.25rem">&#128506;</span></div>
<div>
<h3>rTrips</h3>
<p>Trip itineraries auto-populate with calendar events for departure, accommodation, and activities.</p>
<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>
</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">&#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-integration">
<div class="rl-icon-box" style="flex-shrink:0"><span style="font-size:1.25rem">&#128101;</span></div>
<div>
<h3>rNetwork</h3>
<p>See when your community members are available and schedule group meetings.</p>
<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>
</div>
</div>
<div class="rl-integration" style="border-color:rgba(52,211,153,0.15)">
<div class="rl-integration">
<div class="rl-icon-box" style="flex-shrink:0"><span style="font-size:1.25rem">&#128722;</span></div>
<div>
<h3>rCart</h3>
<p>Product launches, market days, and delivery windows sync to your calendar.</p>
<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>
</div>
</div>
<div class="rl-integration" style="border-color:rgba(52,211,153,0.15)">
<div class="rl-integration">
<div class="rl-icon-box" style="flex-shrink:0"><span style="font-size:1.25rem">&#128221;</span></div>
<div>
<h3>rNotes</h3>
<p>Meeting notes link back to calendar events. Transcriptions attach to the moment they happened.</p>
<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>
</div>
</div>
<div class="rl-integration" style="border-color:rgba(52,211,153,0.15)">
<div class="rl-integration">
<div class="rl-icon-box" style="flex-shrink:0"><span style="font-size:1.25rem">&#127760;</span></div>
<div>
<h3>rSpace</h3>
<p>Each space gets its own calendar. Subdomain routing means each community has a dedicated view.</p>
<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>
</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" 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>
<h2 class="rl-heading">(You)rCal, your rhythm.</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/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>
<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>
</div>
</div>
</section>

View File

@ -1,198 +1,165 @@
/**
* rChoices landing page quick collaborative decisions.
* Ported from the Next.js page.tsx. Interactive React demos (SpiderDemo,
* RankingDemo, VotingDemo) replaced with text descriptions.
* rChoices rich landing page body.
* Returned by landingPage() in the module export;
* the shell wraps it with header, CSS, and analytics.
*/
export function renderLanding(): string {
return `
return `
<!-- Hero -->
<div class="rl-hero">
<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>
<span class="rl-tagline">rChoices</span>
<h1 class="rl-heading">(You)rChoices, your voice.</h1>
<p class="rl-subtitle">Decide Together, Fairly</p>
<p class="rl-subtext">
Spider plots to weigh trade-offs. Rankings to sort preferences.
Live voting to decide fast. Powered by rSpace real-time sync.
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.
</p>
<div class="rl-cta-row">
<a href="https://demo.rspace.online/rchoices" class="rl-cta-primary" id="ml-primary">Create a Choice Room</a>
<a href="https://demo.rspace.online/rchoices" class="rl-cta-primary" id="ml-primary">Start Deciding</a>
<a href="/create-space" class="rl-cta-secondary">Create a Space</a>
</div>
</div>
<!-- Three tools -->
<!-- Features -->
<section class="rl-section">
<div class="rl-container">
<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>
<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>
</div>
<!-- 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 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>
</div>
<!-- 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 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>
</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</h3>
<p>Name your choice room. It comes pre-loaded with vote, rank, and spider tools.</p>
<h3>Create a Decision</h3>
<p>Pick a voting method, name it, and add options. The choice shape appears on the canvas.</p>
</div>
<div class="rl-step">
<div class="rl-step__num">2</div>
<h3>Share</h3>
<p>Send the link. Everyone joins the same real-time canvas &mdash; add options, cast votes.</p>
<h3>Add Options &amp; Invite Voters</h3>
<p>Space members interact with the shape to cast votes, rank preferences, or score criteria.</p>
</div>
<div class="rl-step">
<div class="rl-step__num">3</div>
<h3>Decide</h3>
<p>Results aggregate live. The group sees consensus emerge in seconds.</p>
<h3>Results Calculated Fairly in Real Time</h3>
<p>Live tallies update as votes arrive. View charts, rankings, and spider diagrams instantly.</p>
</div>
</div>
</div>
</section>
<!-- Use cases -->
<!-- Voting Methods -->
<section class="rl-section">
<div class="rl-container">
<h2 class="rl-heading" style="text-align:center">Decisions, not debates</h2>
<h2 class="rl-heading" style="text-align:center">Voting Methods</h2>
<p class="rl-subtext" style="text-align:center">
Built for the everyday choices that stall group chats
Three powerful mechanisms, each designed for different decision contexts.
</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 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>
<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 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>
<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 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>
<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>
</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>
</div>
</div>
</section>
<!-- CTA -->
<section class="rl-section rl-section--alt">
<section class="rl-section">
<div class="rl-container" style="text-align:center">
<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>
<h2 class="rl-heading">(You)rChoices, 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/rchoices" class="rl-cta-primary">Create a Choice Room</a>
<a href="https://demo.rspace.online/rchoices" class="rl-cta-primary">Start Deciding</a>
<a href="/create-space" class="rl-cta-secondary">Create a Space</a>
</div>
</div>

View File

@ -1,6 +1,5 @@
/**
* rForum landing page Discourse forum provisioning.
* Ported from /opt/apps/rforum-online/src/app/page.tsx
* Forum module landing page static HTML, no React.
*/
export function renderLanding(): string {
return `
@ -19,41 +18,61 @@ export function renderLanding(): string {
</div>
</div>
<!-- How It Works -->
<!-- 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">
<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 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 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>
<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 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>
<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 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>
</div>
</div>
</section>
<!-- Pricing -->
<section class="rl-section rl-section--alt" id="pricing">
<section class="rl-section" 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">
@ -113,49 +132,31 @@ export function renderLanding(): string {
</section>
<!-- What You Get -->
<section class="rl-section">
<section class="rl-section rl-section--alt">
<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>
@ -164,36 +165,24 @@ export function renderLanding(): string {
</section>
<!-- Built on Open Source -->
<section class="rl-section rl-section--alt">
<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 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>
@ -202,7 +191,7 @@ export function renderLanding(): string {
</section>
<!-- Your Data, Protected -->
<section class="rl-section">
<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 rForum keeps your information safe.</p>
@ -229,12 +218,12 @@ export function renderLanding(): string {
</section>
<!-- CTA -->
<section class="rl-section rl-section--alt">
<section class="rl-section">
<div class="rl-container" style="text-align:center">
<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>
<h2 class="rl-heading">(You)rForum, your community.</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/rforum" class="rl-cta-primary">Launch Your Forum</a>
<a href="https://demo.rspace.online/rforum" class="rl-cta-primary">Get Started</a>
<a href="/create-space" class="rl-cta-secondary">Create a Space</a>
</div>
</div>
@ -242,5 +231,6 @@ export function renderLanding(): string {
<div class="rl-back">
<a href="/">&larr; Back to rSpace</a>
</div>`;
</div>
`;
}

View File

@ -1,6 +1,5 @@
/**
* 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.
*/
@ -9,107 +8,66 @@ export function renderLanding(): string {
<!-- Hero -->
<div class="rl-hero">
<span class="rl-tagline">rFunds</span>
<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.
<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.
</p>
<div class="rl-cta-row">
<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>
<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>
</div>
</div>
<!-- How It Works -->
<!-- Features -->
<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">
<h2 class="rl-heading" style="text-align:center">What rFunds Handles</h2>
<div class="rl-grid-4">
<div class="rl-card rl-card--center">
<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 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>
<div class="rl-card rl-card--center">
<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 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>
<div class="rl-card rl-card--center">
<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 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>
</div>
</div>
</section>
<!-- The Funnel Metaphor -->
<!-- How It Works -->
<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">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>
<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>
</div>
</div>
@ -142,7 +100,7 @@ export function renderLanding(): string {
</section>
<!-- Built on Open Source -->
<section class="rl-section rl-section--alt">
<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 rFunds.</p>
@ -167,7 +125,7 @@ export function renderLanding(): string {
</section>
<!-- Your Data, Protected -->
<section class="rl-section">
<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 rFunds keeps your information safe.</p>
@ -194,13 +152,13 @@ export function renderLanding(): string {
</section>
<!-- CTA -->
<section class="rl-section rl-section--alt">
<section class="rl-section">
<div class="rl-container" style="text-align:center">
<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>
<h2 class="rl-heading">(You)rFunds, 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/rfunds" class="rl-cta-primary">Try the Demo</a>
<a href="/create-space" class="rl-cta-secondary">Create Your Own</a>
<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>
</div>
</div>
</section>

View File

@ -1,188 +1,203 @@
/**
* rInbox (rChats) landing page encrypted community chat.
* Ported from rchats-online Next.js page.tsx (shadcn/ui + Lucide).
* Inbox module landing page static HTML, no React.
*/
export function renderLanding(): string {
return `
return `
<!-- Hero -->
<div class="rl-hero">
<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>
<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>
<p class="rl-subtext">
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.
A shared email client where teams read, discuss, and approve messages
together &mdash; with cryptographic multi-signature workflows before anything gets sent.
</p>
<div class="rl-cta-row">
<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>
<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>
</div>
</div>
<!-- How It Works -->
<section class="rl-section rl-section--alt">
<!-- Features -->
<section class="rl-section">
<div class="rl-container">
<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-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>
<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" 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 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" 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 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>
<!-- Features Row 1 -->
<section class="rl-section">
<!-- How It Works -->
<section class="rl-section rl-section--alt">
<div class="rl-container">
<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>
<div class="rl-grid-4">
<div class="rl-card rl-card--center">
<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>
<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 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>
<div class="rl-card rl-card--center">
<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 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>
<div class="rl-card rl-card--center">
<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">
<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 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>
</div>
</div>
</section>
<!-- Features Row 2 -->
<div class="rl-grid-4" style="margin-top:1rem">
<div class="rl-card rl-card--center">
<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>
<!-- Collaboration Features -->
<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 rl-card--center">
<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 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>
<div class="rl-card rl-card--center">
<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>
<!-- 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">
<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>
<h3>ImapFlow</h3>
<p>High-performance IMAP client for real-time email synchronization.</p>
</div>
<div class="rl-card rl-card--center">
<h3>Mailparser</h3>
<p>Email parsing and MIME handling for reliable message processing.</p>
</div>
<div class="rl-card rl-card--center">
<h3>Gnosis Safe</h3>
<p>Multisig approval protocol adapted for email signing workflows.</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>
</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">
<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">
<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>
<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>
</div>
</div>
</section>
<div class="rl-back">
<a href="/">&larr; Back to rSpace</a>
</div>`;
</div>
`;
}

View File

@ -1,90 +1,109 @@
/**
* 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">Community Pocket Press</span>
<h1 class="rl-heading">Write it. Press it.<br>Share it.</h1>
<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>
<p class="rl-subtext">
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.
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.
</p>
<div class="rl-cta-row">
<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="https://demo.rspace.online/rpubs" class="rl-cta-primary" id="ml-primary">Try the Press</a>
<a href="/create-space" class="rl-cta-secondary">Create a Space</a>
</div>
</div>
<!-- How it works -->
<section class="rl-section rl-section--alt">
<!-- Features -->
<section class="rl-section">
<div class="rl-container">
<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">
<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>
<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-step">
<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 &mdash; from A7 pocket to digest &mdash; and generate a typeset PDF in seconds.</p>
<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-step">
<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>Find a community print shop nearby, or download an imposition PDF and bind it at home.</p>
<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>
<!-- Four pocket formats -->
<!-- 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>Write / paste</h3>
<p>Drop in markdown or rich text. Headings, images, footnotes &mdash; it all just works.</p>
</div>
<div class="rl-step">
<span class="rl-step__num">2</span>
<h3>Press it</h3>
<p>Pick a pocket format. rPubs typesets your document with Typst and generates a print-ready PDF.</p>
</div>
<div class="rl-step">
<span class="rl-step__num">3</span>
<h3>Print locally</h3>
<p>Print at home, at a local shop, or list it on rCart for cosmolocal fulfillment.</p>
</div>
</div>
</div>
</section>
<!-- 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 tiny zines that fit in your back pocket to digest-sized readers for longer works.
</p>
<p class="rl-subtext" style="text-align:center">From palm-sized zines to digest readers. All print-ready at 300 dpi with bleeds.</p>
<div class="rl-grid-4" style="margin-top:2rem">
<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 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>
<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 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>
<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 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>
<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 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>
</div>
</div>
@ -93,253 +112,117 @@ 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">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 -->
<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>
<div class="rl-grid-3" style="margin-top:2rem">
<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 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>
<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 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>
<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 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>
</div>
</div>
</section>
<!-- 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>
<!-- 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>
</div>
</div>
</div>
</section>
<!-- Cross-title batching -->
<section class="rl-section">
<section class="rl-section rl-section--alt">
<div class="rl-container">
<h2 class="rl-heading" style="text-align:center">Bundle across titles, not just within them</h2>
<h2 class="rl-heading" style="text-align:center">Cross-title batching</h2>
<p class="rl-subtext" style="text-align:center">
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.
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.
</p>
<!-- 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 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>
</div>
<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 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>
<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 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>
</div>
<div class="rl-divider"><span>at the same local printer</span></div>
<div class="rl-divider"><span>combined</span></div>
<div style="text-align:center">
<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>
<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>
</div>
</div>
</div>
</section>
<!-- rCart integration -->
<section class="rl-section rl-section--alt">
<section class="rl-section">
<div class="rl-container">
<div class="rl-grid-2">
<div>
<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.
<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.
</p>
<ul class="rl-check-list">
<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>
<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>
</ul>
</div>
<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 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>
<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>
<h3>Shop + Press</h3>
<p>rPubs creates the artifact.<br>rCart sells and fulfills it.</p>
</div>
</div>
</div>
@ -347,38 +230,76 @@ export function renderLanding(): string {
</section>
<!-- Cosmolocal -->
<section class="rl-section">
<section class="rl-section rl-section--alt">
<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">
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.
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.
</p>
<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>
</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>
</div>
</section>
<!-- CTA -->
<section class="rl-section rl-section--alt">
<section class="rl-section">
<div class="rl-container" style="text-align:center">
<h2 class="rl-heading">Write it. Press it. Share it.</h2>
<h2 class="rl-heading">(You)rPubs, your press.</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">Start Writing</a>
<a href="https://demo.rspace.online/rpubs" class="rl-cta-primary">Try the Press</a>
<a href="/create-space" class="rl-cta-secondary">Create a Space</a>
</div>
</div>

View File

@ -1,177 +1,79 @@
/**
* 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" 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>
<h1 class="rl-heading">(You)rTrips, your horizon.</h1>
<p class="rl-subtitle">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">Start Planning</a>
<a href="https://demo.rspace.online/rtrips" class="rl-cta-primary" id="ml-primary">Plan a Trip</a>
<a href="/create-space" class="rl-cta-secondary">Create a Space</a>
</div>
</div>
<!-- How It Works -->
<!-- Features -->
<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">
<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>
<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>
<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>
</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-card rl-card--center">
<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 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>
</div>
<div class="rl-card rl-card--center">
<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 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>
</div>
<div class="rl-card rl-card--center">
<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>
<!-- Features -->
<section class="rl-section rl-section--alt">
<div class="rl-container">
<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>
<!-- 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>
<!-- 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 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>
</div>
</div>
</div>
</section>
<!-- Built on Open Source -->
<section class="rl-section rl-section--alt">
<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 rTrips.</p>
@ -196,7 +98,7 @@ export function renderLanding(): string {
</section>
<!-- Your Data, Protected -->
<section class="rl-section">
<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 rTrips keeps your information safe.</p>
@ -223,10 +125,10 @@ export function renderLanding(): string {
</section>
<!-- CTA -->
<section class="rl-section rl-section--alt">
<section class="rl-section">
<div class="rl-container" style="text-align:center">
<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>
<h2 class="rl-heading">(You)rTrips, your horizon.</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/rtrips" class="rl-cta-primary">Plan a Trip</a>
<a href="/create-space" class="rl-cta-secondary">Create a Space</a>

View File

@ -1,195 +1,163 @@
/**
* 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.
* Tube module landing page rich content for rspace.online/rtube
*/
export function renderLanding(): string {
return `
<!-- 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>
<!-- 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 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 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 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>
</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 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>
</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 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">
<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>
<!-- 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" style="background:#dc2626">Start Streaming</a>
<a href="https://demo.rspace.online/rtube" class="rl-cta-secondary">Browse Videos</a>
<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>
</div>
</div>
</section>
<div class="rl-back">
<a href="/">&larr; Back to rSpace</a>
</div>`;
<!-- 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>
</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>
<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>
<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>
</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">
<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>
</div>
</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>
</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 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>
</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>`;
}

View File

@ -1,353 +1,216 @@
/**
* 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" 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.
<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.
</p>
<div class="rl-cta-row">
<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="https://demo.rspace.online/rvote" class="rl-cta-primary" id="ml-primary">Start Voting</a>
<a href="/create-space" class="rl-cta-secondary">Create a Space</a>
</div>
</div>
<!-- ELI5 Section: rVote in 30 Seconds -->
<section class="rl-section" style="border-top:none">
<div class="rl-container">
<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 class="rl-grid-3">
<!-- 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>
<!-- 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>
<!-- 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>
<!-- 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 -->
<!-- Features -->
<section class="rl-section">
<div class="rl-container">
<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>
<!-- 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>
<!-- From Chaos to Consensus (How It Works) -->
<section class="rl-section rl-section--alt">
<div class="rl-container">
<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>
<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>
<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>
<!-- Features: Built for Fair Prioritization -->
<section class="rl-section">
<div class="rl-container">
<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>
<h2 class="rl-heading" style="text-align:center">What rVote Handles</h2>
<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 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>
</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>
</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>
</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>
</div>
</div>
</div>
</section>
<!-- What is QPR -->
<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>
<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>
</div>
</div>
</div>
</section>
<!-- Vote Cost Calculator -->
<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>
<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>
</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>
</div>
</div>
</div>
</div>
</section>
<!-- Built for real governance -->
<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>
<h3>Earn Credits Daily</h3>
<p>Get 10 credits every day. Start with 50. Max 500.</p>
<p>Every verified member receives a daily credit allowance. No pay-to-play.</p>
</div>
<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 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>
<h3>Vote Decay</h3>
<p>Old votes fade away, keeping rankings fresh and dynamic.</p>
<p>Votes decay linearly from day 30 to day 60. Stale support fades, keeping rankings fresh.</p>
</div>
<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 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>
<h3>Sybil Resistant</h3>
<p>Quadratic costs make fake account attacks expensive.</p>
<p>Passkey authentication via EncryptID. One person, one identity, one credit stream.</p>
</div>
<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 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>
<h3>Auto Promotion</h3>
<p>Top proposals automatically advance to voting.</p>
<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>
</div>
</div>
</div>
@ -355,33 +218,12 @@ export function renderLanding(): string {
<!-- CTA -->
<section class="rl-section rl-section--alt">
<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 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>
</div>
</section>

View File

@ -1,183 +1,136 @@
/**
* 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">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>
<span class="rl-tagline">rWork</span>
<h1 class="rl-heading">(You)rWork, your flow.</h1>
<p class="rl-subtitle">Get things done, together</p>
<p class="rl-subtext">
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.
Kanban boards, team spaces, and real-time collaboration &mdash; built for groups
that share work, not just assign it.
</p>
<div class="rl-cta-row">
<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>
<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>
</div>
</div>
<!-- How It Works -->
<section class="rl-section rl-section--alt">
<!-- Features -->
<section class="rl-section">
<div class="rl-container">
<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-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>
<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" 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 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" 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 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>
<!-- Features Row 1 -->
<section class="rl-section">
<!-- How It Works -->
<section class="rl-section rl-section--alt">
<div class="rl-container">
<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" 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>
<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 workspace</h3>
<p>Every workspace lives inside an rSpace &mdash; shared by default with your team.</p>
</div>
<div class="rl-card rl-card--center">
<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 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>
<div class="rl-card rl-card--center">
<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 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>
</div>
</div>
</section>
<!-- Features Row 2 -->
<div class="rl-grid-4" style="margin-top:1rem">
<!-- 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 rWork.</p>
<div class="rl-grid-3">
<div class="rl-card rl-card--center">
<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 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" 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 class="rl-icon-box">&#128451;</div>
<h3>PostgreSQL</h3>
<p>Rock-solid relational database for task storage, workspaces, boards, and activity logs.</p>
</div>
<div class="rl-card rl-card--center">
<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 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>
</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">
<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 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">
<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>
<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>
</div>
</div>
</section>