facecog-liveness-showcase 0.0.1

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 (229) hide show
  1. package/.browserslistrc +15 -0
  2. package/.dockerignore +48 -0
  3. package/.editorconfig +16 -0
  4. package/.eslintrc.json +47 -0
  5. package/.vercelignore +7 -0
  6. package/.vscode/extensions.json +5 -0
  7. package/.vscode/settings.json +3 -0
  8. package/DOCKER.md +221 -0
  9. package/Dockerfile +33 -0
  10. package/README.md +268 -0
  11. package/angular.json +156 -0
  12. package/capacitor.config.ts +9 -0
  13. package/docker-compose.dev.yml +20 -0
  14. package/docker-compose.yml +18 -0
  15. package/ionic.config.json +7 -0
  16. package/jest.config.js +38 -0
  17. package/nginx.conf +50 -0
  18. package/package.json +131 -0
  19. package/patches/ng-packagr+20.3.2.patch +60 -0
  20. package/projects/facecog-liveness-verification/README.md +295 -0
  21. package/projects/facecog-liveness-verification/ng-package.json +7 -0
  22. package/projects/facecog-liveness-verification/package.json +48 -0
  23. package/projects/facecog-liveness-verification/scripts/build-with-wrapper-copy.js +38 -0
  24. package/projects/facecog-liveness-verification/scripts/copy-wrapper-after-ngc.js +35 -0
  25. package/projects/facecog-liveness-verification/sources/FaceLivenessReactWrapper.tsx +320 -0
  26. package/projects/facecog-liveness-verification/src/lib/components/aws-face-liveness/FaceLivenessReactWrapper.generated.d.ts +28 -0
  27. package/projects/facecog-liveness-verification/src/lib/components/aws-face-liveness/FaceLivenessReactWrapper.generated.js +247 -0
  28. package/projects/facecog-liveness-verification/src/lib/components/aws-face-liveness/FaceLivenessReactWrapper.generated.js.map +1 -0
  29. package/projects/facecog-liveness-verification/src/lib/components/aws-face-liveness/FaceLivenessReactWrapper.js.map +1 -0
  30. package/projects/facecog-liveness-verification/src/lib/components/aws-face-liveness/FaceLivenessReactWrapper.ts +5 -0
  31. package/projects/facecog-liveness-verification/src/lib/components/aws-face-liveness/aws-face-liveness.component.ts +500 -0
  32. package/projects/facecog-liveness-verification/src/lib/components/camera-permission/camera-permission.component.html +41 -0
  33. package/projects/facecog-liveness-verification/src/lib/components/camera-permission/camera-permission.component.scss +234 -0
  34. package/projects/facecog-liveness-verification/src/lib/components/camera-permission/camera-permission.component.spec.ts +158 -0
  35. package/projects/facecog-liveness-verification/src/lib/components/camera-permission/camera-permission.component.ts +58 -0
  36. package/projects/facecog-liveness-verification/src/lib/components/camera-verification/camera-verification.component.html +34 -0
  37. package/projects/facecog-liveness-verification/src/lib/components/camera-verification/camera-verification.component.ts +210 -0
  38. package/projects/facecog-liveness-verification/src/lib/components/dialogs/save-custom-pose-dialog.component.ts +174 -0
  39. package/projects/facecog-liveness-verification/src/lib/components/facetec-scan/facetec-scan.component.html +45 -0
  40. package/projects/facecog-liveness-verification/src/lib/components/facetec-scan/facetec-scan.component.scss +87 -0
  41. package/projects/facecog-liveness-verification/src/lib/components/facetec-scan/facetec-scan.component.ts +182 -0
  42. package/projects/facecog-liveness-verification/src/lib/components/intro/intro.component.html +394 -0
  43. package/projects/facecog-liveness-verification/src/lib/components/intro/intro.component.scss +1567 -0
  44. package/projects/facecog-liveness-verification/src/lib/components/intro/intro.component.spec.ts +699 -0
  45. package/projects/facecog-liveness-verification/src/lib/components/intro/intro.component.ts +721 -0
  46. package/projects/facecog-liveness-verification/src/lib/components/live-preview/live-preview.component.html +120 -0
  47. package/projects/facecog-liveness-verification/src/lib/components/live-preview/live-preview.component.scss +611 -0
  48. package/projects/facecog-liveness-verification/src/lib/components/live-preview/live-preview.component.spec.ts +605 -0
  49. package/projects/facecog-liveness-verification/src/lib/components/live-preview/live-preview.component.ts +524 -0
  50. package/projects/facecog-liveness-verification/src/lib/components/liveness-flow/liveness-flow.component.html +73 -0
  51. package/projects/facecog-liveness-verification/src/lib/components/liveness-flow/liveness-flow.component.scss +19 -0
  52. package/projects/facecog-liveness-verification/src/lib/components/liveness-flow/liveness-flow.component.spec.ts +673 -0
  53. package/projects/facecog-liveness-verification/src/lib/components/liveness-flow/liveness-flow.component.ts +963 -0
  54. package/projects/facecog-liveness-verification/src/lib/components/liveness-verification/liveness-verification.component.html +38 -0
  55. package/projects/facecog-liveness-verification/src/lib/components/liveness-verification/liveness-verification.component.scss +10 -0
  56. package/projects/facecog-liveness-verification/src/lib/components/liveness-verification/liveness-verification.component.ts +233 -0
  57. package/projects/facecog-liveness-verification/src/lib/components/pose-selection/pose-selection.component.html +17 -0
  58. package/projects/facecog-liveness-verification/src/lib/components/pose-selection/pose-selection.component.spec.ts +35 -0
  59. package/projects/facecog-liveness-verification/src/lib/components/pose-selection/pose-selection.component.ts +33 -0
  60. package/projects/facecog-liveness-verification/src/lib/components/processing/processing.component.html +17 -0
  61. package/projects/facecog-liveness-verification/src/lib/components/processing/processing.component.scss +156 -0
  62. package/projects/facecog-liveness-verification/src/lib/components/processing/processing.component.spec.ts +46 -0
  63. package/projects/facecog-liveness-verification/src/lib/components/processing/processing.component.ts +18 -0
  64. package/projects/facecog-liveness-verification/src/lib/components/verification-result/verification-result.component.html +190 -0
  65. package/projects/facecog-liveness-verification/src/lib/components/verification-result/verification-result.component.scss +534 -0
  66. package/projects/facecog-liveness-verification/src/lib/components/verification-result/verification-result.component.spec.ts +286 -0
  67. package/projects/facecog-liveness-verification/src/lib/components/verification-result/verification-result.component.ts +155 -0
  68. package/projects/facecog-liveness-verification/src/lib/interfaces/analyze-response.interface.ts +16 -0
  69. package/projects/facecog-liveness-verification/src/lib/interfaces/aws-face-liveness.interface.ts +46 -0
  70. package/projects/facecog-liveness-verification/src/lib/interfaces/backend-adapter.interface.ts +21 -0
  71. package/projects/facecog-liveness-verification/src/lib/interfaces/backend-http-client.interface.ts +93 -0
  72. package/projects/facecog-liveness-verification/src/lib/interfaces/backend-response.interface.ts +9 -0
  73. package/projects/facecog-liveness-verification/src/lib/interfaces/camera-provider.interface.ts +107 -0
  74. package/projects/facecog-liveness-verification/src/lib/interfaces/category-info.interface.ts +9 -0
  75. package/projects/facecog-liveness-verification/src/lib/interfaces/custom-pose-data.interface.ts +14 -0
  76. package/projects/facecog-liveness-verification/src/lib/interfaces/custom-pose-repository.interface.ts +48 -0
  77. package/projects/facecog-liveness-verification/src/lib/interfaces/custom-pose-response.interface.ts +14 -0
  78. package/projects/facecog-liveness-verification/src/lib/interfaces/index.ts +52 -0
  79. package/projects/facecog-liveness-verification/src/lib/interfaces/liveness-action-result.interface.ts +13 -0
  80. package/projects/facecog-liveness-verification/src/lib/interfaces/liveness-config.interface.ts +17 -0
  81. package/projects/facecog-liveness-verification/src/lib/interfaces/liveness-metadata.interface.ts +17 -0
  82. package/projects/facecog-liveness-verification/src/lib/interfaces/liveness-result.interface.ts +24 -0
  83. package/projects/facecog-liveness-verification/src/lib/interfaces/liveness-verification-config.interface.ts +41 -0
  84. package/projects/facecog-liveness-verification/src/lib/interfaces/multi-backend-analyze-response.interface.ts +21 -0
  85. package/projects/facecog-liveness-verification/src/lib/interfaces/multi-backend-liveness-result.interface.ts +14 -0
  86. package/projects/facecog-liveness-verification/src/lib/interfaces/pose-definition.interface.ts +35 -0
  87. package/projects/facecog-liveness-verification/src/lib/interfaces/pose-keypoint.interface.ts +12 -0
  88. package/projects/facecog-liveness-verification/src/lib/interfaces/pose-match-result.interface.ts +9 -0
  89. package/projects/facecog-liveness-verification/src/lib/interfaces/pose-verify-response.interface.ts +8 -0
  90. package/projects/facecog-liveness-verification/src/lib/interfaces/scan-results.interface.ts +29 -0
  91. package/projects/facecog-liveness-verification/src/lib/interfaces/verification-plan.interface.ts +42 -0
  92. package/projects/facecog-liveness-verification/src/lib/interfaces/verification-progress-event.interface.ts +12 -0
  93. package/projects/facecog-liveness-verification/src/lib/interfaces/verification-session.interface.ts +72 -0
  94. package/projects/facecog-liveness-verification/src/lib/interfaces/verification-step-change-event.interface.ts +11 -0
  95. package/projects/facecog-liveness-verification/src/lib/interfaces/video-recording.interface.ts +9 -0
  96. package/projects/facecog-liveness-verification/src/lib/liveness-verification.module.ts +123 -0
  97. package/projects/facecog-liveness-verification/src/lib/models/constants/aws-face-liveness-component.token.ts +23 -0
  98. package/projects/facecog-liveness-verification/src/lib/models/constants/category-info.constant.ts +14 -0
  99. package/projects/facecog-liveness-verification/src/lib/models/constants/default-liveness-config.constant.ts +18 -0
  100. package/projects/facecog-liveness-verification/src/lib/models/constants/index.ts +5 -0
  101. package/projects/facecog-liveness-verification/src/lib/models/constants/liveness-verification-config.token.ts +16 -0
  102. package/projects/facecog-liveness-verification/src/lib/models/constants/pose-definitions.constant.ts +377 -0
  103. package/projects/facecog-liveness-verification/src/lib/models/index.ts +5 -0
  104. package/projects/facecog-liveness-verification/src/lib/models/utils/index.ts +2 -0
  105. package/projects/facecog-liveness-verification/src/lib/models/utils/pose.utils.spec.ts +76 -0
  106. package/projects/facecog-liveness-verification/src/lib/models/utils/pose.utils.ts +59 -0
  107. package/projects/facecog-liveness-verification/src/lib/services/aws-face-liveness.service.ts +49 -0
  108. package/projects/facecog-liveness-verification/src/lib/services/backend-http.service.spec.ts +111 -0
  109. package/projects/facecog-liveness-verification/src/lib/services/backend-http.service.ts +130 -0
  110. package/projects/facecog-liveness-verification/src/lib/services/backends/azure-backend.service.spec.ts +69 -0
  111. package/projects/facecog-liveness-verification/src/lib/services/backends/azure-backend.service.ts +72 -0
  112. package/projects/facecog-liveness-verification/src/lib/services/backends/facetec-backend.service.spec.ts +24 -0
  113. package/projects/facecog-liveness-verification/src/lib/services/backends/facetec-backend.service.ts +35 -0
  114. package/projects/facecog-liveness-verification/src/lib/services/backends/mock-backend.service.spec.ts +36 -0
  115. package/projects/facecog-liveness-verification/src/lib/services/backends/mock-backend.service.ts +39 -0
  116. package/projects/facecog-liveness-verification/src/lib/services/backends/openpose-backend.service.spec.ts +81 -0
  117. package/projects/facecog-liveness-verification/src/lib/services/backends/openpose-backend.service.ts +72 -0
  118. package/projects/facecog-liveness-verification/src/lib/services/backends/rekognition-analysis-backend.service.spec.ts +69 -0
  119. package/projects/facecog-liveness-verification/src/lib/services/backends/rekognition-analysis-backend.service.ts +83 -0
  120. package/projects/facecog-liveness-verification/src/lib/services/camera.service.spec.ts +200 -0
  121. package/projects/facecog-liveness-verification/src/lib/services/camera.service.ts +155 -0
  122. package/projects/facecog-liveness-verification/src/lib/services/custom-poses-api.service.ts +117 -0
  123. package/projects/facecog-liveness-verification/src/lib/services/index.ts +18 -0
  124. package/projects/facecog-liveness-verification/src/lib/services/liveness-backend.service.spec.ts +103 -0
  125. package/projects/facecog-liveness-verification/src/lib/services/liveness-backend.service.ts +61 -0
  126. package/projects/facecog-liveness-verification/src/lib/services/liveness-config.service.spec.ts +109 -0
  127. package/projects/facecog-liveness-verification/src/lib/services/liveness-config.service.ts +70 -0
  128. package/projects/facecog-liveness-verification/src/lib/services/liveness-orchestrator.service.spec.ts +144 -0
  129. package/projects/facecog-liveness-verification/src/lib/services/liveness-orchestrator.service.ts +162 -0
  130. package/projects/facecog-liveness-verification/src/lib/services/pose-detection/hand-gesture-detection.service.ts +315 -0
  131. package/projects/facecog-liveness-verification/src/lib/services/pose-detection/index.ts +5 -0
  132. package/projects/facecog-liveness-verification/src/lib/services/pose-detection/openpose.service.ts +287 -0
  133. package/projects/facecog-liveness-verification/src/lib/services/pose-detection/pose-comparison.service.ts +353 -0
  134. package/projects/facecog-liveness-verification/src/lib/services/pose-detection/pose-matching.service.ts +2370 -0
  135. package/projects/facecog-liveness-verification/src/lib/services/pose-detection/reference-pose.service.ts +271 -0
  136. package/projects/facecog-liveness-verification/src/lib/services/pose-selection.service.spec.ts +183 -0
  137. package/projects/facecog-liveness-verification/src/lib/services/pose-selection.service.ts +179 -0
  138. package/projects/facecog-liveness-verification/src/lib/services/verification-api.service.spec.ts +159 -0
  139. package/projects/facecog-liveness-verification/src/lib/services/verification-api.service.ts +151 -0
  140. package/projects/facecog-liveness-verification/src/lib/services/verification-plan.service.spec.ts +184 -0
  141. package/projects/facecog-liveness-verification/src/lib/services/verification-plan.service.ts +94 -0
  142. package/projects/facecog-liveness-verification/src/lib/services/video-recorder.service.spec.ts +52 -0
  143. package/projects/facecog-liveness-verification/src/lib/services/video-recorder.service.ts +117 -0
  144. package/projects/facecog-liveness-verification/src/lib/types/detection-strategy.type.ts +5 -0
  145. package/projects/facecog-liveness-verification/src/lib/types/index.ts +7 -0
  146. package/projects/facecog-liveness-verification/src/lib/types/liveness-action.type.ts +31 -0
  147. package/projects/facecog-liveness-verification/src/lib/types/liveness-backend.type.ts +5 -0
  148. package/projects/facecog-liveness-verification/src/lib/types/pose-category.type.ts +5 -0
  149. package/projects/facecog-liveness-verification/src/lib/types/pose-difficulty.type.ts +5 -0
  150. package/projects/facecog-liveness-verification/src/lib/types/verification-flow-step.type.ts +5 -0
  151. package/projects/facecog-liveness-verification/src/lib/types/verification-step-kind.type.ts +4 -0
  152. package/projects/facecog-liveness-verification/src/public-api.ts +150 -0
  153. package/projects/facecog-liveness-verification/tsconfig.lib.json +20 -0
  154. package/projects/facecog-liveness-verification/tsconfig.lib.prod.json +11 -0
  155. package/projects/facecog-liveness-verification/tsconfig.spec.json +13 -0
  156. package/projects/facecog-liveness-verification/tsconfig.wrapper.json +15 -0
  157. package/projects/facecog-liveness-verification-test/src/app/app-routing.module.ts +22 -0
  158. package/projects/facecog-liveness-verification-test/src/app/app.component.html +3 -0
  159. package/projects/facecog-liveness-verification-test/src/app/app.component.scss +0 -0
  160. package/projects/facecog-liveness-verification-test/src/app/app.component.ts +11 -0
  161. package/projects/facecog-liveness-verification-test/src/app/app.module.ts +27 -0
  162. package/projects/facecog-liveness-verification-test/src/app/home/home-routing.module.ts +16 -0
  163. package/projects/facecog-liveness-verification-test/src/app/home/home.module.ts +19 -0
  164. package/projects/facecog-liveness-verification-test/src/app/home/home.page.html +39 -0
  165. package/projects/facecog-liveness-verification-test/src/app/home/home.page.scss +97 -0
  166. package/projects/facecog-liveness-verification-test/src/app/home/home.page.spec.ts +24 -0
  167. package/projects/facecog-liveness-verification-test/src/app/home/home.page.ts +92 -0
  168. package/projects/facecog-liveness-verification-test/src/app/home/verification-modal.component.ts +106 -0
  169. package/projects/facecog-liveness-verification-test/src/assets/fonts/gilroy/Gilroy-Bold_0.ttf +0 -0
  170. package/projects/facecog-liveness-verification-test/src/assets/fonts/gilroy/Gilroy-Medium_0.ttf +0 -0
  171. package/projects/facecog-liveness-verification-test/src/assets/fonts/gilroy/Gilroy-Regular_0.ttf +0 -0
  172. package/projects/facecog-liveness-verification-test/src/assets/fonts/gilroy/Gilroy-SemiBold_0.ttf +0 -0
  173. package/projects/facecog-liveness-verification-test/src/assets/fonts/gilroy/Gilroy-Thin_0.ttf +0 -0
  174. package/projects/facecog-liveness-verification-test/src/assets/icon/favicon.png +0 -0
  175. package/projects/facecog-liveness-verification-test/src/assets/images/poses/Five_Fingers_Left.jpg +0 -0
  176. package/projects/facecog-liveness-verification-test/src/assets/images/poses/Left_Palm.jpg +0 -0
  177. package/projects/facecog-liveness-verification-test/src/assets/images/poses/Ok_Sign_Right.jpg +0 -0
  178. package/projects/facecog-liveness-verification-test/src/assets/images/poses/Peace_Sign_Left.jpg +0 -0
  179. package/projects/facecog-liveness-verification-test/src/assets/images/poses/README.md +77 -0
  180. package/projects/facecog-liveness-verification-test/src/assets/images/poses/Right_Palm.jpg +0 -0
  181. package/projects/facecog-liveness-verification-test/src/assets/images/poses/Speak_Phrase.jpg +0 -0
  182. package/projects/facecog-liveness-verification-test/src/assets/images/poses/Three_Fingers_Right.jpg +0 -0
  183. package/projects/facecog-liveness-verification-test/src/assets/images/poses/Thumbs_Up_Left.jpg +0 -0
  184. package/projects/facecog-liveness-verification-test/src/assets/images/poses/Thumbs_Up_Right.jpg +0 -0
  185. package/projects/facecog-liveness-verification-test/src/assets/images/poses/Wave_Right.jpg +0 -0
  186. package/projects/facecog-liveness-verification-test/src/assets/images/poses/blink.jpeg +0 -0
  187. package/projects/facecog-liveness-verification-test/src/assets/images/poses/blink_twice.jpeg +0 -0
  188. package/projects/facecog-liveness-verification-test/src/assets/images/poses/center_face.png +0 -0
  189. package/projects/facecog-liveness-verification-test/src/assets/images/poses/clap.jpeg +0 -0
  190. package/projects/facecog-liveness-verification-test/src/assets/images/poses/cover_mouth.png +0 -0
  191. package/projects/facecog-liveness-verification-test/src/assets/images/poses/cover_right_eye.png +0 -0
  192. package/projects/facecog-liveness-verification-test/src/assets/images/poses/cross_arms.png +0 -0
  193. package/projects/facecog-liveness-verification-test/src/assets/images/poses/face_straight.png +0 -0
  194. package/projects/facecog-liveness-verification-test/src/assets/images/poses/follow_dot.png +0 -0
  195. package/projects/facecog-liveness-verification-test/src/assets/images/poses/look_down.png +0 -0
  196. package/projects/facecog-liveness-verification-test/src/assets/images/poses/look_up.png +0 -0
  197. package/projects/facecog-liveness-verification-test/src/assets/images/poses/move_closer.png +0 -0
  198. package/projects/facecog-liveness-verification-test/src/assets/images/poses/nod.png +0 -0
  199. package/projects/facecog-liveness-verification-test/src/assets/images/poses/open_mouth.png +0 -0
  200. package/projects/facecog-liveness-verification-test/src/assets/images/poses/raise_eyebrow.png +0 -0
  201. package/projects/facecog-liveness-verification-test/src/assets/images/poses/rotate_face.jpeg +0 -0
  202. package/projects/facecog-liveness-verification-test/src/assets/images/poses/shake_head.jpeg +0 -0
  203. package/projects/facecog-liveness-verification-test/src/assets/images/poses/smile.png +0 -0
  204. package/projects/facecog-liveness-verification-test/src/assets/images/poses/tilt_left.png +0 -0
  205. package/projects/facecog-liveness-verification-test/src/assets/images/poses/tilt_right.png +0 -0
  206. package/projects/facecog-liveness-verification-test/src/assets/images/poses/touch_chin_left.jpg +0 -0
  207. package/projects/facecog-liveness-verification-test/src/assets/images/poses/touch_left_cheek.jpeg +0 -0
  208. package/projects/facecog-liveness-verification-test/src/assets/images/poses/touch_nose_right.png +0 -0
  209. package/projects/facecog-liveness-verification-test/src/assets/images/poses/touch_right_cheek.jpeg +0 -0
  210. package/projects/facecog-liveness-verification-test/src/assets/images/poses/turn_left.png +0 -0
  211. package/projects/facecog-liveness-verification-test/src/assets/images/poses/turn_right.png +0 -0
  212. package/projects/facecog-liveness-verification-test/src/assets/images/poses/wink.jpeg +0 -0
  213. package/projects/facecog-liveness-verification-test/src/assets/images/reference-pose.jpg +0 -0
  214. package/projects/facecog-liveness-verification-test/src/assets/shapes.svg +1 -0
  215. package/projects/facecog-liveness-verification-test/src/environments/environment.prod.ts +4 -0
  216. package/projects/facecog-liveness-verification-test/src/environments/environment.ts +17 -0
  217. package/projects/facecog-liveness-verification-test/src/global.scss +288 -0
  218. package/projects/facecog-liveness-verification-test/src/index.html +31 -0
  219. package/projects/facecog-liveness-verification-test/src/main.ts +6 -0
  220. package/projects/facecog-liveness-verification-test/src/polyfills.ts +55 -0
  221. package/projects/facecog-liveness-verification-test/src/theme/nextsapien-theme.scss +174 -0
  222. package/projects/facecog-liveness-verification-test/src/theme/variables.scss +2 -0
  223. package/projects/facecog-liveness-verification-test/src/zone-flags.ts +6 -0
  224. package/projects/facecog-liveness-verification-test/tsconfig.app.json +15 -0
  225. package/projects/facecog-liveness-verification-test/tsconfig.spec.json +14 -0
  226. package/setup-jest.ts +118 -0
  227. package/tsconfig.json +41 -0
  228. package/tsconfig.spec.json +15 -0
  229. package/vercel.json +24 -0
@@ -0,0 +1,1567 @@
1
+ :host {
2
+ display: flex;
3
+ flex-direction: column;
4
+ height: 100%;
5
+ width: 100%;
6
+ }
7
+
8
+ .intro-scroll-wrapper {
9
+ overflow-y: auto;
10
+ flex: 1;
11
+ padding: 16px;
12
+ padding-bottom: 32px;
13
+ background: var(--ion-background-color, #fff);
14
+ -webkit-overflow-scrolling: touch;
15
+ }
16
+
17
+ .intro-container {
18
+ display: flex;
19
+ flex-direction: column;
20
+ align-items: center;
21
+ padding: 24px;
22
+ background: var(--ion-background-color);
23
+ }
24
+
25
+ .content-wrapper {
26
+ display: flex;
27
+ flex-direction: column;
28
+ align-items: center;
29
+ width: 100%;
30
+ max-width: 480px;
31
+ }
32
+
33
+ .icon-container {
34
+ margin: 0 0 32px;
35
+ animation: fadeInScale 0.5s ease-out;
36
+
37
+ .shield-icon {
38
+ font-size: 120px;
39
+ filter: drop-shadow(0 4px 12px rgba(var(--ion-color-primary-rgb), 0.3));
40
+ }
41
+ }
42
+
43
+ .actions-list {
44
+ margin: 24px auto;
45
+ width: 100%;
46
+ max-width: 320px;
47
+ display: flex;
48
+ flex-direction: column;
49
+ align-items: center;
50
+
51
+ .action-item {
52
+ display: flex;
53
+ align-items: center;
54
+ justify-content: flex-start;
55
+ gap: 16px;
56
+ padding: 12px 16px;
57
+ margin: 8px 0;
58
+ width: 100%;
59
+ background: var(--ion-color-light);
60
+ border-radius: 12px;
61
+ transition: transform 0.2s ease, box-shadow 0.2s ease;
62
+
63
+ ion-icon {
64
+ font-size: 24px;
65
+ flex-shrink: 0;
66
+ }
67
+
68
+ span {
69
+ font-size: 15px;
70
+ font-weight: 500;
71
+ color: var(--ion-text-color);
72
+ }
73
+
74
+ &:hover {
75
+ transform: translateX(4px);
76
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
77
+ }
78
+ }
79
+ }
80
+
81
+ .tip {
82
+ margin-top: 24px;
83
+ font-size: 14px !important;
84
+ font-style: italic;
85
+ color: var(--ion-color-medium) !important;
86
+ }
87
+
88
+ .instruction-text {
89
+ text-align: center;
90
+ margin: 0 0 40px;
91
+ width: 100%;
92
+
93
+ h2 {
94
+ color: var(--ion-color-primary);
95
+ margin-bottom: 20px;
96
+ font-size: 28px;
97
+ font-weight: 700;
98
+ letter-spacing: -0.5px;
99
+ }
100
+
101
+ p {
102
+ color: var(--ion-color-medium);
103
+ line-height: 1.7;
104
+ margin: 10px 0;
105
+ font-size: 16px;
106
+ font-weight: 400;
107
+
108
+ &:first-of-type {
109
+ font-size: 17px;
110
+ color: var(--ion-text-color);
111
+ font-weight: 500;
112
+ }
113
+ }
114
+ }
115
+
116
+ .button-container {
117
+ width: 100%;
118
+ max-width: 320px;
119
+ display: flex;
120
+ flex-direction: column;
121
+ align-items: center;
122
+ gap: 16px;
123
+ margin: 0 auto;
124
+
125
+ ion-button {
126
+ width: 100%;
127
+ }
128
+
129
+ .cancel-link {
130
+ background: none;
131
+ border: none;
132
+ color: var(--ion-color-medium);
133
+ font-size: 15px;
134
+ font-weight: 500;
135
+ padding: 12px 16px;
136
+ cursor: pointer;
137
+ transition: color 0.2s ease;
138
+ text-decoration: none;
139
+
140
+ &:hover {
141
+ color: var(--ion-color-primary);
142
+ text-decoration: underline;
143
+ }
144
+
145
+ &:active {
146
+ opacity: 0.7;
147
+ }
148
+ }
149
+ }
150
+
151
+ @keyframes fadeInScale {
152
+ 0% {
153
+ opacity: 0;
154
+ transform: scale(0.9);
155
+ }
156
+ 100% {
157
+ opacity: 1;
158
+ transform: scale(1);
159
+ }
160
+ }
161
+
162
+ @media (max-width: 768px) {
163
+ .example-image-container,
164
+ .example-image-placeholder {
165
+ width: 240px;
166
+ height: 240px;
167
+ }
168
+
169
+ .instruction-text {
170
+ h2 {
171
+ font-size: 24px;
172
+ }
173
+
174
+ p {
175
+ font-size: 15px;
176
+
177
+ &:first-of-type {
178
+ font-size: 16px;
179
+ }
180
+ }
181
+ }
182
+ }
183
+
184
+ // Pose Selection Section
185
+ .pose-selection-section {
186
+ width: 100%;
187
+ max-width: 900px;
188
+ margin: 32px auto;
189
+ padding: 24px;
190
+ background: var(--ion-color-light);
191
+ border-radius: 16px;
192
+ overflow: visible;
193
+
194
+ h3 {
195
+ font-size: 20px;
196
+ font-weight: 600;
197
+ color: var(--ion-text-color);
198
+ margin: 0 0 8px;
199
+ text-align: center;
200
+ }
201
+
202
+ .section-description {
203
+ font-size: 14px;
204
+ color: var(--ion-color-medium);
205
+ text-align: center;
206
+ margin: 0 0 24px;
207
+ }
208
+ }
209
+
210
+ // Selected Pose Display
211
+ .selected-pose-display {
212
+ margin-bottom: 24px;
213
+
214
+ .selected-badge {
215
+ display: flex;
216
+ align-items: center;
217
+ gap: 8px;
218
+ justify-content: center;
219
+ margin-bottom: 12px;
220
+ color: var(--ion-color-success);
221
+ font-weight: 600;
222
+ font-size: 14px;
223
+
224
+ ion-icon {
225
+ font-size: 24px;
226
+ }
227
+ }
228
+
229
+ .selected-pose-card {
230
+ display: flex;
231
+ flex-direction: row;
232
+ align-items: center;
233
+ gap: 16px;
234
+ padding: 16px;
235
+ background: var(--ion-background-color);
236
+ border-radius: 12px;
237
+ border: 2px solid var(--ion-color-success);
238
+ box-shadow: 0 4px 12px rgba(var(--ion-color-success-rgb), 0.2);
239
+
240
+ .pose-image-container {
241
+ position: relative;
242
+ width: 80px;
243
+ height: 80px;
244
+ flex-shrink: 0;
245
+ border-radius: 8px;
246
+ overflow: hidden;
247
+ background: var(--ion-color-light);
248
+
249
+ img {
250
+ width: 100%;
251
+ height: 100%;
252
+ object-fit: cover;
253
+ }
254
+
255
+ .fallback-icon {
256
+ position: absolute;
257
+ top: 50%;
258
+ left: 50%;
259
+ transform: translate(-50%, -50%);
260
+ font-size: 40px;
261
+ display: none; // Hide icon overlay
262
+ }
263
+ }
264
+
265
+ .pose-details {
266
+ flex: 1;
267
+ min-width: 0;
268
+ overflow: hidden;
269
+
270
+ h4 {
271
+ font-size: 16px;
272
+ font-weight: 600;
273
+ margin: 0 0 4px;
274
+ color: var(--ion-text-color);
275
+ white-space: normal;
276
+ word-break: break-word;
277
+ overflow-wrap: break-word;
278
+ display: block;
279
+ }
280
+
281
+ p {
282
+ font-size: 13px;
283
+ color: var(--ion-color-medium);
284
+ margin: 0 0 8px;
285
+ line-height: 1.4;
286
+ white-space: normal;
287
+ word-break: break-word;
288
+ overflow-wrap: break-word;
289
+ display: block;
290
+ }
291
+
292
+ .pose-badges {
293
+ display: flex;
294
+ gap: 6px;
295
+ flex-wrap: wrap;
296
+ }
297
+ }
298
+ }
299
+
300
+ .change-pose-link {
301
+ background: none;
302
+ border: none;
303
+ color: var(--ion-color-primary);
304
+ font-size: 14px;
305
+ font-weight: 500;
306
+ padding: 8px 0;
307
+ cursor: pointer;
308
+ transition: color 0.2s ease;
309
+ text-decoration: underline;
310
+ text-align: center;
311
+ margin-top: 8px;
312
+
313
+ &:hover {
314
+ color: var(--ion-color-primary-shade);
315
+ opacity: 0.8;
316
+ }
317
+
318
+ &:active {
319
+ opacity: 0.6;
320
+ }
321
+ }
322
+ }
323
+
324
+ // Filters Container
325
+ .filters-container {
326
+ margin-bottom: 20px;
327
+ width: 100%;
328
+
329
+ .filter-header {
330
+ display: flex;
331
+ justify-content: space-between;
332
+ align-items: center;
333
+ margin-bottom: 12px;
334
+ gap: 12px;
335
+ width: 100%;
336
+
337
+ > ion-button {
338
+ flex: 0 1 auto;
339
+ white-space: nowrap;
340
+ overflow: visible;
341
+
342
+ ion-icon {
343
+ flex-shrink: 0;
344
+ }
345
+ }
346
+
347
+ .view-toggle {
348
+ display: flex;
349
+ gap: 8px;
350
+ align-items: center;
351
+ flex-shrink: 0;
352
+ margin-left: auto;
353
+
354
+ ion-button {
355
+ --padding-start: 10px;
356
+ --padding-end: 10px;
357
+ margin: 0;
358
+ width: 44px;
359
+ height: 44px;
360
+
361
+ ion-icon {
362
+ font-size: 20px;
363
+ }
364
+ }
365
+ }
366
+ }
367
+
368
+ .filters-content {
369
+ padding: 16px;
370
+ background: var(--ion-background-color);
371
+ border-radius: 12px;
372
+ margin-top: 12px;
373
+
374
+ ion-searchbar {
375
+ padding: 0 0 16px;
376
+ }
377
+
378
+ .filter-group {
379
+ margin-bottom: 16px;
380
+
381
+ label {
382
+ display: block;
383
+ font-size: 14px;
384
+ font-weight: 600;
385
+ color: var(--ion-text-color);
386
+ margin-bottom: 8px;
387
+ }
388
+
389
+ .filter-chips {
390
+ display: flex;
391
+ flex-wrap: wrap;
392
+ gap: 8px;
393
+
394
+ ion-chip {
395
+ cursor: pointer;
396
+ transition: all 0.2s ease;
397
+
398
+ &:hover {
399
+ transform: translateY(-2px);
400
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
401
+ }
402
+ }
403
+ }
404
+ }
405
+ }
406
+ }
407
+
408
+ // Results Count
409
+ .results-count {
410
+ font-size: 13px;
411
+ color: var(--ion-color-medium);
412
+ text-align: center;
413
+ margin: 0 0 16px;
414
+ font-weight: 500;
415
+ }
416
+
417
+ // Pose Grid
418
+ .pose-grid {
419
+ display: grid;
420
+ grid-template-columns: repeat(auto-fill, minmax(120px, 1fr));
421
+ gap: 16px;
422
+
423
+ .pose-card {
424
+ position: relative;
425
+ background: var(--ion-background-color);
426
+ border-radius: 12px;
427
+ padding: 12px;
428
+ cursor: pointer;
429
+ transition: all 0.3s ease;
430
+ border: 2px solid transparent;
431
+
432
+ &:hover {
433
+ transform: translateY(-4px);
434
+ box-shadow: 0 8px 24px rgba(0, 0, 0, 0.12);
435
+ border-color: var(--ion-color-primary);
436
+ }
437
+
438
+ &.selected {
439
+ border-color: var(--ion-color-success);
440
+ background: rgba(var(--ion-color-success-rgb), 0.05);
441
+ box-shadow: 0 4px 16px rgba(var(--ion-color-success-rgb), 0.3);
442
+ }
443
+
444
+ .pose-image-container {
445
+ position: relative;
446
+ width: 100%;
447
+ padding-bottom: 100%; // 1:1 aspect ratio
448
+ background: var(--ion-color-light);
449
+ border-radius: 8px;
450
+ overflow: hidden;
451
+ margin-bottom: 8px;
452
+
453
+ img {
454
+ position: absolute;
455
+ top: 0;
456
+ left: 0;
457
+ width: 100%;
458
+ height: 100%;
459
+ object-fit: cover;
460
+ }
461
+
462
+ .fallback-icon {
463
+ position: absolute;
464
+ top: 50%;
465
+ left: 50%;
466
+ transform: translate(-50%, -50%);
467
+ font-size: 48px;
468
+ display: none; // Hide icon overlay
469
+ }
470
+ }
471
+
472
+ .pose-info-compact {
473
+ h4 {
474
+ font-size: 13px;
475
+ font-weight: 600;
476
+ margin: 0 0 6px;
477
+ color: var(--ion-text-color);
478
+ white-space: nowrap;
479
+ overflow: hidden;
480
+ text-overflow: ellipsis;
481
+ }
482
+
483
+ .badges-compact {
484
+ display: flex;
485
+ justify-content: center;
486
+
487
+ ion-badge {
488
+ font-size: 10px;
489
+ padding: 2px 8px;
490
+ }
491
+ }
492
+ }
493
+
494
+ .pose-number {
495
+ position: absolute;
496
+ top: 8px;
497
+ right: 8px;
498
+ background: rgba(0, 0, 0, 0.7);
499
+ color: white;
500
+ width: 24px;
501
+ height: 24px;
502
+ border-radius: 50%;
503
+ display: none; // Hide pose number overlay
504
+ align-items: center;
505
+ justify-content: center;
506
+ font-size: 11px;
507
+ font-weight: 600;
508
+ }
509
+ }
510
+ }
511
+
512
+ // Pose List
513
+ .pose-list {
514
+ ion-item {
515
+ --background: var(--ion-background-color);
516
+ --border-radius: 12px;
517
+ margin-bottom: 8px;
518
+ cursor: pointer;
519
+
520
+ &.selected {
521
+ --background: rgba(var(--ion-color-success-rgb), 0.05);
522
+ border: 2px solid var(--ion-color-success);
523
+ }
524
+
525
+ ion-label {
526
+ h3 {
527
+ font-size: 15px;
528
+ font-weight: 600;
529
+ margin-bottom: 4px;
530
+ }
531
+
532
+ p {
533
+ font-size: 13px;
534
+ color: var(--ion-color-medium);
535
+ }
536
+ }
537
+ }
538
+ }
539
+
540
+ // No Results
541
+ .no-results {
542
+ display: flex;
543
+ flex-direction: column;
544
+ align-items: center;
545
+ justify-content: center;
546
+ padding: 40px 20px;
547
+ text-align: center;
548
+
549
+ ion-icon {
550
+ font-size: 64px;
551
+ margin-bottom: 16px;
552
+ }
553
+
554
+ p {
555
+ font-size: 16px;
556
+ color: var(--ion-color-medium);
557
+ margin: 0 0 16px;
558
+ }
559
+ }
560
+
561
+ @media (max-width: 768px) {
562
+ .pose-selection-section {
563
+ padding: 16px;
564
+
565
+ h3 {
566
+ font-size: 18px;
567
+ }
568
+ }
569
+
570
+ .pose-grid {
571
+ grid-template-columns: repeat(auto-fill, minmax(100px, 1fr));
572
+ gap: 12px;
573
+ }
574
+
575
+ .selected-pose-display {
576
+ .selected-pose-card {
577
+ flex-direction: column;
578
+ align-items: center;
579
+ text-align: center;
580
+ gap: 12px;
581
+ padding: 16px;
582
+
583
+ .pose-image-container {
584
+ width: 100px;
585
+ height: 100px;
586
+ }
587
+
588
+ .pose-details {
589
+ width: 100%;
590
+ max-width: 100%;
591
+ overflow: visible;
592
+
593
+ h4 {
594
+ font-size: 15px;
595
+ display: block;
596
+ white-space: normal;
597
+ word-break: break-word;
598
+ overflow-wrap: break-word;
599
+ }
600
+
601
+ p {
602
+ font-size: 13px;
603
+ line-height: 1.5;
604
+ display: block;
605
+ white-space: normal;
606
+ word-break: break-word;
607
+ overflow-wrap: break-word;
608
+ }
609
+
610
+ .pose-badges {
611
+ justify-content: center;
612
+ }
613
+ }
614
+ }
615
+ }
616
+
617
+ .filters-content {
618
+ .filter-chips {
619
+ ion-chip {
620
+ font-size: 12px;
621
+ }
622
+ }
623
+ }
624
+ }
625
+
626
+ @media (max-width: 480px) {
627
+ .intro-container {
628
+ padding: 24px 20px;
629
+ }
630
+
631
+ .instruction-text {
632
+ margin: 16px 0 24px;
633
+
634
+ h2 {
635
+ font-size: 22px;
636
+ }
637
+ }
638
+
639
+ .pose-selection-section {
640
+ padding: 12px;
641
+ margin: 20px auto;
642
+
643
+ h3 {
644
+ font-size: 16px;
645
+ }
646
+
647
+ .section-description {
648
+ font-size: 13px;
649
+ }
650
+ }
651
+
652
+ .pose-grid {
653
+ grid-template-columns: repeat(2, 1fr);
654
+ gap: 10px;
655
+
656
+ .pose-card {
657
+ padding: 8px;
658
+
659
+ .pose-info-compact h4 {
660
+ font-size: 12px;
661
+ }
662
+ }
663
+ }
664
+
665
+ .filters-content {
666
+ padding: 12px;
667
+
668
+ .filter-group {
669
+ margin-bottom: 12px;
670
+
671
+ label {
672
+ font-size: 13px;
673
+ }
674
+ }
675
+ }
676
+ }
677
+
678
+ // Mode Toggle (Browse vs Upload)
679
+ .mode-toggle-container {
680
+ margin-bottom: 24px;
681
+
682
+ ion-segment {
683
+ --background: var(--ion-background-color);
684
+ border-radius: 12px;
685
+ padding: 4px;
686
+
687
+ ion-segment-button {
688
+ --indicator-color: var(--ion-color-primary);
689
+ --color: var(--ion-color-medium);
690
+ --color-checked: var(--ion-color-primary-contrast);
691
+ min-height: 48px;
692
+ font-weight: 500;
693
+ font-size: 14px;
694
+
695
+ ion-icon {
696
+ font-size: 20px;
697
+ margin-bottom: 4px;
698
+ }
699
+
700
+ ion-label {
701
+ margin-top: 4px;
702
+ }
703
+ }
704
+ }
705
+ }
706
+
707
+ // Upload Custom Pose Section
708
+ .upload-pose-section {
709
+ margin-bottom: 24px;
710
+
711
+ .upload-container {
712
+ position: relative;
713
+ width: 100%;
714
+ min-height: 280px;
715
+ padding: 32px;
716
+ background: var(--ion-background-color);
717
+ border: 2px dashed var(--ion-color-medium);
718
+ border-radius: 16px;
719
+ cursor: pointer;
720
+ transition: all 0.3s ease;
721
+ display: flex;
722
+ align-items: center;
723
+ justify-content: center;
724
+
725
+ &:hover {
726
+ border-color: var(--ion-color-primary);
727
+ background: rgba(var(--ion-color-primary-rgb), 0.02);
728
+ transform: translateY(-2px);
729
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);
730
+ }
731
+
732
+ &.dragging {
733
+ border-color: var(--ion-color-primary);
734
+ background: rgba(var(--ion-color-primary-rgb), 0.05);
735
+ border-width: 3px;
736
+ box-shadow: 0 8px 24px rgba(var(--ion-color-primary-rgb), 0.2);
737
+ }
738
+
739
+ .upload-content {
740
+ display: flex;
741
+ flex-direction: column;
742
+ align-items: center;
743
+ justify-content: center;
744
+ text-align: center;
745
+ width: 100%;
746
+
747
+ .upload-icon {
748
+ font-size: 80px;
749
+ margin-bottom: 16px;
750
+ opacity: 0.8;
751
+ }
752
+
753
+ h4 {
754
+ font-size: 18px;
755
+ font-weight: 600;
756
+ color: var(--ion-text-color);
757
+ margin: 0 0 8px;
758
+ }
759
+
760
+ .upload-instructions {
761
+ font-size: 15px;
762
+ color: var(--ion-color-medium);
763
+ margin: 0 0 8px;
764
+ font-weight: 500;
765
+ }
766
+
767
+ .upload-hint {
768
+ font-size: 13px;
769
+ color: var(--ion-color-medium);
770
+ margin: 0 0 20px;
771
+ font-style: italic;
772
+ }
773
+
774
+ ion-button {
775
+ --padding-start: 20px;
776
+ --padding-end: 20px;
777
+ font-weight: 600;
778
+ }
779
+ }
780
+
781
+ .upload-processing {
782
+ display: flex;
783
+ flex-direction: column;
784
+ align-items: center;
785
+ justify-content: center;
786
+ gap: 16px;
787
+
788
+ ion-spinner {
789
+ width: 48px;
790
+ height: 48px;
791
+ }
792
+
793
+ p {
794
+ font-size: 15px;
795
+ color: var(--ion-color-medium);
796
+ font-weight: 500;
797
+ margin: 0;
798
+ }
799
+ }
800
+ }
801
+
802
+ .upload-tips {
803
+ margin-top: 20px;
804
+ padding: 16px;
805
+ background: rgba(var(--ion-color-primary-rgb), 0.05);
806
+ border-radius: 12px;
807
+ border-left: 4px solid var(--ion-color-primary);
808
+
809
+ h5 {
810
+ font-size: 14px;
811
+ font-weight: 600;
812
+ color: var(--ion-text-color);
813
+ margin: 0 0 12px;
814
+ }
815
+
816
+ ul {
817
+ margin: 0;
818
+ padding-left: 20px;
819
+ list-style: disc;
820
+
821
+ li {
822
+ font-size: 13px;
823
+ color: var(--ion-color-medium);
824
+ margin: 6px 0;
825
+ line-height: 1.5;
826
+ }
827
+ }
828
+ }
829
+
830
+ .upload-status {
831
+ margin-top: 16px;
832
+
833
+ ion-card {
834
+ margin: 0;
835
+ border-radius: 12px;
836
+
837
+ ion-card-content {
838
+ padding: 12px 16px;
839
+
840
+ .status-content {
841
+ display: flex;
842
+ align-items: center;
843
+ gap: 12px;
844
+
845
+ ion-icon {
846
+ font-size: 24px;
847
+ flex-shrink: 0;
848
+ }
849
+
850
+ span {
851
+ font-size: 14px;
852
+ font-weight: 500;
853
+ flex: 1;
854
+ }
855
+ }
856
+ }
857
+ }
858
+ }
859
+ }
860
+
861
+ // Uploaded Pose Display
862
+ .uploaded-pose-display {
863
+ margin-bottom: 24px;
864
+
865
+ .selected-badge {
866
+ display: flex;
867
+ align-items: center;
868
+ gap: 8px;
869
+ justify-content: center;
870
+ margin-bottom: 12px;
871
+ color: var(--ion-color-success);
872
+ font-weight: 600;
873
+ font-size: 14px;
874
+
875
+ ion-icon {
876
+ font-size: 24px;
877
+ }
878
+ }
879
+
880
+ .uploaded-pose-card {
881
+ display: flex;
882
+ flex-direction: row;
883
+ align-items: center;
884
+ gap: 16px;
885
+ padding: 16px;
886
+ background: var(--ion-background-color);
887
+ border-radius: 12px;
888
+ border: 2px solid var(--ion-color-success);
889
+ box-shadow: 0 4px 12px rgba(var(--ion-color-success-rgb), 0.2);
890
+
891
+ .pose-image-container {
892
+ position: relative;
893
+ width: 100px;
894
+ height: 100px;
895
+ flex-shrink: 0;
896
+ border-radius: 8px;
897
+ overflow: hidden;
898
+ background: var(--ion-color-light);
899
+
900
+ img {
901
+ width: 100%;
902
+ height: 100%;
903
+ object-fit: cover;
904
+ }
905
+
906
+ .pose-overlay-canvas {
907
+ position: absolute;
908
+ top: 0;
909
+ left: 0;
910
+ width: 100%;
911
+ height: 100%;
912
+ pointer-events: none;
913
+ }
914
+ }
915
+
916
+ .pose-details {
917
+ flex: 1;
918
+ min-width: 0;
919
+
920
+ h4 {
921
+ font-size: 16px;
922
+ font-weight: 600;
923
+ margin: 0 0 4px;
924
+ color: var(--ion-text-color);
925
+ }
926
+
927
+ p {
928
+ font-size: 13px;
929
+ color: var(--ion-color-medium);
930
+ margin: 0 0 8px;
931
+ line-height: 1.4;
932
+ }
933
+
934
+ .pose-status {
935
+ ion-badge {
936
+ font-size: 11px;
937
+ padding: 4px 10px;
938
+ }
939
+ }
940
+ }
941
+ }
942
+
943
+ .change-pose-link {
944
+ background: none;
945
+ border: none;
946
+ color: var(--ion-color-primary);
947
+ font-size: 14px;
948
+ font-weight: 500;
949
+ padding: 8px 0;
950
+ cursor: pointer;
951
+ transition: color 0.2s ease;
952
+ text-decoration: underline;
953
+ text-align: center;
954
+ margin-top: 8px;
955
+
956
+ &:hover {
957
+ color: var(--ion-color-primary-shade);
958
+ opacity: 0.8;
959
+ }
960
+
961
+ &:active {
962
+ opacity: 0.6;
963
+ }
964
+ }
965
+ }
966
+
967
+ // Mobile responsiveness for upload section
968
+ @media (max-width: 768px) {
969
+ .upload-pose-section {
970
+ .upload-container {
971
+ min-height: 240px;
972
+ padding: 24px;
973
+
974
+ .upload-content {
975
+ .upload-icon {
976
+ font-size: 64px;
977
+ }
978
+
979
+ h4 {
980
+ font-size: 16px;
981
+ }
982
+
983
+ .upload-instructions {
984
+ font-size: 14px;
985
+ }
986
+
987
+ .upload-hint {
988
+ font-size: 12px;
989
+ }
990
+ }
991
+ }
992
+
993
+ .upload-tips {
994
+ padding: 12px;
995
+
996
+ h5 {
997
+ font-size: 13px;
998
+ }
999
+
1000
+ ul li {
1001
+ font-size: 12px;
1002
+ }
1003
+ }
1004
+ }
1005
+
1006
+ .uploaded-pose-display {
1007
+ .uploaded-pose-card {
1008
+ flex-direction: column;
1009
+ align-items: center;
1010
+ text-align: center;
1011
+
1012
+ .pose-image-container {
1013
+ width: 120px;
1014
+ height: 120px;
1015
+ }
1016
+
1017
+ .pose-details {
1018
+ width: 100%;
1019
+ }
1020
+ }
1021
+ }
1022
+
1023
+ .mode-toggle-container {
1024
+ ion-segment-button {
1025
+ min-height: 44px;
1026
+ font-size: 13px;
1027
+
1028
+ ion-icon {
1029
+ font-size: 18px;
1030
+ }
1031
+ }
1032
+ }
1033
+ }
1034
+
1035
+ @media (max-width: 480px) {
1036
+ .upload-pose-section {
1037
+ .upload-container {
1038
+ min-height: 200px;
1039
+ padding: 20px;
1040
+
1041
+ .upload-content {
1042
+ .upload-icon {
1043
+ font-size: 56px;
1044
+ }
1045
+
1046
+ h4 {
1047
+ font-size: 15px;
1048
+ }
1049
+ }
1050
+ }
1051
+ }
1052
+
1053
+ .mode-toggle-container {
1054
+ margin-bottom: 16px;
1055
+
1056
+ ion-segment {
1057
+ padding: 2px;
1058
+
1059
+ ion-segment-button {
1060
+ min-height: 40px;
1061
+ font-size: 12px;
1062
+ flex-direction: column;
1063
+ gap: 2px;
1064
+
1065
+ ion-icon {
1066
+ font-size: 16px;
1067
+ margin-bottom: 2px;
1068
+ }
1069
+
1070
+ ion-label {
1071
+ margin-top: 2px;
1072
+ }
1073
+ }
1074
+ }
1075
+ }
1076
+ }
1077
+
1078
+ // Custom Pose Management Styles
1079
+ .save-custom-pose-section {
1080
+ margin-top: 16px;
1081
+ padding-top: 16px;
1082
+ border-top: 1px solid var(--ion-color-light-shade);
1083
+
1084
+ ion-button {
1085
+ --padding-start: 20px;
1086
+ --padding-end: 20px;
1087
+ font-weight: 600;
1088
+ font-size: 15px;
1089
+ height: 48px;
1090
+ margin: 0;
1091
+
1092
+ ion-icon {
1093
+ font-size: 20px;
1094
+ }
1095
+ }
1096
+
1097
+ .help-text {
1098
+ font-size: 12px;
1099
+ color: var(--ion-color-medium);
1100
+ text-align: center;
1101
+ margin: 8px 0 0;
1102
+ font-style: italic;
1103
+ line-height: 1.5;
1104
+ }
1105
+ }
1106
+
1107
+ // Custom Badge (on pose cards)
1108
+ .custom-badge {
1109
+ position: absolute;
1110
+ top: 8px;
1111
+ left: 8px;
1112
+ display: flex;
1113
+ align-items: center;
1114
+ gap: 4px;
1115
+ padding: 4px 8px;
1116
+ background: var(--ion-color-secondary);
1117
+ border-radius: 6px;
1118
+ z-index: 10;
1119
+ font-size: 10px;
1120
+ font-weight: 600;
1121
+ box-shadow: 0 2px 6px rgba(0, 0, 0, 0.15);
1122
+
1123
+ ion-icon {
1124
+ font-size: 12px;
1125
+ }
1126
+ }
1127
+
1128
+ // Delete Button (on custom pose cards)
1129
+ .delete-pose-button {
1130
+ position: absolute;
1131
+ top: 8px;
1132
+ right: 8px;
1133
+ width: 32px;
1134
+ height: 32px;
1135
+ display: flex;
1136
+ align-items: center;
1137
+ justify-content: center;
1138
+ background: var(--ion-color-danger);
1139
+ color: white;
1140
+ border: none;
1141
+ border-radius: 50%;
1142
+ cursor: pointer;
1143
+ z-index: 10;
1144
+ transition: all 0.2s ease;
1145
+ opacity: 0.9;
1146
+ box-shadow: 0 2px 8px rgba(var(--ion-color-danger-rgb), 0.3);
1147
+
1148
+ ion-icon {
1149
+ font-size: 18px;
1150
+ pointer-events: none;
1151
+ }
1152
+
1153
+ &:hover {
1154
+ opacity: 1;
1155
+ transform: scale(1.1);
1156
+ box-shadow: 0 4px 12px rgba(var(--ion-color-danger-rgb), 0.5);
1157
+ }
1158
+
1159
+ &:active {
1160
+ transform: scale(0.95);
1161
+ }
1162
+ }
1163
+
1164
+ // Custom Pose Card Modifier
1165
+ .pose-card.custom-pose {
1166
+ border-color: var(--ion-color-secondary-tint);
1167
+
1168
+ &:hover {
1169
+ border-color: var(--ion-color-secondary);
1170
+ box-shadow: 0 8px 24px rgba(var(--ion-color-secondary-rgb), 0.2);
1171
+ }
1172
+
1173
+ &.selected {
1174
+ border-color: var(--ion-color-success);
1175
+ background: rgba(var(--ion-color-success-rgb), 0.05);
1176
+ box-shadow: 0 4px 16px rgba(var(--ion-color-success-rgb), 0.3);
1177
+ }
1178
+ }
1179
+
1180
+ // Mobile responsiveness for custom pose elements
1181
+ @media (max-width: 480px) {
1182
+ .custom-badge {
1183
+ font-size: 9px;
1184
+ padding: 3px 6px;
1185
+ gap: 3px;
1186
+
1187
+ ion-icon {
1188
+ font-size: 10px;
1189
+ }
1190
+ }
1191
+
1192
+ .delete-pose-button {
1193
+ width: 28px;
1194
+ height: 28px;
1195
+
1196
+ ion-icon {
1197
+ font-size: 16px;
1198
+ }
1199
+ }
1200
+
1201
+ .save-custom-pose-section {
1202
+ ion-button {
1203
+ font-size: 14px;
1204
+ height: 44px;
1205
+
1206
+ ion-icon {
1207
+ font-size: 18px;
1208
+ }
1209
+ }
1210
+
1211
+ .help-text {
1212
+ font-size: 11px;
1213
+ }
1214
+ }
1215
+ }
1216
+
1217
+ // Backend Selection Section
1218
+ .backend-selection-section {
1219
+ width: 100%;
1220
+ margin-bottom: 24px;
1221
+ background: var(--ion-color-light);
1222
+ border-radius: 12px;
1223
+ overflow: hidden;
1224
+
1225
+ .backend-header {
1226
+ display: flex;
1227
+ align-items: center;
1228
+ gap: 8px;
1229
+ padding: 12px 16px;
1230
+ cursor: pointer;
1231
+ background: var(--ion-color-light-shade);
1232
+ transition: background 0.2s ease;
1233
+
1234
+ &:hover {
1235
+ background: var(--ion-color-light-tint);
1236
+ }
1237
+
1238
+ ion-icon:first-child {
1239
+ font-size: 18px;
1240
+ color: var(--ion-color-medium);
1241
+ }
1242
+
1243
+ span {
1244
+ flex: 1;
1245
+ font-size: 14px;
1246
+ font-weight: 600;
1247
+ color: var(--ion-text-color);
1248
+ }
1249
+
1250
+ .settings-icon {
1251
+ font-size: 20px;
1252
+ color: var(--ion-color-primary);
1253
+ }
1254
+ }
1255
+
1256
+ .backend-options {
1257
+ padding: 16px;
1258
+ animation: fadeIn 0.2s ease;
1259
+
1260
+ .backend-description {
1261
+ font-size: 13px;
1262
+ color: var(--ion-color-medium);
1263
+ margin: 0 0 12px;
1264
+ }
1265
+
1266
+ .backend-checkboxes {
1267
+ display: flex;
1268
+ flex-direction: column;
1269
+ gap: 8px;
1270
+ }
1271
+
1272
+ .backend-item {
1273
+ --background: transparent;
1274
+ --padding-start: 0;
1275
+ --inner-padding-end: 0;
1276
+
1277
+ ion-checkbox {
1278
+ --size: 20px;
1279
+ margin-right: 12px;
1280
+ }
1281
+
1282
+ ion-label {
1283
+ h3 {
1284
+ font-size: 14px;
1285
+ font-weight: 600;
1286
+ margin: 0 0 2px;
1287
+ }
1288
+
1289
+ p {
1290
+ font-size: 12px;
1291
+ color: var(--ion-color-medium);
1292
+ margin: 0;
1293
+ }
1294
+ }
1295
+ }
1296
+
1297
+ .backend-note {
1298
+ display: flex;
1299
+ align-items: center;
1300
+ gap: 6px;
1301
+ font-size: 12px;
1302
+ color: var(--ion-color-primary);
1303
+ margin: 12px 0 0;
1304
+ padding: 8px 12px;
1305
+ background: rgba(var(--ion-color-primary-rgb), 0.1);
1306
+ border-radius: 8px;
1307
+
1308
+ ion-icon {
1309
+ font-size: 16px;
1310
+ flex-shrink: 0;
1311
+ }
1312
+ }
1313
+ }
1314
+ }
1315
+
1316
+ @keyframes fadeIn {
1317
+ from {
1318
+ opacity: 0;
1319
+ transform: translateY(-8px);
1320
+ }
1321
+ to {
1322
+ opacity: 1;
1323
+ transform: translateY(0);
1324
+ }
1325
+ }
1326
+
1327
+ // AWS Face Liveness Anti-Spoofing Section
1328
+ .aws-liveness-section {
1329
+ margin-top: 16px;
1330
+
1331
+ .section-divider {
1332
+ height: 1px;
1333
+ background: var(--ion-color-light-shade);
1334
+ margin-bottom: 16px;
1335
+ }
1336
+
1337
+ .aws-liveness-title {
1338
+ display: flex;
1339
+ align-items: center;
1340
+ gap: 8px;
1341
+ font-size: 15px;
1342
+ font-weight: 600;
1343
+ color: var(--ion-text-color);
1344
+ margin: 0 0 12px;
1345
+
1346
+ ion-icon {
1347
+ font-size: 20px;
1348
+ color: var(--ion-color-success);
1349
+ }
1350
+ }
1351
+
1352
+ .aws-liveness-item {
1353
+ --background: transparent;
1354
+ --padding-start: 0;
1355
+ --inner-padding-end: 0;
1356
+ margin-bottom: 16px;
1357
+
1358
+ ion-toggle {
1359
+ margin-right: 12px;
1360
+ }
1361
+
1362
+ ion-label {
1363
+ h3 {
1364
+ font-size: 14px;
1365
+ font-weight: 600;
1366
+ margin: 0 0 2px;
1367
+ }
1368
+
1369
+ p {
1370
+ font-size: 12px;
1371
+ color: var(--ion-color-medium);
1372
+ margin: 0;
1373
+ }
1374
+ }
1375
+ }
1376
+
1377
+ .liveness-explanation {
1378
+ display: flex;
1379
+ flex-direction: column;
1380
+ gap: 12px;
1381
+
1382
+ .explanation-card {
1383
+ padding: 14px;
1384
+ background: var(--ion-background-color);
1385
+ border-radius: 10px;
1386
+ border: 2px solid var(--ion-color-light-shade);
1387
+ transition: all 0.3s ease;
1388
+
1389
+ &.inactive {
1390
+ opacity: 0.6;
1391
+ }
1392
+
1393
+ &.recommended {
1394
+ border-color: var(--ion-color-success-tint);
1395
+ background: rgba(var(--ion-color-success-rgb), 0.02);
1396
+ }
1397
+
1398
+ &.active {
1399
+ border-color: var(--ion-color-success);
1400
+ background: rgba(var(--ion-color-success-rgb), 0.08);
1401
+ box-shadow: 0 4px 12px rgba(var(--ion-color-success-rgb), 0.2);
1402
+ opacity: 1;
1403
+ }
1404
+
1405
+ .card-header {
1406
+ display: flex;
1407
+ align-items: center;
1408
+ gap: 8px;
1409
+ margin-bottom: 8px;
1410
+
1411
+ ion-icon {
1412
+ font-size: 18px;
1413
+ color: var(--ion-color-medium);
1414
+ }
1415
+
1416
+ span {
1417
+ font-size: 13px;
1418
+ font-weight: 600;
1419
+ color: var(--ion-text-color);
1420
+ }
1421
+
1422
+ ion-badge {
1423
+ font-size: 10px;
1424
+ padding: 3px 8px;
1425
+ margin-left: auto;
1426
+ }
1427
+ }
1428
+
1429
+ &.recommended .card-header ion-icon {
1430
+ color: var(--ion-color-success);
1431
+ }
1432
+
1433
+ p {
1434
+ font-size: 12px;
1435
+ color: var(--ion-color-medium);
1436
+ margin: 0;
1437
+ line-height: 1.5;
1438
+
1439
+ strong {
1440
+ color: var(--ion-text-color);
1441
+ }
1442
+ }
1443
+
1444
+ .features {
1445
+ display: flex;
1446
+ flex-wrap: wrap;
1447
+ gap: 8px;
1448
+ margin-top: 10px;
1449
+
1450
+ span {
1451
+ display: flex;
1452
+ align-items: center;
1453
+ gap: 4px;
1454
+ font-size: 11px;
1455
+ color: var(--ion-color-success);
1456
+ background: rgba(var(--ion-color-success-rgb), 0.1);
1457
+ padding: 4px 8px;
1458
+ border-radius: 6px;
1459
+ font-weight: 500;
1460
+
1461
+ ion-icon {
1462
+ font-size: 14px;
1463
+ }
1464
+ }
1465
+ }
1466
+ }
1467
+ }
1468
+
1469
+ .aws-note {
1470
+ display: flex;
1471
+ align-items: center;
1472
+ gap: 6px;
1473
+ font-size: 12px;
1474
+ color: var(--ion-color-success);
1475
+ margin: 12px 0 0;
1476
+ padding: 8px 12px;
1477
+ background: rgba(var(--ion-color-success-rgb), 0.1);
1478
+ border-radius: 8px;
1479
+
1480
+ ion-icon {
1481
+ font-size: 16px;
1482
+ flex-shrink: 0;
1483
+ }
1484
+ }
1485
+
1486
+ .browser-warning {
1487
+ display: flex;
1488
+ align-items: flex-start;
1489
+ gap: 10px;
1490
+ margin: 12px 0 0;
1491
+ padding: 12px;
1492
+ background: rgba(var(--ion-color-warning-rgb), 0.15);
1493
+ border: 1px solid var(--ion-color-warning);
1494
+ border-radius: 8px;
1495
+
1496
+ > ion-icon {
1497
+ font-size: 24px;
1498
+ color: var(--ion-color-warning);
1499
+ flex-shrink: 0;
1500
+ margin-top: 2px;
1501
+ }
1502
+
1503
+ .warning-content {
1504
+ flex: 1;
1505
+
1506
+ strong {
1507
+ display: block;
1508
+ font-size: 13px;
1509
+ color: var(--ion-color-warning-shade);
1510
+ margin-bottom: 4px;
1511
+ }
1512
+
1513
+ p {
1514
+ font-size: 12px;
1515
+ color: var(--ion-color-medium);
1516
+ margin: 0;
1517
+ line-height: 1.4;
1518
+ }
1519
+ }
1520
+ }
1521
+ }
1522
+
1523
+ @media (max-width: 480px) {
1524
+ .aws-liveness-section {
1525
+ .aws-liveness-title {
1526
+ font-size: 14px;
1527
+
1528
+ ion-icon {
1529
+ font-size: 18px;
1530
+ }
1531
+ }
1532
+
1533
+ .liveness-explanation {
1534
+ .explanation-card {
1535
+ padding: 12px;
1536
+
1537
+ .card-header {
1538
+ span {
1539
+ font-size: 12px;
1540
+ }
1541
+
1542
+ ion-badge {
1543
+ font-size: 9px;
1544
+ padding: 2px 6px;
1545
+ }
1546
+ }
1547
+
1548
+ p {
1549
+ font-size: 11px;
1550
+ }
1551
+
1552
+ .features {
1553
+ gap: 6px;
1554
+
1555
+ span {
1556
+ font-size: 10px;
1557
+ padding: 3px 6px;
1558
+
1559
+ ion-icon {
1560
+ font-size: 12px;
1561
+ }
1562
+ }
1563
+ }
1564
+ }
1565
+ }
1566
+ }
1567
+ }