264 lines
14 KiB
Markdown
264 lines
14 KiB
Markdown
## 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 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 `#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
|