Blame · Line-by-line history
landing-v2.tsx
Each line is annotated with the commit that last touched it. Click any SHA to jump to that commit and see the surrounding change.
| 11c3ab6 | 1 | import type { FC } from "hono/jsx"; |
| 2 | ||
| 3 | export interface LandingPageProps { | |
| 4 | stats?: { | |
| 5 | publicRepos?: number; | |
| 6 | users?: number; | |
| 7 | }; | |
| 8 | } | |
| 9 | ||
| 10 | const demoAllEvents = [ | |
| 11 | { title: "Push received", time: "now", dot: "#16181d", body: "feat/repair-sandbox-loop — gates fire at the wire, not in a queue." }, | |
| 12 | { title: "Sonnet 5 review posted", time: "now", dot: "#4353c9", body: "Line-level comments, one risk flag, verdict: approve pending gates." }, | |
| 13 | { title: "Gate failed — repair engaged", time: "now", dot: "#b45309", body: "2 tests red. The agent attached to the PR sandbox and reproduced both in isolation." }, | |
| 14 | { title: "Patch drafted, gates re-run", time: "now", dot: "#b45309", body: "Bounded the repair loop, threaded the sandbox session. All 412 tests green." }, | |
| 15 | { title: "Merged & deployed", time: "now", dot: "#1e7f5c", body: "One human approval, then auto-merge and deploy. Fully reversible in one click." }, | |
| 16 | ]; | |
| 17 | ||
| 18 | const tickerItems = [ | |
| 19 | { dot: "#1e7f5c", text: "auto-merge · northwind-labs/api №341 — gates green" }, | |
| 20 | { dot: "#b45309", text: "repair · acme-tools/web №88 — attempt 2 of 5" }, | |
| 21 | { dot: "#4353c9", text: "review · Sonnet 5 posted 6 comments on helvetia/core №129" }, | |
| 22 | { dot: "#1e7f5c", text: "deploy · gluecron 82321e8 → production, 41s" }, | |
| 23 | { dot: "#1e7f5c", text: "fleet · auth-header rename merged atomically across 4 repos" }, | |
| 24 | { dot: "#4353c9", text: "sandbox · pr-220.preview booted" }, | |
| 25 | { dot: "#1e7f5c", text: "flaky test assassinated · sandbox-boot.test.ts fixed after bisect" }, | |
| 26 | { dot: "#b45309", text: "advisory · transitive CVE patched, exposure 19 min" }, | |
| 27 | { dot: "#1e7f5c", text: "auto-merge · northwind-labs/api №341 — gates green" }, | |
| 28 | { dot: "#b45309", text: "repair · acme-tools/web №88 — attempt 2 of 5" }, | |
| 29 | { dot: "#4353c9", text: "review · Sonnet 5 posted 6 comments on helvetia/core №129" }, | |
| 30 | { dot: "#1e7f5c", text: "deploy · gluecron 82321e8 → production, 41s" }, | |
| 31 | { dot: "#1e7f5c", text: "fleet · auth-header rename merged atomically across 4 repos" }, | |
| 32 | { dot: "#4353c9", text: "sandbox · pr-220.preview booted" }, | |
| 33 | { dot: "#1e7f5c", text: "flaky test assassinated · sandbox-boot.test.ts fixed after bisect" }, | |
| 34 | { dot: "#b45309", text: "advisory · transitive CVE patched, exposure 19 min" }, | |
| 35 | ]; | |
| 36 | ||
| 37 | const stageData = [ | |
| 38 | { name: "Push", desc: "Git-native Smart HTTP. Your existing workflow, unchanged.", meta: "no queue, ever" }, | |
| 39 | { name: "Gate", desc: "Security, tests, types — enforced at the moment of push.", meta: "before the branch moves" }, | |
| 40 | { name: "Review", desc: "Sonnet 5 reviews the instant the PR opens. Line-level, auditable.", meta: "the model devs trust" }, | |
| 41 | { name: "Repair", desc: "Red gate? The agent fixes it inside an isolated sandbox.", meta: "93.5% self-heal" }, | |
| 42 | { name: "Merge", desc: "Green across the board merges immediately — with your approval policy.", meta: "you set the policy" }, | |
| 43 | { name: "Deploy", desc: "Streams live to the dashboard. One-click rollback, always.", meta: "reversible by design" }, | |
| 44 | ]; | |
| 45 | ||
| 46 | const heroFeatures = [ | |
| 47 | { | |
| 48 | href: "/", | |
| 49 | eyebrow: "01 · The autonomous repair loop", | |
| 50 | title: "Failures fix themselves — and show their work.", | |
| 51 | body: "When a gate goes red, the repair engine attaches to the PR's own sandbox, reproduces the failure, drafts a bounded patch, and re-runs the gates. Every attempt is recorded to the flywheel with the failing gate, the diff, and the outcome. You watch it happen live, interrupt any time, or take the keyboard yourself.", | |
| 52 | cta: "Watch a live repair session", | |
| 53 | mock: [ | |
| 54 | { dot: "#b42318", color: "#b42318", text: "✗ gate: tests — 2 failing" }, | |
| 55 | { dot: "#b45309", color: "#b45309", text: "agent attached · sandbox pr-218" }, | |
| 56 | { dot: "#b45309", color: "#b45309", text: "patch drafted · +9 −3 · bounded loop" }, | |
| 57 | { dot: "#1e7f5c", color: "#1e7f5c", text: "✓ gates re-run — 412 passing" }, | |
| 58 | { dot: "#1e7f5c", color: "#8a8d99", text: "waiting on your approval" }, | |
| 59 | ], | |
| 60 | }, | |
| 61 | { | |
| 62 | href: "/", | |
| 63 | eyebrow: "02 · Live sandbox isolation", | |
| 64 | title: "Every PR gets its own instant, disposable environment.", | |
| 65 | body: "The moment a PR opens, an isolated environment boots on your hardware: preview URL, shared terminal, real data shape. Reviewers click a link instead of pulling a branch. Agents repair inside the same box they broke nothing in. It expires on merge and leaves an audit trail behind.", | |
| 66 | cta: "See a PR with its sandbox", | |
| 67 | mock: [ | |
| 68 | { dot: "#1e7f5c", color: "#1e7f5c", text: "pr-218.preview.gluecron.com · live" }, | |
| 69 | { dot: "#c4c6cf", color: "#8a8d99", text: "isolated · branch-scoped · your metal" }, | |
| 70 | { dot: "#4353c9", color: "#4353c9", text: "reviewer joined the shared terminal" }, | |
| 71 | { dot: "#c4c6cf", color: "#8a8d99", text: "expires on merge · audit retained" }, | |
| 72 | ], | |
| 73 | }, | |
| 74 | { | |
| 75 | href: "/", | |
| 76 | eyebrow: "03 · Multiplayer IDE workspaces", | |
| 77 | title: "You and the agent, side by side, in your editor.", | |
| 78 | body: "The VS Code and JetBrains extensions join the same live session: you see the agent's cursor, it sees your edits, and either of you can take over. Prefer to fly solo? Observe-only mode turns the agent into a silent reviewer in your gutter. The browser becomes optional.", | |
| 79 | cta: "See the editor session", | |
| 80 | mock: [ | |
| 81 | { dot: "#4353c9", color: "#4353c9", text: "you: the loop needs an upper bound" }, | |
| 82 | { dot: "#1e7f5c", color: "#1e7f5c", text: "claude: agreed — typing lines 151–154" }, | |
| 83 | { dot: "#1e7f5c", color: "#d6d8e0", text: "+ for (let i = 0; i < MAX_ATTEMPTS; i++)" }, | |
| 84 | { dot: "#c4c6cf", color: "#8a8d99", text: "mode: suggest → you accept · or observe-only" }, | |
| 85 | ], | |
| 86 | }, | |
| 87 | ]; | |
| 88 | ||
| 89 | const capabilities = [ | |
| 90 | { group: "Code hosting", items: ["Git Smart HTTP", "SSH, PATs, OAuth2 provider", "Forks, stars, templates, mirrors", "Releases & protected tags", "Push policy rulesets"] }, | |
| 91 | { group: "Collaboration", items: ["Issues, labels, milestones", "Inline review & draft PRs", "Merge queues", "Discussions, wikis, projects", "Gists & reactions"] }, | |
| 92 | { group: "AI-native", items: ["Sonnet 5 code review", "Security review + secret scanner", "Auto-repair engine", "Spec-to-PR with plan approval", "Merge-conflict resolver", "Org memory & archaeology"] }, | |
| 93 | { group: "Automation", items: ["Push-time gates", "Workflow runner, zero YAML", "HMAC webhooks", "Dependency updater", "CODEOWNERS auto-sync"] }, | |
| 94 | { group: "Platform", items: ["Orgs, teams, roles", "2FA, passkeys, OIDC SSO", "npm package registry", "Static pages hosting", "REST + GraphQL + MCP"] }, | |
| 95 | { group: "Sovereignty", items: ["Self-host anywhere Bun runs", "Local LLM routing", "Air-gapped region sync", "Own-edge Caddy ingress", "Data-region residency"] }, | |
| 96 | { group: "Observability", items: ["Request-ID tracing", "Audit log, 100% coverage", "Traffic analytics", "Org insights & green rate", "Health scores"] }, | |
| 97 | { group: "Trust", items: ["Live public quality metrics", "Blast radius before approval", "One-click reversal", "Zero irreversible auto-actions", "Manual twin for every surface"] }, | |
| 98 | ]; | |
| 99 | ||
| 100 | const sovereignLayerNames = [ | |
| 101 | "Frontend foundation", "APIs & backend logic", "Database & storage", "Auth & permissions", | |
| 102 | "Hosting & deployment", "Cloud & compute", "CI/CD & version control", "Security & RLS", | |
| 103 | "Rate limiting", "Caching & CDN", "Load balancing & scaling", "Error tracking & logs", | |
| 104 | "Availability & recovery", | |
| 105 | ]; | |
| 106 | ||
| 107 | export const LandingPageV2: FC<LandingPageProps> = (_props) => { | |
| 108 | return ( | |
| 109 | <> | |
| 110 | <style dangerouslySetInnerHTML={{ __html: css }} /> | |
| 111 | ||
| 112 | {/* Nav */} | |
| 113 | <header class="lv-nav"> | |
| 114 | <div class="lv-nav-inner"> | |
| 115 | <a href="/" class="lv-logo"> | |
| 116 | <span class="lv-logo-mark"></span>gluecron | |
| 117 | </a> | |
| 118 | <nav class="lv-nav-links"> | |
| 119 | <a href="#loop" class="lv-nav-link">The loop</a> | |
| 120 | <a href="#platform" class="lv-nav-link">Platform</a> | |
| 121 | <a href="#sovereign" class="lv-nav-link">Sovereignty</a> | |
| 122 | <a href="/trust" class="lv-nav-link">Trust</a> | |
| 123 | </nav> | |
| 124 | <div class="lv-nav-ctas"> | |
| 125 | <a href="/login" class="lv-btn-secondary">Sign in</a> | |
| 126 | <a href="/register" class="lv-btn-primary">Start building</a> | |
| 127 | </div> | |
| 128 | </div> | |
| 129 | </header> | |
| 130 | ||
| 131 | {/* Hero */} | |
| 132 | <section class="lv-hero"> | |
| 133 | <div class="lv-hero-glow"></div> | |
| 134 | <div class="lv-hero-inner"> | |
| 135 | <div class="lv-hero-badge"> | |
| 136 | <span class="lv-dot lv-dot-green lv-pulse"></span> | |
| 137 | Live: a repair loop converged on pr-218 while you read this | |
| 138 | </div> | |
| 139 | <h1 class="lv-h1">Your PR is done before the dinosaurs finish booting.</h1> | |
| 140 | <p class="lv-hero-sub"> | |
| 141 | No CI queue. No pipeline warm-up. Gates fire <strong class="lv-strong">at the moment of push</strong>, <strong class="lv-strong">Claude Sonnet 5</strong> reviews the instant your PR opens, failures repair themselves in isolated sandboxes, and clean work merges immediately. You stay in flow — and the manual path is always one click away. | |
| 142 | </p> | |
| 143 | <div class="lv-hero-actions"> | |
| 144 | <a href="/register" class="lv-cta-primary">Start building — free →</a> | |
| 145 | <a href="/" class="lv-cta-secondary">Watch a live repair</a> | |
| 146 | </div> | |
| 147 | <div class="lv-hero-tag">Self-hosted · Git-native · Sonnet 5 reviews · Manual-always-possible</div> | |
| 148 | ||
| 149 | {/* Live product window */} | |
| 150 | <div class="lv-demo-window"> | |
| 151 | <div class="lv-demo-bar"> | |
| 152 | <span class="lv-demo-dot"></span> | |
| 153 | <span class="lv-demo-dot"></span> | |
| 154 | <span class="lv-demo-dot"></span> | |
| 155 | <span class="lv-demo-url">gluecron.com / ccantynz-alt / gluecron · PR №218 · live</span> | |
| 156 | <span class="lv-demo-live"> | |
| 157 | <span class="lv-dot lv-dot-green lv-pulse" style="width:6px;height:6px"></span> | |
| 158 | LIVE | |
| 159 | </span> | |
| 160 | </div> | |
| 161 | <div class="lv-demo-body" id="lv-demo-body"> | |
| 162 | {/* Events rendered by JS */} | |
| 163 | {demoAllEvents.slice(0, 1).map((e, i) => ( | |
| 164 | <div class="lv-demo-event" key={i}> | |
| 165 | <div class="lv-demo-event-track"> | |
| 166 | <span class="lv-dot lv-pulse" style={`width:8px;height:8px;background:${e.dot}`}></span> | |
| 167 | <span class="lv-demo-line" style="display:none"></span> | |
| 168 | </div> | |
| 169 | <div class="lv-demo-event-content"> | |
| 170 | <div class="lv-demo-event-header"> | |
| 171 | <span class="lv-demo-event-title">{e.title}</span> | |
| 172 | <span class="lv-demo-event-time">{e.time}</span> | |
| 173 | </div> | |
| 174 | <div class="lv-demo-event-body">{e.body}</div> | |
| 175 | </div> | |
| 176 | </div> | |
| 177 | ))} | |
| 178 | </div> | |
| 179 | </div> | |
| 180 | </div> | |
| 181 | ||
| 182 | {/* Activity ticker */} | |
| 183 | <div class="lv-ticker-wrap"> | |
| 184 | <div class="lv-ticker-track"> | |
| 185 | {tickerItems.map((t, i) => ( | |
| 186 | <span class="lv-ticker-item" key={i}> | |
| 187 | <span class="lv-dot" style={`width:6px;height:6px;background:${t.dot}`}></span> | |
| 188 | {t.text} | |
| 189 | </span> | |
| 190 | ))} | |
| 191 | </div> | |
| 192 | </div> | |
| 193 | </section> | |
| 194 | ||
| 195 | {/* Stat band */} | |
| 196 | <section class="lv-stats"> | |
| 197 | <div class="lv-stats-inner"> | |
| 198 | <div class="lv-stat"> | |
| 199 | <div class="lv-stat-num">Sonnet 5</div> | |
| 200 | <div class="lv-stat-label">reviews every pull request — the model developers trust</div> | |
| 201 | </div> | |
| 202 | <div class="lv-stat"> | |
| 203 | <div class="lv-stat-num">93.5%</div> | |
| 204 | <div class="lv-stat-label">of failures self-repair without a human</div> | |
| 205 | </div> | |
| 206 | <div class="lv-stat"> | |
| 207 | <div class="lv-stat-num">1.9%</div> | |
| 208 | <div class="lv-stat-label">AI merges reverted — published live</div> | |
| 209 | </div> | |
| 210 | <div class="lv-stat"> | |
| 211 | <div class="lv-stat-num">0</div> | |
| 212 | <div class="lv-stat-label">irreversible actions taken autonomously</div> | |
| 213 | </div> | |
| 214 | </div> | |
| 215 | </section> | |
| 216 | ||
| 217 | {/* The loop */} | |
| 218 | <section id="loop" class="lv-loop"> | |
| 219 | <div class="lv-loop-inner"> | |
| 220 | <div class="lv-section-header"> | |
| 221 | <div class="lv-eyebrow lv-eyebrow-indigo">The closed loop — running now</div> | |
| 222 | <h2 class="lv-h2">Push. Gate. Review. Repair. Merge. Deploy.</h2> | |
| 223 | <p class="lv-section-sub">Six stages, zero YAML, full audit trail. The highlighted stage is cycling live — this is the pipeline, not a diagram of one.</p> | |
| 224 | </div> | |
| 225 | <div class="lv-stages" id="lv-stages"> | |
| 226 | {stageData.map((s, i) => ( | |
| 227 | <div class={`lv-stage-card${i === 0 ? " lv-stage-active" : ""}`} key={i} data-stage={i}> | |
| 228 | <div class="lv-stage-header"> | |
| 229 | <span class={`lv-dot${i === 0 ? " lv-dot-indigo lv-pulse" : " lv-dot-idle"}`} style="width:7px;height:7px"></span> | |
| 230 | <span class="lv-stage-n">0{i + 1}</span> | |
| 231 | </div> | |
| 232 | <div class="lv-stage-name">{s.name}</div> | |
| 233 | <div class="lv-stage-desc">{s.desc}</div> | |
| 234 | <div class={`lv-stage-meta${i === 0 ? " lv-stage-meta-active" : ""}`}>{s.meta}</div> | |
| 235 | </div> | |
| 236 | ))} | |
| 237 | </div> | |
| 238 | </div> | |
| 239 | </section> | |
| 240 | ||
| 241 | {/* Three heroes */} | |
| 242 | <section class="lv-heroes"> | |
| 243 | <div class="lv-heroes-inner"> | |
| 244 | <div class="lv-heroes-header"> | |
| 245 | <div class="lv-eyebrow lv-eyebrow-indigo">Three things nobody else has</div> | |
| 246 | <h2 class="lv-h2">Legacy hosts store code.<br />Gluecron finishes it.</h2> | |
| 247 | </div> | |
| 248 | <div class="lv-heroes-list"> | |
| 249 | {heroFeatures.map((h, i) => ( | |
| 250 | <a href={h.href} class="lv-hero-card" key={i}> | |
| 251 | <div class="lv-hero-card-left"> | |
| 252 | <div class="lv-eyebrow">{h.eyebrow}</div> | |
| 253 | <h3 class="lv-hero-card-title">{h.title}</h3> | |
| 254 | <p class="lv-hero-card-body">{h.body}</p> | |
| 255 | <span class="lv-hero-card-cta">{h.cta} →</span> | |
| 256 | </div> | |
| 257 | <div class="lv-terminal"> | |
| 258 | {h.mock.map((m, j) => ( | |
| 259 | <div class="lv-terminal-line" key={j}> | |
| 260 | <span class="lv-dot" style={`width:6px;height:6px;background:${m.dot};flex-shrink:0`}></span> | |
| 261 | <span style={`color:${m.color};overflow:hidden;text-overflow:ellipsis`}>{m.text}</span> | |
| 262 | </div> | |
| 263 | ))} | |
| 264 | </div> | |
| 265 | </a> | |
| 266 | ))} | |
| 267 | </div> | |
| 268 | </div> | |
| 269 | </section> | |
| 270 | ||
| 271 | {/* Everything grid */} | |
| 272 | <section id="platform" class="lv-platform"> | |
| 273 | <div class="lv-platform-inner"> | |
| 274 | <div class="lv-section-header lv-section-header-center"> | |
| 275 | <div class="lv-eyebrow lv-eyebrow-indigo">The whole platform, day one</div> | |
| 276 | <h2 class="lv-h2">Everything you'd assemble from five vendors. Built in.</h2> | |
| 277 | <p class="lv-section-sub">No marketplace scavenger hunt. Every capability below ships with your first push — on by default, opt out per feature.</p> | |
| 278 | </div> | |
| 279 | <div class="lv-cap-grid"> | |
| 280 | {capabilities.map((c, i) => ( | |
| 281 | <div class="lv-cap-col" key={i}> | |
| 282 | <div class="lv-cap-group">{c.group}</div> | |
| 283 | <div class="lv-cap-items"> | |
| 284 | {c.items.map((item, j) => ( | |
| 285 | <div class="lv-cap-item" key={j}>{item}</div> | |
| 286 | ))} | |
| 287 | </div> | |
| 288 | </div> | |
| 289 | ))} | |
| 290 | </div> | |
| 291 | </div> | |
| 292 | </section> | |
| 293 | ||
| 294 | {/* Sovereignty band */} | |
| 295 | <section id="sovereign" class="lv-sovereign"> | |
| 296 | <div class="lv-sovereign-grid-bg"></div> | |
| 297 | <div class="lv-sovereign-inner"> | |
| 298 | <div class="lv-section-header lv-section-header-center lv-section-header-dark"> | |
| 299 | <div class="lv-eyebrow lv-eyebrow-light">Infrastructure sovereignty</div> | |
| 300 | <h2 class="lv-h2-dark">Your code. Your servers. Your models. Your keys.</h2> | |
| 301 | <p class="lv-section-sub-dark">Thirteen production layers with zero external runtime dependencies — no magic edge proxies, no third-party CDN in the serving path. Route AI to local models, burst to private cloud, or run fully air-gapped on bare metal.</p> | |
| 302 | </div> | |
| 303 | <div class="lv-layers-grid"> | |
| 304 | {sovereignLayerNames.map((name, i) => ( | |
| 305 | <div class="lv-layer-chip" key={i}> | |
| 306 | <div class="lv-layer-n">{String(i + 1).padStart(2, "0")}</div> | |
| 307 | <div class="lv-layer-name">{name}</div> | |
| 308 | </div> | |
| 309 | ))} | |
| 310 | <a href="/" class="lv-layer-chip lv-layer-cta"> | |
| 311 | <div class="lv-layer-cta-text">All self-owned →</div> | |
| 312 | </a> | |
| 313 | </div> | |
| 314 | <div class="lv-sovereign-feats"> | |
| 315 | <div class="lv-sovereign-feat"> | |
| 316 | <div class="lv-sovereign-feat-title">Local inference first</div> | |
| 317 | <div class="lv-sovereign-feat-sub">your hardware, private cloud only on burst</div> | |
| 318 | </div> | |
| 319 | <div class="lv-sovereign-feat"> | |
| 320 | <div class="lv-sovereign-feat-title">Air-gapped sync</div> | |
| 321 | <div class="lv-sovereign-feat-sub">repos, indices, and registries to bare metal</div> | |
| 322 | </div> | |
| 323 | <div class="lv-sovereign-feat"> | |
| 324 | <div class="lv-sovereign-feat-title">Self-healing infra</div> | |
| 325 | <div class="lv-sovereign-feat-sub">the platform repairs itself with the same engine</div> | |
| 326 | </div> | |
| 327 | </div> | |
| 328 | </div> | |
| 329 | </section> | |
| 330 | ||
| 331 | {/* Manual-first + reversibility */} | |
| 332 | <section class="lv-twin"> | |
| 333 | <div class="lv-twin-inner"> | |
| 334 | <div class="lv-twin-card"> | |
| 335 | <div class="lv-eyebrow">Manual-first, always</div> | |
| 336 | <h3 class="lv-twin-title">Every AI surface has a manual twin.</h3> | |
| 337 | <p class="lv-twin-body">Pull up the raw diff. Work the merge by hand. Set agents to observe-only, per repo or per developer. The manual path is the same first-class UI — never a degraded fallback. Developers who never touch AI get the best git host they've ever used.</p> | |
| 338 | </div> | |
| 339 | <div class="lv-twin-card"> | |
| 340 | <div class="lv-eyebrow">The reversibility guarantee</div> | |
| 341 | <h3 class="lv-twin-title">One click undoes anything the AI did.</h3> | |
| 342 | <p class="lv-twin-body">Every autonomous merge, repair, and deploy shows its blast radius before you approve and reverses in one click after. If it can't be reversed, it isn't done autonomously — policy, not promise. Our quality numbers are published live, unedited.</p> | |
| 343 | <a href="/trust" class="lv-twin-link">See the live trust report →</a> | |
| 344 | </div> | |
| 345 | </div> | |
| 346 | </section> | |
| 347 | ||
| 348 | {/* Quote */} | |
| 349 | <section class="lv-quote"> | |
| 350 | <div class="lv-quote-inner"> | |
| 351 | <p class="lv-quote-text"> | |
| 352 | "GitHub gives you a place to <em class="lv-em">store</em> code.<br /> | |
| 353 | Gluecron is where code gets <em class="lv-em">finished</em>." | |
| 354 | </p> | |
| 355 | </div> | |
| 356 | </section> | |
| 357 | ||
| 358 | {/* CTA */} | |
| 359 | <section class="lv-cta-section"> | |
| 360 | <div class="lv-cta-card"> | |
| 361 | <div class="lv-cta-glow"></div> | |
| 362 | <h2 class="lv-cta-h2">The next decade of shipping starts with one push.</h2> | |
| 363 | <p class="lv-cta-sub">Migrate from GitHub in one click — continuous two-way mirror, zero cutover risk, leave whenever you want.</p> | |
| 364 | <div class="lv-cta-actions"> | |
| 365 | <a href="/register" class="lv-cta-primary">Create your account →</a> | |
| 366 | <a href="/" class="lv-cta-secondary">Migrate from GitHub</a> | |
| 367 | </div> | |
| 368 | <div class="lv-cta-fine">free for individuals · internal orgs never billed · try without signing up at /play</div> | |
| 369 | </div> | |
| 370 | </section> | |
| 371 | ||
| 372 | {/* Footer */} | |
| 373 | <footer class="lv-footer"> | |
| 374 | <div class="lv-footer-inner"> | |
| 375 | <div class="lv-footer-brand"> | |
| 376 | <a href="/" class="lv-logo"> | |
| 377 | <span class="lv-logo-mark"></span>gluecron | |
| 378 | </a> | |
| 379 | <p class="lv-footer-tagline">The AI-native git host. Self-hosted, auditable, reversible — and fully manual whenever you want it.</p> | |
| 380 | </div> | |
| 381 | <div class="lv-footer-cols"> | |
| 382 | <div class="lv-footer-col"> | |
| 383 | <h4 class="lv-footer-col-head">Product</h4> | |
| 384 | <a href="/" class="lv-footer-link">Agent workspace</a> | |
| 385 | <a href="/" class="lv-footer-link">Fleet refactors</a> | |
| 386 | <a href="/" class="lv-footer-link">Org memory</a> | |
| 387 | <a href="/" class="lv-footer-link">IDE extensions</a> | |
| 388 | </div> | |
| 389 | <div class="lv-footer-col"> | |
| 390 | <h4 class="lv-footer-col-head">Platform</h4> | |
| 391 | <a href="/" class="lv-footer-link">Production layers</a> | |
| 392 | <a href="/trust" class="lv-footer-link">Trust report</a> | |
| 393 | <a href="/" class="lv-footer-link">Docs</a> | |
| 394 | <a href="/" class="lv-footer-link">Status</a> | |
| 395 | </div> | |
| 396 | <div class="lv-footer-col"> | |
| 397 | <h4 class="lv-footer-col-head">Company</h4> | |
| 398 | <a href="/" class="lv-footer-link">About</a> | |
| 399 | <a href="/" class="lv-footer-link">Pricing</a> | |
| 400 | <a href="/" class="lv-footer-link">Enterprise</a> | |
| 401 | </div> | |
| 402 | </div> | |
| 403 | </div> | |
| 404 | <div class="lv-footer-bar"> | |
| 405 | <span>© 2026 Gluecron</span> | |
| 406 | <span class="lv-footer-stack">Self-hosted · Git-native · Sonnet 5 · Reversible</span> | |
| 407 | </div> | |
| 408 | </footer> | |
| 409 | ||
| 410 | <script dangerouslySetInnerHTML={{ __html: clientScript }} /> | |
| 411 | </> | |
| 412 | ); | |
| 413 | }; | |
| 414 | ||
| 415 | export const LandingPage = LandingPageV2; | |
| 416 | export default LandingPageV2; | |
| 417 | ||
| 418 | const clientScript = ` | |
| 419 | (function() { | |
| 420 | var demoAll = [ | |
| 421 | { title: "Push received", time: "now", dot: "#16181d", body: "feat/repair-sandbox-loop — gates fire at the wire, not in a queue." }, | |
| 422 | { title: "Sonnet 5 review posted", time: "now", dot: "#4353c9", body: "Line-level comments, one risk flag, verdict: approve pending gates." }, | |
| 423 | { title: "Gate failed — repair engaged", time: "now", dot: "#b45309", body: "2 tests red. The agent attached to the PR sandbox and reproduced both in isolation." }, | |
| 424 | { title: "Patch drafted, gates re-run", time: "now", dot: "#b45309", body: "Bounded the repair loop, threaded the sandbox session. All 412 tests green." }, | |
| 425 | { title: "Merged & deployed", time: "now", dot: "#1e7f5c", body: "One human approval, then auto-merge and deploy. Fully reversible in one click." }, | |
| 426 | ]; | |
| 427 | ||
| 428 | var demoStep = 0; | |
| 429 | var stage = 0; | |
| 430 | ||
| 431 | function renderDemo() { | |
| 432 | var container = document.getElementById('lv-demo-body'); | |
| 433 | if (!container) return; | |
| 434 | var visible = demoAll.slice(0, demoStep + 1); | |
| 435 | container.innerHTML = visible.map(function(e, i) { | |
| 436 | var isLast = i === visible.length - 1; | |
| 437 | var pulse = isLast && demoStep < 4 ? 'lv-pulse' : ''; | |
| 438 | return '<div class="lv-demo-event">' + | |
| 439 | '<div class="lv-demo-event-track">' + | |
| 440 | '<span class="lv-dot ' + pulse + '" style="width:8px;height:8px;background:' + e.dot + '"></span>' + | |
| 441 | '<span class="lv-demo-line" style="display:' + (isLast ? 'none' : 'block') + '"></span>' + | |
| 442 | '</div>' + | |
| 443 | '<div class="lv-demo-event-content">' + | |
| 444 | '<div class="lv-demo-event-header">' + | |
| 445 | '<span class="lv-demo-event-title">' + e.title + '</span>' + | |
| 446 | '<span class="lv-demo-event-time">' + e.time + '</span>' + | |
| 447 | '</div>' + | |
| 448 | '<div class="lv-demo-event-body">' + e.body + '</div>' + | |
| 449 | '</div>' + | |
| 450 | '</div>'; | |
| 451 | }).join(''); | |
| 452 | } | |
| 453 | ||
| 454 | function renderStages() { | |
| 455 | var cards = document.querySelectorAll('.lv-stage-card'); | |
| 456 | cards.forEach(function(card, i) { | |
| 457 | var dot = card.querySelector('.lv-dot'); | |
| 458 | var meta = card.querySelector('.lv-stage-meta'); | |
| 459 | if (i === stage) { | |
| 460 | card.classList.add('lv-stage-active'); | |
| 461 | if (dot) { | |
| 462 | dot.classList.remove('lv-dot-idle'); | |
| 463 | dot.classList.add('lv-dot-indigo', 'lv-pulse'); | |
| 464 | } | |
| 465 | if (meta) meta.classList.add('lv-stage-meta-active'); | |
| 466 | } else { | |
| 467 | card.classList.remove('lv-stage-active'); | |
| 468 | if (dot) { | |
| 469 | dot.classList.add('lv-dot-idle'); | |
| 470 | dot.classList.remove('lv-dot-indigo', 'lv-pulse'); | |
| 471 | } | |
| 472 | if (meta) meta.classList.remove('lv-stage-meta-active'); | |
| 473 | } | |
| 474 | }); | |
| 475 | } | |
| 476 | ||
| 477 | renderDemo(); | |
| 478 | ||
| 479 | setInterval(function() { | |
| 480 | demoStep = (demoStep + 1) % 5; | |
| 481 | renderDemo(); | |
| 482 | }, 3600); | |
| 483 | ||
| 484 | setInterval(function() { | |
| 485 | stage = (stage + 1) % 6; | |
| 486 | renderStages(); | |
| 487 | }, 2200); | |
| 488 | })(); | |
| 489 | `; | |
| 490 | ||
| 491 | const css = ` | |
| 492 | @import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;450;500;600;700&family=Inter+Tight:wght@500;600;700;800&family=JetBrains+Mono:wght@400;500&display=swap'); | |
| 493 | ||
| 494 | *, *::before, *::after { box-sizing: border-box; } | |
| 495 | ||
| 496 | body { | |
| 497 | margin: 0; | |
| 498 | background: #fcfcfd; | |
| 499 | -webkit-font-smoothing: antialiased; | |
| 500 | text-rendering: optimizeLegibility; | |
| 501 | font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', system-ui, sans-serif; | |
| 502 | font-size: 15px; | |
| 503 | line-height: 1.6; | |
| 504 | letter-spacing: -0.008em; | |
| 505 | color: #16181d; | |
| 506 | } | |
| 507 | ||
| 508 | @keyframes gcPulse { | |
| 509 | 0%, 100% { opacity: 1; } | |
| 510 | 50% { opacity: 0.35; } | |
| 511 | } | |
| 512 | ||
| 513 | @keyframes gcTicker { | |
| 514 | 0% { transform: translateX(0); } | |
| 515 | 100% { transform: translateX(-50%); } | |
| 516 | } | |
| 517 | ||
| 518 | /* Shared utilities */ | |
| 519 | .lv-dot { | |
| 520 | display: inline-block; | |
| 521 | border-radius: 50%; | |
| 522 | } | |
| 523 | .lv-dot-green { background: #1e7f5c; } | |
| 524 | .lv-dot-indigo { background: #4353c9; } | |
| 525 | .lv-dot-idle { background: #c4c6cf; } | |
| 526 | .lv-pulse { animation: gcPulse 1.4s ease-in-out infinite; } | |
| 527 | ||
| 528 | .lv-strong { color: #16181d; font-weight: 600; } | |
| 529 | ||
| 530 | .lv-eyebrow { | |
| 531 | font-family: 'JetBrains Mono', monospace; | |
| 532 | font-size: 11px; | |
| 533 | letter-spacing: 0.12em; | |
| 534 | text-transform: uppercase; | |
| 535 | color: #8a8d99; | |
| 536 | font-weight: 500; | |
| 537 | margin-bottom: 12px; | |
| 538 | } | |
| 539 | .lv-eyebrow-indigo { color: #4353c9; font-size: 11.5px; margin-bottom: 16px; } | |
| 540 | .lv-eyebrow-light { color: #a9b4ee; font-size: 11.5px; margin-bottom: 16px; } | |
| 541 | ||
| 542 | .lv-h1 { | |
| 543 | font-family: 'Inter Tight', sans-serif; | |
| 544 | font-weight: 700; | |
| 545 | letter-spacing: -0.035em; | |
| 546 | font-size: clamp(44px, 7vw, 84px); | |
| 547 | line-height: 0.98; | |
| 548 | margin: 30px auto 0; | |
| 549 | max-width: 14ch; | |
| 550 | color: #111318; | |
| 551 | } | |
| 552 | ||
| 553 | .lv-h2 { | |
| 554 | font-family: 'Inter Tight', sans-serif; | |
| 555 | font-weight: 700; | |
| 556 | letter-spacing: -0.028em; | |
| 557 | font-size: clamp(30px, 4.4vw, 48px); | |
| 558 | line-height: 1.05; | |
| 559 | margin: 0; | |
| 560 | color: #111318; | |
| 561 | } | |
| 562 | ||
| 563 | .lv-h2-dark { | |
| 564 | font-family: 'Inter Tight', sans-serif; | |
| 565 | font-weight: 700; | |
| 566 | letter-spacing: -0.028em; | |
| 567 | font-size: clamp(30px, 4.6vw, 52px); | |
| 568 | line-height: 1.05; | |
| 569 | margin: 0; | |
| 570 | color: #fff; | |
| 571 | } | |
| 572 | ||
| 573 | .lv-section-header { | |
| 574 | max-width: 640px; | |
| 575 | margin: 0 auto 56px; | |
| 576 | } | |
| 577 | ||
| 578 | .lv-section-header-center { | |
| 579 | text-align: center; | |
| 580 | } | |
| 581 | ||
| 582 | .lv-section-sub { | |
| 583 | color: #6b7080; | |
| 584 | font-size: 17px; | |
| 585 | margin: 18px auto 0; | |
| 586 | max-width: 52ch; | |
| 587 | } | |
| 588 | ||
| 589 | .lv-section-sub-dark { | |
| 590 | color: rgba(255,255,255,0.72); | |
| 591 | font-size: 17px; | |
| 592 | margin: 18px auto 0; | |
| 593 | max-width: 56ch; | |
| 594 | } | |
| 595 | ||
| 596 | /* Nav */ | |
| 597 | .lv-nav { | |
| 598 | position: sticky; | |
| 599 | top: 0; | |
| 600 | z-index: 60; | |
| 601 | backdrop-filter: saturate(180%) blur(14px); | |
| 602 | -webkit-backdrop-filter: saturate(180%) blur(14px); | |
| 603 | background: rgba(252,252,253,0.8); | |
| 604 | border-bottom: 1px solid rgba(22,24,29,0.07); | |
| 605 | } | |
| 606 | ||
| 607 | .lv-nav-inner { | |
| 608 | max-width: 1200px; | |
| 609 | margin: 0 auto; | |
| 610 | padding: 14px 28px; | |
| 611 | display: flex; | |
| 612 | align-items: center; | |
| 613 | gap: 28px; | |
| 614 | } | |
| 615 | ||
| 616 | .lv-logo { | |
| 617 | display: inline-flex; | |
| 618 | align-items: center; | |
| 619 | gap: 9px; | |
| 620 | font-family: 'Inter Tight', sans-serif; | |
| 621 | font-weight: 700; | |
| 622 | font-size: 17px; | |
| 623 | letter-spacing: -0.02em; | |
| 624 | color: #16181d; | |
| 625 | text-decoration: none; | |
| 626 | } | |
| 627 | ||
| 628 | .lv-logo-mark { | |
| 629 | width: 17px; | |
| 630 | height: 17px; | |
| 631 | border-radius: 5px; | |
| 632 | background: #4353c9; | |
| 633 | display: inline-block; | |
| 634 | flex-shrink: 0; | |
| 635 | } | |
| 636 | ||
| 637 | .lv-nav-links { | |
| 638 | display: flex; | |
| 639 | gap: 24px; | |
| 640 | font-size: 13.5px; | |
| 641 | font-weight: 500; | |
| 642 | } | |
| 643 | ||
| 644 | .lv-nav-link { | |
| 645 | color: #6b7080; | |
| 646 | text-decoration: none; | |
| 647 | transition: color 0.15s; | |
| 648 | } | |
| 649 | .lv-nav-link:hover { color: #16181d; } | |
| 650 | ||
| 651 | .lv-nav-ctas { | |
| 652 | margin-left: auto; | |
| 653 | display: flex; | |
| 654 | align-items: center; | |
| 655 | gap: 10px; | |
| 656 | } | |
| 657 | ||
| 658 | .lv-btn-secondary { | |
| 659 | padding: 8px 15px; | |
| 660 | border-radius: 8px; | |
| 661 | font-size: 13.5px; | |
| 662 | font-weight: 500; | |
| 663 | color: #16181d; | |
| 664 | border: 1px solid rgba(22,24,29,0.12); | |
| 665 | background: #ffffff; | |
| 666 | text-decoration: none; | |
| 667 | white-space: nowrap; | |
| 668 | transition: border-color 0.15s; | |
| 669 | } | |
| 670 | .lv-btn-secondary:hover { border-color: rgba(22,24,29,0.28); } | |
| 671 | ||
| 672 | .lv-btn-primary { | |
| 673 | padding: 8px 15px; | |
| 674 | border-radius: 8px; | |
| 675 | font-size: 13.5px; | |
| 676 | font-weight: 600; | |
| 677 | background: #16181d; | |
| 678 | color: #fff; | |
| 679 | text-decoration: none; | |
| 680 | white-space: nowrap; | |
| 681 | transition: box-shadow 0.15s; | |
| 682 | } | |
| 683 | .lv-btn-primary:hover { box-shadow: 0 8px 22px rgba(22,24,29,0.18); } | |
| 684 | ||
| 685 | /* Hero */ | |
| 686 | .lv-hero { | |
| 687 | position: relative; | |
| 688 | overflow: hidden; | |
| 689 | padding: 88px 0 0; | |
| 690 | } | |
| 691 | ||
| 692 | .lv-hero-glow { | |
| 693 | position: absolute; | |
| 694 | inset: -10% 0 auto 0; | |
| 695 | height: 640px; | |
| 696 | pointer-events: none; | |
| 697 | background: radial-gradient(55% 55% at 50% 0%, rgba(67,83,201,0.06), transparent 70%); | |
| 698 | } | |
| 699 | ||
| 700 | .lv-hero-inner { | |
| 701 | position: relative; | |
| 702 | max-width: 1200px; | |
| 703 | margin: 0 auto; | |
| 704 | padding: 0 28px; | |
| 705 | text-align: center; | |
| 706 | } | |
| 707 | ||
| 708 | .lv-hero-badge { | |
| 709 | display: inline-flex; | |
| 710 | align-items: center; | |
| 711 | gap: 9px; | |
| 712 | font-size: 12.5px; | |
| 713 | font-weight: 600; | |
| 714 | color: #3a3d45; | |
| 715 | background: #ffffff; | |
| 716 | border: 1px solid rgba(22,24,29,0.10); | |
| 717 | border-radius: 9999px; | |
| 718 | padding: 7px 16px; | |
| 719 | box-shadow: 0 1px 2px rgba(22,24,29,0.04); | |
| 720 | } | |
| 721 | ||
| 722 | .lv-hero-sub { | |
| 723 | font-size: clamp(16px, 2vw, 19px); | |
| 724 | color: #6b7080; | |
| 725 | max-width: 60ch; | |
| 726 | margin: 24px auto 0; | |
| 727 | font-weight: 450; | |
| 728 | line-height: 1.65; | |
| 729 | } | |
| 730 | ||
| 731 | .lv-hero-actions { | |
| 732 | display: flex; | |
| 733 | gap: 12px; | |
| 734 | justify-content: center; | |
| 735 | flex-wrap: wrap; | |
| 736 | margin-top: 32px; | |
| 737 | } | |
| 738 | ||
| 739 | .lv-cta-primary { | |
| 740 | padding: 13px 24px; | |
| 741 | border-radius: 11px; | |
| 742 | font-size: 15.5px; | |
| 743 | font-weight: 600; | |
| 744 | background: #16181d; | |
| 745 | color: #fff; | |
| 746 | text-decoration: none; | |
| 747 | white-space: nowrap; | |
| 748 | transition: box-shadow 0.15s; | |
| 749 | } | |
| 750 | .lv-cta-primary:hover { box-shadow: 0 10px 26px rgba(22,24,29,0.22); } | |
| 751 | ||
| 752 | .lv-cta-secondary { | |
| 753 | padding: 13px 24px; | |
| 754 | border-radius: 11px; | |
| 755 | font-size: 15.5px; | |
| 756 | font-weight: 600; | |
| 757 | color: #16181d; | |
| 758 | border: 1px solid rgba(22,24,29,0.14); | |
| 759 | background: #ffffff; | |
| 760 | text-decoration: none; | |
| 761 | white-space: nowrap; | |
| 762 | transition: border-color 0.15s; | |
| 763 | } | |
| 764 | .lv-cta-secondary:hover { border-color: rgba(22,24,29,0.30); } | |
| 765 | ||
| 766 | .lv-hero-tag { | |
| 767 | margin-top: 18px; | |
| 768 | font-family: 'JetBrains Mono', monospace; | |
| 769 | font-size: 11.5px; | |
| 770 | letter-spacing: 0.08em; | |
| 771 | text-transform: uppercase; | |
| 772 | color: #8a8d99; | |
| 773 | } | |
| 774 | ||
| 775 | /* Demo window */ | |
| 776 | .lv-demo-window { | |
| 777 | margin: 56px auto 0; | |
| 778 | max-width: 860px; | |
| 779 | text-align: left; | |
| 780 | background: #ffffff; | |
| 781 | border: 1px solid rgba(22,24,29,0.09); | |
| 782 | border-radius: 18px; | |
| 783 | box-shadow: 0 40px 90px -40px rgba(22,24,29,0.30), 0 1px 2px rgba(22,24,29,0.04); | |
| 784 | overflow: hidden; | |
| 785 | } | |
| 786 | ||
| 787 | .lv-demo-bar { | |
| 788 | display: flex; | |
| 789 | align-items: center; | |
| 790 | gap: 7px; | |
| 791 | padding: 12px 18px; | |
| 792 | border-bottom: 1px solid rgba(22,24,29,0.07); | |
| 793 | background: #fcfcfd; | |
| 794 | } | |
| 795 | ||
| 796 | .lv-demo-dot { | |
| 797 | width: 10px; | |
| 798 | height: 10px; | |
| 799 | border-radius: 50%; | |
| 800 | background: #e4e5ea; | |
| 801 | } | |
| 802 | ||
| 803 | .lv-demo-url { | |
| 804 | margin-left: 10px; | |
| 805 | font-family: 'JetBrains Mono', monospace; | |
| 806 | font-size: 12px; | |
| 807 | color: #6b7080; | |
| 808 | } | |
| 809 | ||
| 810 | .lv-demo-live { | |
| 811 | margin-left: auto; | |
| 812 | display: inline-flex; | |
| 813 | align-items: center; | |
| 814 | gap: 6px; | |
| 815 | font-size: 11px; | |
| 816 | font-weight: 600; | |
| 817 | color: #1e7f5c; | |
| 818 | } | |
| 819 | ||
| 820 | .lv-demo-body { | |
| 821 | padding: 22px 24px; | |
| 822 | } | |
| 823 | ||
| 824 | .lv-demo-event { | |
| 825 | display: grid; | |
| 826 | grid-template-columns: 18px minmax(0, 1fr); | |
| 827 | gap: 14px; | |
| 828 | padding-bottom: 20px; | |
| 829 | position: relative; | |
| 830 | } | |
| 831 | .lv-demo-event:last-child { padding-bottom: 0; } | |
| 832 | ||
| 833 | .lv-demo-event-track { | |
| 834 | display: flex; | |
| 835 | flex-direction: column; | |
| 836 | align-items: center; | |
| 837 | } | |
| 838 | ||
| 839 | .lv-demo-line { | |
| 840 | width: 1px; | |
| 841 | flex: 1; | |
| 842 | background: rgba(22,24,29,0.08); | |
| 843 | margin-top: 5px; | |
| 844 | min-height: 20px; | |
| 845 | } | |
| 846 | ||
| 847 | .lv-demo-event-content {} | |
| 848 | ||
| 849 | .lv-demo-event-header { | |
| 850 | display: flex; | |
| 851 | align-items: baseline; | |
| 852 | gap: 10px; | |
| 853 | } | |
| 854 | ||
| 855 | .lv-demo-event-title { | |
| 856 | font-size: 13.5px; | |
| 857 | font-weight: 600; | |
| 858 | color: #16181d; | |
| 859 | } | |
| 860 | ||
| 861 | .lv-demo-event-time { | |
| 862 | font-family: 'JetBrains Mono', monospace; | |
| 863 | font-size: 11px; | |
| 864 | color: #8a8d99; | |
| 865 | } | |
| 866 | ||
| 867 | .lv-demo-event-body { | |
| 868 | font-size: 13px; | |
| 869 | color: #6b7080; | |
| 870 | margin-top: 2px; | |
| 871 | } | |
| 872 | ||
| 873 | /* Ticker */ | |
| 874 | .lv-ticker-wrap { | |
| 875 | border-top: 1px solid rgba(22,24,29,0.07); | |
| 876 | border-bottom: 1px solid rgba(22,24,29,0.07); | |
| 877 | background: #ffffff; | |
| 878 | margin-top: 64px; | |
| 879 | overflow: hidden; | |
| 880 | white-space: nowrap; | |
| 881 | position: relative; | |
| 882 | } | |
| 883 | ||
| 884 | .lv-ticker-track { | |
| 885 | display: inline-flex; | |
| 886 | animation: gcTicker 40s linear infinite; | |
| 887 | padding: 11px 0; | |
| 888 | } | |
| 889 | ||
| 890 | .lv-ticker-item { | |
| 891 | display: inline-flex; | |
| 892 | align-items: center; | |
| 893 | gap: 8px; | |
| 894 | font-family: 'JetBrains Mono', monospace; | |
| 895 | font-size: 11.5px; | |
| 896 | color: #6b7080; | |
| 897 | padding: 0 28px; | |
| 898 | border-right: 1px solid rgba(22,24,29,0.06); | |
| 899 | } | |
| 900 | ||
| 901 | /* Stats */ | |
| 902 | .lv-stats { | |
| 903 | background: #fcfcfd; | |
| 904 | } | |
| 905 | ||
| 906 | .lv-stats-inner { | |
| 907 | max-width: 1200px; | |
| 908 | margin: 0 auto; | |
| 909 | display: grid; | |
| 910 | grid-template-columns: repeat(4, 1fr); | |
| 911 | gap: 24px; | |
| 912 | padding: 52px 28px; | |
| 913 | } | |
| 914 | ||
| 915 | .lv-stat { | |
| 916 | text-align: center; | |
| 917 | } | |
| 918 | ||
| 919 | .lv-stat-num { | |
| 920 | font-family: 'Inter Tight', sans-serif; | |
| 921 | font-weight: 700; | |
| 922 | font-size: clamp(30px, 4vw, 44px); | |
| 923 | letter-spacing: -0.025em; | |
| 924 | color: #111318; | |
| 925 | } | |
| 926 | ||
| 927 | .lv-stat-label { | |
| 928 | font-size: 13px; | |
| 929 | color: #6b7080; | |
| 930 | margin-top: 4px; | |
| 931 | } | |
| 932 | ||
| 933 | /* Loop */ | |
| 934 | .lv-loop { | |
| 935 | padding: 96px 0; | |
| 936 | background: #ffffff; | |
| 937 | border-top: 1px solid rgba(22,24,29,0.07); | |
| 938 | border-bottom: 1px solid rgba(22,24,29,0.07); | |
| 939 | } | |
| 940 | ||
| 941 | .lv-loop-inner { | |
| 942 | max-width: 1200px; | |
| 943 | margin: 0 auto; | |
| 944 | padding: 0 28px; | |
| 945 | } | |
| 946 | ||
| 947 | .lv-stages { | |
| 948 | display: grid; | |
| 949 | grid-template-columns: repeat(6, 1fr); | |
| 950 | gap: 12px; | |
| 951 | } | |
| 952 | ||
| 953 | .lv-stage-card { | |
| 954 | border: 1px solid rgba(22,24,29,0.08); | |
| 955 | border-radius: 14px; | |
| 956 | background: #ffffff; | |
| 957 | padding: 20px 18px; | |
| 958 | transition: border-color 0.3s, background 0.3s; | |
| 959 | } | |
| 960 | ||
| 961 | .lv-stage-card.lv-stage-active { | |
| 962 | border-color: rgba(67,83,201,0.45); | |
| 963 | background: rgba(67,83,201,0.03); | |
| 964 | } | |
| 965 | ||
| 966 | .lv-stage-header { | |
| 967 | display: flex; | |
| 968 | align-items: center; | |
| 969 | gap: 8px; | |
| 970 | margin-bottom: 10px; | |
| 971 | } | |
| 972 | ||
| 973 | .lv-stage-n { | |
| 974 | font-family: 'JetBrains Mono', monospace; | |
| 975 | font-size: 10.5px; | |
| 976 | letter-spacing: 0.1em; | |
| 977 | text-transform: uppercase; | |
| 978 | color: #8a8d99; | |
| 979 | } | |
| 980 | ||
| 981 | .lv-stage-name { | |
| 982 | font-family: 'Inter Tight', sans-serif; | |
| 983 | font-size: 16px; | |
| 984 | font-weight: 600; | |
| 985 | letter-spacing: -0.01em; | |
| 986 | color: #16181d; | |
| 987 | margin-bottom: 5px; | |
| 988 | } | |
| 989 | ||
| 990 | .lv-stage-desc { | |
| 991 | font-size: 12px; | |
| 992 | color: #6b7080; | |
| 993 | line-height: 1.55; | |
| 994 | } | |
| 995 | ||
| 996 | .lv-stage-meta { | |
| 997 | font-family: 'JetBrains Mono', monospace; | |
| 998 | font-size: 10.5px; | |
| 999 | color: #8a8d99; | |
| 1000 | margin-top: 10px; | |
| 1001 | transition: color 0.3s; | |
| 1002 | } | |
| 1003 | ||
| 1004 | .lv-stage-meta.lv-stage-meta-active { | |
| 1005 | color: #4353c9; | |
| 1006 | } | |
| 1007 | ||
| 1008 | /* Heroes */ | |
| 1009 | .lv-heroes { | |
| 1010 | padding: 96px 0; | |
| 1011 | background: #fcfcfd; | |
| 1012 | } | |
| 1013 | ||
| 1014 | .lv-heroes-inner { | |
| 1015 | max-width: 1200px; | |
| 1016 | margin: 0 auto; | |
| 1017 | padding: 0 28px; | |
| 1018 | } | |
| 1019 | ||
| 1020 | .lv-heroes-header { | |
| 1021 | max-width: 640px; | |
| 1022 | margin-bottom: 56px; | |
| 1023 | } | |
| 1024 | ||
| 1025 | .lv-heroes-list { | |
| 1026 | display: flex; | |
| 1027 | flex-direction: column; | |
| 1028 | gap: 20px; | |
| 1029 | } | |
| 1030 | ||
| 1031 | .lv-hero-card { | |
| 1032 | display: grid; | |
| 1033 | grid-template-columns: minmax(0, 1fr) minmax(0, 1.1fr); | |
| 1034 | gap: 48px; | |
| 1035 | align-items: center; | |
| 1036 | border: 1px solid rgba(22,24,29,0.08); | |
| 1037 | border-radius: 20px; | |
| 1038 | background: #ffffff; | |
| 1039 | padding: 44px 48px; | |
| 1040 | text-decoration: none; | |
| 1041 | transition: border-color 0.2s, box-shadow 0.2s; | |
| 1042 | } | |
| 1043 | .lv-hero-card:hover { | |
| 1044 | border-color: rgba(22,24,29,0.22); | |
| 1045 | box-shadow: 0 24px 60px -36px rgba(22,24,29,0.24); | |
| 1046 | } | |
| 1047 | ||
| 1048 | .lv-hero-card-left {} | |
| 1049 | ||
| 1050 | .lv-hero-card-title { | |
| 1051 | font-family: 'Inter Tight', sans-serif; | |
| 1052 | font-size: 26px; | |
| 1053 | font-weight: 600; | |
| 1054 | letter-spacing: -0.022em; | |
| 1055 | line-height: 1.15; | |
| 1056 | color: #16181d; | |
| 1057 | margin: 0 0 12px; | |
| 1058 | } | |
| 1059 | ||
| 1060 | .lv-hero-card-body { | |
| 1061 | font-size: 14.5px; | |
| 1062 | color: #6b7080; | |
| 1063 | margin: 0 0 18px; | |
| 1064 | line-height: 1.65; | |
| 1065 | } | |
| 1066 | ||
| 1067 | .lv-hero-card-cta { | |
| 1068 | font-size: 13.5px; | |
| 1069 | font-weight: 600; | |
| 1070 | color: #4353c9; | |
| 1071 | } | |
| 1072 | ||
| 1073 | .lv-terminal { | |
| 1074 | border: 1px solid rgba(22,24,29,0.07); | |
| 1075 | border-radius: 14px; | |
| 1076 | background: #fcfcfd; | |
| 1077 | padding: 20px 22px; | |
| 1078 | font-family: 'JetBrains Mono', monospace; | |
| 1079 | font-size: 12px; | |
| 1080 | line-height: 1.9; | |
| 1081 | overflow: hidden; | |
| 1082 | } | |
| 1083 | ||
| 1084 | .lv-terminal-line { | |
| 1085 | display: flex; | |
| 1086 | align-items: center; | |
| 1087 | gap: 10px; | |
| 1088 | white-space: nowrap; | |
| 1089 | overflow: hidden; | |
| 1090 | text-overflow: ellipsis; | |
| 1091 | } | |
| 1092 | ||
| 1093 | /* Platform */ | |
| 1094 | .lv-platform { | |
| 1095 | padding: 96px 0; | |
| 1096 | background: #ffffff; | |
| 1097 | border-top: 1px solid rgba(22,24,29,0.07); | |
| 1098 | } | |
| 1099 | ||
| 1100 | .lv-platform-inner { | |
| 1101 | max-width: 1200px; | |
| 1102 | margin: 0 auto; | |
| 1103 | padding: 0 28px; | |
| 1104 | } | |
| 1105 | ||
| 1106 | .lv-cap-grid { | |
| 1107 | display: grid; | |
| 1108 | grid-template-columns: repeat(4, 1fr); | |
| 1109 | gap: 24px 32px; | |
| 1110 | } | |
| 1111 | ||
| 1112 | .lv-cap-col {} | |
| 1113 | ||
| 1114 | .lv-cap-group { | |
| 1115 | font-family: 'JetBrains Mono', monospace; | |
| 1116 | font-size: 10.5px; | |
| 1117 | letter-spacing: 0.12em; | |
| 1118 | text-transform: uppercase; | |
| 1119 | color: #8a8d99; | |
| 1120 | font-weight: 500; | |
| 1121 | margin-bottom: 12px; | |
| 1122 | padding-bottom: 8px; | |
| 1123 | border-bottom: 1px solid rgba(22,24,29,0.07); | |
| 1124 | } | |
| 1125 | ||
| 1126 | .lv-cap-items { | |
| 1127 | display: flex; | |
| 1128 | flex-direction: column; | |
| 1129 | gap: 7px; | |
| 1130 | } | |
| 1131 | ||
| 1132 | .lv-cap-item { | |
| 1133 | font-size: 12.5px; | |
| 1134 | color: #3a3d45; | |
| 1135 | line-height: 1.45; | |
| 1136 | } | |
| 1137 | ||
| 1138 | /* Sovereignty */ | |
| 1139 | .lv-sovereign { | |
| 1140 | position: relative; | |
| 1141 | overflow: hidden; | |
| 1142 | padding: 104px 0; | |
| 1143 | color: #fff; | |
| 1144 | background: radial-gradient(130% 130% at 50% -10%, #1b2030 0%, #12151f 45%, #0b0d13 100%); | |
| 1145 | } | |
| 1146 | ||
| 1147 | .lv-sovereign-grid-bg { | |
| 1148 | position: absolute; | |
| 1149 | inset: 0; | |
| 1150 | opacity: 0.4; | |
| 1151 | background-image: linear-gradient(rgba(255,255,255,0.05) 1px, transparent 1px), linear-gradient(90deg, rgba(255,255,255,0.05) 1px, transparent 1px); | |
| 1152 | background-size: 56px 56px; | |
| 1153 | -webkit-mask-image: radial-gradient(80% 80% at 50% 0%, #000, transparent 78%); | |
| 1154 | mask-image: radial-gradient(80% 80% at 50% 0%, #000, transparent 78%); | |
| 1155 | } | |
| 1156 | ||
| 1157 | .lv-sovereign-inner { | |
| 1158 | position: relative; | |
| 1159 | max-width: 1200px; | |
| 1160 | margin: 0 auto; | |
| 1161 | padding: 0 28px; | |
| 1162 | } | |
| 1163 | ||
| 1164 | .lv-section-header-dark { | |
| 1165 | max-width: 680px; | |
| 1166 | margin: 0 auto 48px; | |
| 1167 | text-align: center; | |
| 1168 | } | |
| 1169 | ||
| 1170 | .lv-layers-grid { | |
| 1171 | display: grid; | |
| 1172 | grid-template-columns: repeat(4, 1fr); | |
| 1173 | gap: 10px; | |
| 1174 | max-width: 980px; | |
| 1175 | margin: 0 auto; | |
| 1176 | } | |
| 1177 | ||
| 1178 | .lv-layer-chip { | |
| 1179 | border: 1px solid rgba(255,255,255,0.10); | |
| 1180 | border-radius: 10px; | |
| 1181 | padding: 12px 16px; | |
| 1182 | background: rgba(255,255,255,0.03); | |
| 1183 | } | |
| 1184 | ||
| 1185 | .lv-layer-cta { | |
| 1186 | border-color: rgba(169,180,238,0.30); | |
| 1187 | background: rgba(169,180,238,0.06); | |
| 1188 | display: flex; | |
| 1189 | align-items: center; | |
| 1190 | text-decoration: none; | |
| 1191 | transition: background 0.15s; | |
| 1192 | } | |
| 1193 | .lv-layer-cta:hover { background: rgba(169,180,238,0.10); } | |
| 1194 | ||
| 1195 | .lv-layer-cta-text { | |
| 1196 | font-size: 13px; | |
| 1197 | font-weight: 500; | |
| 1198 | color: #a9b4ee; | |
| 1199 | } | |
| 1200 | ||
| 1201 | .lv-layer-n { | |
| 1202 | font-family: 'JetBrains Mono', monospace; | |
| 1203 | font-size: 10px; | |
| 1204 | color: rgba(255,255,255,0.4); | |
| 1205 | margin-bottom: 3px; | |
| 1206 | } | |
| 1207 | ||
| 1208 | .lv-layer-name { | |
| 1209 | font-size: 13px; | |
| 1210 | font-weight: 500; | |
| 1211 | color: rgba(255,255,255,0.92); | |
| 1212 | } | |
| 1213 | ||
| 1214 | .lv-sovereign-feats { | |
| 1215 | display: flex; | |
| 1216 | gap: 44px; | |
| 1217 | justify-content: center; | |
| 1218 | flex-wrap: wrap; | |
| 1219 | margin-top: 52px; | |
| 1220 | text-align: center; | |
| 1221 | } | |
| 1222 | ||
| 1223 | .lv-sovereign-feat {} | |
| 1224 | ||
| 1225 | .lv-sovereign-feat-title { | |
| 1226 | font-family: 'Inter Tight', sans-serif; | |
| 1227 | font-size: 20px; | |
| 1228 | font-weight: 700; | |
| 1229 | color: #fff; | |
| 1230 | } | |
| 1231 | ||
| 1232 | .lv-sovereign-feat-sub { | |
| 1233 | color: rgba(255,255,255,0.55); | |
| 1234 | font-size: 13px; | |
| 1235 | margin-top: 2px; | |
| 1236 | } | |
| 1237 | ||
| 1238 | /* Twin cards */ | |
| 1239 | .lv-twin { | |
| 1240 | padding: 96px 0; | |
| 1241 | background: #fcfcfd; | |
| 1242 | } | |
| 1243 | ||
| 1244 | .lv-twin-inner { | |
| 1245 | max-width: 1200px; | |
| 1246 | margin: 0 auto; | |
| 1247 | padding: 0 28px; | |
| 1248 | display: grid; | |
| 1249 | grid-template-columns: 1fr 1fr; | |
| 1250 | gap: 24px; | |
| 1251 | } | |
| 1252 | ||
| 1253 | .lv-twin-card { | |
| 1254 | border: 1px solid rgba(22,24,29,0.08); | |
| 1255 | border-radius: 20px; | |
| 1256 | background: #ffffff; | |
| 1257 | padding: 44px 48px; | |
| 1258 | } | |
| 1259 | ||
| 1260 | .lv-twin-title { | |
| 1261 | font-family: 'Inter Tight', sans-serif; | |
| 1262 | font-size: 24px; | |
| 1263 | font-weight: 600; | |
| 1264 | letter-spacing: -0.02em; | |
| 1265 | line-height: 1.2; | |
| 1266 | margin: 0 0 12px; | |
| 1267 | color: #16181d; | |
| 1268 | } | |
| 1269 | ||
| 1270 | .lv-twin-body { | |
| 1271 | font-size: 14.5px; | |
| 1272 | color: #6b7080; | |
| 1273 | margin: 0 0 16px; | |
| 1274 | line-height: 1.7; | |
| 1275 | } | |
| 1276 | ||
| 1277 | .lv-twin-link { | |
| 1278 | font-size: 13.5px; | |
| 1279 | font-weight: 600; | |
| 1280 | color: #4353c9; | |
| 1281 | text-decoration: none; | |
| 1282 | } | |
| 1283 | .lv-twin-link:hover { text-decoration: underline; } | |
| 1284 | ||
| 1285 | /* Quote */ | |
| 1286 | .lv-quote { | |
| 1287 | padding: 40px 0 96px; | |
| 1288 | background: #fcfcfd; | |
| 1289 | } | |
| 1290 | ||
| 1291 | .lv-quote-inner { | |
| 1292 | max-width: 980px; | |
| 1293 | margin: 0 auto; | |
| 1294 | padding: 0 28px; | |
| 1295 | text-align: center; | |
| 1296 | } | |
| 1297 | ||
| 1298 | .lv-quote-text { | |
| 1299 | font-family: 'Inter Tight', sans-serif; | |
| 1300 | font-weight: 600; | |
| 1301 | font-size: clamp(26px, 3.8vw, 42px); | |
| 1302 | line-height: 1.2; | |
| 1303 | letter-spacing: -0.025em; | |
| 1304 | margin: 0; | |
| 1305 | color: #111318; | |
| 1306 | } | |
| 1307 | ||
| 1308 | .lv-em { | |
| 1309 | font-style: normal; | |
| 1310 | color: #4353c9; | |
| 1311 | } | |
| 1312 | ||
| 1313 | /* CTA */ | |
| 1314 | .lv-cta-section { | |
| 1315 | padding: 0 0 104px; | |
| 1316 | background: #fcfcfd; | |
| 1317 | } | |
| 1318 | ||
| 1319 | .lv-cta-card { | |
| 1320 | max-width: 820px; | |
| 1321 | margin: 0 auto; | |
| 1322 | padding: 64px 40px; | |
| 1323 | text-align: center; | |
| 1324 | background: #ffffff; | |
| 1325 | border: 1px solid rgba(22,24,29,0.08); | |
| 1326 | border-radius: 26px; | |
| 1327 | box-shadow: 0 30px 80px -50px rgba(22,24,29,0.28); | |
| 1328 | position: relative; | |
| 1329 | overflow: hidden; | |
| 1330 | } | |
| 1331 | ||
| 1332 | .lv-cta-glow { | |
| 1333 | position: absolute; | |
| 1334 | inset: -40% 0 auto 0; | |
| 1335 | height: 280px; | |
| 1336 | background: radial-gradient(50% 60% at 50% 0%, rgba(67,83,201,0.06), transparent 70%); | |
| 1337 | pointer-events: none; | |
| 1338 | } | |
| 1339 | ||
| 1340 | .lv-cta-h2 { | |
| 1341 | font-family: 'Inter Tight', sans-serif; | |
| 1342 | font-weight: 700; | |
| 1343 | letter-spacing: -0.028em; | |
| 1344 | font-size: clamp(30px, 4.6vw, 48px); | |
| 1345 | margin: 0; | |
| 1346 | position: relative; | |
| 1347 | color: #111318; | |
| 1348 | } | |
| 1349 | ||
| 1350 | .lv-cta-sub { | |
| 1351 | color: #6b7080; | |
| 1352 | font-size: 17px; | |
| 1353 | margin: 16px 0 30px; | |
| 1354 | position: relative; | |
| 1355 | } | |
| 1356 | ||
| 1357 | .lv-cta-actions { | |
| 1358 | display: flex; | |
| 1359 | gap: 12px; | |
| 1360 | justify-content: center; | |
| 1361 | flex-wrap: wrap; | |
| 1362 | position: relative; | |
| 1363 | } | |
| 1364 | ||
| 1365 | .lv-cta-fine { | |
| 1366 | margin-top: 20px; | |
| 1367 | font-family: 'JetBrains Mono', monospace; | |
| 1368 | font-size: 11px; | |
| 1369 | color: #8a8d99; | |
| 1370 | position: relative; | |
| 1371 | } | |
| 1372 | ||
| 1373 | /* Footer */ | |
| 1374 | .lv-footer { | |
| 1375 | border-top: 1px solid rgba(22,24,29,0.07); | |
| 1376 | background: #ffffff; | |
| 1377 | padding: 56px 0 30px; | |
| 1378 | } | |
| 1379 | ||
| 1380 | .lv-footer-inner { | |
| 1381 | max-width: 1200px; | |
| 1382 | margin: 0 auto; | |
| 1383 | padding: 0 28px; | |
| 1384 | display: flex; | |
| 1385 | gap: 48px; | |
| 1386 | flex-wrap: wrap; | |
| 1387 | justify-content: space-between; | |
| 1388 | } | |
| 1389 | ||
| 1390 | .lv-footer-brand {} | |
| 1391 | ||
| 1392 | .lv-footer-tagline { | |
| 1393 | color: #6b7080; | |
| 1394 | font-size: 13.5px; | |
| 1395 | margin: 12px 0 0; | |
| 1396 | max-width: 32ch; | |
| 1397 | line-height: 1.6; | |
| 1398 | } | |
| 1399 | ||
| 1400 | .lv-footer-cols { | |
| 1401 | display: flex; | |
| 1402 | gap: 64px; | |
| 1403 | flex-wrap: wrap; | |
| 1404 | } | |
| 1405 | ||
| 1406 | .lv-footer-col { | |
| 1407 | display: flex; | |
| 1408 | flex-direction: column; | |
| 1409 | gap: 9px; | |
| 1410 | } | |
| 1411 | ||
| 1412 | .lv-footer-col-head { | |
| 1413 | font-family: 'JetBrains Mono', monospace; | |
| 1414 | font-size: 11px; | |
| 1415 | text-transform: uppercase; | |
| 1416 | letter-spacing: 0.1em; | |
| 1417 | color: #8a8d99; | |
| 1418 | margin: 0 0 4px; | |
| 1419 | font-weight: 500; | |
| 1420 | } | |
| 1421 | ||
| 1422 | .lv-footer-link { | |
| 1423 | color: #3a3d45; | |
| 1424 | font-size: 13.5px; | |
| 1425 | text-decoration: none; | |
| 1426 | transition: color 0.15s; | |
| 1427 | } | |
| 1428 | .lv-footer-link:hover { color: #16181d; } | |
| 1429 | ||
| 1430 | .lv-footer-bar { | |
| 1431 | max-width: 1200px; | |
| 1432 | margin: 44px auto 0; | |
| 1433 | padding: 22px 28px 0; | |
| 1434 | border-top: 1px solid rgba(22,24,29,0.06); | |
| 1435 | display: flex; | |
| 1436 | justify-content: space-between; | |
| 1437 | flex-wrap: wrap; | |
| 1438 | gap: 8px; | |
| 1439 | color: #8a8d99; | |
| 1440 | font-size: 12.5px; | |
| 1441 | } | |
| 1442 | ||
| 1443 | .lv-footer-stack { | |
| 1444 | font-family: 'JetBrains Mono', monospace; | |
| 1445 | font-size: 11px; | |
| 1446 | } | |
| 1447 | `; |