Prompt rail: shrinks its padding before it hides, so narrow windows keep it hoverable
Leo (2026-11-01), on the prompt rail in small windows: "also when things shrink it should be able to be more easily hoverable it's just kinda flickering in and out of being accessible at smaller viewpoints even though it certainly has enough space just shrink its padding more it can even have a dedicated space for more"
Stacked on #30355 and the full-height rail PR (lane/rail-full-height); review the two commits after 81999c55359b. Design spec: leo-workspace design/session-rail.md ("Narrow panes: the tight gutter"). Related: #30190, which keeps the occluded rail at 40%; its approach is the dimmed arm here.
What changed
Below about 790 px the rail's resting box (8 px inset plus a 20 px minimum hit width) overlapped the text's 18-20 px edge. It then hid at rest and could only be reached through a hover strip, so as the window moved around that width the rail kept appearing and disappearing. The transcript always keeps an 18 px page edge, and a resting tick is 6 px, so the room was there.
gutter.experiment.ts, three versions:tight(picked, the default): the inset shrinks to--cmux-space-1(4 px) first, then the hit width to--cmux-space-3(12 px). 4 + 12 fits the 18 px page edge, so the rail is never hidden at rest at any width. While it is hovered, focused, scrubbed or revealed, a rail narrower than a magnified tick (30 px) widens to 36 px over the text, so the wave draws whole; at rest it keeps its gutter.edge-strip: the 2026-10-28 placement, hidden at rest once it overlaps, with the pane-edge strip.dimmed: the edge strip drawn at 40% over the text (#30190).
- Gallery
agent-pane.thread-minimap-narrowcompares the three arms at 160/800/1600 px, with the edge and a tick hovered. The strip and occluded logic stay for the cases that still need them, such as a right rail beside the VS Code minimap. - Full-height follow-ups from its review: a long list's lead now ends at the box's own end, which removes a 0-9 px jump when the index arrives. A stack that hasn't been measured since it appeared reads its current reach.
Test
bun test test/thread-rail-narrow-gutter.test.tsx fails on 81999c55359b (5 of 6). It passes on this head (6 pass): no overlap at any pane width from 120 to 2400 px; padding shrinks before hit width; at 320/520/760/800 px the rail is drawn at rest, hovered without hiding, shows the full 6-10-14-20-26 wave, and returns to its resting width. thread-rail-full-height's new overflow case fails on the old lead (558 vs 555) and passes. The narrow and side suites pin the edge-strip arm for the strip tests.
Observed / Not run
Ran: every rail suite above, thread-bookmarks, chat-minimap, preview-card-placement, hover-intent-cards, and scripts/web-lint.sh.
Not run: a DEV build at a small window size.
Risk
Normal: rail placement only, at narrow widths. Wide panes are unchanged; they already use the widest inset since #30355.
Changelog
Fixed: In narrow windows the prompt rail stays visible and hoverable instead of flickering out of reach.
🤖 Generated with Claude Code
Agent session: agent session
![View with [code]smith](https://pr-comments-assets.blacksmith.sh/codesmith/view-with-codesmith-dark-v3-3x.png)
![Autofix with [code]smith](https://pr-comments-assets.blacksmith.sh/codesmith/autofix-with-codesmith-dark-3x.png)
Need help on this PR? Tag @codesmith-bot with what you need.
Summary by cubic
Fixes the prompt rail flickering in and out of reach in narrow windows: it now shrinks its padding and hit width before ever hiding, so it stays drawn and hoverable at every pane width. The rail also keeps its own layout box and opens at the height of every prompt the chat has even before they're all loaded. Wide panes are unchanged.
Bug Fixes
- In panes below about 790 px, the resting rail overlapped the text edge and hid, so it flickered in and out of reach as the window crossed that width.
- The default
tightgutter shrinks the inset to 4 px and the hit width to 12 px before anything hides, which always fits the 18 px page edge every transcript keeps. - While hovered, focused, scrubbed, or revealed, a compressed rail widens to 36 px over the text so the full tick wave draws whole; at rest it keeps its gutter.
- The rail's top, height, and inset now read only the view and the prompt count: a composer that grows, a tray that opens, or the sidebar toggle no longer moves it, and the mask leaves its lane in full ink.
- A list longer than the rail's room ends at the box's end, and the resting-stack latch resets per chat and stack.
New Features
- Adds a
thread-minimap-gutterexperiment withtight(default),edge-strip(the earlier hidden-at-rest placement), anddimmed(the occluded rail at 40%) arms, compared in the gallery. - With older history unread, the snapshot's
promptCountsizes the rail at full height from the first frame; arriving pages fill the rows above without moving held ticks.