An interactive demonstration of modern layout structures. Explore different header grids, photo grids, card lists, and testimonial sections.
Marketing Templates Laboratory
Select an industry domain and a layout style. Explore custom scrolling reveals, type hierarchies, and Emotion-styled layouts.
CrewOS brings your CRM, invoicing, scheduling, and job tracking into one platform built for contractors and small service businesses — so you spend less time on admin and more time doing the work.
We spent eight years running an electrical crew before we wrote a single line of code.
Every contractor we know runs their business across at least four different tools. A spreadsheet for customers. A notes app for jobs. Email for estimates. QuickBooks for invoices. And somehow they're all out of sync.
We missed a $22,000 job because a follow-up fell through the cracks — lost in a thread of unread emails. That was the moment we started building CrewOS. Not as a side project. As a lifeline.
CrewOS is one place for your entire operation. Leads come in, turn into estimates, estimates become jobs, jobs become invoices, invoices become cash in your account. Every step connected. Nothing falls through.
Keep every customer, lead, and job in one place. Track communication history, set follow-up reminders, and never let a prospect fall through the cracks again.
Generate professional invoices directly from completed jobs. Accept card payments, ACH, and financing. Get paid in hours, not weeks.
Drag-and-drop scheduling that accounts for crew availability, travel time, and job duration. Everyone on your team knows exactly where to be and when.
Build and send estimates from the field in minutes. Add line items, photos, and optional add-ons. Customers sign off electronically — no printing, no faxing.
Know exactly where every job stands in real time. Technicians check in and out from their phones, updating job status automatically so the office is always in sync.
Give customers a branded portal to view their estimates, approve work, pay invoices, and track scheduled visits. Fewer phone calls, happier clients.
Before CrewOS, I was juggling a spreadsheet, a notes app, and QuickBooks and still missing follow-ups. Now everything lives in one place. I brought in four new clients last month just from the CRM reminders alone.
The invoicing alone paid for itself in the first week. I used to wait 45 days to get paid. Now it's usually same day. My cash flow has completely changed.
I have a crew of nine people across three trucks. Scheduling was a nightmare. CrewOS scheduling is the first tool that actually maps to how we work in the field — not how some software company thinks we work.
The client portal is something I didn't know I needed. My customers love being able to see their upcoming appointments and pay online. Complaints about missed invoices dropped to zero.
Former electrician turned software entrepreneur. Built CrewOS after spending 8 years managing a 12-person crew with spreadsheets and Post-it notes.
Ex-Salesforce engineer obsessed with making enterprise-grade software feel simple. Believes field service businesses deserve the same tools Fortune 500 companies use.
Product veteran from Jobber and ServiceTitan. Spent two years riding along with HVAC techs and plumbers to understand how real crews operate before writing a single line of code.
Worked in her family's landscaping business for a decade. Leads a support team that responds in under 2 hours — because she knows downtime means lost revenue.
Join thousands of contractors who replaced their spreadsheets with CrewOS. 14-day free trial. No credit card required.
Start free for 14 daysImplementation Source Code (saas/Variant1_EditorialLongform.tsx)
Variant1_EditorialLongform.tsx (Marketing Template Source)
/** @jsxImportSource @emotion/react */
import { useEffect, useState } from "react";
import { css } from "@emotion/react";
import {
HiOutlineUsers,
HiOutlineDocumentText,
HiOutlineCalendar,
HiOutlineClipboardDocumentList,
HiOutlineMapPin,
HiOutlineComputerDesktop,
HiOutlineStar,
HiOutlineArrowRight,
HiOutlineCheckCircle,
} from "react-icons/hi2";
import type { MarketingTemplateProps } from "../types";
import { RevealSection } from "../shared/RevealSection";
import {
fadeInUp,
fadeInLeft,
fadeInRight,
fadeIn,
fadeInDown,
revealStyle,
hiddenStyle,
} from "../shared/animations";
import { useScrollReveal } from "../shared/useScrollReveal";
// Color palette
const C = {
navy: "#1B2A4A",
navyLight: "#243558",
gold: "#D4A853",
goldLight: "#E8C47A",
goldPale: "#F7EDD5",
cream: "#FAF8F5",
creamDark: "#F2EDE4",
charcoal: "#2C2C2C",
muted: "#6B6456",
border: "#E4DDD0",
white: "#FFFFFF",
};
const iconMap: Record<string, React.ComponentType<{ size?: number; color?: string }>> = {
HiOutlineUsers,
HiOutlineDocumentText,
HiOutlineCalendar,
HiOutlineClipboardDocumentList,
HiOutlineMapPin,
HiOutlineComputerDesktop,
};
// ─── Hero ───────────────────────────────────────────────────────────────────
function HeroSection({ hero, companyName }: Pick<MarketingTemplateProps, "hero" | "companyName">) {
const [visible, setVisible] = useState(false);
useEffect(() => {
const t = setTimeout(() => setVisible(true), 80);
return () => clearTimeout(t);
}, []);
const words = hero.headline.split(" ");
const boldWords = new Set([0, 2, 5, 6]);
return (
<section
css={css`
background: ${C.cream};
padding: 7rem 0 5rem;
overflow: hidden;
position: relative;
@media (max-width: 768px) {
padding: 4rem 0 3rem;
}
`}
>
{/* Decorative gold bar */}
<div
css={css`
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 4px;
background: linear-gradient(90deg, ${C.gold} 0%, ${C.goldLight} 60%, transparent 100%);
`}
/>
<div
css={css`
max-width: 1100px;
margin: 0 auto;
padding: 0 2rem;
display: grid;
grid-template-columns: 3fr 2fr;
gap: 5rem;
align-items: center;
@media (max-width: 900px) {
grid-template-columns: 1fr;
gap: 3rem;
}
`}
>
{/* Left: headline + CTA */}
<div>
<div
css={css`
display: inline-block;
font-size: 0.72rem;
font-weight: 700;
letter-spacing: 0.18em;
text-transform: uppercase;
color: ${C.gold};
border-bottom: 2px solid ${C.gold};
padding-bottom: 2px;
margin-bottom: 2rem;
${visible ? revealStyle(fadeInDown, "0.6s", "0s") : hiddenStyle}
`}
>
{companyName}
</div>
<h1
css={css`
font-size: clamp(2.6rem, 5vw, 4.2rem);
line-height: 1.1;
color: ${C.navy};
margin: 0 0 2rem;
${visible ? revealStyle(fadeInUp, "0.8s", "0.1s") : hiddenStyle}
`}
>
{words.map((word, i) => (
<span
key={i}
css={css`
font-weight: ${boldWords.has(i) ? "800" : "300"};
font-style: ${i === 4 ? "italic" : "normal"};
`}
>
{word}
{i < words.length - 1 ? " " : ""}
</span>
))}
</h1>
<p
css={css`
font-size: 1.15rem;
line-height: 1.75;
color: ${C.muted};
max-width: 540px;
margin: 0 0 2.5rem;
${visible ? revealStyle(fadeInUp, "0.8s", "0.2s") : hiddenStyle}
`}
>
{hero.subheadline}
</p>
<div
css={css`
display: flex;
gap: 1rem;
flex-wrap: wrap;
${visible ? revealStyle(fadeInUp, "0.8s", "0.3s") : hiddenStyle}
`}
>
<a
href="#pricing"
css={css`
display: inline-flex;
align-items: center;
gap: 0.5rem;
background: ${C.navy};
color: ${C.white};
padding: 0.875rem 2rem;
font-size: 0.95rem;
font-weight: 600;
text-decoration: none;
letter-spacing: 0.02em;
transition: background 0.2s;
&:hover {
background: ${C.navyLight};
}
`}
>
{hero.ctaText}
<HiOutlineArrowRight size={16} />
</a>
{hero.ctaSecondaryText && (
<a
href="#features"
css={css`
display: inline-flex;
align-items: center;
gap: 0.5rem;
color: ${C.navy};
padding: 0.875rem 1.5rem;
font-size: 0.95rem;
font-weight: 500;
text-decoration: none;
border-bottom: 2px solid ${C.border};
transition: border-color 0.2s;
&:hover {
border-color: ${C.gold};
}
`}
>
{hero.ctaSecondaryText}
</a>
)}
</div>
</div>
{/* Right: editorial accent block */}
<div
css={css`
${visible ? revealStyle(fadeInRight, "0.9s", "0.25s") : hiddenStyle}
@media (max-width: 900px) {
display: none;
}
`}
>
<div
css={css`
background: ${C.navy};
padding: 2.5rem;
position: relative;
&::before {
content: "";
position: absolute;
top: 12px;
left: 12px;
right: -12px;
bottom: -12px;
border: 2px solid ${C.gold};
z-index: -1;
}
`}
>
<div
css={css`
font-size: 0.7rem;
letter-spacing: 0.2em;
text-transform: uppercase;
color: ${C.gold};
margin-bottom: 1.5rem;
`}
>
Built by contractors, for contractors
</div>
{[
"Average 4.2 hrs saved per week",
"Payments collected 3x faster",
"90% fewer missed follow-ups",
"14-day free trial, no card required",
].map((stat, i) => (
<div
key={i}
css={css`
display: flex;
align-items: flex-start;
gap: 0.75rem;
margin-bottom: 1rem;
&:last-child {
margin-bottom: 0;
}
`}
>
<HiOutlineCheckCircle
size={18}
color={C.gold}
style={{ flexShrink: 0, marginTop: 2 }}
/>
<span
css={css`
color: #c8d0de;
font-size: 0.93rem;
line-height: 1.5;
`}
>
{stat}
</span>
</div>
))}
</div>
</div>
</div>
</section>
);
}
// ─── Intro Narrative ────────────────────────────────────────────────────────
function NarrativeSection() {
return (
<section
css={css`
background: ${C.white};
padding: 6rem 0;
`}
>
<div
css={css`
max-width: 1100px;
margin: 0 auto;
padding: 0 2rem;
display: grid;
grid-template-columns: 2fr 3fr;
gap: 6rem;
align-items: start;
@media (max-width: 900px) {
grid-template-columns: 1fr;
gap: 2.5rem;
}
`}
>
<RevealSection animation={fadeInLeft}>
<div
css={css`
position: sticky;
top: 5rem;
`}
>
<div
css={css`
width: 3px;
height: 56px;
background: ${C.gold};
margin-bottom: 1.5rem;
`}
/>
<h2
css={css`
font-size: 2rem;
font-weight: 800;
color: ${C.navy};
line-height: 1.2;
margin: 0 0 1rem;
`}
>
The story behind the software
</h2>
<p
css={css`
font-size: 0.95rem;
color: ${C.muted};
line-height: 1.7;
`}
>
We spent eight years running an electrical crew before we wrote a single line of code.
</p>
</div>
</RevealSection>
<div>
{[
{
label: "The problem",
body: "Every contractor we know runs their business across at least four different tools. A spreadsheet for customers. A notes app for jobs. Email for estimates. QuickBooks for invoices. And somehow they're all out of sync.",
},
{
label: "The turning point",
body: "We missed a $22,000 job because a follow-up fell through the cracks — lost in a thread of unread emails. That was the moment we started building CrewOS. Not as a side project. As a lifeline.",
},
{
label: "What we built",
body: "CrewOS is one place for your entire operation. Leads come in, turn into estimates, estimates become jobs, jobs become invoices, invoices become cash in your account. Every step connected. Nothing falls through.",
},
].map((block, i) => (
<RevealSection key={i} animation={fadeInUp} delay={`${i * 0.12}s`}>
<div
css={css`
margin-bottom: 3rem;
&:last-child {
margin-bottom: 0;
}
`}
>
<div
css={css`
font-size: 0.7rem;
font-weight: 700;
letter-spacing: 0.18em;
text-transform: uppercase;
color: ${C.gold};
margin-bottom: 0.75rem;
`}
>
{block.label}
</div>
<p
css={css`
font-size: 1.1rem;
line-height: 1.8;
color: ${C.charcoal};
margin: 0;
`}
>
{block.body}
</p>
</div>
</RevealSection>
))}
</div>
</div>
</section>
);
}
// ─── Services ───────────────────────────────────────────────────────────────
function ServicesSection({ services }: Pick<MarketingTemplateProps, "services">) {
return (
<section
id="features"
css={css`
background: ${C.creamDark};
padding: 6rem 0;
`}
>
<div
css={css`
max-width: 1100px;
margin: 0 auto;
padding: 0 2rem;
`}
>
<RevealSection animation={fadeInUp}>
<div
css={css`
margin-bottom: 4rem;
`}
>
<div
css={css`
font-size: 0.7rem;
font-weight: 700;
letter-spacing: 0.18em;
text-transform: uppercase;
color: ${C.gold};
margin-bottom: 0.75rem;
`}
>
Everything you need
</div>
<h2
css={css`
font-size: clamp(1.8rem, 3.5vw, 2.8rem);
font-weight: 800;
color: ${C.navy};
max-width: 480px;
line-height: 1.2;
margin: 0;
`}
>
Six tools. One platform. Zero spreadsheets.
</h2>
</div>
</RevealSection>
<div
css={css`
display: flex;
flex-direction: column;
gap: 0;
`}
>
{services.map((service, i) => {
const Icon = iconMap[service.icon] ?? HiOutlineUsers;
const isEven = i % 2 === 0;
return (
<RevealSection
key={service.id}
animation={isEven ? fadeInLeft : fadeInRight}
delay={`${i * 0.05}s`}
>
<div
css={css`
display: grid;
grid-template-columns: ${isEven ? "1fr 2fr" : "2fr 1fr"};
gap: 0;
border-top: 1px solid ${C.border};
padding: 2.5rem 0;
&:last-child {
border-bottom: 1px solid ${C.border};
}
@media (max-width: 768px) {
grid-template-columns: 1fr;
gap: 1rem;
}
`}
>
{isEven ? (
<>
<div
css={css`
display: flex;
align-items: flex-start;
gap: 1rem;
padding-right: 3rem;
@media (max-width: 768px) {
padding-right: 0;
}
`}
>
<div
css={css`
background: ${C.goldPale};
padding: 0.75rem;
flex-shrink: 0;
`}
>
<Icon size={22} color={C.navy} />
</div>
<div>
<div
css={css`
font-size: 0.68rem;
font-weight: 700;
letter-spacing: 0.15em;
text-transform: uppercase;
color: ${C.muted};
margin-bottom: 0.25rem;
`}
>
{String(i + 1).padStart(2, "0")}
</div>
<h3
css={css`
font-size: 1.25rem;
font-weight: 700;
color: ${C.navy};
margin: 0;
`}
>
{service.title}
</h3>
</div>
</div>
<p
css={css`
font-size: 1rem;
line-height: 1.75;
color: ${C.muted};
margin: 0;
padding-left: 1rem;
border-left: 2px solid ${C.border};
@media (max-width: 768px) {
border-left: none;
padding-left: 0;
}
`}
>
{service.description}
</p>
</>
) : (
<>
<p
css={css`
font-size: 1rem;
line-height: 1.75;
color: ${C.muted};
margin: 0;
padding-right: 1rem;
border-right: 2px solid ${C.border};
@media (max-width: 768px) {
border-right: none;
padding-right: 0;
order: 2;
}
`}
>
{service.description}
</p>
<div
css={css`
display: flex;
align-items: flex-start;
gap: 1rem;
padding-left: 3rem;
@media (max-width: 768px) {
padding-left: 0;
order: 1;
}
`}
>
<div
css={css`
background: ${C.goldPale};
padding: 0.75rem;
flex-shrink: 0;
`}
>
<Icon size={22} color={C.navy} />
</div>
<div>
<div
css={css`
font-size: 0.68rem;
font-weight: 700;
letter-spacing: 0.15em;
text-transform: uppercase;
color: ${C.muted};
margin-bottom: 0.25rem;
`}
>
{String(i + 1).padStart(2, "0")}
</div>
<h3
css={css`
font-size: 1.25rem;
font-weight: 700;
color: ${C.navy};
margin: 0;
`}
>
{service.title}
</h3>
</div>
</div>
</>
)}
</div>
</RevealSection>
);
})}
</div>
</div>
</section>
);
}
// ─── Testimonials ────────────────────────────────────────────────────────────
function TestimonialsSection({ testimonials }: Pick<MarketingTemplateProps, "testimonials">) {
return (
<section
css={css`
background: ${C.navy};
padding: 6rem 0;
`}
>
<div
css={css`
max-width: 1100px;
margin: 0 auto;
padding: 0 2rem;
`}
>
<RevealSection animation={fadeInUp}>
<div
css={css`
font-size: 0.7rem;
font-weight: 700;
letter-spacing: 0.18em;
text-transform: uppercase;
color: ${C.gold};
margin-bottom: 3.5rem;
`}
>
From the field
</div>
</RevealSection>
<div
css={css`
display: flex;
flex-direction: column;
gap: 4rem;
`}
>
{testimonials.map((t, i) => (
<RevealSection key={t.id} animation={fadeInUp} delay={`${i * 0.1}s`}>
<div
css={css`
display: grid;
grid-template-columns: ${i % 2 === 0 ? "1fr 3fr" : "3fr 1fr"};
gap: 3rem;
align-items: start;
@media (max-width: 768px) {
grid-template-columns: 1fr;
gap: 1.5rem;
}
`}
>
{i % 2 === 0 ? (
<>
<div
css={css`
@media (max-width: 768px) {
order: 2;
}
`}
>
<div
css={css`
font-size: 1rem;
font-weight: 700;
color: ${C.white};
margin-bottom: 0.25rem;
`}
>
{t.name}
</div>
<div
css={css`
font-size: 0.85rem;
color: #7a8ca3;
margin-bottom: 0.75rem;
`}
>
{t.location}
</div>
<div
css={css`
display: flex;
gap: 3px;
`}
>
{Array.from({ length: t.rating }).map((_, si) => (
<HiOutlineStar key={si} size={14} color={C.gold} />
))}
</div>
</div>
<div
css={css`
position: relative;
@media (max-width: 768px) {
order: 1;
}
`}
>
<div
css={css`
position: absolute;
top: -1.5rem;
left: -0.5rem;
font-size: 6rem;
line-height: 1;
color: ${C.gold};
opacity: 0.25;
font-family: Georgia, serif;
pointer-events: none;
user-select: none;
`}
>
“
</div>
<blockquote
css={css`
font-size: clamp(1.1rem, 2vw, 1.35rem);
line-height: 1.7;
color: #d0dae8;
font-style: italic;
margin: 0;
padding-left: 1rem;
border-left: 3px solid ${C.gold};
`}
>
{t.quote}
</blockquote>
</div>
</>
) : (
<>
<div
css={css`
position: relative;
`}
>
<div
css={css`
position: absolute;
top: -1.5rem;
left: -0.5rem;
font-size: 6rem;
line-height: 1;
color: ${C.gold};
opacity: 0.25;
font-family: Georgia, serif;
pointer-events: none;
user-select: none;
`}
>
“
</div>
<blockquote
css={css`
font-size: clamp(1.1rem, 2vw, 1.35rem);
line-height: 1.7;
color: #d0dae8;
font-style: italic;
margin: 0;
padding-left: 1rem;
border-left: 3px solid ${C.gold};
`}
>
{t.quote}
</blockquote>
</div>
<div
css={css`
text-align: right;
@media (max-width: 768px) {
text-align: left;
}
`}
>
<div
css={css`
font-size: 1rem;
font-weight: 700;
color: ${C.white};
margin-bottom: 0.25rem;
`}
>
{t.name}
</div>
<div
css={css`
font-size: 0.85rem;
color: #7a8ca3;
margin-bottom: 0.75rem;
`}
>
{t.location}
</div>
<div
css={css`
display: flex;
gap: 3px;
justify-content: flex-end;
@media (max-width: 768px) {
justify-content: flex-start;
}
`}
>
{Array.from({ length: t.rating }).map((_, si) => (
<HiOutlineStar key={si} size={14} color={C.gold} />
))}
</div>
</div>
</>
)}
</div>
</RevealSection>
))}
</div>
</div>
</section>
);
}
// ─── Pricing ────────────────────────────────────────────────────────────────
function PricingSection({ pricing }: Pick<MarketingTemplateProps, "pricing">) {
return (
<section
id="pricing"
css={css`
background: ${C.cream};
padding: 6rem 0;
`}
>
<div
css={css`
max-width: 1100px;
margin: 0 auto;
padding: 0 2rem;
`}
>
<RevealSection animation={fadeInUp}>
<div
css={css`
margin-bottom: 4rem;
`}
>
<div
css={css`
font-size: 0.7rem;
font-weight: 700;
letter-spacing: 0.18em;
text-transform: uppercase;
color: ${C.gold};
margin-bottom: 0.75rem;
`}
>
Simple pricing
</div>
<h2
css={css`
font-size: clamp(1.8rem, 3.5vw, 2.8rem);
font-weight: 800;
color: ${C.navy};
line-height: 1.2;
margin: 0;
`}
>
Choose the plan that fits your crew
</h2>
</div>
</RevealSection>
<div
css={css`
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 1.5rem;
align-items: start;
@media (max-width: 900px) {
grid-template-columns: 1fr;
max-width: 440px;
}
`}
>
{pricing.map((tier, i) => (
<RevealSection key={tier.id} animation={fadeInUp} delay={`${i * 0.1}s`}>
<div
css={css`
background: ${tier.highlighted ? C.navy : C.white};
border: ${tier.highlighted ? `2px solid ${C.gold}` : `1px solid ${C.border}`};
padding: 2.5rem;
position: relative;
${tier.highlighted
? `
&::before {
content: "Most Popular";
position: absolute;
top: -1px;
left: 50%;
transform: translateX(-50%) translateY(-50%);
background: ${C.gold};
color: ${C.navy};
font-size: 0.7rem;
font-weight: 700;
letter-spacing: 0.12em;
text-transform: uppercase;
padding: 0.3rem 1rem;
white-space: nowrap;
}
`
: ""}
`}
>
<div
css={css`
font-size: 0.7rem;
font-weight: 700;
letter-spacing: 0.15em;
text-transform: uppercase;
color: ${tier.highlighted ? C.gold : C.muted};
margin-bottom: 1rem;
`}
>
{tier.name}
</div>
<div
css={css`
display: flex;
align-items: baseline;
gap: 0.25rem;
margin-bottom: 0.5rem;
`}
>
<span
css={css`
font-size: 3rem;
font-weight: 800;
color: ${tier.highlighted ? C.white : C.navy};
line-height: 1;
`}
>
{tier.price}
</span>
<span
css={css`
font-size: 0.85rem;
color: ${tier.highlighted ? "#7a8ca3" : C.muted};
`}
>
/{tier.period}
</span>
</div>
<div
css={css`
height: 1px;
background: ${tier.highlighted ? "#2e3f60" : C.border};
margin: 1.5rem 0;
`}
/>
<ul
css={css`
list-style: none;
padding: 0;
margin: 0 0 2rem;
display: flex;
flex-direction: column;
gap: 0.75rem;
`}
>
{tier.features.map((f, fi) => (
<li
key={fi}
css={css`
display: flex;
align-items: flex-start;
gap: 0.6rem;
font-size: 0.9rem;
color: ${tier.highlighted ? "#c8d0de" : C.charcoal};
line-height: 1.5;
`}
>
<HiOutlineCheckCircle
size={16}
color={C.gold}
style={{ flexShrink: 0, marginTop: 2 }}
/>
{f}
</li>
))}
</ul>
<a
href="#"
css={css`
display: block;
text-align: center;
padding: 0.875rem 1.5rem;
font-size: 0.9rem;
font-weight: 600;
letter-spacing: 0.02em;
text-decoration: none;
transition: all 0.2s;
background: ${tier.highlighted ? C.gold : "transparent"};
color: ${tier.highlighted ? C.navy : C.navy};
border: 2px solid ${tier.highlighted ? C.gold : C.navy};
&:hover {
background: ${tier.highlighted ? C.goldLight : C.navy};
color: ${tier.highlighted ? C.navy : C.white};
}
`}
>
{tier.ctaText}
</a>
</div>
</RevealSection>
))}
</div>
</div>
</section>
);
}
// ─── Team ────────────────────────────────────────────────────────────────────
function TeamSection({ team }: Pick<MarketingTemplateProps, "team">) {
const { ref, isVisible } = useScrollReveal(0.1);
return (
<section
css={css`
background: ${C.white};
padding: 6rem 0;
`}
>
<div
css={css`
max-width: 1100px;
margin: 0 auto;
padding: 0 2rem;
`}
>
<RevealSection animation={fadeInUp}>
<div
css={css`
margin-bottom: 4rem;
`}
>
<div
css={css`
font-size: 0.7rem;
font-weight: 700;
letter-spacing: 0.18em;
text-transform: uppercase;
color: ${C.gold};
margin-bottom: 0.75rem;
`}
>
The people behind it
</div>
<h2
css={css`
font-size: clamp(1.8rem, 3.5vw, 2.8rem);
font-weight: 800;
color: ${C.navy};
line-height: 1.2;
margin: 0;
`}
>
We've been in your boots
</h2>
</div>
</RevealSection>
<div
ref={ref}
css={css`
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 2rem;
@media (max-width: 900px) {
grid-template-columns: repeat(2, 1fr);
}
@media (max-width: 500px) {
grid-template-columns: 1fr;
}
`}
>
{team.map((member, i) => (
<div
key={member.id}
css={css`
${isVisible ? revealStyle(fadeInUp, "0.7s", `${i * 0.1}s`) : hiddenStyle}
`}
>
<div
css={css`
width: 100%;
aspect-ratio: 1;
background: ${[C.creamDark, C.goldPale, C.navy, C.creamDark][i % 4]};
margin-bottom: 1.25rem;
position: relative;
overflow: hidden;
`}
>
<div
css={css`
position: absolute;
bottom: 0;
left: 0;
right: 0;
height: 60%;
background: ${[
`linear-gradient(135deg, ${C.border} 0%, ${C.cream} 100%)`,
`linear-gradient(135deg, ${C.gold}33 0%, ${C.goldPale} 100%)`,
`linear-gradient(135deg, ${C.navyLight} 0%, ${C.navy} 100%)`,
`linear-gradient(135deg, ${C.border} 0%, ${C.creamDark} 100%)`,
][i % 4]};
`}
/>
<div
css={css`
position: absolute;
bottom: 1rem;
left: 50%;
transform: translateX(-50%);
width: 52px;
height: 52px;
border-radius: 50%;
background: ${[C.muted, C.gold, "#4a7ba3", C.muted][i % 4]};
display: flex;
align-items: center;
justify-content: center;
font-size: 1.4rem;
font-weight: 700;
color: ${C.white};
`}
>
{member.name
.split(" ")
.map((n) => n[0])
.join("")}
</div>
</div>
<div
css={css`
font-size: 1rem;
font-weight: 700;
color: ${C.navy};
margin-bottom: 0.2rem;
`}
>
{member.name}
</div>
<div
css={css`
font-size: 0.78rem;
font-weight: 600;
letter-spacing: 0.1em;
text-transform: uppercase;
color: ${C.gold};
margin-bottom: 0.75rem;
`}
>
{member.role}
</div>
<p
css={css`
font-size: 0.88rem;
line-height: 1.65;
color: ${C.muted};
margin: 0;
`}
>
{member.bio}
</p>
</div>
))}
</div>
</div>
</section>
);
}
// ─── Footer CTA ─────────────────────────────────────────────────────────────
function FooterCTA({
hero,
companyName,
companyTagline,
}: Pick<MarketingTemplateProps, "hero" | "companyName" | "companyTagline">) {
return (
<section
css={css`
background: ${C.creamDark};
padding: 5rem 0 4rem;
border-top: 1px solid ${C.border};
`}
>
<div
css={css`
max-width: 700px;
margin: 0 auto;
padding: 0 2rem;
text-align: center;
`}
>
<RevealSection animation={fadeInUp}>
<div
css={css`
font-size: 0.7rem;
font-weight: 700;
letter-spacing: 0.18em;
text-transform: uppercase;
color: ${C.gold};
margin-bottom: 1.5rem;
`}
>
{companyName}
</div>
<h2
css={css`
font-size: clamp(1.8rem, 4vw, 3rem);
font-weight: 800;
color: ${C.navy};
line-height: 1.2;
margin: 0 0 1.5rem;
`}
>
{companyTagline}
</h2>
<p
css={css`
font-size: 1.05rem;
color: ${C.muted};
line-height: 1.7;
margin: 0 0 2.5rem;
`}
>
Join thousands of contractors who replaced their spreadsheets with CrewOS. 14-day free
trial. No credit card required.
</p>
<a
href="#"
css={css`
display: inline-flex;
align-items: center;
gap: 0.5rem;
background: ${C.navy};
color: ${C.white};
padding: 1rem 2.5rem;
font-size: 0.95rem;
font-weight: 600;
letter-spacing: 0.02em;
text-decoration: none;
transition: background 0.2s;
&:hover {
background: ${C.navyLight};
}
`}
>
{hero.ctaText}
<HiOutlineArrowRight size={16} />
</a>
</RevealSection>
<RevealSection animation={fadeIn} delay="0.3s">
<div
css={css`
margin-top: 4rem;
padding-top: 2rem;
border-top: 1px solid ${C.border};
display: flex;
justify-content: space-between;
align-items: center;
flex-wrap: wrap;
gap: 1rem;
`}
>
<span
css={css`
font-size: 0.82rem;
color: ${C.muted};
`}
>
© {new Date().getFullYear()} {companyName}. All rights reserved.
</span>
<div
css={css`
display: flex;
gap: 1.5rem;
`}
>
{["Privacy", "Terms", "Support"].map((link) => (
<a
key={link}
href="#"
css={css`
font-size: 0.82rem;
color: ${C.muted};
text-decoration: none;
&:hover {
color: ${C.navy};
}
`}
>
{link}
</a>
))}
</div>
</div>
</RevealSection>
</div>
</section>
);
}
// ─── Root Export ─────────────────────────────────────────────────────────────
export function Variant1_EditorialLongform(props: MarketingTemplateProps) {
return (
<div
css={css`
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif;
background: ${C.cream};
color: ${C.charcoal};
* {
box-sizing: border-box;
}
`}
>
<HeroSection hero={props.hero} companyName={props.companyName} />
<NarrativeSection />
<ServicesSection services={props.services} />
<TestimonialsSection testimonials={props.testimonials} />
<PricingSection pricing={props.pricing} />
<TeamSection team={props.team} />
<FooterCTA
hero={props.hero}
companyName={props.companyName}
companyTagline={props.companyTagline}
/>
</div>
);
}