AptlyDigital commited on
Commit
44c3a3c
·
verified ·
1 Parent(s): 58dc9d4

Upload deepseek_html_20260108_c1212a.html

Browse files
Files changed (1) hide show
  1. deepseek_html_20260108_c1212a.html +1915 -0
deepseek_html_20260108_c1212a.html ADDED
@@ -0,0 +1,1915 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
+ <title>AI-Powered Spelling Tutor</title>
7
+ <script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
8
+ <script src="https://cdn.jsdelivr.net/npm/three@0.128.0/examples/js/controls/OrbitControls.min.js"></script>
9
+ <script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
10
+ <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
11
+ <style>
12
+ * {
13
+ margin: 0;
14
+ padding: 0;
15
+ box-sizing: border-box;
16
+ }
17
+
18
+ body {
19
+ background: linear-gradient(135deg, #0a0a0f 0%, #1a1a2e 100%);
20
+ color: #fff;
21
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, sans-serif;
22
+ overflow: hidden;
23
+ height: 100vh;
24
+ }
25
+
26
+ #canvasContainer {
27
+ width: 100%;
28
+ height: 100%;
29
+ position: fixed;
30
+ top: 0;
31
+ left: 0;
32
+ z-index: 1;
33
+ }
34
+
35
+ canvas {
36
+ display: block;
37
+ outline: none;
38
+ width: 100%;
39
+ height: 100%;
40
+ }
41
+
42
+ /* === MAIN INTERFACE === */
43
+ .main-interface {
44
+ position: fixed;
45
+ top: 20px;
46
+ left: 20px;
47
+ right: 20px;
48
+ bottom: 20px;
49
+ background: rgba(20, 20, 35, 0.7);
50
+ backdrop-filter: blur(10px);
51
+ border-radius: 24px;
52
+ border: 1px solid rgba(255, 255, 255, 0.1);
53
+ box-shadow: 0 20px 60px rgba(0, 0, 0, 0.4);
54
+ display: flex;
55
+ overflow: hidden;
56
+ z-index: 2;
57
+ }
58
+
59
+ /* === SIDEBAR === */
60
+ .sidebar {
61
+ width: 320px;
62
+ background: rgba(15, 15, 25, 0.9);
63
+ border-right: 1px solid rgba(255, 255, 255, 0.05);
64
+ padding: 25px;
65
+ display: flex;
66
+ flex-direction: column;
67
+ overflow-y: auto;
68
+ }
69
+
70
+ .sidebar-header {
71
+ margin-bottom: 30px;
72
+ }
73
+
74
+ .sidebar-title {
75
+ font-size: 1.5em;
76
+ font-weight: 600;
77
+ color: #5a6cff;
78
+ margin-bottom: 5px;
79
+ display: flex;
80
+ align-items: center;
81
+ gap: 10px;
82
+ }
83
+
84
+ .sidebar-subtitle {
85
+ color: #8892b0;
86
+ font-size: 0.9em;
87
+ }
88
+
89
+ .section {
90
+ margin-bottom: 30px;
91
+ }
92
+
93
+ .section-title {
94
+ font-size: 1em;
95
+ font-weight: 600;
96
+ color: #a0b0ff;
97
+ margin-bottom: 15px;
98
+ display: flex;
99
+ align-items: center;
100
+ gap: 8px;
101
+ }
102
+
103
+ .btn-group {
104
+ display: flex;
105
+ flex-direction: column;
106
+ gap: 10px;
107
+ }
108
+
109
+ .btn {
110
+ padding: 12px 20px;
111
+ background: rgba(255, 255, 255, 0.07);
112
+ border: 1px solid rgba(255, 255, 255, 0.1);
113
+ border-radius: 12px;
114
+ color: #e0e0ff;
115
+ font-family: inherit;
116
+ font-size: 0.95em;
117
+ cursor: pointer;
118
+ transition: all 0.3s ease;
119
+ text-align: left;
120
+ display: flex;
121
+ align-items: center;
122
+ gap: 10px;
123
+ }
124
+
125
+ .btn:hover {
126
+ background: rgba(255, 255, 255, 0.12);
127
+ transform: translateX(5px);
128
+ }
129
+
130
+ .btn.active {
131
+ background: linear-gradient(135deg, #5a6cff, #7a8aff);
132
+ color: white;
133
+ border-color: #5a6cff;
134
+ }
135
+
136
+ .btn-primary {
137
+ background: linear-gradient(135deg, #5a6cff, #7a8aff);
138
+ color: white;
139
+ border: none;
140
+ font-weight: 500;
141
+ justify-content: center;
142
+ }
143
+
144
+ .btn-primary:hover {
145
+ background: linear-gradient(135deg, #7a8aff, #5a6cff);
146
+ transform: translateY(-2px);
147
+ box-shadow: 0 5px 15px rgba(90, 108, 255, 0.4);
148
+ }
149
+
150
+ .btn-danger {
151
+ background: linear-gradient(135deg, #ff5a5a, #ff7a7a);
152
+ color: white;
153
+ border: none;
154
+ font-weight: 500;
155
+ justify-content: center;
156
+ }
157
+
158
+ .btn-danger:hover {
159
+ background: linear-gradient(135deg, #ff7a7a, #ff5a5a);
160
+ transform: translateY(-2px);
161
+ box-shadow: 0 5px 15px rgba(255, 90, 90, 0.4);
162
+ }
163
+
164
+ .progress-container {
165
+ background: rgba(255, 255, 255, 0.05);
166
+ border-radius: 12px;
167
+ padding: 15px;
168
+ margin-top: 15px;
169
+ }
170
+
171
+ .progress-bar {
172
+ height: 6px;
173
+ background: rgba(255, 255, 255, 0.1);
174
+ border-radius: 3px;
175
+ overflow: hidden;
176
+ margin: 8px 0;
177
+ }
178
+
179
+ .progress-fill {
180
+ height: 100%;
181
+ background: linear-gradient(90deg, #5a6cff, #34d399);
182
+ border-radius: 3px;
183
+ transition: width 0.5s ease;
184
+ }
185
+
186
+ .progress-stats {
187
+ display: flex;
188
+ justify-content: space-between;
189
+ font-size: 0.9em;
190
+ color: #8892b0;
191
+ }
192
+
193
+ .stats-grid {
194
+ display: grid;
195
+ grid-template-columns: 1fr 1fr;
196
+ gap: 10px;
197
+ margin-top: 15px;
198
+ }
199
+
200
+ .stat-card {
201
+ background: rgba(255, 255, 255, 0.05);
202
+ border-radius: 10px;
203
+ padding: 12px;
204
+ text-align: center;
205
+ }
206
+
207
+ .stat-value {
208
+ font-size: 1.3em;
209
+ font-weight: 600;
210
+ color: #5a6cff;
211
+ margin-bottom: 5px;
212
+ }
213
+
214
+ .stat-label {
215
+ font-size: 0.8em;
216
+ color: #8892b0;
217
+ }
218
+
219
+ /* === MAIN CONTENT === */
220
+ .main-content {
221
+ flex: 1;
222
+ padding: 30px;
223
+ display: flex;
224
+ flex-direction: column;
225
+ overflow-y: auto;
226
+ }
227
+
228
+ .word-display-container {
229
+ background: rgba(15, 15, 25, 0.8);
230
+ border-radius: 20px;
231
+ padding: 40px;
232
+ text-align: center;
233
+ margin-bottom: 30px;
234
+ border: 2px solid rgba(90, 108, 255, 0.3);
235
+ min-height: 200px;
236
+ display: flex;
237
+ align-items: center;
238
+ justify-content: center;
239
+ flex-direction: column;
240
+ }
241
+
242
+ .word-display {
243
+ font-family: 'Courier New', monospace;
244
+ font-size: 4em;
245
+ font-weight: 800;
246
+ letter-spacing: 8px;
247
+ margin: 20px 0;
248
+ color: white;
249
+ text-shadow: 0 0 20px rgba(90, 108, 255, 0.3);
250
+ }
251
+
252
+ .word-display.correct {
253
+ color: #34d399;
254
+ text-shadow: 0 0 20px rgba(52, 211, 153, 0.3);
255
+ }
256
+
257
+ .word-display.incorrect {
258
+ color: #ff5a5a;
259
+ text-shadow: 0 0 20px rgba(255, 90, 90, 0.3);
260
+ }
261
+
262
+ .word-hint {
263
+ color: #a0b0ff;
264
+ font-size: 1.2em;
265
+ margin-top: 15px;
266
+ font-style: italic;
267
+ }
268
+
269
+ .controls-grid {
270
+ display: grid;
271
+ grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
272
+ gap: 15px;
273
+ margin-bottom: 30px;
274
+ }
275
+
276
+ .input-container {
277
+ background: rgba(255, 255, 255, 0.05);
278
+ border-radius: 15px;
279
+ padding: 25px;
280
+ margin-bottom: 25px;
281
+ }
282
+
283
+ .input-label {
284
+ display: block;
285
+ margin-bottom: 15px;
286
+ color: #a0b0ff;
287
+ font-weight: 500;
288
+ }
289
+
290
+ .answer-input {
291
+ width: 100%;
292
+ background: rgba(255, 255, 255, 0.07);
293
+ border: 2px solid rgba(255, 255, 255, 0.1);
294
+ border-radius: 12px;
295
+ padding: 18px;
296
+ font-size: 1.3em;
297
+ color: white;
298
+ font-family: inherit;
299
+ transition: all 0.3s ease;
300
+ }
301
+
302
+ .answer-input:focus {
303
+ outline: none;
304
+ border-color: #5a6cff;
305
+ background: rgba(255, 255, 255, 0.1);
306
+ box-shadow: 0 0 0 3px rgba(90, 108, 255, 0.2);
307
+ }
308
+
309
+ .action-buttons {
310
+ display: flex;
311
+ gap: 15px;
312
+ margin-top: 20px;
313
+ }
314
+
315
+ .action-btn {
316
+ flex: 1;
317
+ padding: 16px;
318
+ border-radius: 12px;
319
+ border: none;
320
+ font-size: 1.1em;
321
+ font-weight: 600;
322
+ cursor: pointer;
323
+ transition: all 0.3s ease;
324
+ display: flex;
325
+ align-items: center;
326
+ justify-content: center;
327
+ gap: 10px;
328
+ }
329
+
330
+ .action-btn.check {
331
+ background: linear-gradient(135deg, #34d399, #10b981);
332
+ color: white;
333
+ }
334
+
335
+ .action-btn.check:hover {
336
+ background: linear-gradient(135deg, #10b981, #34d399);
337
+ transform: translateY(-2px);
338
+ box-shadow: 0 5px 15px rgba(16, 185, 129, 0.4);
339
+ }
340
+
341
+ .action-btn.next {
342
+ background: linear-gradient(135deg, #5a6cff, #7a8aff);
343
+ color: white;
344
+ }
345
+
346
+ .action-btn.next:hover {
347
+ background: linear-gradient(135deg, #7a8aff, #5a6cff);
348
+ transform: translateY(-2px);
349
+ box-shadow: 0 5px 15px rgba(90, 108, 255, 0.4);
350
+ }
351
+
352
+ .action-btn.hint {
353
+ background: linear-gradient(135deg, #fbbf24, #f59e0b);
354
+ color: white;
355
+ }
356
+
357
+ .action-btn.hint:hover {
358
+ background: linear-gradient(135deg, #f59e0b, #fbbf24);
359
+ transform: translateY(-2px);
360
+ box-shadow: 0 5px 15px rgba(251, 191, 36, 0.4);
361
+ }
362
+
363
+ .feedback-container {
364
+ background: rgba(255, 255, 255, 0.05);
365
+ border-radius: 15px;
366
+ padding: 25px;
367
+ margin-top: 25px;
368
+ }
369
+
370
+ .feedback-title {
371
+ color: #a0b0ff;
372
+ margin-bottom: 15px;
373
+ font-weight: 500;
374
+ }
375
+
376
+ .feedback-content {
377
+ color: #e0e0ff;
378
+ line-height: 1.6;
379
+ font-size: 1.1em;
380
+ }
381
+
382
+ .feedback-content.correct {
383
+ color: #34d399;
384
+ }
385
+
386
+ .feedback-content.incorrect {
387
+ color: #ff5a5a;
388
+ }
389
+
390
+ /* === AI CHAT === */
391
+ .ai-chat {
392
+ width: 350px;
393
+ background: rgba(15, 15, 25, 0.9);
394
+ border-left: 1px solid rgba(255, 255, 255, 0.05);
395
+ display: flex;
396
+ flex-direction: column;
397
+ }
398
+
399
+ .chat-header {
400
+ padding: 25px;
401
+ border-bottom: 1px solid rgba(255, 255, 255, 0.05);
402
+ }
403
+
404
+ .chat-title {
405
+ font-size: 1.2em;
406
+ font-weight: 600;
407
+ color: #5a6cff;
408
+ display: flex;
409
+ align-items: center;
410
+ gap: 10px;
411
+ }
412
+
413
+ .chat-status {
414
+ display: flex;
415
+ align-items: center;
416
+ gap: 8px;
417
+ font-size: 0.9em;
418
+ color: #8892b0;
419
+ margin-top: 5px;
420
+ }
421
+
422
+ .status-indicator {
423
+ width: 8px;
424
+ height: 8px;
425
+ border-radius: 50%;
426
+ background: #00ff9d;
427
+ animation: pulse 2s infinite;
428
+ }
429
+
430
+ @keyframes pulse {
431
+ 0%, 100% { opacity: 1; }
432
+ 50% { opacity: 0.5; }
433
+ }
434
+
435
+ .chat-messages {
436
+ flex: 1;
437
+ padding: 20px;
438
+ overflow-y: auto;
439
+ display: flex;
440
+ flex-direction: column;
441
+ gap: 15px;
442
+ }
443
+
444
+ .message {
445
+ max-width: 85%;
446
+ padding: 12px 16px;
447
+ border-radius: 18px;
448
+ line-height: 1.4;
449
+ animation: messageAppear 0.3s ease;
450
+ }
451
+
452
+ @keyframes messageAppear {
453
+ from {
454
+ opacity: 0;
455
+ transform: translateY(10px);
456
+ }
457
+ to {
458
+ opacity: 1;
459
+ transform: translateY(0);
460
+ }
461
+ }
462
+
463
+ .message-ai {
464
+ align-self: flex-start;
465
+ background: rgba(90, 108, 255, 0.2);
466
+ color: #e0e0ff;
467
+ border: 1px solid rgba(90, 108, 255, 0.3);
468
+ }
469
+
470
+ .message-user {
471
+ align-self: flex-end;
472
+ background: rgba(52, 211, 153, 0.2);
473
+ color: #e0e0ff;
474
+ border: 1px solid rgba(52, 211, 153, 0.3);
475
+ }
476
+
477
+ .typing-indicator {
478
+ display: flex;
479
+ align-items: center;
480
+ gap: 5px;
481
+ padding: 12px 16px;
482
+ background: rgba(255, 255, 255, 0.05);
483
+ border-radius: 18px;
484
+ align-self: flex-start;
485
+ width: 70px;
486
+ }
487
+
488
+ .typing-dot {
489
+ width: 8px;
490
+ height: 8px;
491
+ background: #a0b0ff;
492
+ border-radius: 50%;
493
+ animation: typing 1.4s infinite ease-in-out;
494
+ }
495
+
496
+ .typing-dot:nth-child(1) { animation-delay: -0.32s; }
497
+ .typing-dot:nth-child(2) { animation-delay: -0.16s; }
498
+
499
+ @keyframes typing {
500
+ 0%, 80%, 100% { transform: translateY(0); }
501
+ 40% { transform: translateY(-10px); }
502
+ }
503
+
504
+ .chat-input-container {
505
+ padding: 20px;
506
+ border-top: 1px solid rgba(255, 255, 255, 0.05);
507
+ }
508
+
509
+ .chat-input-wrapper {
510
+ display: flex;
511
+ gap: 10px;
512
+ }
513
+
514
+ .chat-input {
515
+ flex: 1;
516
+ background: rgba(255, 255, 255, 0.07);
517
+ border: 1px solid rgba(255, 255, 255, 0.1);
518
+ border-radius: 12px;
519
+ padding: 12px 16px;
520
+ color: white;
521
+ font-family: inherit;
522
+ resize: none;
523
+ min-height: 50px;
524
+ max-height: 100px;
525
+ }
526
+
527
+ .chat-input:focus {
528
+ outline: none;
529
+ border-color: #5a6cff;
530
+ }
531
+
532
+ .voice-input-btn {
533
+ width: 50px;
534
+ border-radius: 12px;
535
+ background: linear-gradient(135deg, #5a6cff, #7a8aff);
536
+ border: none;
537
+ color: white;
538
+ cursor: pointer;
539
+ display: flex;
540
+ align-items: center;
541
+ justify-content: center;
542
+ transition: all 0.3s ease;
543
+ }
544
+
545
+ .voice-input-btn:hover {
546
+ background: linear-gradient(135deg, #7a8aff, #5a6cff);
547
+ transform: translateY(-2px);
548
+ }
549
+
550
+ .voice-input-btn.listening {
551
+ background: linear-gradient(135deg, #ff5a5a, #ff7a7a);
552
+ animation: pulse 1.5s infinite;
553
+ }
554
+
555
+ /* === LOADING SCREEN === */
556
+ .loading-screen {
557
+ position: fixed;
558
+ top: 0;
559
+ left: 0;
560
+ width: 100%;
561
+ height: 100%;
562
+ background: linear-gradient(135deg, #0a0a0f 0%, #1a1a2e 100%);
563
+ display: flex;
564
+ flex-direction: column;
565
+ justify-content: center;
566
+ align-items: center;
567
+ z-index: 1000;
568
+ }
569
+
570
+ .spinner {
571
+ width: 60px;
572
+ height: 60px;
573
+ border: 3px solid rgba(90, 108, 255, 0.3);
574
+ border-top-color: #5a6cff;
575
+ border-radius: 50%;
576
+ animation: spin 1s linear infinite;
577
+ margin-bottom: 20px;
578
+ }
579
+
580
+ @keyframes spin {
581
+ to { transform: rotate(360deg); }
582
+ }
583
+
584
+ /* === RESPONSIVE === */
585
+ @media (max-width: 1200px) {
586
+ .ai-chat {
587
+ display: none;
588
+ }
589
+ }
590
+
591
+ @media (max-width: 900px) {
592
+ .sidebar {
593
+ width: 280px;
594
+ }
595
+
596
+ .word-display {
597
+ font-size: 3em;
598
+ letter-spacing: 6px;
599
+ }
600
+ }
601
+
602
+ @media (max-width: 768px) {
603
+ .main-interface {
604
+ flex-direction: column;
605
+ }
606
+
607
+ .sidebar {
608
+ width: 100%;
609
+ border-right: none;
610
+ border-bottom: 1px solid rgba(255, 255, 255, 0.05);
611
+ max-height: 200px;
612
+ }
613
+
614
+ .controls-grid {
615
+ grid-template-columns: 1fr;
616
+ }
617
+
618
+ .action-buttons {
619
+ flex-direction: column;
620
+ }
621
+ }
622
+ </style>
623
+ </head>
624
+ <body>
625
+ <!-- 3D Visualization Canvas -->
626
+ <div id="canvasContainer">
627
+ <canvas id="mainCanvas"></canvas>
628
+ </div>
629
+
630
+ <!-- Main Interface -->
631
+ <div class="main-interface">
632
+ <!-- Sidebar -->
633
+ <div class="sidebar">
634
+ <div class="sidebar-header">
635
+ <div class="sidebar-title">
636
+ <i class="fas fa-brain"></i>
637
+ AI Spelling Tutor
638
+ </div>
639
+ <div class="sidebar-subtitle">Adaptive Learning System</div>
640
+ </div>
641
+
642
+ <div class="section">
643
+ <div class="section-title">
644
+ <i class="fas fa-book"></i>
645
+ Difficulty Level
646
+ </div>
647
+ <div class="btn-group">
648
+ <button class="btn active" data-level="beginner">
649
+ <i class="fas fa-seedling"></i>
650
+ Beginner
651
+ </button>
652
+ <button class="btn" data-level="intermediate">
653
+ <i class="fas fa-leaf"></i>
654
+ Intermediate
655
+ </button>
656
+ <button class="btn" data-level="advanced">
657
+ <i class="fas fa-tree"></i>
658
+ Advanced
659
+ </button>
660
+ <button class="btn" data-level="expert">
661
+ <i class="fas fa-mountain"></i>
662
+ Expert
663
+ </button>
664
+ </div>
665
+ </div>
666
+
667
+ <div class="section">
668
+ <div class="section-title">
669
+ <i class="fas fa-gamepad"></i>
670
+ Training Mode
671
+ </div>
672
+ <div class="btn-group">
673
+ <button class="btn active" data-mode="adaptive">
674
+ <i class="fas fa-robot"></i>
675
+ Adaptive AI
676
+ </button>
677
+ <button class="btn" data-mode="practice">
678
+ <i class="fas fa-dumbbell"></i>
679
+ Practice Mode
680
+ </button>
681
+ <button class="btn" data-mode="challenge">
682
+ <i class="fas fa-trophy"></i>
683
+ Challenge Mode
684
+ </button>
685
+ <button class="btn" data-mode="time-trial">
686
+ <i class="fas fa-clock"></i>
687
+ Time Trial
688
+ </button>
689
+ </div>
690
+ </div>
691
+
692
+ <div class="section">
693
+ <div class="section-title">
694
+ <i class="fas fa-chart-line"></i>
695
+ Progress
696
+ </div>
697
+ <div class="progress-container">
698
+ <div class="progress-stats">
699
+ <span>Level 2</span>
700
+ <span>65%</span>
701
+ </div>
702
+ <div class="progress-bar">
703
+ <div class="progress-fill" id="progressFill" style="width: 65%"></div>
704
+ </div>
705
+ <div class="stats-grid">
706
+ <div class="stat-card">
707
+ <div class="stat-value" id="wordsMastered">24</div>
708
+ <div class="stat-label">Words Mastered</div>
709
+ </div>
710
+ <div class="stat-card">
711
+ <div class="stat-value" id="streakCount">5</div>
712
+ <div class="stat-label">Day Streak</div>
713
+ </div>
714
+ </div>
715
+ </div>
716
+ </div>
717
+
718
+ <div class="section">
719
+ <div class="section-title">
720
+ <i class="fas fa-volume-up"></i>
721
+ Voice Settings
722
+ </div>
723
+ <div class="btn-group">
724
+ <button class="btn active" data-voice="en-US-GuyNeural">
725
+ <i class="fas fa-user"></i>
726
+ US Male
727
+ </button>
728
+ <button class="btn" data-voice="en-US-AriaNeural">
729
+ <i class="fas fa-user"></i>
730
+ US Female
731
+ </button>
732
+ <button class="btn" data-voice="en-GB-SoniaNeural">
733
+ <i class="fas fa-user"></i>
734
+ UK Female
735
+ </button>
736
+ </div>
737
+ </div>
738
+
739
+ <button class="btn btn-primary" id="startSession">
740
+ <i class="fas fa-play"></i>
741
+ Start Training Session
742
+ </button>
743
+
744
+ <button class="btn btn-danger" id="resetSession" style="margin-top: 15px;">
745
+ <i class="fas fa-redo"></i>
746
+ Reset Session
747
+ </button>
748
+ </div>
749
+
750
+ <!-- Main Content -->
751
+ <div class="main-content">
752
+ <div class="word-display-container">
753
+ <div class="word-display" id="currentWord">Ready to begin?</div>
754
+ <div class="word-hint" id="wordHint"></div>
755
+ </div>
756
+
757
+ <div class="input-container">
758
+ <label class="input-label">
759
+ <i class="fas fa-keyboard"></i>
760
+ Type your spelling here:
761
+ </label>
762
+ <input type="text" class="answer-input" id="answerInput" placeholder="Type the word you hear...">
763
+
764
+ <div class="action-buttons">
765
+ <button class="action-btn check" id="checkButton">
766
+ <i class="fas fa-check"></i>
767
+ Check Answer
768
+ </button>
769
+ <button class="action-btn hint" id="hintButton">
770
+ <i class="fas fa-lightbulb"></i>
771
+ Get Hint
772
+ </button>
773
+ <button class="action-btn next" id="nextButton" style="display: none;">
774
+ <i class="fas fa-arrow-right"></i>
775
+ Next Word
776
+ </button>
777
+ </div>
778
+ </div>
779
+
780
+ <div class="controls-grid">
781
+ <button class="btn" id="hearButton">
782
+ <i class="fas fa-volume-up"></i>
783
+ Hear Word
784
+ </button>
785
+ <button class="btn" id="spellButton">
786
+ <i class="fas fa-spell-check"></i>
787
+ Spell Out
788
+ </button>
789
+ <button class="btn" id="contextButton">
790
+ <i class="fas fa-comment-alt"></i>
791
+ Context Sentence
792
+ </button>
793
+ <button class="btn" id="repeatButton">
794
+ <i class="fas fa-redo"></i>
795
+ Repeat
796
+ </button>
797
+ </div>
798
+
799
+ <div class="feedback-container">
800
+ <div class="feedback-title">
801
+ <i class="fas fa-comment-dots"></i>
802
+ AI Tutor Feedback
803
+ </div>
804
+ <div class="feedback-content" id="aiFeedback">
805
+ Welcome to AI Spelling Tutor! I'll help you improve your spelling skills through personalized training. Click "Start Training Session" to begin!
806
+ </div>
807
+ </div>
808
+ </div>
809
+
810
+ <!-- AI Chat -->
811
+ <div class="ai-chat">
812
+ <div class="chat-header">
813
+ <div class="chat-title">
814
+ <i class="fas fa-robot"></i>
815
+ AI Tutor
816
+ </div>
817
+ <div class="chat-status">
818
+ <span class="status-indicator"></span>
819
+ <span>Adaptive Learning Active</span>
820
+ </div>
821
+ </div>
822
+
823
+ <div class="chat-messages" id="chatMessages">
824
+ <div class="message message-ai">
825
+ Hello! I'm your AI spelling tutor. I'll adapt to your skill level and help you master spelling through personalized exercises.
826
+ </div>
827
+ <div class="message message-ai">
828
+ Click "Start Training Session" to begin. I'll track your progress and adjust difficulty based on your performance.
829
+ </div>
830
+ <div class="typing-indicator" id="typingIndicator" style="display: none;">
831
+ <div class="typing-dot"></div>
832
+ <div class="typing-dot"></div>
833
+ <div class="typing-dot"></div>
834
+ </div>
835
+ </div>
836
+
837
+ <div class="chat-input-container">
838
+ <div class="chat-input-wrapper">
839
+ <textarea class="chat-input" id="chatInput" placeholder="Ask your AI tutor a question..."></textarea>
840
+ <button class="voice-input-btn" id="voiceButton">
841
+ <i class="fas fa-microphone"></i>
842
+ </button>
843
+ </div>
844
+ </div>
845
+ </div>
846
+ </div>
847
+
848
+ <!-- Loading Screen -->
849
+ <div class="loading-screen" id="loadingScreen">
850
+ <div class="spinner"></div>
851
+ <div id="loadingText">Initializing AI Tutor System...</div>
852
+ </div>
853
+
854
+ <script>
855
+ // ============================================================================
856
+ // CORE AI SPELLING TUTOR SYSTEM
857
+ // ============================================================================
858
+
859
+ class AISpellingTutor {
860
+ constructor() {
861
+ this.initializeState();
862
+ this.initialize3D();
863
+ this.setupEventListeners();
864
+ this.hideLoading();
865
+ }
866
+
867
+ initializeState() {
868
+ // Core training state
869
+ this.state = {
870
+ sessionActive: false,
871
+ currentWord: null,
872
+ currentWordIndex: 0,
873
+ attempts: 0,
874
+ hintsUsed: 0,
875
+ isCorrect: false,
876
+ showNextButton: false,
877
+
878
+ // Adaptive learning metrics
879
+ difficulty: 'beginner',
880
+ trainingMode: 'adaptive',
881
+ currentVoice: 'en-US-GuyNeural',
882
+
883
+ // Progress tracking
884
+ wordsMastered: 24,
885
+ currentStreak: 5,
886
+ accuracy: 85,
887
+ levelProgress: 65,
888
+
889
+ // Word banks by difficulty
890
+ wordLists: {
891
+ beginner: [
892
+ { word: "cat", context: "The small ___ purred softly.", phonetic: "/kæt/" },
893
+ { word: "dog", context: "The loyal ___ wagged its tail.", phonetic: "/dɒɡ/" },
894
+ { word: "house", context: "We live in a big red ___.", phonetic: "/haʊs/" },
895
+ { word: "book", context: "She read an interesting ___.", phonetic: "/bʊk/" },
896
+ { word: "friend", context: "My best ___ is coming over.", phonetic: "/frɛnd/" },
897
+ { word: "water", context: "I drink eight glasses of ___ daily.", phonetic: "/ˈwɔːtər/" },
898
+ { word: "happy", context: "She felt very ___ today.", phonetic: "/ˈhæpi/" },
899
+ { word: "school", context: "Children learn at ___.", phonetic: "/skuːl/" }
900
+ ],
901
+ intermediate: [
902
+ { word: "beautiful", context: "The sunset was incredibly ___.", phonetic: "/ˈbjuːtɪfʊl/" },
903
+ { word: "chocolate", context: "She loves dark ___.", phonetic: "/ˈtʃɒklət/" },
904
+ { word: "mountain", context: "We climbed the high ___.", phonetic: "/ˈmaʊntɪn/" },
905
+ { word: "language", context: "English is a global ___.", phonetic: "/ˈlæŋɡwɪdʒ/" },
906
+ { word: "calendar", context: "Check the ___ for dates.", phonetic: "/ˈkælɪndər/" },
907
+ { word: "restaurant", context: "We dined at a fancy ___.", phonetic: "/ˈrɛstrɒnt/" },
908
+ { word: "environment", context: "Protect the natural ___.", phonetic: "/ɪnˈvaɪrənmənt/" },
909
+ { word: "temperature", context: "The ___ is rising today.", phonetic: "/ˈtɛmprətʃər/" }
910
+ ],
911
+ advanced: [
912
+ { word: "pneumonia", context: "He was hospitalized with ___.", phonetic: "/njuːˈmoʊniə/" },
913
+ { word: "xylophone", context: "She played the ___ beautifully.", phonetic: "/ˈzaɪləfoʊn/" },
914
+ { word: "bouquet", context: "He brought her a ___ of roses.", phonetic: "/buːˈkeɪ/" },
915
+ { word: "mnemonic", context: "A ___ helps with memory.", phonetic: "/nɪˈmɒnɪk/" },
916
+ { word: "chrysanthemum", context: "The ___ bloomed in autumn.", phonetic: "/krɪˈsænθəməm/" },
917
+ { word: "psychology", context: "She studies ___.", phonetic: "/saɪˈkɒlədʒi/" },
918
+ { word: "rendezvous", context: "Their ___ was at sunset.", phonetic: "/ˈrɒndeɪvuː/" },
919
+ { word: "entrepreneur", context: "The ___ started a business.", phonetic: "/ˌɒntrəprəˈnɜːr/" }
920
+ ],
921
+ expert: [
922
+ { word: "onomatopoeia", context: "Buzz is an example of ___.", phonetic: "/ˌɒnəˌmætəˈpiːə/" },
923
+ { word: "synecdoche", context: "All hands on deck is a ___.", phonetic: "/sɪˈnɛkdəki/" },
924
+ { word: "antediluvian", context: "The artifact was ___.", phonetic: "/ˌæntɪdɪˈluːviən/" },
925
+ { word: "sesquipedalian", context: "He used ___ words.", phonetic: "/ˌsɛskwɪpɪˈdeɪliən/" },
926
+ { word: "perspicacious", context: "Her insights were ___.", phonetic: "/ˌpɜːspɪˈkeɪʃəs/" },
927
+ { word: "serendipity", context: "Finding the book was pure ___.", phonetic: "/ˌsɛrənˈdɪpɪti/" },
928
+ { word: "philanthropist", context: "The ___ donated millions.", phonetic: "/fɪˈlænθrəpɪst/" },
929
+ { word: "antidisestablishmentarianism", context: "He studied ___ movements.", phonetic: "/ˌæntidɪsəˌstæblɪʃmənˈtɛəriənɪzəm/" }
930
+ ]
931
+ },
932
+
933
+ // Current word list based on difficulty
934
+ currentList: [],
935
+
936
+ // Performance tracking
937
+ sessionStats: {
938
+ correct: 0,
939
+ incorrect: 0,
940
+ totalAttempts: 0,
941
+ totalHints: 0,
942
+ startTime: null,
943
+ sessionDuration: 0
944
+ }
945
+ };
946
+
947
+ // Speech synthesis
948
+ this.synth = window.speechSynthesis;
949
+ this.voices = [];
950
+ this.currentUtterance = null;
951
+
952
+ // Initialize voices
953
+ this.initializeVoices();
954
+ }
955
+
956
+ initializeVoices() {
957
+ const loadVoices = () => {
958
+ this.voices = this.synth.getVoices();
959
+ console.log('Voices loaded:', this.voices.length);
960
+ };
961
+
962
+ if (this.synth.onvoiceschanged !== undefined) {
963
+ this.synth.onvoiceschanged = loadVoices;
964
+ }
965
+
966
+ if (this.synth.getVoices().length > 0) {
967
+ loadVoices();
968
+ }
969
+ }
970
+
971
+ async initialize3D() {
972
+ try {
973
+ // Check if Three.js is available
974
+ if (typeof THREE === 'undefined') {
975
+ console.log('Three.js not available, skipping 3D');
976
+ return;
977
+ }
978
+
979
+ // Create scene
980
+ this.scene = new THREE.Scene();
981
+ this.scene.background = new THREE.Color(0x0a0a0f);
982
+
983
+ // Create camera
984
+ this.camera = new THREE.PerspectiveCamera(
985
+ 75,
986
+ window.innerWidth / window.innerHeight,
987
+ 0.1,
988
+ 1000
989
+ );
990
+ this.camera.position.z = 5;
991
+
992
+ // Create renderer
993
+ const canvas = document.getElementById('mainCanvas');
994
+ this.renderer = new THREE.WebGLRenderer({
995
+ canvas: canvas,
996
+ antialias: true,
997
+ alpha: true
998
+ });
999
+ this.renderer.setSize(window.innerWidth, window.innerHeight);
1000
+ this.renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2));
1001
+
1002
+ // Add lights
1003
+ const ambientLight = new THREE.AmbientLight(0x222244, 0.5);
1004
+ this.scene.add(ambientLight);
1005
+
1006
+ const directionalLight = new THREE.DirectionalLight(0x5a6cff, 1);
1007
+ directionalLight.position.set(5, 3, 5);
1008
+ this.scene.add(directionalLight);
1009
+
1010
+ // Add particles
1011
+ this.createParticles();
1012
+
1013
+ // Start animation loop
1014
+ this.animate();
1015
+
1016
+ // Handle window resize
1017
+ window.addEventListener('resize', () => this.onWindowResize());
1018
+
1019
+ console.log('3D scene initialized');
1020
+ } catch (error) {
1021
+ console.error('3D initialization error:', error);
1022
+ }
1023
+ }
1024
+
1025
+ createParticles() {
1026
+ const particleCount = 1000;
1027
+ const geometry = new THREE.BufferGeometry();
1028
+ const positions = new Float32Array(particleCount * 3);
1029
+
1030
+ for (let i = 0; i < particleCount; i++) {
1031
+ const i3 = i * 3;
1032
+ positions[i3] = (Math.random() - 0.5) * 10;
1033
+ positions[i3 + 1] = (Math.random() - 0.5) * 10;
1034
+ positions[i3 + 2] = (Math.random() - 0.5) * 10;
1035
+ }
1036
+
1037
+ geometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));
1038
+
1039
+ const material = new THREE.PointsMaterial({
1040
+ size: 0.05,
1041
+ color: 0x5a6cff,
1042
+ transparent: true,
1043
+ opacity: 0.6,
1044
+ blending: THREE.AdditiveBlending
1045
+ });
1046
+
1047
+ this.particles = new THREE.Points(geometry, material);
1048
+ this.scene.add(this.particles);
1049
+
1050
+ // Add central sphere
1051
+ const sphereGeometry = new THREE.SphereGeometry(1, 32, 32);
1052
+ const sphereMaterial = new THREE.MeshBasicMaterial({
1053
+ color: 0x5a6cff,
1054
+ wireframe: true,
1055
+ transparent: true,
1056
+ opacity: 0.1
1057
+ });
1058
+ this.sphere = new THREE.Mesh(sphereGeometry, sphereMaterial);
1059
+ this.scene.add(this.sphere);
1060
+ }
1061
+
1062
+ animate() {
1063
+ requestAnimationFrame(() => this.animate());
1064
+
1065
+ if (this.particles) {
1066
+ this.particles.rotation.y += 0.001;
1067
+ this.particles.rotation.x += 0.0005;
1068
+
1069
+ // Pulsing effect
1070
+ const time = Date.now() * 0.001;
1071
+ const scale = 1 + Math.sin(time) * 0.1;
1072
+ this.particles.scale.set(scale, scale, scale);
1073
+ }
1074
+
1075
+ if (this.sphere) {
1076
+ this.sphere.rotation.y += 0.002;
1077
+ }
1078
+
1079
+ if (this.renderer && this.scene && this.camera) {
1080
+ this.renderer.render(this.scene, this.camera);
1081
+ }
1082
+ }
1083
+
1084
+ onWindowResize() {
1085
+ if (this.camera && this.renderer) {
1086
+ this.camera.aspect = window.innerWidth / window.innerHeight;
1087
+ this.camera.updateProjectionMatrix();
1088
+ this.renderer.setSize(window.innerWidth, window.innerHeight);
1089
+ }
1090
+ }
1091
+
1092
+ setupEventListeners() {
1093
+ // Start session button
1094
+ document.getElementById('startSession').addEventListener('click', () => this.startSession());
1095
+
1096
+ // Reset session button
1097
+ document.getElementById('resetSession').addEventListener('click', () => this.resetSession());
1098
+
1099
+ // Check answer button
1100
+ document.getElementById('checkButton').addEventListener('click', () => this.checkAnswer());
1101
+
1102
+ // Next word button
1103
+ document.getElementById('nextButton').addEventListener('click', () => this.nextWord());
1104
+
1105
+ // Hint button
1106
+ document.getElementById('hintButton').addEventListener('click', () => this.giveHint());
1107
+
1108
+ // Audio buttons
1109
+ document.getElementById('hearButton').addEventListener('click', () => this.speakWord());
1110
+ document.getElementById('spellButton').addEventListener('click', () => this.spellWord());
1111
+ document.getElementById('contextButton').addEventListener('click', () => this.speakContext());
1112
+ document.getElementById('repeatButton').addEventListener('click', () => this.repeatWord());
1113
+
1114
+ // Answer input - handle Enter key
1115
+ document.getElementById('answerInput').addEventListener('keypress', (e) => {
1116
+ if (e.key === 'Enter') {
1117
+ this.checkAnswer();
1118
+ }
1119
+ });
1120
+
1121
+ // Difficulty buttons
1122
+ document.querySelectorAll('[data-level]').forEach(btn => {
1123
+ btn.addEventListener('click', (e) => {
1124
+ this.setDifficulty(e.target.dataset.level);
1125
+ });
1126
+ });
1127
+
1128
+ // Training mode buttons
1129
+ document.querySelectorAll('[data-mode]').forEach(btn => {
1130
+ btn.addEventListener('click', (e) => {
1131
+ this.setTrainingMode(e.target.dataset.mode);
1132
+ });
1133
+ });
1134
+
1135
+ // Voice buttons
1136
+ document.querySelectorAll('[data-voice]').forEach(btn => {
1137
+ btn.addEventListener('click', (e) => {
1138
+ this.setVoice(e.target.dataset.voice);
1139
+ });
1140
+ });
1141
+
1142
+ // Chat input
1143
+ document.getElementById('chatInput').addEventListener('keypress', (e) => {
1144
+ if (e.key === 'Enter' && !e.shiftKey) {
1145
+ e.preventDefault();
1146
+ this.sendChatMessage();
1147
+ }
1148
+ });
1149
+
1150
+ // Voice input button
1151
+ document.getElementById('voiceButton').addEventListener('click', () => this.toggleVoiceInput());
1152
+ }
1153
+
1154
+ hideLoading() {
1155
+ setTimeout(() => {
1156
+ document.getElementById('loadingScreen').style.opacity = '0';
1157
+ setTimeout(() => {
1158
+ document.getElementById('loadingScreen').style.display = 'none';
1159
+ }, 500);
1160
+ }, 1500);
1161
+ }
1162
+
1163
+ // ============================================================================
1164
+ // SESSION MANAGEMENT
1165
+ // ============================================================================
1166
+
1167
+ startSession() {
1168
+ this.state.sessionActive = true;
1169
+ this.state.sessionStats.startTime = Date.now();
1170
+ this.state.currentWordIndex = 0;
1171
+ this.state.currentList = [...this.state.wordLists[this.state.difficulty]];
1172
+
1173
+ // Shuffle the list for practice
1174
+ if (this.state.trainingMode === 'practice' || this.state.trainingMode === 'challenge') {
1175
+ this.shuffleArray(this.state.currentList);
1176
+ }
1177
+
1178
+ // Reset session stats
1179
+ this.state.sessionStats = {
1180
+ correct: 0,
1181
+ incorrect: 0,
1182
+ totalAttempts: 0,
1183
+ totalHints: 0,
1184
+ startTime: Date.now(),
1185
+ sessionDuration: 0
1186
+ };
1187
+
1188
+ // Update UI
1189
+ document.getElementById('startSession').disabled = true;
1190
+ document.getElementById('startSession').innerHTML = '<i class="fas fa-spinner fa-spin"></i> Session Active';
1191
+
1192
+ // Get first word
1193
+ this.getNewWord();
1194
+
1195
+ // Add AI chat message
1196
+ this.addAIMessage(`Starting ${this.state.difficulty} level spelling session! I'll adapt to your performance.`);
1197
+ this.showTypingIndicator();
1198
+ setTimeout(() => {
1199
+ this.hideTypingIndicator();
1200
+ this.addAIMessage(`First word: "${this.state.currentWord.word}". Listen carefully and type what you hear.`);
1201
+ }, 1500);
1202
+ }
1203
+
1204
+ resetSession() {
1205
+ if (confirm('Are you sure you want to reset the current session?')) {
1206
+ this.state.sessionActive = false;
1207
+ this.state.currentWord = null;
1208
+ this.state.currentWordIndex = 0;
1209
+ this.state.attempts = 0;
1210
+ this.state.hintsUsed = 0;
1211
+ this.state.isCorrect = false;
1212
+ this.state.showNextButton = false;
1213
+
1214
+ // Reset UI
1215
+ document.getElementById('currentWord').textContent = 'Ready to begin?';
1216
+ document.getElementById('currentWord').className = 'word-display';
1217
+ document.getElementById('wordHint').textContent = '';
1218
+ document.getElementById('answerInput').value = '';
1219
+ document.getElementById('aiFeedback').textContent = 'Session reset. Click "Start Training Session" to begin!';
1220
+ document.getElementById('aiFeedback').className = 'feedback-content';
1221
+ document.getElementById('nextButton').style.display = 'none';
1222
+ document.getElementById('checkButton').style.display = 'flex';
1223
+ document.getElementById('hintButton').style.display = 'flex';
1224
+
1225
+ document.getElementById('startSession').disabled = false;
1226
+ document.getElementById('startSession').innerHTML = '<i class="fas fa-play"></i> Start Training Session';
1227
+
1228
+ // Clear chat messages
1229
+ document.getElementById('chatMessages').innerHTML = `
1230
+ <div class="message message-ai">
1231
+ Hello! I'm your AI spelling tutor. I'll adapt to your skill level and help you master spelling through personalized exercises.
1232
+ </div>
1233
+ <div class="message message-ai">
1234
+ Click "Start Training Session" to begin. I'll track your progress and adjust difficulty based on your performance.
1235
+ </div>
1236
+ <div class="typing-indicator" id="typingIndicator" style="display: none;">
1237
+ <div class="typing-dot"></div>
1238
+ <div class="typing-dot"></div>
1239
+ <div class="typing-dot"></div>
1240
+ </div>
1241
+ `;
1242
+
1243
+ this.addAIMessage('Session reset. Ready for a new challenge?');
1244
+ }
1245
+ }
1246
+
1247
+ getNewWord() {
1248
+ if (this.state.currentWordIndex < this.state.currentList.length) {
1249
+ this.state.currentWord = this.state.currentList[this.state.currentWordIndex];
1250
+ this.state.attempts = 0;
1251
+ this.state.hintsUsed = 0;
1252
+ this.state.isCorrect = false;
1253
+ this.state.showNextButton = false;
1254
+
1255
+ // Update UI
1256
+ document.getElementById('currentWord').textContent = '_'.repeat(this.state.currentWord.word.length);
1257
+ document.getElementById('currentWord').className = 'word-display';
1258
+ document.getElementById('wordHint').textContent = '';
1259
+ document.getElementById('answerInput').value = '';
1260
+ document.getElementById('answerInput').focus();
1261
+ document.getElementById('nextButton').style.display = 'none';
1262
+ document.getElementById('checkButton').style.display = 'flex';
1263
+ document.getElementById('hintButton').style.display = 'flex';
1264
+
1265
+ // Speak the word
1266
+ setTimeout(() => this.speakWord(), 500);
1267
+
1268
+ // Update feedback
1269
+ document.getElementById('aiFeedback').textContent = `New word! Listen carefully and spell it correctly. Difficulty: ${this.state.difficulty}`;
1270
+
1271
+ return true;
1272
+ } else {
1273
+ this.endSession();
1274
+ return false;
1275
+ }
1276
+ }
1277
+
1278
+ nextWord() {
1279
+ this.state.currentWordIndex++;
1280
+ this.getNewWord();
1281
+ }
1282
+
1283
+ endSession() {
1284
+ this.state.sessionActive = false;
1285
+ this.state.sessionStats.sessionDuration = Date.now() - this.state.sessionStats.startTime;
1286
+
1287
+ const accuracy = this.state.sessionStats.totalAttempts > 0
1288
+ ? Math.round((this.state.sessionStats.correct / this.state.sessionStats.totalAttempts) * 100)
1289
+ : 0;
1290
+
1291
+ // Update progress
1292
+ if (accuracy > 80) {
1293
+ this.state.levelProgress = Math.min(100, this.state.levelProgress + 10);
1294
+ document.getElementById('progressFill').style.width = `${this.state.levelProgress}%`;
1295
+ }
1296
+
1297
+ // Update UI
1298
+ document.getElementById('currentWord').textContent = 'Session Complete!';
1299
+ document.getElementById('wordHint').textContent = `Accuracy: ${accuracy}% | Words: ${this.state.sessionStats.correct}`;
1300
+ document.getElementById('answerInput').value = '';
1301
+ document.getElementById('aiFeedback').textContent = `Great job! You completed the session with ${accuracy}% accuracy. Ready for another challenge?`;
1302
+ document.getElementById('nextButton').style.display = 'none';
1303
+
1304
+ document.getElementById('startSession').disabled = false;
1305
+ document.getElementById('startSession').innerHTML = '<i class="fas fa-play"></i> Start Training Session';
1306
+
1307
+ // Add AI message
1308
+ this.addAIMessage(`Session completed! You got ${this.state.sessionStats.correct} words correct with ${accuracy}% accuracy.`);
1309
+
1310
+ // Update stats
1311
+ this.updateStats();
1312
+ }
1313
+
1314
+ // ============================================================================
1315
+ // SPELLING LOGIC
1316
+ // ============================================================================
1317
+
1318
+ checkAnswer() {
1319
+ const userInput = document.getElementById('answerInput').value.trim();
1320
+ if (!userInput) return;
1321
+
1322
+ this.state.attempts++;
1323
+ this.state.sessionStats.totalAttempts++;
1324
+
1325
+ const isCorrect = userInput.toLowerCase() === this.state.currentWord.word.toLowerCase();
1326
+
1327
+ if (isCorrect) {
1328
+ this.handleCorrectAnswer();
1329
+ } else {
1330
+ this.handleIncorrectAnswer(userInput);
1331
+ }
1332
+ }
1333
+
1334
+ handleCorrectAnswer() {
1335
+ this.state.isCorrect = true;
1336
+ this.state.showNextButton = true;
1337
+ this.state.sessionStats.correct++;
1338
+ this.state.wordsMastered++;
1339
+
1340
+ // Update UI
1341
+ document.getElementById('currentWord').textContent = this.state.currentWord.word;
1342
+ document.getElementById('currentWord').className = 'word-display correct';
1343
+ document.getElementById('answerInput').value = '';
1344
+ document.getElementById('nextButton').style.display = 'flex';
1345
+ document.getElementById('checkButton').style.display = 'none';
1346
+ document.getElementById('hintButton').style.display = 'none';
1347
+
1348
+ // Calculate points
1349
+ const basePoints = 10;
1350
+ const hintPenalty = this.state.hintsUsed * 2;
1351
+ const attemptPenalty = Math.max(0, this.state.attempts - 1) * 3;
1352
+ const pointsEarned = Math.max(1, basePoints - hintPenalty - attemptPenalty);
1353
+
1354
+ // Update feedback
1355
+ document.getElementById('aiFeedback').textContent = `✅ Excellent! "${this.state.currentWord.word}" is correct! `;
1356
+ document.getElementById('aiFeedback').className = 'feedback-content correct';
1357
+
1358
+ if (this.state.attempts === 1 && this.state.hintsUsed === 0) {
1359
+ document.getElementById('aiFeedback').textContent += `Perfect first try! +${pointsEarned} points!`;
1360
+ } else {
1361
+ document.getElementById('aiFeedback').textContent += `You used ${this.state.hintsUsed} hint(s) and ${this.state.attempts} attempt(s). +${pointsEarned} points!`;
1362
+ }
1363
+
1364
+ // Add AI chat message
1365
+ this.addAIMessage(`Correct! "${this.state.currentWord.word}" is spelled correctly. Great job!`);
1366
+
1367
+ // Play success sound
1368
+ this.playSuccessSound();
1369
+
1370
+ // Update stats
1371
+ this.updateStats();
1372
+
1373
+ // Adaptive learning: adjust difficulty based on performance
1374
+ if (this.state.attempts === 1 && this.state.hintsUsed === 0) {
1375
+ this.considerDifficultyIncrease();
1376
+ }
1377
+ }
1378
+
1379
+ handleIncorrectAnswer(userInput) {
1380
+ this.state.sessionStats.incorrect++;
1381
+
1382
+ // Show incorrect feedback
1383
+ document.getElementById('currentWord').className = 'word-display incorrect';
1384
+ document.getElementById('aiFeedback').textContent = `❌ Not quite. "${userInput}" is incorrect. Try again!`;
1385
+ document.getElementById('aiFeedback').className = 'feedback-content incorrect';
1386
+
1387
+ // Add AI chat message
1388
+ this.addAIMessage(`Incorrect attempt for "${this.state.currentWord.word}". Try again or ask for a hint!`);
1389
+
1390
+ // Give progressive hints
1391
+ if (this.state.attempts === 2) {
1392
+ this.giveHint();
1393
+ } else if (this.state.attempts === 3) {
1394
+ this.revealFirstLetter();
1395
+ }
1396
+
1397
+ // Adaptive learning: consider difficulty decrease if struggling
1398
+ if (this.state.attempts >= 3) {
1399
+ this.considerDifficultyDecrease();
1400
+ }
1401
+ }
1402
+
1403
+ giveHint() {
1404
+ if (!this.state.currentWord || this.state.isCorrect) return;
1405
+
1406
+ this.state.hintsUsed++;
1407
+ this.state.sessionStats.totalHints++;
1408
+
1409
+ // Show phonetic hint
1410
+ if (this.state.hintsUsed === 1) {
1411
+ document.getElementById('wordHint').textContent = `Phonetic: ${this.state.currentWord.phonetic}`;
1412
+ this.addAIMessage(`Hint: The word sounds like "${this.state.currentWord.phonetic}"`);
1413
+ }
1414
+ // Show context hint
1415
+ else if (this.state.hintsUsed === 2) {
1416
+ document.getElementById('wordHint').textContent += ` | Context: ${this.state.currentWord.context}`;
1417
+ this.addAIMessage(`Context: ${this.state.currentWord.context}`);
1418
+ }
1419
+ // Show first letter
1420
+ else if (this.state.hintsUsed === 3) {
1421
+ this.revealFirstLetter();
1422
+ }
1423
+ }
1424
+
1425
+ revealFirstLetter() {
1426
+ if (!this.state.currentWord) return;
1427
+
1428
+ const word = this.state.currentWord.word;
1429
+ const displayed = document.getElementById('currentWord').textContent;
1430
+ const firstLetter = word[0];
1431
+
1432
+ // Update display to show first letter
1433
+ let newDisplay = firstLetter;
1434
+ for (let i = 1; i < word.length; i++) {
1435
+ newDisplay += displayed[i] === '_' ? '_' : displayed[i];
1436
+ }
1437
+
1438
+ document.getElementById('currentWord').textContent = newDisplay;
1439
+ this.addAIMessage(`First letter revealed: "${firstLetter}"`);
1440
+ }
1441
+
1442
+ // ============================================================================
1443
+ // SPEECH SYNTHESIS
1444
+ // ============================================================================
1445
+
1446
+ speakText(text, rate = 1.0, pitch = 1.0) {
1447
+ if (!this.synth) return;
1448
+
1449
+ // Stop any current speech
1450
+ this.synth.cancel();
1451
+
1452
+ const utterance = new SpeechSynthesisUtterance(text);
1453
+
1454
+ // Try to find the selected voice
1455
+ if (this.voices.length > 0) {
1456
+ const selectedVoice = this.voices.find(voice =>
1457
+ voice.name.includes(this.state.currentVoice) ||
1458
+ voice.lang.includes(this.state.currentVoice.split('-').slice(0, 2).join('-'))
1459
+ );
1460
+
1461
+ if (selectedVoice) {
1462
+ utterance.voice = selectedVoice;
1463
+ }
1464
+ }
1465
+
1466
+ utterance.rate = rate;
1467
+ utterance.pitch = pitch;
1468
+ utterance.volume = 1.0;
1469
+
1470
+ this.currentUtterance = utterance;
1471
+ this.synth.speak(utterance);
1472
+ }
1473
+
1474
+ speakWord() {
1475
+ if (!this.state.currentWord) return;
1476
+
1477
+ this.speakText(this.state.currentWord.word, 0.8, 1.0);
1478
+
1479
+ // Add visual feedback
1480
+ const wordDisplay = document.getElementById('currentWord');
1481
+ const originalText = wordDisplay.textContent;
1482
+ wordDisplay.style.color = '#5a6cff';
1483
+ setTimeout(() => {
1484
+ wordDisplay.style.color = '';
1485
+ }, 1000);
1486
+ }
1487
+
1488
+ spellWord() {
1489
+ if (!this.state.currentWord) return;
1490
+
1491
+ const word = this.state.currentWord.word.toUpperCase();
1492
+ const letters = word.split('');
1493
+ const spelled = letters.join('. ') + '.';
1494
+
1495
+ this.speakText(spelled, 0.5, 1.1);
1496
+
1497
+ // Visual spelling display
1498
+ let display = '';
1499
+ let i = 0;
1500
+
1501
+ const spellInterval = setInterval(() => {
1502
+ if (i < word.length) {
1503
+ display = word.substring(0, i + 1) + '_'.repeat(word.length - i - 1);
1504
+ document.getElementById('currentWord').textContent = display;
1505
+ i++;
1506
+ } else {
1507
+ clearInterval(spellInterval);
1508
+ setTimeout(() => {
1509
+ document.getElementById('currentWord').textContent = '_'.repeat(word.length);
1510
+ }, 1000);
1511
+ }
1512
+ }, 500);
1513
+ }
1514
+
1515
+ speakContext() {
1516
+ if (!this.state.currentWord || !this.state.currentWord.context) return;
1517
+
1518
+ this.speakText(this.state.currentWord.context, 0.9, 1.0);
1519
+
1520
+ // Highlight context in feedback
1521
+ document.getElementById('aiFeedback').textContent = `Context: ${this.state.currentWord.context}`;
1522
+ setTimeout(() => {
1523
+ if (!this.state.isCorrect) {
1524
+ document.getElementById('aiFeedback').textContent = 'Try spelling the word from the context clue!';
1525
+ }
1526
+ }, 3000);
1527
+ }
1528
+
1529
+ repeatWord() {
1530
+ this.speakWord();
1531
+ }
1532
+
1533
+ playSuccessSound() {
1534
+ // Create a simple success tone using Web Audio API
1535
+ try {
1536
+ const audioContext = new (window.AudioContext || window.webkitAudioContext)();
1537
+ const oscillator = audioContext.createOscillator();
1538
+ const gainNode = audioContext.createGain();
1539
+
1540
+ oscillator.connect(gainNode);
1541
+ gainNode.connect(audioContext.destination);
1542
+
1543
+ oscillator.frequency.setValueAtTime(523.25, audioContext.currentTime); // C5
1544
+ oscillator.frequency.setValueAtTime(659.25, audioContext.currentTime + 0.1); // E5
1545
+ oscillator.frequency.setValueAtTime(783.99, audioContext.currentTime + 0.2); // G5
1546
+
1547
+ gainNode.gain.setValueAtTime(0.3, audioContext.currentTime);
1548
+ gainNode.gain.exponentialRampToValueAtTime(0.01, audioContext.currentTime + 0.5);
1549
+
1550
+ oscillator.start(audioContext.currentTime);
1551
+ oscillator.stop(audioContext.currentTime + 0.5);
1552
+ } catch (e) {
1553
+ console.log('Web Audio API not supported');
1554
+ }
1555
+ }
1556
+
1557
+ // ============================================================================
1558
+ // ADAPTIVE LEARNING AI
1559
+ // ============================================================================
1560
+
1561
+ considerDifficultyIncrease() {
1562
+ // Check if user has perfect streak
1563
+ const perfectStreak = this.getPerfectStreak();
1564
+
1565
+ if (perfectStreak >= 3) {
1566
+ const currentLevel = this.state.difficulty;
1567
+ const nextLevel = this.getNextDifficultyLevel(currentLevel);
1568
+
1569
+ if (nextLevel) {
1570
+ this.addAIMessage(`🎯 Perfect streak detected! Advancing to ${nextLevel} level for next session.`);
1571
+ this.state.difficulty = nextLevel;
1572
+
1573
+ // Update UI
1574
+ document.querySelectorAll('[data-level]').forEach(btn => {
1575
+ btn.classList.toggle('active', btn.dataset.level === nextLevel);
1576
+ });
1577
+ }
1578
+ }
1579
+ }
1580
+
1581
+ considerDifficultyDecrease() {
1582
+ // Check if user is struggling
1583
+ const recentAccuracy = this.getRecentAccuracy();
1584
+
1585
+ if (recentAccuracy < 50) {
1586
+ const currentLevel = this.state.difficulty;
1587
+ const prevLevel = this.getPreviousDifficultyLevel(currentLevel);
1588
+
1589
+ if (prevLevel) {
1590
+ this.addAIMessage(`I notice you're finding this challenging. Let's try ${prevLevel} level for better learning.`);
1591
+ this.state.difficulty = prevLevel;
1592
+
1593
+ // Update UI
1594
+ document.querySelectorAll('[data-level]').forEach(btn => {
1595
+ btn.classList.toggle('active', btn.dataset.level === prevLevel);
1596
+ });
1597
+ }
1598
+ }
1599
+ }
1600
+
1601
+ getPerfectStreak() {
1602
+ // Simplified - in real implementation, track actual streak
1603
+ return this.state.sessionStats.correct;
1604
+ }
1605
+
1606
+ getRecentAccuracy() {
1607
+ if (this.state.sessionStats.totalAttempts === 0) return 100;
1608
+ return (this.state.sessionStats.correct / this.state.sessionStats.totalAttempts) * 100;
1609
+ }
1610
+
1611
+ getNextDifficultyLevel(current) {
1612
+ const levels = ['beginner', 'intermediate', 'advanced', 'expert'];
1613
+ const currentIndex = levels.indexOf(current);
1614
+ return currentIndex < levels.length - 1 ? levels[currentIndex + 1] : null;
1615
+ }
1616
+
1617
+ getPreviousDifficultyLevel(current) {
1618
+ const levels = ['beginner', 'intermediate', 'advanced', 'expert'];
1619
+ const currentIndex = levels.indexOf(current);
1620
+ return currentIndex > 0 ? levels[currentIndex - 1] : null;
1621
+ }
1622
+
1623
+ // ============================================================================
1624
+ // CHAT AI FUNCTIONALITY
1625
+ // ============================================================================
1626
+
1627
+ addAIMessage(text) {
1628
+ const chatMessages = document.getElementById('chatMessages');
1629
+ const typingIndicator = document.getElementById('typingIndicator');
1630
+
1631
+ if (typingIndicator.style.display !== 'none') {
1632
+ typingIndicator.style.display = 'none';
1633
+ }
1634
+
1635
+ const messageDiv = document.createElement('div');
1636
+ messageDiv.className = 'message message-ai';
1637
+ messageDiv.textContent = text;
1638
+
1639
+ chatMessages.appendChild(messageDiv);
1640
+ chatMessages.scrollTop = chatMessages.scrollHeight;
1641
+ }
1642
+
1643
+ addUserMessage(text) {
1644
+ const chatMessages = document.getElementById('chatMessages');
1645
+ const typingIndicator = document.getElementById('typingIndicator');
1646
+
1647
+ if (typingIndicator.style.display !== 'none') {
1648
+ typingIndicator.style.display = 'none';
1649
+ }
1650
+
1651
+ const messageDiv = document.createElement('div');
1652
+ messageDiv.className = 'message message-user';
1653
+ messageDiv.textContent = text;
1654
+
1655
+ chatMessages.appendChild(messageDiv);
1656
+ chatMessages.scrollTop = chatMessages.scrollHeight;
1657
+ }
1658
+
1659
+ showTypingIndicator() {
1660
+ const typingIndicator = document.getElementById('typingIndicator');
1661
+ typingIndicator.style.display = 'flex';
1662
+
1663
+ const chatMessages = document.getElementById('chatMessages');
1664
+ chatMessages.scrollTop = chatMessages.scrollHeight;
1665
+ }
1666
+
1667
+ hideTypingIndicator() {
1668
+ const typingIndicator = document.getElementById('typingIndicator');
1669
+ typingIndicator.style.display = 'none';
1670
+ }
1671
+
1672
+ sendChatMessage() {
1673
+ const chatInput = document.getElementById('chatInput');
1674
+ const message = chatInput.value.trim();
1675
+
1676
+ if (!message) return;
1677
+
1678
+ // Add user message
1679
+ this.addUserMessage(message);
1680
+
1681
+ // Clear input
1682
+ chatInput.value = '';
1683
+
1684
+ // Show typing indicator
1685
+ this.showTypingIndicator();
1686
+
1687
+ // AI response with delay
1688
+ setTimeout(() => {
1689
+ this.hideTypingIndicator();
1690
+ this.generateAIResponse(message);
1691
+ }, 1000 + Math.random() * 1000);
1692
+ }
1693
+
1694
+ generateAIResponse(userMessage) {
1695
+ const lowerMessage = userMessage.toLowerCase();
1696
+ let response = '';
1697
+
1698
+ // Simple AI response logic - in production, connect to actual AI API
1699
+ if (lowerMessage.includes('help') || lowerMessage.includes('how')) {
1700
+ response = "I'm here to help you improve your spelling! Listen to the word, type it correctly, and I'll give you feedback. Use hints if you need help!";
1701
+ } else if (lowerMessage.includes('difficulty') || lowerMessage.includes('hard') || lowerMessage.includes('easy')) {
1702
+ response = "I automatically adjust difficulty based on your performance. Get words correct on the first try to advance levels!";
1703
+ } else if (lowerMessage.includes('score') || lowerMessage.includes('points')) {
1704
+ response = `Your current stats: ${this.state.wordsMastered} words mastered, ${this.state.currentStreak} day streak, Level ${Math.floor(this.state.levelProgress/25)+1}.`;
1705
+ } else if (lowerMessage.includes('hint') || lowerMessage.includes('clue')) {
1706
+ response = "Click the 'Get Hint' button for phonetic clues, context sentences, or letter reveals. Don't overuse hints for maximum points!";
1707
+ } else if (lowerMessage.includes('current word') || lowerMessage.includes('what word')) {
1708
+ if (this.state.currentWord) {
1709
+ response = `The current word is "${this.state.currentWord.word}". Listen carefully and try to spell it!`;
1710
+ } else {
1711
+ response = "Start a training session to get your first word!";
1712
+ }
1713
+ } else if (lowerMessage.includes('thank')) {
1714
+ response = "You're welcome! Keep practicing to become a spelling champion! 🏆";
1715
+ } else {
1716
+ response = this.getRandomAIResponse();
1717
+ }
1718
+
1719
+ this.addAIMessage(response);
1720
+
1721
+ // Optional: Speak the response
1722
+ if (this.state.sessionActive) {
1723
+ this.speakText(response, 0.9, 1.0);
1724
+ }
1725
+ }
1726
+
1727
+ getRandomAIResponse() {
1728
+ const responses = [
1729
+ "Great question! Focus on listening carefully to each word. The phonetic clues can help if you're stuck.",
1730
+ "Remember, spelling improves with practice. Each word you master builds your vocabulary!",
1731
+ "I'm tracking your progress and will adjust the difficulty to match your skill level.",
1732
+ "Try to spell words without hints for maximum points. But don't hesitate to use hints if you need them!",
1733
+ "Pay attention to vowel sounds and silent letters - they're often the trickiest parts of spelling.",
1734
+ "Consistent practice is key to spelling mastery. Even 10 minutes a day makes a big difference!"
1735
+ ];
1736
+ return responses[Math.floor(Math.random() * responses.length)];
1737
+ }
1738
+
1739
+ toggleVoiceInput() {
1740
+ const voiceBtn = document.getElementById('voiceButton');
1741
+ const isListening = voiceBtn.classList.contains('listening');
1742
+
1743
+ if (!isListening) {
1744
+ // Start listening
1745
+ voiceBtn.classList.add('listening');
1746
+ voiceBtn.innerHTML = '<i class="fas fa-stop"></i>';
1747
+ this.startVoiceRecognition();
1748
+ } else {
1749
+ // Stop listening
1750
+ voiceBtn.classList.remove('listening');
1751
+ voiceBtn.innerHTML = '<i class="fas fa-microphone"></i>';
1752
+ this.stopVoiceRecognition();
1753
+ }
1754
+ }
1755
+
1756
+ startVoiceRecognition() {
1757
+ if ('webkitSpeechRecognition' in window || 'SpeechRecognition' in window) {
1758
+ const SpeechRecognition = window.SpeechRecognition || window.webkitSpeechRecognition;
1759
+ this.recognition = new SpeechRecognition();
1760
+
1761
+ this.recognition.continuous = false;
1762
+ this.recognition.interimResults = false;
1763
+ this.recognition.lang = 'en-US';
1764
+
1765
+ this.recognition.onresult = (event) => {
1766
+ const transcript = event.results[0][0].transcript;
1767
+ document.getElementById('answerInput').value = transcript;
1768
+
1769
+ // Auto-check if in spelling mode
1770
+ if (this.state.sessionActive && !this.state.isCorrect) {
1771
+ setTimeout(() => this.checkAnswer(), 500);
1772
+ }
1773
+ };
1774
+
1775
+ this.recognition.onerror = (event) => {
1776
+ console.log('Speech recognition error:', event.error);
1777
+ };
1778
+
1779
+ this.recognition.start();
1780
+ } else {
1781
+ alert('Speech recognition not supported in this browser. Try Chrome or Edge.');
1782
+ }
1783
+ }
1784
+
1785
+ stopVoiceRecognition() {
1786
+ if (this.recognition) {
1787
+ this.recognition.stop();
1788
+ }
1789
+ }
1790
+
1791
+ // ============================================================================
1792
+ // UI SETTINGS
1793
+ // ============================================================================
1794
+
1795
+ setDifficulty(level) {
1796
+ this.state.difficulty = level;
1797
+
1798
+ // Update UI
1799
+ document.querySelectorAll('[data-level]').forEach(btn => {
1800
+ btn.classList.toggle('active', btn.dataset.level === level);
1801
+ });
1802
+
1803
+ this.addAIMessage(`Difficulty set to ${level} level. Words will match this skill level.`);
1804
+ }
1805
+
1806
+ setTrainingMode(mode) {
1807
+ this.state.trainingMode = mode;
1808
+
1809
+ // Update UI
1810
+ document.querySelectorAll('[data-mode]').forEach(btn => {
1811
+ btn.classList.toggle('active', btn.dataset.mode === mode);
1812
+ });
1813
+
1814
+ const modeDescriptions = {
1815
+ 'adaptive': 'AI adapts difficulty in real-time',
1816
+ 'practice': 'Random words for general practice',
1817
+ 'challenge': 'Time-limited spelling challenges',
1818
+ 'time-trial': 'Race against the clock'
1819
+ };
1820
+
1821
+ this.addAIMessage(`Training mode set to ${mode}. ${modeDescriptions[mode]}`);
1822
+ }
1823
+
1824
+ setVoice(voice) {
1825
+ this.state.currentVoice = voice;
1826
+
1827
+ // Update UI
1828
+ document.querySelectorAll('[data-voice]').forEach(btn => {
1829
+ btn.classList.toggle('active', btn.dataset.voice === voice);
1830
+ });
1831
+
1832
+ // Test the voice
1833
+ this.speakText('Voice updated', 0.9, 1.0);
1834
+ }
1835
+
1836
+ updateStats() {
1837
+ document.getElementById('wordsMastered').textContent = this.state.wordsMastered;
1838
+ document.getElementById('streakCount').textContent = this.state.currentStreak;
1839
+
1840
+ // Update progress bar
1841
+ document.getElementById('progressFill').style.width = `${this.state.levelProgress}%`;
1842
+
1843
+ // Update sidebar progress
1844
+ const progressContainer = document.querySelector('.progress-stats');
1845
+ const level = Math.floor(this.state.levelProgress / 25) + 1;
1846
+ progressContainer.innerHTML = `<span>Level ${level}</span><span>${this.state.levelProgress}%</span>`;
1847
+ }
1848
+
1849
+ // ============================================================================
1850
+ // UTILITY FUNCTIONS
1851
+ // ============================================================================
1852
+
1853
+ shuffleArray(array) {
1854
+ for (let i = array.length - 1; i > 0; i--) {
1855
+ const j = Math.floor(Math.random() * (i + 1));
1856
+ [array[i], array[j]] = [array[j], array[i]];
1857
+ }
1858
+ return array;
1859
+ }
1860
+ }
1861
+
1862
+ // ============================================================================
1863
+ // INITIALIZE APPLICATION
1864
+ // ============================================================================
1865
+
1866
+ // Start the AI Spelling Tutor when page loads
1867
+ document.addEventListener('DOMContentLoaded', () => {
1868
+ window.spellingTutor = new AISpellingTutor();
1869
+
1870
+ // Add keyboard shortcuts
1871
+ document.addEventListener('keydown', (e) => {
1872
+ // Ctrl + Space to hear word
1873
+ if (e.ctrlKey && e.code === 'Space') {
1874
+ e.preventDefault();
1875
+ window.spellingTutor.speakWord();
1876
+ }
1877
+
1878
+ // Ctrl + Enter to check answer
1879
+ if (e.ctrlKey && e.key === 'Enter') {
1880
+ e.preventDefault();
1881
+ window.spellingTutor.checkAnswer();
1882
+ }
1883
+
1884
+ // Ctrl + H for hint
1885
+ if (e.ctrlKey && e.key === 'h') {
1886
+ e.preventDefault();
1887
+ window.spellingTutor.giveHint();
1888
+ }
1889
+
1890
+ // Ctrl + N for next word (when available)
1891
+ if (e.ctrlKey && e.key === 'n') {
1892
+ e.preventDefault();
1893
+ if (window.spellingTutor.state.showNextButton) {
1894
+ window.spellingTutor.nextWord();
1895
+ }
1896
+ }
1897
+ });
1898
+
1899
+ // Instructions tooltip
1900
+ setTimeout(() => {
1901
+ if (window.spellingTutor) {
1902
+ window.spellingTutor.addAIMessage('💡 Tip: Use Ctrl+Space to hear the word, Ctrl+Enter to check your answer!');
1903
+ }
1904
+ }, 3000);
1905
+ });
1906
+
1907
+ // Handle window resize
1908
+ window.addEventListener('resize', () => {
1909
+ if (window.spellingTutor && window.spellingTutor.onWindowResize) {
1910
+ window.spellingTutor.onWindowResize();
1911
+ }
1912
+ });
1913
+ </script>
1914
+ </body>
1915
+ </html>