| <!DOCTYPE html> |
| <html lang="en"> |
| <head> |
| <meta charset="UTF-8" /> |
| <meta name="viewport" content="width=device-width, initial-scale=1.0" /> |
| <title>Lingo Bridge — Watch a sentence become another language</title> |
| <link rel="preconnect" href="https://fonts.googleapis.com"> |
| <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> |
| <link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=Space+Grotesk:wght@500;600;700&family=Share+Tech+Mono&display=swap" rel="stylesheet"> |
| <link rel="stylesheet" href="/static/style.css?v=21" /> |
| <link rel="icon" type="image/svg+xml" href="/static/logo.svg" /> |
| </head> |
| <body> |
| <div id="bg-glow"></div> |
|
|
| <header class="topbar"> |
| <div class="brand"> |
| <img src="/static/logo.svg" class="logo-img" alt="Lingo Bridge Logo" /> |
| <div> |
| <h1>Lingo Bridge</h1> |
| <p class="tag">Watch & hear a sentence gradually become another language.</p> |
| </div> |
| </div> |
| <div class="badges"> |
| <span class="badge" id="badge-llm">LLM: …</span> |
| <span class="badge" id="badge-tts">TTS: …</span> |
| </div> |
| </header> |
|
|
| <section class="controls"> |
| <textarea id="input" rows="1" placeholder="Type a sentence…">The cat sat quietly on the warm mat</textarea> |
| <div class="langrow"> |
| <select id="source" class="sel" aria-label="Source language"></select> |
| <button id="swap" class="swap" title="Swap languages">⇄</button> |
| <select id="target" class="sel" aria-label="Target language"></select> |
| <button id="example" class="playall" title="Load a random example sentence">🎲 Surprise me</button> |
| <button id="go" class="go">Translate →</button> |
| </div> |
| <div class="viewrow"> |
| <div class="perspective-control"> |
| <span class="lbl">2D</span> |
| <input type="range" id="perspective-slider" min="0" max="1" step="0.001" value="1" aria-label="Perspective Morph" /> |
| <span class="lbl">3D</span> |
| </div> |
| <button id="playall" class="playall" title="Play every layer in sequence">▶ Play all layers</button> |
| </div> |
| </section> |
|
|
| <main id="stage"> |
| <div id="view-cards" class="view"></div> |
| |
|
|
| |
| |
| <div class="zoom-controls"> |
| <div class="zoom-slider-wrap" title="Magnification (Zoom)"> |
| <button id="btn-zoom-in" class="zoom-btn" title="Zoom In (Magnification)" style="display: flex; align-items: center; justify-content: center; padding: 2px; height: 20px; width: 20px; border-radius: 3px; border: none; background: transparent; cursor: pointer; color: var(--muted); transition: color 0.15s;"> |
| <svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" style="opacity: 0.85;"> |
| <circle cx="11" cy="11" r="8"></circle> |
| <line x1="21" y1="21" x2="16.65" y2="16.65"></line> |
| <line x1="11" y1="8" x2="11" y2="14"></line> |
| <line x1="8" y1="11" x2="14" y2="11"></line> |
| </svg> |
| </button> |
| <input type="range" id="zoom-slider" min="0" max="1" step="0.001" value="0.5" class="zoom-slider" aria-label="Magnification Slider" /> |
| <button id="btn-zoom-out" class="zoom-btn" title="Zoom Out (Magnification)" style="display: flex; align-items: center; justify-content: center; padding: 2px; height: 20px; width: 20px; border-radius: 3px; border: none; background: transparent; cursor: pointer; color: var(--muted); transition: color 0.15s;"> |
| <svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" style="opacity: 0.85;"> |
| <circle cx="11" cy="11" r="8"></circle> |
| <line x1="21" y1="21" x2="16.65" y2="16.65"></line> |
| <line x1="8" y1="11" x2="14" y2="11"></line> |
| </svg> |
| </button> |
| </div> |
| <div style="height: 1px; background: rgba(150, 170, 255, 0.15); margin: 4px 0;"></div> |
| <button id="btn-rotate-left" class="zoom-btn" title="Rotate Left" style="display: flex; align-items: center; justify-content: center; padding: 2px;"> |
| <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="opacity: 0.85;"> |
| |
| <path d="M 4 12 C 4 7.5, 20 7.5, 20 12" stroke-dasharray="3 3" opacity="0.45" /> |
| |
| <line x1="12" y1="3" x2="12" y2="21" stroke-width="2.5" /> |
| |
| <path d="M 20 12 C 20 16.5, 4 16.5, 4 12" /> |
| <polyline points="8 9 4 12 8 15" /> |
| </svg> |
| </button> |
| <button id="btn-rotate-right" class="zoom-btn" title="Rotate Right" style="display: flex; align-items: center; justify-content: center; padding: 2px;"> |
| <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="opacity: 0.85;"> |
| |
| <path d="M 20 12 C 20 7.5, 4 7.5, 4 12" stroke-dasharray="3 3" opacity="0.45" /> |
| |
| <line x1="12" y1="3" x2="12" y2="21" stroke-width="2.5" /> |
| |
| <path d="M 4 12 C 4 16.5, 20 16.5, 20 12" /> |
| <polyline points="16 9 20 12 16 15" /> |
| </svg> |
| </button> |
| <div style="height: 1px; background: rgba(150, 170, 255, 0.15); margin: 4px 0;"></div> |
| <button id="btn-move-forward" class="zoom-btn" title="Move Forward (Push In)" style="display: flex; align-items: center; justify-content: center; padding: 2px;"> |
| <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="none" xmlns="http://www.w3.org/2000/svg" style="opacity: 0.85;"> |
| |
| |
| <polygon points="6.5,17.5 17.5,17.5 17.5,20 6.5,20" fill="currentColor" fill-opacity="0.5" stroke="var(--bg)" stroke-width="0.8" stroke-linejoin="round" /> |
| <polygon points="5.5,8.5 10,8.5 10,10.5 5.5,10.5" fill="currentColor" fill-opacity="0.5" stroke="var(--bg)" stroke-width="0.8" stroke-linejoin="round" /> |
| <polygon points="14,8.5 18.5,8.5 18.5,10.5 14,10.5" fill="currentColor" fill-opacity="0.5" stroke="var(--bg)" stroke-width="0.8" stroke-linejoin="round" /> |
| |
| <polygon points="6.5,17.5 17.5,17.5 14,8.5 18.5,8.5 12,4 5.5,8.5 10,8.5" fill="currentColor" fill-opacity="0.95" stroke="var(--bg)" stroke-width="0.8" stroke-linejoin="round" /> |
| </svg> |
| </button> |
| <button id="btn-move-backward" class="zoom-btn" title="Move Backward (Push Out)" style="display: flex; align-items: center; justify-content: center; padding: 2px;"> |
| <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="none" xmlns="http://www.w3.org/2000/svg" style="opacity: 0.85;"> |
| |
| |
| <polygon points="6.5,6.5 17.5,6.5 17.5,4 6.5,4" fill="currentColor" fill-opacity="0.5" stroke="var(--bg)" stroke-width="0.8" stroke-linejoin="round" /> |
| <polygon points="5.5,15.5 10,15.5 10,13.5 5.5,13.5" fill="currentColor" fill-opacity="0.5" stroke="var(--bg)" stroke-width="0.8" stroke-linejoin="round" /> |
| <polygon points="14,15.5 18.5,15.5 18.5,13.5 14,13.5" fill="currentColor" fill-opacity="0.5" stroke="var(--bg)" stroke-width="0.8" stroke-linejoin="round" /> |
| |
| <polygon points="6.5,6.5 17.5,6.5 14,15.5 18.5,15.5 12,20 5.5,15.5 10,15.5" fill="currentColor" fill-opacity="0.95" stroke="var(--bg)" stroke-width="0.8" stroke-linejoin="round" /> |
| </svg> |
| </button> |
| </div> |
| |
| <div id="loader" class="loader hidden"><div class="spin"></div><span id="loadmsg">Thinking…</span></div> |
| <div id="hint" class="hint"> |
| <div class="hint-icon-wrap"> |
| <img src="/static/logo.svg" class="hint-logo" alt="Lingo Bridge Logo" /> |
| </div> |
| <h2>Welcome to Lingo Bridge</h2> |
| <p class="hint-tagline">An interactive toy exploring the migration of language, grammar, and word order.</p> |
| <div class="hint-steps"> |
| <div class="hint-step"> |
| <span class="step-num">1</span> |
| <p>Type a sentence above or click <b>🎲 Surprise me</b></p> |
| </div> |
| <div class="hint-step"> |
| <span class="step-num">2</span> |
| <p>Click <b>Translate →</b> to decompose it into 7 layered steps</p> |
| </div> |
| <div class="hint-step"> |
| <span class="step-num">3</span> |
| <p>Hover over phrases to trace the path, or click <b>▶ Play</b> to hear them</p> |
| </div> |
| </div> |
| </div> |
| </main> |
|
|
| <audio id="player"></audio> |
|
|
| <script type="importmap"> |
| { "imports": { |
| "three": "/static/vendor/three.module.js", |
| "three/addons/controls/OrbitControls.js": "/static/vendor/OrbitControls.js" |
| }} |
| </script> |
| <script src="/static/app.js?v=21" type="module"></script> |
| </body> |
| </html> |
|
|