Gera asked what the already-active stage should do on click, and delegated the call. It already collapses; this is the proof, and the guard that keeps it true.
30 Aug 2026 · branch fix/rail-tabindex-exact · captured against propflow-stage · at c1b567cc7c+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 behaviour that exists today rather than a description of it. The script opened the page, clicked the Signed step to move the panel there, then clicked Signed again — the already-open stage, which is the click Gera reported as dead.
The panel is gone in this frame. That is the whole finding: the collapse already works on main, which is why this PR ships no behaviour change. The rail measures 98.5px tall here against 146.5px with a panel open — getBoundingClientRect on the rail wrapper, read in the same Chromium session that drove these clicks, not off these screenshots. Cited because it is a number rather than something you can see, and everything else in this artifact is either asserted or explicitly picture-carried.
The rest of the control is still doing its job with nothing expanded — Reached on each stage the lead passed, Not yet on Signed, and the heavier label plus aria-current="step" still marking Application as where this lead actually is. Nothing is stranded by closing it.
Asserted in the captured DOM — Leasing progress · Not yet · Reached. Rail-local strings only. Deliberately NOT "Application Submitted" — that text renders twice on this page (the rail panel and the Activity Log in the sidebar), so asserting it would pass whether or not the panel existed. That is the vacuous-assertion trap this repo has been bitten by, and the reason the discriminating string below is the one the Activity Log cannot produce.
The same prospect on this branch, untouched. Application is open at first paint — the furthest stage this lead reached, not the next one they have not (Gera: "it should by default be on the current one, which is application").
This is the state that matters for the question, because the open stage here was not opened by a click — it came from defaultOpenId. The suite before this PR only ever toggled a stage the reader had opened themselves, so the case Gera actually named was the one nothing pinned.
Asserted in the captured DOM — Leasing progress · Not yet · Reached
One click on the Signed step. The panel moves there rather than a second one appearing — this rail is an accordion, exactly one panel for the whole control.
Signed has nothing on file for this lead, so the panel says so in words instead of opening onto an empty box. That sentence — Nothing recorded for this stage. — is the one string on the page that only the rail panel can produce. The Activity Log cannot render it. That makes it the assertion that actually discriminates open from closed, which is why the three frames in this artifact are built around it.
Asserted in the captured DOM — Nothing recorded for this stage. · Leasing progress. Asserted in the state the screenshot shows, after the click. This string is absent from the page at rest and present here — so the assertion is a real change of state, not a label that was always on screen.
A second click on Signed — the stage that is now the open one. The panel is gone and the card has shrunk back to the bare rail. This is the answer to Gera's question, and it is the behaviour that already shipped.
The grey chip still under “Signed” is the HOVER wash, not a stranded selection. The script clicked that step and the pointer stays parked on it, and this rail paints hover and selection as two grounds that are different in kind rather than two opacities of one tint — selection is the raised white pill with a hairline ring (see it on Application in the frame above, and on Signed in the frame before this one), hover is a flat 6% wash of the text colour. They never stack. Confirmed in the DOM: after the collapse the pill element is removed outright and the step reports data-selected="false".
Be honest about what is proven here. This tool asserts that strings are present; it has no way to assert one is absent. So the sentence Nothing recorded for this stage. being gone from this frame is carried by the picture, not by a check — and the rigorous negative lives in the unit test, which asserts aria-expanded="false", no aria-controls, and zero [role="region"] nodes. Read this frame against the one above and the one below: present, then absent, then present again. A dead click could not produce the middle frame.
Asserted in the captured DOM — Leasing progress · Not yet · Reached. The asserted strings only establish that the rail rendered and the page is the right one. The claim of this frame — that the panel closed — is deliberately NOT dressed up as an assertion, because this tool cannot make it. The screenshot is the evidence; prospect-detail-stage-rail.test.tsx is the guard.
A third click on Signed. The panel returns and the rail-only sentence is asserted present again.
This closes the loop the middle frame opens: the discriminating string is present → absent → present across three frames driven by three identical clicks on one control. Collapsing strands nothing — the reader gets back in the same way they got out, with no reload and no other affordance needed.
Asserted in the captured DOM — Nothing recorded for this stage. · Leasing progress
"No dead clicks" has a second half: an element that genuinely should not be interactive must not look interactive. This lead cancelled a tour, so the rail carries the short red Cancelled marker between Tour and Application.
The marker has no panel to open — the dated, reasoned line lives in the Tour stage's panel — so it carries no affordance at all: it renders as a <div>, not a button; cursor: auto, not pointer; no tabindex, so it is not a tab stop; no handler. Verified in Chromium across five leads in tour_cancelled / not_interested.
That is a DOM and CSS claim a text assertion cannot make, so it is pinned by test instead — and by a positive control that gives the marker a detail, turns it into a button, and watches the case redden.
Asserted in the captured DOM — Leasing progress · Cancelled. The assertion establishes the marker rendered on this lead's rail. Its INERTNESS is a DOM/CSS property this tool cannot assert; that half is carried by the unit test and its positive control.
The brief that produced this PR described a dead click. It does not reproduce. The first two frames are the reason that had to be checked in a browser rather than argued from source: the collapse has been in ui/TimelineRail since the rail was born (#6350), and the code comments say so, but comments are not behaviour.
So what ships is not a fix — it is the defence. The behaviour was correct and undefended, and one plausible refactor away from recreating the reported symptom: the page polls every 5s, and syncing defaultOpenId to state on render would reopen the panel within five seconds of the reader closing it. That is indistinguishable, from the reader's chair, from the click doing nothing. Six cases now pin it, each one broken and watched redden before it was trusted.