Files
vibn-agent-runner/design-templates/VIBN (2)/audience.jsx

191 lines
6.5 KiB
JavaScript

// Who it's for — three audience cards, each with a Reddit-style customer quote
// and Vibn's answer.
const AUDIENCE = [
{
label: "Small business owners",
icon: "shop",
headline: "Stop renting. Build the tool that actually fits.",
quote: "I'm paying $312/month for software that does 60% of what I need and zero of the rest.",
source: "u/coffeeshop_owner · r/smallbusiness",
answer: "Replace the whole stack with one tool that matches your workflow — bookings, customers, invoicing, all in one place. Owned by you.",
},
{
label: "Freelancers & local builders",
icon: "spark",
headline: "Become the craftsman who builds for businesses in your town.",
quote: "My client wants a quote tool. I can mock the frontend in a day. The backend? Two weeks I don't have.",
source: "u/agency_of_one · r/freelance",
answer: "Deliver the whole thing — login, data, hosting, polish — in the same chat where you built the screens. Bill for the system, not the hours.",
},
{
label: "Quiet entrepreneurs",
icon: "spark2",
headline: "Build a business without ever picking up the phone.",
quote: "I want to build my thing, ship my thing, and find my customers — without doing sales calls or talking to a developer.",
source: "u/asynchronous_human · r/indiehackers",
answer: "No deploys. No GitHub. No cold outreach. The thing you described is online, with logins, marketing on autopilot — ready for the right people to find it.",
},
];
function Audience() {
return (
<section className="section audience">
<style>{`
.audience-head { text-align: center; max-width: 820px; margin: 0 auto 56px; }
.audience-title {
font-size: clamp(36px, 4.8vw, 64px);
font-weight: 500; letter-spacing: -0.025em; line-height: 1.02;
text-wrap: balance;
}
.audience-sub {
margin-top: 20px;
color: var(--fg-mute);
font-size: 17px;
}
.audience-grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 18px;
}
@media (max-width: 1000px) { .audience-grid { grid-template-columns: 1fr; } }
.a-card {
position: relative;
padding: 28px 26px 26px;
border-radius: 18px;
background: linear-gradient(180deg, oklch(0.20 0.009 60 / 0.55), oklch(0.17 0.008 60 / 0.55));
border: 1px solid var(--hairline);
display: flex; flex-direction: column;
min-height: 380px;
overflow: hidden;
}
.a-card::after {
content: "";
position: absolute;
top: 0; left: 24px; right: 24px;
height: 1px;
background: linear-gradient(90deg, transparent, var(--accent), transparent);
opacity: .6;
}
.a-icon {
width: 40px; height: 40px;
border-radius: 10px;
display: grid; place-items: center;
background: oklch(0.22 0.011 60);
border: 1px solid var(--hairline);
color: var(--accent);
margin-bottom: 18px;
}
.a-label {
font-size: 19px; font-weight: 500;
letter-spacing: -0.015em;
color: var(--fg);
}
.a-headline {
margin: 8px 0 0;
color: var(--accent);
font-size: 15px;
line-height: 1.4;
letter-spacing: -0.005em;
font-weight: 500;
text-wrap: balance;
}
.a-quote {
margin: 18px 0 0;
padding: 16px 18px;
background: oklch(0.16 0.008 60 / 0.55);
border-left: 2px solid var(--accent);
border-radius: 4px 10px 10px 4px;
font-style: italic;
color: var(--fg-dim);
font-size: 14.5px;
line-height: 1.5;
position: relative;
}
.a-source {
margin-top: 8px;
font-family: var(--font-mono);
font-size: 11px;
color: var(--fg-faint);
letter-spacing: 0.02em;
}
.a-answer {
margin-top: auto;
padding-top: 22px;
font-size: 15px;
color: var(--fg);
line-height: 1.5;
display: flex; gap: 10px; align-items: flex-start;
}
.a-answer .label {
font-family: var(--font-mono);
font-size: 10px;
letter-spacing: 0.12em;
text-transform: uppercase;
color: var(--accent);
padding: 3px 7px;
background: oklch(0.74 0.175 35 / 0.12);
border: 1px solid oklch(0.74 0.175 35 / 0.4);
border-radius: 4px;
margin-top: 1px;
flex-shrink: 0;
}
`}</style>
<div className="wrap">
<div className="audience-head">
<Eyebrow>Who Vibn is for</Eyebrow>
<h2 className="audience-title" style={{ marginTop: 18 }}>
People who have an idea not a stack.
</h2>
<p className="audience-sub">
Three people who feel the same thing different ways to fix it.
</p>
</div>
<div className="audience-grid">
{AUDIENCE.map((a) => (
<div className="a-card" key={a.label}>
<div className="a-icon"><AudienceIcon name={a.icon} /></div>
<div className="a-label">{a.label}</div>
<p className="a-headline">{a.headline}</p>
<div className="a-quote">
"{a.quote}"
<div className="a-source"> {a.source}</div>
</div>
<div className="a-answer">
<span className="label">Vibn</span>
<span>{a.answer}</span>
</div>
</div>
))}
</div>
</div>
</section>
);
}
function AudienceIcon({ name }) {
const p = { width: 20, height: 20, viewBox: "0 0 20 20", fill: "none",
stroke: "currentColor", strokeWidth: 1.5, strokeLinecap: "round", strokeLinejoin: "round" };
if (name === "shop") return (
<svg {...p}><path d="M3.5 6.5h13l-1 9.5h-11l-1-9.5Z"/><path d="M7 6.5V5a3 3 0 0 1 6 0v1.5"/></svg>
);
if (name === "spark") return (
<svg {...p}><path d="M10 3v4M10 13v4M3 10h4M13 10h4M5.3 5.3l2.8 2.8M11.9 11.9l2.8 2.8M14.7 5.3l-2.8 2.8M8.1 11.9l-2.8 2.8"/></svg>
);
if (name === "spark2") return (
<svg {...p}><path d="M10 2.5v3M10 14.5v3M2.5 10h3M14.5 10h3"/><circle cx="10" cy="10" r="3"/></svg>
);
return null;
}
Object.assign(window, { Audience });