Canvas and paper were both #ffffff in light mode — cards only separated by a 1px hairline, causing eye fatigue. Tints the canvas token to a very pale cool neutral (#f3f5f8) so paper cards lift naturally without shadow or radius, preserving brutalism. Dark mode tokens unchanged. Updates DESIGN.md Surface section with rationale. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
14 KiB
Overview
Mimic is a BAS (Breach and Attack Simulation) purple-team console — not a product catalog, not a marketing page. The aesthetic is Bloomberg Terminal / SOC dashboard: dense, angular, semantic-color-driven, zero ornament. Every surface decision reinforces operational trust: data is primary, chrome is invisible.
The system sits on a pale-tinted canvas (light: #f3f5f8) / dark slab (dark) with one chromatic action color — Electric Blue ({colors.primary} — #024ad8) — and semantic status signals (success, warn, bloom-deep). Inter handles body/headers/labels. JetBrains Mono carries data: IDs, ISO dates, commands, execution output, MITRE technique codes, metrics — anything that must be read at a glance without typographic distraction.
No rounded corners on containers. No shadows on interactive surfaces. No transitions. Hover is instantaneous. Focus rings are sharp. This is a tool, not a storefront.
Key Characteristics:
- Angular surfaces everywhere (
border-radius: 0) — exception: status pills (rounded-pill) and avatars - Zero transitions / zero animations — state changes are immediate
- Semantic color signals: primary blue = action, success green = confirmed, warn amber = pending/caution, bloom-deep = destructive/error
- Monospace data discipline:
font-monoONLY for IDs, dates, codes, output, metrics — never for headers, labels, prose - Dense spacing: section gap 48px (not 80px), card padding 12–16px on dense surfaces
- Light + dark modes both supported; dark mode is the primary operational mode for SOC analysts
Colors
Brand & Accent
- Electric Blue (
{colors.primary}—#024ad8): primary CTA fill, active nav indicator, focus ring. Never used as a section background. - Bright Blue (
{colors.primary-bright}—#296ef9): CTA on dark slab surfaces where#024ad8muddles. - Deep Navy (
{colors.primary-deep}—#0e3191): pressed state for primary CTA. - Soft Blue (
{colors.primary-soft}—#c9e0fc): selection highlight, chip background on light surfaces.
Surface
- Canvas (
{colors.canvas}—#f3f5f8light /#111827dark): universal page background. In light mode, canvas is tinted while paper stays pure white so cards lift without shadow or radius, preserving brutalism. - Paper (
{colors.paper}—#fffffflight /#1f2937dark): card and panel surfaces. - Cloud (
{colors.cloud}—#f7f7f7light /#1f2937dark): alternating section band, table row zebra. - Fog (
{colors.fog}—#e8e8e8light /#374151dark): secondary section band, input background on dense panels. - Steel (
{colors.steel}—#c2c2c2light /#4b5563dark): hairline borders, disabled states. - Hairline (
{colors.hairline}): 1px divider between cells, panels, table rows. - Slab (
{colors.slab}—#111827): fixed-dark surface — utility strip, footer, dark bands. Does NOT invert in dark mode.
Text
- Ink (
{colors.ink}—#1a1a1alight /#f9fafbdark): universal body text color. - Ink Deep (
{colors.ink-deep}—#000000light /#ffffffdark): maximum contrast for headings. - Ink Soft (
{colors.ink-soft}—#292929light /#e5e7ebdark): muted body, secondary labels. - On Ink (
{colors.ink-on}—#fffffflight /#111827dark): text on slab surfaces. - Charcoal (
{colors.charcoal}—#3d3d3dlight /#d1d5dbdark): secondary descriptions, captions. - Graphite (
{colors.graphite}—#636363light /#9ca3afdark): timestamps, metadata, footnotes.
Semantic (Status Signals)
- Success (
{colors.success}—#16a34alight /#22c55edark): confirmed detections, done status, positive metrics. Background softened to{colors.success-soft}(#dcfce7light /#14532ddark) for badge fills. - Warn (
{colors.warn}—#d97706light /#f59e0bdark): pending review, caution states, partial detection. Background softened to{colors.warn-soft}(#fef3c7light /#78350fdark) for badge fills. - Bloom Deep (
{colors.bloom-deep}—#b3262b): error, destructive action, failed detection. Bloom family covers red-spectrum signals. - Bloom Wine (
{colors.bloom-wine}—#5a1313): darkened destructive emphasis. - Bloom Coral (
{colors.bloom-coral}—#ff5050): alert highlight on dark surfaces.
Typography
Font Families
- Inter Variable (
{fontFamily.sans}): body text, labels, headers, navigation, form fields. The universal surface font. - JetBrains Mono Variable (
{fontFamily.mono}): data cells ONLY — engagement IDs, simulation IDs, ISO 8601 dates, execution commands, terminal output, MITRE technique codes (T1059.001), numeric metrics, usernames-as-identifiers. Never used for prose, headings, or labels.
Both fonts are bundled locally via @fontsource-variable/inter and @fontsource-variable/jetbrains-mono. Zero CDN loading at runtime.
Hierarchy
| Token | Size | Weight | Line Height | Use |
|---|---|---|---|---|
{typography.display-xxl} |
40px | 500 | 1.1 | Page-level hero (rare — dashboard title) |
{typography.display-xl} |
32px | 500 | 1.1 | Section title (engagement name, modal header) |
{typography.display-lg} |
28px | 500 | 1.1 | Sub-section header, panel title |
{typography.display-md} |
24px | 500 | 1.1 | Card title, table header group |
{typography.display-sm} |
20px | 500 | 1.1 | Item title, form section header |
{typography.display-xs} |
16px | 600 | 1.1 | Compact section header, sidebar label |
{typography.body-lg} |
18px | 400 | 1.4 | Lead paragraph |
{typography.body-md} |
16px | 400 | 1.4 | Default body, form labels |
{typography.body-emphasis} |
16px | 500 | 1.4 | Bolded inline copy, table column headers |
{typography.caption-md} |
14px | 400 | 1.5 | Secondary metadata, captions, table cells (non-data) |
{typography.caption-bold} |
14px | 700 | 1.3 | Status labels, tag text |
{typography.caption-sm} |
12px | 400 | 1.33 | Footnotes, legal fine-print |
{typography.button-md} |
14px | 600 | 1.4 | Button labels (uppercase) |
{typography.button-sm} |
12.6px | 700 | 1.0 | Compact button in tight cells |
Monospace Discipline
JetBrains Mono carries data that must be scanned without typographic noise. Apply font-mono (Tailwind) or font-family: var(--font-mono) to:
- Engagement IDs, simulation IDs (any UUID or integer identifier)
- ISO 8601 dates and timestamps (
2024-06-09T14:32:00) - MITRE technique codes (
T1059.001,TA0002) - Execution commands and command fields
- Terminal / execution output
- Numeric metrics (counts, durations)
- Usernames displayed as record identifiers (not greeting text)
Never apply font-mono to: page titles, section headers, body prose, navigation, form labels, button text.
Layout
Spacing System
- Base unit: 8px. Half-step 4px.
- Tokens:
{spacing.xxs}4px ·{spacing.xs}8px ·{spacing.sm}12px ·{spacing.md}16px ·{spacing.lg}20px ·{spacing.xl}24px ·{spacing.xxl}32px ·{spacing.section}48px - Section padding: 48px vertical between major bands (desktop); ~24px on mobile.
- Card padding: 16px on dense panels; 24px on standard cards.
- Gutter: 24px between grid columns on desktop; 16px on tablet/mobile.
Grid & Container
- Max-width: 1366px content container, full-bleed on canvas.
- List pages: full-width table with 1px hairline borders, no card wrap.
- Detail pages: 2-column split (60/40) on desktop, stacked on mobile.
- Form pages: single-column centered at 640px max-width.
Whitespace Philosophy
Dense but not cramped. Table rows at 44px height (WCAG touch target). Card padding minimum 12px. No whitespace used as decoration — every gap serves alignment or grouping. Editorial breathing room (80px sections, hero-scale photography) does not apply here.
Shapes
Border Radius
| Token | Value | Use |
|---|---|---|
{rounded.none} |
0px | Default for everything: buttons, cards, modals, inputs, dropdowns, panels, tags, tables |
{rounded.pill} |
9999px | Status pills only (StatusBadge, SimulationStatusBadge) and circular avatars |
No intermediate radius values (xs, sm, md, lg, xl) are used on visible surfaces. The brutalist rule: if it's not a status pill or avatar, border-radius: 0.
Elevation
No shadows on interactive surfaces. Elevation is communicated by border contrast (1px hairline on paper over canvas) not box-shadow.
| Level | Treatment | Use |
|---|---|---|
| 0 — Flat | No border, no shadow | Page background, full-bleed bands |
| 1 — Hairline | 1px solid {colors.hairline} |
Cards, panels, table cells, input borders |
| 2 — Modal overlay | rgba(0,0,0,0.6) backdrop |
Modal dialogs — backdrop only, frame stays hairline |
Shadows (box-shadow) are not used anywhere.
Components
Every component spec below: border-radius 0 unless noted. No
transition-*on any interactive surface. Hover is instantaneous.
Buttons
.btn-primary — Electric Blue CTA
- Background
{colors.primary}, text white, uppercase, 14px/600,h-11, padding12px 24px,rounded-none - Hover: background
{colors.primary-deep}— no transition - Disabled: background
{colors.steel}, cursor not-allowed
.btn-ink — Fixed-dark filled CTA
- Background
{colors.slab}, text{colors.slab-text}, uppercase, same metrics as btn-primary - Used on dark band surfaces where blue would clash
.btn-outline — Outlined blue CTA
- Background
{colors.canvas}, text{colors.primary}, 1px{colors.primary}border,rounded-none - Hover: background
{colors.primary-soft}
.btn-outline-ink — Outlined neutral CTA
- Background
{colors.canvas}, text{colors.ink}, 1px{colors.ink}border,rounded-none - Hover: background
{colors.cloud}
.btn-text-link — Inline text link
- Text
{colors.primary}, no background, no border - Hover: underline, no color change
Inputs & Forms
.text-input — Standard text field
- Background
{colors.canvas}, text{colors.ink}, 1px{colors.steel}border,rounded-none,h-11 - Focus: border becomes 1px
{colors.primary}, no halo, no transition
textarea.text-input — Multiline variant
- Same as text-input,
min-h-[88px], height auto
select.text-input — Dropdown select
- Same surface as text-input, caret via OS or custom SVG
Cards & Panels
.card-product — Standard content card
- Background
{colors.paper}, 1px{colors.hairline}border,rounded-none, padding{spacing.md}(16px) - No shadow. Dense surfaces use padding
{spacing.sm}(12px).
.modal-backdrop — Modal overlay backdrop
background-color: rgba(0,0,0,0.6)— fixed, never themed- Modal frame:
{colors.paper}background, 1px{colors.hairline}border,rounded-none
Badges & Tags
.badge-pill-* — Status pills (StatusBadge, SimulationStatusBadge)
rounded-pill(9999px) — THE ONLY rounded surfaces on status badges- Semantic fill: planned→warn-soft/warn, active→primary-soft/primary, closed→cloud/graphite
- done→success-soft/success, review→warn-soft/warn, pending→cloud/graphite, in-progress→primary-soft/primary
MITRE technique tags — NOT pills
- Angular (
rounded-none), 1px{colors.hairline}border,{colors.cloud}background, caption-md size - They are labels, not status signals — no pill shape
Navigation
.utility-strip — Top utility bar
- Background
{colors.slab}, text{colors.slab-text}, height 36px,font-monofor user role/username
.nav-bar-top — Main navigation
- Background
{colors.slab}(fixed dark — does not invert), height 56px - Active link: 2px
{colors.primary}bottom border
.nav-link — Navigation anchor
- Text
{colors.slab-text}, caption-md,rounded-none - Active state: 2px primary bottom border
Data Tables
table-layout: fixed,word-break: break-word- Header row: background
{colors.cloud},body-emphasistext, 1px{colors.hairline}bottom border - Data cells: 44px min-height, 1px
{colors.hairline}bottom border - ID / date / technique columns:
font-mono - Zebra striping optional — use
{colors.cloud}for odd rows if table is wide
Toast Notifications
- Angular (
rounded-none), 4px left border strip in semantic color (success/warn/bloom-deep/primary) - Background
{colors.paper}, 1px{colors.hairline}border
Do's and Don'ts
Do
rounded-noneon every container, button, input, modal, dropdown, panel, tagfont-monoon IDs, ISO dates, MITRE codes, commands, output, metrics- Semantic color for status: success green, warn amber, bloom-deep for errors
- 1px hairline borders for panel separation — never shadow
- Instant hover (no
transition-*) - Sharp focus ring:
outline: 2px solid {colors.primary}; outline-offset: 0 - Keep Inter for all headers, labels, prose, navigation, button text
Don't
- Don't round containers — not even
2px. If it's not a status pill or avatar,rounded-none - Don't use
font-monofor headers, labels, prose, or button text - Don't add
transition-*on any interactive element - Don't use shadows — hairline borders only
- Don't use
{colors.primary}as a background for sections - Don't drop opacity on ink text — use
{colors.charcoal}or{colors.graphite}for hierarchy - Don't use animated spinners with rounded tracks — a simple spinning line or text indicator fits the terminal aesthetic better
- Don't apply
rounded-pillto anything that is not a STATUS BADGE or AVATAR
Iteration Guide
- One component at a time — no section refactors in one pass
- Reference tokens by name (
{colors.primary},font-mono,rounded-none) — not hex/px in prose - When adding a new data field: ask "is this a datum (ID, date, code, metric)?" →
font-mono. If no → Inter - New status signals: map to existing semantic tokens (success/warn/bloom-deep/primary). No ad-hoc colors
- For new badge-like elements: pill ONLY if it's a status indicator with semantic color. Otherwise angular tag