lingo-bridge / static /index.html
Iona401's picture
Disable wheel-zoom so embedded 3D view does not expand on scroll
9f074fb verified
Raw
History Blame Contribute Delete
9.39 kB
<!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&nbsp;Bridge</h1>
<p class="tag">Watch &amp; 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>
<!-- Floating Zoom & Rotation Widget -->
<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;">
<!-- Back of revolve (dashed) -->
<path d="M 4 12 C 4 7.5, 20 7.5, 20 12" stroke-dasharray="3 3" opacity="0.45" />
<!-- Vertical axis bar -->
<line x1="12" y1="3" x2="12" y2="21" stroke-width="2.5" />
<!-- Front of revolve (solid) -->
<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;">
<!-- Back of revolve (dashed) -->
<path d="M 20 12 C 20 7.5, 4 7.5, 4 12" stroke-dasharray="3 3" opacity="0.45" />
<!-- Vertical axis bar -->
<line x1="12" y1="3" x2="12" y2="21" stroke-width="2.5" />
<!-- Front of revolve (solid) -->
<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;">
<!-- 3D Tapered Arrow pointing Up/Away (Move Forward) - Wide Observable Wings -->
<!-- Thickness / Shadow Faces -->
<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" />
<!-- Main Front Face -->
<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;">
<!-- 3D Tapered Arrow pointing Down/Towards (Move Backward) - Wide Observable Wings -->
<!-- Thickness / Shadow Faces -->
<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" />
<!-- Main Front Face -->
<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>