Scratch Proto

Prototype
Browser-based diagnostic tools · internal dev aesthetic

A dark, monospace design language built around an exposed-wireframe feel: a dot-grid substrate, faint scanlines, registration corner-marks, amber caution accents, and build-stamp metadata. It reads like an internal instrument that was never meant to ship — and looks proud of it. This page is the canonical reference, reconciled from the scratch and simple-llm-ui repos.

01

Color

5 surfaces · 4 text · amber primary + green/red status

Surfaces step in near-black increments — almost no chroma. The whole system rides on three semantic colors, each with one job: --accent (amber) is primary action / caution, --signal (green) is success / live, --danger (red) is error / destructive. Amber is locked — keeping green and red unambiguous as status. Everything else is neutral so those three carry all the meaning.

Surfaces
Text
Semantic colors
Borders
02

Typography

2 families · monospace-first

Space Grotesk for display (headings, names), JetBrains Mono for everything else. The monospace body is core to the identity — it makes every screen feel like console output. Two signature prefixes carry hierarchy without extra weight: > for primary titles, // for captions and comments.

Display · Space Grotesk
H1 · 1.75rem / 700 · letter-spacing -0.03em
> Scratch Proto
H2 · 1.5rem / 700
Reflection Blur
H3 / Card name · 0.95rem / 600
GPU Benchmark
Mono · JetBrains Mono
Body · 14px / 1.65
Real-time GPS position display with interactive Leaflet map.
Description · 12px · --text-muted
WebGL2 texture-space shading with debug atlas views
Label / micro · 10px · uppercase · tracking 0.12em
ADD UPSTREAM
Index prefix · decimal-leading-zero counter
00 Location History Map    01 Microphone Diagnostics
Error / failed text (.text-cut-shadow)
BUILD FAILED soft red glow, 2×2px checkerboard cutout
03

Spacing & Radius

neither repo had a formal scale

The source repos used ad-hoc values (10/12/14/16px, 1.15rem…). This formalizes a 4-based scale — existing values snap to the nearest step on export. Radius is 0 by default: the system is hard-edged. The only rounded elements are true pills and status dots (--r-pill).

Spacing · 4px base
--sp-14px
--sp-28px
--sp-312px
--sp-416px
--sp-524px
--sp-632px
--sp-748px
--sp-864px
Radius · square by default
--r-sm/md/lg = 0
everything
--r-pill = 999px
dots & pills only
Applied spacing · component padding & gaps

Components reference semantic spacing tokens — not raw px — so padding and gaps are tuned from one place.

live · governed by --pad-* / --gap-*
button primary ↳ --pad-control-y · --pad-control-x
↳ --pad-control-y · --pad-control-x
DeepSeekKEY
https://api.deepseek.com
↳ --pad-card
↳ gap = --gap-stack
current values
--pad-control-ybuttons · inputs · tabs (vertical)8px
--pad-control-xbuttons · inputs · tabs (horizontal)12px
--pad-cardcards · list items · modal rows18px
--gap-stackvertical gap inside stacks8px
04

Motion

click a curve to preview

Motion is restrained and quick. One curve only--ease-out — is used for every transition; nothing eases any other way. UI transitions sit at 0.09–0.11s, overlays at 0.19s. The only motion that runs unprompted is the looping “live system” pulse (status LED, streaming caret), which signals work in flight.

--ease-out
cubic-bezier(.16, 1, .3, 1) — the only curve
--dur scale
fast .09 · base .11 · slow .19
05

Signature Patterns

the load-bearing motifs

These are what make it Scratch Proto and not just another dark theme. Use them deliberately — they carry the "exposed instrument" personality.

Substrate · dot-grid + scanline
--grid-dot · --scanline

A 24px radial dot-grid is fixed to the viewport behind everything; a faint 2px scanline rides on top. Both reconciled on (scratch's variant).

Registration corner-marks
test Add
Bracket corners ("cut here" registration marks) are the universal cue for an interactive surface — every clickable card and box-button carries them, so they read apart from static text, code, or badges. 10px on cards, 5px on buttons.
Hover: brackets warm to amber.
Status · prototype badge · caution stripe

Motion rule: a dot pulses only while work is actively happening — running or queued. Every other state is a static dot; the pulse is a signal that something is in flight (e.g. the auto-reload poller checking for a new build), never ambient decoration.

live-state motifs
Prototype
running (pulses) queued (pulses) idle stale error
.caution-stripe — diagonal hazard border for destructive / experimental zones
Build-stamp
footer metadata
SW:ACTIVE · BUILD:59FC335
DEPLOYED:4 DAYS AGO
SRC
06

Components

lifted verbatim from the repos
Buttons

The first true component<scratch-button>, a shadow-DOM custom element. Structure and styles are sealed inside; only the design tokens reach in. There's no .btn class to misuse, so a button literally cannot be assembled wrong. Variants are an attribute.

<scratch-button> · default / accent / danger / link
test Add Remove test connection disabled
variant="ghost" · the quiet borderless tier
× rename muted → bright on hover · no marks, no box, no ring · disabled = dimmed only

Buttons are form-associated: type="submit" submits the owning <form> (native validation included). No type, no submit — a plain button never touches a form, so existing wiring is untouched.

Inputs
<scratch-field> · disabled = dashed · type="password | number | …"

type covers the single-line modes — text (default) · password · number · search · email · url — with min / max / step passed through for number use. multiline ignores it.

Select

Component <scratch-select> — light-DOM <option> children are the options source, mirrored into a sealed control and kept live by a MutationObserver (edit the list any time; the current value survives while it still names an option). Form-associated; fires composed input/change. Option text renders verbatim — no uppercase, so model ids read as-is.

<scratch-select> · placeholder / disabled = dashed
Toggle

Component <scratch-toggle> — form-associated checkbox riding a hidden native <input type="checkbox">, so keyboard and a11y come for free. The box is hard-edged; checked fills an inset amber square (LED-adjacent, never rounded). The label is slotted — click anywhere to flip.

<scratch-toggle> · on / off / disabled = dashed
stream responses retro-title sweep telemetry — not in this build
Progress

Component <scratch-progress> — a thin instrument bar. value / max drive the fill; state picks the semantic color; indeterminate sweeps a segment on the system curve. The motion rule holds: under prefers-reduced-motion the sweep is replaced by a static dim 40% fill — no motion, same meaning. Updates are cheap (a style.width mutation), so feeding it every frame is fine. Height via --progress-height (6px).

<scratch-progress> · determinate / indeterminate
accent · value=72
signal · complete
danger · failing
indeterminate · sweeping
Tabs

Component <scratch-tabs> with <scratch-tab label="…"> children — each tab's label and panel live in one element, so they can't desync. The connected-underline strip is generated and sealed; selected sets the default; switching fires change.

<scratch-tabs> · <scratch-tab> No favorites pinned yet. Three upstreams configured. No tool servers connected.
Cards
<scratch-card> grid · auto-fill minmax(280px)
Badges
<scratch-badge> · default / variant="key" / variant="off"
Prototype Anthropic KEY Ollama KEY disabled off — the inactive chip: dashed, muted, no LED
Preview + caption

The second sealed component: <scratch-preview> holds a color, sample, or image placeholder in its body (via color or a slot) above a caption (label / sub). The entire Color section is built from instances of it.

<scratch-preview> · .preview-grid
image
Settings modal
<scratch-modal>
Sidebar navigation

One component — <scratch-nav> with <scratch-nav-item> children — powers both this overlay specimen and this page's own left rail. Items auto-number and carry the connected indicator. desc is optional: omit it and you get the shorter rail-style button (see the rail at left).

<scratch-nav boxed label="…"> · with desc
Chat message & composer
<scratch-message> · <scratch-composer>
Benchmark the WebGPU fillrate path and report draw-call overhead. Running the fillrate sweep now
07

Reconciliation

scratch vs simple-llm-ui · resolved

The two repos drifted. Per your call, the canon adopts scratch's richer variant, fixes outright bugs, and adds the scale neither had.

Decisionscratchsimple-llm-uiCanonVerdict
Scanline overlayondroppedonkept
Card corner-marksbracketsplain boxbracketskept
Prototype badgebadge-protoplain .badgeboth, scopedkept
--signal-glow / --warningdefinedmissingrestoredfixed
--ease-out (sole curve)definedmissingrestored; --ease-bounce droppedfixed
var(--muted) typobroken ref→ --text-mutedfixed
grid-dot opacity0.080.08 / 0.06*0.08fixed
Spacing scalead-hocad-hoc4-based, 8 stepsadded
Radius tokens4 / 6px raw4 / 6px raw0 — square; pill for dotsadded
Type scaleimplicitimplicit8 named stepsadded

* nav.css fallback drifted to 0.06; canon locks 0.08 everywhere.