diff --git a/.impeccable/config.json b/.impeccable/config.json
index afa9284..af8998d 100644
--- a/.impeccable/config.json
+++ b/.impeccable/config.json
@@ -1,154 +1,122 @@
{
- "detector": {
- "ignoreRules": [],
- "ignoreFiles": [],
- "ignoreValues": [
- {
- "rule": "cramped-padding",
- "value": "*",
- "files": [
- "index.html"
- ],
- "createdAt": "2026-08-17T03:39:35.263Z",
- "reason": "Agent: color-chip palette swatches are intentional edge-to-edge color demos, not content containers"
- },
- {
- "rule": "undersized-ui-text",
- "value": "*",
- "files": [
- "index.html"
- ],
- "createdAt": "2026-08-17T03:39:35.352Z",
- "reason": "Agent: color-chip hex labels are decorative swatch captions in a palette showcase, sized by design spec"
- },
- {
- "rule": "side-tab",
- "value": "*",
- "files": [
- "ui.html"
- ],
- "createdAt": "2026-08-17T03:39:45.534Z",
- "reason": "Agent: left-accent callout/toast pattern is a spec'd Digital Rust component (Digital Rust UI Specification), demonstrated on ui.html"
- },
- {
- "rule": "design-system-color",
- "value": "*",
- "files": [
- "spec.html"
- ],
- "createdAt": "2026-08-17T03:39:45.630Z",
- "reason": "Agent: spec.html renders palette demonstration diagrams; white/black swatch surfaces are the subject of the spec, not page chrome"
- },
- {
- "rule": "design-system-radius",
- "value": "2px0",
- "createdAt": "2026-08-17T03:39:45.704Z",
- "reason": "Agent: detector parse artifact concatenating 2px radius with 0; no such value exists in source"
- },
- {
- "rule": "design-system-font-size",
- "value": "0.7rem",
- "createdAt": "2026-08-17T03:42:49.330Z",
- "reason": "Agent: token-swatch inline chip label, intentionally below the 0.75rem label step for compact inline code chips"
- },
- {
- "rule": "design-system-font-size",
- "value": "0.65rem",
- "createdAt": "2026-08-17T03:42:49.407Z",
- "reason": "Agent: color-hex caption under palette swatch chips, decorative metadata below the label step by design"
- },
- {
- "rule": "design-system-font-size",
- "value": "0.6rem",
- "createdAt": "2026-08-17T03:42:49.500Z",
- "reason": "Agent: mobile (<480px) shrink of the color-hex swatch caption; pairs with the 0.65rem desktop value"
- },
- {
- "rule": "design-system-font-size",
- "value": "2.5rem",
- "createdAt": "2026-08-17T03:42:49.587Z",
- "reason": "Agent: mobile h1 clamp ceiling (1.75rem-2.5rem) mirrors the desktop display clamp; intentional responsive step"
- },
- {
- "rule": "gray-on-color",
- "value": "*",
- "files": [
- "index.html",
- "spec.html",
- "ui.html"
- ],
- "createdAt": "2026-08-17T03:47:39.568Z",
- "reason": "Agent: Ghost Pixel #f7eae8 is the spec'd near-white text of the Digital Rust palette (rust ramp IS the neutral scale, no grays exist); detector misclassifies it as gray-on-color"
- },
- {
- "rule": "dark-glow",
- "value": "*",
- "files": [
- "index.html",
- "spec.html",
- "ui.html"
- ],
- "createdAt": "2026-08-17T03:47:39.684Z",
- "reason": "Agent: zero-offset brand glow and CRT glitch text-shadow are intentional, spec'd Digital Rust aesthetics (DESIGN.md typography + shadow tokens)"
- },
- {
- "rule": "broken-image",
- "value": "*",
- "files": [
- "index.html"
- ],
- "createdAt": "2026-08-17T03:47:39.818Z",
- "reason": "Agent: lightbox dialog img src is populated by JS at runtime; the empty src is a deliberate placeholder"
- },
- {
- "rule": "repeating-stripes-gradient",
- "value": "*",
- "files": [
- "index.html",
- "spec.html",
- "ui.html"
- ],
- "createdAt": "2026-08-17T03:47:39.902Z",
- "reason": "Agent: scanline overlay is the intentional CRT aesthetic of the Digital Rust design system"
- },
- {
- "rule": "image-hover-transform",
- "value": "*",
- "files": [
- "index.html",
- "ui.html"
- ],
- "createdAt": "2026-08-17T03:47:40.009Z",
- "reason": "Agent: lightbox preview zoom is the intended interaction on the showcase pages"
- },
- {
- "rule": "low-contrast",
- "value": "*",
- "files": [
- "spec.html"
- ],
- "createdAt": "2026-08-17T03:47:40.115Z",
- "reason": "Agent: spec.html renders palette swatch diagrams; ramp-on-white and black-on-ramp pairings are the demonstration subject, not readable page copy"
- },
- {
- "rule": "nested-cards",
- "value": "*",
- "files": [
- "index.html",
- "ui.html"
- ],
- "createdAt": "2026-08-17T03:51:36.176Z",
- "reason": "Agent: intentional component demos — palette/ANSI swatch chips in a panelled showcase, and UI-spec demos (tabs/modal/menu inside demo panels) on the design-system documentation pages"
- },
- {
- "rule": "side-tab",
- "value": "*",
- "files": [
- "style.css"
- ],
- "createdAt": "2026-08-17T03:51:55.660Z",
- "reason": "Agent: 3px left accent on toasts/callouts is a deliberate spec'd exception in the Digital Rust UI Specification (semantic blocks identifiable at scroll speed)"
- }
- ]
- }
+ "detector": {
+ "ignoreRules": [],
+ "ignoreFiles": [],
+ "ignoreValues": [
+ {
+ "rule": "cramped-padding",
+ "value": "*",
+ "files": ["index.html"],
+ "createdAt": "2026-08-17T03:39:35.263Z",
+ "reason": "Agent: color-chip palette swatches are intentional edge-to-edge color demos, not content containers"
+ },
+ {
+ "rule": "undersized-ui-text",
+ "value": "*",
+ "files": ["index.html"],
+ "createdAt": "2026-08-17T03:39:35.352Z",
+ "reason": "Agent: color-chip hex labels are decorative swatch captions in a palette showcase, sized by design spec"
+ },
+ {
+ "rule": "side-tab",
+ "value": "*",
+ "files": ["ui.html"],
+ "createdAt": "2026-08-17T03:39:45.534Z",
+ "reason": "Agent: left-accent callout/toast pattern is a spec'd Digital Rust component (Digital Rust UI Specification), demonstrated on ui.html"
+ },
+ {
+ "rule": "design-system-color",
+ "value": "*",
+ "files": ["spec.html"],
+ "createdAt": "2026-08-17T03:39:45.630Z",
+ "reason": "Agent: spec.html renders palette demonstration diagrams; white/black swatch surfaces are the subject of the spec, not page chrome"
+ },
+ {
+ "rule": "design-system-radius",
+ "value": "2px0",
+ "createdAt": "2026-08-17T03:39:45.704Z",
+ "reason": "Agent: detector parse artifact concatenating 2px radius with 0; no such value exists in source"
+ },
+ {
+ "rule": "design-system-font-size",
+ "value": "0.7rem",
+ "createdAt": "2026-08-17T03:42:49.330Z",
+ "reason": "Agent: token-swatch inline chip label, intentionally below the 0.75rem label step for compact inline code chips"
+ },
+ {
+ "rule": "design-system-font-size",
+ "value": "0.65rem",
+ "createdAt": "2026-08-17T03:42:49.407Z",
+ "reason": "Agent: color-hex caption under palette swatch chips, decorative metadata below the label step by design"
+ },
+ {
+ "rule": "design-system-font-size",
+ "value": "0.6rem",
+ "createdAt": "2026-08-17T03:42:49.500Z",
+ "reason": "Agent: mobile (<480px) shrink of the color-hex swatch caption; pairs with the 0.65rem desktop value"
+ },
+ {
+ "rule": "design-system-font-size",
+ "value": "2.5rem",
+ "createdAt": "2026-08-17T03:42:49.587Z",
+ "reason": "Agent: mobile h1 clamp ceiling (1.75rem-2.5rem) mirrors the desktop display clamp; intentional responsive step"
+ },
+ {
+ "rule": "gray-on-color",
+ "value": "*",
+ "files": ["index.html", "spec.html", "ui.html"],
+ "createdAt": "2026-08-17T03:47:39.568Z",
+ "reason": "Agent: Ghost Pixel #f7eae8 is the spec'd near-white text of the Digital Rust palette (rust ramp IS the neutral scale, no grays exist); detector misclassifies it as gray-on-color"
+ },
+ {
+ "rule": "dark-glow",
+ "value": "*",
+ "files": ["index.html", "spec.html", "ui.html"],
+ "createdAt": "2026-08-17T03:47:39.684Z",
+ "reason": "Agent: zero-offset brand glow and CRT glitch text-shadow are intentional, spec'd Digital Rust aesthetics (DESIGN.md typography + shadow tokens)"
+ },
+ {
+ "rule": "broken-image",
+ "value": "*",
+ "files": ["index.html"],
+ "createdAt": "2026-08-17T03:47:39.818Z",
+ "reason": "Agent: lightbox dialog img src is populated by JS at runtime; the empty src is a deliberate placeholder"
+ },
+ {
+ "rule": "repeating-stripes-gradient",
+ "value": "*",
+ "files": ["index.html", "spec.html", "ui.html"],
+ "createdAt": "2026-08-17T03:47:39.902Z",
+ "reason": "Agent: scanline overlay is the intentional CRT aesthetic of the Digital Rust design system"
+ },
+ {
+ "rule": "image-hover-transform",
+ "value": "*",
+ "files": ["index.html", "ui.html"],
+ "createdAt": "2026-08-17T03:47:40.009Z",
+ "reason": "Agent: lightbox preview zoom is the intended interaction on the showcase pages"
+ },
+ {
+ "rule": "low-contrast",
+ "value": "*",
+ "files": ["spec.html"],
+ "createdAt": "2026-08-17T03:47:40.115Z",
+ "reason": "Agent: spec.html renders palette swatch diagrams; ramp-on-white and black-on-ramp pairings are the demonstration subject, not readable page copy"
+ },
+ {
+ "rule": "nested-cards",
+ "value": "*",
+ "files": ["index.html", "ui.html"],
+ "createdAt": "2026-08-17T03:51:36.176Z",
+ "reason": "Agent: intentional component demos — palette/ANSI swatch chips in a panelled showcase, and UI-spec demos (tabs/modal/menu inside demo panels) on the design-system documentation pages"
+ },
+ {
+ "rule": "side-tab",
+ "value": "*",
+ "files": ["style.css"],
+ "createdAt": "2026-08-17T03:51:55.660Z",
+ "reason": "Agent: 3px left accent on toasts/callouts is a deliberate spec'd exception in the Digital Rust UI Specification (semantic blocks identifiable at scroll speed)"
+ }
+ ]
+ }
}
diff --git a/.impeccable/design.json b/.impeccable/design.json
index 60470f3..878ced7 100644
--- a/.impeccable/design.json
+++ b/.impeccable/design.json
@@ -1,867 +1,867 @@
{
- "schemaVersion": 2,
- "generatedAt": "2026-08-17T04:02:00.494Z",
- "title": "Design System: Digital Rust",
- "extensions": {
- "colorMeta": {
- "ghost-pixel": {
- "role": "primary",
- "displayName": "Ghost Pixel",
- "canonical": "#f7eae8",
- "tonalRamp": [
- "#0e0a0a",
- "#2a2322",
- "#493f3e",
- "#695e5d",
- "#8b7f7e",
- "#aca2a1",
- "#cfc7c6",
- "#f1eeed"
- ]
- },
- "phosphor-smoke": {
- "role": "primary",
- "displayName": "Phosphor Smoke",
- "canonical": "#efd5d1",
- "tonalRamp": [
- "#100908",
- "#2f211f",
- "#4f3d3a",
- "#715b58",
- "#937c79",
- "#b4a09c",
- "#d4c5c3",
- "#f3edec"
- ]
- },
- "phantom-current": {
- "role": "primary",
- "displayName": "Phantom Current",
- "canonical": "#e7c0ba",
- "tonalRamp": [
- "#120807",
- "#331f1c",
- "#563a36",
- "#795853",
- "#9b7973",
- "#bc9d98",
- "#dac3bf",
- "#f6ecea"
- ]
- },
- "corrupted-cache": {
- "role": "neutral",
- "displayName": "Corrupted Cache",
- "canonical": "#dfaba3",
- "tonalRamp": [
- "#140706",
- "#381c18",
- "#5d3631",
- "#81544d",
- "#a4756e",
- "#c49993",
- "#e0c1bc",
- "#f8ebe9"
- ]
- },
- "copper-trace": {
- "role": "neutral",
- "displayName": "Copper Trace",
- "canonical": "#d7968c",
- "tonalRamp": [
- "#170604",
- "#3c1914",
- "#63322b",
- "#894f47",
- "#ac7067",
- "#cc968d",
- "#e7beb8",
- "#fbeae7"
- ]
- },
- "fatal-error": {
- "role": "primary",
- "displayName": "Fatal Error",
- "canonical": "#cf8175",
- "tonalRamp": [
- "#190403",
- "#41150f",
- "#6a2c24",
- "#91493f",
- "#b56b60",
- "#d49287",
- "#edbcb3",
- "#fee9e5"
- ]
- },
- "rouge-signal": {
- "role": "neutral",
- "displayName": "Rouge Signal",
- "canonical": "#c76c5e",
- "tonalRamp": [
- "#1b0302",
- "#450f09",
- "#70261d",
- "#994337",
- "#bd6658",
- "#dc8d80",
- "#f3b9af",
- "#ffe8e4"
- ]
- },
- "amber-alert": {
- "role": "primary",
- "displayName": "Amber Alert",
- "canonical": "#bf5747",
- "tonalRamp": [
- "#1d0100",
- "#4a0803",
- "#761e13",
- "#a03c2d",
- "#c56050",
- "#e48979",
- "#f9b6aa",
- "#ffe7e2"
- ]
- },
- "amber-alert-text": {
- "role": "neutral",
- "displayName": "Amber Alert Text",
- "canonical": "#cb6353",
- "tonalRamp": [
- "#1d0101",
- "#490803",
- "#761e14",
- "#9f3c2f",
- "#c56051",
- "#e3897a",
- "#f9b6aa",
- "#ffe7e2"
- ]
- },
- "firewall-breach": {
- "role": "neutral",
- "displayName": "Firewall Breach",
- "canonical": "#b74230",
- "tonalRamp": [
- "#1f0000",
- "#4e0000",
- "#7c1305",
- "#a73322",
- "#cd5946",
- "#eb8472",
- "#ffb3a5",
- "#ffe6e0"
- ]
- },
- "digital-rust": {
- "role": "primary",
- "displayName": "Digital Rust",
- "canonical": "#af2e1a",
- "tonalRamp": [
- "#210000",
- "#500000",
- "#800500",
- "#ac2c18",
- "#d2543f",
- "#f0816c",
- "#ffb1a1",
- "#ffe5de"
- ]
- },
- "kernel-panic": {
- "role": "neutral",
- "displayName": "Kernel Panic",
- "canonical": "#9d2917",
- "tonalRamp": [
- "#1f0000",
- "#4e0000",
- "#7c1303",
- "#a73421",
- "#cc5946",
- "#ea8471",
- "#ffb3a4",
- "#ffe6e0"
- ]
- },
- "data-rot": {
- "role": "neutral",
- "displayName": "Data Rot",
- "canonical": "#8c2414",
- "tonalRamp": [
- "#1e0100",
- "#4b0600",
- "#781c0d",
- "#a23a29",
- "#c75e4c",
- "#e58876",
- "#fbb5a7",
- "#ffe7e1"
- ]
- },
- "bricked-board": {
- "role": "neutral",
- "displayName": "Bricked Board",
- "canonical": "#7a2012",
- "tonalRamp": [
- "#1c0201",
- "#470d05",
- "#732316",
- "#9c4031",
- "#c16352",
- "#df8c7b",
- "#f6b8ab",
- "#ffe8e2"
- ]
- },
- "dark-packet": {
- "role": "primary",
- "displayName": "Dark Packet",
- "canonical": "#691b0f",
- "tonalRamp": [
- "#1b0302",
- "#441109",
- "#6e281d",
- "#964537",
- "#bb6858",
- "#d98f80",
- "#f1baaf",
- "#ffe8e4"
- ]
- },
- "daemon-blood": {
- "role": "neutral",
- "displayName": "Daemon Blood",
- "canonical": "#57170d",
- "tonalRamp": [
- "#190503",
- "#40160e",
- "#692e23",
- "#904b3e",
- "#b36d5f",
- "#d29386",
- "#ecbcb3",
- "#fde9e5"
- ]
- },
- "bad-sector": {
- "role": "neutral",
- "displayName": "Bad Sector",
- "canonical": "#46120a",
- "tonalRamp": [
- "#170604",
- "#3d1913",
- "#633229",
- "#894f44",
- "#ad7065",
- "#cc968b",
- "#e7beb6",
- "#fbeae7"
- ]
- },
- "core-meltdown": {
- "role": "neutral",
- "displayName": "Core Meltdown",
- "canonical": "#340d07",
- "tonalRamp": [
- "#150705",
- "#381c17",
- "#5d362e",
- "#82534a",
- "#a4756b",
- "#c49990",
- "#e1c1ba",
- "#f9ebe8"
- ]
- },
- "null-pointer": {
- "role": "neutral",
- "displayName": "Null Pointer",
- "canonical": "#230905",
- "tonalRamp": [
- "#120806",
- "#331f1b",
- "#563a34",
- "#795851",
- "#9b7971",
- "#bc9d96",
- "#dac3be",
- "#f6ecea"
- ]
- },
- "event-horizon": {
- "role": "primary",
- "displayName": "Event Horizon",
- "canonical": "#110402",
- "tonalRamp": [
- "#100908",
- "#2e221e",
- "#4f3d38",
- "#705c56",
- "#927d77",
- "#b3a09b",
- "#d4c6c1",
- "#f3edeb"
- ]
- },
- "memory-leek": {
- "role": "secondary",
- "displayName": "Memory Leek",
- "canonical": "#8fa667",
- "tonalRamp": [
- "#080e00",
- "#1e2a02",
- "#384911",
- "#556a2d",
- "#768c50",
- "#9aae7a",
- "#c1d0aa",
- "#ebf1e2"
- ]
- },
- "dim-memory-leek": {
- "role": "secondary",
- "displayName": "Dim Memory Leek",
- "canonical": "#627247",
- "tonalRamp": [
- "#090d03",
- "#20290e",
- "#3a4823",
- "#58683e",
- "#79895f",
- "#9dac86",
- "#c3ceb3",
- "#ecf0e5"
- ]
- },
- "bright-memory-leek": {
- "role": "secondary",
- "displayName": "Bright Memory Leek",
- "canonical": "#94a577",
- "tonalRamp": [
- "#090d02",
- "#20290d",
- "#3b4822",
- "#59683d",
- "#7a895e",
- "#9dac85",
- "#c3ceb2",
- "#ecf0e5"
- ]
- },
- "stack-overglow": {
- "role": "secondary",
- "displayName": "Stack Overglow",
- "canonical": "#d4a759",
- "tonalRamp": [
- "#150800",
- "#381f00",
- "#5d3a00",
- "#825800",
- "#a47a2c",
- "#c49f60",
- "#e0c59a",
- "#f8eddc"
- ]
- },
- "dim-stack-overglow": {
- "role": "secondary",
- "displayName": "Dim Stack Overglow",
- "canonical": "#a07e43",
- "tonalRamp": [
- "#130900",
- "#352100",
- "#583c00",
- "#7b5b1e",
- "#9d7c44",
- "#bea070",
- "#dbc6a4",
- "#f6eddf"
- ]
- },
- "bright-stack-overglow": {
- "role": "secondary",
- "displayName": "Bright Stack Overglow",
- "canonical": "#d3ae6e",
- "tonalRamp": [
- "#130900",
- "#352000",
- "#593c00",
- "#7c5b16",
- "#9e7c3f",
- "#bea06d",
- "#dcc6a1",
- "#f6edde"
- ]
- },
- "blue-screen": {
- "role": "tertiary",
- "displayName": "Blue Screen",
- "canonical": "#8791b0",
- "tonalRamp": [
- "#080b13",
- "#1f2436",
- "#394159",
- "#57607d",
- "#78819f",
- "#9ca4bf",
- "#c2c9dc",
- "#ebeef6"
- ]
- },
- "dim-blue-screen": {
- "role": "tertiary",
- "displayName": "Dim Blue Screen",
- "canonical": "#60677c",
- "tonalRamp": [
- "#090b11",
- "#202531",
- "#3c4153",
- "#5a6175",
- "#7b8297",
- "#9ea5b8",
- "#c4c9d7",
- "#eceef4"
- ]
- },
- "bright-blue-screen": {
- "role": "tertiary",
- "displayName": "Bright Blue Screen",
- "canonical": "#999eaf",
- "tonalRamp": [
- "#0a0b10",
- "#22252e",
- "#3e414f",
- "#5c6170",
- "#7d8292",
- "#a0a4b3",
- "#c6c9d3",
- "#edeef3"
- ]
- },
- "fractured-shell": {
- "role": "tertiary",
- "displayName": "Fractured Shell",
- "canonical": "#ba5a7d",
- "tonalRamp": [
- "#1b020b",
- "#450a24",
- "#701f41",
- "#983c60",
- "#bd5f81",
- "#dc88a4",
- "#f3b5c8",
- "#ffe7ee"
- ]
- },
- "dim-fractured-shell": {
- "role": "tertiary",
- "displayName": "Dim Fractured Shell",
- "canonical": "#87405a",
- "tonalRamp": [
- "#18040b",
- "#3f1324",
- "#672a41",
- "#8e4760",
- "#b26881",
- "#d18fa4",
- "#ebbac8",
- "#fde8ee"
- ]
- },
- "bright-fractured-shell": {
- "role": "tertiary",
- "displayName": "Bright Fractured Shell",
- "canonical": "#ba6b88",
- "tonalRamp": [
- "#18030b",
- "#401225",
- "#682842",
- "#8f4562",
- "#b36783",
- "#d28ea6",
- "#ecb9c9",
- "#fee8ef"
- ]
- },
- "dead-thread": {
- "role": "secondary",
- "displayName": "Dead Thread",
- "canonical": "#6fa5a0",
- "tonalRamp": [
- "#010e0d",
- "#062b29",
- "#1b4b47",
- "#376c68",
- "#5a8d89",
- "#83afab",
- "#b1d1cd",
- "#e5f2f0"
- ]
- },
- "dim-dead-thread": {
- "role": "secondary",
- "displayName": "Dim Dead Thread",
- "canonical": "#4c726e",
- "tonalRamp": [
- "#030e0c",
- "#122a28",
- "#284946",
- "#446966",
- "#658b87",
- "#8cada9",
- "#b7cfcc",
- "#e7f1f0"
- ]
- },
- "bright-dead-thread": {
- "role": "secondary",
- "displayName": "Bright Dead Thread",
- "canonical": "#7fa5a1",
- "tonalRamp": [
- "#040d0c",
- "#122a28",
- "#294946",
- "#456966",
- "#678b87",
- "#8daca9",
- "#b8cfcc",
- "#e8f1f0"
- ]
- },
- "thermal-throttle": {
- "role": "tertiary",
- "displayName": "Thermal Throttle",
- "canonical": "#d78556",
- "tonalRamp": [
- "#1a0400",
- "#431400",
- "#6d2c00",
- "#954916",
- "#b96c3e",
- "#d7926c",
- "#f0bda1",
- "#ffeade"
- ]
- },
- "dim-thermal-throttle": {
- "role": "tertiary",
- "displayName": "Dim Thermal Throttle",
- "canonical": "#ac6d4a",
- "tonalRamp": [
- "#170600",
- "#3e1902",
- "#653212",
- "#8b502d",
- "#af714f",
- "#ce9779",
- "#e8bfaa",
- "#fcebe2"
- ]
- },
- "bright-thermal-throttle": {
- "role": "tertiary",
- "displayName": "Bright Thermal Throttle",
- "canonical": "#d6926b",
- "tonalRamp": [
- "#180600",
- "#3f1900",
- "#66310d",
- "#8d4f29",
- "#b0714c",
- "#cf9676",
- "#e9bfa8",
- "#fceae1"
- ]
- }
- },
- "typographyMeta": {
- "display": {
- "displayName": "Display",
- "purpose": "The h1. Used once per page for the logo/title. Tracked wide to read like embossed lettering on a server panel."
- },
- "headline": {
- "displayName": "Headline",
- "purpose": "Section titles (h2). Same family as Display, smaller and less tracked."
- },
- "title": {
- "displayName": "Title",
- "purpose": "Card headers, code-block titles, panel labels. Small, dense, tracked. The workhorse label voice."
- },
- "body": {
- "displayName": "Body",
- "purpose": "Running text, descriptions, documentation. Warm slab serif at 500 weight, comfortable over long sessions."
- },
- "label": {
- "displayName": "Label",
- "purpose": "Tags, badges, version indicators. The smallest tracked voice."
- },
- "mono": {
- "displayName": "Mono",
- "purpose": "Code blocks, terminal output, hex values. Tabular numerals, no hyphenation."
- }
- },
- "shadows": [
- {
- "name": "offset-sm",
- "value": "2px 2px 0 0 #46120a",
- "purpose": "Default elevation for cards and code blocks at rest."
- },
- {
- "name": "offset-md",
- "value": "3px 3px 0 0 #46120a",
- "purpose": "Elevated surfaces, terminals, and palette sections."
- },
- {
- "name": "offset-lg",
- "value": "4px 4px 0 0 #46120a",
- "purpose": "Lightbox images and primary call-to-action emphasis."
- },
- {
- "name": "hover-md",
- "value": "4px 4px 0 0 #46120a",
- "purpose": "Hover state. Offset grows by 2px on both axes."
- },
- {
- "name": "active",
- "value": "0 0 0 0 #46120a",
- "purpose": "Pressed state. Offset collapses to zero; the element sits flush against the surface."
- },
- {
- "name": "glow-sm",
- "value": "0 0 10px rgba(175, 46, 26, 0.4)",
- "purpose": "Subtle brand-colour glow on hovered primary buttons and focused accent elements."
- },
- {
- "name": "glow-md",
- "value": "0 0 20px rgba(175, 46, 26, 0.4)",
- "purpose": "Stronger glow for lightbox images and hero-level emphasis."
- },
- {
- "name": "inner-highlight",
- "value": "inset 0 1px 0 rgba(255, 255, 255, 0.1)",
- "purpose": "Faint light-line at the top edge of raised surfaces; stacked under the offset shadow, the two travel together."
- },
- {
- "name": "inner-lowlight",
- "value": "inset 0 -1px 0 rgba(17, 4, 2, 0.6)",
- "purpose": "Inverse shade at the bottom edge of wells, toggle thumbs, and slider thumbs. Paired with the inner highlight on machined parts."
- },
- {
- "name": "accent",
- "value": "5px 5px 0 0 #af2e1a",
- "purpose": "Offset in the brand colour for primary buttons and brand-level emphasis."
- }
- ],
- "motion": [
- {
- "name": "ease-default",
- "value": "cubic-bezier(0.4, 0, 0.2, 1)",
- "purpose": "Default easing for state transitions."
- },
- {
- "name": "ease-out-expo",
- "value": "cubic-bezier(0.22, 1, 0.36, 1)",
- "purpose": "Entrance animations (typeIn)."
- },
- {
- "name": "duration-fast",
- "value": "150ms",
- "purpose": "Hover, focus, and micro-feedback transitions. The press cycle runs at this speed."
- },
- {
- "name": "duration-normal",
- "value": "250ms",
- "purpose": "Standard state transitions."
- },
- {
- "name": "duration-slow",
- "value": "400ms",
- "purpose": "Entrance and reveal animations."
- },
- {
- "name": "transition-fast",
- "value": "150ms cubic-bezier(0.4, 0, 0.2, 1)",
- "purpose": "Composed fast transition used by the press cycle on interactive elements."
- },
- {
- "name": "transition-normal",
- "value": "250ms cubic-bezier(0.4, 0, 0.2, 1)",
- "purpose": "Composed standard transition."
- }
- ],
- "breakpoints": [
- {
- "name": "sm",
- "value": "480px",
- "purpose": "Small mobile / narrow viewport."
- },
- {
- "name": "md",
- "value": "768px",
- "purpose": "Tablet / compact layout; code blocks drop to 0.75rem below this."
- }
- ]
- },
- "components": [
- {
- "name": "Primary Button",
- "kind": "button",
- "refersTo": "btn-primary",
- "description": "The brand identity button. Digital Rust background, thick border, offset shadow with inner-highlight bevel, physical press response. One per view.",
- "html": "SAVE CHANGES ",
- "css": ".ds-btn-primary { background: #af2e1a; color: #f7eae8; padding: 0.5rem 1.5rem; border: 2px solid #af2e1a; border-radius: 4px; font-family: \"Rajdhani\", \"Saira SemiCondensed\", \"Trebuchet MS\", sans-serif; font-weight: 600; font-size: 0.875rem; text-transform: uppercase; letter-spacing: 0.05em; cursor: pointer; box-shadow: 3px 3px 0 0 #46120a, inset 0 1px 0 rgba(255, 255, 255, 0.1); transition: transform 150ms cubic-bezier(0.4, 0, 0.2, 1), box-shadow 150ms cubic-bezier(0.4, 0, 0.2, 1), background-color 150ms cubic-bezier(0.4, 0, 0.2, 1), border-color 150ms cubic-bezier(0.4, 0, 0.2, 1); } .ds-btn-primary:hover { background: #b74230; border-color: #b74230; transform: translate(-2px, -2px); box-shadow: 4px 4px 0 0 #46120a, 0 0 10px rgba(175, 46, 26, 0.4), inset 0 1px 0 rgba(255, 255, 255, 0.1); } .ds-btn-primary:active { transform: translate(2px, 2px); box-shadow: 0 0 0 0 #46120a; } .ds-btn-primary:focus-visible { outline: 2px solid #d4a759; outline-offset: 2px; }"
- },
- {
- "name": "Ghost Button",
- "kind": "button",
- "refersTo": "btn",
- "description": "The default/secondary button. Transparent background, Dark Packet border, offset shadow with inner highlight; hover fills Core Meltdown with a Digital Rust edge.",
- "html": "CANCEL ",
- "css": ".ds-btn-ghost { background: transparent; color: #efd5d1; padding: 0.5rem 1.5rem; border: 2px solid #691b0f; border-radius: 4px; font-family: \"Rajdhani\", \"Saira SemiCondensed\", \"Trebuchet MS\", sans-serif; font-weight: 600; font-size: 0.875rem; text-transform: uppercase; letter-spacing: 0.05em; cursor: pointer; box-shadow: 2px 2px 0 0 #46120a, inset 0 1px 0 rgba(255, 255, 255, 0.1); transition: transform 150ms cubic-bezier(0.4, 0, 0.2, 1), box-shadow 150ms cubic-bezier(0.4, 0, 0.2, 1), background-color 150ms cubic-bezier(0.4, 0, 0.2, 1), border-color 150ms cubic-bezier(0.4, 0, 0.2, 1), color 150ms cubic-bezier(0.4, 0, 0.2, 1); } .ds-btn-ghost:hover { background: #340d07; border-color: #af2e1a; color: #f7eae8; transform: translate(-2px, -2px); box-shadow: 4px 4px 0 0 #46120a, inset 0 1px 0 rgba(255, 255, 255, 0.1); } .ds-btn-ghost:active { transform: translate(2px, 2px); box-shadow: 0 0 0 0 #46120a; } .ds-btn-ghost:focus-visible { outline: 2px solid #d4a759; outline-offset: 2px; }"
- },
- {
- "name": "Card",
- "kind": "card",
- "refersTo": "spec-card",
- "description": "Workhorse container with thick borders, offset shadow, and inner highlight. Presses in on active like a bolted rack module.",
- "html": "PRIORITY STACK Error scopes override everything with Amber Alert
",
- "css": ".ds-card { background: #340d07; border: 2px solid #691b0f; border-radius: 4px; padding: 1.5rem; box-shadow: 2px 2px 0 0 #46120a, inset 0 1px 0 rgba(255, 255, 255, 0.1); transition: transform 150ms cubic-bezier(0.4, 0, 0.2, 1), box-shadow 150ms cubic-bezier(0.4, 0, 0.2, 1); } .ds-card:hover { transform: translate(-2px, -2px); box-shadow: 4px 4px 0 0 #46120a; } .ds-card:active { transform: translate(2px, 2px); box-shadow: 0 0 0 0 #46120a; } .ds-card-title { color: #cf8175; margin-bottom: 0.5rem; font-size: 0.875rem; letter-spacing: 0.05em; text-transform: uppercase; font-family: \"Rajdhani\", \"Saira SemiCondensed\", \"Trebuchet MS\", sans-serif; font-weight: 700; } .ds-card-body { color: #f7eae8; font-size: 1rem; line-height: 1.6; font-family: \"Zilla Slab\", \"Bitter\", \"Source Serif 4\", Georgia, serif; }"
- },
- {
- "name": "Badge - Success",
- "kind": "chip",
- "refersTo": "badge",
- "description": "Semantic success indicator with Memory Leek tint. Static: no press cycle, no shadow.",
- "html": "GIT ADDED ",
- "css": ".ds-badge-success { border-radius: 4px; padding: 0.2rem 0.6rem; font-size: 0.75rem; text-transform: uppercase; letter-spacing: 0.08em; font-weight: 700; font-family: \"Rajdhani\", \"Saira SemiCondensed\", \"Trebuchet MS\", sans-serif; border: 1px solid rgba(143, 166, 103, 0.3); background: rgba(143, 166, 103, 0.15); color: #8fa667; }"
- },
- {
- "name": "Badge - Info",
- "kind": "chip",
- "refersTo": "badge",
- "description": "Semantic informational indicator with Dead Thread tint. Static: no press cycle, no shadow.",
- "html": "MODIFIED ",
- "css": ".ds-badge-info { border-radius: 4px; padding: 0.2rem 0.6rem; font-size: 0.75rem; text-transform: uppercase; letter-spacing: 0.08em; font-weight: 700; font-family: \"Rajdhani\", \"Saira SemiCondensed\", \"Trebuchet MS\", sans-serif; border: 1px solid rgba(111, 165, 160, 0.3); background: rgba(111, 165, 160, 0.15); color: #6fa5a0; }"
- },
- {
- "name": "Badge - Warning",
- "kind": "chip",
- "refersTo": "badge",
- "description": "Semantic warning indicator with Stack Overglow tint. Static: no press cycle, no shadow.",
- "html": "DEPRECATED ",
- "css": ".ds-badge-warning { border-radius: 4px; padding: 0.2rem 0.6rem; font-size: 0.75rem; text-transform: uppercase; letter-spacing: 0.08em; font-weight: 700; font-family: \"Rajdhani\", \"Saira SemiCondensed\", \"Trebuchet MS\", sans-serif; border: 1px solid rgba(212, 167, 89, 0.3); background: rgba(212, 167, 89, 0.15); color: #d4a759; }"
- },
- {
- "name": "Badge - Error",
- "kind": "chip",
- "refersTo": "badge",
- "description": "Semantic error indicator. Amber Alert Text on a 10% Amber Alert tint — the AA-compliant text variant, never the raw colour.",
- "html": "GIT DELETED ",
- "css": ".ds-badge-error { border-radius: 4px; padding: 0.2rem 0.6rem; font-size: 0.75rem; text-transform: uppercase; letter-spacing: 0.08em; font-weight: 700; font-family: \"Rajdhani\", \"Saira SemiCondensed\", \"Trebuchet MS\", sans-serif; border: 1px solid rgba(191, 87, 71, 0.25); background: rgba(191, 87, 71, 0.1); color: #cb6353; }"
- },
- {
- "name": "Text Input (Well)",
- "kind": "input",
- "refersTo": null,
- "description": "Recessed well: the darkest surface on the page, no offset shadow, no lift. Responds through border colour only (Bad Sector rest, Dark Packet hover, Digital Rust focus).",
- "html": " ",
- "css": ".ds-input { background: #110402; border: 2px solid #46120a; border-radius: 4px; padding: 0.5rem 0.75rem; color: #f7eae8; font-family: \"Zilla Slab\", \"Bitter\", \"Source Serif 4\", Georgia, serif; font-size: 1rem; transition: border-color 150ms cubic-bezier(0.4, 0, 0.2, 1), box-shadow 150ms cubic-bezier(0.4, 0, 0.2, 1); } .ds-input:hover:not(:focus) { border-color: #691b0f; } .ds-input:focus { outline: 2px solid #d4a759; outline-offset: 2px; border-color: #af2e1a; } .ds-input::placeholder { color: rgba(239, 213, 209, 0.5); font-style: italic; }"
- },
- {
- "name": "Navigation Link",
- "kind": "nav",
- "refersTo": null,
- "description": "Phantom Current with a 1px underline at 3px offset. Hover shifts to Fatal Error with a 2px underline; visited is Corrupted Cache.",
- "html": "Read the specification ",
- "css": ".ds-link { color: #e7c0ba; text-decoration: underline; text-decoration-thickness: 1px; text-underline-offset: 3px; font-family: \"Zilla Slab\", \"Bitter\", \"Source Serif 4\", Georgia, serif; transition: color 150ms cubic-bezier(0.4, 0, 0.2, 1), text-decoration-thickness 150ms cubic-bezier(0.4, 0, 0.2, 1); } .ds-link:hover { color: #cf8175; text-decoration-thickness: 2px; } .ds-link:visited { color: #dfaba3; } .ds-link:focus-visible { outline: 2px solid #d4a759; outline-offset: 2px; }"
- },
- {
- "name": "Terminal",
- "kind": "custom",
- "refersTo": "terminal",
- "description": "The brand's signature interactive metaphor. Fake terminal running spec validation commands, with a Stack Overglow block cursor.",
- "html": "
● ● ●
digitalrust@entropy:~$ theme audit --strict
Syntax Coverage ........ PASS
digitalrust@entropy:~$
",
- "css": ".ds-terminal { background: #110402; border: 2px solid #691b0f; border-radius: 6px; padding: 1.5rem; position: relative; overflow: hidden; box-shadow: 3px 3px 0 0 #46120a, inset 0 1px 0 rgba(255, 255, 255, 0.1); } .ds-terminal-dots { position: absolute; top: 0; left: 0; right: 0; padding: 0.5rem 1rem; background: #340d07; color: #af2e1a; border-bottom: 1px solid #46120a; font-size: 0.75rem; letter-spacing: 0.5rem; } .ds-terminal-body { margin-top: 2rem; font-family: \"IBM Plex Mono\", \"Space Mono\", ui-monospace, \"Fira Code\", monospace; font-size: 0.875rem; line-height: 1.6; } .ds-terminal-prompt { color: #e7c0ba; } .ds-terminal-cmd { color: #f7eae8; } .ds-terminal-output { color: #efd5d1; margin-left: 2rem; opacity: 0.95; } .ds-terminal-pass { color: #8fa667; font-weight: 700; } .ds-terminal-cursor { display: inline-block; width: 0.6em; height: 1.2em; background: #d4a759; vertical-align: text-bottom; }"
- }
- ],
- "narrative": {
- "northStar": "The Corroded Mainframe",
- "overview": "A server room where every surface has oxidized, but the machines still hum. The walls are rust; the screens still glow. Failure is the texture, not the state.\n\nDigital Rust is a dark-mode-only system built around a single rust-to-void gradient: warm copper tones that bleed from near-white to near-black through 19 named stops, each one a hardware failure metaphor. The accent colours (Memory Leek, Stack Overglow, Dead Thread, Blue Screen, Fractured Shell, Thermal Throttle) are named after system crashes and injected surgically, never as a rainbow. Surfaces carry structural noise and scanline overlays; flat, noiseless backgrounds are a design failure. Borders are thick and heavy (2-4px Dark Packet), shadows are offset solids with no blur, corners never exceed 6px radius. Every component feels like a physical panel in a failing server rack: brutalist, tactile, press-and-release.\n\nThe system explicitly rejects the cold blue-purple dark theme family (Dracula, Nord, Tokyo Night, One Dark) and any sterile \"pro\" aesthetic with gray surfaces and blue accents. Pure black (`#000`) is forbidden in shadows and backgrounds, replaced by the warm near-blacks of the rust ramp. The hostility is in the atmosphere, not the readability: Ghost Pixel on Event Horizon hits 17.17:1 contrast ratio.",
- "keyCharacteristics": [
- "Single-hue warm ramp (copper/rust/bone) as the structural spine, not a multi-hue palette",
- "Offset solid shadows (no blur) that serve both interaction feedback and the corroded machine aesthetic",
- "Structural noise and scanline overlays on every surface; silence them only for `prefers-reduced-motion`",
- "Borders as heavy structural elements (2-4px Dark Packet), never decorative hairlines",
- "Accent colours named after system failures, used surgically for syntax and diagnostics",
- "Radius ceiling of 6px; nothing rounds past \"gently chamfered\""
- ],
- "rules": [
- {
- "name": "The One Hue Rule",
- "body": "The 19-stop main ramp occupies a single warm hue family. Accents are admitted in six named failure families, but the surface itself never leaves the rust-to-void gradient. If a background or border colour is not one of the 19 ramp stops or one of the 6 accent families, it does not belong in the system.",
- "section": "colors"
- },
- {
- "name": "The Black Is Forbidden Rule",
- "body": "`#000000` is prohibited in shadows, borders, and backgrounds. The nearest near-black is Event Horizon (`#110402`). Shadows, overlays, and vignettes use warm-tinted transparencies of the brand colour: `rgba(175, 46, 26, ...)`. Pure black reads as a different material; this system has no cold materials.",
- "section": "colors"
- },
- {
- "name": "The Flat Surface Failure Rule",
- "body": "A flat, noiseless dark surface with no texture overlay is a design defect. Every ambient surface carries the SVG noise texture (opacity 0.02) and scanline overlay. These are structural, not decorative. The sole exemptions are interactive text surfaces (inputs, text areas, editable code regions), which stay clean for legibility, and `prefers-reduced-motion: reduce`, which silences all overlays.",
- "section": "colors"
- },
- {
- "name": "The One Heading Colour Rule",
- "body": "Fatal Error (`#cf8175`) is the only colour used for headings of any level. Not white, not Ghost Pixel, not the accent colours. Every heading speaks in the same warm-copper voice. If a heading is not Fatal Error, it is not a heading.",
- "section": "typography"
- },
- {
- "name": "The All-Caps Ceiling Rule",
- "body": "Rajdhani headings and labels are set in all-caps with wide tracking. This is an intentional, restricted choice for short strings (titles, labels, badges). Body copy is never all-caps. A sentence in all-caps at body size is unreadable and prohibited.",
- "section": "typography"
- },
- {
- "name": "The No Blur Rule",
- "body": "`box-shadow` blur radius is zero for all structural shadows. The only blur in the system is the glow shadow (which simulates light, not material depth). If a shadow has a non-zero blur and is not a glow, it does not belong.",
- "section": "elevation"
- },
- {
- "name": "The Press-And-Release Rule",
- "body": "Interactive elements with offset shadows must implement the full hover-then-press cycle: rest has offset, hover grows offset by 2px on both axes and lifts the element `translate(-2px, -2px)`, active collapses offset to zero and drives the element `translate(2px, 2px)` into the surface. The state transition must use `--dr-transition-fast` (150ms).",
- "section": "elevation"
- },
- {
- "name": "The Recessed Well Rule",
- "body": "Inputs, text areas, and editable code regions sit *below* the panel, not above it: Event Horizon background, 2px Bad Sector border, no offset shadow, no lift on hover. Wells respond through border colour (Bad Sector rest, Dark Packet hover, Digital Rust focus). They are exempt from noise and scanline texture; legibility outranks atmosphere inside a text field.",
- "section": "elevation"
- }
- ],
- "dos": [
- "Do use the 19-stop rust ramp as the only neutral scale. There is no separate gray ramp; the warm stops from Ghost Pixel to Event Horizon are the neutrals.",
- "Do enforce WCAG 2.1 AA contrast on all text. Ghost Pixel on Event Horizon (17.17:1) is the baseline; Dim Thermal Throttle on Event Horizon (4.84:1) is the darkest acceptable body text.",
- "Do use noise and scanline overlays on every surface. They are structural, not decorative. A flat noiseless dark background is a defect.",
- "Do use offset solid shadows (no blur) in Bad Sector for material depth. Grow offset on hover, collapse on active to simulate a physical press.",
- "Do use thick borders (2-4px Dark Particle) as structural elements. Borders are walls, not decoration.",
- "Do keep radius at 2-6px. Nothing rounds past \"gently chamfered\". A 16px+ radius on a card or panel is a different design system.",
- "Do name accent colours after system failures (Memory Leek, Stack Overglow, Dead Thread, Blue Screen, Fractured Shell, Thermal Throttle). New accents get parallel naming.",
- "Do use wavy underlines for diagnostics (Amber Alert wavy for errors, Stack Overglow wavy for warnings) and solid underlines for links. The underline style carries semantic information.",
- "Do implement the full hover-then-press cycle on all interactive elements: rest offset, hover offset grows, active offset collapses.",
- "Do suppress noise, scanlines, and all animations for `prefers-reduced-motion: reduce`. The content must be fully visible without the animation.",
- "Do keep surface-background tints for badges/diagnostics at 10-15% opacity of the named colour. This is enough to carry the semantic tint without competing with the ramp."
- ],
- "donts": [
- "Don't use pure black (`#000000`) in shadows, borders, or backgrounds. The system has no cold materials. Use Event Horizon (`#110402`) or warm-tinted transparencies of the brand colour.",
- "Don't use blurred drop shadows. The only blur in the system is the glow effect (`0 0 Npx rgba(175, 46, 26, 0.4)`), which simulates radiated heat, not material depth.",
- "Don't use Dracula, Nord, Tokyo Night, One Dark, or any cold/blue/purple dark theme aesthetic. Those are the explicit anti-references. Cool tones are the opposite of the corroded mainframe.",
- "Don't use flat, noiseless dark surfaces without the SVG noise and scanline overlays. Remove only for `prefers-reduced-motion`.",
- "Don't use colours outside the 19 ramp stops and 6 accent families. If a colour is not in the palette, it does not belong. Extend the palette deliberately, not by accident.",
- "Don't use Fatal Error (`#cf8175`) for body text or link text. It is reserved for headings and keyword tokens. Body text uses Ghost Pixel or Phosphor Smoke; links use Phantom Current.",
- "Don't set body copy in all-caps. Rajdhani all-caps with wide tracking is for headings and labels only (4 words or fewer for labels).",
- "Don't use `border-left` or `border-right` greater than 1px as a coloured accent stripe on cards, list items, or callouts. The section-title left border is a rare deliberate exception.",
- "Don't use border-radius above 6px on any card, panel, or container. Full-pill radius is acceptable for small inline elements (badges, tags) only.",
- "Don't place a 1px border and a wide soft shadow on the same element. Pick one: a solid thick border at the brand colour, or a defined offset shadow at no more than 8px offset. Never both as decoration."
- ]
- }
+ "schemaVersion": 2,
+ "generatedAt": "2026-08-17T04:02:00.494Z",
+ "title": "Design System: Digital Rust",
+ "extensions": {
+ "colorMeta": {
+ "ghost-pixel": {
+ "role": "primary",
+ "displayName": "Ghost Pixel",
+ "canonical": "#f7eae8",
+ "tonalRamp": [
+ "#0e0a0a",
+ "#2a2322",
+ "#493f3e",
+ "#695e5d",
+ "#8b7f7e",
+ "#aca2a1",
+ "#cfc7c6",
+ "#f1eeed"
+ ]
+ },
+ "phosphor-smoke": {
+ "role": "primary",
+ "displayName": "Phosphor Smoke",
+ "canonical": "#efd5d1",
+ "tonalRamp": [
+ "#100908",
+ "#2f211f",
+ "#4f3d3a",
+ "#715b58",
+ "#937c79",
+ "#b4a09c",
+ "#d4c5c3",
+ "#f3edec"
+ ]
+ },
+ "phantom-current": {
+ "role": "primary",
+ "displayName": "Phantom Current",
+ "canonical": "#e7c0ba",
+ "tonalRamp": [
+ "#120807",
+ "#331f1c",
+ "#563a36",
+ "#795853",
+ "#9b7973",
+ "#bc9d98",
+ "#dac3bf",
+ "#f6ecea"
+ ]
+ },
+ "corrupted-cache": {
+ "role": "neutral",
+ "displayName": "Corrupted Cache",
+ "canonical": "#dfaba3",
+ "tonalRamp": [
+ "#140706",
+ "#381c18",
+ "#5d3631",
+ "#81544d",
+ "#a4756e",
+ "#c49993",
+ "#e0c1bc",
+ "#f8ebe9"
+ ]
+ },
+ "copper-trace": {
+ "role": "neutral",
+ "displayName": "Copper Trace",
+ "canonical": "#d7968c",
+ "tonalRamp": [
+ "#170604",
+ "#3c1914",
+ "#63322b",
+ "#894f47",
+ "#ac7067",
+ "#cc968d",
+ "#e7beb8",
+ "#fbeae7"
+ ]
+ },
+ "fatal-error": {
+ "role": "primary",
+ "displayName": "Fatal Error",
+ "canonical": "#cf8175",
+ "tonalRamp": [
+ "#190403",
+ "#41150f",
+ "#6a2c24",
+ "#91493f",
+ "#b56b60",
+ "#d49287",
+ "#edbcb3",
+ "#fee9e5"
+ ]
+ },
+ "rouge-signal": {
+ "role": "neutral",
+ "displayName": "Rouge Signal",
+ "canonical": "#c76c5e",
+ "tonalRamp": [
+ "#1b0302",
+ "#450f09",
+ "#70261d",
+ "#994337",
+ "#bd6658",
+ "#dc8d80",
+ "#f3b9af",
+ "#ffe8e4"
+ ]
+ },
+ "amber-alert": {
+ "role": "primary",
+ "displayName": "Amber Alert",
+ "canonical": "#bf5747",
+ "tonalRamp": [
+ "#1d0100",
+ "#4a0803",
+ "#761e13",
+ "#a03c2d",
+ "#c56050",
+ "#e48979",
+ "#f9b6aa",
+ "#ffe7e2"
+ ]
+ },
+ "amber-alert-text": {
+ "role": "neutral",
+ "displayName": "Amber Alert Text",
+ "canonical": "#cb6353",
+ "tonalRamp": [
+ "#1d0101",
+ "#490803",
+ "#761e14",
+ "#9f3c2f",
+ "#c56051",
+ "#e3897a",
+ "#f9b6aa",
+ "#ffe7e2"
+ ]
+ },
+ "firewall-breach": {
+ "role": "neutral",
+ "displayName": "Firewall Breach",
+ "canonical": "#b74230",
+ "tonalRamp": [
+ "#1f0000",
+ "#4e0000",
+ "#7c1305",
+ "#a73322",
+ "#cd5946",
+ "#eb8472",
+ "#ffb3a5",
+ "#ffe6e0"
+ ]
+ },
+ "digital-rust": {
+ "role": "primary",
+ "displayName": "Digital Rust",
+ "canonical": "#af2e1a",
+ "tonalRamp": [
+ "#210000",
+ "#500000",
+ "#800500",
+ "#ac2c18",
+ "#d2543f",
+ "#f0816c",
+ "#ffb1a1",
+ "#ffe5de"
+ ]
+ },
+ "kernel-panic": {
+ "role": "neutral",
+ "displayName": "Kernel Panic",
+ "canonical": "#9d2917",
+ "tonalRamp": [
+ "#1f0000",
+ "#4e0000",
+ "#7c1303",
+ "#a73421",
+ "#cc5946",
+ "#ea8471",
+ "#ffb3a4",
+ "#ffe6e0"
+ ]
+ },
+ "data-rot": {
+ "role": "neutral",
+ "displayName": "Data Rot",
+ "canonical": "#8c2414",
+ "tonalRamp": [
+ "#1e0100",
+ "#4b0600",
+ "#781c0d",
+ "#a23a29",
+ "#c75e4c",
+ "#e58876",
+ "#fbb5a7",
+ "#ffe7e1"
+ ]
+ },
+ "bricked-board": {
+ "role": "neutral",
+ "displayName": "Bricked Board",
+ "canonical": "#7a2012",
+ "tonalRamp": [
+ "#1c0201",
+ "#470d05",
+ "#732316",
+ "#9c4031",
+ "#c16352",
+ "#df8c7b",
+ "#f6b8ab",
+ "#ffe8e2"
+ ]
+ },
+ "dark-packet": {
+ "role": "primary",
+ "displayName": "Dark Packet",
+ "canonical": "#691b0f",
+ "tonalRamp": [
+ "#1b0302",
+ "#441109",
+ "#6e281d",
+ "#964537",
+ "#bb6858",
+ "#d98f80",
+ "#f1baaf",
+ "#ffe8e4"
+ ]
+ },
+ "daemon-blood": {
+ "role": "neutral",
+ "displayName": "Daemon Blood",
+ "canonical": "#57170d",
+ "tonalRamp": [
+ "#190503",
+ "#40160e",
+ "#692e23",
+ "#904b3e",
+ "#b36d5f",
+ "#d29386",
+ "#ecbcb3",
+ "#fde9e5"
+ ]
+ },
+ "bad-sector": {
+ "role": "neutral",
+ "displayName": "Bad Sector",
+ "canonical": "#46120a",
+ "tonalRamp": [
+ "#170604",
+ "#3d1913",
+ "#633229",
+ "#894f44",
+ "#ad7065",
+ "#cc968b",
+ "#e7beb6",
+ "#fbeae7"
+ ]
+ },
+ "core-meltdown": {
+ "role": "neutral",
+ "displayName": "Core Meltdown",
+ "canonical": "#340d07",
+ "tonalRamp": [
+ "#150705",
+ "#381c17",
+ "#5d362e",
+ "#82534a",
+ "#a4756b",
+ "#c49990",
+ "#e1c1ba",
+ "#f9ebe8"
+ ]
+ },
+ "null-pointer": {
+ "role": "neutral",
+ "displayName": "Null Pointer",
+ "canonical": "#230905",
+ "tonalRamp": [
+ "#120806",
+ "#331f1b",
+ "#563a34",
+ "#795851",
+ "#9b7971",
+ "#bc9d96",
+ "#dac3be",
+ "#f6ecea"
+ ]
+ },
+ "event-horizon": {
+ "role": "primary",
+ "displayName": "Event Horizon",
+ "canonical": "#110402",
+ "tonalRamp": [
+ "#100908",
+ "#2e221e",
+ "#4f3d38",
+ "#705c56",
+ "#927d77",
+ "#b3a09b",
+ "#d4c6c1",
+ "#f3edeb"
+ ]
+ },
+ "memory-leek": {
+ "role": "secondary",
+ "displayName": "Memory Leek",
+ "canonical": "#8fa667",
+ "tonalRamp": [
+ "#080e00",
+ "#1e2a02",
+ "#384911",
+ "#556a2d",
+ "#768c50",
+ "#9aae7a",
+ "#c1d0aa",
+ "#ebf1e2"
+ ]
+ },
+ "dim-memory-leek": {
+ "role": "secondary",
+ "displayName": "Dim Memory Leek",
+ "canonical": "#627247",
+ "tonalRamp": [
+ "#090d03",
+ "#20290e",
+ "#3a4823",
+ "#58683e",
+ "#79895f",
+ "#9dac86",
+ "#c3ceb3",
+ "#ecf0e5"
+ ]
+ },
+ "bright-memory-leek": {
+ "role": "secondary",
+ "displayName": "Bright Memory Leek",
+ "canonical": "#94a577",
+ "tonalRamp": [
+ "#090d02",
+ "#20290d",
+ "#3b4822",
+ "#59683d",
+ "#7a895e",
+ "#9dac85",
+ "#c3ceb2",
+ "#ecf0e5"
+ ]
+ },
+ "stack-overglow": {
+ "role": "secondary",
+ "displayName": "Stack Overglow",
+ "canonical": "#d4a759",
+ "tonalRamp": [
+ "#150800",
+ "#381f00",
+ "#5d3a00",
+ "#825800",
+ "#a47a2c",
+ "#c49f60",
+ "#e0c59a",
+ "#f8eddc"
+ ]
+ },
+ "dim-stack-overglow": {
+ "role": "secondary",
+ "displayName": "Dim Stack Overglow",
+ "canonical": "#a07e43",
+ "tonalRamp": [
+ "#130900",
+ "#352100",
+ "#583c00",
+ "#7b5b1e",
+ "#9d7c44",
+ "#bea070",
+ "#dbc6a4",
+ "#f6eddf"
+ ]
+ },
+ "bright-stack-overglow": {
+ "role": "secondary",
+ "displayName": "Bright Stack Overglow",
+ "canonical": "#d3ae6e",
+ "tonalRamp": [
+ "#130900",
+ "#352000",
+ "#593c00",
+ "#7c5b16",
+ "#9e7c3f",
+ "#bea06d",
+ "#dcc6a1",
+ "#f6edde"
+ ]
+ },
+ "blue-screen": {
+ "role": "tertiary",
+ "displayName": "Blue Screen",
+ "canonical": "#8791b0",
+ "tonalRamp": [
+ "#080b13",
+ "#1f2436",
+ "#394159",
+ "#57607d",
+ "#78819f",
+ "#9ca4bf",
+ "#c2c9dc",
+ "#ebeef6"
+ ]
+ },
+ "dim-blue-screen": {
+ "role": "tertiary",
+ "displayName": "Dim Blue Screen",
+ "canonical": "#60677c",
+ "tonalRamp": [
+ "#090b11",
+ "#202531",
+ "#3c4153",
+ "#5a6175",
+ "#7b8297",
+ "#9ea5b8",
+ "#c4c9d7",
+ "#eceef4"
+ ]
+ },
+ "bright-blue-screen": {
+ "role": "tertiary",
+ "displayName": "Bright Blue Screen",
+ "canonical": "#999eaf",
+ "tonalRamp": [
+ "#0a0b10",
+ "#22252e",
+ "#3e414f",
+ "#5c6170",
+ "#7d8292",
+ "#a0a4b3",
+ "#c6c9d3",
+ "#edeef3"
+ ]
+ },
+ "fractured-shell": {
+ "role": "tertiary",
+ "displayName": "Fractured Shell",
+ "canonical": "#ba5a7d",
+ "tonalRamp": [
+ "#1b020b",
+ "#450a24",
+ "#701f41",
+ "#983c60",
+ "#bd5f81",
+ "#dc88a4",
+ "#f3b5c8",
+ "#ffe7ee"
+ ]
+ },
+ "dim-fractured-shell": {
+ "role": "tertiary",
+ "displayName": "Dim Fractured Shell",
+ "canonical": "#87405a",
+ "tonalRamp": [
+ "#18040b",
+ "#3f1324",
+ "#672a41",
+ "#8e4760",
+ "#b26881",
+ "#d18fa4",
+ "#ebbac8",
+ "#fde8ee"
+ ]
+ },
+ "bright-fractured-shell": {
+ "role": "tertiary",
+ "displayName": "Bright Fractured Shell",
+ "canonical": "#ba6b88",
+ "tonalRamp": [
+ "#18030b",
+ "#401225",
+ "#682842",
+ "#8f4562",
+ "#b36783",
+ "#d28ea6",
+ "#ecb9c9",
+ "#fee8ef"
+ ]
+ },
+ "dead-thread": {
+ "role": "secondary",
+ "displayName": "Dead Thread",
+ "canonical": "#6fa5a0",
+ "tonalRamp": [
+ "#010e0d",
+ "#062b29",
+ "#1b4b47",
+ "#376c68",
+ "#5a8d89",
+ "#83afab",
+ "#b1d1cd",
+ "#e5f2f0"
+ ]
+ },
+ "dim-dead-thread": {
+ "role": "secondary",
+ "displayName": "Dim Dead Thread",
+ "canonical": "#4c726e",
+ "tonalRamp": [
+ "#030e0c",
+ "#122a28",
+ "#284946",
+ "#446966",
+ "#658b87",
+ "#8cada9",
+ "#b7cfcc",
+ "#e7f1f0"
+ ]
+ },
+ "bright-dead-thread": {
+ "role": "secondary",
+ "displayName": "Bright Dead Thread",
+ "canonical": "#7fa5a1",
+ "tonalRamp": [
+ "#040d0c",
+ "#122a28",
+ "#294946",
+ "#456966",
+ "#678b87",
+ "#8daca9",
+ "#b8cfcc",
+ "#e8f1f0"
+ ]
+ },
+ "thermal-throttle": {
+ "role": "tertiary",
+ "displayName": "Thermal Throttle",
+ "canonical": "#d78556",
+ "tonalRamp": [
+ "#1a0400",
+ "#431400",
+ "#6d2c00",
+ "#954916",
+ "#b96c3e",
+ "#d7926c",
+ "#f0bda1",
+ "#ffeade"
+ ]
+ },
+ "dim-thermal-throttle": {
+ "role": "tertiary",
+ "displayName": "Dim Thermal Throttle",
+ "canonical": "#ac6d4a",
+ "tonalRamp": [
+ "#170600",
+ "#3e1902",
+ "#653212",
+ "#8b502d",
+ "#af714f",
+ "#ce9779",
+ "#e8bfaa",
+ "#fcebe2"
+ ]
+ },
+ "bright-thermal-throttle": {
+ "role": "tertiary",
+ "displayName": "Bright Thermal Throttle",
+ "canonical": "#d6926b",
+ "tonalRamp": [
+ "#180600",
+ "#3f1900",
+ "#66310d",
+ "#8d4f29",
+ "#b0714c",
+ "#cf9676",
+ "#e9bfa8",
+ "#fceae1"
+ ]
+ }
+ },
+ "typographyMeta": {
+ "display": {
+ "displayName": "Display",
+ "purpose": "The h1. Used once per page for the logo/title. Tracked wide to read like embossed lettering on a server panel."
+ },
+ "headline": {
+ "displayName": "Headline",
+ "purpose": "Section titles (h2). Same family as Display, smaller and less tracked."
+ },
+ "title": {
+ "displayName": "Title",
+ "purpose": "Card headers, code-block titles, panel labels. Small, dense, tracked. The workhorse label voice."
+ },
+ "body": {
+ "displayName": "Body",
+ "purpose": "Running text, descriptions, documentation. Warm slab serif at 500 weight, comfortable over long sessions."
+ },
+ "label": {
+ "displayName": "Label",
+ "purpose": "Tags, badges, version indicators. The smallest tracked voice."
+ },
+ "mono": {
+ "displayName": "Mono",
+ "purpose": "Code blocks, terminal output, hex values. Tabular numerals, no hyphenation."
+ }
+ },
+ "shadows": [
+ {
+ "name": "offset-sm",
+ "value": "2px 2px 0 0 #46120a",
+ "purpose": "Default elevation for cards and code blocks at rest."
+ },
+ {
+ "name": "offset-md",
+ "value": "3px 3px 0 0 #46120a",
+ "purpose": "Elevated surfaces, terminals, and palette sections."
+ },
+ {
+ "name": "offset-lg",
+ "value": "4px 4px 0 0 #46120a",
+ "purpose": "Lightbox images and primary call-to-action emphasis."
+ },
+ {
+ "name": "hover-md",
+ "value": "4px 4px 0 0 #46120a",
+ "purpose": "Hover state. Offset grows by 2px on both axes."
+ },
+ {
+ "name": "active",
+ "value": "0 0 0 0 #46120a",
+ "purpose": "Pressed state. Offset collapses to zero; the element sits flush against the surface."
+ },
+ {
+ "name": "glow-sm",
+ "value": "0 0 10px rgba(175, 46, 26, 0.4)",
+ "purpose": "Subtle brand-colour glow on hovered primary buttons and focused accent elements."
+ },
+ {
+ "name": "glow-md",
+ "value": "0 0 20px rgba(175, 46, 26, 0.4)",
+ "purpose": "Stronger glow for lightbox images and hero-level emphasis."
+ },
+ {
+ "name": "inner-highlight",
+ "value": "inset 0 1px 0 rgba(255, 255, 255, 0.1)",
+ "purpose": "Faint light-line at the top edge of raised surfaces; stacked under the offset shadow, the two travel together."
+ },
+ {
+ "name": "inner-lowlight",
+ "value": "inset 0 -1px 0 rgba(17, 4, 2, 0.6)",
+ "purpose": "Inverse shade at the bottom edge of wells, toggle thumbs, and slider thumbs. Paired with the inner highlight on machined parts."
+ },
+ {
+ "name": "accent",
+ "value": "5px 5px 0 0 #af2e1a",
+ "purpose": "Offset in the brand colour for primary buttons and brand-level emphasis."
+ }
+ ],
+ "motion": [
+ {
+ "name": "ease-default",
+ "value": "cubic-bezier(0.4, 0, 0.2, 1)",
+ "purpose": "Default easing for state transitions."
+ },
+ {
+ "name": "ease-out-expo",
+ "value": "cubic-bezier(0.22, 1, 0.36, 1)",
+ "purpose": "Entrance animations (typeIn)."
+ },
+ {
+ "name": "duration-fast",
+ "value": "150ms",
+ "purpose": "Hover, focus, and micro-feedback transitions. The press cycle runs at this speed."
+ },
+ {
+ "name": "duration-normal",
+ "value": "250ms",
+ "purpose": "Standard state transitions."
+ },
+ {
+ "name": "duration-slow",
+ "value": "400ms",
+ "purpose": "Entrance and reveal animations."
+ },
+ {
+ "name": "transition-fast",
+ "value": "150ms cubic-bezier(0.4, 0, 0.2, 1)",
+ "purpose": "Composed fast transition used by the press cycle on interactive elements."
+ },
+ {
+ "name": "transition-normal",
+ "value": "250ms cubic-bezier(0.4, 0, 0.2, 1)",
+ "purpose": "Composed standard transition."
+ }
+ ],
+ "breakpoints": [
+ {
+ "name": "sm",
+ "value": "480px",
+ "purpose": "Small mobile / narrow viewport."
+ },
+ {
+ "name": "md",
+ "value": "768px",
+ "purpose": "Tablet / compact layout; code blocks drop to 0.75rem below this."
+ }
+ ]
+ },
+ "components": [
+ {
+ "name": "Primary Button",
+ "kind": "button",
+ "refersTo": "btn-primary",
+ "description": "The brand identity button. Digital Rust background, thick border, offset shadow with inner-highlight bevel, physical press response. One per view.",
+ "html": "SAVE CHANGES ",
+ "css": ".ds-btn-primary { background: #af2e1a; color: #f7eae8; padding: 0.5rem 1.5rem; border: 2px solid #af2e1a; border-radius: 4px; font-family: \"Rajdhani\", \"Saira SemiCondensed\", \"Trebuchet MS\", sans-serif; font-weight: 600; font-size: 0.875rem; text-transform: uppercase; letter-spacing: 0.05em; cursor: pointer; box-shadow: 3px 3px 0 0 #46120a, inset 0 1px 0 rgba(255, 255, 255, 0.1); transition: transform 150ms cubic-bezier(0.4, 0, 0.2, 1), box-shadow 150ms cubic-bezier(0.4, 0, 0.2, 1), background-color 150ms cubic-bezier(0.4, 0, 0.2, 1), border-color 150ms cubic-bezier(0.4, 0, 0.2, 1); } .ds-btn-primary:hover { background: #b74230; border-color: #b74230; transform: translate(-2px, -2px); box-shadow: 4px 4px 0 0 #46120a, 0 0 10px rgba(175, 46, 26, 0.4), inset 0 1px 0 rgba(255, 255, 255, 0.1); } .ds-btn-primary:active { transform: translate(2px, 2px); box-shadow: 0 0 0 0 #46120a; } .ds-btn-primary:focus-visible { outline: 2px solid #d4a759; outline-offset: 2px; }"
+ },
+ {
+ "name": "Ghost Button",
+ "kind": "button",
+ "refersTo": "btn",
+ "description": "The default/secondary button. Transparent background, Dark Packet border, offset shadow with inner highlight; hover fills Core Meltdown with a Digital Rust edge.",
+ "html": "CANCEL ",
+ "css": ".ds-btn-ghost { background: transparent; color: #efd5d1; padding: 0.5rem 1.5rem; border: 2px solid #691b0f; border-radius: 4px; font-family: \"Rajdhani\", \"Saira SemiCondensed\", \"Trebuchet MS\", sans-serif; font-weight: 600; font-size: 0.875rem; text-transform: uppercase; letter-spacing: 0.05em; cursor: pointer; box-shadow: 2px 2px 0 0 #46120a, inset 0 1px 0 rgba(255, 255, 255, 0.1); transition: transform 150ms cubic-bezier(0.4, 0, 0.2, 1), box-shadow 150ms cubic-bezier(0.4, 0, 0.2, 1), background-color 150ms cubic-bezier(0.4, 0, 0.2, 1), border-color 150ms cubic-bezier(0.4, 0, 0.2, 1), color 150ms cubic-bezier(0.4, 0, 0.2, 1); } .ds-btn-ghost:hover { background: #340d07; border-color: #af2e1a; color: #f7eae8; transform: translate(-2px, -2px); box-shadow: 4px 4px 0 0 #46120a, inset 0 1px 0 rgba(255, 255, 255, 0.1); } .ds-btn-ghost:active { transform: translate(2px, 2px); box-shadow: 0 0 0 0 #46120a; } .ds-btn-ghost:focus-visible { outline: 2px solid #d4a759; outline-offset: 2px; }"
+ },
+ {
+ "name": "Card",
+ "kind": "card",
+ "refersTo": "spec-card",
+ "description": "Workhorse container with thick borders, offset shadow, and inner highlight. Presses in on active like a bolted rack module.",
+ "html": "PRIORITY STACK Error scopes override everything with Amber Alert
",
+ "css": ".ds-card { background: #340d07; border: 2px solid #691b0f; border-radius: 4px; padding: 1.5rem; box-shadow: 2px 2px 0 0 #46120a, inset 0 1px 0 rgba(255, 255, 255, 0.1); transition: transform 150ms cubic-bezier(0.4, 0, 0.2, 1), box-shadow 150ms cubic-bezier(0.4, 0, 0.2, 1); } .ds-card:hover { transform: translate(-2px, -2px); box-shadow: 4px 4px 0 0 #46120a; } .ds-card:active { transform: translate(2px, 2px); box-shadow: 0 0 0 0 #46120a; } .ds-card-title { color: #cf8175; margin-bottom: 0.5rem; font-size: 0.875rem; letter-spacing: 0.05em; text-transform: uppercase; font-family: \"Rajdhani\", \"Saira SemiCondensed\", \"Trebuchet MS\", sans-serif; font-weight: 700; } .ds-card-body { color: #f7eae8; font-size: 1rem; line-height: 1.6; font-family: \"Zilla Slab\", \"Bitter\", \"Source Serif 4\", Georgia, serif; }"
+ },
+ {
+ "name": "Badge - Success",
+ "kind": "chip",
+ "refersTo": "badge",
+ "description": "Semantic success indicator with Memory Leek tint. Static: no press cycle, no shadow.",
+ "html": "GIT ADDED ",
+ "css": ".ds-badge-success { border-radius: 4px; padding: 0.2rem 0.6rem; font-size: 0.75rem; text-transform: uppercase; letter-spacing: 0.08em; font-weight: 700; font-family: \"Rajdhani\", \"Saira SemiCondensed\", \"Trebuchet MS\", sans-serif; border: 1px solid rgba(143, 166, 103, 0.3); background: rgba(143, 166, 103, 0.15); color: #8fa667; }"
+ },
+ {
+ "name": "Badge - Info",
+ "kind": "chip",
+ "refersTo": "badge",
+ "description": "Semantic informational indicator with Dead Thread tint. Static: no press cycle, no shadow.",
+ "html": "MODIFIED ",
+ "css": ".ds-badge-info { border-radius: 4px; padding: 0.2rem 0.6rem; font-size: 0.75rem; text-transform: uppercase; letter-spacing: 0.08em; font-weight: 700; font-family: \"Rajdhani\", \"Saira SemiCondensed\", \"Trebuchet MS\", sans-serif; border: 1px solid rgba(111, 165, 160, 0.3); background: rgba(111, 165, 160, 0.15); color: #6fa5a0; }"
+ },
+ {
+ "name": "Badge - Warning",
+ "kind": "chip",
+ "refersTo": "badge",
+ "description": "Semantic warning indicator with Stack Overglow tint. Static: no press cycle, no shadow.",
+ "html": "DEPRECATED ",
+ "css": ".ds-badge-warning { border-radius: 4px; padding: 0.2rem 0.6rem; font-size: 0.75rem; text-transform: uppercase; letter-spacing: 0.08em; font-weight: 700; font-family: \"Rajdhani\", \"Saira SemiCondensed\", \"Trebuchet MS\", sans-serif; border: 1px solid rgba(212, 167, 89, 0.3); background: rgba(212, 167, 89, 0.15); color: #d4a759; }"
+ },
+ {
+ "name": "Badge - Error",
+ "kind": "chip",
+ "refersTo": "badge",
+ "description": "Semantic error indicator. Amber Alert Text on a 10% Amber Alert tint — the AA-compliant text variant, never the raw colour.",
+ "html": "GIT DELETED ",
+ "css": ".ds-badge-error { border-radius: 4px; padding: 0.2rem 0.6rem; font-size: 0.75rem; text-transform: uppercase; letter-spacing: 0.08em; font-weight: 700; font-family: \"Rajdhani\", \"Saira SemiCondensed\", \"Trebuchet MS\", sans-serif; border: 1px solid rgba(191, 87, 71, 0.25); background: rgba(191, 87, 71, 0.1); color: #cb6353; }"
+ },
+ {
+ "name": "Text Input (Well)",
+ "kind": "input",
+ "refersTo": null,
+ "description": "Recessed well: the darkest surface on the page, no offset shadow, no lift. Responds through border colour only (Bad Sector rest, Dark Packet hover, Digital Rust focus).",
+ "html": " ",
+ "css": ".ds-input { background: #110402; border: 2px solid #46120a; border-radius: 4px; padding: 0.5rem 0.75rem; color: #f7eae8; font-family: \"Zilla Slab\", \"Bitter\", \"Source Serif 4\", Georgia, serif; font-size: 1rem; transition: border-color 150ms cubic-bezier(0.4, 0, 0.2, 1), box-shadow 150ms cubic-bezier(0.4, 0, 0.2, 1); } .ds-input:hover:not(:focus) { border-color: #691b0f; } .ds-input:focus { outline: 2px solid #d4a759; outline-offset: 2px; border-color: #af2e1a; } .ds-input::placeholder { color: rgba(239, 213, 209, 0.5); font-style: italic; }"
+ },
+ {
+ "name": "Navigation Link",
+ "kind": "nav",
+ "refersTo": null,
+ "description": "Phantom Current with a 1px underline at 3px offset. Hover shifts to Fatal Error with a 2px underline; visited is Corrupted Cache.",
+ "html": "Read the specification ",
+ "css": ".ds-link { color: #e7c0ba; text-decoration: underline; text-decoration-thickness: 1px; text-underline-offset: 3px; font-family: \"Zilla Slab\", \"Bitter\", \"Source Serif 4\", Georgia, serif; transition: color 150ms cubic-bezier(0.4, 0, 0.2, 1), text-decoration-thickness 150ms cubic-bezier(0.4, 0, 0.2, 1); } .ds-link:hover { color: #cf8175; text-decoration-thickness: 2px; } .ds-link:visited { color: #dfaba3; } .ds-link:focus-visible { outline: 2px solid #d4a759; outline-offset: 2px; }"
+ },
+ {
+ "name": "Terminal",
+ "kind": "custom",
+ "refersTo": "terminal",
+ "description": "The brand's signature interactive metaphor. Fake terminal running spec validation commands, with a Stack Overglow block cursor.",
+ "html": "● ● ●
digitalrust@entropy:~$ theme audit --strict
Syntax Coverage ........ PASS
digitalrust@entropy:~$
",
+ "css": ".ds-terminal { background: #110402; border: 2px solid #691b0f; border-radius: 6px; padding: 1.5rem; position: relative; overflow: hidden; box-shadow: 3px 3px 0 0 #46120a, inset 0 1px 0 rgba(255, 255, 255, 0.1); } .ds-terminal-dots { position: absolute; top: 0; left: 0; right: 0; padding: 0.5rem 1rem; background: #340d07; color: #af2e1a; border-bottom: 1px solid #46120a; font-size: 0.75rem; letter-spacing: 0.5rem; } .ds-terminal-body { margin-top: 2rem; font-family: \"IBM Plex Mono\", \"Space Mono\", ui-monospace, \"Fira Code\", monospace; font-size: 0.875rem; line-height: 1.6; } .ds-terminal-prompt { color: #e7c0ba; } .ds-terminal-cmd { color: #f7eae8; } .ds-terminal-output { color: #efd5d1; margin-left: 2rem; opacity: 0.95; } .ds-terminal-pass { color: #8fa667; font-weight: 700; } .ds-terminal-cursor { display: inline-block; width: 0.6em; height: 1.2em; background: #d4a759; vertical-align: text-bottom; }"
+ }
+ ],
+ "narrative": {
+ "northStar": "The Corroded Mainframe",
+ "overview": "A server room where every surface has oxidized, but the machines still hum. The walls are rust; the screens still glow. Failure is the texture, not the state.\n\nDigital Rust is a dark-mode-only system built around a single rust-to-void gradient: warm copper tones that bleed from near-white to near-black through 19 named stops, each one a hardware failure metaphor. The accent colours (Memory Leek, Stack Overglow, Dead Thread, Blue Screen, Fractured Shell, Thermal Throttle) are named after system crashes and injected surgically, never as a rainbow. Surfaces carry structural noise and scanline overlays; flat, noiseless backgrounds are a design failure. Borders are thick and heavy (2-4px Dark Packet), shadows are offset solids with no blur, corners never exceed 6px radius. Every component feels like a physical panel in a failing server rack: brutalist, tactile, press-and-release.\n\nThe system explicitly rejects the cold blue-purple dark theme family (Dracula, Nord, Tokyo Night, One Dark) and any sterile \"pro\" aesthetic with gray surfaces and blue accents. Pure black (`#000`) is forbidden in shadows and backgrounds, replaced by the warm near-blacks of the rust ramp. The hostility is in the atmosphere, not the readability: Ghost Pixel on Event Horizon hits 17.17:1 contrast ratio.",
+ "keyCharacteristics": [
+ "Single-hue warm ramp (copper/rust/bone) as the structural spine, not a multi-hue palette",
+ "Offset solid shadows (no blur) that serve both interaction feedback and the corroded machine aesthetic",
+ "Structural noise and scanline overlays on every surface; silence them only for `prefers-reduced-motion`",
+ "Borders as heavy structural elements (2-4px Dark Packet), never decorative hairlines",
+ "Accent colours named after system failures, used surgically for syntax and diagnostics",
+ "Radius ceiling of 6px; nothing rounds past \"gently chamfered\""
+ ],
+ "rules": [
+ {
+ "name": "The One Hue Rule",
+ "body": "The 19-stop main ramp occupies a single warm hue family. Accents are admitted in six named failure families, but the surface itself never leaves the rust-to-void gradient. If a background or border colour is not one of the 19 ramp stops or one of the 6 accent families, it does not belong in the system.",
+ "section": "colors"
+ },
+ {
+ "name": "The Black Is Forbidden Rule",
+ "body": "`#000000` is prohibited in shadows, borders, and backgrounds. The nearest near-black is Event Horizon (`#110402`). Shadows, overlays, and vignettes use warm-tinted transparencies of the brand colour: `rgba(175, 46, 26, ...)`. Pure black reads as a different material; this system has no cold materials.",
+ "section": "colors"
+ },
+ {
+ "name": "The Flat Surface Failure Rule",
+ "body": "A flat, noiseless dark surface with no texture overlay is a design defect. Every ambient surface carries the SVG noise texture (opacity 0.02) and scanline overlay. These are structural, not decorative. The sole exemptions are interactive text surfaces (inputs, text areas, editable code regions), which stay clean for legibility, and `prefers-reduced-motion: reduce`, which silences all overlays.",
+ "section": "colors"
+ },
+ {
+ "name": "The One Heading Colour Rule",
+ "body": "Fatal Error (`#cf8175`) is the only colour used for headings of any level. Not white, not Ghost Pixel, not the accent colours. Every heading speaks in the same warm-copper voice. If a heading is not Fatal Error, it is not a heading.",
+ "section": "typography"
+ },
+ {
+ "name": "The All-Caps Ceiling Rule",
+ "body": "Rajdhani headings and labels are set in all-caps with wide tracking. This is an intentional, restricted choice for short strings (titles, labels, badges). Body copy is never all-caps. A sentence in all-caps at body size is unreadable and prohibited.",
+ "section": "typography"
+ },
+ {
+ "name": "The No Blur Rule",
+ "body": "`box-shadow` blur radius is zero for all structural shadows. The only blur in the system is the glow shadow (which simulates light, not material depth). If a shadow has a non-zero blur and is not a glow, it does not belong.",
+ "section": "elevation"
+ },
+ {
+ "name": "The Press-And-Release Rule",
+ "body": "Interactive elements with offset shadows must implement the full hover-then-press cycle: rest has offset, hover grows offset by 2px on both axes and lifts the element `translate(-2px, -2px)`, active collapses offset to zero and drives the element `translate(2px, 2px)` into the surface. The state transition must use `--dr-transition-fast` (150ms).",
+ "section": "elevation"
+ },
+ {
+ "name": "The Recessed Well Rule",
+ "body": "Inputs, text areas, and editable code regions sit *below* the panel, not above it: Event Horizon background, 2px Bad Sector border, no offset shadow, no lift on hover. Wells respond through border colour (Bad Sector rest, Dark Packet hover, Digital Rust focus). They are exempt from noise and scanline texture; legibility outranks atmosphere inside a text field.",
+ "section": "elevation"
+ }
+ ],
+ "dos": [
+ "Do use the 19-stop rust ramp as the only neutral scale. There is no separate gray ramp; the warm stops from Ghost Pixel to Event Horizon are the neutrals.",
+ "Do enforce WCAG 2.1 AA contrast on all text. Ghost Pixel on Event Horizon (17.17:1) is the baseline; Dim Thermal Throttle on Event Horizon (4.84:1) is the darkest acceptable body text.",
+ "Do use noise and scanline overlays on every surface. They are structural, not decorative. A flat noiseless dark background is a defect.",
+ "Do use offset solid shadows (no blur) in Bad Sector for material depth. Grow offset on hover, collapse on active to simulate a physical press.",
+ "Do use thick borders (2-4px Dark Particle) as structural elements. Borders are walls, not decoration.",
+ "Do keep radius at 2-6px. Nothing rounds past \"gently chamfered\". A 16px+ radius on a card or panel is a different design system.",
+ "Do name accent colours after system failures (Memory Leek, Stack Overglow, Dead Thread, Blue Screen, Fractured Shell, Thermal Throttle). New accents get parallel naming.",
+ "Do use wavy underlines for diagnostics (Amber Alert wavy for errors, Stack Overglow wavy for warnings) and solid underlines for links. The underline style carries semantic information.",
+ "Do implement the full hover-then-press cycle on all interactive elements: rest offset, hover offset grows, active offset collapses.",
+ "Do suppress noise, scanlines, and all animations for `prefers-reduced-motion: reduce`. The content must be fully visible without the animation.",
+ "Do keep surface-background tints for badges/diagnostics at 10-15% opacity of the named colour. This is enough to carry the semantic tint without competing with the ramp."
+ ],
+ "donts": [
+ "Don't use pure black (`#000000`) in shadows, borders, or backgrounds. The system has no cold materials. Use Event Horizon (`#110402`) or warm-tinted transparencies of the brand colour.",
+ "Don't use blurred drop shadows. The only blur in the system is the glow effect (`0 0 Npx rgba(175, 46, 26, 0.4)`), which simulates radiated heat, not material depth.",
+ "Don't use Dracula, Nord, Tokyo Night, One Dark, or any cold/blue/purple dark theme aesthetic. Those are the explicit anti-references. Cool tones are the opposite of the corroded mainframe.",
+ "Don't use flat, noiseless dark surfaces without the SVG noise and scanline overlays. Remove only for `prefers-reduced-motion`.",
+ "Don't use colours outside the 19 ramp stops and 6 accent families. If a colour is not in the palette, it does not belong. Extend the palette deliberately, not by accident.",
+ "Don't use Fatal Error (`#cf8175`) for body text or link text. It is reserved for headings and keyword tokens. Body text uses Ghost Pixel or Phosphor Smoke; links use Phantom Current.",
+ "Don't set body copy in all-caps. Rajdhani all-caps with wide tracking is for headings and labels only (4 words or fewer for labels).",
+ "Don't use `border-left` or `border-right` greater than 1px as a coloured accent stripe on cards, list items, or callouts. The section-title left border is a rare deliberate exception.",
+ "Don't use border-radius above 6px on any card, panel, or container. Full-pill radius is acceptable for small inline elements (badges, tags) only.",
+ "Don't place a 1px border and a wide soft shadow on the same element. Pick one: a solid thick border at the brand colour, or a defined offset shadow at no more than 8px offset. Never both as decoration."
+ ]
+ }
}
diff --git a/.impeccable/live/config.json b/.impeccable/live/config.json
index bd9a444..4419c78 100644
--- a/.impeccable/live/config.json
+++ b/.impeccable/live/config.json
@@ -1,6 +1,6 @@
{
- "files": ["*.html"],
- "insertBefore": "
-
-
-
-
-
-
- digitalrust@entropy:~$
- cat DIGITAL_RUST_SPEC.md | verify --strict
-
-
- fingerprint: 0xDR-1.2.2
- updated: 2025-11-29
- priority-order: errors > warnings > semantic > textmate
-
-
-
- digitalrust@entropy:~$
- theme audit --sections syntax ui terminal accessibility
-
-
- Syntax Coverage ........ PASS
- UI Surfaces ............ PASS
- ANSI Map ............... PASS
- Non-color cues ......... PASS
-
-
-
- digitalrust@entropy:~$
- tail -n4 /var/log/digital-rust
-
-
- [OK] WCAG contrast ≥ 4.5 :1 enforced
- [OK] Markdown + JSON + Diff snapshots loaded
- [OK] Terminal ANSI pairs bound to palette
- [!] Remember: errors outrank keywords
-
-
-
- digitalrust@entropy:~$
-
-
-
-
-
-
- Spec Guarantees
-
-
- Priority Stack
-
- Error scopes override everything with Amber Alert
- Warnings inherit Stack Overglow with wavy underline
- Semantic tokens fall back to TextMate colors when absent
-
-
-
- Language Coverage
-
- TypeScript · Python · Rust · Markdown · JSON/TOML
- HTML/CSS · SQL · Shell · Diff/SCM views
- Template + decorator scopes, regex, interpolation
-
-
-
- Editor & UI
-
- Tabs, gutter, minimap, status bar, panels
- Diagnostics + git markers reuse ANSI cues
- Focus rings + disabled states meet contrast rules
-
-
-
- Accessibility
-
- Solid vs. wavy underline separates links/errors
- Color-blind safe via redundant icons + patterns
- Documented contrast pairs for auditing
-
-
-
-
-
-
-
-
- CLOSE
- PREV
- NEXT
-
-
-
-
- Token Classification Map
-
- Each card renders the canonical color, name, and example scopes. Sigils inherit their parent token color
- per
- spec.
-
-
-
-
- Keywords & Storage
- Fatal Error · #cf8175
-
- Control flow, modifiers, `try/catch`, storage types.
-
- class
- return
- await
-
-
-
-
- Functions & Macros
- Stack Overglow ·
- #d4a759
-
- User functions, built macros, shell commands.
-
- renderTheme()
- println!
- COUNT
-
-
-
-
- Classes & Types
- Dead Thread · #6fa5a0
-
- Types, interfaces, trait names, lifetimes.
-
- SystemState
- bool
- 'static
-
-
-
-
- Strings & Regex
- Memory Leek · #8fa667
-
- Literal text, heredocs, regex bodies & groups.
-
- "corrupted"
- /kernel.+panic/
-
-
-
-
- Numbers & Units
- Thermal Throttle ·
- #d78556
-
- Integers, floats, hex, CSS units, rgb values.
-
- 0xDEADBEEF
- 42
- 85.5°C
-
-
-
-
- Constants & Specials
- Bright Stack Overglow
- ·
- #d3ae6e
-
- Booleans, null-like, enum values, magic names.
-
- true
- None
- Status::OK
-
-
-
-
- Comments & Docs
- Dim Thermal ·
- #ac6d4a
-
- Inline comments, docstrings, shebangs (italic).
-
-
-
-
-
-
-
- Decorators & Attributes
- Dead Thread · #6fa5a0
-
- Python decorators, Rust attributes, JSX props.
-
- @dataclass
- #[cfg(test)]
-
-
-
-
- Support & Built-ins
- Dim Stack Overglow ·
- #a07e43
-
- Standard library functions, DOM globals, HTML attributes.
-
- console
- print
- class
-
-
-
-
- Variables & Identifiers
- Ghost Pixel · #f7eae8
-
- Parameters, locals, properties, fallback text.
-
- entropyLevel
- error
- $PATH
-
-
-
-
- Operators & Punctuation
- Copper Trace · #d7968c
-
- Brackets, sigils, punctuation, interpolation braces.
-
- ===
- { }
- ::
-
-
-
-
- Diagnostics & Errors
- Amber Alert · #bf5747
-
- Wavy underline + icon ensures non-color cues.
-
- panic()
- deprecated()
-
-
-
-
-
-
- Language Snapshots
- Nine grammars render simultaneously, satisfying the spec requirement for multi-language verification.
-
-
-
-
-export class KernelProbe {
- readonly threshold : number = 85.5
- async ping ( bus : SystemBus ) : Promise < void > {
- const reading = await bus . read ( "temp" )
- if ( reading > this . threshold ) {
- throw new Error ( `🔥 kernel panic: ${ reading } °C` )
- }
- }
-}
-
-
-
-
-
-
-
-@dataclass
-class Snapshot :
- name : str
- ok : bool = True
-
- def emit ( self , metric : float ) -> None :
- print ( f"{self.name}: {metric:.2f}" )
-
-RUN = Snapshot ( "ansi-map" , True )
-if __name__ == "__main__" :
- RUN . emit ( 4.50 )
-
-
-
-
-
-#[derive(Debug, Clone)]
-pub struct Telemetry<'a> {
- buffer : &'a [u8] ,
- heat : f32 ,
-}
-
-impl Telemetry <'_> {
- pub fn check_integrity (& self ) -> Result <bool , Error > {
- if self . heat > 95.0 {
- return Err ( Error ::new ( ErrorKind ::Other , "KERNEL PANIC" ))
- }
- Ok ( true )
- }
-}
-
-
-
-
-
## Digital Rust Guarantees
-- Tokens inherit `Ghost Pixel` when undefined
-- Links stay underlined [even offline] (spec.md)
-> Errors outrank keywords every time.
-
-
-
-
-
{
- "editor" : {
- "background" : "#110402" ,
- "cursor" : "#D4A759" ,
- "useRainbowBrackets" : true
- } ,
- "diagnostics" : [ "error:wavy" , "warning:stack" ]
-}
-
-
-
-
-
< section class = "panel" >
- < h3 > @keyframes glitch</ h3 >
-</ section >
-
-.panel {
- border : 1px solid var(--dark-packet) ;
- color : var(--ghost-pixel) ;
-}
-
-
-
-
-
@@ -12,6 +12,7 @@
-- panic!("kernel meltdown")
-+ log::warn!("stack overglow engaged")
- return Ok(())
-
-
-
-
-
rust@host $ digitalrust --apply --profile = "dark"
-rust@host $ export THEME = "digital-rust"
-rust@host $ printf "%s\n" $THEME
-
-
-
-
-
SELECT
- COUNT ( * ) AS total_panics
-FROM errors
-WHERE palette = 'digital-rust'
- AND severity IN ( 'fatal' , 'critical' ) ;
-
-
-
-
-
-
- Warm rust-to-void gradient used across editor, UI, and docs.
-
-
- Ghost Pixel
- #F7EAE8
-
-
- Phosphor Smoke
- #EFD5D1
-
-
- Phantom Current
- #E7C0BA
-
-
- Corrupted Cache
- #DFABA3
-
-
- Copper Trace
- #D7968C
-
-
- Fatal Error
- #CF8175
-
-
- Rouge Signal
- #C76C5E
-
-
- Amber Alert
- #BF5747
-
-
- Firewall Breach
- #B74230
-
-
- Digital Rust
- #AF2E1A
-
-
- Kernel Panic
- #9D2917
-
-
- Data Rot
- #8C2414
-
-
- Bricked Board
- #7A2012
-
-
- Dark Packet
- #691B0F
-
-
- Daemon Blood
- #57170D
-
-
- Bad Sector
- #46120A
-
-
- Core Meltdown
- #340D07
-
-
- Null Pointer
- #230905
-
-
- Event Horizon
- #110402
-
-
-
-
-
-
-
-
- Black
- Event Horizon
- #110402
-
-
- Red
- Digital Rust
- #AF2E1A
-
-
- Green
- Memory Leek
- #8FA667
-
-
- Yellow
- Stack Overglow
- #D4A759
-
-
- Blue
- Blue Screen
- #8791B0
-
-
- Magenta
- Fractured Shell
- #BA5A7D
-
-
- Cyan
- Dead Thread
- #6FA5A0
-
-
- White
- Phosphor Smoke
- #EFD5D1
-
-
- Bright Black
- Bad Sector
- #46120A
-
-
- Bright Red
- Fatal Error
- #CF8175
-
-
- Bright Green
- Bright Memory Leek
- #94A577
-
-
- Bright Yellow
- Bright Stack Overglow
- #D3AE6E
-
-
- Bright Blue
- Bright Blue Screen
- #999EAF
-
-
- Bright Magenta
- Bright Fractured Shell
- #BA6B88
-
-
- Bright Cyan
- Bright Dead Thread
- #7FA5A1
-
-
- Bright White
- Ghost Pixel
- #F7EAE8
-
-
-
-
-
- Editor & UI Surfaces
-
-
-
-
-
- 42
- 43
- 44
- 45
-
-
-
#[cfg(test)]
-
fn assert_entropy () {
-
·· assert_eq ( true , true );
-
}
-
-
-
- Rust Analyzer
- CPU 42%
- Git✓
-
-
-
-
-
Diff Indicators
-
- Git Added
- Git Modified
- Git Deleted
-
-
-
+ Memory Leek · bg 15%
-
~ Dead Thread · bg 10%
-
- Amber Alert · bg 15%
-
-
-
-
-
Diagnostics
-
- ✗ Kernel panic detected: wavy Amber Alert underline
- ⚠ Deprecated API: Stack Overglow underline
- ℹ Hint bubbles use Dead Thread
-
-
- Inlay hint
- parameter: rust
-
-
-
-
-
-
- UI Components
-
- The Digital Rust UI Specification: chunky hardware panel switches, recessed input wells,
- and the press-and-release cycle. Rest carries an offset shadow and inner-highlight bevel;
- hover lifts toward the light; active drives the element into the rack.
- Full component gallery →
-
-
-
-
Buttons
-
- Save Changes
- Discard
-
-
- Apply Patch
- Force Push
- Kill Process
-
-
- Offline
-
-
rest: offset-sm + bevel · hover: lift(-2px,-2px) + offset grows · active: press(2px,2px) + collapse
-
-
-
-
Inputs — Recessed Wells
-
- Hostname
-
-
-
-
Port
-
-
✗ Connection refused on port 22
-
-
Event Horizon well · no offset shadow · hover: Dark Packet border · focus: Digital Rust border + Stack Overglow ring
-
-
-
-
Checkbox & Toggle
-
- Enable telemetry scrubbing
-
-
- Mount /dev/rust
-
-
- Thermal limiter
-
-
- Overclock bus
-
-
checkbox runs the full press cycle · toggle thumb slides on a railed track
-
-
-
-
Tabs
-
-
- main.rs
- spec.toml
- DRIFT.log
-
-
active tab: Null Pointer bg + Digital Rust power rail · hover: Bad Sector fill
-
-
- digitalrust@entropy
- CPU 42%
- Git✓
-
-
-
-
-
-
- Accessibility & Testing
-
-
-
Contrast Benchmarks
-
-
-
- Pair
- Ratio
- Status
-
-
-
-
- Ghost Pixel on Event Horizon
- 17.17:1
- Pass
-
-
- Dim Thermal Throttle on Event Horizon
- 4.84:1
- Pass
-
-
- Bad Sector on Core Meltdown
- Decorative only
- ⚠
-
-
-
-
-
-
Non-Color Cues
-
- Links Solid underline + Phantom Current
- Errors Amber Alert + wavy underline + icon
- Warnings Stack Overglow wavy underline
- Spelling Amber Alert dotted underline variant
-
-
-
-
Test Checklist
-
- ☑ Five programming languages rendered
- ☑ Markdown, JSON, diff, terminal verified
- ☑ ANSI 16 + UI chrome demonstrated
- ☑ Motion honors user prefers-reduced-motion
-
-
-
-
-
-
-
-
-",
- "commentSyntax": "html",
- "cspChecked": true
+ "files": ["*.html"],
+ "insertBefore": "",
+ "commentSyntax": "html",
+ "cspChecked": true
}
diff --git a/.prettierignore b/.prettierignore
index ab8a9a5..3dfe78c 100644
--- a/.prettierignore
+++ b/.prettierignore
@@ -7,4 +7,12 @@ bun.lockb
# Miscellaneous
/static/
-src/lib/generated/
+/src/lib/generated/
+
+# Canonical hand-maintained documents; Prettier does not touch them
+/Digital Rust Syntax Highlighting Specification.md
+/Digital Rust UI Specification.md
+/DESIGN.md
+/PRODUCT.md
+/AGENTS.md
+/README.md
diff --git a/AGENTS.md b/AGENTS.md
index 509ad9c..4bda027 100644
--- a/AGENTS.md
+++ b/AGENTS.md
@@ -1,26 +1,35 @@
# AGENTS.md
-Digital Rust is a colour scheme, not an app. The deliverables are the palette itself: static HTML/CSS showcase pages at the repo root, terminal/editor port files in `ports/`, and a Svelte playground in `playground/` for previewing syntax highlighting. There is no test suite and no CI; verification is visual plus the commands below.
+Digital Rust is a colour scheme, not an app. The deliverables are the palette itself: this SvelteKit static site (prerendered to `build/`), terminal/editor port files in `static/ports/`, and the two canonical spec documents at the repo root. There is no test suite and no CI; verification is visual plus the commands below.
## Commands
-- `cd playground && pnpm install` — package manager is **pnpm** (switched from npm in 3a364ab; `package-lock.json` is gitignored, never commit one).
-- `pnpm dev` / `pnpm build` / `pnpm check` (run inside `playground/`) — `check` is `svelte-check` + `tsc`; use it as the typecheck/lint step.
-- Root site (`index.html`, `spec.html`) is plain static files. Serve with any static server (e.g. `python -m http.server`) — no build step exists.
+- `pnpm install` — package manager is **pnpm**; never commit a `package-lock.json`.
+- `pnpm dev` / `pnpm build` / `pnpm preview` — output is fully static in `build/`.
+- `pnpm check` — svelte-check + tsc. `pnpm lint` — prettier + eslint. Run both before committing.
## Palette changes (the critical workflow)
-The palette is duplicated by hand across ~8 files. When adding or changing a colour/token, update **all** of these or they silently drift apart:
+`src/lib/palette.ts` is the site's single source of truth for hex values. It generates `src/lib/generated/tokens.css` (a vite plugin regenerates it on dev/build; the file is gitignored — never edit it directly) and feeds the Shiki theme in `src/lib/theme/digital-rust-theme.ts` and every palette-driven component.
-- `Digital Rust Syntax Highlighting Specification.md` — canonical syntax/palette spec (hex tables, scope→colour mappings)
-- `Digital Rust UI Specification.md` — canonical UI spec (surfaces, elevation, interaction physics, component definitions); demonstrated live on `ui.html`
-- `tokens.css` — CSS custom properties; semantic tokens (`--dr-*`) reference named ramp vars, so edit the named var, not the alias
-- `DESIGN.md` — YAML front matter holds the design-token copy of the palette
-- `playground/src/lib/digital-rust-theme.ts` — Shiki/TextMate theme object
-- `ports/` — each port file (Konsole, KDE, Kate, fish, Ptyxis, `digitalrustpi/digital-rust.json`) hardcodes hex values in its own format
-- `.impeccable/design.json` — generated design-system metadata with tonal ramps
+Outside the site, hexes are still duplicated by hand. When you add or change a colour/token, also update:
-Hex values are the single source of truth across all formats; names (Ghost Pixel, Event Horizon, ...) are stable identifiers — never rename one without updating the spec, site copy, and all ports.
+- `Digital Rust Syntax Highlighting Specification.md` — canonical syntax/palette spec
+- `Digital Rust UI Specification.md` — canonical UI spec
+- `DESIGN.md` — YAML front matter holds the design-token copy
+- `static/ports/` — each port file hardcodes hexes in its own format
+- `.impeccable/design.json` — generated design-system metadata (local tooling; see below)
+
+Names (Ghost Pixel, Event Horizon, ...) are stable identifiers — never rename one without updating the spec, site copy, and all ports.
+
+## Spec pages render from markdown
+
+`/spec` renders `Digital Rust Syntax Highlighting Specification.md` at build time (`src/lib/spec/render-spec.ts`). The markdown is canonical; edit the .md, not the page. Gotchas:
+
+- The build throws if the marker sections vanish: the spec must keep an H1 followed by a lede paragraph and an `## Overview` section, because the meta bar and live-demo component are spliced in after them.
+- Palette tables are recognised by a `Hex Code` first header cell and get card grids generated above them. Keep that column first.
+- Both spec .md files are served as downloads via prerendered `+server.ts` routes under `/spec/`.
+- The two spec .md files, DESIGN.md, PRODUCT.md, AGENTS.md and README.md are in `.prettierignore` on purpose. `pnpm format` must not reflow them.
## Hard constraints (from DESIGN.md/PRODUCT.md — enforced by review, not tooling)
@@ -33,8 +42,9 @@ Hex values are the single source of truth across all formats; names (Ghost Pixel
## Gotchas
-- `pnpm-workspace.yaml` in `playground/` only sets `minimumReleaseAgeExclude` for an exact pinned svelte version — if you bump svelte, update that entry too or pnpm may refuse to install it.
-- Playground `vite.config.ts` uses `base: './'` deliberately — the build is served from a subpath; don't change to `/`.
-- `.impeccable/` and `.crush/` are local tooling state, not project source — don't edit or commit changes there.
-- The repo's public mirror is Tangled (`tangled.org/katsuricata.com/DigitalRust`); `index.html` links to ports by relative path, so new ports need both a file in `ports/` and a link in `index.html` (and the downloads section of `spec.html` if applicable).
-- EditorConfig: tabs, size 4 — match it in CSS/HTML/MD even where existing files mix styles.
+- Kit 3 uses `#lib/*` (package.json imports), not `$lib`. Import TS modules with a `.js` suffix: `import { color } from '#lib/palette.js'`.
+- `trailingSlash = 'always'` gives every route a directory URL (`/spec/`, `/ui/`, `/playground/`) that works on any static server. `static/spec.html` and `static/ui.html` are meta-refresh stubs for old bookmarks — keep them.
+- Component styles in `.svelte` files are scoped; styles for `{@html}` content (the spec body) must live in `src/lib/styles/spec.css`, which loads only on `/spec`.
+- `.impeccable/` and `.crush/` are local tooling state — don't edit or commit changes there.
+- The repo's public mirror is Tangled (`tangled.org/katsuricata.com/DigitalRust`). New ports need a file in `static/ports/` and a link in the port list in `src/routes/+page.svelte`.
+- EditorConfig: tabs, size 4. Prettier enforces it for everything outside `.prettierignore`.
diff --git a/index.html b/index.html
deleted file mode 100644
index 83a9215..0000000
--- a/index.html
+++ /dev/null
@@ -1,878 +0,0 @@
-
-
-
-