Merge pull request 'feat(landing): redesign hero + editorial layout with Atkinson Hyperlegible' (#187) from feat/landing-redesign into main
Some checks failed
CI / frontend (push) Has been cancelled
CI / e2e (push) Has been cancelled
CI / backend (push) Has been cancelled
Mirror to GitHub / mirror (push) Has been cancelled

Visually approved in local PR env. 1 commit, frontend-only, fully reversible.
This commit was merged in pull request #187.
This commit is contained in:
2026-05-29 04:23:27 +00:00
3 changed files with 434 additions and 299 deletions

View File

@@ -164,46 +164,74 @@ export default function LandingPage() {
</div>
</section>
{/* Problem — asymmetric: headline left, cards right */}
<section id="problem" className="landing-section landing-section-alt landing-reveal">
{/* Problem — editorial list, no cards */}
<section id="problem" className="landing-section landing-section-alt landing-reveal landing-section-tight">
<div className="landing-section-inner">
<div className="landing-problem-layout">
<div className="landing-problem-headline">
<div className="landing-section-label">The Problem</div>
<h2>Documentation is broken.<br />Everyone knows it.</h2>
<p>Engineers don&apos;t want to write it. Managers hate chasing it. Clients never see it. The same issues get solved from scratch &mdash; every time.</p>
</div>
<div className="landing-problem-grid">
<ProblemCard icon="&#9201;" color="red" title="15&ndash;25 min lost per ticket" description="More time documenting than resolving. After a complex issue, writing notes is the last thing anyone does." />
<ProblemCard icon="&#128203;" color="amber" title="Vague, useless notes" description={`"Fixed Outlook" tells no one anything. Notes under pressure are always too vague to help next time.`} />
<ProblemCard icon="&#128260;" color="slate" title="Knowledge walks out the door" description="When a senior engineer leaves, years of tribal knowledge vanish overnight." />
<ProblemCard icon="&#129504;" color="violet" title="Context switching kills speed" description="Jumping between the issue, docs, PSA tickets, and knowledge bases fragments focus." />
<p>Engineers don&apos;t want to write it. Managers hate chasing it. Clients never see it. The same issues get solved from scratch, every time.</p>
</div>
<ol className="landing-problem-list">
<li className="landing-problem-item">
<span className="landing-problem-num">01</span>
<div className="landing-problem-body">
<h3>15&ndash;25 min lost per ticket</h3>
<p>More time documenting than resolving. After a complex issue, writing notes is the last thing anyone does.</p>
</div>
</li>
<li className="landing-problem-item">
<span className="landing-problem-num">02</span>
<div className="landing-problem-body">
<h3>Vague, useless notes</h3>
<p>&ldquo;Fixed Outlook&rdquo; tells no one anything. Notes under pressure are always too vague to help next time.</p>
</div>
</li>
<li className="landing-problem-item">
<span className="landing-problem-num">03</span>
<div className="landing-problem-body">
<h3>Knowledge walks out the door</h3>
<p>When a senior engineer leaves, years of tribal knowledge vanish overnight.</p>
</div>
</li>
<li className="landing-problem-item">
<span className="landing-problem-num">04</span>
<div className="landing-problem-body">
<h3>Context switching kills speed</h3>
<p>Jumping between the issue, docs, PSA tickets, and knowledge bases fragments focus.</p>
</div>
</li>
</ol>
</div>
</div>
</section>
{/* Equation */}
{/* Equation — typographic moment */}
<div className="landing-equation-section landing-reveal">
<div className="landing-equation-inner">
<div className="landing-section-label">The Answer</div>
<div className="landing-brand-equation">
<span className="landing-eq-item">Resolution</span>
<span className="landing-eq-operator">+</span>
<span className="landing-eq-item">Documentation</span>
<span className="landing-eq-operator">&minus;</span>
<span className="landing-eq-item">Time</span>
<span className="landing-eq-operator">=</span>
<span className="landing-eq-result">ResolutionFlow</span>
<div className="landing-brand-equation" aria-label="Resolution plus documentation minus time equals ResolutionFlow">
<div className="landing-eq-lhs">
<span className="landing-eq-item">Resolution</span>
<span className="landing-eq-operator">+</span>
<span className="landing-eq-item">Documentation</span>
<span className="landing-eq-operator">&minus;</span>
<span className="landing-eq-item">Time</span>
</div>
<div className="landing-eq-equals">
<span className="landing-eq-operator-equals">=</span>
</div>
<div className="landing-eq-result">ResolutionFlow</div>
</div>
<p className="landing-equation-desc">
What if documentation was a <em>byproduct</em> of solving the issue &mdash; not a separate task?
What if documentation was a <em>byproduct</em> of solving the issue, not a separate task?
</p>
</div>
</div>
{/* How It Works — zigzag */}
<section id="how-it-works" className="landing-section landing-reveal">
<section id="how-it-works" className="landing-section landing-reveal landing-section-tight">
<div className="landing-section-inner">
<div className="landing-section-label">How It Works</div>
<h2 className="landing-section-title">Three steps. Zero note-writing.</h2>
@@ -268,54 +296,47 @@ export default function LandingPage() {
</div>
</section>
{/* Features */}
<section id="features" className="landing-section landing-section-alt landing-reveal">
{/* Features — editorial spec list */}
<section id="features" className="landing-section landing-section-alt landing-reveal landing-section-generous">
<div className="landing-section-inner">
<div className="landing-section-label">Features</div>
<h2 className="landing-section-title">Everything you need to troubleshoot faster.</h2>
<div className="landing-feature-highlight">
<div className="landing-feature-highlight-icon">
<svg width="28" height="28" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><circle cx="12" cy="12" r="3" /><path d="M12 1v2M12 21v2M4.22 4.22l1.42 1.42M18.36 18.36l1.42 1.42M1 12h2M21 12h2M4.22 19.78l1.42-1.42M18.36 5.64l1.42-1.42" /></svg>
</div>
<div className="landing-feature-highlight-marker" aria-hidden="true">FP</div>
<div className="landing-feature-highlight-content">
<h3>FlowPilot &mdash; Your AI Copilot</h3>
<p>Like having a senior engineer on every call. Describe the issue, get expert troubleshooting guidance, and documentation writes itself &mdash; as a byproduct of solving the problem.</p>
<h3>FlowPilot, your AI copilot</h3>
<p>Like having a senior engineer on every call. Describe the issue, get expert troubleshooting guidance, and documentation writes itself, as a byproduct of solving the problem.</p>
</div>
</div>
<div className="landing-features-grid">
<FeatureCard
icon={<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><rect x="3" y="3" width="18" height="18" rx="2" /><line x1="9" y1="3" x2="9" y2="21" /></svg>}
title="Guided Flows"
description="Build step-by-step troubleshooting paths your team can follow. Great for onboarding and consistency."
/>
<FeatureCard
icon={<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="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" /><line x1="16" y1="13" x2="8" y2="13" /><line x1="16" y1="17" x2="8" y2="17" /></svg>}
title="Zero Empty Tickets"
description="Every session generates timestamped notes, formatted for your PSA. No more empty ticket closures."
/>
<FeatureCard
icon={<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><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>}
title="Team Knowledge"
description="Solutions are saved and surfaced when the next engineer hits a similar issue."
/>
<FeatureCard
icon={<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><polyline points="22 12 18 12 15 21 9 3 6 12 2 12" /></svg>}
title="Session Analytics"
description="Track resolution times, identify recurring issues, and measure team performance."
/>
<FeatureCard
icon={<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><rect x="2" y="3" width="20" height="14" rx="2" ry="2" /><line x1="8" y1="21" x2="16" y2="21" /><line x1="12" y1="17" x2="12" y2="21" /></svg>}
title="PSA Integration"
description="Connect to ConnectWise, Atera, and Syncro. Push session docs straight to tickets."
/>
</div>
<dl className="landing-feature-spec">
<div className="landing-feature-row">
<dt>Guided Flows</dt>
<dd>Build step-by-step troubleshooting paths your team can follow. Great for onboarding and consistency.</dd>
</div>
<div className="landing-feature-row">
<dt>Zero Empty Tickets</dt>
<dd>Every session generates timestamped notes, formatted for your PSA. No more empty ticket closures.</dd>
</div>
<div className="landing-feature-row">
<dt>Team Knowledge</dt>
<dd>Solutions are saved and surfaced when the next engineer hits a similar issue.</dd>
</div>
<div className="landing-feature-row">
<dt>Session Analytics</dt>
<dd>Track resolution times, identify recurring issues, and measure team performance.</dd>
</div>
<div className="landing-feature-row">
<dt>PSA Integration</dt>
<dd>Connect to ConnectWise, Atera, and Syncro. Push session docs straight to tickets.</dd>
</div>
</dl>
</div>
</section>
{/* Pricing */}
<section id="pricing" className="landing-section landing-reveal">
<section id="pricing" className="landing-section landing-reveal landing-section-generous">
<div className="landing-section-inner">
<div className="landing-section-label">Pricing</div>
<h2 className="landing-section-title">Simple pricing. No surprises.</h2>
@@ -364,7 +385,7 @@ export default function LandingPage() {
</section>
{/* FAQ */}
<section id="faq" className="landing-section landing-section-alt landing-reveal">
<section id="faq" className="landing-section landing-section-alt landing-reveal landing-section-tight">
<div className="landing-section-inner">
<div className="landing-section-label">FAQ</div>
<h2 className="landing-section-title">Common questions</h2>
@@ -399,15 +420,16 @@ export default function LandingPage() {
</div>
</div>
{/* CTA */}
<section className="landing-cta-section landing-reveal">
{/* CTA — drenched */}
<section className="landing-cta-section landing-cta-drench landing-reveal">
<div className="landing-cta-inner">
<h2>Ready to stop writing ticket notes?</h2>
<p>Get early access. Troubleshoot your next ticket with FlowPilot.</p>
<div className="landing-cta-eyebrow">Stop writing ticket notes</div>
<h2>Troubleshoot your next ticket with FlowPilot.</h2>
<p>Get early access. Free to start, no credit card.</p>
<div className="landing-cta-actions">
<Link to="/register?from=beta" className="landing-btn-hero-primary">Get started</Link>
<Link to="/register?from=beta" className="landing-btn-cta-invert">Get started</Link>
<a href="#how-it-works" className="landing-btn-cta-ghost">See how it works</a>
</div>
<p className="landing-cta-fine-print">Free to start. No credit card required.</p>
</div>
</section>
@@ -421,30 +443,6 @@ export default function LandingPage() {
/* ---- Sub-components ---- */
function ProblemCard({ icon, color, title, description }: {
icon: string; color: string; title: string; description: string
}) {
return (
<div className="landing-problem-card">
<div className={`landing-problem-icon ${color}`}>{icon}</div>
<h3>{title}</h3>
<p>{description}</p>
</div>
)
}
function FeatureCard({ icon, title, description }: {
icon: React.ReactNode; title: string; description: string
}) {
return (
<div className="landing-feature-card">
<div className="landing-feature-icon">{icon}</div>
<h3>{title}</h3>
<p>{description}</p>
</div>
)
}
function PricingCard({ name, target, amount, period, note, features, btnLabel, btnStyle, featured, plan }: {
name: string; target: string; amount: string; period?: string; note: string
features: string[]; btnLabel: string; btnStyle: 'outline' | 'filled'; featured?: boolean; plan: string