Files
mimic/DESIGN.md

264 lines
14 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
## 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 **pure-white canvas** (light) / **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}``#ffffff` light / `#111827` dark): universal page background.
- **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