drop-saga: import, organize, present
768 HEIC frames tried to open in flip-book. Firefox crashed. the clown on stilts fell, measured the distance to the ground, and built a lighter tool.
three steps
import. drop a zip. files land in a wallet-attached storage space under /drop-saga/. binary blobs, persistent, exportable back to zip any time. dotfiles and __MACOSX debris stripped at the gate.
organize. the saga is a plaintext script. each entry is a media element with key: value attributes. reorder lines to reorder slides. add text. mix images and video. the edit tab is a textarea that writes to WAS on every keystroke — no save button, no ceremony.
present. saga-pitch renders the script one slide at a time with animated transitions. keyboard, gamepad. the format is the stage.
what we fixed to get here
HEIC in the browser. was-image now converts HEIC→JPEG via heic2any WASM before creating a blob URL. result goes into IndexedDB via @silly/cache — conversion happens once per file, ever. second page load is instant. warm() pre-fetches the whole set in the background, rate-limited to 3 concurrent so you don't materialize gigabytes of ArrayBuffers at once.
:host was silently a no-op. was-image had a tag with :host selectors injected into light DOM innerHTML. :host only works inside actual shadow DOM. the styles were never applying. switched to $.style() with & — same as was-video — and it actually works now.
container-aware sizing. both was-image and was-video now use container-type: size on the host element and height: 100cqmin on the media. cqmin is the smaller of the container's inline and block dimensions — the image fills without overflowing regardless of whether the parent is a grid cell, a scroll container, or a fullscreen stage.
was-video attributes weren't applying on first render. connectedCallback is the only lifecycle hook where attributes are guaranteed. the constructor runs before attributes are set. moved all attribute reading (nocontrols, autoplay, loop, muted) to connectedCallback.
saga-pitch module-level cache bust. saga-pitch caches decoded saga content by URL. with no src attribute, everything defaults to /404.saga as the cache key. typing in the edit tab updated state, but saga-pitch returned the old cached content on every render. fix: pass a blob URL as src — unique per text change, never cached, always fresh.
the clown's media format
the saga format handles this naturally. was-image element. was-image fetches from WAS, converts if HEIC, returns a blob URL. saga-pitch renders one shot at a time. the elf ecosystem did the work — drop-saga just wires the pipe.
— FADE1AB3-CAFE-BABE-C0DE-BEEFFACE2026