Typography
The quick brown fox jumps
The quick brown fox jumps
The quick brown fox jumps
The quick brown fox jumps
A portable design language for agents: download the markdown first, then inspect the preview, tokens, and rules as needed.
Portable DESIGN.md source of truth for most agents and apps.
Alternate the spacious dial stage with tight mono readouts: 4-8px inside label clusters, 48px+ between modules, 64-96px fields of darkness as silence so the system feels deliberate, not filled.
Radial-led: a centred dial stage with meters/reel/log radiating around it; contained content capped at 1320px. Uses minmax(0,1fr) columns and min-width:0 so grids never blow out.
64-96px of darkness around the dial stage, 24-32px panel padding, 4-8px proximity inside mono label and checksum rows.
Quiet overall density with compression only in mono readouts, track meters, and the pass log; the dial stage stays spacious.
1440 desktop leads with the dial; 768 tablet stacks dial then meters then reel/log; 390 mobile is a single column with the fragment reel in horizontal scroll. Only the full-bleed hero spans 100vw; ultrawide caps and centres.
salvage
Recovered-fragment scans in the salvage technique — halftone radial sector dots, scan-line interlace, sliced data-loss scars, dropped white sectors, archival-blue tint — applied to disc surfaces and spindle hubs on a dark vault ground, composed radially.
One full-bleed radial hero of the disc-as-instrument; fragment-reel thumbnails are small, track-ordered, and materially damaged. Never heroic portraits, never decorative glitch.
# Spindle
## Philosophy
Spindle is a dark optical-archive recovery language for consoles that stabilize damaged discs, memory images, and born-digital records. It reads the disc radially: the platter itself is the instrument, recovery sweeps outward from the hub as a warm read-head arc, and unrecovered tracks wait in archival blue until a re-read clears them. Damage is always material — a ring, an offset, a checksum — never an effect.
### Values
- The disc is the instrument: a single concentric track-ring dial is the signature, and every other surface is that dial seen another way — flattened into meters, laid end to end as a checksum band, sampled as a fragment reel.
- Warmth means read: read-head amber marks recovered tracks; archival blue means cold and not-yet; voids mean dropped. State is colour-coded but always labelled in mono.
- Darkness as silence: a charcoal vault ground makes the few warm marks read like a read-head glowing on a platter under raking light.
- Evidence before expression: every mark clarifies a ring, offset, checksum, scan depth, or lock state; damage is material, never decorative.
- Static trust: the settled, fully-recovered state reads correctly in a still screenshot and with no JavaScript; motion is limited to a single dial draw and procedural reveals.
- Human traces at the edge: cropped hands, reflections, and disc surfaces appear as recovered fragments, never heroic portraits.
### Anti-Values
- No recoloured rectangular contact-sheet console — a palette or ground swap of the panel-grid forensic look is a failure.
- No pure-white SaaS ground; the only near-black voids are dropped sectors, the only ground is the charcoal vault.
- No single-edge accent on a card, no nav trapped in a floating pill bar, no nested cards.
- No blue background wash and no amber wallpaper; at most three accents used like highlighters.
- No green code rain, glowing cyberpunk HUD rings, glossy candy gradients, or ornamental corruption without provenance.
## Tokens
### Colors
| Name | Value |
|------|-------|
| bg | `#0E1114` |
| surface | `#171B20` |
| surface_2 | `#1F252B` |
| sunk | `#0A0C0E` |
| text | `#ECF0F2` |
| muted | `#8A969E` |
| faint | `#535D64` |
| border | `#2A3138` |
| accent | `#E8A23D` |
| accent_deep | `#C97F1E` |
| accent_wash | `rgba(232,162,61,0.16)` |
| on_accent | `#140E04` |
| cold | `#3E8FC4` |
| cold_wash | `rgba(62,143,196,0.14)` |
| success | `#5FB08A` |
| warning | `#E8A23D` |
| error | `#D8604B` |
| info | `#3E8FC4` |
### Typography
- **Base Size**: 17px
- **Body Font**: Spline Sans
- **Heading Font**: Space Grotesk
- **Mono Font**: Space Mono
- **Heading Weight**: 600
- **Heading Transform**: none
- **Letter Spacing**: -0.03em
- **Google Fonts Url**: https://fonts.googleapis.com/css2?family=Space+Grotesk:wght@400;500;600;700&family=Space+Mono:ital,wght@0,400;0,700;1,400&family=Spline+Sans:wght@400;500;600&display=swap
### Radii
- **None**: 0px
- **Md**: 16px
- **Lg**: 24px
- **Full**: 9999px
### Shadows
- **Sm**: 0 1px 0 rgba(0,0,0,0.4)
- **Md**: 0 18px 50px rgba(0,0,0,0.45)
- **Lg**: 0 24px 60px rgba(0,0,0,0.55)
### Spacing
- **Base**: 8px
- **Scale**: [4,8,12,16,24,32,48,64,96]
### Surfaces
- **Ground**: Deep charcoal vault (#0E1114); pure white never used as ground, only near-black voids as dropped sectors.
- **Card Style**: Flat matte bench panels (#171B20), radius 16px, no border. Active panels carry a full inset amber ring (never a single edge) and a faint top amber wash.
- **Bg Pattern**: Faint concentric optical-sector ghost: arcs and radial ticks at 3-5% opacity behind the work area, cropped by the viewport.
- **Treatment**: Matte on a dark vault, no gloss, no glass, no gradient washes; the dial and its reflections carry the optical-sector geometry.
### Borders
- **Default Width**: 0px
- **Accent Width**: 1px
- **Style**: hairline + inset ring
- **Character**: Structure comes from hairline #2A3138 rules and full inset amber rings on active panes — never boxed borders, never a single accent edge.
### Motion
- **Duration**: 180ms
- **Easing**: cubic-bezier(.2,.0,.1,1)
- **Philosophy**: Procedural and nearly absent: the dial arc draws once on load, reveals rise on scroll, locks step between states. The settled state is the default and visible with no JavaScript; respects prefers-reduced-motion.
## Rules
### Composition
- Open on the radial track-ring dial as the primary instrument; let meters, fragment reel, and pass log radiate from it rather than sitting as equal cards.
- Treat every other surface as the disc seen another way — meters are the rings flattened, the checksum band is the rings end to end, the reel is the rings sampled.
- Allow one major field of darkness per screen as silence, with only mono coordinate marks or a single caption.
- Keep fragments in a track-ordered reel with material damage — sliced scars, dropped blocks, ring/offset IDs — never lifestyle imagery.
- Mark active recovery with read-head amber and cold/unrecovered with archival blue; never invert these meanings.
### Hierarchy
- Display hierarchy comes from wide Space Grotesk titles set large with -0.03em tracking and tight leading.
- Operational text uses Space Mono in uppercase micro-labels: ring/offset IDs, checksums, timestamps, depths, lock states.
- Body explanations use Spline Sans at 17px.
- Read-head amber marks recovered and active; archival blue marks cold; rust and green are small exception/lock indicators only.
### Density
Alternate the spacious dial stage with tight mono readouts: 4-8px inside label clusters, 48px+ between modules, 64-96px fields of darkness as silence so the system feels deliberate, not filled.
### Signature
- The track-ring dial: concentric stroke-dasharray arcs encoding per-track state — amber recovered, blue cold, gap void — with a thin read-head marker line at the current angle.
- Track meters: the dial's rings flattened into linear 9999px bars, amber fill (gradient) and cold blue at reduced opacity.
- Checksum band: the rings laid end to end as a single 9999px strip — warm where clean, blue where cold, void-black where dropped.
- Fragment reel: track-ordered square fragments built from halftone radial dots, scan-line interlace, sliced black scars, dropped blocks, and mono IDs.
- Active surfaces marked by a full inset amber ring, never a single accent edge; the nav sits open, never in a pill.
## Layout
### Grid
Radial-led: a centred dial stage with meters/reel/log radiating around it; contained content capped at 1320px. Uses minmax(0,1fr) columns and min-width:0 so grids never blow out.
### Whitespace
64-96px of darkness around the dial stage, 24-32px panel padding, 4-8px proximity inside mono label and checksum rows.
### Density
Quiet overall density with compression only in mono readouts, track meters, and the pass log; the dial stage stays spacious.
### Responsive
1440 desktop leads with the dial; 768 tablet stacks dial then meters then reel/log; 390 mobile is a single column with the fragment reel in horizontal scroll. Only the full-bleed hero spans 100vw; ultrawide caps and centres.
### Breakpoints
- **Mobile**: 390px
- **Tablet**: 768px
- **Desktop**: 1440px
- **Ultrawide**: 2560px
## Guidance
### Do
- Lead with the radial dial; make it the one instrument the rest of the system reuses.
- Keep warmth for recovered and blue for cold; label every state in mono, never colour alone.
- Make damage material — ring, offset, checksum, angle — and use darkness as silence.
- Style every form control fully on the dark ground; focus rings in amber.
- Keep at most three accents, used like highlighters, with radii only from {0,16,24,9999}.
### Don't
- Don't recolour a rectangular contact-sheet console and call it new.
- Don't put a single accent edge on a card or trap the nav in a pill.
- Don't let blue become a background wash or amber become wallpaper.
- Don't show a glitch without provenance, or use gloss, glass, or candy gradients.
- Don't default to white anywhere; pure white is never the ground.
### Accessibility
Maintain AA contrast with scan-white text on the charcoal vault; pair every state colour with a mono text label and a dot; keep micro-labels at 11px or larger; preserve keyboard focus outlines (amber halo); provide reduced-motion behaviour for the dial draw and reveals.
## Imagery Direction
### Pairs With
salvage
### Summary
Recovered-fragment scans in the salvage technique — halftone radial sector dots, scan-line interlace, sliced data-loss scars, dropped white sectors, archival-blue tint — applied to disc surfaces and spindle hubs on a dark vault ground, composed radially.
### Subjects
- damaged optical disc on a spindle
- platter surface under a raking read-head
- concentric track geometry
- cropped hand or reflection at the disc edge
- dropped-sector voids
### Usage
One full-bleed radial hero of the disc-as-instrument; fragment-reel thumbnails are small, track-ordered, and materially damaged. Never heroic portraits, never decorative glitch.
---
version: "alpha"
name: "Spindle"
description: "Agent-curated design language exported from Katagami as DESIGN.md."
colors:
bg: "#0E1114"
surface: "#171B20"
surface_2: "#1F252B"
sunk: "#0A0C0E"
text: "#ECF0F2"
muted: "#8A969E"
faint: "#535D64"
border: "#2A3138"
accent: "#E8A23D"
accent_deep: "#C97F1E"
on_accent: "#140E04"
cold: "#3E8FC4"
success: "#5FB08A"
warning: "#E8A23D"
error: "#D8604B"
info: "#3E8FC4"
typography:
headline-lg:
fontFamily: "Space Grotesk"
fontSize: "2.075rem"
fontWeight: 700
lineHeight: 1.1
letterSpacing: "-0.03em"
headline-md:
fontFamily: "Space Grotesk"
fontSize: "1.66rem"
fontWeight: 600
lineHeight: 1.15
letterSpacing: "-0.03em"
body-md:
fontFamily: "Spline Sans"
fontSize: "17px"
fontWeight: 400
lineHeight: 1.5
letterSpacing: "-0.03em"
label-md:
fontFamily: "Space Mono"
fontSize: "0.75rem"
fontWeight: 600
lineHeight: 1
letterSpacing: "0.08em"
rounded:
none: "0px"
md: "16px"
lg: "24px"
full: "9999px"
spacing:
base: "8px"
xs: "4px"
sm: "8px"
md: "12px"
lg: "16px"
xl: "24px"
2xl: "32px"
3xl: "48px"
4xl: "64px"
step-8: "96px"
components:
color-reference-bg:
backgroundColor: "{colors.bg}"
color-reference-surface:
backgroundColor: "{colors.surface}"
color-reference-surface_2:
backgroundColor: "{colors.surface_2}"
color-reference-sunk:
backgroundColor: "{colors.sunk}"
color-reference-text:
backgroundColor: "{colors.text}"
color-reference-muted:
backgroundColor: "{colors.muted}"
color-reference-faint:
backgroundColor: "{colors.faint}"
color-reference-border:
backgroundColor: "{colors.border}"
color-reference-accent:
backgroundColor: "{colors.accent}"
color-reference-accent_deep:
backgroundColor: "{colors.accent_deep}"
color-reference-on_accent:
backgroundColor: "{colors.on_accent}"
color-reference-cold:
backgroundColor: "{colors.cold}"
color-reference-success:
backgroundColor: "{colors.success}"
color-reference-warning:
backgroundColor: "{colors.warning}"
color-reference-error:
backgroundColor: "{colors.error}"
color-reference-info:
backgroundColor: "{colors.info}"
button-primary:
backgroundColor: "{colors.accent}"
textColor: "#000000"
typography: "{typography.label-md}"
rounded: "{rounded.md}"
padding: "{spacing.md}"
card-surface:
backgroundColor: "{colors.surface}"
textColor: "{colors.text}"
rounded: "{rounded.md}"
padding: "{spacing.md}"
input-default:
backgroundColor: "{colors.surface}"
textColor: "{colors.text}"
rounded: "{rounded.md}"
height: "44px"
---
# Spindle
## Overview
Spindle is a dark optical-archive recovery language for consoles that stabilize damaged discs, memory images, and born-digital records. It reads the disc radially: the platter itself is the instrument, recovery sweeps outward from the hub as a warm read-head arc, and unrecovered tracks wait in archival blue until a re-read clears them. Damage is always material — a ring, an offset, a checksum — never an effect.
### Values
- The disc is the instrument: a single concentric track-ring dial is the signature, and every other surface is that dial seen another way — flattened into meters, laid end to end as a checksum band, sampled as a fragment reel.
- Warmth means read: read-head amber marks recovered tracks; archival blue means cold and not-yet; voids mean dropped. State is colour-coded but always labelled in mono.
- Darkness as silence: a charcoal vault ground makes the few warm marks read like a read-head glowing on a platter under raking light.
- Evidence before expression: every mark clarifies a ring, offset, checksum, scan depth, or lock state; damage is material, never decorative.
- Static trust: the settled, fully-recovered state reads correctly in a still screenshot and with no JavaScript; motion is limited to a single dial draw and procedural reveals.
- Human traces at the edge: cropped hands, reflections, and disc surfaces appear as recovered fragments, never heroic portraits.
### Anti-Values
- No recoloured rectangular contact-sheet console — a palette or ground swap of the panel-grid forensic look is a failure.
- No pure-white SaaS ground; the only near-black voids are dropped sectors, the only ground is the charcoal vault.
- No single-edge accent on a card, no nav trapped in a floating pill bar, no nested cards.
- No blue background wash and no amber wallpaper; at most three accents used like highlighters.
- No green code rain, glowing cyberpunk HUD rings, glossy candy gradients, or ornamental corruption without provenance.
## Colors
Use the YAML color tokens as the normative palette. The prose below names the roles agents should preserve when generating UI.
| Token | Value |
|-------|-------|
| bg | `#0E1114` |
| surface | `#171B20` |
| surface_2 | `#1F252B` |
| sunk | `#0A0C0E` |
| text | `#ECF0F2` |
| muted | `#8A969E` |
| faint | `#535D64` |
| border | `#2A3138` |
| accent | `#E8A23D` |
| accent_deep | `#C97F1E` |
| on_accent | `#140E04` |
| cold | `#3E8FC4` |
| success | `#5FB08A` |
| warning | `#E8A23D` |
| error | `#D8604B` |
| info | `#3E8FC4` |
## Typography
- **Headline-Lg**: Space Grotesk, 2.075rem, weight 700, line-height 1.1.
- **Headline-Md**: Space Grotesk, 1.66rem, weight 600, line-height 1.15.
- **Body-Md**: Spline Sans, 17px, weight 400, line-height 1.5.
- **Label-Md**: Space Mono, 0.75rem, weight 600, line-height 1.
## Layout
### Spacing Tokens
- **Base**: `8px`
- **Xs**: `4px`
- **Sm**: `8px`
- **Md**: `12px`
- **Lg**: `16px`
- **Xl**: `24px`
- **2xl**: `32px`
- **3xl**: `48px`
- **4xl**: `64px`
- **Step-8**: `96px`
### Grid
Radial-led: a centred dial stage with meters/reel/log radiating around it; contained content capped at 1320px. Uses minmax(0,1fr) columns and min-width:0 so grids never blow out.
### Whitespace
64-96px of darkness around the dial stage, 24-32px panel padding, 4-8px proximity inside mono label and checksum rows.
### Density
Quiet overall density with compression only in mono readouts, track meters, and the pass log; the dial stage stays spacious.
### Responsive
1440 desktop leads with the dial; 768 tablet stacks dial then meters then reel/log; 390 mobile is a single column with the fragment reel in horizontal scroll. Only the full-bleed hero spans 100vw; ultrawide caps and centres.
### Breakpoints
- **Mobile**: 390px
- **Tablet**: 768px
- **Desktop**: 1440px
- **Ultrawide**: 2560px
## Elevation & Depth
### Shadows
- **Sm**: 0 1px 0 rgba(0,0,0,0.4)
- **Md**: 0 18px 50px rgba(0,0,0,0.45)
- **Lg**: 0 24px 60px rgba(0,0,0,0.55)
## Shapes
### Rounded
- **None**: `0px`
- **Md**: `16px`
- **Lg**: `24px`
- **Full**: `9999px`
### Surfaces
- **Ground**: Deep charcoal vault (#0E1114); pure white never used as ground, only near-black voids as dropped sectors.
- **Card Style**: Flat matte bench panels (#171B20), radius 16px, no border. Active panels carry a full inset amber ring (never a single edge) and a faint top amber wash.
- **Bg Pattern**: Faint concentric optical-sector ghost: arcs and radial ticks at 3-5% opacity behind the work area, cropped by the viewport.
- **Treatment**: Matte on a dark vault, no gloss, no glass, no gradient washes; the dial and its reflections carry the optical-sector geometry.
### Borders
- **Default Width**: 0px
- **Accent Width**: 1px
- **Style**: hairline + inset ring
- **Character**: Structure comes from hairline #2A3138 rules and full inset amber rings on active panes — never boxed borders, never a single accent edge.
## Components
### Composition
- Open on the radial track-ring dial as the primary instrument; let meters, fragment reel, and pass log radiate from it rather than sitting as equal cards.
- Treat every other surface as the disc seen another way — meters are the rings flattened, the checksum band is the rings end to end, the reel is the rings sampled.
- Allow one major field of darkness per screen as silence, with only mono coordinate marks or a single caption.
- Keep fragments in a track-ordered reel with material damage — sliced scars, dropped blocks, ring/offset IDs — never lifestyle imagery.
- Mark active recovery with read-head amber and cold/unrecovered with archival blue; never invert these meanings.
### Hierarchy
- Display hierarchy comes from wide Space Grotesk titles set large with -0.03em tracking and tight leading.
- Operational text uses Space Mono in uppercase micro-labels: ring/offset IDs, checksums, timestamps, depths, lock states.
- Body explanations use Spline Sans at 17px.
- Read-head amber marks recovered and active; archival blue marks cold; rust and green are small exception/lock indicators only.
### Density
Alternate the spacious dial stage with tight mono readouts: 4-8px inside label clusters, 48px+ between modules, 64-96px fields of darkness as silence so the system feels deliberate, not filled.
### Signature
- The track-ring dial: concentric stroke-dasharray arcs encoding per-track state — amber recovered, blue cold, gap void — with a thin read-head marker line at the current angle.
- Track meters: the dial's rings flattened into linear 9999px bars, amber fill (gradient) and cold blue at reduced opacity.
- Checksum band: the rings laid end to end as a single 9999px strip — warm where clean, blue where cold, void-black where dropped.
- Fragment reel: track-ordered square fragments built from halftone radial dots, scan-line interlace, sliced black scars, dropped blocks, and mono IDs.
- Active surfaces marked by a full inset amber ring, never a single accent edge; the nav sits open, never in a pill.
## shadcn/ui Usage
When the target app uses shadcn/ui, copy DESIGN.md with shadcn instead of the plain DESIGN.md. It contains the same Katagami design-language source plus the shadcn/ui primitives, imports, theme variables, component recipes, and preview-shot guidance.
DESIGN.md with shadcn: `/language/en-019ef831-f022-7871-9f76-630c171550eb/DESIGN.with-shadcn.md`.
The shadcn page also exposes optional machine-readable files for automation, but the human-facing handoff is DESIGN.md with shadcn.
Install recommended primitives with `npx shadcn@latest add button card input textarea select dialog sheet tabs badge separator checkbox switch slider tooltip dropdown-menu table`.
Use these primitives in shadcn apps:
- button
- card
- input
- textarea
- select
- dialog
- sheet
- tabs
- badge
- separator
- checkbox
- switch
- slider
- tooltip
- dropdown-menu
- table
Implementation rule for agents: import shadcn primitives from `@/components/ui/*`, apply the generated CSS variables first, then compose the language-specific recipes from the companion MD. Katagami remains the source of truth; shadcn names are the implementation surface.
## Do's and Don'ts
- Do Lead with the radial dial; make it the one instrument the rest of the system reuses.
- Do Keep warmth for recovered and blue for cold; label every state in mono, never colour alone.
- Do Make damage material — ring, offset, checksum, angle — and use darkness as silence.
- Do Style every form control fully on the dark ground; focus rings in amber.
- Do Keep at most three accents, used like highlighters, with radii only from {0,16,24,9999}.
- Don't Don't recolour a rectangular contact-sheet console and call it new.
- Don't Don't put a single accent edge on a card or trap the nav in a pill.
- Don't Don't let blue become a background wash or amber become wallpaper.
- Don't Don't show a glitch without provenance, or use gloss, glass, or candy gradients.
- Don't Don't default to white anywhere; pure white is never the ground.
### Accessibility
Maintain AA contrast with scan-white text on the charcoal vault; pair every state colour with a mono text label and a dot; keep micro-labels at 11px or larger; preserve keyboard focus outlines (amber halo); provide reduced-motion behaviour for the dial draw and reveals.
## Imagery Direction
### Pairs With
salvage
### Summary
Recovered-fragment scans in the salvage technique — halftone radial sector dots, scan-line interlace, sliced data-loss scars, dropped white sectors, archival-blue tint — applied to disc surfaces and spindle hubs on a dark vault ground, composed radially.
### Subjects
- damaged optical disc on a spindle
- platter surface under a raking read-head
- concentric track geometry
- cropped hand or reflection at the disc edge
- dropped-sector voids
### Usage
One full-bleed radial hero of the disc-as-instrument; fragment-reel thumbnails are small, track-ordered, and materially damaged. Never heroic portraits, never decorative glitch.
```json
{
"$schema": "https://ui.shadcn.com/schema/registry-item.json",
"name": "spindle",
"type": "registry:theme",
"title": "Spindle shadcn Theme",
"cssVars": {
"theme": {},
"light": {
"background": "#0E1114",
"foreground": "#ECF0F2",
"card": "#171B20",
"card-foreground": "#ECF0F2",
"popover": "#171B20",
"popover-foreground": "#ECF0F2",
"primary": "#ECF0F2",
"primary-foreground": "#111111",
"secondary": "#f4f4f5",
"secondary-foreground": "#111111",
"muted": "#8A969E",
"muted-foreground": "#ECF0F2",
"accent": "#E8A23D",
"accent-foreground": "#ffffff",
"destructive": "#D8604B",
"border": "#2A3138",
"input": "#2A3138",
"ring": "#E8A23D",
"chart-1": "#ECF0F2",
"chart-2": "#f4f4f5",
"chart-3": "#E8A23D",
"chart-4": "#5FB08A",
"chart-5": "#E8A23D",
"sidebar": "#171B20",
"sidebar-foreground": "#ECF0F2",
"sidebar-primary": "#ECF0F2",
"sidebar-primary-foreground": "#111111",
"sidebar-accent": "#3E8FC4",
"sidebar-accent-foreground": "#ffffff",
"sidebar-border": "#2A3138",
"sidebar-ring": "#E8A23D",
"radius": "16px"
},
"dark": {
"background": "#0f1115",
"foreground": "#f8fafc",
"card": "#181b22",
"card-foreground": "#f8fafc",
"popover": "#181b22",
"popover-foreground": "#f8fafc",
"primary": "#ECF0F2",
"primary-foreground": "#111111",
"secondary": "#252a33",
"secondary-foreground": "#f8fafc",
"muted": "#252a33",
"muted-foreground": "#a1a1aa",
"accent": "#E8A23D",
"accent-foreground": "#ffffff",
"destructive": "#D8604B",
"border": "#303642",
"input": "#303642",
"ring": "#E8A23D",
"chart-1": "#ECF0F2",
"chart-2": "#f4f4f5",
"chart-3": "#E8A23D",
"chart-4": "#5FB08A",
"chart-5": "#E8A23D",
"sidebar": "#181b22",
"sidebar-foreground": "#f8fafc",
"sidebar-primary": "#ECF0F2",
"sidebar-primary-foreground": "#111111",
"sidebar-accent": "#E8A23D",
"sidebar-accent-foreground": "#ffffff",
"sidebar-border": "#303642",
"sidebar-ring": "#E8A23D",
"radius": "16px"
}
},
"meta": {
"source": "katagami",
"languageId": "en-019ef831-f022-7871-9f76-630c171550eb",
"slug": "spindle",
"componentManifest": [
"button",
"card",
"input",
"textarea",
"select",
"dialog",
"sheet",
"tabs",
"badge",
"separator",
"checkbox",
"switch",
"slider",
"tooltip",
"dropdown-menu",
"table"
],
"installCommand": "npx shadcn@latest add button card input textarea select dialog sheet tabs badge separator checkbox switch slider tooltip dropdown-menu table",
"nativeTokenNames": {
"colors": [
"accent",
"accent_deep",
"accent_wash",
"bg",
"border",
"cold",
"cold_wash",
"error",
"faint",
"info",
"muted",
"on_accent",
"success",
"sunk",
"surface",
"surface_2",
"text",
"warning"
],
"typography": [
"base_size",
"body_font",
"google_fonts_url",
"heading_font",
"heading_transform",
"heading_weight",
"letter_spacing",
"mono_font"
],
"radii": [
"full",
"lg",
"md",
"none"
],
"shadows": [
"lg",
"md",
"sm"
],
"spacing": [
"base",
"scale"
],
"surfaces": [
"bg_pattern",
"card_style",
"ground",
"treatment"
],
"borders": [
"accent_width",
"character",
"default_width",
"style"
],
"motion": [
"duration",
"easing",
"philosophy"
]
}
}
}
```The quick brown fox jumps
The quick brown fox jumps
The quick brown fox jumps
The quick brown fox jumps
Agent-generated
Keep Spindleand swap a palette and an art style onto it — the landing & dashboard recolor live. The Studio does the same with all three lanes free.
Copy this when the target app uses shadcn/ui. It packages the Katagami DESIGN.md context with the install list, theme variables, component recipes, preview-shot contract, and starter TSX in one Markdown companion.
npx shadcn@latest add button card input textarea select dialog sheet tabs badge separator checkbox switch slider tooltip dropdown-menu table:root {
--background: #0E1114;
--foreground: #ECF0F2;
--card: #171B20;
--card-foreground: #ECF0F2;
--popover: #171B20;
--popover-foreground: #ECF0F2;
--primary: #ECF0F2;
--primary-foreground: #111111;
--secondary: #f4f4f5;
--secondary-foreground: #111111;
--muted: #8A969E;
--muted-foreground: #ECF0F2;
--accent: #E8A23D;
--accent-foreground: #ffffff;
--destructive: #D8604B;
--border: #2A3138;
--input: #2A3138;
--ring: #E8A23D;
--chart-1: #ECF0F2;
--chart-2: #f4f4f5;
--chart-3: #E8A23D;
--chart-4: #5FB08A;
--chart-5: #E8A23D;
--sidebar: #171B20;
--sidebar-foreground: #ECF0F2;
--sidebar-primary: #ECF0F2;
--sidebar-primary-foreground: #111111;
--sidebar-accent: #3E8FC4;
--sidebar-accent-foreground: #ffffff;
--sidebar-border: #2A3138;
--sidebar-ring: #E8A23D;
--radius: 16px;
}
.dark {
--background: #0f1115;
--foreground: #f8fafc;
--card: #181b22;
--card-foreground: #f8fafc;
--popover: #181b22;
--popover-foreground: #f8fafc;
--primary: #ECF0F2;
--primary-foreground: #111111;
--secondary: #252a33;
--secondary-foreground: #f8fafc;
--muted: #252a33;
--muted-foreground: #a1a1aa;
--accent: #E8A23D;
--accent-foreground: #ffffff;
--destructive: #D8604B;
--border: #303642;
--input: #303642;
--ring: #E8A23D;
--chart-1: #ECF0F2;
--chart-2: #f4f4f5;
--chart-3: #E8A23D;
--chart-4: #5FB08A;
--chart-5: #E8A23D;
--sidebar: #181b22;
--sidebar-foreground: #f8fafc;
--sidebar-primary: #ECF0F2;
--sidebar-primary-foreground: #111111;
--sidebar-accent: #E8A23D;
--sidebar-accent-foreground: #ffffff;
--sidebar-border: #303642;
--sidebar-ring: #E8A23D;
--radius: 16px;
}
import { Badge } from "@/components/ui/badge";
import { Button } from "@/components/ui/button";
import {
Card,
CardContent,
CardDescription,
CardFooter,
CardHeader,
CardTitle,
} from "@/components/ui/card";
import { Input } from "@/components/ui/input";
import { Tabs, TabsList, TabsTrigger } from "@/components/ui/tabs";
export function SpindleShadcnKit() {
return (
<section className="grid gap-4 rounded-[var(--radius)] border bg-background p-4 text-foreground">
<div className="flex items-start justify-between gap-4">
<div>
<Badge variant="outline">shadcn/ui</Badge>
<h2 className="mt-3 text-2xl font-semibold tracking-tight">Spindle</h2>
<p className="mt-1 max-w-xl text-sm text-muted-foreground">
Use the Katagami registry theme, then compose these shadcn primitives
with the language-specific component recipes.
</p>
</div>
<Button>Apply theme</Button>
</div>
<Tabs defaultValue="components">
<TabsList>
<TabsTrigger value="components">Components</TabsTrigger>
<TabsTrigger value="states">States</TabsTrigger>
<TabsTrigger value="export">Export</TabsTrigger>
</TabsList>
</Tabs>
<Card>
<CardHeader>
<CardTitle>Component recipe</CardTitle>
<CardDescription>
Replace this starter content with the agent-authored product scene
from components.md and preview-shots.json.
</CardDescription>
</CardHeader>
<CardContent className="grid gap-3 sm:grid-cols-[1fr_auto]">
<Input defaultValue="Tokenized shadcn surface" aria-label="Recipe name" />
<Button variant="secondary">Preview state</Button>
</CardContent>
<CardFooter className="justify-between">
<Badge>Ready</Badge>
<Button variant="outline">Copy recipe</Button>
</CardFooter>
</Card>
</section>
);
}
{
"$schema": "https://ui.shadcn.com/schema/registry-item.json",
"name": "spindle",
"type": "registry:theme",
"author": "katagami-agent",
"title": "Spindle — optical-archive recovery",
"visualProfile": {
"mode": "dark",
"ground": "deep charcoal vault (#0E1114); pure white never used as ground",
"material": "flat matte panels on a dark vault; no gloss, no glass, no gradient washes",
"borders": "hairline #2A3138 only; active surfaces marked by a full inset amber ring, never a single edge",
"radius": "16px panels, 9999px pills/rings/dials, 0/24px reserved; no arbitrary in-between radii",
"accent_usage": "read-head amber (#E8A23D) for active recovery; archival blue (#3E8FC4) for cold/unrecovered; used like highlighters",
"typography": "Space Grotesk display (wide, -0.03em), Space Mono operational labels, Spline Sans body 17px",
"signature": "concentric track-ring dial; the disc is the instrument, every surface is the disc seen another way",
"motion": "procedural and near-absent; settled state default, no-JS visible"
},
"cssVars": {
"theme": {
"font-sans": "Spline Sans, system-ui, sans-serif",
"font-mono": "Space Mono, ui-monospace, monospace",
"font-display": "Space Grotesk, system-ui, sans-serif",
"radius": "16px"
},
"dark": {
"background": "#0E1114",
"foreground": "#ECF0F2",
"card": "#171B20",
"card-foreground": "#ECF0F2",
"popover": "#171B20",
"popover-foreground": "#ECF0F2",
"primary": "#E8A23D",
"primary-foreground": "#140E04",
"secondary": "#1F252B",
"secondary-foreground": "#ECF0F2",
"muted": "#1F252B",
"muted-foreground": "#8A969E",
"accent": "#3E8FC4",
"accent-foreground": "#0A0C0E",
"destructive": "#D8604B",
"destructive-foreground": "#ECF0F2",
"success": "#5FB08A",
"warning": "#E8A23D",
"info": "#3E8FC4",
"border": "#2A3138",
"input": "#0A0C0E",
"ring": "#E8A23D",
"radius": "16px"
}
}
}
# Spindle shadcn/ui Components
Artifact: `component-recipes-v1`
Author: `katagami-ui-projection`
Language ID: `en-019ef831-f022-7871-9f76-630c171550eb`
Slug: `spindle`
## Intent
Spindle is a dark optical-archive recovery language for consoles that stabilize damaged discs, memory images, and born-digital records. It reads the disc radially: the platter itself is the instrument, recovery sweeps outward from the hub as a warm read-head arc, and unrecovered tracks wait in archival blue until a re-read clears them. Damage is always material — a ring, an offset, a checksum — never an effect.
## Required primitives
- button
- card
- input
- textarea
- select
- dialog
- sheet
- tabs
- badge
- separator
- checkbox
- switch
- slider
- tooltip
- dropdown-menu
- table
Install with `npx shadcn@latest add button card input textarea select dialog sheet tabs badge separator checkbox switch slider tooltip dropdown-menu table`.
## Token cues
Colors:
{
"bg": "#0E1114",
"surface": "#171B20",
"surface_2": "#1F252B",
"sunk": "#0A0C0E",
"text": "#ECF0F2",
"muted": "#8A969E",
"faint": "#535D64",
"border": "#2A3138",
"accent": "#E8A23D",
"accent_deep": "#C97F1E",
"accent_wash": "rgba(232,162,61,0.16)",
"on_accent": "#140E04",
"cold": "#3E8FC4",
"cold_wash": "rgba(62,143,196,0.14)",
"success": "#5FB08A",
"warning": "#E8A23D",
"error": "#D8604B",
"info": "#3E8FC4"
}
Typography:
{
"base_size": "17px",
"body_font": "Spline Sans",
"heading_font": "Space Grotesk",
"mono_font": "Space Mono",
"heading_weight": "600",
"heading_transform": "none",
"letter_spacing": "-0.03em",
"google_fonts_url": "https://fonts.googleapis.com/css2?family=Space+Grotesk:wght@400;500;600;700&family=Space+Mono:ital,wght@0,400;0,700;1,400&family=Spline+Sans:wght@400;500;600&display=swap"
}
## Visual character to preserve
- Make the source language's structural identity visible in every component state.
## ShadSync visual profile
{
"family": "system",
"material": "flat",
"contour": "default",
"border": "solid",
"underlay": false,
"grain": false,
"stickerBadges": false,
"motion": "still",
"density": "balanced",
"accents": [
"primary",
"accent",
"secondary",
"muted"
]
}
## Signature component recipes
### Button
Use `Button` for primary, secondary, outline, and ghost actions. Primary actions must expose the language's strongest contrast pair, while secondary and ghost actions should preserve the surface treatment instead of falling back to default neutral SaaS styling.
### Card
Use `Card`, `CardHeader`, `CardContent`, `CardFooter`, and `CardAction` as the main composition frame. Cards should demonstrate the language's surface, border, hierarchy, and density rules rather than appearing as generic rounded rectangles.
### Input and Textarea
Use `Input` and `Textarea` with visible focus rings, field labels, validation states, and the language's rhythm. Forms should show real product content, not placeholder-only controls.
### Select, Tabs, and Table
Use `Select`, `Tabs`, and `Table` to prove navigation, filtering, and dense data states. The table should show row rhythm, separators, hover/focus states, and an empty or status state when the language calls for it.
### Dialog and Sheet
Use `Dialog` for centered decisions and `Sheet` for contextual editing. Both should inherit the language's spacing, border, overlay, and motion rules.
## Preview shots
- `application-shell`: dashboard or workspace shell with navigation, cards, forms, and state badges.
- `detail-editor`: focused editing flow using input, textarea, select, switch/checkbox, dialog or sheet, and action buttons.
- `data-operations`: table-heavy operational view with tabs, dropdown menu affordances, badges, and destructive/empty states.
- Each preview shot must include a renderable `scene` payload with concrete headline, description, actions, and rows/fields/stats for the UI preview.
## Implementation contract
- Start from local `ui/src/components/ui` shadcn-style primitives; do not create a second component system.
- Apply `/katagami/shadcn/spindle/registry-theme.json` variables, then use these recipes for composition and state design.
- Preserve Katagami token names as source metadata; shadcn semantic names are only the export surface.
- Do: Lead with the radial dial; make it the one instrument the rest of the system reuses.; Keep warmth for recovered and blue for cold; label every state in mono, never colour alone.; Make damage material — ring, offset, checksum, angle — and use darkness as silence.; Style every form control fully on the dark ground; focus rings in amber.; Keep at most three accents, used like highlighters, with radii only from {0,16,24,9999}.
- Do not: Don't recolour a rectangular contact-sheet console and call it new.; Don't put a single accent edge on a card or trap the nav in a pill.; Don't let blue become a background wash or amber become wallpaper.; Don't show a glitch without provenance, or use gloss, glass, or candy gradients.; Don't default to white anywhere; pure white is never the ground.
## Copy-paste component example
This generated starter proves the import shape. Production Katagami agents should replace it with a language-specific product composition.
```tsx
import { Badge } from "@/components/ui/badge";
import { Button } from "@/components/ui/button";
import {
Card,
CardContent,
CardDescription,
CardFooter,
CardHeader,
CardTitle,
} from "@/components/ui/card";
import { Input } from "@/components/ui/input";
import { Tabs, TabsList, TabsTrigger } from "@/components/ui/tabs";
export function SpindleShadcnKit() {
return (
<section className="grid gap-4 rounded-[var(--radius)] border bg-background p-4 text-foreground">
<div className="flex items-start justify-between gap-4">
<div>
<Badge variant="outline">shadcn/ui</Badge>
<h2 className="mt-3 text-2xl font-semibold tracking-tight">Spindle</h2>
<p className="mt-1 max-w-xl text-sm text-muted-foreground">
Use the Katagami registry theme, then compose these shadcn primitives
with the language-specific component recipes.
</p>
</div>
<Button>Apply theme</Button>
</div>
<Tabs defaultValue="components">
<TabsList>
<TabsTrigger value="components">Components</TabsTrigger>
<TabsTrigger value="states">States</TabsTrigger>
<TabsTrigger value="export">Export</TabsTrigger>
</TabsList>
</Tabs>
<Card>
<CardHeader>
<CardTitle>Component recipe</CardTitle>
<CardDescription>
Replace this starter content with the agent-authored product scene
from components.md and preview-shots.json.
</CardDescription>
</CardHeader>
<CardContent className="grid gap-3 sm:grid-cols-[1fr_auto]">
<Input defaultValue="Tokenized shadcn surface" aria-label="Recipe name" />
<Button variant="secondary">Preview state</Button>
</CardContent>
<CardFooter className="justify-between">
<Badge>Ready</Badge>
<Button variant="outline">Copy recipe</Button>
</CardFooter>
</Card>
</section>
);
}
```
## Layout notes
{
"grid": "Radial-led: a centred dial stage with meters/reel/log radiating around it; contained content capped at 1320px. Uses minmax(0,1fr) columns and min-width:0 so grids never blow out.",
"whitespace": "64-96px of darkness around the dial stage, 24-32px panel padding, 4-8px proximity inside mono label and checksum rows.",
"density": "Quiet overall density with compression only in mono readouts, track meters, and the pass log; the dial stage stays spacious.",
"responsive": "1440 desktop leads with the dial; 768 tablet stacks dial then meters then reel/log; 390 mobile is a single column with the fragment reel in horizontal scroll. Only the full-bleed hero spans 100vw; ultrawide caps and centres.",
"breakpoints": {
"mobile": "390px",
"tablet": "768px",
"desktop": "1440px",
"ultrawide": "2560px"
}
}
{
"artifact": "katagami:shadcn-preview-shots",
"version": "preview-shots-v1",
"generator": "katagami-ui-compatibility-projection",
"generatedBy": "katagami-ui-projection",
"requiresVisualProfile": true,
"schema": "katagami:shadcn-preview-shots/renderable-v1",
"renderable": true,
"language": {
"id": "en-019ef831-f022-7871-9f76-630c171550eb",
"name": "Spindle",
"slug": "spindle"
},
"installCommand": "npx shadcn@latest add button card input textarea select dialog sheet tabs badge separator checkbox switch slider tooltip dropdown-menu table",
"primitives": [
"button",
"card",
"input",
"textarea",
"select",
"dialog",
"sheet",
"tabs",
"badge",
"separator",
"checkbox",
"switch",
"slider",
"tooltip",
"dropdown-menu",
"table"
],
"identityNotes": [],
"visualProfile": {
"family": "system",
"material": "flat",
"contour": "default",
"border": "solid",
"underlay": false,
"grain": false,
"stickerBadges": false,
"motion": "still",
"density": "balanced",
"accents": [
"primary",
"accent",
"secondary",
"muted"
]
},
"shots": [
{
"id": "application-shell",
"title": "Application shell",
"viewport": "desktop",
"primitives": [
"button",
"card",
"input",
"select",
"tabs",
"badge",
"separator",
"table"
],
"composition": "A real product workspace with navigation, summary cards, filtering controls, and one dense content region.",
"mustShow": [
"primary and secondary actions",
"card hierarchy",
"filterable state",
"table or list density"
],
"avoid": [
"component inventory walls",
"placeholder-only content",
"generic rounded SaaS chrome"
],
"scene": {
"eyebrow": "workspace spread",
"headline": "Spindle launch room",
"description": "A product team workspace where navigation, filters, metrics, and dense rows carry the language's visible structure.",
"primaryAction": "Apply theme",
"secondaryAction": "Review states",
"stats": [
{
"label": "components",
"value": "16",
"tone": "accent"
},
{
"label": "states",
"value": "ready"
},
{
"label": "density",
"value": "balanced",
"tone": "warning"
}
],
"rows": [
{
"label": "Primary flow",
"value": "mapped",
"status": "active"
},
{
"label": "Token coverage",
"value": "semantic",
"status": "synced"
},
{
"label": "Responsive proof",
"value": "queued",
"status": "review"
}
],
"statuses": [
"Active",
"Synced",
"Draft"
]
}
},
{
"id": "detail-editor",
"title": "Detail editor",
"viewport": "tablet",
"primitives": [
"button",
"card",
"input",
"textarea",
"select",
"checkbox",
"switch",
"slider",
"dialog",
"sheet"
],
"composition": "A focused editing flow with form fields, validation, confirmation, and a contextual side panel.",
"mustShow": [
"focus ring",
"error or destructive state",
"dialog or sheet treatment",
"written guidance content"
],
"avoid": [
"unstyled browser controls",
"floating cards inside cards",
"missing labels"
],
"scene": {
"eyebrow": "editing flow",
"headline": "Language recipe editor",
"description": "A focused form proving labels, validation, toggles, panel rhythm, and action hierarchy.",
"primaryAction": "Save recipe",
"secondaryAction": "Open sheet",
"fields": [
{
"label": "Component family",
"value": "Narrative cards"
},
{
"label": "State treatment",
"value": "Visible focus + validation"
},
{
"label": "Motion",
"value": "Small lift, no opacity-only fade"
}
],
"statuses": [
"Focus",
"Invalid",
"Confirmed"
]
}
},
{
"id": "data-operations",
"title": "Data operations",
"viewport": "mobile",
"primitives": [
"button",
"tabs",
"badge",
"dropdown-menu",
"table",
"tooltip",
"separator"
],
"composition": "A compact operational view proving row rhythm, stacked actions, menu states, badges, and empty/destructive states.",
"mustShow": [
"responsive reflow",
"dense row styling",
"menu affordance",
"status badge system"
],
"avoid": [
"desktop-only tables",
"text overflow",
"default shadcn spacing without Katagami character"
],
"scene": {
"eyebrow": "operations",
"headline": "Compact review queue",
"description": "A narrow viewport scene with rows, menus, tooltips, badges, and destructive affordances.",
"primaryAction": "Resolve",
"secondaryAction": "Filter",
"rows": [
{
"label": "Button hierarchy",
"value": "approved",
"status": "ok"
},
{
"label": "Table rhythm",
"value": "needs pass",
"status": "watch"
},
{
"label": "Empty state",
"value": "designed",
"status": "done"
}
],
"statuses": [
"Queued",
"Blocked",
"Done"
]
}
}
],
"componentRecipes": [
{
"primitive": "button",
"intent": "Prove action hierarchy, focus, disabled, and destructive states."
},
{
"primitive": "card",
"intent": "Carry the language surface, border, elevation, and density rules."
},
{
"primitive": "input",
"intent": "Show labels, focus rings, validation, and spacing rhythm."
},
{
"primitive": "textarea",
"intent": "Show longer guidance, validation copy, and writing density."
},
{
"primitive": "select",
"intent": "Show filtering, selection contrast, and menu trigger styling."
},
{
"primitive": "dialog",
"intent": "Show centered decision states and overlay treatment."
},
{
"primitive": "sheet",
"intent": "Show contextual side panels and responsive editing."
},
{
"primitive": "tabs",
"intent": "Show navigational structure and active/inactive contrast."
},
{
"primitive": "badge",
"intent": "Show compact status vocabulary and semantic colors."
},
{
"primitive": "separator",
"intent": "Show section rhythm without generic gray dividers."
},
{
"primitive": "checkbox",
"intent": "Show binary selection with visible focus and checked states."
},
{
"primitive": "switch",
"intent": "Show settings toggles and on/off contrast."
},
{
"primitive": "slider",
"intent": "Show numeric adjustment with track/thumb styling."
},
{
"primitive": "tooltip",
"intent": "Show concise explanation styling above compact controls."
},
{
"primitive": "dropdown-menu",
"intent": "Show action menus, destructive items, and grouped choices."
},
{
"primitive": "table",
"intent": "Show dense operational data, separators, row states, and responsive behavior."
}
],
"qualityRules": {
"do": [
"Lead with the radial dial; make it the one instrument the rest of the system reuses.",
"Keep warmth for recovered and blue for cold; label every state in mono, never colour alone.",
"Make damage material — ring, offset, checksum, angle — and use darkness as silence.",
"Style every form control fully on the dark ground; focus rings in amber.",
"Keep at most three accents, used like highlighters, with radii only from {0,16,24,9999}."
],
"dont": [
"Don't recolour a rectangular contact-sheet console and call it new.",
"Don't put a single accent edge on a card or trap the nav in a pill.",
"Don't let blue become a background wash or amber become wallpaper.",
"Don't show a glitch without provenance, or use gloss, glass, or candy gradients.",
"Don't default to white anywhere; pure white is never the ground."
]
}
}