smartcomply-web-sdk 1.0.62 → 1.0.63

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 (57) hide show
  1. package/dist/esm/flow/DocumentCapture.d.ts +19 -1
  2. package/dist/esm/flow/DocumentCapture.d.ts.map +1 -1
  3. package/dist/esm/flow/DocumentCapture.js +144 -77
  4. package/dist/esm/flow/DocumentCapture.js.map +1 -1
  5. package/dist/esm/flow/SmartComplyFlow.d.ts.map +1 -1
  6. package/dist/esm/flow/SmartComplyFlow.js +76 -103
  7. package/dist/esm/flow/SmartComplyFlow.js.map +1 -1
  8. package/dist/esm/flow/icons.d.ts +14 -0
  9. package/dist/esm/flow/icons.d.ts.map +1 -0
  10. package/dist/esm/flow/icons.js +34 -0
  11. package/dist/esm/flow/icons.js.map +1 -0
  12. package/dist/esm/flow/spinner.d.ts +15 -0
  13. package/dist/esm/flow/spinner.d.ts.map +1 -0
  14. package/dist/esm/flow/spinner.js +55 -0
  15. package/dist/esm/flow/spinner.js.map +1 -0
  16. package/dist/esm/flow/theme.d.ts +19 -0
  17. package/dist/esm/flow/theme.d.ts.map +1 -1
  18. package/dist/esm/flow/theme.js +19 -0
  19. package/dist/esm/flow/theme.js.map +1 -1
  20. package/dist/esm/modules/liveness/LivenessUI.d.ts +10 -0
  21. package/dist/esm/modules/liveness/LivenessUI.d.ts.map +1 -1
  22. package/dist/esm/modules/liveness/LivenessUI.js +17 -16
  23. package/dist/esm/modules/liveness/LivenessUI.js.map +1 -1
  24. package/dist/esm/modules/liveness/liveness.d.ts +2 -0
  25. package/dist/esm/modules/liveness/liveness.d.ts.map +1 -1
  26. package/dist/esm/modules/liveness/liveness.js +1 -1
  27. package/dist/esm/modules/liveness/liveness.js.map +1 -1
  28. package/dist/flow/DocumentCapture.d.ts +19 -1
  29. package/dist/flow/DocumentCapture.d.ts.map +1 -1
  30. package/dist/flow/DocumentCapture.js +144 -77
  31. package/dist/flow/DocumentCapture.js.map +1 -1
  32. package/dist/flow/SmartComplyFlow.d.ts.map +1 -1
  33. package/dist/flow/SmartComplyFlow.js +75 -102
  34. package/dist/flow/SmartComplyFlow.js.map +1 -1
  35. package/dist/flow/icons.d.ts +14 -0
  36. package/dist/flow/icons.d.ts.map +1 -0
  37. package/dist/flow/icons.js +37 -0
  38. package/dist/flow/icons.js.map +1 -0
  39. package/dist/flow/spinner.d.ts +15 -0
  40. package/dist/flow/spinner.d.ts.map +1 -0
  41. package/dist/flow/spinner.js +59 -0
  42. package/dist/flow/spinner.js.map +1 -0
  43. package/dist/flow/theme.d.ts +19 -0
  44. package/dist/flow/theme.d.ts.map +1 -1
  45. package/dist/flow/theme.js +20 -1
  46. package/dist/flow/theme.js.map +1 -1
  47. package/dist/modules/liveness/LivenessUI.d.ts +10 -0
  48. package/dist/modules/liveness/LivenessUI.d.ts.map +1 -1
  49. package/dist/modules/liveness/LivenessUI.js +17 -16
  50. package/dist/modules/liveness/LivenessUI.js.map +1 -1
  51. package/dist/modules/liveness/liveness.d.ts +2 -0
  52. package/dist/modules/liveness/liveness.d.ts.map +1 -1
  53. package/dist/modules/liveness/liveness.js +1 -1
  54. package/dist/modules/liveness/liveness.js.map +1 -1
  55. package/dist/smartcomply.browser.js +316 -202
  56. package/dist/smartcomply.browser.js.map +4 -4
  57. 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,12 +5974,87 @@ 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;
5964
6060
  this.frontBlob = null;
@@ -6034,14 +6130,14 @@ var SmartComplySDK = (() => {
6034
6130
  iconBox.style.cssText = `
6035
6131
  width:48px;height:48px;border-radius:14px;flex-shrink:0;
6036
6132
  display:flex;align-items:center;justify-content:center;
6037
- font-size:24px;
6133
+ color:${theme.primary};
6038
6134
  background:${theme.primary}15;
6039
6135
  border:1.5px solid ${theme.primary}30;
6040
6136
  `;
6041
- iconBox.textContent = this._docIcon(documentType);
6137
+ iconBox.innerHTML = icon(this._docIcon(documentType), 22);
6042
6138
  const titleBlock = document.createElement("div");
6043
6139
  const titleEl = document.createElement("div");
6044
- titleEl.style.cssText = `color:${theme.text};font-size:16px;font-weight:700;line-height:1.3;`;
6140
+ titleEl.style.cssText = `color:${theme.text};font-size:${TYPE.headingSm}px;font-weight:700;line-height:1.3;`;
6045
6141
  titleEl.textContent = `Capture your ${docLabel}`;
6046
6142
  const subEl = document.createElement("div");
6047
6143
  subEl.style.cssText = `color:${theme.textSecondary};font-size:12px;margin-top:2px;`;
@@ -6066,7 +6162,7 @@ var SmartComplySDK = (() => {
6066
6162
  transition:all 0.15s ease;min-height:80px;
6067
6163
  box-shadow:0 4px 14px ${theme.primary}30;
6068
6164
  `;
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>`;
6165
+ 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
6166
  cameraBtn.addEventListener("mouseenter", () => {
6071
6167
  cameraBtn.style.opacity = "0.9";
6072
6168
  cameraBtn.style.transform = "translateY(-1px)";
@@ -6088,7 +6184,7 @@ var SmartComplySDK = (() => {
6088
6184
  font-size:13px;font-weight:600;font-family:inherit;
6089
6185
  transition:all 0.15s ease;min-height:80px;
6090
6186
  `;
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>`;
6187
+ 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
6188
  uploadBtn.addEventListener("mouseenter", () => {
6093
6189
  uploadBtn.style.borderColor = theme.primary;
6094
6190
  uploadBtn.style.transform = "translateY(-1px)";
@@ -6107,7 +6203,7 @@ var SmartComplySDK = (() => {
6107
6203
  tips.style.cssText = `
6108
6204
  margin:0 20px 16px;padding:12px 14px;
6109
6205
  background:${theme.shimmer || theme.cardBg};
6110
- border:1px solid ${theme.border};border-radius:12px;
6206
+ border:1px solid ${theme.border};border-radius:${RADIUS.md}px;
6111
6207
  `;
6112
6208
  const tipsGrid = document.createElement("div");
6113
6209
  tipsGrid.style.cssText = `
@@ -6122,7 +6218,7 @@ var SmartComplySDK = (() => {
6122
6218
  tipItems.forEach((t2) => {
6123
6219
  const row = document.createElement("div");
6124
6220
  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>`;
6221
+ row.innerHTML = `<span style="color:${theme.primary};flex-shrink:0;display:inline-flex;">${icon("check", 12)}</span><span>${t2}</span>`;
6126
6222
  tipsGrid.appendChild(row);
6127
6223
  });
6128
6224
  tips.appendChild(tipsGrid);
@@ -6159,45 +6255,84 @@ var SmartComplySDK = (() => {
6159
6255
  this.root.appendChild(fileInput);
6160
6256
  container.appendChild(this.root);
6161
6257
  }
6162
- /** Returns an appropriate emoji icon for the document type. */
6258
+ /** Returns the icon name matching the document type. */
6163
6259
  _docIcon(documentType) {
6164
6260
  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 "🪪";
6261
+ if (t2.includes("passport")) return "passport";
6262
+ if (t2.includes("driver") || t2.includes("licen")) return "car";
6263
+ if (t2.includes("voter") || t2.includes("pvc")) return "ballot";
6264
+ return "id-card";
6169
6265
  }
6170
6266
  renderCameraView(container, theme, documentType) {
6171
6267
  const wrapper = document.createElement("div");
6172
- wrapper.style.cssText = "position:relative;width:100%;border-radius:12px;overflow:hidden;background:#000;";
6268
+ wrapper.style.cssText = `
6269
+ position:relative;width:100%;max-width:420px;margin:0 auto;
6270
+ background:#0a0a0a;border-radius:${RADIUS.lg}px;overflow:hidden;
6271
+ box-shadow:0 8px 32px rgba(0,0,0,0.4);
6272
+ `;
6273
+ this.videoWrapEl = wrapper;
6173
6274
  this.videoEl = document.createElement("video");
6174
6275
  this.videoEl.autoplay = true;
6175
6276
  this.videoEl.playsInline = true;
6176
6277
  this.videoEl.muted = true;
6177
6278
  this.videoEl.style.cssText = "width:100%;display:block;aspect-ratio:4/3;object-fit:cover;";
6178
6279
  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;
6280
+ const vignette = document.createElement("div");
6281
+ vignette.style.cssText = `
6282
+ position:absolute;inset:0;pointer-events:none;
6283
+ box-shadow:inset 0 0 0 9999px rgba(0,0,0,0.38);
6284
+ -webkit-mask:radial-gradient(ellipse 46% 34% at 50% 50%, transparent 60%, #000 100%);
6285
+ mask:radial-gradient(ellipse 46% 34% at 50% 50%, transparent 60%, #000 100%);
6183
6286
  `;
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);
6287
+ wrapper.appendChild(vignette);
6288
+ const guideWrap = document.createElement("div");
6289
+ guideWrap.style.cssText = `
6290
+ position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);
6291
+ width:84%;aspect-ratio:16/10;pointer-events:none;
6292
+ `;
6293
+ const svg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
6294
+ svg.setAttribute("viewBox", "0 0 160 100");
6295
+ svg.style.cssText = "width:100%;height:100%;overflow:visible;";
6296
+ const bracketGroup = document.createElementNS("http://www.w3.org/2000/svg", "g");
6297
+ bracketGroup.setAttribute("stroke", theme.primary);
6298
+ bracketGroup.setAttribute("stroke-width", "3");
6299
+ bracketGroup.setAttribute("stroke-linecap", "round");
6300
+ bracketGroup.setAttribute("fill", "none");
6301
+ const bLen = 16;
6302
+ const bx0 = 4, bx1 = 156, by0 = 4, by1 = 96;
6303
+ const brackets = [
6304
+ `M${bx0},${by0 + bLen} L${bx0},${by0} L${bx0 + bLen},${by0}`,
6305
+ `M${bx1 - bLen},${by0} L${bx1},${by0} L${bx1},${by0 + bLen}`,
6306
+ `M${bx0},${by1 - bLen} L${bx0},${by1} L${bx0 + bLen},${by1}`,
6307
+ `M${bx1 - bLen},${by1} L${bx1},${by1} L${bx1},${by1 - bLen}`
6308
+ ];
6309
+ for (const d2 of brackets) {
6310
+ const path = document.createElementNS("http://www.w3.org/2000/svg", "path");
6311
+ path.setAttribute("d", d2);
6312
+ bracketGroup.appendChild(path);
6313
+ }
6314
+ svg.appendChild(bracketGroup);
6315
+ guideWrap.appendChild(svg);
6316
+ wrapper.appendChild(guideWrap);
6317
+ const header = document.createElement("div");
6318
+ header.style.cssText = `
6319
+ position:absolute;top:0;left:0;right:0;
6320
+ background:linear-gradient(180deg,rgba(0,0,0,0.8) 0%,transparent 100%);
6321
+ padding:14px 16px 32px;text-align:center;
6188
6322
  `;
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);
6323
+ header.innerHTML = `<div style="color:#fff;font-size:${TYPE.sm}px;font-weight:600;">Align your ${this.getDocumentLabel(documentType)} within the frame</div>`;
6324
+ wrapper.appendChild(header);
6325
+ const footer = document.createElement("div");
6326
+ footer.style.cssText = `
6327
+ position:absolute;bottom:0;left:0;right:0;
6328
+ background:linear-gradient(0deg,rgba(0,0,0,0.7) 0%,transparent 100%);
6329
+ padding:28px 10px 18px;text-align:center;
6196
6330
  `;
6197
- guideLbl.textContent = `Align your ${this.getDocumentLabel(documentType)} within the frame`;
6198
- wrapper.appendChild(guideLbl);
6331
+ 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>`;
6332
+ wrapper.appendChild(footer);
6199
6333
  container.appendChild(wrapper);
6200
6334
  const captureBtn = document.createElement("button");
6335
+ captureBtn.setAttribute("aria-label", "Capture photo");
6201
6336
  captureBtn.style.cssText = `
6202
6337
  display:block;margin:16px auto 0;width:64px;height:64px;
6203
6338
  border-radius:50%;border:4px solid ${theme.primary};
@@ -6223,6 +6358,39 @@ var SmartComplySDK = (() => {
6223
6358
  container.appendChild(captureBtn);
6224
6359
  this.openCamera();
6225
6360
  }
6361
+ /**
6362
+ * Matches the video box's aspect-ratio CSS to the stream's actual
6363
+ * negotiated dimensions instead of a single hardcoded ratio — a stream
6364
+ * that's natively 16:9 no longer gets force-cropped into a 4:3 box.
6365
+ * Clamped to a sane document-shaped range so a degenerate/unusual stream
6366
+ * can't produce a sliver-thin or absurdly tall box.
6367
+ */
6368
+ _fitToStream() {
6369
+ if (!this.videoEl) return;
6370
+ const { videoWidth: w2, videoHeight: h2 } = this.videoEl;
6371
+ if (!w2 || !h2) return;
6372
+ const ratio = Math.min(Math.max(w2 / h2, 1), 2);
6373
+ this.videoEl.style.aspectRatio = `${ratio}`;
6374
+ }
6375
+ /**
6376
+ * Re-fits the video box when the device rotates mid-capture. Does not
6377
+ * re-request getUserMedia (disruptive/slow) — the stream's dimensions
6378
+ * don't change on rotation, only the viewport does, so re-reading the
6379
+ * already-known videoWidth/videoHeight is enough to keep the box sane.
6380
+ */
6381
+ _watchOrientation() {
6382
+ this._unwatchOrientation();
6383
+ this.orientationHandler = () => this._fitToStream();
6384
+ window.addEventListener("orientationchange", this.orientationHandler);
6385
+ window.addEventListener("resize", this.orientationHandler);
6386
+ }
6387
+ _unwatchOrientation() {
6388
+ if (this.orientationHandler) {
6389
+ window.removeEventListener("orientationchange", this.orientationHandler);
6390
+ window.removeEventListener("resize", this.orientationHandler);
6391
+ this.orientationHandler = null;
6392
+ }
6393
+ }
6226
6394
  async openCamera() {
6227
6395
  if (!navigator.mediaDevices || !navigator.mediaDevices.getUserMedia) {
6228
6396
  this.rejectCapture?.(new Error("Camera access is not supported in this browser. Please use a modern browser like Chrome, Firefox, or Safari."));
@@ -6269,6 +6437,8 @@ var SmartComplySDK = (() => {
6269
6437
  });
6270
6438
  if (this.videoEl) {
6271
6439
  this.videoEl.srcObject = stream;
6440
+ this.videoEl.addEventListener("loadedmetadata", () => this._fitToStream(), { once: true });
6441
+ this._watchOrientation();
6272
6442
  }
6273
6443
  }
6274
6444
  captureFrame(container, theme, documentType) {
@@ -6334,21 +6504,30 @@ var SmartComplySDK = (() => {
6334
6504
  container.appendChild(this.root);
6335
6505
  }
6336
6506
  this.root.style.cssText = "display:flex;flex-direction:column;align-items:center;gap:16px;";
6507
+ const stepBadge = document.createElement("div");
6508
+ stepBadge.style.cssText = `
6509
+ display:inline-flex;align-items:center;gap:5px;
6510
+ padding:3px 11px;border-radius:${RADIUS.pill}px;
6511
+ font-size:10.5px;font-weight:600;letter-spacing:0.2px;
6512
+ color:${theme.primary};background:${theme.primary}15;border:1px solid ${theme.primary}30;
6513
+ `;
6514
+ stepBadge.textContent = "STEP 1 OF 2 · CHECK THE PHOTO";
6515
+ this.root.appendChild(stepBadge);
6337
6516
  const img = document.createElement("img");
6338
6517
  const imageUrl = URL.createObjectURL(imageData);
6339
6518
  img.src = imageUrl;
6340
6519
  img.style.cssText = `
6341
- width:100%;max-height:300px;object-fit:contain;border-radius:12px;
6520
+ width:100%;max-height:300px;object-fit:contain;border-radius:${RADIUS.md}px;
6342
6521
  border:2px solid ${theme.border};
6343
6522
  `;
6344
6523
  this.root.appendChild(img);
6345
6524
  img._blobUrl = imageUrl;
6346
6525
  const label = document.createElement("div");
6347
- label.style.cssText = `color:${theme.textSecondary};font-size:13px;text-align:center;font-weight:500;`;
6526
+ label.style.cssText = `color:${theme.text};font-size:${TYPE.base}px;font-weight:700;text-align:center;`;
6348
6527
  label.textContent = "Does the photo look clear?";
6349
6528
  this.root.appendChild(label);
6350
6529
  const sublabel = document.createElement("div");
6351
- sublabel.style.cssText = `color:${theme.textMuted};font-size:11px;text-align:center;line-height:1.6;`;
6530
+ sublabel.style.cssText = `color:${theme.textMuted};font-size:${TYPE.xs}px;text-align:center;line-height:1.6;`;
6352
6531
  sublabel.textContent = "All text must be readable and all four corners must be visible.";
6353
6532
  this.root.appendChild(sublabel);
6354
6533
  const qualityIsPoor = !!quality && !quality.isValid;
@@ -6456,63 +6635,30 @@ var SmartComplySDK = (() => {
6456
6635
  if (input) input.click();
6457
6636
  }
6458
6637
  stopCamera() {
6638
+ this._unwatchOrientation();
6459
6639
  this.cameraManager.stop();
6460
6640
  if (this.videoEl) {
6461
6641
  this.videoEl.srcObject = null;
6462
6642
  this.videoEl = null;
6463
6643
  }
6644
+ this.videoWrapEl = null;
6464
6645
  }
6465
6646
  showLoadingState(message, theme) {
6466
6647
  if (!this.root) return;
6467
6648
  this.root.innerHTML = "";
6468
6649
  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);
6650
+ this.root.appendChild(renderSpinner(theme, { size: 80, icon: icon("document", 28) }));
6487
6651
  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
- `;
6652
+ loadingText.style.cssText = `color:${theme.text};font-size:${TYPE.heading}px;font-weight:600;text-align:center;`;
6492
6653
  loadingText.textContent = message;
6493
6654
  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
6655
  }
6510
6656
  showError(message) {
6511
6657
  if (!this.root) return;
6512
6658
  const errorContainer = document.createElement("div");
6513
6659
  errorContainer.style.cssText = `
6514
6660
  display:flex;align-items:center;gap:12px;padding:16px;
6515
- background:#ff444415;border:1px solid #ff444430;border-radius:12px;
6661
+ background:#ff444415;border:1px solid #ff444430;border-radius:${RADIUS.md}px;
6516
6662
  color:#ff4444;font-size:14px;margin-top:16px;animation:shake 0.5s ease-in-out;
6517
6663
  `;
6518
6664
  errorContainer.innerHTML = `
@@ -6520,16 +6666,16 @@ var SmartComplySDK = (() => {
6520
6666
  <span>${message}</span>
6521
6667
  `;
6522
6668
  if (!document.head.querySelector("style[data-shake-animation]")) {
6523
- const style2 = document.createElement("style");
6524
- style2.setAttribute("data-shake-animation", "true");
6525
- style2.textContent = `
6669
+ const style = document.createElement("style");
6670
+ style.setAttribute("data-shake-animation", "true");
6671
+ style.textContent = `
6526
6672
  @keyframes shake {
6527
6673
  0%, 100% { transform: translateX(0); }
6528
6674
  25% { transform: translateX(-5px); }
6529
6675
  75% { transform: translateX(5px); }
6530
6676
  }
6531
6677
  `;
6532
- document.head.appendChild(style2);
6678
+ document.head.appendChild(style);
6533
6679
  }
6534
6680
  this.root.appendChild(errorContainer);
6535
6681
  setTimeout(() => errorContainer.remove(), 5e3);
@@ -6538,7 +6684,7 @@ var SmartComplySDK = (() => {
6538
6684
  const btn = document.createElement("button");
6539
6685
  btn.textContent = label;
6540
6686
  btn.style.cssText = `
6541
- padding:16px 24px;border-radius:12px;font-size:16px;font-weight:600;
6687
+ padding:16px 24px;border-radius:${RADIUS.md}px;font-size:16px;font-weight:600;
6542
6688
  cursor:pointer;transition:all 0.2s ease;border:none;width:100%;
6543
6689
  min-height:52px;touch-action:manipulation;-webkit-tap-highlight-color:transparent;
6544
6690
  ${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 +7011,6 @@ var SmartComplySDK = (() => {
6865
7011
  if (map[key]) return map[key];
6866
7012
  return code.replace(/_/g, " ").replace(/\b\w/g, (c2) => c2.toUpperCase());
6867
7013
  }
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
7014
  var _SmartComplyFlow = class _SmartComplyFlow {
6880
7015
  constructor(options) {
6881
7016
  this.theme = getTheme("default");
@@ -7217,27 +7352,9 @@ var SmartComplySDK = (() => {
7217
7352
  // ── Loading ─────────────────────────────────────────────────────
7218
7353
  renderLoading(container) {
7219
7354
  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);
7355
+ container.appendChild(renderSpinner(this.theme, { size: 60, icon: icon("shield", 22) }));
7239
7356
  const label = document.createElement("div");
7240
- label.style.cssText = `color:${this.theme.text};font-size:15px;font-weight:600;`;
7357
+ label.style.cssText = `color:${this.theme.text};font-size:${TYPE.base}px;font-weight:600;`;
7241
7358
  label.textContent = "Setting up secure session";
7242
7359
  container.appendChild(label);
7243
7360
  const sub = document.createElement("div");
@@ -7255,11 +7372,11 @@ var SmartComplySDK = (() => {
7255
7372
  iconWrap.style.cssText = `
7256
7373
  width:50px;height:50px;border-radius:14px;
7257
7374
  display:flex;align-items:center;justify-content:center;
7258
- font-size:22px;
7375
+ color:${this.theme.primary};
7259
7376
  background:linear-gradient(135deg,${this.theme.primary}22,${this.theme.primaryGlow});
7260
7377
  border:1.5px solid ${this.theme.primary}33;
7261
7378
  `;
7262
- iconWrap.textContent = isDocFlow ? "🪪" : "🛡️";
7379
+ iconWrap.innerHTML = icon(isDocFlow ? "id-card" : "shield", 24);
7263
7380
  topRow.appendChild(iconWrap);
7264
7381
  const badge = document.createElement("div");
7265
7382
  badge.style.cssText = `
@@ -7277,7 +7394,7 @@ var SmartComplySDK = (() => {
7277
7394
  titleWrap.style.cssText = "display:flex;flex-direction:column;gap:5px;";
7278
7395
  const title = document.createElement("h2");
7279
7396
  title.style.cssText = `
7280
- color:${this.theme.text};font-size:20px;font-weight:700;
7397
+ color:${this.theme.text};font-size:${TYPE.heading}px;font-weight:700;
7281
7398
  margin:0;line-height:1.2;
7282
7399
  `;
7283
7400
  const brandName = this.sdkConfig?.brand_name;
@@ -7303,7 +7420,7 @@ var SmartComplySDK = (() => {
7303
7420
  const stepsWrap = document.createElement("div");
7304
7421
  stepsWrap.style.cssText = `
7305
7422
  width:100%;display:flex;flex-direction:column;gap:0;
7306
- border-radius:12px;overflow:hidden;
7423
+ border-radius:${RADIUS.md}px;overflow:hidden;
7307
7424
  border:1.5px solid ${this.theme.border};
7308
7425
  `;
7309
7426
  steps.forEach((step, i2) => {
@@ -7316,7 +7433,7 @@ var SmartComplySDK = (() => {
7316
7433
  `;
7317
7434
  const iconEl = document.createElement("div");
7318
7435
  iconEl.style.cssText = `
7319
- width:28px;height:28px;border-radius:8px;flex-shrink:0;
7436
+ width:28px;height:28px;border-radius:${RADIUS.sm}px;flex-shrink:0;
7320
7437
  display:flex;align-items:center;justify-content:center;
7321
7438
  font-size:13px;
7322
7439
  background:${this.theme.primary}12;
@@ -7509,7 +7626,7 @@ var SmartComplySDK = (() => {
7509
7626
  if (field.type === "dropdown" || field.type === "select") {
7510
7627
  const select = document.createElement("select");
7511
7628
  select.style.cssText = `
7512
- width:100%;padding:13px 16px;border-radius:12px;
7629
+ width:100%;padding:13px 16px;border-radius:${RADIUS.md}px;
7513
7630
  font-size:15px;
7514
7631
  background:${this.theme.inputBg};
7515
7632
  color:${this.theme.text};
@@ -7546,7 +7663,7 @@ var SmartComplySDK = (() => {
7546
7663
  fileInput.type = "file";
7547
7664
  fileInput.accept = "image/*";
7548
7665
  fileInput.style.cssText = `
7549
- width:100%;padding:12px 16px;border-radius:12px;
7666
+ width:100%;padding:12px 16px;border-radius:${RADIUS.md}px;
7550
7667
  font-size:14px;font-weight:500;
7551
7668
  background:${this.theme.inputBg};
7552
7669
  color:${this.theme.text};
@@ -7587,7 +7704,7 @@ var SmartComplySDK = (() => {
7587
7704
  input.maxLength = rule?.maxLen ? rule.maxLen + 2 : 50;
7588
7705
  if (rule?.numeric) input.inputMode = "numeric";
7589
7706
  input.style.cssText = `
7590
- width:100%;padding:14px 16px;border-radius:12px;
7707
+ width:100%;padding:14px 16px;border-radius:${RADIUS.md}px;
7591
7708
  font-size:16px;font-weight:500;
7592
7709
  background:${this.theme.inputBg};
7593
7710
  color:${this.theme.text};
@@ -7644,7 +7761,7 @@ var SmartComplySDK = (() => {
7644
7761
  errorEl.id = "sc-id-error";
7645
7762
  errorEl.style.cssText = `
7646
7763
  color:${this.theme.error};font-size:13px;display:none;
7647
- padding:8px 12px;border-radius:8px;background:${this.theme.errorBg};
7764
+ padding:8px 12px;border-radius:${RADIUS.sm}px;background:${this.theme.errorBg};
7648
7765
  `;
7649
7766
  container.appendChild(errorEl);
7650
7767
  const submitBtn = this.createPrimaryButton("Verify & Continue");
@@ -7662,7 +7779,7 @@ var SmartComplySDK = (() => {
7662
7779
  };
7663
7780
  submitBtn.addEventListener("click", async () => {
7664
7781
  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>`;
7782
+ submitBtn.innerHTML = `<span style="display:inline-flex;align-items:center;justify-content:center;gap:8px;">${renderInlineSpinner("#fff", 13)}Verifying...</span>`;
7666
7783
  errorEl.style.display = "none";
7667
7784
  try {
7668
7785
  this.verificationResult = await this.sdk.onboarding.verify({
@@ -7760,11 +7877,11 @@ var SmartComplySDK = (() => {
7760
7877
  }
7761
7878
  this._prewarmCamera();
7762
7879
  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 = "🛡️";
7880
+ 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};`;
7881
+ iconWrap.innerHTML = icon("shield", 28);
7765
7882
  container.appendChild(iconWrap);
7766
7883
  const title = document.createElement("h2");
7767
- title.style.cssText = `color:${this.theme.text};font-size:18px;font-weight:700;margin:0;`;
7884
+ title.style.cssText = `color:${this.theme.text};font-size:${TYPE.heading}px;font-weight:700;margin:0;`;
7768
7885
  title.textContent = this._ivsName ? `Is this you?` : "Identity Confirmed";
7769
7886
  container.appendChild(title);
7770
7887
  if (this._ivsName) {
@@ -7823,12 +7940,21 @@ var SmartComplySDK = (() => {
7823
7940
  return;
7824
7941
  }
7825
7942
  this._prewarmCamera();
7943
+ const stepBadge = document.createElement("div");
7944
+ stepBadge.style.cssText = `
7945
+ display:inline-flex;align-items:center;gap:5px;
7946
+ padding:3px 11px;border-radius:${RADIUS.pill}px;
7947
+ font-size:10.5px;font-weight:600;letter-spacing:0.2px;
7948
+ color:${this.theme.primary};background:${this.theme.primary}15;border:1px solid ${this.theme.primary}30;
7949
+ `;
7950
+ stepBadge.textContent = "STEP 2 OF 2 · CHECK WHAT WE READ";
7951
+ container.appendChild(stepBadge);
7826
7952
  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 = "📄";
7953
+ 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};`;
7954
+ iconWrap.innerHTML = icon("document", 28);
7829
7955
  container.appendChild(iconWrap);
7830
7956
  const title = document.createElement("h2");
7831
- title.style.cssText = `color:${this.theme.text};font-size:18px;font-weight:700;margin:0;`;
7957
+ title.style.cssText = `color:${this.theme.text};font-size:${TYPE.heading}px;font-weight:700;margin:0;`;
7832
7958
  title.textContent = "Are these your details?";
7833
7959
  container.appendChild(title);
7834
7960
  const sub = document.createElement("p");
@@ -7906,19 +8032,10 @@ var SmartComplySDK = (() => {
7906
8032
  // ── W6+W7+W8: OCR Gate (document verification) ───────────────────
7907
8033
  renderOcrGate(container) {
7908
8034
  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);
8035
+ container.appendChild(renderSpinner(this.theme, { size: 52, icon: icon("document", 20) }));
7919
8036
  const statusEl = document.createElement("div");
7920
8037
  statusEl.setAttribute("aria-live", "polite");
7921
- statusEl.style.cssText = `color:${this.theme.text};font-size:15px;font-weight:600;`;
8038
+ statusEl.style.cssText = `color:${this.theme.text};font-size:${TYPE.base}px;font-weight:600;`;
7922
8039
  statusEl.textContent = "Reading your document…";
7923
8040
  container.appendChild(statusEl);
7924
8041
  const subEl = document.createElement("div");
@@ -7990,12 +8107,12 @@ var SmartComplySDK = (() => {
7990
8107
  }
7991
8108
  _renderExpiredDocument(container) {
7992
8109
  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);
8110
+ const icon2 = document.createElement("div");
8111
+ 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;`;
8112
+ icon2.textContent = "📅";
8113
+ container.appendChild(icon2);
7997
8114
  const t2 = document.createElement("h2");
7998
- t2.style.cssText = `color:${this.theme.text};font-size:18px;font-weight:700;margin:0;`;
8115
+ t2.style.cssText = `color:${this.theme.text};font-size:${TYPE.heading}px;font-weight:700;margin:0;`;
7999
8116
  t2.textContent = "Document Expired";
8000
8117
  container.appendChild(t2);
8001
8118
  const d2 = document.createElement("p");
@@ -8019,12 +8136,12 @@ var SmartComplySDK = (() => {
8019
8136
  }
8020
8137
  _renderOcrQualityFail(container, reason) {
8021
8138
  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);
8139
+ const icon2 = document.createElement("div");
8140
+ 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;`;
8141
+ icon2.textContent = "🔍";
8142
+ container.appendChild(icon2);
8026
8143
  const t2 = document.createElement("h2");
8027
- t2.style.cssText = `color:${this.theme.text};font-size:18px;font-weight:700;margin:0;`;
8144
+ t2.style.cssText = `color:${this.theme.text};font-size:${TYPE.heading}px;font-weight:700;margin:0;`;
8028
8145
  t2.textContent = "Document Photo Unclear";
8029
8146
  container.appendChild(t2);
8030
8147
  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 +8170,11 @@ var SmartComplySDK = (() => {
8053
8170
  verificationResult: this.verificationResult || void 0
8054
8171
  });
8055
8172
  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 = "✓";
8173
+ 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;`;
8174
+ iconWrap.innerHTML = icon("check", 36);
8058
8175
  container.appendChild(iconWrap);
8059
8176
  const title = document.createElement("h2");
8060
- title.style.cssText = `color:${this.theme.text};font-size:22px;font-weight:700;margin:0;`;
8177
+ title.style.cssText = `color:${this.theme.text};font-size:${TYPE.headingLg}px;font-weight:700;margin:0;`;
8061
8178
  title.textContent = "You're all done!";
8062
8179
  container.appendChild(title);
8063
8180
  const desc = document.createElement("p");
@@ -8077,12 +8194,12 @@ var SmartComplySDK = (() => {
8077
8194
  // ── W14: Retry limit reached ─────────────────────────────────────
8078
8195
  _renderRetryLimitReached(container) {
8079
8196
  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);
8197
+ const icon2 = document.createElement("div");
8198
+ 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;`;
8199
+ icon2.textContent = "⚠️";
8200
+ container.appendChild(icon2);
8084
8201
  const t2 = document.createElement("h2");
8085
- t2.style.cssText = `color:${this.theme.text};font-size:18px;font-weight:700;margin:0;`;
8202
+ t2.style.cssText = `color:${this.theme.text};font-size:${TYPE.heading}px;font-weight:700;margin:0;`;
8086
8203
  t2.textContent = "Unable to Complete Verification";
8087
8204
  container.appendChild(t2);
8088
8205
  const d2 = document.createElement("p");
@@ -8131,15 +8248,12 @@ var SmartComplySDK = (() => {
8131
8248
  throw new Error("Document image is too large. Please retake in better lighting or use a clearer photo.");
8132
8249
  }
8133
8250
  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>
8251
+ captureContainer.innerHTML = "";
8252
+ captureContainer.style.cssText += "display:flex;flex-direction:column;align-items:center;gap:14px;padding:28px 20px;";
8253
+ captureContainer.appendChild(renderSpinner(this.theme, { size: 52, icon: icon("search", 20) }));
8254
+ captureContainer.insertAdjacentHTML("beforeend", `
8140
8255
  <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>`;
8256
+ <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
8257
  const identifier = Object.values(this.collectedFields)[0] || this.idNumber || this.selectedIdType || `DOC-${Date.now()}`;
8144
8258
  const COUNTRY_CODES = {
8145
8259
  nigeria: "NG",
@@ -8189,15 +8303,12 @@ var SmartComplySDK = (() => {
8189
8303
  retryCount++;
8190
8304
  console.log(`Retrying document processing (attempt ${retryCount}/${maxRetries})`);
8191
8305
  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>
8306
+ captureContainer.innerHTML = "";
8307
+ captureContainer.style.cssText += "display:flex;flex-direction:column;align-items:center;gap:16px;padding:28px 20px;text-align:center;";
8308
+ captureContainer.appendChild(renderSpinner(this.theme, { size: 52, icon: icon("refresh", 20) }));
8309
+ captureContainer.insertAdjacentHTML("beforeend", `
8198
8310
  <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>`;
8311
+ <div style="color:${this.theme.textSecondary};font-size:12px;max-width:240px;line-height:1.5;">Attempt ${retryCount} of ${maxRetries}</div>`);
8201
8312
  }
8202
8313
  await new Promise((resolve) => setTimeout(resolve, 2e3));
8203
8314
  return attemptProcessing();
@@ -8232,10 +8343,10 @@ var SmartComplySDK = (() => {
8232
8343
  const wrap = document.createElement("div");
8233
8344
  wrap.style.cssText = "display:flex;flex-direction:column;align-items:center;gap:16px;padding:28px 20px;text-align:center;";
8234
8345
  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);
8346
+ const icon2 = document.createElement("div");
8347
+ 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;`;
8348
+ icon2.textContent = "🔍";
8349
+ wrap.appendChild(icon2);
8239
8350
  const titleEl = document.createElement("div");
8240
8351
  titleEl.style.cssText = `color:${this.theme.text};font-size:14px;font-weight:700;`;
8241
8352
  titleEl.textContent = "Document Could Not Be Verified";
@@ -8248,7 +8359,7 @@ var SmartComplySDK = (() => {
8248
8359
  const retryBtn = document.createElement("button");
8249
8360
  retryBtn.textContent = "Try Again";
8250
8361
  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;`;
8362
+ 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
8363
  retryBtn.addEventListener("click", () => this.showStep("document_capture"));
8253
8364
  wrap.appendChild(retryBtn);
8254
8365
  }
@@ -8298,7 +8409,13 @@ var SmartComplySDK = (() => {
8298
8409
  identity_check: this.identityCheckId || void 0,
8299
8410
  verification_type: this.identityCheckId ? "data_verification" : this.documentBlob ? "document_verification" : "liveness_only",
8300
8411
  // B4: pass pre-warmed stream so camera.open() is skipped
8301
- prewarmedStream: this._prewarmedStream || void 0
8412
+ prewarmedStream: this._prewarmedStream || void 0,
8413
+ colors: {
8414
+ primary: this.theme.primary,
8415
+ success: this.theme.success,
8416
+ error: this.theme.error,
8417
+ warning: this.theme.warning
8418
+ }
8302
8419
  },
8303
8420
  ["BLINK"],
8304
8421
  this.livenessEntryId || void 0
@@ -8333,21 +8450,21 @@ var SmartComplySDK = (() => {
8333
8450
  const isExpiredDoc = /document.*expired|expired.*document/i.test(message);
8334
8451
  const isFaceMatch = /face.*match|selfie.*match|does not match/i.test(message);
8335
8452
  const isBillingErr = /wallet|balance|insufficient.*fund|payment.*required/i.test(message);
8336
- const errorIcon = isCameraErr ? "📷" : isNetworkErr ? "📡" : isAuthErr ? "⏱" : isDocQuality ? "🔍" : isExpiredDoc ? "📅" : isFaceMatch ? "🤳" : isBillingErr ? "⚠️" : "✕";
8453
+ const errorIconName = isCameraErr ? "camera" : isNetworkErr ? "network" : isAuthErr ? "clock" : isDocQuality ? "search" : isExpiredDoc ? "calendar" : isFaceMatch ? "face" : isBillingErr ? "warning" : "close";
8337
8454
  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
8455
  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
8456
  const iconWrap = document.createElement("div");
8340
8457
  iconWrap.style.cssText = `
8341
8458
  width:72px;height:72px;border-radius:50%;
8342
8459
  display:flex;align-items:center;justify-content:center;
8343
- font-size:28px;
8460
+ color:${this.theme.error};
8344
8461
  background:${this.theme.errorBg};
8345
8462
  border:3px solid ${this.theme.error};
8346
8463
  `;
8347
- iconWrap.textContent = errorIcon;
8464
+ iconWrap.innerHTML = icon(errorIconName, 28);
8348
8465
  wrapper.appendChild(iconWrap);
8349
8466
  const title = document.createElement("h2");
8350
- title.style.cssText = `color:${this.theme.text};font-size:18px;font-weight:700;margin:0;`;
8467
+ title.style.cssText = `color:${this.theme.text};font-size:${TYPE.heading}px;font-weight:700;margin:0;`;
8351
8468
  title.textContent = errorTitle;
8352
8469
  wrapper.appendChild(title);
8353
8470
  const desc = document.createElement("p");
@@ -8385,7 +8502,7 @@ var SmartComplySDK = (() => {
8385
8502
  this.headerBackBtn.innerHTML = "&#8592;";
8386
8503
  this.headerBackBtn.setAttribute("aria-label", "Go back to previous step");
8387
8504
  this.headerBackBtn.style.cssText = `
8388
- width:30px;height:30px;border-radius:8px;flex-shrink:0;
8505
+ width:30px;height:30px;border-radius:${RADIUS.sm}px;flex-shrink:0;
8389
8506
  display:none;align-items:center;justify-content:center;
8390
8507
  border:1.5px solid ${this.theme.border};cursor:pointer;
8391
8508
  font-size:16px;line-height:1;
@@ -8441,7 +8558,7 @@ var SmartComplySDK = (() => {
8441
8558
  closeBtn.innerHTML = "✕";
8442
8559
  closeBtn.setAttribute("aria-label", "Close identity verification");
8443
8560
  closeBtn.style.cssText = `
8444
- width:32px;height:32px;border-radius:8px;flex-shrink:0;
8561
+ width:32px;height:32px;border-radius:${RADIUS.sm}px;flex-shrink:0;
8445
8562
  display:flex;align-items:center;justify-content:center;
8446
8563
  border:none;cursor:pointer;font-size:16px;
8447
8564
  background:${this.theme.shimmer};color:${this.theme.textMuted};
@@ -8478,7 +8595,7 @@ var SmartComplySDK = (() => {
8478
8595
  createStepTitle(text) {
8479
8596
  const el = document.createElement("h3");
8480
8597
  el.style.cssText = `
8481
- color:${this.theme.text};font-size:18px;font-weight:700;
8598
+ color:${this.theme.text};font-size:${TYPE.heading}px;font-weight:700;
8482
8599
  margin:0;
8483
8600
  `;
8484
8601
  el.textContent = text;
@@ -8488,7 +8605,7 @@ var SmartComplySDK = (() => {
8488
8605
  const card = document.createElement("button");
8489
8606
  card.setAttribute("aria-label", subtitle ? `${title}: ${subtitle}` : title);
8490
8607
  card.style.cssText = `
8491
- width:100%;padding:13px 16px;border-radius:12px;
8608
+ width:100%;padding:13px 16px;border-radius:${RADIUS.md}px;
8492
8609
  background:${this.theme.cardBg};
8493
8610
  border:2px solid ${this.theme.border};
8494
8611
  cursor:pointer;text-align:left;
@@ -8528,7 +8645,7 @@ var SmartComplySDK = (() => {
8528
8645
  const btn = document.createElement("button");
8529
8646
  btn.textContent = text;
8530
8647
  btn.style.cssText = `
8531
- width:100%;padding:14px;border-radius:12px;
8648
+ width:100%;padding:14px;border-radius:${RADIUS.md}px;
8532
8649
  font-size:15px;font-weight:600;
8533
8650
  background:${this.theme.primary};color:#fff;
8534
8651
  border:none;cursor:pointer;
@@ -8549,7 +8666,7 @@ var SmartComplySDK = (() => {
8549
8666
  const btn = document.createElement("button");
8550
8667
  btn.textContent = text;
8551
8668
  btn.style.cssText = `
8552
- width:100%;padding:12px;border-radius:12px;
8669
+ width:100%;padding:12px;border-radius:${RADIUS.md}px;
8553
8670
  font-size:14px;font-weight:500;
8554
8671
  background:transparent;color:${this.theme.textSecondary};
8555
8672
  border:none;cursor:pointer;
@@ -8665,12 +8782,9 @@ var SmartComplySDK = (() => {
8665
8782
  }
8666
8783
  injectStyles() {
8667
8784
  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
- }
8785
+ const style = document.createElement("style");
8786
+ style.id = "sc-flow-styles";
8787
+ style.textContent = `
8674
8788
  @keyframes sc-pop {
8675
8789
  0% { transform: scale(0.8); opacity: 0; }
8676
8790
  50% { transform: scale(1.05); }
@@ -8696,7 +8810,7 @@ var SmartComplySDK = (() => {
8696
8810
  border-radius: 4px;
8697
8811
  }
8698
8812
  `;
8699
- document.head.appendChild(style2);
8813
+ document.head.appendChild(style);
8700
8814
  }
8701
8815
  };
8702
8816
  _SmartComplyFlow.MAX_RETRIES = 3;