All checks were successful
Build & Push / build-and-push (push) Successful in 1m26s
Hero: - Removed fake trust proof avatars - Added decorative gradient separator line - Pushed content down for better vertical rhythm - More visible secondary CTA button TrustBar: - Icon circles with primary tint backdrops - Gradient top accent bar on hover - Gradient fade transition from hero section - Increased card padding Services: - Subtle grid texture background - Larger primary-colored feature dots - Enhanced AI narrative with horizontal decorative rules - Hover shadow elevation on pillars Configurator: - Step numbers in tinted circles with vertical rail - ShieldCheck trust icon - Radial gradient glow on wizard panel - Sparkles icon on AI toggle - Empty-state hint message - Service card icons in circular primary backdrops Process: - Gradient top accent strips on cards - Icon containers with primary tint - Vertical accent bar on section heading - Dashed SVG connector lines between cards SelectedWorks: - Distinct geometric compositions per card (Monaco, Nimara, Amador) - Bottom gradient fade on placeholder images - Dot separators between tags - Animated background pulse on coming-soon cards - Enhanced CTA hover animations Philosophy: - Enriched decorative panel (circle rings, diagonal lines, navy gradient) - Primary-colored pillar numbers - Left border accent on pull-quote card CTABanner: - Grid pattern + circle ring overlays - Email link underline-on-hover animation Footer: - Full logo image replacing text wordmark - Larger social icons - Gradient divider line - Larger nav logo (h-14 desktop, h-11 mobile) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
146 lines
3.8 KiB
TypeScript
146 lines
3.8 KiB
TypeScript
'use client';
|
|
|
|
import { motion } from 'framer-motion';
|
|
import { useTranslations } from 'next-intl';
|
|
import { Compass, Shield, Brain, MapPin } from 'lucide-react';
|
|
import { cn } from '@/lib/utils';
|
|
import {
|
|
revealVariants,
|
|
staggerContainerWide,
|
|
viewportOnce,
|
|
} from '@/lib/animations';
|
|
import type { LucideIcon } from 'lucide-react';
|
|
|
|
// Each item's icon scale-bounce on enter
|
|
const iconBounceVariants = {
|
|
hidden: { scale: 0.7, opacity: 0 },
|
|
visible: {
|
|
scale: 1,
|
|
opacity: 1,
|
|
transition: {
|
|
duration: 0.5,
|
|
ease: [0.34, 1.56, 0.64, 1] as [number, number, number, number], // spring-like overshoot
|
|
},
|
|
},
|
|
};
|
|
|
|
interface TrustItem {
|
|
key: string;
|
|
Icon: LucideIcon;
|
|
}
|
|
|
|
const ITEMS: TrustItem[] = [
|
|
{ key: 'customBuilt', Icon: Compass },
|
|
{ key: 'privateInfra', Icon: Shield },
|
|
{ key: 'aiPowered', Icon: Brain },
|
|
{ key: 'rivieraBased', Icon: MapPin },
|
|
];
|
|
|
|
interface TrustCardProps {
|
|
item: TrustItem;
|
|
index: number;
|
|
t: (key: string) => string;
|
|
}
|
|
|
|
function TrustCard({ item, index, t }: TrustCardProps) {
|
|
const { Icon, key } = item;
|
|
|
|
return (
|
|
<motion.div
|
|
variants={revealVariants}
|
|
className={cn(
|
|
'group relative flex flex-col items-start gap-4 p-8',
|
|
'rounded-2xl bg-surface-high shadow-subtle',
|
|
'transition-shadow duration-300 hover:shadow-card',
|
|
'overflow-hidden cursor-default',
|
|
)}
|
|
>
|
|
{/* Top accent gradient bar — fades in on hover */}
|
|
<span
|
|
className={cn(
|
|
'pointer-events-none absolute top-0 left-6 right-6 h-[3px] rounded-full',
|
|
'opacity-0 group-hover:opacity-100 transition-opacity duration-300',
|
|
)}
|
|
style={{
|
|
background: 'linear-gradient(to right, #006494, #5BA4D9)',
|
|
}}
|
|
aria-hidden="true"
|
|
/>
|
|
|
|
{/* Icon with scale-bounce on scroll reveal */}
|
|
<motion.div
|
|
variants={iconBounceVariants}
|
|
className={cn(
|
|
'flex items-center justify-center w-12 h-12 rounded-full',
|
|
'bg-primary/8',
|
|
'transition-transform duration-300 ease-out',
|
|
'group-hover:-translate-y-1',
|
|
)}
|
|
aria-hidden="true"
|
|
>
|
|
<Icon
|
|
size={24}
|
|
className="text-primary transition-colors duration-300"
|
|
strokeWidth={1.75}
|
|
/>
|
|
</motion.div>
|
|
|
|
{/* Title */}
|
|
<div>
|
|
<h3
|
|
className={cn(
|
|
'font-semibold text-on-surface text-base leading-snug mb-1',
|
|
'transition-colors duration-300 group-hover:text-primary-dark',
|
|
)}
|
|
>
|
|
{t(`${key}.title`)}
|
|
</h3>
|
|
|
|
{/* Description */}
|
|
<p className="text-sm text-outline leading-relaxed">
|
|
{t(`${key}.description`)}
|
|
</p>
|
|
</div>
|
|
</motion.div>
|
|
);
|
|
}
|
|
|
|
export default function TrustBar() {
|
|
const t = useTranslations('trustBar');
|
|
|
|
return (
|
|
<section
|
|
aria-label="Trust indicators"
|
|
className="relative bg-surface-low py-16"
|
|
>
|
|
{/* Gradient bridge — blends hero surface-high into this section */}
|
|
<div
|
|
className="absolute top-0 left-0 right-0 h-8 pointer-events-none"
|
|
style={{
|
|
background: 'linear-gradient(to bottom, #ffffff, transparent)',
|
|
}}
|
|
aria-hidden="true"
|
|
/>
|
|
<div className="max-w-6xl mx-auto px-6">
|
|
{/* Stagger wrapper — triggers children revealVariants on scroll */}
|
|
<motion.div
|
|
variants={staggerContainerWide}
|
|
initial="hidden"
|
|
whileInView="visible"
|
|
viewport={viewportOnce}
|
|
className="grid grid-cols-2 md:grid-cols-4 gap-6 md:gap-8"
|
|
>
|
|
{ITEMS.map((item, index) => (
|
|
<TrustCard
|
|
key={item.key}
|
|
item={item}
|
|
index={index}
|
|
t={t}
|
|
/>
|
|
))}
|
|
</motion.div>
|
|
</div>
|
|
</section>
|
|
);
|
|
}
|