385 lines
14 KiB
TypeScript
385 lines
14 KiB
TypeScript
import Link from "next/link";
|
|
import {
|
|
SITE,
|
|
services,
|
|
cases,
|
|
testimonials,
|
|
} from "./content";
|
|
|
|
import SiteHeader from "./components/SiteHeader";
|
|
import Hero from "./components/Hero";
|
|
import VelocityMarquee from "./components/VelocityMarquee";
|
|
import Reveal, { RevealItem } from "./components/Reveal";
|
|
import Scoreboard from "./components/Scoreboard";
|
|
import CaseCard, { type CaseData } from "./components/CaseCard";
|
|
import ProcessLoop from "./components/ProcessLoop";
|
|
import Faq from "./components/Faq";
|
|
import Magnetic from "./components/Magnetic";
|
|
import SectionDivider from "./components/SectionDivider";
|
|
|
|
const TAPE = [
|
|
"Revenue, not vanity metrics",
|
|
"Paid",
|
|
"SEO",
|
|
"Content",
|
|
"Social",
|
|
"+52% ROAS",
|
|
"+217% demos",
|
|
"+128 booked/mo",
|
|
"Reported every month",
|
|
];
|
|
|
|
const INDUSTRIES = [
|
|
"E-commerce",
|
|
"B2B SaaS",
|
|
"Clinics",
|
|
"Professional services",
|
|
"DTC brands",
|
|
"Marketplaces",
|
|
];
|
|
|
|
/* Monochrome partner / certification marks, recreated as simple inline SVG
|
|
wordmark-badges (no raster, no copied brand art). Illustrative, consistent
|
|
with the footer "illustrative samples" disclaimer. ~24px tall, --c-text-dim. */
|
|
const TRUST_MARKS: { label: string; svg: React.ReactNode }[] = [
|
|
{
|
|
label: "Google Partner",
|
|
svg: (
|
|
<svg viewBox="0 0 150 24" role="img" focusable="false">
|
|
<circle cx="11" cy="12" r="9" fill="none" stroke="currentColor" strokeWidth="2.2" />
|
|
<path d="M11 12h9" stroke="currentColor" strokeWidth="2.2" />
|
|
<path d="M16 12a5 5 0 1 0-1.5 3.6" fill="none" stroke="currentColor" strokeWidth="2.2" strokeLinecap="round" />
|
|
<text x="28" y="16" fontFamily="var(--font-sans)" fontSize="13" fontWeight="700" fill="currentColor">
|
|
Google Partner
|
|
</text>
|
|
</svg>
|
|
),
|
|
},
|
|
{
|
|
label: "Meta Business Partner",
|
|
svg: (
|
|
<svg viewBox="0 0 178 24" role="img" focusable="false">
|
|
<path
|
|
d="M4 16c0-5 2.5-8 5.5-8 2.6 0 4 2 5.5 5 1.5-3 2.9-5 5.5-5 3 0 5.5 3 5.5 8M4 16c0 2 1 3 2.6 3 2.2 0 3.6-2.8 4.9-5M22 16c0 2-1 3-2.6 3-2.2 0-3.6-2.8-4.9-5"
|
|
fill="none"
|
|
stroke="currentColor"
|
|
strokeWidth="2.2"
|
|
strokeLinecap="round"
|
|
/>
|
|
<text x="32" y="16" fontFamily="var(--font-sans)" fontSize="13" fontWeight="700" fill="currentColor">
|
|
Meta Business Partner
|
|
</text>
|
|
</svg>
|
|
),
|
|
},
|
|
{
|
|
label: "HubSpot Certified",
|
|
svg: (
|
|
<svg viewBox="0 0 158 24" role="img" focusable="false">
|
|
<circle cx="12" cy="14" r="6" fill="none" stroke="currentColor" strokeWidth="2.2" />
|
|
<circle cx="18.5" cy="6.5" r="2.6" fill="none" stroke="currentColor" strokeWidth="2" />
|
|
<path d="M12 8V5M15 12l2.2-3.4" stroke="currentColor" strokeWidth="2.2" strokeLinecap="round" />
|
|
<text x="30" y="16" fontFamily="var(--font-sans)" fontSize="13" fontWeight="700" fill="currentColor">
|
|
HubSpot Certified
|
|
</text>
|
|
</svg>
|
|
),
|
|
},
|
|
{
|
|
label: "Shopify Plus Partner",
|
|
svg: (
|
|
<svg viewBox="0 0 168 24" role="img" focusable="false">
|
|
<path
|
|
d="M9 4 5 5 3 20l8 1 2-16-4-1Zm0 0 1.6.4M11 6.5c-1.6 0-2.2 1.2-2.2 2.2 0 1.4 2.4 1.3 2.4 2.8 0 .7-.6 1-1.2 1"
|
|
fill="none"
|
|
stroke="currentColor"
|
|
strokeWidth="1.8"
|
|
strokeLinejoin="round"
|
|
strokeLinecap="round"
|
|
/>
|
|
<text x="22" y="16" fontFamily="var(--font-sans)" fontSize="13" fontWeight="700" fill="currentColor">
|
|
Shopify Plus Partner
|
|
</text>
|
|
</svg>
|
|
),
|
|
},
|
|
];
|
|
|
|
/* Small live-feeling figures that flank the manifesto so the section reads full,
|
|
not empty. Illustrative samples, consistent with the rest of the prototype. */
|
|
const MANIFESTO_STATS = [
|
|
{ k: "Avg. reporting cadence", v: "Monthly" },
|
|
{ k: "Channels we run", v: "6+" },
|
|
{ k: "Built around", v: "Your revenue" },
|
|
];
|
|
|
|
export default function Page() {
|
|
return (
|
|
<>
|
|
<SiteHeader />
|
|
|
|
<main id="main">
|
|
<Hero />
|
|
|
|
{/* ===== KINETIC TAPE — scroll-velocity marquee ===== */}
|
|
<section className="tape" aria-label="What we do, at a glance">
|
|
<VelocityMarquee items={TAPE} />
|
|
</section>
|
|
|
|
{/* ===== POSITIONING / MANIFESTO ===== */}
|
|
<section id="manifesto" className="manifesto frame" aria-labelledby="man-h">
|
|
<div className="wrap manifesto__wrap">
|
|
<Reveal as="p" className="kicker">
|
|
<span className="kicker__dot" />
|
|
The problem with most agencies
|
|
</Reveal>
|
|
<Reveal as="p" className="manifesto__lead display" delay={80}>
|
|
<span id="man-h">
|
|
Most budgets buy <span className="strike">activity</span>, not
|
|
outcomes. Dashboards fill with impressions while the sales number{" "}
|
|
<span className="grad">sits still.</span>
|
|
</span>
|
|
</Reveal>
|
|
<Reveal as="p" className="manifesto__body" delay={180}>
|
|
We started Feedback Studios to fix that. Every campaign we run is
|
|
built to move revenue, and we report on it the way your CFO would.
|
|
No vanity metrics. No mystery. Just the number that pays the bills.
|
|
</Reveal>
|
|
|
|
{/* stat ribbon — fills the section, adds a "live" texture */}
|
|
<Reveal as="ul" className="manifesto__stats" stagger={0.07} delay={120}>
|
|
{MANIFESTO_STATS.map((s) => (
|
|
<RevealItem as="li" className="manifesto__stat" key={s.k}>
|
|
<span className="manifesto__stat-v display">{s.v}</span>
|
|
<span className="manifesto__stat-k">{s.k}</span>
|
|
</RevealItem>
|
|
))}
|
|
</Reveal>
|
|
</div>
|
|
</section>
|
|
|
|
{/* ===== INDUSTRIES / SOCIAL PROOF ===== */}
|
|
<section className="proof" aria-label="Who we work with">
|
|
<div className="wrap">
|
|
<p className="kicker proof__label">
|
|
Trusted by teams that care about the sales number
|
|
</p>
|
|
<Reveal as="ul" className="proof__list" stagger={0.06}>
|
|
{INDUSTRIES.map((p) => (
|
|
<RevealItem as="li" className="proof__item" key={p}>
|
|
<span className="proof__item-dot" aria-hidden="true" />
|
|
{p}
|
|
</RevealItem>
|
|
))}
|
|
</Reveal>
|
|
|
|
{/* second row — monochrome partner / certification marks (inline
|
|
SVG, no raster) so the section reads substantiated, not sparse */}
|
|
<Reveal as="ul" className="proof__logos" stagger={0.06} delay={120}>
|
|
{TRUST_MARKS.map((m) => (
|
|
<RevealItem as="li" className="proof__logo" key={m.label}>
|
|
<span className="proof__logo-svg" aria-hidden="true">
|
|
{m.svg}
|
|
</span>
|
|
<span className="sr-only">{m.label}</span>
|
|
</RevealItem>
|
|
))}
|
|
</Reveal>
|
|
</div>
|
|
</section>
|
|
|
|
<SectionDivider label="What we do" />
|
|
|
|
{/* ===== SERVICES — interactive ledger ===== */}
|
|
<section id="services" className="services frame" aria-labelledby="svc-h">
|
|
<div className="wrap">
|
|
<header className="sec-head">
|
|
<p className="kicker">
|
|
<span className="kicker__dot" />
|
|
Services / 06
|
|
</p>
|
|
<Reveal as="h2" variant="clip">
|
|
<span id="svc-h" className="display sec-head__title">
|
|
How we grow your business
|
|
</span>
|
|
</Reveal>
|
|
</header>
|
|
|
|
<Reveal as="ol" className="ledger" stagger={0.07}>
|
|
{services.map((s, i) => (
|
|
<RevealItem as="li" key={s.id}>
|
|
<a href={SITE.booking} className="ledger__row" data-cursor="Scope it">
|
|
<span className="ledger__no">
|
|
{String(i + 1).padStart(2, "0")}
|
|
</span>
|
|
<h3 className="ledger__name display">{s.name}</h3>
|
|
<p className="ledger__desc">{s.desc}</p>
|
|
<span className="ledger__arrow" aria-hidden="true">↗</span>
|
|
</a>
|
|
</RevealItem>
|
|
))}
|
|
</Reveal>
|
|
</div>
|
|
</section>
|
|
|
|
{/* ===== METRICS scoreboard (animated SVG bars + count-ups) ===== */}
|
|
<Scoreboard />
|
|
|
|
{/* ===== CASE STUDIES — 3D tilt + coded charts ===== */}
|
|
<section id="work" className="work frame" aria-labelledby="work-h">
|
|
<div className="wrap">
|
|
<header className="sec-head">
|
|
<p className="kicker">
|
|
<span className="kicker__dot" />
|
|
Selected work — sample
|
|
</p>
|
|
<Reveal as="h2" variant="clip">
|
|
<span id="work-h" className="display sec-head__title">
|
|
Proof, not promises
|
|
</span>
|
|
</Reveal>
|
|
</header>
|
|
|
|
<div className="work__grid">
|
|
{cases.map((c, i) => (
|
|
<CaseCard key={c.tag} data={c as unknown as CaseData} index={i} />
|
|
))}
|
|
</div>
|
|
|
|
<div className="work__cta">
|
|
<Magnetic strength={0.3}>
|
|
<a href={SITE.booking} className="btn btn--ghost" data-cursor="See more">
|
|
View all work <span className="arrow" aria-hidden="true">→</span>
|
|
</a>
|
|
</Magnetic>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
{/* ===== PROCESS — pinned scroll + morphing SVG ===== */}
|
|
<ProcessLoop />
|
|
|
|
{/* ===== TESTIMONIALS ===== */}
|
|
<section className="quotes frame" aria-label="What clients say">
|
|
<div className="wrap">
|
|
<header className="sec-head">
|
|
<p className="kicker">
|
|
<span className="kicker__dot" />
|
|
In their words — sample
|
|
</p>
|
|
<Reveal as="h2" variant="clip">
|
|
<span className="display sec-head__title">
|
|
The number is the point
|
|
</span>
|
|
</Reveal>
|
|
</header>
|
|
</div>
|
|
<div className="wrap quotes__grid">
|
|
{testimonials.map((t, i) => (
|
|
<Reveal as="figure" className="quote" key={i} delay={i * 120}>
|
|
<span className="quote__mark display" aria-hidden="true">“</span>
|
|
<blockquote className="quote__text display">{t.quote}</blockquote>
|
|
<figcaption className="quote__by">
|
|
<span className="quote__rule" aria-hidden="true" />
|
|
{t.by}
|
|
</figcaption>
|
|
</Reveal>
|
|
))}
|
|
</div>
|
|
<div className="wrap partners">
|
|
<p className="kicker">Partners</p>
|
|
<ul className="partners__list">
|
|
<li>Google Partner</li>
|
|
<li>Meta Business Partner</li>
|
|
</ul>
|
|
</div>
|
|
</section>
|
|
|
|
{/* ===== FAQ ===== */}
|
|
<section id="faq" data-invert className="faq-sec frame" aria-labelledby="faq-h">
|
|
<div className="wrap faq-sec__wrap">
|
|
<header className="sec-head">
|
|
<p className="kicker">
|
|
<span className="kicker__dot" />
|
|
FAQ
|
|
</p>
|
|
<Reveal as="h2" variant="clip">
|
|
<span id="faq-h" className="display sec-head__title">
|
|
Questions about working with a digital marketing agency
|
|
</span>
|
|
</Reveal>
|
|
</header>
|
|
<Faq />
|
|
</div>
|
|
</section>
|
|
|
|
{/* ===== FINAL CTA ===== */}
|
|
<section className="final frame" aria-labelledby="final-h">
|
|
<div className="wrap final__wrap">
|
|
<p className="kicker">
|
|
<span className="kicker__dot" />
|
|
The bottom line
|
|
</p>
|
|
<Reveal as="header">
|
|
<h2 id="final-h" className="display final__h">
|
|
Ready to <span className="grad">grow?</span>
|
|
</h2>
|
|
</Reveal>
|
|
<p className="final__sub">
|
|
No long contracts. No vanity reports. Marketing you can measure in
|
|
sales.
|
|
</p>
|
|
<div className="final__cta">
|
|
<Magnetic strength={0.4}>
|
|
<Link href={SITE.booking} className="btn btn--accent" data-cursor="Book a call">
|
|
Book a call
|
|
</Link>
|
|
</Magnetic>
|
|
<a href={`mailto:${SITE.email}`} className="btn btn--ghost">
|
|
or {SITE.email}
|
|
</a>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
</main>
|
|
|
|
{/* ===== FOOTER ===== */}
|
|
<footer data-invert className="colophon frame" aria-label="Footer">
|
|
<div className="wrap">
|
|
<div className="colophon__top">
|
|
<div className="colophon__brand">
|
|
<span className="brand__mark" aria-hidden="true">
|
|
<span className="brand__dot" />
|
|
</span>
|
|
<p className="colophon__line">
|
|
{SITE.name}. {SITE.tagline}
|
|
</p>
|
|
</div>
|
|
<nav className="colophon__nav" aria-label="Footer">
|
|
<ul>
|
|
<li><a href="#services">Services</a></li>
|
|
<li><a href="#work">Work</a></li>
|
|
<li><a href="#process">About</a></li>
|
|
<li><a href="#faq">FAQ</a></li>
|
|
<li><a href={`mailto:${SITE.email}`}>Contact</a></li>
|
|
</ul>
|
|
<ul>
|
|
<li><a href="https://www.linkedin.com" rel="noopener">LinkedIn</a></li>
|
|
<li><a href={SITE.booking}>Book a call</a></li>
|
|
<li><a href="#main">Privacy</a></li>
|
|
<li><a href="#main">Terms</a></li>
|
|
</ul>
|
|
</nav>
|
|
</div>
|
|
<div className="rule" />
|
|
<div className="colophon__bottom">
|
|
<p>© 2026 {SITE.name}. All rights reserved.</p>
|
|
<p className="colophon__note">
|
|
Metrics and case studies shown are illustrative samples.
|
|
</p>
|
|
</div>
|
|
</div>
|
|
</footer>
|
|
</>
|
|
);
|
|
}
|