Spaces:
Running on Zero
Running on Zero
| <!-- | |
| Lightloom — "speak, and your world unrolls ahead of you." | |
| A full-bleed immersive 3D corridor: each phrase you narrate becomes a vivid, | |
| depth-displaced scene the camera flies forward through. Served framework-free by | |
| gradio.Server. No build step, no npm. Vanilla ES modules + WebGL (Three.js). | |
| English-default; ES is a toggle. The world IS the interface. | |
| --> | |
| <html lang="en" data-lang="en"> | |
| <head> | |
| <meta charset="utf-8" /> | |
| <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover" /> | |
| <meta name="color-scheme" content="dark" /> | |
| <meta name="theme-color" content="#07080c" /> | |
| <title>Lightloom — speak your world into being</title> | |
| <meta | |
| name="description" | |
| content="Speak, and your world unrolls ahead of you. Lightloom turns your voice into an endless, explorable 3D world — tiny local models listen, direct, paint and give depth to every scene in real time." | |
| /> | |
| <!-- Preload the self-hosted hero fonts so the title card / wordmark never FOUT-flash Georgia first. --> | |
| <link rel="preload" as="font" type="font/woff2" crossorigin href="/assets/fonts/Fraunces-Variable.woff2" /> | |
| <link rel="preload" as="font" type="font/woff2" crossorigin href="/assets/fonts/Inter-Variable.woff2" /> | |
| <link rel="stylesheet" href="/frontend/css/tokens.css" /> | |
| <link rel="stylesheet" href="/frontend/css/immersive.css" /> | |
| <script type="importmap"> | |
| { "imports": { "three": "/frontend/vendor/three.module.js" } } | |
| </script> | |
| </head> | |
| <body> | |
| <!-- The world: a full-bleed 3D corridor that is always behind everything. --> | |
| <canvas id="world-canvas" aria-hidden="true"></canvas> | |
| <div id="world-veil" aria-hidden="true"></div> | |
| <!-- Top HUD: brand + the live orchestra (which tiny model is working now) + counter. --> | |
| <header id="hud" class="hud"> | |
| <span class="hud__brand">LIGHT<b>LOOM</b></span> | |
| <nav class="orchestra" aria-label="Model orchestra"> | |
| <span class="orch" id="orch-asr"><i></i>Voice</span> | |
| <span class="orch" id="orch-director"><i></i>Director</span> | |
| <span class="orch" id="orch-painter"><i></i>Painter</span> | |
| <span class="orch" id="orch-depth"><i></i>Depth</span> | |
| </nav> | |
| <span class="hud__count" id="scene-count" aria-live="polite"></span> | |
| </header> | |
| <!-- "Now playing": the live model's one-line job (lit by controller._orch). --> | |
| <div id="now-playing" class="hud__now" aria-live="polite"></div> | |
| <!-- Intro: the living world already fills the screen; a small mic is the only call. --> | |
| <section id="intro" class="intro"> | |
| <p class="intro__tag"> | |
| <span data-en>Speak, and your world unrolls ahead of you.</span> | |
| <span data-es hidden>Habla, y tu mundo se desenrolla ante ti.</span> | |
| </p> | |
| <button id="mic-btn" class="mic" type="button" aria-label="Hold the mic and speak your story"> | |
| <span class="mic__ring"></span> | |
| <span class="mic__dot">🎤</span> | |
| </button> | |
| <p class="mic__hint" id="mic-hint"> | |
| <span data-en>Tap, speak, tap again — watch it become a world.</span> | |
| <span data-es hidden>Toca, habla, toca de nuevo — mírala volverse mundo.</span> | |
| </p> | |
| <div class="intro__alt"> | |
| <button id="type-toggle" class="ghost" type="button"> | |
| <span data-en>or type a story</span><span data-es hidden>o escribe una historia</span> | |
| </button> | |
| <button id="showcase-btn" class="ghost" type="button"> | |
| <span data-en>watch the showcase</span><span data-es hidden>ver el showcase</span> | |
| </button> | |
| </div> | |
| <div id="composer" class="composer" hidden> | |
| <textarea | |
| id="story-text" | |
| class="composer__text" | |
| rows="3" | |
| spellcheck="false" | |
| placeholder="An old lighthouse keeper counted the waves at the edge of the world. Far away, a market woke under orange awnings. A child ran through a garden of impossible glowing flowers." | |
| >An old lighthouse keeper counted the waves at the edge of the world. Far away, a market woke under orange awnings and warm morning light. A child ran through a garden of impossible glowing flowers. Then snow buried the quiet road in silence.</textarea> | |
| <button id="begin-btn" class="begin" type="button"> | |
| <span data-en>Begin the world</span><span data-es hidden>Comenzar el mundo</span> | |
| </button> | |
| </div> | |
| </section> | |
| <!-- The Director's name for your world (MiniCPM) — a delightful title for your creation. --> | |
| <div id="world-title" class="world-title" aria-live="polite"></div> | |
| <!-- Floating transcript: the words that are becoming the world. --> | |
| <div id="transcript" class="transcript" aria-live="polite"></div> | |
| <!-- Status line (warming / listening / quota), unobtrusive. --> | |
| <div id="status" class="status" role="status" aria-live="polite"></div> | |
| <!-- Bottom controls (appear once a world is live). --> | |
| <div id="controls" class="controls" hidden> | |
| <button id="mic-mini" class="ctl" type="button" title="Speak more" aria-label="Speak more">🎤</button> | |
| <button id="save-btn" class="ctl" type="button" title="Save your world" aria-label="Save your world">🎬</button> | |
| <button id="stop-btn" class="ctl" type="button" title="New world" aria-label="New world">⟲</button> | |
| <button id="rm-btn" class="ctl" type="button" title="Reduce motion" aria-label="Reduce motion">🐢</button> | |
| <button id="about-btn" class="ctl" type="button" title="About" aria-label="About">ⓘ</button> | |
| </div> | |
| <!-- About overlay: the orchestra + honest ledger. --> | |
| <section id="about" class="about" hidden role="dialog" aria-modal="true" aria-label="About Lightloom"> | |
| <div class="about__panel"> | |
| <button id="about-close" class="about__close" type="button" aria-label="Close">✕</button> | |
| <h2>Lightloom</h2> | |
| <p class="about__lead" data-en> | |
| You speak; tiny <b>local</b> models turn your words into a living world. | |
| <b>NVIDIA Parakeet</b> hears you, an OpenBMB <b>MiniCPM</b> director shapes each scene, | |
| <b>FLUX.2 klein</b> paints it, <b>Depth-Anything</b> gives it depth — and when you finish, | |
| an OpenBMB <b>MiniCPM-V</b> art director names your world from its own pixels. | |
| Zero cloud APIs. | |
| </p> | |
| <p class="about__lead" data-es hidden> | |
| Tú hablas; modelos <b>locales</b> diminutos convierten tus palabras en un mundo vivo. | |
| <b>NVIDIA Parakeet</b> te escucha, un director <b>MiniCPM</b> de OpenBMB moldea cada escena, | |
| <b>FLUX.2 klein</b> la pinta, <b>Depth-Anything</b> le da profundidad — y al terminar, un | |
| director de arte <b>MiniCPM-V</b> de OpenBMB nombra tu mundo a partir de sus propios píxeles. | |
| Cero APIs en la nube. | |
| </p> | |
| <p class="about__note" id="about-ledger">6.13B / 32B parameters · all local · Off the Grid</p> | |
| </div> | |
| </section> | |
| <!-- Director's Cut keepsake: the MiniCPM-V-named fly-through film of your finished world (injected by | |
| controller._showKeepsake on the 🎬 button). Independent post-process; never blocks the live world. --> | |
| <section id="keepsake" class="keepsake" hidden role="dialog" aria-modal="true" aria-label="Your saved world"></section> | |
| <!-- ES modules in dependency order. The corridor controller wires everything. --> | |
| <script type="module" src="/frontend/js/api.js"></script> | |
| <script type="module" src="/frontend/js/recorder.js"></script> | |
| <script type="module" src="/frontend/js/stage-scroll.js"></script> | |
| <script type="module" src="/frontend/js/explore3d.js"></script> | |
| <script type="module" src="/frontend/js/controller.js"></script> | |
| </body> | |
| </html> | |