carvus-lens 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/index.html ADDED
@@ -0,0 +1,687 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+
4
+ <head>
5
+ <meta charset="UTF-8">
6
+ <title>Carvus Lens</title>
7
+ <link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700;800;900&display=swap"
8
+ rel="stylesheet">
9
+ <style>
10
+ :root {
11
+ --bg-surface: rgba(32, 28, 26, 0.94);
12
+ --bg-surface-raised: rgba(42, 38, 35, 0.96);
13
+ --bg-input: rgba(56, 50, 46, 0.7);
14
+ --accent: #c96442;
15
+ --accent-warm: #d4845a;
16
+ --accent-gold: #e2a96d;
17
+ --accent-glow: rgba(201, 100, 66, 0.4);
18
+ --text-primary: #f5efe7;
19
+ --text-secondary: #bfb5a8;
20
+ --text-muted: #8a7f72;
21
+ --border: rgba(255, 255, 255, 0.06);
22
+ --border-warm: rgba(201, 100, 66, 0.2);
23
+ --font: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
24
+ }
25
+
26
+ * {
27
+ margin: 0;
28
+ padding: 0;
29
+ box-sizing: border-box;
30
+ }
31
+
32
+ body {
33
+ overflow: hidden;
34
+ cursor: crosshair;
35
+ font-family: var(--font);
36
+ background: transparent;
37
+ -webkit-font-smoothing: antialiased;
38
+ }
39
+
40
+ #captureCanvas {
41
+ position: absolute;
42
+ top: 0;
43
+ left: 0;
44
+ width: 100vw;
45
+ height: 100vh;
46
+ z-index: 10;
47
+ }
48
+
49
+ /* ─── Edge Lighting ─── */
50
+ #edgeLighting {
51
+ position: fixed;
52
+ top: 0;
53
+ left: 0;
54
+ width: 100vw;
55
+ height: 100vh;
56
+ pointer-events: none;
57
+ z-index: 5;
58
+ opacity: 0;
59
+ transition: opacity 0.8s ease;
60
+ }
61
+
62
+ #edgeLighting.active,
63
+ #edgeLighting.visible {
64
+ opacity: 1;
65
+ }
66
+
67
+ #edgeLightingCanvas {
68
+ width: 100%;
69
+ height: 100%;
70
+ }
71
+
72
+ /* ─── Particle Canvas ─── */
73
+ #particleCanvas {
74
+ position: fixed;
75
+ top: 0;
76
+ left: 0;
77
+ width: 100vw;
78
+ height: 100vh;
79
+ pointer-events: none;
80
+ z-index: 12;
81
+ }
82
+
83
+ /* ─── Status Pill ─── */
84
+ #statusPill {
85
+ position: fixed;
86
+ top: 24px;
87
+ left: 50%;
88
+ transform: translateX(-50%);
89
+ padding: 10px 28px;
90
+ background: rgba(32, 28, 26, 0.92);
91
+ backdrop-filter: blur(24px);
92
+ border: 1px solcid var(--border-warm);
93
+ border-radius: 100px;
94
+ color: var(--accent-warm);
95
+ font-size: 12px;
96
+ font-weight: 600;
97
+ font-family: var(--font);
98
+ letter-spacing: 0.3px;
99
+ z-index: 50;
100
+ opacity: 0;
101
+ transition: opacity 0.4s ease;
102
+ display: flex;
103
+ align-items: center;
104
+ gap: 10px;
105
+ box-shadow: 0 8px 32px rgba(0, 0, 0, 0.3);
106
+ }
107
+
108
+ #statusPill.visible {
109
+ opacity: 1;
110
+ }
111
+
112
+ .status-dot {
113
+ width: 7px;
114
+ height: 7px;
115
+ border-radius: 50%;
116
+ background: var(--accent);
117
+ animation: pulse 2s ease-in-out infinite;
118
+ }
119
+
120
+ @keyframes pulse {
121
+
122
+ 0%,
123
+ 100% {
124
+ opacity: 0.4;
125
+ transform: scale(0.9);
126
+ }
127
+
128
+ 50% {
129
+ opacity: 1;
130
+ transform: scale(1.1);
131
+ }
132
+ }
133
+
134
+ /* ─── Hint Overlay ─── */
135
+ #hintOverlay {
136
+ position: fixed;
137
+ top: 50%;
138
+ left: 50%;
139
+ transform: translate(-50%, -50%);
140
+ z-index: 15;
141
+ text-align: center;
142
+ pointer-events: none;
143
+ opacity: 0;
144
+ transition: opacity 0.5s ease;
145
+ }
146
+
147
+ #hintOverlay.visible {
148
+ opacity: 1;
149
+ animation: hintFade 3s ease-in-out infinite;
150
+ }
151
+
152
+ @keyframes hintFade {
153
+
154
+ 0%,
155
+ 100% {
156
+ opacity: 0.5;
157
+ }
158
+
159
+ 50% {
160
+ opacity: 0.85;
161
+ }
162
+ }
163
+
164
+ .hint-logo {
165
+ width: 80px;
166
+ height: 80px;
167
+ margin: 0 auto 16px;
168
+ border-radius: 50%;
169
+ background: transparent;
170
+ object-fit: contain;
171
+ animation: logoFloat 3s ease-in-out infinite, logoGlow 2s ease-in-out infinite;
172
+ }
173
+
174
+ @keyframes logoFloat {
175
+ 0%, 100% { transform: translateY(0); }
176
+ 50% { transform: translateY(-8px); }
177
+ }
178
+
179
+ @keyframes logoGlow {
180
+ 0%, 100% { filter: drop-shadow(0 0 12px rgba(201,100,66,0.3)); }
181
+ 50% { filter: drop-shadow(0 0 28px rgba(201,100,66,0.7)); }
182
+ }
183
+
184
+ .hint-text {
185
+ font-size: 14px;
186
+ font-weight: 500;
187
+ color: rgba(245, 239, 231, 0.7);
188
+ }
189
+
190
+ .hint-sub {
191
+ font-size: 10px;
192
+ color: rgba(245, 239, 231, 0.3);
193
+ margin-top: 6px;
194
+ letter-spacing: 1.5px;
195
+ text-transform: uppercase;
196
+ }
197
+
198
+ /* ─── TOS Modal ─── */
199
+ #tosModal {
200
+ position: fixed;
201
+ top: 50%;
202
+ left: 50%;
203
+ transform: translate(-50%, -50%);
204
+ width: min(80%, 500px);
205
+ background: var(--bg-surface);
206
+ backdrop-filter: blur(48px) saturate(160%);
207
+ border-radius: 20px;
208
+ color: var(--text-primary);
209
+ box-shadow: 0 0 0 1px var(--border), 0 24px 64px rgba(0, 0, 0, 0.55), 0 0 48px rgba(201, 100, 66, 0.08);
210
+ z-index: 200;
211
+ display: none;
212
+ flex-direction: column;
213
+ padding: 24px;
214
+ animation: popIn 0.45s cubic-bezier(0.16, 1, 0.3, 1) forwards;
215
+ }
216
+ #tosModal.visible { display: flex; }
217
+ .tos-title { font-size: 18px; font-weight: 700; margin-bottom: 12px; color: var(--accent-warm); }
218
+ .tos-content { font-size: 14px; line-height: 1.6; color: var(--text-secondary); margin-bottom: 24px; }
219
+ .tos-btn {
220
+ background: linear-gradient(135deg, var(--accent), var(--accent-warm));
221
+ color: #fff; border: none; font-weight: 700;
222
+ padding: 10px 20px; border-radius: 10px; cursor: pointer; align-self: flex-end;
223
+ }
224
+
225
+ /* ─── Result Popup ─── */
226
+ #resultPopup {
227
+ display: none;
228
+ position: fixed;
229
+ bottom: 36px;
230
+ left: 50%;
231
+ transform: translateX(-50%);
232
+ width: min(88%, 880px);
233
+ height: 60vh;
234
+ background: var(--bg-surface);
235
+ backdrop-filter: blur(48px) saturate(160%);
236
+ border-radius: 20px;
237
+ color: var(--text-primary);
238
+ box-shadow: 0 0 0 1px var(--border), 0 24px 64px rgba(0, 0, 0, 0.55), 0 0 48px rgba(201, 100, 66, 0.08);
239
+ z-index: 100;
240
+ overflow: hidden;
241
+ animation: popIn 0.45s cubic-bezier(0.16, 1, 0.3, 1) forwards;
242
+ resize: both;
243
+ min-width: 400px;
244
+ min-height: 300px;
245
+ flex-direction: column;
246
+ }
247
+
248
+ #resultPopup.visible {
249
+ display: flex;
250
+ }
251
+
252
+ @keyframes popIn {
253
+ from {
254
+ bottom: -180px;
255
+ opacity: 0;
256
+ transform: translateX(-50%) scale(0.94);
257
+ }
258
+
259
+ to {
260
+ bottom: 36px;
261
+ opacity: 1;
262
+ transform: translateX(-50%) scale(1);
263
+ }
264
+ }
265
+
266
+ /* Animated border */
267
+ #resultPopup::before {
268
+ content: '';
269
+ position: absolute;
270
+ inset: -1px;
271
+ border-radius: 20px;
272
+ background: conic-gradient(from var(--border-angle, 0deg),
273
+ transparent 25%, var(--accent) 37%,
274
+ var(--accent-gold) 50%, var(--accent-warm) 63%,
275
+ transparent 75%);
276
+ z-index: -1;
277
+ opacity: 0.35;
278
+ animation: spin 5s linear infinite;
279
+ }
280
+
281
+ @property --border-angle {
282
+ syntax: '<angle>';
283
+ initial-value: 0deg;
284
+ inherits: false;
285
+ }
286
+
287
+ @keyframes spin {
288
+ to {
289
+ --border-angle: 360deg;
290
+ }
291
+ }
292
+
293
+ /* ─── Header ─── */
294
+ .header {
295
+ display: flex;
296
+ align-items: center;
297
+ justify-content: space-between;
298
+ padding: 13px 20px;
299
+ background: rgba(0, 0, 0, 0.2);
300
+ border-bottom: 1px solid var(--border);
301
+ user-select: none;
302
+ flex-shrink: 0;
303
+ }
304
+
305
+ .header-left {
306
+ display: flex;
307
+ align-items: center;
308
+ gap: 12px;
309
+ }
310
+
311
+ .logo-svg {
312
+ width: 32px;
313
+ height: 32px;
314
+ filter: drop-shadow(0 0 8px rgba(201, 100, 66, 0.5));
315
+ }
316
+
317
+ .title-container {
318
+ display: flex;
319
+ flex-direction: column;
320
+ gap: 1px;
321
+ }
322
+
323
+ .title {
324
+ font-weight: 800;
325
+ font-size: 15px;
326
+ letter-spacing: 1.5px;
327
+ background: linear-gradient(135deg, var(--text-primary) 0%, var(--accent-warm) 60%, var(--accent-gold) 100%);
328
+ background-size: 200% auto;
329
+ -webkit-background-clip: text;
330
+ -webkit-text-fill-color: transparent;
331
+ animation: shimmer 5s ease-in-out infinite;
332
+ }
333
+
334
+ @keyframes shimmer {
335
+
336
+ 0%,
337
+ 100% {
338
+ background-position: 0% center;
339
+ }
340
+
341
+ 50% {
342
+ background-position: 200% center;
343
+ }
344
+ }
345
+
346
+ .branding-sub {
347
+ font-size: 9px;
348
+ color: var(--text-muted);
349
+ text-transform: uppercase;
350
+ letter-spacing: 2.5px;
351
+ font-weight: 600;
352
+ }
353
+
354
+ .header-right {
355
+ display: flex;
356
+ align-items: center;
357
+ gap: 10px;
358
+ }
359
+
360
+ .branding-author {
361
+ font-size: 10px;
362
+ color: var(--text-muted);
363
+ font-weight: 600;
364
+ padding: 4px 12px;
365
+ background: rgba(255, 255, 255, 0.03);
366
+ border-radius: 16px;
367
+ border: 1px solid var(--border);
368
+ }
369
+
370
+ .close-btn {
371
+ background: rgba(255, 255, 255, 0.03);
372
+ border: 1px solid var(--border);
373
+ color: var(--text-muted);
374
+ width: 30px;
375
+ height: 30px;
376
+ border-radius: 50%;
377
+ display: flex;
378
+ align-items: center;
379
+ justify-content: center;
380
+ cursor: pointer;
381
+ transition: all 0.2s;
382
+ font-size: 16px;
383
+ line-height: 1;
384
+ }
385
+
386
+ .close-btn:hover {
387
+ background: rgba(220, 80, 60, 0.15);
388
+ color: #e05040;
389
+ border-color: rgba(220, 80, 60, 0.3);
390
+ }
391
+
392
+ /* ─── Content ─── */
393
+ .content-area {
394
+ flex: 1;
395
+ overflow: hidden;
396
+ position: relative;
397
+ }
398
+
399
+ #loading {
400
+ display: none;
401
+ padding: 48px 30px;
402
+ text-align: center;
403
+ flex-direction: column;
404
+ align-items: center;
405
+ gap: 18px;
406
+ }
407
+
408
+ #loading.visible {
409
+ display: flex;
410
+ }
411
+
412
+ .loading-spinner {
413
+ width: 40px;
414
+ height: 40px;
415
+ border: 3px solid rgba(201, 100, 66, 0.12);
416
+ border-top-color: var(--accent);
417
+ border-radius: 50%;
418
+ animation: lspin 0.75s linear infinite;
419
+ }
420
+
421
+ @keyframes lspin {
422
+ to {
423
+ transform: rotate(360deg);
424
+ }
425
+ }
426
+
427
+ .loading-text {
428
+ font-size: 13px;
429
+ color: var(--text-secondary);
430
+ font-weight: 500;
431
+ }
432
+
433
+ #resultContent {
434
+ display: none;
435
+ font-size: 14px;
436
+ line-height: 1.8;
437
+ color: var(--text-primary);
438
+ padding: 24px 28px 80px;
439
+ overflow-y: auto;
440
+ height: 100%;
441
+ white-space: pre-wrap;
442
+ word-break: break-word;
443
+ scrollbar-width: thin;
444
+ scrollbar-color: rgba(201, 100, 66, 0.25) transparent;
445
+ }
446
+
447
+ #resultContent.visible {
448
+ display: block;
449
+ }
450
+
451
+ #resultContent::-webkit-scrollbar {
452
+ width: 5px;
453
+ }
454
+
455
+ #resultContent::-webkit-scrollbar-track {
456
+ background: transparent;
457
+ }
458
+
459
+ #resultContent::-webkit-scrollbar-thumb {
460
+ background: rgba(201, 100, 66, 0.25);
461
+ border-radius: 3px;
462
+ }
463
+
464
+ /* ─── GCSE Container ─── */
465
+ #gcseContainer {
466
+ width: 100%;
467
+ height: 100%;
468
+ display: none;
469
+ background: #1a1714;
470
+ }
471
+
472
+ #gcseContainer.visible {
473
+ display: block;
474
+ }
475
+
476
+ /* ─── Footer ─── */
477
+ .footer-branding {
478
+ position: absolute;
479
+ bottom: 56px;
480
+ left: 0;
481
+ right: 0;
482
+ text-align: center;
483
+ font-size: 9px;
484
+ color: rgba(255, 255, 255, 0.08);
485
+ pointer-events: none;
486
+ text-transform: uppercase;
487
+ letter-spacing: 2px;
488
+ }
489
+
490
+ /* ─── Action Bar ─── */
491
+ .action-bar {
492
+ display: none;
493
+ gap: 6px;
494
+ padding: 12px 18px;
495
+ background: rgba(22, 18, 16, 0.95);
496
+ backdrop-filter: blur(16px);
497
+ border-top: 1px solid var(--border);
498
+ flex-shrink: 0;
499
+ justify-content: center;
500
+ align-items: center;
501
+ flex-wrap: wrap;
502
+ }
503
+
504
+ .action-bar.visible {
505
+ display: flex;
506
+ }
507
+
508
+ .action-btn {
509
+ background: rgba(255, 255, 255, 0.05);
510
+ border: 1px solid var(--border);
511
+ color: var(--text-primary);
512
+ padding: 7px 16px;
513
+ border-radius: 10px;
514
+ font-size: 12px;
515
+ font-weight: 600;
516
+ font-family: var(--font);
517
+ cursor: pointer;
518
+ transition: all 0.2s ease;
519
+ display: flex;
520
+ align-items: center;
521
+ gap: 6px;
522
+ white-space: nowrap;
523
+ }
524
+
525
+ .action-btn:hover {
526
+ background: rgba(255, 255, 255, 0.1);
527
+ border-color: rgba(255, 255, 255, 0.12);
528
+ transform: translateY(-1px);
529
+ }
530
+
531
+ .action-btn:active {
532
+ transform: translateY(0) scale(0.97);
533
+ }
534
+
535
+ .action-btn.primary {
536
+ background: linear-gradient(135deg, var(--accent), var(--accent-warm));
537
+ color: #fff;
538
+ border: none;
539
+ font-weight: 700;
540
+ box-shadow: 0 4px 20px rgba(201, 100, 66, 0.35);
541
+ }
542
+
543
+ .action-btn.primary:hover {
544
+ box-shadow: 0 6px 28px rgba(201, 100, 66, 0.45);
545
+ transform: translateY(-2px);
546
+ }
547
+
548
+ .action-btn.success {
549
+ background: rgba(52, 211, 153, 0.12);
550
+ color: #34d399;
551
+ border-color: rgba(52, 211, 153, 0.2);
552
+ }
553
+
554
+ .action-btn.reading {
555
+ background: rgba(201, 100, 66, 0.15);
556
+ color: var(--accent-warm);
557
+ border-color: rgba(201, 100, 66, 0.3);
558
+ }
559
+
560
+ .action-btn svg {
561
+ width: 13px;
562
+ height: 13px;
563
+ flex-shrink: 0;
564
+ }
565
+
566
+ select.action-btn {
567
+ background: var(--bg-input);
568
+ -webkit-appearance: none;
569
+ appearance: none;
570
+ padding-right: 26px;
571
+ background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='10' fill='%238a7f72' viewBox='0 0 16 16'%3E%3Cpath d='M8 11L3 6h10z'/%3E%3C/svg%3E");
572
+ background-repeat: no-repeat;
573
+ background-position: right 10px center;
574
+ }
575
+
576
+ select.action-btn option {
577
+ background: #2a2622;
578
+ color: #f5efe7;
579
+ }
580
+ </style>
581
+ </head>
582
+
583
+ <body>
584
+
585
+ <div id="edgeLighting"><canvas id="edgeLightingCanvas"></canvas></div>
586
+ <canvas id="particleCanvas"></canvas>
587
+
588
+ <div id="statusPill">
589
+ <span class="status-dot"></span>
590
+ <span id="statusText">Draw a circle to search</span>
591
+ </div>
592
+
593
+ <div id="hintOverlay">
594
+ <div class="hint-icon">
595
+ <svg viewBox="0 0 24 24" fill="none" stroke="#c96442" stroke-width="2" stroke-linecap="round"
596
+ stroke-linejoin="round">
597
+ <circle cx="11" cy="11" r="8" />
598
+ <path d="M21 21l-4.35-4.35" />
599
+ </svg>
600
+ </div>
601
+ <div class="hint-text">Draw a circle around anything</div>
602
+ <div class="hint-sub">Esc to exit · Ctrl+C to close</div>
603
+ </div>
604
+
605
+ <div id="tosModal">
606
+ <div class="tos-title">Welcome to Carvus Lens</div>
607
+ <div class="tos-content">
608
+ By using Carvus Lens, you agree to our terms. Images you circle are uploaded to a secure temporary image host to enable Google Lens visual search. Extracted text is processed via Groq AI. Do not circle sensitive personal information.
609
+ </div>
610
+ <button class="tos-btn" id="btnAcceptTos">I Agree, Let's Go!</button>
611
+ </div>
612
+
613
+ <canvas id="captureCanvas"></canvas>
614
+
615
+ <div id="resultPopup">
616
+ <div class="header" id="popupHeader">
617
+ <div class="header-left">
618
+ <svg class="logo-svg" viewBox="0 0 100 100" fill="none">
619
+ <defs>
620
+ <linearGradient id="lg1" x1="0" y1="0" x2="100" y2="100" gradientUnits="userSpaceOnUse">
621
+ <stop stop-color="#c96442" />
622
+ <stop offset="0.5" stop-color="#d4845a" />
623
+ <stop offset="1" stop-color="#e2a96d" />
624
+ </linearGradient>
625
+ </defs>
626
+ <circle cx="50" cy="50" r="42" stroke="url(#lg1)" stroke-width="5" fill="none" />
627
+ <circle cx="50" cy="50" r="26" stroke="url(#lg1)" stroke-width="2.5" fill="none" opacity="0.35" />
628
+ <circle cx="50" cy="50" r="7" fill="url(#lg1)" />
629
+ <line x1="68" y1="68" x2="85" y2="85" stroke="url(#lg1)" stroke-width="5" stroke-linecap="round" />
630
+ </svg>
631
+ <div class="title-container">
632
+ <div class="title">CARVUS LENS</div>
633
+ <div class="branding-sub">Visual Intelligence Engine</div>
634
+ </div>
635
+ </div>
636
+ <div class="header-right">
637
+ <div class="branding-author">By Aadil Fazal</div>
638
+ <button class="close-btn" id="closeBtn">&times;</button>
639
+ </div>
640
+ </div>
641
+
642
+ <div class="content-area">
643
+ <div id="loading">
644
+ <div class="loading-spinner"></div>
645
+ <div class="loading-text" id="loadingText">Analyzing content...</div>
646
+ </div>
647
+ <div id="resultContent"></div>
648
+ <div id="gcseContainer"></div>
649
+ <div class="footer-branding">Carvus Lens — Groq AI & Google Search</div>
650
+ </div>
651
+
652
+ <div class="action-bar" id="actionBar">
653
+ <select id="modelSelect" class="action-btn" title="AI Model">
654
+ <option value="meta-llama/llama-4-scout-17b-16e-instruct" selected>Llama 4 Scout (Vision)</option>
655
+ <option value="llama-3.3-70b-versatile">Llama 3.3 70B</option>
656
+ <option value="llama-3.1-8b-instant">Llama 3.1 8B Fast</option>
657
+ <option value="mixtral-8x7b-32768">Mixtral 8x7B</option>
658
+ </select>
659
+ <button class="action-btn" id="btnCopy"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><rect x="9" y="9" width="13" height="13" rx="2"/><path d="M5 15H4a2 2 0 01-2-2V4a2 2 0 012-2h9a2 2 0 012 2v1"/></svg>Copy</button>
660
+ <button class="action-btn" id="btnRead"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><polygon points="11 5 6 9 2 9 2 15 6 15 11 19 11 5"/><path d="M15.54 8.46a5 5 0 010 7.07"/></svg>Read Aloud</button>
661
+ <button class="action-btn" id="btnSearch"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><circle cx="11" cy="11" r="8"/><path d="M21 21l-4.35-4.35"/></svg>Google Lens</button>
662
+ <button class="action-btn primary" id="btnAskAI"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><path d="M12 2L2 7l10 5 10-5-10-5z"/><path d="M2 17l10 5 10-5"/><path d="M2 12l10 5 10-5"/></svg>Ask AI</button>
663
+ <select id="langSelect" class="action-btn" title="Translate To">
664
+ <option value="Spanish">→ Spanish</option>
665
+ <option value="English">→ English</option>
666
+ <option value="French">→ French</option>
667
+ <option value="German">→ German</option>
668
+ <option value="Hindi">→ Hindi</option>
669
+ <option value="Chinese">→ Chinese</option>
670
+ <option value="Japanese">→ Japanese</option>
671
+ <option value="Korean">→ Korean</option>
672
+ <option value="Arabic">→ Arabic</option>
673
+ <option value="Portuguese">→ Portuguese</option>
674
+ <option value="Russian">→ Russian</option>
675
+ <option value="Italian">→ Italian</option>
676
+ <option value="Urdu">→ Urdu</option>
677
+ </select>
678
+ <button class="action-btn" id="btnTranslate"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><path d="M4 5h7"/><path d="M9 3v2"/><path d="M4 9c0 0 2.5 4 7.5 4"/><path d="M14 18l3-8 3 8"/><path d="M15 16h4"/></svg>Translate</button>
679
+ </div>
680
+ </div>
681
+
682
+ <script src="https://unpkg.com/tesseract.js@v5.0.4/dist/tesseract.min.js"></script>
683
+ <script async src="https://cse.google.com/cse.js?cx=b8175f3a0a4c04230"></script>
684
+ <script src="render.js"></script>
685
+ </body>
686
+
687
+ </html>