# Digital Rust UI Specification

Part of Digital Rust Specification v1.2.1

This document is the canonical specification for Digital Rust as a **user interface
theme**: surfaces, elevation, interaction physics, and component definitions. It is
a sibling to the *Digital Rust Syntax Highlighting Specification*, which owns the
colour palette, token classification, editor chrome, and terminal configuration.
The palette itself is defined there and is not re-specified here; this document
references colours by name only.

A conforming UI implementation uses the named colours from the syntax
specification, and follows the component, elevation, and interaction rules below.

**Semantic tokens.** Component implementations reference the semantic `--dr-*`
tokens defined in `tokens.css`, never raw palette values. On top of the
surface and text tokens, the semantic layer is:

| Token | Colour | Role |
| --- | --- | --- |
| `--dr-accent` | Digital Rust | Primary brand accent: primary buttons, checked states, active links |
| `--dr-accent-hover` | Firewall Breach | Primary hover fill; Ghost Pixel on it passes AA (4.66:1), raw Amber Alert does not |
| `--dr-success` | Memory Leek | Success borders, text, fills |
| `--dr-warning` | Stack Overglow | Warning borders, text, fills; the focus ring |
| `--dr-danger` | Amber Alert | Error borders and fills |
| `--dr-danger-text` | Amber Alert Text | AA-compliant error text on base/elevated surfaces |
| `--dr-info` | Dead Thread | Informational accents |
| `--dr-border-color` | Dark Packet | The 2px wall on interactive elements |
| `--dr-border-color-well` | Bad Sector | Recessed input wells |
| `--dr-border-color-hover` | Digital Rust | Ghost-control hover, focused wells |
| `--dr-border-color-invalid` | Amber Alert | Invalid controls |

## Contents

- [Design Principles](#design-principles)
- [Surfaces & Texture](#surfaces--texture)
- [Elevation](#elevation)
- [Interaction Physics](#interaction-physics)
- [Typography in UI](#typography-in-ui)
- [Components](#components)
  - [Buttons](#buttons)
  - [Inputs & Text Areas](#inputs--text-areas)
  - [Checkboxes](#checkboxes)
  - [Toggles](#toggles)
  - [Sliders](#sliders)
  - [Tabs](#tabs)
  - [Menus & List Boxes](#menus--list-boxes)
  - [Modals & Dialogs](#modals--dialogs)
  - [Toasts & Notices](#toasts--notices)
  - [Tooltips & Popovers](#tooltips--popovers)
  - [Badges & Tags](#badges--tags)
  - [Callouts & Panels](#callouts--panels)
  - [Scrollbars](#scrollbars)
  - [Links](#links)
  - [Status Bars](#status-bars)
  - [Tables](#tables)
- [States](#states)
- [Accessibility](#accessibility)
- [Do's and Don'ts](#dos-and-donts)

## Design Principles

Digital Rust interfaces are **tactile panels in a failing server rack**. Every
interactive element should feel like a physical piece of chunky old hardware:
a switch you can press, a bezel that catches light, a surface that has weight.

Five rules carry the whole system:

1. **Everything physical has an edge.** Interactive elements carry 2px Dark
   Packet borders. Borders are walls, not decoration.
2. **Everything raised casts a hard shadow.** Offset solid shadows, no blur,
   drawn in Bad Sector. Light in this system is directional and warm.
3. **Everything raised catches light.** Elevated and interactive elements carry
   the inner highlight, `inset 0 1px 0 rgba(255, 255, 255, 0.1)`, a faint
   light-line along the top edge. This is the bevel of the panel.
4. **Everything pressable presses.** Rest has offset; hover grows the offset and
   lifts the element; active collapses the offset and drives the element into
   the rack. No interactive element is allowed a static hover.
5. **Nothing is flat.** Surfaces carry structural noise and scanlines. The only
   exemptions are interactive text surfaces (inputs, text areas, editable
   regions), which stay clean for legibility, and `prefers-reduced-motion`.

The system rejects: blurred drop shadows, pure black (`#000`) anywhere,
border-radius above 6px, hairline decorative borders, and any cold blue-purple
dark-theme material. These are defined in the syntax specification's named
rules and apply equally to UI.

## Surfaces & Texture

The rust ramp is the only neutral scale. Semantic surface tokens map onto it:

| Token | Colour | Role |
| --- | --- | --- |
| `--dr-surface-base` | Event Horizon `#110402` | Page background; input wells; code blocks |
| `--dr-surface-secondary` | Null Pointer `#230905` | Elevated chrome: tab bars, gutters, sidebars |
| `--dr-surface-elevated` | Core Meltdown `#340d07` | Cards, popovers, menus, modals, filled hovers |
| `--dr-surface-highlight` | Bad Sector `#46120a` | Hover fills, active list items, shadow colour |
| `--dr-surface-active` | `#5a1810` | Scrollbar hover, pressed wells |

**The Recessed Well Rule.** Inputs and editable regions sit *below* the panel,
not above it. A well uses the darkest surface (Event Horizon), a 2px Bad Sector
border, and no offset shadow. Wells never rise on hover; they respond through
border colour, not elevation. (See [Inputs](#inputs--text-areas).)

**Texture exemption.** The Flat Surface Failure Rule (syntax specification)
applies to all *ambient* surfaces: page backgrounds, cards, panels, modals.
Interactive text surfaces — inputs, text areas, code editors — are exempt.
Texture inside a text field fights the text; legibility outranks atmosphere.

**Implementation.** The texture is two full-page fixed overlays, stacked above
content with `pointer-events: none`: a faint noise layer (SVG `feTurbulence`
tile at ~2% opacity) and a scanline layer (4px repeating band in
`--dr-scanline` directly under the noise). Content stays below both.

```css
body {
	position: relative;
	z-index: var(--dr-z-content);
}
body::before { /* noise */
	content: "";
	position: fixed;
	inset: 0;
	background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 256 256' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
	opacity: 0.02;
	pointer-events: none;
	z-index: var(--dr-z-noise);
}
body::after { /* scanlines */
	content: "";
	position: fixed;
	inset: 0;
	background: repeating-linear-gradient(0deg,
		transparent,
		transparent 2px,
		var(--dr-scanline) 2px,
		var(--dr-scanline) 4px);
	pointer-events: none;
	z-index: calc(var(--dr-z-noise) - 1);
}
@media (prefers-reduced-motion: reduce) {
	body::before, body::after { content: none; }
}
```

The overlays suppress entirely under `prefers-reduced-motion: reduce` and never
render inside wells.

## Elevation

All structural shadows are offset solids in Bad Sector (`--dr-surface-highlight`)
with zero blur. Light is always top-left; shadows fall down-right.

| Token | Value | Use |
| --- | --- | --- |
| `--dr-shadow-offset-sm` | `2px 2px 0 0` | Resting interactive elements: buttons, checkboxes, toggles |
| `--dr-shadow-offset-md` | `3px 3px 0 0` | Raised containers: menus, toasts, callouts, terminals |
| `--dr-shadow-offset-lg` | `4px 4px 0 0` | Highest layer: modals, lightboxes, drag ghosts |
| `--dr-shadow-hover-md` | `4px 4px 0 0` | Hover state for elements resting at `offset-sm` |
| `--dr-shadow-active` | `0 0 0 0` | Pressed state; the element sits flush |
| `--dr-shadow-glow-sm` | `0 0 10px rgba(175, 46, 26, 0.4)` | Radiated heat on primary hover / focused accents |
| `--dr-shadow-glow-md` | `0 0 20px rgba(175, 46, 26, 0.4)` | Hero-level emphasis only |
| `--dr-shadow-inner-highlight` | `inset 0 1px 0 rgba(255, 255, 255, 0.1)` | Top-edge bevel on raised/interactive elements |
| `--dr-shadow-inner-lowlight` | `inset 0 -1px 0 rgba(17, 4, 2, 0.6)` | Bottom-edge shade for wells and thumbs |

**The No Blur Rule.** Blur radius is zero everywhere except the glow shadows,
which simulate radiated heat, not material depth.

**The Bevel Rule.** The inner highlight accompanies every offset shadow on an
interactive or elevated element. An element with `offset-sm/md/lg` and no inner
highlight is unfinished. The two are stacked:

```css
box-shadow:
	var(--dr-shadow-offset-sm),
	var(--dr-shadow-inner-highlight);
```

## Interaction Physics

The press cycle is the system's signature motion. It applies to buttons,
checkboxes, chips, tabs, and any element that behaves like a switch.

| State | Transform | Shadow |
| --- | --- | --- |
| Rest | `translate(0, 0)` | resting offset (`offset-sm` or `offset-md`) + inner highlight |
| Hover | `translate(-2px, -2px)` | offset grows 2px per axis (`hover-md`) + inner highlight |
| Active | `translate(2px, 2px)` | `0 0 0 0`; element drives into the rack |

- Transitions use `--dr-duration-fast` (150ms) with
  `--dr-ease-default` (`cubic-bezier(0.4, 0, 0.2, 1)`).
- The element translates *with* the shadow change: hover lifts toward the light
  (up-left), active presses away from it (down-right). The shadow offset and the
  translation are always the same magnitude and direction.
- **Focus visible**: 2px Stack Overglow outline, 2px offset. Focus never removes
  the resting shadow. Keyboard focus and mouse hover are independent states.
- **Disabled**: no transform, no shadow, muted colours, `cursor: not-allowed`.
  A dead switch does not click.
- All of the above is suppressed under `prefers-reduced-motion: reduce`: the
  full state *colours* still apply, but transform and transition are removed.

```css
.dr-button {
	transition:
		transform var(--dr-transition-fast),
		box-shadow var(--dr-transition-fast),
		background-color var(--dr-transition-fast),
		border-color var(--dr-transition-fast),
		color var(--dr-transition-fast);
}
.dr-button:hover  { transform: var(--dr-press-hover); }
.dr-button:active { transform: var(--dr-press-active); }
```

## Typography in UI

Digital Rust pairs three typographic roles. The guidance below describes each
role **generically first**; the named faces are examples of the role, not the
only acceptable choices.

- **Display, headings, and labels** — a condensed, technical, near-geometric
  sans with a slightly mechanical, engineered feel. Set all-caps with wide
  tracking for short strings (titles, labels, badges); never all-caps at body
  size. Example pairing: Rajdhani, with Saira SemiCondensed and Trebuchet MS
  as fallbacks. This is the "embossed server panel" voice.
- **Body and content** — a warm slab serif (or a humanist serif with sturdy,
  bracketed terminals) that stays comfortable over long sessions. Sentence case
  at body size. Example: Zilla Slab, falling back to Bitter, Source Serif 4,
  or Georgia.
- **Monospace readouts** — a monospace with tabular numerals for any value
  where character alignment matters: status bars, hex values, version stamps,
  code. Example: IBM Plex Mono, with Space Mono, Fira Code, Cascadia Code, or
  the platform mono as fallbacks.

These are **general recommendations, not rules that cannot be diverged from**.
Appropriateness to the content and the audience is the most important
criterion: pick faces that read clearly at the required sizes and fit the
product's voice, and treat the guidance above as a tested starting point
rather than a constraint. Where a chosen face changes the character of the
theme, favour warmth and mechanical honesty over decoration.

Applied to components, the three roles surface as:

- **Button and tab labels**: heading/label sans (e.g. Rajdhani) at 600–700,
  uppercase, 0.05em tracking, verb + object ("Save changes", not "OK").
- **Badges and tags**: heading/label sans (e.g. Rajdhani) at 700, uppercase,
  0.08em tracking, 0.75rem.
- **Panel and card titles**: heading/label sans (e.g. Rajdhani) at 700,
  uppercase, 0.05em tracking, Fatal Error colour (the One Heading Colour Rule).
- **Inputs and text areas**: body serif/sans (e.g. Zilla Slab), 1rem, no
  uppercase. Placeholder text is muted and italic.
- **Readouts, status bars, hex values, version stamps**: monospace
  (e.g. IBM Plex Mono), 0.875rem or smaller, tabular numerals.

Across all roles, weights, tracking, and case matter more than the exact face;
 swapping in an equivalent category with matching metrics keeps the system
 intact.

## Components

### Buttons

The signature component. A hardware panel switch: thick edge, hard shadow,
light-catching bevel, physical travel.

**Base (all buttons)**

| Property | Value |
| --- | --- |
| Padding | `0.5rem 1.5rem` (`--dr-space-sm --dr-space-lg`) |
| Border | `2px solid` (colour per variant) |
| Radius | `4px` (`--dr-radius`) |
| Font | heading/label sans (e.g. Rajdhani) at 600, uppercase, `0.05em` tracking, `--dr-text-sm` |
| Shadow | resting offset + inner highlight |
| Cursor | `pointer` |
| Interaction | full press cycle at 150ms |

**Variants**

| Variant | Rest | Hover | Active |
| --- | --- | --- | --- |
| **Default / Ghost** | Transparent bg, Phosphor Smoke text, Dark Packet border, `offset-sm` | Core Meltdown fill, Ghost Pixel text, Digital Rust border, `hover-md`, lifts | `offset` collapses, presses in |
| **Primary** | Digital Rust bg, Ghost Pixel text, Digital Rust border, `offset-md` | Firewall Breach bg and border, `hover-md` + `glow-sm`, lifts | `offset` collapses, glow removed, presses in |
| **Success** | Memory Leek border and text | Memory Leek bg, Event Horizon text | presses in |
| **Warning** | Stack Overglow border and text | Stack Overglow bg, Event Horizon text | presses in |
| **Error** | Amber Alert border, Amber Alert Text (`#cb6353`) text | Amber Alert bg, Event Horizon text | presses in |
| **Disabled** | Bad Sector bg, muted text, no border colour shift | no response | no response; `cursor: not-allowed` |

Reference CSS:

```css
.dr-btn {
	padding: var(--dr-space-sm) var(--dr-space-lg);
	border: 2px solid var(--dark-packet);
	border-radius: var(--dr-radius);
	background: transparent;
	color: var(--dr-text-secondary);
	font-family: var(--dr-font-heading);
	font-weight: 600;
	font-size: var(--dr-text-sm);
	text-transform: uppercase;
	letter-spacing: 0.05em;
	box-shadow: var(--dr-shadow-offset-sm), var(--dr-shadow-inner-highlight);
	cursor: pointer;
	transition:
		transform var(--dr-transition-fast),
		box-shadow var(--dr-transition-fast),
		background-color var(--dr-transition-fast),
		border-color var(--dr-transition-fast),
		color var(--dr-transition-fast);
}
.dr-btn:hover {
	background: var(--dr-surface-elevated);
	border-color: var(--digital-rust);
	color: var(--dr-text-primary);
	transform: var(--dr-press-hover);
	box-shadow: var(--dr-shadow-hover-md), var(--dr-shadow-inner-highlight);
}
.dr-btn:active {
	transform: var(--dr-press-active);
	box-shadow: var(--dr-shadow-active);
}
.dr-btn:focus-visible {
	outline: var(--dr-focus-ring);
	outline-offset: var(--dr-focus-ring-offset);
}

.dr-btn-primary {
	background: var(--digital-rust);
	border-color: var(--digital-rust);
	color: var(--dr-text-on-accent);
	box-shadow: var(--dr-shadow-offset-md), var(--dr-shadow-inner-highlight);
}
.dr-btn-primary:hover {
	background: var(--firewall-breach);
	border-color: var(--firewall-breach);
	transform: var(--dr-press-hover);
	box-shadow:
		var(--dr-shadow-hover-md),
		var(--dr-shadow-glow-sm),
		var(--dr-shadow-inner-highlight);
}
```

**Rules**

- One primary button per view. Primary carries the brand; two primaries on one
  screen is a visual shouting match.
- Labels are short verbs or verb + object, never "OK" / "Submit" / "Click here".
- Icon + text buttons keep the icon at text size, `0.25rem` gap.
- Full-pill radius is forbidden on buttons; `4px` only.

### Inputs & Text Areas

Recessed wells. The darkest surface on the page; the user types into the machine.

| Property | Value |
| --- | --- |
| Background | Event Horizon (`--dr-surface-base`) |
| Border | `2px solid` Bad Sector (`--dr-border-color-well`) |
| Radius | `4px` |
| Padding | `0.5rem 0.75rem` |
| Font | body font, `--dr-text-base`, Ghost Pixel text |
| Shadow | none at rest (wells do not rise) |
| Placeholder | muted text (`--dr-text-muted`), italic |
| Hover (unfocused) | border shifts to Dark Packet (`--dr-border-color`) |
| Focus | border shifts to Digital Rust (`--dr-border-color-hover`); 2px Stack Overglow outline at 2px offset |
| Disabled | transparent border, muted text, no shadow |
| Invalid | Amber Alert border; error message in Amber Alert Text |

```css
.dr-input {
	background: var(--dr-surface-base);
	border: 2px solid var(--dr-surface-highlight);
	border-radius: var(--dr-radius);
	padding: var(--dr-space-sm) 0.75rem;
	color: var(--dr-text-primary);
	font-family: var(--dr-font-body);
	font-size: var(--dr-text-base);
	transition:
		border-color var(--dr-transition-fast),
		box-shadow var(--dr-transition-fast);
}
.dr-input:hover:not(:focus) { border-color: var(--dark-packet); }
.dr-input:focus {
	outline: var(--dr-focus-ring);
	outline-offset: var(--dr-focus-ring-offset);
	border-color: var(--digital-rust);
}
.dr-input::placeholder {
	color: var(--dr-text-muted, rgba(239, 213, 209, 0.5));
	font-style: italic;
}
```

**Rules**

- Wells are exempt from noise/scanline texture (see The Recessed Well Rule).
- No offset shadows on wells. Depth on inputs is communicated by darkness,
  not elevation.
- Labels sit above the input in the label sans (e.g. Rajdhani), uppercase at
  `--dr-text-xs`, Phosphor Smoke.

### Checkboxes

A small square switch with the full press cycle. 16px box, 2px radius.

| State | Style |
| --- | --- |
| Rest | Event Horizon bg, 2px Dark Packet border, `offset-sm` shadow |
| Hover | Digital Rust border, lifts (`-2px, -2px`), `hover-md` |
| Active | presses (`2px, 2px`), shadow collapses |
| Checked | Digital Rust bg and border; Ghost Pixel ✓ mark, 700 weight |
| Focus visible | 2px Stack Overglow outline, 2px offset |
| Disabled | no shadow, muted border, `not-allowed` |

The ✓ glyph is drawn centred, 12px at 16px box size. Indeterminate state uses a
Ghost Pixel em-dash block in place of the check.

### Toggles

A sliding rack switch. Track: Bad Sector bg at rest, Digital Rust when enabled,
always with a 2px Dark Packet border and `offset-sm` shadow. Thumb: Ghost Pixel,
2px radius, its own `1px 1px 0 0` offset in Bad Sector plus inner lowlight.
The thumb slides at 150ms; the track does not translate.

### Sliders

Track: 4px-high Event Horizon well with 1px Bad Sector border. Fill (the
"used" portion): Digital Rust. Thumb: 16px square, 2px radius, Ghost Pixel with
2px Dark Packet border and `offset-sm` shadow; lifts on hover-drag, presses on
active-drag. Thumb never exceeds 2px radius — sliders are machined parts,
not pills.

### Tabs

Tab bar: Core Meltdown bg with a 2px Dark Packet bottom border. Tabs: Phosphor
Smoke text, 2px radius top corners only. Hover: Ghost Pixel text, Bad Sector bg.
Active tab: Null Pointer bg (surface-secondary), Ghost Pixel text, and a 2px
Digital Rust bottom border that overlaps the bar's border — the active tab is
the one still receiving power. Modified/unsaved indicator: Stack Overglow dot
or `● MOD` label.

### Menus & List Boxes

Container: Core Meltdown bg, 2px Dark Packet border, 4px radius,
`offset-md` + inner highlight, `0.25rem` padding. Items: Phosphor Smoke, 2px
radius, `0.25rem 0.5rem` padding. Hover/selected item: Bad Sector bg, Ghost
Pixel text. Separators: 1px Bad Sector line, full-bleed. Menus never blur the
content behind them; they are solid panels bolted over it.

### Modals & Dialogs

The highest layer. Core Meltdown bg, 2px Dark Packet border, 4px radius,
`offset-lg` + inner highlight. Title in Fatal Error, label sans (e.g. Rajdhani)
at 700 uppercase.
Backdrop: warm-tinted scrim, `rgba(17, 4, 2, 0.7)` — never pure black, never
blurred. The footer action row carries at most one primary button. Modals do not
animate in with scale/bounce; a 150ms fade is the only permitted entry motion.

### Toasts & Notices

Bricked Board bg (a hotter panel than modals — notices radiate residual heat),
Ghost Pixel text, 2px Dark Packet border, 4px radius, `offset-md` + inner
highlight. Optional 3px left accent border in the semantic colour (Memory Leek
success, Stack Overglow warning, Amber Alert error, Dead Thread info). Auto-
dismiss toasts show a thin Digital Rust progress line along the bottom edge.

### Tooltips & Popovers

Core Meltdown bg, 2px Dark Packet border, 4px radius, `offset-md` + inner
highlight. Text: Phosphor Smoke at `--dr-text-sm`. No arrow stems; the offset
shadow alone establishes which surface the tooltip floats above. Hover-preview
popovers (rich content) use `offset-lg` and may contain panels; plain text
tooltips use `offset-md`.

### Badges & Tags

Semantic status chips: small, dense, tracked. 4px radius,
`0.2rem 0.6rem` padding, label sans (e.g. Rajdhani) at 700 uppercase, 0.08em
tracking, 0.75rem.

| Kind | Text | Background | Border |
| --- | --- | --- | --- |
| Add / Success | Memory Leek | 15% Memory Leek (`--memory-leek-15`) | 1px Memory Leek 30% (`--memory-leek-30`) |
| Modified / Info | Dead Thread | 15% Dead Thread (`--dead-thread-15`) | 1px Dead Thread 30% (`--dead-thread-30`) |
| Delete / Error | Amber Alert Text | 10% Amber Alert (`--amber-alert-10`) | 1px Amber Alert 25% (`--amber-alert-25`) |
| Warning | Stack Overglow | 15% Stack Overglow (`--stack-overglow-15`) | 1px Stack Overglow 30% (`--stack-overglow-30`) |

Badges are static indicators: no press cycle, no shadow. Full-pill radius is
permitted on badges only (they are rivets, not panels).

### Callouts & Panels

Core Meltdown bg, 2px Dark Packet border, 4px radius, `offset-md` + inner
highlight, `1.5rem` internal padding. Semantic variants tint the title and add a
3px left border in Dead Thread (note/info), Stack Overglow (warning), or Amber
Alert (error/danger). The 3px left accent on callouts is a deliberate exception
to the no-accent-stripe rule; it exists so semantic blocks are identifiable at
scroll speed. Panels that respond to hover (cards, palette chips) use the press
cycle with `offset-sm` rest.

### Scrollbars

Thin (8-10px). Track: transparent. Thumb: Dark Packet at rest, Daemon Blood on
hover, surface-active (`#5a1810`) on drag. 2px radius. Scrollbars are machine
rails: they never glow, never widen past 12px, and never disappear on idle
(visibility of scroll position is a readability concern).

### Links

Default: Phantom Current, 1px underline, 3px offset. Hover: Fatal Error, 2px
underline. Visited: Corrupted Cache. Active: Digital Rust. Focus: 2px Stack
Overglow outline, 2px offset. Underline style carries semantics: solid for
links, wavy for diagnostics. Never style a diagnostic squiggle as a link or
vice versa.

### Status Bars

Bricked Board bg, Ghost Pixel text, 2px Dark Packet top border, monospace
(e.g. IBM Plex Mono) at `--dr-text-xs`, `0.25rem 0.5rem` item padding. Items respond to hover with
Phantom Current text only — status bar items do not lift. Semantic items:
Memory Leek (success/OK), Stack Overglow (warning), Amber Alert Text (error).

### Tables

Header row: label sans (e.g. Rajdhani) at 700 uppercase `--dr-text-xs`, Fatal
Error text, 2px Dark Packet bottom border. Body: body serif/sans (e.g. Zilla
Slab), Ghost Pixel. Row separators: 1px Bad Sector. Row hover: Bad Sector bg. Zebra striping is forbidden (the scanline
overlay already bands the page; double banding reads as interference).

## States

| State | Universal rule |
| --- | --- |
| Hover | Lift toward the light (`-2px, -2px`) + offset grows. Non-pressable surfaces (rows, list items) respond with Bad Sector fill instead of lift. |
| Active (press) | Drive into the rack (`2px, 2px`) + offset collapses to zero. |
| Focus visible | 2px Stack Overglow outline, 2px offset, *in addition to* resting shadow. Never `outline: none` without replacement. |
| Selected | Bad Sector bg + Ghost Pixel text (lists, menus, tabs use tab rules). |
| Disabled | Bad Sector or transparent bg, muted text, no shadow, no transform, `cursor: not-allowed`. |
| Loading / Processing | Stack Overglow with motion (spinner, pulse); under reduced motion, static Stack Overglow text label. |
| Invalid / Error | Amber Alert border on the control + Amber Alert Text message. Errors never rely on colour alone: icon or text accompanies. |

### Loading & skeletons

Busy indicators are readouts, not pressables: Stack Overglow text or spinner,
monospace, never a press cycle. Skeleton placeholders are recessed wells, not
raised panels — Event Horizon fill with a Bad Sector border and a 2px-high
Stack Overglow progress line along the bottom edge when determinate progress
is known; indeterminate work pulses the line at 400ms (`--dr-duration-slow`).
Under `prefers-reduced-motion`, the pulse is removed and the label alone
carries the state.

## Accessibility

- WCAG 2.1 AA contrast is required on all text, as defined in the syntax
  specification (Ghost Pixel on Event Horizon, 17.17:1, is the baseline).
- Amber Alert Text (`#cb6353`) is the AA-compliant text variant of Amber Alert;
  use it for error text on base/elevated surfaces, never the raw `#bf5747`.
- Every interactive element is reachable and operable by keyboard, with a
  visible focus indicator (2px Stack Overglow, 2px offset).
- State is never communicated by colour alone: errors carry icons or text,
  diffs carry +/− glyphs, focus carries an outline.
- `prefers-reduced-motion: reduce` suppresses all transforms, transitions, the
  cursor blink, and the scanline/noise overlays. All state *styling* remains.
- Touch targets are at least 24×24px; the press cycle's 2px travel does not
  count toward target size.

## Do's and Don'ts

### Do

- **Do** stack the inner highlight under every offset shadow on interactive and
  elevated elements. The bevel is half the material.
- **Do** run the full press cycle on every pressable element: rest offset,
  hover lift, active collapse.
- **Do** keep wells (inputs) dark and recessed; depth through darkness, not
  elevation.
- **Do** give every modal exactly one primary action.
- **Do** use Bricked Board for toasts and status bars; it reads as a hotter,
  more urgent panel than Core Meltdown.
- **Do** keep every border in Dark Packet at 2px unless the component spec says
  otherwise.

### Don't

- **Don't** blur any shadow. Glows simulate heat; nothing else blurs.
- **Don't** use pure black (`#000`) anywhere, including scrims and backdrops.
  Warm near-blacks only.
- **Don't** give inputs offset shadows or lift them on hover. Wells stay in
  the rack.
- **Don't** use radius above 6px on any component; 4px is the default, 2px for
  small machined parts (checkboxes, toggle thumbs, slider thumbs, menu items).
- **Don't** animate modals or toasts with scale, spring, or bounce. A 150ms
  fade is the maximum drama permitted.
- **Don't** remove focus outlines. Stack Overglow focus rings are the system's
  one non-negotiable courtesy.
- **Don't** place two primary buttons in one view.
- **Don't** apply the press cycle to passive content (headings, body text,
  badges). Static things stay bolted down.
