The vote page had three suggestion lists stacked down it — people you engage with, people you follow, the standings — each with the same row anatomy ending in the same Vote button. Run together they read as one very long list that kept restarting. They are now three tabs, Engaged / Followed / All, so choosing a mode is the reader saying which question they are asking: who do I talk to, who do I follow, who is winning. Each tab puts its list control in the same strip above the rows, with a count beside it to ground the sample — "233 accounts you follow", "6 nominees · 3 voters" — because a page of six faces means something the six on their own do not.
All three panels mount on load rather than on first visit, which is what makes
"Surprise me" worth keeping. It used to ask the server for a random pool
member, so the one thing it could never suggest was someone who did not already
have a vote — on a page whose whole premise is that anyone can be voted for.
It now draws from the union of all three lists, merging so a leaderboard row
keeps the rank and tally the other two lack, and filtering out the reader, the
face already showing, and everyone they have voted for. The server draw stays
as the floor for a cold load, or a reader who engages with nobody and follows
nobody. Its first draw also waits on myRecords now: fired on the session
alone it raced the ballot load, and the exclude list was usually just the
reader's own did.
Voting is a toggle. VoteButton is the one place a vote is cast or taken back,
and "Voted" is a button carrying aria-pressed rather than the stamp-shaped
span it was — press it again and the vote is gone. Deliberately unconfirmed: a
mis-tap costs one press to undo, and a repo write either way, so a dialog would
be asking about the cheaper of the two mistakes. That is what lets the ballot
page drop its separate Remove button, and with it the "Counted" chip, which
said the same thing as a filled "Voted" standing next to it. The badge still
renders for over_limit, invalid, pending and frozen, since it is the only thing
on the row explaining why a vote the reader can see is not counting.
Stepping out of the nominees is the one that asks. That one drops every vote cast for you off the board and rejoining restores the listing, not the standing — so it confirms inline, where it can say so, rather than through a browser dialog it cannot word.
Also on the ballot page: no rank chip. getProfile carries one and
NomineeCard draws one whenever it is handed one, but a ballot is the people
you picked in no order — the caption says as much — and a number in front of
each face invites reading it as your ranking of them. The response was being
stored behind an as Profile cast that does not declare rank, so it rode
through untyped; the fields are copied explicitly now.
The chrome:
-
The signed-in account's own face, which was never there —
authheld a did and a handle and nothing else. It comes from the same unauthenticated SlingshotgetRecordthe server's actor refresher makes, so it costs no token and no PDS hop.avatarCidOfmoved intoblob-urlto be shared by both paths, legacy blob shape included. -
A footer with room in it. The source link was a full
btnOutlinealone in the centre of the bar, which gave a footer link the weight of a call to action. It is now quiet text level with a byline crediting @pds.dad and @dame.is, each name opening the waypoints menu through a newnamevariant ofOpenIn. The bar is a ruled sheet on the raised surface with the content sitting on opaque chips, because the rules ran straight through bare type. -
Light is the default on a first visit, whatever the OS prefers. This is a printed page with an ink-on-newsprint palette; light is the design's home key, not a fallback, and dark stays a choice the toggle remembers.
-
The wordmark shows on a phone. It fits at 375px with room to spare, and the bare "38" mark alone read as an unlabelled icon; below about 355px it truncates rather than shoving the controls off the bar. On the leaderboard the tally column drops from 96px to 64px on mobile, which hands the name column a third more width — enough for most names to stop truncating — while still fitting a five-figure count.
And the surprise-me landing no longer scales. A zoom reads as the card coming toward the reader, a different gesture from the one the reel frames just made, and the size change was the part that caught the eye rather than the face. It travels down half a rem into place instead, and the spring's small overshoot does the rest.
Co-Authored-By: Claude Opus 5 noreply@anthropic.com