Campaign Brain Style Guide¶
Visual Identity & UI Design System
Version 1.0 • December 2025
1. Introduction¶
This style guide establishes the visual identity and design standards for Campaign Brain, a political campaign CRM and workflow management platform. The design language draws from the brand's core imagery—the eagle representing strength and clarity, paired with the brain symbolizing intelligent, data-driven decisions.
The visual system balances patriotic gravitas with modern usability, creating an interface that feels authoritative yet approachable. This guide covers color palette, typography, iconography, component design, and layout patterns specifically optimized for FastHTML implementations.
2. Color Palette¶
The Campaign Brain color system is derived directly from the logo, emphasizing a professional navy and patriotic red as primary brand colors. The current UI uses a teal/turquoise accent that should be phased out in favor of brand-aligned colors.
2.1 Primary Colors¶
These colors form the core of the Campaign Brain identity and should be used prominently throughout the interface.
| Color | Hex Value | Usage |
|---|---|---|
| Navy Primary | #1E3A5F |
Headers, navigation bars, primary buttons, headings |
| Navy Dark | #152942 |
Hover states, active navigation, footer backgrounds |
| Brand Red | #8B2332 |
Accent elements, call-to-action buttons, important highlights |
| Red Light | #A63446 |
Hover states for red elements, secondary accents |
2.2 Neutral Colors¶
A carefully calibrated gray scale provides the foundation for text, borders, backgrounds, and subtle UI elements.
| Color | Hex Value | Usage |
|---|---|---|
| Background | #F8FAFC |
Page backgrounds, subtle section dividers |
| Border Light | #E2E8F0 |
Card borders, divider lines, input borders |
| Text Secondary | #64748B |
Secondary text, placeholders, disabled states |
| Text Primary | #334155 |
Body text, primary content, labels |
2.3 Semantic Colors¶
Used for status indicators, alerts, and feedback. These should be applied consistently across all system messages.
| Status | Hex Value | Usage |
|---|---|---|
| Success | #059669 |
Active status, confirmations, positive indicators |
| Warning | #D97706 |
Pending states, caution alerts, attention required |
| Error | #DC2626 |
Error states, destructive actions, critical alerts |
| Info | #0284C7 |
Informational messages, tips, links |
2.4 CSS Variables¶
Implement these as CSS custom properties for consistent theming across the application:
:root {
--color-navy-primary: #1E3A5F;
--color-navy-dark: #152942;
--color-red-primary: #8B2332;
--color-red-light: #A63446;
--color-bg-page: #F8FAFC;
--color-bg-card: #FFFFFF;
--color-border: #E2E8F0;
--color-text-primary: #334155;
--color-text-secondary: #64748B;
--color-success: #059669;
--color-warning: #D97706;
--color-error: #DC2626;
--color-info: #0284C7;
}
3. Typography¶
Typography establishes hierarchy and readability. Campaign Brain uses a two-font system: a serif display font for headings that conveys authority, paired with a clean sans-serif for body content that ensures readability in data-dense interfaces.
3.1 Font Selection (Google Fonts)¶
Primary Option: Libre Baskerville + Source Sans 3¶
Libre Baskerville is a refined serif with excellent readability at display sizes. It carries the gravitas appropriate for a political tool while remaining approachable. Use for all headings and display text.
Source Sans 3 (formerly Source Sans Pro) is an open-source sans-serif designed by Adobe for UI clarity. Its clean letterforms work exceptionally well in tables, forms, and dense data displays. Use for body text, labels, and interface elements.
Alternative Option: Merriweather + Inter¶
Merriweather offers a slightly warmer, more contemporary serif alternative if Libre Baskerville feels too formal.
Inter is an excellent fallback for body text—highly legible and widely supported, though slightly less distinctive than Source Sans 3.
<!-- Google Fonts embed -->
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Libre+Baskerville:wght@400;700&family=Source+Sans+3:wght@400;500;600;700&display=swap" rel="stylesheet">
3.2 Type Scale¶
A consistent type scale creates visual rhythm. Sizes are specified in rem for accessibility.
| Element | Size | Weight | Font / Notes |
|---|---|---|---|
| Page Title | 2rem (32px) | 700 | Libre Baskerville, Navy Primary |
| Section Header | 1.5rem (24px) | 700 | Libre Baskerville, Navy Dark |
| Card Title | 1.125rem (18px) | 600 | Source Sans 3 |
| Body Text | 1rem (16px) | 400 | Source Sans 3, Text Primary |
| Small / Caption | 0.875rem (14px) | 400 | Source Sans 3, Text Secondary |
| Button / Label | 0.875rem (14px) | 500-600 | Source Sans 3, uppercase optional |
4. Iconography¶
The current UI uses icons that appear inconsistent in weight and style. A unified icon set will significantly improve visual cohesion.
4.1 Recommended Icon Library¶
Primary Choice: Lucide Icons
Lucide (lucide.dev) is the recommended icon library for Campaign Brain. It offers clean, consistent stroke-based icons that work beautifully at the 20-24px sizes common in dashboard interfaces.
Key advantages: - Consistent 2px stroke weight across all icons - Extensive coverage of data and dashboard icons - MIT license with no attribution required - Easy integration via CDN or npm
<!-- Lucide via CDN -->
<script src="https://unpkg.com/lucide@latest"></script>
<script>lucide.createIcons();</script>
<!-- Usage in HTML -->
<i data-lucide="users"></i>
<i data-lucide="calendar"></i>
<i data-lucide="map-pin"></i>
4.2 Icon Sizing¶
| Context | Size | Stroke |
|---|---|---|
| Navigation (sidebar) | 20px | 1.5px |
| Top navigation | 20px | 1.5px |
| Card headers | 18-20px | 1.5px |
| Stat cards (large) | 24-28px | 2px |
| Inline / buttons | 16px | 2px |
4.3 Recommended Icon Mappings¶
Replace current icons with these Lucide equivalents for consistency:
| Feature | Lucide Icon |
|---|---|
| Dashboard | layout-dashboard |
| Audience / Contacts | users |
| Events | calendar |
| Segments | layers |
| Communications | mail |
| Tags | tag |
| Goals | target |
| Reports | bar-chart-2 |
| Import/Export | arrow-left-right |
| Map | map |
| Settings | settings |
| Tenants | building-2 |
| Ports | network |
5. Component Design¶
Consistent component styling creates a cohesive user experience. These specifications are optimized for FastHTML implementations.
5.1 Buttons¶
| Variant | Styles |
|---|---|
| Primary | Background: Navy Primary (#1E3A5F), Text: White, Border: none, Hover: Navy Dark (#152942), Border-radius: 6px, Padding: 0.625rem 1.25rem, Font-weight: 600 |
| Secondary | Background: White, Text: Navy Primary, Border: 1px solid #E2E8F0, Hover: Background #F1F5F9, Border-radius: 6px |
| Accent (CTA) | Background: Brand Red (#8B2332), Text: White, Hover: Red Light (#A63446), Use sparingly for primary actions |
| Ghost | Background: transparent, Text: Text Secondary, Hover: Background #F1F5F9, For low-emphasis actions |
Note: Replace the current teal "+ New Tenant" button with the Accent (CTA) style to align with brand colors. The current teal (
#10B981range) should be phased out entirely.
5.2 Cards¶
Cards are the primary container for content grouping. The current implementation is solid but can be refined:
- Background: Pure white (
#FFFFFF) - Border: 1px solid
#E2E8F0 - Border-radius: 8px (slightly larger than current)
- Shadow:
0 1px 3px rgba(0, 0, 0, 0.05)— subtle, not pronounced - Padding: 1.5rem (24px)
- Hover (interactive cards): Border-color:
#CBD5E1, Shadow:0 4px 6px rgba(0, 0, 0, 0.07)
5.3 Status Badges¶
The current "Pending" badges are functional but could be more refined:
| Status | Styles |
|---|---|
| Active | Background: #ECFDF5, Text: #059669, Border: 1px solid #A7F3D0 |
| Pending | Background: #FFFBEB, Text: #D97706, Border: 1px solid #FDE68A |
| Inactive | Background: #F1F5F9, Text: #64748B, Border: 1px solid #E2E8F0 |
| Error | Background: #FEF2F2, Text: #DC2626, Border: 1px solid #FECACA |
Badge styling: Font-size: 0.75rem (12px), Font-weight: 500, Padding: 0.25rem 0.75rem, Border-radius: 9999px (pill shape)
6. Layout Patterns¶
6.1 Navigation¶
Top Navigation Bar¶
- Background: Navy Primary (
#1E3A5F) - Height: 56-64px
- Text/Icons: White with 80% opacity, 100% on hover
- Logo: Left-aligned, with product name in white
Sidebar Navigation¶
- Width: 240px expanded, 64px collapsed
- Background: White (
#FFFFFF) - Border: Right border 1px solid
#E2E8F0 - Nav Items: Padding 0.75rem 1rem, border-radius 6px
- Active State: Background
#F1F5F9, left border 3px solid Navy Primary, text color Navy Primary - Hover State: Background
#F8FAFC
6.2 Spacing System¶
Use a consistent 4px base grid for all spacing. Common values:
| Token | Value | Usage |
|---|---|---|
| space-1 | 4px | Tight spacing, icon gaps |
| space-2 | 8px | Form element gaps, badge padding |
| space-3 | 12px | Button padding, list item spacing |
| space-4 | 16px | Standard component padding |
| space-6 | 24px | Card padding, section spacing |
| space-8 | 32px | Large section gaps |
6.3 Data Tables¶
The voter database table in your screenshots is well-structured. Refinements:
- Header row: Background
#F8FAFC, text#64748B(Text Secondary), font-weight 600, font-size 0.75rem, uppercase with letter-spacing 0.05em - Body rows: Background white, border-bottom 1px solid
#F1F5F9 - Row hover: Background
#F8FAFC - Cell padding: 0.75rem 1rem
- Zebra striping: Optional — alternate rows
#FAFAFAif preferred
7. FastHTML Implementation¶
FastHTML's Python-first approach means styling is typically applied via CSS classes. Here's a recommended approach for implementing this style guide.
7.1 CSS Setup¶
Create a centralized CSS file with the design tokens defined as custom properties. Include in your FastHTML app's head:
from fasthtml.common import *
app = FastHTML(
hdrs=[
Link(rel="preconnect", href="https://fonts.googleapis.com"),
Link(rel="preconnect", href="https://fonts.gstatic.com", crossorigin=True),
Link(href="https://fonts.googleapis.com/css2?family=Libre+Baskerville:wght@400;700&family=Source+Sans+3:wght@400;500;600;700&display=swap", rel="stylesheet"),
Link(rel="stylesheet", href="/static/styles.css"),
Script(src="https://unpkg.com/lucide@latest"),
]
)
7.2 Component Helpers¶
Define reusable component functions for consistent styling:
def Button(text, variant="primary", icon=None, **attrs):
cls = f"btn btn-{variant}"
children = []
if icon:
children.append(I(data_lucide=icon, cls="btn-icon"))
children.append(text)
return Button_(*children, cls=cls, **attrs)
def Card(*children, title=None, icon=None, **attrs):
header = []
if icon or title:
header = [Div(
I(data_lucide=icon, cls="card-icon") if icon else None,
H3(title, cls="card-title") if title else None,
cls="card-header"
)]
return Div(*header, *children, cls="card", **attrs)
def Badge(text, status="default"):
return Span(text, cls=f"badge badge-{status}")
8. Summary: Quick Wins¶
To immediately improve the UI with minimal effort, prioritize these changes:
- Replace teal accents — Change the "+ New Tenant" button and any teal elements to Brand Red (
#8B2332) - Unify icon library — Switch all icons to Lucide with consistent 20px sizing and 1.5px stroke
- Add Google Fonts — Implement Libre Baskerville for headings and Source Sans 3 for body text
- Refine card shadows — Use subtle shadows (
0 1px 3px rgba(0,0,0,0.05)) instead of hard borders - Improve active nav states — Add left border accent and background highlight to current page
— End of Style Guide —