Three dogfood-driven UX fixes:
1. `AppState::attach_to_focused` now sets `mode = Mode::Insert` along with
`focus = Focus::Pane`, so pressing Enter on a sidebar row drops the user
straight into typing the remote shell. The leader (default `ctrl-a`)
returns to Normal — same surface as tmux's prefix key.
2. `Keymap::entries(mode)` exposes the live binding table; `App::dispatch
(Action::ShowHelp)` (and `App::new`) rebuild `HelpOverlay::lines` from
it. Users see the actual Normal + Insert bindings + the leader hint,
not just "? to close".
3. Visible blinking cursor in both surfaces that accept text:
- `Pane::render` calls `Frame::set_cursor_position` at the vt100 cursor
position when the pane is focused (and the screen hasn't hidden the
cursor itself). Terminals do the blink.
- `SpawnModal::render` places the cursor at the end of whichever text
field is currently focused (cwd / command / label). Daemon dropdown
and the Submit button still rely on the REVERSED style.
Workspace clippy + 85 unit tests passing.
First-use UX fix: the TUI rendered the daemon list but felt frozen because
mode and focus were invisible, and the sidebar had no nav keys, so
`Enter`/`AttachHighlighted` had nothing to target.
- `render::draw` now reserves the bottom row for a status bar that always
shows `[NORMAL]`/`[INSERT]` (cyan/yellow chip), the focused panel
(sidebar / pane), and the most useful key hints (`j/k: nav • enter:
attach • s: spawn • ?: help • ^Wq: quit`). Status bar is never
eclipsed by overlays.
- `Sidebar::render_with_focus` and the pane block now draw their border
in cyan when focused, in the default colour otherwise.
- New `Action::SidebarNext` / `SidebarPrev`, bound to `j`/`k` and
`down`/`up` in the shipped Normal-mode defaults. Dispatch walks the
catalog's session list, calling `AppState::move_sidebar_highlight`
(wraps both ends).
Workspace clippy + 85 unit tests + 3 integration tests green.
Adds the full visual layer:
- `state.rs` — `AppState` (tabs/focus/mode/sidebar visibility/overlay).
v1 keeps each tab to one optional session; the split tree is v1.5.
- `terminal.rs` — `TerminalGuard` (raw mode + alt screen + mouse capture
with RAII restore) and an idempotent panic hook that restores the
terminal before re-panicking.
- `sidebar.rs` — daemon → session tree with ●/○/✗ glyphs. Pulls a label
out of `metadata.label` (the protocol's shape), falls back to the
command.
- `tabs.rs` — top-row TabBar with active highlight.
- `pane.rs` — `vt100::Screen` → ratatui `Buffer` cell-by-cell, with full
fg/bg/bold/italic/underline/reverse translation. `PaneStatus` round-trips
from `SessionState`.
- `overlays.rs` — SpawnModal (5-field form with rotation), KillConfirm,
HelpOverlay, Toast. All centered popups with `Clear` underlay.
- `render.rs` — `draw(f, RenderInputs)` composes everything; returns a
`RegionMap` whose `region_at(col, row)` resolves a mouse coordinate to
a tagged Region (modal eclipses the rest).
22 new unit tests bringing the crate total to 80 passing. Tests use
content-based assertions over `ratatui::backend::TestBackend` output rather
than file-based goldens — less brittle to whitespace shifts while still
covering the visible content.