diff --git a/Digital Rust Syntax Highlighting Specification.md b/Digital Rust Syntax Highlighting Specification.md
index 8d76be8..56e4421 100644
--- a/Digital Rust Syntax Highlighting Specification.md
+++ b/Digital Rust Syntax Highlighting Specification.md
@@ -59,7 +59,7 @@ Digital Rust is a warm, tech-dystopian color scheme inspired by corrupted hardwa
### Token Classification
-Following _TextMate_ scoping conventions for consistent highlighting across editors.
+Following _TextMate_ scoping conventions for consistent highlighting across editors. These conventions keep highlighting consistent across editors.
#### Primary Tokens
@@ -100,13 +100,13 @@ Following _TextMate_ scoping conventions for consistent highlighting across edit
- Enum Values: `Status.OK`, `Color.RED`, `HttpStatus.NOT_FOUND`
- Language-level Constants: `__name__`, `__FILE__`, `M_PI`, `E`
-> **Design Note**: Booleans and null-like values use a distinct color from numbers to emphasize their semantic role as special language constants rather than numeric data.
+> **Design Note**: Booleans and null-like values use a distinct color from numbers. The distinct color marks their semantic role as special language constants, not numeric data.
**Comments** → `Dim Thermal Throttle (#ac6d4a)` _italic_
- Single-Line: `//`, `#`, `--`
- Multi-Line: `/* */`, ``
-- Documentation Blocks (JSDoc, Javadoc, docstrings, etc.)
+- Documentation Blocks (JSDoc, Javadoc, docstrings)
**Attributes & Decorators** → `Dead Thread (#6fa5a0)` _italic_
@@ -116,7 +116,7 @@ Following _TextMate_ scoping conventions for consistent highlighting across edit
- C# Attributes: `[Serializable]`, `[HttpGet]`
- TypeScript Decorators: `@Injectable`, `@Component`
-> **Sigil Handling**: The `@` or `#` sigil inherits the decorator color and is styled as part of the attribute token.
+> **Sigil Handling**: The `@` or `#` sigil inherits the decorator color. Style the sigil as part of the attribute token.
#### Support & Built-ins
@@ -155,7 +155,7 @@ Following _TextMate_ scoping conventions for consistent highlighting across edit
- Default Text Content
- TextMate scope: `variable`, `variable.parameter`
-**Errors & Warnings** → `Amber Alert (#bf5747)` (note: rendered text on dark backgrounds uses `--amber-alert-text` (#cb6353) for guaranteed WCAG AA compliance)
+**Errors & Warnings** → `Amber Alert (#bf5747)` (note: rendered text on dark backgrounds uses `--amber-alert-text` (#cb6353) for WCAG AA compliance)
- Syntax Errors
- Deprecated Code (with strikethrough where supported)
@@ -209,7 +209,7 @@ Following _TextMate_ scoping conventions for consistent highlighting across edit
- Spelling errors: Dotted underline using `Amber Alert (#bf5747)`
- Potential errors/warnings: Wavy underline using `Stack Overglow (#d4a759)`
-> **Accessibility Note**: Links and spelling errors must be distinguishable by underline style (solid vs. dotted), not just color.
+> **Accessibility Note**: Distinguish links and spelling errors by underline style (solid vs. dotted), not by color alone.
**Strikethrough**
@@ -220,7 +220,7 @@ Following _TextMate_ scoping conventions for consistent highlighting across edit
**Scope Prioritization**
-When multiple scopes apply to a token, apply styles in this precedence order:
+If multiple scopes apply to one token, apply styles in this precedence order:
1. **Error scopes** (highest priority) — Always override other styles
2. **Warning scopes** — Override non-error styles
@@ -228,13 +228,13 @@ When multiple scopes apply to a token, apply styles in this precedence order:
4. **Semantic token colors** — LSP/semantic highlighting
5. **Base syntax colors** (lowest priority) — TextMate grammar defaults
-> **Rule**: If a token is both an error and another role (e.g., a misspelled keyword), the error style takes full precedence. The token should display error styling, not a blend.
+> **Rule**: If a token is both an error and another role (for example, a misspelled keyword), the error style takes full precedence. The token shows the error styling, not a blend.
**Bracket Matching**
- Matching Brackets: Subtle highlight with `Bad Sector (#46120a)` background
- Unmatched Brackets: `Amber Alert (#bf5747)` with wavy underline
-- Rainbow Brackets: Optional, cycling through: `Dead Thread`, `Stack Overglow`, `Fractured Shell`, `Blue Screen`, `Thermal Throttle`, `Memory Leek`
+- Rainbow Brackets: Optional. If enabled, cycle through: `Dead Thread`, `Stack Overglow`, `Fractured Shell`, `Blue Screen`, `Thermal Throttle`, `Memory Leek`
---
@@ -261,7 +261,7 @@ Configuration files use a distinct key/value visual hierarchy:
- Colons, commas, brackets
- YAML dashes for list items
-> **Design Note**: Keys and values are intentionally colored differently to make hierarchical structure immediately visible.
+> **Design Note**: Keys and values use intentionally different colors. The difference makes the hierarchical structure immediately visible.
### Markdown & Rich Text
@@ -311,7 +311,7 @@ Configuration files use a distinct key/value visual hierarchy:
- `<`, `>`, ``, `/>`
-**Template Languages (JSX, Vue, Handlebars, EJS, etc.)**
+**Template Languages (JSX, Vue, Handlebars, EJS)**
- Template Delimiters (`{}`, `{{}}`, `<%`, `%>`) → `Copper Trace (#d7968c)`
- Embedded Expressions → Follow host language syntax rules
@@ -340,7 +340,7 @@ Configuration files use a distinct key/value visual hierarchy:
- `@media`, `@import`, `@keyframes` → `Fatal Error (#cf8175)`
-**Utility-First (Tailwind, etc.)**
+**Utility-First (Tailwind and similar frameworks)**
- Class Names in HTML → `Dead Thread (#6fa5a0)` (treat as structural labels)
@@ -361,7 +361,7 @@ Configuration files use a distinct key/value visual hierarchy:
- `${`, `}`, `#{`, `{`, `}`
-> **Implementation Note**: Interpolated segments should be tokenized as full expressions, not rendered as plain string content.
+> **Implementation Note**: Tokenize interpolated segments as full expressions. Do not render them as plain string content.
### Git & Diff Views
@@ -491,7 +491,7 @@ Configuration files use a distinct key/value visual hierarchy:
- Macro invocations: `println!`, `vec!`, `format!`
- The `!` is part of the macro name
-> **Note**: Rust attributes (`#[derive]`, `#[cfg]`) are already covered under Attributes & Decorators.
+> **Note**: Rust attributes (`#[derive]`, `#[cfg]`) are covered under Attributes & Decorators.
### Haskell / ML / Functional Languages
@@ -514,7 +514,7 @@ Configuration files use a distinct key/value visual hierarchy:
**Type Variables** → `Dead Thread (#6fa5a0)` _italic_
- Lowercase type parameters: `a`, `b`, `m`
-- Distinguish from term-level variables via italic
+- Distinguish them from term-level variables with italic
---
@@ -560,7 +560,7 @@ Configuration files use a distinct key/value visual hierarchy:
| Disabled Text (alt) | `Null Pointer (#230905)` | On lighter backgrounds |
| Placeholder Text | `Phosphor Smoke (#efd5d1)` at 50% | Input hints |
-> **Accessibility Note**: Disabled UI elements should still meet minimum contrast where practical. When full contrast cannot be achieved, use additional visual cues (e.g., reduced opacity, different font weight).
+> **Accessibility Note**: Disabled UI elements must meet minimum contrast where practical. If full contrast is not possible, add other visual cues (for example, reduced opacity or a different font weight).
### Tabs
@@ -612,7 +612,7 @@ Configuration files use a distinct key/value visual hierarchy:
### Inlay Hints & Code Lens
-**Inlay Hints** (parameter names, inferred types, etc.)
+**Inlay Hints** (parameter names, inferred types)
| Element | Color | Style |
| ------------------- | ---------------------------------- | -------------------- |
@@ -627,7 +627,7 @@ Configuration files use a distinct key/value visual hierarchy:
| Code Lens Text | `Phosphor Smoke (#efd5d1)` at 70% | Above function/class |
| Code Lens Hover | `Phantom Current (#e7c0ba)` | On mouse hover |
-> **Note**: Inlay hints and code lens must never have higher contrast than primary code tokens. They are supplementary information and should fade into the background when not focused.
+> **Note**: Inlay hints and code lens must never have higher contrast than primary code tokens. They are supplementary information. They must fade into the background when not focused.
### Minimap & Overview Ruler
@@ -732,9 +732,9 @@ Configuration files use a distinct key/value visual hierarchy:
### 256-Color & Truecolor Guidance
- The 16 ANSI colors above are the canonical core for 256-color terminals
-- Colors 16–255 should interpolate between palette colors where possible
-- Truecolor-capable terminals (24-bit) should use exact hex values from the palette
-- When truecolor is available, prefer it over approximated 256-color values
+- Interpolate colors 16–255 between palette colors where possible
+- Truecolor-capable terminals (24-bit) use the exact hex values from the palette
+- If truecolor is available, prefer it over approximated 256-color values
---
@@ -744,7 +744,7 @@ Configuration files use a distinct key/value visual hierarchy:
#### Minimum Contrast Requirements
-Maintain **4.5:1 minimum contrast ratio** (WCAG 2.1 Level AA) for all text. The following canonical pairs have been verified:
+Maintain **4.5:1 minimum contrast ratio** (WCAG 2.1 Level AA) for all text. These canonical pairs are verified:
| Foreground | Background | Contrast Ratio | Status |
| ------------------------------ | ----------------------- | -------------- | ----------------- |
@@ -755,11 +755,11 @@ Maintain **4.5:1 minimum contrast ratio** (WCAG 2.1 Level AA) for all text. The
| Ghost Pixel (#f7eae8) | Bricked Board (#7a2012) | ~8.76:1 | ✓ Pass |
| Bad Sector (#46120a) | Core Meltdown (#340d07) | ~1.12:1 | ⚠ Decorative only |
-> **Note**: Low-contrast pairs like disabled text on backgrounds are acceptable only for decorative or non-essential elements. Critical information must always meet 4.5:1.
+> **Note**: Low-contrast pairs like disabled text on backgrounds are permitted only for decorative or non-essential elements. Critical information must always meet 4.5:1.
#### Non-Color Cues
-Errors, warnings, and critical states must not rely on color alone. Specify secondary cues:
+Errors, warnings, and critical states must not rely on color alone. Use these secondary cues:
- **Errors**: Red color + wavy underline + error icon (⚠ or ✗)
- **Warnings**: Yellow color + wavy underline + warning icon
@@ -771,32 +771,32 @@ Errors, warnings, and critical states must not rely on color alone. Specify seco
#### Color Vision Deficiency Considerations
- Test with protanopia, deuteranopia, and tritanopia simulations
-- Ensure red/green distinctions (diff views, success/error) have non-color differentiators
-- Consider providing alternative high-contrast mode documentation
+- Give red/green distinctions (diff views, success/error) non-color differentiators
+- Document an alternative high-contrast mode
### Consistency Requirements
-1. **Priority Order**: Follow token classification hierarchy strictly
+1. **Priority Order**: Follow the token classification hierarchy strictly
2. **Fallback Handling**: Use `Ghost Pixel` for unrecognized tokens
3. **Semantic Consistency**: Same meaning = same color across all languages
4. **Warmth Balance**: Maintain the warm rust-copper tone throughout
## UI Design Guidelines
-User-interface theming (surfaces, elevation, interaction physics, and
-component-level definitions for buttons, inputs, menus, modals, and the rest)
-is specified separately in the **Digital Rust UI Specification**. This document
+User-interface theming is specified separately in the **Digital Rust UI
+Specification**: surfaces, elevation, interaction physics, and component-level
+definitions for buttons, inputs, menus, modals, and the rest. This document
owns the palette, syntax token classification, editor chrome, and terminal
-configuration; the UI Specification owns everything a full application theme
+configuration. The UI Specification owns everything a full application theme
needs beyond the editor. Both documents reference colours by the same stable
names defined in the [Color Palette](#color-palette) above.
The summaries below cover the colour-usage rules that ports of this syntax
-theme most commonly need when extending Digital Rust beyond the editor.
+theme need most often when they extend Digital Rust beyond the editor.
### Visual Hierarchy
-Apply colors based on functional importance and user interaction patterns:
+Apply colors by functional importance and user interaction patterns:
- **High Priority**: Interactive elements, CTAs, error states → `Digital Rust (#af2e1a)`, `Amber Alert (#bf5747)`
- **Medium Priority**: Headers, navigation, secondary actions → `Fatal Error (#cf8175)`, `Stack Overglow (#d4a759)`
@@ -813,9 +813,9 @@ Apply colors based on functional importance and user interaction patterns:
**Shadows and Depth**
-- **NEVER use pure black (#000) shadows** — they're cold and dead; always use warm shadow tones
+- **NEVER use pure black (#000) shadows** — they are cold and dead; always use warm shadow tones
- Use `Bad Sector (#46120a)` / `--dr-surface-highlight` for offset shadows
-- Use `Event Horizon (#110402)` only for legacy blunt shadows where maximum depth is needed
+- Use `Event Horizon (#110402)` only for legacy blunt shadows that need maximum depth
- No gradients, no blur, no transparency — solid colors only (atmospheric noise/scanline overlays excepted)
- Interactive and elevated elements add the inner highlight, `inset 0 1px 0 rgba(255, 255, 255, 0.1)`, under the offset shadow
@@ -851,42 +851,50 @@ Digital Rust embraces the aesthetic of system degradation and hardware failure w
1. **Language Coverage**: Test with at least 5 different programming languages
2. **File Types**: Verify Markdown, JSON, XML, and configuration files
-3. **Diff Views**: Ensure additions/deletions are clearly distinguishable
-4. **Terminal Emulation**: Validate ANSI color representation
+3. **Diff Views**: Make sure that additions and deletions are clearly distinguishable
+4. **Terminal Emulation**: Validate the ANSI color representation
5. **Light Sensitivity**: Provide documentation for users sensitive to warm tones
### Performance Considerations
-- Colors should render consistently across sRGB and P3 color spaces
+- Colors must render consistently across sRGB and P3 color spaces
- Test on both high-contrast and standard displays
-- Verify legibility at various zoom levels (50% - 200%)
+- Verify legibility at zoom levels from 50% to 200%
## Implementation Notes
### Canonical Source
-This specification is the **canonical source of truth** for Digital Rust. All editor-specific theme implementations (VS Code, JetBrains, Neovim, Sublime Text, terminals, web applications, etc.) are projections of this specification.
+This specification is the **canonical source of truth** for Digital Rust. All
+editor-specific theme implementations (VS Code, JetBrains, Neovim, Sublime
+Text, terminals, web applications, and others) are projections of this
+specification.
-When conflicts arise between an implementation and this spec, this document takes precedence. Implementers should document any intentional deviations.
+If a conflict arises between an implementation and this spec, this document
+takes precedence. Document any intentional deviations in the implementation.
### Handling Coarse Tokenization
-Some editors or language grammars provide limited token granularity. When fine-grained semantic distinctions cannot be made:
+Some editors or language grammars provide limited token granularity. If fine-grained semantic distinctions are not possible:
-1. **Built-ins vs. User Definitions**: When built-in functions cannot be distinguished from user-defined functions, use `Stack Overglow (#d4a759)` for all functions.
+1. **Built-ins vs. User Definitions**: If built-in functions cannot be distinguished from user-defined functions, use `Stack Overglow (#d4a759)` for all functions.
-2. **Types vs. Variables**: When types cannot be distinguished from variables, prefer `Ghost Pixel (#f7eae8)` as the neutral fallback.
+2. **Types vs. Variables**: If types cannot be distinguished from variables, prefer `Ghost Pixel (#f7eae8)` as the neutral fallback.
-3. **Ambiguous Tokens**: Favor readability and contrast over forcing a semantic color that doesn’t map cleanly.
+3. **Ambiguous Tokens**: Favor readability and contrast over a semantic color that does not map cleanly.
4. **Missing Scopes**: For tokens not covered by the grammar, fall back to `Ghost Pixel (#f7eae8)`.
-> **Guiding Principle**: When in doubt, prioritize readability and visual comfort over strict semantic accuracy.
+> **Guiding Principle**: If in doubt, prioritize readability and visual comfort over strict semantic accuracy.
---
## Version History
+- **v1.2.2**: Technical prose rewritten in Simplified Technical English
+ - Rules, notes, guidelines, and implementation text rewritten for short sentences, condition-first instructions, and consistent verbs
+ - No palette, token, or hex value changes
+ - Brand-voice passages (overview, theme philosophy, design principles) unchanged
- **v1.2.1**: UI specification accessibility and token fixes
- Primary button hover fill changed to Firewall Breach: Ghost Pixel on raw Amber Alert failed WCAG AA (3.83:1); Firewall Breach passes at 4.66:1
- Semantic action/feedback/border-colour token layer added to `tokens.css` (`--dr-accent`, `--dr-accent-hover`, `--dr-success`, `--dr-warning`, `--dr-danger`, `--dr-danger-text`, `--dr-info`, `--dr-border-color*`); component code now references semantic tokens, not raw palette values
diff --git a/Digital Rust UI Specification.md b/Digital Rust UI Specification.md
index 1bb4f61..5383fdc 100644
--- a/Digital Rust UI Specification.md
+++ b/Digital Rust UI Specification.md
@@ -1,20 +1,20 @@
# Digital Rust UI Specification
-Part of Digital Rust Specification v1.2.1
+Part of Digital Rust Specification v1.2.2
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.
+The palette 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.
+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:
+tokens defined in `tokens.css`, never raw palette values. The semantic layer adds
+these tokens on top of the surface and text tokens:
| Token | Colour | Role |
| --- | --- | --- |
@@ -73,8 +73,8 @@ Five rules carry the whole system:
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
+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
@@ -82,8 +82,8 @@ Five rules carry the whole system:
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.
+dark-theme material. The syntax specification defines these as named rules.
+They apply equally to UI.
## Surfaces & Texture
@@ -99,13 +99,13 @@ The rust ramp is the only neutral scale. Semantic surface tokens map onto it:
**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, 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.
+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`
@@ -143,13 +143,13 @@ body::after { /* scanlines */
}
```
-The overlays suppress entirely under `prefers-reduced-motion: reduce` and never
+The overlays suppress entirely under `prefers-reduced-motion: reduce`. They 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.
+with zero blur. Light is always top-left. Shadows fall down-right.
| Token | Value | Use |
| --- | --- | --- |
@@ -163,12 +163,12 @@ with zero blur. Light is always top-left; shadows fall down-right.
| `--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 No Blur Rule.** Blur radius is zero everywhere except the glow shadows.
+The glow shadows 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:
+highlight is unfinished. Stack the two:
```css
box-shadow:
@@ -191,13 +191,13 @@ checkboxes, chips, tabs, and any element that behaves like a switch.
`--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.
+ translation always have 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.
+- `prefers-reduced-motion: reduce` suppresses all of the above: the full state
+ *colours* still apply, but transform and transition are removed.
```css
.dr-button {
@@ -215,14 +215,14 @@ checkboxes, chips, tabs, and any element that behaves like a switch.
## 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.
+role **generically first**. The named faces are examples of the role, not the
+only permitted 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.
+ tracking for short strings (titles, labels, badges). Never set 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,
@@ -232,29 +232,28 @@ only acceptable choices.
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.
+These are **general recommendations, not binding rules**. 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. Treat the
+guidance above as a tested starting point, not a constraint. If 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,
+- **Button and tab labels**: heading/label sans (for example, 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,
+- **Badges and tags**: heading/label sans (for example, Rajdhani) at 700, uppercase,
0.08em tracking, 0.75rem.
-- **Panel and card titles**: heading/label sans (e.g. Rajdhani) at 700,
+- **Panel and card titles**: heading/label sans (for example, 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
+- **Inputs and text areas**: body serif/sans (for example, 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.
+ (for example, 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.
+Across all roles, weights, tracking, and case matter more than the exact face.
+An equivalent category with matching metrics keeps the system intact.
## Components
@@ -270,7 +269,7 @@ light-catching bevel, physical travel.
| 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` |
+| Font | heading/label sans (for example, Rajdhani) at 600, uppercase, `0.05em` tracking, `--dr-text-sm` |
| Shadow | resting offset + inner highlight |
| Cursor | `pointer` |
| Interaction | full press cycle at 150ms |
@@ -344,15 +343,15 @@ Reference CSS:
**Rules**
-- One primary button per view. Primary carries the brand; two primaries on one
- screen is a visual shouting match.
+- One primary button per view. Primary carries the brand. Two primaries on one
+ screen are 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.
+- Full-pill radius is forbidden on buttons. Use `4px` only.
### Inputs & Text Areas
-Recessed wells. The darkest surface on the page; the user types into the machine.
+Recessed wells. The darkest surface on the page. The user types into the machine.
| Property | Value |
| --- | --- |
@@ -398,7 +397,7 @@ Recessed wells. The darkest surface on the page; the user types into the machine
- 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
+- Labels sit above the input in the label sans (for example, Rajdhani), uppercase at
`--dr-text-xs`, Phosphor Smoke.
### Checkboxes
@@ -414,22 +413,22 @@ A small square switch with the full press cycle. 16px box, 2px radius.
| 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.
+The ✓ glyph is drawn centred, 12px at 16px box size. The 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.
+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,
+2px Dark Packet border and `offset-sm` shadow. The thumb lifts on hover-drag
+and presses on active-drag. Thumb never exceeds 2px radius. Sliders are machined parts,
not pills.
### Tabs
@@ -447,16 +446,17 @@ 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.
+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)
+`offset-lg` + inner highlight. Title in Fatal Error, label sans (for example, 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.
+blurred. The footer action row carries at most one primary button. Modals do
+not animate in with scale or bounce. A 150ms fade is the only permitted entry
+motion.
### Toasts & Notices
@@ -469,15 +469,15 @@ 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
+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
+popovers (rich content) use `offset-lg` and can 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
+`0.2rem 0.6rem` padding, label sans (for example, Rajdhani) at 700 uppercase, 0.08em
tracking, 0.75rem.
| Kind | Text | Background | Border |
@@ -488,7 +488,7 @@ tracking, 0.75rem.
| 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).
+permitted on badges only. Badges are rivets, not panels.
### Callouts & Panels
@@ -496,38 +496,40 @@ 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.
+to the no-accent-stripe rule. It exists so that 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).
+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.
+links, wavy for diagnostics. Never style a diagnostic squiggle as a link or a
+link as a diagnostic squiggle.
### 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).
+(for example, 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).
+Header row: label sans (for example, Rajdhani) at 700 uppercase `--dr-text-xs`, Fatal
+Error text, 2px Dark Packet bottom border. Body: body serif/sans (for example, 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
@@ -535,35 +537,35 @@ overlay already bands the page; double banding reads as interference).
| --- | --- |
| 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). |
+| Focus visible | 2px Stack Overglow outline, 2px offset, *in addition to* the resting shadow. Never use `outline: none` without a replacement. |
+| Selected | Bad Sector bg + Ghost Pixel text (lists, menus; tabs use the 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 / Processing | Stack Overglow with motion (spinner, pulse). Under reduced motion, a static Stack Overglow text label. |
+| Invalid / Error | Amber Alert border on the control + Amber Alert Text message. Errors never rely on colour alone: an icon or text accompanies them. |
### 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
+raised panels: Event Horizon fill with a Bad Sector border, plus 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.
+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`.
+- 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
+- Touch targets are at least 24×24px. The press cycle's 2px travel does not
count toward target size.
## Do's and Don'ts
@@ -574,22 +576,22 @@ carries the state.
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
+- **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,
+- **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** 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
+- **Don't** use radius above 6px on any component. The default is 4px, 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.
diff --git a/index.html b/index.html
index 7730659..83a9215 100644
--- a/index.html
+++ b/index.html
@@ -24,7 +24,7 @@
DIGITAL RUST
- Spec v1.2.1
+ Spec v1.2.2
Syntax · UI · Terminal
A warm, tech-dystopian color scheme inspired by corrupted hardware and failing systems.
@@ -65,7 +65,7 @@
cat DIGITAL_RUST_SPEC.md | verify --strict
- fingerprint: 0xDR-1.2.1
+ fingerprint: 0xDR-1.2.2
updated: 2025-11-29
priority-order: errors > warnings > semantic > textmate
diff --git a/spec.html b/spec.html
index 145069c..373083e 100644
--- a/spec.html
+++ b/spec.html
@@ -640,8 +640,8 @@
Design Note: Booleans and null-like values use a
- distinct color from numbers to emphasize their semantic role as special
- language constants rather than numeric data.
+ distinct color from numbers. The distinct color marks their semantic role
+ as special language constants, not numeric data.
@@ -651,7 +651,7 @@
- Single-Line:
//, #, --
- Multi-Line:
/* */, <!-- -->
- - Documentation Blocks (JSDoc, Javadoc, docstrings, etc.)
+ - Documentation Blocks (JSDoc, Javadoc, docstrings)
Attributes & Decorators →
@@ -680,7 +680,7 @@
Sigil Handling: The @ or
- # sigil inherits the decorator color and is styled as part
+ # sigil inherits the decorator color. Style the sigil as part
of the attribute token.
@@ -860,8 +860,8 @@
- Accessibility Note: Links and spelling errors must be
- distinguishable by underline style (solid vs. dotted), not just color.
+ Accessibility Note: Distinguish links and spelling errors
+ by underline style (solid vs. dotted), not by color alone.
Strikethrough
@@ -872,7 +872,7 @@
Special Rules
Scope Prioritization
- When multiple scopes apply to a token, apply styles in this precedence
+ If multiple scopes apply to one token, apply styles in this precedence
order:
@@ -897,7 +897,7 @@
Rule: If a token is both an error and another role
(e.g., a misspelled keyword), the error style takes full precedence. The
- token should display error styling, not a blend.
+ token shows the error styling, not a blend.
Bracket Matching
@@ -911,7 +911,7 @@
underline
-
- Rainbow Brackets: Optional, cycling through:
Dead Thread,
+ Rainbow Brackets: Optional. If enabled, cycle through: Dead Thread,
Stack Overglow, Fractured Shell,
Blue Screen, Thermal Throttle,
Memory Leek
@@ -944,8 +944,8 @@
- Design Note: Keys and values are intentionally colored
- differently to make hierarchical structure immediately visible.
+ Design Note: Keys and values use intentionally different
+ colors. The difference makes the hierarchical structure immediately visible.
Markdown & Rich Text
@@ -1033,7 +1033,7 @@
/>
- Template Languages (JSX, Vue, Handlebars, EJS, etc.)
+ Template Languages (JSX, Vue, Handlebars, EJS)
-
Template Delimiters (
{}, {{}},
@@ -1087,7 +1087,7 @@
Fatal Error (#cf8175)
- Utility-First (Tailwind, etc.)
+ Utility-First (Tailwind and similar frameworks)
-
Class Names in HTML →
Dead Thread (#6fa5a0) (treat as
@@ -1128,8 +1128,8 @@
- Implementation Note: Interpolated segments should be
- tokenized as full expressions, not rendered as plain string content.
+ Implementation Note: Tokenize interpolated segments as full
+ expressions. Do not render them as plain string content.
Git & Diff Views
@@ -1347,7 +1347,7 @@
Note: Rust attributes (#[derive],
- #[cfg]) are already covered under Attributes &
+ #[cfg]) are covered under Attributes &
Decorators.
@@ -1400,7 +1400,7 @@
Lowercase type parameters: a, b,
m
- - Distinguish from term-level variables via italic
+ - Distinguish them from term-level variables with italic
Editor UI Definitions
@@ -1577,10 +1577,9 @@
- Accessibility Note: Disabled UI elements should still
- meet minimum contrast where practical. When full contrast cannot be
- achieved, use additional visual cues (e.g., reduced opacity, different
- font weight).
+ Accessibility Note: Disabled UI elements must meet minimum
+ contrast where practical. If full contrast is not possible, add other visual
+ cues (for example, reduced opacity or a different font weight).
Tabs
@@ -1762,7 +1761,7 @@
Inlay Hints & Code Lens
- Inlay Hints (parameter names, inferred types, etc.)
+ Inlay Hints (parameter names, inferred types)
@@ -1819,8 +1818,8 @@
Note: Inlay hints and code lens must never have higher
- contrast than primary code tokens. They are supplementary information
- and should fade into the background when not focused.
+ contrast than primary code tokens. They are supplementary information. They
+ must fade into the background when not focused.
Minimap & Overview Ruler
@@ -2219,14 +2218,14 @@
The 16 ANSI colors above are the canonical core for 256-color terminals
- Colors 16–255 should interpolate between palette colors where possible
+ Interpolate colors 16–255 between palette colors where possible
- Truecolor-capable terminals (24-bit) should use exact hex values from
+ Truecolor-capable terminals (24-bit) use the exact hex values from
the palette
- When truecolor is available, prefer it over approximated 256-color
+ If truecolor is available, prefer it over approximated 256-color
values
@@ -2236,7 +2235,7 @@
Minimum Contrast Requirements
Maintain 4.5:1 minimum contrast ratio (WCAG 2.1 Level AA)
- for all text. The following canonical pairs have been verified:
+ for all text. These canonical pairs are verified:
@@ -2295,14 +2294,14 @@
Note: Low-contrast pairs like disabled text on
- backgrounds are acceptable only for decorative or non-essential
+ backgrounds are permitted only for decorative or non-essential
elements. Critical information must always meet 4.5:1.
Non-Color Cues
Errors, warnings, and critical states must not rely on color alone.
- Specify secondary cues:
+ Use these secondary cues:
-
@@ -2331,10 +2330,10 @@
- Test with protanopia, deuteranopia, and tritanopia simulations
-
- Ensure red/green distinctions (diff views, success/error) have non-color
+ Give red/green distinctions (diff views, success/error) non-color
differentiators
- - Consider providing alternative high-contrast mode documentation
+ - Document an alternative high-contrast mode
Consistency Requirements
@@ -2404,12 +2403,12 @@
Shadows and Depth
- - NEVER use pure black (#000) shadows. They're cold and dead; always use warm shadow tones
+ - NEVER use pure black (#000) shadows. They are cold and dead; always use warm shadow tones
-
Use
Bad Sector (#46120a) / --dr-surface-highlight for offset shadows
-
- Use
Event Horizon (#110402) only for legacy blunt shadows where maximum depth is needed
+ Use Event Horizon (#110402) only for legacy blunt shadows that need maximum depth
-
No gradients, no blur, no transparency: solid colors only (atmospheric noise/scanline overlays excepted)
@@ -2484,11 +2483,11 @@
configuration files
-
- Diff Views: Ensure additions/deletions are clearly
+ Diff Views: Make sure that additions and deletions are clearly
distinguishable
-
- Terminal Emulation: Validate ANSI color representation
+ Terminal Emulation: Validate the ANSI color representation
-
Light Sensitivity: Provide documentation for users
@@ -2497,39 +2496,39 @@
- - Colors should render consistently across sRGB and P3 color spaces
+ - Colors must render consistently across sRGB and P3 color spaces
- Test on both high-contrast and standard displays
- - Verify legibility at various zoom levels (50% - 200%)
+ - Verify legibility at zoom levels from 50% to 200%
Implementation Notes
Canonical Source
This specification is the canonical source of truth for
Digital Rust. All editor-specific theme implementations (VS Code,
- JetBrains, Neovim, Sublime Text, terminals, web applications, etc.) are
+ JetBrains, Neovim, Sublime Text, terminals, web applications, and others) are
projections of this specification.
- When conflicts arise between an implementation and this spec, this
- document takes precedence. Implementers should document any intentional
- deviations.
+ If a conflict arises between an implementation and this spec, this
+ document takes precedence. Document any intentional deviations in the
+ implementation.
Handling Coarse Tokenization
- Some editors or language grammars provide limited token granularity. When
- fine-grained semantic distinctions cannot be made:
+ Some editors or language grammars provide limited token granularity. If
+ fine-grained semantic distinctions are not possible:
-
- Built-ins vs. User Definitions: When built-in
+ Built-ins vs. User Definitions: If built-in
functions cannot be distinguished from user-defined functions, use
Stack Overglow (#d4a759) for all functions.
-
- Types vs. Variables: When types cannot be
+ Types vs. Variables: If types cannot be
distinguished from variables, prefer
Ghost Pixel (#f7eae8) as the neutral fallback.
@@ -2537,7 +2536,7 @@
-
Ambiguous Tokens: Favor readability and contrast over
- forcing a semantic color that doesn't map cleanly.
+ a semantic color that does not map cleanly.
-
@@ -2549,13 +2548,21 @@
- Guiding Principle: When in doubt, prioritize
+ Guiding Principle: If in doubt, prioritize
readability and visual comfort over strict semantic accuracy.
Version History
+ -
+ v1.2.2: Technical prose rewritten in Simplified Technical English
+
+ - Rules, notes, guidelines, and implementation text rewritten for short sentences, condition-first instructions, and consistent verbs
+ - No palette, token, or hex value changes
+ - Brand-voice passages (overview, theme philosophy, design principles) unchanged
+
+
-
v1.2.1: UI specification accessibility and token fixes
diff --git a/ui.html b/ui.html
index 04a052d..df6e83d 100644
--- a/ui.html
+++ b/ui.html
@@ -24,7 +24,7 @@
UI GUIDELINES
- Spec v1.2.1
+ Spec v1.2.2
Tactile · Heavy · Pressable
Chunky hardware panels for failing systems. The Digital Rust UI Specification,
demonstrated live.