@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
@@ -59,12 +59,129 @@
59
59
  gap: var(--prizma-spacing-8); /* Title → instruction, GUIDELINES §5 */
60
60
  }
61
61
 
62
+ /* ── Short screens: the vertical frame gives up height, never the title ──────
63
+ * The vertical ID (288:456) and passport (306:420) frames are tall. On a
64
+ * 320 × 693 phone the column is 272 wide, so the frame alone is ~431 tall and
65
+ * the stage ran 168px past the bottom, under the shutter strip (Camila,
66
+ * 2026-09-28). Here the frame is the ONE part of the column that shrinks: it
67
+ * starts at its full-width height (the column less its two Spacing/24
68
+ * gutters, over the aspect), and when the screen is too short the flex column
69
+ * takes the shortfall out of its height; the aspect ratio then narrows its
70
+ * width to match, so it stays an ID-shaped frame, centred. The title band
71
+ * keeps its content height. With room to spare (390 × 844) the frame never
72
+ * needs to shrink, so it sits exactly where it did.
73
+ *
74
+ * Scoped to ID + passport with `:not(--poa)`: Document Capture renders the
75
+ * same stage as `type="poa" isVertical`, so it carries `--vertical` too, but
76
+ * the PoA frame has NO aspect ratio (it fills the host's height). `width:
77
+ * auto` there collapsed it to a 0-wide sliver, a grey vertical bar down the
78
+ * camera screen (Elena, 2026-09-30). Only showed where this file and Document
79
+ * Capture's CSS ship in the same bundle, i.e. the production build. */
80
+ .prizma-viewfinder__content:has(> .prizma-id-capture--vertical:not(.prizma-id-capture--poa)) {
81
+ min-height: 0;
82
+ }
83
+ .prizma-viewfinder__content:has(> .prizma-id-capture--vertical:not(.prizma-id-capture--poa)) > .id-capture-band--top {
84
+ flex-shrink: 0;
85
+ min-height: min-content;
86
+ }
87
+ .prizma-viewfinder__content > .prizma-id-capture--vertical:not(.prizma-id-capture--poa) {
88
+ flex: 0 1 auto;
89
+ min-height: 0;
90
+ }
91
+ .prizma-viewfinder__content > .prizma-id-capture--vertical:not(.prizma-id-capture--poa) .prizma-id-capture__frame {
92
+ flex: 0 1 auto;
93
+ min-height: 0;
94
+ width: auto;
95
+ max-width: 100%;
96
+ flex-basis: calc((100cqw - 2 * var(--prizma-spacing-24)) * 456 / 288);
97
+ }
98
+ .prizma-viewfinder__content > .prizma-id-capture--passport.prizma-id-capture--vertical .prizma-id-capture__frame {
99
+ flex-basis: calc((100cqw - 2 * var(--prizma-spacing-24)) * 420 / 306);
100
+ }
101
+
102
+ /* ── A notice on the stage: the horizontal frame may give up height too ──────
103
+ * The "Need more time?" offer (`.id-capture-stage__notice`, IDC-32) adds ~90px
104
+ * of content to the bottom band. On the 390 × 844 reference the band has the
105
+ * room and nothing moves. On a short panel it does not: measured 2026-10-15,
106
+ * the horizontal ID frame is aspect-locked and does not shrink, so the column
107
+ * overflowed and the notice ran 10px into the help strip at 320 × 693 and 36px
108
+ * at the closed iPhone Duo (466 × 678). The same recipe as the vertical rule
109
+ * above, applied to the horizontal frames ONLY while a notice is on the stage:
110
+ * the frame starts at its full-width height and gives up height when the
111
+ * column is short, the aspect ratio narrows it to match, the title band keeps
112
+ * its content height. Face Capture makes the identical trade at 320 (its
113
+ * selfie frame gives up Spacing/40 for the notice, ScreenLayout.css) and the
114
+ * owner's rule is explicit that the frame may get smaller (2026-08-18). A
115
+ * stage without a notice is untouched. */
116
+ .prizma-viewfinder__content:has(> .id-capture-band > .id-capture-stage__notice) {
117
+ min-height: 0;
118
+ }
119
+ .prizma-viewfinder__content:has(> .id-capture-band > .id-capture-stage__notice) > .id-capture-band--top {
120
+ flex-shrink: 0;
121
+ min-height: min-content;
122
+ }
123
+ .prizma-viewfinder__content:has(> .id-capture-band > .id-capture-stage__notice) > .prizma-id-capture--horizontal:not(.prizma-id-capture--poa) {
124
+ flex: 0 1 auto;
125
+ min-height: 0;
126
+ }
127
+ .prizma-viewfinder__content:has(> .id-capture-band > .id-capture-stage__notice) > .prizma-id-capture--horizontal:not(.prizma-id-capture--poa) .prizma-id-capture__frame {
128
+ flex: 0 1 auto;
129
+ min-height: 0;
130
+ width: auto;
131
+ max-width: 100%;
132
+ flex-basis: calc((100cqw - 2 * var(--prizma-spacing-24)) * 220 / 350);
133
+ }
134
+ .prizma-viewfinder__content:has(> .id-capture-band > .id-capture-stage__notice) > .prizma-id-capture--passport.prizma-id-capture--horizontal .prizma-id-capture__frame {
135
+ flex-basis: calc((100cqw - 2 * var(--prizma-spacing-24)) * 254 / 350);
136
+ }
137
+
138
+ /* ── Short panels: the tutorial art is sized by its halo, not its canvas ─────
139
+ * `PrizmaIllustrationIdTutorial` is a 342 × 392 canvas with the halo centred
140
+ * at r130 (y 66–326) and the hand-and-document artwork inside it (y 100–313;
141
+ * the passport's hand fades out above). The 66 above and below the halo are
142
+ * air at rest; the bottom band is where the hand travels in from during the
143
+ * loop. The selfie illustration is a 296 canvas with the same r130 halo and 18
144
+ * of air: on the 844 reference both halos are 260 and the two tutorials match.
145
+ *
146
+ * On a short panel the tutorial middle is height-limited (ScreenLayout.css,
147
+ * #F-35) and the two canvases scale by height, so the ID halo comes out 18 %
148
+ * smaller than the selfie's (170 vs 209 on the closed iPhone Duo, measured
149
+ * 2026-10-14; Camila: "ID tutorials have illustration a bit too small, no?
150
+ * Compared to the size on the selfie tutorial one"). Fixed by cropping the
151
+ * canvas to the halo band plus Spacing/16 on each side — y 50 to 342, 292
152
+ * units, the same 89 % the selfie's halo takes of its own box — so the halo
153
+ * fills the slot the way the selfie's does. The wrapper takes the slot and
154
+ * clips; the svg is scaled so 292 of its 392 units fill the wrapper and
155
+ * centres, so the crop is symmetric around the halo and the halo's centre
156
+ * does not move. During the loop the entering hand is clipped 50 units
157
+ * earlier than the canvas clips it, which is invisible against the fade.
158
+ * Outside the query nothing exists: the reference renders the full canvas.
159
+ * DEVIATIONS #IDC-31. */
160
+ @container pcs-screen (max-height: 720px) {
161
+ .prizma-screen-layout__flex > .prizma-illustration-tutorial {
162
+ flex: 1 1 0;
163
+ min-height: 0;
164
+ align-self: stretch;
165
+ display: flex;
166
+ align-items: center;
167
+ justify-content: center;
168
+ overflow: hidden;
169
+ }
170
+
171
+ .prizma-screen-layout__flex > .prizma-illustration-tutorial > svg {
172
+ flex: none;
173
+ height: calc(100% * 392 / 292);
174
+ width: auto;
175
+ max-width: none;
176
+ }
177
+ }
178
+
62
179
  /* ── Camera stage (dark) ───────────────────────────────────────────────────── */
63
180
 
64
181
  /* The stage's nav row carries only the close X (no logo — the camera owns the
65
182
  * screen). The foundation `.prizma-screen-nav` supplies the status-bar reserve,
66
183
  * the 44px flow slot and the un-fixing of Core's PrizmaNavigation; the ink is
67
- * the only thing the camera stage changes: Core's nav icon is the THEMED
184
+ * the only thing the camera stage changes: Core's nav icon is the themed
68
185
  * `Icon/Neutral/500`, which disappears on the always-dark camera surface, so it
69
186
  * takes the camera's own Static ink — the same token PrizmaCaptureManual uses
70
187
  * for the shutter and the "?" help control. DEVIATIONS.md #IDC-21. */
@@ -78,6 +195,44 @@
78
195
  width: 100%;
79
196
  }
80
197
 
198
+ /* ── The "Need more time?" notice ─────────────────────────────────────────────
199
+ * The Snackbar the stage raises 20 s before auto-capture falls back to the
200
+ * shutter (IdCaptureStageScreen `extendTime`, 2026-10-15). It takes the BOTTOM
201
+ * band — the air between the encrypted row and the strip's reserved space —
202
+ * because, unlike Face Capture, this stage's strip is never empty: the "?" help
203
+ * control rides it on every stage (IDC-29), so the shared rail the selfie notice
204
+ * uses (`.prizma-screen-layout__capture-notice`) would land on top of it.
205
+ *
206
+ * The band is `justify-content: flex-end`, so the notice sits just above the
207
+ * strip's Spacing/12 of breathing and the frame above does not move when the
208
+ * offer arrives. The band is also `flex: 1; min-height: 0`, which on a short
209
+ * panel would let it shrink to nothing and spill the notice upward over the
210
+ * encrypted row; with a notice in it the band keeps its content height and the
211
+ * shortfall goes where this stylesheet already sends it — the vertical frame
212
+ * (the short-panel rule above), which the owner has said may get smaller
213
+ * (2026-08-18). DEVIATIONS #IDC-32. */
214
+ .id-capture-band:has(> .id-capture-stage__notice) {
215
+ flex-shrink: 0;
216
+ min-height: min-content;
217
+ padding-top: var(--prizma-spacing-16);
218
+ }
219
+
220
+ .id-capture-stage__notice {
221
+ display: flex;
222
+ /* The HUD column centres its copy; the Snackbar's own text is left-set. */
223
+ text-align: left;
224
+ }
225
+
226
+ /* On a 320 phone the notice drops its status glyph — the same call Face
227
+ * Capture made (Camila, 2026-10-05, ScreenLayout.css): 44 of the 272px column
228
+ * on a decorative mark pushed the body to four lines. The icon is
229
+ * `aria-hidden`; the copy carries the meaning without it. */
230
+ @container pcs-screen (max-width: 340px) {
231
+ .id-capture-stage__notice .prizma-snackbar__icon {
232
+ display: none;
233
+ }
234
+ }
235
+
81
236
  /* The feedback pill replaces the title block on the error stages (Figma
82
237
  * `1-5-5 … 1-5-9-id-errors`): same band, same Spacing/40 above the frame. */
83
238
  .id-capture-stage__feedback {
@@ -85,6 +240,54 @@
85
240
  justify-content: center;
86
241
  }
87
242
 
243
+ /* ── Short or narrow panels: the live cue takes Template B ───────────────────
244
+ * `PrizmaCaptureFeedback` ships two templates on its `showAnimation` axis:
245
+ * A, the 120-ish pill with the illustration and a Headline/H3 title, and B, a
246
+ * 72 pill with no illustration and Headline/H5. The error stages draw A on the
247
+ * 390 × 844 reference. On a closed iPhone Duo (678) A still fits — measured
248
+ * 2026-10-14, the frame lands at 198–473 with the pill above it — but it is
249
+ * the tallest element on a stage that has just lost 166px, and on a 640 phone
250
+ * or a 320 column it does not fit at all. Video Selfie already made this call
251
+ * for its own cues (DEVIATIONS #VS-30, Camila 2026-10-07): under 340 wide or
252
+ * 720 tall the pill is B. The same line here, so the two camera modules agree
253
+ * on when a cue goes compact. Nothing is re-skinned: fill, radius, stroke and
254
+ * shadow are Core's and identical between A and B (capture-feedback.md §4.4);
255
+ * what changes is exactly Template B's four switches, taken from
256
+ * `CaptureFeedback.css`'s own `--compact` modifier.
257
+ *
258
+ * A container query, not the prop: the screen cannot know the panel's height,
259
+ * the shell's `pcs-screen` container can. ONE `or` condition, not two
260
+ * comma-separated queries (lightningcss rejects the latter; see
261
+ * VideoSelfieLayout.css). The 390 reference is unchanged. DEVIATIONS #IDC-30. */
262
+ @container pcs-screen ((max-width: 340px) or (max-height: 720px)) {
263
+ .id-capture-stage__feedback .prizma-capture-feedback__illustration {
264
+ display: none;
265
+ }
266
+
267
+ /* Template B: body padding-bottom 12 → 16, itemSpacing 8 → 4. */
268
+ .id-capture-stage__feedback .prizma-capture-feedback__body {
269
+ padding: var(--prizma-spacing-16) 0;
270
+ gap: var(--prizma-spacing-4);
271
+ }
272
+
273
+ /* Title Headline/H3 → Headline/H5. */
274
+ .id-capture-stage__feedback .prizma-capture-feedback__title {
275
+ font-weight: var(--prizma-headline-h5-font-weight);
276
+ font-size: var(--prizma-headline-h5-font-size);
277
+ line-height: var(--prizma-headline-h5-line-height);
278
+ letter-spacing: var(--prizma-headline-h5-letter-spacing);
279
+ }
280
+
281
+ /* Subtitle Headline/H5 → Body/M Regular. */
282
+ .id-capture-stage__feedback .prizma-capture-feedback__subtitle {
283
+ font-family: var(--prizma-body-family);
284
+ font-weight: var(--prizma-body-m-regular-font-weight);
285
+ font-size: var(--prizma-body-m-regular-font-size);
286
+ line-height: var(--prizma-body-m-regular-line-height);
287
+ letter-spacing: var(--prizma-body-m-regular-letter-spacing);
288
+ }
289
+ }
290
+
88
291
  /* ── Removed: promoted into the foundation ───────────────────────────────────
89
292
  * `.id-capture-glyph*` (the non-status glyph slot) is now
90
293
  * `ScreenLayout.css`'s `__glyph` — DEVIATIONS #DC-29, closed.
@@ -102,7 +305,7 @@
102
305
  *
103
306
  * The plate needs no override — Core's own `mode="overlay"` already makes the
104
307
  * window transparent, which is what the light screens want. The ink does: the
105
- * row is re-inked with the THEMED body token so it also survives dark mode,
308
+ * row is re-inked with the themed body token so it also survives dark mode,
106
309
  * scoped to the light screens only (the camera stage keeps Core's Static white).
107
310
  * Core gap — PrizmaIdCapture has no surface-aware encrypted row. DEVIATIONS.md #IDC-28.
108
311
  */
@@ -6,6 +6,7 @@ import {
6
6
  } from '@incodetech/prizma-core-web/id-capture';
7
7
  import { PrizmaCaptureManual } from '@incodetech/prizma-core-web/capture-manual';
8
8
  import { PrizmaCaptureFeedback } from '@incodetech/prizma-core-web/capture-feedback';
9
+ import { PrizmaSnackbar } from '@incodetech/prizma-core-web/snackbar';
9
10
  import { PrizmaTag } from '@incodetech/prizma-core-web/tag';
10
11
  import { PrizmaScreenShell, type PrizmaScreenShellProps } from './ScreenShell';
11
12
  import type { PrizmaScreenActionHandler, PrizmaScreenOverrides } from './types';
@@ -80,6 +81,28 @@ export interface IdCaptureStageScreenProps
80
81
  still?: ReactNode;
81
82
  /** Digit shown by the countdown Timer (`*-countdown` sections 1..3). */
82
83
  countdownValue?: 1 | 2 | 3;
84
+ /**
85
+ * Raise the "Need more time?" offer over the feed — the accessibility
86
+ * notification shown 20 s before auto-capture falls back to the shutter.
87
+ *
88
+ * A MODIFIER of whatever stage state is already showing, not a twelfth
89
+ * state: the 30 s fallback timer runs underneath the hint overlay, so the
90
+ * person can be shown the hand-and-document ghost and offered more time in
91
+ * the same frame. Needs `strings.stage.extendTime`; without it the flag is a
92
+ * no-op, which is what a host that has not localized the copy should get
93
+ * rather than English. Same contract as `FaceCaptureCapturingScreen`.
94
+ */
95
+ extendTime?: boolean;
96
+ /** Tapping "Extend auto-capture". The host resets its own fallback timer. */
97
+ onExtendTime?: () => void;
98
+ /**
99
+ * A notice band of the host's own, in the slot `extendTime` uses. Wins over
100
+ * `extendTime` when both are given. Exists for a host that needs the
101
+ * Snackbar to do something the static one cannot — Core Lab's prototype
102
+ * swaps in a copy whose count actually runs down — without reaching into
103
+ * the screen. The static `extendTime` notice stays the default.
104
+ */
105
+ notice?: ReactNode;
83
106
  screenId?: string;
84
107
  overrides?: PrizmaScreenOverrides;
85
108
  onAction?: PrizmaScreenActionHandler;
@@ -113,6 +136,31 @@ export interface IdCaptureStageScreenProps
113
136
  * to the column's bottom padding) — no offsets are invented here, and
114
137
  * PrizmaIdCapture's own frame→encrypted-row adjacency is left untouched
115
138
  * (DEVIATIONS.md #12's lesson: never stack an offset a Core component carries).
139
+ *
140
+ * ── The "Need more time?" offer (`extendTime`) ──────────────────────────────
141
+ *
142
+ * Auto-capture gives up after a configured timeout (30 s in the module's own
143
+ * flow frames) and drops the person onto the shutter. Someone who is
144
+ * struggling — a tremor, low vision, a dark room, a card that will not sit
145
+ * flat — gets moved off the EASIER path precisely because they were slow,
146
+ * which is backwards. So 20 s before the switch, the stage offers to stay on
147
+ * auto. A client turns it on per flow from the dashboard; with it off, nothing
148
+ * about today's capture changes. It is the conformance route for WCAG 2.2.1
149
+ * Timing Adjustable via the *Extend* clause (warn before the limit, ≥20 s to
150
+ * act, ≥10 extensions) — the reasoning, the `role="alert"` decision and the
151
+ * `neutral` state are all Face Capture's (2026-10-05) and are not re-argued
152
+ * here: `FaceCaptureCapturingScreen`'s header is the record. One feature, two
153
+ * modules, one Snackbar.
154
+ *
155
+ * WHERE IT SITS is the one thing this module decides differently. Face
156
+ * Capture anchors the notice on the shutter-strip rail because, there, notice
157
+ * and shutter are alternatives — a capturing screen either raises the offer or
158
+ * shows the button. ID Capture's strip is never free: the "?" help control
159
+ * rides it on every stage, auto or manual (IDC-29). So the notice takes the
160
+ * BOTTOM BAND instead — the flexible air between the encrypted row and the
161
+ * strip's reserved space — which is the one slot on this stage nothing else
162
+ * owns. It bottom-anchors there like the band's other content would, so the
163
+ * frame above does not move when the offer arrives. DEVIATIONS.md #IDC-32.
116
164
  */
117
165
  export const IdCaptureStageScreen = forwardRef<HTMLDivElement, IdCaptureStageScreenProps>(
118
166
  (
@@ -128,6 +176,9 @@ export const IdCaptureStageScreen = forwardRef<HTMLDivElement, IdCaptureStageScr
128
176
  camera,
129
177
  still,
130
178
  countdownValue = 3,
179
+ extendTime,
180
+ onExtendTime,
181
+ notice,
131
182
  screenId = `id-capture-${documentType}-${side}-${state}`,
132
183
  overrides,
133
184
  onAction,
@@ -146,6 +197,29 @@ export const IdCaptureStageScreen = forwardRef<HTMLDivElement, IdCaptureStageScr
146
197
  const pillKind = feedback === undefined ? STAGE_FEEDBACK[state] : feedback;
147
198
  const pillCopy = pillKind ? strings.feedback[pillKind] : undefined;
148
199
 
200
+ const offer = strings.stage.extendTime;
201
+ // No copy, no notice: a host that has not localized this must not get
202
+ // English, and the flag alone is not permission to invent it.
203
+ const band =
204
+ notice ??
205
+ (extendTime && offer ? (
206
+ <PrizmaSnackbar
207
+ state="neutral"
208
+ isMultiline
209
+ // Assertive on purpose — a polite region can queue behind the
210
+ // stage's own state announcements and be read out after the 20 s
211
+ // has already run out. FaceCaptureCapturingScreen's header has the
212
+ // full reasoning; this instance follows it.
213
+ role="alert"
214
+ linkLabel={offer.linkLabel}
215
+ onLinkClick={onExtendTime}
216
+ >
217
+ <strong>{offer.title}</strong>
218
+ <br />
219
+ {offer.description}
220
+ </PrizmaSnackbar>
221
+ ) : undefined);
222
+
149
223
  return (
150
224
  <PrizmaScreenShell
151
225
  ref={ref}
@@ -213,6 +287,7 @@ export const IdCaptureStageScreen = forwardRef<HTMLDivElement, IdCaptureStageScr
213
287
  still={still}
214
288
  />
215
289
  <div className="id-capture-band">
290
+ {band ? <div className="id-capture-stage__notice">{band}</div> : null}
216
291
  </div>
217
292
  </div>
218
293
  <div className="prizma-screen-layout__capture-strip">
@@ -126,6 +126,25 @@ export interface IdCaptureStrings {
126
126
  /** Visually-hidden state announcements, per stage state — forwarded to
127
127
  * `PrizmaIdCapture.stateLabels`. */
128
128
  stateLabels?: Partial<Record<IdCaptureStageState, string>>;
129
+ /**
130
+ * stage.extendTime — the accessibility offer that rides the camera stage
131
+ * 20 s before auto-capture gives up and hands over to the shutter
132
+ * ("Need more time? / Manual capture starts in 20 s / Extend auto-capture").
133
+ * The same contract as Face Capture's `extendTime`: one feature, two
134
+ * modules, identical copy, so the locale overlay translates both at once.
135
+ *
136
+ * `description` is one localized sentence that CONTAINS the count, not a
137
+ * template — ten locales put the number in ten places. Optional: a host
138
+ * that has not localized it gets no notice rather than English.
139
+ */
140
+ extendTime?: {
141
+ /** Bold first line — "Need more time?" */
142
+ title: string;
143
+ /** "Manual capture starts in 20 s" — the count lives inside the copy. */
144
+ description: string;
145
+ /** The action that keeps the user on auto — "Extend auto-capture". */
146
+ linkLabel: string;
147
+ };
129
148
  };
130
149
 
131
150
  /** The on-camera feedback pills the error stages carry. */
@@ -74,9 +74,30 @@ export interface PrizmaListScreenProps
74
74
  * (common issues) and "Quit process" (permission). Figma draws Core's
75
75
  * `tertiary-link` composite in the band's top slot. */
76
76
  linkLabel?: string;
77
+ /**
78
+ * A SECOND tertiary link, under the first. Reusability's selection draws
79
+ * "What data will be shared?" over "Incode’s Privacy Policy" with no primary
80
+ * between them — two non-primary actions a host has to tell apart, so this
81
+ * one emits `tertiary` where `linkLabel` emits `secondary` (the #PI-10
82
+ * reasoning). Stacked at the band's flat Spacing/16 like everything else in
83
+ * it. Omit it and nothing renders, so every existing consumer is untouched.
84
+ * DEVIATIONS #RU-4.
85
+ */
86
+ secondaryLinkLabel?: string;
87
+ /**
88
+ * A shell-level layer painted OVER the whole screen — the same slot
89
+ * archetypes A and E carry (#F-32, #BC-8): a scrim plus Core's
90
+ * `PrizmaBottomSheetContent` or `PrizmaModalContent`, presented on top of the
91
+ * dimmed list. It cannot ride in the content column: it is absolutely
92
+ * positioned against the shell. Reusability's shared-details sheet is the
93
+ * first List consumer (DEVIATIONS #RU-5).
94
+ */
95
+ overlay?: ReactNode;
77
96
  /** "verified by" attribution copy for the footer tag. */
78
97
  verifiedLabel: string;
79
98
  navLabel?: string;
99
+ /** Opt-in back chevron in the nav (its accessible name). Emits `back`. */
100
+ backLabel?: string;
80
101
  screenId?: string;
81
102
  overrides?: PrizmaScreenOverrides;
82
103
  onAction?: PrizmaScreenActionHandler;
@@ -120,8 +141,11 @@ export const PrizmaListScreen = forwardRef<HTMLDivElement, PrizmaListScreenProps
120
141
  ctaLabel,
121
142
  secondaryCtaLabel,
122
143
  linkLabel,
144
+ secondaryLinkLabel,
145
+ overlay,
123
146
  verifiedLabel,
124
147
  navLabel,
148
+ backLabel,
125
149
  screenId,
126
150
  showHeader = true,
127
151
  showFooter = true,
@@ -132,7 +156,13 @@ export const PrizmaListScreen = forwardRef<HTMLDivElement, PrizmaListScreenProps
132
156
  ref,
133
157
  ) => (
134
158
  <PrizmaScreenShell ref={ref} {...shell}>
135
- <PrizmaScreenNav reserved={!showHeader} logo={overrides?.logo} navLabel={navLabel} />
159
+ <PrizmaScreenNav
160
+ reserved={!showHeader}
161
+ logo={overrides?.logo}
162
+ navLabel={navLabel}
163
+ backLabel={backLabel}
164
+ onBack={() => onAction?.({ type: 'back', screenId })}
165
+ />
136
166
  {progress ? (
137
167
  <div className="prizma-screen-layout__progress">{progress}</div>
138
168
  ) : null}
@@ -162,17 +192,34 @@ export const PrizmaListScreen = forwardRef<HTMLDivElement, PrizmaListScreenProps
162
192
  >
163
193
  {children}
164
194
  </div>
165
- {ctaLabel || secondaryCtaLabel || linkLabel || disclaimer ? (
195
+ {ctaLabel || secondaryCtaLabel || linkLabel || secondaryLinkLabel || disclaimer ? (
166
196
  <div className="prizma-screen-layout__band">
167
197
  {disclaimer ? <PrizmaDisclaimer text={disclaimer} /> : null}
168
- {linkLabel ? (
169
- <PrizmaButton
170
- variant="tertiary-link"
171
- size="L"
172
- onClick={() => onAction?.({ type: 'secondary', screenId })}
173
- >
174
- {linkLabel}
175
- </PrizmaButton>
198
+ {linkLabel || secondaryLinkLabel ? (
199
+ /* The links share ONE band slot, stacked flush: two 56px link
200
+ rows with the band's 16 between them read as two distant
201
+ lines (Camila, 2026-10-13); the row height is already the
202
+ touch target. ScreenLayout.css `__band__links`. */
203
+ <div className="prizma-screen-layout__band__links">
204
+ {linkLabel ? (
205
+ <PrizmaButton
206
+ variant="tertiary-link"
207
+ size="L"
208
+ onClick={() => onAction?.({ type: 'secondary', screenId })}
209
+ >
210
+ {linkLabel}
211
+ </PrizmaButton>
212
+ ) : null}
213
+ {secondaryLinkLabel ? (
214
+ <PrizmaButton
215
+ variant="tertiary-link"
216
+ size="L"
217
+ onClick={() => onAction?.({ type: 'tertiary', screenId })}
218
+ >
219
+ {secondaryLinkLabel}
220
+ </PrizmaButton>
221
+ ) : null}
222
+ </div>
176
223
  ) : null}
177
224
  {/* THE PRIMARY ALWAYS SITS ABOVE THE SECONDARY (owner rule
178
225
  2026-08-19, DEVIATIONS #GEO-1). The rule governs the
@@ -205,6 +252,7 @@ export const PrizmaListScreen = forwardRef<HTMLDivElement, PrizmaListScreenProps
205
252
  <PrizmaTag label={verifiedLabel} />
206
253
  </div>
207
254
  ) : null}
255
+ {overlay}
208
256
  </PrizmaScreenShell>
209
257
  ),
210
258
  );
@@ -23,11 +23,13 @@ export interface LoaderScreenProps
23
23
  * (GUIDELINES.md §6-C, `PrizmaProcessingScreen`).
24
24
  *
25
25
  * Figma: `Module Generic Screens` frames `67:2388` ("Processing…") and
26
- * `67:3593` ("Just a moment…"). ONE screen for both, and for every module
27
- * loader after them: logo header → Core's spinner → status line → reassurance
28
- * line → the verified tag, with no CTA. The archetype already IS this recipe;
29
- * this component exists so the family has a name a designer can point at and a
30
- * copy contract a host can fill, not to add layout.
26
+ * `67:3593` ("Just a moment…"), plus the SDK's own "Hold on a sec…" wait that
27
+ * ID Capture, NFC and the Demo App show (`verifyingIdentity`). ONE screen for
28
+ * all of them, and for every module loader after them: logo header → Core's
29
+ * spinner → status line → reassurance line → the verified tag, with no CTA.
30
+ * The archetype already IS this recipe; this component exists so the family
31
+ * has a name a designer can point at and a copy contract a host can fill, not
32
+ * to add layout.
31
33
  *
32
34
  * Reach for `PrizmaResultScreen` the moment a wait screen needs a button — a
33
35
  * loader with a "Cancel" is a result screen, and the missing CTA band here is
@@ -15,12 +15,25 @@
15
15
  // No hardcoded English anywhere in a screen: every visible string arrives here.
16
16
 
17
17
  /**
18
- * The two frames in the generic file. They are the same screen with different
19
- * copy — which is the point of the family: the loader is a shape, and the two
20
- * entries here are examples of filling it, not a closed set. A module that
21
- * waits for something else supplies its own pair of strings under a new key.
18
+ * The copy pairs the family records. The loader is a shape, and each entry
19
+ * here is a way of filling it that more than one module already uses — not a
20
+ * closed set. A module that waits for something else supplies its own pair of
21
+ * strings under a new key.
22
+ *
23
+ * - `processing` — frame `67:2388`. "Processing…" over the generic
24
+ * reassurance line. Watchlist for Business, eKYC, eKYB,
25
+ * Email Input and the signatures all draw this title.
26
+ * - `validating` — frame `67:3593`. "Just a moment…", the documents
27
+ * are being validated.
28
+ * - `verifyingIdentity` — the SDK's own `loadingCircle.holdOn` wait: "Hold on
29
+ * a sec…" over "We're verifying your identity". ID
30
+ * Capture, NFC and the Demo App show it between the
31
+ * last capture and the verdict (Camila, 2026-10-09).
32
+ *
33
+ * Copy rule for every wait title: the ellipsis is the single `…` character,
34
+ * never two or three periods, so the same word reads the same in every module.
22
35
  */
23
- export type LoadersVariant = 'processing' | 'validating';
36
+ export type LoadersVariant = 'processing' | 'validating' | 'verifyingIdentity';
24
37
 
25
38
  export interface LoadersCopy {
26
39
  /** H2 status line ("Processing…"). */
@@ -0,0 +1,53 @@
1
+ import React, { forwardRef } from 'react';
2
+ import { PrizmaResultScreen, type PrizmaResultScreenProps } from './ResultScreen';
3
+ import type { PrizmaScreenActionHandler, PrizmaScreenOverrides } from './types';
4
+ import type { OcrReviewStrings } from './OcrReviewStrings';
5
+ import './ScreenLayout.css';
6
+
7
+ export interface OcrReviewErrorScreenProps
8
+ extends Omit<
9
+ PrizmaResultScreenProps,
10
+ 'status' | 'title' | 'ctaLabel' | 'verifiedLabel' | 'navLabel'
11
+ > {
12
+ /** Module copy — this screen reads the `error` slice. */
13
+ strings: OcrReviewStrings;
14
+ screenId?: string;
15
+ overrides?: PrizmaScreenOverrides;
16
+ onAction?: PrizmaScreenActionHandler;
17
+ }
18
+
19
+ /**
20
+ * OCR Review — "Something went wrong", built on Archetype F (GUIDELINES.md
21
+ * §6-F, `PrizmaResultScreen`). Figma: `OCR Error` (31084:18797), drawn OUTSIDE
22
+ * the Happy Path section and reached off the "Processed successfully?"
23
+ * decision's "No" branch — a plain status + title + "Try again" CTA.
24
+ *
25
+ * Nav and footer tag are left at the archetype's DEFAULT (shown). The frame
26
+ * itself draws neither, matching `DigitalIdUploadFileTooLargeScreen.tsx` —
27
+ * but that screen is the ONE exception in the whole package, not the pattern:
28
+ * every other error screen (`EkycErrorScreen`, `EkybErrorScreen`,
29
+ * `EmailInputErrorScreen`, `FormsErrorScreen`, `IdCaptureDocumentErrorScreen`)
30
+ * keeps both. Hiding them here, with only one CTA to balance the bottom,
31
+ * pushed the status + title below where every sibling error screen centres it
32
+ * (Mili, 2026-10-12 — checked against the system's own screens, not re-derived
33
+ * from the frame).
34
+ */
35
+ export const OcrReviewErrorScreen = forwardRef<HTMLDivElement, OcrReviewErrorScreenProps>(
36
+ ({ strings, screenId = 'ocr-review-error', overrides, onAction, ...shell }, ref) => (
37
+ <PrizmaResultScreen
38
+ ref={ref}
39
+ status="error"
40
+ title={strings.error.title}
41
+ ctaLabel={strings.error.ctaLabel}
42
+ verifiedLabel={strings.verifiedLabel}
43
+ navLabel={strings.navLabel}
44
+ screenId={screenId}
45
+ overrides={overrides}
46
+ onAction={onAction}
47
+ {...shell}
48
+ />
49
+ ),
50
+ );
51
+ OcrReviewErrorScreen.displayName = 'OcrReviewErrorScreen';
52
+
53
+ export default OcrReviewErrorScreen;
@@ -0,0 +1,24 @@
1
+ /* OCR Review — the one piece of chrome the archetype doesn't own.
2
+ *
3
+ * `PrizmaFormScreen.media` places whatever the module hands it; the circular
4
+ * crop and fixed size are the module's own, same split `progress` already
5
+ * draws (the archetype positions a `PrizmaStepper`, never sizes it). 90×90,
6
+ * centred — Figma's `Image / Selfie` instance, read straight off the frame. A
7
+ * `fields` row defaults to `align-items: stretch` (FormScreen.css), so the
8
+ * thumbnail is the one row that opts itself out with `align-self`.
9
+ */
10
+ .ocr-review__photo {
11
+ width: 90px;
12
+ height: 90px;
13
+ flex-shrink: 0;
14
+ align-self: center;
15
+ border-radius: var(--prizma-border-radius-full);
16
+ overflow: hidden;
17
+ }
18
+
19
+ .ocr-review__photo img {
20
+ display: block;
21
+ width: 100%;
22
+ height: 100%;
23
+ object-fit: cover;
24
+ }