Pre-launch — Gluecron is in final validation. Public signups and git hosting for non-owner users open after launch review.
CodeIssuesPull RequestsActionsSecurityInsightsSettings
✨ AI
More
Blame · Line-by-line history

landing.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.

landing.tsxBlame1069 lines · 1 contributor
2b821b7Claude1/**
2 * Marketing landing page for logged-out visitors.
3 *
958d26aClaude4 * Editorial-Technical redesign — 2026.05.
5 * Hero · trust strip · feature grid · workflow walkthrough ·
6 * comparison · terminal · pricing teaser · closing CTA.
2b821b7Claude7 *
958d26aClaude8 * Pure presentational. Drops into <Layout user={null}>.
9 * All styles scoped under `.landing-` so they don't bleed into app views.
2b821b7Claude10 */
11
12import type { FC } from "hono/jsx";
13
14export interface LandingPageProps {
15 stats?: {
16 publicRepos?: number;
17 users?: number;
18 };
19}
20
4c47454Claude21export const LandingHero: FC<LandingPageProps> = ({ stats } = {}) => {
8e9f1d9Claude22 const hasStats =
23 stats &&
24 ((stats.publicRepos !== undefined && stats.publicRepos > 0) ||
25 (stats.users !== undefined && stats.users > 0));
4c47454Claude26
2b821b7Claude27 return (
28 <>
29 <style>{landingCss}</style>
30
4c47454Claude31 <div class="landing-root">
32 {/* ---------- Hero ---------- */}
33 <section class="landing-hero">
958d26aClaude34 <div class="landing-hero-bg" aria-hidden="true">
35 <div class="landing-hero-blob landing-hero-blob-1" />
36 <div class="landing-hero-blob landing-hero-blob-2" />
37 <div class="landing-hero-grid" />
2b821b7Claude38 </div>
958d26aClaude39
40 <div class="landing-hero-inner stagger">
41 <div class="eyebrow landing-hero-eyebrow">
42 <span class="landing-hero-pulse" />
43 v1 · pre-launch · {new Date().getFullYear()}
44 </div>
45
46 <h1 class="landing-hero-title display">
47 Where software{" "}
48 <span class="gradient-text">writes itself.</span>
49 </h1>
50
51 <p class="landing-hero-sub">
52 Gluecron is the operator-tier replacement for GitHub. Push code,
53 and the platform reviews it, fixes it, ships it. Spec-to-PR. Auto-repair.
54 Real-time gates. Built for the era when most code is written by AI
55 and most reviews are too.
56 </p>
57
58 <div class="landing-hero-ctas">
59 <a href="/register" class="btn btn-primary btn-xl landing-cta-primary">
60 Start shipping
61 <span class="landing-cta-arrow" aria-hidden="true">{"→"}</span>
62 </a>
63 <a href="/explore" class="btn btn-secondary btn-xl">
64 Explore repos
65 </a>
66 </div>
67
68 <p class="landing-hero-caption">
69 Already have a repo?
70 <span class="landing-hero-cmd">
71 <span class="kbd">git</span>
72 <span class="kbd">remote</span>
73 <span class="kbd">add</span>
74 <span class="kbd">gluecron</span>
75 <span class="landing-hero-arrow">{"→"}</span>
76 <span class="kbd">git push</span>
77 </span>
78 </p>
79
80 {hasStats && (
81 <p class="landing-stats">
82 {stats!.publicRepos !== undefined && stats!.publicRepos > 0 && (
83 <span>
84 <strong>{stats!.publicRepos.toLocaleString()}</strong>
85 {stats!.publicRepos === 1 ? " repo" : " repos"}
86 </span>
87 )}
88 {stats!.publicRepos !== undefined &&
89 stats!.publicRepos > 0 &&
90 stats!.users !== undefined &&
91 stats!.users > 0 && <span class="landing-stats-sep">·</span>}
92 {stats!.users !== undefined && stats!.users > 0 && (
93 <span>
94 <strong>{stats!.users.toLocaleString()}</strong>
95 {stats!.users === 1 ? " developer" : " developers"}
96 </span>
97 )}
98 <span class="landing-stats-sep">·</span>
4c47454Claude99 <span>
958d26aClaude100 <strong>100%</strong> AI-native
4c47454Claude101 </span>
958d26aClaude102 </p>
103 )}
104 </div>
105 </section>
106
107 {/* ---------- Trust strip ---------- */}
108 <section class="landing-trust">
109 <p class="landing-trust-label">Built for the new shape of software</p>
110 <div class="landing-trust-row">
111 <span class="landing-trust-item">Spec-to-PR</span>
112 <span class="landing-trust-dot" aria-hidden="true" />
113 <span class="landing-trust-item">Auto-repair</span>
114 <span class="landing-trust-dot" aria-hidden="true" />
115 <span class="landing-trust-item">Live gates</span>
116 <span class="landing-trust-dot" aria-hidden="true" />
117 <span class="landing-trust-item">MCP-native</span>
118 <span class="landing-trust-dot" aria-hidden="true" />
119 <span class="landing-trust-item">Workflow runner</span>
120 <span class="landing-trust-dot" aria-hidden="true" />
121 <span class="landing-trust-item">Self-hosted</span>
122 </div>
4c47454Claude123 </section>
124
125 {/* ---------- Feature grid ---------- */}
958d26aClaude126 <section class="landing-section">
127 <div class="section-header">
128 <div class="eyebrow">The platform</div>
129 <h2>An IDE for your repo, not just a host.</h2>
130 <p>
131 Gluecron ships the surfaces GitHub charges extra for, and the
132 ones it never built. AI is a teammate with its own commits, not
133 a sidebar.
2b821b7Claude134 </p>
135 </div>
4c47454Claude136
958d26aClaude137 <div class="landing-features stagger">
138 <FeatureCard
139 icon={
140 <svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round">
141 <path d="M12 3l1.9 4.6L18.5 9l-3.6 3 1 4.8L12 14.5 8.1 16.8l1-4.8L5.5 9l4.6-1.4z" />
142 </svg>
143 }
144 title="AI as a teammate"
145 desc="Spec-to-PR drafts entire features from plain English. Auto-explain reviews every diff. The AI commits with its own bot account, visible in your history."
146 />
147 <FeatureCard
148 icon={
149 <svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round">
150 <path d="M12 2.5l8 3.5v6c0 5-3.5 8.5-8 9.5-4.5-1-8-4.5-8-9.5v-6z" />
151 <path d="M9 12l2 2 4-4" />
152 </svg>
153 }
154 title="Quality gate that learns"
155 desc="GateTest scans every push. Auto-repair fixes regressions before you see them. Required checks block bad PRs from merging. Your software self-corrects."
156 />
157 <FeatureCard
158 icon={
159 <svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round">
160 <path d="M13 2L4 14h7l-1 8 9-12h-7z" />
161 </svg>
162 }
163 title="Real-time everything"
164 desc="Live workflow logs over SSE. Live PR review presence. Live deploys you watch happen. No polling, no refresh, no waiting on a CI tab."
165 />
166 <FeatureCard
167 icon={
168 <svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round">
169 <rect x="3" y="3" width="18" height="18" rx="3" />
170 <path d="M3 9h18M9 21V9" />
171 </svg>
172 }
173 title="Workflow runner"
174 desc="Drop a yaml in `.gluecron/workflows/` and it runs on every push. Cron triggers, secret substitution, matrix runs, artifacts. No SaaS provider in the loop."
175 />
176 <FeatureCard
177 icon={
178 <svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round">
179 <circle cx="12" cy="12" r="9" />
180 <path d="M3 12h18M12 3a14 14 0 010 18M12 3a14 14 0 000 18" />
181 </svg>
182 }
183 title="MCP-native"
184 desc="Claude, Cursor, Code — they speak Model Context Protocol. Gluecron exposes search, file read, issues, codebase explain as MCP tools by default."
185 />
186 <FeatureCard
187 icon={
188 <svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round">
189 <path d="M21 12a9 9 0 11-18 0 9 9 0 0118 0z" />
190 <path d="M12 7v5l3 2" />
191 </svg>
192 }
193 title="Yours, on your hardware"
194 desc="Single-binary Bun runtime. Postgres + bare git repos on a volume. Deploy to Fly, Railway, your own VPS. No vendor lock, no surprise bills."
195 />
2b821b7Claude196 </div>
958d26aClaude197 </section>
2b821b7Claude198
958d26aClaude199 {/* ---------- Workflow walkthrough ---------- */}
200 <section class="landing-section landing-walk">
201 <div class="section-header">
202 <div class="eyebrow">How it works</div>
203 <h2>Push code. Watch it ship.</h2>
204 <p>
205 Every push triggers the same pipeline whether the commit came
206 from you, from CI, or from an AI agent.
4c47454Claude207 </p>
208 </div>
958d26aClaude209
210 <div class="landing-walk-grid">
211 <WalkStep n="01" title="Push" desc="git push to gluecron — Smart-HTTP, SSH, or via the web editor." />
212 <WalkStep n="02" title="Gate" desc="GateTest runs. Secret scanner runs. AI security review posts inline comments." />
213 <WalkStep n="03" title="Repair" desc="If a gate fails, auto-repair tries to fix it. New commit gets re-gated." />
214 <WalkStep n="04" title="Ship" desc="Green push to default branch fires deploy webhook. Crontech, Fly, your prod." />
215 </div>
4c47454Claude216 </section>
2b821b7Claude217
4c47454Claude218 {/* ---------- Terminal block ---------- */}
958d26aClaude219 <section class="landing-section landing-terminal-section">
220 <div class="landing-terminal-wrap">
221 <div class="landing-terminal" role="img" aria-label="Example git push to gluecron with passing gates">
222 <div class="landing-terminal-chrome">
223 <span class="landing-terminal-dot landing-terminal-dot-r" />
224 <span class="landing-terminal-dot landing-terminal-dot-y" />
225 <span class="landing-terminal-dot landing-terminal-dot-g" />
226 <span class="landing-terminal-title">~/your-repo &mdash; zsh</span>
227 </div>
228 <div class="landing-terminal-body">
229 <div class="landing-term-line">
230 <span class="landing-term-prompt">$</span>
231 <span>git remote add gluecron https://gluecron.com/you/your-repo.git</span>
232 </div>
233 <div class="landing-term-line">
234 <span class="landing-term-prompt">$</span>
235 <span>git push -u gluecron main</span>
236 </div>
237 <div class="landing-term-line landing-term-out">
238 <span class="landing-term-meta">remote:</span>
239 <span>Resolving deltas… 100% (24/24)</span>
240 </div>
241 <div class="landing-term-line landing-term-out landing-term-ok-line">
242 <span class="landing-term-ok">{"✓"}</span>
243 <span>pushed to gluecron.com/you/your-repo</span>
244 </div>
245 <div class="landing-term-line landing-term-out landing-term-ok-line">
246 <span class="landing-term-ok">{"✓"}</span>
247 <span>GateTest passed (12 rules, 0 violations)</span>
248 </div>
249 <div class="landing-term-line landing-term-out landing-term-ok-line">
250 <span class="landing-term-ok">{"✓"}</span>
251 <span>AI review posted (2 suggestions, 0 blockers)</span>
252 </div>
253 <div class="landing-term-line landing-term-out landing-term-ok-line">
254 <span class="landing-term-ok">{"✓"}</span>
255 <span>deployed to your-repo.gluecron.com <span class="landing-term-meta">(4.1s)</span></span>
256 </div>
257 <div class="landing-term-line landing-term-cursor">
258 <span class="landing-term-prompt">$</span>
259 <span class="landing-term-blink">▍</span>
260 </div>
261 </div>
4c47454Claude262 </div>
958d26aClaude263 </div>
264 </section>
265
266 {/* ---------- Comparison ---------- */}
267 <section class="landing-section">
268 <div class="section-header">
269 <div class="eyebrow">vs the incumbent</div>
270 <h2>Everything GitHub charges for. And the parts they didn't build.</h2>
271 </div>
272
273 <div class="landing-compare">
274 <CompareRow feature="Git hosting + Smart-HTTP push" them="✓" us="✓" />
275 <CompareRow feature="Issues, PRs, code review" them="✓" us="✓" />
276 <CompareRow feature="Workflow runner (Actions-equivalent)" them="paid minutes" us="self-hosted, unmetered" highlight />
277 <CompareRow feature="AI code review on every PR" them="Copilot subscription" us="built in" highlight />
278 <CompareRow feature="Spec-to-PR (NL feature → draft PR)" them="—" us="✓" highlight />
279 <CompareRow feature="Auto-repair on failed gates" them="—" us="✓" highlight />
280 <CompareRow feature="Real-time SSE for logs + PRs" them="polling" us="streaming" highlight />
281 <CompareRow feature="MCP server (Claude / Cursor)" them="—" us="✓" highlight />
282 <CompareRow feature="Self-host on your own infra" them="enterprise tier" us="single binary" highlight />
283 <CompareRow feature="Pre-receive policy enforcement" them="rulesets (GHE)" us="✓" />
284 </div>
285 </section>
286
287 {/* ---------- Pricing teaser ---------- */}
288 <section class="landing-section">
289 <div class="section-header">
290 <div class="eyebrow">Pricing</div>
291 <h2>Free to start. Honest at scale.</h2>
292 <p>
293 Self-hosting is free forever. Hosted plans price the AI calls,
294 not the seats.
295 </p>
296 </div>
297
298 <div class="landing-pricing">
299 <PricingCard
300 tier="Free"
301 price="$0"
302 cadence="forever"
303 desc="For personal projects + open source. Public + private repos, full AI suite, fair quotas."
304 features={["Unlimited public repos", "3 private repos", "5K AI calls / mo", "Community support"]}
305 cta="Start free"
306 href="/register"
307 />
308 <PricingCard
309 tier="Pro"
310 price="$12"
311 cadence="per user / mo"
312 desc="For working developers. Lifts every quota, adds priority routing, no Gluecron branding on deploys."
313 features={["Unlimited private repos", "100K AI calls / mo", "Priority queue", "Custom domains"]}
314 cta="Go Pro"
315 href="/settings/billing"
316 highlight
317 />
318 <PricingCard
319 tier="Team"
320 price="Talk to us"
321 cadence="custom"
322 desc="For orgs running production on Gluecron. SSO, audit retention, enterprise SLA, on-prem."
323 features={["SSO + SCIM", "On-prem deploy", "Dedicated capacity", "24/7 incident response"]}
324 cta="Contact"
325 href="mailto:hello@gluecron.com"
326 />
327 </div>
328 </section>
329
330 {/* ---------- Closing CTA ---------- */}
331 <section class="landing-cta-section">
332 <div class="landing-cta-card">
333 <div class="landing-cta-bg" aria-hidden="true" />
334 <div class="eyebrow">Ready when you are</div>
335 <h2 class="landing-cta-title">
336 Stop maintaining the platform.<br />
337 <span class="gradient-text">Start shipping the product.</span>
338 </h2>
339 <p class="landing-cta-sub">
340 Free to start, self-hosted-friendly, MCP-native. Migrate from
341 GitHub in one click.
342 </p>
343 <div class="landing-cta-buttons">
344 <a href="/register" class="btn btn-primary btn-xl">
345 Create your account
346 <span class="landing-cta-arrow" aria-hidden="true">{"→"}</span>
347 </a>
348 <a href="/import" class="btn btn-ghost btn-xl">
349 Migrate a repo
350 </a>
4c47454Claude351 </div>
352 </div>
353 </section>
354 </div>
2b821b7Claude355 </>
356 );
357};
358
958d26aClaude359const FeatureCard: FC<{ icon: any; title: string; desc: string }> = ({
360 icon,
361 title,
362 desc,
363}) => (
364 <div class="landing-feature">
365 <div class="landing-feature-icon" aria-hidden="true">
366 {icon}
367 </div>
368 <h3 class="landing-feature-title">{title}</h3>
369 <p class="landing-feature-desc">{desc}</p>
370 </div>
371);
372
373const WalkStep: FC<{ n: string; title: string; desc: string }> = ({
374 n,
375 title,
376 desc,
377}) => (
378 <div class="landing-walk-step">
379 <div class="landing-walk-num">{n}</div>
380 <h3 class="landing-walk-title">{title}</h3>
381 <p class="landing-walk-desc">{desc}</p>
382 </div>
383);
384
385const CompareRow: FC<{
386 feature: string;
387 them: string;
388 us: string;
389 highlight?: boolean;
390}> = ({ feature, them, us, highlight }) => (
391 <div class={`landing-compare-row${highlight ? " landing-compare-hl" : ""}`}>
392 <div class="landing-compare-feature">{feature}</div>
393 <div class="landing-compare-them">{them}</div>
394 <div class="landing-compare-us">{us === "✓" ? "✓" : us}</div>
395 </div>
396);
397
398const PricingCard: FC<{
399 tier: string;
400 price: string;
401 cadence: string;
402 desc: string;
403 features: string[];
404 cta: string;
405 href: string;
406 highlight?: boolean;
407}> = ({ tier, price, cadence, desc, features, cta, href, highlight }) => (
408 <div class={`landing-price-card${highlight ? " landing-price-hl" : ""}`}>
409 {highlight && <div class="landing-price-badge">Most popular</div>}
410 <div class="landing-price-tier">{tier}</div>
411 <div class="landing-price-amount">
412 <span class="landing-price-num">{price}</span>
413 <span class="landing-price-cad">{cadence}</span>
414 </div>
415 <p class="landing-price-desc">{desc}</p>
416 <ul class="landing-price-features">
417 {features.map((f) => (
418 <li>
419 <span class="landing-price-check" aria-hidden="true">{"✓"}</span>
420 {f}
421 </li>
422 ))}
423 </ul>
424 <a
425 href={href}
426 class={`btn ${highlight ? "btn-primary" : "btn-secondary"} btn-block landing-price-cta`}
427 >
428 {cta}
429 </a>
430 </div>
431);
432
4c47454Claude433// Backwards-compatible default — web.tsx imports `LandingPage`.
434export const LandingPage: FC<LandingPageProps> = (props) => (
435 <LandingHero {...props} />
2b821b7Claude436);
437
4c47454Claude438export default LandingPage;
439
2b821b7Claude440const landingCss = `
958d26aClaude441 /* ============================================================ */
442 /* Landing — Editorial-Technical 2026.05 */
443 /* ============================================================ */
4c47454Claude444 .landing-root {
445 position: relative;
958d26aClaude446 max-width: 1180px;
4c47454Claude447 margin: 0 auto;
448 padding: 0 16px;
958d26aClaude449 }
450 .landing-root > section { position: relative; }
451
452 /* ---------- Hero ---------- */
453 .landing-hero {
454 position: relative;
455 padding: var(--s-20) 0 var(--s-16);
456 text-align: center;
4c47454Claude457 overflow: hidden;
458 }
958d26aClaude459 .landing-hero-bg {
460 position: absolute;
461 inset: -10% -20%;
462 pointer-events: none;
463 z-index: 0;
4c47454Claude464 }
958d26aClaude465 .landing-hero-blob {
466 position: absolute;
467 border-radius: 50%;
468 filter: blur(80px);
469 opacity: 0.55;
470 }
471 .landing-hero-blob-1 {
472 top: -10%;
473 left: 30%;
474 width: 480px;
475 height: 480px;
476 background: radial-gradient(circle, rgba(140,109,255,0.55), transparent 65%);
477 }
478 .landing-hero-blob-2 {
479 top: 10%;
480 left: 50%;
481 width: 380px;
482 height: 380px;
483 background: radial-gradient(circle, rgba(54,197,214,0.40), transparent 65%);
484 }
485 .landing-hero-grid {
4c47454Claude486 position: absolute;
487 inset: 0;
958d26aClaude488 background-image:
489 linear-gradient(to right, rgba(255,255,255,0.04) 1px, transparent 1px),
490 linear-gradient(to bottom, rgba(255,255,255,0.04) 1px, transparent 1px);
491 background-size: 60px 60px;
492 mask-image: radial-gradient(ellipse 50% 50% at 50% 30%, #000 0%, transparent 75%);
493 -webkit-mask-image: radial-gradient(ellipse 50% 50% at 50% 30%, #000 0%, transparent 75%);
494 }
495 :root[data-theme='light'] .landing-hero-grid {
496 background-image:
497 linear-gradient(to right, rgba(15,16,28,0.06) 1px, transparent 1px),
498 linear-gradient(to bottom, rgba(15,16,28,0.06) 1px, transparent 1px);
4c47454Claude499 }
500
958d26aClaude501 .landing-hero-inner {
502 position: relative;
503 z-index: 1;
504 max-width: 960px;
2b821b7Claude505 margin: 0 auto;
506 }
958d26aClaude507 .landing-hero-eyebrow {
508 margin: 0 auto var(--s-6);
509 color: var(--accent);
510 }
511 .landing-hero-eyebrow::before { display: none; }
512 .landing-hero-pulse {
513 width: 7px;
514 height: 7px;
515 border-radius: 50%;
516 background: var(--accent);
517 box-shadow: 0 0 0 0 rgba(140,109,255,0.6);
518 animation: pulse 1.8s ease-out infinite;
519 flex-shrink: 0;
520 }
521 @keyframes pulse {
522 0% { box-shadow: 0 0 0 0 rgba(140,109,255,0.55); }
523 70% { box-shadow: 0 0 0 10px rgba(140,109,255,0); }
524 100% { box-shadow: 0 0 0 0 rgba(140,109,255,0); }
525 }
526
2b821b7Claude527 .landing-hero-title {
958d26aClaude528 font-size: clamp(44px, 8vw, 92px);
529 line-height: 0.98;
530 letter-spacing: -0.04em;
4c47454Claude531 font-weight: 600;
958d26aClaude532 margin: 0 0 var(--s-6);
533 color: var(--text-strong);
2b821b7Claude534 }
958d26aClaude535
2b821b7Claude536 .landing-hero-sub {
958d26aClaude537 font-size: clamp(15px, 1.6vw, 19px);
2b821b7Claude538 color: var(--text-muted);
958d26aClaude539 max-width: 680px;
540 margin: 0 auto;
4c47454Claude541 line-height: 1.55;
958d26aClaude542 letter-spacing: -0.005em;
2b821b7Claude543 }
4c47454Claude544
2b821b7Claude545 .landing-hero-ctas {
546 display: flex;
958d26aClaude547 gap: 12px;
2b821b7Claude548 justify-content: center;
549 flex-wrap: wrap;
958d26aClaude550 margin-top: var(--s-10);
2b821b7Claude551 }
958d26aClaude552 .landing-cta-arrow {
553 transition: transform var(--t-base) var(--ease-spring);
554 display: inline-block;
2b821b7Claude555 }
958d26aClaude556 .btn:hover .landing-cta-arrow,
557 .landing-cta-primary:hover .landing-cta-arrow {
558 transform: translateX(4px);
8e9f1d9Claude559 }
2b821b7Claude560
4c47454Claude561 .landing-hero-caption {
958d26aClaude562 margin-top: var(--s-8);
563 font-size: var(--t-sm);
4c47454Claude564 color: var(--text-muted);
958d26aClaude565 display: flex;
566 flex-wrap: wrap;
567 align-items: center;
568 justify-content: center;
569 gap: 12px;
2b821b7Claude570 }
958d26aClaude571 .landing-hero-cmd {
572 display: inline-flex;
573 align-items: center;
574 gap: 4px;
575 padding: 6px 12px;
576 background: var(--bg-elevated);
4c47454Claude577 border: 1px solid var(--border);
958d26aClaude578 border-radius: var(--r-full);
579 box-shadow: var(--elev-1);
580 }
581 .landing-hero-cmd .kbd {
582 border: 0;
583 background: transparent;
584 padding: 0 4px;
585 color: var(--text-muted);
586 font-size: 12px;
587 }
588 .landing-hero-cmd .kbd:nth-last-of-type(1) { color: var(--accent); }
589 .landing-hero-arrow {
590 color: var(--text-faint);
591 font-size: 13px;
592 margin: 0 2px;
2b821b7Claude593 }
4c47454Claude594
595 .landing-stats {
958d26aClaude596 margin-top: var(--s-7);
597 font-family: var(--font-mono);
598 font-size: 12px;
599 color: var(--text-muted);
600 display: flex;
601 align-items: center;
602 justify-content: center;
603 gap: 10px;
604 flex-wrap: wrap;
605 letter-spacing: 0.02em;
606 }
607 .landing-stats strong {
608 color: var(--text-strong);
609 font-weight: 600;
610 font-feature-settings: 'tnum';
611 }
612 .landing-stats-sep { opacity: 0.4; }
613
614 /* ---------- Trust strip ---------- */
615 .landing-trust {
616 margin: var(--s-8) auto var(--s-16);
617 padding: var(--s-7) 0;
618 border-top: 1px solid var(--border-subtle);
619 border-bottom: 1px solid var(--border-subtle);
620 text-align: center;
621 }
622 .landing-trust-label {
623 font-family: var(--font-mono);
624 font-size: 11px;
625 text-transform: uppercase;
626 letter-spacing: 0.18em;
627 color: var(--text-faint);
628 margin-bottom: var(--s-4);
629 }
630 .landing-trust-row {
631 display: flex;
632 align-items: center;
633 justify-content: center;
634 gap: 16px;
635 flex-wrap: wrap;
636 }
637 .landing-trust-item {
638 font-family: var(--font-display);
639 font-size: 17px;
640 font-weight: 500;
641 letter-spacing: -0.015em;
2b821b7Claude642 color: var(--text-muted);
958d26aClaude643 transition: color var(--t-fast) var(--ease);
2b821b7Claude644 }
958d26aClaude645 .landing-trust-item:hover { color: var(--text-strong); }
646 .landing-trust-dot {
647 width: 4px;
648 height: 4px;
649 border-radius: 50%;
650 background: var(--text-faint);
651 opacity: 0.5;
652 }
653
654 /* ---------- Section base ---------- */
655 .landing-section { margin: var(--s-20) auto; }
2b821b7Claude656
4c47454Claude657 /* ---------- Feature grid ---------- */
658 .landing-features {
2b821b7Claude659 display: grid;
660 grid-template-columns: repeat(3, 1fr);
958d26aClaude661 gap: 16px;
2b821b7Claude662 }
663 .landing-feature {
958d26aClaude664 background: var(--bg-elevated);
2b821b7Claude665 border: 1px solid var(--border);
958d26aClaude666 border-radius: var(--r-lg);
667 padding: var(--s-7);
668 position: relative;
669 overflow: hidden;
670 isolation: isolate;
671 transition:
672 transform var(--t-base) var(--ease-out-quart),
673 border-color var(--t-base) var(--ease),
674 box-shadow var(--t-base) var(--ease);
675 }
676 .landing-feature::before {
677 content: '';
678 position: absolute;
679 inset: 0;
680 background: radial-gradient(120% 100% at 0% 0%, rgba(140,109,255,0.08), transparent 55%);
681 opacity: 0;
682 transition: opacity var(--t-base) var(--ease);
683 z-index: -1;
4c47454Claude684 }
685 .landing-feature:hover {
958d26aClaude686 transform: translateY(-3px);
687 border-color: var(--border-strong);
688 box-shadow: var(--elev-2);
2b821b7Claude689 }
958d26aClaude690 .landing-feature:hover::before { opacity: 1; }
2b821b7Claude691 .landing-feature-icon {
4c47454Claude692 display: inline-flex;
693 align-items: center;
694 justify-content: center;
958d26aClaude695 width: 40px;
696 height: 40px;
697 border-radius: var(--r);
698 background: var(--accent-gradient-soft);
699 color: var(--accent);
700 margin-bottom: var(--s-4);
701 border: 1px solid rgba(140,109,255,0.20);
2b821b7Claude702 }
703 .landing-feature-title {
958d26aClaude704 font-family: var(--font-display);
705 font-size: 19px;
706 font-weight: 600;
707 letter-spacing: -0.018em;
708 margin: 0 0 var(--s-2);
709 color: var(--text-strong);
2b821b7Claude710 }
711 .landing-feature-desc {
958d26aClaude712 font-size: var(--t-sm);
713 color: var(--text-muted);
714 line-height: 1.6;
715 margin: 0;
716 }
717
718 /* ---------- Walkthrough ---------- */
719 .landing-walk-grid {
720 display: grid;
721 grid-template-columns: repeat(4, 1fr);
722 gap: 16px;
723 counter-reset: walk;
724 }
725 .landing-walk-step {
726 position: relative;
727 padding: var(--s-7) var(--s-6) var(--s-6);
728 background: var(--bg-elevated);
729 border: 1px solid var(--border);
730 border-radius: var(--r-lg);
731 }
732 .landing-walk-step::after {
733 content: '';
734 position: absolute;
735 top: 50%;
736 right: -12px;
737 width: 12px;
738 height: 1px;
739 background: var(--border-strong);
740 }
741 .landing-walk-step:last-child::after { display: none; }
742 .landing-walk-num {
743 display: inline-block;
744 font-family: var(--font-mono);
745 font-size: 11px;
746 color: var(--accent);
747 background: var(--accent-gradient-faint);
748 border: 1px solid rgba(140,109,255,0.30);
749 padding: 3px 8px;
750 border-radius: var(--r-full);
751 letter-spacing: 0.06em;
752 margin-bottom: var(--s-3);
753 }
754 .landing-walk-title {
755 font-family: var(--font-display);
756 font-size: 22px;
757 font-weight: 600;
758 letter-spacing: -0.022em;
759 margin: 0 0 var(--s-2);
760 color: var(--text-strong);
761 }
762 .landing-walk-desc {
763 font-size: var(--t-sm);
2b821b7Claude764 color: var(--text-muted);
765 line-height: 1.55;
766 margin: 0;
767 }
768
958d26aClaude769 /* ---------- Terminal ---------- */
770 .landing-terminal-section { margin-top: var(--s-16); }
4c47454Claude771 .landing-terminal-wrap {
772 display: flex;
2b821b7Claude773 justify-content: center;
774 }
4c47454Claude775 .landing-terminal {
776 width: 100%;
958d26aClaude777 max-width: 820px;
778 background: linear-gradient(180deg, #0a0b12 0%, #06070c 100%);
779 border: 1px solid var(--border-strong);
780 border-radius: var(--r-lg);
781 overflow: hidden;
782 box-shadow: var(--elev-3), 0 0 60px -10px rgba(140,109,255,0.18);
4c47454Claude783 text-align: left;
2b821b7Claude784 }
958d26aClaude785 :root[data-theme='light'] .landing-terminal {
786 background: linear-gradient(180deg, #0f111a 0%, #06070c 100%);
787 }
788 .landing-terminal-chrome {
789 display: flex;
790 align-items: center;
791 gap: 7px;
792 padding: 11px 14px;
793 background: rgba(255,255,255,0.025);
794 border-bottom: 1px solid rgba(255,255,255,0.06);
795 position: relative;
796 }
797 .landing-terminal-dot {
798 width: 11px;
799 height: 11px;
800 border-radius: 50%;
801 flex-shrink: 0;
802 }
803 .landing-terminal-dot-r { background: #ff5f57; }
804 .landing-terminal-dot-y { background: #febc2e; }
805 .landing-terminal-dot-g { background: #28c840; }
806 .landing-terminal-title {
807 position: absolute;
808 left: 50%;
809 transform: translateX(-50%);
810 font-family: var(--font-mono);
811 font-size: 11px;
812 color: rgba(237,237,242,0.55);
813 letter-spacing: 0.01em;
814 }
815 .landing-terminal-body {
816 padding: var(--s-6) var(--s-7);
817 font-family: var(--font-mono);
818 font-feature-settings: var(--mono-feat);
819 font-size: 13.5px;
820 line-height: 1.85;
821 color: rgba(237,237,242,0.92);
822 }
4c47454Claude823 .landing-term-line {
824 display: flex;
825 gap: 10px;
826 white-space: pre-wrap;
827 word-break: break-all;
2b821b7Claude828 }
958d26aClaude829 .landing-term-out { color: rgba(237,237,242,0.7); }
830 .landing-term-prompt { color: rgba(140,109,255,0.85); user-select: none; flex-shrink: 0; }
831 .landing-term-meta { color: rgba(237,237,242,0.45); }
832 .landing-term-ok { color: var(--green); user-select: none; flex-shrink: 0; }
833 .landing-term-ok-line { color: rgba(237,237,242,0.92); }
834 .landing-term-cursor { margin-top: 4px; }
835 .landing-term-blink {
836 animation: blink 1.05s steps(2) infinite;
837 color: var(--accent);
838 }
839 @keyframes blink { 50% { opacity: 0; } }
840
841 /* ---------- Comparison ---------- */
842 .landing-compare {
843 max-width: 920px;
844 margin: 0 auto;
845 border: 1px solid var(--border);
846 border-radius: var(--r-lg);
847 overflow: hidden;
848 background: var(--bg-elevated);
849 }
850 .landing-compare-row {
851 display: grid;
852 grid-template-columns: 1fr 180px 180px;
853 align-items: center;
854 padding: 14px 20px;
855 border-bottom: 1px solid var(--border-subtle);
856 font-size: var(--t-sm);
857 transition: background var(--t-fast) var(--ease);
858 }
859 .landing-compare-row:last-child { border-bottom: none; }
860 .landing-compare-row:hover { background: var(--bg-hover); }
861 .landing-compare-feature {
862 color: var(--text-strong);
863 font-weight: 500;
864 }
865 .landing-compare-them, .landing-compare-us {
866 text-align: center;
867 font-family: var(--font-mono);
868 font-size: 12px;
869 color: var(--text-muted);
870 }
871 .landing-compare-us { color: var(--green); font-weight: 500; }
872 .landing-compare-hl .landing-compare-us {
873 color: var(--accent);
874 font-weight: 600;
2b821b7Claude875 }
958d26aClaude876 .landing-compare-hl .landing-compare-feature::after {
877 content: 'NEW';
878 margin-left: 8px;
879 padding: 1px 6px;
880 border-radius: 4px;
881 background: var(--accent-gradient-faint);
882 color: var(--accent);
883 font-family: var(--font-mono);
884 font-size: 9px;
885 letter-spacing: 0.1em;
886 font-weight: 600;
887 vertical-align: 1px;
888 }
889 @media (max-width: 720px) {
890 .landing-compare-row { grid-template-columns: 1fr 80px 80px; padding: 12px 14px; }
891 .landing-compare-hl .landing-compare-feature::after { display: none; }
892 }
893
894 /* ---------- Pricing ---------- */
895 .landing-pricing {
896 display: grid;
897 grid-template-columns: repeat(3, 1fr);
898 gap: 16px;
899 max-width: 1080px;
900 margin: 0 auto;
901 align-items: stretch;
902 }
903 .landing-price-card {
904 position: relative;
905 background: var(--bg-elevated);
906 border: 1px solid var(--border);
907 border-radius: var(--r-lg);
908 padding: var(--s-7);
909 display: flex;
910 flex-direction: column;
911 gap: var(--s-4);
912 transition: border-color var(--t-base) var(--ease), transform var(--t-base) var(--ease);
913 }
914 .landing-price-card:hover {
915 border-color: var(--border-strong);
916 transform: translateY(-2px);
917 }
918 .landing-price-hl {
919 border-color: rgba(140,109,255,0.35);
920 box-shadow: var(--elev-2), 0 0 0 1px rgba(140,109,255,0.25);
921 background:
922 linear-gradient(180deg, rgba(140,109,255,0.05), transparent 50%),
923 var(--bg-elevated);
924 }
925 .landing-price-hl:hover { border-color: rgba(140,109,255,0.55); }
926 .landing-price-badge {
927 position: absolute;
928 top: -10px;
929 left: 50%;
930 transform: translateX(-50%);
931 padding: 3px 12px;
932 background: var(--accent-gradient);
933 color: #fff;
934 font-family: var(--font-mono);
935 font-size: 10px;
936 letter-spacing: 0.1em;
937 text-transform: uppercase;
938 font-weight: 600;
939 border-radius: var(--r-full);
940 box-shadow: 0 4px 12px -2px rgba(140,109,255,0.4);
941 }
942 .landing-price-tier {
943 font-family: var(--font-mono);
944 font-size: 11px;
945 text-transform: uppercase;
946 letter-spacing: 0.16em;
947 color: var(--text-muted);
948 }
949 .landing-price-amount {
950 display: flex;
951 align-items: baseline;
952 gap: 8px;
953 }
954 .landing-price-num {
955 font-family: var(--font-display);
956 font-size: 40px;
957 font-weight: 600;
958 letter-spacing: -0.03em;
959 color: var(--text-strong);
960 }
961 .landing-price-cad {
962 font-size: var(--t-sm);
963 color: var(--text-faint);
964 }
965 .landing-price-desc {
966 font-size: var(--t-sm);
967 color: var(--text-muted);
968 line-height: 1.55;
969 margin: 0;
970 }
971 .landing-price-features {
972 list-style: none;
973 padding: 0;
974 margin: 0;
975 display: flex;
976 flex-direction: column;
977 gap: 8px;
978 font-size: var(--t-sm);
979 color: var(--text);
980 }
981 .landing-price-features li {
982 display: flex;
983 align-items: center;
984 gap: 9px;
985 }
986 .landing-price-check {
987 color: var(--accent);
988 font-weight: 600;
4c47454Claude989 flex-shrink: 0;
2b821b7Claude990 }
958d26aClaude991 .landing-price-cta { margin-top: auto; }
992
993 /* ---------- Closing CTA ---------- */
994 .landing-cta-section { margin: var(--s-20) auto var(--s-16); }
995 .landing-cta-card {
996 position: relative;
997 text-align: center;
998 padding: var(--s-16) var(--s-7);
999 border: 1px solid var(--border-strong);
1000 border-radius: var(--r-2xl);
1001 background: var(--bg-elevated);
1002 overflow: hidden;
1003 isolation: isolate;
1004 }
1005 .landing-cta-bg {
1006 position: absolute;
1007 inset: 0;
1008 z-index: -1;
1009 background:
1010 radial-gradient(60% 100% at 50% 0%, rgba(140,109,255,0.16), transparent 65%),
1011 radial-gradient(40% 80% at 80% 100%, rgba(54,197,214,0.10), transparent 65%);
1012 }
1013 .landing-cta-card::after {
1014 content: '';
1015 position: absolute;
1016 inset: 0;
1017 z-index: -1;
1018 background-image: radial-gradient(rgba(255,255,255,0.04) 1px, transparent 1px);
1019 background-size: 24px 24px;
1020 mask-image: radial-gradient(ellipse at center, #000 0%, transparent 65%);
1021 -webkit-mask-image: radial-gradient(ellipse at center, #000 0%, transparent 65%);
1022 opacity: 0.6;
1023 }
1024 :root[data-theme='light'] .landing-cta-card::after {
1025 background-image: radial-gradient(rgba(15,16,28,0.07) 1px, transparent 1px);
1026 }
1027 .landing-cta-card .eyebrow { justify-content: center; }
1028 .landing-cta-title {
1029 font-family: var(--font-display);
1030 font-size: clamp(28px, 4.4vw, 56px);
1031 line-height: 1.05;
1032 letter-spacing: -0.03em;
1033 font-weight: 600;
1034 margin: var(--s-3) 0 var(--s-4);
1035 color: var(--text-strong);
1036 }
1037 .landing-cta-sub {
1038 font-size: var(--t-md);
1039 color: var(--text-muted);
1040 max-width: 560px;
1041 margin: 0 auto var(--s-8);
1042 line-height: 1.55;
1043 }
1044 .landing-cta-buttons {
1045 display: flex;
1046 gap: 12px;
1047 justify-content: center;
1048 flex-wrap: wrap;
1049 }
2b821b7Claude1050
1051 /* ---------- Responsive ---------- */
958d26aClaude1052 @media (max-width: 960px) {
1053 .landing-features { grid-template-columns: repeat(2, 1fr); }
1054 .landing-walk-grid { grid-template-columns: repeat(2, 1fr); }
1055 .landing-walk-step::after { display: none; }
1056 .landing-pricing { grid-template-columns: 1fr; max-width: 480px; }
1057 }
1058 @media (max-width: 640px) {
1059 .landing-hero { padding: var(--s-14) 0 var(--s-10); }
1060 .landing-hero-cmd { flex-wrap: wrap; justify-content: center; }
1061 .landing-hero-ctas { flex-direction: column; align-items: stretch; }
1062 .landing-hero-ctas .btn { width: 100%; justify-content: center; }
1063 .landing-features { grid-template-columns: 1fr; }
1064 .landing-walk-grid { grid-template-columns: 1fr; }
1065 .landing-section { margin: var(--s-12) auto; }
1066 .landing-cta-card { padding: var(--s-10) var(--s-5); }
1067 .landing-cta-buttons .btn { width: 100%; justify-content: center; }
2b821b7Claude1068 }
1069`;