radinplaid commited on
Commit
4e41745
·
1 Parent(s): b6b0c93

Initial commit

Browse files
Files changed (2) hide show
  1. index.html +212 -0
  2. style.css +668 -0
index.html ADDED
@@ -0,0 +1,212 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+
4
+ <head>
5
+ <meta charset="UTF-8">
6
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
7
+ <title>QuickMT Machine Translation</title>
8
+ <link rel="preconnect" href="https://fonts.googleapis.com">
9
+ <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
10
+ <link
11
+ href="https://fonts.googleapis.com/css2?family=Outfit:wght@300;400;500;600;700&family=Inter:wght@300;400;500;600&display=swap"
12
+ rel="stylesheet">
13
+ <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css">
14
+ <link rel="stylesheet" href="style.css">
15
+ </head>
16
+
17
+ <body>
18
+ <div class="bg-blur"></div>
19
+
20
+ <div class="top-nav-links">
21
+ <a href="https://huggingface.co/quickmt" target="_blank" title="Hugging Face Models" class="glass-btn">
22
+ <span class="btn-icon">🤗</span>
23
+ </a>
24
+ <a href="https://github.com/quickmt/quickmt" target="_blank" title="GitHub Repository"
25
+ class="glass-btn icon-only">
26
+ <span class="btn-icon"><i class="fa-brands fa-github"></i></span>
27
+ </a>
28
+ </div>
29
+
30
+ <main class="app-container">
31
+ <!-- Sidebar Navigation -->
32
+ <nav class="sidebar glass">
33
+ <div class="logo">
34
+ <div class="logo-icon">Q</div>
35
+ <span>QuickMT</span>
36
+ </div>
37
+ <ul class="nav-links">
38
+ <li class="active">
39
+ <a href="#translate">
40
+ <span class="nav-icon">🔁</span>
41
+ <span class="nav-text">Translate</span>
42
+ </a>
43
+ </li>
44
+ <li>
45
+ <a href="#models">
46
+ <span class="nav-icon">🧩</span>
47
+ <span class="nav-text">Models</span>
48
+ </a>
49
+ </li>
50
+ <li>
51
+ <a href="#settings">
52
+ <span class="nav-icon">⚙️</span>
53
+ <span class="nav-text">Settings</span>
54
+ </a>
55
+ </li>
56
+ </ul>
57
+ <div class="sidebar-footer">
58
+ <div id="health-indicator" class="status-pill status-loading">
59
+ <span class="dot"></span>
60
+ <span class="status-text">Connecting...</span>
61
+ </div>
62
+ <div class="theme-toggle-container">
63
+ <button id="theme-toggle" title="Toggle Light/Dark Mode">
64
+ <span class="mode-icon">◑</span>
65
+ <span class="mode-text">Dark Mode</span>
66
+ </button>
67
+ </div>
68
+ <button id="sidebar-toggle" class="icon-btn collapse-btn" title="Toggle Sidebar">«</button>
69
+ </div>
70
+ </nav>
71
+
72
+ <!-- Main Content -->
73
+ <section class="content">
74
+ <!-- Translate View -->
75
+ <div id="translate-view" class="view active">
76
+ <header class="view-header">
77
+ <h1>QuickMT Neural MachineTranslation</h1>
78
+ </header>
79
+
80
+ <div class="translation-grid">
81
+ <!-- Source Column -->
82
+ <div class="card glass translation-card">
83
+ <div class="card-header">
84
+ <div class="lang-group">
85
+ <span class="lang-label">From</span>
86
+ <select id="src-lang-select" class="lang-select">
87
+ <option value="">Auto-detect</option>
88
+ </select>
89
+ </div>
90
+ <div id="detected-badge" class="detected-badge"></div>
91
+ </div>
92
+ <div class="card-body">
93
+ <textarea id="src-text" placeholder="Enter text to translate..." autofocus></textarea>
94
+ </div>
95
+ <div class="card-footer">
96
+ <span id="char-count">0 characters</span>
97
+ </div>
98
+ </div>
99
+
100
+ <!-- Target Column -->
101
+ <div class="card glass translation-card target-card">
102
+ <div class="card-header">
103
+ <div class="lang-group">
104
+ <span class="lang-label">To</span>
105
+ <select id="tgt-lang-select" class="lang-select">
106
+ <option value="en">English</option>
107
+ </select>
108
+ </div>
109
+ </div>
110
+ <div class="card-body">
111
+ <textarea id="tgt-text" readonly placeholder="Translation will appear here..."></textarea>
112
+ <div id="translation-loader" class="loader-overlay hidden">
113
+ <div class="spinner"></div>
114
+ </div>
115
+ </div>
116
+ <div class="card-footer">
117
+ <span id="timing-info">Ready</span>
118
+ <button id="copy-btn" class="action-btn">Copy</button>
119
+ </div>
120
+ </div>
121
+ </div>
122
+ </div>
123
+
124
+ <!-- Models View -->
125
+ <div id="models-view" class="view">
126
+ <header class="view-header">
127
+ <h1>Available Models</h1>
128
+ <p>Browse models from the quickmt Hugging Face collection</p>
129
+ </header>
130
+ <div id="models-list" class="models-grid">
131
+ <!-- Model cards will be injected here -->
132
+ </div>
133
+ </div>
134
+ <!-- Settings View -->
135
+ <div id="settings-view" class="view">
136
+ <header class="view-header">
137
+ <h1>Inference Settings</h1>
138
+ <p>Fine-tune the translation engine for your needs</p>
139
+ </header>
140
+
141
+ <div class="settings-container glass">
142
+ <div class="settings-grid">
143
+ <!-- Beam Size -->
144
+ <div class="setting-item">
145
+ <div class="setting-info">
146
+ <label>Beam Size</label>
147
+ <span class="setting-desc">Number of hypotheses to explore (1-10)</span>
148
+ </div>
149
+ <div class="setting-control">
150
+ <input type="range" id="setting-beam-size" min="1" max="10" step="1" value="2">
151
+ <span class="setting-val">2</span>
152
+ </div>
153
+ </div>
154
+
155
+ <!-- Patience -->
156
+ <div class="setting-item">
157
+ <div class="setting-info">
158
+ <label>Patience</label>
159
+ <span class="setting-desc">Stopping criterion factor (1-10)</span>
160
+ </div>
161
+ <div class="setting-control">
162
+ <input type="range" id="setting-patience" min="1" max="10" step="1" value="1">
163
+ <span class="setting-val">1</span>
164
+ </div>
165
+ </div>
166
+
167
+ <!-- Length Penalty -->
168
+ <div class="setting-item">
169
+ <div class="setting-info">
170
+ <label>Length Penalty</label>
171
+ <span class="setting-desc">Favour longer or shorter sentences (default 1.0)</span>
172
+ </div>
173
+ <div class="setting-control">
174
+ <input type="number" id="setting-length-penalty" step="0.1" value="1.0">
175
+ </div>
176
+ </div>
177
+
178
+ <!-- Coverage Penalty -->
179
+ <div class="setting-item">
180
+ <div class="setting-info">
181
+ <label>Coverage Penalty</label>
182
+ <span class="setting-desc">Ensure all source words are translated (default 0.0)</span>
183
+ </div>
184
+ <div class="setting-control">
185
+ <input type="number" id="setting-coverage-penalty" step="0.1" value="0.0">
186
+ </div>
187
+ </div>
188
+
189
+ <!-- Repetition Penalty -->
190
+ <div class="setting-item">
191
+ <div class="setting-info">
192
+ <label>Repetition Penalty</label>
193
+ <span class="setting-desc">Prevent repeating words (default 1.0)</span>
194
+ </div>
195
+ <div class="setting-control">
196
+ <input type="number" id="setting-repetition-penalty" step="0.1" value="1.0">
197
+ </div>
198
+ </div>
199
+ </div>
200
+
201
+ <div class="settings-actions">
202
+ <button id="reset-settings" class="action-btn secondary">Reset to Defaults</button>
203
+ </div>
204
+ </div>
205
+ </div>
206
+ </section>
207
+ </main>
208
+
209
+ <script src="app.js"></script>
210
+ </body>
211
+
212
+ </html>
style.css ADDED
@@ -0,0 +1,668 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ :root {
2
+ --primary: #6366f1;
3
+ --primary-glow: rgba(99, 102, 241, 0.5);
4
+ --bg-gradient: linear-gradient(135deg, #0f172a 0%, #1e1b4b 100%);
5
+ --glass-bg: rgba(255, 255, 255, 0.03);
6
+ --glass-border: rgba(255, 255, 255, 0.1);
7
+ --text-main: #f8fafc;
8
+ --text-muted: #94a3b8;
9
+ --card-shadow: 0 8px 32px 0 rgba(0, 0, 0, 0.37);
10
+ --transition: none;
11
+ --sidebar-active-bg: rgba(255, 255, 255, 0.05);
12
+ --input-bg: rgba(255, 255, 255, 0.05);
13
+ --btn-hover-bg: rgba(255, 255, 255, 0.1);
14
+ }
15
+
16
+ body.light-mode {
17
+ --bg-gradient: linear-gradient(135deg, #f8fafc 0%, #e2e8f0 100%);
18
+ --glass-bg: rgba(255, 255, 255, 0.7);
19
+ --glass-border: rgba(99, 102, 241, 0.1);
20
+ --text-main: #1e293b;
21
+ --text-muted: #64748b;
22
+ --card-shadow: 0 8px 32px 0 rgba(31, 38, 135, 0.07);
23
+ --sidebar-active-bg: rgba(99, 102, 241, 0.05);
24
+ --input-bg: rgba(0, 0, 0, 0.02);
25
+ --btn-hover-bg: rgba(99, 102, 241, 0.1);
26
+ }
27
+
28
+ * {
29
+ margin: 0;
30
+ padding: 0;
31
+ box-sizing: border-box;
32
+ font-family: 'Inter', sans-serif;
33
+ }
34
+
35
+ h1,
36
+ h2,
37
+ h3,
38
+ .logo {
39
+ font-family: 'Outfit', sans-serif;
40
+ }
41
+
42
+ body {
43
+ background: var(--bg-gradient);
44
+ color: var(--text-main);
45
+ min-height: 100vh;
46
+ overflow: hidden;
47
+ }
48
+
49
+ .bg-blur {
50
+ position: fixed;
51
+ top: 0;
52
+ left: 0;
53
+ width: 100%;
54
+ height: 100%;
55
+ z-index: -1;
56
+ background: radial-gradient(circle at 20% 30%, rgba(99, 102, 241, 0.15) 0%, transparent 40%),
57
+ radial-gradient(circle at 80% 70%, rgba(168, 85, 247, 0.15) 0%, transparent 40%);
58
+ }
59
+
60
+ .top-nav-links {
61
+ position: fixed;
62
+ top: 1.5rem;
63
+ right: 2.5rem;
64
+ display: flex;
65
+ gap: 0.75rem;
66
+ z-index: 100;
67
+ }
68
+
69
+ .glass-btn {
70
+ display: flex;
71
+ align-items: center;
72
+ justify-content: center;
73
+ padding: 0.6rem 1rem;
74
+ min-width: 44px;
75
+ height: 44px;
76
+ background: var(--glass-bg);
77
+ backdrop-filter: blur(12px);
78
+ -webkit-backdrop-filter: blur(12px);
79
+ border: 1px solid var(--glass-border);
80
+ border-radius: 0.75rem;
81
+ color: var(--text-main);
82
+ text-decoration: none;
83
+ font-size: 0.85rem;
84
+ font-weight: 600;
85
+ transition: none;
86
+ }
87
+
88
+ .glass-btn.icon-only {
89
+ padding: 0;
90
+ width: 44px;
91
+ }
92
+
93
+ .glass-btn .btn-icon i {
94
+ font-size: 1.25rem;
95
+ }
96
+
97
+ .glass-btn:hover {
98
+ background: var(--btn-hover-bg);
99
+ }
100
+
101
+ .glass-btn .btn-icon {
102
+ display: flex;
103
+ align-items: center;
104
+ gap: 0.5rem;
105
+ }
106
+
107
+ .app-container {
108
+ display: flex;
109
+ height: 100vh;
110
+ padding: 1.5rem;
111
+ gap: 1.5rem;
112
+ }
113
+
114
+ /* Glass Effect */
115
+ .glass {
116
+ background: var(--glass-bg);
117
+ backdrop-filter: blur(12px);
118
+ -webkit-backdrop-filter: blur(12px);
119
+ border: 1px solid var(--glass-border);
120
+ border-radius: 1.25rem;
121
+ }
122
+
123
+ /* Sidebar */
124
+ .sidebar {
125
+ width: 280px;
126
+ display: flex;
127
+ flex-direction: column;
128
+ padding: 2rem;
129
+ transition: none;
130
+ overflow: hidden;
131
+ }
132
+
133
+ .sidebar.collapsed {
134
+ width: 90px;
135
+ padding: 2rem 1.25rem;
136
+ }
137
+
138
+ .logo {
139
+ display: flex;
140
+ align-items: center;
141
+ gap: 1rem;
142
+ font-size: 1.5rem;
143
+ font-weight: 700;
144
+ margin-bottom: 3rem;
145
+ position: relative;
146
+ }
147
+
148
+ .logo span {
149
+ transition: none;
150
+ white-space: nowrap;
151
+ }
152
+
153
+ .sidebar.collapsed .logo span {
154
+ opacity: 0;
155
+ pointer-events: none;
156
+ }
157
+
158
+ .logo-icon {
159
+ width: 40px;
160
+ height: 40px;
161
+ min-width: 40px;
162
+ background: var(--primary);
163
+ border-radius: 10px;
164
+ display: flex;
165
+ align-items: center;
166
+ justify-content: center;
167
+ color: white;
168
+ box-shadow: 0 0 20px var(--primary-glow);
169
+ }
170
+
171
+ .nav-links {
172
+ list-style: none;
173
+ flex: 1;
174
+ }
175
+
176
+ .nav-links li {
177
+ margin-bottom: 0.5rem;
178
+ }
179
+
180
+ .nav-links a {
181
+ display: flex;
182
+ align-items: center;
183
+ padding: 0.75rem 1rem;
184
+ color: var(--text-muted);
185
+ text-decoration: none;
186
+ border-radius: 0.75rem;
187
+ transition: none;
188
+ }
189
+
190
+ .nav-links .nav-text {
191
+ transition: none;
192
+ }
193
+
194
+ .sidebar.collapsed .nav-links .nav-text {
195
+ opacity: 0;
196
+ pointer-events: none;
197
+ width: 0;
198
+ }
199
+
200
+ .nav-icon {
201
+ font-size: 1.25rem;
202
+ min-width: 24px;
203
+ display: flex;
204
+ align-items: center;
205
+ justify-content: center;
206
+ margin-right: 0.75rem;
207
+ transition: none;
208
+ }
209
+
210
+ .sidebar.collapsed .nav-icon {
211
+ margin-right: 0;
212
+ width: 100%;
213
+ }
214
+
215
+ .sidebar.collapsed .nav-links a {
216
+ justify-content: center;
217
+ padding: 0.75rem 0;
218
+ }
219
+
220
+ .nav-links li.active a,
221
+ .nav-links a:hover {
222
+ background: var(--sidebar-active-bg);
223
+ color: var(--text-main);
224
+ }
225
+
226
+ .nav-links li.active a {
227
+ border-left: 3px solid var(--primary);
228
+ }
229
+
230
+ .sidebar.collapsed .nav-links li.active a {
231
+ border-left: none;
232
+ background: var(--sidebar-active-bg);
233
+ box-shadow: inset 0 0 10px rgba(99, 102, 241, 0.2);
234
+ }
235
+
236
+ /* Content Area */
237
+ .content {
238
+ flex: 1;
239
+ overflow-y: auto;
240
+ padding-right: 0.5rem;
241
+ }
242
+
243
+ .view {
244
+ display: none;
245
+ }
246
+
247
+ .view.active {
248
+ display: flex;
249
+ flex-direction: column;
250
+ height: 100%;
251
+ }
252
+
253
+
254
+
255
+ .view-header {
256
+ margin-bottom: 2rem;
257
+ }
258
+
259
+ .view-header h1 {
260
+ font-size: 2.25rem;
261
+ margin-bottom: 0.5rem;
262
+ }
263
+
264
+ .view-header p {
265
+ color: var(--text-muted);
266
+ }
267
+
268
+ /* Prediction / Translation Grid */
269
+ .translation-grid {
270
+ display: grid;
271
+ grid-template-columns: 1fr 1fr;
272
+ gap: 1.5rem;
273
+ flex: 1;
274
+ min-height: 0;
275
+ }
276
+
277
+ .card {
278
+ display: flex;
279
+ flex-direction: column;
280
+ box-shadow: var(--card-shadow);
281
+ }
282
+
283
+ .card-header {
284
+ padding: 1rem 1.5rem;
285
+ border-bottom: 1px solid var(--glass-border);
286
+ display: flex;
287
+ align-items: center;
288
+ justify-content: space-between;
289
+ }
290
+
291
+ .card-body {
292
+ flex: 1;
293
+ position: relative;
294
+ }
295
+
296
+ .card-footer {
297
+ padding: 1rem 1.5rem;
298
+ border-top: 1px solid var(--glass-border);
299
+ font-size: 0.85rem;
300
+ color: var(--text-muted);
301
+ display: flex;
302
+ align-items: center;
303
+ justify-content: space-between;
304
+ }
305
+
306
+ textarea {
307
+ width: 100%;
308
+ height: 100%;
309
+ background: transparent;
310
+ border: none;
311
+ resize: none;
312
+ padding: 1.5rem;
313
+ color: var(--text-main);
314
+ font-size: 1.1rem;
315
+ line-height: 1.6;
316
+ outline: none;
317
+ }
318
+
319
+ .lang-group {
320
+ display: flex;
321
+ align-items: center;
322
+ gap: 0.75rem;
323
+ }
324
+
325
+ .lang-label {
326
+ font-size: 0.7rem;
327
+ font-weight: 700;
328
+ text-transform: uppercase;
329
+ letter-spacing: 0.05em;
330
+ color: var(--text-muted);
331
+ }
332
+
333
+ .lang-select {
334
+ background: var(--input-bg);
335
+ border: 1px solid var(--glass-border);
336
+ color: var(--text-main);
337
+ padding: 0.5rem 1rem;
338
+ border-radius: 0.5rem;
339
+ outline: none;
340
+ cursor: pointer;
341
+ }
342
+
343
+ .detected-badge {
344
+ font-size: 0.75rem;
345
+ background: var(--primary);
346
+ padding: 0.2rem 0.6rem;
347
+ border-radius: 1rem;
348
+ color: white;
349
+ opacity: 0;
350
+ transition: none;
351
+ }
352
+
353
+ .detected-badge.visible {
354
+ opacity: 1;
355
+ transition: none;
356
+ }
357
+
358
+ /* Loader */
359
+ .loader-overlay {
360
+ position: absolute;
361
+ top: 0;
362
+ left: 0;
363
+ width: 100%;
364
+ height: 100%;
365
+ background: rgba(15, 23, 42, 0.5);
366
+ display: flex;
367
+ align-items: center;
368
+ justify-content: center;
369
+ border-radius: 0 0 1.25rem 1.25rem;
370
+ }
371
+
372
+ .hidden {
373
+ display: none !important;
374
+ }
375
+
376
+ .spinner {
377
+ width: 30px;
378
+ height: 30px;
379
+ border: 3px solid rgba(255, 255, 255, 0.1);
380
+ border-top-color: var(--primary);
381
+ border-radius: 50%;
382
+ animation: none;
383
+ }
384
+
385
+ @keyframes spin {
386
+ to {
387
+ transform: rotate(360deg);
388
+ }
389
+ }
390
+
391
+ /* Success Pills */
392
+ .status-pill {
393
+ display: flex;
394
+ align-items: center;
395
+ gap: 0.5rem;
396
+ padding: 0.5rem 1rem;
397
+ border-radius: 2rem;
398
+ background: rgba(0, 0, 0, 0.2);
399
+ font-size: 0.85rem;
400
+ }
401
+
402
+ .dot {
403
+ width: 8px;
404
+ height: 8px;
405
+ border-radius: 50%;
406
+ }
407
+
408
+ .status-online .dot {
409
+ background: #10b981;
410
+ box-shadow: 0 0 10px #10b981;
411
+ }
412
+
413
+ .status-loading .dot {
414
+ background: #f59e0b;
415
+ animation: none;
416
+ }
417
+
418
+ @keyframes pulse {
419
+ 0% {
420
+ transform: scale(1);
421
+ opacity: 1;
422
+ }
423
+
424
+ 50% {
425
+ transform: scale(1.2);
426
+ opacity: 0.5;
427
+ }
428
+
429
+ 100% {
430
+ transform: scale(1);
431
+ opacity: 1;
432
+ }
433
+ }
434
+
435
+ /* Models Grid */
436
+ .models-grid {
437
+ display: grid;
438
+ grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
439
+ gap: 1.5rem;
440
+ }
441
+
442
+ .model-card {
443
+ padding: 1.5rem;
444
+ transition: none;
445
+ /* Performance optimizations */
446
+ contain: layout style paint;
447
+ will-change: background;
448
+ /* Remove expensive backdrop-filter for better scrolling */
449
+ background: var(--glass-bg);
450
+ border: 1px solid var(--glass-border);
451
+ border-radius: 1.25rem;
452
+ box-shadow: var(--card-shadow);
453
+ }
454
+
455
+ .model-card:hover {
456
+ background: var(--sidebar-active-bg);
457
+ }
458
+
459
+ .model-lang-pair {
460
+ display: flex;
461
+ align-items: center;
462
+ gap: 0.5rem;
463
+ font-weight: 600;
464
+ margin-bottom: 0.5rem;
465
+ }
466
+
467
+ .model-id {
468
+ font-size: 0.8rem;
469
+ color: var(--text-muted);
470
+ word-break: break-all;
471
+ }
472
+
473
+ .loaded-badge {
474
+ display: inline-block;
475
+ padding: 0.2rem 0.5rem;
476
+ background: rgba(16, 185, 129, 0.1);
477
+ color: #10b981;
478
+ border: 1px solid rgba(16, 185, 129, 0.2);
479
+ border-radius: 0.4rem;
480
+ font-size: 0.7rem;
481
+ margin-top: 1rem;
482
+ }
483
+
484
+ /* Buttons */
485
+ .action-btn {
486
+ background: var(--primary);
487
+ color: white;
488
+ border: none;
489
+ padding: 0.5rem 1rem;
490
+ border-radius: 0.5rem;
491
+ cursor: pointer;
492
+ font-weight: 500;
493
+ transition: none;
494
+ }
495
+
496
+ .action-btn:hover {
497
+ background: #4f46e5;
498
+ }
499
+
500
+ .icon-btn {
501
+ background: transparent;
502
+ border: none;
503
+ color: var(--text-muted);
504
+ font-size: 1.25rem;
505
+ cursor: pointer;
506
+ transition: none;
507
+ }
508
+
509
+ .icon-btn:hover {
510
+ color: var(--text-main);
511
+ }
512
+
513
+ /* Settings View */
514
+ .settings-container {
515
+ max-width: 800px;
516
+ padding: 2rem;
517
+ margin-top: 1rem;
518
+ }
519
+
520
+ .settings-grid {
521
+ display: flex;
522
+ flex-direction: column;
523
+ gap: 2rem;
524
+ }
525
+
526
+ .setting-item {
527
+ display: grid;
528
+ grid-template-columns: 1fr 200px;
529
+ align-items: center;
530
+ gap: 2rem;
531
+ padding-bottom: 2rem;
532
+ border-bottom: 1px solid var(--glass-border);
533
+ }
534
+
535
+ .setting-item:last-child {
536
+ border-bottom: none;
537
+ }
538
+
539
+ .setting-info {
540
+ display: flex;
541
+ flex-direction: column;
542
+ gap: 0.25rem;
543
+ }
544
+
545
+ .setting-info label {
546
+ font-weight: 600;
547
+ font-size: 1.1rem;
548
+ }
549
+
550
+ .setting-desc {
551
+ color: var(--text-muted);
552
+ font-size: 0.85rem;
553
+ }
554
+
555
+ .setting-control {
556
+ display: flex;
557
+ align-items: center;
558
+ gap: 1rem;
559
+ }
560
+
561
+ .setting-val {
562
+ min-width: 30px;
563
+ font-family: monospace;
564
+ font-weight: 600;
565
+ color: var(--primary);
566
+ }
567
+
568
+ input[type="range"] {
569
+ flex: 1;
570
+ cursor: pointer;
571
+ accent-color: var(--primary);
572
+ }
573
+
574
+ input[type="number"] {
575
+ width: 100%;
576
+ background: var(--input-bg);
577
+ border: 1px solid var(--glass-border);
578
+ color: var(--text-main);
579
+ padding: 0.5rem;
580
+ border-radius: 0.5rem;
581
+ outline: none;
582
+ font-family: inherit;
583
+ }
584
+
585
+ .settings-actions {
586
+ margin-top: 3rem;
587
+ display: flex;
588
+ justify-content: flex-end;
589
+ }
590
+
591
+ .action-btn.secondary {
592
+ background: rgba(255, 255, 255, 0.05);
593
+ border: 1px solid var(--glass-border);
594
+ }
595
+
596
+ .action-btn.secondary:hover {
597
+ background: rgba(255, 255, 255, 0.1);
598
+ }
599
+
600
+ /* Theme Toggle Button */
601
+ .theme-toggle-container {
602
+ margin-top: 1rem;
603
+ }
604
+
605
+ #theme-toggle {
606
+ width: 100%;
607
+ display: flex;
608
+ align-items: center;
609
+ gap: 0.75rem;
610
+ background: var(--input-bg);
611
+ border: 1px solid var(--glass-border);
612
+ color: var(--text-main);
613
+ padding: 0.75rem 1rem;
614
+ border-radius: 0.75rem;
615
+ cursor: pointer;
616
+ font-size: 0.9rem;
617
+ transition: none;
618
+ }
619
+
620
+ #theme-toggle:hover {
621
+ background: var(--sidebar-active-bg);
622
+ }
623
+
624
+ .mode-icon {
625
+ font-size: 1.1rem;
626
+ }
627
+
628
+ .sidebar.collapsed .mode-text {
629
+ display: none;
630
+ }
631
+
632
+ .sidebar.collapsed .theme-toggle-container {
633
+ display: flex;
634
+ justify-content: center;
635
+ }
636
+
637
+ #sidebar-toggle {
638
+ margin-top: 1rem;
639
+ width: 40px;
640
+ height: 40px;
641
+ display: flex;
642
+ align-items: center;
643
+ justify-content: center;
644
+ background: var(--input-bg);
645
+ border-radius: 50%;
646
+ margin-left: auto;
647
+ font-size: 1.25rem;
648
+ transition: none;
649
+ z-index: 10;
650
+ }
651
+
652
+ #sidebar-toggle:hover {
653
+ background: var(--sidebar-active-bg);
654
+ }
655
+
656
+ .sidebar.collapsed #sidebar-toggle {
657
+ transform: rotate(180deg);
658
+ margin-left: 0.5rem;
659
+ }
660
+
661
+ .sidebar.collapsed .sidebar-footer .status-text {
662
+ display: none;
663
+ }
664
+
665
+ .sidebar.collapsed .status-pill {
666
+ padding: 0.5rem;
667
+ justify-content: center;
668
+ }