feat: complete agency site build (Phases 1-7)
Full Next.js 16 + Payload CMS 3.x agency site with: - Homepage: Hero, TrustBar, Services, Configurator wizard, Process, Selected Works, Philosophy, CTA Banner - Sub-pages: /services (3 pillars + AI Layer), /work/[slug] (case studies), /about (philosophy + story) - Configurator: 3-step wizard with AI brief generation API - i18n: Full EN/FR bilingual with next-intl - Design system: Cormorant Garamond + Inter, celestial blue palette, glassmorphism nav, Framer Motion animations - Payload CMS collections: Projects, Services, Submissions, Media Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
81
src/components/icons/AnimatedCheckmark.tsx
Normal file
81
src/components/icons/AnimatedCheckmark.tsx
Normal file
@@ -0,0 +1,81 @@
|
||||
'use client';
|
||||
|
||||
import { motion } from 'framer-motion';
|
||||
|
||||
interface AnimatedCheckmarkProps {
|
||||
size?: number;
|
||||
color?: string;
|
||||
className?: string;
|
||||
}
|
||||
|
||||
export default function AnimatedCheckmark({
|
||||
size = 56,
|
||||
color = '#006494',
|
||||
className,
|
||||
}: AnimatedCheckmarkProps) {
|
||||
const strokeWidth = size * 0.0625; // scales proportionally with size
|
||||
const radius = (size - strokeWidth) / 2;
|
||||
const circumference = 2 * Math.PI * radius;
|
||||
const center = size / 2;
|
||||
|
||||
// Checkmark path — scaled relative to size
|
||||
const checkStartX = size * 0.27;
|
||||
const checkStartY = size * 0.5;
|
||||
const checkMidX = size * 0.44;
|
||||
const checkMidY = size * 0.66;
|
||||
const checkEndX = size * 0.73;
|
||||
const checkEndY = size * 0.34;
|
||||
|
||||
return (
|
||||
<svg
|
||||
width={size}
|
||||
height={size}
|
||||
viewBox={`0 0 ${size} ${size}`}
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
className={className}
|
||||
aria-hidden="true"
|
||||
>
|
||||
{/* Circle */}
|
||||
<motion.circle
|
||||
cx={center}
|
||||
cy={center}
|
||||
r={radius}
|
||||
stroke={color}
|
||||
strokeWidth={strokeWidth}
|
||||
strokeLinecap="round"
|
||||
fill="none"
|
||||
initial={{ strokeDasharray: circumference, strokeDashoffset: circumference }}
|
||||
animate={{ strokeDashoffset: 0 }}
|
||||
transition={{
|
||||
duration: 0.55,
|
||||
ease: [0.4, 0, 0.2, 1],
|
||||
delay: 0.05,
|
||||
}}
|
||||
/>
|
||||
|
||||
{/* Checkmark */}
|
||||
<motion.path
|
||||
d={`M ${checkStartX} ${checkStartY} L ${checkMidX} ${checkMidY} L ${checkEndX} ${checkEndY}`}
|
||||
stroke={color}
|
||||
strokeWidth={strokeWidth}
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
fill="none"
|
||||
initial={{ pathLength: 0, opacity: 0 }}
|
||||
animate={{ pathLength: 1, opacity: 1 }}
|
||||
transition={{
|
||||
pathLength: {
|
||||
duration: 0.4,
|
||||
ease: [0.4, 0, 0.2, 1],
|
||||
delay: 0.65,
|
||||
},
|
||||
opacity: {
|
||||
duration: 0.01,
|
||||
delay: 0.65,
|
||||
},
|
||||
}}
|
||||
/>
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
44
src/components/icons/CornerBracket.tsx
Normal file
44
src/components/icons/CornerBracket.tsx
Normal file
@@ -0,0 +1,44 @@
|
||||
interface CornerBracketProps {
|
||||
size?: number;
|
||||
position?: 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right';
|
||||
color?: string;
|
||||
className?: string;
|
||||
}
|
||||
|
||||
const rotationMap: Record<NonNullable<CornerBracketProps['position']>, string> = {
|
||||
'top-left': 'rotate(0deg)',
|
||||
'top-right': 'rotate(90deg)',
|
||||
'bottom-right': 'rotate(180deg)',
|
||||
'bottom-left': 'rotate(270deg)',
|
||||
};
|
||||
|
||||
export default function CornerBracket({
|
||||
size = 40,
|
||||
position = 'top-left',
|
||||
color = '#c2c7ce',
|
||||
className,
|
||||
}: CornerBracketProps) {
|
||||
return (
|
||||
<div
|
||||
className={className}
|
||||
style={{
|
||||
width: size,
|
||||
height: size,
|
||||
transform: rotationMap[position],
|
||||
flexShrink: 0,
|
||||
}}
|
||||
aria-hidden="true"
|
||||
>
|
||||
<svg
|
||||
width={size}
|
||||
height={size}
|
||||
viewBox="0 0 40 40"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<line x1="1" y1="1" x2="1" y2="18" stroke={color} strokeWidth="1" strokeLinecap="square" />
|
||||
<line x1="1" y1="1" x2="18" y2="1" stroke={color} strokeWidth="1" strokeLinecap="square" />
|
||||
</svg>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
402
src/components/icons/HeroGeometric.tsx
Normal file
402
src/components/icons/HeroGeometric.tsx
Normal file
@@ -0,0 +1,402 @@
|
||||
import React from "react";
|
||||
|
||||
interface HeroGeometricProps {
|
||||
className?: string;
|
||||
}
|
||||
|
||||
export default function HeroGeometric({ className }: HeroGeometricProps) {
|
||||
return (
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 1440 900"
|
||||
preserveAspectRatio="xMidYMid slice"
|
||||
aria-hidden="true"
|
||||
className={className}
|
||||
style={{
|
||||
position: "absolute",
|
||||
inset: 0,
|
||||
width: "100%",
|
||||
height: "100%",
|
||||
pointerEvents: "none",
|
||||
overflow: "hidden",
|
||||
}}
|
||||
>
|
||||
<defs>
|
||||
{/* Celestial blue at various opacities — all values halved for a more atmospheric effect */}
|
||||
<style>{`
|
||||
.cb-fill-03 { fill: #5BA4D9; fill-opacity: 0.015; }
|
||||
.cb-fill-05 { fill: #5BA4D9; fill-opacity: 0.025; }
|
||||
.cb-fill-08 { fill: #5BA4D9; fill-opacity: 0.04; }
|
||||
.cb-fill-12 { fill: #5BA4D9; fill-opacity: 0.06; }
|
||||
.cb-fill-15 { fill: #5BA4D9; fill-opacity: 0.07; }
|
||||
.dn-stroke-06 { fill: none; stroke: #1C2B3A; stroke-opacity: 0.03; }
|
||||
.dn-stroke-08 { fill: none; stroke: #1C2B3A; stroke-opacity: 0.04; }
|
||||
.dn-stroke-10 { fill: none; stroke: #1C2B3A; stroke-opacity: 0.05; }
|
||||
.dn-stroke-14 { fill: none; stroke: #1C2B3A; stroke-opacity: 0.07; }
|
||||
.cb-stroke-08 { fill: none; stroke: #5BA4D9; stroke-opacity: 0.04; }
|
||||
.cb-stroke-12 { fill: none; stroke: #5BA4D9; stroke-opacity: 0.06; }
|
||||
.cb-dot { fill: #1C2B3A; fill-opacity: 0.06; }
|
||||
.cb-dot-sm { fill: #5BA4D9; fill-opacity: 0.05; }
|
||||
`}</style>
|
||||
</defs>
|
||||
|
||||
{/* ─── BACKGROUND LAYER ─────────────────────────────────────────── */}
|
||||
<g data-layer="background">
|
||||
|
||||
{/* Large low-opacity rectangle — far upper-left anchor */}
|
||||
<rect
|
||||
x="-60" y="-40"
|
||||
width="680" height="480"
|
||||
rx="2"
|
||||
className="cb-fill-03 dn-stroke-06"
|
||||
strokeWidth="0.5"
|
||||
/>
|
||||
|
||||
{/* Horizon guide line — full width */}
|
||||
<line
|
||||
x1="0" y1="520"
|
||||
x2="1440" y2="520"
|
||||
className="dn-stroke-06"
|
||||
strokeWidth="0.5"
|
||||
strokeDasharray="6 14"
|
||||
/>
|
||||
|
||||
{/* Vertical axis line — far right third */}
|
||||
<line
|
||||
x1="1060" y1="0"
|
||||
x2="1060" y2="900"
|
||||
className="dn-stroke-06"
|
||||
strokeWidth="0.5"
|
||||
strokeDasharray="4 20"
|
||||
/>
|
||||
|
||||
{/* Large background circle — lower-right anchor */}
|
||||
<circle
|
||||
cx="1280" cy="740"
|
||||
r="320"
|
||||
className="cb-fill-03 dn-stroke-06"
|
||||
strokeWidth="0.5"
|
||||
/>
|
||||
|
||||
{/* Secondary background circle — upper-right bleed */}
|
||||
<circle
|
||||
cx="1380" cy="-60"
|
||||
r="200"
|
||||
className="cb-fill-03 dn-stroke-08"
|
||||
strokeWidth="0.5"
|
||||
/>
|
||||
|
||||
{/* Wide shallow rectangle — lower band */}
|
||||
<rect
|
||||
x="180" y="760"
|
||||
width="900" height="80"
|
||||
rx="1"
|
||||
className="cb-fill-03 dn-stroke-06"
|
||||
strokeWidth="0.5"
|
||||
/>
|
||||
|
||||
{/* Fine grid cluster — upper-left quadrant (sparse) */}
|
||||
{/* Horizontal grid lines */}
|
||||
{[80, 120, 160, 200, 240].map((y) => (
|
||||
<line
|
||||
key={`bg-hgrid-${y}`}
|
||||
x1="40" y1={y}
|
||||
x2="380" y2={y}
|
||||
className="dn-stroke-06"
|
||||
strokeWidth="0.5"
|
||||
/>
|
||||
))}
|
||||
{/* Vertical grid lines */}
|
||||
{[60, 100, 140, 180, 220, 260, 300, 340, 380].map((x) => (
|
||||
<line
|
||||
key={`bg-vgrid-${x}`}
|
||||
x1={x} y1="60"
|
||||
x2={x} y2="260"
|
||||
className="dn-stroke-06"
|
||||
strokeWidth="0.5"
|
||||
/>
|
||||
))}
|
||||
|
||||
{/* Blueprint registration mark — upper left */}
|
||||
<line x1="28" y1="40" x2="28" y2="56" className="dn-stroke-10" strokeWidth="1" />
|
||||
<line x1="20" y1="48" x2="36" y2="48" className="dn-stroke-10" strokeWidth="1" />
|
||||
|
||||
{/* Blueprint registration mark — far right mid */}
|
||||
<line x1="1400" y1="418" x2="1400" y2="434" className="dn-stroke-10" strokeWidth="1" />
|
||||
<line x1="1392" y1="426" x2="1408" y2="426" className="dn-stroke-10" strokeWidth="1" />
|
||||
</g>
|
||||
|
||||
{/* ─── MIDGROUND LAYER ──────────────────────────────────────────── */}
|
||||
<g data-layer="midground">
|
||||
|
||||
{/* Large architectural rectangle — right column */}
|
||||
<rect
|
||||
x="1100" y="80"
|
||||
width="260" height="560"
|
||||
rx="3"
|
||||
className="cb-fill-05 dn-stroke-08"
|
||||
strokeWidth="0.75"
|
||||
/>
|
||||
|
||||
{/* Inset rectangle inside large right column */}
|
||||
<rect
|
||||
x="1126" y="108"
|
||||
width="208" height="120"
|
||||
rx="2"
|
||||
className="cb-fill-08 dn-stroke-10"
|
||||
strokeWidth="0.75"
|
||||
/>
|
||||
|
||||
{/* Tall thin divider — left of center */}
|
||||
<rect
|
||||
x="520" y="60"
|
||||
width="2" height="420"
|
||||
className="cb-fill-15"
|
||||
/>
|
||||
|
||||
{/* Wide horizontal band — upper area */}
|
||||
<rect
|
||||
x="460" y="60"
|
||||
width="540" height="1.5"
|
||||
className="cb-fill-12"
|
||||
/>
|
||||
|
||||
{/* Mid arc — upper right area, partial */}
|
||||
<path
|
||||
d="M 1060 160 A 180 180 0 0 1 1240 160"
|
||||
className="cb-stroke-08"
|
||||
strokeWidth="1"
|
||||
/>
|
||||
|
||||
{/* Concentric arc pair — lower left */}
|
||||
<path
|
||||
d="M 100 900 A 340 340 0 0 1 440 560"
|
||||
className="dn-stroke-08"
|
||||
strokeWidth="0.75"
|
||||
/>
|
||||
<path
|
||||
d="M 60 900 A 380 380 0 0 1 440 520"
|
||||
className="dn-stroke-06"
|
||||
strokeWidth="0.5"
|
||||
strokeDasharray="3 9"
|
||||
/>
|
||||
|
||||
{/* Section label rectangle — left */}
|
||||
<rect
|
||||
x="60" y="320"
|
||||
width="160" height="44"
|
||||
rx="2"
|
||||
className="cb-fill-08 dn-stroke-10"
|
||||
strokeWidth="0.75"
|
||||
/>
|
||||
|
||||
{/* Thin horizontal rule under label */}
|
||||
<line
|
||||
x1="60" y1="374"
|
||||
x2="220" y2="374"
|
||||
className="dn-stroke-08"
|
||||
strokeWidth="0.75"
|
||||
/>
|
||||
|
||||
{/* Dotted measurement track — horizontal mid */}
|
||||
<line
|
||||
x1="560" y1="440"
|
||||
x2="980" y2="440"
|
||||
className="dn-stroke-08"
|
||||
strokeWidth="0.75"
|
||||
strokeDasharray="2 6"
|
||||
/>
|
||||
{/* Tick marks on measurement track */}
|
||||
{[560, 640, 720, 800, 880, 980].map((x) => (
|
||||
<line
|
||||
key={`tick-${x}`}
|
||||
x1={x} y1="434"
|
||||
x2={x} y2="446"
|
||||
className="dn-stroke-10"
|
||||
strokeWidth="0.75"
|
||||
/>
|
||||
))}
|
||||
|
||||
{/* Small dimension rectangle — lower center */}
|
||||
<rect
|
||||
x="680" y="620"
|
||||
width="200" height="120"
|
||||
rx="2"
|
||||
className="cb-fill-05 dn-stroke-08"
|
||||
strokeWidth="0.75"
|
||||
/>
|
||||
|
||||
{/* Diagonal tension line — upper center to right */}
|
||||
<line
|
||||
x1="520" y1="60"
|
||||
x2="1100" y2="640"
|
||||
className="dn-stroke-06"
|
||||
strokeWidth="0.5"
|
||||
/>
|
||||
|
||||
{/* Medium circle — center-left */}
|
||||
<circle
|
||||
cx="380" cy="480"
|
||||
r="90"
|
||||
className="cb-fill-05 dn-stroke-08"
|
||||
strokeWidth="0.75"
|
||||
/>
|
||||
|
||||
{/* Inner ring of medium circle */}
|
||||
<circle
|
||||
cx="380" cy="480"
|
||||
r="60"
|
||||
className="cb-stroke-08"
|
||||
strokeWidth="0.5"
|
||||
strokeDasharray="4 8"
|
||||
/>
|
||||
|
||||
{/* Small circle — upper right cluster */}
|
||||
<circle
|
||||
cx="1200" cy="260"
|
||||
r="36"
|
||||
className="cb-fill-08 dn-stroke-10"
|
||||
strokeWidth="0.75"
|
||||
/>
|
||||
|
||||
{/* Dot grid — right of center, 4x5 */}
|
||||
{[0, 1, 2, 3].map((col) =>
|
||||
[0, 1, 2, 3, 4].map((row) => (
|
||||
<circle
|
||||
key={`dot-${col}-${row}`}
|
||||
cx={760 + col * 28}
|
||||
cy={160 + row * 28}
|
||||
r="1.5"
|
||||
className="cb-dot"
|
||||
/>
|
||||
))
|
||||
)}
|
||||
</g>
|
||||
|
||||
{/* ─── FOREGROUND LAYER ─────────────────────────────────────────── */}
|
||||
<g data-layer="foreground">
|
||||
|
||||
{/* Blueprint frame — upper left inset panel */}
|
||||
<rect
|
||||
x="80" y="80"
|
||||
width="320" height="200"
|
||||
rx="2"
|
||||
className="cb-fill-05 dn-stroke-14"
|
||||
strokeWidth="1"
|
||||
/>
|
||||
|
||||
{/* Inner division of upper-left panel */}
|
||||
<line
|
||||
x1="80" y1="160"
|
||||
x2="400" y2="160"
|
||||
className="dn-stroke-10"
|
||||
strokeWidth="0.75"
|
||||
/>
|
||||
<line
|
||||
x1="240" y1="80"
|
||||
x2="240" y2="280"
|
||||
className="dn-stroke-10"
|
||||
strokeWidth="0.75"
|
||||
/>
|
||||
|
||||
{/* Corner notches on blueprint frame */}
|
||||
<path d="M 80 100 L 80 80 L 100 80" className="dn-stroke-14" strokeWidth="1" fill="none" />
|
||||
<path d="M 380 80 L 400 80 L 400 100" className="dn-stroke-14" strokeWidth="1" fill="none" />
|
||||
<path d="M 80 260 L 80 280 L 100 280" className="dn-stroke-14" strokeWidth="1" fill="none" />
|
||||
<path d="M 380 280 L 400 280 L 400 260" className="dn-stroke-14" strokeWidth="1" fill="none" />
|
||||
|
||||
{/* Precision arc — upper left panel, quarter circle */}
|
||||
<path
|
||||
d="M 160 80 A 80 80 0 0 1 240 160"
|
||||
className="cb-stroke-12"
|
||||
strokeWidth="1"
|
||||
/>
|
||||
|
||||
{/* Foreground tall rect — left bleed */}
|
||||
<rect
|
||||
x="-20" y="400"
|
||||
width="100" height="340"
|
||||
rx="2"
|
||||
className="cb-fill-08 dn-stroke-10"
|
||||
strokeWidth="0.75"
|
||||
/>
|
||||
|
||||
{/* Foreground arc — lower right */}
|
||||
<path
|
||||
d="M 1140 640 A 240 240 0 0 0 1380 640"
|
||||
className="dn-stroke-10"
|
||||
strokeWidth="1"
|
||||
/>
|
||||
<path
|
||||
d="M 1160 640 A 200 200 0 0 0 1360 640"
|
||||
className="cb-stroke-12"
|
||||
strokeWidth="0.75"
|
||||
strokeDasharray="3 7"
|
||||
/>
|
||||
|
||||
{/* Callout line — from blueprint panel to right */}
|
||||
<line
|
||||
x1="400" y1="180"
|
||||
x2="520" y2="180"
|
||||
className="dn-stroke-14"
|
||||
strokeWidth="0.75"
|
||||
/>
|
||||
<circle cx="520" cy="180" r="3" className="cb-fill-15" />
|
||||
|
||||
{/* Thin vertical guide — right of blueprint panel */}
|
||||
<line
|
||||
x1="520" y1="80"
|
||||
x2="520" y2="360"
|
||||
className="dn-stroke-08"
|
||||
strokeWidth="0.5"
|
||||
strokeDasharray="2 8"
|
||||
/>
|
||||
|
||||
{/* Small accent square — upper center */}
|
||||
<rect
|
||||
x="690" y="100"
|
||||
width="48" height="48"
|
||||
rx="1"
|
||||
className="cb-fill-12 dn-stroke-14"
|
||||
strokeWidth="1"
|
||||
transform="rotate(12 714 124)"
|
||||
/>
|
||||
|
||||
{/* Dot accent — scattered foreground points */}
|
||||
<circle cx="460" cy="320" r="2.5" className="cb-dot-sm" />
|
||||
<circle cx="560" cy="280" r="2" className="cb-dot-sm" />
|
||||
<circle cx="600" cy="340" r="1.5" className="cb-dot-sm" />
|
||||
<circle cx="1080" cy="680" r="2.5" className="cb-dot-sm" />
|
||||
<circle cx="1140" cy="700" r="1.5" className="cb-dot-sm" />
|
||||
<circle cx="300" cy="600" r="2" className="cb-dot-sm" />
|
||||
<circle cx="340" cy="560" r="1.5" className="cb-dot-sm" />
|
||||
|
||||
{/* Small labeled rectangle — lower left */}
|
||||
<rect
|
||||
x="100" y="700"
|
||||
width="120" height="60"
|
||||
rx="1"
|
||||
className="cb-fill-08 dn-stroke-10"
|
||||
strokeWidth="0.75"
|
||||
/>
|
||||
{/* Tick detail inside small rect */}
|
||||
<line x1="100" y1="720" x2="220" y2="720" className="dn-stroke-08" strokeWidth="0.5" />
|
||||
<line x1="160" y1="700" x2="160" y2="760" className="dn-stroke-08" strokeWidth="0.5" />
|
||||
|
||||
{/* Fine detail lines — lower right corner cluster */}
|
||||
<line x1="1300" y1="820" x2="1440" y2="820" className="dn-stroke-08" strokeWidth="0.5" />
|
||||
<line x1="1300" y1="840" x2="1440" y2="840" className="dn-stroke-06" strokeWidth="0.5" strokeDasharray="3 6" />
|
||||
<line x1="1320" y1="800" x2="1320" y2="900" className="dn-stroke-08" strokeWidth="0.5" />
|
||||
<circle cx="1320" cy="820" r="3" className="cb-fill-15" />
|
||||
|
||||
{/* Radius annotation arc — center large circle */}
|
||||
<path
|
||||
d="M 320 480 L 380 480"
|
||||
className="dn-stroke-14"
|
||||
strokeWidth="0.75"
|
||||
/>
|
||||
<circle cx="380" cy="480" r="2" className="cb-fill-15" />
|
||||
</g>
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user