opensource / japones-carta-al-samurai.html
🌸
Una carta al samurái
Juego narrativo donde el usuario ayuda a Hana a escribir una carta de amor en japonés. Aprendizaje a través de la emoción.
🇯🇵 Japonés HTML CSS JavaScript Narrative Japanese MIT License
1 archivo 940 líneas MIT
Ver en AlpacaViajes Volver
japones-carta-al-samurai.html 940 líneas
HTML · CSS · JavaScript
1 <!DOCTYPE html>
2 class="tok-tag"><htmlclass="tok-attr"> lang="es"class="tok-tag">>
3 class="tok-tag"><headclass="tok-attr">class="tok-tag">>
4 class="tok-tag"><metaclass="tok-attr"> charset="UTF-8"class="tok-tag">>
5 class="tok-tag"><metaclass="tok-attr"> name="viewport" content="width=device-width, initial-scale=1.0"class="tok-tag">>
6 class="tok-tag"><titleclass="tok-attr">class="tok-tag">>Una carta al samuráiclass="tok-tag"></titleclass="tok-attr">class="tok-tag">>
7 class="tok-tag"><linkclass="tok-attr"> href="class="tok-prop">https:class="tok-val">//fonts.googleapis.com/css2?family=Noto+Serif+JP:wght@300;400;700&family=IM+Fell+class="tok-prop">English:class="tok-val">ital@0;1&family=Noto+Sans+class="tok-prop">JP:class="tok-val">wght@300;400&display=swap" rel="stylesheet"class="tok-tag">>
8 class="tok-tag"><styleclass="tok-attr">class="tok-tag">>
9 :root {
10 class="tok-prop">--paper: class="tok-val">#f7f0e3;
11 class="tok-prop">--paper-dark: class="tok-val">#ede0c4;
12 class="tok-prop">--ink: class="tok-val">#1a1008;
13 class="tok-prop">--ink-light: class="tok-val">#3d2e1a;
14 class="tok-prop">--red: class="tok-val">#8b1a1a;
15 class="tok-prop">--gold: class="tok-val">#b8860b;
16 class="tok-prop">--gold-light: class="tok-val">#d4a843;
17 class="tok-prop">--sakura: class="tok-val">#d4849a;
18 class="tok-prop">--sakura-light: class="tok-val">#f0b8c8;
19 class="tok-prop">--mist: class="tok-val">#8fa8b0;
20 class="tok-prop">--shadow: class="tok-val">rgba(26,16,8,0.15);
21 class="tok-prop">--radius: class="tok-val">4px;
22 }
23
24 * { class="tok-prop">margin:class="tok-val">0; class="tok-prop">padding:class="tok-val">0; class="tok-prop">box-sizing:class="tok-val">border-box; }
25
26 body {
27 class="tok-prop">background: class="tok-val">#1a1008;
28 class="tok-prop">font-family: class="tok-val">';IM Fell English', serif;
29 class="tok-prop">min-height: class="tok-val">100vh;
30 class="tok-prop">display: class="tok-val">flex;
31 class="tok-prop">align-items: class="tok-val">center;
32 class="tok-prop">justify-content: class="tok-val">center;
33 class="tok-prop">overflow-x: class="tok-val">hidden;
34 class="tok-prop">position: class="tok-val">relative;
35 }
36
37 /* Background — ink wash */
38 class="tok-prop">body:class="tok-val">:before {
39 class="tok-prop">content: class="tok-val">';';
40 class="tok-prop">position: class="tok-val">fixed; class="tok-prop">inset: class="tok-val">0;
41 background:
42 radial-gradient(ellipse at 20% 50%, rgba(139,26,26,0.08) 0%, transparent 60%),
43 radial-gradient(ellipse at 80% 20%, rgba(184,134,11,0.06) 0%, transparent 50%),
44 radial-gradient(ellipse at 60% 80%, rgba(143,168,176,0.05) 0%, transparent 50%);
45 class="tok-prop">pointer-events: class="tok-val">none;
46 }
47
48 /* Falling petals */
49 .petal {
50 class="tok-prop">position: class="tok-val">fixed;
51 class="tok-prop">width: class="tok-val">8px; class="tok-prop">height: class="tok-val">10px;
52 class="tok-prop">border-radius: class="tok-val">50% 50% 50% 0;
53 class="tok-prop">opacity: class="tok-val">0;
54 class="tok-prop">pointer-events: class="tok-val">none;
55 class="tok-prop">animation: class="tok-val">fall linear infinite;
56 }
57
58 @keyframes fall {
59 0% { class="tok-prop">transform: class="tok-val">translateY(-20px) rotate(0deg) translateX(0); class="tok-prop">opacity: class="tok-val">0; }
60 10% { class="tok-prop">opacity: class="tok-val">0.6; }
61 90% { class="tok-prop">opacity: class="tok-val">0.3; }
62 100% { class="tok-prop">transform: class="tok-val">translateY(110vh) rotate(720deg) translateX(40px); class="tok-prop">opacity: class="tok-val">0; }
63 }
64
65 /* Main wrapper */
66 .wrapper {
67 class="tok-prop">width: class="tok-val">100%;
68 class="tok-prop">max-width: class="tok-val">680px;
69 class="tok-prop">min-height: class="tok-val">100vh;
70 class="tok-prop">display: class="tok-val">flex;
71 class="tok-prop">flex-direction: class="tok-val">column;
72 class="tok-prop">align-items: class="tok-val">center;
73 class="tok-prop">justify-content: class="tok-val">center;
74 class="tok-prop">padding: class="tok-val">40px 20px;
75 class="tok-prop">position: class="tok-val">relative;
76 class="tok-prop">z-index: class="tok-val">1;
77 }
78
79 /* ── SCREENS ── */
80 .screen { class="tok-prop">display: class="tok-val">none; class="tok-prop">width: class="tok-val">100%; class="tok-prop">flex-direction: class="tok-val">column; class="tok-prop">align-items: class="tok-val">center; }
81 .screen.active { class="tok-prop">display: class="tok-val">flex; class="tok-prop">animation: class="tok-val">fadeUp 0.7s ease both; }
82
83 @keyframes fadeUp {
84 from { class="tok-prop">opacity: class="tok-val">0; class="tok-prop">transform: class="tok-val">translateY(24px); }
85 to { class="tok-prop">opacity: class="tok-val">1; class="tok-prop">transform: class="tok-val">translateY(0); }
86 }
87
88 /* ── INTRO SCREEN ── */
89 .intro-deco {
90 class="tok-prop">font-size: class="tok-val">11px;
91 class="tok-prop">letter-spacing: class="tok-val">6px;
92 class="tok-prop">color: class="tok-val">class="tok-kw">var(--gold);
93 class="tok-prop">text-transform: class="tok-val">uppercase;
94 class="tok-prop">margin-bottom: class="tok-val">16px;
95 class="tok-prop">opacity: class="tok-val">0.8;
96 }
97
98 .intro-kanji {
99 class="tok-prop">font-family: class="tok-val">';Noto Serif JP', serif;
100 class="tok-prop">font-size: class="tok-val">96px;
101 class="tok-prop">color: class="tok-val">class="tok-kw">var(--paper);
102 class="tok-prop">line-height: class="tok-val">1;
103 class="tok-prop">margin-bottom: class="tok-val">8px;
104 class="tok-prop">text-shadow: class="tok-val">0 0 60px rgba(212,132,154,0.3), 0 4px 20px rgba(0,0,0,0.5);
105 class="tok-prop">animation: class="tok-val">breathe 4s ease-in-out infinite;
106 }
107
108 @keyframes breathe {
109 0%, 100% { class="tok-prop">text-shadow: class="tok-val">0 0 60px rgba(212,132,154,0.3), 0 4px 20px rgba(0,0,0,0.5); }
110 50% { class="tok-prop">text-shadow: class="tok-val">0 0 80px rgba(212,132,154,0.5), 0 4px 30px rgba(0,0,0,0.5); }
111 }
112
113 .intro-title {
114 class="tok-prop">font-size: class="tok-val">clamp(1.6rem, 5vw, 2.4rem);
115 class="tok-prop">color: class="tok-val">class="tok-kw">var(--paper);
116 class="tok-prop">text-align: class="tok-val">center;
117 class="tok-prop">line-height: class="tok-val">1.2;
118 class="tok-prop">margin-bottom: class="tok-val">6px;
119 }
120
121 .intro-subtitle {
122 class="tok-prop">font-style: class="tok-val">italic;
123 class="tok-prop">color: class="tok-val">class="tok-kw">var(--sakura-light);
124 class="tok-prop">font-size: class="tok-val">14px;
125 class="tok-prop">margin-bottom: class="tok-val">40px;
126 class="tok-prop">opacity: class="tok-val">0.8;
127 }
128
129 /* Paper card — used in intro & dialogue */
130 .paper-card {
131 class="tok-prop">background: class="tok-val">class="tok-kw">var(--paper);
132 class="tok-prop">border-radius: class="tok-val">class="tok-kw">var(--radius);
133 class="tok-prop">padding: class="tok-val">32px 36px;
134 class="tok-prop">width: class="tok-val">100%;
135 class="tok-prop">max-width: class="tok-val">540px;
136 class="tok-prop">box-shadow: class="tok-val">0 24px 60px rgba(0,0,0,0.6), 0 2px 0 class="tok-kw">var(--paper-dark) inset;
137 class="tok-prop">position: class="tok-val">relative;
138 class="tok-prop">margin-bottom: class="tok-val">28px;
139 }
140
141 .class="tok-prop">paper-card:class="tok-val">:before {
142 class="tok-prop">content: class="tok-val">';';
143 class="tok-prop">position: class="tok-val">absolute;
144 class="tok-prop">inset: class="tok-val">0;
145 class="tok-prop">background: class="tok-val">repeating-linear-gradient(
146 transparent,
147 transparent 27px,
148 rgba(26,16,8,0.06) 28px
149 );
150 class="tok-prop">border-radius: class="tok-val">class="tok-kw">var(--radius);
151 class="tok-prop">pointer-events: class="tok-val">none;
152 }
153
154 .class="tok-prop">paper-card:class="tok-val">:after {
155 class="tok-prop">content: class="tok-val">';';
156 class="tok-prop">position: class="tok-val">absolute;
157 class="tok-prop">top: class="tok-val">0; class="tok-prop">left: class="tok-val">36px;
158 class="tok-prop">width: class="tok-val">1px; class="tok-prop">height: class="tok-val">100%;
159 class="tok-prop">background: class="tok-val">rgba(139,26,26,0.12);
160 }
161
162 .char-portrait {
163 class="tok-prop">width: class="tok-val">64px; class="tok-prop">height: class="tok-val">64px;
164 class="tok-prop">border-radius: class="tok-val">50%;
165 class="tok-prop">background: class="tok-val">linear-gradient(135deg, class="tok-kw">var(--sakura) 0%, class="tok-kw">var(--sakura-light) 100%);
166 class="tok-prop">display: class="tok-val">flex; class="tok-prop">align-items: class="tok-val">center; class="tok-prop">justify-content: class="tok-val">center;
167 class="tok-prop">font-size: class="tok-val">32px;
168 class="tok-prop">margin-bottom: class="tok-val">16px;
169 class="tok-prop">box-shadow: class="tok-val">0 4px 16px rgba(212,132,154,0.4);
170 class="tok-prop">flex-shrink: class="tok-val">0;
171 }
172
173 .char-name {
174 class="tok-prop">font-size: class="tok-val">11px;
175 class="tok-prop">letter-spacing: class="tok-val">3px;
176 class="tok-prop">text-transform: class="tok-val">uppercase;
177 class="tok-prop">color: class="tok-val">class="tok-kw">var(--red);
178 class="tok-prop">margin-bottom: class="tok-val">8px;
179 class="tok-prop">font-family: class="tok-val">';Noto Sans JP', sans-serif;
180 }
181
182 .dialogue-text {
183 class="tok-prop">font-size: class="tok-val">15px;
184 class="tok-prop">color: class="tok-val">class="tok-kw">var(--ink);
185 class="tok-prop">line-height: class="tok-val">1.9;
186 class="tok-prop">font-style: class="tok-val">italic;
187 }
188
189 .dialogue-text strong {
190 class="tok-prop">font-style: class="tok-val">normal;
191 class="tok-prop">color: class="tok-val">class="tok-kw">var(--red);
192 }
193
194 .btn-primary {
195 class="tok-prop">background: class="tok-val">class="tok-kw">var(--ink);
196 class="tok-prop">color: class="tok-val">class="tok-kw">var(--paper);
197 class="tok-prop">border: class="tok-val">none;
198 class="tok-prop">padding: class="tok-val">14px 40px;
199 class="tok-prop">font-family: class="tok-val">';IM Fell English', serif;
200 class="tok-prop">font-size: class="tok-val">15px;
201 class="tok-prop">border-radius: class="tok-val">2px;
202 class="tok-prop">cursor: class="tok-val">pointer;
203 class="tok-prop">letter-spacing: class="tok-val">1px;
204 class="tok-prop">transition: class="tok-val">all 0.25s ease;
205 class="tok-prop">box-shadow: class="tok-val">0 8px 24px rgba(0,0,0,0.4);
206 class="tok-prop">position: class="tok-val">relative;
207 class="tok-prop">overflow: class="tok-val">hidden;
208 }
209
210 .class="tok-prop">btn-primary:class="tok-val">:before {
211 class="tok-prop">content: class="tok-val">';';
212 class="tok-prop">position: class="tok-val">absolute;
213 class="tok-prop">inset: class="tok-val">0;
214 class="tok-prop">background: class="tok-val">linear-gradient(135deg, transparent 40%, rgba(255,255,255,0.05));
215 }
216
217 .class="tok-prop">btn-primary:class="tok-val">hover {
218 class="tok-prop">background: class="tok-val">class="tok-kw">var(--red);
219 class="tok-prop">transform: class="tok-val">translateY(-2px);
220 class="tok-prop">box-shadow: class="tok-val">0 12px 32px rgba(139,26,26,0.4);
221 }
222
223 .class="tok-prop">btn-primary:class="tok-val">active { class="tok-prop">transform: class="tok-val">translateY(0); }
224
225 /* ── LESSON SCREEN ── */
226 .lesson-header {
227 class="tok-prop">text-align: class="tok-val">center;
228 class="tok-prop">margin-bottom: class="tok-val">24px;
229 class="tok-prop">width: class="tok-val">100%;
230 }
231
232 .lesson-step {
233 class="tok-prop">font-size: class="tok-val">11px;
234 class="tok-prop">letter-spacing: class="tok-val">4px;
235 class="tok-prop">color: class="tok-val">class="tok-kw">var(--gold);
236 class="tok-prop">text-transform: class="tok-val">uppercase;
237 class="tok-prop">margin-bottom: class="tok-val">6px;
238 }
239
240 .lesson-question {
241 class="tok-prop">font-size: class="tok-val">13px;
242 class="tok-prop">color: class="tok-val">rgba(247,240,227,0.5);
243 class="tok-prop">font-style: class="tok-val">italic;
244 }
245
246 /* Dialogue bubble */
247 .bubble-wrap {
248 class="tok-prop">display: class="tok-val">flex;
249 class="tok-prop">gap: class="tok-val">14px;
250 class="tok-prop">align-items: class="tok-val">flex-start;
251 class="tok-prop">width: class="tok-val">100%;
252 class="tok-prop">max-width: class="tok-val">540px;
253 class="tok-prop">margin-bottom: class="tok-val">24px;
254 }
255
256 .bubble-portrait {
257 class="tok-prop">width: class="tok-val">48px; class="tok-prop">height: class="tok-val">48px;
258 class="tok-prop">border-radius: class="tok-val">50%;
259 class="tok-prop">background: class="tok-val">linear-gradient(135deg, class="tok-kw">var(--sakura), class="tok-kw">var(--sakura-light));
260 class="tok-prop">display: class="tok-val">flex; class="tok-prop">align-items: class="tok-val">center; class="tok-prop">justify-content: class="tok-val">center;
261 class="tok-prop">font-size: class="tok-val">24px;
262 class="tok-prop">flex-shrink: class="tok-val">0;
263 class="tok-prop">box-shadow: class="tok-val">0 4px 12px rgba(212,132,154,0.35);
264 }
265
266 .bubble {
267 class="tok-prop">background: class="tok-val">class="tok-kw">var(--paper);
268 class="tok-prop">border-radius: class="tok-val">0 12px 12px 12px;
269 class="tok-prop">padding: class="tok-val">16px 20px;
270 class="tok-prop">flex: class="tok-val">1;
271 class="tok-prop">box-shadow: class="tok-val">0 8px 24px rgba(0,0,0,0.4);
272 class="tok-prop">position: class="tok-val">relative;
273 }
274
275 .class="tok-prop">bubble:class="tok-val">:before {
276 class="tok-prop">content: class="tok-val">';';
277 class="tok-prop">position: class="tok-val">absolute;
278 class="tok-prop">top: class="tok-val">0; class="tok-prop">left: class="tok-val">-10px;
279 class="tok-prop">border: class="tok-val">10px solid transparent;
280 class="tok-prop">border-right-color: class="tok-val">class="tok-kw">var(--paper);
281 class="tok-prop">border-top: class="tok-val">0;
282 }
283
284 .bubble-name {
285 class="tok-prop">font-size: class="tok-val">10px;
286 class="tok-prop">letter-spacing: class="tok-val">2px;
287 class="tok-prop">color: class="tok-val">class="tok-kw">var(--red);
288 class="tok-prop">text-transform: class="tok-val">uppercase;
289 class="tok-prop">font-family: class="tok-val">';Noto Sans JP', sans-serif;
290 class="tok-prop">margin-bottom: class="tok-val">6px;
291 }
292
293 .bubble-text {
294 class="tok-prop">font-size: class="tok-val">14px;
295 class="tok-prop">color: class="tok-val">class="tok-kw">var(--ink);
296 class="tok-prop">line-height: class="tok-val">1.7;
297 class="tok-prop">font-style: class="tok-val">italic;
298 }
299
300 .bubble-text em {
301 class="tok-prop">color: class="tok-val">class="tok-kw">var(--red);
302 class="tok-prop">font-style: class="tok-val">normal;
303 class="tok-prop">font-weight: class="tok-val">bold;
304 }
305
306 /* FLIP CARD */
307 .flip-area {
308 class="tok-prop">perspective: class="tok-val">1200px;
309 class="tok-prop">width: class="tok-val">280px;
310 class="tok-prop">height: class="tok-val">340px;
311 class="tok-prop">margin: class="tok-val">0 auto 28px;
312 class="tok-prop">cursor: class="tok-val">pointer;
313 }
314
315 .flip-inner {
316 class="tok-prop">width: class="tok-val">100%; class="tok-prop">height: class="tok-val">100%;
317 class="tok-prop">position: class="tok-val">relative;
318 class="tok-prop">transform-style: class="tok-val">preserve-3d;
319 class="tok-prop">transition: class="tok-val">transform 0.65s cubic-bezier(0.4,0,0.2,1);
320 }
321
322 .flip-inner.flipped { class="tok-prop">transform: class="tok-val">rotateY(180deg); }
323
324 .flip-face {
325 class="tok-prop">position: class="tok-val">absolute; class="tok-prop">inset: class="tok-val">0;
326 class="tok-prop">border-radius: class="tok-val">8px;
327 class="tok-prop">backface-visibility: class="tok-val">hidden;
328 class="tok-prop">display: class="tok-val">flex;
329 class="tok-prop">flex-direction: class="tok-val">column;
330 class="tok-prop">align-items: class="tok-val">center;
331 class="tok-prop">justify-content: class="tok-val">center;
332 class="tok-prop">padding: class="tok-val">28px 24px;
333 }
334
335 .flip-front {
336 class="tok-prop">background: class="tok-val">class="tok-kw">var(--paper);
337 class="tok-prop">box-shadow: class="tok-val">0 20px 50px rgba(0,0,0,0.5), 4px 4px 0 class="tok-kw">var(--paper-dark);
338 }
339
340 .class="tok-prop">flip-front:class="tok-val">:before {
341 class="tok-prop">content: class="tok-val">';';
342 class="tok-prop">position: class="tok-val">absolute; class="tok-prop">inset: class="tok-val">0;
343 class="tok-prop">background: class="tok-val">repeating-linear-gradient(transparent, transparent 27px, rgba(26,16,8,0.05) 28px);
344 class="tok-prop">border-radius: class="tok-val">8px;
345 class="tok-prop">pointer-events: class="tok-val">none;
346 }
347
348 .flip-back {
349 class="tok-prop">background: class="tok-val">linear-gradient(145deg, #1a0f05, #0d0800);
350 class="tok-prop">border: class="tok-val">1px solid rgba(184,134,11,0.2);
351 class="tok-prop">box-shadow: class="tok-val">0 20px 50px rgba(0,0,0,0.6), 0 0 40px rgba(184,134,11,0.05);
352 class="tok-prop">transform: class="tok-val">rotateY(180deg);
353 }
354
355 .flip-hint-emoji { class="tok-prop">font-size: class="tok-val">56px; class="tok-prop">margin-bottom: class="tok-val">12px; }
356
357 .flip-hint-word {
358 class="tok-prop">font-size: class="tok-val">13px;
359 class="tok-prop">color: class="tok-val">class="tok-kw">var(--ink-light);
360 class="tok-prop">text-align: class="tok-val">center;
361 class="tok-prop">line-height: class="tok-val">1.6;
362 class="tok-prop">font-style: class="tok-val">italic;
363 class="tok-prop">max-width: class="tok-val">180px;
364 }
365
366 .flip-tap {
367 class="tok-prop">position: class="tok-val">absolute; class="tok-prop">bottom: class="tok-val">16px;
368 class="tok-prop">font-size: class="tok-val">10px;
369 class="tok-prop">color: class="tok-val">rgba(26,16,8,0.3);
370 class="tok-prop">letter-spacing: class="tok-val">2px;
371 class="tok-prop">font-family: class="tok-val">';Noto Sans JP', sans-serif;
372 }
373
374 /* Back face content */
375 .flip-kanji {
376 class="tok-prop">font-family: class="tok-val">';Noto Serif JP', serif;
377 class="tok-prop">font-size: class="tok-val">88px;
378 class="tok-prop">line-height: class="tok-val">1;
379 class="tok-prop">margin-bottom: class="tok-val">10px;
380 class="tok-prop">background: class="tok-val">linear-gradient(135deg, class="tok-kw">var(--paper) 40%, class="tok-kw">var(--gold-light));
381 class="tok-prop">-webkit-background-clip: class="tok-val">text;
382 class="tok-prop">-webkit-text-fill-color: class="tok-val">transparent;
383 class="tok-prop">background-clip: class="tok-val">text;
384 class="tok-prop">filter: class="tok-val">drop-shadow(0 0 20px rgba(184,134,11,0.3));
385 }
386
387 .flip-romaji {
388 class="tok-prop">font-size: class="tok-val">18px;
389 class="tok-prop">color: class="tok-val">class="tok-kw">var(--gold-light);
390 class="tok-prop">letter-spacing: class="tok-val">3px;
391 class="tok-prop">margin-bottom: class="tok-val">8px;
392 class="tok-prop">font-family: class="tok-val">';Noto Sans JP', sans-serif;
393 class="tok-prop">font-weight: class="tok-val">300;
394 }
395
396 .flip-meaning {
397 class="tok-prop">font-size: class="tok-val">16px;
398 class="tok-prop">color: class="tok-val">class="tok-kw">var(--paper);
399 class="tok-prop">font-weight: class="tok-val">400;
400 class="tok-prop">margin-bottom: class="tok-val">10px;
401 }
402
403 .flip-example {
404 class="tok-prop">font-size: class="tok-val">11px;
405 class="tok-prop">color: class="tok-val">rgba(247,240,227,0.45);
406 class="tok-prop">text-align: class="tok-val">center;
407 class="tok-prop">line-height: class="tok-val">1.8;
408 class="tok-prop">font-family: class="tok-val">';Noto Sans JP', sans-serif;
409 }
410
411 /* Answer buttons */
412 .answer-row {
413 class="tok-prop">display: class="tok-val">flex;
414 class="tok-prop">gap: class="tok-val">14px;
415 class="tok-prop">justify-content: class="tok-val">center;
416 class="tok-prop">margin-bottom: class="tok-val">10px;
417 }
418
419 .btn-answer {
420 class="tok-prop">padding: class="tok-val">12px 28px;
421 class="tok-prop">border: class="tok-val">none;
422 class="tok-prop">border-radius: class="tok-val">2px;
423 class="tok-prop">font-family: class="tok-val">';IM Fell English', serif;
424 class="tok-prop">font-size: class="tok-val">13px;
425 class="tok-prop">cursor: class="tok-val">pointer;
426 class="tok-prop">letter-spacing: class="tok-val">0.5px;
427 class="tok-prop">transition: class="tok-val">all 0.2s ease;
428 }
429
430 .class="tok-prop">btn-answer:class="tok-val">disabled {
431 class="tok-prop">opacity: class="tok-val">0.3;
432 class="tok-prop">cursor: class="tok-val">not-allowed;
433 class="tok-prop">transform: class="tok-val">none !important;
434 }
435
436 .btn-knew {
437 class="tok-prop">background: class="tok-val">#2d4a2d;
438 class="tok-prop">color: class="tok-val">#a8d4a8;
439 class="tok-prop">box-shadow: class="tok-val">0 6px 20px rgba(0,0,0,0.3);
440 }
441 .class="tok-prop">btn-knew:class="tok-val">not(:disabled):hover {
442 class="tok-prop">background: class="tok-val">#3d6a3d;
443 class="tok-prop">transform: class="tok-val">translateY(-2px);
444 }
445
446 .btn-forgot {
447 class="tok-prop">background: class="tok-val">#3a1a1a;
448 class="tok-prop">color: class="tok-val">#d4a0a0;
449 class="tok-prop">box-shadow: class="tok-val">0 6px 20px rgba(0,0,0,0.3);
450 }
451 .class="tok-prop">btn-forgot:class="tok-val">not(:disabled):hover {
452 class="tok-prop">background: class="tok-val">#5a2a2a;
453 class="tok-prop">transform: class="tok-val">translateY(-2px);
454 }
455
456 .btn-reveal {
457 class="tok-prop">background: class="tok-val">transparent;
458 class="tok-prop">color: class="tok-val">rgba(247,240,227,0.4);
459 class="tok-prop">border: class="tok-val">1px solid rgba(247,240,227,0.1);
460 class="tok-prop">padding: class="tok-val">10px 20px;
461 class="tok-prop">font-family: class="tok-val">';Noto Sans JP', sans-serif;
462 class="tok-prop">font-size: class="tok-val">11px;
463 class="tok-prop">letter-spacing: class="tok-val">2px;
464 class="tok-prop">cursor: class="tok-val">pointer;
465 class="tok-prop">border-radius: class="tok-val">2px;
466 class="tok-prop">transition: class="tok-val">all 0.2s;
467 }
468 .class="tok-prop">btn-reveal:class="tok-val">hover {
469 class="tok-prop">color: class="tok-val">rgba(247,240,227,0.7);
470 class="tok-prop">border-color: class="tok-val">rgba(247,240,227,0.25);
471 }
472
473 /* Progress dots */
474 .progress-dots {
475 class="tok-prop">display: class="tok-val">flex;
476 class="tok-prop">gap: class="tok-val">8px;
477 class="tok-prop">margin-top: class="tok-val">24px;
478 }
479
480 .dot {
481 class="tok-prop">width: class="tok-val">8px; class="tok-prop">height: class="tok-val">8px;
482 class="tok-prop">border-radius: class="tok-val">50%;
483 class="tok-prop">background: class="tok-val">rgba(247,240,227,0.15);
484 class="tok-prop">transition: class="tok-val">all 0.3s ease;
485 }
486 .dot.done { class="tok-prop">background: class="tok-val">class="tok-kw">var(--gold); }
487 .dot.current { class="tok-prop">background: class="tok-val">class="tok-kw">var(--sakura); class="tok-prop">transform: class="tok-val">scale(1.3); }
488
489 /* ── LETTER SCREEN ── */
490 .letter-wrap {
491 class="tok-prop">width: class="tok-val">100%;
492 class="tok-prop">max-width: class="tok-val">540px;
493 }
494
495 .letter-title {
496 class="tok-prop">text-align: class="tok-val">center;
497 class="tok-prop">color: class="tok-val">class="tok-kw">var(--gold-light);
498 class="tok-prop">font-size: class="tok-val">11px;
499 class="tok-prop">letter-spacing: class="tok-val">5px;
500 class="tok-prop">text-transform: class="tok-val">uppercase;
501 class="tok-prop">margin-bottom: class="tok-val">24px;
502 class="tok-prop">opacity: class="tok-val">0.8;
503 }
504
505 .letter-paper {
506 class="tok-prop">background: class="tok-val">class="tok-kw">var(--paper);
507 class="tok-prop">padding: class="tok-val">48px 52px;
508 class="tok-prop">border-radius: class="tok-val">class="tok-kw">var(--radius);
509 class="tok-prop">box-shadow: class="tok-val">0 24px 60px rgba(0,0,0,0.6), 4px 4px 0 class="tok-kw">var(--paper-dark), 8px 8px 0 rgba(26,16,8,0.1);
510 class="tok-prop">margin-bottom: class="tok-val">28px;
511 class="tok-prop">position: class="tok-val">relative;
512 }
513
514 .class="tok-prop">letter-paper:class="tok-val">:before {
515 class="tok-prop">content: class="tok-val">';';
516 class="tok-prop">position: class="tok-val">absolute; class="tok-prop">inset: class="tok-val">0;
517 class="tok-prop">background: class="tok-val">repeating-linear-gradient(transparent, transparent 27px, rgba(26,16,8,0.06) 28px);
518 class="tok-prop">border-radius: class="tok-val">class="tok-kw">var(--radius);
519 class="tok-prop">pointer-events: class="tok-val">none;
520 }
521
522 .class="tok-prop">letter-paper:class="tok-val">:after {
523 class="tok-prop">content: class="tok-val">';';
524 class="tok-prop">position: class="tok-val">absolute;
525 class="tok-prop">top: class="tok-val">0; class="tok-prop">left: class="tok-val">60px;
526 class="tok-prop">width: class="tok-val">1px; class="tok-prop">height: class="tok-val">100%;
527 class="tok-prop">background: class="tok-val">rgba(139,26,26,0.1);
528 }
529
530 .letter-seal {
531 class="tok-prop">text-align: class="tok-val">center;
532 class="tok-prop">margin-bottom: class="tok-val">24px;
533 class="tok-prop">font-size: class="tok-val">32px;
534 }
535
536 .letter-line {
537 class="tok-prop">display: class="tok-val">flex;
538 class="tok-prop">align-items: class="tok-val">baseline;
539 class="tok-prop">gap: class="tok-val">12px;
540 class="tok-prop">margin-bottom: class="tok-val">14px;
541 class="tok-prop">opacity: class="tok-val">0;
542 class="tok-prop">transform: class="tok-val">translateY(8px);
543 class="tok-prop">animation: class="tok-val">lineReveal 0.5s ease forwards;
544 }
545
546 @keyframes lineReveal {
547 to { class="tok-prop">opacity: class="tok-val">1; class="tok-prop">transform: class="tok-val">translateY(0); }
548 }
549
550 .letter-jp {
551 class="tok-prop">font-family: class="tok-val">';Noto Serif JP', serif;
552 class="tok-prop">font-size: class="tok-val">20px;
553 class="tok-prop">color: class="tok-val">class="tok-kw">var(--ink);
554 class="tok-prop">min-width: class="tok-val">120px;
555 }
556
557 .letter-romaji {
558 class="tok-prop">font-size: class="tok-val">11px;
559 class="tok-prop">color: class="tok-val">class="tok-kw">var(--mist);
560 class="tok-prop">font-family: class="tok-val">';Noto Sans JP', sans-serif;
561 class="tok-prop">letter-spacing: class="tok-val">1px;
562 }
563
564 .letter-translation {
565 class="tok-prop">font-size: class="tok-val">13px;
566 class="tok-prop">color: class="tok-val">class="tok-kw">var(--ink-light);
567 class="tok-prop">font-style: class="tok-val">italic;
568 class="tok-prop">border-left: class="tok-val">2px solid class="tok-kw">var(--sakura-light);
569 class="tok-prop">padding-left: class="tok-val">10px;
570 class="tok-prop">margin-left: class="tok-val">auto;
571 class="tok-prop">max-width: class="tok-val">200px;
572 class="tok-prop">line-height: class="tok-val">1.5;
573 }
574
575 .letter-signature {
576 class="tok-prop">text-align: class="tok-val">right;
577 class="tok-prop">margin-top: class="tok-val">28px;
578 class="tok-prop">font-family: class="tok-val">';Noto Serif JP', serif;
579 class="tok-prop">font-size: class="tok-val">16px;
580 class="tok-prop">color: class="tok-val">class="tok-kw">var(--red);
581 class="tok-prop">opacity: class="tok-val">0;
582 class="tok-prop">animation: class="tok-val">lineReveal 0.5s ease 1.8s forwards;
583 }
584
585 /* Result message */
586 .result-message {
587 class="tok-prop">background: class="tok-val">class="tok-kw">var(--paper);
588 class="tok-prop">border-radius: class="tok-val">class="tok-kw">var(--radius);
589 class="tok-prop">padding: class="tok-val">28px 32px;
590 class="tok-prop">max-width: class="tok-val">540px;
591 class="tok-prop">width: class="tok-val">100%;
592 class="tok-prop">text-align: class="tok-val">center;
593 class="tok-prop">box-shadow: class="tok-val">0 16px 40px rgba(0,0,0,0.5);
594 class="tok-prop">margin-bottom: class="tok-val">24px;
595 }
596
597 .result-icon { class="tok-prop">font-size: class="tok-val">48px; class="tok-prop">margin-bottom: class="tok-val">12px; }
598
599 .result-title-text {
600 class="tok-prop">font-size: class="tok-val">1.4rem;
601 class="tok-prop">color: class="tok-val">class="tok-kw">var(--ink);
602 class="tok-prop">margin-bottom: class="tok-val">8px;
603 }
604
605 .result-sub {
606 class="tok-prop">font-size: class="tok-val">13px;
607 class="tok-prop">color: class="tok-val">class="tok-kw">var(--ink-light);
608 class="tok-prop">font-style: class="tok-val">italic;
609 class="tok-prop">line-height: class="tok-val">1.7;
610 }
611
612 /* Shake animation */
613 @keyframes shake {
614 0%,100% { class="tok-prop">transform: class="tok-val">translateX(0); }
615 20% { class="tok-prop">transform: class="tok-val">translateX(-8px); }
616 40% { class="tok-prop">transform: class="tok-val">translateX(8px); }
617 60% { class="tok-prop">transform: class="tok-val">translateX(-6px); }
618 80% { class="tok-prop">transform: class="tok-val">translateX(6px); }
619 }
620 .shake { class="tok-prop">animation: class="tok-val">shake 0.4s ease; }
621 class="tok-tag"></styleclass="tok-attr">class="tok-tag">>
622 class="tok-tag"></headclass="tok-attr">class="tok-tag">>
623 class="tok-tag"><bodyclass="tok-attr">class="tok-tag">>
624
625 <!-- Petals -->
626 class="tok-tag"><divclass="tok-attr"> id="petals"class="tok-tag">>class="tok-tag"></divclass="tok-attr">class="tok-tag">>
627
628 class="tok-tag"><divclass="tok-attr"> class="wrapper"class="tok-tag">>
629
630 <!-- ══ INTRO ══ -->
631 class="tok-tag"><divclass="tok-attr"> class="screen active" id="screen-intro"class="tok-tag">>
632 class="tok-tag"><divclass="tok-attr"> class="intro-deco"class="tok-tag">>✦ AlpacaViajes · Japonés · Nivel 1 ✦class="tok-tag"></divclass="tok-attr">class="tok-tag">>
633 class="tok-tag"><divclass="tok-attr"> class="intro-kanji"class="tok-tag">>桜class="tok-tag"></divclass="tok-attr">class="tok-tag">>
634 class="tok-tag"><h1class="tok-attr"> class="intro-title"class="tok-tag">>Una carta al samuráiclass="tok-tag"></h1class="tok-attr">class="tok-tag">>
635 class="tok-tag"><pclass="tok-attr"> class="intro-subtitle"class="tok-tag">>Una historia de amor escrita en japonésclass="tok-tag"></pclass="tok-attr">class="tok-tag">>
636
637 class="tok-tag"><divclass="tok-attr"> class="paper-card"class="tok-tag">>
638 class="tok-tag"><divclass="tok-attr"> style="class="tok-prop">display:class="tok-val">flex;class="tok-prop">align-items:class="tok-val">flex-start;class="tok-prop">gap:class="tok-val">16px;"class="tok-tag">>
639 class="tok-tag"><divclass="tok-attr"> class="char-portrait"class="tok-tag">>🌸class="tok-tag"></divclass="tok-attr">class="tok-tag">>
640 class="tok-tag"><divclass="tok-attr">class="tok-tag">>
641 class="tok-tag"><divclass="tok-attr"> class="char-name"class="tok-tag">>Hana · La doncellaclass="tok-tag"></divclass="tok-attr">class="tok-tag">>
642 class="tok-tag"><pclass="tok-attr"> class="dialogue-text"class="tok-tag">>
643 "Por favor... class="tok-tag"><strongclass="tok-attr">class="tok-tag">>necesito tu ayuda.class="tok-tag"></strongclass="tok-attr">class="tok-tag">>class="tok-tag"><brclass="tok-attr">class="tok-tag">>class="tok-tag"><brclass="tok-attr">class="tok-tag">>
644 Vi a un samurái cruzar el jardín del templo al amanecer.
645 Solo una vez. No sé su nombre, ni él sabe que existo.class="tok-tag"><brclass="tok-attr">class="tok-tag">>class="tok-tag"><brclass="tok-attr">class="tok-tag">>
646 Quiero escribirle una carta, pero no conozco bien su idioma.
647 ¿Me ayudas a encontrar las palabras?"
648 class="tok-tag"></pclass="tok-attr">class="tok-tag">>
649 class="tok-tag"></divclass="tok-attr">class="tok-tag">>
650 class="tok-tag"></divclass="tok-attr">class="tok-tag">>
651 class="tok-tag"></divclass="tok-attr">class="tok-tag">>
652
653 class="tok-tag"><buttonclass="tok-attr"> class="btn-primary" onclick="startLesson()"class="tok-tag">>✦ Ayudar a Hanaclass="tok-tag"></buttonclass="tok-attr">class="tok-tag">>
654 class="tok-tag"></divclass="tok-attr">class="tok-tag">>
655
656 <!-- ══ LESSON ══ -->
657 class="tok-tag"><divclass="tok-attr"> class="screen" id="screen-lesson"class="tok-tag">>
658 class="tok-tag"><divclass="tok-attr"> class="lesson-header"class="tok-tag">>
659 class="tok-tag"><divclass="tok-attr"> class="lesson-step" id="lesson-step"class="tok-tag">>Palabra 1 de 5class="tok-tag"></divclass="tok-attr">class="tok-tag">>
660 class="tok-tag"><divclass="tok-attr"> class="lesson-question" id="lesson-question"class="tok-tag">>Hana te pregunta...class="tok-tag"></divclass="tok-attr">class="tok-tag">>
661 class="tok-tag"></divclass="tok-attr">class="tok-tag">>
662
663 class="tok-tag"><divclass="tok-attr"> class="bubble-wrap"class="tok-tag">>
664 class="tok-tag"><divclass="tok-attr"> class="bubble-portrait"class="tok-tag">>🌸class="tok-tag"></divclass="tok-attr">class="tok-tag">>
665 class="tok-tag"><divclass="tok-attr"> class="bubble"class="tok-tag">>
666 class="tok-tag"><divclass="tok-attr"> class="bubble-name"class="tok-tag">>Hanaclass="tok-tag"></divclass="tok-attr">class="tok-tag">>
667 class="tok-tag"><divclass="tok-attr"> class="bubble-text" id="bubble-text"class="tok-tag">>...class="tok-tag"></divclass="tok-attr">class="tok-tag">>
668 class="tok-tag"></divclass="tok-attr">class="tok-tag">>
669 class="tok-tag"></divclass="tok-attr">class="tok-tag">>
670
671 class="tok-tag"><divclass="tok-attr"> class="flip-area" onclick="revealCard()"class="tok-tag">>
672 class="tok-tag"><divclass="tok-attr"> class="flip-inner" id="flip-inner"class="tok-tag">>
673 class="tok-tag"><divclass="tok-attr"> class="flip-face flip-front"class="tok-tag">>
674 class="tok-tag"><divclass="tok-attr"> class="flip-hint-emoji" id="flip-emoji"class="tok-tag">>🌸class="tok-tag"></divclass="tok-attr">class="tok-tag">>
675 class="tok-tag"><divclass="tok-attr"> class="flip-hint-word" id="flip-hint"class="tok-tag">>...class="tok-tag"></divclass="tok-attr">class="tok-tag">>
676 class="tok-tag"><divclass="tok-attr"> class="flip-tap"class="tok-tag">>toca para revelarclass="tok-tag"></divclass="tok-attr">class="tok-tag">>
677 class="tok-tag"></divclass="tok-attr">class="tok-tag">>
678 class="tok-tag"><divclass="tok-attr"> class="flip-face flip-back"class="tok-tag">>
679 class="tok-tag"><divclass="tok-attr"> class="flip-kanji" id="flip-kanji"class="tok-tag">>名前class="tok-tag"></divclass="tok-attr">class="tok-tag">>
680 class="tok-tag"><divclass="tok-attr"> class="flip-romaji" id="flip-romaji"class="tok-tag">>namaeclass="tok-tag"></divclass="tok-attr">class="tok-tag">>
681 class="tok-tag"><divclass="tok-attr"> class="flip-meaning" id="flip-meaning"class="tok-tag">>nombreclass="tok-tag"></divclass="tok-attr">class="tok-tag">>
682 class="tok-tag"><divclass="tok-attr"> class="flip-example" id="flip-example"class="tok-tag">>class="tok-tag"></divclass="tok-attr">class="tok-tag">>
683 class="tok-tag"></divclass="tok-attr">class="tok-tag">>
684 class="tok-tag"></divclass="tok-attr">class="tok-tag">>
685 class="tok-tag"></divclass="tok-attr">class="tok-tag">>
686
687 class="tok-tag"><divclass="tok-attr"> class="answer-row"class="tok-tag">>
688 class="tok-tag"><buttonclass="tok-attr"> class="btn-answer btn-forgot" id="btn-forgot" onclick="answer(false)" disabledclass="tok-tag">>✗ Lo olvidoclass="tok-tag"></buttonclass="tok-attr">class="tok-tag">>
689 class="tok-tag"><buttonclass="tok-attr"> class="btn-reveal" onclick="revealCard()"class="tok-tag">>↺ voltearclass="tok-tag"></buttonclass="tok-attr">class="tok-tag">>
690 class="tok-tag"><buttonclass="tok-attr"> class="btn-answer btn-knew" id="btn-knew" onclick="answer(true)" disabledclass="tok-tag">>✓ Lo recuerdoclass="tok-tag"></buttonclass="tok-attr">class="tok-tag">>
691 class="tok-tag"></divclass="tok-attr">class="tok-tag">>
692
693 class="tok-tag"><divclass="tok-attr"> class="progress-dots" id="progress-dots"class="tok-tag">>class="tok-tag"></divclass="tok-attr">class="tok-tag">>
694 class="tok-tag"></divclass="tok-attr">class="tok-tag">>
695
696 <!-- ══ LETTER ══ -->
697 class="tok-tag"><divclass="tok-attr"> class="screen" id="screen-letter"class="tok-tag">>
698 class="tok-tag"><divclass="tok-attr"> class="letter-wrap"class="tok-tag">>
699 class="tok-tag"><divclass="tok-attr"> class="letter-title"class="tok-tag">>✦ La carta de Hana ✦class="tok-tag"></divclass="tok-attr">class="tok-tag">>
700
701 class="tok-tag"><divclass="tok-attr"> class="letter-paper" id="letter-paper"class="tok-tag">>
702 class="tok-tag"><divclass="tok-attr"> class="letter-seal"class="tok-tag">>🌸class="tok-tag"></divclass="tok-attr">class="tok-tag">>
703 <!-- Lines injected by JS -->
704 class="tok-tag"></divclass="tok-attr">class="tok-tag">>
705
706 class="tok-tag"><divclass="tok-attr"> class="result-message" id="result-message"class="tok-tag">>
707 class="tok-tag"><divclass="tok-attr"> class="result-icon" id="res-icon"class="tok-tag">>💌class="tok-tag"></divclass="tok-attr">class="tok-tag">>
708 class="tok-tag"><divclass="tok-attr"> class="result-title-text" id="res-title"class="tok-tag">>La carta está listaclass="tok-tag"></divclass="tok-attr">class="tok-tag">>
709 class="tok-tag"><divclass="tok-attr"> class="result-sub" id="res-sub"class="tok-tag">>Hana puede enviársela al samurái...class="tok-tag"></divclass="tok-attr">class="tok-tag">>
710 class="tok-tag"></divclass="tok-attr">class="tok-tag">>
711
712 class="tok-tag"><buttonclass="tok-attr"> class="btn-primary" onclick="restartGame()"class="tok-tag">>↺ Jugar de nuevoclass="tok-tag"></buttonclass="tok-attr">class="tok-tag">>
713 class="tok-tag"></divclass="tok-attr">class="tok-tag">>
714 class="tok-tag"></divclass="tok-attr">class="tok-tag">>
715
716 class="tok-tag"></divclass="tok-attr">class="tok-tag">>
717
718 class="tok-tag"><scriptclass="tok-attr">class="tok-tag">>
719 // ── DATA ──
720 class="tok-kw">const lessons = [
721 {
722 class="tok-prop">bubble: class="tok-val">';¿Cómo se dice class="tok-tag"><emclass="tok-attr">class="tok-tag">>nombreclass="tok-tag"></emclass="tok-attr">class="tok-tag">>? Quiero saber cómo se llama...',
723 class="tok-prop">emoji: class="tok-val">';📛',
724 class="tok-prop">hint: class="tok-val">';"Cómo te llamas,\nquién eres tú"',
725 class="tok-prop">kanji: class="tok-val">';名前',
726 class="tok-prop">romaji: class="tok-val">';namae',
727 class="tok-prop">meaning: class="tok-val">';nombre',
728 class="tok-prop">example: class="tok-val">';私の名前は... = Mi nombre es...',
729 letter_class="tok-prop">jp: class="tok-val">';貴方の名前を教えてください。',
730 letter_class="tok-prop">romaji: class="tok-val">';Anata no namae wo oshiete kudasai.',
731 letter_class="tok-prop">es: class="tok-val">';"Por favor, dime tu nombre."'
732 },
733 {
734 class="tok-prop">bubble: class="tok-val">';¿Y cómo digo class="tok-tag"><emclass="tok-attr">class="tok-tag">>corazónclass="tok-tag"></emclass="tok-attr">class="tok-tag">>? Siento algo aquí adentro que no entiendo...',
735 class="tok-prop">emoji: class="tok-val">';💗',
736 class="tok-prop">hint: class="tok-val">';"Late dentro de ti,\nguarda lo que no se dice"',
737 class="tok-prop">kanji: class="tok-val">';心',
738 class="tok-prop">romaji: class="tok-val">';kokoro',
739 class="tok-prop">meaning: class="tok-val">';corazón / alma',
740 class="tok-prop">example: class="tok-val">';心が痛い = El corazón duele',
741 letter_class="tok-prop">jp: class="tok-val">';私の心はあなたを忘れられない。',
742 letter_class="tok-prop">romaji: class="tok-val">';Watashi no kokoro wa anata wo wasurenai.',
743 letter_class="tok-prop">es: class="tok-val">';"Mi corazón no puede olvidarte."'
744 },
745 {
746 class="tok-prop">bubble: class="tok-val">';¿Cómo digo que quiero class="tok-tag"><emclass="tok-attr">class="tok-tag">>verteclass="tok-tag"></emclass="tok-attr">class="tok-tag">>? Solo una vez más...',
747 class="tok-prop">emoji: class="tok-val">';👁️',
748 class="tok-prop">hint: class="tok-val">';"Deseo encontrarme,\nverte, estar cerca"',
749 class="tok-prop">kanji: class="tok-val">';会いたい',
750 class="tok-prop">romaji: class="tok-val">';aitai',
751 class="tok-prop">meaning: class="tok-val">';quiero verte',
752 class="tok-prop">example: class="tok-val">';会いたいです = Quiero verte (formal)',
753 letter_class="tok-prop">jp: class="tok-val">';もう一度、会いたいです。',
754 letter_class="tok-prop">romaji: class="tok-val">';Mou ichido, aitai desu.',
755 letter_class="tok-prop">es: class="tok-val">';"Quiero verte una vez más."'
756 },
757 {
758 class="tok-prop">bubble: class="tok-val">';¿Cómo pregunto si... si class="tok-tag"><emclass="tok-attr">class="tok-tag">>le gustoclass="tok-tag"></emclass="tok-attr">class="tok-tag">> a alguien? Es una pregunta difícil...',
759 class="tok-prop">emoji: class="tok-val">';🌸',
760 class="tok-prop">hint: class="tok-val">';"Sentir afecto,\n¿me quieres un poco?"',
761 class="tok-prop">kanji: class="tok-val">';好き',
762 class="tok-prop">romaji: class="tok-val">';suki',
763 class="tok-prop">meaning: class="tok-val">';gustar / querer',
764 class="tok-prop">example: class="tok-val">';好きですか?= ¿Te gusto? / ¿Me quieres?',
765 letter_class="tok-prop">jp: class="tok-val">';私のことが好きですか?',
766 letter_class="tok-prop">romaji: class="tok-val">';Watashi no koto ga suki desu ka?',
767 letter_class="tok-prop">es: class="tok-val">';"¿Acaso te gusto?"'
768 },
769 {
770 class="tok-prop">bubble: class="tok-val">';Y... ¿cómo digo class="tok-tag"><emclass="tok-attr">class="tok-tag">>de verdadclass="tok-tag"></emclass="tok-attr">class="tok-tag">>? Quiero que sepa que esto es real.',
771 class="tok-prop">emoji: class="tok-val">';✨',
772 class="tok-prop">hint: class="tok-val">';"Sin mentiras,\nsin máscaras, verdad"',
773 class="tok-prop">kanji: class="tok-val">';本当',
774 class="tok-prop">romaji: class="tok-val">';hontō',
775 class="tok-prop">meaning: class="tok-val">';verdad / de verdad',
776 class="tok-prop">example: class="tok-val">';本当ですか?= ¿De verdad? / ¿Es cierto?',
777 letter_class="tok-prop">jp: class="tok-val">';本当のことを話してください。',
778 letter_class="tok-prop">romaji: class="tok-val">';Hontō no koto wo hanashite kudasai.',
779 letter_class="tok-prop">es: class="tok-val">';"Por favor, dime la verdad."'
780 }
781 ];
782
783 class="tok-kw">let current = 0;
784 class="tok-kw">let revealed = false;
785 class="tok-kw">let score = 0;
786
787 // ── PETALS ──
788 class="tok-kw">function createPetals() {
789 class="tok-kw">const container = document.getElementById('petals');
790 class="tok-kw">const colors = ['#d4849a','#f0b8c8','#e8a0b4','#c87090','#f8d0e0'];
791 class="tok-kw">for (class="tok-kw">let i = 0; i < 18; i++) {
792 class="tok-kw">const p = document.createElement('div');
793 p.className = 'petal';
794 p.style.cssText = `
795 class="tok-prop">left: class="tok-val">${Math.random()*100}vw;
796 class="tok-prop">background: class="tok-val">${colors[Math.floor(Math.random()*colors.length)]};
797 class="tok-prop">animation-duration: class="tok-val">${6 + Math.random()*8}s;
798 class="tok-prop">animation-delay: class="tok-val">${Math.random()*10}s;
799 class="tok-prop">width: class="tok-val">${6+Math.random()*6}px;
800 class="tok-prop">height: class="tok-val">${8+Math.random()*6}px;
801 class="tok-prop">opacity: class="tok-val">0;
802 class="tok-prop">transform: class="tok-val">rotate(${Math.random()*360}deg);
803 `;
804 container.appendChild(p);
805 }
806 }
807
808 // ── NAVIGATION ──
809 class="tok-kw">function showScreen(id) {
810 document.querySelectorAll('.screen').forEach(s => s.classList.remove('active'));
811 document.getElementById(id).classList.add('active');
812 }
813
814 class="tok-kw">function startLesson() {
815 current = 0; score = 0; revealed = false;
816 buildDots();
817 loadLesson(0);
818 showScreen('screen-lesson');
819 }
820
821 // ── LESSON ──
822 class="tok-kw">function buildDots() {
823 class="tok-kw">const wrap = document.getElementById('progress-dots');
824 wrap.innerHTML = '';
825 lessons.forEach((_, i) => {
826 class="tok-kw">const d = document.createElement('div');
827 d.className = 'dot' + (i === 0 ? ' current' : '');
828 d.id = 'dot-' + i;
829 wrap.appendChild(d);
830 });
831 }
832
833 class="tok-kw">function loadLesson(idx) {
834 class="tok-kw">const l = lessons[idx];
835 revealed = false;
836
837 document.getElementById('lesson-step').textContent = `Palabra ${idx+1} de ${lessons.length}`;
838 document.getElementById('bubble-text').innerHTML = l.bubble;
839 document.getElementById('flip-emoji').textContent = l.emoji;
840 document.getElementById('flip-hint').textContent = l.hint;
841 document.getElementById('flip-kanji').textContent = l.kanji;
842 document.getElementById('flip-romaji').textContent = l.romaji;
843 document.getElementById('flip-meaning').textContent = l.meaning;
844 document.getElementById('flip-example').textContent = l.example;
845
846 document.getElementById('flip-inner').classList.remove('flipped');
847 document.getElementById('btn-knew').disabled = true;
848 document.getElementById('btn-forgot').disabled = true;
849
850 // dots
851 lessons.forEach((_, i) => {
852 class="tok-kw">const d = document.getElementById('dot-' + i);
853 class="tok-kw">if (!d) class="tok-kw">return;
854 d.className = 'dot' + (i < idx ? ' done' : i === idx ? ' current' : '');
855 });
856 }
857
858 class="tok-kw">function revealCard() {
859 class="tok-kw">if (revealed) class="tok-kw">return;
860 revealed = true;
861 document.getElementById('flip-inner').classList.add('flipped');
862 document.getElementById('btn-knew').disabled = false;
863 document.getElementById('btn-forgot').disabled = false;
864 }
865
866 class="tok-kw">function answer(knew) {
867 class="tok-kw">if (!revealed) class="tok-kw">return;
868 class="tok-kw">if (knew) score++;
869
870 class="tok-kw">const area = document.querySelector('.flip-area');
871 class="tok-kw">if (!knew) {
872 area.classList.add('shake');
873 setTimeout(() => area.classList.remove('shake'), 450);
874 }
875
876 current++;
877 class="tok-kw">if (current >= lessons.length) {
878 setTimeout(showLetter, 400);
879 } class="tok-kw">else {
880 setTimeout(() => loadLesson(current), 350);
881 }
882 }
883
884 // ── LETTER ──
885 class="tok-kw">function showLetter() {
886 class="tok-kw">const paper = document.getElementById('letter-paper');
887 paper.innerHTML = 'class="tok-tag"><divclass="tok-attr"> class="letter-seal"class="tok-tag">>🌸class="tok-tag"></divclass="tok-attr">class="tok-tag">>';
888
889 lessons.forEach((l, i) => {
890 class="tok-kw">const line = document.createElement('div');
891 line.className = 'letter-line';
892 line.style.animationDelay = (0.3 + i * 0.35) + 's';
893 line.innerHTML = `
894 class="tok-tag"><divclass="tok-attr"> class="letter-jp"class="tok-tag">>${l.letter_jp}class="tok-tag"></divclass="tok-attr">class="tok-tag">>
895 class="tok-tag"><divclass="tok-attr"> class="letter-translation"class="tok-tag">>${l.letter_es}class="tok-tag"></divclass="tok-attr">class="tok-tag">>
896 `;
897 paper.appendChild(line);
898
899 class="tok-kw">const sub = document.createElement('div');
900 sub.style.cssText = `class="tok-prop">font-family:class="tok-val">';Noto Sans JP',sans-serif;class="tok-prop">font-size:class="tok-val">10px;class="tok-prop">color:class="tok-val">#8fa8b0;class="tok-prop">letter-spacing:class="tok-val">1px;class="tok-prop">margin-bottom:class="tok-val">18px;class="tok-prop">padding-left:class="tok-val">4px;class="tok-prop">opacity:class="tok-val">0;class="tok-prop">animation:class="tok-val">lineReveal 0.5s ease ${0.3 + i * 0.35 + 0.1}s forwards;`;
901 sub.textContent = l.letter_romaji;
902 paper.appendChild(sub);
903 });
904
905 class="tok-kw">const sig = document.createElement('div');
906 sig.className = 'letter-signature';
907 sig.textContent = '花より — Hana';
908 paper.appendChild(sig);
909
910 // Result message
911 class="tok-kw">const pct = Math.round((score / lessons.length) * 100);
912 class="tok-kw">let icon, title, sub;
913 class="tok-kw">if (pct === 100) {
914 icon = '🌸'; title = '¡Hana está radiante!';
915 sub = 'Aprendiste todas las palabras. La carta quedó perfecta. Ahora... solo queda esperar su respuesta.';
916 } class="tok-kw">else class="tok-kw">if (pct >= 60) {
917 icon = '💌'; title = 'La carta está lista';
918 sub = 'Hana puede enviarla. Algunas palabras necesitan más práctica, pero el corazón se entiende en cualquier idioma.';
919 } class="tok-kw">else {
920 icon = '🌱'; title = 'Hana necesita más ayuda';
921 sub = 'Todavía hay palabras que aprender. ¿Volvemos a intentarlo juntos?';
922 }
923
924 document.getElementById('res-icon').textContent = icon;
925 document.getElementById('res-title').textContent = title;
926 document.getElementById('res-sub').textContent = sub;
927
928 showScreen('screen-letter');
929 }
930
931 class="tok-kw">function restartGame() {
932 showScreen('screen-intro');
933 }
934
935 // ── INIT ──
936 createPetals();
937 class="tok-tag"></scriptclass="tok-attr">class="tok-tag">>
938 class="tok-tag"></bodyclass="tok-attr">class="tok-tag">>
939 class="tok-tag"></htmlclass="tok-attr">class="tok-tag">>
940