Gera opened with "I feel like this one's really good", so this is refinement: the orb comes off the zero case, and the past-due block stops restating what Tenant info already says.
30 Aug 2026 · branch fix/tenant-detail-refinements · captured against propflow-stage · at afe27972a1+local
Data note. Every name and balance below comes from propflow-stage, which is anonymized by construction (ADR-0097/0110 — phones in the impossible +1000 NPA, emails @example.test). The identical capture against prod would carry real tenants' names and balances and is not safe to attach anywhere, which is why the generator refuses to run against one.
Captured from a second dev server running origin/main, so this is the state Gera reviewed rather than a description of it. Four things to read, top to bottom.
The past-due block, second card down. It opens with “Unit 108 · lease window not on file” — the unit is already stated in the Tenant info card directly above it, as a link up there and as plain text down here. (This fixture resident carries no lease end, so the second half of that line renders its gap copy; on a resident who has one it reads “lease through …” and duplicates Tenant info's Lease end row as well.) Under that, a 32px figure in --color-danger. Gera: the block “carries too much color”.
The chip cluster on its right. Five filled Badge pills with micro-labels above them, including an amber “Language not asked”. Every one is a fact a labelled row states better — and he had already ruled on this idiom twice on 2026-08-27: “I'm not a big fan of putting a lot of things in the pill or in the badges. Maybe a green circle.”
“Account balance $4,180”, at the right end of the aged-band row. load-tenant-detail.ts builds this and the figure on Tenant info from the same balanceHistory[last] row — one number, rendered twice on one page.
The Work Orders card in the right rail. A 64px resting Clara orb over a py-12 column, to say zero. Gera: “for work orders, we don't need to show that like orb… If we have zero work orders, it could be kind of collapsed and just shows zero.”
Asserted in the captured DOM — Unit 108 · lease window not on file · Language not asked · ACCOUNT BALANCE · No work orders · Collections activity. Every one of these is a thing this PR removes or moves, asserted on the BEFORE so the AFTER's negatives are a real change and not a page that failed to load. ACCOUNT BALANCE is shouted because that is literally what is on screen — the band headers are `text-[10px] uppercase`, and these assertions match rendered innerText, which carries the CSS transform.
The same route on the branch, against the same fixture. Read it against the frame above.
The past-due block now names itself — a SummaryCardHeader reading “Past due”, the same heading component every other card on the page uses. It had no heading at all; the reader inferred what the 32px number was from the number.
The figure is --color-text. The severity is carried by the words directly under it (“past due 31+ days”) and by the card's own title — which is exactly how Tenant info states this same account one card up: a value plus a dot, never coloured text.
The chips are gone. The four standing facts are Field + StatusValue rows under a “Standing facts” heading, out of pms-card-primitives — the Tenant info idiom, not a second one. The claim kind survives in the labels: “Recorded stage” (a human declared it) and “Observed outreach” (our lane derived it). Those axes are kept apart on purpose in the data layer and collapsing them here would have been the real loss.
The unit line and the “Account balance” cell are gone, because the page already said both. What is left on this card is the part that appears nowhere else: how the money is aged.
The Work Orders card is one line. Same idiom the Conversations card beneath it already used.
Asserted in the captured DOM — Past due · past due 31+ days · Standing facts · RECORDED STAGE · OBSERVED OUTREACH · No work orders for this tenant. · Collections activity. RECORDED STAGE / OBSERVED OUTREACH are shouted because `Field`'s label is `text-xs uppercase` and these assertions match rendered innerText. “Collections activity” is asserted on BOTH frames on purpose — item 105 was Gera confirming it should stay its own card, so the evidence has to show it surviving the cleanup, not just show the cleanup.
The top of the page, cropped to the Tenant info card. Language now sits in the Contact sub-section, between Mailing address and the hairline — through the sub-section that was already there, with the same FieldGridSection and the same mt-3 pt-3 border-t rule as Lease and Status above it. No second pattern was invented for it.
It reads “Not asked”, not “English”. That distinction is the whole reason the field exists: the outbound stack defaults an unset preference to English, but in Colorado a demand's validity turns on the language we know the resident speaks, so a card that spelled the default as a recorded fact would be helping a PM prepare a void document.
This resident IS past due, so the gap carries an amber dot. On a resident nobody is collecting from, the same row renders as a plain muted value with no colour at all — semantic colour where it encodes severity and nowhere else, which is the point of taking the amber pill off it rather than moving the pill.
Asserted in the captured DOM — Tenant info · Contact · LANGUAGE · Not asked · Lease. Asserted after Contact so the row is shown inside the sub-section it was folded into, not merely somewhere on the page. LANGUAGE is the label (`text-xs uppercase`); “Not asked” is its value and is not transformed — which is exactly the pair that has to be on screen together.
The counterpart frame, and the reason it is here: “collapsed and just shows zero” is a claim about one branch, and a change that quietly emptied the card for everybody would pass every assertion in the frames above. This resident is not past due either, so the same capture doubles as the no-collections state — no “Past due” card, and the Language row in Tenant info with no amber on it.
Asserted in the captured DOM — Work Orders · Tenant info
Two of the four tracker rows were Gera confirming things he wanted left alone, and on this page a “clean it up” pass is exactly the kind of change that absorbs a card nobody asked it to touch.
Collections activity stays its own card — “collections activity could be separate. That one's fine.” It is visible, unchanged, in both the BEFORE and AFTER frames, and pinned in TenantDetailClient.round5.test.tsx as a structural claim: the card must not be a descendant of the Tenant info card. A fold-in would still leave the words on the page; it would not leave them outside Tenant info.
The “Also on file · Prospect” cross-link stays. It does not appear in these frames because this fixture resident holds no other role — a card that renders nothing at all for an ordinary resident is its documented behaviour, and asserting it here would have meant capturing a different tenant to prove a card that was not the subject. It is pinned in two test files instead, one of which renders it alongside every round-5 edit at once.
Also unchanged and worth naming, because it is a real inconsistency I chose not to fix: Collections activity still titles itself through Card's own title prop — an h3 at 14px/500 — while every other card on the page uses SummaryCardHeader's h2 at 16px/600. That is live drift from “make sure all of them have the same title styling”, but item 105 was “that one's fine”, and restyling a card he had just confirmed is not what he asked for. Flagged rather than silently done.