@incodetech/prizma-core-screens 0.2.4 → 0.2.12

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 (243) hide show
  1. package/dist/BiometricConsentScreen.d.ts +95 -0
  2. package/dist/BiometricConsentScreen.js +91 -0
  3. package/dist/BiometricConsentStrings.d.ts +84 -0
  4. package/dist/BiometricConsentStrings.js +31 -0
  5. package/dist/CaptureScreen.d.ts +13 -0
  6. package/dist/CaptureScreen.js +2 -2
  7. package/dist/CurpEnterScreen.d.ts +7 -0
  8. package/dist/CurpEnterScreen.js +17 -3
  9. package/dist/CurpGenerateScreen.d.ts +8 -0
  10. package/dist/CurpGenerateScreen.js +28 -13
  11. package/dist/CurpLayout.css +8 -34
  12. package/dist/CurpStrings.d.ts +16 -2
  13. package/dist/DemoScreensLayout.css +16 -0
  14. package/dist/DemoScreensRedirectScreen.d.ts +6 -1
  15. package/dist/DemoScreensRedirectScreen.js +3 -2
  16. package/dist/DemoScreensStrings.d.ts +5 -0
  17. package/dist/DigitalIdUploadErrorScreen.d.ts +31 -0
  18. package/dist/DigitalIdUploadErrorScreen.js +26 -0
  19. package/dist/DigitalIdUploadFileTooLargeScreen.d.ts +27 -0
  20. package/dist/DigitalIdUploadFileTooLargeScreen.js +21 -0
  21. package/dist/DigitalIdUploadReviewScreen.d.ts +57 -0
  22. package/dist/DigitalIdUploadReviewScreen.js +44 -0
  23. package/dist/DigitalIdUploadStrings.d.ts +64 -0
  24. package/dist/DigitalIdUploadStrings.js +19 -0
  25. package/dist/DigitalIdUploadTutorialScreen.d.ts +28 -0
  26. package/dist/DigitalIdUploadTutorialScreen.js +23 -0
  27. package/dist/DocumentCaptureIllustration.d.ts +1 -1
  28. package/dist/EkybAddressDetailsScreen.d.ts +7 -0
  29. package/dist/EkybAddressDetailsScreen.js +25 -7
  30. package/dist/EkybBusinessDetailsScreen.d.ts +6 -0
  31. package/dist/EkybBusinessDetailsScreen.js +23 -6
  32. package/dist/EkybCountryScreen.d.ts +13 -5
  33. package/dist/EkybCountryScreen.js +41 -10
  34. package/dist/EkybOwnersScreen.d.ts +8 -0
  35. package/dist/EkybOwnersScreen.js +26 -3
  36. package/dist/EkybStrings.d.ts +32 -10
  37. package/dist/EkycCountryCatalog.d.ts +4 -1
  38. package/dist/EkycCountryCatalog.js +5 -3
  39. package/dist/EkycCountryFormScreen.d.ts +12 -3
  40. package/dist/EkycCountryFormScreen.js +28 -10
  41. package/dist/EkycDetailsScreen.d.ts +7 -0
  42. package/dist/EkycDetailsScreen.js +21 -4
  43. package/dist/EkycStrings.d.ts +14 -2
  44. package/dist/ElectronicSignatureLayout.css +6 -0
  45. package/dist/EmailInputStrings.d.ts +11 -1
  46. package/dist/EmailInputVerifyScreen.d.ts +7 -0
  47. package/dist/EmailInputVerifyScreen.js +17 -3
  48. package/dist/ErrorScreensScreen.d.ts +5 -2
  49. package/dist/ErrorScreensScreen.js +15 -4
  50. package/dist/ErrorScreensStrings.d.ts +17 -2
  51. package/dist/ErrorScreensStrings.js +18 -10
  52. package/dist/FaceCaptureCapturingScreen.d.ts +63 -0
  53. package/dist/FaceCaptureCapturingScreen.js +62 -2
  54. package/dist/FaceCaptureLayout.css +69 -4
  55. package/dist/FaceCaptureStrings.d.ts +23 -0
  56. package/dist/FaceMatchComparisonScreen.d.ts +3 -3
  57. package/dist/FaceMatchLayout.css +21 -12
  58. package/dist/FormScreen.css +30 -0
  59. package/dist/FormScreen.d.ts +28 -0
  60. package/dist/FormScreen.js +3 -2
  61. package/dist/FormsLongFormScreen.d.ts +8 -0
  62. package/dist/FormsLongFormScreen.js +34 -13
  63. package/dist/FormsStrings.d.ts +11 -1
  64. package/dist/GeolocationBrowserStepsScreen.d.ts +6 -2
  65. package/dist/GeolocationBrowserStepsScreen.js +7 -3
  66. package/dist/GeolocationStrings.d.ts +3 -0
  67. package/dist/IdCaptureLayout.css +205 -2
  68. package/dist/IdCaptureStageScreen.d.ts +47 -0
  69. package/dist/IdCaptureStageScreen.js +39 -3
  70. package/dist/IdCaptureStrings.d.ts +19 -0
  71. package/dist/ListScreen.d.ts +21 -0
  72. package/dist/ListScreen.js +7 -2
  73. package/dist/LoaderScreen.d.ts +7 -5
  74. package/dist/LoaderScreen.js +7 -5
  75. package/dist/LoadersStrings.d.ts +18 -5
  76. package/dist/OcrReviewErrorScreen.d.ts +30 -0
  77. package/dist/OcrReviewErrorScreen.js +24 -0
  78. package/dist/OcrReviewLayout.css +24 -0
  79. package/dist/OcrReviewLoadingScreen.d.ts +25 -0
  80. package/dist/OcrReviewLoadingScreen.js +19 -0
  81. package/dist/OcrReviewScreen.d.ts +76 -0
  82. package/dist/OcrReviewScreen.js +65 -0
  83. package/dist/OcrReviewStrings.d.ts +47 -0
  84. package/dist/OcrReviewStrings.js +17 -0
  85. package/dist/OcrReviewSuccessScreen.d.ts +30 -0
  86. package/dist/OcrReviewSuccessScreen.js +24 -0
  87. package/dist/PermissionsAllowScreen.d.ts +8 -11
  88. package/dist/PermissionsAllowScreen.js +8 -11
  89. package/dist/PermissionsAskScreen.d.ts +41 -0
  90. package/dist/PermissionsAskScreen.js +43 -0
  91. package/dist/PermissionsBrowserStepsScreen.d.ts +9 -2
  92. package/dist/PermissionsBrowserStepsScreen.js +12 -3
  93. package/dist/PermissionsLayout.css +47 -0
  94. package/dist/PermissionsStrings.d.ts +20 -9
  95. package/dist/PermissionsStrings.js +10 -4
  96. package/dist/PhoneInputLayout.css +10 -9
  97. package/dist/PhoneInputOtpScreen.d.ts +8 -0
  98. package/dist/PhoneInputOtpScreen.js +26 -19
  99. package/dist/PhoneInputStrings.d.ts +22 -4
  100. package/dist/PhoneInputVerifyScreen.d.ts +8 -0
  101. package/dist/PhoneInputVerifyScreen.js +36 -7
  102. package/dist/QualifiedSignatureAcceptScreen.js +6 -1
  103. package/dist/QualifiedSignatureDocumentScreen.d.ts +17 -10
  104. package/dist/QualifiedSignatureDocumentScreen.js +22 -17
  105. package/dist/QualifiedSignatureLayout.css +76 -0
  106. package/dist/QualifiedSignatureResultScreen.d.ts +16 -13
  107. package/dist/QualifiedSignatureResultScreen.js +17 -18
  108. package/dist/QualifiedSignatureStrings.d.ts +19 -2
  109. package/dist/ResultScreen.d.ts +8 -0
  110. package/dist/ResultScreen.js +14 -3
  111. package/dist/ReusabilityCredentialSelectionScreen.d.ts +95 -0
  112. package/dist/ReusabilityCredentialSelectionScreen.js +94 -0
  113. package/dist/ReusabilityLayout.css +241 -0
  114. package/dist/ReusabilityPrivacyPolicyScreen.d.ts +55 -0
  115. package/dist/ReusabilityPrivacyPolicyScreen.js +44 -0
  116. package/dist/ReusabilityStrings.d.ts +85 -0
  117. package/dist/ReusabilityStrings.js +37 -0
  118. package/dist/ReviewScreen.d.ts +38 -12
  119. package/dist/ReviewScreen.js +41 -8
  120. package/dist/ScreenLayout.css +382 -6
  121. package/dist/ScreenNav.css +8 -0
  122. package/dist/ScreenNav.d.ts +15 -2
  123. package/dist/ScreenNav.js +10 -3
  124. package/dist/VideoSelfieErrorScreen.js +1 -1
  125. package/dist/VideoSelfieIdCaptureScreen.d.ts +10 -3
  126. package/dist/VideoSelfieIdCaptureScreen.js +45 -14
  127. package/dist/VideoSelfieLayout.css +467 -34
  128. package/dist/VideoSelfieSelfieCaptureScreen.d.ts +44 -27
  129. package/dist/VideoSelfieSelfieCaptureScreen.js +65 -39
  130. package/dist/VideoSelfieSpeakScreen.js +19 -2
  131. package/dist/VideoSelfieStrings.d.ts +82 -13
  132. package/dist/VideoSelfieTurnHeadScreen.d.ts +51 -0
  133. package/dist/VideoSelfieTurnHeadScreen.js +66 -0
  134. package/dist/VideoSelfieTutorialScreen.d.ts +9 -0
  135. package/dist/VideoSelfieTutorialScreen.js +22 -5
  136. package/dist/VideoSelfieWaveScreen.d.ts +53 -0
  137. package/dist/VideoSelfieWaveScreen.js +62 -0
  138. package/dist/ViewfinderScreen.css +36 -0
  139. package/dist/WatchlistBusinessFormScreen.d.ts +11 -7
  140. package/dist/WatchlistBusinessFormScreen.js +27 -13
  141. package/dist/WatchlistBusinessStrings.d.ts +21 -7
  142. package/dist/flows.d.ts +8 -0
  143. package/dist/flows.js +17 -0
  144. package/dist/index.d.ts +19 -1
  145. package/dist/index.js +14 -0
  146. package/dist/styles.css +3 -0
  147. package/dist/types.d.ts +3 -1
  148. package/package.json +79 -3
  149. package/samples/video-selfie-camera-wide.jpg +0 -0
  150. package/samples/video-selfie-room-wide.jpg +0 -0
  151. package/samples/video-selfie-room.png +0 -0
  152. package/src/BiometricConsentScreen.tsx +192 -0
  153. package/src/BiometricConsentStrings.ts +119 -0
  154. package/src/CaptureScreen.tsx +17 -0
  155. package/src/CurpEnterScreen.tsx +21 -4
  156. package/src/CurpGenerateScreen.tsx +46 -22
  157. package/src/CurpLayout.css +8 -34
  158. package/src/CurpStrings.ts +22 -2
  159. package/src/DemoScreensLayout.css +16 -0
  160. package/src/DemoScreensRedirectScreen.tsx +14 -6
  161. package/src/DemoScreensStrings.ts +5 -0
  162. package/src/DigitalIdUploadErrorScreen.tsx +83 -0
  163. package/src/DigitalIdUploadFileTooLargeScreen.tsx +67 -0
  164. package/src/DigitalIdUploadReviewScreen.tsx +119 -0
  165. package/src/DigitalIdUploadStrings.ts +88 -0
  166. package/src/DigitalIdUploadTutorialScreen.tsx +59 -0
  167. package/src/DocumentCaptureIllustration.tsx +1 -1
  168. package/src/EkybAddressDetailsScreen.tsx +32 -4
  169. package/src/EkybBusinessDetailsScreen.tsx +23 -5
  170. package/src/EkybCountryScreen.tsx +45 -7
  171. package/src/EkybOwnersScreen.tsx +34 -3
  172. package/src/EkybStrings.ts +34 -10
  173. package/src/EkycCountryCatalog.ts +9 -4
  174. package/src/EkycCountryFormScreen.tsx +51 -12
  175. package/src/EkycDetailsScreen.tsx +22 -1
  176. package/src/EkycStrings.ts +14 -2
  177. package/src/ElectronicSignatureLayout.css +6 -0
  178. package/src/EmailInputStrings.ts +12 -1
  179. package/src/EmailInputVerifyScreen.tsx +21 -4
  180. package/src/ErrorScreensScreen.tsx +15 -4
  181. package/src/ErrorScreensStrings.ts +37 -12
  182. package/src/FaceCaptureCapturingScreen.tsx +102 -13
  183. package/src/FaceCaptureLayout.css +69 -4
  184. package/src/FaceCaptureStrings.ts +24 -0
  185. package/src/FaceMatchComparisonScreen.tsx +3 -3
  186. package/src/FaceMatchLayout.css +21 -12
  187. package/src/FormScreen.css +30 -0
  188. package/src/FormScreen.tsx +34 -0
  189. package/src/FormsLongFormScreen.tsx +41 -13
  190. package/src/FormsStrings.ts +12 -1
  191. package/src/GeolocationBrowserStepsScreen.tsx +6 -3
  192. package/src/GeolocationStrings.ts +3 -0
  193. package/src/IdCaptureLayout.css +205 -2
  194. package/src/IdCaptureStageScreen.tsx +75 -0
  195. package/src/IdCaptureStrings.ts +19 -0
  196. package/src/ListScreen.tsx +58 -10
  197. package/src/LoaderScreen.tsx +7 -5
  198. package/src/LoadersStrings.ts +18 -5
  199. package/src/OcrReviewErrorScreen.tsx +53 -0
  200. package/src/OcrReviewLayout.css +24 -0
  201. package/src/OcrReviewLoadingScreen.tsx +48 -0
  202. package/src/OcrReviewScreen.tsx +190 -0
  203. package/src/OcrReviewStrings.ts +69 -0
  204. package/src/OcrReviewSuccessScreen.tsx +52 -0
  205. package/src/PermissionsAllowScreen.tsx +9 -10
  206. package/src/PermissionsAskScreen.tsx +105 -0
  207. package/src/PermissionsBrowserStepsScreen.tsx +11 -3
  208. package/src/PermissionsLayout.css +47 -0
  209. package/src/PermissionsStrings.ts +42 -12
  210. package/src/PhoneInputLayout.css +10 -9
  211. package/src/PhoneInputOtpScreen.tsx +23 -3
  212. package/src/PhoneInputStrings.ts +23 -4
  213. package/src/PhoneInputVerifyScreen.tsx +41 -5
  214. package/src/QualifiedSignatureAcceptScreen.tsx +12 -1
  215. package/src/QualifiedSignatureDocumentScreen.tsx +31 -19
  216. package/src/QualifiedSignatureLayout.css +76 -0
  217. package/src/QualifiedSignatureResultScreen.tsx +28 -26
  218. package/src/QualifiedSignatureStrings.ts +19 -2
  219. package/src/ResultScreen.tsx +33 -2
  220. package/src/ReusabilityCredentialSelectionScreen.tsx +246 -0
  221. package/src/ReusabilityLayout.css +241 -0
  222. package/src/ReusabilityPrivacyPolicyScreen.tsx +109 -0
  223. package/src/ReusabilityStrings.ts +127 -0
  224. package/src/ReviewScreen.tsx +96 -27
  225. package/src/ScreenLayout.css +382 -6
  226. package/src/ScreenNav.css +8 -0
  227. package/src/ScreenNav.tsx +35 -5
  228. package/src/VideoSelfieErrorScreen.tsx +1 -1
  229. package/src/VideoSelfieIdCaptureScreen.tsx +125 -31
  230. package/src/VideoSelfieLayout.css +467 -34
  231. package/src/VideoSelfieSelfieCaptureScreen.tsx +110 -57
  232. package/src/VideoSelfieSpeakScreen.tsx +34 -15
  233. package/src/VideoSelfieStrings.ts +89 -14
  234. package/src/VideoSelfieTurnHeadScreen.tsx +162 -0
  235. package/src/VideoSelfieTutorialScreen.tsx +45 -23
  236. package/src/VideoSelfieWaveScreen.tsx +143 -0
  237. package/src/ViewfinderScreen.css +36 -0
  238. package/src/WatchlistBusinessFormScreen.tsx +35 -16
  239. package/src/WatchlistBusinessStrings.ts +21 -7
  240. package/src/flows.ts +25 -0
  241. package/src/index.ts +88 -3
  242. package/src/styles.css +3 -0
  243. package/src/types.ts +3 -1
@@ -3,15 +3,18 @@ import {
3
3
  PrizmaIdCapture,
4
4
  type PrizmaIdCaptureState,
5
5
  } from '@incodetech/prizma-core-web/id-capture';
6
+ import { PrizmaCaptureFeedback } from '@incodetech/prizma-core-web/capture-feedback';
6
7
  import { PrizmaLoadingSpinner } from '@incodetech/prizma-core-web/loading-spinner';
7
- import { PrizmaSnackbar } from '@incodetech/prizma-core-web/snackbar';
8
8
  import { PrizmaStepper } from '@incodetech/prizma-core-web/stepper';
9
9
  import { PrizmaTag } from '@incodetech/prizma-core-web/tag';
10
+ import { PrizmaTitle } from '@incodetech/prizma-core-web/title';
10
11
  import { PrizmaScreenShell, type PrizmaScreenShellProps } from './ScreenShell';
11
12
  import type { PrizmaScreenActionHandler, PrizmaScreenOverrides } from './types';
12
13
  import type {
13
14
  VideoSelfieDocumentType,
14
- VideoSelfieIdErrorSeverity,
15
+ VideoSelfieIdCondition,
16
+ VideoSelfieIdErrorReason,
17
+ VideoSelfieIdErrorSeverity,
15
18
  VideoSelfieIdSide,
16
19
  VideoSelfieStrings,
17
20
  } from './VideoSelfieStrings';
@@ -19,13 +22,52 @@ import './ScreenLayout.css';
19
22
  import './ViewfinderScreen.css';
20
23
  import './VideoSelfieLayout.css';
21
24
 
22
- /** Which purple stage section to render (groups 3, 5 and 6). */
25
+ /** Which purple stage section to render (groups 3, 5 and 6), plus the live
26
+ * coaching beat the full-flow frames draw between them. */
23
27
  export type VideoSelfieIdCaptureState =
24
28
  | 'default'
25
29
  | 'shown'
26
30
  | 'processing'
27
31
  | 'allGood'
28
- | 'error';
32
+ | 'error'
33
+ | 'condition';
34
+
35
+ /**
36
+ * Condition → the Core treatment that already exists for it.
37
+ *
38
+ * Four are `PrizmaIdCapture`'s own error states. `blurry` is the plain error
39
+ * border: blur is a DETECTION result, not a framing mistake, and the owner's
40
+ * 2026-07-28 call is that those pair the plain border with the feedback
41
+ * bubble rather than inventing a semantic overlay (`IdCapture.tsx`, the note
42
+ * above `error`). Either way the message is the bubble's, never the frame's.
43
+ */
44
+ const CONDITION_STATE: Record<VideoSelfieIdCondition, PrizmaIdCaptureState> = {
45
+ wrongSide: 'error-wrong-side',
46
+ notAligned: 'error-not-aligned',
47
+ glare: 'error-glare',
48
+ tooDark: 'error-too-dark',
49
+ blurry: 'error',
50
+ };
51
+
52
+ /** Condition → the bubble's own variant. All six of Core's are used: the
53
+ * wrong-side bubble names the face the user SHOULD be showing, so it flips
54
+ * with the leg — `show-front` on the front, `show-back` on the back. */
55
+ const CONDITION_FEEDBACK: Record<
56
+ VideoSelfieIdCondition,
57
+ 'not-aligned' | 'blurry' | 'glare' | 'too-dark'
58
+ > = {
59
+ wrongSide: 'not-aligned', // unused — the wrong-side variant is side-keyed below
60
+ notAligned: 'not-aligned',
61
+ blurry: 'blurry',
62
+ glare: 'glare',
63
+ tooDark: 'too-dark',
64
+ };
65
+
66
+ /** The wrong-side bubble, per leg. */
67
+ const WRONG_SIDE_FEEDBACK: Record<VideoSelfieIdSide, 'show-front' | 'show-back'> = {
68
+ front: 'show-front',
69
+ back: 'show-back',
70
+ };
29
71
 
30
72
  /** Purple stage state → Core `PrizmaIdCapture` state. The frame border, the
31
73
  * analyzing sweep, the scrim and the encrypted row are ALL Core's. */
@@ -35,6 +77,8 @@ const CAPTURE_STATE: Record<VideoSelfieIdCaptureState, PrizmaIdCaptureState> = {
35
77
  processing: 'analyzing',
36
78
  allGood: 'success',
37
79
  error: 'error',
80
+ // Replaced per-condition below — the map needs an entry for every key.
81
+ condition: 'error',
38
82
  };
39
83
 
40
84
  /** Which beat of the seven-step journey each side occupies — front is step 2
@@ -56,6 +100,12 @@ export interface VideoSelfieIdCaptureScreenProps
56
100
  /** Whether the rejection invites a retry (`6.1`/`6.3`) or is terminal
57
101
  * (`6.2`/`6.4`). Read only when `state="error"`. */
58
102
  errorSeverity?: VideoSelfieIdErrorSeverity;
103
+ /** WHY the read was rejected — the `.1`–`.4` suffix of the group 6 section.
104
+ * Read only when `state="error"`. Default `scan`. */
105
+ errorReason?: VideoSelfieIdErrorReason;
106
+ /** Which live condition to coach the user out of. Read only when
107
+ * `state="condition"`. Default `notAligned`. */
108
+ condition?: VideoSelfieIdCondition;
59
109
  /** Live camera feed (<video>) or sample still (<img>) behind the frame. */
60
110
  camera?: ReactNode;
61
111
  /** The captured document still, for the states Core draws one in. */
@@ -118,6 +168,8 @@ export const VideoSelfieIdCaptureScreen = forwardRef<
118
168
  documentType = 'id',
119
169
  state = 'default',
120
170
  errorSeverity = 'tryAgain',
171
+ errorReason = 'scan',
172
+ condition = 'notAligned',
121
173
  camera,
122
174
  still,
123
175
  screenId = `video-selfie-id-capture-${side}-${state}`,
@@ -128,10 +180,26 @@ export const VideoSelfieIdCaptureScreen = forwardRef<
128
180
  },
129
181
  ref,
130
182
  ) => {
131
- const errorLabel = strings.idCapture.errors[errorSeverity];
183
+ const errorLabel = strings.idCapture.errors[errorReason][errorSeverity];
184
+ /* Only the wrong-side bubble is keyed by side — it is the one that names
185
+ the face to show. The other four describe the shot. */
186
+ const conditionCopy =
187
+ condition === 'wrongSide'
188
+ ? strings.idCapture.conditions.wrongSide[side]
189
+ : strings.idCapture.conditions[condition];
190
+ const conditionFeedback =
191
+ condition === 'wrongSide' ? WRONG_SIDE_FEEDBACK[side] : CONDITION_FEEDBACK[condition];
132
192
 
133
193
  return (
134
- <PrizmaScreenShell ref={ref} dark className={className} {...shell}>
194
+ <PrizmaScreenShell
195
+ ref={ref}
196
+ dark
197
+ /* The camera owns the whole window, never a column of it — see the
198
+ contract note in `VideoSelfieLayout.css`. */
199
+ data-pcs-overlay="window"
200
+ className={className}
201
+ {...shell}
202
+ >
135
203
  <div className="prizma-viewfinder__surface">{camera}</div>
136
204
  <div className="video-selfie-stepper">
137
205
  <PrizmaStepper
@@ -149,50 +217,76 @@ export const VideoSelfieIdCaptureScreen = forwardRef<
149
217
  .filter(Boolean)
150
218
  .join(' ')}
151
219
  >
152
- <div className="video-selfie-band" />
220
+ {/* The frame is CENTRED in the air between the stepper and the tag,
221
+ not bottom-anchored: Figma seats `ID Capture Frame` at y 172–627
222
+ of a 91–708 content area, dead centre. One flexible band either
223
+ side is the whole geometry — no offset is declared. */}
224
+ {/* The coaching bubble sits in the band ABOVE the frame, which is
225
+ where the five condition frames draw it — Core's own
226
+ `PrizmaCaptureFeedback`, the same piece ID Capture's stage uses
227
+ for the same job (`IdCaptureStageScreen`). The frame underneath
228
+ takes the matching red treatment, so the two say one thing:
229
+ what is wrong, and what to do about it. */}
230
+ <div className="video-selfie-band">
231
+ {state === 'condition' ? (
232
+ <div className="video-selfie-feedback">
233
+ <PrizmaCaptureFeedback
234
+ feedback={conditionFeedback}
235
+ title={conditionCopy.title}
236
+ subtitle={conditionCopy.subtitle}
237
+ />
238
+ </div>
239
+ ) : null}
240
+ </div>
153
241
  <PrizmaIdCapture
242
+ className="video-selfie-stage"
154
243
  type={documentType}
155
- state={CAPTURE_STATE[state]}
244
+ state={state === 'condition' ? CONDITION_STATE[condition] : CAPTURE_STATE[state]}
156
245
  isVertical
157
246
  mode="overlay"
158
247
  scrim
159
248
  showEncryptedLabel={false}
160
249
  still={still}
161
250
  />
251
+ <div className="video-selfie-band" />
162
252
  {/* Centred ON the frame, not below it — `3.2`/`5.2` put the spinner
163
253
  and its caption over the document (DEVIATIONS #VS-7). */}
164
254
  {state === 'processing' ? (
165
255
  <div className="video-selfie-stage-status">
166
- <PrizmaLoadingSpinner
167
- showTitle
168
- titleText={strings.idCapture.processingLabel}
169
- loadingLabel={strings.idCapture.processingLabel}
170
- />
256
+ <div className="video-selfie-stage-status__card">
257
+ <PrizmaLoadingSpinner
258
+ showTitle
259
+ titleText={strings.idCapture.processingLabel}
260
+ loadingLabel={strings.idCapture.processingLabel}
261
+ />
262
+ </div>
171
263
  </div>
172
264
  ) : null}
173
265
  {/* `3.3`/`5.3` and every `6.x` draw the verdict in the SAME dark card,
174
266
  centred on the document, as `3.2`/`5.2` draw the spinner — three
175
267
  identical Figma treatments had become two different ones once the
176
- spinner moved (owner QA 2026-08-19). DEVIATIONS #VS-13. */}
268
+ spinner moved (owner QA 2026-08-19). DEVIATIONS #VS-13.
269
+
270
+ The card's CONTENT is Core's `PrizmaTitle` with its status icon,
271
+ not a Snackbar: Figma stacks the mark ABOVE the label, centred,
272
+ with the label free to wrap onto two or three lines ("ID photo
273
+ verification failed, try again"). A Snackbar is a one-line ROW —
274
+ icon beside text — so it printed the copy across the full column
275
+ and had to be told, by a prop, whether its own text would wrap
276
+ (#VS-9). The stacked status block is what Core already ships for
277
+ this shape, and it is the same piece the liveness ring uses on
278
+ the same beat. DEVIATIONS #VS-19. */}
177
279
  {state === 'allGood' || state === 'error' ? (
178
280
  <div className="video-selfie-stage-status">
179
- {state === 'allGood' ? (
180
- <PrizmaSnackbar state="success" role="status">
181
- {strings.idCapture.successLabel}
182
- </PrizmaSnackbar>
183
- ) : (
184
- /* NOT `isMultiline`: that modifier switches the row to
185
- `align-items: flex-start` so an icon anchors to the top of
186
- WRAPPED text. The rejection copy renders on ONE line, so it
187
- only pushed the icon 6.9px below the text centre
188
- (owner-reported 2026-08-19: "the text is not even aligned to
189
- the icon"). CORE REQUEST: have the Snackbar follow actual
190
- wrapping rather than a prop the caller has to predict.
191
- DEVIATIONS #VS-9. */
192
- <PrizmaSnackbar state="error" role="alert">
193
- {errorLabel}
194
- </PrizmaSnackbar>
195
- )}
281
+ <div
282
+ className="video-selfie-stage-status__card"
283
+ role={state === 'error' ? 'alert' : 'status'}
284
+ >
285
+ <PrizmaTitle
286
+ title={state === 'allGood' ? strings.idCapture.successLabel : errorLabel}
287
+ icon={{ type: 'status', status: state === 'allGood' ? 'success' : 'error' }}
288
+ />
289
+ </div>
196
290
  </div>
197
291
  ) : null}
198
292
  </div>