website landing page

This commit is contained in:
2025-12-02 19:44:18 +01:00
parent fd3b4171aa
commit 895318ac40
33 changed files with 2226 additions and 842 deletions

View File

@@ -22,11 +22,11 @@ export default function Button({
as = 'button',
...props
}: ButtonProps) {
const baseStyles = 'rounded-full px-6 py-3 text-sm font-semibold transition-all duration-75 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 hover:scale-[1.03] active:scale-[0.98]';
const baseStyles = 'min-h-[44px] rounded-full px-6 py-3 text-sm font-semibold transition-all duration-75 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 hover:scale-[1.03] active:scale-95';
const variantStyles = {
primary: 'bg-primary-blue text-white hover:shadow-glow active:ring-2 active:ring-primary-blue focus-visible:outline-primary-blue',
secondary: 'bg-iron-gray text-white border border-charcoal-outline hover:shadow-glow-strong hover:border-primary-blue focus-visible:outline-primary-blue'
primary: 'bg-primary-blue text-white shadow-[0_0_15px_rgba(25,140,255,0.4)] hover:shadow-[0_0_25px_rgba(25,140,255,0.6)] active:ring-2 active:ring-primary-blue focus-visible:outline-primary-blue',
secondary: 'bg-iron-gray text-white border border-charcoal-outline shadow-[0_0_10px_rgba(25,140,255,0.2)] hover:shadow-[0_0_20px_rgba(25,140,255,0.4)] hover:border-primary-blue focus-visible:outline-primary-blue'
};
const classes = `${baseStyles} ${variantStyles[variant]} ${className}`;

View File

@@ -4,9 +4,10 @@ interface HeadingProps {
level: 1 | 2 | 3;
children: ReactNode;
className?: string;
style?: React.CSSProperties;
}
export default function Heading({ level, children, className = '' }: HeadingProps) {
export default function Heading({ level, children, className = '', style }: HeadingProps) {
const baseStyles = 'font-bold tracking-tight';
const levelStyles = {
@@ -18,7 +19,7 @@ export default function Heading({ level, children, className = '' }: HeadingProp
const Tag = `h${level}` as keyof JSX.IntrinsicElements;
return (
<Tag className={`${baseStyles} ${levelStyles[level]} ${className}`}>
<Tag className={`${baseStyles} ${levelStyles[level]} ${className}`} style={style}>
{children}
</Tag>
);

View File

@@ -1,7 +1,7 @@
'use client';
import { motion, useReducedMotion } from 'framer-motion';
import { ReactNode } from 'react';
import { ReactNode, useEffect, useState } from 'react';
interface MockupStackProps {
children: ReactNode;
@@ -10,13 +10,68 @@ interface MockupStackProps {
export default function MockupStack({ children, index = 0 }: MockupStackProps) {
const shouldReduceMotion = useReducedMotion();
const [isMounted, setIsMounted] = useState(false);
const [isMobile, setIsMobile] = useState(true); // Default to mobile (no animations)
useEffect(() => {
setIsMounted(true);
const checkMobile = () => setIsMobile(window.innerWidth < 768);
checkMobile();
window.addEventListener('resize', checkMobile);
return () => window.removeEventListener('resize', checkMobile);
}, []);
const seed = index * 1337;
const rotation1 = ((seed * 17) % 80 - 40) / 20;
const rotation2 = ((seed * 23) % 80 - 40) / 20;
// On mobile or before mount, render without animations
if (!isMounted || isMobile) {
return (
<div className="relative w-full h-full scale-60 sm:scale-70 md:scale-85 lg:scale-95 max-w-[85vw] mx-auto my-4 sm:my-0" style={{ perspective: '1200px' }}>
<div
className="absolute rounded-lg bg-iron-gray/80 border border-charcoal-outline"
style={{
rotate: rotation1,
zIndex: 1,
top: '-8px',
left: '-8px',
right: '-8px',
bottom: '-8px',
boxShadow: '0 12px 40px rgba(0,0,0,0.3)',
opacity: 0.5,
}}
/>
<div
className="absolute rounded-lg bg-iron-gray/90 border border-charcoal-outline"
style={{
rotate: rotation2,
zIndex: 2,
top: '-4px',
left: '-4px',
right: '-4px',
bottom: '-4px',
boxShadow: '0 16px 48px rgba(0,0,0,0.35)',
opacity: 0.7,
}}
/>
<div
className="relative z-10 w-full h-full rounded-lg overflow-hidden"
style={{
boxShadow: '0 20px 60px rgba(0,0,0,0.45)',
}}
>
{children}
</div>
</div>
);
}
// Desktop: render with animations
return (
<div className="relative w-full h-full" style={{ perspective: '1200px' }}>
<div className="relative w-full h-full scale-60 sm:scale-70 md:scale-85 lg:scale-95 max-w-[85vw] mx-auto my-4 sm:my-0" style={{ perspective: '1200px' }}>
<motion.div
className="absolute rounded-lg bg-iron-gray/80 border border-charcoal-outline"
style={{

View File

@@ -22,7 +22,7 @@ export default function Section({
return (
<section
id={id}
className={`${variantStyles[variant]} px-6 py-32 sm:py-40 lg:px-8 ${className}`}
className={`${variantStyles[variant]} px-[calc(1rem+var(--sal))] pr-[calc(1rem+var(--sar))] py-16 sm:py-20 md:py-32 md:px-[calc(2rem+var(--sal))] md:pr-[calc(2rem+var(--sar))] lg:px-8 ${className}`}
>
{children}
</section>