/.metanomicon design system
/.metanomicon 0.000
#00  the doctrine, hung as cloth verlet · 10 passes · seed = the text

/.metanomicon

the design system one bit · two faces · five tokens

Section 00 hangs above as cloth — one character of the doctrine to a cell, on a grid that answers the pointer and settles again on its own. The mark stands behind it, and shows through the weave.

· cells carry one line of the doctrine dormant

This is the canon for every surface that claims the mark — the shipped scroll surface, static pieces, design canvases, artifacts, decks, documents — and for every agent or person producing one, whatever tool the design arrives from.

The system is small and strict on purpose. Good integration work is mapping into these rules, not inventing alongside them. Part I is portable and holds anywhere the brand appears. Part II binds it to the repository. Part III is the integration appendix, one section per design source. Every rule ships with its reason — a rule without one is obeyed until the first inconvenience.

0

Product context

A design system that never states who it serves quietly becomes the strategy. These are the facts the design has to serve; every rule after this one is accountable to them, and a rule that stops serving them should be deleted rather than defended.

who uses itAgents and operators building surfaces for the organisation — rarely the same one twice, often with no prior exposure to the brand. The reader is usually mid-task.
audience
the taskProduce a surface that is recognisably of this organisation on the first attempt, without a review cycle to correct drift.
job
what it governsA holding layer above every namespace: marketing surfaces, applications, documentation, canvases, artifacts, print. Not one product — the container of them.
surface
constraintsOffline-capable (fonts bundled, backgrounds procedural). Desktop-first, degrading honestly. Two typefaces, licence-clean. No component kit, no icon library, no build step a static page cannot perform.
technical
what it must never becomeA skin. If a surface reads as this brand only because the colours were copied, the system has failed — the character has to survive being described in words.
the line

The constraint ladder — the working method, in order

Product contextWhat the system must serve. Above.
References supply vocabulary, never identityA reference design is research material. Handing one to an agent unchanged hands over another product's assumptions with it.
A reviewed contract constrains implementationThis document — short enough that a person actually reads it.
One representative surface tests the constraintsAgainst real content, interaction, accessibility and a narrow viewport. A rule that fails there fails everywhere; fix the system before spreading it across ten screens.
The agent gets a bounded buildNamed surface, real content, existing components, required states, validation criteria — and judgment stays with a person.
The constraints are re-checked by script, not by memoryRungs 1–5 are the method; this one is why it holds. Every defect this canon has shipped was a rule everybody believed. Section 16.

Rungs 1–5 restate Joshua Guo's sequence in DESIGN.md Is a Starting Point, Not a Design System; rung 6 is this canon's addition.

The north star. A dotfile is hidden by convention, not by lock: present to anyone who knows to look. The system renders that idea literally — a ground you have to attend to before it resolves, instrumentation that shows its own workings, and exactly one thing alive on the screen at a time. It fits because this layer is infrastructure: it should feel measured and legible rather than persuasive, since nothing here is being sold.

Conformance — the DESIGN.md nine, plus three

The canon lives at the repository root as DESIGN.md, under the conventional name, so an agent looking for one finds it rather than inferring a system from the code. It carries the nine sections of the Stitch format in that order, so an agent trained on the format can navigate it without being told.

#DESIGN.md sectionHere
1Visual theme & atmosphere§00 Doctrine
2Colour palette & roles§01 Colour
3Typography rules§02 Typography
4Component stylings§03 Components
5Layout principles§04 Space & layout
6Depth & elevation§05 Elevation
7Do's and don'ts§11 Guardrails
8Responsive behaviour§10 Responsive
9Agent prompt guide§14 Agent quick reference
+Product context§0 above
+Accessibility§15 Accessibility
+Code mapping§14 & Part II
++Evidence & negative space§16 Evidence
++The constraint ladder§0 above

The last five rows are not in the nine. Three come from Joshua Guo's argument that a borrowed DESIGN.md is research material rather than implementation instructions — and the sections he adds are exactly the ones the format omits. Conforming to a structure means inheriting its blind spots; those three were this canon's, and adding them found four real defects rather than four missing paragraphs.

The last two come from the wider corpus around that article, where every technical note names what it did not establish — a reference file is not a design system, a routed model is not automatically compatible, a successful demo is not a benchmark. Section 16 applies that discipline to a design system, and the constraint ladder above names the method the rest of this document is the output of. They are the two additions that changed how this document is read rather than what it contains.

The nine are otherwise the floor, not the ceiling. Sections 06–09 and 13 are this canon's own: a system whose background is an algorithm, whose imagery passes a dither gate, and whose extension surface is exactly five tokens cannot be described by the nine alone.

00

Doctrine

Seven laws. Everything else in this document is their consequence — when a rule below and a law above disagree, the law wins and the rule is a bug.

  1. 01

    The dot is the through-line

    /. at the meta layer — the dot hides, as it does in a dotfile. [[. ]] at the vessel layer — the dot lives. Same glyph, two functions; the lineage is carried in the punctuation. Every mark contains a period.

  2. 02

    Grey is a lie told by dots

    The native depth is one bit. A mid-tone is a density of marks, never a shade. Where a surface goes continuous — the solid field — the grain moves into the objects standing on it rather than disappearing.

  3. 03

    Essence marks the dot and live elements only

    Never a fill, never a background, never a border. If it is not alive, it is not cyan.

  4. 04

    Sigil is instrumentation

    Lines and labels — evidence about the work, never the work. Crimson annotates; it does not speak.

  5. 05

    Chromatic split is a ghost

    Remove the red and cyan channels and the text must still read. The solid core carries the message; the ghosts carry only velocity.

  6. 06

    Two faces, no third

    The meta layer speaks in a neutral grotesque, because the container of all brands must not itself look branded. The system layer speaks in the pixel mono.

  7. 07

    Heartbeats and sweeps

    Nothing bounces. The pointer perturbs a field, it never drives one. Every animated surface ships a real reduced-motion state that is static and correct, not degraded.

Atmosphere. Dense, instrumented, unlit. The ground is near-black and the type sits directly on it; there is no card-on-grey softening and no glow that is not a live element. Surfaces read as measurement apparatus — ruled, ticked, labelled in tracked monospace — rather than as marketing. Restraint is the house style: one bold move per view, everything around it quiet.

01

Colour

Seven values, two of them reserved. A colour arriving from any design source maps to the nearest token or is rejected — new hexes, gradient stops and shadows are never imported.

void#050505The dark ground. Raised planes at #0a0a0b and #111113.
paper#f2f0e9The light ground; ink on it is #0b0b0c. A design that only survives on black is not finished.
signal#e6e6e6Text on void. On paper it becomes #14141a. Hierarchy is opacity, never weight.
essence#00f0ffReserved. The dot and live elements only — shown here at its true size. Deep teal #056a75 on paper.
sigil#c2333dReserved. Instrumentation lines and labels — shown here as the hairline it is.
split & witness255,55,55 · 60,220,230Red leads, cyan trails, the witness core holds. Ghosts never carry meaning alone.

Hierarchy is the opacity ladder — never a new grey, never a heavier weight

o-4 is the floor for text. Below it the ladder is for borders, hairlines and disabled states only — o-5 measures 3.19:1 against void and o-6 measures 1.88:1, so a 10px label set there is not dim, it is unreadable. Section 15 carries the computed table.

Status is brightness, not hue. [OK] sits at o-3, [WARN] at o-2, [FAIL] at o-1 — urgency ascends with brightness, and all three sit above the contrast floor. A red failure state would collide with the sigil reservation and read as annotation.

Field tinting is the one sanctioned colour field: the substrate may tint its cells cyan-led, shifting crimson-ward with depth, the channels mixed by a slow spatial mask. It never exceeds roughly half saturation toward the witness core — past that the field starts competing with the type it exists to carry.

02

Typography

Geist carries the meta layer; Departure Mono carries the system layer. Both are bundled with the page, never fetched from a font host — the offline guarantee is doctrine, and a silent fallback is a brand failure nobody notices.

Geist · meta layer400 / 500 — no other weights
We do not build tools. We build the conditions under which better tools become inevitable.

The face-switch is this system's italic. An accent word inside a Geist heading is set in Departure at about 0.85em — never in italics, never in colour. The two words above are the mechanism, not a description of it.

Departure Mono · system layersingle weight
ns.resolve  signal  state=readable  at=0.41
the format of formats root canon observe · decide · record [OK]
The scaleclamp() throughout — no fixed hero

heroclamp(4rem, 15vw, 317px)

sectionTwo faces, no third

body13–16px at 1.6–1.75 leading, measure near 65 characters

labeldeparture 9–11px, tracked .14em–.32em

03

Components

There is no component kit, and the canon does not import one. Everything below is derived from the laws, not borrowed — every state is a consequence of sections 00 through 02. A component that needs a new colour or a new radius is a signal that the design is wrong, not that the canon is short. These are live: focus them, type in the field.

buttons · three ranks, no fourthnever an essence or sigil fill

Nothing translates on press — the fill moves instead, because nothing bounces. Focus draws a sigil outline: instrumentation marking the live target. A loading button pulses its label on the canonical beat rather than spinning.

inputs · the caret is the live elementerrors by brightness, never hue
Focus it. The caret is cyan — a caret is the one live thing in a form, and the only place essence belongs there.
[FAIL]  a mark must contain a period
the state tableo-n = the opacity ladder
RankRestHoverFocusActiveLoadingErrorDisabled
primarysignal fill, void textfill to #fff1px sigil outline, offset 2pxfill to o-2label pulses on the beat[FAIL] beside, at o-1o-6, no pointer
secondary1px border o-7, text o-2border o-5, text o-1as aboveborder o-4as aboveas aboveo-6
ghosttext o-3, no bordertext o-1as abovetext o-4as aboveas aboveo-6

Plates and cards sit on void-2 with a 1px border and 6–8px sigil corner ticks, and butt against each other on a 1px rule rather than floating apart on shadow. Navigation is the pill — the only earned radius in the system. Tables take a void-3 header, 1px row rules and tabular numerals, and never zebra stripes: the rules already do that work, and striping invents a grey. Status is bracketed and encoded by brightness — no badges, no chips.

04

Space & layout

Base unit 4px, on the ramp 4 · 8 · 12 · 16 · 24 · 32 · 48 · 72 · 96. Sibling groups are laid out with flex or grid and gap, never with per-element margins that collapse or double. Content caps at 1180px; prose measure runs 62–70 characters. Corners are square. Radius must be earned, and so far only pill controls have earned it — which is why every plate on this page is notched rather than softened. The rule governs containers and controls: a mark is not a box, and the marks in this system have always been circles — the lattice draws arcs, and so does the Bayer plate in section 08.

05

Elevation

There are no shadows. A shadow implies a light source, and this ground has none. Depth is carried by three things instead.

voidThe ground. Type sits directly on it.
#050505
void-2Plates and cards. One step, not a card-on-grey softening.
#0a0a0b
void-3Insets — code, table headers, input fields.
#111113

Three steps, no fourth. Beyond the ladder, planes are separated by a hairline at o-7 or o-8 — an edge, not a blur — and by blur over a live field only, which is the glass panel. Glass reads as depth precisely because the field behind it is moving; over a flat colour it is decoration.

The stacking map — fixed layers on the shipped surface

100
navnothing floats above it
20
panelglass, only over a live field
10
herochar-split type
07
platesdithered bitmaps
05
signal bandscroll-scrubbed destruction
00
fieldthe substrate, always

New layers claim a gap, and a layer that cannot name its gap does not ship. Nothing floats above nav.

06

Motion

One curve governs everything alive: sin⁴(t · 1.55) — sharp systole, long diastole. It is plotted below at its real speed, with the dot riding it. Ease elsewhere is cubic-bezier(0,0,.2,1) or a linear scrub. No elastic, no overshoot, no bounce.

the canonical pulse · beat 1.6s · sweep 10s · budget ≤7ms/frame at 1440×900

Scroll is a scrubber. It advances a process — field time, destruction, revelation — rather than triggering fire-and-forget tweens. That is why the readout in the rail is a coordinate and not a progress bar: position in the work, not distance to the end.

07

Iconography

There is no icon set, and none may be added. No icon library, no emoji, no exported vectors. The complete vocabulary is below; icons arriving from any source are replaced with a glyph or dropped. A home icon becomes the mark, a close button becomes a multiplication sign, and the index control on this page at narrow widths is a hash. A glyph joins this vocabulary only once both faces are confirmed to carry it — verified, not assumed. The index mark was ⌧ until the font was actually measured and found not to have it, at which point the button rendered a tofu box.

/.meta mark
[[. ]]vessel mark
direction
·separator
interval
#index
×dismiss
┌─┐structure
[OK]status · o-3
[WARN]status · o-2
[FAIL]status · o-1
08

Imagery — the dither gate

Bitmaps do not ship raw. Photographic material passes through the ordered dither: Rec.709 luma against a Bayer-8 threshold, lit cells in a channel tint, unlit cells transparent so the ground breathes through. No grey survives the crossing — what looks like tone below is density. This is a real product photograph from the HORCRX #001 vessel set, not a procedural gradient, because the easy case proves nothing.

sourcerec.709 luma · 8-bit
bayer 4×4ordered · 16 thresholds
bayer 8×8ordered · the canon's gate
floyd–steinbergerror diffusion · serial
1.12

Open and close the gate. The canon runs at 1.12 — below it the mid-tones starve and the subject falls out of the ground; above it they clot and the dither stops carrying tone at all.

Why ordered, and not the better-looking one. Floyd–Steinberg renders a photograph more faithfully — it carries quantisation error forward, so it holds detail an ordered matrix throws away. The canon still chooses Bayer, and the reason is not aesthetic: ordered dithering is deterministic, stateless and tileable. The same input gives the same output, every cell can be computed without knowing any other, and a region can be rendered alone and still match its neighbours. Error diffusion is serial — its result depends on the order pixels are visited, it cannot be tiled, resumed, or evaluated per-cell on a GPU, and two crops of one image will not agree at the seam.

That is the same seed discipline the substrate runs on: same input, same climate, always. A gate that produced a slightly different image each time it ran would be prettier and wrong.

The operator itself — the 8×8 Bayer threshold matrix

Recursively generated, never a stored table: M(2n) = 4·M(n) + [0 2 / 3 1]. Each cell is drawn at the density its own threshold represents, so the matrix is its own legend — a lit cell is one whose luma beat the number written on it.

Dither buffers render at an integer cell scale and upscale with image-rendering: pixelated. A scaled dither is a blur, and a blurred dither is just a bad photograph — the canvas bitmap must match its CSS box or the whole argument collapses.

09

The generative substrate

The background is not an image, it is an algorithm, and its settled ratios are tokens as binding as the hexes. The field at the top of this page is that algorithm running live; it is reproducible from its seed and nothing else.

ParameterSettled valueWhy this value
lattice pitch8pxTighter and the mid-tones clot; wider and they starve.
radiuspow(f, 1.35) × 0.62 × pitchThe response curve that keeps a mid-tone reading as a mid-tone.
shaping(f − 0.18) / 0.72Contrast window; clips the dead ends of the noise range.
domain warpweather 1.9 · warp 1.05 × 2.4Two stages. Lower goes flat, higher muddies.
disagreement|df| > 0.10Warm leads a rising contour, cold trails a falling one.
revelation gatepow(r, 1.8) × 0.55 × (0.30 + 0.85f)The climate admits the latent stratum unevenly rather than printing it.
peak legibilityscroll 0.41One depth where the buried layer is readable; destruction scales with distance from it.
living dotsexactly 1Beats on the canonical pulse. Never accumulates into the record.

Same seed, same climate, always. A field captured to an image is a citation, not an asset — it must be labelled with its seed and parameters so an implementation can reproduce it live instead of shipping the screenshot.

the lattice, given a third axis

The substrate of this system is flat: one bit deep, eight pixels to a cell, a climate of marks. This plate is the solid that lattice is a slice of — thirteen unit spheres in cuboctahedral close pack. One at the centre, twelve touching it, which is the most that can touch it. Six of the twelve share the centre's plane, and that ring of six around one is the flower of life.

One key light, no fill. The primary hit is solved rather than marched, the creases are darkened by a four-tap distance field, and the result passes the same Bayer-8 gate the imagery does. Nothing on the plate is grey. Every mid-tone is a density of marks, as it is everywhere else here.

THIRTEEN SPHERES · CLOSE PACK θ ---.-°
CELL 4 PX GATE BAYER 8 BUFFER --- FRAME --- [LIVE]

One fragment per cell. The drawing buffer is not the pixel grid; it is the dither grid, upscaled with image-rendering: pixelated. Ordered dithering asks each cell whether its luminance clears a fixed threshold, and if several pixels inside one cell each answer from their own slightly different luminance, the cell boils. Rendering at the cell makes the answer singular. It also pays for the third dimension: at a four-pixel pitch the renderer runs on a sixteenth of the pixels, and on a 2× display a sixty-fourth.

Eighty-four seconds per revolution. Shimmer scales with how fast luminance crosses a threshold that is standing still. There are sixty-four Bayer levels; at this rate a point on the surface crosses one roughly every nineteen frames rather than every frame. The slow register is the canon's anyway — a climate, not a plasma — so the fix and the law are the same rule.

The dark patches are sampled in object space. They are a noise field read on the local surface normal, before the rotation is applied, so a patch belongs to its sphere and turns with it. Reading the same field from the fragment coordinate instead is the copy-paste that makes a rotating sphere crawl: the threshold would stand still while the value under it moved. Their two cut-offs, 0.6532 and 0.5934, are the 85th and 72nd percentiles of this exact noise measured over 312,000 points on the sphere. The flat lattice's own figures, 0.600 and 0.555, belong to a different hash: against this distribution they sit near the 72nd and 60th percentiles, so inheriting them would have put more than a quarter of every sphere into the deep step instead of the intended sixth.

Warm leads, cold trails. The substrate tints its cells by the sign of the climate's gradient; the same law applies here, and here it is exact rather than sampled. The angular velocity is known, so whether a point is turning into the light or out of it is a dot product, not an estimate. The tint is confined to the terminator and capped at half saturation, because away from the terminator nothing is changing state and a colour there would be decoration.

The pointer bends the light; it does not aim it. The key light has its own drift on a sixty-one second cycle and the plate is complete with no pointer at all. Where a pointer is present it adds a bounded deflection on the profile x(1−x)² — zero directly under the cursor, peaking in a ring, dead at 220 pixels. Zero at the centre is the point: a peak under the cursor is a spotlight, and a spotlight has a direction singularity.

The cyan dot marks the sphere you cannot see. The centre of a close pack is enclosed by its twelve neighbours from every direction; no ray reaches it. The dot is drawn last, over the gate, beating on sin⁴(t·1.55). It is the only cyan on the plate and the only thing here that is not a measurement of the surface.

On the flower of life. The construction is compass and straightedge: equal circles centred on a hexagonal lattice. It carries a long ornamental and occult history, and in sacred-geometry literature it is read as a claim about how the world is put together. Nothing here reads it that way. It is in this canon for a mechanical reason — hexagonal close packing is the densest arrangement of equal spheres, and the flat ring of six around one is that solid's shadow along its own axis. Press 7 · flat to remove the two capping layers and the shadow is what is left. The plate demonstrates the geometry. It is a procedure with a reason, not evidence for anything.

QuantityValueStatusEstablished by
centre spacing1.90 rassertedspheres interpenetrate, so the joins read as creases
layer height1.5513 rderivedS·√(2/3), face-centred cubic
occlusion p85 / p720.6532 / 0.5934measured312,000 samples of this fbm on the unit sphere
bayer-8 in shader64 / 64 exactmeasuredcompared against the repository's bayerMatrix(8)
revolution84 sderivedone Bayer level crossed per ~19 frames
cell pitch4 → 8 pxmeasuredthe plate coarsens the cell if it cannot hold the interval
rays per cell13 + 13 + 52derivedprimary, penumbra, four distance-field taps

the ephemeris seed

The field is reproducible from its seed, which is a promise worth very little while the seed is a constant somebody typed. This one is derived: the date, the phase of the moon, the planetary hour and the lunar mansion over a fixed point on the prime meridian, hashed to thirty-two bits and handed to the noise function as a domain offset. Same date, same seed, same climate, on any machine. The field now has a calendar.

reading the sky

field · date · seed · pitch 8 · v1.0 — the citation Part III asks for; ?date= in the address opens this page at any day

+0

Forty-five days either side of now, one day a step. The buttons move whole hours, because the planetary hour is the one input that changes inside a day — the moon needs a week to say anything new.

the field at this seed seed —
domain offset from the seed · the living dot is the moon
phase
figure six bits · read bottom to top

The chain, every step of it — the same table goes to the console on each derivation

StepValueWhere it comes from

Every getter is UTC, and that is not a preference. Swap one of them for a local-time getter and the same instant hashes differently in Berlin and in Denver — the page still runs, it simply stops agreeing with itself across machines. Reproducibility that disagrees with itself is not reproducibility.

The location is fixed, stated, and not yours. Planetary hours are twelfths of the actual daylight, so they need a sunrise, and a sunrise needs a place. Asking for the viewer's location would make the seed a property of the viewer rather than of the date, which is the law this section exists to keep. So the observer stands at 51.4779° N, 0.0015° W — the Royal Observatory, where UTC already points — and the polar failure case, where the sunrise equation returns no root at all, never arises.

Accurate to the day and to the minute, which is not the same as precise. The moon's longitude is Meeus's low-order series truncated to its six largest periodic terms: about a third of a degree, inside a mansion twelve degrees wide, so the index is right even though the longitude is not ephemeris-grade. Sunrise is the NOAA equation, good to about a minute. The synodic month is the IAU mean value, 29.530588861 days, and the true one varies by half a day across a cycle. There is no VSOP87 here, no ELP2000, no nutation and no aberration.

This is a procedure with a reason, not a claim about the world. Nothing here predicts anything, and the section makes no argument that it could. What the tradition supplies is a parameter list: several real astronomical quantities that are periodic, computable from a date alone, and uncorrelated with each other — the moon's phase turns over in a month, the planetary hour in a fifth of a day, the mansion in a day, the year in a year. That is precisely what a seed wants. The arithmetic underneath is ordinary: a Julian day number, six sine terms, a division into twelfths, and FNV-1a.

Names, never glyphs, and an index with no name. Departure Mono was measured and does not carry the planetary symbols, so the hours are spelled out; a later pass that improves them back into symbols will render seven tofu boxes. The mansion is given as a number out of twenty-eight and left unnamed, because the three traditions that count twenty-eight of them disagree about which is which, and this system does not borrow authority it has not earned.

D · the king wen dither — the received order as a threshold matrix

The ephemeris argues that a six-bit figure's trigram coordinates are its address in the 8×8 Bayer matrix: three bits of row, three of column, built by the same recursive halving. If that is true, the sixty-four thresholds can be re-ordered by any other complete ordering of the sixty-four figures without moving a single figure out of its cell. The received sequence is such an ordering. Below, each cell's threshold is that figure's position in it — one to sixty-four — instead of its rank in the construction. Same sixty-four numbers, same sixty-four addresses, one arrangement built and one inherited.

The prediction was written before the run: the received order will clump, because Bayer's recurrence exists to spread thresholds evenly across every 2×2 and 4×4 sub-block and a sequence assembled by pairing figures under inversion has no such property. Both panels run the same photograph, the same luma, the same gain. The numbers under them are the test.

bayer 8×8constructed · recursive halving
king wen 8×8received · sequence position
1.12

Both panels move together; the gain is shared so the comparison stays honest at every opening of the gate. Source luma is read back from the gate’s own source plate above, at the 8-bit precision that plate stores — so both panels here argue about one photograph at one precision, and the residual disagreement with the gate’s own float thresholding is printed rather than claimed away.

The two operators — same addresses, different numbers

bayer · rank in the construction

king wen · position in the sequence

Row is the upper trigram, column the lower, each three bits with the bottom line as bit 0 — so the figure drawn in the right-hand cell is the address it sits at, and the left-hand cell at the same coordinates holds the same figure. Every mark is a density: the radius carries the threshold on the response curve the lattice uses, and no cell is filled with a tone.

What is borrowed and what is declined. What is borrowed is a permutation of sixty-four six-bit words that people spent three thousand years arranging, and one structural fact about it: consecutive pairs are joined by turning the figure upside down, and where a figure is unchanged by turning — there are eight of those, one for each choice of upper-half lines — the pair is joined by swapping every line instead. That is checkable, and it is checked. What is declined is everything else. No name, no judgement, no reading, no correspondence is attached to any figure here; the sequence is used as an ordering and nothing more, because the system does not borrow authority it has not earned.

Why the comparison is fair. Both matrices are bijections from the sixty-four cells onto the numbers 0–63, so at any gain the two panels put very nearly the same quantity of ink on the page — the lit-cell counts are printed so that can be checked rather than assumed. The statistics run over an aligned 168×120 sub-region, divisible by four (the measurement window) and by eight (the matrix tile), so neither matrix is charged for a partial tile at the bottom edge. The residual variance subtracts the local target density from the local lit density: a dark region is sparse under any matrix, and that is the photograph's doing, not the ordering's.

Why ordered, still. This changes nothing about the canon's gate. King Wen is as deterministic, stateless and tileable as Bayer — that is what makes it a legitimate rival and not a curiosity. It loses on the measurement, and the measurement is the reason to keep Bayer, which is a better reason than the one the section had before: that the recurrence is elegant.

09 · e — the almanac

A year of weather at one bit per day. Every day of the UTC year is derived at 12:00 by the same routine that seeds the field, its patch of the climate is sampled at 288 points, and the warm-minus-cold balance the tide gives it is drawn as one dithered phase disc. Weeks run across, days run down, Monday first. Nothing here is a forecast and nothing is a judgement — it is the same procedure, run three hundred and sixty-five times, printed.

disc 0 cold-led · 1 warm-led

The disc is window.MN_phaseDisc, the primitive §09 already ships, at twelve cells. The lit fraction is the day's balance; the terminator is a real ellipse; every cell is one Bayer-8 decision. There is no grey in the grid because there is no grey anywhere — what reads as a mid-tone is a count of marks.

§09 caps that primitive at three uses and says the fourth turns it into decoration. The cap counts instruments, not calls: the rail is one use however many discs it steps through, and the almanac is one instrument — a single grid, read as a grid, whose cell happens to be the disc. It is the fourth instrument and the last one this page is allowed. What §09 forbids is the disc appearing as an ornament beside something that did not need it; a calendar whose only mark is a lit fraction is the opposite case.

Three statistics were prototyped and all three were drawn. Moon illumination is the control: it is a 29.53-day cosine by construction, so bands are guaranteed and carry nothing the ephemeris has not already said. The field's mean density at the day's offset carries the page's own climate, but the seed is an FNV-1a hash, so consecutive days land in unrelated parts of the noise domain — measured lag-1 autocorrelation −0.009 and, drawn, a column-to-column contrast of 1.66 lit cells against the control's 21.34. That is a calendar of static. The balance keeps the lunation — lag-29 autocorrelation 0.904 on the lit-cell counts against the control's 0.913 — and adds the terrain: 13.8% of its variation survives regressing out illumination, and it paints 52 distinguishable disc states against the control's 51. It is the only one of the three that is a calendar of this page rather than of the sky alone.

The cursor is the ephemeris's own date, moved by the ephemeris's own controls. It is drawn as a one-cell ring stepped by Bresenham rather than a stroked arc, because a stroked arc antialiases and antialiasing is grey. The ring is sigil, opaque, and the same whether the date is today or one the reader travelled to: instrumentation is sigil, and the page's essence budget is one dot, which the field is already spending. Today is said in words — the [today] bracket in the readout, and the canvas's accessible name — because status is text before it is colour.

The whole year is derived once, at mount, from window.MN_derive, and the grid is sized to the year: ceil((offset + days) / 7) columns, which is 53 most years and 54 for a leap year starting on a Sunday. The grid is painted once into an offscreen canvas and blitted when the cursor moves. Nothing here animates, so there is no loop to start and prefers-reduced-motion has nothing to switch off: the reduced picture and the default picture are the same picture.

09 · g — the figure, played

The six-bit figure is six one-bit pulse trains, one per line: a solid line plays its train whole, a broken line plays half of it, and the gap you can see in the drawn line is a gap you hear. The tempo is the planetary hour — the pattern is sixty-four steps because there are sixty-four figures, and it passes sixty-four times inside the hour, so one step is one four-thousand-and-ninety-sixth of an hour that is not sixty minutes long. Nothing is audible here that is not already printed on this page, and nothing plays until you ask for it. No name and no judgement is attached to any figure: it is a procedure with a reason, not a claim about the world.

no audio node exists

Six trains from one counter. The step counter runs 0 to 63 and line i is bit i of it, counting from the bottom line up — so each line is a square wave one octave under the line below it, and the strip is a binary counter you can read. The figure decides what happens to each train: a solid line plays it whole, thirty-two steps of sixty-four; a broken line drops the second pulse of every pair, sixteen of sixty-four. The top line is the exception, and it is stated rather than fudged: inside a sixty-four-step pattern its train is one unbroken block of thirty-two, so there is no pair to drop. It halves that one block instead — the same sixteen of sixty-four, the gap in the middle. Every line's density is halved by a break and no line borrows a bit from another. The two kinds of line differ in density and in nothing else, which is the substrate's own law — a mid-tone is a count of marks — applied to time instead of to space.

The tempo is the hour, and the hour is not an hour. A planetary hour is a twelfth of the daylight or a twelfth of the night, so it is sixty minutes twice a year and never in between. MN_derive(now).hourLengthMin supplies it and the step is that divided by 4096. The observer is the ephemeris's own fixed point — the Royal Observatory, 51.4779°N, in UTC — and it is never the reader's location, because a tempo that followed the reader would make the piece a property of the reader rather than of the date. Over 2026 that hour runs from 36.85 to 83.17 minutes, so the step runs from 539.8 to 1218.2 milliseconds: a longer hour is a longer step, so the piece is 2.26 times faster on a midsummer night than on a midsummer afternoon, and the same figure is a different tempo every hour of the year. Measured over 730 hours in evidence.md.

A one-bit stream carries a tone by pulse density. The sounding lines are combined by exclusive-or into a single bit per sample — plus one, minus one, or zero where no line sounds — and that bit goes through a gentle low-pass. There is no oscillator bank and no level: the filter is what turns a count of pulses into a pitch, exactly as a count of marks turns into a tone on the page. The fundamental is the lunar mansion, which divides one octave from 55 Hz as it divides the ecliptic into twenty-eight, and the lines take its first six harmonics. Underneath, a square an octave below the fundamental is opened and closed by the canonical pulse, sin⁴(t·1.55) — the thump is generated one bit too, and the low-pass is the only thing that makes it round.

Nothing exists before the gesture. No AudioContext, no worklet module, no node is constructed until listen is pressed; pressing it again ramps the master down, disconnects every node and closes the context, and the readout says so. An AudioWorklet is used where one is available and a ScriptProcessor where it is not; both run the same generator function, stringified into the worklet module from the same source the strip is drawn from, so a mark and a pulse cannot drift apart. Output is gain-staged to peak below −18 dBFS and measured there, because a page that makes a sound the reader did not ask for at a level they did not choose has taken something.

The cursor is a line, so it is sigil. It marks a position in a printed record. It is instrumentation and it is not alive; the page's one living dot belongs to the field, and a second cyan would be a second claim. You do not start the piece either — the cursor opens where the planetary hour already stands, and pressing listen joins an hour in progress. Under prefers-reduced-motion the strip is drawn once, at t = 3.0, and held: the whole pattern is legible in that one frame, the audio still plays, and nothing moves.

10

Responsive

Hero and section type scale with clamp() and need no breakpoint. The four below exist for structure, not for size — which is why the rail you are reading beside simply leaves at lg rather than reflowing into the column.

BreakpointWidthWhat changes
sm640pxSingle column; plates lose their cap row's right slot.
md900pxNav pills collapse to the mark plus a menu control.
lg1080pxThe instrumentation rail appears.
xl1440pxReference width — canvases and captures are authored here.

Touch targets are 44px minimum; pill controls already clear it, ghost buttons need padding to reach it. The canon surface is desktop-first, and static plates and canvas artboards are fixed-size pieces that do not respond — they paginate or scale as a whole.

Canvases resize by re-deriving their bitmap from the CSS box, never by stretching. Cell-based work — dither, lattice — keeps its pitch in CSS pixels and scales it by device pixel ratio, so density is the same on every screen.

11

Guardrails

The scannable version. Everything here is stated with its reason somewhere above; this is where an agent checks its work, and where a review reports each violation against the law it breaks.

do
  • Map every incoming colour to a token, or reject it.
  • Use the opacity ladder for hierarchy.
  • Set the accent word in the other face.
  • Make backgrounds procedural and reproducible from a seed.
  • Put the grain in the objects when the ground goes continuous.
  • Ship the reduced-motion state in the same commit as the motion.
  • Give every rule its reason.
don't
  • Fill anything with essence or sigil.
  • Introduce a third typeface, a fifth weight, or a new grey.
  • Round a corner that isn't a pill control.
  • Add a shadow, an icon set, or a gradient that is not the hero veil.
  • Encode status in hue.
  • Ship a raw photograph, or upscale a dither.
  • Animate with bounce, elastic, or overshoot.
  • Let a chromatic ghost carry meaning on its own.
  • Override anything outside the five namespace tokens.
12

Voice

The canon states constraints; the namespaces have voices. Sentence case in prose, lowercase or tracked uppercase in chrome, no marketing verbs about one's own work — and every rule ships with its reason, because a rule without one is obeyed until the first inconvenience.

13

Extending — the namespace contract

A child brand overrides exactly five tokens and nothing else, ever. Substrates, the opacity ladder, spacing, motion timing, the dither doctrine and the split channels are inherited and not overridable. An extension point that can change anything is not an extension point, it is a rewrite.

live namespace override rank · root
#00 · source of truth: this package

Everything you see change is one of five tokens. Everything you see hold — the ground, the ladder, the plate's notched corners, the tracking on this label — is the canon, and is not on offer.



      

Two edits register a namespace: a [data-ns] block appended to the token layer, and a row in the registry. No third. A design that needs more than five tokens is a fork, and a fork needs a conversation rather than a token.

14

Agent quick reference

Paste-ready — if a value is not here, it is not a token, and inventing one is the drift this document exists to prevent.

This block is a mirror, not the source. Inside the repository the canonical token layer is public/tokens.css, and code should point at it rather than copy from here — a design document that restates tokens has invented a second source of truth and will disagree with the code within a month. The block exists for surfaces that have no token layer to point at: artifacts, canvases, a deck, a page in someone else's stack.

:root{
  color-scheme:dark;
  --void:#050505; --void-2:#0a0a0b; --void-3:#111113;
  --paper:#f2f0e9; --ink:#0b0b0c;
  --signal:230,230,230;          /* rgba(var(--signal), <ladder>) */
  --essence:#00f0ff;             /* the dot & live elements ONLY */
  --sigil:#c2333d;               /* instrumentation lines & labels ONLY */
  --witness:226,228,230;
  --split-r:255,55,55; --split-c:60,220,230;
  --o-1:1.00; --o-2:.85; --o-3:.70; --o-4:.55;
  --o-5:.40; --o-6:.25; --o-7:.15; --o-8:.08;
  --font-meta:"Geist",ui-sans-serif,system-ui,sans-serif;
  --font-system:"Departure","SF Mono","Courier New",monospace;
  --beat:1.6s; --sweep:10s; --ease:cubic-bezier(0,0,.2,1);
  --ns-name:"metanomicon"; --ns-accent:var(--essence);
  --ns-sigil:var(--sigil);  --ns-mark:"/."; --ns-face:var(--font-meta);
}

Prompts that work

build a surface Follow DESIGN.md. Void ground, Geist for prose and Departure for all labels and data, hierarchy by the opacity ladder only. Square corners. No icons — typographic glyphs. Essence only on live elements, sigil only on instrumentation. Procedural background, no image. Ship the reduced-motion state.
translate an incoming design Map every fill and stroke to a DESIGN.md token or reject it; replace foreign fonts with the two faces; icons become glyphs; photos go through the dither gate; rounded corners become square plus a border; rewrite the copy into the voice in VOICE.md.
review Check this against DESIGN.md section 11 and report each violation with the law it breaks.

The three-question check — for anything claiming the mark

01

Does it contain a period?

02

Could you remove the chromatic ghosts and still read it?

03

Is the only cyan thing on screen alive?

15

Accessibility

A system built on an opacity ladder over near-black has to know where that ladder stops being legible. It was measured, not estimated — and the measurement moved three rules.

The ladder against #050505 — WCAG 2.1 contrast, computed

RungAlphaCompositeRatioLegal for
o-11.00rgb(230)16.33anything
o-20.85rgb(196)11.69anything
o-30.70rgb(163)8.08anything — body prose sits here
o-40.55rgb(129)5.23the floor for text — all labels
o-50.40rgb(95)3.19UI borders and large type only
o-60.25rgb(61)1.88non-text only — and disabled states
o-70.15rgb(39)1.36hairlines
o-80.08rgb(23)1.14hairlines

o-4 is the floor for text. This canon previously set labels at o-5 and chrome at o-6, which is 3.19:1 and 1.88:1 — below the 4.5:1 threshold at the 9–11px sizes labels actually use. Every label on this page has been lifted to o-4 or above. o-5 through o-8 remain in the ladder because borders, hairlines and disabled states legitimately live there; they are simply not text.

Sigil is never dimmed, and never a sole carrier. #c2333d on void is 3.72:1 — enough for a UI element or large type, not for small body text, and at the 0.85 opacity this canon used it fell to 2.94:1. Sigil text now renders at full opacity, and because it is instrumentation it always sits beside the thing it annotates rather than carrying the meaning alone.

The status ladder ran backwards. It assigned [FAIL] the dimmest rung — the most urgent state rendered least legibly, at 1.88:1. Urgency now ascends with brightness: [OK] at o-3, [WARN] at o-2, [FAIL] at o-1.

Reserved colours clear their bars. Essence is 14.47:1 and split-cyan 12.20:1 against void; split-red is 5.68:1. On paper, ink is 17.25:1 and the deep teal essence 5.54:1 — which is why essence shifts hue between substrates rather than keeping its cyan.

Focus, keyboard, targets. Every interactive element takes a visible :focus-visible state — a 1px sigil outline at 2px offset, which is instrumentation marking the live target rather than a new colour. Tab order follows document order; the instrumentation rail is a real <nav> and its entries are anchors. Interactive targets are 44px minimum: measured, not assumed — the pill controls on this page were 33px until that measurement was actually taken.

Motion. prefers-reduced-motion yields a static, correct page: the lattice renders one frame with the living dot held at t=3.0, and the pulse plot draws the same curve without advancing. Nothing is merely slowed.

One sanctioned gradient. Section 11 forbids gradient stops, and the hero veil is one — so the rule needed the carve-out rather than the design needing a change. Type set over a live field cannot rely on a flat contrast measurement, because the ground moves underneath it; the veil is a legibility device carrying no colour and no decoration, and it is the only gradient in the system. Anything else claiming the same exemption is decoration.

16

Evidence

Every rule here ships with its reason. That is not the same as shipping with its evidence, and the difference is where this canon has been wrong. The 44px touch target, the U+2317 index glyph, the o-5 label, the namespace generalisation — all four were reasoned, plausible, written down, believed, and false. None survived being measured.

So every load-bearing claim carries a status. Status is set in weight and opacity, never in hue — section 01 leaves no room for a green pass and a red fail.

measured

A number a script in this repository produces. The script is named.

derived

Computed from another rule rather than chosen — the 18% sigil lift, for instance.

asserted

A deliberate choice. No measurement is possible or wanted — but it is marked, so nobody mistakes taste for evidence.

inherited

Comes from outside: WCAG, a font licence, the host.

falsified

Was asserted, tested, found false, and the rule changed. Kept visible, because a canon that hides its corrections invites them again.

untested

Stated and never verified. The honest default, and the most common status in any design system that has not looked.

The ledger

ClaimStatusEstablished by
Opacity ladder; o-4 floor for textmeasuredcontrast-audit.mjs
sigil-text = sigil +18% → 5.00:1derivedcontrast-audit.mjs
Reserved colours clear their bars, both substratesmeasuredcontrast-audit.mjs
Glyph vocabulary present in both facesmeasuredcoverage probe
Two faces; weights 400/500; square corners; no iconsmeasuredreview.mjs
≤7ms/framemeasuredreview.mjs — desktop, software GL
Reduced motion static and correctmeasuredreview.mjs
44px targets; no h-scroll 390–1440measuredreview.mjs
Namespace contract holds across the registrymeasurednamespace-check.mjs + document-scope render
Namespace contract holds for any legal namespacefalsifiedsame run — floors added to §13
WCAG thresholds; SIL OFL; prefers-reduced-motioninherited
The dot lineage; two faces; square corners; essence reservedasserteddoctrine, §00
Dither gate on real photographsmeasured§08 runs one live, against three other algorithms
Any surface in paper modeuntestedratios computed; nothing ships on paper
Print: 12pt floor, paginationuntestednothing has been printed
Peak legibility at scroll 0.41untested hereinherited from the shipped surface
Frame budget on real mobile siliconderivedno longer asserted — the field measures its own frame interval and degrades

What this canon has not established

Naming the negative space is the practice this canon took from the V2SPACE corpus, where every technical note states what it did not show — a reference file is not a design system, a routed model is not automatically compatible, a successful demo is not a benchmark.

That it works on paper. The paper substrate is specified and its contrast computed; no surface has been built on it. Treat paper as designed, not proven.
That it survives print. No plate has left a screen.
That it is fast on a phone. Still not measured on real mobile silicon — but no longer asserted either: the field now measures its own frame interval and gives up resolution rather than frames. The claim moved from untested to self-correcting, which is not the same as proven.
That an agent using it produces conforming work. The rules are checkable; whether an unfamiliar agent given only this document lands in the brand has not been trialled. That is the whole purpose, and it is the least evidenced claim here.
That the character survives being described in words. Part 0's own line for what this must never become. Untestable as written, which makes it an aspiration rather than a rule.
II

This repository

Branch proposal/optical-canon of chipoto69/metanomicon. React 19, Vite 7, Tailwind v4 and GSAP 3 — ScrollTrigger and ScrollToPlugin only. No router, no state library, no component kit, no second animation library.

src/            the shipped surface
  App.tsx         fixed layers over a 500vh scroll container
  components/     ScrollField · MoshScrub · VesselPlates
                  ScrollFloat · GlassPanel · PillNav
  canon/          gl.js · dither.js · chroma.js · sigil.js
  index.css       Tailwind v4 @theme (token mirror)
public/         tokens.css (canonical) · fonts/ · vessels/
                lib/ · preview/ (the living component docs)
brandkit/       Claude Design canvas sources
artifact/       design-system.src.html · build.mjs (fonts inlined)
VOICE.md · REGISTRY.md · SKILL.md · DESIGN.md (this document)

Tokens live twice. public/tokens.css is canonical; the @theme block in src/index.css is the Tailwind mirror. When they disagree, fix the mirror. There is no tailwind.config file and none should be added.

Build on src/canon/, never reimplement. A dither or split effect that bypasses the shared library is drift; extend the library instead. New techniques get a public/preview/ piece first — those files are the component documentation, and there is no Storybook.

The scroll map is the feature organisation. On page progress 0–1: the hero flies out over 0→0.25, the signal band lives 0.16–0.66 and is readable at 0.41, vessel plates hold 0.60–0.88, the panel rises 0.875→1. A new beat claims a window and clears it before the next beat owns the frame.

Known traps, each of which has already cost a session: a canvas bitmap must match its CSS box; inset:0 does not stretch a canvas, because a canvas is a replaced element and resolves to its intrinsic 300×150; naive large-integer hashing silently biases noise thresholds; pixel-sorting text produces no streaks without a directional smear, because glyphs give short runs. All GSAP work goes inside gsap.context() with ctx.revert() — StrictMode double-mounts.

III

Integration appendix

Five sources, one destination. In every case the mapping runs one way: the incoming design is translated into the canon, and never the other way around.

source

Figma, via MCP

Map every fill and stroke to a token or reject it. Foreign fonts are replaced, not embedded. Icons become glyphs; photographs go through the dither gate; rounded corners become square plus a border. A Figma background is a reference for field parameters, not an asset — backgrounds ship procedural. Copy is rewritten into the voice.

source

Claude Design canvases

Canvases are mockups; the contract board carrying the settled ratios is the implementation spec. Backgrounds on canvases should be captures from the real algorithm, marked with seed and parameters so the implementation reproduces them live. Artboards embed both faces as data URIs.

source

Claude artifacts

Commit to the void substrate as a single deliberate theme: paint the background and every colour explicitly rather than depending on the viewer's. Bundle Departure as a data URI; Geist may come from Google Fonts where a host admits only that. Respect the icon and colour law exactly — an artifact is a brand surface, not an exception. Interactive pieces keep the seed discipline.

source

Documents, decks, print

The paper substrate is first-class, not a fallback: ink #0b0b0c on #f2f0e9, with essence going deep teal at #056a75 to survive the ground. Plates are fixed single pages; flowing documents paginate. A 12pt body floor for print, and the dither gate still governs imagery.

source

Code from any agent

Read SKILL.md first. Obey the scroll map, the depth map and the frame budget. Ship the reduced-motion state. Verify in a real browser before handover — two frames apart to prove the motion is live, and zero console errors.

Keeping it alive

This document changes when the design decisions change — not after every screenshot, and never as a frozen moodboard. It needs enough detail to constrain an implementation and it has to stay short enough for a person to review, which are in tension, and the tiebreaker is the reason: if nobody here can explain why a rule exists, it does not belong, and an agent will not honour it either. That is also the deletion test. Rules leave this document the same way they arrive.

Three documents, three jobs, and they should not absorb each other. This is the visual contract. SKILL.md explains how to work in the repository — build steps, traps, conventions. Product requirements say what has to exist. When this file starts explaining how to run the dev server, it has stopped being a design system.