ASCII Design System & Pattern Library
family and icon/tile slot added (2026-07-27); other house kits seeded
Scope: Visual composition vocabulary for all screen surfaces — frames, dividers, fills,
accents, data display, network maps. Applies to system screens and cartridge UI alike.
Companion documents: character-set.md
(glyph bytes — the byte authority for everything below), screen-design-rules.md
(row contract), animation.md (the two sanctioned motion styles),
animation.md (the two sanctioned animation styles).
Curated 2026-07-26 from a ~610-pattern capture of asciiart.eu (kn86-ascii workbench); the §5 data/sheet family was selected 2026-07-27 in the kn86-ambercalc workbench; artist credits ride inside each sampled piece and are never stripped. Pieces marked (drawn) are original KN-86 work.
1. The slot model
Section titled “1. The slot model”A house style is not a pile of art — it is a set of named slots, each filled by one pattern. Screens compose from slots, never from the raw palette. The palette (the workbench) holds alternates; promotion into a slot is a design decision.
| Slot | Purpose |
|---|---|
frame/hero | Full-screen ceremony — title, board masthead |
frame/panel | The workhorse content border |
frame/inset | Light sub-panel / card |
frame/title-tab | Label embedded in a panel’s top edge |
junction/tee | How an interior divider meets the frame edge |
divider/major | Multi-row section break |
divider/minor | One-row rule |
fill/sparse fill/medium fill/dense | One motif at three densities — the amber intensity ramp |
accent/set | Single-cell furniture: bullet, selector, gauge ticks, end-caps |
icon/tile | Multi-cell pictorial mark (7x3 cells) for program / subject identity |
Three styles are defined so far. Deck chrome (the runtime’s own voice) is quiet and rectilinear; icebreaker is the first cart house style; wire (§4) is the first program house style. The rule that lets them coexist on one device: chrome is text, house styles are display. Identity moments (titles, mastheads, ceremony) take the house style; dense working panels take chrome.
2. Deck chrome (system style)
Section titled “2. Deck chrome (system style)”Straight lines only, drawn from the KN-86 Code Page’s box/block regions
(character-set.md §2 — byte constants like KN86_BOX_H 0x80, KN86_BLOCK_FULL 0xA2,
shades 0xA5–0xA7).
| Slot | Piece |
|---|---|
frame/hairline | Box-drawing light set (┌─┐│└┘) — dense data screens |
frame/emphasis | Box-drawing double set (╔═╗║╚╝) — modals, focus |
frame/alert | Block frame (█▀▄) — alerts, interrupts |
frame/utility | ASCII dot-dash box (.--. / '--') — degraded/log surfaces |
divider/minor | ─ rule; +- tiled variant |
divider/major | ═ double rule |
fill/texture | ---+---+ grid, ___ ruled lines, .--. brick |
accent/set | ► selector (0x0C), ♦ marker (0x04), ▲▼ (0x09/0x0A) scroll hints, device icons 0x10–0x13 |
3. Icebreaker house kit (v1)
Section titled “3. Icebreaker house kit (v1)”One vocabulary throughout: the /\ diagonal. Everything below is pure ASCII except the
♦ accent (0x04).
frame/hero — ornate diamond (sampled, edge unit repeats every 4 cols)
Section titled “frame/hero — ornate diamond (sampled, edge unit repeats every 4 cols)” /\ /\ /\ /\ /\ /\ /\ /\//\\//\\//\\//\\//\\//\\//\\//\\\\//\\//\\//\\//\\//\\//\\//\\////\\ \/ \/ \/ \/ \/ \/ //\\\\// \\// \/ \/frame/panel — tight weave (sampled, 2×2 unit, tiles to any size)
Section titled “frame/panel — tight weave (sampled, 2×2 unit, tiles to any size)”/\/\/\/\/\/\/\/\/\/\/\/\\/\/\/\/\/\/\/\/\/\/\/\//\ /\\/ \//\/\/\/\/\/\/\/\/\/\/\/\\/\/\/\/\/\/\/\/\/\/\/\/frame/inset (drawn) — hairline, <> corners, 1×1 edges
Section titled “frame/inset (drawn) — hairline, <> corners, 1×1 edges”<>----------------<>| || |<>----------------<>frame/title-tab (drawn) — label replaces top-edge weave units
Section titled “frame/title-tab (drawn) — label replaces top-edge weave units”/\/\[ CONTRACT ]/\/\/\/\/\/\/\/\\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/Label slot must consume a whole number of /\ units (even char count including
brackets); pad the label with spaces to fit.
junction/tee (drawn) — interior divider butts the frame with <> caps
Section titled “junction/tee (drawn) — interior divider butts the frame with <> caps”/\ /\\/<>--------------<>\//\ /\Dividers
Section titled “Dividers”minor: <><><><><><><><><><> (also >< , <+> , <*> , <<>> , \\// variants)
major: ______________________________________ /\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\ \/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/
major-alt (6-col unit): ____ ____ ____ ____ ____ ____ /\ \/\ \/\ \/\ \/\ \/\ \ / \___\ \___\ \___\ \___\ \___\ \___\ \ / / / / / / / / / / / / \/___/\/___/\/___/\/___/\/___/\/___/Fill ramp — one motif, three brightness levels
Section titled “Fill ramp — one motif, three brightness levels”sparse (dim): medium: dense (bright): X X X X / \/ \/ \/ \ /__\/__\/__\/ \/ \/ \/ \ \_/\_/\_/\_/ \ /\ /\ /\ /\ /\ /\ / / \/ \/ \/ \ \/ \/ \/ X X X X \_/\_/\_/\_/ /\ /\ /\Density of lit pixels per cell is the deck’s brightness axis (see the light-value ramp
in the workbench guide). Use the ramp steps as background states — idle/ambient/active.
Animated fills ride the soft-glyph style per animation.md.
accent/set (drawn)
Section titled “accent/set (drawn)”bullet: ♦ item selector: ♦> ACCEPT CONTRACTticks: |-♦--♦--♦--| end caps: <>------- -------<>inline: -♦- <*> ><♦ is 0x04. The icebreaker skin swaps chrome’s ► selector for ♦> and chrome’s ─
rules for the <> family.
Kit gaps, known
Section titled “Kit gaps, known”Tiling caveat: the hero’s 4-col unit and panel’s 2-col unit both divide 128; the major-alt’s 6-col unit does not (last repeat truncates — end the row with its cap).
4. Wire house kit (v1) — the recon cluster
Section titled “4. Wire house kit (v1) — the recon cluster”The shared house style for the recon-cluster programs: bzbx (probe the network)
and CONDUIT (ride one host) first, the rest of the toolkit as they land.
Implementation: ui/kit-wire.lsp.
This kit invents nothing. It promotes §6’s network-map language (─ link, ═ trunk,
├┤┬┴┼ junctions, [host] (store) {ice} nodes, ♦ operator) from a map component
into house furniture. Deck chrome draws ─ as a rule; the wire kit draws ─ as a
wire, so every divider terminates in a junction or a node. Every glyph is already in
font.c; every piece rides a renderer that already exists in ui/pattern.lsp or
ui/frames.lsp.
One kit, two poses. The shared slots carry both programs. Each pose adds only what
its own verb needs: bzbx enumerates (state per target), CONDUIT connects (direction per
line). Both put their meaning in the same leading-glyph column (the
ui-design-language.md §4 attention channel), which is
what makes the two programs read as one toolkit.
| Slot | Piece | Rides |
|---|---|---|
frame/panel | chrome’s hairline box, deliberately | ui/panel |
frame/hero | double rail carrying nodes | ui/cbox + ui/net-node |
junction/tee | ├───┤, real junctions into the frame | ui/net-junction |
divider/minor | link run with ┬ taps | ui/net-link-h |
divider/major | trunk with junction caps + ╬ midspan | ui/net-link-h |
fill/sparse⋅medium⋅dense | the link lattice at three densities | ui/pattern-fill |
accent/set | node classes + state + direction | ui/net-node, glyph codes |
frame/panel — the quiet box, with honest junctions
Section titled “frame/panel — the quiet box, with honest junctions”These are dense working surfaces (a ranked capture table, a session transcript), and §1 gives those the quiet frame. The kit shows up where an interior divider meets the frame:
┌───[ CAPTURE ]────────────────────┐│ │├──────────────────┬───────────────┤ junction/tee: ├ ─── ┤│ │ │└──────────────────────────────────┘frame/hero — the panel sits on the network
Section titled “frame/hero — the panel sits on the network”╔═[GW-01]═══╦═══[RELAY-7]═══╦═══[CORE]═══╗║ ║ ║ ║║ (VAULT)─────────{ICE} ║╚════════════════════════════════════════╝Nodes stamp opaque onto the top rail, so they sit on the trunk. ui/wire-hero takes
(col class label) triples; the screen places them, since a declarative panel has no
topology to know about.
Dividers
Section titled “Dividers”minor (drops mark branch points): ──────┬───────────┬───────────┬──────
major (trunk, capped, ╬ midspan): ├════════════╬════════════════┤Fill ramp — the link lattice, three densities
Section titled “Fill ramp — the link lattice, three densities”sparse (open field) medium (mapped lattice) dense (saturated grid)─ ─ ─ ─ ─ ─┼───┼───┼───┼───┼── ═╬═══╬═══╬═══╬═══╬══ │ │ │ │ │ ║ ║ ║ ║ ║One motif at three densities, per §3’s rule. 4-col unit, so it divides 128 and stays in phase across the full grid. Spaces are transparent, so the sparse step composes over whatever is underneath.
accent/set — the shared vocabulary
Section titled “accent/set — the shared vocabulary”node class: [HOST] host / gateway (STORE) datastore {ICE} countermeasurestate: ● up / responding ○ down / no answer ▒ filtered ♦ revealeddirection: ► outbound (you sent) ◄ inbound (it answered)Codes: ● 0x05, ○ 0x06, ▒ 0xA6, ♦ 0x04, ► 0x0C, ◄ 0x0B. All were already in
font.c; only ◄ needed a name in ui/glyphs.lsp, alongside the double-junction set
╠╣╦╩╬ (0x91–0x95) the trunk dividers and lattice fill use.
bzbx pose — enumerate and identify
Section titled “bzbx pose — enumerate and identify”The port strip is bzbx’s motif. Selected pieces #26 and #550 are the same motif at
different spacings; #26’s |_||_| unit is 3 cols and does not divide 128, so the kit
takes #550’s 2-col |_|_| form and #26 becomes the frame built from it.
port strip (divider): port frame (rails, plain sides): _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_|_|_|_|_|_|_|_|_ |_|_|_|_|_|_|_|_ | | |_ _ _ _ _ _ _ _|Open ports hang off a host’s own wire. Closed and filtered ports have no drop; absence is the encoding:
[fin-relay-07]──┬────┬──────┬──┬──────────┬──────── 22 80 443 8080 9100Target state rides the leading-glyph column, which ui/list already accepts as its
leading-glyph-fn. Node-class brackets carry kind; the gutter carries state:
● [fin-relay-07] 10.0.7.14 ssh up / responding○ [------------] 10.0.7.15 --- down / no answer▒ [core-ledger ] 10.0.7.31 ftp filtered♦ [gw-01 ] 10.0.7.1 telnet revealed → DOSSIERCONDUIT pose — be on the box
Section titled “CONDUIT pose — be on the box”CONDUIT is the client, so its hero is the connection it holds, and session state is the link’s state:
on ♦════════════════════════►[fin-relay-07] solid trunk, arriveddialing ♦═════════════════····► [fin-relay-07] trailing off, not there yetauth ♦═════════════════════║ [fin-relay-07] stopped at a wallclosed ♦──────────────────── [fin-relay-07] thin line, nothing at the endA shell has one visual rhythm: what you sent, and what came back. That is the same leading-glyph column bzbx uses:
● session open: fin-relay-07 (ssh)► cat /etc/route.conf◄ gateway 10.0.7.1♦ finding: routes-to core-ledger○ session closedThe prompt line is ui/field, which already draws a caret.
Screen DSL
Section titled “Screen DSL”panel, divider, and fill take (kit wire). Panel slots: hero, ports, default
panel. Divider kinds: major, ports, default minor. fill keeps icebreaker as its
default kit, since fill predates the kit attr and existing screens depend on it.
Kit gaps, known
Section titled “Kit gaps, known”frame/inset and frame/title-tab are inherited from chrome rather than skinned; the
hairline box and its title cutout already read correctly at this weight. The pose heroes
(ui/wire-hero with rail nodes, ui/wire-link) are called by screens directly, since
neither has a meaningful declarative form.
Provenance (kn86-ascii workbench ids): port strip #550, port frame #26, scan-as-map hero #662, host-state gutter #663, ports-as-taps #664 — all selected. Shared frames, dividers, and fill ramp #657–#661, drawn.
4b. icon/tile: multi-cell program marks
Section titled “4b. icon/tile: multi-cell program marks”A slot for pictorial identity where a single glyph is too small and spending a font byte is
unwarranted. A tile is 7 columns x 3 rows of cells (56x24 px), composed entirely from codes that
already exist in the Code Page. Because the mark is multi-cell, it needs no new font bytes: the
reserved single-cell icon range (0x14–0x1F, character-set.md §9.2) stays unspent no matter how
many tiles get drawn.
First consumer: the PROGS launcher’s ICON view (ADR-0059,
progs-launcher.md §5). Set locked 2026-07-27.
Construction rules
Section titled “Construction rules”- 7 x 3 cells, fixed. Every tile in a set is the same size.
- Existing glyphs only: box
0x80–0x90, vertical ramp0x96–0x9C, half and full blocks0xA0–0xA4, shades0xA5–0xA7, symbols0x04–0x0F, ASCII. Diagonals (U+2571/2572) do not exist in this font; use ASCII/and\. - Depict the subject’s artifact, the thing it operates on: a grid, a key, a tree, an envelope, a file card, a waveform. One consistent basis is what makes a set cohere; without it the marks read as unrelated doodles.
- Watch lit-cell weight across the set. A full-bleed tile (21 of 21 cells lit) reads brighter than a sparse one and pulls the eye. Where a set mixes both, give every tile the same background well so the container carries the rhythm and the interior does the distinguishing.
- Spaces are transparent.
- The label sits beneath, centred on the tile’s axis. Names longer than the grid pitch wrap to a second centred row.
- Selection inverts the label row and flips the label to black. A tile cell owns no other full-pitch band, and selection is inversion everywhere else in the system (§4).
The PROGS set (14, A-Z)
Section titled “The PROGS set (14, A-Z)” ┌┬┬┬┬┬┐ ┌─┬─┬─┐ ┌─────┐ ┌──┐ ├┼█┼┼┼┤ │▒│░│▓│ ■═════■ │□□□□□│ │ └──┐ └┴┴┴┴┴┘ └─┴─┴─┘ └─────┘ └─────┘ AMBERCALC bzbx CONDUIT DECK HUB DOSSIER
○─┬─┐ ┌─────┐ ► ▐██ ┌─┬───┐ │ │ │\___/│ λ(▒)█ ► ▐██ │├│▒▒▒│ ▀ ▀ └─────┘ ► ▐██ └┴┴───┘ KEYRING kn9 knEmacs knSALK KOMMANDER
┌███┐ ┌─────┐ ▄▄▄▄▄▄▄ ▁▃▅▇▅▃▁ │───│ │ >_ │ ███████ ─────── └───┘ └─────┘ /\/\/\/ ▁▂▃▄▅▆▇ MISSION REPL RIPSAW WAVAMPSTER BOARDEach mark is its program’s artifact: the sheet’s grid with an active cell, three shaded applets, two linked hosts, empty loadout slots, a filed folder, a keyring, an envelope, a form with point in it, traffic stopping at a wall, a tree beside a pane, a clipboard, a shell prompt, a saw blade (the name), a level meter.
Known tension in this set. DECK HUB, kn9 and REPL share an identical ┌─────┐ outer frame and
differ only across five interior cells, so at 24 px the frame stops carrying information for those
three. Lit weight also spans 5 cells (knEmacs) to 21 (seven tiles). Rule 4’s uniform well is the
remedy that keeps every mark as drawn.
data/kv-line
Section titled “data/kv-line”ui/kv-line returns one dot-leader row as a string (KEY ....... VALUE, value
right-aligned to the field) instead of drawing it. ui/kv draws with it; callers that
need the row as text — a ui/list-row entry, a selectable readout — share the exact
leader arithmetic instead of re-deriving it.
media/transport
Section titled “media/transport”► PLAYING COLD TRANSIT state line — ui/transport-line▌ PAUSED paused■ STOPPED stopped
┌────┐ ┌────┐ ┌────┐ ┌────┐ ┌────┐│ ◄◄ │ │ ► │ │ ▌▌ │ │ ■ │ │ ►► │ button rack — ui/transport-rack└────┘ └────┘ └────┘ └────┘ └────┘ CONS INFO INFO BACK LINKTransport state is the identity channel: read it from the leading glyph, never from colour. The rack’s active button inverts (the §4 selection channel), so one glance gives both the binding and the state. Key labels sit under their buttons because the deck has no dedicated transport keys. Buttons are 6 cells wide on a 7-cell pitch, 4 rows tall including the label row.
media/needle
Section titled “media/needle”0:00 ──────────●──────────────── 0:03 ui/needle-trackProgress as a needle (● 0x05) riding a rule (─ 0x80). The quiet counterpart to
data/meter: no fill, no density, one row. ui/needle-bar is the bare span;
ui/needle-track brackets it with pre-formatted clock strings. Clamped at both ends;
max <= 0 parks the needle at the left.
Use the needle when the magnitude is position in a span (playback, scrub, seek) and
data/meter when it is level (load, charge, signal). The distinction matters
because a needle reads as “where am I” and a filled bar reads as “how much”.
4c. knamp house kit (v1)
Section titled “4c. knamp house kit (v1)”WavAmpster’s visual identity, implemented in ui/kit-knamp.lsp. Selected in the
workbench 2026-07-27.
This kit is deliberately light. The selection pass took the decorative pieces and
the hardware sprites, and rejected every waveform, staff, and note vocabulary (the
sine/pulse/square rules, the carrier-wave borders, the tuner dial). The structural
slots stay empty on purpose: WavAmpster’s working panels are deck chrome
(ui/panel), and the kit supplies identity only. Two of the three role labels Josh
assigned say it outright: frame/decor, divider/flourish.
| Slot | Filled by | Function |
|---|---|---|
frame/decor | colon band (#20) | ui/knamp-decor, ui/knamp-decor-rule |
divider/flourish-minor | scallop (#603) | ui/knamp-flourish-minor |
divider/flourish-major | arcs over groove (#605) | ui/knamp-flourish-major |
accent/tuned | tower + play (0x15, 0x0C) | ui/knamp-tuned |
accent/mark | operator mark (#233) | ui/knamp-mark |
sprite/cassette | compact cassette (#640) | ui/knamp-cassette |
sprite/boombox | boombox face (#641) | ui/knamp-boombox |
frame/panel frame/inset frame/title-tab junction/tee fill/* | (unfilled — deck chrome serves these) |
frame/decor — the colon band (#20)
Section titled “frame/decor — the colon band (#20)”:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::The masthead. Two solid colon rows over and under a hollow interior; the title stamps opaque through the interior row. The unit is 2 cells, so any even span stays in phase (128 divides cleanly).
divider/flourish-minor — the scallop (#603)
Section titled “divider/flourish-minor — the scallop (#603)” .-.-. .-.-. .-.-. .-.-. / / \ \ / / \ \ / / \ \ / / \ \`-' `-`-' `-`-' `-`-' `-8-cell unit, 3 rows. 128 divides by 8, so a full-width span is in phase.
divider/flourish-major — arcs over a groove (#605)
Section titled “divider/flourish-major — arcs over a groove (#605)” .--. .--. .--.:::::.\:::::::::.\:::::::::.\:::' `--' `--' `--'10-cell unit, 3 rows. 128 is not a multiple of 10, so a full-width span clips mid-unit at the right edge. Size the span to a multiple of 10 where phase matters; the colon groove row hides the clip well otherwise.
Sprites
Section titled “Sprites”ui/knamp-cassette (21×5) is the library identity piece; ui/knamp-boombox (20×7) is
the empty-dial art. Both draw transparently (spaces leave cells untouched), so they
compose over a fill.
Kit gaps, accepted
Section titled “Kit gaps, accepted”No fill/* ramp: nothing in the selected pool carried a density motif, and
WavAmpster’s panels are chrome-bordered with empty interiors. If a textured background
is wanted later, it goes through the workbench first.
5. Data display components
Section titled “5. Data display components”Chrome-flavored by default; house styles reskin selector/rules/gauge ticks only.
data/list
Section titled “data/list” CONTRACTS AVAILABLE──────────────────────────► BREACH THE VAULT 3d TRACE THE COURIER 1d SILENT AUDIT 5d────────────────────────── 3 OPEN · 2 LOCKED► = 0x0C. Right-aligned meta column; hairline rules above/below the scroll region.
data/table
Section titled “data/table”NODE CLASS HEAT ICE─────────────────────────GW-01 gate ▓▓░ yesVAULT-2 store ░░░ noWhitespace columns, no │ rules — alignment does the work at 8×8. A ▓░ cell is a
micro-meter; any column may be one.
data/kv — dot-leader readout
Section titled “data/kv — dot-leader readout”OPERATOR ......... KESTRELCREDITS .......... 12,405REPUTATION ....... TRUSTEDdata/meter
Section titled “data/meter”Three forms, all built on glyphs that already exist (character-set.md §9):
INTEGRITY [██████████ ] 66% bracketed bar — 0xA2 fill, blank empty (ui/meter)TRACE █████▊░░░ 78% fine bar — sub-cell eighths, §9.5 recipeHEAT ▓▓▓▓▓░░░░░ HIGH unbracketed ambient stripCALIBRATE |-♦--♦--♦--| icebreaker tick-rail skinThe fine-bar recipe (full blocks + one partial 0xA8–0xAE glyph + shade padding) gives
a 16-cell bar 128 distinct positions — smooth enough to animate during a run.
data/spark
Section titled “data/spark”NET LOAD ▂▃▅▇█▆▃▁▂▄▆▇▅▃▂▁ bar sparkline — vertical ramp 0x96–0x9D, §9.5 recipePING 1h ░░▒▒▓█▓▒░░▒▓██▓▒ shade-run alternative (4 levels)QUIET .:-=+*#*+=-:. pure-ASCII density run (7 levels)One char per sample, scroll left, newest sample rightmost (bold via invert attribute). Empty buckets render as space, not the zero-bar.
data/sheet
Section titled “data/sheet”The furniture a columnar spreadsheet surface needs and the slots above have no place
for. Implemented in ui/sheet.lsp; selected slot by slot in
the kn86-ascii sibling workbench (kn86-ambercalc, port 7781) on 2026-07-27, where every
candidate was the real screen with exactly one thing changed. AmberCalc is the first
consumer; Black Ledger’s register lens is the next.
┌─[ AMBERCALC ]────────────────────────────────────────────────┐│@ ■1 ►2 ¤3 4 5 │ <- inverted│ 1│ 2087-03-11 Shell:Cay:~ $12,405 cleared TX-8801 ││ 2│ 2087-03-14 Shell:Cay:~ ($3,200) held TX-8814 ││ 3│ 2087-03-19 Trust:Car:~ ($900) cleared TX-8822 ││ 4│ ────────── ││ 5│ TOTAL ♦$8,305 │ <- cursor row│ │ ══════════ ││ EMPTY WORLD ││ ┌─[ @5$3 ]─────────────────────────────┐ ││ │ (sum (range @1$3 @3$3))█ │ ││ └──────────────────────────────────────┘ │└──────────────────────────────────────────────────────────────┘| Slot | Piece | Bytes |
|---|---|---|
sheet/header-band | one unbroken inverted slab over gutter + columns, carrying grid column numbers so a scrolled window reads $6 $7 rather than renumbering | inversion |
sheet/gutter | row number flush right against a rule, so 9 and 10 line up | │ 0x81 |
sheet/cell-cursor | inverted cell and inverted row number — both ends of a crosshair, no ink between | inversion |
sheet/col-rule | none: whitespace and alignment do the work | — |
sheet/type-sigil | a distinct glyph per column type; :acct is a real badge, not a blank | ¤ 0x0E, ■ 0x07, ► 0x0C, # |
sheet/numeric-align | currency right-aligns to the column edge | — |
sheet/negative | accounting parens — at 8×8 a leading - is one lit row and reads as noise | ( ) |
sheet/total-rule | single rule above an aggregate, double below | ─ 0x80, ═ 0x8B |
sheet/formula-mark | a formula’s value leads with the diamond | ♦ 0x04 |
sheet/composer | framed strip, coordinate as a title tab, block caret — entry reads as a mode | ┌┐└┘│─, █ 0xA2 |
sheet/col-width | fixed pitch, truncation marked so the operator knows the value continues | ~ 0x7E |
sheet/overflow-ticker | the resting cell reads itself out | — |
sheet/column-viewport | the window follows the cursor; cues where populated grid continues | ◄►▲▼ 0x0B/0x0C/0x09/0x0A |
Geometry is an argument, never a constant. Sheet components take a pixel origin plus a scale, with widths in characters — unlike the rest of the kit, which is cell-addressed at scale 1. A sheet is a mixed-scale surface (AmberCalc draws its body at scale 2 so 16px glyphs survive a downscaled recording) and cell-at-scale-1 cannot express that.
The ticker holds at the head for 4 frames, scrolls one character per frame to the tail,
holds, then snaps back — at 250 ms/frame, the 4 chars/sec the CIPHER-LINE OLED driver
already uses for its own row overflow (hosts/device/firmware/pico2/src/oled_layout.c,
compute_ticker_window). One ticker rule on both displays. A value that fits is
returned whole and never moves; the ticker is armed only by overflow, which is that
driver’s ticker_active rule. Drawing it is animation.md’s glyph-cycle
style (a per-cell glyph choice per frame), not soft-glyph — one cell row, so ~11 glyph
writes a frame on the idle timer.
The viewport moves only when the cursor would leave it: stepping off the left/top pulls
the window to the cursor, stepping off the right/bottom pulls it so the cursor is the last
visible line. Edge cues key off the populated extent of the grid, never off (cell-cols)
/ (cell-rows-usable) — the grid is addressable to 128×73, so cueing against the maximum
promises “more this way” on every row of an empty sheet.
Two glyph traps, both of which draw a blank cell if you walk into them: there is no
ellipsis anywhere in the Code Page (U+2026 is unmapped), and 0xFA — CP437’s · — is
all-zeros in font.c. Hence ~ as the truncation marker. Build any glyph ≥ 0x80 from its
code via (char->string CODE), which is byte-exact; a literal ─ in Lisp source is
stored as multi-byte UTF-8 and render_text draws each byte as a separate glyph.
Palette alternates (judged, not promoted): a per-column-chip header, underlined names, and name-over-coordinate for the header band; ruler ticks in the gutter; hairline column rules; OLED-rule wrap and ping-pong for the ticker; freeze-first-column and page-by-screenful for the viewport.
6. Network maps
Section titled “6. Network maps”Node class is encoded by bracket shape — readable at any density, no legend needed after first exposure:
[GW-01] host / gateway {ICE} countermeasure(VAULT) datastore ♦ operator positionTrunk style (orthogonal, CP437 box edges — the generatable form):
[GW-01]──┬──[RELAY-7]══[CORE] │ │ (VAULT)────{ICE}───┘── link, ══ trunk/backbone, ┬ ┘ ├ junctions. Generated topologies (World Engine)
snap nodes to a coarse grid and route edges Manhattan-style so this renders with pure
cell writes.
Freeform style (authored screens only — diagonals allowed):
[GW-01] / \ {fw-1} (VAULT) | | [RELAY-7]---{ICE!} | ♦Animated edges: for live topology (pulse traveling a link during a trace), draw the
same grid-snapped layout with render/half-block-line strokes instead of box glyphs —
the maps-doc overlay approach; node vocabulary unchanged. Animate the lookup, not the
pixels.
7. CIPHER-LINE (the auxiliary panel)
Section titled “7. CIPHER-LINE (the auxiliary panel)”The 256×64 auxiliary display carries its own slot decisions, settled 2026-07-27 in the
kn86-aux workbench against the real oled.c render path and the real kn86_font.
It is deck chrome only, because the panel is the runtime’s own voice, so cart house styles
do not reach it.
7.1 Geometry: 32×8 at 8×8
Section titled “7.1 Geometry: 32×8 at 8×8”The panel renders design-system surfaces on a 32-column × 8-row grid at a strict 8×8 cell. The 8×16 tier (four logical rows, each glyph sampled twice vertically) is not used for these surfaces.
Two reasons, both observed on glass:
- A two-row frame or a pair of rules costs 25% of the panel at 8×8 and 50% at 8×16. Only 8×8 leaves room for chrome and four lines of content.
- The icons (§7.2) are 8×8 art. On the 8×16 tier every glyph row is drawn twice, so the battery nub doubles and the signal bars smear. Icons only read at 8×8.
This supersedes the four-row logical carving in
ADR-0015§2 for design-system surfaces. The row semantics are unchanged (status, CIPHER current, CIPHER echo, contextual); they now occupy named cell rows (§7.3) instead of four 16-pixel bands. ADR-0015’s panel geometry (32 cells × 8 rows at 8×8 native) is unchanged; only the carving moves.
7.2 Icons: the Code Page set
Section titled “7.2 Icons: the Code Page set”0x10–0x13, defined in character-set.md §9.2
and reserved there for inline UI markers. No new art was drawn.
| Byte | Icon | Use on the panel |
|---|---|---|
0x10 | CARTRIDGE | Loaded cart, before its name |
0x11 | BATTERY | Charge readout, before the gauge |
0x12 | SIGNAL | Link quality, before the level |
0x13 | PADLOCK | Marks an encrypted value (the seed line) |
Icons replace their words (BAT: SIG: CART:), which frees ~9 of 32 cells. That
saving is what buys the mission timer a place on the strip.
7.3 The standing layout
Section titled “7.3 The standing layout”| Cell row | Content | Owner |
|---|---|---|
| 0 | Status strip (§7.4) | runtime |
| 1 | divider/minor: ─ (0x80) tiled full width | runtime |
| 2 | blank | — |
| 3 | CIPHER current utterance | CIPHER engine |
| 4 | CIPHER previous echo | CIPHER engine |
| 5 | blank | — |
| 6 | divider/minor | runtime |
| 7 | Contextual line (the oled_row4.c claim stack) | claimant |
B[███▊] S4 C ICE T+12:04 TERM────────────────────────────────
> ICE TRACE CLEAN. LINK STABLE. FLOOR LOW.
────────────────────────────────L 4F2A910C LAB 00:17Icon placeholders above: B = 0x11 BATTERY, S = 0x12 SIGNAL,
C = 0x10 CARTRIDGE, L = 0x13 PADLOCK. Each occupies one cell; the icons have no
Unicode equivalent, so they are written by byte throughout this section.
7.4 Slots
Section titled “7.4 Slots”| Slot | Piece |
|---|---|
aux/geometry | 32×8 at 8×8 |
aux/divider/minor | ─ (0x80) tiled full width, cell rows 1 and 6 |
aux/icon/set | 0x10–0x13 (§7.2) |
aux/icon/battery | 0x11 + a bracketed bar: B[███▊] |
aux/meter | Bracketed bar + exact percent: TRACE [██████▍░░░] 66% |
aux/row4/mission | Trace gauge + countdown, right-aligned: TRACE [███▎░░░░] 42% T-01:38 |
aux/hero/clock | HH:MM:SS at scale 4, full width, nothing else |
aux/hero/splash | KINOSHITA at scale 2 over <>--- KN-86 // DECKLINE ---<> |
7.5 The bracket rule
Section titled “7.5 The bracket rule”A fill needs a boundary glyph at this scale. A bare run of full blocks (0xA2)
reads as one lit slab. At any charge above ~75% the level stops being legible, because
there is no edge to measure it against. Every gauge on this panel is bracketed:
B[███▊] battery, bracketed readsB ███▊ battery, bare slabTRACE [██████▍░░░] 66% readsThe bracket also does the labelling work that the freed cells paid for: [ and ] cost
2 cells and remove any doubt about where the gauge starts and ends.
Gauges use the fine-bar recipe from character-set.md §9.5 (full blocks 0xA2 plus one
partial 0xA8–0xAE plus light-shade 0xA5 padding), so a 4-cell bar has 32 distinct
positions and slides smoothly rather than stepping.
7.6 Full-screen modes
Section titled “7.6 Full-screen modes”Modes claim the whole panel through the oled/ mode manager and paint with the pixel
tier, so they are not bound to the cell grid.
- Clock.
HH:MM:SSat scale 4. Eight glyphs × 32 px spans exactly 256 px. No furniture: a full-screen mode is ceremony, and chrome only crowds it. - Boot splash.
KINOSHITAat scale 2, with<>--- KN-86 // DECKLINE ---<>beneath. The<>caps are the accent family from §3, the one place the panel borrows a house gesture, used here because the splash is an identity moment.
8. Other house kits (seeded, not yet v1)
Section titled “8. Other house kits (seeded, not yet v1)”The workbench holds curated palettes awaiting slot promotion: depthcharge (waves/sonar), blackledger (ledger rules, columns, medallions), neongrid (skyline, traffic, arrows), snake (serpentine, scales), tunnel-rat (mice, tunnels), attract (fractals + the fireworks/starfield/galaxy animation recipes). Each becomes a §3-style section when its cart enters design.
First-party programs take kits too, and they share rather than one-per-program: the deck would stop reading as one device at thirteen vocabularies. §4’s wire kit covers the whole recon cluster (bzbx, CONDUIT, and RIPSAW / Kommander / Keyring / kn9 as they enter design), with each program adding only an accent pose over the shared slots.
9. Provenance
Section titled “9. Provenance”Sampled pieces: asciiart.eu, captured 2026-07-26; embedded artist initials preserved
(e.g. gfj/98 in the cross-stitch sampler), credit fields in the workbench db.
Drawn pieces: original. The workbench (kn86-ascii, port 7797) remains the palette
browser and the place new candidates get judged before entering this document.