Files
mimic/DESIGN.md
Knacky e4b1d6cb57 style(frontend): tint canvas light to #f3f5f8 for cards-on-canvas contrast
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>
2026-06-11 11:01:00 +02:00

14 KiB
Raw Blame History

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-mono ONLY for IDs, dates, codes, output, metrics — never for headers, labels, prose
  • Dense spacing: section gap 48px (not 80px), card padding 1216px 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 #024ad8 muddles.
  • 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}#f3f5f8 light / #111827 dark): 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}#ffffff light / #1f2937 dark): card and panel surfaces.
  • Cloud ({colors.cloud}#f7f7f7 light / #1f2937 dark): alternating section band, table row zebra.
  • Fog ({colors.fog}#e8e8e8 light / #374151 dark): secondary section band, input background on dense panels.
  • Steel ({colors.steel}#c2c2c2 light / #4b5563 dark): 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}#1a1a1a light / #f9fafb dark): universal body text color.
  • Ink Deep ({colors.ink-deep}#000000 light / #ffffff dark): maximum contrast for headings.
  • Ink Soft ({colors.ink-soft}#292929 light / #e5e7eb dark): muted body, secondary labels.
  • On Ink ({colors.ink-on}#ffffff light / #111827 dark): text on slab surfaces.
  • Charcoal ({colors.charcoal}#3d3d3d light / #d1d5db dark): secondary descriptions, captions.
  • Graphite ({colors.graphite}#636363 light / #9ca3af dark): timestamps, metadata, footnotes.

Semantic (Status Signals)

  • Success ({colors.success}#16a34a light / #22c55e dark): confirmed detections, done status, positive metrics. Background softened to {colors.success-soft} (#dcfce7 light / #14532d dark) for badge fills.
  • Warn ({colors.warn}#d97706 light / #f59e0b dark): pending review, caution states, partial detection. Background softened to {colors.warn-soft} (#fef3c7 light / #78350f dark) 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, padding 12px 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-mono for 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-emphasis text, 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-none on every container, button, input, modal, dropdown, panel, tag
  • font-mono on 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-mono for 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-pill to anything that is not a STATUS BADGE or AVATAR

Iteration Guide

  1. One component at a time — no section refactors in one pass
  2. Reference tokens by name ({colors.primary}, font-mono, rounded-none) — not hex/px in prose
  3. When adding a new data field: ask "is this a datum (ID, date, code, metric)?" → font-mono. If no → Inter
  4. New status signals: map to existing semantic tokens (success/warn/bloom-deep/primary). No ad-hoc colors
  5. For new badge-like elements: pill ONLY if it's a status indicator with semantic color. Otherwise angular tag