5c6aff1430
* fix(desktop): hide the terminal overlay when its pane is inactive One xterm is CSS-overlayed onto whichever `<TerminalSlot />` is active, positioned with `position: fixed` from the slot's bounding rect. Keep-alive tab layers stay MOUNTED when inactive — hidden with `visibility: hidden` + `data-pane-hidden`, deliberately preserving their layout box so scroll state and xterm survive a tab round-trip. So an inactive terminal slot still reports a full-size rect identical to the front tab's, and `rect.width > 0 && rect.height > 0` cannot tell the two apart. The overlay stayed painted at z-4 over whatever tab the user switched to, swallowing its clicks. Sample the hidden state alongside the geometry: `Rect` carries `hidden` from `isElementInHiddenPane(slot)`, `sameRect` compares it so a tab switch wakes the tracker, the ancestor MutationObserver watches `PANE_HIDDEN_ATTR`, and the overlay gates on `!rect.hidden`. `TerminalWorkspace` stays mounted throughout — PTYs are never torn down, only the surface stops painting. `opacity: 0` rides alongside `visibility: hidden` because Electron can keep xterm's WebGL canvas composited after an ancestor goes hidden. Refs #71407 * fix(desktop): collapse an active tool pane onto the workspace, not a neighbour `setPaneCollapsed` on the ACTIVE pane of a shared zone that holds the uncloseable workspace handed the active slot to `group.panes[at - 1]` — the tab to its left, whichever that happened to be. The workspace can't minimize (it would strand the app), so tab-switching to a sibling is the right shape; picking a positional neighbour is not. In the Focus preset the terminal is a tab in the workspace's own group: [workspace, files, review, terminal] Collapsing the active terminal therefore selected `review`. The user asked for the terminal to go away and landed on a diff pane they never opened — and with the overlay still painting (before the previous commit), it read as "the terminal came back". Hand the slot to the uncloseable pane itself. That pane is the zone's anchor: it's the one member guaranteed to be a real destination rather than another tool the user was not asking for. The positional fallback stays for the defensive case of collapsing the uncloseable pane itself. This is deliberately broader than one entry point — every route into `setPaneCollapsed` for a shared zone gets it: the rail, the tab toggle, and ⌃`. Pure tool-only zones are untouched and still fold as a unit. * fix(desktop): front the workspace when a fresh chat starts `startFreshSessionDraft` resets the whole view — messages, usage, timers, route intent, cwd — but left `$terminalTakeover` set. That atom is not a cosmetic flag: `controller.tsx` binds it as the terminal's toggle store via `bindToolPaneCollapse`, so while it stays true the terminal keeps the pane fronted and ⌘N appeared to bounce straight back into the shell. Clear it, then `revealTreePane('workspace')`. The reveal is not redundant with the clear: takeover can already be false while the terminal is simply the active tab (the flag stays true behind a stacked sibling, and tile flows never touch it), so the state the user sees and the state the flag describes drift apart. Clearing homes the common case; revealing states the intent outright — a new chat shows the chat. The terminal is not torn down. Tool panels collapse to a rail and keep their PTYs; re-opening finds the same shell. The `+` / ⌘T tile path needs no takeover clear — it fronts its new tile through `revealTreePane` and relies on the hidden-pane-aware overlay. * fix(desktop): reveal the workspace without closing the terminal The fresh-session commit cleared `$terminalTakeover` on the way to fronting the workspace. That atom is not a Focus-only fronting flag — it is the terminal's open/closed state in every layout, and clearing it is wrong twice over. Only the Focus preset stacks the terminal with the workspace. Default, Terminal deck, and Quad each give it a zone of its own, where it sits beside the chat and obscures nothing — and there ⌘N minimized a terminal the user had deliberately open. The flag is also persisted, so the damage outlived the session. On the next boot the Focus terminal tab is still in the strip and its zone is not minimized, so clicking it only calls `activateTreePane`; `PersistentTerminal` mounts its workspace solely while takeover is true, so the tab fronted empty. `revealTreePane('workspace')` already carries the whole intent. Behind another tab the terminal is HIDDEN, not closed: it keeps its PTYs, and the overlay stops painting on the pane-hidden marker from the first commit in this branch — which is what was actually covering the chat. Removing the clear costs nothing and keeps the toggle store truthful. Two regression tests, both verified to fail when the clear is reinstated: a terminal in its own zone stays open and visible across a fresh chat, and a Focus terminal tab still mounts after a restart. Reported by Copilot review on #81019. --------- Co-authored-by: izumi0uu <izumi0uu@gmail.com> Co-authored-by: Ritesh Patel <60716910+DECRUX9812@users.noreply.github.com>