The spreadsheet — mechanics
The fork in this look
Row 2 is the fork: any printable key, =, / or the black = TYPE cell starts a formula in the frozen bar; a wheel, swipe or ↓ SCROLL reads on. SCROLL, bold on grey, is the resting state: complete without JavaScript, indexable, free. TYPE is black, the mind's colour, and each Enter costs a model turn, about a cent.
Enter from the hero switches on the sheet's own filter: programme rows no answer cites hide behind the heavy gutter line the phone lineup filter already draws. One 400 ms startViewTransition lifts the typed words into the new block's 40 px heading as the blocks below fold into that line. [ clear filter ] returns the full site, unfolding them onto the answer's source rows inside marching ants.
The standard route
- Nav: tabs are links, to anchors on the home sheet and to stand-alone sheets (
/lineup/,/agenda/tue/,/tickets/,/place/, new Partners and FAQ) numbered from row 1, as a workbook's are. - Agenda and speakers: a row per session or person; column labels sort; names and described sessions open a spreadsheet note.
- Tickets: four tiers in accounting format, Buy cells to Eventbrite.
Asking the mind
Plain words become =MIND("…"); a selection becomes its second argument, =MIND("which are about AI", A147:L149), and its ids lead the page note, so the context sent is visible. Typing dims unmatched rows locally (the mockup's route()).
Thinking is recalculation. On phase: thinking a numbered block inserts under the last answer, its caption cell reads #BUSY! under the mind's flag, and the status bar counts "Calculating… 1.4 s". say types over #BUSY! at about 25 ms a character, never half a second behind the stream. Each ui event is Point mode: ants circle the cited rows wherever they show, then the cursor pastes copies; done reconciles and writes the footnote.
Components copy the sheet's rows by id (data-sid, data-pid):
- Text:
sayat 300,faqat 400 as a key–value row: weight separates the mind's words from the site's. - Speakers:
speaker_gridpastes up to 12 lineup rows with heads;speaker_cardadds the note and a six-row crop. - Sessions: programme rows;
session_cardadds the note. - Agenda day: the day's rows and label row; a track applies an AutoFilter ("5 of 15 rows").
- Venue: the Place rows
focuspicks; hotel reads#N/A. - Tickets: the tier rows, Buy cells live.
- Choices: replace the bar's suggestion verbs; links are black cells.
- Sources: "¹ Copied from Wed 5, A164:L176 · sample data · typed in 3.1 s", renderer-written, updated as rows insert.
Fallbacks are the sheet's error values, each with a one-line note: #N/A beside the nearest real rows (not_in_snapshot, or a partial answer's gap); #NAME? off topic; #BLOCKED! for a block or refusal; #CALC! with [ recalculate ] when truncated or invalid; #CONNECT! when the proxy is down, route() answering from the rows and saying so. Failed turns append nothing to the history. Older blocks group under the gutter's outline +.
The assistant in the chrome
- The composer is a rule: the frozen bar's 2 px rule, never a box; unfiltered and below the hero, it sends
mode: "standard", the path and up to 30 on-screen ids. - The edge-parked card: a spreadsheet note parked against column M, three columns wide: number, question at 13 px bold, say-line, "6 rows selected below ↓", source,
[ clear ]. On-screen records are selected, never duplicated; the block still joins the stack above, scroll anchoring holding the view. Phones park it above the tabs. - The state line: the status bar's mode (Ready, Enter, Calculating…, Point), filter, sums, Austin time, snapshot, "sample data"; "still calculating" after 2 s without a word; Escape stops.
Data, performance and accessibility
The fixture holds every printed fact: 50 sessions (3 described, no rooms), 77 speakers (59 photos, 36 bios), four tiers, the unannounced venue, 8 FAQ, 39 sponsors, placeholder flags; faces.json holds crop landmarks. Ticket, place, FAQ and partner rows need ids. WordPress must expose the hidden title, organisation and TLOY fields and add an Event record (venue, hotel, coordinates, answer 01's question); Whova must supply the ETS27 programme, rooms and descriptions.
Motion: the 2.3 s intro once per session, skippable by any key; at rest only caret, ants, live cell and clock, paused when hidden; per answer a 400 ms transition and a paste capped at 1.2 s. Bake 2x crops; stop scaling hotlinked Whova portraits. Reduced motion: finished states, static ants, no live loop.
Keyboard: = and / need the prototype's [ shortcuts off ] (WCAG 2.1.4); arrows move the selection, Shift extends it into the range argument; column labels become buttons. Screen readers: blocks become <table>s with captions, the title an <h1>, the live region only the mode cell (today it wraps the ticking clock); answers announce once, aria-busy while streaming. EEA 2 keys (4.24:1), #N/A text (3.63:1) and gutter ink (3.84:1) fail AA: use #E2433A, #B8261E, #5D5D58.
Build plan
Carries over: server.py (SSE contract, sanitizer, cache, fallbacks, budget), taught to serve this folder and take page on standard turns; the fixture and gen.py; the seven-component catalogue; the renderer spine (streamAnswer, reconcile, offlineAnswer) and the mockup's typeBlock, renumber, sortBy.
New: rows.json from gen.py (a row per record id); speaker_card, session_card, agenda_day, faq, sources, coverage; filter, error values, note, range argument, table semantics; answer 01 recalculated at publish and seeded as each session's first exchange. About three front-end weeks beyond the shared Next.js engine, plus a data week.
Risks
- Inserts and sorts renumber rows: links and references key on record ids.
- Literal other-visitor questions need retained text: type canonical ones for the top router topics ("asked 41 times today"); count minds from the session store.
faces.swiftneeds macOS Vision: bake crops on a Mac at publish, with consent per speaker.- The four gauge colours group seven invented tracks; Zpryme must own them.