Internal · v1.0 · aligned to docs/design-system-audit.md
The Firewire design system.
Every page on firewiredigital.com.au has to match the standard set here. If a component drifts from these tokens, treat it as a bug.
01 · Typography
Plus Jakarta Sans & Instrument Serif italic
Accent treatment
Wrap accent words in .accent to get italic Instrument Serif emphasis.
Weights & rules
Headlines
500 Medium
600 SemiBold
Never 700+. Tracking tight: -0.02 to -0.035em. Line height 1.02 to 1.1.
Body
400 Regular for reading.
500 Medium for slight lift.
Never SemiBold or Bold in body: weight is reserved for hierarchy. Line height 1.5 to 1.65.
Labels
Eyebrows, CTAs, metric labels: 600.
Captions and fine print: 500 in muted grey.
Sentence case for headlines. All-caps lives only on over-labels in cards (12-MONTH TREND).
02 · Colour
Surface, ink, and one flame.
The flame gradient, used for CTAs and key callouts only.
linear-gradient(135deg, #ff6503 0%, #ffb43c 100%)
Text tokens: fg-* on dark, ink-* on light
The quick brown fox
--fg-strong · Headlines on dark
The quick brown fox
--fg-default · Body on dark
The quick brown fox
--fg-muted · Secondary body on dark
The quick brown fox
--fg-subtle · Fine print on dark. #84847f since the 2026-06-07 a11y sweep: AA on page + card surfaces
The quick brown fox
--fg-accent · Inline orange highlight
The quick brown fox
--ink-strong · Headlines on light
The quick brown fox
--ink-muted · Body on light
The quick brown fox
--ink-subtle · Captions on light
Secondary palette: selective accents only
Logo halos, chart strokes, small decorative moments. Never headline text in primary brand contexts.
Borders: hairline by default
--border
rgba(255,255,255,0.06) · default divider on dark
--border-emphasis
rgba(255,255,255,0.10) · emphasised container
--border-accent
rgba(255,100,0,0.20) · hover/focus state
03 · Spacing
4 px base · scale up by t-shirt.
Section rhythm
--section-rhythm = 120 px between major sections. --space-40 (160 px) is reserved for hero and closer moments only.
Container
--container-max = 1280 px. Gutters: 32 px default, 48 px at lg. Brand.md says 1400; the designed pages hold 1280.
Card interiors
Card padding 24 to 32 px. Inter-card grid gap 16 px. Two-column section gap 48 to 64 px. Icon-to-label 8 to 12 px.
04 · Radii
Soft corners, never floating.
r-xs
3px
Pixel tiles
r-sm
6px
Inputs, small chips
r-md
12px
Inner card surfaces
r-lg
16px
Default card
r-xl
24px
Large feature card
r-2xl
32px
Hero container
r-full
9999px
Pills, nav, dots
05 · Shadows
Whitespace and borders first. Shadows only float.
The system prefers hairline borders over elevation. Shadows appear only on floating or overlapping elements. Never inner shadows; never a drop shadow on the logo (prohibited by brand); never heavy ambient washes.
--shadow-card
0 1px 2px rgba(0,0,0,0.3) · minimal lift, rare
--shadow-float
0 8px 30px rgba(0,0,0,0.35) · phone mockups, overlapping moments
--shadow-cta
0 14px 40px rgba(255,100,3,0.30) · primary CTA glow, selective
06 · Primitives
Built once, used everywhere.
Live components from src/components/primitives/. Each variant below is the real component: if it drifts here, it drifts everywhere.
Button: variants & sizes
Primary · md
Book a strategy callSecondary · md
See the workGhost · md
Learn morePrimary · sm
CompactPrimary · lg
Take the next stepNo arrow
Plain labelEyebrow: variants
Dot (default)
Case study · Hamilton JankeTile
Our servicesPlain
ResultsTag: tones
InlineLink: tones
Read the Hamilton Janke case study , or jump straight to our Newcastle SEO service page .
MetricBlock: sizes
Compact
Default
Large
Card: variants
Default
Default card surface, bg-elevated with a hairline border. Use for grouped content blocks.
Accent
Accent border for emphasis. Same surface, fire orange tint on the edge.
Interactive (link)
Hover me: borders shift, slight lift. Used when the whole card is clickable.
PullQuote: default
The point of the styleguide isn't aesthetics. It's so every page on the site already agrees with itself before anyone has to argue about it.
Arrow: sizes
PixelCluster: decorative motif
Sparkline: small inline trend
Single-line micro-chart for in-flow stats, different to the larger BackdropSparkline which sits behind card content.
Container: page-width wrapper
Centres content to --container-max (1280 px) with horizontal gutter padding. Use as <Container>...</Container> anywhere a section needs the standard reading width.
07 · Motion
One curve. No springs.
Default easing: --ease-out (cubic-bezier(0.16, 1, 0.3, 1)). Durations: --dur-fast (200 ms), --dur-base (500 ms), --dur-slow (700 ms). Reduced-motion is respected globally.
Reveal on scroll
Wrap a section in .fw-reveal. The shared IntersectionObserver in BaseLayout adds .is-in when it enters the viewport: 40 px lift + opacity 0 → 1 over 800 ms.
opacity 0 → 1
translateY(40 → 0)
800 ms, staggered
--ease-out throughout
CountUp
<CountUp value=252 suffix="%" /> eases from 0 to the target over 1.4 s when the element enters the viewport. Supports prefix, suffix, decimals, and surface="dark|light". Easing is 1 − (1 − t)³.
Organic growth
Client revenue influenced
Lead volume
Marquee
Edge-faded marquee for client logos. ~40 s linear loop. Hover pauses it.
Hover affordances
Border shift + lift on cards. Arrow tile scale on CTAs. The one playful moment: mark rotates 45 → 405° over 700 ms.
Hover me. Border colour shifts to --border-accent; card lifts 2 px.
Hover the icon.
08 · Iconography
Inline SVG only. Two-pixel strokes, rounded ends.
No icon font, no library. Stroke 2 → 2.2 px with stroke-linecap="round" + stroke-linejoin="round". The canonical CTA arrow path is locked and must not be substituted.
M7 17L17 7M17 7H7M17 7v10 1.5 / 2 / 2.2 / 3: only the middle two are in-system.
Emoji as icons. Unicode glyphs as icons. Drop-shadows on the logo mark. Any rotation or recolour of the brand mark itself.
09 · Z-index
Named layers. Never raw numbers.
Stacking is named, not numerical. Reach for a higher layer? Add it to the scale in tokens.css, don't free-handedly type z-index: 9999.
10 · Polish kit
The patterns the homepage lives on.
Eight composable primitives lifted from the homepage's polish pass. Import any of them on any page, and every other page picks up the same gradient, the same rotation, the same easing as the homepage. If you find yourself hand-rolling a polaroid or a brand-tint card, reach for these instead.
Polaroid
Rotated card with orange tape detail and a square portrait area. <Polaroid name="..." width=440>: pass mono for grayscale; place the portrait in the slot="portrait" slot and put meta in the default slot.
RadialTile
Square tile with a radial-orange backdrop. Used on the Methodology "Outcome" card. <RadialTile size=124 intensity="medium"> supports low / medium / high intensity and optional bordered hairline.
BrandTintCard
Feature card with orange-tint gradient + orange hairline border. Used for the StrategistCta box and blog newsletter card. Renders as <a> when given an href, otherwise <div>.
The closing CTA pattern.
Use this any time a section wants to feel like an invitation. The gradient does the work; keep the content sparse.
PillLink
Secondary CTA pill, sits next to a primary <Button>. arrow="forward" (default, →) or arrow="down" (↓) for in-page anchor jumps.
PulseDot
Gently pulsing orange dot. Use for live status indicators (availability, "active engagement", "online"). Animation is @keyframes fw-pulse from global.css; honours prefers-reduced-motion.
BackdropSparkline
Trend curve rendered as a card backdrop, sits behind a CountUp or headline number. Used by the 3 Results client cards on the homepage. Path is computed server-side from a points array (0..1), so the curve renders correct on first paint with no client JS.
SectionHeader
Eyebrow + h2 + lede block, the prototype's signature section-opener. Three variants: split (default), centred, and stacked.
The 1.4fr / 1fr section opener.
Headline left, supporting paragraph right with end-aligned baselines. The pattern used on Methodology, Results, Team, and Testimonials.
Compare-style centred header.
Eyebrow + headline + lede stacked, all centre-aligned. Use for comparison tables, contrasts, and "set the stage" moments.
RomanDot: class, not component
Use <span class="roman-dot">.</span> immediately after an italic .accent word to keep the period upright instead of slanting with the serif. Inherits currentColor, so it works on dark or light surfaces.
Earned Presence.
Earned Presence.
11 · Global atmosphere
Effects that live on every page.
Three site-wide effects ship via BaseLayout. You can't opt out, but you can see them at work just by moving your cursor or scrolling.
A 460 px radial of rgba(255,100,3,0.10) tracks the cursor via --fw-pointer-x/y. Hover devices only; bypassed on touch + under prefers-reduced-motion.
body::before with a faint amber radial at 80% / 80%, mix-blend-mode: screen. Lifts the darks just enough to stop the page reading flat.
Wrap a section in .fw-reveal. The shared observer in BaseLayout adds .is-in when it enters. 40 px lift + opacity 0 → 1 over 800 ms.
12 · Brand assets
Every lockup, every variant.
All sourced from /public/brand/. The dark site header uses FWD_LOGO_W+COLOUR.svg; the light footer uses FWD_LOGO_B+COLOUR.svg; the favicon is FWD_ICON_COLOUR (the orange peaks stay legible on both light and dark browser tabs). Don't recolour. Don't rotate. Don't reconstruct the mark from primitives: these SVGs are the only sanctioned files.
Full logo lockups: mark + wordmark
FWD_LOGO_W+COLOUR.svg
Header, dark surfaces
FWD_LOGO_B+COLOUR.svg
Footer, light surfaces
Mark: peaks only
FWD_ICON_COLOUR.svg
Hero accents, AI module callouts
FWD_ICON_WHITE.svg
Mono, dark surfaces, gradient suppressed
Wordmark: text only
FWD_WORDMARK_WHITE.svg
Dark surfaces, mark suppressed
FWD_WORDMARK_BLACK.svg
Light surfaces, mark suppressed
FW lettermark: favicon + tight spaces
FWD_FWICON_W+COLOUR.svg
Social avatar · tight spaces
FWD_FWICON_B+COLOUR.svg
Social avatar on light surfaces
13 · Decisions locked
The audit's open flags, resolved.
The design-system audit closed with five open flags. Every one is now a locked decision (CLAUDE.md is the record). Don't re-litigate them here.
Container width
1280 px. Brand.md says 1400; every designed page targets 1280, so 1280 holds.
Section rhythm
120 px default. 160 px (--space-40) reserved for hero and closer sections.
Italic emphasis
Canonised. Instrument Serif italic via .accent is the only display serif. DM Serif Display is dead.
Page background
#0b0b0e. The earlier #111114 and #0a0a0c values are gone from the system.
Copy rules
Sentence case headlines. No em-dashes in copy. En-dash only for date and number ranges. Title suffix is | Firewire.
Contrast floor
WCAG AA. --fg-subtle is #84847f (4.5:1+ on page and card). Don't reintroduce #5d5d5b on dark surfaces.