Visual &
motion
system

Everything the homepage, case-study template and contact page are built from. Palette and type come from the logo: an angular geometric wordmark, red/olive/gold stripes on a black or white field. We kept the four colours, made paper the default light surface, and added one display face with the same cut-corner energy.

Homepage →   Case study →   Contact →

01 Colour

From the logo
Aa
Ink
#0C0B09
Dark surface, text on paper, strokes
Aa
Paper
#F3EDE1
Light surface, text on ink
Aa
Red
#C7351F
Primary accent · CTA field · cursor
Aa
Gold
#F2A51A
Labels on ink · fills · notes
Aa
Olive
#7E8B2C
Duotone · strokes · shadows
Aa
Ink 60
rgba(12,11,9,.65)
Secondary text on paper (Paper 60 on ink)
Dark surface (Ink)Manifesto, services, partners, footer. Text is Paper; accent labels are Gold (9.7:1); Red is for underlines and shapes only — never body text on ink (3.9:1).
Light surface (Paper)Hero, work, process. Text is Ink; accent labels Red (5.1:1); Olive works for large type only (3.6:1). Gold is a fill colour, not a text colour, on paper.
Red fieldOne per page, for the closing CTA. Paper text (5.1:1 — headline scale) with Ink strokes and punctuation. Sections alternate Paper → Ink → Paper → Ink → Paper → Ink → Red → Ink.

02 Typography

Big Shoulders Display + DM Sans (Google Fonts, variable)
Display XLclamp(64px,11.5vw,184px) · .9 · 700/900Art is the
Display Lclamp(48px,7vw,120px) · .9 · 900+500 mixSelected work
Display Mclamp(34px,4.6vw,76px) · 1.02 · 500We are four partners
Titleclamp(26px,2.4vw,36px) · 1 · 700Beyond The Hustle
Ledeclamp(16px,1.4vw,21px) · 1.45 · 300A four-partner design and engineering studio in Accra.
Body14–15px · 1.5–1.6 · 400Weekly releases on a real URL. You click it on your phone.
Label11–13px · .14–.16em · 500 · caps02 — Six pieces · 2023 → 2026
NumeralDisplay 900, any size4 · 30+ · −40% · ₵12
Display
pairs with

DM Sans at 300 for lede paragraphs, 400 for body, 500 for labels. Optical size axis on: small text renders wider.

Rules. Display is always uppercase above 36px, mixed case below. Weight is a voice: 500 speaks, 700 states, 900 shouts — mix them within one headline (see "Selected WORK"). Body never exceeds 68ch. Labels are 11–13px, 0.14–0.16em tracking, uppercase. Numerals in display, always.

Why these. Big Shoulders' narrow, cut-corner letters echo the logo's angular A and R without copying it. DM Sans is neutral enough to disappear next to it, and has the Ghanaian cedi sign.

03 Texture & pattern

Abstracted, not quoted

References: Adinkra stamp repetition, kente warp stripes, Bogolan mud-cloth grids, market signwriting, screen-printed posters. What we keep is the logic — hand-made repetition, misregistration, bold flat colour — never the motifs themselves.

T1 Paper grain
SVG feTurbulence, multiply, 25–35% opacity. Every light surface. Shader: 1 octave noise, cheap.
T2 Halftone
6px cell on portraits, 5px on posters. In WebGL: dot size from luminance. Hover shrinks cell → photo resolves.
T3 Warp stripes
The logo's diagonal, unequal stripe rhythm. Dividers, preloader wipe, image frames. Never as wallpaper.
T4 Brush marks
Seeded quadratic strokes, 4 colours, round caps, multiply. Hero, process cards, CTA, contact. Max 4 per view.
T5 Stamp grid
Adinkra-logic repetition with our own abstract glyphs. 404 page, loading states, section numbers.
ART
T6 Misregistration
Offset colour plates ±4–8px on display type. Hover state for section titles; preloader wordmark.

04 Grid & spacing

12 columns, gutter clamp(16px, 2vw, 32px), page margin clamp(20px, 4vw, 56px). Max content width: none — type scales with vw and caps in px.

Spacing scale 4 · 8 · 12 · 16 · 24 · 32 · 48 · 64 · 88 · 120 · 150 · 180. Section padding clamp(72px, 10vw, 150px).

Breaking the grid, deliberately. Work pieces may rotate ±2°, offset vertically by 40–140px, and hang 8–16px hard shadows in a logo colour. Brush marks ignore the grid entirely. Rules: at most one rotated element per viewport, and text never rotates.

Mobile collapses to 4 columns, 16px gutter, 20px margin; rotations drop to ±1°, offsets to 24px.

05 Components

Nav
ARTFRICA.WorkStudioServicesContact ↗

Fixed, mix-blend-mode: difference so it inverts over any surface. Wordmark text, not image (the logo lives in hero and footer). Active link underlined in red. Hides on scroll-down, returns on scroll-up (300ms).

Buttons
Primary Secondary Chip

Pill, 44px min height. The dot is the signature: it's the logo's colour stripes reduced to one point. Hover: fill swaps ink↔paper (300ms), dot scales 1→1.4 with overshoot. Magnetic ±6px within 40px radius.

Links

Underline is a 1.5px border, not text-decoration. Hover: underline slides out left and back in from right (400ms, expo), colour → red. Nav links: text splits and rolls up (the classic), 350ms.

Image frames

Four treatments: Tilt + hard shadow, Duotone + halftone, Colour block with one radius corner, Browser frame. Never two of the same treatment adjacent.

Cursor

14px red dot, mix-blend difference, lerp 0.18 (slightly behind the pointer — a brush following a hand). Over links: 40px paper ring. Over work: 88px gold disc with a verb. Hidden on touch devices and when a native cursor is needed (inputs).

06 Motion system

GSAP + ScrollTrigger · Lenis · R3F

One idea: a hand making marks, then a machine finishing them. Entrances are drawn or wiped (organic, decelerating); interactions are crisp and mechanical (short, springy). Two easings only: expo.out / cubic-bezier(.2,.9,.2,1) for arrivals, cubic-bezier(.7,0,.2,1) for wipes and exits. Lenis lerp 0.08. Yellow M-tags on the homepage point to each entry below (press n on the homepage to show them).

M0PreloaderPaper screen. A single ink stroke draws left→right (0.8s), splits into red/olive/gold plates that wipe down the logo diagonal (T3), revealing the page. Counter 0→100 in Display 900 bottom-left. Shown once per session; later visits skip to the hero draw-on.First route load1.4s total · expo.out draw, cubic-bezier(.7,0,.2,1) wipesA hand starts, the machine finishes. Sets the whole thesis in the first second.
M1HeroFour seeded strokes draw via stroke-dashoffset in sequence; headline lines slide up 30px behind them; cursor-dot blinks last. Tier 1: WebGL brush with velocity width and paper bleed; visitor can drag to paint a fifth stroke (fades after 6s).After preloader · mousedown/drag1.6 → 1.0s decelerating, 400ms stagger · headline 1s expo.outEvery visit is a new painting. Generative = "Art", drag = "you can touch it".
M1bHero exitStrokes parallax at 0.4/0.7/1.0/1.2× and bleed 200px into the black manifesto section; headline fades to 0 at 60% scroll.ScrollTrigger scrub, hero → manifestoscrub 0.5 (Lenis lerp .08)Sections are one continuous canvas, not slides.
M2ManifestoSection pins for 150vh. Words step from 20% to 100% opacity in reading order; "four partners" and the underline draw last. Three numerals count up.Pin at section topscrub, linear per word · counts 1.2s expo.outSlows the reader down for the one paragraph that matters.
M3Work gridPieces enter with clip-path inset wipe from bottom (0.9s) and hold individual y-parallax (data-speed .8–1.3). Hover: GLSL ripple follows pointer (uStrength .12, decay 500ms), duotone → colour 600ms, image scale 1.04 over 1.2s, cursor → 88px gold VIEW. Click: image FLIPs to case-study hero.Enter 20% viewport · pointer · clickwipe .9s cubic-bezier(.7,0,.2,1) · hover 600ms · FLIP .9s power4.inOutEach project is a framed print; hover lifts it off the wall.
M4Services listRows rise 40px with 60ms stagger. Hover: row inverts paper/ink, weight tweens 500→900 (variable font), a floating thumbnail (last project of that service) follows the cursor at lerp .12. Row number rolls like an odometer.Enter 30% viewport · hover.8s power3.out · hover 400msA typographic list that behaves like a poster wall being read.
M5Process (horizontal)Desktop ≥1024: section pins, vertical scroll maps to x translate of the card row; each card's brush mark draws on as it passes 40% of viewport; cards tilt ±1.5° toward scroll direction. Mobile: native horizontal scroll with snap, no pin.Pin, scrubscrub .6 · marks .8s expo.out"How we work" is a walk along a wall of sketches.
M6PartnersDuotone + halftone via shader (T2). Cards drift on scroll at alternating rates (0 / +40px). Hover: halftone cell 6px→2px, photo resolves to grayscale, name underlines in that partner's colour.Scroll · hover500ms expo.outPortraits as prints, people as the medium.
M7CTARed field wipes up over the partners section (clip-path); the ink stroke draws across; headline words rise. Hover on headline: colour → gold and a magnetic pull of ±10px toward the cursor.Enter 10% viewport · hoverwipe 1s cubic-bezier(.7,0,.2,1) · magnetic lerp .15The loudest moment on the page, in the logo's loudest colour.
M8Cursor14px red dot, mix-blend difference, trails the pointer at lerp .18. States: 40px paper ring on links, 88px gold disc with verb on work/CTA, hidden over inputs and on touch.Always (pointer: fine only)state change 250ms cubic-bezier(.2,.9,.2,1)A brush tip that follows the hand.
M9Nav & buttonsNav hides on scroll-down, returns on up (translateY, 300ms). Link hover: text rolls up 100% revealing a red duplicate. Buttons: fill swap ink↔paper, dot scales 1→1.4 with overshoot; magnetic ±6px within 40px.Scroll direction · hover300–350ms · dot back.out(2)Mechanical precision against the organic entrances.
M10Route transitionLeaving: paper curtain wipes up from bottom while current page scales to .96. Arriving: curtain wipes off upward; for work→case-study the clicked image FLIPs into the hero slot and the title letters rise. Lenis resets to top under the curtain.Next.js route change (template.tsx + GSAP)out .5s / in .7s cubic-bezier(.7,0,.2,1) · FLIP .9sPages turn like sheets of paper on a desk.

07 Mobile

Hero · Work · Services at 390px
ARTFRICA.Menu

Art is the
interface

A four-partner design and engineering studio in Accra. Every mark here was drawn fresh when you arrived.

Selected work ↓Redraw ↻

Selected
work

Six pieces
swipe →
Somavi
School OS · Product + web app
Beyond The Hustle
MenundaReal estate
03 — What we doTap a line
01Web design
02Product / UI design
03Web & app dev
04AI integration
05Branding
06Motion & 3D
07E-commerce
08Consulting

Tap opens the line to a two-line description and a "Start →" link. No hover states on touch; the row inverts on press instead.

08 Accessibility & performance

Reduced motionprefers-reduced-motion: strokes render complete, no draw-on; no pinning, no parallax, no horizontal hijack; marquees stop; page transitions become 200ms cross-fades; custom cursor off. Everything remains reachable by scrolling. A visible "Motion: on/off" toggle in the footer overrides either way.
Contrast & inputInk/Paper 15.6:1 both ways. Gold on Ink 9.7:1, Red on Paper 5.1:1 (labels ≥12px). Red text never on Ink; Olive never as body text. Focus: 2px red outline offset 4px, always visible. Custom cursor never replaces focus. Nav "difference" blend: checked against every surface it crosses; falls back to solid on unsupported browsers.
Degradation ladderTier 1 (desktop GPU): WebGL brush, image ripple, halftone shader. Tier 2 (mid mobile, or navigator.hardwareConcurrency ≤ 4): SVG strokes, CSS duotone, no ripple. Tier 3 (no WebGL / save-data): static SVG strokes, plain images. Detect once on load; never switch mid-session.
BudgetsFonts: two variable files, subset Latin, ≤ 90 KB total, font-display: swap with size-adjusted fallbacks so the hero doesn't reflow. Hero LCP under 2.5s on 3G: the headline is text; strokes are inline SVG (no request). Work images: AVIF, 1600w, lazy below the fold, blur-up in a logo colour. Three.js loaded only on Tier 1, after first paint. Cap DPR at 1.5.