## Description
<!-- Please insert your description here and especially provide info
about the "what" this PR is solving -->
### As-is
Depending on the size, the Controls Island area gets cut off, making the
buttons in the cropped area inaccessible.
### To-be
The Controls Island is managed via scrolling, allowing interaction with
buttons regardless of the size.
If the main controls also exceed the available space, the entire
Controls Island becomes scrollable. Horizontal scrolling is available
for narrow windows.
#### narrow & smaill
https://github.com/user-attachments/assets/1a44ff4f-8fe2-4a05-96a8-59ebf7dafcff
#### somewhat generous size
https://github.com/user-attachments/assets/c73dbee4-8c8f-4937-ae1a-eda00178274c
## Linked Issues
<!-- Optional, if you have any -->
close#2400
## Additional Context
<!-- e.g. is there anything you'd like reviewers to focus on? -->
Although the size is somewhat less than ideal, the issue has been
resolved, and this serves as a universal solution.
---------
Co-authored-by: leafyy <wuqizq@outlook.com>
## Summary
- Send a serializable Live2D expression snapshot from the stage renderer
to the separate Settings window.
- Route expression changes back to the renderer that owns the loaded
model, with owner ID checks for stale-window isolation.
- Add browser regressions for the component boundary and the complete
BroadcastChannel round trip.
Fixes#2450
## Verification
- `pnpm typecheck`
- `pnpm lint`
- `../../node_modules/.bin/vitest run --project browser
src/components/scenarios/settings/model-settings/live2d.browser.test.ts`
- `node_modules/.bin/vitest run --config
apps/stage-tamagotchi/vitest.config.ts --project browser
apps/stage-tamagotchi/src/renderer/composables/model-settings-runtime.browser.test.ts`
- `./node_modules/.bin/electron-vite build`
- Vishot Electron capture with the issue Live2D fixture on the merge
base and this branch
- `sem diff upstream/main...HEAD --no-cosmetics -v --file-exts .ts .tsx`
## Visual changes
| Before | After |
|---|---|
|

|

|
| Settings / Models / Live2D expressions: empty list | Settings / Models
/ Live2D expressions: model entries are available |
## Description
Let `dev` and `start` scripts run `install-electron` before
`electron-vite`.
Electron 42 removed the `postinstall` script. The `electron` package now
downloads its binary on its `bin` entry's first run. `electron-vite`
reads `node_modules/electron/path.txt` directly, so it never starts that
download. A fresh install therefore fails with:
```
error during start dev server and electron app:
Error: Electron uninstall
at getElectronPath (...)
...
```
`install-electron` runs the same code as the removed `postinstall`
script. It returns immediately when the binary is already present.