File size: 9,387 Bytes
7135dbd
 
 
 
 
 
 
 
 
9f074fb
7135dbd
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
9f074fb
7135dbd
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
<!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>