aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLucas Faria Mendes <lucas.fariamo08@gmail.com>2026-08-14 18:06:35 +0000
committerLucas Faria Mendes <lucas.fariamo08@gmail.com>2026-08-14 18:06:35 +0000
commit2c2dfba45357bbd205a59145ae55a2779c911ae0 (patch)
tree0736b848aed56ec2da3c2489c49da0519447703d
downloadyaba-2c2dfba45357bbd205a59145ae55a2779c911ae0.tar.gz
yaba-2c2dfba45357bbd205a59145ae55a2779c911ae0.zip
remake
Signed-off-by: Lucas Faria Mendes <lucas.fariamo08@gmail.com>
-rw-r--r--.DS_Storebin0 -> 8196 bytes
-rw-r--r--.expo/README.md14
-rw-r--r--.expo/dev/logs/start.log425
-rw-r--r--.expo/devices.json8
-rw-r--r--.expo/types/router.d.ts14
-rw-r--r--.expo/web/cache/production/images/android-adaptive-background/android-adaptive-background-fb139c2dee362ebf2070e23b96da6fc0d43f8492de38b8af1fd7223e19b5861d-cover-transparent/icon_108.pngbin0 -> 3411 bytes
-rw-r--r--.expo/web/cache/production/images/android-adaptive-background/android-adaptive-background-fb139c2dee362ebf2070e23b96da6fc0d43f8492de38b8af1fd7223e19b5861d-cover-transparent/icon_162.pngbin0 -> 5960 bytes
-rw-r--r--.expo/web/cache/production/images/android-adaptive-background/android-adaptive-background-fb139c2dee362ebf2070e23b96da6fc0d43f8492de38b8af1fd7223e19b5861d-cover-transparent/icon_216.pngbin0 -> 8772 bytes
-rw-r--r--.expo/web/cache/production/images/android-adaptive-background/android-adaptive-background-fb139c2dee362ebf2070e23b96da6fc0d43f8492de38b8af1fd7223e19b5861d-cover-transparent/icon_324.pngbin0 -> 15702 bytes
-rw-r--r--.expo/web/cache/production/images/android-adaptive-background/android-adaptive-background-fb139c2dee362ebf2070e23b96da6fc0d43f8492de38b8af1fd7223e19b5861d-cover-transparent/icon_432.pngbin0 -> 23353 bytes
-rw-r--r--.expo/web/cache/production/images/android-adaptive-foreground/android-adaptive-foreground-9e3d0315a33c6799de601dd34cd8bf8cc3a8d16f3bf75592baec2ceb7240b391-cover-transparent/icon_108.pngbin0 -> 5598 bytes
-rw-r--r--.expo/web/cache/production/images/android-adaptive-foreground/android-adaptive-foreground-9e3d0315a33c6799de601dd34cd8bf8cc3a8d16f3bf75592baec2ceb7240b391-cover-transparent/icon_162.pngbin0 -> 11190 bytes
-rw-r--r--.expo/web/cache/production/images/android-adaptive-foreground/android-adaptive-foreground-9e3d0315a33c6799de601dd34cd8bf8cc3a8d16f3bf75592baec2ceb7240b391-cover-transparent/icon_216.pngbin0 -> 18945 bytes
-rw-r--r--.expo/web/cache/production/images/android-adaptive-foreground/android-adaptive-foreground-9e3d0315a33c6799de601dd34cd8bf8cc3a8d16f3bf75592baec2ceb7240b391-cover-transparent/icon_324.pngbin0 -> 39763 bytes
-rw-r--r--.expo/web/cache/production/images/android-adaptive-foreground/android-adaptive-foreground-9e3d0315a33c6799de601dd34cd8bf8cc3a8d16f3bf75592baec2ceb7240b391-cover-transparent/icon_432.pngbin0 -> 67631 bytes
-rw-r--r--.expo/web/cache/production/images/android-adaptive-monochrome/android-adaptive-monochrome-6371fc2c12e33ad2215a86c281db3d682a81bebe7c957a842c13b8bf00cceb83-cover-transparent/icon_108.pngbin0 -> 1317 bytes
-rw-r--r--.expo/web/cache/production/images/android-adaptive-monochrome/android-adaptive-monochrome-6371fc2c12e33ad2215a86c281db3d682a81bebe7c957a842c13b8bf00cceb83-cover-transparent/icon_162.pngbin0 -> 2139 bytes
-rw-r--r--.expo/web/cache/production/images/android-adaptive-monochrome/android-adaptive-monochrome-6371fc2c12e33ad2215a86c281db3d682a81bebe7c957a842c13b8bf00cceb83-cover-transparent/icon_216.pngbin0 -> 2629 bytes
-rw-r--r--.expo/web/cache/production/images/android-adaptive-monochrome/android-adaptive-monochrome-6371fc2c12e33ad2215a86c281db3d682a81bebe7c957a842c13b8bf00cceb83-cover-transparent/icon_324.pngbin0 -> 5065 bytes
-rw-r--r--.expo/web/cache/production/images/android-adaptive-monochrome/android-adaptive-monochrome-6371fc2c12e33ad2215a86c281db3d682a81bebe7c957a842c13b8bf00cceb83-cover-transparent/icon_432.pngbin0 -> 5325 bytes
-rw-r--r--.expo/web/cache/production/images/android-standard-circle/android-standard-circle-7a667804bb80a6a424a5daf18a2599c4f32237cf06fe78fc0de45dbb09e0eccf-cover-transparent/icon_144.pngbin0 -> 20940 bytes
-rw-r--r--.expo/web/cache/production/images/android-standard-circle/android-standard-circle-7a667804bb80a6a424a5daf18a2599c4f32237cf06fe78fc0de45dbb09e0eccf-cover-transparent/icon_192.pngbin0 -> 33103 bytes
-rw-r--r--.expo/web/cache/production/images/android-standard-circle/android-standard-circle-7a667804bb80a6a424a5daf18a2599c4f32237cf06fe78fc0de45dbb09e0eccf-cover-transparent/icon_48.pngbin0 -> 3480 bytes
-rw-r--r--.expo/web/cache/production/images/android-standard-circle/android-standard-circle-7a667804bb80a6a424a5daf18a2599c4f32237cf06fe78fc0de45dbb09e0eccf-cover-transparent/icon_72.pngbin0 -> 6950 bytes
-rw-r--r--.expo/web/cache/production/images/android-standard-circle/android-standard-circle-7a667804bb80a6a424a5daf18a2599c4f32237cf06fe78fc0de45dbb09e0eccf-cover-transparent/icon_96.pngbin0 -> 11269 bytes
-rw-r--r--.expo/web/cache/production/images/android-standard-square/android-standard-square-7a667804bb80a6a424a5daf18a2599c4f32237cf06fe78fc0de45dbb09e0eccf-cover-transparent/icon_144.pngbin0 -> 19451 bytes
-rw-r--r--.expo/web/cache/production/images/android-standard-square/android-standard-square-7a667804bb80a6a424a5daf18a2599c4f32237cf06fe78fc0de45dbb09e0eccf-cover-transparent/icon_192.pngbin0 -> 31064 bytes
-rw-r--r--.expo/web/cache/production/images/android-standard-square/android-standard-square-7a667804bb80a6a424a5daf18a2599c4f32237cf06fe78fc0de45dbb09e0eccf-cover-transparent/icon_48.pngbin0 -> 3090 bytes
-rw-r--r--.expo/web/cache/production/images/android-standard-square/android-standard-square-7a667804bb80a6a424a5daf18a2599c4f32237cf06fe78fc0de45dbb09e0eccf-cover-transparent/icon_72.pngbin0 -> 6282 bytes
-rw-r--r--.expo/web/cache/production/images/android-standard-square/android-standard-square-7a667804bb80a6a424a5daf18a2599c4f32237cf06fe78fc0de45dbb09e0eccf-cover-transparent/icon_96.pngbin0 -> 10335 bytes
-rw-r--r--.expo/web/cache/production/images/splash-android/splash-android-27b060a757a29038c9618586baa0ba3894dbe60d084c6059df497ff429c2d92f-contain/icon_114.pngbin0 -> 2128 bytes
-rw-r--r--.expo/web/cache/production/images/splash-android/splash-android-27b060a757a29038c9618586baa0ba3894dbe60d084c6059df497ff429c2d92f-contain/icon_152.pngbin0 -> 2814 bytes
-rw-r--r--.expo/web/cache/production/images/splash-android/splash-android-27b060a757a29038c9618586baa0ba3894dbe60d084c6059df497ff429c2d92f-contain/icon_228.pngbin0 -> 3365 bytes
-rw-r--r--.expo/web/cache/production/images/splash-android/splash-android-27b060a757a29038c9618586baa0ba3894dbe60d084c6059df497ff429c2d92f-contain/icon_304.pngbin0 -> 15489 bytes
-rw-r--r--.expo/web/cache/production/images/splash-android/splash-android-27b060a757a29038c9618586baa0ba3894dbe60d084c6059df497ff429c2d92f-contain/icon_76.pngbin0 -> 1223 bytes
-rw-r--r--.gitignore10
-rw-r--r--AGENTS.md3
-rw-r--r--CLAUDE.md1
-rw-r--r--LICENSE21
-rw-r--r--README.md56
-rw-r--r--app.json52
-rw-r--r--assets/.DS_Storebin0 -> 6148 bytes
-rw-r--r--assets/expo.icon/Assets/expo-symbol 2.svg3
-rw-r--r--assets/expo.icon/Assets/grid.pngbin0 -> 53681 bytes
-rw-r--r--assets/expo.icon/icon.json40
-rw-r--r--assets/images/android-icon-background.pngbin0 -> 17549 bytes
-rw-r--r--assets/images/android-icon-foreground.pngbin0 -> 78796 bytes
-rw-r--r--assets/images/android-icon-monochrome.pngbin0 -> 4140 bytes
-rw-r--r--assets/images/expo-badge-white.pngbin0 -> 4129 bytes
-rw-r--r--assets/images/expo-badge.pngbin0 -> 4137 bytes
-rw-r--r--assets/images/expo-logo.pngbin0 -> 3317 bytes
-rw-r--r--assets/images/favicon.pngbin0 -> 1129 bytes
-rw-r--r--assets/images/icon.pngbin0 -> 402945 bytes
-rw-r--r--assets/images/logo-glow.pngbin0 -> 331624 bytes
-rw-r--r--assets/images/react-logo.pngbin0 -> 6341 bytes
-rw-r--r--assets/images/react-logo@2x.pngbin0 -> 14225 bytes
-rw-r--r--assets/images/react-logo@3x.pngbin0 -> 21252 bytes
-rw-r--r--assets/images/splash-icon.pngbin0 -> 3317 bytes
-rw-r--r--assets/images/tabIcons/explore.pngbin0 -> 215 bytes
-rw-r--r--assets/images/tabIcons/explore@2x.pngbin0 -> 347 bytes
-rw-r--r--assets/images/tabIcons/explore@3x.pngbin0 -> 468 bytes
-rw-r--r--assets/images/tabIcons/home.pngbin0 -> 253 bytes
-rw-r--r--assets/images/tabIcons/home@2x.pngbin0 -> 343 bytes
-rw-r--r--assets/images/tabIcons/home@3x.pngbin0 -> 479 bytes
-rw-r--r--assets/images/tutorial-web.pngbin0 -> 58959 bytes
-rw-r--r--bun.lock1386
-rw-r--r--eas.json21
-rw-r--r--package.json54
-rw-r--r--scripts/reset-project.js114
-rw-r--r--src/app/(app)/(tabs)/_layout.tsx169
-rw-r--r--src/app/(app)/(tabs)/expenses.tsx2
-rw-r--r--src/app/(app)/(tabs)/index.tsx2
-rw-r--r--src/app/(app)/(tabs)/recurring.tsx2
-rw-r--r--src/app/(app)/(tabs)/salary.tsx2
-rw-r--r--src/app/(app)/_layout.tsx21
-rw-r--r--src/app/_layout.tsx54
-rw-r--r--src/app/biometrics.tsx120
-rw-r--r--src/app/login.tsx144
-rw-r--r--src/app/register.tsx142
-rw-r--r--src/components/animated-splash-screen.tsx103
-rw-r--r--src/components/expense-row.tsx213
-rw-r--r--src/components/ui/action-modal.tsx107
-rw-r--r--src/components/ui/button.tsx141
-rw-r--r--src/components/ui/expenses-chart.tsx187
-rw-r--r--src/components/ui/input.tsx98
-rw-r--r--src/components/ui/options-modal.tsx137
-rw-r--r--src/components/ui/primitives.tsx104
-rw-r--r--src/constants/theme.ts99
-rw-r--r--src/contexts/AuthContext.tsx107
-rw-r--r--src/global.css9
-rw-r--r--src/hooks/use-app-hooks.ts20
-rw-r--r--src/screens/dashboard-screen.tsx440
-rw-r--r--src/screens/one-time-expenses-screen.tsx485
-rw-r--r--src/screens/recurring-expenses-screen.tsx442
-rw-r--r--src/screens/salary-screen.tsx232
-rw-r--r--src/services/api.ts165
-rw-r--r--src/types/index.ts98
-rw-r--r--src/utils/tax-calculator.ts85
-rw-r--r--tsconfig.json20
99 files changed, 6172 insertions, 0 deletions
diff --git a/.DS_Store b/.DS_Store
new file mode 100644
index 0000000..60c030b
--- /dev/null
+++ b/.DS_Store
Binary files differ
diff --git a/.expo/README.md b/.expo/README.md
new file mode 100644
index 0000000..563b815
--- /dev/null
+++ b/.expo/README.md
@@ -0,0 +1,14 @@
+> Why do I have a folder named ".expo" in my project?
+
+The ".expo" folder is created when an Expo project is started using "expo start" command.
+
+> What do the files contain?
+
+- "devices.json": contains information about devices that have recently opened this project. This is used to populate the "Development sessions" list in your development builds.
+- "settings.json": contains the server configuration that is used to serve the application manifest.
+- "dev/logs/": contains structured JSONL event logs from CLI commands (e.g. start.log, export.log). These are truncated on each run.
+
+> Should I commit the ".expo" folder?
+
+No, you should not share the ".expo" folder. It does not contain any information that is relevant for other developers working on the project, it is specific to your machine.
+Upon project creation, the ".expo" folder is already added to your ".gitignore" file.
diff --git a/.expo/dev/logs/start.log b/.expo/dev/logs/start.log
new file mode 100644
index 0000000..a7b78f4
--- /dev/null
+++ b/.expo/dev/logs/start.log
@@ -0,0 +1,425 @@
+{"_e":"root:init","_t":1786664384002,"format":"v0-jsonl","version":"57.0.14"}
+{"_e":"devserver:start","_t":1786664384064,"mode":"development","web":true,"baseUrl":"","asyncRoutes":false,"routerRoot":"../../../src/app","serverComponents":false,"serverActions":false,"serverRendering":true,"apiRoutes":false,"exporting":false}
+{"_e":"metro:config","_t":1786664384333,"serverRoot":"../../..","projectRoot":"../../..","exporting":false,"flags":{"autolinkingModuleResolution":false,"serverActions":false,"serverComponents":false,"reactCompiler":true,"optimizeGraph":false,"treeshaking":false,"logbox":false}}
+{"_e":"expo:dev-tools-plugin:load","_t":1786664384465,"plugins":[]}
+{"_e":"metro:instantiate","_t":1786664384918,"atlas":false,"workers":4,"host":"::","port":8081}
+{"_e":"metro:bundling:started","_t":1786664408833,"id":"1","platform":"android","environment":null,"entry":"node_modules/expo-router/entry.js"}
+{"_e":"metro:bundling:progress","_t":1786664408833,"id":"1","progress":0,"total":1,"current":0}
+{"_e":"metro:bundling:progress","_t":1786664408837,"id":"1","progress":0,"total":1,"current":0}
+{"_e":"metro:bundling:progress","_t":1786664409163,"id":"1","progress":0.010000000000000002,"total":1,"current":1}
+{"_e":"metro:bundling:progress","_t":1786664409265,"id":"1","progress":0.1322314049586777,"total":11,"current":4}
+{"_e":"metro:bundling:progress","_t":1786664409346,"id":"1","progress":0.20661157024793386,"total":11,"current":5}
+{"_e":"metro:bundling:progress","_t":1786664409448,"id":"1","progress":0.20661157024793386,"total":127,"current":9}
+{"_e":"metro:bundling:progress","_t":1786664409550,"id":"1","progress":0.20661157024793386,"total":141,"current":15}
+{"_e":"metro:bundling:progress","_t":1786664409650,"id":"1","progress":0.20661157024793386,"total":160,"current":38}
+{"_e":"metro:bundling:progress","_t":1786664409751,"id":"1","progress":0.20661157024793386,"total":174,"current":49}
+{"_e":"metro:bundling:progress","_t":1786664409851,"id":"1","progress":0.20661157024793386,"total":213,"current":77}
+{"_e":"metro:bundling:progress","_t":1786664409952,"id":"1","progress":0.20661157024793386,"total":269,"current":114}
+{"_e":"metro:bundling:progress","_t":1786664410054,"id":"1","progress":0.20786947644607867,"total":329,"current":150}
+{"_e":"metro:bundling:progress","_t":1786664410154,"id":"1","progress":0.26234384295062463,"total":369,"current":189}
+{"_e":"metro:bundling:progress","_t":1786664410255,"id":"1","progress":0.30978350729909493,"total":433,"current":241}
+{"_e":"metro:bundling:progress","_t":1786664410355,"id":"1","progress":0.3770390889504463,"total":456,"current":280}
+{"_e":"metro:bundling:progress","_t":1786664410455,"id":"1","progress":0.38727919099633445,"total":466,"current":290}
+{"_e":"metro:bundling:progress","_t":1786664410557,"id":"1","progress":0.38727919099633445,"total":516,"current":312}
+{"_e":"metro:bundling:progress","_t":1786664410659,"id":"1","progress":0.3895017079861291,"total":556,"current":347}
+{"_e":"metro:bundling:progress","_t":1786664410758,"id":"1","progress":0.4587420149891857,"total":564,"current":382}
+{"_e":"metro:bundling:progress","_t":1786664410860,"id":"1","progress":0.5694541345950145,"total":595,"current":449}
+{"_e":"metro:bundling:progress","_t":1786664410960,"id":"1","progress":0.5694541345950145,"total":635,"current":472}
+{"_e":"metro:bundling:progress","_t":1786664411060,"id":"1","progress":0.5694541345950145,"total":673,"current":499}
+{"_e":"metro:bundling:progress","_t":1786664411160,"id":"1","progress":0.5694541345950145,"total":734,"current":537}
+{"_e":"metro:bundling:progress","_t":1786664411261,"id":"1","progress":0.5694541345950145,"total":763,"current":572}
+{"_e":"metro:bundling:progress","_t":1786664411362,"id":"1","progress":0.5873356140208807,"total":809,"current":620}
+{"_e":"metro:bundling:progress","_t":1786664411463,"id":"1","progress":0.5873356140208807,"total":825,"current":630}
+{"_e":"metro:bundling:progress","_t":1786664411564,"id":"1","progress":0.5873356140208807,"total":873,"current":663}
+{"_e":"metro:bundling:progress","_t":1786664411665,"id":"1","progress":0.5873356140208807,"total":896,"current":685}
+{"_e":"metro:bundling:progress","_t":1786664411765,"id":"1","progress":0.5873356140208807,"total":950,"current":718}
+{"_e":"metro:bundling:progress","_t":1786664411866,"id":"1","progress":0.5873356140208807,"total":978,"current":745}
+{"_e":"metro:bundling:progress","_t":1786664411970,"id":"1","progress":0.5992252141094498,"total":996,"current":771}
+{"_e":"metro:bundling:progress","_t":1786664412072,"id":"1","progress":0.6141503970360315,"total":1017,"current":797}
+{"_e":"metro:bundling:progress","_t":1786664412171,"id":"1","progress":0.6362518382194855,"total":1023,"current":816}
+{"_e":"metro:bundling:progress","_t":1786664412293,"id":"1","progress":0.6531535588762611,"total":1027,"current":830}
+{"_e":"metro:bundling:progress","_t":1786664412393,"id":"1","progress":0.6531535588762611,"total":1091,"current":853}
+{"_e":"metro:bundling:progress","_t":1786664412493,"id":"1","progress":0.6534394873457454,"total":1101,"current":890}
+{"_e":"metro:bundling:progress","_t":1786664412593,"id":"1","progress":0.6976985727375618,"total":1111,"current":928}
+{"_e":"metro:bundling:progress","_t":1786664412694,"id":"1","progress":0.7246341902082449,"total":1116,"current":950}
+{"_e":"metro:bundling:progress","_t":1786664412795,"id":"1","progress":0.7457295489486213,"total":1136,"current":981}
+{"_e":"metro:bundling:progress","_t":1786664412896,"id":"1","progress":0.7680848377730085,"total":1157,"current":1014}
+{"_e":"metro:bundling:progress","_t":1786664412998,"id":"1","progress":0.7751167051907102,"total":1179,"current":1038}
+{"_e":"metro:bundling:progress","_t":1786664413098,"id":"1","progress":0.7751167051907102,"total":1198,"current":1048}
+{"_e":"metro:bundling:progress","_t":1786664413198,"id":"1","progress":0.7751167051907102,"total":1223,"current":1057}
+{"_e":"metro:bundling:progress","_t":1786664413306,"id":"1","progress":0.7751167051907102,"total":1224,"current":1060}
+{"_e":"metro:bundling:progress","_t":1786664413405,"id":"1","progress":0.7751167051907102,"total":1271,"current":1095}
+{"_e":"metro:bundling:progress","_t":1786664413506,"id":"1","progress":0.7816979845156236,"total":1286,"current":1137}
+{"_e":"metro:bundling:progress","_t":1786664413606,"id":"1","progress":0.8322312266116275,"total":1288,"current":1175}
+{"_e":"metro:bundling:progress","_t":1786664413706,"id":"1","progress":0.843456297584273,"total":1299,"current":1193}
+{"_e":"metro:bundling:progress","_t":1786664413806,"id":"1","progress":0.845954335743401,"total":1321,"current":1215}
+{"_e":"metro:bundling:progress","_t":1786664413907,"id":"1","progress":0.845954335743401,"total":1344,"current":1236}
+{"_e":"metro:bundling:progress","_t":1786664414006,"id":"1","progress":0.845954335743401,"total":1386,"current":1264}
+{"_e":"metro:bundling:progress","_t":1786664414107,"id":"1","progress":0.845954335743401,"total":1416,"current":1301}
+{"_e":"metro:bundling:progress","_t":1786664414221,"id":"1","progress":0.8498936954496207,"total":1434,"current":1322}
+{"_e":"metro:bundling:progress","_t":1786664414342,"id":"1","progress":0.8576258196537953,"total":1434,"current":1328}
+{"_e":"metro:bundling:progress","_t":1786664414448,"id":"1","progress":0.8692896560712251,"total":1434,"current":1337}
+{"_e":"metro:bundling:progress","_t":1786664414548,"id":"1","progress":0.8855058148858574,"total":1441,"current":1356}
+{"_e":"metro:bundling:progress","_t":1786664414648,"id":"1","progress":0.9034025321769098,"total":1474,"current":1401}
+{"_e":"metro:bundling:progress","_t":1786664414748,"id":"1","progress":0.9230044615496745,"total":1477,"current":1419}
+{"_e":"metro:bundling:progress","_t":1786664414848,"id":"1","progress":0.9385569717588258,"total":1506,"current":1459}
+{"_e":"metro:bundling:progress","_t":1786664414948,"id":"1","progress":0.9385569717588258,"total":1586,"current":1495}
+{"_e":"metro:bundling:progress","_t":1786664415049,"id":"1","progress":0.9385569717588258,"total":1654,"current":1550}
+{"_e":"metro:bundling:progress","_t":1786664415149,"id":"1","progress":0.9385569717588258,"total":1686,"current":1606}
+{"_e":"metro:bundling:progress","_t":1786664415249,"id":"1","progress":0.9385569717588258,"total":1717,"current":1659}
+{"_e":"metro:bundling:progress","_t":1786664415349,"id":"1","progress":0.9524686765626291,"total":1746,"current":1704}
+{"_e":"metro:bundling:progress","_t":1786664415450,"id":"1","progress":0.9852984754451719,"total":1762,"current":1749}
+{"_e":"metro:bundling:progress","_t":1786664415555,"id":"1","progress":0.999,"total":1764,"current":1764}
+{"_e":"metro:bundling:done","_t":1786664415732,"id":"1","total":1764,"ms":6898.292666}
+{"_e":"metro:bundling:started","_t":1786664592238,"id":"7","platform":"android","environment":null,"entry":"node_modules/expo-router/entry.js"}
+{"_e":"metro:bundling:progress","_t":1786664592239,"id":"7","progress":0,"total":1,"current":0}
+{"_e":"metro:bundling:progress","_t":1786664592244,"id":"7","progress":0,"total":1,"current":0}
+{"_e":"metro:bundling:progress","_t":1786664592344,"id":"7","progress":0,"total":1,"current":0}
+{"_e":"metro:bundling:progress","_t":1786664592442,"id":"7","progress":0,"total":1,"current":0}
+{"_e":"metro:bundling:progress","_t":1786664592542,"id":"7","progress":0,"total":1,"current":0}
+{"_e":"metro:bundling:done","_t":1786664592659,"id":"7","total":1,"ms":420.139083}
+{"_e":"metro:bundling:started","_t":1786664597650,"id":"8","platform":"android","environment":null,"entry":"node_modules/expo-router/entry.js"}
+{"_e":"metro:bundling:progress","_t":1786664597650,"id":"8","progress":0,"total":1,"current":0}
+{"_e":"metro:bundling:done","_t":1786664597704,"id":"8","total":1,"ms":53.752208}
+{"_e":"metro:client_log","_t":1786667131853,"level":"error","data":["[Error: Cannot find native module 'ExpoSecureStore']","\n\n\u001b[1mCode: AuthContext.tsx\u001b[22m\n\u001b[0m \u001b[90m 1 |\u001b[39m \u001b[36mimport\u001b[39m { \u001b[33mUser\u001b[39m } \u001b[36mfrom\u001b[39m \u001b[32m'@/types'\u001b[39m\u001b[33m;\u001b[39m\n \u001b[90m 2 |\u001b[39m \u001b[36mimport\u001b[39m \u001b[33mReact\u001b[39m\u001b[33m,\u001b[39m { createContext\u001b[33m,\u001b[39m useContext\u001b[33m,\u001b[39m useEffect\u001b[33m,\u001b[39m useState } \u001b[36mfrom\u001b[39m \u001b[32m'react'\u001b[39m\u001b[33m;\u001b[39m\n\u001b[31m\u001b[1m>\u001b[22m\u001b[39m\u001b[90m 3 |\u001b[39m \u001b[36mimport\u001b[39m \u001b[33m*\u001b[39m \u001b[36mas\u001b[39m \u001b[33mSecureStore\u001b[39m \u001b[36mfrom\u001b[39m \u001b[32m'expo-secure-store'\u001b[39m\u001b[33m;\u001b[39m\n \u001b[90m |\u001b[39m \u001b[31m\u001b[1m^\u001b[22m\u001b[39m\n \u001b[90m 4 |\u001b[39m \u001b[36mimport\u001b[39m \u001b[33m*\u001b[39m \u001b[36mas\u001b[39m \u001b[33mLocalAuthentication\u001b[39m \u001b[36mfrom\u001b[39m \u001b[32m'expo-local-authentication'\u001b[39m\u001b[33m;\u001b[39m\n \u001b[90m 5 |\u001b[39m \u001b[36mimport\u001b[39m { setApiToken } \u001b[36mfrom\u001b[39m \u001b[32m'@/services/api'\u001b[39m\u001b[33m;\u001b[39m\n \u001b[90m 6 |\u001b[39m\u001b[0m\n\u001b[1mCall Stack\u001b[22m\n\u001b[90m <global> (src/contexts/AuthContext.tsx:3)\u001b[39m\n\u001b[90m <global> (src/app/_layout.tsx:1)\u001b[39m"]}
+{"_e":"metro:bundling:started","_t":1786667163530,"id":"d","platform":"android","environment":null,"entry":"node_modules/expo-router/entry.js"}
+{"_e":"metro:bundling:progress","_t":1786667163530,"id":"d","progress":0,"total":1,"current":0}
+{"_e":"metro:bundling:done","_t":1786667163582,"id":"d","total":1,"ms":52.1765}
+{"_e":"metro:client_log","_t":1786667165117,"level":"warn","data":["Route \"./_layout.tsx\" is missing the required default export. Ensure a React component is exported as default."]}
+{"_e":"metro:client_log","_t":1786667165121,"level":"warn","data":["Route \"./_layout.tsx\" is missing the required default export. Ensure a React component is exported as default."]}
+{"_e":"metro:client_log","_t":1786667165132,"level":"error","data":["[Error: Cannot find native module 'ExpoSecureStore']","\n\n\u001b[1mCode: AuthContext.tsx\u001b[22m\n\u001b[0m \u001b[90m 1 |\u001b[39m \u001b[36mimport\u001b[39m { \u001b[33mUser\u001b[39m } \u001b[36mfrom\u001b[39m \u001b[32m'@/types'\u001b[39m\u001b[33m;\u001b[39m\n \u001b[90m 2 |\u001b[39m \u001b[36mimport\u001b[39m \u001b[33mReact\u001b[39m\u001b[33m,\u001b[39m { createContext\u001b[33m,\u001b[39m useContext\u001b[33m,\u001b[39m useEffect\u001b[33m,\u001b[39m useState } \u001b[36mfrom\u001b[39m \u001b[32m'react'\u001b[39m\u001b[33m;\u001b[39m\n\u001b[31m\u001b[1m>\u001b[22m\u001b[39m\u001b[90m 3 |\u001b[39m \u001b[36mimport\u001b[39m \u001b[33m*\u001b[39m \u001b[36mas\u001b[39m \u001b[33mSecureStore\u001b[39m \u001b[36mfrom\u001b[39m \u001b[32m'expo-secure-store'\u001b[39m\u001b[33m;\u001b[39m\n \u001b[90m |\u001b[39m \u001b[31m\u001b[1m^\u001b[22m\u001b[39m\n \u001b[90m 4 |\u001b[39m \u001b[36mimport\u001b[39m \u001b[33m*\u001b[39m \u001b[36mas\u001b[39m \u001b[33mLocalAuthentication\u001b[39m \u001b[36mfrom\u001b[39m \u001b[32m'expo-local-authentication'\u001b[39m\u001b[33m;\u001b[39m\n \u001b[90m 5 |\u001b[39m \u001b[36mimport\u001b[39m { setApiToken } \u001b[36mfrom\u001b[39m \u001b[32m'@/services/api'\u001b[39m\u001b[33m;\u001b[39m\n \u001b[90m 6 |\u001b[39m\u001b[0m\n\u001b[1mCall Stack\u001b[22m\n\u001b[90m <global> (src/contexts/AuthContext.tsx:3)\u001b[39m\n\u001b[90m <global> (src/app/_layout.tsx:1)\u001b[39m","\n\n\u001b[1mCode: ExpoRoot.js\u001b[22m\n\u001b[0m \u001b[90m 83 |\u001b[39m initialMetrics\u001b[33m:\u001b[39m \u001b[33mINITIAL_METRICS\u001b[39m\u001b[33m,\u001b[39m children\u001b[33m:\u001b[39m children }) }) }))\u001b[33m;\u001b[39m\n \u001b[90m 84 |\u001b[39m }\u001b[33m,\u001b[39m [\u001b[33mParentWrapper\u001b[39m])\u001b[33m;\u001b[39m\n\u001b[31m\u001b[1m>\u001b[22m\u001b[39m\u001b[90m 85 |\u001b[39m \u001b[36mreturn\u001b[39m (\u001b[35m0\u001b[39m\u001b[33m,\u001b[39m jsx_runtime_1\u001b[33m.\u001b[39mjsx)(\u001b[33mContextNavigator\u001b[39m\u001b[33m,\u001b[39m { \u001b[33m...\u001b[39mprops\u001b[33m,\u001b[39m wrapper\u001b[33m:\u001b[39m wrapper })\u001b[33m;\u001b[39m\n \u001b[90m |\u001b[39m \u001b[31m\u001b[1m^\u001b[22m\u001b[39m\n \u001b[90m 86 |\u001b[39m }\n \u001b[90m 87 |\u001b[39m \u001b[36mconst\u001b[39m initialUrl \u001b[33m=\u001b[39m react_native_1\u001b[33m.\u001b[39m\u001b[33mPlatform\u001b[39m\u001b[33m.\u001b[39m\u001b[33mOS\u001b[39m \u001b[33m===\u001b[39m \u001b[32m'web'\u001b[39m \u001b[33m&&\u001b[39m \u001b[36mtypeof\u001b[39m window \u001b[33m!==\u001b[39m \u001b[32m'undefined'\u001b[39m\n \u001b[90m 88 |\u001b[39m \u001b[33m?\u001b[39m \u001b[36mnew\u001b[39m \u001b[33mURL\u001b[39m(window\u001b[33m.\u001b[39mlocation\u001b[33m.\u001b[39mhref)\u001b[0m\n\u001b[1mCall Stack\u001b[22m\n\u001b[2m\u001b[90m ExpoRoot (node_modules/expo-router/build/ExpoRoot.js:85:33)\u001b[39m\u001b[22m\n\u001b[2m\u001b[90m App (node_modules/expo-router/build/qualified-entry.js:20:91)\u001b[39m\u001b[22m\n\u001b[2m\u001b[90m WithDevTools (node_modules/expo/src/launch/withDevTools.tsx:21:12)\u001b[39m\u001b[22m"]}
+{"_e":"metro:client_log","_t":1786667165155,"level":"error","data":["[Error: Cannot find native module 'ExpoSecureStore']","\n\n\u001b[1mCode: AuthContext.tsx\u001b[22m\n\u001b[0m \u001b[90m 1 |\u001b[39m \u001b[36mimport\u001b[39m { \u001b[33mUser\u001b[39m } \u001b[36mfrom\u001b[39m \u001b[32m'@/types'\u001b[39m\u001b[33m;\u001b[39m\n \u001b[90m 2 |\u001b[39m \u001b[36mimport\u001b[39m \u001b[33mReact\u001b[39m\u001b[33m,\u001b[39m { createContext\u001b[33m,\u001b[39m useContext\u001b[33m,\u001b[39m useEffect\u001b[33m,\u001b[39m useState } \u001b[36mfrom\u001b[39m \u001b[32m'react'\u001b[39m\u001b[33m;\u001b[39m\n\u001b[31m\u001b[1m>\u001b[22m\u001b[39m\u001b[90m 3 |\u001b[39m \u001b[36mimport\u001b[39m \u001b[33m*\u001b[39m \u001b[36mas\u001b[39m \u001b[33mSecureStore\u001b[39m \u001b[36mfrom\u001b[39m \u001b[32m'expo-secure-store'\u001b[39m\u001b[33m;\u001b[39m\n \u001b[90m |\u001b[39m \u001b[31m\u001b[1m^\u001b[22m\u001b[39m\n \u001b[90m 4 |\u001b[39m \u001b[36mimport\u001b[39m \u001b[33m*\u001b[39m \u001b[36mas\u001b[39m \u001b[33mLocalAuthentication\u001b[39m \u001b[36mfrom\u001b[39m \u001b[32m'expo-local-authentication'\u001b[39m\u001b[33m;\u001b[39m\n \u001b[90m 5 |\u001b[39m \u001b[36mimport\u001b[39m { setApiToken } \u001b[36mfrom\u001b[39m \u001b[32m'@/services/api'\u001b[39m\u001b[33m;\u001b[39m\n \u001b[90m 6 |\u001b[39m\u001b[0m\n\u001b[1mCall Stack\u001b[22m\n\u001b[90m <global> (src/contexts/AuthContext.tsx:3)\u001b[39m\n\u001b[90m <global> (src/app/_layout.tsx:1)\u001b[39m","\n\n\u001b[1mCode: ExpoRoot.js\u001b[22m\n\u001b[0m \u001b[90m 83 |\u001b[39m initialMetrics\u001b[33m:\u001b[39m \u001b[33mINITIAL_METRICS\u001b[39m\u001b[33m,\u001b[39m children\u001b[33m:\u001b[39m children }) }) }))\u001b[33m;\u001b[39m\n \u001b[90m 84 |\u001b[39m }\u001b[33m,\u001b[39m [\u001b[33mParentWrapper\u001b[39m])\u001b[33m;\u001b[39m\n\u001b[31m\u001b[1m>\u001b[22m\u001b[39m\u001b[90m 85 |\u001b[39m \u001b[36mreturn\u001b[39m (\u001b[35m0\u001b[39m\u001b[33m,\u001b[39m jsx_runtime_1\u001b[33m.\u001b[39mjsx)(\u001b[33mContextNavigator\u001b[39m\u001b[33m,\u001b[39m { \u001b[33m...\u001b[39mprops\u001b[33m,\u001b[39m wrapper\u001b[33m:\u001b[39m wrapper })\u001b[33m;\u001b[39m\n \u001b[90m |\u001b[39m \u001b[31m\u001b[1m^\u001b[22m\u001b[39m\n \u001b[90m 86 |\u001b[39m }\n \u001b[90m 87 |\u001b[39m \u001b[36mconst\u001b[39m initialUrl \u001b[33m=\u001b[39m react_native_1\u001b[33m.\u001b[39m\u001b[33mPlatform\u001b[39m\u001b[33m.\u001b[39m\u001b[33mOS\u001b[39m \u001b[33m===\u001b[39m \u001b[32m'web'\u001b[39m \u001b[33m&&\u001b[39m \u001b[36mtypeof\u001b[39m window \u001b[33m!==\u001b[39m \u001b[32m'undefined'\u001b[39m\n \u001b[90m 88 |\u001b[39m \u001b[33m?\u001b[39m \u001b[36mnew\u001b[39m \u001b[33mURL\u001b[39m(window\u001b[33m.\u001b[39mlocation\u001b[33m.\u001b[39mhref)\u001b[0m\n\u001b[1mCall Stack\u001b[22m\n\u001b[2m\u001b[90m ExpoRoot (node_modules/expo-router/build/ExpoRoot.js:85:33)\u001b[39m\u001b[22m\n\u001b[2m\u001b[90m App (node_modules/expo-router/build/qualified-entry.js:20:91)\u001b[39m\u001b[22m\n\u001b[2m\u001b[90m WithDevTools (node_modules/expo/src/launch/withDevTools.tsx:21:12)\u001b[39m\u001b[22m"]}
+{"_e":"metro:client_log","_t":1786667165161,"level":"error","data":["[Error: Cannot find native module 'ExpoSecureStore']","\n\n\u001b[1mCode: AuthContext.tsx\u001b[22m\n\u001b[0m \u001b[90m 1 |\u001b[39m \u001b[36mimport\u001b[39m { \u001b[33mUser\u001b[39m } \u001b[36mfrom\u001b[39m \u001b[32m'@/types'\u001b[39m\u001b[33m;\u001b[39m\n \u001b[90m 2 |\u001b[39m \u001b[36mimport\u001b[39m \u001b[33mReact\u001b[39m\u001b[33m,\u001b[39m { createContext\u001b[33m,\u001b[39m useContext\u001b[33m,\u001b[39m useEffect\u001b[33m,\u001b[39m useState } \u001b[36mfrom\u001b[39m \u001b[32m'react'\u001b[39m\u001b[33m;\u001b[39m\n\u001b[31m\u001b[1m>\u001b[22m\u001b[39m\u001b[90m 3 |\u001b[39m \u001b[36mimport\u001b[39m \u001b[33m*\u001b[39m \u001b[36mas\u001b[39m \u001b[33mSecureStore\u001b[39m \u001b[36mfrom\u001b[39m \u001b[32m'expo-secure-store'\u001b[39m\u001b[33m;\u001b[39m\n \u001b[90m |\u001b[39m \u001b[31m\u001b[1m^\u001b[22m\u001b[39m\n \u001b[90m 4 |\u001b[39m \u001b[36mimport\u001b[39m \u001b[33m*\u001b[39m \u001b[36mas\u001b[39m \u001b[33mLocalAuthentication\u001b[39m \u001b[36mfrom\u001b[39m \u001b[32m'expo-local-authentication'\u001b[39m\u001b[33m;\u001b[39m\n \u001b[90m 5 |\u001b[39m \u001b[36mimport\u001b[39m { setApiToken } \u001b[36mfrom\u001b[39m \u001b[32m'@/services/api'\u001b[39m\u001b[33m;\u001b[39m\n \u001b[90m 6 |\u001b[39m\u001b[0m\n\u001b[1mCall Stack\u001b[22m\n\u001b[90m <global> (src/contexts/AuthContext.tsx:3)\u001b[39m\n\u001b[90m <global> (src/app/_layout.tsx:1)\u001b[39m","\n\n\u001b[1mCode: ExpoRoot.js\u001b[22m\n\u001b[0m \u001b[90m 83 |\u001b[39m initialMetrics\u001b[33m:\u001b[39m \u001b[33mINITIAL_METRICS\u001b[39m\u001b[33m,\u001b[39m children\u001b[33m:\u001b[39m children }) }) }))\u001b[33m;\u001b[39m\n \u001b[90m 84 |\u001b[39m }\u001b[33m,\u001b[39m [\u001b[33mParentWrapper\u001b[39m])\u001b[33m;\u001b[39m\n\u001b[31m\u001b[1m>\u001b[22m\u001b[39m\u001b[90m 85 |\u001b[39m \u001b[36mreturn\u001b[39m (\u001b[35m0\u001b[39m\u001b[33m,\u001b[39m jsx_runtime_1\u001b[33m.\u001b[39mjsx)(\u001b[33mContextNavigator\u001b[39m\u001b[33m,\u001b[39m { \u001b[33m...\u001b[39mprops\u001b[33m,\u001b[39m wrapper\u001b[33m:\u001b[39m wrapper })\u001b[33m;\u001b[39m\n \u001b[90m |\u001b[39m \u001b[31m\u001b[1m^\u001b[22m\u001b[39m\n \u001b[90m 86 |\u001b[39m }\n \u001b[90m 87 |\u001b[39m \u001b[36mconst\u001b[39m initialUrl \u001b[33m=\u001b[39m react_native_1\u001b[33m.\u001b[39m\u001b[33mPlatform\u001b[39m\u001b[33m.\u001b[39m\u001b[33mOS\u001b[39m \u001b[33m===\u001b[39m \u001b[32m'web'\u001b[39m \u001b[33m&&\u001b[39m \u001b[36mtypeof\u001b[39m window \u001b[33m!==\u001b[39m \u001b[32m'undefined'\u001b[39m\n \u001b[90m 88 |\u001b[39m \u001b[33m?\u001b[39m \u001b[36mnew\u001b[39m \u001b[33mURL\u001b[39m(window\u001b[33m.\u001b[39mlocation\u001b[33m.\u001b[39mhref)\u001b[0m\n\u001b[1mCall Stack\u001b[22m\n\u001b[2m\u001b[90m ExpoRoot (node_modules/expo-router/build/ExpoRoot.js:85:33)\u001b[39m\u001b[22m\n\u001b[2m\u001b[90m App (node_modules/expo-router/build/qualified-entry.js:20:91)\u001b[39m\u001b[22m\n\u001b[2m\u001b[90m WithDevTools (node_modules/expo/src/launch/withDevTools.tsx:21:12)\u001b[39m\u001b[22m"]}
+{"_e":"metro:client_log","_t":1786667165164,"level":"error","data":["[Error: Cannot find native module 'ExpoSecureStore']","\n\n\u001b[1mCode: AuthContext.tsx\u001b[22m\n\u001b[0m \u001b[90m 1 |\u001b[39m \u001b[36mimport\u001b[39m { \u001b[33mUser\u001b[39m } \u001b[36mfrom\u001b[39m \u001b[32m'@/types'\u001b[39m\u001b[33m;\u001b[39m\n \u001b[90m 2 |\u001b[39m \u001b[36mimport\u001b[39m \u001b[33mReact\u001b[39m\u001b[33m,\u001b[39m { createContext\u001b[33m,\u001b[39m useContext\u001b[33m,\u001b[39m useEffect\u001b[33m,\u001b[39m useState } \u001b[36mfrom\u001b[39m \u001b[32m'react'\u001b[39m\u001b[33m;\u001b[39m\n\u001b[31m\u001b[1m>\u001b[22m\u001b[39m\u001b[90m 3 |\u001b[39m \u001b[36mimport\u001b[39m \u001b[33m*\u001b[39m \u001b[36mas\u001b[39m \u001b[33mSecureStore\u001b[39m \u001b[36mfrom\u001b[39m \u001b[32m'expo-secure-store'\u001b[39m\u001b[33m;\u001b[39m\n \u001b[90m |\u001b[39m \u001b[31m\u001b[1m^\u001b[22m\u001b[39m\n \u001b[90m 4 |\u001b[39m \u001b[36mimport\u001b[39m \u001b[33m*\u001b[39m \u001b[36mas\u001b[39m \u001b[33mLocalAuthentication\u001b[39m \u001b[36mfrom\u001b[39m \u001b[32m'expo-local-authentication'\u001b[39m\u001b[33m;\u001b[39m\n \u001b[90m 5 |\u001b[39m \u001b[36mimport\u001b[39m { setApiToken } \u001b[36mfrom\u001b[39m \u001b[32m'@/services/api'\u001b[39m\u001b[33m;\u001b[39m\n \u001b[90m 6 |\u001b[39m\u001b[0m\n\u001b[1mCall Stack\u001b[22m\n\u001b[90m <global> (src/contexts/AuthContext.tsx:3)\u001b[39m\n\u001b[90m <global> (src/app/_layout.tsx:1)\u001b[39m","\n\n\u001b[1mCode: ExpoRoot.js\u001b[22m\n\u001b[0m \u001b[90m 83 |\u001b[39m initialMetrics\u001b[33m:\u001b[39m \u001b[33mINITIAL_METRICS\u001b[39m\u001b[33m,\u001b[39m children\u001b[33m:\u001b[39m children }) }) }))\u001b[33m;\u001b[39m\n \u001b[90m 84 |\u001b[39m }\u001b[33m,\u001b[39m [\u001b[33mParentWrapper\u001b[39m])\u001b[33m;\u001b[39m\n\u001b[31m\u001b[1m>\u001b[22m\u001b[39m\u001b[90m 85 |\u001b[39m \u001b[36mreturn\u001b[39m (\u001b[35m0\u001b[39m\u001b[33m,\u001b[39m jsx_runtime_1\u001b[33m.\u001b[39mjsx)(\u001b[33mContextNavigator\u001b[39m\u001b[33m,\u001b[39m { \u001b[33m...\u001b[39mprops\u001b[33m,\u001b[39m wrapper\u001b[33m:\u001b[39m wrapper })\u001b[33m;\u001b[39m\n \u001b[90m |\u001b[39m \u001b[31m\u001b[1m^\u001b[22m\u001b[39m\n \u001b[90m 86 |\u001b[39m }\n \u001b[90m 87 |\u001b[39m \u001b[36mconst\u001b[39m initialUrl \u001b[33m=\u001b[39m react_native_1\u001b[33m.\u001b[39m\u001b[33mPlatform\u001b[39m\u001b[33m.\u001b[39m\u001b[33mOS\u001b[39m \u001b[33m===\u001b[39m \u001b[32m'web'\u001b[39m \u001b[33m&&\u001b[39m \u001b[36mtypeof\u001b[39m window \u001b[33m!==\u001b[39m \u001b[32m'undefined'\u001b[39m\n \u001b[90m 88 |\u001b[39m \u001b[33m?\u001b[39m \u001b[36mnew\u001b[39m \u001b[33mURL\u001b[39m(window\u001b[33m.\u001b[39mlocation\u001b[33m.\u001b[39mhref)\u001b[0m\n\u001b[1mCall Stack\u001b[22m\n\u001b[2m\u001b[90m ExpoRoot (node_modules/expo-router/build/ExpoRoot.js:85:33)\u001b[39m\u001b[22m\n\u001b[2m\u001b[90m App (node_modules/expo-router/build/qualified-entry.js:20:91)\u001b[39m\u001b[22m\n\u001b[2m\u001b[90m WithDevTools (node_modules/expo/src/launch/withDevTools.tsx:21:12)\u001b[39m\u001b[22m"]}
+{"_e":"metro:client_log","_t":1786667165167,"level":"error","data":["[Error: Cannot find native module 'ExpoSecureStore']","\n\n\u001b[1mCode: AuthContext.tsx\u001b[22m\n\u001b[0m \u001b[90m 1 |\u001b[39m \u001b[36mimport\u001b[39m { \u001b[33mUser\u001b[39m } \u001b[36mfrom\u001b[39m \u001b[32m'@/types'\u001b[39m\u001b[33m;\u001b[39m\n \u001b[90m 2 |\u001b[39m \u001b[36mimport\u001b[39m \u001b[33mReact\u001b[39m\u001b[33m,\u001b[39m { createContext\u001b[33m,\u001b[39m useContext\u001b[33m,\u001b[39m useEffect\u001b[33m,\u001b[39m useState } \u001b[36mfrom\u001b[39m \u001b[32m'react'\u001b[39m\u001b[33m;\u001b[39m\n\u001b[31m\u001b[1m>\u001b[22m\u001b[39m\u001b[90m 3 |\u001b[39m \u001b[36mimport\u001b[39m \u001b[33m*\u001b[39m \u001b[36mas\u001b[39m \u001b[33mSecureStore\u001b[39m \u001b[36mfrom\u001b[39m \u001b[32m'expo-secure-store'\u001b[39m\u001b[33m;\u001b[39m\n \u001b[90m |\u001b[39m \u001b[31m\u001b[1m^\u001b[22m\u001b[39m\n \u001b[90m 4 |\u001b[39m \u001b[36mimport\u001b[39m \u001b[33m*\u001b[39m \u001b[36mas\u001b[39m \u001b[33mLocalAuthentication\u001b[39m \u001b[36mfrom\u001b[39m \u001b[32m'expo-local-authentication'\u001b[39m\u001b[33m;\u001b[39m\n \u001b[90m 5 |\u001b[39m \u001b[36mimport\u001b[39m { setApiToken } \u001b[36mfrom\u001b[39m \u001b[32m'@/services/api'\u001b[39m\u001b[33m;\u001b[39m\n \u001b[90m 6 |\u001b[39m\u001b[0m\n\u001b[1mCall Stack\u001b[22m\n\u001b[90m <global> (src/contexts/AuthContext.tsx:3)\u001b[39m\n\u001b[90m <global> (src/app/_layout.tsx:1)\u001b[39m","\n\n\u001b[1mCode: ExpoRoot.js\u001b[22m\n\u001b[0m \u001b[90m 83 |\u001b[39m initialMetrics\u001b[33m:\u001b[39m \u001b[33mINITIAL_METRICS\u001b[39m\u001b[33m,\u001b[39m children\u001b[33m:\u001b[39m children }) }) }))\u001b[33m;\u001b[39m\n \u001b[90m 84 |\u001b[39m }\u001b[33m,\u001b[39m [\u001b[33mParentWrapper\u001b[39m])\u001b[33m;\u001b[39m\n\u001b[31m\u001b[1m>\u001b[22m\u001b[39m\u001b[90m 85 |\u001b[39m \u001b[36mreturn\u001b[39m (\u001b[35m0\u001b[39m\u001b[33m,\u001b[39m jsx_runtime_1\u001b[33m.\u001b[39mjsx)(\u001b[33mContextNavigator\u001b[39m\u001b[33m,\u001b[39m { \u001b[33m...\u001b[39mprops\u001b[33m,\u001b[39m wrapper\u001b[33m:\u001b[39m wrapper })\u001b[33m;\u001b[39m\n \u001b[90m |\u001b[39m \u001b[31m\u001b[1m^\u001b[22m\u001b[39m\n \u001b[90m 86 |\u001b[39m }\n \u001b[90m 87 |\u001b[39m \u001b[36mconst\u001b[39m initialUrl \u001b[33m=\u001b[39m react_native_1\u001b[33m.\u001b[39m\u001b[33mPlatform\u001b[39m\u001b[33m.\u001b[39m\u001b[33mOS\u001b[39m \u001b[33m===\u001b[39m \u001b[32m'web'\u001b[39m \u001b[33m&&\u001b[39m \u001b[36mtypeof\u001b[39m window \u001b[33m!==\u001b[39m \u001b[32m'undefined'\u001b[39m\n \u001b[90m 88 |\u001b[39m \u001b[33m?\u001b[39m \u001b[36mnew\u001b[39m \u001b[33mURL\u001b[39m(window\u001b[33m.\u001b[39mlocation\u001b[33m.\u001b[39mhref)\u001b[0m\n\u001b[1mCall Stack\u001b[22m\n\u001b[2m\u001b[90m ExpoRoot (node_modules/expo-router/build/ExpoRoot.js:85:33)\u001b[39m\u001b[22m\n\u001b[2m\u001b[90m App (node_modules/expo-router/build/qualified-entry.js:20:91)\u001b[39m\u001b[22m\n\u001b[2m\u001b[90m WithDevTools (node_modules/expo/src/launch/withDevTools.tsx:21:12)\u001b[39m\u001b[22m"]}
+{"_e":"metro:client_log","_t":1786667165171,"level":"error","data":["[Error: Cannot find native module 'ExpoSecureStore']","\n\n\u001b[1mCode: AuthContext.tsx\u001b[22m\n\u001b[0m \u001b[90m 1 |\u001b[39m \u001b[36mimport\u001b[39m { \u001b[33mUser\u001b[39m } \u001b[36mfrom\u001b[39m \u001b[32m'@/types'\u001b[39m\u001b[33m;\u001b[39m\n \u001b[90m 2 |\u001b[39m \u001b[36mimport\u001b[39m \u001b[33mReact\u001b[39m\u001b[33m,\u001b[39m { createContext\u001b[33m,\u001b[39m useContext\u001b[33m,\u001b[39m useEffect\u001b[33m,\u001b[39m useState } \u001b[36mfrom\u001b[39m \u001b[32m'react'\u001b[39m\u001b[33m;\u001b[39m\n\u001b[31m\u001b[1m>\u001b[22m\u001b[39m\u001b[90m 3 |\u001b[39m \u001b[36mimport\u001b[39m \u001b[33m*\u001b[39m \u001b[36mas\u001b[39m \u001b[33mSecureStore\u001b[39m \u001b[36mfrom\u001b[39m \u001b[32m'expo-secure-store'\u001b[39m\u001b[33m;\u001b[39m\n \u001b[90m |\u001b[39m \u001b[31m\u001b[1m^\u001b[22m\u001b[39m\n \u001b[90m 4 |\u001b[39m \u001b[36mimport\u001b[39m \u001b[33m*\u001b[39m \u001b[36mas\u001b[39m \u001b[33mLocalAuthentication\u001b[39m \u001b[36mfrom\u001b[39m \u001b[32m'expo-local-authentication'\u001b[39m\u001b[33m;\u001b[39m\n \u001b[90m 5 |\u001b[39m \u001b[36mimport\u001b[39m { setApiToken } \u001b[36mfrom\u001b[39m \u001b[32m'@/services/api'\u001b[39m\u001b[33m;\u001b[39m\n \u001b[90m 6 |\u001b[39m\u001b[0m\n\u001b[1mCall Stack\u001b[22m\n\u001b[90m <global> (src/contexts/AuthContext.tsx:3)\u001b[39m\n\u001b[90m <global> (src/app/_layout.tsx:1)\u001b[39m","\n\n\u001b[1mCode: ExpoRoot.js\u001b[22m\n\u001b[0m \u001b[90m 83 |\u001b[39m initialMetrics\u001b[33m:\u001b[39m \u001b[33mINITIAL_METRICS\u001b[39m\u001b[33m,\u001b[39m children\u001b[33m:\u001b[39m children }) }) }))\u001b[33m;\u001b[39m\n \u001b[90m 84 |\u001b[39m }\u001b[33m,\u001b[39m [\u001b[33mParentWrapper\u001b[39m])\u001b[33m;\u001b[39m\n\u001b[31m\u001b[1m>\u001b[22m\u001b[39m\u001b[90m 85 |\u001b[39m \u001b[36mreturn\u001b[39m (\u001b[35m0\u001b[39m\u001b[33m,\u001b[39m jsx_runtime_1\u001b[33m.\u001b[39mjsx)(\u001b[33mContextNavigator\u001b[39m\u001b[33m,\u001b[39m { \u001b[33m...\u001b[39mprops\u001b[33m,\u001b[39m wrapper\u001b[33m:\u001b[39m wrapper })\u001b[33m;\u001b[39m\n \u001b[90m |\u001b[39m \u001b[31m\u001b[1m^\u001b[22m\u001b[39m\n \u001b[90m 86 |\u001b[39m }\n \u001b[90m 87 |\u001b[39m \u001b[36mconst\u001b[39m initialUrl \u001b[33m=\u001b[39m react_native_1\u001b[33m.\u001b[39m\u001b[33mPlatform\u001b[39m\u001b[33m.\u001b[39m\u001b[33mOS\u001b[39m \u001b[33m===\u001b[39m \u001b[32m'web'\u001b[39m \u001b[33m&&\u001b[39m \u001b[36mtypeof\u001b[39m window \u001b[33m!==\u001b[39m \u001b[32m'undefined'\u001b[39m\n \u001b[90m 88 |\u001b[39m \u001b[33m?\u001b[39m \u001b[36mnew\u001b[39m \u001b[33mURL\u001b[39m(window\u001b[33m.\u001b[39mlocation\u001b[33m.\u001b[39mhref)\u001b[0m\n\u001b[1mCall Stack\u001b[22m\n\u001b[2m\u001b[90m ExpoRoot (node_modules/expo-router/build/ExpoRoot.js:85:33)\u001b[39m\u001b[22m\n\u001b[2m\u001b[90m App (node_modules/expo-router/build/qualified-entry.js:20:91)\u001b[39m\u001b[22m\n\u001b[2m\u001b[90m WithDevTools (node_modules/expo/src/launch/withDevTools.tsx:21:12)\u001b[39m\u001b[22m"]}
+{"_e":"metro:client_log","_t":1786667165173,"level":"error","data":["[TypeError: Cannot read property 'ErrorBoundary' of undefined]","\n\n\u001b[1mCode: useScreens.js\u001b[22m\n\u001b[0m \u001b[90m 139 |\u001b[39m })\u001b[33m,\u001b[39m [sorted\u001b[33m,\u001b[39m protectedScreens])\u001b[33m;\u001b[39m\n \u001b[90m 140 |\u001b[39m }\n\u001b[31m\u001b[1m>\u001b[22m\u001b[39m\u001b[90m 141 |\u001b[39m \u001b[36mfunction\u001b[39m fromImport(value\u001b[33m,\u001b[39m { \u001b[33mErrorBoundary\u001b[39m\u001b[33m,\u001b[39m \u001b[33mSuspenseFallback\u001b[39m\u001b[33m,\u001b[39m \u001b[33m...\u001b[39mcomponent }) {\n \u001b[90m |\u001b[39m \u001b[31m\u001b[1m^\u001b[22m\u001b[39m\n \u001b[90m 142 |\u001b[39m \u001b[90m// If possible, add a more helpful display name for the component stack to improve debugging of React errors such as `Text strings must be rendered within a <Text> component.`.\u001b[39m\n \u001b[90m 143 |\u001b[39m \u001b[36mif\u001b[39m (component\u001b[33m?\u001b[39m\u001b[33m.\u001b[39m\u001b[36mdefault\u001b[39m \u001b[33m&&\u001b[39m __DEV__) {\n \u001b[90m 144 |\u001b[39m component\u001b[33m.\u001b[39m\u001b[36mdefault\u001b[39m\u001b[33m.\u001b[39mdisplayName \u001b[33m?\u001b[39m\u001b[33m?\u001b[39m\u001b[33m=\u001b[39m \u001b[32m`${component.default.name ?? 'Route'}(${value.contextKey})`\u001b[39m\u001b[33m;\u001b[39m\u001b[0m\n\u001b[1mCall Stack\u001b[22m\n\u001b[2m\u001b[90m fromImport (node_modules/expo-router/build/useScreens.js:141)\u001b[39m\u001b[22m\n\u001b[2m\u001b[90m getQualifiedRouteComponent (node_modules/expo-router/build/useScreens.js:206:34)\u001b[39m\u001b[22m\n\u001b[2m\u001b[90m useStore (node_modules/expo-router/build/global-state/useStore.js:55:68)\u001b[39m\u001b[22m\n\u001b[2m\u001b[90m ContextNavigator (node_modules/expo-router/build/ExpoRoot.js:122:46)\u001b[39m\u001b[22m\n\u001b[2m\u001b[90m callComponent.react_stack_bottom_frame (node_modules/react-native/Libraries/Renderer/implementations/ReactFabric-dev.js:17130:29)\u001b[39m\u001b[22m\n\u001b[2m\u001b[90m renderWithHooks (node_modules/react-native/Libraries/Renderer/implementations/ReactFabric-dev.js:5648:40)\u001b[39m\u001b[22m\n\u001b[2m\u001b[90m updateFunctionComponent (node_modules/react-native/Libraries/Renderer/implementations/ReactFabric-dev.js:8081:34)\u001b[39m\u001b[22m\n\u001b[2m\u001b[90m beginWork (node_modules/react-native/Libraries/Renderer/implementations/ReactFabric-dev.js:9340:41)\u001b[39m\u001b[22m\n\u001b[2m\u001b[90m run (<native>)\u001b[39m\u001b[22m\n\u001b[2m\u001b[90m runWithFiberInDEV (node_modules/react-native/Libraries/Renderer/implementations/ReactFabric-dev.js:697:33)\u001b[39m\u001b[22m\n\u001b[2m\u001b[90m performUnitOfWork (node_modules/react-native/Libraries/Renderer/implementations/ReactFabric-dev.js:14134:39)\u001b[39m\u001b[22m\n\u001b[2m\u001b[90m workLoopSync (node_modules/react-native/Libraries/Renderer/implementations/ReactFabric-dev.js:13966:58)\u001b[39m\u001b[22m\n\u001b[2m\u001b[90m renderRootSync (node_modules/react-native/Libraries/Renderer/implementations/ReactFabric-dev.js:13947:23)\u001b[39m\u001b[22m\n\u001b[2m\u001b[90m performWorkOnRoot (node_modules/react-native/Libraries/Renderer/implementations/ReactFabric-dev.js:13160:43)\u001b[39m\u001b[22m\n\u001b[2m\u001b[90m performWorkOnRootViaSchedulerTask (node_modules/react-native/Libraries/Renderer/implementations/ReactFabric-dev.js:3673:24)\u001b[39m\u001b[22m","\n\n\u001b[1mCode: ExpoRoot.js\u001b[22m\n\u001b[0m \u001b[90m 83 |\u001b[39m initialMetrics\u001b[33m:\u001b[39m \u001b[33mINITIAL_METRICS\u001b[39m\u001b[33m,\u001b[39m children\u001b[33m:\u001b[39m children }) }) }))\u001b[33m;\u001b[39m\n \u001b[90m 84 |\u001b[39m }\u001b[33m,\u001b[39m [\u001b[33mParentWrapper\u001b[39m])\u001b[33m;\u001b[39m\n\u001b[31m\u001b[1m>\u001b[22m\u001b[39m\u001b[90m 85 |\u001b[39m \u001b[36mreturn\u001b[39m (\u001b[35m0\u001b[39m\u001b[33m,\u001b[39m jsx_runtime_1\u001b[33m.\u001b[39mjsx)(\u001b[33mContextNavigator\u001b[39m\u001b[33m,\u001b[39m { \u001b[33m...\u001b[39mprops\u001b[33m,\u001b[39m wrapper\u001b[33m:\u001b[39m wrapper })\u001b[33m;\u001b[39m\n \u001b[90m |\u001b[39m \u001b[31m\u001b[1m^\u001b[22m\u001b[39m\n \u001b[90m 86 |\u001b[39m }\n \u001b[90m 87 |\u001b[39m \u001b[36mconst\u001b[39m initialUrl \u001b[33m=\u001b[39m react_native_1\u001b[33m.\u001b[39m\u001b[33mPlatform\u001b[39m\u001b[33m.\u001b[39m\u001b[33mOS\u001b[39m \u001b[33m===\u001b[39m \u001b[32m'web'\u001b[39m \u001b[33m&&\u001b[39m \u001b[36mtypeof\u001b[39m window \u001b[33m!==\u001b[39m \u001b[32m'undefined'\u001b[39m\n \u001b[90m 88 |\u001b[39m \u001b[33m?\u001b[39m \u001b[36mnew\u001b[39m \u001b[33mURL\u001b[39m(window\u001b[33m.\u001b[39mlocation\u001b[33m.\u001b[39mhref)\u001b[0m\n\u001b[1mCall Stack\u001b[22m\n\u001b[2m\u001b[90m ExpoRoot (node_modules/expo-router/build/ExpoRoot.js:85:33)\u001b[39m\u001b[22m\n\u001b[2m\u001b[90m App (node_modules/expo-router/build/qualified-entry.js:20:91)\u001b[39m\u001b[22m\n\u001b[2m\u001b[90m WithDevTools (node_modules/expo/src/launch/withDevTools.tsx:21:12)\u001b[39m\u001b[22m"]}
+{"_e":"root:init","_t":1786667211050,"format":"v0-jsonl","version":"57.0.14"}
+{"_e":"devserver:start","_t":1786667211071,"mode":"development","web":true,"baseUrl":"","asyncRoutes":false,"routerRoot":"../../../src/app","serverComponents":false,"serverActions":false,"serverRendering":true,"apiRoutes":false,"exporting":false}
+{"_e":"metro:config","_t":1786667211289,"serverRoot":"../../..","projectRoot":"../../..","exporting":false,"flags":{"autolinkingModuleResolution":false,"serverActions":false,"serverComponents":false,"reactCompiler":true,"optimizeGraph":false,"treeshaking":false,"logbox":false}}
+{"_e":"expo:dev-tools-plugin:load","_t":1786667211403,"plugins":[]}
+{"_e":"metro:instantiate","_t":1786667212134,"atlas":false,"workers":4,"host":"::","port":8081}
+{"_e":"metro:bundling:started","_t":1786667240898,"id":"1","platform":"android","environment":null,"entry":"node_modules/expo-router/entry.js"}
+{"_e":"metro:bundling:progress","_t":1786667240898,"id":"1","progress":0,"total":1,"current":0}
+{"_e":"metro:bundling:progress","_t":1786667240907,"id":"1","progress":0,"total":1,"current":0}
+{"_e":"metro:bundling:progress","_t":1786667241007,"id":"1","progress":0.1326138527849243,"total":346,"current":126}
+{"_e":"metro:bundling:progress","_t":1786667241107,"id":"1","progress":0.3692790571921489,"total":859,"current":522}
+{"_e":"metro:bundling:progress","_t":1786667241207,"id":"1","progress":0.8449980401909084,"total":1102,"current":1013}
+{"_e":"metro:bundling:progress","_t":1786667241307,"id":"1","progress":0.9943741321166435,"total":1420,"current":1416}
+{"_e":"metro:bundling:done","_t":1786667241363,"id":"1","total":1420,"ms":464.47725}
+{"_e":"metro:bundling:started","_t":1786667417285,"id":"2","platform":"android","environment":null,"entry":"node_modules/expo-router/entry.js"}
+{"_e":"metro:bundling:progress","_t":1786667417285,"id":"2","progress":0,"total":1,"current":0}
+{"_e":"metro:bundling:done","_t":1786667417340,"id":"2","total":1,"ms":55.097375}
+{"_e":"metro:bundling:started","_t":1786667518688,"id":"3","platform":"android","environment":null,"entry":"node_modules/expo-router/entry.js"}
+{"_e":"metro:bundling:progress","_t":1786667518688,"id":"3","progress":0,"total":1,"current":0}
+{"_e":"metro:bundling:done","_t":1786667518744,"id":"3","total":1,"ms":56.403833}
+{"_e":"root:init","_t":1786667657727,"format":"v0-jsonl","version":"57.0.14"}
+{"_e":"devserver:start","_t":1786667657746,"mode":"development","web":true,"baseUrl":"","asyncRoutes":false,"routerRoot":"../../../src/app","serverComponents":false,"serverActions":false,"serverRendering":true,"apiRoutes":false,"exporting":false}
+{"_e":"metro:config","_t":1786667657939,"serverRoot":"../../..","projectRoot":"../../..","exporting":false,"flags":{"autolinkingModuleResolution":false,"serverActions":false,"serverComponents":false,"reactCompiler":true,"optimizeGraph":false,"treeshaking":false,"logbox":false}}
+{"_e":"expo:dev-tools-plugin:load","_t":1786667658037,"plugins":[]}
+{"_e":"metro:instantiate","_t":1786667658593,"atlas":false,"workers":4,"host":"::","port":8081}
+{"_e":"metro:bundling:started","_t":1786667689111,"id":"1","platform":"android","environment":null,"entry":"node_modules/expo-router/entry.js"}
+{"_e":"metro:bundling:progress","_t":1786667689111,"id":"1","progress":0,"total":1,"current":0}
+{"_e":"metro:bundling:progress","_t":1786667689120,"id":"1","progress":0,"total":1,"current":0}
+{"_e":"metro:bundling:progress","_t":1786667689221,"id":"1","progress":0.19285574312029335,"total":378,"current":166}
+{"_e":"metro:bundling:progress","_t":1786667689321,"id":"1","progress":0.5127939459070457,"total":789,"current":565}
+{"_e":"metro:bundling:progress","_t":1786667689421,"id":"1","progress":0.843252736604642,"total":1028,"current":944}
+{"_e":"metro:bundling:progress","_t":1786667689523,"id":"1","progress":0.9688792757740022,"total":1339,"current":1318}
+{"_e":"metro:bundling:progress","_t":1786667689624,"id":"1","progress":0.9985124583687641,"total":1344,"current":1343}
+{"_e":"metro:bundling:progress","_t":1786667689815,"id":"1","progress":0.999,"total":1344,"current":1344}
+{"_e":"metro:bundling:done","_t":1786667689874,"id":"1","total":1344,"ms":763.056417}
+{"_e":"metro:bundling:started","_t":1786667983327,"id":"2","platform":"android","environment":null,"entry":"node_modules/expo-router/entry.js"}
+{"_e":"metro:bundling:progress","_t":1786667983328,"id":"2","progress":0,"total":1,"current":0}
+{"_e":"metro:bundling:done","_t":1786667983402,"id":"2","total":1,"ms":74.646375}
+{"_e":"metro:bundling:started","_t":1786667988361,"id":"3","platform":"android","environment":null,"entry":"node_modules/expo-router/entry.js"}
+{"_e":"metro:bundling:progress","_t":1786667988362,"id":"3","progress":0,"total":1,"current":0}
+{"_e":"metro:bundling:done","_t":1786667988427,"id":"3","total":1,"ms":65.752125}
+{"_e":"metro:client_log","_t":1786668102509,"level":"warn","data":["Route \"./login.tsx\" is missing the required default export. Ensure a React component is exported as default."]}
+{"_e":"metro:client_log","_t":1786668671321,"level":"warn","data":["Route \"./(app)/_layout.tsx\" is missing the required default export. Ensure a React component is exported as default."]}
+{"_e":"metro:client_log","_t":1786668877358,"level":"warn","data":["[Layout children]: Too many screens defined. Route \"register\" is extraneous."]}
+{"_e":"metro:client_log","_t":1786668877397,"level":"warn","data":["Unable to get the view config for default view from module &s ExpoLinearGradient"]}
+{"_e":"metro:bundling:started","_t":1786668924449,"id":"8","platform":"android","environment":null,"entry":"node_modules/expo-router/entry.js"}
+{"_e":"metro:bundling:progress","_t":1786668924449,"id":"8","progress":0,"total":1,"current":0}
+{"_e":"metro:bundling:progress","_t":1786668924455,"id":"8","progress":0,"total":1,"current":0}
+{"_e":"metro:bundling:progress","_t":1786668924555,"id":"8","progress":0.09467455621301776,"total":13,"current":4}
+{"_e":"metro:bundling:progress","_t":1786668924669,"id":"8","progress":0.09467455621301776,"total":20,"current":6}
+{"_e":"metro:bundling:progress","_t":1786668924678,"id":"8","progress":0.12249999999999998,"total":20,"current":7}
+{"_e":"metro:bundling:progress","_t":1786668924779,"id":"8","progress":0.12249999999999998,"total":126,"current":13}
+{"_e":"metro:bundling:progress","_t":1786668924882,"id":"8","progress":0.12249999999999998,"total":153,"current":20}
+{"_e":"metro:bundling:progress","_t":1786668924984,"id":"8","progress":0.12249999999999998,"total":176,"current":27}
+{"_e":"metro:bundling:progress","_t":1786668925086,"id":"8","progress":0.12249999999999998,"total":193,"current":37}
+{"_e":"metro:bundling:progress","_t":1786668925187,"id":"8","progress":0.12249999999999998,"total":210,"current":43}
+{"_e":"metro:bundling:progress","_t":1786668925287,"id":"8","progress":0.12249999999999998,"total":244,"current":75}
+{"_e":"metro:bundling:progress","_t":1786668925387,"id":"8","progress":0.18890234613991932,"total":283,"current":123}
+{"_e":"metro:bundling:progress","_t":1786668925487,"id":"8","progress":0.28141731112433077,"total":328,"current":174}
+{"_e":"metro:bundling:progress","_t":1786668925587,"id":"8","progress":0.29374745061476604,"total":393,"current":213}
+{"_e":"metro:bundling:progress","_t":1786668925687,"id":"8","progress":0.3407062042733218,"total":454,"current":265}
+{"_e":"metro:bundling:progress","_t":1786668925792,"id":"8","progress":0.3731830450052029,"total":496,"current":303}
+{"_e":"metro:bundling:progress","_t":1786668925898,"id":"8","progress":0.4026887344112459,"total":509,"current":323}
+{"_e":"metro:bundling:progress","_t":1786668925998,"id":"8","progress":0.4127654388490157,"total":551,"current":354}
+{"_e":"metro:bundling:progress","_t":1786668926098,"id":"8","progress":0.4127654388490157,"total":604,"current":388}
+{"_e":"metro:bundling:progress","_t":1786668926198,"id":"8","progress":0.5043058181054401,"total":621,"current":441}
+{"_e":"metro:bundling:progress","_t":1786668926298,"id":"8","progress":0.5780826404635928,"total":630,"current":479}
+{"_e":"metro:bundling:progress","_t":1786668926398,"id":"8","progress":0.6347492297139384,"total":669,"current":533}
+{"_e":"metro:bundling:progress","_t":1786668926498,"id":"8","progress":0.6634182019066738,"total":717,"current":584}
+{"_e":"metro:bundling:progress","_t":1786668926598,"id":"8","progress":0.6634182019066738,"total":789,"current":628}
+{"_e":"metro:bundling:progress","_t":1786668926699,"id":"8","progress":0.6634182019066738,"total":830,"current":662}
+{"_e":"metro:bundling:progress","_t":1786668926800,"id":"8","progress":0.6634182019066738,"total":855,"current":689}
+{"_e":"metro:bundling:progress","_t":1786668926900,"id":"8","progress":0.6634182019066738,"total":902,"current":722}
+{"_e":"metro:bundling:progress","_t":1786668927001,"id":"8","progress":0.6634182019066738,"total":922,"current":746}
+{"_e":"metro:bundling:progress","_t":1786668927101,"id":"8","progress":0.6634182019066738,"total":978,"current":778}
+{"_e":"metro:bundling:progress","_t":1786668927206,"id":"8","progress":0.6634182019066738,"total":1000,"current":808}
+{"_e":"metro:bundling:progress","_t":1786668927306,"id":"8","progress":0.6720752867365943,"total":1010,"current":828}
+{"_e":"metro:bundling:progress","_t":1786668927418,"id":"8","progress":0.6892441693327318,"total":1013,"current":841}
+{"_e":"metro:bundling:progress","_t":1786668927520,"id":"8","progress":0.7190246571594678,"total":1026,"current":870}
+{"_e":"metro:bundling:progress","_t":1786668927619,"id":"8","progress":0.7806462310598867,"total":1039,"current":918}
+{"_e":"metro:bundling:progress","_t":1786668927719,"id":"8","progress":0.8247073098143357,"total":1045,"current":949}
+{"_e":"metro:bundling:progress","_t":1786668927821,"id":"8","progress":0.8599937700249198,"total":1060,"current":983}
+{"_e":"metro:bundling:progress","_t":1786668927924,"id":"8","progress":0.8786872215914054,"total":1070,"current":1003}
+{"_e":"metro:bundling:progress","_t":1786668928024,"id":"8","progress":0.9038018389941828,"total":1095,"current":1041}
+{"_e":"metro:bundling:progress","_t":1786668928124,"id":"8","progress":0.9622845137591454,"total":1103,"current":1082}
+{"_e":"metro:bundling:progress","_t":1786668928224,"id":"8","progress":0.9683953324457671,"total":1130,"current":1112}
+{"_e":"metro:bundling:progress","_t":1786668928324,"id":"8","progress":0.9683953324457671,"total":1199,"current":1154}
+{"_e":"metro:bundling:progress","_t":1786668928425,"id":"8","progress":0.9683953324457671,"total":1229,"current":1204}
+{"_e":"metro:bundling:progress","_t":1786668928525,"id":"8","progress":0.9683953324457671,"total":1306,"current":1258}
+{"_e":"metro:bundling:progress","_t":1786668928628,"id":"8","progress":0.9790738224650464,"total":1331,"current":1317}
+{"_e":"metro:bundling:progress","_t":1786668928729,"id":"8","progress":0.9790738224650464,"total":1366,"current":1346}
+{"_e":"metro:bundling:progress","_t":1786668928830,"id":"8","progress":0.9898071287761735,"total":1370,"current":1363}
+{"_e":"metro:bundling:progress","_t":1786668928931,"id":"8","progress":0.999,"total":1375,"current":1375}
+{"_e":"metro:bundling:done","_t":1786668929022,"id":"8","total":1375,"ms":4572.863958}
+{"_e":"metro:bundling:started","_t":1786668934022,"id":"9","platform":"android","environment":null,"entry":"node_modules/expo-router/entry.js"}
+{"_e":"metro:bundling:progress","_t":1786668934022,"id":"9","progress":0,"total":1,"current":0}
+{"_e":"metro:bundling:progress","_t":1786668934026,"id":"9","progress":0,"total":1,"current":0}
+{"_e":"metro:bundling:done","_t":1786668934095,"id":"9","total":1,"ms":72.474542}
+{"_e":"metro:client_log","_t":1786668936416,"level":"warn","data":["[Layout children]: Too many screens defined. Route \"register\" is extraneous."]}
+{"_e":"metro:client_log","_t":1786668936491,"level":"warn","data":["Unable to get the view config for default view from module &s ExpoLinearGradient"]}
+{"_e":"metro:bundling:started","_t":1786668940099,"id":"a","platform":"android","environment":null,"entry":"node_modules/expo-router/entry.js"}
+{"_e":"metro:bundling:progress","_t":1786668940099,"id":"a","progress":0,"total":1,"current":0}
+{"_e":"metro:bundling:done","_t":1786668940158,"id":"a","total":1,"ms":59.636334}
+{"_e":"metro:client_log","_t":1786668942560,"level":"warn","data":["[Layout children]: Too many screens defined. Route \"register\" is extraneous."]}
+{"_e":"metro:client_log","_t":1786668942634,"level":"warn","data":["Unable to get the view config for default view from module &s ExpoLinearGradient"]}
+{"_e":"metro:bundling:started","_t":1786668990201,"id":"b","platform":"android","environment":null,"entry":"node_modules/expo-router/entry.js"}
+{"_e":"metro:bundling:progress","_t":1786668990202,"id":"b","progress":0,"total":1,"current":0}
+{"_e":"metro:bundling:progress","_t":1786668990209,"id":"b","progress":0,"total":1,"current":0}
+{"_e":"metro:bundling:done","_t":1786668990344,"id":"b","total":1,"ms":142.19725}
+{"_e":"metro:client_log","_t":1786668992770,"level":"warn","data":["[Layout children]: Too many screens defined. Route \"register\" is extraneous."]}
+{"_e":"metro:client_log","_t":1786668992848,"level":"warn","data":["Unable to get the view config for default view from module &s ExpoLinearGradient"]}
+{"_e":"root:init","_t":1786669142655,"format":"v0-jsonl","version":"57.0.14"}
+{"_e":"devserver:start","_t":1786669142675,"mode":"development","web":true,"baseUrl":"","asyncRoutes":false,"routerRoot":"../../../src/app","serverComponents":false,"serverActions":false,"serverRendering":true,"apiRoutes":false,"exporting":false}
+{"_e":"metro:config","_t":1786669142883,"serverRoot":"../../..","projectRoot":"../../..","exporting":false,"flags":{"autolinkingModuleResolution":false,"serverActions":false,"serverComponents":false,"reactCompiler":true,"optimizeGraph":false,"treeshaking":false,"logbox":false}}
+{"_e":"expo:dev-tools-plugin:load","_t":1786669142997,"plugins":[]}
+{"_e":"metro:instantiate","_t":1786669143551,"atlas":false,"workers":4,"host":"::","port":8081}
+{"_e":"metro:bundling:started","_t":1786669172072,"id":"1","platform":"android","environment":null,"entry":"node_modules/expo-router/entry.js"}
+{"_e":"metro:bundling:progress","_t":1786669172072,"id":"1","progress":0,"total":1,"current":0}
+{"_e":"metro:bundling:progress","_t":1786669172078,"id":"1","progress":0,"total":1,"current":0}
+{"_e":"metro:bundling:progress","_t":1786669172178,"id":"1","progress":0.2373970122227252,"total":470,"current":229}
+{"_e":"metro:bundling:progress","_t":1786669172278,"id":"1","progress":0.49891672987289054,"total":899,"current":635}
+{"_e":"metro:bundling:progress","_t":1786669172378,"id":"1","progress":0.744792644023269,"total":1095,"current":945}
+{"_e":"metro:bundling:progress","_t":1786669172478,"id":"1","progress":0.8793117898492595,"total":1445,"current":1355}
+{"_e":"metro:bundling:progress","_t":1786669172578,"id":"1","progress":0.9224745033406198,"total":1669,"current":1603}
+{"_e":"metro:bundling:progress","_t":1786669172678,"id":"1","progress":0.9988548526561777,"total":1746,"current":1745}
+{"_e":"metro:bundling:progress","_t":1786669172795,"id":"1","progress":0.999,"total":1746,"current":1746}
+{"_e":"metro:bundling:done","_t":1786669172853,"id":"1","total":1746,"ms":780.973583}
+{"_e":"metro:client_log","_t":1786669175178,"level":"warn","data":["[Layout children]: Too many screens defined. Route \"register\" is extraneous."]}
+{"_e":"metro:client_log","_t":1786669177912,"level":"error","data":["[ReferenceError: Property 'FadeInUp' doesn't exist]","\n\n\u001b[1mCode: login.tsx\u001b[22m\n\u001b[0m \u001b[90m 44 |\u001b[39m \u001b[33m<\u001b[39m\u001b[33mKeyboardAvoidingView\u001b[39m style\u001b[33m=\u001b[39m{styles\u001b[33m.\u001b[39mcontainer} behavior\u001b[33m=\u001b[39m{\u001b[33mPlatform\u001b[39m\u001b[33m.\u001b[39m\u001b[33mOS\u001b[39m \u001b[33m===\u001b[39m \u001b[32m'ios'\u001b[39m \u001b[33m?\u001b[39m \u001b[32m'padding'\u001b[39m \u001b[33m:\u001b[39m undefined}\u001b[33m>\u001b[39m\n \u001b[90m 45 |\u001b[39m \u001b[33m<\u001b[39m\u001b[33mView\u001b[39m style\u001b[33m=\u001b[39m{[styles\u001b[33m.\u001b[39mcontent\u001b[33m,\u001b[39m { paddingTop\u001b[33m:\u001b[39m insets\u001b[33m.\u001b[39mtop \u001b[33m+\u001b[39m \u001b[33mSpacing\u001b[39m\u001b[33m.\u001b[39mxxl }]}\u001b[33m>\u001b[39m\n\u001b[31m\u001b[1m>\u001b[22m\u001b[39m\u001b[90m 46 |\u001b[39m \u001b[33m<\u001b[39m\u001b[33mAnimated\u001b[39m\u001b[33m.\u001b[39m\u001b[33mView\u001b[39m entering\u001b[33m=\u001b[39m{\u001b[33mFadeInUp\u001b[39m\u001b[33m.\u001b[39mduration(\u001b[35m600\u001b[39m)} style\u001b[33m=\u001b[39m{styles\u001b[33m.\u001b[39mheader}\u001b[33m>\u001b[39m\n \u001b[90m |\u001b[39m \u001b[31m\u001b[1m^\u001b[22m\u001b[39m\n \u001b[90m 47 |\u001b[39m \u001b[33m<\u001b[39m\u001b[33mText\u001b[39m style\u001b[33m=\u001b[39m{styles\u001b[33m.\u001b[39mtitle}\u001b[33m>\u001b[39m\u001b[33mYABA\u001b[39m\u001b[33m<\u001b[39m\u001b[33m/\u001b[39m\u001b[33mText\u001b[39m\u001b[33m>\u001b[39m\n \u001b[90m 48 |\u001b[39m \u001b[33m<\u001b[39m\u001b[33mText\u001b[39m style\u001b[33m=\u001b[39m{styles\u001b[33m.\u001b[39msubtitle}\u001b[33m>\u001b[39m\u001b[33mO\u001b[39m seu dinheiro\u001b[33m,\u001b[39m no seu controle\u001b[33m.\u001b[39m\u001b[33m<\u001b[39m\u001b[33m/\u001b[39m\u001b[33mText\u001b[39m\u001b[33m>\u001b[39m\n \u001b[90m 49 |\u001b[39m \u001b[33m<\u001b[39m\u001b[33m/\u001b[39m\u001b[33mAnimated\u001b[39m\u001b[33m.\u001b[39m\u001b[33mView\u001b[39m\u001b[33m>\u001b[39m\u001b[0m\n\u001b[1mCall Stack\u001b[22m\n\u001b[90m LoginScreen (src/app/login.tsx:46:42)\u001b[39m","\n\n\u001b[1mCode: _layout.tsx\u001b[22m\n\u001b[0m \u001b[90m 30 |\u001b[39m \u001b[36mreturn\u001b[39m (\n \u001b[90m 31 |\u001b[39m \u001b[33m<\u001b[39m\u001b[33mView\u001b[39m style\u001b[33m=\u001b[39m{{ flex\u001b[33m:\u001b[39m \u001b[35m1\u001b[39m\u001b[33m,\u001b[39m backgroundColor\u001b[33m:\u001b[39m \u001b[33mColors\u001b[39m\u001b[33m.\u001b[39mbackground }}\u001b[33m>\u001b[39m\n\u001b[31m\u001b[1m>\u001b[22m\u001b[39m\u001b[90m 32 |\u001b[39m \u001b[33m<\u001b[39m\u001b[33mStack\u001b[39m screenOptions\u001b[33m=\u001b[39m{{ headerShown\u001b[33m:\u001b[39m \u001b[36mfalse\u001b[39m\u001b[33m,\u001b[39m contentStyle\u001b[33m:\u001b[39m { backgroundColor\u001b[33m:\u001b[39m \u001b[33mColors\u001b[39m\u001b[33m.\u001b[39mbackground } }}\u001b[33m>\u001b[39m\n \u001b[90m |\u001b[39m \u001b[31m\u001b[1m^\u001b[22m\u001b[39m\n \u001b[90m 33 |\u001b[39m \u001b[33m<\u001b[39m\u001b[33mStack\u001b[39m\u001b[33m.\u001b[39m\u001b[33mScreen\u001b[39m name\u001b[33m=\u001b[39m\u001b[32m\"(app)\"\u001b[39m \u001b[33m/\u001b[39m\u001b[33m>\u001b[39m\n \u001b[90m 34 |\u001b[39m \u001b[33m<\u001b[39m\u001b[33mStack\u001b[39m\u001b[33m.\u001b[39m\u001b[33mScreen\u001b[39m name\u001b[33m=\u001b[39m\u001b[32m\"login\"\u001b[39m \u001b[33m/\u001b[39m\u001b[33m>\u001b[39m\n \u001b[90m 35 |\u001b[39m \u001b[33m<\u001b[39m\u001b[33mStack\u001b[39m\u001b[33m.\u001b[39m\u001b[33mScreen\u001b[39m name\u001b[33m=\u001b[39m\u001b[32m\"register\"\u001b[39m \u001b[33m/\u001b[39m\u001b[33m>\u001b[39m\u001b[0m\n\u001b[1mCall Stack\u001b[22m\n\u001b[90m RootContent (src/app/_layout.tsx:32:13)\u001b[39m\n\u001b[90m RootLayout (src/app/_layout.tsx:50:17)\u001b[39m"]}
+{"_e":"metro:client_log","_t":1786669304305,"level":"warn","data":["[Layout children]: Too many screens defined. Route \"register\" is extraneous."]}
+{"_e":"metro:client_log","_t":1786669304461,"level":"error","data":["[ReferenceError: Property 'Button' doesn't exist]","\n\n\u001b[1mCode: login.tsx\u001b[22m\n\u001b[0m \u001b[90m 70 |\u001b[39m \u001b[33m/\u001b[39m\u001b[33m>\u001b[39m\n \u001b[90m 71 |\u001b[39m\n\u001b[31m\u001b[1m>\u001b[22m\u001b[39m\u001b[90m 72 |\u001b[39m \u001b[33m<\u001b[39m\u001b[33mButton\u001b[39m\n \u001b[90m |\u001b[39m \u001b[31m\u001b[1m^\u001b[22m\u001b[39m\n \u001b[90m 73 |\u001b[39m id\u001b[33m=\u001b[39m\u001b[32m\"login-button\"\u001b[39m\n \u001b[90m 74 |\u001b[39m label\u001b[33m=\u001b[39m\u001b[32m\"Entrar\"\u001b[39m\n \u001b[90m 75 |\u001b[39m fullWidth\u001b[0m\n\u001b[1mCall Stack\u001b[22m\n\u001b[90m LoginScreen (src/app/login.tsx:72:22)\u001b[39m","\n\n\u001b[1mCode: _layout.tsx\u001b[22m\n\u001b[0m \u001b[90m 30 |\u001b[39m \u001b[36mreturn\u001b[39m (\n \u001b[90m 31 |\u001b[39m \u001b[33m<\u001b[39m\u001b[33mView\u001b[39m style\u001b[33m=\u001b[39m{{ flex\u001b[33m:\u001b[39m \u001b[35m1\u001b[39m\u001b[33m,\u001b[39m backgroundColor\u001b[33m:\u001b[39m \u001b[33mColors\u001b[39m\u001b[33m.\u001b[39mbackground }}\u001b[33m>\u001b[39m\n\u001b[31m\u001b[1m>\u001b[22m\u001b[39m\u001b[90m 32 |\u001b[39m \u001b[33m<\u001b[39m\u001b[33mStack\u001b[39m screenOptions\u001b[33m=\u001b[39m{{ headerShown\u001b[33m:\u001b[39m \u001b[36mfalse\u001b[39m\u001b[33m,\u001b[39m contentStyle\u001b[33m:\u001b[39m { backgroundColor\u001b[33m:\u001b[39m \u001b[33mColors\u001b[39m\u001b[33m.\u001b[39mbackground } }}\u001b[33m>\u001b[39m\n \u001b[90m |\u001b[39m \u001b[31m\u001b[1m^\u001b[22m\u001b[39m\n \u001b[90m 33 |\u001b[39m \u001b[33m<\u001b[39m\u001b[33mStack\u001b[39m\u001b[33m.\u001b[39m\u001b[33mScreen\u001b[39m name\u001b[33m=\u001b[39m\u001b[32m\"(app)\"\u001b[39m \u001b[33m/\u001b[39m\u001b[33m>\u001b[39m\n \u001b[90m 34 |\u001b[39m \u001b[33m<\u001b[39m\u001b[33mStack\u001b[39m\u001b[33m.\u001b[39m\u001b[33mScreen\u001b[39m name\u001b[33m=\u001b[39m\u001b[32m\"login\"\u001b[39m \u001b[33m/\u001b[39m\u001b[33m>\u001b[39m\n \u001b[90m 35 |\u001b[39m \u001b[33m<\u001b[39m\u001b[33mStack\u001b[39m\u001b[33m.\u001b[39m\u001b[33mScreen\u001b[39m name\u001b[33m=\u001b[39m\u001b[32m\"register\"\u001b[39m \u001b[33m/\u001b[39m\u001b[33m>\u001b[39m\u001b[0m\n\u001b[1mCall Stack\u001b[22m\n\u001b[90m RootContent (src/app/_layout.tsx:32:13)\u001b[39m\n\u001b[90m RootLayout (src/app/_layout.tsx:50:17)\u001b[39m"]}
+{"_e":"metro:bundling:started","_t":1786669364003,"id":"a","platform":"android","environment":null,"entry":"node_modules/expo-router/entry.js"}
+{"_e":"metro:bundling:progress","_t":1786669364004,"id":"a","progress":0,"total":1,"current":0}
+{"_e":"metro:bundling:done","_t":1786669364078,"id":"a","total":1,"ms":73.626166}
+{"_e":"metro:client_log","_t":1786669366264,"level":"warn","data":["[Layout children]: Too many screens defined. Route \"register\" is extraneous."]}
+{"_e":"metro:client_log","_t":1786669366558,"level":"error","data":["[ReferenceError: Property 'Button' doesn't exist]","\n\n\u001b[1mCode: login.tsx\u001b[22m\n\u001b[0m \u001b[90m 70 |\u001b[39m \u001b[33m/\u001b[39m\u001b[33m>\u001b[39m\n \u001b[90m 71 |\u001b[39m\n\u001b[31m\u001b[1m>\u001b[22m\u001b[39m\u001b[90m 72 |\u001b[39m \u001b[33m<\u001b[39m\u001b[33mButton\u001b[39m\n \u001b[90m |\u001b[39m \u001b[31m\u001b[1m^\u001b[22m\u001b[39m\n \u001b[90m 73 |\u001b[39m id\u001b[33m=\u001b[39m\u001b[32m\"login-button\"\u001b[39m\n \u001b[90m 74 |\u001b[39m label\u001b[33m=\u001b[39m\u001b[32m\"Entrar\"\u001b[39m\n \u001b[90m 75 |\u001b[39m fullWidth\u001b[0m\n\u001b[1mCall Stack\u001b[22m\n\u001b[90m LoginScreen (src/app/login.tsx:72:22)\u001b[39m","\n\n\u001b[1mCode: _layout.tsx\u001b[22m\n\u001b[0m \u001b[90m 30 |\u001b[39m \u001b[36mreturn\u001b[39m (\n \u001b[90m 31 |\u001b[39m \u001b[33m<\u001b[39m\u001b[33mView\u001b[39m style\u001b[33m=\u001b[39m{{ flex\u001b[33m:\u001b[39m \u001b[35m1\u001b[39m\u001b[33m,\u001b[39m backgroundColor\u001b[33m:\u001b[39m \u001b[33mColors\u001b[39m\u001b[33m.\u001b[39mbackground }}\u001b[33m>\u001b[39m\n\u001b[31m\u001b[1m>\u001b[22m\u001b[39m\u001b[90m 32 |\u001b[39m \u001b[33m<\u001b[39m\u001b[33mStack\u001b[39m screenOptions\u001b[33m=\u001b[39m{{ headerShown\u001b[33m:\u001b[39m \u001b[36mfalse\u001b[39m\u001b[33m,\u001b[39m contentStyle\u001b[33m:\u001b[39m { backgroundColor\u001b[33m:\u001b[39m \u001b[33mColors\u001b[39m\u001b[33m.\u001b[39mbackground } }}\u001b[33m>\u001b[39m\n \u001b[90m |\u001b[39m \u001b[31m\u001b[1m^\u001b[22m\u001b[39m\n \u001b[90m 33 |\u001b[39m \u001b[33m<\u001b[39m\u001b[33mStack\u001b[39m\u001b[33m.\u001b[39m\u001b[33mScreen\u001b[39m name\u001b[33m=\u001b[39m\u001b[32m\"(app)\"\u001b[39m \u001b[33m/\u001b[39m\u001b[33m>\u001b[39m\n \u001b[90m 34 |\u001b[39m \u001b[33m<\u001b[39m\u001b[33mStack\u001b[39m\u001b[33m.\u001b[39m\u001b[33mScreen\u001b[39m name\u001b[33m=\u001b[39m\u001b[32m\"login\"\u001b[39m \u001b[33m/\u001b[39m\u001b[33m>\u001b[39m\n \u001b[90m 35 |\u001b[39m \u001b[33m<\u001b[39m\u001b[33mStack\u001b[39m\u001b[33m.\u001b[39m\u001b[33mScreen\u001b[39m name\u001b[33m=\u001b[39m\u001b[32m\"register\"\u001b[39m \u001b[33m/\u001b[39m\u001b[33m>\u001b[39m\u001b[0m\n\u001b[1mCall Stack\u001b[22m\n\u001b[90m RootContent (src/app/_layout.tsx:32:13)\u001b[39m\n\u001b[90m RootLayout (src/app/_layout.tsx:50:17)\u001b[39m"]}
+{"_e":"metro:bundling:started","_t":1786669370848,"id":"f","platform":"android","environment":null,"entry":"node_modules/expo-router/entry.js"}
+{"_e":"metro:bundling:progress","_t":1786669370849,"id":"f","progress":0,"total":1,"current":0}
+{"_e":"metro:bundling:done","_t":1786669370909,"id":"f","total":1,"ms":60.586041}
+{"_e":"metro:client_log","_t":1786669373087,"level":"warn","data":["[Layout children]: Too many screens defined. Route \"register\" is extraneous."]}
+{"_e":"metro:client_log","_t":1786669373347,"level":"error","data":["[ReferenceError: Property 'Button' doesn't exist]","\n\n\u001b[1mCode: login.tsx\u001b[22m\n\u001b[0m \u001b[90m 70 |\u001b[39m \u001b[33m/\u001b[39m\u001b[33m>\u001b[39m\n \u001b[90m 71 |\u001b[39m\n\u001b[31m\u001b[1m>\u001b[22m\u001b[39m\u001b[90m 72 |\u001b[39m \u001b[33m<\u001b[39m\u001b[33mButton\u001b[39m\n \u001b[90m |\u001b[39m \u001b[31m\u001b[1m^\u001b[22m\u001b[39m\n \u001b[90m 73 |\u001b[39m id\u001b[33m=\u001b[39m\u001b[32m\"login-button\"\u001b[39m\n \u001b[90m 74 |\u001b[39m label\u001b[33m=\u001b[39m\u001b[32m\"Entrar\"\u001b[39m\n \u001b[90m 75 |\u001b[39m fullWidth\u001b[0m\n\u001b[1mCall Stack\u001b[22m\n\u001b[90m LoginScreen (src/app/login.tsx:72:22)\u001b[39m","\n\n\u001b[1mCode: _layout.tsx\u001b[22m\n\u001b[0m \u001b[90m 30 |\u001b[39m \u001b[36mreturn\u001b[39m (\n \u001b[90m 31 |\u001b[39m \u001b[33m<\u001b[39m\u001b[33mView\u001b[39m style\u001b[33m=\u001b[39m{{ flex\u001b[33m:\u001b[39m \u001b[35m1\u001b[39m\u001b[33m,\u001b[39m backgroundColor\u001b[33m:\u001b[39m \u001b[33mColors\u001b[39m\u001b[33m.\u001b[39mbackground }}\u001b[33m>\u001b[39m\n\u001b[31m\u001b[1m>\u001b[22m\u001b[39m\u001b[90m 32 |\u001b[39m \u001b[33m<\u001b[39m\u001b[33mStack\u001b[39m screenOptions\u001b[33m=\u001b[39m{{ headerShown\u001b[33m:\u001b[39m \u001b[36mfalse\u001b[39m\u001b[33m,\u001b[39m contentStyle\u001b[33m:\u001b[39m { backgroundColor\u001b[33m:\u001b[39m \u001b[33mColors\u001b[39m\u001b[33m.\u001b[39mbackground } }}\u001b[33m>\u001b[39m\n \u001b[90m |\u001b[39m \u001b[31m\u001b[1m^\u001b[22m\u001b[39m\n \u001b[90m 33 |\u001b[39m \u001b[33m<\u001b[39m\u001b[33mStack\u001b[39m\u001b[33m.\u001b[39m\u001b[33mScreen\u001b[39m name\u001b[33m=\u001b[39m\u001b[32m\"(app)\"\u001b[39m \u001b[33m/\u001b[39m\u001b[33m>\u001b[39m\n \u001b[90m 34 |\u001b[39m \u001b[33m<\u001b[39m\u001b[33mStack\u001b[39m\u001b[33m.\u001b[39m\u001b[33mScreen\u001b[39m name\u001b[33m=\u001b[39m\u001b[32m\"login\"\u001b[39m \u001b[33m/\u001b[39m\u001b[33m>\u001b[39m\n \u001b[90m 35 |\u001b[39m \u001b[33m<\u001b[39m\u001b[33mStack\u001b[39m\u001b[33m.\u001b[39m\u001b[33mScreen\u001b[39m name\u001b[33m=\u001b[39m\u001b[32m\"register\"\u001b[39m \u001b[33m/\u001b[39m\u001b[33m>\u001b[39m\u001b[0m\n\u001b[1mCall Stack\u001b[22m\n\u001b[90m RootContent (src/app/_layout.tsx:32:13)\u001b[39m\n\u001b[90m RootLayout (src/app/_layout.tsx:50:17)\u001b[39m"]}
+{"_e":"root:init","_t":1786669402477,"format":"v0-jsonl","version":"57.0.14"}
+{"_e":"devserver:start","_t":1786669402488,"mode":"development","web":true,"baseUrl":"","asyncRoutes":false,"routerRoot":"../../../src/app","serverComponents":false,"serverActions":false,"serverRendering":true,"apiRoutes":false,"exporting":false}
+{"_e":"metro:config","_t":1786669402675,"serverRoot":"../../..","projectRoot":"../../..","exporting":false,"flags":{"autolinkingModuleResolution":false,"serverActions":false,"serverComponents":false,"reactCompiler":true,"optimizeGraph":false,"treeshaking":false,"logbox":false}}
+{"_e":"expo:dev-tools-plugin:load","_t":1786669402765,"plugins":[]}
+{"_e":"metro:instantiate","_t":1786669403417,"atlas":false,"workers":4,"host":"::","port":8081}
+{"_e":"metro:bundling:started","_t":1786669438125,"id":"1","platform":"android","environment":null,"entry":"node_modules/expo-router/entry.js"}
+{"_e":"metro:bundling:progress","_t":1786669438125,"id":"1","progress":0,"total":1,"current":0}
+{"_e":"metro:bundling:progress","_t":1786669438131,"id":"1","progress":0,"total":1,"current":0}
+{"_e":"metro:bundling:progress","_t":1786669438231,"id":"1","progress":0.30918488105301295,"total":455,"current":253}
+{"_e":"metro:bundling:progress","_t":1786669438332,"id":"1","progress":0.5655653894210746,"total":980,"current":737}
+{"_e":"metro:bundling:progress","_t":1786669438431,"id":"1","progress":0.8075607257179918,"total":1401,"current":1259}
+{"_e":"metro:bundling:done","_t":1786669438565,"id":"1","total":1401,"ms":439.637667}
+{"_e":"metro:client_log","_t":1786669441376,"level":"warn","data":["[Layout children]: Too many screens defined. Route \"register\" is extraneous."]}
+{"_e":"metro:client_log","_t":1786669441676,"level":"error","data":["[ReferenceError: Property 'Button' doesn't exist]","\n\n\u001b[1mCode: login.tsx\u001b[22m\n\u001b[0m \u001b[90m 70 |\u001b[39m \u001b[33m/\u001b[39m\u001b[33m>\u001b[39m\n \u001b[90m 71 |\u001b[39m\n\u001b[31m\u001b[1m>\u001b[22m\u001b[39m\u001b[90m 72 |\u001b[39m \u001b[33m<\u001b[39m\u001b[33mButton\u001b[39m\n \u001b[90m |\u001b[39m \u001b[31m\u001b[1m^\u001b[22m\u001b[39m\n \u001b[90m 73 |\u001b[39m id\u001b[33m=\u001b[39m\u001b[32m\"login-button\"\u001b[39m\n \u001b[90m 74 |\u001b[39m label\u001b[33m=\u001b[39m\u001b[32m\"Entrar\"\u001b[39m\n \u001b[90m 75 |\u001b[39m fullWidth\u001b[0m\n\u001b[1mCall Stack\u001b[22m\n\u001b[90m LoginScreen (src/app/login.tsx:72:22)\u001b[39m","\n\n\u001b[1mCode: _layout.tsx\u001b[22m\n\u001b[0m \u001b[90m 30 |\u001b[39m \u001b[36mreturn\u001b[39m (\n \u001b[90m 31 |\u001b[39m \u001b[33m<\u001b[39m\u001b[33mView\u001b[39m style\u001b[33m=\u001b[39m{{ flex\u001b[33m:\u001b[39m \u001b[35m1\u001b[39m\u001b[33m,\u001b[39m backgroundColor\u001b[33m:\u001b[39m \u001b[33mColors\u001b[39m\u001b[33m.\u001b[39mbackground }}\u001b[33m>\u001b[39m\n\u001b[31m\u001b[1m>\u001b[22m\u001b[39m\u001b[90m 32 |\u001b[39m \u001b[33m<\u001b[39m\u001b[33mStack\u001b[39m screenOptions\u001b[33m=\u001b[39m{{ headerShown\u001b[33m:\u001b[39m \u001b[36mfalse\u001b[39m\u001b[33m,\u001b[39m contentStyle\u001b[33m:\u001b[39m { backgroundColor\u001b[33m:\u001b[39m \u001b[33mColors\u001b[39m\u001b[33m.\u001b[39mbackground } }}\u001b[33m>\u001b[39m\n \u001b[90m |\u001b[39m \u001b[31m\u001b[1m^\u001b[22m\u001b[39m\n \u001b[90m 33 |\u001b[39m \u001b[33m<\u001b[39m\u001b[33mStack\u001b[39m\u001b[33m.\u001b[39m\u001b[33mScreen\u001b[39m name\u001b[33m=\u001b[39m\u001b[32m\"(app)\"\u001b[39m \u001b[33m/\u001b[39m\u001b[33m>\u001b[39m\n \u001b[90m 34 |\u001b[39m \u001b[33m<\u001b[39m\u001b[33mStack\u001b[39m\u001b[33m.\u001b[39m\u001b[33mScreen\u001b[39m name\u001b[33m=\u001b[39m\u001b[32m\"login\"\u001b[39m \u001b[33m/\u001b[39m\u001b[33m>\u001b[39m\n \u001b[90m 35 |\u001b[39m \u001b[33m<\u001b[39m\u001b[33mStack\u001b[39m\u001b[33m.\u001b[39m\u001b[33mScreen\u001b[39m name\u001b[33m=\u001b[39m\u001b[32m\"register\"\u001b[39m \u001b[33m/\u001b[39m\u001b[33m>\u001b[39m\u001b[0m\n\u001b[1mCall Stack\u001b[22m\n\u001b[90m RootContent (src/app/_layout.tsx:32:13)\u001b[39m\n\u001b[90m RootLayout (src/app/_layout.tsx:50:17)\u001b[39m"]}
+{"_e":"metro:client_log","_t":1786669661366,"level":"warn","data":["[Layout children]: Too many screens defined. Route \"register\" is extraneous."]}
+{"_e":"metro:client_log","_t":1786669661471,"level":"error","data":["[ReferenceError: Property 'Button' doesn't exist]","\n\n\u001b[1mCode: login.tsx\u001b[22m\n\u001b[0m \u001b[90m 71 |\u001b[39m\n \u001b[90m 72 |\u001b[39m \u001b[33m<\u001b[39m\u001b[33mButton\u001b[39m\n\u001b[31m\u001b[1m>\u001b[22m\u001b[39m\u001b[90m 73 |\u001b[39m id\u001b[33m=\u001b[39m\u001b[32m\"login-button\"\u001b[39m\n \u001b[90m |\u001b[39m \u001b[31m\u001b[1m^\u001b[22m\u001b[39m\n \u001b[90m 74 |\u001b[39m label\u001b[33m=\u001b[39m\u001b[32m\"Entrar\"\u001b[39m\n \u001b[90m 75 |\u001b[39m fullWidth\n \u001b[90m 76 |\u001b[39m onPress\u001b[33m=\u001b[39m{handleLogin}\u001b[0m\n\u001b[1mCall Stack\u001b[22m\n\u001b[90m LoginScreen (src/app/login.tsx:73:42)\u001b[39m","\n\n\u001b[1mCode: _layout.tsx\u001b[22m\n\u001b[0m \u001b[90m 30 |\u001b[39m \u001b[36mreturn\u001b[39m (\n \u001b[90m 31 |\u001b[39m \u001b[33m<\u001b[39m\u001b[33mView\u001b[39m style\u001b[33m=\u001b[39m{{ flex\u001b[33m:\u001b[39m \u001b[35m1\u001b[39m\u001b[33m,\u001b[39m backgroundColor\u001b[33m:\u001b[39m \u001b[33mColors\u001b[39m\u001b[33m.\u001b[39mbackground }}\u001b[33m>\u001b[39m\n\u001b[31m\u001b[1m>\u001b[22m\u001b[39m\u001b[90m 32 |\u001b[39m \u001b[33m<\u001b[39m\u001b[33mStack\u001b[39m screenOptions\u001b[33m=\u001b[39m{{ headerShown\u001b[33m:\u001b[39m \u001b[36mfalse\u001b[39m\u001b[33m,\u001b[39m contentStyle\u001b[33m:\u001b[39m { backgroundColor\u001b[33m:\u001b[39m \u001b[33mColors\u001b[39m\u001b[33m.\u001b[39mbackground } }}\u001b[33m>\u001b[39m\n \u001b[90m |\u001b[39m \u001b[31m\u001b[1m^\u001b[22m\u001b[39m\n \u001b[90m 33 |\u001b[39m \u001b[33m<\u001b[39m\u001b[33mStack\u001b[39m\u001b[33m.\u001b[39m\u001b[33mScreen\u001b[39m name\u001b[33m=\u001b[39m\u001b[32m\"(app)\"\u001b[39m \u001b[33m/\u001b[39m\u001b[33m>\u001b[39m\n \u001b[90m 34 |\u001b[39m \u001b[33m<\u001b[39m\u001b[33mStack\u001b[39m\u001b[33m.\u001b[39m\u001b[33mScreen\u001b[39m name\u001b[33m=\u001b[39m\u001b[32m\"login\"\u001b[39m \u001b[33m/\u001b[39m\u001b[33m>\u001b[39m\n \u001b[90m 35 |\u001b[39m \u001b[33m<\u001b[39m\u001b[33mStack\u001b[39m\u001b[33m.\u001b[39m\u001b[33mScreen\u001b[39m name\u001b[33m=\u001b[39m\u001b[32m\"register\"\u001b[39m \u001b[33m/\u001b[39m\u001b[33m>\u001b[39m\u001b[0m\n\u001b[1mCall Stack\u001b[22m\n\u001b[90m RootContent (src/app/_layout.tsx:32:13)\u001b[39m\n\u001b[90m RootLayout (src/app/_layout.tsx:50:17)\u001b[39m"]}
+{"_e":"metro:client_log","_t":1786669704278,"level":"warn","data":["[Layout children]: Too many screens defined. Route \"register\" is extraneous."]}
+{"_e":"metro:client_log","_t":1786669729835,"level":"warn","data":["[Layout children]: Too many screens defined. Route \"register\" is extraneous."]}
+{"_e":"metro:bundling:failed","_t":1786669797566,"id":null,"message":"Unable to resolve \"@/components/ui/Button\" from \"src/app/register.tsx\"\n 6 | import * as LocalAuthentication from 'expo-local-authentication';\n 7 | import * as SecureStore from 'expo-secure-store';\n> 8 | import { Button } from '@/components/ui/Button';\n | ^\n 9 | import { Input } from '@/components/ui/Input';\n 10 | import { Colors, Spacing, Typography } from '@/theme/tokens';\n 11 | import { useAuth } from '@/contexts/AuthContext';","importStack":"\u001b[1mImport stack:\u001b[22m\n\n\u001b[90m \u001b[39msrc/app/register.tsx\n\u001b[90m |\u001b[39m \u001b[36mimport\u001b[39m \u001b[32m\"@/components/ui/Button\"\u001b[39m\n\n\u001b[90m \u001b[39msrc/app\u001b[2m (require.context)\u001b[22m\n","filename":null,"targetModuleName":"@/components/ui/Button","originModulePath":"src/app/register.tsx"}
+{"_e":"metro:bundling:failed","_t":1786669797720,"id":null,"message":"Unable to resolve \"@/components/ui/Button\" from \"src/app/register.tsx\"\n 6 | import * as LocalAuthentication from 'expo-local-authentication';\n 7 | import * as SecureStore from 'expo-secure-store';\n> 8 | import { Button } from '@/components/ui/Button';\n | ^\n 9 | import { Input } from '@/components/ui/Input';\n 10 | import { Colors, Spacing, Typography } from '@/theme/tokens';\n 11 | import { useAuth } from '@/contexts/AuthContext';","importStack":"\u001b[1mImport stack:\u001b[22m\n\n\u001b[90m \u001b[39msrc/app/register.tsx\n\u001b[90m |\u001b[39m \u001b[36mimport\u001b[39m \u001b[32m\"@/components/ui/Button\"\u001b[39m\n\n\u001b[90m \u001b[39msrc/app\u001b[2m (require.context)\u001b[22m\n","filename":null,"targetModuleName":"@/components/ui/Button","originModulePath":"src/app/register.tsx"}
+{"_e":"metro:bundling:failed","_t":1786669798743,"id":null,"message":"Unable to resolve \"@/components/ui/Button\" from \"src/app/register.tsx\"\n 6 | import * as LocalAuthentication from 'expo-local-authentication';\n 7 | import * as SecureStore from 'expo-secure-store';\n> 8 | import { Button } from '@/components/ui/Button';\n | ^\n 9 | import { Input } from '@/components/ui/Input';\n 10 | import { Colors, Spacing, Typography } from '@/theme/tokens';\n 11 | import { useAuth } from '@/contexts/AuthContext';","importStack":"\u001b[1mImport stack:\u001b[22m\n\n\u001b[90m \u001b[39msrc/app/register.tsx\n\u001b[90m |\u001b[39m \u001b[36mimport\u001b[39m \u001b[32m\"@/components/ui/Button\"\u001b[39m\n\n\u001b[90m \u001b[39msrc/app\u001b[2m (require.context)\u001b[22m\n","filename":null,"targetModuleName":"@/components/ui/Button","originModulePath":"src/app/register.tsx"}
+{"_e":"metro:bundling:failed","_t":1786669798811,"id":null,"message":"Unable to resolve \"@/components/ui/Button\" from \"src/app/register.tsx\"\n 6 | import * as LocalAuthentication from 'expo-local-authentication';\n 7 | import * as SecureStore from 'expo-secure-store';\n> 8 | import { Button } from '@/components/ui/Button';\n | ^\n 9 | import { Input } from '@/components/ui/Input';\n 10 | import { Colors, Spacing, Typography } from '@/theme/tokens';\n 11 | import { useAuth } from '@/contexts/AuthContext';","importStack":"\u001b[1mImport stack:\u001b[22m\n\n\u001b[90m \u001b[39msrc/app/register.tsx\n\u001b[90m |\u001b[39m \u001b[36mimport\u001b[39m \u001b[32m\"@/components/ui/Button\"\u001b[39m\n\n\u001b[90m \u001b[39msrc/app\u001b[2m (require.context)\u001b[22m\n","filename":null,"targetModuleName":"@/components/ui/Button","originModulePath":"src/app/register.tsx"}
+{"_e":"metro:bundling:failed","_t":1786669800791,"id":null,"message":"Unable to resolve \"@/components/ui/Button\" from \"src/app/register.tsx\"\n 6 | import * as LocalAuthentication from 'expo-local-authentication';\n 7 | import * as SecureStore from 'expo-secure-store';\n> 8 | import { Button } from '@/components/ui/Button';\n | ^\n 9 | import { Input } from '@/components/ui/Input';\n 10 | import { Colors, Spacing, Typography } from '@/theme/tokens';\n 11 | import { useAuth } from '@/contexts/AuthContext';","importStack":"\u001b[1mImport stack:\u001b[22m\n\n\u001b[90m \u001b[39msrc/app/register.tsx\n\u001b[90m |\u001b[39m \u001b[36mimport\u001b[39m \u001b[32m\"@/components/ui/Button\"\u001b[39m\n\n\u001b[90m \u001b[39msrc/app\u001b[2m (require.context)\u001b[22m\n","filename":null,"targetModuleName":"@/components/ui/Button","originModulePath":"src/app/register.tsx"}
+{"_e":"metro:bundling:failed","_t":1786669802489,"id":null,"message":"Unable to resolve \"@/components/ui/Button\" from \"src/app/register.tsx\"\n 6 | import * as LocalAuthentication from 'expo-local-authentication';\n 7 | import * as SecureStore from 'expo-secure-store';\n> 8 | import { Button } from '@/components/ui/Button';\n | ^\n 9 | import { Input } from '@/components/ui/Input';\n 10 | import { Colors, Spacing, Typography } from '@/theme/tokens';\n 11 | import { useAuth } from '@/contexts/AuthContext';","importStack":"\u001b[1mImport stack:\u001b[22m\n\n\u001b[90m \u001b[39msrc/app/register.tsx\n\u001b[90m |\u001b[39m \u001b[36mimport\u001b[39m \u001b[32m\"@/components/ui/Button\"\u001b[39m\n\n\u001b[90m \u001b[39msrc/app\u001b[2m (require.context)\u001b[22m\n","filename":null,"targetModuleName":"@/components/ui/Button","originModulePath":"src/app/register.tsx"}
+{"_e":"metro:bundling:failed","_t":1786669803514,"id":null,"message":"Unable to resolve \"@/components/ui/Button\" from \"src/app/register.tsx\"\n 6 | import * as LocalAuthentication from 'expo-local-authentication';\n 7 | import * as SecureStore from 'expo-secure-store';\n> 8 | import { Button } from '@/components/ui/Button';\n | ^\n 9 | import { Input } from '@/components/ui/Input';\n 10 | import { Colors, Spacing, Typography } from '@/theme/tokens';\n 11 | import { useAuth } from '@/contexts/AuthContext';","importStack":"\u001b[1mImport stack:\u001b[22m\n\n\u001b[90m \u001b[39msrc/app/register.tsx\n\u001b[90m |\u001b[39m \u001b[36mimport\u001b[39m \u001b[32m\"@/components/ui/Button\"\u001b[39m\n\n\u001b[90m \u001b[39msrc/app\u001b[2m (require.context)\u001b[22m\n","filename":null,"targetModuleName":"@/components/ui/Button","originModulePath":"src/app/register.tsx"}
+{"_e":"metro:bundling:failed","_t":1786669803729,"id":null,"message":"Unable to resolve \"@/components/ui/Button\" from \"src/app/register.tsx\"\n 6 | import * as LocalAuthentication from 'expo-local-authentication';\n 7 | import * as SecureStore from 'expo-secure-store';\n> 8 | import { Button } from '@/components/ui/Button';\n | ^\n 9 | import { Input } from '@/components/ui/Input';\n 10 | import { Colors, Spacing, Typography } from '@/theme/tokens';\n 11 | import { useAuth } from '@/contexts/AuthContext';","importStack":"\u001b[1mImport stack:\u001b[22m\n\n\u001b[90m \u001b[39msrc/app/register.tsx\n\u001b[90m |\u001b[39m \u001b[36mimport\u001b[39m \u001b[32m\"@/components/ui/Button\"\u001b[39m\n\n\u001b[90m \u001b[39msrc/app\u001b[2m (require.context)\u001b[22m\n","filename":null,"targetModuleName":"@/components/ui/Button","originModulePath":"src/app/register.tsx"}
+{"_e":"metro:bundling:failed","_t":1786669805935,"id":null,"message":"Unable to resolve \"@/components/ui/Button\" from \"src/app/register.tsx\"\n 6 | import * as LocalAuthentication from 'expo-local-authentication';\n 7 | import * as SecureStore from 'expo-secure-store';\n> 8 | import { Button } from '@/components/ui/Button';\n | ^\n 9 | import { Input } from '@/components/ui/Input';\n 10 | import { Colors, Spacing, Typography } from '@/theme/tokens';\n 11 | import { useAuth } from '@/contexts/AuthContext';","importStack":"\u001b[1mImport stack:\u001b[22m\n\n\u001b[90m \u001b[39msrc/app/register.tsx\n\u001b[90m |\u001b[39m \u001b[36mimport\u001b[39m \u001b[32m\"@/components/ui/Button\"\u001b[39m\n\n\u001b[90m \u001b[39msrc/app\u001b[2m (require.context)\u001b[22m\n","filename":null,"targetModuleName":"@/components/ui/Button","originModulePath":"src/app/register.tsx"}
+{"_e":"metro:bundling:failed","_t":1786669899473,"id":null,"message":"Unable to resolve \"@expo/vector-icons\" from \"src/app/biometrics.tsx\"\n 4 | import * as SecureStore from 'expo-secure-store';\n 5 | import Animated, { FadeInDown, FadeInUp } from 'react-native-reanimated';\n> 6 | import { Feather } from '@expo/vector-icons';\n | ^\n 7 | import { useSafeAreaInsets } from 'react-native-safe-area-context';\n 8 | import { Button } from '@/components/ui/Button';\n 9 | import { Colors, Spacing, Typography, Radius } from '@/theme/tokens';","importStack":"\u001b[1mImport stack:\u001b[22m\n\n\u001b[90m \u001b[39msrc/app/biometrics.tsx\n\u001b[90m |\u001b[39m \u001b[36mimport\u001b[39m \u001b[32m\"@expo/vector-icons\"\u001b[39m\n\n\u001b[90m \u001b[39msrc/app\u001b[2m (require.context)\u001b[22m\n","filename":null,"targetModuleName":"@expo/vector-icons","originModulePath":"src/app/biometrics.tsx"}
+{"_e":"metro:bundling:failed","_t":1786669899505,"id":null,"message":"Unable to resolve \"@expo/vector-icons\" from \"src/app/biometrics.tsx\"\n 4 | import * as SecureStore from 'expo-secure-store';\n 5 | import Animated, { FadeInDown, FadeInUp } from 'react-native-reanimated';\n> 6 | import { Feather } from '@expo/vector-icons';\n | ^\n 7 | import { useSafeAreaInsets } from 'react-native-safe-area-context';\n 8 | import { Button } from '@/components/ui/Button';\n 9 | import { Colors, Spacing, Typography, Radius } from '@/theme/tokens';","importStack":"\u001b[1mImport stack:\u001b[22m\n\n\u001b[90m \u001b[39msrc/app/biometrics.tsx\n\u001b[90m |\u001b[39m \u001b[36mimport\u001b[39m \u001b[32m\"@expo/vector-icons\"\u001b[39m\n\n\u001b[90m \u001b[39msrc/app\u001b[2m (require.context)\u001b[22m\n","filename":null,"targetModuleName":"@expo/vector-icons","originModulePath":"src/app/biometrics.tsx"}
+{"_e":"metro:bundling:failed","_t":1786669900463,"id":null,"message":"Unable to resolve \"@expo/vector-icons\" from \"src/app/biometrics.tsx\"\n 4 | import * as SecureStore from 'expo-secure-store';\n 5 | import Animated, { FadeInDown, FadeInUp } from 'react-native-reanimated';\n> 6 | import { Feather } from '@expo/vector-icons';\n | ^\n 7 | import { useSafeAreaInsets } from 'react-native-safe-area-context';\n 8 | import { Button } from '@/components/ui/Button';\n 9 | import { Colors, Spacing, Typography, Radius } from '@/theme/tokens';","importStack":"\u001b[1mImport stack:\u001b[22m\n\n\u001b[90m \u001b[39msrc/app/biometrics.tsx\n\u001b[90m |\u001b[39m \u001b[36mimport\u001b[39m \u001b[32m\"@expo/vector-icons\"\u001b[39m\n\n\u001b[90m \u001b[39msrc/app\u001b[2m (require.context)\u001b[22m\n","filename":null,"targetModuleName":"@expo/vector-icons","originModulePath":"src/app/biometrics.tsx"}
+{"_e":"metro:bundling:failed","_t":1786669900710,"id":null,"message":"Unable to resolve \"@expo/vector-icons\" from \"src/app/biometrics.tsx\"\n 4 | import * as SecureStore from 'expo-secure-store';\n 5 | import Animated, { FadeInDown, FadeInUp } from 'react-native-reanimated';\n> 6 | import { Feather } from '@expo/vector-icons';\n | ^\n 7 | import { useSafeAreaInsets } from 'react-native-safe-area-context';\n 8 | import { Button } from '@/components/ui/Button';\n 9 | import { Colors, Spacing, Typography, Radius } from '@/theme/tokens';","importStack":"\u001b[1mImport stack:\u001b[22m\n\n\u001b[90m \u001b[39msrc/app/biometrics.tsx\n\u001b[90m |\u001b[39m \u001b[36mimport\u001b[39m \u001b[32m\"@expo/vector-icons\"\u001b[39m\n\n\u001b[90m \u001b[39msrc/app\u001b[2m (require.context)\u001b[22m\n","filename":null,"targetModuleName":"@expo/vector-icons","originModulePath":"src/app/biometrics.tsx"}
+{"_e":"metro:bundling:failed","_t":1786669902722,"id":null,"message":"Unable to resolve \"@expo/vector-icons\" from \"src/app/biometrics.tsx\"\n 4 | import * as SecureStore from 'expo-secure-store';\n 5 | import Animated, { FadeInDown, FadeInUp } from 'react-native-reanimated';\n> 6 | import { Feather } from '@expo/vector-icons';\n | ^\n 7 | import { useSafeAreaInsets } from 'react-native-safe-area-context';\n 8 | import { Button } from '@/components/ui/Button';\n 9 | import { Colors, Spacing, Typography, Radius } from '@/theme/tokens';","importStack":"\u001b[1mImport stack:\u001b[22m\n\n\u001b[90m \u001b[39msrc/app/biometrics.tsx\n\u001b[90m |\u001b[39m \u001b[36mimport\u001b[39m \u001b[32m\"@expo/vector-icons\"\u001b[39m\n\n\u001b[90m \u001b[39msrc/app\u001b[2m (require.context)\u001b[22m\n","filename":null,"targetModuleName":"@expo/vector-icons","originModulePath":"src/app/biometrics.tsx"}
+{"_e":"metro:bundling:failed","_t":1786669903744,"id":null,"message":"Unable to resolve \"@expo/vector-icons\" from \"src/app/biometrics.tsx\"\n 4 | import * as SecureStore from 'expo-secure-store';\n 5 | import Animated, { FadeInDown, FadeInUp } from 'react-native-reanimated';\n> 6 | import { Feather } from '@expo/vector-icons';\n | ^\n 7 | import { useSafeAreaInsets } from 'react-native-safe-area-context';\n 8 | import { Button } from '@/components/ui/Button';\n 9 | import { Colors, Spacing, Typography, Radius } from '@/theme/tokens';","importStack":"\u001b[1mImport stack:\u001b[22m\n\n\u001b[90m \u001b[39msrc/app/biometrics.tsx\n\u001b[90m |\u001b[39m \u001b[36mimport\u001b[39m \u001b[32m\"@expo/vector-icons\"\u001b[39m\n\n\u001b[90m \u001b[39msrc/app\u001b[2m (require.context)\u001b[22m\n","filename":null,"targetModuleName":"@expo/vector-icons","originModulePath":"src/app/biometrics.tsx"}
+{"_e":"metro:bundling:failed","_t":1786669903990,"id":null,"message":"Unable to resolve \"@expo/vector-icons\" from \"src/app/biometrics.tsx\"\n 4 | import * as SecureStore from 'expo-secure-store';\n 5 | import Animated, { FadeInDown, FadeInUp } from 'react-native-reanimated';\n> 6 | import { Feather } from '@expo/vector-icons';\n | ^\n 7 | import { useSafeAreaInsets } from 'react-native-safe-area-context';\n 8 | import { Button } from '@/components/ui/Button';\n 9 | import { Colors, Spacing, Typography, Radius } from '@/theme/tokens';","importStack":"\u001b[1mImport stack:\u001b[22m\n\n\u001b[90m \u001b[39msrc/app/biometrics.tsx\n\u001b[90m |\u001b[39m \u001b[36mimport\u001b[39m \u001b[32m\"@expo/vector-icons\"\u001b[39m\n\n\u001b[90m \u001b[39msrc/app\u001b[2m (require.context)\u001b[22m\n","filename":null,"targetModuleName":"@expo/vector-icons","originModulePath":"src/app/biometrics.tsx"}
+{"_e":"metro:bundling:failed","_t":1786669905934,"id":null,"message":"Unable to resolve \"@expo/vector-icons\" from \"src/app/biometrics.tsx\"\n 4 | import * as SecureStore from 'expo-secure-store';\n 5 | import Animated, { FadeInDown, FadeInUp } from 'react-native-reanimated';\n> 6 | import { Feather } from '@expo/vector-icons';\n | ^\n 7 | import { useSafeAreaInsets } from 'react-native-safe-area-context';\n 8 | import { Button } from '@/components/ui/Button';\n 9 | import { Colors, Spacing, Typography, Radius } from '@/theme/tokens';","importStack":"\u001b[1mImport stack:\u001b[22m\n\n\u001b[90m \u001b[39msrc/app/biometrics.tsx\n\u001b[90m |\u001b[39m \u001b[36mimport\u001b[39m \u001b[32m\"@expo/vector-icons\"\u001b[39m\n\n\u001b[90m \u001b[39msrc/app\u001b[2m (require.context)\u001b[22m\n","filename":null,"targetModuleName":"@expo/vector-icons","originModulePath":"src/app/biometrics.tsx"}
+{"_e":"metro:bundling:failed","_t":1786669908904,"id":null,"message":"Unable to resolve \"@expo/vector-icons\" from \"src/app/biometrics.tsx\"\n 4 | import * as SecureStore from 'expo-secure-store';\n 5 | import Animated, { FadeInDown, FadeInUp } from 'react-native-reanimated';\n> 6 | import { Feather } from '@expo/vector-icons';\n | ^\n 7 | import { useSafeAreaInsets } from 'react-native-safe-area-context';\n 8 | import { Button } from '@/components/ui/button';\n 9 | import { Colors, Spacing, Typography, Radius } from '@/constants/theme';","importStack":"\u001b[1mImport stack:\u001b[22m\n\n\u001b[90m \u001b[39msrc/app/biometrics.tsx\n\u001b[90m |\u001b[39m \u001b[36mimport\u001b[39m \u001b[32m\"@expo/vector-icons\"\u001b[39m\n\n\u001b[90m \u001b[39msrc/app\u001b[2m (require.context)\u001b[22m\n","filename":null,"targetModuleName":"@expo/vector-icons","originModulePath":"src/app/biometrics.tsx"}
+{"_e":"metro:bundling:failed","_t":1786669908912,"id":null,"message":"Unable to resolve \"@expo/vector-icons\" from \"src/app/biometrics.tsx\"\n 4 | import * as SecureStore from 'expo-secure-store';\n 5 | import Animated, { FadeInDown, FadeInUp } from 'react-native-reanimated';\n> 6 | import { Feather } from '@expo/vector-icons';\n | ^\n 7 | import { useSafeAreaInsets } from 'react-native-safe-area-context';\n 8 | import { Button } from '@/components/ui/button';\n 9 | import { Colors, Spacing, Typography, Radius } from '@/constants/theme';","importStack":"\u001b[1mImport stack:\u001b[22m\n\n\u001b[90m \u001b[39msrc/app/biometrics.tsx\n\u001b[90m |\u001b[39m \u001b[36mimport\u001b[39m \u001b[32m\"@expo/vector-icons\"\u001b[39m\n\n\u001b[90m \u001b[39msrc/app\u001b[2m (require.context)\u001b[22m\n","filename":null,"targetModuleName":"@expo/vector-icons","originModulePath":"src/app/biometrics.tsx"}
+{"_e":"metro:bundling:failed","_t":1786669909961,"id":null,"message":"Unable to resolve \"@expo/vector-icons\" from \"src/app/biometrics.tsx\"\n 4 | import * as SecureStore from 'expo-secure-store';\n 5 | import Animated, { FadeInDown, FadeInUp } from 'react-native-reanimated';\n> 6 | import { Feather } from '@expo/vector-icons';\n | ^\n 7 | import { useSafeAreaInsets } from 'react-native-safe-area-context';\n 8 | import { Button } from '@/components/ui/button';\n 9 | import { Colors, Spacing, Typography, Radius } from '@/constants/theme';","importStack":"\u001b[1mImport stack:\u001b[22m\n\n\u001b[90m \u001b[39msrc/app/biometrics.tsx\n\u001b[90m |\u001b[39m \u001b[36mimport\u001b[39m \u001b[32m\"@expo/vector-icons\"\u001b[39m\n\n\u001b[90m \u001b[39msrc/app\u001b[2m (require.context)\u001b[22m\n","filename":null,"targetModuleName":"@expo/vector-icons","originModulePath":"src/app/biometrics.tsx"}
+{"_e":"metro:bundling:failed","_t":1786669910484,"id":null,"message":"Unable to resolve \"@expo/vector-icons\" from \"src/app/biometrics.tsx\"\n 4 | import * as SecureStore from 'expo-secure-store';\n 5 | import Animated, { FadeInDown, FadeInUp } from 'react-native-reanimated';\n> 6 | import { Feather } from '@expo/vector-icons';\n | ^\n 7 | import { useSafeAreaInsets } from 'react-native-safe-area-context';\n 8 | import { Button } from '@/components/ui/button';\n 9 | import { Colors, Spacing, Typography, Radius } from '@/constants/theme';","importStack":"\u001b[1mImport stack:\u001b[22m\n\n\u001b[90m \u001b[39msrc/app/biometrics.tsx\n\u001b[90m |\u001b[39m \u001b[36mimport\u001b[39m \u001b[32m\"@expo/vector-icons\"\u001b[39m\n\n\u001b[90m \u001b[39msrc/app\u001b[2m (require.context)\u001b[22m\n","filename":null,"targetModuleName":"@expo/vector-icons","originModulePath":"src/app/biometrics.tsx"}
+{"_e":"metro:bundling:failed","_t":1786669912137,"id":null,"message":"Unable to resolve \"@expo/vector-icons\" from \"src/app/biometrics.tsx\"\n 4 | import * as SecureStore from 'expo-secure-store';\n 5 | import Animated, { FadeInDown, FadeInUp } from 'react-native-reanimated';\n> 6 | import { Feather } from '@expo/vector-icons';\n | ^\n 7 | import { useSafeAreaInsets } from 'react-native-safe-area-context';\n 8 | import { Button } from '@/components/ui/button';\n 9 | import { Colors, Spacing, Typography, Radius } from '@/constants/theme';","importStack":"\u001b[1mImport stack:\u001b[22m\n\n\u001b[90m \u001b[39msrc/app/biometrics.tsx\n\u001b[90m |\u001b[39m \u001b[36mimport\u001b[39m \u001b[32m\"@expo/vector-icons\"\u001b[39m\n\n\u001b[90m \u001b[39msrc/app\u001b[2m (require.context)\u001b[22m\n","filename":null,"targetModuleName":"@expo/vector-icons","originModulePath":"src/app/biometrics.tsx"}
+{"_e":"metro:bundling:failed","_t":1786669913157,"id":null,"message":"Unable to resolve \"@expo/vector-icons\" from \"src/app/biometrics.tsx\"\n 4 | import * as SecureStore from 'expo-secure-store';\n 5 | import Animated, { FadeInDown, FadeInUp } from 'react-native-reanimated';\n> 6 | import { Feather } from '@expo/vector-icons';\n | ^\n 7 | import { useSafeAreaInsets } from 'react-native-safe-area-context';\n 8 | import { Button } from '@/components/ui/button';\n 9 | import { Colors, Spacing, Typography, Radius } from '@/constants/theme';","importStack":"\u001b[1mImport stack:\u001b[22m\n\n\u001b[90m \u001b[39msrc/app/biometrics.tsx\n\u001b[90m |\u001b[39m \u001b[36mimport\u001b[39m \u001b[32m\"@expo/vector-icons\"\u001b[39m\n\n\u001b[90m \u001b[39msrc/app\u001b[2m (require.context)\u001b[22m\n","filename":null,"targetModuleName":"@expo/vector-icons","originModulePath":"src/app/biometrics.tsx"}
+{"_e":"metro:bundling:failed","_t":1786669913462,"id":null,"message":"Unable to resolve \"@expo/vector-icons\" from \"src/app/biometrics.tsx\"\n 4 | import * as SecureStore from 'expo-secure-store';\n 5 | import Animated, { FadeInDown, FadeInUp } from 'react-native-reanimated';\n> 6 | import { Feather } from '@expo/vector-icons';\n | ^\n 7 | import { useSafeAreaInsets } from 'react-native-safe-area-context';\n 8 | import { Button } from '@/components/ui/button';\n 9 | import { Colors, Spacing, Typography, Radius } from '@/constants/theme';","importStack":"\u001b[1mImport stack:\u001b[22m\n\n\u001b[90m \u001b[39msrc/app/biometrics.tsx\n\u001b[90m |\u001b[39m \u001b[36mimport\u001b[39m \u001b[32m\"@expo/vector-icons\"\u001b[39m\n\n\u001b[90m \u001b[39msrc/app\u001b[2m (require.context)\u001b[22m\n","filename":null,"targetModuleName":"@expo/vector-icons","originModulePath":"src/app/biometrics.tsx"}
+{"_e":"metro:bundling:failed","_t":1786669915844,"id":null,"message":"Unable to resolve \"@expo/vector-icons\" from \"src/app/biometrics.tsx\"\n 4 | import * as SecureStore from 'expo-secure-store';\n 5 | import Animated, { FadeInDown, FadeInUp } from 'react-native-reanimated';\n> 6 | import { Feather } from '@expo/vector-icons';\n | ^\n 7 | import { useSafeAreaInsets } from 'react-native-safe-area-context';\n 8 | import { Button } from '@/components/ui/button';\n 9 | import { Colors, Spacing, Typography, Radius } from '@/constants/theme';","importStack":"\u001b[1mImport stack:\u001b[22m\n\n\u001b[90m \u001b[39msrc/app/biometrics.tsx\n\u001b[90m |\u001b[39m \u001b[36mimport\u001b[39m \u001b[32m\"@expo/vector-icons\"\u001b[39m\n\n\u001b[90m \u001b[39msrc/app\u001b[2m (require.context)\u001b[22m\n","filename":null,"targetModuleName":"@expo/vector-icons","originModulePath":"src/app/biometrics.tsx"}
+{"_e":"metro:bundling:failed","_t":1786669925595,"id":null,"message":"Unable to resolve \"@expo/vector-icons\" from \"src/app/biometrics.tsx\"\n 4 | import * as SecureStore from 'expo-secure-store';\n 5 | import Animated, { FadeInDown, FadeInUp } from 'react-native-reanimated';\n> 6 | import { Feather } from '@expo/vector-icons';\n | ^\n 7 | import { useSafeAreaInsets } from 'react-native-safe-area-context';\n 8 | import { Button } from '@/components/ui/button';\n 9 | import { Colors, Spacing, Typography, Radius } from '@/constants/theme';","importStack":"\u001b[1mImport stack:\u001b[22m\n\n\u001b[90m \u001b[39msrc/app/biometrics.tsx\n\u001b[90m |\u001b[39m \u001b[36mimport\u001b[39m \u001b[32m\"@expo/vector-icons\"\u001b[39m\n\n\u001b[90m \u001b[39msrc/app\u001b[2m (require.context)\u001b[22m\n","filename":null,"targetModuleName":"@expo/vector-icons","originModulePath":"src/app/biometrics.tsx"}
+{"_e":"metro:bundling:failed","_t":1786669925927,"id":null,"message":"Unable to resolve \"@expo/vector-icons\" from \"src/app/biometrics.tsx\"\n 4 | import * as SecureStore from 'expo-secure-store';\n 5 | import Animated, { FadeInDown, FadeInUp } from 'react-native-reanimated';\n> 6 | import { Feather } from '@expo/vector-icons';\n | ^\n 7 | import { useSafeAreaInsets } from 'react-native-safe-area-context';\n 8 | import { Button } from '@/components/ui/button';\n 9 | import { Colors, Spacing, Typography, Radius } from '@/constants/theme';","importStack":"\u001b[1mImport stack:\u001b[22m\n\n\u001b[90m \u001b[39msrc/app/biometrics.tsx\n\u001b[90m |\u001b[39m \u001b[36mimport\u001b[39m \u001b[32m\"@expo/vector-icons\"\u001b[39m\n\n\u001b[90m \u001b[39msrc/app\u001b[2m (require.context)\u001b[22m\n","filename":null,"targetModuleName":"@expo/vector-icons","originModulePath":"src/app/biometrics.tsx"}
+{"_e":"metro:bundling:failed","_t":1786669926214,"id":null,"message":"Unable to resolve \"@expo/vector-icons\" from \"src/app/biometrics.tsx\"\n 4 | import * as SecureStore from 'expo-secure-store';\n 5 | import Animated, { FadeInDown, FadeInUp } from 'react-native-reanimated';\n> 6 | import { Feather } from '@expo/vector-icons';\n | ^\n 7 | import { useSafeAreaInsets } from 'react-native-safe-area-context';\n 8 | import { Button } from '@/components/ui/button';\n 9 | import { Colors, Spacing, Typography, Radius } from '@/constants/theme';","importStack":"\u001b[1mImport stack:\u001b[22m\n\n\u001b[90m \u001b[39msrc/app/biometrics.tsx\n\u001b[90m |\u001b[39m \u001b[36mimport\u001b[39m \u001b[32m\"@expo/vector-icons\"\u001b[39m\n\n\u001b[90m \u001b[39msrc/app\u001b[2m (require.context)\u001b[22m\n","filename":null,"targetModuleName":"@expo/vector-icons","originModulePath":"src/app/biometrics.tsx"}
+{"_e":"metro:bundling:failed","_t":1786669926797,"id":null,"message":"Unable to resolve \"@expo/vector-icons\" from \"src/app/biometrics.tsx\"\n 4 | import * as SecureStore from 'expo-secure-store';\n 5 | import Animated, { FadeInDown, FadeInUp } from 'react-native-reanimated';\n> 6 | import { Feather } from '@expo/vector-icons';\n | ^\n 7 | import { useSafeAreaInsets } from 'react-native-safe-area-context';\n 8 | import { Button } from '@/components/ui/button';\n 9 | import { Colors, Spacing, Typography, Radius } from '@/constants/theme';","importStack":"\u001b[1mImport stack:\u001b[22m\n\n\u001b[90m \u001b[39msrc/app/biometrics.tsx\n\u001b[90m |\u001b[39m \u001b[36mimport\u001b[39m \u001b[32m\"@expo/vector-icons\"\u001b[39m\n\n\u001b[90m \u001b[39msrc/app\u001b[2m (require.context)\u001b[22m\n","filename":null,"targetModuleName":"@expo/vector-icons","originModulePath":"src/app/biometrics.tsx"}
+{"_e":"metro:bundling:failed","_t":1786669927334,"id":null,"message":"Unable to resolve \"@expo/vector-icons\" from \"src/app/biometrics.tsx\"\n 4 | import * as SecureStore from 'expo-secure-store';\n 5 | import Animated, { FadeInDown, FadeInUp } from 'react-native-reanimated';\n> 6 | import { Feather } from '@expo/vector-icons';\n | ^\n 7 | import { useSafeAreaInsets } from 'react-native-safe-area-context';\n 8 | import { Button } from '@/components/ui/button';\n 9 | import { Colors, Spacing, Typography, Radius } from '@/constants/theme';","importStack":"\u001b[1mImport stack:\u001b[22m\n\n\u001b[90m \u001b[39msrc/app/biometrics.tsx\n\u001b[90m |\u001b[39m \u001b[36mimport\u001b[39m \u001b[32m\"@expo/vector-icons\"\u001b[39m\n\n\u001b[90m \u001b[39msrc/app\u001b[2m (require.context)\u001b[22m\n","filename":null,"targetModuleName":"@expo/vector-icons","originModulePath":"src/app/biometrics.tsx"}
+{"_e":"metro:bundling:failed","_t":1786669927726,"id":null,"message":"Unable to resolve \"@expo/vector-icons\" from \"src/app/biometrics.tsx\"\n 4 | import * as SecureStore from 'expo-secure-store';\n 5 | import Animated, { FadeInDown, FadeInUp } from 'react-native-reanimated';\n> 6 | import { Feather } from '@expo/vector-icons';\n | ^\n 7 | import { useSafeAreaInsets } from 'react-native-safe-area-context';\n 8 | import { Button } from '@/components/ui/button';\n 9 | import { Colors, Spacing, Typography, Radius } from '@/constants/theme';","importStack":"\u001b[1mImport stack:\u001b[22m\n\n\u001b[90m \u001b[39msrc/app/biometrics.tsx\n\u001b[90m |\u001b[39m \u001b[36mimport\u001b[39m \u001b[32m\"@expo/vector-icons\"\u001b[39m\n\n\u001b[90m \u001b[39msrc/app\u001b[2m (require.context)\u001b[22m\n","filename":null,"targetModuleName":"@expo/vector-icons","originModulePath":"src/app/biometrics.tsx"}
+{"_e":"metro:bundling:failed","_t":1786669928054,"id":null,"message":"Unable to resolve \"@expo/vector-icons\" from \"src/app/biometrics.tsx\"\n 4 | import * as SecureStore from 'expo-secure-store';\n 5 | import Animated, { FadeInDown, FadeInUp } from 'react-native-reanimated';\n> 6 | import { Feather } from '@expo/vector-icons';\n | ^\n 7 | import { useSafeAreaInsets } from 'react-native-safe-area-context';\n 8 | import { Button } from '@/components/ui/button';\n 9 | import { Colors, Spacing, Typography, Radius } from '@/constants/theme';","importStack":"\u001b[1mImport stack:\u001b[22m\n\n\u001b[90m \u001b[39msrc/app/biometrics.tsx\n\u001b[90m |\u001b[39m \u001b[36mimport\u001b[39m \u001b[32m\"@expo/vector-icons\"\u001b[39m\n\n\u001b[90m \u001b[39msrc/app\u001b[2m (require.context)\u001b[22m\n","filename":null,"targetModuleName":"@expo/vector-icons","originModulePath":"src/app/biometrics.tsx"}
+{"_e":"metro:bundling:failed","_t":1786669928316,"id":null,"message":"Unable to resolve \"@expo/vector-icons\" from \"src/app/biometrics.tsx\"\n 4 | import * as SecureStore from 'expo-secure-store';\n 5 | import Animated, { FadeInDown, FadeInUp } from 'react-native-reanimated';\n> 6 | import { Feather } from '@expo/vector-icons';\n | ^\n 7 | import { useSafeAreaInsets } from 'react-native-safe-area-context';\n 8 | import { Button } from '@/components/ui/button';\n 9 | import { Colors, Spacing, Typography, Radius } from '@/constants/theme';","importStack":"\u001b[1mImport stack:\u001b[22m\n\n\u001b[90m \u001b[39msrc/app/biometrics.tsx\n\u001b[90m |\u001b[39m \u001b[36mimport\u001b[39m \u001b[32m\"@expo/vector-icons\"\u001b[39m\n\n\u001b[90m \u001b[39msrc/app\u001b[2m (require.context)\u001b[22m\n","filename":null,"targetModuleName":"@expo/vector-icons","originModulePath":"src/app/biometrics.tsx"}
+{"_e":"metro:bundling:failed","_t":1786669928604,"id":null,"message":"Unable to resolve \"@expo/vector-icons\" from \"src/app/biometrics.tsx\"\n 4 | import * as SecureStore from 'expo-secure-store';\n 5 | import Animated, { FadeInDown, FadeInUp } from 'react-native-reanimated';\n> 6 | import { Feather } from '@expo/vector-icons';\n | ^\n 7 | import { useSafeAreaInsets } from 'react-native-safe-area-context';\n 8 | import { Button } from '@/components/ui/button';\n 9 | import { Colors, Spacing, Typography, Radius } from '@/constants/theme';","importStack":"\u001b[1mImport stack:\u001b[22m\n\n\u001b[90m \u001b[39msrc/app/biometrics.tsx\n\u001b[90m |\u001b[39m \u001b[36mimport\u001b[39m \u001b[32m\"@expo/vector-icons\"\u001b[39m\n\n\u001b[90m \u001b[39msrc/app\u001b[2m (require.context)\u001b[22m\n","filename":null,"targetModuleName":"@expo/vector-icons","originModulePath":"src/app/biometrics.tsx"}
+{"_e":"metro:bundling:failed","_t":1786669928857,"id":null,"message":"Unable to resolve \"@expo/vector-icons\" from \"src/app/biometrics.tsx\"\n 4 | import * as SecureStore from 'expo-secure-store';\n 5 | import Animated, { FadeInDown, FadeInUp } from 'react-native-reanimated';\n> 6 | import { Feather } from '@expo/vector-icons';\n | ^\n 7 | import { useSafeAreaInsets } from 'react-native-safe-area-context';\n 8 | import { Button } from '@/components/ui/button';\n 9 | import { Colors, Spacing, Typography, Radius } from '@/constants/theme';","importStack":"\u001b[1mImport stack:\u001b[22m\n\n\u001b[90m \u001b[39msrc/app/biometrics.tsx\n\u001b[90m |\u001b[39m \u001b[36mimport\u001b[39m \u001b[32m\"@expo/vector-icons\"\u001b[39m\n\n\u001b[90m \u001b[39msrc/app\u001b[2m (require.context)\u001b[22m\n","filename":null,"targetModuleName":"@expo/vector-icons","originModulePath":"src/app/biometrics.tsx"}
+{"_e":"metro:bundling:failed","_t":1786669929052,"id":null,"message":"Unable to resolve \"@expo/vector-icons\" from \"src/app/biometrics.tsx\"\n 4 | import * as SecureStore from 'expo-secure-store';\n 5 | import Animated, { FadeInDown, FadeInUp } from 'react-native-reanimated';\n> 6 | import { Feather } from '@expo/vector-icons';\n | ^\n 7 | import { useSafeAreaInsets } from 'react-native-safe-area-context';\n 8 | import { Button } from '@/components/ui/button';\n 9 | import { Colors, Spacing, Typography, Radius } from '@/constants/theme';","importStack":"\u001b[1mImport stack:\u001b[22m\n\n\u001b[90m \u001b[39msrc/app/biometrics.tsx\n\u001b[90m |\u001b[39m \u001b[36mimport\u001b[39m \u001b[32m\"@expo/vector-icons\"\u001b[39m\n\n\u001b[90m \u001b[39msrc/app\u001b[2m (require.context)\u001b[22m\n","filename":null,"targetModuleName":"@expo/vector-icons","originModulePath":"src/app/biometrics.tsx"}
+{"_e":"metro:bundling:failed","_t":1786669929341,"id":null,"message":"Unable to resolve \"@expo/vector-icons\" from \"src/app/biometrics.tsx\"\n 4 | import * as SecureStore from 'expo-secure-store';\n 5 | import Animated, { FadeInDown, FadeInUp } from 'react-native-reanimated';\n> 6 | import { Feather } from '@expo/vector-icons';\n | ^\n 7 | import { useSafeAreaInsets } from 'react-native-safe-area-context';\n 8 | import { Button } from '@/components/ui/button';\n 9 | import { Colors, Spacing, Typography, Radius } from '@/constants/theme';","importStack":"\u001b[1mImport stack:\u001b[22m\n\n\u001b[90m \u001b[39msrc/app/biometrics.tsx\n\u001b[90m |\u001b[39m \u001b[36mimport\u001b[39m \u001b[32m\"@expo/vector-icons\"\u001b[39m\n\n\u001b[90m \u001b[39msrc/app\u001b[2m (require.context)\u001b[22m\n","filename":null,"targetModuleName":"@expo/vector-icons","originModulePath":"src/app/biometrics.tsx"}
+{"_e":"metro:bundling:failed","_t":1786669930964,"id":null,"message":"Unable to resolve \"@expo/vector-icons\" from \"src/app/biometrics.tsx\"\n 4 | import * as SecureStore from 'expo-secure-store';\n 5 | import Animated, { FadeInDown, FadeInUp } from 'react-native-reanimated';\n> 6 | import { Feather } from '@expo/vector-icons';\n | ^\n 7 | import { useSafeAreaInsets } from 'react-native-safe-area-context';\n 8 | import { Button } from '@/components/ui/button';\n 9 | import { Colors, Spacing, Typography, Radius } from '@/constants/theme';","importStack":"\u001b[1mImport stack:\u001b[22m\n\n\u001b[90m \u001b[39msrc/app/biometrics.tsx\n\u001b[90m |\u001b[39m \u001b[36mimport\u001b[39m \u001b[32m\"@expo/vector-icons\"\u001b[39m\n\n\u001b[90m \u001b[39msrc/app\u001b[2m (require.context)\u001b[22m\n","filename":null,"targetModuleName":"@expo/vector-icons","originModulePath":"src/app/biometrics.tsx"}
+{"_e":"metro:bundling:failed","_t":1786669931335,"id":null,"message":"Unable to resolve \"@expo/vector-icons\" from \"src/app/biometrics.tsx\"\n 4 | import * as SecureStore from 'expo-secure-store';\n 5 | import Animated, { FadeInDown, FadeInUp } from 'react-native-reanimated';\n> 6 | import { Feather } from '@expo/vector-icons';\n | ^\n 7 | import { useSafeAreaInsets } from 'react-native-safe-area-context';\n 8 | import { Button } from '@/components/ui/button';\n 9 | import { Colors, Spacing, Typography, Radius } from '@/constants/theme';","importStack":"\u001b[1mImport stack:\u001b[22m\n\n\u001b[90m \u001b[39msrc/app/biometrics.tsx\n\u001b[90m |\u001b[39m \u001b[36mimport\u001b[39m \u001b[32m\"@expo/vector-icons\"\u001b[39m\n\n\u001b[90m \u001b[39msrc/app\u001b[2m (require.context)\u001b[22m\n","filename":null,"targetModuleName":"@expo/vector-icons","originModulePath":"src/app/biometrics.tsx"}
+{"_e":"metro:bundling:failed","_t":1786669935249,"id":null,"message":"Unable to resolve \"@expo/vector-icons\" from \"src/app/biometrics.tsx\"\n 4 | import * as SecureStore from 'expo-secure-store';\n 5 | import Animated, { FadeInDown, FadeInUp } from 'react-native-reanimated';\n> 6 | import { Feather } from '@expo/vector-icons';\n | ^\n 7 | import { useSafeAreaInsets } from 'react-native-safe-area-context';\n 8 | import { Button } from '@/components/ui/button';\n 9 | import { Colors, Spacing, Typography, Radius } from '@/constants/theme';","importStack":"\u001b[1mImport stack:\u001b[22m\n\n\u001b[90m \u001b[39msrc/app/biometrics.tsx\n\u001b[90m |\u001b[39m \u001b[36mimport\u001b[39m \u001b[32m\"@expo/vector-icons\"\u001b[39m\n\n\u001b[90m \u001b[39msrc/app\u001b[2m (require.context)\u001b[22m\n","filename":null,"targetModuleName":"@expo/vector-icons","originModulePath":"src/app/biometrics.tsx"}
+{"_e":"metro:bundling:failed","_t":1786669935571,"id":null,"message":"Unable to resolve \"@expo/vector-icons\" from \"src/app/biometrics.tsx\"\n 4 | import * as SecureStore from 'expo-secure-store';\n 5 | import Animated, { FadeInDown, FadeInUp } from 'react-native-reanimated';\n> 6 | import { Feather } from '@expo/vector-icons';\n | ^\n 7 | import { useSafeAreaInsets } from 'react-native-safe-area-context';\n 8 | import { Button } from '@/components/ui/button';\n 9 | import { Colors, Spacing, Typography, Radius } from '@/constants/theme';","importStack":"\u001b[1mImport stack:\u001b[22m\n\n\u001b[90m \u001b[39msrc/app/biometrics.tsx\n\u001b[90m |\u001b[39m \u001b[36mimport\u001b[39m \u001b[32m\"@expo/vector-icons\"\u001b[39m\n\n\u001b[90m \u001b[39msrc/app\u001b[2m (require.context)\u001b[22m\n","filename":null,"targetModuleName":"@expo/vector-icons","originModulePath":"src/app/biometrics.tsx"}
+{"_e":"metro:bundling:failed","_t":1786669935804,"id":null,"message":"Unable to resolve \"@expo/vector-icons\" from \"src/app/biometrics.tsx\"\n 4 | import * as SecureStore from 'expo-secure-store';\n 5 | import Animated, { FadeInDown, FadeInUp } from 'react-native-reanimated';\n> 6 | import { Feather } from '@expo/vector-icons';\n | ^\n 7 | import { useSafeAreaInsets } from 'react-native-safe-area-context';\n 8 | import { Button } from '@/components/ui/button';\n 9 | import { Colors, Spacing, Typography, Radius } from '@/constants/theme';","importStack":"\u001b[1mImport stack:\u001b[22m\n\n\u001b[90m \u001b[39msrc/app/biometrics.tsx\n\u001b[90m |\u001b[39m \u001b[36mimport\u001b[39m \u001b[32m\"@expo/vector-icons\"\u001b[39m\n\n\u001b[90m \u001b[39msrc/app\u001b[2m (require.context)\u001b[22m\n","filename":null,"targetModuleName":"@expo/vector-icons","originModulePath":"src/app/biometrics.tsx"}
+{"_e":"metro:bundling:failed","_t":1786669936061,"id":null,"message":"Unable to resolve \"@expo/vector-icons\" from \"src/app/biometrics.tsx\"\n 4 | import * as SecureStore from 'expo-secure-store';\n 5 | import Animated, { FadeInDown, FadeInUp } from 'react-native-reanimated';\n> 6 | import { Feather } from '@expo/vector-icons';\n | ^\n 7 | import { useSafeAreaInsets } from 'react-native-safe-area-context';\n 8 | import { Button } from '@/components/ui/button';\n 9 | import { Colors, Spacing, Typography, Radius } from '@/constants/theme';","importStack":"\u001b[1mImport stack:\u001b[22m\n\n\u001b[90m \u001b[39msrc/app/biometrics.tsx\n\u001b[90m |\u001b[39m \u001b[36mimport\u001b[39m \u001b[32m\"@expo/vector-icons\"\u001b[39m\n\n\u001b[90m \u001b[39msrc/app\u001b[2m (require.context)\u001b[22m\n","filename":null,"targetModuleName":"@expo/vector-icons","originModulePath":"src/app/biometrics.tsx"}
+{"_e":"metro:bundling:failed","_t":1786669936572,"id":null,"message":"Unable to resolve \"@expo/vector-icons\" from \"src/app/biometrics.tsx\"\n 4 | import * as SecureStore from 'expo-secure-store';\n 5 | import Animated, { FadeInDown, FadeInUp } from 'react-native-reanimated';\n> 6 | import { Feather } from '@expo/vector-icons';\n | ^\n 7 | import { useSafeAreaInsets } from 'react-native-safe-area-context';\n 8 | import { Button } from '@/components/ui/button';\n 9 | import { Colors, Spacing, Typography, Radius } from '@/constants/theme';","importStack":"\u001b[1mImport stack:\u001b[22m\n\n\u001b[90m \u001b[39msrc/app/biometrics.tsx\n\u001b[90m |\u001b[39m \u001b[36mimport\u001b[39m \u001b[32m\"@expo/vector-icons\"\u001b[39m\n\n\u001b[90m \u001b[39msrc/app\u001b[2m (require.context)\u001b[22m\n","filename":null,"targetModuleName":"@expo/vector-icons","originModulePath":"src/app/biometrics.tsx"}
+{"_e":"metro:bundling:failed","_t":1786669936854,"id":null,"message":"Unable to resolve \"@expo/vector-icons\" from \"src/app/biometrics.tsx\"\n 4 | import * as SecureStore from 'expo-secure-store';\n 5 | import Animated, { FadeInDown, FadeInUp } from 'react-native-reanimated';\n> 6 | import { Feather } from '@expo/vector-icons';\n | ^\n 7 | import { useSafeAreaInsets } from 'react-native-safe-area-context';\n 8 | import { Button } from '@/components/ui/button';\n 9 | import { Colors, Spacing, Typography, Radius } from '@/constants/theme';","importStack":"\u001b[1mImport stack:\u001b[22m\n\n\u001b[90m \u001b[39msrc/app/biometrics.tsx\n\u001b[90m |\u001b[39m \u001b[36mimport\u001b[39m \u001b[32m\"@expo/vector-icons\"\u001b[39m\n\n\u001b[90m \u001b[39msrc/app\u001b[2m (require.context)\u001b[22m\n","filename":null,"targetModuleName":"@expo/vector-icons","originModulePath":"src/app/biometrics.tsx"}
+{"_e":"metro:bundling:failed","_t":1786669937150,"id":null,"message":"Unable to resolve \"@expo/vector-icons\" from \"src/app/biometrics.tsx\"\n 4 | import * as SecureStore from 'expo-secure-store';\n 5 | import Animated, { FadeInDown, FadeInUp } from 'react-native-reanimated';\n> 6 | import { Feather } from '@expo/vector-icons';\n | ^\n 7 | import { useSafeAreaInsets } from 'react-native-safe-area-context';\n 8 | import { Button } from '@/components/ui/button';\n 9 | import { Colors, Spacing, Typography, Radius } from '@/constants/theme';","importStack":"\u001b[1mImport stack:\u001b[22m\n\n\u001b[90m \u001b[39msrc/app/biometrics.tsx\n\u001b[90m |\u001b[39m \u001b[36mimport\u001b[39m \u001b[32m\"@expo/vector-icons\"\u001b[39m\n\n\u001b[90m \u001b[39msrc/app\u001b[2m (require.context)\u001b[22m\n","filename":null,"targetModuleName":"@expo/vector-icons","originModulePath":"src/app/biometrics.tsx"}
+{"_e":"metro:bundling:failed","_t":1786669937524,"id":null,"message":"Unable to resolve \"@expo/vector-icons\" from \"src/app/biometrics.tsx\"\n 4 | import * as SecureStore from 'expo-secure-store';\n 5 | import Animated, { FadeInDown, FadeInUp } from 'react-native-reanimated';\n> 6 | import { Feather } from '@expo/vector-icons';\n | ^\n 7 | import { useSafeAreaInsets } from 'react-native-safe-area-context';\n 8 | import { Button } from '@/components/ui/button';\n 9 | import { Colors, Spacing, Typography, Radius } from '@/constants/theme';","importStack":"\u001b[1mImport stack:\u001b[22m\n\n\u001b[90m \u001b[39msrc/app/biometrics.tsx\n\u001b[90m |\u001b[39m \u001b[36mimport\u001b[39m \u001b[32m\"@expo/vector-icons\"\u001b[39m\n\n\u001b[90m \u001b[39msrc/app\u001b[2m (require.context)\u001b[22m\n","filename":null,"targetModuleName":"@expo/vector-icons","originModulePath":"src/app/biometrics.tsx"}
+{"_e":"metro:bundling:failed","_t":1786669937752,"id":null,"message":"Unable to resolve \"@expo/vector-icons\" from \"src/app/biometrics.tsx\"\n 4 | import * as SecureStore from 'expo-secure-store';\n 5 | import Animated, { FadeInDown, FadeInUp } from 'react-native-reanimated';\n> 6 | import { Feather } from '@expo/vector-icons';\n | ^\n 7 | import { useSafeAreaInsets } from 'react-native-safe-area-context';\n 8 | import { Button } from '@/components/ui/button';\n 9 | import { Colors, Spacing, Typography, Radius } from '@/constants/theme';","importStack":"\u001b[1mImport stack:\u001b[22m\n\n\u001b[90m \u001b[39msrc/app/biometrics.tsx\n\u001b[90m |\u001b[39m \u001b[36mimport\u001b[39m \u001b[32m\"@expo/vector-icons\"\u001b[39m\n\n\u001b[90m \u001b[39msrc/app\u001b[2m (require.context)\u001b[22m\n","filename":null,"targetModuleName":"@expo/vector-icons","originModulePath":"src/app/biometrics.tsx"}
+{"_e":"metro:bundling:failed","_t":1786669942049,"id":null,"message":"Unable to resolve \"@expo/vector-icons\" from \"src/app/biometrics.tsx\"\n 4 | import * as SecureStore from 'expo-secure-store';\n 5 | import Animated, { FadeInDown, FadeInUp } from 'react-native-reanimated';\n> 6 | import { Feather } from '@expo/vector-icons';\n | ^\n 7 | import { useSafeAreaInsets } from 'react-native-safe-area-context';\n 8 | import { Button } from '@/components/ui/button';\n 9 | import { Colors, Spacing, Typography, Radius } from '@/constants/theme';","importStack":"\u001b[1mImport stack:\u001b[22m\n\n\u001b[90m \u001b[39msrc/app/biometrics.tsx\n\u001b[90m |\u001b[39m \u001b[36mimport\u001b[39m \u001b[32m\"@expo/vector-icons\"\u001b[39m\n\n\u001b[90m \u001b[39msrc/app\u001b[2m (require.context)\u001b[22m\n","filename":null,"targetModuleName":"@expo/vector-icons","originModulePath":"src/app/biometrics.tsx"}
+{"_e":"metro:bundling:failed","_t":1786669942315,"id":null,"message":"Unable to resolve \"@expo/vector-icons\" from \"src/app/biometrics.tsx\"\n 4 | import * as SecureStore from 'expo-secure-store';\n 5 | import Animated, { FadeInDown, FadeInUp } from 'react-native-reanimated';\n> 6 | import { Feather } from '@expo/vector-icons';\n | ^\n 7 | import { useSafeAreaInsets } from 'react-native-safe-area-context';\n 8 | import { Button } from '@/components/ui/button';\n 9 | import { Colors, Spacing, Typography, Radius } from '@/constants/theme';","importStack":"\u001b[1mImport stack:\u001b[22m\n\n\u001b[90m \u001b[39msrc/app/biometrics.tsx\n\u001b[90m |\u001b[39m \u001b[36mimport\u001b[39m \u001b[32m\"@expo/vector-icons\"\u001b[39m\n\n\u001b[90m \u001b[39msrc/app\u001b[2m (require.context)\u001b[22m\n","filename":null,"targetModuleName":"@expo/vector-icons","originModulePath":"src/app/biometrics.tsx"}
+{"_e":"metro:bundling:failed","_t":1786669942636,"id":null,"message":"Unable to resolve \"@expo/vector-icons\" from \"src/app/biometrics.tsx\"\n 4 | import * as SecureStore from 'expo-secure-store';\n 5 | import Animated, { FadeInDown, FadeInUp } from 'react-native-reanimated';\n> 6 | import { Feather } from '@expo/vector-icons';\n | ^\n 7 | import { useSafeAreaInsets } from 'react-native-safe-area-context';\n 8 | import { Button } from '@/components/ui/button';\n 9 | import { Colors, Spacing, Typography, Radius } from '@/constants/theme';","importStack":"\u001b[1mImport stack:\u001b[22m\n\n\u001b[90m \u001b[39msrc/app/biometrics.tsx\n\u001b[90m |\u001b[39m \u001b[36mimport\u001b[39m \u001b[32m\"@expo/vector-icons\"\u001b[39m\n\n\u001b[90m \u001b[39msrc/app\u001b[2m (require.context)\u001b[22m\n","filename":null,"targetModuleName":"@expo/vector-icons","originModulePath":"src/app/biometrics.tsx"}
+{"_e":"metro:bundling:failed","_t":1786669942871,"id":null,"message":"Unable to resolve \"@expo/vector-icons\" from \"src/app/biometrics.tsx\"\n 4 | import * as SecureStore from 'expo-secure-store';\n 5 | import Animated, { FadeInDown, FadeInUp } from 'react-native-reanimated';\n> 6 | import { Feather } from '@expo/vector-icons';\n | ^\n 7 | import { useSafeAreaInsets } from 'react-native-safe-area-context';\n 8 | import { Button } from '@/components/ui/button';\n 9 | import { Colors, Spacing, Typography, Radius } from '@/constants/theme';","importStack":"\u001b[1mImport stack:\u001b[22m\n\n\u001b[90m \u001b[39msrc/app/biometrics.tsx\n\u001b[90m |\u001b[39m \u001b[36mimport\u001b[39m \u001b[32m\"@expo/vector-icons\"\u001b[39m\n\n\u001b[90m \u001b[39msrc/app\u001b[2m (require.context)\u001b[22m\n","filename":null,"targetModuleName":"@expo/vector-icons","originModulePath":"src/app/biometrics.tsx"}
+{"_e":"metro:bundling:failed","_t":1786669943064,"id":null,"message":"Unable to resolve \"@expo/vector-icons\" from \"src/app/biometrics.tsx\"\n 4 | import * as SecureStore from 'expo-secure-store';\n 5 | import Animated, { FadeInDown, FadeInUp } from 'react-native-reanimated';\n> 6 | import { Feather } from '@expo/vector-icons';\n | ^\n 7 | import { useSafeAreaInsets } from 'react-native-safe-area-context';\n 8 | import { Button } from '@/components/ui/button';\n 9 | import { Colors, Spacing, Typography, Radius } from '@/constants/theme';","importStack":"\u001b[1mImport stack:\u001b[22m\n\n\u001b[90m \u001b[39msrc/app/biometrics.tsx\n\u001b[90m |\u001b[39m \u001b[36mimport\u001b[39m \u001b[32m\"@expo/vector-icons\"\u001b[39m\n\n\u001b[90m \u001b[39msrc/app\u001b[2m (require.context)\u001b[22m\n","filename":null,"targetModuleName":"@expo/vector-icons","originModulePath":"src/app/biometrics.tsx"}
+{"_e":"metro:bundling:failed","_t":1786669951314,"id":null,"message":"Unable to resolve \"@expo/vector-icons\" from \"src/app/biometrics.tsx\"\n 4 | import * as SecureStore from 'expo-secure-store';\n 5 | import Animated, { FadeInDown, FadeInUp } from 'react-native-reanimated';\n> 6 | import { Feather } from '@expo/vector-icons';\n | ^\n 7 | import { useSafeAreaInsets } from 'react-native-safe-area-context';\n 8 | import { Button } from '@/components/ui/button';\n 9 | import { Colors, Spacing, Typography, Radius } from '@/constants/theme';","importStack":"\u001b[1mImport stack:\u001b[22m\n\n\u001b[90m \u001b[39msrc/app/biometrics.tsx\n\u001b[90m |\u001b[39m \u001b[36mimport\u001b[39m \u001b[32m\"@expo/vector-icons\"\u001b[39m\n\n\u001b[90m \u001b[39msrc/app\u001b[2m (require.context)\u001b[22m\n","filename":null,"targetModuleName":"@expo/vector-icons","originModulePath":"src/app/biometrics.tsx"}
+{"_e":"metro:bundling:failed","_t":1786669951707,"id":null,"message":"Unable to resolve \"@expo/vector-icons\" from \"src/app/biometrics.tsx\"\n 4 | import * as SecureStore from 'expo-secure-store';\n 5 | import Animated, { FadeInDown, FadeInUp } from 'react-native-reanimated';\n> 6 | import { Feather } from '@expo/vector-icons';\n | ^\n 7 | import { useSafeAreaInsets } from 'react-native-safe-area-context';\n 8 | import { Button } from '@/components/ui/button';\n 9 | import { Colors, Spacing, Typography, Radius } from '@/constants/theme';","importStack":"\u001b[1mImport stack:\u001b[22m\n\n\u001b[90m \u001b[39msrc/app/biometrics.tsx\n\u001b[90m |\u001b[39m \u001b[36mimport\u001b[39m \u001b[32m\"@expo/vector-icons\"\u001b[39m\n\n\u001b[90m \u001b[39msrc/app\u001b[2m (require.context)\u001b[22m\n","filename":null,"targetModuleName":"@expo/vector-icons","originModulePath":"src/app/biometrics.tsx"}
+{"_e":"metro:client_log","_t":1786670156434,"level":"error","data":["API Error (400):","{\"error\":\"Email já está em uso.\"}","\n\n\u001b[1mCode: api.ts\u001b[22m\n\u001b[0m \u001b[90m 39 |\u001b[39m \u001b[36mif\u001b[39m (\u001b[33m!\u001b[39mresponse\u001b[33m.\u001b[39mok) {\n \u001b[90m 40 |\u001b[39m \u001b[36mconst\u001b[39m errorText \u001b[33m=\u001b[39m \u001b[36mawait\u001b[39m response\u001b[33m.\u001b[39mtext()\u001b[33m;\u001b[39m\n\u001b[31m\u001b[1m>\u001b[22m\u001b[39m\u001b[90m 41 |\u001b[39m console\u001b[33m.\u001b[39merror(\u001b[32m`API Error (${response.status}):`\u001b[39m\u001b[33m,\u001b[39m errorText)\u001b[33m;\u001b[39m\n \u001b[90m |\u001b[39m \u001b[31m\u001b[1m^\u001b[22m\u001b[39m\n \u001b[90m 42 |\u001b[39m \u001b[36mthrow\u001b[39m \u001b[36mnew\u001b[39m \u001b[33mError\u001b[39m(\u001b[32m`API Error: ${response.status}`\u001b[39m)\u001b[33m;\u001b[39m\n \u001b[90m 43 |\u001b[39m }\n \u001b[90m 44 |\u001b[39m \u001b[0m\n\u001b[1mCall Stack\u001b[22m\n\u001b[90m fetcher (src/services/api.ts:41:26)\u001b[39m"]}
+{"_e":"metro:client_log","_t":1786670156435,"level":"error","data":["Fetch Error on /auth/register:","[Error: API Error: 400]","\n\n\u001b[1mCode: api.ts\u001b[22m\n\u001b[0m \u001b[90m 40 |\u001b[39m \u001b[36mconst\u001b[39m errorText \u001b[33m=\u001b[39m \u001b[36mawait\u001b[39m response\u001b[33m.\u001b[39mtext()\u001b[33m;\u001b[39m\n \u001b[90m 41 |\u001b[39m console\u001b[33m.\u001b[39merror(\u001b[32m`API Error (${response.status}):`\u001b[39m\u001b[33m,\u001b[39m errorText)\u001b[33m;\u001b[39m\n\u001b[31m\u001b[1m>\u001b[22m\u001b[39m\u001b[90m 42 |\u001b[39m \u001b[36mthrow\u001b[39m \u001b[36mnew\u001b[39m \u001b[33mError\u001b[39m(\u001b[32m`API Error: ${response.status}`\u001b[39m)\u001b[33m;\u001b[39m\n \u001b[90m |\u001b[39m \u001b[31m\u001b[1m^\u001b[22m\u001b[39m\n \u001b[90m 43 |\u001b[39m }\n \u001b[90m 44 |\u001b[39m \n \u001b[90m 45 |\u001b[39m \u001b[36mconst\u001b[39m data \u001b[33m=\u001b[39m \u001b[36mawait\u001b[39m response\u001b[33m.\u001b[39mjson()\u001b[33m;\u001b[39m\u001b[0m\n\u001b[1mCall Stack\u001b[22m\n\u001b[90m fetcher (src/services/api.ts:42:28)\u001b[39m"]}
+{"_e":"metro:client_log","_t":1786670446248,"level":"error","data":["API Error (400):","{\"error\":\"Email já está em uso.\"}","\n\n\u001b[1mCode: api.ts\u001b[22m\n\u001b[0m \u001b[90m 39 |\u001b[39m \u001b[36mif\u001b[39m (\u001b[33m!\u001b[39mresponse\u001b[33m.\u001b[39mok) {\n \u001b[90m 40 |\u001b[39m \u001b[36mconst\u001b[39m errorText \u001b[33m=\u001b[39m \u001b[36mawait\u001b[39m response\u001b[33m.\u001b[39mtext()\u001b[33m;\u001b[39m\n\u001b[31m\u001b[1m>\u001b[22m\u001b[39m\u001b[90m 41 |\u001b[39m console\u001b[33m.\u001b[39merror(\u001b[32m`API Error (${response.status}):`\u001b[39m\u001b[33m,\u001b[39m errorText)\u001b[33m;\u001b[39m\n \u001b[90m |\u001b[39m \u001b[31m\u001b[1m^\u001b[22m\u001b[39m\n \u001b[90m 42 |\u001b[39m \u001b[36mthrow\u001b[39m \u001b[36mnew\u001b[39m \u001b[33mError\u001b[39m(\u001b[32m`API Error: ${response.status}`\u001b[39m)\u001b[33m;\u001b[39m\n \u001b[90m 43 |\u001b[39m }\n \u001b[90m 44 |\u001b[39m \u001b[0m\n\u001b[1mCall Stack\u001b[22m\n\u001b[90m fetcher (src/services/api.ts:41:26)\u001b[39m"]}
+{"_e":"metro:client_log","_t":1786670446249,"level":"error","data":["Fetch Error on /auth/register:","[Error: API Error: 400]","\n\n\u001b[1mCode: api.ts\u001b[22m\n\u001b[0m \u001b[90m 40 |\u001b[39m \u001b[36mconst\u001b[39m errorText \u001b[33m=\u001b[39m \u001b[36mawait\u001b[39m response\u001b[33m.\u001b[39mtext()\u001b[33m;\u001b[39m\n \u001b[90m 41 |\u001b[39m console\u001b[33m.\u001b[39merror(\u001b[32m`API Error (${response.status}):`\u001b[39m\u001b[33m,\u001b[39m errorText)\u001b[33m;\u001b[39m\n\u001b[31m\u001b[1m>\u001b[22m\u001b[39m\u001b[90m 42 |\u001b[39m \u001b[36mthrow\u001b[39m \u001b[36mnew\u001b[39m \u001b[33mError\u001b[39m(\u001b[32m`API Error: ${response.status}`\u001b[39m)\u001b[33m;\u001b[39m\n \u001b[90m |\u001b[39m \u001b[31m\u001b[1m^\u001b[22m\u001b[39m\n \u001b[90m 43 |\u001b[39m }\n \u001b[90m 44 |\u001b[39m \n \u001b[90m 45 |\u001b[39m \u001b[36mconst\u001b[39m data \u001b[33m=\u001b[39m \u001b[36mawait\u001b[39m response\u001b[33m.\u001b[39mjson()\u001b[33m;\u001b[39m\u001b[0m\n\u001b[1mCall Stack\u001b[22m\n\u001b[90m fetcher (src/services/api.ts:42:28)\u001b[39m"]}
+{"_e":"metro:client_log","_t":1786670496583,"level":"error","data":["API Error (401):","{\"error\":\"Email ou senha inválidos.\"}","\n\n\u001b[1mCode: api.ts\u001b[22m\n\u001b[0m \u001b[90m 39 |\u001b[39m \u001b[36mif\u001b[39m (\u001b[33m!\u001b[39mresponse\u001b[33m.\u001b[39mok) {\n \u001b[90m 40 |\u001b[39m \u001b[36mconst\u001b[39m errorText \u001b[33m=\u001b[39m \u001b[36mawait\u001b[39m response\u001b[33m.\u001b[39mtext()\u001b[33m;\u001b[39m\n\u001b[31m\u001b[1m>\u001b[22m\u001b[39m\u001b[90m 41 |\u001b[39m console\u001b[33m.\u001b[39merror(\u001b[32m`API Error (${response.status}):`\u001b[39m\u001b[33m,\u001b[39m errorText)\u001b[33m;\u001b[39m\n \u001b[90m |\u001b[39m \u001b[31m\u001b[1m^\u001b[22m\u001b[39m\n \u001b[90m 42 |\u001b[39m \u001b[36mthrow\u001b[39m \u001b[36mnew\u001b[39m \u001b[33mError\u001b[39m(\u001b[32m`API Error: ${response.status}`\u001b[39m)\u001b[33m;\u001b[39m\n \u001b[90m 43 |\u001b[39m }\n \u001b[90m 44 |\u001b[39m \u001b[0m\n\u001b[1mCall Stack\u001b[22m\n\u001b[90m fetcher (src/services/api.ts:41:26)\u001b[39m"]}
+{"_e":"metro:client_log","_t":1786670496587,"level":"error","data":["Fetch Error on /auth/login:","[Error: API Error: 401]","\n\n\u001b[1mCode: api.ts\u001b[22m\n\u001b[0m \u001b[90m 40 |\u001b[39m \u001b[36mconst\u001b[39m errorText \u001b[33m=\u001b[39m \u001b[36mawait\u001b[39m response\u001b[33m.\u001b[39mtext()\u001b[33m;\u001b[39m\n \u001b[90m 41 |\u001b[39m console\u001b[33m.\u001b[39merror(\u001b[32m`API Error (${response.status}):`\u001b[39m\u001b[33m,\u001b[39m errorText)\u001b[33m;\u001b[39m\n\u001b[31m\u001b[1m>\u001b[22m\u001b[39m\u001b[90m 42 |\u001b[39m \u001b[36mthrow\u001b[39m \u001b[36mnew\u001b[39m \u001b[33mError\u001b[39m(\u001b[32m`API Error: ${response.status}`\u001b[39m)\u001b[33m;\u001b[39m\n \u001b[90m |\u001b[39m \u001b[31m\u001b[1m^\u001b[22m\u001b[39m\n \u001b[90m 43 |\u001b[39m }\n \u001b[90m 44 |\u001b[39m \n \u001b[90m 45 |\u001b[39m \u001b[36mconst\u001b[39m data \u001b[33m=\u001b[39m \u001b[36mawait\u001b[39m response\u001b[33m.\u001b[39mjson()\u001b[33m;\u001b[39m\u001b[0m\n\u001b[1mCall Stack\u001b[22m\n\u001b[90m fetcher (src/services/api.ts:42:28)\u001b[39m"]}
+{"_e":"metro:client_log","_t":1786670513450,"level":"error","data":["API Error (401):","{\"error\":\"Email ou senha inválidos.\"}","\n\n\u001b[1mCode: api.ts\u001b[22m\n\u001b[0m \u001b[90m 39 |\u001b[39m \u001b[36mif\u001b[39m (\u001b[33m!\u001b[39mresponse\u001b[33m.\u001b[39mok) {\n \u001b[90m 40 |\u001b[39m \u001b[36mconst\u001b[39m errorText \u001b[33m=\u001b[39m \u001b[36mawait\u001b[39m response\u001b[33m.\u001b[39mtext()\u001b[33m;\u001b[39m\n\u001b[31m\u001b[1m>\u001b[22m\u001b[39m\u001b[90m 41 |\u001b[39m console\u001b[33m.\u001b[39merror(\u001b[32m`API Error (${response.status}):`\u001b[39m\u001b[33m,\u001b[39m errorText)\u001b[33m;\u001b[39m\n \u001b[90m |\u001b[39m \u001b[31m\u001b[1m^\u001b[22m\u001b[39m\n \u001b[90m 42 |\u001b[39m \u001b[36mthrow\u001b[39m \u001b[36mnew\u001b[39m \u001b[33mError\u001b[39m(\u001b[32m`API Error: ${response.status}`\u001b[39m)\u001b[33m;\u001b[39m\n \u001b[90m 43 |\u001b[39m }\n \u001b[90m 44 |\u001b[39m \u001b[0m\n\u001b[1mCall Stack\u001b[22m\n\u001b[90m fetcher (src/services/api.ts:41:26)\u001b[39m"]}
+{"_e":"metro:client_log","_t":1786670513453,"level":"error","data":["Fetch Error on /auth/login:","[Error: API Error: 401]","\n\n\u001b[1mCode: api.ts\u001b[22m\n\u001b[0m \u001b[90m 40 |\u001b[39m \u001b[36mconst\u001b[39m errorText \u001b[33m=\u001b[39m \u001b[36mawait\u001b[39m response\u001b[33m.\u001b[39mtext()\u001b[33m;\u001b[39m\n \u001b[90m 41 |\u001b[39m console\u001b[33m.\u001b[39merror(\u001b[32m`API Error (${response.status}):`\u001b[39m\u001b[33m,\u001b[39m errorText)\u001b[33m;\u001b[39m\n\u001b[31m\u001b[1m>\u001b[22m\u001b[39m\u001b[90m 42 |\u001b[39m \u001b[36mthrow\u001b[39m \u001b[36mnew\u001b[39m \u001b[33mError\u001b[39m(\u001b[32m`API Error: ${response.status}`\u001b[39m)\u001b[33m;\u001b[39m\n \u001b[90m |\u001b[39m \u001b[31m\u001b[1m^\u001b[22m\u001b[39m\n \u001b[90m 43 |\u001b[39m }\n \u001b[90m 44 |\u001b[39m \n \u001b[90m 45 |\u001b[39m \u001b[36mconst\u001b[39m data \u001b[33m=\u001b[39m \u001b[36mawait\u001b[39m response\u001b[33m.\u001b[39mjson()\u001b[33m;\u001b[39m\u001b[0m\n\u001b[1mCall Stack\u001b[22m\n\u001b[90m fetcher (src/services/api.ts:42:28)\u001b[39m"]}
+{"_e":"metro:client_log","_t":1786670525231,"level":"error","data":["API Error (401):","{\"error\":\"Email ou senha inválidos.\"}","\n\n\u001b[1mCode: api.ts\u001b[22m\n\u001b[0m \u001b[90m 39 |\u001b[39m \u001b[36mif\u001b[39m (\u001b[33m!\u001b[39mresponse\u001b[33m.\u001b[39mok) {\n \u001b[90m 40 |\u001b[39m \u001b[36mconst\u001b[39m errorText \u001b[33m=\u001b[39m \u001b[36mawait\u001b[39m response\u001b[33m.\u001b[39mtext()\u001b[33m;\u001b[39m\n\u001b[31m\u001b[1m>\u001b[22m\u001b[39m\u001b[90m 41 |\u001b[39m console\u001b[33m.\u001b[39merror(\u001b[32m`API Error (${response.status}):`\u001b[39m\u001b[33m,\u001b[39m errorText)\u001b[33m;\u001b[39m\n \u001b[90m |\u001b[39m \u001b[31m\u001b[1m^\u001b[22m\u001b[39m\n \u001b[90m 42 |\u001b[39m \u001b[36mthrow\u001b[39m \u001b[36mnew\u001b[39m \u001b[33mError\u001b[39m(\u001b[32m`API Error: ${response.status}`\u001b[39m)\u001b[33m;\u001b[39m\n \u001b[90m 43 |\u001b[39m }\n \u001b[90m 44 |\u001b[39m \u001b[0m\n\u001b[1mCall Stack\u001b[22m\n\u001b[90m fetcher (src/services/api.ts:41:26)\u001b[39m"]}
+{"_e":"metro:client_log","_t":1786670525235,"level":"error","data":["Fetch Error on /auth/login:","[Error: API Error: 401]","\n\n\u001b[1mCode: api.ts\u001b[22m\n\u001b[0m \u001b[90m 40 |\u001b[39m \u001b[36mconst\u001b[39m errorText \u001b[33m=\u001b[39m \u001b[36mawait\u001b[39m response\u001b[33m.\u001b[39mtext()\u001b[33m;\u001b[39m\n \u001b[90m 41 |\u001b[39m console\u001b[33m.\u001b[39merror(\u001b[32m`API Error (${response.status}):`\u001b[39m\u001b[33m,\u001b[39m errorText)\u001b[33m;\u001b[39m\n\u001b[31m\u001b[1m>\u001b[22m\u001b[39m\u001b[90m 42 |\u001b[39m \u001b[36mthrow\u001b[39m \u001b[36mnew\u001b[39m \u001b[33mError\u001b[39m(\u001b[32m`API Error: ${response.status}`\u001b[39m)\u001b[33m;\u001b[39m\n \u001b[90m |\u001b[39m \u001b[31m\u001b[1m^\u001b[22m\u001b[39m\n \u001b[90m 43 |\u001b[39m }\n \u001b[90m 44 |\u001b[39m \n \u001b[90m 45 |\u001b[39m \u001b[36mconst\u001b[39m data \u001b[33m=\u001b[39m \u001b[36mawait\u001b[39m response\u001b[33m.\u001b[39mjson()\u001b[33m;\u001b[39m\u001b[0m\n\u001b[1mCall Stack\u001b[22m\n\u001b[90m fetcher (src/services/api.ts:42:28)\u001b[39m"]}
+{"_e":"metro:client_log","_t":1786670536089,"level":"error","data":["API Error (401):","{\"error\":\"Email ou senha inválidos.\"}","\n\n\u001b[1mCode: api.ts\u001b[22m\n\u001b[0m \u001b[90m 39 |\u001b[39m \u001b[36mif\u001b[39m (\u001b[33m!\u001b[39mresponse\u001b[33m.\u001b[39mok) {\n \u001b[90m 40 |\u001b[39m \u001b[36mconst\u001b[39m errorText \u001b[33m=\u001b[39m \u001b[36mawait\u001b[39m response\u001b[33m.\u001b[39mtext()\u001b[33m;\u001b[39m\n\u001b[31m\u001b[1m>\u001b[22m\u001b[39m\u001b[90m 41 |\u001b[39m console\u001b[33m.\u001b[39merror(\u001b[32m`API Error (${response.status}):`\u001b[39m\u001b[33m,\u001b[39m errorText)\u001b[33m;\u001b[39m\n \u001b[90m |\u001b[39m \u001b[31m\u001b[1m^\u001b[22m\u001b[39m\n \u001b[90m 42 |\u001b[39m \u001b[36mthrow\u001b[39m \u001b[36mnew\u001b[39m \u001b[33mError\u001b[39m(\u001b[32m`API Error: ${response.status}`\u001b[39m)\u001b[33m;\u001b[39m\n \u001b[90m 43 |\u001b[39m }\n \u001b[90m 44 |\u001b[39m \u001b[0m\n\u001b[1mCall Stack\u001b[22m\n\u001b[90m fetcher (src/services/api.ts:41:26)\u001b[39m"]}
+{"_e":"metro:client_log","_t":1786670536092,"level":"error","data":["Fetch Error on /auth/login:","[Error: API Error: 401]","\n\n\u001b[1mCode: api.ts\u001b[22m\n\u001b[0m \u001b[90m 40 |\u001b[39m \u001b[36mconst\u001b[39m errorText \u001b[33m=\u001b[39m \u001b[36mawait\u001b[39m response\u001b[33m.\u001b[39mtext()\u001b[33m;\u001b[39m\n \u001b[90m 41 |\u001b[39m console\u001b[33m.\u001b[39merror(\u001b[32m`API Error (${response.status}):`\u001b[39m\u001b[33m,\u001b[39m errorText)\u001b[33m;\u001b[39m\n\u001b[31m\u001b[1m>\u001b[22m\u001b[39m\u001b[90m 42 |\u001b[39m \u001b[36mthrow\u001b[39m \u001b[36mnew\u001b[39m \u001b[33mError\u001b[39m(\u001b[32m`API Error: ${response.status}`\u001b[39m)\u001b[33m;\u001b[39m\n \u001b[90m |\u001b[39m \u001b[31m\u001b[1m^\u001b[22m\u001b[39m\n \u001b[90m 43 |\u001b[39m }\n \u001b[90m 44 |\u001b[39m \n \u001b[90m 45 |\u001b[39m \u001b[36mconst\u001b[39m data \u001b[33m=\u001b[39m \u001b[36mawait\u001b[39m response\u001b[33m.\u001b[39mjson()\u001b[33m;\u001b[39m\u001b[0m\n\u001b[1mCall Stack\u001b[22m\n\u001b[90m fetcher (src/services/api.ts:42:28)\u001b[39m"]}
+{"_e":"metro:client_log","_t":1786670555045,"level":"warn","data":["Unable to get the view config for ExpoBlurView from module &s ExpoBlur"]}
+{"_e":"root:init","_t":1786670664496,"format":"v0-jsonl","version":"57.0.14"}
+{"_e":"devserver:start","_t":1786670664510,"mode":"development","web":true,"baseUrl":"","asyncRoutes":false,"routerRoot":"../../../src/app","serverComponents":false,"serverActions":false,"serverRendering":true,"apiRoutes":false,"exporting":false}
+{"_e":"metro:config","_t":1786670664699,"serverRoot":"../../..","projectRoot":"../../..","exporting":false,"flags":{"autolinkingModuleResolution":false,"serverActions":false,"serverComponents":false,"reactCompiler":true,"optimizeGraph":false,"treeshaking":false,"logbox":false}}
+{"_e":"expo:dev-tools-plugin:load","_t":1786670664898,"plugins":[]}
+{"_e":"metro:instantiate","_t":1786670665436,"atlas":false,"workers":4,"host":"::","port":8081}
+{"_e":"metro:bundling:started","_t":1786670695643,"id":"1","platform":"android","environment":null,"entry":"node_modules/expo-router/entry.js"}
+{"_e":"metro:bundling:progress","_t":1786670695645,"id":"1","progress":0,"total":1,"current":0}
+{"_e":"metro:bundling:progress","_t":1786670695652,"id":"1","progress":0,"total":1,"current":0}
+{"_e":"metro:bundling:progress","_t":1786670695752,"id":"1","progress":0.1810774105930285,"total":376,"current":160}
+{"_e":"metro:bundling:progress","_t":1786670695852,"id":"1","progress":0.48884683311194294,"total":728,"current":509}
+{"_e":"metro:bundling:progress","_t":1786670695952,"id":"1","progress":0.6365863226315231,"total":1217,"current":971}
+{"_e":"metro:bundling:progress","_t":1786670696052,"id":"1","progress":0.9012369843107826,"total":1579,"current":1499}
+{"_e":"metro:bundling:done","_t":1786670696180,"id":"1","total":1579,"ms":535.292083}
+{"_e":"metro:bundling:started","_t":1786670918236,"id":"2","platform":"android","environment":null,"entry":"node_modules/expo-router/entry.js"}
+{"_e":"metro:bundling:progress","_t":1786670918236,"id":"2","progress":0,"total":1,"current":0}
+{"_e":"metro:bundling:done","_t":1786670918326,"id":"2","total":1,"ms":89.640708}
+{"_e":"root:init","_t":1786708630838,"format":"v0-jsonl","version":"57.0.14"}
+{"_e":"devserver:start","_t":1786708630861,"mode":"development","web":true,"baseUrl":"","asyncRoutes":false,"routerRoot":"../../../src/app","serverComponents":false,"serverActions":false,"serverRendering":true,"apiRoutes":false,"exporting":false}
+{"_e":"metro:config","_t":1786708631096,"serverRoot":"../../..","projectRoot":"../../..","exporting":false,"flags":{"autolinkingModuleResolution":false,"serverActions":false,"serverComponents":false,"reactCompiler":true,"optimizeGraph":false,"treeshaking":false,"logbox":false}}
+{"_e":"expo:dev-tools-plugin:load","_t":1786708631228,"plugins":[]}
+{"_e":"metro:instantiate","_t":1786708631929,"atlas":false,"workers":4,"host":"::","port":8081}
+{"_e":"metro:bundling:started","_t":1786708662422,"id":"1","platform":"android","environment":null,"entry":"node_modules/expo-router/entry.js"}
+{"_e":"metro:bundling:progress","_t":1786708662422,"id":"1","progress":0,"total":1,"current":0}
+{"_e":"metro:bundling:progress","_t":1786708662426,"id":"1","progress":0,"total":1,"current":0}
+{"_e":"metro:bundling:progress","_t":1786708662526,"id":"1","progress":0.2433484135841837,"total":448,"current":221}
+{"_e":"metro:bundling:progress","_t":1786708662626,"id":"1","progress":0.5102040816326531,"total":875,"current":625}
+{"_e":"metro:bundling:progress","_t":1786708662726,"id":"1","progress":0.9316296380589206,"total":1121,"current":1082}
+{"_e":"metro:bundling:progress","_t":1786708662827,"id":"1","progress":0.9985113511553523,"total":1343,"current":1342}
+{"_e":"metro:bundling:progress","_t":1786708662998,"id":"1","progress":0.999,"total":1343,"current":1343}
+{"_e":"metro:bundling:progress","_t":1786708663098,"id":"1","progress":0.999,"total":1705,"current":1670}
+{"_e":"metro:bundling:progress","_t":1786708663198,"id":"1","progress":0.999,"total":1821,"current":1819}
+{"_e":"metro:bundling:progress","_t":1786708663299,"id":"1","progress":0.999,"total":1824,"current":1822}
+{"_e":"metro:bundling:progress","_t":1786708663457,"id":"1","progress":0.999,"total":1824,"current":1823}
+{"_e":"metro:bundling:progress","_t":1786708663458,"id":"1","progress":0.999,"total":1824,"current":1824}
+{"_e":"metro:bundling:failed","_t":1786708663459,"id":"1","message":"Unable to resolve \"@/screens/DashboardScreen\" from \"src/app/(app)/(tabs)/index.tsx\"\n> 1 | import DashboardScreen from '@/screens/DashboardScreen';\n | ^\n 2 | export default DashboardScreen;\n 3 |","importStack":"\u001b[1mImport stack:\u001b[22m\n\n\u001b[90m \u001b[39msrc/app/(app)/(tabs)/index.tsx\n\u001b[90m |\u001b[39m \u001b[36mimport\u001b[39m \u001b[32m\"@/screens/DashboardScreen\"\u001b[39m\n\n\u001b[90m \u001b[39msrc/app\u001b[2m (require.context)\u001b[22m\n","filename":null,"targetModuleName":"@/screens/DashboardScreen","originModulePath":"src/app/(app)/(tabs)/index.tsx"}
+{"_e":"metro:bundling:started","_t":1786708698008,"id":"2","platform":"android","environment":null,"entry":"node_modules/expo-router/entry.js"}
+{"_e":"metro:bundling:progress","_t":1786708698008,"id":"2","progress":0,"total":1,"current":0}
+{"_e":"metro:bundling:progress","_t":1786708698010,"id":"2","progress":0,"total":1,"current":0}
+{"_e":"metro:bundling:progress","_t":1786708698110,"id":"2","progress":0.30050117154005934,"total":467,"current":256}
+{"_e":"metro:bundling:progress","_t":1786708698210,"id":"2","progress":0.5684581465928307,"total":1199,"current":904}
+{"_e":"metro:bundling:progress","_t":1786708698310,"id":"2","progress":0.8633092882267152,"total":1496,"current":1390}
+{"_e":"metro:bundling:failed","_t":1786708698371,"id":"2","message":"As of SDK 56, expo-router is no longer compatible with react-navigation. For more information, see https://docs.expo.dev/router/migrate/sdk-55-to-56/. You can disable this check by setting the environment variable EXPO_ROUTER_DISABLE_RN_NAVIGATION_CHECK=1.","importStack":"\u001b[1mImport stack:\u001b[22m\n\n\u001b[90m \u001b[39msrc/screens/dashboard-screen.tsx\n\u001b[90m |\u001b[39m \u001b[36mimport\u001b[39m \u001b[32m\"@react-navigation/native\"\u001b[39m\n\n\u001b[90m \u001b[39msrc/app/(app)/(tabs)/index.tsx\n\u001b[90m |\u001b[39m \u001b[36mimport\u001b[39m \u001b[32m\"@/screens/dashboard-screen\"\u001b[39m\n\n\u001b[90m \u001b[39msrc/app\u001b[2m (require.context)\u001b[22m\n","filename":null,"targetModuleName":null,"originModulePath":null}
+{"_e":"metro:bundling:started","_t":1786708912534,"id":"3","platform":"android","environment":null,"entry":"node_modules/expo-router/entry.js"}
+{"_e":"metro:bundling:progress","_t":1786708912534,"id":"3","progress":0,"total":1,"current":0}
+{"_e":"metro:bundling:progress","_t":1786708912538,"id":"3","progress":0,"total":1,"current":0}
+{"_e":"metro:bundling:progress","_t":1786708912638,"id":"3","progress":0.17693373645754598,"total":378,"current":159}
+{"_e":"metro:bundling:progress","_t":1786708912738,"id":"3","progress":0.466776091676154,"total":947,"current":647}
+{"_e":"metro:bundling:progress","_t":1786708912840,"id":"3","progress":0.7518748881428149,"total":1362,"current":1181}
+{"_e":"metro:bundling:progress","_t":1786708912945,"id":"3","progress":0.8895057571869575,"total":1741,"current":1642}
+{"_e":"metro:bundling:progress","_t":1786708913044,"id":"3","progress":0.9989062073555536,"total":1828,"current":1827}
+{"_e":"metro:bundling:progress","_t":1786708913146,"id":"3","progress":0.9989062073555536,"total":1841,"current":1830}
+{"_e":"metro:bundling:progress","_t":1786708913248,"id":"3","progress":0.9989062073555536,"total":1862,"current":1834}
+{"_e":"metro:bundling:progress","_t":1786708913365,"id":"3","progress":0.9989062073555536,"total":1870,"current":1841}
+{"_e":"metro:bundling:progress","_t":1786708913476,"id":"3","progress":0.9989062073555536,"total":1870,"current":1845}
+{"_e":"metro:bundling:progress","_t":1786708913584,"id":"3","progress":0.9989062073555536,"total":1870,"current":1852}
+{"_e":"metro:bundling:progress","_t":1786708913684,"id":"3","progress":0.9989062073555536,"total":1872,"current":1862}
+{"_e":"metro:bundling:progress","_t":1786708913785,"id":"3","progress":0.9989062073555536,"total":1888,"current":1873}
+{"_e":"metro:bundling:progress","_t":1786708913885,"id":"3","progress":0.9989062073555536,"total":1972,"current":1894}
+{"_e":"metro:bundling:progress","_t":1786708913985,"id":"3","progress":0.9989062073555536,"total":1979,"current":1935}
+{"_e":"metro:bundling:progress","_t":1786708914086,"id":"3","progress":0.9989062073555536,"total":1993,"current":1989}
+{"_e":"metro:bundling:done","_t":1786708914220,"id":"3","total":1993,"ms":1686.217166}
+{"_e":"metro:bundling:started","_t":1786709009016,"id":"9","platform":"android","environment":null,"entry":"node_modules/expo-router/entry.js"}
+{"_e":"metro:bundling:progress","_t":1786709009017,"id":"9","progress":0,"total":1,"current":0}
+{"_e":"metro:bundling:progress","_t":1786709009029,"id":"9","progress":0,"total":1,"current":0}
+{"_e":"metro:bundling:done","_t":1786709009122,"id":"9","total":1,"ms":105.456209}
+{"_e":"metro:client_log","_t":1786709014683,"level":"warn","data":["[Layout children]: Too many screens defined. Route \"salary\" is extraneous."]}
+{"_e":"metro:client_log","_t":1786709014699,"level":"warn","data":["[Layout children]: Too many screens defined. Route \"recurring\" is extraneous."]}
+{"_e":"metro:client_log","_t":1786709014699,"level":"warn","data":["[Layout children]: Too many screens defined. Route \"expenses\" is extraneous."]}
+{"_e":"metro:bundling:started","_t":1786709571016,"id":"a","platform":"android","environment":null,"entry":"node_modules/expo-router/entry.js"}
+{"_e":"metro:bundling:progress","_t":1786709571017,"id":"a","progress":0,"total":1,"current":0}
+{"_e":"metro:bundling:progress","_t":1786709571026,"id":"a","progress":0,"total":1,"current":0}
+{"_e":"metro:bundling:failed","_t":1786709571112,"id":"a","message":"As of SDK 56, expo-router is no longer compatible with react-navigation. For more information, see https://docs.expo.dev/router/migrate/sdk-55-to-56/. You can disable this check by setting the environment variable EXPO_ROUTER_DISABLE_RN_NAVIGATION_CHECK=1.","importStack":"\u001b[1mImport stack:\u001b[22m\n\n\u001b[90m \u001b[39msrc/screens/salary-screen.tsx\n\u001b[90m |\u001b[39m \u001b[36mimport\u001b[39m \u001b[32m\"@react-navigation/native\"\u001b[39m\n\n\u001b[90m \u001b[39msrc/app/(app)/(tabs)/salary.tsx\n\u001b[90m |\u001b[39m \u001b[36mimport\u001b[39m \u001b[32m\"@/screens/salary-screen\"\u001b[39m\n\n\u001b[90m \u001b[39msrc/app\u001b[2m (require.context)\u001b[22m\n","filename":null,"targetModuleName":null,"originModulePath":null}
+{"_e":"metro:bundling:started","_t":1786709812789,"id":"b","platform":"android","environment":null,"entry":"node_modules/expo-router/entry.js"}
+{"_e":"metro:bundling:progress","_t":1786709812790,"id":"b","progress":0,"total":1,"current":0}
+{"_e":"metro:bundling:progress","_t":1786709812798,"id":"b","progress":0,"total":1,"current":0}
+{"_e":"metro:bundling:progress","_t":1786709812899,"id":"b","progress":0,"total":1,"current":0}
+{"_e":"metro:bundling:done","_t":1786709812977,"id":"b","total":1,"ms":186.96025}
+{"_e":"metro:client_log","_t":1786709818803,"level":"warn","data":["[Layout children]: Too many screens defined. Route \"recurring\" is extraneous."]}
+{"_e":"metro:client_log","_t":1786709818828,"level":"warn","data":["[Layout children]: Too many screens defined. Route \"expenses\" is extraneous."]}
+{"_e":"metro:server_log","_t":1786710024430,"level":"error","data":["[timeout] connection terminated with Device for app='%s' on device='%s' after not responding for %s seconds.","com.anonymous.yaba","SM-S918B - 16 - API 36","60"]}
+{"_e":"metro:bundling:started","_t":1786730119994,"id":"c","platform":"android","environment":null,"entry":"node_modules/expo-router/entry.js"}
+{"_e":"metro:bundling:progress","_t":1786730119996,"id":"c","progress":0,"total":1,"current":0}
+{"_e":"metro:bundling:progress","_t":1786730120004,"id":"c","progress":0,"total":1,"current":0}
+{"_e":"metro:bundling:progress","_t":1786730120104,"id":"c","progress":0,"total":1,"current":0}
+{"_e":"metro:bundling:progress","_t":1786730120287,"id":"c","progress":0,"total":1,"current":0}
+{"_e":"metro:bundling:progress","_t":1786730120389,"id":"c","progress":0,"total":1,"current":0}
+{"_e":"metro:bundling:progress","_t":1786730120502,"id":"c","progress":0,"total":1,"current":0}
+{"_e":"metro:bundling:progress","_t":1786730120603,"id":"c","progress":0,"total":1,"current":0}
+{"_e":"metro:bundling:failed","_t":1786730120702,"id":"c","message":"As of SDK 56, expo-router is no longer compatible with react-navigation. For more information, see https://docs.expo.dev/router/migrate/sdk-55-to-56/. You can disable this check by setting the environment variable EXPO_ROUTER_DISABLE_RN_NAVIGATION_CHECK=1.","importStack":"\u001b[1mImport stack:\u001b[22m\n\n\u001b[90m \u001b[39msrc/screens/recurring-expenses-screen.tsx\n\u001b[90m |\u001b[39m \u001b[36mimport\u001b[39m \u001b[32m\"@react-navigation/native\"\u001b[39m\n\n\u001b[90m \u001b[39msrc/app/(app)/(tabs)/recurring.tsx\n\u001b[90m |\u001b[39m \u001b[36mimport\u001b[39m \u001b[32m\"@/screens/recurring-expenses-screen\"\u001b[39m\n\n\u001b[90m \u001b[39msrc/app\u001b[2m (require.context)\u001b[22m\n","filename":null,"targetModuleName":null,"originModulePath":null}
+{"_e":"metro:bundling:started","_t":1786730134607,"id":"d","platform":"android","environment":null,"entry":"node_modules/expo-router/entry.js"}
+{"_e":"metro:bundling:progress","_t":1786730134607,"id":"d","progress":0,"total":1,"current":0}
+{"_e":"metro:bundling:progress","_t":1786730134615,"id":"d","progress":0,"total":1,"current":0}
+{"_e":"metro:bundling:progress","_t":1786730134717,"id":"d","progress":0,"total":1,"current":0}
+{"_e":"metro:bundling:progress","_t":1786730134818,"id":"d","progress":0,"total":1,"current":0}
+{"_e":"metro:bundling:done","_t":1786730134882,"id":"d","total":1,"ms":274.4905}
+{"_e":"metro:client_log","_t":1786730140883,"level":"warn","data":["[Layout children]: Too many screens defined. Route \"expenses\" is extraneous."]}
+{"_e":"metro:bundling:started","_t":1786730330101,"id":"e","platform":"android","environment":null,"entry":"node_modules/expo-router/entry.js"}
+{"_e":"metro:bundling:progress","_t":1786730330102,"id":"e","progress":0,"total":1,"current":0}
+{"_e":"metro:bundling:progress","_t":1786730330110,"id":"e","progress":0,"total":1,"current":0}
+{"_e":"metro:bundling:done","_t":1786730330242,"id":"e","total":1,"ms":140.914208}
+{"_e":"metro:bundling:started","_t":1786730404864,"id":"f","platform":"android","environment":null,"entry":"node_modules/expo-router/entry.js"}
+{"_e":"metro:bundling:progress","_t":1786730404865,"id":"f","progress":0,"total":1,"current":0}
+{"_e":"metro:bundling:done","_t":1786730404939,"id":"f","total":1,"ms":73.694709}
diff --git a/.expo/devices.json b/.expo/devices.json
new file mode 100644
index 0000000..571b1da
--- /dev/null
+++ b/.expo/devices.json
@@ -0,0 +1,8 @@
+{
+ "devices": [
+ {
+ "installationId": "f06b0747-5dd9-402d-ad65-d21673fd02e8",
+ "lastUsed": 1786730404334
+ }
+ ]
+}
diff --git a/.expo/types/router.d.ts b/.expo/types/router.d.ts
new file mode 100644
index 0000000..fe9ff7f
--- /dev/null
+++ b/.expo/types/router.d.ts
@@ -0,0 +1,14 @@
+/* eslint-disable */
+import * as Router from 'expo-router';
+
+export * from 'expo-router';
+
+declare module 'expo-router' {
+ export namespace ExpoRouter {
+ export interface __routes<T extends string | object = string> {
+ hrefInputParams: { pathname: Router.RelativePathString, params?: Router.UnknownInputParams } | { pathname: Router.ExternalPathString, params?: Router.UnknownInputParams } | { pathname: `/biometrics`; params?: Router.UnknownInputParams; } | { pathname: `/login`; params?: Router.UnknownInputParams; } | { pathname: `/register`; params?: Router.UnknownInputParams; } | { pathname: `/_sitemap`; params?: Router.UnknownInputParams; } | { pathname: `${'/(app)'}${'/(tabs)'}` | `/`; params?: Router.UnknownInputParams; } | { pathname: `${'/(app)'}${'/(tabs)'}/salary` | `/salary`; params?: Router.UnknownInputParams; } | { pathname: `${'/(app)'}${'/(tabs)'}/recurring` | `/recurring`; params?: Router.UnknownInputParams; } | { pathname: `${'/(app)'}${'/(tabs)'}/expenses` | `/expenses`; params?: Router.UnknownInputParams; };
+ hrefOutputParams: { pathname: Router.RelativePathString, params?: Router.UnknownOutputParams } | { pathname: Router.ExternalPathString, params?: Router.UnknownOutputParams } | { pathname: `/biometrics`; params?: Router.UnknownOutputParams; } | { pathname: `/login`; params?: Router.UnknownOutputParams; } | { pathname: `/register`; params?: Router.UnknownOutputParams; } | { pathname: `/_sitemap`; params?: Router.UnknownOutputParams; } | { pathname: `${'/(app)'}${'/(tabs)'}` | `/`; params?: Router.UnknownOutputParams; } | { pathname: `${'/(app)'}${'/(tabs)'}/salary` | `/salary`; params?: Router.UnknownOutputParams; } | { pathname: `${'/(app)'}${'/(tabs)'}/recurring` | `/recurring`; params?: Router.UnknownOutputParams; } | { pathname: `${'/(app)'}${'/(tabs)'}/expenses` | `/expenses`; params?: Router.UnknownOutputParams; };
+ href: Router.RelativePathString | Router.ExternalPathString | `/biometrics${`?${string}` | `#${string}` | ''}` | `/login${`?${string}` | `#${string}` | ''}` | `/register${`?${string}` | `#${string}` | ''}` | `/_sitemap${`?${string}` | `#${string}` | ''}` | `${'/(app)'}${'/(tabs)'}${`?${string}` | `#${string}` | ''}` | `/${`?${string}` | `#${string}` | ''}` | `${'/(app)'}${'/(tabs)'}/salary${`?${string}` | `#${string}` | ''}` | `/salary${`?${string}` | `#${string}` | ''}` | `${'/(app)'}${'/(tabs)'}/recurring${`?${string}` | `#${string}` | ''}` | `/recurring${`?${string}` | `#${string}` | ''}` | `${'/(app)'}${'/(tabs)'}/expenses${`?${string}` | `#${string}` | ''}` | `/expenses${`?${string}` | `#${string}` | ''}` | { pathname: Router.RelativePathString, params?: Router.UnknownInputParams } | { pathname: Router.ExternalPathString, params?: Router.UnknownInputParams } | { pathname: `/biometrics`; params?: Router.UnknownInputParams; } | { pathname: `/login`; params?: Router.UnknownInputParams; } | { pathname: `/register`; params?: Router.UnknownInputParams; } | { pathname: `/_sitemap`; params?: Router.UnknownInputParams; } | { pathname: `${'/(app)'}${'/(tabs)'}` | `/`; params?: Router.UnknownInputParams; } | { pathname: `${'/(app)'}${'/(tabs)'}/salary` | `/salary`; params?: Router.UnknownInputParams; } | { pathname: `${'/(app)'}${'/(tabs)'}/recurring` | `/recurring`; params?: Router.UnknownInputParams; } | { pathname: `${'/(app)'}${'/(tabs)'}/expenses` | `/expenses`; params?: Router.UnknownInputParams; };
+ }
+ }
+}
diff --git a/.expo/web/cache/production/images/android-adaptive-background/android-adaptive-background-fb139c2dee362ebf2070e23b96da6fc0d43f8492de38b8af1fd7223e19b5861d-cover-transparent/icon_108.png b/.expo/web/cache/production/images/android-adaptive-background/android-adaptive-background-fb139c2dee362ebf2070e23b96da6fc0d43f8492de38b8af1fd7223e19b5861d-cover-transparent/icon_108.png
new file mode 100644
index 0000000..1e9b3d1
--- /dev/null
+++ b/.expo/web/cache/production/images/android-adaptive-background/android-adaptive-background-fb139c2dee362ebf2070e23b96da6fc0d43f8492de38b8af1fd7223e19b5861d-cover-transparent/icon_108.png
Binary files differ
diff --git a/.expo/web/cache/production/images/android-adaptive-background/android-adaptive-background-fb139c2dee362ebf2070e23b96da6fc0d43f8492de38b8af1fd7223e19b5861d-cover-transparent/icon_162.png b/.expo/web/cache/production/images/android-adaptive-background/android-adaptive-background-fb139c2dee362ebf2070e23b96da6fc0d43f8492de38b8af1fd7223e19b5861d-cover-transparent/icon_162.png
new file mode 100644
index 0000000..c02225f
--- /dev/null
+++ b/.expo/web/cache/production/images/android-adaptive-background/android-adaptive-background-fb139c2dee362ebf2070e23b96da6fc0d43f8492de38b8af1fd7223e19b5861d-cover-transparent/icon_162.png
Binary files differ
diff --git a/.expo/web/cache/production/images/android-adaptive-background/android-adaptive-background-fb139c2dee362ebf2070e23b96da6fc0d43f8492de38b8af1fd7223e19b5861d-cover-transparent/icon_216.png b/.expo/web/cache/production/images/android-adaptive-background/android-adaptive-background-fb139c2dee362ebf2070e23b96da6fc0d43f8492de38b8af1fd7223e19b5861d-cover-transparent/icon_216.png
new file mode 100644
index 0000000..dde133a
--- /dev/null
+++ b/.expo/web/cache/production/images/android-adaptive-background/android-adaptive-background-fb139c2dee362ebf2070e23b96da6fc0d43f8492de38b8af1fd7223e19b5861d-cover-transparent/icon_216.png
Binary files differ
diff --git a/.expo/web/cache/production/images/android-adaptive-background/android-adaptive-background-fb139c2dee362ebf2070e23b96da6fc0d43f8492de38b8af1fd7223e19b5861d-cover-transparent/icon_324.png b/.expo/web/cache/production/images/android-adaptive-background/android-adaptive-background-fb139c2dee362ebf2070e23b96da6fc0d43f8492de38b8af1fd7223e19b5861d-cover-transparent/icon_324.png
new file mode 100644
index 0000000..55a3581
--- /dev/null
+++ b/.expo/web/cache/production/images/android-adaptive-background/android-adaptive-background-fb139c2dee362ebf2070e23b96da6fc0d43f8492de38b8af1fd7223e19b5861d-cover-transparent/icon_324.png
Binary files differ
diff --git a/.expo/web/cache/production/images/android-adaptive-background/android-adaptive-background-fb139c2dee362ebf2070e23b96da6fc0d43f8492de38b8af1fd7223e19b5861d-cover-transparent/icon_432.png b/.expo/web/cache/production/images/android-adaptive-background/android-adaptive-background-fb139c2dee362ebf2070e23b96da6fc0d43f8492de38b8af1fd7223e19b5861d-cover-transparent/icon_432.png
new file mode 100644
index 0000000..d190cdd
--- /dev/null
+++ b/.expo/web/cache/production/images/android-adaptive-background/android-adaptive-background-fb139c2dee362ebf2070e23b96da6fc0d43f8492de38b8af1fd7223e19b5861d-cover-transparent/icon_432.png
Binary files differ
diff --git a/.expo/web/cache/production/images/android-adaptive-foreground/android-adaptive-foreground-9e3d0315a33c6799de601dd34cd8bf8cc3a8d16f3bf75592baec2ceb7240b391-cover-transparent/icon_108.png b/.expo/web/cache/production/images/android-adaptive-foreground/android-adaptive-foreground-9e3d0315a33c6799de601dd34cd8bf8cc3a8d16f3bf75592baec2ceb7240b391-cover-transparent/icon_108.png
new file mode 100644
index 0000000..46ea7d0
--- /dev/null
+++ b/.expo/web/cache/production/images/android-adaptive-foreground/android-adaptive-foreground-9e3d0315a33c6799de601dd34cd8bf8cc3a8d16f3bf75592baec2ceb7240b391-cover-transparent/icon_108.png
Binary files differ
diff --git a/.expo/web/cache/production/images/android-adaptive-foreground/android-adaptive-foreground-9e3d0315a33c6799de601dd34cd8bf8cc3a8d16f3bf75592baec2ceb7240b391-cover-transparent/icon_162.png b/.expo/web/cache/production/images/android-adaptive-foreground/android-adaptive-foreground-9e3d0315a33c6799de601dd34cd8bf8cc3a8d16f3bf75592baec2ceb7240b391-cover-transparent/icon_162.png
new file mode 100644
index 0000000..49a260f
--- /dev/null
+++ b/.expo/web/cache/production/images/android-adaptive-foreground/android-adaptive-foreground-9e3d0315a33c6799de601dd34cd8bf8cc3a8d16f3bf75592baec2ceb7240b391-cover-transparent/icon_162.png
Binary files differ
diff --git a/.expo/web/cache/production/images/android-adaptive-foreground/android-adaptive-foreground-9e3d0315a33c6799de601dd34cd8bf8cc3a8d16f3bf75592baec2ceb7240b391-cover-transparent/icon_216.png b/.expo/web/cache/production/images/android-adaptive-foreground/android-adaptive-foreground-9e3d0315a33c6799de601dd34cd8bf8cc3a8d16f3bf75592baec2ceb7240b391-cover-transparent/icon_216.png
new file mode 100644
index 0000000..671b75f
--- /dev/null
+++ b/.expo/web/cache/production/images/android-adaptive-foreground/android-adaptive-foreground-9e3d0315a33c6799de601dd34cd8bf8cc3a8d16f3bf75592baec2ceb7240b391-cover-transparent/icon_216.png
Binary files differ
diff --git a/.expo/web/cache/production/images/android-adaptive-foreground/android-adaptive-foreground-9e3d0315a33c6799de601dd34cd8bf8cc3a8d16f3bf75592baec2ceb7240b391-cover-transparent/icon_324.png b/.expo/web/cache/production/images/android-adaptive-foreground/android-adaptive-foreground-9e3d0315a33c6799de601dd34cd8bf8cc3a8d16f3bf75592baec2ceb7240b391-cover-transparent/icon_324.png
new file mode 100644
index 0000000..ba86612
--- /dev/null
+++ b/.expo/web/cache/production/images/android-adaptive-foreground/android-adaptive-foreground-9e3d0315a33c6799de601dd34cd8bf8cc3a8d16f3bf75592baec2ceb7240b391-cover-transparent/icon_324.png
Binary files differ
diff --git a/.expo/web/cache/production/images/android-adaptive-foreground/android-adaptive-foreground-9e3d0315a33c6799de601dd34cd8bf8cc3a8d16f3bf75592baec2ceb7240b391-cover-transparent/icon_432.png b/.expo/web/cache/production/images/android-adaptive-foreground/android-adaptive-foreground-9e3d0315a33c6799de601dd34cd8bf8cc3a8d16f3bf75592baec2ceb7240b391-cover-transparent/icon_432.png
new file mode 100644
index 0000000..3468026
--- /dev/null
+++ b/.expo/web/cache/production/images/android-adaptive-foreground/android-adaptive-foreground-9e3d0315a33c6799de601dd34cd8bf8cc3a8d16f3bf75592baec2ceb7240b391-cover-transparent/icon_432.png
Binary files differ
diff --git a/.expo/web/cache/production/images/android-adaptive-monochrome/android-adaptive-monochrome-6371fc2c12e33ad2215a86c281db3d682a81bebe7c957a842c13b8bf00cceb83-cover-transparent/icon_108.png b/.expo/web/cache/production/images/android-adaptive-monochrome/android-adaptive-monochrome-6371fc2c12e33ad2215a86c281db3d682a81bebe7c957a842c13b8bf00cceb83-cover-transparent/icon_108.png
new file mode 100644
index 0000000..12a3278
--- /dev/null
+++ b/.expo/web/cache/production/images/android-adaptive-monochrome/android-adaptive-monochrome-6371fc2c12e33ad2215a86c281db3d682a81bebe7c957a842c13b8bf00cceb83-cover-transparent/icon_108.png
Binary files differ
diff --git a/.expo/web/cache/production/images/android-adaptive-monochrome/android-adaptive-monochrome-6371fc2c12e33ad2215a86c281db3d682a81bebe7c957a842c13b8bf00cceb83-cover-transparent/icon_162.png b/.expo/web/cache/production/images/android-adaptive-monochrome/android-adaptive-monochrome-6371fc2c12e33ad2215a86c281db3d682a81bebe7c957a842c13b8bf00cceb83-cover-transparent/icon_162.png
new file mode 100644
index 0000000..fc1087b
--- /dev/null
+++ b/.expo/web/cache/production/images/android-adaptive-monochrome/android-adaptive-monochrome-6371fc2c12e33ad2215a86c281db3d682a81bebe7c957a842c13b8bf00cceb83-cover-transparent/icon_162.png
Binary files differ
diff --git a/.expo/web/cache/production/images/android-adaptive-monochrome/android-adaptive-monochrome-6371fc2c12e33ad2215a86c281db3d682a81bebe7c957a842c13b8bf00cceb83-cover-transparent/icon_216.png b/.expo/web/cache/production/images/android-adaptive-monochrome/android-adaptive-monochrome-6371fc2c12e33ad2215a86c281db3d682a81bebe7c957a842c13b8bf00cceb83-cover-transparent/icon_216.png
new file mode 100644
index 0000000..2809d31
--- /dev/null
+++ b/.expo/web/cache/production/images/android-adaptive-monochrome/android-adaptive-monochrome-6371fc2c12e33ad2215a86c281db3d682a81bebe7c957a842c13b8bf00cceb83-cover-transparent/icon_216.png
Binary files differ
diff --git a/.expo/web/cache/production/images/android-adaptive-monochrome/android-adaptive-monochrome-6371fc2c12e33ad2215a86c281db3d682a81bebe7c957a842c13b8bf00cceb83-cover-transparent/icon_324.png b/.expo/web/cache/production/images/android-adaptive-monochrome/android-adaptive-monochrome-6371fc2c12e33ad2215a86c281db3d682a81bebe7c957a842c13b8bf00cceb83-cover-transparent/icon_324.png
new file mode 100644
index 0000000..9dbe470
--- /dev/null
+++ b/.expo/web/cache/production/images/android-adaptive-monochrome/android-adaptive-monochrome-6371fc2c12e33ad2215a86c281db3d682a81bebe7c957a842c13b8bf00cceb83-cover-transparent/icon_324.png
Binary files differ
diff --git a/.expo/web/cache/production/images/android-adaptive-monochrome/android-adaptive-monochrome-6371fc2c12e33ad2215a86c281db3d682a81bebe7c957a842c13b8bf00cceb83-cover-transparent/icon_432.png b/.expo/web/cache/production/images/android-adaptive-monochrome/android-adaptive-monochrome-6371fc2c12e33ad2215a86c281db3d682a81bebe7c957a842c13b8bf00cceb83-cover-transparent/icon_432.png
new file mode 100644
index 0000000..8736a27
--- /dev/null
+++ b/.expo/web/cache/production/images/android-adaptive-monochrome/android-adaptive-monochrome-6371fc2c12e33ad2215a86c281db3d682a81bebe7c957a842c13b8bf00cceb83-cover-transparent/icon_432.png
Binary files differ
diff --git a/.expo/web/cache/production/images/android-standard-circle/android-standard-circle-7a667804bb80a6a424a5daf18a2599c4f32237cf06fe78fc0de45dbb09e0eccf-cover-transparent/icon_144.png b/.expo/web/cache/production/images/android-standard-circle/android-standard-circle-7a667804bb80a6a424a5daf18a2599c4f32237cf06fe78fc0de45dbb09e0eccf-cover-transparent/icon_144.png
new file mode 100644
index 0000000..c8c582d
--- /dev/null
+++ b/.expo/web/cache/production/images/android-standard-circle/android-standard-circle-7a667804bb80a6a424a5daf18a2599c4f32237cf06fe78fc0de45dbb09e0eccf-cover-transparent/icon_144.png
Binary files differ
diff --git a/.expo/web/cache/production/images/android-standard-circle/android-standard-circle-7a667804bb80a6a424a5daf18a2599c4f32237cf06fe78fc0de45dbb09e0eccf-cover-transparent/icon_192.png b/.expo/web/cache/production/images/android-standard-circle/android-standard-circle-7a667804bb80a6a424a5daf18a2599c4f32237cf06fe78fc0de45dbb09e0eccf-cover-transparent/icon_192.png
new file mode 100644
index 0000000..2c3e350
--- /dev/null
+++ b/.expo/web/cache/production/images/android-standard-circle/android-standard-circle-7a667804bb80a6a424a5daf18a2599c4f32237cf06fe78fc0de45dbb09e0eccf-cover-transparent/icon_192.png
Binary files differ
diff --git a/.expo/web/cache/production/images/android-standard-circle/android-standard-circle-7a667804bb80a6a424a5daf18a2599c4f32237cf06fe78fc0de45dbb09e0eccf-cover-transparent/icon_48.png b/.expo/web/cache/production/images/android-standard-circle/android-standard-circle-7a667804bb80a6a424a5daf18a2599c4f32237cf06fe78fc0de45dbb09e0eccf-cover-transparent/icon_48.png
new file mode 100644
index 0000000..dd4b27a
--- /dev/null
+++ b/.expo/web/cache/production/images/android-standard-circle/android-standard-circle-7a667804bb80a6a424a5daf18a2599c4f32237cf06fe78fc0de45dbb09e0eccf-cover-transparent/icon_48.png
Binary files differ
diff --git a/.expo/web/cache/production/images/android-standard-circle/android-standard-circle-7a667804bb80a6a424a5daf18a2599c4f32237cf06fe78fc0de45dbb09e0eccf-cover-transparent/icon_72.png b/.expo/web/cache/production/images/android-standard-circle/android-standard-circle-7a667804bb80a6a424a5daf18a2599c4f32237cf06fe78fc0de45dbb09e0eccf-cover-transparent/icon_72.png
new file mode 100644
index 0000000..2153670
--- /dev/null
+++ b/.expo/web/cache/production/images/android-standard-circle/android-standard-circle-7a667804bb80a6a424a5daf18a2599c4f32237cf06fe78fc0de45dbb09e0eccf-cover-transparent/icon_72.png
Binary files differ
diff --git a/.expo/web/cache/production/images/android-standard-circle/android-standard-circle-7a667804bb80a6a424a5daf18a2599c4f32237cf06fe78fc0de45dbb09e0eccf-cover-transparent/icon_96.png b/.expo/web/cache/production/images/android-standard-circle/android-standard-circle-7a667804bb80a6a424a5daf18a2599c4f32237cf06fe78fc0de45dbb09e0eccf-cover-transparent/icon_96.png
new file mode 100644
index 0000000..79a6f3d
--- /dev/null
+++ b/.expo/web/cache/production/images/android-standard-circle/android-standard-circle-7a667804bb80a6a424a5daf18a2599c4f32237cf06fe78fc0de45dbb09e0eccf-cover-transparent/icon_96.png
Binary files differ
diff --git a/.expo/web/cache/production/images/android-standard-square/android-standard-square-7a667804bb80a6a424a5daf18a2599c4f32237cf06fe78fc0de45dbb09e0eccf-cover-transparent/icon_144.png b/.expo/web/cache/production/images/android-standard-square/android-standard-square-7a667804bb80a6a424a5daf18a2599c4f32237cf06fe78fc0de45dbb09e0eccf-cover-transparent/icon_144.png
new file mode 100644
index 0000000..05e3e1c
--- /dev/null
+++ b/.expo/web/cache/production/images/android-standard-square/android-standard-square-7a667804bb80a6a424a5daf18a2599c4f32237cf06fe78fc0de45dbb09e0eccf-cover-transparent/icon_144.png
Binary files differ
diff --git a/.expo/web/cache/production/images/android-standard-square/android-standard-square-7a667804bb80a6a424a5daf18a2599c4f32237cf06fe78fc0de45dbb09e0eccf-cover-transparent/icon_192.png b/.expo/web/cache/production/images/android-standard-square/android-standard-square-7a667804bb80a6a424a5daf18a2599c4f32237cf06fe78fc0de45dbb09e0eccf-cover-transparent/icon_192.png
new file mode 100644
index 0000000..13f9687
--- /dev/null
+++ b/.expo/web/cache/production/images/android-standard-square/android-standard-square-7a667804bb80a6a424a5daf18a2599c4f32237cf06fe78fc0de45dbb09e0eccf-cover-transparent/icon_192.png
Binary files differ
diff --git a/.expo/web/cache/production/images/android-standard-square/android-standard-square-7a667804bb80a6a424a5daf18a2599c4f32237cf06fe78fc0de45dbb09e0eccf-cover-transparent/icon_48.png b/.expo/web/cache/production/images/android-standard-square/android-standard-square-7a667804bb80a6a424a5daf18a2599c4f32237cf06fe78fc0de45dbb09e0eccf-cover-transparent/icon_48.png
new file mode 100644
index 0000000..7d14513
--- /dev/null
+++ b/.expo/web/cache/production/images/android-standard-square/android-standard-square-7a667804bb80a6a424a5daf18a2599c4f32237cf06fe78fc0de45dbb09e0eccf-cover-transparent/icon_48.png
Binary files differ
diff --git a/.expo/web/cache/production/images/android-standard-square/android-standard-square-7a667804bb80a6a424a5daf18a2599c4f32237cf06fe78fc0de45dbb09e0eccf-cover-transparent/icon_72.png b/.expo/web/cache/production/images/android-standard-square/android-standard-square-7a667804bb80a6a424a5daf18a2599c4f32237cf06fe78fc0de45dbb09e0eccf-cover-transparent/icon_72.png
new file mode 100644
index 0000000..6b743ad
--- /dev/null
+++ b/.expo/web/cache/production/images/android-standard-square/android-standard-square-7a667804bb80a6a424a5daf18a2599c4f32237cf06fe78fc0de45dbb09e0eccf-cover-transparent/icon_72.png
Binary files differ
diff --git a/.expo/web/cache/production/images/android-standard-square/android-standard-square-7a667804bb80a6a424a5daf18a2599c4f32237cf06fe78fc0de45dbb09e0eccf-cover-transparent/icon_96.png b/.expo/web/cache/production/images/android-standard-square/android-standard-square-7a667804bb80a6a424a5daf18a2599c4f32237cf06fe78fc0de45dbb09e0eccf-cover-transparent/icon_96.png
new file mode 100644
index 0000000..553d6b5
--- /dev/null
+++ b/.expo/web/cache/production/images/android-standard-square/android-standard-square-7a667804bb80a6a424a5daf18a2599c4f32237cf06fe78fc0de45dbb09e0eccf-cover-transparent/icon_96.png
Binary files differ
diff --git a/.expo/web/cache/production/images/splash-android/splash-android-27b060a757a29038c9618586baa0ba3894dbe60d084c6059df497ff429c2d92f-contain/icon_114.png b/.expo/web/cache/production/images/splash-android/splash-android-27b060a757a29038c9618586baa0ba3894dbe60d084c6059df497ff429c2d92f-contain/icon_114.png
new file mode 100644
index 0000000..6c88010
--- /dev/null
+++ b/.expo/web/cache/production/images/splash-android/splash-android-27b060a757a29038c9618586baa0ba3894dbe60d084c6059df497ff429c2d92f-contain/icon_114.png
Binary files differ
diff --git a/.expo/web/cache/production/images/splash-android/splash-android-27b060a757a29038c9618586baa0ba3894dbe60d084c6059df497ff429c2d92f-contain/icon_152.png b/.expo/web/cache/production/images/splash-android/splash-android-27b060a757a29038c9618586baa0ba3894dbe60d084c6059df497ff429c2d92f-contain/icon_152.png
new file mode 100644
index 0000000..c0a217a
--- /dev/null
+++ b/.expo/web/cache/production/images/splash-android/splash-android-27b060a757a29038c9618586baa0ba3894dbe60d084c6059df497ff429c2d92f-contain/icon_152.png
Binary files differ
diff --git a/.expo/web/cache/production/images/splash-android/splash-android-27b060a757a29038c9618586baa0ba3894dbe60d084c6059df497ff429c2d92f-contain/icon_228.png b/.expo/web/cache/production/images/splash-android/splash-android-27b060a757a29038c9618586baa0ba3894dbe60d084c6059df497ff429c2d92f-contain/icon_228.png
new file mode 100644
index 0000000..c9289ca
--- /dev/null
+++ b/.expo/web/cache/production/images/splash-android/splash-android-27b060a757a29038c9618586baa0ba3894dbe60d084c6059df497ff429c2d92f-contain/icon_228.png
Binary files differ
diff --git a/.expo/web/cache/production/images/splash-android/splash-android-27b060a757a29038c9618586baa0ba3894dbe60d084c6059df497ff429c2d92f-contain/icon_304.png b/.expo/web/cache/production/images/splash-android/splash-android-27b060a757a29038c9618586baa0ba3894dbe60d084c6059df497ff429c2d92f-contain/icon_304.png
new file mode 100644
index 0000000..365ebab
--- /dev/null
+++ b/.expo/web/cache/production/images/splash-android/splash-android-27b060a757a29038c9618586baa0ba3894dbe60d084c6059df497ff429c2d92f-contain/icon_304.png
Binary files differ
diff --git a/.expo/web/cache/production/images/splash-android/splash-android-27b060a757a29038c9618586baa0ba3894dbe60d084c6059df497ff429c2d92f-contain/icon_76.png b/.expo/web/cache/production/images/splash-android/splash-android-27b060a757a29038c9618586baa0ba3894dbe60d084c6059df497ff429c2d92f-contain/icon_76.png
new file mode 100644
index 0000000..dd7546a
--- /dev/null
+++ b/.expo/web/cache/production/images/splash-android/splash-android-27b060a757a29038c9618586baa0ba3894dbe60d084c6059df497ff429c2d92f-contain/icon_76.png
Binary files differ
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..041ad3c
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,10 @@
+
+# @generated expo-cli sync-2b81b286409207a5da26e14c78851eb30d8ccbdb
+# The following patterns were generated by expo-cli
+
+expo-env.d.ts
+# @end expo-cli
+
+node_modules/
+android/
+ios/ \ No newline at end of file
diff --git a/AGENTS.md b/AGENTS.md
new file mode 100644
index 0000000..0e6bc80
--- /dev/null
+++ b/AGENTS.md
@@ -0,0 +1,3 @@
+# Expo HAS CHANGED
+
+Read the exact versioned docs at https://docs.expo.dev/versions/v57.0.0/ before writing any code.
diff --git a/CLAUDE.md b/CLAUDE.md
new file mode 100644
index 0000000..43c994c
--- /dev/null
+++ b/CLAUDE.md
@@ -0,0 +1 @@
+@AGENTS.md
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..30b20e3
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2015-present 650 Industries, Inc. (aka Expo)
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..4d67aec
--- /dev/null
+++ b/README.md
@@ -0,0 +1,56 @@
+# Welcome to your Expo app 👋
+
+This is an [Expo](https://expo.dev) project created with [`create-expo-app`](https://www.npmjs.com/package/create-expo-app).
+
+## Get started
+
+1. Install dependencies
+
+ ```bash
+ npm install
+ ```
+
+2. Start the app
+
+ ```bash
+ npx expo start
+ ```
+
+In the output, you'll find options to open the app in a
+
+- [development build](https://docs.expo.dev/develop/development-builds/introduction/)
+- [Android emulator](https://docs.expo.dev/workflow/android-studio-emulator/)
+- [iOS simulator](https://docs.expo.dev/workflow/ios-simulator/)
+- [Expo Go](https://expo.dev/go), a limited sandbox for trying out app development with Expo
+
+You can start developing by editing the files inside the **app** directory. This project uses [file-based routing](https://docs.expo.dev/router/introduction).
+
+## Get a fresh project
+
+When you're ready, run:
+
+```bash
+npm run reset-project
+```
+
+This command will move the starter code to the **app-example** directory and create a blank **app** directory where you can start developing.
+
+### Other setup steps
+
+- To set up ESLint for linting, run `npx expo lint`, or follow our guide on ["Using ESLint and Prettier"](https://docs.expo.dev/guides/using-eslint/)
+- If you'd like to set up unit testing, follow our guide on ["Unit Testing with Jest"](https://docs.expo.dev/develop/unit-testing/)
+- Learn more about the TypeScript setup in this template in our guide on ["Using TypeScript"](https://docs.expo.dev/guides/typescript/)
+
+## Learn more
+
+To learn more about developing your project with Expo, look at the following resources:
+
+- [Expo documentation](https://docs.expo.dev/): Learn fundamentals, or go into advanced topics with our [guides](https://docs.expo.dev/guides).
+- [Learn Expo tutorial](https://docs.expo.dev/tutorial/introduction/): Follow a step-by-step tutorial where you'll create a project that runs on Android, iOS, and the web.
+
+## Join the community
+
+Join our community of developers creating universal apps.
+
+- [Expo on GitHub](https://github.com/expo/expo): View our open source platform and contribute.
+- [Discord community](https://chat.expo.dev): Chat with Expo users and ask questions.
diff --git a/app.json b/app.json
new file mode 100644
index 0000000..334b661
--- /dev/null
+++ b/app.json
@@ -0,0 +1,52 @@
+{
+ "expo": {
+ "name": "YABA",
+ "slug": "YABA",
+ "version": "1.0.0",
+ "orientation": "portrait",
+ "icon": "./assets/images/icon.png",
+ "scheme": "YABA",
+ "userInterfaceStyle": "automatic",
+ "ios": {
+ "icon": "./assets/expo.icon"
+ },
+ "android": {
+ "adaptiveIcon": {
+ "backgroundColor": "#E6F4FE",
+ "foregroundImage": "./assets/images/android-icon-foreground.png",
+ "backgroundImage": "./assets/images/android-icon-background.png",
+ "monochromeImage": "./assets/images/android-icon-monochrome.png"
+ },
+ "predictiveBackGestureEnabled": false,
+ "package": "com.lucas.yaba"
+ },
+ "web": {
+ "output": "static",
+ "favicon": "./assets/images/favicon.png"
+ },
+ "plugins": [
+ "expo-router",
+ [
+ "expo-splash-screen",
+ {
+ "backgroundColor": "#208AEF",
+ "image": "./assets/images/splash-icon.png",
+ "imageWidth": 76
+ }
+ ],
+ "expo-secure-store",
+ "expo-font",
+ "expo-status-bar"
+ ],
+ "experiments": {
+ "typedRoutes": true,
+ "reactCompiler": true
+ },
+ "extra": {
+ "router": {},
+ "eas": {
+ "projectId": "29008d68-2bba-4ab2-8d77-6d2cf5d78f1a"
+ }
+ }
+ }
+}
diff --git a/assets/.DS_Store b/assets/.DS_Store
new file mode 100644
index 0000000..59fbaf7
--- /dev/null
+++ b/assets/.DS_Store
Binary files differ
diff --git a/assets/expo.icon/Assets/expo-symbol 2.svg b/assets/expo.icon/Assets/expo-symbol 2.svg
new file mode 100644
index 0000000..51d3676
--- /dev/null
+++ b/assets/expo.icon/Assets/expo-symbol 2.svg
@@ -0,0 +1,3 @@
+<svg width="652" height="606" viewBox="0 0 652 606" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M353.554 0H298.446C273.006 0 249.684 14.6347 237.962 37.9539L4.37994 502.646C-1.04325 513.435 -1.45067 526.178 3.2716 537.313L22.6123 582.918C34.6475 611.297 72.5404 614.156 88.4414 587.885L309.863 222.063C313.34 216.317 319.439 212.826 326 212.826C332.561 212.826 338.659 216.317 342.137 222.063L563.559 587.885C579.46 614.156 617.352 611.297 629.388 582.918L648.728 537.313C653.451 526.178 653.043 513.435 647.62 502.646L414.038 37.9539C402.316 14.6347 378.994 0 353.554 0Z" fill="white"/>
+</svg>
diff --git a/assets/expo.icon/Assets/grid.png b/assets/expo.icon/Assets/grid.png
new file mode 100644
index 0000000..eefea24
--- /dev/null
+++ b/assets/expo.icon/Assets/grid.png
Binary files differ
diff --git a/assets/expo.icon/icon.json b/assets/expo.icon/icon.json
new file mode 100644
index 0000000..7a2c33c
--- /dev/null
+++ b/assets/expo.icon/icon.json
@@ -0,0 +1,40 @@
+{
+ "fill" : {
+ "automatic-gradient" : "extended-srgb:0.00000,0.47843,1.00000,1.00000"
+ },
+ "groups" : [
+ {
+ "layers" : [
+ {
+ "image-name" : "expo-symbol 2.svg",
+ "name" : "expo-symbol 2",
+ "position" : {
+ "scale" : 1,
+ "translation-in-points" : [
+ 1.1008400065293245e-05,
+ -16.046875
+ ]
+ }
+ },
+ {
+ "image-name" : "grid.png",
+ "name" : "grid"
+ }
+ ],
+ "shadow" : {
+ "kind" : "neutral",
+ "opacity" : 0.5
+ },
+ "translucency" : {
+ "enabled" : true,
+ "value" : 0.5
+ }
+ }
+ ],
+ "supported-platforms" : {
+ "circles" : [
+ "watchOS"
+ ],
+ "squares" : "shared"
+ }
+} \ No newline at end of file
diff --git a/assets/images/android-icon-background.png b/assets/images/android-icon-background.png
new file mode 100644
index 0000000..5ffefc5
--- /dev/null
+++ b/assets/images/android-icon-background.png
Binary files differ
diff --git a/assets/images/android-icon-foreground.png b/assets/images/android-icon-foreground.png
new file mode 100644
index 0000000..3a9e501
--- /dev/null
+++ b/assets/images/android-icon-foreground.png
Binary files differ
diff --git a/assets/images/android-icon-monochrome.png b/assets/images/android-icon-monochrome.png
new file mode 100644
index 0000000..77484eb
--- /dev/null
+++ b/assets/images/android-icon-monochrome.png
Binary files differ
diff --git a/assets/images/expo-badge-white.png b/assets/images/expo-badge-white.png
new file mode 100644
index 0000000..2863067
--- /dev/null
+++ b/assets/images/expo-badge-white.png
Binary files differ
diff --git a/assets/images/expo-badge.png b/assets/images/expo-badge.png
new file mode 100644
index 0000000..5d5c5bb
--- /dev/null
+++ b/assets/images/expo-badge.png
Binary files differ
diff --git a/assets/images/expo-logo.png b/assets/images/expo-logo.png
new file mode 100644
index 0000000..6b1642a
--- /dev/null
+++ b/assets/images/expo-logo.png
Binary files differ
diff --git a/assets/images/favicon.png b/assets/images/favicon.png
new file mode 100644
index 0000000..408bd74
--- /dev/null
+++ b/assets/images/favicon.png
Binary files differ
diff --git a/assets/images/icon.png b/assets/images/icon.png
new file mode 100644
index 0000000..d611bd6
--- /dev/null
+++ b/assets/images/icon.png
Binary files differ
diff --git a/assets/images/logo-glow.png b/assets/images/logo-glow.png
new file mode 100644
index 0000000..edc99be
--- /dev/null
+++ b/assets/images/logo-glow.png
Binary files differ
diff --git a/assets/images/react-logo.png b/assets/images/react-logo.png
new file mode 100644
index 0000000..9d72a9f
--- /dev/null
+++ b/assets/images/react-logo.png
Binary files differ
diff --git a/assets/images/react-logo@2x.png b/assets/images/react-logo@2x.png
new file mode 100644
index 0000000..2229b13
--- /dev/null
+++ b/assets/images/react-logo@2x.png
Binary files differ
diff --git a/assets/images/react-logo@3x.png b/assets/images/react-logo@3x.png
new file mode 100644
index 0000000..a99b203
--- /dev/null
+++ b/assets/images/react-logo@3x.png
Binary files differ
diff --git a/assets/images/splash-icon.png b/assets/images/splash-icon.png
new file mode 100644
index 0000000..6b1642a
--- /dev/null
+++ b/assets/images/splash-icon.png
Binary files differ
diff --git a/assets/images/tabIcons/explore.png b/assets/images/tabIcons/explore.png
new file mode 100644
index 0000000..73d8258
--- /dev/null
+++ b/assets/images/tabIcons/explore.png
Binary files differ
diff --git a/assets/images/tabIcons/explore@2x.png b/assets/images/tabIcons/explore@2x.png
new file mode 100644
index 0000000..21b9bd2
--- /dev/null
+++ b/assets/images/tabIcons/explore@2x.png
Binary files differ
diff --git a/assets/images/tabIcons/explore@3x.png b/assets/images/tabIcons/explore@3x.png
new file mode 100644
index 0000000..422202d
--- /dev/null
+++ b/assets/images/tabIcons/explore@3x.png
Binary files differ
diff --git a/assets/images/tabIcons/home.png b/assets/images/tabIcons/home.png
new file mode 100644
index 0000000..ad5699c
--- /dev/null
+++ b/assets/images/tabIcons/home.png
Binary files differ
diff --git a/assets/images/tabIcons/home@2x.png b/assets/images/tabIcons/home@2x.png
new file mode 100644
index 0000000..22a1f2c
--- /dev/null
+++ b/assets/images/tabIcons/home@2x.png
Binary files differ
diff --git a/assets/images/tabIcons/home@3x.png b/assets/images/tabIcons/home@3x.png
new file mode 100644
index 0000000..f5d1f9a
--- /dev/null
+++ b/assets/images/tabIcons/home@3x.png
Binary files differ
diff --git a/assets/images/tutorial-web.png b/assets/images/tutorial-web.png
new file mode 100644
index 0000000..e4a8c58
--- /dev/null
+++ b/assets/images/tutorial-web.png
Binary files differ
diff --git a/bun.lock b/bun.lock
new file mode 100644
index 0000000..790417e
--- /dev/null
+++ b/bun.lock
@@ -0,0 +1,1386 @@
+{
+ "lockfileVersion": 1,
+ "configVersion": 1,
+ "workspaces": {
+ "": {
+ "name": "yaba",
+ "dependencies": {
+ "@expo-google-fonts/dm-sans": "^0.4.2",
+ "@expo/ui": "~57.0.10",
+ "@expo/vector-icons": "^15.0.2",
+ "@react-navigation/bottom-tabs": "^7.18.16",
+ "expo": "~57.0.12",
+ "expo-blur": "~57.0.2",
+ "expo-constants": "~57.0.10",
+ "expo-dev-client": "~57.0.11",
+ "expo-device": "~57.0.1",
+ "expo-font": "~57.0.1",
+ "expo-glass-effect": "~57.0.1",
+ "expo-haptics": "~57.0.1",
+ "expo-image": "~57.0.2",
+ "expo-linear-gradient": "~57.0.1",
+ "expo-linking": "~57.0.5",
+ "expo-local-authentication": "~57.0.2",
+ "expo-router": "~57.0.12",
+ "expo-secure-store": "~57.0.1",
+ "expo-splash-screen": "~57.0.6",
+ "expo-status-bar": "~57.0.1",
+ "expo-symbols": "~57.0.2",
+ "expo-system-ui": "~57.0.2",
+ "expo-web-browser": "~57.0.2",
+ "react": "19.2.3",
+ "react-dom": "19.2.3",
+ "react-native": "0.86.2",
+ "react-native-gesture-handler": "~2.32.0",
+ "react-native-gifted-charts": "^1.4.78",
+ "react-native-reanimated": "4.5.1",
+ "react-native-safe-area-context": "~5.7.0",
+ "react-native-screens": "~4.26.0",
+ "react-native-svg": "15.15.4",
+ "react-native-web": "~0.21.0",
+ "react-native-worklets": "0.10.1",
+ },
+ "devDependencies": {
+ "@types/react": "~19.2.2",
+ "typescript": "~6.0.3",
+ },
+ },
+ },
+ "packages": {
+ "@adobe/css-tools": ["@adobe/css-tools@4.5.0", "", {}, "sha512-6OzddxPio9UiWTCemp4N8cYLV2ZN1ncRnV1cVGtve7dhPOtRkleRyx32GQCYSwDYgaHU3USMm84tNsvKzRCa1Q=="],
+
+ "@babel/code-frame": ["@babel/code-frame@7.29.7", "", { "dependencies": { "@babel/helper-validator-identifier": "^7.29.7", "js-tokens": "^4.0.0", "picocolors": "^1.1.1" } }, "sha512-Aup7aUOfpbAUg2ROOJN6Iw5f9DMBlzu0mIkm/malLQFN/YQgO48wCj0Kxa3sEHJvPVFg7siR+qRInwXd2qhQKw=="],
+
+ "@babel/compat-data": ["@babel/compat-data@7.29.7", "", {}, "sha512-locTkQyKvwIEgBzVrn8693ebc97F2U8ZHjbXwDXJ5Fn2TCpNwTlKcaKLkdHop5c/icOFE7qt7Q9JC5hnKNa6Gg=="],
+
+ "@babel/core": ["@babel/core@7.29.7", "", { "dependencies": { "@babel/code-frame": "^7.29.7", "@babel/generator": "^7.29.7", "@babel/helper-compilation-targets": "^7.29.7", "@babel/helper-module-transforms": "^7.29.7", "@babel/helpers": "^7.29.7", "@babel/parser": "^7.29.7", "@babel/template": "^7.29.7", "@babel/traverse": "^7.29.7", "@babel/types": "^7.29.7", "@jridgewell/remapping": "^2.3.5", "convert-source-map": "^2.0.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", "json5": "^2.2.3", "semver": "^6.3.1" } }, "sha512-RgHBCvtjbOK2gXSNBNIkNoEc9qoVEtau3hj8gEqKQuL3HZAibKarWFEI3Lfm6EYKkLalOh8eSrj9b+ch9H/VBA=="],
+
+ "@babel/generator": ["@babel/generator@7.29.8", "", { "dependencies": { "@babel/parser": "^7.29.8", "@babel/types": "^7.29.8", "@jridgewell/gen-mapping": "^0.3.12", "@jridgewell/trace-mapping": "^0.3.28", "jsesc": "^3.0.2" } }, "sha512-gZbepsdh3WDtgZKWL+vTPh71LSBrm/Y4/QDZBVCcYfmeTEEuoOYwlSy+G1StfJg+/Zy550u/3TATbm7qDbbMtg=="],
+
+ "@babel/helper-annotate-as-pure": ["@babel/helper-annotate-as-pure@7.29.7", "", { "dependencies": { "@babel/types": "^7.29.7" } }, "sha512-OoK6239jHPuSQOoS0kfTVKn0b/rVTk0seKq4Gd2UMLtmOVLjDC0ki3e+c90Trqv2gMfvJFqkiljrr568+qddiw=="],
+
+ "@babel/helper-compilation-targets": ["@babel/helper-compilation-targets@7.29.7", "", { "dependencies": { "@babel/compat-data": "^7.29.7", "@babel/helper-validator-option": "^7.29.7", "browserslist": "^4.24.0", "lru-cache": "^5.1.1", "semver": "^6.3.1" } }, "sha512-wem6WaBj4NaVYVdNhLPPVacES6ZJ+KBBfSkTMD3YZxbP3rm3Di85tJU5ljaUNhaOynt+Aj0xruhYuzQBt8n71g=="],
+
+ "@babel/helper-create-class-features-plugin": ["@babel/helper-create-class-features-plugin@7.29.7", "", { "dependencies": { "@babel/helper-annotate-as-pure": "^7.29.7", "@babel/helper-member-expression-to-functions": "^7.29.7", "@babel/helper-optimise-call-expression": "^7.29.7", "@babel/helper-replace-supers": "^7.29.7", "@babel/helper-skip-transparent-expression-wrappers": "^7.29.7", "@babel/traverse": "^7.29.7", "semver": "^6.3.1" }, "peerDependencies": { "@babel/core": "^7.0.0" } }, "sha512-IY3ZD9Tmooqr3TUhc3DUWxiuo8xx1DWLhd5M7hQ+ZWJamqM2BbalrBJb2MisSLoYorOj75U03qULCxQTY9r3hg=="],
+
+ "@babel/helper-create-regexp-features-plugin": ["@babel/helper-create-regexp-features-plugin@7.29.7", "", { "dependencies": { "@babel/helper-annotate-as-pure": "^7.29.7", "regexpu-core": "^6.3.1", "semver": "^6.3.1" }, "peerDependencies": { "@babel/core": "^7.0.0" } }, "sha512-907Uymvqgg1dwUA+7IGwFAOSYzQOuzPXKNJ1yxzwPffzkYFg2q2eHi1fIOs6sXkG9NbIUMunnUlkYsfRFNvomg=="],
+
+ "@babel/helper-define-polyfill-provider": ["@babel/helper-define-polyfill-provider@0.6.8", "", { "dependencies": { "@babel/helper-compilation-targets": "^7.28.6", "@babel/helper-plugin-utils": "^7.28.6", "debug": "^4.4.3", "lodash.debounce": "^4.0.8", "resolve": "^1.22.11" }, "peerDependencies": { "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" } }, "sha512-47UwBLPpQi1NoWzLuHNjRoHlYXMwIJoBf7MFou6viC/sIHWYygpvr0B6IAyh5sBdA2nr2LPIRww8lfaUVQINBA=="],
+
+ "@babel/helper-globals": ["@babel/helper-globals@7.29.7", "", {}, "sha512-3nQVUAtvkKH9zahfWgw96Jc/uFOmjACE1kQz82E2lqWmHBgjzbNlsC22nuQTfahmWeQtTq5nQ/4Nnd2A1wj4zA=="],
+
+ "@babel/helper-member-expression-to-functions": ["@babel/helper-member-expression-to-functions@7.29.7", "", { "dependencies": { "@babel/traverse": "^7.29.7", "@babel/types": "^7.29.7" } }, "sha512-j+7JYmk1JYDtACIGj0QJqqWZjoUpMoEikQGADMaHgCMCSDqd2+P32rfcibUNrGOMWrlzK1WJBdxrB3JJQZwWtg=="],
+
+ "@babel/helper-module-imports": ["@babel/helper-module-imports@7.29.7", "", { "dependencies": { "@babel/traverse": "^7.29.7", "@babel/types": "^7.29.7" } }, "sha512-ejHwrQQYcm9xnTivShn2IDOlIzInN34AXskvq9QicvCtEzq1Vzclu/tKF8Jq1Cg8JG2GL6/EmjgsCT7lXepE3g=="],
+
+ "@babel/helper-module-transforms": ["@babel/helper-module-transforms@7.29.7", "", { "dependencies": { "@babel/helper-module-imports": "^7.29.7", "@babel/helper-validator-identifier": "^7.29.7", "@babel/traverse": "^7.29.7" }, "peerDependencies": { "@babel/core": "^7.0.0" } }, "sha512-UPUVSyXbOh627KiCIGQSgwWzGeBKLkaJ9PJEdrngIwMSzxLR4jS4+f1f1jb7VzBbg8nFLaYotvVPFCTqdrmTAg=="],
+
+ "@babel/helper-optimise-call-expression": ["@babel/helper-optimise-call-expression@7.29.7", "", { "dependencies": { "@babel/types": "^7.29.7" } }, "sha512-+kmGVjcT9RGYzoDwdwEqEvGgKe3BYq+O1iGzjFubaNgZHwYHP6lsF2Yghf4kEuv9BV7tYDZ913aBW9am6YKong=="],
+
+ "@babel/helper-plugin-utils": ["@babel/helper-plugin-utils@7.29.7", "", {}, "sha512-G7sHYigPY17oO5SYWnfD/0MTBwVR781S/JI643e/JhUYgVgWE/61SoW3NH9KWUKyKq5LVh3npif99Wkt6j86Jw=="],
+
+ "@babel/helper-remap-async-to-generator": ["@babel/helper-remap-async-to-generator@7.29.7", "", { "dependencies": { "@babel/helper-annotate-as-pure": "^7.29.7", "@babel/helper-wrap-function": "^7.29.7", "@babel/traverse": "^7.29.7" }, "peerDependencies": { "@babel/core": "^7.0.0" } }, "sha512-16AMiW26DbXWBbr3B8wNozKM0ydMLB892vaOaJW/fPJdnT8vJk5sdkQcU/isqUxyCE0cEoa8wZOcbgDuC4b6Og=="],
+
+ "@babel/helper-replace-supers": ["@babel/helper-replace-supers@7.29.7", "", { "dependencies": { "@babel/helper-member-expression-to-functions": "^7.29.7", "@babel/helper-optimise-call-expression": "^7.29.7", "@babel/traverse": "^7.29.7" }, "peerDependencies": { "@babel/core": "^7.0.0" } }, "sha512-atfGXWSeCiF4DnKZIfmJfQRkSw9b9gNNXR1kqKjbhG4pGYCOnkp8OcTB8E3NXjBu8NpheSnOeNKz8KT7UNFTmQ=="],
+
+ "@babel/helper-skip-transparent-expression-wrappers": ["@babel/helper-skip-transparent-expression-wrappers@7.29.7", "", { "dependencies": { "@babel/traverse": "^7.29.7", "@babel/types": "^7.29.7" } }, "sha512-brcMGQaVzIeUb+6/bs1Av0f8YuNNjKY2JyvfRCsFuFsdKccEQ5Ges2y74D74NZ1Rz8lKJ9ksJkfqwQFJ/iNEyQ=="],
+
+ "@babel/helper-string-parser": ["@babel/helper-string-parser@7.29.7", "", {}, "sha512-Pb5ijPrZ89GDH8223L4UP8i6QApWxs04RbPQJTeWDV0/keR2E36MeKnyr6LYmUUvqRRI+Iv87SuF1W6ErINzYw=="],
+
+ "@babel/helper-validator-identifier": ["@babel/helper-validator-identifier@7.29.7", "", {}, "sha512-qehxGkRj55h/ff8EMaJ+cYhyaKlHIxqYDn682wQD7RNp9UujOQsHog2uS0r2vzr4pW+sXf90NeeayjcNaX3fFg=="],
+
+ "@babel/helper-validator-option": ["@babel/helper-validator-option@7.29.7", "", {}, "sha512-N9ZErrD+yW5geCDtBqnOoxmR8+tNKiGuxKlDpuJxfsqpa2dFcexaziGAE/qoHLiDDreVNMupxGmSoNlyvsA3gw=="],
+
+ "@babel/helper-wrap-function": ["@babel/helper-wrap-function@7.29.7", "", { "dependencies": { "@babel/template": "^7.29.7", "@babel/traverse": "^7.29.7", "@babel/types": "^7.29.7" } }, "sha512-iES0Skag9ERIF68aXadpO6dbXa03mNWK3sEqJaMnLNs/eC3l0lkImdfoy6Y09/SfkpawdAB4RjQ7PVA7TcVGdw=="],
+
+ "@babel/helpers": ["@babel/helpers@7.29.7", "", { "dependencies": { "@babel/template": "^7.29.7", "@babel/types": "^7.29.7" } }, "sha512-1k2lAGRMfHTcwuNYcCNUmaUffmQv8KWMfh2iJUUeRlwlwH4FdNG7mfPI10NPfLHJFThE4Tyr4mv7kTNZOiPuBg=="],
+
+ "@babel/parser": ["@babel/parser@7.29.8", "", { "dependencies": { "@babel/types": "^7.29.8" }, "bin": "./bin/babel-parser.js" }, "sha512-E8lTAYNB1KW+FH+VGJuZM1ioAx2E6oVlvQFRrf5P8ZZmsiJXYAD9vTFV7yyEURNzgh1dFqMZuO6tUwcARbqFCA=="],
+
+ "@babel/plugin-proposal-decorators": ["@babel/plugin-proposal-decorators@7.29.7", "", { "dependencies": { "@babel/helper-create-class-features-plugin": "^7.29.7", "@babel/helper-plugin-utils": "^7.29.7", "@babel/plugin-syntax-decorators": "^7.29.7" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-EtU0Hi3GvrTqD56xKmZvV/uCXK2ZbwVNPNLAquVItcAZpUhkXwWlo3Fmj0c2LxgSf2I8IDULeAepwNP1OefLXg=="],
+
+ "@babel/plugin-proposal-export-default-from": ["@babel/plugin-proposal-export-default-from@7.29.7", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.29.7" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-p+G5BNXDcy3bOXplhY4HybQ1GxH3i2Tppmdm/3epyRu2VgJJZuUlZ61MqRTg582Q7ZLBdP7fePYvsumSEkMxcQ=="],
+
+ "@babel/plugin-syntax-decorators": ["@babel/plugin-syntax-decorators@7.29.7", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.29.7" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-9MTTLbF39X6sqM92JPEsoI7++26hjZvzkxKZy64aMhWLH2mPkJ/Q3AV4QLmls3R14FpSpkOwQQfUh962JGQxxg=="],
+
+ "@babel/plugin-syntax-dynamic-import": ["@babel/plugin-syntax-dynamic-import@7.8.3", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.8.0" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ=="],
+
+ "@babel/plugin-syntax-export-default-from": ["@babel/plugin-syntax-export-default-from@7.29.7", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.29.7" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-foag0BB37ROhdeIX9O8G0jX7hw0UekJc04cHMrYLOnrErsnBKqJGHJ8eDRpoCFZBvEPPygmmtw4qyU97qa4oOw=="],
+
+ "@babel/plugin-syntax-flow": ["@babel/plugin-syntax-flow@7.29.7", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.29.7" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-ajMX6QPcyomotqwpzhkYGxcK2i/us0rs1Qo9QvUpa+Fca0FTmqrzKrctoIYLMxcOhGZldGT/BAVkRGTWBiR8gQ=="],
+
+ "@babel/plugin-syntax-jsx": ["@babel/plugin-syntax-jsx@7.29.7", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.29.7" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-TSu8+mHCoEaaCDEZ0I3+6mvTBYR4PCxQwf2z9/r5Tbztv6NaLR3B9thGTTxX2WGuGHJqRiAbKPeGTJ5XWXVg6A=="],
+
+ "@babel/plugin-syntax-nullish-coalescing-operator": ["@babel/plugin-syntax-nullish-coalescing-operator@7.8.3", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.8.0" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ=="],
+
+ "@babel/plugin-syntax-optional-chaining": ["@babel/plugin-syntax-optional-chaining@7.8.3", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.8.0" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg=="],
+
+ "@babel/plugin-syntax-typescript": ["@babel/plugin-syntax-typescript@7.29.7", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.29.7" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-ngr+82Sh0xMz25TPCZi+nC2iTzjfCdWS2ONXTp/PtSCHCgaCNBpdMqgvJ2ccdLlClVZ7sisIgB914j/JFe+RZA=="],
+
+ "@babel/plugin-transform-arrow-functions": ["@babel/plugin-transform-arrow-functions@7.29.7", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.29.7" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-N7zArUXWzAMzm+/N0uPBeVB3Fam5lMxtUwMmDK5f/IBBS7a7p1qeUoxd/6CckXoxUdgsntq1Dh8xNW06maZbDQ=="],
+
+ "@babel/plugin-transform-async-generator-functions": ["@babel/plugin-transform-async-generator-functions@7.29.7", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.29.7", "@babel/helper-remap-async-to-generator": "^7.29.7", "@babel/traverse": "^7.29.7" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-d98gXZkgswvkyohMBABkhm3GeXhYj8psWfwQ2C7gtfrKGTykQa/iOIi+JJhwMjPlZ6Vm2XN+DCf3Es1EoG4ZLA=="],
+
+ "@babel/plugin-transform-async-to-generator": ["@babel/plugin-transform-async-to-generator@7.29.7", "", { "dependencies": { "@babel/helper-module-imports": "^7.29.7", "@babel/helper-plugin-utils": "^7.29.7", "@babel/helper-remap-async-to-generator": "^7.29.7" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-pcUb2SS+RMo9TWVBwKGI5ShtoG7R+zBsFmCKDa6fe8c+hPr3XJlZgoE5j6i8W7gDjhyvy+85vmYexanvXh3d1w=="],
+
+ "@babel/plugin-transform-block-scoping": ["@babel/plugin-transform-block-scoping@7.29.7", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.29.7" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-ONyr4+AZhKh8yKWInVxU9AXA9EbsyeLcL6V0dJy6M2/62vuvpGm29zzuymbTpdc451GEpDIdAyPLP3r+P61yKQ=="],
+
+ "@babel/plugin-transform-class-properties": ["@babel/plugin-transform-class-properties@7.29.7", "", { "dependencies": { "@babel/helper-create-class-features-plugin": "^7.29.7", "@babel/helper-plugin-utils": "^7.29.7" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-GtcpjFvanPfzNQi3eTitsCqtRRmmqzpy/A+yhTR1HaZo1Ly3EA8ZXxlPyHdR8/IuRMYc3E4wdGBewB2QKQjAaA=="],
+
+ "@babel/plugin-transform-class-static-block": ["@babel/plugin-transform-class-static-block@7.29.7", "", { "dependencies": { "@babel/helper-create-class-features-plugin": "^7.29.7", "@babel/helper-plugin-utils": "^7.29.7" }, "peerDependencies": { "@babel/core": "^7.12.0" } }, "sha512-kibJgmEdX2iMwsHY2tSZNDgj8PwIlCQz7FK9KuGKO8zsuoUwSEhoNnNVp/emKWrbY4HeO6kkXfdMqRKKKXBm2A=="],
+
+ "@babel/plugin-transform-classes": ["@babel/plugin-transform-classes@7.29.7", "", { "dependencies": { "@babel/helper-annotate-as-pure": "^7.29.7", "@babel/helper-compilation-targets": "^7.29.7", "@babel/helper-globals": "^7.29.7", "@babel/helper-plugin-utils": "^7.29.7", "@babel/helper-replace-supers": "^7.29.7", "@babel/traverse": "^7.29.7" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-qV0OGGBVacduzQHE649JyCneOFI/maT+YKsO+K4Yi3xv2wTPNjM/W2o2gdzMwEAZz7fXNTHAe0NcSg30bIN69g=="],
+
+ "@babel/plugin-transform-destructuring": ["@babel/plugin-transform-destructuring@7.29.7", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.29.7", "@babel/traverse": "^7.29.7" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-iPX8aD6H9zV5s7ZsqTdNocPN/MGQ5sSMnElKrktxjJRMnB2jN/1p2+R7GkfD6CAYoVFqy5A4XnSIUeGgJzIWpg=="],
+
+ "@babel/plugin-transform-export-namespace-from": ["@babel/plugin-transform-export-namespace-from@7.29.7", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.29.7" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-24B2nOy2TeJSMheqwPD4DDQOV/elLSIlKxjZt4i05H5AgdPdWR3n18HnNrcJ+j76WJd9gbwb9jPjNYUy6RautA=="],
+
+ "@babel/plugin-transform-flow-strip-types": ["@babel/plugin-transform-flow-strip-types@7.29.7", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.29.7", "@babel/plugin-syntax-flow": "^7.29.7" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-wRHeUjUjCZnMHmiO5bRgjFLcoEh7JyTdByOW11ahhwNa4V0bmeGEaIvt51yq0zQp2yWIpqfxXXPyUP6GFJZHOQ=="],
+
+ "@babel/plugin-transform-for-of": ["@babel/plugin-transform-for-of@7.29.7", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.29.7", "@babel/helper-skip-transparent-expression-wrappers": "^7.29.7" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-zeSIHh0+E1Um1WJRXCFlHQYu2ieJNdivLLjlBEp+dIBu3S51n+SZZmIXjxnItw6pz56Cn+KvK68BIBVsxq2JiQ=="],
+
+ "@babel/plugin-transform-logical-assignment-operators": ["@babel/plugin-transform-logical-assignment-operators@7.29.7", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.29.7" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-A0H91hh6W8MFRkp5TqJmMr39jzGD1A1E1Ysiv2O06Sfbhkapm+XyIzxWCEh5kqwOZ1/8QZ0dY3SeQ7XBqfJd5Q=="],
+
+ "@babel/plugin-transform-modules-commonjs": ["@babel/plugin-transform-modules-commonjs@7.29.7", "", { "dependencies": { "@babel/helper-module-transforms": "^7.29.7", "@babel/helper-plugin-utils": "^7.29.7" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-j0vCldybPC5b5dwCQOJ21uKtHzt7hxLygJTg9eF1ScfaikEDNfzn94XoW5Fi+seBR0nCyL23xaBFFkq7dTM8XQ=="],
+
+ "@babel/plugin-transform-named-capturing-groups-regex": ["@babel/plugin-transform-named-capturing-groups-regex@7.29.7", "", { "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.29.7", "@babel/helper-plugin-utils": "^7.29.7" }, "peerDependencies": { "@babel/core": "^7.0.0" } }, "sha512-vuFoLwr4qnv2xbZ16SQd6uPcH5FNrLHhk/Jzo++0XJFcaDsr4gjJVg6j398oMHiC+83k/GiBzviwF5KBJkPUtQ=="],
+
+ "@babel/plugin-transform-nullish-coalescing-operator": ["@babel/plugin-transform-nullish-coalescing-operator@7.29.7", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.29.7" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-idmp1dFaekP9GbcMvG24Kvw2BfhFZjHnNJCkV4WuIY4PskJzwI3f1N5OdgYke38T7rftO6ERulFRn2cFeZwRkg=="],
+
+ "@babel/plugin-transform-object-rest-spread": ["@babel/plugin-transform-object-rest-spread@7.29.7", "", { "dependencies": { "@babel/helper-compilation-targets": "^7.29.7", "@babel/helper-plugin-utils": "^7.29.7", "@babel/plugin-transform-destructuring": "^7.29.7", "@babel/plugin-transform-parameters": "^7.29.7", "@babel/traverse": "^7.29.7" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-Ld98jn4c0smUywL57m7SgsHq3OpThOa6LqZJif3G6jYOovPleoFhVrBJ1WegRApSFB2wu4+RelAj9AC9G08Z4A=="],
+
+ "@babel/plugin-transform-optional-catch-binding": ["@babel/plugin-transform-optional-catch-binding@7.29.7", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.29.7" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-sLsyndxK2VwX6yNUOakMb7Sh553ZTe/vVM1XJ+9Z5aW1ytsc8xOIwmyk05NNjN60vkc5/KqoTH6hB4V41LJhng=="],
+
+ "@babel/plugin-transform-optional-chaining": ["@babel/plugin-transform-optional-chaining@7.29.7", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.29.7", "@babel/helper-skip-transparent-expression-wrappers": "^7.29.7" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-6GM1dhvK3gNODkXcEcMCOLEDCLSoZ/sBbro2Ax8HURyasQ4NshagQixkRFdh5niI6E4gmA/jYI/4aT7rRos3ZQ=="],
+
+ "@babel/plugin-transform-parameters": ["@babel/plugin-transform-parameters@7.29.7", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.29.7" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-ZDOBqV/qLYJI0YElr8DcENEyARsFQeESqWXH6gZlghYXuPPjvweuDhP4VyEi4BlUBlLRFZVjxoZDMjxhLW766g=="],
+
+ "@babel/plugin-transform-private-methods": ["@babel/plugin-transform-private-methods@7.29.7", "", { "dependencies": { "@babel/helper-create-class-features-plugin": "^7.29.7", "@babel/helper-plugin-utils": "^7.29.7" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-/6Rz4DK1ETDEM/bWHsPHcaEe7ZaT1EqSXjtSP/L0DijOYuaUhiRiOKcwpZ8P7zR4xXEHc2ITdiCgBm9Tpyv9ug=="],
+
+ "@babel/plugin-transform-private-property-in-object": ["@babel/plugin-transform-private-property-in-object@7.29.7", "", { "dependencies": { "@babel/helper-annotate-as-pure": "^7.29.7", "@babel/helper-create-class-features-plugin": "^7.29.7", "@babel/helper-plugin-utils": "^7.29.7" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-+BNo06dnrzdNNqCm1X6YUaVv0DKk8Q+JYcoZfOkLhYWNCXzlwTSRq8zGWayT1csjcpNXV9CQTBRRbmTLZac5cA=="],
+
+ "@babel/plugin-transform-react-display-name": ["@babel/plugin-transform-react-display-name@7.29.7", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.29.7" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-+1wdDMGNb4UPeY3Q4L5yLiYe6TXPXubs4NjrgRFw13hPRLJfEMw2Q5OXkee6/IfdqePIeW4Jjwe3aBh7SdKz4Q=="],
+
+ "@babel/plugin-transform-react-jsx": ["@babel/plugin-transform-react-jsx@7.29.7", "", { "dependencies": { "@babel/helper-annotate-as-pure": "^7.29.7", "@babel/helper-module-imports": "^7.29.7", "@babel/helper-plugin-utils": "^7.29.7", "@babel/plugin-syntax-jsx": "^7.29.7", "@babel/types": "^7.29.7" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-WsZulLVBUHXVj2cUcPVx6UE21TpalB6bHbSFErKT0Ib++ax24jjXe73FqlWvdylFOjiuPHYi6VCcgRad1ItN+A=="],
+
+ "@babel/plugin-transform-react-jsx-development": ["@babel/plugin-transform-react-jsx-development@7.29.7", "", { "dependencies": { "@babel/plugin-transform-react-jsx": "^7.29.7" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-Xfy3UVMF04+ypnFbkhvfqtmvwfe92qwQdbGZVonhE+6v35GzlofmOnA1szaZqzb9xYWr0nl1e5EMmzi0DNON1g=="],
+
+ "@babel/plugin-transform-react-jsx-self": ["@babel/plugin-transform-react-jsx-self@7.29.7", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.29.7" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-TL0hMc9xzy86VD31nUiwzd5otRAcyEPcsegCxolO0PvcXuH1v0kECe/UIznYFihpkvU5wg/jk4v0TTEFfm53fw=="],
+
+ "@babel/plugin-transform-react-jsx-source": ["@babel/plugin-transform-react-jsx-source@7.29.7", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.29.7" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-06IyK09H3wi4cGbhDBwp5gUGo0IKtnYa8tyTiephirPCK6fbobVGiXMMI5zLQ4aKEYP3wZ3ArU44o+8KMrSG/Q=="],
+
+ "@babel/plugin-transform-react-pure-annotations": ["@babel/plugin-transform-react-pure-annotations@7.29.7", "", { "dependencies": { "@babel/helper-annotate-as-pure": "^7.29.7", "@babel/helper-plugin-utils": "^7.29.7" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-H5E+HBgDpr6Q5t+Aj11tL7XkIui1jhbIoArVQnqjgXo5/3YxkN7ZEBcWF4RQlB0T4rrxJQbXS6kiFV6B7XTqUA=="],
+
+ "@babel/plugin-transform-regenerator": ["@babel/plugin-transform-regenerator@7.29.8", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.29.7" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-0UpIXPtdDtMXfnV2OJAVMLpj3H/92vmkA6lpSRakmycJvj3VUy6Xs1dM8tXRugupykr5WB+LpiVl0J8LMVg2mg=="],
+
+ "@babel/plugin-transform-runtime": ["@babel/plugin-transform-runtime@7.29.7", "", { "dependencies": { "@babel/helper-module-imports": "^7.29.7", "@babel/helper-plugin-utils": "^7.29.7", "babel-plugin-polyfill-corejs2": "^0.4.14", "babel-plugin-polyfill-corejs3": "^0.13.0", "babel-plugin-polyfill-regenerator": "^0.6.5", "semver": "^6.3.1" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-xmAscdE/AsqRW7vutbPNoUmu/nF5SrLKPs7aoJgEjo35lLKA/Bc0i2rMv/hr1+Y0o1bQCiVtith3u2vdgRL39Q=="],
+
+ "@babel/plugin-transform-shorthand-properties": ["@babel/plugin-transform-shorthand-properties@7.29.7", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.29.7" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-I+WYbGBAiCn7nA6xBrlgPH+MB7HWb4u8pv5S0Pv7OtwNvIFvCCb24YlttKEeUFVurfBCEaOTnuhlqsb7f0Z5Dg=="],
+
+ "@babel/plugin-transform-template-literals": ["@babel/plugin-transform-template-literals@7.29.7", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.29.7" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-NCSEJ4sLFU2gqAub45HYh4fus2yQ36rr6ei6vpU7NdoJqCpxvEG8E6eJpscGyXP3VHD2Ny+fSXr04k1hoUrFqA=="],
+
+ "@babel/plugin-transform-typescript": ["@babel/plugin-transform-typescript@7.29.7", "", { "dependencies": { "@babel/helper-annotate-as-pure": "^7.29.7", "@babel/helper-create-class-features-plugin": "^7.29.7", "@babel/helper-plugin-utils": "^7.29.7", "@babel/helper-skip-transparent-expression-wrappers": "^7.29.7", "@babel/plugin-syntax-typescript": "^7.29.7" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-jK52h8LaLc7JarhQV2ofeFMts4H7vnOXnqZNA6fYglBTZewRBE51KWt3BUltW1P+KoPsYkHoJeXePuz4zo2LMw=="],
+
+ "@babel/plugin-transform-unicode-regex": ["@babel/plugin-transform-unicode-regex@7.29.7", "", { "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.29.7", "@babel/helper-plugin-utils": "^7.29.7" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-7D/x/23/d/3VqZ0QA+LGbZMlGwZjztBygSWWWsfTPoQ1oQ6Q1P6Mr3d0kk42XabyUVw+fha3LqdRsFqeKqvCyA=="],
+
+ "@babel/preset-typescript": ["@babel/preset-typescript@7.29.7", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.29.7", "@babel/helper-validator-option": "^7.29.7", "@babel/plugin-syntax-jsx": "^7.29.7", "@babel/plugin-transform-modules-commonjs": "^7.29.7", "@babel/plugin-transform-typescript": "^7.29.7" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-/Foi8vKY2EVbed/1eZx0gJEEwHAIxogrySI7rULcRIvhZzbvoE/b5qG5Ghc0WKAFKOHA9SD1x7RsFlOYdutIiQ=="],
+
+ "@babel/runtime": ["@babel/runtime@7.29.7", "", {}, "sha512-Nq8OhGWiZIZGV6hLHoyAKLLcJihP/xFeBMGJoUrxTX2psI8dCifzLhZISFb+VWS3wFMRDmCGw5R+dOySCqPLhw=="],
+
+ "@babel/template": ["@babel/template@7.29.7", "", { "dependencies": { "@babel/code-frame": "^7.29.7", "@babel/parser": "^7.29.7", "@babel/types": "^7.29.7" } }, "sha512-puq+Gf35oI24FeN11LkoUQFqv9uwNeWpxXZi/Ji3rRIoKAzKnxRaZ+Gkj0vKS9ZCiTESfng1N9LyOyXvo+m+Gg=="],
+
+ "@babel/traverse": ["@babel/traverse@7.29.8", "", { "dependencies": { "@babel/code-frame": "^7.29.7", "@babel/generator": "^7.29.8", "@babel/helper-globals": "^7.29.7", "@babel/parser": "^7.29.8", "@babel/template": "^7.29.7", "@babel/types": "^7.29.8", "debug": "^4.3.1" } }, "sha512-I5z7H3bf/41ktsNVLtpN0wAa336HkqIHQ5BuPLEhTkt1jVSyZpeNKIzTgEWmlxjdg81R0IgUCcaE+Ok3NvrfZg=="],
+
+ "@babel/types": ["@babel/types@7.29.8", "", { "dependencies": { "@babel/helper-string-parser": "^7.29.7", "@babel/helper-validator-identifier": "^7.29.7" } }, "sha512-Vj1jF3cPfxg7OAfoI7QnVKLoILlm2JF9pnVHrX8qx7AHMiYWT+NDAA7jChlNgRS4WTLc/fD1lXLmPixluj+3Gg=="],
+
+ "@egjs/hammerjs": ["@egjs/hammerjs@2.0.17", "", { "dependencies": { "@types/hammerjs": "^2.0.36" } }, "sha512-XQsZgjm2EcVUiZQf11UBJQfmZeEmOW8DpI1gsFeln6w0ae0ii4dMQEQ0kjl6DspdWX1aGY1/loyXnP0JS06e/A=="],
+
+ "@expo-google-fonts/dm-sans": ["@expo-google-fonts/dm-sans@0.4.2", "", {}, "sha512-e/fLH5aCJzkEenz7axvEn8N7IJAKhUwNjIxS75h9j+Ip1M9S7d22M19gJN3A7QW4egVkBJRyQh1hQFhngQn9yA=="],
+
+ "@expo-google-fonts/material-symbols": ["@expo-google-fonts/material-symbols@0.4.43", "", {}, "sha512-jJzgVcbkJnl48X5iBFNaL5CQHwoBElJapl8unc2Ri8DnyuBR+gRiuAD4gu3ESZjjo3sknIoYIwloOsWzKbLknQ=="],
+
+ "@expo/cli": ["@expo/cli@57.0.14", "", { "dependencies": { "@expo/code-signing-certificates": "^0.0.6", "@expo/config": "~57.0.7", "@expo/config-plugins": "~57.0.7", "@expo/devcert": "^1.2.1", "@expo/env": "~2.4.2", "@expo/image-utils": "^0.11.4", "@expo/inline-modules": "^0.1.5", "@expo/json-file": "^11.0.1", "@expo/log-box": "^57.0.2", "@expo/metro": "~56.0.0", "@expo/metro-config": "~57.0.8", "@expo/metro-file-map": "^57.0.1", "@expo/osascript": "^2.7.1", "@expo/package-manager": "^1.13.1", "@expo/plist": "^0.8.1", "@expo/prebuild-config": "^57.0.11", "@expo/require-utils": "^57.0.4", "@expo/router-server": "^57.0.5", "@expo/schema-utils": "^57.0.2", "@expo/spawn-async": "^1.8.0", "@expo/ws-tunnel": "^2.0.0", "@expo/xcpretty": "^4.4.4", "@react-native/dev-middleware": "0.86.2", "accepts": "^1.3.8", "agent-cli-detector": "^0.1.2", "arg": "^5.0.2", "bplist-creator": "0.1.0", "bplist-parser": "^0.3.1", "chalk": "^4.0.0", "ci-info": "^3.3.0", "compression": "^1.7.4", "connect": "^3.7.0", "debug": "^4.3.4", "dnssd-advertise": "^1.1.4", "expo-server": "^57.0.2", "fetch-nodeshim": "^0.4.10", "getenv": "^2.0.0", "glob": "^13.0.0", "lan-network": "^0.2.1", "multitars": "^1.0.0", "node-forge": "^1.3.3", "npm-package-arg": "^11.0.0", "ora": "^3.4.0", "picomatch": "^4.0.4", "pretty-format": "^29.7.0", "progress": "^2.0.3", "prompts": "^2.3.2", "resolve-from": "^5.0.0", "semver": "^7.6.0", "send": "^0.19.0", "slugify": "^1.3.4", "stacktrace-parser": "^0.1.10", "structured-headers": "^0.4.1", "terminal-link": "^2.1.1", "toqr": "^0.1.1", "wrap-ansi": "^7.0.0", "ws": "^8.12.1", "zod": "^3.25.76" }, "peerDependencies": { "expo": "*", "expo-router": "*", "react-native": "*" }, "optionalPeers": ["expo-router", "react-native"], "bin": { "expo-internal": "main.js" } }, "sha512-yu3sie3cDPDXBTUMvivqguW+lT8jnLIF8Q6e75MRaq7BoAzihor0KrJwtXAtC4ep5eOYYC1otEvtOuctG1xf8Q=="],
+
+ "@expo/code-signing-certificates": ["@expo/code-signing-certificates@0.0.6", "", { "dependencies": { "node-forge": "^1.3.3" } }, "sha512-iNe0puxwBNEcuua9gmTGzq+SuMDa0iATai1FlFTMHJ/vUmKvN/V//drXoLJkVb5i5H3iE/n/qIJxyoBnXouD0w=="],
+
+ "@expo/config": ["@expo/config@57.0.7", "", { "dependencies": { "@expo/config-plugins": "~57.0.7", "@expo/config-types": "^57.0.2", "@expo/json-file": "^11.0.1", "@expo/require-utils": "^57.0.4", "deepmerge": "^4.3.1", "getenv": "^2.0.0", "glob": "^13.0.0", "resolve-workspace-root": "^2.0.0", "semver": "^7.6.0", "slugify": "^1.3.4" } }, "sha512-4A+V8x5OmQqNm76l84S+RrB6kVoeFrvcm/Xn/6d+ELPF/HeucDheAFchdYxYNy+NEvWzuNlI/oCvrftIeK+dbQ=="],
+
+ "@expo/config-plugins": ["@expo/config-plugins@57.0.7", "", { "dependencies": { "@expo/config-types": "^57.0.2", "@expo/json-file": "~11.0.1", "@expo/plist": "^0.8.1", "@expo/require-utils": "^57.0.4", "@expo/sdk-runtime-versions": "^1.0.0", "chalk": "^4.1.2", "debug": "^4.3.5", "getenv": "^2.0.0", "glob": "^13.0.0", "semver": "^7.5.4", "slugify": "^1.6.6", "xcode": "^3.0.1", "xml2js": "0.6.0" } }, "sha512-jvXMiNuH8W7fmU9yCk4/jVwDX2G/5rWUg5PZ22mriccEeQVS9HJjQiUHivMaK6MxEG5L9f0RPScxe/nQfnpQvg=="],
+
+ "@expo/config-types": ["@expo/config-types@57.0.2", "", {}, "sha512-ewW08OonrcRIsRKIlFvvcmmafE5zemb1ocu3HkNwtVPyRtj2w42pZCAkMIROYpcVBaPnc3mDT9UZDzwXWC3i6g=="],
+
+ "@expo/devcert": ["@expo/devcert@1.2.1", "", { "dependencies": { "@expo/sudo-prompt": "^9.3.1", "debug": "^3.1.0" } }, "sha512-qC4eaxmKMTmJC2ahwyui6ud8f3W60Ss7pMkpBq40Hu3zyiAaugPXnZ24145U7K36qO9UHdZUVxsCvIpz2RYYCA=="],
+
+ "@expo/devtools": ["@expo/devtools@57.0.1", "", { "dependencies": { "chalk": "^4.1.2" }, "peerDependencies": { "react": "*", "react-native": "*" }, "optionalPeers": ["react", "react-native"] }, "sha512-GyUf+wFNkbttaX0jR7MZa9bm77U0IrLg6d2AjpxdyoXw/w4abHoXG0oFufwLMgP9zLTd5+Ct4X/ffNUTnlzZgg=="],
+
+ "@expo/dom-webview": ["@expo/dom-webview@57.0.1", "", { "peerDependencies": { "expo": "*", "react": "*", "react-native": "*" } }, "sha512-lAKsME4SAq+8sf56oN0DX5TBYyruupoRxbWbD2xf9RnKY8y6x8eb9LCE5pxSN0qyWdqnp+0wmyWzDkKboThKAw=="],
+
+ "@expo/env": ["@expo/env@2.4.2", "", { "dependencies": { "chalk": "^4.0.0", "debug": "^4.3.4", "getenv": "^2.0.0" } }, "sha512-28pqaEqwnmLduZ00Pq9HkSzE5wbj1MTwp5/n8nm8rD8MCjR9eUnVOwmNksPI3Be2ReAPO/DbPn1puy0mvoocsQ=="],
+
+ "@expo/expo-modules-macros-plugin": ["@expo/expo-modules-macros-plugin@0.6.1", "", {}, "sha512-cpsLZE4rqkc1Y3eZTkxB98jrqY1YXgetmtxFt8q89jBRmk3quRuk1BZo+VcnCSObZardjg99r1k5xijEMONFGA=="],
+
+ "@expo/fingerprint": ["@expo/fingerprint@0.20.7", "", { "dependencies": { "@expo/env": "^2.4.2", "@expo/spawn-async": "^1.8.0", "arg": "^5.0.2", "chalk": "^4.1.2", "debug": "^4.3.4", "getenv": "^2.0.0", "glob": "^13.0.0", "ignore": "^5.3.1", "minimatch": "^10.2.2", "resolve-from": "^5.0.0", "semver": "^7.6.0" }, "bin": { "fingerprint": "bin/cli.js" } }, "sha512-tYyZD4XZSn1C30pr9IvjN/BjAqpf6r9e1NL09lPvheO1DMLByOVdmMHFLSwW8Pu6veVgzue7GDWmq9P8mc8GMg=="],
+
+ "@expo/image-utils": ["@expo/image-utils@0.11.4", "", { "dependencies": { "@expo/require-utils": "^57.0.4", "@expo/spawn-async": "^1.8.0", "chalk": "^4.0.0", "getenv": "^2.0.0", "jimp-compact": "0.16.1", "parse-png": "^2.1.0", "semver": "^7.6.0" } }, "sha512-pn/4770DIEOcYZr484uazuwg20FX/qaDkeMRF6J+oxejynDmEmO8wLsCudaNShFE0BhyKGQTYrs2rsRhqrqESw=="],
+
+ "@expo/inline-modules": ["@expo/inline-modules@0.1.5", "", { "dependencies": { "@expo/config-plugins": "~57.0.7" } }, "sha512-LC+kWeIwnvsGIvDaFBd8uzleWzWZiZTCG7CmtfxBLjW/Gify596X67ZqTi76iHzm5KToAfwwX0nppAKPDA9vQw=="],
+
+ "@expo/json-file": ["@expo/json-file@11.0.1", "", { "dependencies": { "@babel/code-frame": "^7.20.0", "json5": "^2.2.3" } }, "sha512-zxHWj4MKKMAL29ZQSY/Fssx4Thluk40JmuGNaeS078wy/NhlFhnVi+rHHunulE3xJAJ0CM73m8VK2+GkF9eRwQ=="],
+
+ "@expo/local-build-cache-provider": ["@expo/local-build-cache-provider@57.0.6", "", { "dependencies": { "@expo/config": "~57.0.7", "chalk": "^4.1.2" } }, "sha512-6aFMROb1SzIvrefpwhgS5QGNELU9T2lpK0Hcl6oiZ4/mbKgZRk0WEPauo/dHH6IgDmyK25InCMHF5nj7XY4LWg=="],
+
+ "@expo/log-box": ["@expo/log-box@57.0.2", "", { "dependencies": { "@expo/dom-webview": "^57.0.1", "anser": "^1.4.9", "stacktrace-parser": "^0.1.10" }, "peerDependencies": { "expo": "*", "react": "*", "react-native": "*" } }, "sha512-ZsFyfIR7YCbQAdVLzuTUmMHofZC7ZS9ywYCJNPlLc78x59cI8GwXFEIVbRjjC0uJERpNtXx/tsNNnkhexXlzMw=="],
+
+ "@expo/metro": ["@expo/metro@56.0.0", "", { "dependencies": { "metro": "0.84.4", "metro-babel-transformer": "0.84.4", "metro-cache": "0.84.4", "metro-cache-key": "0.84.4", "metro-config": "0.84.4", "metro-core": "0.84.4", "metro-file-map": "0.84.4", "metro-minify-terser": "0.84.4", "metro-resolver": "0.84.4", "metro-runtime": "0.84.4", "metro-source-map": "0.84.4", "metro-symbolicate": "0.84.4", "metro-transform-plugins": "0.84.4", "metro-transform-worker": "0.84.4" } }, "sha512-5gIgQHtEpjjvsjKfVtIv23a98LLRV0/y07PDShEwYSytAMlE3FSF8RHXqtHc1sUJL6dn7hnuIBpIbrLXXuVi0A=="],
+
+ "@expo/metro-config": ["@expo/metro-config@57.0.8", "", { "dependencies": { "@babel/code-frame": "^7.20.0", "@babel/core": "^7.20.0", "@babel/generator": "^7.20.5", "@expo/config": "~57.0.7", "@expo/env": "~2.4.2", "@expo/json-file": "~11.0.1", "@expo/metro": "~56.0.0", "@expo/require-utils": "^57.0.4", "@expo/spawn-async": "^1.8.0", "@jridgewell/gen-mapping": "^0.3.13", "@jridgewell/remapping": "^2.3.5", "@jridgewell/sourcemap-codec": "^1.5.5", "browserslist": "^4.25.0", "chalk": "^4.1.0", "debug": "^4.3.2", "getenv": "^2.0.0", "glob": "^13.0.0", "hermes-parser": "^0.36.0", "jsc-safe-url": "^0.2.4", "lightningcss": "^1.30.1", "picomatch": "^4.0.4", "postcss": "^8.5.14", "resolve-from": "^5.0.0" }, "peerDependencies": { "expo": "*" }, "optionalPeers": ["expo"] }, "sha512-cZOVjbljqRBMCXcloc5k23gsFOhWdiKXhDkp5jU/wY6IXR6G7cYtNOwxKfxI1QLhs0KcXY0gDmZ2UIueoHzY7g=="],
+
+ "@expo/metro-file-map": ["@expo/metro-file-map@57.0.1", "", { "dependencies": { "debug": "^4.3.4", "fb-watchman": "^2.0.2", "invariant": "^2.2.4", "jest-worker": "^29.7.0", "micromatch": "^4.0.4", "walker": "^1.0.8" } }, "sha512-8JXfVstZN7QnP4NianZZnlTVboOWR0sG8trUDNajOjnbGlPln29vponXM84tY+3tAHapz5/TxE53L0ixUwqPtA=="],
+
+ "@expo/metro-runtime": ["@expo/metro-runtime@57.0.9", "", { "dependencies": { "@expo/log-box": "^57.0.2", "anser": "^1.4.9", "pretty-format": "^29.7.0", "stacktrace-parser": "^0.1.10", "whatwg-fetch": "^3.0.0" }, "peerDependencies": { "expo": "*", "react": "*", "react-dom": "*", "react-native": "*" }, "optionalPeers": ["react-dom"] }, "sha512-gtly6wOk59Ip7S5NtYSYMmMmz7VyKeNWo/dERF7b1q3Rmek4fBwEV5tTHIXaDTKboAryXdWR9gjSv1DzErP/Dg=="],
+
+ "@expo/osascript": ["@expo/osascript@2.7.1", "", { "dependencies": { "@expo/spawn-async": "^1.8.0" } }, "sha512-Zn03EX6In7ts2lPUW2ESUSkEhEWQN1qqsiXjadtZMJOuZRkMiAg1ZQHuvz9DjByDWNJ2pBwAGyrts9lj9k389g=="],
+
+ "@expo/package-manager": ["@expo/package-manager@1.13.1", "", { "dependencies": { "@expo/json-file": "^11.0.1", "@expo/spawn-async": "^1.8.0", "chalk": "^4.0.0", "npm-package-arg": "^11.0.0", "ora": "^3.4.0", "resolve-workspace-root": "^2.0.0" } }, "sha512-y/K+CaYYpZpNGZhSX4HyLT/vyIunFjNfyoxNysPBCefeLKI/VCx6f9LNPzrxayr3rCYO5bl9O8H+HRQK265Nkg=="],
+
+ "@expo/plist": ["@expo/plist@0.8.1", "", { "dependencies": { "@xmldom/xmldom": "^0.8.8", "base64-js": "^1.5.1", "xmlbuilder": "^15.1.1" } }, "sha512-3gTReGIUm0oRaMClsAJYxBnVPCl6fVpsl8HS+DTVxDhW4GyVyxg9E/Znm3BvcHtUJ51RJJI14pC1wvrNilCRHw=="],
+
+ "@expo/prebuild-config": ["@expo/prebuild-config@57.0.11", "", { "dependencies": { "@expo/config": "~57.0.7", "@expo/config-plugins": "~57.0.7", "@expo/config-types": "^57.0.2", "@expo/image-utils": "^0.11.4", "@expo/json-file": "^11.0.1", "@react-native/normalize-colors": "0.86.2", "debug": "^4.3.1", "expo-modules-autolinking": "~57.0.9", "resolve-from": "^5.0.0", "semver": "^7.6.0" } }, "sha512-GcBX2xQ6l4VrkxmlAXm6lVUeHhnURe0Jh86hNVQqoYYIFflUx4IFmMm9B9bN0mbp/Jb+j+CGjkSPQcIYq9NM/Q=="],
+
+ "@expo/require-utils": ["@expo/require-utils@57.0.4", "", { "dependencies": { "@babel/code-frame": "^7.20.0", "@babel/core": "^7.25.2", "@babel/plugin-transform-modules-commonjs": "^7.24.8" }, "peerDependencies": { "typescript": "^5.0.0 || ^5.0.0-0 || ^6.0.0 || ^7.0.0" }, "optionalPeers": ["typescript"] }, "sha512-e7xbg/9BTQcsZE/oErafZXtI7kh5IgfasLJ97J5sFSzX2cA74pDvdlhW1KHVSaDkQyQv6h1LSLhsY7dEeOk7hw=="],
+
+ "@expo/router-server": ["@expo/router-server@57.0.5", "", { "dependencies": { "debug": "^4.3.4" }, "peerDependencies": { "@expo/metro-runtime": "^57.0.8", "expo": "*", "expo-constants": "^57.0.9", "expo-font": "^57.0.1", "expo-router": "*", "expo-server": "^57.0.1", "react": "*", "react-dom": "*", "react-server-dom-webpack": "~19.0.1 || ~19.1.2 || ~19.2.1" }, "optionalPeers": ["@expo/metro-runtime", "expo-router", "react-dom", "react-server-dom-webpack"] }, "sha512-vke39l0bo3H2q9JB/KXpAJ7HpscdTG3Mktbxanc8yn3riWzzSsnv0uxwZGZCrZrnDQzFxlLTXgbZrGkU26ng1w=="],
+
+ "@expo/schema-utils": ["@expo/schema-utils@57.0.2", "", {}, "sha512-fMu/jyN0l1Wzv7XkeWR4IYCx1M8ryui3FdBNGrWwbRgJ7EhxXxK8E2jxP2W3pbgUwUY0V3hG8+GyfCZwny+Lxw=="],
+
+ "@expo/sdk-runtime-versions": ["@expo/sdk-runtime-versions@1.0.0", "", {}, "sha512-Doz2bfiPndXYFPMRwPyGa1k5QaKDVpY806UJj570epIiMzWaYyCtobasyfC++qfIXVb5Ocy7r3tP9d62hAQ7IQ=="],
+
+ "@expo/spawn-async": ["@expo/spawn-async@1.8.0", "", { "dependencies": { "cross-spawn": "^7.0.6" } }, "sha512-eb9xxd/LbuEGSdua4NumCu/McVB9EM+F/JxB9pWgnERw4HQ9XyTNH1KapG6oqLWR8TuRK2LQfzJlmNi94CVobw=="],
+
+ "@expo/sudo-prompt": ["@expo/sudo-prompt@9.3.2", "", {}, "sha512-HHQigo3rQWKMDzYDLkubN5WQOYXJJE2eNqIQC2axC2iO3mHdwnIR7FgZVvHWtBwAdzBgAP0ECp8KqS8TiMKvgw=="],
+
+ "@expo/ui": ["@expo/ui@57.0.10", "", { "dependencies": { "sf-symbols-typescript": "^2.1.0", "vaul": "^1.1.2" }, "peerDependencies": { "@babel/core": "*", "expo": "*", "react": "*", "react-dom": "*", "react-native": "*", "react-native-worklets": "*" }, "optionalPeers": ["@babel/core", "react-dom", "react-native-worklets"] }, "sha512-cYVo6R6JmJgza2p1jyE1lGfNPWncHJGWRxhTyOi+pLRAAdiwo8Z2LcdaArewEXVUwJTQhczLRxeXGL0i99NUwQ=="],
+
+ "@expo/vector-icons": ["@expo/vector-icons@15.1.1", "", { "peerDependencies": { "expo-font": ">=14.0.4", "react": "*", "react-native": "*" } }, "sha512-Iu2VkcoI5vygbtYngm7jb4ifxElNVXQYdDrYkT7UCEIiKLeWnQY0wf2ZhHZ+Wro6Sc5TaumpKUOqDRpLi5rkvw=="],
+
+ "@expo/ws-tunnel": ["@expo/ws-tunnel@2.0.0", "", { "peerDependencies": { "ws": "^8.0.0" } }, "sha512-j+JfTRdCk820J9dU0sA2SqshQIKFOMo7ED84w9MJFcebfbNQgsLztEY/SABDkGnjatrW4xGqnUhVRxSBVyCkXw=="],
+
+ "@expo/xcpretty": ["@expo/xcpretty@4.4.4", "", { "dependencies": { "@babel/code-frame": "^7.20.0", "chalk": "^4.1.0", "js-yaml": "^4.1.0" }, "bin": { "excpretty": "build/cli.js" } }, "sha512-4aQzz9vgxcNXFfo/iyNgDDYfsU5XGKKxWxZopw0cVotHiW+U8IJbIxMaxsINs6bHhtkG3StKNPcOrn3eBuxKPw=="],
+
+ "@isaacs/ttlcache": ["@isaacs/ttlcache@1.4.1", "", {}, "sha512-RQgQ4uQ+pLbqXfOmieB91ejmLwvSgv9nLx6sT6sD83s7umBypgg+OIBOBbEUiJXrfpnp9j0mRhYYdzp9uqq3lA=="],
+
+ "@jest/schemas": ["@jest/schemas@29.6.3", "", { "dependencies": { "@sinclair/typebox": "^0.27.8" } }, "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA=="],
+
+ "@jest/types": ["@jest/types@29.6.3", "", { "dependencies": { "@jest/schemas": "^29.6.3", "@types/istanbul-lib-coverage": "^2.0.0", "@types/istanbul-reports": "^3.0.0", "@types/node": "*", "@types/yargs": "^17.0.8", "chalk": "^4.0.0" } }, "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw=="],
+
+ "@jridgewell/gen-mapping": ["@jridgewell/gen-mapping@0.3.13", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.0", "@jridgewell/trace-mapping": "^0.3.24" } }, "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA=="],
+
+ "@jridgewell/remapping": ["@jridgewell/remapping@2.3.5", "", { "dependencies": { "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.24" } }, "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ=="],
+
+ "@jridgewell/resolve-uri": ["@jridgewell/resolve-uri@3.1.2", "", {}, "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw=="],
+
+ "@jridgewell/source-map": ["@jridgewell/source-map@0.3.11", "", { "dependencies": { "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.25" } }, "sha512-ZMp1V8ZFcPG5dIWnQLr3NSI1MiCU7UETdS/A0G8V/XWHvJv3ZsFqutJn1Y5RPmAPX6F3BiE397OqveU/9NCuIA=="],
+
+ "@jridgewell/sourcemap-codec": ["@jridgewell/sourcemap-codec@1.5.5", "", {}, "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og=="],
+
+ "@jridgewell/trace-mapping": ["@jridgewell/trace-mapping@0.3.31", "", { "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/sourcemap-codec": "^1.4.14" } }, "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw=="],
+
+ "@radix-ui/primitive": ["@radix-ui/primitive@1.1.7", "", {}, "sha512-rqWnm76nYT8HoNNqEjpgJ7Pw/DrBj5iBTrmEPo6HTX5+VJyBNOqTdv4g89G63HuR5g0AaENoAcH7Is5fF2kZ8Q=="],
+
+ "@radix-ui/react-collection": ["@radix-ui/react-collection@1.1.15", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.5", "@radix-ui/react-context": "1.2.2", "@radix-ui/react-primitive": "2.1.10", "@radix-ui/react-slot": "1.3.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-9W+B9NPF0NaaPh/1NJd3+KqsnlLqU9H7T2rvww+fp+T/evVXdNAyYcnfRQZFOjkR1ajQp3yORlqnI8soawLvNA=="],
+
+ "@radix-ui/react-compose-refs": ["@radix-ui/react-compose-refs@1.1.5", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-+48PbAAbq3didjJxa+OaWY2ZwgAKsNiRGyeHKszblZMQ+kcpd9pAaT11cMkGEie0vsOi3QdeTE6d5Fe3Gn61kA=="],
+
+ "@radix-ui/react-context": ["@radix-ui/react-context@1.2.2", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-RHCUGwKHDr0hDGg4X7ma4JG4/+12qxw8rkh5QKdDldlCvtja6nUx1Ef/8HVrJze81lEsgLQlqjzjGNHantgnQA=="],
+
+ "@radix-ui/react-dialog": ["@radix-ui/react-dialog@1.1.23", "", { "dependencies": { "@radix-ui/primitive": "1.1.7", "@radix-ui/react-compose-refs": "1.1.5", "@radix-ui/react-context": "1.2.2", "@radix-ui/react-dismissable-layer": "1.1.19", "@radix-ui/react-focus-guards": "1.1.6", "@radix-ui/react-focus-scope": "1.1.16", "@radix-ui/react-id": "1.1.4", "@radix-ui/react-portal": "1.1.17", "@radix-ui/react-presence": "1.1.10", "@radix-ui/react-primitive": "2.1.10", "@radix-ui/react-slot": "1.3.3", "@radix-ui/react-use-controllable-state": "1.2.6", "@radix-ui/react-use-layout-effect": "1.1.4", "aria-hidden": "^1.2.4", "react-remove-scroll": "^2.7.2" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-Ksw4WeROkO4rC9k/onilX/Ao2Cr1ku1unMNH+XSCcP4jSXYu7HDsg9n4ojMjVb22XpYjAQ9qfrFlVbru1vXDUA=="],
+
+ "@radix-ui/react-direction": ["@radix-ui/react-direction@1.1.4", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-5pzg4FGQNpExhnhT2zlrP1wZFaYCd1K0nYWoFAdcYoYK868IEigqMX3B3f8yIoRlAhAeDWciLI6ZdCKHF9P4Vg=="],
+
+ "@radix-ui/react-dismissable-layer": ["@radix-ui/react-dismissable-layer@1.1.19", "", { "dependencies": { "@radix-ui/primitive": "1.1.7", "@radix-ui/react-compose-refs": "1.1.5", "@radix-ui/react-primitive": "2.1.10", "@radix-ui/react-use-callback-ref": "1.1.4", "@radix-ui/react-use-effect-event": "0.0.5" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-8g4pfOL9HoKKLWGiypT+dphVqjFfmcXO5GBnhsG6zI+lxAx/8feQpr+1LSN8Re3hiZ+XkLNS4O9ztK11/LzQ6w=="],
+
+ "@radix-ui/react-focus-guards": ["@radix-ui/react-focus-guards@1.1.6", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-RNOJjfZMTyBM6xYmV3IVGXkPjIhcBAuv48POevAXwrGJhkWZ9p1rFoIS1JFooPuT193AZmRsCPhpoVJxx6OPoQ=="],
+
+ "@radix-ui/react-focus-scope": ["@radix-ui/react-focus-scope@1.1.16", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.5", "@radix-ui/react-primitive": "2.1.10", "@radix-ui/react-use-callback-ref": "1.1.4" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-wmRZ2WWLvmt6KHy2rNPOdPUjwq5xOHY02+m+udwJTn0aNIox/rkskAvJTyTLGhPK6KgrUjlJUJpgmx/+wFiFIQ=="],
+
+ "@radix-ui/react-id": ["@radix-ui/react-id@1.1.4", "", { "dependencies": { "@radix-ui/react-use-layout-effect": "1.1.4" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-TMQp2llA+RYn7JcjnrMnz7wN4pcVttPZnRZo52PLQsoLVKzNlVwUeHmfePgTgRluXFvlD3GD5g5MOVVTJCO0qA=="],
+
+ "@radix-ui/react-portal": ["@radix-ui/react-portal@1.1.17", "", { "dependencies": { "@radix-ui/react-primitive": "2.1.10", "@radix-ui/react-use-layout-effect": "1.1.4" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-vKQLcWypUnwZVvfV7UkGahH2g6ySe8M8R+zYBwPrv5byZ9QAW6cQVvNKo7GgmD+p8aYb6D9JBuvy8/WhOno2wQ=="],
+
+ "@radix-ui/react-presence": ["@radix-ui/react-presence@1.1.10", "", { "dependencies": { "@radix-ui/react-use-layout-effect": "1.1.4" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-3wyzCQ6+ubRA+D4uv9m95JYLXxmOHp05qjrkjeA7uKHHtjpPggQzc6DAb0URl7j67oR0K2foO4ip27TiX037Bw=="],
+
+ "@radix-ui/react-primitive": ["@radix-ui/react-primitive@2.1.10", "", { "dependencies": { "@radix-ui/react-slot": "1.3.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-MucOnzh6hR5mid6VpkbglRAMYMjKLqRnGBbjXkzjK52fuQDd1qbkx78a5P40mkcnVXJdEVxm26E9OPAiUq7nBg=="],
+
+ "@radix-ui/react-roving-focus": ["@radix-ui/react-roving-focus@1.1.19", "", { "dependencies": { "@radix-ui/primitive": "1.1.7", "@radix-ui/react-collection": "1.1.15", "@radix-ui/react-compose-refs": "1.1.5", "@radix-ui/react-context": "1.2.2", "@radix-ui/react-direction": "1.1.4", "@radix-ui/react-id": "1.1.4", "@radix-ui/react-primitive": "2.1.10", "@radix-ui/react-use-callback-ref": "1.1.4", "@radix-ui/react-use-controllable-state": "1.2.6", "@radix-ui/react-use-is-hydrated": "0.1.3", "@radix-ui/react-use-layout-effect": "1.1.4" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-V9jI6hDjT7l3jsCQD9bLNvDLM3tH/gdbOTp7Tefp3hbbgCGQoK7tUvrWiRlcoBHIZ809ElXwNQwVo0B98LuTXQ=="],
+
+ "@radix-ui/react-slot": ["@radix-ui/react-slot@1.3.3", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.5" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-qx7oqnYbxnK9kYI9m317qmFmEgo6ywqWvbTogdj7cL9p3/yx4M48p7Rnw5z3H890cL/ow/EeWJsuTykeZVXP5Q=="],
+
+ "@radix-ui/react-tabs": ["@radix-ui/react-tabs@1.1.21", "", { "dependencies": { "@radix-ui/primitive": "1.1.7", "@radix-ui/react-context": "1.2.2", "@radix-ui/react-direction": "1.1.4", "@radix-ui/react-id": "1.1.4", "@radix-ui/react-presence": "1.1.10", "@radix-ui/react-primitive": "2.1.10", "@radix-ui/react-roving-focus": "1.1.19", "@radix-ui/react-use-controllable-state": "1.2.6" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-UKxJlZid7FVtsk/WTxj4i4uSEgj2Au+KBbS7SQyTlzMhhn+86Cz3tISZdTa87bfEfcuvZezf2ZsxD4xuEKtkog=="],
+
+ "@radix-ui/react-use-callback-ref": ["@radix-ui/react-use-callback-ref@1.1.4", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-R6OUY2e2fA6Yn6s+VSx5KBV6Nx8LQEhu+cz7LCej18rQ1HLyg9PSC9jP/ZNx0o6FAIK9c0F1kHylzSxKsdlkrQ=="],
+
+ "@radix-ui/react-use-controllable-state": ["@radix-ui/react-use-controllable-state@1.2.6", "", { "dependencies": { "@radix-ui/primitive": "1.1.7", "@radix-ui/react-use-effect-event": "0.0.5", "@radix-ui/react-use-layout-effect": "1.1.4" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-uEQJGT97ZA/TgP/Hydw47lHu+/vQj6z/0jA+WeTbK1o9Rx45GImjpD0tc3W5ad3D6XTSR6e1yEO0FvGq6WQfVQ=="],
+
+ "@radix-ui/react-use-effect-event": ["@radix-ui/react-use-effect-event@0.0.5", "", { "dependencies": { "@radix-ui/react-use-layout-effect": "1.1.4" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-7cshFL8HGS/7HEiHH+9kL9HBwp2sa9yX18Knwek6KYWmXwM7pegMgta2AXMQKI+rq3JnfSj9x8wYqFMTdG1Jgg=="],
+
+ "@radix-ui/react-use-is-hydrated": ["@radix-ui/react-use-is-hydrated@0.1.3", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-umO/aJ+82CpOnhDZUTbILCQf7kU/g0iv+oGs/Q8jw7IkhWBzaEP4sA268PhFAJTFetbwp3ICc6ktpI4TqtxcIw=="],
+
+ "@radix-ui/react-use-layout-effect": ["@radix-ui/react-use-layout-effect@1.1.4", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-K20DkRkUwDnxEYMBPcg3Y6voLkEy5p5QQmszZgLngKKiC7dzBR/aEuK3w1qlx2JWDUNH6FluahYdgR3BP+QbYw=="],
+
+ "@react-native-masked-view/masked-view": ["@react-native-masked-view/masked-view@0.3.2", "", { "peerDependencies": { "react": ">=16", "react-native": ">=0.57" } }, "sha512-XwuQoW7/GEgWRMovOQtX3A4PrXhyaZm0lVUiY8qJDvdngjLms9Cpdck6SmGAUNqQwcj2EadHC1HwL0bEyoa/SQ=="],
+
+ "@react-native/assets-registry": ["@react-native/assets-registry@0.86.2", "", {}, "sha512-vcX/mBjWAVnWofu7KecotquI2unZ/tITwA7OGdq/mdY/zmGXIEvYhfEYyOQij/LRqi9WAL+iizInTBWnxDhK/Q=="],
+
+ "@react-native/babel-plugin-codegen": ["@react-native/babel-plugin-codegen@0.86.2", "", { "dependencies": { "@babel/traverse": "^7.29.0", "@react-native/codegen": "0.86.2" } }, "sha512-NNDZqOlNbH5SzgPks1jFDYH3234Rpa5e/nhZymxhIiBH3NcE3uD+rGj/HWXhH7nHF2ToGK6XbUpqy7nmJPeh+g=="],
+
+ "@react-native/babel-preset": ["@react-native/babel-preset@0.87.0", "", { "dependencies": { "@babel/core": "^7.25.2", "@babel/plugin-proposal-export-default-from": "^7.24.7", "@babel/plugin-syntax-dynamic-import": "^7.8.3", "@babel/plugin-syntax-export-default-from": "^7.24.7", "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", "@babel/plugin-syntax-optional-chaining": "^7.8.3", "@babel/plugin-transform-async-generator-functions": "^7.25.4", "@babel/plugin-transform-async-to-generator": "^7.24.7", "@babel/plugin-transform-block-scoping": "^7.25.0", "@babel/plugin-transform-class-properties": "^7.25.4", "@babel/plugin-transform-classes": "^7.25.4", "@babel/plugin-transform-destructuring": "^7.24.8", "@babel/plugin-transform-flow-strip-types": "^7.25.2", "@babel/plugin-transform-for-of": "^7.24.7", "@babel/plugin-transform-modules-commonjs": "^7.24.8", "@babel/plugin-transform-named-capturing-groups-regex": "^7.24.7", "@babel/plugin-transform-nullish-coalescing-operator": "^7.24.7", "@babel/plugin-transform-optional-catch-binding": "^7.24.7", "@babel/plugin-transform-optional-chaining": "^7.24.8", "@babel/plugin-transform-private-methods": "^7.24.7", "@babel/plugin-transform-private-property-in-object": "^7.24.7", "@babel/plugin-transform-react-display-name": "^7.24.7", "@babel/plugin-transform-react-jsx": "^7.25.2", "@babel/plugin-transform-react-jsx-self": "^7.24.7", "@babel/plugin-transform-react-jsx-source": "^7.24.7", "@babel/plugin-transform-regenerator": "^7.24.7", "@babel/plugin-transform-runtime": "^7.24.7", "@babel/plugin-transform-typescript": "^7.25.2", "@babel/plugin-transform-unicode-regex": "^7.24.7", "@react-native/babel-plugin-codegen": "0.87.0", "babel-plugin-syntax-hermes-parser": "0.36.1", "babel-plugin-transform-flow-enums": "^0.0.2", "react-refresh": "^0.14.0" } }, "sha512-vthkHlSDWFVCQtQ22JZadM1J7wicn0773sP0C8wMb+2g6+6hn1209A1rMJz0ijpTI+RQ4XyQRmbnyTsf4kuIWg=="],
+
+ "@react-native/codegen": ["@react-native/codegen@0.86.2", "", { "dependencies": { "@babel/core": "^7.25.2", "@babel/parser": "^7.29.0", "hermes-parser": "0.36.0", "invariant": "^2.2.4", "nullthrows": "^1.1.1", "tinyglobby": "^0.2.15", "yargs": "^17.6.2" } }, "sha512-xKkudsahUJ1n//55g4fXk5BStVqqmZlz8HQveL45ZxcfDnwvhuYe2GymksQANFsSN+slvrarjrfq8kIxJzbceA=="],
+
+ "@react-native/community-cli-plugin": ["@react-native/community-cli-plugin@0.86.2", "", { "dependencies": { "@react-native/dev-middleware": "0.86.2", "debug": "^4.4.0", "invariant": "^2.2.4", "metro": "^0.84.3", "metro-config": "^0.84.3", "metro-core": "^0.84.3", "semver": "^7.1.3" }, "peerDependencies": { "@react-native-community/cli": "*", "@react-native/metro-config": "0.86.2" }, "optionalPeers": ["@react-native-community/cli", "@react-native/metro-config"] }, "sha512-YHXNKoM6Y/HjREySZ5arET2xgiHgg67r1MdwJB//MPJAJ0Xc5g0u6UHxY9VzsHO3Y07dre6s0BinYwjt1SEWvQ=="],
+
+ "@react-native/debugger-frontend": ["@react-native/debugger-frontend@0.86.2", "", {}, "sha512-KGS1aV5F6cIqpnoIUhLBXyVzy1oAj8jBFGau6vX4Vy0HXRJN7p+68RU7x6NuyraHvQcR14ccMGT5TkFuNjQ4gA=="],
+
+ "@react-native/debugger-shell": ["@react-native/debugger-shell@0.86.2", "", { "dependencies": { "cross-spawn": "^7.0.6", "debug": "^4.4.0", "fb-dotslash": "0.5.8" } }, "sha512-/TaVJ2+gGajZPJGrFaObUQmHmlaxAlfmOPZicl6pNKDUjzSgFMpcLkdTOExvb+USYTVdGX1XwxXyvjQdUO2bvg=="],
+
+ "@react-native/dev-middleware": ["@react-native/dev-middleware@0.86.2", "", { "dependencies": { "@isaacs/ttlcache": "^1.4.1", "@react-native/debugger-frontend": "0.86.2", "@react-native/debugger-shell": "0.86.2", "chrome-launcher": "^0.15.2", "chromium-edge-launcher": "^0.3.0", "connect": "^3.6.5", "debug": "^4.4.0", "invariant": "^2.2.4", "nullthrows": "^1.1.1", "open": "^7.0.3", "serve-static": "^1.16.2", "ws": "^7.5.10" } }, "sha512-B7L0vKvg+IcEElT7Vpqh1xj5yJAqWUegjbP+bQRaorJMAYnv11GkliTnZV2AdTDfZQJWgOEx8i8LGkHkUg7bnA=="],
+
+ "@react-native/gradle-plugin": ["@react-native/gradle-plugin@0.86.2", "", {}, "sha512-2F6x14NcHMpVmfTTFKfMkpV5dZedZrLiv6PE+c3vgnesV2bjleUBydr4U+NI8VkI7OwW71L0A5qQ76I9LCrfoQ=="],
+
+ "@react-native/js-polyfills": ["@react-native/js-polyfills@0.86.2", "", {}, "sha512-bIwNcGBaQ74shB5z1mRkxOpjikimuwsnOCEkZSzL67Z1FTyK1ObpENfyd2QvcvVW9Cjl+tHuw9ynpBnb2jPoJQ=="],
+
+ "@react-native/metro-babel-transformer": ["@react-native/metro-babel-transformer@0.87.0", "", { "dependencies": { "@babel/core": "^7.25.2", "@react-native/babel-preset": "0.87.0", "hermes-parser": "0.36.1", "nullthrows": "^1.1.1" } }, "sha512-z57jsBX3q0fh2jTnrXisBo8A5qfkVFrnVJ0HMKRa8+cVsw/bz6MiEkXA/dsBK8eJfjawccxzXhAIzTzwbnxl4Q=="],
+
+ "@react-native/metro-config": ["@react-native/metro-config@0.87.0", "", { "dependencies": { "@react-native/js-polyfills": "0.87.0", "@react-native/metro-babel-transformer": "0.87.0", "metro-config": "^0.87.0", "metro-runtime": "^0.87.0" } }, "sha512-Pg0DmsJ/DbLP8JuxnRSDmrIaQjKhpzd2uYAZRyB2A8fJQzJWpAFLr7TUAXhiGD5025F6+PVPAnJL3HXaeMfZqQ=="],
+
+ "@react-native/normalize-colors": ["@react-native/normalize-colors@0.86.2", "", {}, "sha512-EzPFc9Y6lzYOWeso2almwXI7f8+qReHxWvT+algsOczb2UhWXIWXDoSvkdwoSfiwwmGt/ijJgKJoeHlzPkLwRg=="],
+
+ "@react-native/virtualized-lists": ["@react-native/virtualized-lists@0.86.2", "", { "dependencies": { "invariant": "^2.2.4", "nullthrows": "^1.1.1" }, "peerDependencies": { "@types/react": "^19.2.0", "react": "*", "react-native": "0.86.2" }, "optionalPeers": ["@types/react"] }, "sha512-uO0J72gh3EvE+1/GHRk18QRyBDTRHRB0AraAfojsRjbT7VMuJwKrZYaKGshavoaEud6aw00ZB9/8mTMIKjjcAw=="],
+
+ "@react-navigation/bottom-tabs": ["@react-navigation/bottom-tabs@7.18.16", "", { "dependencies": { "@react-navigation/elements": "^2.9.38", "color": "^4.2.3", "sf-symbols-typescript": "^2.1.0" }, "peerDependencies": { "@react-navigation/native": "^7.3.16", "react": ">= 18.2.0", "react-native": "*", "react-native-safe-area-context": ">= 4.0.0", "react-native-screens": ">= 4.0.0" } }, "sha512-5tBFuxvsCQBvYauDZK6u/uPdD86i/caWgBzABlZfTh8W2J7YZSHjT9SWOsquSMmR6dpcNj6idMd4utCNzuOnZg=="],
+
+ "@react-navigation/core": ["@react-navigation/core@7.21.12", "", { "dependencies": { "@react-navigation/routers": "^7.6.4", "escape-string-regexp": "^4.0.0", "fast-deep-equal": "^3.1.3", "nanoid": "^3.3.11", "query-string": "^7.1.3", "react-is": "^19.1.0", "use-latest-callback": "^0.2.4", "use-sync-external-store": "^1.5.0" }, "peerDependencies": { "react": ">= 18.2.0" } }, "sha512-FopGMGy5df+IMqUYg9w7ygwK0oP4RaQbMnpb7VFP30+vZdd8MqsAGc+bZZwdiVSnzK9hzhgJtZV9XF0ZFlUYOQ=="],
+
+ "@react-navigation/elements": ["@react-navigation/elements@2.9.38", "", { "dependencies": { "color": "^4.2.3", "use-latest-callback": "^0.2.4", "use-sync-external-store": "^1.5.0" }, "peerDependencies": { "@react-native-masked-view/masked-view": ">= 0.2.0", "@react-navigation/native": "^7.3.16", "react": ">= 18.2.0", "react-native": "*", "react-native-safe-area-context": ">= 4.0.0" }, "optionalPeers": ["@react-native-masked-view/masked-view"] }, "sha512-M/2HWDiSO4zO7VyfAnovrTPWOAzTC+1DnVT7ZWZW93+/KVRF9OYlqixIUpPenQ0iQh2j1EaQ4zOe/134Arisqw=="],
+
+ "@react-navigation/native": ["@react-navigation/native@7.3.16", "", { "dependencies": { "@react-navigation/core": "^7.21.12", "escape-string-regexp": "^4.0.0", "fast-deep-equal": "^3.1.3", "nanoid": "^3.3.11", "standard-navigation": "^0.0.8", "use-latest-callback": "^0.2.4" }, "peerDependencies": { "react": ">= 18.2.0", "react-native": "*" } }, "sha512-Wy/6mai2HpA5AEVFk7JFfvv4RUArwuN2UenP/fc3NK7kOyfSlNu1tmb/3JDPpMzPIRbF1MPB8PKAHjVB29qNEQ=="],
+
+ "@react-navigation/routers": ["@react-navigation/routers@7.6.4", "", { "dependencies": { "nanoid": "^3.3.11" } }, "sha512-GI7eJm8/KsZUQaYcXvEExikKurRZRgEsSzyZ7faENfi65yqJBCXjDMwyN1pF6pNW1MoLH1ErDwDivFxY6BzD3w=="],
+
+ "@sinclair/typebox": ["@sinclair/typebox@0.27.12", "", {}, "sha512-hhyNJ+nbR6ZR7pToHvllEFun9TL0sbL+tk/ON75lo+Xas054uez98qRbsuNt7MBCyZKK4+8Yli/OAGZhmfBZ/g=="],
+
+ "@testing-library/dom": ["@testing-library/dom@10.4.1", "", { "dependencies": { "@babel/code-frame": "^7.10.4", "@babel/runtime": "^7.12.5", "@types/aria-query": "^5.0.1", "aria-query": "5.3.0", "dom-accessibility-api": "^0.5.9", "lz-string": "^1.5.0", "picocolors": "1.1.1", "pretty-format": "^27.0.2" } }, "sha512-o4PXJQidqJl82ckFaXUeoAW+XysPLauYI43Abki5hABd853iMhitooc6znOnczgbTYmEP6U6/y1ZyKAIsvMKGg=="],
+
+ "@testing-library/jest-dom": ["@testing-library/jest-dom@6.10.0", "", { "dependencies": { "@adobe/css-tools": "^4.4.0", "aria-query": "^5.0.0", "css.escape": "^1.5.1", "dom-accessibility-api": "^0.6.3", "picocolors": "^1.1.1", "redent": "^3.0.0" }, "peerDependencies": { "@testing-library/dom": ">=10 <11" } }, "sha512-HQwu0KaB2zyT0iLzBL+8CLyZDL3KlZlZJ+2iyc9uCUnlJVskJU/UlPuVCyIPhtukjPQdT2QNoR5nCP5FqTmmDQ=="],
+
+ "@testing-library/user-event": ["@testing-library/user-event@14.6.4", "", { "peerDependencies": { "@testing-library/dom": ">=7.21.4" } }, "sha512-QCGwP6QrjypBLwyj5cuyfVamkaIEy/XGY+1VDehbtbQqOggYmTFpFOdWR5mPz14vX8vXLMVjDHlRNBcClyO9ew=="],
+
+ "@types/aria-query": ["@types/aria-query@5.0.4", "", {}, "sha512-rfT93uj5s0PRL7EzccGMs3brplhcrghnDoV26NqKhCAS1hVo+WdNsPvE/yb6ilfr5hi2MEk6d5EWJTKdxg8jVw=="],
+
+ "@types/hammerjs": ["@types/hammerjs@2.0.46", "", {}, "sha512-ynRvcq6wvqexJ9brDMS4BnBLzmr0e14d6ZJTEShTBWKymQiHwlAyGu0ZPEFI2Fh1U53F7tN9ufClWM5KvqkKOw=="],
+
+ "@types/istanbul-lib-coverage": ["@types/istanbul-lib-coverage@2.0.6", "", {}, "sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w=="],
+
+ "@types/istanbul-lib-report": ["@types/istanbul-lib-report@3.0.3", "", { "dependencies": { "@types/istanbul-lib-coverage": "*" } }, "sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA=="],
+
+ "@types/istanbul-reports": ["@types/istanbul-reports@3.0.4", "", { "dependencies": { "@types/istanbul-lib-report": "*" } }, "sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ=="],
+
+ "@types/node": ["@types/node@26.2.0", "", { "dependencies": { "undici-types": "~8.3.0" } }, "sha512-5IviulTZeRNp2vAJ514cc/HUlY5nZ9fCbq9DMyC52BrhFZACo3nI0R7qBxhQmo/d27NFe96ur/b7Wwxklda+kg=="],
+
+ "@types/react": ["@types/react@19.2.18", "", { "dependencies": { "csstype": "^3.2.2" } }, "sha512-AnzbBERsrLKtk2XSfTbYRLjQPdy116Sty4q+T+Bp3IC4l6jNBvreVPAHmpq9qhXQM7CXZPjLVmGMw9sy+hxQ3w=="],
+
+ "@types/react-test-renderer": ["@types/react-test-renderer@19.1.0", "", { "dependencies": { "@types/react": "*" } }, "sha512-XD0WZrHqjNrxA/MaR9O22w/RNidWR9YZmBdRGI7wcnWGrv/3dA8wKCJ8m63Sn+tLJhcjmuhOi629N66W6kgWzQ=="],
+
+ "@types/yargs": ["@types/yargs@17.0.35", "", { "dependencies": { "@types/yargs-parser": "*" } }, "sha512-qUHkeCyQFxMXg79wQfTtfndEC+N9ZZg76HJftDJp+qH2tV7Gj4OJi7l+PiWwJ+pWtW8GwSmqsDj/oymhrTWXjg=="],
+
+ "@types/yargs-parser": ["@types/yargs-parser@21.0.3", "", {}, "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ=="],
+
+ "@ungap/structured-clone": ["@ungap/structured-clone@1.3.3", "", {}, "sha512-60YRaenCQcVjYEKOcG824+DRGGIQ3VKErcBoAEDJZz5bKIs2ZG+X/H9Nk+Q6EVkwJk5QNApxbrc5QtBSwtrXAg=="],
+
+ "@xmldom/xmldom": ["@xmldom/xmldom@0.8.14", "", {}, "sha512-T4EDRUBVZYRldYApjEJiU0e1stYWaRAX7CuSnKzrpwdZKo53zGV8/pqfzV6FfwNl9YThD2OumQYvqtvjvgG7aQ=="],
+
+ "abort-controller": ["abort-controller@3.0.0", "", { "dependencies": { "event-target-shim": "^5.0.0" } }, "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg=="],
+
+ "accepts": ["accepts@1.3.8", "", { "dependencies": { "mime-types": "~2.1.34", "negotiator": "0.6.3" } }, "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw=="],
+
+ "acorn": ["acorn@8.18.0", "", { "bin": { "acorn": "bin/acorn" } }, "sha512-lGq+9yr1/GuAWaVYIHRjvvySG5/4VfKIvC8EWxStPdcDh/Ka7FG3twP6v4d5BkravUilhIAsG4Qj83t02LWUPQ=="],
+
+ "agent-base": ["agent-base@7.1.4", "", {}, "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ=="],
+
+ "agent-cli-detector": ["agent-cli-detector@0.1.5", "", { "bin": { "agent-cli-detector": "dist/cli.js" } }, "sha512-6xvLw0EGPuxoYGZeqyMV4AK+WoZ31jsqb7a5pln1BTf6oDFsrgvfCJT7E7y9oAqifJZhJ3fZ0J36H7o6JzrB0Q=="],
+
+ "anser": ["anser@1.4.10", "", {}, "sha512-hCv9AqTQ8ycjpSd3upOJd7vFwW1JaoYQ7tpham03GJ1ca8/65rqn0RpaWpItOAd6ylW9wAw6luXYPJIyPFVOww=="],
+
+ "ansi-escapes": ["ansi-escapes@4.3.2", "", { "dependencies": { "type-fest": "^0.21.3" } }, "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ=="],
+
+ "ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="],
+
+ "ansi-styles": ["ansi-styles@5.2.0", "", {}, "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA=="],
+
+ "arg": ["arg@5.0.2", "", {}, "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg=="],
+
+ "argparse": ["argparse@2.0.1", "", {}, "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="],
+
+ "aria-hidden": ["aria-hidden@1.2.6", "", { "dependencies": { "tslib": "^2.0.0" } }, "sha512-ik3ZgC9dY/lYVVM++OISsaYDeg1tb0VtP5uL3ouh1koGOaUMDPpbFIei4JkFimWUFPn90sbMNMXQAIVOlnYKJA=="],
+
+ "aria-query": ["aria-query@5.3.2", "", {}, "sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw=="],
+
+ "asap": ["asap@2.0.6", "", {}, "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA=="],
+
+ "babel-plugin-polyfill-corejs2": ["babel-plugin-polyfill-corejs2@0.4.17", "", { "dependencies": { "@babel/compat-data": "^7.28.6", "@babel/helper-define-polyfill-provider": "^0.6.8", "semver": "^6.3.1" }, "peerDependencies": { "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" } }, "sha512-aTyf30K/rqAsNwN76zYrdtx8obu0E4KoUME29B1xj+B3WxgvWkp943vYQ+z8Mv3lw9xHXMHpvSPOBxzAkIa94w=="],
+
+ "babel-plugin-polyfill-corejs3": ["babel-plugin-polyfill-corejs3@0.13.0", "", { "dependencies": { "@babel/helper-define-polyfill-provider": "^0.6.5", "core-js-compat": "^3.43.0" }, "peerDependencies": { "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" } }, "sha512-U+GNwMdSFgzVmfhNm8GJUX88AadB3uo9KpJqS3FaqNIPKgySuvMb+bHPsOmmuWyIcuqZj/pzt1RUIUZns4y2+A=="],
+
+ "babel-plugin-polyfill-regenerator": ["babel-plugin-polyfill-regenerator@0.6.8", "", { "dependencies": { "@babel/helper-define-polyfill-provider": "^0.6.8" }, "peerDependencies": { "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" } }, "sha512-M762rNHfSF1EV3SLtnCJXFoQbbIIz0OyRwnCmV0KPC7qosSfCO0QLTSuJX3ayAebubhE6oYBAYPrBA5ljowaZg=="],
+
+ "babel-plugin-react-compiler": ["babel-plugin-react-compiler@1.0.0", "", { "dependencies": { "@babel/types": "^7.26.0" } }, "sha512-Ixm8tFfoKKIPYdCCKYTsqv+Fd4IJ0DQqMyEimo+pxUOMUR9cVPlwTrFt9Avu+3cb6Zp3mAzl+t1MrG2fxxKsxw=="],
+
+ "babel-plugin-react-native-web": ["babel-plugin-react-native-web@0.21.2", "", {}, "sha512-SPD0J6qjJn8231i0HZhlAGH6NORe+QvRSQM2mwQEzJ2Fb3E4ruWTiiicPlHjmeWShDXLcvoorOCXjeR7k/lyWA=="],
+
+ "babel-plugin-syntax-hermes-parser": ["babel-plugin-syntax-hermes-parser@0.36.0", "", { "dependencies": { "hermes-parser": "0.36.0" } }, "sha512-LhD0xdoedDw7ansQgXbB2DADLZIK/LRXuWNBPuVzMc5S2WK5GyT89tCM+cQzxFGO0mGyLK6D5TrVOJJzAoDy8Q=="],
+
+ "babel-plugin-transform-flow-enums": ["babel-plugin-transform-flow-enums@0.0.2", "", { "dependencies": { "@babel/plugin-syntax-flow": "^7.12.1" } }, "sha512-g4aaCrDDOsWjbm0PUUeVnkcVd6AKJsVc/MbnPhEotEpkeJQP6b8nzewohQi7+QS8UyPehOhGWn0nOwjvWpmMvQ=="],
+
+ "babel-preset-expo": ["babel-preset-expo@57.0.6", "", { "dependencies": { "@babel/generator": "^7.20.5", "@babel/helper-module-imports": "^7.25.9", "@babel/plugin-proposal-decorators": "^7.12.9", "@babel/plugin-proposal-export-default-from": "^7.24.7", "@babel/plugin-syntax-dynamic-import": "^7.8.3", "@babel/plugin-syntax-export-default-from": "^7.24.7", "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", "@babel/plugin-syntax-optional-chaining": "^7.8.3", "@babel/plugin-transform-async-generator-functions": "^7.25.4", "@babel/plugin-transform-async-to-generator": "^7.24.7", "@babel/plugin-transform-block-scoping": "^7.25.0", "@babel/plugin-transform-class-properties": "^7.25.4", "@babel/plugin-transform-class-static-block": "^7.27.1", "@babel/plugin-transform-classes": "^7.25.4", "@babel/plugin-transform-destructuring": "^7.24.8", "@babel/plugin-transform-export-namespace-from": "^7.25.9", "@babel/plugin-transform-flow-strip-types": "^7.25.2", "@babel/plugin-transform-for-of": "^7.24.7", "@babel/plugin-transform-logical-assignment-operators": "^7.24.7", "@babel/plugin-transform-modules-commonjs": "^7.24.8", "@babel/plugin-transform-named-capturing-groups-regex": "^7.24.7", "@babel/plugin-transform-nullish-coalescing-operator": "^7.24.7", "@babel/plugin-transform-object-rest-spread": "^7.24.7", "@babel/plugin-transform-optional-catch-binding": "^7.24.7", "@babel/plugin-transform-optional-chaining": "^7.24.8", "@babel/plugin-transform-parameters": "^7.24.7", "@babel/plugin-transform-private-methods": "^7.24.7", "@babel/plugin-transform-private-property-in-object": "^7.24.7", "@babel/plugin-transform-react-display-name": "^7.24.7", "@babel/plugin-transform-react-jsx": "^7.28.6", "@babel/plugin-transform-react-jsx-development": "^7.27.1", "@babel/plugin-transform-react-pure-annotations": "^7.27.1", "@babel/plugin-transform-runtime": "^7.24.7", "@babel/plugin-transform-typescript": "^7.25.2", "@babel/plugin-transform-unicode-regex": "^7.24.7", "@babel/preset-typescript": "^7.23.0", "@react-native/babel-plugin-codegen": "0.86.2", "babel-plugin-react-compiler": "^1.0.0", "babel-plugin-react-native-web": "~0.21.0", "babel-plugin-syntax-hermes-parser": "^0.36.0", "babel-plugin-transform-flow-enums": "^0.0.2", "debug": "^4.3.4" }, "peerDependencies": { "@babel/runtime": "^7.20.0", "expo": "*", "expo-widgets": "^57.0.8", "react-refresh": ">=0.14.0 <1.0.0" }, "optionalPeers": ["@babel/runtime", "expo", "expo-widgets"] }, "sha512-ASyy0iP7yPQtq2QaMEnZG4O7YQ/x4sTMguk7PZcow2OHFnWsBpX6v+UCmh/uwCzGfD1q93jDQEuACWwWx4kSrw=="],
+
+ "balanced-match": ["balanced-match@4.0.4", "", {}, "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA=="],
+
+ "base64-js": ["base64-js@1.5.1", "", {}, "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA=="],
+
+ "baseline-browser-mapping": ["baseline-browser-mapping@2.11.14", "", { "bin": { "baseline-browser-mapping": "dist/cli.cjs" } }, "sha512-JyJ954WzuIR8/FFzX0o5krdSTrBAkcCSRfWSleRsIHSWV+cZe2FI1PKggVkFke1hBldRs+LRxUczzE9iPmgZww=="],
+
+ "big-integer": ["big-integer@1.6.52", "", {}, "sha512-QxD8cf2eVqJOOz63z6JIN9BzvVs/dlySa5HGSBH5xtR8dPteIRQnBxxKqkNTiT6jbDTF6jAfrd4oMcND9RGbQg=="],
+
+ "boolbase": ["boolbase@1.0.0", "", {}, "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww=="],
+
+ "bplist-creator": ["bplist-creator@0.1.0", "", { "dependencies": { "stream-buffers": "2.2.x" } }, "sha512-sXaHZicyEEmY86WyueLTQesbeoH/mquvarJaQNbjuOQO+7gbFcDEWqKmcWA4cOTLzFlfgvkiVxolk1k5bBIpmg=="],
+
+ "bplist-parser": ["bplist-parser@0.3.2", "", { "dependencies": { "big-integer": "1.6.x" } }, "sha512-apC2+fspHGI3mMKj+dGevkGo/tCqVB8jMb6i+OX+E29p0Iposz07fABkRIfVUPNd5A5VbuOz1bZbnmkKLYF+wQ=="],
+
+ "brace-expansion": ["brace-expansion@5.0.9", "", { "dependencies": { "balanced-match": "^4.0.2" } }, "sha512-ScQ4IuvIEF1TMlP7Zt+vjJ//9zlPb2SDcxWxM3bk8s6t6GGdJ7KO1dCcTidOPJKePW30LE/2cT7wCyPho9/Wxg=="],
+
+ "braces": ["braces@3.0.3", "", { "dependencies": { "fill-range": "^7.1.1" } }, "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA=="],
+
+ "browserslist": ["browserslist@4.28.8", "", { "dependencies": { "baseline-browser-mapping": "^2.11.12", "caniuse-lite": "^1.0.30001809", "electron-to-chromium": "^1.5.402", "node-releases": "^2.0.53", "update-browserslist-db": "^1.3.0" }, "bin": { "browserslist": "cli.js" } }, "sha512-V2NpofLblG64mfOtSgDhOJESZEGogzDMBv/q+W6oc4LXWP/q75eOXoOaaOu1EOadB9U4Bwx/e0yzbvwKH8zalA=="],
+
+ "bser": ["bser@2.1.1", "", { "dependencies": { "node-int64": "^0.4.0" } }, "sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ=="],
+
+ "buffer-from": ["buffer-from@1.1.2", "", {}, "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ=="],
+
+ "bytes": ["bytes@3.1.2", "", {}, "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg=="],
+
+ "camelcase": ["camelcase@6.3.0", "", {}, "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA=="],
+
+ "caniuse-lite": ["caniuse-lite@1.0.30001809", "", {}, "sha512-xxWVywk6a6Arlk+hymeycyn/VgqEfLDxupvhH/xiY5SJ/18kmi9o6MiO320DCUzypORHLtvh0I4i04tUhCNHNQ=="],
+
+ "chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="],
+
+ "chrome-launcher": ["chrome-launcher@0.15.2", "", { "dependencies": { "@types/node": "*", "escape-string-regexp": "^4.0.0", "is-wsl": "^2.2.0", "lighthouse-logger": "^1.0.0" }, "bin": { "print-chrome-path": "bin/print-chrome-path.js" } }, "sha512-zdLEwNo3aUVzIhKhTtXfxhdvZhUghrnmkvcAq2NoDd+LeOHKf03H5jwZ8T/STsAlzyALkBVK552iaG1fGf1xVQ=="],
+
+ "chromium-edge-launcher": ["chromium-edge-launcher@0.3.0", "", { "dependencies": { "@types/node": "*", "escape-string-regexp": "^4.0.0", "is-wsl": "^2.2.0", "lighthouse-logger": "^1.0.0", "mkdirp": "^1.0.4" } }, "sha512-p03azHlGjtyRvFEee3cyvtsRYdniSkwjkzmM/KmVnqT5d7QkkwpJBhis/zCLMYdQMVJ5tt140TBNqqrZPaWeFA=="],
+
+ "ci-info": ["ci-info@3.9.0", "", {}, "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ=="],
+
+ "cli-cursor": ["cli-cursor@2.1.0", "", { "dependencies": { "restore-cursor": "^2.0.0" } }, "sha512-8lgKz8LmCRYZZQDpRyT2m5rKJ08TnU4tR9FFFW2rxpxR1FzWi4PQ/NfyODchAatHaUgnSPVcx/R5w6NuTBzFiw=="],
+
+ "cli-spinners": ["cli-spinners@2.9.2", "", {}, "sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg=="],
+
+ "client-only": ["client-only@0.0.1", "", {}, "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA=="],
+
+ "cliui": ["cliui@8.0.1", "", { "dependencies": { "string-width": "^4.2.0", "strip-ansi": "^6.0.1", "wrap-ansi": "^7.0.0" } }, "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ=="],
+
+ "clone": ["clone@1.0.4", "", {}, "sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg=="],
+
+ "color": ["color@4.2.3", "", { "dependencies": { "color-convert": "^2.0.1", "color-string": "^1.9.0" } }, "sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A=="],
+
+ "color-convert": ["color-convert@2.0.1", "", { "dependencies": { "color-name": "~1.1.4" } }, "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ=="],
+
+ "color-name": ["color-name@1.1.4", "", {}, "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="],
+
+ "color-string": ["color-string@1.9.1", "", { "dependencies": { "color-name": "^1.0.0", "simple-swizzle": "^0.2.2" } }, "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg=="],
+
+ "commander": ["commander@12.1.0", "", {}, "sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA=="],
+
+ "compressible": ["compressible@2.0.18", "", { "dependencies": { "mime-db": ">= 1.43.0 < 2" } }, "sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg=="],
+
+ "compression": ["compression@1.8.1", "", { "dependencies": { "bytes": "3.1.2", "compressible": "~2.0.18", "debug": "2.6.9", "negotiator": "~0.6.4", "on-headers": "~1.1.0", "safe-buffer": "5.2.1", "vary": "~1.1.2" } }, "sha512-9mAqGPHLakhCLeNyxPkK4xVo746zQ/czLH1Ky+vkitMnWfWZps8r0qXuwhwizagCRttsL4lfG4pIOvaWLpAP0w=="],
+
+ "connect": ["connect@3.7.0", "", { "dependencies": { "debug": "2.6.9", "finalhandler": "1.1.2", "parseurl": "~1.3.3", "utils-merge": "1.0.1" } }, "sha512-ZqRXc+tZukToSNmh5C2iWMSoV3X1YUcPbqEM4DkEG5tNQXrQUZCNVGGv3IuicnkMtPfGf3Xtp8WCXs295iQ1pQ=="],
+
+ "convert-source-map": ["convert-source-map@2.0.0", "", {}, "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg=="],
+
+ "core-js-compat": ["core-js-compat@3.50.0", "", { "dependencies": { "browserslist": "^4.28.7" } }, "sha512-XGpFGbMLHwSt74YLTKho7Ib242qi6O8MSX+sRokV4oz7iKXvQWGYZthjIhjRGMxjzVkAubBO512dKGYcefmX3Q=="],
+
+ "cross-fetch": ["cross-fetch@3.2.0", "", { "dependencies": { "node-fetch": "^2.7.0" } }, "sha512-Q+xVJLoGOeIMXZmbUK4HYk+69cQH6LudR0Vu/pRm2YlU/hDV9CiS0gKUMaWY5f2NeUH9C1nV3bsTlCo0FsTV1Q=="],
+
+ "cross-spawn": ["cross-spawn@7.0.6", "", { "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", "which": "^2.0.1" } }, "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA=="],
+
+ "css-in-js-utils": ["css-in-js-utils@3.1.0", "", { "dependencies": { "hyphenate-style-name": "^1.0.3" } }, "sha512-fJAcud6B3rRu+KHYk+Bwf+WFL2MDCJJ1XG9x137tJQ0xYxor7XziQtuGFbWNdqrvF4Tk26O3H73nfVqXt/fW1A=="],
+
+ "css-select": ["css-select@5.2.2", "", { "dependencies": { "boolbase": "^1.0.0", "css-what": "^6.1.0", "domhandler": "^5.0.2", "domutils": "^3.0.1", "nth-check": "^2.0.1" } }, "sha512-TizTzUddG/xYLA3NXodFM0fSbNizXjOKhqiQQwvhlspadZokn1KDy0NZFS0wuEubIYAV5/c1/lAr0TaaFXEXzw=="],
+
+ "css-tree": ["css-tree@1.1.3", "", { "dependencies": { "mdn-data": "2.0.14", "source-map": "^0.6.1" } }, "sha512-tRpdppF7TRazZrjJ6v3stzv93qxRcSsFmW6cX0Zm2NVKpxE1WV1HblnghVv9TreireHkqI/VDEsfolRF1p6y7Q=="],
+
+ "css-what": ["css-what@6.2.2", "", {}, "sha512-u/O3vwbptzhMs3L1fQE82ZSLHQQfto5gyZzwteVIEyeaY5Fc7R4dapF/BvRoSYFeqfBk4m0V1Vafq5Pjv25wvA=="],
+
+ "css.escape": ["css.escape@1.5.1", "", {}, "sha512-YUifsXXuknHlUsmlgyY0PKzgPOr7/FjCePfHNt0jxm83wHZi44VDMQ7/fGNkjY3/jV1MC+1CmZbaHzugyeRtpg=="],
+
+ "csstype": ["csstype@3.2.3", "", {}, "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ=="],
+
+ "debug": ["debug@4.4.3", "", { "dependencies": { "ms": "^2.1.3" }, "peerDependencies": { "supports-color": "*" }, "optionalPeers": ["supports-color"] }, "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA=="],
+
+ "decode-uri-component": ["decode-uri-component@0.2.2", "", {}, "sha512-FqUYQ+8o158GyGTrMFJms9qh3CqTKvAqgqsTnkLI8sKu0028orqBhxNMFkFen0zGyg6epACD32pjVk58ngIErQ=="],
+
+ "deepmerge": ["deepmerge@4.3.1", "", {}, "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A=="],
+
+ "defaults": ["defaults@1.0.4", "", { "dependencies": { "clone": "^1.0.2" } }, "sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A=="],
+
+ "depd": ["depd@2.0.0", "", {}, "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw=="],
+
+ "dequal": ["dequal@2.0.3", "", {}, "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA=="],
+
+ "destroy": ["destroy@1.2.0", "", {}, "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg=="],
+
+ "detect-libc": ["detect-libc@2.1.2", "", {}, "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ=="],
+
+ "detect-node-es": ["detect-node-es@1.1.0", "", {}, "sha512-ypdmJU/TbBby2Dxibuv7ZLW3Bs1QEmM7nHjEANfohJLvE0XVujisn1qPJcZxg+qDucsr+bP6fLD1rPS3AhJ7EQ=="],
+
+ "dnssd-advertise": ["dnssd-advertise@1.1.6", "", {}, "sha512-Ndrrf6BMPalkQPd/zubL+4YghH2J9NspapQ09uDXwYbvOPkP0oaqf5CkcwJ0b50kS2O3ul6yVu+jz+RY62Cejg=="],
+
+ "dom-accessibility-api": ["dom-accessibility-api@0.6.3", "", {}, "sha512-7ZgogeTnjuHbo+ct10G9Ffp0mif17idi0IyWNVA/wcwcm7NPOD/WEHVP3n7n3MhXqxoIYm8d6MuZohYWIZ4T3w=="],
+
+ "dom-serializer": ["dom-serializer@2.0.0", "", { "dependencies": { "domelementtype": "^2.3.0", "domhandler": "^5.0.2", "entities": "^4.2.0" } }, "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg=="],
+
+ "domelementtype": ["domelementtype@2.3.0", "", {}, "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw=="],
+
+ "domhandler": ["domhandler@5.0.3", "", { "dependencies": { "domelementtype": "^2.3.0" } }, "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w=="],
+
+ "domutils": ["domutils@3.2.2", "", { "dependencies": { "dom-serializer": "^2.0.0", "domelementtype": "^2.3.0", "domhandler": "^5.0.3" } }, "sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw=="],
+
+ "ee-first": ["ee-first@1.1.1", "", {}, "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow=="],
+
+ "electron-to-chromium": ["electron-to-chromium@1.5.405", "", {}, "sha512-bNglH7lPH5l+yHOes7Zr4VqxhOy4BQ9ZBUX4VdoFgxMpzJk7W1ZoO3Vgd9Pxa9PyjQ76sfm2aKH/nzEcCNRlew=="],
+
+ "emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="],
+
+ "encodeurl": ["encodeurl@2.0.0", "", {}, "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg=="],
+
+ "entities": ["entities@4.5.0", "", {}, "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw=="],
+
+ "error-stack-parser": ["error-stack-parser@2.1.4", "", { "dependencies": { "stackframe": "^1.3.4" } }, "sha512-Sk5V6wVazPhq5MhpO+AUxJn5x7XSXGl1R93Vn7i+zS15KDVxQijejNCrz8340/2bgLBjR9GtEG8ZVKONDjcqGQ=="],
+
+ "es-errors": ["es-errors@1.3.0", "", {}, "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw=="],
+
+ "escalade": ["escalade@3.2.0", "", {}, "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA=="],
+
+ "escape-html": ["escape-html@1.0.3", "", {}, "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow=="],
+
+ "escape-string-regexp": ["escape-string-regexp@4.0.0", "", {}, "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA=="],
+
+ "etag": ["etag@1.8.1", "", {}, "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg=="],
+
+ "event-target-shim": ["event-target-shim@5.0.1", "", {}, "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ=="],
+
+ "expo": ["expo@57.0.12", "", { "dependencies": { "@babel/runtime": "^7.20.0", "@expo/cli": "^57.0.14", "@expo/config": "~57.0.7", "@expo/config-plugins": "~57.0.7", "@expo/devtools": "~57.0.1", "@expo/dom-webview": "~57.0.1", "@expo/fingerprint": "^0.20.7", "@expo/local-build-cache-provider": "^57.0.6", "@expo/log-box": "^57.0.2", "@expo/metro": "~56.0.0", "@expo/metro-config": "~57.0.8", "@ungap/structured-clone": "^1.3.0", "babel-preset-expo": "~57.0.6", "expo-asset": "~57.0.10", "expo-constants": "~57.0.10", "expo-file-system": "~57.0.2", "expo-font": "~57.0.1", "expo-keep-awake": "~57.0.1", "expo-modules-autolinking": "~57.0.9", "expo-modules-core": "~57.0.10", "pretty-format": "^29.7.0", "react-refresh": "^0.14.2", "whatwg-url-minimum": "^0.1.2" }, "peerDependencies": { "@expo/metro-runtime": "*", "react": "*", "react-dom": "*", "react-native": "*", "react-native-web": "*", "react-native-webview": "*" }, "optionalPeers": ["@expo/metro-runtime", "react-dom", "react-native-web", "react-native-webview"], "bin": { "expo": "bin/cli", "fingerprint": "bin/fingerprint", "expo-modules-autolinking": "bin/autolinking" } }, "sha512-sVgXaMjh5uapBvBkik3QibxbKI2g1zNtNeHntjRfixWAI3tlQZbaK4ACdInY4+jUBVymkf8u9BXJUaSes9jdtA=="],
+
+ "expo-asset": ["expo-asset@57.0.10", "", { "dependencies": { "@expo/image-utils": "^0.11.4", "expo-constants": "~57.0.10" }, "peerDependencies": { "expo": "*", "react": "*", "react-native": "*" } }, "sha512-32QpNkWlb8ftxq3ClAriwFXcZlpzuP7Qx4z3Gc9vhbAm1QZzGsCN+PwYt3fN8W46HBw5qaI6DSXcAyBlYzeVqA=="],
+
+ "expo-blur": ["expo-blur@57.0.2", "", { "peerDependencies": { "expo": "*", "react": "*", "react-native": "*" } }, "sha512-Aoud8H8lmlNkbRufyvRLefmGFELdBf1n5Te/Xm+Zx8ORINH+aXL+gKb5mbftFSha860+I7pMArz77TBYz8HDVg=="],
+
+ "expo-constants": ["expo-constants@57.0.10", "", { "dependencies": { "@expo/env": "~2.4.2" }, "peerDependencies": { "expo": "*", "react-native": "*" } }, "sha512-GCDXYEsloBfouMdT3BzoGhAkcLnYxEFNLQoSbNKIvIrD9FY5MmSeWuvRSveJdOiuydwQY2iH6hy020vTaQflCQ=="],
+
+ "expo-dev-client": ["expo-dev-client@57.0.11", "", { "dependencies": { "expo-dev-launcher": "~57.0.11", "expo-dev-menu": "~57.0.11", "expo-dev-menu-interface": "~57.0.0", "expo-manifests": "~57.0.1", "expo-updates-interface": "~57.0.1" }, "peerDependencies": { "expo": "*" } }, "sha512-IHatS97Vl0eQT8IG1Tsc10qDoyItxwjOw9AXLAbub+3uU7KljcqnXiCWRlhsI5KTjWV9/Dboc8psgiRb7oXXQw=="],
+
+ "expo-dev-launcher": ["expo-dev-launcher@57.0.11", "", { "dependencies": { "@expo/schema-utils": "^57.0.2", "expo-dev-menu": "~57.0.11", "expo-manifests": "~57.0.1" }, "peerDependencies": { "expo": "*", "react-native": "*" } }, "sha512-PpYoSmtMkvLYG9xVVHv8ZDMMsHR0D5ax9lFTgy+e6WT98NLUTwTexlObOkjCB80cfiGaKfmOZEKyXRiec3Lgag=="],
+
+ "expo-dev-menu": ["expo-dev-menu@57.0.11", "", { "dependencies": { "expo-dev-menu-interface": "~57.0.0" }, "peerDependencies": { "expo": "*", "react-native": "*" } }, "sha512-XY+rT7JALQAMBVYLLGfTwZ/E9igLDtUnyCPox1xxWaH6n7T3LJyxVb5unoORYhF4HzHQoxxeeHd6hg5P4AfyrQ=="],
+
+ "expo-dev-menu-interface": ["expo-dev-menu-interface@57.0.0", "", { "peerDependencies": { "expo": "*" } }, "sha512-F47VdzOHYc19FhI/jBgctpO8a5UskTIxG6a1E5t3W5gF8VImuvBQffdXXfLHhsuCl7dS3v3U0R45cleeVXO1Zg=="],
+
+ "expo-device": ["expo-device@57.0.1", "", { "dependencies": { "ua-parser-js": "^0.7.33" }, "peerDependencies": { "expo": "*" } }, "sha512-jyEMDUticH+dhcL3GHa2aiifOvGXJsmb3oVT2R2q4i8bN7Bddy61+NkpMmuS2VAZrvoLQwf0TJJ/1vi1ukvutA=="],
+
+ "expo-file-system": ["expo-file-system@57.0.2", "", { "peerDependencies": { "expo": "*", "react-native": "*" } }, "sha512-bPgzpaOJ3NWHZxV++Osj/1QoFzFe/QOo1jBF4EODJdiZgrrxyi2dv+7PLhKuut5QqPBuihUOITRh3s5jhRtA5A=="],
+
+ "expo-font": ["expo-font@57.0.1", "", { "dependencies": { "fontfaceobserver": "^2.1.0" }, "peerDependencies": { "expo": "*", "react": "*", "react-native": "*" } }, "sha512-QyS9L1Kh9sKJg4gfU6rdbpxpmH+DyzBX8z6jVvXMUDoqLr1GqmkO/Wu379KCXjL///kWbhpNlbi7AgBuj4VdIQ=="],
+
+ "expo-glass-effect": ["expo-glass-effect@57.0.1", "", { "peerDependencies": { "expo": "*", "react": "*", "react-native": "*" } }, "sha512-m/n8maxqNcHk6ZDhuqXBfD5Kt1Iz3M8xykVgdB0iSCIXvF70IqWXmQhX8Psswhrp8eZ+3r0mAD0Jh/2gFA3QaA=="],
+
+ "expo-haptics": ["expo-haptics@57.0.1", "", { "peerDependencies": { "expo": "*" } }, "sha512-8VhbnxlIrfXjP0syZr1JT197nafYicQu9119adOJnX62osU9Cw+PdDnAx/6LxuKJRzQdwxOMq7b7eWjhNL5zAQ=="],
+
+ "expo-image": ["expo-image@57.0.2", "", { "dependencies": { "sf-symbols-typescript": "^2.2.0" }, "peerDependencies": { "expo": "*", "react": "*", "react-native": "*", "react-native-web": "*" }, "optionalPeers": ["react-native-web"] }, "sha512-SAHDJiQ/Sf8JJ6NJ5/RbSewo8HtQtIGn4bDEgcvipwIw5lPURP0vXPzIOIrZ/ZroZ0abPgwTaWmkspoEO8Sxcw=="],
+
+ "expo-json-utils": ["expo-json-utils@57.0.1", "", {}, "sha512-cgTe1NqzQdYs/WN+3nIY5IZg8s0pb0xaTUbhYvxQDn137GbwRfHoGM2se3m3Vsl4Qu+B9G4RPEK5WJDEU2Do7g=="],
+
+ "expo-keep-awake": ["expo-keep-awake@57.0.1", "", { "peerDependencies": { "expo": "*", "react": "*" } }, "sha512-28lkFImeXTS+bhAjuCFV7w7tW5bXg27BJVrxv+nC/nyYa86qEa0oFeHwqol6ha5k4pdVDQgBF09GM4A1k76Ssg=="],
+
+ "expo-linear-gradient": ["expo-linear-gradient@57.0.1", "", { "peerDependencies": { "expo": "*", "react": "*", "react-native": "*" } }, "sha512-CpS8eMqoIWcHVGKV66zbDvzotCw9qYp3f8CuI9N+h1LaO0tMLUzBpkhAKePUsXlpN3yolYlHFSPkfVZ/uSh+iA=="],
+
+ "expo-linking": ["expo-linking@57.0.5", "", { "dependencies": { "expo-constants": "~57.0.9", "invariant": "^2.2.4" }, "peerDependencies": { "react": "*", "react-native": "*" } }, "sha512-SmJI3wr0EVfeKPGf+Qgr9gUbrXk8mM0ATqYLvAX/EAzawDjohPzMJ5pTt7TYMX0Wknj4XCtyCQrGhnERMXT6cQ=="],
+
+ "expo-local-authentication": ["expo-local-authentication@57.0.2", "", { "dependencies": { "invariant": "^2.2.4" }, "peerDependencies": { "expo": "*" } }, "sha512-8K4zcrQ5wZkRS1rwEWY8qHbeGVMNh35e9D1VTVKlMHz1O47itW+pW6iBVuqwGFLozN4fRBeEDQH8hu9Gt58YuQ=="],
+
+ "expo-manifests": ["expo-manifests@57.0.1", "", { "dependencies": { "expo-json-utils": "~57.0.1" }, "peerDependencies": { "expo": "*" } }, "sha512-qB/mDG2dYdl+EvUeQuqP8KFYCFgFCQjJYdWIHo8SFBgDzMYmdF286DFY2M1M9Okr99wkb5M4tgA3aCcwv3aEQA=="],
+
+ "expo-modules-autolinking": ["expo-modules-autolinking@57.0.9", "", { "dependencies": { "@expo/require-utils": "^57.0.4", "@expo/spawn-async": "^1.8.0", "chalk": "^4.1.0", "commander": "^7.2.0" }, "bin": { "expo-modules-autolinking": "bin/expo-modules-autolinking.js" } }, "sha512-lj2nsAKMMRLXSFnGgaaQrWJ2fdSpLPc/bca6Rkiw4g8zYPn7qX4MRUJgavvzm/hBrzvMnlhXVgJtidOGuwBh+w=="],
+
+ "expo-modules-core": ["expo-modules-core@57.0.10", "", { "dependencies": { "@expo/expo-modules-macros-plugin": "0.6.1", "expo-modules-jsi": "~57.0.4", "invariant": "^2.2.4" }, "peerDependencies": { "react": "*", "react-native": "*", "react-native-worklets": "^0.7.4 || ^0.8.0 || ^0.9.0 || ^0.10.0" }, "optionalPeers": ["react-native-worklets"] }, "sha512-aRi3G8OctoyZl8x9CLTVpbPljClfKm2eqKRgBzhcGsrH3gS1t5Y2ye7+PIZK4XK2VVP5iGqygN2b1vtqRo3xVQ=="],
+
+ "expo-modules-jsi": ["expo-modules-jsi@57.0.4", "", { "peerDependencies": { "react-native": "*" } }, "sha512-vt7FyqUqqFXiRVnBqYD7y+GSPTgeua5Ocoy0+SYt+RSHkZEA2Fyop7If3g1TYDzQObYybPRo7TG2Rle1XLaWFw=="],
+
+ "expo-router": ["expo-router@57.0.12", "", { "dependencies": { "@expo/log-box": "^57.0.2", "@expo/metro-runtime": "^57.0.9", "@expo/schema-utils": "^57.0.2", "@expo/ui": "^57.0.10", "@radix-ui/react-slot": "^1.2.0", "@radix-ui/react-tabs": "^1.1.12", "@react-native-masked-view/masked-view": "^0.3.2", "@testing-library/jest-dom": "^6.9.1", "@testing-library/user-event": "^14.6.1", "client-only": "^0.0.1", "color": "^4.2.3", "debug": "^4.3.4", "escape-string-regexp": "^4.0.0", "expo-glass-effect": "^57.0.1", "expo-server": "^57.0.2", "expo-symbols": "^57.0.2", "fast-deep-equal": "^3.1.3", "invariant": "^2.2.4", "nanoid": "^3.3.8", "query-string": "^7.1.3", "react-fast-compare": "^3.2.2", "react-is": "^19.1.0", "react-native-drawer-layout": "^4.2.2", "react-native-screens": "^4.26.0", "server-only": "^0.0.1", "sf-symbols-typescript": "^2.1.0", "shallowequal": "^1.1.0", "standard-navigation": "^0.0.5", "vaul": "^1.1.2" }, "peerDependencies": { "@testing-library/react-native": ">= 13.2.0", "expo": "*", "expo-constants": "^57.0.10", "expo-linking": "^57.0.5", "react": "*", "react-dom": "*", "react-native": "*", "react-native-gesture-handler": "*", "react-native-reanimated": "*", "react-native-safe-area-context": ">= 5.4.0", "react-native-web": "*", "react-server-dom-webpack": "~19.0.4 || ~19.1.5 || ~19.2.4" }, "optionalPeers": ["@testing-library/react-native", "react-dom", "react-native-gesture-handler", "react-native-reanimated", "react-native-web", "react-server-dom-webpack"] }, "sha512-vA+RUSzMwHmWa/pQpoYqJoTbhIQaX/OzvMvOlWVBeMflF1RC40zCzqLiXMKimWfEUh/G6ITnz31EtpNKUghxQw=="],
+
+ "expo-secure-store": ["expo-secure-store@57.0.1", "", { "peerDependencies": { "expo": "*" } }, "sha512-tLa1VmSadOq19mA/dwkl99RbHyjLE0T1qqBYMY3/OsguZTI+rlrDy/DDJjupqlVtmr95hD7o1pYqx5aL+B4YMA=="],
+
+ "expo-server": ["expo-server@57.0.2", "", {}, "sha512-GzfiSHC19xU7I0Dq4O/7DOtWdmc14vynpxBb9nWDRvsF+7RjoSIdkVePFhx4Qm6ILFNbo6KxFGu95QnDdKxUdw=="],
+
+ "expo-splash-screen": ["expo-splash-screen@57.0.6", "", { "dependencies": { "@expo/config-plugins": "~57.0.7", "@expo/image-utils": "^0.11.4", "xml2js": "0.6.0" }, "peerDependencies": { "expo": "*" } }, "sha512-FY0E7hMyXVAsNh18yGzIjdooPXdjafalEb6mk2EcqNPjXspHuu+pVEhUscEunw4wF8F/w6MOpT7UfOwHVWez9g=="],
+
+ "expo-status-bar": ["expo-status-bar@57.0.1", "", { "peerDependencies": { "expo": "*", "react": "*", "react-native": "*" } }, "sha512-Xwaq1gAoVRWx5dPG5VhT5RSbnI9OilhZnO5qoPBnUaBAa5VzRzfdS8q0/bsPt0jR2DKLtGuP0bQ6efMJ4RIMDg=="],
+
+ "expo-symbols": ["expo-symbols@57.0.2", "", { "dependencies": { "@expo-google-fonts/material-symbols": "^0.4.1", "sf-symbols-typescript": "^2.0.0" }, "peerDependencies": { "expo": "*", "expo-font": "*", "react": "*", "react-native": "*" } }, "sha512-qZ0iqOflm5lZGwRsQ5Y8sDksw3GAUKwHSX1bJBoocXf7gu14vafIXXYWte+JT9VfXAUGyKodJhLHP/GoOrcNWg=="],
+
+ "expo-system-ui": ["expo-system-ui@57.0.2", "", { "dependencies": { "@react-native/normalize-colors": "0.86.2", "debug": "^4.3.2" }, "peerDependencies": { "expo": "*", "react-native": "*", "react-native-web": "*" }, "optionalPeers": ["react-native-web"] }, "sha512-zABCRqFSioDBAo/RtmS0dQiGgDtDPZUVk01Y3Ti4ducobNM4HTM2sNAtq+YPpEUhaVW3hccPVsEUH4LK/ADVhA=="],
+
+ "expo-updates-interface": ["expo-updates-interface@57.0.1", "", { "peerDependencies": { "expo": "*" } }, "sha512-+LUWwJ0gf/TEKMVdQAw/Gjih4dvrk+URgy24X9qEGKuuMDZqjBRm9T4yQyBVALGL5TTdPUaB6ILxx3lshm3pwQ=="],
+
+ "expo-web-browser": ["expo-web-browser@57.0.2", "", { "peerDependencies": { "expo": "*", "react-native": "*" } }, "sha512-3vl5kvd7PB48ub6PpNIJUuPxO8xVa6D8RnIgNba6SXRwqFprOfeEZgwTgtm41kz0AAtvMOztUVNEUkwrHKjqMQ=="],
+
+ "exponential-backoff": ["exponential-backoff@3.1.3", "", {}, "sha512-ZgEeZXj30q+I0EN+CbSSpIyPaJ5HVQD18Z1m+u1FXbAeT94mr1zw50q4q6jiiC447Nl/YTcIYSAftiGqetwXCA=="],
+
+ "fast-deep-equal": ["fast-deep-equal@3.1.3", "", {}, "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="],
+
+ "fb-dotslash": ["fb-dotslash@0.5.8", "", { "bin": { "dotslash": "bin/dotslash" } }, "sha512-XHYLKk9J4BupDxi9bSEhkfss0m+Vr9ChTrjhf9l2iw3jB5C7BnY4GVPoMcqbrTutsKJso6yj2nAB6BI/F2oZaA=="],
+
+ "fb-watchman": ["fb-watchman@2.0.2", "", { "dependencies": { "bser": "2.1.1" } }, "sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA=="],
+
+ "fbjs": ["fbjs@3.0.5", "", { "dependencies": { "cross-fetch": "^3.1.5", "fbjs-css-vars": "^1.0.0", "loose-envify": "^1.0.0", "object-assign": "^4.1.0", "promise": "^7.1.1", "setimmediate": "^1.0.5", "ua-parser-js": "^1.0.35" } }, "sha512-ztsSx77JBtkuMrEypfhgc3cI0+0h+svqeie7xHbh1k/IKdcydnvadp/mUaGgjAOXQmQSxsqgaRhS3q9fy+1kxg=="],
+
+ "fbjs-css-vars": ["fbjs-css-vars@1.0.2", "", {}, "sha512-b2XGFAFdWZWg0phtAWLHCk836A1Xann+I+Dgd3Gk64MHKZO44FfoD1KxyvbSh0qZsIoXQGGlVztIY+oitJPpRQ=="],
+
+ "fdir": ["fdir@6.5.0", "", { "peerDependencies": { "picomatch": "^3 || ^4" }, "optionalPeers": ["picomatch"] }, "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg=="],
+
+ "fetch-nodeshim": ["fetch-nodeshim@0.4.10", "", {}, "sha512-m6I8ALe4L4XpdETy7MJZWs6L1IVMbjs99bwbpIKphxX+0CTns4IKDWJY0LWfr4YsFjfg+z1TjzTMU8lKl8rG0w=="],
+
+ "fill-range": ["fill-range@7.1.1", "", { "dependencies": { "to-regex-range": "^5.0.1" } }, "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg=="],
+
+ "filter-obj": ["filter-obj@1.1.0", "", {}, "sha512-8rXg1ZnX7xzy2NGDVkBVaAy+lSlPNwad13BtgSlLuxfIslyt5Vg64U7tFcCt4WS1R0hvtnQybT/IyCkGZ3DpXQ=="],
+
+ "finalhandler": ["finalhandler@1.1.2", "", { "dependencies": { "debug": "2.6.9", "encodeurl": "~1.0.2", "escape-html": "~1.0.3", "on-finished": "~2.3.0", "parseurl": "~1.3.3", "statuses": "~1.5.0", "unpipe": "~1.0.0" } }, "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA=="],
+
+ "flow-enums-runtime": ["flow-enums-runtime@0.0.6", "", {}, "sha512-3PYnM29RFXwvAN6Pc/scUfkI7RwhQ/xqyLUyPNlXUp9S40zI8nup9tUSrTLSVnWGBN38FNiGWbwZOB6uR4OGdw=="],
+
+ "fontfaceobserver": ["fontfaceobserver@2.3.0", "", {}, "sha512-6FPvD/IVyT4ZlNe7Wcn5Fb/4ChigpucKYSvD6a+0iMoLn2inpo711eyIcKjmDtE5XNcgAkSH9uN/nfAeZzHEfg=="],
+
+ "fresh": ["fresh@0.5.2", "", {}, "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q=="],
+
+ "function-bind": ["function-bind@1.1.2", "", {}, "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA=="],
+
+ "gensync": ["gensync@1.0.0-beta.2", "", {}, "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg=="],
+
+ "get-caller-file": ["get-caller-file@2.0.5", "", {}, "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg=="],
+
+ "get-nonce": ["get-nonce@1.0.1", "", {}, "sha512-FJhYRoDaiatfEkUK8HKlicmu/3SGFD51q3itKDGoSTysQJBnfOcxU5GxnhE1E6soB76MbT0MBtnKJuXyAx+96Q=="],
+
+ "getenv": ["getenv@2.0.0", "", {}, "sha512-VilgtJj/ALgGY77fiLam5iD336eSWi96Q15JSAG1zi8NRBysm3LXKdGnHb4m5cuyxvOLQQKWpBZAT6ni4FI2iQ=="],
+
+ "gifted-charts-core": ["gifted-charts-core@0.1.82", "", { "peerDependencies": { "react": "*", "react-native": "*", "react-native-svg": "*" } }, "sha512-2rwYFUj16Vod10Q0tBo5IZCfWqvIGBEWN/4XECnbbZrHmhkn+NpbaRHDg+ajyKgASUka/qT98eWQsVa8xZvPqA=="],
+
+ "glob": ["glob@13.0.6", "", { "dependencies": { "minimatch": "^10.2.2", "minipass": "^7.1.3", "path-scurry": "^2.0.2" } }, "sha512-Wjlyrolmm8uDpm/ogGyXZXb1Z+Ca2B8NbJwqBVg0axK9GbBeoS7yGV6vjXnYdGm6X53iehEuxxbyiKp8QmN4Vw=="],
+
+ "graceful-fs": ["graceful-fs@4.2.11", "", {}, "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ=="],
+
+ "has-flag": ["has-flag@4.0.0", "", {}, "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ=="],
+
+ "hasown": ["hasown@2.0.4", "", { "dependencies": { "function-bind": "^1.1.2" } }, "sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A=="],
+
+ "hermes-compiler": ["hermes-compiler@250829098.0.16", "", {}, "sha512-xsgzk+mUyvt9t1nUbF8USBlYxajTUtPJhVZ86q85s/SEoMKCF+52YZcudb0ENSnV3T3lV9mgB3s6R7+pH90zgw=="],
+
+ "hermes-estree": ["hermes-estree@0.36.1", "", {}, "sha512-guv1nQ6IJ7S83NRFPWc3SA7IBZrdNC9kapwOq6uXvF4wP+sDCgjzQbKPCoyYmoyZRzztF/n/c36l/rccCZSiCw=="],
+
+ "hermes-parser": ["hermes-parser@0.36.1", "", { "dependencies": { "hermes-estree": "0.36.1" } }, "sha512-GApNk4zLHi2UWoWZZkx7LNCOSzLSc5lB55pZ/PhK7ycFeg7u5LcF88p/WbpIi1XUDtE0MpHE3uRR3u3KB7TjSQ=="],
+
+ "hoist-non-react-statics": ["hoist-non-react-statics@3.3.2", "", { "dependencies": { "react-is": "^16.7.0" } }, "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw=="],
+
+ "hosted-git-info": ["hosted-git-info@7.0.2", "", { "dependencies": { "lru-cache": "^10.0.1" } }, "sha512-puUZAUKT5m8Zzvs72XWy3HtvVbTWljRE66cP60bxJzAqf2DgICo7lYTY2IHUmLnNpjYvw5bvmoHvPc0QO2a62w=="],
+
+ "http-errors": ["http-errors@2.0.1", "", { "dependencies": { "depd": "~2.0.0", "inherits": "~2.0.4", "setprototypeof": "~1.2.0", "statuses": "~2.0.2", "toidentifier": "~1.0.1" } }, "sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ=="],
+
+ "https-proxy-agent": ["https-proxy-agent@7.0.6", "", { "dependencies": { "agent-base": "^7.1.2", "debug": "4" } }, "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw=="],
+
+ "hyphenate-style-name": ["hyphenate-style-name@1.1.0", "", {}, "sha512-WDC/ui2VVRrz3jOVi+XtjqkDjiVjTtFaAGiW37k6b+ohyQ5wYDOGkvCZa8+H0nx3gyvv0+BST9xuOgIyGQ00gw=="],
+
+ "ignore": ["ignore@5.3.2", "", {}, "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g=="],
+
+ "image-size": ["image-size@1.2.1", "", { "dependencies": { "queue": "6.0.2" }, "bin": { "image-size": "bin/image-size.js" } }, "sha512-rH+46sQJ2dlwfjfhCyNx5thzrv+dtmBIhPHk0zgRUukHzZ/kRueTJXoYYsclBaKcSMBWuGbOFXtioLpzTb5euw=="],
+
+ "indent-string": ["indent-string@4.0.0", "", {}, "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg=="],
+
+ "inherits": ["inherits@2.0.4", "", {}, "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="],
+
+ "inline-style-prefixer": ["inline-style-prefixer@7.0.1", "", { "dependencies": { "css-in-js-utils": "^3.1.0" } }, "sha512-lhYo5qNTQp3EvSSp3sRvXMbVQTLrvGV6DycRMJ5dm2BLMiJ30wpXKdDdgX+GmJZ5uQMucwRKHamXSst3Sj/Giw=="],
+
+ "invariant": ["invariant@2.2.4", "", { "dependencies": { "loose-envify": "^1.0.0" } }, "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA=="],
+
+ "is-arrayish": ["is-arrayish@0.3.4", "", {}, "sha512-m6UrgzFVUYawGBh1dUsWR5M2Clqic9RVXC/9f8ceNlv2IcO9j9J/z8UoCLPqtsPBFNzEpfR3xftohbfqDx8EQA=="],
+
+ "is-core-module": ["is-core-module@2.16.2", "", { "dependencies": { "hasown": "^2.0.3" } }, "sha512-evOr8xfXKxE6qSR0hSXL2r3sd7ALj8+7jQEUvPYcm5sgZFdJ+AYzT6yNmJenvIYQBgIGwfwz08sL8zoL7yq2BA=="],
+
+ "is-docker": ["is-docker@2.2.1", "", { "bin": { "is-docker": "cli.js" } }, "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ=="],
+
+ "is-fullwidth-code-point": ["is-fullwidth-code-point@3.0.0", "", {}, "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg=="],
+
+ "is-number": ["is-number@7.0.0", "", {}, "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng=="],
+
+ "is-wsl": ["is-wsl@2.2.0", "", { "dependencies": { "is-docker": "^2.0.0" } }, "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww=="],
+
+ "isexe": ["isexe@2.0.0", "", {}, "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="],
+
+ "jest-get-type": ["jest-get-type@29.6.3", "", {}, "sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw=="],
+
+ "jest-util": ["jest-util@29.7.0", "", { "dependencies": { "@jest/types": "^29.6.3", "@types/node": "*", "chalk": "^4.0.0", "ci-info": "^3.2.0", "graceful-fs": "^4.2.9", "picomatch": "^2.2.3" } }, "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA=="],
+
+ "jest-validate": ["jest-validate@29.7.0", "", { "dependencies": { "@jest/types": "^29.6.3", "camelcase": "^6.2.0", "chalk": "^4.0.0", "jest-get-type": "^29.6.3", "leven": "^3.1.0", "pretty-format": "^29.7.0" } }, "sha512-ZB7wHqaRGVw/9hST/OuFUReG7M8vKeq0/J2egIGLdvjHCmYqGARhzXmtgi+gVeZ5uXFF219aOc3Ls2yLg27tkw=="],
+
+ "jest-worker": ["jest-worker@29.7.0", "", { "dependencies": { "@types/node": "*", "jest-util": "^29.7.0", "merge-stream": "^2.0.0", "supports-color": "^8.0.0" } }, "sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw=="],
+
+ "jimp-compact": ["jimp-compact@0.16.1", "", {}, "sha512-dZ6Ra7u1G8c4Letq/B5EzAxj4tLFHL+cGtdpR+PVm4yzPDj+lCk+AbivWt1eOM+ikzkowtyV7qSqX6qr3t71Ww=="],
+
+ "js-tokens": ["js-tokens@4.0.0", "", {}, "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ=="],
+
+ "js-yaml": ["js-yaml@4.3.1", "", { "dependencies": { "argparse": "^2.0.1" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "sha512-CY6crGq313MX8GkwvB7tzgp99vjQxY1++5y10/BKN/GUfHqWaOGQMNZkBvqSzsZKWk/ijwHlWzzkLulsGHhjWQ=="],
+
+ "jsc-safe-url": ["jsc-safe-url@0.2.4", "", {}, "sha512-0wM3YBWtYePOjfyXQH5MWQ8H7sdk5EXSwZvmSLKk2RboVQ2Bu239jycHDz5J/8Blf3K0Qnoy2b6xD+z10MFB+Q=="],
+
+ "jsesc": ["jsesc@3.1.0", "", { "bin": { "jsesc": "bin/jsesc" } }, "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA=="],
+
+ "json5": ["json5@2.2.3", "", { "bin": { "json5": "lib/cli.js" } }, "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg=="],
+
+ "kleur": ["kleur@3.0.3", "", {}, "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w=="],
+
+ "lan-network": ["lan-network@0.2.1", "", { "bin": { "lan-network": "dist/lan-network-cli.js" } }, "sha512-ONPnazC96VKDntab9j9JKwIWhZ4ZUceB4A9Epu4Ssg0hYFmtHZSeQ+n15nIwTFmcBUKtExOer8WTJ4GF9MO64A=="],
+
+ "leven": ["leven@3.1.0", "", {}, "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A=="],
+
+ "lighthouse-logger": ["lighthouse-logger@1.4.2", "", { "dependencies": { "debug": "^2.6.9", "marky": "^1.2.2" } }, "sha512-gPWxznF6TKmUHrOQjlVo2UbaL2EJ71mb2CCeRs/2qBpi4L/g4LUVc9+3lKQ6DTUZwJswfM7ainGrLO1+fOqa2g=="],
+
+ "lightningcss": ["lightningcss@1.33.0", "", { "dependencies": { "detect-libc": "^2.0.3" }, "optionalDependencies": { "lightningcss-android-arm64": "1.33.0", "lightningcss-darwin-arm64": "1.33.0", "lightningcss-darwin-x64": "1.33.0", "lightningcss-freebsd-x64": "1.33.0", "lightningcss-linux-arm-gnueabihf": "1.33.0", "lightningcss-linux-arm64-gnu": "1.33.0", "lightningcss-linux-arm64-musl": "1.33.0", "lightningcss-linux-x64-gnu": "1.33.0", "lightningcss-linux-x64-musl": "1.33.0", "lightningcss-win32-arm64-msvc": "1.33.0", "lightningcss-win32-x64-msvc": "1.33.0" } }, "sha512-WkUDrojuJs0xkgGf2udWxa3yGBRxPtxUkB79i6aCZLRgc7PM8fZe9TosfPDcvEpQZbuFASnHYmRLBLUbmLOIIA=="],
+
+ "lightningcss-android-arm64": ["lightningcss-android-arm64@1.33.0", "", { "os": "android", "cpu": "arm64" }, "sha512-gEpRTalKdosp4Bb8qWtc2iOgE5SeIHlpS1up9bFq2wAyYhl1UdTObYiHe98zEM9SQvSoqQZ1IQD0JNpg3Ml5pg=="],
+
+ "lightningcss-darwin-arm64": ["lightningcss-darwin-arm64@1.33.0", "", { "os": "darwin", "cpu": "arm64" }, "sha512-Sciaz8eenNTKn9b3t7+xr0ipTp9YxKQY4npwQ3mrRuL0BAVHBLyZxofhaKBAVtzmtRZ/zTyo0/to4B1uWG/Djg=="],
+
+ "lightningcss-darwin-x64": ["lightningcss-darwin-x64@1.33.0", "", { "os": "darwin", "cpu": "x64" }, "sha512-Z5UPAxzrjlWNNyGy6i65cJzzvgJ5D3T6wMvs+gWpY9d7qRhANrxqAp6LhxIgZhWEw18RfJTGcRxjuLIBr+m8XQ=="],
+
+ "lightningcss-freebsd-x64": ["lightningcss-freebsd-x64@1.33.0", "", { "os": "freebsd", "cpu": "x64" }, "sha512-QQM/Ti/hQajJwCY+RiWuCZ9sdtI/XQk7nDK5vC8kkdwixezOlDgvDx7+RT+QjK6FcFT4MpsuoBnHIo/O3StRRg=="],
+
+ "lightningcss-linux-arm-gnueabihf": ["lightningcss-linux-arm-gnueabihf@1.33.0", "", { "os": "linux", "cpu": "arm" }, "sha512-N7FVBe6iS24MlM6R/4RBTxGhQheZGs7tiQ9U32UtF75NzP5Q7xWPRqLBCKxlRQRk3rY1jCIPLzx7WzOhuUIRLQ=="],
+
+ "lightningcss-linux-arm64-gnu": ["lightningcss-linux-arm64-gnu@1.33.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-j2v/itmy4HlNxlc6voKXYgBqNi0Ng2LShg4z7GufpEgs05P+2suBVyi9I6YHq5uoVFx9ETin3eCEhLVyXGQnKg=="],
+
+ "lightningcss-linux-arm64-musl": ["lightningcss-linux-arm64-musl@1.33.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-yiO5ROMuYQgXbC60yjZU5CYSFZGKXL0HFATXt9mHJn1+zW55oCtMI9NfcVhYLMFDL7gV7oBPon/EmMMGg2OvtQ=="],
+
+ "lightningcss-linux-x64-gnu": ["lightningcss-linux-x64-gnu@1.33.0", "", { "os": "linux", "cpu": "x64" }, "sha512-ar+Ju7LmcN0Jo4FpL4hpFybwNG9/3A/Br5KW2n2jyODg3MEZXaDYADdemoNS+BDNfMgKvylJLj4S5tyRActuAg=="],
+
+ "lightningcss-linux-x64-musl": ["lightningcss-linux-x64-musl@1.33.0", "", { "os": "linux", "cpu": "x64" }, "sha512-RYiYbkokw0trfKqqzfF55lginwEPrD3OJDfTuJzFs1MK6iFnDenaz1fqLLtX4ITG3OktJQXOeTaw1awrBAlZPw=="],
+
+ "lightningcss-win32-arm64-msvc": ["lightningcss-win32-arm64-msvc@1.33.0", "", { "os": "win32", "cpu": "arm64" }, "sha512-1K+MPfLSFVpphzpdbfkhlWk6wBrTObBzS2T6db10PNOZgR9GoVsAWzwNyuhUYYbTp23j+4RrncfujZ4uAzXvwA=="],
+
+ "lightningcss-win32-x64-msvc": ["lightningcss-win32-x64-msvc@1.33.0", "", { "os": "win32", "cpu": "x64" }, "sha512-OlEICDx/Xl0FqSp4bry8zFnCvGpig3Gl4gCquvYwHuqJKEC1+n9NgDniFvqHGmMv1ZkqDJrDqKKSykTDX+ehuA=="],
+
+ "lodash.debounce": ["lodash.debounce@4.0.8", "", {}, "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow=="],
+
+ "lodash.throttle": ["lodash.throttle@4.1.1", "", {}, "sha512-wIkUCfVKpVsWo3JSZlc+8MB5it+2AN5W8J7YVMST30UrvcQNZ1Okbj+rbVniijTWE6FGYy4XJq/rHkas8qJMLQ=="],
+
+ "log-symbols": ["log-symbols@2.2.0", "", { "dependencies": { "chalk": "^2.0.1" } }, "sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg=="],
+
+ "loose-envify": ["loose-envify@1.4.0", "", { "dependencies": { "js-tokens": "^3.0.0 || ^4.0.0" }, "bin": { "loose-envify": "cli.js" } }, "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q=="],
+
+ "lru-cache": ["lru-cache@5.1.1", "", { "dependencies": { "yallist": "^3.0.2" } }, "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w=="],
+
+ "lz-string": ["lz-string@1.5.0", "", { "bin": { "lz-string": "bin/bin.js" } }, "sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ=="],
+
+ "makeerror": ["makeerror@1.0.12", "", { "dependencies": { "tmpl": "1.0.5" } }, "sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg=="],
+
+ "marky": ["marky@1.3.0", "", {}, "sha512-ocnPZQLNpvbedwTy9kNrQEsknEfgvcLMvOtz3sFeWApDq1MXH1TqkCIx58xlpESsfwQOnuBO9beyQuNGzVvuhQ=="],
+
+ "mdn-data": ["mdn-data@2.0.14", "", {}, "sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow=="],
+
+ "memoize-one": ["memoize-one@5.2.1", "", {}, "sha512-zYiwtZUcYyXKo/np96AGZAckk+FWWsUdJ3cHGGmld7+AhvcWmQyGCYUh1hc4Q/pkOhb65dQR/pqCyK0cOaHz4Q=="],
+
+ "merge-stream": ["merge-stream@2.0.0", "", {}, "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w=="],
+
+ "metro": ["metro@0.84.4", "", { "dependencies": { "@babel/code-frame": "^7.29.0", "@babel/core": "^7.25.2", "@babel/generator": "^7.29.1", "@babel/parser": "^7.29.0", "@babel/template": "^7.28.6", "@babel/traverse": "^7.29.0", "@babel/types": "^7.29.0", "accepts": "^2.0.0", "ci-info": "^2.0.0", "connect": "^3.6.5", "debug": "^4.4.0", "error-stack-parser": "^2.0.6", "flow-enums-runtime": "^0.0.6", "graceful-fs": "^4.2.4", "hermes-parser": "0.35.0", "image-size": "^1.0.2", "invariant": "^2.2.4", "jest-worker": "^29.7.0", "jsc-safe-url": "^0.2.2", "lodash.throttle": "^4.1.1", "metro-babel-transformer": "0.84.4", "metro-cache": "0.84.4", "metro-cache-key": "0.84.4", "metro-config": "0.84.4", "metro-core": "0.84.4", "metro-file-map": "0.84.4", "metro-resolver": "0.84.4", "metro-runtime": "0.84.4", "metro-source-map": "0.84.4", "metro-symbolicate": "0.84.4", "metro-transform-plugins": "0.84.4", "metro-transform-worker": "0.84.4", "mime-types": "^3.0.1", "nullthrows": "^1.1.1", "serialize-error": "^2.1.0", "source-map": "^0.5.6", "throat": "^5.0.0", "ws": "^7.5.10", "yargs": "^17.6.2" }, "bin": { "metro": "src/cli.js" } }, "sha512-8ETTubqfD6ornDy2zYDvRcKnVDOXdFJsjetYDBsY4oAsb6NJkiwFR+FaMESyGppFmQUyBQA4H4sFGxzcQSGtFA=="],
+
+ "metro-babel-transformer": ["metro-babel-transformer@0.84.4", "", { "dependencies": { "@babel/core": "^7.25.2", "flow-enums-runtime": "^0.0.6", "hermes-parser": "0.35.0", "metro-cache-key": "0.84.4", "nullthrows": "^1.1.1" } }, "sha512-rvCfz8snl9h20VcvpOHxZuHP1SlAkv4HXbzw7nyyVwu6Eqo5PRerbakQ9XmUCOsRy70spJ37O+G1TK8oMzo48g=="],
+
+ "metro-cache": ["metro-cache@0.84.4", "", { "dependencies": { "exponential-backoff": "^3.1.1", "flow-enums-runtime": "^0.0.6", "https-proxy-agent": "^7.0.5", "metro-core": "0.84.4" } }, "sha512-gpcFQdSLUwUCk71saKoE64jLFbx2nwTfVCcPSULMNT8QYq0p1eZZE29Jvd0HtT/UlhC3ZOutLxJME5xqD2JUZg=="],
+
+ "metro-cache-key": ["metro-cache-key@0.84.4", "", { "dependencies": { "flow-enums-runtime": "^0.0.6" } }, "sha512-wVO79aGrkYImpnaVS4+d5RrRBRPX31QtvKB3wKGBuiNSznduZTQHzsrJZRroFJSwnygrzdsGUtDQPuqqFjFdvw=="],
+
+ "metro-config": ["metro-config@0.84.4", "", { "dependencies": { "connect": "^3.6.5", "flow-enums-runtime": "^0.0.6", "jest-validate": "^29.7.0", "metro": "0.84.4", "metro-cache": "0.84.4", "metro-core": "0.84.4", "metro-runtime": "0.84.4", "yaml": "^2.6.1" } }, "sha512-PMotGDjXcXLWo2TMRH+VR99phFNgYTwqh4OoieIKK3yTJa1Jmkl+fZJxDO0jfBvNF+WESHciHvpNuBtXaF3B0Q=="],
+
+ "metro-core": ["metro-core@0.84.4", "", { "dependencies": { "flow-enums-runtime": "^0.0.6", "lodash.throttle": "^4.1.1", "metro-resolver": "0.84.4" } }, "sha512-HONpWC5LGXZn3ffkd4Hu6AIrfE7j4Z0g0wMo/goV24WOB3lhuFZ40KgvaDiSw8iyQHloMYay5N/wPX+z8oN/PQ=="],
+
+ "metro-file-map": ["metro-file-map@0.84.4", "", { "dependencies": { "debug": "^4.4.0", "fb-watchman": "^2.0.0", "flow-enums-runtime": "^0.0.6", "graceful-fs": "^4.2.4", "invariant": "^2.2.4", "jest-worker": "^29.7.0", "micromatch": "^4.0.4", "nullthrows": "^1.1.1", "walker": "^1.0.7" } }, "sha512-KSVDi/u60hKPx++NLu3MTIvyjzNoJnFAF8PQFxaj1jiSka/wjw+Ua6sNuJ0TDHQv+7AAoFQxeMgaRAe8Yic5wQ=="],
+
+ "metro-minify-terser": ["metro-minify-terser@0.84.4", "", { "dependencies": { "flow-enums-runtime": "^0.0.6", "terser": "^5.15.0" } }, "sha512-5qpbaVOMC7CPitIpuewzVeGw7E+C3ykbv2mqTjQLl85Z3annSVGlSCTcsZjqXZzjupfK4Ztj3dDc4kc44NZwtQ=="],
+
+ "metro-resolver": ["metro-resolver@0.84.4", "", { "dependencies": { "flow-enums-runtime": "^0.0.6" } }, "sha512-1qLgbxQ5ZGhhutuPot1Yp348ofDsATL2WkrHF65TobqTT9K3P9qJXw38bomk7ncp5B7OYMfWwtyBZo1lCV792A=="],
+
+ "metro-runtime": ["metro-runtime@0.84.4", "", { "dependencies": { "@babel/runtime": "^7.25.0", "flow-enums-runtime": "^0.0.6" } }, "sha512-Jibypds4g7AhzdRKY+kDoj51s5EXMwgyp5ddtlreDAsWefMdOx+agWqgm0H2XSZ/ueanHHVM89fnf5OJnlxa8Q=="],
+
+ "metro-source-map": ["metro-source-map@0.84.4", "", { "dependencies": { "@babel/traverse": "^7.29.0", "@babel/types": "^7.29.0", "flow-enums-runtime": "^0.0.6", "invariant": "^2.2.4", "metro-symbolicate": "0.84.4", "nullthrows": "^1.1.1", "ob1": "0.84.4", "source-map": "^0.5.6", "vlq": "^1.0.0" } }, "sha512-jbWkPxIesVuo1IWkvezmMJld6iu8nD62GsrZiV6jP37AOdbo4OBq1FJ+qkOg8sV05wAHB//jAbziuW0SlJfW4g=="],
+
+ "metro-symbolicate": ["metro-symbolicate@0.84.4", "", { "dependencies": { "flow-enums-runtime": "^0.0.6", "invariant": "^2.2.4", "metro-source-map": "0.84.4", "nullthrows": "^1.1.1", "source-map": "^0.5.6", "vlq": "^1.0.0" }, "bin": { "metro-symbolicate": "src/index.js" } }, "sha512-OnfpacxUqGPZQ27t8qK9mFa7uqHIlVWeqRqkCbvMvreEBiamEeOn8krKtcwgP5M4cYDPwuSmCTopHMVthqG4zA=="],
+
+ "metro-transform-plugins": ["metro-transform-plugins@0.84.4", "", { "dependencies": { "@babel/core": "^7.25.2", "@babel/generator": "^7.29.1", "@babel/template": "^7.28.6", "@babel/traverse": "^7.29.0", "flow-enums-runtime": "^0.0.6", "nullthrows": "^1.1.1" } }, "sha512-kehr6HbAecqD0/a3xLXobELdPaAmRAl8bel0qagPF4vhZtux93nS8S4eq2kgKt6J2GnQpVjSoW1PXdst04mwow=="],
+
+ "metro-transform-worker": ["metro-transform-worker@0.84.4", "", { "dependencies": { "@babel/core": "^7.25.2", "@babel/generator": "^7.29.1", "@babel/parser": "^7.29.0", "@babel/types": "^7.29.0", "flow-enums-runtime": "^0.0.6", "metro": "0.84.4", "metro-babel-transformer": "0.84.4", "metro-cache": "0.84.4", "metro-cache-key": "0.84.4", "metro-minify-terser": "0.84.4", "metro-source-map": "0.84.4", "metro-transform-plugins": "0.84.4", "nullthrows": "^1.1.1" } }, "sha512-W1IYMvvXTu4MxYr7d9h7CeG2vpIr3bmLLIavkPY4O1ilzDrvS8z/NEe6y+pC44Ff7raMXQgYSfdqDUwN/i39gg=="],
+
+ "micromatch": ["micromatch@4.0.8", "", { "dependencies": { "braces": "^3.0.3", "picomatch": "^2.3.1" } }, "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA=="],
+
+ "mime": ["mime@1.6.0", "", { "bin": { "mime": "cli.js" } }, "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg=="],
+
+ "mime-db": ["mime-db@1.52.0", "", {}, "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg=="],
+
+ "mime-types": ["mime-types@2.1.35", "", { "dependencies": { "mime-db": "1.52.0" } }, "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw=="],
+
+ "mimic-fn": ["mimic-fn@1.2.0", "", {}, "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ=="],
+
+ "min-indent": ["min-indent@1.0.1", "", {}, "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg=="],
+
+ "minimatch": ["minimatch@10.2.6", "", { "dependencies": { "brace-expansion": "^5.0.8" } }, "sha512-vpLQEs+VLCr1nU0BXS07maYoFwlDAH0gngQuuttxIwutDFEMHq2blX+8vpgxDdK3J1PwjCJiep77OitTZ4Ll1A=="],
+
+ "minipass": ["minipass@7.1.3", "", {}, "sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A=="],
+
+ "mkdirp": ["mkdirp@1.0.4", "", { "bin": { "mkdirp": "bin/cmd.js" } }, "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw=="],
+
+ "ms": ["ms@2.1.3", "", {}, "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="],
+
+ "multitars": ["multitars@1.0.2", "", {}, "sha512-6GwVw5eLi9sThdtlS4PKwC7yRLaf45pYhIEzKBHdKxi+YOXGKFX8acIniH+Uh/+k9mS2lQOupTccjoe5r0/1IQ=="],
+
+ "nanoid": ["nanoid@3.3.18", "", { "bin": { "nanoid": "bin/nanoid.cjs" } }, "sha512-DTg4MJbGMWkfi6VZFdNt2/caMbQy4Ou+Op/hJQvGEWcnVfoA1QA+xzRKAzw9jD6+GVOOeYr/mIcuDSdug6F6+w=="],
+
+ "negotiator": ["negotiator@0.6.3", "", {}, "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg=="],
+
+ "node-fetch": ["node-fetch@2.7.0", "", { "dependencies": { "whatwg-url": "^5.0.0" }, "peerDependencies": { "encoding": "^0.1.0" }, "optionalPeers": ["encoding"] }, "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A=="],
+
+ "node-forge": ["node-forge@1.4.0", "", {}, "sha512-LarFH0+6VfriEhqMMcLX2F7SwSXeWwnEAJEsYm5QKWchiVYVvJyV9v7UDvUv+w5HO23ZpQTXDv/GxdDdMyOuoQ=="],
+
+ "node-int64": ["node-int64@0.4.0", "", {}, "sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw=="],
+
+ "node-releases": ["node-releases@2.0.53", "", {}, "sha512-D9UOmYG3UH1V+ENW56t5QXBwJw1YEY18ruVeus89Rw+SyIgjPkCO84bRzO3uNIYosJbNwiabWVn48o3uJLjxFQ=="],
+
+ "npm-package-arg": ["npm-package-arg@11.0.3", "", { "dependencies": { "hosted-git-info": "^7.0.0", "proc-log": "^4.0.0", "semver": "^7.3.5", "validate-npm-package-name": "^5.0.0" } }, "sha512-sHGJy8sOC1YraBywpzQlIKBE4pBbGbiF95U6Auspzyem956E0+FtDtsx1ZxlOJkQCZ1AFXAY/yuvtFYrOxF+Bw=="],
+
+ "nth-check": ["nth-check@2.1.1", "", { "dependencies": { "boolbase": "^1.0.0" } }, "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w=="],
+
+ "nullthrows": ["nullthrows@1.1.1", "", {}, "sha512-2vPPEi+Z7WqML2jZYddDIfy5Dqb0r2fze2zTxNNknZaFpVHU3mFB3R+DWeJWGVx0ecvttSGlJTI+WG+8Z4cDWw=="],
+
+ "ob1": ["ob1@0.84.4", "", { "dependencies": { "flow-enums-runtime": "^0.0.6" } }, "sha512-eJXMpz4aQHXF/YBB9ddqZDIS+ooO91hObo9FoW/xBkr54/zCwYYCDqT/O54vNo8kOkWs5Ou/y28NgdrV0edQNA=="],
+
+ "object-assign": ["object-assign@4.1.1", "", {}, "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg=="],
+
+ "on-finished": ["on-finished@2.4.1", "", { "dependencies": { "ee-first": "1.1.1" } }, "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg=="],
+
+ "on-headers": ["on-headers@1.1.0", "", {}, "sha512-737ZY3yNnXy37FHkQxPzt4UZ2UWPWiCZWLvFZ4fu5cueciegX0zGPnrlY6bwRg4FdQOe9YU8MkmJwGhoMybl8A=="],
+
+ "onetime": ["onetime@2.0.1", "", { "dependencies": { "mimic-fn": "^1.0.0" } }, "sha512-oyyPpiMaKARvvcgip+JV+7zci5L8D1W9RZIz2l1o08AM3pfspitVWnPt3mzHcBPp12oYMTy0pqrFs/C+m3EwsQ=="],
+
+ "open": ["open@7.4.2", "", { "dependencies": { "is-docker": "^2.0.0", "is-wsl": "^2.1.1" } }, "sha512-MVHddDVweXZF3awtlAS+6pgKLlm/JgxZ90+/NBurBoQctVOOB/zDdVjcyPzQ+0laDGbsWgrRkflI65sQeOgT9Q=="],
+
+ "ora": ["ora@3.4.0", "", { "dependencies": { "chalk": "^2.4.2", "cli-cursor": "^2.1.0", "cli-spinners": "^2.0.0", "log-symbols": "^2.2.0", "strip-ansi": "^5.2.0", "wcwidth": "^1.0.1" } }, "sha512-eNwHudNbO1folBP3JsZ19v9azXWtQZjICdr3Q0TDPIaeBQ3mXLrh54wM+er0+hSp+dWKf+Z8KM58CYzEyIYxYg=="],
+
+ "parse-png": ["parse-png@2.1.0", "", { "dependencies": { "pngjs": "^3.3.0" } }, "sha512-Nt/a5SfCLiTnQAjx3fHlqp8hRgTL3z7kTQZzvIMS9uCAepnCyjpdEc6M/sz69WqMBdaDBw9sF1F1UaHROYzGkQ=="],
+
+ "parseurl": ["parseurl@1.3.3", "", {}, "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ=="],
+
+ "path-key": ["path-key@3.1.1", "", {}, "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q=="],
+
+ "path-parse": ["path-parse@1.0.7", "", {}, "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw=="],
+
+ "path-scurry": ["path-scurry@2.0.2", "", { "dependencies": { "lru-cache": "^11.0.0", "minipass": "^7.1.2" } }, "sha512-3O/iVVsJAPsOnpwWIeD+d6z/7PmqApyQePUtCndjatj/9I5LylHvt5qluFaBT3I5h3r1ejfR056c+FCv+NnNXg=="],
+
+ "picocolors": ["picocolors@1.1.1", "", {}, "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA=="],
+
+ "picomatch": ["picomatch@4.0.5", "", {}, "sha512-RvwwcruNjI1ncT5xRakeyS9Lf8lcItv34KD+aif+VH9kduAyfYBipGh12274xtenIPZ119/R9BdTBa8gAwSh0A=="],
+
+ "plist": ["plist@3.1.1", "", { "dependencies": { "@xmldom/xmldom": "^0.9.10", "base64-js": "^1.5.1", "xmlbuilder": "^15.1.1" } }, "sha512-ZIfcLJC+7E7FBFnDxm9MPmt7D+DidyQ26lewieO75AdhA2ayMtsJSES0iWzqJQbcVRSrTufQoy0DR94xHue0oA=="],
+
+ "pngjs": ["pngjs@3.4.0", "", {}, "sha512-NCrCHhWmnQklfH4MtJMRjZ2a8c80qXeMlQMv2uVp9ISJMTt562SbGd6n2oq0PaPgKm7Z6pL9E2UlLIhC+SHL3w=="],
+
+ "postcss": ["postcss@8.5.26", "", { "dependencies": { "nanoid": "^3.3.17", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-u82N74LFzG8ca+dD8puPnplTXoGH4fTPpVGuIbt36G3qvNlkvfD0lEAZSxaly3KX8TS/L1A1gsCEmvKmBcVbkQ=="],
+
+ "postcss-value-parser": ["postcss-value-parser@4.2.0", "", {}, "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ=="],
+
+ "pretty-format": ["pretty-format@29.7.0", "", { "dependencies": { "@jest/schemas": "^29.6.3", "ansi-styles": "^5.0.0", "react-is": "^18.0.0" } }, "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ=="],
+
+ "proc-log": ["proc-log@4.2.0", "", {}, "sha512-g8+OnU/L2v+wyiVK+D5fA34J7EH8jZ8DDlvwhRCMxmMj7UCBvxiO1mGeN+36JXIKF4zevU4kRBd8lVgG9vLelA=="],
+
+ "progress": ["progress@2.0.3", "", {}, "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA=="],
+
+ "promise": ["promise@8.3.0", "", { "dependencies": { "asap": "~2.0.6" } }, "sha512-rZPNPKTOYVNEEKFaq1HqTgOwZD+4/YHS5ukLzQCypkj+OkYx7iv0mA91lJlpPPZ8vMau3IIGj5Qlwrx+8iiSmg=="],
+
+ "prompts": ["prompts@2.4.2", "", { "dependencies": { "kleur": "^3.0.3", "sisteransi": "^1.0.5" } }, "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q=="],
+
+ "query-string": ["query-string@7.1.3", "", { "dependencies": { "decode-uri-component": "^0.2.2", "filter-obj": "^1.1.0", "split-on-first": "^1.0.0", "strict-uri-encode": "^2.0.0" } }, "sha512-hh2WYhq4fi8+b+/2Kg9CEge4fDPvHS534aOOvOZeQ3+Vf2mCFsaFBYj0i+iXcAq6I9Vzp5fjMFBlONvayDC1qg=="],
+
+ "queue": ["queue@6.0.2", "", { "dependencies": { "inherits": "~2.0.3" } }, "sha512-iHZWu+q3IdFZFX36ro/lKBkSvfkztY5Y7HMiPlOUjhupPcG2JMfst2KKEpu5XndviX/3UhFbRngUPNKtgvtZiA=="],
+
+ "range-parser": ["range-parser@1.2.1", "", {}, "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg=="],
+
+ "react": ["react@19.2.3", "", {}, "sha512-Ku/hhYbVjOQnXDZFv2+RibmLFGwFdeeKHFcOTlrt7xplBnya5OGn/hIRDsqDiSUcfORsDC7MPxwork8jBwsIWA=="],
+
+ "react-devtools-core": ["react-devtools-core@6.1.5", "", { "dependencies": { "shell-quote": "^1.6.1", "ws": "^7" } }, "sha512-ePrwPfxAnB+7hgnEr8vpKxL9cmnp7F322t8oqcPshbIQQhDKgFDW4tjhF2wjVbdXF9O/nyuy3sQWd9JGpiLPvA=="],
+
+ "react-dom": ["react-dom@19.2.3", "", { "dependencies": { "scheduler": "^0.27.0" }, "peerDependencies": { "react": "^19.2.3" } }, "sha512-yELu4WmLPw5Mr/lmeEpox5rw3RETacE++JgHqQzd2dg+YbJuat3jH4ingc+WPZhxaoFzdv9y33G+F7Nl5O0GBg=="],
+
+ "react-fast-compare": ["react-fast-compare@3.2.2", "", {}, "sha512-nsO+KSNgo1SbJqJEYRE9ERzo7YtYbou/OqjSQKxV7jcKox7+usiUVZOAC+XnDOABXggQTno0Y1CpVnuWEc1boQ=="],
+
+ "react-freeze": ["react-freeze@1.0.4", "", { "peerDependencies": { "react": ">=17.0.0" } }, "sha512-r4F0Sec0BLxWicc7HEyo2x3/2icUTrRmDjaaRyzzn+7aDyFZliszMDOgLVwSnQnYENOlL1o569Ze2HZefk8clA=="],
+
+ "react-is": ["react-is@19.2.8", "", {}, "sha512-s5un28nYxKJw5gvUHyW5PCC28CvBqLu9r3cWgzHT4Vo/5fqqkFcdRYsGcKf50WMPpjjFZS5d76fn3YCo2njKwQ=="],
+
+ "react-native": ["react-native@0.86.2", "", { "dependencies": { "@react-native/assets-registry": "0.86.2", "@react-native/codegen": "0.86.2", "@react-native/community-cli-plugin": "0.86.2", "@react-native/gradle-plugin": "0.86.2", "@react-native/js-polyfills": "0.86.2", "@react-native/normalize-colors": "0.86.2", "@react-native/virtualized-lists": "0.86.2", "abort-controller": "^3.0.0", "anser": "^1.4.9", "ansi-regex": "^5.0.0", "babel-plugin-syntax-hermes-parser": "0.36.0", "base64-js": "^1.5.1", "commander": "^12.0.0", "flow-enums-runtime": "^0.0.6", "hermes-compiler": "250829098.0.16", "invariant": "^2.2.4", "memoize-one": "^5.0.0", "metro-runtime": "^0.84.3", "metro-source-map": "^0.84.3", "nullthrows": "^1.1.1", "pretty-format": "^29.7.0", "promise": "^8.3.0", "react-devtools-core": "^6.1.5", "react-refresh": "^0.14.0", "regenerator-runtime": "^0.13.2", "scheduler": "0.27.0", "semver": "^7.1.3", "stacktrace-parser": "^0.1.10", "tinyglobby": "^0.2.15", "whatwg-fetch": "^3.0.0", "ws": "^7.5.10", "yargs": "^17.6.2" }, "peerDependencies": { "@react-native/jest-preset": "0.86.2", "@types/react": "^19.1.1", "react": "^19.2.3" }, "optionalPeers": ["@react-native/jest-preset", "@types/react"], "bin": { "react-native": "cli.js" } }, "sha512-zbJXGZpwfZGA79Z9ob6Atvfx4nAQL8yJBa35s58E4Oo+khPykfQP2sTeumkKbjwajFYfVayg8pj7Il9nIfTk7A=="],
+
+ "react-native-drawer-layout": ["react-native-drawer-layout@4.2.10", "", { "dependencies": { "color": "^4.2.3", "use-latest-callback": "^0.2.4" }, "peerDependencies": { "react": ">= 18.2.0", "react-native": "*", "react-native-gesture-handler": ">= 2.0.0", "react-native-reanimated": ">= 2.0.0" } }, "sha512-O6TQdZ5LSm3dqnuR4rX9KPtE+9dVg7jsezEYz1l01rkQTe4fQvYZIoPu2sZFl5X2N70uhRdjnPULySVR3sBUwA=="],
+
+ "react-native-gesture-handler": ["react-native-gesture-handler@2.32.0", "", { "dependencies": { "@egjs/hammerjs": "^2.0.17", "@types/react-test-renderer": "^19.1.0", "hoist-non-react-statics": "^3.3.0", "invariant": "^2.2.4" }, "peerDependencies": { "react": "*", "react-native": "*" } }, "sha512-uYIMOKlKENORq2SABE+jIjbPU+h5I/sQKcq2v16zRq848nwEp1fWRVwML4QWqijc8UcXJC25o54S8GQd4Mf2OA=="],
+
+ "react-native-gifted-charts": ["react-native-gifted-charts@1.4.78", "", { "dependencies": { "gifted-charts-core": "0.1.82" }, "peerDependencies": { "expo-linear-gradient": "*", "react": "*", "react-native": "*", "react-native-linear-gradient": "*", "react-native-svg": "*" }, "optionalPeers": ["expo-linear-gradient", "react-native-linear-gradient"] }, "sha512-6TGFeu7UkUi4LKJFiOjoFfdTNgTw4UyPaeCoIfo/YYT3a374pJ4bzKok3G9VM9J1JBlALtlKxl/oUOLPNwrawA=="],
+
+ "react-native-is-edge-to-edge": ["react-native-is-edge-to-edge@1.3.1", "", { "peerDependencies": { "react": "*", "react-native": "*" } }, "sha512-NIXU/iT5+ORyCc7p0z2nnlkouYKX425vuU1OEm6bMMtWWR9yvb+Xg5AZmImTKoF9abxCPqrKC3rOZsKzUYgYZA=="],
+
+ "react-native-reanimated": ["react-native-reanimated@4.5.1", "", { "dependencies": { "react-native-is-edge-to-edge": "^1.3.1", "semver": "^7.7.3" }, "peerDependencies": { "react": "*", "react-native": "0.83 - 0.86", "react-native-worklets": "0.10.x" } }, "sha512-RnMvtDuR+68ig864gAvZCOdZehqhC5rFmMo0kn+ARfgVSTvFeF6IFLBVgMPUu0KwihaapEyW24WRi6nEyy1kSA=="],
+
+ "react-native-safe-area-context": ["react-native-safe-area-context@5.7.0", "", { "peerDependencies": { "react": "*", "react-native": "*" } }, "sha512-/9/MtQz8ODphjsLdZ+GZAIcC/RtoqW9EeShf7Uvnfgm/pzYrJ75y3PV/J1wuAV1T5Dye5ygq4EAW20RoBq0ABQ=="],
+
+ "react-native-screens": ["react-native-screens@4.26.2", "", { "dependencies": { "react-freeze": "^1.0.0", "warn-once": "^0.1.0" }, "peerDependencies": { "react": "*", "react-native": "*" } }, "sha512-2XnWsZToKj76trGtEZzx5ELD/qOICFEprEeUntImmitQFVUkea27fiWdUSITArI356Y1qynpXZINW+Unbhky/A=="],
+
+ "react-native-svg": ["react-native-svg@15.15.4", "", { "dependencies": { "css-select": "^5.1.0", "css-tree": "^1.1.3", "warn-once": "0.1.1" }, "peerDependencies": { "react": "*", "react-native": "*" } }, "sha512-boT/vIRgj6zZKBpfTPJJiYWMbZE9duBMOwPK6kCSTgxsS947IFMOq9OgIFkpWZTB7t229H24pDRkh3W9ZK/J1A=="],
+
+ "react-native-web": ["react-native-web@0.21.2", "", { "dependencies": { "@babel/runtime": "^7.18.6", "@react-native/normalize-colors": "^0.74.1", "fbjs": "^3.0.4", "inline-style-prefixer": "^7.0.1", "memoize-one": "^6.0.0", "nullthrows": "^1.1.1", "postcss-value-parser": "^4.2.0", "styleq": "^0.1.3" }, "peerDependencies": { "react": "^18.0.0 || ^19.0.0", "react-dom": "^18.0.0 || ^19.0.0" } }, "sha512-SO2t9/17zM4iEnFvlu2DA9jqNbzNhoUP+AItkoCOyFmDMOhUnBBznBDCYN92fGdfAkfQlWzPoez6+zLxFNsZEg=="],
+
+ "react-native-worklets": ["react-native-worklets@0.10.1", "", { "dependencies": { "@babel/plugin-transform-arrow-functions": "^7.27.1", "@babel/plugin-transform-class-properties": "^7.28.6", "@babel/plugin-transform-classes": "^7.28.6", "@babel/plugin-transform-nullish-coalescing-operator": "^7.28.6", "@babel/plugin-transform-optional-chaining": "^7.28.6", "@babel/plugin-transform-shorthand-properties": "^7.27.1", "@babel/plugin-transform-template-literals": "^7.27.1", "@babel/plugin-transform-unicode-regex": "^7.27.1", "@babel/preset-typescript": "^7.28.5", "@babel/types": "^7.27.1", "convert-source-map": "^2.0.0", "semver": "^7.7.4" }, "peerDependencies": { "@babel/core": "*", "@react-native/metro-config": "*", "react": "*", "react-native": "0.83 - 0.86" } }, "sha512-62mRM19bDpfpdI8HLkEErcdOsrAPDtE9lA/sw+5lLRpzBHNhxaoj9QyY2KjXqUmirelxkX4zuPGTC3VdA0feJA=="],
+
+ "react-refresh": ["react-refresh@0.14.2", "", {}, "sha512-jCvmsr+1IUSMUyzOkRcvnVbX3ZYC6g9TDrDbFuFmRDq7PD4yaGbLKNQL6k2jnArV8hjYxh7hVhAZB6s9HDGpZA=="],
+
+ "react-remove-scroll": ["react-remove-scroll@2.7.2", "", { "dependencies": { "react-remove-scroll-bar": "^2.3.7", "react-style-singleton": "^2.2.3", "tslib": "^2.1.0", "use-callback-ref": "^1.3.3", "use-sidecar": "^1.1.3" }, "peerDependencies": { "@types/react": "*", "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-Iqb9NjCCTt6Hf+vOdNIZGdTiH1QSqr27H/Ek9sv/a97gfueI/5h1s3yRi1nngzMUaOOToin5dI1dXKdXiF+u0Q=="],
+
+ "react-remove-scroll-bar": ["react-remove-scroll-bar@2.3.8", "", { "dependencies": { "react-style-singleton": "^2.2.2", "tslib": "^2.0.0" }, "peerDependencies": { "@types/react": "*", "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" }, "optionalPeers": ["@types/react"] }, "sha512-9r+yi9+mgU33AKcj6IbT9oRCO78WriSj6t/cF8DWBZJ9aOGPOTEDvdUDz1FwKim7QXWwmHqtdHnRJfhAxEG46Q=="],
+
+ "react-style-singleton": ["react-style-singleton@2.2.3", "", { "dependencies": { "get-nonce": "^1.0.0", "tslib": "^2.0.0" }, "peerDependencies": { "@types/react": "*", "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-b6jSvxvVnyptAiLjbkWLE/lOnR4lfTtDAl+eUC7RZy+QQWc6wRzIV2CE6xBuMmDxc2qIihtDCZD5NPOFl7fRBQ=="],
+
+ "redent": ["redent@3.0.0", "", { "dependencies": { "indent-string": "^4.0.0", "strip-indent": "^3.0.0" } }, "sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg=="],
+
+ "regenerate": ["regenerate@1.4.2", "", {}, "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A=="],
+
+ "regenerate-unicode-properties": ["regenerate-unicode-properties@10.2.2", "", { "dependencies": { "regenerate": "^1.4.2" } }, "sha512-m03P+zhBeQd1RGnYxrGyDAPpWX/epKirLrp8e3qevZdVkKtnCrjjWczIbYc8+xd6vcTStVlqfycTx1KR4LOr0g=="],
+
+ "regenerator-runtime": ["regenerator-runtime@0.13.11", "", {}, "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg=="],
+
+ "regexpu-core": ["regexpu-core@6.4.0", "", { "dependencies": { "regenerate": "^1.4.2", "regenerate-unicode-properties": "^10.2.2", "regjsgen": "^0.8.0", "regjsparser": "^0.13.0", "unicode-match-property-ecmascript": "^2.0.0", "unicode-match-property-value-ecmascript": "^2.2.1" } }, "sha512-0ghuzq67LI9bLXpOX/ISfve/Mq33a4aFRzoQYhnnok1JOFpmE/A2TBGkNVenOGEeSBCjIiWcc6MVOG5HEQv0sA=="],
+
+ "regjsgen": ["regjsgen@0.8.0", "", {}, "sha512-RvwtGe3d7LvWiDQXeQw8p5asZUmfU1G/l6WbUXeHta7Y2PEIvBTwH6E2EfmYUK8pxcxEdEmaomqyp0vZZ7C+3Q=="],
+
+ "regjsparser": ["regjsparser@0.13.2", "", { "dependencies": { "jsesc": "~3.1.0" }, "bin": { "regjsparser": "bin/parser" } }, "sha512-NgRBy2Nx/bE+9F27nVHnqcN5HjyLmecqsqx2PJHu3/IEtADD4WuxuXIVExD5PoSDFVrl78dOonfcOe5O+5nbzQ=="],
+
+ "require-directory": ["require-directory@2.1.1", "", {}, "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q=="],
+
+ "resolve": ["resolve@1.22.12", "", { "dependencies": { "es-errors": "^1.3.0", "is-core-module": "^2.16.1", "path-parse": "^1.0.7", "supports-preserve-symlinks-flag": "^1.0.0" }, "bin": { "resolve": "bin/resolve" } }, "sha512-TyeJ1zif53BPfHootBGwPRYT1RUt6oGWsaQr8UyZW/eAm9bKoijtvruSDEmZHm92CwS9nj7/fWttqPCgzep8CA=="],
+
+ "resolve-from": ["resolve-from@5.0.0", "", {}, "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw=="],
+
+ "resolve-workspace-root": ["resolve-workspace-root@2.0.1", "", {}, "sha512-nR23LHAvaI6aHtMg6RWoaHpdR4D881Nydkzi2CixINyg9T00KgaJdJI6Vwty+Ps8WLxZHuxsS0BseWjxSA4C+w=="],
+
+ "restore-cursor": ["restore-cursor@2.0.0", "", { "dependencies": { "onetime": "^2.0.0", "signal-exit": "^3.0.2" } }, "sha512-6IzJLuGi4+R14vwagDHX+JrXmPVtPpn4mffDJ1UdR7/Edm87fl6yi8mMBIVvFtJaNTUvjughmW4hwLhRG7gC1Q=="],
+
+ "safe-buffer": ["safe-buffer@5.2.1", "", {}, "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ=="],
+
+ "sax": ["sax@1.6.1", "", {}, "sha512-42tBVwLWnaQvW5zc4HbZrTuWccECCZfBi92FDuwtqxasH+JbPB3/FOKb1m222K42R4WxuxzzMsTswfzgtSu64Q=="],
+
+ "scheduler": ["scheduler@0.27.0", "", {}, "sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q=="],
+
+ "semver": ["semver@7.8.5", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA=="],
+
+ "send": ["send@0.19.2", "", { "dependencies": { "debug": "2.6.9", "depd": "2.0.0", "destroy": "1.2.0", "encodeurl": "~2.0.0", "escape-html": "~1.0.3", "etag": "~1.8.1", "fresh": "~0.5.2", "http-errors": "~2.0.1", "mime": "1.6.0", "ms": "2.1.3", "on-finished": "~2.4.1", "range-parser": "~1.2.1", "statuses": "~2.0.2" } }, "sha512-VMbMxbDeehAxpOtWJXlcUS5E8iXh6QmN+BkRX1GARS3wRaXEEgzCcB10gTQazO42tpNIya8xIyNx8fll1OFPrg=="],
+
+ "serialize-error": ["serialize-error@2.1.0", "", {}, "sha512-ghgmKt5o4Tly5yEG/UJp8qTd0AN7Xalw4XBtDEKP655B699qMEtra1WlXeE6WIvdEG481JvRxULKsInq/iNysw=="],
+
+ "serve-static": ["serve-static@1.16.3", "", { "dependencies": { "encodeurl": "~2.0.0", "escape-html": "~1.0.3", "parseurl": "~1.3.3", "send": "~0.19.1" } }, "sha512-x0RTqQel6g5SY7Lg6ZreMmsOzncHFU7nhnRWkKgWuMTu5NN0DR5oruckMqRvacAN9d5w6ARnRBXl9xhDCgfMeA=="],
+
+ "server-only": ["server-only@0.0.1", "", {}, "sha512-qepMx2JxAa5jjfzxG79yPPq+8BuFToHd1hm7kI+Z4zAq1ftQiP7HcxMhDDItrbtwVeLg/cY2JnKnrcFkmiswNA=="],
+
+ "setimmediate": ["setimmediate@1.0.5", "", {}, "sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA=="],
+
+ "setprototypeof": ["setprototypeof@1.2.0", "", {}, "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw=="],
+
+ "sf-symbols-typescript": ["sf-symbols-typescript@2.2.0", "", {}, "sha512-TPbeg0b7ylrswdGCji8FRGFAKuqbpQlLbL8SOle3j1iHSs5Ob5mhvMAxWN2UItOjgALAB5Zp3fmMfj8mbWvXKw=="],
+
+ "shallowequal": ["shallowequal@1.1.0", "", {}, "sha512-y0m1JoUZSlPAjXVtPPW70aZWfIL/dSP7AFkRnniLCrK/8MDKog3TySTBmckD+RObVxH0v4Tox67+F14PdED2oQ=="],
+
+ "shebang-command": ["shebang-command@2.0.0", "", { "dependencies": { "shebang-regex": "^3.0.0" } }, "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA=="],
+
+ "shebang-regex": ["shebang-regex@3.0.0", "", {}, "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A=="],
+
+ "shell-quote": ["shell-quote@1.10.0", "", {}, "sha512-w1aiOKwKuRgtwAReIIj89puqg+I7GvX4IbLrvmhXbzQsj1+Zwi4VO3+fa6ZF91TWSjIxoEkKnMeHcLEODK5ZXA=="],
+
+ "signal-exit": ["signal-exit@3.0.7", "", {}, "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ=="],
+
+ "simple-plist": ["simple-plist@1.3.1", "", { "dependencies": { "bplist-creator": "0.1.0", "bplist-parser": "0.3.1", "plist": "^3.0.5" } }, "sha512-iMSw5i0XseMnrhtIzRb7XpQEXepa9xhWxGUojHBL43SIpQuDQkh3Wpy67ZbDzZVr6EKxvwVChnVpdl8hEVLDiw=="],
+
+ "simple-swizzle": ["simple-swizzle@0.2.4", "", { "dependencies": { "is-arrayish": "^0.3.1" } }, "sha512-nAu1WFPQSMNr2Zn9PGSZK9AGn4t/y97lEm+MXTtUDwfP0ksAIX4nO+6ruD9Jwut4C49SB1Ws+fbXsm/yScWOHw=="],
+
+ "sisteransi": ["sisteransi@1.0.5", "", {}, "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg=="],
+
+ "slugify": ["slugify@1.6.9", "", {}, "sha512-vZ7rfeehZui7wQs438JXBckYLkIIdfHOXsaVEUMyS5fHo1483l1bMdo0EDSWYclY0yZKFOipDy4KHuKs6ssvdg=="],
+
+ "source-map": ["source-map@0.5.7", "", {}, "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ=="],
+
+ "source-map-js": ["source-map-js@1.2.1", "", {}, "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA=="],
+
+ "source-map-support": ["source-map-support@0.5.21", "", { "dependencies": { "buffer-from": "^1.0.0", "source-map": "^0.6.0" } }, "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w=="],
+
+ "split-on-first": ["split-on-first@1.1.0", "", {}, "sha512-43ZssAJaMusuKWL8sKUBQXHWOpq8d6CfN/u1p4gUzfJkM05C8rxTmYrkIPTXapZpORA6LkkzcUulJ8FqA7Uudw=="],
+
+ "stackframe": ["stackframe@1.3.4", "", {}, "sha512-oeVtt7eWQS+Na6F//S4kJ2K2VbRlS9D43mAlMyVpVWovy9o+jfgH8O9agzANzaiLjclA0oYzUXEM4PurhSUChw=="],
+
+ "stacktrace-parser": ["stacktrace-parser@0.1.11", "", { "dependencies": { "type-fest": "^0.7.1" } }, "sha512-WjlahMgHmCJpqzU8bIBy4qtsZdU9lRlcZE3Lvyej6t4tuOuv1vk57OW3MBrj6hXBFx/nNoC9MPMTcr5YA7NQbg=="],
+
+ "standard-navigation": ["standard-navigation@0.0.5", "", {}, "sha512-YAmzwAiiQVocZxO/VGPFiQHcu5pKiz09QIGC0MK6aRMoa3E0QkoTQgcqJr7ZZ3OMiNhu4DkaGElFI5htjOIDbw=="],
+
+ "statuses": ["statuses@2.0.2", "", {}, "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw=="],
+
+ "stream-buffers": ["stream-buffers@2.2.0", "", {}, "sha512-uyQK/mx5QjHun80FLJTfaWE7JtwfRMKBLkMne6udYOmvH0CawotVa7TfgYHzAnpphn4+TweIx1QKMnRIbipmUg=="],
+
+ "strict-uri-encode": ["strict-uri-encode@2.0.0", "", {}, "sha512-QwiXZgpRcKkhTj2Scnn++4PKtWsH0kpzZ62L2R6c/LUVYv7hVnZqcg2+sMuT6R7Jusu1vviK/MFsu6kNJfWlEQ=="],
+
+ "string-width": ["string-width@4.2.3", "", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="],
+
+ "strip-ansi": ["strip-ansi@5.2.0", "", { "dependencies": { "ansi-regex": "^4.1.0" } }, "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA=="],
+
+ "strip-indent": ["strip-indent@3.0.0", "", { "dependencies": { "min-indent": "^1.0.0" } }, "sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ=="],
+
+ "structured-headers": ["structured-headers@0.4.1", "", {}, "sha512-0MP/Cxx5SzeeZ10p/bZI0S6MpgD+yxAhi1BOQ34jgnMXsCq3j1t6tQnZu+KdlL7dvJTLT3g9xN8tl10TqgFMcg=="],
+
+ "styleq": ["styleq@0.1.3", "", {}, "sha512-3ZUifmCDCQanjeej1f6kyl/BeP/Vae5EYkQ9iJfUm/QwZvlgnZzyflqAsAWYURdtea8Vkvswu2GrC57h3qffcA=="],
+
+ "supports-color": ["supports-color@7.2.0", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw=="],
+
+ "supports-hyperlinks": ["supports-hyperlinks@2.3.0", "", { "dependencies": { "has-flag": "^4.0.0", "supports-color": "^7.0.0" } }, "sha512-RpsAZlpWcDwOPQA22aCH4J0t7L8JmAvsCxfOSEwm7cQs3LshN36QaTkwd70DnBOXDWGssw2eUoc8CaRWT0XunA=="],
+
+ "supports-preserve-symlinks-flag": ["supports-preserve-symlinks-flag@1.0.0", "", {}, "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w=="],
+
+ "terminal-link": ["terminal-link@2.1.1", "", { "dependencies": { "ansi-escapes": "^4.2.1", "supports-hyperlinks": "^2.0.0" } }, "sha512-un0FmiRUQNr5PJqy9kP7c40F5BOfpGlYTrxonDChEZB7pzZxRNp/bt+ymiy9/npwXya9KH99nJ/GXFIiUkYGFQ=="],
+
+ "terser": ["terser@5.50.0", "", { "dependencies": { "@jridgewell/source-map": "^0.3.3", "acorn": "^8.15.0", "commander": "^2.20.0", "source-map-support": "~0.5.20" }, "bin": { "terser": "bin/terser" } }, "sha512-CN9BVxWhgS/hRxtUMjtC2uRWSTcSfQFHMDWma6sKKfIivCD91sM+FOPfvwoaRMqCSrUpe1nv3jDamd9eEQ4y+w=="],
+
+ "throat": ["throat@5.0.0", "", {}, "sha512-fcwX4mndzpLQKBS1DVYhGAcYaYt7vsHNIvQV+WXMvnow5cgjPphq5CaayLaGsjRdSCKZFNGt7/GYAuXaNOiYCA=="],
+
+ "tinyglobby": ["tinyglobby@0.2.17", "", { "dependencies": { "fdir": "^6.5.0", "picomatch": "^4.0.4" } }, "sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g=="],
+
+ "tmpl": ["tmpl@1.0.5", "", {}, "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw=="],
+
+ "to-regex-range": ["to-regex-range@5.0.1", "", { "dependencies": { "is-number": "^7.0.0" } }, "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ=="],
+
+ "toidentifier": ["toidentifier@1.0.1", "", {}, "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA=="],
+
+ "toqr": ["toqr@0.1.1", "", {}, "sha512-FWAPzCIHZHnrE/5/w9MPk0kK25hSQSH2IKhYh9PyjS3SG/+IEMvlwIHbhz+oF7xl54I+ueZlVnMjyzdSwLmAwA=="],
+
+ "tr46": ["tr46@0.0.3", "", {}, "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw=="],
+
+ "tslib": ["tslib@2.8.1", "", {}, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="],
+
+ "type-fest": ["type-fest@0.7.1", "", {}, "sha512-Ne2YiiGN8bmrmJJEuTWTLJR32nh/JdL1+PSicowtNb0WFpn59GK8/lfD61bVtzguz7b3PBt74nxpv/Pw5po5Rg=="],
+
+ "typescript": ["typescript@6.0.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-y2TvuxSZPDyQakkFRPZHKFm+KKVqIisdg9/CZwm9ftvKXLP8NRWj38/ODjNbr43SsoXqNuAisEf1GdCxqWcdBw=="],
+
+ "ua-parser-js": ["ua-parser-js@0.7.41", "", { "bin": { "ua-parser-js": "script/cli.js" } }, "sha512-O3oYyCMPYgNNHuO7Jjk3uacJWZF8loBgwrfd/5LE/HyZ3lUIOdniQ7DNXJcIgZbwioZxk0fLfI4EVnetdiX5jg=="],
+
+ "undici-types": ["undici-types@8.3.0", "", {}, "sha512-j375ScV60dom+YkPFIfTLcOiPxkN/buHz5GobjLhixFuANaNs3C9l4GmrWqejgXWJ7BbJcFYpTEUkS1Ge8bpZQ=="],
+
+ "unicode-canonical-property-names-ecmascript": ["unicode-canonical-property-names-ecmascript@2.0.1", "", {}, "sha512-dA8WbNeb2a6oQzAQ55YlT5vQAWGV9WXOsi3SskE3bcCdM0P4SDd+24zS/OCacdRq5BkdsRj9q3Pg6YyQoxIGqg=="],
+
+ "unicode-match-property-ecmascript": ["unicode-match-property-ecmascript@2.0.0", "", { "dependencies": { "unicode-canonical-property-names-ecmascript": "^2.0.0", "unicode-property-aliases-ecmascript": "^2.0.0" } }, "sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q=="],
+
+ "unicode-match-property-value-ecmascript": ["unicode-match-property-value-ecmascript@2.2.1", "", {}, "sha512-JQ84qTuMg4nVkx8ga4A16a1epI9H6uTXAknqxkGF/aFfRLw1xC/Bp24HNLaZhHSkWd3+84t8iXnp1J0kYcZHhg=="],
+
+ "unicode-property-aliases-ecmascript": ["unicode-property-aliases-ecmascript@2.2.0", "", {}, "sha512-hpbDzxUY9BFwX+UeBnxv3Sh1q7HFxj48DTmXchNgRa46lO8uj3/1iEn3MiNUYTg1g9ctIqXCCERn8gYZhHC5lQ=="],
+
+ "unpipe": ["unpipe@1.0.0", "", {}, "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ=="],
+
+ "update-browserslist-db": ["update-browserslist-db@1.3.1", "", { "dependencies": { "escalade": "^3.2.0", "picocolors": "^1.1.1" }, "peerDependencies": { "browserslist": ">= 4.21.0" }, "bin": { "update-browserslist-db": "cli.js" } }, "sha512-ZZ61DsRsOnakl74HAmp3oSN4aXUmEWXf+i/yv0h7tIBfICc3VdrFErQKUUKPgu3AMsTUMbcongALEN4l6GSUrQ=="],
+
+ "use-callback-ref": ["use-callback-ref@1.3.3", "", { "dependencies": { "tslib": "^2.0.0" }, "peerDependencies": { "@types/react": "*", "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-jQL3lRnocaFtu3V00JToYz/4QkNWswxijDaCVNZRiRTO3HQDLsdu1ZtmIUvV4yPp+rvWm5j0y0TG/S61cuijTg=="],
+
+ "use-latest-callback": ["use-latest-callback@0.2.6", "", { "peerDependencies": { "react": ">=16.8" } }, "sha512-FvRG9i1HSo0wagmX63Vrm8SnlUU3LMM3WyZkQ76RnslpBrX694AdG4A0zQBx2B3ZifFA0yv/BaEHGBnEax5rZg=="],
+
+ "use-sidecar": ["use-sidecar@1.1.3", "", { "dependencies": { "detect-node-es": "^1.1.0", "tslib": "^2.0.0" }, "peerDependencies": { "@types/react": "*", "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-Fedw0aZvkhynoPYlA5WXrMCAMm+nSWdZt6lzJQ7Ok8S6Q+VsHmHpRWndVRJ8Be0ZbkfPc5LRYH+5XrzXcEeLRQ=="],
+
+ "use-sync-external-store": ["use-sync-external-store@1.6.0", "", { "peerDependencies": { "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, "sha512-Pp6GSwGP/NrPIrxVFAIkOQeyw8lFenOHijQWkUTrDvrF4ALqylP2C/KCkeS9dpUM3KvYRQhna5vt7IL95+ZQ9w=="],
+
+ "utils-merge": ["utils-merge@1.0.1", "", {}, "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA=="],
+
+ "uuid": ["uuid@7.0.3", "", { "bin": { "uuid": "dist/bin/uuid" } }, "sha512-DPSke0pXhTZgoF/d+WSt2QaKMCFSfx7QegxEWT+JOuHF5aWrKEn0G+ztjuJg/gG8/ItK+rbPCD/yNv8yyih6Cg=="],
+
+ "validate-npm-package-name": ["validate-npm-package-name@5.0.1", "", {}, "sha512-OljLrQ9SQdOUqTaQxqL5dEfZWrXExyyWsozYlAWFawPVNuD83igl7uJD2RTkNMbniIYgt8l81eCJGIdQF7avLQ=="],
+
+ "vary": ["vary@1.1.2", "", {}, "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg=="],
+
+ "vaul": ["vaul@1.1.2", "", { "dependencies": { "@radix-ui/react-dialog": "^1.1.1" }, "peerDependencies": { "react": "^16.8 || ^17.0 || ^18.0 || ^19.0.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0.0 || ^19.0.0-rc" } }, "sha512-ZFkClGpWyI2WUQjdLJ/BaGuV6AVQiJ3uELGk3OYtP+B6yCO7Cmn9vPFXVJkRaGkOJu3m8bQMgtyzNHixULceQA=="],
+
+ "vlq": ["vlq@1.0.1", "", {}, "sha512-gQpnTgkubC6hQgdIcRdYGDSDc+SaujOdyesZQMv6JlfQee/9Mp0Qhnys6WxDWvQnL5WZdT7o2Ul187aSt0Rq+w=="],
+
+ "walker": ["walker@1.0.8", "", { "dependencies": { "makeerror": "1.0.12" } }, "sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ=="],
+
+ "warn-once": ["warn-once@0.1.1", "", {}, "sha512-VkQZJbO8zVImzYFteBXvBOZEl1qL175WH8VmZcxF2fZAoudNhNDvHi+doCaAEdU2l2vtcIwa2zn0QK5+I1HQ3Q=="],
+
+ "wcwidth": ["wcwidth@1.0.1", "", { "dependencies": { "defaults": "^1.0.3" } }, "sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg=="],
+
+ "webidl-conversions": ["webidl-conversions@3.0.1", "", {}, "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ=="],
+
+ "whatwg-fetch": ["whatwg-fetch@3.6.20", "", {}, "sha512-EqhiFU6daOA8kpjOWTL0olhVOF3i7OrFzSYiGsEMB8GcXS+RrzauAERX65xMeNWVqxA6HXH2m69Z9LaKKdisfg=="],
+
+ "whatwg-url": ["whatwg-url@5.0.0", "", { "dependencies": { "tr46": "~0.0.3", "webidl-conversions": "^3.0.0" } }, "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw=="],
+
+ "whatwg-url-minimum": ["whatwg-url-minimum@0.1.2", "", {}, "sha512-XPEm0XFQWNVG292lII1PrRRJl3sItrs7CettZ4ncYxuDVpLyy+NwlGyut2hXI0JswcJUxeCH+CyOJK0ZzAXD6A=="],
+
+ "which": ["which@2.0.2", "", { "dependencies": { "isexe": "^2.0.0" }, "bin": { "node-which": "./bin/node-which" } }, "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA=="],
+
+ "wrap-ansi": ["wrap-ansi@7.0.0", "", { "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", "strip-ansi": "^6.0.0" } }, "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q=="],
+
+ "ws": ["ws@7.5.13", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": "^5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-rsKI6xDBFVf4r/x8XyChGK04QR/XHroxs/jUcoWvtEZM8TPU/X/uIY9B1CsSzYws9ZJb/6bbBu7dPhFW00CAoA=="],
+
+ "xcode": ["xcode@3.0.1", "", { "dependencies": { "simple-plist": "^1.1.0", "uuid": "^7.0.3" } }, "sha512-kCz5k7J7XbJtjABOvkc5lJmkiDh8VhjVCGNiqdKCscmVpdVUpEAyXv1xmCLkQJ5dsHqx3IPO4XW+NTDhU/fatA=="],
+
+ "xml2js": ["xml2js@0.6.0", "", { "dependencies": { "sax": ">=0.6.0", "xmlbuilder": "~11.0.0" } }, "sha512-eLTh0kA8uHceqesPqSE+VvO1CDDJWMwlQfB6LuN6T8w6MaDJ8Txm8P7s5cHD0miF0V+GGTZrDQfxPZQVsur33w=="],
+
+ "xmlbuilder": ["xmlbuilder@11.0.1", "", {}, "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA=="],
+
+ "y18n": ["y18n@5.0.8", "", {}, "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA=="],
+
+ "yallist": ["yallist@3.1.1", "", {}, "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g=="],
+
+ "yaml": ["yaml@2.9.0", "", { "bin": { "yaml": "bin.mjs" } }, "sha512-2AvhNX3mb8zd6Zy7INTtSpl1F15HW6Wnqj0srWlkKLcpYl/gMIMJiyuGq2KeI2YFxUPjdlB+3Lc10seMLtL4cA=="],
+
+ "yargs": ["yargs@17.7.3", "", { "dependencies": { "cliui": "^8.0.1", "escalade": "^3.1.1", "get-caller-file": "^2.0.5", "require-directory": "^2.1.1", "string-width": "^4.2.3", "y18n": "^5.0.5", "yargs-parser": "^21.1.1" } }, "sha512-GZtjxm/J/4TSxuL3FNYjCmLktBTnIw/rVmKSIyKeYAZpmJB2ig9VauCC5xsa82GNKVKDAqpOn3KVzNt0zmrU0g=="],
+
+ "yargs-parser": ["yargs-parser@21.1.1", "", {}, "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw=="],
+
+ "zod": ["zod@3.25.76", "", {}, "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ=="],
+
+ "@babel/core/semver": ["semver@6.3.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="],
+
+ "@babel/helper-compilation-targets/semver": ["semver@6.3.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="],
+
+ "@babel/helper-create-class-features-plugin/semver": ["semver@6.3.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="],
+
+ "@babel/helper-create-regexp-features-plugin/semver": ["semver@6.3.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="],
+
+ "@babel/plugin-transform-runtime/semver": ["semver@6.3.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="],
+
+ "@expo/cli/ws": ["ws@8.21.3", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": ">=5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-201TZ/kPWxoPr/OKWjquZR1SWKXcvxdH+e1xrx89b3YbmzLMFCLfnaG1HFIgWzJOEWZ7MvpK++odZufgYR50Rw=="],
+
+ "@expo/devcert/debug": ["debug@3.2.7", "", { "dependencies": { "ms": "^2.1.1" } }, "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ=="],
+
+ "@expo/plist/xmlbuilder": ["xmlbuilder@15.1.1", "", {}, "sha512-yMqGBqtXyeN1e3TGYvgNgDVZ3j84W4cwkOXQswghol6APgZWaff9lnbvN7MHYJOiXsvGPXtjTYJEiC9J2wv9Eg=="],
+
+ "@expo/ws-tunnel/ws": ["ws@8.21.3", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": ">=5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-201TZ/kPWxoPr/OKWjquZR1SWKXcvxdH+e1xrx89b3YbmzLMFCLfnaG1HFIgWzJOEWZ7MvpK++odZufgYR50Rw=="],
+
+ "@react-native/babel-preset/@react-native/babel-plugin-codegen": ["@react-native/babel-plugin-codegen@0.87.0", "", { "dependencies": { "@babel/traverse": "^7.29.0", "@react-native/codegen": "0.87.0" } }, "sha512-q0CCSAYgomb2G1fkmJ5ughwvVLqjHcdJ4w3Ffxw4YsdBenWYZsnMARyr/ghvcvfV33/YsZQhdMZ3XnpG6oth/Q=="],
+
+ "@react-native/babel-preset/babel-plugin-syntax-hermes-parser": ["babel-plugin-syntax-hermes-parser@0.36.1", "", { "dependencies": { "hermes-parser": "0.36.1" } }, "sha512-ycduwJbvdvIMmVvlAZqGggS+pm5Eu4Bk9pcV9Sm2Z4PJNRVsKkv0g7vHj+LeuC1gHTeF67sJXFOq61IlqCa2hA=="],
+
+ "@react-native/codegen/hermes-parser": ["hermes-parser@0.36.0", "", { "dependencies": { "hermes-estree": "0.36.0" } }, "sha512-GdpwMmH5x6IpC1cijvcvYnlPB60Mh6kTSF/NFdYV/j56gYdi+0RIakYs+eqOV+bbO0SW7mgVVGSsTJxyPQfo3w=="],
+
+ "@react-native/metro-config/@react-native/js-polyfills": ["@react-native/js-polyfills@0.87.0", "", {}, "sha512-iwX3S/6XnR/TkOIk6Cz+FjeToDM/a4M1Cz/o1tfDakULjhKMI/UBtta1DsJgeg5c4WIJjkD4c8XlAJEb8pWOtg=="],
+
+ "@react-native/metro-config/metro-config": ["metro-config@0.87.0", "", { "dependencies": { "connect": "^3.6.5", "flow-enums-runtime": "^0.0.6", "jest-validate": "^29.7.0", "metro": "0.87.0", "metro-cache": "0.87.0", "metro-core": "0.87.0", "metro-runtime": "0.87.0" } }, "sha512-yZ9QAIzWH9MxwrzwRlX/CBGRWOT14l7klSDYg8hdtSdnoUs5A7MQRdHE2KB9iHVzGQW5wgWM5aXJswNeWbSQPA=="],
+
+ "@react-native/metro-config/metro-runtime": ["metro-runtime@0.87.0", "", { "dependencies": { "@babel/runtime": "^7.25.0", "flow-enums-runtime": "^0.0.6" } }, "sha512-XsXZkgEwI0ZMYSBfvOMAbenzwa60XlObXJ27g6/Khgrz9ESbiBbAsd7hR62G2jRBYOhGAzG61Gk22dpRJj/mdw=="],
+
+ "@react-navigation/native/standard-navigation": ["standard-navigation@0.0.8", "", { "peerDependencies": { "react": "*" } }, "sha512-TyVbo7INUDWtsUWDFn8RR7kwR87U0S4xHfLfbbnyeC581TmmyqQ+eM+nPw8rQTSD8QitRVcYfPaSHr/QJiUy1g=="],
+
+ "@testing-library/dom/aria-query": ["aria-query@5.3.0", "", { "dependencies": { "dequal": "^2.0.3" } }, "sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A=="],
+
+ "@testing-library/dom/dom-accessibility-api": ["dom-accessibility-api@0.5.16", "", {}, "sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg=="],
+
+ "@testing-library/dom/pretty-format": ["pretty-format@27.5.1", "", { "dependencies": { "ansi-regex": "^5.0.1", "ansi-styles": "^5.0.0", "react-is": "^17.0.1" } }, "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ=="],
+
+ "ansi-escapes/type-fest": ["type-fest@0.21.3", "", {}, "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w=="],
+
+ "babel-plugin-polyfill-corejs2/semver": ["semver@6.3.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="],
+
+ "babel-plugin-syntax-hermes-parser/hermes-parser": ["hermes-parser@0.36.0", "", { "dependencies": { "hermes-estree": "0.36.0" } }, "sha512-GdpwMmH5x6IpC1cijvcvYnlPB60Mh6kTSF/NFdYV/j56gYdi+0RIakYs+eqOV+bbO0SW7mgVVGSsTJxyPQfo3w=="],
+
+ "chalk/ansi-styles": ["ansi-styles@4.3.0", "", { "dependencies": { "color-convert": "^2.0.1" } }, "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg=="],
+
+ "cliui/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="],
+
+ "compressible/mime-db": ["mime-db@1.54.0", "", {}, "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ=="],
+
+ "compression/debug": ["debug@2.6.9", "", { "dependencies": { "ms": "2.0.0" } }, "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA=="],
+
+ "compression/negotiator": ["negotiator@0.6.4", "", {}, "sha512-myRT3DiWPHqho5PrJaIRyaMv2kgYf0mUVgBNOYMuCH5Ki1yEiQaf/ZJuQ62nvpc44wL5WDbTX7yGJi1Neevw8w=="],
+
+ "connect/debug": ["debug@2.6.9", "", { "dependencies": { "ms": "2.0.0" } }, "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA=="],
+
+ "css-tree/source-map": ["source-map@0.6.1", "", {}, "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="],
+
+ "expo-modules-autolinking/commander": ["commander@7.2.0", "", {}, "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw=="],
+
+ "fbjs/promise": ["promise@7.3.1", "", { "dependencies": { "asap": "~2.0.3" } }, "sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg=="],
+
+ "fbjs/ua-parser-js": ["ua-parser-js@1.0.41", "", { "bin": { "ua-parser-js": "script/cli.js" } }, "sha512-LbBDqdIC5s8iROCUjMbW1f5dJQTEFB1+KO9ogbvlb3nm9n4YHa5p4KTvFPWvh2Hs8gZMBuiB1/8+pdfe/tDPug=="],
+
+ "finalhandler/debug": ["debug@2.6.9", "", { "dependencies": { "ms": "2.0.0" } }, "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA=="],
+
+ "finalhandler/encodeurl": ["encodeurl@1.0.2", "", {}, "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w=="],
+
+ "finalhandler/on-finished": ["on-finished@2.3.0", "", { "dependencies": { "ee-first": "1.1.1" } }, "sha512-ikqdkGAAyf/X/gPhXGvfgAytDZtDbr+bkNUJ0N9h5MI/dmdgCs3l6hoHrcUv41sRKew3jIwrp4qQDXiK99Utww=="],
+
+ "finalhandler/statuses": ["statuses@1.5.0", "", {}, "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA=="],
+
+ "hoist-non-react-statics/react-is": ["react-is@16.13.1", "", {}, "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="],
+
+ "hosted-git-info/lru-cache": ["lru-cache@10.4.3", "", {}, "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ=="],
+
+ "jest-util/picomatch": ["picomatch@2.3.2", "", {}, "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA=="],
+
+ "jest-worker/supports-color": ["supports-color@8.1.1", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q=="],
+
+ "lighthouse-logger/debug": ["debug@2.6.9", "", { "dependencies": { "ms": "2.0.0" } }, "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA=="],
+
+ "log-symbols/chalk": ["chalk@2.4.2", "", { "dependencies": { "ansi-styles": "^3.2.1", "escape-string-regexp": "^1.0.5", "supports-color": "^5.3.0" } }, "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ=="],
+
+ "metro/accepts": ["accepts@2.0.0", "", { "dependencies": { "mime-types": "^3.0.0", "negotiator": "^1.0.0" } }, "sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng=="],
+
+ "metro/ci-info": ["ci-info@2.0.0", "", {}, "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ=="],
+
+ "metro/hermes-parser": ["hermes-parser@0.35.0", "", { "dependencies": { "hermes-estree": "0.35.0" } }, "sha512-9JLjeHxBx8T4CAsydZR49PNZUaix+WpQJwu9p2010lu+7Kwl6D/7wYFFJxoz+aXkaaClp9Zfg6W6/zVlSJORaA=="],
+
+ "metro/mime-types": ["mime-types@3.0.2", "", { "dependencies": { "mime-db": "^1.54.0" } }, "sha512-Lbgzdk0h4juoQ9fCKXW4by0UJqj+nOOrI9MJ1sSj4nI8aI2eo1qmvQEie4VD1glsS250n15LsWsYtCugiStS5A=="],
+
+ "metro-babel-transformer/hermes-parser": ["hermes-parser@0.35.0", "", { "dependencies": { "hermes-estree": "0.35.0" } }, "sha512-9JLjeHxBx8T4CAsydZR49PNZUaix+WpQJwu9p2010lu+7Kwl6D/7wYFFJxoz+aXkaaClp9Zfg6W6/zVlSJORaA=="],
+
+ "micromatch/picomatch": ["picomatch@2.3.2", "", {}, "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA=="],
+
+ "ora/chalk": ["chalk@2.4.2", "", { "dependencies": { "ansi-styles": "^3.2.1", "escape-string-regexp": "^1.0.5", "supports-color": "^5.3.0" } }, "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ=="],
+
+ "path-scurry/lru-cache": ["lru-cache@11.5.2", "", {}, "sha512-4pfM1Ff0x50o0tQwb5ucw/RzNyD0/YJME6IVcStalZuMWxdt3sR3huStTtxz4PUmvZfRguvDejasvQ2kifR11g=="],
+
+ "plist/@xmldom/xmldom": ["@xmldom/xmldom@0.9.11", "", {}, "sha512-tW8bcK3hsG0/uqSnNz6TK4BkcuZSezoU7DlnYssILmZDktPnSHHuDJJFM0AJv+13gz2r0iGdrj6qqKeUnxXEDg=="],
+
+ "plist/xmlbuilder": ["xmlbuilder@15.1.1", "", {}, "sha512-yMqGBqtXyeN1e3TGYvgNgDVZ3j84W4cwkOXQswghol6APgZWaff9lnbvN7MHYJOiXsvGPXtjTYJEiC9J2wv9Eg=="],
+
+ "pretty-format/react-is": ["react-is@18.3.1", "", {}, "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg=="],
+
+ "react-native-web/@react-native/normalize-colors": ["@react-native/normalize-colors@0.74.89", "", {}, "sha512-qoMMXddVKVhZ8PA1AbUCk83trpd6N+1nF2A6k1i6LsQObyS92fELuk8kU/lQs6M7BsMHwqyLCpQJ1uFgNvIQXg=="],
+
+ "react-native-web/memoize-one": ["memoize-one@6.0.0", "", {}, "sha512-rkpe71W0N0c0Xz6QD0eJETuWAJGnJ9afsl1srmwPrI+yBCkge5EycXXbYRyvL29zZVUWQCY7InPRCv3GDXuZNw=="],
+
+ "send/debug": ["debug@2.6.9", "", { "dependencies": { "ms": "2.0.0" } }, "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA=="],
+
+ "simple-plist/bplist-parser": ["bplist-parser@0.3.1", "", { "dependencies": { "big-integer": "1.6.x" } }, "sha512-PyJxiNtA5T2PlLIeBot4lbp7rj4OadzjnMZD/G5zuBNt8ei/yCU7+wW0h2bag9vr8c+/WuRWmSxbqAl9hL1rBA=="],
+
+ "source-map-support/source-map": ["source-map@0.6.1", "", {}, "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="],
+
+ "string-width/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="],
+
+ "strip-ansi/ansi-regex": ["ansi-regex@4.1.1", "", {}, "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g=="],
+
+ "terser/commander": ["commander@2.20.3", "", {}, "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ=="],
+
+ "wrap-ansi/ansi-styles": ["ansi-styles@4.3.0", "", { "dependencies": { "color-convert": "^2.0.1" } }, "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg=="],
+
+ "wrap-ansi/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="],
+
+ "@react-native/babel-preset/@react-native/babel-plugin-codegen/@react-native/codegen": ["@react-native/codegen@0.87.0", "", { "dependencies": { "@babel/core": "^7.25.2", "@babel/parser": "^7.29.0", "hermes-parser": "0.36.1", "invariant": "^2.2.4", "nullthrows": "^1.1.1", "tinyglobby": "^0.2.15", "yargs": "^17.6.2" } }, "sha512-odcBGR0A9Ee83A/XvzOp9juGRkSQOQcI4ZYs+3H20MySMxvZJ34/2nVHoxdmj0YY0Mn6gF8BjLzYkL0axbHuCA=="],
+
+ "@react-native/codegen/hermes-parser/hermes-estree": ["hermes-estree@0.36.0", "", {}, "sha512-A1+8zn5oss2CFP7pKsOaxorQG6FNIz1WU1VDqruLPPZl3LVgeE2C5xfFg8Ow6/Ow4mSslLLtYP1J3n38eKyW9w=="],
+
+ "@react-native/metro-config/metro-config/metro": ["metro@0.87.0", "", { "dependencies": { "@babel/code-frame": "^7.29.0", "@babel/core": "^7.25.2", "@babel/generator": "^7.29.1", "@babel/parser": "^7.29.0", "@babel/template": "^7.28.6", "@babel/traverse": "^7.29.0", "@babel/types": "^7.29.0", "accepts": "^2.0.0", "ci-info": "^2.0.0", "connect": "^3.6.5", "debug": "^4.4.0", "error-stack-parser": "^2.0.6", "flow-enums-runtime": "^0.0.6", "graceful-fs": "^4.2.4", "hermes-parser": "0.36.1", "image-size": "^1.0.2", "invariant": "^2.2.4", "jest-worker": "^29.7.0", "jsc-safe-url": "^0.2.2", "lodash.throttle": "^4.1.1", "metro-babel-transformer": "0.87.0", "metro-cache": "0.87.0", "metro-cache-key": "0.87.0", "metro-config": "0.87.0", "metro-core": "0.87.0", "metro-file-map": "0.87.0", "metro-resolver": "0.87.0", "metro-runtime": "0.87.0", "metro-source-map": "0.87.0", "metro-symbolicate": "0.87.0", "metro-transform-plugins": "0.87.0", "metro-transform-worker": "0.87.0", "mime-types": "^3.0.1", "nullthrows": "^1.1.1", "serialize-error": "^2.1.0", "source-map": "^0.5.6", "throat": "^5.0.0", "ws": "^7.5.10", "yargs": "^17.6.2" }, "bin": { "metro": "src/cli.js" } }, "sha512-fRqFhSzQhLNQSCvJFeuRzBRXAOOKXf1O8d2cvmMtG6yFR0jCllQ7vBsXoLP18yuqtf+N1XwWXTPF11eWy9q6dQ=="],
+
+ "@react-native/metro-config/metro-config/metro-cache": ["metro-cache@0.87.0", "", { "dependencies": { "exponential-backoff": "^3.1.1", "flow-enums-runtime": "^0.0.6", "https-proxy-agent": "^7.0.5", "metro-core": "0.87.0" } }, "sha512-146vS1BMSKcp99jddOhFBfHwzUEWN35NrsnSJDF2sQQ0ZT5OsBcOjd574PM233TWEZISRJ5DOK+vokD+1ubx+w=="],
+
+ "@react-native/metro-config/metro-config/metro-core": ["metro-core@0.87.0", "", { "dependencies": { "flow-enums-runtime": "^0.0.6", "lodash.throttle": "^4.1.1", "metro-resolver": "0.87.0" } }, "sha512-yW57+pCOHRC/CJZ99GA2PTd+30dORwDAjUPRCokj91IWW5In9Jwtt2FB5wACrGO8P0GHTyVHdTwDNyZsNndUbA=="],
+
+ "@testing-library/dom/pretty-format/react-is": ["react-is@17.0.2", "", {}, "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w=="],
+
+ "babel-plugin-syntax-hermes-parser/hermes-parser/hermes-estree": ["hermes-estree@0.36.0", "", {}, "sha512-A1+8zn5oss2CFP7pKsOaxorQG6FNIz1WU1VDqruLPPZl3LVgeE2C5xfFg8Ow6/Ow4mSslLLtYP1J3n38eKyW9w=="],
+
+ "compression/debug/ms": ["ms@2.0.0", "", {}, "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="],
+
+ "connect/debug/ms": ["ms@2.0.0", "", {}, "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="],
+
+ "finalhandler/debug/ms": ["ms@2.0.0", "", {}, "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="],
+
+ "lighthouse-logger/debug/ms": ["ms@2.0.0", "", {}, "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="],
+
+ "log-symbols/chalk/ansi-styles": ["ansi-styles@3.2.1", "", { "dependencies": { "color-convert": "^1.9.0" } }, "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA=="],
+
+ "log-symbols/chalk/escape-string-regexp": ["escape-string-regexp@1.0.5", "", {}, "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg=="],
+
+ "log-symbols/chalk/supports-color": ["supports-color@5.5.0", "", { "dependencies": { "has-flag": "^3.0.0" } }, "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow=="],
+
+ "metro-babel-transformer/hermes-parser/hermes-estree": ["hermes-estree@0.35.0", "", {}, "sha512-xVx5Opwy8Oo1I5yGpVRhCvWL/iV3M+ylksSKVNlxxD90cpDpR/AR1jLYqK8HWihm065a6UI3HeyAmYzwS8NOOg=="],
+
+ "metro/accepts/negotiator": ["negotiator@1.0.0", "", {}, "sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg=="],
+
+ "metro/hermes-parser/hermes-estree": ["hermes-estree@0.35.0", "", {}, "sha512-xVx5Opwy8Oo1I5yGpVRhCvWL/iV3M+ylksSKVNlxxD90cpDpR/AR1jLYqK8HWihm065a6UI3HeyAmYzwS8NOOg=="],
+
+ "metro/mime-types/mime-db": ["mime-db@1.54.0", "", {}, "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ=="],
+
+ "ora/chalk/ansi-styles": ["ansi-styles@3.2.1", "", { "dependencies": { "color-convert": "^1.9.0" } }, "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA=="],
+
+ "ora/chalk/escape-string-regexp": ["escape-string-regexp@1.0.5", "", {}, "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg=="],
+
+ "ora/chalk/supports-color": ["supports-color@5.5.0", "", { "dependencies": { "has-flag": "^3.0.0" } }, "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow=="],
+
+ "send/debug/ms": ["ms@2.0.0", "", {}, "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="],
+
+ "@react-native/metro-config/metro-config/metro/accepts": ["accepts@2.0.0", "", { "dependencies": { "mime-types": "^3.0.0", "negotiator": "^1.0.0" } }, "sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng=="],
+
+ "@react-native/metro-config/metro-config/metro/ci-info": ["ci-info@2.0.0", "", {}, "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ=="],
+
+ "@react-native/metro-config/metro-config/metro/metro-babel-transformer": ["metro-babel-transformer@0.87.0", "", { "dependencies": { "@babel/core": "^7.25.2", "flow-enums-runtime": "^0.0.6", "hermes-parser": "0.36.1", "metro-cache-key": "0.87.0", "nullthrows": "^1.1.1" } }, "sha512-IEn1K1FyY4J1sA5y6zqDjf2OkfmpTEqhZOeP6MJX8HepSW0cuHGw1m8bYOdv2adkG3XUE9dtM0csUs0gP/Xa5w=="],
+
+ "@react-native/metro-config/metro-config/metro/metro-cache-key": ["metro-cache-key@0.87.0", "", { "dependencies": { "flow-enums-runtime": "^0.0.6" } }, "sha512-Q+MPt6jl0zQogr4Q02WaJK6HY+GtE5A0nzj8kIV1Owgrx6OMNvm6scPTr1SM/R4LpCE8EH/Y5qfbXQ84GHTr0Q=="],
+
+ "@react-native/metro-config/metro-config/metro/metro-file-map": ["metro-file-map@0.87.0", "", { "dependencies": { "debug": "^4.4.0", "fb-watchman": "^2.0.0", "flow-enums-runtime": "^0.0.6", "graceful-fs": "^4.2.4", "invariant": "^2.2.4", "jest-worker": "^29.7.0", "micromatch": "^4.0.4", "nullthrows": "^1.1.1", "walker": "^1.0.7" } }, "sha512-Dc57t8jsINwA90bbVlqaeDlxf1rVGgj5SmOEnOMbaHNUM/HCYYTJxPV8SRdOBwh7qTz/biO9vaQvBTjRBgbbsg=="],
+
+ "@react-native/metro-config/metro-config/metro/metro-resolver": ["metro-resolver@0.87.0", "", { "dependencies": { "flow-enums-runtime": "^0.0.6" } }, "sha512-Xl3M9R3KToaHJvXlI2lSOxtYHitzxite+195DSi00HL9PcS7Xik5+3xlRjfkKb3FA86SZxYPj+WJwlcfgaZoxg=="],
+
+ "@react-native/metro-config/metro-config/metro/metro-source-map": ["metro-source-map@0.87.0", "", { "dependencies": { "@babel/traverse": "^7.29.0", "@babel/types": "^7.29.0", "flow-enums-runtime": "^0.0.6", "invariant": "^2.2.4", "metro-symbolicate": "0.87.0", "nullthrows": "^1.1.1", "ob1": "0.87.0", "source-map": "^0.5.6", "vlq": "^1.0.0" } }, "sha512-31BrYqu1c2co93rF1LN9Pw+7g+BrfDyxJkNQWrYm+pfA/+eVYVumF7tFMHbXLePLmHfhvSgVvbK6su1Oyiw1ng=="],
+
+ "@react-native/metro-config/metro-config/metro/metro-symbolicate": ["metro-symbolicate@0.87.0", "", { "dependencies": { "flow-enums-runtime": "^0.0.6", "invariant": "^2.2.4", "metro-source-map": "0.87.0", "nullthrows": "^1.1.1", "source-map": "^0.5.6", "vlq": "^1.0.0" }, "bin": { "metro-symbolicate": "src/index.js" } }, "sha512-uOpTxAXu74N+RSujUZ78L6gjI6bDdnz6XuW+AIUNuubZDEQPIpaX0StzIb0GMeQWP6zfHOHwFrWPP5Iquu1GXw=="],
+
+ "@react-native/metro-config/metro-config/metro/metro-transform-plugins": ["metro-transform-plugins@0.87.0", "", { "dependencies": { "@babel/core": "^7.25.2", "@babel/generator": "^7.29.1", "@babel/template": "^7.28.6", "@babel/traverse": "^7.29.0", "flow-enums-runtime": "^0.0.6", "nullthrows": "^1.1.1" } }, "sha512-i8keUe9+BaSwMuQM26DGheElCpTtflAKIrSwJAm8ZsgDb50RAUQus+e6zt2suaJXJ1OxZa7vqgtqoZxdniM6Fw=="],
+
+ "@react-native/metro-config/metro-config/metro/metro-transform-worker": ["metro-transform-worker@0.87.0", "", { "dependencies": { "@babel/core": "^7.25.2", "@babel/generator": "^7.29.1", "@babel/parser": "^7.29.0", "@babel/types": "^7.29.0", "flow-enums-runtime": "^0.0.6", "metro": "0.87.0", "metro-babel-transformer": "0.87.0", "metro-cache": "0.87.0", "metro-cache-key": "0.87.0", "metro-minify-terser": "0.87.0", "metro-source-map": "0.87.0", "metro-transform-plugins": "0.87.0", "nullthrows": "^1.1.1" } }, "sha512-YftLzNJxCTYxEN5k4AzR8KYwiENTEuz30L+4QeoMrtDd+U8mDThZg/ArR3JVRd8LaikwPOjVAS5SP3xPJN0AaA=="],
+
+ "@react-native/metro-config/metro-config/metro/mime-types": ["mime-types@3.0.2", "", { "dependencies": { "mime-db": "^1.54.0" } }, "sha512-Lbgzdk0h4juoQ9fCKXW4by0UJqj+nOOrI9MJ1sSj4nI8aI2eo1qmvQEie4VD1glsS250n15LsWsYtCugiStS5A=="],
+
+ "@react-native/metro-config/metro-config/metro-core/metro-resolver": ["metro-resolver@0.87.0", "", { "dependencies": { "flow-enums-runtime": "^0.0.6" } }, "sha512-Xl3M9R3KToaHJvXlI2lSOxtYHitzxite+195DSi00HL9PcS7Xik5+3xlRjfkKb3FA86SZxYPj+WJwlcfgaZoxg=="],
+
+ "log-symbols/chalk/ansi-styles/color-convert": ["color-convert@1.9.3", "", { "dependencies": { "color-name": "1.1.3" } }, "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg=="],
+
+ "log-symbols/chalk/supports-color/has-flag": ["has-flag@3.0.0", "", {}, "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw=="],
+
+ "ora/chalk/ansi-styles/color-convert": ["color-convert@1.9.3", "", { "dependencies": { "color-name": "1.1.3" } }, "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg=="],
+
+ "ora/chalk/supports-color/has-flag": ["has-flag@3.0.0", "", {}, "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw=="],
+
+ "@react-native/metro-config/metro-config/metro/accepts/negotiator": ["negotiator@1.0.0", "", {}, "sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg=="],
+
+ "@react-native/metro-config/metro-config/metro/metro-source-map/ob1": ["ob1@0.87.0", "", { "dependencies": { "flow-enums-runtime": "^0.0.6" } }, "sha512-8Q8sKCiUwsxgSmjDtVWyRgmxsgeJXXam3oQH6Id8ADfNaJMV6GZKyeAl8+pGVVdgwAZabfk5+aExle7AP/nZiA=="],
+
+ "@react-native/metro-config/metro-config/metro/metro-transform-worker/metro-minify-terser": ["metro-minify-terser@0.87.0", "", { "dependencies": { "flow-enums-runtime": "^0.0.6", "terser": "^5.15.0" } }, "sha512-tPa0O983PDutFu3LXbArRH5NduogcKrvW6fs9VHhksTKUA1iqDyoD1ZSj/Me52xJ6T9/9pOwIVyj9ulKc/zMkg=="],
+
+ "@react-native/metro-config/metro-config/metro/mime-types/mime-db": ["mime-db@1.54.0", "", {}, "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ=="],
+
+ "log-symbols/chalk/ansi-styles/color-convert/color-name": ["color-name@1.1.3", "", {}, "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw=="],
+
+ "ora/chalk/ansi-styles/color-convert/color-name": ["color-name@1.1.3", "", {}, "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw=="],
+ }
+}
diff --git a/eas.json b/eas.json
new file mode 100644
index 0000000..c6a91e8
--- /dev/null
+++ b/eas.json
@@ -0,0 +1,21 @@
+{
+ "cli": {
+ "version": ">= 21.8.0",
+ "appVersionSource": "remote"
+ },
+ "build": {
+ "development": {
+ "developmentClient": true,
+ "distribution": "internal"
+ },
+ "preview": {
+ "distribution": "internal"
+ },
+ "production": {
+ "autoIncrement": true
+ }
+ },
+ "submit": {
+ "production": {}
+ }
+}
diff --git a/package.json b/package.json
new file mode 100644
index 0000000..73ebdb4
--- /dev/null
+++ b/package.json
@@ -0,0 +1,54 @@
+{
+ "name": "yaba",
+ "main": "expo-router/entry",
+ "version": "1.0.0",
+ "dependencies": {
+ "@expo-google-fonts/dm-sans": "^0.4.2",
+ "@expo/ui": "~57.0.10",
+ "@expo/vector-icons": "^15.0.2",
+ "@react-navigation/bottom-tabs": "^7.18.16",
+ "expo": "~57.0.12",
+ "expo-blur": "~57.0.2",
+ "expo-constants": "~57.0.10",
+ "expo-dev-client": "~57.0.11",
+ "expo-device": "~57.0.1",
+ "expo-font": "~57.0.1",
+ "expo-glass-effect": "~57.0.1",
+ "expo-haptics": "~57.0.1",
+ "expo-image": "~57.0.2",
+ "expo-linear-gradient": "~57.0.1",
+ "expo-linking": "~57.0.5",
+ "expo-local-authentication": "~57.0.2",
+ "expo-router": "~57.0.12",
+ "expo-secure-store": "~57.0.1",
+ "expo-splash-screen": "~57.0.6",
+ "expo-status-bar": "~57.0.1",
+ "expo-symbols": "~57.0.2",
+ "expo-system-ui": "~57.0.2",
+ "expo-web-browser": "~57.0.2",
+ "react": "19.2.3",
+ "react-dom": "19.2.3",
+ "react-native": "0.86.2",
+ "react-native-gesture-handler": "~2.32.0",
+ "react-native-gifted-charts": "^1.4.78",
+ "react-native-reanimated": "4.5.1",
+ "react-native-safe-area-context": "~5.7.0",
+ "react-native-screens": "~4.26.0",
+ "react-native-svg": "15.15.4",
+ "react-native-web": "~0.21.0",
+ "react-native-worklets": "0.10.1"
+ },
+ "devDependencies": {
+ "@types/react": "~19.2.2",
+ "typescript": "~6.0.3"
+ },
+ "scripts": {
+ "start": "expo start",
+ "reset-project": "node ./scripts/reset-project.js",
+ "android": "expo run:android",
+ "ios": "expo run:ios",
+ "web": "expo start --web",
+ "lint": "expo lint"
+ },
+ "private": true
+}
diff --git a/scripts/reset-project.js b/scripts/reset-project.js
new file mode 100644
index 0000000..055d15b
--- /dev/null
+++ b/scripts/reset-project.js
@@ -0,0 +1,114 @@
+#!/usr/bin/env node
+
+/**
+ * This script is used to reset the project to a blank state.
+ * It deletes or moves the /src and /scripts directories to /example based on user input and creates a new /src/app directory with an index.tsx and _layout.tsx file.
+ * You can remove the `reset-project` script from package.json and safely delete this file after running it.
+ */
+
+const fs = require("fs");
+const path = require("path");
+const readline = require("readline");
+
+const root = process.cwd();
+const oldDirs = ["src", "scripts"];
+const exampleDir = "example";
+const newAppDir = "src/app";
+const exampleDirPath = path.join(root, exampleDir);
+
+const indexContent = `import { Text, View, StyleSheet } from "react-native";
+
+export default function Index() {
+ return (
+ <View style={styles.container}>
+ <Text>Edit src/app/index.tsx to edit this screen.</Text>
+ </View>
+ );
+}
+
+const styles = StyleSheet.create({
+ container: {
+ flex: 1,
+ alignItems: "center",
+ justifyContent: "center",
+ },
+});
+`;
+
+const layoutContent = `import { Stack } from "expo-router";
+
+export default function RootLayout() {
+ return <Stack />;
+}
+`;
+
+const rl = readline.createInterface({
+ input: process.stdin,
+ output: process.stdout,
+});
+
+const moveDirectories = async (userInput) => {
+ try {
+ if (userInput === "y") {
+ // Create the app-example directory
+ await fs.promises.mkdir(exampleDirPath, { recursive: true });
+ console.log(`📁 /${exampleDir} directory created.`);
+ }
+
+ // Move old directories to new app-example directory or delete them
+ for (const dir of oldDirs) {
+ const oldDirPath = path.join(root, dir);
+ if (fs.existsSync(oldDirPath)) {
+ if (userInput === "y") {
+ const newDirPath = path.join(root, exampleDir, dir);
+ await fs.promises.rename(oldDirPath, newDirPath);
+ console.log(`➡️ /${dir} moved to /${exampleDir}/${dir}.`);
+ } else {
+ await fs.promises.rm(oldDirPath, { recursive: true, force: true });
+ console.log(`❌ /${dir} deleted.`);
+ }
+ } else {
+ console.log(`➡️ /${dir} does not exist, skipping.`);
+ }
+ }
+
+ // Create new /src/app directory
+ const newAppDirPath = path.join(root, newAppDir);
+ await fs.promises.mkdir(newAppDirPath, { recursive: true });
+ console.log("\n📁 New /src/app directory created.");
+
+ // Create index.tsx
+ const indexPath = path.join(newAppDirPath, "index.tsx");
+ await fs.promises.writeFile(indexPath, indexContent);
+ console.log("📄 src/app/index.tsx created.");
+
+ // Create _layout.tsx
+ const layoutPath = path.join(newAppDirPath, "_layout.tsx");
+ await fs.promises.writeFile(layoutPath, layoutContent);
+ console.log("📄 src/app/_layout.tsx created.");
+
+ console.log("\n✅ Project reset complete. Next steps:");
+ console.log(
+ `1. Run \`npx expo start\` to start a development server.\n2. Edit src/app/index.tsx to edit the main screen.\n3. Put all your application code in /src, only screens and layout files should be in /src/app.${
+ userInput === "y"
+ ? `\n4. Delete the /${exampleDir} directory when you're done referencing it.`
+ : ""
+ }`
+ );
+ } catch (error) {
+ console.error(`❌ Error during script execution: ${error.message}`);
+ }
+};
+
+rl.question(
+ "Do you want to move existing files to /example instead of deleting them? (Y/n): ",
+ (answer) => {
+ const userInput = answer.trim().toLowerCase() || "y";
+ if (userInput === "y" || userInput === "n") {
+ moveDirectories(userInput).finally(() => rl.close());
+ } else {
+ console.log("❌ Invalid input. Please enter 'Y' or 'N'.");
+ rl.close();
+ }
+ }
+);
diff --git a/src/app/(app)/(tabs)/_layout.tsx b/src/app/(app)/(tabs)/_layout.tsx
new file mode 100644
index 0000000..5033232
--- /dev/null
+++ b/src/app/(app)/(tabs)/_layout.tsx
@@ -0,0 +1,169 @@
+import React from 'react';
+import { Platform, StyleSheet, TouchableOpacity, View } from 'react-native';
+import { Tabs } from 'expo-router';
+import { BlurView } from 'expo-blur';
+import { Feather } from '@expo/vector-icons';
+import Animated, {
+ useAnimatedStyle,
+ withSpring,
+ withTiming,
+} from 'react-native-reanimated';
+import * as Haptics from 'expo-haptics';
+import { Colors, Spacing } from '@/constants/theme';
+
+function TabBarIcon({
+ name,
+ isFocused,
+}: {
+ name: keyof typeof Feather.glyphMap;
+ isFocused: boolean;
+}) {
+ const animatedIconStyle = useAnimatedStyle(() => {
+ return {
+ transform: [
+ { scale: withSpring(isFocused ? 1.15 : 1, { damping: 12, stiffness: 300 }) },
+ ],
+ };
+ });
+
+ const animatedIndicatorStyle = useAnimatedStyle(() => {
+ return {
+ opacity: withTiming(isFocused ? 1 : 0, { duration: 200 }),
+ transform: [
+ { scale: withSpring(isFocused ? 1 : 0.5, { damping: 15, stiffness: 300 }) },
+ ],
+ };
+ });
+
+ return (
+ <View style={styles.iconContainer}>
+ <Animated.View style={animatedIconStyle}>
+ <Feather
+ name={name}
+ size={22}
+ color={isFocused ? Colors.primaryLight : Colors.textMuted}
+ />
+ </Animated.View>
+ <Animated.View style={[styles.indicator, animatedIndicatorStyle]} />
+ </View>
+ );
+}
+
+function CustomTabBar({ state, descriptors, navigation }: any) {
+ return (
+ <View style={styles.tabBarContainer}>
+ <BlurView
+ intensity={Platform.OS === 'ios' ? 80 : 100}
+ tint="dark"
+ style={styles.blurView}
+ >
+ {state.routes.map((route: any, index: number) => {
+ const { options } = descriptors[route.key];
+ const isFocused = state.index === index;
+
+ const onPress = () => {
+ const event = navigation.emit({
+ type: 'tabPress',
+ target: route.key,
+ canPreventDefault: true,
+ });
+
+ if (!isFocused && !event.defaultPrevented) {
+ Haptics.impactAsync(Haptics.ImpactFeedbackStyle.Light);
+ navigation.navigate(route.name);
+ }
+ };
+
+ let iconName: keyof typeof Feather.glyphMap = 'home';
+ if (route.name === 'index') iconName = 'pie-chart';
+ else if (route.name === 'salary') iconName = 'dollar-sign';
+ else if (route.name === 'recurring') iconName = 'repeat';
+ else if (route.name === 'expenses') iconName = 'plus-square';
+
+ return (
+ <TouchableOpacity
+ key={route.key}
+ accessibilityRole="button"
+ accessibilityState={isFocused ? { selected: true } : {}}
+ accessibilityLabel={options.tabBarAccessibilityLabel}
+ onPress={onPress}
+ style={styles.tabItem}
+ activeOpacity={1}
+ >
+ <TabBarIcon name={iconName} isFocused={isFocused} />
+ </TouchableOpacity>
+ );
+ })}
+ </BlurView>
+ </View>
+ );
+}
+
+export default function TabsLayout() {
+ return (
+ <Tabs
+ tabBar={(props) => <CustomTabBar {...props} />}
+ screenOptions={{
+ headerShown: false,
+ }}
+ >
+ <Tabs.Screen name="index" options={{ title: 'Dashboard' }} />
+ <Tabs.Screen name="salary" options={{ title: 'Salário' }} />
+ <Tabs.Screen name="recurring" options={{ title: 'Gastos Fixos' }} />
+ <Tabs.Screen name="expenses" options={{ title: 'Gastos do Mês' }} />
+ </Tabs>
+ );
+}
+
+const styles = StyleSheet.create({
+ tabBarContainer: {
+ position: 'absolute',
+ bottom: Platform.OS === 'ios' ? 30 : 20,
+ left: 24,
+ right: 24,
+ borderRadius: 32,
+ ...Platform.select({
+ ios: {
+ shadowColor: '#000',
+ shadowOffset: { width: 0, height: 8 },
+ shadowOpacity: 0.5,
+ shadowRadius: 16,
+ },
+ android: {
+ elevation: 10,
+ },
+ }),
+ },
+ blurView: {
+ flexDirection: 'row',
+ alignItems: 'center',
+ justifyContent: 'space-around',
+ borderRadius: 32,
+ backgroundColor: 'rgba(22, 27, 34, 0.75)',
+ borderWidth: 1,
+ borderColor: 'rgba(255, 255, 255, 0.08)',
+ overflow: 'hidden',
+ height: 64,
+ paddingHorizontal: Spacing.sm,
+ },
+ tabItem: {
+ flex: 1,
+ alignItems: 'center',
+ justifyContent: 'center',
+ height: '100%',
+ },
+ iconContainer: {
+ alignItems: 'center',
+ justifyContent: 'center',
+ width: 44,
+ height: 44,
+ },
+ indicator: {
+ position: 'absolute',
+ bottom: -2,
+ width: 4,
+ height: 4,
+ borderRadius: 2,
+ backgroundColor: Colors.primaryLight,
+ },
+});
diff --git a/src/app/(app)/(tabs)/expenses.tsx b/src/app/(app)/(tabs)/expenses.tsx
new file mode 100644
index 0000000..c313dc6
--- /dev/null
+++ b/src/app/(app)/(tabs)/expenses.tsx
@@ -0,0 +1,2 @@
+import OneTimeExpensesScreen from '@/screens/one-time-expenses-screen';
+export default OneTimeExpensesScreen;
diff --git a/src/app/(app)/(tabs)/index.tsx b/src/app/(app)/(tabs)/index.tsx
new file mode 100644
index 0000000..73bede0
--- /dev/null
+++ b/src/app/(app)/(tabs)/index.tsx
@@ -0,0 +1,2 @@
+import DashboardScreen from '@/screens/dashboard-screen';
+export default DashboardScreen;
diff --git a/src/app/(app)/(tabs)/recurring.tsx b/src/app/(app)/(tabs)/recurring.tsx
new file mode 100644
index 0000000..c5340ed
--- /dev/null
+++ b/src/app/(app)/(tabs)/recurring.tsx
@@ -0,0 +1,2 @@
+import RecurringExpensesScreen from '@/screens/recurring-expenses-screen';
+export default RecurringExpensesScreen;
diff --git a/src/app/(app)/(tabs)/salary.tsx b/src/app/(app)/(tabs)/salary.tsx
new file mode 100644
index 0000000..1d30bb1
--- /dev/null
+++ b/src/app/(app)/(tabs)/salary.tsx
@@ -0,0 +1,2 @@
+import SalaryScreen from '@/screens/salary-screen';
+export default SalaryScreen;
diff --git a/src/app/(app)/_layout.tsx b/src/app/(app)/_layout.tsx
new file mode 100644
index 0000000..6099274
--- /dev/null
+++ b/src/app/(app)/_layout.tsx
@@ -0,0 +1,21 @@
+import { Colors } from "@/constants/theme";
+import { useAuth } from "@/contexts/AuthContext";
+import { Redirect, Slot } from "expo-router";
+import { ActivityIndicator, View } from "react-native";
+
+export default function AppLayout() {
+ const { user, isLoading } = useAuth();
+
+ if (isLoading) {
+ return (
+ <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center', backgroundColor: Colors.background }}>
+ <ActivityIndicator size="large" color={Colors.primary} />
+ </View>
+ );
+ }
+
+ if (!user)
+ return <Redirect href="/login" />;
+
+ return <Slot />;
+} \ No newline at end of file
diff --git a/src/app/_layout.tsx b/src/app/_layout.tsx
new file mode 100644
index 0000000..fe9f265
--- /dev/null
+++ b/src/app/_layout.tsx
@@ -0,0 +1,54 @@
+import { SplashScreen, Stack } from 'expo-router';
+import { useState, useEffect } from 'react';
+import { StatusBar } from 'expo-status-bar';
+import { SafeAreaProvider } from 'react-native-safe-area-context';
+import { useAppFonts } from '@/hooks/use-app-hooks';
+import { AuthProvider, useAuth } from '@/contexts/AuthContext';
+import { Colors } from '@/constants/theme';
+
+import { AnimatedSplashScreen } from '@/components/animated-splash-screen';
+import { View } from 'react-native';
+
+SplashScreen.preventAutoHideAsync();
+
+function RootContent() {
+ const { isLoading } = useAuth();
+ const { fontsLoaded, fontsError } = useAppFonts();
+ const [splashFinished, setSplashFinished] = useState(false);
+
+ const isAppReady = !isLoading;
+
+ useEffect(() => {
+ if (fontsLoaded || fontsError) {
+ SplashScreen.hideAsync();
+ }
+ }, [fontsLoaded, fontsError]);
+
+ if (!fontsLoaded && !fontsError)
+ return null;
+
+ return (
+ <View style={{ flex: 1, backgroundColor: Colors.background }}>
+ <Stack screenOptions={{ headerShown: false, contentStyle: { backgroundColor: Colors.background } }}>
+ <Stack.Screen name="(app)" />
+ <Stack.Screen name="login" />
+ <Stack.Screen name="register" />
+ </Stack>
+
+ {!splashFinished && (
+ <AnimatedSplashScreen isAppReady={isAppReady} onAnimationComplete={() => setSplashFinished(true)} />
+ )}
+ </View>
+ )
+}
+
+export default function RootLayout() {
+ return (
+ <SafeAreaProvider>
+ <StatusBar style="light" />
+ <AuthProvider>
+ <RootContent />
+ </AuthProvider>
+ </SafeAreaProvider>
+ )
+}
diff --git a/src/app/biometrics.tsx b/src/app/biometrics.tsx
new file mode 100644
index 0000000..500adc9
--- /dev/null
+++ b/src/app/biometrics.tsx
@@ -0,0 +1,120 @@
+import React from 'react';
+import { View, Text, StyleSheet } from 'react-native';
+import { useRouter } from 'expo-router';
+import * as SecureStore from 'expo-secure-store';
+import Animated, { FadeInDown, FadeInUp } from 'react-native-reanimated';
+import { Feather } from '@expo/vector-icons';
+import { useSafeAreaInsets } from 'react-native-safe-area-context';
+import { Button } from '@/components/ui/button';
+import { Colors, Spacing, Typography, Radius } from '@/constants/theme';
+import { BlurView } from 'expo-blur';
+
+export default function BiometricsScreen() {
+ const router = useRouter();
+ const insets = useSafeAreaInsets();
+
+ async function handleAccept() {
+ await SecureStore.setItemAsync('yaba_use_biometrics', 'true');
+ router.replace('/');
+ }
+
+ function handleDecline() {
+ router.replace('/');
+ }
+
+ return (
+ <View style={[styles.container, { paddingTop: insets.top, paddingBottom: insets.bottom }]}>
+
+ <View style={styles.content}>
+ <Animated.View entering={FadeInDown.duration(600).delay(100)} style={styles.iconContainer}>
+ <View style={styles.iconBackground}>
+ <Feather size={64} color={Colors.primary} />
+ </View>
+ </Animated.View>
+
+ <Animated.View entering={FadeInUp.duration(600).delay(200)} style={styles.textContainer}>
+ <Text style={styles.title}>Login por Biometria</Text>
+ <Text style={styles.subtitle}>
+ Deseja utilizar sua biometria (Face ID / Digital) para acessar o app mais rapidamente nas próximas vezes?
+ </Text>
+ </Animated.View>
+ </View>
+
+ <Animated.View entering={FadeInUp.duration(600).delay(400)} style={styles.footer}>
+ <BlurView intensity={80} tint="dark" style={styles.blurContainer}>
+ <Button
+ label="Sim, usar biometria"
+ onPress={handleAccept}
+ fullWidth
+ style={styles.primaryButton}
+ />
+ <Button
+ label="Não, manter acesso livre"
+ variant="ghost"
+ onPress={handleDecline}
+ fullWidth
+ />
+ </BlurView>
+ </Animated.View>
+ </View>
+ );
+}
+
+const styles = StyleSheet.create({
+ container: {
+ flex: 1,
+ backgroundColor: Colors.background,
+ justifyContent: 'space-between',
+ },
+ content: {
+ flex: 1,
+ justifyContent: 'center',
+ alignItems: 'center',
+ paddingHorizontal: Spacing.xl,
+ gap: Spacing.xxl,
+ },
+ iconContainer: {
+ alignItems: 'center',
+ },
+ iconBackground: {
+ width: 120,
+ height: 120,
+ borderRadius: 60,
+ backgroundColor: 'rgba(238, 250, 13, 0.1)',
+ alignItems: 'center',
+ justifyContent: 'center',
+ borderWidth: 1,
+ borderColor: 'rgba(238, 250, 13, 0.2)',
+ },
+ textContainer: {
+ alignItems: 'center',
+ gap: Spacing.sm,
+ },
+ title: {
+ ...Typography.h1,
+ color: Colors.textPrimary,
+ textAlign: 'center',
+ },
+ subtitle: {
+ ...Typography.bodyLarge,
+ color: Colors.textSecondary,
+ textAlign: 'center',
+ lineHeight: 24,
+ },
+ footer: {
+ paddingHorizontal: Spacing.lg,
+ paddingBottom: Spacing.lg,
+ },
+ blurContainer: {
+ padding: Spacing.lg,
+ borderRadius: Radius.lg,
+ gap: Spacing.md,
+ backgroundColor: 'rgba(22, 27, 34, 0.6)',
+ borderWidth: 1,
+ borderColor: 'rgba(255, 255, 255, 0.08)',
+ overflow: 'hidden',
+ },
+ primaryButton: {
+ height: 56,
+ }
+});
diff --git a/src/app/login.tsx b/src/app/login.tsx
new file mode 100644
index 0000000..15ec3be
--- /dev/null
+++ b/src/app/login.tsx
@@ -0,0 +1,144 @@
+import { useAuth } from "@/contexts/AuthContext";
+import { Link, useRouter } from "expo-router";
+import { useState } from "react";
+import {
+ Alert,
+ KeyboardAvoidingView,
+ Platform,
+ StyleSheet,
+ Text,
+ View,
+} from "react-native";
+import { useSafeAreaInsets } from "react-native-safe-area-context";
+import * as LocalAuthentication from "expo-local-authentication";
+import Animated, { FadeInDown, FadeInUp } from "react-native-reanimated";
+import { Colors, Spacing, Typography } from "@/constants/theme";
+import { Input } from "@/components/ui/input";
+import { Button } from "@/components/ui/button";
+
+export default function LoginScreen() {
+ const insets = useSafeAreaInsets();
+ const router = useRouter();
+ const { login } = useAuth();
+
+ const [email, setEmail] = useState("");
+ const [password, setPassword] = useState("");
+ const [isLoading, setIsLoading] = useState(false);
+
+ async function handleLogin() {
+ if (!email || !password) {
+ Alert.alert("Erro", "Por favor, preencha todos os campos.");
+ return;
+ }
+
+ try {
+ setIsLoading(true);
+ await login({ email: email.trim(), password });
+
+ const hasHardware = await LocalAuthentication.hasHardwareAsync();
+ const isEnrolled = await LocalAuthentication.isEnrolledAsync();
+
+ if (hasHardware && isEnrolled) {
+ router.replace("/biometrics");
+ } else {
+ router.replace("/");
+ }
+ } catch (error) {
+ Alert.alert("Erro", "Falha ao fazer login. Verifique suas credenciais e tente novamente.");
+ } finally {
+ setIsLoading(false);
+ }
+ }
+
+ return (
+ <KeyboardAvoidingView style={styles.container} behavior={Platform.OS === "ios" ? "padding" : undefined}>
+ <View style={[styles.content, { paddingTop: insets.top + Spacing.xxl }]}>
+ <Animated.View entering={FadeInUp.duration(600)} style={styles.header}>
+ <Text style={styles.title}>YABA</Text>
+ <Text style={styles.subtitle}>O seu dinheiro, no seu controle.</Text>
+ </Animated.View>
+
+ <Animated.View entering={FadeInDown.delay(200).duration(600)} style={styles.form}>
+ <Input
+ id="login-email"
+ label="E-mail"
+ placeholder="seu@email.com"
+ value={email}
+ onChangeText={setEmail}
+ keyboardType="email-address"
+ autoCapitalize="none"
+ />
+ <Input
+ id="login-password"
+ label="Senha"
+ placeholder="********"
+ value={password}
+ onChangeText={setPassword}
+ secureTextEntry
+ />
+
+ <Button
+ id="login-button"
+ label="Entrar"
+ fullWidth
+ onPress={handleLogin}
+ loading={isLoading}
+ disabled={isLoading}
+ />
+
+ <View style={styles.footer}>
+ <Text style={styles.footerText}>Não tem uma conta? </Text>
+ <Link href="/register" asChild>
+ <Text style={styles.linkText}>Cadastre-se</Text>
+ </Link>
+ </View>
+ </Animated.View>
+ </View>
+ </KeyboardAvoidingView>
+ );
+}
+
+const styles = StyleSheet.create({
+ container: {
+ flex: 1,
+ backgroundColor: Colors.background,
+ },
+ content: {
+ flex: 1,
+ padding: Spacing.xl,
+ justifyContent: "center",
+ },
+ header: {
+ alignItems: "center",
+ marginBottom: Spacing.xl,
+ },
+ title: {
+ ...Typography.h1,
+ fontSize: 48,
+ color: Colors.primaryLight,
+ letterSpacing: 2,
+ fontFamily: "DMSans_700Bold",
+ },
+ subtitle: {
+ ...Typography.body,
+ color: Colors.textSecondary,
+ marginTop: Spacing.xs,
+ },
+ form: {
+ gap: Spacing.lg,
+ },
+ footer: {
+ flexDirection: "row",
+ justifyContent: "center",
+ marginTop: Spacing.xl,
+ },
+ footerText: {
+ ...Typography.body,
+ color: Colors.textSecondary,
+ },
+ linkText: {
+ ...Typography.body,
+ color: Colors.primaryLight,
+ fontFamily: "DMSans_700Bold",
+ },
+}); \ No newline at end of file
diff --git a/src/app/register.tsx b/src/app/register.tsx
new file mode 100644
index 0000000..aac588d
--- /dev/null
+++ b/src/app/register.tsx
@@ -0,0 +1,142 @@
+import React, { useState } from 'react';
+import { View, StyleSheet, Text, KeyboardAvoidingView, Platform, Alert, ScrollView } from 'react-native';
+import { Link, useRouter } from 'expo-router';
+import { useSafeAreaInsets } from 'react-native-safe-area-context';
+import Animated, { FadeInDown, FadeInUp } from 'react-native-reanimated';
+import * as LocalAuthentication from 'expo-local-authentication';
+import * as SecureStore from 'expo-secure-store';
+import { Button } from '@/components/ui/button';
+import { Input } from '@/components/ui/input';
+import { Colors, Spacing, Typography } from '@/constants/theme';
+import { useAuth } from '@/contexts/AuthContext';
+
+export default function RegisterScreen() {
+ const insets = useSafeAreaInsets();
+ const router = useRouter();
+ const { register } = useAuth();
+
+ const [name, setName] = useState('');
+ const [email, setEmail] = useState('');
+ const [password, setPassword] = useState('');
+ const [isLoading, setIsLoading] = useState(false);
+
+ async function handleRegister() {
+ if (!name || !email || !password) {
+ Alert.alert('Erro', 'Preencha todos os campos.');
+ return;
+ }
+ try {
+ setIsLoading(true);
+ await register({ name: name.trim(), email: email.trim(), password });
+
+ const hasHardware = await LocalAuthentication.hasHardwareAsync();
+ const isEnrolled = await LocalAuthentication.isEnrolledAsync();
+
+ if (hasHardware && isEnrolled) {
+ router.replace('/biometrics');
+ } else {
+ router.replace('/');
+ }
+ } catch (err: any) {
+ Alert.alert('Erro no cadastro', 'Verifique seus dados.');
+ setIsLoading(false);
+ }
+ }
+
+ return (
+ <KeyboardAvoidingView style={styles.container} behavior={Platform.OS === 'ios' ? 'padding' : undefined}>
+ <ScrollView contentContainerStyle={[styles.content, { paddingTop: insets.top + Spacing.xl }]}>
+ <Animated.View entering={FadeInUp.duration(600)} style={styles.header}>
+ <Text style={styles.title}>Criar Conta</Text>
+ <Text style={styles.subtitle}>Junte-se ao YABA e organize sua vida financeira.</Text>
+ </Animated.View>
+
+ <Animated.View entering={FadeInDown.delay(200).duration(600)} style={styles.form}>
+ <Input
+ id="register-name"
+ label="Nome"
+ placeholder="Como quer ser chamado?"
+ value={name}
+ onChangeText={setName}
+ />
+ <Input
+ id="register-email"
+ label="E-mail"
+ placeholder="seu@email.com"
+ value={email}
+ onChangeText={setEmail}
+ keyboardType="email-address"
+ autoCapitalize="none"
+ />
+ <Input
+ id="register-password"
+ label="Senha"
+ placeholder="No mínimo 6 caracteres"
+ value={password}
+ onChangeText={setPassword}
+ secureTextEntry
+ />
+
+ <Button
+ id="register-button"
+ label="Cadastrar"
+ fullWidth
+ onPress={handleRegister}
+ loading={isLoading}
+ disabled={isLoading}
+ />
+
+ <View style={styles.footer}>
+ <Text style={styles.footerText}>Já tem uma conta? </Text>
+ <Link href="/login" asChild>
+ <Text style={styles.linkText}>Faça login</Text>
+ </Link>
+ </View>
+ </Animated.View>
+ </ScrollView>
+ </KeyboardAvoidingView>
+ );
+}
+
+const styles = StyleSheet.create({
+ container: {
+ flex: 1,
+ backgroundColor: Colors.background,
+ },
+ content: {
+ flexGrow: 1,
+ padding: Spacing.xl,
+ justifyContent: 'center',
+ },
+ header: {
+ alignItems: 'center',
+ marginBottom: Spacing.xl,
+ },
+ title: {
+ ...Typography.h1,
+ color: Colors.textPrimary,
+ },
+ subtitle: {
+ ...Typography.body,
+ color: Colors.textSecondary,
+ marginTop: Spacing.xs,
+ textAlign: 'center',
+ },
+ form: {
+ gap: Spacing.lg,
+ },
+ footer: {
+ flexDirection: 'row',
+ justifyContent: 'center',
+ marginTop: Spacing.xl,
+ },
+ footerText: {
+ ...Typography.body,
+ color: Colors.textSecondary,
+ },
+ linkText: {
+ ...Typography.body,
+ color: Colors.primaryLight,
+ fontFamily: 'DMSans_700Bold',
+ },
+});
diff --git a/src/components/animated-splash-screen.tsx b/src/components/animated-splash-screen.tsx
new file mode 100644
index 0000000..7ecfdef
--- /dev/null
+++ b/src/components/animated-splash-screen.tsx
@@ -0,0 +1,103 @@
+import React, { useEffect } from 'react';
+import { StyleSheet, View, Text } from 'react-native';
+import Animated, {
+ useAnimatedStyle,
+ useSharedValue,
+ withTiming,
+ withSpring,
+ Easing,
+ runOnJS,
+ withDelay,
+} from 'react-native-reanimated';
+import { Colors } from '@/constants/theme';
+import { LinearGradient } from 'expo-linear-gradient';
+
+interface Props {
+ isAppReady: boolean;
+ onAnimationComplete: () => void;
+}
+
+export function AnimatedSplashScreen({ isAppReady, onAnimationComplete }: Props) {
+ const opacity = useSharedValue(1);
+ const scale = useSharedValue(1);
+ const textOpacity = useSharedValue(0);
+ const textTranslateY = useSharedValue(20);
+ const logoScale = useSharedValue(0.8);
+
+ useEffect(() => {
+ textOpacity.value = withTiming(1, { duration: 1000 });
+ textTranslateY.value = withSpring(0, { damping: 14, stiffness: 100 });
+ logoScale.value = withSpring(1, { damping: 10, stiffness: 100 });
+ }, []);
+
+ useEffect(() => {
+ if (isAppReady) {
+ opacity.value = withDelay(
+ 600,
+ withTiming(0, { duration: 700, easing: Easing.inOut(Easing.ease) }, (finished) => {
+ if (finished) {
+ runOnJS(onAnimationComplete)();
+ }
+ })
+ );
+
+ scale.value = withDelay(
+ 600,
+ withTiming(1.3, { duration: 700, easing: Easing.inOut(Easing.ease) })
+ );
+ }
+ }, [isAppReady]);
+
+ const animatedContainerStyle = useAnimatedStyle(() => ({
+ opacity: opacity.value,
+ transform: [{ scale: scale.value }],
+ }));
+
+ const animatedTextStyle = useAnimatedStyle(() => ({
+ opacity: textOpacity.value,
+ transform: [
+ { translateY: textTranslateY.value },
+ { scale: logoScale.value }
+ ],
+ }));
+
+ return (
+ <Animated.View style={[styles.container, animatedContainerStyle]}>
+ <LinearGradient
+ colors={['#0D2818', Colors.background]}
+ style={StyleSheet.absoluteFill}
+ start={{ x: 0, y: 0 }}
+ end={{ x: 0, y: 1 }}
+ />
+ <Animated.View style={animatedTextStyle}>
+ <Text style={styles.logoText}>YABA</Text>
+ <Text style={styles.subText}>Finanças Pessoais</Text>
+ </Animated.View>
+ </Animated.View>
+ );
+}
+
+const styles = StyleSheet.create({
+ container: {
+ ...StyleSheet.absoluteFill,
+ justifyContent: 'center',
+ alignItems: 'center',
+ zIndex: 9999,
+ },
+ logoText: {
+ fontFamily: 'Outfit_700Bold',
+ fontSize: 72,
+ color: Colors.white,
+ letterSpacing: -2,
+ textAlign: 'center',
+ },
+ subText: {
+ fontFamily: 'DMSans_500Medium',
+ fontSize: 16,
+ color: Colors.primaryLight,
+ letterSpacing: 2,
+ textTransform: 'uppercase',
+ textAlign: 'center',
+ marginTop: 8,
+ }
+});
diff --git a/src/components/expense-row.tsx b/src/components/expense-row.tsx
new file mode 100644
index 0000000..0f58c78
--- /dev/null
+++ b/src/components/expense-row.tsx
@@ -0,0 +1,213 @@
+import React from 'react';
+import { StyleSheet, Text, TouchableOpacity, View } from 'react-native';
+import Animated, { FadeInDown, LinearTransition } from 'react-native-reanimated';
+import { Colors, Radius, Spacing, Typography } from '@/constants/theme';
+import type { OneTimeExpense, RecurringExpense } from '@/types';
+
+const CATEGORY_EMOJI: Record<string, string> = {
+ moradia: '🏠',
+ alimentação: '🍽️',
+ transporte: '🚗',
+ saúde: '💊',
+ educação: '📚',
+ lazer: '🎬',
+ serviços: '⚙️',
+ outros: '📦',
+};
+
+interface ExpenseRowProps {
+ name: string;
+ amount: number;
+ category: string;
+ subtitle?: string;
+ index?: number;
+ onPress?: () => void;
+ rightElement?: React.ReactNode;
+ type?: 'expense' | 'income';
+}
+
+export function ExpenseRow({
+ name,
+ amount,
+ category,
+ subtitle,
+ index = 0,
+ onPress,
+ rightElement,
+ type = 'expense',
+}: ExpenseRowProps) {
+ const emoji = CATEGORY_EMOJI[category] ?? '📦';
+ const prefix = type === 'income' ? '+ ' : '- ';
+ const amountColor = type === 'income' ? Colors.positive : Colors.negative;
+
+ const formattedAmount = amount.toLocaleString('pt-BR', {
+ style: 'currency',
+ currency: 'BRL',
+ minimumFractionDigits: 2,
+ });
+
+ return (
+ <Animated.View
+ entering={FadeInDown.delay(index * 60).springify()}
+ layout={LinearTransition.springify()}
+ >
+ <TouchableOpacity
+ style={styles.row}
+ onPress={onPress}
+ activeOpacity={0.7}
+ disabled={!onPress}
+ accessibilityRole="button"
+ accessibilityLabel={`${name}, ${formattedAmount}`}
+ >
+ <View style={styles.iconBox}>
+ <Text style={styles.emoji}>{emoji}</Text>
+ </View>
+
+ <View style={styles.info}>
+ <Text style={styles.name} numberOfLines={1}>
+ {name}
+ </Text>
+ {subtitle ? (
+ <Text style={styles.subtitle} numberOfLines={1}>
+ {subtitle}
+ </Text>
+ ) : null}
+ </View>
+
+ <View style={styles.right}>
+ <Text style={[styles.amount, { color: amountColor }]}>
+ {prefix}{formattedAmount}
+ </Text>
+ {rightElement}
+ </View>
+ </TouchableOpacity>
+ </Animated.View>
+ );
+}
+
+interface RecurringExpenseRowProps {
+ expense: RecurringExpense;
+ index?: number;
+ onToggle: () => void;
+ onPress: () => void;
+}
+
+export function RecurringExpenseRow({
+ expense,
+ index = 0,
+ onToggle,
+ onPress,
+}: RecurringExpenseRowProps) {
+ return (
+ <ExpenseRow
+ name={expense.name}
+ amount={expense.amount}
+ category={expense.category}
+ type={expense.type}
+ subtitle={expense.due_day ? `Vence dia ${expense.due_day}` : undefined}
+ index={index}
+ onPress={onPress}
+ rightElement={
+ <TouchableOpacity
+ style={[
+ styles.toggleBadge,
+ expense.is_active ? styles.toggleActive : styles.toggleInactive,
+ ]}
+ onPress={onToggle}
+ hitSlop={{ top: 8, bottom: 8, left: 8, right: 8 }}
+ accessibilityLabel={expense.is_active ? 'Desativar gasto' : 'Ativar gasto'}
+ accessibilityRole="switch"
+ >
+ <Text style={styles.toggleText}>
+ {expense.is_active ? 'Ativo' : 'Pausado'}
+ </Text>
+ </TouchableOpacity>
+ }
+ />
+ );
+}
+
+interface OneTimeExpenseRowProps {
+ expense: OneTimeExpense;
+ index?: number;
+ onPress: () => void;
+}
+
+export function OneTimeExpenseRow({
+ expense,
+ index = 0,
+ onPress,
+}: OneTimeExpenseRowProps) {
+ const date = new Date(expense.expense_date + 'T12:00:00');
+ const formattedDate = date.toLocaleDateString('pt-BR', {
+ day: '2-digit',
+ month: 'short',
+ });
+
+ return (
+ <ExpenseRow
+ name={expense.name}
+ amount={expense.amount}
+ category={expense.category}
+ subtitle={formattedDate}
+ index={index}
+ onPress={onPress}
+ type={expense.type}
+ />
+ );
+}
+
+const styles = StyleSheet.create({
+ row: {
+ flexDirection: 'row',
+ alignItems: 'center',
+ paddingVertical: Spacing.md,
+ gap: Spacing.md,
+ },
+ iconBox: {
+ width: 44,
+ height: 44,
+ borderRadius: Radius.md,
+ backgroundColor: Colors.surfaceElevated,
+ alignItems: 'center',
+ justifyContent: 'center',
+ },
+ emoji: {
+ fontSize: 22,
+ },
+ info: {
+ flex: 1,
+ gap: 2,
+ },
+ name: {
+ ...Typography.bodyLarge,
+ color: Colors.textPrimary,
+ },
+ subtitle: {
+ ...Typography.caption,
+ color: Colors.textSecondary,
+ },
+ right: {
+ alignItems: 'flex-end',
+ gap: Spacing.xs,
+ },
+ amount: {
+ ...Typography.bodyLarge,
+ fontFamily: 'DMSans_600SemiBold',
+ },
+ toggleBadge: {
+ paddingHorizontal: Spacing.sm,
+ paddingVertical: 2,
+ borderRadius: Radius.full,
+ },
+ toggleActive: {
+ backgroundColor: `${Colors.positive}22`,
+ },
+ toggleInactive: {
+ backgroundColor: `${Colors.textMuted}22`,
+ },
+ toggleText: {
+ ...Typography.caption,
+ color: Colors.textSecondary,
+ },
+});
diff --git a/src/components/ui/action-modal.tsx b/src/components/ui/action-modal.tsx
new file mode 100644
index 0000000..a1d95be
--- /dev/null
+++ b/src/components/ui/action-modal.tsx
@@ -0,0 +1,107 @@
+import React from 'react';
+import { Modal, StyleSheet, Text, TouchableOpacity, View } from 'react-native';
+import { BlurView } from 'expo-blur';
+import Animated, { FadeIn, FadeInDown, FadeOut, FadeOutDown } from 'react-native-reanimated';
+import { Colors, Radius, Spacing, Typography } from '@/constants/theme';
+import { Button } from './button';
+
+interface ActionModalProps {
+ visible: boolean;
+ title: string;
+ message: string;
+ confirmText?: string;
+ cancelText?: string;
+ onConfirm: () => void;
+ onCancel: () => void;
+ isDestructive?: boolean;
+}
+
+export function ActionModal({
+ visible,
+ title,
+ message,
+ confirmText = 'Confirmar',
+ cancelText = 'Cancelar',
+ onConfirm,
+ onCancel,
+ isDestructive = false,
+}: ActionModalProps) {
+ if (!visible) return null;
+
+ return (
+ <Modal visible={visible} transparent animationType="none" onRequestClose={onCancel}>
+ <Animated.View entering={FadeIn.duration(200)} exiting={FadeOut.duration(200)} style={styles.overlay}>
+ <TouchableOpacity style={styles.backdrop} activeOpacity={1} onPress={onCancel} />
+
+ <Animated.View entering={FadeInDown.duration(300).springify()} exiting={FadeOutDown.duration(200)} style={styles.modalContainer}>
+ <BlurView intensity={80} tint="dark" style={styles.blurView}>
+ <View style={styles.content}>
+ <Text style={styles.title}>{title}</Text>
+ <Text style={styles.message}>{message}</Text>
+
+ <View style={styles.actions}>
+ <Button
+ label={cancelText}
+ variant="ghost"
+ onPress={onCancel}
+ style={styles.actionButton}
+ />
+ <Button
+ label={confirmText}
+ variant={isDestructive ? 'danger' : 'primary'}
+ onPress={onConfirm}
+ style={styles.actionButton}
+ />
+ </View>
+ </View>
+ </BlurView>
+ </Animated.View>
+ </Animated.View>
+ </Modal>
+ );
+}
+
+const styles = StyleSheet.create({
+ overlay: {
+ flex: 1,
+ justifyContent: 'flex-end',
+ backgroundColor: 'rgba(0, 0, 0, 0.4)',
+ },
+ backdrop: {
+ ...StyleSheet.absoluteFill,
+ },
+ modalContainer: {
+ padding: Spacing.md,
+ paddingBottom: Spacing.xxl,
+ },
+ blurView: {
+ borderRadius: Radius.lg,
+ overflow: 'hidden',
+ borderWidth: 1,
+ borderColor: 'rgba(255, 255, 255, 0.08)',
+ },
+ content: {
+ padding: Spacing.xl,
+ gap: Spacing.md,
+ backgroundColor: 'rgba(22, 27, 34, 0.6)',
+ },
+ title: {
+ ...Typography.h2,
+ color: Colors.textPrimary,
+ textAlign: 'center',
+ },
+ message: {
+ ...Typography.body,
+ color: Colors.textSecondary,
+ textAlign: 'center',
+ lineHeight: 22,
+ },
+ actions: {
+ flexDirection: 'row',
+ gap: Spacing.sm,
+ marginTop: Spacing.md,
+ },
+ actionButton: {
+ flex: 1,
+ },
+});
diff --git a/src/components/ui/button.tsx b/src/components/ui/button.tsx
new file mode 100644
index 0000000..3486ff7
--- /dev/null
+++ b/src/components/ui/button.tsx
@@ -0,0 +1,141 @@
+import React from 'react';
+import {
+ ActivityIndicator,
+ StyleSheet,
+ Text,
+ TouchableOpacity,
+ type TouchableOpacityProps,
+ View,
+} from 'react-native';
+import Animated, {
+ useAnimatedStyle,
+ useSharedValue,
+ withSpring,
+} from 'react-native-reanimated';
+import { Colors, Radius, Spacing, Typography } from '@/constants/theme';
+
+const AnimatedTouchable = Animated.createAnimatedComponent(TouchableOpacity);
+
+interface ButtonProps extends TouchableOpacityProps {
+ label: string;
+ variant?: 'primary' | 'secondary' | 'ghost' | 'danger';
+ loading?: boolean;
+ fullWidth?: boolean;
+}
+
+export function Button({
+ label,
+ variant = 'primary',
+ loading = false,
+ fullWidth = false,
+ onPress,
+ disabled,
+ style,
+ ...rest
+}: ButtonProps) {
+ const scale = useSharedValue(1);
+
+ const animatedStyle = useAnimatedStyle(() => ({
+ transform: [{ scale: scale.value }],
+ }));
+
+ function handlePressIn() {
+ scale.value = withSpring(0.96, { damping: 15, stiffness: 400 });
+ }
+
+ function handlePressOut() {
+ scale.value = withSpring(1, { damping: 15, stiffness: 400 });
+ }
+
+ const containerStyle = [
+ styles.base,
+ styles[variant],
+ fullWidth && styles.fullWidth,
+ (disabled || loading) && styles.disabled,
+ style,
+ ];
+
+ const textColor =
+ variant === 'secondary' || variant === 'ghost'
+ ? Colors.textPrimary
+ : Colors.white;
+
+ return (
+ <AnimatedTouchable
+ style={[animatedStyle, containerStyle]}
+ onPress={onPress}
+ onPressIn={handlePressIn}
+ onPressOut={handlePressOut}
+ disabled={disabled || loading}
+ activeOpacity={1}
+ {...rest}
+ >
+ {loading ? (
+ <ActivityIndicator color={textColor} size="small" />
+ ) : (
+ <Text style={[styles.label, { color: textColor }]}>{label}</Text>
+ )}
+ </AnimatedTouchable>
+ );
+}
+
+interface IconButtonProps {
+ onPress: () => void;
+ children: React.ReactNode;
+ accessibilityLabel: string;
+}
+
+export function IconButton({ onPress, children, accessibilityLabel }: IconButtonProps) {
+ return (
+ <TouchableOpacity
+ style={styles.iconButton}
+ onPress={onPress}
+ hitSlop={{ top: 8, bottom: 8, left: 8, right: 8 }}
+ accessibilityLabel={accessibilityLabel}
+ accessibilityRole="button"
+ >
+ <View>{children}</View>
+ </TouchableOpacity>
+ );
+}
+
+const styles = StyleSheet.create({
+ base: {
+ height: 52,
+ borderRadius: Radius.md,
+ alignItems: 'center',
+ justifyContent: 'center',
+ paddingHorizontal: Spacing.lg,
+ minWidth: 44, // touch target mínimo
+ },
+ primary: {
+ backgroundColor: Colors.primary,
+ },
+ secondary: {
+ backgroundColor: Colors.surfaceElevated,
+ borderWidth: 1,
+ borderColor: Colors.border,
+ },
+ ghost: {
+ backgroundColor: Colors.transparent,
+ },
+ danger: {
+ backgroundColor: Colors.negative,
+ },
+ fullWidth: {
+ width: '100%',
+ },
+ disabled: {
+ opacity: 0.5,
+ },
+ label: {
+ ...Typography.bodyLarge,
+ fontFamily: 'DMSans_600SemiBold',
+ },
+ iconButton: {
+ width: 44,
+ height: 44,
+ alignItems: 'center',
+ justifyContent: 'center',
+ },
+});
diff --git a/src/components/ui/expenses-chart.tsx b/src/components/ui/expenses-chart.tsx
new file mode 100644
index 0000000..efd5dee
--- /dev/null
+++ b/src/components/ui/expenses-chart.tsx
@@ -0,0 +1,187 @@
+import React from 'react';
+import { StyleSheet, Text, View } from 'react-native';
+import { PieChart } from 'react-native-gifted-charts';
+import { Colors, Radius, Spacing, Typography } from '@/constants/theme';
+import type { DashboardExpenseItem } from '@/types';
+import { Card, SectionLabel } from './primitives';
+
+interface ExpensesChartProps {
+ recurring: DashboardExpenseItem[];
+ oneTime: DashboardExpenseItem[];
+}
+
+const CATEGORY_COLORS: Record<string, string> = {
+ moradia: '#4C6EF5',
+ alimentação: '#FA5252',
+ transporte: '#FAB005',
+ saúde: '#12B886',
+ educação: '#BE4BDB',
+ lazer: '#FF922B',
+ serviços: '#228BE6',
+ outros: '#868E96',
+};
+
+const CATEGORY_LABELS: Record<string, string> = {
+ moradia: 'Moradia',
+ alimentação: 'Alimentação',
+ transporte: 'Transporte',
+ saúde: 'Saúde',
+ educação: 'Educação',
+ lazer: 'Lazer',
+ serviços: 'Serviços',
+ outros: 'Outros',
+};
+
+export function ExpensesChart({ recurring, oneTime }: ExpensesChartProps) {
+ const categoryTotals: Record<string, number> = {};
+
+ const allExpenses = [
+ ...recurring.filter(e => e.is_active && e.type === 'expense'),
+ ...oneTime.filter(e => e.type === 'expense')
+ ];
+
+ if (allExpenses.length === 0) {
+ return (
+ <Card style={styles.card}>
+ <SectionLabel text="Análise de Gastos" />
+ <View style={styles.emptyContainer}>
+ <Text style={styles.emptyText}>Não há despesas para analisar neste mês.</Text>
+ </View>
+ </Card>
+ );
+ }
+
+ let totalExpenses = 0;
+ allExpenses.forEach(e => {
+ if (!categoryTotals[e.category]) {
+ categoryTotals[e.category] = 0;
+ }
+ categoryTotals[e.category] += e.amount;
+ totalExpenses += e.amount;
+ });
+
+ const pieData = Object.keys(categoryTotals)
+ .map(category => ({
+ value: categoryTotals[category],
+ color: CATEGORY_COLORS[category] || CATEGORY_COLORS.outros,
+ label: CATEGORY_LABELS[category] || 'Outros',
+ percentage: ((categoryTotals[category] / totalExpenses) * 100).toFixed(0) + '%',
+ }))
+ .sort((a, b) => b.value - a.value);
+
+ return (
+ <Card style={styles.card}>
+ <SectionLabel text="Análise de Gastos" />
+
+ <View style={styles.chartRow}>
+ <View style={styles.chartWrapper}>
+ <PieChart
+ data={pieData}
+ donut
+ radius={70}
+ innerRadius={50}
+ innerCircleColor={Colors.surface}
+ centerLabelComponent={() => {
+ return (
+ <View style={styles.centerLabel}>
+ <Text style={styles.centerLabelValue}>
+ {totalExpenses.toLocaleString('pt-BR', {
+ style: 'currency',
+ currency: 'BRL',
+ minimumFractionDigits: 0,
+ maximumFractionDigits: 0,
+ })}
+ </Text>
+ <Text style={styles.centerLabelText}>Total</Text>
+ </View>
+ );
+ }}
+ />
+ </View>
+
+ <View style={styles.legendContainer}>
+ {pieData.map((item, index) => (
+ <View key={index} style={styles.legendItem}>
+ <View style={[styles.legendDot, { backgroundColor: item.color }]} />
+ <View style={styles.legendTextWrapper}>
+ <Text style={styles.legendLabel} numberOfLines={1}>{item.label}</Text>
+ <Text style={styles.legendValue}>
+ {item.value.toLocaleString('pt-BR', {
+ style: 'currency',
+ currency: 'BRL',
+ })} ({item.percentage})
+ </Text>
+ </View>
+ </View>
+ ))}
+ </View>
+ </View>
+ </Card>
+ );
+}
+
+const styles = StyleSheet.create({
+ card: {
+ gap: Spacing.md,
+ },
+ emptyContainer: {
+ paddingVertical: Spacing.xl,
+ alignItems: 'center',
+ justifyContent: 'center',
+ },
+ emptyText: {
+ ...Typography.body,
+ color: Colors.textMuted,
+ },
+ chartRow: {
+ flexDirection: 'row',
+ alignItems: 'center',
+ justifyContent: 'space-between',
+ },
+ chartWrapper: {
+ alignItems: 'center',
+ justifyContent: 'center',
+ },
+ centerLabel: {
+ alignItems: 'center',
+ justifyContent: 'center',
+ },
+ centerLabelValue: {
+ ...Typography.body,
+ fontFamily: 'DMSans_700Bold',
+ color: Colors.textPrimary,
+ fontSize: 14,
+ },
+ centerLabelText: {
+ ...Typography.caption,
+ color: Colors.textSecondary,
+ fontSize: 10,
+ },
+ legendContainer: {
+ flex: 1,
+ marginLeft: Spacing.lg,
+ gap: Spacing.sm,
+ },
+ legendItem: {
+ flexDirection: 'row',
+ alignItems: 'center',
+ },
+ legendDot: {
+ width: 10,
+ height: 10,
+ borderRadius: 5,
+ marginRight: Spacing.xs,
+ },
+ legendTextWrapper: {
+ flex: 1,
+ },
+ legendLabel: {
+ ...Typography.caption,
+ color: Colors.textSecondary,
+ },
+ legendValue: {
+ ...Typography.caption,
+ color: Colors.textPrimary,
+ fontFamily: 'DMSans_600SemiBold',
+ },
+});
diff --git a/src/components/ui/input.tsx b/src/components/ui/input.tsx
new file mode 100644
index 0000000..25728df
--- /dev/null
+++ b/src/components/ui/input.tsx
@@ -0,0 +1,98 @@
+import React, { forwardRef, useState } from 'react';
+import {
+ StyleSheet,
+ Text,
+ TextInput,
+ type TextInputProps,
+ View,
+} from 'react-native';
+import { Colors, Radius, Spacing, Typography } from '@/constants/theme';
+
+interface InputProps extends TextInputProps {
+ label: string;
+ error?: string;
+ hint?: string;
+ prefix?: string;
+}
+
+export const Input = forwardRef<TextInput, InputProps>(function Input(
+ { label, error, hint, prefix, style, ...rest },
+ ref,
+) {
+ const [focused, setFocused] = useState(false);
+
+ return (
+ <View style={styles.wrapper}>
+ <Text style={styles.label}>{label}</Text>
+ <View
+ style={[
+ styles.inputRow,
+ focused && styles.inputRowFocused,
+ !!error && styles.inputRowError,
+ ]}
+ >
+ {prefix ? <Text style={styles.prefix}>{prefix}</Text> : null}
+ <TextInput
+ ref={ref}
+ style={[styles.input, style]}
+ placeholderTextColor={Colors.textMuted}
+ onFocus={() => setFocused(true)}
+ onBlur={() => setFocused(false)}
+ selectionColor={Colors.primaryLight}
+ {...rest}
+ />
+ </View>
+ {error ? (
+ <Text style={styles.error}>{error}</Text>
+ ) : hint ? (
+ <Text style={styles.hint}>{hint}</Text>
+ ) : null}
+ </View>
+ );
+});
+
+const styles = StyleSheet.create({
+ wrapper: {
+ gap: Spacing.xs,
+ },
+ label: {
+ ...Typography.caption,
+ color: Colors.textSecondary,
+ textTransform: 'uppercase',
+ letterSpacing: 1,
+ },
+ inputRow: {
+ flexDirection: 'row',
+ alignItems: 'center',
+ backgroundColor: Colors.surfaceElevated,
+ borderRadius: Radius.md,
+ borderWidth: 1,
+ borderColor: Colors.border,
+ paddingHorizontal: Spacing.md,
+ height: 52,
+ },
+ inputRowFocused: {
+ borderColor: Colors.primaryLight,
+ },
+ inputRowError: {
+ borderColor: Colors.negative,
+ },
+ prefix: {
+ ...Typography.bodyLarge,
+ color: Colors.textSecondary,
+ marginRight: Spacing.sm,
+ },
+ input: {
+ flex: 1,
+ ...Typography.bodyLarge,
+ color: Colors.textPrimary,
+ },
+ error: {
+ ...Typography.caption,
+ color: Colors.negative,
+ },
+ hint: {
+ ...Typography.caption,
+ color: Colors.textMuted,
+ },
+});
diff --git a/src/components/ui/options-modal.tsx b/src/components/ui/options-modal.tsx
new file mode 100644
index 0000000..8d5d984
--- /dev/null
+++ b/src/components/ui/options-modal.tsx
@@ -0,0 +1,137 @@
+import React from 'react';
+import { Modal, StyleSheet, Text, TouchableOpacity, View } from 'react-native';
+import { BlurView } from 'expo-blur';
+import Animated, { FadeIn, FadeInDown, FadeOut, FadeOutDown } from 'react-native-reanimated';
+import { Feather } from '@expo/vector-icons';
+import { Colors, Radius, Spacing, Typography } from '@/constants/theme';
+
+export interface MenuOption {
+ label: string;
+ icon?: keyof typeof Feather.glyphMap;
+ destructive?: boolean;
+ onPress: () => void;
+}
+
+interface OptionsModalProps {
+ visible: boolean;
+ title?: string;
+ options: MenuOption[];
+ onClose: () => void;
+}
+
+export function OptionsModal({ visible, title, options, onClose }: OptionsModalProps) {
+ if (!visible) return null;
+
+ return (
+ <Modal visible={visible} transparent animationType="none" onRequestClose={onClose}>
+ <Animated.View entering={FadeIn.duration(200)} exiting={FadeOut.duration(200)} style={styles.overlay}>
+ <TouchableOpacity style={styles.backdrop} activeOpacity={1} onPress={onClose} />
+
+ <Animated.View entering={FadeInDown.duration(300).springify()} exiting={FadeOutDown.duration(200)} style={styles.modalContainer}>
+ <BlurView intensity={80} tint="dark" style={styles.blurView}>
+ <View style={styles.content}>
+ {title && <Text style={styles.title}>{title}</Text>}
+
+ <View style={styles.optionsList}>
+ {options.map((option, index) => (
+ <TouchableOpacity
+ key={index}
+ style={[styles.optionButton, index < options.length - 1 && styles.optionBorder]}
+ onPress={() => {
+ onClose();
+ setTimeout(option.onPress, 50);
+ }}
+ >
+ {option.icon && (
+ <Feather
+ name={option.icon}
+ size={20}
+ color={option.destructive ? Colors.negative : Colors.textPrimary}
+ style={styles.optionIcon}
+ />
+ )}
+ <Text style={[styles.optionText, option.destructive && styles.optionTextDestructive]}>
+ {option.label}
+ </Text>
+ </TouchableOpacity>
+ ))}
+ </View>
+
+ <TouchableOpacity style={styles.cancelButton} onPress={onClose}>
+ <Text style={styles.cancelText}>Cancelar</Text>
+ </TouchableOpacity>
+ </View>
+ </BlurView>
+ </Animated.View>
+ </Animated.View>
+ </Modal>
+ );
+}
+
+const styles = StyleSheet.create({
+ overlay: {
+ flex: 1,
+ justifyContent: 'flex-end',
+ backgroundColor: 'rgba(0, 0, 0, 0.4)',
+ },
+ backdrop: {
+ ...StyleSheet.absoluteFill,
+ },
+ modalContainer: {
+ padding: Spacing.md,
+ paddingBottom: Spacing.xxl,
+ },
+ blurView: {
+ borderRadius: Radius.lg,
+ overflow: 'hidden',
+ borderWidth: 1,
+ borderColor: 'rgba(255, 255, 255, 0.08)',
+ },
+ content: {
+ padding: Spacing.md,
+ gap: Spacing.md,
+ backgroundColor: 'rgba(22, 27, 34, 0.6)',
+ },
+ title: {
+ ...Typography.body,
+ color: Colors.textSecondary,
+ textAlign: 'center',
+ marginBottom: Spacing.xs,
+ },
+ optionsList: {
+ backgroundColor: 'rgba(255,255,255,0.05)',
+ borderRadius: Radius.md,
+ overflow: 'hidden',
+ },
+ optionButton: {
+ flexDirection: 'row',
+ alignItems: 'center',
+ padding: Spacing.md,
+ backgroundColor: 'transparent',
+ },
+ optionBorder: {
+ borderBottomWidth: 1,
+ borderBottomColor: 'rgba(255,255,255,0.05)',
+ },
+ optionIcon: {
+ marginRight: Spacing.sm,
+ },
+ optionText: {
+ ...Typography.bodyLarge,
+ color: Colors.textPrimary,
+ },
+ optionTextDestructive: {
+ color: Colors.negative,
+ },
+ cancelButton: {
+ padding: Spacing.md,
+ backgroundColor: 'rgba(255,255,255,0.1)',
+ borderRadius: Radius.md,
+ alignItems: 'center',
+ },
+ cancelText: {
+ ...Typography.bodyLarge,
+ color: Colors.textPrimary,
+ fontFamily: 'DMSans_600SemiBold',
+ },
+});
diff --git a/src/components/ui/primitives.tsx b/src/components/ui/primitives.tsx
new file mode 100644
index 0000000..d598bd2
--- /dev/null
+++ b/src/components/ui/primitives.tsx
@@ -0,0 +1,104 @@
+import React from 'react';
+import { StyleSheet, Text, View } from 'react-native';
+import { Colors, Radius, Shadow, Spacing, Typography } from '@/constants/theme';
+
+interface CardProps {
+ children: React.ReactNode;
+ style?: object;
+}
+
+export function Card({ children, style }: CardProps) {
+ return <View style={[styles.card, style]}>{children}</View>;
+}
+
+interface LabelProps {
+ text: string;
+ color?: string;
+}
+
+export function SectionLabel({ text, color = Colors.textSecondary }: LabelProps) {
+ return <Text style={[styles.label, { color }]}>{text}</Text>;
+}
+
+interface CurrencyDisplayProps {
+ amount: number;
+ size?: 'display' | 'large' | 'normal';
+ showSign?: boolean;
+}
+
+export function CurrencyDisplay({
+ amount,
+ size = 'normal',
+ showSign = false,
+}: CurrencyDisplayProps) {
+ const isNegative = amount < 0;
+ const color = isNegative ? Colors.negative : Colors.positive;
+ const formatted = Math.abs(amount).toLocaleString('pt-BR', {
+ minimumFractionDigits: 2,
+ maximumFractionDigits: 2,
+ });
+ const sign = showSign ? (isNegative ? '- ' : '+ ') : '';
+
+ const textStyle =
+ size === 'display'
+ ? styles.displayAmount
+ : size === 'large'
+ ? styles.largeAmount
+ : styles.normalAmount;
+
+ return (
+ <View style={styles.currencyRow}>
+ <Text style={[styles.currencyPrefix, { color }]}>
+ {sign}R${' '}
+ </Text>
+ <Text style={[textStyle, { color }]}>{formatted}</Text>
+ </View>
+ );
+}
+
+interface DividerProps {
+ style?: object;
+}
+
+export function Divider({ style }: DividerProps) {
+ return <View style={[styles.divider, style]} />;
+}
+
+const styles = StyleSheet.create({
+ card: {
+ backgroundColor: Colors.surface,
+ borderRadius: Radius.lg,
+ padding: Spacing.lg,
+ borderWidth: 1,
+ borderColor: Colors.border,
+ ...Shadow.card,
+ },
+ label: {
+ ...Typography.caption,
+ textTransform: 'uppercase',
+ letterSpacing: 1.2,
+ },
+ currencyRow: {
+ flexDirection: 'row',
+ alignItems: 'flex-end',
+ },
+ currencyPrefix: {
+ ...Typography.currencyLabel,
+ paddingBottom: 4,
+ },
+ displayAmount: {
+ ...Typography.display,
+ },
+ largeAmount: {
+ ...Typography.h1,
+ },
+ normalAmount: {
+ ...Typography.bodyLarge,
+ fontFamily: 'DMSans_600SemiBold',
+ },
+ divider: {
+ height: 1,
+ backgroundColor: Colors.border,
+ marginVertical: Spacing.md,
+ },
+});
diff --git a/src/constants/theme.ts b/src/constants/theme.ts
new file mode 100644
index 0000000..880e3d8
--- /dev/null
+++ b/src/constants/theme.ts
@@ -0,0 +1,99 @@
+export const Colors = {
+ background: '#0D1117',
+ surface: '#161B22',
+ surfaceElevated: '#1C2333',
+ border: '#2A3444',
+
+ primary: '#1A6B3C',
+ primaryLight: '#24A55A',
+ accent: '#C9A84C',
+
+ positive: '#24A55A',
+ negative: '#E05252',
+ warning: '#E0A84C',
+
+ textPrimary: '#E6EDF3',
+ textSecondary: '#8B949E',
+ textMuted: '#484F58',
+ textOnPrimary: '#FFFFFF',
+
+ white: '#FFFFFF',
+ transparent: 'transparent',
+} as const;
+
+export const Typography = {
+ display: {
+ fontFamily: 'DMSans_700Bold',
+ fontSize: 52,
+ lineHeight: 60,
+ letterSpacing: -1.5,
+ },
+ h1: {
+ fontFamily: 'DMSans_700Bold',
+ fontSize: 28,
+ lineHeight: 34,
+ letterSpacing: -0.5,
+ },
+ h2: {
+ fontFamily: 'DMSans_600SemiBold',
+ fontSize: 20,
+ lineHeight: 26,
+ letterSpacing: -0.3,
+ },
+ bodyLarge: {
+ fontFamily: 'DMSans_400Regular',
+ fontSize: 17,
+ lineHeight: 24,
+ },
+ body: {
+ fontFamily: 'DMSans_400Regular',
+ fontSize: 15,
+ lineHeight: 22,
+ },
+ caption: {
+ fontFamily: 'DMSans_400Regular',
+ fontSize: 12,
+ lineHeight: 16,
+ letterSpacing: 0.3,
+ },
+ currencyLabel: {
+ fontFamily: 'DMSans_300Light',
+ fontSize: 24,
+ lineHeight: 32,
+ letterSpacing: -0.5,
+ },
+} as const;
+
+export const Spacing = {
+ xs: 4,
+ sm: 8,
+ md: 16,
+ lg: 24,
+ xl: 32,
+ xxl: 48,
+} as const;
+
+export const Radius = {
+ sm: 8,
+ md: 12,
+ lg: 16,
+ xl: 24,
+ full: 9999,
+} as const;
+
+export const Shadow = {
+ card: {
+ shadowColor: '#000',
+ shadowOffset: { width: 0, height: 4 },
+ shadowOpacity: 0.3,
+ shadowRadius: 8,
+ elevation: 8,
+ },
+ glow: {
+ shadowColor: Colors.primary,
+ shadowOffset: { width: 0, height: 0 },
+ shadowOpacity: 0.4,
+ shadowRadius: 16,
+ elevation: 12,
+ },
+} as const;
diff --git a/src/contexts/AuthContext.tsx b/src/contexts/AuthContext.tsx
new file mode 100644
index 0000000..d2fd7a9
--- /dev/null
+++ b/src/contexts/AuthContext.tsx
@@ -0,0 +1,107 @@
+import { User } from '@/types';
+import React, { createContext, useContext, useEffect, useState } from 'react';
+import * as SecureStore from 'expo-secure-store';
+import * as LocalAuthentication from 'expo-local-authentication';
+import { apiLogin, apiRegister, LoginPayload, RegisterPayload, setApiToken } from '@/services/api';
+
+interface AuthContextData {
+ user: User | null;
+ token: string | null;
+ isLoading: boolean;
+ login: (data: LoginPayload) => Promise<void>;
+ register: (data: RegisterPayload) => Promise<void>;
+ logout: () => Promise<void>;
+ updateUser: (newUser: User) => Promise<void>;
+}
+
+const AuthContext = createContext<AuthContextData>({} as AuthContextData);
+
+export function AuthProvider({ children }: { children: React.ReactNode }) {
+ const [user, setUser] = useState<User | null>(null);
+ const [token, setToken] = useState<string | null>(null);
+ const [isLoading, setIsLoading] = useState<boolean>(true);
+
+ useEffect(() => {
+ async function loadStorageData() {
+ try {
+ const storedToken = await SecureStore.getItemAsync('yaba_token');
+ const storedUser = await SecureStore.getItemAsync('yaba_user');
+ const useBiometrics = await SecureStore.getItemAsync('yaba_use_biometrics');
+
+ if (storedToken && storedUser) {
+ let authenticated = true;
+
+ if (useBiometrics === 'true') {
+ const hasHardware = await LocalAuthentication.hasHardwareAsync();
+ const isEnrolled = await LocalAuthentication.isEnrolledAsync();
+
+ if (hasHardware && isEnrolled) {
+ const result = await LocalAuthentication.authenticateAsync({
+ promptMessage: 'Use sua digital para continuar',
+ fallbackLabel: 'Usar senha',
+ });
+
+ authenticated = result.success;
+ }
+ }
+
+ if (authenticated) {
+ setApiToken(storedToken);
+ setToken(storedToken);
+ setUser(JSON.parse(storedUser));
+ } else {
+ await SecureStore.deleteItemAsync('yaba_token');
+ await SecureStore.deleteItemAsync('yaba_user');
+ }
+ }
+ } catch (error) {
+ console.error('Error loading storage data:', error);
+ } finally {
+ setIsLoading(false);
+ }
+ }
+
+ loadStorageData();
+ }, []);
+
+ async function login(data: LoginPayload) {
+ const res = await apiLogin(data);
+ await SecureStore.setItemAsync('yaba_token', res.token);
+ await SecureStore.setItemAsync('yaba_user', JSON.stringify(res.user));
+ setApiToken(res.token);
+ setToken(res.token);
+ setUser(res.user);
+ }
+
+ async function register(data: RegisterPayload) {
+ const res = await apiRegister(data);
+ await SecureStore.setItemAsync('yaba_token', res.token);
+ await SecureStore.setItemAsync('yaba_user', JSON.stringify(res.user));
+ setApiToken(res.token);
+ setToken(res.token);
+ setUser(res.user);
+ }
+
+ async function logout() {
+ await SecureStore.deleteItemAsync('yaba_token');
+ await SecureStore.deleteItemAsync('yaba_user');
+ setApiToken(null);
+ setToken(null);
+ setUser(null);
+ }
+
+ async function updateUser(newUser: User) {
+ await SecureStore.setItemAsync('yaba_user', JSON.stringify(newUser));
+ setUser(newUser);
+ }
+
+ return (
+ <AuthContext.Provider value={{ user, token, isLoading, login, register, logout, updateUser }}>
+ {children}
+ </AuthContext.Provider>
+ );
+}
+
+export function useAuth() {
+ return useContext(AuthContext);
+} \ No newline at end of file
diff --git a/src/global.css b/src/global.css
new file mode 100644
index 0000000..c8fe503
--- /dev/null
+++ b/src/global.css
@@ -0,0 +1,9 @@
+:root {
+ --font-display:
+ Spline Sans, Inter, ui-sans-serif, system-ui, sans-serif, Apple Color Emoji, Segoe UI Emoji,
+ Segoe UI Symbol, Noto Color Emoji;
+ --font-mono:
+ ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, Liberation Mono, Courier New, monospace;
+ --font-rounded: 'SF Pro Rounded', 'Hiragino Maru Gothic ProN', Meiryo, 'MS PGothic', sans-serif;
+ --font-serif: Georgia, 'Times New Roman', serif;
+}
diff --git a/src/hooks/use-app-hooks.ts b/src/hooks/use-app-hooks.ts
new file mode 100644
index 0000000..f10d1ef
--- /dev/null
+++ b/src/hooks/use-app-hooks.ts
@@ -0,0 +1,20 @@
+import { useFonts } from 'expo-font';
+import { DMSans_300Light, DMSans_400Regular, DMSans_600SemiBold, DMSans_700Bold } from '@expo-google-fonts/dm-sans';
+import { calcularSalarioLiquido, type ResultadoCalculo } from '@/utils/tax-calculator';
+
+export function useAppFonts() {
+ const [loaded, error] = useFonts({
+ DMSans_300Light,
+ DMSans_400Regular,
+ DMSans_600SemiBold,
+ DMSans_700Bold,
+ });
+
+ return { fontsLoaded: loaded, fontsError: error };
+}
+
+export function useSalaryCalculator(grossSalaryStr: string): ResultadoCalculo | null {
+ const value = parseFloat(grossSalaryStr.replace(',', '.'));
+ if (isNaN(value) || value <= 0) return null;
+ return calcularSalarioLiquido(value);
+} \ No newline at end of file
diff --git a/src/screens/dashboard-screen.tsx b/src/screens/dashboard-screen.tsx
new file mode 100644
index 0000000..c4a533c
--- /dev/null
+++ b/src/screens/dashboard-screen.tsx
@@ -0,0 +1,440 @@
+import React, { useCallback, useState } from 'react';
+import {
+ ActivityIndicator,
+ RefreshControl,
+ ScrollView,
+ StyleSheet,
+ Text,
+ TouchableOpacity,
+ View,
+} from 'react-native';
+import { Feather } from '@expo/vector-icons';
+import { LinearGradient } from 'expo-linear-gradient';
+import Animated, {
+ FadeInDown,
+ FadeInUp,
+ LinearTransition,
+} from 'react-native-reanimated';
+import { useSafeAreaInsets } from 'react-native-safe-area-context';
+import { Card, CurrencyDisplay, Divider, SectionLabel } from '@/components/ui/primitives';
+import { ExpensesChart } from '@/components/ui/expenses-chart';
+import { Colors, Spacing, Typography } from '@/constants/theme';
+import { getDashboard } from '@/services/api';
+import type { DashboardData } from '@/types';
+import { useAuth } from '@/contexts/AuthContext';
+import { useRouter, useFocusEffect } from 'expo-router';
+import { useIsFocused } from "expo-router/react-navigation";
+
+const MONTH_NAMES = [
+ '', 'Janeiro', 'Fevereiro', 'Março', 'Abril', 'Maio', 'Junho',
+ 'Julho', 'Agosto', 'Setembro', 'Outubro', 'Novembro', 'Dezembro',
+];
+
+export default function DashboardScreen() {
+ const insets = useSafeAreaInsets();
+ const [refreshing, setRefreshing] = useState(false);
+ const [data, setData] = useState<DashboardData | null>(null);
+ const [loading, setLoading] = useState(true);
+ const [error, setError] = useState<string | null>(null);
+ const { user, logout } = useAuth();
+ const router = useRouter();
+ const isFocused = useIsFocused();
+
+ const [targetMonth, setTargetMonth] = useState(() => new Date().getMonth() + 1);
+ const [targetYear, setTargetYear] = useState(() => new Date().getFullYear());
+
+ const fetchDashboard = useCallback(async () => {
+ if (!user) return;
+ try {
+ setError(null);
+ const res = await getDashboard(user.id, targetMonth, targetYear);
+ setData(res);
+ } catch (err) {
+ setError('Não foi possível carregar os dados.');
+ } finally {
+ setLoading(false);
+ }
+ }, [targetMonth, targetYear, user]);
+
+ useFocusEffect(
+ useCallback(() => {
+ fetchDashboard();
+ }, [fetchDashboard])
+ );
+
+ async function handleRefresh() {
+ setRefreshing(true);
+ await fetchDashboard();
+ setRefreshing(false);
+ }
+
+ if (loading) {
+ return (
+ <View style={[styles.container, styles.centered]}>
+ <ActivityIndicator size="large" color={Colors.primary} />
+ </View>
+ );
+ }
+
+ if (error || !data) {
+ return (
+ <View style={[styles.container, styles.centered]}>
+ <Text style={styles.errorText}>{error}</Text>
+ </View>
+ );
+ }
+
+ const isPositive = data.balance.available >= 0;
+ const monthName = MONTH_NAMES[data.period.month];
+
+ return (
+ <View style={[styles.container, { paddingTop: insets.top }]}>
+ <LinearGradient
+ colors={['#0D2818', Colors.background]}
+ style={styles.headerGradient}
+ start={{ x: 0, y: 0 }}
+ end={{ x: 0, y: 1 }}
+ />
+
+ {isFocused && (
+ <ScrollView
+ contentContainerStyle={[styles.scroll, { paddingBottom: insets.bottom + 80 }]}
+ showsVerticalScrollIndicator={false}
+ refreshControl={
+ <RefreshControl
+ refreshing={refreshing}
+ onRefresh={handleRefresh}
+ tintColor={Colors.primaryLight}
+ />
+ }
+ >
+ <Animated.View entering={FadeInUp.duration(500)} style={styles.headerTop}>
+ <View style={styles.greeting}>
+ <Text style={styles.greetingText}>Olá, {data.user.name} 👋</Text>
+
+ <View style={styles.monthSelector}>
+ <TouchableOpacity
+ onPress={() => {
+ let m = targetMonth - 1;
+ let y = targetYear;
+ if (m < 1) { m = 12; y -= 1; }
+ setTargetMonth(m);
+ setTargetYear(y);
+ setLoading(true);
+ }}
+ style={styles.monthButton}
+ >
+ <Feather name="chevron-left" size={20} color={Colors.textSecondary} />
+ </TouchableOpacity>
+
+ <Text style={styles.periodText}>
+ {monthName} {data.period.year}
+ </Text>
+
+ <TouchableOpacity
+ onPress={() => {
+ let m = targetMonth + 1;
+ let y = targetYear;
+ if (m > 12) { m = 1; y += 1; }
+ setTargetMonth(m);
+ setTargetYear(y);
+ setLoading(true);
+ }}
+ style={styles.monthButton}
+ >
+ <Feather name="chevron-right" size={20} color={Colors.textSecondary} />
+ </TouchableOpacity>
+ </View>
+ </View>
+
+ <TouchableOpacity
+ style={styles.logoutBtn}
+ onPress={async () => {
+ await logout();
+ router.replace('/login');
+ }}
+ >
+ <Feather name="log-out" size={20} color={Colors.textSecondary} />
+ </TouchableOpacity>
+ </Animated.View>
+
+ <Animated.View entering={FadeInUp.delay(100).duration(500)} layout={LinearTransition.springify()}>
+ <Card style={[styles.heroCard, isPositive ? styles.heroPositive : styles.heroNegative]}>
+ <SectionLabel
+ text="Saldo Disponível"
+ color={isPositive ? Colors.positive : Colors.negative}
+ />
+ <View style={styles.heroBalance}>
+ <CurrencyDisplay amount={data.balance.available} size="display" />
+ </View>
+
+ <View style={styles.ratioSection}>
+ <View style={styles.ratioBar}>
+ <View
+ style={[
+ styles.ratioFill,
+ {
+ width: `${Math.min(data.balance.expense_ratio, 100)}%` as `${number}%`,
+ backgroundColor:
+ data.balance.expense_ratio > 80 ? Colors.negative : Colors.primary,
+ },
+ ]}
+ />
+ </View>
+ <Text style={styles.ratioText}>
+ {data.balance.expense_ratio.toFixed(1)}% do salário comprometido
+ </Text>
+ </View>
+ </Card>
+ </Animated.View>
+
+ <Animated.View entering={FadeInDown.delay(200).duration(500)} layout={LinearTransition.springify()}>
+ <Card style={styles.card}>
+ <SectionLabel text="Salário" />
+ <View style={styles.salaryRow}>
+ <View style={styles.salaryItem}>
+ <Text style={styles.salaryLabel}>Bruto</Text>
+ <Text style={styles.salaryValue}>
+ {data.salary.gross.toLocaleString('pt-BR', {
+ style: 'currency',
+ currency: 'BRL',
+ minimumFractionDigits: 0,
+ })}
+ </Text>
+ </View>
+ <View style={styles.salaryArrow}>
+ <Text style={styles.salaryArrowText}>→</Text>
+ </View>
+ <View style={styles.salaryItem}>
+ <Text style={styles.salaryLabel}>Líquido</Text>
+ <Text style={[styles.salaryValue, { color: Colors.positive }]}>
+ {data.salary.effective_net.toLocaleString('pt-BR', {
+ style: 'currency',
+ currency: 'BRL',
+ minimumFractionDigits: 0,
+ })}
+ </Text>
+ </View>
+ </View>
+ <Divider />
+ <View style={styles.taxRow}>
+ <Text style={styles.taxLabel}>INSS</Text>
+ <Text style={styles.taxValue}>
+ -{data.salary.inss_discount.toLocaleString('pt-BR', {
+ style: 'currency',
+ currency: 'BRL',
+ })}
+ </Text>
+ </View>
+ <View style={styles.taxRow}>
+ <Text style={styles.taxLabel}>IRRF</Text>
+ <Text style={styles.taxValue}>
+ -{data.salary.irrf_discount.toLocaleString('pt-BR', {
+ style: 'currency',
+ currency: 'BRL',
+ })}
+ </Text>
+ </View>
+ </Card>
+ </Animated.View>
+
+ <Animated.View entering={FadeInDown.delay(250).duration(500)} layout={LinearTransition.springify()}>
+ <ExpensesChart
+ recurring={data.expenses.recurring_list}
+ oneTime={data.expenses.one_time_list}
+ />
+ </Animated.View>
+
+ <Animated.View entering={FadeInDown.delay(300).duration(500)} layout={LinearTransition.springify()}>
+ <Card style={styles.card}>
+ <View style={[styles.sectionHeader, { marginBottom: 0 }]}>
+ <SectionLabel text="Lançamentos Fixos" />
+ <Text
+ style={[
+ styles.totalBadge,
+ data.expenses.recurring_total < 0 ? { color: Colors.positive } : { color: Colors.negative }
+ ]}
+ >
+ {data.expenses.recurring_total < 0 ? '+ ' : (data.expenses.recurring_total > 0 ? '- ' : '')}
+ {Math.abs(data.expenses.recurring_total).toLocaleString('pt-BR', {
+ style: 'currency',
+ currency: 'BRL',
+ minimumFractionDigits: 0,
+ })}
+ </Text>
+ </View>
+ </Card>
+ </Animated.View>
+
+ <Animated.View entering={FadeInDown.delay(400).duration(500)} layout={LinearTransition.springify()}>
+ <Card style={styles.card}>
+ <View style={[styles.sectionHeader, { marginBottom: 0 }]}>
+ <SectionLabel text="Lançamentos do Mês" />
+ <Text
+ style={[
+ styles.totalBadge,
+ data.expenses.one_time_total < 0 ? { color: Colors.positive } : { color: Colors.negative }
+ ]}
+ >
+ {data.expenses.one_time_total < 0 ? '+ ' : (data.expenses.one_time_total > 0 ? '- ' : '')}
+ {Math.abs(data.expenses.one_time_total).toLocaleString('pt-BR', {
+ style: 'currency',
+ currency: 'BRL',
+ minimumFractionDigits: 0,
+ })}
+ </Text>
+ </View>
+ </Card>
+ </Animated.View>
+ </ScrollView>
+ )}
+ </View>
+ );
+}
+
+const styles = StyleSheet.create({
+ container: {
+ flex: 1,
+ backgroundColor: Colors.background,
+ },
+ centered: {
+ justifyContent: 'center',
+ alignItems: 'center',
+ },
+ errorText: {
+ ...Typography.body,
+ color: Colors.negative,
+ },
+ headerGradient: {
+ position: 'absolute',
+ top: 0,
+ left: 0,
+ right: 0,
+ height: 200,
+ },
+ scroll: {
+ padding: Spacing.md,
+ gap: Spacing.md,
+ },
+ headerTop: {
+ flexDirection: 'row',
+ justifyContent: 'space-between',
+ alignItems: 'flex-start',
+ paddingVertical: Spacing.sm,
+ },
+ greeting: {
+ flex: 1,
+ },
+ logoutBtn: {
+ padding: 8,
+ backgroundColor: 'rgba(255,255,255,0.05)',
+ borderRadius: 12,
+ },
+ greetingText: {
+ ...Typography.h2,
+ color: Colors.textPrimary,
+ },
+ periodText: {
+ ...Typography.caption,
+ color: Colors.textSecondary,
+ textTransform: 'uppercase',
+ letterSpacing: 1.5,
+ },
+ monthSelector: {
+ flexDirection: 'row',
+ alignItems: 'center',
+ marginTop: 6,
+ gap: Spacing.xs,
+ },
+ monthButton: {
+ padding: 4,
+ },
+ card: {
+ gap: Spacing.sm,
+ },
+ heroCard: {
+ gap: Spacing.md,
+ borderWidth: 1,
+ },
+ heroPositive: {
+ borderColor: `${Colors.positive}40`,
+ },
+ heroNegative: {
+ borderColor: `${Colors.negative}40`,
+ },
+ heroBalance: {
+ marginTop: Spacing.xs,
+ },
+ ratioSection: {
+ gap: Spacing.xs,
+ },
+ ratioBar: {
+ height: 4,
+ backgroundColor: Colors.border,
+ borderRadius: 2,
+ overflow: 'hidden',
+ },
+ ratioFill: {
+ height: '100%',
+ borderRadius: 2,
+ },
+ ratioText: {
+ ...Typography.caption,
+ color: Colors.textMuted,
+ },
+ salaryRow: {
+ flexDirection: 'row',
+ alignItems: 'center',
+ justifyContent: 'space-between',
+ marginTop: Spacing.sm,
+ },
+ salaryItem: {
+ flex: 1,
+ gap: 4,
+ },
+ salaryLabel: {
+ ...Typography.caption,
+ color: Colors.textMuted,
+ textTransform: 'uppercase',
+ letterSpacing: 1,
+ },
+ salaryValue: {
+ ...Typography.h2,
+ color: Colors.textPrimary,
+ },
+ salaryArrow: {
+ paddingHorizontal: Spacing.md,
+ },
+ salaryArrowText: {
+ ...Typography.h2,
+ color: Colors.textMuted,
+ },
+ taxRow: {
+ flexDirection: 'row',
+ justifyContent: 'space-between',
+ alignItems: 'center',
+ },
+ taxLabel: {
+ ...Typography.body,
+ color: Colors.textSecondary,
+ },
+ taxValue: {
+ ...Typography.body,
+ color: Colors.negative,
+ fontFamily: 'DMSans_600SemiBold',
+ },
+ sectionHeader: {
+ flexDirection: 'row',
+ justifyContent: 'space-between',
+ alignItems: 'center',
+ marginBottom: Spacing.xs,
+ },
+ totalBadge: {
+ ...Typography.body,
+ color: Colors.negative,
+ fontFamily: 'DMSans_600SemiBold',
+ },
+ rowDivider: {
+ marginVertical: 0,
+ },
+});
diff --git a/src/screens/one-time-expenses-screen.tsx b/src/screens/one-time-expenses-screen.tsx
new file mode 100644
index 0000000..c84a39f
--- /dev/null
+++ b/src/screens/one-time-expenses-screen.tsx
@@ -0,0 +1,485 @@
+import React, { useCallback, useState } from 'react';
+import {
+ Alert,
+ ScrollView,
+ StyleSheet,
+ Text,
+ TouchableOpacity,
+ View,
+} from 'react-native';
+import Animated, { FadeInDown, LinearTransition } from 'react-native-reanimated';
+import { useSafeAreaInsets } from 'react-native-safe-area-context';
+import * as Haptics from 'expo-haptics';
+import { Button } from '@/components/ui/button';
+import { Input } from '@/components/ui/input';
+import { Card, Divider, SectionLabel } from '@/components/ui/primitives';
+import { OneTimeExpenseRow } from '@/components/expense-row';
+import { Colors, Radius, Spacing, Typography } from '@/constants/theme';
+import type { Category, OneTimeExpense } from '@/types';
+import {
+ createOneTimeExpense,
+ updateOneTimeExpense,
+ deleteOneTimeExpense,
+ getOneTimeExpenses,
+} from '@/services/api';
+import { useAuth } from '@/contexts/AuthContext';
+import { ActionModal } from '@/components/ui/action-modal';
+import { OptionsModal } from '@/components/ui/options-modal';
+import { useFocusEffect } from 'expo-router';
+import { useIsFocused } from "expo-router/react-navigation";
+
+const CATEGORIES: { value: Category; emoji: string; label: string }[] = [
+ { value: 'alimentação', emoji: '🍽️', label: 'Alimentação' },
+ { value: 'lazer', emoji: '🎬', label: 'Lazer' },
+ { value: 'transporte', emoji: '🚗', label: 'Transporte' },
+ { value: 'saúde', emoji: '💊', label: 'Saúde' },
+ { value: 'moradia', emoji: '🏠', label: 'Moradia' },
+ { value: 'educação', emoji: '📚', label: 'Educação' },
+ { value: 'serviços', emoji: '⚙️', label: 'Serviços' },
+ { value: 'outros', emoji: '📦', label: 'Outros' },
+];
+
+export default function OneTimeExpensesScreen() {
+ const insets = useSafeAreaInsets();
+ const { user } = useAuth();
+ const [expenses, setExpenses] = useState<OneTimeExpense[]>([]);
+ const [showForm, setShowForm] = useState(false);
+ const [loading, setLoading] = useState(true);
+
+ const [name, setName] = useState('');
+ const [amount, setAmount] = useState('');
+ const [selectedCategory, setSelectedCategory] = useState<Category>('outros');
+ const [expenseType, setExpenseType] = useState<'expense' | 'income'>('expense');
+ const [notes, setNotes] = useState('');
+ const [isSubmitting, setIsSubmitting] = useState(false);
+
+ const [expenseToDelete, setExpenseToDelete] = useState<number | null>(null);
+ const [selectedExpense, setSelectedExpense] = useState<OneTimeExpense | null>(null);
+ const [editingExpenseId, setEditingExpenseId] = useState<number | null>(null);
+
+ const isFocused = useIsFocused();
+
+ const fetchExpenses = useCallback(async () => {
+ if (!user) return;
+ try {
+ setLoading(true);
+ const data = await getOneTimeExpenses(user.id);
+ setExpenses(data);
+ } catch (err) {
+ Alert.alert('Erro', 'Não foi possível carregar os gastos do mês.');
+ } finally {
+ setLoading(false);
+ }
+ }, [user]);
+
+ useFocusEffect(
+ useCallback(() => {
+ fetchExpenses();
+ }, [fetchExpenses])
+ );
+
+ const monthTotal = expenses.reduce((sum, e) => {
+ return sum + (e.type === 'income' ? -e.amount : e.amount);
+ }, 0);
+ const isTotalIncome = monthTotal < 0;
+ const absTotal = Math.abs(monthTotal);
+ const formattedTotal = absTotal.toLocaleString('pt-BR', {
+ style: 'currency',
+ currency: 'BRL',
+ });
+
+ async function handleAdd() {
+ const amountNum = parseFloat(amount.replace(',', '.'));
+ if (!name.trim() || isNaN(amountNum) || amountNum <= 0) {
+ Alert.alert('Dados inválidos', 'Preencha o nome e um valor válido.');
+ return;
+ }
+
+ try {
+ if (!user) return;
+ setIsSubmitting(true);
+
+ if (editingExpenseId) {
+ const updated = await updateOneTimeExpense(user.id, editingExpenseId, {
+ name: name.trim(),
+ amount: amountNum,
+ category: selectedCategory,
+ type: expenseType,
+ notes: notes.trim() || null,
+ });
+ setExpenses((prev) => prev.map((e) => e.id === editingExpenseId ? updated : e));
+ Haptics.notificationAsync(Haptics.NotificationFeedbackType.Success);
+ } else {
+ const today = new Date().toISOString().split('T')[0];
+ const newExpense = await createOneTimeExpense(user.id, {
+ name: name.trim(),
+ amount: amountNum,
+ category: selectedCategory,
+ type: expenseType,
+ expense_date: today,
+ notes: notes.trim() || null,
+ });
+ setExpenses((prev) => [...prev, newExpense]);
+ Haptics.notificationAsync(Haptics.NotificationFeedbackType.Success);
+ }
+
+ setName('');
+ setAmount('');
+ setNotes('');
+ setExpenseType('expense');
+ setShowForm(false);
+ setEditingExpenseId(null);
+ } catch (err) {
+ Alert.alert('Erro', 'Não foi possível salvar o lançamento.');
+ } finally {
+ setIsSubmitting(false);
+ }
+ }
+
+ function handleDelete(id: number) {
+ setExpenseToDelete(id);
+ setSelectedExpense(null);
+ }
+
+ function handleEdit(expense: OneTimeExpense) {
+ setName(expense.name);
+ setAmount(expense.amount.toString());
+ setSelectedCategory(expense.category);
+ setExpenseType(expense.type);
+ setNotes(expense.notes || '');
+ setEditingExpenseId(expense.id);
+ setSelectedExpense(null);
+ setShowForm(true);
+ }
+
+ async function confirmDelete() {
+ if (!user || expenseToDelete === null) return;
+ Haptics.impactAsync(Haptics.ImpactFeedbackStyle.Medium);
+ try {
+ await deleteOneTimeExpense(user.id, expenseToDelete);
+ setExpenses((prev) => prev.filter((e) => e.id !== expenseToDelete));
+ } catch (err) {
+ Alert.alert('Erro', 'Não foi possível remover o lançamento.');
+ } finally {
+ setExpenseToDelete(null);
+ }
+ }
+
+ return (
+ <View style={[styles.container, { paddingTop: insets.top }]}>
+ {isFocused && (
+ <ScrollView
+ contentContainerStyle={[
+ styles.scroll,
+ { paddingBottom: insets.bottom + Spacing.xxl },
+ ]}
+ keyboardShouldPersistTaps="handled"
+ showsVerticalScrollIndicator={false}
+ >
+ <Animated.View entering={FadeInDown.duration(400)} style={styles.header}>
+ <View>
+ <Text style={styles.title}>Lançamentos</Text>
+ <Text style={styles.subtitle}>
+ Saldo líquido:{' '}
+ <Text
+ style={[
+ styles.totalHighlight,
+ isTotalIncome ? { color: Colors.positive } : { color: Colors.negative }
+ ]}
+ >
+ {isTotalIncome ? '+ ' : (monthTotal > 0 ? '- ' : '')}{formattedTotal}
+ </Text>
+ </Text>
+ </View>
+ <TouchableOpacity
+ id="onetime-add-button"
+ style={[styles.addButton, showForm && styles.addButtonActive]}
+ onPress={() => {
+ if (showForm) {
+ setEditingExpenseId(null);
+ setName('');
+ setAmount('');
+ setNotes('');
+ }
+ setShowForm((v) => !v);
+ }}
+ accessibilityLabel="Adicionar lançamento"
+ accessibilityRole="button"
+ >
+ <Text style={styles.addButtonText}>{showForm ? '✕' : '+'}</Text>
+ </TouchableOpacity>
+ </Animated.View>
+
+ {showForm && (
+ <Animated.View entering={FadeInDown.duration(300)}>
+ <Card style={styles.formCard}>
+ <SectionLabel text={editingExpenseId ? "Editar Lançamento" : "Novo Lançamento"} />
+
+ <View style={styles.typeSelector}>
+ <TouchableOpacity
+ style={[styles.typeButton, expenseType === 'expense' && styles.typeButtonExpenseActive]}
+ onPress={() => setExpenseType('expense')}
+ >
+ <Text style={[styles.typeButtonText, expenseType === 'expense' && { color: Colors.negative }]}>
+ Despesa
+ </Text>
+ </TouchableOpacity>
+ <TouchableOpacity
+ style={[styles.typeButton, expenseType === 'income' && styles.typeButtonIncomeActive]}
+ onPress={() => setExpenseType('income')}
+ >
+ <Text style={[styles.typeButtonText, expenseType === 'income' && { color: Colors.positive }]}>
+ Receita
+ </Text>
+ </TouchableOpacity>
+ </View>
+
+ <Input
+ id="one-time-name-input"
+ label="Descrição"
+ value={name}
+ onChangeText={setName}
+ placeholder="Ex: iFood, Cinema, Uber..."
+ />
+
+ <Input
+ id="one-time-amount-input"
+ label="Valor"
+ prefix="R$"
+ value={amount}
+ onChangeText={setAmount}
+ keyboardType="decimal-pad"
+ placeholder="0,00"
+ />
+
+ <View>
+ <Text style={styles.catLabel}>Categoria</Text>
+ <View style={styles.categoryGrid}>
+ {CATEGORIES.map((cat) => (
+ <TouchableOpacity
+ key={cat.value}
+ style={[
+ styles.catChip,
+ selectedCategory === cat.value && styles.catChipSelected,
+ ]}
+ onPress={() => setSelectedCategory(cat.value)}
+ accessibilityLabel={cat.label}
+ accessibilityRole="radio"
+ >
+ <Text style={styles.catEmoji}>{cat.emoji}</Text>
+ <Text
+ style={[
+ styles.catText,
+ selectedCategory === cat.value && styles.catTextSelected,
+ ]}
+ >
+ {cat.label}
+ </Text>
+ </TouchableOpacity>
+ ))}
+ </View>
+ </View>
+
+ <Input
+ id="one-time-notes-input"
+ label="Observações (opcional)"
+ value={notes}
+ onChangeText={setNotes}
+ placeholder="Ex: almoço de aniversário"
+ multiline
+ />
+
+ <Button
+ id="one-time-save-button"
+ label={expenseType === 'income' ? 'Adicionar Receita' : 'Adicionar Gasto'}
+ fullWidth
+ onPress={handleAdd}
+ loading={isSubmitting}
+ disabled={isSubmitting}
+ style={expenseType === 'income' ? { backgroundColor: Colors.positive } : undefined}
+ />
+ </Card>
+ </Animated.View>
+ )}
+
+ <Animated.View layout={LinearTransition.springify()}>
+ <Card style={styles.listCard}>
+ <SectionLabel text={`${expenses.length} lançamentos este mês`} />
+ {expenses.length === 0 ? (
+ <Text style={styles.emptyText}>
+ Nenhum lançamento registrado este mês.{'\n'}Toque em + para adicionar.
+ </Text>
+ ) : (
+ expenses.map((expense, i) => (
+ <React.Fragment key={expense.id}>
+ {i > 0 && <Divider style={styles.rowDivider} />}
+ <OneTimeExpenseRow
+ expense={expense}
+ index={i}
+ onPress={() => setSelectedExpense(expense)}
+ />
+ </React.Fragment>
+ ))
+ )}
+ </Card>
+ </Animated.View>
+ </ScrollView>
+ )}
+
+ <ActionModal
+ visible={expenseToDelete !== null}
+ title="Remover lançamento"
+ message="Deseja realmente remover este lançamento? Esta ação não pode ser desfeita."
+ confirmText="Remover"
+ isDestructive={true}
+ onCancel={() => setExpenseToDelete(null)}
+ onConfirm={confirmDelete}
+ />
+
+ <OptionsModal
+ visible={selectedExpense !== null}
+ title={selectedExpense?.name}
+ onClose={() => setSelectedExpense(null)}
+ options={[
+ {
+ label: 'Editar',
+ icon: 'edit-2',
+ onPress: () => selectedExpense && handleEdit(selectedExpense),
+ },
+ {
+ label: 'Excluir',
+ icon: 'trash-2',
+ destructive: true,
+ onPress: () => selectedExpense && handleDelete(selectedExpense.id),
+ }
+ ]}
+ />
+ </View>
+ );
+}
+
+const styles = StyleSheet.create({
+ container: {
+ flex: 1,
+ backgroundColor: Colors.background,
+ },
+ scroll: {
+ padding: Spacing.md,
+ gap: Spacing.md,
+ },
+ header: {
+ flexDirection: 'row',
+ justifyContent: 'space-between',
+ alignItems: 'flex-start',
+ },
+ title: {
+ ...Typography.h1,
+ color: Colors.textPrimary,
+ },
+ subtitle: {
+ ...Typography.body,
+ color: Colors.textSecondary,
+ marginTop: 4,
+ },
+ totalHighlight: {
+ color: Colors.negative,
+ fontFamily: 'DMSans_600SemiBold',
+ },
+ addButton: {
+ width: 44,
+ height: 44,
+ borderRadius: 22,
+ backgroundColor: Colors.primary,
+ alignItems: 'center',
+ justifyContent: 'center',
+ },
+ addButtonActive: {
+ backgroundColor: Colors.surfaceElevated,
+ borderWidth: 1,
+ borderColor: Colors.border,
+ },
+ addButtonText: {
+ ...Typography.h2,
+ color: Colors.white,
+ },
+ formCard: {
+ gap: Spacing.md,
+ },
+ typeSelector: {
+ flexDirection: 'row',
+ gap: Spacing.sm,
+ },
+ typeButton: {
+ flex: 1,
+ paddingVertical: Spacing.sm,
+ alignItems: 'center',
+ borderRadius: Radius.md,
+ borderWidth: 1,
+ borderColor: Colors.border,
+ backgroundColor: Colors.surfaceElevated,
+ },
+ typeButtonExpenseActive: {
+ borderColor: Colors.negative,
+ backgroundColor: `${Colors.negative}1A`,
+ },
+ typeButtonIncomeActive: {
+ borderColor: Colors.positive,
+ backgroundColor: `${Colors.positive}1A`,
+ },
+ typeButtonText: {
+ ...Typography.body,
+ color: Colors.textSecondary,
+ fontFamily: 'DMSans_600SemiBold',
+ },
+ listCard: {
+ gap: Spacing.xs,
+ },
+ rowDivider: {
+ marginVertical: 0,
+ },
+ emptyText: {
+ ...Typography.body,
+ color: Colors.textMuted,
+ textAlign: 'center',
+ paddingVertical: Spacing.xl,
+ lineHeight: 24,
+ },
+ catLabel: {
+ ...Typography.caption,
+ color: Colors.textSecondary,
+ textTransform: 'uppercase',
+ letterSpacing: 1,
+ marginBottom: Spacing.sm,
+ },
+ categoryGrid: {
+ flexDirection: 'row',
+ flexWrap: 'wrap',
+ gap: Spacing.sm,
+ },
+ catChip: {
+ flexDirection: 'row',
+ alignItems: 'center',
+ gap: Spacing.xs,
+ paddingVertical: Spacing.sm,
+ paddingHorizontal: Spacing.md,
+ borderRadius: Radius.full,
+ backgroundColor: Colors.surfaceElevated,
+ borderWidth: 1,
+ borderColor: Colors.border,
+ },
+ catChipSelected: {
+ borderColor: Colors.primaryLight,
+ backgroundColor: `${Colors.primary}33`,
+ },
+ catEmoji: {
+ fontSize: 14,
+ },
+ catText: {
+ ...Typography.caption,
+ color: Colors.textSecondary,
+ },
+ catTextSelected: {
+ color: Colors.primaryLight,
+ fontFamily: 'DMSans_600SemiBold',
+ },
+});
diff --git a/src/screens/recurring-expenses-screen.tsx b/src/screens/recurring-expenses-screen.tsx
new file mode 100644
index 0000000..ea6f165
--- /dev/null
+++ b/src/screens/recurring-expenses-screen.tsx
@@ -0,0 +1,442 @@
+import React, { useCallback, useState } from 'react';
+import {
+ Alert,
+ Platform,
+ ScrollView,
+ StyleSheet,
+ Text,
+ TouchableOpacity,
+ View,
+} from 'react-native';
+import Animated, { FadeInDown, LinearTransition } from 'react-native-reanimated';
+import { useSafeAreaInsets } from 'react-native-safe-area-context';
+import * as Haptics from 'expo-haptics';
+import { Button } from '@/components/ui/button';
+import { Input } from '@/components/ui/input';
+import { Card, Divider, SectionLabel } from '@/components/ui/primitives';
+import { RecurringExpenseRow } from '@/components/expense-row';
+import { Colors, Spacing, Typography } from '@/constants/theme';
+import type { RecurringExpense } from '@/types';
+import {
+ createRecurringExpense,
+ deleteRecurringExpense,
+ getRecurringExpenses,
+ toggleRecurringExpense,
+ updateRecurringExpense,
+} from '@/services/api';
+import { useAuth } from '@/contexts/AuthContext';
+import { ActionModal } from '@/components/ui/action-modal';
+import { OptionsModal } from '@/components/ui/options-modal';
+import { useFocusEffect } from 'expo-router';
+import { useIsFocused } from "expo-router/react-navigation";
+
+export default function RecurringExpensesScreen() {
+ const insets = useSafeAreaInsets();
+ const { user } = useAuth();
+ const [expenses, setExpenses] = useState<RecurringExpense[]>([]);
+ const [showForm, setShowForm] = useState(false);
+ const [loading, setLoading] = useState(true);
+
+ const [name, setName] = useState('');
+ const [amount, setAmount] = useState('');
+ const [expenseType, setExpenseType] = useState<'expense' | 'income'>('expense');
+ const [dueDay, setDueDay] = useState('');
+ const [isSubmitting, setIsSubmitting] = useState(false);
+
+ const [expenseToDelete, setExpenseToDelete] = useState<number | null>(null);
+ const [selectedExpense, setSelectedExpense] = useState<RecurringExpense | null>(null);
+ const [editingExpenseId, setEditingExpenseId] = useState<number | null>(null);
+
+ const isFocused = useIsFocused();
+
+ const fetchExpenses = useCallback(async () => {
+ if (!user) return;
+ try {
+ setLoading(true);
+ const data = await getRecurringExpenses(user.id);
+ setExpenses(data);
+ } catch (err) {
+ Alert.alert('Erro', 'Não foi possível carregar os gastos.');
+ } finally {
+ setLoading(false);
+ }
+ }, [user]);
+
+ useFocusEffect(
+ useCallback(() => {
+ fetchExpenses();
+ }, [fetchExpenses])
+ );
+
+ const activeTotal = expenses
+ .filter((e) => e.is_active)
+ .reduce((sum, e) => {
+ return sum + (e.type === 'income' ? -e.amount : e.amount);
+ }, 0);
+
+ const isTotalIncome = activeTotal < 0;
+ const absTotal = Math.abs(activeTotal);
+ const formattedTotal = absTotal.toLocaleString('pt-BR', {
+ style: 'currency',
+ currency: 'BRL',
+ });
+
+ async function handleToggle(id: number) {
+ Haptics.impactAsync(Haptics.ImpactFeedbackStyle.Light);
+
+ setExpenses((prev) =>
+ prev.map((e) => (e.id === id ? { ...e, is_active: !e.is_active } : e)),
+ );
+ try {
+ if (!user) return;
+ await toggleRecurringExpense(user.id, id);
+ } catch (err) {
+ setExpenses((prev) =>
+ prev.map((e) => (e.id === id ? { ...e, is_active: !e.is_active } : e)),
+ );
+ Alert.alert('Erro', 'Não foi possível alterar o status do gasto.');
+ }
+ }
+
+ async function handleAdd() {
+ const amountNum = parseFloat(amount.replace(',', '.'));
+ if (!name.trim() || isNaN(amountNum) || amountNum <= 0) {
+ Alert.alert('Dados inválidos', 'Preencha o nome e um valor válido.');
+ return;
+ }
+
+ try {
+ if (!user) return;
+ setIsSubmitting(true);
+
+ if (editingExpenseId) {
+ const updated = await updateRecurringExpense(user.id, editingExpenseId, {
+ name: name.trim(),
+ amount: amountNum,
+ category: 'outros',
+ type: expenseType,
+ due_day: dueDay ? parseInt(dueDay, 10) : null,
+ });
+ setExpenses((prev) => prev.map((e) => e.id === editingExpenseId ? updated : e));
+ Haptics.notificationAsync(Haptics.NotificationFeedbackType.Success);
+ } else {
+ const newExpense = await createRecurringExpense(user.id, {
+ name: name.trim(),
+ amount: amountNum,
+ category: 'outros',
+ type: expenseType,
+ due_day: dueDay ? parseInt(dueDay, 10) : null,
+ is_active: true,
+ starts_at: new Date().toISOString().split('T')[0],
+ ends_at: null,
+ });
+ setExpenses((prev) => [...prev, newExpense]);
+ Haptics.notificationAsync(Haptics.NotificationFeedbackType.Success);
+ }
+
+ setName('');
+ setAmount('');
+ setExpenseType('expense');
+ setDueDay('');
+ setShowForm(false);
+ setEditingExpenseId(null);
+ } catch (err) {
+ Alert.alert('Erro', 'Não foi possível salvar o lançamento.');
+ } finally {
+ setIsSubmitting(false);
+ }
+ }
+
+ function handleDelete(id: number) {
+ setExpenseToDelete(id);
+ setSelectedExpense(null);
+ }
+
+ function handleEdit(expense: RecurringExpense) {
+ setName(expense.name);
+ setAmount(expense.amount.toString());
+ setExpenseType(expense.type);
+ setDueDay(expense.due_day ? expense.due_day.toString() : '');
+ setEditingExpenseId(expense.id);
+ setSelectedExpense(null);
+ setShowForm(true);
+ }
+
+ async function confirmDelete() {
+ if (!user || expenseToDelete === null) return;
+ Haptics.impactAsync(Haptics.ImpactFeedbackStyle.Medium);
+ try {
+ await deleteRecurringExpense(user.id, expenseToDelete);
+ setExpenses((prev) => prev.filter((e) => e.id !== expenseToDelete));
+ } catch (err) {
+ Alert.alert('Erro', 'Não foi possível remover o gasto.');
+ } finally {
+ setExpenseToDelete(null);
+ }
+ }
+
+ return (
+ <View style={[styles.container, { paddingTop: insets.top }]}>
+ {isFocused && (
+ <ScrollView
+ contentContainerStyle={[
+ styles.scroll,
+ { paddingBottom: insets.bottom + 80 },
+ ]}
+ keyboardShouldPersistTaps="handled"
+ showsVerticalScrollIndicator={false}
+ >
+ <Animated.View entering={FadeInDown.duration(400)} style={styles.header}>
+ <View>
+ <Text style={styles.title}>Lançamentos Fixos</Text>
+ <Text style={styles.subtitle}>
+ Saldo líquido:{' '}
+ <Text
+ style={[
+ styles.totalHighlight,
+ isTotalIncome ? { color: Colors.positive } : { color: Colors.negative }
+ ]}
+ >
+ {isTotalIncome ? '+ ' : (activeTotal > 0 ? '- ' : '')}{formattedTotal}
+ </Text>
+ </Text>
+ </View>
+ <TouchableOpacity
+ id="recurring-add-button"
+ style={[styles.addButton, showForm && styles.addButtonActive]}
+ onPress={() => {
+ if (showForm) {
+ setEditingExpenseId(null);
+ setName('');
+ setAmount('');
+ setDueDay('');
+ }
+ setShowForm((v) => !v);
+ }}
+ accessibilityLabel="Adicionar lançamento fixo"
+ accessibilityRole="button"
+ >
+ <Text style={styles.addButtonText}>{showForm ? '✕' : '+'}</Text>
+ </TouchableOpacity>
+ </Animated.View>
+
+ {showForm && (
+ <Animated.View entering={FadeInDown.duration(300)}>
+ <Card style={styles.formCard}>
+ <SectionLabel text={editingExpenseId ? "Editar Lançamento" : "Novo Lançamento Fixo"} />
+ <Input
+ id="recurring-name-input"
+ label="Nome"
+ value={name}
+ onChangeText={setName}
+ placeholder="Ex: Academia, Netflix..."
+ />
+ <Input
+ id="recurring-amount-input"
+ label="Valor Mensal"
+ prefix="R$"
+ value={amount}
+ onChangeText={setAmount}
+ keyboardType="decimal-pad"
+ placeholder="0,00"
+ />
+
+ <View style={styles.typeToggle}>
+ <TouchableOpacity
+ style={[styles.typeButton, expenseType === 'expense' && styles.typeButtonExpense]}
+ onPress={() => setExpenseType('expense')}
+ >
+ <Text style={[styles.typeButtonText, expenseType === 'expense' && styles.typeButtonTextActive]}>
+ Despesa
+ </Text>
+ </TouchableOpacity>
+ <TouchableOpacity
+ style={[styles.typeButton, expenseType === 'income' && styles.typeButtonIncome]}
+ onPress={() => setExpenseType('income')}
+ >
+ <Text style={[styles.typeButtonText, expenseType === 'income' && styles.typeButtonTextActive]}>
+ Receita
+ </Text>
+ </TouchableOpacity>
+ </View>
+
+ <Input
+ id="recurring-due-day-input"
+ label="Dia de Vencimento (opcional)"
+ value={dueDay}
+ onChangeText={setDueDay}
+ keyboardType="number-pad"
+ placeholder="Ex: 5"
+ hint="Dia do mês em que costuma vencer"
+ />
+ <Button
+ id="recurring-save-button"
+ label={editingExpenseId ? "Salvar Alterações" : "Adicionar Lançamento Fixo"}
+ fullWidth
+ onPress={handleAdd}
+ loading={isSubmitting}
+ disabled={isSubmitting}
+ />
+ </Card>
+ </Animated.View>
+ )}
+
+ <Animated.View layout={LinearTransition.springify()}>
+ <Card style={styles.listCard}>
+ <SectionLabel text={`${expenses.length} lançamentos cadastrados`} />
+ {expenses.length === 0 ? (
+ <Text style={styles.emptyText}>
+ Nenhum lançamento fixo cadastrado.{'\n'}Toque em + para adicionar.
+ </Text>
+ ) : (
+ expenses.map((expense, i) => (
+ <React.Fragment key={expense.id}>
+ {i > 0 && <Divider style={styles.rowDivider} />}
+ <RecurringExpenseRow
+ expense={expense}
+ index={i}
+ onToggle={() => handleToggle(expense.id)}
+ onPress={() => setSelectedExpense(expense)}
+ />
+ </React.Fragment>
+ ))
+ )}
+ </Card>
+ </Animated.View>
+ </ScrollView>
+ )}
+
+ <ActionModal
+ visible={expenseToDelete !== null}
+ title="Remover lançamento fixo"
+ message="Deseja realmente remover este lançamento? Ele deixará de afetar seu saldo mensal."
+ confirmText="Remover"
+ isDestructive={true}
+ onCancel={() => setExpenseToDelete(null)}
+ onConfirm={confirmDelete}
+ />
+
+ <OptionsModal
+ visible={selectedExpense !== null}
+ title={selectedExpense?.name}
+ onClose={() => setSelectedExpense(null)}
+ options={[
+ {
+ label: 'Editar',
+ icon: 'edit-2',
+ onPress: () => selectedExpense && handleEdit(selectedExpense),
+ },
+ {
+ label: selectedExpense?.is_active ? 'Pausar' : 'Ativar',
+ icon: selectedExpense?.is_active ? 'pause-circle' : 'play-circle',
+ onPress: () => {
+ if (selectedExpense) {
+ handleToggle(selectedExpense.id);
+ setSelectedExpense(null);
+ }
+ },
+ },
+ {
+ label: 'Excluir',
+ icon: 'trash-2',
+ destructive: true,
+ onPress: () => selectedExpense && handleDelete(selectedExpense.id),
+ }
+ ]}
+ />
+ </View>
+ );
+}
+
+const styles = StyleSheet.create({
+ container: {
+ flex: 1,
+ backgroundColor: Colors.background,
+ },
+ scroll: {
+ padding: Spacing.md,
+ gap: Spacing.md,
+ },
+ header: {
+ flexDirection: 'row',
+ justifyContent: 'space-between',
+ alignItems: 'flex-start',
+ },
+ title: {
+ ...Typography.h1,
+ color: Colors.textPrimary,
+ },
+ subtitle: {
+ ...Typography.body,
+ color: Colors.textSecondary,
+ marginTop: 4,
+ },
+ totalHighlight: {
+ color: Colors.negative,
+ fontFamily: 'DMSans_600SemiBold',
+ },
+ addButton: {
+ width: 44,
+ height: 44,
+ borderRadius: 22,
+ backgroundColor: Colors.primary,
+ alignItems: 'center',
+ justifyContent: 'center',
+ },
+ addButtonActive: {
+ backgroundColor: Colors.surfaceElevated,
+ borderWidth: 1,
+ borderColor: Colors.border,
+ },
+ addButtonText: {
+ ...Typography.h2,
+ color: Colors.white,
+ },
+ formCard: {
+ gap: Spacing.md,
+ },
+ listCard: {
+ gap: Spacing.xs,
+ },
+ rowDivider: {
+ marginVertical: 0,
+ },
+ emptyText: {
+ ...Typography.body,
+ color: Colors.textMuted,
+ textAlign: 'center',
+ paddingVertical: Spacing.xl,
+ lineHeight: 24,
+ },
+ typeToggle: {
+ flexDirection: 'row',
+ gap: Spacing.sm,
+ marginBottom: Spacing.sm,
+ },
+ typeButton: {
+ flex: 1,
+ paddingVertical: Spacing.sm,
+ alignItems: 'center',
+ borderRadius: 12,
+ backgroundColor: Colors.surfaceElevated,
+ borderWidth: 1,
+ borderColor: Colors.border,
+ },
+ typeButtonExpense: {
+ backgroundColor: `${Colors.negative}15`,
+ borderColor: `${Colors.negative}40`,
+ },
+ typeButtonIncome: {
+ backgroundColor: `${Colors.positive}15`,
+ borderColor: `${Colors.positive}40`,
+ },
+ typeButtonText: {
+ ...Typography.body,
+ color: Colors.textSecondary,
+ fontFamily: 'DMSans_500Medium',
+ },
+ typeButtonTextActive: {
+ color: Colors.textPrimary,
+ fontFamily: 'DMSans_700Bold',
+ },
+});
diff --git a/src/screens/salary-screen.tsx b/src/screens/salary-screen.tsx
new file mode 100644
index 0000000..6847c4b
--- /dev/null
+++ b/src/screens/salary-screen.tsx
@@ -0,0 +1,232 @@
+import { useState } from 'react';
+import {
+ Alert,
+ ScrollView,
+ StyleSheet,
+ Text,
+ View,
+} from 'react-native';
+import Animated, { FadeInDown, LinearTransition } from 'react-native-reanimated';
+import { useSafeAreaInsets } from 'react-native-safe-area-context';
+import * as Haptics from 'expo-haptics';
+import { Button } from '@/components/ui/button';
+import { Input } from '@/components/ui/input';
+import { Card, Divider, SectionLabel } from '@/components/ui/primitives';
+import { useSalaryCalculator } from '@/hooks/use-app-hooks';
+import { Colors, Spacing, Typography } from '@/constants/theme';
+import { formatCurrency } from '@/utils/tax-calculator';
+import { updateUserSalary } from '@/services/api';
+import { useAuth } from '@/contexts/AuthContext';
+import { useIsFocused } from "expo-router/react-navigation";
+
+export default function SalaryScreen() {
+ const insets = useSafeAreaInsets();
+ const { user, updateUser } = useAuth();
+ const isFocused = useIsFocused();
+
+ const [grossStr, setGrossStr] = useState(user?.gross_salary ? String(user.gross_salary) : '');
+ const [netOverrideStr, setNetOverrideStr] = useState(
+ user?.net_salary_override ? String(user.net_salary_override) : ''
+ );
+ const [isOverriding, setIsOverriding] = useState(!!user?.net_salary_override);
+
+ const result = useSalaryCalculator(grossStr);
+
+ const effectiveNet = isOverriding
+ ? parseFloat(netOverrideStr.replace(',', '.')) || 0
+ : (result?.salarioLiquidoCalculado ?? 0);
+
+ const [isSaving, setIsSaving] = useState(false);
+ const [saved, setSaved] = useState(false);
+
+ async function handleSave() {
+ if (!result || !user) return;
+ try {
+ setIsSaving(true);
+ setSaved(false);
+ const updatedUser = await updateUserSalary(user.id, {
+ gross_salary: result.salarioBruto,
+ net_salary_override: isOverriding ? effectiveNet : null,
+ });
+ await updateUser(updatedUser);
+ Haptics.notificationAsync(Haptics.NotificationFeedbackType.Success);
+ setSaved(true);
+ setTimeout(() => setSaved(false), 2500);
+ } catch (err) {
+ Alert.alert('Erro', 'Não foi possível salvar o salário.');
+ } finally {
+ setIsSaving(false);
+ }
+ }
+
+ function handleToggleOverride() {
+ if (isOverriding) {
+ setNetOverrideStr('');
+ setIsOverriding(false);
+ } else {
+ setNetOverrideStr(result?.salarioLiquidoCalculado.toFixed(2) ?? '');
+ setIsOverriding(true);
+ }
+ }
+
+ return (
+ <View style={[styles.container, { paddingTop: insets.top }]}>
+ {isFocused && (
+ <ScrollView
+ contentContainerStyle={[
+ styles.scroll,
+ { paddingBottom: insets.bottom + Spacing.xxl },
+ ]}
+ keyboardShouldPersistTaps="handled"
+ showsVerticalScrollIndicator={false}
+ >
+ <Animated.View entering={FadeInDown.duration(400)}>
+ <Text style={styles.title}>Meu Salário</Text>
+ <Text style={styles.subtitle}>
+ Informe seu salário bruto e ajuste o líquido se necessário.
+ </Text>
+ </Animated.View>
+
+ <Animated.View entering={FadeInDown.delay(100).duration(400)}>
+ <Input
+ id="salary-gross-input"
+ label="Salário Bruto"
+ prefix="R$"
+ value={grossStr}
+ onChangeText={setGrossStr}
+ keyboardType="decimal-pad"
+ placeholder="0,00"
+ hint="Valor antes dos descontos (INSS, IRRF)"
+ />
+ </Animated.View>
+
+ {result && (
+ <Animated.View entering={FadeInDown.delay(150).duration(400)} layout={LinearTransition.springify()}>
+ <Card style={styles.resultCard}>
+ <SectionLabel text="Cálculo Automático" />
+
+ <View style={styles.resultRow}>
+ <Text style={styles.resultLabel}>Salário Bruto</Text>
+ <Text style={[styles.resultValue, { color: Colors.textPrimary }]}>
+ {formatCurrency(result.salarioBruto)}
+ </Text>
+ </View>
+
+ <View style={styles.resultRow}>
+ <Text style={styles.resultLabel}>Desconto INSS</Text>
+ <Text style={[styles.resultValue, { color: Colors.negative }]}>
+ - {formatCurrency(result.descontoINSS)}
+ </Text>
+ </View>
+
+ <View style={styles.resultRow}>
+ <Text style={styles.resultLabel}>Desconto IRRF</Text>
+ <Text style={[styles.resultValue, { color: Colors.negative }]}>
+ - {formatCurrency(result.descontoIRRF)}
+ </Text>
+ </View>
+
+ <Divider />
+
+ <View style={styles.resultRow}>
+ <Text style={[styles.resultLabel, { color: Colors.textPrimary }]}>
+ Salário Líquido
+ </Text>
+ <Text style={[styles.resultValue, { color: Colors.positive }]}>
+ {formatCurrency(result.salarioLiquidoCalculado)}
+ </Text>
+ </View>
+ </Card>
+ </Animated.View>
+ )}
+
+ {result && (
+ <Animated.View
+ entering={FadeInDown.delay(200).duration(400)}
+ layout={LinearTransition.springify()}
+ style={styles.overrideSection}
+ >
+ <Button
+ label={
+ isOverriding
+ ? 'Usar valor calculado'
+ : 'Tenho outros descontos (ajustar manualmente)'
+ }
+ variant="ghost"
+ onPress={handleToggleOverride}
+ />
+
+ {isOverriding && (
+ <Animated.View entering={FadeInDown.duration(300)}>
+ <Input
+ id="salary-net-override-input"
+ label="Salário Líquido Real"
+ prefix="R$"
+ value={netOverrideStr}
+ onChangeText={setNetOverrideStr}
+ keyboardType="decimal-pad"
+ placeholder="0,00"
+ hint="Descontos extras: plano de saúde, VT, previdência privada, etc."
+ />
+ </Animated.View>
+ )}
+ </Animated.View>
+ )}
+
+ {result && (
+ <Animated.View entering={FadeInDown.delay(300).duration(400)} layout={LinearTransition.springify()}>
+ <Button
+ id="salary-save-button"
+ label={saved ? 'Salvo com sucesso! ✓' : 'Salvar Salário'}
+ fullWidth
+ onPress={handleSave}
+ disabled={!result || isSaving || saved}
+ loading={isSaving}
+ style={saved ? { backgroundColor: Colors.positive } : undefined}
+ />
+ </Animated.View>
+ )}
+ </ScrollView>
+ )}
+ </View>
+ );
+}
+
+const styles = StyleSheet.create({
+ container: {
+ flex: 1,
+ backgroundColor: Colors.background,
+ },
+ scroll: {
+ padding: Spacing.md,
+ gap: Spacing.lg,
+ },
+ title: {
+ ...Typography.h1,
+ color: Colors.textPrimary,
+ marginBottom: Spacing.xs,
+ },
+ subtitle: {
+ ...Typography.body,
+ color: Colors.textSecondary,
+ },
+ resultCard: {
+ gap: Spacing.sm,
+ },
+ resultRow: {
+ flexDirection: 'row',
+ justifyContent: 'space-between',
+ alignItems: 'center',
+ },
+ resultLabel: {
+ ...Typography.body,
+ color: Colors.textSecondary,
+ },
+ resultValue: {
+ ...Typography.body,
+ fontFamily: 'DMSans_600SemiBold',
+ },
+ overrideSection: {
+ gap: Spacing.md,
+ },
+});
diff --git a/src/services/api.ts b/src/services/api.ts
new file mode 100644
index 0000000..edd376e
--- /dev/null
+++ b/src/services/api.ts
@@ -0,0 +1,165 @@
+import { Platform } from 'react-native';
+import type { DashboardData, OneTimeExpense, RecurringExpense, User } from '@/types';
+
+export type LoginPayload = any;
+export type RegisterPayload = any;
+
+const BASE_URL = 'http://64.181.172.51:3333/api/v1'
+
+let currentToken: string | null = null;
+
+export function setApiToken(token: string | null) {
+ currentToken = token;
+}
+
+async function fetcher<T>(endpoint: string, options?: RequestInit): Promise<T> {
+ const url = `${BASE_URL}${endpoint}`;
+ try {
+ const headers: Record<string, string> = {};
+ if (options?.body) {
+ headers['Content-Type'] = 'application/json';
+ }
+ if (currentToken) {
+ headers['Authorization'] = `Bearer ${currentToken}`;
+ }
+
+ const response = await fetch(url, {
+ ...options,
+ headers: {
+ ...headers,
+ ...options?.headers,
+ },
+ });
+
+ if (!response.ok) {
+ const errorText = await response.text();
+ console.error(`API Error (${response.status}):`, errorText);
+ throw new Error(`API Error: ${response.status}`);
+ }
+
+ const data = await response.json();
+ return data;
+ } catch (error) {
+ console.error(`Fetch Error on ${endpoint}:`, error);
+ throw error;
+ }
+}
+
+export async function apiLogin(data: any): Promise<{ user: User; token: string }> {
+ const result = await fetcher<{ data: { user: User; token: string } }>('/auth/login', {
+ method: 'POST',
+ body: JSON.stringify(data),
+ });
+ return result.data;
+}
+
+export async function apiRegister(data: any): Promise<{ user: User; token: string }> {
+ const result = await fetcher<{ data: { user: User; token: string } }>('/auth/register', {
+ method: 'POST',
+ body: JSON.stringify(data),
+ });
+ return result.data;
+}
+
+export async function getDashboard(userId: number, month?: number, year?: number): Promise<DashboardData> {
+ const params = new URLSearchParams();
+ if (month) params.append('month', month.toString());
+ if (year) params.append('year', year.toString());
+ const qs = params.toString() ? `?${params.toString()}` : '';
+
+ const result = await fetcher<{ data: DashboardData }>(`/users/${userId}/dashboard${qs}`);
+ return result.data;
+}
+
+export async function updateUserSalary(
+ userId: number,
+ data: { gross_salary: number; net_salary_override: number | null },
+): Promise<User> {
+ const result = await fetcher<{ data: User }>(`/users/${userId}`, {
+ method: 'PUT',
+ body: JSON.stringify(data),
+ });
+ return result.data;
+}
+
+export async function getRecurringExpenses(userId: number): Promise<RecurringExpense[]> {
+ const result = await fetcher<{ data: RecurringExpense[] }>(`/users/${userId}/recurring-expenses`);
+ return result.data;
+}
+
+export async function createRecurringExpense(
+ userId: number,
+ data: Omit<RecurringExpense, 'id' | 'user_id' | 'created_at' | 'updated_at'>,
+): Promise<RecurringExpense> {
+ const result = await fetcher<{ data: RecurringExpense }>(`/users/${userId}/recurring-expenses`, {
+ method: 'POST',
+ body: JSON.stringify(data),
+ });
+ return result.data;
+}
+
+export async function toggleRecurringExpense(
+ userId: number,
+ expenseId: number,
+): Promise<RecurringExpense> {
+ const result = await fetcher<{ data: RecurringExpense }>(`/users/${userId}/recurring-expenses/${expenseId}/toggle`, {
+ method: 'PATCH',
+ });
+ return result.data;
+}
+
+export async function updateRecurringExpense(
+ userId: number,
+ expenseId: number,
+ data: Partial<Omit<RecurringExpense, 'id' | 'user_id' | 'created_at' | 'updated_at'>>,
+): Promise<RecurringExpense> {
+ const result = await fetcher<{ data: RecurringExpense }>(`/users/${userId}/recurring-expenses/${expenseId}`, {
+ method: 'PUT',
+ body: JSON.stringify(data),
+ });
+ return result.data;
+}
+
+export async function deleteRecurringExpense(userId: number, expenseId: number): Promise<void> {
+ await fetcher(`/users/${userId}/recurring-expenses/${expenseId}`, {
+ method: 'DELETE',
+ });
+}
+
+export async function getOneTimeExpenses(userId: number, month?: number, year?: number): Promise<OneTimeExpense[]> {
+ const params = new URLSearchParams();
+ if (month) params.append('month', month.toString());
+ if (year) params.append('year', year.toString());
+ const qs = params.toString() ? `?${params.toString()}` : '';
+ const result = await fetcher<{ data: OneTimeExpense[] }>(`/users/${userId}/one-time-expenses${qs}`);
+ return result.data;
+}
+
+export async function createOneTimeExpense(
+ userId: number,
+ data: Omit<OneTimeExpense, 'id' | 'user_id' | 'created_at' | 'updated_at'>,
+): Promise<OneTimeExpense> {
+ const result = await fetcher<{ data: OneTimeExpense }>(`/users/${userId}/one-time-expenses`, {
+ method: 'POST',
+ body: JSON.stringify(data),
+ });
+ return result.data;
+}
+
+export async function updateOneTimeExpense(
+ userId: number,
+ expenseId: number,
+ data: Partial<Omit<OneTimeExpense, 'id' | 'user_id' | 'created_at' | 'updated_at'>>,
+): Promise<OneTimeExpense> {
+ const result = await fetcher<{ data: OneTimeExpense }>(`/users/${userId}/one-time-expenses/${expenseId}`, {
+ method: 'PUT',
+ body: JSON.stringify(data),
+ });
+ return result.data;
+}
+
+export async function deleteOneTimeExpense(userId: number, expenseId: number): Promise<void> {
+ await fetcher(`/users/${userId}/one-time-expenses/${expenseId}`, {
+ method: 'DELETE',
+ });
+}
diff --git a/src/types/index.ts b/src/types/index.ts
new file mode 100644
index 0000000..7554419
--- /dev/null
+++ b/src/types/index.ts
@@ -0,0 +1,98 @@
+export interface User {
+ id: number;
+ name: string;
+ gross_salary: number;
+ net_salary_override: number | null;
+ created_at: string;
+ updated_at: string;
+}
+
+export interface Income {
+ id: number;
+ user_id: number;
+ gross_salary: number;
+ calculated_net_salary: number;
+ effective_net_salary: number;
+ reference_month: number;
+ reference_year: number;
+ description: string | null;
+ created_at: string;
+ updated_at: string;
+}
+
+export type Category =
+ | 'moradia'
+ | 'alimentação'
+ | 'transporte'
+ | 'saúde'
+ | 'educação'
+ | 'lazer'
+ | 'serviços'
+ | 'outros';
+
+export interface RecurringExpense {
+ id: number;
+ user_id: number;
+ name: string;
+ amount: number;
+ category: Category;
+ type: 'expense' | 'income';
+ due_day: number | null;
+ is_active: boolean;
+ starts_at: string;
+ ends_at: string | null;
+ created_at: string;
+ updated_at: string;
+}
+
+export interface OneTimeExpense {
+ id: number;
+ user_id: number;
+ name: string;
+ amount: number;
+ category: Category;
+ type: 'expense' | 'income';
+ expense_date: string;
+ notes: string | null;
+ created_at: string;
+ updated_at: string;
+}
+
+export interface DashboardExpenseItem {
+ id: number;
+ name: string;
+ amount: number;
+ category: string;
+ type: 'expense' | 'income';
+ is_active?: boolean;
+ expense_date?: string;
+}
+
+export interface DashboardData {
+ user: {
+ id: number;
+ name: string;
+ gross_salary: number;
+ net_salary_override: number | null;
+ };
+ period: { month: number; year: number };
+ salary: {
+ gross: number;
+ calculated_net: number;
+ effective_net: number;
+ inss_discount: number;
+ irrf_discount: number;
+ has_override: boolean;
+ };
+ expenses: {
+ recurring_total: number;
+ one_time_total: number;
+ total: number;
+ recurring_list: DashboardExpenseItem[];
+ one_time_list: DashboardExpenseItem[];
+ };
+ balance: {
+ available: number;
+ expense_ratio: number;
+ };
+}
diff --git a/src/utils/tax-calculator.ts b/src/utils/tax-calculator.ts
new file mode 100644
index 0000000..64b1c08
--- /dev/null
+++ b/src/utils/tax-calculator.ts
@@ -0,0 +1,85 @@
+const INSS_TABLE = [
+ { upTo: 1_518.0, rate: 0.075 },
+ { upTo: 2_793.88, rate: 0.09 },
+ { upTo: 4_190.83, rate: 0.12 },
+ { upTo: 8_157.41, rate: 0.14 },
+] as const;
+
+const INSS_TETO = 908.86;
+
+export function calcularINSS(salarioBruto: number): number {
+ if (salarioBruto <= 0) return 0;
+ if (salarioBruto > INSS_TABLE[INSS_TABLE.length - 1].upTo) return INSS_TETO;
+
+ let inss = 0;
+ let limiteAnterior = 0;
+
+ for (const faixa of INSS_TABLE) {
+ const baseNaFaixa = Math.min(salarioBruto, faixa.upTo) - limiteAnterior;
+ if (baseNaFaixa <= 0) break;
+ inss += baseNaFaixa * faixa.rate;
+ limiteAnterior = faixa.upTo;
+ }
+
+ return parseFloat(inss.toFixed(2));
+}
+
+interface FaixaIRRF {
+ upTo: number | null;
+ rate: number;
+ deduction: number;
+}
+
+const IRRF_TABLE: FaixaIRRF[] = [
+ { upTo: 2_259.2, rate: 0, deduction: 0 },
+ { upTo: 2_826.65, rate: 0.075, deduction: 169.44 },
+ { upTo: 3_751.05, rate: 0.15, deduction: 381.44 },
+ { upTo: 4_664.68, rate: 0.225, deduction: 662.77 },
+ { upTo: null, rate: 0.275, deduction: 896.0 },
+];
+
+export function calcularIRRF(salarioBruto: number, inss: number): number {
+ const base = salarioBruto - inss;
+ if (base <= 0) return 0;
+
+ const faixa = IRRF_TABLE.find((f) => f.upTo === null || base <= f.upTo)!;
+ return parseFloat(Math.max(0, base * faixa.rate - faixa.deduction).toFixed(2));
+}
+
+export interface ResultadoCalculo {
+ salarioBruto: number;
+ descontoINSS: number;
+ descontoIRRF: number;
+ totalDescontos: number;
+ salarioLiquidoCalculado: number;
+}
+
+export function calcularSalarioLiquido(salarioBruto: number): ResultadoCalculo {
+ const descontoINSS = calcularINSS(salarioBruto);
+ const descontoIRRF = calcularIRRF(salarioBruto, descontoINSS);
+ const totalDescontos = parseFloat((descontoINSS + descontoIRRF).toFixed(2));
+ const salarioLiquidoCalculado = parseFloat(
+ (salarioBruto - totalDescontos).toFixed(2),
+ );
+ return { salarioBruto, descontoINSS, descontoIRRF, totalDescontos, salarioLiquidoCalculado };
+}
+
+export function formatCurrency(value: number): string {
+ return value.toLocaleString('pt-BR', {
+ style: 'currency',
+ currency: 'BRL',
+ minimumFractionDigits: 2,
+ });
+}
+
+export function formatCurrencyCompact(value: number): string {
+ if (Math.abs(value) >= 1_000) {
+ return value.toLocaleString('pt-BR', {
+ style: 'currency',
+ currency: 'BRL',
+ minimumFractionDigits: 0,
+ maximumFractionDigits: 0,
+ });
+ }
+ return formatCurrency(value);
+}
diff --git a/tsconfig.json b/tsconfig.json
new file mode 100644
index 0000000..2e9a669
--- /dev/null
+++ b/tsconfig.json
@@ -0,0 +1,20 @@
+{
+ "extends": "expo/tsconfig.base",
+ "compilerOptions": {
+ "strict": true,
+ "paths": {
+ "@/*": [
+ "./src/*"
+ ],
+ "@/assets/*": [
+ "./assets/*"
+ ]
+ }
+ },
+ "include": [
+ "**/*.ts",
+ "**/*.tsx",
+ ".expo/types/**/*.ts",
+ "expo-env.d.ts"
+ ]
+}