heroes /
AI Summit Tilted (Diagonal Marquee · Deep Teal)
Teal-palette variant of the AI Summit hero with the dual speaker marquees rotated 45° as a unit. Two columns of uniform 3:4 portraits scroll in opposite directions along the diagonal, creating ribbons of speakers crossing the right half of the section. A subtle horizontal vignette keeps the headline readable over the photos.
Preview
Source
tsx
import { Cpu } from "lucide-react";
interface NavItem {
label: string;
href: string;
}
interface PortraitTile {
src: string;
alt: string;
}
export interface AiSummitTiltedProps {
brand?: string;
navItems?: NavItem[];
registerCta?: { label: string; href: string };
headlinePart1?: string;
headlinePart2?: string;
body?: string;
primaryCta?: { label: string; href: string };
/** Speaker portraits. Uniform 3:4 tiles, split evenly across the two tilted marquee columns. */
portraits?: PortraitTile[];
/** Deep base color. */
bgColor?: string;
/** Bright accent for glow + CTA gradient. */
accentColor?: string;
/** Seconds for one full marquee loop. */
marqueeDurationSec?: number;
/** Tilt of the column pair, in degrees. Default 22. */
tiltDeg?: number;
/** Path to the background video (mp4). Pass null to disable. */
videoSrc?: string | null;
/** Optional poster image shown while the video buffers. */
videoPoster?: string;
}
const DEFAULT_PORTRAITS: PortraitTile[] = [
{
src: "https://images.unsplash.com/photo-1531123897727-8f129e1688ce?w=900&h=1200&fit=crop&crop=faces",
alt: "Speaker portrait with dramatic red and blue lighting on orange backdrop",
},
{
src: "https://images.unsplash.com/photo-1573496359142-b8d87734a5a2?w=900&h=1200&fit=crop&crop=faces",
alt: "Smiling speaker portrait in pink turtleneck against teal backdrop",
},
{
src: "https://images.unsplash.com/photo-1525134479668-1bee5c7c6845?w=900&h=1200&fit=crop&crop=faces",
alt: "Speaker portrait wearing a black cap against orange backdrop",
},
{
src: "https://images.unsplash.com/photo-1488426862026-3ee34a7d66df?w=900&h=1200&fit=crop&crop=faces",
alt: "Speaker portrait in red knit sweater",
},
{
src: "https://images.unsplash.com/photo-1507003211169-0a1dd7228f2d?w=900&h=1200&fit=crop&crop=faces",
alt: "Speaker portrait on teal backdrop",
},
{
src: "https://images.unsplash.com/photo-1544005313-94ddf0286df2?w=900&h=1200&fit=crop&crop=faces",
alt: "Speaker portrait — woman with curly hair",
},
{
src: "https://images.unsplash.com/photo-1500648767791-00dcc994a43e?w=900&h=1200&fit=crop&crop=faces",
alt: "Speaker portrait — bearded man",
},
{
src: "https://images.unsplash.com/photo-1539571696357-5a69c17a67c6?w=900&h=1200&fit=crop&crop=faces",
alt: "Speaker portrait — man in glasses",
},
];
export default function AiSummitTilted({
brand = "AI SUMMIT",
navItems = [
{ label: "Sessions", href: "#sessions" },
{ label: "Speakers", href: "#speakers" },
{ label: "Ticket Options", href: "#tickets" },
{ label: "FAQ", href: "#faq" },
],
registerCta = { label: "Register Your Ticket", href: "#register" },
headlinePart1 = "AI Horizons:",
headlinePart2 = "Shaping the Future of Intelligence",
body = "Join us at AI Tech Summit, the premier global event where industry leaders, innovators, and visionaries converge to explore the transformative power of artificial intelligence.",
primaryCta = { label: "Learn More", href: "#learn-more" },
portraits = DEFAULT_PORTRAITS,
bgColor = "#0A3D44",
accentColor = "#22E5D0",
marqueeDurationSec = 55,
tiltDeg = 22,
videoSrc = "/heroes/ai-summit/hero-video.mp4",
videoPoster,
}: AiSummitTiltedProps) {
const col1 = portraits.filter((_, i) => i % 2 === 0);
const col2 = portraits.filter((_, i) => i % 2 === 1);
// Triple the list so the strip is always much taller than the visible column.
// 3x duplication keeps the loop seamless (any integer >=2 works; 3 gives us
// generous overhang above and below the visible area at every keyframe).
const col1Loop = [...col1, ...col1, ...col1];
const col2Loop = [...col2, ...col2, ...col2];
return (
<section
className="ai-summit-tilted relative isolate h-screen min-h-[760px] overflow-hidden bg-black font-sans text-white"
>
{/* VIDEO BACKGROUND */}
{videoSrc && (
<video
autoPlay
loop
muted
playsInline
preload="auto"
poster={videoPoster}
className="absolute inset-0 z-0 h-full w-full object-cover"
>
<source src={videoSrc} type="video/mp4" />
</video>
)}
{/* GRADIENT OVERLAY — strong dark on the left for headline contrast,
fading lighter toward the right where the photo marquee sits. */}
<div
aria-hidden
className="pointer-events-none absolute inset-0 z-[1]"
style={{
background: `linear-gradient(95deg, rgba(0,0,0,0.88) 0%, rgba(0,0,0,0.78) 28%, rgba(0,0,0,0.55) 52%, rgba(0,0,0,0.35) 78%, rgba(0,0,0,0.45) 100%)`,
}}
/>
{/* Color flavor — subtle accent glows sit above the gradient overlay */}
<div
aria-hidden
className="pointer-events-none absolute -left-32 bottom-0 z-[2] h-[420px] w-[420px] rounded-full opacity-40 blur-3xl"
style={{ background: accentColor }}
/>
<div
aria-hidden
className="pointer-events-none absolute right-1/3 -top-24 z-[2] h-[320px] w-[320px] rounded-full opacity-30 blur-3xl"
style={{ background: "#FFB347" }}
/>
{/* TILTED MARQUEES — wrapper rotated as a unit; section's overflow-hidden clips the corners */}
<div className="pointer-events-none absolute inset-0 z-10 hidden overflow-hidden lg:block">
<div
className="absolute flex items-center justify-center gap-5 will-change-transform"
style={{
width: "120vh",
height: "260vh",
top: "50%",
right: "-15vh",
transform: `translateY(-50%) rotate(${tiltDeg}deg)`,
transformOrigin: "center center",
}}
>
{/* Column 1 — scrolling DOWN (visually toward lower-right after tilt) */}
<div className="relative h-full w-[24vh] overflow-hidden">
<div
className="flex flex-col gap-5 will-change-transform"
style={{
animation: `aiSummitTiltedDown ${marqueeDurationSec}s linear infinite`,
}}
>
{col1Loop.map((p, i) => (
<PortraitFrame key={`c1-${i}`} img={p} />
))}
</div>
</div>
{/* Column 2 — scrolling UP (visually toward upper-left after tilt) */}
<div className="relative h-full w-[24vh] overflow-hidden">
<div
className="flex flex-col gap-5 will-change-transform"
style={{
animation: `aiSummitTiltedUp ${marqueeDurationSec}s linear infinite`,
}}
>
{col2Loop.map((p, i) => (
<PortraitFrame key={`c2-${i}`} img={p} />
))}
</div>
</div>
</div>
</div>
{/* Extra darkening behind the headline so it stays readable
on top of both the video and the tilted photos. */}
<div
aria-hidden
className="pointer-events-none absolute inset-0 z-[15] hidden lg:block"
style={{
background: `linear-gradient(95deg, rgba(0,0,0,0.7) 0%, rgba(0,0,0,0.5) 22%, rgba(0,0,0,0.2) 38%, transparent 50%)`,
}}
/>
{/* FOREGROUND: nav + copy */}
<div className="relative z-20 mx-auto flex h-full max-w-7xl flex-col px-4 sm:px-6 lg:px-8">
{/* GLASS PILL NAV */}
<nav className="mt-6 flex items-center justify-between gap-4 rounded-full border border-white/15 bg-white/10 px-4 py-2 backdrop-blur-md sm:px-5 sm:py-3">
<a href="/" className="flex items-center gap-2 pl-1">
<Cpu className="h-6 w-6" strokeWidth={1.5} />
<span className="text-sm font-semibold tracking-[0.18em] sm:text-base">
{brand}
</span>
</a>
<div className="hidden items-center gap-8 md:flex">
{navItems.map((item) => (
<a
key={item.label}
href={item.href}
className="text-sm font-medium text-white/85 transition-colors hover:text-white"
>
{item.label}
</a>
))}
</div>
<a
href={registerCta.href}
className="rounded-full px-4 py-2 text-xs font-semibold transition-all hover:-translate-y-0.5 sm:px-6 sm:py-2.5 sm:text-sm"
style={{
background: `linear-gradient(135deg, ${accentColor} 0%, #0E8C7E 100%)`,
color: "#062326",
boxShadow: `0 8px 24px ${accentColor}55`,
}}
>
{registerCta.label}
</a>
</nav>
{/* COPY BLOCK */}
<div className="flex flex-1 items-center py-10 lg:py-16">
<div className="max-w-xl lg:max-w-[46%]">
<h1 className="text-[44px] font-bold leading-[1.05] tracking-tight sm:text-5xl lg:text-6xl">
{headlinePart1}
<br />
{headlinePart2}
</h1>
<p className="mt-7 max-w-md text-base leading-relaxed text-white/75">
{body}
</p>
<a
href={primaryCta.href}
className="mt-10 inline-flex items-center rounded-full px-9 py-3.5 text-sm font-semibold transition-all hover:-translate-y-0.5"
style={{
background: `linear-gradient(135deg, ${accentColor} 0%, #0E8C7E 100%)`,
color: "#062326",
boxShadow: `0 12px 32px ${accentColor}66`,
}}
>
{primaryCta.label}
</a>
</div>
</div>
</div>
<style>{`
/* Strips are 3 sublists tall (tripled). Animating between -33.333% and
-66.666% scrolls by one sublist (seamless loop) while keeping the
visible window centered in the strip — so there's always ~1 sublist
of photos extending off the top and off the bottom of the column. */
@keyframes aiSummitTiltedUp {
from { transform: translateY(-33.333%); }
to { transform: translateY(-66.666%); }
}
@keyframes aiSummitTiltedDown {
from { transform: translateY(-66.666%); }
to { transform: translateY(-33.333%); }
}
@media (prefers-reduced-motion: reduce) {
.ai-summit-tilted [style*="aiSummitTiltedUp"],
.ai-summit-tilted [style*="aiSummitTiltedDown"] {
animation: none !important;
}
}
`}</style>
</section>
);
}
function PortraitFrame({ img }: { img: PortraitTile }) {
return (
<div className="relative aspect-[3/4] w-full shrink-0 overflow-hidden rounded-2xl bg-white/5 shadow-lg ring-1 ring-white/10">
<img
src={img.src}
alt={img.alt}
loading="eager"
decoding="async"
className="absolute inset-0 h-full w-full object-cover"
/>
</div>
);
} Claude Code Instructions
CLI Install
npx innovations add ai-summit-tiltedWhere to use it
Use for AI conferences, tech summits, speaker-led events where you want more motion than the standard AI Summit hero. Pairs well with bold/futuristic brand systems.
In Astro:
---
import AiSummitTilted from '../components/innovations/heroes/ai-summit-tilted';
---
<AiSummitTilted />
In Next.js (app/page.tsx):
import AiSummitTilted from '@/components/innovations/heroes/ai-summit-tilted';
No client:* required — server-renderable, no hooks.
CUSTOMIZATION:
<AiSummitTilted
brand="AI SUMMIT"
navItems={[
{ label: "Sessions", href: "#sessions" },
...
]}
registerCta={{ label: "Register Your Ticket", href: "#register" }}
headlinePart1="AI Horizons:"
headlinePart2="Shaping the Future of Intelligence"
body="..."
primaryCta={{ label: "Learn More", href: "#learn-more" }}
portraits={[ { src: "...", alt: "..." }, ... ]}
bgColor="#0A3D44" // deep teal base
accentColor="#22E5D0" // bright cyan-mint accent
marqueeDurationSec={55} // lower = faster
tiltDeg={45} // rotation of the column pair
/>
ROTATION: the column pair is wrapped in a fixed 150vh × 180vh element that's translated to the right edge and rotated by tiltDeg. The section's overflow-hidden clips the diagonal corners. For a less aggressive tilt try 20–30 deg; for vertical (no tilt) use the sibling ai-summit-hero instead.
VIGNETTE: a left-to-right gradient overlay sits between the marquees (z-10) and the text (z-20) so the headline stays readable on top of the photo flow. If you swap bgColor, the vignette auto-adapts (it uses the same bg color with stepped opacity).
ACCESSIBILITY: animations respect prefers-reduced-motion: reduce and stop entirely for those users.
MOBILE: the tilted marquee is hidden below lg. Below lg the hero collapses to the text block on its own.