@jjlmoya/utils-games-development 1.65.0 → 1.67.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (77) hide show
  1. package/package.json +67 -67
  2. package/scripts/postinstall.mjs +27 -27
  3. package/src/category/GamesCategorySEO.astro +19 -19
  4. package/src/category/i18n/de.ts +15 -15
  5. package/src/category/i18n/en.ts +15 -15
  6. package/src/category/i18n/es.ts +15 -15
  7. package/src/category/i18n/fr.ts +15 -15
  8. package/src/category/i18n/id.ts +10 -10
  9. package/src/category/i18n/it.ts +10 -10
  10. package/src/category/i18n/ja.ts +10 -10
  11. package/src/category/i18n/ko.ts +10 -10
  12. package/src/category/i18n/nl.ts +10 -10
  13. package/src/category/i18n/pl.ts +10 -10
  14. package/src/category/i18n/pt.ts +10 -10
  15. package/src/category/i18n/ru.ts +10 -10
  16. package/src/category/i18n/sv.ts +10 -10
  17. package/src/category/i18n/tr.ts +10 -10
  18. package/src/category/i18n/zh.ts +10 -10
  19. package/src/category/seo.astro +15 -15
  20. package/src/components/PreviewNavSidebar.astro +116 -116
  21. package/src/components/PreviewToolbar.astro +143 -143
  22. package/src/data.ts +11 -11
  23. package/src/env.d.ts +5 -5
  24. package/src/index.ts +20 -20
  25. package/src/layouts/PreviewLayout.astro +122 -122
  26. package/src/pages/[locale]/[slug].astro +165 -165
  27. package/src/pages/[locale].astro +250 -250
  28. package/src/pages/index.astro +4 -4
  29. package/src/tests/bibliography_wellformed_export.test.ts +46 -0
  30. package/src/tests/category_seo_quality.test.ts +74 -0
  31. package/src/tests/diacritics_density.test.ts +118 -118
  32. package/src/tests/faq_count.test.ts +19 -19
  33. package/src/tests/i18n_coverage.test.ts +36 -36
  34. package/src/tests/inverted_punctuation.test.ts +84 -84
  35. package/src/tests/mocks/astro_mock.js +2 -2
  36. package/src/tests/no_en_dash.test.ts +70 -70
  37. package/src/tests/no_h1_in_components.test.ts +48 -48
  38. package/src/tests/pagespeed_best_practices.test.ts +198 -198
  39. package/src/tests/qa-test-helpers.ts +32 -32
  40. package/src/tests/qa_bibliography_links.test.ts +41 -41
  41. package/src/tests/qa_claim_evidence.test.ts +69 -69
  42. package/src/tests/qa_logic_reference_coverage.test.ts +46 -46
  43. package/src/tests/qa_runtime_i18n.test.ts +100 -100
  44. package/src/tests/schemas_fulfillment.test.ts +23 -23
  45. package/src/tests/script_density.test.ts +94 -94
  46. package/src/tests/seo_length.test.ts +23 -23
  47. package/src/tests/seo_wellformed_export.test.ts +65 -0
  48. package/src/tests/slug_language_code_format.test.ts +23 -23
  49. package/src/tests/slug_uniqueness.test.ts +80 -80
  50. package/src/tests/title_quality.test.ts +56 -56
  51. package/src/tool/audioLoopPointFinder/audio-loop-point-finder.css +322 -322
  52. package/src/tool/audioLoopPointFinder/client.ts +262 -262
  53. package/src/tool/damageFormulaLab/bibliography.astro +3 -21
  54. package/src/tool/damageFormulaLab/seo.astro +7 -5
  55. package/src/tool/gameDeltaTimeFixedTimestepLab/bibliography.astro +3 -19
  56. package/src/tool/hitboxHurtboxAnimator/hitbox-hurtbox-animator.css +614 -614
  57. package/src/tool/hitboxHurtboxAnimator/seo.astro +7 -5
  58. package/src/tool/saveFileEditor/component.astro +351 -351
  59. package/src/tool/saveFileEditor/game-save-file-editor.css +250 -250
  60. package/src/tool/spriteSheetPacker/app-client.ts +248 -248
  61. package/src/tool/spriteSheetPacker/bibliography.ts +12 -12
  62. package/src/tool/spriteSheetPacker/component.astro +229 -229
  63. package/src/tool/spriteSheetPacker/dropzone-client.ts +55 -55
  64. package/src/tool/spriteSheetPacker/entry.ts +28 -28
  65. package/src/tool/spriteSheetPacker/exporter.ts +116 -116
  66. package/src/tool/spriteSheetPacker/extractor-client.ts +127 -127
  67. package/src/tool/spriteSheetPacker/flipbook-client.ts +60 -60
  68. package/src/tool/spriteSheetPacker/logic.test.ts +155 -155
  69. package/src/tool/spriteSheetPacker/logic.ts +32 -32
  70. package/src/tool/spriteSheetPacker/packer-core.ts +121 -121
  71. package/src/tool/spriteSheetPacker/packer-ui.ts +86 -86
  72. package/src/tool/spriteSheetPacker/sprite-sheet-packer.css +578 -578
  73. package/src/tool/spriteSheetPacker/types.ts +89 -89
  74. package/src/tool/spriteSheetPacker/ui.ts +42 -42
  75. package/src/tool/steamCapsuleGenerator/index.ts +9 -9
  76. package/src/tool/steamCapsuleGenerator/validation.ts +14 -14
  77. package/src/types.ts +72 -72
@@ -1,578 +1,578 @@
1
- .ssp-container {
2
- width: 100%;
3
- max-width: 1200px;
4
- margin: 0 auto;
5
- color: var(--text-base, #1e293b);
6
- position: relative;
7
- }
8
-
9
- .theme-dark .ssp-container {
10
- color: var(--text-base, #f8fafc);
11
- }
12
-
13
- .ssp-main-card {
14
- background: var(--bg-surface, #fff);
15
- border: 1px solid var(--border-base, #cbd5e1);
16
- border-radius: 16px;
17
- overflow: hidden;
18
- box-shadow: 0 10px 35px rgba(0, 0, 0, 0.08);
19
- display: flex;
20
- flex-direction: column;
21
- position: relative;
22
- }
23
-
24
- .theme-dark .ssp-main-card {
25
- background: var(--bg-surface, #090d16);
26
- border-color: var(--border-base, #1e293b);
27
- box-shadow: 0 10px 35px rgba(0, 0, 0, 0.4);
28
- }
29
-
30
- .ssp-header-tabs {
31
- display: flex;
32
- background: rgba(148, 163, 184, 0.08);
33
- border-bottom: 1px solid var(--border-base, #e2e8f0);
34
- padding: 0.5rem 0.5rem 0;
35
- gap: 0.5rem;
36
- }
37
-
38
- .theme-dark .ssp-header-tabs {
39
- background: #0f172a;
40
- border-color: #1e293b;
41
- }
42
-
43
- .ssp-tab-btn {
44
- flex: 1;
45
- padding: 0.85rem 1.5rem;
46
- border: none;
47
- border-radius: 10px 10px 0 0;
48
- background: transparent;
49
- color: inherit;
50
- font-weight: 600;
51
- font-size: 0.95rem;
52
- cursor: pointer;
53
- transition: all 0.2s ease;
54
- opacity: 0.65;
55
- }
56
-
57
- .ssp-tab-btn.active {
58
- background: var(--bg-surface, #fff);
59
- color: var(--color-primary, #4f46e5);
60
- opacity: 1;
61
- border: 1px solid var(--border-base, #cbd5e1);
62
- border-bottom: 1px solid var(--bg-surface, #fff);
63
- margin-bottom: -1px;
64
- }
65
-
66
- .theme-dark .ssp-tab-btn.active {
67
- background: var(--bg-surface, #090d16);
68
- color: var(--color-primary-light, #818cf8);
69
- border-color: #1e293b;
70
- border-bottom-color: var(--bg-surface, #090d16);
71
- }
72
-
73
- .ssp-body-grid {
74
- display: grid;
75
- grid-template-columns: 1fr;
76
- padding: 1.5rem;
77
- gap: 1.5rem;
78
- }
79
-
80
- @media (min-width: 900px) {
81
- .ssp-body-grid {
82
- grid-template-columns: 340px 1fr;
83
- }
84
- }
85
-
86
- .ssp-sidebar-section {
87
- display: flex;
88
- flex-direction: column;
89
- gap: 1.25rem;
90
- padding-right: 0;
91
- }
92
-
93
- @media (min-width: 900px) {
94
- .ssp-sidebar-section {
95
- padding-right: 1.5rem;
96
- border-right: 1px solid var(--border-base, #e2e8f0);
97
- }
98
-
99
- .theme-dark .ssp-sidebar-section {
100
- border-color: #1e293b;
101
- }
102
- }
103
-
104
- .ssp-main-section {
105
- display: flex;
106
- flex-direction: column;
107
- gap: 1.25rem;
108
- }
109
-
110
- .ssp-dropzone {
111
- border: 2px dashed var(--color-primary-light, #818cf8);
112
- border-radius: 12px;
113
- padding: 1.5rem 1rem;
114
- text-align: center;
115
- background: rgba(129, 140, 248, 0.05);
116
- cursor: pointer;
117
- transition: all 0.2s ease;
118
- }
119
-
120
- .ssp-dropzone:hover,
121
- .ssp-dropzone.dragover {
122
- background: rgba(129, 140, 248, 0.12);
123
- border-color: var(--color-primary, #6366f1);
124
- }
125
-
126
- .ssp-drop-title {
127
- font-weight: 700;
128
- font-size: 1rem;
129
- margin-bottom: 0.25rem;
130
- }
131
-
132
- .ssp-drop-sub {
133
- font-size: 0.8rem;
134
- opacity: 0.7;
135
- }
136
-
137
- .ssp-file-input {
138
- display: none;
139
- }
140
-
141
- .ssp-presets-row {
142
- display: flex;
143
- gap: 0.4rem;
144
- flex-wrap: wrap;
145
- }
146
-
147
- .ssp-chip-btn {
148
- flex: 1;
149
- min-width: 85px;
150
- padding: 0.45rem 0.6rem;
151
- font-size: 0.75rem;
152
- font-weight: 600;
153
- border-radius: 6px;
154
- border: 1px solid rgba(129, 140, 248, 0.3);
155
- background: rgba(129, 140, 248, 0.08);
156
- color: inherit;
157
- cursor: pointer;
158
- transition: all 0.15s ease;
159
- text-align: center;
160
- }
161
-
162
- .ssp-chip-btn:hover {
163
- background: rgba(129, 140, 248, 0.2);
164
- border-color: var(--color-primary, #6366f1);
165
- }
166
-
167
- .ssp-chip-btn.active {
168
- background: linear-gradient(135deg, #6366f1, #4f46e5);
169
- color: var(--text-on-primary, #fff);
170
- border-color: var(--color-primary, #6366f1);
171
- box-shadow: 0 2px 8px rgba(99, 102, 241, 0.3);
172
- }
173
-
174
- .ssp-controls-list {
175
- display: flex;
176
- flex-direction: column;
177
- gap: 1rem;
178
- }
179
-
180
- .ssp-control-group {
181
- display: flex;
182
- flex-direction: column;
183
- gap: 0.4rem;
184
- }
185
-
186
- .ssp-label {
187
- font-size: 0.85rem;
188
- font-weight: 600;
189
- display: flex;
190
- justify-content: space-between;
191
- }
192
-
193
- .ssp-stepper-box {
194
- display: flex;
195
- align-items: center;
196
- gap: 0.4rem;
197
- width: 100%;
198
- }
199
-
200
- .ssp-step-btn {
201
- width: 32px;
202
- height: 32px;
203
- border-radius: 6px;
204
- border: 1px solid var(--border-base, #cbd5e1);
205
- background: rgba(148, 163, 184, 0.1);
206
- color: inherit;
207
- font-weight: 700;
208
- font-size: 1rem;
209
- cursor: pointer;
210
- display: flex;
211
- align-items: center;
212
- justify-content: center;
213
- transition: background 0.15s ease, transform 0.1s ease;
214
- flex-shrink: 0;
215
- }
216
-
217
- .theme-dark .ssp-step-btn {
218
- border-color: #334155;
219
- }
220
-
221
- .ssp-step-btn:hover {
222
- background: rgba(99, 102, 241, 0.2);
223
- border-color: var(--color-primary, #6366f1);
224
- }
225
-
226
- .ssp-step-btn:active {
227
- transform: scale(0.92);
228
- }
229
-
230
- .ssp-slider {
231
- flex: 1;
232
- accent-color: var(--color-primary, #6366f1);
233
- }
234
-
235
- .ssp-select,
236
- .ssp-input {
237
- width: 100%;
238
- padding: 0.6rem 0.8rem;
239
- border-radius: 8px;
240
- border: 1px solid var(--border-base, #cbd5e1);
241
- background: var(--bg-surface, #fff);
242
- color: inherit;
243
- font-size: 0.9rem;
244
- }
245
-
246
- .theme-dark .ssp-select,
247
- .theme-dark .ssp-input {
248
- background: #1e293b;
249
- border-color: #334155;
250
- }
251
-
252
- .ssp-toggle-group {
253
- display: flex;
254
- align-items: center;
255
- justify-content: space-between;
256
- padding: 0.3rem 0;
257
- }
258
-
259
- .ssp-toggle-input {
260
- width: 1.25rem;
261
- height: 1.25rem;
262
- accent-color: var(--color-primary, #6366f1);
263
- cursor: pointer;
264
- }
265
-
266
- .ssp-btn-row {
267
- display: flex;
268
- gap: 0.5rem;
269
- flex-wrap: wrap;
270
- }
271
-
272
- .ssp-btn {
273
- flex: 1;
274
- min-width: 110px;
275
- padding: 0.7rem 0.9rem;
276
- border-radius: 8px;
277
- border: none;
278
- font-weight: 600;
279
- font-size: 0.88rem;
280
- cursor: pointer;
281
- transition: transform 0.15s ease, opacity 0.15s ease, background 0.2s ease;
282
- display: inline-flex;
283
- align-items: center;
284
- justify-content: center;
285
- gap: 0.5rem;
286
- }
287
-
288
- .ssp-btn:hover {
289
- transform: translateY(-1px);
290
- }
291
-
292
- .ssp-btn:active {
293
- transform: scale(0.96);
294
- }
295
-
296
- .ssp-btn-primary {
297
- background: linear-gradient(135deg, #6366f1, #4f46e5);
298
- color: var(--text-on-primary, #fff);
299
- }
300
-
301
- .ssp-btn-secondary {
302
- background: rgba(148, 163, 184, 0.12);
303
- color: inherit;
304
- border: 1px solid var(--border-base, #cbd5e1);
305
- }
306
-
307
- .theme-dark .ssp-btn-secondary {
308
- border-color: #334155;
309
- }
310
-
311
- .ssp-btn-danger {
312
- background: #dc2626;
313
- color: var(--text-on-primary, #fff);
314
- }
315
-
316
- .ssp-btn-success {
317
- background: #047857;
318
- color: var(--text-on-primary, #fff);
319
- border-color: #047857;
320
- }
321
-
322
- .ssp-stats-grid {
323
- display: grid;
324
- grid-template-columns: repeat(auto-fit, minmax(110px, 1fr));
325
- gap: 0.75rem;
326
- }
327
-
328
- .ssp-stat-badge {
329
- background: rgba(99, 102, 241, 0.08);
330
- border: 1px solid rgba(99, 102, 241, 0.2);
331
- border-radius: 10px;
332
- padding: 0.6rem 0.75rem;
333
- text-align: center;
334
- }
335
-
336
- .ssp-stat-val {
337
- font-size: 1.1rem;
338
- font-weight: 700;
339
- color: var(--color-primary, #6366f1);
340
- }
341
-
342
- .theme-dark .ssp-stat-val {
343
- color: var(--color-primary-light, #818cf8);
344
- }
345
-
346
- .ssp-stat-lbl {
347
- font-size: 0.75rem;
348
- opacity: 0.8;
349
- }
350
-
351
- .ssp-canvas-wrapper {
352
- width: 100%;
353
- height: 380px;
354
- overflow: auto;
355
- border-radius: 12px;
356
- background-image: linear-gradient(45deg, #cbd5e1 25%, transparent 25%),
357
- linear-gradient(-45deg, #cbd5e1 25%, transparent 25%),
358
- linear-gradient(45deg, transparent 75%, #cbd5e1 75%),
359
- linear-gradient(-45deg, transparent 75%, #cbd5e1 75%);
360
- background-size: 16px 16px;
361
- background-position: 0 0, 0 8px, 8px -8px, -8px 0;
362
- display: flex;
363
- align-items: center;
364
- justify-content: center;
365
- padding: 1rem;
366
- border: 1px solid var(--border-base, #e2e8f0);
367
- box-sizing: border-box;
368
- }
369
-
370
- .theme-dark .ssp-canvas-wrapper {
371
- background-image: linear-gradient(45deg, #1e293b 25%, transparent 25%),
372
- linear-gradient(-45deg, #1e293b 25%, transparent 25%),
373
- linear-gradient(45deg, transparent 75%, #1e293b 75%),
374
- linear-gradient(-45deg, transparent 75%, #1e293b 75%);
375
- border-color: #1e293b;
376
- }
377
-
378
- .ssp-canvas {
379
- max-width: 100%;
380
- max-height: 100%;
381
- object-fit: contain;
382
- border-radius: 4px;
383
- box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
384
- image-rendering: pixelated;
385
- }
386
-
387
- .ssp-flipbook-box {
388
- display: flex;
389
- flex-direction: column;
390
- gap: 0.75rem;
391
- padding: 1rem;
392
- background: rgba(99, 102, 241, 0.04);
393
- border-radius: 12px;
394
- border: 1px solid rgba(99, 102, 241, 0.18);
395
- }
396
-
397
- .ssp-flipbook-header {
398
- font-weight: 700;
399
- font-size: 0.9rem;
400
- }
401
-
402
- .ssp-flipbook-body {
403
- display: flex;
404
- align-items: center;
405
- gap: 1.25rem;
406
- flex-wrap: wrap;
407
- }
408
-
409
- .ssp-flipbook-canvas {
410
- width: 100px;
411
- height: 100px;
412
- image-rendering: pixelated;
413
- background: rgba(0, 0, 0, 0.2);
414
- border-radius: 8px;
415
- border: 1px solid rgba(255, 255, 255, 0.1);
416
- }
417
-
418
- .ssp-flipbook-controls {
419
- flex: 1;
420
- min-width: 200px;
421
- display: flex;
422
- flex-direction: column;
423
- gap: 0.75rem;
424
- }
425
-
426
- .ssp-code-container {
427
- display: flex;
428
- flex-direction: column;
429
- border-radius: 10px;
430
- overflow: hidden;
431
- border: 1px solid var(--border-base, #e2e8f0);
432
- background: var(--bg-surface-secondary, #f8fafc);
433
- }
434
-
435
- .theme-dark .ssp-code-container {
436
- border-color: #1e293b;
437
- background: #090d16;
438
- }
439
-
440
- .ssp-code-header {
441
- display: flex;
442
- align-items: center;
443
- justify-content: space-between;
444
- background: rgba(148, 163, 184, 0.12);
445
- padding: 0.6rem 0.85rem;
446
- border-bottom: 1px solid var(--border-base, #e2e8f0);
447
- }
448
-
449
- .theme-dark .ssp-code-header {
450
- background: #0f172a;
451
- border-color: #1e293b;
452
- }
453
-
454
- .ssp-code-title {
455
- font-size: 0.82rem;
456
- font-weight: 600;
457
- color: var(--text-base, #334155);
458
- }
459
-
460
- .theme-dark .ssp-code-title {
461
- color: var(--text-muted, #94a3b8);
462
- }
463
-
464
- .ssp-copy-btn {
465
- background: rgba(99, 102, 241, 0.1);
466
- border: 1px solid rgba(99, 102, 241, 0.3);
467
- color: var(--color-primary, #4f46e5);
468
- padding: 0.35rem 0.75rem;
469
- border-radius: 6px;
470
- font-size: 0.78rem;
471
- font-weight: 600;
472
- cursor: pointer;
473
- transition: all 0.15s ease;
474
- }
475
-
476
- .theme-dark .ssp-copy-btn {
477
- background: rgba(56, 189, 248, 0.12);
478
- border-color: rgba(56, 189, 248, 0.3);
479
- color: var(--color-cyan, #38bdf8);
480
- }
481
-
482
- .ssp-copy-btn:hover {
483
- background: rgba(99, 102, 241, 0.2);
484
- }
485
-
486
- .theme-dark .ssp-copy-btn:hover {
487
- background: rgba(56, 189, 248, 0.25);
488
- }
489
-
490
- .ssp-copy-btn:active {
491
- transform: scale(0.95);
492
- }
493
-
494
- .ssp-code-block {
495
- width: 100%;
496
- margin: 0;
497
- background: #f1f5f9;
498
- color: var(--text-base, #0f172a);
499
- font-size: 0.82rem;
500
- padding: 0.85rem 1rem;
501
- overflow-x: auto;
502
- white-space: pre-wrap;
503
- word-break: break-all;
504
- }
505
-
506
- .theme-dark .ssp-code-block {
507
- background: #070a12;
508
- color: var(--color-cyan, #38bdf8);
509
- }
510
-
511
- .ssp-toast {
512
- position: fixed;
513
- bottom: 2rem;
514
- right: 2rem;
515
- background: #047857;
516
- color: var(--text-on-primary, #fff);
517
- padding: 0.75rem 1.25rem;
518
- border-radius: 8px;
519
- font-weight: 600;
520
- box-shadow: 0 4px 14px rgba(16, 185, 129, 0.4);
521
- opacity: 0;
522
- transform: translateY(10px);
523
- pointer-events: none;
524
- transition: opacity 0.3s ease, transform 0.3s ease;
525
- z-index: 1000;
526
- }
527
-
528
- .ssp-toast.show {
529
- opacity: 1;
530
- transform: translateY(0);
531
- }
532
-
533
- .ssp-particle-container {
534
- position: fixed;
535
- top: 0;
536
- left: 0;
537
- width: 100vw;
538
- height: 100vh;
539
- pointer-events: none;
540
- z-index: 2000;
541
- }
542
-
543
- .ssp-particle {
544
- position: absolute;
545
- font-size: 0.75rem;
546
- font-weight: 800;
547
- color: var(--color-primary, #4f46e5);
548
- background: rgba(255, 255, 255, 0.95);
549
- border: 1px solid var(--color-primary, #6366f1);
550
- border-radius: 4px;
551
- padding: 0.2rem 0.5rem;
552
- box-shadow: 0 0 10px rgba(99, 102, 241, 0.3);
553
- animation: ssp-particle-float 1s forwards ease-out;
554
- }
555
-
556
- .theme-dark .ssp-particle {
557
- color: var(--color-cyan, #38bdf8);
558
- background: rgba(15, 23, 42, 0.9);
559
- border-color: #38bdf8;
560
- box-shadow: 0 0 10px rgba(56, 189, 248, 0.5);
561
- }
562
-
563
- @keyframes ssp-particle-float {
564
- 0% {
565
- opacity: 1;
566
- transform: translate(-50%, -50%) scale(0.8);
567
- }
568
-
569
- 50% {
570
- opacity: 1;
571
- transform: translate(-50%, -120%) scale(1.1);
572
- }
573
-
574
- 100% {
575
- opacity: 0;
576
- transform: translate(-50%, -180%) scale(0.9);
577
- }
578
- }
1
+ .ssp-container {
2
+ width: 100%;
3
+ max-width: 1200px;
4
+ margin: 0 auto;
5
+ color: var(--text-base, #1e293b);
6
+ position: relative;
7
+ }
8
+
9
+ .theme-dark .ssp-container {
10
+ color: var(--text-base, #f8fafc);
11
+ }
12
+
13
+ .ssp-main-card {
14
+ background: var(--bg-surface, #fff);
15
+ border: 1px solid var(--border-base, #cbd5e1);
16
+ border-radius: 16px;
17
+ overflow: hidden;
18
+ box-shadow: 0 10px 35px rgba(0, 0, 0, 0.08);
19
+ display: flex;
20
+ flex-direction: column;
21
+ position: relative;
22
+ }
23
+
24
+ .theme-dark .ssp-main-card {
25
+ background: var(--bg-surface, #090d16);
26
+ border-color: var(--border-base, #1e293b);
27
+ box-shadow: 0 10px 35px rgba(0, 0, 0, 0.4);
28
+ }
29
+
30
+ .ssp-header-tabs {
31
+ display: flex;
32
+ background: rgba(148, 163, 184, 0.08);
33
+ border-bottom: 1px solid var(--border-base, #e2e8f0);
34
+ padding: 0.5rem 0.5rem 0;
35
+ gap: 0.5rem;
36
+ }
37
+
38
+ .theme-dark .ssp-header-tabs {
39
+ background: #0f172a;
40
+ border-color: #1e293b;
41
+ }
42
+
43
+ .ssp-tab-btn {
44
+ flex: 1;
45
+ padding: 0.85rem 1.5rem;
46
+ border: none;
47
+ border-radius: 10px 10px 0 0;
48
+ background: transparent;
49
+ color: inherit;
50
+ font-weight: 600;
51
+ font-size: 0.95rem;
52
+ cursor: pointer;
53
+ transition: all 0.2s ease;
54
+ opacity: 0.65;
55
+ }
56
+
57
+ .ssp-tab-btn.active {
58
+ background: var(--bg-surface, #fff);
59
+ color: var(--color-primary, #4f46e5);
60
+ opacity: 1;
61
+ border: 1px solid var(--border-base, #cbd5e1);
62
+ border-bottom: 1px solid var(--bg-surface, #fff);
63
+ margin-bottom: -1px;
64
+ }
65
+
66
+ .theme-dark .ssp-tab-btn.active {
67
+ background: var(--bg-surface, #090d16);
68
+ color: var(--color-primary-light, #818cf8);
69
+ border-color: #1e293b;
70
+ border-bottom-color: var(--bg-surface, #090d16);
71
+ }
72
+
73
+ .ssp-body-grid {
74
+ display: grid;
75
+ grid-template-columns: 1fr;
76
+ padding: 1.5rem;
77
+ gap: 1.5rem;
78
+ }
79
+
80
+ @media (min-width: 900px) {
81
+ .ssp-body-grid {
82
+ grid-template-columns: 340px 1fr;
83
+ }
84
+ }
85
+
86
+ .ssp-sidebar-section {
87
+ display: flex;
88
+ flex-direction: column;
89
+ gap: 1.25rem;
90
+ padding-right: 0;
91
+ }
92
+
93
+ @media (min-width: 900px) {
94
+ .ssp-sidebar-section {
95
+ padding-right: 1.5rem;
96
+ border-right: 1px solid var(--border-base, #e2e8f0);
97
+ }
98
+
99
+ .theme-dark .ssp-sidebar-section {
100
+ border-color: #1e293b;
101
+ }
102
+ }
103
+
104
+ .ssp-main-section {
105
+ display: flex;
106
+ flex-direction: column;
107
+ gap: 1.25rem;
108
+ }
109
+
110
+ .ssp-dropzone {
111
+ border: 2px dashed var(--color-primary-light, #818cf8);
112
+ border-radius: 12px;
113
+ padding: 1.5rem 1rem;
114
+ text-align: center;
115
+ background: rgba(129, 140, 248, 0.05);
116
+ cursor: pointer;
117
+ transition: all 0.2s ease;
118
+ }
119
+
120
+ .ssp-dropzone:hover,
121
+ .ssp-dropzone.dragover {
122
+ background: rgba(129, 140, 248, 0.12);
123
+ border-color: var(--color-primary, #6366f1);
124
+ }
125
+
126
+ .ssp-drop-title {
127
+ font-weight: 700;
128
+ font-size: 1rem;
129
+ margin-bottom: 0.25rem;
130
+ }
131
+
132
+ .ssp-drop-sub {
133
+ font-size: 0.8rem;
134
+ opacity: 0.7;
135
+ }
136
+
137
+ .ssp-file-input {
138
+ display: none;
139
+ }
140
+
141
+ .ssp-presets-row {
142
+ display: flex;
143
+ gap: 0.4rem;
144
+ flex-wrap: wrap;
145
+ }
146
+
147
+ .ssp-chip-btn {
148
+ flex: 1;
149
+ min-width: 85px;
150
+ padding: 0.45rem 0.6rem;
151
+ font-size: 0.75rem;
152
+ font-weight: 600;
153
+ border-radius: 6px;
154
+ border: 1px solid rgba(129, 140, 248, 0.3);
155
+ background: rgba(129, 140, 248, 0.08);
156
+ color: inherit;
157
+ cursor: pointer;
158
+ transition: all 0.15s ease;
159
+ text-align: center;
160
+ }
161
+
162
+ .ssp-chip-btn:hover {
163
+ background: rgba(129, 140, 248, 0.2);
164
+ border-color: var(--color-primary, #6366f1);
165
+ }
166
+
167
+ .ssp-chip-btn.active {
168
+ background: linear-gradient(135deg, #6366f1, #4f46e5);
169
+ color: var(--text-on-primary, #fff);
170
+ border-color: var(--color-primary, #6366f1);
171
+ box-shadow: 0 2px 8px rgba(99, 102, 241, 0.3);
172
+ }
173
+
174
+ .ssp-controls-list {
175
+ display: flex;
176
+ flex-direction: column;
177
+ gap: 1rem;
178
+ }
179
+
180
+ .ssp-control-group {
181
+ display: flex;
182
+ flex-direction: column;
183
+ gap: 0.4rem;
184
+ }
185
+
186
+ .ssp-label {
187
+ font-size: 0.85rem;
188
+ font-weight: 600;
189
+ display: flex;
190
+ justify-content: space-between;
191
+ }
192
+
193
+ .ssp-stepper-box {
194
+ display: flex;
195
+ align-items: center;
196
+ gap: 0.4rem;
197
+ width: 100%;
198
+ }
199
+
200
+ .ssp-step-btn {
201
+ width: 32px;
202
+ height: 32px;
203
+ border-radius: 6px;
204
+ border: 1px solid var(--border-base, #cbd5e1);
205
+ background: rgba(148, 163, 184, 0.1);
206
+ color: inherit;
207
+ font-weight: 700;
208
+ font-size: 1rem;
209
+ cursor: pointer;
210
+ display: flex;
211
+ align-items: center;
212
+ justify-content: center;
213
+ transition: background 0.15s ease, transform 0.1s ease;
214
+ flex-shrink: 0;
215
+ }
216
+
217
+ .theme-dark .ssp-step-btn {
218
+ border-color: #334155;
219
+ }
220
+
221
+ .ssp-step-btn:hover {
222
+ background: rgba(99, 102, 241, 0.2);
223
+ border-color: var(--color-primary, #6366f1);
224
+ }
225
+
226
+ .ssp-step-btn:active {
227
+ transform: scale(0.92);
228
+ }
229
+
230
+ .ssp-slider {
231
+ flex: 1;
232
+ accent-color: var(--color-primary, #6366f1);
233
+ }
234
+
235
+ .ssp-select,
236
+ .ssp-input {
237
+ width: 100%;
238
+ padding: 0.6rem 0.8rem;
239
+ border-radius: 8px;
240
+ border: 1px solid var(--border-base, #cbd5e1);
241
+ background: var(--bg-surface, #fff);
242
+ color: inherit;
243
+ font-size: 0.9rem;
244
+ }
245
+
246
+ .theme-dark .ssp-select,
247
+ .theme-dark .ssp-input {
248
+ background: #1e293b;
249
+ border-color: #334155;
250
+ }
251
+
252
+ .ssp-toggle-group {
253
+ display: flex;
254
+ align-items: center;
255
+ justify-content: space-between;
256
+ padding: 0.3rem 0;
257
+ }
258
+
259
+ .ssp-toggle-input {
260
+ width: 1.25rem;
261
+ height: 1.25rem;
262
+ accent-color: var(--color-primary, #6366f1);
263
+ cursor: pointer;
264
+ }
265
+
266
+ .ssp-btn-row {
267
+ display: flex;
268
+ gap: 0.5rem;
269
+ flex-wrap: wrap;
270
+ }
271
+
272
+ .ssp-btn {
273
+ flex: 1;
274
+ min-width: 110px;
275
+ padding: 0.7rem 0.9rem;
276
+ border-radius: 8px;
277
+ border: none;
278
+ font-weight: 600;
279
+ font-size: 0.88rem;
280
+ cursor: pointer;
281
+ transition: transform 0.15s ease, opacity 0.15s ease, background 0.2s ease;
282
+ display: inline-flex;
283
+ align-items: center;
284
+ justify-content: center;
285
+ gap: 0.5rem;
286
+ }
287
+
288
+ .ssp-btn:hover {
289
+ transform: translateY(-1px);
290
+ }
291
+
292
+ .ssp-btn:active {
293
+ transform: scale(0.96);
294
+ }
295
+
296
+ .ssp-btn-primary {
297
+ background: linear-gradient(135deg, #6366f1, #4f46e5);
298
+ color: var(--text-on-primary, #fff);
299
+ }
300
+
301
+ .ssp-btn-secondary {
302
+ background: rgba(148, 163, 184, 0.12);
303
+ color: inherit;
304
+ border: 1px solid var(--border-base, #cbd5e1);
305
+ }
306
+
307
+ .theme-dark .ssp-btn-secondary {
308
+ border-color: #334155;
309
+ }
310
+
311
+ .ssp-btn-danger {
312
+ background: #dc2626;
313
+ color: var(--text-on-primary, #fff);
314
+ }
315
+
316
+ .ssp-btn-success {
317
+ background: #047857;
318
+ color: var(--text-on-primary, #fff);
319
+ border-color: #047857;
320
+ }
321
+
322
+ .ssp-stats-grid {
323
+ display: grid;
324
+ grid-template-columns: repeat(auto-fit, minmax(110px, 1fr));
325
+ gap: 0.75rem;
326
+ }
327
+
328
+ .ssp-stat-badge {
329
+ background: rgba(99, 102, 241, 0.08);
330
+ border: 1px solid rgba(99, 102, 241, 0.2);
331
+ border-radius: 10px;
332
+ padding: 0.6rem 0.75rem;
333
+ text-align: center;
334
+ }
335
+
336
+ .ssp-stat-val {
337
+ font-size: 1.1rem;
338
+ font-weight: 700;
339
+ color: var(--color-primary, #6366f1);
340
+ }
341
+
342
+ .theme-dark .ssp-stat-val {
343
+ color: var(--color-primary-light, #818cf8);
344
+ }
345
+
346
+ .ssp-stat-lbl {
347
+ font-size: 0.75rem;
348
+ opacity: 0.8;
349
+ }
350
+
351
+ .ssp-canvas-wrapper {
352
+ width: 100%;
353
+ height: 380px;
354
+ overflow: auto;
355
+ border-radius: 12px;
356
+ background-image: linear-gradient(45deg, #cbd5e1 25%, transparent 25%),
357
+ linear-gradient(-45deg, #cbd5e1 25%, transparent 25%),
358
+ linear-gradient(45deg, transparent 75%, #cbd5e1 75%),
359
+ linear-gradient(-45deg, transparent 75%, #cbd5e1 75%);
360
+ background-size: 16px 16px;
361
+ background-position: 0 0, 0 8px, 8px -8px, -8px 0;
362
+ display: flex;
363
+ align-items: center;
364
+ justify-content: center;
365
+ padding: 1rem;
366
+ border: 1px solid var(--border-base, #e2e8f0);
367
+ box-sizing: border-box;
368
+ }
369
+
370
+ .theme-dark .ssp-canvas-wrapper {
371
+ background-image: linear-gradient(45deg, #1e293b 25%, transparent 25%),
372
+ linear-gradient(-45deg, #1e293b 25%, transparent 25%),
373
+ linear-gradient(45deg, transparent 75%, #1e293b 75%),
374
+ linear-gradient(-45deg, transparent 75%, #1e293b 75%);
375
+ border-color: #1e293b;
376
+ }
377
+
378
+ .ssp-canvas {
379
+ max-width: 100%;
380
+ max-height: 100%;
381
+ object-fit: contain;
382
+ border-radius: 4px;
383
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
384
+ image-rendering: pixelated;
385
+ }
386
+
387
+ .ssp-flipbook-box {
388
+ display: flex;
389
+ flex-direction: column;
390
+ gap: 0.75rem;
391
+ padding: 1rem;
392
+ background: rgba(99, 102, 241, 0.04);
393
+ border-radius: 12px;
394
+ border: 1px solid rgba(99, 102, 241, 0.18);
395
+ }
396
+
397
+ .ssp-flipbook-header {
398
+ font-weight: 700;
399
+ font-size: 0.9rem;
400
+ }
401
+
402
+ .ssp-flipbook-body {
403
+ display: flex;
404
+ align-items: center;
405
+ gap: 1.25rem;
406
+ flex-wrap: wrap;
407
+ }
408
+
409
+ .ssp-flipbook-canvas {
410
+ width: 100px;
411
+ height: 100px;
412
+ image-rendering: pixelated;
413
+ background: rgba(0, 0, 0, 0.2);
414
+ border-radius: 8px;
415
+ border: 1px solid rgba(255, 255, 255, 0.1);
416
+ }
417
+
418
+ .ssp-flipbook-controls {
419
+ flex: 1;
420
+ min-width: 200px;
421
+ display: flex;
422
+ flex-direction: column;
423
+ gap: 0.75rem;
424
+ }
425
+
426
+ .ssp-code-container {
427
+ display: flex;
428
+ flex-direction: column;
429
+ border-radius: 10px;
430
+ overflow: hidden;
431
+ border: 1px solid var(--border-base, #e2e8f0);
432
+ background: var(--bg-surface-secondary, #f8fafc);
433
+ }
434
+
435
+ .theme-dark .ssp-code-container {
436
+ border-color: #1e293b;
437
+ background: #090d16;
438
+ }
439
+
440
+ .ssp-code-header {
441
+ display: flex;
442
+ align-items: center;
443
+ justify-content: space-between;
444
+ background: rgba(148, 163, 184, 0.12);
445
+ padding: 0.6rem 0.85rem;
446
+ border-bottom: 1px solid var(--border-base, #e2e8f0);
447
+ }
448
+
449
+ .theme-dark .ssp-code-header {
450
+ background: #0f172a;
451
+ border-color: #1e293b;
452
+ }
453
+
454
+ .ssp-code-title {
455
+ font-size: 0.82rem;
456
+ font-weight: 600;
457
+ color: var(--text-base, #334155);
458
+ }
459
+
460
+ .theme-dark .ssp-code-title {
461
+ color: var(--text-muted, #94a3b8);
462
+ }
463
+
464
+ .ssp-copy-btn {
465
+ background: rgba(99, 102, 241, 0.1);
466
+ border: 1px solid rgba(99, 102, 241, 0.3);
467
+ color: var(--color-primary, #4f46e5);
468
+ padding: 0.35rem 0.75rem;
469
+ border-radius: 6px;
470
+ font-size: 0.78rem;
471
+ font-weight: 600;
472
+ cursor: pointer;
473
+ transition: all 0.15s ease;
474
+ }
475
+
476
+ .theme-dark .ssp-copy-btn {
477
+ background: rgba(56, 189, 248, 0.12);
478
+ border-color: rgba(56, 189, 248, 0.3);
479
+ color: var(--color-cyan, #38bdf8);
480
+ }
481
+
482
+ .ssp-copy-btn:hover {
483
+ background: rgba(99, 102, 241, 0.2);
484
+ }
485
+
486
+ .theme-dark .ssp-copy-btn:hover {
487
+ background: rgba(56, 189, 248, 0.25);
488
+ }
489
+
490
+ .ssp-copy-btn:active {
491
+ transform: scale(0.95);
492
+ }
493
+
494
+ .ssp-code-block {
495
+ width: 100%;
496
+ margin: 0;
497
+ background: #f1f5f9;
498
+ color: var(--text-base, #0f172a);
499
+ font-size: 0.82rem;
500
+ padding: 0.85rem 1rem;
501
+ overflow-x: auto;
502
+ white-space: pre-wrap;
503
+ word-break: break-all;
504
+ }
505
+
506
+ .theme-dark .ssp-code-block {
507
+ background: #070a12;
508
+ color: var(--color-cyan, #38bdf8);
509
+ }
510
+
511
+ .ssp-toast {
512
+ position: fixed;
513
+ bottom: 2rem;
514
+ right: 2rem;
515
+ background: #047857;
516
+ color: var(--text-on-primary, #fff);
517
+ padding: 0.75rem 1.25rem;
518
+ border-radius: 8px;
519
+ font-weight: 600;
520
+ box-shadow: 0 4px 14px rgba(16, 185, 129, 0.4);
521
+ opacity: 0;
522
+ transform: translateY(10px);
523
+ pointer-events: none;
524
+ transition: opacity 0.3s ease, transform 0.3s ease;
525
+ z-index: 1000;
526
+ }
527
+
528
+ .ssp-toast.show {
529
+ opacity: 1;
530
+ transform: translateY(0);
531
+ }
532
+
533
+ .ssp-particle-container {
534
+ position: fixed;
535
+ top: 0;
536
+ left: 0;
537
+ width: 100vw;
538
+ height: 100vh;
539
+ pointer-events: none;
540
+ z-index: 2000;
541
+ }
542
+
543
+ .ssp-particle {
544
+ position: absolute;
545
+ font-size: 0.75rem;
546
+ font-weight: 800;
547
+ color: var(--color-primary, #4f46e5);
548
+ background: rgba(255, 255, 255, 0.95);
549
+ border: 1px solid var(--color-primary, #6366f1);
550
+ border-radius: 4px;
551
+ padding: 0.2rem 0.5rem;
552
+ box-shadow: 0 0 10px rgba(99, 102, 241, 0.3);
553
+ animation: ssp-particle-float 1s forwards ease-out;
554
+ }
555
+
556
+ .theme-dark .ssp-particle {
557
+ color: var(--color-cyan, #38bdf8);
558
+ background: rgba(15, 23, 42, 0.9);
559
+ border-color: #38bdf8;
560
+ box-shadow: 0 0 10px rgba(56, 189, 248, 0.5);
561
+ }
562
+
563
+ @keyframes ssp-particle-float {
564
+ 0% {
565
+ opacity: 1;
566
+ transform: translate(-50%, -50%) scale(0.8);
567
+ }
568
+
569
+ 50% {
570
+ opacity: 1;
571
+ transform: translate(-50%, -120%) scale(1.1);
572
+ }
573
+
574
+ 100% {
575
+ opacity: 0;
576
+ transform: translate(-50%, -180%) scale(0.9);
577
+ }
578
+ }