@jaak.ai/stamps 2.5.7-dev.4 → 2.5.7

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 (45) hide show
  1. package/dist/cjs/{index-BcFBOmM6.js → index-D6NBn_qu.js} +4 -30
  2. package/dist/cjs/index-D6NBn_qu.js.map +1 -0
  3. package/dist/cjs/jaak-stamps-webcomponent.cjs.js +2 -2
  4. package/dist/cjs/jaak-stamps.cjs.entry.js +72 -145
  5. package/dist/cjs/jaak-stamps.cjs.entry.js.map +1 -1
  6. package/dist/cjs/jaak-stamps.entry.cjs.js.map +1 -1
  7. package/dist/cjs/loader.cjs.js +2 -2
  8. package/dist/collection/collection-manifest.json +1 -1
  9. package/dist/collection/components/{jaak-stamps/jaak-stamps.js → my-component/my-component.js} +34 -90
  10. package/dist/collection/components/my-component/my-component.js.map +1 -0
  11. package/dist/collection/components/my-component/watermark-fallback.js.map +1 -0
  12. package/dist/collection/services/DetectionService.js +38 -60
  13. package/dist/collection/services/DetectionService.js.map +1 -1
  14. package/dist/collection/utils/utils.js +4 -0
  15. package/dist/collection/utils/utils.js.map +1 -0
  16. package/dist/components/index.js +2 -20
  17. package/dist/components/index.js.map +1 -1
  18. package/dist/components/jaak-stamps.js +71 -147
  19. package/dist/components/jaak-stamps.js.map +1 -1
  20. package/dist/esm/{index-Cb0ILUvS.js → index-BCfAsrzL.js} +4 -30
  21. package/dist/esm/index-BCfAsrzL.js.map +1 -0
  22. package/dist/esm/jaak-stamps-webcomponent.js +3 -3
  23. package/dist/esm/jaak-stamps.entry.js +72 -145
  24. package/dist/esm/jaak-stamps.entry.js.map +1 -1
  25. package/dist/esm/loader.js +3 -3
  26. package/dist/jaak-stamps-webcomponent/jaak-stamps-webcomponent.esm.js +1 -1
  27. package/dist/jaak-stamps-webcomponent/jaak-stamps.entry.esm.js.map +1 -1
  28. package/dist/jaak-stamps-webcomponent/{p-9afd846d.entry.js → p-63c2c085.entry.js} +3 -3
  29. package/dist/jaak-stamps-webcomponent/p-63c2c085.entry.js.map +1 -0
  30. package/dist/jaak-stamps-webcomponent/p-BCfAsrzL.js +3 -0
  31. package/dist/jaak-stamps-webcomponent/p-BCfAsrzL.js.map +1 -0
  32. package/dist/types/components/{jaak-stamps/jaak-stamps.d.ts → my-component/my-component.d.ts} +0 -5
  33. package/dist/types/services/DetectionService.d.ts +4 -5
  34. package/dist/types/utils/utils.d.ts +1 -0
  35. package/package.json +4 -4
  36. package/dist/cjs/index-BcFBOmM6.js.map +0 -1
  37. package/dist/collection/components/jaak-stamps/jaak-stamps.js.map +0 -1
  38. package/dist/collection/components/jaak-stamps/watermark-fallback.js.map +0 -1
  39. package/dist/esm/index-Cb0ILUvS.js.map +0 -1
  40. package/dist/jaak-stamps-webcomponent/p-9afd846d.entry.js.map +0 -1
  41. package/dist/jaak-stamps-webcomponent/p-Cb0ILUvS.js +0 -3
  42. package/dist/jaak-stamps-webcomponent/p-Cb0ILUvS.js.map +0 -1
  43. /package/dist/collection/components/{jaak-stamps/jaak-stamps.css → my-component/my-component.css} +0 -0
  44. /package/dist/collection/components/{jaak-stamps → my-component}/watermark-fallback.js +0 -0
  45. /package/dist/types/components/{jaak-stamps → my-component}/watermark-fallback.d.ts +0 -0
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- var index = require('./index-BcFBOmM6.js');
3
+ var index = require('./index-D6NBn_qu.js');
4
4
 
5
5
  class EventBusService {
6
6
  events = new Map();
@@ -798,6 +798,15 @@ class DetectionService {
798
798
  INPUT_SIZE = 320;
799
799
  CONFIDENCE_THRESHOLD = 0.6;
800
800
  useFloat16 = true;
801
+ // Hoisted views for float32->float16 bit-twiddling. A fresh ArrayBuffer
802
+ // per call was costing ~614K allocations per frame.
803
+ _f32View = new Float32Array(1);
804
+ _u32View = new Uint32Array(this._f32View.buffer);
805
+ // Pre-allocated tensor buffers reused across frames. Same shape every time
806
+ // (3 * INPUT_SIZE * INPUT_SIZE), and runInference is awaited before the next
807
+ // preprocess runs, so reuse is safe.
808
+ _tensorF32 = new Float32Array(3 * 320 * 320);
809
+ _tensorF16 = new Uint16Array(3 * 320 * 320);
801
810
  // Canvas pool for optimization
802
811
  preprocessCanvas;
803
812
  preprocessCtx;
@@ -824,7 +833,7 @@ class DetectionService {
824
833
  try {
825
834
  const sessionOptions = this.deviceStrategy.getSessionOptions(this.debug);
826
835
  try {
827
- this.session = await this.createSession(this.MODEL_PATH, sessionOptions);
836
+ this.session = await window.ort.InferenceSession.create(this.MODEL_PATH, sessionOptions);
828
837
  this.detectFloat16Support();
829
838
  }
830
839
  catch (error) {
@@ -839,7 +848,7 @@ class DetectionService {
839
848
  if (isFloat16Error) {
840
849
  this.useFloat16 = false;
841
850
  try {
842
- this.session = await this.createSession(this.MODEL_PATH_FP32, sessionOptions);
851
+ this.session = await window.ort.InferenceSession.create(this.MODEL_PATH_FP32, sessionOptions);
843
852
  }
844
853
  catch (fp32Error) {
845
854
  // Intentar con opciones minimas de WASM
@@ -848,7 +857,7 @@ class DetectionService {
848
857
  graphOptimizationLevel: 'all',
849
858
  logSeverityLevel: this.debug ? 2 : 4,
850
859
  };
851
- this.session = await this.createSession(this.MODEL_PATH_FP32, wasmOptions);
860
+ this.session = await window.ort.InferenceSession.create(this.MODEL_PATH_FP32, wasmOptions);
852
861
  }
853
862
  }
854
863
  else if (isMemoryError) {
@@ -867,7 +876,7 @@ class DetectionService {
867
876
  };
868
877
  this.useFloat16 = false;
869
878
  try {
870
- this.session = await this.createSession(this.MODEL_PATH_FP32, fallbackOptions);
879
+ this.session = await window.ort.InferenceSession.create(this.MODEL_PATH_FP32, fallbackOptions);
871
880
  }
872
881
  catch (fallbackError) {
873
882
  throw new Error(`no available backend found. ERR: [wasm] RangeError: Out of memory`);
@@ -908,7 +917,7 @@ class DetectionService {
908
917
  // Load model
909
918
  const sessionOptions = this.deviceStrategy.getSessionOptions(this.debug);
910
919
  try {
911
- this.mobileNetSession = await this.createSession(this.MOBILENET_MODEL_PATH, sessionOptions);
920
+ this.mobileNetSession = await window.ort.InferenceSession.create(this.MOBILENET_MODEL_PATH, sessionOptions);
912
921
  }
913
922
  catch (error) {
914
923
  // Múltiples tipos de errores de memoria que pueden ocurrir
@@ -932,7 +941,7 @@ class DetectionService {
932
941
  sessionLogVerbosityLevel: 0,
933
942
  };
934
943
  try {
935
- this.mobileNetSession = await this.createSession(this.MOBILENET_MODEL_PATH, fallbackOptions);
944
+ this.mobileNetSession = await window.ort.InferenceSession.create(this.MOBILENET_MODEL_PATH, fallbackOptions);
936
945
  }
937
946
  catch (fallbackError) {
938
947
  throw new Error(`no available backend found. ERR: [wasm] RangeError: Out of memory`);
@@ -958,25 +967,31 @@ class DetectionService {
958
967
  if (!this.preprocessCanvas || !this.preprocessCtx) {
959
968
  this.initializeCanvasPool();
960
969
  }
961
- this.preprocessCtx.clearRect(0, 0, this.INPUT_SIZE, this.INPUT_SIZE);
962
- this.preprocessCtx.drawImage(video, 0, 0, this.INPUT_SIZE, this.INPUT_SIZE);
963
- const imageData = this.preprocessCtx.getImageData(0, 0, this.INPUT_SIZE, this.INPUT_SIZE);
964
- const [R, G, B] = [[], [], []];
970
+ const SIZE = this.INPUT_SIZE;
971
+ this.preprocessCtx.clearRect(0, 0, SIZE, SIZE);
972
+ this.preprocessCtx.drawImage(video, 0, 0, SIZE, SIZE);
973
+ const imageData = this.preprocessCtx.getImageData(0, 0, SIZE, SIZE);
965
974
  const { data } = imageData;
966
- for (let i = 0; i < data.length; i += 4) {
967
- R.push(data[i] / 255);
968
- G.push(data[i + 1] / 255);
969
- B.push(data[i + 2] / 255);
970
- }
971
- const transposedData = new Float32Array(R.concat(G, B));
975
+ const pixels = SIZE * SIZE;
976
+ const gOffset = pixels;
977
+ const bOffset = pixels * 2;
978
+ const inv255 = 1 / 255;
972
979
  if (this.useFloat16) {
973
- const float16Data = new Uint16Array(transposedData.length);
974
- for (let i = 0; i < transposedData.length; i++) {
975
- float16Data[i] = this.float32ToFloat16(transposedData[i]);
980
+ const out = this._tensorF16;
981
+ for (let i = 0, p = 0; i < data.length; i += 4, p++) {
982
+ out[p] = this.float32ToFloat16(data[i] * inv255);
983
+ out[gOffset + p] = this.float32ToFloat16(data[i + 1] * inv255);
984
+ out[bOffset + p] = this.float32ToFloat16(data[i + 2] * inv255);
976
985
  }
977
- return new window.ort.Tensor("float16", float16Data, [1, 3, this.INPUT_SIZE, this.INPUT_SIZE]);
986
+ return new window.ort.Tensor("float16", out, [1, 3, SIZE, SIZE]);
987
+ }
988
+ const out = this._tensorF32;
989
+ for (let i = 0, p = 0; i < data.length; i += 4, p++) {
990
+ out[p] = data[i] * inv255;
991
+ out[gOffset + p] = data[i + 1] * inv255;
992
+ out[bOffset + p] = data[i + 2] * inv255;
978
993
  }
979
- return new window.ort.Tensor("float32", transposedData, [1, 3, this.INPUT_SIZE, this.INPUT_SIZE]);
994
+ return new window.ort.Tensor("float32", out, [1, 3, SIZE, SIZE]);
980
995
  }
981
996
  async runInference(inputTensor) {
982
997
  if (!this.useDocumentDetector) {
@@ -1124,41 +1139,6 @@ class DetectionService {
1124
1139
  areAllSidesAligned(alignment) {
1125
1140
  return alignment.top && alignment.right && alignment.bottom && alignment.left;
1126
1141
  }
1127
- // Reference counter so concurrent sessions share one filter and the last
1128
- // one to finish restores the original console.warn.
1129
- static _ortWarnActiveCount = 0;
1130
- static _originalWarn = null;
1131
- static _acquireWarnFilter() {
1132
- if (DetectionService._ortWarnActiveCount === 0) {
1133
- DetectionService._originalWarn = console.warn;
1134
- console.warn = (...args) => {
1135
- const msg = typeof args[0] === 'string' ? args[0] : '';
1136
- if (!msg.includes('removing requested execution provider')) {
1137
- DetectionService._originalWarn.apply(console, args);
1138
- }
1139
- };
1140
- }
1141
- DetectionService._ortWarnActiveCount++;
1142
- }
1143
- static _releaseWarnFilter() {
1144
- DetectionService._ortWarnActiveCount--;
1145
- if (DetectionService._ortWarnActiveCount === 0 && DetectionService._originalWarn) {
1146
- console.warn = DetectionService._originalWarn;
1147
- DetectionService._originalWarn = null;
1148
- }
1149
- }
1150
- async createSession(modelPath, options) {
1151
- // Keep the filter active for the full await: ORT may emit
1152
- // "removing requested execution provider" during async resolution,
1153
- // not only in the synchronous preamble of create().
1154
- DetectionService._acquireWarnFilter();
1155
- try {
1156
- return await window.ort.InferenceSession.create(modelPath, options);
1157
- }
1158
- finally {
1159
- DetectionService._releaseWarnFilter();
1160
- }
1161
- }
1162
1142
  cleanup() {
1163
1143
  this.cleanupCanvasPool();
1164
1144
  if (this.session) {
@@ -1203,10 +1183,8 @@ class DetectionService {
1203
1183
  }
1204
1184
  }
1205
1185
  float32ToFloat16(value) {
1206
- const buffer = new ArrayBuffer(4);
1207
- const view = new DataView(buffer);
1208
- view.setFloat32(0, value, true);
1209
- const f = view.getUint32(0, true);
1186
+ this._f32View[0] = value;
1187
+ const f = this._u32View[0];
1210
1188
  const sign = (f >> 31) & 0x1;
1211
1189
  const exp = (f >> 23) & 0xFF;
1212
1190
  const frac = f & 0x7FFFFF;
@@ -18669,7 +18647,7 @@ class LicenseValidationService {
18669
18647
  }
18670
18648
  }
18671
18649
 
18672
- const jaakStampsCss = ":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}}";
18650
+ 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}}";
18673
18651
 
18674
18652
  const JaakStamps = class {
18675
18653
  constructor(hostRef) {
@@ -18699,7 +18677,7 @@ const JaakStamps = class {
18699
18677
  propagateTraceHeaderCorsUrls; // Comma-separated URLs or regex patterns
18700
18678
  metricsExportIntervalMillis = 60000; // Export metrics every 60 seconds
18701
18679
  license; // License key for validation
18702
- licenseEnvironment = 'prod';
18680
+ licenseEnvironment = 'prod'; // Environment for license validation
18703
18681
  traceId; // Optional trace ID for tracking
18704
18682
  appId = 'jaak-stamps-web'; // Application ID for license validation
18705
18683
  captureCompleted;
@@ -18747,8 +18725,6 @@ const JaakStamps = class {
18747
18725
  licenseValid = true; // License validation status
18748
18726
  licenseError = null; // License validation error message
18749
18727
  classificationDisabled = false; // Classification disabled at runtime due to errors
18750
- _initialized = false;
18751
- _initializing = false;
18752
18728
  // Services
18753
18729
  licenseValidationService = null;
18754
18730
  serviceContainer;
@@ -18818,12 +18794,8 @@ const JaakStamps = class {
18818
18794
  canvasPool = [];
18819
18795
  MAX_CANVAS_POOL_SIZE = 3;
18820
18796
  async componentWillLoad() {
18821
- // Use setTimeout(0) instead of Promise.resolve() so Angular's synchronous change-detection
18822
- // cycle (which sets property bindings like licenseEnvironment) finishes before we read props.
18823
- // A microtask yield is not enough when the consuming framework defers its first CD cycle.
18824
- await new Promise(resolve => setTimeout(resolve, 0));
18825
18797
  if (this.debug) {
18826
- console.log('[JAAK-DEBUG] componentWillLoad() - Props after microtask yield:');
18798
+ console.log('[JAAK-DEBUG] componentWillLoad() - Props at initialization:');
18827
18799
  console.log('[JAAK-DEBUG] useDocumentDetector:', this.useDocumentDetector, '(type:', typeof this.useDocumentDetector, ')');
18828
18800
  console.log('[JAAK-DEBUG] useDocumentClassification:', this.useDocumentClassification);
18829
18801
  console.log('[JAAK-DEBUG] debug:', this.debug);
@@ -18835,64 +18807,32 @@ const JaakStamps = class {
18835
18807
  console.log('[JAAK-DEBUG] preferredCamera:', this.preferredCamera);
18836
18808
  console.log('[JAAK-DEBUG] appId:', this.appId);
18837
18809
  }
18838
- if (!this.license) {
18839
- // No license yet show blocking UI; @Watch('license') triggers init when it arrives
18840
- this.licenseValid = false;
18841
- this.licenseError = 'Se requiere una licencia para continuar. Por favor, proporcione una licencia usando el atributo "license".';
18842
- this.updateStatus('Licencia requerida', 'Proporcione una licencia para continuar', 'error');
18843
- }
18844
- else {
18845
- // License present — pre-set the first status synchronously so the initial render
18846
- // already shows it, preventing a state change inside componentDidLoad that Stencil
18847
- // would flag as an extra re-render.
18848
- this.updateStatus('Validando licencia...', 'Verificando autorización de uso', 'initializing');
18849
- }
18850
- // Heavy initialization is deferred to componentDidLoad so the first render is not blocked
18851
- }
18852
- async componentDidLoad() {
18853
- // License absent at mount time — @Watch('license') handles initialization when it arrives
18854
- if (!this.license || this._initialized || this._initializing) {
18855
- return;
18810
+ // License is required - always validate
18811
+ // Wait a bit to ensure props are set from attributes
18812
+ await new Promise(resolve => setTimeout(resolve, 50));
18813
+ if (this.debug) {
18814
+ console.log('[JAAK-DEBUG] Props AFTER 50ms wait:');
18815
+ console.log('[JAAK-DEBUG] useDocumentDetector:', this.useDocumentDetector, '(type:', typeof this.useDocumentDetector, ')');
18856
18816
  }
18857
- await this.validateAndInitialize();
18858
- }
18859
- async onLicenseChanged(newLicense) {
18860
- if (!newLicense || this._initialized || this._initializing) {
18817
+ this.updateStatus('Validando licencia...', 'Verificando autorización de uso', 'initializing');
18818
+ await this.validateLicense();
18819
+ // If license validation failed, stop initialization
18820
+ if (!this.licenseValid) {
18821
+ if (this.debug) {
18822
+ console.error('[JAAK-DEBUG] License validation FAILED. Stopping initialization.');
18823
+ }
18861
18824
  return;
18862
18825
  }
18863
- // Set status synchronously before the async work so the UI updates immediately
18864
- this.updateStatus('Validando licencia...', 'Verificando autorización de uso', 'initializing');
18865
- await this.validateAndInitialize();
18866
- }
18867
- async onLicenseEnvironmentChanged() {
18868
- // Always recreate the service so the correct environment URL is used from now on.
18869
- this.licenseValidationService = new LicenseValidationService(this.licenseEnvironment);
18870
- // If a license is present but the component never finished initializing
18871
- // (e.g. first validate ran against the wrong env and failed, or license arrived
18872
- // before licenseEnvironment was set), retry the full init flow now.
18873
- if (this.license && !this._initialized && !this._initializing) {
18874
- this.updateStatus('Validando licencia...', 'Verificando autorización de uso', 'initializing');
18875
- await this.validateAndInitialize();
18826
+ if (this.debug) {
18827
+ console.log('[JAAK-DEBUG] License validation OK');
18876
18828
  }
18877
18829
  }
18878
- async validateAndInitialize() {
18879
- if (this._initialized || this._initializing) {
18880
- return;
18881
- }
18882
- this._initializing = true;
18830
+ async componentDidLoad() {
18883
18831
  try {
18884
- // Status was already set synchronously by the caller (componentWillLoad or @Watch)
18885
- // to avoid a state change inside componentDidLoad that Stencil warns about.
18886
- await this.validateLicense();
18832
+ // If license validation failed, stop initialization
18887
18833
  if (!this.licenseValid) {
18888
- if (this.debug) {
18889
- console.error('[JAAK-DEBUG] License validation FAILED. Stopping initialization.');
18890
- }
18891
18834
  return;
18892
18835
  }
18893
- if (this.debug) {
18894
- console.log('[JAAK-DEBUG] License validation OK');
18895
- }
18896
18836
  this.updateStatus('Preparando capturador...', 'Configurando herramientas de captura', 'initializing');
18897
18837
  await this.initializeServices();
18898
18838
  this.updateStatus('Preparando funciones...', 'Configurando herramientas de trabajo', 'initializing');
@@ -18902,14 +18842,9 @@ const JaakStamps = class {
18902
18842
  if (this.debug) {
18903
18843
  this.initializePerformanceMonitor();
18904
18844
  }
18905
- this._initialized = true;
18906
18845
  }
18907
18846
  catch (error) {
18908
- const errorMessage = error instanceof Error ? error.message : String(error);
18909
- this.updateStatus('Error de inicialización', errorMessage, 'error');
18910
- }
18911
- finally {
18912
- this._initializing = false;
18847
+ this.updateStatus('Error de inicialización', error.message, 'error');
18913
18848
  }
18914
18849
  }
18915
18850
  async initializeServices() {
@@ -18959,14 +18894,14 @@ const JaakStamps = class {
18959
18894
  }
18960
18895
  async validateLicense() {
18961
18896
  if (!this.license) {
18897
+ console.error('❌ No license provided for JAAK Stamps component');
18962
18898
  this.licenseError = 'Este componente requiere una licencia válida. Por favor, proporcione una licencia usando el atributo "license".';
18963
18899
  this.licenseValid = false;
18964
18900
  this.updateStatus('Error de licencia', 'Licencia no proporcionada', 'error');
18965
18901
  return;
18966
18902
  }
18967
18903
  try {
18968
- if (this.debug)
18969
- console.log('[jaak-stamps] validating license...');
18904
+ console.log('🔑 Validating license for JAAK Stamps...');
18970
18905
  // Initialize license validation service
18971
18906
  this.licenseValidationService = new LicenseValidationService(this.licenseEnvironment);
18972
18907
  // Validate the license, passing traceId and appId if provided
@@ -18974,21 +18909,18 @@ const JaakStamps = class {
18974
18909
  if (response && response.access_token) {
18975
18910
  this.licenseValid = true;
18976
18911
  this.licenseError = null;
18977
- if (this.debug)
18978
- console.log('[jaak-stamps] license validated successfully');
18912
+ console.log('✅ License validated successfully for JAAK Stamps');
18979
18913
  // Emit the traceId (either provided or generated)
18980
18914
  if (response.traceId) {
18981
18915
  this.traceIdGenerated.emit({ traceId: response.traceId });
18982
- if (this.debug)
18983
- console.log('[jaak-stamps] traceId:', response.traceId);
18916
+ console.log('📋 TraceId:', response.traceId);
18984
18917
  }
18985
18918
  }
18986
18919
  else {
18987
18920
  this.licenseValid = false;
18988
18921
  this.licenseError = 'La licencia proporcionada no es válida. Por favor, verifique su licencia e intente nuevamente.';
18989
18922
  this.updateStatus('Error de licencia', 'Licencia inválida', 'error');
18990
- if (this.debug)
18991
- console.error('[jaak-stamps] invalid license');
18923
+ console.error('❌ Invalid license for JAAK Stamps');
18992
18924
  }
18993
18925
  }
18994
18926
  catch (error) {
@@ -18996,8 +18928,7 @@ const JaakStamps = class {
18996
18928
  const licenseError = error;
18997
18929
  this.licenseError = licenseError.error_description || 'Error al validar la licencia. Por favor, verifique su conexión e intente nuevamente.';
18998
18930
  this.updateStatus('Error de licencia', 'Fallo en la validación', 'error');
18999
- if (this.debug)
19000
- console.error('[jaak-stamps] license validation failed:', error);
18931
+ console.error('❌ License validation failed for JAAK Stamps:', error);
19001
18932
  }
19002
18933
  }
19003
18934
  async setupEventListeners() {
@@ -20283,7 +20214,7 @@ const JaakStamps = class {
20283
20214
  isCapturing: false
20284
20215
  };
20285
20216
  const cameraInfo = this.cameraInfoWithAutofocus;
20286
- return (index.h("div", { key: 'ebb920fee5499ae979cb60332342b2f0758fb497', class: "detector-container" }, !this.licenseValid && this.licenseError && (index.h("div", { key: 'c5f912119d581b52c66e72b67241a72b976ec44e', class: "license-error-container" }, index.h("div", { key: '19ab81fde436b79252b45b44e772ab303e19405e', class: "license-error-card" }, index.h("svg", { key: '68ab28d6649949dcfd4c13d2dc8e77486b242da5', class: "license-error-icon", width: "64", height: "64", viewBox: "0 0 24 24", fill: "none", xmlns: "http://www.w3.org/2000/svg" }, index.h("path", { key: '19e0e5aa75368a125a65932d116467f65a4ffffc', 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" }), index.h("path", { key: 'b5aee63abfc96b7851d59d5ccb19f872de0fed66', d: "M12 8V12", stroke: "currentColor", "stroke-width": "2", "stroke-linecap": "round" }), index.h("circle", { key: '5d25fedbe498d583a96ec0c5c3b91872b3cdf111', cx: "12", cy: "16", r: "0.5", fill: "currentColor", stroke: "currentColor", "stroke-width": "1" })), index.h("h2", { key: '679c39266afc7c3c987a3da02510a739d4f34679', class: "license-error-title" }, "Licencia Requerida"), index.h("p", { key: '38069563654e3aa16784e77c2539620fcf2b60f6', class: "license-error-message" }, this.licenseError), index.h("p", { key: '3fcd6403a7c39e3ed6e63699d051607f348b5ea2', class: "license-error-help" }, "Contacte a soporte: ", index.h("a", { key: '328e62a4d4a70ec06eb73aa6bb90a2b7912dfdc4', href: "mailto:support@jaak.ai" }, "support@jaak.ai")), index.h("div", { key: 'c16315263a11d06d1cd9a6aff673f1a8cd609d05', class: "license-error-footer" }, "JAAK Stamps")))), this.licenseValid && (index.h("div", { key: 'c7baf6eca897342a564c8dfe3c3e81091bb881ef', class: "video-container" }, index.h("video", { key: '3ea8f97b026f2e53dbee64c0cd2976d9a84c47db', ref: el => this.videoRef = el, autoplay: true, muted: true, playsinline: true, class: this.shouldMirrorVideo ? 'mirror' : '', style: {
20217
+ return (index.h("div", { key: 'a4f5254bb0f5198cfea553fb46d8841c4a410853', class: "detector-container" }, !this.licenseValid && this.licenseError && (index.h("div", { key: '48353567b7c23df1b44e035cd6b52dd692b338a6', class: "license-error-container" }, index.h("div", { key: '8a520b2cb936cae9ed64c513ae9e583f62d31b99', class: "license-error-card" }, index.h("svg", { key: 'dccdda293c28bd5d1e76bbff0060859a394a800c', class: "license-error-icon", width: "64", height: "64", viewBox: "0 0 24 24", fill: "none", xmlns: "http://www.w3.org/2000/svg" }, index.h("path", { key: '09015453d8230c523abe8e5b4b800b4a55a81202', 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" }), index.h("path", { key: '5f9fd50412d21de2274e124c02dcc8e971fd23ee', d: "M12 8V12", stroke: "currentColor", "stroke-width": "2", "stroke-linecap": "round" }), index.h("circle", { key: 'e534af1f29c6382c2c47623129a94d3aac3ec71e', cx: "12", cy: "16", r: "0.5", fill: "currentColor", stroke: "currentColor", "stroke-width": "1" })), index.h("h2", { key: '6ed105bb6e16d8ce7419bc64a0f69e7e2d7ed0ac', class: "license-error-title" }, "Licencia Requerida"), index.h("p", { key: 'c1d7e06b03a4af316e28836eb7a0f3729993ca1f', class: "license-error-message" }, this.licenseError), index.h("p", { key: '349ae281248b56524460cb18f36300e69c11ab5e', class: "license-error-help" }, "Contacte a soporte: ", index.h("a", { key: '62546d77296d220338953c3bd1820946164ff96c', href: "mailto:support@jaak.ai" }, "support@jaak.ai")), index.h("div", { key: 'b45ac9c2d9b9d65e4156d07a067e6c9214da8113', class: "license-error-footer" }, "JAAK Stamps")))), this.licenseValid && (index.h("div", { key: '77c274b14b69fe4220f71ef789de8c4943833fee', class: "video-container" }, index.h("video", { key: 'e036a408939aa5875e36a1f038bed98bfbfba134', ref: el => this.videoRef = el, autoplay: true, muted: true, playsinline: true, class: this.shouldMirrorVideo ? 'mirror' : '', style: {
20287
20218
  // Keep the element rendered (display: block) so the browser
20288
20219
  // loads stream metadata and fires 'loadedmetadata'. Hiding it
20289
20220
  // with display:none prevents metadata loading in Chrome and
@@ -20292,7 +20223,7 @@ const JaakStamps = class {
20292
20223
  // render context alive.
20293
20224
  opacity: captureState.isVideoActive ? '1' : '0',
20294
20225
  visibility: captureState.isVideoActive ? 'visible' : 'hidden',
20295
- } }), index.h("div", { key: '03150c4c1d5b5978b7a1742760b56135873c754d', ref: el => this.detectionContainer = el, class: `detection-overlay ${this.shouldMirrorVideo ? 'mirror' : ''}` }, this.debug && this.detectionBoxes.map((box, index$1) => (index.h("div", { key: index$1, class: "detection-box", style: {
20226
+ } }), index.h("div", { key: '9389f1495814409aa849ce409a28cb578761df76', ref: el => this.detectionContainer = el, class: `detection-overlay ${this.shouldMirrorVideo ? 'mirror' : ''}` }, this.debug && this.detectionBoxes.map((box, index$1) => (index.h("div", { key: index$1, class: "detection-box", style: {
20296
20227
  position: 'absolute',
20297
20228
  left: `${box.x}px`,
20298
20229
  top: `${box.y}px`,
@@ -20301,9 +20232,9 @@ const JaakStamps = class {
20301
20232
  border: '2px solid #32406C',
20302
20233
  pointerEvents: 'none',
20303
20234
  boxSizing: 'border-box'
20304
- } })))), this.isMaskReady && (index.h("div", { key: '96d73c2ff335d9dc7acf443c7b6e62613d2d3ed7', class: "overlay-mask" }, index.h("div", { key: 'cac27d59a12131f3d93ea763fcf7c00987861926', class: "card-outline" }, index.h("div", { key: '29b40014f26a20f7ec1aaa7dd1a154f834b40d2b', class: "side side-top" }), index.h("div", { key: 'cb31796ea1d74cfb68b4e74f7a0abbef873f67c3', class: "side side-right" }), index.h("div", { key: 'ec596a1ff9f6e51243359145a2f8a9ea5ceca61d', class: "side side-bottom" }), index.h("div", { key: '20e19a59cc88e6fab27452c828187b8916126211', class: "side side-left" })), !captureState.showFlipAnimation && !captureState.showSuccessAnimation && (index.h("div", { key: 'd03cd5a33364b1b6cb368c998e3cb05373c284c9', class: `guide-text ${this.showPerformanceMessage ? 'performance-warning-text' : ''}` }, this.getGuideText(captureState.step))), captureState.step === 'back' && !captureState.showFlipAnimation && !captureState.showSuccessAnimation && (index.h("div", { key: 'd4b4760cbda1af33f4e4e037c6d0222e9f5966f0', class: "back-capture-section" }, index.h("div", { key: '318ffc4138982564b23e84b399533034b42b9ec7', class: "back-capture-buttons" }, (!this.useDocumentDetector || this.performanceDegradedMode || this.showManualCaptureButton) && (index.h("button", { key: '33e12aae5d1981a56f5706ad840c46ea46686a8c', class: "capture-button primary-button", onClick: () => this.takeManualScreenshot(), type: "button", disabled: this.processingButton !== null }, this.processingButton === 'capture-back' && (index.h("span", { key: '5e2d871d21c972c2ae929b06a971ecea5291ae09', class: "button-spinner" })), "Capturar Reverso")), index.h("button", { key: 'cd5e64d18b99893f973b8279a18ebe6058705be2', class: "skip-button", onClick: () => this.skipBackCapture(), type: "button", disabled: this.processingButton !== null }, this.processingButton === 'skip-back' && (index.h("span", { key: 'aa41d6aae7440fa35941734398e26b7ec5c87dd6', class: "button-spinner" })), this.enableBackDocumentTimer && this.backDocumentTimerRemaining > 0
20235
+ } })))), this.isMaskReady && (index.h("div", { key: '8050beb9a72279f3a2d54884fe598eca8b1929af', class: "overlay-mask" }, index.h("div", { key: '25028f1c5bab6b457563c098899c7645083be3a0', class: "card-outline" }, index.h("div", { key: 'd125b627160c671f1be837d1f957704d016dcf47', class: "side side-top" }), index.h("div", { key: '78ed55f578fcadba60e80c50315f4a82bbe9c15c', class: "side side-right" }), index.h("div", { key: '263d29d0844bfa88d68698d71630fd9b08debc26', class: "side side-bottom" }), index.h("div", { key: '18e528b4d877699add45d9b4e1e029a2bb993582', class: "side side-left" })), !captureState.showFlipAnimation && !captureState.showSuccessAnimation && (index.h("div", { key: '7e09980601c146cd48f80a04640a8a7d635e14d4', class: `guide-text ${this.showPerformanceMessage ? 'performance-warning-text' : ''}` }, this.getGuideText(captureState.step))), captureState.step === 'back' && !captureState.showFlipAnimation && !captureState.showSuccessAnimation && (index.h("div", { key: '102e95d211e79d5c5d8e13ae717cb8913eae7ea1', class: "back-capture-section" }, index.h("div", { key: 'cde593bf62825392df6e950585e9950351bac430', class: "back-capture-buttons" }, (!this.useDocumentDetector || this.performanceDegradedMode || this.showManualCaptureButton) && (index.h("button", { key: '823b35d70e2bb1cf242e01578e921c8a091c7639', class: "capture-button primary-button", onClick: () => this.takeManualScreenshot(), type: "button", disabled: this.processingButton !== null }, this.processingButton === 'capture-back' && (index.h("span", { key: 'b6f6e82f515cd588eeca60e7abe220d89b40cfe8', class: "button-spinner" })), "Capturar Reverso")), index.h("button", { key: '7d91e6b780958a36df9a859fb02d8224b0de46dc', class: "skip-button", onClick: () => this.skipBackCapture(), type: "button", disabled: this.processingButton !== null }, this.processingButton === 'skip-back' && (index.h("span", { key: '0d5bce58452c7f7b5e197dfa0eff959971357b3c', class: "button-spinner" })), this.enableBackDocumentTimer && this.backDocumentTimerRemaining > 0
20305
20236
  ? `Saltar reverso (${this.backDocumentTimerRemaining}s)`
20306
- : 'Saltar reverso')))), captureState.isVideoActive && (index.h("div", { key: '67dd6532dbba68518b1e63f3b7a4274c7c4752ee', class: "camera-controls" }, index.h("button", { key: '263a995b82253189b0dd38166b4922fd05116359', class: `camera-selector-button ${this.isSwitchingCamera ? 'loading' : ''}`, onClick: () => this.toggleCameraSelector(), type: "button", title: "Seleccionar c\u00E1mara", disabled: this.isSwitchingCamera }, this.isSwitchingCamera ? (index.h("div", { class: "button-spinner" })) : ('Cámaras')))), this.showCameraSelector && cameraInfo.availableCameras.length > 0 && (index.h("div", { key: '26b730e85d5e8b6343bc5f7b9fb7d8e17caa7020', class: "camera-selector-dropdown" }, index.h("div", { key: 'c738e36131f87fb1aac2d872b9e53d2e3c315056', class: "camera-selector-header" }, index.h("span", { key: 'b5fd2cfa2700bca4b27cec3a8ebfe1ece6fe111a' }, "Seleccionar C\u00E1mara"), index.h("button", { key: '5d11e0227a6727733fee1c204635146c5c748ae9', class: "close-selector", onClick: () => this.toggleCameraSelector(), type: "button" }, "\u00D7")), index.h("div", { key: '190a36537e7650d37c8ed8d891a1c97fd4303869', class: "camera-list" }, cameraInfo.availableCameras.map((camera) => (index.h("button", { key: camera.id, class: `camera-option ${cameraInfo.selectedCameraId === camera.id ? 'selected' : ''}`, onClick: () => this.handleCameraSwitch(camera.id), type: "button" }, index.h("span", { class: "camera-label" }, camera.label || `Cámara ${cameraInfo.availableCameras.indexOf(camera) + 1}`, camera.hasAutofocus && (index.h("span", { class: "autofocus-icon", title: "Autofoco disponible" }, "\u29BF"))), cameraInfo.selectedCameraId === camera.id && (index.h("span", { class: "selected-indicator" }, "\u2713")))))), index.h("div", { key: '51405091e987752df5b85891ee9805b26d9e5fb8', class: "device-info" }, index.h("small", { key: '95c3e242217b722b584966946f4809aa61fb2b54' }, "Dispositivo: ", cameraInfo.deviceType)))), this.showManualCaptureButton && captureState.step === 'front' && !captureState.showFlipAnimation && !captureState.showSuccessAnimation && (index.h("div", { key: '577cc09e5ffdaeef0de4c06dbb82d299e48716d6', class: "manual-capture-section" }, index.h("button", { key: 'bf1fd11171e13c4c52b83d076d6cb3c79a225a84', class: "manual-capture-button", onClick: () => this.takeManualScreenshot(), type: "button", disabled: this.processingButton !== null }, this.processingButton === 'capture-front' && (index.h("span", { key: 'cbf77eb7cb791bb298de3cbbafd9955535e32c15', class: "button-spinner" })), "Capturar Frente"))))), captureState.isCapturing && (index.h("div", { key: 'bdd3793d2ce5ba351308fb64aa5a31bfa8dd85a1', class: "capture-animation" })), captureState.showFlipAnimation && (index.h("div", { key: '0f9df69e3a1002967c407505b965c14061c47365', class: "flip-animation" }, index.h("div", { key: '1384d5b75bd5e1f3584b93711a39825ae5a9b9a0', class: "id-card-icon" }), index.h("div", { key: 'aa4912fe5a4ec46ca69793a454a8c51632381fcd', class: "flip-text" }, "\u00A1Voltea tu identificaci\u00F3n!"))), captureState.showSuccessAnimation && (index.h("div", { key: '5e95f8b372b49719dd601367e9c7ba6dfbd13e30', class: "success-animation" }, index.h("div", { key: '72085304ac5fe6e2777f009a2091a39381fbc219', class: "check-icon" }), index.h("div", { key: '1476720f83274b7002365eb8c911f6dce0b84772', class: "success-text" }, "\u00A1Proceso completado!"))), index.h("div", { key: '68c3f77eb5fa1f442e9c77bcc8207189fd8126e4', class: `component-status status-${this.currentStatus.type}` }, (this.currentStatus.type === 'loading' || this.currentStatus.type === 'initializing') && (index.h("div", { key: '22bd3df4eca189c0100795befb31408ee4399461', class: "status-spinner" })), index.h("div", { key: '84c5b65b1b9f3f92704589d791e817a75e2e677d', class: "status-content" }, index.h("div", { key: 'a474e0cc716fff4f76cfb98dd0e7783eb4521db9', class: "status-message" }, this.currentStatus.message), this.currentStatus.description && (index.h("div", { key: '5255fe7ddb68f84b7a33ecede21af80c4ef9c476', class: "status-description" }, this.currentStatus.description)))), this.debug && (index.h("div", { key: 'a4e3a44c7896d3861980cca96329cf88a1cb6693', class: "performance-monitor" }, index.h("div", { key: '145ec7a322e316bf9989ea72e7ca877eb9630016', class: "performance-expanded" }, index.h("div", { key: '5bafabe9b0c82ac4682c474dafe7ecbe9be33896', class: "metrics-row" }, index.h("div", { key: '2c30946e8340f20887ba3a2c769fd731388a1fc8', class: "metric-compact" }, index.h("span", { key: '82b3b0679c93b88f0f0d88b1cd43479f01dbbd75', class: "metric-label" }, "FPS"), index.h("span", { key: '9af03b3dda821a0b8fbaec5be7127dd41d897b5d', class: `metric-value ${this.performanceData.fps < 15 ? 'warning' : this.performanceData.fps < 10 ? 'danger' : 'good'}` }, this.performanceData.fps)), index.h("div", { key: '2d0cc36e696b72f9d616b16e8e75c9bc977dd984', class: "metric-compact" }, index.h("span", { key: '624beadfa8641dbd690059fc7606cadc413ac247', class: "metric-label" }, "MEM"), index.h("span", { key: '30bd599357c1cbe7b945d2b72c1723ba7f361982', class: `metric-value ${this.performanceData.memoryUsage > 100 ? 'warning' : this.performanceData.memoryUsage > 200 ? 'danger' : 'good'}` }, this.performanceData.memoryUsage, "MB"))), index.h("div", { key: '661a150fca2411a1565cda581b105dd15a17a3d5', class: "metrics-row" }, index.h("div", { key: '82a8101abcbdebe1a32314d866a10d7be42b3e2f', class: "metric-compact" }, index.h("span", { key: '5abfae37ed5ec1f1bb14785f55a61bc1364aab40', class: "metric-label" }, "INF"), index.h("span", { key: '481df1d1fa0e1603bea786de8f20351f2cd9f949', class: `metric-value ${this.performanceData.inferenceTime > 100 ? 'warning' : this.performanceData.inferenceTime > 200 ? 'danger' : 'good'}` }, this.performanceData.inferenceTime, "ms")), index.h("div", { key: 'bfd657acb2cf6686e47c2ae4a348bf6ddfd11a66', class: "metric-compact" }, index.h("span", { key: '8dd9dfd72ae9183dce9985cca81c6ce6f80bc072', class: "metric-label" }, "FRAME"), index.h("span", { key: '09bff194b73d48d5e7c400d6132eab3741cd30f7', class: `metric-value ${this.performanceData.frameProcessingTime > 50 ? 'warning' : this.performanceData.frameProcessingTime > 100 ? 'danger' : 'good'}` }, this.performanceData.frameProcessingTime, "ms"))), index.h("div", { key: 'ad18e77ee79c7cec2257f30ed70cf1fd4289548e', class: "metrics-row" }, index.h("div", { key: 'ca2614b32424d8ccaa5e0823a740dfefc17a1ed5', class: "metric-compact" }, index.h("span", { key: 'd4b78f37d0b23bdcc35133417960d5a744f4a7df', class: "metric-label" }, "DET"), index.h("span", { key: 'c8b52e13d51f737e7e6cd1985abf570db27ccb0e', class: "metric-value good" }, this.performanceData.successfulDetections, "/", this.performanceData.totalDetections)), index.h("div", { key: '018d1bb321178b969fa868f1cf5eecba4bfdaa1f', class: "metric-compact" }, index.h("span", { key: '19b475406a767cf7fe417fd7c7dad980f54536b9', class: "metric-label" }, "RATE"), index.h("span", { key: '5994ed1ad88e07a597d82e1246cbe90c66d58214', class: `metric-value ${this.performanceData.detectionRate < 30 ? 'danger' : this.performanceData.detectionRate < 60 ? 'warning' : 'good'}` }, this.performanceData.detectionRate, "%")))))), index.h("div", { key: 'f07bd04ef68386e02f0b8d468bff1547986196e5', class: "watermark" }, index.h("img", { key: '009735bf081ace290d1a8e1805dd5d27201898c4', src: "https://static.jaak.ai/commons/powered-by-jaak.png", alt: "Powered by Jaak", onError: (e) => {
20237
+ : 'Saltar reverso')))), captureState.isVideoActive && (index.h("div", { key: 'e8fc7f2bb1a0ca8235a82ed368717205c7b63ad8', class: "camera-controls" }, index.h("button", { key: '691e4a97f2804666db5e32236619196d616227f7', class: `camera-selector-button ${this.isSwitchingCamera ? 'loading' : ''}`, onClick: () => this.toggleCameraSelector(), type: "button", title: "Seleccionar c\u00E1mara", disabled: this.isSwitchingCamera }, this.isSwitchingCamera ? (index.h("div", { class: "button-spinner" })) : ('Cámaras')))), this.showCameraSelector && cameraInfo.availableCameras.length > 0 && (index.h("div", { key: '80233723131262f516574a4dd2bb125970f7aeea', class: "camera-selector-dropdown" }, index.h("div", { key: 'c9284a77cd9f2d3e600924c9e5f38614f3d06dc4', class: "camera-selector-header" }, index.h("span", { key: '92a495d2b605a73a067791442a8c8617706d96bf' }, "Seleccionar C\u00E1mara"), index.h("button", { key: 'dc06382c154443ea9928740d53546dc2ab3ce662', class: "close-selector", onClick: () => this.toggleCameraSelector(), type: "button" }, "\u00D7")), index.h("div", { key: 'b520d0940ef51dc1a46641adaf834e105a16c964', class: "camera-list" }, cameraInfo.availableCameras.map((camera) => (index.h("button", { key: camera.id, class: `camera-option ${cameraInfo.selectedCameraId === camera.id ? 'selected' : ''}`, onClick: () => this.handleCameraSwitch(camera.id), type: "button" }, index.h("span", { class: "camera-label" }, camera.label || `Cámara ${cameraInfo.availableCameras.indexOf(camera) + 1}`, camera.hasAutofocus && (index.h("span", { class: "autofocus-icon", title: "Autofoco disponible" }, "\u29BF"))), cameraInfo.selectedCameraId === camera.id && (index.h("span", { class: "selected-indicator" }, "\u2713")))))), index.h("div", { key: '7df8908982af0142d5c02d9b09827f44e697cbb5', class: "device-info" }, index.h("small", { key: '5669aa375b7aa6cd98d36e5a77eb217e549a5d4d' }, "Dispositivo: ", cameraInfo.deviceType)))), this.showManualCaptureButton && captureState.step === 'front' && !captureState.showFlipAnimation && !captureState.showSuccessAnimation && (index.h("div", { key: '40ed9bde6c2a0afadd8b949ce0cba59344b09379', class: "manual-capture-section" }, index.h("button", { key: 'f394d0a578888782a0a569e721f06bb642ebfbd4', class: "manual-capture-button", onClick: () => this.takeManualScreenshot(), type: "button", disabled: this.processingButton !== null }, this.processingButton === 'capture-front' && (index.h("span", { key: 'ec5ee370a578705ccc3a562763c906701a1e4da4', class: "button-spinner" })), "Capturar Frente"))))), captureState.isCapturing && (index.h("div", { key: '60520ec5cdd2632ac9cd645a5d8d820298b7388b', class: "capture-animation" })), captureState.showFlipAnimation && (index.h("div", { key: 'af3647bc1dd4e58630bf06bae37d7e5cd522c900', class: "flip-animation" }, index.h("div", { key: 'e974ee4fc12ebdef1cdcef288951abb0b98b368a', class: "id-card-icon" }), index.h("div", { key: 'd80764bf0e01069d4fa1367b250215024c8e41ee', class: "flip-text" }, "\u00A1Voltea tu identificaci\u00F3n!"))), captureState.showSuccessAnimation && (index.h("div", { key: '07956e4e03dee2ebe64d5eeb1d0c6559dbd8c944', class: "success-animation" }, index.h("div", { key: 'd8cb39f4f7ad3adc9c16b2226b75d14b788636f6', class: "check-icon" }), index.h("div", { key: '9e3ddbac4946cd585de7c406d55915f532a390ed', class: "success-text" }, "\u00A1Proceso completado!"))), index.h("div", { key: 'b1ba412c9c4664eda9c024c3fa22e53f11acae4f', class: `component-status status-${this.currentStatus.type}` }, (this.currentStatus.type === 'loading' || this.currentStatus.type === 'initializing') && (index.h("div", { key: 'b466904829c87bcb050500c9f24f507a6d42d56d', class: "status-spinner" })), index.h("div", { key: '3dcfe509f83adf031fadd2fa322a110456e5993b', class: "status-content" }, index.h("div", { key: '3a6c820251b30c0cbd63538b23872ac1191b5213', class: "status-message" }, this.currentStatus.message), this.currentStatus.description && (index.h("div", { key: 'a7c35a8a773d852035a35e77fb99cf475307a5f7', class: "status-description" }, this.currentStatus.description)))), this.debug && (index.h("div", { key: 'd581099e2e1aedc1aea88a4c26af59a118042070', class: "performance-monitor" }, index.h("div", { key: '18bf5ba4feb6515a454d0769fe8eb02fd37ef167', class: "performance-expanded" }, index.h("div", { key: '7765f916c26556046b8326befc796f9188aeca3f', class: "metrics-row" }, index.h("div", { key: '9533109a7a762a7d8a95f12f45dddb6833fa7326', class: "metric-compact" }, index.h("span", { key: 'c236d06e692694a58519e86f133f39a5184a485f', class: "metric-label" }, "FPS"), index.h("span", { key: '4a7b53c89c4822dc03c6683f6d6895f96458b95d', class: `metric-value ${this.performanceData.fps < 15 ? 'warning' : this.performanceData.fps < 10 ? 'danger' : 'good'}` }, this.performanceData.fps)), index.h("div", { key: 'd362ceb5edf7585fc7c05da7367a6affee83b942', class: "metric-compact" }, index.h("span", { key: '08779e8da11b1593f7d91b409b36184ed405dee6', class: "metric-label" }, "MEM"), index.h("span", { key: '64c15bcbaeca6760e578e4ff9386583938c0be87', class: `metric-value ${this.performanceData.memoryUsage > 100 ? 'warning' : this.performanceData.memoryUsage > 200 ? 'danger' : 'good'}` }, this.performanceData.memoryUsage, "MB"))), index.h("div", { key: '1ef4f7a5aaae9ed9131bd45c7a4c227ad6419d93', class: "metrics-row" }, index.h("div", { key: 'c5d5ab2a81f7c8f5145253ece37e43981c68ccb8', class: "metric-compact" }, index.h("span", { key: '7ba45cae45b336c52adf1eb4588851be20475f4e', class: "metric-label" }, "INF"), index.h("span", { key: '1341edaafa1de81b304605378a8b1262f2f8a084', class: `metric-value ${this.performanceData.inferenceTime > 100 ? 'warning' : this.performanceData.inferenceTime > 200 ? 'danger' : 'good'}` }, this.performanceData.inferenceTime, "ms")), index.h("div", { key: '4c6edc10f88b776825a5a07643864fef4295c295', class: "metric-compact" }, index.h("span", { key: '7d58a7250a133b84f001a5313dce606fcd9eda82', class: "metric-label" }, "FRAME"), index.h("span", { key: 'de6a8e8475cd893546b939d5e3a7045a9d7df6dc', class: `metric-value ${this.performanceData.frameProcessingTime > 50 ? 'warning' : this.performanceData.frameProcessingTime > 100 ? 'danger' : 'good'}` }, this.performanceData.frameProcessingTime, "ms"))), index.h("div", { key: 'a26794337b9fd17fc9bc6718461c5251b57c1949', class: "metrics-row" }, index.h("div", { key: 'd790ac359b04532a5e7aa44e2a2952522c1ceb64', class: "metric-compact" }, index.h("span", { key: '581c72f166de867bbbfe3bb654cdf89e94cfc27b', class: "metric-label" }, "DET"), index.h("span", { key: '8d478a6d5e84151504e2dd136e2b1ff1e26e0853', class: "metric-value good" }, this.performanceData.successfulDetections, "/", this.performanceData.totalDetections)), index.h("div", { key: 'bb7f6dad291a79b5f683e51e07558ca73c22ad98', class: "metric-compact" }, index.h("span", { key: '1d2626fb63026ce3eb9d0696501b08c0ddf4be09', class: "metric-label" }, "RATE"), index.h("span", { key: '8f8a67276ad40ce3fe9acab86c2a807f426d2a23', class: `metric-value ${this.performanceData.detectionRate < 30 ? 'danger' : this.performanceData.detectionRate < 60 ? 'warning' : 'good'}` }, this.performanceData.detectionRate, "%")))))), index.h("div", { key: 'a9ae57be92d04f8d5d7eae801c0a0ae7c548f770', class: "watermark" }, index.h("img", { key: 'c9cd4510dfff2265e3ae5d213845e7b5d8f9a343', src: "https://static.jaak.ai/commons/powered-by-jaak.png", alt: "Powered by Jaak", onError: (e) => {
20307
20238
  const img = e.target;
20308
20239
  img.onerror = null;
20309
20240
  img.src = POWERED_BY_JAAK_FALLBACK;
@@ -20851,7 +20782,7 @@ const JaakStamps = class {
20851
20782
  await this.tracingService.flush();
20852
20783
  }
20853
20784
  catch (error) {
20854
- console.error('[jaak-stamps] Failed to flush traces:', error);
20785
+ console.error('[my-component] Failed to flush traces:', error);
20855
20786
  }
20856
20787
  }
20857
20788
  this.captureCompleted.emit(finalImages);
@@ -21124,12 +21055,8 @@ const JaakStamps = class {
21124
21055
  // If pool is full, let the canvas be garbage collected
21125
21056
  }
21126
21057
  static get assetsDirs() { return ["../../assets"]; }
21127
- static get watchers() { return {
21128
- "license": ["onLicenseChanged"],
21129
- "licenseEnvironment": ["onLicenseEnvironmentChanged"]
21130
- }; }
21131
21058
  };
21132
- JaakStamps.style = jaakStampsCss;
21059
+ JaakStamps.style = myComponentCss;
21133
21060
 
21134
21061
  exports.jaak_stamps = JaakStamps;
21135
21062
  //# sourceMappingURL=jaak-stamps.entry.cjs.js.map