@jaak.ai/stamps 2.2.0-dev.9 → 2.3.0-dev.1

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 (30) hide show
  1. package/README.md +188 -8
  2. package/dist/cjs/jaak-stamps.cjs.entry.js +124 -25
  3. package/dist/cjs/jaak-stamps.cjs.entry.js.map +1 -1
  4. package/dist/cjs/jaak-stamps.entry.cjs.js.map +1 -1
  5. package/dist/collection/components/my-component/my-component.css +23 -2
  6. package/dist/collection/components/my-component/my-component.js +44 -16
  7. package/dist/collection/components/my-component/my-component.js.map +1 -1
  8. package/dist/collection/services/CameraService.js +41 -9
  9. package/dist/collection/services/CameraService.js.map +1 -1
  10. package/dist/collection/services/LicenseValidationService.js +1 -1
  11. package/dist/collection/services/LicenseValidationService.js.map +1 -1
  12. package/dist/collection/services/factories/DeviceStrategyFactory.js +7 -0
  13. package/dist/collection/services/factories/DeviceStrategyFactory.js.map +1 -1
  14. package/dist/collection/services/strategies/IOSSafariStrategy.js +33 -0
  15. package/dist/collection/services/strategies/IOSSafariStrategy.js.map +1 -0
  16. package/dist/components/jaak-stamps.js +124 -25
  17. package/dist/components/jaak-stamps.js.map +1 -1
  18. package/dist/esm/jaak-stamps.entry.js +124 -25
  19. package/dist/esm/jaak-stamps.entry.js.map +1 -1
  20. package/dist/jaak-stamps-webcomponent/jaak-stamps-webcomponent.esm.js +1 -1
  21. package/dist/jaak-stamps-webcomponent/jaak-stamps.entry.esm.js.map +1 -1
  22. package/dist/jaak-stamps-webcomponent/p-04f57d50.entry.js +7 -0
  23. package/dist/jaak-stamps-webcomponent/p-04f57d50.entry.js.map +1 -0
  24. package/dist/types/components/my-component/my-component.d.ts +2 -1
  25. package/dist/types/components.d.ts +2 -2
  26. package/dist/types/services/LicenseValidationService.d.ts +1 -1
  27. package/dist/types/services/strategies/IOSSafariStrategy.d.ts +12 -0
  28. package/package.json +1 -1
  29. package/dist/jaak-stamps-webcomponent/p-dfecb452.entry.js +0 -7
  30. package/dist/jaak-stamps-webcomponent/p-dfecb452.entry.js.map +0 -1
@@ -530,17 +530,30 @@ class CameraService {
530
530
  }
531
531
  const constraints = { ...videoConstraints };
532
532
  if (capabilities.width && capabilities.height) {
533
- const maxWidth = Math.min(capabilities.width.max, 1920);
534
- const maxHeight = Math.min(capabilities.height.max, 1080);
535
533
  const isTablet = /iPad|Android/i.test(navigator.userAgent) && window.innerWidth >= 768;
536
- if (isTablet) {
537
- constraints.width = { ideal: Math.min(maxWidth, 1280) };
538
- constraints.height = { ideal: Math.min(maxHeight, 720) };
534
+ const isMobileDevice = this.deviceType === 'mobile' ||
535
+ /Android|iPhone|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);
536
+ // Optimize resolution based on device type to prevent "slow motion" effect
537
+ // on devices with high-resolution cameras
538
+ let targetWidth;
539
+ let targetHeight;
540
+ if (isMobileDevice && !isTablet) {
541
+ // Mobile phones: Use 720p max to ensure smooth detection performance
542
+ targetWidth = Math.min(capabilities.width.max, 1280);
543
+ targetHeight = Math.min(capabilities.height.max, 720);
544
+ }
545
+ else if (isTablet) {
546
+ // Tablets: Can handle slightly higher resolution
547
+ targetWidth = Math.min(capabilities.width.max, 1280);
548
+ targetHeight = Math.min(capabilities.height.max, 720);
539
549
  }
540
550
  else {
541
- constraints.width = { ideal: maxWidth };
542
- constraints.height = { ideal: maxHeight };
551
+ // Desktop: Can handle full HD
552
+ targetWidth = Math.min(capabilities.width.max, 1920);
553
+ targetHeight = Math.min(capabilities.height.max, 1080);
543
554
  }
555
+ constraints.width = { ideal: targetWidth };
556
+ constraints.height = { ideal: targetHeight };
544
557
  }
545
558
  // Configure autofocus if camera has the capability
546
559
  const capabilitiesAny = capabilities;
@@ -560,9 +573,28 @@ class CameraService {
560
573
  await this.detectDeviceType();
561
574
  }
562
575
  const isTablet = /iPad|Android/i.test(navigator.userAgent) && window.innerWidth >= 768;
576
+ const isMobileDevice = this.deviceType === 'mobile' ||
577
+ /Android|iPhone|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);
578
+ // Optimized fallback constraints for device type
579
+ let fallbackWidth;
580
+ let fallbackHeight;
581
+ if (isMobileDevice && !isTablet) {
582
+ // Mobile phones: Use 720p for smooth performance
583
+ fallbackWidth = 1280;
584
+ fallbackHeight = 720;
585
+ }
586
+ else if (isTablet) {
587
+ fallbackWidth = 1280;
588
+ fallbackHeight = 720;
589
+ }
590
+ else {
591
+ // Desktop
592
+ fallbackWidth = 1920;
593
+ fallbackHeight = 1080;
594
+ }
563
595
  const fallbackConstraints = {
564
- width: { ideal: isTablet ? 1280 : 1920 },
565
- height: { ideal: isTablet ? 720 : 1080 }
596
+ width: { ideal: fallbackWidth },
597
+ height: { ideal: fallbackHeight }
566
598
  };
567
599
  if (this.selectedCameraId) {
568
600
  fallbackConstraints.deviceId = { exact: this.selectedCameraId };
@@ -695,9 +727,48 @@ class HighPerformanceDeviceStrategy {
695
727
  }
696
728
  }
697
729
 
730
+ /**
731
+ * Strategy for iOS Safari to prevent jetsam memory kills.
732
+ * WebKit 26+ has a known bug with ONNX Runtime JSEP mode that causes memory exhaustion.
733
+ * This strategy forces pure WASM execution without GPU acceleration.
734
+ * See: https://github.com/microsoft/onnxruntime/issues/26827
735
+ */
736
+ class IOSSafariStrategy {
737
+ getDeviceInfo() {
738
+ return {
739
+ estimatedRAM: 3, // Assume low memory for iOS
740
+ isLowMemory: true,
741
+ isSlowConnection: false
742
+ };
743
+ }
744
+ getSessionOptions(_debug) {
745
+ return {
746
+ // Force pure WASM - no WebGL, no WebGPU, no JSEP
747
+ executionProviders: ['wasm'],
748
+ graphOptimizationLevel: 'disabled', // Disable graph optimization to reduce memory
749
+ logSeverityLevel: 4,
750
+ logVerbosityLevel: 0,
751
+ enableCpuMemArena: false, // Don't use CPU memory arena
752
+ enableMemPattern: false, // Don't use memory pattern optimization
753
+ executionMode: 'sequential', // Sequential execution uses less memory
754
+ interOpNumThreads: 1, // Single thread
755
+ intraOpNumThreads: 1, // Single thread
756
+ };
757
+ }
758
+ shouldUseSequentialLoading() {
759
+ return true;
760
+ }
761
+ }
762
+
698
763
  class DeviceStrategyFactory {
699
764
  static createStrategy() {
700
765
  const nav = navigator;
766
+ const ua = navigator.userAgent;
767
+ // iOS Safari requires special handling due to WebKit memory constraints
768
+ const isIOSSafari = /iPad|iPhone|iPod/.test(ua) && /Safari/.test(ua) && !/CriOS|FxiOS|OPiOS|EdgiOS/.test(ua);
769
+ if (isIOSSafari) {
770
+ return new IOSSafariStrategy();
771
+ }
701
772
  const memory = nav.deviceMemory || nav.hardwareConcurrency || 4;
702
773
  const isLowMemory = memory <= 4;
703
774
  if (isLowMemory) {
@@ -18457,7 +18528,7 @@ class LicenseValidationService {
18457
18528
  static ENVIRONMENT_URLS = {
18458
18529
  dev: 'https://api.dev.jaak.ai',
18459
18530
  qa: 'https://api.qa.jaak.ai',
18460
- staging: 'https://api.sandbox.jaak.ai',
18531
+ sandbox: 'https://api.sandbox.jaak.ai',
18461
18532
  prod: 'https://services.api.jaak.ai',
18462
18533
  };
18463
18534
  constructor(environment = 'prod') {
@@ -18557,7 +18628,7 @@ class LicenseValidationService {
18557
18628
  }
18558
18629
  }
18559
18630
 
18560
- const myComponentCss = ":host{display:block;width:100%;height:100%;font-family:system-ui, -apple-system, sans-serif;color:#1a1a1a}.detector-container{display:flex;flex-direction:column;align-items:center;width:100%;height:100%}h1{font-size:24px;font-weight:500;color:#333;margin:0 0 24px 0}.video-container{position:relative;width:100%;height:100%;background:#333;border:1px solid #e0e0e0;border-radius:8px;overflow:hidden}video,.detection-overlay{position:absolute;width:100%;height:100%;border-radius:8px}video.mirror,.detection-overlay.mirror{transform:rotateY(180deg)}.detection-overlay{z-index:1;pointer-events:none}video{z-index:0}.detection-box{transition:opacity 0.2s ease}.status{margin-top:16px;font-size:12px;color:#666}.overlay-mask{position:absolute;top:0;left:0;width:100%;height:100%;z-index:10;display:block;pointer-events:none}.card-outline{position:absolute;top:var(--mask-center-y, 50%);left:var(--mask-center-x, 50%);transform:translate(-50%, -50%);width:var(--mask-width, 88%);height:var(--mask-height, 55%);border:none;border-radius:4px;background:transparent;opacity:0.8}.side{position:absolute;background:#999;transition:background-color 0.3s ease;border-radius:1px}.side-top.aligned{border-left-color:#28a745;border-top-color:#28a745}.side-right.aligned{border-right-color:#28a745;border-top-color:#28a745}.side-bottom.aligned{border-left-color:#28a745;border-bottom-color:#28a745}.side-left.aligned{border-right-color:#28a745;border-bottom-color:#28a745}.side-top{top:-3px;left:-3px;width:30px;height:30px;border-left:6px solid #ffffff;border-top:6px solid #ffffff;background:transparent}.side-right{top:-3px;right:-3px;width:30px;height:30px;border-right:6px solid #ffffff;border-top:6px solid #ffffff;background:transparent}.side-bottom{bottom:-3px;left:-3px;width:30px;height:30px;border-left:6px solid #ffffff;border-bottom:6px solid #ffffff;background:transparent}.side-left{bottom:-3px;right:-3px;width:30px;height:30px;border-right:6px solid #ffffff;border-bottom:6px solid #ffffff;background:transparent}.guide-text{position:absolute;top:50%;left:50%;transform:translate(-50%, -50%);background:rgba(0, 0, 0, 0.25);backdrop-filter:blur(20px);border-radius:12px;border:1px solid rgba(255, 255, 255, 0.1);color:#ffffff;font-size:12px;font-weight:500;text-align:center;white-space:normal;padding:13px;max-width:300px;z-index:20;height:fit-content;width:fit-content;animation:slideInFromTopCentered 0.3s ease-out}.quality-indicator{position:absolute;top:20px;right:20px;display:flex;align-items:center;gap:8px;background:rgba(0, 0, 0, 0.8);padding:8px 12px;border-radius:20px;z-index:25;transition:all 0.3s ease}.quality-indicator.warning{background:rgba(255, 152, 0, 0.9)}.quality-indicator.good{background:rgba(76, 175, 80, 0.9)}.quality-score{color:#fff;font-size:12px;font-weight:600;min-width:30px;text-align:center}.quality-status{width:20px;height:20px;border-radius:50%;display:flex;align-items:center;justify-content:center;font-size:14px;font-weight:bold;color:#fff;transition:all 0.3s ease}.quality-status.ready{background:#4CAF50}.quality-status.not-ready{background:#f44336}.card-outline.quality-warning{animation:qualityWarning 1s ease-in-out infinite alternate}@keyframes qualityWarning{0%{box-shadow:0 0 0 3px rgba(255, 152, 0, 0.6)}100%{box-shadow:0 0 0 6px rgba(255, 152, 0, 0.3)}}.capture-animation{position:absolute;top:0;left:0;width:100%;height:100%;background:#fff;opacity:0;z-index:30;pointer-events:none;animation:captureFlash 0.6s ease-out}@keyframes captureFlash{0%{opacity:0}15%{opacity:0.8}30%{opacity:0}45%{opacity:0.4}60%{opacity:0}100%{opacity:0}}.card-outline.capturing{animation:pulseGreen 0.6s ease-out}@keyframes pulseGreen{0%{border-color:#28a745;box-shadow:0 0 0 4px rgba(40, 167, 69, 0)}50%{border-color:#28a745;box-shadow:0 0 0 8px rgba(40, 167, 69, 0.6)}100%{border-color:#28a745;box-shadow:0 0 0 4px rgba(40, 167, 69, 0)}}.flip-animation{position:absolute;top:50%;left:50%;transform:translate(-50%, -50%);z-index:35;pointer-events:none;opacity:0;animation:showFlipInstruction 3s ease-in-out;display:flex;flex-direction:column;align-items:center;justify-content:center}.id-card-icon{width:80px;height:50px;background:linear-gradient(135deg, #6c757d 0%, #495057 100%);border-radius:8px;position:relative;animation:flipCard 2s ease-in-out infinite;box-shadow:0 4px 12px rgba(0, 0, 0, 0.3)}.id-card-icon::before{content:'';position:absolute;top:8px;left:8px;width:16px;height:12px;background:rgba(255, 255, 255, 0.9);border-radius:2px}.id-card-icon::after{content:'';position:absolute;top:25px;left:8px;width:64px;height:3px;background:rgba(255, 255, 255, 0.7);border-radius:1px;box-shadow:0 6px 0 rgba(255, 255, 255, 0.7), 0 12px 0 rgba(255, 255, 255, 0.7)}.flip-text{margin-top:12px;color:#fff;font-size:14px;font-weight:600;text-align:center;background:rgba(128, 128, 128, 0.8);padding:12px 20px;border-radius:20px;max-width:300px}@keyframes showFlipInstruction{0%{opacity:0;transform:translate(-50%, -50%) scale(0.8)}15%{opacity:1;transform:translate(-50%, -50%) scale(1)}85%{opacity:1;transform:translate(-50%, -50%) scale(1)}100%{opacity:0;transform:translate(-50%, -50%) scale(0.8)}}@keyframes flipCard{0%{transform:rotateY(0deg)}50%{transform:rotateY(180deg)}100%{transform:rotateY(360deg)}}.success-animation{position:absolute;top:50%;left:50%;transform:translate(-50%, -50%);z-index:35;pointer-events:none;opacity:0;animation:showSuccessMessage 3s ease-in-out;display:flex;flex-direction:column;align-items:center;justify-content:center}.check-icon{width:80px;height:80px;background:linear-gradient(135deg, #6c757d 0%, #495057 100%);border-radius:50%;position:relative;animation:bounceSuccess 0.6s ease-out;box-shadow:0 4px 16px rgba(108, 117, 125, 0.4);display:flex;align-items:center;justify-content:center}.check-icon::before{content:'';position:absolute;width:20px;height:35px;border:4px solid #fff;border-top:none;border-left:none;transform:rotate(45deg);}.success-text{margin-top:16px;color:#fff;font-size:14px;font-weight:600;text-align:center;background:rgba(128, 128, 128, 0.8);padding:12px 20px;border-radius:20px;max-width:300px;animation:fadeInUp 0.5s ease-out 0.4s both}@keyframes showSuccessMessage{0%{opacity:0;transform:translate(-50%, -50%) scale(0.5)}15%{opacity:1;transform:translate(-50%, -50%) scale(1)}85%{opacity:1;transform:translate(-50%, -50%) scale(1)}100%{opacity:0;transform:translate(-50%, -50%) scale(0.9)}}@keyframes bounceSuccess{0%{transform:scale(0)}50%{transform:scale(1.1)}100%{transform:scale(1)}}@keyframes drawCheck{0%{width:0;height:0}50%{width:20px;height:0}100%{width:20px;height:35px}}@keyframes fadeInUp{0%{opacity:0;transform:translateY(20px)}100%{opacity:1;transform:translateY(0)}}.skip-section{position:absolute;bottom:20px;left:50%;transform:translateX(-50%);z-index:25;display:flex;flex-direction:column;align-items:center;width:100%;max-width:300px}.back-capture-section{position:absolute;bottom:20px;left:50%;transform:translateX(-50%);z-index:25;display:flex;flex-direction:column;align-items:center;width:100%;max-width:320px}.back-capture-buttons{display:flex;gap:12px;align-items:center;justify-content:center;flex-wrap:wrap}.capture-button{pointer-events:auto;background:#fff;color:#333;border:none;border-radius:25px;padding:12px 24px;font-size:14px;font-weight:600;cursor:pointer;transition:all 0.3s ease}.capture-button:hover{background:#f8f9fa}.capture-button:active{background:#e9ecef;transform:translateY(1px)}.capture-button:disabled,.capture-button.primary-button:disabled{cursor:not-allowed !important;transform:none !important;opacity:0.7 !important;transition:none !important}@media (max-width: 480px){.back-capture-section{bottom:16px;max-width:300px}.back-capture-buttons{flex-direction:column;gap:8px;width:100%}.capture-button,.back-capture-buttons .skip-button{width:100%;max-width:200px;padding:10px 20px;font-size:13px}.capture-button:disabled,.capture-button.primary-button:disabled,.skip-button:disabled{opacity:0.7 !important;cursor:not-allowed !important}}.skip-explanation{background:rgba(0, 0, 0, 0.5);color:#ffffff;padding:10px 16px;border-radius:8px;font-size:14px;font-weight:500;text-align:center;margin-bottom:12px;box-shadow:0 2px 8px rgba(0, 0, 0, 0.2);backdrop-filter:blur(12px);border:1px solid rgba(255, 255, 255, 0.1);animation:fadeIn 0.3s ease-in-out}@keyframes fadeIn{from{opacity:0;transform:translateY(10px)}to{opacity:1;transform:translateY(0)}}.guide-text.performance-warning-text{animation:gentlePulse 2s ease-in-out infinite;background:rgba(255, 107, 107, 0.3);border:1px solid rgba(255, 107, 107, 0.5)}@keyframes gentlePulse{0%,100%{transform:translate(-50%, -50%) scale(1);background:rgba(255, 107, 107, 0.3)}50%{transform:translate(-50%, -50%) scale(1.02);background:rgba(255, 107, 107, 0.4)}}.skip-button{pointer-events:auto;background:#fff;color:#333;border:none;border-radius:25px;padding:12px 24px;font-size:14px;font-weight:600;cursor:pointer;transition:all 0.3s ease}.skip-button:hover{background:#f8f9fa}.skip-button:active{background:#e9ecef;transform:translateY(1px)}.skip-button:disabled{cursor:not-allowed !important;transform:none !important;opacity:0.7 !important;transition:none !important}.camera-controls{position:absolute;top:16px;right:16px;z-index:25;display:flex;gap:8px;pointer-events:auto;animation:slideInFromTop 0.3s ease-out}.camera-selector-button{height:32px;padding:0 10px;border:none;border-radius:8px;background:rgba(0, 0, 0, 0.25);backdrop-filter:blur(12px);color:#ffffff;font-size:12px;font-weight:500;cursor:pointer;transition:all 0.2s ease;display:flex;align-items:center;justify-content:center;border:1px solid rgba(255, 255, 255, 0.1);white-space:nowrap;min-width:fit-content}.camera-selector-button:hover{background:rgba(0, 0, 0, 0.8);border-color:rgba(255, 255, 255, 0.2);transform:translateY(-1px)}.camera-selector-button:active{transform:translateY(0);background:rgba(0, 0, 0, 0.9)}.camera-selector-button:disabled,.camera-selector-button.loading{opacity:0.7;cursor:not-allowed;pointer-events:none}.camera-selector-button:disabled:hover,.camera-selector-button.loading:hover{transform:none;background:rgba(0, 0, 0, 0.6);border-color:rgba(255, 255, 255, 0.1)}.button-spinner{width:16px;height:16px;border:2px solid rgba(0, 0, 0, 0.2);border-top:2px solid #333333;border-radius:50%;animation:spin 1s linear infinite;display:inline-block;margin-right:8px;vertical-align:middle}@keyframes spin{0%{transform:rotate(0deg)}100%{transform:rotate(360deg)}}.camera-selector-dropdown{position:absolute;top:56px;right:16px;z-index:30;background:rgba(0, 0, 0, 0.25);backdrop-filter:blur(20px);border-radius:12px;min-width:260px;max-width:300px;border:1px solid rgba(255, 255, 255, 0.1);overflow:hidden;pointer-events:auto;animation:slideInFromTop 0.3s ease-out}@keyframes slideInFromTop{0%{opacity:0;transform:translateY(-8px) scale(0.95)}100%{opacity:1;transform:translateY(0) scale(1)}}@keyframes slideInFromTopCentered{0%{opacity:0;transform:translate(-50%, -50%) translateY(-8px) scale(0.95)}100%{opacity:1;transform:translate(-50%, -50%) translateY(0) scale(1)}}.camera-selector-header{display:flex;justify-content:space-between;align-items:center;padding:8px 12px;border-bottom:1px solid rgba(255, 255, 255, 0.1)}.camera-selector-header span{font-weight:500;color:#ffffff;font-size:13px;opacity:0.9}.close-selector{width:20px;height:20px;border:none;background:none;color:rgba(255, 255, 255, 0.7);font-size:16px;cursor:pointer;display:flex;align-items:center;justify-content:center;border-radius:4px;transition:all 0.2s ease}.close-selector:hover{background:rgba(255, 255, 255, 0.1);color:#ffffff}.camera-list{padding:4px 0;max-height:240px;overflow-y:auto}.camera-option{width:100%;padding:8px 12px;border:none;background:none;text-align:left;cursor:pointer;transition:all 0.2s ease;display:flex;justify-content:flex-start;align-items:center;gap:8px;color:rgba(255, 255, 255, 0.9)}.camera-option:hover{background:rgba(255, 255, 255, 0.08)}.camera-option.selected{background:rgba(255, 255, 255, 0.12);color:#ffffff}.camera-label{font-size:13px;flex:1;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;margin-right:0;font-weight:400;display:flex;align-items:center;gap:6px}.camera-label .autofocus-icon{font-size:12px;color:#ffffff !important;opacity:0.8;flex-shrink:0}.selected-indicator{font-size:14px;color:#ffffff;opacity:0.9;flex-shrink:0}.device-info{padding:6px 12px;border-top:1px solid rgba(255, 255, 255, 0.1);background:rgba(255, 255, 255, 0.05)}.device-info small{color:rgba(255, 255, 255, 0.6);font-size:11px;text-transform:capitalize;font-weight:400}@media (max-width: 480px){.camera-controls{top:12px;right:12px;gap:6px}.camera-selector-button{height:36px;padding:0 12px;font-size:11px;border-radius:6px}.camera-selector-dropdown{right:12px;top:48px;min-width:240px;max-width:calc(100vw - 24px)}.camera-selector-header{padding:6px 10px}.camera-option{padding:6px 10px}.device-info{padding:4px 10px}}.watermark{position:absolute;bottom:12px;right:12px;z-index:15;pointer-events:none;opacity:0.7}.watermark img{height:24px;width:auto;filter:drop-shadow(0 1px 2px rgba(0, 0, 0, 0.3))}.component-status{position:absolute;top:16px;left:16px;background:rgba(0, 0, 0, 0.25);backdrop-filter:blur(20px);border-radius:12px;border:1px solid rgba(255, 255, 255, 0.1);display:flex;align-items:center;gap:6px;padding:6px 10px;z-index:40;height:32px;width:fit-content;animation:slideInFromTop 0.3s ease-out}.status-spinner{width:16px;height:16px;border:1px solid rgba(255, 255, 255, 0.3);border-top:1px solid #ffffff;border-radius:50%;animation:statusSpin 1s linear infinite;flex-shrink:0}.status-content{display:flex;flex-direction:column;gap:1px}.status-message{color:#ffffff;font-size:12px;font-weight:500;margin:0}.status-description{color:rgba(255, 255, 255, 0.7);font-size:10px;line-height:1.2;margin:0}@keyframes statusSpin{0%{transform:rotate(0deg)}100%{transform:rotate(360deg)}}@media (max-width: 480px){.component-status{top:12px;left:12px;padding:4px 8px;gap:4px;height:28px;border-radius:8px}.status-spinner{width:14px;height:14px}.status-message{font-size:11px}.status-description{font-size:9px}.guide-text{font-size:11px;padding:4px 8px;border-radius:8px}}.loading-overlay{position:absolute;top:0;left:0;width:100%;height:100%;background:rgba(0, 0, 0, 0.85);backdrop-filter:blur(4px);display:flex;flex-direction:column;align-items:center;justify-content:center;z-index:30;border-radius:8px}.loading-spinner{width:50px;height:50px;border:3px solid rgba(255, 255, 255, 0.15);border-top:3px solid #28a745;border-radius:50%;animation:spin 1s ease-in-out infinite;margin-bottom:16px}.loading-text{color:#ffffff;font-size:14px;font-weight:500;text-align:center;opacity:0.9;margin-bottom:4px}.loading-description{color:rgba(255, 255, 255, 0.7);font-size:12px;text-align:center;opacity:0.8}@keyframes spin{0%{transform:rotate(0deg)}100%{transform:rotate(360deg)}}.performance-monitor{position:absolute;top:70px;left:16px;background:rgba(0, 0, 0, 0.25);backdrop-filter:blur(20px);border-radius:12px;border:1px solid rgba(255, 255, 255, 0.1);z-index:35;width:fit-content;animation:slideInFromTop 0.3s ease-out;transition:all 0.3s ease}@keyframes slideInFromLeft{0%{opacity:0;transform:translateX(-20px) scale(0.95)}100%{opacity:1;transform:translateX(0) scale(1)}}.performance-expanded{padding:6px 10px}.metrics-row{display:flex;gap:8px;margin-bottom:4px}.metrics-row:last-child{margin-bottom:0}.metric-compact{display:flex;flex-direction:column;align-items:center;gap:2px;min-width:50px}.metric-label{font-size:9px;color:rgba(255, 255, 255, 0.6);font-weight:500;text-transform:uppercase;letter-spacing:0.3px}.metric-value{font-size:10px;font-weight:600;font-family:'Monaco', 'Menlo', 'Consolas', monospace;padding:2px 4px;border-radius:3px;text-align:center;white-space:nowrap}.metric-value.good{color:#4ade80;background:rgba(74, 222, 128, 0.1);border:1px solid rgba(74, 222, 128, 0.2)}.metric-value.warning{color:#fbbf24;background:rgba(251, 191, 36, 0.1);border:1px solid rgba(251, 191, 36, 0.2)}.metric-value.danger{color:#f87171;background:rgba(248, 113, 113, 0.1);border:1px solid rgba(248, 113, 113, 0.2)}@media (max-width: 480px){.performance-monitor{top:60px;left:12px;width:fit-content}.performance-expanded{padding:4px 8px}.metrics-row{gap:6px;margin-bottom:3px}.metric-compact{min-width:45px;gap:1px}.metric-label{font-size:8px}.metric-value{font-size:9px;padding:1px 3px}}.quality-monitor{position:absolute;top:200px;left:16px;background:rgba(0, 0, 0, 0.25);backdrop-filter:blur(20px);border-radius:12px;border:1px solid rgba(255, 255, 255, 0.1);z-index:35;width:fit-content;animation:slideInFromLeft 0.3s ease-out;transition:all 0.3s ease}.quality-text{padding:6px 10px;font-size:11px;color:white;font-family:'Monaco', 'Menlo', 'Consolas', monospace;line-height:1.4}.quality-fail{color:#ff9999}@keyframes pulse{0%,100%{opacity:1}50%{opacity:0.7}}.metric-value.danger{animation:pulse 2s infinite}@media (max-width: 480px){.quality-monitor{top:160px;left:12px}.quality-text{padding:4px 8px;font-size:10px}}.manual-capture-section{position:absolute;bottom:20px;left:50%;transform:translateX(-50%);z-index:25;display:flex;flex-direction:column;align-items:center;width:100%;max-width:300px}.manual-capture-button{pointer-events:auto;background:#fff;color:#333;border:none;border-radius:25px;padding:12px 24px;font-size:14px;font-weight:600;cursor:pointer;transition:all 0.3s ease}.manual-capture-button:hover{background:#f8f9fa}.manual-capture-button:active{background:#e9ecef;transform:translateY(1px)}.manual-capture-button:disabled{cursor:not-allowed !important;transform:none !important;opacity:0.7 !important;transition:none !important}@media (max-width: 480px){.manual-capture-section{bottom:16px;max-width:280px}.manual-capture-button{padding:10px 20px;font-size:13px}.manual-capture-button:disabled{opacity:0.7 !important;cursor:not-allowed !important}}.license-error-container{display:flex;align-items:center;justify-content:center;padding:40px 20px;height:100%;width:100%;background:#f5f7fa;font-family:-apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', sans-serif}.license-error-card{background:#ffffff;border-radius:8px;box-shadow:0 2px 12px rgba(0, 0, 0, 0.1);max-width:480px;width:100%;padding:48px 32px;text-align:center}.license-error-icon{color:#dc3545;margin-bottom:24px}.license-error-title{color:#2c3e50;font-size:24px;font-weight:600;margin:0 0 16px 0}.license-error-message{color:#495057;font-size:16px;line-height:1.6;margin:0 0 24px 0}.license-error-help{color:#6c757d;font-size:14px;margin:0 0 32px 0}.license-error-help a{color:#007bff;text-decoration:none;font-weight:500}.license-error-help a:hover{text-decoration:underline}.license-error-footer{color:#adb5bd;font-size:12px;font-weight:500;padding-top:24px;border-top:1px solid #e9ecef}@media (max-width: 640px){.license-error-card{padding:32px 24px}.license-error-title{font-size:20px}.license-error-message{font-size:14px}}";
18631
+ const myComponentCss = ":host{display:block;width:100%;height:100%;font-family:system-ui, -apple-system, sans-serif;color:#1a1a1a}.detector-container{display:flex;flex-direction:column;align-items:center;width:100%;height:100%}h1{font-size:24px;font-weight:500;color:#333;margin:0 0 24px 0}.video-container{position:relative;width:100%;height:100%;background-color:#000;border:none;border-radius:8px;overflow:hidden}video,.detection-overlay{position:absolute;width:100%;height:100%;border-radius:8px}video.mirror,.detection-overlay.mirror{transform:rotateY(180deg)}.detection-overlay{z-index:1;pointer-events:none}video{z-index:0}video::-webkit-media-controls{display:none !important}video::-webkit-media-controls-panel{display:none !important}video::-webkit-media-controls-play-button{display:none !important}video::-webkit-media-controls-start-playback-button{display:none !important}video::-webkit-media-controls-enclosure{display:none !important}.detection-box{transition:opacity 0.2s ease}.status{margin-top:16px;font-size:12px;color:#666}.overlay-mask{position:absolute;top:0;left:0;width:100%;height:100%;z-index:10;display:block;pointer-events:none}.card-outline{position:absolute;top:var(--mask-center-y, 50%);left:var(--mask-center-x, 50%);transform:translate(-50%, -50%);width:var(--mask-width, 88%);height:var(--mask-height, 55%);border:none;border-radius:4px;background:transparent;opacity:0.8}.side{position:absolute;background:#999;transition:background-color 0.3s ease;border-radius:1px}.side-top.aligned{border-left-color:#28a745;border-top-color:#28a745}.side-right.aligned{border-right-color:#28a745;border-top-color:#28a745}.side-bottom.aligned{border-left-color:#28a745;border-bottom-color:#28a745}.side-left.aligned{border-right-color:#28a745;border-bottom-color:#28a745}.side-top{top:-3px;left:-3px;width:30px;height:30px;border-left:6px solid #ffffff;border-top:6px solid #ffffff;background:transparent}.side-right{top:-3px;right:-3px;width:30px;height:30px;border-right:6px solid #ffffff;border-top:6px solid #ffffff;background:transparent}.side-bottom{bottom:-3px;left:-3px;width:30px;height:30px;border-left:6px solid #ffffff;border-bottom:6px solid #ffffff;background:transparent}.side-left{bottom:-3px;right:-3px;width:30px;height:30px;border-right:6px solid #ffffff;border-bottom:6px solid #ffffff;background:transparent}.guide-text{position:absolute;top:50%;left:50%;transform:translate(-50%, -50%);background:rgba(0, 0, 0, 0.25);backdrop-filter:blur(20px);border-radius:12px;border:1px solid rgba(255, 255, 255, 0.1);color:#ffffff;font-size:12px;font-weight:500;text-align:center;white-space:normal;padding:13px;max-width:300px;z-index:20;height:fit-content;width:fit-content;animation:slideInFromTopCentered 0.3s ease-out}.quality-indicator{position:absolute;top:20px;right:20px;display:flex;align-items:center;gap:8px;background:rgba(0, 0, 0, 0.8);padding:8px 12px;border-radius:20px;z-index:25;transition:all 0.3s ease}.quality-indicator.warning{background:rgba(255, 152, 0, 0.9)}.quality-indicator.good{background:rgba(76, 175, 80, 0.9)}.quality-score{color:#fff;font-size:12px;font-weight:600;min-width:30px;text-align:center}.quality-status{width:20px;height:20px;border-radius:50%;display:flex;align-items:center;justify-content:center;font-size:14px;font-weight:bold;color:#fff;transition:all 0.3s ease}.quality-status.ready{background:#4CAF50}.quality-status.not-ready{background:#f44336}.card-outline.quality-warning{animation:qualityWarning 1s ease-in-out infinite alternate}@keyframes qualityWarning{0%{box-shadow:0 0 0 3px rgba(255, 152, 0, 0.6)}100%{box-shadow:0 0 0 6px rgba(255, 152, 0, 0.3)}}.capture-animation{position:absolute;top:0;left:0;width:100%;height:100%;background:#fff;opacity:0;z-index:30;pointer-events:none;animation:captureFlash 0.6s ease-out}@keyframes captureFlash{0%{opacity:0}15%{opacity:0.8}30%{opacity:0}45%{opacity:0.4}60%{opacity:0}100%{opacity:0}}.card-outline.capturing{animation:pulseGreen 0.6s ease-out}@keyframes pulseGreen{0%{border-color:#28a745;box-shadow:0 0 0 4px rgba(40, 167, 69, 0)}50%{border-color:#28a745;box-shadow:0 0 0 8px rgba(40, 167, 69, 0.6)}100%{border-color:#28a745;box-shadow:0 0 0 4px rgba(40, 167, 69, 0)}}.flip-animation{position:absolute;top:50%;left:50%;transform:translate(-50%, -50%);z-index:35;pointer-events:none;opacity:0;animation:showFlipInstruction 3s ease-in-out;display:flex;flex-direction:column;align-items:center;justify-content:center}.id-card-icon{width:80px;height:50px;background:linear-gradient(135deg, #6c757d 0%, #495057 100%);border-radius:8px;position:relative;animation:flipCard 2s ease-in-out infinite;box-shadow:0 4px 12px rgba(0, 0, 0, 0.3)}.id-card-icon::before{content:'';position:absolute;top:8px;left:8px;width:16px;height:12px;background:rgba(255, 255, 255, 0.9);border-radius:2px}.id-card-icon::after{content:'';position:absolute;top:25px;left:8px;width:64px;height:3px;background:rgba(255, 255, 255, 0.7);border-radius:1px;box-shadow:0 6px 0 rgba(255, 255, 255, 0.7), 0 12px 0 rgba(255, 255, 255, 0.7)}.flip-text{margin-top:12px;color:#fff;font-size:14px;font-weight:600;text-align:center;background:rgba(128, 128, 128, 0.8);padding:12px 20px;border-radius:20px;max-width:300px}@keyframes showFlipInstruction{0%{opacity:0;transform:translate(-50%, -50%) scale(0.8)}15%{opacity:1;transform:translate(-50%, -50%) scale(1)}85%{opacity:1;transform:translate(-50%, -50%) scale(1)}100%{opacity:0;transform:translate(-50%, -50%) scale(0.8)}}@keyframes flipCard{0%{transform:rotateY(0deg)}50%{transform:rotateY(180deg)}100%{transform:rotateY(360deg)}}.success-animation{position:absolute;top:50%;left:50%;transform:translate(-50%, -50%);z-index:35;pointer-events:none;opacity:0;animation:showSuccessMessage 3s ease-in-out;display:flex;flex-direction:column;align-items:center;justify-content:center}.check-icon{width:80px;height:80px;background:linear-gradient(135deg, #6c757d 0%, #495057 100%);border-radius:50%;position:relative;animation:bounceSuccess 0.6s ease-out;box-shadow:0 4px 16px rgba(108, 117, 125, 0.4);display:flex;align-items:center;justify-content:center}.check-icon::before{content:'';position:absolute;width:20px;height:35px;border:4px solid #fff;border-top:none;border-left:none;transform:rotate(45deg);}.success-text{margin-top:16px;color:#fff;font-size:14px;font-weight:600;text-align:center;background:rgba(128, 128, 128, 0.8);padding:12px 20px;border-radius:20px;max-width:300px;animation:fadeInUp 0.5s ease-out 0.4s both}@keyframes showSuccessMessage{0%{opacity:0;transform:translate(-50%, -50%) scale(0.5)}15%{opacity:1;transform:translate(-50%, -50%) scale(1)}85%{opacity:1;transform:translate(-50%, -50%) scale(1)}100%{opacity:0;transform:translate(-50%, -50%) scale(0.9)}}@keyframes bounceSuccess{0%{transform:scale(0)}50%{transform:scale(1.1)}100%{transform:scale(1)}}@keyframes drawCheck{0%{width:0;height:0}50%{width:20px;height:0}100%{width:20px;height:35px}}@keyframes fadeInUp{0%{opacity:0;transform:translateY(20px)}100%{opacity:1;transform:translateY(0)}}.skip-section{position:absolute;bottom:20px;left:50%;transform:translateX(-50%);z-index:25;display:flex;flex-direction:column;align-items:center;width:100%;max-width:300px}.back-capture-section{position:absolute;bottom:20px;left:50%;transform:translateX(-50%);z-index:25;display:flex;flex-direction:column;align-items:center;width:100%;max-width:320px}.back-capture-buttons{display:flex;gap:12px;align-items:center;justify-content:center;flex-wrap:wrap}.capture-button{pointer-events:auto;background:#fff;color:#333;border:none;border-radius:25px;padding:12px 24px;font-size:14px;font-weight:600;cursor:pointer;transition:all 0.3s ease}.capture-button:hover{background:#f8f9fa}.capture-button:active{background:#e9ecef;transform:translateY(1px)}.capture-button:disabled,.capture-button.primary-button:disabled{cursor:not-allowed !important;transform:none !important;opacity:0.7 !important;transition:none !important}@media (max-width: 480px){.back-capture-section{bottom:16px;max-width:300px}.back-capture-buttons{flex-direction:column;gap:8px;width:100%}.capture-button,.back-capture-buttons .skip-button{width:100%;max-width:200px;padding:10px 20px;font-size:13px}.capture-button:disabled,.capture-button.primary-button:disabled,.skip-button:disabled{opacity:0.7 !important;cursor:not-allowed !important}}.skip-explanation{background:rgba(0, 0, 0, 0.5);color:#ffffff;padding:10px 16px;border-radius:8px;font-size:14px;font-weight:500;text-align:center;margin-bottom:12px;box-shadow:0 2px 8px rgba(0, 0, 0, 0.2);backdrop-filter:blur(12px);border:1px solid rgba(255, 255, 255, 0.1);animation:fadeIn 0.3s ease-in-out}@keyframes fadeIn{from{opacity:0;transform:translateY(10px)}to{opacity:1;transform:translateY(0)}}.guide-text.performance-warning-text{animation:gentlePulse 2s ease-in-out infinite;background:rgba(255, 107, 107, 0.3);border:1px solid rgba(255, 107, 107, 0.5)}@keyframes gentlePulse{0%,100%{transform:translate(-50%, -50%) scale(1);background:rgba(255, 107, 107, 0.3)}50%{transform:translate(-50%, -50%) scale(1.02);background:rgba(255, 107, 107, 0.4)}}.skip-button{pointer-events:auto;background:#fff;color:#333;border:none;border-radius:25px;padding:12px 24px;font-size:14px;font-weight:600;cursor:pointer;transition:all 0.3s ease}.skip-button:hover{background:#f8f9fa}.skip-button:active{background:#e9ecef;transform:translateY(1px)}.skip-button:disabled{cursor:not-allowed !important;transform:none !important;opacity:0.7 !important;transition:none !important}.camera-controls{position:absolute;top:16px;right:16px;z-index:25;display:flex;gap:8px;pointer-events:auto;animation:slideInFromTop 0.3s ease-out}.camera-selector-button{height:32px;padding:0 10px;border:none;border-radius:8px;background:rgba(0, 0, 0, 0.25);backdrop-filter:blur(12px);color:#ffffff;font-size:12px;font-weight:500;cursor:pointer;transition:all 0.2s ease;display:flex;align-items:center;justify-content:center;border:1px solid rgba(255, 255, 255, 0.1);white-space:nowrap;min-width:fit-content}.camera-selector-button:hover{background:rgba(0, 0, 0, 0.8);border-color:rgba(255, 255, 255, 0.2);transform:translateY(-1px)}.camera-selector-button:active{transform:translateY(0);background:rgba(0, 0, 0, 0.9)}.camera-selector-button:disabled,.camera-selector-button.loading{opacity:0.7;cursor:not-allowed;pointer-events:none}.camera-selector-button:disabled:hover,.camera-selector-button.loading:hover{transform:none;background:rgba(0, 0, 0, 0.6);border-color:rgba(255, 255, 255, 0.1)}.button-spinner{width:16px;height:16px;border:2px solid rgba(0, 0, 0, 0.2);border-top:2px solid #333333;border-radius:50%;animation:spin 1s linear infinite;display:inline-block;margin-right:8px;vertical-align:middle}@keyframes spin{0%{transform:rotate(0deg)}100%{transform:rotate(360deg)}}.camera-selector-dropdown{position:absolute;top:56px;right:16px;z-index:30;background:rgba(0, 0, 0, 0.25);backdrop-filter:blur(20px);border-radius:12px;min-width:260px;max-width:300px;border:1px solid rgba(255, 255, 255, 0.1);overflow:hidden;pointer-events:auto;animation:slideInFromTop 0.3s ease-out}@keyframes slideInFromTop{0%{opacity:0;transform:translateY(-8px) scale(0.95)}100%{opacity:1;transform:translateY(0) scale(1)}}@keyframes slideInFromTopCentered{0%{opacity:0;transform:translate(-50%, -50%) translateY(-8px) scale(0.95)}100%{opacity:1;transform:translate(-50%, -50%) translateY(0) scale(1)}}.camera-selector-header{display:flex;justify-content:space-between;align-items:center;padding:8px 12px;border-bottom:1px solid rgba(255, 255, 255, 0.1)}.camera-selector-header span{font-weight:500;color:#ffffff;font-size:13px;opacity:0.9}.close-selector{width:20px;height:20px;border:none;background:none;color:rgba(255, 255, 255, 0.7);font-size:16px;cursor:pointer;display:flex;align-items:center;justify-content:center;border-radius:4px;transition:all 0.2s ease}.close-selector:hover{background:rgba(255, 255, 255, 0.1);color:#ffffff}.camera-list{padding:4px 0;max-height:240px;overflow-y:auto}.camera-option{width:100%;padding:8px 12px;border:none;background:none;text-align:left;cursor:pointer;transition:all 0.2s ease;display:flex;justify-content:flex-start;align-items:center;gap:8px;color:rgba(255, 255, 255, 0.9)}.camera-option:hover{background:rgba(255, 255, 255, 0.08)}.camera-option.selected{background:rgba(255, 255, 255, 0.12);color:#ffffff}.camera-label{font-size:13px;flex:1;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;margin-right:0;font-weight:400;display:flex;align-items:center;gap:6px}.camera-label .autofocus-icon{font-size:12px;color:#ffffff !important;opacity:0.8;flex-shrink:0}.selected-indicator{font-size:14px;color:#ffffff;opacity:0.9;flex-shrink:0}.device-info{padding:6px 12px;border-top:1px solid rgba(255, 255, 255, 0.1);background:rgba(255, 255, 255, 0.05)}.device-info small{color:rgba(255, 255, 255, 0.6);font-size:11px;text-transform:capitalize;font-weight:400}@media (max-width: 480px){.camera-controls{top:12px;right:12px;gap:6px}.camera-selector-button{height:36px;padding:0 12px;font-size:11px;border-radius:6px}.camera-selector-dropdown{right:12px;top:48px;min-width:240px;max-width:calc(100vw - 24px)}.camera-selector-header{padding:6px 10px}.camera-option{padding:6px 10px}.device-info{padding:4px 10px}}.watermark{position:absolute;bottom:12px;right:12px;z-index:15;pointer-events:none;opacity:0.7}.watermark img{height:24px;width:auto;filter:drop-shadow(0 1px 2px rgba(0, 0, 0, 0.3))}.component-status{position:absolute;top:16px;left:16px;background:rgba(0, 0, 0, 0.25);backdrop-filter:blur(20px);border-radius:12px;border:1px solid rgba(255, 255, 255, 0.1);display:flex;align-items:center;gap:6px;padding:6px 10px;z-index:40;height:32px;width:fit-content;animation:slideInFromTop 0.3s ease-out}.status-spinner{width:16px;height:16px;border:1px solid rgba(255, 255, 255, 0.3);border-top:1px solid #ffffff;border-radius:50%;animation:statusSpin 1s linear infinite;flex-shrink:0}.status-content{display:flex;flex-direction:column;gap:1px}.status-message{color:#ffffff;font-size:12px;font-weight:500;margin:0}.status-description{color:rgba(255, 255, 255, 0.7);font-size:10px;line-height:1.2;margin:0}@keyframes statusSpin{0%{transform:rotate(0deg)}100%{transform:rotate(360deg)}}@media (max-width: 480px){.component-status{top:12px;left:12px;padding:4px 8px;gap:4px;height:28px;border-radius:8px}.status-spinner{width:14px;height:14px}.status-message{font-size:11px}.status-description{font-size:9px}.guide-text{font-size:11px;padding:4px 8px;border-radius:8px}}.loading-overlay{position:absolute;top:0;left:0;width:100%;height:100%;background:rgba(0, 0, 0, 0.85);backdrop-filter:blur(4px);display:flex;flex-direction:column;align-items:center;justify-content:center;z-index:30;border-radius:8px}.loading-spinner{width:50px;height:50px;border:3px solid rgba(255, 255, 255, 0.15);border-top:3px solid #28a745;border-radius:50%;animation:spin 1s ease-in-out infinite;margin-bottom:16px}.loading-text{color:#ffffff;font-size:14px;font-weight:500;text-align:center;opacity:0.9;margin-bottom:4px}.loading-description{color:rgba(255, 255, 255, 0.7);font-size:12px;text-align:center;opacity:0.8}@keyframes spin{0%{transform:rotate(0deg)}100%{transform:rotate(360deg)}}.performance-monitor{position:absolute;top:70px;left:16px;background:rgba(0, 0, 0, 0.25);backdrop-filter:blur(20px);border-radius:12px;border:1px solid rgba(255, 255, 255, 0.1);z-index:35;width:fit-content;animation:slideInFromTop 0.3s ease-out;transition:all 0.3s ease}@keyframes slideInFromLeft{0%{opacity:0;transform:translateX(-20px) scale(0.95)}100%{opacity:1;transform:translateX(0) scale(1)}}.performance-expanded{padding:6px 10px}.metrics-row{display:flex;gap:8px;margin-bottom:4px}.metrics-row:last-child{margin-bottom:0}.metric-compact{display:flex;flex-direction:column;align-items:center;gap:2px;min-width:50px}.metric-label{font-size:9px;color:rgba(255, 255, 255, 0.6);font-weight:500;text-transform:uppercase;letter-spacing:0.3px}.metric-value{font-size:10px;font-weight:600;font-family:'Monaco', 'Menlo', 'Consolas', monospace;padding:2px 4px;border-radius:3px;text-align:center;white-space:nowrap}.metric-value.good{color:#4ade80;background:rgba(74, 222, 128, 0.1);border:1px solid rgba(74, 222, 128, 0.2)}.metric-value.warning{color:#fbbf24;background:rgba(251, 191, 36, 0.1);border:1px solid rgba(251, 191, 36, 0.2)}.metric-value.danger{color:#f87171;background:rgba(248, 113, 113, 0.1);border:1px solid rgba(248, 113, 113, 0.2)}@media (max-width: 480px){.performance-monitor{top:60px;left:12px;width:fit-content}.performance-expanded{padding:4px 8px}.metrics-row{gap:6px;margin-bottom:3px}.metric-compact{min-width:45px;gap:1px}.metric-label{font-size:8px}.metric-value{font-size:9px;padding:1px 3px}}.quality-monitor{position:absolute;top:200px;left:16px;background:rgba(0, 0, 0, 0.25);backdrop-filter:blur(20px);border-radius:12px;border:1px solid rgba(255, 255, 255, 0.1);z-index:35;width:fit-content;animation:slideInFromLeft 0.3s ease-out;transition:all 0.3s ease}.quality-text{padding:6px 10px;font-size:11px;color:white;font-family:'Monaco', 'Menlo', 'Consolas', monospace;line-height:1.4}.quality-fail{color:#ff9999}@keyframes pulse{0%,100%{opacity:1}50%{opacity:0.7}}.metric-value.danger{animation:pulse 2s infinite}@media (max-width: 480px){.quality-monitor{top:160px;left:12px}.quality-text{padding:4px 8px;font-size:10px}}.manual-capture-section{position:absolute;bottom:20px;left:50%;transform:translateX(-50%);z-index:25;display:flex;flex-direction:column;align-items:center;width:100%;max-width:300px}.manual-capture-button{pointer-events:auto;background:#fff;color:#333;border:none;border-radius:25px;padding:12px 24px;font-size:14px;font-weight:600;cursor:pointer;transition:all 0.3s ease}.manual-capture-button:hover{background:#f8f9fa}.manual-capture-button:active{background:#e9ecef;transform:translateY(1px)}.manual-capture-button:disabled{cursor:not-allowed !important;transform:none !important;opacity:0.7 !important;transition:none !important}@media (max-width: 480px){.manual-capture-section{bottom:16px;max-width:280px}.manual-capture-button{padding:10px 20px;font-size:13px}.manual-capture-button:disabled{opacity:0.7 !important;cursor:not-allowed !important}}.license-error-container{display:flex;align-items:center;justify-content:center;padding:40px 20px;height:100%;width:100%;background:#f5f7fa;font-family:-apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', sans-serif}.license-error-card{background:#ffffff;border-radius:8px;box-shadow:0 2px 12px rgba(0, 0, 0, 0.1);max-width:480px;width:100%;padding:48px 32px;text-align:center}.license-error-icon{color:#dc3545;margin-bottom:24px}.license-error-title{color:#2c3e50;font-size:24px;font-weight:600;margin:0 0 16px 0}.license-error-message{color:#495057;font-size:16px;line-height:1.6;margin:0 0 24px 0}.license-error-help{color:#6c757d;font-size:14px;margin:0 0 32px 0}.license-error-help a{color:#007bff;text-decoration:none;font-weight:500}.license-error-help a:hover{text-decoration:underline}.license-error-footer{color:#adb5bd;font-size:12px;font-weight:500;padding-top:24px;border-top:1px solid #e9ecef}@media (max-width: 640px){.license-error-card{padding:32px 24px}.license-error-title{font-size:20px}.license-error-message{font-size:14px}}";
18561
18632
 
18562
18633
  const JaakStamps$1 = /*@__PURE__*/ proxyCustomElement(class JaakStamps extends H {
18563
18634
  constructor() {
@@ -18679,6 +18750,7 @@ const JaakStamps$1 = /*@__PURE__*/ proxyCustomElement(class JaakStamps extends H
18679
18750
  MAX_FAILURES = 30;
18680
18751
  lastInferenceTime = 0;
18681
18752
  MIN_INFERENCE_INTERVAL = 50;
18753
+ MOBILE_MIN_INFERENCE_INTERVAL = 100; // Higher interval for mobile to prevent slow motion
18682
18754
  performanceHistory = [];
18683
18755
  PERFORMANCE_HISTORY_SIZE = 10;
18684
18756
  // Sistema simplificado de monitoreo de rendimiento
@@ -18843,10 +18915,25 @@ const JaakStamps$1 = /*@__PURE__*/ proxyCustomElement(class JaakStamps extends H
18843
18915
  if (!window.ort) {
18844
18916
  this.updateStatus('Preparando herramientas...', 'Configurando funciones de captura', 'initializing');
18845
18917
  const script = document.createElement('script');
18846
- script.src = 'https://cdn.jsdelivr.net/npm/onnxruntime-web@1.23.0/dist/ort.min.js';
18918
+ // iOS Safari uses WASM-only build to prevent memory issues (WebKit 26+ bug)
18919
+ const ua = navigator.userAgent;
18920
+ const isIOSSafari = /iPad|iPhone|iPod/.test(ua) && /Safari/.test(ua) && !/CriOS|FxiOS|OPiOS|EdgiOS/.test(ua);
18921
+ if (isIOSSafari) {
18922
+ script.src = 'https://cdn.jsdelivr.net/npm/onnxruntime-web@1.23.0/dist/ort.wasm.min.js';
18923
+ }
18924
+ else {
18925
+ script.src = 'https://cdn.jsdelivr.net/npm/onnxruntime-web@1.23.0/dist/ort.min.js';
18926
+ }
18847
18927
  document.head.appendChild(script);
18848
18928
  await new Promise((resolve) => {
18849
18929
  script.onload = () => {
18930
+ // Configure ONNX for iOS Safari low memory mode
18931
+ if (isIOSSafari && window.ort?.env) {
18932
+ const ort = window.ort;
18933
+ ort.env.wasm.simd = false;
18934
+ ort.env.wasm.numThreads = 1;
18935
+ ort.env.wasm.proxy = false;
18936
+ }
18850
18937
  setTimeout(async () => {
18851
18938
  await this.finalizeInitialization();
18852
18939
  resolve(undefined);
@@ -19543,9 +19630,14 @@ const JaakStamps$1 = /*@__PURE__*/ proxyCustomElement(class JaakStamps extends H
19543
19630
  return;
19544
19631
  }
19545
19632
  this.frameSkipCounter = 0;
19546
- // Throttle inference
19633
+ // Throttle inference - use higher interval for mobile devices to prevent slow motion effect
19547
19634
  const currentTime = Date.now();
19548
- if (currentTime - this.lastInferenceTime < this.MIN_INFERENCE_INTERVAL) {
19635
+ const isMobileDevice = this.cameraInfoWithAutofocus.deviceType === 'mobile' ||
19636
+ /Android|iPhone|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);
19637
+ const isTablet = this.cameraInfoWithAutofocus.deviceType === 'tablet' ||
19638
+ (/iPad|Android/i.test(navigator.userAgent) && window.innerWidth >= 768);
19639
+ const minInterval = (isMobileDevice && !isTablet) ? this.MOBILE_MIN_INFERENCE_INTERVAL : this.MIN_INFERENCE_INTERVAL;
19640
+ if (currentTime - this.lastInferenceTime < minInterval) {
19549
19641
  if (captureState.step !== 'completed') {
19550
19642
  this.animationId = requestAnimationFrame(() => this.detectFrame());
19551
19643
  }
@@ -19698,7 +19790,7 @@ const JaakStamps$1 = /*@__PURE__*/ proxyCustomElement(class JaakStamps extends H
19698
19790
  isCapturing: false
19699
19791
  };
19700
19792
  const cameraInfo = this.cameraInfoWithAutofocus;
19701
- return (h("div", { key: 'a52b452a7aef6574a5e4b74a88c7bd3f9d45fd15', class: "detector-container" }, !this.licenseValid && this.licenseError && (h("div", { key: '18a99579e0b74ceb2cf1c4c3e21a864d2ec7d944', class: "license-error-container" }, h("div", { key: '3431722f4f47824c172a5b6f3a2ad9bd3bf377f2', class: "license-error-card" }, h("svg", { key: 'bf3854de3ba865a58c5c91cfd7a85d3d725be0df', class: "license-error-icon", width: "64", height: "64", viewBox: "0 0 24 24", fill: "none", xmlns: "http://www.w3.org/2000/svg" }, h("path", { key: '209e3a2a22333ec90e102a7156eb644b529f47c7', d: "M12 22C12 22 20 18 20 12V5L12 2L4 5V12C4 18 12 22 12 22Z", stroke: "currentColor", "stroke-width": "2", "stroke-linecap": "round", "stroke-linejoin": "round" }), h("path", { key: '7b0dc1cd29a9055e552885b23f4537c19932556d', d: "M12 8V12", stroke: "currentColor", "stroke-width": "2", "stroke-linecap": "round" }), h("circle", { key: '8ea686ebfb31a5744303f313fd104c03c02a5472', cx: "12", cy: "16", r: "0.5", fill: "currentColor", stroke: "currentColor", "stroke-width": "1" })), h("h2", { key: '7e0ec3ec23b80176cbec9c706999746d62486f3c', class: "license-error-title" }, "Licencia Requerida"), h("p", { key: '261a91e2c20feb09319dc4f319fb79611cc36a46', class: "license-error-message" }, this.licenseError), h("p", { key: '2e3cc8da0f4a8ebfd52db469b0f0900514d1d7f8', class: "license-error-help" }, "Contacte a soporte: ", h("a", { key: '283eea87e2f69dce1ea7376e3a63fed780633499', href: "mailto:support@jaak.ai" }, "support@jaak.ai")), h("div", { key: 'b4227ed25a4fb4d953c753671d27ac8c931a435f', class: "license-error-footer" }, "JAAK Stamps")))), this.licenseValid && (h("div", { key: 'cb33431cf6992f6e7466273406f729c42c1cbcdb', class: "video-container" }, h("video", { key: 'b44befd61ad616fd36fe1e98fd089a2443bc65b6', ref: el => this.videoRef = el, autoplay: true, muted: true, playsinline: true, class: this.shouldMirrorVideo ? 'mirror' : '', style: { display: captureState.isVideoActive ? 'block' : 'none' } }), h("div", { key: '8cee95ddab5f771a87d43fa434a3ba0c241d2f3e', ref: el => this.detectionContainer = el, class: `detection-overlay ${this.shouldMirrorVideo ? 'mirror' : ''}` }, this.debug && this.detectionBoxes.map((box, index) => (h("div", { key: index, class: "detection-box", style: {
19793
+ return (h("div", { key: 'dc3aed0b4d2d84039b4a123d4bdfe484ea3320ef', class: "detector-container" }, !this.licenseValid && this.licenseError && (h("div", { key: 'a9da275905e2d051252f191be944675781632d10', class: "license-error-container" }, h("div", { key: 'a36f7408f0d862edd1183ba813c64d9be91f15c6', class: "license-error-card" }, h("svg", { key: 'a8e5f3eefc224e16fb62fc0b6d152c85cee249d1', class: "license-error-icon", width: "64", height: "64", viewBox: "0 0 24 24", fill: "none", xmlns: "http://www.w3.org/2000/svg" }, h("path", { key: 'f645fb46a62004309dee1ede871d980c104fedc5', d: "M12 22C12 22 20 18 20 12V5L12 2L4 5V12C4 18 12 22 12 22Z", stroke: "currentColor", "stroke-width": "2", "stroke-linecap": "round", "stroke-linejoin": "round" }), h("path", { key: 'ee472eb3d17cddf46bef7e96561296ff6fbb1aed', d: "M12 8V12", stroke: "currentColor", "stroke-width": "2", "stroke-linecap": "round" }), h("circle", { key: 'c58c787c6c9e307159b3103fdd240e282823aa2f', cx: "12", cy: "16", r: "0.5", fill: "currentColor", stroke: "currentColor", "stroke-width": "1" })), h("h2", { key: 'f737ae630fb7661d12a17b7e48cb2c3a1cb6cb4e', class: "license-error-title" }, "Licencia Requerida"), h("p", { key: 'fb5cf8d815cddc79f7b5e9ff39f34852a43bc976', class: "license-error-message" }, this.licenseError), h("p", { key: 'b47831ee55110b100aa0ea9cbe21d39d2fc19306', class: "license-error-help" }, "Contacte a soporte: ", h("a", { key: '52eb8dea1dfdc989b921134f57f1f3f188429061', href: "mailto:support@jaak.ai" }, "support@jaak.ai")), h("div", { key: 'fd78565f67049165236694de5ddd415421d0063e', class: "license-error-footer" }, "JAAK Stamps")))), this.licenseValid && (h("div", { key: '19e5854e1683f57dbde2d857289095db75084496', class: "video-container" }, h("video", { key: 'e44fbc4c020317899620e8aa9e7e3c854ca5a2d9', ref: el => this.videoRef = el, autoplay: true, muted: true, playsinline: true, class: this.shouldMirrorVideo ? 'mirror' : '', style: { display: captureState.isVideoActive ? 'block' : 'none' } }), h("div", { key: '2b3af557f8ccb39fd7dbcef07fa6d41d021fd772', ref: el => this.detectionContainer = el, class: `detection-overlay ${this.shouldMirrorVideo ? 'mirror' : ''}` }, this.debug && this.detectionBoxes.map((box, index) => (h("div", { key: index, class: "detection-box", style: {
19702
19794
  position: 'absolute',
19703
19795
  left: `${box.x}px`,
19704
19796
  top: `${box.y}px`,
@@ -19707,9 +19799,9 @@ const JaakStamps$1 = /*@__PURE__*/ proxyCustomElement(class JaakStamps extends H
19707
19799
  border: '2px solid #32406C',
19708
19800
  pointerEvents: 'none',
19709
19801
  boxSizing: 'border-box'
19710
- } })))), this.isMaskReady && (h("div", { key: '00a749ad234294695d9a292911b41fdacafd219a', class: "overlay-mask" }, h("div", { key: 'e344df8a709fca5225985ccc9f8def75ddbd393c', class: "card-outline" }, h("div", { key: '2dcae9e414f2b7131397d49a3d5ecabfc7cd5eb8', class: "side side-top" }), h("div", { key: '48ac3f06fa4a2c83741df378719911f682811caa', class: "side side-right" }), h("div", { key: '238a3269b2a12d528e8a1889d3109ee319c7fd88', class: "side side-bottom" }), h("div", { key: 'b02eec6c102d7e9fb03ef24dfce7c75e081ff1c4', class: "side side-left" })), !captureState.showFlipAnimation && !captureState.showSuccessAnimation && (h("div", { key: '15588129ca8027a6ec1c81d70001142986966826', class: `guide-text ${this.showPerformanceMessage ? 'performance-warning-text' : ''}` }, this.getGuideText(captureState.step))), captureState.step === 'back' && !captureState.showFlipAnimation && !captureState.showSuccessAnimation && (h("div", { key: 'f15fd9bddc20c54afcca7be79c3cf2f9ee2b74f7', class: "back-capture-section" }, h("div", { key: 'e3284e1301840a9555857fa879de9f4ca91dc21b', class: "back-capture-buttons" }, (!this.useDocumentDetector || this.performanceDegradedMode || this.showManualCaptureButton) && (h("button", { key: '8508d13e117deb3b223308497b1db976643b86f2', class: "capture-button primary-button", onClick: () => this.takeManualScreenshot(), type: "button", disabled: this.processingButton !== null }, this.processingButton === 'capture-back' && (h("span", { key: '99bd464541d9ee8589bc11e937c5ad6bca9d95c8', class: "button-spinner" })), "Capturar Reverso")), h("button", { key: '3de5f0a142f9dfdfe4578c0fcbe004bb5fe94c56', class: "skip-button", onClick: () => this.skipBackCapture(), type: "button", disabled: this.processingButton !== null }, this.processingButton === 'skip-back' && (h("span", { key: '268ce949bf5155b3729298f23eea0d7ec15b3590', class: "button-spinner" })), this.enableBackDocumentTimer && this.backDocumentTimerRemaining > 0
19802
+ } })))), this.isMaskReady && (h("div", { key: '2cf20cef5e5dc4d5d3282413dce2af0f75b1babe', class: "overlay-mask" }, h("div", { key: '241879ebba739d63a736eca258b735c5c8fdac00', class: "card-outline" }, h("div", { key: '30d895b1a438636d9cd9a759b0fc096446e256a1', class: "side side-top" }), h("div", { key: 'dcca6a422e4c1c20bfc1bd17d7f45305422386a8', class: "side side-right" }), h("div", { key: '2cec938bd863737ae9c0906ed0bce2f16b7461fa', class: "side side-bottom" }), h("div", { key: 'c6045def438350be85f4333b9166111a9820c8fd', class: "side side-left" })), !captureState.showFlipAnimation && !captureState.showSuccessAnimation && (h("div", { key: '187bb5013fe6e7454bfc498b3f24844bb16881a3', class: `guide-text ${this.showPerformanceMessage ? 'performance-warning-text' : ''}` }, this.getGuideText(captureState.step))), captureState.step === 'back' && !captureState.showFlipAnimation && !captureState.showSuccessAnimation && (h("div", { key: 'a8ffba382875432493eb6564e4d8872d5d7e485a', class: "back-capture-section" }, h("div", { key: '562c149a1f81b8a73df631c81dc2119c1b9427cd', class: "back-capture-buttons" }, (!this.useDocumentDetector || this.performanceDegradedMode || this.showManualCaptureButton) && (h("button", { key: '6dc9a222959df902caec68d72c885fba11e41a79', class: "capture-button primary-button", onClick: () => this.takeManualScreenshot(), type: "button", disabled: this.processingButton !== null }, this.processingButton === 'capture-back' && (h("span", { key: 'dd3ae6cdba5f4e6085d4d31abebda12f1c1367f8', class: "button-spinner" })), "Capturar Reverso")), h("button", { key: 'cddd1951d4370da5165bf0fa450e3c176ec6cf61', class: "skip-button", onClick: () => this.skipBackCapture(), type: "button", disabled: this.processingButton !== null }, this.processingButton === 'skip-back' && (h("span", { key: 'da8c1c0af97e164150110cce97d4f4d83e9ffb20', class: "button-spinner" })), this.enableBackDocumentTimer && this.backDocumentTimerRemaining > 0
19711
19803
  ? `Saltar reverso (${this.backDocumentTimerRemaining}s)`
19712
- : 'Saltar reverso')))), captureState.isVideoActive && (h("div", { key: 'bb5c00ad882c303d8a2b6ddc79c9d5b27ff9824e', class: "camera-controls" }, h("button", { key: '7d231b550b58a8336f125a1a7fe7235c8bb3d7dd', class: `camera-selector-button ${this.isSwitchingCamera ? 'loading' : ''}`, onClick: () => this.toggleCameraSelector(), type: "button", title: "Seleccionar c\u00E1mara", disabled: this.isSwitchingCamera }, this.isSwitchingCamera ? (h("div", { class: "button-spinner" })) : ('Cámaras')))), this.showCameraSelector && cameraInfo.availableCameras.length > 0 && (h("div", { key: '95d1e0d0937f7ef821ff3ad167cd42e25fd1c87f', class: "camera-selector-dropdown" }, h("div", { key: 'e42219e5895c82f40c559c27c4f80f3145fc0a0e', class: "camera-selector-header" }, h("span", { key: '544a6fb2e08211ab6c44b0bfb281124bee318fae' }, "Seleccionar C\u00E1mara"), h("button", { key: '7c4a71243278491ee7dbcc7ab2564bc7e92f5da3', class: "close-selector", onClick: () => this.toggleCameraSelector(), type: "button" }, "\u00D7")), h("div", { key: 'c9d24e0bd906d20370214fdfd24ae91abfda98e1', class: "camera-list" }, cameraInfo.availableCameras.map((camera) => (h("button", { key: camera.id, class: `camera-option ${cameraInfo.selectedCameraId === camera.id ? 'selected' : ''}`, onClick: () => this.handleCameraSwitch(camera.id), type: "button" }, h("span", { class: "camera-label" }, camera.label || `Cámara ${cameraInfo.availableCameras.indexOf(camera) + 1}`, camera.hasAutofocus && (h("span", { class: "autofocus-icon", title: "Autofoco disponible" }, "\u29BF"))), cameraInfo.selectedCameraId === camera.id && (h("span", { class: "selected-indicator" }, "\u2713")))))), h("div", { key: '8c2e1d2ed02bc55c84f3f726e5be577686d0f32d', class: "device-info" }, h("small", { key: '142410a86e4f819b96ffc9573816994351588a3e' }, "Dispositivo: ", cameraInfo.deviceType)))), this.showManualCaptureButton && captureState.step === 'front' && !captureState.showFlipAnimation && !captureState.showSuccessAnimation && (h("div", { key: '48c33b2d6c8c80d18fba6e5f454faaa24c28fbd9', class: "manual-capture-section" }, h("button", { key: 'e3d5bfe9ef8b8f16bf669b66bce4e7a500113798', class: "manual-capture-button", onClick: () => this.takeManualScreenshot(), type: "button", disabled: this.processingButton !== null }, this.processingButton === 'capture-front' && (h("span", { key: 'f50640fe4308c765011e6ed175528920228df5e7', class: "button-spinner" })), "Capturar Frente"))))), captureState.isCapturing && (h("div", { key: '080ab315293fa1fe5b1d97aa2511a2ffe2b013f4', class: "capture-animation" })), captureState.showFlipAnimation && (h("div", { key: 'b062c546af50b799bb1fb7dda07b3ffa601c4bac', class: "flip-animation" }, h("div", { key: 'f7162dc31673c7db1d8e03a658a722a3d323b28e', class: "id-card-icon" }), h("div", { key: 'd950952b480342d80d37df5c48031d72be4ac01a', class: "flip-text" }, "\u00A1Voltea tu identificaci\u00F3n!"))), captureState.showSuccessAnimation && (h("div", { key: 'bd576fd28065aa712e42636c5fd0e3566d26cc25', class: "success-animation" }, h("div", { key: '6ca5c24510df790bd1c955c5e2936909c4767560', class: "check-icon" }), h("div", { key: '3420164eacddbe1a9aa0a181528ba0be7683af56', class: "success-text" }, "\u00A1Proceso completado!"))), h("div", { key: '8ec2b295b233e7bb8ab0cc1c183adedd4e3c7e04', class: `component-status status-${this.currentStatus.type}` }, (this.currentStatus.type === 'loading' || this.currentStatus.type === 'initializing') && (h("div", { key: '97c8e7e6219984673ebc631da111c17bf72a83cb', class: "status-spinner" })), h("div", { key: '7ca06c48f295892ff77eceff6245891ef7d9dd5e', class: "status-content" }, h("div", { key: '08056c7ec8fd66d23e0b6714c08aeccc092cf46a', class: "status-message" }, this.currentStatus.message), this.currentStatus.description && (h("div", { key: '1e32ca14de53cc2f105822ed5a58e691918b307b', class: "status-description" }, this.currentStatus.description)))), this.debug && (h("div", { key: 'c25022d9aadd37ead9ae7d1cf7c7d916cdeb9cc1', class: "performance-monitor" }, h("div", { key: 'f0f99c7e820532432ba64726ef0c2aeabeb3309f', class: "performance-expanded" }, h("div", { key: 'e839e90c9cb0f33068ac3311e41914aa52610149', class: "metrics-row" }, h("div", { key: '9f74f4877a048e63f542f2df54f569f79d6f8bd0', class: "metric-compact" }, h("span", { key: '21ec7255706d6fb2cfec035c4be92295ee0216b6', class: "metric-label" }, "FPS"), h("span", { key: 'c8be17f3dc752304bf6b7fd9746f11783f7ff6ca', class: `metric-value ${this.performanceData.fps < 15 ? 'warning' : this.performanceData.fps < 10 ? 'danger' : 'good'}` }, this.performanceData.fps)), h("div", { key: '79187257ea30ead7fb41534a94272a3a855e050b', class: "metric-compact" }, h("span", { key: 'cc53dc282c1fe4234217207c2085fa2be06a5458', class: "metric-label" }, "MEM"), h("span", { key: '032002ff63b3a2349b34833668fed8d6337e2063', class: `metric-value ${this.performanceData.memoryUsage > 100 ? 'warning' : this.performanceData.memoryUsage > 200 ? 'danger' : 'good'}` }, this.performanceData.memoryUsage, "MB"))), h("div", { key: 'e628febd5bbfb9f593e029b10827635ddd0344fb', class: "metrics-row" }, h("div", { key: 'b2fe558bab709ff6b6781648b13ebc66238f3298', class: "metric-compact" }, h("span", { key: 'd7d816aff11503657781f8ebe9cb5f0f07c7279e', class: "metric-label" }, "INF"), h("span", { key: '3d735d092b5b39d0e96f4ac59b3bf2acde739fab', class: `metric-value ${this.performanceData.inferenceTime > 100 ? 'warning' : this.performanceData.inferenceTime > 200 ? 'danger' : 'good'}` }, this.performanceData.inferenceTime, "ms")), h("div", { key: '9a83fd4fe43e8a3760aaea1f134c3101b8757681', class: "metric-compact" }, h("span", { key: '8136ab82b50230537f19cd58ed2da0956d291287', class: "metric-label" }, "FRAME"), h("span", { key: '6221cc10edff8c4b0e4034a3734deb548416a3e6', class: `metric-value ${this.performanceData.frameProcessingTime > 50 ? 'warning' : this.performanceData.frameProcessingTime > 100 ? 'danger' : 'good'}` }, this.performanceData.frameProcessingTime, "ms"))), h("div", { key: 'a31bad44d5c2c5fd5417ed82589c0f103bba1d32', class: "metrics-row" }, h("div", { key: '1441d11e0d83b3b44dfa963e415c3074691eb4f2', class: "metric-compact" }, h("span", { key: '9fe5643129aa7a842f75644b6f71b1ff80993f1b', class: "metric-label" }, "DET"), h("span", { key: '0604065a3867e71a745bfb4e804c7e96048cb70e', class: "metric-value good" }, this.performanceData.successfulDetections, "/", this.performanceData.totalDetections)), h("div", { key: 'daff0fede819f2b59a4ddb83560dc53f6151c2c9', class: "metric-compact" }, h("span", { key: '75a55c4a4e36b98af3620866ec6f7842b9ef81f7', class: "metric-label" }, "RATE"), h("span", { key: '61776c3fd4c3200d5e18cc28d917c538b282625a', class: `metric-value ${this.performanceData.detectionRate < 30 ? 'danger' : this.performanceData.detectionRate < 60 ? 'warning' : 'good'}` }, this.performanceData.detectionRate, "%")))))), h("div", { key: '4092c684ee3a148ec40e266fd16a718f2c2f2f52', class: "watermark" }, h("img", { key: 'd7bae6157d22675f8b71dbf1afdf345374398c82', src: "https://storage.googleapis.com/jaak-static/commons/powered-by-jaak.png", alt: "Powered by Jaak" }))))));
19804
+ : 'Saltar reverso')))), captureState.isVideoActive && (h("div", { key: 'd6478c7161d61e1f9f95a9d7bd13cd0cde157061', class: "camera-controls" }, h("button", { key: 'dfede9b72f07c88fc5133d3951ddfb6e507b8e8a', class: `camera-selector-button ${this.isSwitchingCamera ? 'loading' : ''}`, onClick: () => this.toggleCameraSelector(), type: "button", title: "Seleccionar c\u00E1mara", disabled: this.isSwitchingCamera }, this.isSwitchingCamera ? (h("div", { class: "button-spinner" })) : ('Cámaras')))), this.showCameraSelector && cameraInfo.availableCameras.length > 0 && (h("div", { key: '9218f824cc57b7a8b08f87ed0728c3995fa8b57e', class: "camera-selector-dropdown" }, h("div", { key: '48828e7532f49c3e9eece8051585aa803ea3c69e', class: "camera-selector-header" }, h("span", { key: '49488cbea9f196788e4110cb9b1f132b8097a771' }, "Seleccionar C\u00E1mara"), h("button", { key: '5b762a2da1719c645a490e5234703ba07c50d294', class: "close-selector", onClick: () => this.toggleCameraSelector(), type: "button" }, "\u00D7")), h("div", { key: '4c13d185e4166dc59621dd8a79a2e7123d810dff', class: "camera-list" }, cameraInfo.availableCameras.map((camera) => (h("button", { key: camera.id, class: `camera-option ${cameraInfo.selectedCameraId === camera.id ? 'selected' : ''}`, onClick: () => this.handleCameraSwitch(camera.id), type: "button" }, h("span", { class: "camera-label" }, camera.label || `Cámara ${cameraInfo.availableCameras.indexOf(camera) + 1}`, camera.hasAutofocus && (h("span", { class: "autofocus-icon", title: "Autofoco disponible" }, "\u29BF"))), cameraInfo.selectedCameraId === camera.id && (h("span", { class: "selected-indicator" }, "\u2713")))))), h("div", { key: '6860e0fbc0578a74fcd59b3567dd6e4f9a5a4139', class: "device-info" }, h("small", { key: '45e6045c7fdc0f4d58bc3c4da059a6b7c2ce09f6' }, "Dispositivo: ", cameraInfo.deviceType)))), this.showManualCaptureButton && captureState.step === 'front' && !captureState.showFlipAnimation && !captureState.showSuccessAnimation && (h("div", { key: '600d4932b6a7ae7529ef9dc8c22bb352e0f3ae5d', class: "manual-capture-section" }, h("button", { key: '6ad22fbe065602d9214530c374aed05d728114cc', class: "manual-capture-button", onClick: () => this.takeManualScreenshot(), type: "button", disabled: this.processingButton !== null }, this.processingButton === 'capture-front' && (h("span", { key: 'd54d5624764ef2774bac1f77551d4c657f4b3e92', class: "button-spinner" })), "Capturar Frente"))))), captureState.isCapturing && (h("div", { key: 'ab8c46dd497c3911e72d685310c4dccd0e5aca57', class: "capture-animation" })), captureState.showFlipAnimation && (h("div", { key: '545fc8d38085825921e5d61e9d20960b5767a50a', class: "flip-animation" }, h("div", { key: 'fd8540ca1e388070233e366aef791e00c1970de1', class: "id-card-icon" }), h("div", { key: 'f952bdf0b5eccffe5d6b36930250e699ebfb8fd8', class: "flip-text" }, "\u00A1Voltea tu identificaci\u00F3n!"))), captureState.showSuccessAnimation && (h("div", { key: 'cd9b11e3de2f799096b610582b66e044eda64c2e', class: "success-animation" }, h("div", { key: '73091c9dae5e6c0f2dbd23bf2e0b760f2495f33b', class: "check-icon" }), h("div", { key: 'ad2f9b0b90190b385740bb2fd4ed9454858f13a2', class: "success-text" }, "\u00A1Proceso completado!"))), h("div", { key: 'd74d66f12fab510f0aff01f0e233482ed6f63e46', class: `component-status status-${this.currentStatus.type}` }, (this.currentStatus.type === 'loading' || this.currentStatus.type === 'initializing') && (h("div", { key: '9060ae79961c7b1b473d5148493fda6462e50388', class: "status-spinner" })), h("div", { key: 'fd0c61e49a751afd826d30ed9f63b96b58c8e275', class: "status-content" }, h("div", { key: 'd0f0e155fba7a09658f7c21beae5f07c26c0701e', class: "status-message" }, this.currentStatus.message), this.currentStatus.description && (h("div", { key: '0694da4ec0ef14750097e69e8caf1db88cf58ed5', class: "status-description" }, this.currentStatus.description)))), this.debug && (h("div", { key: '277369112303b12a3cef89c1b7218fdc6f130723', class: "performance-monitor" }, h("div", { key: 'f6456cfd210c0d4b8b02b2b73d2405fa7c12923d', class: "performance-expanded" }, h("div", { key: '2cd33cbccf2cf3422f09bd3b914a3bc37b0a1190', class: "metrics-row" }, h("div", { key: '7871e7fe4f63249731ff33f87023351d9c5ded77', class: "metric-compact" }, h("span", { key: 'b864eb43b44838fd5c67c8e430bfa04553130473', class: "metric-label" }, "FPS"), h("span", { key: '7a0e6f4ebcf80b1483102094e0906b2b1a5aa83b', class: `metric-value ${this.performanceData.fps < 15 ? 'warning' : this.performanceData.fps < 10 ? 'danger' : 'good'}` }, this.performanceData.fps)), h("div", { key: 'ef5e590957e12bd6e9371710654278396baa5314', class: "metric-compact" }, h("span", { key: '5cc740e4a2a1e07eb53bcb0cc8c5c3df59f27730', class: "metric-label" }, "MEM"), h("span", { key: '758018f1731d7f26aa5d84e7563b059f352be361', class: `metric-value ${this.performanceData.memoryUsage > 100 ? 'warning' : this.performanceData.memoryUsage > 200 ? 'danger' : 'good'}` }, this.performanceData.memoryUsage, "MB"))), h("div", { key: '1bedd37486ae4b8ba547507f2664ea19c67a18c7', class: "metrics-row" }, h("div", { key: '4f99be14cda01b199cae93905043a6e03a852d1b', class: "metric-compact" }, h("span", { key: 'c29a4a3461633e776cd86168c59c89c6b39af18d', class: "metric-label" }, "INF"), h("span", { key: '9401828ffd1d3e41ce473ba3d0aec592a683472f', class: `metric-value ${this.performanceData.inferenceTime > 100 ? 'warning' : this.performanceData.inferenceTime > 200 ? 'danger' : 'good'}` }, this.performanceData.inferenceTime, "ms")), h("div", { key: '7d4fdad150bb665640add08464ea361aeaa8ef6b', class: "metric-compact" }, h("span", { key: '7c21d775970466b339fdbb392227ec7006b87e31', class: "metric-label" }, "FRAME"), h("span", { key: '255d408312a11f350ea75654fc64edf0d4bcfef2', class: `metric-value ${this.performanceData.frameProcessingTime > 50 ? 'warning' : this.performanceData.frameProcessingTime > 100 ? 'danger' : 'good'}` }, this.performanceData.frameProcessingTime, "ms"))), h("div", { key: '54ab129c3ffda4f1a32a2b0f437a7c38cb480aba', class: "metrics-row" }, h("div", { key: 'a246db2ef3a69d0d64827a73dd32968cb1e978e9', class: "metric-compact" }, h("span", { key: '8da1c9a5be45bcc23584234cb04f0e75fa3662c6', class: "metric-label" }, "DET"), h("span", { key: 'ad05c2b885a6b344391f70ce3acee8b41523743d', class: "metric-value good" }, this.performanceData.successfulDetections, "/", this.performanceData.totalDetections)), h("div", { key: '7449e8f7cbd15a6b828b90c923212c3578de3d11', class: "metric-compact" }, h("span", { key: 'da37f89e9641edfdfd60de7fdbf2f6285a2a4120', class: "metric-label" }, "RATE"), h("span", { key: 'de71b2072ce451a304ceb6b158d32b0ecde6d64a', class: `metric-value ${this.performanceData.detectionRate < 30 ? 'danger' : this.performanceData.detectionRate < 60 ? 'warning' : 'good'}` }, this.performanceData.detectionRate, "%")))))), h("div", { key: '6e2c10e239bca24062cd2972b5e4a3eb0951d0eb', class: "watermark" }, h("img", { key: '63fbe0ade07a191ccc9c007fc2813ac8f6e5ab2f', src: "https://storage.googleapis.com/jaak-static/commons/powered-by-jaak.png", alt: "Powered by Jaak" }))))));
19713
19805
  }
19714
19806
  // Utility methods
19715
19807
  updateDetectionBoxes(boxes) {
@@ -20432,28 +20524,35 @@ const JaakStamps$1 = /*@__PURE__*/ proxyCustomElement(class JaakStamps extends H
20432
20524
  }
20433
20525
  // Adaptive frame skipping based on performance
20434
20526
  getAdaptiveFrameSkip() {
20527
+ // Check if running on mobile device for more aggressive frame skipping
20528
+ const isMobileDevice = this.cameraInfoWithAutofocus.deviceType === 'mobile' ||
20529
+ /Android|iPhone|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);
20530
+ const isTablet = this.cameraInfoWithAutofocus.deviceType === 'tablet' ||
20531
+ (/iPad|Android/i.test(navigator.userAgent) && window.innerWidth >= 768);
20532
+ // Mobile-specific base frame skip (more aggressive to prevent slow motion effect)
20533
+ const mobileBaseSkip = isMobileDevice && !isTablet ? 4 : this.BASE_FRAME_SKIP;
20435
20534
  // Base conditions for high frame skip
20436
20535
  if (this.consecutiveFailures > 20)
20437
20536
  return this.MAX_FRAME_SKIP;
20438
20537
  if (this.performanceMetrics.inferenceTime > 200)
20439
- return 6;
20538
+ return Math.max(6, mobileBaseSkip);
20440
20539
  if (this.performanceMetrics.memoryUsage > 200)
20441
- return 5;
20540
+ return Math.max(5, mobileBaseSkip);
20442
20541
  // Calculate average processing time
20443
20542
  if (this.performanceHistory.length > 0) {
20444
20543
  const avgProcessingTime = this.performanceHistory.reduce((a, b) => a + b, 0) / this.performanceHistory.length;
20445
20544
  if (avgProcessingTime > 100)
20446
- return 4;
20545
+ return Math.max(4, mobileBaseSkip);
20447
20546
  if (avgProcessingTime > 80)
20448
- return 3;
20547
+ return Math.max(3, mobileBaseSkip);
20449
20548
  if (avgProcessingTime > 60)
20450
- return this.BASE_FRAME_SKIP + 1;
20549
+ return Math.max(this.BASE_FRAME_SKIP + 1, mobileBaseSkip);
20451
20550
  }
20452
20551
  // Low memory devices get higher frame skip
20453
20552
  if (this.performanceMetrics.memoryUsage > 150)
20454
- return 4;
20455
- // Performance is good, use base frame skip
20456
- return this.BASE_FRAME_SKIP;
20553
+ return Math.max(4, mobileBaseSkip);
20554
+ // Mobile devices use higher base frame skip for smoother video
20555
+ return mobileBaseSkip;
20457
20556
  }
20458
20557
  // Método para resetear la máscara a color blanco
20459
20558
  resetMaskToWhite() {