smartcomply-web-sdk 1.0.62 → 1.0.64

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 (59) hide show
  1. package/dist/esm/flow/DocumentCapture.d.ts +21 -1
  2. package/dist/esm/flow/DocumentCapture.d.ts.map +1 -1
  3. package/dist/esm/flow/DocumentCapture.js +155 -84
  4. package/dist/esm/flow/DocumentCapture.js.map +1 -1
  5. package/dist/esm/flow/SmartComplyFlow.d.ts +1 -0
  6. package/dist/esm/flow/SmartComplyFlow.d.ts.map +1 -1
  7. package/dist/esm/flow/SmartComplyFlow.js +89 -105
  8. package/dist/esm/flow/SmartComplyFlow.js.map +1 -1
  9. package/dist/esm/flow/icons.d.ts +14 -0
  10. package/dist/esm/flow/icons.d.ts.map +1 -0
  11. package/dist/esm/flow/icons.js +34 -0
  12. package/dist/esm/flow/icons.js.map +1 -0
  13. package/dist/esm/flow/spinner.d.ts +15 -0
  14. package/dist/esm/flow/spinner.d.ts.map +1 -0
  15. package/dist/esm/flow/spinner.js +55 -0
  16. package/dist/esm/flow/spinner.js.map +1 -0
  17. package/dist/esm/flow/theme.d.ts +19 -0
  18. package/dist/esm/flow/theme.d.ts.map +1 -1
  19. package/dist/esm/flow/theme.js +19 -0
  20. package/dist/esm/flow/theme.js.map +1 -1
  21. package/dist/esm/modules/liveness/LivenessUI.d.ts +10 -0
  22. package/dist/esm/modules/liveness/LivenessUI.d.ts.map +1 -1
  23. package/dist/esm/modules/liveness/LivenessUI.js +17 -16
  24. package/dist/esm/modules/liveness/LivenessUI.js.map +1 -1
  25. package/dist/esm/modules/liveness/liveness.d.ts +2 -0
  26. package/dist/esm/modules/liveness/liveness.d.ts.map +1 -1
  27. package/dist/esm/modules/liveness/liveness.js +1 -1
  28. package/dist/esm/modules/liveness/liveness.js.map +1 -1
  29. package/dist/flow/DocumentCapture.d.ts +21 -1
  30. package/dist/flow/DocumentCapture.d.ts.map +1 -1
  31. package/dist/flow/DocumentCapture.js +155 -84
  32. package/dist/flow/DocumentCapture.js.map +1 -1
  33. package/dist/flow/SmartComplyFlow.d.ts +1 -0
  34. package/dist/flow/SmartComplyFlow.d.ts.map +1 -1
  35. package/dist/flow/SmartComplyFlow.js +88 -104
  36. package/dist/flow/SmartComplyFlow.js.map +1 -1
  37. package/dist/flow/icons.d.ts +14 -0
  38. package/dist/flow/icons.d.ts.map +1 -0
  39. package/dist/flow/icons.js +37 -0
  40. package/dist/flow/icons.js.map +1 -0
  41. package/dist/flow/spinner.d.ts +15 -0
  42. package/dist/flow/spinner.d.ts.map +1 -0
  43. package/dist/flow/spinner.js +59 -0
  44. package/dist/flow/spinner.js.map +1 -0
  45. package/dist/flow/theme.d.ts +19 -0
  46. package/dist/flow/theme.d.ts.map +1 -1
  47. package/dist/flow/theme.js +20 -1
  48. package/dist/flow/theme.js.map +1 -1
  49. package/dist/modules/liveness/LivenessUI.d.ts +10 -0
  50. package/dist/modules/liveness/LivenessUI.d.ts.map +1 -1
  51. package/dist/modules/liveness/LivenessUI.js +17 -16
  52. package/dist/modules/liveness/LivenessUI.js.map +1 -1
  53. package/dist/modules/liveness/liveness.d.ts +2 -0
  54. package/dist/modules/liveness/liveness.d.ts.map +1 -1
  55. package/dist/modules/liveness/liveness.js +1 -1
  56. package/dist/modules/liveness/liveness.js.map +1 -1
  57. package/dist/smartcomply.browser.js +333 -209
  58. package/dist/smartcomply.browser.js.map +4 -4
  59. package/package.json +1 -1
@@ -4672,8 +4672,14 @@ var SmartComplySDK = (() => {
4672
4672
  `;
4673
4673
  document.head.appendChild(s2);
4674
4674
  }
4675
+ var DEFAULT_COLORS = {
4676
+ primary: "#3b82f6",
4677
+ success: "#22c55e",
4678
+ error: "#ef4444",
4679
+ warning: "#fbbf24"
4680
+ };
4675
4681
  var LivenessUI = class {
4676
- constructor() {
4682
+ constructor(colors) {
4677
4683
  this.root = null;
4678
4684
  this.videoEl = null;
4679
4685
  this.instructionEl = null;
@@ -4687,6 +4693,7 @@ var SmartComplySDK = (() => {
4687
4693
  this.scanStartMs = 0;
4688
4694
  this.scanDurationMs = 0;
4689
4695
  this.faceTracked = false;
4696
+ this.colors = { ...DEFAULT_COLORS, ...colors };
4690
4697
  }
4691
4698
  mount(container, challenge) {
4692
4699
  injectLivenessKeyframes();
@@ -4761,7 +4768,7 @@ var SmartComplySDK = (() => {
4761
4768
  confOval.setAttribute("rx", "64");
4762
4769
  confOval.setAttribute("ry", "86");
4763
4770
  confOval.setAttribute("fill", "none");
4764
- confOval.setAttribute("stroke", "#3b82f6");
4771
+ confOval.setAttribute("stroke", this.colors.primary);
4765
4772
  confOval.setAttribute("stroke-width", "2.5");
4766
4773
  confOval.setAttribute("stroke-linecap", "round");
4767
4774
  const circ = 2 * Math.PI * Math.sqrt((64 * 64 + 86 * 86) / 2);
@@ -4770,7 +4777,7 @@ var SmartComplySDK = (() => {
4770
4777
  confOval.style.cssText = "transition:stroke-dashoffset 0.2s linear,stroke 0.3s ease;transform:rotate(-90deg);transform-origin:70px 90px;";
4771
4778
  this.confidenceRingEl = confOval;
4772
4779
  const bracketGroup = document.createElementNS("http://www.w3.org/2000/svg", "g");
4773
- bracketGroup.setAttribute("stroke", "#3b82f6");
4780
+ bracketGroup.setAttribute("stroke", this.colors.primary);
4774
4781
  bracketGroup.setAttribute("stroke-width", "3");
4775
4782
  bracketGroup.setAttribute("stroke-linecap", "round");
4776
4783
  bracketGroup.setAttribute("fill", "none");
@@ -4831,7 +4838,7 @@ var SmartComplySDK = (() => {
4831
4838
  for (let i2 = 0; i2 < 3; i2++) {
4832
4839
  const dot = document.createElement("div");
4833
4840
  dot.style.cssText = `
4834
- width:6px;height:6px;border-radius:50%;background:#3b82f6;
4841
+ width:6px;height:6px;border-radius:50%;background:${this.colors.primary};
4835
4842
  animation:sc-scan-dot 1.1s ease-in-out ${i2 * 0.18}s infinite;
4836
4843
  `;
4837
4844
  this.dotsEl.appendChild(dot);
@@ -4870,7 +4877,7 @@ var SmartComplySDK = (() => {
4870
4877
  const pct = this.scanDurationMs > 0 ? Math.min(1, elapsed / this.scanDurationMs) : 0;
4871
4878
  const circ = 2 * Math.PI * Math.sqrt((64 * 64 + 86 * 86) / 2);
4872
4879
  this.confidenceRingEl.setAttribute("stroke-dashoffset", `${circ * (1 - pct)}`);
4873
- this.confidenceRingEl.setAttribute("stroke", livenessConfirmed ? "#22c55e" : "#3b82f6");
4880
+ this.confidenceRingEl.setAttribute("stroke", livenessConfirmed ? this.colors.success : this.colors.primary);
4874
4881
  }
4875
4882
  /**
4876
4883
  * Reflects whether a face is currently detected in-frame — brightens the
@@ -4906,7 +4913,7 @@ var SmartComplySDK = (() => {
4906
4913
  <div style="text-align:center;color:#fff;animation:sc-pop-in 0.35s ease;padding:24px;">
4907
4914
  <div style="width:72px;height:72px;border-radius:50%;margin:0 auto 16px;display:flex;align-items:center;justify-content:center;font-size:32px;
4908
4915
  background:${ok ? "rgba(34,197,94,0.2)" : "rgba(239,68,68,0.2)"};
4909
- border:3px solid ${ok ? "#22c55e" : "#ef4444"};">
4916
+ border:3px solid ${ok ? this.colors.success : this.colors.error};">
4910
4917
  ${ok ? "✓" : "✕"}
4911
4918
  </div>
4912
4919
  <div style="font-size:17px;font-weight:700;margin-bottom:8px;">${ok ? "Verification submitted" : "Submission failed"}</div>
@@ -4924,10 +4931,10 @@ var SmartComplySDK = (() => {
4924
4931
  this.overlayEl.style.display = "flex";
4925
4932
  this.overlayEl.innerHTML = `
4926
4933
  <div style="text-align:center;color:#fff;animation:sc-pop-in 0.35s ease;padding:24px;">
4927
- <div style="width:72px;height:72px;border-radius:50%;margin:0 auto 14px;display:flex;align-items:center;justify-content:center;font-size:32px;background:rgba(251,191,36,0.15);border:3px solid #fbbf24;">⏱</div>
4934
+ <div style="width:72px;height:72px;border-radius:50%;margin:0 auto 14px;display:flex;align-items:center;justify-content:center;font-size:32px;background:rgba(251,191,36,0.15);border:3px solid ${this.colors.warning};">⏱</div>
4928
4935
  <div style="font-size:17px;font-weight:700;margin-bottom:8px;">Time's Up</div>
4929
4936
  <div style="font-size:12px;opacity:0.6;margin-bottom:18px;">We couldn't confirm liveness in time. Please try again.</div>
4930
- <button id="sc-retry-btn" style="padding:11px 28px;border-radius:10px;background:#3b82f6;color:#fff;border:none;cursor:pointer;font-size:14px;font-weight:600;width:100%;max-width:180px;">Try Again</button>
4937
+ <button id="sc-retry-btn" style="padding:11px 28px;border-radius:10px;background:${this.colors.primary};color:#fff;border:none;cursor:pointer;font-size:14px;font-weight:600;width:100%;max-width:180px;">Try Again</button>
4931
4938
  </div>`;
4932
4939
  const btn = this.overlayEl.querySelector("#sc-retry-btn");
4933
4940
  if (btn) {
@@ -4961,13 +4968,13 @@ var SmartComplySDK = (() => {
4961
4968
  docVideo.srcObject = stream;
4962
4969
  const guideOverlay = document.createElement("div");
4963
4970
  guideOverlay.style.cssText = "position:absolute;inset:0;pointer-events:none;display:flex;align-items:center;justify-content:center;";
4964
- guideOverlay.innerHTML = `<div style="width:83%;height:53%;border:2px dashed rgba(255,255,255,0.55);border-radius:10px;box-shadow:0 0 0 2000px rgba(0,0,0,0.45);position:relative;"><div style="position:absolute;top:-2px;left:-2px;width:18px;height:18px;border-top:3px solid #3b82f6;border-left:3px solid #3b82f6;border-radius:4px 0 0 0;"></div><div style="position:absolute;top:-2px;right:-2px;width:18px;height:18px;border-top:3px solid #3b82f6;border-right:3px solid #3b82f6;border-radius:0 4px 0 0;"></div><div style="position:absolute;bottom:-2px;left:-2px;width:18px;height:18px;border-bottom:3px solid #3b82f6;border-left:3px solid #3b82f6;border-radius:0 0 0 4px;"></div><div style="position:absolute;bottom:-2px;right:-2px;width:18px;height:18px;border-bottom:3px solid #3b82f6;border-right:3px solid #3b82f6;border-radius:0 0 4px 0;"></div></div>`;
4971
+ guideOverlay.innerHTML = `<div style="width:83%;height:53%;border:2px dashed rgba(255,255,255,0.55);border-radius:10px;box-shadow:0 0 0 2000px rgba(0,0,0,0.45);position:relative;"><div style="position:absolute;top:-2px;left:-2px;width:18px;height:18px;border-top:3px solid ${this.colors.primary};border-left:3px solid ${this.colors.primary};border-radius:4px 0 0 0;"></div><div style="position:absolute;top:-2px;right:-2px;width:18px;height:18px;border-top:3px solid ${this.colors.primary};border-right:3px solid ${this.colors.primary};border-radius:0 4px 0 0;"></div><div style="position:absolute;bottom:-2px;left:-2px;width:18px;height:18px;border-bottom:3px solid ${this.colors.primary};border-left:3px solid ${this.colors.primary};border-radius:0 0 0 4px;"></div><div style="position:absolute;bottom:-2px;right:-2px;width:18px;height:18px;border-bottom:3px solid ${this.colors.primary};border-right:3px solid ${this.colors.primary};border-radius:0 0 4px 0;"></div></div>`;
4965
4972
  const header = document.createElement("div");
4966
4973
  header.style.cssText = "position:absolute;top:0;left:0;right:0;background:linear-gradient(180deg,rgba(0,0,0,0.88) 0%,transparent 100%);padding:18px 16px 40px;text-align:center;";
4967
4974
  header.innerHTML = `<div style="color:#fff;font-size:16px;font-weight:700;margin-bottom:6px;">Scan Your ID Document</div><div style="color:rgba(255,255,255,0.6);font-size:12px;line-height:1.6;">Fit your document inside the frame.<br>Make sure all text and corners are visible.</div>`;
4968
4975
  const bottomPanel = document.createElement("div");
4969
4976
  bottomPanel.style.cssText = "position:absolute;bottom:0;left:0;right:0;background:linear-gradient(0deg,rgba(0,0,0,0.92) 0%,rgba(0,0,0,0.6) 70%,transparent 100%);padding:16px;";
4970
- bottomPanel.innerHTML = `<div style="font-size:11px;color:rgba(255,255,255,0.4);text-align:center;margin-bottom:12px;">💡 Good lighting · No glare · All 4 corners visible</div><button id="sc-capture-doc-btn" style="width:100%;padding:12px;border-radius:12px;background:#3b82f6;color:#fff;border:none;cursor:pointer;font-size:15px;font-weight:700;margin-bottom:8px;">Capture Document</button><label style="width:100%;display:flex;align-items:center;justify-content:center;gap:6px;padding:9px;border-radius:12px;border:1.5px solid rgba(255,255,255,0.18);cursor:pointer;color:rgba(255,255,255,0.6);font-size:13px;font-weight:500;"><span>📁</span><span>Upload from gallery instead</span><input id="sc-upload-doc-input" type="file" accept="image/*" style="display:none;" /></label>`;
4977
+ bottomPanel.innerHTML = `<div style="font-size:11px;color:rgba(255,255,255,0.4);text-align:center;margin-bottom:12px;">Good lighting · No glare · All 4 corners visible</div><button id="sc-capture-doc-btn" style="width:100%;padding:12px;border-radius:12px;background:${this.colors.primary};color:#fff;border:none;cursor:pointer;font-size:15px;font-weight:700;margin-bottom:8px;">Capture Document</button><label style="width:100%;display:flex;align-items:center;justify-content:center;gap:6px;padding:9px;border-radius:12px;border:1.5px solid rgba(255,255,255,0.18);cursor:pointer;color:rgba(255,255,255,0.6);font-size:13px;font-weight:500;"><span>📁</span><span>Upload from gallery instead</span><input id="sc-upload-doc-input" type="file" accept="image/*" style="display:none;" /></label>`;
4971
4978
  docRoot.appendChild(docVideo);
4972
4979
  docRoot.appendChild(guideOverlay);
4973
4980
  docRoot.appendChild(header);
@@ -5323,7 +5330,7 @@ var SmartComplySDK = (() => {
5323
5330
  const camera = new CameraManager();
5324
5331
  const recorder = new VideoRecorder();
5325
5332
  const faceEngine = new FaceDetectorEngine();
5326
- const ui2 = new LivenessUI();
5333
+ const ui2 = new LivenessUI(params.colors);
5327
5334
  let cleanedUp = false;
5328
5335
  const cleanup = () => {
5329
5336
  if (cleanedUp) return;
@@ -5713,6 +5720,20 @@ var SmartComplySDK = (() => {
5713
5720
  };
5714
5721
 
5715
5722
  // src/flow/theme.ts
5723
+ var RADIUS = {
5724
+ sm: 8,
5725
+ md: 12,
5726
+ lg: 16,
5727
+ pill: 999
5728
+ };
5729
+ var TYPE = {
5730
+ xs: 12,
5731
+ sm: 13,
5732
+ base: 15,
5733
+ headingSm: 16,
5734
+ heading: 18,
5735
+ headingLg: 22
5736
+ };
5716
5737
  var THEMES = {
5717
5738
  default: {
5718
5739
  primary: "#3b82f6",
@@ -5953,14 +5974,90 @@ var SmartComplySDK = (() => {
5953
5974
  return Math.min(maxWidth / srcWidth, maxHeight / srcHeight, 1);
5954
5975
  }
5955
5976
 
5977
+ // src/flow/icons.ts
5978
+ var PATHS = {
5979
+ shield: '<path d="M12 2l8 3v6c0 5-3.5 8.5-8 11-4.5-2.5-8-6-8-11V5l8-3z"/>',
5980
+ "id-card": '<rect x="2" y="5" width="20" height="14" rx="2"/><circle cx="8" cy="12" r="2"/><path d="M13 10h6M13 14h4"/>',
5981
+ document: '<path d="M6 2h9l5 5v15H6z"/><path d="M15 2v5h5"/><path d="M9 13h6M9 17h6"/>',
5982
+ check: '<path d="M4 12l6 6L20 6"/>',
5983
+ close: '<path d="M5 5l14 14M19 5L5 19"/>',
5984
+ camera: '<path d="M4 8h3l2-3h6l2 3h3v11H4z"/><circle cx="12" cy="13" r="3.5"/>',
5985
+ gallery: '<rect x="3" y="4" width="18" height="16" rx="2"/><circle cx="8.5" cy="9.5" r="1.5"/><path d="M21 15l-5-5-9 9"/>',
5986
+ network: '<path d="M2 8.5a17 17 0 0120 0M5.5 12.5a12 12 0 0113 0M9 16.5a6 6 0 016 0"/><circle cx="12" cy="20" r="1"/>',
5987
+ clock: '<circle cx="12" cy="12" r="9"/><path d="M12 7v5l3.5 2"/>',
5988
+ search: '<circle cx="10.5" cy="10.5" r="6.5"/><path d="M20 20l-4.8-4.8"/>',
5989
+ calendar: '<rect x="3" y="5" width="18" height="16" rx="2"/><path d="M3 10h18M8 3v4M16 3v4"/>',
5990
+ face: '<circle cx="12" cy="12" r="9"/><path d="M9 10h.01M15 10h.01M8.5 15c1 1.2 2.2 1.8 3.5 1.8s2.5-.6 3.5-1.8"/>',
5991
+ warning: '<path d="M12 3l10 18H2z"/><path d="M12 10v4"/><circle cx="12" cy="17" r="0.5" fill="currentColor"/>',
5992
+ passport: '<rect x="5" y="2" width="14" height="20" rx="2"/><circle cx="12" cy="9" r="2.5"/><path d="M9 15h6"/>',
5993
+ car: '<path d="M4 16V11l2-5h12l2 5v5"/><path d="M4 16h16M7 16v2M17 16v2"/><circle cx="7.5" cy="14" r="1"/><circle cx="16.5" cy="14" r="1"/>',
5994
+ ballot: '<rect x="4" y="8" width="16" height="12" rx="1"/><path d="M9 8V5a3 3 0 016 0v3"/><path d="M12 12v4"/>',
5995
+ refresh: '<path d="M4 4v6h6"/><path d="M20 20v-6h-6"/><path d="M20 10a8 8 0 00-14.6-4.6M4 14a8 8 0 0014.6 4.6"/>'
5996
+ };
5997
+ function icon(name, size = 24) {
5998
+ const d2 = PATHS[name];
5999
+ return `<svg width="${size}" height="${size}" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">${d2}</svg>`;
6000
+ }
6001
+
6002
+ // src/flow/spinner.ts
6003
+ var injected = false;
6004
+ function injectSpinnerKeyframes() {
6005
+ if (injected || document.getElementById("sc-spinner-kf")) {
6006
+ injected = true;
6007
+ return;
6008
+ }
6009
+ const style = document.createElement("style");
6010
+ style.id = "sc-spinner-kf";
6011
+ style.textContent = `
6012
+ @keyframes sc-spin { to { transform: rotate(360deg); } }
6013
+ @keyframes sc-spinner-pulse {
6014
+ 0%, 100% { transform: scale(1); opacity: 1; }
6015
+ 50% { transform: scale(1.1); opacity: 0.8; }
6016
+ }
6017
+ `;
6018
+ document.head.appendChild(style);
6019
+ injected = true;
6020
+ }
6021
+ function renderSpinner(theme, opts = {}) {
6022
+ injectSpinnerKeyframes();
6023
+ const size = opts.size ?? 44;
6024
+ const wrap = document.createElement("div");
6025
+ wrap.style.cssText = `position:relative;width:${size}px;height:${size}px;flex-shrink:0;`;
6026
+ const ring = document.createElement("div");
6027
+ ring.style.cssText = `
6028
+ position:absolute;inset:0;border-radius:50%;
6029
+ border:${Math.max(2, Math.round(size / 20))}px solid ${theme.border};
6030
+ border-top-color:${theme.primary};
6031
+ animation:sc-spin 0.9s linear infinite;
6032
+ `;
6033
+ wrap.appendChild(ring);
6034
+ if (opts.icon) {
6035
+ const center = document.createElement("div");
6036
+ center.style.cssText = `
6037
+ position:absolute;inset:0;display:flex;align-items:center;justify-content:center;
6038
+ color:${theme.primary};animation:sc-spinner-pulse 2s ease-in-out infinite;
6039
+ `;
6040
+ center.innerHTML = opts.icon;
6041
+ wrap.appendChild(center);
6042
+ }
6043
+ return wrap;
6044
+ }
6045
+ function renderInlineSpinner(color = "#fff", size = 13) {
6046
+ injectSpinnerKeyframes();
6047
+ return `<span style="display:inline-block;width:${size}px;height:${size}px;border-radius:50%;border:2px solid rgba(255,255,255,0.3);border-top-color:${color};animation:sc-spin 0.6s linear infinite;flex-shrink:0;"></span>`;
6048
+ }
6049
+
5956
6050
  // src/flow/DocumentCapture.ts
5957
6051
  var DocumentCapture = class {
5958
6052
  constructor() {
5959
6053
  this.root = null;
5960
6054
  this.videoEl = null;
6055
+ this.videoWrapEl = null;
5961
6056
  this.cameraManager = new CameraManager();
6057
+ this.orientationHandler = null;
5962
6058
  this.resolveCapture = null;
5963
6059
  this.rejectCapture = null;
6060
+ this.frontViaCamera = false;
5964
6061
  this.frontBlob = null;
5965
6062
  this.backBlob = null;
5966
6063
  this.currentSide = "front";
@@ -5992,6 +6089,7 @@ var SmartComplySDK = (() => {
5992
6089
  this.rejectCapture = reject;
5993
6090
  this.frontBlob = null;
5994
6091
  this.backBlob = null;
6092
+ this.frontViaCamera = false;
5995
6093
  this.currentSide = "front";
5996
6094
  this.requiresBackOverride = requiresBack;
5997
6095
  this.renderChoiceScreen(container, theme, documentType);
@@ -6034,14 +6132,14 @@ var SmartComplySDK = (() => {
6034
6132
  iconBox.style.cssText = `
6035
6133
  width:48px;height:48px;border-radius:14px;flex-shrink:0;
6036
6134
  display:flex;align-items:center;justify-content:center;
6037
- font-size:24px;
6135
+ color:${theme.primary};
6038
6136
  background:${theme.primary}15;
6039
6137
  border:1.5px solid ${theme.primary}30;
6040
6138
  `;
6041
- iconBox.textContent = this._docIcon(documentType);
6139
+ iconBox.innerHTML = icon(this._docIcon(documentType), 22);
6042
6140
  const titleBlock = document.createElement("div");
6043
6141
  const titleEl = document.createElement("div");
6044
- titleEl.style.cssText = `color:${theme.text};font-size:16px;font-weight:700;line-height:1.3;`;
6142
+ titleEl.style.cssText = `color:${theme.text};font-size:${TYPE.headingSm}px;font-weight:700;line-height:1.3;`;
6045
6143
  titleEl.textContent = `Capture your ${docLabel}`;
6046
6144
  const subEl = document.createElement("div");
6047
6145
  subEl.style.cssText = `color:${theme.textSecondary};font-size:12px;margin-top:2px;`;
@@ -6066,7 +6164,7 @@ var SmartComplySDK = (() => {
6066
6164
  transition:all 0.15s ease;min-height:80px;
6067
6165
  box-shadow:0 4px 14px ${theme.primary}30;
6068
6166
  `;
6069
- cameraBtn.innerHTML = `<span style="font-size:26px;">📷</span><span>Take Photo</span><span style="font-size:10px;opacity:0.8;font-weight:500;">Use camera</span>`;
6167
+ cameraBtn.innerHTML = `<span style="display:inline-flex;">${icon("camera", 24)}</span><span>Take Photo</span><span style="font-size:10px;opacity:0.8;font-weight:500;">Use camera</span>`;
6070
6168
  cameraBtn.addEventListener("mouseenter", () => {
6071
6169
  cameraBtn.style.opacity = "0.9";
6072
6170
  cameraBtn.style.transform = "translateY(-1px)";
@@ -6088,7 +6186,7 @@ var SmartComplySDK = (() => {
6088
6186
  font-size:13px;font-weight:600;font-family:inherit;
6089
6187
  transition:all 0.15s ease;min-height:80px;
6090
6188
  `;
6091
- uploadBtn.innerHTML = `<span style="font-size:26px;">🖼️</span><span>From Gallery</span><span style="font-size:10px;color:${theme.textMuted || theme.textSecondary};font-weight:500;">Upload file</span>`;
6189
+ uploadBtn.innerHTML = `<span style="display:inline-flex;">${icon("gallery", 24)}</span><span>From Gallery</span><span style="font-size:10px;color:${theme.textMuted || theme.textSecondary};font-weight:500;">Upload file</span>`;
6092
6190
  uploadBtn.addEventListener("mouseenter", () => {
6093
6191
  uploadBtn.style.borderColor = theme.primary;
6094
6192
  uploadBtn.style.transform = "translateY(-1px)";
@@ -6107,7 +6205,7 @@ var SmartComplySDK = (() => {
6107
6205
  tips.style.cssText = `
6108
6206
  margin:0 20px 16px;padding:12px 14px;
6109
6207
  background:${theme.shimmer || theme.cardBg};
6110
- border:1px solid ${theme.border};border-radius:12px;
6208
+ border:1px solid ${theme.border};border-radius:${RADIUS.md}px;
6111
6209
  `;
6112
6210
  const tipsGrid = document.createElement("div");
6113
6211
  tipsGrid.style.cssText = `
@@ -6122,7 +6220,7 @@ var SmartComplySDK = (() => {
6122
6220
  tipItems.forEach((t2) => {
6123
6221
  const row = document.createElement("div");
6124
6222
  row.style.cssText = `display:flex;align-items:center;gap:5px;font-size:11px;color:${theme.textSecondary};`;
6125
- row.innerHTML = `<span style="color:${theme.primary};font-weight:700;flex-shrink:0;">✓</span><span>${t2}</span>`;
6223
+ row.innerHTML = `<span style="color:${theme.primary};flex-shrink:0;display:inline-flex;">${icon("check", 12)}</span><span>${t2}</span>`;
6126
6224
  tipsGrid.appendChild(row);
6127
6225
  });
6128
6226
  tips.appendChild(tipsGrid);
@@ -6159,45 +6257,84 @@ var SmartComplySDK = (() => {
6159
6257
  this.root.appendChild(fileInput);
6160
6258
  container.appendChild(this.root);
6161
6259
  }
6162
- /** Returns an appropriate emoji icon for the document type. */
6260
+ /** Returns the icon name matching the document type. */
6163
6261
  _docIcon(documentType) {
6164
6262
  const t2 = documentType.toLowerCase();
6165
- if (t2.includes("passport")) return "📘";
6166
- if (t2.includes("driver") || t2.includes("licen")) return "🚗";
6167
- if (t2.includes("voter") || t2.includes("pvc")) return "🗳️";
6168
- return "🪪";
6263
+ if (t2.includes("passport")) return "passport";
6264
+ if (t2.includes("driver") || t2.includes("licen")) return "car";
6265
+ if (t2.includes("voter") || t2.includes("pvc")) return "ballot";
6266
+ return "id-card";
6169
6267
  }
6170
6268
  renderCameraView(container, theme, documentType) {
6171
6269
  const wrapper = document.createElement("div");
6172
- wrapper.style.cssText = "position:relative;width:100%;border-radius:12px;overflow:hidden;background:#000;";
6270
+ wrapper.style.cssText = `
6271
+ position:relative;width:100%;max-width:420px;margin:0 auto;
6272
+ background:#0a0a0a;border-radius:${RADIUS.lg}px;overflow:hidden;
6273
+ box-shadow:0 8px 32px rgba(0,0,0,0.4);
6274
+ `;
6275
+ this.videoWrapEl = wrapper;
6173
6276
  this.videoEl = document.createElement("video");
6174
6277
  this.videoEl.autoplay = true;
6175
6278
  this.videoEl.playsInline = true;
6176
6279
  this.videoEl.muted = true;
6177
6280
  this.videoEl.style.cssText = "width:100%;display:block;aspect-ratio:4/3;object-fit:cover;";
6178
6281
  wrapper.appendChild(this.videoEl);
6179
- const guide = document.createElement("div");
6180
- guide.style.cssText = `
6181
- position:absolute;inset:0;display:flex;align-items:center;justify-content:center;
6182
- pointer-events:none;
6282
+ const vignette = document.createElement("div");
6283
+ vignette.style.cssText = `
6284
+ position:absolute;inset:0;pointer-events:none;
6285
+ box-shadow:inset 0 0 0 9999px rgba(0,0,0,0.38);
6286
+ -webkit-mask:radial-gradient(ellipse 46% 34% at 50% 50%, transparent 60%, #000 100%);
6287
+ mask:radial-gradient(ellipse 46% 34% at 50% 50%, transparent 60%, #000 100%);
6183
6288
  `;
6184
- const rect = document.createElement("div");
6185
- rect.style.cssText = `
6186
- width:85%;height:60%;border:2px solid rgba(255,255,255,0.6);
6187
- border-radius:12px;box-shadow:0 0 0 9999px rgba(0,0,0,0.4);
6289
+ wrapper.appendChild(vignette);
6290
+ const guideWrap = document.createElement("div");
6291
+ guideWrap.style.cssText = `
6292
+ position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);
6293
+ width:84%;aspect-ratio:16/10;pointer-events:none;
6188
6294
  `;
6189
- guide.appendChild(rect);
6190
- wrapper.appendChild(guide);
6191
- const guideLbl = document.createElement("div");
6192
- guideLbl.style.cssText = `
6193
- position:absolute;bottom:60px;left:0;right:0;text-align:center;
6194
- color:#fff;font-size:13px;font-weight:600;
6195
- text-shadow:0 1px 3px rgba(0,0,0,0.5);
6295
+ const svg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
6296
+ svg.setAttribute("viewBox", "0 0 160 100");
6297
+ svg.style.cssText = "width:100%;height:100%;overflow:visible;";
6298
+ const bracketGroup = document.createElementNS("http://www.w3.org/2000/svg", "g");
6299
+ bracketGroup.setAttribute("stroke", theme.primary);
6300
+ bracketGroup.setAttribute("stroke-width", "3");
6301
+ bracketGroup.setAttribute("stroke-linecap", "round");
6302
+ bracketGroup.setAttribute("fill", "none");
6303
+ const bLen = 16;
6304
+ const bx0 = 4, bx1 = 156, by0 = 4, by1 = 96;
6305
+ const brackets = [
6306
+ `M${bx0},${by0 + bLen} L${bx0},${by0} L${bx0 + bLen},${by0}`,
6307
+ `M${bx1 - bLen},${by0} L${bx1},${by0} L${bx1},${by0 + bLen}`,
6308
+ `M${bx0},${by1 - bLen} L${bx0},${by1} L${bx0 + bLen},${by1}`,
6309
+ `M${bx1 - bLen},${by1} L${bx1},${by1} L${bx1},${by1 - bLen}`
6310
+ ];
6311
+ for (const d2 of brackets) {
6312
+ const path = document.createElementNS("http://www.w3.org/2000/svg", "path");
6313
+ path.setAttribute("d", d2);
6314
+ bracketGroup.appendChild(path);
6315
+ }
6316
+ svg.appendChild(bracketGroup);
6317
+ guideWrap.appendChild(svg);
6318
+ wrapper.appendChild(guideWrap);
6319
+ const header = document.createElement("div");
6320
+ header.style.cssText = `
6321
+ position:absolute;top:0;left:0;right:0;
6322
+ background:linear-gradient(180deg,rgba(0,0,0,0.8) 0%,transparent 100%);
6323
+ padding:14px 16px 32px;text-align:center;
6196
6324
  `;
6197
- guideLbl.textContent = `Align your ${this.getDocumentLabel(documentType)} within the frame`;
6198
- wrapper.appendChild(guideLbl);
6325
+ header.innerHTML = `<div style="color:#fff;font-size:${TYPE.sm}px;font-weight:600;">Align your ${this.getDocumentLabel(documentType)} within the frame</div>`;
6326
+ wrapper.appendChild(header);
6327
+ const footer = document.createElement("div");
6328
+ footer.style.cssText = `
6329
+ position:absolute;bottom:0;left:0;right:0;
6330
+ background:linear-gradient(0deg,rgba(0,0,0,0.7) 0%,transparent 100%);
6331
+ padding:28px 10px 18px;text-align:center;
6332
+ `;
6333
+ footer.innerHTML = `<div style="font-size:${TYPE.xs}px;color:rgba(255,255,255,0.55);">Good lighting · No glare · All 4 corners visible</div>`;
6334
+ wrapper.appendChild(footer);
6199
6335
  container.appendChild(wrapper);
6200
6336
  const captureBtn = document.createElement("button");
6337
+ captureBtn.setAttribute("aria-label", "Capture photo");
6201
6338
  captureBtn.style.cssText = `
6202
6339
  display:block;margin:16px auto 0;width:64px;height:64px;
6203
6340
  border-radius:50%;border:4px solid ${theme.primary};
@@ -6223,6 +6360,39 @@ var SmartComplySDK = (() => {
6223
6360
  container.appendChild(captureBtn);
6224
6361
  this.openCamera();
6225
6362
  }
6363
+ /**
6364
+ * Matches the video box's aspect-ratio CSS to the stream's actual
6365
+ * negotiated dimensions instead of a single hardcoded ratio — a stream
6366
+ * that's natively 16:9 no longer gets force-cropped into a 4:3 box.
6367
+ * Clamped to a sane document-shaped range so a degenerate/unusual stream
6368
+ * can't produce a sliver-thin or absurdly tall box.
6369
+ */
6370
+ _fitToStream() {
6371
+ if (!this.videoEl) return;
6372
+ const { videoWidth: w2, videoHeight: h2 } = this.videoEl;
6373
+ if (!w2 || !h2) return;
6374
+ const ratio = Math.min(Math.max(w2 / h2, 1), 2);
6375
+ this.videoEl.style.aspectRatio = `${ratio}`;
6376
+ }
6377
+ /**
6378
+ * Re-fits the video box when the device rotates mid-capture. Does not
6379
+ * re-request getUserMedia (disruptive/slow) — the stream's dimensions
6380
+ * don't change on rotation, only the viewport does, so re-reading the
6381
+ * already-known videoWidth/videoHeight is enough to keep the box sane.
6382
+ */
6383
+ _watchOrientation() {
6384
+ this._unwatchOrientation();
6385
+ this.orientationHandler = () => this._fitToStream();
6386
+ window.addEventListener("orientationchange", this.orientationHandler);
6387
+ window.addEventListener("resize", this.orientationHandler);
6388
+ }
6389
+ _unwatchOrientation() {
6390
+ if (this.orientationHandler) {
6391
+ window.removeEventListener("orientationchange", this.orientationHandler);
6392
+ window.removeEventListener("resize", this.orientationHandler);
6393
+ this.orientationHandler = null;
6394
+ }
6395
+ }
6226
6396
  async openCamera() {
6227
6397
  if (!navigator.mediaDevices || !navigator.mediaDevices.getUserMedia) {
6228
6398
  this.rejectCapture?.(new Error("Camera access is not supported in this browser. Please use a modern browser like Chrome, Firefox, or Safari."));
@@ -6269,6 +6439,8 @@ var SmartComplySDK = (() => {
6269
6439
  });
6270
6440
  if (this.videoEl) {
6271
6441
  this.videoEl.srcObject = stream;
6442
+ this.videoEl.addEventListener("loadedmetadata", () => this._fitToStream(), { once: true });
6443
+ this._watchOrientation();
6272
6444
  }
6273
6445
  }
6274
6446
  captureFrame(container, theme, documentType) {
@@ -6285,7 +6457,7 @@ var SmartComplySDK = (() => {
6285
6457
  this.stopCamera();
6286
6458
  this.showLoadingState("Analyzing photo...", theme);
6287
6459
  const quality = await this._assessImageQuality(canvas, ctx);
6288
- this.showPreview(container, theme, blob, documentType, quality);
6460
+ this.showPreview(container, theme, blob, documentType, quality, true);
6289
6461
  }
6290
6462
  },
6291
6463
  "image/jpeg",
@@ -6327,28 +6499,37 @@ var SmartComplySDK = (() => {
6327
6499
  return null;
6328
6500
  }
6329
6501
  }
6330
- showPreview(container, theme, imageData, documentType, quality) {
6502
+ showPreview(container, theme, imageData, documentType, quality, viaCamera) {
6331
6503
  if (this.root) this.root.innerHTML = "";
6332
6504
  else {
6333
6505
  this.root = document.createElement("div");
6334
6506
  container.appendChild(this.root);
6335
6507
  }
6336
6508
  this.root.style.cssText = "display:flex;flex-direction:column;align-items:center;gap:16px;";
6509
+ const stepBadge = document.createElement("div");
6510
+ stepBadge.style.cssText = `
6511
+ display:inline-flex;align-items:center;gap:5px;
6512
+ padding:3px 11px;border-radius:${RADIUS.pill}px;
6513
+ font-size:10.5px;font-weight:600;letter-spacing:0.2px;
6514
+ color:${theme.primary};background:${theme.primary}15;border:1px solid ${theme.primary}30;
6515
+ `;
6516
+ stepBadge.textContent = "STEP 1 OF 2 · CHECK THE PHOTO";
6517
+ this.root.appendChild(stepBadge);
6337
6518
  const img = document.createElement("img");
6338
6519
  const imageUrl = URL.createObjectURL(imageData);
6339
6520
  img.src = imageUrl;
6340
6521
  img.style.cssText = `
6341
- width:100%;max-height:300px;object-fit:contain;border-radius:12px;
6522
+ width:100%;max-height:300px;object-fit:contain;border-radius:${RADIUS.md}px;
6342
6523
  border:2px solid ${theme.border};
6343
6524
  `;
6344
6525
  this.root.appendChild(img);
6345
6526
  img._blobUrl = imageUrl;
6346
6527
  const label = document.createElement("div");
6347
- label.style.cssText = `color:${theme.textSecondary};font-size:13px;text-align:center;font-weight:500;`;
6528
+ label.style.cssText = `color:${theme.text};font-size:${TYPE.base}px;font-weight:700;text-align:center;`;
6348
6529
  label.textContent = "Does the photo look clear?";
6349
6530
  this.root.appendChild(label);
6350
6531
  const sublabel = document.createElement("div");
6351
- sublabel.style.cssText = `color:${theme.textMuted};font-size:11px;text-align:center;line-height:1.6;`;
6532
+ sublabel.style.cssText = `color:${theme.textMuted};font-size:${TYPE.xs}px;text-align:center;line-height:1.6;`;
6352
6533
  sublabel.textContent = "All text must be readable and all four corners must be visible.";
6353
6534
  this.root.appendChild(sublabel);
6354
6535
  const qualityIsPoor = !!quality && !quality.isValid;
@@ -6388,7 +6569,7 @@ var SmartComplySDK = (() => {
6388
6569
  }
6389
6570
  useBtn.textContent = "Processing...";
6390
6571
  useBtn.disabled = true;
6391
- this.compressImage(imageData, 2e3, 1500, 0.92).then((compressed) => this.handleCaptureComplete(compressed, container, theme, documentType)).catch(() => this.handleCaptureComplete(imageData, container, theme, documentType));
6572
+ this.compressImage(imageData, 2e3, 1500, 0.92).then((compressed) => this.handleCaptureComplete(compressed, container, theme, documentType, viaCamera)).catch(() => this.handleCaptureComplete(imageData, container, theme, documentType, viaCamera));
6392
6573
  };
6393
6574
  const useBtn = this.createButton(qualityIsPoor ? "Use Anyway ⚠" : "Use Photo ✓", theme, !qualityIsPoor);
6394
6575
  useBtn.style.flex = "1";
@@ -6409,11 +6590,12 @@ var SmartComplySDK = (() => {
6409
6590
  btnRow.appendChild(useBtn);
6410
6591
  this.root.appendChild(btnRow);
6411
6592
  }
6412
- handleCaptureComplete(imageData, container, theme, documentType) {
6593
+ handleCaptureComplete(imageData, container, theme, documentType, viaCamera) {
6413
6594
  const requiresBack = this.shouldCaptureBackSide(documentType);
6414
6595
  const wasCapturingFront = this.currentSide === "front";
6415
6596
  if (wasCapturingFront) {
6416
6597
  this.frontBlob = imageData;
6598
+ this.frontViaCamera = viaCamera;
6417
6599
  } else {
6418
6600
  this.backBlob = imageData;
6419
6601
  }
@@ -6429,13 +6611,14 @@ var SmartComplySDK = (() => {
6429
6611
  }
6430
6612
  const result = {
6431
6613
  front: this.frontBlob,
6432
- back: this.backBlob || void 0
6614
+ back: this.backBlob || void 0,
6615
+ viaCamera: this.frontViaCamera
6433
6616
  };
6434
6617
  this.resolveCapture?.(result);
6435
6618
  }
6436
6619
  async handleFileUploadComplete(imageData, container, theme, documentType) {
6437
6620
  const quality = await this._assessBlobQuality(imageData);
6438
- this.showPreview(container, theme, imageData, documentType, quality);
6621
+ this.showPreview(container, theme, imageData, documentType, quality, false);
6439
6622
  }
6440
6623
  validateFile(file) {
6441
6624
  const allowedTypes = ["image/jpeg", "image/jpg", "image/png"];
@@ -6456,63 +6639,30 @@ var SmartComplySDK = (() => {
6456
6639
  if (input) input.click();
6457
6640
  }
6458
6641
  stopCamera() {
6642
+ this._unwatchOrientation();
6459
6643
  this.cameraManager.stop();
6460
6644
  if (this.videoEl) {
6461
6645
  this.videoEl.srcObject = null;
6462
6646
  this.videoEl = null;
6463
6647
  }
6648
+ this.videoWrapEl = null;
6464
6649
  }
6465
6650
  showLoadingState(message, theme) {
6466
6651
  if (!this.root) return;
6467
6652
  this.root.innerHTML = "";
6468
6653
  this.root.style.cssText = "display:flex;flex-direction:column;align-items:center;justify-content:center;gap:20px;padding:40px 20px;min-height:300px;";
6469
- const spinnerContainer = document.createElement("div");
6470
- spinnerContainer.style.cssText = "position:relative;width:80px;height:80px;";
6471
- const spinner = document.createElement("div");
6472
- spinner.style.cssText = `
6473
- position:absolute;inset:0;border-radius:50%;
6474
- border:4px solid ${theme.border};
6475
- border-top-color:${theme.primary};
6476
- animation:sc-spin 1s linear infinite;
6477
- `;
6478
- spinnerContainer.appendChild(spinner);
6479
- const centerIcon = document.createElement("div");
6480
- centerIcon.style.cssText = `
6481
- position:absolute;inset:0;display:flex;align-items:center;justify-content:center;
6482
- font-size:28px;animation:pulse 2s ease-in-out infinite;
6483
- `;
6484
- centerIcon.textContent = "📄";
6485
- spinnerContainer.appendChild(centerIcon);
6486
- this.root.appendChild(spinnerContainer);
6654
+ this.root.appendChild(renderSpinner(theme, { size: 80, icon: icon("document", 28) }));
6487
6655
  const loadingText = document.createElement("div");
6488
- loadingText.style.cssText = `
6489
- color:${theme.text};font-size:16px;font-weight:600;text-align:center;
6490
- animation:fadeIn 0.5s ease-out;
6491
- `;
6656
+ loadingText.style.cssText = `color:${theme.text};font-size:${TYPE.heading}px;font-weight:600;text-align:center;`;
6492
6657
  loadingText.textContent = message;
6493
6658
  this.root.appendChild(loadingText);
6494
- if (!document.head.querySelector("style[data-pulse-animation]")) {
6495
- const style2 = document.createElement("style");
6496
- style2.setAttribute("data-pulse-animation", "true");
6497
- style2.textContent = `
6498
- @keyframes pulse {
6499
- 0%, 100% { transform: scale(1); opacity: 1; }
6500
- 50% { transform: scale(1.1); opacity: 0.8; }
6501
- }
6502
- @keyframes fadeIn {
6503
- from { opacity: 0; transform: translateY(10px); }
6504
- to { opacity: 1; transform: translateY(0); }
6505
- }
6506
- `;
6507
- document.head.appendChild(style2);
6508
- }
6509
6659
  }
6510
6660
  showError(message) {
6511
6661
  if (!this.root) return;
6512
6662
  const errorContainer = document.createElement("div");
6513
6663
  errorContainer.style.cssText = `
6514
6664
  display:flex;align-items:center;gap:12px;padding:16px;
6515
- background:#ff444415;border:1px solid #ff444430;border-radius:12px;
6665
+ background:#ff444415;border:1px solid #ff444430;border-radius:${RADIUS.md}px;
6516
6666
  color:#ff4444;font-size:14px;margin-top:16px;animation:shake 0.5s ease-in-out;
6517
6667
  `;
6518
6668
  errorContainer.innerHTML = `
@@ -6520,16 +6670,16 @@ var SmartComplySDK = (() => {
6520
6670
  <span>${message}</span>
6521
6671
  `;
6522
6672
  if (!document.head.querySelector("style[data-shake-animation]")) {
6523
- const style2 = document.createElement("style");
6524
- style2.setAttribute("data-shake-animation", "true");
6525
- style2.textContent = `
6673
+ const style = document.createElement("style");
6674
+ style.setAttribute("data-shake-animation", "true");
6675
+ style.textContent = `
6526
6676
  @keyframes shake {
6527
6677
  0%, 100% { transform: translateX(0); }
6528
6678
  25% { transform: translateX(-5px); }
6529
6679
  75% { transform: translateX(5px); }
6530
6680
  }
6531
6681
  `;
6532
- document.head.appendChild(style2);
6682
+ document.head.appendChild(style);
6533
6683
  }
6534
6684
  this.root.appendChild(errorContainer);
6535
6685
  setTimeout(() => errorContainer.remove(), 5e3);
@@ -6538,7 +6688,7 @@ var SmartComplySDK = (() => {
6538
6688
  const btn = document.createElement("button");
6539
6689
  btn.textContent = label;
6540
6690
  btn.style.cssText = `
6541
- padding:16px 24px;border-radius:12px;font-size:16px;font-weight:600;
6691
+ padding:16px 24px;border-radius:${RADIUS.md}px;font-size:16px;font-weight:600;
6542
6692
  cursor:pointer;transition:all 0.2s ease;border:none;width:100%;
6543
6693
  min-height:52px;touch-action:manipulation;-webkit-tap-highlight-color:transparent;
6544
6694
  ${isPrimary ? `background:${theme.primary};color:#fff;box-shadow:0 4px 12px ${theme.primary}30;` : `background:${theme.inputBg};color:${theme.text};border:2px solid ${theme.border};`}
@@ -6865,17 +7015,6 @@ var SmartComplySDK = (() => {
6865
7015
  if (map[key]) return map[key];
6866
7016
  return code.replace(/_/g, " ").replace(/\b\w/g, (c2) => c2.toUpperCase());
6867
7017
  }
6868
- var style = document.createElement("style");
6869
- style.textContent = `
6870
- @keyframes sc-spin {
6871
- 0% { transform: rotate(0deg); }
6872
- 100% { transform: rotate(360deg); }
6873
- }
6874
- `;
6875
- if (!document.head.querySelector("style[data-sc-animations]")) {
6876
- style.setAttribute("data-sc-animations", "true");
6877
- document.head.appendChild(style);
6878
- }
6879
7018
  var _SmartComplyFlow = class _SmartComplyFlow {
6880
7019
  constructor(options) {
6881
7020
  this.theme = getTheme("default");
@@ -6903,6 +7042,11 @@ var SmartComplySDK = (() => {
6903
7042
  this.idNumber = "";
6904
7043
  this.documentBlob = null;
6905
7044
  this.documentBackBlob = null;
7045
+ // Whether the document's front image came from the live camera vs. a
7046
+ // gallery/file upload — gates whether pre-warming the liveness camera on
7047
+ // the confirm screens makes sense (reusing an already-open camera) or
7048
+ // would surprise a user who hasn't touched their camera yet this session.
7049
+ this._documentViaCamera = false;
6906
7050
  this.identityCheckId = null;
6907
7051
  this.verificationResult = null;
6908
7052
  this.livenessEntryId = null;
@@ -7217,27 +7361,9 @@ var SmartComplySDK = (() => {
7217
7361
  // ── Loading ─────────────────────────────────────────────────────
7218
7362
  renderLoading(container) {
7219
7363
  container.style.cssText += "display:flex;flex-direction:column;align-items:center;justify-content:center;min-height:300px;gap:16px;";
7220
- const spinnerWrap = document.createElement("div");
7221
- spinnerWrap.style.cssText = "position:relative;width:60px;height:60px;flex-shrink:0;";
7222
- const ring = document.createElement("div");
7223
- ring.style.cssText = `
7224
- position:absolute;inset:0;border-radius:50%;
7225
- border:3px solid ${this.theme.border};
7226
- border-top-color:${this.theme.primary};
7227
- animation:sc-spin 0.9s linear infinite;
7228
- `;
7229
- const centre = document.createElement("div");
7230
- centre.style.cssText = `
7231
- position:absolute;inset:0;
7232
- display:flex;align-items:center;justify-content:center;
7233
- font-size:22px;
7234
- `;
7235
- centre.textContent = "🛡️";
7236
- spinnerWrap.appendChild(ring);
7237
- spinnerWrap.appendChild(centre);
7238
- container.appendChild(spinnerWrap);
7364
+ container.appendChild(renderSpinner(this.theme, { size: 60, icon: icon("shield", 22) }));
7239
7365
  const label = document.createElement("div");
7240
- label.style.cssText = `color:${this.theme.text};font-size:15px;font-weight:600;`;
7366
+ label.style.cssText = `color:${this.theme.text};font-size:${TYPE.base}px;font-weight:600;`;
7241
7367
  label.textContent = "Setting up secure session";
7242
7368
  container.appendChild(label);
7243
7369
  const sub = document.createElement("div");
@@ -7255,11 +7381,11 @@ var SmartComplySDK = (() => {
7255
7381
  iconWrap.style.cssText = `
7256
7382
  width:50px;height:50px;border-radius:14px;
7257
7383
  display:flex;align-items:center;justify-content:center;
7258
- font-size:22px;
7384
+ color:${this.theme.primary};
7259
7385
  background:linear-gradient(135deg,${this.theme.primary}22,${this.theme.primaryGlow});
7260
7386
  border:1.5px solid ${this.theme.primary}33;
7261
7387
  `;
7262
- iconWrap.textContent = isDocFlow ? "🪪" : "🛡️";
7388
+ iconWrap.innerHTML = icon(isDocFlow ? "id-card" : "shield", 24);
7263
7389
  topRow.appendChild(iconWrap);
7264
7390
  const badge = document.createElement("div");
7265
7391
  badge.style.cssText = `
@@ -7277,7 +7403,7 @@ var SmartComplySDK = (() => {
7277
7403
  titleWrap.style.cssText = "display:flex;flex-direction:column;gap:5px;";
7278
7404
  const title = document.createElement("h2");
7279
7405
  title.style.cssText = `
7280
- color:${this.theme.text};font-size:20px;font-weight:700;
7406
+ color:${this.theme.text};font-size:${TYPE.heading}px;font-weight:700;
7281
7407
  margin:0;line-height:1.2;
7282
7408
  `;
7283
7409
  const brandName = this.sdkConfig?.brand_name;
@@ -7303,7 +7429,7 @@ var SmartComplySDK = (() => {
7303
7429
  const stepsWrap = document.createElement("div");
7304
7430
  stepsWrap.style.cssText = `
7305
7431
  width:100%;display:flex;flex-direction:column;gap:0;
7306
- border-radius:12px;overflow:hidden;
7432
+ border-radius:${RADIUS.md}px;overflow:hidden;
7307
7433
  border:1.5px solid ${this.theme.border};
7308
7434
  `;
7309
7435
  steps.forEach((step, i2) => {
@@ -7316,7 +7442,7 @@ var SmartComplySDK = (() => {
7316
7442
  `;
7317
7443
  const iconEl = document.createElement("div");
7318
7444
  iconEl.style.cssText = `
7319
- width:28px;height:28px;border-radius:8px;flex-shrink:0;
7445
+ width:28px;height:28px;border-radius:${RADIUS.sm}px;flex-shrink:0;
7320
7446
  display:flex;align-items:center;justify-content:center;
7321
7447
  font-size:13px;
7322
7448
  background:${this.theme.primary}12;
@@ -7509,7 +7635,7 @@ var SmartComplySDK = (() => {
7509
7635
  if (field.type === "dropdown" || field.type === "select") {
7510
7636
  const select = document.createElement("select");
7511
7637
  select.style.cssText = `
7512
- width:100%;padding:13px 16px;border-radius:12px;
7638
+ width:100%;padding:13px 16px;border-radius:${RADIUS.md}px;
7513
7639
  font-size:15px;
7514
7640
  background:${this.theme.inputBg};
7515
7641
  color:${this.theme.text};
@@ -7546,7 +7672,7 @@ var SmartComplySDK = (() => {
7546
7672
  fileInput.type = "file";
7547
7673
  fileInput.accept = "image/*";
7548
7674
  fileInput.style.cssText = `
7549
- width:100%;padding:12px 16px;border-radius:12px;
7675
+ width:100%;padding:12px 16px;border-radius:${RADIUS.md}px;
7550
7676
  font-size:14px;font-weight:500;
7551
7677
  background:${this.theme.inputBg};
7552
7678
  color:${this.theme.text};
@@ -7587,7 +7713,7 @@ var SmartComplySDK = (() => {
7587
7713
  input.maxLength = rule?.maxLen ? rule.maxLen + 2 : 50;
7588
7714
  if (rule?.numeric) input.inputMode = "numeric";
7589
7715
  input.style.cssText = `
7590
- width:100%;padding:14px 16px;border-radius:12px;
7716
+ width:100%;padding:14px 16px;border-radius:${RADIUS.md}px;
7591
7717
  font-size:16px;font-weight:500;
7592
7718
  background:${this.theme.inputBg};
7593
7719
  color:${this.theme.text};
@@ -7644,7 +7770,7 @@ var SmartComplySDK = (() => {
7644
7770
  errorEl.id = "sc-id-error";
7645
7771
  errorEl.style.cssText = `
7646
7772
  color:${this.theme.error};font-size:13px;display:none;
7647
- padding:8px 12px;border-radius:8px;background:${this.theme.errorBg};
7773
+ padding:8px 12px;border-radius:${RADIUS.sm}px;background:${this.theme.errorBg};
7648
7774
  `;
7649
7775
  container.appendChild(errorEl);
7650
7776
  const submitBtn = this.createPrimaryButton("Verify & Continue");
@@ -7662,7 +7788,7 @@ var SmartComplySDK = (() => {
7662
7788
  };
7663
7789
  submitBtn.addEventListener("click", async () => {
7664
7790
  submitBtn.disabled = true;
7665
- submitBtn.innerHTML = `<span style="display:inline-flex;align-items:center;justify-content:center;gap:8px;"><span style="width:13px;height:13px;border-radius:50%;border:2px solid rgba(255,255,255,0.3);border-top-color:#fff;animation:sc-spin 0.6s linear infinite;display:inline-block;flex-shrink:0;"></span>Verifying...</span>`;
7791
+ submitBtn.innerHTML = `<span style="display:inline-flex;align-items:center;justify-content:center;gap:8px;">${renderInlineSpinner("#fff", 13)}Verifying...</span>`;
7666
7792
  errorEl.style.display = "none";
7667
7793
  try {
7668
7794
  this.verificationResult = await this.sdk.onboarding.verify({
@@ -7760,11 +7886,11 @@ var SmartComplySDK = (() => {
7760
7886
  }
7761
7887
  this._prewarmCamera();
7762
7888
  const iconWrap = document.createElement("div");
7763
- iconWrap.style.cssText = `width:64px;height:64px;border-radius:50%;background:${this.theme.primary}15;border:2px solid ${this.theme.primary}30;display:flex;align-items:center;justify-content:center;font-size:28px;`;
7764
- iconWrap.textContent = "🛡️";
7889
+ iconWrap.style.cssText = `width:64px;height:64px;border-radius:50%;background:${this.theme.primary}15;border:2px solid ${this.theme.primary}30;display:flex;align-items:center;justify-content:center;color:${this.theme.primary};`;
7890
+ iconWrap.innerHTML = icon("shield", 28);
7765
7891
  container.appendChild(iconWrap);
7766
7892
  const title = document.createElement("h2");
7767
- title.style.cssText = `color:${this.theme.text};font-size:18px;font-weight:700;margin:0;`;
7893
+ title.style.cssText = `color:${this.theme.text};font-size:${TYPE.heading}px;font-weight:700;margin:0;`;
7768
7894
  title.textContent = this._ivsName ? `Is this you?` : "Identity Confirmed";
7769
7895
  container.appendChild(title);
7770
7896
  if (this._ivsName) {
@@ -7822,13 +7948,22 @@ var SmartComplySDK = (() => {
7822
7948
  this._renderRetryLimitReached(container);
7823
7949
  return;
7824
7950
  }
7825
- this._prewarmCamera();
7951
+ if (this._documentViaCamera) this._prewarmCamera();
7952
+ const stepBadge = document.createElement("div");
7953
+ stepBadge.style.cssText = `
7954
+ display:inline-flex;align-items:center;gap:5px;
7955
+ padding:3px 11px;border-radius:${RADIUS.pill}px;
7956
+ font-size:10.5px;font-weight:600;letter-spacing:0.2px;
7957
+ color:${this.theme.primary};background:${this.theme.primary}15;border:1px solid ${this.theme.primary}30;
7958
+ `;
7959
+ stepBadge.textContent = "STEP 2 OF 2 · CHECK WHAT WE READ";
7960
+ container.appendChild(stepBadge);
7826
7961
  const iconWrap = document.createElement("div");
7827
- iconWrap.style.cssText = `width:64px;height:64px;border-radius:50%;background:${this.theme.primary}15;border:2px solid ${this.theme.primary}30;display:flex;align-items:center;justify-content:center;font-size:28px;`;
7828
- iconWrap.textContent = "📄";
7962
+ iconWrap.style.cssText = `width:64px;height:64px;border-radius:50%;background:${this.theme.primary}15;border:2px solid ${this.theme.primary}30;display:flex;align-items:center;justify-content:center;color:${this.theme.primary};`;
7963
+ iconWrap.innerHTML = icon("document", 28);
7829
7964
  container.appendChild(iconWrap);
7830
7965
  const title = document.createElement("h2");
7831
- title.style.cssText = `color:${this.theme.text};font-size:18px;font-weight:700;margin:0;`;
7966
+ title.style.cssText = `color:${this.theme.text};font-size:${TYPE.heading}px;font-weight:700;margin:0;`;
7832
7967
  title.textContent = "Are these your details?";
7833
7968
  container.appendChild(title);
7834
7969
  const sub = document.createElement("p");
@@ -7906,19 +8041,10 @@ var SmartComplySDK = (() => {
7906
8041
  // ── W6+W7+W8: OCR Gate (document verification) ───────────────────
7907
8042
  renderOcrGate(container) {
7908
8043
  container.style.cssText += "display:flex;flex-direction:column;align-items:center;gap:14px;padding:20px 0;text-align:center;";
7909
- const spinnerWrap = document.createElement("div");
7910
- spinnerWrap.style.cssText = "position:relative;width:52px;height:52px;flex-shrink:0;";
7911
- const ring = document.createElement("div");
7912
- ring.style.cssText = `position:absolute;inset:0;border-radius:50%;border:3px solid ${this.theme.border};border-top-color:${this.theme.primary};animation:sc-spin 0.9s linear infinite;`;
7913
- const centre = document.createElement("div");
7914
- centre.style.cssText = "position:absolute;inset:0;display:flex;align-items:center;justify-content:center;font-size:20px;";
7915
- centre.textContent = "📄";
7916
- spinnerWrap.appendChild(ring);
7917
- spinnerWrap.appendChild(centre);
7918
- container.appendChild(spinnerWrap);
8044
+ container.appendChild(renderSpinner(this.theme, { size: 52, icon: icon("document", 20) }));
7919
8045
  const statusEl = document.createElement("div");
7920
8046
  statusEl.setAttribute("aria-live", "polite");
7921
- statusEl.style.cssText = `color:${this.theme.text};font-size:15px;font-weight:600;`;
8047
+ statusEl.style.cssText = `color:${this.theme.text};font-size:${TYPE.base}px;font-weight:600;`;
7922
8048
  statusEl.textContent = "Reading your document…";
7923
8049
  container.appendChild(statusEl);
7924
8050
  const subEl = document.createElement("div");
@@ -7990,12 +8116,12 @@ var SmartComplySDK = (() => {
7990
8116
  }
7991
8117
  _renderExpiredDocument(container) {
7992
8118
  container.style.cssText += "display:flex;flex-direction:column;align-items:center;text-align:center;gap:14px;padding:20px 0;";
7993
- const icon = document.createElement("div");
7994
- icon.style.cssText = `width:72px;height:72px;border-radius:50%;background:${this.theme.errorBg};border:3px solid ${this.theme.error};display:flex;align-items:center;justify-content:center;font-size:28px;`;
7995
- icon.textContent = "📅";
7996
- container.appendChild(icon);
8119
+ const icon2 = document.createElement("div");
8120
+ icon2.style.cssText = `width:72px;height:72px;border-radius:50%;background:${this.theme.errorBg};border:3px solid ${this.theme.error};display:flex;align-items:center;justify-content:center;font-size:28px;`;
8121
+ icon2.textContent = "📅";
8122
+ container.appendChild(icon2);
7997
8123
  const t2 = document.createElement("h2");
7998
- t2.style.cssText = `color:${this.theme.text};font-size:18px;font-weight:700;margin:0;`;
8124
+ t2.style.cssText = `color:${this.theme.text};font-size:${TYPE.heading}px;font-weight:700;margin:0;`;
7999
8125
  t2.textContent = "Document Expired";
8000
8126
  container.appendChild(t2);
8001
8127
  const d2 = document.createElement("p");
@@ -8019,12 +8145,12 @@ var SmartComplySDK = (() => {
8019
8145
  }
8020
8146
  _renderOcrQualityFail(container, reason) {
8021
8147
  container.style.cssText += "display:flex;flex-direction:column;align-items:center;text-align:center;gap:14px;padding:20px 0;";
8022
- const icon = document.createElement("div");
8023
- icon.style.cssText = `width:72px;height:72px;border-radius:50%;background:${this.theme.errorBg};border:3px solid ${this.theme.error};display:flex;align-items:center;justify-content:center;font-size:28px;`;
8024
- icon.textContent = "🔍";
8025
- container.appendChild(icon);
8148
+ const icon2 = document.createElement("div");
8149
+ icon2.style.cssText = `width:72px;height:72px;border-radius:50%;background:${this.theme.errorBg};border:3px solid ${this.theme.error};display:flex;align-items:center;justify-content:center;font-size:28px;`;
8150
+ icon2.textContent = "🔍";
8151
+ container.appendChild(icon2);
8026
8152
  const t2 = document.createElement("h2");
8027
- t2.style.cssText = `color:${this.theme.text};font-size:18px;font-weight:700;margin:0;`;
8153
+ t2.style.cssText = `color:${this.theme.text};font-size:${TYPE.heading}px;font-weight:700;margin:0;`;
8028
8154
  t2.textContent = "Document Photo Unclear";
8029
8155
  container.appendChild(t2);
8030
8156
  const msg = reason === "image_too_blurry" ? "Your document photo is too blurry. Please retake it in good lighting with a steady hand." : reason === "image_too_dark" ? "Your document photo is too dark. Please retake it in better lighting." : reason === "image_too_bright" ? "Your document photo has too much glare. Please reduce reflections and retake." : reason === "document_not_detected" ? "We could not detect a document in the photo. Please ensure the full ID is visible." : "We could not read your document clearly. Please retake the photo in good lighting with no glare.";
@@ -8053,11 +8179,11 @@ var SmartComplySDK = (() => {
8053
8179
  verificationResult: this.verificationResult || void 0
8054
8180
  });
8055
8181
  const iconWrap = document.createElement("div");
8056
- iconWrap.style.cssText = `width:80px;height:80px;border-radius:50%;background:${this.theme.successBg};border:3px solid ${this.theme.success};display:flex;align-items:center;justify-content:center;font-size:36px;font-weight:700;color:${this.theme.success};animation:sc-pop 0.4s ease;`;
8057
- iconWrap.textContent = "✓";
8182
+ iconWrap.style.cssText = `width:80px;height:80px;border-radius:50%;background:${this.theme.successBg};border:3px solid ${this.theme.success};display:flex;align-items:center;justify-content:center;color:${this.theme.success};animation:sc-pop 0.4s ease;`;
8183
+ iconWrap.innerHTML = icon("check", 36);
8058
8184
  container.appendChild(iconWrap);
8059
8185
  const title = document.createElement("h2");
8060
- title.style.cssText = `color:${this.theme.text};font-size:22px;font-weight:700;margin:0;`;
8186
+ title.style.cssText = `color:${this.theme.text};font-size:${TYPE.headingLg}px;font-weight:700;margin:0;`;
8061
8187
  title.textContent = "You're all done!";
8062
8188
  container.appendChild(title);
8063
8189
  const desc = document.createElement("p");
@@ -8077,12 +8203,12 @@ var SmartComplySDK = (() => {
8077
8203
  // ── W14: Retry limit reached ─────────────────────────────────────
8078
8204
  _renderRetryLimitReached(container) {
8079
8205
  container.style.cssText += "display:flex;flex-direction:column;align-items:center;text-align:center;gap:14px;padding:24px 0;";
8080
- const icon = document.createElement("div");
8081
- icon.style.cssText = `width:72px;height:72px;border-radius:50%;background:${this.theme.errorBg};border:3px solid ${this.theme.error};display:flex;align-items:center;justify-content:center;font-size:28px;`;
8082
- icon.textContent = "⚠️";
8083
- container.appendChild(icon);
8206
+ const icon2 = document.createElement("div");
8207
+ icon2.style.cssText = `width:72px;height:72px;border-radius:50%;background:${this.theme.errorBg};border:3px solid ${this.theme.error};display:flex;align-items:center;justify-content:center;font-size:28px;`;
8208
+ icon2.textContent = "⚠️";
8209
+ container.appendChild(icon2);
8084
8210
  const t2 = document.createElement("h2");
8085
- t2.style.cssText = `color:${this.theme.text};font-size:18px;font-weight:700;margin:0;`;
8211
+ t2.style.cssText = `color:${this.theme.text};font-size:${TYPE.heading}px;font-weight:700;margin:0;`;
8086
8212
  t2.textContent = "Unable to Complete Verification";
8087
8213
  container.appendChild(t2);
8088
8214
  const d2 = document.createElement("p");
@@ -8114,6 +8240,7 @@ var SmartComplySDK = (() => {
8114
8240
  async processDocumentCaptureResult(result, captureContainer, container) {
8115
8241
  this.documentBlob = await _compressImage(result.front, 1600, 0.85);
8116
8242
  this.documentBackBlob = result.back ? await _compressImage(result.back, 1600, 0.85) : null;
8243
+ this._documentViaCamera = result.viaCamera;
8117
8244
  await this.processDocumentBlob(this.documentBlob, captureContainer, container);
8118
8245
  }
8119
8246
  /**
@@ -8131,15 +8258,12 @@ var SmartComplySDK = (() => {
8131
8258
  throw new Error("Document image is too large. Please retake in better lighting or use a clearer photo.");
8132
8259
  }
8133
8260
  this.documentBlob = blob;
8134
- captureContainer.innerHTML = `
8135
- <div style="display:flex;flex-direction:column;align-items:center;gap:14px;padding:28px 20px;">
8136
- <div style="position:relative;width:52px;height:52px;">
8137
- <div style="position:absolute;inset:0;border-radius:50%;border:3px solid ${this.theme.border};border-top-color:${this.theme.primary};animation:sc-spin 0.8s linear infinite;"></div>
8138
- <div style="position:absolute;inset:0;display:flex;align-items:center;justify-content:center;font-size:20px;">🔍</div>
8139
- </div>
8261
+ captureContainer.innerHTML = "";
8262
+ captureContainer.style.cssText += "display:flex;flex-direction:column;align-items:center;gap:14px;padding:28px 20px;";
8263
+ captureContainer.appendChild(renderSpinner(this.theme, { size: 52, icon: icon("search", 20) }));
8264
+ captureContainer.insertAdjacentHTML("beforeend", `
8140
8265
  <div style="color:${this.theme.text};font-size:14px;font-weight:600;">Scanning document...</div>
8141
- <div style="color:${this.theme.textSecondary};font-size:12px;text-align:center;max-width:200px;line-height:1.5;">Running OCR and verifying your identity</div>
8142
- </div>`;
8266
+ <div style="color:${this.theme.textSecondary};font-size:12px;text-align:center;max-width:200px;line-height:1.5;">Running OCR and verifying your identity</div>`);
8143
8267
  const identifier = Object.values(this.collectedFields)[0] || this.idNumber || this.selectedIdType || `DOC-${Date.now()}`;
8144
8268
  const COUNTRY_CODES = {
8145
8269
  nigeria: "NG",
@@ -8189,15 +8313,12 @@ var SmartComplySDK = (() => {
8189
8313
  retryCount++;
8190
8314
  console.log(`Retrying document processing (attempt ${retryCount}/${maxRetries})`);
8191
8315
  if (captureContainer) {
8192
- captureContainer.innerHTML = `
8193
- <div style="display:flex;flex-direction:column;align-items:center;gap:16px;padding:28px 20px;text-align:center;">
8194
- <div style="position:relative;width:52px;height:52px;">
8195
- <div style="position:absolute;inset:0;border-radius:50%;border:3px solid ${this.theme.border};border-top-color:${this.theme.primary};animation:sc-spin 0.8s linear infinite;"></div>
8196
- <div style="position:absolute;inset:0;display:flex;align-items:center;justify-content:center;font-size:20px;">🔄</div>
8197
- </div>
8316
+ captureContainer.innerHTML = "";
8317
+ captureContainer.style.cssText += "display:flex;flex-direction:column;align-items:center;gap:16px;padding:28px 20px;text-align:center;";
8318
+ captureContainer.appendChild(renderSpinner(this.theme, { size: 52, icon: icon("refresh", 20) }));
8319
+ captureContainer.insertAdjacentHTML("beforeend", `
8198
8320
  <div style="color:${this.theme.text};font-size:14px;font-weight:600;">Retrying...</div>
8199
- <div style="color:${this.theme.textSecondary};font-size:12px;max-width:240px;line-height:1.5;">Attempt ${retryCount} of ${maxRetries}</div>
8200
- </div>`;
8321
+ <div style="color:${this.theme.textSecondary};font-size:12px;max-width:240px;line-height:1.5;">Attempt ${retryCount} of ${maxRetries}</div>`);
8201
8322
  }
8202
8323
  await new Promise((resolve) => setTimeout(resolve, 2e3));
8203
8324
  return attemptProcessing();
@@ -8232,10 +8353,10 @@ var SmartComplySDK = (() => {
8232
8353
  const wrap = document.createElement("div");
8233
8354
  wrap.style.cssText = "display:flex;flex-direction:column;align-items:center;gap:16px;padding:28px 20px;text-align:center;";
8234
8355
  wrap.setAttribute("role", "alert");
8235
- const icon = document.createElement("div");
8236
- icon.style.cssText = `width:56px;height:56px;border-radius:50%;background:${this.theme.errorBg};border:3px solid ${this.theme.error};display:flex;align-items:center;justify-content:center;font-size:26px;`;
8237
- icon.textContent = "🔍";
8238
- wrap.appendChild(icon);
8356
+ const icon2 = document.createElement("div");
8357
+ icon2.style.cssText = `width:56px;height:56px;border-radius:50%;background:${this.theme.errorBg};border:3px solid ${this.theme.error};display:flex;align-items:center;justify-content:center;font-size:26px;`;
8358
+ icon2.textContent = "🔍";
8359
+ wrap.appendChild(icon2);
8239
8360
  const titleEl = document.createElement("div");
8240
8361
  titleEl.style.cssText = `color:${this.theme.text};font-size:14px;font-weight:700;`;
8241
8362
  titleEl.textContent = "Document Could Not Be Verified";
@@ -8248,7 +8369,7 @@ var SmartComplySDK = (() => {
8248
8369
  const retryBtn = document.createElement("button");
8249
8370
  retryBtn.textContent = "Try Again";
8250
8371
  retryBtn.setAttribute("aria-label", "Retake document photo");
8251
- retryBtn.style.cssText = `margin-top:8px;padding:12px 24px;border-radius:8px;background:${this.theme.primary};color:#fff;border:none;font-size:14px;font-weight:600;cursor:pointer;`;
8372
+ retryBtn.style.cssText = `margin-top:8px;padding:12px 24px;border-radius:${RADIUS.sm}px;background:${this.theme.primary};color:#fff;border:none;font-size:14px;font-weight:600;cursor:pointer;`;
8252
8373
  retryBtn.addEventListener("click", () => this.showStep("document_capture"));
8253
8374
  wrap.appendChild(retryBtn);
8254
8375
  }
@@ -8298,7 +8419,13 @@ var SmartComplySDK = (() => {
8298
8419
  identity_check: this.identityCheckId || void 0,
8299
8420
  verification_type: this.identityCheckId ? "data_verification" : this.documentBlob ? "document_verification" : "liveness_only",
8300
8421
  // B4: pass pre-warmed stream so camera.open() is skipped
8301
- prewarmedStream: this._prewarmedStream || void 0
8422
+ prewarmedStream: this._prewarmedStream || void 0,
8423
+ colors: {
8424
+ primary: this.theme.primary,
8425
+ success: this.theme.success,
8426
+ error: this.theme.error,
8427
+ warning: this.theme.warning
8428
+ }
8302
8429
  },
8303
8430
  ["BLINK"],
8304
8431
  this.livenessEntryId || void 0
@@ -8333,21 +8460,21 @@ var SmartComplySDK = (() => {
8333
8460
  const isExpiredDoc = /document.*expired|expired.*document/i.test(message);
8334
8461
  const isFaceMatch = /face.*match|selfie.*match|does not match/i.test(message);
8335
8462
  const isBillingErr = /wallet|balance|insufficient.*fund|payment.*required/i.test(message);
8336
- const errorIcon = isCameraErr ? "📷" : isNetworkErr ? "📡" : isAuthErr ? "⏱" : isDocQuality ? "🔍" : isExpiredDoc ? "📅" : isFaceMatch ? "🤳" : isBillingErr ? "⚠️" : "✕";
8463
+ const errorIconName = isCameraErr ? "camera" : isNetworkErr ? "network" : isAuthErr ? "clock" : isDocQuality ? "search" : isExpiredDoc ? "calendar" : isFaceMatch ? "face" : isBillingErr ? "warning" : "close";
8337
8464
  const errorTitle = isCameraErr ? "Camera Access Required" : isNetworkErr ? "Connection Problem" : isAuthErr ? "Session Expired" : isDocQuality ? "Document Photo Unclear" : isExpiredDoc ? "Document Expired" : isFaceMatch ? "Face Match Failed" : isBillingErr ? "Verification Unavailable" : "Verification Unsuccessful";
8338
8465
  const userMessage = isCameraErr ? "Please allow camera access in your browser settings and try again." : isNetworkErr ? "Check your internet connection and try again." : isAuthErr ? "Your session has expired. Please start again." : isDocQuality ? _sanitizeUserMessage(message) || "Please retake your document photo in good lighting with no glare." : isExpiredDoc ? "The document you submitted has expired. Please use a valid, current ID." : isFaceMatch ? "Your selfie did not match the photo on your ID. Please ensure you are using your own valid document and face the camera directly." : isBillingErr ? "Verification is temporarily unavailable. Please contact support." : _sanitizeUserMessage(message) || "We were unable to complete your verification. Please try again.";
8339
8466
  const iconWrap = document.createElement("div");
8340
8467
  iconWrap.style.cssText = `
8341
8468
  width:72px;height:72px;border-radius:50%;
8342
8469
  display:flex;align-items:center;justify-content:center;
8343
- font-size:28px;
8470
+ color:${this.theme.error};
8344
8471
  background:${this.theme.errorBg};
8345
8472
  border:3px solid ${this.theme.error};
8346
8473
  `;
8347
- iconWrap.textContent = errorIcon;
8474
+ iconWrap.innerHTML = icon(errorIconName, 28);
8348
8475
  wrapper.appendChild(iconWrap);
8349
8476
  const title = document.createElement("h2");
8350
- title.style.cssText = `color:${this.theme.text};font-size:18px;font-weight:700;margin:0;`;
8477
+ title.style.cssText = `color:${this.theme.text};font-size:${TYPE.heading}px;font-weight:700;margin:0;`;
8351
8478
  title.textContent = errorTitle;
8352
8479
  wrapper.appendChild(title);
8353
8480
  const desc = document.createElement("p");
@@ -8385,7 +8512,7 @@ var SmartComplySDK = (() => {
8385
8512
  this.headerBackBtn.innerHTML = "&#8592;";
8386
8513
  this.headerBackBtn.setAttribute("aria-label", "Go back to previous step");
8387
8514
  this.headerBackBtn.style.cssText = `
8388
- width:30px;height:30px;border-radius:8px;flex-shrink:0;
8515
+ width:30px;height:30px;border-radius:${RADIUS.sm}px;flex-shrink:0;
8389
8516
  display:none;align-items:center;justify-content:center;
8390
8517
  border:1.5px solid ${this.theme.border};cursor:pointer;
8391
8518
  font-size:16px;line-height:1;
@@ -8441,7 +8568,7 @@ var SmartComplySDK = (() => {
8441
8568
  closeBtn.innerHTML = "✕";
8442
8569
  closeBtn.setAttribute("aria-label", "Close identity verification");
8443
8570
  closeBtn.style.cssText = `
8444
- width:32px;height:32px;border-radius:8px;flex-shrink:0;
8571
+ width:32px;height:32px;border-radius:${RADIUS.sm}px;flex-shrink:0;
8445
8572
  display:flex;align-items:center;justify-content:center;
8446
8573
  border:none;cursor:pointer;font-size:16px;
8447
8574
  background:${this.theme.shimmer};color:${this.theme.textMuted};
@@ -8478,7 +8605,7 @@ var SmartComplySDK = (() => {
8478
8605
  createStepTitle(text) {
8479
8606
  const el = document.createElement("h3");
8480
8607
  el.style.cssText = `
8481
- color:${this.theme.text};font-size:18px;font-weight:700;
8608
+ color:${this.theme.text};font-size:${TYPE.heading}px;font-weight:700;
8482
8609
  margin:0;
8483
8610
  `;
8484
8611
  el.textContent = text;
@@ -8488,7 +8615,7 @@ var SmartComplySDK = (() => {
8488
8615
  const card = document.createElement("button");
8489
8616
  card.setAttribute("aria-label", subtitle ? `${title}: ${subtitle}` : title);
8490
8617
  card.style.cssText = `
8491
- width:100%;padding:13px 16px;border-radius:12px;
8618
+ width:100%;padding:13px 16px;border-radius:${RADIUS.md}px;
8492
8619
  background:${this.theme.cardBg};
8493
8620
  border:2px solid ${this.theme.border};
8494
8621
  cursor:pointer;text-align:left;
@@ -8528,7 +8655,7 @@ var SmartComplySDK = (() => {
8528
8655
  const btn = document.createElement("button");
8529
8656
  btn.textContent = text;
8530
8657
  btn.style.cssText = `
8531
- width:100%;padding:14px;border-radius:12px;
8658
+ width:100%;padding:14px;border-radius:${RADIUS.md}px;
8532
8659
  font-size:15px;font-weight:600;
8533
8660
  background:${this.theme.primary};color:#fff;
8534
8661
  border:none;cursor:pointer;
@@ -8549,7 +8676,7 @@ var SmartComplySDK = (() => {
8549
8676
  const btn = document.createElement("button");
8550
8677
  btn.textContent = text;
8551
8678
  btn.style.cssText = `
8552
- width:100%;padding:12px;border-radius:12px;
8679
+ width:100%;padding:12px;border-radius:${RADIUS.md}px;
8553
8680
  font-size:14px;font-weight:500;
8554
8681
  background:transparent;color:${this.theme.textSecondary};
8555
8682
  border:none;cursor:pointer;
@@ -8665,12 +8792,9 @@ var SmartComplySDK = (() => {
8665
8792
  }
8666
8793
  injectStyles() {
8667
8794
  if (document.getElementById("sc-flow-styles")) return;
8668
- const style2 = document.createElement("style");
8669
- style2.id = "sc-flow-styles";
8670
- style2.textContent = `
8671
- @keyframes sc-spin {
8672
- to { transform: rotate(360deg); }
8673
- }
8795
+ const style = document.createElement("style");
8796
+ style.id = "sc-flow-styles";
8797
+ style.textContent = `
8674
8798
  @keyframes sc-pop {
8675
8799
  0% { transform: scale(0.8); opacity: 0; }
8676
8800
  50% { transform: scale(1.05); }
@@ -8696,7 +8820,7 @@ var SmartComplySDK = (() => {
8696
8820
  border-radius: 4px;
8697
8821
  }
8698
8822
  `;
8699
- document.head.appendChild(style2);
8823
+ document.head.appendChild(style);
8700
8824
  }
8701
8825
  };
8702
8826
  _SmartComplyFlow.MAX_RETRIES = 3;