"Anchor 8 quoted the README: dock is intentionally out of v1. Then dock shipped — and overlay came with it. This anchor is what the extension learned on the way."
The Shape That Replaced One Surface With Three
ChromeEmbed v0.1 had exactly one place Pippa could appear: Chrome's own side panel. v0.2 has three, and the extension names them in a single array near the top of the service worker.
That array is doing more work than it looks like. It is the allowlist, the normalizer's source of truth, and the first thing a reader greps for. Every mode value that flows through the bus, out of storage, or in from the popup passes normalizeDisplayMode — and anything unrecognized becomes 'sidepanel' rather than an error. An extension that has been installed for months and read a mode string written by an older version does not get to crash over it.
Two Renderers, Not One
The interesting part is that the three modes are not three variations of one implementation. They split across two completely different rendering paths:
- Side panel — Chrome renders it. The extension calls
chrome.sidePanel.open({ windowId })and the browser owns the frame, its width, its close button, and its persistence. That is Anchor 5's iframe bridge, unchanged. - Dock and overlay — the content script renders them. There is no Chrome API for "a floating window over the page." The extension injects its own element, sets its own geometry, installs its own drag and resize handles, and remembers its own size.
So a single toggle in the popup crosses an architectural boundary. Choosing side panel is a request to the browser; choosing dock or overlay is a request to a script running inside someone else's page. Anchor 3 built the sensor that reads the page — the same content script now also draws on it.
Why Dock Needs Page Padding And Overlay Does Not
Overlay floats. It sits over the page at a position the user dragged it to, and the page underneath does not know it exists — which is fine, because the user can move it off whatever it is covering.
Dock is pinned to the bottom edge across the full width. Nothing can be dragged out from under it. Without intervention it permanently hides the bottom strip of every page — often exactly where a submit button or a pagination control lives. So the dock path adds bottom padding to the page equal to its own height, and re-applies that padding through a ResizeObserver whenever the user drags the dock taller or shorter.
That observer is created only in dock mode and disconnected the moment the mode changes. A ResizeObserver left running on every page for a feature that is not currently visible is the kind of cost that does not show up in testing and does show up in a user's battery.
The Mode Has To Survive The Tab
A display preference that resets on navigation is not a preference. Dock and overlay live inside a content script, and a content script dies with its page — so the mode is written to chrome.storage.local and the service worker caches it in a promise so repeated reads do not re-hit storage.
Note which storage area: local, not session. The same file uses chrome.storage.session for the browser session id, because a session id should die when the browser closes. A display mode should not. Same API, opposite lifetime, and the choice between them is a product decision wearing a storage-area name.
What Anchor 4's Popup Became
Once there are three modes, something has to choose between them — and the only surface the user can reach without Pippa already being open is the toolbar popup. That is why the six-line doorway of Anchor 4 grew: not because someone wanted a richer popup, but because mode selection has nowhere else to live.
It still refuses to be an experience surface. No chat, no message preview, no input field. Three buttons and a selector, then window.close(). The doorway principle held; only the number of doors changed.
The Lesson Anchor 8 Could Not Teach
Anchor 8 predicted dock would need a shadow root, a high z-index, drag handles, and an iframe pointed at a smaller route. Every one of those turned out right — Anchor 7's refactor discipline held, and the deferred feature landed close to the sketch.
What the sketch could not predict was overlay. It is not on Anchor 8's list of four deferred features at all. It appeared because once the content script could draw one floating surface, the second one was nearly free — the geometry code, the drag handles, the storage layer, and the mode plumbing were already built. The expensive part was crossing from "Chrome renders our UI" to "we render our UI." After that crossing, modes are cheap.
That is the shape worth carrying out of this quest: deferred-feature lists are guesses about cost, and cost moves. The moment a boundary gets crossed for one reason, re-read the list — some of what is on it may have just become nearly free, and some of what is not on it may now be worth having.