"use client";
import { cn } from "@/lib/utils";
import Image from "next/image";
import { ReactNode, useState } from "react";
interface MarqueeProps {
children: ReactNode;
pauseOnHover?: boolean;
reverse?: boolean;
className?: string;
speed?: number;
}
function Marquee({
children,
pauseOnHover = false,
reverse = false,
className,
speed = 40,
}: MarqueeProps) {
return (
<div
className={cn(
"group flex overflow-hidden [--gap:0rem] [gap:var(--gap)]",
className
)}
style={
{
"--duration": `${speed}s`,
} as React.CSSProperties
}
>
<div
className={cn(
"flex min-w-full shrink-0 items-center justify-around gap-[var(--gap)] animate-marquee",
reverse && "[animation-direction:reverse]",
pauseOnHover && "group-hover:[animation-play-state:paused]"
)}
>
{children}
</div>
<div
className={cn(
"flex min-w-full shrink-0 items-center justify-around gap-[var(--gap)] animate-marquee",
reverse && "[animation-direction:reverse]",
pauseOnHover && "group-hover:[animation-play-state:paused]"
)}
aria-hidden="true"
>
{children}
</div>
</div>
);
}
const images = [
"https://cdn.21st.dev/assets/mirror/ef/ef19c5a8d215cdff456b7874d70e4069e94ee14df318a443f8ed3180599f061c.jpg",
"https://cdn.21st.dev/assets/mirror/8e/8ee3945e4554269971eee8a787ed55945d692528746dee1d7b50fc06fa0ac9d8.jpg",
"https://cdn.21st.dev/assets/mirror/25/25d37caf50d06441e284d190e362da8cde082042e96ac344b19a6cdd73373549.jpg",
"https://cdn.21st.dev/assets/mirror/2c/2cb5e1165c868beee9a565847d062726e33da007a48b8625ec5239e94db10762.jpg",
];
const images2 = [
"https://cdn.21st.dev/assets/mirror/3b/3b3a5167ff73698abe7c7022f286838cc7db30c7c7a18f58308fb72de7391e36.jpg",
"https://cdn.21st.dev/assets/mirror/50/509a3566233260430784a9c049f3430e402ea5c77f70b1fc6eecbfc21b66fb40.jpg",
"https://cdn.21st.dev/assets/mirror/70/7083136ba27f49f979afcba90b12be3cd5abc9e0d694cf6d90326858f1d1a7b2.jpg",
"https://cdn.21st.dev/assets/mirror/b4/b484922b62223291afa76914a5ebd4ca5bfde61f5244ee2a3e18d2b1a655932d.jpg",
];
function ScrambleButton() {
const [displayText, setDisplayText] = useState("Start with one agent");
const [isScrambling, setIsScrambling] = useState(false);
const originalText = "Start with one agent";
const chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!@#$%^&*";
const scramble = () => {
if (isScrambling) return;
setIsScrambling(true);
let iteration = 0;
const maxIterations = originalText.length;
const interval = setInterval(() => {
setDisplayText(() =>
originalText
.split("")
.map((letter, index) => {
if (index < iteration) {
return originalText[index];
}
return chars[Math.floor(Math.random() * chars.length)];
})
.join("")
);
if (iteration >= maxIterations) {
clearInterval(interval);
setIsScrambling(false);
}
iteration += 1 / 3;
}, 30);
};
return (
<button
onMouseEnter={scramble}
className="px-8 py-3 bg-primary text-primary-foreground rounded-full font-semibold hover:bg-primary/90 transition-colors"
>
{displayText}
</button>
);
}
export default function HeroWithMarqueeLarge() {
return (
<div className="min-h-screen bg-background text-foreground flex items-center overflow-hidden relative">
<div className="w-full">
<div className="flex flex-col lg:flex-row items-center lg:gap-4">
{/* Left Content */}
<div className="flex-shrink-0 space-y-6 px-6 lg:px-12 py-12 lg:py-0 lg:max-w-2xl">
<h1 className="text-4xl md:text-5xl lg:text-6xl font-bold leading-tight">
Start small. Ship one working agent.
</h1>
<div className="space-y-1 text-muted-foreground">
<p className="text-lg">Starter: your first agent, narrow scope.</p>
<p className="text-lg">Scope widens after the first workflow passes.</p>
</div>
<ScrambleButton />
</div>
{/* Right Marquee Grid */}
<div className="flex-1 w-full lg:w-auto space-y-0 overflow-hidden">
<Marquee speed={30} reverse className="[--gap:0rem]">
{images.map((src, idx) => (
<div
key={idx}
className="relative w-64 h-64 lg:w-80 lg:h-80 overflow-hidden flex-shrink-0"
>
<Image
src={src}
alt={`Dali Agents showcase ${idx + 1}`}
fill
className="object-cover"
/>
</div>
))}
</Marquee>
<Marquee speed={30} className="[--gap:0rem]">
{images2.map((src, idx) => (
<div
key={idx}
className="relative w-64 h-64 lg:w-80 lg:h-80 overflow-hidden flex-shrink-0"
>
<Image
src={src}
alt={`Dali Agents showcase ${idx + 5}`}
fill
className="object-cover"
/>
</div>
))}
</Marquee>
</div>
</div>
</div>
<a
href="https://daliagents.com"
target="_blank"
rel="noreferrer"
className="absolute bottom-4 left-1/2 -translate-x-1/2 text-[10px] tracking-wide text-muted-foreground/60 transition-colors hover:text-muted-foreground"
>
daliagents.com
</a>
</div>
);
}