Files

344 lines
12 KiB
JavaScript

// Replace your stack — visualizes the SMB's fractured subscription landscape
// collapsing into one tool. Eight grayscale "rented" tiles + spaghetti
// connections, an arrow, then one bright "owned" tile.
const STACK_TOOLS = [
{ name: "Booking", price: "$29/mo", glyph: "B" },
{ name: "POS", price: "$79/mo", glyph: "P" },
{ name: "CRM", price: "$45/mo", glyph: "C" },
{ name: "Accounting", price: "$30/mo", glyph: "A" },
{ name: "Inventory", price: "$59/mo", glyph: "I" },
{ name: "Email", price: "$19/mo", glyph: "E" },
{ name: "Loyalty", price: "$25/mo", glyph: "L" },
{ name: "+ spreadsheet", price: "the one you trust", glyph: "+" },
];
function Stack() {
return (
<section className="section stack">
<style>{`
.stack { padding-block: clamp(80px, 11vh, 130px); }
.stack-head { text-align: center; max-width: 820px; margin: 0 auto 56px; }
.stack-title {
font-size: clamp(36px, 4.8vw, 64px);
font-weight: 500; letter-spacing: -0.025em; line-height: 1.02;
text-wrap: balance;
}
.stack-title .accent { color: var(--accent); }
.stack-sub {
margin-top: 20px;
color: var(--fg-mute); font-size: 17px;
line-height: 1.5;
text-wrap: balance;
max-width: 640px; margin-inline: auto;
}
.stack-stage {
display: grid;
grid-template-columns: 1fr auto 1fr;
gap: clamp(20px, 4vw, 56px);
align-items: center;
max-width: 1080px; margin: 0 auto;
}
@media (max-width: 880px) {
.stack-stage { grid-template-columns: 1fr; }
}
/* Left side: 8 rented tiles */
.rented-wrap { position: relative; }
.rented-label, .owned-label {
font-family: var(--font-mono);
font-size: 11px;
letter-spacing: 0.12em;
text-transform: uppercase;
color: var(--fg-faint);
margin-bottom: 16px;
display: flex; align-items: center; gap: 10px;
}
.owned-label { color: var(--accent); }
.rented-label::after, .owned-label::after {
content: ""; flex: 1; height: 1px;
background: var(--hairline);
}
.rented-grid {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 8px;
position: relative;
}
@media (max-width: 540px) {
.rented-grid { grid-template-columns: repeat(2, 1fr); }
}
.tool-tile {
position: relative;
padding: 14px 12px 12px;
background: oklch(0.18 0.006 60 / 0.7);
border: 1px solid var(--hairline);
border-radius: 10px;
filter: grayscale(1);
opacity: 0.85;
transition: opacity .3s;
}
.tool-tile:hover { opacity: 1; }
.tool-glyph {
width: 22px; height: 22px;
border-radius: 6px;
background: oklch(0.30 0.008 60);
color: var(--fg-mute);
font-family: var(--font-mono);
font-weight: 600;
font-size: 12px;
display: grid; place-items: center;
margin-bottom: 8px;
}
.tool-name {
font-size: 13px;
color: var(--fg-dim);
font-weight: 500;
letter-spacing: -0.01em;
}
.tool-price {
margin-top: 2px;
font-family: var(--font-mono);
font-size: 10.5px;
color: var(--fg-faint);
letter-spacing: 0.02em;
}
/* The chaos: faint connecting lines between tiles */
.rented-grid::before {
content: "";
position: absolute;
inset: -4px;
background:
radial-gradient(circle at 22% 28%, oklch(0.50 0.05 35 / 0.18), transparent 24%),
radial-gradient(circle at 78% 72%, oklch(0.50 0.05 60 / 0.15), transparent 26%);
pointer-events: none;
z-index: 0;
}
.rented-grid > .tool-tile { z-index: 1; }
/* Spaghetti lines SVG overlay */
.rented-spaghetti {
position: absolute;
inset: 0;
pointer-events: none;
z-index: 0;
}
.rented-spaghetti path {
fill: none;
stroke: oklch(0.45 0.04 35 / 0.4);
stroke-width: 1;
stroke-dasharray: 3 4;
}
/* Rented total at bottom */
.rented-total {
margin-top: 14px;
display: flex; justify-content: space-between; align-items: baseline;
padding: 10px 14px;
background: oklch(0.16 0.008 60 / 0.5);
border: 1px dashed var(--hairline);
border-radius: 8px;
font-family: var(--font-mono);
font-size: 12px;
color: var(--fg-mute);
letter-spacing: 0.02em;
}
.rented-total b {
color: var(--fg-dim);
font-weight: 500;
font-size: 15px;
}
/* Middle arrow */
.stack-arrow {
display: flex; flex-direction: column;
align-items: center; justify-content: center;
color: var(--accent);
gap: 6px;
}
.stack-arrow svg {
filter: drop-shadow(0 0 12px var(--accent-glow));
}
.stack-arrow-label {
font-family: var(--font-mono);
font-size: 10px;
letter-spacing: 0.14em;
text-transform: uppercase;
color: var(--accent);
}
@media (max-width: 880px) {
.stack-arrow { padding: 16px 0; transform: rotate(90deg); }
}
/* Right side: one tile */
.owned-tile {
position: relative;
padding: 28px 26px 26px;
background: linear-gradient(180deg, oklch(0.22 0.012 60 / 0.95), oklch(0.18 0.008 60 / 0.95));
border: 1px solid oklch(0.74 0.175 35 / 0.55);
border-radius: 18px;
box-shadow:
0 0 60px -10px var(--accent-glow),
0 30px 80px -20px oklch(0 0 0 / 0.6),
inset 0 1px 0 oklch(0.84 0.16 35 / 0.18);
overflow: hidden;
}
.owned-tile::before {
/* Top accent hairline */
content: "";
position: absolute; top: 0; left: 0; right: 0; height: 1px;
background: linear-gradient(90deg, transparent, var(--accent), transparent);
opacity: .9;
}
.owned-glyph {
width: 44px; height: 44px;
border-radius: 12px;
background: linear-gradient(135deg, var(--accent), oklch(0.65 0.20 18));
color: var(--accent-fg);
display: grid; place-items: center;
margin-bottom: 16px;
box-shadow: 0 0 24px var(--accent-glow), inset 0 1px 0 oklch(1 0 0 / 0.25);
}
.owned-glyph svg { display: block; }
.owned-title {
font-size: 22px; font-weight: 500;
letter-spacing: -0.018em;
color: var(--fg);
}
.owned-sub {
margin-top: 4px;
font-family: var(--font-mono);
font-size: 12px;
color: var(--accent);
letter-spacing: 0.04em;
}
.owned-features {
list-style: none; padding: 0; margin: 18px 0 0;
display: flex; flex-direction: column; gap: 6px;
font-size: 13.5px;
color: var(--fg-dim);
}
.owned-features li {
display: flex; align-items: center; gap: 8px;
}
.owned-features li::before {
content: "✓";
color: var(--ok);
font-family: var(--font-mono);
font-weight: 600;
font-size: 12px;
width: 16px; flex-shrink: 0;
}
.owned-foot {
margin-top: 20px;
padding-top: 16px;
border-top: 1px solid var(--hairline);
display: flex; justify-content: space-between; align-items: baseline;
font-family: var(--font-mono);
font-size: 11.5px;
color: var(--fg-mute);
letter-spacing: 0.02em;
}
.owned-foot b {
color: var(--accent);
font-weight: 500;
font-size: 14px;
}
.stack-foot {
margin-top: 48px;
text-align: center;
font-size: 17px;
color: var(--fg-dim);
text-wrap: balance;
max-width: 720px; margin-inline: auto;
}
.stack-foot b { color: var(--fg); font-weight: 500; }
`}</style>
<div className="wrap">
<div className="stack-head">
<Eyebrow>Replace your stack</Eyebrow>
<h2 className="stack-title" style={{ marginTop: 18 }}>
You're running your business on <span className="accent">eight tools</span>
<br/>that don't fit.
</h2>
<p className="stack-sub">
A booking app over here. Invoicing over there. A separate CRM.
A POS that doesn't quite know about either. An accounting add-on, a scheduler,
a loyalty platform, plus the spreadsheet you actually trust.
</p>
</div>
<div className="stack-stage">
{/* Left: rented mess */}
<div className="rented-wrap">
<div className="rented-label">What you rent today</div>
<div className="rented-grid">
<svg className="rented-spaghetti" viewBox="0 0 200 100" preserveAspectRatio="none" aria-hidden="true">
<path d="M20 25 C 60 60, 120 10, 180 50" />
<path d="M50 15 C 90 70, 130 80, 170 25" />
<path d="M30 75 C 80 30, 140 60, 180 80" />
<path d="M15 50 C 80 80, 120 20, 185 70" />
</svg>
{STACK_TOOLS.map((tool) => (
<div className="tool-tile" key={tool.name}>
<div className="tool-glyph">{tool.glyph}</div>
<div className="tool-name">{tool.name}</div>
<div className="tool-price">{tool.price}</div>
</div>
))}
</div>
<div className="rented-total">
<span>Monthly rent</span>
<b>$286+ / mo</b>
</div>
</div>
{/* Middle: arrow */}
<div className="stack-arrow">
<span className="stack-arrow-label">Replaced by</span>
<svg width="44" height="44" viewBox="0 0 44 44" fill="none" aria-hidden="true">
<path d="M8 22h26M24 12l10 10-10 10" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"/>
</svg>
</div>
{/* Right: owned tile */}
<div className="owned-tile">
<div className="owned-label">What you own with Vibn</div>
<div className="owned-glyph">
<svg viewBox="0 0 36 32" width="60%" height="60%" fill="currentColor" stroke="currentColor" strokeWidth="1.2" strokeLinejoin="round" aria-hidden="true">
<path d="M4 5 L10 5 L12 18 L14 5 L20 5 L12 27 Z" />
<rect x="22.5" y="23" width="9.5" height="3.8" rx="0.7" />
</svg>
</div>
<div className="owned-title">Your business, one tool.</div>
<div className="owned-sub">built for you · owned by you</div>
<ul className="owned-features">
<li>Bookings, customers, invoicing one place</li>
<li>Fits how your business actually runs</li>
<li>No new tools to learn. No homework.</li>
<li>You own the code. You own the data.</li>
</ul>
<div className="owned-foot">
<span>One tool</span>
<b>One price · No rent</b>
</div>
</div>
</div>
<p className="stack-foot">
Eight tools, none of them built for you, none of them talking to each other.
<br/><b>Vibn replaces the whole stack with one tool built for your business, owned by you.</b>
</p>
</div>
</section>
);
}
Object.assign(window, { Stack });