[Overview](https://rickylabs.github.io/netscript/design-system/)[Guidelines](https://rickylabs.github.io/netscript/design-system/guidelines/)[Token contract](https://rickylabs.github.io/netscript/design-system/token-contract/)[Docs kit](https://rickylabs.github.io/netscript/design-system/docs-kit/)[Theme builder](https://rickylabs.github.io/netscript/create/)[Components](https://rickylabs.github.io/netscript/design-system/components/)[Create your own theme](https://rickylabs.github.io/netscript/design-system/create-your-own-theme/)[Studio](https://rickylabs.github.io/netscript/design-system/themes/studio/)[Tonal](https://rickylabs.github.io/netscript/design-system/themes/tonal/)[Bloom](https://rickylabs.github.io/netscript/design-system/themes/bloom/)[Cupertino](https://rickylabs.github.io/netscript/design-system/themes/cupertino/)[Liquid](https://rickylabs.github.io/netscript/design-system/themes/liquid/)[Fluent](https://rickylabs.github.io/netscript/design-system/themes/fluent/)[Brutal](https://rickylabs.github.io/netscript/design-system/themes/brutal/)[Filigrane](https://rickylabs.github.io/netscript/design-system/themes/filigrane/)[Terminal](https://rickylabs.github.io/netscript/design-system/themes/terminal/)[Pixel](https://rickylabs.github.io/netscript/design-system/themes/pixel/)[Tactile](https://rickylabs.github.io/netscript/design-system/themes/tactile/)

# Brutal

Gumroad-style neo-brutalism. Flat saturated blocks, black ink outlines and hard zero-blur offset shadows that stay black in both schemes.

[DESIGN.md](https://raw.githubusercontent.com/rickylabs/netscript/main/docs/design-system/themes/brutal/DESIGN.md) [SKILL.md](https://raw.githubusercontent.com/rickylabs/netscript/main/docs/design-system/themes/brutal/SKILL.md)

On this page

- [Light and dark](#design-specimens)
- [Theme values](#design-values)
- [Values: Colors](#values-colors)
- [Values: Typography](#values-typography)
- [Values: Radii](#values-rounded)
- [Values: Spacing](#values-spacing)
- [Values: Component recipes](#values-components)
- [Overview](#overview)
- [Colors](#colors)
- [Typography](#typography)
- [Layout](#layout)
- [Elevation & Depth](#elevation-depth)
- [Shapes](#shapes)
- [Components](#components)
- [Do's and Don'ts](#dos-and-donts)
- [Iconography & Imagery](#iconography-imagery)
- [Motion & States](#motion-states)
- [Accessibility](#accessibility)
- [NetScript Mapping](#netscript-mapping)
- [Sources](#sources)

## Light and dark

### Brutal

![Brutal Orders specimen, light scheme](https://rickylabs.github.io/netscript/assets/design-system/brutal--light.webp)

*Light*

![Brutal Orders specimen, dark scheme](https://rickylabs.github.io/netscript/assets/design-system/brutal--dark.webp)

*Dark*

Specification values · alpha

## Theme values

### Values: Colors

**Brutal · Colors**

| Property | Value |
| --- | --- |
| `bg` | `#fefbe9` |
| `bg-dark` | `#31312e` |
| `surface` | `#f9f9f8` |
| `surface-dark` | `#191918` |
| `card` | `#ffffff` |
| `card-dark` | `#191918` |
| `surface-raised` | `#ffffff` |
| `surface-raised-dark` | `#222221` |
| `muted` | `#f1f0ef` |
| `muted-dark` | `#222221` |
| `selected` | `#fff7c2` |
| `selected-dark` | `#302008` |
| `overlay` | `#00000066` |
| `overlay-dark` | `#000000a8` |
| `fg` | `#21201c` |
| `fg-dark` | `#eeeeec` |
| `muted-fg` | `#63635e` |
| `muted-fg-dark` | `#b5b3ad` |
| `ink-fg` | `#fdfdfc` |
| `ink-fg-dark` | `#eeeeec` |
| `border` | `#dad9d6` |
| `border-dark` | `#3b3a37` |
| `input-border` | `#82827c` |
| `input-border-dark` | `#7c7b74` |
| `border-control` | `#000000` |
| `border-control-dark` | `#7c7b74` |
| `ink` | `#000000` |
| `ink-dark` | `#000000` |
| `ring` | `#0d74ce` |
| `ring-dark` | `#70b8ff` |
| `primary` | `#ffc53d` |
| `primary-dark` | `#ffc53d` |
| `primary-hover` | `#ffba18` |
| `primary-hover-dark` | `#ffd60a` |
| `primary-fg` | `#21201c` |
| `primary-fg-dark` | `#21201c` |
| `primary-text` | `#ab6400` |
| `primary-text-dark` | `#ffca16` |
| `block-yellow` | `#ffc53d` |
| `block-yellow-dark` | `#ffc53d` |
| `block-blue` | `#c2e5ff` |
| `block-blue-dark` | `#0090ff` |
| `block-green` | `#d3e7a6` |
| `block-green-dark` | `#bdee63` |
| `block-pink` | `#ffcdc2` |
| `block-pink-dark` | `#e54d2e` |
| `block-purple` | `#e1d9ff` |
| `block-purple-dark` | `#6e56cf` |
| `block-fg` | `#000000` |
| `block-fg-dark` | `#000000` |
| `shadow-color` | `#000000` |
| `shadow-color-dark` | `#000000` |
| `success` | `#46a758` |
| `success-dark` | `#46a758` |
| `success-text` | `#2a7e3b` |
| `success-text-dark` | `#71d083` |
| `warning` | `#ffc53d` |
| `warning-dark` | `#ffc53d` |
| `warning-text` | `#4f3422` |
| `warning-text-dark` | `#ffca16` |
| `destructive` | `#e5484d` |
| `destructive-dark` | `#e5484d` |
| `destructive-text` | `#641723` |
| `destructive-text-dark` | `#ff9592` |
| `info` | `#0090ff` |
| `info-dark` | `#0090ff` |
| `info-text` | `#113264` |
| `info-text-dark` | `#70b8ff` |

### Values: Typography

**Brutal · Typography**

| Property | Value |
| --- | --- |
| `title.fontFamily` | `Space Grotesk` |
| `title.fontSize` | `52px` |
| `title.fontWeight` | `400` |
| `title.lineHeight` | `52px` |
| `title.letterSpacing` | `-2px` |
| `kpi.fontFamily` | `Space Grotesk` |
| `kpi.fontSize` | `40px` |
| `kpi.fontWeight` | `700` |
| `kpi.lineHeight` | `44px` |
| `kpi.letterSpacing` | `-1.5px` |
| `heading.fontFamily` | `Space Grotesk` |
| `heading.fontSize` | `18px` |
| `heading.fontWeight` | `700` |
| `heading.lineHeight` | `24px` |
| `heading.letterSpacing` | `-0.3px` |
| `body.fontFamily` | `Space Grotesk` |
| `body.fontSize` | `14px` |
| `body.fontWeight` | `400` |
| `body.lineHeight` | `20px` |
| `button.fontFamily` | `Space Grotesk` |
| `button.fontSize` | `14px` |
| `button.fontWeight` | `700` |
| `button.lineHeight` | `20px` |
| `button.letterSpacing` | `-0.3px` |
| `caption.fontFamily` | `Space Grotesk` |
| `caption.fontSize` | `12px` |
| `caption.fontWeight` | `400` |
| `caption.lineHeight` | `16px` |
| `label.fontFamily` | `Space Mono` |
| `label.fontSize` | `11px` |
| `label.fontWeight` | `700` |
| `label.lineHeight` | `16px` |
| `label.letterSpacing` | `0.6px` |
| `data.fontFamily` | `JetBrains Mono` |
| `data.fontSize` | `14px` |
| `data.fontWeight` | `700` |
| `data.lineHeight` | `20px` |
| `data.fontFeature` | `"tnum" 1` |
| `data-meta.fontFamily` | `JetBrains Mono` |
| `data-meta.fontSize` | `13px` |
| `data-meta.fontWeight` | `400` |
| `data-meta.lineHeight` | `18px` |

### Values: Radii

**Brutal · Radii**

| Property | Value |
| --- | --- |
| `none` | `0px` |
| `xs` | `4px` |
| `sm` | `6px` |
| `md` | `8px` |
| `lg` | `12px` |
| `full` | `9999px` |

### Values: Spacing

**Brutal · Spacing**

| Property | Value |
| --- | --- |
| `xs` | `4px` |
| `sm` | `8px` |
| `md` | `12px` |
| `lg` | `16px` |
| `xl` | `20px` |
| `2xl` | `24px` |
| `3xl` | `32px` |

### Values: Component recipes

**Brutal · Component recipes**

| Property | Value |
| --- | --- |
| `button-primary.backgroundColor` | `{colors.block-yellow}` |
| `button-primary.textColor` | `{colors.block-fg}` |
| `button-primary.typography` | `{typography.button}` |
| `button-primary.rounded` | `{rounded.md}` |
| `button-primary.height` | `44px` |
| `button-primary-dark.backgroundColor` | `{colors.block-yellow-dark}` |
| `button-primary-dark.textColor` | `{colors.block-fg-dark}` |
| `button-primary-dark.typography` | `{typography.button}` |
| `button-primary-dark.rounded` | `{rounded.md}` |
| `button-primary-dark.height` | `44px` |
| `button-secondary.backgroundColor` | `{colors.card}` |
| `button-secondary.textColor` | `{colors.fg}` |
| `button-secondary.rounded` | `{rounded.md}` |
| `button-secondary.height` | `44px` |
| `button-secondary-dark.backgroundColor` | `{colors.card-dark}` |
| `button-secondary-dark.textColor` | `{colors.fg-dark}` |
| `button-secondary-dark.rounded` | `{rounded.md}` |
| `button-secondary-dark.height` | `44px` |
| `button-ink.backgroundColor` | `{colors.ink}` |
| `button-ink.textColor` | `{colors.ink-fg}` |
| `button-ink.rounded` | `{rounded.md}` |
| `button-ink.height` | `44px` |
| `input.backgroundColor` | `{colors.card}` |
| `input.textColor` | `{colors.fg}` |
| `input.rounded` | `{rounded.md}` |
| `input.height` | `44px` |
| `input-dark.backgroundColor` | `{colors.card-dark}` |
| `input-dark.textColor` | `{colors.fg-dark}` |
| `input-dark.rounded` | `{rounded.md}` |
| `input-dark.height` | `44px` |
| `checkbox-checked.backgroundColor` | `{colors.primary}` |
| `checkbox-checked.textColor` | `{colors.primary-fg}` |
| `checkbox-checked.rounded` | `{rounded.xs}` |
| `checkbox-checked.size` | `22px` |
| `switch-on.backgroundColor` | `{colors.block-green}` |
| `switch-on.rounded` | `{rounded.full}` |
| `switch-on.width` | `52px` |
| `switch-on.height` | `28px` |
| `sticker-success.backgroundColor` | `{colors.block-green}` |
| `sticker-success.textColor` | `{colors.block-fg}` |
| `sticker-success.typography` | `{typography.label}` |
| `sticker-success.rounded` | `{rounded.full}` |
| `sticker-success.height` | `26px` |
| `tab-selected.backgroundColor` | `{colors.ink}` |
| `tab-selected.textColor` | `{colors.ink-fg}` |
| `tab-selected.typography` | `{typography.label}` |
| `tab-selected.height` | `40px` |
| `table-header.backgroundColor` | `{colors.ink}` |
| `table-header.textColor` | `{colors.ink-fg}` |
| `table-header.typography` | `{typography.label}` |
| `table-header.height` | `44px` |
| `table-header-dark.backgroundColor` | `{colors.ink-dark}` |
| `table-header-dark.textColor` | `{colors.ink-fg-dark}` |
| `table-header-dark.typography` | `{typography.label}` |
| `table-header-dark.height` | `44px` |
| `table-row-selected.backgroundColor` | `{colors.block-yellow}` |
| `table-row-selected.textColor` | `{colors.block-fg}` |
| `table-row-selected.height` | `60px` |
| `kpi-card.backgroundColor` | `{colors.block-yellow}` |
| `kpi-card.textColor` | `{colors.block-fg}` |
| `kpi-card.typography` | `{typography.kpi}` |
| `kpi-card.rounded` | `{rounded.lg}` |
| `kpi-card.width` | `289px` |
| `kpi-card.height` | `190px` |
| `kpi-card-dark.backgroundColor` | `{colors.block-blue-dark}` |
| `kpi-card-dark.textColor` | `{colors.block-fg-dark}` |
| `kpi-card-dark.typography` | `{typography.kpi}` |
| `kpi-card-dark.rounded` | `{rounded.lg}` |
| `notice.backgroundColor` | `{colors.block-pink}` |
| `notice.textColor` | `{colors.block-fg}` |
| `notice.rounded` | `{rounded.lg}` |
| `notice-dark.backgroundColor` | `{colors.block-pink-dark}` |
| `notice-dark.textColor` | `{colors.block-fg-dark}` |
| `notice-dark.rounded` | `{rounded.lg}` |
| `panel.backgroundColor` | `{colors.card}` |
| `panel.textColor` | `{colors.fg}` |
| `panel.rounded` | `{rounded.lg}` |
| `panel-dark.backgroundColor` | `{colors.card-dark}` |
| `panel-dark.textColor` | `{colors.fg-dark}` |
| `panel-dark.rounded` | `{rounded.lg}` |

Read YAML values and notes

```text
version: alpha
name: Brutal
description: Gumroad-style neo-brutalism. Flat saturated blocks, black ink outlines and hard zero-blur offset shadows that stay black in both schemes.
colors:
  # Resolved from the NetScript Figma library for the Light and Dark Orders screens.
  # Theme = Brutal. Keys are the --ns-* suffix.
  bg: '#fefbe9'
  bg-dark: '#31312e'
  surface: '#f9f9f8'
  surface-dark: '#191918'
  card: '#ffffff'
  card-dark: '#191918'
  surface-raised: '#ffffff'
  surface-raised-dark: '#222221'
  muted: '#f1f0ef'
  muted-dark: '#222221'
  selected: '#fff7c2'
  selected-dark: '#302008'
  overlay: '#00000066'
  overlay-dark: '#000000a8'
  fg: '#21201c'
  fg-dark: '#eeeeec'
  muted-fg: '#63635e'
  muted-fg-dark: '#b5b3ad'
  ink-fg: '#fdfdfc'
  ink-fg-dark: '#eeeeec'
  border: '#dad9d6'
  border-dark: '#3b3a37'
  input-border: '#82827c'
  input-border-dark: '#7c7b74'
  border-control: '#000000'
  border-control-dark: '#7c7b74'
  ink: '#000000'
  ink-dark: '#000000'
  ring: '#0d74ce'
  ring-dark: '#70b8ff'
  primary: '#ffc53d'
  primary-dark: '#ffc53d'
  primary-hover: '#ffba18'
  primary-hover-dark: '#ffd60a'
  primary-fg: '#21201c'
  primary-fg-dark: '#21201c'
  primary-text: '#ab6400'
  primary-text-dark: '#ffca16'
  block-yellow: '#ffc53d'
  block-yellow-dark: '#ffc53d'
  block-blue: '#c2e5ff'
  block-blue-dark: '#0090ff'
  block-green: '#d3e7a6'
  block-green-dark: '#bdee63'
  block-pink: '#ffcdc2'
  block-pink-dark: '#e54d2e'
  block-purple: '#e1d9ff'
  block-purple-dark: '#6e56cf'
  block-fg: '#000000'
  block-fg-dark: '#000000'
  shadow-color: '#000000'
  shadow-color-dark: '#000000'
  success: '#46a758'
  success-dark: '#46a758'
  success-text: '#2a7e3b'
  success-text-dark: '#71d083'
  warning: '#ffc53d'
  warning-dark: '#ffc53d'
  warning-text: '#4f3422'
  warning-text-dark: '#ffca16'
  destructive: '#e5484d'
  destructive-dark: '#e5484d'
  destructive-text: '#641723'
  destructive-text-dark: '#ff9592'
  info: '#0090ff'
  info-dark: '#0090ff'
  info-text: '#113264'
  info-text-dark: '#70b8ff'
typography:
  title: {
    fontFamily: Space Grotesk,
    fontSize: 52px,
    fontWeight: 400,
    lineHeight: 52px,
    letterSpacing: -2px,
  }
  kpi: {
    fontFamily: Space Grotesk,
    fontSize: 40px,
    fontWeight: 700,
    lineHeight: 44px,
    letterSpacing: -1.5px,
  }
  heading: {
    fontFamily: Space Grotesk,
    fontSize: 18px,
    fontWeight: 700,
    lineHeight: 24px,
    letterSpacing: -0.3px,
  }
  body: { fontFamily: Space Grotesk, fontSize: 14px, fontWeight: 400, lineHeight: 20px }
  button: {
    fontFamily: Space Grotesk,
    fontSize: 14px,
    fontWeight: 700,
    lineHeight: 20px,
    letterSpacing: -0.3px,
  }
  caption: { fontFamily: Space Grotesk, fontSize: 12px, fontWeight: 400, lineHeight: 16px }
  label: {
    fontFamily: Space Mono,
    fontSize: 11px,
    fontWeight: 700,
    lineHeight: 16px,
    letterSpacing: 0.6px,
  }
  data: {
    fontFamily: JetBrains Mono,
    fontSize: 14px,
    fontWeight: 700,
    lineHeight: 20px,
    fontFeature: '"tnum" 1',
  }
  data-meta: { fontFamily: JetBrains Mono, fontSize: 13px, fontWeight: 400, lineHeight: 18px }
rounded:
  none: 0px
  xs: 4px
  sm: 6px
  md: 8px
  lg: 12px
  full: 9999px
spacing:
  xs: 4px
  sm: 8px
  md: 12px
  lg: 16px
  xl: 20px
  2xl: 24px
  3xl: 32px
components:
  button-primary: {
    backgroundColor: '{colors.block-yellow}',
    textColor: '{colors.block-fg}',
    typography: '{typography.button}',
    rounded: '{rounded.md}',
    height: 44px,
  }
  button-primary-dark: {
    backgroundColor: '{colors.block-yellow-dark}',
    textColor: '{colors.block-fg-dark}',
    typography: '{typography.button}',
    rounded: '{rounded.md}',
    height: 44px,
  }
  button-secondary: {
    backgroundColor: '{colors.card}',
    textColor: '{colors.fg}',
    rounded: '{rounded.md}',
    height: 44px,
  }
  button-secondary-dark: {
    backgroundColor: '{colors.card-dark}',
    textColor: '{colors.fg-dark}',
    rounded: '{rounded.md}',
    height: 44px,
  }
  button-ink: {
    backgroundColor: '{colors.ink}',
    textColor: '{colors.ink-fg}',
    rounded: '{rounded.md}',
    height: 44px,
  }
  input: {
    backgroundColor: '{colors.card}',
    textColor: '{colors.fg}',
    rounded: '{rounded.md}',
    height: 44px,
  }
  input-dark: {
    backgroundColor: '{colors.card-dark}',
    textColor: '{colors.fg-dark}',
    rounded: '{rounded.md}',
    height: 44px,
  }
  checkbox-checked: {
    backgroundColor: '{colors.primary}',
    textColor: '{colors.primary-fg}',
    rounded: '{rounded.xs}',
    size: 22px,
  }
  switch-on: {
    backgroundColor: '{colors.block-green}',
    rounded: '{rounded.full}',
    width: 52px,
    height: 28px,
  }
  sticker-success: {
    backgroundColor: '{colors.block-green}',
    textColor: '{colors.block-fg}',
    typography: '{typography.label}',
    rounded: '{rounded.full}',
    height: 26px,
  }
  tab-selected: {
    backgroundColor: '{colors.ink}',
    textColor: '{colors.ink-fg}',
    typography: '{typography.label}',
    height: 40px,
  }
  table-header: {
    backgroundColor: '{colors.ink}',
    textColor: '{colors.ink-fg}',
    typography: '{typography.label}',
    height: 44px,
  }
  table-header-dark: {
    backgroundColor: '{colors.ink-dark}',
    textColor: '{colors.ink-fg-dark}',
    typography: '{typography.label}',
    height: 44px,
  }
  table-row-selected: {
    backgroundColor: '{colors.block-yellow}',
    textColor: '{colors.block-fg}',
    height: 60px,
  }
  kpi-card: {
    backgroundColor: '{colors.block-yellow}',
    textColor: '{colors.block-fg}',
    typography: '{typography.kpi}',
    rounded: '{rounded.lg}',
    width: 289px,
    height: 190px,
  }
  kpi-card-dark: {
    backgroundColor: '{colors.block-blue-dark}',
    textColor: '{colors.block-fg-dark}',
    typography: '{typography.kpi}',
    rounded: '{rounded.lg}',
  }
  notice: {
    backgroundColor: '{colors.block-pink}',
    textColor: '{colors.block-fg}',
    rounded: '{rounded.lg}',
  }
  notice-dark: {
    backgroundColor: '{colors.block-pink-dark}',
    textColor: '{colors.block-fg-dark}',
    rounded: '{rounded.lg}',
  }
  panel: { backgroundColor: '{colors.card}', textColor: '{colors.fg}', rounded: '{rounded.lg}' }
  panel-dark: {
    backgroundColor: '{colors.card-dark}',
    textColor: '{colors.fg-dark}',
    rounded: '{rounded.lg}',
  }
```

## Overview

- **Thesis:** a commerce console styled as a sticker book. Each surface is a flat, saturated block with a black ink outline and a hard offset shadow. The ink stays black in the dark scheme.
- Signature moves:

  1. Zero-blur offset shadows in `#000000`, sized 3/3, 4/4 or 6/6 by object size, in both schemes.
  2. Saturated colour blocks that carry data: the four KPI tiles (yellow, blue, pink, green), the pink notice and the yellow selected row. Text on them is always black `block-fg`.
  3. Sticker labels in Space Mono Bold 11px uppercase with 0.6px tracking, on pill stickers with a 2px ink border. The `LIVE SYNC` sticker is rotated −6°.
- **Anchor:** Gumroad UI code (MIT, `antiwork/gumroad`) plus neobrutalism.dev (MIT, `ekmas/neobrutalism-components`). Taken: the hard shadow pinned to black in dark mode, the bordered pill badge, regular-weight headings, colour-block fills without gradients, and the shadow that collapses on press. Not copied: Gumroad's name, coin illustrations, pink `#ff90e8` trade dress and the commercial ABC Favorit font (replaced by Space Grotesk). Figma's 2024 brand is not an anchor because it dropped heavy outlines.
- **Family:** Expressive.
- **Best for / avoid for:** creator tools, storefront admin, marketing consoles. Avoid long data sessions and dense analytics, because every row has a 2px rule and every panel a 6px slab.
- **Feel:** loud and tactile, like a printed zine used to run a shop.

## Colors

- Ground and surface ladder.

  - Light: canvas `bg` `#fefbe9` (amber/l/2, warm cream) → panels `card` `#ffffff` → blocks.
  - Dark: canvas `bg-dark` `#31312e` (sand/d/5) is *lighter* than the panels `card-dark` `#191918` (sand/d/2). The panels read as dark slabs on a mid-dark ground, so the black outlines and shadows still separate them from the canvas.
- **Accent policy.** Colour appears only in `block/*` fills: KPI tiles, the notice, avatars, stickers, the selected nav item and the selected row (`block-yellow`). Text on a block is `block-fg` (`#000000`), except on the dark violet `block-purple`, where text uses `text/fg` because black on it is 3.9:1. Accent never tints text, outlines or shadows.
- **Ink.** `border/ink` and `effect/shadow` are `#000000` in both schemes. The table header, the selected filter tab, the delta pills and page key 1 are filled with `border/ink` and labelled with `ink/fg` (`#fdfdfc` light, `#eeeeec` dark).
- **Status colours.** Stickers map Paid → `block-green`, Awaiting payment → `block-yellow`, Shipped → `block-blue`, Failed → `block-pink`, Refunded → `card` (neutral). Error text and outlines use `destructive` (`#e5484d`) and `destructive-text`.
- **Dark design notes.** The blocks change ramp in dark: blue goes from blue/l/5 `#c2e5ff` to blue/d/9 `#0090ff`, pink from tomato/l/5 to tomato/d/9 `#e54d2e`, green from lime/l/5 to lime/d/9 `#bdee63`. They stay saturated so black text keeps ≥5.4:1. Control boundaries change from ink to `border/control` = sand/d/10 `#7c7b74`, because black on `#31312e` is only 1.61:1.

## Typography

| Role | Family | Size / line | Weight | Tracking | Used for |
| --- | --- | --- | --- | --- | --- |
| title | Space Grotesk | 52/52 | Regular 400 | −2px | Page title "Orders" (bound to `type/title`) |
| kpi | Space Grotesk | 40/44 | Bold 700 | −1.5px | KPI values |
| heading | Space Grotesk | 18/24 | Bold 700 | −0.3px | Brand, panel titles, notice heading |
| button | Space Grotesk | 14/20 | Bold 700 | −0.3px | Button labels, customer names |
| body | Space Grotesk | 14/20 (13/18 small) | Regular 400 | 0 | Subtitle, channel, activity text |
| label | Space Mono | 11/16 | Bold 700, UPPERCASE | +0.6px | Nav, column headers, stickers, KPI labels |
| data | JetBrains Mono | 14/20 Bold; 13/18 Regular | 700 / 400 | 0 | Order IDs, totals, dates, field values |

- All three families are OFL on Google Fonts. Fallbacks: `"Space Grotesk", ui-sans-serif, system-ui`; `"Space Mono", "JetBrains Mono", ui-monospace`.
- Headings are regular weight at display size, following Gumroad. Only the KPI numerals are bold.
- Field values and placeholders are mono (`JetBrains Mono Regular 14/20`), so inputs read as typed data.
- Tabular numerals: the mono faces are fixed-width. `"tnum"` for Space Grotesk numerals is pending in #2414 and #2416, because Figma cannot set or verify it.

## Layout

- **Canvas:** 1280 wide. Top bar 76px tall (padding 0/32, gap 28) with a 2px ink bottom rule. Body padding 36px top and 32px sides; vertical rhythm between regions is 32px.
- Orders fixture composition:

  1. Header: breadcrumb label, 52px title with the rotated sticker, subtitle; Export and Create order buttons right.
  2. KPI row: four 289×190 tiles, gap 20, padding 18/20, internal gap 10, each with a 12-bar ink bar chart.
  3. Orders panel (1216 wide): toolbar 72 (padding 16/20) with joined filter tabs, header row 44, six rows of 60 with a 2px ink bottom rule, footer 66 with 36px page keys.
  4. Bottom row (gap 24): order form 812 wide (padding 22/24/24/24, gap 20, two-column field rows with gap 16) and a 380-wide side column (notice, then recent activity; gap 24).
- **Table columns:** select 52px, order 112px, customer `minmax(0, 1fr)`, channel 136px, status 176px, date 132px, total 120px, actions 48px. Cells have 0/8 padding inside their track. The customer track gets the rest of the 1216px panel after subtracting its 2px borders, row padding and column gaps. A fixed 412px customer width, and totals derived from it, do not fit once padding and borders are counted; compute the track from the layout instead. Never shrink the type or clip a column to force the arithmetic.
- **Density:** Brutal sets no density mode and binds no density variable; its geometry is fixed. The effective density is between Comfortable and Chunky (44px controls, 60px rows). Treat these numbers as Brutal's own until the density mapping lands in #2414.

## Elevation & Depth

Brutal shows depth only with a hard offset slab. It uses no blur, gradient or tint.

| Level | Recipe (CSS) | Applied to | Why |
| --- | --- | --- | --- |
| Flat | `box-shadow: none` | Rows, nav items, stickers, inputs at rest, tabs, avatars | Printed on the block; not an object |
| Slab S | `3px 3px 0 0 #000` | Logo tile 40×40, "Next" page button 36px | Small objects get a short throw |
| Slab M | `4px 4px 0 0 #000` | Buttons 44px (Export, Create order, Cancel, Save) | Pressable controls |
| Slab L | `6px 6px 0 0 #000` | KPI tiles, Orders panel, order form, notice, activity panel | Regions |
| Focus | `4px 4px 0 0 var(--ns-ring)` | Focused field | Replaces nothing; the 2px ink border stays |
| Invalid | `4px 4px 0 0 var(--ns-destructive)` | Invalid field | Paired with icon and helper text |
| Pressed | `none`, content translated +4/+4 | Button `State=Pressed` | The slab collapses into the page |

- The shadow colour is `effect/shadow` = `#000000` in **both** schemes. A pale offset in dark is an error.
- Pressed keeps the hit area. The pressed variant changes padding from 0/18/0/16 to 4/14/0/20.

## Shapes

- **Radius scale:** `rounded.xs` 4 (checkbox, delta pill), `sm` 6 (nav item, page key, avatar), `md` 8 (button, input, search, logo), `lg` 12 (tiles, panels), `full` (stickers, switch). Theme variables: `radius/control` 8, `radius/input` 8, `radius/card` 12, `radius/badge` 999.
- **Strokes:** 2px inside strokes everywhere: panels, buttons, inputs, stickers, avatars, checkbox, switch, row rules. Activity dividers are 1.5px dashed `[6, 4]`.
- **Joined tabs:** the filter tabs overlap by 2px (gap −2) so neighbouring borders merge; only the outer corners are rounded.
- **Tilt:** one sticker per screen may rotate (−6° on `LIVE SYNC`). Never rotate controls.

## Components

| Component | Variant used | Anatomy and states |
| --- | --- | --- |
| Button | `Brutal/Button` Kind = Primary (block-yellow), Secondary (card), Ink (ink fill) | 44 tall, radius 8, 2px `border/ink`, Slab M. Pressed: no shadow, content +4/+4. Toolbar instances are 40 tall without shadow. Kind=Ink (not used on the Orders screens): `border/ink` fill with the label and "+" glyph in `ink/fg`, *measured* at `#eeeeec` on `#000000` (18.08:1) in dark and `#fdfdfc` (20.63:1) in light; matches the YAML `button-ink` entry. |
| Input / select | `Brutal/Input` Default, Focus, Error | Label (Space Mono 11) above a 44px field with radius 8 and a mono value. Default border is `border/control`; Focus keeps a 2px ink border and adds the 4/4 ring slab; Error uses a `destructive` border, 4/4 destructive slab, trailing alert icon and helper "This code expired on Oct 15. Remove it or choose another." |
| Textarea | One-off frame; no library component yet | 92px field, radius 8, `border/control`, counter helper "Optional · 0 / 500". |
| Checkbox | `Brutal/Checkbox` 22×22, radius 4 | Unchecked: card fill, `border/control`. Checked: `primary` fill, `primary-fg` check, 2px `primary-fg` keyline. |
| Switch | `Brutal/Switch` 52×28 pill | Off: card fill, `border/control`, black thumb with a 1px `border/control` inner contour. On: `block-green`, ink border. |
| Tabs | `Brutal/Tab` | Joined row, 40 tall. Selected: ink fill, `ink-fg` label and count. Unselected: card fill. |
| Table row | Frames `Row — *` | 60 tall, 2px ink bottom rule. Selected: `block-yellow` fill, checked box. Header: ink fill, `ink-fg` Space Mono labels. |
| Sticker (badge) | `Brutal/Sticker` Tone = Success, Warning, Error, Info, Neutral | 26 tall pill, 2px ink border, Space Mono Bold 11 uppercase. "AWAITING PAYMENT" is spelled out (min width 144). |
| KPI tile | Frames `KPI — *` | 289×190, radius 12, Slab L, block fill, label, 40px value, ink delta pill (radius 4) with `ink-fg` arrow and %, 12 ink bars. |
| Notice | `Notice` frame | `block-pink` slab, ink alert disc, Space Grotesk 18 heading, underlined mono "REVIEW ORDERS" link. |
| Nav item | `Nav — *` | 28 tall, radius 6, no fill. Selected: `block-yellow`, 2px ink border, 32 tall. |
| Top bar | `Top bar` frame | Logo tile with Slab S, nav, 240×40 search with `border/control`. |
| Page keys | `Page *` | 36×36, radius 6, `border/control`; current page ink-filled. |
| Dialog / sheet | Not drawn | Overlay roles exist (`overlay` 40% / 66% black). Anatomy is pending in #2416. |

Hover, disabled and focus-visible states for buttons, tabs and rows are not drawn yet; they are pending in #2416.

## Do's and Don'ts

- **Do** keep outlines and hard shadows `#000000` in dark. Symptom to avoid: the dark scheme is the light scheme with its colours inverted, and it becomes unreadable.
- **Don't** let any header, tab or slab turn white in dark. The table header and selected tab are ink-filled in both schemes.
- **Do** keep the dark canvas (`#31312e`) lighter than the dark panels (`#191918`) so slabs still read as objects.
- **Do** use `border/control` for every boundary a user has to find: inputs, search, checkbox, switch track and thumb contour, page keys. Black on dark measures 1.61:1.
- **Don't** use `border/control` on decorative panel outlines; those stay ink.
- **Do** pair the colour blocks with black text and check each pair. Dark blue, pink and green give 6.43, 5.43 and 15.57:1.
- **Don't** put black text on the dark violet block (3.9:1). Avatar labels on `block-purple` use `text/fg`: 4.64:1 dark, 12.09:1 light.
- **Do** bind chart bars and delta arrows to ink roles (`primary/fg`, `ink/fg`), never to the block colour.
- **Don't** label an ink-filled surface with `text/inverse`; it flips to near-black in dark, where an Ink button label bound to it measures 1.05:1. Use `ink/fg`, as the table header, selected tab, delta pills and Ink button do.
- **Do** show focus as a separate hard 4/4 offset in `border/ring` while keeping the ink border. Never signal focus by border colour alone.
- **Do** collapse the slab on press (shadow 0, content +4/+4) and keep the hit area.
- **Do** use one label per command ("Create order" everywhere) and spell statuses in full.
- **Don't** add blur, gradients or soft shadows; Brutal's depth is only the offset slab.
- **Don't** make headings bold. Display and title are Space Grotesk Regular.
- **Don't** add a second accent family. Blocks come from `block/*` only.

## Iconography & Imagery

- Stroke icons come from `icon/*` instances named after Lucide (ISC) glyphs: search, chevron, arrow, alert. They are 16–18px and ink coloured.
- Avatars are 34×34 colour blocks with radius 6, a 2px ink border and Space Mono Bold initials. No photos.
- No illustration or backdrop. Gumroad's coins and mascots must not be used.

## Motion & States

- **Pressed:** the slab collapses (shadow 0) and content moves +4/+4. **Hover** (anchor behaviour, not drawn): neobrutalism.dev moves the element toward its shadow; Gumroad lifts with `translate(-0.25rem)`. The choice between them is pending in #2416; either way the hit area stays fixed.
- **Easing:** the anchor animates `transform` only with `ease-out`; no colour fades. Durations are pending in #2419.
- **Reduced motion:** drop the translation and keep the shadow change.
- **Selection:** a selected row fills with `block-yellow`; a selected tab fills with ink. Both also change the checkbox or label, so selection never relies on colour alone.

## Accessibility

Ratios are *(token)* arithmetic from the resolved tokens. Dark values were also *measured* on rendered pixels.

| Pair | Light | Dark |
| --- | --- | --- |
| `fg` on `bg` / on `card` | 15.67 / 16.30 | 11.23 / 15.14 |
| `muted-fg` on `card` | 6.04 | 8.39 |
| `block-fg` on blue / pink / green block | 15.95 / 14.76 / 15.75 | 6.43 / 5.43 / 15.57 |
| `ink-fg` on ink header | 20.63 | 18.08 |
| Control boundary on canvas | ink 20.19 | `#7c7b74` on `#31312e` 3.07 (3.0710 on rendered pixels) |
| Focus offset `ring` on `bg` | 4.58 | 6.21 |

- Hit targets: buttons 44, fields 44, page keys 36, checkbox 22 (row cell is 52 wide), switch 52×28.
- Known exceptions: black panel outlines on dark panels measure 1.19:1. They are decorative; `border/control` provides the 3:1 boundary.
- RTL: mirror the slab offset (`-4px 4px`) and the pressed translation. Pending in #2419.

## NetScript Mapping

| Layer | Value |
| --- | --- |
| Figma Theme mode | `Brutal` |
| Base gray × accent | Neutral × Ink by default. Brutal's Theme mode aliases its own sand gray and amber accent, so neither base mode changes the output |
| Density | none set (Comfortable by default); no Density variable bound |
| Flavor | n/a |
| `data-theme` | `brutal` |
| Language roles | none. Brutal uses core roles plus the shared `block/*`, `border/ink`, `border/control` and `ink/fg` |

- **Primitive bindings:** none known. Brutal binds semantic roles only.
- **Ink button:** the `Brutal/Button` Kind=Ink label and its "+" icon bind `ink/fg`, in the rest and pressed states.
- **Status.** Values come from the NetScript Figma library. Role and mode names, including the shared `block/*` names, are provisional until the token export in #2414. Hover, disabled and focus-visible states on buttons and tabs, dialog anatomy and the pressed state are pending in #2416. Keyboard, viewport, reduced-motion and RTL behaviour are pending in #2419.

## Sources

- **References:** Gumroad (`github.com/antiwork/gumroad`, MIT; `app/javascript/components/ui/*`), neobrutalism.dev (MIT, `ekmas/neobrutalism-components`). What is taken and what must not be copied is listed under *Overview* → Anchor.
- **Demo content:** the "Northwind" store, orders SO-10477…SO-10482, customer names and emails, all amounts, KPI values and deltas, activity entries and the AUTUMN24 code are invented demo data from the shared Orders fixture.
