The Firefly design system
A first pass at documenting Firefly Partners' visual language as tokens and components — built from what's already live in the site's codebase, and complemented by the shared brand book and moodboard, ready to react to and revise together.
Logo
Per the 2024 Brand Book: minimum clear space equals the width/height of the light element; minimum size 32px on screen, 10mm in print; always retain proportions.
Full lockup on approved backgrounds
Pictogram alone
Color
Semantic aliases point at a primitive for a specific job — surfaces, text, states — so a color's meaning can be looked up by name instead of memorized by hex.
Primitives
Semantic — surfaces & text
Semantic — states
Typography
Three families, three jobs: Stabil Grotesk carries reading text, Monosten labels and technical metadata, Monosten Stencil is reserved for shouted emphasis. This page renders system fallbacks — open it inside the repo to see the real faces.
Type scale — Stabil Grotesk
Monosten — labels & metadata
Monosten Stencil — emphasis only
Graphic elements
Marks, shapes, and badge treatments from the Moodboard Integration Proposal.
Icons
Small functional marks.
Firefly Arrow motif
Hand-drawn accent marks
Proposal: pick one per emphasis (the underline is the safest default), never stack several on one page.
Color on an accent mark
Propose a color for a mark by checking it against the background it sits on — the same rule already used for text on accent colors — rather than picking freely. A mark keyed to its container's background can land on a color it disappears into or fights with if that check is skipped.
| Background | Works well | Avoid |
|---|---|---|
| White / light-gray | Off-black, orange, mid-gray | Yellow (fails contrast) |
| Orange | Off-black, white | Yellow (fails contrast — see Accessibility) |
| Yellow | Off-black, mid-gray | Orange, white (both fail contrast) |
| Off-black | White, yellow, light-purple | Orange (fails contrast), mid-gray |
| Purple / light-purple | Off-black only | Yellow, orange, white (all fail contrast) |
<svg> with fill="currentColor" — so a single color value on a container recolors the mark, per the table above. No separate asset swap needed per color.Tag pills
Open question: would tag pills actually be needed for taxonomies (e.g. categorizing projects or articles), or is this shape only useful as the in-text highlight below? Confirm the use case before treating this as a component.
Sector pills (white background, off-black text) and Platform pills (off-black background, white text):
Pill highlight, in text
A second use of the same pill shape: not a taxonomy tag, but a solid-color highlight behind one word inside a sentence — the same job the yellow <mark> does in this page's own H1. This gives that treatment more colors to choose from, under the same contrast rule as accent marks: check the pill color against its background rather than picking it freely.
Where digital strategy meets progressive passion.
An outline-only variant, for a lighter touch where a solid fill feels too heavy.
Where digital strategy meets progressive passion.
Accent mark, applied
One mark, one job: underline a single emphasized word in a featured headline. Never more than once per page. Applied here to a real headline already live on the site (index.astro, the .radical__heading block).
Let's change
your tech,
RADICALLY
Second example — Homepage hero
The same swap applied to the live homepage hero (index.astro) — replacing .hero__underline's text-decoration: underline with the real accent mark on "slipping." Off-black is used here, not white, since the hero's own heading color is already off-black (per the pairing table: off-black is one of the two allowed marks on an orange background).
Serving mission-driven organizations since 2007
Your tools don't talk to each other. Your fundraising is slipping.
And now AI showed up.
We can help.
.hero__underline{ text-decoration: underline; } is replaced by the accent-mark SVG positioned under the word — everything else in the hero (copy, layout, CTAs) stays untouched.Organic-shape image mask
Three real clip-path shapes from the shared reference files. Proposal: we can build a two-layer system, not a single crop — a mask clips the base photo, and a second, separately-cropped overlay photo is placed so it appears to break out of the mask's edge. Each mask would be a reusable component; the overlay image would need to be prepared by hand before upload each time.
Spacing & radius
The live site uses a fluid Utopia scale (values shift with viewport width) — shown here at their minimum, mobile-width value. Always use a token; a hardcoded px/rem value is the exception, not the rule.
Spacing
Radius
Buttons
Sourced from the live repo — .nav-link / .btn-primary and .home-logo in Header.astro, plus .hero__secondary-cta in index.astro. Primary and Secondary are the same two colors in opposite order; Link is the lowest-emphasis action in a group.
Primary
Off-black background, yellow text — used for nav pills and the site's main CTAs.
Secondary
The same pairing, inverted — yellow background, off-black text. Used for the home icon pill in the header.
Link
Underlined text, no background — the lowest-emphasis action in a group, like "See Our Work" next to the hero's primary CTA.
Play Episode
Sourced from untangled.astro — .episode__play. Off-black background, white mono text, a play-triangle icon. A distinct pattern from Primary/Secondary: hover doesn't invert color, it dims to 85% opacity.
Subscribe
Sourced from untangled.astro — .newsletter-cta__btn. Orange background, white text — used only on the dark newsletter card, next to an email field. Same opacity-dim hover as Play Episode, not the off-black/yellow inversion pattern.
Text inputs
Used in the slide-up contact form and the newsletter block. A 1.5px border keeps focus/error states visible without relying on color alone.
Checkbox
Used in the contact form's "Type of project" group (AI Adoption, Digital Tools, Website, Strategy & Performance, Other).
Cards
Sourced from the live repo — .card.article-card in resources/articles.astro. Image thumbnail, mono uppercase tag in orange, title, excerpt, and a meta row (author · date · read time). Hover adds a soft shadow, no border-color change.
Nav bar
Sourced from the live repo — Header.astro. White surface, rounded only at the bottom corners; off-black pills with yellow text for nav links, a yellow pill for the home icon and Get Started CTA.
Accessibility
WCAG 2.1 AA is the project's stated minimum (per the Functional Spec). The pairings below are the ones actually in use — check any new pairing before shipping it.
| Pairing | Preview | Ratio | Result |
|---|---|---|---|
| Off-black on white | Aa | 18.1:1 | AAA |
| Mid-gray on white | Aa | 6.3:1 | AA |
| Off-black on orange | Aa | 7.2:1 | AAA |
| White on orange | Aa | 2.9:1 | Fails AA |
| Off-black on yellow | Aa | 10.9:1 | AAA |
| White on off-black | Aa | 18.1:1 | AAA |
--text-on-accent (off-black), never white — white-on-orange fails AA at 2.9:1.Do's & don'ts
The short version of the rules already written into CONTRIBUTING.md and the "holistic, not bolted-on" principle from the design system plan.
Add a new visual pattern as a shared token or component first, then use it everywhere it applies.
Style a one-off element directly on a single page — it's the fastest way to end up with the same thing looking different in three places.
Use white or off-black text on orange/yellow accents.
Put white text on orange — it fails contrast at 2.9:1.
Reach for a spacing token (--space-*) for every margin, padding, and gap.
Hardcode a px/rem value when a token already fits — per the project's own CSS rules.
How to apply this
No new tool, no Figma — this system is applied by talking to Claude Code the same way you'd talk to a builder. These four steps are what keep a new style from ending up bolted onto just one page.
Name the pattern
Before adding anything new, describe it in one line — "a swoosh underline for one emphasized word in a headline," not "make it more playful."
Ask for it as a shared token or component
Tell Claude to add it to design-system.css / global.css, or as its own component — never written directly into one page's markup.
Apply it everywhere it belongs
Once it exists as a shared piece, every page that needs it references the same definition — so it reads as one decision, not several.
Audit before calling it done
Check 2–3 pages where it should appear and confirm it looks identical everywhere — that's the whole test.
The instruction that matters most
Say this explicitly, every time — it's the difference between a shared style and a one-off:
Vague vs. specific
"Make the homepage more playful."
"Add the swoosh accent mark under 'real behavior' in the hero headline, as a shared component."
"Use one of the moodboard tag colors here."
"Use the orange tag pill style from the design system on this Article card's topic tag."