tabs.rs had grown to 538 lines — past the 500-line ceiling — and was
mixing four unrelated concerns:
- `tab_navigation` (URL changes + history back/forward)
- `tab_metadata` (title, favicon, zoom, favorite/pin, sort, sync flag)
- `tab_archive_restore` (un-archive entry points + query matching)
- core CRUD (open / close / move-to-space + private helpers)
Each split file lives below 250 lines and only pulls the `ely_domain`
types and crate helpers it actually uses. `active_tab_mut` and the
`TabUrlUpdate` enum get `pub(super)` so siblings can reach them; no
behaviour change.
Lift `apply_viewport`'s three-way diff (resize / set_hidpi / set_zoom)
into a `ViewportChange` value so the decision is testable without a
running `SoftwareServoHost`. Four unit cases pin the contract:
- Retina creation (DPR=2.0): only the hidpi push fires (the bug above).
- Standard-DPI creation (DPR=1.0): nothing to push, session already
matches Servo's defaults.
- Mid-session zoom change: only `set_page_zoom` fires.
- Cross-monitor DPR change: only the hidpi push fires.
This is a regression guard for the previous commit — any future change
that re-initializes a session from request values instead of Servo's
post-build defaults will fail `fresh_retina_session_pushes_hidpi_only`.
The newly-created session was stamped with the request's hidpi factor,
but `WebViewBuilder` defaults `hidpi_scale_factor` to 1.0 and we never
override it. `apply_viewport`'s diff check then saw
`session.dpr == request.dpr` and skipped `set_hidpi_scale`, leaving Servo
at hidpi=1.0 forever. On Retina that collapses CSS pixels onto device
pixels — the page lays out for a 2× viewport and renders at half size.
Same shape applies to page zoom.
Initialize the session with Servo's actual post-build defaults so the
viewport diff is the source of truth for whether `set_hidpi_scale` and
`set_page_zoom` need to run.
Drops the separate dashboard tile and the top-level "+" button so the
sidebar's first row holds a single workspace identity. "+ New
workspace" lives inside the disclosure popover next to the existing
spaces list, matching that row's geometry instead of inventing a new
square tile.
The previous 76 px traffic-light reserve only cleared the buttons
when the row also carried the tile and "+" — with the pill alone
plus its drop-shadow, it slid back behind the green button on the
default sidebar width. Widen `TRAFFIC_LIGHT_RESERVE` to 100 px and
document the derivation: pill outer left = `29 + RESERVE`, traffic-
light group right edge ≈ 112 px, so 100 leaves 17 px of breathing
room. Anchor solver and tests track the new geometry.