Build notes · Site 190 · Generative Assets
Stamping one glyph through all seventeen plane groups
Wallpaper is a working printing plate for the classification theorem every repeating pattern obeys: any two-directional repeat belongs to one of exactly seventeen symmetry groups. The page's single job is to make that census physical — one Fraunces ampersand, its weight slowly breathing, is stamped live through each group in turn while the mirrors, glide axes and rotation centres that define it are drawn as construction marks over the ink.
Palette — plate, ink, and two kinds of mark
The scheme is argued from letterpress furniture: a dark steel plate, one pale ink, and the two colours a plate-maker would scribe in. Teal is reserved for lines — mirrors solid, glides dashed — and brass for point marks, the rotation centres. Body text never borrows the accent colours; it has its own ink so small labels stay above 4.5:1 on the plate.
- Printing plate
- The ground. Green-black steel, dark enough that flooded ink reads as relief, not decoration.
- Motif ink
- The ampersand itself. A warm stone white — full white would strobe against 200 stamps a screen.
- Symmetry teal
- Lines and marks only: mirror lines solid, glide axes dashed, the unit-cell outline. Never body copy.
- Rotation brass
- Point marks: lozenge, triangle, square, hexagon for 2-, 3-, 4- and 6-fold centres, as crystallographers draw them.
- Body ink
- Derived reading tone for running text — the ink/line split the collection settled on in Wave 2.
- Muted label
- Census metadata, eyebrows, this caption tier. Checked at 375px against both plate tones.
Type — the specimen is the subject
Fraunces &
Fraunces variable
The motif is not set in Fraunces; the motif is Fraunces. Its weight axis breathes between 180 and 640 on a 4.2-second cycle, so the whole plane pulses as one organism. Display sizes ride the optical-size axis to 144; the hexagonal family's group names (p3, p3m1, p31m, p6, p6m) are set italic as a quiet taxonomy marker.
p4g · 04/17
Azeret Mono
The surveyor's voice: crystallographic names, cell metadata, generator readouts, and every caption on this page. Its squarish counters sit naturally beside construction marks, and tabular figures keep the 17-group census aligned.
Technique — symmetry as arithmetic, marks as theorems
Everything is canvas 2D — no libraries. Each of the seventeen groups is stored as its
textbook operation set: integer 2×3 matrices in lattice coordinates, exactly as
the International Tables list them (p4g, for instance, is the four rotations of p4 plus
the same four reflections shifted by ½,½). A basis matrix B per lattice
class — oblique, rectangular, rhombic, square, hexagonal — maps cell coordinates to
pixels, and each operation's screen transform is the conjugation
L = B·M·B⁻¹, handed straight to
ctx.setTransform. The ampersand lives on one offscreen 320px canvas,
re-rasterised every frame at the breathing weight, then stamped hundreds of times per
group; where an operation's determinant is negative the stamp prints
left-handed — a chiral ampersand no font menu contains, and the site's second
read.
The construction marks are the part I refused to hand-draw. For every operation the
code solves for its fixed locus: rotations solve (I−L)c = τ for
the centre point and take the trace for its order; reflections split their translation
into components along and normal to the axis direction
φ = ½·atan2 of the linear part, and the smallest parallel
component over all lattice copies decides solid mirror or dashed glide. So the marks are
not an illustration of the group — they are computed from it, and a wrong matrix
would draw its own accusation. A test hook asserts the derived mirror/glide/rotation
census for all seventeen groups against the crystallographic table on every build.
Choreography: each group floods outward from the centre — stamps pop in distance-ordered with a cubic ease — then cell outline, axes and centres fade up over the ink. The cycle rests 5.4 seconds per group (9.5 on the opening p6m, so the first frame a visitor or a thumbnail sees is the full kaleidoscope, flooded, marks up). Labels swap through a 180ms opacity dip; the census cards and the 17-stop rail jump the plate to any group directly.
Iteration log
Pass 1Craft
- Unified the mark language across every surface: census-card chips repeat the plate's exact grammar — solid teal outline for mirror, dashed for glide, brass for rotation — so the legend teaches itself.
- Kept teal and brass off running text entirely; body copy got its own two-ink scale (#BEC7C0 / #8FA097), both checked above 4.5:1 on the plate tones.
- The giant group-name readout was hidden from assistive tech with
aria-hidden— removed it; the name is the page's principal live datum. - Rewrote generator captions to read as spoken geometry ("mirror one way · glide the other · half-turns") rather than Hermann–Mauguin shorthand.
Pass 2Depth
- Replaced hand-placed decorations with derived marks: centres and axes are solved from the operation matrices at runtime, which is what makes seventeen genuinely different plates rather than seventeen backdrops.
- Added the chirality second read — reflected stamps print left-handed ampersands, and the rotation-only family (p1, p2, p3, p4, p6) provably never flips one; the legend note points it out only after the census.
- Gave the boot cycle an overture: the page wakes on p6m, the order-12 maximum, and holds it 9.5 seconds before starting the tour from p1.
- Exposed a
features()self-test that recomputes each group's mirror/glide/max-rotation census; all seventeen match the textbook table.
Pass 3Hardening
- 375px verified by element boxes (wordmark, nav, readout, rail), not just
scrollWidth; the readout column stacks and the rail keeps 17 stops tappable — hit areas widened past the 3px tick marks. - Reduced motion renders a settled mid-cycle plate — flooded stamps, marks up, no
loop — via the CSS query plus a
matchMediaswitch with a live change listener. - Canvas discipline: DPR capped at 2, debounced resize rebuild, rAF paused when the
tab hides, painting skipped while the hero is scrolled out of view, fonts gated on
document.fonts.readywith a 3-second fallback. - Headless checks: zero console errors, exactly one h1 per page, two-frame screenshot-hash liveness, and per-group screenshots pairwise distinct across the glide and hexagonal families.