*,
*::before,
*::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
body {
font-family: system-ui, -apple-system, sans-serif;
background: #050910;
color: #f2f6ff;
}
.hero {
height: 100vh;
display: grid;
place-items: center;
place-content: center;
gap: 1rem;
text-align: center;
}
.hero-label {
color: #334155;
font-size: 0.875rem;
letter-spacing: 0.1em;
text-transform: uppercase;
}
.hero-arrow {
font-size: 1.5rem;
color: #334155;
animation: bounce 1.5s ease-in-out infinite;
}
@keyframes bounce {
0%,
100% {
transform: translateY(0);
}
50% {
transform: translateY(8px);
}
}
/* ── Sections ── */
.reveal-section {
min-height: 100vh;
display: grid;
place-items: center;
padding: 4rem 2rem;
}
.reveal-block {
width: min(700px, 100%);
background: rgba(255, 255, 255, 0.03);
border: 1px solid rgba(255, 255, 255, 0.07);
border-radius: 1.5rem;
overflow: hidden;
}
.reveal-inner {
padding: 3rem;
display: flex;
flex-direction: column;
gap: 1rem;
}
.reveal-tag {
font-size: 0.72rem;
font-weight: 700;
letter-spacing: 0.1em;
text-transform: uppercase;
color: #38bdf8;
background: rgba(56, 189, 248, 0.1);
padding: 0.25rem 0.75rem;
border-radius: 999px;
align-self: flex-start;
}
.reveal-inner h2 {
font-size: clamp(2rem, 5vw, 3.5rem);
font-weight: 800;
letter-spacing: -0.03em;
line-height: 1.1;
}
.reveal-inner p {
font-size: 0.9rem;
color: #475569;
line-height: 1.65;
}
/* ── Split variant ── */
.reveal-split {
display: flex;
width: min(700px, 100%);
gap: 2px;
border-radius: 1.5rem;
overflow: hidden;
}
.reveal-half {
flex: 1;
background: rgba(255, 255, 255, 0.03);
border: 1px solid rgba(255, 255, 255, 0.07);
}
.reveal-half .reveal-inner {
padding: 3rem 2rem;
align-items: center;
text-align: center;
}
.reveal-half--left h2 {
color: #38bdf8;
font-size: clamp(2.5rem, 6vw, 5rem);
}
.reveal-half--right h2 {
color: #818cf8;
font-size: clamp(2.5rem, 6vw, 5rem);
}
(function () {
if (!window.gsap || !window.ScrollTrigger) return;
gsap.registerPlugin(ScrollTrigger);
const reduced = window.matchMedia("(prefers-reduced-motion: reduce)").matches;
if (reduced) {
gsap.set(".reveal-block, .reveal-half", { clipPath: "inset(0 0% 0 0)" });
return;
}
// ── Wipe from right → left ──
const leftEl = document.querySelector(".reveal--left");
if (leftEl) {
gsap.fromTo(
leftEl,
{ clipPath: "inset(0 100% 0 0)" },
{
clipPath: "inset(0 0% 0 0)",
ease: "power2.inOut",
scrollTrigger: { trigger: leftEl, start: "top 80%", end: "top 30%", scrub: 1 },
}
);
}
// ── Wipe from bottom → up ──
const bottomEl = document.querySelector(".reveal--bottom");
if (bottomEl) {
gsap.fromTo(
bottomEl,
{ clipPath: "inset(100% 0 0 0)" },
{
clipPath: "inset(0% 0 0 0)",
ease: "power2.inOut",
scrollTrigger: { trigger: bottomEl, start: "top 80%", end: "top 20%", scrub: 1.2 },
}
);
}
// ── Split reveal — both halves from center out ──
const leftHalf = document.querySelector(".reveal-half--left");
const rightHalf = document.querySelector(".reveal-half--right");
if (leftHalf && rightHalf) {
const tl = gsap.timeline({
scrollTrigger: {
trigger: leftHalf.closest(".reveal-split"),
start: "top 75%",
end: "top 25%",
scrub: 1,
},
});
tl.fromTo(
leftHalf,
{ clipPath: "inset(0 100% 0 0)" },
{ clipPath: "inset(0 0% 0 0)", ease: "power2.inOut" },
0
).fromTo(
rightHalf,
{ clipPath: "inset(0 0 0 100%)" },
{ clipPath: "inset(0 0 0 0%)", ease: "power2.inOut" },
0
);
}
// ── Diagonal — polygon from corner ──
const diagEl = document.querySelector(".reveal--diagonal");
if (diagEl) {
gsap.fromTo(
diagEl,
{ clipPath: "polygon(0 0, 0 0, 0 100%, 0 100%)" },
{
clipPath: "polygon(0 0, 100% 0, 100% 100%, 0 100%)",
ease: "power3.inOut",
scrollTrigger: { trigger: diagEl, start: "top 78%", end: "top 20%", scrub: 1.5 },
}
);
}
})();