Files changed (1) hide show
  1. index.html +1249 -83
index.html CHANGED
@@ -1,88 +1,1254 @@
1
- <!doctype html>
2
- <html lang="en">
3
- <head>
4
- <meta charset="UTF-8" />
5
- <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
- <!-- Paint the site theme before external styles or the app can load. -->
7
- <style>
8
- :root { color-scheme: light; --bg: #FAF8F4; --ink: #1A1814; }
9
- :root.dark { color-scheme: dark; --bg: #11100E; --ink: #F3EFE7; }
10
- @media (prefers-color-scheme: dark) {
11
- :root:not(.light):not(.dark) { color-scheme: dark; --bg: #11100E; --ink: #F3EFE7; }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
12
  }
13
- html, body { margin: 0; background: var(--bg); color: var(--ink); }
14
- /* Source HTML is for crawlers, never an intermediate browser layout. */
15
- html [data-pwc-initial-document], html .initial-discovery-footer { display: none !important; }
16
- </style>
17
- <script>
18
- (function () {
19
- var theme;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
20
  try {
21
- theme = localStorage.getItem("pwc-theme");
22
- } catch (_) {
23
- // Storage can be unavailable in embedded browsers; use system theme.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
24
  }
25
- var dark = theme === "dark" ||
26
- (theme !== "light" && window.matchMedia("(prefers-color-scheme: dark)").matches);
27
- document.documentElement.classList.add(dark ? "dark" : "light");
28
- })();
29
- </script>
30
- <title>Papers with Code</title>
31
- <meta name="description" content="Trending AI research papers with code, datasets, methods, and evaluation leaderboards." />
32
-
33
- <meta property="og:title" content="Papers with Code" />
34
- <meta property="og:description" content="Trending AI research papers with code, datasets, methods, and evaluation leaderboards." />
35
- <meta property="og:type" content="website" />
36
- <meta property="og:url" content="https://paperswithcode.co/" />
37
- <meta property="og:site_name" content="Papers with Code" />
38
- <meta property="og:image" content="https://paperswithcode.co/og-image.png?v=2" />
39
- <meta property="og:image:width" content="1200" />
40
- <meta property="og:image:height" content="630" />
41
- <meta property="og:image:alt" content="Papers with Code" />
42
-
43
- <meta name="twitter:card" content="summary_large_image" />
44
- <meta name="twitter:title" content="Papers with Code" />
45
- <meta name="twitter:description" content="Trending AI research papers with code, datasets, methods, and evaluation leaderboards." />
46
- <meta name="twitter:image" content="https://paperswithcode.co/og-image.png?v=2" />
47
-
48
- <link rel="icon" type="image/svg+xml" href="/favicon.svg?v=2" />
49
- <link rel="icon" type="image/png" sizes="32x32" href="/favicon-32.png?v=2" />
50
- <link rel="icon" type="image/png" sizes="192x192" href="/favicon-192.png?v=2" />
51
- <link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png?v=2" />
52
-
53
- <!-- Privacy-friendly analytics by Plausible -->
54
- <script>
55
- // Only load on production so local dev, staging, and the HF Space mirror
56
- // don't pollute the analytics dashboard.
57
- (function () {
58
- var host = window.location.hostname;
59
- if (host !== "paperswithcode.co" && host !== "www.paperswithcode.co") return;
60
-
61
- var s = document.createElement("script");
62
- s.async = true;
63
- s.src = "https://plausible.io/js/pa-Sg1vl99ezagzhWZIahx2o.js";
64
- document.head.appendChild(s);
65
-
66
- window.plausible = window.plausible || function () {
67
- (plausible.q = plausible.q || []).push(arguments);
68
- };
69
- plausible.init = plausible.init || function (i) {
70
- plausible.o = i || {};
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
71
  };
72
- plausible.init();
73
- })();
74
- </script>
75
- <script type="module" crossorigin src="/assets/index-DAAEdKQ4.js"></script>
76
- <link rel="stylesheet" crossorigin href="/assets/index-ByDiZUZl.css">
77
- </head>
78
- <body>
79
- <div id="root"></div>
80
- <footer hidden id="initial-discovery-footer" class="initial-discovery-footer">
81
- <a href="/papers/recent">Recent papers</a>
82
- <span aria-hidden="true">·</span>
83
- <a href="/papers/archive">Paper archive</a>
84
- <span aria-hidden="true">·</span>
85
- <a href="/privacy">Privacy</a>
86
- </footer>
87
- </body>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
88
  </html>
 
1
+ <!--
2
+ Modified from the Manual
3
+ Last updated: 2026-10-02
4
+ Author : Edo Erpani
5
+ Licence : Eunoiaverse Digital Teknologi
6
+ -->
7
+ <!DOCTYPE html>
8
+ <html class="kamus_bahasa_daerah" dir="ltr" lang="id-ID">
9
+ <head>
10
+ <meta charset="UTF-8" />
11
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
12
+ <title id="title">Kamus Daerah Multibahasa - Eunoiaverse</title>
13
+
14
+ <!-- Google Fonts & Icons -->
15
+ <link rel="preconnect" href="https://fonts.googleapis.com">
16
+ <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
17
+ <link href="https://fonts.googleapis.com/css2?family=Plus+Jakarta+Sans:wght@400;500;600;700;800&display=swap" rel="stylesheet">
18
+ <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css" crossorigin="anonymous" referrerpolicy="no-referrer" />
19
+
20
+ <!-- Tailwind CSS CDN -->
21
+ <script src="https://cdn.tailwindcss.com"></script>
22
+ <script>
23
+ tailwind.config = {
24
+ darkMode: 'class',
25
+ }
26
+ </script>
27
+
28
+ <style>
29
+ :root {
30
+ --bg-color: #e0e5ec;
31
+ --text-main: #3d4852;
32
+ --text-muted: #718096;
33
+ --primary: #4f46e5;
34
+
35
+ /* Light Neumorphic Shadows */
36
+ --shadow-flat: 8px 8px 16px #a3b1c6, -8px -8px 16px #ffffff;
37
+ --shadow-flat-sm: 4px 4px 8px #a3b1c6, -4px -4px 8px #ffffff;
38
+ --shadow-pressed: inset 4px 4px 8px #a3b1c6, inset -4px -4px 8px #ffffff;
39
+ --shadow-pressed-deep: inset 6px 6px 12px #92a1b6, inset -6px -6px 12px #ffffff;
40
+ --neu-drop: 9px 9px 16px #bebebe, -9px -9px 16px #ffffff;
41
+ --neu-inset: inset 6px 6px 10px #bebebe, inset -6px -6px 10px #ffffff;
42
+ --neu-btn: 5px 5px 10px #bebebe, -5px -5px 10px #ffffff;
43
+ --neu-btn-active: inset 3px 3px 6px #bebebe, inset -3px -3px 6px #ffffff;
44
+ }
45
+ .dark {
46
+ --bg-color: #1a1e24;
47
+ --text-main: #e2e8f0;
48
+ --text-muted: #94a3b8;
49
+
50
+ /* Dark Neumorphic Shadows */
51
+ --shadow-flat: 7px 7px 15px #121519, -7px -7px 15px #22272f;
52
+ --shadow-flat-sm: 4px 4px 8px #121519, -4px -4px 8px #22272f;
53
+ --shadow-pressed: inset 4px 4px 8px #121519, inset -4px -4px 8px #22272f;
54
+ --shadow-pressed-deep: inset 6px 6px 12px #0f1115, inset -6px -6px 12px #252b33;
55
+ --neu-drop: 9px 9px 16px #121519, -9px -9px 16px #22272f;
56
+ --neu-inset: inset 5px 5px 8px #121519, inset -5px -5px 8px #22272f;
57
+ --neu-btn: 5px 5px 10px #121519, -5px -5px 10px #22272f;
58
+ --neu-btn-active: inset 3px 3px 6px #121519, inset -3px -3px 6px #22272f;
59
+ }
60
+
61
+ * {
62
+ box-sizing: border-box;
63
+ margin: 0;
64
+ padding: 0;
65
+ }
66
+
67
+ body {
68
+ background-color: var(--bg-color);
69
+ color: var(--text-main);
70
+ font-family: 'Plus Jakarta Sans', sans-serif;
71
+ transition: background-color 0.4s ease, color 0.4s ease;
72
+ min-height: 100vh;
73
+ display: flex;
74
+ flex-direction: column;
75
+ }
76
+
77
+ /* Utility Neumorphic Classes */
78
+ .neu-flat {
79
+ box-shadow: var(--shadow-flat);
80
+ background: var(--bg-color);
81
+ transition: all 0.25s cubic-bezier(0.4, 0, 0.2, 1);
82
+ }
83
+
84
+ .neu-flat-sm {
85
+ box-shadow: var(--shadow-flat-sm);
86
+ background: var(--bg-color);
87
+ transition: all 0.25s cubic-bezier(0.4, 0, 0.2, 1);
88
+ }
89
+
90
+ .neu-pressed {
91
+ box-shadow: var(--shadow-pressed) !important;
92
+ background: var(--bg-color);
93
+ transition: all 0.25s cubic-bezier(0.4, 0, 0.2, 1);
94
+ }
95
+
96
+ .neu-pressed-deep {
97
+ box-shadow: var(--shadow-pressed-deep) !important;
98
+ background: var(--bg-color);
99
+ }
100
+
101
+ .neu-button {
102
+ box-shadow: var(--shadow-flat);
103
+ background: var(--bg-color);
104
+ transition: all 0.2s ease;
105
+ }
106
+
107
+ .neu-button:hover {
108
+ transform: translateY(-2px);
109
+ }
110
+
111
+ .neu-button:active {
112
+ transform: translateY(1px);
113
+ box-shadow: var(--shadow-pressed);
114
+ }
115
+
116
+ .tab-active-accent {
117
+ color: #4f46e5;
118
+ }
119
+ .dark .tab-active-accent {
120
+ color: #818cf8;
121
+ }
122
+
123
+ /* Scrollbar */
124
+ ::-webkit-scrollbar {
125
+ width: 8px;
126
+ }
127
+ ::-webkit-scrollbar-track {
128
+ background: var(--bg-color);
129
+ }
130
+ ::-webkit-scrollbar-thumb {
131
+ background: #cbd5e1;
132
+ border-radius: 9999px;
133
+ }
134
+ .dark ::-webkit-scrollbar-thumb {
135
+ background: #334155;
136
+ }
137
+
138
+ /* Container Main */
139
+ main {
140
+ flex: 1;
141
+ display: flex;
142
+ justify-content: center;
143
+ align-items: center;
144
+ padding: 24px 16px;
145
+ }
146
+
147
+ .tab-content {
148
+ display: none;
149
+ width: 100%;
150
+ justify-content: center;
151
+ }
152
+
153
+ .tab-content.active {
154
+ display: flex;
155
+ }
156
+
157
+ .translator-card {
158
+ background: var(--bg-color);
159
+ width: 100%;
160
+ max-width: 760px;
161
+ border-radius: 24px;
162
+ box-shadow: var(--neu-drop);
163
+ padding: 24px;
164
+ display: flex;
165
+ flex-direction: column;
166
+ gap: 20px;
167
+ }
168
+
169
+ .card-header {
170
+ display: flex;
171
+ justify-content: space-between;
172
+ align-items: center;
173
+ flex-wrap: wrap;
174
+ gap: 12px;
175
+ }
176
+
177
+ .card-title {
178
+ font-size: 1.35rem;
179
+ font-weight: 700;
180
+ }
181
+
182
+ .card-subtitle {
183
+ font-size: 0.85rem;
184
+ color: var(--text-muted);
185
+ margin-top: 2px;
186
+ }
187
+
188
+ .add-word-trigger {
189
+ background: var(--bg-color);
190
+ border: none;
191
+ padding: 10px 16px;
192
+ border-radius: 12px;
193
+ box-shadow: var(--neu-btn);
194
+ cursor: pointer;
195
+ color: var(--primary);
196
+ font-weight: 600;
197
+ font-size: 0.85rem;
198
+ display: flex;
199
+ align-items: center;
200
+ gap: 6px;
201
+ transition: all 0.2s ease;
202
+ }
203
+
204
+ .add-word-trigger:active {
205
+ box-shadow: var(--neu-btn-active);
206
+ }
207
+
208
+ .language-bar {
209
+ display: flex;
210
+ align-items: center;
211
+ justify-content: space-between;
212
+ gap: 12px;
213
+ width: 100%;
214
+ }
215
+
216
+ .select-wrapper {
217
+ flex: 1;
218
+ position: relative;
219
+ background: var(--bg-color);
220
+ border-radius: 12px;
221
+ box-shadow: var(--neu-inset);
222
+ display: flex;
223
+ align-items: center;
224
+ padding: 2px 12px;
225
+ }
226
+
227
+ .lang-select {
228
+ width: 100%;
229
+ padding: 10px 24px 10px 8px;
230
+ font-weight: 600;
231
+ color: var(--primary);
232
+ font-size: 0.95rem;
233
+ background: transparent;
234
+ border: none;
235
+ outline: none;
236
+ cursor: pointer;
237
+ appearance: none;
238
+ -webkit-appearance: none;
239
+ -moz-appearance: none;
240
+ }
241
+
242
+ .select-wrapper::after {
243
+ content: '\f107';
244
+ font-family: 'Font Awesome 6 Free';
245
+ font-weight: 900;
246
+ color: var(--primary);
247
+ position: absolute;
248
+ right: 12px;
249
+ pointer-events: none;
250
+ font-size: 0.85rem;
251
+ }
252
+
253
+ .lang-select option {
254
+ color: var(--text-main);
255
+ background: var(--bg-color);
256
+ }
257
+
258
+ .swap-btn {
259
+ background: var(--bg-color);
260
+ border: none;
261
+ border-radius: 50%;
262
+ width: 42px;
263
+ height: 42px;
264
+ min-width: 42px;
265
+ cursor: pointer;
266
+ display: flex;
267
+ align-items: center;
268
+ justify-content: center;
269
+ box-shadow: var(--neu-btn);
270
+ color: var(--text-main);
271
+ transition: all 0.2s ease;
272
+ }
273
+
274
+ .swap-btn:active {
275
+ box-shadow: var(--neu-btn-active);
276
+ }
277
+
278
+ .card-body {
279
+ display: grid;
280
+ grid-template-columns: 1fr 1fr;
281
+ gap: 16px;
282
+ }
283
+
284
+ .text-box-container {
285
+ background: var(--bg-color);
286
+ border-radius: 16px;
287
+ box-shadow: var(--neu-inset);
288
+ padding: 16px;
289
+ display: flex;
290
+ flex-direction: column;
291
+ justify-content: space-between;
292
+ }
293
+
294
+ textarea {
295
+ width: 100%;
296
+ height: 140px;
297
+ border: none;
298
+ outline: none;
299
+ resize: none;
300
+ font-size: 0.98rem;
301
+ color: var(--text-main);
302
+ background: transparent;
303
+ }
304
+
305
+ textarea::placeholder {
306
+ color: var(--text-muted);
307
+ opacity: 0.7;
308
+ }
309
+
310
+ .actions {
311
+ display: flex;
312
+ justify-content: flex-end;
313
+ gap: 8px;
314
+ margin-top: 8px;
315
+ flex-wrap: wrap;
316
+ }
317
+
318
+ .icon-btn {
319
+ background: var(--bg-color);
320
+ border: none;
321
+ color: var(--text-muted);
322
+ cursor: pointer;
323
+ padding: 8px 12px;
324
+ border-radius: 10px;
325
+ font-size: 0.85rem;
326
+ display: flex;
327
+ align-items: center;
328
+ gap: 6px;
329
+ box-shadow: var(--neu-btn);
330
+ transition: all 0.2s ease;
331
+ }
332
+
333
+ .icon-btn:active {
334
+ box-shadow: var(--neu-btn-active);
335
+ }
336
+
337
+ .btn-translate {
338
+ color: var(--primary);
339
+ font-weight: 600;
340
+ }
341
+
342
+ .btn-audio {
343
+ color: #10b981;
344
+ font-weight: 600;
345
+ }
346
+
347
+ .card-footer {
348
+ font-size: 0.8rem;
349
+ color: var(--text-muted);
350
+ text-align: center;
351
+ display: flex;
352
+ justify-content: space-between;
353
+ align-items: center;
354
+ padding-top: 8px;
355
+ flex-wrap: wrap;
356
+ gap: 10px;
357
+ }
358
+
359
+ .card-footer a {
360
+ color: var(--text-main);
361
+ text-decoration: none;
362
+ font-weight: 600;
363
+ }
364
+
365
+ /* Modal Styling */
366
+ .modal-overlay {
367
+ position: fixed;
368
+ top: 0;
369
+ left: 0;
370
+ width: 100vw;
371
+ height: 100vh;
372
+ background: rgba(0, 0, 0, 0.4);
373
+ backdrop-filter: blur(4px);
374
+ display: none;
375
+ justify-content: center;
376
+ align-items: center;
377
+ z-index: 1000;
378
+ padding: 16px;
379
+ }
380
+
381
+ .modal-overlay.active {
382
+ display: flex;
383
+ }
384
+
385
+ .modal {
386
+ background: var(--bg-color);
387
+ width: 100%;
388
+ max-width: 440px;
389
+ padding: 24px;
390
+ border-radius: 20px;
391
+ box-shadow: var(--neu-drop);
392
+ display: flex;
393
+ flex-direction: column;
394
+ gap: 16px;
395
+ }
396
+
397
+ .modal-header {
398
+ display: flex;
399
+ justify-content: space-between;
400
+ align-items: center;
401
+ }
402
+
403
+ .modal-header h3 {
404
+ font-size: 1.15rem;
405
+ font-weight: 700;
406
+ }
407
+
408
+ .input-group {
409
+ display: flex;
410
+ flex-direction: column;
411
+ gap: 6px;
412
+ }
413
+
414
+ .input-group label {
415
+ font-size: 0.85rem;
416
+ font-weight: 600;
417
+ color: var(--text-muted);
418
+ }
419
+
420
+ .input-group input {
421
+ background: var(--bg-color);
422
+ border: none;
423
+ outline: none;
424
+ padding: 12px;
425
+ border-radius: 12px;
426
+ box-shadow: var(--neu-inset);
427
+ color: var(--text-main);
428
+ font-size: 0.95rem;
429
+ }
430
+
431
+ .modal-actions {
432
+ display: flex;
433
+ justify-content: flex-end;
434
+ gap: 12px;
435
+ margin-top: 8px;
436
+ }
437
+
438
+ .btn-submit {
439
+ color: var(--primary);
440
+ }
441
+
442
+ /* Media Queries */
443
+ @media (max-width: 768px) {
444
+ .card-body {
445
+ grid-template-columns: 1fr;
446
+ }
447
+
448
+ .language-bar {
449
+ gap: 8px;
450
+ }
451
+
452
+ .swap-btn {
453
+ width: 38px;
454
+ height: 38px;
455
+ min-width: 38px;
456
+ }
457
+ }
458
+
459
+ @media (max-width: 480px) {
460
+ .translator-card {
461
+ padding: 16px;
462
+ gap: 16px;
463
+ }
464
+
465
+ .card-header {
466
+ flex-direction: column;
467
+ align-items: flex-start;
468
+ }
469
+
470
+ .add-word-trigger {
471
+ width: 100%;
472
+ justify-content: center;
473
+ }
474
+
475
+ .actions {
476
+ width: 100%;
477
+ justify-content: space-between;
478
+ }
479
+
480
+ .icon-btn {
481
+ flex: 1;
482
+ justify-content: center;
483
+ }
484
+ }
485
+ </style>
486
+ </head>
487
+ <body>
488
+
489
+ <!-- HEADER NAVBAR -->
490
+ <header class="sticky top-0 z-50 w-full px-4 sm:px-8 py-4 backdrop-blur-md transition-all duration-300">
491
+ <div class="max-w-7xl mx-auto flex items-center justify-between p-3 sm:p-4 rounded-2xl neu-flat border border-white/20 dark:border-white/5">
492
+
493
+ <!-- Brand Logo -->
494
+ <a href="#" class="flex items-center gap-3 group focus:outline-none" aria-label="Eunoiaverse Homepage">
495
+ <div class="w-10 h-10 rounded-xl neu-flat flex items-center justify-center text-indigo-600 dark:text-indigo-400 font-extrabold text-xl group-hover:scale-105 transition-transform">
496
+ <svg class="w-6 h-6 stroke-current" viewBox="0 0 24 24" fill="none" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">
497
+ <path d="M12 2L2 7l10 5 10-5-10-5zM2 17l10 5 10-5M2 12l10 5 10-5"/>
498
+ </svg>
499
+ </div>
500
+ <div class="flex flex-col">
501
+ <span class="font-bold text-lg leading-tight tracking-tight text-slate-800 dark:text-slate-100">Kamus Bahasa Daerah</span>
502
+ <span class="text-[10px] font-semibold text-slate-400 dark:text-slate-500 uppercase tracking-widest">Platform</span>
503
+ </div>
504
+ </a>
505
+
506
+ <!-- Navigation Tab Bar (Desktop) -->
507
+ <div class="hidden md:flex items-center gap-3">
508
+ <nav class="flex items-center gap-2 p-1.5 rounded-xl neu-pressed border border-black/5 dark:border-white/5" role="tablist" aria-label="Main Navigation">
509
+
510
+ <!-- Tab 1: Donation -->
511
+ <button
512
+ id="tab-donation"
513
+ onclick="switchTab('donation')"
514
+ role="tab"
515
+ aria-selected="true"
516
+ aria-controls="panel-donation"
517
+ class="tab-btn neu-pressed tab-active-accent flex items-center gap-2.5 px-5 py-2.5 rounded-lg text-sm font-semibold transition-all duration-200 focus:outline-none">
518
+ <svg class="w-4 h-4" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
519
+ <path stroke-linecap="round" stroke-linejoin="round" d="M4.318 6.318a4.5 4.5 0 000 6.364L12 20.364l7.682-7.684a4.5 4.5 0 00-6.364-6.364L12 7.636l-1.318-1.318a4.5 4.5 0 00-6.364 0z" />
520
+ </svg>
521
+ <span>Donation</span>
522
+ <span class="ml-1 px-1.5 py-0.5 text-[10px] rounded-full bg-indigo-500/10 text-indigo-600 dark:text-indigo-400 font-bold">New</span>
523
+ </button>
524
+
525
+ <!-- Tab 2: Book -->
526
+ <button
527
+ id="tab-book"
528
+ onclick="switchTab('book')"
529
+ role="tab"
530
+ aria-selected="false"
531
+ aria-controls="panel-book"
532
+ class="tab-btn neu-flat text-slate-600 dark:text-slate-400 hover:text-indigo-600 dark:hover:text-indigo-400 flex items-center gap-2.5 px-5 py-2.5 rounded-lg text-sm font-semibold transition-all duration-200 focus:outline-none">
533
+ <svg class="w-4 h-4" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
534
+ <path stroke-linecap="round" stroke-linejoin="round" d="M12 6.253v13m0-13C10.832 5.477 9.246 5 7.5 5S4.168 5.477 3 6.253v13C4.168 18.477 5.754 18 7.5 18s3.332.477 4.5 1.253m0-13C13.168 5.477 14.754 5 16.5 5c1.747 0 3.332.477 4.5 1.253v13C19.832 18.477 18.247 18 16.5 18c-1.746 0-3.332.477-4.5 1.253" />
535
+ </svg>
536
+ <span>Kamus</span>
537
+ </button>
538
+
539
+ <!-- Tab 3: Proposal -->
540
+ <button
541
+ id="tab-proposal"
542
+ onclick="switchTab('proposal')"
543
+ role="tab"
544
+ aria-selected="false"
545
+ aria-controls="panel-proposal"
546
+ class="tab-btn neu-flat text-slate-600 dark:text-slate-400 hover:text-indigo-600 dark:hover:text-indigo-400 flex items-center gap-2.5 px-5 py-2.5 rounded-lg text-sm font-semibold transition-all duration-200 focus:outline-none">
547
+ <svg class="w-4 h-4" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
548
+ <path stroke-linecap="round" stroke-linejoin="round" d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z" />
549
+ </svg>
550
+ <span>Proposal</span>
551
+ <span class="w-2 h-2 rounded-full bg-emerald-500 animate-pulse"></span>
552
+ </button>
553
+ </nav>
554
+
555
+ <!-- Utility Theme Switcher -->
556
+ <button
557
+ onclick="toggleTheme()"
558
+ title="Toggle Theme"
559
+ class="p-2.5 rounded-xl neu-button text-slate-600 dark:text-slate-300 hover:text-indigo-600 dark:hover:text-indigo-400 focus:outline-none"
560
+ aria-label="Toggle light and dark mode">
561
+ <svg id="sun-icon" class="w-5 h-5 hidden dark:block" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
562
+ <path stroke-linecap="round" stroke-linejoin="round" d="M12 3v1m0 16v1m9-9h-1M4 12H3m15.364 6.364l-.707-.707M6.343 6.343l-.707-.707m12.728 0l-.707.707M6.343 17.657l-.707.707M16 12a4 4 0 11-8 0 4 4 0 018 0z" />
563
+ </svg>
564
+ <svg id="moon-icon" class="w-5 h-5 block dark:hidden" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
565
+ <path stroke-linecap="round" stroke-linejoin="round" d="M20.354 15.354A9 9 0 018.646 3.646 9.003 9.003 0 0012 21a9.003 9.003 0 008.354-5.646z" />
566
+ </svg>
567
+ </button>
568
+ </div>
569
+
570
+ <!-- Mobile Controls (Hamburger & Theme) -->
571
+ <div class="flex items-center gap-3 md:hidden">
572
+ <button
573
+ onclick="toggleTheme()"
574
+ class="p-2.5 rounded-xl neu-button text-slate-600 dark:text-slate-300 focus:outline-none"
575
+ aria-label="Toggle Theme">
576
+ <svg class="w-5 h-5 hidden dark:block" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" d="M12 3v1m0 16v1m9-9h-1M4 12H3m15.364 6.364l-.707-.707M6.343 6.343l-.707-.707m12.728 0l-.707.707M6.343 17.657l-.707.707M16 12a4 4 0 11-8 0 4 4 0 018 0z" /></svg>
577
+ <svg class="w-5 h-5 block dark:hidden" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" d="M20.354 15.354A9 9 0 018.646 3.646 9.003 9.003 0 0012 21a9.003 9.003 0 008.354-5.646z" /></svg>
578
+ </button>
579
+
580
+ <button
581
+ id="mobile-menu-btn"
582
+ onclick="toggleMobileMenu()"
583
+ class="p-2.5 rounded-xl neu-button text-slate-600 dark:text-slate-300 focus:outline-none"
584
+ aria-label="Toggle Mobile Menu">
585
+ <svg id="hamburger-icon" class="w-6 h-6" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
586
+ <path stroke-linecap="round" stroke-linejoin="round" d="M4 6h16M4 12h16M4 18h16" />
587
+ </svg>
588
+ <svg id="close-icon" class="w-6 h-6 hidden" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
589
+ <path stroke-linecap="round" stroke-linejoin="round" d="M6 18L18 6M6 6l12 12" />
590
+ </svg>
591
+ </button>
592
+ </div>
593
+
594
+ </div>
595
+
596
+ <!-- Mobile Navigation Menu -->
597
+ <div id="mobile-menu" class="hidden md:hidden mt-3 p-4 rounded-2xl neu-flat flex-col gap-2">
598
+ <button onclick="switchTab('donation')" class="w-full text-left px-4 py-2.5 rounded-xl font-semibold text-slate-700 dark:text-slate-200 hover:bg-indigo-500/10">Donation</button>
599
+ <button onclick="switchTab('book')" class="w-full text-left px-4 py-2.5 rounded-xl font-semibold text-slate-700 dark:text-slate-200 hover:bg-indigo-500/10">Kamus</button>
600
+ <button onclick="switchTab('proposal')" class="w-full text-left px-4 py-2.5 rounded-xl font-semibold text-slate-700 dark:text-slate-200 hover:bg-indigo-500/10">Proposal</button>
601
+ </div>
602
+ </header>
603
+
604
+ <!-- MAIN CONTAINER WITH TABS -->
605
+ <main>
606
+ <!-- TAB PANEL 1: DONATION -->
607
+ <div id="panel-donation" class="tab-content active">
608
+ <div class="w-full max-w-2xl bg-white rounded-3xl shadow-xl shadow-slate-200/60 border border-slate-100 overflow-hidden transition-all duration-300 text-left">
609
+
610
+ <!-- Header Banner -->
611
+ <div class="bg-gradient-to-r from-emerald-600 to-teal-600 p-6 sm:p-8 text-white relative overflow-hidden">
612
+ <div class="absolute -right-10 -bottom-10 opacity-10 text-9xl">
613
+ <i class="fa-solid fa-hand-holding-heart"></i>
614
+ </div>
615
+ <div class="relative z-10">
616
+ <span class="inline-flex items-center gap-1.5 px-3 py-1 rounded-full text-xs font-semibold bg-emerald-500/40 text-emerald-100 mb-3 backdrop-blur-md">
617
+ <i class="fa-solid fa-shield-heart"></i> Secure & Verified
618
+ </span>
619
+ <h2 class="text-2xl sm:text-3xl font-bold tracking-tight">Make a Difference Today</h2>
620
+ <p class="text-emerald-100 mt-1 text-sm sm:text-base max-w-lg">Your contribution helps us preserve regional languages and support cultural documentation worldwide.</p>
621
+ </div>
622
+ </div>
623
+
624
+ <!-- Donation Body Form -->
625
+ <div class="p-6 sm:p-8 space-y-6">
626
+
627
+ <!-- Frequency Selection -->
628
+ <div>
629
+ <label class="block text-xs font-semibold uppercase tracking-wider text-slate-500 mb-2">Donation Frequency</label>
630
+ <div class="grid grid-cols-2 gap-3 p-1 bg-slate-100 rounded-2xl">
631
+ <button type="button" id="freq-one-time" onclick="setFrequency('one-time')" class="py-2.5 px-4 text-sm font-medium rounded-xl transition-all bg-white text-emerald-700 shadow-sm">One-Time</button>
632
+ <button type="button" id="freq-monthly" onclick="setFrequency('monthly')" class="py-2.5 px-4 text-sm font-medium rounded-xl transition-all text-slate-600 hover:text-slate-900">Monthly <span class="text-xs bg-emerald-100 text-emerald-800 px-1.5 py-0.5 rounded-md ml-1 font-semibold">Save 10%</span></button>
633
+ </div>
634
+ </div>
635
+
636
+ <!-- Donation Tiers -->
637
+ <div>
638
+ <label class="block text-xs font-semibold uppercase tracking-wider text-slate-500 mb-3">Select Amount</label>
639
+ <div class="grid grid-cols-2 sm:grid-cols-4 gap-3">
640
+ <button type="button" onclick="selectAmount(10)" class="tier-btn py-3 px-4 rounded-2xl border-2 border-slate-200 hover:border-emerald-500 font-bold text-slate-700 hover:text-emerald-600 transition-all text-center group bg-white">
641
+ <span class="block text-xl group-hover:scale-105 transition-transform">$10</span>
642
+ <span class="block text-[11px] font-normal text-slate-400 mt-0.5">Sponsors 1 Word</span>
643
+ </button>
644
+ <button type="button" onclick="selectAmount(25)" class="tier-btn py-3 px-4 rounded-2xl border-2 border-slate-200 hover:border-emerald-500 font-bold text-slate-700 hover:text-emerald-600 transition-all text-center group bg-white">
645
+ <span class="block text-xl group-hover:scale-105 transition-transform">$25</span>
646
+ <span class="block text-[11px] font-normal text-slate-400 mt-0.5">Sponsors 3 Words</span>
647
+ </button>
648
+ <button type="button" onclick="selectAmount(50)" class="tier-btn py-3 px-4 rounded-2xl border-2 border-emerald-500 font-bold text-emerald-700 bg-emerald-50/50 transition-all text-center group shadow-sm active-tier" id="tier-50">
649
+ <span class="block text-xl group-hover:scale-105 transition-transform">$50</span>
650
+ <span class="block text-[11px] font-normal text-emerald-600/80 mt-0.5">Supports 1 Dialect</span>
651
+ </button>
652
+ <button type="button" onclick="selectAmount(100)" class="tier-btn py-3 px-4 rounded-2xl border-2 border-slate-200 hover:border-emerald-500 font-bold text-slate-700 hover:text-emerald-600 transition-all text-center group bg-white">
653
+ <span class="block text-xl group-hover:scale-105 transition-transform">$100</span>
654
+ <span class="block text-[11px] font-normal text-slate-400 mt-0.5">Archive Patron</span>
655
+ </button>
656
+ </div>
657
+ </div>
658
+
659
+ <!-- Custom Amount Input -->
660
+ <div>
661
+ <label for="custom-amount" class="block text-xs font-semibold uppercase tracking-wider text-slate-500 mb-2">Or Custom Amount</label>
662
+ <div class="relative rounded-2xl shadow-sm">
663
+ <div class="absolute inset-y-0 left-0 pl-4 flex items-center pointer-events-none text-slate-400 font-bold text-lg">$</div>
664
+ <input type="number" id="custom-amount" placeholder="Enter amount" oninput="handleCustomInput(this.value)" class="block w-full pl-9 pr-4 py-3.5 bg-slate-50 border border-slate-200 rounded-2xl focus:ring-2 focus:ring-emerald-500 focus:border-emerald-500 text-slate-800 font-semibold text-base outline-none transition-all">
665
+ </div>
666
+ </div>
667
+
668
+ <!-- Payment Method Selection -->
669
+ <div>
670
+ <label class="block text-xs font-semibold uppercase tracking-wider text-slate-500 mb-3">Payment Method</label>
671
+ <div class="grid grid-cols-3 gap-3">
672
+ <button type="button" onclick="selectPayment('card')" id="pay-card" class="pay-btn flex flex-col items-center justify-center p-3 rounded-2xl border-2 border-emerald-500 bg-emerald-50/40 text-emerald-700 transition-all">
673
+ <i class="fa-solid fa-credit-card text-xl mb-1"></i>
674
+ <span class="text-xs font-semibold">Card</span>
675
+ </button>
676
+ <button type="button" onclick="selectPayment('paypal')" id="pay-paypal" class="pay-btn flex flex-col items-center justify-center p-3 rounded-2xl border-2 border-slate-200 hover:border-slate-300 text-slate-600 transition-all bg-white">
677
+ <i class="fa-brands fa-paypal text-xl mb-1 text-blue-600"></i>
678
+ <span class="text-xs font-semibold">PayPal</span>
679
+ </button>
680
+ <button type="button" onclick="selectPayment('apple')" id="pay-apple" class="pay-btn flex flex-col items-center justify-center p-3 rounded-2xl border-2 border-slate-200 hover:border-slate-300 text-slate-600 transition-all bg-white">
681
+ <i class="fa-brands fa-apple-pay text-2xl mb-0.5 text-slate-900"></i>
682
+ <span class="text-xs font-semibold">Apple Pay</span>
683
+ </button>
684
+ </div>
685
+ </div>
686
+
687
+ <!-- Permissions & Payment Agreements Section -->
688
+ <div class="bg-slate-50 border border-slate-200 rounded-2xl p-4 space-y-3">
689
+ <label class="block text-xs font-semibold uppercase tracking-wider text-slate-500">Payment Authorization & Permissions</label>
690
+
691
+ <!-- Checkbox 1: Terms and Conditions -->
692
+ <div class="flex items-start gap-3">
693
+ <input type="checkbox" id="perm-terms" class="mt-1 h-4 w-4 rounded border-slate-300 text-emerald-600 focus:ring-emerald-500 cursor-pointer">
694
+ <label for="perm-terms" class="text-xs text-slate-600 cursor-pointer select-none">
695
+ I authorize this payment and agree to the <a href="#" class="text-emerald-600 font-medium hover:underline">Terms of Service</a> & <a href="#" class="text-emerald-600 font-medium hover:underline">Privacy Policy</a>.
696
+ </label>
697
+ </div>
698
+
699
+ <!-- Checkbox 2: Recurring/Automatic Billing Authorization -->
700
+ <div class="flex items-start gap-3" id="recurring-permission-wrapper">
701
+ <input type="checkbox" id="perm-recurring" class="mt-1 h-4 w-4 rounded border-slate-300 text-emerald-600 focus:ring-emerald-500 cursor-pointer">
702
+ <label for="perm-recurring" class="text-xs text-slate-600 cursor-pointer select-none" id="recurring-permission-label">
703
+ I authorize this one-time debit from my selected payment method.
704
+ </label>
705
+ </div>
706
+ </div>
707
+
708
+ <!-- Error message container -->
709
+ <div id="error-alert" class="hidden bg-rose-50 border border-rose-200 text-rose-700 px-4 py-2.5 rounded-xl text-xs font-medium flex items-center gap-2">
710
+ <i class="fa-solid fa-circle-exclamation text-rose-500"></i>
711
+ <span id="error-text">Please agree to the terms and payment permissions to proceed.</span>
712
+ </div>
713
+
714
+ <!-- Submit Button & Disclaimer -->
715
+ <div class="pt-2">
716
+ <button type="button" onclick="handleDonate()" class="w-full py-4 px-6 bg-gradient-to-r from-emerald-600 to-teal-600 hover:from-emerald-700 hover:to-teal-700 text-white font-bold rounded-2xl shadow-lg shadow-emerald-600/30 transition-all transform hover:-translate-y-0.5 active:translate-y-0 flex items-center justify-center gap-2 text-base">
717
+ <span>Donate <span id="donate-btn-amount">$50</span> Now</span>
718
+ <i class="fa-solid fa-arrow-right text-sm"></i>
719
+ </button>
720
+ <p class="text-center text-xs text-slate-400 mt-3 flex items-center justify-center gap-1.5">
721
+ <i class="fa-solid fa-lock text-[10px]"></i> Payments are 256-bit SSL encrypted and tax-deductible.
722
+ </p>
723
+ </div>
724
+
725
+ </div>
726
+
727
+ </div>
728
+ </div>
729
+
730
+ <!-- TAB PANEL 2: KAMUS (TRANSLATOR) -->
731
+ <div id="panel-book" class="tab-content">
732
+ <div class="translator-card">
733
+ <div class="card-header">
734
+ <div>
735
+ <div class="card-title"></div>
736
+ <div class="card-subtitle" id="subtitle-info">Kutai Barat & Kalimantan Timur</div>
737
+ </div>
738
+ <button class="add-word-trigger" id="openModalBtn">
739
+ <i class="fa-solid fa-plus"></i> Tambah Kata
740
+ </button>
741
+ </div>
742
+
743
+ <!-- Dropdown Select Bahasa -->
744
+ <div class="language-bar">
745
+ <div class="select-wrapper">
746
+ <select class="lang-select" id="srcLang" title="Pilih Bahasa Sumber"></select>
747
+ </div>
748
+
749
+ <button class="swap-btn" id="swapBtn" title="Swap Languages">⇄</button>
750
+
751
+ <div class="select-wrapper">
752
+ <select class="lang-select" id="targetLang" title="Pilih Bahasa Tujuan"></select>
753
+ </div>
754
+ </div>
755
+
756
+ <div class="card-body">
757
+ <!-- Input Text Container -->
758
+ <div class="text-box-container">
759
+ <textarea id="sourceText" placeholder="Ketik teks di sini..."></textarea>
760
+ <div class="actions">
761
+ <button class="icon-btn btn-audio" id="srcAudioBtn" title="Dengarkan Sumber">
762
+ <i class="fa-solid fa-volume-high"></i>
763
+ </button>
764
+ <button class="icon-btn" id="clearBtn"><i class="fa-solid fa-xmark"></i> Clear</button>
765
+ <button class="icon-btn btn-translate" id="translateBtn"><i class="fa-solid fa-language"></i> Translate</button>
766
+ </div>
767
+ </div>
768
+
769
+ <!-- Output Text Container -->
770
+ <div class="text-box-container">
771
+ <textarea id="targetText" placeholder="Hasil terjemahan akan muncul di sini..." readonly></textarea>
772
+ <div class="actions">
773
+ <button class="icon-btn btn-audio" id="targetAudioBtn" title="Dengarkan Terjemahan">
774
+ <i class="fa-solid fa-volume-high"></i>
775
+ </button>
776
+ <button class="icon-btn" id="copyBtn"><i class="fa-solid fa-copy"></i> Copy</button>
777
+ </div>
778
+ </div>
779
+ </div>
780
+
781
+ <div class="card-footer">
782
+ <span id="wordCountBadge">Total kata tersimpan: 0</span>
783
+ <div>
784
+ Powered by <a href="https://w.wiki/8FLu" target="_blank" rel="noopener noreferrer">Edo Erpani</a>
785
+ </div>
786
+ </div>
787
+ </div>
788
+ </div>
789
+
790
+ <!-- TAB PANEL 3: PROPOSAL -->
791
+ <div id="panel-proposal" class="tab-content">
792
+ <div class="translator-card text-left p-6 sm:p-8">
793
+ <h3 class="text-xl font-bold mb-3">Project Proposal & Documentation</h3>
794
+ <p class="text-sm text-slate-500 mb-4 leading-relaxed">
795
+ Eunoiaverse Multilingual Regional Dictionary is a community-driven initiative aimed at safeguarding, preserving, and making indigenous languages in East Kalimantan (such as Tunjung, Benuaq, Kenyah, Bahau, and Kutai) digitally accessible.
796
+ </p>
797
+ <div class="bg-slate-50 p-4 rounded-2xl border border-slate-200 text-xs text-slate-600 space-y-2">
798
+ <div class="font-semibold text-slate-700">Key Objectives:</div>
799
+ <ul class="list-disc list-inside space-y-1">
800
+ <li>Open-source collection of local vocabulary.</li>
801
+ <li>Real-time browser-based translation tools.</li>
802
+ <li>Collaborative contributions directly from speakers.</li>
803
+ </ul>
804
+ </div>
805
+ </div>
806
+ </div>
807
+ </main>
808
+
809
+ <!-- MODAL TAMBAH KATA -->
810
+ <div class="modal-overlay" id="modalOverlay">
811
+ <div class="modal text-left">
812
+ <div class="modal-header">
813
+ <h3>Tambah Kata Baru</h3>
814
+ <button class="icon-btn" id="closeModalBtn"><i class="fa-solid fa-xmark"></i></button>
815
+ </div>
816
+
817
+ <div class="input-group">
818
+ <label for="newWordLanguage">Bahasa Daerah</label>
819
+ <select id="newWordLanguage" class="lang-select" aria-label="Pilih bahasa kata baru">
820
+ <option value="tj-TJ">Tunjung</option>
821
+ <option value="bq-BQ">Benuaq</option>
822
+ <option value="ky-KY">Kenyah</option>
823
+ <option value="bh-BH">Bahau</option>
824
+ <option value="kt-KT">Kutai</option>
825
+ </select>
826
+ </div>
827
+
828
+ <div class="input-group">
829
+ <label for="newWordInput">Kata Daerah</label>
830
+ <input type="text" id="newWordInput" placeholder="Contoh: Emooq">
831
+ </div>
832
+
833
+ <div class="input-group">
834
+ <label for="newIndoInput">Terjemahan Indonesia</label>
835
+ <input type="text" id="newIndoInput" placeholder="Contoh: Tinggi / Panjang">
836
+ </div>
837
+
838
+ <div class="modal-actions">
839
+ <button class="icon-btn btn-submit" id="saveWordBtn">
840
+ <i class="fa-solid fa-check"></i> Simpan Kata
841
+ </button>
842
+ </div>
843
+ </div>
844
+ </div>
845
+
846
+ <!-- Success Modal Notification -->
847
+ <div id="success-modal" class="fixed inset-0 bg-slate-900/60 backdrop-blur-sm hidden items-center justify-center p-4 z-50 transition-opacity">
848
+ <div class="bg-white rounded-3xl p-8 max-w-sm w-full text-center shadow-2xl transform scale-95 transition-transform duration-300" id="modal-content">
849
+ <div class="w-16 h-16 bg-emerald-100 text-emerald-600 rounded-full flex items-center justify-center mx-auto mb-4 text-3xl">
850
+ <i class="fa-solid fa-check"></i>
851
+ </div>
852
+ <h3 class="text-xl font-bold text-slate-800 mb-1">Thank You!</h3>
853
+ <p class="text-slate-500 text-sm mb-6" id="success-message">Your generous donation has been successfully processed.</p>
854
+ <button onclick="closeDonationModal()" class="w-full py-3 bg-slate-900 hover:bg-slate-800 text-white font-semibold rounded-xl transition-all">Close</button>
855
+ </div>
856
+ </div>
857
+
858
+ <!-- JAVASCRIPT LOGIC -->
859
+ <script>
860
+ // Language options configuration
861
+ const languages = [
862
+ { code: 'id-ID', name: 'Indonesia' },
863
+ { code: 'tj-TJ', name: 'Tunjung' },
864
+ { code: 'bq-BQ', name: 'Benuaq' },
865
+ { code: 'ky-KY', name: 'Kenyah' },
866
+ { code: 'bh-BH', name: 'Bahau' },
867
+ { code: 'kt-KT', name: 'Kutai' }
868
+ ];
869
+
870
+ // Initial Dictionary Dataset
871
+ const initialDictionary = [
872
+ ['Baq', 'Ada'], ['Nya', 'apakah'], ['Nyama', 'apa'], ['Lonya', 'Bagaimana'], ['Menya', 'Kemana'], ['Adi', 'Berapa'], ['Tih', 'Ini'], ['Ito', 'Itu'], ['Dito', 'Disana'], ['Ditih', 'Disini'], ['Dinya', 'Dimana'], ['Encoq', 'Jauh'], ['Totoq', 'Dekat'], ['Emooq', 'Tinggi'], ['Itint', 'Rendah'], ['Moq', 'Panjang'],
873
+ ['Itit', 'Kecil'], ['Hajaq', 'Besar'], ['Inaq', 'Belum'], ['Soq', 'Sudah'], ['Perangk', 'Panas'], ['Celamp', 'Dingin'], ['Isay', 'Baru'], ['Isay tih', 'Baru ini'], ['Isay nyi', 'Baru saja'], ['Mai', 'Lama'], ['Nemaq', 'Pergi'], ['Diapm', 'Tinggal'], ['Mot', 'Datang'], ['Buru-buru', 'Gagaq'], ['Cepat', 'Jamit'], ['Berdohai', 'Pelan-pelan'], ['Sengket', 'Naik'], ['Mile', 'Turun'], ['Tala', 'Terang'], ['Gelap', 'Gempitaq'], ['Pejai', 'Jelek'], ['Pajiq', 'Baik'], ['Bajik', 'Baik'],
874
+ ['Mui', 'Tidak'], ['Ewah', 'Iya'], ['Heq', 'Enggak'], ['Lat', 'Bohong'],
875
+ ['Hitam', 'Permaq'], ['Biru', 'Nahum'], ['Bohongq', 'Merah'], ['Putiq', 'Putih'],
876
+ ['Bueh', 'Satu'], ['Regaq', 'Dua'], ['Teluq', 'Tiga'], ['Pat', 'Empat'], ['Limaq', 'Lima'], ['Hagant', 'Enam'], ['Tucuq', 'Tujuh'], ['Kalungk', 'Delapan'], ['Setiant', 'Sembilan'], ['Sawangk', 'Sepuluh'],
877
+ ['Belas', 'Sebelas'], ['Cahatu', 'Seratus'], ['Ribu', 'Seribu'], ['Juta', 'Sejuta'], ['Gari', 'Adik'], ['Mpom Lihaq', 'Kakek'], ['Mpom Waweq', 'Nenek'], ['Ucuq', 'Paman'],
878
+ ['Wanaq', 'Suami'], ['Sagaq', 'Istri'], ['Akuq', 'Aku'], ['Koi', 'Kamu'], ['Kamiq', 'Kami'], ['Tai', 'Kita'], ['Kamp', 'Kalian'], ['Eraq', 'Mereka'], ['Ulunt', 'Orang'],
879
+ ['Mersiaq', 'Manusia'], ['Ulunt Pelagaq', 'Orang Tua'], ['Pelegaq Mai', 'Leluhur'], ['Pelegaq', 'Tua'], ['Kabant Tuhiq', 'Anak-anak'], ['Tuhiq', 'Anak'], ['Encunt', 'Cucu'], ['Mulai', 'Mulai'], ['Tagaq', 'Tertawa'], ['Nangi', 'Menangis'], ['Tiro', 'Tidur'], ['Kuman', 'Makan'], ['Muruq', 'Minum'], ['Bejalan', 'Ngedot'], ['teliuq', 'Berlari'], ['Ngaweng', 'Memanjat'], ['Tepatiiq', 'Melompat'], ['Nulis', 'Menulis'], ['Maca', 'Membaca'],
880
+ ['Angka', 'Kira-kira'], ['Angkake', 'Kiranya'], ['Angkai', 'Bangkai'], ['Laitn', 'Lain'], ['Laoq', 'Lapar'], ['Lea', 'Bosan'], ['Loah', 'Mual'],
881
+ ['Loaaq', 'Lemak'], ['Loan', 'Lemak'], ['Loseeu', 'Longgar'], ['Luuok', 'Lubang'], ['Nau', 'Hari'], ['Dilau', 'Besok'], ['Telamaq', 'Depan'], ['Lituq', 'Belakang'], ['Ulant', 'Bulan'], ['Taont', 'Tahun'], ['Mentiuuq', 'Bunuh diri'], ['Meraiq', 'Melerai'],
882
+ ['Nerdaatn', 'Berterus terang'], ['Jaur', 'Kabur'], ['Keliuq', 'Keracunan'], ['Nguit', 'Menyukit'], ['Leler-maer', 'Tidak Terurus'], ['Tertimpa', 'Keluatn']
883
+ ];
884
+
885
+ // State Variables
886
+ let activeDictionary = [];
887
+ let currentAmount = 50;
888
+ let currentFrequency = 'one-time';
889
+ let currentPayment = 'card';
890
+
891
+ // DOM Elements
892
+ const srcLangSelect = document.getElementById('srcLang');
893
+ const targetLangSelect = document.getElementById('targetLang');
894
+ const sourceText = document.getElementById('sourceText');
895
+ const targetText = document.getElementById('targetText');
896
+ const swapBtn = document.getElementById('swapBtn');
897
+ const translateBtn = document.getElementById('translateBtn');
898
+ const clearBtn = document.getElementById('clearBtn');
899
+ const copyBtn = document.getElementById('copyBtn');
900
+ const wordCountBadge = document.getElementById('wordCountBadge');
901
+
902
+ // Modal Elements
903
+ const openModalBtn = document.getElementById('openModalBtn');
904
+ const closeModalBtn = document.getElementById('closeModalBtn');
905
+ const modalOverlay = document.getElementById('modalOverlay');
906
+ const saveWordBtn = document.getElementById('saveWordBtn');
907
+ const newWordLanguage = document.getElementById('newWordLanguage');
908
+ const newWordInput = document.getElementById('newWordInput');
909
+ const newIndoInput = document.getElementById('newIndoInput');
910
+
911
+ // Initialize App
912
+ document.addEventListener('DOMContentLoaded', () => {
913
+ loadDictionary();
914
+ populateLanguageSelects();
915
+ setupEventListeners();
916
+ updateWordCount();
917
+ });
918
+
919
+ // Load dictionary from localStorage or default
920
+ function loadDictionary() {
921
+ const stored = localStorage.getItem('eunoia_dictionary');
922
+ if (stored) {
923
+ try {
924
+ activeDictionary = JSON.parse(stored);
925
+ } catch (e) {
926
+ activeDictionary = [...initialDictionary];
927
+ }
928
+ } else {
929
+ activeDictionary = [...initialDictionary];
930
+ saveDictionary();
931
+ }
932
+ }
933
+
934
+ function saveDictionary() {
935
+ localStorage.setItem('eunoia_dictionary', JSON.stringify(activeDictionary));
936
+ updateWordCount();
937
+ }
938
+
939
+ function updateWordCount() {
940
+ wordCountBadge.textContent = `Total kata tersimpan: ${activeDictionary.length}`;
941
+ }
942
+
943
+ // Populate Select Options
944
+ function populateLanguageSelects() {
945
+ srcLangSelect.innerHTML = '';
946
+ targetLangSelect.innerHTML = '';
947
+
948
+ languages.forEach((lang) => {
949
+ const opt1 = new Option(lang.name, lang.code);
950
+ const opt2 = new Option(lang.name, lang.code);
951
+ srcLangSelect.add(opt1);
952
+ targetLangSelect.add(opt2);
953
+ });
954
+
955
+ srcLangSelect.value = 'id-ID';
956
+ targetLangSelect.value = 'tj-TJ';
957
+ }
958
+
959
+ // Translation Engine Logic
960
+ function translate() {
961
+ const query = sourceText.value.trim();
962
+ if (!query) {
963
+ targetText.value = '';
964
+ return;
965
  }
966
+
967
+ const fromLang = srcLangSelect.value;
968
+ const toLang = targetLangSelect.value;
969
+
970
+ if (fromLang === toLang) {
971
+ targetText.value = sourceText.value;
972
+ return;
973
+ }
974
+
975
+ const tokens = query.split(/(\s+|[^\p{L}\p{N}\s])/gu);
976
+ const translatedTokens = tokens.map((token) => {
977
+ const cleanToken = token.trim();
978
+ if (!cleanToken || /[^\p{L}\p{N}]/u.test(cleanToken)) return token;
979
+
980
+ const entry = activeDictionary.find(
981
+ (item) => item[fromLang] && item[fromLang].toLowerCase() === cleanToken.toLowerCase()
982
+ );
983
+
984
+ if (entry && entry[toLang]) {
985
+ return entry[toLang];
986
+ }
987
+
988
+ return cleanToken;
989
+ });
990
+
991
+ targetText.value = translatedTokens.join('');
992
+ }
993
+
994
+ // Setup Event Listeners
995
+ function setupEventListeners() {
996
+ sourceText.addEventListener('input', translate);
997
+ srcLangSelect.addEventListener('change', translate);
998
+ targetLangSelect.addEventListener('change', translate);
999
+
1000
+ swapBtn.addEventListener('click', () => {
1001
+ const temp = srcLangSelect.value;
1002
+ srcLangSelect.value = targetLangSelect.value;
1003
+ targetLangSelect.value = temp;
1004
+
1005
+ const tempText = sourceText.value;
1006
+ sourceText.value = targetText.value;
1007
+ targetText.value = tempText;
1008
+
1009
+ translate();
1010
+ });
1011
+
1012
+ translateBtn.addEventListener('click', translate);
1013
+ clearBtn.addEventListener('click', () => {
1014
+ sourceText.value = '';
1015
+ targetText.value = '';
1016
+ });
1017
+
1018
+ copyBtn.addEventListener('click', async () => {
1019
+ if (!targetText.value) return;
1020
+
1021
  try {
1022
+ if (navigator.clipboard && window.isSecureContext) {
1023
+ await navigator.clipboard.writeText(targetText.value);
1024
+ } else {
1025
+ const tempInput = document.createElement('textarea');
1026
+ tempInput.value = targetText.value;
1027
+ tempInput.setAttribute('readonly', '');
1028
+ tempInput.style.position = 'fixed';
1029
+ tempInput.style.opacity = '0';
1030
+ document.body.appendChild(tempInput);
1031
+ tempInput.select();
1032
+ document.execCommand('copy');
1033
+ document.body.removeChild(tempInput);
1034
+ }
1035
+
1036
+ const origText = copyBtn.innerHTML;
1037
+ copyBtn.innerHTML = '<i class="fa-solid fa-check"></i> Copied!';
1038
+ setTimeout(() => (copyBtn.innerHTML = origText), 1800);
1039
+ } catch (error) {
1040
+ const origText = copyBtn.innerHTML;
1041
+ copyBtn.innerHTML = '<i class="fa-solid fa-triangle-exclamation"></i> Failed';
1042
+ setTimeout(() => (copyBtn.innerHTML = origText), 1800);
1043
  }
1044
+ });
1045
+
1046
+ document.getElementById('srcAudioBtn').addEventListener('click', () => speakText(sourceText.value, srcLangSelect.value));
1047
+ document.getElementById('targetAudioBtn').addEventListener('click', () => speakText(targetText.value, targetLangSelect.value));
1048
+
1049
+ openModalBtn.addEventListener('click', () => modalOverlay.classList.add('active'));
1050
+ closeModalBtn.addEventListener('click', () => modalOverlay.classList.remove('active'));
1051
+ modalOverlay.addEventListener('click', (e) => {
1052
+ if (e.target === modalOverlay) modalOverlay.classList.remove('active');
1053
+ });
1054
+
1055
+ saveWordBtn.addEventListener('click', () => {
1056
+ const lang = newWordLanguage.value;
1057
+ const regionalWord = newWordInput.value.trim().toLowerCase();
1058
+ const indoWord = newIndoInput.value.trim().toLowerCase();
1059
+
1060
+ if (!regionalWord || !indoWord) {
1061
+ alert('Mohon isi kata daerah dan terjemahannya.');
1062
+ return;
1063
+ }
1064
+
1065
+ let existing = activeDictionary.find((item) => item['id-ID'] === indoWord);
1066
+ if (existing) {
1067
+ existing[lang] = regionalWord;
1068
+ } else {
1069
+ const newEntry = {
1070
+ id: Date.now().toString(),
1071
+ 'id-ID': indoWord,
1072
+ [lang]: regionalWord
1073
+ };
1074
+ activeDictionary.push(newEntry);
1075
+ }
1076
+
1077
+ saveDictionary();
1078
+ newWordInput.value = '';
1079
+ newIndoInput.value = '';
1080
+ modalOverlay.classList.remove('active');
1081
+ translate();
1082
+ });
1083
+ }
1084
+
1085
+ // Donation Form Handlers
1086
+ function setFrequency(freq) {
1087
+ currentFrequency = freq;
1088
+ const oneTimeBtn = document.getElementById('freq-one-time');
1089
+ const monthlyBtn = document.getElementById('freq-monthly');
1090
+ const recurringLabel = document.getElementById('recurring-permission-label');
1091
+
1092
+ if (freq === 'one-time') {
1093
+ oneTimeBtn.className = "py-2.5 px-4 text-sm font-medium rounded-xl transition-all bg-white text-emerald-700 shadow-sm";
1094
+ monthlyBtn.className = "py-2.5 px-4 text-sm font-medium rounded-xl transition-all text-slate-600 hover:text-slate-900";
1095
+ recurringLabel.innerText = "I authorize this one-time debit from my selected payment method.";
1096
+ } else {
1097
+ monthlyBtn.className = "py-2.5 px-4 text-sm font-medium rounded-xl transition-all bg-white text-emerald-700 shadow-sm";
1098
+ oneTimeBtn.className = "py-2.5 px-4 text-sm font-medium rounded-xl transition-all text-slate-600 hover:text-slate-900";
1099
+ recurringLabel.innerText = "I authorize recurring monthly deductions until I choose to cancel my subscription.";
1100
+ }
1101
+ }
1102
+
1103
+ function selectAmount(amount) {
1104
+ currentAmount = amount;
1105
+ document.getElementById('custom-amount').value = '';
1106
+
1107
+ const buttons = document.querySelectorAll('.tier-btn');
1108
+ buttons.forEach(btn => {
1109
+ btn.className = "tier-btn py-3 px-4 rounded-2xl border-2 border-slate-200 hover:border-emerald-500 font-bold text-slate-700 hover:text-emerald-600 transition-all text-center group bg-white";
1110
+ const subtext = btn.querySelector('span:last-child');
1111
+ if(subtext) subtext.className = "block text-[11px] font-normal text-slate-400 mt-0.5";
1112
+ });
1113
+
1114
+ event.currentTarget.className = "tier-btn py-3 px-4 rounded-2xl border-2 border-emerald-500 font-bold text-emerald-700 bg-emerald-50/50 transition-all text-center group shadow-sm active-tier";
1115
+ const activeSub = event.currentTarget.querySelector('span:last-child');
1116
+ if(activeSub) activeSub.className = "block text-[11px] font-normal text-emerald-600/80 mt-0.5";
1117
+
1118
+ updateButtonLabel();
1119
+ }
1120
+
1121
+ function handleCustomInput(val) {
1122
+ if (val && !isNaN(val) && val > 0) {
1123
+ currentAmount = Number(val);
1124
+ const buttons = document.querySelectorAll('.tier-btn');
1125
+ buttons.forEach(btn => {
1126
+ btn.className = "tier-btn py-3 px-4 rounded-2xl border-2 border-slate-200 hover:border-emerald-500 font-bold text-slate-700 hover:text-emerald-600 transition-all text-center group bg-white";
1127
+ const subtext = btn.querySelector('span:last-child');
1128
+ if(subtext) subtext.className = "block text-[11px] font-normal text-slate-400 mt-0.5";
1129
+ });
1130
+ updateButtonLabel();
1131
+ }
1132
+ }
1133
+
1134
+ function selectPayment(method) {
1135
+ currentPayment = method;
1136
+ const methods = ['card', 'paypal', 'apple'];
1137
+ methods.forEach(m => {
1138
+ const btn = document.getElementById(`pay-${m}`);
1139
+ if (m === method) {
1140
+ btn.className = "pay-btn flex flex-col items-center justify-center p-3 rounded-2xl border-2 border-emerald-500 bg-emerald-50/40 text-emerald-700 transition-all";
1141
+ } else {
1142
+ btn.className = "pay-btn flex flex-col items-center justify-center p-3 rounded-2xl border-2 border-slate-200 hover:border-slate-300 text-slate-600 transition-all bg-white";
1143
+ }
1144
+ });
1145
+ }
1146
+
1147
+ function updateButtonLabel() {
1148
+ document.getElementById('donate-btn-amount').innerText = `$${currentAmount}`;
1149
+ }
1150
+
1151
+ function handleDonate() {
1152
+ const termsChecked = document.getElementById('perm-terms').checked;
1153
+ const recurringChecked = document.getElementById('perm-recurring').checked;
1154
+ const errorAlert = document.getElementById('error-alert');
1155
+
1156
+ if (!termsChecked || !recurringChecked) {
1157
+ errorAlert.classList.remove('hidden');
1158
+ return;
1159
+ } else {
1160
+ errorAlert.classList.add('hidden');
1161
+ }
1162
+
1163
+ const amountToDisplay = currentAmount > 0 ? currentAmount : 50;
1164
+ const freqText = currentFrequency === 'monthly' ? 'monthly' : '';
1165
+ document.getElementById('success-message').innerText = `Your generous ${freqText} donation of $${amountToDisplay} has been successfully processed. Thank you for supporting regional language preservation!`;
1166
+
1167
+ const modal = document.getElementById('success-modal');
1168
+ const modalContent = document.getElementById('modal-content');
1169
+ modal.style.display = 'flex';
1170
+ setTimeout(() => {
1171
+ modal.classList.remove('hidden');
1172
+ modalContent.classList.remove('scale-95');
1173
+ modalContent.classList.add('scale-100');
1174
+ }, 10);
1175
+ }
1176
+
1177
+ function closeDonationModal() {
1178
+ const modal = document.getElementById('success-modal');
1179
+ const modalContent = document.getElementById('modal-content');
1180
+ modalContent.classList.remove('scale-100');
1181
+ modalContent.classList.add('scale-95');
1182
+ setTimeout(() => {
1183
+ modal.classList.add('hidden');
1184
+ modal.style.display = 'none';
1185
+ }, 200);
1186
+ }
1187
+
1188
+ // Text to Speech Helper
1189
+ function speakText(text, langCode) {
1190
+ if (!text) return;
1191
+ if ('speechSynthesis' in window) {
1192
+ window.speechSynthesis.cancel();
1193
+ const utterance = new SpeechSynthesisUtterance(text);
1194
+
1195
+ const languageMap = {
1196
+ 'id-ID': 'id-ID',
1197
+ 'tj-TJ': 'id-ID',
1198
+ 'bq-BQ': 'id-ID',
1199
+ 'ky-KY': 'id-ID',
1200
+ 'bh-BH': 'id-ID',
1201
+ 'kt-KT': 'id-ID'
1202
  };
1203
+
1204
+ utterance.lang = languageMap[langCode] || 'id-ID';
1205
+ window.speechSynthesis.speak(utterance);
1206
+ }
1207
+ }
1208
+
1209
+ // Navigation Tab Switcher
1210
+ function switchTab(tabName) {
1211
+ const tabs = ['donation', 'book', 'proposal'];
1212
+ tabs.forEach((t) => {
1213
+ const btn = document.getElementById(`tab-${t}`);
1214
+ const panel = document.getElementById(`panel-${t}`);
1215
+ if (!btn || !panel) return;
1216
+
1217
+ if (t === tabName) {
1218
+ btn.className = 'tab-btn neu-pressed tab-active-accent flex items-center gap-2.5 px-5 py-2.5 rounded-lg text-sm font-semibold transition-all duration-200 focus:outline-none';
1219
+ btn.setAttribute('aria-selected', 'true');
1220
+ panel.classList.add('active');
1221
+ } else {
1222
+ btn.className = 'tab-btn neu-flat text-slate-600 dark:text-slate-400 hover:text-indigo-600 dark:hover:text-indigo-400 flex items-center gap-2.5 px-5 py-2.5 rounded-lg text-sm font-semibold transition-all duration-200 focus:outline-none';
1223
+ btn.setAttribute('aria-selected', 'false');
1224
+ panel.classList.remove('active');
1225
+ }
1226
+ });
1227
+ }
1228
+
1229
+ // Theme Toggle Function
1230
+ function toggleTheme() {
1231
+ document.documentElement.classList.toggle('dark');
1232
+ }
1233
+
1234
+ // Mobile Menu Toggle
1235
+ function toggleMobileMenu() {
1236
+ const menu = document.getElementById('mobile-menu');
1237
+ const hamburger = document.getElementById('hamburger-icon');
1238
+ const close = document.getElementById('close-icon');
1239
+
1240
+ if (menu.classList.contains('hidden')) {
1241
+ menu.classList.remove('hidden');
1242
+ menu.classList.add('flex');
1243
+ hamburger.classList.add('hidden');
1244
+ close.classList.remove('hidden');
1245
+ } else {
1246
+ menu.classList.add('hidden');
1247
+ menu.classList.remove('flex');
1248
+ hamburger.classList.remove('hidden');
1249
+ close.classList.add('hidden');
1250
+ }
1251
+ }
1252
+ </script>
1253
+ </body>
1254
  </html>