The lattice — mechanics
The fork in this look
The first interaction is either verb of the dateline: a letter or / puts the caret on the 02 rule; a wheel or swipe starts reading. One URL, one answer state: switching is scrolling. TYPE (wght 850) owns the first screen, SCROLL (wght 200) the rest; cost follows weight: typing re-selects locally, Enter spends a turn (about a cent), scrolling costs nothing.
Enter runs a same-document view transition: the typed words (view-transition-name: question) lift off the rule into the heading as the previous answer folds into a numbered section below. Cells are excluded: transitions morph in straight lines, but the lattice moves along rows then columns.
Answer 01 (Tuesday) replies to an editorial resting question: generated per snapshot publish, shipped as static HTML, seeded server-side as every session's first exchange so "and Wednesday?" follows on.
The standard route
- Nav: no bar. The corners link to top, Eventbrite, the place and the days; below the fold the sticky rail lights the current section, its one phone label opening the rest.
- Pages: the long page is home, statically generated;
/lineup/,/agenda/,/tickets/,/place/and a new partners ledger stand alone. - Agenda and speakers: day columns and ledger rows, anchored by record id; a name opens its row in place, as a
speaker_card. - Tickets: phase 1 rows with Buy → Eventbrite, phase 2 "Later", the not-published readouts.
Asking the mind
Typing is attention; answering (Enter, or a question on the rule) is ink. Typed matches (substring or day word) sharpen in width and contrast, never ink, so bright means answered.
On phase: thinking the previous lit set slides back to programme order and the lens walks down the rows, 60 ms each, sharpening without inking: the mind reading. The first say delta stops it; the leaning say-line prints. Component events light their ids in place; the final answer's reconciled set gathers into the diagonal once, so no word moves twice. The merged cell stays 7 × 19, so streaming never re-lays the lattice.
- Text:
sayleans;faqstands upright, the site's own words. - Speakers: four ledger rows and "+ 8 more, in the lineup below ↓";
speaker_cardadds bio and session times. - Sessions: time, title, type, people, plus description once published;
agenda_dayis the Tuesday form, a track narrowing it ("4 of 15"). - Venue and tickets: the place's readouts and the tier rows, lighting their fact cells.
- Choices: the questions on the rule; a link option takes the hairline arrow.
- Sources: the superscript footnote, written by the renderer from page ids and
placeholderflags; "sample data" stays.
Fallbacks: off_topic is one unnumbered line; not_in_snapshot lights nothing beside the nearest real record; partial lights what exists. Errors keep the prototype's codes, the lit set and the question; proxy down, the mockup's keyword composer answers and says so.
The assistant in the chrome
- The composer is a rule: one form element, in the merged cell while the masthead shows, then moved, draft intact, to a hairline across columns 3–12 at the viewport's foot, sending
mode: "standard"and the on-screen ids. - The edge-parked card: a three-column merged cell above the rule's right end: number, 17 px heading, say-line, source,
[ clear ]. Page records light in place, never hidden, and the card keeps "11 lit in the lineup ↑". Escape returns Tuesday everywhere. On phones it spans the width. - The state line: the footer readout, mirrored on the rule mid-turn: "Reading the programme", "Answer 04 · 12 people lit · sample data", "Still reading" after 8 s.
Data, performance and accessibility
The fixture holds every printed word (days, 50 sessions, 77 speakers, tiers, venue status, FAQ), flagged placeholder. A generator builds the 194 cells from it, adding record ids (cells match names by text today), colon-cut short titles and fact cells per tier, FAQ topic and venue field. WordPress adds the hidden speaker fields, an Event record holding the resting question, and short-title overrides; Whova the ETS27 programme, rooms and descriptions; the sync bakes 40/80 px stamps.
Motion: entry 3.5 s once; un-gather hidden inside thinking; gather capped at 1.6 s; at rest only the caret and the 3.6 s hop. Frames write transforms only (the ground becomes a scaled pseudo-element). Reduced motion: settled layout, instant swaps, no hop, walk or scroll-driven type.
Type-to-ask focuses with preventScroll (today a keystroke in the agenda jumps to the masthead); the prototype's [ shortcuts off ] returns. The lattice is aria-hidden behind one rewritten sentence ("28 people and 11 sessions on Tuesday are lit"); lit records are links in the answer, announced once by a status region. Cream on #1F7A6E is 4.28:1, under AA at 11–17 px: the ground moves to #1D7569 (4.58:1), and below-fold rows rest at full ink (66 % reads 2.75:1), selected by axis and dimmed only during a question.
Build plan
Carries over: server.py (SSE contract, cache, scanner, sanitizer, budget), the fixture and builder, the seven-component catalogue, and the renderer spine (streamAnswer, reconcile, summarize, error copy, mergeIntoPage re-pointed from hiding to lighting); from the mockup, the layout engine, attention field, select() and compose().
New: the cell generator, per-answer gather, what the prototype lacks (speaker_card, session_card, agenda_day, faq, sources, coverage), rule, card, state line, page surface notes, Answer 01 publishing, section pages. About four weeks for one front-end engineer beyond the shared engine; the long pole is a layout engine tuned for one 40-cell Tuesday.
Risks
- ETS26's real 147 speakers and 68 sessions overflow 12 × 43 cells: the first screen shows the lit set plus what fits, and past about 70 cell-widths a selection stays lit in place, unsloped.
- The seven tracks are invented groupings printed like programme facts.
- A late font load changes every span; layout re-runs on
document.fontsevents. - First word (1.2–3.1 s) plus the gather: the walk must read as reading, not loading.