Files
gridpilot.gg/apps/website/components/landing/LandingHero.tsx
2026-01-17 02:32:34 +01:00

128 lines
4.8 KiB
TypeScript

import { useRef } from 'react';
import { useParallax } from '@/hooks/useScrollProgress';
import { Box } from '@/ui/Box';
import { Button } from '@/ui/Button';
import { Container } from '@/ui/Container';
import { Heading } from '@/ui/Heading';
import { Stack } from '@/ui/Stack';
import { Text } from '@/ui/Text';
import { Glow } from '@/ui/Glow';
const discordUrl = process.env.NEXT_PUBLIC_DISCORD_URL || '#';
export function LandingHero() {
const sectionRef = useRef<HTMLElement>(null);
const bgParallax = useParallax(sectionRef, 0.2);
return (
<Box
as="section"
ref={sectionRef}
position="relative"
overflow="hidden"
bg="graphite-black"
pt={{ base: 24, md: 32, lg: 40 }}
pb={{ base: 16, md: 24, lg: 32 }}
className="border-b border-border-gray"
>
{/* Background image layer with parallax */}
<Box
position="absolute"
inset="0"
bg="url(/images/header.jpeg)"
backgroundSize="cover"
backgroundPosition="center"
opacity={0.2}
style={{ transform: `translateY(${bgParallax * 0.5}px)` }}
/>
{/* Robust gradient overlay */}
<Box
position="absolute"
inset="0"
bg="linear-gradient(to bottom, #0C0D0F 0%, transparent 50%, #0C0D0F 100%)"
/>
<Box
position="absolute"
inset="0"
bg="radial-gradient(circle at center, transparent 0%, #0C0D0F 100%)"
opacity={0.6}
/>
<Glow color="primary" size="xl" position="center" opacity={0.1} />
<Container size="lg" position="relative" zIndex={10}>
<Stack gap={{ base: 8, md: 12 }}>
<Stack gap={6} maxWidth="3xl">
<Box borderLeft borderStyle="solid" borderColor="primary-accent" pl={4} mb={2}>
<Text size="xs" weight="bold" color="text-primary-accent" className="uppercase tracking-[0.2em]">
Precision Racing Infrastructure
</Text>
</Box>
<Heading
level={1}
fontSize={{ base: '3xl', sm: '4xl', md: '5xl', lg: '7xl' }}
weight="bold"
className="text-white leading-[1.1] tracking-tight"
>
Modern Motorsport <br />
<span className="text-primary-accent">Infrastructure.</span>
</Heading>
<Text size={{ base: 'lg', md: 'xl' }} color="text-gray-400" weight="normal" leading="relaxed" className="max-w-2xl">
GridPilot gives your league racing a real home. Results, standings, teams, and career progression engineered for precision and control.
</Text>
</Stack>
<Box display="flex" flexDirection={{ base: 'column', sm: 'row' }} gap={4}>
<Button
as="a"
href={discordUrl}
variant="primary"
size="lg"
className="px-10 rounded-none uppercase tracking-widest text-xs font-bold"
>
Join the Grid
</Button>
<Button
variant="secondary"
size="lg"
className="px-10 rounded-none border-border-gray hover:border-primary-accent/50 uppercase tracking-widest text-xs font-bold"
>
Explore Leagues
</Button>
</Box>
{/* Problem list - more professional */}
<Box
display="grid"
gridCols={{ base: 1, sm: 2, lg: 4 }}
gap={8}
mt={12}
className="border-t border-border-gray/30 pt-12"
>
{[
{ label: 'IDENTITY', text: 'Your racing career in one place', color: 'primary' },
{ label: 'AUTOMATION', text: 'No more manual session setup', color: 'aqua' },
{ label: 'PRECISION', text: 'Real-time results and standings', color: 'amber' },
{ label: 'COMMUNITY', text: 'Built for teams and leagues', color: 'green' }
].map((item) => (
<Stack key={item.label} gap={3} className="group">
<Box display="flex" alignItems="center" gap={2}>
<Box w="2" h="2" rounded="full" className={`bg-${item.color === 'primary' ? 'primary-accent' : item.color === 'aqua' ? 'telemetry-aqua' : item.color === 'amber' ? 'warning-amber' : 'success-green'}`} />
<Text size="xs" weight="bold" color="text-gray-500" className="uppercase tracking-[0.2em] group-hover:text-white transition-colors">
{item.label}
</Text>
</Box>
<Text size="sm" color="text-gray-400" className="group-hover:text-gray-200 transition-colors">
{item.text}
</Text>
</Stack>
))}
</Box>
</Stack>
</Container>
</Box>
);
}