135 lines
4.0 KiB
JavaScript
135 lines
4.0 KiB
JavaScript
// Crossed-out list — technical terms struck through, ending in "Your AI handles
|
|
// all of it. You just keep building."
|
|
|
|
const CROSSED_TERMS = [
|
|
"Databases",
|
|
"Auth providers",
|
|
"GitHub",
|
|
"Hosting",
|
|
"API keys",
|
|
"Environment variables",
|
|
"Deployment",
|
|
"Backend code",
|
|
"Servers",
|
|
"DNS records",
|
|
"SSL certificates",
|
|
"CORS errors",
|
|
"Webhooks",
|
|
"Build pipelines",
|
|
"package.json",
|
|
"npm install",
|
|
];
|
|
|
|
function CrossedOut() {
|
|
return (
|
|
<section className="section crossed">
|
|
<style>{`
|
|
.crossed { padding-block: clamp(70px, 10vh, 130px); }
|
|
.crossed-head { text-align: center; max-width: 760px; margin: 0 auto 56px; }
|
|
.crossed-title {
|
|
font-size: clamp(36px, 4.8vw, 64px);
|
|
font-weight: 500; letter-spacing: -0.025em; line-height: 1.02;
|
|
text-wrap: balance;
|
|
}
|
|
.crossed-sub {
|
|
margin-top: 18px;
|
|
color: var(--fg-mute);
|
|
font-size: 17px;
|
|
}
|
|
|
|
.crossed-wall {
|
|
display: flex; flex-wrap: wrap; gap: 10px 14px;
|
|
justify-content: center;
|
|
max-width: 880px; margin: 0 auto;
|
|
}
|
|
.crossed-item {
|
|
position: relative;
|
|
font-family: var(--font-mono);
|
|
font-size: clamp(15px, 1.7vw, 22px);
|
|
font-weight: 400;
|
|
color: var(--fg-mute);
|
|
padding: 8px 14px;
|
|
border-radius: 8px;
|
|
background: oklch(0.20 0.009 60 / 0.45);
|
|
border: 1px solid var(--hairline);
|
|
letter-spacing: 0.005em;
|
|
overflow: hidden;
|
|
}
|
|
.crossed-item::after {
|
|
content: "";
|
|
position: absolute;
|
|
left: 8px; right: 8px;
|
|
top: 50%;
|
|
height: 2px;
|
|
transform: translateY(-50%) rotate(-1deg);
|
|
background: var(--accent);
|
|
box-shadow: 0 0 12px var(--accent-glow);
|
|
border-radius: 2px;
|
|
opacity: 0;
|
|
animation: strike 0.6s cubic-bezier(.7,.1,.3,1) forwards;
|
|
animation-delay: var(--delay, 0s);
|
|
}
|
|
.crossed-item .term {
|
|
opacity: 1;
|
|
animation: fade 0.4s ease forwards;
|
|
animation-delay: var(--delay, 0s);
|
|
display: inline-block;
|
|
}
|
|
@keyframes strike {
|
|
from { opacity: 0; transform: translateY(-50%) rotate(-1deg) scaleX(0); transform-origin: left center; }
|
|
to { opacity: 1; transform: translateY(-50%) rotate(-1deg) scaleX(1); transform-origin: left center; }
|
|
}
|
|
@keyframes fade {
|
|
to { opacity: 0.5; }
|
|
}
|
|
|
|
.crossed-closer {
|
|
margin-top: 56px;
|
|
text-align: center;
|
|
font-size: clamp(24px, 3vw, 36px);
|
|
font-weight: 500; letter-spacing: -0.02em;
|
|
line-height: 1.18;
|
|
text-wrap: balance;
|
|
max-width: 760px; margin-inline: auto; margin-top: 56px;
|
|
}
|
|
.crossed-closer .accent { color: var(--accent); }
|
|
.crossed-closer .sep {
|
|
display: block; width: 48px; height: 1px;
|
|
background: var(--hairline);
|
|
margin: 28px auto;
|
|
}
|
|
`}</style>
|
|
|
|
<div className="wrap">
|
|
<div className="crossed-head">
|
|
<Eyebrow>What you don't have to learn</Eyebrow>
|
|
<h2 className="crossed-title" style={{ marginTop: 18 }}>
|
|
All the stuff that made you give up last time.
|
|
</h2>
|
|
<p className="crossed-sub">Forget every word on this list.</p>
|
|
</div>
|
|
|
|
<div className="crossed-wall">
|
|
{CROSSED_TERMS.map((term, i) => (
|
|
<span
|
|
className="crossed-item"
|
|
key={term}
|
|
style={{ "--delay": `${0.12 + i * 0.06}s` }}
|
|
>
|
|
<span className="term">{term}</span>
|
|
</span>
|
|
))}
|
|
</div>
|
|
|
|
<p className="crossed-closer">
|
|
Your AI handles <span className="accent">all of it</span>.
|
|
<span className="sep" />
|
|
You just keep building.
|
|
</p>
|
|
</div>
|
|
</section>
|
|
);
|
|
}
|
|
|
|
Object.assign(window, { CrossedOut });
|