@jjlmoya/utils-hardware 1.12.0 → 1.14.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.
@@ -14,94 +14,7 @@ const t = (ui ?? {}) as TestMandoUI;
14
14
 
15
15
  <div id="gamepad-root" class="tm-wrapper"
16
16
  data-s={JSON.stringify({c:t.gameLogConnected,cm:t.connectionMessage,d:t.gameLogDisconnected,cl:t.gameLogCleared,bp:t.gameLogBtnPrefix,vn:t.gameVibNotSupported,vl:t.gameVibLow,vh:t.gameVibHigh,ms:t.gameMoveStick,pr:t.gamePress,rln:t.rankLegendaryName,rld:t.rankLegendaryDesc,rlf:t.rankLegendaryFlavor,rpn:t.rankProName,rpd:t.rankProDesc,rpf:t.rankProFlavor,rgn:t.rankGamerName,rgd:t.rankGamerDesc,rgf:t.rankGamerFlavor,rnn:t.rankNoobName,rnd:t.rankNoobDesc,rnf:t.rankNoobFlavor,gst:t.gameShareText,gsp:t.gameShareScorePrefix,gss:t.gameShareScoreSuffix,gt:t.gameShareTitle})}>
17
- <style is:global>
18
- .tm-wrapper {
19
- --tm-accent: #4f46e5;
20
- --tm-accent-glow: rgba(79, 70, 229, 0.4);
21
- --tm-surface: #fff;
22
- --tm-surface-alt: #f8fafc;
23
- --tm-surface-dark: #020617;
24
- --tm-border: #e2e8f0;
25
- --tm-text: #0f172a;
26
- --tm-text-muted: #64748b;
27
- --tm-btn-bg: #f1f5f9;
28
- --tm-btn-border: #cbd5e1;
29
- --tm-active: #0ea5e9;
30
- --tm-active-glow: rgba(14, 165, 233, 0.5);
31
- --tm-success: #10b981;
32
- --tm-danger: #f43f5e;
33
- --tm-kb-bg: #1e293b;
34
- --tm-kb-border: #334155;
35
- --tm-stick-base: #475569;
36
- --tm-stick-cap: #334155;
37
- --tm-stick-border: #64748b;
38
- }
39
-
40
- .theme-dark .tm-wrapper {
41
- --tm-surface: #0f172a;
42
- --tm-surface-alt: #1e293b;
43
- --tm-border: #334155;
44
- --tm-text: #f1f5f9;
45
- --tm-text-muted: #94a3b8;
46
- --tm-btn-bg: #1e293b;
47
- --tm-btn-border: #475569;
48
- --tm-kb-bg: #020617;
49
- --tm-kb-border: #1e293b;
50
- --tm-stick-base: #0f172a;
51
- --tm-stick-cap: #475569;
52
- --tm-stick-border: #334155;
53
- }
54
-
55
- body.is-widget .tm-wrapper {
56
- padding: 0;
57
- }
58
-
59
- .tm-active-btn {
60
- background-color: var(--tm-active);
61
- border-color: var(--tm-active);
62
- color: white;
63
- box-shadow: 0 0 18px var(--tm-active-glow), 0 0 36px var(--tm-active-glow);
64
- transform: scale(0.88);
65
- }
66
-
67
- .tm-active-dpad {
68
- background-color: var(--tm-active);
69
- box-shadow: 0 0 14px var(--tm-active-glow);
70
- }
71
-
72
- .tm-active-stick-cap {
73
- background-color: var(--tm-active);
74
- border-color: #7dd3fc;
75
- box-shadow: 0 0 18px var(--tm-active-glow);
76
- }
77
-
78
- .tm-target-pop {
79
- animation: tm-pop 0.3s cubic-bezier(0.175, 0.885, 0.32, 1.275) forwards;
80
- }
81
-
82
- @keyframes tm-pop {
83
- 0% {
84
- transform: scale(0) rotate(-10deg);
85
- opacity: 0;
86
- }
87
- 100% {
88
- transform: scale(1) rotate(0deg);
89
- opacity: 1;
90
- }
91
- }
92
-
93
- .tm-shake {
94
- animation: tm-shake 0.4s cubic-bezier(0.36, 0.07, 0.19, 0.97) both;
95
- }
96
-
97
- @keyframes tm-shake {
98
- 10%, 90% { transform: translate3d(-1px, 0, 0); }
99
- 20%, 80% { transform: translate3d(2px, 0, 0); }
100
- 30%, 50%, 70% { transform: translate3d(-4px, 0, 0); }
101
- 40%, 60% { transform: translate3d(4px, 0, 0); }
102
- }
103
- </style>
104
-
17
+
105
18
  <div class="tm-container">
106
19
 
107
20
  <div class="tm-card">
@@ -280,891 +193,7 @@ const t = (ui ?? {}) as TestMandoUI;
280
193
 
281
194
  </div>
282
195
 
283
- <style>
284
- .tm-wrapper {
285
- width: 100%;
286
- color: var(--tm-text);
287
- }
288
-
289
- .tm-container {
290
- max-width: 56rem;
291
- margin: 0 auto;
292
- padding: 1rem;
293
- display: flex;
294
- flex-direction: column;
295
- gap: 3rem;
296
- }
297
-
298
- .tm-card {
299
- background: var(--tm-surface);
300
- border-radius: 1.5rem;
301
- padding: 2rem;
302
- box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.1);
303
- border: 1px solid var(--tm-border);
304
- }
305
-
306
- .tm-card-header {
307
- text-align: center;
308
- margin-bottom: 2rem;
309
- }
310
-
311
- .tm-badge {
312
- display: inline-flex;
313
- align-items: center;
314
- gap: 0.5rem;
315
- padding: 0.25rem 0.75rem;
316
- border-radius: 9999px;
317
- background-color: rgba(79, 70, 229, 0.1);
318
- color: var(--tm-accent);
319
- font-size: 0.75rem;
320
- font-weight: 700;
321
- text-transform: uppercase;
322
- letter-spacing: 0.05em;
323
- margin-bottom: 0.75rem;
324
- }
325
-
326
- .tm-badge-icon {
327
- width: 1rem;
328
- height: 1rem;
329
- }
330
-
331
- .tm-title {
332
- font-size: 1.875rem;
333
- font-weight: 900;
334
- letter-spacing: -0.02em;
335
- margin: 0 0 0.25rem;
336
- }
337
-
338
- .tm-description {
339
- font-size: 0.9375rem;
340
- color: var(--tm-text-muted);
341
- margin: 0;
342
- }
343
-
344
- .tm-stage-wrapper {
345
- display: flex;
346
- flex-direction: column;
347
- align-items: center;
348
- gap: 1rem;
349
- }
350
-
351
- .tm-stage {
352
- position: relative;
353
- width: 600px;
354
- height: 420px;
355
- transition: all 500ms;
356
- }
357
-
358
- .tm-stage-inactive {
359
- opacity: 0.25;
360
- filter: grayscale(1);
361
- transform: scale(0.9);
362
- }
363
-
364
- @media (min-width: 640px) {
365
- .tm-stage-inactive {
366
- transform: scale(1);
367
- }
368
- }
369
-
370
- .tm-trigger {
371
- position: absolute;
372
- top: 0;
373
- width: 8rem;
374
- height: 4rem;
375
- background: var(--tm-btn-bg);
376
- border-radius: 0.75rem 0.75rem 0 0;
377
- border: 1px solid var(--tm-btn-border);
378
- border-bottom: none;
379
- display: flex;
380
- flex-direction: column;
381
- justify-content: flex-end;
382
- padding: 0.5rem;
383
- }
384
-
385
- .tm-trigger-left { left: 2rem; }
386
- .tm-trigger-right { right: 2rem; }
387
-
388
- .tm-trigger-label {
389
- position: absolute;
390
- top: -1.5rem;
391
- font-size: 0.625rem;
392
- font-weight: 700;
393
- color: var(--tm-text-muted);
394
- }
395
-
396
- .tm-trigger-left .tm-trigger-label { left: 0; }
397
- .tm-trigger-right .tm-trigger-label { right: 0; }
398
-
399
- .tm-trigger-bar-track {
400
- width: 100%;
401
- background: var(--tm-border);
402
- height: 0.5rem;
403
- border-radius: 9999px;
404
- overflow: hidden;
405
- }
406
-
407
- .tm-trigger-bar {
408
- height: 100%;
409
- background: var(--tm-active);
410
- width: 0;
411
- transition: width 50ms;
412
- }
413
-
414
- .tm-trigger-btn {
415
- margin-top: 0.5rem;
416
- width: 100%;
417
- height: 2rem;
418
- border-radius: 0.5rem;
419
- border: 2px solid var(--tm-btn-border);
420
- transition: all 150ms;
421
- }
422
-
423
- .tm-shoulder {
424
- position: absolute;
425
- top: 5rem;
426
- width: 8rem;
427
- height: 2.5rem;
428
- background: var(--tm-surface);
429
- border-radius: 0.5rem;
430
- border: 2px solid var(--tm-btn-border);
431
- display: flex;
432
- align-items: center;
433
- justify-content: center;
434
- font-size: 0.75rem;
435
- font-weight: 700;
436
- color: var(--tm-btn-border);
437
- transition: all 150ms;
438
- }
439
-
440
- .tm-shoulder-left { left: 2rem; }
441
- .tm-shoulder-right { right: 2rem; }
442
-
443
- .tm-left-cluster {
444
- position: absolute;
445
- top: 8rem;
446
- left: 4rem;
447
- width: 12rem;
448
- height: 12rem;
449
- }
450
-
451
- .tm-stick-base {
452
- position: absolute;
453
- top: 0;
454
- left: 0;
455
- width: 6rem;
456
- height: 6rem;
457
- background: var(--tm-stick-base);
458
- border-radius: 9999px;
459
- border: 2px solid var(--tm-stick-border);
460
- display: flex;
461
- align-items: center;
462
- justify-content: center;
463
- box-shadow: inset 0 2px 6px rgba(0, 0, 0, 0.4);
464
- }
465
-
466
- .tm-left-cluster .tm-stick-base {
467
- top: 0;
468
- left: 0;
469
- }
470
-
471
- .tm-stick-cap {
472
- width: 3.5rem;
473
- height: 3.5rem;
474
- background: var(--tm-stick-cap);
475
- border-radius: 9999px;
476
- box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.15), 0 2px 6px rgba(0, 0, 0, 0.5);
477
- position: relative;
478
- will-change: transform;
479
- transition: background 150ms, box-shadow 150ms;
480
- }
481
-
482
- .tm-stick-press {
483
- width: 100%;
484
- height: 100%;
485
- border-radius: 9999px;
486
- border: 4px solid transparent;
487
- transition: border-color 150ms;
488
- }
489
-
490
- .tm-dpad {
491
- position: absolute;
492
- bottom: 0;
493
- right: 0;
494
- width: 6rem;
495
- height: 6rem;
496
- }
497
-
498
- .tm-dpad-up,
499
- .tm-dpad-down,
500
- .tm-dpad-left,
501
- .tm-dpad-right {
502
- position: absolute;
503
- width: 2rem;
504
- height: 2rem;
505
- border-radius: 0.25rem;
506
- background: var(--tm-btn-bg);
507
- border: 2px solid var(--tm-btn-border);
508
- transition: all 150ms;
509
- }
510
-
511
- .tm-dpad-up {
512
- top: 0;
513
- left: 50%;
514
- transform: translateX(-50%);
515
- }
516
- .tm-dpad-down {
517
- bottom: 0;
518
- left: 50%;
519
- transform: translateX(-50%);
520
- }
521
- .tm-dpad-left {
522
- left: 0;
523
- top: 50%;
524
- transform: translateY(-50%);
525
- }
526
- .tm-dpad-right {
527
- right: 0;
528
- top: 50%;
529
- transform: translateY(-50%);
530
- }
531
- .tm-dpad-center {
532
- position: absolute;
533
- inset: 2rem;
534
- background: var(--tm-btn-bg);
535
- border-radius: 0.25rem;
536
- }
537
-
538
- .tm-right-cluster {
539
- position: absolute;
540
- top: 8rem;
541
- right: 4rem;
542
- width: 6rem;
543
- height: 6rem;
544
- }
545
-
546
- .tm-stick-right {
547
- position: absolute;
548
- bottom: 12rem;
549
- right: 16rem;
550
- }
551
-
552
- .tm-face-buttons {
553
- position: absolute;
554
- top: 0;
555
- right: 0;
556
- width: 6rem;
557
- height: 6rem;
558
- }
559
-
560
- .tm-face-btn {
561
- position: absolute;
562
- width: 2.5rem;
563
- height: 2.5rem;
564
- border-radius: 9999px;
565
- border: 2px solid var(--tm-btn-border);
566
- background: var(--tm-surface);
567
- display: flex;
568
- align-items: center;
569
- justify-content: center;
570
- font-weight: 700;
571
- font-size: 0.75rem;
572
- color: var(--tm-btn-border);
573
- transition: all 150ms;
574
- }
575
-
576
- #btn-3 {
577
- top: 0;
578
- left: 50%;
579
- transform: translateX(-50%);
580
- color: #eab308;
581
- border-color: rgba(234, 179, 8, 0.6);
582
- }
583
- #btn-1 {
584
- right: 0;
585
- top: 50%;
586
- transform: translateY(-50%);
587
- color: #f43f5e;
588
- border-color: rgba(244, 63, 94, 0.6);
589
- }
590
- #btn-0 {
591
- bottom: 0;
592
- left: 50%;
593
- transform: translateX(-50%);
594
- color: #10b981;
595
- border-color: rgba(16, 185, 129, 0.6);
596
- }
597
- #btn-2 {
598
- left: 0;
599
- top: 50%;
600
- transform: translateY(-50%);
601
- color: #0ea5e9;
602
- border-color: rgba(14, 165, 233, 0.6);
603
- }
604
-
605
- .tm-center-buttons {
606
- position: absolute;
607
- top: 10rem;
608
- left: 50%;
609
- transform: translateX(-50%);
610
- display: flex;
611
- gap: 1.5rem;
612
- }
613
-
614
- .tm-center-btn {
615
- width: 2rem;
616
- height: 2rem;
617
- border-radius: 9999px;
618
- background: var(--tm-btn-bg);
619
- display: flex;
620
- align-items: center;
621
- justify-content: center;
622
- font-size: 0.625rem;
623
- font-weight: 700;
624
- color: var(--tm-text-muted);
625
- transition: all 150ms;
626
- }
627
-
628
- .tm-power-btn {
629
- position: absolute;
630
- top: 6rem;
631
- left: 50%;
632
- transform: translateX(-50%);
633
- width: 3rem;
634
- height: 3rem;
635
- border-radius: 9999px;
636
- border: 4px solid var(--tm-btn-bg);
637
- background: var(--tm-surface);
638
- box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
639
- display: flex;
640
- align-items: center;
641
- justify-content: center;
642
- transition: all 150ms;
643
- }
644
-
645
- .tm-power-icon {
646
- width: 1.5rem;
647
- height: 1.5rem;
648
- color: var(--tm-btn-border);
649
- }
650
-
651
- .tm-info-bar {
652
- width: 100%;
653
- padding-top: 1.5rem;
654
- border-top: 1px solid var(--tm-border);
655
- display: flex;
656
- justify-content: space-between;
657
- align-items: center;
658
- font-size: 0.75rem;
659
- color: var(--tm-text-muted);
660
- transition: opacity 500ms;
661
- }
662
-
663
- .tm-info-inactive { opacity: 0.5; }
664
-
665
- .tm-info-left,
666
- .tm-info-right {
667
- display: flex;
668
- gap: 1rem;
669
- }
670
-
671
- .tm-gp-id {
672
- display: none;
673
- }
674
-
675
- @media (min-width: 768px) {
676
- .tm-gp-id { display: inline; }
677
- }
678
-
679
- .tm-vibration-panel {
680
- margin-top: 2rem;
681
- background: var(--tm-surface-alt);
682
- border-radius: 1rem;
683
- padding: 1.5rem;
684
- border: 1px solid var(--tm-border);
685
- display: flex;
686
- flex-direction: column;
687
- gap: 1rem;
688
- transition: opacity 500ms;
689
- }
690
-
691
- @media (min-width: 768px) {
692
- .tm-vibration-panel {
693
- flex-direction: row;
694
- align-items: center;
695
- justify-content: space-between;
696
- }
697
- }
698
-
699
- .tm-vibration-inactive {
700
- opacity: 0.5;
701
- pointer-events: none;
702
- }
703
-
704
- .tm-vibration-title {
705
- font-size: 0.9375rem;
706
- font-weight: 700;
707
- display: flex;
708
- align-items: center;
709
- gap: 0.5rem;
710
- margin: 0 0 0.25rem;
711
- }
712
-
713
- .tm-vibration-icon {
714
- width: 1.25rem;
715
- height: 1.25rem;
716
- color: #d946ef;
717
- }
718
-
719
- .tm-vibration-desc {
720
- font-size: 0.75rem;
721
- color: var(--tm-text-muted);
722
- margin: 0;
723
- }
724
-
725
- .tm-vibration-btns {
726
- display: flex;
727
- gap: 1rem;
728
- }
729
-
730
- .tm-vib-btn {
731
- padding: 0.5rem 1rem;
732
- background: var(--tm-surface);
733
- border: 1px solid var(--tm-btn-border);
734
- border-radius: 0.5rem;
735
- font-size: 0.875rem;
736
- font-weight: 700;
737
- cursor: pointer;
738
- color: var(--tm-text);
739
- transition: all 150ms;
740
- }
741
-
742
- .tm-vib-btn:hover {
743
- border-color: var(--tm-accent);
744
- color: var(--tm-accent);
745
- }
746
-
747
- .tm-log-section {
748
- margin-top: 2rem;
749
- background: var(--tm-surface-alt);
750
- border-radius: 1rem;
751
- padding: 1rem;
752
- border: 1px solid var(--tm-border);
753
- }
754
-
755
- .tm-log-header {
756
- display: flex;
757
- justify-content: space-between;
758
- align-items: center;
759
- margin-bottom: 0.5rem;
760
- }
761
-
762
- .tm-log-title {
763
- font-size: 0.75rem;
764
- font-weight: 700;
765
- text-transform: uppercase;
766
- color: var(--tm-text-muted);
767
- letter-spacing: 0.1em;
768
- }
769
-
770
- .tm-log-clear {
771
- font-size: 0.625rem;
772
- font-weight: 700;
773
- text-transform: uppercase;
774
- background: none;
775
- border: none;
776
- cursor: pointer;
777
- color: var(--tm-text-muted);
778
- }
779
-
780
- .tm-log-clear:hover {
781
- color: var(--tm-active);
782
- }
783
-
784
- .tm-log {
785
- height: 10rem;
786
- overflow-y: auto;
787
- font-size: 0.75rem;
788
- color: var(--tm-text-muted);
789
- background: var(--tm-kb-bg);
790
- padding: 0.75rem;
791
- border-radius: 0.5rem;
792
- border: 1px solid var(--tm-kb-border);
793
- scrollbar-width: thin;
794
- scrollbar-color: var(--tm-border) transparent;
795
- }
796
-
797
- .tm-log::-webkit-scrollbar {
798
- width: 4px;
799
- }
800
-
801
- .tm-log::-webkit-scrollbar-thumb {
802
- background: var(--tm-border);
803
- border-radius: 2px;
804
- }
805
-
806
- .tm-log-waiting {
807
- font-style: italic;
808
- opacity: 0.5;
809
- color: var(--tm-text-muted);
810
- }
811
-
812
- .tm-log div {
813
- line-height: 1.8;
814
- border-bottom: 1px solid rgba(255, 255, 255, 0.04);
815
- padding-bottom: 0.125rem;
816
- }
817
-
818
- .tm-game-card {
819
- background: var(--tm-surface-dark);
820
- border-radius: 3rem;
821
- padding: 2.5rem;
822
- position: relative;
823
- overflow: hidden;
824
- min-height: 500px;
825
- display: flex;
826
- flex-direction: column;
827
- align-items: center;
828
- justify-content: center;
829
- border: 1px solid rgba(255, 255, 255, 0.05);
830
- color: white;
831
- }
832
-
833
- .tm-game-intro {
834
- position: relative;
835
- z-index: 10;
836
- text-align: center;
837
- }
838
-
839
- .tm-game-icon {
840
- display: inline-flex;
841
- align-items: center;
842
- justify-content: center;
843
- width: 5rem;
844
- height: 5rem;
845
- border-radius: 1.5rem;
846
- background: rgba(255, 255, 255, 0.05);
847
- border: 1px solid rgba(255, 255, 255, 0.1);
848
- margin-bottom: 1.5rem;
849
- }
850
-
851
- .tm-game-icon-svg {
852
- width: 2.5rem;
853
- height: 2.5rem;
854
- color: var(--tm-success);
855
- }
856
-
857
- .tm-game-intro-title {
858
- font-size: clamp(1.75rem, 5vw, 3rem);
859
- font-weight: 900;
860
- letter-spacing: -0.02em;
861
- margin: 0 0 1rem;
862
- }
863
-
864
- .tm-game-highlight {
865
- background: linear-gradient(to right, #34d399, #22d3ee);
866
- -webkit-background-clip: text;
867
- -webkit-text-fill-color: transparent;
868
- background-clip: text;
869
- }
870
-
871
- .tm-game-intro-desc {
872
- color: #94a3b8;
873
- margin: 0 0 2.5rem;
874
- max-width: 28rem;
875
- font-size: 1.125rem;
876
- line-height: 1.6;
877
- }
878
-
879
- .tm-game-start-btn {
880
- position: relative;
881
- padding: 1.25rem 2.5rem;
882
- background: linear-gradient(to right, #10b981, #06b6d4);
883
- border: none;
884
- border-radius: 1rem;
885
- font-weight: 900;
886
- font-size: 1.25rem;
887
- color: white;
888
- cursor: pointer;
889
- box-shadow: 0 10px 30px rgba(16, 185, 129, 0.3);
890
- transition: all 300ms;
891
- overflow: hidden;
892
- }
893
-
894
- .tm-game-start-btn:hover {
895
- box-shadow: 0 15px 40px rgba(16, 185, 129, 0.5);
896
- transform: scale(1.05);
897
- }
898
-
899
- .tm-game-start-btn:active {
900
- transform: scale(0.95);
901
- }
902
-
903
- .tm-game-warning {
904
- margin-top: 1.5rem;
905
- font-size: 0.875rem;
906
- font-weight: 500;
907
- display: flex;
908
- align-items: center;
909
- justify-content: center;
910
- gap: 0.5rem;
911
- color: #94a3b8;
912
- }
913
-
914
- .tm-game-warning-icon {
915
- width: 1rem;
916
- height: 1rem;
917
- }
918
-
919
- .tm-game-play {
920
- position: relative;
921
- z-index: 10;
922
- width: 100%;
923
- flex-direction: column;
924
- align-items: center;
925
- }
926
-
927
- .tm-game-hud {
928
- display: flex;
929
- justify-content: space-between;
930
- align-items: center;
931
- width: 100%;
932
- margin-bottom: 3rem;
933
- }
934
-
935
- .tm-hud-item {
936
- display: flex;
937
- flex-direction: column;
938
- }
939
-
940
- .tm-hud-right {
941
- align-items: flex-end;
942
- }
943
-
944
- .tm-hud-label {
945
- font-size: 0.625rem;
946
- text-transform: uppercase;
947
- letter-spacing: 0.2em;
948
- color: #64748b;
949
- font-weight: 900;
950
- }
951
-
952
- .tm-hud-value {
953
- font-size: 2.25rem;
954
- font-weight: 900;
955
- color: white;
956
- }
957
-
958
- .tm-hud-timer {
959
- color: var(--tm-success);
960
- }
961
-
962
- .tm-hud-progress {
963
- width: 3rem;
964
- height: 0.25rem;
965
- background: rgba(255, 255, 255, 0.1);
966
- border-radius: 9999px;
967
- overflow: hidden;
968
- }
969
-
970
- .tm-progress-bar {
971
- height: 100%;
972
- background: var(--tm-success);
973
- width: 100%;
974
- transition: width 100ms linear;
975
- }
976
-
977
- .tm-target-container {
978
- position: relative;
979
- width: 18rem;
980
- height: 18rem;
981
- display: flex;
982
- align-items: center;
983
- justify-content: center;
984
- }
985
-
986
- .tm-target-ring {
987
- position: absolute;
988
- inset: 0;
989
- border-radius: 9999px;
990
- border: 1px solid rgba(255, 255, 255, 0.05);
991
- animation: ping 1s cubic-bezier(0, 0, 0.2, 1) infinite;
992
- }
993
-
994
- .tm-target-ring-inner {
995
- position: absolute;
996
- inset: 1rem;
997
- border-radius: 9999px;
998
- border: 1px solid rgba(255, 255, 255, 0.1);
999
- }
1000
-
1001
- .tm-target-btn {
1002
- width: 10rem;
1003
- height: 10rem;
1004
- border-radius: 1.5rem;
1005
- border: 2px solid rgba(255, 255, 255, 0.2);
1006
- display: flex;
1007
- flex-direction: column;
1008
- align-items: center;
1009
- justify-content: center;
1010
- font-size: 3.75rem;
1011
- font-weight: 900;
1012
- transition: all 150ms;
1013
- }
1014
-
1015
- .tm-target-hidden {
1016
- transform: scale(0);
1017
- }
1018
-
1019
- .tm-target-sub {
1020
- font-size: 0.625rem;
1021
- text-transform: uppercase;
1022
- letter-spacing: 0.1em;
1023
- opacity: 0.4;
1024
- }
1025
-
1026
- .tm-flash {
1027
- position: absolute;
1028
- inset: 0;
1029
- border-radius: 9999px;
1030
- opacity: 0;
1031
- pointer-events: none;
1032
- transition: opacity 150ms;
1033
- }
1034
-
1035
- .tm-flash-hit {
1036
- background: rgba(16, 185, 129, 0.3);
1037
- filter: blur(3rem);
1038
- }
1039
- .tm-flash-miss {
1040
- background: rgba(244, 63, 94, 0.3);
1041
- filter: blur(3rem);
1042
- }
1043
-
1044
- .tm-game-instruction {
1045
- margin-top: 3rem;
1046
- display: flex;
1047
- align-items: center;
1048
- gap: 0.75rem;
1049
- padding: 0.75rem 1.5rem;
1050
- background: rgba(255, 255, 255, 0.05);
1051
- border-radius: 9999px;
1052
- border: 1px solid rgba(255, 255, 255, 0.1);
1053
- }
1054
-
1055
- .tm-instruction-dot {
1056
- width: 0.75rem;
1057
- height: 0.75rem;
1058
- border-radius: 9999px;
1059
- background: var(--tm-success);
1060
- animation: pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite;
1061
- }
1062
-
1063
- .tm-game-results {
1064
- position: relative;
1065
- z-index: 10;
1066
- text-align: center;
1067
- }
1068
-
1069
- .tm-trophy-wrapper {
1070
- position: relative;
1071
- display: inline-block;
1072
- margin-bottom: 1.5rem;
1073
- }
1074
-
1075
- .tm-trophy {
1076
- width: 6rem;
1077
- height: 6rem;
1078
- color: #facc15;
1079
- filter: drop-shadow(0 0 30px rgba(250, 204, 21, 0.4));
1080
- }
1081
-
1082
- .tm-new-record {
1083
- position: absolute;
1084
- top: -0.5rem;
1085
- right: -0.5rem;
1086
- background: var(--tm-success);
1087
- color: white;
1088
- font-size: 0.625rem;
1089
- font-weight: 900;
1090
- padding: 0.25rem 0.5rem;
1091
- border-radius: 0.5rem;
1092
- }
1093
-
1094
- .tm-results-title {
1095
- font-size: 1.5rem;
1096
- font-weight: 700;
1097
- color: #94a3b8;
1098
- margin: 0 0 0.5rem;
1099
- }
1100
-
1101
- .tm-final-score {
1102
- font-size: 6rem;
1103
- font-weight: 900;
1104
- color: white;
1105
- letter-spacing: -0.05em;
1106
- margin-bottom: 1.5rem;
1107
- line-height: 1;
1108
- }
1109
-
1110
- .tm-game-result-feedback {
1111
- color: #cbd5e1;
1112
- margin: 0 0 2.5rem;
1113
- font-size: 1.125rem;
1114
- }
1115
-
1116
- .tm-results-btns {
1117
- display: flex;
1118
- flex-direction: column;
1119
- gap: 1rem;
1120
- justify-content: center;
1121
- }
1122
-
1123
- @media (min-width: 640px) {
1124
- .tm-results-btns { flex-direction: row; }
1125
- }
1126
-
1127
- .tm-restart-btn {
1128
- padding: 1rem 2rem;
1129
- background: white;
1130
- color: black;
1131
- border: none;
1132
- border-radius: 1rem;
1133
- font-weight: 900;
1134
- font-size: 1.125rem;
1135
- cursor: pointer;
1136
- transition: all 200ms;
1137
- }
1138
-
1139
- .tm-restart-btn:hover { transform: scale(1.05); }
1140
- .tm-restart-btn:active { transform: scale(0.95); }
1141
-
1142
- .tm-share-btn {
1143
- padding: 1rem 2rem;
1144
- background: rgba(255, 255, 255, 0.1);
1145
- color: white;
1146
- border: 1px solid rgba(255, 255, 255, 0.1);
1147
- border-radius: 1rem;
1148
- font-weight: 900;
1149
- font-size: 1.125rem;
1150
- cursor: pointer;
1151
- transition: all 200ms;
1152
- }
1153
-
1154
- .tm-share-btn:hover { background: rgba(255, 255, 255, 0.2); }
1155
-
1156
- @keyframes ping {
1157
- 75%, 100% {
1158
- transform: scale(2);
1159
- opacity: 0;
1160
- }
1161
- }
1162
-
1163
- @keyframes pulse {
1164
- 50% { opacity: 0.5; }
1165
- }
1166
- </style>
1167
-
196
+
1168
197
  <script>
1169
198
  interface VibGamepad {
1170
199
  vibrationActuator?: { playEffect: (t: string, p: object) => Promise<void> };