4.3 KiB
Persona rendering concerns
Each selectable persona owns src/personas/<id>/effect.ts. Its existing persona registry definition exposes a lazy effect.load() plus opacity and DPR limits. Gateway and pause have no ambient renderer. The shared contract contains only resize, draw, destroy, and frame input; it imports no persona algorithms.
| Persona | Rendering concern | Work bound |
|---|---|---|
| Samantha69 | WebGL soft pink word bloom, grain, pointer warmth | Four Gaussian levels cached on resize; one composite per frame |
| Nelly | Refractive aqua wave contours | Precomputed spatial waves; twelve shade paths |
| Hisoka | Metallic 4 × 6 Lissajous table | Precomputed positions/tangents, 32 shade buckets per cell |
| Xixi | Crystal facets and interference seams | Cached facet geometry and shared lighting |
| Cybelle | Confetti and rosette geometry | Cached rosettes, batched confetti |
| Galatée | Cloudy carved-word reveal | One WebGL pass, shared texture parallax |
| Polaire | Touching-disc negative-space lattice | 42 columns, whole inset rows, one even-odd field fill |
Placement
The selected onboarding tile and active chat atmosphere mount the effect. The all-persona chooser mounts no persona engines. It mounts one shared landing fluid atmosphere; selected onboarding adds one persona tile engine. Existing generated images, ornaments, Arizona typography, semantic links, and readable HTML remain the base composition. Buttons and composer retain image/SVG treatments instead of multiplying GPU contexts or animation loops. Decoration does not intercept pointer events or enter the accessibility tree.
PersonaEffectSurface owns visibility, route-pending state, resize, pointer input, reduced-motion changes, and one animation clock. Rendering is capped at 30 submissions per second, DPR at 1.5 or 2 by persona. Hidden/offscreen/navigation pauses preserve active time. Reduced motion draws a resolved still. A renderer change replaces the canvas, allowing Canvas 2D/WebGL switches. Unsupported or lost contexts leave the original artwork usable.
Verification
- 18 phone browser checks passed: all seven renderer switches, lazy loading, reduced motion, offscreen pause, simulated document visibility, WebGL absence, onboarding geometry and generated-image decoding.
- 183 registry/context unit checks passed. The test runner reported a server shutdown timeout after successful tests.
- Production build emits seven separate effect chunks, approximately 1.4–3.7 kB each before gzip.
- Seven selected tiles inspected at 390 × 844; overflow tested at 320 px.
- Isolated desktop CPU submission measurements: Polaire median 0.3 ms / p95 0.6 ms; Hisoka median 2.0 ms / p95 2.8 ms at card size. These are not mobile-device FPS or GPU timings.
Physical-phone GPU profiling remains a useful follow-up. Motion is deliberately concentrated in a shared onboarding atmosphere and the selected tile, not repeated on every control.
Landing alignment and shared tile transitions
Onboarding reuses the landing palette verbatim in onboarding-landing.css, its 8px dot texture, and the original hero scrims. landing-fluid.ts ports all ten GLSL blocks unchanged from the landing hero, including its current neon palette and ASCII display. The common renderer host supplies pause, reduced-motion, pointer, and cleanup behavior; simulation buffers use half-float targets. Arizona remains the application typeface.
The chooser is two columns with 154px compact tiles. Selecting a persona expands the same PersonaTile component to its full layout. Stable per-persona view-transition names on tile, avatar, and title pair both renders; the tile link and back link enable TanStack view transitions. Reduced motion disables the transition. Unsupported browsers navigate normally.
Browser checks verify exact black/text palette, 8px texture, live shader initialization, 320/390px two-column bounds, and successful native transition ready/finished events forward and backward.