- On a phone the page itself was the thing that scrolled, and the keyboard could break the chat outright. The document never scrolls on phones anymore. Two earlier unlocks had made the document the browser's fallback scroller, and three known engine behaviours then took turns with it: focusing the composer panned the whole page down into the dead space below the content, the sent message's pin seated against a viewport that had already changed and jumped out of view, and rotating with the keyboard up locked the layout on numbers that were no longer true. The shell is now sized in real pixels from the visible viewport and moved by its own offset, so everything fixed inside it, the sheet, the pill, the floating question card, re-anchors to the part of the screen you can actually see. The measuring pass was rewritten around that: coalesced to one per frame, idempotent, with guards for pinch-zoom and for nonsense heights, and with the old timed undo replaced by a bounded one that targets the single signal a scroll call can actually move. The plausibility floor is orientation-aware rather than a flat number, so a small phone in landscape, where the real keyboard viewport is genuinely tiny, gets measured instead of frozen. And that bound re-arms when the keyboard closes, because a leak nothing could move would otherwise pin the counter at its cap for the life of the page and disable the undo for every later keyboard session. Desktop stays pixel-identical.
- The brief drawer stopped being a drawer and became a top-level Chat or Job description toggle. The bottom sheet on phones is deleted. The chat home is two peer views under one persistent row now, a real tablist with arrow keys, plus the progress meter as a chip that opens ONLY the checklist and never the document. Entering the job description pushes a history entry, so the browser's own Back gesture leaves the document, and both views stay mounted and swap by visibility, so the draft in the composer and each view's scroll position survive every toggle. Going with the sheet: the modal machinery layered over a live composer, the peek-bar choreography, the drag and snap tween, and the standing fight between the sheet and the keyboard for the bottom edge. Review then found two real Back-button traps and the answer was a design change rather than another patch: an entry may only be popped when it carries one of our own markers AND a stamp matching this document load, so a reload-restored entry, which this session never pushed, is rewritten in place instead of navigating somebody out of the app entirely. The switch got its motion afterwards, a measured thumb that slides between the two unequal tabs and a short directional cross-fade, with a dot on the job description tab when the brief changes while you are reading the chat, cleared the moment you look.
- The keyboard now closes after every sent message, and a docked card can no longer ghost-click the brief open underneath itself. The keyboard dismissal is a product decision applied at one chokepoint: on touch-first devices it closes after every send and on every non-typing transition, while typing actions, a suggestion chip, a blank-area tap, a refine prefill, still bring it up. It has to run inside the tap's own task, because a deferred blur is ignored and script can never reopen a keyboard, so each dismissal is a deliberate one-way door. The ghost click was subtler and worth the detail: while a question card owns the zone above the composer the brief peek is slid off-screen, and answering unmounts the card in the same render, so the peek animates back into the exact spot the finger just touched, over about a quarter of a second, while its ability to be clicked snaps back the same frame. The phone then replays its trailing compatibility click a beat later, re-tested against whatever is under the finger at that moment, and it landed on the returning peek and opened the brief on top of the answer. So the vacated space is not re-occupied immediately: hit-testing stays off for a short grace window while the slide-back still animates, with the timing living in a plain tested helper rather than in the component.
- A message half-typed before signing in used to die with the document, and signing in booted the app twice. Uploaded files survived a sign-in because they go to the server immediately, but the typed words did not, because they were ordinary in-memory state and every sign-in path is a full navigation. The text, the caret and which project it belonged to are now stashed the instant the redirect starts, and consumed once on the way back: another project's draft is refused, an old one expires, the caret comes back, and it never sends itself. A restored-from-cache document, whose memory is intact, skips the restore entirely. There is a crash net on a slow idle timer, an emptied composer clears the stash immediately so a sent message cannot resurrect itself, and switching accounts drops the key, so a shared browser cannot carry one person's half-written message into the next person's composer. Separately, the landing after sign-in deliberately booted twice, mounting as a guest, learning who you actually were, and reloading, because the authority cookie is not readable by the page. The callback now sets a short-lived readable hint beside it carrying nothing but the identifier, adopted at load so the workspace is handed to the account BEFORE the cache key is derived, and the page boots once, warm, as you. The refusals are the load-bearing part: no hint falls back to the old double boot unchanged, a hint for a DIFFERENT cached identity is never adopted because an account switch must keep its purge, and signing out drops the hint so a stale one cannot re-adopt a signed-out identity seconds later.
- The question card popped up before anybody had said anything, and came back after signing in. The floating question above the composer showed itself right after sign-in, before the client had typed a word, and a card a guest had already seen re-appeared after the round trip. Two gates now: nothing docks until there is at least one message from the client in the conversation, and a skippable card shows at most once per person. A card the agent leads with stays inline in the conversation, undocked and still answerable. The showing is claimed the moment the card reaches the screen rather than when it is answered, because somebody who saw it and ignored it has consumed the showing, and it is claimed in three layers, in the session, in local durable storage, and as a stamp on the card's own stored message, written first-write-wins so a replay keeps the original moment. That stamp rides the transcript through the guest-to-account handover, which is what keeps the card away on any device afterwards, and a local not-shown can never outrank the server's shown. Review caught two real holes: the claim and the read were resolving the project two different ways, so on a boot where the identifier had not settled the mark was written under one key and read under another, and a text-route question, which never renders as a card at all, was burning its one showing and severing the routing that lets its answer be recorded.
- The live search rail became one glance card that grows into the shelf, and the glow took all afternoon. The rail's resting face is now a single white card floating on the search glow, one to one with the design: the mark, ONE status line, which is the searching line while the engine runs and the agent's own closing sentence once a snapshot lands, the found faces with an overflow bubble, and the chevron. The whole card is the control, the default flips to collapsed, and it now also renders mid-search with nothing found yet, as an inert status card with no chevron, because there is no shelf to open. Expanding grows the same card rather than swapping to a different one, on an animated fold, and takes the width of the conversation column; the old expanded bar went with its title row, its one-line note, its spinner and its labelled pill, since the status line and the glow now carry the whole story. The glow itself went through the full loop: a stretched sweep whose ramp terminated visibly, a research pass on how shipped activity glows actually work, a light-pass system, a comet riding the border, and finally the design team's own effects tool as the source of truth, tuned in review to a broad quiet wash that is the card's only lift. The one genuinely interesting bug in that chain: the tool's wheel is white at both ends, a wide span that is invisible over a white card, so a colour mass rotating into it vanished and the eye jumped to the other side; closing the wheel green into lime and back made the light orbit continuously. A constant rotation also reads as crawl-the-edges then snap-across-the-ends on a card this wide, so the keyframes now hold the corners at their share of the perimeter and the light travels the rim at an even speed. Also fixed along the way: the glow was painting over the last chat lines and the composer, and the expanded panel was unbounded and squeezed the conversation to nothing, hiding the newest messages behind the card.
- The talent card on that shelf now says why this person, and the finalist card speaks to an ongoing hire. The early-stage card carries the grader's own words under a quiet heading, keeps the pinned best-match pill, and drops the seller levels and rank chips, since order plus one badge says enough. No price and no delivery date, deliberately, because both are unreliable at that stage and absent is better than wrong. One action, view profile, with the same beacons the final carousel uses, and the whole rail-side send flow is deleted with it. On an ongoing or hybrid engagement the finalist card's three statistics were rewritten to answer hiring questions rather than marketplace ones: price becomes our own rate-at-scope estimate in the client's own unit and derived from the talent's real economics, never invented, degrading to their own pricing axis when there is no honest basis; delivery becomes availability, read off a vacation window nobody had ever parsed or off the talent's own stated start, and unknown renders as to be confirmed rather than as an empty slot; and the project count becomes continuity, the returning-client share plus the year they started. A one-off hire is byte-identical everywhere, pinned by tests. It shipped, was reverted within the hour, and re-landed the same afternoon.
- A talent has working hours now, and being inside them is worth a little, but it never removes anybody. Everyone is assumed to work a wide default in their own timezone unless they say otherwise, and a talent may state their own, stored beside their earliest start date rather than as a sentence in their rules, because a sentence there would be read as work they will not take and would quietly drop them from everything. The arithmetic is delegated to the code that already does the daylight-saving-safe version for quiet hours, rather than restated, since two copies drift and the second copy is the one nobody tests on the night the clocks move. It is worth two points, not five, because being online now already implies being in hours and the two would double-count the same person. And it deliberately does NOT screen: a start date is a fact about the whole job while working hours are a fact about this minute, so filtering on them would delete the Americas from every afternoon search and Asia from every morning one, for the same client and the same brief. The talent is always found, always shortlisted, always shown. Shipped with it, the preference turn now says the specification's own sentences verbatim rather than a paraphrase that read differently every turn, guaranteed at the seam rather than requested in a prompt, and asking whether there is anything else became a property of state rather than of the model remembering.
- Talents stopped getting the twenty-minute are-you-there chaser, and phones stopped being in the experiments. The unprompted just-checking-in note to a talent who had not replied yet read as nagging, so the whole pipeline is gone, the arming, the job, the handler, the template and its mapping. The half-hour silence timeout, which is silent and replaces the talent, and the last call before the reveal both stay. Jobs already queued by the previous release simply fail to parse and die, which is exactly the point. Separately, a phone or touch-primary device now renders the control experience for both live experiments whatever arm it hashes or pins to, even at a full dial. The arm itself stays per person on the server, so the same account on a laptop keeps it, and the effective cohort is derived at every point of consumption rather than at one gate. The debug panel keeps showing the served arm and says why a phone is still seeing the control.
- And a long tail of phone-sized repairs, each of them the first thing you would notice. Saving the brief as a document failed on iPhone, because the export can take up to a minute and a half while the browser only honours a tap for about five seconds, so the click that followed was silently dropped or parked the tab on the storage address instead of saving; it is a plain navigation now, which is not gated on that, plus a real visible link underneath as a belt. The transcript could be swiped sideways and push messages off the left edge, on landscape phones wide enough to land in the desktop layout. On that same landscape width the progress checklist only revealed on hover, so a touch user could never open it at all. The brief header's icons had scattered across a grid built for buttons that had since become icons, leaving the close control orphaned on its own line over the document; the grid is deleted rather than patched again. At eight of eight the finished brief now reads from the top with its call to action docked at the bottom, instead of welding a band onto the dark header over an empty sheet. Swiping to the next shortlist card settles it into the screen under the compare line, and the best match takes the leftmost seat on a phone, because only one card fits and the deliberate middle-of-three seat hid it one swipe away. A suggestion chip splices into whatever you have already typed instead of deleting it. And the reasoning strip counted raw steps in its header while the list counted merged rows, so testers read three shown plus seven earlier against eleven in the header.
A Sunday of 28 commits, and the through-line is the phone finally being treated as a real surface. The document does not scroll on phones anymore: the shell is sized from the visible viewport and moved with it, which is what fixes the keyboard panning the page into dead space, the sent message jumping out of view, and rotation locking the layout on stale numbers. The brief drawer is gone and the chat home is two peer views under one toggle, with the browser's own Back leaving the document and both views keeping their draft and their scroll. The keyboard closes after every send, a docked card can no longer ghost-click the brief open underneath itself, and a message half-typed before signing in survives the redirect with its caret intact, on a landing that now boots once instead of twice. The question card waits for the first message and shows once per person, claimed when it is seen rather than when it is answered. The live search rail became one glance card that grows into the shelf, its talent cards carrying the grader's own reason on their face, and the finalist card learned to answer an ongoing hire in rate-at-scope, availability and repeat clients. A talent has working hours now, worth a couple of points and never a filter, the twenty-minute chaser to talents is retired, and phones now always render the control arm of both experiments.