@jaak.ai/stamps 2.0.0-beta.2 → 2.0.0-beta.4

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 (84) hide show
  1. package/README.md +216 -212
  2. package/dist/cjs/{index-DGM9-FNg.js → index-BfhtOB0D.js} +5 -2
  3. package/dist/cjs/index-BfhtOB0D.js.map +1 -0
  4. package/dist/cjs/jaak-stamps-webcomponent.cjs.js +2 -2
  5. package/dist/cjs/jaak-stamps.cjs.entry.js +1860 -783
  6. package/dist/cjs/jaak-stamps.cjs.entry.js.map +1 -1
  7. package/dist/cjs/jaak-stamps.entry.cjs.js.map +1 -1
  8. package/dist/cjs/loader.cjs.js +2 -2
  9. package/dist/collection/components/my-component/my-component.css +629 -72
  10. package/dist/collection/components/my-component/my-component.js +896 -781
  11. package/dist/collection/components/my-component/my-component.js.map +1 -1
  12. package/dist/collection/services/CameraService.js +453 -0
  13. package/dist/collection/services/CameraService.js.map +1 -0
  14. package/dist/collection/services/DetectionService.js +369 -0
  15. package/dist/collection/services/DetectionService.js.map +1 -0
  16. package/dist/collection/services/EventBusService.js +42 -0
  17. package/dist/collection/services/EventBusService.js.map +1 -0
  18. package/dist/collection/services/LoggerService.js +40 -0
  19. package/dist/collection/services/LoggerService.js.map +1 -0
  20. package/dist/collection/services/ServiceContainer.js +66 -0
  21. package/dist/collection/services/ServiceContainer.js.map +1 -0
  22. package/dist/collection/services/StateManagerService.js +109 -0
  23. package/dist/collection/services/StateManagerService.js.map +1 -0
  24. package/dist/collection/services/factories/DeviceStrategyFactory.js +16 -0
  25. package/dist/collection/services/factories/DeviceStrategyFactory.js.map +1 -0
  26. package/dist/collection/services/interfaces/ICameraService.js +2 -0
  27. package/dist/collection/services/interfaces/ICameraService.js.map +1 -0
  28. package/dist/collection/services/interfaces/IDetectionService.js +2 -0
  29. package/dist/collection/services/interfaces/IDetectionService.js.map +1 -0
  30. package/dist/collection/services/interfaces/IEventBus.js +2 -0
  31. package/dist/collection/services/interfaces/IEventBus.js.map +1 -0
  32. package/dist/collection/services/interfaces/ILogger.js +2 -0
  33. package/dist/collection/services/interfaces/ILogger.js.map +1 -0
  34. package/dist/collection/services/interfaces/IStateManager.js +2 -0
  35. package/dist/collection/services/interfaces/IStateManager.js.map +1 -0
  36. package/dist/collection/services/strategies/HighPerformanceDeviceStrategy.js +30 -0
  37. package/dist/collection/services/strategies/HighPerformanceDeviceStrategy.js.map +1 -0
  38. package/dist/collection/services/strategies/IDeviceStrategy.js +2 -0
  39. package/dist/collection/services/strategies/IDeviceStrategy.js.map +1 -0
  40. package/dist/collection/services/strategies/LowMemoryDeviceStrategy.js +30 -0
  41. package/dist/collection/services/strategies/LowMemoryDeviceStrategy.js.map +1 -0
  42. package/dist/collection/types/component-types.js +2 -0
  43. package/dist/collection/types/component-types.js.map +1 -0
  44. package/dist/components/index.js +3 -0
  45. package/dist/components/index.js.map +1 -1
  46. package/dist/components/jaak-stamps.js +1873 -797
  47. package/dist/components/jaak-stamps.js.map +1 -1
  48. package/dist/esm/{index-DqoVMnc7.js → index-BP1Q4KOg.js} +5 -2
  49. package/dist/esm/index-BP1Q4KOg.js.map +1 -0
  50. package/dist/esm/jaak-stamps-webcomponent.js +3 -3
  51. package/dist/esm/jaak-stamps.entry.js +1860 -783
  52. package/dist/esm/jaak-stamps.entry.js.map +1 -1
  53. package/dist/esm/loader.js +3 -3
  54. package/dist/jaak-stamps-webcomponent/jaak-stamps-webcomponent.esm.js +1 -1
  55. package/dist/jaak-stamps-webcomponent/jaak-stamps.entry.esm.js.map +1 -1
  56. package/dist/jaak-stamps-webcomponent/p-10ee2dab.entry.js +2 -0
  57. package/dist/jaak-stamps-webcomponent/p-10ee2dab.entry.js.map +1 -0
  58. package/dist/jaak-stamps-webcomponent/p-BP1Q4KOg.js +3 -0
  59. package/dist/jaak-stamps-webcomponent/p-BP1Q4KOg.js.map +1 -0
  60. package/dist/types/components/my-component/my-component.d.ts +90 -79
  61. package/dist/types/components.d.ts +32 -8
  62. package/dist/types/services/CameraService.d.ts +46 -0
  63. package/dist/types/services/DetectionService.d.ts +35 -0
  64. package/dist/types/services/EventBusService.d.ts +9 -0
  65. package/dist/types/services/LoggerService.d.ts +12 -0
  66. package/dist/types/services/ServiceContainer.d.ts +27 -0
  67. package/dist/types/services/StateManagerService.d.ts +15 -0
  68. package/dist/types/services/factories/DeviceStrategyFactory.d.ts +4 -0
  69. package/dist/types/services/interfaces/ICameraService.d.ts +34 -0
  70. package/dist/types/services/interfaces/IDetectionService.d.ts +31 -0
  71. package/dist/types/services/interfaces/IEventBus.d.ts +16 -0
  72. package/dist/types/services/interfaces/ILogger.d.ts +8 -0
  73. package/dist/types/services/interfaces/IStateManager.d.ts +35 -0
  74. package/dist/types/services/strategies/HighPerformanceDeviceStrategy.d.ts +6 -0
  75. package/dist/types/services/strategies/IDeviceStrategy.d.ts +21 -0
  76. package/dist/types/services/strategies/LowMemoryDeviceStrategy.d.ts +6 -0
  77. package/dist/types/types/component-types.d.ts +36 -0
  78. package/package.json +3 -3
  79. package/dist/cjs/index-DGM9-FNg.js.map +0 -1
  80. package/dist/esm/index-DqoVMnc7.js.map +0 -1
  81. package/dist/jaak-stamps-webcomponent/p-DqoVMnc7.js +0 -3
  82. package/dist/jaak-stamps-webcomponent/p-DqoVMnc7.js.map +0 -1
  83. package/dist/jaak-stamps-webcomponent/p-f1172b06.entry.js +0 -2
  84. package/dist/jaak-stamps-webcomponent/p-f1172b06.entry.js.map +0 -1
@@ -31,25 +31,31 @@ h1 {
31
31
  overflow: hidden;
32
32
  }
33
33
 
34
- video, canvas {
34
+ video, .detection-overlay {
35
35
  position: absolute;
36
36
  width: 100%;
37
37
  height: 100%;
38
38
  border-radius: 8px;
39
39
  }
40
40
 
41
- video.mirror, canvas.mirror {
41
+ video.mirror, .detection-overlay.mirror {
42
42
  transform: rotateY(180deg);
43
43
  }
44
44
 
45
- canvas {
45
+ .detection-overlay {
46
46
  z-index: 1;
47
+ pointer-events: none;
47
48
  }
48
49
 
49
50
  video {
50
51
  z-index: 0;
51
52
  }
52
53
 
54
+ /* Detection boxes for debug mode */
55
+ .detection-box {
56
+ transition: opacity 0.2s ease;
57
+ }
58
+
53
59
 
54
60
  .status {
55
61
  margin-top: 16px;
@@ -79,12 +85,10 @@ video {
79
85
  border: none;
80
86
  border-radius: 4px;
81
87
  background: transparent;
82
- box-shadow: 0 0 0 9999px rgba(0, 0, 0, 0.7);
83
88
  opacity: 0.8;
84
89
  }
85
90
 
86
91
  .card-outline.perfect-match {
87
- box-shadow: 0 0 0 9999px rgba(0, 0, 0, 0.7);
88
92
  }
89
93
 
90
94
  /* Lados individuales de la máscara */
@@ -92,79 +96,74 @@ video {
92
96
  position: absolute;
93
97
  background: #999;
94
98
  transition: background-color 0.3s ease;
99
+ border-radius: 1px;
100
+ }
101
+
102
+ .side-top.aligned {
103
+ border-left-color: #28a745;
104
+ border-top-color: #28a745;
105
+ }
106
+
107
+ .side-right.aligned {
108
+ border-right-color: #28a745;
109
+ border-top-color: #28a745;
110
+ }
111
+
112
+ .side-bottom.aligned {
113
+ border-left-color: #28a745;
114
+ border-bottom-color: #28a745;
95
115
  }
96
116
 
97
- .side.aligned {
98
- background: #28a745;
117
+ .side-left.aligned {
118
+ border-right-color: #28a745;
119
+ border-bottom-color: #28a745;
99
120
  }
100
121
 
101
122
  .side-top {
102
- top: 0;
103
- left: 0;
104
- width: 100%;
105
- height: 3px;
123
+ top: -3px;
124
+ left: -3px;
125
+ width: 30px;
126
+ height: 30px;
127
+ border-left: 6px solid #ffffff;
128
+ border-top: 6px solid #ffffff;
129
+ background: transparent;
106
130
  }
107
131
 
108
132
  .side-right {
109
- top: 0;
110
- right: 0;
111
- width: 3px;
112
- height: 100%;
133
+ top: -3px;
134
+ right: -3px;
135
+ width: 30px;
136
+ height: 30px;
137
+ border-right: 6px solid #ffffff;
138
+ border-top: 6px solid #ffffff;
139
+ background: transparent;
113
140
  }
114
141
 
115
142
  .side-bottom {
116
- bottom: 0;
117
- left: 0;
118
- width: 100%;
119
- height: 3px;
143
+ bottom: -3px;
144
+ left: -3px;
145
+ width: 30px;
146
+ height: 30px;
147
+ border-left: 6px solid #ffffff;
148
+ border-bottom: 6px solid #ffffff;
149
+ background: transparent;
120
150
  }
121
151
 
122
152
  .side-left {
123
- top: 0;
124
- left: 0;
125
- width: 3px;
126
- height: 100%;
153
+ bottom: -3px;
154
+ right: -3px;
155
+ width: 30px;
156
+ height: 30px;
157
+ border-right: 6px solid #ffffff;
158
+ border-bottom: 6px solid #ffffff;
159
+ background: transparent;
127
160
  }
128
161
 
129
- .corner {
130
- position: absolute;
131
- width: 20px;
132
- height: 20px;
133
- border: 2px solid #999;
134
- z-index: 12;
135
- }
136
162
 
137
- .corner-tl {
138
- top: -10px;
139
- left: -10px;
140
- border-right: none;
141
- border-bottom: none;
142
- }
143
163
 
144
- .corner-tr {
145
- top: -10px;
146
- right: -10px;
147
- border-left: none;
148
- border-bottom: none;
149
- }
150
164
 
151
- .corner-bl {
152
- bottom: -10px;
153
- left: -10px;
154
- border-right: none;
155
- border-top: none;
156
- }
157
165
 
158
- .corner-br {
159
- bottom: -10px;
160
- right: -10px;
161
- border-left: none;
162
- border-top: none;
163
- }
164
166
 
165
- .corner.perfect-match {
166
- border-color: #28a745;
167
- }
168
167
 
169
168
  .guide-text {
170
169
  position: absolute;
@@ -183,6 +182,72 @@ video {
183
182
  z-index: 20;
184
183
  }
185
184
 
185
+ /* Quality indicator */
186
+ .quality-indicator {
187
+ position: absolute;
188
+ top: 20px;
189
+ right: 20px;
190
+ display: flex;
191
+ align-items: center;
192
+ gap: 8px;
193
+ background: rgba(0, 0, 0, 0.8);
194
+ padding: 8px 12px;
195
+ border-radius: 20px;
196
+ z-index: 25;
197
+ transition: all 0.3s ease;
198
+ }
199
+
200
+ .quality-indicator.warning {
201
+ background: rgba(255, 152, 0, 0.9);
202
+ }
203
+
204
+ .quality-indicator.good {
205
+ background: rgba(76, 175, 80, 0.9);
206
+ }
207
+
208
+ .quality-score {
209
+ color: #fff;
210
+ font-size: 12px;
211
+ font-weight: 600;
212
+ min-width: 30px;
213
+ text-align: center;
214
+ }
215
+
216
+ .quality-status {
217
+ width: 20px;
218
+ height: 20px;
219
+ border-radius: 50%;
220
+ display: flex;
221
+ align-items: center;
222
+ justify-content: center;
223
+ font-size: 14px;
224
+ font-weight: bold;
225
+ color: #fff;
226
+ transition: all 0.3s ease;
227
+ }
228
+
229
+ .quality-status.ready {
230
+ background: #4CAF50;
231
+ }
232
+
233
+ .quality-status.not-ready {
234
+ background: #f44336;
235
+ }
236
+
237
+ /* Enhanced card outline for quality warnings */
238
+ .card-outline.quality-warning {
239
+ animation: qualityWarning 1s ease-in-out infinite alternate;
240
+ }
241
+
242
+ @keyframes qualityWarning {
243
+ 0% {
244
+ box-shadow: 0 0 0 3px rgba(255, 152, 0, 0.6);
245
+ }
246
+ 100% {
247
+ box-shadow: 0 0 0 6px rgba(255, 152, 0, 0.3);
248
+ }
249
+ }
250
+
186
251
 
187
252
  /* Animación de captura */
188
253
  .capture-animation {
@@ -227,15 +292,15 @@ video {
227
292
  @keyframes pulseGreen {
228
293
  0% {
229
294
  border-color: #28a745;
230
- box-shadow: 0 0 0 9999px rgba(0, 0, 0, 0.7), 0 0 0 4px rgba(40, 167, 69, 0);
295
+ box-shadow: 0 0 0 4px rgba(40, 167, 69, 0);
231
296
  }
232
297
  50% {
233
298
  border-color: #28a745;
234
- box-shadow: 0 0 0 9999px rgba(0, 0, 0, 0.7), 0 0 0 8px rgba(40, 167, 69, 0.6);
299
+ box-shadow: 0 0 0 8px rgba(40, 167, 69, 0.6);
235
300
  }
236
301
  100% {
237
302
  border-color: #28a745;
238
- box-shadow: 0 0 0 9999px rgba(0, 0, 0, 0.7), 0 0 0 4px rgba(40, 167, 69, 0);
303
+ box-shadow: 0 0 0 4px rgba(40, 167, 69, 0);
239
304
  }
240
305
  }
241
306
 
@@ -470,6 +535,233 @@ video {
470
535
  transform: translateX(-50%) translateY(0);
471
536
  }
472
537
 
538
+ /* Camera controls */
539
+ .camera-controls {
540
+ position: absolute;
541
+ top: 16px;
542
+ right: 16px;
543
+ z-index: 25;
544
+ display: flex;
545
+ gap: 8px;
546
+ pointer-events: auto;
547
+ }
548
+
549
+
550
+ .camera-selector-button {
551
+ height: 32px;
552
+ padding: 0 10px;
553
+ border: none;
554
+ border-radius: 8px;
555
+ background: rgba(0, 0, 0, 0.25);
556
+ backdrop-filter: blur(12px);
557
+ color: #ffffff;
558
+ font-size: 12px;
559
+ font-weight: 500;
560
+ cursor: pointer;
561
+ transition: all 0.2s ease;
562
+ display: flex;
563
+ align-items: center;
564
+ justify-content: center;
565
+ border: 1px solid rgba(255, 255, 255, 0.1);
566
+ white-space: nowrap;
567
+ min-width: fit-content;
568
+ }
569
+
570
+ .camera-selector-button:hover {
571
+ background: rgba(0, 0, 0, 0.8);
572
+ border-color: rgba(255, 255, 255, 0.2);
573
+ transform: translateY(-1px);
574
+ }
575
+
576
+ .camera-selector-button:active {
577
+ transform: translateY(0);
578
+ background: rgba(0, 0, 0, 0.9);
579
+ }
580
+
581
+ .camera-selector-button:disabled,
582
+ .camera-selector-button.loading {
583
+ opacity: 0.7;
584
+ cursor: not-allowed;
585
+ pointer-events: none;
586
+ }
587
+
588
+ .camera-selector-button:disabled:hover,
589
+ .camera-selector-button.loading:hover {
590
+ transform: none;
591
+ background: rgba(0, 0, 0, 0.6);
592
+ border-color: rgba(255, 255, 255, 0.1);
593
+ }
594
+
595
+ .button-spinner {
596
+ width: 16px;
597
+ height: 16px;
598
+ border: 2px solid rgba(255, 255, 255, 0.3);
599
+ border-top: 2px solid #ffffff;
600
+ border-radius: 50%;
601
+ animation: spin 1s linear infinite;
602
+ }
603
+
604
+ @keyframes spin {
605
+ 0% { transform: rotate(0deg); }
606
+ 100% { transform: rotate(360deg); }
607
+ }
608
+
609
+ /* Camera selector dropdown */
610
+ .camera-selector-dropdown {
611
+ position: absolute;
612
+ top: 56px;
613
+ right: 16px;
614
+ z-index: 30;
615
+ background: rgba(0, 0, 0, 0.25);
616
+ backdrop-filter: blur(20px);
617
+ border-radius: 12px;
618
+ min-width: 260px;
619
+ max-width: 300px;
620
+ border: 1px solid rgba(255, 255, 255, 0.1);
621
+ overflow: hidden;
622
+ pointer-events: auto;
623
+ animation: slideInFromTop 0.3s ease-out;
624
+ }
625
+
626
+ @keyframes slideInFromTop {
627
+ 0% {
628
+ opacity: 0;
629
+ transform: translateY(-8px) scale(0.95);
630
+ }
631
+ 100% {
632
+ opacity: 1;
633
+ transform: translateY(0) scale(1);
634
+ }
635
+ }
636
+
637
+ .camera-selector-header {
638
+ display: flex;
639
+ justify-content: space-between;
640
+ align-items: center;
641
+ padding: 8px 12px;
642
+ border-bottom: 1px solid rgba(255, 255, 255, 0.1);
643
+ }
644
+
645
+ .camera-selector-header span {
646
+ font-weight: 500;
647
+ color: #ffffff;
648
+ font-size: 13px;
649
+ opacity: 0.9;
650
+ }
651
+
652
+ .close-selector {
653
+ width: 20px;
654
+ height: 20px;
655
+ border: none;
656
+ background: none;
657
+ color: rgba(255, 255, 255, 0.7);
658
+ font-size: 16px;
659
+ cursor: pointer;
660
+ display: flex;
661
+ align-items: center;
662
+ justify-content: center;
663
+ border-radius: 4px;
664
+ transition: all 0.2s ease;
665
+ }
666
+
667
+ .close-selector:hover {
668
+ background: rgba(255, 255, 255, 0.1);
669
+ color: #ffffff;
670
+ }
671
+
672
+ .camera-list {
673
+ padding: 4px 0;
674
+ max-height: 240px;
675
+ overflow-y: auto;
676
+ }
677
+
678
+ .camera-option {
679
+ width: 100%;
680
+ padding: 8px 12px;
681
+ border: none;
682
+ background: none;
683
+ text-align: left;
684
+ cursor: pointer;
685
+ transition: all 0.2s ease;
686
+ display: flex;
687
+ justify-content: space-between;
688
+ align-items: center;
689
+ color: rgba(255, 255, 255, 0.9);
690
+ }
691
+
692
+ .camera-option:hover {
693
+ background: rgba(255, 255, 255, 0.08);
694
+ }
695
+
696
+ .camera-option.selected {
697
+ background: rgba(255, 255, 255, 0.12);
698
+ color: #ffffff;
699
+ }
700
+
701
+ .camera-label {
702
+ font-size: 13px;
703
+ flex: 1;
704
+ white-space: nowrap;
705
+ overflow: hidden;
706
+ text-overflow: ellipsis;
707
+ margin-right: 8px;
708
+ font-weight: 400;
709
+ }
710
+
711
+ .selected-indicator {
712
+ font-size: 14px;
713
+ color: #ffffff;
714
+ opacity: 0.9;
715
+ }
716
+
717
+ .device-info {
718
+ padding: 6px 12px;
719
+ border-top: 1px solid rgba(255, 255, 255, 0.1);
720
+ background: rgba(255, 255, 255, 0.05);
721
+ }
722
+
723
+ .device-info small {
724
+ color: rgba(255, 255, 255, 0.6);
725
+ font-size: 11px;
726
+ text-transform: capitalize;
727
+ font-weight: 400;
728
+ }
729
+
730
+ /* Responsive design for camera controls */
731
+ @media (max-width: 480px) {
732
+ .camera-controls {
733
+ top: 12px;
734
+ right: 12px;
735
+ gap: 6px;
736
+ }
737
+
738
+ .camera-selector-button {
739
+ height: 36px;
740
+ padding: 0 12px;
741
+ font-size: 11px;
742
+ border-radius: 6px;
743
+ }
744
+
745
+ .camera-selector-dropdown {
746
+ right: 12px;
747
+ top: 48px;
748
+ min-width: 240px;
749
+ max-width: calc(100vw - 24px);
750
+ }
751
+
752
+ .camera-selector-header {
753
+ padding: 6px 10px;
754
+ }
755
+
756
+ .camera-option {
757
+ padding: 6px 10px;
758
+ }
759
+
760
+ .device-info {
761
+ padding: 4px 10px;
762
+ }
763
+ }
764
+
473
765
  /* Marca de agua */
474
766
  .watermark {
475
767
  position: absolute;
@@ -486,38 +778,131 @@ video {
486
778
  filter: drop-shadow(0 1px 2px rgba(0, 0, 0, 0.3));
487
779
  }
488
780
 
489
- /* Animación de carga */
781
+ /* Estado siempre visible del componente */
782
+ .component-status {
783
+ position: absolute;
784
+ top: 16px;
785
+ left: 16px;
786
+ background: rgba(0, 0, 0, 0.25);
787
+ backdrop-filter: blur(20px);
788
+ border-radius: 12px;
789
+ border: 1px solid rgba(255, 255, 255, 0.1);
790
+ display: flex;
791
+ align-items: center;
792
+ gap: 6px;
793
+ padding: 6px 10px;
794
+ z-index: 40;
795
+ height: 32px;
796
+ width: fit-content;
797
+ animation: slideInFromTop 0.3s ease-out;
798
+ }
799
+
800
+
801
+ .status-spinner {
802
+ width: 16px;
803
+ height: 16px;
804
+ border: 1px solid rgba(255, 255, 255, 0.3);
805
+ border-top: 1px solid #ffffff;
806
+ border-radius: 50%;
807
+ animation: statusSpin 1s linear infinite;
808
+ flex-shrink: 0;
809
+ }
810
+
811
+ .status-content {
812
+ display: flex;
813
+ flex-direction: column;
814
+ gap: 1px;
815
+ }
816
+
817
+ .status-message {
818
+ color: #ffffff;
819
+ font-size: 12px;
820
+ font-weight: 500;
821
+ margin: 0;
822
+ }
823
+
824
+ .status-description {
825
+ color: rgba(255, 255, 255, 0.7);
826
+ font-size: 10px;
827
+ line-height: 1.2;
828
+ margin: 0;
829
+ }
830
+
831
+ @keyframes statusSpin {
832
+ 0% {
833
+ transform: rotate(0deg);
834
+ }
835
+ 100% {
836
+ transform: rotate(360deg);
837
+ }
838
+ }
839
+
840
+ /* Responsive para estado en móviles */
841
+ @media (max-width: 480px) {
842
+ .component-status {
843
+ top: 12px;
844
+ left: 12px;
845
+ padding: 4px 8px;
846
+ gap: 4px;
847
+ height: 28px;
848
+ border-radius: 8px;
849
+ }
850
+
851
+ .status-spinner {
852
+ width: 14px;
853
+ height: 14px;
854
+ }
855
+
856
+ .status-message {
857
+ font-size: 11px;
858
+ }
859
+
860
+ .status-description {
861
+ font-size: 9px;
862
+ }
863
+ }
864
+
865
+ /* Animación de carga mejorada */
490
866
  .loading-overlay {
491
867
  position: absolute;
492
868
  top: 0;
493
869
  left: 0;
494
870
  width: 100%;
495
871
  height: 100%;
496
- background: rgba(0, 0, 0, 0.8);
872
+ background: rgba(0, 0, 0, 0.85);
873
+ backdrop-filter: blur(4px);
497
874
  display: flex;
498
875
  flex-direction: column;
499
876
  align-items: center;
500
877
  justify-content: center;
501
878
  z-index: 30;
502
- border-radius: 20px;
879
+ border-radius: 8px;
503
880
  }
504
881
 
505
882
  .loading-spinner {
506
- width: 60px;
507
- height: 60px;
508
- border: 4px solid rgba(255, 255, 255, 0.2);
509
- border-top: 4px solid #007bff;
883
+ width: 50px;
884
+ height: 50px;
885
+ border: 3px solid rgba(255, 255, 255, 0.15);
886
+ border-top: 3px solid #28a745;
510
887
  border-radius: 50%;
511
- animation: spin 1s linear infinite;
512
- margin-bottom: 20px;
888
+ animation: spin 1s ease-in-out infinite;
889
+ margin-bottom: 16px;
513
890
  }
514
891
 
515
892
  .loading-text {
516
- color: white;
517
- font-size: 16px;
893
+ color: #ffffff;
894
+ font-size: 14px;
518
895
  font-weight: 500;
519
896
  text-align: center;
520
897
  opacity: 0.9;
898
+ margin-bottom: 4px;
899
+ }
900
+
901
+ .loading-description {
902
+ color: rgba(255, 255, 255, 0.7);
903
+ font-size: 12px;
904
+ text-align: center;
905
+ opacity: 0.8;
521
906
  }
522
907
 
523
908
  @keyframes spin {
@@ -527,4 +912,176 @@ video {
527
912
  100% {
528
913
  transform: rotate(360deg);
529
914
  }
530
- }
915
+ }
916
+
917
+ /* Monitor de Performance - Diseño compacto y minimalista */
918
+ .performance-monitor {
919
+ position: absolute;
920
+ top: 70px;
921
+ left: 16px;
922
+ background: rgba(0, 0, 0, 0.25);
923
+ backdrop-filter: blur(20px);
924
+ border-radius: 12px;
925
+ border: 1px solid rgba(255, 255, 255, 0.1);
926
+ z-index: 35;
927
+ width: fit-content;
928
+ animation: slideInFromLeft 0.3s ease-out;
929
+ transition: all 0.3s ease;
930
+ }
931
+
932
+ @keyframes slideInFromLeft {
933
+ 0% {
934
+ opacity: 0;
935
+ transform: translateX(-20px) scale(0.95);
936
+ }
937
+ 100% {
938
+ opacity: 1;
939
+ transform: translateX(0) scale(1);
940
+ }
941
+ }
942
+
943
+
944
+ .performance-expanded {
945
+ padding: 6px 10px;
946
+ }
947
+
948
+ .metrics-row {
949
+ display: flex;
950
+ gap: 8px;
951
+ margin-bottom: 4px;
952
+ }
953
+
954
+ .metrics-row:last-child {
955
+ margin-bottom: 0;
956
+ }
957
+
958
+ .metric-compact {
959
+ display: flex;
960
+ flex-direction: column;
961
+ align-items: center;
962
+ gap: 2px;
963
+ min-width: 50px;
964
+ }
965
+
966
+ .metric-label {
967
+ font-size: 9px;
968
+ color: rgba(255, 255, 255, 0.6);
969
+ font-weight: 500;
970
+ text-transform: uppercase;
971
+ letter-spacing: 0.3px;
972
+ }
973
+
974
+ .metric-value {
975
+ font-size: 10px;
976
+ font-weight: 600;
977
+ font-family: 'Monaco', 'Menlo', 'Consolas', monospace;
978
+ padding: 2px 4px;
979
+ border-radius: 3px;
980
+ text-align: center;
981
+ white-space: nowrap;
982
+ }
983
+
984
+ .metric-value.good {
985
+ color: #4ade80;
986
+ background: rgba(74, 222, 128, 0.1);
987
+ border: 1px solid rgba(74, 222, 128, 0.2);
988
+ }
989
+
990
+ .metric-value.warning {
991
+ color: #fbbf24;
992
+ background: rgba(251, 191, 36, 0.1);
993
+ border: 1px solid rgba(251, 191, 36, 0.2);
994
+ }
995
+
996
+ .metric-value.danger {
997
+ color: #f87171;
998
+ background: rgba(248, 113, 113, 0.1);
999
+ border: 1px solid rgba(248, 113, 113, 0.2);
1000
+ }
1001
+
1002
+ /* Responsive para monitor de performance */
1003
+ @media (max-width: 480px) {
1004
+ .performance-monitor {
1005
+ top: 60px;
1006
+ left: 12px;
1007
+ width: fit-content;
1008
+ }
1009
+
1010
+ .performance-expanded {
1011
+ padding: 4px 8px;
1012
+ }
1013
+
1014
+ .metrics-row {
1015
+ gap: 6px;
1016
+ margin-bottom: 3px;
1017
+ }
1018
+
1019
+ .metric-compact {
1020
+ min-width: 45px;
1021
+ gap: 1px;
1022
+ }
1023
+
1024
+ .metric-label {
1025
+ font-size: 8px;
1026
+ }
1027
+
1028
+ .metric-value {
1029
+ font-size: 9px;
1030
+ padding: 1px 3px;
1031
+ }
1032
+ }
1033
+
1034
+ /* Quality Monitor */
1035
+ .quality-monitor {
1036
+ position: absolute;
1037
+ top: 200px;
1038
+ left: 16px;
1039
+ background: rgba(0, 0, 0, 0.25);
1040
+ backdrop-filter: blur(20px);
1041
+ border-radius: 12px;
1042
+ border: 1px solid rgba(255, 255, 255, 0.1);
1043
+ z-index: 35;
1044
+ width: fit-content;
1045
+ animation: slideInFromLeft 0.3s ease-out;
1046
+ transition: all 0.3s ease;
1047
+ }
1048
+
1049
+ .quality-text {
1050
+ padding: 6px 10px;
1051
+ font-size: 11px;
1052
+ color: white;
1053
+ font-family: 'Monaco', 'Menlo', 'Consolas', monospace;
1054
+ line-height: 1.4;
1055
+ }
1056
+
1057
+ .quality-fail {
1058
+ color: #ff9999;
1059
+ }
1060
+
1061
+ /* Animación pulsante para valores críticos */
1062
+ @keyframes pulse {
1063
+ 0%, 100% {
1064
+ opacity: 1;
1065
+ }
1066
+ 50% {
1067
+ opacity: 0.7;
1068
+ }
1069
+ }
1070
+
1071
+ .metric-value.danger {
1072
+ animation: pulse 2s infinite;
1073
+ }
1074
+
1075
+ /* Mobile optimizations */
1076
+ @media (max-width: 480px) {
1077
+ .quality-monitor {
1078
+ top: 160px;
1079
+ left: 12px;
1080
+ }
1081
+
1082
+ .quality-text {
1083
+ padding: 4px 8px;
1084
+ font-size: 10px;
1085
+ }
1086
+ }
1087
+