Back to Funclet
SOURCE / PINNED RELEASE

Made of little things.

Funclet

Release
0b497cfc2f66…
Author-recorded commit
1e531b24f490…
License
LICENSE
Author’s source reference
nostr://npub182jczunncwe0jn6frpqwq3e0qjws7yqqnc3auccqv9nte2dnd63scjm4rf/wss%3A%2F%2Fgit.napplet.soy%2F/n-6b7a37cac1d

Archive hash verified: 71d97a89ed8c40c2…. The source-to-build association is the author’s claim; it has not been independently rebuilt.

docs/funclet-mobile-graphics.md
# Mobile graphics repair — 2026-10-23

Reported browser: Brave on Android. The phone model, GPU, browser version and
device crash log were not available. This repair addresses confirmed weaknesses
in the renderer; the original physical-device crash has not been reproduced.

## Diagnosis

The renderer used multisample antialiasing, a 1024×1024 dynamic shadow map and an
uncapped animation loop on touch devices. Its constructor caught graphics errors,
but subsequent animation-frame and ResizeObserver errors escaped. Injecting a
WebGL draw failure into the previous built artifact produced an uncaught error
and left `data-renderer="webgl"` on a frozen scene instead of showing the fallback.

The ranked hypotheses were mobile GPU pressure, an unhandled asynchronous draw
failure, and engine-specific context handling. The second was reproduced. GPU
pressure is a plausible trigger, not a proven diagnosis of this particular phone.
The user's Brave clarification focused verification on Chromium rather than WebKit.

## Changes

- Coarse-pointer devices use a 30 fps render limit, no multisample antialiasing,
  and a 128×128 contact-shadow texture instead of a dynamic shadow pass.
- Mobile drawing buffers are capped at 1.25 DPR, 400,000 pixels and 1024 pixels
  per dimension. Desktop rendering retains dynamic shadows, with its own bounds.
- Offscreen receivers stop rendering and resume when visible. Reduced motion,
  visibility changes and the existing station-detail suspension remain supported.
- Drawing, resize, display-texture and shader-link failures switch to the existing
  accessible fallback. One transient context loss can recover; repeated loss
  releases the graphics resources without recreating the playback session.
- The radio, physical controls, rotating WF cube and shader remain real 3D.
  No shell capability, relay routing or playback ownership changed.

## Evidence

At a 390×844 viewport with device scale factor 3, the measured canvas changed from
640×439 to 457×313 (49% fewer pixels). The one-second samples recorded 8,190 versus
4,320 draw calls. The updated sample rendered 30 frames and allocated no shadow
renderbuffer. These are local Chromium measurements, not Android benchmarks.

`pnpm test:mobile` exercises the built artifact in a sandboxed iframe with Pixel 7
emulation and explicit host fixtures. It checks animation, portrait/landscape
resizing, buffer limits, offscreen suspension, a genuine WebGL context loss and
restoration, repeated loss, and injected draw/resize/shader failures. Normal radio
controls remain functional after each permanent graphics failure, without retuning.

The existing UI suite also passes, including mesh controls, reduced motion,
no-WebGL startup, optional-domain absence and seven sizes in both host themes.
Real soyLI-hosted search, playback, CVM metadata, volume, pause/resume, artist
search and settings pass without fixture data. Unit tests (16), guidance checks
(6), type checking and the build pass. Conformance reports 5 passed, 0 failed,
5 skipped: no manifest evidence, wire envelopes or teardown evidence is supplied
to that reference-shell invocation; its skipped checks are not verified by it.

The public release regression also supports `--mobile` to check the actual signed
artifact at Android density with real search and playback. Physical Brave/Android
validation remains a separate device check; desktop emulation cannot establish
driver stability or browser-process recovery on the reported phone.