@swan-admin/swan-web-component 1.0.122 → 1.0.123
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.
- package/dist/BodyScan-CCRXkFFL.mjs +3 -0
- package/dist/BodyScan-CCRXkFFL.mjs.map +1 -0
- package/dist/BodyScan-RBxSYdGc.js +3 -0
- package/dist/BodyScan-RBxSYdGc.js.map +1 -0
- package/dist/{FaceScan-BdcqQIJ5.mjs → FaceScan-DQvhrp3K.mjs} +2 -2
- package/dist/{FaceScan-BdcqQIJ5.mjs.map → FaceScan-DQvhrp3K.mjs.map} +1 -1
- package/dist/{FaceScan-lUHosRqk.js → FaceScan-Dva9De8x.js} +2 -2
- package/dist/{FaceScan-lUHosRqk.js.map → FaceScan-Dva9De8x.js.map} +1 -1
- package/dist/{Modal-TzaSySDr.mjs → Modal-CZgyeNwW.mjs} +1 -1
- package/dist/{Modal-TzaSySDr.mjs.map → Modal-CZgyeNwW.mjs.map} +1 -1
- package/dist/{Modal-DxgejzjH.js → Modal-CmbYIXgn.js} +1 -1
- package/dist/{Modal-DxgejzjH.js.map → Modal-CmbYIXgn.js.map} +1 -1
- package/dist/bodyScan.js +1 -1
- package/dist/bodyScan.mjs +1 -1
- package/dist/faceScan.js +1 -1
- package/dist/faceScan.mjs +1 -1
- package/dist/index.css +1 -1
- package/dist/index.js +1 -1
- package/dist/index.mjs +1 -1
- package/dist/{pose-detection.esm-BV7VgekA.js → pose-detection.esm-DFB9u8DH.js} +1 -1
- package/dist/{pose-detection.esm-BV7VgekA.js.map → pose-detection.esm-DFB9u8DH.js.map} +1 -1
- package/dist/{pose-detection.esm-D8r1CbkV.mjs → pose-detection.esm-EvS-BndH.mjs} +1 -1
- package/dist/{pose-detection.esm-D8r1CbkV.mjs.map → pose-detection.esm-EvS-BndH.mjs.map} +1 -1
- package/package.json +1 -1
- package/dist/BodyScan-B5BvnBHj.js +0 -3
- package/dist/BodyScan-B5BvnBHj.js.map +0 -1
- package/dist/BodyScan-CL9reolN.mjs +0 -3
- package/dist/BodyScan-CL9reolN.mjs.map +0 -1
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"BodyScan-CL9reolN.mjs","sources":["../src/utils/context/mediaContext.tsx","../src/Icons/SwitchIcon.tsx","../src/components/bodyScan/LevelScreen.tsx","../src/components/bodyScan/CameraScanChild.tsx","../src/customHooks/useTensorFlow.ts","../src/components/bodyScan/ScanningComponent.tsx","../src/components/bodyScan/AngleDetector.tsx","../src/components/bodyScan/CameraPermission.tsx","../src/components/bodyScan/VideoPlayer.tsx","../src/components/bodyScan/ScanErrorMessage.tsx","../src/components/Signup.tsx","../src/components/bodyScan/BodyScanSteps.tsx","../src/components/bodyScan/BodyScan.tsx","../src/customHooks/useGyroSensor.ts"],"sourcesContent":["\"use client\"\nimport React, {\n createContext,\n Dispatch,\n ReactNode,\n SetStateAction,\n useEffect,\n useLayoutEffect,\n useMemo,\n useState,\n} from \"react\";\n\nexport const MEDIA_TYPES = {\n DESKTOP: \"DESKTOP\",\n TAB: \"TAB\",\n MOBILE: \"MOBILE\",\n};\n\ninterface MediaContextType {\n size: number[];\n setSize: Dispatch<SetStateAction<number[]>>;\n clearInputs: boolean;\n setClearInputs: Dispatch<SetStateAction<boolean>>;\n media: string;\n}\n\nexport const MediaContext = createContext<MediaContextType | undefined>(\n undefined\n);\n\nfunction MediaContextProvider({ children }: { children: ReactNode }) {\n const [size, setSize] = useState([window?.innerWidth, window?.innerHeight]);\n const [clearInputs, setClearInputs] = useState(false);\n\n const updateSize = () => {\n setSize([window?.innerWidth, window?.innerHeight]);\n };\n useEffect(() => {\n updateSize();\n }, []);\n useLayoutEffect(() => {\n window.addEventListener(\"resize\", updateSize);\n return () => window.removeEventListener(\"resize\", updateSize);\n }, [updateSize]);\n let media = MEDIA_TYPES.DESKTOP;\n if (size[0] > 768 && size[0] < 1024) {\n media = MEDIA_TYPES.TAB;\n }\n if (size[0] < 768) {\n media = MEDIA_TYPES.MOBILE;\n }\n\n const mediaDetails = useMemo(\n () => ({\n size,\n setSize,\n clearInputs,\n setClearInputs,\n media,\n }),\n [size, clearInputs, media]\n );\n\n return (\n <MediaContext.Provider value={mediaDetails}>\n {children}\n </MediaContext.Provider>\n );\n}\n\nexport default MediaContextProvider;\n","import React from \"react\";\n\nfunction SwitchIcon({ size = 16 }: { size?: number }) {\n return (\n <svg\n width={size}\n height={size}\n viewBox=\"0 0 25 25\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n >\n <path\n d=\"M22.6968 14.6968C22.6968 16.8185 21.8539 18.8533 20.3536 20.3536C18.8533 21.8539 16.8185 22.6968 14.6968 22.6968\"\n stroke=\"white\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n />\n <path\n d=\"M18.6968 11.6968V10.6968C18.6968 10.1663 18.4861 9.65764 18.111 9.28256C17.7359 8.90749 17.2272 8.69678 16.6968 8.69678C16.1663 8.69678 15.6576 8.90749 15.2826 9.28256C14.9075 9.65764 14.6968 10.1663 14.6968 10.6968\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n />\n <path\n d=\"M14.6968 10.6968V9.69678C14.6968 9.16634 14.4861 8.65764 14.111 8.28256C13.7359 7.90749 13.2272 7.69678 12.6968 7.69678C12.1663 7.69678 11.6576 7.90749 11.2826 8.28256C10.9075 8.65764 10.6968 9.16634 10.6968 9.69678V10.6968\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n />\n <path\n d=\"M10.6968 10.1968V4.69678C10.6968 4.16634 10.4861 3.65764 10.111 3.28256C9.73592 2.90749 9.22721 2.69678 8.69678 2.69678C8.16634 2.69678 7.65764 2.90749 7.28256 3.28256C6.90749 3.65764 6.69678 4.16634 6.69678 4.69678V14.6968\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n />\n <path\n d=\"M18.6969 11.6968C18.6969 11.1663 18.9076 10.6576 19.2827 10.2826C19.6577 9.90749 20.1664 9.69678 20.6969 9.69678C21.2273 9.69678 21.736 9.90749 22.1111 10.2826C22.4862 10.6576 22.6969 11.1663 22.6969 11.6968V14.6968C22.6969 16.8185 21.854 18.8533 20.3537 20.3536C18.8534 21.8539 16.8186 22.6968 14.6969 22.6968H12.6969C9.89688 22.6968 8.19688 21.8368 6.70688 20.3568L3.10688 16.7568C2.76282 16.3757 2.57847 15.8769 2.592 15.3637C2.60554 14.8505 2.81593 14.3621 3.1796 13.9997C3.54327 13.6373 4.03238 13.4287 4.54565 13.417C5.05892 13.4053 5.55704 13.5914 5.93688 13.9368L7.69688 15.6968\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n />\n </svg>\n );\n}\n\nexport default React.memo(SwitchIcon);\n","/* eslint-disable no-nested-ternary */\n\nimport React, { useCallback, useContext, useMemo } from \"react\";\nimport Header from \"../Header\";\nimport cn from \"clsx\";\nimport { LevelScreenProps } from \"../../types/interfaces\";\nimport SwitchIcon from \"../../Icons/SwitchIcon\";\nimport { LanguageContext } from \"../../utils/context/languageContext\";\nimport { LanguageKeys } from \"../../utils/languageKeys\";\nimport { useConfig } from \"../../utils/context/configContext\";\n\nfunction LevelScreen({ angle, countdown, isScanning, isInTargetRange, stabilityScore, children }: Omit<LevelScreenProps, \"config\">) {\n\tconst { translate } = useContext(LanguageContext) || {};\n\tconst config = useConfig();\n\n\tconst getProximityToTarget = useCallback(() => {\n\t\tif (angle < 80) return Math.max(0, Math.min(100, (angle - 60) * 10));\n\t\tif (angle > 95) return Math.max(0, Math.min(100, (105 - angle) * 10));\n\t\treturn 100;\n\t}, [angle]);\n\n\tconst backgroundColor = useMemo(() => {\n\t\tif (isScanning) return config?.style?.angleDetector?.successAngleBackground || \"#4f46e5\";\n\n\t\tconst proximity = getProximityToTarget();\n\t\tif (proximity === 0) return config?.style?.angleDetector?.successAngleLowBackground || \"#ffffff\";\n\t\tif (proximity === 100) return config?.style?.angleDetector?.successAngleBackground || \"#4f46e5\";\n\n const r = Math.round(255 - (255 - 139) * (proximity / 100));\n const g = Math.round(255 - (255 - 92) * (proximity / 100));\n const b = Math.round(255 - (255 - 246) * (proximity / 100));\n return `rgb(${r}, ${g}, ${b})`;\n }, [isScanning, getProximityToTarget]);\n\n\tconst handelTextColour = useCallback((isLight: boolean, proximity: number) => {\n\t\tif (proximity > 70) {\n\t\t\treturn isLight ? `text-[${config?.style?.angleDetector?.successAngleTextLightColor}]/70` : `text-[${config?.style?.angleDetector?.successAngleTextLightColor}]`;\n\t\t}\n\t\treturn isLight ? `text-[${config?.style?.angleDetector?.successAngleTextLightColor}]/40` : `text-[${config?.style?.angleDetector?.successAngleTextDarkColor}]/70`;\n\t}, []);\n\n\tconst getTextColor = useCallback(\n\t\t(isLight = false) => {\n\t\t\tconst proximity = getProximityToTarget();\n\t\t\tif (isScanning) return `text-[${config?.style?.angleDetector?.successAngleTextLightColor}]`;\n\t\t\treturn handelTextColour(isLight, proximity);\n\t\t},\n\t\t[isScanning, getProximityToTarget],\n\t);\n\n\tconst handelColourCode = useCallback((isLight: boolean, proximity: number) => {\n\t\tif (proximity > 70) {\n\t\t\treturn isLight ? config?.style?.angleDetector?.successAngleTextLightColor : config?.style?.angleDetector?.successAngleTextLightColor;\n\t\t}\n\t\treturn isLight ? config?.style?.angleDetector?.successAngleTextLightColor : config?.style?.angleDetector?.successAngleTextDarkColor;\n\t}, []);\n\tconst getColorCode = useCallback(\n\t\t(isLight = false) => {\n\t\t\tconst proximity = getProximityToTarget();\n\t\t\tif (isScanning) return config?.style?.angleDetector?.successAngleTextLightColor;\n\t\t\treturn handelColourCode(isLight, proximity);\n\t\t},\n\t\t[isScanning, getProximityToTarget],\n\t);\n\tconst cd = countdown;\n\tfunction fixVh() {\n\t\tdocument.documentElement.style.setProperty(\"--real-vh\", window.innerHeight + \"px\");\n\t}\n\tfixVh();\n\twindow.addEventListener(\"resize\", fixVh);\n\treturn (\n\t\t<div\n\t\t\tclassName=\"flex common-ui-main w-screen flex-col items-center h-[var(--real-vh)] overflow-hidden touch-none justify-center transition-all duration-300 max-w-[28rem] mx-auto\"\n\t\t\tstyle={{ backgroundColor }}\n\t\t\tdata-testid=\"level-screen\"\n\t\t\tdata-angle-state={isScanning ? \"locked\" : isInTargetRange ? \"target\" : \"adjusting\"}\n\t\t>\n\t\t\t<div className=\"flex justify-start fixed top-[.5rem] max-w-[28rem] mx-auto w-full px-[1rem]\">\n\t\t\t\t<div className=\"flex justify-start \">\n\t\t\t\t\t<Header noTitle />\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t\t{cd !== null ? (\n\t\t\t\t<div\n\t\t\t\t\tclassName=\"relative flex h-[6rem] w-[6rem] items-center justify-center rounded-[9999px] bg-[#fff]/20 transition-all duration-300\"\n\t\t\t\t\tstyle={{\n\t\t\t\t\t\tborder: `2px solid ${getColorCode()}`,\n\t\t\t\t\t}}\n\t\t\t\t>\n\t\t\t\t\t<div\n\t\t\t\t\t\tclassName={`text-[3rem] font-bold text-[${getColorCode()}]`}\n\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\tfontFamily: config?.style?.base?.baseFontFamily || \"Inter, sans-serif\",\n color: getColorCode(),\n\t\t\t\t\t\t}}\n\t\t\t\t\t>\n\t\t\t\t\t\t{cd}\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t) : isScanning ? (\n\t\t\t\t<div className=\"relative flex flex-col items-center justify-center\">\n\t\t\t\t\t<div className=\"relative flex h-16 w-16 items-center justify-center rounded-[9999px] border-2 bg-[#fff]/30 border-[#fff]\">\n\t\t\t\t\t\t<div className=\"h-4 w-4 rounded-[9999px] animate-pulse bg-[#fff]/80\" />\n\t\t\t\t\t</div>\n\t\t\t\t\t{children}\n\t\t\t\t</div>\n\t\t\t) : (\n\t\t\t\t<div\n\t\t\t\t\tclassName={cn(\"relative flex h-[4rem] w-[4rem] items-center justify-center rounded-[9999px] \", isInTargetRange ? \"bg-[#fff]/20 border-[#fff]\" : \"bg-[#fff]/10 border-[#fff]\")}\n\t\t\t\t\tstyle={{\n\t\t\t\t\t\ttransform: `translateY(${(90 - angle) * 3}px)`,\n\t\t\t\t\t\ttransition: \"transform 0.2s ease-out\",\n\t\t\t\t\t\tborder: `2px solid ${getColorCode()}`,\n\t\t\t\t\t}}\n\t\t\t\t>\n\t\t\t\t\t<div className={`h-[1rem] w-[1rem] rounded-[9999px] bg-[${getColorCode()}]/80`}\n style={{\n\t\t\t\t\t\tbackgroundColor: `${getColorCode()}B3`,\n\t\t\t\t\t}}\n />\n\t\t\t\t\t<div\n\t\t\t\t\t\t// className=\" text-[#fff]\"\n\t\t\t\t\t\tclassName={cn(\"mt-[.5rem] text-center w-[180px] flex-col flex items-center absolute top-[60px]\", getTextColor())}\n style={{\n\t\t\t\t\t\tcolor: getColorCode(),\n\t\t\t\t\t}}\n\t\t\t\t\t>\n\t\t\t\t\t\t<SwitchIcon size={30} />\n\t\t\t\t\t\t<p\n\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\tfontFamily: config?.style?.base?.baseFontFamily || \"Inter, sans-serif\",\n\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t{\" \"}\n\t\t\t\t\t\t\t{translate?.(LanguageKeys.startLevelCheck)}\n\t\t\t\t\t\t\t<br />\n\t\t\t\t\t\t</p>\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t)}\n\n\t\t\t{cd !== null && (\n\t\t\t\t<div className=\"absolute bottom-[8rem] text-center\">\n\t\t\t\t\t<div\n\t\t\t\t\t\tclassName={cn(\"text-sm font-medium px-4 py-1.5 bg-black/20 rounded-[9999px] mt-8\", getTextColor())}\n\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\tfontFamily: config?.style?.base?.baseFontFamily || \"Inter, sans-serif\",\n color: getColorCode(),\n\t\t\t\t\t\t}}\n\t\t\t\t\t>\n\t\t\t\t\t\t{translate?.(LanguageKeys.leavePhone)}\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t)}\n\t\t\t{isInTargetRange && cd === null && !isScanning && (\n\t\t\t\t<div className=\"absolute bottom-[8rem] w-[12rem]\">\n\t\t\t\t\t<div\n\t\t\t\t\t\tclassName={`h-[.375rem] w-full bg-[${getColorCode()}]/20 rounded-[9999px] overflow-hidden`}\n\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\tbackgroundColor: `${getColorCode()}33`, // 20% opacity\n\t\t\t\t\t\t}}\n\t\t\t\t\t>\n\t\t\t\t\t\t<div\n\t\t\t\t\t\t\tclassName={`h-full bg-[${getColorCode()}]/70 transition-all duration-300 rounded-[9999px]`}\n\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\twidth: `${angle}%`,\n\t\t\t\t\t\t\t\tbackgroundColor: `${getColorCode()}B3`,\n\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t/>\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t)}\n\n {cd === null && !isScanning && (\n <div className=\"absolute bottom-[5rem] text-center\">\n <div className={cn(\"text-[1.5rem] font-light\", getTextColor())}\n style={{\n\t\t\t\t\t\tcolor: getColorCode(),\n\t\t\t\t\t}}\n >\n {Math.round(angle)}°\n </div>\n </div>\n )}\n\n\t\t\t{cd === null && !isScanning && (\n\t\t\t\t<div className=\"absolute bottom-[2rem] text-center max-w-[20rem] mx-auto\">\n\t\t\t\t\t<div\n\t\t\t\t\t\tclassName={cn(\"text-[.75rem] opacity-50\", getTextColor())}\n\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\tfontFamily: config?.style?.base?.baseFontFamily || \"Inter, sans-serif\",\n color: getColorCode(),\n\t\t\t\t\t\t}}\n\t\t\t\t\t>\n\t\t\t\t\t\t{translate?.(LanguageKeys.placePhoneUpright)}\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t)}\n\t\t</div>\n\t);\n}\nexport default React.memo(LevelScreen);\n","import { useContext } from \"react\";\nimport Webcam from \"react-webcam\";\nimport { CameraScanChildProps } from \"../../types/interfaces\";\nimport { MEDIA_TYPES, MediaContext } from \"../../utils/context/mediaContext\";\nimport { LanguageContext } from \"../../utils/context/languageContext\";\nimport { pauseIcon, voiceOverAssetsPath } from \"../../utils/constants\";\nimport SpecificButton from \"../../atoms/specificButton/SpecificButton\";\nimport { LanguageKeys } from \"../../utils/languageKeys\";\nimport { X } from \"lucide-react\";\n\n\n\nfunction CameraScanChild({\n resetScan,\n loadingCam,\n onUserMedia,\n onPause,\n onReScan,\n pause,\n recordingStarted,\n startSendingVideoFrames,\n showPause,\n webcamRef,\n onUserMediaError,\n resetDetector,\n videoConstraints,\n webcamKey,\n faceDone,\n isScanning,\n}: Omit<CameraScanChildProps, \"config\">) {\n const { media } = useContext(MediaContext) || {};\n const { translate } = useContext(LanguageContext) || {};\n\n return (\n <div className=\"App w-screen h-[100vh] relative common-ui-main\" data-testid=\"camera-scan\" data-scan-phase={faceDone ? \"spinning\" : recordingStarted ? \"pose-detecting\" : isScanning ? \"starting\" : \"ready\"}>\n <span\n onClick={() => {\n resetScan();\n resetDetector();\n }}\n className=\"fixed right-[20px] top-[20px] z-[999]\"\n >\n <X className=\"text-[#fff]\" />\n </span>\n\n <div className=\"w-full h-full overflow-hidden \">\n {media === MEDIA_TYPES.MOBILE && (\n <Webcam\n key={webcamKey}\n audio={false}\n ref={webcamRef}\n screenshotQuality={1}\n videoConstraints={videoConstraints}\n mirrored\n screenshotFormat=\"image/jpeg\"\n onUserMedia={onUserMedia}\n onUserMediaError={onUserMediaError}\n style={{\n position: \"fixed\",\n top: 0,\n bottom: 0,\n zIndex: 0,\n width: \"100%\",\n height: \"100%\",\n objectFit: \"cover\",\n }}\n />\n )}\n </div>\n\n <div className=\"fixed bottom-[30px] w-full z-[999] flex flex-col gap-4 items-center justify-center\">\n {showPause && (\n <SpecificButton\n className=\"!w-[180px] !h-[40px] !py-[0] mx-auto \"\n prefix={pauseIcon}\n buttonText={translate?.(LanguageKeys.pause)}\n buttonFunc={onPause}\n btnSecondary\n />\n )}\n\n {pause ? (\n <div>\n <SpecificButton\n className=\"!w-[180px] !h-[40px] !py-[0] mx-auto\"\n buttonText={translate?.(LanguageKeys.restart)}\n buttonFunc={onReScan}\n btnSecondary\n />\n </div>\n ) : !recordingStarted ? (\n <SpecificButton\n data-testid=\"start-scan-btn\"\n className={`!w-[180px] !h-[40px] !py-[0] mx-auto !bg-[#ffffff] !text-[#000000] ${\n loadingCam ? \"!opacity-50\" : \"\"\n }`}\n buttonText={translate?.(LanguageKeys.startScan)}\n buttonFunc={startSendingVideoFrames}\n disabled={loadingCam}\n />\n ) : null}\n </div>\n\n <audio\n id=\"audioElement\"\n crossOrigin=\"anonymous\"\n preload=\"auto\"\n style={{\n position: \"absolute\",\n zIndex: -99999,\n }}\n src={`${voiceOverAssetsPath}scanAudioInstructions/silence.mp3`}\n />\n </div>\n );\n}\n\nexport default CameraScanChild;\n","import { useState, useRef, useEffect } from \"react\";\n// We keep this, but we will make it optional in the logic below\n\ntype KeypointTuple = [number, number, number];\n\n// GLOBAL SINGLETONS (Persist across component re-mounts)\n// This prevents reloading the heavy model if the user navigates away and back.\nlet globalLoadingPromise: Promise<boolean> | null = null;\nlet globalDetector: any = null;\nlet globalPoseLib: any = null;\n\nexport default function useTensorFlow() {\n const [consecutiveFronts, setConsecutiveFronts] = useState(0);\n const [spinPhase, setSpinPhase] = useState(0);\n const [isLoaded, setIsLoaded] = useState(false);\n\n const spinPhaseRef = useRef(0);\n const consecutiveFrontsRef = useRef(0);\n const mounted = useRef(true);\n\n useEffect(() => {\n mounted.current = true; // Reset on mount\n\n // 1. If already loaded globally, just use it.\n if (globalDetector) {\n setIsLoaded(true);\n return;\n }\n\n // 2. If not loading, start the process.\n if (!globalLoadingPromise) {\n globalLoadingPromise = loadDependenciesGlobal();\n }\n\n // 3. Wait for the global promise to resolve.\n globalLoadingPromise.then((success) => {\n if (success && mounted.current) {\n setIsLoaded(true);\n }\n });\n\n return () => {\n mounted.current = false;\n };\n }, []);\n\n /**\n * Loads TensorFlow/MediaPipe dynamically.\n * This logic is ISOLATED from the server.\n */\n async function loadDependenciesGlobal(): Promise<boolean> {\n // GUARDRAIL 1: Strict Environment Check\n // Ensure we are in a browser environment with media capabilities\n if (\n typeof window === 'undefined' || \n typeof navigator === 'undefined'\n ) {\n return false;\n }\n \n try {\n console.log(\"Starting TensorFlow preload...\");\n \n // GUARDRAIL 2: Dynamic Imports\n // These heavy modules are only fetched by the browser, never the server.\n const [poseLib, tfjsCore, tfjsBackend] = await Promise.all([\n import(\"@tensorflow-models/pose-detection\"),\n import(\"@tensorflow/tfjs-core\"),\n import(\"@tensorflow/tfjs-backend-webgl\") // Triggers backend registration side-effect\n ]);\n \n globalPoseLib = poseLib;\n \n // Explicitly set the backend to WebGL for performance\n await tfjsCore.setBackend('webgl');\n await tfjsCore.ready();\n console.log(\"TensorFlow backend ready (WebGL)\");\n\n // GUARDRAIL 3: Zero-Config Asset Loading\n // If TENSORFLOW_SOLUTION_PATH fails or is missing, we must fallback \n // to a CDN so the user doesn't have to copy files manually.\n const modelConfig = {\n runtime: \"mediapipe\",\n modelType: \"full\",\n solutionPath:\"https://cdn.jsdelivr.net/npm/@mediapipe/pose\", // Fallback for Zero Config\n } as const;\n\n try {\n globalDetector = await globalPoseLib.createDetector(\n globalPoseLib.SupportedModels.BlazePose,\n modelConfig\n );\n console.log(\"MediaPipe detector created successfully\");\n } catch (mediapipeError) {\n console.warn(\"MediaPipe failed, falling back to TFJS runtime:\", mediapipeError);\n \n // Fallback to TFJS runtime (slower but works without external assets)\n globalDetector = await globalPoseLib.createDetector(\n globalPoseLib.SupportedModels.BlazePose,\n {\n runtime: \"tfjs\",\n modelType: \"full\",\n }\n );\n console.log(\"TFJS detector created successfully\");\n }\n \n return true;\n } catch (error) {\n console.error(\"Failed to load TensorFlow dependencies:\", error);\n globalLoadingPromise = null; // Reset so retry is possible\n return false;\n }\n }\n\n function isFrontFrame(body: KeypointTuple[]) {\n // Guardrail: Ensure points exist before filtering\n if (!body || body.length === 0) return false;\n return body.filter((p) => p[2] > 0.7).length === 22;\n }\n\n const poseDetector = async (callback: () => void, webcamRef: any) => {\n // GUARDRAIL 4: Runtime Safety\n // Check if everything is truly ready before calculating\n if (!globalDetector || !mounted.current || !webcamRef?.current?.video) {\n return;\n }\n \n // Check if video is actually playing and has data\n const video = webcamRef.current.video;\n if (video.readyState < 2) return; \n\n try {\n const poses = await globalDetector.estimatePoses(\n video,\n { flipHorizontal: false }\n );\n\n if (!poses || !poses.length) return;\n\n const keypoints = poses[0].keypoints;\n \n // Standardize keypoints\n const body: KeypointTuple[] = keypoints\n .slice(11) // Ignore face keypoints (0-10)\n .map((kp: any) => [\n kp.x > 0 && kp.x < 720 ? kp.x : -1,\n kp.y > 0 && kp.y < 1280 ? kp.y : -1,\n kp.score ?? 0,\n ]);\n\n if (spinPhaseRef.current === 0 && !isFrontFrame(body)) {\n setConsecutiveFronts((prev) => prev + 1);\n }\n\n if (spinPhaseRef.current === 1 && isFrontFrame(body)) {\n setConsecutiveFronts((prev) => prev + 1);\n }\n\n if (spinPhaseRef.current === 2) callback();\n } catch (err) {\n console.error(\"Pose detection error:\", err);\n }\n };\n\n useEffect(() => {\n consecutiveFrontsRef.current = consecutiveFronts;\n if (consecutiveFronts > 6 && spinPhaseRef.current < 2) {\n setSpinPhase((s) => s + 1);\n setConsecutiveFronts(0);\n }\n }, [consecutiveFronts]);\n\n useEffect(() => {\n spinPhaseRef.current = spinPhase;\n }, [spinPhase]);\n\n const resetDetector = () => {\n spinPhaseRef.current = 0;\n consecutiveFrontsRef.current = 0;\n setConsecutiveFronts(0);\n setSpinPhase(0);\n };\n\n const retryLoading = async () => {\n if (!globalDetector && !globalLoadingPromise) {\n globalLoadingPromise = loadDependenciesGlobal();\n const success = await globalLoadingPromise;\n if (success && mounted.current) {\n setIsLoaded(true);\n }\n }\n };\n\n return { \n poseDetector, \n isLoaded,\n spinPhase,\n resetDetector,\n retryLoading\n };\n}","/* eslint-disable no-use-before-define */\nimport React, { useCallback, useContext, useEffect, useMemo, useRef, useState } from \"react\";\nimport CameraScanChild from \"./CameraScanChild\";\nimport posthog from \"../../utils/posthog\";\nimport Webcam from \"react-webcam\";\nimport { ScanningComponentProps } from \"../../types/interfaces\";\nimport useTensorFlow from \"../../customHooks/useTensorFlow\";\nimport ParamsContext from \"../../utils/context/paramsContext\";\nimport {\n\tgenerateUuid,\n\tgetCurrentTimeInSeconds,\n\tgetPreferredMediaRecorderTypes,\n\tgetRecordingExtension,\n\tgetRecordingMimeType,\n\tgetSupportedMediaRecorderTypes,\n\thandleScanTimeCapture,\n\trescanSupportCaptureEvent,\n} from \"../../utils/utils\";\nimport speechService from \"../../utils/service/speechService\";\nimport { videoConstraintsExact, videoConstraintsFallback, videoTypes, voiceOverAssetsPath } from \"../../utils/constants\";\n\nlet audioTimeoutId: ReturnType<typeof setTimeout> | undefined;\nlet lastVideoPlayed: {\n\tskipCount: number;\n\tno_of_times_skipped: number;\n\taudioName: string;\n} | null = null;\n\nfunction ScanningComponent({ setIsScanLocked, resetDetector, scanID, setIsVideoUploaded, setScanFailsError, setScanStartTime, setScanUniqueKey, userDetails }: Omit<ScanningComponentProps, \"config\">) {\n\tconst { email, shopDomain, gender, heightInCm } = userDetails;\n\tconst webcamRef = useRef<Webcam | null>(null);\n\tconst mediaRecorderRef = useRef<MediaRecorder | null>(null);\n\tconst recordedFpsRef = useRef<number | null>(null);\n\tconst [recordedChunks, setRecordedChunks] = useState<Blob[]>([]);\n\tconst [loadingCam, setLoadingCam] = useState(true);\n\tconst [recordingStarted, setRecordingStarted] = useState(false);\n\tconst [faceDone, setFaceDone] = useState(false);\n\tconst [mediaRecorderStopped, setMediaRecorderStopped] = useState(true);\n\tconst [isScanning, setIsScanning] = useState(false);\n\tconst captureVideoTimeOutHandle = useRef<ReturnType<typeof setTimeout> | null>(null);\n\tconst [audioSource, setAudioSource] = useState(\"\");\n\tconst [audioSourceList, setAudioSourceList] = useState<string[]>([]);\n\tconst [emptyAudioSource, setEmptyAudioSource] = useState(\"\");\n\tconst [startAgain, setStartAgain] = useState(false);\n\tconst [showRestart, setRestart] = useState(false);\n\tconst [pause, setPause] = useState(false);\n\tconst [events, setEvents] = useState<any>([]);\n\tconst [showPause, setShowPause] = useState(false);\n\tconst allowAudioToPlay = useRef(true);\n\tconst { poseDetector } = useTensorFlow();\n\tconst firstScan = useRef(true);\n\tconst poseStoppedRef = useRef(false);\n\tconst counterRef = useRef(0);\n\tconst consecutiveFalseRef = useRef(0);\n\tconst poseListenerRegistered = useRef(false);\n\tconst isConnectingRef = useRef(false);\n\tconst brilliantPlayedRef = useRef(false);\n\tconst postPoseProcessRef = useRef<() => void>(() => {});\n\tconst startSendingVideoFramesRef = useRef<() => void>(() => {});\n\tconst idRef = useRef<string | null>(null);\n\tconst [supportedTypes, setSupportedTypes] = useState<string[]>([]);\n\tconst [webcamKey, setWebcamKey] = useState(0);\n\tconst [currentVideoConstraints, setCurrentVideoConstraints] = useState<MediaTrackConstraints>(videoConstraintsExact);\n\tconst { setStartGyro, uploadScanFile, setUploadLoading, swan, onScanStart, onCaptureComplete } = useContext(ParamsContext);\n\n\t// Refs to avoid stale closures in callbacks after pause/restart\n\tconst scanIDRef = useRef(scanID);\n\tuseEffect(() => {\n\t\tscanIDRef.current = scanID;\n\t}, [scanID]);\n\n\tconst eventsRef = useRef(events);\n\tuseEffect(() => {\n\t\teventsRef.current = events;\n\t}, [events]);\n\n\tconst resetScan = () => {\n\t\tposeStoppedRef.current = false;\n\t\tclearTimeout(audioTimeoutId);\n\t\tif (captureVideoTimeOutHandle.current) clearTimeout(captureVideoTimeOutHandle.current);\n\t\tsetScanUniqueKey(generateUuid());\n\t\tsetScanFailsError(\"\");\n\t\tsetUploadLoading?.(false);\n\t\tsetRecordedChunks([]);\n\t\trecordedFpsRef.current = null;\n\t\tsetLoadingCam(true);\n\t\tsetRecordingStarted(false);\n\t\tsetFaceDone(false);\n\t\tsetMediaRecorderStopped(true);\n\t\tsetIsScanning(false);\n\t\tcaptureVideoTimeOutHandle.current = null;\n\t\tsetAudioSource(\"\");\n\t\tsetAudioSourceList([]);\n\t\tsetEmptyAudioSource(\"\");\n\t\tsetStartAgain(!startAgain);\n\t\tsetStartGyro(false);\n\t\tspeechService.stopAudio();\n\t\tsetRestart(false);\n\t\tsetPause(false);\n\t\tcounterRef.current = 0;\n\t\tconsecutiveFalseRef.current = 0;\n\t\tposeListenerRegistered.current = false;\n\t\tbrilliantPlayedRef.current = false;\n\t\tif (mediaRecorderRef.current !== null) {\n\t\t\tmediaRecorderRef.current.stop();\n\t\t}\n\n\t\tevents.forEach((el: any) => {\n\t\t\tif (mediaRecorderRef.current) mediaRecorderRef.current.removeEventListener(\"dataavailable\", el);\n\t\t});\n\n\t\tsetEvents([]);\n\t\tallowAudioToPlay.current = true;\n\t\tsetShowPause(false);\n\t\tsetIsVideoUploaded(false);\n\t\tif (webcamRef.current?.stream) {\n\t\t\tsetLoadingCam(false);\n\t\t}\n\t};\n\n\tconst handleRestart = async () => {\n\t\trescanSupportCaptureEvent({\n\t\t\teventName: `${shopDomain}/rescan`,\n\t\t\temail,\n\t\t\tscanID: scanIDRef.current,\n\t\t\theight: heightInCm,\n\t\t\tgender,\n\t\t\tstatus: false,\n\t\t});\n\t\tswan.poseDetection.disconnect();\n\t\tresetScan();\n\t\tawait handleSocket();\n\t};\n\n\tconst handleUserMedia = useCallback(() => {\n\t\tsetTimeout(() => {\n\t\t\tsetLoadingCam(false);\n\t\t}, 1000);\n\t}, []);\n\n\tconst handleUserMediaError = useCallback(\n\t\t(error: string | DOMException) => {\n\t\t\tconsole.log(\"camera error\", error);\n\t\t\t// Retry once with relaxed constraints for broader device compatibility.\n\t\t\tif (currentVideoConstraints === videoConstraintsExact) {\n\t\t\t\tsetCurrentVideoConstraints(videoConstraintsFallback);\n\t\t\t\tsetWebcamKey((prev) => prev + 1);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tsetLoadingCam(false);\n\t\t},\n\t\t[currentVideoConstraints],\n\t);\n\n\tconst handlePause = useCallback(() => {\n\t\tallowAudioToPlay.current = false;\n\t\tsetPause(true);\n\t\tsetShowPause(false);\n\t\tif (captureVideoTimeOutHandle.current) clearTimeout(captureVideoTimeOutHandle.current);\n\t\tif (mediaRecorderRef.current) {\n\t\t\tmediaRecorderRef.current.pause();\n\t\t}\n\t\tspeechService.stopAudio();\n\t\tswan.poseDetection.disconnect();\n\t\tposthog.capture(`${shopDomain}/pose_detection_disconnected`, {\n\t\t\tscanID: scanID,\n\t\t\temail,\n\t\t\tid: idRef.current,\n\t\t\treason: \"pause\",\n\t\t});\n\t\tcounterRef.current = 0;\n\t\tconsecutiveFalseRef.current = 0;\n\t\tposeListenerRegistered.current = false;\n\t\tbrilliantPlayedRef.current = false;\n\t\tif (mediaRecorderRef.current) {\n\t\t\tmediaRecorderRef.current.stop();\n\t\t}\n\t\tevents.forEach((el: any) => {\n\t\t\tif (mediaRecorderRef.current) mediaRecorderRef.current.removeEventListener(\"dataavailable\", el);\n\t\t});\n\t\tsetEvents([]);\n\t\tclearTimeout(audioTimeoutId);\n\t}, [mediaRecorderRef, events, speechService, allowAudioToPlay]);\n\n\t// const supportedTypes = videoTypes.filter((type) => MediaRecorder.isTypeSupported(type));\n\tconst preferredVideoTypes = useMemo(() => getPreferredMediaRecorderTypes(), []);\n\tconst recordingMimeType = getRecordingMimeType(supportedTypes);\n\tconst recordingExtension = getRecordingExtension(recordingMimeType);\n\n\tconst stopRecording = useCallback(async () => {\n\t\tallowAudioToPlay.current = true;\n\t\tawait speechService.playAudio(`${voiceOverAssetsPath}SpotOn.mp3`);\n\t\tsetPause(false);\n\t\tsetShowPause(false);\n\t\tif (captureVideoTimeOutHandle.current) clearTimeout(captureVideoTimeOutHandle.current);\n\t\tsetRecordingStarted(false);\n\t}, [captureVideoTimeOutHandle, speechService]);\n\n\tconst handleSocket = useCallback(async () => {\n\t\t// Guard against React StrictMode double-mount: skip if already connecting or connected\n\t\tif (isConnectingRef.current || idRef.current) return;\n\t\tisConnectingRef.current = true;\n\t\ttry {\n\t\t\tidRef.current = await swan.poseDetection.connect();\n\n\t\t\tposthog.capture(`${shopDomain}/pose_detection_connected`, {\n\t\t\t\tscanID: scanIDRef.current,\n\t\t\t\temail,\n\t\t\t\tid: idRef.current,\n\t\t\t});\n\t\t} catch (error) {\n\t\t\tconsole.log(error, \"while connecting websocket\");\n\t\t\tposthog.capture(`${shopDomain}/pose_detection_connect_failed`, {\n\t\t\t\tscanID: scanID,\n\t\t\t\temail,\n\t\t\t\terror: String(error),\n\t\t\t});\n\t\t} finally {\n\t\t\tisConnectingRef.current = false;\n\t\t}\n\t}, [scanID, shopDomain, email]);\n\n\tconst handleSpinDataAvailable = useCallback(\n\t\t({ data }: BlobEvent) => {\n\t\t\tif (data && data.size > 0 && allowAudioToPlay.current) {\n\t\t\t\tsetRecordedChunks((prev) => prev.concat(data));\n\t\t\t\tif (!poseStoppedRef.current && webcamRef.current) {\n\t\t\t\t\tposeStoppedRef.current = true;\n\t\t\t\t\tposeDetector(() => {\n\t\t\t\t\t\tstopRecording();\n\t\t\t\t\t\thandleScanTimeCapture({\n\t\t\t\t\t\t\teventName: `${shopDomain}/tensorFlow`,\n\t\t\t\t\t\t\tscanID: scanIDRef.current,\n\t\t\t\t\t\t\temail,\n\t\t\t\t\t\t\tmessage: \"recording stopped by tensorflow \",\n\t\t\t\t\t\t});\n\t\t\t\t\t}, webcamRef);\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\t[stopRecording, handleScanTimeCapture, shopDomain, email, webcamRef],\n\t);\n\n\tconst playAudio = useCallback(async () => {\n\t\tconst lastAudio = audioSourceList[audioSourceList.length - 1];\n\t\tif (lastAudio && allowAudioToPlay.current) {\n\t\t\tawait speechService.playAudio(voiceOverAssetsPath + lastAudio);\n\t\t\tif (allowAudioToPlay.current) {\n\t\t\t\taudioTimeoutId = setTimeout(playAudio, 2000);\n\t\t\t}\n\t\t}\n\t}, [audioSourceList, allowAudioToPlay]);\n\n\tconst handleStartCaptureClick = useCallback(() => {\n\t\tif (mediaRecorderRef && mediaRecorderRef.current) {\n\t\t\tmediaRecorderRef.current.stop();\n\t\t}\n\t\tsetRecordingStarted(true);\n\t\ttry {\n\t\t\tif (webcamRef && webcamRef.current && webcamRef.current.stream) {\n\t\t\t\t// Capture FPS from stream settings\n\t\t\t\tconst videoTrack = webcamRef.current.stream.getVideoTracks()[0];\n\t\t\t\tif (videoTrack) {\n\t\t\t\t\tconst settings = videoTrack.getSettings();\n\t\t\t\t\trecordedFpsRef.current = settings.frameRate || null;\n\t\t\t\t}\n\n\t\t\t\tconst mediaRecorderOptions: MediaRecorderOptions = {\n\t\t\t\t\tvideoBitsPerSecond: 1_500_000,\n\t\t\t\t};\n\t\t\t\tif (supportedTypes[0]) {\n\t\t\t\t\tmediaRecorderOptions.mimeType = supportedTypes[0];\n\t\t\t\t}\n\t\t\t\tmediaRecorderRef.current = new MediaRecorder(webcamRef.current.stream, mediaRecorderOptions);\n\t\t\t\tmediaRecorderRef.current.addEventListener(\"dataavailable\", handleSpinDataAvailable);\n\n\t\t\t\t// Mark recorder as fully stopped only after all dataavailable events have fired\n\t\t\t\tmediaRecorderRef.current.addEventListener(\"stop\", () => {\n\t\t\t\t\tsetMediaRecorderStopped(true);\n\t\t\t\t});\n\n\t\t\t\tsetEvents([...events, handleSpinDataAvailable]);\n\t\t\t\tmediaRecorderRef.current.start(1000);\n\t\t\t\tsetMediaRecorderStopped(false);\n\t\t\t}\n\t\t} catch (e) {\n\t\t\tconsole.log(\"error while using media recorder\", e);\n\t\t}\n\t}, [webcamRef, supportedTypes, handleSpinDataAvailable, events]);\n\n\tconst postPoseProcess = useCallback(async () => {\n\t\tif (captureVideoTimeOutHandle.current) {\n\t\t\tclearTimeout(captureVideoTimeOutHandle.current);\n\t\t}\n\t\thandleStartCaptureClick();\n\t\tif (allowAudioToPlay.current) {\n\t\t\tcaptureVideoTimeOutHandle.current = setTimeout(async () => {\n\t\t\t\tif (allowAudioToPlay.current) {\n\t\t\t\t\tawait speechService.playAudio(`${voiceOverAssetsPath}SpotOn.mp3`);\n\t\t\t\t\tsetRecordingStarted(false);\n\t\t\t\t}\n\t\t\t}, 15000);\n\t\t}\n\t\tsetFaceDone(true);\n\t\tif (allowAudioToPlay.current) {\n\t\t\tawait speechService.playAudio(`${voiceOverAssetsPath}Spin.mp3`);\n\t\t}\n\t}, [handleStartCaptureClick, allowAudioToPlay, speechService]);\n\n\tuseEffect(() => {\n\t\tpostPoseProcessRef.current = postPoseProcess;\n\t}, [postPoseProcess]);\n\n\tconst handleDataAvailable = useCallback(\n\t\t({ data }: BlobEvent) => {\n\t\t\tconst connected = swan.poseDetection.connected();\n\t\t\tif (data.size > 0 && connected) {\n\t\t\t\tif (!poseListenerRegistered.current) {\n\t\t\t\t\tposeListenerRegistered.current = true;\n\t\t\t\t\tswan.poseDetection.poseStatus(async (data: any) => {\n\t\t\t\t\t\tif (data && data.audio && data.audio.length > 0) {\n\t\t\t\t\t\t\tconst audio = document.querySelector(\"#audioElement\") as HTMLAudioElement | null;\n\n\t\t\t\t\t\t\tposthog.capture(`${shopDomain}/pose_instruction_received`, {\n\t\t\t\t\t\t\t\tscanID: scanIDRef.current,\n\t\t\t\t\t\t\t\temail,\n\t\t\t\t\t\t\t\taudio: data.audio,\n\t\t\t\t\t\t\t\tstatus: data.status,\n\t\t\t\t\t\t\t\tsid: data.sid,\n\t\t\t\t\t\t\t\tcounter: counterRef.current,\n\t\t\t\t\t\t\t\tconsecutiveFalse: consecutiveFalseRef.current,\n\t\t\t\t\t\t\t\ttype: \"body_scan_instruction\",\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\tif (data.status === true && data.sid === idRef.current) {\n\t\t\t\t\t\t\t\tconsecutiveFalseRef.current = 0;\n\t\t\t\t\t\t\t\tif (counterRef.current < 2) {\n\t\t\t\t\t\t\t\t\tcounterRef.current += 1;\n\t\t\t\t\t\t\t\t\tif (counterRef.current === 1 && !brilliantPlayedRef.current) {\n\t\t\t\t\t\t\t\t\t\tbrilliantPlayedRef.current = true;\n\t\t\t\t\t\t\t\t\t\tclearTimeout(audioTimeoutId);\n\t\t\t\t\t\t\t\t\t\tspeechService.stopAudio();\n\t\t\t\t\t\t\t\t\t\tawait speechService.playAudio(voiceOverAssetsPath + data.audio);\n\t\t\t\t\t\t\t\t\t} else if (counterRef.current === 2 && audio?.paused) {\n\t\t\t\t\t\t\t\t\t\tclearTimeout(audioTimeoutId);\n\t\t\t\t\t\t\t\t\t\tspeechService.playAudio(voiceOverAssetsPath + data.audio);\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tsetEmptyAudioSource(data.audio);\n\t\t\t\t\t\t\t\t\tclearTimeout(audioTimeoutId);\n\t\t\t\t\t\t\t\t\tswan.poseDetection.disconnect();\n\t\t\t\t\t\t\t\t\tposthog.capture(`${shopDomain}/pose_detection_disconnected`, {\n\t\t\t\t\t\t\t\t\t\tscanID: scanID,\n\t\t\t\t\t\t\t\t\t\temail,\n\t\t\t\t\t\t\t\t\t\tid: idRef.current,\n\t\t\t\t\t\t\t\t\t\treason: \"pose_confirmed\",\n\t\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t\t\tposeListenerRegistered.current = false;\n\t\t\t\t\t\t\t\t\tsetTimeout(() => postPoseProcessRef.current(), 1000);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tconsecutiveFalseRef.current += 1;\n\t\t\t\t\t\t\t\tif (consecutiveFalseRef.current >= 3) {\n\t\t\t\t\t\t\t\t\tcounterRef.current = 0;\n\t\t\t\t\t\t\t\t\tbrilliantPlayedRef.current = false;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tif (audio?.paused && (!lastVideoPlayed || lastVideoPlayed?.audioName !== data.audio)) {\n\t\t\t\t\t\t\t\t\tlastVideoPlayed = {\n\t\t\t\t\t\t\t\t\t\tskipCount: 2,\n\t\t\t\t\t\t\t\t\t\tno_of_times_skipped: 0,\n\t\t\t\t\t\t\t\t\t\taudioName: data.audio,\n\t\t\t\t\t\t\t\t\t};\n\t\t\t\t\t\t\t\t\tspeechService.playAudio(voiceOverAssetsPath + data.audio);\n\t\t\t\t\t\t\t\t} else if (lastVideoPlayed?.audioName === data.audio && audio?.paused) {\n\t\t\t\t\t\t\t\t\tif (lastVideoPlayed && lastVideoPlayed.no_of_times_skipped >= lastVideoPlayed.skipCount) {\n\t\t\t\t\t\t\t\t\t\tlastVideoPlayed.no_of_times_skipped = 0;\n\t\t\t\t\t\t\t\t\t\tspeechService.playAudio(voiceOverAssetsPath + data.audio);\n\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\tif (lastVideoPlayed) lastVideoPlayed.no_of_times_skipped += 1;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\tif (webcamRef?.current && webcamRef.current.getScreenshot() !== null) {\n\t\t\t\t\tconsole.log(\"[videoEmit] sending frame with scanId:\", scanIDRef.current);\n\t\t\t\t\tswan.poseDetection.videoEmit({\n\t\t\t\t\t\timage: webcamRef.current.getScreenshot() || \"\",\n\t\t\t\t\t\tscanId: scanIDRef.current,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\t[webcamRef, scanID, swan, speechService, shopDomain, email],\n\t);\n\n\tconst startSendingVideoFrames = useCallback(async () => {\n\t\tsetIsScanning(true);\n\t\tsetStartGyro(true);\n\t\tonScanStart?.();\n\t\tif (firstScan.current) {\n\t\t\tfirstScan.current = false;\n\t\t\thandleScanTimeCapture({\n\t\t\t\teventName: \"scan started\",\n\t\t\t\tscanID: scanIDRef.current,\n\t\t\t\tstatus: \"success\",\n\t\t\t\temail,\n\t\t\t});\n\t\t}\n\t\tsetScanStartTime(getCurrentTimeInSeconds());\n\t\tsetLoadingCam(true);\n\t\tif (allowAudioToPlay.current) {\n\t\t\tawait speechService.playAudio(`${voiceOverAssetsPath}StartScan.mp3`);\n\t\t}\n\t\tif (allowAudioToPlay.current) {\n\t\t\tawait speechService.playAudio(`${voiceOverAssetsPath}LiftArmsAndHoldAtHip.mp3`);\n\t\t}\n\t\tif (allowAudioToPlay.current) {\n\t\t\tsetIsScanning(false);\n\t\t\tsetRecordingStarted(true);\n\t\t\tsetRestart(true);\n\t\t\tsetShowPause(true);\n\t\t\thandleUserMedia();\n\t\t}\n\t\ttry {\n\t\t\tif (webcamRef && webcamRef.current && webcamRef.current.stream && allowAudioToPlay.current) {\n\t\t\t\t// Capture FPS from stream settings\n\t\t\t\tconst videoTrack = webcamRef.current.stream.getVideoTracks()[0];\n\t\t\t\tif (videoTrack) {\n\t\t\t\t\tconst settings = videoTrack.getSettings();\n\t\t\t\t\trecordedFpsRef.current = settings.frameRate || null;\n\t\t\t\t}\n\n\t\t\t\tconst mediaRecorderOptions: MediaRecorderOptions = {\n\t\t\t\t\tvideoBitsPerSecond: 1_500_000,\n\t\t\t\t};\n\t\t\t\tif (supportedTypes[0]) {\n\t\t\t\t\tmediaRecorderOptions.mimeType = supportedTypes[0];\n\t\t\t\t}\n\t\t\t\tif (allowAudioToPlay.current) {\n\t\t\t\t\tmediaRecorderRef.current = new MediaRecorder(webcamRef.current.stream, mediaRecorderOptions);\n\t\t\t\t}\n\t\t\t\tif (allowAudioToPlay.current && mediaRecorderRef.current) {\n\t\t\t\t\tmediaRecorderRef.current.addEventListener(\"dataavailable\", handleDataAvailable);\n\t\t\t\t}\n\n\t\t\t\tsetEvents([...eventsRef.current, handleDataAvailable]);\n\t\t\t\tif (mediaRecorderRef.current) mediaRecorderRef.current.start(1000);\n\t\t\t\tsetMediaRecorderStopped(false);\n\t\t\t\tif (allowAudioToPlay.current) {\n\t\t\t\t\taudioTimeoutId = setTimeout(playAudio, 2000);\n\t\t\t\t}\n\t\t\t}\n\t\t} catch (err) {\n\t\t\tconsole.log(\"error ----------\", err);\n\t\t}\n\t}, [webcamRef, supportedTypes, handleDataAvailable, playAudio, allowAudioToPlay, onScanStart]);\n\n\tuseEffect(() => {\n\t\tstartSendingVideoFramesRef.current = startSendingVideoFrames;\n\t}, [startSendingVideoFrames]);\n\n\tuseEffect(() => {\n\t\tif (shopDomain) {\n\t\t\tsetIsScanLocked(true);\n\t\t\thandleSocket();\n\t\t}\n\t\treturn () => {\n\t\t\t// Capture then reset id so next genuine mount can reconnect.\n\t\t\t// Do NOT reset isConnectingRef here — keeping it true blocks the\n\t\t\t// StrictMode second-mount call while the first connect is still awaiting.\n\t\t\tconst prevId = idRef.current;\n\t\t\tidRef.current = null;\n\t\t\tif (prevId) {\n\t\t\t\tswan.poseDetection.disconnect();\n\t\t\t\tposthog.capture(`${shopDomain}/pose_detection_disconnected`, {\n\t\t\t\t\tscanID: scanIDRef.current,\n\t\t\t\t\temail,\n\t\t\t\t\tid: prevId,\n\t\t\t\t\treason: \"unmount\",\n\t\t\t\t});\n\t\t\t}\n\t\t\tevents.forEach((el: any) => {\n\t\t\t\tmediaRecorderRef?.current?.removeEventListener(\"dataavailable\", el);\n\t\t\t});\n\t\t};\n\t}, [shopDomain]);\n\tuseEffect(() => {\n\t\taudioSourceList.push(audioSource);\n\t}, [audioSource]);\n\n\tuseEffect(() => {\n\t\tsetAudioSourceList([]);\n\t}, [emptyAudioSource]);\n\tuseEffect(() => {\n\t\tconst bypassChecksToBackup = recordedChunks.length && recordedChunks.length > 0;\n\t\tif (!mediaRecorderStopped && bypassChecksToBackup && !recordingStarted && allowAudioToPlay.current && !pause) {\n\t\t\tif (mediaRecorderRef && mediaRecorderRef.current) {\n\t\t\t\tif (!recordingStarted) {\n\t\t\t\t\tmediaRecorderRef.current.stop();\n\t\t\t\t\t// mediaRecorderStopped will be set by the \"stop\" event listener\n\t\t\t\t\t// which fires AFTER all dataavailable events are done\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}, [mediaRecorderStopped, recordingStarted, recordedChunks, pause]);\n\n\tuseEffect(() => {\n\t\tconst bypassChecksToBackup = recordedChunks.length && recordedChunks.length > 0;\n\t\tif (mediaRecorderStopped && bypassChecksToBackup && !recordingStarted) {\n\t\t\tif (mediaRecorderRef && mediaRecorderRef.current && allowAudioToPlay.current && !pause) {\n\t\t\t\tif (!recordingStarted) {\n\t\t\t\t\tconst videoFile = new File(recordedChunks, `${scanID}.${recordingExtension}`, {\n\t\t\t\t\t\ttype: recordingMimeType,\n\t\t\t\t\t});\n\t\t\t\t\tonCaptureComplete?.();\n\t\t\t\t\tsetUploadLoading?.(true);\n\t\t\t\t\tsetScanFailsError(\"\");\n\t\t\t\t\t// Pass FPS captured at recording time\n\t\t\t\t\tuploadScanFile?.(videoFile, recordedFpsRef.current);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}, [mediaRecorderStopped, recordingStarted, recordedChunks, pause, mediaRecorderRef, allowAudioToPlay]);\n\tuseEffect(() => {\n\t\tstartSendingVideoFramesRef.current = startSendingVideoFrames;\n\t}, [startSendingVideoFrames]);\n\n\tuseEffect(() => {\n\t\tconst supported = getSupportedMediaRecorderTypes(preferredVideoTypes, videoTypes);\n\t\tsetSupportedTypes(supported);\n\t}, [preferredVideoTypes]);\n\tuseEffect(() => {\n\t\tresetScan();\n\t}, []);\n\n\treturn (\n\t\t<CameraScanChild\n\t\t\tresetDetector={resetDetector}\n\t\t\tresetScan={resetScan}\n\t\t\tloadingCam={loadingCam}\n\t\t\tonPause={handlePause}\n\t\t\tshowRestart={showRestart}\n\t\t\tpause={pause}\n\t\t\tonReScan={handleRestart}\n\t\t\trecordingStarted={recordingStarted}\n\t\t\tisScanning={isScanning}\n\t\t\tstartSendingVideoFrames={startSendingVideoFrames}\n\t\t\tfaceDone={faceDone}\n\t\t\tstopRecording={stopRecording}\n\t\t\tshowPause={showPause}\n\t\t\twebcamRef={webcamRef}\n\t\t\tonUserMedia={handleUserMedia}\n\t\t\tonUserMediaError={handleUserMediaError}\n\t\t\tvideoConstraints={currentVideoConstraints}\n\t\t\twebcamKey={webcamKey}\n\t\t/>\n\t);\n}\n\nexport default React.memo(ScanningComponent);\n","/* eslint-disable no-use-before-define */\n\nimport { useEffect, useState, useRef } from \"react\";\nimport { IOSDeviceOrientationEvent } from \"../../customHooks/useGyroSensor\";\nimport LevelScreen from \"./LevelScreen\";\nimport ScanningComponent from \"./ScanningComponent\";\nimport { AngleDetectorProps } from \"../../types/interfaces\";\n\nexport default function AngleDetector({\n scanID,\n userDetails,\n setIsVideoUploaded,\n setScanFailsError,\n setScanStartTime,\n setScanUniqueKey,\n}: Omit<AngleDetectorProps, \"config\">) {\n const [angle, setAngle] = useState(90);\n const [calibrationOffset, setCalibrationOffset] = useState(0);\n const [countdown, setCountdown] = useState<number | null>(null);\n const [isScanning, setIsScanning] = useState(false);\n const [stabilityScore, setStabilityScore] = useState(0);\n const lastAnglesRef = useRef<number[]>([]);\n const [isScanLocked, setIsScanLocked] = useState(false);\n const calibratedAngle = angle - calibrationOffset;\n const isInTargetRange = calibratedAngle >= 80 && calibratedAngle <= 95;\n\n const resetDetector = () => {\n setAngle(90);\n setCalibrationOffset(0);\n setCountdown(null);\n setIsScanning(false);\n setStabilityScore(0);\n setIsScanLocked(false);\n lastAnglesRef.current = [];\n };\n\n useEffect(() => {\n if (typeof window !== \"undefined\" && window.DeviceOrientationEvent) {\n const handleOrientation = (event: DeviceOrientationEvent) => {\n if (event.beta !== null) {\n let newAngle = Math.abs(event.beta);\n if (event.gamma !== null) {\n newAngle *= Math.cos((event.gamma * Math.PI) / 180);\n }\n newAngle = Math.max(0, Math.min(180, newAngle));\n setAngle(newAngle);\n }\n };\n\n const requestPermission = async () => {\n const DeviceOrientation =\n DeviceOrientationEvent as unknown as IOSDeviceOrientationEvent;\n\n if (\n DeviceOrientation &&\n typeof DeviceOrientation.requestPermission === \"function\"\n ) {\n try {\n const permission = await DeviceOrientation.requestPermission();\n if (permission === \"granted\") {\n // wrappedHandler = timeout(handleOrientation, 2000);\n window.addEventListener(\"deviceorientation\", handleOrientation);\n }\n } catch (e) {\n console.error(\"Permission error\", e);\n }\n } else {\n // wrappedHandler = handleOrientation;\n window.addEventListener(\"deviceorientation\", handleOrientation);\n }\n\n return () => {\n if (handleOrientation) {\n window.removeEventListener(\"deviceorientation\", handleOrientation);\n }\n };\n };\n\n document.addEventListener(\"click\", requestPermission, { once: true });\n }\n }, []);\n\n useEffect(() => {\n lastAnglesRef.current = [\n ...lastAnglesRef.current.slice(-4),\n calibratedAngle,\n ];\n\n if (lastAnglesRef.current.length >= 5) {\n const variation =\n Math.max(...lastAnglesRef.current) - Math.min(...lastAnglesRef.current);\n if (isInTargetRange && variation < 2) {\n setStabilityScore((prev) => Math.min(100, prev + 10));\n } else {\n setStabilityScore((prev) => Math.max(0, prev - 20));\n }\n }\n\n if (!isInTargetRange && (countdown !== null || isScanning)) {\n resetCountdown();\n }\n }, [calibratedAngle, isInTargetRange, countdown, isScanning]);\n\n\tuseEffect(() => {\n\t\tif (stabilityScore >= 100 && countdown === null && !isScanning ) {\n\t\t\tstartCountdown();\n\t\t}\n\t\tif (stabilityScore < 50 && countdown !== null) {\n\t\t\tresetCountdown();\n\t\t}\n\t}, [stabilityScore, countdown, isScanning]);\n\n const startCountdown = () => {\n setCountdown(3);\n const timer = setInterval(() => {\n setCountdown((prev) => {\n if (prev === null || prev <= 1) {\n clearInterval(timer);\n setIsScanning(true);\n return null;\n }\n return prev - 1;\n });\n }, 1000);\n };\n\n const resetCountdown = () => {\n setCountdown(null);\n if (!isScanLocked) {\n setIsScanning(false);\n }\n };\n\n\n return (\n <LevelScreen\n angle={calibratedAngle}\n countdown={countdown}\n isScanning={isScanning}\n isInTargetRange={isInTargetRange}\n stabilityScore={stabilityScore}\n >\n {isScanning && (\n <ScanningComponent\n setIsScanLocked={setIsScanLocked}\n resetDetector={resetDetector}\n scanID={scanID}\n userDetails={userDetails}\n setIsVideoUploaded={setIsVideoUploaded}\n setScanFailsError={setScanFailsError}\n setScanStartTime={setScanStartTime}\n setScanUniqueKey={setScanUniqueKey}\n />\n )}\n </LevelScreen>\n );\n}\n","import { useEffect, useState, useRef, useCallback, Dispatch, SetStateAction } from \"react\";\nimport Webcam from \"react-webcam\";\nimport Modal from \"../Modal\";\nimport LoadingScreen from \"../LoadingScreen\";\nimport { checkCameraPermission } from \"../../utils/utils\";\nimport { videoConstraints } from \"../../utils/constants\";\n\n\nfunction CameraPermission({ setShowDrawer, config,loader }: { setShowDrawer?: Dispatch<SetStateAction<boolean>>; config?: any,loader?:string }) {\n\tconst [showDeniedModal, setShowDeniedModal] = useState({\n\t\tdisabled: false,\n\t\tmessage: \"\",\n\t});\n\tconst [loading, setLoading] = useState(true);\n\tconst webcamRef = useRef(null);\n\n\tconst handleCameraPermission = useCallback(async () => {\n\t\tconst permission = await checkCameraPermission();\n\t\tsetShowDeniedModal(permission);\n\t\tsetLoading(false);\n\t}, []);\n\n\tuseEffect(() => {\n\t\thandleCameraPermission();\n\t}, []);\n\n\tif (loading) {\n\t\treturn <LoadingScreen url={loader} loaderType=\"black\" />\n\t}\n\n\tif (showDeniedModal?.disabled) {\n\t\treturn <Modal config={config} message={showDeniedModal?.message} />;\n\t}\n\treturn (\n\t\t<Webcam\n\t\t\taudio={false}\n\t\t\tref={webcamRef}\n\t\t\tscreenshotQuality={1}\n\t\t\tvideoConstraints={videoConstraints}\n\t\t\tmirrored\n\t\t\tonUserMedia={() => setShowDrawer?.(true)}\n\t\t\tscreenshotFormat=\"image/jpeg\"\n\t\t\tstyle={{\n\t\t\t\tposition: \"relative\",\n\t\t\t\ttop: 0,\n\t\t\t\tbottom: 0,\n\t\t\t\tzIndex: 0,\n\t\t\t\twidth: \"100%\",\n\t\t\t\theight: \"100%\",\n\t\t\t\tobjectFit: \"cover\",\n\t\t\t}}\n\t\t/>\n\t);\n}\n\nexport default CameraPermission;\n","\nimport React, { useEffect, useRef } from \"react\";\nimport videojs from \"video.js\";\nimport type Player from \"video.js/dist/types/player\";\nimport { videoPoster } from \"../../utils/constants\";\n\nfunction VideoPlayer({ link, onReady, wrapperClassName = \"[&_video]:rounded-t-[20px] w-full h-full\" }: { link?: string; wrapperClassName?: string; onReady?: (args: Player) => void }) {\n\tconst videoReference = useRef<HTMLVideoElement | null>(null);\n\tconst playerReference = useRef<Player | null>(null);\n\n\tlet videoJsOptions: any = {\n\t\tautoplay: true,\n\t\tcontrols: false,\n\t\tresponsive: true,\n\t\tfluid: true,\n\t\tmuted: true,\n\t\tnavigationUI: \"hide\",\n\t\tpreload: \"metadata\",\n\t\tposter: videoPoster,\n\t};\n\n\tuseEffect(() => {\n\t\tif (!playerReference.current && link && videoReference?.current) {\n\t\t\tconst player = videojs(videoReference.current, {\n\t\t\t\t...videoJsOptions,\n\t\t\t});\n\t\t\tplayer.ready(() => {\n\t\t\t\tplayerReference.current = player;\n\n\t\t\t\tconst updatedOptions = {\n\t\t\t\t\t...videoJsOptions,\n\t\t\t\t\tsources: [{ src: link, type: \"application/x-mpegURL\" }],\n\t\t\t\t};\n\n\t\t\t\tplayer.autoplay(updatedOptions.autoplay);\n\t\t\t\tplayer.src(updatedOptions.sources);\n\n\t\t\t\tonReady?.(player);\n\t\t\t});\n\t\t}\n\t}, [link, videoReference]);\n\n\tuseEffect(() => {\n\t\tconst player = playerReference.current;\n\t\treturn () => {\n\t\t\tif (player && !player.isDisposed()) {\n\t\t\t\tplayer.dispose();\n\t\t\t\tplayerReference.current = null;\n\t\t\t}\n\t\t};\n\t}, [playerReference]);\n\n\treturn (\n\t\t<div className={wrapperClassName}>\n\t\t\t<video ref={videoReference} muted className=\"video-js\" playsInline onDrag={(e) => e.preventDefault()} />\n\t\t</div>\n\t);\n}\nexport default VideoPlayer;\n","import { useContext, useState } from \"react\";\nimport {Dialog} from \"@mui/material\";\nimport { LanguageContext } from \"../../utils/context/languageContext\";\nimport Header from \"../Header\";\nimport VideoPlayer from \"./VideoPlayer\";\nimport { ScanErrorMessageProps } from \"../../types/interfaces\";\nimport { generateUuid, handleErrorMessage } from \"../../utils/utils\";\nimport { GENDER, VIDEO_POSTER_GENDER_BASED } from \"../../utils/constants\";\nimport SpecificButton from \"../../atoms/specificButton/SpecificButton\";\nimport { LanguageKeys } from \"../../utils/languageKeys\";\nimport { X } from \"lucide-react\";\nimport { useConfig } from \"../../utils/context/configContext\";\n\nfunction ScanErrorMessage({ scanFailsError, onNext, gender, setScanUniqueKey, setIsVideoUploaded }: ScanErrorMessageProps) {\n\tconst { translate } = useContext(LanguageContext) || {};\n\tconst resolvedConfig = useConfig();\n\tconst [showModal, setShowModal] = useState(false);\n\n\tconst handleBtnClick = () => {\n\t\tif (onNext) {\n\t\t\tonNext?.();\n\t\t} else {\n\t\t\tsetScanUniqueKey?.(generateUuid());\n\t\t}\n\t\tsetIsVideoUploaded?.(false);\n\t};\n\n\tconst handleShowModal = () => {\n\t\tsetShowModal(!showModal);\n\t};\n\n\n\treturn (\n\t\t<>\n\t\t\t<div data-testid=\"scan-error-message\" className=\"flex common-ui-main flex-col h-full max-w-[28rem] mx-auto w-full rounded-t-[20px] overflow-y-auto\" style={{ background: resolvedConfig?.style?.base?.backgroundColor }}>\n\t\t\t\t<div className=\"w-full max-w-[28rem] mx-auto pt-[1rem] px-[1rem]\">\n\t\t\t\t\t<Header noTitle />\n\t\t\t\t</div>\n\t\t\t\t<div className=\"flex-1\">\n\t\t\t\t\t{scanFailsError && (\n\t\t\t\t\t\t<div className=\"px-[1rem]\">\n\t\t\t\t\t\t\t<h2\n\t\t\t\t\t\t\t\tclassName=\"text-center\"\n\t\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\t\tfontFamily: resolvedConfig?.style?.heading?.headingFontFamily || \"SeriouslyNostalgic Fn\",\n\t\t\t\t\t\t\t\t\tfontSize: resolvedConfig?.style?.heading?.headingFontSize || \"32px\",\n\t\t\t\t\t\t\t\t\tcolor: resolvedConfig?.style?.heading?.headingColor || \"#000\",\n\t\t\t\t\t\t\t\t\tfontWeight: resolvedConfig?.style?.heading?.headingFontWeight || \"normal\",\n\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t{translate?.(LanguageKeys.issueWithScan)}\n\t\t\t\t\t\t\t</h2>\n\t\t\t\t\t\t\t<p\n\t\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\t\tfontFamily: resolvedConfig?.style?.base?.baseFontFamily || \"Inter, sans-serif\",\n\t\t\t\t\t\t\t\t\tfontSize: resolvedConfig?.style?.base?.baseFontSize || \"16px\",\n\t\t\t\t\t\t\t\t\tcolor: resolvedConfig?.style?.base?.baseTextColor || \"#1E1E1E\",\n\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t{translate?.(LanguageKeys.reason)}\n\t\t\t\t\t\t\t</p>\n\t\t\t\t\t\t\t<p\n\t\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\t\tfontFamily: resolvedConfig?.style?.base?.baseFontFamily || \"Inter, sans-serif\",\n\t\t\t\t\t\t\t\t\tfontSize: resolvedConfig?.style?.base?.baseFontSize || \"16px\",\n\t\t\t\t\t\t\t\t\tcolor: resolvedConfig?.style?.base?.baseTextColor || \"#1E1E1E\",\n\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t{handleErrorMessage(scanFailsError)}\n\t\t\t\t\t\t\t</p>\n\n\t\t\t\t\t\t\t<img className=\"my-[0.5rem] aspect-[2/1.4] w-full object-cover\" onClick={handleShowModal} src={VIDEO_POSTER_GENDER_BASED[gender]} alt=\"icon\" />\n\t\t\t\t\t\t</div>\n\t\t\t\t\t)}\n\t\t\t\t</div>\n\t\t\t\t{scanFailsError && (\n\t\t\t\t\t<div className=\"p-[1rem] flex gap-[0.5rem]\">\n\t\t\t\t\t\t<SpecificButton data-testid=\"scan-again-btn\" disabled={false} buttonText={translate?.(LanguageKeys.scanAgain)} className=\"!shadow-none\" buttonFunc={handleBtnClick} />\n\t\t\t\t\t</div>\n\t\t\t\t)}\n\t\t\t</div>\n\t\t\t{showModal && (\n\t\t\t\t<Dialog className=\"w-screen h-screen video-modal\" onClose={handleShowModal} open={showModal}>\n\t\t\t\t\t<div className=\"flex justifyEnd \">\n\t\t\t\t\t\t<span className=\"closeBtn\" onClick={handleShowModal}>\n\t\t\t\t\t\t\t<X className=\"absolute right-[8px] top-[8px] text-white z-[9]\" />\n\t\t\t\t\t\t</span>\n\t\t\t\t\t</div>\n\t\t\t\t\t<div className=\"aspect-video object-cover rounded-[20px] \">\n\t\t\t\t\t\t<VideoPlayer link={gender ? GENDER[gender].PRE_LINK : GENDER.male.PRE_LINK} wrapperClassName=\"w-screen h-screen fixed top-[0] left-[0]\" />\n\t\t\t\t\t</div>\n\t\t\t\t</Dialog>\n\t\t\t)}\n\t\t</>\n\t);\n}\n\nexport default ScanErrorMessage;\n","import { useCallback, useContext, useEffect, useState } from \"react\";\nimport {Box,Drawer} from \"@mui/material\";\nimport posthog from \"../utils/posthog\";\nimport Header from \"./Header\";\nimport CameraPermission from \"./bodyScan/CameraPermission\";\nimport { SignUpProps } from \"../types/interfaces\";\nimport { CLOTHING_BANNER_SCAN, CLOTHING_CUSTOM_FIT_SCAN, CLOTHING_CUSTOM_SCAN, maleMeasurementProgress, measurementProgress } from \"../utils/constants\";\nimport { GenderType } from \"../utils/enums\";\nimport SpecificButton from \"../atoms/specificButton/SpecificButton\";\nimport { LanguageContext } from \"../utils/context/languageContext\";\nimport { LanguageKeys } from \"../utils/languageKeys\";\n\nfunction SignUp({\n\tscanId,\n\tuserDetails,\n\tconfig,\n\tisVideoUploadedCorrect,\n\tisMeasurementAvailable,\n\tonComplete,\n\tisSuccess,\n\tonCustomScanSuccess,\n\tswan,\n}: SignUpProps) {\n\tconst { gender, shopDomain, heightInCm, deviceFocalLength, userName, email, scanType } = userDetails || {};\n\tconst isCustom = [CLOTHING_CUSTOM_SCAN, CLOTHING_BANNER_SCAN, CLOTHING_CUSTOM_FIT_SCAN].includes(scanType ?? \"\");\n\tconst [showDrawer, setShowDrawer] = useState(true);\n\tconst handlePostHogEvent = () => {\n\t\tposthog.capture(shopDomain??\"\", {\n\t\t\tscanID: scanId,\n\t\t\temail: email,\n\t\t\theight: heightInCm,\n\t\t\tfocalLength: deviceFocalLength,\n\t\t\tclothesFit: \"0\",\n\t\t\tgender: gender,\n\t\t});\n\t};\n\n\tconst handleSignUp = useCallback(async () => {\n\t\ttry {\n\t\t\tif (isCustom) {\n\t\t\t\tawait swan?.auth.addUser({\n\t\t\t\t\tscanId,\n\t\t\t\t\temail,\n\t\t\t\t\tname: userName,\n\t\t\t\t\tgender,\n\t\t\t\t\theight: heightInCm,\n\t\t\t\t});\n\t\t\t\tonCustomScanSuccess?.();\n\t\t\t}\n\t\t\thandlePostHogEvent();\n\t\t} catch (error) {\n\t\t\tconsole.log(error);\n\t\t}\n\t}, [isCustom]);\n\n\tconst { translate } = useContext(LanguageContext) || {};\n\n\tuseEffect(() => {\n\t\tif (isVideoUploadedCorrect || isMeasurementAvailable) {\n\t\t\thandleSignUp();\n\t\t}\n\t}, [isVideoUploadedCorrect, isMeasurementAvailable]);\n\n\t// For custom scans the flow auto-redirects via onCustomScanSuccess once addUser\n\t// resolves, so the manual Next button must never show (otherwise a stray\n\t// \"Continue\" appears during the addUser network window). The drawer's progress\n\t// video + \"measurements being taken\" header already serves as the processing\n\t// state while the redirect is in flight.\n\tconst showNextButton = (isSuccess || isVideoUploadedCorrect || isMeasurementAvailable) && !isCustom;\n\n\treturn (\n\t\t<Box className=\"flex h-full w-full flex-col common-ui-main\">\n\t\t\t<div className=\"h-full w-full flex-col items-center justify-center flex\">\n\t\t\t\t<CameraPermission loader={config?.loader} setShowDrawer={setShowDrawer} />\n\t\t\t\t<Drawer\n\t\t\t\t\topen={showDrawer}\n\t\t\t\t\tonClose={(_, reason) => {\n\t\t\t\t\t\tif (reason === \"backdropClick\") {\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\t\t\t\t\t}}\n\t\t\t\t\tclassName=\"camera-drawer\"\n\t\t\t\t\tanchor=\"bottom\"\n\t\t\t\t>\n\t\t\t\t\t<div\n\t\t\t\t\t\tclassName=\"max-w-[28rem] mx-auto w-full h-full flex text-center flex-col justify-between items-center bg-primary rounded-t-[30px] p-[1rem]\"\n\t\t\t\t\t\tstyle={{ background: config?.style?.base?.backgroundColor }}\n\t\t\t\t\t>\n\t\t\t\t\t\t<div className=\"w-full h-full flex flex-col\">\n\t\t\t\t\t\t\t<Header title={translate?.(LanguageKeys.measurementsBeingTaken)} />\n\t\t\t\t\t\t\t<div className=\"flex items-center justify-center flex-1\">\n\t\t\t\t\t\t\t\t<video preload=\"auto\" className=\"max-h-[calc(100vh-450px)] mx-auto w-full object-contain border-none\" muted loop autoPlay playsInline>\n\t\t\t\t\t\t\t\t\t<source src={gender === GenderType.Male ? maleMeasurementProgress : measurementProgress} type=\"video/mp4\" />\n\t\t\t\t\t\t\t\t</video>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t{showNextButton && <SpecificButton className=\"!w-[180px] mx-auto\" buttonText={translate?.(LanguageKeys.next)} buttonFunc={()=>{onComplete?.()\n\t\t\t\t\t\t\t}} />}\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</div>\n\t\t\t\t</Drawer>\n\t\t\t</div>\n\t\t</Box>\n\t);\n}\nexport default SignUp;\n","\"use client\";\nimport { useContext } from \"react\";\nimport AngleDetector from \"./AngleDetector\";\nimport CameraPermission from \"./CameraPermission\";\nimport Modal from \"../Modal\";\nimport { Drawer } from \"@mui/material\";\nimport ScanErrorMessage from \"./ScanErrorMessage\";\nimport LoadingScreen from \"../LoadingScreen\";\nimport SignUp from \"../Signup\";\nimport { useConfig } from \"../../utils/context/configContext\";\nimport ParamsContext from \"../../utils/context/paramsContext\";\n\nexport const BodyScanSteps = () => {\n\tconst {\n\t\tuserDetails,\n\t\tonRetry,\n\t\tisError,\n\t\tisSuccess,\n\t\tgender,\n\t\tscanUniqueKey,\n\t\tscanFailsError,\n\t\tsetScanUniqueKey,\n\t\tsetIsVideoUploaded,\n\t\tisMeasurementAvailable,\n\t\tisVideoUploadedCorrect,\n\t\tloading,\n\t\tshowDeniedModal,\n\t\tuploadLoading,\n\t\tsetScanFailsError,\n\t\tsetScanStartTime,\n\t\tresetScan,\n\t\tonCustomScanSuccess,\n\t\tswan,\n\t\tonComplete,\n\t} = useContext(ParamsContext);\n\tconst resolvedConfig = useConfig();\n\n\tif (isError) {\n\t\treturn (\n\t\t\t<div data-scan-state=\"error\">\n\t\t\t\t<CameraPermission />\n\t\t\t\t<Drawer\n\t\t\t\t\tanchor=\"bottom\"\n\t\t\t\t\topen={true}\n\t\t\t\t\tclassName=\"camera-drawer\"\n\t\t\t\t\tonClose={(event, reason) => {\n\t\t\t\t\t\tif (reason === \"backdropClick\") {\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\t\t\t\t\t}}\n\t\t\t\t>\n\t\t\t\t\t<ScanErrorMessage scanFailsError onNext={onRetry} gender={gender} />\n\t\t\t\t</Drawer>\n\t\t\t</div>\n\t\t);\n\t}\n\n\tif (isSuccess) {\n\t\treturn <div data-scan-state=\"success\"><SignUp isSuccess onComplete={onComplete} /></div>;\n\t}\n\n\tif (loading) {\n\t\treturn (\n\t\t\t<div data-scan-state=\"loading\" className=\"flex top-0 !mt-0 left-0 z-[999] absolute justify-center items-center w-full h-full\" style={{ background: resolvedConfig?.style?.base?.backgroundColor }}>\n\t\t\t\t<LoadingScreen url={resolvedConfig?.loader} loaderType=\"black\" />\n\t\t\t</div>\n\t\t);\n\t}\n\tif (showDeniedModal.disabled) {\n\t\treturn <div data-scan-state=\"camera-denied\"><Modal /></div>;\n\t}\n\n\tif (!uploadLoading && !scanFailsError && !isMeasurementAvailable && !isVideoUploadedCorrect) {\n\t\treturn (\n\t\t\t<div data-scan-state=\"scanning\">\n\t\t\t<AngleDetector\n\t\t\t\tscanID={scanUniqueKey}\n\t\t\t\tuserDetails={userDetails}\n\t\t\t\tsetIsVideoUploaded={setIsVideoUploaded}\n\t\t\t\tsetScanFailsError={setScanFailsError}\n\t\t\t\tsetScanStartTime={setScanStartTime}\n\t\t\t\tsetScanUniqueKey={setScanUniqueKey}\n\t\t\t/>\n\t\t\t</div>\n\t\t);\n\t}\n\tif ((uploadLoading || isMeasurementAvailable || isVideoUploadedCorrect) && !scanFailsError) {\n\t\treturn (\n\t\t\t<div data-scan-state=\"processing\">\n\t\t\t<SignUp\n\t\t\t\tscanId={scanUniqueKey}\n\t\t\t\tisMeasurementAvailable={isMeasurementAvailable}\n\t\t\t\tuserDetails={userDetails}\n\t\t\t\tisVideoUploadedCorrect={isVideoUploadedCorrect}\n\t\t\t\tonCustomScanSuccess={onCustomScanSuccess}\n\t\t\t\tswan={swan}\n\t\t\t\tonComplete={onComplete}\n\t\t\t\tconfig={resolvedConfig}\n\t\t\t/>\n\t\t\t</div>\n\t\t);\n\t}\n\treturn (\n\t\t<div data-scan-state=\"error-retry\">\n\t\t\t<CameraPermission />\n\t\t\t<Drawer\n\t\t\t\tanchor=\"bottom\"\n\t\t\t\topen\n\t\t\t\tclassName=\"camera-drawer\"\n\t\t\t\tonClose={(event, reason) => {\n\t\t\t\t\tif (reason === \"backdropClick\") {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t}}\n\t\t\t>\n\t\t\t\t<ScanErrorMessage\n\t\t\t\t\tscanFailsError={scanFailsError}\n\t\t\t\t\tonNext={() => {\n\t\t\t\t\t\tonRetry?.();\n\t\t\t\t\t\tresetScan();\n\t\t\t\t\t}}\n\t\t\t\t\tsetScanUniqueKey={setScanUniqueKey}\n\t\t\t\t\tgender={gender}\n\t\t\t\t\tsetIsVideoUploaded={setIsVideoUploaded}\n\t\t\t\t/>\n\t\t\t</Drawer>\n\t\t</div>\n\t);\n};\n","\"use client\";\nimport { useCallback, useEffect, useMemo, useState } from \"react\";\nimport useGyroSensor from \"../../customHooks/useGyroSensor\";\nimport usePosthogPageview from \"../../customHooks/usePosthogPageview\";\nimport {\n\tcheckCameraPermission,\n\tcreateObjectMetadataArray,\n\tgenerateUuid,\n\tgetCurrentTimeInSeconds,\n\tgetVideoFPS,\n\thandleErrorMessage,\n\thandleScanTimeCapture,\n\thandleWebSocketCapture,\n} from \"../../utils/utils\";\nimport LanguageContextProvider from \"../../utils/context/languageContext\";\nimport { ConfigProvider } from \"../../utils/context/configContext\";\nimport { getSwanService } from \"../../utils/service/swanService\";\nimport ParamsContext from \"../../utils/context/paramsContext\";\nimport MediaContextProvider from \"../../utils/context/mediaContext\";\nimport { BodyScanProps, UserDetails } from \"../../types/interfaces\";\nimport { BodyScanSteps } from \"./BodyScanSteps\";\n\nconst clothesFit = \"0\";\n\nconst BodyScan: React.FC<BodyScanProps> = (props) => {\n\tconst {\n\t\tconfig,\n\t\tonRetry,\n\t\tonScanStart,\n\t\tonCaptureComplete,\n\t\tonUploadStart,\n\t\tonUploadEnd,\n\t\tonMeasurementSocketStart,\n\t\tonMeasurementSocketClose,\n\t\tonIntermediateScanSuccess,\n\t\tonScanError,\n\t\tonScanSuccess,\n\t\tonCustomScanSuccess,\n\t\tonComplete,\n\t\tisError,\n\t\tisSuccess,\n\t} = props;\n\tconst userDetails: UserDetails = {\n\t\temail: \"\",\n\t\tshopDomain: \"\",\n\t\tgender: \"male\",\n\t\theightInCm: 0,\n\t\tscanType: \"\",\n\t\tdeviceFocalLength: 0,\n\t\tdeviceModelName: \"\",\n\t\tsourceTag: \"\",\n\t\tcallbackUrl: null,\n\t\t...(props.userDetails ?? {}),\n\t};\n\tconst token = props.token ?? \"\";\n\tconst { gender, scanType, shopDomain, heightInCm, email, deviceFocalLength, deviceModelName, callbackUrl, sourceTag } = userDetails;\n\tconst swan = useMemo(() => getSwanService(token), [token]);\n\tconst [uploadLoading, setUploadLoading] = useState(false);\n\tconst [isVideoUploadedCorrect, setIsVideoUploadedCorrect] = useState(false);\n\tconst [isMeasurementAvailable, setIsMeasurementAvailable] = useState(false);\n\tconst [showDeniedModal, setShowDeniedModal] = useState({\n\t\tdisabled: false,\n\t\tmessage: \"\",\n\t});\n\tconst [scanFailsError, setScanFailsError] = useState(\"\");\n\tconst [isVideoUploaded, setIsVideoUploaded] = useState(false);\n\tconst [loading, setLoading] = useState(true);\n\tconst [startGyro, setStartGyro] = useState(false);\n\tconst [scanUniqueKey, setScanUniqueKey] = useState(\"\");\n\tconst [scanStartTime, setScanStartTime] = useState<number | null>(getCurrentTimeInSeconds());\n\tconst { gyroData } = useGyroSensor(startGyro);\n\tusePosthogPageview();\n\n\tconst resetScan = useCallback(() => {\n\t\tsetScanUniqueKey(generateUuid());\n\t\tsetScanFailsError(\"\");\n\t\tsetUploadLoading(false);\n\t\tsetIsVideoUploaded(false);\n\t}, []);\n\n\tconst onError = (data: any) => {\n\t\tonScanError?.({ ...data, message: handleErrorMessage(data) });\n\t\tclearScanStartTimeAndScanId();\n\t\tsetIsMeasurementAvailable(false);\n\t\tsetScanFailsError(data);\n\t\tsetIsVideoUploadedCorrect(false);\n\t\thandleScanTimeCapture({\n\t\t\teventName: `${shopDomain}/measurement_failed/fit-view`,\n\t\t\tscanID: scanUniqueKey,\n\t\t\tstatus: \"failed\",\n\t\t\temail,\n\t\t\tmessage: handleErrorMessage(data),\n\t\t});\n\t\tif (scanStartTime)\n\t\t\thandleScanTimeCapture({\n\t\t\t\teventName: `${shopDomain}/scan_completion_time`,\n\t\t\t\tscanID: scanUniqueKey,\n\t\t\t\tstatus: \"failed\",\n\t\t\t\tcompletionTime: getCurrentTimeInSeconds() - scanStartTime,\n\t\t\t\temail,\n\t\t\t});\n\t};\n\n\tconst clearScanStartTimeAndScanId = () => {\n\t\tsetScanStartTime(null);\n\t\tsetScanUniqueKey(\"\");\n\t};\n\n\tconst onSuccess = useCallback(\n\t\tasync (data: any) => {\n\t\t\tif (data && data?.scanStatus === \"success\" && data?.resultType === \"intermediate\" && data?.code === 200) {\n\t\t\t\thandleScanTimeCapture({\n\t\t\t\t\teventName: `${shopDomain}/measurement_success/intermediate`,\n\t\t\t\t\tscanID: scanUniqueKey,\n\t\t\t\t\tstatus: \"success\",\n\t\t\t\t\temail,\n\t\t\t\t});\n\t\t\t\tsetIsVideoUploadedCorrect(true);\n\t\t\t\tonIntermediateScanSuccess?.(data);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tonScanSuccess?.(data);\n\t\t\tsetIsVideoUploadedCorrect(true);\n\t\t\tclearScanStartTimeAndScanId();\n\t\t\tconst scanIdToSet = scanUniqueKey;\n\t\t\tsetIsMeasurementAvailable(true);\n\t\t\thandleScanTimeCapture({\n\t\t\t\teventName: `${shopDomain}/measurement_success/fit-view`,\n\t\t\t\tscanID: scanIdToSet,\n\t\t\t\tstatus: \"success\",\n\t\t\t\temail,\n\t\t\t});\n\t\t\tif (scanStartTime)\n\t\t\t\thandleScanTimeCapture({\n\t\t\t\t\teventName: `${shopDomain}/scan_completion_time`,\n\t\t\t\t\tscanID: scanIdToSet,\n\t\t\t\t\tstatus: \"success\",\n\t\t\t\t\tcompletionTime: getCurrentTimeInSeconds() - scanStartTime,\n\t\t\t\t\temail,\n\t\t\t\t});\n\t\t},\n\t\t[scanType, shopDomain, scanUniqueKey],\n\t);\n\n\tconst handleMeasurementRecommendation = (scanId?: string) => {\n\t\tsetIsMeasurementAvailable(false);\n\t\tsetScanFailsError(\"\");\n\t\tsetIsVideoUploadedCorrect(false);\n\t\tswan.measurement.handleMeasurementSocket({\n\t\t\tscanId: scanId || scanUniqueKey,\n\t\t\tonPreopen: () => {\n\t\t\t\thandleWebSocketCapture({\n\t\t\t\t\teventName: `${shopDomain}/webSocket`,\n\t\t\t\t\tscanID: scanUniqueKey,\n\t\t\t\t\tconnection: \"pre_open\",\n\t\t\t\t\ttype: \"measurement_recommendation\",\n\t\t\t\t\temail,\n\t\t\t\t});\n\t\t\t},\n\t\t\tonOpen: () => {\n\t\t\t\tonMeasurementSocketStart?.();\n\t\t\t\thandleWebSocketCapture({\n\t\t\t\t\teventName: `${shopDomain}/webSocket`,\n\t\t\t\t\tscanID: scanUniqueKey,\n\t\t\t\t\tconnection: \"open\",\n\t\t\t\t\ttype: \"measurement_recommendation\",\n\t\t\t\t\temail,\n\t\t\t\t});\n\t\t\t},\n\t\t\tonClose: () => {\n\t\t\t\tonMeasurementSocketClose?.();\n\t\t\t\thandleWebSocketCapture({\n\t\t\t\t\teventName: `${shopDomain}/webSocket`,\n\t\t\t\t\tscanID: scanUniqueKey,\n\t\t\t\t\tconnection: \"close\",\n\t\t\t\t\ttype: \"measurement_recommendation\",\n\t\t\t\t\temail,\n\t\t\t\t});\n\t\t\t},\n\t\t\tonError: (err) => {\n\t\t\t\tonError(err);\n\t\t\t\thandleWebSocketCapture({\n\t\t\t\t\teventName: `${shopDomain}/webSocket`,\n\t\t\t\t\tscanID: scanUniqueKey,\n\t\t\t\t\tconnection: \"error\",\n\t\t\t\t\ttype: \"measurement_recommendation\",\n\t\t\t\t\temail,\n\t\t\t\t});\n\t\t\t},\n\t\t\tonSuccess: (data) => {\n\t\t\t\thandleWebSocketCapture({\n\t\t\t\t\teventName: `${shopDomain}/webSocket`,\n\t\t\t\t\tscanID: scanUniqueKey,\n\t\t\t\t\tconnection: \"success\",\n\t\t\t\t\ttype: \"measurement_recommendation\",\n\t\t\t\t\temail,\n\t\t\t\t});\n\t\t\t\tonSuccess(data);\n\t\t\t},\n\t\t});\n\t};\n\n\tconst uploadScanFile = useCallback(\n\t\tasync (file: File, recordedFps?: number | null) => {\n\t\t\tconst fileSizeInMB = Number((file.size / (1024 * 1024)).toFixed(2));\n\t\t\t// Use FPS captured at recording time, fallback to calculation if not available\n\t\t\tconst videoFps = recordedFps !== undefined && recordedFps !== null ? recordedFps : await getVideoFPS(file);\n\t\t\tconst arrayMetaData = createObjectMetadataArray({\n\t\t\t\tgender,\n\t\t\t\tfocal_length: `${deviceFocalLength}`,\n\t\t\t\theight: `${heightInCm}`,\n\t\t\t\tcustomer_store_url: shopDomain,\n\t\t\t\tclothes_fit: clothesFit,\n\t\t\t\tscan_type: scanType,\n\t\t\t\tcallback_url: callbackUrl,\n\t\t\t\tsource_tag: sourceTag,\n\t\t\t});\n\t\t\thandleScanTimeCapture({\n\t\t\t\teventName: `${shopDomain}/body_scan_meta_data`,\n\t\t\t\tscanID: scanUniqueKey,\n\t\t\t\temail,\n\t\t\t\tdata: JSON.stringify([...arrayMetaData, { fileSizeInMB, video_fps: videoFps || 0 }]),\n\t\t\t});\n\t\t\tonUploadStart?.();\n\t\t\ttry {\n\t\t\t\tawait swan.fileUpload.uploadFileFrontend({\n\t\t\t\t\tfile,\n\t\t\t\t\tarrayMetaData,\n\t\t\t\t\tscanId: scanUniqueKey,\n\t\t\t\t\temail,\n\t\t\t\t});\n\t\t\t\tawait swan.fileUpload.setDeviceInfo({\n\t\t\t\t\tmodel: deviceModelName,\n\t\t\t\t\tdetection: \"manual\",\n\t\t\t\t\tgyro: gyroData,\n\t\t\t\t\tscanId: scanUniqueKey,\n\t\t\t\t});\n\t\t\t\tconsole.log(\"video successfully uploaded\");\n\t\t\t\tsetIsVideoUploaded(false);\n\t\t\t\thandleScanTimeCapture({\n\t\t\t\t\teventName: `${shopDomain}/scan_success`,\n\t\t\t\t\tscanID: scanUniqueKey,\n\t\t\t\t\tstatus: \"success\",\n\t\t\t\t\temail,\n\t\t\t\t\tdata: JSON.stringify(arrayMetaData),\n\t\t\t\t});\n\t\t\t\thandleScanTimeCapture({\n\t\t\t\t\teventName: \"scan finished\",\n\t\t\t\t\tscanID: scanUniqueKey,\n\t\t\t\t\tstatus: \"success\",\n\t\t\t\t\temail,\n\t\t\t\t});\n\t\t\t\tsetScanStartTime(getCurrentTimeInSeconds());\n\t\t\t\tsetTimeout(() => {\n\t\t\t\t\tsetIsVideoUploaded(true);\n\t\t\t\t}, 3000);\n\t\t\t} catch (error:any) {\n\t\t\t\thandleScanTimeCapture({\n\t\t\t\t\teventName: \"scan finished\",\n\t\t\t\t\tscanID: scanUniqueKey,\n\t\t\t\t\tstatus: \"failed\",\n\t\t\t\t\temail,\n\t\t\t\t\tmessage: handleErrorMessage(error),\n\t\t\t\t});\n\t\t\t\thandleScanTimeCapture({\n\t\t\t\t\teventName: `${shopDomain}/scan_failed`,\n\t\t\t\t\tscanID: scanUniqueKey,\n\t\t\t\t\tstatus: \"failed\",\n\t\t\t\t\temail,\n\t\t\t\t\tmessage: handleErrorMessage(error),\n\t\t\t\t\tdata: JSON.stringify(arrayMetaData),\n\t\t\t\t});\n\t\t\t\tsetScanFailsError(handleErrorMessage(error));\n\t\t\t\tsetIsVideoUploaded(false);\n\t\t\t\tonScanError?.({...error, message: handleErrorMessage(error) });\n\t\t\t\tclearScanStartTimeAndScanId();\n\t\t\t} finally {\n\t\t\t\tsetStartGyro(false);\n\t\t\t\tonUploadEnd?.();\n\t\t\t}\n\t\t},\n\t\t[scanUniqueKey, gyroData, onUploadStart, onUploadEnd],\n\t);\n\t// const checkMeasurementStatus = useCallback(\n\t// \tasync (scanId: string) => {\n\t// \t\ttry {\n\t// \t\t\tconst res = await swan.measurement.getMeasurementResult(scanId);\n\t// \t\t\tconst isMeasured = res?.data?.isMeasured;\n\t// \t\t\tconst tempScanStartTime = scanStartTime || getCurrentTimeInSeconds();\n\t// \t\t\tconst currentTimeInSeconds = getCurrentTimeInSeconds();\n\t// \t\t\tconst fiveMinutesInSeconds = 5 * 60;\n\t// \t\t\tsetLoading(false);\n\t// \t\t\tif (isMeasured === false) {\n\t// \t\t\t\tclearScanStartTimeAndScanId();\n\t// \t\t\t\tsetScanUniqueKey(generateUuid());\n\t// \t\t\t\treturn;\n\t// \t\t\t}\n\t// \t\t\tsetUploadLoading(true);\n\t// \t\t\tif (isMeasured === true) {\n\t// \t\t\t\tawait onSuccess(null);\n\t// \t\t\t} else if (isMeasured === null && tempScanStartTime > currentTimeInSeconds + fiveMinutesInSeconds) {\n\t// \t\t\t\tonError(res?.data?.error);\n\t// \t\t\t} else {\n\t// \t\t\t\thandleMeasurementRecommendation(scanId);\n\t// \t\t\t}\n\t// \t\t} catch (error) {\n\t// \t\t\tconsole.log(error);\n\t// \t\t\tclearScanStartTimeAndScanId();\n\t// \t\t\tsetScanUniqueKey(generateUuid());\n\t// \t\t\tsetUploadLoading(false);\n\t// \t\t}\n\t// \t},\n\t// \t[onError, onSuccess, setScanUniqueKey],\n\t// );\n\n\tconst handleCameraPermission = useCallback(async () => {\n\t\tif (+heightInCm < 152.4 || +heightInCm > 213.36) {\n\t\t\tonScanError?.({\n\t\t\t\tmessage: \"Height must be between 152.4cm (5ft) and 213.36cm (7ft)\",\n\t\t\t});\n\t\t\treturn;\n\t\t}\n\n\t\tconst permission = await checkCameraPermission();\n\t\tif (permission.disabled) {\n\t\t\thandleScanTimeCapture({\n\t\t\t\teventName: `${shopDomain}/camera_activation`,\n\t\t\t\tscanID: scanUniqueKey,\n\t\t\t\tstatus: \"failed\",\n\t\t\t\temail,\n\t\t\t});\n\t\t\tsetLoading(false);\n\t\t} else {\n\t\t\t// const scanId = scanUniqueKey;\n\t\t\t// if (scanId) {\n\t\t\t// \tcheckMeasurementStatus(scanId);\n\t\t\t// } else {\n\t\t\t// \tsetLoading(false);\n\t\t\t// }\n\t\t\tsetLoading(false);\n\t\t\thandleScanTimeCapture({\n\t\t\t\teventName: `${shopDomain}/camera_activation`,\n\t\t\t\tscanID: scanUniqueKey,\n\t\t\t\tstatus: \"success\",\n\t\t\t\temail,\n\t\t\t});\n\t\t}\n\t\tsetShowDeniedModal(permission);\n\t\tsetScanFailsError(\"\");\n\t\tsetIsVideoUploaded(false);\n\t}, [email, scanUniqueKey, setScanUniqueKey, shopDomain]);\n\n\tuseEffect(() => {\n\t\tif (isError || isSuccess) return;\n\t\tif (shopDomain) {\n\t\t\thandleCameraPermission();\n\t\t}\n\t}, [shopDomain, heightInCm, isError, isSuccess]);\n\n\tuseEffect(() => {\n\t\tif (isError || isSuccess) return;\n\t\tif (isVideoUploaded && shopDomain && scanUniqueKey) {\n\t\t\thandleMeasurementRecommendation();\n\t\t}\n\t}, [isVideoUploaded, shopDomain, scanUniqueKey, isError, isSuccess]);\n\treturn (\n\t\t<div data-testid=\"body-scan-root\">\n\t\t<LanguageContextProvider>\n\t\t\t<ConfigProvider config={config}>\n\t\t\t\t<MediaContextProvider>\n\t\t\t\t\t<ParamsContext.Provider\n\t\t\t\t\t\tvalue={{\n\t\t\t\t\t\t\tuserDetails,\n\t\t\t\t\t\t\tonRetry,\n\t\t\t\t\t\t\tonScanError,\n\t\t\t\t\t\t\tisError,\n\t\t\t\t\t\t\tisSuccess,\n\t\t\t\t\t\t\tonScanSuccess,\n\t\t\t\t\t\t\tgender,\n\t\t\t\t\t\t\tscanUniqueKey,\n\t\t\t\t\t\t\tscanFailsError,\n\t\t\t\t\t\t\tsetScanUniqueKey,\n\t\t\t\t\t\t\tsetIsVideoUploaded,\n\t\t\t\t\t\t\tisMeasurementAvailable,\n\t\t\t\t\t\t\tisVideoUploadedCorrect,\n\t\t\t\t\t\t\tloading,\n\t\t\t\t\t\t\tshowDeniedModal,\n\t\t\t\t\t\t\tuploadLoading,\n\t\t\t\t\t\t\tsetStartGyro,\n\t\t\t\t\t\t\tuploadScanFile,\n\t\t\t\t\t\t\tsetUploadLoading,\n\t\t\t\t\t\t\tresetScan,\n\t\t\t\t\t\t\tsetScanFailsError,\n\t\t\t\t\t\t\tsetScanStartTime,\n\t\t\t\t\t\t\tonScanStart,\n\t\t\t\t\t\t\tonCaptureComplete,\n\t\t\t\t\t\t\tonCustomScanSuccess,\n\t\t\t\t\t\t\tonComplete,\n\t\t\t\t\t\t\tswan,\n\t\t\t\t\t\t}}\n\t\t\t\t\t>\n\t\t\t\t\t\t<BodyScanSteps />\n\t\t\t\t\t</ParamsContext.Provider>\n\t\t\t\t</MediaContextProvider>\n\t\t\t</ConfigProvider>\n\t\t</LanguageContextProvider>\n\t\t</div>\n\t);\n};\n\n// SSR mount-gate: the camera/scan tree is browser-only (touches window/document\n// during render and uses the webcam). This thin wrapper renders a neutral\n// placeholder on the server and the first client render, then mounts the real\n// component only after the effect fires in the browser. This lets consumers\n// import BodyScan into a server-rendered app (Next/Remix) without a crash or a\n// dynamic(ssr:false) wrapper. None of BodyScanInner's hooks run on the server.\nconst BodyScanClientGate: React.FC<BodyScanProps> = (props) => {\n\tconst [mounted, setMounted] = useState(false);\n\tuseEffect(() => {\n\t\tsetMounted(true);\n\t}, []);\n\n\tif (!mounted) {\n\t\treturn <div data-testid=\"body-scan-root\" />;\n\t}\n\n\treturn <BodyScan {...props} />;\n};\n\nexport { BodyScanClientGate as BodyScan };\n","import { useCallback, useEffect, useState } from \"react\";\n\ninterface GyroDataItem {\n alpha?: string;\n beta?: string;\n gamma?: string;\n timestamp?: string;\n}\n\nexport interface IOSDeviceOrientationEvent extends DeviceOrientationEvent {\n requestPermission?: () => Promise<PermissionState>;\n}\n\nfunction useGyroSensor(startGyro: boolean) {\n const [gyroData, setGyroData] = useState<GyroDataItem[]>([]);\n const [permissionGranted, setPermissionGranted] = useState(false);\n\n const handleOrientation = useCallback((event: DeviceOrientationEvent) => {\n try {\n const { alpha, beta, gamma } = event;\n setGyroData((prev: GyroDataItem[]) => [\n ...prev,\n {\n alpha: alpha?.toString() || undefined,\n beta: beta?.toString() || undefined,\n gamma: gamma?.toString() || undefined,\n timestamp: new Date().toISOString(),\n },\n ]);\n } catch (error) {\n console.log(error);\n }\n }, []);\n\n const requestPermission = useCallback(async () => {\n const DeviceOrientation =\n DeviceOrientationEvent as unknown as IOSDeviceOrientationEvent;\n\n if (\n typeof DeviceOrientation !== \"undefined\" &&\n typeof DeviceOrientation.requestPermission === \"function\"\n ) {\n try {\n const response = await DeviceOrientation.requestPermission();\n if (response === \"granted\") {\n setPermissionGranted(true);\n } else {\n console.warn(\"Device orientation permission denied.\");\n }\n } catch (error) {\n console.error(\"Error requesting device orientation permission:\", error);\n }\n } else {\n // Permission not required on non-iOS devices\n setPermissionGranted(true);\n }\n }, []);\n\n useEffect(() => {\n if (startGyro && permissionGranted) {\n window.addEventListener(\"deviceorientation\", handleOrientation);\n } else {\n setGyroData([]);\n }\n return () => {\n window.removeEventListener(\"deviceorientation\", handleOrientation);\n };\n }, [startGyro, permissionGranted, handleOrientation]);\n\n useEffect(() => {\n if (startGyro) {\n requestPermission();\n }\n }, [startGyro, requestPermission]);\n\n return { gyroData };\n}\n\nexport default useGyroSensor;\n"],"names":["MEDIA_TYPES","MediaContext","createContext","undefined","MediaContextProvider","children","size","setSize","useState","window","innerWidth","innerHeight","clearInputs","setClearInputs","updateSize","useEffect","useLayoutEffect","addEventListener","removeEventListener","media","mediaDetails","useMemo","_jsx","Provider","value","SwitchIcon","React","memo","_jsxs","width","height","viewBox","fill","xmlns","d","stroke","strokeWidth","strokeLinecap","strokeLinejoin","LevelScreen","angle","countdown","isScanning","isInTargetRange","stabilityScore","translate","useContext","LanguageContext","config","useConfig","getProximityToTarget","useCallback","Math","max","min","backgroundColor","style","angleDetector","successAngleBackground","proximity","successAngleLowBackground","round","handelTextColour","isLight","successAngleTextLightColor","successAngleTextDarkColor","getTextColor","handelColourCode","getColorCode","cd","fixVh","document","documentElement","setProperty","className","Header","noTitle","border","fontFamily","base","baseFontFamily","color","cn","transform","transition","LanguageKeys","startLevelCheck","leavePhone","placePhoneUpright","CameraScanChild","resetScan","loadingCam","onUserMedia","onPause","onReScan","pause","recordingStarted","startSendingVideoFrames","showPause","webcamRef","onUserMediaError","resetDetector","videoConstraints","webcamKey","faceDone","onClick","X","Webcam","audio","ref","screenshotQuality","mirrored","screenshotFormat","position","top","bottom","zIndex","objectFit","SpecificButton","prefix","pauseIcon","buttonText","buttonFunc","btnSecondary","restart","startScan","disabled","id","crossOrigin","preload","src","voiceOverAssetsPath","audioTimeoutId","globalLoadingPromise","globalDetector","globalPoseLib","lastVideoPlayed","ScanningComponent","setIsScanLocked","scanID","setIsVideoUploaded","setScanFailsError","setScanStartTime","setScanUniqueKey","userDetails","email","shopDomain","gender","heightInCm","useRef","mediaRecorderRef","recordedFpsRef","recordedChunks","setRecordedChunks","setLoadingCam","setRecordingStarted","setFaceDone","mediaRecorderStopped","setMediaRecorderStopped","setIsScanning","captureVideoTimeOutHandle","audioSource","setAudioSource","audioSourceList","setAudioSourceList","emptyAudioSource","setEmptyAudioSource","startAgain","setStartAgain","showRestart","setRestart","setPause","events","setEvents","setShowPause","allowAudioToPlay","poseDetector","consecutiveFronts","setConsecutiveFronts","spinPhase","setSpinPhase","isLoaded","setIsLoaded","spinPhaseRef","consecutiveFrontsRef","mounted","async","loadDependenciesGlobal","navigator","console","log","poseLib","tfjsCore","tfjsBackend","Promise","all","import","setBackend","ready","modelConfig","runtime","modelType","solutionPath","createDetector","SupportedModels","BlazePose","mediapipeError","warn","error","isFrontFrame","body","length","filter","p","current","then","success","s","callback","video","readyState","poses","estimatePoses","flipHorizontal","keypoints","slice","map","kp","x","y","score","prev","err","retryLoading","useTensorFlow","firstScan","poseStoppedRef","counterRef","consecutiveFalseRef","poseListenerRegistered","isConnectingRef","brilliantPlayedRef","postPoseProcessRef","startSendingVideoFramesRef","idRef","supportedTypes","setSupportedTypes","setWebcamKey","currentVideoConstraints","setCurrentVideoConstraints","videoConstraintsExact","setStartGyro","uploadScanFile","setUploadLoading","swan","onScanStart","onCaptureComplete","ParamsContext","scanIDRef","eventsRef","clearTimeout","generateUuid","speechService","stopAudio","stop","forEach","el","stream","handleUserMedia","setTimeout","handleUserMediaError","videoConstraintsFallback","handlePause","poseDetection","disconnect","posthog","capture","reason","preferredVideoTypes","getPreferredMediaRecorderTypes","recordingMimeType","getRecordingMimeType","recordingExtension","getRecordingExtension","stopRecording","playAudio","handleSocket","connect","String","handleSpinDataAvailable","data","concat","handleScanTimeCapture","eventName","message","lastAudio","handleStartCaptureClick","videoTrack","getVideoTracks","settings","getSettings","frameRate","mediaRecorderOptions","videoBitsPerSecond","mimeType","MediaRecorder","start","e","postPoseProcess","handleDataAvailable","connected","poseStatus","querySelector","status","sid","counter","consecutiveFalse","type","paused","audioName","no_of_times_skipped","skipCount","getScreenshot","videoEmit","image","scanId","getCurrentTimeInSeconds","prevId","push","bypassChecksToBackup","videoFile","File","supported","getSupportedMediaRecorderTypes","videoTypes","rescanSupportCaptureEvent","AngleDetector","setAngle","calibrationOffset","setCalibrationOffset","setCountdown","setStabilityScore","lastAnglesRef","isScanLocked","calibratedAngle","DeviceOrientationEvent","handleOrientation","event","beta","newAngle","abs","gamma","cos","PI","requestPermission","DeviceOrientation","once","variation","resetCountdown","startCountdown","timer","setInterval","clearInterval","CameraPermission","setShowDrawer","loader","showDeniedModal","setShowDeniedModal","loading","setLoading","handleCameraPermission","permission","checkCameraPermission","LoadingScreen","url","loaderType","Modal","VideoPlayer","link","onReady","wrapperClassName","videoReference","playerReference","videoJsOptions","autoplay","controls","responsive","fluid","muted","navigationUI","poster","videoPoster","player","videojs","updatedOptions","sources","isDisposed","dispose","playsInline","onDrag","preventDefault","ScanErrorMessage","scanFailsError","onNext","resolvedConfig","showModal","setShowModal","handleShowModal","_Fragment","background","heading","headingFontFamily","fontSize","headingFontSize","headingColor","fontWeight","headingFontWeight","issueWithScan","baseFontSize","baseTextColor","handleErrorMessage","VIDEO_POSTER_GENDER_BASED","alt","scanAgain","Dialog","onClose","open","GENDER","PRE_LINK","male","SignUp","isVideoUploadedCorrect","isMeasurementAvailable","onComplete","isSuccess","onCustomScanSuccess","deviceFocalLength","userName","scanType","isCustom","CLOTHING_CUSTOM_SCAN","CLOTHING_BANNER_SCAN","CLOTHING_CUSTOM_FIT_SCAN","includes","showDrawer","handleSignUp","auth","addUser","name","focalLength","clothesFit","showNextButton","Box","Drawer","_","anchor","title","measurementsBeingTaken","loop","autoPlay","GenderType","Male","maleMeasurementProgress","measurementProgress","next","BodyScanSteps","onRetry","isError","scanUniqueKey","uploadLoading","BodyScan","props","onUploadStart","onUploadEnd","onMeasurementSocketStart","onMeasurementSocketClose","onIntermediateScanSuccess","onScanError","onScanSuccess","deviceModelName","sourceTag","callbackUrl","token","getSwanService","setIsVideoUploadedCorrect","setIsMeasurementAvailable","isVideoUploaded","startGyro","scanStartTime","gyroData","setGyroData","permissionGranted","setPermissionGranted","alpha","toString","timestamp","Date","toISOString","useGyroSensor","usePosthogPageview","clearScanStartTimeAndScanId","onSuccess","scanStatus","resultType","code","scanIdToSet","completionTime","handleMeasurementRecommendation","measurement","handleMeasurementSocket","onPreopen","handleWebSocketCapture","connection","onOpen","onError","file","recordedFps","fileSizeInMB","Number","toFixed","videoFps","getVideoFPS","arrayMetaData","createObjectMetadataArray","focal_length","customer_store_url","clothes_fit","scan_type","callback_url","source_tag","JSON","stringify","video_fps","fileUpload","uploadFileFrontend","setDeviceInfo","model","detection","gyro","LanguageContextProvider","ConfigProvider","BodyScanClientGate","setMounted"],"mappings":"ysBAYO,MAAMA,GACF,UADEA,GAEN,MAFMA,GAGH,SAWGC,GAAeC,OAC1BC,GAGF,SAASC,IAAqBC,SAAEA,IAC9B,MAAOC,EAAMC,GAAWC,EAAS,CAACC,QAAQC,WAAYD,QAAQE,eACvDC,EAAaC,GAAkBL,GAAS,GAEzCM,EAAa,KACjBP,EAAQ,CAACE,QAAQC,WAAYD,QAAQE,eAEvCI,EAAU,KACRD,KACC,IACHE,EAAgB,KACdP,OAAOQ,iBAAiB,SAAUH,GAC3B,IAAML,OAAOS,oBAAoB,SAAUJ,IACjD,CAACA,IACJ,IAAIK,EAAQnB,GACRM,EAAK,GAAK,KAAOA,EAAK,GAAK,OAC7Ba,EAAQnB,IAENM,EAAK,GAAK,MACZa,EAAQnB,IAGV,MAAMoB,EAAeC,EACnB,KAAA,CACEf,OACAC,UACAK,cACAC,iBACAM,UAEF,CAACb,EAAMM,EAAaO,IAGtB,OACEG,EAACrB,GAAasB,SAAQ,CAACC,MAAOJ,EAAYf,SACvCA,GAGP,CClBA,IAAAoB,GAAeC,EAAMC,KAhDrB,UAAoBrB,KAAEA,EAAO,KAC3B,OACEsB,EAAA,MAAA,CACEC,MAAOvB,EACPwB,OAAQxB,EACRyB,QAAQ,YACRC,KAAK,OACLC,MAAM,6BAA4B5B,SAAA,CAElCiB,EAAA,OAAA,CACEY,EAAE,mHACFC,OAAO,QACPC,YAAY,IACZC,cAAc,QACdC,eAAe,UAEjBhB,EAAA,OAAA,CACEY,EAAE,0NACFC,OAAO,eACPC,YAAY,IACZC,cAAc,QACdC,eAAe,UAEjBhB,EAAA,OAAA,CACEY,EAAE,kOACFC,OAAO,eACPC,YAAY,IACZC,cAAc,QACdC,eAAe,UAEjBhB,EAAA,OAAA,CACEY,EAAE,kOACFC,OAAO,eACPC,YAAY,IACZC,cAAc,QACdC,eAAe,UAEjBhB,EAAA,OAAA,CACEY,EAAE,6kBACFC,OAAO,eACPC,YAAY,IACZC,cAAc,QACdC,eAAe,YAIvB,GCyJA,IAAAC,GAAeb,EAAMC,KA9LrB,UAAqBa,MAAEA,EAAKC,UAAEA,EAASC,WAAEA,EAAUC,gBAAEA,EAAeC,eAAEA,EAAcvC,SAAEA,IACrF,MAAMwC,UAAEA,GAAcC,EAAWC,IAAoB,CAAA,EAC/CC,EAASC,IAETC,EAAuBC,EAAY,IACpCX,EAAQ,GAAWY,KAAKC,IAAI,EAAGD,KAAKE,IAAI,IAAoB,IAAdd,EAAQ,MACtDA,EAAQ,GAAWY,KAAKC,IAAI,EAAGD,KAAKE,IAAI,IAAqB,IAAf,IAAMd,KACjD,IACL,CAACA,IAEEe,EAAkBlC,EAAQ,KAC/B,GAAIqB,EAAY,OAAOM,GAAQQ,OAAOC,eAAeC,wBAA0B,UAE/E,MAAMC,EAAYT,IAClB,GAAkB,IAAdS,EAAiB,OAAOX,GAAQQ,OAAOC,eAAeG,2BAA6B,UACvF,GAAkB,MAAdD,EAAmB,OAAOX,GAAQQ,OAAOC,eAAeC,wBAA0B,UAKpF,MAAO,OAHGN,KAAKS,MAAM,IAAqBF,EAAY,IAA3B,SACjBP,KAAKS,MAAM,IAAoBF,EAAY,IAA1B,SACjBP,KAAKS,MAAM,IAAqBF,EAAY,IAA3B,OAE1B,CAACjB,EAAYQ,IAEXY,EAAmBX,EAAY,CAACY,EAAkBJ,IACnDA,EAAY,GACRI,EAAU,SAASf,GAAQQ,OAAOC,eAAeO,iCAAmC,SAAShB,GAAQQ,OAAOC,eAAeO,8BAE5HD,EAAU,SAASf,GAAQQ,OAAOC,eAAeO,iCAAmC,SAAShB,GAAQQ,OAAOC,eAAeQ,gCAChI,IAEGC,EAAef,EACpB,CAACY,GAAU,KACV,MAAMJ,EAAYT,IAClB,OAAIR,EAAmB,SAASM,GAAQQ,OAAOC,eAAeO,8BACvDF,EAAiBC,EAASJ,IAElC,CAACjB,EAAYQ,IAGRiB,EAAmBhB,EAAY,CAACY,EAAkBJ,IACnDA,EAAY,IAGTI,EAFWf,GAAQQ,OAAOC,eAAeO,2BAE4BhB,GAAQQ,OAAOC,eAAeQ,0BACxG,IACGG,EAAejB,EACpB,CAACY,GAAU,KACV,MAAMJ,EAAYT,IAClB,OAAIR,EAAmBM,GAAQQ,OAAOC,eAAeO,2BAC9CG,EAAiBJ,EAASJ,IAElC,CAACjB,EAAYQ,IAERmB,EAAK5B,EACX,SAAS6B,IACRC,SAASC,gBAAgBhB,MAAMiB,YAAY,YAAahE,OAAOE,YAAc,KAC9E,CAGA,OAFA2D,IACA7D,OAAOQ,iBAAiB,SAAUqD,GAEjC1C,EAAA,MAAA,CACC8C,UAAU,qKACVlB,MAAO,CAAED,mBAAiB,cACd,eAAc,mBACRb,EAAa,SAAWC,EAAkB,SAAW,YAAWtC,SAAA,CAElFiB,EAAA,MAAA,CAAKoD,UAAU,8EAA6ErE,SAC3FiB,EAAA,MAAA,CAAKoD,UAAU,wBAAuBrE,SACrCiB,EAACqD,EAAM,CAACC,SAAO,QAGT,OAAPP,EACA/C,EAAA,MAAA,CACCoD,UAAU,yHACVlB,MAAO,CACNqB,OAAQ,aAAaT,OACrB/D,SAEDiB,EAAA,MAAA,CACCoD,UAAW,+BAA+BN,OAC1CZ,MAAO,CACNsB,WAAY9B,GAAQQ,OAAOuB,MAAMC,gBAAkB,oBAC9BC,MAAOb,KAC5B/D,SAEAgE,MAIHzC,QADGc,GACEgC,UAAU,qDAAoDrE,SAAA,CAClEiB,EAAA,MAAA,CAAKoD,UAAU,2GAA0GrE,SACxHiB,EAAA,MAAA,CAAKoD,UAAU,2DAEfrE,IAGF,CACCqE,UAAWQ,GAAG,iFAAkFvC,EAAkB,6BAA+B,8BACjJa,MAAO,CACN2B,UAAW,cAA6B,GAAd,GAAK3C,QAC/B4C,WAAY,0BACZP,OAAQ,aAAaT,OACrB/D,SAAA,CAEDiB,EAAA,MAAA,CAAKoD,UAAW,0CAA0CN,UAC3CZ,MAAO,CACrBD,gBAAiB,GAAGa,WAGrBxC,EAAA,MAAA,CAEC8C,UAAWQ,GAAG,mFAAoFhB,KAC/EV,MAAO,CAC1ByB,MAAOb,KACP/D,SAAA,CAEAiB,EAACG,GAAU,CAACnB,KAAM,KAClBsB,EAAA,IAAA,CACC4B,MAAO,CACNsB,WAAY9B,GAAQQ,OAAOuB,MAAMC,gBAAkB,qBACnD3E,SAAA,CAEA,IACAwC,IAAYwC,EAAaC,iBAC1BhE,oBAMI,OAAP+C,GACA/C,SAAKoD,UAAU,qCAAoCrE,SAClDiB,SACCoD,UAAWQ,GAAG,oEAAqEhB,KACnFV,MAAO,CACNsB,WAAY9B,GAAQQ,OAAOuB,MAAMC,gBAAkB,oBAC9BC,MAAOb,KAC5B/D,SAEAwC,IAAYwC,EAAaE,gBAI5B5C,GAA0B,OAAP0B,IAAgB3B,GACnCpB,EAAA,MAAA,CAAKoD,UAAU,mCAAkCrE,SAChDiB,EAAA,MAAA,CACCoD,UAAW,0BAA0BN,2CACrCZ,MAAO,CACND,gBAAiB,GAAGa,SACpB/D,SAEDiB,EAAA,MAAA,CACCoD,UAAW,cAAcN,uDACzBZ,MAAO,CACN3B,MAAO,GAAGW,KACVe,gBAAiB,GAAGa,eAOd,OAAPC,IAAgB3B,GACfpB,EAAA,MAAA,CAAKoD,UAAU,qCAAoCrE,SACjDuB,EAAA,MAAA,CAAK8C,UAAWQ,GAAG,2BAA4BhB,KAC9CV,MAAO,CACZyB,MAAOb,KACP/D,SAAA,CAEO+C,KAAKS,MAAMrB,GAAM,SAKnB,OAAP6B,IAAgB3B,GAChBpB,EAAA,MAAA,CAAKoD,UAAU,2DAA0DrE,SACxEiB,EAAA,MAAA,CACCoD,UAAWQ,GAAG,2BAA4BhB,KAC1CV,MAAO,CACNsB,WAAY9B,GAAQQ,OAAOuB,MAAMC,gBAAkB,oBAC9BC,MAAOb,KAC5B/D,SAEAwC,IAAYwC,EAAaG,yBAMhC,GC5LA,SAASC,IAAgBC,UACvBA,EAASC,WACTA,EAAUC,YACVA,EAAWC,QACXA,EAAOC,SACPA,EAAQC,MACRA,EAAKC,iBACLA,EAAgBC,wBAChBA,EAAuBC,UACvBA,EAASC,UACTA,EAASC,iBACTA,EAAgBC,cAChBA,EAAaC,iBACbA,EAAgBC,UAChBA,EAASC,SACTA,EAAQ9D,WACRA,IAEA,MAAMvB,MAAEA,GAAU2B,EAAW7C,KAAiB,CAAA,GACxC4C,UAAEA,GAAcC,EAAWC,IAAoB,CAAA,EAErD,OACEnB,EAAA,MAAA,CAAK8C,UAAU,+DAA6D,cAAa,kBAAkB8B,EAAW,WAAaR,EAAmB,iBAAmBtD,EAAa,WAAa,QAAOrC,SAAA,CACxMiB,UACEmF,QAAS,KACPf,IACAW,KAEF3B,UAAU,wCAAuCrE,SAEjDiB,EAACoF,GAAC,CAAChC,UAAU,kBAGfpD,EAAA,MAAA,CAAKoD,UAAU,iCAAgCrE,SAC5Cc,IAAUnB,IACTsB,EAACqF,GAAM,CAELC,OAAO,EACPC,IAAKV,EACLW,kBAAmB,EACnBR,iBAAkBA,EAClBS,UAAQ,EACRC,iBAAiB,aACjBpB,YAAaA,EACbQ,iBAAkBA,EAClB5C,MAAO,CACLyD,SAAU,QACVC,IAAK,EACLC,OAAQ,EACRC,OAAQ,EACRvF,MAAO,OACPC,OAAQ,OACRuF,UAAW,UAhBRd,KAsBX3E,EAAA,MAAA,CAAK8C,UAAU,qFAAoFrE,SAAA,CAChG6F,GACC5E,EAACgG,EAAc,CACb5C,UAAU,2CACV6C,OAAQC,EACRC,WAAY5E,IAAYwC,EAAaU,OACrC2B,WAAY7B,EACZ8B,cAAY,IAIf5B,EACCzE,EAAA,MAAA,CAAAjB,SACEiB,EAACgG,EAAc,CACb5C,UAAU,wCACV+C,WAAY5E,IAAYwC,EAAauC,SACrCF,WAAY5B,EACZ6B,cAAY,MAGb3B,EAUD,KATF1E,EAACgG,EAAc,CAAA,cACD,iBACZ5C,UAAW,wEACTiB,EAAa,cAAgB,IAE/B8B,WAAY5E,IAAYwC,EAAawC,WACrCH,WAAYzB,EACZ6B,SAAUnC,OAKhBrE,EAAA,QAAA,CACEyG,GAAG,eACHC,YAAY,YACZC,QAAQ,OACRzE,MAAO,CACLyD,SAAU,WACVG,QAAQ,OAEVc,IAAK,GAAGC,yCAIhB,CC5GA,ICcIC,GDdAC,GAAgD,KAChDC,GAAsB,KACtBC,GAAqB,KCazB,IAAIC,GAIO,KAshBX,IAAAC,GAAe/G,EAAMC,KAphBrB,UAA2B+G,gBAAEA,EAAerC,cAAEA,EAAasC,OAAEA,EAAMC,mBAAEA,EAAkBC,kBAAEA,EAAiBC,iBAAEA,EAAgBC,iBAAEA,EAAgBC,YAAEA,IAC/I,MAAMC,MAAEA,EAAKC,WAAEA,EAAUC,OAAEA,EAAMC,WAAEA,GAAeJ,EAC5C7C,EAAYkD,EAAsB,MAClCC,EAAmBD,EAA6B,MAChDE,EAAiBF,EAAsB,OACtCG,EAAgBC,GAAqBjJ,EAAiB,KACtDmF,EAAY+D,GAAiBlJ,GAAS,IACtCwF,EAAkB2D,GAAuBnJ,GAAS,IAClDgG,EAAUoD,GAAepJ,GAAS,IAClCqJ,EAAsBC,GAA2BtJ,GAAS,IAC1DkC,EAAYqH,GAAiBvJ,GAAS,GACvCwJ,EAA4BX,EAA6C,OACxEY,EAAaC,GAAkB1J,EAAS,KACxC2J,EAAiBC,GAAsB5J,EAAmB,KAC1D6J,GAAkBC,IAAuB9J,EAAS,KAClD+J,GAAYC,IAAiBhK,GAAS,IACtCiK,GAAaC,IAAclK,GAAS,IACpCuF,GAAO4E,IAAYnK,GAAS,IAC5BoK,GAAQC,IAAarK,EAAc,KACnC0F,GAAW4E,IAAgBtK,GAAS,GACrCuK,GAAmB1B,GAAO,IAC1B2B,aAAEA,IDtCK,WACZ,MAAOC,EAAmBC,GAAwB1K,EAAS,IACpD2K,EAAWC,GAAgB5K,EAAS,IACpC6K,EAAUC,GAAe9K,GAAS,GAEnC+K,EAAelC,EAAO,GACtBmC,EAAuBnC,EAAO,GAC9BoC,EAAUpC,GAAO,GAgCvBqC,eAAeC,IAGb,GACoB,oBAAXlL,QACc,oBAAdmL,UAEP,OAAO,EAGT,IACEC,QAAQC,IAAI,kCAIZ,MAAOC,EAASC,EAAUC,SAAqBC,QAAQC,IAAI,CACzDC,OAAO,qCACPA,OAAO,yBACPA,OAAO,oCAGT7D,GAAgBwD,QAGVC,EAASK,WAAW,eACpBL,EAASM,QACfT,QAAQC,IAAI,oCAKZ,MAAMS,EAAc,CAClBC,QAAS,YACTC,UAAW,OACXC,aAAa,gDAGf,IACEpE,SAAuBC,GAAcoE,eACnCpE,GAAcqE,gBAAgBC,UAC9BN,GAEFV,QAAQC,IAAI,0CACb,CAAC,MAAOgB,GACPjB,QAAQkB,KAAK,kDAAmDD,GAGhExE,SAAuBC,GAAcoE,eACnCpE,GAAcqE,gBAAgBC,UAC9B,CACEL,QAAS,OACTC,UAAW,SAGfZ,QAAQC,IAAI,qCACb,CAED,OAAO,CACR,CAAC,MAAOkB,GAGP,OAFAnB,QAAQmB,MAAM,0CAA2CA,GACzD3E,GAAuB,MAChB,CACR,CACH,CAEA,SAAS4E,EAAaC,GAEpB,SAAKA,GAAwB,IAAhBA,EAAKC,SAC+B,KAA1CD,EAAKE,OAAQC,GAAMA,EAAE,GAAK,IAAKF,MACxC,CA2EA,OA9KApM,EAAU,KAIR,GAHA0K,EAAQ6B,SAAU,GAGdhF,GAiBJ,OAXKD,KACHA,GAAuBsD,KAIzBtD,GAAqBkF,KAAMC,IACrBA,GAAW/B,EAAQ6B,SACrBhC,GAAY,KAIT,KACLG,EAAQ6B,SAAU,GAjBlBhC,GAAY,IAmBb,IAyHHvK,EAAU,KACRyK,EAAqB8B,QAAUrC,EAC3BA,EAAoB,GAAKM,EAAa+B,QAAU,IAClDlC,EAAcqC,GAAMA,EAAI,GACxBvC,EAAqB,KAEtB,CAACD,IAEJlK,EAAU,KACRwK,EAAa+B,QAAUnC,GACtB,CAACA,IAmBG,CACLH,aA1EmBU,MAAOgC,EAAsBvH,KAGhD,IAAKmC,KAAmBmD,EAAQ6B,UAAYnH,GAAWmH,SAASK,MAC9D,OAIF,MAAMA,EAAQxH,EAAUmH,QAAQK,MAChC,KAAIA,EAAMC,WAAa,GAEvB,IACE,MAAMC,QAAcvF,GAAewF,cACjCH,EACA,CAAEI,gBAAgB,IAGpB,IAAKF,IAAUA,EAAMV,OAAQ,OAE7B,MAGMD,EAHYW,EAAM,GAAGG,UAIxBC,MAAM,IACNC,IAAKC,GAAY,CAChBA,EAAGC,EAAI,GAAKD,EAAGC,EAAI,IAAMD,EAAGC,GAAK,EACjCD,EAAGE,EAAI,GAAKF,EAAGE,EAAI,KAAOF,EAAGE,GAAK,EAClCF,EAAGG,OAAS,IAGa,IAAzB/C,EAAa+B,SAAkBL,EAAaC,IAC9ChC,EAAsBqD,GAASA,EAAO,GAGX,IAAzBhD,EAAa+B,SAAiBL,EAAaC,IAC7ChC,EAAsBqD,GAASA,EAAO,GAGX,IAAzBhD,EAAa+B,SAAeI,GACjC,CAAC,MAAOc,GACP3C,QAAQmB,MAAM,wBAAyBwB,EACxC,GAkCDnD,WACAF,YACA9E,cArBoB,KACpBkF,EAAa+B,QAAU,EACvB9B,EAAqB8B,QAAU,EAC/BpC,EAAqB,GACrBE,EAAa,IAkBbqD,aAfmB/C,UACdpD,IAAmBD,KACtBA,GAAuBsD,UACDtD,IACPoD,EAAQ6B,SACrBhC,GAAY,KAYpB,CCxJ0BoD,GACnBC,GAAYtF,GAAO,GACnBuF,GAAiBvF,GAAO,GACxBwF,GAAaxF,EAAO,GACpByF,GAAsBzF,EAAO,GAC7B0F,GAAyB1F,GAAO,GAChC2F,GAAkB3F,GAAO,GACzB4F,GAAqB5F,GAAO,GAC5B6F,GAAqB7F,EAAmB,QACxC8F,GAA6B9F,EAAmB,QAChD+F,GAAQ/F,EAAsB,OAC7BgG,GAAgBC,IAAqB9O,EAAmB,KACxD+F,GAAWgJ,IAAgB/O,EAAS,IACpCgP,GAAyBC,IAA8BjP,EAAgCkP,IACxFC,aAAEA,GAAYC,eAAEA,GAAcC,iBAAEA,GAAgBC,KAAEA,GAAIC,YAAEA,GAAWC,kBAAEA,IAAsBlN,EAAWmN,GAGtGC,GAAY7G,EAAOV,GACzB5H,EAAU,KACTmP,GAAU5C,QAAU3E,GAClB,CAACA,IAEJ,MAAMwH,GAAY9G,EAAOuB,IACzB7J,EAAU,KACToP,GAAU7C,QAAU1C,IAClB,CAACA,KAEJ,MAAMlF,GAAY,KACjBkJ,GAAetB,SAAU,EACzB8C,aAAahI,IACT4B,EAA0BsD,SAAS8C,aAAapG,EAA0BsD,SAC9EvE,EAAiBsH,KACjBxH,EAAkB,IAClBgH,MAAmB,GACnBpG,EAAkB,IAClBF,EAAe+D,QAAU,KACzB5D,GAAc,GACdC,GAAoB,GACpBC,GAAY,GACZE,GAAwB,GACxBC,GAAc,GACdC,EAA0BsD,QAAU,KACpCpD,EAAe,IACfE,EAAmB,IACnBE,GAAoB,IACpBE,IAAeD,IACfoF,IAAa,GACbW,EAAcC,YACd7F,IAAW,GACXC,IAAS,GACTkE,GAAWvB,QAAU,EACrBwB,GAAoBxB,QAAU,EAC9ByB,GAAuBzB,SAAU,EACjC2B,GAAmB3B,SAAU,EACI,OAA7BhE,EAAiBgE,SACpBhE,EAAiBgE,QAAQkD,OAG1B5F,GAAO6F,QAASC,IACXpH,EAAiBgE,SAAShE,EAAiBgE,QAAQpM,oBAAoB,gBAAiBwP,KAG7F7F,GAAU,IACVE,GAAiBuC,SAAU,EAC3BxC,IAAa,GACblC,GAAmB,GACfzC,EAAUmH,SAASqD,QACtBjH,GAAc,IAkBVkH,GAAkBzN,EAAY,KACnC0N,WAAW,KACVnH,GAAc,IACZ,MACD,IAEGoH,GAAuB3N,EAC3B6J,IAGA,GAFAnB,QAAQC,IAAI,eAAgBkB,GAExBwC,KAA4BE,EAG/B,OAFAD,GAA2BsB,QAC3BxB,GAAchB,GAASA,EAAO,GAG/B7E,GAAc,IAEf,CAAC8F,KAGIwB,GAAc7N,EAAY,KAC/B4H,GAAiBuC,SAAU,EAC3B3C,IAAS,GACTG,IAAa,GACTd,EAA0BsD,SAAS8C,aAAapG,EAA0BsD,SAC1EhE,EAAiBgE,SACpBhE,EAAiBgE,QAAQvH,QAE1BuK,EAAcC,YACdT,GAAKmB,cAAcC,aACnBC,EAAQC,QAAQ,GAAGlI,gCAA0C,CAC5DP,OAAQA,EACRM,QACAlB,GAAIqH,GAAM9B,QACV+D,OAAQ,UAETxC,GAAWvB,QAAU,EACrBwB,GAAoBxB,QAAU,EAC9ByB,GAAuBzB,SAAU,EACjC2B,GAAmB3B,SAAU,EACzBhE,EAAiBgE,SACpBhE,EAAiBgE,QAAQkD,OAE1B5F,GAAO6F,QAASC,IACXpH,EAAiBgE,SAAShE,EAAiBgE,QAAQpM,oBAAoB,gBAAiBwP,KAE7F7F,GAAU,IACVuF,aAAahI,KACX,CAACkB,EAAkBsB,GAAQ0F,EAAevF,KAGvCuG,GAAsBjQ,EAAQ,IAAMkQ,IAAkC,IACtEC,GAAoBC,EAAqBpC,IACzCqC,GAAqBC,EAAsBH,IAE3CI,GAAgBzO,EAAYuI,UACjCX,GAAiBuC,SAAU,QACrBgD,EAAcuB,UAAU,GAAG1J,eACjCwC,IAAS,GACTG,IAAa,GACTd,EAA0BsD,SAAS8C,aAAapG,EAA0BsD,SAC9E3D,GAAoB,IAClB,CAACK,EAA2BsG,IAEzBwB,GAAe3O,EAAYuI,UAEhC,IAAIsD,GAAgB1B,UAAW8B,GAAM9B,QAArC,CACA0B,GAAgB1B,SAAU,EAC1B,IACC8B,GAAM9B,cAAgBwC,GAAKmB,cAAcc,UAEzCZ,EAAQC,QAAQ,GAAGlI,6BAAuC,CACzDP,OAAQuH,GAAU5C,QAClBrE,QACAlB,GAAIqH,GAAM9B,SAEX,CAAC,MAAON,GACRnB,QAAQC,IAAIkB,EAAO,8BACnBmE,EAAQC,QAAQ,GAAGlI,kCAA4C,CAC9DP,OAAQA,EACRM,QACA+D,MAAOgF,OAAOhF,IAEf,CAAS,QACTgC,GAAgB1B,SAAU,CAC1B,CAnB6C,GAoB5C,CAAC3E,EAAQO,EAAYD,IAElBgJ,GAA0B9O,EAC/B,EAAG+O,WACEA,GAAQA,EAAK5R,KAAO,GAAKyK,GAAiBuC,UAC7C7D,EAAmB8E,GAASA,EAAK4D,OAAOD,KACnCtD,GAAetB,SAAWnH,EAAUmH,UACxCsB,GAAetB,SAAU,EACzBtC,GAAa,KACZ4G,KACAQ,EAAsB,CACrBC,UAAW,GAAGnJ,eACdP,OAAQuH,GAAU5C,QAClBrE,QACAqJ,QAAS,sCAERnM,MAIN,CAACyL,GAAeQ,EAAuBlJ,EAAYD,EAAO9C,IAGrD0L,GAAY1O,EAAYuI,UAC7B,MAAM6G,EAAYpI,EAAgBA,EAAgBgD,OAAS,GACvDoF,GAAaxH,GAAiBuC,gBAC3BgD,EAAcuB,UAAU1J,EAAsBoK,GAChDxH,GAAiBuC,UACpBlF,GAAiByI,WAAWgB,GAAW,QAGvC,CAAC1H,EAAiBY,KAEfyH,GAA0BrP,EAAY,KACvCmG,GAAoBA,EAAiBgE,SACxChE,EAAiBgE,QAAQkD,OAE1B7G,GAAoB,GACpB,IACC,GAAIxD,GAAaA,EAAUmH,SAAWnH,EAAUmH,QAAQqD,OAAQ,CAE/D,MAAM8B,EAAatM,EAAUmH,QAAQqD,OAAO+B,iBAAiB,GAC7D,GAAID,EAAY,CACf,MAAME,EAAWF,EAAWG,cAC5BrJ,EAAe+D,QAAUqF,EAASE,WAAa,IAC/C,CAED,MAAMC,EAA6C,CAClDC,mBAAoB,MAEjB1D,GAAe,KAClByD,EAAqBE,SAAW3D,GAAe,IAEhD/F,EAAiBgE,QAAU,IAAI2F,cAAc9M,EAAUmH,QAAQqD,OAAQmC,GACvExJ,EAAiBgE,QAAQrM,iBAAiB,gBAAiBgR,IAG3D3I,EAAiBgE,QAAQrM,iBAAiB,OAAQ,KACjD6I,GAAwB,KAGzBe,GAAU,IAAID,GAAQqH,KACtB3I,EAAiBgE,QAAQ4F,MAAM,KAC/BpJ,GAAwB,EACxB,CACD,CAAC,MAAOqJ,GACRtH,QAAQC,IAAI,mCAAoCqH,EAChD,GACC,CAAChN,EAAWkJ,GAAgB4C,GAAyBrH,KAElDwI,GAAkBjQ,EAAYuI,UAC/B1B,EAA0BsD,SAC7B8C,aAAapG,EAA0BsD,SAExCkF,KACIzH,GAAiBuC,UACpBtD,EAA0BsD,QAAUuD,WAAWnF,UAC1CX,GAAiBuC,gBACdgD,EAAcuB,UAAU,GAAG1J,eACjCwB,GAAoB,KAEnB,OAEJC,GAAY,GACRmB,GAAiBuC,eACdgD,EAAcuB,UAAU,GAAG1J,cAEhC,CAACqK,GAAyBzH,GAAkBuF,IAE/CvP,EAAU,KACTmO,GAAmB5B,QAAU8F,IAC3B,CAACA,KAEJ,MAAMC,GAAsBlQ,EAC3B,EAAG+O,WACF,MAAMoB,EAAYxD,GAAKmB,cAAcqC,YACjCpB,EAAK5R,KAAO,GAAKgT,IACfvE,GAAuBzB,UAC3ByB,GAAuBzB,SAAU,EACjCwC,GAAKmB,cAAcsC,WAAW7H,MAAOwG,IACpC,GAAIA,GAAQA,EAAKtL,OAASsL,EAAKtL,MAAMuG,OAAS,EAAG,CAChD,MAAMvG,EAAQrC,SAASiP,cAAc,iBAErCrC,EAAQC,QAAQ,GAAGlI,8BAAwC,CAC1DP,OAAQuH,GAAU5C,QAClBrE,QACArC,MAAOsL,EAAKtL,MACZ6M,OAAQvB,EAAKuB,OACbC,IAAKxB,EAAKwB,IACVC,QAAS9E,GAAWvB,QACpBsG,iBAAkB9E,GAAoBxB,QACtCuG,KAAM,2BAEa,IAAhB3B,EAAKuB,QAAmBvB,EAAKwB,MAAQtE,GAAM9B,SAC9CwB,GAAoBxB,QAAU,EAC1BuB,GAAWvB,QAAU,GACxBuB,GAAWvB,SAAW,EACK,IAAvBuB,GAAWvB,SAAkB2B,GAAmB3B,QAKlB,IAAvBuB,GAAWvB,SAAiB1G,GAAOkN,SAC7C1D,aAAahI,IACbkI,EAAcuB,UAAU1J,EAAsB+J,EAAKtL,SANnDqI,GAAmB3B,SAAU,EAC7B8C,aAAahI,IACbkI,EAAcC,kBACRD,EAAcuB,UAAU1J,EAAsB+J,EAAKtL,UAM1D0D,GAAoB4H,EAAKtL,OACzBwJ,aAAahI,IACb0H,GAAKmB,cAAcC,aACnBC,EAAQC,QAAQ,GAAGlI,gCAA0C,CAC5DP,OAAQA,EACRM,QACAlB,GAAIqH,GAAM9B,QACV+D,OAAQ,mBAETtC,GAAuBzB,SAAU,EACjCuD,WAAW,IAAM3B,GAAmB5B,UAAW,QAGhDwB,GAAoBxB,SAAW,EAC3BwB,GAAoBxB,SAAW,IAClCuB,GAAWvB,QAAU,EACrB2B,GAAmB3B,SAAU,IAE1B1G,GAAOkN,QAAYtL,IAAmBA,IAAiBuL,YAAc7B,EAAKtL,MAOnE4B,IAAiBuL,YAAc7B,EAAKtL,OAASA,GAAOkN,SAC1DtL,IAAmBA,GAAgBwL,qBAAuBxL,GAAgByL,WAC7EzL,GAAgBwL,oBAAsB,EACtC1D,EAAcuB,UAAU1J,EAAsB+J,EAAKtL,QAE/C4B,KAAiBA,GAAgBwL,qBAAuB,KAX7DxL,GAAkB,CACjByL,UAAW,EACXD,oBAAqB,EACrBD,UAAW7B,EAAKtL,OAEjB0J,EAAcuB,UAAU1J,EAAsB+J,EAAKtL,QAUrD,KAGCT,GAAWmH,SAAiD,OAAtCnH,EAAUmH,QAAQ4G,kBAC3CrI,QAAQC,IAAI,yCAA0CoE,GAAU5C,SAChEwC,GAAKmB,cAAckD,UAAU,CAC5BC,MAAOjO,EAAUmH,QAAQ4G,iBAAmB,GAC5CG,OAAQnE,GAAU5C,aAKtB,CAACnH,EAAWwC,EAAQmH,GAAMQ,EAAepH,EAAYD,IAGhDhD,GAA0B9C,EAAYuI,UAC3C3B,GAAc,GACd4F,IAAa,GACbI,OACIpB,GAAUrB,UACbqB,GAAUrB,SAAU,EACpB8E,EAAsB,CACrBC,UAAW,eACX1J,OAAQuH,GAAU5C,QAClBmG,OAAQ,UACRxK,WAGFH,EAAiBwL,KACjB5K,GAAc,GACVqB,GAAiBuC,eACdgD,EAAcuB,UAAU,GAAG1J,kBAE9B4C,GAAiBuC,eACdgD,EAAcuB,UAAU,GAAG1J,6BAE9B4C,GAAiBuC,UACpBvD,GAAc,GACdJ,GAAoB,GACpBe,IAAW,GACXI,IAAa,GACb8F,MAED,IACC,GAAIzK,GAAaA,EAAUmH,SAAWnH,EAAUmH,QAAQqD,QAAU5F,GAAiBuC,QAAS,CAE3F,MAAMmF,EAAatM,EAAUmH,QAAQqD,OAAO+B,iBAAiB,GAC7D,GAAID,EAAY,CACf,MAAME,EAAWF,EAAWG,cAC5BrJ,EAAe+D,QAAUqF,EAASE,WAAa,IAC/C,CAED,MAAMC,EAA6C,CAClDC,mBAAoB,MAEjB1D,GAAe,KAClByD,EAAqBE,SAAW3D,GAAe,IAE5CtE,GAAiBuC,UACpBhE,EAAiBgE,QAAU,IAAI2F,cAAc9M,EAAUmH,QAAQqD,OAAQmC,IAEpE/H,GAAiBuC,SAAWhE,EAAiBgE,SAChDhE,EAAiBgE,QAAQrM,iBAAiB,gBAAiBoS,IAG5DxI,GAAU,IAAIsF,GAAU7C,QAAS+F,KAC7B/J,EAAiBgE,SAAShE,EAAiBgE,QAAQ4F,MAAM,KAC7DpJ,GAAwB,GACpBiB,GAAiBuC,UACpBlF,GAAiByI,WAAWgB,GAAW,KAExC,CACD,CAAC,MAAOrD,GACR3C,QAAQC,IAAI,mBAAoB0C,EAChC,GACC,CAACrI,EAAWkJ,GAAgBgE,GAAqBxB,GAAW9G,GAAkBgF,KAgFjF,OA9EAhP,EAAU,KACToO,GAA2B7B,QAAUrH,IACnC,CAACA,KAEJlF,EAAU,KACLmI,IACHR,GAAgB,GAChBoJ,MAEM,KAIN,MAAMyC,EAASnF,GAAM9B,QACrB8B,GAAM9B,QAAU,KACZiH,IACHzE,GAAKmB,cAAcC,aACnBC,EAAQC,QAAQ,GAAGlI,gCAA0C,CAC5DP,OAAQuH,GAAU5C,QAClBrE,QACAlB,GAAIwM,EACJlD,OAAQ,aAGVzG,GAAO6F,QAASC,IACfpH,GAAkBgE,SAASpM,oBAAoB,gBAAiBwP,OAGhE,CAACxH,IACJnI,EAAU,KACToJ,EAAgBqK,KAAKvK,IACnB,CAACA,IAEJlJ,EAAU,KACTqJ,EAAmB,KACjB,CAACC,KACJtJ,EAAU,KACT,MAAM0T,EAAuBjL,EAAe2D,QAAU3D,EAAe2D,OAAS,EACzEtD,IAAwB4K,GAAyBzO,IAAoB+E,GAAiBuC,SAAYvH,IAClGuD,GAAoBA,EAAiBgE,UACnCtH,GACJsD,EAAiBgE,QAAQkD,SAM1B,CAAC3G,EAAsB7D,EAAkBwD,EAAgBzD,KAE5DhF,EAAU,KACT,MAAM0T,EAAuBjL,EAAe2D,QAAU3D,EAAe2D,OAAS,EAC9E,GAAItD,GAAwB4K,IAAyBzO,GAChDsD,GAAoBA,EAAiBgE,SAAWvC,GAAiBuC,UAAYvH,KAC3EC,EAAkB,CACtB,MAAM0O,EAAY,IAAIC,KAAKnL,EAAgB,GAAGb,KAAU+I,KAAsB,CAC7EmC,KAAMrC,KAEPxB,OACAH,MAAmB,GACnBhH,EAAkB,IAElB+G,KAAiB8E,EAAWnL,EAAe+D,QAC3C,GAGD,CAACzD,EAAsB7D,EAAkBwD,EAAgBzD,GAAOuD,EAAkByB,KACrFhK,EAAU,KACToO,GAA2B7B,QAAUrH,IACnC,CAACA,KAEJlF,EAAU,KACT,MAAM6T,EAAYC,EAA+BvD,GAAqBwD,GACtExF,GAAkBsF,IAChB,CAACtD,KACJvQ,EAAU,KACT2E,MACE,IAGFpE,EAACmE,GAAe,CACfY,cAAeA,EACfX,UAAWA,GACXC,WAAYA,EACZE,QAASmL,GACTvG,YAAaA,GACb1E,MAAOA,GACPD,SAxaoB4F,UACrBqJ,EAA0B,CACzB1C,UAAW,GAAGnJ,WACdD,QACAN,OAAQuH,GAAU5C,QAClBxL,OAAQsH,EACRD,SACAsK,QAAQ,IAET3D,GAAKmB,cAAcC,aACnBxL,WACMoM,MA8ZL9L,iBAAkBA,EAClBtD,WAAYA,EACZuD,wBAAyBA,GACzBO,SAAUA,EACVoL,cAAeA,GACf1L,UAAWA,GACXC,UAAWA,EACXP,YAAagL,GACbxK,iBAAkB0K,GAClBxK,iBAAkBkJ,GAClBjJ,UAAWA,IAGd,GCtiBc,SAAUyO,IAAcrM,OACpCA,EAAMK,YACNA,EAAWJ,mBACXA,EAAkBC,kBAClBA,EAAiBC,iBACjBA,EAAgBC,iBAChBA,IAEA,MAAOvG,EAAOyS,GAAYzU,EAAS,KAC5B0U,EAAmBC,GAAwB3U,EAAS,IACpDiC,EAAW2S,GAAgB5U,EAAwB,OACnDkC,EAAYqH,GAAiBvJ,GAAS,IACtCoC,EAAgByS,GAAqB7U,EAAS,GAC/C8U,EAAgBjM,EAAiB,KAChCkM,EAAc7M,GAAmBlI,GAAS,GAC3CgV,EAAkBhT,EAAQ0S,EAC1BvS,EAAkB6S,GAAmB,IAAMA,GAAmB,GAYpEzU,EAAU,KACR,GAAsB,oBAAXN,QAA0BA,OAAOgV,uBAAwB,CAClE,MAAMC,EAAqBC,IACzB,GAAmB,OAAfA,EAAMC,KAAe,CACvB,IAAIC,EAAWzS,KAAK0S,IAAIH,EAAMC,MACV,OAAhBD,EAAMI,QACRF,GAAYzS,KAAK4S,IAAKL,EAAMI,MAAQ3S,KAAK6S,GAAM,MAEjDJ,EAAWzS,KAAKC,IAAI,EAAGD,KAAKE,IAAI,IAAKuS,IACrCZ,EAASY,EACV,GAGGK,EAAoBxK,UACxB,MAAMyK,EACJV,uBAEF,GACEU,GAC+C,mBAAxCA,EAAkBD,kBAEzB,IAEqB,kBADMC,EAAkBD,qBAGzCzV,OAAOQ,iBAAiB,oBAAqByU,EAEhD,CAAC,MAAOvC,GACPtH,QAAQmB,MAAM,mBAAoBmG,EACnC,MAGD1S,OAAOQ,iBAAiB,oBAAqByU,GAG/C,MAAO,KACDA,GACFjV,OAAOS,oBAAoB,oBAAqBwU,KAKtDnR,SAAStD,iBAAiB,QAASiV,EAAmB,CAAEE,MAAM,GAC/D,GACA,IAEHrV,EAAU,KAMR,GALAuU,EAAchI,QAAU,IACnBgI,EAAchI,QAAQW,UACzBuH,GAGEF,EAAchI,QAAQH,QAAU,EAAG,CACrC,MAAMkJ,EACJjT,KAAKC,OAAOiS,EAAchI,SAAWlK,KAAKE,OAAOgS,EAAchI,SAE/D+H,EADE1S,GAAmB0T,EAAY,EACd9H,GAASnL,KAAKE,IAAI,IAAKiL,EAAO,IAE9BA,GAASnL,KAAKC,IAAI,EAAGkL,EAAO,IAElD,CAEI5L,GAAkC,OAAdF,IAAsBC,GAC7C4T,KAED,CAACd,EAAiB7S,EAAiBF,EAAWC,IAElD3B,EAAU,KACL6B,GAAkB,KAAqB,OAAdH,IAAuBC,GACnD6T,IAEG3T,EAAiB,IAAoB,OAAdH,GAC1B6T,KAEC,CAAC1T,EAAgBH,EAAWC,IAE9B,MAAM6T,EAAiB,KACrBnB,EAAa,GACb,MAAMoB,EAAQC,YAAY,KACxBrB,EAAc7G,GACC,OAATA,GAAiBA,GAAQ,GAC3BmI,cAAcF,GACdzM,GAAc,GACP,MAEFwE,EAAO,IAEf,MAGC+H,EAAiB,KACrBlB,EAAa,MACRG,GACHxL,GAAc,IAKlB,OACEzI,EAACiB,GAAW,CACVC,MAAOgT,EACP/S,UAAWA,EACXC,WAAYA,EACZC,gBAAiBA,EACjBC,eAAgBA,EAAcvC,SAE7BqC,GACCpB,EAACmH,IACCC,gBAAiBA,EACjBrC,cAvHc,KACpB4O,EAAS,IACTE,EAAqB,GACrBC,EAAa,MACbrL,GAAc,GACdsL,EAAkB,GAClB3M,GAAgB,GAChB4M,EAAchI,QAAU,IAiHlB3E,OAAQA,EACRK,YAAaA,EACbJ,mBAAoBA,EACpBC,kBAAmBA,EACnBC,iBAAkBA,EAClBC,iBAAkBA,KAK5B,CCpJA,SAAS4N,IAAiBC,cAAEA,EAAa5T,OAAEA,EAAM6T,OAACA,IACjD,MAAOC,EAAiBC,GAAsBvW,EAAS,CACtDsH,UAAU,EACVwK,QAAS,MAEH0E,EAASC,GAAczW,GAAS,GACjC2F,EAAYkD,EAAO,MAEnB6N,EAAyB/T,EAAYuI,UAC1C,MAAMyL,QAAmBC,IACzBL,EAAmBI,GACnBF,GAAW,IACT,IAMH,OAJAlW,EAAU,KACTmW,KACE,IAECF,EACI1V,EAAC+V,EAAa,CAACC,IAAKT,EAAQU,WAAW,UAG3CT,GAAiBhP,SACbxG,EAACkW,EAAK,CAACxU,OAAQA,EAAQsP,QAASwE,GAAiBxE,UAGxDhR,EAACqF,GAAM,CACNC,OAAO,EACPC,IAAKV,EACLW,kBAAmB,EACnBR,iBAAkBA,EAClBS,YACAnB,YAAa,IAAMgR,KAAgB,GACnC5P,iBAAiB,aACjBxD,MAAO,CACNyD,SAAU,WACVC,IAAK,EACLC,OAAQ,EACRC,OAAQ,EACRvF,MAAO,OACPC,OAAQ,OACRuF,UAAW,UAIf,CC/CA,SAASoQ,IAAYC,KAAEA,EAAIC,QAAEA,EAAOC,iBAAEA,EAAmB,8CACxD,MAAMC,EAAiBxO,EAAgC,MACjDyO,EAAkBzO,EAAsB,MAE9C,IAAI0O,EAAsB,CACzBC,UAAU,EACVC,UAAU,EACVC,YAAY,EACZC,OAAO,EACPC,OAAO,EACPC,aAAc,OACdpQ,QAAS,WACTqQ,OAAQC,GAkCT,OA/BAxX,EAAU,KACT,IAAK+W,EAAgBxK,SAAWoK,GAAQG,GAAgBvK,QAAS,CAChE,MAAMkL,EAASC,GAAQZ,EAAevK,QAAS,IAC3CyK,IAEJS,EAAOlM,MAAM,KACZwL,EAAgBxK,QAAUkL,EAE1B,MAAME,EAAiB,IACnBX,EACHY,QAAS,CAAC,CAAEzQ,IAAKwP,EAAM7D,KAAM,2BAG9B2E,EAAOR,SAASU,EAAeV,UAC/BQ,EAAOtQ,IAAIwQ,EAAeC,SAE1BhB,IAAUa,IAEX,GACC,CAACd,EAAMG,IAEV9W,EAAU,KACT,MAAMyX,EAASV,EAAgBxK,QAC/B,MAAO,KACFkL,IAAWA,EAAOI,eACrBJ,EAAOK,UACPf,EAAgBxK,QAAU,QAG1B,CAACwK,IAGHxW,EAAA,MAAA,CAAKoD,UAAWkT,EAAgBvX,SAC/BiB,EAAA,QAAA,CAAOuF,IAAKgR,EAAgBO,OAAK,EAAC1T,UAAU,WAAWoU,aAAW,EAACC,OAAS5F,GAAMA,EAAE6F,oBAGvF,CC5CA,SAASC,IAAiBC,eAAEA,EAAcC,OAAEA,EAAMhQ,OAAEA,EAAMJ,iBAAEA,EAAgBH,mBAAEA,IAC7E,MAAM/F,UAAEA,GAAcC,EAAWC,IAAoB,CAAA,EAC/CqW,EAAiBnW,KAChBoW,EAAWC,GAAgB9Y,GAAS,GAWrC+Y,EAAkB,KACvBD,GAAcD,IAIf,OACCzX,EAAA4X,EAAA,CAAAnZ,SAAA,CACCuB,EAAA,MAAA,CAAA,cAAiB,qBAAqB8C,UAAU,oGAAoGlB,MAAO,CAAEiW,WAAYL,GAAgB5V,OAAOuB,MAAMxB,iBAAiBlD,SAAA,CACtNiB,EAAA,MAAA,CAAKoD,UAAU,6DACdpD,EAACqD,EAAM,CAACC,SAAO,MAEhBtD,EAAA,MAAA,CAAKoD,UAAU,SAAQrE,SACrB6Y,GACAtX,EAAA,MAAA,CAAK8C,UAAU,YAAWrE,SAAA,CACzBiB,EAAA,KAAA,CACCoD,UAAU,cACVlB,MAAO,CACNsB,WAAYsU,GAAgB5V,OAAOkW,SAASC,mBAAqB,wBACjEC,SAAUR,GAAgB5V,OAAOkW,SAASG,iBAAmB,OAC7D5U,MAAOmU,GAAgB5V,OAAOkW,SAASI,cAAgB,OACvDC,WAAYX,GAAgB5V,OAAOkW,SAASM,mBAAqB,UACjE3Z,SAEAwC,IAAYwC,EAAa4U,iBAE3B3Y,EAAA,IAAA,CACCkC,MAAO,CACNsB,WAAYsU,GAAgB5V,OAAOuB,MAAMC,gBAAkB,oBAC3D4U,SAAUR,GAAgB5V,OAAOuB,MAAMmV,cAAgB,OACvDjV,MAAOmU,GAAgB5V,OAAOuB,MAAMoV,eAAiB,WACrD9Z,SAEAwC,IAAYwC,EAAagM,UAE3B/P,EAAA,IAAA,CACCkC,MAAO,CACNsB,WAAYsU,GAAgB5V,OAAOuB,MAAMC,gBAAkB,oBAC3D4U,SAAUR,GAAgB5V,OAAOuB,MAAMmV,cAAgB,OACvDjV,MAAOmU,GAAgB5V,OAAOuB,MAAMoV,eAAiB,WACrD9Z,SAEA+Z,EAAmBlB,KAGrB5X,EAAA,MAAA,CAAKoD,UAAU,iDAAiD+B,QAAS8S,EAAiBrR,IAAKmS,EAA0BlR,GAASmR,IAAI,cAIxIpB,GACA5X,SAAKoD,UAAU,6BAA4BrE,SAC1CiB,EAACgG,EAAc,CAAA,cAAa,iBAAiBQ,UAAU,EAAOL,WAAY5E,IAAYwC,EAAakV,WAAY7V,UAAU,eAAegD,WA3DtH,KAClByR,EACHA,MAEApQ,IAAmBsH,KAEpBzH,KAAqB,WAyDnByQ,GACAzX,EAAC4Y,GAAM,CAAC9V,UAAU,gCAAgC+V,QAASlB,EAAiBmB,KAAMrB,EAAShZ,SAAA,CAC1FiB,EAAA,MAAA,CAAKoD,UAAU,mBAAkBrE,SAChCiB,EAAA,OAAA,CAAMoD,UAAU,WAAW+B,QAAS8S,EAAelZ,SAClDiB,EAACoF,GAAC,CAAChC,UAAU,wDAGfpD,EAAA,MAAA,CAAKoD,UAAU,4CAA2CrE,SACzDiB,EAACmW,IAAYC,KAAMvO,EAASwR,EAAOxR,GAAQyR,SAAWD,EAAOE,KAAKD,SAAUhD,iBAAiB,oDAMnG,CCnFA,SAASkD,IAAOzG,OACfA,EAAMrL,YACNA,EAAWhG,OACXA,EAAM+X,uBACNA,EAAsBC,uBACtBA,EAAsBC,WACtBA,EAAUC,UACVA,EAASC,oBACTA,EAAmBrL,KACnBA,IAEA,MAAM3G,OAAEA,EAAMD,WAAEA,EAAUE,WAAEA,EAAUgS,kBAAEA,EAAiBC,SAAEA,EAAQpS,MAAEA,EAAKqS,SAAEA,GAAatS,GAAe,CAAA,EAClGuS,EAAW,CAACC,EAAsBC,EAAsBC,GAA0BC,SAASL,GAAY,KACtGM,EAAYhF,GAAiBpW,GAAS,GAYvCqb,EAAe1Y,EAAYuI,UAChC,IACK6P,UACGzL,GAAMgM,KAAKC,QAAQ,CACxB1H,SACApL,QACA+S,KAAMX,EACNlS,SACArH,OAAQsH,KAET+R,OApBFhK,EAAQC,QAAQlI,GAAY,GAAI,CAC/BP,OAAQ0L,EACRpL,MAAOA,EACPnH,OAAQsH,EACR6S,YAAab,EACbc,WAAY,IACZ/S,OAAQA,GAiBR,CAAC,MAAO6D,GACRnB,QAAQC,IAAIkB,EACZ,GACC,CAACuO,KAEE1Y,UAAEA,GAAcC,EAAWC,IAAoB,CAAA,EAErDhC,EAAU,MACLga,GAA0BC,IAC7Ba,KAEC,CAACd,EAAwBC,IAO5B,MAAMmB,GAAkBjB,GAAaH,GAA0BC,KAA4BO,EAE3F,OACCja,EAAC8a,IAAI1X,UAAU,6CAA4CrE,SAC1DuB,EAAA,MAAA,CAAK8C,UAAU,0DAAyDrE,SAAA,CACvEiB,EAACqV,GAAgB,CAACE,OAAQ7T,GAAQ6T,OAAQD,cAAeA,IACzDtV,EAAC+a,GAAM,CACN3B,KAAMkB,EACNnB,QAAS,CAAC6B,EAAGjL,OAKb3M,UAAU,gBACV6X,OAAO,SAAQlc,SAEfiB,EAAA,MAAA,CACCoD,UAAU,mIACVlB,MAAO,CAAEiW,WAAYzW,GAAQQ,OAAOuB,MAAMxB,0BAE1C3B,EAAA,MAAA,CAAK8C,UAAU,8BAA6BrE,SAAA,CAC3CiB,EAACqD,EAAM,CAAC6X,MAAO3Z,IAAYwC,EAAaoX,0BACxCnb,EAAA,MAAA,CAAKoD,UAAU,0CAAyCrE,SACvDiB,EAAA,QAAA,CAAO2G,QAAQ,OAAOvD,UAAU,sEAAsE0T,OAAK,EAACsE,MAAI,EAACC,UAAQ,EAAC7D,aAAW,EAAAzY,SACpIiB,EAAA,SAAA,CAAQ4G,IAAKiB,IAAWyT,EAAWC,KAAOC,EAA0BC,EAAqBlJ,KAAK,kBAG/FsI,GAAkB7a,EAACgG,EAAc,CAAC5C,UAAU,qBAAqB+C,WAAY5E,IAAYwC,EAAa2X,MAAOtV,WAAY,KAAKuT,oBAQtI,CC3FO,MAAMgC,GAAgB,KAC5B,MAAMjU,YACLA,EAAWkU,QACXA,EAAOC,QACPA,EAAOjC,UACPA,EAAS/R,OACTA,EAAMiU,cACNA,EAAalE,eACbA,EAAcnQ,iBACdA,EAAgBH,mBAChBA,EAAkBoS,uBAClBA,EAAsBD,uBACtBA,EAAsB/D,QACtBA,EAAOF,gBACPA,EAAeuG,cACfA,EAAaxU,kBACbA,EAAiBC,iBACjBA,EAAgBpD,UAChBA,EAASyV,oBACTA,EAAmBrL,KACnBA,EAAImL,WACJA,GACGnY,EAAWmN,GACTmJ,EAAiBnW,IAEvB,OAAIka,EAEFvb,EAAA,MAAA,CAAA,kBAAqB,QAAOvB,SAAA,CAC3BiB,EAACqV,GAAgB,CAAA,GACjBrV,EAAC+a,GAAM,CACNE,OAAO,SACP7B,MAAM,EACNhW,UAAU,gBACV+V,QAAS,CAAC9E,EAAOtE,gBAMjB/P,EAAC2X,GAAgB,CAACC,kBAAeC,OAAQ+D,EAAS/T,OAAQA,SAM1D+R,EACI5Z,EAAA,MAAA,CAAA,kBAAqB,UAASjB,SAACiB,EAACwZ,GAAM,CAACI,WAAS,EAACD,WAAYA,MAGjEjE,EAEF1V,EAAA,MAAA,CAAA,kBAAqB,UAAUoD,UAAU,sFAAsFlB,MAAO,CAAEiW,WAAYL,GAAgB5V,OAAOuB,MAAMxB,iBAAiBlD,SACjMiB,EAAC+V,EAAa,CAACC,IAAK8B,GAAgBvC,OAAQU,WAAW,YAItDT,EAAgBhP,SACZxG,2BAAqB,gBAAejB,SAACiB,EAACkW,EAAK,CAAA,KAG9C6F,GAAkBnE,GAAmB8B,GAA2BD,GAchEsC,GAAiBrC,GAA0BD,KAA4B7B,EAE1E5X,EAAA,MAAA,CAAA,kBAAqB,sBACrBA,EAACwZ,IACAzG,OAAQ+I,EACRpC,uBAAwBA,EACxBhS,YAAaA,EACb+R,uBAAwBA,EACxBI,oBAAqBA,EACrBrL,KAAMA,EACNmL,WAAYA,EACZjY,OAAQoW,MAMVxX,EAAA,MAAA,CAAA,kBAAqB,cAAavB,SAAA,CACjCiB,EAACqV,GAAgB,CAAA,GACjBrV,EAAC+a,GAAM,CACNE,OAAO,SACP7B,MAAI,EACJhW,UAAU,gBACV+V,QAAS,CAAC9E,EAAOtE,OAIhBhR,SAEDiB,EAAC2X,GAAgB,CAChBC,eAAgBA,EAChBC,OAAQ,KACP+D,MACAxX,KAEDqD,iBAAkBA,EAClBI,OAAQA,EACRP,mBAAoBA,SAjDtBtH,EAAA,MAAA,CAAA,kBAAqB,WAAUjB,SAC/BiB,EAAC0T,GAAa,CACbrM,OAAQyU,EACRpU,YAAaA,EACbJ,mBAAoBA,EACpBC,kBAAmBA,EACnBC,iBAAkBA,EAClBC,iBAAkBA,OCzDhBuU,GAAqCC,IAC1C,MAAMva,OACLA,EAAMka,QACNA,EAAOnN,YACPA,EAAWC,kBACXA,EAAiBwN,cACjBA,EAAaC,YACbA,EAAWC,yBACXA,EAAwBC,yBACxBA,EAAwBC,0BACxBA,EAAyBC,YACzBA,EAAWC,cACXA,EAAa3C,oBACbA,EAAmBF,WACnBA,EAAUkC,QACVA,EAAOjC,UACPA,GACGqC,EACEvU,EAA2B,CAChCC,MAAO,GACPC,WAAY,GACZC,OAAQ,OACRC,WAAY,EACZkS,SAAU,GACVF,kBAAmB,EACnB2C,gBAAiB,GACjBC,UAAW,GACXC,YAAa,QACTV,EAAMvU,aAAe,IAEpBkV,EAAQX,EAAMW,OAAS,IACvB/U,OAAEA,EAAMmS,SAAEA,EAAQpS,WAAEA,EAAUE,WAAEA,EAAUH,MAAEA,EAAKmS,kBAAEA,EAAiB2C,gBAAEA,EAAeE,YAAEA,EAAWD,UAAEA,GAAchV,EAClH8G,EAAOzO,EAAQ,IAAM8c,EAAeD,GAAQ,CAACA,KAC5Cb,EAAexN,GAAoBrP,GAAS,IAC5Cua,EAAwBqD,GAA6B5d,GAAS,IAC9Dwa,EAAwBqD,GAA6B7d,GAAS,IAC9DsW,EAAiBC,GAAsBvW,EAAS,CACtDsH,UAAU,EACVwK,QAAS,MAEH4G,GAAgBrQ,IAAqBrI,EAAS,KAC9C8d,GAAiB1V,IAAsBpI,GAAS,IAChDwW,GAASC,IAAczW,GAAS,IAChC+d,GAAW5O,IAAgBnP,GAAS,IACpC4c,GAAerU,IAAoBvI,EAAS,KAC5Cge,GAAe1V,IAAoBtI,EAAwB8T,MAC5DmK,SAAEA,ICzDT,SAAuBF,GACrB,MAAOE,EAAUC,GAAele,EAAyB,KAClDme,EAAmBC,GAAwBpe,GAAS,GAErDkV,EAAoBvS,EAAawS,IACrC,IACE,MAAMkJ,MAAEA,EAAKjJ,KAAEA,EAAIG,MAAEA,GAAUJ,EAC/B+I,EAAanQ,GAAyB,IACjCA,EACH,CACEsQ,MAAOA,GAAOC,iBAAc3e,EAC5ByV,KAAMA,GAAMkJ,iBAAc3e,EAC1B4V,MAAOA,GAAO+I,iBAAc3e,EAC5B4e,WAAW,IAAIC,MAAOC,gBAG3B,CAAC,MAAOjS,GACPnB,QAAQC,IAAIkB,EACb,GACA,IAEGkJ,EAAoB/S,EAAYuI,UACpC,MAAMyK,EACJV,uBAEF,QAC+B,IAAtBU,GACwC,mBAAxCA,EAAkBD,kBAEzB,IAEmB,kBADMC,EAAkBD,oBAEvC0I,GAAqB,GAErB/S,QAAQkB,KAAK,wCAEhB,CAAC,MAAOC,GACPnB,QAAQmB,MAAM,kDAAmDA,EAClE,MAGD4R,GAAqB,IAEtB,IAmBH,OAjBA7d,EAAU,KACJwd,GAAaI,EACfle,OAAOQ,iBAAiB,oBAAqByU,GAE7CgJ,EAAY,IAEP,KACLje,OAAOS,oBAAoB,oBAAqBwU,KAEjD,CAAC6I,EAAWI,EAAmBjJ,IAElC3U,EAAU,KACJwd,GACFrI,KAED,CAACqI,EAAWrI,IAER,CAAEuI,WACX,CDNsBS,CAAcX,IACnCY,IAEA,MAAMzZ,GAAYvC,EAAY,KAC7B4F,GAAiBsH,KACjBxH,GAAkB,IAClBgH,GAAiB,GACjBjH,IAAmB,IACjB,IAyBGwW,GAA8B,KACnCtW,GAAiB,MACjBC,GAAiB,KAGZsW,GAAYlc,EACjBuI,MAAOwG,IACN,GAAIA,GAA6B,YAArBA,GAAMoN,YAAiD,iBAArBpN,GAAMqN,YAAgD,MAAfrN,GAAMsN,KAS1F,OARApN,EAAsB,CACrBC,UAAW,GAAGnJ,qCACdP,OAAQyU,GACR3J,OAAQ,UACRxK,UAEDmV,GAA0B,QAC1BR,IAA4B1L,GAG7B4L,IAAgB5L,GAChBkM,GAA0B,GAC1BgB,KACA,MAAMK,EAAcrC,GACpBiB,GAA0B,GAC1BjM,EAAsB,CACrBC,UAAW,GAAGnJ,iCACdP,OAAQ8W,EACRhM,OAAQ,UACRxK,UAEGuV,IACHpM,EAAsB,CACrBC,UAAW,GAAGnJ,yBACdP,OAAQ8W,EACRhM,OAAQ,UACRiM,eAAgBpL,IAA4BkK,GAC5CvV,WAGH,CAACqS,EAAUpS,EAAYkU,KAGlBuC,GAAmCtL,IACxCgK,GAA0B,GAC1BxV,GAAkB,IAClBuV,GAA0B,GAC1BtO,EAAK8P,YAAYC,wBAAwB,CACxCxL,OAAkB+I,GAClB0C,UAAW,KACVC,EAAuB,CACtB1N,UAAW,GAAGnJ,cACdP,OAAQyU,GACR4C,WAAY,WACZnM,KAAM,6BACN5K,WAGFgX,OAAQ,KACPvC,MACAqC,EAAuB,CACtB1N,UAAW,GAAGnJ,cACdP,OAAQyU,GACR4C,WAAY,OACZnM,KAAM,6BACN5K,WAGFwR,QAAS,KACRkD,MACAoC,EAAuB,CACtB1N,UAAW,GAAGnJ,cACdP,OAAQyU,GACR4C,WAAY,QACZnM,KAAM,6BACN5K,WAGFiX,QAAU1R,IAnGI,IAAC0D,IAoGN1D,EAnGVqP,IAAc,IAAK3L,EAAMI,QAAS8H,EAAmBlI,KACrDkN,KACAf,GAA0B,GAC1BxV,GAAkBqJ,GAClBkM,GAA0B,GAC1BhM,EAAsB,CACrBC,UAAW,GAAGnJ,gCACdP,OAAQyU,GACR3J,OAAQ,SACRxK,QACAqJ,QAAS8H,EAAmBlI,KAEzBsM,IACHpM,EAAsB,CACrBC,UAAW,GAAGnJ,yBACdP,OAAQyU,GACR3J,OAAQ,SACRiM,eAAgBpL,IAA4BkK,GAC5CvV,UAkFA8W,EAAuB,CACtB1N,UAAW,GAAGnJ,cACdP,OAAQyU,GACR4C,WAAY,QACZnM,KAAM,6BACN5K,WAGFoW,UAAYnN,IACX6N,EAAuB,CACtB1N,UAAW,GAAGnJ,cACdP,OAAQyU,GACR4C,WAAY,UACZnM,KAAM,6BACN5K,UAEDoW,GAAUnN,OAKPtC,GAAiBzM,EACtBuI,MAAOyU,EAAYC,KAClB,MAAMC,EAAeC,QAAQH,EAAK7f,cAAsBigB,QAAQ,IAE1DC,EAAWJ,QAAoDA,QAAoBK,EAAYN,GAC/FO,EAAgBC,EAA0B,CAC/CxX,SACAyX,aAAc,GAAGxF,IACjBtZ,OAAQ,GAAGsH,IACXyX,mBAAoB3X,EACpB4X,YA9Le,IA+LfC,UAAWzF,EACX0F,aAAc/C,EACdgD,WAAYjD,IAEb5L,EAAsB,CACrBC,UAAW,GAAGnJ,wBACdP,OAAQyU,GACRnU,QACAiJ,KAAMgP,KAAKC,UAAU,IAAIT,EAAe,CAAEL,eAAce,UAAWZ,GAAY,OAEhFhD,MACA,UACO1N,EAAKuR,WAAWC,mBAAmB,CACxCnB,OACAO,gBACArM,OAAQ+I,GACRnU,gBAEK6G,EAAKuR,WAAWE,cAAc,CACnCC,MAAOzD,EACP0D,UAAW,SACXC,KAAMjD,GACNpK,OAAQ+I,KAETvR,QAAQC,IAAI,+BACZlD,IAAmB,GACnBwJ,EAAsB,CACrBC,UAAW,GAAGnJ,iBACdP,OAAQyU,GACR3J,OAAQ,UACRxK,QACAiJ,KAAMgP,KAAKC,UAAUT,KAEtBtO,EAAsB,CACrBC,UAAW,gBACX1J,OAAQyU,GACR3J,OAAQ,UACRxK,UAEDH,GAAiBwL,KACjBzD,WAAW,KACVjI,IAAmB,IACjB,IACH,CAAC,MAAOoE,GACRoF,EAAsB,CACrBC,UAAW,gBACX1J,OAAQyU,GACR3J,OAAQ,SACRxK,QACAqJ,QAAS8H,EAAmBpN,KAE7BoF,EAAsB,CACrBC,UAAW,GAAGnJ,gBACdP,OAAQyU,GACR3J,OAAQ,SACRxK,QACAqJ,QAAS8H,EAAmBpN,GAC5BkF,KAAMgP,KAAKC,UAAUT,KAEtB7X,GAAkBuR,EAAmBpN,IACrCpE,IAAmB,GACnBiV,IAAc,IAAI7Q,EAAOsF,QAAS8H,EAAmBpN,KACrDoS,IACA,CAAS,QACTzP,IAAa,GACb8N,KACA,GAEF,CAACL,GAAeqB,GAAUjB,EAAeC,IAkCpCvG,GAAyB/T,EAAYuI,UAC1C,IAAKtC,EAAa,QAAUA,EAAa,OAIxC,YAHAyU,IAAc,CACbvL,QAAS,4DAKX,MAAM6E,QAAmBC,IACrBD,EAAWrP,UACdsK,EAAsB,CACrBC,UAAW,GAAGnJ,sBACdP,OAAQyU,GACR3J,OAAQ,SACRxK,UAEDgO,IAAW,KAQXA,IAAW,GACX7E,EAAsB,CACrBC,UAAW,GAAGnJ,sBACdP,OAAQyU,GACR3J,OAAQ,UACRxK,WAGF8N,EAAmBI,GACnBtO,GAAkB,IAClBD,IAAmB,IACjB,CAACK,EAAOmU,GAAerU,GAAkBG,IAe5C,OAbAnI,EAAU,KACLoc,GAAWjC,GACXhS,GACHgO,MAEC,CAAChO,EAAYE,EAAY+T,EAASjC,IAErCna,EAAU,KACLoc,GAAWjC,GACXoD,IAAmBpV,GAAckU,IACpCuC,MAEC,CAACrB,GAAiBpV,EAAYkU,GAAeD,EAASjC,IAExD5Z,uBAAiB,iBAAgBjB,SACjCiB,EAACqgB,EAAuB,CAAAthB,SACvBiB,EAACsgB,EAAc,CAAC5e,OAAQA,EAAM3C,SAC7BiB,EAAClB,GAAoB,CAAAC,SACpBiB,EAAC2O,EAAc1O,SAAQ,CACtBC,MAAO,CACNwH,cACAkU,UACAW,cACAV,UACAjC,YACA4C,gBACA3U,SACAiU,iBACAlE,kBACAnQ,oBACAH,sBACAoS,yBACAD,yBACA/D,WACAF,kBACAuG,gBACA1N,gBACAC,kBACAC,mBACAnK,aACAmD,qBACAC,oBACAiH,cACAC,oBACAmL,sBACAF,aACAnL,QACAzP,SAEDiB,EAAC2b,GAAa,CAAA,cAed4E,GAA+CtE,IACpD,MAAO9R,EAASqW,GAActhB,GAAS,GAKvC,OAJAO,EAAU,KACT+gB,GAAW,IACT,IAEErW,EAIEnK,EAACgc,GAAQ,IAAKC,IAHbjc,EAAA,MAAA,CAAA,cAAiB"}
|