Each waterlily represents a single input item:
sourceType:textorimagecontent: the original text, or a local URL for the chosen imageembedding: a normalized CLIP vectorshapePath: an SVG path derived from the embedding valuesfill,outline: colors derived deterministically from the embedding (constrained to a pink-to-near-white palette)x,y: 2D coordinates produced by PCA over all lilies
The UI is intentionally simple: grow a lily (compute an embedding), preview it, then plant it into the pond. Hover for a quick peek; click for details.
- Click
New Waterlily(orGrow your first Waterlily!when the pond is empty). - In the modal (
src/components/LilyCreator.vue), choose Text or Image and provide input. - Click
Grow waterlily. - The app computes an embedding and shows an “embedding numbers” animation.
- First lily is intentionally slower (~8s) so the process is legible.
- Later lilies are faster (~2–3s) so the app stays snappy.
- A preview appears (lily shape + lily pads).
- Click
Plant waterlilyto place it into the pond (manual planting; no auto-plant). - Hover any lily for a lightweight preview popover.
- Click any lily to open the detailed inspector popover.
- Optional: open the bottom-left Info panel for plain-language explanations.
src/components/LilyCreator.vueemitsgrowwith{ type, data }.src/App.vuehandlesgrow:computeEmbedding(type, data)-> embedding vectorembeddingToPath(embedding)-> lily SVG path- derive deterministic colors from embedding
- keep the result as a “draft” until the user plants
- Planting in
src/App.vue:- append the draft lily to the list
computePcaLayout(lilies.map(l => l.embedding))->{x,y}for each lily- animate the new lily from the “plant” origin into its PCA target
- persist final
{x,y}into the stored lily list
src/components/PondScene.vue:- renders lilies as positioned buttons centered in the viewport
- emits
hoveron pointer enter/leave andselecton click
src/components/LilyPopover.vue:- click mode: shows the original input and the full embedding vector (with a scrollable values box)
- hover mode: shows a compact preview only (no embedding values; no close button)
src/components/InfoPopover.vue:- centered, light-background panel with neutral/scientific explanations
- PCA is recomputed on every planting so positions are consistent for all lilies.
- PCA output is normalized into screen space using the current
window.innerWidth/innerHeight.
- Lily shapes are radial polygons: each embedding component maps to a radius at a fixed angle.
- Lily pad geometry is shared between pond + preview via
src/utils/lilyPad.ts. - Decorative lily pads, drift, and ripples are generated procedurally for atmosphere.
- Ripples are triggered by both water clicks and planting a lily.
- A subtle “ambient” ripple is seeded on load near the
New Waterlilybutton so the scene doesn’t start perfectly still. src/components/CausticsCanvas.vuecontains an experimental Three.js ripple + caustics shader canvas (not currently mounted by default).