Internal reference · Design system v2
Brand Handbook
Bold/Geometric + Sparse/Authoritative. Typography-driven authority, confident whitespace, colors as accents — not backgrounds. This is the single source of truth for every design decision.
51.7519° N 1.2578° W
Design Philosophy
Core direction
Typography-driven authority
Georgia serif headings do the heavy lifting. Bold type at scale creates authority without decorative chrome.
Confident whitespace
Breathing room is intentional. Sections breathe at py-12 and never stack without a hairline pause.
Colors as accents
Full-color backgrounds are used in exactly two places: blue (positioning band + CTA section) and tea-green (How We Work + quote bands). Everything else sits on ivory.
Distinctive, not corporate
This is not a consulting firm. No deck aesthetic, no lucide icon grids. The design should feel direct and editorial.
Anti-patterns — never use these
- ×Pill / oval tags (rounded-full badges)
- ×Card grids with box-shadow
- ×Wave SVGs or decorative shape dividers
- ×Full-color section backgrounds (outside blue & green exceptions)
- ×Lucide icons anywhere on the site
- ×container mx-auto px-4 layout wrapper
Note: MagneticButton on the homepage does use rounded-full because the CTA pill is a deliberate editorial contrast against the otherwise rectilinear system. Hero CTA buttons also use rounded-full. Internal UI components (capability cards, border bars) remain sharp-cornered.
Brand Colors
Brand Blue
#0047bb · brand-blue- — Positioning band (full-width section below hero)
- — Final CTA section background on all pages
- — Angled blue edge element bleeding from hero footer
- — Accent top border (6px) on capability cards
- — Left-border bars on credibility items (cycles with tangerine, tea-green)
- — Quote band left-border accent inside tea-green sections
- — MagneticButton hover background
Brand Ivory
#fffff2 · brand-ivory- — Default background for ALL non-accent sections
- — Text and button color on dark/blue surfaces
- — Hero primary CTA button background (hovers to tangerine)
Brand Tea Green
#c6d8af · brand-tea-green- — How We Work section on homepage — parallelogram shape
- — Mid-page quote/insight band on inner pages (flat, no clip-path)
- — Section label hairline rule (capabilities): rgba(198,216,175,0.6)
- — Left-border bar accent (third item in color cycling pattern)
- — Top border on every third capability card
- — Image frame border: rgba(198,216,175,0.3)
Brand Tangerine
#fca17d · brand-tangerine- — Ticker / marquee band background
- — MagneticButton default background
- — Inner page CTA primary button (style={{ backgroundColor: '#fca17d' }})
- — Left-border bar accent (second item in cycling pattern)
- — Top border on second capability card
- — Cursor spotlight on hero: rgba(252,161,125,0.09)
- — Hero h1 left-border accent on some inner pages
Brand Black
#000000 · brand-black- — All body text on ivory backgrounds
- — MagneticButton and CTA button text on tangerine backgrounds
- — Ticker item text
Typography
Headings — Georgia serif, bold
h1Heading One
{/* Homepage hero — slightly larger */}
<h1 className="text-4xl md:text-5xl lg:text-6xl font-serif font-bold leading-tight"
style={{ color: "#fffff2" }}>
{/* Inner page heroes — on ivory with left accent */}
<div style={{ borderLeft: "3px solid #fca17d" }} className="pl-3 mb-8">
<h1 className="text-4xl md:text-5xl font-serif font-bold text-brand-black leading-tight">
Page title here.
</h1>
</div>h2Heading Two
<h2 className="text-2xl md:text-3xl font-serif font-bold text-brand-black">
h3Heading Three
<h3 className="font-serif font-bold text-base leading-snug text-brand-black">
Body text — opacity hierarchy
Primary body: 70% opacity. Used for main prose content on ivory backgrounds.
Secondary body: 65% opacity. Used in How We Work step bodies, team section, and some inner-page copy.
Small / supporting: text-xs at 60% opacity. Used in credibility border-bar bodies, capability card descriptions (0.58), and dense data contexts.
{/* Primary body — ivory background */}
<p className="text-sm leading-relaxed" style={{ color: "rgba(0,0,0,0.70)" }}>
{/* Secondary body — slightly dimmer */}
<p className="text-sm leading-relaxed" style={{ color: "rgba(0,0,0,0.65)" }}>
{/* Small supporting — border-bar detail text */}
<p className="text-xs leading-snug" style={{ color: "rgba(0,0,0,0.60)" }}>
{/* Capability card desc — just slightly more transparent */}
<p className="text-sm leading-relaxed" style={{ color: "rgba(0,0,0,0.58)" }}>
{/* On dark/blue surfaces */}
<p className="text-sm leading-relaxed" style={{ color: "rgba(255,255,242,0.70)" }}>
<p className="text-lg leading-relaxed" style={{ color: "rgba(255,255,242,0.80)" }}>Section labels — eyebrow annotations
About Us
What we do
{/* Inner page heroes and section headings — text-[10px] */}
<p className="text-[10px] font-bold tracking-widest uppercase mb-6"
style={{ color: "rgba(0,0,0,0.35)" }}>
About Us
</p>
{/* Homepage section labels — text-[8px] */}
<p className="text-[8px] font-bold tracking-widest uppercase"
style={{ color: "rgba(0,0,0,0.35)" }}>
What we do
</p>
{/* Label + tea-green hairline rule — capabilities section */}
<div className="flex items-center gap-4 mb-8">
<span className="text-xs font-bold tracking-widest uppercase text-black/35 whitespace-nowrap">
What we do
</span>
<div className="flex-1 h-px" style={{ backgroundColor: "rgba(198,216,175,0.6)" }} />
</div>
{/* On blue surfaces */}
<p className="text-[10px] font-bold tracking-widest uppercase mb-5"
style={{ color: "rgba(255,255,242,0.45)" }}>
Work with us
</p>Never use a label as a pill/badge. No rounded-full on labels.
Ghost numbers — decorative counters
{/* Page-level section heading (48px, 8% opacity) */}
<span
className="font-serif font-bold leading-none select-none"
style={{ fontSize: "48px", color: "rgba(0,0,0,0.08)" }}
aria-hidden="true"
>
01
</span>
{/* In-grid item number (36px, 8% opacity) — capabilities, philosophy lists */}
<div
className="font-serif font-bold select-none mb-3 leading-none"
style={{ fontSize: "36px", color: "rgba(0,0,0,0.08)" }}
>
01
</div>
{/* How We Work steps — 36px but at 18% for tea-green contrast */}
<div
className="font-serif font-bold select-none mb-1"
style={{ fontSize: "36px", color: "rgba(0,0,0,0.18)", lineHeight: 1 }}
>
01
</div>Mono — technical annotations only
51.7519° N 1.2578° W
{/* Easter egg — 28% ivory opacity on dark hero background */}
<p className="font-mono text-[9px] tracking-widest"
style={{ color: "rgba(255,255,242,0.28)" }}>
51.7519° N 1.2578° W
</p>
{/* Metadata / hex annotations — 45% opacity on ivory */}
<code className="font-mono text-[9px]" style={{ color: "rgba(0,0,0,0.45)" }}>
#0047bb · brand-blue
</code>Layout Patterns
Section padding — full width, no container
All sections span full width. No container mx-auto or px-4. Horizontal padding scales with breakpoint. Vertical padding varies by section type.
{/* Standard content section */}
<section className="bg-brand-ivory px-8 md:px-14 lg:px-20 py-12">
{/* Inner page hero */}
<section className="bg-brand-ivory px-8 md:px-14 lg:px-20 pt-20 pb-16">
{/* Credibility section — extra vertical breathing room */}
<section className="bg-brand-ivory px-8 md:px-14 lg:px-20 py-16">
{/* Blue CTA — inner pages */}
<section className="px-8 md:px-14 lg:px-20 py-16" style={{ backgroundColor: "#0047bb" }}>
{/* Final CTA — homepage (larger, centered) */}
<section
className="relative py-24 px-8 md:px-14 lg:px-20 text-center overflow-hidden"
style={{ backgroundColor: "#0047bb" }}
>Inner page hero — standard pattern
Every inner page (About, What We Do, etc.) opens with an ivory hero that has pt-20 pb-16, a small eyebrow label, and an h1 wrapped in a left accent bar. The accent color varies by page.
<section className="bg-brand-ivory px-8 md:px-14 lg:px-20 pt-20 pb-16">
<div className="max-w-3xl">
{/* Eyebrow label — fades in first */}
<motion.div
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
transition={{ duration: 0.6, delay: 0.1, ease: [0.22, 1, 0.36, 1] }}
>
<p className="text-[10px] font-bold tracking-widest uppercase mb-6"
style={{ color: "rgba(0,0,0,0.35)" }}>
About Us
</p>
</motion.div>
{/* h1 with left accent bar — delay 0.2 */}
<motion.div
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
transition={{ duration: 0.6, delay: 0.2, ease: [0.22, 1, 0.36, 1] }}
>
<div style={{ borderLeft: "3px solid #fca17d" }} className="pl-3 mb-8">
<h1 className="text-4xl md:text-5xl font-serif font-bold text-brand-black leading-tight">
Page headline here.
</h1>
</div>
</motion.div>
{/* Intro paragraph — delay 0.3 */}
<motion.div
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
transition={{ duration: 0.6, delay: 0.3, ease: [0.22, 1, 0.36, 1] }}
>
<p className="text-sm leading-relaxed max-w-2xl"
style={{ color: "rgba(0,0,0,0.70)" }}>
Supporting paragraph text.
</p>
</motion.div>
</div>
</section>Page section sequence — inner pages
Every inner page follows this sequence. The tea-green band and blue CTA are not optional.
- [1]Inner page hero (ivory, pt-20 pb-16, eyebrow + h1 with left accent)
- [2]Hairline divider (h-px, rgba(0,0,0,0.08))
- [3]Content sections (ivory, py-12) — as many as needed, each separated by hairlines
- [4]Tea-green quote/insight band (py-12, flat — no clip-path on inner pages)
- [5]More content sections if needed
- [6]Blue CTA section (py-16) — always last before footer
Left border bars — data and credibility items
Technical depth
Supporting detail text.
Strategic range
Supporting detail text.
Honest scoping
Supporting detail text.
// Cycling color pattern — blue → tangerine → tea-green → repeat
const ACCENT_COLORS = ["#0047bb", "#fca17d", "#c6d8af"]
{ITEMS.map(({ label, body }, i) => (
<div
key={label}
className="pl-3"
style={{ borderLeft: `3px solid ${ACCENT_COLORS[i % 3]}` }}
>
<p className="font-serif font-bold text-sm text-brand-black mb-1">{label}</p>
<p className="text-xs leading-snug" style={{ color: "rgba(0,0,0,0.60)" }}>{body}</p>
</div>
))}
{/* Single-color variant (background items on About page — all tea-green) */}
<div className="py-5 pl-3" style={{ borderLeft: "3px solid #c6d8af" }}>
{/* Quote band left border on tea-green background — pl-4 instead of pl-3 */}
<div className="max-w-3xl" style={{ borderLeft: "3px solid #0047bb" }}>
<p className="pl-4 text-2xl md:text-3xl font-serif font-bold italic leading-snug">
"Quote text here."
</p>
</div>Hairline rules — section dividers
{/* Standard section divider — used between every section on inner pages */}
<div className="h-px w-full" style={{ backgroundColor: "rgba(0,0,0,0.08)" }} />
{/* Same but as inline style on a wrapping div (also common) */}
<div className="h-px" style={{ backgroundColor: "rgba(0,0,0,0.08)" }} />
{/* Within-section hairline — between list items or subsections */}
{i < ITEMS.length - 1 && (
<div className="h-px" style={{ backgroundColor: "rgba(0,0,0,0.08)" }} />
)}
{/* How We Work footer rule — inside tea-green band */}
<div className="mt-6 pt-3" style={{ borderTop: "1px solid rgba(0,0,0,0.10)" }} />Content max-widths — constrain prose, not sections
{/* Body copy — tightest constraint */}
<p className="max-w-2xl ...">
{/* Wider prose blocks and quote bands */}
<div className="max-w-3xl ...">
{/* Inner page hero text area */}
<div className="max-w-3xl">
{/* Grid content (capabilities, philosophy) */}
<div className="max-w-4xl ...">
{/* Blue CTA inner pages — left-aligned */}
<div className="max-w-2xl">
{/* Homepage hero — spans left side */}
<div className="px-8 md:px-14 lg:px-20 max-w-3xl">Grid patterns — common column layouts
{/* 2-col: text + media (origin / credibility sections) */}
<div className="grid grid-cols-1 lg:grid-cols-2 gap-14 items-center">
{/* 2-col: text + items (credibility) */}
<div className="grid grid-cols-1 md:grid-cols-2 gap-6 relative z-[1] items-center">
{/* Ghost number + content — used in philosophy and section headings */}
<div className="py-6 grid gap-4" style={{ gridTemplateColumns: "56px 1fr" }}>
{/* Capabilities — 3×2 grid with border dividers */}
<div
className="grid grid-cols-1 md:grid-cols-2 relative"
style={{ border: "1px solid rgba(0,0,0,0.07)" }}
>
{/* How We Work steps — 3-col on md+ */}
<div className="grid grid-cols-1 md:grid-cols-3 gap-6 max-w-4xl w-full">How We Work — tea-green parallelogram (homepage only)
The only section using clip-path. Negative margins pull it into adjacent ivory sections; clip-path creates the angled top and bottom edges. z-10 ensures it sits above its neighbors. Inner pages use a flat tea-green band instead.
{/* Homepage only — parallelogram shape */}
<section
className="bg-brand-tea-green px-8 md:px-14 lg:px-20 flex flex-col items-center relative z-10"
style={{
marginTop: "-44px",
marginBottom: "-32px",
paddingTop: "calc(2.5rem + 44px)",
paddingBottom: "calc(2.5rem + 32px)",
clipPath: "polygon(0 0, 100% 44px, 100% calc(100% - 32px), 0 100%)",
}}
>
{/* Inner pages — flat tea-green band, no clip-path */}
<section
className="px-8 md:px-14 lg:px-20 py-12"
style={{ backgroundColor: "#c6d8af" }}
>Dot-grid texture — decorative overlay on blue sections
Used in both the homepage hero and the final CTA section. Always pointer-events-none and absolute inset-0. Dot opacity and grid size differ slightly between the two contexts.
{/* Hero — 8% ivory dots, 28px grid */}
<div
className="absolute inset-0 z-[1] pointer-events-none"
style={{
backgroundImage: "radial-gradient(rgba(255,255,242,0.08) 1px, transparent 1px)",
backgroundSize: "28px 28px",
}}
/>
{/* Final CTA — 7% ivory dots, 22px grid */}
<div
className="absolute inset-0 pointer-events-none"
style={{
backgroundImage: "radial-gradient(rgba(255,255,242,0.07) 1px, transparent 1px)",
backgroundSize: "22px 22px",
}}
/>Buttons & Links
Homepage hero CTAs — rounded-full pair
Only context where non-magnetic buttons use rounded-full. Primary is ivory (hovers to tangerine). Secondary is an outline ghost. Both are pills.
{/* Primary */}
<Button size="lg" className="rounded-full px-8 bg-brand-ivory text-brand-black
hover:bg-brand-tangerine transition-colors duration-300 w-full sm:w-auto font-medium">
Start a Conversation
</Button>
{/* Secondary outline */}
<Button
variant="outline"
size="lg"
className="rounded-full px-8 border-brand-ivory text-brand-ivory
hover:bg-brand-ivory hover:text-brand-black bg-transparent
transition-colors duration-300 w-full sm:w-auto font-medium"
>
What We Do
</Button>Inner page CTA buttons — sharp corners on blue backgrounds
On blue CTA sections, the primary button uses tangerine fill with text-brand-black. No rounded-full. Secondary is a ghost outline. Both use Reveal wrappers with staggered delays.
{/* Primary — tangerine with black text */}
<Button
size="lg"
className="px-8 text-brand-black font-medium transition-colors duration-300 w-full sm:w-auto"
style={{ backgroundColor: "#fca17d" }}
>
Start a Conversation
</Button>
{/* Secondary — ghost outline, ivory text */}
<Button
variant="outline"
size="lg"
className="px-8 font-medium transition-colors duration-300 w-full sm:w-auto"
style={{
backgroundColor: "transparent",
border: "1px solid rgba(255,255,242,0.35)",
color: "#fffff2",
}}
>
See Our Work
</Button>Inline links — text only, underline offset
{/* On ivory — blue text with underline */}
<Link
href="/what-we-do"
className="text-sm font-semibold text-brand-blue underline underline-offset-4
hover:text-brand-tangerine transition-colors"
>
Explore all capabilities →
</Link>
{/* On tea-green — subdued, no color */}
<Link
href="/approach"
className="text-xs underline underline-offset-4 hover:text-brand-blue transition-colors"
style={{ color: "rgba(0,0,0,0.45)" }}
>
Our full approach →
</Link>Animation System
Reveal — shared scroll-triggered component
Import from @/components/reveal for all inner pages. Supports delay for stagger and direction for slide-in axis. The homepage defines its own local Reveal in ClientPage.tsx — functionally the same.
// components/reveal.tsx
"use client"
import { motion } from "framer-motion"
interface RevealProps {
children: React.ReactNode
className?: string
delay?: number
direction?: "up" | "left" | "right"
}
export function Reveal({ children, className, delay = 0, direction = "up" }: RevealProps) {
const initial =
direction === "left" ? { opacity: 0, x: -20 }
: direction === "right" ? { opacity: 0, x: 20 }
: { opacity: 0, y: 20 }
return (
<motion.div
className={className}
initial={initial}
whileInView={{ opacity: 1, x: 0, y: 0 }}
viewport={{ once: true, amount: 0.15 }}
transition={{ duration: 0.55, delay, ease: [0.22, 1, 0.36, 1] }}
>
{children}
</motion.div>
)
}
// Usage — stagger by mapping with delay={i * 0.08}
{ITEMS.map((item, i) => (
<Reveal key={item.label} delay={i * 0.08}>
{/* item content */}
</Reveal>
))}Hero load animation — animate on mount, not on scroll
Both homepage and inner page heroes use animate (fires on mount), not whileInView. Standard delay stagger: eyebrow at 0.1s, h1 at 0.2s, body at 0.3s, CTA at 0.4s.
{/* Eyebrow label — delay 0.1 */}
<motion.div
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
transition={{ duration: 0.6, delay: 0.1, ease: [0.22, 1, 0.36, 1] }}
>
{/* h1 — delay 0.2 */}
<motion.div
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
transition={{ duration: 0.6, delay: 0.2, ease: [0.22, 1, 0.36, 1] }}
>
{/* Body paragraph — delay 0.3 */}
<motion.div
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
transition={{ duration: 0.6, delay: 0.3, ease: [0.22, 1, 0.36, 1] }}
>
{/* CTA row — delay 0.4 (homepage) */}
<motion.div
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
transition={{ duration: 0.7, delay: 0.4, ease: [0.22, 1, 0.36, 1] }}
>Stagger — per-item delay in mapped lists
Three stagger patterns in use. The standard is i * 0.08 for dense lists. Capabilities uses column-modulo to avoid over-delaying bottom rows. Credibility slides in from right instead of up.
{/* Dense lists (philosophy, background items) — delay={i * 0.08} via Reveal */}
<Reveal key={item.label} delay={i * 0.08}>
{/* How We Work steps — delay: i * 0.1 */}
transition={{ duration: 0.55, delay: i * 0.1, ease: [0.22, 1, 0.36, 1] }}
{/* Capabilities grid — stagger by column only, prevents runaway delay on row 3 */}
transition={{ duration: 0.5, delay: (i % 2) * 0.08, ease: [0.22, 1, 0.36, 1] }}
{/* Credibility items — slide in from right */}
initial={{ opacity: 0, x: 24 }}
whileInView={{ opacity: 1, x: 0 }}
transition={{ duration: 0.55, delay: i * 0.1, ease: [0.22, 1, 0.36, 1] }}
{/* CTA section on blue — Reveal wrappers with explicit delays */}
<Reveal delay={0.08}> {/* h2 */}
<Reveal delay={0.16}> {/* body */}
<Reveal delay={0.24}> {/* button row */}Capabilities grid — animated divider lines
The gridlines in the capabilities section are Framer Motion elements that scale in from zero on scroll. The vertical line scales on Y (top origin), horizontal lines scale on X (left origin).
{/* Animated vertical divider — scales from top */}
<motion.div
className="hidden md:block absolute top-0 bottom-0 pointer-events-none"
style={{ left: "50%", width: "1px", backgroundColor: "rgba(0,0,0,0.07)", transformOrigin: "top" }}
initial={{ scaleY: 0 }}
whileInView={{ scaleY: 1 }}
viewport={{ once: true, amount: 0.1 }}
transition={{ duration: 0.7, ease: [0.22, 1, 0.36, 1] }}
/>
{/* Animated horizontal dividers at 33.33% and 66.66% — scales from left */}
{[33.33, 66.66].map((pct) => (
<motion.div
key={pct}
className="absolute left-0 right-0 pointer-events-none"
style={{ top: `${pct}%`, height: "1px", backgroundColor: "rgba(0,0,0,0.07)", transformOrigin: "left" }}
initial={{ scaleX: 0 }}
whileInView={{ scaleX: 1 }}
viewport={{ once: true, amount: 0.1 }}
transition={{ duration: 0.7, delay: 0.1, ease: [0.22, 1, 0.36, 1] }}
/>
))}Capabilities hover — accent bar scales from top
Each capability card uses whileHover="hovered" on the outer motion.div, with a child that responds via variants. The accent bar matches the card's top-border color.
<motion.div
whileHover="hovered"
className="p-6 relative overflow-hidden"
style={{ borderTop: `6px solid ${accent}` }}
>
{/* Accent bar — scaleY from 0 at top on hover */}
<motion.div
variants={{ hovered: { scaleY: 1 }, initial: { scaleY: 0 } }}
initial="initial"
className="absolute left-0 top-0 bottom-0 pointer-events-none"
style={{ width: "3px", backgroundColor: accent, transformOrigin: "top" }}
transition={{ duration: 0.3, ease: [0.22, 1, 0.36, 1] }}
/>
{/* card content */}
</motion.div>Hero parallax image — useScroll + useTransform
const heroRef = useRef<HTMLElement>(null)
const { scrollYProgress } = useScroll({ target: heroRef, offset: ["start start", "end start"] })
const parallaxY = useTransform(scrollYProgress, [0, 1], [0, 80])
{/* Image wrapper — scale: 1.1 prevents white edges as it shifts */}
<motion.div style={{ y: parallaxY, scale: 1.1 }} className="absolute inset-0">
<Image src="/images/hero-cityscape.jpg" fill className="object-cover" priority />
</motion.div>Cursor spotlight — hero tangerine radial gradient
Mouse offset is smoothed with useSpring (stiffness 80, damping 20) before being fed into a useMotionTemplate gradient. Initial position is off-screen (-600, -600) so no glow shows until the cursor enters.
const mouseX = useMotionValue(-600)
const mouseY = useMotionValue(-600)
const smoothX = useSpring(mouseX, { stiffness: 80, damping: 20 })
const smoothY = useSpring(mouseY, { stiffness: 80, damping: 20 })
const spotlightBg = useMotionTemplate`radial-gradient(520px circle at ${smoothX}px ${smoothY}px, rgba(252,161,125,0.09), transparent 70%)`
{/* Overlay — z-[1], pointer-events-none */}
<motion.div
className="absolute inset-0 z-[1] pointer-events-none"
style={{ background: spotlightBg }}
/>MagneticButton — spring cursor tracking
35% lerp on mouse offset. Springs: stiffness 300, damping 25. Used only on the homepage final CTA. The button is rounded-full — one of only two deliberate pill shapes in the system (the other being the hero CTA pair).
function MagneticButton({ children, href }: { children: React.ReactNode; href: string }) {
const ref = useRef<HTMLDivElement>(null)
const x = useMotionValue(0)
const y = useMotionValue(0)
const springX = useSpring(x, { stiffness: 300, damping: 25 })
const springY = useSpring(y, { stiffness: 300, damping: 25 })
const handleMouseMove = (e: React.MouseEvent) => {
const rect = ref.current?.getBoundingClientRect()
if (!rect) return
x.set((e.clientX - (rect.left + rect.width / 2)) * 0.35) // 35% lerp
y.set((e.clientY - (rect.top + rect.height / 2)) * 0.35)
}
return (
<motion.div
ref={ref}
style={{ x: springX, y: springY, display: "inline-block" }}
onMouseMove={handleMouseMove}
onMouseLeave={() => { x.set(0); y.set(0) }}
>
<Link href={href}>
<Button size="lg" className="rounded-full px-10 py-6 text-base font-semibold
bg-brand-tangerine text-brand-black hover:bg-brand-blue hover:text-brand-ivory
transition-colors duration-300">
{children}
</Button>
</Link>
</motion.div>
)
}Ticker band — Framer Motion infinite scroll
Uses animate: x: ["0%", "-50%"] rather than a CSS keyframe. Items are duplicated once (2 copies) for a seamless loop. The pinned label does not scroll — it sits outside the motion track. Duration: 28s.
<section className="overflow-hidden py-3" style={{ backgroundColor: "#fca17d" }}>
<div className="flex items-baseline gap-6 whitespace-nowrap">
{/* Pinned label — not scrolling */}
<span
className="pl-8 md:pl-14 lg:pl-20 text-[8px] font-bold tracking-widest uppercase shrink-0"
style={{ color: "rgba(0,0,0,0.42)" }}
>
Active focus areas
</span>
{/* Scrolling track */}
<div className="relative flex overflow-hidden">
<motion.div
className="flex gap-8 shrink-0"
animate={{ x: ["0%", "-50%"] }}
transition={{ duration: 28, ease: "linear", repeat: Infinity }}
>
{[...Array(2)].map((_, rep) => (
<span key={rep} className="flex gap-8 shrink-0 text-xs" style={{ color: "rgba(0,0,0,0.70)" }}>
{ITEMS.map((item) => (
<span key={item} className="shrink-0">
{item}<span className="mx-4" style={{ color: "rgba(0,0,0,0.30)" }}>·</span>
</span>
))}
</span>
))}
</motion.div>
</div>
</div>
</section>Homepage Composition
Hero — layer stack (bottom to top)
Height: clamp(560px, 80vh, 760px).
[1]Parallax image (scale 1.1, y from useScroll → useTransform)[2]Gradient overlay: 105deg, rgba(0,0,0,0.88) → rgba(0,0,0,0.65) → rgba(0,71,187,0.30)[3]Cursor spotlight: z-[1], pointer-events-none[4]Dot-grid texture: z-[1], pointer-events-none, 28px grid[5]Text content: z-[2], absolute inset-0 flex items-center[6]Coordinate easter egg: z-[2], absolute bottom-14 right-8 md:right-14 lg:right-20[7]Angled blue edge: z-[2], absolute bottom-0, height 48px
<section
ref={heroRef}
className="relative w-full overflow-hidden"
style={{ height: "clamp(560px, 80vh, 760px)" }}
onMouseMove={handleHeroMouseMove}
onMouseLeave={handleHeroMouseLeave}
>
{/* [1] Parallax image */}
<motion.div style={{ y: parallaxY, scale: 1.1 }} className="absolute inset-0"> ... </motion.div>
{/* [2] Gradient overlay */}
<div className="absolute inset-0"
style={{ background: "linear-gradient(105deg, rgba(0,0,0,0.88) 0%, rgba(0,0,0,0.65) 50%, rgba(0,71,187,0.30) 100%)" }} />
{/* [3] Cursor spotlight — z-[1] */}
{/* [4] Dot-grid texture — z-[1] */}
{/* [5] Text */}
<div className="absolute inset-0 flex items-center z-[2]">
<div className="px-8 md:px-14 lg:px-20 max-w-3xl">
{/* motion.h1, motion.p, motion.div (CTA row) with staggered animate delays */}
</div>
</div>
{/* [6] Coordinate easter egg — z-[2] */}
{/* [7] Angled blue edge — z-[2], clipPath: "polygon(0 100%, 100% 100%, 100% 0%, 0 100%)" */}
</section>Full homepage section order
- [1]Hero (full-bleed image, overlay, parallax) — clamp(560px, 80vh, 760px)
- [2]Positioning band (blue, py-16) — single serif sentence at font-weight 400
- [3]Capabilities section (ivory, py-12) — label + 3×2 grid with animated dividers
- [4]How We Work (tea-green parallelogram) — 3-col steps
- [5]Credibility (ivory, py-16) — 2-col with logo watermark
- [6]Ticker band (tangerine, py-3) — scrolling focus areas
- [7]Final CTA (blue, py-24, centered) — MagneticButton, dot-grid texture
Credibility section — logo watermark
logo-square.png at 7% opacity, absolutely positioned center-right, behind content (z-0). Content sits at z-[1]. The watermark is decorative — no alt text.
<section className="bg-brand-ivory px-8 md:px-14 lg:px-20 py-16 relative overflow-hidden">
{/* Watermark */}
<div
className="absolute right-36 md:right-48 top-1/2 -translate-y-1/2 z-0 pointer-events-none"
style={{ opacity: 0.07 }}
>
<Image src="/images/logo-square.png" alt="" width={220} height={220} />
</div>
{/* Content — must be z-[1] to sit above watermark */}
<div className="grid grid-cols-1 md:grid-cols-2 gap-6 relative z-[1] items-center">
{/* Reveal-wrapped heading + body left, credibility border-bar items right */}
</div>
</section>Easter Egg
Oxford coordinates — hero bottom-right
The coordinates 51.7519° N 1.2578° W reference The Bear pub in Oxford, England. They appear in the hero at 28% ivory opacity — barely legible, a quiet nod to the brand's intellectual character. Fades in on mount with a 1.0s delay (not on scroll).
{/* Fades in on mount with 1.0s delay — not scroll-triggered */}
<motion.div
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
transition={{ duration: 1.2, delay: 1.0 }}
className="absolute bottom-14 right-8 md:right-14 lg:right-20 z-[2] text-right pointer-events-none select-none"
>
<p className="font-mono text-[9px] tracking-widest" style={{ color: "rgba(255,255,242,0.28)" }}>
51.7519° N 1.2578° W
</p>
</motion.div>Logo Usage

Main
General use

Header
Navigation bar

Footer
Footer compact

Square
Social / watermark

Banner
Wide banners
Do
- ✓ Maintain clear space equal to the logo height
- ✓ Use approved variants only
- ✓ Ensure adequate contrast with background
- ✓ Scale proportionally at all times
Don't
- × Stretch or distort the logo
- × Recolor outside approved palette
- × Place on busy or low-contrast backgrounds
- × Recreate or modify any element
Internal document
Questions about the design system?
This handbook is the canonical reference. If a pattern is not documented here, default to Bold/Geometric + Sparse/Authoritative: serif headings, ivory background, colors as accents only. When in doubt, look at ClientPage.tsx (homepage) and AboutClientPage.tsx (inner page) — they are always the ground truth.