One system, every surface.
The source of truth for the Nominate.AI brand - on this site and across the platform. Every swatch and component renders from the same CSS custom properties and classes the rest of the site uses; change a token in v3.css and this guide updates itself. Fonts and icons come off our own CDN. Tokens over hex, always.
Monroe is the mark.
A circular pixel-art medallion - the Nominate.AI logo, the favicon, the whole identity. The same portrait reads on cream and on navy; a faint halo lifts it off the dark ground. It's public/logo.png; the circular treatment lives in v3.css.


Same asset on Parchment and on Deep Navy. Never recolor the mark or drop it on a busy photo - give it a solid ground.

Wordmark sets in Baloo 2. Keep clear space of at least the mark's height on all sides; minimum mark size 24px. Mark-only in tight chrome (the nav uses it solo).
Tokens, not hex.
Components never hardcode color - they read tokens, so the same markup flips between the cream light theme and the navy dark theme. The named values below are the portable canonical (light) brand; copy these into any service. Each accent ships with a dark ink twin that clears WCAG AA (4.5:1) as text.
The ramp keeps its legacy --v3-blue-* names so the component layer stays untouched - but the values are vermillion in light and launch-blue in dark. Use the token, get the right one for free.
charcoal/ink for text, slate for secondary, line for borders, paper/cloud for surfaces.
Four faces, four jobs.
Each family has one role and is self-hosted from the CDN (cdn.campaignbrain.dev/css/fonts.css) - the build pulls nothing third-party. Body and mono load as display: optional so the LCP element paints at fallback render; only the display face is allowed to swap in.
h1-h2, hero text, big numbers. display: swap - brand-critical.
Paragraphs, lede, prose. display: optional - keeps LCP at fallback render.
Reserved for the wordmark lockup.
Labels, numerals, eyebrows, version pills.
Heading one
Heading two
Heading three
Lede paragraph - the one-sentence promise under every h1.
Body paragraph. Comfortable measure, generous line-height, slate for secondary text and charcoal for primary.
One set, served once.
323 line icons live on the CDN at cdn.campaignbrain.dev/svg/icons/<name>.svg - the same set every Nominate.AI surface draws from. Render them as a CSS mask so they inherit the current text color and theme cleanly. Below is a representative slice.
Reference by name, never paste raw <svg> or emoji. The full set (323) is browsable in cbloom's widget-zoo; pull any one at https://cdn.campaignbrain.dev/svg/icons/<name>.svg.
The working set.
Pills tag and categorize, buttons act, panels contain, eyebrows introduce. Everything below is the real class, not a mockup.
v3-pill v3-pill--{color} - one per card, top-left, always before the title.
Title with an accent.
Eyebrows use blue-ink (not blue-500) so they clear contrast on cream. v3-accent underlines the payoff word in the heading.
Radius and elevation.
Four radii, four shadows. Sections alternate cloud and paper backgrounds; cards sit on either with sh-1 at rest and sh-2 on hover.
Reveal on scroll, eager above the fold.
Every section you've scrolled past on this page faded in through V3Reveal - an IntersectionObserver that adds .is-in once. Above-the-fold content uses the eager prop so first paint is already at full opacity and the LCP element never waits on JavaScript.
<V3Reveal eager> // hero, h1, lede - painted at full opacity, no observer
<V3Reveal> // everything below the fold - fades in on scroll
<V3Reveal delay={i * 60}> // stagger card grids 60ms per item- Tokens over hex - components never hardcode a color.
- Bright accents fill; ink twins write. Text on cream always uses the ink variant.
- Headings never skip a level; cards under an h2 use h3.
- One primary button per view.
- Icons by name from the CDN - never inline raw SVG or emoji.
- Above-the-fold reveals are eager - LCP never waits on an observer.
- Every page ships with a per-route OG card and passes the audit suite (axe, visual, perf budget).
Adopt the brand in three lines.
Everything here is meant to travel. Any Nominate.AI surface points at the same CDN for fonts and icons, reads the same tokens, and inherits the brand for free - no copied font files, no forked palettes.
<!-- 1. Brand fonts + tokens, link these two, inherit the brand -->
<link rel="preconnect" href="https://cdn.campaignbrain.dev">
<link rel="stylesheet" href="https://cdn.campaignbrain.dev/css/fonts.css">
<link rel="stylesheet" href="https://cdn.campaignbrain.dev/css/brand-tokens.css">
/* then, anywhere: color: var(--cb-text); background: var(--cb-canvas);
accent: var(--cb-brand); font-family: var(--cb-font-body);
add data-theme="dark" on a wrapper for the navy theme. */
<!-- 2. The mark -->
<img src="https://cdn.campaignbrain.dev/images/brand/logo.png" alt="Nominate.AI" height="28">
<!-- 3. Icons, reference by name, tint with currentColor -->
<span style="
background: currentColor;
-webkit-mask: url(https://cdn.campaignbrain.dev/svg/icons/brain.svg) center/contain no-repeat;
mask: url(https://cdn.campaignbrain.dev/svg/icons/brain.svg) center/contain no-repeat;
width: 24px; height: 24px; display: inline-block;"></span>
<!-- 4. Tenant branding (logos + favicon + palette) -->
https://cdn.campaignbrain.dev/tenants/<slug>/{icon,cropped,full,favicon}/css/brand-tokens.css, the palette as--cb-*/css/fonts.css, 7 brand-ready faces/images/brand/, canonical logo + favicon set/svg/icons/, 323 line icons/tenants/<slug>/, per-tenant branding
- Reconcile cbloom onto the tokens, one
campaign-braintheme, fix the stray light accent - Reskin the legacy navy/maroon services (cbapp, cbtenant, cbdocs, cbmobile) onto
--cb-* - Retire the ad-hoc one-offs and the external-CDN dependency
Source of truth: app/v3.css + the cbcdn repo - this page reads the tokens live.